Merge branch 'for-linus' of git://linux-nfs.org/~bfields/linux

* 'for-linus' of git://linux-nfs.org/~bfields/linux: (100 commits)
  SUNRPC: RPC program information is stored in unsigned integers
  SUNRPC: Move exported symbol definitions after function declaration part 2
  NLM: tear down RPC clients in nlm_shutdown_hosts
  SUNRPC: spin svc_rqst initialization to its own function
  nfsd: more careful input validation in nfsctl write methods
  lockd: minor log message fix
  knfsd: don't bother mapping putrootfh enoent to eperm
  rdma: makefile
  rdma: ONCRPC RDMA protocol marshalling
  rdma: SVCRDMA sendto
  rdma: SVCRDMA recvfrom
  rdma: SVCRDMA Core Transport Services
  rdma: SVCRDMA Transport Module
  rdma: SVCRMDA Header File
  svc: Add svc_xprt_names service to replace svc_sock_names
  knfsd: Support adding transports by writing portlist file
  svc: Add svc API that queries for a transport instance
  svc: Add /proc/sys/sunrpc/transport files
  svc: Add transport hdr size for defer/revisit
  svc: Move the xprt independent code to the svc_xprt.c file
  ...
diff --git a/Documentation/ABI/testing/sysfs-bus-usb b/Documentation/ABI/testing/sysfs-bus-usb
index 9734577..11a3c16 100644
--- a/Documentation/ABI/testing/sysfs-bus-usb
+++ b/Documentation/ABI/testing/sysfs-bus-usb
@@ -52,3 +52,36 @@
 		facility is inherently dangerous, it is disabled by default
 		for all devices except hubs.  For more information, see
 		Documentation/usb/persist.txt.
+
+What:		/sys/bus/usb/device/.../power/connected_duration
+Date:		January 2008
+KernelVersion:	2.6.25
+Contact:	Sarah Sharp <sarah.a.sharp@intel.com>
+Description:
+		If CONFIG_PM and CONFIG_USB_SUSPEND are enabled, then this file
+		is present.  When read, it returns the total time (in msec)
+		that the USB device has been connected to the machine.  This
+		file is read-only.
+Users:
+		PowerTOP <power@bughost.org>
+		http://www.lesswatts.org/projects/powertop/
+
+What:		/sys/bus/usb/device/.../power/active_duration
+Date:		January 2008
+KernelVersion:	2.6.25
+Contact:	Sarah Sharp <sarah.a.sharp@intel.com>
+Description:
+		If CONFIG_PM and CONFIG_USB_SUSPEND are enabled, then this file
+		is present.  When read, it returns the total time (in msec)
+		that the USB device has been active, i.e. not in a suspended
+		state.  This file is read-only.
+
+		Tools can use this file and the connected_duration file to
+		compute the percentage of time that a device has been active.
+		For example,
+		echo $((100 * `cat active_duration` / `cat connected_duration`))
+		will give an integer percentage.  Note that this does not
+		account for counter wrap.
+Users:
+		PowerTOP <power@bughost.org>
+		http://www.lesswatts.org/projects/powertop/
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index 181bff0..a7d9d17 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -156,22 +156,6 @@
 
 ---------------------------
 
-What:	USB driver API moves to EXPORT_SYMBOL_GPL
-When:	February 2008
-Files:	include/linux/usb.h, drivers/usb/core/driver.c
-Why:	The USB subsystem has changed a lot over time, and it has been
-	possible to create userspace USB drivers using usbfs/libusb/gadgetfs
-	that operate as fast as the USB bus allows.  Because of this, the USB
-	subsystem will not be allowing closed source kernel drivers to
-	register with it, after this grace period is over.  If anyone needs
-	any help in converting their closed source drivers over to use the
-	userspace filesystems, please contact the
-	linux-usb-devel@lists.sourceforge.net mailing list, and the developers
-	there will be glad to help you out.
-Who:	Greg Kroah-Hartman <gregkh@suse.de>
-
----------------------------
-
 What:	vm_ops.nopage
 When:	Soon, provided in-kernel callers have been converted
 Why:	This interface is replaced by vm_ops.fault, but it has been around
diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt
index 11fe51c..194c8f35 100644
--- a/Documentation/filesystems/proc.txt
+++ b/Documentation/filesystems/proc.txt
@@ -1134,13 +1134,6 @@
 resume it  if we have a value of 3 or more percent; consider information about
 the amount of free space valid for 30 seconds
 
-audit_argv_kb
--------------
-
-The file contains a single value denoting the limit on the argv array size
-for execve (in KiB). This limit is only applied when system call auditing for
-execve is enabled, otherwise the value is ignored.
-
 ctrl-alt-del
 ------------
 
diff --git a/Documentation/ide/ChangeLog.ide-cd.1994-2004 b/Documentation/ide/ChangeLog.ide-cd.1994-2004
new file mode 100644
index 0000000..190d17b
--- /dev/null
+++ b/Documentation/ide/ChangeLog.ide-cd.1994-2004
@@ -0,0 +1,268 @@
+/*
+ * 1.00  Oct 31, 1994 -- Initial version.
+ * 1.01  Nov  2, 1994 -- Fixed problem with starting request in
+ *                       cdrom_check_status.
+ * 1.03  Nov 25, 1994 -- leaving unmask_intr[] as a user-setting (as for disks)
+ * (from mlord)       -- minor changes to cdrom_setup()
+ *                    -- renamed ide_dev_s to ide_drive_t, enable irq on command
+ * 2.00  Nov 27, 1994 -- Generalize packet command interface;
+ *                       add audio ioctls.
+ * 2.01  Dec  3, 1994 -- Rework packet command interface to handle devices
+ *                       which send an interrupt when ready for a command.
+ * 2.02  Dec 11, 1994 -- Cache the TOC in the driver.
+ *                       Don't use SCMD_PLAYAUDIO_TI; it's not included
+ *                       in the current version of ATAPI.
+ *                       Try to use LBA instead of track or MSF addressing
+ *                       when possible.
+ *                       Don't wait for READY_STAT.
+ * 2.03  Jan 10, 1995 -- Rewrite block read routines to handle block sizes
+ *                       other than 2k and to move multiple sectors in a
+ *                       single transaction.
+ * 2.04  Apr 21, 1995 -- Add work-around for Creative Labs CD220E drives.
+ *                       Thanks to Nick Saw <cwsaw@pts7.pts.mot.com> for
+ *                       help in figuring this out.  Ditto for Acer and
+ *                       Aztech drives, which seem to have the same problem.
+ * 2.04b May 30, 1995 -- Fix to match changes in ide.c version 3.16 -ml
+ * 2.05  Jun  8, 1995 -- Don't attempt to retry after an illegal request
+ *                        or data protect error.
+ *                       Use HWIF and DEV_HWIF macros as in ide.c.
+ *                       Always try to do a request_sense after
+ *                        a failed command.
+ *                       Include an option to give textual descriptions
+ *                        of ATAPI errors.
+ *                       Fix a bug in handling the sector cache which
+ *                        showed up if the drive returned data in 512 byte
+ *                        blocks (like Pioneer drives).  Thanks to
+ *                        Richard Hirst <srh@gpt.co.uk> for diagnosing this.
+ *                       Properly supply the page number field in the
+ *                        MODE_SELECT command.
+ *                       PLAYAUDIO12 is broken on the Aztech; work around it.
+ * 2.05x Aug 11, 1995 -- lots of data structure renaming/restructuring in ide.c
+ *                       (my apologies to Scott, but now ide-cd.c is independent)
+ * 3.00  Aug 22, 1995 -- Implement CDROMMULTISESSION ioctl.
+ *                       Implement CDROMREADAUDIO ioctl (UNTESTED).
+ *                       Use input_ide_data() and output_ide_data().
+ *                       Add door locking.
+ *                       Fix usage count leak in cdrom_open, which happened
+ *                        when a read-write mount was attempted.
+ *                       Try to load the disk on open.
+ *                       Implement CDROMEJECT_SW ioctl (off by default).
+ *                       Read total cdrom capacity during open.
+ *                       Rearrange logic in cdrom_decode_status.  Issue
+ *                        request sense commands for failed packet commands
+ *                        from here instead of from cdrom_queue_packet_command.
+ *                        Fix a race condition in retrieving error information.
+ *                       Suppress printing normal unit attention errors and
+ *                        some drive not ready errors.
+ *                       Implement CDROMVOLREAD ioctl.
+ *                       Implement CDROMREADMODE1/2 ioctls.
+ *                       Fix race condition in setting up interrupt handlers
+ *                        when the `serialize' option is used.
+ * 3.01  Sep  2, 1995 -- Fix ordering of reenabling interrupts in
+ *                        cdrom_queue_request.
+ *                       Another try at using ide_[input,output]_data.
+ * 3.02  Sep 16, 1995 -- Stick total disk capacity in partition table as well.
+ *                       Make VERBOSE_IDE_CD_ERRORS dump failed command again.
+ *                       Dump out more information for ILLEGAL REQUEST errs.
+ *                       Fix handling of errors occurring before the
+ *                        packet command is transferred.
+ *                       Fix transfers with odd bytelengths.
+ * 3.03  Oct 27, 1995 -- Some Creative drives have an id of just `CD'.
+ *                       `DCI-2S10' drives are broken too.
+ * 3.04  Nov 20, 1995 -- So are Vertos drives.
+ * 3.05  Dec  1, 1995 -- Changes to go with overhaul of ide.c and ide-tape.c
+ * 3.06  Dec 16, 1995 -- Add support needed for partitions.
+ *                       More workarounds for Vertos bugs (based on patches
+ *                        from Holger Dietze <dietze@aix520.informatik.uni-leipzig.de>).
+ *                       Try to eliminate byteorder assumptions.
+ *                       Use atapi_cdrom_subchnl struct definition.
+ *                       Add STANDARD_ATAPI compilation option.
+ * 3.07  Jan 29, 1996 -- More twiddling for broken drives: Sony 55D,
+ *                        Vertos 300.
+ *                       Add NO_DOOR_LOCKING configuration option.
+ *                       Handle drive_cmd requests w/NULL args (for hdparm -t).
+ *                       Work around sporadic Sony55e audio play problem.
+ * 3.07a Feb 11, 1996 -- check drive->id for NULL before dereferencing, to fix
+ *                        problem with "hde=cdrom" with no drive present.  -ml
+ * 3.08  Mar  6, 1996 -- More Vertos workarounds.
+ * 3.09  Apr  5, 1996 -- Add CDROMCLOSETRAY ioctl.
+ *                       Switch to using MSF addressing for audio commands.
+ *                       Reformat to match kernel tabbing style.
+ *                       Add CDROM_GET_UPC ioctl.
+ * 3.10  Apr 10, 1996 -- Fix compilation error with STANDARD_ATAPI.
+ * 3.11  Apr 29, 1996 -- Patch from Heiko Eißfeldt <heiko@colossus.escape.de>
+ *                       to remove redundant verify_area calls.
+ * 3.12  May  7, 1996 -- Rudimentary changer support.  Based on patches
+ *                        from Gerhard Zuber <zuber@berlin.snafu.de>.
+ *                       Let open succeed even if there's no loaded disc.
+ * 3.13  May 19, 1996 -- Fixes for changer code.
+ * 3.14  May 29, 1996 -- Add work-around for Vertos 600.
+ *                        (From Hennus Bergman <hennus@sky.ow.nl>.)
+ * 3.15  July 2, 1996 -- Added support for Sanyo 3 CD changers
+ *                        from Ben Galliart <bgallia@luc.edu> with
+ *                        special help from Jeff Lightfoot
+ *                        <jeffml@pobox.com>
+ * 3.15a July 9, 1996 -- Improved Sanyo 3 CD changer identification
+ * 3.16  Jul 28, 1996 -- Fix from Gadi to reduce kernel stack usage for ioctl.
+ * 3.17  Sep 17, 1996 -- Tweak audio reads for some drives.
+ *                       Start changing CDROMLOADFROMSLOT to CDROM_SELECT_DISC.
+ * 3.18  Oct 31, 1996 -- Added module and DMA support.
+ *
+ * 4.00  Nov 5, 1996   -- New ide-cd maintainer,
+ *                                 Erik B. Andersen <andersee@debian.org>
+ *                     -- Newer Creative drives don't always set the error
+ *                          register correctly.  Make sure we see media changes
+ *                          regardless.
+ *                     -- Integrate with generic cdrom driver.
+ *                     -- CDROMGETSPINDOWN and CDROMSETSPINDOWN ioctls, based on
+ *                          a patch from Ciro Cattuto <>.
+ *                     -- Call set_device_ro.
+ *                     -- Implement CDROMMECHANISMSTATUS and CDROMSLOTTABLE
+ *                          ioctls, based on patch by Erik Andersen
+ *                     -- Add some probes of drive capability during setup.
+ *
+ * 4.01  Nov 11, 1996  -- Split into ide-cd.c and ide-cd.h
+ *                     -- Removed CDROMMECHANISMSTATUS and CDROMSLOTTABLE
+ *                          ioctls in favor of a generalized approach
+ *                          using the generic cdrom driver.
+ *                     -- Fully integrated with the 2.1.X kernel.
+ *                     -- Other stuff that I forgot (lots of changes)
+ *
+ * 4.02  Dec 01, 1996  -- Applied patch from Gadi Oxman <gadio@netvision.net.il>
+ *                          to fix the drive door locking problems.
+ *
+ * 4.03  Dec 04, 1996  -- Added DSC overlap support.
+ * 4.04  Dec 29, 1996  -- Added CDROMREADRAW ioclt based on patch
+ *                          by Ales Makarov (xmakarov@sun.felk.cvut.cz)
+ *
+ * 4.05  Nov 20, 1997  -- Modified to print more drive info on init
+ *                        Minor other changes
+ *                        Fix errors on CDROMSTOP (If you have a "Dolphin",
+ *                          you must define IHAVEADOLPHIN)
+ *                        Added identifier so new Sanyo CD-changer works
+ *                        Better detection if door locking isn't supported
+ *
+ * 4.06  Dec 17, 1997  -- fixed endless "tray open" messages  -ml
+ * 4.07  Dec 17, 1997  -- fallback to set pc->stat on "tray open"
+ * 4.08  Dec 18, 1997  -- spew less noise when tray is empty
+ *                     -- fix speed display for ACER 24X, 18X
+ * 4.09  Jan 04, 1998  -- fix handling of the last block so we return
+ *                         an end of file instead of an I/O error (Gadi)
+ * 4.10  Jan 24, 1998  -- fixed a bug so now changers can change to a new
+ *                         slot when there is no disc in the current slot.
+ *                     -- Fixed a memory leak where info->changer_info was
+ *                         malloc'ed but never free'd when closing the device.
+ *                     -- Cleaned up the global namespace a bit by making more
+ *                         functions static that should already have been.
+ * 4.11  Mar 12, 1998  -- Added support for the CDROM_SELECT_SPEED ioctl
+ *                         based on a patch for 2.0.33 by Jelle Foks
+ *                         <jelle@scintilla.utwente.nl>, a patch for 2.0.33
+ *                         by Toni Giorgino <toni@pcape2.pi.infn.it>, the SCSI
+ *                         version, and my own efforts.  -erik
+ *                     -- Fixed a stupid bug which egcs was kind enough to
+ *                         inform me of where "Illegal mode for this track"
+ *                         was never returned due to a comparison on data
+ *                         types of limited range.
+ * 4.12  Mar 29, 1998  -- Fixed bug in CDROM_SELECT_SPEED so write speed is
+ *                         now set ionly for CD-R and CD-RW drives.  I had
+ *                         removed this support because it produced errors.
+ *                         It produced errors _only_ for non-writers. duh.
+ * 4.13  May 05, 1998  -- Suppress useless "in progress of becoming ready"
+ *                         messages, since this is not an error.
+ *                     -- Change error messages to be const
+ *                     -- Remove a "\t" which looks ugly in the syslogs
+ * 4.14  July 17, 1998 -- Change to pointing to .ps version of ATAPI spec
+ *                         since the .pdf version doesn't seem to work...
+ *                     -- Updated the TODO list to something more current.
+ *
+ * 4.15  Aug 25, 1998  -- Updated ide-cd.h to respect mechine endianess,
+ *                         patch thanks to "Eddie C. Dost" <ecd@skynet.be>
+ *
+ * 4.50  Oct 19, 1998  -- New maintainers!
+ *                         Jens Axboe <axboe@image.dk>
+ *                         Chris Zwilling <chris@cloudnet.com>
+ *
+ * 4.51  Dec 23, 1998  -- Jens Axboe <axboe@image.dk>
+ *                      - ide_cdrom_reset enabled since the ide subsystem
+ *                         handles resets fine now. <axboe@image.dk>
+ *                      - Transfer size fix for Samsung CD-ROMs, thanks to
+ *                        "Ville Hallik" <ville.hallik@mail.ee>.
+ *                      - other minor stuff.
+ *
+ * 4.52  Jan 19, 1999  -- Jens Axboe <axboe@image.dk>
+ *                      - Detect DVD-ROM/RAM drives
+ *
+ * 4.53  Feb 22, 1999   - Include other model Samsung and one Goldstar
+ *                         drive in transfer size limit.
+ *                      - Fix the I/O error when doing eject without a medium
+ *                         loaded on some drives.
+ *                      - CDROMREADMODE2 is now implemented through
+ *                         CDROMREADRAW, since many drives don't support
+ *                         MODE2 (even though ATAPI 2.6 says they must).
+ *                      - Added ignore parameter to ide-cd (as a module), eg
+ *                         	insmod ide-cd ignore='hda hdb'
+ *                         Useful when using ide-cd in conjunction with
+ *                         ide-scsi. TODO: non-modular way of doing the
+ *                         same.
+ *
+ * 4.54  Aug 5, 1999	- Support for MMC2 class commands through the generic
+ *			  packet interface to cdrom.c.
+ *			- Unified audio ioctl support, most of it.
+ *			- cleaned up various deprecated verify_area().
+ *			- Added ide_cdrom_packet() as the interface for
+ *			  the Uniform generic_packet().
+ *			- bunch of other stuff, will fill in logs later.
+ *			- report 1 slot for non-changers, like the other
+ *			  cd-rom drivers. don't report select disc for
+ *			  non-changers as well.
+ *			- mask out audio playing, if the device can't do it.
+ *
+ * 4.55  Sep 1, 1999	- Eliminated the rest of the audio ioctls, except
+ *			  for CDROMREADTOC[ENTRY|HEADER]. Some of the drivers
+ *			  use this independently of the actual audio handling.
+ *			  They will disappear later when I get the time to
+ *			  do it cleanly.
+ *			- Minimize the TOC reading - only do it when we
+ *			  know a media change has occurred.
+ *			- Moved all the CDROMREADx ioctls to the Uniform layer.
+ *			- Heiko Eißfeldt <heiko@colossus.escape.de> supplied
+ *			  some fixes for CDI.
+ *			- CD-ROM leaving door locked fix from Andries
+ *			  Brouwer <Andries.Brouwer@cwi.nl>
+ *			- Erik Andersen <andersen@xmission.com> unified
+ *			  commands across the various drivers and how
+ *			  sense errors are handled.
+ *
+ * 4.56  Sep 12, 1999	- Removed changer support - it is now in the
+ *			  Uniform layer.
+ *			- Added partition based multisession handling.
+ *			- Mode sense and mode select moved to the
+ *			  Uniform layer.
+ *			- Fixed a problem with WPI CDS-32X drive - it
+ *			  failed the capabilities
+ *
+ * 4.57  Apr 7, 2000	- Fixed sense reporting.
+ *			- Fixed possible oops in ide_cdrom_get_last_session()
+ *			- Fix locking mania and make ide_cdrom_reset relock
+ *			- Stop spewing errors to log when magicdev polls with
+ *			  TEST_UNIT_READY on some drives.
+ *			- Various fixes from Tobias Ringstrom:
+ *			  tray if it was locked prior to the reset.
+ *			  - cdrom_read_capacity returns one frame too little.
+ *			  - Fix real capacity reporting.
+ *
+ * 4.58  May 1, 2000	- Clean up ACER50 stuff.
+ *			- Fix small problem with ide_cdrom_capacity
+ *
+ * 4.59  Aug 11, 2000	- Fix changer problem in cdrom_read_toc, we weren't
+ *			  correctly sensing a disc change.
+ *			- Rearranged some code
+ *			- Use extended sense on drives that support it for
+ *			  correctly reporting tray status -- from
+ *			  Michael D Johnson <johnsom@orst.edu>
+ * 4.60  Dec 17, 2003	- Add mt rainier support
+ *			- Bump timeout for packet commands, matches sr
+ *			- Odd stuff
+ * 4.61  Jan 22, 2004	- support hardware sector sizes other than 2kB,
+ *			  Pascal Schmidt <der.eremit@email.de>
+ */
diff --git a/Documentation/ide/ChangeLog.ide-floppy.1996-2002 b/Documentation/ide/ChangeLog.ide-floppy.1996-2002
new file mode 100644
index 0000000..46c19ef
--- /dev/null
+++ b/Documentation/ide/ChangeLog.ide-floppy.1996-2002
@@ -0,0 +1,63 @@
+/*
+ * Many thanks to Lode Leroy <Lode.Leroy@www.ibase.be>, who tested so many
+ * ALPHA patches to this driver on an EASYSTOR LS-120 ATAPI floppy drive.
+ *
+ * Ver 0.1   Oct 17 96   Initial test version, mostly based on ide-tape.c.
+ * Ver 0.2   Oct 31 96   Minor changes.
+ * Ver 0.3   Dec  2 96   Fixed error recovery bug.
+ * Ver 0.4   Jan 26 97   Add support for the HDIO_GETGEO ioctl.
+ * Ver 0.5   Feb 21 97   Add partitions support.
+ *                       Use the minimum of the LBA and CHS capacities.
+ *                       Avoid hwgroup->rq == NULL on the last irq.
+ *                       Fix potential null dereferencing with DEBUG_LOG.
+ * Ver 0.8   Dec  7 97   Increase irq timeout from 10 to 50 seconds.
+ *                       Add media write-protect detection.
+ *                       Issue START command only if TEST UNIT READY fails.
+ *                       Add work-around for IOMEGA ZIP revision 21.D.
+ *                       Remove idefloppy_get_capabilities().
+ * Ver 0.9   Jul  4 99   Fix a bug which might have caused the number of
+ *                        bytes requested on each interrupt to be zero.
+ *                        Thanks to <shanos@es.co.nz> for pointing this out.
+ * Ver 0.9.sv Jan 6 01   Sam Varshavchik <mrsam@courier-mta.com>
+ *                       Implement low level formatting.  Reimplemented
+ *                       IDEFLOPPY_CAPABILITIES_PAGE, since we need the srfp
+ *                       bit.  My LS-120 drive barfs on
+ *                       IDEFLOPPY_CAPABILITIES_PAGE, but maybe it's just me.
+ *                       Compromise by not reporting a failure to get this
+ *                       mode page.  Implemented four IOCTLs in order to
+ *                       implement formatting.  IOCTls begin with 0x4600,
+ *                       0x46 is 'F' as in Format.
+ *            Jan 9 01   Userland option to select format verify.
+ *                       Added PC_SUPPRESS_ERROR flag - some idefloppy drives
+ *                       do not implement IDEFLOPPY_CAPABILITIES_PAGE, and
+ *                       return a sense error.  Suppress error reporting in
+ *                       this particular case in order to avoid spurious
+ *                       errors in syslog.  The culprit is
+ *                       idefloppy_get_capability_page(), so move it to
+ *                       idefloppy_begin_format() so that it's not used
+ *                       unless absolutely necessary.
+ *                       If drive does not support format progress indication
+ *                       monitor the dsc bit in the status register.
+ *                       Also, O_NDELAY on open will allow the device to be
+ *                       opened without a disk available.  This can be used to
+ *                       open an unformatted disk, or get the device capacity.
+ * Ver 0.91  Dec 11 99   Added IOMEGA Clik! drive support by
+ *     		   <paul@paulbristow.net>
+ * Ver 0.92  Oct 22 00   Paul Bristow became official maintainer for this
+ *           		   driver.  Included Powerbook internal zip kludge.
+ * Ver 0.93  Oct 24 00   Fixed bugs for Clik! drive
+ *                        no disk on insert and disk change now works
+ * Ver 0.94  Oct 27 00   Tidied up to remove strstr(Clik) everywhere
+ * Ver 0.95  Nov  7 00   Brought across to kernel 2.4
+ * Ver 0.96  Jan  7 01   Actually in line with release version of 2.4.0
+ *                       including set_bit patch from Rusty Russell
+ * Ver 0.97  Jul 22 01   Merge 0.91-0.96 onto 0.9.sv for ac series
+ * Ver 0.97.sv Aug 3 01  Backported from 2.4.7-ac3
+ * Ver 0.98  Oct 26 01   Split idefloppy_transfer_pc into two pieces to
+ *                        fix a lost interrupt problem. It appears the busy
+ *                        bit was being deasserted by my IOMEGA ATAPI ZIP 100
+ *                        drive before the drive was actually ready.
+ * Ver 0.98a Oct 29 01   Expose delay value so we can play.
+ * Ver 0.99  Feb 24 02   Remove duplicate code, modify clik! detection code
+ *                        to support new PocketZip drives
+ */
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 92c40d1..cf38689 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -168,6 +168,11 @@
 	acpi_irq_isa=	[HW,ACPI] If irq_balance, mark listed IRQs used by ISA
 			Format: <irq>,<irq>...
 
+	acpi_new_pts_ordering [HW,ACPI]
+			Enforce the ACPI 2.0 ordering of the _PTS control
+			method wrt putting devices into low power states
+			default: pre ACPI 2.0 ordering of _PTS
+
 	acpi_no_auto_ssdt	[HW,ACPI] Disable automatic loading of SSDT
 
 	acpi_os_name=	[HW,ACPI] Tell ACPI BIOS the name of the OS
diff --git a/Documentation/pci.txt b/Documentation/pci.txt
index 7754f5a..72b20c6 100644
--- a/Documentation/pci.txt
+++ b/Documentation/pci.txt
@@ -274,8 +274,6 @@
 	o allocate an IRQ (if BIOS did not).
 
 NOTE: pci_enable_device() can fail! Check the return value.
-NOTE2: Also see pci_enable_device_bars() below. Drivers can
-    attempt to enable only a subset of BARs they need.
 
 [ OS BUG: we don't check resource allocations before enabling those
   resources. The sequence would make more sense if we called
@@ -605,40 +603,7 @@
 
 
 
-10. pci_enable_device_bars() and Legacy I/O Port space
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Large servers may not be able to provide I/O port resources to all PCI
-devices. I/O Port space is only 64KB on Intel Architecture[1] and is
-likely also fragmented since the I/O base register of PCI-to-PCI
-bridge will usually be aligned to a 4KB boundary[2]. On such systems,
-pci_enable_device() and pci_request_region() will fail when
-attempting to enable I/O Port regions that don't have I/O Port
-resources assigned.
-
-Fortunately, many PCI devices which request I/O Port resources also
-provide access to the same registers via MMIO BARs. These devices can
-be handled without using I/O port space and the drivers typically
-offer a CONFIG_ option to only use MMIO regions
-(e.g. CONFIG_TULIP_MMIO). PCI devices typically provide I/O port
-interface for legacy OSes and will work when I/O port resources are not
-assigned. The "PCI Local Bus Specification Revision 3.0" discusses
-this on p.44, "IMPLEMENTATION NOTE".
-
-If your PCI device driver doesn't need I/O port resources assigned to
-I/O Port BARs, you should use pci_enable_device_bars() instead of
-pci_enable_device() in order not to enable I/O port regions for the
-corresponding devices. In addition, you should use
-pci_request_selected_regions() and pci_release_selected_regions()
-instead of pci_request_regions()/pci_release_regions() in order not to
-request/release I/O port regions for the corresponding devices.
-
-[1] Some systems support 64KB I/O port space per PCI segment.
-[2] Some PCI-to-PCI bridges support optional 1KB aligned I/O base.
-
-
-
-11. MMIO Space and "Write Posting"
+10. MMIO Space and "Write Posting"
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 Converting a driver from using I/O Port space to using MMIO space
diff --git a/Documentation/power/basic-pm-debugging.txt b/Documentation/power/basic-pm-debugging.txt
index 57aef2f..1555001 100644
--- a/Documentation/power/basic-pm-debugging.txt
+++ b/Documentation/power/basic-pm-debugging.txt
@@ -1,45 +1,111 @@
-Debugging suspend and resume
+Debugging hibernation and suspend
 	(C) 2007 Rafael J. Wysocki <rjw@sisk.pl>, GPL
 
-1. Testing suspend to disk (STD)
+1. Testing hibernation (aka suspend to disk or STD)
 
-To verify that the STD works, you can try to suspend in the "reboot" mode:
+To check if hibernation works, you can try to hibernate in the "reboot" mode:
 
 # echo reboot > /sys/power/disk
 # echo disk > /sys/power/state
 
-and the system should suspend, reboot, resume and get back to the command prompt
-where you have started the transition.  If that happens, the STD is most likely
-to work correctly, but you need to repeat the test at least a couple of times in
-a row for confidence.  This is necessary, because some problems only show up on
-a second attempt at suspending and resuming the system.  You should also test
-the "platform" and "shutdown" modes of suspend:
+and the system should create a hibernation image, reboot, resume and get back to
+the command prompt where you have started the transition.  If that happens,
+hibernation is most likely to work correctly.  Still, you need to repeat the
+test at least a couple of times in a row for confidence.  [This is necessary,
+because some problems only show up on a second attempt at suspending and
+resuming the system.]  Moreover, hibernating in the "reboot" and "shutdown"
+modes causes the PM core to skip some platform-related callbacks which on ACPI
+systems might be necessary to make hibernation work.  Thus, if you machine fails
+to hibernate or resume in the "reboot" mode, you should try the "platform" mode:
 
 # echo platform > /sys/power/disk
 # echo disk > /sys/power/state
 
-or
+which is the default and recommended mode of hibernation.
+
+Unfortunately, the "platform" mode of hibernation does not work on some systems
+with broken BIOSes.  In such cases the "shutdown" mode of hibernation might
+work:
 
 # echo shutdown > /sys/power/disk
 # echo disk > /sys/power/state
 
-in which cases you will have to press the power button to make the system
-resume.  If that does not work, you will need to identify what goes wrong.
+(it is similar to the "reboot" mode, but it requires you to press the power
+button to make the system resume).
 
-a) Test mode of STD
+If neither "platform" nor "shutdown" hibernation mode works, you will need to
+identify what goes wrong.
 
-To verify if there are any drivers that cause problems you can run the STD
-in the test mode:
+a) Test modes of hibernation
 
-# echo test > /sys/power/disk
+To find out why hibernation fails on your system, you can use a special testing
+facility available if the kernel is compiled with CONFIG_PM_DEBUG set.  Then,
+there is the file /sys/power/pm_test that can be used to make the hibernation
+core run in a test mode.  There are 5 test modes available:
+
+freezer
+- test the freezing of processes
+
+devices
+- test the freezing of processes and suspending of devices
+
+platform
+- test the freezing of processes, suspending of devices and platform
+  global control methods(*)
+
+processors
+- test the freezing of processes, suspending of devices, platform
+  global control methods(*) and the disabling of nonboot CPUs
+
+core
+- test the freezing of processes, suspending of devices, platform global
+  control methods(*), the disabling of nonboot CPUs and suspending of
+  platform/system devices
+
+(*) the platform global control methods are only available on ACPI systems
+    and are only tested if the hibernation mode is set to "platform"
+
+To use one of them it is necessary to write the corresponding string to
+/sys/power/pm_test (eg. "devices" to test the freezing of processes and
+suspending devices) and issue the standard hibernation commands.  For example,
+to use the "devices" test mode along with the "platform" mode of hibernation,
+you should do the following:
+
+# echo devices > /sys/power/pm_test
+# echo platform > /sys/power/disk
 # echo disk > /sys/power/state
 
-in which case the system should freeze tasks, suspend devices, disable nonboot
-CPUs (if any), wait for 5 seconds, enable nonboot CPUs, resume devices, thaw
-tasks and return to your command prompt.  If that fails, most likely there is
-a driver that fails to either suspend or resume (in the latter case the system
-may hang or be unstable after the test, so please take that into consideration).
-To find this driver, you can carry out a binary search according to the rules:
+Then, the kernel will try to freeze processes, suspend devices, wait 5 seconds,
+resume devices and thaw processes.  If "platform" is written to
+/sys/power/pm_test , then after suspending devices the kernel will additionally
+invoke the global control methods (eg. ACPI global control methods) used to
+prepare the platform firmware for hibernation.  Next, it will wait 5 seconds and
+invoke the platform (eg. ACPI) global methods used to cancel hibernation etc.
+
+Writing "none" to /sys/power/pm_test causes the kernel to switch to the normal
+hibernation/suspend operations.  Also, when open for reading, /sys/power/pm_test
+contains a space-separated list of all available tests (including "none" that
+represents the normal functionality) in which the current test level is
+indicated by square brackets.
+
+Generally, as you can see, each test level is more "invasive" than the previous
+one and the "core" level tests the hardware and drivers as deeply as possible
+without creating a hibernation image.  Obviously, if the "devices" test fails,
+the "platform" test will fail as well and so on.  Thus, as a rule of thumb, you
+should try the test modes starting from "freezer", through "devices", "platform"
+and "processors" up to "core" (repeat the test on each level a couple of times
+to make sure that any random factors are avoided).
+
+If the "freezer" test fails, there is a task that cannot be frozen (in that case
+it usually is possible to identify the offending task by analysing the output of
+dmesg obtained after the failing test).  Failure at this level usually means
+that there is a problem with the tasks freezer subsystem that should be
+reported.
+
+If the "devices" test fails, most likely there is a driver that cannot suspend
+or resume its device (in the latter case the system may hang or become unstable
+after the test, so please take that into consideration).  To find this driver,
+you can carry out a binary search according to the rules:
 - if the test fails, unload a half of the drivers currently loaded and repeat
 (that would probably involve rebooting the system, so always note what drivers
 have been loaded before the test),
@@ -47,23 +113,46 @@
 recently and repeat.
 
 Once you have found the failing driver (there can be more than just one of
-them), you have to unload it every time before the STD transition.  In that case
-please make sure to report the problem with the driver.
+them), you have to unload it every time before hibernation.  In that case please
+make sure to report the problem with the driver.
 
-It is also possible that a cycle can still fail after you have unloaded
-all modules. In that case, you would want to look in your kernel configuration
-for the drivers that can be compiled as modules (testing again with them as
-modules), and possibly also try boot time options such as "noapic" or "noacpi".
+It is also possible that the "devices" test will still fail after you have
+unloaded all modules. In that case, you may want to look in your kernel
+configuration for the drivers that can be compiled as modules (and test again
+with these drivers compiled as modules).  You may also try to use some special
+kernel command line options such as "noapic", "noacpi" or even "acpi=off".
+
+If the "platform" test fails, there is a problem with the handling of the
+platform (eg. ACPI) firmware on your system.  In that case the "platform" mode
+of hibernation is not likely to work.  You can try the "shutdown" mode, but that
+is rather a poor man's workaround.
+
+If the "processors" test fails, the disabling/enabling of nonboot CPUs does not
+work (of course, this only may be an issue on SMP systems) and the problem
+should be reported.  In that case you can also try to switch the nonboot CPUs
+off and on using the /sys/devices/system/cpu/cpu*/online sysfs attributes and
+see if that works.
+
+If the "core" test fails, which means that suspending of the system/platform
+devices has failed (these devices are suspended on one CPU with interrupts off),
+the problem is most probably hardware-related and serious, so it should be
+reported.
+
+A failure of any of the "platform", "processors" or "core" tests may cause your
+system to hang or become unstable, so please beware.  Such a failure usually
+indicates a serious problem that very well may be related to the hardware, but
+please report it anyway.
 
 b) Testing minimal configuration
 
-If the test mode of STD works, you can boot the system with "init=/bin/bash"
-and attempt to suspend in the "reboot", "shutdown" and "platform" modes.  If
-that does not work, there probably is a problem with a driver statically
-compiled into the kernel and you can try to compile more drivers as modules,
-so that they can be tested individually.  Otherwise, there is a problem with a
-modular driver and you can find it by loading a half of the modules you normally
-use and binary searching in accordance with the algorithm:
+If all of the hibernation test modes work, you can boot the system with the
+"init=/bin/bash" command line parameter and attempt to hibernate in the
+"reboot", "shutdown" and "platform" modes.  If that does not work, there
+probably is a problem with a driver statically compiled into the kernel and you
+can try to compile more drivers as modules, so that they can be tested
+individually.  Otherwise, there is a problem with a modular driver and you can
+find it by loading a half of the modules you normally use and binary searching
+in accordance with the algorithm:
 - if there are n modules loaded and the attempt to suspend and resume fails,
 unload n/2 of the modules and try again (that would probably involve rebooting
 the system),
@@ -71,19 +160,19 @@
 load n/2 modules more and try again.
 
 Again, if you find the offending module(s), it(they) must be unloaded every time
-before the STD transition, and please report the problem with it(them).
+before hibernation, and please report the problem with it(them).
 
 c) Advanced debugging
 
-In case the STD does not work on your system even in the minimal configuration
-and compiling more drivers as modules is not practical or some modules cannot
-be unloaded, you can use one of the more advanced debugging techniques to find
-the problem.  First, if there is a serial port in your box, you can boot the
-kernel with the 'no_console_suspend' parameter and try to log kernel
-messages using the serial console.  This may provide you with some information
-about the reasons of the suspend (resume) failure.  Alternatively, it may be
-possible to use a FireWire port for debugging with firescope
-(ftp://ftp.firstfloor.org/pub/ak/firescope/).  On i386 it is also possible to
+In case that hibernation does not work on your system even in the minimal
+configuration and compiling more drivers as modules is not practical or some
+modules cannot be unloaded, you can use one of the more advanced debugging
+techniques to find the problem.  First, if there is a serial port in your box,
+you can boot the kernel with the 'no_console_suspend' parameter and try to log
+kernel messages using the serial console.  This may provide you with some
+information about the reasons of the suspend (resume) failure.  Alternatively,
+it may be possible to use a FireWire port for debugging with firescope
+(ftp://ftp.firstfloor.org/pub/ak/firescope/).  On x86 it is also possible to
 use the PM_TRACE mechanism documented in Documentation/s2ram.txt .
 
 2. Testing suspend to RAM (STR)
@@ -91,16 +180,25 @@
 To verify that the STR works, it is generally more convenient to use the s2ram
 tool available from http://suspend.sf.net and documented at
 http://en.opensuse.org/s2ram .  However, before doing that it is recommended to
-carry out the procedure described in section 1.
+carry out STR testing using the facility described in section 1.
 
-Assume you have resolved the problems with the STD and you have found some
-failing drivers.  These drivers are also likely to fail during the STR or
-during the resume, so it is better to unload them every time before the STR
-transition.  Now, you can follow the instructions at
-http://en.opensuse.org/s2ram to test the system, but if it does not work
-"out of the box", you may need to boot it with "init=/bin/bash" and test
-s2ram in the minimal configuration.  In that case, you may be able to search
-for failing drivers by following the procedure analogous to the one described in
-1b).  If you find some failing drivers, you will have to unload them every time
-before the STR transition (ie. before you run s2ram), and please report the
-problems with them.
+Namely, after writing "freezer", "devices", "platform", "processors", or "core"
+into /sys/power/pm_test (available if the kernel is compiled with
+CONFIG_PM_DEBUG set) the suspend code will work in the test mode corresponding
+to given string.  The STR test modes are defined in the same way as for
+hibernation, so please refer to Section 1 for more information about them.  In
+particular, the "core" test allows you to test everything except for the actual
+invocation of the platform firmware in order to put the system into the sleep
+state.
+
+Among other things, the testing with the help of /sys/power/pm_test may allow
+you to identify drivers that fail to suspend or resume their devices.  They
+should be unloaded every time before an STR transition.
+
+Next, you can follow the instructions at http://en.opensuse.org/s2ram to test
+the system, but if it does not work "out of the box", you may need to boot it
+with "init=/bin/bash" and test s2ram in the minimal configuration.  In that
+case, you may be able to search for failing drivers by following the procedure
+analogous to the one described in section 1.  If you find some failing drivers,
+you will have to unload them every time before an STR transition (ie. before
+you run s2ram), and please report the problems with them.
diff --git a/Documentation/power/devices.txt b/Documentation/power/devices.txt
index d0e79d5..c53d263 100644
--- a/Documentation/power/devices.txt
+++ b/Documentation/power/devices.txt
@@ -502,52 +502,3 @@
 to shift to lower voltage settings and reduce the power cost of executing
 a given number of instructions.  (Without voltage adjustment, it's rare
 for cpufreq to save much power; the cost-per-instruction must go down.)
-
-
-/sys/devices/.../power/state files
-==================================
-For now you can also test some of this functionality using sysfs.
-
-	DEPRECATED:  USE "power/state" ONLY FOR DRIVER TESTING, AND
-	AVOID USING dev->power.power_state IN DRIVERS.
-
-	THESE WILL BE REMOVED.  IF THE "power/state" FILE GETS REPLACED,
-	IT WILL BECOME SOMETHING COUPLED TO THE BUS OR DRIVER.
-
-In each device's directory, there is a 'power' directory, which contains
-at least a 'state' file.  The value of this field is effectively boolean,
-PM_EVENT_ON or PM_EVENT_SUSPEND.
-
-   *	Reading from this file displays a value corresponding to
-	the power.power_state.event field.  All nonzero values are
-	displayed as "2", corresponding to a low power state; zero
-	is displayed as "0", corresponding to normal operation.
-
-   *	Writing to this file initiates a transition using the
-   	specified event code number; only '0', '2', and '3' are
-	accepted (without a newline); '2' and '3' are both
-	mapped to PM_EVENT_SUSPEND.
-
-On writes, the PM core relies on that recorded event code and the device/bus
-capabilities to determine whether it uses a partial suspend() or resume()
-sequence to change things so that the recorded event corresponds to the
-numeric parameter.
-
-   -	If the bus requires the irqs-disabled suspend_late()/resume_early()
-	phases, writes fail because those operations are not supported here.
-
-   -	If the recorded value is the expected value, nothing is done.
-
-   -	If the recorded value is nonzero, the device is partially resumed,
-	using the bus.resume() and/or class.resume() methods.
-
-   -	If the target value is nonzero, the device is partially suspended,
-	using the class.suspend() and/or bus.suspend() methods and the
-	PM_EVENT_SUSPEND message.
-
-Drivers have no way to tell whether their suspend() and resume() calls
-have come through the sysfs power/state file or as part of entering a
-system sleep state, except that when accessed through sysfs the normal
-parent/child sequencing rules are ignored.  Drivers (such as bus, bridge,
-or hub drivers) which expose child devices may need to enforce those rules
-on their own.
diff --git a/Documentation/power/drivers-testing.txt b/Documentation/power/drivers-testing.txt
index e4bdcae..7f7a737 100644
--- a/Documentation/power/drivers-testing.txt
+++ b/Documentation/power/drivers-testing.txt
@@ -6,9 +6,9 @@
 Unfortunately, to effectively test the support for the system-wide suspend and
 resume transitions in a driver, it is necessary to suspend and resume a fully
 functional system with this driver loaded.  Moreover, that should be done
-several times, preferably several times in a row, and separately for the suspend
-to disk (STD) and the suspend to RAM (STR) transitions, because each of these
-cases involves different ordering of operations and different interactions with
+several times, preferably several times in a row, and separately for hibernation
+(aka suspend to disk or STD) and suspend to RAM (STR), because each of these
+cases involves slightly different operations and different interactions with
 the machine's BIOS.
 
 Of course, for this purpose the test system has to be known to suspend and
@@ -22,20 +22,24 @@
 Once you have resolved the suspend/resume-related problems with your test system
 without the new driver, you are ready to test it:
 
-a) Build the driver as a module, load it and try the STD in the test mode (see:
-Documents/power/basic-pm-debugging.txt, 1a)).
+a) Build the driver as a module, load it and try the test modes of hibernation
+   (see: Documents/power/basic-pm-debugging.txt, 1).
 
-b) Load the driver and attempt to suspend to disk in the "reboot", "shutdown"
-and "platform" modes (see: Documents/power/basic-pm-debugging.txt, 1).
+b) Load the driver and attempt to hibernate in the "reboot", "shutdown" and
+   "platform" modes (see: Documents/power/basic-pm-debugging.txt, 1).
 
-c) Compile the driver directly into the kernel and try the STD in the test mode.
+c) Compile the driver directly into the kernel and try the test modes of
+   hibernation.
 
-d) Attempt to suspend to disk with the driver compiled directly into the kernel
-in the "reboot", "shutdown" and "platform" modes.
+d) Attempt to hibernate with the driver compiled directly into the kernel
+   in the "reboot", "shutdown" and "platform" modes.
 
-e) Attempt to suspend to RAM using the s2ram tool with the driver loaded (see:
-Documents/power/basic-pm-debugging.txt, 2).  As far as the STR tests are
-concerned, it should not matter whether or not the driver is built as a module.
+e) Try the test modes of suspend (see: Documents/power/basic-pm-debugging.txt,
+   2).  [As far as the STR tests are concerned, it should not matter whether or
+   not the driver is built as a module.]
+
+f) Attempt to suspend to RAM using the s2ram tool with the driver loaded
+   (see: Documents/power/basic-pm-debugging.txt, 2).
 
 Each of the above tests should be repeated several times and the STD tests
 should be mixed with the STR tests.  If any of them fails, the driver cannot be
diff --git a/Documentation/power/notifiers.txt b/Documentation/power/notifiers.txt
index 9293e4b..ae1b7ec 100644
--- a/Documentation/power/notifiers.txt
+++ b/Documentation/power/notifiers.txt
@@ -28,6 +28,14 @@
 			hibernation.  Device drivers' .resume() callbacks have
 			been executed and tasks have been thawed.
 
+PM_RESTORE_PREPARE	The system is going to restore a hibernation image.
+			If all goes well the restored kernel will issue a
+			PM_POST_HIBERNATION notification.
+
+PM_POST_RESTORE		An error occurred during the hibernation restore.
+			Device drivers' .resume() callbacks have been executed
+			and tasks have been thawed.
+
 PM_SUSPEND_PREPARE	The system is preparing for a suspend.
 
 PM_POST_SUSPEND		The system has just resumed or an error occured during
diff --git a/Documentation/power/userland-swsusp.txt b/Documentation/power/userland-swsusp.txt
index e00c6cf..7b99636 100644
--- a/Documentation/power/userland-swsusp.txt
+++ b/Documentation/power/userland-swsusp.txt
@@ -14,7 +14,7 @@
 
 The interface consists of a character device providing the open(),
 release(), read(), and write() operations as well as several ioctl()
-commands defined in kernel/power/power.h.  The major and minor
+commands defined in include/linux/suspend_ioctls.h .  The major and minor
 numbers of the device are, respectively, 10 and 231, and they can
 be read from /sys/class/misc/snapshot/dev.
 
@@ -27,17 +27,17 @@
 The ioctl() commands recognized by the device are:
 
 SNAPSHOT_FREEZE - freeze user space processes (the current process is
-	not frozen); this is required for SNAPSHOT_ATOMIC_SNAPSHOT
+	not frozen); this is required for SNAPSHOT_CREATE_IMAGE
 	and SNAPSHOT_ATOMIC_RESTORE to succeed
 
 SNAPSHOT_UNFREEZE - thaw user space processes frozen by SNAPSHOT_FREEZE
 
-SNAPSHOT_ATOMIC_SNAPSHOT - create a snapshot of the system memory; the
+SNAPSHOT_CREATE_IMAGE - create a snapshot of the system memory; the
 	last argument of ioctl() should be a pointer to an int variable,
 	the value of which will indicate whether the call returned after
 	creating the snapshot (1) or after restoring the system memory state
 	from it (0) (after resume the system finds itself finishing the
-	SNAPSHOT_ATOMIC_SNAPSHOT ioctl() again); after the snapshot
+	SNAPSHOT_CREATE_IMAGE ioctl() again); after the snapshot
 	has been created the read() operation can be used to transfer
 	it out of the kernel
 
@@ -49,39 +49,37 @@
 
 SNAPSHOT_FREE - free memory allocated for the snapshot image
 
-SNAPSHOT_SET_IMAGE_SIZE - set the preferred maximum size of the image
+SNAPSHOT_PREF_IMAGE_SIZE - set the preferred maximum size of the image
 	(the kernel will do its best to ensure the image size will not exceed
 	this number, but if it turns out to be impossible, the kernel will
 	create the smallest image possible)
 
-SNAPSHOT_AVAIL_SWAP - return the amount of available swap in bytes (the last
-	argument should be a pointer to an unsigned int variable that will
+SNAPSHOT_GET_IMAGE_SIZE - return the actual size of the hibernation image
+
+SNAPSHOT_AVAIL_SWAP_SIZE - return the amount of available swap in bytes (the
+	last argument should be a pointer to an unsigned int variable that will
 	contain the result if the call is successful).
 
-SNAPSHOT_GET_SWAP_PAGE - allocate a swap page from the resume partition
+SNAPSHOT_ALLOC_SWAP_PAGE - allocate a swap page from the resume partition
 	(the last argument should be a pointer to a loff_t variable that
 	will contain the swap page offset if the call is successful)
 
-SNAPSHOT_FREE_SWAP_PAGES - free all swap pages allocated with
-	SNAPSHOT_GET_SWAP_PAGE
-
-SNAPSHOT_SET_SWAP_FILE - set the resume partition (the last ioctl() argument
-	should specify the device's major and minor numbers in the old
-	two-byte format, as returned by the stat() function in the .st_rdev
-	member of the stat structure)
+SNAPSHOT_FREE_SWAP_PAGES - free all swap pages allocated by
+	SNAPSHOT_ALLOC_SWAP_PAGE
 
 SNAPSHOT_SET_SWAP_AREA - set the resume partition and the offset (in <PAGE_SIZE>
 	units) from the beginning of the partition at which the swap header is
 	located (the last ioctl() argument should point to a struct
-	resume_swap_area, as defined in kernel/power/power.h, containing the
-	resume device specification, as for the SNAPSHOT_SET_SWAP_FILE ioctl(),
-	and the offset); for swap partitions the offset is always 0, but it is
-	different to zero for swap files (please see
-	Documentation/swsusp-and-swap-files.txt for details).
-	The SNAPSHOT_SET_SWAP_AREA ioctl() is considered as a replacement for
-	SNAPSHOT_SET_SWAP_FILE which is regarded as obsolete.   It is
-	recommended to always use this call, because the code to set the resume
-	partition may be removed from future kernels
+	resume_swap_area, as defined in kernel/power/suspend_ioctls.h,
+	containing the resume device specification and the offset); for swap
+	partitions the offset is always 0, but it is different from zero for
+	swap files (see Documentation/swsusp-and-swap-files.txt for details).
+
+SNAPSHOT_PLATFORM_SUPPORT - enable/disable the hibernation platform support,
+	depending on the argument value (enable, if the argument is nonzero)
+
+SNAPSHOT_POWER_OFF - make the kernel transition the system to the hibernation
+	state (eg. ACPI S4) using the platform (eg. ACPI) driver
 
 SNAPSHOT_S2RAM - suspend to RAM; using this call causes the kernel to
 	immediately enter the suspend-to-RAM state, so this call must always
@@ -93,24 +91,6 @@
 	to resume the system from RAM if there's enough battery power or restore
 	its state on the basis of the saved suspend image otherwise)
 
-SNAPSHOT_PMOPS - enable the usage of the hibernation_ops->prepare,
-	hibernate_ops->enter and hibernation_ops->finish methods (the in-kernel
-	swsusp knows these as the "platform method") which are needed on many
-	machines to (among others) speed up the resume by letting the BIOS skip
-	some steps or to let the system recognise the correct state of the
-	hardware after the resume (in particular on many machines this ensures
-	that unplugged AC adapters get correctly detected and that kacpid does
-	not run wild after the resume).  The last ioctl() argument can take one
-	of the three values, defined in kernel/power/power.h:
-	PMOPS_PREPARE - make the kernel carry out the
-		hibernation_ops->prepare() operation
-	PMOPS_ENTER - make the kernel power off the system by calling
-		hibernation_ops->enter()
-	PMOPS_FINISH - make the kernel carry out the
-		hibernation_ops->finish() operation
-	Note that the actual constants are misnamed because they surface
-	internal kernel implementation details that have changed.
-
 The device's read() operation can be used to transfer the snapshot image from
 the kernel.  It has the following limitations:
 - you cannot read() more than one virtual memory page at a time
@@ -122,7 +102,7 @@
 into the kernel.  It has the same limitations as the read() operation.
 
 The release() operation frees all memory allocated for the snapshot image
-and all swap pages allocated with SNAPSHOT_GET_SWAP_PAGE (if any).
+and all swap pages allocated with SNAPSHOT_ALLOC_SWAP_PAGE (if any).
 Thus it is not necessary to use either SNAPSHOT_FREE or
 SNAPSHOT_FREE_SWAP_PAGES before closing the device (in fact it will also
 unfreeze user space processes frozen by SNAPSHOT_UNFREEZE if they are
@@ -133,16 +113,12 @@
 partition, or a swap file as storage space (if a swap file is used, the resume
 partition is the partition that holds this file).  However, this is not really
 required, as they can use, for example, a special (blank) suspend partition or
-a file on a partition that is unmounted before SNAPSHOT_ATOMIC_SNAPSHOT and
+a file on a partition that is unmounted before SNAPSHOT_CREATE_IMAGE and
 mounted afterwards.
 
-These utilities SHOULD NOT make any assumptions regarding the ordering of
-data within the snapshot image, except for the image header that MAY be
-assumed to start with an swsusp_info structure, as specified in
-kernel/power/power.h.  This structure MAY be used by the userland utilities
-to obtain some information about the snapshot image, such as the size
-of the snapshot image, including the metadata and the header itself,
-contained in the .size member of swsusp_info.
+These utilities MUST NOT make any assumptions regarding the ordering of
+data within the snapshot image.  The contents of the image are entirely owned
+by the kernel and its structure may be changed in future kernel releases.
 
 The snapshot image MUST be written to the kernel unaltered (ie. all of the image
 data, metadata and header MUST be written in _exactly_ the same amount, form
@@ -159,7 +135,7 @@
 The suspending and resuming utilities MUST lock themselves in memory,
 preferrably using mlockall(), before calling SNAPSHOT_FREEZE.
 
-The suspending utility MUST check the value stored by SNAPSHOT_ATOMIC_SNAPSHOT
+The suspending utility MUST check the value stored by SNAPSHOT_CREATE_IMAGE
 in the memory location pointed to by the last argument of ioctl() and proceed
 in accordance with it:
 1. 	If the value is 1 (ie. the system memory snapshot has just been
@@ -173,7 +149,7 @@
 		image has been saved.
 	(b)	The suspending utility SHOULD NOT attempt to perform any
 		file system operations (including reads) on the file systems
-		that were mounted before SNAPSHOT_ATOMIC_SNAPSHOT has been
+		that were mounted before SNAPSHOT_CREATE_IMAGE has been
 		called.  However, it MAY mount a file system that was not
 		mounted at that time and perform some operations on it (eg.
 		use it for saving the image).
diff --git a/Documentation/usb/gadget_printer.txt b/Documentation/usb/gadget_printer.txt
new file mode 100644
index 0000000..ad995bf
--- /dev/null
+++ b/Documentation/usb/gadget_printer.txt
@@ -0,0 +1,510 @@
+
+                       Linux USB Printer Gadget Driver
+                                 06/04/2007
+
+              Copyright (C) 2007 Craig W. Nadler <craig@nadler.us>
+
+
+
+GENERAL
+=======
+
+This driver may be used if you are writing printer firmware using Linux as
+the embedded OS. This driver has nothing to do with using a printer with
+your Linux host system.
+
+You will need a USB device controller and a Linux driver for it that accepts
+a gadget / "device class" driver using the Linux USB Gadget API. After the
+USB device controller driver is loaded then load the printer gadget driver.
+This will present a printer interface to the USB Host that your USB Device
+port is connected to.
+
+This driver is structured for printer firmware that runs in user mode. The
+user mode printer firmware will read and write data from the kernel mode
+printer gadget driver using a device file. The printer returns a printer status
+byte when the USB HOST sends a device request to get the printer status.  The
+user space firmware can read or write this status byte using a device file
+/dev/g_printer . Both blocking and non-blocking read/write calls are supported.
+
+
+
+
+HOWTO USE THIS DRIVER
+=====================
+
+To load the USB device controller driver and the printer gadget driver. The
+following example uses the Netchip 2280 USB device controller driver:
+
+modprobe net2280
+modprobe g_printer
+
+
+The follow command line parameter can be used when loading the printer gadget
+(ex: modprobe g_printer idVendor=0x0525 idProduct=0xa4a8 ):
+
+idVendor - This is the Vendor ID used in the device descriptor. The default is
+	the Netchip vendor id 0x0525. YOU MUST CHANGE TO YOUR OWN VENDOR ID
+	BEFORE RELEASING A PRODUCT. If you plan to release a product and don't
+	already have a Vendor ID please see www.usb.org for details on how to
+	get one.
+
+idProduct - This is the Product ID used in the device descriptor. The default
+	is 0xa4a8, you should change this to an ID that's not used by any of
+	your other USB products if you have any. It would be a good idea to
+	start numbering your products starting with say 0x0001.
+
+bcdDevice - This is the version number of your product. It would be a good idea
+	to put your firmware version here.
+
+iManufacturer - A string containing the name of the Vendor.
+
+iProduct - A string containing the Product Name.
+
+iSerialNum - A string containing the Serial Number. This should be changed for
+	each unit of your product.
+
+iPNPstring -  The PNP ID string used for this printer. You will want to set
+	either on the command line or hard code the PNP ID string used for
+	your printer product.
+
+qlen - The number of 8k buffers to use per endpoint. The default is 10, you
+	should tune this for your product. You may also want to tune the
+	size of each buffer for your product.
+
+
+
+
+USING THE EXAMPLE CODE
+======================
+
+This example code talks to stdout, instead of a print engine.
+
+To compile the test code below:
+
+1) save it to a file called prn_example.c
+2) compile the code with the follow command:
+	 gcc prn_example.c -o prn_example
+
+
+
+To read printer data from the host to stdout:
+
+	# prn_example -read_data
+
+
+To write printer data from a file (data_file) to the host:
+
+	# cat data_file | prn_example -write_data
+
+
+To get the current printer status for the gadget driver:
+
+	# prn_example -get_status
+
+	Printer status is:
+	     Printer is NOT Selected
+	     Paper is Out
+	     Printer OK
+
+
+To set printer to Selected/On-line:
+
+	# prn_example -selected
+
+
+To set printer to Not Selected/Off-line:
+
+	# prn_example -not_selected
+
+
+To set paper status to paper out:
+
+	# prn_example -paper_out
+
+
+To set paper status to paper loaded:
+
+	# prn_example -paper_loaded
+
+
+To set error status to printer OK:
+
+	# prn_example -no_error
+
+
+To set error status to ERROR:
+
+	# prn_example -error
+
+
+
+
+EXAMPLE CODE
+============
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <linux/poll.h>
+#include <sys/ioctl.h>
+#include <linux/usb/g_printer.h>
+
+#define PRINTER_FILE			"/dev/g_printer"
+#define BUF_SIZE			512
+
+
+/*
+ * 'usage()' - Show program usage.
+ */
+
+static void
+usage(const char *option)		/* I - Option string or NULL */
+{
+	if (option) {
+		fprintf(stderr,"prn_example: Unknown option \"%s\"!\n",
+				option);
+	}
+
+	fputs("\n", stderr);
+	fputs("Usage: prn_example -[options]\n", stderr);
+	fputs("Options:\n", stderr);
+	fputs("\n", stderr);
+	fputs("-get_status    Get the current printer status.\n", stderr);
+	fputs("-selected      Set the selected status to selected.\n", stderr);
+	fputs("-not_selected  Set the selected status to NOT selected.\n",
+			stderr);
+	fputs("-error         Set the error status to error.\n", stderr);
+	fputs("-no_error      Set the error status to NO error.\n", stderr);
+	fputs("-paper_out     Set the paper status to paper out.\n", stderr);
+	fputs("-paper_loaded  Set the paper status to paper loaded.\n",
+			stderr);
+	fputs("-read_data     Read printer data from driver.\n", stderr);
+	fputs("-write_data    Write printer sata to driver.\n", stderr);
+	fputs("-NB_read_data  (Non-Blocking) Read printer data from driver.\n",
+			stderr);
+	fputs("\n\n", stderr);
+
+	exit(1);
+}
+
+
+static int
+read_printer_data()
+{
+	struct pollfd	fd[1];
+
+	/* Open device file for printer gadget. */
+	fd[0].fd = open(PRINTER_FILE, O_RDWR);
+	if (fd[0].fd < 0) {
+		printf("Error %d opening %s\n", fd[0].fd, PRINTER_FILE);
+		close(fd[0].fd);
+		return(-1);
+	}
+
+	fd[0].events = POLLIN | POLLRDNORM;
+
+	while (1) {
+		static char buf[BUF_SIZE];
+		int bytes_read;
+		int retval;
+
+		/* Wait for up to 1 second for data. */
+		retval = poll(fd, 1, 1000);
+
+		if (retval && (fd[0].revents & POLLRDNORM)) {
+
+			/* Read data from printer gadget driver. */
+			bytes_read = read(fd[0].fd, buf, BUF_SIZE);
+
+			if (bytes_read < 0) {
+				printf("Error %d reading from %s\n",
+						fd[0].fd, PRINTER_FILE);
+				close(fd[0].fd);
+				return(-1);
+			} else if (bytes_read > 0) {
+				/* Write data to standard OUTPUT (stdout). */
+				fwrite(buf, 1, bytes_read, stdout);
+				fflush(stdout);
+			}
+
+		}
+
+	}
+
+	/* Close the device file. */
+	close(fd[0].fd);
+
+	return 0;
+}
+
+
+static int
+write_printer_data()
+{
+	struct pollfd	fd[1];
+
+	/* Open device file for printer gadget. */
+	fd[0].fd = open (PRINTER_FILE, O_RDWR);
+	if (fd[0].fd < 0) {
+		printf("Error %d opening %s\n", fd[0].fd, PRINTER_FILE);
+		close(fd[0].fd);
+		return(-1);
+	}
+
+	fd[0].events = POLLOUT | POLLWRNORM;
+
+	while (1) {
+		int retval;
+		static char buf[BUF_SIZE];
+		/* Read data from standard INPUT (stdin). */
+		int bytes_read = fread(buf, 1, BUF_SIZE, stdin);
+
+		if (!bytes_read) {
+			break;
+		}
+
+		while (bytes_read) {
+
+			/* Wait for up to 1 second to sent data. */
+			retval = poll(fd, 1, 1000);
+
+			/* Write data to printer gadget driver. */
+			if (retval && (fd[0].revents & POLLWRNORM)) {
+				retval = write(fd[0].fd, buf, bytes_read);
+				if (retval < 0) {
+					printf("Error %d writing to %s\n",
+							fd[0].fd,
+							PRINTER_FILE);
+					close(fd[0].fd);
+					return(-1);
+				} else {
+					bytes_read -= retval;
+				}
+
+			}
+
+		}
+
+	}
+
+	/* Wait until the data has been sent. */
+	fsync(fd[0].fd);
+
+	/* Close the device file. */
+	close(fd[0].fd);
+
+	return 0;
+}
+
+
+static int
+read_NB_printer_data()
+{
+	int		fd;
+	static char	buf[BUF_SIZE];
+	int		bytes_read;
+
+	/* Open device file for printer gadget. */
+	fd = open(PRINTER_FILE, O_RDWR|O_NONBLOCK);
+	if (fd < 0) {
+		printf("Error %d opening %s\n", fd, PRINTER_FILE);
+		close(fd);
+		return(-1);
+	}
+
+	while (1) {
+		/* Read data from printer gadget driver. */
+		bytes_read = read(fd, buf, BUF_SIZE);
+		if (bytes_read <= 0) {
+			break;
+		}
+
+		/* Write data to standard OUTPUT (stdout). */
+		fwrite(buf, 1, bytes_read, stdout);
+		fflush(stdout);
+	}
+
+	/* Close the device file. */
+	close(fd);
+
+	return 0;
+}
+
+
+static int
+get_printer_status()
+{
+	int	retval;
+	int	fd;
+
+	/* Open device file for printer gadget. */
+	fd = open(PRINTER_FILE, O_RDWR);
+	if (fd < 0) {
+		printf("Error %d opening %s\n", fd, PRINTER_FILE);
+		close(fd);
+		return(-1);
+	}
+
+	/* Make the IOCTL call. */
+	retval = ioctl(fd, GADGET_GET_PRINTER_STATUS);
+	if (retval < 0) {
+		fprintf(stderr, "ERROR: Failed to set printer status\n");
+		return(-1);
+	}
+
+	/* Close the device file. */
+	close(fd);
+
+	return(retval);
+}
+
+
+static int
+set_printer_status(unsigned char buf, int clear_printer_status_bit)
+{
+	int	retval;
+	int	fd;
+
+	retval = get_printer_status();
+	if (retval < 0) {
+		fprintf(stderr, "ERROR: Failed to get printer status\n");
+		return(-1);
+	}
+
+	/* Open device file for printer gadget. */
+	fd = open(PRINTER_FILE, O_RDWR);
+
+	if (fd < 0) {
+		printf("Error %d opening %s\n", fd, PRINTER_FILE);
+		close(fd);
+		return(-1);
+	}
+
+	if (clear_printer_status_bit) {
+		retval &= ~buf;
+	} else {
+		retval |= buf;
+	}
+
+	/* Make the IOCTL call. */
+	if (ioctl(fd, GADGET_SET_PRINTER_STATUS, (unsigned char)retval)) {
+		fprintf(stderr, "ERROR: Failed to set printer status\n");
+		return(-1);
+	}
+
+	/* Close the device file. */
+	close(fd);
+
+	return 0;
+}
+
+
+static int
+display_printer_status()
+{
+	char	printer_status;
+
+	printer_status = get_printer_status();
+	if (printer_status < 0) {
+		fprintf(stderr, "ERROR: Failed to get printer status\n");
+		return(-1);
+	}
+
+	printf("Printer status is:\n");
+	if (printer_status & PRINTER_SELECTED) {
+		printf("     Printer is Selected\n");
+	} else {
+		printf("     Printer is NOT Selected\n");
+	}
+	if (printer_status & PRINTER_PAPER_EMPTY) {
+		printf("     Paper is Out\n");
+	} else {
+		printf("     Paper is Loaded\n");
+	}
+	if (printer_status & PRINTER_NOT_ERROR) {
+		printf("     Printer OK\n");
+	} else {
+		printf("     Printer ERROR\n");
+	}
+
+	return(0);
+}
+
+
+int
+main(int  argc, char *argv[])
+{
+	int	i;		/* Looping var */
+	int	retval = 0;
+
+	/* No Args */
+	if (argc == 1) {
+		usage(0);
+		exit(0);
+	}
+
+	for (i = 1; i < argc && !retval; i ++) {
+
+		if (argv[i][0] != '-') {
+			continue;
+		}
+
+		if (!strcmp(argv[i], "-get_status")) {
+			if (display_printer_status()) {
+				retval = 1;
+			}
+
+		} else if (!strcmp(argv[i], "-paper_loaded")) {
+			if (set_printer_status(PRINTER_PAPER_EMPTY, 1)) {
+				retval = 1;
+			}
+
+		} else if (!strcmp(argv[i], "-paper_out")) {
+			if (set_printer_status(PRINTER_PAPER_EMPTY, 0)) {
+				retval = 1;
+			}
+
+		} else if (!strcmp(argv[i], "-selected")) {
+			if (set_printer_status(PRINTER_SELECTED, 0)) {
+				retval = 1;
+			}
+
+		} else if (!strcmp(argv[i], "-not_selected")) {
+			if (set_printer_status(PRINTER_SELECTED, 1)) {
+				retval = 1;
+			}
+
+		} else if (!strcmp(argv[i], "-error")) {
+			if (set_printer_status(PRINTER_NOT_ERROR, 1)) {
+				retval = 1;
+			}
+
+		} else if (!strcmp(argv[i], "-no_error")) {
+			if (set_printer_status(PRINTER_NOT_ERROR, 0)) {
+				retval = 1;
+			}
+
+		} else if (!strcmp(argv[i], "-read_data")) {
+			if (read_printer_data()) {
+				retval = 1;
+			}
+
+		} else if (!strcmp(argv[i], "-write_data")) {
+			if (write_printer_data()) {
+				retval = 1;
+			}
+
+		} else if (!strcmp(argv[i], "-NB_read_data")) {
+			if (read_NB_printer_data()) {
+				retval = 1;
+			}
+
+		} else {
+			usage(argv[i]);
+			retval = 1;
+		}
+	}
+
+	exit(retval);
+}
diff --git a/Documentation/usb/iuu_phoenix.txt b/Documentation/usb/iuu_phoenix.txt
new file mode 100644
index 0000000..e5f0480
--- /dev/null
+++ b/Documentation/usb/iuu_phoenix.txt
@@ -0,0 +1,84 @@
+Infinity Usb Unlimited Readme
+-----------------------------
+
+Hi all,
+
+
+This module provide a serial interface to use your
+IUU unit in phoenix mode. Loading this module will
+bring a ttyUSB[0-x] interface. This driver must be
+used by your favorite application to pilot the IUU
+
+This driver is still in beta stage, so bugs can
+occur and your system may freeze. As far I now,
+I never had any problem with it, but I'm not a real
+guru, so don't blame me if your system is unstable
+
+You can plug more than one IUU. Every unit will
+have his own device file(/dev/ttyUSB0,/dev/ttyUSB1,...)
+
+
+
+How to tune the reader speed ?
+
+ A few parameters can be used at load time
+ To use parameters, just unload the module if it is
+ already loaded and use modprobe iuu_phoenix param=value.
+ In case of prebuilt module, use the command
+ insmod iuu_phoenix param=value.
+
+ Example:
+
+ modprobe iuu_phoenix clockmode=3
+
+ The parameters are:
+
+ parm:           clockmode:1=3Mhz579,2=3Mhz680,3=6Mhz (int)
+ parm:           boost:overclock boost percent 100 to 500 (int)
+ parm:           cdmode:Card detect mode 0=none, 1=CD, 2=!CD, 3=DSR, 4=!DSR, 5=CTS, 6=!CTS, 7=RING, 8=!RING (int)
+ parm:           xmas:xmas color enabled or not (bool)
+ parm:           debug:Debug enabled or not (bool)
+
+-  clockmode will provide 3 different base settings commonly adopted by
+   different software:
+ 	1. 3Mhz579
+	2. 3Mhz680
+	3. 6Mhz
+
+-  boost provide a way to overclock the reader ( my favorite :-)  )
+   For example to have best performance than a simple clockmode=3, try this:
+
+      modprobe boost=195
+
+   This will put the reader in a base of 3Mhz579 but boosted a 195 % !
+   the real clock will be now : 6979050 Hz ( 6Mhz979 ) and will increase
+   the speed to a score 10 to 20% better than the simple clockmode=3 !!!
+
+
+-  cdmode permit to setup the signal used to inform the userland ( ioctl answer )
+   if the card is present or not. Eight signals are possible.
+
+-  xmas is completely useless except for your eyes. This is one of my friend who was
+   so sad to have a nice device like the iuu without seeing all color range available.
+   So I have added this option to permit him to see a lot of color ( each activity change the color
+   and the frequency randomly )
+
+-  debug will produce a lot of debugging messages...
+
+
+ Last notes:
+
+ Don't worry about the serial settings, the serial emulation
+ is an abstraction, so use any speed or parity setting will
+ work. ( This will not change anything ).Later I will perhaps
+ use this settings to deduce de boost but is that feature
+ really necessary ?
+ The autodetect feature used is the serial CD. If that doesn't
+ work for your software, disable detection mechanism in it.
+
+
+ Have fun !
+
+ Alain Degreffe
+
+ eczema(at)ecze.com
diff --git a/arch/alpha/Kconfig b/arch/alpha/Kconfig
index 4c002ba..c613d5f 100644
--- a/arch/alpha/Kconfig
+++ b/arch/alpha/Kconfig
@@ -318,11 +318,6 @@
 	  your box. Other bus systems are ISA, EISA, MicroChannel (MCA) or
 	  VESA. If you have PCI, say Y, otherwise N.
 
-	  The PCI-HOWTO, available from
-	  <http://www.tldp.org/docs.html#howto>, contains valuable
-	  information about which PCI hardware does work under Linux and which
-	  doesn't.
-
 config PCI_DOMAINS
 	bool
 	default y
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 77201d3..4b1a8e3 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -577,11 +577,6 @@
 	  your box. Other bus systems are ISA, EISA, MicroChannel (MCA) or
 	  VESA. If you have PCI, say Y, otherwise N.
 
-	  The PCI-HOWTO, available from
-	  <http://www.tldp.org/docs.html#howto>, contains valuable
-	  information about which PCI hardware does work under Linux and which
-	  doesn't.
-
 config PCI_SYSCALL
 	def_bool PCI
 
@@ -1035,6 +1030,9 @@
 
 source "kernel/power/Kconfig"
 
+config ARCH_SUSPEND_POSSIBLE
+	def_bool y
+
 endmenu
 
 source "net/Kconfig"
diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c
index 4b120cc..a67defd 100644
--- a/arch/arm/mach-at91/pm.c
+++ b/arch/arm/mach-at91/pm.c
@@ -52,7 +52,7 @@
 /*
  * Called after processes are frozen, but before we shutdown devices.
  */
-static int at91_pm_set_target(suspend_state_t state)
+static int at91_pm_begin(suspend_state_t state)
 {
 	target_state = state;
 	return 0;
@@ -202,11 +202,20 @@
 	return 0;
 }
 
+/*
+ * Called right prior to thawing processes.
+ */
+static void at91_pm_end(void)
+{
+	target_state = PM_SUSPEND_ON;
+}
+
 
 static struct platform_suspend_ops at91_pm_ops ={
-	.valid		= at91_pm_valid_state,
-	.set_target	= at91_pm_set_target,
-	.enter		= at91_pm_enter,
+	.valid	= at91_pm_valid_state,
+	.begin	= at91_pm_begin,
+	.enter	= at91_pm_enter,
+	.end	= at91_pm_end,
 };
 
 static int __init at91_pm_init(void)
diff --git a/arch/arm/mach-pxa/tosa.c b/arch/arm/mach-pxa/tosa.c
index 1919756..1a9c844 100644
--- a/arch/arm/mach-pxa/tosa.c
+++ b/arch/arm/mach-pxa/tosa.c
@@ -157,15 +157,10 @@
 	}
 }
 
-static int tosa_udc_is_connected(void)
-{
-	return ((GPLR(TOSA_GPIO_USB_IN) & GPIO_bit(TOSA_GPIO_USB_IN)) == 0);
-}
-
-
 static struct pxa2xx_udc_mach_info udc_info __initdata = {
 	.udc_command		= tosa_udc_command,
-	.udc_is_connected	= tosa_udc_is_connected,
+	.gpio_vbus		= TOSA_GPIO_USB_IN,
+	.gpio_vbus_inverted	= 1,
 };
 
 /*
diff --git a/arch/blackfin/Kconfig b/arch/blackfin/Kconfig
index fc7ca86..4802eb7 100644
--- a/arch/blackfin/Kconfig
+++ b/arch/blackfin/Kconfig
@@ -898,6 +898,10 @@
 menu "Power management options"
 source "kernel/power/Kconfig"
 
+config ARCH_SUSPEND_POSSIBLE
+	def_bool y
+	depends on !SMP
+
 choice
 	prompt "Select PM Wakeup Event Source"
 	default PM_WAKEUP_GPIO_BY_SIC_IWR
diff --git a/arch/frv/Kconfig b/arch/frv/Kconfig
index 43153e7..e3f965c 100644
--- a/arch/frv/Kconfig
+++ b/arch/frv/Kconfig
@@ -322,11 +322,6 @@
 	  onboard. If you have one of these boards and you wish to use the PCI
 	  facilities, say Y here.
 
-	  The PCI-HOWTO, available from
-	  <http://www.tldp.org/docs.html#howto>, contains valuable
-	  information about which PCI hardware does work under Linux and which
-	  doesn't.
-
 config RESERVE_DMA_COHERENT
 	bool "Reserve DMA coherent memory"
 	depends on PCI && !MMU
@@ -357,6 +352,11 @@
 #	  should probably wait a while.
 
 menu "Power management options"
+
+config ARCH_SUSPEND_POSSIBLE
+	def_bool y
+	depends on !SMP
+
 source kernel/power/Kconfig
 endmenu
 
diff --git a/arch/m32r/Kconfig b/arch/m32r/Kconfig
index f7237c5..49326e9 100644
--- a/arch/m32r/Kconfig
+++ b/arch/m32r/Kconfig
@@ -359,11 +359,6 @@
 	  your box. Other bus systems are ISA, EISA, MicroChannel (MCA) or
 	  VESA. If you have PCI, say Y, otherwise N.
 
-	  The PCI-HOWTO, available from
-	  <http://www.linuxdoc.org/docs.html#howto>, contains valuable
-	  information about which PCI hardware does work under Linux and which
-	  doesn't.
-
 choice
 	prompt "PCI access mode"
 	depends on PCI
diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig
index 01dee84..24e6bc0 100644
--- a/arch/m68k/Kconfig
+++ b/arch/m68k/Kconfig
@@ -145,11 +145,6 @@
 	  your box. Other bus systems are ISA, EISA, MicroChannel (MCA) or
 	  VESA. If you have PCI, say Y, otherwise N.
 
-	  The PCI-HOWTO, available from
-	  <http://www.tldp.org/docs.html#howto>, contains valuable
-	  information about which PCI hardware does work under Linux and which
-	  doesn't.
-
 config MAC
 	bool "Macintosh support"
 	depends on !MMU_SUN3
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 4fad0a3..36a4018 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -1961,11 +1961,6 @@
 	  your box. Other bus systems are ISA, EISA, or VESA. If you have PCI,
 	  say Y, otherwise N.
 
-	  The PCI-HOWTO, available from
-	  <http://www.tldp.org/docs.html#howto>, contains valuable
-	  information about which PCI hardware does work under Linux and which
-	  doesn't.
-
 config PCI_DOMAINS
 	bool
 
@@ -2086,6 +2081,10 @@
 
 menu "Power management options"
 
+config ARCH_SUSPEND_POSSIBLE
+	def_bool y
+	depends on !SMP
+
 source "kernel/power/Kconfig"
 
 endmenu
diff --git a/arch/mips/kernel/head.S b/arch/mips/kernel/head.S
index 50be56c..a24fb79 100644
--- a/arch/mips/kernel/head.S
+++ b/arch/mips/kernel/head.S
@@ -140,7 +140,7 @@
 	j	kernel_entry
 #endif
 
-	__INIT_REFOK
+	__REF
 
 NESTED(kernel_entry, 16, sp)			# kernel entry point
 
diff --git a/arch/mips/mm/Makefile b/arch/mips/mm/Makefile
index 32fd5db..c6f832e 100644
--- a/arch/mips/mm/Makefile
+++ b/arch/mips/mm/Makefile
@@ -3,7 +3,8 @@
 #
 
 obj-y				+= cache.o dma-default.o extable.o fault.o \
-				   init.o pgtable.o tlbex.o tlbex-fault.o
+				   init.o pgtable.o tlbex.o tlbex-fault.o \
+				   uasm.o
 
 obj-$(CONFIG_32BIT)		+= ioremap.o pgtable-32.o
 obj-$(CONFIG_64BIT)		+= pgtable-64.o
diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c
index d026302..218a6cc 100644
--- a/arch/mips/mm/tlbex.c
+++ b/arch/mips/mm/tlbex.c
@@ -5,7 +5,7 @@
  *
  * Synthesize TLB refill handlers at runtime.
  *
- * Copyright (C) 2004,2005,2006 by Thiemo Seufer
+ * Copyright (C) 2004, 2005, 2006, 2008  Thiemo Seufer
  * Copyright (C) 2005, 2007  Maciej W. Rozycki
  * Copyright (C) 2006  Ralf Baechle (ralf@linux-mips.org)
  *
@@ -24,12 +24,11 @@
 #include <linux/string.h>
 #include <linux/init.h>
 
-#include <asm/bugs.h>
 #include <asm/mmu_context.h>
-#include <asm/inst.h>
-#include <asm/elf.h>
 #include <asm/war.h>
 
+#include "uasm.h"
+
 static inline int r45k_bvahwbug(void)
 {
 	/* XXX: We should probe for the presence of this bug, but we don't. */
@@ -67,371 +66,9 @@
 	       (PRID_COMP_MIPS | PRID_IMP_4KC);
 }
 
-/*
- * A little micro-assembler, intended for TLB refill handler
- * synthesizing. It is intentionally kept simple, does only support
- * a subset of instructions, and does not try to hide pipeline effects
- * like branch delay slots.
- */
-
-enum fields
-{
-	RS = 0x001,
-	RT = 0x002,
-	RD = 0x004,
-	RE = 0x008,
-	SIMM = 0x010,
-	UIMM = 0x020,
-	BIMM = 0x040,
-	JIMM = 0x080,
-	FUNC = 0x100,
-	SET = 0x200
-};
-
-#define OP_MASK		0x3f
-#define OP_SH		26
-#define RS_MASK		0x1f
-#define RS_SH		21
-#define RT_MASK		0x1f
-#define RT_SH		16
-#define RD_MASK		0x1f
-#define RD_SH		11
-#define RE_MASK		0x1f
-#define RE_SH		6
-#define IMM_MASK	0xffff
-#define IMM_SH		0
-#define JIMM_MASK	0x3ffffff
-#define JIMM_SH		0
-#define FUNC_MASK	0x3f
-#define FUNC_SH		0
-#define SET_MASK	0x7
-#define SET_SH		0
-
-enum opcode {
-	insn_invalid,
-	insn_addu, insn_addiu, insn_and, insn_andi, insn_beq,
-	insn_beql, insn_bgez, insn_bgezl, insn_bltz, insn_bltzl,
-	insn_bne, insn_daddu, insn_daddiu, insn_dmfc0, insn_dmtc0,
-	insn_dsll, insn_dsll32, insn_dsra, insn_dsrl, insn_dsrl32,
-	insn_dsubu, insn_eret, insn_j, insn_jal, insn_jr, insn_ld,
-	insn_ll, insn_lld, insn_lui, insn_lw, insn_mfc0, insn_mtc0,
-	insn_ori, insn_rfe, insn_sc, insn_scd, insn_sd, insn_sll,
-	insn_sra, insn_srl, insn_subu, insn_sw, insn_tlbp, insn_tlbwi,
-	insn_tlbwr, insn_xor, insn_xori
-};
-
-struct insn {
-	enum opcode opcode;
-	u32 match;
-	enum fields fields;
-};
-
-/* This macro sets the non-variable bits of an instruction. */
-#define M(a, b, c, d, e, f)					\
-	((a) << OP_SH						\
-	 | (b) << RS_SH						\
-	 | (c) << RT_SH						\
-	 | (d) << RD_SH						\
-	 | (e) << RE_SH						\
-	 | (f) << FUNC_SH)
-
-static struct insn insn_table[] __initdata = {
-	{ insn_addiu, M(addiu_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
-	{ insn_addu, M(spec_op, 0, 0, 0, 0, addu_op), RS | RT | RD },
-	{ insn_and, M(spec_op, 0, 0, 0, 0, and_op), RS | RT | RD },
-	{ insn_andi, M(andi_op, 0, 0, 0, 0, 0), RS | RT | UIMM },
-	{ insn_beq, M(beq_op, 0, 0, 0, 0, 0), RS | RT | BIMM },
-	{ insn_beql, M(beql_op, 0, 0, 0, 0, 0), RS | RT | BIMM },
-	{ insn_bgez, M(bcond_op, 0, bgez_op, 0, 0, 0), RS | BIMM },
-	{ insn_bgezl, M(bcond_op, 0, bgezl_op, 0, 0, 0), RS | BIMM },
-	{ insn_bltz, M(bcond_op, 0, bltz_op, 0, 0, 0), RS | BIMM },
-	{ insn_bltzl, M(bcond_op, 0, bltzl_op, 0, 0, 0), RS | BIMM },
-	{ insn_bne, M(bne_op, 0, 0, 0, 0, 0), RS | RT | BIMM },
-	{ insn_daddiu, M(daddiu_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
-	{ insn_daddu, M(spec_op, 0, 0, 0, 0, daddu_op), RS | RT | RD },
-	{ insn_dmfc0, M(cop0_op, dmfc_op, 0, 0, 0, 0), RT | RD | SET},
-	{ insn_dmtc0, M(cop0_op, dmtc_op, 0, 0, 0, 0), RT | RD | SET},
-	{ insn_dsll, M(spec_op, 0, 0, 0, 0, dsll_op), RT | RD | RE },
-	{ insn_dsll32, M(spec_op, 0, 0, 0, 0, dsll32_op), RT | RD | RE },
-	{ insn_dsra, M(spec_op, 0, 0, 0, 0, dsra_op), RT | RD | RE },
-	{ insn_dsrl, M(spec_op, 0, 0, 0, 0, dsrl_op), RT | RD | RE },
-	{ insn_dsrl32, M(spec_op, 0, 0, 0, 0, dsrl32_op), RT | RD | RE },
-	{ insn_dsubu, M(spec_op, 0, 0, 0, 0, dsubu_op), RS | RT | RD },
-	{ insn_eret,  M(cop0_op, cop_op, 0, 0, 0, eret_op),  0 },
-	{ insn_j,  M(j_op, 0, 0, 0, 0, 0),  JIMM },
-	{ insn_jal,  M(jal_op, 0, 0, 0, 0, 0),  JIMM },
-	{ insn_jr,  M(spec_op, 0, 0, 0, 0, jr_op),  RS },
-	{ insn_ld,  M(ld_op, 0, 0, 0, 0, 0),  RS | RT | SIMM },
-	{ insn_ll,  M(ll_op, 0, 0, 0, 0, 0),  RS | RT | SIMM },
-	{ insn_lld,  M(lld_op, 0, 0, 0, 0, 0),  RS | RT | SIMM },
-	{ insn_lui,  M(lui_op, 0, 0, 0, 0, 0),  RT | SIMM },
-	{ insn_lw,  M(lw_op, 0, 0, 0, 0, 0),  RS | RT | SIMM },
-	{ insn_mfc0,  M(cop0_op, mfc_op, 0, 0, 0, 0),  RT | RD | SET},
-	{ insn_mtc0,  M(cop0_op, mtc_op, 0, 0, 0, 0),  RT | RD | SET},
-	{ insn_ori,  M(ori_op, 0, 0, 0, 0, 0),  RS | RT | UIMM },
-	{ insn_rfe,  M(cop0_op, cop_op, 0, 0, 0, rfe_op),  0 },
-	{ insn_sc,  M(sc_op, 0, 0, 0, 0, 0),  RS | RT | SIMM },
-	{ insn_scd,  M(scd_op, 0, 0, 0, 0, 0),  RS | RT | SIMM },
-	{ insn_sd,  M(sd_op, 0, 0, 0, 0, 0),  RS | RT | SIMM },
-	{ insn_sll,  M(spec_op, 0, 0, 0, 0, sll_op),  RT | RD | RE },
-	{ insn_sra,  M(spec_op, 0, 0, 0, 0, sra_op),  RT | RD | RE },
-	{ insn_srl,  M(spec_op, 0, 0, 0, 0, srl_op),  RT | RD | RE },
-	{ insn_subu,  M(spec_op, 0, 0, 0, 0, subu_op),  RS | RT | RD },
-	{ insn_sw,  M(sw_op, 0, 0, 0, 0, 0),  RS | RT | SIMM },
-	{ insn_tlbp,  M(cop0_op, cop_op, 0, 0, 0, tlbp_op),  0 },
-	{ insn_tlbwi,  M(cop0_op, cop_op, 0, 0, 0, tlbwi_op),  0 },
-	{ insn_tlbwr,  M(cop0_op, cop_op, 0, 0, 0, tlbwr_op),  0 },
-	{ insn_xor,  M(spec_op, 0, 0, 0, 0, xor_op),  RS | RT | RD },
-	{ insn_xori,  M(xori_op, 0, 0, 0, 0, 0),  RS | RT | UIMM },
-	{ insn_invalid, 0, 0 }
-};
-
-#undef M
-
-static u32 __init build_rs(u32 arg)
-{
-	if (arg & ~RS_MASK)
-		printk(KERN_WARNING "TLB synthesizer field overflow\n");
-
-	return (arg & RS_MASK) << RS_SH;
-}
-
-static u32 __init build_rt(u32 arg)
-{
-	if (arg & ~RT_MASK)
-		printk(KERN_WARNING "TLB synthesizer field overflow\n");
-
-	return (arg & RT_MASK) << RT_SH;
-}
-
-static u32 __init build_rd(u32 arg)
-{
-	if (arg & ~RD_MASK)
-		printk(KERN_WARNING "TLB synthesizer field overflow\n");
-
-	return (arg & RD_MASK) << RD_SH;
-}
-
-static u32 __init build_re(u32 arg)
-{
-	if (arg & ~RE_MASK)
-		printk(KERN_WARNING "TLB synthesizer field overflow\n");
-
-	return (arg & RE_MASK) << RE_SH;
-}
-
-static u32 __init build_simm(s32 arg)
-{
-	if (arg > 0x7fff || arg < -0x8000)
-		printk(KERN_WARNING "TLB synthesizer field overflow\n");
-
-	return arg & 0xffff;
-}
-
-static u32 __init build_uimm(u32 arg)
-{
-	if (arg & ~IMM_MASK)
-		printk(KERN_WARNING "TLB synthesizer field overflow\n");
-
-	return arg & IMM_MASK;
-}
-
-static u32 __init build_bimm(s32 arg)
-{
-	if (arg > 0x1ffff || arg < -0x20000)
-		printk(KERN_WARNING "TLB synthesizer field overflow\n");
-
-	if (arg & 0x3)
-		printk(KERN_WARNING "Invalid TLB synthesizer branch target\n");
-
-	return ((arg < 0) ? (1 << 15) : 0) | ((arg >> 2) & 0x7fff);
-}
-
-static u32 __init build_jimm(u32 arg)
-{
-	if (arg & ~((JIMM_MASK) << 2))
-		printk(KERN_WARNING "TLB synthesizer field overflow\n");
-
-	return (arg >> 2) & JIMM_MASK;
-}
-
-static u32 __init build_func(u32 arg)
-{
-	if (arg & ~FUNC_MASK)
-		printk(KERN_WARNING "TLB synthesizer field overflow\n");
-
-	return arg & FUNC_MASK;
-}
-
-static u32 __init build_set(u32 arg)
-{
-	if (arg & ~SET_MASK)
-		printk(KERN_WARNING "TLB synthesizer field overflow\n");
-
-	return arg & SET_MASK;
-}
-
-/*
- * The order of opcode arguments is implicitly left to right,
- * starting with RS and ending with FUNC or IMM.
- */
-static void __init build_insn(u32 **buf, enum opcode opc, ...)
-{
-	struct insn *ip = NULL;
-	unsigned int i;
-	va_list ap;
-	u32 op;
-
-	for (i = 0; insn_table[i].opcode != insn_invalid; i++)
-		if (insn_table[i].opcode == opc) {
-			ip = &insn_table[i];
-			break;
-		}
-
-	if (!ip || (opc == insn_daddiu && r4k_daddiu_bug()))
-		panic("Unsupported TLB synthesizer instruction %d", opc);
-
-	op = ip->match;
-	va_start(ap, opc);
-	if (ip->fields & RS) op |= build_rs(va_arg(ap, u32));
-	if (ip->fields & RT) op |= build_rt(va_arg(ap, u32));
-	if (ip->fields & RD) op |= build_rd(va_arg(ap, u32));
-	if (ip->fields & RE) op |= build_re(va_arg(ap, u32));
-	if (ip->fields & SIMM) op |= build_simm(va_arg(ap, s32));
-	if (ip->fields & UIMM) op |= build_uimm(va_arg(ap, u32));
-	if (ip->fields & BIMM) op |= build_bimm(va_arg(ap, s32));
-	if (ip->fields & JIMM) op |= build_jimm(va_arg(ap, u32));
-	if (ip->fields & FUNC) op |= build_func(va_arg(ap, u32));
-	if (ip->fields & SET) op |= build_set(va_arg(ap, u32));
-	va_end(ap);
-
-	**buf = op;
-	(*buf)++;
-}
-
-#define I_u1u2u3(op)						\
-	static void __init __maybe_unused i##op(u32 **buf, unsigned int a, \
-	 	unsigned int b, unsigned int c)			\
-	{							\
-		build_insn(buf, insn##op, a, b, c);		\
-	}
-
-#define I_u2u1u3(op)						\
-	static void __init __maybe_unused i##op(u32 **buf, unsigned int a, \
-	 	unsigned int b, unsigned int c)			\
-	{							\
-		build_insn(buf, insn##op, b, a, c);		\
-	}
-
-#define I_u3u1u2(op)						\
-	static void __init __maybe_unused i##op(u32 **buf, unsigned int a, \
-	 	unsigned int b, unsigned int c)			\
-	{							\
-		build_insn(buf, insn##op, b, c, a);		\
-	}
-
-#define I_u1u2s3(op)						\
-	static void __init __maybe_unused i##op(u32 **buf, unsigned int a, \
-	 	unsigned int b, signed int c)			\
-	{							\
-		build_insn(buf, insn##op, a, b, c);		\
-	}
-
-#define I_u2s3u1(op)						\
-	static void __init __maybe_unused i##op(u32 **buf, unsigned int a, \
-	 	signed int b, unsigned int c)			\
-	{							\
-		build_insn(buf, insn##op, c, a, b);		\
-	}
-
-#define I_u2u1s3(op)						\
-	static void __init __maybe_unused i##op(u32 **buf, unsigned int a, \
-	 	unsigned int b, signed int c)			\
-	{							\
-		build_insn(buf, insn##op, b, a, c);		\
-	}
-
-#define I_u1u2(op)						\
-	static void __init __maybe_unused i##op(u32 **buf, unsigned int a, \
-	 	unsigned int b)					\
-	{							\
-		build_insn(buf, insn##op, a, b);		\
-	}
-
-#define I_u1s2(op)						\
-	static void __init __maybe_unused i##op(u32 **buf, unsigned int a, \
-	 	signed int b)					\
-	{							\
-		build_insn(buf, insn##op, a, b);		\
-	}
-
-#define I_u1(op)						\
-	static void __init __maybe_unused i##op(u32 **buf, unsigned int a) \
-	{							\
-		build_insn(buf, insn##op, a);			\
-	}
-
-#define I_0(op)							\
-	static void __init __maybe_unused i##op(u32 **buf)	\
-	{							\
-		build_insn(buf, insn##op);			\
-	}
-
-I_u2u1s3(_addiu);
-I_u3u1u2(_addu);
-I_u2u1u3(_andi);
-I_u3u1u2(_and);
-I_u1u2s3(_beq);
-I_u1u2s3(_beql);
-I_u1s2(_bgez);
-I_u1s2(_bgezl);
-I_u1s2(_bltz);
-I_u1s2(_bltzl);
-I_u1u2s3(_bne);
-I_u1u2u3(_dmfc0);
-I_u1u2u3(_dmtc0);
-I_u2u1s3(_daddiu);
-I_u3u1u2(_daddu);
-I_u2u1u3(_dsll);
-I_u2u1u3(_dsll32);
-I_u2u1u3(_dsra);
-I_u2u1u3(_dsrl);
-I_u2u1u3(_dsrl32);
-I_u3u1u2(_dsubu);
-I_0(_eret);
-I_u1(_j);
-I_u1(_jal);
-I_u1(_jr);
-I_u2s3u1(_ld);
-I_u2s3u1(_ll);
-I_u2s3u1(_lld);
-I_u1s2(_lui);
-I_u2s3u1(_lw);
-I_u1u2u3(_mfc0);
-I_u1u2u3(_mtc0);
-I_u2u1u3(_ori);
-I_0(_rfe);
-I_u2s3u1(_sc);
-I_u2s3u1(_scd);
-I_u2s3u1(_sd);
-I_u2u1u3(_sll);
-I_u2u1u3(_sra);
-I_u2u1u3(_srl);
-I_u3u1u2(_subu);
-I_u2s3u1(_sw);
-I_0(_tlbp);
-I_0(_tlbwi);
-I_0(_tlbwr);
-I_u3u1u2(_xor)
-I_u2u1u3(_xori);
-
-/*
- * handling labels
- */
-
+/* Handle labels (which must be positive integers). */
 enum label_id {
-	label_invalid,
-	label_second_part,
+	label_second_part = 1,
 	label_leave,
 #ifdef MODULE_START
 	label_module_alloc,
@@ -447,278 +84,20 @@
 	label_r3000_write_probe_fail,
 };
 
-struct label {
-	u32 *addr;
-	enum label_id lab;
-};
-
-static void __init build_label(struct label **lab, u32 *addr,
-			       enum label_id l)
-{
-	(*lab)->addr = addr;
-	(*lab)->lab = l;
-	(*lab)++;
-}
-
-#define L_LA(lb)						\
-	static inline void __init l##lb(struct label **lab, u32 *addr) \
-	{							\
-		build_label(lab, addr, label##lb);		\
-	}
-
-L_LA(_second_part)
-L_LA(_leave)
+UASM_L_LA(_second_part)
+UASM_L_LA(_leave)
 #ifdef MODULE_START
-L_LA(_module_alloc)
+UASM_L_LA(_module_alloc)
 #endif
-L_LA(_vmalloc)
-L_LA(_vmalloc_done)
-L_LA(_tlbw_hazard)
-L_LA(_split)
-L_LA(_nopage_tlbl)
-L_LA(_nopage_tlbs)
-L_LA(_nopage_tlbm)
-L_LA(_smp_pgtable_change)
-L_LA(_r3000_write_probe_fail)
-
-/* convenience macros for instructions */
-#ifdef CONFIG_64BIT
-# define i_LW(buf, rs, rt, off) i_ld(buf, rs, rt, off)
-# define i_SW(buf, rs, rt, off) i_sd(buf, rs, rt, off)
-# define i_SLL(buf, rs, rt, sh) i_dsll(buf, rs, rt, sh)
-# define i_SRA(buf, rs, rt, sh) i_dsra(buf, rs, rt, sh)
-# define i_SRL(buf, rs, rt, sh) i_dsrl(buf, rs, rt, sh)
-# define i_MFC0(buf, rt, rd...) i_dmfc0(buf, rt, rd)
-# define i_MTC0(buf, rt, rd...) i_dmtc0(buf, rt, rd)
-# define i_ADDIU(buf, rs, rt, val) i_daddiu(buf, rs, rt, val)
-# define i_ADDU(buf, rs, rt, rd) i_daddu(buf, rs, rt, rd)
-# define i_SUBU(buf, rs, rt, rd) i_dsubu(buf, rs, rt, rd)
-# define i_LL(buf, rs, rt, off) i_lld(buf, rs, rt, off)
-# define i_SC(buf, rs, rt, off) i_scd(buf, rs, rt, off)
-#else
-# define i_LW(buf, rs, rt, off) i_lw(buf, rs, rt, off)
-# define i_SW(buf, rs, rt, off) i_sw(buf, rs, rt, off)
-# define i_SLL(buf, rs, rt, sh) i_sll(buf, rs, rt, sh)
-# define i_SRA(buf, rs, rt, sh) i_sra(buf, rs, rt, sh)
-# define i_SRL(buf, rs, rt, sh) i_srl(buf, rs, rt, sh)
-# define i_MFC0(buf, rt, rd...) i_mfc0(buf, rt, rd)
-# define i_MTC0(buf, rt, rd...) i_mtc0(buf, rt, rd)
-# define i_ADDIU(buf, rs, rt, val) i_addiu(buf, rs, rt, val)
-# define i_ADDU(buf, rs, rt, rd) i_addu(buf, rs, rt, rd)
-# define i_SUBU(buf, rs, rt, rd) i_subu(buf, rs, rt, rd)
-# define i_LL(buf, rs, rt, off) i_ll(buf, rs, rt, off)
-# define i_SC(buf, rs, rt, off) i_sc(buf, rs, rt, off)
-#endif
-
-#define i_b(buf, off) i_beq(buf, 0, 0, off)
-#define i_beqz(buf, rs, off) i_beq(buf, rs, 0, off)
-#define i_beqzl(buf, rs, off) i_beql(buf, rs, 0, off)
-#define i_bnez(buf, rs, off) i_bne(buf, rs, 0, off)
-#define i_bnezl(buf, rs, off) i_bnel(buf, rs, 0, off)
-#define i_move(buf, a, b) i_ADDU(buf, a, 0, b)
-#define i_nop(buf) i_sll(buf, 0, 0, 0)
-#define i_ssnop(buf) i_sll(buf, 0, 0, 1)
-#define i_ehb(buf) i_sll(buf, 0, 0, 3)
-
-static int __init __maybe_unused in_compat_space_p(long addr)
-{
-	/* Is this address in 32bit compat space? */
-#ifdef CONFIG_64BIT
-	return (((addr) & 0xffffffff00000000L) == 0xffffffff00000000L);
-#else
-	return 1;
-#endif
-}
-
-static int __init __maybe_unused rel_highest(long val)
-{
-#ifdef CONFIG_64BIT
-	return ((((val + 0x800080008000L) >> 48) & 0xffff) ^ 0x8000) - 0x8000;
-#else
-	return 0;
-#endif
-}
-
-static int __init __maybe_unused rel_higher(long val)
-{
-#ifdef CONFIG_64BIT
-	return ((((val + 0x80008000L) >> 32) & 0xffff) ^ 0x8000) - 0x8000;
-#else
-	return 0;
-#endif
-}
-
-static int __init rel_hi(long val)
-{
-	return ((((val + 0x8000L) >> 16) & 0xffff) ^ 0x8000) - 0x8000;
-}
-
-static int __init rel_lo(long val)
-{
-	return ((val & 0xffff) ^ 0x8000) - 0x8000;
-}
-
-static void __init i_LA_mostly(u32 **buf, unsigned int rs, long addr)
-{
-	if (!in_compat_space_p(addr)) {
-		i_lui(buf, rs, rel_highest(addr));
-		if (rel_higher(addr))
-			i_daddiu(buf, rs, rs, rel_higher(addr));
-		if (rel_hi(addr)) {
-			i_dsll(buf, rs, rs, 16);
-			i_daddiu(buf, rs, rs, rel_hi(addr));
-			i_dsll(buf, rs, rs, 16);
-		} else
-			i_dsll32(buf, rs, rs, 0);
-	} else
-		i_lui(buf, rs, rel_hi(addr));
-}
-
-static void __init __maybe_unused i_LA(u32 **buf, unsigned int rs, long addr)
-{
-	i_LA_mostly(buf, rs, addr);
-	if (rel_lo(addr)) {
-		if (!in_compat_space_p(addr))
-			i_daddiu(buf, rs, rs, rel_lo(addr));
-		else
-			i_addiu(buf, rs, rs, rel_lo(addr));
-	}
-}
-
-/*
- * handle relocations
- */
-
-struct reloc {
-	u32 *addr;
-	unsigned int type;
-	enum label_id lab;
-};
-
-static void __init r_mips_pc16(struct reloc **rel, u32 *addr,
-			       enum label_id l)
-{
-	(*rel)->addr = addr;
-	(*rel)->type = R_MIPS_PC16;
-	(*rel)->lab = l;
-	(*rel)++;
-}
-
-static inline void __resolve_relocs(struct reloc *rel, struct label *lab)
-{
-	long laddr = (long)lab->addr;
-	long raddr = (long)rel->addr;
-
-	switch (rel->type) {
-	case R_MIPS_PC16:
-		*rel->addr |= build_bimm(laddr - (raddr + 4));
-		break;
-
-	default:
-		panic("Unsupported TLB synthesizer relocation %d",
-		      rel->type);
-	}
-}
-
-static void __init resolve_relocs(struct reloc *rel, struct label *lab)
-{
-	struct label *l;
-
-	for (; rel->lab != label_invalid; rel++)
-		for (l = lab; l->lab != label_invalid; l++)
-			if (rel->lab == l->lab)
-				__resolve_relocs(rel, l);
-}
-
-static void __init move_relocs(struct reloc *rel, u32 *first, u32 *end,
-			       long off)
-{
-	for (; rel->lab != label_invalid; rel++)
-		if (rel->addr >= first && rel->addr < end)
-			rel->addr += off;
-}
-
-static void __init move_labels(struct label *lab, u32 *first, u32 *end,
-			       long off)
-{
-	for (; lab->lab != label_invalid; lab++)
-		if (lab->addr >= first && lab->addr < end)
-			lab->addr += off;
-}
-
-static void __init copy_handler(struct reloc *rel, struct label *lab,
-				u32 *first, u32 *end, u32 *target)
-{
-	long off = (long)(target - first);
-
-	memcpy(target, first, (end - first) * sizeof(u32));
-
-	move_relocs(rel, first, end, off);
-	move_labels(lab, first, end, off);
-}
-
-static int __init __maybe_unused insn_has_bdelay(struct reloc *rel,
-						       u32 *addr)
-{
-	for (; rel->lab != label_invalid; rel++) {
-		if (rel->addr == addr
-		    && (rel->type == R_MIPS_PC16
-			|| rel->type == R_MIPS_26))
-			return 1;
-	}
-
-	return 0;
-}
-
-/* convenience functions for labeled branches */
-static void __init __maybe_unused
-	il_bltz(u32 **p, struct reloc **r, unsigned int reg, enum label_id l)
-{
-	r_mips_pc16(r, *p, l);
-	i_bltz(p, reg, 0);
-}
-
-static void __init __maybe_unused il_b(u32 **p, struct reloc **r,
-					     enum label_id l)
-{
-	r_mips_pc16(r, *p, l);
-	i_b(p, 0);
-}
-
-static void __init il_beqz(u32 **p, struct reloc **r, unsigned int reg,
-		    enum label_id l)
-{
-	r_mips_pc16(r, *p, l);
-	i_beqz(p, reg, 0);
-}
-
-static void __init __maybe_unused
-il_beqzl(u32 **p, struct reloc **r, unsigned int reg, enum label_id l)
-{
-	r_mips_pc16(r, *p, l);
-	i_beqzl(p, reg, 0);
-}
-
-static void __init il_bnez(u32 **p, struct reloc **r, unsigned int reg,
-		    enum label_id l)
-{
-	r_mips_pc16(r, *p, l);
-	i_bnez(p, reg, 0);
-}
-
-static void __init il_bgezl(u32 **p, struct reloc **r, unsigned int reg,
-		     enum label_id l)
-{
-	r_mips_pc16(r, *p, l);
-	i_bgezl(p, reg, 0);
-}
-
-static void __init __maybe_unused
-il_bgez(u32 **p, struct reloc **r, unsigned int reg, enum label_id l)
-{
-	r_mips_pc16(r, *p, l);
-	i_bgez(p, reg, 0);
-}
+UASM_L_LA(_vmalloc)
+UASM_L_LA(_vmalloc_done)
+UASM_L_LA(_tlbw_hazard)
+UASM_L_LA(_split)
+UASM_L_LA(_nopage_tlbl)
+UASM_L_LA(_nopage_tlbs)
+UASM_L_LA(_nopage_tlbm)
+UASM_L_LA(_smp_pgtable_change)
+UASM_L_LA(_r3000_write_probe_fail)
 
 /*
  * For debug purposes.
@@ -752,9 +131,9 @@
 #define C0_XCONTEXT	20, 0
 
 #ifdef CONFIG_64BIT
-# define GET_CONTEXT(buf, reg) i_MFC0(buf, reg, C0_XCONTEXT)
+# define GET_CONTEXT(buf, reg) UASM_i_MFC0(buf, reg, C0_XCONTEXT)
 #else
-# define GET_CONTEXT(buf, reg) i_MFC0(buf, reg, C0_CONTEXT)
+# define GET_CONTEXT(buf, reg) UASM_i_MFC0(buf, reg, C0_CONTEXT)
 #endif
 
 /* The worst case length of the handler is around 18 instructions for
@@ -768,8 +147,8 @@
 static u32 tlb_handler[128] __initdata;
 
 /* simply assume worst case size for labels and relocs */
-static struct label labels[128] __initdata;
-static struct reloc relocs[128] __initdata;
+static struct uasm_label labels[128] __initdata;
+static struct uasm_reloc relocs[128] __initdata;
 
 /*
  * The R3000 TLB handler is simple.
@@ -782,29 +161,29 @@
 	memset(tlb_handler, 0, sizeof(tlb_handler));
 	p = tlb_handler;
 
-	i_mfc0(&p, K0, C0_BADVADDR);
-	i_lui(&p, K1, rel_hi(pgdc)); /* cp0 delay */
-	i_lw(&p, K1, rel_lo(pgdc), K1);
-	i_srl(&p, K0, K0, 22); /* load delay */
-	i_sll(&p, K0, K0, 2);
-	i_addu(&p, K1, K1, K0);
-	i_mfc0(&p, K0, C0_CONTEXT);
-	i_lw(&p, K1, 0, K1); /* cp0 delay */
-	i_andi(&p, K0, K0, 0xffc); /* load delay */
-	i_addu(&p, K1, K1, K0);
-	i_lw(&p, K0, 0, K1);
-	i_nop(&p); /* load delay */
-	i_mtc0(&p, K0, C0_ENTRYLO0);
-	i_mfc0(&p, K1, C0_EPC); /* cp0 delay */
-	i_tlbwr(&p); /* cp0 delay */
-	i_jr(&p, K1);
-	i_rfe(&p); /* branch delay */
+	uasm_i_mfc0(&p, K0, C0_BADVADDR);
+	uasm_i_lui(&p, K1, uasm_rel_hi(pgdc)); /* cp0 delay */
+	uasm_i_lw(&p, K1, uasm_rel_lo(pgdc), K1);
+	uasm_i_srl(&p, K0, K0, 22); /* load delay */
+	uasm_i_sll(&p, K0, K0, 2);
+	uasm_i_addu(&p, K1, K1, K0);
+	uasm_i_mfc0(&p, K0, C0_CONTEXT);
+	uasm_i_lw(&p, K1, 0, K1); /* cp0 delay */
+	uasm_i_andi(&p, K0, K0, 0xffc); /* load delay */
+	uasm_i_addu(&p, K1, K1, K0);
+	uasm_i_lw(&p, K0, 0, K1);
+	uasm_i_nop(&p); /* load delay */
+	uasm_i_mtc0(&p, K0, C0_ENTRYLO0);
+	uasm_i_mfc0(&p, K1, C0_EPC); /* cp0 delay */
+	uasm_i_tlbwr(&p); /* cp0 delay */
+	uasm_i_jr(&p, K1);
+	uasm_i_rfe(&p); /* branch delay */
 
 	if (p > tlb_handler + 32)
 		panic("TLB refill handler space exceeded");
 
-	pr_info("Synthesized TLB refill handler (%u instructions).\n",
-		(unsigned int)(p - tlb_handler));
+	pr_debug("Wrote TLB refill handler (%u instructions).\n",
+		 (unsigned int)(p - tlb_handler));
 
 	memcpy((void *)ebase, tlb_handler, 0x80);
 
@@ -850,12 +229,12 @@
 	case CPU_R5000:
 	case CPU_R5000A:
 	case CPU_NEVADA:
-		i_nop(p);
-		i_tlbp(p);
+		uasm_i_nop(p);
+		uasm_i_tlbp(p);
 		break;
 
 	default:
-		i_tlbp(p);
+		uasm_i_tlbp(p);
 		break;
 	}
 }
@@ -866,19 +245,19 @@
  */
 enum tlb_write_entry { tlb_random, tlb_indexed };
 
-static void __init build_tlb_write_entry(u32 **p, struct label **l,
-					 struct reloc **r,
+static void __init build_tlb_write_entry(u32 **p, struct uasm_label **l,
+					 struct uasm_reloc **r,
 					 enum tlb_write_entry wmode)
 {
 	void(*tlbw)(u32 **) = NULL;
 
 	switch (wmode) {
-	case tlb_random: tlbw = i_tlbwr; break;
-	case tlb_indexed: tlbw = i_tlbwi; break;
+	case tlb_random: tlbw = uasm_i_tlbwr; break;
+	case tlb_indexed: tlbw = uasm_i_tlbwi; break;
 	}
 
 	if (cpu_has_mips_r2) {
-		i_ehb(p);
+		uasm_i_ehb(p);
 		tlbw(p);
 		return;
 	}
@@ -894,19 +273,19 @@
 		 * This branch uses up a mtc0 hazard nop slot and saves
 		 * two nops after the tlbw instruction.
 		 */
-		il_bgezl(p, r, 0, label_tlbw_hazard);
+		uasm_il_bgezl(p, r, 0, label_tlbw_hazard);
 		tlbw(p);
-		l_tlbw_hazard(l, *p);
-		i_nop(p);
+		uasm_l_tlbw_hazard(l, *p);
+		uasm_i_nop(p);
 		break;
 
 	case CPU_R4600:
 	case CPU_R4700:
 	case CPU_R5000:
 	case CPU_R5000A:
-		i_nop(p);
+		uasm_i_nop(p);
 		tlbw(p);
-		i_nop(p);
+		uasm_i_nop(p);
 		break;
 
 	case CPU_R4300:
@@ -920,7 +299,7 @@
 	case CPU_AU1210:
 	case CPU_AU1250:
 	case CPU_PR4450:
-		i_nop(p);
+		uasm_i_nop(p);
 		tlbw(p);
 		break;
 
@@ -937,26 +316,26 @@
 	case CPU_BCM4710:
 	case CPU_LOONGSON2:
 		if (m4kc_tlbp_war())
-			i_nop(p);
+			uasm_i_nop(p);
 		tlbw(p);
 		break;
 
 	case CPU_NEVADA:
-		i_nop(p); /* QED specifies 2 nops hazard */
+		uasm_i_nop(p); /* QED specifies 2 nops hazard */
 		/*
 		 * This branch uses up a mtc0 hazard nop slot and saves
 		 * a nop after the tlbw instruction.
 		 */
-		il_bgezl(p, r, 0, label_tlbw_hazard);
+		uasm_il_bgezl(p, r, 0, label_tlbw_hazard);
 		tlbw(p);
-		l_tlbw_hazard(l, *p);
+		uasm_l_tlbw_hazard(l, *p);
 		break;
 
 	case CPU_RM7000:
-		i_nop(p);
-		i_nop(p);
-		i_nop(p);
-		i_nop(p);
+		uasm_i_nop(p);
+		uasm_i_nop(p);
+		uasm_i_nop(p);
+		uasm_i_nop(p);
 		tlbw(p);
 		break;
 
@@ -967,15 +346,15 @@
 		 * cpu cycles and use for data translations should not occur
 		 * for 3 cpu cycles.
 		 */
-		i_ssnop(p);
-		i_ssnop(p);
-		i_ssnop(p);
-		i_ssnop(p);
+		uasm_i_ssnop(p);
+		uasm_i_ssnop(p);
+		uasm_i_ssnop(p);
+		uasm_i_ssnop(p);
 		tlbw(p);
-		i_ssnop(p);
-		i_ssnop(p);
-		i_ssnop(p);
-		i_ssnop(p);
+		uasm_i_ssnop(p);
+		uasm_i_ssnop(p);
+		uasm_i_ssnop(p);
+		uasm_i_ssnop(p);
 		break;
 
 	case CPU_VR4111:
@@ -983,18 +362,18 @@
 	case CPU_VR4122:
 	case CPU_VR4181:
 	case CPU_VR4181A:
-		i_nop(p);
-		i_nop(p);
+		uasm_i_nop(p);
+		uasm_i_nop(p);
 		tlbw(p);
-		i_nop(p);
-		i_nop(p);
+		uasm_i_nop(p);
+		uasm_i_nop(p);
 		break;
 
 	case CPU_VR4131:
 	case CPU_VR4133:
 	case CPU_R5432:
-		i_nop(p);
-		i_nop(p);
+		uasm_i_nop(p);
+		uasm_i_nop(p);
 		tlbw(p);
 		break;
 
@@ -1011,7 +390,7 @@
  * TMP will be clobbered, PTR will hold the pmd entry.
  */
 static void __init
-build_get_pmde64(u32 **p, struct label **l, struct reloc **r,
+build_get_pmde64(u32 **p, struct uasm_label **l, struct uasm_reloc **r,
 		 unsigned int tmp, unsigned int ptr)
 {
 	long pgdc = (long)pgd_current;
@@ -1019,52 +398,52 @@
 	/*
 	 * The vmalloc handling is not in the hotpath.
 	 */
-	i_dmfc0(p, tmp, C0_BADVADDR);
+	uasm_i_dmfc0(p, tmp, C0_BADVADDR);
 #ifdef MODULE_START
-	il_bltz(p, r, tmp, label_module_alloc);
+	uasm_il_bltz(p, r, tmp, label_module_alloc);
 #else
-	il_bltz(p, r, tmp, label_vmalloc);
+	uasm_il_bltz(p, r, tmp, label_vmalloc);
 #endif
-	/* No i_nop needed here, since the next insn doesn't touch TMP. */
+	/* No uasm_i_nop needed here, since the next insn doesn't touch TMP. */
 
 #ifdef CONFIG_SMP
 # ifdef  CONFIG_MIPS_MT_SMTC
 	/*
 	 * SMTC uses TCBind value as "CPU" index
 	 */
-	i_mfc0(p, ptr, C0_TCBIND);
-	i_dsrl(p, ptr, ptr, 19);
+	uasm_i_mfc0(p, ptr, C0_TCBIND);
+	uasm_i_dsrl(p, ptr, ptr, 19);
 # else
 	/*
 	 * 64 bit SMP running in XKPHYS has smp_processor_id() << 3
 	 * stored in CONTEXT.
 	 */
-	i_dmfc0(p, ptr, C0_CONTEXT);
-	i_dsrl(p, ptr, ptr, 23);
+	uasm_i_dmfc0(p, ptr, C0_CONTEXT);
+	uasm_i_dsrl(p, ptr, ptr, 23);
 #endif
-	i_LA_mostly(p, tmp, pgdc);
-	i_daddu(p, ptr, ptr, tmp);
-	i_dmfc0(p, tmp, C0_BADVADDR);
-	i_ld(p, ptr, rel_lo(pgdc), ptr);
+	UASM_i_LA_mostly(p, tmp, pgdc);
+	uasm_i_daddu(p, ptr, ptr, tmp);
+	uasm_i_dmfc0(p, tmp, C0_BADVADDR);
+	uasm_i_ld(p, ptr, uasm_rel_lo(pgdc), ptr);
 #else
-	i_LA_mostly(p, ptr, pgdc);
-	i_ld(p, ptr, rel_lo(pgdc), ptr);
+	UASM_i_LA_mostly(p, ptr, pgdc);
+	uasm_i_ld(p, ptr, uasm_rel_lo(pgdc), ptr);
 #endif
 
-	l_vmalloc_done(l, *p);
+	uasm_l_vmalloc_done(l, *p);
 
 	if (PGDIR_SHIFT - 3 < 32)		/* get pgd offset in bytes */
-		i_dsrl(p, tmp, tmp, PGDIR_SHIFT-3);
+		uasm_i_dsrl(p, tmp, tmp, PGDIR_SHIFT-3);
 	else
-		i_dsrl32(p, tmp, tmp, PGDIR_SHIFT - 3 - 32);
+		uasm_i_dsrl32(p, tmp, tmp, PGDIR_SHIFT - 3 - 32);
 
-	i_andi(p, tmp, tmp, (PTRS_PER_PGD - 1)<<3);
-	i_daddu(p, ptr, ptr, tmp); /* add in pgd offset */
-	i_dmfc0(p, tmp, C0_BADVADDR); /* get faulting address */
-	i_ld(p, ptr, 0, ptr); /* get pmd pointer */
-	i_dsrl(p, tmp, tmp, PMD_SHIFT-3); /* get pmd offset in bytes */
-	i_andi(p, tmp, tmp, (PTRS_PER_PMD - 1)<<3);
-	i_daddu(p, ptr, ptr, tmp); /* add in pmd offset */
+	uasm_i_andi(p, tmp, tmp, (PTRS_PER_PGD - 1)<<3);
+	uasm_i_daddu(p, ptr, ptr, tmp); /* add in pgd offset */
+	uasm_i_dmfc0(p, tmp, C0_BADVADDR); /* get faulting address */
+	uasm_i_ld(p, ptr, 0, ptr); /* get pmd pointer */
+	uasm_i_dsrl(p, tmp, tmp, PMD_SHIFT-3); /* get pmd offset in bytes */
+	uasm_i_andi(p, tmp, tmp, (PTRS_PER_PMD - 1)<<3);
+	uasm_i_daddu(p, ptr, ptr, tmp); /* add in pmd offset */
 }
 
 /*
@@ -1072,7 +451,7 @@
  * PTR will hold the pgd for vmalloc.
  */
 static void __init
-build_get_pgd_vmalloc64(u32 **p, struct label **l, struct reloc **r,
+build_get_pgd_vmalloc64(u32 **p, struct uasm_label **l, struct uasm_reloc **r,
 			unsigned int bvaddr, unsigned int ptr)
 {
 	long swpd = (long)swapper_pg_dir;
@@ -1080,58 +459,60 @@
 #ifdef MODULE_START
 	long modd = (long)module_pg_dir;
 
-	l_module_alloc(l, *p);
+	uasm_l_module_alloc(l, *p);
 	/*
 	 * Assumption:
 	 * VMALLOC_START >= 0xc000000000000000UL
 	 * MODULE_START >= 0xe000000000000000UL
 	 */
-	i_SLL(p, ptr, bvaddr, 2);
-	il_bgez(p, r, ptr, label_vmalloc);
+	UASM_i_SLL(p, ptr, bvaddr, 2);
+	uasm_il_bgez(p, r, ptr, label_vmalloc);
 
-	if (in_compat_space_p(MODULE_START) && !rel_lo(MODULE_START)) {
-		i_lui(p, ptr, rel_hi(MODULE_START)); /* delay slot */
+	if (uasm_in_compat_space_p(MODULE_START) &&
+	    !uasm_rel_lo(MODULE_START)) {
+		uasm_i_lui(p, ptr, uasm_rel_hi(MODULE_START)); /* delay slot */
 	} else {
 		/* unlikely configuration */
-		i_nop(p); /* delay slot */
-		i_LA(p, ptr, MODULE_START);
+		uasm_i_nop(p); /* delay slot */
+		UASM_i_LA(p, ptr, MODULE_START);
 	}
-	i_dsubu(p, bvaddr, bvaddr, ptr);
+	uasm_i_dsubu(p, bvaddr, bvaddr, ptr);
 
-	if (in_compat_space_p(modd) && !rel_lo(modd)) {
-		il_b(p, r, label_vmalloc_done);
-		i_lui(p, ptr, rel_hi(modd));
+	if (uasm_in_compat_space_p(modd) && !uasm_rel_lo(modd)) {
+		uasm_il_b(p, r, label_vmalloc_done);
+		uasm_i_lui(p, ptr, uasm_rel_hi(modd));
 	} else {
-		i_LA_mostly(p, ptr, modd);
-		il_b(p, r, label_vmalloc_done);
-		if (in_compat_space_p(modd))
-			i_addiu(p, ptr, ptr, rel_lo(modd));
+		UASM_i_LA_mostly(p, ptr, modd);
+		uasm_il_b(p, r, label_vmalloc_done);
+		if (uasm_in_compat_space_p(modd))
+			uasm_i_addiu(p, ptr, ptr, uasm_rel_lo(modd));
 		else
-			i_daddiu(p, ptr, ptr, rel_lo(modd));
+			uasm_i_daddiu(p, ptr, ptr, uasm_rel_lo(modd));
 	}
 
-	l_vmalloc(l, *p);
-	if (in_compat_space_p(MODULE_START) && !rel_lo(MODULE_START) &&
+	uasm_l_vmalloc(l, *p);
+	if (uasm_in_compat_space_p(MODULE_START) &&
+	    !uasm_rel_lo(MODULE_START) &&
 	    MODULE_START << 32 == VMALLOC_START)
-		i_dsll32(p, ptr, ptr, 0);	/* typical case */
+		uasm_i_dsll32(p, ptr, ptr, 0);	/* typical case */
 	else
-		i_LA(p, ptr, VMALLOC_START);
+		UASM_i_LA(p, ptr, VMALLOC_START);
 #else
-	l_vmalloc(l, *p);
-	i_LA(p, ptr, VMALLOC_START);
+	uasm_l_vmalloc(l, *p);
+	UASM_i_LA(p, ptr, VMALLOC_START);
 #endif
-	i_dsubu(p, bvaddr, bvaddr, ptr);
+	uasm_i_dsubu(p, bvaddr, bvaddr, ptr);
 
-	if (in_compat_space_p(swpd) && !rel_lo(swpd)) {
-		il_b(p, r, label_vmalloc_done);
-		i_lui(p, ptr, rel_hi(swpd));
+	if (uasm_in_compat_space_p(swpd) && !uasm_rel_lo(swpd)) {
+		uasm_il_b(p, r, label_vmalloc_done);
+		uasm_i_lui(p, ptr, uasm_rel_hi(swpd));
 	} else {
-		i_LA_mostly(p, ptr, swpd);
-		il_b(p, r, label_vmalloc_done);
-		if (in_compat_space_p(swpd))
-			i_addiu(p, ptr, ptr, rel_lo(swpd));
+		UASM_i_LA_mostly(p, ptr, swpd);
+		uasm_il_b(p, r, label_vmalloc_done);
+		if (uasm_in_compat_space_p(swpd))
+			uasm_i_addiu(p, ptr, ptr, uasm_rel_lo(swpd));
 		else
-			i_daddiu(p, ptr, ptr, rel_lo(swpd));
+			uasm_i_daddiu(p, ptr, ptr, uasm_rel_lo(swpd));
 	}
 }
 
@@ -1152,26 +533,26 @@
 	/*
 	 * SMTC uses TCBind value as "CPU" index
 	 */
-	i_mfc0(p, ptr, C0_TCBIND);
-	i_LA_mostly(p, tmp, pgdc);
-	i_srl(p, ptr, ptr, 19);
+	uasm_i_mfc0(p, ptr, C0_TCBIND);
+	UASM_i_LA_mostly(p, tmp, pgdc);
+	uasm_i_srl(p, ptr, ptr, 19);
 #else
 	/*
 	 * smp_processor_id() << 3 is stored in CONTEXT.
          */
-	i_mfc0(p, ptr, C0_CONTEXT);
-	i_LA_mostly(p, tmp, pgdc);
-	i_srl(p, ptr, ptr, 23);
+	uasm_i_mfc0(p, ptr, C0_CONTEXT);
+	UASM_i_LA_mostly(p, tmp, pgdc);
+	uasm_i_srl(p, ptr, ptr, 23);
 #endif
-	i_addu(p, ptr, tmp, ptr);
+	uasm_i_addu(p, ptr, tmp, ptr);
 #else
-	i_LA_mostly(p, ptr, pgdc);
+	UASM_i_LA_mostly(p, ptr, pgdc);
 #endif
-	i_mfc0(p, tmp, C0_BADVADDR); /* get faulting address */
-	i_lw(p, ptr, rel_lo(pgdc), ptr);
-	i_srl(p, tmp, tmp, PGDIR_SHIFT); /* get pgd only bits */
-	i_sll(p, tmp, tmp, PGD_T_LOG2);
-	i_addu(p, ptr, ptr, tmp); /* add in pgd offset */
+	uasm_i_mfc0(p, tmp, C0_BADVADDR); /* get faulting address */
+	uasm_i_lw(p, ptr, uasm_rel_lo(pgdc), ptr);
+	uasm_i_srl(p, tmp, tmp, PGDIR_SHIFT); /* get pgd only bits */
+	uasm_i_sll(p, tmp, tmp, PGD_T_LOG2);
+	uasm_i_addu(p, ptr, ptr, tmp); /* add in pgd offset */
 }
 
 #endif /* !CONFIG_64BIT */
@@ -1198,8 +579,8 @@
 	}
 
 	if (shift)
-		i_SRL(p, ctx, ctx, shift);
-	i_andi(p, ctx, ctx, mask);
+		UASM_i_SRL(p, ctx, ctx, shift);
+	uasm_i_andi(p, ctx, ctx, mask);
 }
 
 static void __init build_get_ptep(u32 **p, unsigned int tmp, unsigned int ptr)
@@ -1213,18 +594,18 @@
 	 */
 	switch (current_cpu_type()) {
 	case CPU_NEVADA:
-		i_LW(p, ptr, 0, ptr);
+		UASM_i_LW(p, ptr, 0, ptr);
 		GET_CONTEXT(p, tmp); /* get context reg */
 		break;
 
 	default:
 		GET_CONTEXT(p, tmp); /* get context reg */
-		i_LW(p, ptr, 0, ptr);
+		UASM_i_LW(p, ptr, 0, ptr);
 		break;
 	}
 
 	build_adjust_context(p, tmp);
-	i_ADDU(p, ptr, ptr, tmp); /* add in offset */
+	UASM_i_ADDU(p, ptr, ptr, tmp); /* add in offset */
 }
 
 static void __init build_update_entries(u32 **p, unsigned int tmp,
@@ -1236,45 +617,45 @@
 	 */
 #ifdef CONFIG_64BIT_PHYS_ADDR
 	if (cpu_has_64bits) {
-		i_ld(p, tmp, 0, ptep); /* get even pte */
-		i_ld(p, ptep, sizeof(pte_t), ptep); /* get odd pte */
-		i_dsrl(p, tmp, tmp, 6); /* convert to entrylo0 */
-		i_mtc0(p, tmp, C0_ENTRYLO0); /* load it */
-		i_dsrl(p, ptep, ptep, 6); /* convert to entrylo1 */
-		i_mtc0(p, ptep, C0_ENTRYLO1); /* load it */
+		uasm_i_ld(p, tmp, 0, ptep); /* get even pte */
+		uasm_i_ld(p, ptep, sizeof(pte_t), ptep); /* get odd pte */
+		uasm_i_dsrl(p, tmp, tmp, 6); /* convert to entrylo0 */
+		uasm_i_mtc0(p, tmp, C0_ENTRYLO0); /* load it */
+		uasm_i_dsrl(p, ptep, ptep, 6); /* convert to entrylo1 */
+		uasm_i_mtc0(p, ptep, C0_ENTRYLO1); /* load it */
 	} else {
 		int pte_off_even = sizeof(pte_t) / 2;
 		int pte_off_odd = pte_off_even + sizeof(pte_t);
 
 		/* The pte entries are pre-shifted */
-		i_lw(p, tmp, pte_off_even, ptep); /* get even pte */
-		i_mtc0(p, tmp, C0_ENTRYLO0); /* load it */
-		i_lw(p, ptep, pte_off_odd, ptep); /* get odd pte */
-		i_mtc0(p, ptep, C0_ENTRYLO1); /* load it */
+		uasm_i_lw(p, tmp, pte_off_even, ptep); /* get even pte */
+		uasm_i_mtc0(p, tmp, C0_ENTRYLO0); /* load it */
+		uasm_i_lw(p, ptep, pte_off_odd, ptep); /* get odd pte */
+		uasm_i_mtc0(p, ptep, C0_ENTRYLO1); /* load it */
 	}
 #else
-	i_LW(p, tmp, 0, ptep); /* get even pte */
-	i_LW(p, ptep, sizeof(pte_t), ptep); /* get odd pte */
+	UASM_i_LW(p, tmp, 0, ptep); /* get even pte */
+	UASM_i_LW(p, ptep, sizeof(pte_t), ptep); /* get odd pte */
 	if (r45k_bvahwbug())
 		build_tlb_probe_entry(p);
-	i_SRL(p, tmp, tmp, 6); /* convert to entrylo0 */
+	UASM_i_SRL(p, tmp, tmp, 6); /* convert to entrylo0 */
 	if (r4k_250MHZhwbug())
-		i_mtc0(p, 0, C0_ENTRYLO0);
-	i_mtc0(p, tmp, C0_ENTRYLO0); /* load it */
-	i_SRL(p, ptep, ptep, 6); /* convert to entrylo1 */
+		uasm_i_mtc0(p, 0, C0_ENTRYLO0);
+	uasm_i_mtc0(p, tmp, C0_ENTRYLO0); /* load it */
+	UASM_i_SRL(p, ptep, ptep, 6); /* convert to entrylo1 */
 	if (r45k_bvahwbug())
-		i_mfc0(p, tmp, C0_INDEX);
+		uasm_i_mfc0(p, tmp, C0_INDEX);
 	if (r4k_250MHZhwbug())
-		i_mtc0(p, 0, C0_ENTRYLO1);
-	i_mtc0(p, ptep, C0_ENTRYLO1); /* load it */
+		uasm_i_mtc0(p, 0, C0_ENTRYLO1);
+	uasm_i_mtc0(p, ptep, C0_ENTRYLO1); /* load it */
 #endif
 }
 
 static void __init build_r4000_tlb_refill_handler(void)
 {
 	u32 *p = tlb_handler;
-	struct label *l = labels;
-	struct reloc *r = relocs;
+	struct uasm_label *l = labels;
+	struct uasm_reloc *r = relocs;
 	u32 *f;
 	unsigned int final_len;
 
@@ -1287,12 +668,12 @@
 	 * create the plain linear handler
 	 */
 	if (bcm1250_m3_war()) {
-		i_MFC0(&p, K0, C0_BADVADDR);
-		i_MFC0(&p, K1, C0_ENTRYHI);
-		i_xor(&p, K0, K0, K1);
-		i_SRL(&p, K0, K0, PAGE_SHIFT + 1);
-		il_bnez(&p, &r, K0, label_leave);
-		/* No need for i_nop */
+		UASM_i_MFC0(&p, K0, C0_BADVADDR);
+		UASM_i_MFC0(&p, K1, C0_ENTRYHI);
+		uasm_i_xor(&p, K0, K0, K1);
+		UASM_i_SRL(&p, K0, K0, PAGE_SHIFT + 1);
+		uasm_il_bnez(&p, &r, K0, label_leave);
+		/* No need for uasm_i_nop */
 	}
 
 #ifdef CONFIG_64BIT
@@ -1304,8 +685,8 @@
 	build_get_ptep(&p, K0, K1);
 	build_update_entries(&p, K0, K1);
 	build_tlb_write_entry(&p, &l, &r, tlb_random);
-	l_leave(&l, p);
-	i_eret(&p); /* return from trap */
+	uasm_l_leave(&l, p);
+	uasm_i_eret(&p); /* return from trap */
 
 #ifdef CONFIG_64BIT
 	build_get_pgd_vmalloc64(&p, &l, &r, K0, K1);
@@ -1325,7 +706,7 @@
 #else
 	if (((p - tlb_handler) > 63)
 	    || (((p - tlb_handler) > 61)
-		&& insn_has_bdelay(relocs, tlb_handler + 29)))
+		&& uasm_insn_has_bdelay(relocs, tlb_handler + 29)))
 		panic("TLB refill handler space exceeded");
 #endif
 
@@ -1335,13 +716,13 @@
 #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);
+	uasm_copy_handler(relocs, labels, tlb_handler, p, f);
 	final_len = p - tlb_handler;
 #else /* CONFIG_64BIT */
 	f = final_handler + 32;
 	if ((p - tlb_handler) <= 32) {
 		/* Just copy the handler. */
-		copy_handler(relocs, labels, tlb_handler, p, f);
+		uasm_copy_handler(relocs, labels, tlb_handler, p, f);
 		final_len = p - tlb_handler;
 	} else {
 		u32 *split = tlb_handler + 30;
@@ -1349,34 +730,34 @@
 		/*
 		 * Find the split point.
 		 */
-		if (insn_has_bdelay(relocs, split - 1))
+		if (uasm_insn_has_bdelay(relocs, split - 1))
 			split--;
 
 		/* Copy first part of the handler. */
-		copy_handler(relocs, labels, tlb_handler, split, f);
+		uasm_copy_handler(relocs, labels, tlb_handler, split, f);
 		f += split - tlb_handler;
 
 		/* Insert branch. */
-		l_split(&l, final_handler);
-		il_b(&f, &r, label_split);
-		if (insn_has_bdelay(relocs, split))
-			i_nop(&f);
+		uasm_l_split(&l, final_handler);
+		uasm_il_b(&f, &r, label_split);
+		if (uasm_insn_has_bdelay(relocs, split))
+			uasm_i_nop(&f);
 		else {
-			copy_handler(relocs, labels, split, split + 1, f);
-			move_labels(labels, f, f + 1, -1);
+			uasm_copy_handler(relocs, labels, split, split + 1, f);
+			uasm_move_labels(labels, f, f + 1, -1);
 			f++;
 			split++;
 		}
 
 		/* Copy the rest of the handler. */
-		copy_handler(relocs, labels, split, p, final_handler);
+		uasm_copy_handler(relocs, labels, split, p, final_handler);
 		final_len = (f - (final_handler + 32)) + (p - split);
 	}
 #endif /* CONFIG_64BIT */
 
-	resolve_relocs(relocs, labels);
-	pr_info("Synthesized TLB refill handler (%u instructions).\n",
-		final_len);
+	uasm_resolve_relocs(relocs, labels);
+	pr_debug("Wrote TLB refill handler (%u instructions).\n",
+		 final_len);
 
 	memcpy((void *)ebase, final_handler, 0x100);
 
@@ -1403,75 +784,75 @@
 u32 handle_tlbm[FASTPATH_SIZE] __cacheline_aligned;
 
 static void __init
-iPTE_LW(u32 **p, struct label **l, unsigned int pte, unsigned int ptr)
+iPTE_LW(u32 **p, struct uasm_label **l, unsigned int pte, unsigned int ptr)
 {
 #ifdef CONFIG_SMP
 # ifdef CONFIG_64BIT_PHYS_ADDR
 	if (cpu_has_64bits)
-		i_lld(p, pte, 0, ptr);
+		uasm_i_lld(p, pte, 0, ptr);
 	else
 # endif
-		i_LL(p, pte, 0, ptr);
+		UASM_i_LL(p, pte, 0, ptr);
 #else
 # ifdef CONFIG_64BIT_PHYS_ADDR
 	if (cpu_has_64bits)
-		i_ld(p, pte, 0, ptr);
+		uasm_i_ld(p, pte, 0, ptr);
 	else
 # endif
-		i_LW(p, pte, 0, ptr);
+		UASM_i_LW(p, pte, 0, ptr);
 #endif
 }
 
 static void __init
-iPTE_SW(u32 **p, struct reloc **r, unsigned int pte, unsigned int ptr,
+iPTE_SW(u32 **p, struct uasm_reloc **r, unsigned int pte, unsigned int ptr,
 	unsigned int mode)
 {
 #ifdef CONFIG_64BIT_PHYS_ADDR
 	unsigned int hwmode = mode & (_PAGE_VALID | _PAGE_DIRTY);
 #endif
 
-	i_ori(p, pte, pte, mode);
+	uasm_i_ori(p, pte, pte, mode);
 #ifdef CONFIG_SMP
 # ifdef CONFIG_64BIT_PHYS_ADDR
 	if (cpu_has_64bits)
-		i_scd(p, pte, 0, ptr);
+		uasm_i_scd(p, pte, 0, ptr);
 	else
 # endif
-		i_SC(p, pte, 0, ptr);
+		UASM_i_SC(p, pte, 0, ptr);
 
 	if (r10000_llsc_war())
-		il_beqzl(p, r, pte, label_smp_pgtable_change);
+		uasm_il_beqzl(p, r, pte, label_smp_pgtable_change);
 	else
-		il_beqz(p, r, pte, label_smp_pgtable_change);
+		uasm_il_beqz(p, r, pte, label_smp_pgtable_change);
 
 # ifdef CONFIG_64BIT_PHYS_ADDR
 	if (!cpu_has_64bits) {
-		/* no i_nop needed */
-		i_ll(p, pte, sizeof(pte_t) / 2, ptr);
-		i_ori(p, pte, pte, hwmode);
-		i_sc(p, pte, sizeof(pte_t) / 2, ptr);
-		il_beqz(p, r, pte, label_smp_pgtable_change);
-		/* no i_nop needed */
-		i_lw(p, pte, 0, ptr);
+		/* no uasm_i_nop needed */
+		uasm_i_ll(p, pte, sizeof(pte_t) / 2, ptr);
+		uasm_i_ori(p, pte, pte, hwmode);
+		uasm_i_sc(p, pte, sizeof(pte_t) / 2, ptr);
+		uasm_il_beqz(p, r, pte, label_smp_pgtable_change);
+		/* no uasm_i_nop needed */
+		uasm_i_lw(p, pte, 0, ptr);
 	} else
-		i_nop(p);
+		uasm_i_nop(p);
 # else
-	i_nop(p);
+	uasm_i_nop(p);
 # endif
 #else
 # ifdef CONFIG_64BIT_PHYS_ADDR
 	if (cpu_has_64bits)
-		i_sd(p, pte, 0, ptr);
+		uasm_i_sd(p, pte, 0, ptr);
 	else
 # endif
-		i_SW(p, pte, 0, ptr);
+		UASM_i_SW(p, pte, 0, ptr);
 
 # ifdef CONFIG_64BIT_PHYS_ADDR
 	if (!cpu_has_64bits) {
-		i_lw(p, pte, sizeof(pte_t) / 2, ptr);
-		i_ori(p, pte, pte, hwmode);
-		i_sw(p, pte, sizeof(pte_t) / 2, ptr);
-		i_lw(p, pte, 0, ptr);
+		uasm_i_lw(p, pte, sizeof(pte_t) / 2, ptr);
+		uasm_i_ori(p, pte, pte, hwmode);
+		uasm_i_sw(p, pte, sizeof(pte_t) / 2, ptr);
+		uasm_i_lw(p, pte, 0, ptr);
 	}
 # endif
 #endif
@@ -1483,18 +864,18 @@
  * with it's original value.
  */
 static void __init
-build_pte_present(u32 **p, struct label **l, struct reloc **r,
+build_pte_present(u32 **p, struct uasm_label **l, struct uasm_reloc **r,
 		  unsigned int pte, unsigned int ptr, enum label_id lid)
 {
-	i_andi(p, pte, pte, _PAGE_PRESENT | _PAGE_READ);
-	i_xori(p, pte, pte, _PAGE_PRESENT | _PAGE_READ);
-	il_bnez(p, r, pte, lid);
+	uasm_i_andi(p, pte, pte, _PAGE_PRESENT | _PAGE_READ);
+	uasm_i_xori(p, pte, pte, _PAGE_PRESENT | _PAGE_READ);
+	uasm_il_bnez(p, r, pte, lid);
 	iPTE_LW(p, l, pte, ptr);
 }
 
 /* Make PTE valid, store result in PTR. */
 static void __init
-build_make_valid(u32 **p, struct reloc **r, unsigned int pte,
+build_make_valid(u32 **p, struct uasm_reloc **r, unsigned int pte,
 		 unsigned int ptr)
 {
 	unsigned int mode = _PAGE_VALID | _PAGE_ACCESSED;
@@ -1507,12 +888,12 @@
  * restore PTE with value from PTR when done.
  */
 static void __init
-build_pte_writable(u32 **p, struct label **l, struct reloc **r,
+build_pte_writable(u32 **p, struct uasm_label **l, struct uasm_reloc **r,
 		   unsigned int pte, unsigned int ptr, enum label_id lid)
 {
-	i_andi(p, pte, pte, _PAGE_PRESENT | _PAGE_WRITE);
-	i_xori(p, pte, pte, _PAGE_PRESENT | _PAGE_WRITE);
-	il_bnez(p, r, pte, lid);
+	uasm_i_andi(p, pte, pte, _PAGE_PRESENT | _PAGE_WRITE);
+	uasm_i_xori(p, pte, pte, _PAGE_PRESENT | _PAGE_WRITE);
+	uasm_il_bnez(p, r, pte, lid);
 	iPTE_LW(p, l, pte, ptr);
 }
 
@@ -1520,7 +901,7 @@
  * at PTR.
  */
 static void __init
-build_make_write(u32 **p, struct reloc **r, unsigned int pte,
+build_make_write(u32 **p, struct uasm_reloc **r, unsigned int pte,
 		 unsigned int ptr)
 {
 	unsigned int mode = (_PAGE_ACCESSED | _PAGE_MODIFIED | _PAGE_VALID
@@ -1534,11 +915,11 @@
  * restore PTE with value from PTR when done.
  */
 static void __init
-build_pte_modifiable(u32 **p, struct label **l, struct reloc **r,
+build_pte_modifiable(u32 **p, struct uasm_label **l, struct uasm_reloc **r,
 		     unsigned int pte, unsigned int ptr, enum label_id lid)
 {
-	i_andi(p, pte, pte, _PAGE_WRITE);
-	il_beqz(p, r, pte, lid);
+	uasm_i_andi(p, pte, pte, _PAGE_WRITE);
+	uasm_il_beqz(p, r, pte, lid);
 	iPTE_LW(p, l, pte, ptr);
 }
 
@@ -1553,11 +934,11 @@
 static void __init
 build_r3000_pte_reload_tlbwi(u32 **p, unsigned int pte, unsigned int tmp)
 {
-	i_mtc0(p, pte, C0_ENTRYLO0); /* cp0 delay */
-	i_mfc0(p, tmp, C0_EPC); /* cp0 delay */
-	i_tlbwi(p);
-	i_jr(p, tmp);
-	i_rfe(p); /* branch delay */
+	uasm_i_mtc0(p, pte, C0_ENTRYLO0); /* cp0 delay */
+	uasm_i_mfc0(p, tmp, C0_EPC); /* cp0 delay */
+	uasm_i_tlbwi(p);
+	uasm_i_jr(p, tmp);
+	uasm_i_rfe(p); /* branch delay */
 }
 
 /*
@@ -1567,20 +948,21 @@
  * kseg2 access, i.e. without refill.  Then it returns.
  */
 static void __init
-build_r3000_tlb_reload_write(u32 **p, struct label **l, struct reloc **r,
-			     unsigned int pte, unsigned int tmp)
+build_r3000_tlb_reload_write(u32 **p, struct uasm_label **l,
+			     struct uasm_reloc **r, unsigned int pte,
+			     unsigned int tmp)
 {
-	i_mfc0(p, tmp, C0_INDEX);
-	i_mtc0(p, pte, C0_ENTRYLO0); /* cp0 delay */
-	il_bltz(p, r, tmp, label_r3000_write_probe_fail); /* cp0 delay */
-	i_mfc0(p, tmp, C0_EPC); /* branch delay */
-	i_tlbwi(p); /* cp0 delay */
-	i_jr(p, tmp);
-	i_rfe(p); /* branch delay */
-	l_r3000_write_probe_fail(l, *p);
-	i_tlbwr(p); /* cp0 delay */
-	i_jr(p, tmp);
-	i_rfe(p); /* branch delay */
+	uasm_i_mfc0(p, tmp, C0_INDEX);
+	uasm_i_mtc0(p, pte, C0_ENTRYLO0); /* cp0 delay */
+	uasm_il_bltz(p, r, tmp, label_r3000_write_probe_fail); /* cp0 delay */
+	uasm_i_mfc0(p, tmp, C0_EPC); /* branch delay */
+	uasm_i_tlbwi(p); /* cp0 delay */
+	uasm_i_jr(p, tmp);
+	uasm_i_rfe(p); /* branch delay */
+	uasm_l_r3000_write_probe_fail(l, *p);
+	uasm_i_tlbwr(p); /* cp0 delay */
+	uasm_i_jr(p, tmp);
+	uasm_i_rfe(p); /* branch delay */
 }
 
 static void __init
@@ -1589,25 +971,25 @@
 {
 	long pgdc = (long)pgd_current;
 
-	i_mfc0(p, pte, C0_BADVADDR);
-	i_lui(p, ptr, rel_hi(pgdc)); /* cp0 delay */
-	i_lw(p, ptr, rel_lo(pgdc), ptr);
-	i_srl(p, pte, pte, 22); /* load delay */
-	i_sll(p, pte, pte, 2);
-	i_addu(p, ptr, ptr, pte);
-	i_mfc0(p, pte, C0_CONTEXT);
-	i_lw(p, ptr, 0, ptr); /* cp0 delay */
-	i_andi(p, pte, pte, 0xffc); /* load delay */
-	i_addu(p, ptr, ptr, pte);
-	i_lw(p, pte, 0, ptr);
-	i_tlbp(p); /* load delay */
+	uasm_i_mfc0(p, pte, C0_BADVADDR);
+	uasm_i_lui(p, ptr, uasm_rel_hi(pgdc)); /* cp0 delay */
+	uasm_i_lw(p, ptr, uasm_rel_lo(pgdc), ptr);
+	uasm_i_srl(p, pte, pte, 22); /* load delay */
+	uasm_i_sll(p, pte, pte, 2);
+	uasm_i_addu(p, ptr, ptr, pte);
+	uasm_i_mfc0(p, pte, C0_CONTEXT);
+	uasm_i_lw(p, ptr, 0, ptr); /* cp0 delay */
+	uasm_i_andi(p, pte, pte, 0xffc); /* load delay */
+	uasm_i_addu(p, ptr, ptr, pte);
+	uasm_i_lw(p, pte, 0, ptr);
+	uasm_i_tlbp(p); /* load delay */
 }
 
 static void __init build_r3000_tlb_load_handler(void)
 {
 	u32 *p = handle_tlbl;
-	struct label *l = labels;
-	struct reloc *r = relocs;
+	struct uasm_label *l = labels;
+	struct uasm_reloc *r = relocs;
 
 	memset(handle_tlbl, 0, sizeof(handle_tlbl));
 	memset(labels, 0, sizeof(labels));
@@ -1615,20 +997,20 @@
 
 	build_r3000_tlbchange_handler_head(&p, K0, K1);
 	build_pte_present(&p, &l, &r, K0, K1, label_nopage_tlbl);
-	i_nop(&p); /* load delay */
+	uasm_i_nop(&p); /* load delay */
 	build_make_valid(&p, &r, K0, K1);
 	build_r3000_tlb_reload_write(&p, &l, &r, K0, K1);
 
-	l_nopage_tlbl(&l, p);
-	i_j(&p, (unsigned long)tlb_do_page_fault_0 & 0x0fffffff);
-	i_nop(&p);
+	uasm_l_nopage_tlbl(&l, p);
+	uasm_i_j(&p, (unsigned long)tlb_do_page_fault_0 & 0x0fffffff);
+	uasm_i_nop(&p);
 
 	if ((p - handle_tlbl) > FASTPATH_SIZE)
 		panic("TLB load handler fastpath space exceeded");
 
-	resolve_relocs(relocs, labels);
-	pr_info("Synthesized TLB load handler fastpath (%u instructions).\n",
-		(unsigned int)(p - handle_tlbl));
+	uasm_resolve_relocs(relocs, labels);
+	pr_debug("Wrote TLB load handler fastpath (%u instructions).\n",
+		 (unsigned int)(p - handle_tlbl));
 
 	dump_handler(handle_tlbl, ARRAY_SIZE(handle_tlbl));
 }
@@ -1636,8 +1018,8 @@
 static void __init build_r3000_tlb_store_handler(void)
 {
 	u32 *p = handle_tlbs;
-	struct label *l = labels;
-	struct reloc *r = relocs;
+	struct uasm_label *l = labels;
+	struct uasm_reloc *r = relocs;
 
 	memset(handle_tlbs, 0, sizeof(handle_tlbs));
 	memset(labels, 0, sizeof(labels));
@@ -1645,20 +1027,20 @@
 
 	build_r3000_tlbchange_handler_head(&p, K0, K1);
 	build_pte_writable(&p, &l, &r, K0, K1, label_nopage_tlbs);
-	i_nop(&p); /* load delay */
+	uasm_i_nop(&p); /* load delay */
 	build_make_write(&p, &r, K0, K1);
 	build_r3000_tlb_reload_write(&p, &l, &r, K0, K1);
 
-	l_nopage_tlbs(&l, p);
-	i_j(&p, (unsigned long)tlb_do_page_fault_1 & 0x0fffffff);
-	i_nop(&p);
+	uasm_l_nopage_tlbs(&l, p);
+	uasm_i_j(&p, (unsigned long)tlb_do_page_fault_1 & 0x0fffffff);
+	uasm_i_nop(&p);
 
 	if ((p - handle_tlbs) > FASTPATH_SIZE)
 		panic("TLB store handler fastpath space exceeded");
 
-	resolve_relocs(relocs, labels);
-	pr_info("Synthesized TLB store handler fastpath (%u instructions).\n",
-		(unsigned int)(p - handle_tlbs));
+	uasm_resolve_relocs(relocs, labels);
+	pr_debug("Wrote TLB store handler fastpath (%u instructions).\n",
+		 (unsigned int)(p - handle_tlbs));
 
 	dump_handler(handle_tlbs, ARRAY_SIZE(handle_tlbs));
 }
@@ -1666,8 +1048,8 @@
 static void __init build_r3000_tlb_modify_handler(void)
 {
 	u32 *p = handle_tlbm;
-	struct label *l = labels;
-	struct reloc *r = relocs;
+	struct uasm_label *l = labels;
+	struct uasm_reloc *r = relocs;
 
 	memset(handle_tlbm, 0, sizeof(handle_tlbm));
 	memset(labels, 0, sizeof(labels));
@@ -1675,20 +1057,20 @@
 
 	build_r3000_tlbchange_handler_head(&p, K0, K1);
 	build_pte_modifiable(&p, &l, &r, K0, K1, label_nopage_tlbm);
-	i_nop(&p); /* load delay */
+	uasm_i_nop(&p); /* load delay */
 	build_make_write(&p, &r, K0, K1);
 	build_r3000_pte_reload_tlbwi(&p, K0, K1);
 
-	l_nopage_tlbm(&l, p);
-	i_j(&p, (unsigned long)tlb_do_page_fault_1 & 0x0fffffff);
-	i_nop(&p);
+	uasm_l_nopage_tlbm(&l, p);
+	uasm_i_j(&p, (unsigned long)tlb_do_page_fault_1 & 0x0fffffff);
+	uasm_i_nop(&p);
 
 	if ((p - handle_tlbm) > FASTPATH_SIZE)
 		panic("TLB modify handler fastpath space exceeded");
 
-	resolve_relocs(relocs, labels);
-	pr_info("Synthesized TLB modify handler fastpath (%u instructions).\n",
-		(unsigned int)(p - handle_tlbm));
+	uasm_resolve_relocs(relocs, labels);
+	pr_debug("Wrote TLB modify handler fastpath (%u instructions).\n",
+		 (unsigned int)(p - handle_tlbm));
 
 	dump_handler(handle_tlbm, ARRAY_SIZE(handle_tlbm));
 }
@@ -1697,8 +1079,8 @@
  * R4000 style TLB load/store/modify handlers.
  */
 static void __init
-build_r4000_tlbchange_handler_head(u32 **p, struct label **l,
-				   struct reloc **r, unsigned int pte,
+build_r4000_tlbchange_handler_head(u32 **p, struct uasm_label **l,
+				   struct uasm_reloc **r, unsigned int pte,
 				   unsigned int ptr)
 {
 #ifdef CONFIG_64BIT
@@ -1707,31 +1089,31 @@
 	build_get_pgde32(p, pte, ptr); /* get pgd in ptr */
 #endif
 
-	i_MFC0(p, pte, C0_BADVADDR);
-	i_LW(p, ptr, 0, ptr);
-	i_SRL(p, pte, pte, PAGE_SHIFT + PTE_ORDER - PTE_T_LOG2);
-	i_andi(p, pte, pte, (PTRS_PER_PTE - 1) << PTE_T_LOG2);
-	i_ADDU(p, ptr, ptr, pte);
+	UASM_i_MFC0(p, pte, C0_BADVADDR);
+	UASM_i_LW(p, ptr, 0, ptr);
+	UASM_i_SRL(p, pte, pte, PAGE_SHIFT + PTE_ORDER - PTE_T_LOG2);
+	uasm_i_andi(p, pte, pte, (PTRS_PER_PTE - 1) << PTE_T_LOG2);
+	UASM_i_ADDU(p, ptr, ptr, pte);
 
 #ifdef CONFIG_SMP
-	l_smp_pgtable_change(l, *p);
-# endif
+	uasm_l_smp_pgtable_change(l, *p);
+#endif
 	iPTE_LW(p, l, pte, ptr); /* get even pte */
 	if (!m4kc_tlbp_war())
 		build_tlb_probe_entry(p);
 }
 
 static void __init
-build_r4000_tlbchange_handler_tail(u32 **p, struct label **l,
-				   struct reloc **r, unsigned int tmp,
+build_r4000_tlbchange_handler_tail(u32 **p, struct uasm_label **l,
+				   struct uasm_reloc **r, unsigned int tmp,
 				   unsigned int ptr)
 {
-	i_ori(p, ptr, ptr, sizeof(pte_t));
-	i_xori(p, ptr, ptr, sizeof(pte_t));
+	uasm_i_ori(p, ptr, ptr, sizeof(pte_t));
+	uasm_i_xori(p, ptr, ptr, sizeof(pte_t));
 	build_update_entries(p, tmp, ptr);
 	build_tlb_write_entry(p, l, r, tlb_indexed);
-	l_leave(l, *p);
-	i_eret(p); /* return from trap */
+	uasm_l_leave(l, *p);
+	uasm_i_eret(p); /* return from trap */
 
 #ifdef CONFIG_64BIT
 	build_get_pgd_vmalloc64(p, l, r, tmp, ptr);
@@ -1741,20 +1123,20 @@
 static void __init build_r4000_tlb_load_handler(void)
 {
 	u32 *p = handle_tlbl;
-	struct label *l = labels;
-	struct reloc *r = relocs;
+	struct uasm_label *l = labels;
+	struct uasm_reloc *r = relocs;
 
 	memset(handle_tlbl, 0, sizeof(handle_tlbl));
 	memset(labels, 0, sizeof(labels));
 	memset(relocs, 0, sizeof(relocs));
 
 	if (bcm1250_m3_war()) {
-		i_MFC0(&p, K0, C0_BADVADDR);
-		i_MFC0(&p, K1, C0_ENTRYHI);
-		i_xor(&p, K0, K0, K1);
-		i_SRL(&p, K0, K0, PAGE_SHIFT + 1);
-		il_bnez(&p, &r, K0, label_leave);
-		/* No need for i_nop */
+		UASM_i_MFC0(&p, K0, C0_BADVADDR);
+		UASM_i_MFC0(&p, K1, C0_ENTRYHI);
+		uasm_i_xor(&p, K0, K0, K1);
+		UASM_i_SRL(&p, K0, K0, PAGE_SHIFT + 1);
+		uasm_il_bnez(&p, &r, K0, label_leave);
+		/* No need for uasm_i_nop */
 	}
 
 	build_r4000_tlbchange_handler_head(&p, &l, &r, K0, K1);
@@ -1764,16 +1146,16 @@
 	build_make_valid(&p, &r, K0, K1);
 	build_r4000_tlbchange_handler_tail(&p, &l, &r, K0, K1);
 
-	l_nopage_tlbl(&l, p);
-	i_j(&p, (unsigned long)tlb_do_page_fault_0 & 0x0fffffff);
-	i_nop(&p);
+	uasm_l_nopage_tlbl(&l, p);
+	uasm_i_j(&p, (unsigned long)tlb_do_page_fault_0 & 0x0fffffff);
+	uasm_i_nop(&p);
 
 	if ((p - handle_tlbl) > FASTPATH_SIZE)
 		panic("TLB load handler fastpath space exceeded");
 
-	resolve_relocs(relocs, labels);
-	pr_info("Synthesized TLB load handler fastpath (%u instructions).\n",
-		(unsigned int)(p - handle_tlbl));
+	uasm_resolve_relocs(relocs, labels);
+	pr_debug("Wrote TLB load handler fastpath (%u instructions).\n",
+		 (unsigned int)(p - handle_tlbl));
 
 	dump_handler(handle_tlbl, ARRAY_SIZE(handle_tlbl));
 }
@@ -1781,8 +1163,8 @@
 static void __init build_r4000_tlb_store_handler(void)
 {
 	u32 *p = handle_tlbs;
-	struct label *l = labels;
-	struct reloc *r = relocs;
+	struct uasm_label *l = labels;
+	struct uasm_reloc *r = relocs;
 
 	memset(handle_tlbs, 0, sizeof(handle_tlbs));
 	memset(labels, 0, sizeof(labels));
@@ -1795,16 +1177,16 @@
 	build_make_write(&p, &r, K0, K1);
 	build_r4000_tlbchange_handler_tail(&p, &l, &r, K0, K1);
 
-	l_nopage_tlbs(&l, p);
-	i_j(&p, (unsigned long)tlb_do_page_fault_1 & 0x0fffffff);
-	i_nop(&p);
+	uasm_l_nopage_tlbs(&l, p);
+	uasm_i_j(&p, (unsigned long)tlb_do_page_fault_1 & 0x0fffffff);
+	uasm_i_nop(&p);
 
 	if ((p - handle_tlbs) > FASTPATH_SIZE)
 		panic("TLB store handler fastpath space exceeded");
 
-	resolve_relocs(relocs, labels);
-	pr_info("Synthesized TLB store handler fastpath (%u instructions).\n",
-		(unsigned int)(p - handle_tlbs));
+	uasm_resolve_relocs(relocs, labels);
+	pr_debug("Wrote TLB store handler fastpath (%u instructions).\n",
+		 (unsigned int)(p - handle_tlbs));
 
 	dump_handler(handle_tlbs, ARRAY_SIZE(handle_tlbs));
 }
@@ -1812,8 +1194,8 @@
 static void __init build_r4000_tlb_modify_handler(void)
 {
 	u32 *p = handle_tlbm;
-	struct label *l = labels;
-	struct reloc *r = relocs;
+	struct uasm_label *l = labels;
+	struct uasm_reloc *r = relocs;
 
 	memset(handle_tlbm, 0, sizeof(handle_tlbm));
 	memset(labels, 0, sizeof(labels));
@@ -1827,16 +1209,16 @@
 	build_make_write(&p, &r, K0, K1);
 	build_r4000_tlbchange_handler_tail(&p, &l, &r, K0, K1);
 
-	l_nopage_tlbm(&l, p);
-	i_j(&p, (unsigned long)tlb_do_page_fault_1 & 0x0fffffff);
-	i_nop(&p);
+	uasm_l_nopage_tlbm(&l, p);
+	uasm_i_j(&p, (unsigned long)tlb_do_page_fault_1 & 0x0fffffff);
+	uasm_i_nop(&p);
 
 	if ((p - handle_tlbm) > FASTPATH_SIZE)
 		panic("TLB modify handler fastpath space exceeded");
 
-	resolve_relocs(relocs, labels);
-	pr_info("Synthesized TLB modify handler fastpath (%u instructions).\n",
-		(unsigned int)(p - handle_tlbm));
+	uasm_resolve_relocs(relocs, labels);
+	pr_debug("Wrote TLB modify handler fastpath (%u instructions).\n",
+		 (unsigned int)(p - handle_tlbm));
 
 	dump_handler(handle_tlbm, ARRAY_SIZE(handle_tlbm));
 }
diff --git a/arch/mips/mm/uasm.c b/arch/mips/mm/uasm.c
new file mode 100644
index 0000000..e3f74ed
--- /dev/null
+++ b/arch/mips/mm/uasm.c
@@ -0,0 +1,576 @@
+/*
+ * 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.
+ *
+ * A small micro-assembler. It is intentionally kept simple, does only
+ * support a subset of instructions, and does not try to hide pipeline
+ * effects like branch delay slots.
+ *
+ * Copyright (C) 2004, 2005, 2006, 2008  Thiemo Seufer
+ * Copyright (C) 2005, 2007  Maciej W. Rozycki
+ * Copyright (C) 2006  Ralf Baechle (ralf@linux-mips.org)
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/init.h>
+
+#include <asm/inst.h>
+#include <asm/elf.h>
+#include <asm/bugs.h>
+
+#include "uasm.h"
+
+enum fields {
+	RS = 0x001,
+	RT = 0x002,
+	RD = 0x004,
+	RE = 0x008,
+	SIMM = 0x010,
+	UIMM = 0x020,
+	BIMM = 0x040,
+	JIMM = 0x080,
+	FUNC = 0x100,
+	SET = 0x200
+};
+
+#define OP_MASK		0x3f
+#define OP_SH		26
+#define RS_MASK		0x1f
+#define RS_SH		21
+#define RT_MASK		0x1f
+#define RT_SH		16
+#define RD_MASK		0x1f
+#define RD_SH		11
+#define RE_MASK		0x1f
+#define RE_SH		6
+#define IMM_MASK	0xffff
+#define IMM_SH		0
+#define JIMM_MASK	0x3ffffff
+#define JIMM_SH		0
+#define FUNC_MASK	0x3f
+#define FUNC_SH		0
+#define SET_MASK	0x7
+#define SET_SH		0
+
+enum opcode {
+	insn_invalid,
+	insn_addu, insn_addiu, insn_and, insn_andi, insn_beq,
+	insn_beql, insn_bgez, insn_bgezl, insn_bltz, insn_bltzl,
+	insn_bne, insn_daddu, insn_daddiu, insn_dmfc0, insn_dmtc0,
+	insn_dsll, insn_dsll32, insn_dsra, insn_dsrl, insn_dsrl32,
+	insn_dsubu, insn_eret, insn_j, insn_jal, insn_jr, insn_ld,
+	insn_ll, insn_lld, insn_lui, insn_lw, insn_mfc0, insn_mtc0,
+	insn_ori, insn_rfe, insn_sc, insn_scd, insn_sd, insn_sll,
+	insn_sra, insn_srl, insn_subu, insn_sw, insn_tlbp, insn_tlbwi,
+	insn_tlbwr, insn_xor, insn_xori
+};
+
+struct insn {
+	enum opcode opcode;
+	u32 match;
+	enum fields fields;
+};
+
+/* This macro sets the non-variable bits of an instruction. */
+#define M(a, b, c, d, e, f)					\
+	((a) << OP_SH						\
+	 | (b) << RS_SH						\
+	 | (c) << RT_SH						\
+	 | (d) << RD_SH						\
+	 | (e) << RE_SH						\
+	 | (f) << FUNC_SH)
+
+static struct insn insn_table[] __initdata = {
+	{ insn_addiu, M(addiu_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
+	{ insn_addu, M(spec_op, 0, 0, 0, 0, addu_op), RS | RT | RD },
+	{ insn_and, M(spec_op, 0, 0, 0, 0, and_op), RS | RT | RD },
+	{ insn_andi, M(andi_op, 0, 0, 0, 0, 0), RS | RT | UIMM },
+	{ insn_beq, M(beq_op, 0, 0, 0, 0, 0), RS | RT | BIMM },
+	{ insn_beql, M(beql_op, 0, 0, 0, 0, 0), RS | RT | BIMM },
+	{ insn_bgez, M(bcond_op, 0, bgez_op, 0, 0, 0), RS | BIMM },
+	{ insn_bgezl, M(bcond_op, 0, bgezl_op, 0, 0, 0), RS | BIMM },
+	{ insn_bltz, M(bcond_op, 0, bltz_op, 0, 0, 0), RS | BIMM },
+	{ insn_bltzl, M(bcond_op, 0, bltzl_op, 0, 0, 0), RS | BIMM },
+	{ insn_bne, M(bne_op, 0, 0, 0, 0, 0), RS | RT | BIMM },
+	{ insn_daddiu, M(daddiu_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
+	{ insn_daddu, M(spec_op, 0, 0, 0, 0, daddu_op), RS | RT | RD },
+	{ insn_dmfc0, M(cop0_op, dmfc_op, 0, 0, 0, 0), RT | RD | SET},
+	{ insn_dmtc0, M(cop0_op, dmtc_op, 0, 0, 0, 0), RT | RD | SET},
+	{ insn_dsll, M(spec_op, 0, 0, 0, 0, dsll_op), RT | RD | RE },
+	{ insn_dsll32, M(spec_op, 0, 0, 0, 0, dsll32_op), RT | RD | RE },
+	{ insn_dsra, M(spec_op, 0, 0, 0, 0, dsra_op), RT | RD | RE },
+	{ insn_dsrl, M(spec_op, 0, 0, 0, 0, dsrl_op), RT | RD | RE },
+	{ insn_dsrl32, M(spec_op, 0, 0, 0, 0, dsrl32_op), RT | RD | RE },
+	{ insn_dsubu, M(spec_op, 0, 0, 0, 0, dsubu_op), RS | RT | RD },
+	{ insn_eret,  M(cop0_op, cop_op, 0, 0, 0, eret_op),  0 },
+	{ insn_j,  M(j_op, 0, 0, 0, 0, 0),  JIMM },
+	{ insn_jal,  M(jal_op, 0, 0, 0, 0, 0),  JIMM },
+	{ insn_jr,  M(spec_op, 0, 0, 0, 0, jr_op),  RS },
+	{ insn_ld,  M(ld_op, 0, 0, 0, 0, 0),  RS | RT | SIMM },
+	{ insn_ll,  M(ll_op, 0, 0, 0, 0, 0),  RS | RT | SIMM },
+	{ insn_lld,  M(lld_op, 0, 0, 0, 0, 0),  RS | RT | SIMM },
+	{ insn_lui,  M(lui_op, 0, 0, 0, 0, 0),  RT | SIMM },
+	{ insn_lw,  M(lw_op, 0, 0, 0, 0, 0),  RS | RT | SIMM },
+	{ insn_mfc0,  M(cop0_op, mfc_op, 0, 0, 0, 0),  RT | RD | SET},
+	{ insn_mtc0,  M(cop0_op, mtc_op, 0, 0, 0, 0),  RT | RD | SET},
+	{ insn_ori,  M(ori_op, 0, 0, 0, 0, 0),  RS | RT | UIMM },
+	{ insn_rfe,  M(cop0_op, cop_op, 0, 0, 0, rfe_op),  0 },
+	{ insn_sc,  M(sc_op, 0, 0, 0, 0, 0),  RS | RT | SIMM },
+	{ insn_scd,  M(scd_op, 0, 0, 0, 0, 0),  RS | RT | SIMM },
+	{ insn_sd,  M(sd_op, 0, 0, 0, 0, 0),  RS | RT | SIMM },
+	{ insn_sll,  M(spec_op, 0, 0, 0, 0, sll_op),  RT | RD | RE },
+	{ insn_sra,  M(spec_op, 0, 0, 0, 0, sra_op),  RT | RD | RE },
+	{ insn_srl,  M(spec_op, 0, 0, 0, 0, srl_op),  RT | RD | RE },
+	{ insn_subu,  M(spec_op, 0, 0, 0, 0, subu_op),  RS | RT | RD },
+	{ insn_sw,  M(sw_op, 0, 0, 0, 0, 0),  RS | RT | SIMM },
+	{ insn_tlbp,  M(cop0_op, cop_op, 0, 0, 0, tlbp_op),  0 },
+	{ insn_tlbwi,  M(cop0_op, cop_op, 0, 0, 0, tlbwi_op),  0 },
+	{ insn_tlbwr,  M(cop0_op, cop_op, 0, 0, 0, tlbwr_op),  0 },
+	{ insn_xor,  M(spec_op, 0, 0, 0, 0, xor_op),  RS | RT | RD },
+	{ insn_xori,  M(xori_op, 0, 0, 0, 0, 0),  RS | RT | UIMM },
+	{ insn_invalid, 0, 0 }
+};
+
+#undef M
+
+static inline __init u32 build_rs(u32 arg)
+{
+	if (arg & ~RS_MASK)
+		printk(KERN_WARNING "Micro-assembler field overflow\n");
+
+	return (arg & RS_MASK) << RS_SH;
+}
+
+static inline __init u32 build_rt(u32 arg)
+{
+	if (arg & ~RT_MASK)
+		printk(KERN_WARNING "Micro-assembler field overflow\n");
+
+	return (arg & RT_MASK) << RT_SH;
+}
+
+static inline __init u32 build_rd(u32 arg)
+{
+	if (arg & ~RD_MASK)
+		printk(KERN_WARNING "Micro-assembler field overflow\n");
+
+	return (arg & RD_MASK) << RD_SH;
+}
+
+static inline __init u32 build_re(u32 arg)
+{
+	if (arg & ~RE_MASK)
+		printk(KERN_WARNING "Micro-assembler field overflow\n");
+
+	return (arg & RE_MASK) << RE_SH;
+}
+
+static inline __init u32 build_simm(s32 arg)
+{
+	if (arg > 0x7fff || arg < -0x8000)
+		printk(KERN_WARNING "Micro-assembler field overflow\n");
+
+	return arg & 0xffff;
+}
+
+static inline __init u32 build_uimm(u32 arg)
+{
+	if (arg & ~IMM_MASK)
+		printk(KERN_WARNING "Micro-assembler field overflow\n");
+
+	return arg & IMM_MASK;
+}
+
+static inline __init u32 build_bimm(s32 arg)
+{
+	if (arg > 0x1ffff || arg < -0x20000)
+		printk(KERN_WARNING "Micro-assembler field overflow\n");
+
+	if (arg & 0x3)
+		printk(KERN_WARNING "Invalid micro-assembler branch target\n");
+
+	return ((arg < 0) ? (1 << 15) : 0) | ((arg >> 2) & 0x7fff);
+}
+
+static inline __init u32 build_jimm(u32 arg)
+{
+	if (arg & ~((JIMM_MASK) << 2))
+		printk(KERN_WARNING "Micro-assembler field overflow\n");
+
+	return (arg >> 2) & JIMM_MASK;
+}
+
+static inline __init u32 build_func(u32 arg)
+{
+	if (arg & ~FUNC_MASK)
+		printk(KERN_WARNING "Micro-assembler field overflow\n");
+
+	return arg & FUNC_MASK;
+}
+
+static inline __init u32 build_set(u32 arg)
+{
+	if (arg & ~SET_MASK)
+		printk(KERN_WARNING "Micro-assembler field overflow\n");
+
+	return arg & SET_MASK;
+}
+
+/*
+ * The order of opcode arguments is implicitly left to right,
+ * starting with RS and ending with FUNC or IMM.
+ */
+static void __init build_insn(u32 **buf, enum opcode opc, ...)
+{
+	struct insn *ip = NULL;
+	unsigned int i;
+	va_list ap;
+	u32 op;
+
+	for (i = 0; insn_table[i].opcode != insn_invalid; i++)
+		if (insn_table[i].opcode == opc) {
+			ip = &insn_table[i];
+			break;
+		}
+
+	if (!ip || (opc == insn_daddiu && r4k_daddiu_bug()))
+		panic("Unsupported Micro-assembler instruction %d", opc);
+
+	op = ip->match;
+	va_start(ap, opc);
+	if (ip->fields & RS)
+		op |= build_rs(va_arg(ap, u32));
+	if (ip->fields & RT)
+		op |= build_rt(va_arg(ap, u32));
+	if (ip->fields & RD)
+		op |= build_rd(va_arg(ap, u32));
+	if (ip->fields & RE)
+		op |= build_re(va_arg(ap, u32));
+	if (ip->fields & SIMM)
+		op |= build_simm(va_arg(ap, s32));
+	if (ip->fields & UIMM)
+		op |= build_uimm(va_arg(ap, u32));
+	if (ip->fields & BIMM)
+		op |= build_bimm(va_arg(ap, s32));
+	if (ip->fields & JIMM)
+		op |= build_jimm(va_arg(ap, u32));
+	if (ip->fields & FUNC)
+		op |= build_func(va_arg(ap, u32));
+	if (ip->fields & SET)
+		op |= build_set(va_arg(ap, u32));
+	va_end(ap);
+
+	**buf = op;
+	(*buf)++;
+}
+
+#define I_u1u2u3(op)					\
+Ip_u1u2u3(op)						\
+{							\
+	build_insn(buf, insn##op, a, b, c);		\
+}
+
+#define I_u2u1u3(op)					\
+Ip_u2u1u3(op)						\
+{							\
+	build_insn(buf, insn##op, b, a, c);		\
+}
+
+#define I_u3u1u2(op)					\
+Ip_u3u1u2(op)						\
+{							\
+	build_insn(buf, insn##op, b, c, a);		\
+}
+
+#define I_u1u2s3(op)					\
+Ip_u1u2s3(op)						\
+{							\
+	build_insn(buf, insn##op, a, b, c);		\
+}
+
+#define I_u2s3u1(op)					\
+Ip_u2s3u1(op)						\
+{							\
+	build_insn(buf, insn##op, c, a, b);		\
+}
+
+#define I_u2u1s3(op)					\
+Ip_u2u1s3(op)						\
+{							\
+	build_insn(buf, insn##op, b, a, c);		\
+}
+
+#define I_u1u2(op)					\
+Ip_u1u2(op)						\
+{							\
+	build_insn(buf, insn##op, a, b);		\
+}
+
+#define I_u1s2(op)					\
+Ip_u1s2(op)						\
+{							\
+	build_insn(buf, insn##op, a, b);		\
+}
+
+#define I_u1(op)					\
+Ip_u1(op)						\
+{							\
+	build_insn(buf, insn##op, a);			\
+}
+
+#define I_0(op)						\
+Ip_0(op)						\
+{							\
+	build_insn(buf, insn##op);			\
+}
+
+I_u2u1s3(_addiu)
+I_u3u1u2(_addu)
+I_u2u1u3(_andi)
+I_u3u1u2(_and)
+I_u1u2s3(_beq)
+I_u1u2s3(_beql)
+I_u1s2(_bgez)
+I_u1s2(_bgezl)
+I_u1s2(_bltz)
+I_u1s2(_bltzl)
+I_u1u2s3(_bne)
+I_u1u2u3(_dmfc0)
+I_u1u2u3(_dmtc0)
+I_u2u1s3(_daddiu)
+I_u3u1u2(_daddu)
+I_u2u1u3(_dsll)
+I_u2u1u3(_dsll32)
+I_u2u1u3(_dsra)
+I_u2u1u3(_dsrl)
+I_u2u1u3(_dsrl32)
+I_u3u1u2(_dsubu)
+I_0(_eret)
+I_u1(_j)
+I_u1(_jal)
+I_u1(_jr)
+I_u2s3u1(_ld)
+I_u2s3u1(_ll)
+I_u2s3u1(_lld)
+I_u1s2(_lui)
+I_u2s3u1(_lw)
+I_u1u2u3(_mfc0)
+I_u1u2u3(_mtc0)
+I_u2u1u3(_ori)
+I_0(_rfe)
+I_u2s3u1(_sc)
+I_u2s3u1(_scd)
+I_u2s3u1(_sd)
+I_u2u1u3(_sll)
+I_u2u1u3(_sra)
+I_u2u1u3(_srl)
+I_u3u1u2(_subu)
+I_u2s3u1(_sw)
+I_0(_tlbp)
+I_0(_tlbwi)
+I_0(_tlbwr)
+I_u3u1u2(_xor)
+I_u2u1u3(_xori)
+
+/* Handle labels. */
+void __init uasm_build_label(struct uasm_label **lab, u32 *addr, int lid)
+{
+	(*lab)->addr = addr;
+	(*lab)->lab = lid;
+	(*lab)++;
+}
+
+int __init uasm_in_compat_space_p(long addr)
+{
+	/* Is this address in 32bit compat space? */
+#ifdef CONFIG_64BIT
+	return (((addr) & 0xffffffff00000000L) == 0xffffffff00000000L);
+#else
+	return 1;
+#endif
+}
+
+int __init uasm_rel_highest(long val)
+{
+#ifdef CONFIG_64BIT
+	return ((((val + 0x800080008000L) >> 48) & 0xffff) ^ 0x8000) - 0x8000;
+#else
+	return 0;
+#endif
+}
+
+int __init uasm_rel_higher(long val)
+{
+#ifdef CONFIG_64BIT
+	return ((((val + 0x80008000L) >> 32) & 0xffff) ^ 0x8000) - 0x8000;
+#else
+	return 0;
+#endif
+}
+
+int __init uasm_rel_hi(long val)
+{
+	return ((((val + 0x8000L) >> 16) & 0xffff) ^ 0x8000) - 0x8000;
+}
+
+int __init uasm_rel_lo(long val)
+{
+	return ((val & 0xffff) ^ 0x8000) - 0x8000;
+}
+
+void __init UASM_i_LA_mostly(u32 **buf, unsigned int rs, long addr)
+{
+	if (!uasm_in_compat_space_p(addr)) {
+		uasm_i_lui(buf, rs, uasm_rel_highest(addr));
+		if (uasm_rel_higher(addr))
+			uasm_i_daddiu(buf, rs, rs, uasm_rel_higher(addr));
+		if (uasm_rel_hi(addr)) {
+			uasm_i_dsll(buf, rs, rs, 16);
+			uasm_i_daddiu(buf, rs, rs, uasm_rel_hi(addr));
+			uasm_i_dsll(buf, rs, rs, 16);
+		} else
+			uasm_i_dsll32(buf, rs, rs, 0);
+	} else
+		uasm_i_lui(buf, rs, uasm_rel_hi(addr));
+}
+
+void __init UASM_i_LA(u32 **buf, unsigned int rs, long addr)
+{
+	UASM_i_LA_mostly(buf, rs, addr);
+	if (uasm_rel_lo(addr)) {
+		if (!uasm_in_compat_space_p(addr))
+			uasm_i_daddiu(buf, rs, rs, uasm_rel_lo(addr));
+		else
+			uasm_i_addiu(buf, rs, rs, uasm_rel_lo(addr));
+	}
+}
+
+/* Handle relocations. */
+void __init
+uasm_r_mips_pc16(struct uasm_reloc **rel, u32 *addr, int lid)
+{
+	(*rel)->addr = addr;
+	(*rel)->type = R_MIPS_PC16;
+	(*rel)->lab = lid;
+	(*rel)++;
+}
+
+static inline void __init
+__resolve_relocs(struct uasm_reloc *rel, struct uasm_label *lab)
+{
+	long laddr = (long)lab->addr;
+	long raddr = (long)rel->addr;
+
+	switch (rel->type) {
+	case R_MIPS_PC16:
+		*rel->addr |= build_bimm(laddr - (raddr + 4));
+		break;
+
+	default:
+		panic("Unsupported Micro-assembler relocation %d",
+		      rel->type);
+	}
+}
+
+void __init
+uasm_resolve_relocs(struct uasm_reloc *rel, struct uasm_label *lab)
+{
+	struct uasm_label *l;
+
+	for (; rel->lab != UASM_LABEL_INVALID; rel++)
+		for (l = lab; l->lab != UASM_LABEL_INVALID; l++)
+			if (rel->lab == l->lab)
+				__resolve_relocs(rel, l);
+}
+
+void __init
+uasm_move_relocs(struct uasm_reloc *rel, u32 *first, u32 *end, long off)
+{
+	for (; rel->lab != UASM_LABEL_INVALID; rel++)
+		if (rel->addr >= first && rel->addr < end)
+			rel->addr += off;
+}
+
+void __init
+uasm_move_labels(struct uasm_label *lab, u32 *first, u32 *end, long off)
+{
+	for (; lab->lab != UASM_LABEL_INVALID; lab++)
+		if (lab->addr >= first && lab->addr < end)
+			lab->addr += off;
+}
+
+void __init
+uasm_copy_handler(struct uasm_reloc *rel, struct uasm_label *lab, u32 *first,
+		  u32 *end, u32 *target)
+{
+	long off = (long)(target - first);
+
+	memcpy(target, first, (end - first) * sizeof(u32));
+
+	uasm_move_relocs(rel, first, end, off);
+	uasm_move_labels(lab, first, end, off);
+}
+
+int __init uasm_insn_has_bdelay(struct uasm_reloc *rel, u32 *addr)
+{
+	for (; rel->lab != UASM_LABEL_INVALID; rel++) {
+		if (rel->addr == addr
+		    && (rel->type == R_MIPS_PC16
+			|| rel->type == R_MIPS_26))
+			return 1;
+	}
+
+	return 0;
+}
+
+/* Convenience functions for labeled branches. */
+void __init
+uasm_il_bltz(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid)
+{
+	uasm_r_mips_pc16(r, *p, lid);
+	uasm_i_bltz(p, reg, 0);
+}
+
+void __init
+uasm_il_b(u32 **p, struct uasm_reloc **r, int lid)
+{
+	uasm_r_mips_pc16(r, *p, lid);
+	uasm_i_b(p, 0);
+}
+
+void __init
+uasm_il_beqz(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid)
+{
+	uasm_r_mips_pc16(r, *p, lid);
+	uasm_i_beqz(p, reg, 0);
+}
+
+void __init
+uasm_il_beqzl(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid)
+{
+	uasm_r_mips_pc16(r, *p, lid);
+	uasm_i_beqzl(p, reg, 0);
+}
+
+void __init
+uasm_il_bnez(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid)
+{
+	uasm_r_mips_pc16(r, *p, lid);
+	uasm_i_bnez(p, reg, 0);
+}
+
+void __init
+uasm_il_bgezl(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid)
+{
+	uasm_r_mips_pc16(r, *p, lid);
+	uasm_i_bgezl(p, reg, 0);
+}
+
+void __init
+uasm_il_bgez(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid)
+{
+	uasm_r_mips_pc16(r, *p, lid);
+	uasm_i_bgez(p, reg, 0);
+}
diff --git a/arch/mips/mm/uasm.h b/arch/mips/mm/uasm.h
new file mode 100644
index 0000000..a10fc11
--- /dev/null
+++ b/arch/mips/mm/uasm.h
@@ -0,0 +1,192 @@
+/*
+ * 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, 2005, 2006, 2008  Thiemo Seufer
+ * Copyright (C) 2005  Maciej W. Rozycki
+ * Copyright (C) 2006  Ralf Baechle (ralf@linux-mips.org)
+ */
+
+#include <linux/types.h>
+
+#define Ip_u1u2u3(op)							\
+void __init								\
+uasm_i##op(u32 **buf, unsigned int a, unsigned int b, unsigned int c)
+
+#define Ip_u2u1u3(op)							\
+void __init								\
+uasm_i##op(u32 **buf, unsigned int a, unsigned int b, unsigned int c)
+
+#define Ip_u3u1u2(op)							\
+void __init								\
+uasm_i##op(u32 **buf, unsigned int a, unsigned int b, unsigned int c)
+
+#define Ip_u1u2s3(op)							\
+void __init								\
+uasm_i##op(u32 **buf, unsigned int a, unsigned int b, signed int c)
+
+#define Ip_u2s3u1(op)							\
+void __init								\
+uasm_i##op(u32 **buf, unsigned int a, signed int b, unsigned int c)
+
+#define Ip_u2u1s3(op)							\
+void __init								\
+uasm_i##op(u32 **buf, unsigned int a, unsigned int b, signed int c)
+
+#define Ip_u1u2(op)							\
+void __init uasm_i##op(u32 **buf, unsigned int a, unsigned int b)
+
+#define Ip_u1s2(op)							\
+void __init uasm_i##op(u32 **buf, unsigned int a, signed int b)
+
+#define Ip_u1(op) void __init uasm_i##op(u32 **buf, unsigned int a)
+
+#define Ip_0(op) void __init uasm_i##op(u32 **buf)
+
+Ip_u2u1s3(_addiu);
+Ip_u3u1u2(_addu);
+Ip_u2u1u3(_andi);
+Ip_u3u1u2(_and);
+Ip_u1u2s3(_beq);
+Ip_u1u2s3(_beql);
+Ip_u1s2(_bgez);
+Ip_u1s2(_bgezl);
+Ip_u1s2(_bltz);
+Ip_u1s2(_bltzl);
+Ip_u1u2s3(_bne);
+Ip_u1u2u3(_dmfc0);
+Ip_u1u2u3(_dmtc0);
+Ip_u2u1s3(_daddiu);
+Ip_u3u1u2(_daddu);
+Ip_u2u1u3(_dsll);
+Ip_u2u1u3(_dsll32);
+Ip_u2u1u3(_dsra);
+Ip_u2u1u3(_dsrl);
+Ip_u2u1u3(_dsrl32);
+Ip_u3u1u2(_dsubu);
+Ip_0(_eret);
+Ip_u1(_j);
+Ip_u1(_jal);
+Ip_u1(_jr);
+Ip_u2s3u1(_ld);
+Ip_u2s3u1(_ll);
+Ip_u2s3u1(_lld);
+Ip_u1s2(_lui);
+Ip_u2s3u1(_lw);
+Ip_u1u2u3(_mfc0);
+Ip_u1u2u3(_mtc0);
+Ip_u2u1u3(_ori);
+Ip_0(_rfe);
+Ip_u2s3u1(_sc);
+Ip_u2s3u1(_scd);
+Ip_u2s3u1(_sd);
+Ip_u2u1u3(_sll);
+Ip_u2u1u3(_sra);
+Ip_u2u1u3(_srl);
+Ip_u3u1u2(_subu);
+Ip_u2s3u1(_sw);
+Ip_0(_tlbp);
+Ip_0(_tlbwi);
+Ip_0(_tlbwr);
+Ip_u3u1u2(_xor);
+Ip_u2u1u3(_xori);
+
+/* Handle labels. */
+struct uasm_label {
+	u32 *addr;
+	int lab;
+};
+
+void __init uasm_build_label(struct uasm_label **lab, u32 *addr, int lid);
+#ifdef CONFIG_64BIT
+int __init uasm_in_compat_space_p(long addr);
+int __init uasm_rel_highest(long val);
+int __init uasm_rel_higher(long val);
+#endif
+int __init uasm_rel_hi(long val);
+int __init uasm_rel_lo(long val);
+void __init UASM_i_LA_mostly(u32 **buf, unsigned int rs, long addr);
+void __init UASM_i_LA(u32 **buf, unsigned int rs, long addr);
+
+#define UASM_L_LA(lb)							\
+static inline void __init uasm_l##lb(struct uasm_label **lab, u32 *addr) \
+{									\
+	uasm_build_label(lab, addr, label##lb);				\
+}
+
+/* convenience macros for instructions */
+#ifdef CONFIG_64BIT
+# define UASM_i_LW(buf, rs, rt, off) uasm_i_ld(buf, rs, rt, off)
+# define UASM_i_SW(buf, rs, rt, off) uasm_i_sd(buf, rs, rt, off)
+# define UASM_i_SLL(buf, rs, rt, sh) uasm_i_dsll(buf, rs, rt, sh)
+# define UASM_i_SRA(buf, rs, rt, sh) uasm_i_dsra(buf, rs, rt, sh)
+# define UASM_i_SRL(buf, rs, rt, sh) uasm_i_dsrl(buf, rs, rt, sh)
+# define UASM_i_MFC0(buf, rt, rd...) uasm_i_dmfc0(buf, rt, rd)
+# define UASM_i_MTC0(buf, rt, rd...) uasm_i_dmtc0(buf, rt, rd)
+# define UASM_i_ADDIU(buf, rs, rt, val) uasm_i_daddiu(buf, rs, rt, val)
+# define UASM_i_ADDU(buf, rs, rt, rd) uasm_i_daddu(buf, rs, rt, rd)
+# define UASM_i_SUBU(buf, rs, rt, rd) uasm_i_dsubu(buf, rs, rt, rd)
+# define UASM_i_LL(buf, rs, rt, off) uasm_i_lld(buf, rs, rt, off)
+# define UASM_i_SC(buf, rs, rt, off) uasm_i_scd(buf, rs, rt, off)
+#else
+# define UASM_i_LW(buf, rs, rt, off) uasm_i_lw(buf, rs, rt, off)
+# define UASM_i_SW(buf, rs, rt, off) uasm_i_sw(buf, rs, rt, off)
+# define UASM_i_SLL(buf, rs, rt, sh) uasm_i_sll(buf, rs, rt, sh)
+# define UASM_i_SRA(buf, rs, rt, sh) uasm_i_sra(buf, rs, rt, sh)
+# define UASM_i_SRL(buf, rs, rt, sh) uasm_i_srl(buf, rs, rt, sh)
+# define UASM_i_MFC0(buf, rt, rd...) uasm_i_mfc0(buf, rt, rd)
+# define UASM_i_MTC0(buf, rt, rd...) uasm_i_mtc0(buf, rt, rd)
+# define UASM_i_ADDIU(buf, rs, rt, val) uasm_i_addiu(buf, rs, rt, val)
+# define UASM_i_ADDU(buf, rs, rt, rd) uasm_i_addu(buf, rs, rt, rd)
+# define UASM_i_SUBU(buf, rs, rt, rd) uasm_i_subu(buf, rs, rt, rd)
+# define UASM_i_LL(buf, rs, rt, off) uasm_i_ll(buf, rs, rt, off)
+# define UASM_i_SC(buf, rs, rt, off) uasm_i_sc(buf, rs, rt, off)
+#endif
+
+#define uasm_i_b(buf, off) uasm_i_beq(buf, 0, 0, off)
+#define uasm_i_beqz(buf, rs, off) uasm_i_beq(buf, rs, 0, off)
+#define uasm_i_beqzl(buf, rs, off) uasm_i_beql(buf, rs, 0, off)
+#define uasm_i_bnez(buf, rs, off) uasm_i_bne(buf, rs, 0, off)
+#define uasm_i_bnezl(buf, rs, off) uasm_i_bnel(buf, rs, 0, off)
+#define uasm_i_move(buf, a, b) UASM_i_ADDU(buf, a, 0, b)
+#define uasm_i_nop(buf) uasm_i_sll(buf, 0, 0, 0)
+#define uasm_i_ssnop(buf) uasm_i_sll(buf, 0, 0, 1)
+#define uasm_i_ehb(buf) uasm_i_sll(buf, 0, 0, 3)
+
+/* Handle relocations. */
+struct uasm_reloc {
+	u32 *addr;
+	unsigned int type;
+	int lab;
+};
+
+/* This is zero so we can use zeroed label arrays. */
+#define UASM_LABEL_INVALID 0
+
+void __init uasm_r_mips_pc16(struct uasm_reloc **rel, u32 *addr, int lid);
+void __init
+uasm_resolve_relocs(struct uasm_reloc *rel, struct uasm_label *lab);
+void __init
+uasm_move_relocs(struct uasm_reloc *rel, u32 *first, u32 *end, long off);
+void __init
+uasm_move_labels(struct uasm_label *lab, u32 *first, u32 *end, long off);
+void __init
+uasm_copy_handler(struct uasm_reloc *rel, struct uasm_label *lab, u32 *first,
+		  u32 *end, u32 *target);
+int __init uasm_insn_has_bdelay(struct uasm_reloc *rel, u32 *addr);
+
+/* Convenience functions for labeled branches. */
+void __init
+uasm_il_bltz(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid);
+void __init uasm_il_b(u32 **p, struct uasm_reloc **r, int lid);
+void __init
+uasm_il_beqz(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid);
+void __init
+uasm_il_beqzl(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid);
+void __init
+uasm_il_bnez(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid);
+void __init
+uasm_il_bgezl(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid);
+void __init
+uasm_il_bgez(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid);
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 9c44af3..4a22c99 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -151,11 +151,25 @@
 config REDBOOT
 	bool
 
-config PPC64_SWSUSP
+config HIBERNATE_32
 	bool
-	depends on PPC64 && (BROKEN || (PPC_PMAC64 && EXPERIMENTAL))
+	depends on (PPC_PMAC && !SMP) || BROKEN
 	default y
 
+config HIBERNATE_64
+	bool
+	depends on BROKEN || (PPC_PMAC64 && EXPERIMENTAL)
+	default y
+
+config ARCH_HIBERNATION_POSSIBLE
+	bool
+	depends on (PPC64 && HIBERNATE_64) || (PPC32 && HIBERNATE_32)
+	default y
+
+config ARCH_SUSPEND_POSSIBLE
+	def_bool y
+	depends on ADB_PMU || PPC_EFIKA || PPC_LITE5200
+
 config PPC_DCR_NATIVE
 	bool
 	default n
@@ -391,6 +405,10 @@
 	  most cases you will need to specify the root device here.
 
 if !44x || BROKEN
+config ARCH_WANTS_FREEZER_CONTROL
+	def_bool y
+	depends on ADB_PMU
+
 source kernel/power/Kconfig
 endif
 
diff --git a/arch/powerpc/platforms/52xx/lite5200_pm.c b/arch/powerpc/platforms/52xx/lite5200_pm.c
index c0f13e8..41c7fd9 100644
--- a/arch/powerpc/platforms/52xx/lite5200_pm.c
+++ b/arch/powerpc/platforms/52xx/lite5200_pm.c
@@ -31,7 +31,7 @@
 	}
 }
 
-static int lite5200_pm_set_target(suspend_state_t state)
+static int lite5200_pm_begin(suspend_state_t state)
 {
 	if (lite5200_pm_valid(state)) {
 		lite5200_pm_target_state = state;
@@ -219,12 +219,18 @@
 		mpc52xx_pm_finish();
 }
 
+static void lite5200_pm_end(void)
+{
+	lite5200_pm_target_state = PM_SUSPEND_ON;
+}
+
 static struct platform_suspend_ops lite5200_pm_ops = {
 	.valid		= lite5200_pm_valid,
-	.set_target	= lite5200_pm_set_target,
+	.begin		= lite5200_pm_begin,
 	.prepare	= lite5200_pm_prepare,
 	.enter		= lite5200_pm_enter,
 	.finish		= lite5200_pm_finish,
+	.end		= lite5200_pm_end,
 };
 
 int __init lite5200_pm_init(void)
diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig
index 1cd9c8f..b30c4c3 100644
--- a/arch/sh/Kconfig
+++ b/arch/sh/Kconfig
@@ -882,6 +882,10 @@
 menu "Power management options (EXPERIMENTAL)"
 depends on EXPERIMENTAL && SYS_SUPPORTS_PM
 
+config ARCH_SUSPEND_POSSIBLE
+	def_bool y
+	depends on !SMP
+
 source kernel/power/Kconfig
 
 endmenu
diff --git a/arch/sh/drivers/pci/Kconfig b/arch/sh/drivers/pci/Kconfig
index fbc6f2c..7e816ed 100644
--- a/arch/sh/drivers/pci/Kconfig
+++ b/arch/sh/drivers/pci/Kconfig
@@ -6,11 +6,6 @@
 	  bus system, i.e. the way the CPU talks to the other stuff inside
 	  your box. If you have PCI, say Y, otherwise N.
 
-	  The PCI-HOWTO, available from
-	  <http://www.tldp.org/docs.html#howto>, contains valuable
-	  information about which PCI hardware does work under Linux and which
-	  doesn't.
-
 config SH_PCIDMA_NONCOHERENT
 	bool "Cache and PCI noncoherent"
 	depends on PCI
diff --git a/arch/sparc64/Kconfig b/arch/sparc64/Kconfig
index 73fc05d..158522f 100644
--- a/arch/sparc64/Kconfig
+++ b/arch/sparc64/Kconfig
@@ -351,11 +351,6 @@
 	  your box. Other bus systems are ISA, EISA, MicroChannel (MCA) or
 	  VESA. If you have PCI, say Y, otherwise N.
 
-	  The PCI-HOWTO, available from
-	  <http://www.tldp.org/docs.html#howto>, contains valuable
-	  information about which PCI hardware does work under Linux and which
-	  doesn't.
-
 config PCI_DOMAINS
 	def_bool PCI
 
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 65b4491..7109037 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -44,6 +44,9 @@
 config STACKTRACE_SUPPORT
 	def_bool y
 
+config HAVE_LATENCYTOP_SUPPORT
+	def_bool y
+
 config SEMAPHORE_SLEEPERS
 	def_bool y
 
@@ -109,6 +112,14 @@
 
 select HAVE_KVM
 
+config ARCH_HIBERNATION_POSSIBLE
+	def_bool y
+	depends on !SMP || !X86_VOYAGER
+
+config ARCH_SUSPEND_POSSIBLE
+	def_bool y
+	depends on !X86_VOYAGER
+
 config ZONE_DMA32
 	bool
 	default X86_64
@@ -1366,11 +1377,6 @@
 	  your box. Other bus systems are ISA, EISA, MicroChannel (MCA) or
 	  VESA. If you have PCI, say Y, otherwise N.
 
-	  The PCI-HOWTO, available from
-	  <http://www.tldp.org/docs.html#howto>, contains valuable
-	  information about which PCI hardware does work under Linux and which
-	  doesn't.
-
 choice
 	prompt "PCI access mode"
 	depends on X86_32 && PCI && !X86_VISWS
diff --git a/arch/x86/boot/compressed/vmlinux_64.lds b/arch/x86/boot/compressed/vmlinux_64.lds
index f6e5b44..7e5c720 100644
--- a/arch/x86/boot/compressed/vmlinux_64.lds
+++ b/arch/x86/boot/compressed/vmlinux_64.lds
@@ -3,7 +3,7 @@
 ENTRY(startup_64)
 SECTIONS
 {
-	/* Be careful parts of head_64.S assume startup_64 is at
+	/* Be careful parts of head_64.S assume startup_32 is at
 	 * address 0.
 	 */
 	. = 0;
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index 0ca27c7..d2a5843 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -496,7 +496,8 @@
  *  ACPI based hotplug support for CPU
  */
 #ifdef CONFIG_ACPI_HOTPLUG_CPU
-int acpi_map_lsapic(acpi_handle handle, int *pcpu)
+
+static int __cpuinit _acpi_map_lsapic(acpi_handle handle, int *pcpu)
 {
 	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
 	union acpi_object *obj;
@@ -551,6 +552,11 @@
 	return 0;
 }
 
+/* wrapper to silence section mismatch warning */
+int __ref acpi_map_lsapic(acpi_handle handle, int *pcpu)
+{
+	return _acpi_map_lsapic(handle, pcpu);
+}
 EXPORT_SYMBOL(acpi_map_lsapic);
 
 int acpi_unmap_lsapic(int cpu)
diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c
index 06fa159..693e353 100644
--- a/arch/x86/kernel/cpu/amd.c
+++ b/arch/x86/kernel/cpu/amd.c
@@ -304,7 +304,7 @@
 	if (c->x86 < 6)
 		clear_bit(X86_FEATURE_MCE, c->x86_capability);
 
-	if (cpu_has_xmm)
+	if (cpu_has_xmm2)
 		set_bit(X86_FEATURE_MFENCE_RDTSC, c->x86_capability);
 }
 
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index d608c9e..b7b2142 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -258,10 +258,10 @@
 void __init cpu_detect(struct cpuinfo_x86 *c)
 {
 	/* Get vendor name */
-	cpuid(0x00000000, &c->cpuid_level,
-	      (int *)&c->x86_vendor_id[0],
-	      (int *)&c->x86_vendor_id[8],
-	      (int *)&c->x86_vendor_id[4]);
+	cpuid(0x00000000, (unsigned int *)&c->cpuid_level,
+	      (unsigned int *)&c->x86_vendor_id[0],
+	      (unsigned int *)&c->x86_vendor_id[8],
+	      (unsigned int *)&c->x86_vendor_id[4]);
 
 	c->x86 = 4;
 	if (c->cpuid_level >= 0x00000001) {
@@ -283,7 +283,7 @@
 static void __cpuinit early_get_cap(struct cpuinfo_x86 *c)
 {
 	u32 tfms, xlvl;
-	int ebx;
+	unsigned int ebx;
 
 	memset(&c->x86_capability, 0, sizeof c->x86_capability);
 	if (have_cpuid_p()) {
@@ -343,14 +343,14 @@
 static void __cpuinit generic_identify(struct cpuinfo_x86 * c)
 {
 	u32 tfms, xlvl;
-	int ebx;
+	unsigned int ebx;
 
 	if (have_cpuid_p()) {
 		/* Get vendor name */
-		cpuid(0x00000000, &c->cpuid_level,
-		      (int *)&c->x86_vendor_id[0],
-		      (int *)&c->x86_vendor_id[8],
-		      (int *)&c->x86_vendor_id[4]);
+		cpuid(0x00000000, (unsigned int *)&c->cpuid_level,
+		      (unsigned int *)&c->x86_vendor_id[0],
+		      (unsigned int *)&c->x86_vendor_id[8],
+		      (unsigned int *)&c->x86_vendor_id[4]);
 		
 		get_cpu_vendor(c, 0);
 		/* Initialize the standard set of capabilities */
diff --git a/arch/x86/kernel/cpuid.c b/arch/x86/kernel/cpuid.c
index dec66e4..a63432d 100644
--- a/arch/x86/kernel/cpuid.c
+++ b/arch/x86/kernel/cpuid.c
@@ -170,7 +170,7 @@
 	return err ? NOTIFY_BAD : NOTIFY_OK;
 }
 
-static struct notifier_block __cpuinitdata cpuid_class_cpu_notifier =
+static struct notifier_block __refdata cpuid_class_cpu_notifier =
 {
 	.notifier_call = cpuid_class_cpu_callback,
 };
diff --git a/arch/x86/kernel/e820_64.c b/arch/x86/kernel/e820_64.c
index c617174..9f65b4c 100644
--- a/arch/x86/kernel/e820_64.c
+++ b/arch/x86/kernel/e820_64.c
@@ -54,30 +54,33 @@
 
 struct early_res {
 	unsigned long start, end;
+	char name[16];
 };
 static struct early_res early_res[MAX_EARLY_RES] __initdata = {
-	{ 0, PAGE_SIZE },			/* BIOS data page */
+	{ 0, PAGE_SIZE, "BIOS data page" },			/* BIOS data page */
 #ifdef CONFIG_SMP
-	{ SMP_TRAMPOLINE_BASE, SMP_TRAMPOLINE_BASE + 2*PAGE_SIZE },
+	{ SMP_TRAMPOLINE_BASE, SMP_TRAMPOLINE_BASE + 2*PAGE_SIZE, "SMP_TRAMPOLINE" },
 #endif
 	{}
 };
 
-void __init reserve_early(unsigned long start, unsigned long end)
+void __init reserve_early(unsigned long start, unsigned long end, char *name)
 {
 	int i;
 	struct early_res *r;
 	for (i = 0; i < MAX_EARLY_RES && early_res[i].end; i++) {
 		r = &early_res[i];
 		if (end > r->start && start < r->end)
-			panic("Overlapping early reservations %lx-%lx to %lx-%lx\n",
-			      start, end, r->start, r->end);
+			panic("Overlapping early reservations %lx-%lx %s to %lx-%lx %s\n",
+			      start, end - 1, name?name:"", r->start, r->end - 1, r->name);
 	}
 	if (i >= MAX_EARLY_RES)
 		panic("Too many early reservations");
 	r = &early_res[i];
 	r->start = start;
 	r->end = end;
+	if (name)
+		strncpy(r->name, name, sizeof(r->name) - 1);
 }
 
 void __init early_res_to_bootmem(void)
@@ -85,6 +88,8 @@
 	int i;
 	for (i = 0; i < MAX_EARLY_RES && early_res[i].end; i++) {
 		struct early_res *r = &early_res[i];
+		printk(KERN_INFO "early res: %d [%lx-%lx] %s\n", i,
+			r->start, r->end - 1, r->name);
 		reserve_bootmem_generic(r->start, r->end - r->start);
 	}
 }
@@ -166,12 +171,13 @@
 }
 
 /*
- * Find a free area in a specific range.
+ * Find a free area with specified alignment in a specific range.
  */
 unsigned long __init find_e820_area(unsigned long start, unsigned long end,
-				    unsigned size)
+				    unsigned size, unsigned long align)
 {
 	int i;
+	unsigned long mask = ~(align - 1);
 
 	for (i = 0; i < e820.nr_map; i++) {
 		struct e820entry *ei = &e820.map[i];
@@ -185,7 +191,8 @@
 			continue;
 		while (bad_addr(&addr, size) && addr+size <= ei->addr+ei->size)
 			;
-		last = PAGE_ALIGN(addr) + size;
+		addr = (addr + align - 1) & mask;
+		last = addr + size;
 		if (last > ei->addr + ei->size)
 			continue;
 		if (last > end)
diff --git a/arch/x86/kernel/early_printk.c b/arch/x86/kernel/early_printk.c
index b7d6c23..cff84cd 100644
--- a/arch/x86/kernel/early_printk.c
+++ b/arch/x86/kernel/early_printk.c
@@ -193,7 +193,7 @@
 };
 
 /* Direct interface for emergencies */
-struct console *early_console = &early_vga_console;
+static struct console *early_console = &early_vga_console;
 static int early_console_initialized = 0;
 
 void early_printk(const char *fmt, ...)
diff --git a/arch/x86/kernel/efi_64.c b/arch/x86/kernel/efi_64.c
index 4b73992..674f237 100644
--- a/arch/x86/kernel/efi_64.c
+++ b/arch/x86/kernel/efi_64.c
@@ -44,7 +44,7 @@
 					  int executable)
 {
 	pte_t *kpte;
-	int level;
+	unsigned int level;
 
 	while (start < end) {
 		kpte = lookup_address((unsigned long)__va(start), &level);
diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c
index a317336..24dbf56 100644
--- a/arch/x86/kernel/head64.c
+++ b/arch/x86/kernel/head64.c
@@ -75,7 +75,7 @@
 	if (ebda_size > 64*1024)
 		ebda_size = 64*1024;
 
-	reserve_early(ebda_addr, ebda_addr + ebda_size);
+	reserve_early(ebda_addr, ebda_addr + ebda_size, "EBDA");
 }
 
 void __init x86_64_start_kernel(char * real_mode_data)
@@ -105,14 +105,14 @@
 	pda_init(0);
 	copy_bootdata(__va(real_mode_data));
 
-	reserve_early(__pa_symbol(&_text), __pa_symbol(&_end));
+	reserve_early(__pa_symbol(&_text), __pa_symbol(&_end), "TEXT DATA BSS");
 
 	/* Reserve INITRD */
 	if (boot_params.hdr.type_of_loader && boot_params.hdr.ramdisk_image) {
 		unsigned long ramdisk_image = boot_params.hdr.ramdisk_image;
 		unsigned long ramdisk_size  = boot_params.hdr.ramdisk_size;
 		unsigned long ramdisk_end   = ramdisk_image + ramdisk_size;
-		reserve_early(ramdisk_image, ramdisk_end);
+		reserve_early(ramdisk_image, ramdisk_end, "RAMDISK");
 	}
 
 	reserve_ebda();
diff --git a/arch/x86/kernel/microcode.c b/arch/x86/kernel/microcode.c
index 6ff447f..f2702d0 100644
--- a/arch/x86/kernel/microcode.c
+++ b/arch/x86/kernel/microcode.c
@@ -797,7 +797,7 @@
 	return NOTIFY_OK;
 }
 
-static struct notifier_block __cpuinitdata mc_cpu_notifier = {
+static struct notifier_block __refdata mc_cpu_notifier = {
 	.notifier_call = mc_cpu_callback,
 };
 
diff --git a/arch/x86/kernel/msr.c b/arch/x86/kernel/msr.c
index 21f6e3c..bd82850 100644
--- a/arch/x86/kernel/msr.c
+++ b/arch/x86/kernel/msr.c
@@ -168,7 +168,7 @@
 	return err ? NOTIFY_BAD : NOTIFY_OK;
 }
 
-static struct notifier_block __cpuinitdata msr_class_cpu_notifier = {
+static struct notifier_block __refdata msr_class_cpu_notifier = {
 	.notifier_call = msr_class_cpu_callback,
 };
 
diff --git a/arch/x86/kernel/pci-calgary_64.c b/arch/x86/kernel/pci-calgary_64.c
index 21f34db..1fe7f04 100644
--- a/arch/x86/kernel/pci-calgary_64.c
+++ b/arch/x86/kernel/pci-calgary_64.c
@@ -1006,7 +1006,7 @@
 	readq(target); /* flush */
 }
 
-static void calioc2_handle_quirks(struct iommu_table *tbl, struct pci_dev *dev)
+static void __init calioc2_handle_quirks(struct iommu_table *tbl, struct pci_dev *dev)
 {
 	unsigned char busnum = dev->bus->number;
 	void __iomem *bbar = tbl->bbar;
@@ -1022,7 +1022,7 @@
 	writel(cpu_to_be32(val), target);
 }
 
-static void calgary_handle_quirks(struct iommu_table *tbl, struct pci_dev *dev)
+static void __init calgary_handle_quirks(struct iommu_table *tbl, struct pci_dev *dev)
 {
 	unsigned char busnum = dev->bus->number;
 
diff --git a/arch/x86/kernel/quirks.c b/arch/x86/kernel/quirks.c
index 150ba29..3cd7a2d 100644
--- a/arch/x86/kernel/quirks.c
+++ b/arch/x86/kernel/quirks.c
@@ -30,8 +30,8 @@
 	raw_pci_ops->read(0, 0, 0x40, 0x4c, 2, &word);
 
 	if (!(word & (1 << 13))) {
-		printk(KERN_INFO "Intel E7520/7320/7525 detected. "
-			"Disabling irq balancing and affinity\n");
+		dev_info(&dev->dev, "Intel E7520/7320/7525 detected; "
+			"disabling irq balancing and affinity\n");
 #ifdef CONFIG_IRQBALANCE
 		irqbalance_disable("");
 #endif
@@ -104,14 +104,16 @@
 	pci_read_config_dword(dev, 0xF0, &rcba);
 	rcba &= 0xFFFFC000;
 	if (rcba == 0) {
-		printk(KERN_DEBUG "RCBA disabled. Cannot force enable HPET\n");
+		dev_printk(KERN_DEBUG, &dev->dev, "RCBA disabled; "
+			"cannot force enable HPET\n");
 		return;
 	}
 
 	/* use bits 31:14, 16 kB aligned */
 	rcba_base = ioremap_nocache(rcba, 0x4000);
 	if (rcba_base == NULL) {
-		printk(KERN_DEBUG "ioremap failed. Cannot force enable HPET\n");
+		dev_printk(KERN_DEBUG, &dev->dev, "ioremap failed; "
+			"cannot force enable HPET\n");
 		return;
 	}
 
@@ -122,8 +124,8 @@
 		/* HPET is enabled in HPTC. Just not reported by BIOS */
 		val = val & 0x3;
 		force_hpet_address = 0xFED00000 | (val << 12);
-		printk(KERN_DEBUG "Force enabled HPET at base address 0x%lx\n",
-			       force_hpet_address);
+		dev_printk(KERN_DEBUG, &dev->dev, "Force enabled HPET at "
+			"0x%lx\n", force_hpet_address);
 		iounmap(rcba_base);
 		return;
 	}
@@ -142,11 +144,12 @@
 	if (err) {
 		force_hpet_address = 0;
 		iounmap(rcba_base);
-		printk(KERN_DEBUG "Failed to force enable HPET\n");
+		dev_printk(KERN_DEBUG, &dev->dev,
+			"Failed to force enable HPET\n");
 	} else {
 		force_hpet_resume_type = ICH_FORCE_HPET_RESUME;
-		printk(KERN_DEBUG "Force enabled HPET at base address 0x%lx\n",
-			       force_hpet_address);
+		dev_printk(KERN_DEBUG, &dev->dev, "Force enabled HPET at "
+			"0x%lx\n", force_hpet_address);
 	}
 }
 
@@ -208,8 +211,8 @@
 	if (val & 0x4) {
 		val &= 0x3;
 		force_hpet_address = 0xFED00000 | (val << 12);
-		printk(KERN_DEBUG "HPET at base address 0x%lx\n",
-			       force_hpet_address);
+		dev_printk(KERN_DEBUG, &dev->dev, "HPET at 0x%lx\n",
+			force_hpet_address);
 		return;
 	}
 
@@ -229,14 +232,14 @@
 		/* HPET is enabled in HPTC. Just not reported by BIOS */
 		val &= 0x3;
 		force_hpet_address = 0xFED00000 | (val << 12);
-		printk(KERN_DEBUG "Force enabled HPET at base address 0x%lx\n",
-			       force_hpet_address);
+		dev_printk(KERN_DEBUG, &dev->dev, "Force enabled HPET at "
+			"0x%lx\n", force_hpet_address);
 		cached_dev = dev;
 		force_hpet_resume_type = OLD_ICH_FORCE_HPET_RESUME;
 		return;
 	}
 
-	printk(KERN_DEBUG "Failed to force enable HPET\n");
+	dev_printk(KERN_DEBUG, &dev->dev, "Failed to force enable HPET\n");
 }
 
 /*
@@ -294,8 +297,8 @@
 	 */
 	if (val & 0x80) {
 		force_hpet_address = (val & ~0x3ff);
-		printk(KERN_DEBUG "HPET at base address 0x%lx\n",
-			       force_hpet_address);
+		dev_printk(KERN_DEBUG, &dev->dev, "HPET at 0x%lx\n",
+			force_hpet_address);
 		return;
 	}
 
@@ -309,14 +312,14 @@
 	pci_read_config_dword(dev, 0x68, &val);
 	if (val & 0x80) {
 		force_hpet_address = (val & ~0x3ff);
-		printk(KERN_DEBUG "Force enabled HPET at base address 0x%lx\n",
-			       force_hpet_address);
+		dev_printk(KERN_DEBUG, &dev->dev, "Force enabled HPET at "
+			"0x%lx\n", force_hpet_address);
 		cached_dev = dev;
 		force_hpet_resume_type = VT8237_FORCE_HPET_RESUME;
 		return;
 	}
 
-	printk(KERN_DEBUG "Failed to force enable HPET\n");
+	dev_printk(KERN_DEBUG, &dev->dev, "Failed to force enable HPET\n");
 }
 
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8235,
@@ -344,7 +347,7 @@
 	pci_read_config_dword(dev, 0x44, &val);
 	force_hpet_address = val & 0xfffffffe;
 	force_hpet_resume_type = NVIDIA_FORCE_HPET_RESUME;
-	printk(KERN_DEBUG "Force enabled HPET at base address 0x%lx\n",
+	dev_printk(KERN_DEBUG, &dev->dev, "Force enabled HPET at 0x%lx\n",
 		force_hpet_address);
 	cached_dev = dev;
 	return;
diff --git a/arch/x86/kernel/setup_64.c b/arch/x86/kernel/setup_64.c
index 77fb87b..18df70c 100644
--- a/arch/x86/kernel/setup_64.c
+++ b/arch/x86/kernel/setup_64.c
@@ -182,7 +182,8 @@
 	unsigned long bootmap_size, bootmap;
 
 	bootmap_size = bootmem_bootmap_pages(end_pfn)<<PAGE_SHIFT;
-	bootmap = find_e820_area(0, end_pfn<<PAGE_SHIFT, bootmap_size);
+	bootmap = find_e820_area(0, end_pfn<<PAGE_SHIFT, bootmap_size,
+				 PAGE_SIZE);
 	if (bootmap == -1L)
 		panic("Cannot find bootmem map of size %ld\n", bootmap_size);
 	bootmap_size = init_bootmem(bootmap >> PAGE_SHIFT, end_pfn);
diff --git a/arch/x86/kernel/smpboot_64.c b/arch/x86/kernel/smpboot_64.c
index cc64b80..d53bd6f 100644
--- a/arch/x86/kernel/smpboot_64.c
+++ b/arch/x86/kernel/smpboot_64.c
@@ -1019,7 +1019,7 @@
 	cpu_clear(cpu, cpu_sibling_setup_map);
 }
 
-void remove_cpu_from_maps(void)
+static void __ref remove_cpu_from_maps(void)
 {
 	int cpu = smp_processor_id();
 
diff --git a/arch/x86/kernel/suspend_64.c b/arch/x86/kernel/suspend_64.c
index 0919951..7ac7130 100644
--- a/arch/x86/kernel/suspend_64.c
+++ b/arch/x86/kernel/suspend_64.c
@@ -140,7 +140,12 @@
 	int cpu = smp_processor_id();
 	struct tss_struct *t = &per_cpu(init_tss, cpu);
 
-	set_tss_desc(cpu,t);	/* This just modifies memory; should not be necessary. But... This is necessary, because 386 hardware has concept of busy TSS or some similar stupidity. */
+	/*
+	 * This just modifies memory; should not be necessary. But... This
+	 * is necessary, because 386 hardware has concept of busy TSS or some
+	 * similar stupidity.
+	 */
+	set_tss_desc(cpu, t);
 
 	get_cpu_gdt_table(cpu)[GDT_ENTRY_TSS].type = 9;
 
@@ -160,7 +165,6 @@
                 loaddebug(&current->thread, 6);
                 loaddebug(&current->thread, 7);
 	}
-
 }
 
 #ifdef CONFIG_HIBERNATION
diff --git a/arch/x86/kernel/topology.c b/arch/x86/kernel/topology.c
index 78cbb65..e6757aa 100644
--- a/arch/x86/kernel/topology.c
+++ b/arch/x86/kernel/topology.c
@@ -57,11 +57,10 @@
 }
 EXPORT_SYMBOL(arch_unregister_cpu);
 #else
-int arch_register_cpu(int num)
+static int __init arch_register_cpu(int num)
 {
 	return register_cpu(&per_cpu(cpu_devices, num).cpu, num);
 }
-EXPORT_SYMBOL(arch_register_cpu);
 #endif /*CONFIG_HOTPLUG_CPU*/
 
 static int __init topology_init(void)
diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c
index e28cc52..e4440d0 100644
--- a/arch/x86/mm/fault.c
+++ b/arch/x86/mm/fault.c
@@ -382,7 +382,7 @@
 
 #ifdef CONFIG_X86_PAE
 	if (error_code & PF_INSTR) {
-		int level;
+		unsigned int level;
 		pte_t *pte = lookup_address(address, &level);
 
 		if (pte && pte_present(*pte) && !pte_exec(*pte))
diff --git a/arch/x86/mm/init_32.c b/arch/x86/mm/init_32.c
index da524fb..f2f36f8 100644
--- a/arch/x86/mm/init_32.c
+++ b/arch/x86/mm/init_32.c
@@ -423,23 +423,23 @@
 	paravirt_pagetable_setup_done(pgd_base);
 }
 
-#if defined(CONFIG_HIBERNATION) || defined(CONFIG_ACPI)
+#ifdef CONFIG_ACPI_SLEEP
 /*
- * Swap suspend & friends need this for resume because things like the intel-agp
+ * ACPI suspend needs this for resume, because things like the intel-agp
  * driver might have split up a kernel 4MB mapping.
  */
-char __nosavedata swsusp_pg_dir[PAGE_SIZE]
+char swsusp_pg_dir[PAGE_SIZE]
 	__attribute__ ((aligned(PAGE_SIZE)));
 
 static inline void save_pg_dir(void)
 {
 	memcpy(swsusp_pg_dir, swapper_pg_dir, PAGE_SIZE);
 }
-#else
+#else /* !CONFIG_ACPI_SLEEP */
 static inline void save_pg_dir(void)
 {
 }
-#endif
+#endif /* !CONFIG_ACPI_SLEEP */
 
 void zap_low_mappings(void)
 {
diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c
index cc50a13..eabcaed 100644
--- a/arch/x86/mm/init_64.c
+++ b/arch/x86/mm/init_64.c
@@ -354,17 +354,10 @@
 	 * need roughly 0.5KB per GB.
 	 */
 	start = 0x8000;
-	table_start = find_e820_area(start, end, tables);
+	table_start = find_e820_area(start, end, tables, PAGE_SIZE);
 	if (table_start == -1UL)
 		panic("Cannot find space for the kernel page tables");
 
-	/*
-	 * When you have a lot of RAM like 256GB, early_table will not fit
-	 * into 0x8000 range, find_e820_area() will find area after kernel
-	 * bss but the table_start is not page aligned, so need to round it
-	 * up to avoid overlap with bss:
-	 */
-	table_start = round_up(table_start, PAGE_SIZE);
 	table_start >>= PAGE_SHIFT;
 	table_end = table_start;
 
@@ -420,7 +413,9 @@
 		mmu_cr4_features = read_cr4();
 	__flush_tlb_all();
 
-	reserve_early(table_start << PAGE_SHIFT, table_end << PAGE_SHIFT);
+	if (!after_bootmem)
+		reserve_early(table_start << PAGE_SHIFT,
+				 table_end << PAGE_SHIFT, "PGTABLE");
 }
 
 #ifndef CONFIG_NUMA
diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c
index a177d76..c004d94 100644
--- a/arch/x86/mm/ioremap.c
+++ b/arch/x86/mm/ioremap.c
@@ -75,7 +75,8 @@
 {
 	unsigned long vaddr = (unsigned long)__va(paddr);
 	unsigned long nrpages = size >> PAGE_SHIFT;
-	int err, level;
+	unsigned int level;
+	int err;
 
 	/* No change for pages after the last mapping */
 	if ((paddr + size - 1) >= (max_pfn_mapped << PAGE_SHIFT))
diff --git a/arch/x86/mm/numa_64.c b/arch/x86/mm/numa_64.c
index dc3b1f7..a920d09 100644
--- a/arch/x86/mm/numa_64.c
+++ b/arch/x86/mm/numa_64.c
@@ -84,26 +84,24 @@
 
 static int __init allocate_cachealigned_memnodemap(void)
 {
-	unsigned long pad, pad_addr;
+	unsigned long addr;
 
 	memnodemap = memnode.embedded_map;
 	if (memnodemapsize <= ARRAY_SIZE(memnode.embedded_map))
 		return 0;
 
-	pad = L1_CACHE_BYTES - 1;
-	pad_addr = 0x8000;
-	nodemap_size = pad + sizeof(s16) * memnodemapsize;
-	nodemap_addr = find_e820_area(pad_addr, end_pfn<<PAGE_SHIFT,
-				      nodemap_size);
+	addr = 0x8000;
+	nodemap_size = round_up(sizeof(s16) * memnodemapsize, L1_CACHE_BYTES);
+	nodemap_addr = find_e820_area(addr, end_pfn<<PAGE_SHIFT,
+				      nodemap_size, L1_CACHE_BYTES);
 	if (nodemap_addr == -1UL) {
 		printk(KERN_ERR
 		       "NUMA: Unable to allocate Memory to Node hash map\n");
 		nodemap_addr = nodemap_size = 0;
 		return -1;
 	}
-	pad_addr = (nodemap_addr + pad) & ~pad;
-	memnodemap = phys_to_virt(pad_addr);
-	reserve_early(nodemap_addr, nodemap_addr + nodemap_size);
+	memnodemap = phys_to_virt(nodemap_addr);
+	reserve_early(nodemap_addr, nodemap_addr + nodemap_size, "MEMNODEMAP");
 
 	printk(KERN_DEBUG "NUMA: Allocated memnodemap from %lx - %lx\n",
 	       nodemap_addr, nodemap_addr + nodemap_size);
@@ -164,15 +162,16 @@
 }
 
 static void * __init early_node_mem(int nodeid, unsigned long start,
-				    unsigned long end, unsigned long size)
+				    unsigned long end, unsigned long size,
+				    unsigned long align)
 {
-	unsigned long mem = find_e820_area(start, end, size);
+	unsigned long mem = find_e820_area(start, end, size, align);
 	void *ptr;
 
 	if (mem != -1L)
 		return __va(mem);
-	ptr = __alloc_bootmem_nopanic(size,
-				SMP_CACHE_BYTES, __pa(MAX_DMA_ADDRESS));
+
+	ptr = __alloc_bootmem_nopanic(size, align, __pa(MAX_DMA_ADDRESS));
 	if (ptr == NULL) {
 		printk(KERN_ERR "Cannot find %lu bytes in node %d\n",
 		       size, nodeid);
@@ -198,7 +197,8 @@
 	start_pfn = start >> PAGE_SHIFT;
 	end_pfn = end >> PAGE_SHIFT;
 
-	node_data[nodeid] = early_node_mem(nodeid, start, end, pgdat_size);
+	node_data[nodeid] = early_node_mem(nodeid, start, end, pgdat_size,
+					   SMP_CACHE_BYTES);
 	if (node_data[nodeid] == NULL)
 		return;
 	nodedata_phys = __pa(node_data[nodeid]);
@@ -211,8 +211,12 @@
 	/* Find a place for the bootmem map */
 	bootmap_pages = bootmem_bootmap_pages(end_pfn - start_pfn);
 	bootmap_start = round_up(nodedata_phys + pgdat_size, PAGE_SIZE);
+	/*
+	 * SMP_CAHCE_BYTES could be enough, but init_bootmem_node like
+	 * to use that to align to PAGE_SIZE
+	 */
 	bootmap = early_node_mem(nodeid, bootmap_start, end,
-					bootmap_pages<<PAGE_SHIFT);
+				 bootmap_pages<<PAGE_SHIFT, PAGE_SIZE);
 	if (bootmap == NULL)  {
 		if (nodedata_phys < start || nodedata_phys >= end)
 			free_bootmem((unsigned long)node_data[nodeid],
diff --git a/arch/x86/mm/pageattr-test.c b/arch/x86/mm/pageattr-test.c
index 06353d43..7573e78 100644
--- a/arch/x86/mm/pageattr-test.c
+++ b/arch/x86/mm/pageattr-test.c
@@ -42,7 +42,7 @@
 	s->max_exec = 0;
 	for (i = 0; i < max_pfn_mapped; ) {
 		unsigned long addr = (unsigned long)__va(i << PAGE_SHIFT);
-		int level;
+		unsigned int level;
 		pte_t *pte;
 
 		pte = lookup_address(addr, &level);
@@ -106,7 +106,7 @@
 	unsigned long *bm;
 	pte_t *pte, pte0;
 	int failed = 0;
-	int level;
+	unsigned int level;
 	int i, k;
 	int err;
 
diff --git a/arch/x86/pci/fixup.c b/arch/x86/pci/fixup.c
index cb63007..74d30ff 100644
--- a/arch/x86/pci/fixup.c
+++ b/arch/x86/pci/fixup.c
@@ -17,7 +17,7 @@
 	int pxb, reg;
 	u8 busno, suba, subb;
 
-	printk(KERN_WARNING "PCI: Searching for i450NX host bridges on %s\n", pci_name(d));
+	dev_warn(&d->dev, "Searching for i450NX host bridges\n");
 	reg = 0xd0;
 	for(pxb = 0; pxb < 2; pxb++) {
 		pci_read_config_byte(d, reg++, &busno);
@@ -41,7 +41,7 @@
 	 */
 	u8 busno;
 	pci_read_config_byte(d, 0x4a, &busno);
-	printk(KERN_INFO "PCI: i440KX/GX host bridge %s: secondary bus %02x\n", pci_name(d), busno);
+	dev_info(&d->dev, "i440KX/GX host bridge; secondary bus %02x\n", busno);
 	pci_scan_bus_with_sysdata(busno);
 	pcibios_last_bus = -1;
 }
@@ -55,7 +55,7 @@
 	 */
 	int i;
 
-	printk(KERN_WARNING "PCI: Fixing base address flags for device %s\n", pci_name(d));
+	dev_warn(&d->dev, "Fixing base address flags\n");
 	for(i = 0; i < 4; i++)
 		d->resource[i].flags |= PCI_BASE_ADDRESS_SPACE_IO;
 }
@@ -68,7 +68,7 @@
 	 * Fix class to be PCI_CLASS_STORAGE_SCSI
 	 */
 	if (!d->class) {
-		printk(KERN_WARNING "PCI: fixing NCR 53C810 class code for %s\n", pci_name(d));
+		dev_warn(&d->dev, "Fixing NCR 53C810 class code\n");
 		d->class = PCI_CLASS_STORAGE_SCSI << 8;
 	}
 }
@@ -80,7 +80,7 @@
 	 *  SiS 5597 and 5598 chipsets require latency timer set to
 	 *  at most 32 to avoid lockups.
 	 */
-	DBG("PCI: Setting max latency to 32\n");
+	dev_dbg(&d->dev, "Setting max latency to 32\n");
 	pcibios_max_latency = 32;
 }
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5597, pci_fixup_latency);
@@ -138,7 +138,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", \
+		dev_warn(&d->dev, "Disabling VIA memory write queue (PCI ID %04x, rev %02x): [%02x] %02x & %02x -> %02x\n", \
 			d->device, d->revision, where, v, mask, v & mask);
 		v &= mask;
 		pci_write_config_byte(d, where, v);
@@ -200,7 +200,7 @@
 	 * Apply fixup if needed, but don't touch disconnect state
 	 */
 	if ((val & 0x00FF0000) != 0x00010000) {
-		printk(KERN_WARNING "PCI: nForce2 C1 Halt Disconnect fixup\n");
+		dev_warn(&dev->dev, "nForce2 C1 Halt Disconnect fixup\n");
 		pci_write_config_dword(dev, 0x6c, (val & 0xFF00FFFF) | 0x00010000);
 	}
 }
@@ -348,7 +348,7 @@
 	pci_read_config_word(pdev, PCI_COMMAND, &config);
 	if (config & (PCI_COMMAND_IO | PCI_COMMAND_MEMORY)) {
 		pdev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_SHADOW;
-		printk(KERN_DEBUG "Boot video device is %s\n", pci_name(pdev));
+		dev_printk(KERN_DEBUG, &pdev->dev, "Boot video device\n");
 	}
 }
 DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_video);
@@ -388,11 +388,11 @@
 		/* verify the change for status output */
 		pci_read_config_byte(dev, 0x50, &val);
 		if (val & 0x40)
-			printk(KERN_INFO "PCI: Detected MSI K8T Neo2-FIR, "
+			dev_info(&dev->dev, "Detected MSI K8T Neo2-FIR; "
 					"can't enable onboard soundcard!\n");
 		else
-			printk(KERN_INFO "PCI: Detected MSI K8T Neo2-FIR, "
-					"enabled onboard soundcard.\n");
+			dev_info(&dev->dev, "Detected MSI K8T Neo2-FIR; "
+					"enabled onboard soundcard\n");
 	}
 }
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237,
diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig
index d3cb3d6..844721e 100644
--- a/arch/xtensa/Kconfig
+++ b/arch/xtensa/Kconfig
@@ -174,11 +174,6 @@
 	  your box. Other bus systems are ISA, EISA, MicroChannel (MCA) or
 	  VESA. If you have PCI, say Y, otherwise N.
 
-	  The PCI-HOWTO, available from
-	  <http://www.linuxdoc.org/docs.html#howto>, contains valuable
-	  information about which PCI hardware does work under Linux and which
-	  doesn't
-
 source "drivers/pci/Kconfig"
 
 config HOTPLUG
diff --git a/drivers/acpi/hardware/hwsleep.c b/drivers/acpi/hardware/hwsleep.c
index 81b2484..fd1c4ba 100644
--- a/drivers/acpi/hardware/hwsleep.c
+++ b/drivers/acpi/hardware/hwsleep.c
@@ -192,18 +192,13 @@
 	arg.type = ACPI_TYPE_INTEGER;
 	arg.integer.value = sleep_state;
 
-	/* Run the _PTS and _GTS methods */
+	/* Run the _PTS method */
 
 	status = acpi_evaluate_object(NULL, METHOD_NAME__PTS, &arg_list, NULL);
 	if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
 		return_ACPI_STATUS(status);
 	}
 
-	status = acpi_evaluate_object(NULL, METHOD_NAME__GTS, &arg_list, NULL);
-	if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
-		return_ACPI_STATUS(status);
-	}
-
 	/* Setup the argument to _SST */
 
 	switch (sleep_state) {
@@ -234,10 +229,6 @@
 				"While executing method _SST"));
 	}
 
-	/* Disable/Clear all GPEs */
-
-	status = acpi_hw_disable_all_gpes();
-
 	return_ACPI_STATUS(status);
 }
 
@@ -262,6 +253,8 @@
 	struct acpi_bit_register_info *sleep_type_reg_info;
 	struct acpi_bit_register_info *sleep_enable_reg_info;
 	u32 in_value;
+	struct acpi_object_list arg_list;
+	union acpi_object arg;
 	acpi_status status;
 
 	ACPI_FUNCTION_TRACE(acpi_enter_sleep_state);
@@ -307,6 +300,18 @@
 		return_ACPI_STATUS(status);
 	}
 
+	/* Execute the _GTS method */
+
+	arg_list.count = 1;
+	arg_list.pointer = &arg;
+	arg.type = ACPI_TYPE_INTEGER;
+	arg.integer.value = sleep_state;
+
+	status = acpi_evaluate_object(NULL, METHOD_NAME__GTS, &arg_list, NULL);
+	if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
+		return_ACPI_STATUS(status);
+	}
+
 	/* Get current value of PM1A control */
 
 	status = acpi_hw_register_read(ACPI_REGISTER_PM1_CONTROL, &PM1Acontrol);
@@ -473,17 +478,18 @@
 
 /*******************************************************************************
  *
- * FUNCTION:    acpi_leave_sleep_state
+ * FUNCTION:    acpi_leave_sleep_state_prep
  *
- * PARAMETERS:  sleep_state         - Which sleep state we just exited
+ * PARAMETERS:  sleep_state         - Which sleep state we are exiting
  *
  * RETURN:      Status
  *
- * DESCRIPTION: Perform OS-independent ACPI cleanup after a sleep
- *              Called with interrupts ENABLED.
+ * DESCRIPTION: Perform the first state of OS-independent ACPI cleanup after a
+ *              sleep.
+ *              Called with interrupts DISABLED.
  *
  ******************************************************************************/
-acpi_status acpi_leave_sleep_state(u8 sleep_state)
+acpi_status acpi_leave_sleep_state_prep(u8 sleep_state)
 {
 	struct acpi_object_list arg_list;
 	union acpi_object arg;
@@ -493,7 +499,7 @@
 	u32 PM1Acontrol;
 	u32 PM1Bcontrol;
 
-	ACPI_FUNCTION_TRACE(acpi_leave_sleep_state);
+	ACPI_FUNCTION_TRACE(acpi_leave_sleep_state_prep);
 
 	/*
 	 * Set SLP_TYPE and SLP_EN to state S0.
@@ -540,6 +546,41 @@
 		}
 	}
 
+	/* Execute the _BFS method */
+
+	arg_list.count = 1;
+	arg_list.pointer = &arg;
+	arg.type = ACPI_TYPE_INTEGER;
+	arg.integer.value = sleep_state;
+
+	status = acpi_evaluate_object(NULL, METHOD_NAME__BFS, &arg_list, NULL);
+	if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
+		ACPI_EXCEPTION((AE_INFO, status, "During Method _BFS"));
+	}
+
+	return_ACPI_STATUS(status);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_leave_sleep_state
+ *
+ * PARAMETERS:  sleep_state         - Which sleep state we just exited
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Perform OS-independent ACPI cleanup after a sleep
+ *              Called with interrupts ENABLED.
+ *
+ ******************************************************************************/
+acpi_status acpi_leave_sleep_state(u8 sleep_state)
+{
+	struct acpi_object_list arg_list;
+	union acpi_object arg;
+	acpi_status status;
+
+	ACPI_FUNCTION_TRACE(acpi_leave_sleep_state);
+
 	/* Ensure enter_sleep_state_prep -> enter_sleep_state ordering */
 
 	acpi_gbl_sleep_type_a = ACPI_SLEEP_TYPE_INVALID;
@@ -558,12 +599,6 @@
 		ACPI_EXCEPTION((AE_INFO, status, "During Method _SST"));
 	}
 
-	arg.integer.value = sleep_state;
-	status = acpi_evaluate_object(NULL, METHOD_NAME__BFS, &arg_list, NULL);
-	if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
-		ACPI_EXCEPTION((AE_INFO, status, "During Method _BFS"));
-	}
-
 	/*
 	 * GPEs must be enabled before _WAK is called as GPEs
 	 * might get fired there
diff --git a/drivers/acpi/sleep/main.c b/drivers/acpi/sleep/main.c
index 2c0b663..485de13 100644
--- a/drivers/acpi/sleep/main.c
+++ b/drivers/acpi/sleep/main.c
@@ -26,9 +26,24 @@
 
 #ifdef CONFIG_PM_SLEEP
 static u32 acpi_target_sleep_state = ACPI_STATE_S0;
+static bool acpi_sleep_finish_wake_up;
+
+/*
+ * ACPI 2.0 and later want us to execute _PTS after suspending devices, so we
+ * allow the user to request that behavior by using the 'acpi_new_pts_ordering'
+ * kernel command line option that causes the following variable to be set.
+ */
+static bool new_pts_ordering;
+
+static int __init acpi_new_pts_ordering(char *str)
+{
+	new_pts_ordering = true;
+	return 1;
+}
+__setup("acpi_new_pts_ordering", acpi_new_pts_ordering);
 #endif
 
-int acpi_sleep_prepare(u32 acpi_state)
+static int acpi_sleep_prepare(u32 acpi_state)
 {
 #ifdef CONFIG_ACPI_SLEEP
 	/* do we have a wakeup address for S2 and S3? */
@@ -44,6 +59,8 @@
 	ACPI_FLUSH_CPU_CACHE();
 	acpi_enable_wakeup_device_prep(acpi_state);
 #endif
+	printk(KERN_INFO PREFIX "Preparing to enter system sleep state S%d\n",
+		acpi_state);
 	acpi_enter_sleep_state_prep(acpi_state);
 	return 0;
 }
@@ -63,17 +80,25 @@
 static int init_8259A_after_S1;
 
 /**
- *	acpi_pm_set_target - Set the target system sleep state to the state
+ *	acpi_pm_begin - Set the target system sleep state to the state
  *		associated with given @pm_state, if supported.
  */
 
-static int acpi_pm_set_target(suspend_state_t pm_state)
+static int acpi_pm_begin(suspend_state_t pm_state)
 {
 	u32 acpi_state = acpi_suspend_states[pm_state];
 	int error = 0;
 
 	if (sleep_states[acpi_state]) {
 		acpi_target_sleep_state = acpi_state;
+		if (new_pts_ordering)
+			return 0;
+
+		error = acpi_sleep_prepare(acpi_state);
+		if (error)
+			acpi_target_sleep_state = ACPI_STATE_S0;
+		else
+			acpi_sleep_finish_wake_up = true;
 	} else {
 		printk(KERN_ERR "ACPI does not support this state: %d\n",
 			pm_state);
@@ -91,12 +116,17 @@
 
 static int acpi_pm_prepare(void)
 {
-	int error = acpi_sleep_prepare(acpi_target_sleep_state);
+	if (new_pts_ordering) {
+		int error = acpi_sleep_prepare(acpi_target_sleep_state);
 
-	if (error)
-		acpi_target_sleep_state = ACPI_STATE_S0;
+		if (error) {
+			acpi_target_sleep_state = ACPI_STATE_S0;
+			return error;
+		}
+		acpi_sleep_finish_wake_up = true;
+	}
 
-	return error;
+	return ACPI_SUCCESS(acpi_hw_disable_all_gpes()) ? 0 : -EFAULT;
 }
 
 /**
@@ -120,10 +150,8 @@
 	if (acpi_state == ACPI_STATE_S3) {
 		int error = acpi_save_state_mem();
 
-		if (error) {
-			acpi_target_sleep_state = ACPI_STATE_S0;
+		if (error)
 			return error;
-		}
 	}
 
 	local_irq_save(flags);
@@ -139,6 +167,9 @@
 		break;
 	}
 
+	/* Reprogram control registers and execute _BFS */
+	acpi_leave_sleep_state_prep(acpi_state);
+
 	/* ACPI 3.0 specs (P62) says that it's the responsabilty
 	 * of the OSPM to clear the status bit [ implying that the
 	 * POWER_BUTTON event should not reach userspace ]
@@ -146,6 +177,13 @@
 	if (ACPI_SUCCESS(status) && (acpi_state == ACPI_STATE_S3))
 		acpi_clear_event(ACPI_EVENT_POWER_BUTTON);
 
+	/*
+	 * Disable and clear GPE status before interrupt is enabled. Some GPEs
+	 * (like wakeup GPE) haven't handler, this can avoid such GPE misfire.
+	 * acpi_leave_sleep_state will reenable specific GPEs later
+	 */
+	acpi_hw_disable_all_gpes();
+
 	local_irq_restore(flags);
 	printk(KERN_DEBUG "Back to C!\n");
 
@@ -157,7 +195,7 @@
 }
 
 /**
- *	acpi_pm_finish - Finish up suspend sequence.
+ *	acpi_pm_finish - Instruct the platform to leave a sleep state.
  *
  *	This is called after we wake back up (or if entering the sleep state
  *	failed). 
@@ -174,6 +212,7 @@
 	acpi_set_firmware_waking_vector((acpi_physical_address) 0);
 
 	acpi_target_sleep_state = ACPI_STATE_S0;
+	acpi_sleep_finish_wake_up = false;
 
 #ifdef CONFIG_X86
 	if (init_8259A_after_S1) {
@@ -183,6 +222,20 @@
 #endif
 }
 
+/**
+ *	acpi_pm_end - Finish up suspend sequence.
+ */
+
+static void acpi_pm_end(void)
+{
+	/*
+	 * This is necessary in case acpi_pm_finish() is not called directly
+	 * during a failing transition to a sleep state.
+	 */
+	if (acpi_sleep_finish_wake_up)
+		acpi_pm_finish();
+}
+
 static int acpi_pm_state_valid(suspend_state_t pm_state)
 {
 	u32 acpi_state;
@@ -201,10 +254,11 @@
 
 static struct platform_suspend_ops acpi_pm_ops = {
 	.valid = acpi_pm_state_valid,
-	.set_target = acpi_pm_set_target,
+	.begin = acpi_pm_begin,
 	.prepare = acpi_pm_prepare,
 	.enter = acpi_pm_enter,
 	.finish = acpi_pm_finish,
+	.end = acpi_pm_end,
 };
 
 /*
@@ -229,15 +283,36 @@
 #endif /* CONFIG_SUSPEND */
 
 #ifdef CONFIG_HIBERNATION
-static int acpi_hibernation_start(void)
+static int acpi_hibernation_begin(void)
 {
+	int error;
+
 	acpi_target_sleep_state = ACPI_STATE_S4;
-	return 0;
+	if (new_pts_ordering)
+		return 0;
+
+	error = acpi_sleep_prepare(ACPI_STATE_S4);
+	if (error)
+		acpi_target_sleep_state = ACPI_STATE_S0;
+	else
+		acpi_sleep_finish_wake_up = true;
+
+	return error;
 }
 
 static int acpi_hibernation_prepare(void)
 {
-	return acpi_sleep_prepare(ACPI_STATE_S4);
+	if (new_pts_ordering) {
+		int error = acpi_sleep_prepare(ACPI_STATE_S4);
+
+		if (error) {
+			acpi_target_sleep_state = ACPI_STATE_S0;
+			return error;
+		}
+		acpi_sleep_finish_wake_up = true;
+	}
+
+	return ACPI_SUCCESS(acpi_hw_disable_all_gpes()) ? 0 : -EFAULT;
 }
 
 static int acpi_hibernation_enter(void)
@@ -251,6 +326,8 @@
 	acpi_enable_wakeup_device(ACPI_STATE_S4);
 	/* This shouldn't return.  If it returns, we have a problem */
 	status = acpi_enter_sleep_state(ACPI_STATE_S4);
+	/* Reprogram control registers and execute _BFS */
+	acpi_leave_sleep_state_prep(ACPI_STATE_S4);
 	local_irq_restore(flags);
 
 	return ACPI_SUCCESS(status) ? 0 : -EFAULT;
@@ -263,15 +340,12 @@
 	 * enable it here.
 	 */
 	acpi_enable();
+	/* Reprogram control registers and execute _BFS */
+	acpi_leave_sleep_state_prep(ACPI_STATE_S4);
 }
 
 static void acpi_hibernation_finish(void)
 {
-	/*
-	 * If ACPI is not enabled by the BIOS and the boot kernel, we need to
-	 * enable it here.
-	 */
-	acpi_enable();
 	acpi_disable_wakeup_device(ACPI_STATE_S4);
 	acpi_leave_sleep_state(ACPI_STATE_S4);
 
@@ -279,6 +353,17 @@
 	acpi_set_firmware_waking_vector((acpi_physical_address) 0);
 
 	acpi_target_sleep_state = ACPI_STATE_S0;
+	acpi_sleep_finish_wake_up = false;
+}
+
+static void acpi_hibernation_end(void)
+{
+	/*
+	 * This is necessary in case acpi_hibernation_finish() is not called
+	 * directly during a failing transition to the sleep state.
+	 */
+	if (acpi_sleep_finish_wake_up)
+		acpi_hibernation_finish();
 }
 
 static int acpi_hibernation_pre_restore(void)
@@ -296,7 +381,8 @@
 }
 
 static struct platform_hibernation_ops acpi_hibernation_ops = {
-	.start = acpi_hibernation_start,
+	.begin = acpi_hibernation_begin,
+	.end = acpi_hibernation_end,
 	.pre_snapshot = acpi_hibernation_prepare,
 	.finish = acpi_hibernation_finish,
 	.prepare = acpi_hibernation_prepare,
@@ -403,6 +489,7 @@
 {
 	/* Prepare to power off the system */
 	acpi_sleep_prepare(ACPI_STATE_S5);
+	acpi_hw_disable_all_gpes();
 }
 
 static void acpi_power_off(void)
diff --git a/drivers/acpi/sleep/sleep.h b/drivers/acpi/sleep/sleep.h
index a2ea125..cfaf8f5 100644
--- a/drivers/acpi/sleep/sleep.h
+++ b/drivers/acpi/sleep/sleep.h
@@ -5,5 +5,3 @@
 extern void acpi_enable_wakeup_device_prep(u8 sleep_state);
 extern void acpi_enable_wakeup_device(u8 sleep_state);
 extern void acpi_disable_wakeup_device(u8 sleep_state);
-
-extern int acpi_sleep_prepare(u32 acpi_state);
diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
index ae19c9b..ba8f7f4 100644
--- a/drivers/ata/Kconfig
+++ b/drivers/ata/Kconfig
@@ -69,7 +69,7 @@
 
 config SATA_MV
 	tristate "Marvell SATA support (HIGHLY EXPERIMENTAL)"
-	depends on PCI && EXPERIMENTAL
+	depends on EXPERIMENTAL
 	help
 	  This option enables support for the Marvell Serial ATA family.
 	  Currently supports 88SX[56]0[48][01] chips.
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index 6f089b8..27c8d56 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -475,6 +475,8 @@
 	{ PCI_VDEVICE(INTEL, 0x294e), board_ahci }, /* ICH9M */
 	{ PCI_VDEVICE(INTEL, 0x502a), board_ahci }, /* Tolapai */
 	{ PCI_VDEVICE(INTEL, 0x502b), board_ahci }, /* Tolapai */
+	{ PCI_VDEVICE(INTEL, 0x3a05), board_ahci }, /* ICH10 */
+	{ PCI_VDEVICE(INTEL, 0x3a25), board_ahci }, /* ICH10 */
 
 	/* JMicron 360/1/3/5/6, match class to avoid IDE function */
 	{ PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c
index a65c8ae..47892e6 100644
--- a/drivers/ata/ata_piix.c
+++ b/drivers/ata/ata_piix.c
@@ -267,6 +267,14 @@
 	{ 0x8086, 0x292e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci },
 	/* SATA Controller IDE (Tolapai) */
 	{ 0x8086, 0x5028, PCI_ANY_ID, PCI_ANY_ID, 0, 0, tolapai_sata_ahci },
+	/* SATA Controller IDE (ICH10) */
+	{ 0x8086, 0x3a00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci },
+	/* SATA Controller IDE (ICH10) */
+	{ 0x8086, 0x3a06, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
+	/* SATA Controller IDE (ICH10) */
+	{ 0x8086, 0x3a20, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci },
+	/* SATA Controller IDE (ICH10) */
+	{ 0x8086, 0x3a26, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
 
 	{ }	/* terminate list */
 };
@@ -1068,7 +1076,7 @@
 	iowrite32(val, hpriv->sidpr + PIIX_SIDPR_DATA);
 }
 
-u32 piix_merge_scr(u32 val0, u32 val1, const int * const *merge_tbl)
+static u32 piix_merge_scr(u32 val0, u32 val1, const int * const *merge_tbl)
 {
 	u32 val = 0;
 	int i, mi;
diff --git a/drivers/ata/pata_bf54x.c b/drivers/ata/pata_bf54x.c
index a32e3c4..7f87f10 100644
--- a/drivers/ata/pata_bf54x.c
+++ b/drivers/ata/pata_bf54x.c
@@ -299,7 +299,7 @@
 	*/
 	n6 = num_clocks_min(t6min, fsclk);
 	if (mode >= 0 && mode <= 4 && n6 >= 1) {
-		pr_debug("set piomode: mode=%d, fsclk=%ud\n", mode, fsclk);
+		dev_dbg(adev->link->ap->dev, "set piomode: mode=%d, fsclk=%ud\n", mode, fsclk);
 		/* calculate the timing values for register transfers. */
 		while (mode > 0 && pio_fsclk[mode] > fsclk)
 			mode--;
@@ -376,7 +376,7 @@
 
 	mode = adev->dma_mode - XFER_UDMA_0;
 	if (mode >= 0 && mode <= 5) {
-		pr_debug("set udmamode: mode=%d\n", mode);
+		dev_dbg(adev->link->ap->dev, "set udmamode: mode=%d\n", mode);
 		/* the most restrictive timing value is t6 and tc,
 		 * the DIOW - data hold. If one SCLK pulse is longer
 		 * than this minimum value then register
@@ -433,7 +433,7 @@
 
 	mode = adev->dma_mode - XFER_MW_DMA_0;
 	if (mode >= 0 && mode <= 2) {
-		pr_debug("set mdmamode: mode=%d\n", mode);
+		dev_dbg(adev->link->ap->dev, "set mdmamode: mode=%d\n", mode);
 		/* the most restrictive timing value is tf, the DMACK to
 		 * read data released. If one SCLK pulse is longer than
 		 * this maximum value then the MDMA mode
@@ -697,7 +697,7 @@
 			write_atapi_register(base, ATA_REG_LBAL, tf->hob_lbal);
 			write_atapi_register(base, ATA_REG_LBAM, tf->hob_lbam);
 			write_atapi_register(base, ATA_REG_LBAH, tf->hob_lbah);
-			pr_debug("hob: feat 0x%X nsect 0x%X, lba 0x%X "
+			dev_dbg(ap->dev, "hob: feat 0x%X nsect 0x%X, lba 0x%X "
 				 "0x%X 0x%X\n",
 				tf->hob_feature,
 				tf->hob_nsect,
@@ -711,7 +711,7 @@
 		write_atapi_register(base, ATA_REG_LBAL, tf->lbal);
 		write_atapi_register(base, ATA_REG_LBAM, tf->lbam);
 		write_atapi_register(base, ATA_REG_LBAH, tf->lbah);
-		pr_debug("feat 0x%X nsect 0x%X lba 0x%X 0x%X 0x%X\n",
+		dev_dbg(ap->dev, "feat 0x%X nsect 0x%X lba 0x%X 0x%X 0x%X\n",
 			tf->feature,
 			tf->nsect,
 			tf->lbal,
@@ -721,7 +721,7 @@
 
 	if (tf->flags & ATA_TFLAG_DEVICE) {
 		write_atapi_register(base, ATA_REG_DEVICE, tf->device);
-		pr_debug("device 0x%X\n", tf->device);
+		dev_dbg(ap->dev, "device 0x%X\n", tf->device);
 	}
 
 	ata_wait_idle(ap);
@@ -782,7 +782,7 @@
 			      const struct ata_taskfile *tf)
 {
 	void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr;
-	pr_debug("ata%u: cmd 0x%X\n", ap->print_id, tf->command);
+	dev_dbg(ap->dev, "ata%u: cmd 0x%X\n", ap->print_id, tf->command);
 
 	write_atapi_register(base, ATA_REG_CMD, tf->command);
 	ata_pause(ap);
@@ -834,7 +834,7 @@
 	struct scatterlist *sg;
 	unsigned int si;
 
-	pr_debug("in atapi dma setup\n");
+	dev_dbg(qc->ap->dev, "in atapi dma setup\n");
 	/* Program the ATA_CTRL register with dir */
 	if (qc->tf.flags & ATA_TFLAG_WRITE) {
 		/* fill the ATAPI DMA controller */
@@ -870,7 +870,7 @@
 	struct scatterlist *sg;
 	unsigned int si;
 
-	pr_debug("in atapi dma start\n");
+	dev_dbg(qc->ap->dev, "in atapi dma start\n");
 	if (!(ap->udma_mask || ap->mwdma_mask))
 		return;
 
@@ -888,7 +888,7 @@
 				sg_dma_address(sg) + sg_dma_len(sg));
 		}
 		enable_dma(CH_ATAPI_TX);
-		pr_debug("enable udma write\n");
+		dev_dbg(qc->ap->dev, "enable udma write\n");
 
 		/* Send ATA DMA write command */
 		bfin_exec_command(ap, &qc->tf);
@@ -898,7 +898,7 @@
 			| XFER_DIR));
 	} else {
 		enable_dma(CH_ATAPI_RX);
-		pr_debug("enable udma read\n");
+		dev_dbg(qc->ap->dev, "enable udma read\n");
 
 		/* Send ATA DMA read command */
 		bfin_exec_command(ap, &qc->tf);
@@ -936,7 +936,7 @@
 	struct scatterlist *sg;
 	unsigned int si;
 
-	pr_debug("in atapi dma stop\n");
+	dev_dbg(qc->ap->dev, "in atapi dma stop\n");
 	if (!(ap->udma_mask || ap->mwdma_mask))
 		return;
 
@@ -1147,15 +1147,15 @@
 	void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr;
 	unsigned short int_status = ATAPI_GET_INT_STATUS(base);
 
-	if (ATAPI_GET_STATUS(base) & (MULTI_XFER_ON|ULTRA_XFER_ON)) {
+	if (ATAPI_GET_STATUS(base) & (MULTI_XFER_ON|ULTRA_XFER_ON))
 		host_stat |= ATA_DMA_ACTIVE;
-	}
-	if (int_status & (MULTI_DONE_INT|UDMAIN_DONE_INT|UDMAOUT_DONE_INT)) {
+	if (int_status & (MULTI_DONE_INT|UDMAIN_DONE_INT|UDMAOUT_DONE_INT|
+		ATAPI_DEV_INT))
 		host_stat |= ATA_DMA_INTR;
-	}
-	if (int_status & (MULTI_TERM_INT|UDMAIN_TERM_INT|UDMAOUT_TERM_INT)) {
-		host_stat |= ATA_DMA_ERR;
-	}
+	if (int_status & (MULTI_TERM_INT|UDMAIN_TERM_INT|UDMAOUT_TERM_INT))
+		host_stat |= ATA_DMA_ERR|ATA_DMA_INTR;
+
+	dev_dbg(ap->dev, "ATAPI: host_stat=0x%x\n", host_stat);
 
 	return host_stat;
 }
@@ -1213,8 +1213,7 @@
 {
 	void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr;
 
-	pr_debug("in atapi irq clear\n");
-
+	dev_dbg(ap->dev, "in atapi irq clear\n");
 	ATAPI_SET_INT_STATUS(base, ATAPI_GET_INT_STATUS(base)|ATAPI_DEV_INT
 		| MULTI_DONE_INT | UDMAIN_DONE_INT | UDMAOUT_DONE_INT
 		| MULTI_TERM_INT | UDMAIN_TERM_INT | UDMAOUT_TERM_INT);
@@ -1232,7 +1231,7 @@
 	void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr;
 	u8 tmp;
 
-	pr_debug("in atapi irq on\n");
+	dev_dbg(ap->dev, "in atapi irq on\n");
 	ap->ctl &= ~ATA_NIEN;
 	ap->last_ctl = ap->ctl;
 
@@ -1255,7 +1254,7 @@
 {
 	void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr;
 
-	pr_debug("in atapi dma freeze\n");
+	dev_dbg(ap->dev, "in atapi dma freeze\n");
 	ap->ctl |= ATA_NIEN;
 	ap->last_ctl = ap->ctl;
 
@@ -1328,7 +1327,7 @@
 
 static void bfin_port_stop(struct ata_port *ap)
 {
-	pr_debug("in atapi port stop\n");
+	dev_dbg(ap->dev, "in atapi port stop\n");
 	if (ap->udma_mask != 0 || ap->mwdma_mask != 0) {
 		free_dma(CH_ATAPI_RX);
 		free_dma(CH_ATAPI_TX);
@@ -1337,7 +1336,7 @@
 
 static int bfin_port_start(struct ata_port *ap)
 {
-	pr_debug("in atapi port start\n");
+	dev_dbg(ap->dev, "in atapi port start\n");
 	if (!(ap->udma_mask || ap->mwdma_mask))
 		return 0;
 
@@ -1373,10 +1372,6 @@
 	.slave_configure	= ata_scsi_slave_config,
 	.slave_destroy		= ata_scsi_slave_destroy,
 	.bios_param		= ata_std_bios_param,
-#ifdef CONFIG_PM
-	.resume			= ata_scsi_device_resume,
-	.suspend		= ata_scsi_device_suspend,
-#endif
 };
 
 static const struct ata_port_operations bfin_pata_ops = {
diff --git a/drivers/ata/pata_cs5520.c b/drivers/ata/pata_cs5520.c
index d4590f5..7ed279b 100644
--- a/drivers/ata/pata_cs5520.c
+++ b/drivers/ata/pata_cs5520.c
@@ -229,7 +229,7 @@
 		return -ENOMEM;
 
 	/* Perform set up for DMA */
-	if (pci_enable_device_bars(pdev, 1<<2)) {
+	if (pci_enable_device_io(pdev)) {
 		printk(KERN_ERR DRV_NAME ": unable to configure BAR2.\n");
 		return -ENODEV;
 	}
diff --git a/drivers/ata/pata_sl82c105.c b/drivers/ata/pata_sl82c105.c
index 1388cef5..81ef207 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.2"
+#define DRV_VERSION "0.3.3"
 
 enum {
 	/*
@@ -206,6 +206,34 @@
 	sl82c105_set_piomode(ap, qc->dev);
 }
 
+/**
+ *	sl82c105_qc_defer	-	implement serialization
+ *	@qc: command
+ *
+ *	We must issue one command per host not per channel because
+ *	of the reset bug.
+ *
+ *	Q: is the scsi host lock sufficient ?
+ */
+
+static int sl82c105_qc_defer(struct ata_queued_cmd *qc)
+{
+	struct ata_host *host = qc->ap->host;
+	struct ata_port *alt = host->ports[1 ^ qc->ap->port_no];
+	int rc;
+
+	/* First apply the usual rules */	
+	rc = ata_std_qc_defer(qc);
+	if (rc != 0)
+		return rc;
+
+	/* Now apply serialization rules. Only allow a command if the
+	   other channel state machine is idle */
+	if (alt && alt->qc_active)
+		return	ATA_DEFER_PORT;
+	return 0;
+}
+
 static struct scsi_host_template sl82c105_sht = {
 	.module			= THIS_MODULE,
 	.name			= DRV_NAME,
@@ -245,6 +273,7 @@
 	.bmdma_stop	= sl82c105_bmdma_stop,
 	.bmdma_status 	= ata_bmdma_status,
 
+	.qc_defer	= sl82c105_qc_defer,
 	.qc_prep 	= ata_qc_prep,
 	.qc_issue	= ata_qc_issue_prot,
 
@@ -312,7 +341,7 @@
 	};
 	/* for now use only the first port */
 	const struct ata_port_info *ppi[] = { &info_early,
-					       &ata_dummy_port_info };
+					       NULL };
 	u32 val;
 	int rev;
 
diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c
index 7e72463..3c1b5c90 100644
--- a/drivers/ata/sata_mv.c
+++ b/drivers/ata/sata_mv.c
@@ -29,7 +29,13 @@
   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)
+  2) Improve/fix IRQ and error handling sequences.
+
+  3) ATAPI support (Marvell claims the 60xx/70xx chips can do it).
+
+  4) Think about TCQ support here, and for libata in general
+  with controllers that suppport it via host-queuing hardware
+  (a software-only implementation could be a nightmare).
 
   5) Investigate problems with PCI Message Signalled Interrupts (MSI).
 
@@ -53,8 +59,6 @@
   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.
-
 */
 
 
@@ -73,7 +77,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME	"sata_mv"
-#define DRV_VERSION	"1.01"
+#define DRV_VERSION	"1.20"
 
 enum {
 	/* BAR's are enumerated in terms of pci_resource_start() terms */
@@ -107,14 +111,12 @@
 
 	/* CRQB needs alignment on a 1KB boundary. Size == 1KB
 	 * CRPB needs alignment on a 256B boundary. Size == 256B
-	 * SG count of 176 leads to MV_PORT_PRIV_DMA_SZ == 4KB
 	 * ePRD (SG) entries need alignment on a 16B boundary. Size == 16B
 	 */
 	MV_CRQB_Q_SZ		= (32 * MV_MAX_Q_DEPTH),
 	MV_CRPB_Q_SZ		= (8 * MV_MAX_Q_DEPTH),
-	MV_MAX_SG_CT		= 176,
+	MV_MAX_SG_CT		= 256,
 	MV_SG_TBL_SZ		= (16 * MV_MAX_SG_CT),
-	MV_PORT_PRIV_DMA_SZ	= (MV_CRQB_Q_SZ + MV_CRPB_Q_SZ + MV_SG_TBL_SZ),
 
 	MV_PORTS_PER_HC		= 4,
 	/* == (port / MV_PORTS_PER_HC) to determine HC from 0-7 port */
@@ -125,6 +127,9 @@
 	/* Host Flags */
 	MV_FLAG_DUAL_HC		= (1 << 30),  /* two SATA Host Controllers */
 	MV_FLAG_IRQ_COALESCE	= (1 << 29),  /* IRQ coalescing capability */
+	/* SoC integrated controllers, no PCI interface */
+	MV_FLAG_SOC = (1 << 28),
+
 	MV_COMMON_FLAGS		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
 				  ATA_FLAG_MMIO | ATA_FLAG_NO_ATAPI |
 				  ATA_FLAG_PIO_POLLING,
@@ -170,7 +175,7 @@
 
 	PCIE_IRQ_CAUSE_OFS	= 0x1900,
 	PCIE_IRQ_MASK_OFS	= 0x1910,
-	PCIE_UNMASK_ALL_IRQS	= 0x70a,	/* assorted bits */
+	PCIE_UNMASK_ALL_IRQS	= 0x40a,	/* assorted bits */
 
 	HC_MAIN_IRQ_CAUSE_OFS	= 0x1d60,
 	HC_MAIN_IRQ_MASK_OFS	= 0x1d64,
@@ -210,6 +215,7 @@
 	/* SATA registers */
 	SATA_STATUS_OFS		= 0x300,  /* ctrl, err regs follow status */
 	SATA_ACTIVE_OFS		= 0x350,
+	SATA_FIS_IRQ_CAUSE_OFS	= 0x364,
 	PHY_MODE3		= 0x310,
 	PHY_MODE4		= 0x314,
 	PHY_MODE2		= 0x330,
@@ -222,11 +228,11 @@
 
 	/* Port registers */
 	EDMA_CFG_OFS		= 0,
-	EDMA_CFG_Q_DEPTH	= 0,			/* queueing disabled */
-	EDMA_CFG_NCQ		= (1 << 5),
-	EDMA_CFG_NCQ_GO_ON_ERR	= (1 << 14),		/* continue on error */
-	EDMA_CFG_RD_BRST_EXT	= (1 << 11),		/* read burst 512B */
-	EDMA_CFG_WR_BUFF_LEN	= (1 << 13),		/* write buffer 512B */
+	EDMA_CFG_Q_DEPTH	= 0x1f,		/* max device queue depth */
+	EDMA_CFG_NCQ		= (1 << 5),	/* for R/W FPDMA queued */
+	EDMA_CFG_NCQ_GO_ON_ERR	= (1 << 14),	/* continue on error */
+	EDMA_CFG_RD_BRST_EXT	= (1 << 11),	/* read burst 512B */
+	EDMA_CFG_WR_BUFF_LEN	= (1 << 13),	/* write buffer 512B */
 
 	EDMA_ERR_IRQ_CAUSE_OFS	= 0x8,
 	EDMA_ERR_IRQ_MASK_OFS	= 0xc,
@@ -244,14 +250,33 @@
 	EDMA_ERR_CRPB_PAR	= (1 << 10),	/* CRPB parity error */
 	EDMA_ERR_INTRL_PAR	= (1 << 11),	/* internal parity error */
 	EDMA_ERR_IORDY		= (1 << 12),	/* IORdy timeout */
+
 	EDMA_ERR_LNK_CTRL_RX	= (0xf << 13),	/* link ctrl rx error */
-	EDMA_ERR_LNK_CTRL_RX_2	= (1 << 15),
+	EDMA_ERR_LNK_CTRL_RX_0	= (1 << 13),	/* transient: CRC err */
+	EDMA_ERR_LNK_CTRL_RX_1	= (1 << 14),	/* transient: FIFO err */
+	EDMA_ERR_LNK_CTRL_RX_2	= (1 << 15),	/* fatal: caught SYNC */
+	EDMA_ERR_LNK_CTRL_RX_3	= (1 << 16),	/* transient: FIS rx err */
+
 	EDMA_ERR_LNK_DATA_RX	= (0xf << 17),	/* link data rx error */
+
 	EDMA_ERR_LNK_CTRL_TX	= (0x1f << 21),	/* link ctrl tx error */
+	EDMA_ERR_LNK_CTRL_TX_0	= (1 << 21),	/* transient: CRC err */
+	EDMA_ERR_LNK_CTRL_TX_1	= (1 << 22),	/* transient: FIFO err */
+	EDMA_ERR_LNK_CTRL_TX_2	= (1 << 23),	/* transient: caught SYNC */
+	EDMA_ERR_LNK_CTRL_TX_3	= (1 << 24),	/* transient: caught DMAT */
+	EDMA_ERR_LNK_CTRL_TX_4	= (1 << 25),	/* transient: FIS collision */
+
 	EDMA_ERR_LNK_DATA_TX	= (0x1f << 26),	/* link data tx error */
+
 	EDMA_ERR_TRANS_PROTO	= (1 << 31),	/* transport protocol error */
 	EDMA_ERR_OVERRUN_5	= (1 << 5),
 	EDMA_ERR_UNDERRUN_5	= (1 << 6),
+
+	EDMA_ERR_IRQ_TRANSIENT  = EDMA_ERR_LNK_CTRL_RX_0 |
+				  EDMA_ERR_LNK_CTRL_RX_1 |
+				  EDMA_ERR_LNK_CTRL_RX_3 |
+				  EDMA_ERR_LNK_CTRL_TX,
+
 	EDMA_EH_FREEZE		= EDMA_ERR_D_PAR |
 				  EDMA_ERR_PRD_PAR |
 				  EDMA_ERR_DEV_DCON |
@@ -311,12 +336,14 @@
 
 	/* Port private flags (pp_flags) */
 	MV_PP_FLAG_EDMA_EN	= (1 << 0),	/* is EDMA engine enabled? */
+	MV_PP_FLAG_NCQ_EN	= (1 << 1),	/* is EDMA set up for NCQ? */
 	MV_PP_FLAG_HAD_A_RESET	= (1 << 2),	/* 1st hard reset complete? */
 };
 
 #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)
+#define HAS_PCI(host) (!((host)->ports[0]->flags & MV_FLAG_SOC))
 
 enum {
 	/* DMA boundary 0xffff is required by the s/g splitting
@@ -379,8 +406,8 @@
 	dma_addr_t		crqb_dma;
 	struct mv_crpb		*crpb;
 	dma_addr_t		crpb_dma;
-	struct mv_sg		*sg_tbl;
-	dma_addr_t		sg_tbl_dma;
+	struct mv_sg		*sg_tbl[MV_MAX_Q_DEPTH];
+	dma_addr_t		sg_tbl_dma[MV_MAX_Q_DEPTH];
 
 	unsigned int		req_idx;
 	unsigned int		resp_idx;
@@ -400,6 +427,14 @@
 	u32			irq_cause_ofs;
 	u32			irq_mask_ofs;
 	u32			unmask_all_irqs;
+	/*
+	 * These consistent DMA memory pools give us guaranteed
+	 * alignment for hardware-accessed data structures,
+	 * and less memory waste in accomplishing the alignment.
+	 */
+	struct dma_pool		*crqb_pool;
+	struct dma_pool		*crpb_pool;
+	struct dma_pool		*sg_tbl_pool;
 };
 
 struct mv_hw_ops {
@@ -411,7 +446,7 @@
 	int (*reset_hc)(struct mv_host_priv *hpriv, void __iomem *mmio,
 			unsigned int n_hc);
 	void (*reset_flash)(struct mv_host_priv *hpriv, void __iomem *mmio);
-	void (*reset_bus)(struct pci_dev *pdev, void __iomem *mmio);
+	void (*reset_bus)(struct ata_host *host, void __iomem *mmio);
 };
 
 static void mv_irq_clear(struct ata_port *ap);
@@ -425,10 +460,9 @@
 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_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 mv6_dev_config(struct ata_device *dev);
 
 static void mv5_phy_errata(struct mv_host_priv *hpriv, void __iomem *mmio,
 			   unsigned int port);
@@ -438,7 +472,7 @@
 static int mv5_reset_hc(struct mv_host_priv *hpriv, void __iomem *mmio,
 			unsigned int n_hc);
 static void mv5_reset_flash(struct mv_host_priv *hpriv, void __iomem *mmio);
-static void mv5_reset_bus(struct pci_dev *pdev, void __iomem *mmio);
+static void mv5_reset_bus(struct ata_host *host, void __iomem *mmio);
 
 static void mv6_phy_errata(struct mv_host_priv *hpriv, void __iomem *mmio,
 			   unsigned int port);
@@ -448,10 +482,17 @@
 static int mv6_reset_hc(struct mv_host_priv *hpriv, void __iomem *mmio,
 			unsigned int n_hc);
 static void mv6_reset_flash(struct mv_host_priv *hpriv, void __iomem *mmio);
-static void mv_reset_pci_bus(struct pci_dev *pdev, void __iomem *mmio);
+static void mv_reset_pci_bus(struct ata_host *host, void __iomem *mmio);
 static void mv_channel_reset(struct mv_host_priv *hpriv, void __iomem *mmio,
 			     unsigned int port_no);
+static void mv_edma_cfg(struct mv_port_priv *pp, struct mv_host_priv *hpriv,
+			void __iomem *port_mmio, int want_ncq);
+static int __mv_stop_dma(struct ata_port *ap);
 
+/* .sg_tablesize is (MV_MAX_SG_CT / 2) in the structures below
+ * because we have to allow room for worst case splitting of
+ * PRDs for 64K boundaries in mv_fill_sg().
+ */
 static struct scsi_host_template mv5_sht = {
 	.module			= THIS_MODULE,
 	.name			= DRV_NAME,
@@ -475,7 +516,8 @@
 	.name			= DRV_NAME,
 	.ioctl			= ata_scsi_ioctl,
 	.queuecommand		= ata_scsi_queuecmd,
-	.can_queue		= ATA_DEF_QUEUE,
+	.change_queue_depth	= ata_scsi_change_queue_depth,
+	.can_queue		= MV_MAX_Q_DEPTH - 1,
 	.this_id		= ATA_SHT_THIS_ID,
 	.sg_tablesize		= MV_MAX_SG_CT / 2,
 	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
@@ -505,7 +547,6 @@
 	.irq_on			= ata_irq_on,
 
 	.error_handler		= mv_error_handler,
-	.post_internal_cmd	= mv_post_int_cmd,
 	.freeze			= mv_eh_freeze,
 	.thaw			= mv_eh_thaw,
 
@@ -517,6 +558,7 @@
 };
 
 static const struct ata_port_operations mv6_ops = {
+	.dev_config             = mv6_dev_config,
 	.tf_load		= ata_tf_load,
 	.tf_read		= ata_tf_read,
 	.check_status		= ata_check_status,
@@ -533,9 +575,9 @@
 	.irq_on			= ata_irq_on,
 
 	.error_handler		= mv_error_handler,
-	.post_internal_cmd	= mv_post_int_cmd,
 	.freeze			= mv_eh_freeze,
 	.thaw			= mv_eh_thaw,
+	.qc_defer		= ata_std_qc_defer,
 
 	.scr_read		= mv_scr_read,
 	.scr_write		= mv_scr_write,
@@ -561,9 +603,9 @@
 	.irq_on			= ata_irq_on,
 
 	.error_handler		= mv_error_handler,
-	.post_internal_cmd	= mv_post_int_cmd,
 	.freeze			= mv_eh_freeze,
 	.thaw			= mv_eh_thaw,
+	.qc_defer		= ata_std_qc_defer,
 
 	.scr_read		= mv_scr_read,
 	.scr_write		= mv_scr_write,
@@ -592,26 +634,29 @@
 		.port_ops	= &mv5_ops,
 	},
 	{  /* chip_604x */
-		.flags		= MV_COMMON_FLAGS | MV_6XXX_FLAGS,
+		.flags		= MV_COMMON_FLAGS | MV_6XXX_FLAGS |
+				  ATA_FLAG_NCQ,
 		.pio_mask	= 0x1f,	/* pio0-4 */
 		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &mv6_ops,
 	},
 	{  /* chip_608x */
 		.flags		= MV_COMMON_FLAGS | MV_6XXX_FLAGS |
-				  MV_FLAG_DUAL_HC,
+				  ATA_FLAG_NCQ | MV_FLAG_DUAL_HC,
 		.pio_mask	= 0x1f,	/* pio0-4 */
 		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &mv6_ops,
 	},
 	{  /* chip_6042 */
-		.flags		= MV_COMMON_FLAGS | MV_6XXX_FLAGS,
+		.flags		= MV_COMMON_FLAGS | MV_6XXX_FLAGS |
+				  ATA_FLAG_NCQ,
 		.pio_mask	= 0x1f,	/* pio0-4 */
 		.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 |
+				  ATA_FLAG_NCQ,
 		.pio_mask	= 0x1f,	/* pio0-4 */
 		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &mv_iie_ops,
@@ -648,13 +693,6 @@
 	{ }			/* terminate list */
 };
 
-static struct pci_driver mv_pci_driver = {
-	.name			= DRV_NAME,
-	.id_table		= mv_pci_tbl,
-	.probe			= mv_init_one,
-	.remove			= ata_pci_remove_one,
-};
-
 static const struct mv_hw_ops mv5xxx_ops = {
 	.phy_errata		= mv5_phy_errata,
 	.enable_leds		= mv5_enable_leds,
@@ -674,45 +712,6 @@
 };
 
 /*
- * module options
- */
-static int msi;	      /* Use PCI msi; either zero (off, default) or non-zero */
-
-
-/* move to PCI layer or libata core? */
-static int pci_go_64(struct pci_dev *pdev)
-{
-	int rc;
-
-	if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK)) {
-		rc = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK);
-		if (rc) {
-			rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
-			if (rc) {
-				dev_printk(KERN_ERR, &pdev->dev,
-					   "64-bit DMA enable failed\n");
-				return rc;
-			}
-		}
-	} else {
-		rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
-		if (rc) {
-			dev_printk(KERN_ERR, &pdev->dev,
-				   "32-bit DMA enable failed\n");
-			return rc;
-		}
-		rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
-		if (rc) {
-			dev_printk(KERN_ERR, &pdev->dev,
-				   "32-bit consistent DMA enable failed\n");
-			return rc;
-		}
-	}
-
-	return rc;
-}
-
-/*
  * Functions
  */
 
@@ -815,19 +814,46 @@
  *      LOCKING:
  *      Inherited from caller.
  */
-static void mv_start_dma(void __iomem *base, struct mv_host_priv *hpriv,
-			 struct mv_port_priv *pp)
+static void mv_start_dma(struct ata_port *ap, void __iomem *port_mmio,
+			 struct mv_port_priv *pp, u8 protocol)
 {
+	int want_ncq = (protocol == ATA_PROT_NCQ);
+
+	if (pp->pp_flags & MV_PP_FLAG_EDMA_EN) {
+		int using_ncq = ((pp->pp_flags & MV_PP_FLAG_NCQ_EN) != 0);
+		if (want_ncq != using_ncq)
+			__mv_stop_dma(ap);
+	}
 	if (!(pp->pp_flags & MV_PP_FLAG_EDMA_EN)) {
+		struct mv_host_priv *hpriv = ap->host->private_data;
+		int hard_port = mv_hardport_from_port(ap->port_no);
+		void __iomem *hc_mmio = mv_hc_base_from_port(
+				ap->host->iomap[MV_PRIMARY_BAR], hard_port);
+		u32 hc_irq_cause, ipending;
+
 		/* clear EDMA event indicators, if any */
-		writelfl(0, base + EDMA_ERR_IRQ_CAUSE_OFS);
+		writelfl(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
 
-		mv_set_edma_ptrs(base, hpriv, pp);
+		/* clear EDMA interrupt indicator, if any */
+		hc_irq_cause = readl(hc_mmio + HC_IRQ_CAUSE_OFS);
+		ipending = (DEV_IRQ << hard_port) |
+				(CRPB_DMA_DONE << hard_port);
+		if (hc_irq_cause & ipending) {
+			writelfl(hc_irq_cause & ~ipending,
+				 hc_mmio + HC_IRQ_CAUSE_OFS);
+		}
 
-		writelfl(EDMA_EN, base + EDMA_CMD_OFS);
+		mv_edma_cfg(pp, hpriv, port_mmio, want_ncq);
+
+		/* clear FIS IRQ Cause */
+		writelfl(0, port_mmio + SATA_FIS_IRQ_CAUSE_OFS);
+
+		mv_set_edma_ptrs(port_mmio, hpriv, pp);
+
+		writelfl(EDMA_EN, port_mmio + EDMA_CMD_OFS);
 		pp->pp_flags |= MV_PP_FLAG_EDMA_EN;
 	}
-	WARN_ON(!(EDMA_EN & readl(base + EDMA_CMD_OFS)));
+	WARN_ON(!(EDMA_EN & readl(port_mmio + EDMA_CMD_OFS)));
 }
 
 /**
@@ -1003,38 +1029,76 @@
 		return -EINVAL;
 }
 
-static void mv_edma_cfg(struct ata_port *ap, struct mv_host_priv *hpriv,
-			void __iomem *port_mmio)
+static void mv6_dev_config(struct ata_device *adev)
 {
-	u32 cfg = readl(port_mmio + EDMA_CFG_OFS);
+	/*
+	 * We don't have hob_nsect when doing NCQ commands on Gen-II.
+	 * See mv_qc_prep() for more info.
+	 */
+	if (adev->flags & ATA_DFLAG_NCQ)
+		if (adev->max_sectors > ATA_MAX_SECTORS)
+			adev->max_sectors = ATA_MAX_SECTORS;
+}
+
+static void mv_edma_cfg(struct mv_port_priv *pp, struct mv_host_priv *hpriv,
+			void __iomem *port_mmio, int want_ncq)
+{
+	u32 cfg;
 
 	/* set up non-NCQ EDMA configuration */
-	cfg &= ~(1 << 9);	/* disable eQue */
+	cfg = EDMA_CFG_Q_DEPTH;		/* always 0x1f for *all* chips */
 
-	if (IS_GEN_I(hpriv)) {
-		cfg &= ~0x1f;		/* clear queue depth */
+	if (IS_GEN_I(hpriv))
 		cfg |= (1 << 8);	/* enab config burst size mask */
-	}
 
-	else if (IS_GEN_II(hpriv)) {
-		cfg &= ~0x1f;		/* clear queue depth */
+	else if (IS_GEN_II(hpriv))
 		cfg |= EDMA_CFG_RD_BRST_EXT | EDMA_CFG_WR_BUFF_LEN;
-		cfg &= ~(EDMA_CFG_NCQ | EDMA_CFG_NCQ_GO_ON_ERR); /* clear NCQ */
-	}
 
 	else if (IS_GEN_IIE(hpriv)) {
 		cfg |= (1 << 23);	/* do not mask PM field in rx'd FIS */
 		cfg |= (1 << 22);	/* enab 4-entry host queue cache */
-		cfg &= ~(1 << 19);	/* dis 128-entry queue (for now?) */
 		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);	/* clear NCQ */
 	}
 
+	if (want_ncq) {
+		cfg |= EDMA_CFG_NCQ;
+		pp->pp_flags |=  MV_PP_FLAG_NCQ_EN;
+	} else
+		pp->pp_flags &= ~MV_PP_FLAG_NCQ_EN;
+
 	writelfl(cfg, port_mmio + EDMA_CFG_OFS);
 }
 
+static void mv_port_free_dma_mem(struct ata_port *ap)
+{
+	struct mv_host_priv *hpriv = ap->host->private_data;
+	struct mv_port_priv *pp = ap->private_data;
+	int tag;
+
+	if (pp->crqb) {
+		dma_pool_free(hpriv->crqb_pool, pp->crqb, pp->crqb_dma);
+		pp->crqb = NULL;
+	}
+	if (pp->crpb) {
+		dma_pool_free(hpriv->crpb_pool, pp->crpb, pp->crpb_dma);
+		pp->crpb = NULL;
+	}
+	/*
+	 * For GEN_I, there's no NCQ, so we have only a single sg_tbl.
+	 * For later hardware, we have one unique sg_tbl per NCQ tag.
+	 */
+	for (tag = 0; tag < MV_MAX_Q_DEPTH; ++tag) {
+		if (pp->sg_tbl[tag]) {
+			if (tag == 0 || !IS_GEN_I(hpriv))
+				dma_pool_free(hpriv->sg_tbl_pool,
+					      pp->sg_tbl[tag],
+					      pp->sg_tbl_dma[tag]);
+			pp->sg_tbl[tag] = NULL;
+		}
+	}
+}
+
 /**
  *      mv_port_start - Port specific init/start routine.
  *      @ap: ATA channel to manipulate
@@ -1051,51 +1115,47 @@
 	struct mv_host_priv *hpriv = ap->host->private_data;
 	struct mv_port_priv *pp;
 	void __iomem *port_mmio = mv_ap_base(ap);
-	void *mem;
-	dma_addr_t mem_dma;
 	unsigned long flags;
-	int rc;
+	int tag, rc;
 
 	pp = devm_kzalloc(dev, sizeof(*pp), GFP_KERNEL);
 	if (!pp)
 		return -ENOMEM;
-
-	mem = dmam_alloc_coherent(dev, MV_PORT_PRIV_DMA_SZ, &mem_dma,
-				  GFP_KERNEL);
-	if (!mem)
-		return -ENOMEM;
-	memset(mem, 0, MV_PORT_PRIV_DMA_SZ);
+	ap->private_data = pp;
 
 	rc = ata_pad_alloc(ap, dev);
 	if (rc)
 		return rc;
 
-	/* First item in chunk of DMA memory:
-	 * 32-slot command request table (CRQB), 32 bytes each in size
-	 */
-	pp->crqb = mem;
-	pp->crqb_dma = mem_dma;
-	mem += MV_CRQB_Q_SZ;
-	mem_dma += MV_CRQB_Q_SZ;
+	pp->crqb = dma_pool_alloc(hpriv->crqb_pool, GFP_KERNEL, &pp->crqb_dma);
+	if (!pp->crqb)
+		return -ENOMEM;
+	memset(pp->crqb, 0, MV_CRQB_Q_SZ);
 
-	/* Second item:
-	 * 32-slot command response table (CRPB), 8 bytes each in size
-	 */
-	pp->crpb = mem;
-	pp->crpb_dma = mem_dma;
-	mem += MV_CRPB_Q_SZ;
-	mem_dma += MV_CRPB_Q_SZ;
+	pp->crpb = dma_pool_alloc(hpriv->crpb_pool, GFP_KERNEL, &pp->crpb_dma);
+	if (!pp->crpb)
+		goto out_port_free_dma_mem;
+	memset(pp->crpb, 0, MV_CRPB_Q_SZ);
 
-	/* Third item:
-	 * Table of scatter-gather descriptors (ePRD), 16 bytes each
+	/*
+	 * For GEN_I, there's no NCQ, so we only allocate a single sg_tbl.
+	 * For later hardware, we need one unique sg_tbl per NCQ tag.
 	 */
-	pp->sg_tbl = mem;
-	pp->sg_tbl_dma = mem_dma;
+	for (tag = 0; tag < MV_MAX_Q_DEPTH; ++tag) {
+		if (tag == 0 || !IS_GEN_I(hpriv)) {
+			pp->sg_tbl[tag] = dma_pool_alloc(hpriv->sg_tbl_pool,
+					      GFP_KERNEL, &pp->sg_tbl_dma[tag]);
+			if (!pp->sg_tbl[tag])
+				goto out_port_free_dma_mem;
+		} else {
+			pp->sg_tbl[tag]     = pp->sg_tbl[0];
+			pp->sg_tbl_dma[tag] = pp->sg_tbl_dma[0];
+		}
+	}
 
 	spin_lock_irqsave(&ap->host->lock, flags);
 
-	mv_edma_cfg(ap, hpriv, port_mmio);
-
+	mv_edma_cfg(pp, hpriv, port_mmio, 0);
 	mv_set_edma_ptrs(port_mmio, hpriv, pp);
 
 	spin_unlock_irqrestore(&ap->host->lock, flags);
@@ -1104,8 +1164,11 @@
 	 * we'll be unable to send non-data, PIO, etc due to restricted access
 	 * to shadow regs.
 	 */
-	ap->private_data = pp;
 	return 0;
+
+out_port_free_dma_mem:
+	mv_port_free_dma_mem(ap);
+	return -ENOMEM;
 }
 
 /**
@@ -1120,6 +1183,7 @@
 static void mv_port_stop(struct ata_port *ap)
 {
 	mv_stop_dma(ap);
+	mv_port_free_dma_mem(ap);
 }
 
 /**
@@ -1138,7 +1202,7 @@
 	struct mv_sg *mv_sg, *last_sg = NULL;
 	unsigned int si;
 
-	mv_sg = pp->sg_tbl;
+	mv_sg = pp->sg_tbl[qc->tag];
 	for_each_sg(qc->sg, sg, qc->n_elem, si) {
 		dma_addr_t addr = sg_dma_address(sg);
 		u32 sg_len = sg_dma_len(sg);
@@ -1194,7 +1258,8 @@
 	u16 flags = 0;
 	unsigned in_index;
 
-	if (qc->tf.protocol != ATA_PROT_DMA)
+	if ((qc->tf.protocol != ATA_PROT_DMA) &&
+	    (qc->tf.protocol != ATA_PROT_NCQ))
 		return;
 
 	/* Fill in command request block
@@ -1203,15 +1268,14 @@
 		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 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);
+		cpu_to_le32(pp->sg_tbl_dma[qc->tag] & 0xffffffff);
 	pp->crqb[in_index].sg_addr_hi =
-		cpu_to_le32((pp->sg_tbl_dma >> 16) >> 16);
+		cpu_to_le32((pp->sg_tbl_dma[qc->tag] >> 16) >> 16);
 	pp->crqb[in_index].ctrl_flags = cpu_to_le16(flags);
 
 	cw = &pp->crqb[in_index].ata_cmd[0];
@@ -1231,13 +1295,11 @@
 	case ATA_CMD_WRITE_FUA_EXT:
 		mv_crqb_pack_cmd(cw++, tf->hob_nsect, ATA_REG_NSECT, 0);
 		break;
-#ifdef LIBATA_NCQ		/* FIXME: remove this line when NCQ added */
 	case ATA_CMD_FPDMA_READ:
 	case ATA_CMD_FPDMA_WRITE:
 		mv_crqb_pack_cmd(cw++, tf->hob_feature, ATA_REG_FEATURE, 0);
 		mv_crqb_pack_cmd(cw++, tf->feature, ATA_REG_FEATURE, 0);
 		break;
-#endif				/* FIXME: remove this line when NCQ added */
 	default:
 		/* The only other commands EDMA supports in non-queued and
 		 * non-NCQ mode are: [RW] STREAM DMA and W DMA FUA EXT, none
@@ -1286,7 +1348,8 @@
 	unsigned in_index;
 	u32 flags = 0;
 
-	if (qc->tf.protocol != ATA_PROT_DMA)
+	if ((qc->tf.protocol != ATA_PROT_DMA) &&
+	    (qc->tf.protocol != ATA_PROT_NCQ))
 		return;
 
 	/* Fill in Gen IIE command request block
@@ -1296,15 +1359,14 @@
 
 	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 */
+	flags |= qc->tag << CRQB_HOSTQ_SHIFT;
 
 	/* 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);
-	crqb->addr_hi = cpu_to_le32((pp->sg_tbl_dma >> 16) >> 16);
+	crqb->addr = cpu_to_le32(pp->sg_tbl_dma[qc->tag] & 0xffffffff);
+	crqb->addr_hi = cpu_to_le32((pp->sg_tbl_dma[qc->tag] >> 16) >> 16);
 	crqb->flags = cpu_to_le32(flags);
 
 	tf = &qc->tf;
@@ -1351,10 +1413,10 @@
 	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 (qc->tf.protocol != ATA_PROT_DMA) {
+	if ((qc->tf.protocol != ATA_PROT_DMA) &&
+	    (qc->tf.protocol != ATA_PROT_NCQ)) {
 		/* 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.
@@ -1363,13 +1425,7 @@
 		return ata_qc_issue_prot(qc);
 	}
 
-	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));
+	mv_start_dma(ap, port_mmio, pp, qc->tf.protocol);
 
 	pp->req_idx++;
 
@@ -1437,6 +1493,7 @@
 		ata_ehi_hotplugged(ehi);
 		ata_ehi_push_desc(ehi, edma_err_cause & EDMA_ERR_DEV_DCON ?
 			"dev disconnect" : "dev connect");
+		action |= ATA_EH_HARDRESET;
 	}
 
 	if (IS_GEN_I(hpriv)) {
@@ -1465,7 +1522,7 @@
 	}
 
 	/* Clear EDMA now that SERR cleanup done */
-	writelfl(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
+	writelfl(~edma_err_cause, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
 
 	if (!err_mask) {
 		err_mask = AC_ERR_OTHER;
@@ -1538,23 +1595,17 @@
 		 * support for queueing.  this works transparently for
 		 * queued and non-queued modes.
 		 */
-		else if (IS_GEN_II(hpriv))
-			tag = (le16_to_cpu(pp->crpb[out_index].id)
-				>> CRPB_IOID_SHIFT_6) & 0x3f;
-
-		else /* IS_GEN_IIE */
-			tag = (le16_to_cpu(pp->crpb[out_index].id)
-				>> CRPB_IOID_SHIFT_7) & 0x3f;
+		else
+			tag = le16_to_cpu(pp->crpb[out_index].id) & 0x1f;
 
 		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
+		/* For non-NCQ mode, the lower 8 bits of status
+		 * are from EDMA_ERR_IRQ_CAUSE_OFS,
+		 * which should be zero if all went well.
 		 */
 		status = le16_to_cpu(pp->crpb[out_index].flags);
-		if (unlikely(status & 0xff)) {
+		if ((status & 0xff) && !(pp->pp_flags & MV_PP_FLAG_NCQ_EN)) {
 			mv_err_intr(ap, qc);
 			return;
 		}
@@ -1715,20 +1766,21 @@
 	struct ata_host *host = dev_instance;
 	unsigned int hc, handled = 0, n_hcs;
 	void __iomem *mmio = host->iomap[MV_PRIMARY_BAR];
-	u32 irq_stat;
+	u32 irq_stat, irq_mask;
 
+	spin_lock(&host->lock);
 	irq_stat = readl(mmio + HC_MAIN_IRQ_CAUSE_OFS);
+	irq_mask = readl(mmio + HC_MAIN_IRQ_MASK_OFS);
 
 	/* check the cases where we either have nothing pending or have read
 	 * a bogus register value which can indicate HW removal or PCI fault
 	 */
-	if (!irq_stat || (0xffffffffU == irq_stat))
-		return IRQ_NONE;
+	if (!(irq_stat & irq_mask) || (0xffffffffU == irq_stat))
+		goto out_unlock;
 
 	n_hcs = mv_get_hc_count(host->ports[0]->flags);
-	spin_lock(&host->lock);
 
-	if (unlikely(irq_stat & PCI_ERR)) {
+	if (unlikely((irq_stat & PCI_ERR) && HAS_PCI(host))) {
 		mv_pci_error(host, mmio);
 		handled = 1;
 		goto out_unlock;	/* skip all other HC irq handling */
@@ -1799,8 +1851,9 @@
 		return -EINVAL;
 }
 
-static void mv5_reset_bus(struct pci_dev *pdev, void __iomem *mmio)
+static void mv5_reset_bus(struct ata_host *host, void __iomem *mmio)
 {
+	struct pci_dev *pdev = to_pci_dev(host->dev);
 	int early_5080;
 
 	early_5080 = (pdev->device == 0x5080) && (pdev->revision == 0);
@@ -1811,7 +1864,7 @@
 		writel(tmp, mmio + MV_PCI_EXP_ROM_BAR_CTL);
 	}
 
-	mv_reset_pci_bus(pdev, mmio);
+	mv_reset_pci_bus(host, mmio);
 }
 
 static void mv5_reset_flash(struct mv_host_priv *hpriv, void __iomem *mmio)
@@ -1935,9 +1988,8 @@
 
 #undef ZERO
 #define ZERO(reg) writel(0, mmio + (reg))
-static void mv_reset_pci_bus(struct pci_dev *pdev, void __iomem *mmio)
+static void mv_reset_pci_bus(struct ata_host *host, void __iomem *mmio)
 {
-	struct ata_host     *host = dev_get_drvdata(&pdev->dev);
 	struct mv_host_priv *hpriv = host->private_data;
 	u32 tmp;
 
@@ -2329,11 +2381,6 @@
 		  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];
@@ -2427,8 +2474,8 @@
 	writelfl(readl(port_mmio + serr_ofs), port_mmio + serr_ofs);
 	writelfl(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
 
-	/* unmask all EDMA error interrupts */
-	writelfl(~0, port_mmio + EDMA_ERR_IRQ_MASK_OFS);
+	/* unmask all non-transient EDMA error interrupts */
+	writelfl(~EDMA_ERR_IRQ_TRANSIENT, port_mmio + EDMA_ERR_IRQ_MASK_OFS);
 
 	VPRINTK("EDMA cfg=0x%08x EDMA IRQ err cause/mask=0x%08x/0x%08x\n",
 		readl(port_mmio + EDMA_CFG_OFS),
@@ -2586,7 +2633,6 @@
 static int mv_init_host(struct ata_host *host, unsigned int board_idx)
 {
 	int rc = 0, n_hc, port, hc;
-	struct pci_dev *pdev = to_pci_dev(host->dev);
 	void __iomem *mmio = host->iomap[MV_PRIMARY_BAR];
 	struct mv_host_priv *hpriv = host->private_data;
 
@@ -2607,7 +2653,7 @@
 		goto done;
 
 	hpriv->ops->reset_flash(hpriv, mmio);
-	hpriv->ops->reset_bus(pdev, mmio);
+	hpriv->ops->reset_bus(host, mmio);
 	hpriv->ops->enable_leds(hpriv, mmio);
 
 	for (port = 0; port < host->n_ports; port++) {
@@ -2630,8 +2676,10 @@
 
 		mv_port_init(&ap->ioaddr, port_mmio);
 
+#ifdef CONFIG_PCI
 		ata_port_pbar_desc(ap, MV_PRIMARY_BAR, -1, "mmio");
 		ata_port_pbar_desc(ap, MV_PRIMARY_BAR, offset, "port");
+#endif
 	}
 
 	for (hc = 0; hc < n_hc; hc++) {
@@ -2668,6 +2716,55 @@
 	return rc;
 }
 
+#ifdef CONFIG_PCI
+static int mv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
+
+static struct pci_driver mv_pci_driver = {
+	.name			= DRV_NAME,
+	.id_table		= mv_pci_tbl,
+	.probe			= mv_init_one,
+	.remove			= ata_pci_remove_one,
+};
+
+/*
+ * module options
+ */
+static int msi;	      /* Use PCI msi; either zero (off, default) or non-zero */
+
+
+/* move to PCI layer or libata core? */
+static int pci_go_64(struct pci_dev *pdev)
+{
+	int rc;
+
+	if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK)) {
+		rc = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK);
+		if (rc) {
+			rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
+			if (rc) {
+				dev_printk(KERN_ERR, &pdev->dev,
+					   "64-bit DMA enable failed\n");
+				return rc;
+			}
+		}
+	} else {
+		rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+		if (rc) {
+			dev_printk(KERN_ERR, &pdev->dev,
+				   "32-bit DMA enable failed\n");
+			return rc;
+		}
+		rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
+		if (rc) {
+			dev_printk(KERN_ERR, &pdev->dev,
+				   "32-bit consistent DMA enable failed\n");
+			return rc;
+		}
+	}
+
+	return rc;
+}
+
 /**
  *      mv_print_info - Dump key info to kernel log for perusal.
  *      @host: ATA host to print info about
@@ -2710,6 +2807,26 @@
 	       scc_s, (MV_HP_FLAG_MSI & hpriv->hp_flags) ? "MSI" : "INTx");
 }
 
+static int mv_create_dma_pools(struct mv_host_priv *hpriv, struct device *dev)
+{
+	hpriv->crqb_pool   = dmam_pool_create("crqb_q", dev, MV_CRQB_Q_SZ,
+							     MV_CRQB_Q_SZ, 0);
+	if (!hpriv->crqb_pool)
+		return -ENOMEM;
+
+	hpriv->crpb_pool   = dmam_pool_create("crpb_q", dev, MV_CRPB_Q_SZ,
+							     MV_CRPB_Q_SZ, 0);
+	if (!hpriv->crpb_pool)
+		return -ENOMEM;
+
+	hpriv->sg_tbl_pool = dmam_pool_create("sg_tbl", dev, MV_SG_TBL_SZ,
+							     MV_SG_TBL_SZ, 0);
+	if (!hpriv->sg_tbl_pool)
+		return -ENOMEM;
+
+	return 0;
+}
+
 /**
  *      mv_init_one - handle a positive probe of a Marvell host
  *      @pdev: PCI device found
@@ -2755,6 +2872,10 @@
 	if (rc)
 		return rc;
 
+	rc = mv_create_dma_pools(hpriv, &pdev->dev);
+	if (rc)
+		return rc;
+
 	/* initialize adapter */
 	rc = mv_init_host(host, board_idx);
 	if (rc)
@@ -2772,15 +2893,22 @@
 	return ata_host_activate(host, pdev->irq, mv_interrupt, IRQF_SHARED,
 				 IS_GEN_I(hpriv) ? &mv5_sht : &mv6_sht);
 }
+#endif
 
 static int __init mv_init(void)
 {
-	return pci_register_driver(&mv_pci_driver);
+	int rc = -ENODEV;
+#ifdef CONFIG_PCI
+	rc = pci_register_driver(&mv_pci_driver);
+#endif
+	return rc;
 }
 
 static void __exit mv_exit(void)
 {
+#ifdef CONFIG_PCI
 	pci_unregister_driver(&mv_pci_driver);
+#endif
 }
 
 MODULE_AUTHOR("Brett Russ");
@@ -2789,8 +2917,10 @@
 MODULE_DEVICE_TABLE(pci, mv_pci_tbl);
 MODULE_VERSION(DRV_VERSION);
 
+#ifdef CONFIG_PCI
 module_param(msi, int, 0444);
 MODULE_PARM_DESC(msi, "Enable use of PCI MSI (0=off, 1=on)");
+#endif
 
 module_init(mv_init);
 module_exit(mv_exit);
diff --git a/drivers/ata/sata_nv.c b/drivers/ata/sata_nv.c
index a0f98fd..bfe92a4 100644
--- a/drivers/ata/sata_nv.c
+++ b/drivers/ata/sata_nv.c
@@ -1011,14 +1011,20 @@
 			}
 
 			if (status & (NV_ADMA_STAT_DONE |
-				      NV_ADMA_STAT_CPBERR)) {
-				u32 check_commands;
+				      NV_ADMA_STAT_CPBERR |
+				      NV_ADMA_STAT_CMD_COMPLETE)) {
+				u32 check_commands = notifier_clears[i];
 				int pos, error = 0;
 
-				if (ata_tag_valid(ap->link.active_tag))
-					check_commands = 1 << ap->link.active_tag;
-				else
-					check_commands = ap->link.sactive;
+				if (status & NV_ADMA_STAT_CPBERR) {
+					/* Check all active commands */
+					if (ata_tag_valid(ap->link.active_tag))
+						check_commands = 1 <<
+							ap->link.active_tag;
+					else
+						check_commands = ap->
+							link.sactive;
+				}
 
 				/** Check CPBs for completed commands */
 				while ((pos = ffs(check_commands)) && !error) {
diff --git a/drivers/base/power/Makefile b/drivers/base/power/Makefile
index de28dfd..911208b 100644
--- a/drivers/base/power/Makefile
+++ b/drivers/base/power/Makefile
@@ -1,6 +1,6 @@
 obj-$(CONFIG_PM)	+= sysfs.o
 obj-$(CONFIG_PM_SLEEP)	+= main.o
-obj-$(CONFIG_PM_TRACE)	+= trace.o
+obj-$(CONFIG_PM_TRACE_RTC)	+= trace.o
 
 ccflags-$(CONFIG_DEBUG_DRIVER) := -DDEBUG
 ccflags-$(CONFIG_PM_VERBOSE)   += -DDEBUG
diff --git a/drivers/block/ub.c b/drivers/block/ub.c
index c6179d6..a70c1c2 100644
--- a/drivers/block/ub.c
+++ b/drivers/block/ub.c
@@ -922,11 +922,6 @@
 	usb_fill_bulk_urb(&sc->work_urb, sc->dev, sc->send_bulk_pipe,
 	    bcb, US_BULK_CB_WRAP_LEN, ub_urb_complete, sc);
 
-	/* Fill what we shouldn't be filling, because usb-storage did so. */
-	sc->work_urb.actual_length = 0;
-	sc->work_urb.error_count = 0;
-	sc->work_urb.status = 0;
-
 	if ((rc = usb_submit_urb(&sc->work_urb, GFP_ATOMIC)) != 0) {
 		/* XXX Clear stalls */
 		ub_complete(&sc->work_done);
@@ -1313,9 +1308,6 @@
 	sc->last_pipe = pipe;
 	usb_fill_bulk_urb(&sc->work_urb, sc->dev, pipe, sg_virt(sg),
 	    sg->length, ub_urb_complete, sc);
-	sc->work_urb.actual_length = 0;
-	sc->work_urb.error_count = 0;
-	sc->work_urb.status = 0;
 
 	if ((rc = usb_submit_urb(&sc->work_urb, GFP_ATOMIC)) != 0) {
 		/* XXX Clear stalls */
@@ -1356,9 +1348,6 @@
 	sc->last_pipe = sc->recv_bulk_pipe;
 	usb_fill_bulk_urb(&sc->work_urb, sc->dev, sc->recv_bulk_pipe,
 	    &sc->work_bcs, US_BULK_CS_WRAP_LEN, ub_urb_complete, sc);
-	sc->work_urb.actual_length = 0;
-	sc->work_urb.error_count = 0;
-	sc->work_urb.status = 0;
 
 	if ((rc = usb_submit_urb(&sc->work_urb, GFP_ATOMIC)) != 0) {
 		/* XXX Clear stalls */
@@ -1473,9 +1462,6 @@
 
 	usb_fill_control_urb(&sc->work_urb, sc->dev, sc->send_ctrl_pipe,
 	    (unsigned char*) cr, NULL, 0, ub_urb_complete, sc);
-	sc->work_urb.actual_length = 0;
-	sc->work_urb.error_count = 0;
-	sc->work_urb.status = 0;
 
 	if ((rc = usb_submit_urb(&sc->work_urb, GFP_ATOMIC)) != 0) {
 		ub_complete(&sc->work_done);
@@ -1953,9 +1939,6 @@
 
 	usb_fill_control_urb(&sc->work_urb, sc->dev, sc->send_ctrl_pipe,
 	    (unsigned char*) cr, NULL, 0, ub_probe_urb_complete, &compl);
-	sc->work_urb.actual_length = 0;
-	sc->work_urb.error_count = 0;
-	sc->work_urb.status = 0;
 
 	if ((rc = usb_submit_urb(&sc->work_urb, GFP_KERNEL)) != 0) {
 		printk(KERN_WARNING
@@ -2007,9 +1990,6 @@
 
 	usb_fill_control_urb(&sc->work_urb, sc->dev, sc->recv_ctrl_pipe,
 	    (unsigned char*) cr, p, 1, ub_probe_urb_complete, &compl);
-	sc->work_urb.actual_length = 0;
-	sc->work_urb.error_count = 0;
-	sc->work_urb.status = 0;
 
 	if ((rc = usb_submit_urb(&sc->work_urb, GFP_KERNEL)) != 0)
 		goto err_submit;
@@ -2077,9 +2057,6 @@
 
 	usb_fill_control_urb(&sc->work_urb, sc->dev, sc->send_ctrl_pipe,
 	    (unsigned char*) cr, NULL, 0, ub_probe_urb_complete, &compl);
-	sc->work_urb.actual_length = 0;
-	sc->work_urb.error_count = 0;
-	sc->work_urb.status = 0;
 
 	if ((rc = usb_submit_urb(&sc->work_urb, GFP_KERNEL)) != 0) {
 		printk(KERN_WARNING
diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c
index af05610..47e5b40 100644
--- a/drivers/cdrom/cdrom.c
+++ b/drivers/cdrom/cdrom.c
@@ -2787,12 +2787,6 @@
 	return -ENOSYS;
 }
 
-static inline
-int msf_to_lba(char m, char s, char f)
-{
-	return (((m * CD_SECS) + s) * CD_FRAMES + f) - CD_MSF_OFFSET;
-}
-
 /*
  * Required when we need to use READ_10 to issue other than 2048 block
  * reads
diff --git a/drivers/char/tty_audit.c b/drivers/char/tty_audit.c
index d222012..bacded0 100644
--- a/drivers/char/tty_audit.c
+++ b/drivers/char/tty_audit.c
@@ -73,6 +73,7 @@
  *	@tsk with @loginuid.  @buf->mutex must be locked.
  */
 static void tty_audit_buf_push(struct task_struct *tsk, uid_t loginuid,
+			       unsigned int sessionid,
 			       struct tty_audit_buf *buf)
 {
 	struct audit_buffer *ab;
@@ -85,9 +86,9 @@
 	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);
+		audit_log_format(ab, "tty pid=%u uid=%u auid=%u ses=%u "
+				 "major=%d minor=%d comm=", tsk->pid, tsk->uid,
+				 loginuid, sessionid, buf->major, buf->minor);
 		get_task_comm(name, tsk);
 		audit_log_untrustedstring(ab, name);
 		audit_log_format(ab, " data=");
@@ -105,8 +106,9 @@
  */
 static void tty_audit_buf_push_current(struct tty_audit_buf *buf)
 {
-	tty_audit_buf_push(current, audit_get_loginuid(current->audit_context),
-			   buf);
+	uid_t auid = audit_get_loginuid(current);
+	unsigned int sessionid = audit_get_sessionid(current);
+	tty_audit_buf_push(current, auid, sessionid, buf);
 }
 
 /**
@@ -152,6 +154,11 @@
 void tty_audit_push_task(struct task_struct *tsk, uid_t loginuid)
 {
 	struct tty_audit_buf *buf;
+	/* FIXME I think this is correct.  Check against netlink once that is
+	 * I really need to read this code more closely.  But that's for
+	 * another patch.
+	 */
+	unsigned int sessionid = audit_get_sessionid(tsk);
 
 	spin_lock_irq(&tsk->sighand->siglock);
 	buf = tsk->signal->tty_audit_buf;
@@ -162,7 +169,7 @@
 		return;
 
 	mutex_lock(&buf->mutex);
-	tty_audit_buf_push(tsk, loginuid, buf);
+	tty_audit_buf_push(tsk, loginuid, sessionid, buf);
 	mutex_unlock(&buf->mutex);
 
 	tty_audit_buf_put(buf);
diff --git a/drivers/i2c/busses/scx200_acb.c b/drivers/i2c/busses/scx200_acb.c
index e6c4a2b..f5e7a70 100644
--- a/drivers/i2c/busses/scx200_acb.c
+++ b/drivers/i2c/busses/scx200_acb.c
@@ -492,7 +492,7 @@
 	iface->pdev = pdev;
 	iface->bar = bar;
 
-	rc = pci_enable_device_bars(iface->pdev, 1 << iface->bar);
+	rc = pci_enable_device_io(iface->pdev);
 	if (rc)
 		goto errout_free;
 
diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig
index 64df55e..e42a465 100644
--- a/drivers/ide/Kconfig
+++ b/drivers/ide/Kconfig
@@ -206,6 +206,15 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called ide-cd.
 
+config BLK_DEV_IDECD_VERBOSE_ERRORS
+	bool "Verbose error logging for IDE/ATAPI CDROM driver" if EMBEDDED
+	depends on BLK_DEV_IDECD
+	default y
+	help
+	  Turn this on to have the driver print out the meanings of the
+	  ATAPI error codes.  This will use up additional 8kB of kernel-space
+	  memory, though.
+
 config BLK_DEV_IDETAPE
 	tristate "Include IDE/ATAPI TAPE support (EXPERIMENTAL)"
 	depends on EXPERIMENTAL
@@ -617,8 +626,8 @@
 	tristate "National SCx200 chipset support"
 	select BLK_DEV_IDEDMA_PCI
 	help
-	  This driver adds support for the built in IDE on the National
-	  SCx200 series of embedded x86 "Geode" systems
+	  This driver adds support for the on-board IDE controller on the
+	  National SCx200 series of embedded x86 "Geode" systems.
 
 config BLK_DEV_PIIX
 	tristate "Intel PIIXn chipsets support"
@@ -793,22 +802,22 @@
 	depends on PPC_CELLEB
 	select BLK_DEV_IDEDMA_PCI
 	help
-	  This driver provides support for the built-in IDE controller on
+	  This driver provides support for the on-board IDE controller on
 	  Toshiba Cell Reference Board.
 	  If unsure, say Y.
 
 endif
 
 config BLK_DEV_IDE_PMAC
-	tristate "Builtin PowerMac IDE support"
+	tristate "PowerMac on-board IDE support"
 	depends on PPC_PMAC && IDE=y && BLK_DEV_IDE=y
 	help
-	  This driver provides support for the built-in IDE controller on
+	  This driver provides support for the on-board IDE controller on
 	  most of the recent Apple Power Macintoshes and PowerBooks.
 	  If unsure, say Y.
 
 config BLK_DEV_IDE_PMAC_ATA100FIRST
-	bool "Probe internal ATA/100 (Kauai) first"
+	bool "Probe on-board ATA/100 (Kauai) first"
 	depends on BLK_DEV_IDE_PMAC
 	help
 	  This option will cause the ATA/100 controller found in UniNorth2
@@ -823,7 +832,7 @@
 	depends on BLK_DEV_IDE_PMAC
 	select BLK_DEV_IDEDMA_PCI
 	help
-	  This option allows the driver for the built-in IDE controller on
+	  This option allows the driver for the on-board IDE controller on
 	  Power Macintoshes and PowerBooks to use DMA (direct memory access)
 	  to transfer data to and from memory.  Saying Y is safe and improves
 	  performance.
@@ -934,7 +943,7 @@
 	help
 	  This is the IDE driver for the Amiga Gayle IDE interface. It supports
 	  both the `A1200 style' and `A4000 style' of the Gayle IDE interface,
-	  This includes builtin IDE interfaces on some Amiga models (A600,
+	  This includes on-board IDE interfaces on some Amiga models (A600,
 	  A1200, A4000, and A4000T), and IDE interfaces on the Zorro expansion
 	  bus (M-Tech E-Matrix 530 expansion card).
 	  Say Y if you have an Amiga with a Gayle IDE interface and want to use
@@ -948,10 +957,10 @@
 	depends on BLK_DEV_GAYLE && EXPERIMENTAL
 	---help---
 	  This driver provides support for the so-called `IDE doublers' (made
-	  by various manufacturers, e.g. Eyetech) that can be connected to the
-	  builtin IDE interface of some Amiga models. Using such an IDE
-	  doubler, you can connect up to four instead of two IDE devices on
-	  the Amiga's builtin IDE interface.
+	  by various manufacturers, e.g. Eyetech) that can be connected to
+	  the on-board IDE interface of some Amiga models. Using such an IDE
+	  doubler, you can connect up to four instead of two IDE devices to
+	  the Amiga's on-board IDE interface.
 
 	  Note that the normal Amiga Gayle IDE driver may not work correctly
 	  if you have an IDE doubler and don't enable this driver!
@@ -963,9 +972,9 @@
 	tristate "Buddha/Catweasel/X-Surf IDE interface support (EXPERIMENTAL)"
 	depends on ZORRO && EXPERIMENTAL
 	help
-	  This is the IDE driver for the IDE interfaces on the Buddha, 
-	  Catweasel and X-Surf expansion boards.  It supports up to two interfaces 
-	  on the Buddha, three on the Catweasel and two on the X-Surf.
+	  This is the IDE driver for the IDE interfaces on the Buddha, Catweasel
+	  and X-Surf expansion boards.  It supports up to two interfaces on the
+	  Buddha, three on the Catweasel and two on the X-Surf.
 
 	  Say Y if you have a Buddha or Catweasel expansion board and want to
 	  use IDE devices (hard disks, CD-ROM drives, etc.) that are connected
@@ -975,23 +984,23 @@
 	tristate "Falcon IDE interface support"
 	depends on ATARI
 	help
-	  This is the IDE driver for the builtin IDE interface on the Atari
+	  This is the IDE driver for the on-board IDE interface on the Atari
 	  Falcon. Say Y if you have a Falcon and want to use IDE devices (hard
-	  disks, CD-ROM drives, etc.) that are connected to the builtin IDE
+	  disks, CD-ROM drives, etc.) that are connected to the on-board IDE
 	  interface.
 
 config BLK_DEV_MAC_IDE
 	tristate "Macintosh Quadra/Powerbook IDE interface support"
 	depends on MAC
 	help
-	  This is the IDE driver for the builtin IDE interface on some m68k
+	  This is the IDE driver for the on-board IDE interface on some m68k
 	  Macintosh models. It supports both the `Quadra style' (used in
 	  Quadra/ Centris 630 and Performa 588 models) and `Powerbook style'
 	  (used in the Powerbook 150 and 190 models) IDE interface.
 
 	  Say Y if you have such an Macintosh model and want to use IDE
 	  devices (hard disks, CD-ROM drives, etc.) that are connected to the
-	  builtin IDE interface.
+	  on-board IDE interface.
 
 config BLK_DEV_Q40IDE
 	tristate "Q40/Q60 IDE interface support"
@@ -1062,8 +1071,8 @@
 	  boot parameter.  It enables support for the secondary IDE interface
 	  of the ALI M1439/1443/1445/1487/1489 chipsets, and permits faster
 	  I/O speeds to be set as well.  See the files
-	  <file:Documentation/ide.txt> and <file:drivers/ide/legacy/ali14xx.c> for
-	  more info.
+	  <file:Documentation/ide.txt> and <file:drivers/ide/legacy/ali14xx.c>
+	  for more info.
 
 config BLK_DEV_DTC2278
 	tristate "DTC-2278 support"
@@ -1088,8 +1097,8 @@
 	help
 	  This driver is enabled at runtime using the "qd65xx.probe" kernel
 	  boot parameter.  It permits faster I/O speeds to be set.  See the
-	  <file:Documentation/ide.txt> and <file:drivers/ide/legacy/qd65xx.c> for
-	  more info.
+	  <file:Documentation/ide.txt> and <file:drivers/ide/legacy/qd65xx.c>
+	  for more info.
 
 config BLK_DEV_UMC8672
 	tristate "UMC-8672 support"
diff --git a/drivers/ide/Makefile b/drivers/ide/Makefile
index 0d2da89..a4a4323b 100644
--- a/drivers/ide/Makefile
+++ b/drivers/ide/Makefile
@@ -40,8 +40,10 @@
 obj-$(CONFIG_IDE_H8300)			+= h8300/
 obj-$(CONFIG_IDE_GENERIC)		+= ide-generic.o
 
+ide-cd_mod-y += ide-cd.o ide-cd_ioctl.o ide-cd_verbose.o
+
 obj-$(CONFIG_BLK_DEV_IDEDISK)		+= ide-disk.o
-obj-$(CONFIG_BLK_DEV_IDECD)		+= ide-cd.o
+obj-$(CONFIG_BLK_DEV_IDECD)		+= ide-cd_mod.o
 obj-$(CONFIG_BLK_DEV_IDETAPE)		+= ide-tape.o
 obj-$(CONFIG_BLK_DEV_IDEFLOPPY)		+= ide-floppy.o
 
diff --git a/drivers/ide/arm/bast-ide.c b/drivers/ide/arm/bast-ide.c
index 45bf9c8..037300f 100644
--- a/drivers/ide/arm/bast-ide.c
+++ b/drivers/ide/arm/bast-ide.c
@@ -1,5 +1,4 @@
-/* linux/drivers/ide/arm/bast-ide.c
- *
+/*
  * Copyright (c) 2003-2004 Simtec Electronics
  *  Ben Dooks <ben@simtec.co.uk>
  *
diff --git a/drivers/ide/arm/icside.c b/drivers/ide/arm/icside.c
index 8a5c720..8d2cc47 100644
--- a/drivers/ide/arm/icside.c
+++ b/drivers/ide/arm/icside.c
@@ -1,6 +1,4 @@
 /*
- * linux/drivers/ide/arm/icside.c
- *
  * Copyright (c) 1996-2004 Russell King.
  *
  * Please note that this platform does not support 32-bit IDE IO.
@@ -71,8 +69,6 @@
 	void __iomem *irq_port;
 	void __iomem *ioc_base;
 	unsigned int type;
-	/* parent device... until the IDE core gets one of its own */
-	struct device *dev;
 	ide_hwif_t *hwif[2];
 };
 
@@ -206,23 +202,6 @@
  * interfaces use the same IRQ, which should guarantee this.
  */
 
-static void icside_build_sglist(ide_drive_t *drive, struct request *rq)
-{
-	ide_hwif_t *hwif = drive->hwif;
-	struct icside_state *state = hwif->hwif_data;
-	struct scatterlist *sg = hwif->sg_table;
-
-	ide_map_sg(drive, rq);
-
-	if (rq_data_dir(rq) == READ)
-		hwif->sg_dma_direction = DMA_FROM_DEVICE;
-	else
-		hwif->sg_dma_direction = DMA_TO_DEVICE;
-
-	hwif->sg_nents = dma_map_sg(state->dev, sg, hwif->sg_nents,
-				    hwif->sg_dma_direction);
-}
-
 /*
  * Configure the IOMD to give the appropriate timings for the transfer
  * mode being requested.  We take the advice of the ATA standards, and
@@ -294,33 +273,32 @@
 static int icside_dma_end(ide_drive_t *drive)
 {
 	ide_hwif_t *hwif = HWIF(drive);
-	struct icside_state *state = hwif->hwif_data;
+	struct expansion_card *ec = ECARD_DEV(hwif->dev);
 
 	drive->waiting_for_dma = 0;
 
-	disable_dma(ECARD_DEV(state->dev)->dma);
+	disable_dma(ec->dma);
 
 	/* Teardown mappings after DMA has completed. */
-	dma_unmap_sg(state->dev, hwif->sg_table, hwif->sg_nents,
-		     hwif->sg_dma_direction);
+	ide_destroy_dmatable(drive);
 
-	return get_dma_residue(ECARD_DEV(state->dev)->dma) != 0;
+	return get_dma_residue(ec->dma) != 0;
 }
 
 static void icside_dma_start(ide_drive_t *drive)
 {
 	ide_hwif_t *hwif = HWIF(drive);
-	struct icside_state *state = hwif->hwif_data;
+	struct expansion_card *ec = ECARD_DEV(hwif->dev);
 
 	/* We can not enable DMA on both channels simultaneously. */
-	BUG_ON(dma_channel_active(ECARD_DEV(state->dev)->dma));
-	enable_dma(ECARD_DEV(state->dev)->dma);
+	BUG_ON(dma_channel_active(ec->dma));
+	enable_dma(ec->dma);
 }
 
 static int icside_dma_setup(ide_drive_t *drive)
 {
 	ide_hwif_t *hwif = HWIF(drive);
-	struct icside_state *state = hwif->hwif_data;
+	struct expansion_card *ec = ECARD_DEV(hwif->dev);
 	struct request *rq = hwif->hwgroup->rq;
 	unsigned int dma_mode;
 
@@ -332,9 +310,9 @@
 	/*
 	 * We can not enable DMA on both channels.
 	 */
-	BUG_ON(dma_channel_active(ECARD_DEV(state->dev)->dma));
+	BUG_ON(dma_channel_active(ec->dma));
 
-	icside_build_sglist(drive, rq);
+	hwif->sg_nents = ide_build_sglist(drive, rq);
 
 	/*
 	 * Ensure that we have the right interrupt routed.
@@ -349,14 +327,14 @@
 	/*
 	 * Select the correct timing for this drive.
 	 */
-	set_dma_speed(ECARD_DEV(state->dev)->dma, drive->drive_data);
+	set_dma_speed(ec->dma, drive->drive_data);
 
 	/*
 	 * Tell the DMA engine about the SG table and
 	 * data direction.
 	 */
-	set_dma_sg(ECARD_DEV(state->dev)->dma, hwif->sg_table, hwif->sg_nents);
-	set_dma_mode(ECARD_DEV(state->dev)->dma, dma_mode);
+	set_dma_sg(ec->dma, hwif->sg_table, hwif->sg_nents);
+	set_dma_mode(ec->dma, dma_mode);
 
 	drive->waiting_for_dma = 1;
 
@@ -444,6 +422,7 @@
 		hwif->noprobe = 0;
 		hwif->chipset = ide_acorn;
 		hwif->gendev.parent = &ec->dev;
+		hwif->dev = &ec->dev;
 	}
 
 	return hwif;
@@ -591,7 +570,6 @@
 	}
 
 	state->type	= ICS_TYPE_NOTYPE;
-	state->dev	= &ec->dev;
 
 	idmem = ecardm_iomap(ec, ECARD_RES_IOCFAST, 0, 0);
 	if (idmem) {
diff --git a/drivers/ide/arm/rapide.c b/drivers/ide/arm/rapide.c
index e6b56d1..c8b6581 100644
--- a/drivers/ide/arm/rapide.c
+++ b/drivers/ide/arm/rapide.c
@@ -1,6 +1,4 @@
 /*
- * linux/drivers/ide/arm/rapide.c
- *
  * Copyright (c) 1996-2002 Russell King.
  */
 
@@ -78,8 +76,8 @@
 
 	ecard_set_drvdata(ec, NULL);
 
-	/* there must be a better way */
-	ide_unregister(hwif - ide_hwifs);
+	ide_unregister(hwif->index);
+
 	ecard_release_resources(ec);
 }
 
diff --git a/drivers/ide/cris/ide-cris.c b/drivers/ide/cris/ide-cris.c
index 8c3294c..0640a38 100644
--- a/drivers/ide/cris/ide-cris.c
+++ b/drivers/ide/cris/ide-cris.c
@@ -1,5 +1,4 @@
-/* $Id: cris-ide-driver.patch,v 1.1 2005/06/29 21:39:07 akpm Exp $
- *
+/*
  * Etrax specific IDE functions, like init and PIO-mode setting etc.
  * Almost the entire ide.c is used for the rest of the Etrax ATA driver.
  * Copyright (c) 2000-2005 Axis Communications AB
diff --git a/drivers/ide/h8300/ide-h8300.c b/drivers/ide/h8300/ide-h8300.c
index 4f6d019..0243295 100644
--- a/drivers/ide/h8300/ide-h8300.c
+++ b/drivers/ide/h8300/ide-h8300.c
@@ -1,5 +1,4 @@
 /*
- * drivers/ide/h8300/ide-h8300.c
  * H8/300 generic IDE interface
  */
 
diff --git a/drivers/ide/ide-acpi.c b/drivers/ide/ide-acpi.c
index e888fc3..68bc618 100644
--- a/drivers/ide/ide-acpi.c
+++ b/drivers/ide/ide-acpi.c
@@ -1,5 +1,4 @@
 /*
- * ide-acpi.c
  * Provides ACPI support for IDE drives.
  *
  * Copyright (C) 2005 Intel Corp.
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c
index bee05a3..23074e8 100644
--- a/drivers/ide/ide-cd.c
+++ b/drivers/ide/ide-cd.c
@@ -1,14 +1,14 @@
 /*
- * linux/drivers/ide/ide-cd.c
+ * ATAPI CD-ROM driver.
  *
- * Copyright (C) 1994, 1995, 1996  scott snyder  <snyder@fnald0.fnal.gov>
- * Copyright (C) 1996-1998  Erik Andersen <andersee@debian.org>
- * Copyright (C) 1998-2000  Jens Axboe <axboe@suse.de>
+ * Copyright (C) 1994-1996   Scott Snyder <snyder@fnald0.fnal.gov>
+ * Copyright (C) 1996-1998   Erik Andersen <andersee@debian.org>
+ * Copyright (C) 1998-2000   Jens Axboe <axboe@suse.de>
+ * Copyright (C) 2005, 2007  Bartlomiej Zolnierkiewicz
  *
  * May be copied or modified under the terms of the GNU General Public
  * License.  See linux/COPYING for more information.
  *
- * ATAPI CD-ROM driver.  To be used with ide.c.
  * See Documentation/cdrom/ide-cd for usage information.
  *
  * Suggestions are welcome. Patches that work are more welcome though. ;-)
@@ -19,287 +19,11 @@
  * ftp://fission.dt.wdc.com/pub/standards/SFF_atapi/spec/SFF8020-r2.6/PS/8020r26.ps
  * ftp://ftp.avc-pioneer.com/Mtfuji4/Spec/Fuji4r10.pdf
  *
- * Drives that deviate from these standards will be accommodated as much
- * as possible via compile time or command-line options.  Since I only have
- * a few drives, you generally need to send me patches...
- *
- * ----------------------------------
- * TO DO LIST:
- * -Make it so that Pioneer CD DR-A24X and friends don't get screwed up on
- *   boot
- *
- * ----------------------------------
- * 1.00  Oct 31, 1994 -- Initial version.
- * 1.01  Nov  2, 1994 -- Fixed problem with starting request in
- *                       cdrom_check_status.
- * 1.03  Nov 25, 1994 -- leaving unmask_intr[] as a user-setting (as for disks)
- * (from mlord)       -- minor changes to cdrom_setup()
- *                    -- renamed ide_dev_s to ide_drive_t, enable irq on command
- * 2.00  Nov 27, 1994 -- Generalize packet command interface;
- *                       add audio ioctls.
- * 2.01  Dec  3, 1994 -- Rework packet command interface to handle devices
- *                       which send an interrupt when ready for a command.
- * 2.02  Dec 11, 1994 -- Cache the TOC in the driver.
- *                       Don't use SCMD_PLAYAUDIO_TI; it's not included
- *                       in the current version of ATAPI.
- *                       Try to use LBA instead of track or MSF addressing
- *                       when possible.
- *                       Don't wait for READY_STAT.
- * 2.03  Jan 10, 1995 -- Rewrite block read routines to handle block sizes
- *                       other than 2k and to move multiple sectors in a
- *                       single transaction.
- * 2.04  Apr 21, 1995 -- Add work-around for Creative Labs CD220E drives.
- *                       Thanks to Nick Saw <cwsaw@pts7.pts.mot.com> for
- *                       help in figuring this out.  Ditto for Acer and
- *                       Aztech drives, which seem to have the same problem.
- * 2.04b May 30, 1995 -- Fix to match changes in ide.c version 3.16 -ml
- * 2.05  Jun  8, 1995 -- Don't attempt to retry after an illegal request
- *                        or data protect error.
- *                       Use HWIF and DEV_HWIF macros as in ide.c.
- *                       Always try to do a request_sense after
- *                        a failed command.
- *                       Include an option to give textual descriptions
- *                        of ATAPI errors.
- *                       Fix a bug in handling the sector cache which
- *                        showed up if the drive returned data in 512 byte
- *                        blocks (like Pioneer drives).  Thanks to
- *                        Richard Hirst <srh@gpt.co.uk> for diagnosing this.
- *                       Properly supply the page number field in the
- *                        MODE_SELECT command.
- *                       PLAYAUDIO12 is broken on the Aztech; work around it.
- * 2.05x Aug 11, 1995 -- lots of data structure renaming/restructuring in ide.c
- *                       (my apologies to Scott, but now ide-cd.c is independent)
- * 3.00  Aug 22, 1995 -- Implement CDROMMULTISESSION ioctl.
- *                       Implement CDROMREADAUDIO ioctl (UNTESTED).
- *                       Use input_ide_data() and output_ide_data().
- *                       Add door locking.
- *                       Fix usage count leak in cdrom_open, which happened
- *                        when a read-write mount was attempted.
- *                       Try to load the disk on open.
- *                       Implement CDROMEJECT_SW ioctl (off by default).
- *                       Read total cdrom capacity during open.
- *                       Rearrange logic in cdrom_decode_status.  Issue
- *                        request sense commands for failed packet commands
- *                        from here instead of from cdrom_queue_packet_command.
- *                        Fix a race condition in retrieving error information.
- *                       Suppress printing normal unit attention errors and
- *                        some drive not ready errors.
- *                       Implement CDROMVOLREAD ioctl.
- *                       Implement CDROMREADMODE1/2 ioctls.
- *                       Fix race condition in setting up interrupt handlers
- *                        when the `serialize' option is used.
- * 3.01  Sep  2, 1995 -- Fix ordering of reenabling interrupts in
- *                        cdrom_queue_request.
- *                       Another try at using ide_[input,output]_data.
- * 3.02  Sep 16, 1995 -- Stick total disk capacity in partition table as well.
- *                       Make VERBOSE_IDE_CD_ERRORS dump failed command again.
- *                       Dump out more information for ILLEGAL REQUEST errs.
- *                       Fix handling of errors occurring before the
- *                        packet command is transferred.
- *                       Fix transfers with odd bytelengths.
- * 3.03  Oct 27, 1995 -- Some Creative drives have an id of just `CD'.
- *                       `DCI-2S10' drives are broken too.
- * 3.04  Nov 20, 1995 -- So are Vertos drives.
- * 3.05  Dec  1, 1995 -- Changes to go with overhaul of ide.c and ide-tape.c
- * 3.06  Dec 16, 1995 -- Add support needed for partitions.
- *                       More workarounds for Vertos bugs (based on patches
- *                        from Holger Dietze <dietze@aix520.informatik.uni-leipzig.de>).
- *                       Try to eliminate byteorder assumptions.
- *                       Use atapi_cdrom_subchnl struct definition.
- *                       Add STANDARD_ATAPI compilation option.
- * 3.07  Jan 29, 1996 -- More twiddling for broken drives: Sony 55D,
- *                        Vertos 300.
- *                       Add NO_DOOR_LOCKING configuration option.
- *                       Handle drive_cmd requests w/NULL args (for hdparm -t).
- *                       Work around sporadic Sony55e audio play problem.
- * 3.07a Feb 11, 1996 -- check drive->id for NULL before dereferencing, to fix
- *                        problem with "hde=cdrom" with no drive present.  -ml
- * 3.08  Mar  6, 1996 -- More Vertos workarounds.
- * 3.09  Apr  5, 1996 -- Add CDROMCLOSETRAY ioctl.
- *                       Switch to using MSF addressing for audio commands.
- *                       Reformat to match kernel tabbing style.
- *                       Add CDROM_GET_UPC ioctl.
- * 3.10  Apr 10, 1996 -- Fix compilation error with STANDARD_ATAPI.
- * 3.11  Apr 29, 1996 -- Patch from Heiko Eißfeldt <heiko@colossus.escape.de>
- *                       to remove redundant verify_area calls.
- * 3.12  May  7, 1996 -- Rudimentary changer support.  Based on patches
- *                        from Gerhard Zuber <zuber@berlin.snafu.de>.
- *                       Let open succeed even if there's no loaded disc.
- * 3.13  May 19, 1996 -- Fixes for changer code.
- * 3.14  May 29, 1996 -- Add work-around for Vertos 600.
- *                        (From Hennus Bergman <hennus@sky.ow.nl>.)
- * 3.15  July 2, 1996 -- Added support for Sanyo 3 CD changers
- *                        from Ben Galliart <bgallia@luc.edu> with 
- *                        special help from Jeff Lightfoot 
- *                        <jeffml@pobox.com>
- * 3.15a July 9, 1996 -- Improved Sanyo 3 CD changer identification
- * 3.16  Jul 28, 1996 -- Fix from Gadi to reduce kernel stack usage for ioctl.
- * 3.17  Sep 17, 1996 -- Tweak audio reads for some drives.
- *                       Start changing CDROMLOADFROMSLOT to CDROM_SELECT_DISC.
- * 3.18  Oct 31, 1996 -- Added module and DMA support.
- *                       
- *                       
- * 4.00  Nov 5, 1996   -- New ide-cd maintainer,
- *                                 Erik B. Andersen <andersee@debian.org>
- *                     -- Newer Creative drives don't always set the error
- *                          register correctly.  Make sure we see media changes
- *                          regardless.
- *                     -- Integrate with generic cdrom driver.
- *                     -- CDROMGETSPINDOWN and CDROMSETSPINDOWN ioctls, based on
- *                          a patch from Ciro Cattuto <>.
- *                     -- Call set_device_ro.
- *                     -- Implement CDROMMECHANISMSTATUS and CDROMSLOTTABLE
- *                          ioctls, based on patch by Erik Andersen
- *                     -- Add some probes of drive capability during setup.
- *
- * 4.01  Nov 11, 1996  -- Split into ide-cd.c and ide-cd.h
- *                     -- Removed CDROMMECHANISMSTATUS and CDROMSLOTTABLE 
- *                          ioctls in favor of a generalized approach 
- *                          using the generic cdrom driver.
- *                     -- Fully integrated with the 2.1.X kernel.
- *                     -- Other stuff that I forgot (lots of changes)
- *
- * 4.02  Dec 01, 1996  -- Applied patch from Gadi Oxman <gadio@netvision.net.il>
- *                          to fix the drive door locking problems.
- *
- * 4.03  Dec 04, 1996  -- Added DSC overlap support.
- * 4.04  Dec 29, 1996  -- Added CDROMREADRAW ioclt based on patch 
- *                          by Ales Makarov (xmakarov@sun.felk.cvut.cz)
- *
- * 4.05  Nov 20, 1997  -- Modified to print more drive info on init
- *                        Minor other changes
- *                        Fix errors on CDROMSTOP (If you have a "Dolphin",
- *                          you must define IHAVEADOLPHIN)
- *                        Added identifier so new Sanyo CD-changer works
- *                        Better detection if door locking isn't supported
- *
- * 4.06  Dec 17, 1997  -- fixed endless "tray open" messages  -ml
- * 4.07  Dec 17, 1997  -- fallback to set pc->stat on "tray open"
- * 4.08  Dec 18, 1997  -- spew less noise when tray is empty
- *                     -- fix speed display for ACER 24X, 18X
- * 4.09  Jan 04, 1998  -- fix handling of the last block so we return
- *                         an end of file instead of an I/O error (Gadi)
- * 4.10  Jan 24, 1998  -- fixed a bug so now changers can change to a new
- *                         slot when there is no disc in the current slot.
- *                     -- Fixed a memory leak where info->changer_info was
- *                         malloc'ed but never free'd when closing the device.
- *                     -- Cleaned up the global namespace a bit by making more
- *                         functions static that should already have been.
- * 4.11  Mar 12, 1998  -- Added support for the CDROM_SELECT_SPEED ioctl
- *                         based on a patch for 2.0.33 by Jelle Foks 
- *                         <jelle@scintilla.utwente.nl>, a patch for 2.0.33
- *                         by Toni Giorgino <toni@pcape2.pi.infn.it>, the SCSI
- *                         version, and my own efforts.  -erik
- *                     -- Fixed a stupid bug which egcs was kind enough to
- *                         inform me of where "Illegal mode for this track"
- *                         was never returned due to a comparison on data
- *                         types of limited range.
- * 4.12  Mar 29, 1998  -- Fixed bug in CDROM_SELECT_SPEED so write speed is 
- *                         now set ionly for CD-R and CD-RW drives.  I had 
- *                         removed this support because it produced errors.
- *                         It produced errors _only_ for non-writers. duh.
- * 4.13  May 05, 1998  -- Suppress useless "in progress of becoming ready"
- *                         messages, since this is not an error.
- *                     -- Change error messages to be const
- *                     -- Remove a "\t" which looks ugly in the syslogs
- * 4.14  July 17, 1998 -- Change to pointing to .ps version of ATAPI spec
- *                         since the .pdf version doesn't seem to work...
- *                     -- Updated the TODO list to something more current.
- *
- * 4.15  Aug 25, 1998  -- Updated ide-cd.h to respect mechine endianess, 
- *                         patch thanks to "Eddie C. Dost" <ecd@skynet.be>
- *
- * 4.50  Oct 19, 1998  -- New maintainers!
- *                         Jens Axboe <axboe@image.dk>
- *                         Chris Zwilling <chris@cloudnet.com>
- *
- * 4.51  Dec 23, 1998  -- Jens Axboe <axboe@image.dk>
- *                      - ide_cdrom_reset enabled since the ide subsystem
- *                         handles resets fine now. <axboe@image.dk>
- *                      - Transfer size fix for Samsung CD-ROMs, thanks to
- *                        "Ville Hallik" <ville.hallik@mail.ee>.
- *                      - other minor stuff.
- *
- * 4.52  Jan 19, 1999  -- Jens Axboe <axboe@image.dk>
- *                      - Detect DVD-ROM/RAM drives
- *
- * 4.53  Feb 22, 1999   - Include other model Samsung and one Goldstar
- *                         drive in transfer size limit.
- *                      - Fix the I/O error when doing eject without a medium
- *                         loaded on some drives.
- *                      - CDROMREADMODE2 is now implemented through
- *                         CDROMREADRAW, since many drives don't support
- *                         MODE2 (even though ATAPI 2.6 says they must).
- *                      - Added ignore parameter to ide-cd (as a module), eg
- *                         	insmod ide-cd ignore='hda hdb'
- *                         Useful when using ide-cd in conjunction with
- *                         ide-scsi. TODO: non-modular way of doing the
- *                         same.
- *
- * 4.54  Aug 5, 1999	- Support for MMC2 class commands through the generic
- *			  packet interface to cdrom.c.
- *			- Unified audio ioctl support, most of it.
- *			- cleaned up various deprecated verify_area().
- *			- Added ide_cdrom_packet() as the interface for
- *			  the Uniform generic_packet().
- *			- bunch of other stuff, will fill in logs later.
- *			- report 1 slot for non-changers, like the other
- *			  cd-rom drivers. don't report select disc for
- *			  non-changers as well.
- *			- mask out audio playing, if the device can't do it.
- *
- * 4.55  Sep 1, 1999	- Eliminated the rest of the audio ioctls, except
- *			  for CDROMREADTOC[ENTRY|HEADER]. Some of the drivers
- *			  use this independently of the actual audio handling.
- *			  They will disappear later when I get the time to
- *			  do it cleanly.
- *			- Minimize the TOC reading - only do it when we
- *			  know a media change has occurred.
- *			- Moved all the CDROMREADx ioctls to the Uniform layer.
- *			- Heiko Eißfeldt <heiko@colossus.escape.de> supplied
- *			  some fixes for CDI.
- *			- CD-ROM leaving door locked fix from Andries
- *			  Brouwer <Andries.Brouwer@cwi.nl>
- *			- Erik Andersen <andersen@xmission.com> unified
- *			  commands across the various drivers and how
- *			  sense errors are handled.
- *
- * 4.56  Sep 12, 1999	- Removed changer support - it is now in the
- *			  Uniform layer.
- *			- Added partition based multisession handling.
- *			- Mode sense and mode select moved to the
- *			  Uniform layer.
- *			- Fixed a problem with WPI CDS-32X drive - it
- *			  failed the capabilities 
- *
- * 4.57  Apr 7, 2000	- Fixed sense reporting.
- *			- Fixed possible oops in ide_cdrom_get_last_session()
- *			- Fix locking mania and make ide_cdrom_reset relock
- *			- Stop spewing errors to log when magicdev polls with
- *			  TEST_UNIT_READY on some drives.
- *			- Various fixes from Tobias Ringstrom:
- *			  tray if it was locked prior to the reset.
- *			  - cdrom_read_capacity returns one frame too little.
- *			  - Fix real capacity reporting.
- *
- * 4.58  May 1, 2000	- Clean up ACER50 stuff.
- *			- Fix small problem with ide_cdrom_capacity
- *
- * 4.59  Aug 11, 2000	- Fix changer problem in cdrom_read_toc, we weren't
- *			  correctly sensing a disc change.
- *			- Rearranged some code
- *			- Use extended sense on drives that support it for
- *			  correctly reporting tray status -- from
- *			  Michael D Johnson <johnsom@orst.edu>
- * 4.60  Dec 17, 2003	- Add mt rainier support
- *			- Bump timeout for packet commands, matches sr
- *			- Odd stuff
- * 4.61  Jan 22, 2004	- support hardware sector sizes other than 2kB,
- *			  Pascal Schmidt <der.eremit@email.de>
- *
- *************************************************************************/
- 
-#define IDECD_VERSION "4.61"
+ * For historical changelog please see:
+ *	Documentation/ide/ChangeLog.ide-cd.1994-2004
+ */
+
+#define IDECD_VERSION "5.00"
 
 #include <linux/module.h>
 #include <linux/types.h>
@@ -313,6 +37,7 @@
 #include <linux/ide.h>
 #include <linux/completion.h>
 #include <linux/mutex.h>
+#include <linux/bcd.h>
 
 #include <scsi/scsi.h>	/* For SCSI -> ATAPI command conversion */
 
@@ -360,11 +85,11 @@
    buffers. */
 static void cdrom_saw_media_change (ide_drive_t *drive)
 {
-	struct cdrom_info *info = drive->driver_data;
-	
-	CDROM_STATE_FLAGS (drive)->media_changed = 1;
-	CDROM_STATE_FLAGS (drive)->toc_valid = 0;
-	info->nsectors_buffered = 0;
+	struct cdrom_info *cd = drive->driver_data;
+
+	cd->cd_flags |= IDE_CD_FLAG_MEDIA_CHANGED;
+	cd->cd_flags &= ~IDE_CD_FLAG_TOC_VALID;
+	cd->nsectors_buffered = 0;
 }
 
 static int cdrom_log_sense(ide_drive_t *drive, struct request *rq,
@@ -465,134 +190,14 @@
 			}
  		}
  	}
-#if VERBOSE_IDE_CD_ERRORS
-	{
-		int i;
-		const char *s = "bad sense key!";
-		char buf[80];
 
-		printk ("ATAPI device %s:\n", drive->name);
-		if (sense->error_code==0x70)
-			printk("  Error: ");
-		else if (sense->error_code==0x71)
-			printk("  Deferred Error: ");
-		else if (sense->error_code == 0x7f)
-			printk("  Vendor-specific Error: ");
-		else
-			printk("  Unknown Error Type: ");
-
-		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);
-
-		if (sense->asc == 0x40) {
-			sprintf(buf, "Diagnostic failure on component 0x%02x",
-				 sense->ascq);
-			s = buf;
-		} else {
-			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))
-				key |= sense->ascq;
-			s = NULL;
-
-			while (hi > lo) {
-				mid = (lo + hi) / 2;
-				if (sense_data_texts[mid].asc_ascq == key ||
-				    sense_data_texts[mid].asc_ascq == (0xff0000|key)) {
-					s = sense_data_texts[mid].text;
-					break;
-				}
-				else if (sense_data_texts[mid].asc_ascq > key)
-					hi = mid;
-				else
-					lo = mid+1;
-			}
-		}
-
-		if (s == NULL) {
-			if (sense->asc > 0x80)
-				s = "(vendor-specific error)";
-			else
-				s = "(reserved error code)";
-		}
-
-		printk(KERN_ERR "  %s -- (asc=0x%02x, ascq=0x%02x)\n",
-			s, sense->asc, sense->ascq);
-
-		if (failed_command != NULL) {
-
-			int lo=0, mid, hi= ARRAY_SIZE(packet_command_texts);
-			s = NULL;
-
-			while (hi > lo) {
-				mid = (lo + hi) / 2;
-				if (packet_command_texts[mid].packet_command ==
-				    failed_command->cmd[0]) {
-					s = packet_command_texts[mid].text;
-					break;
-				}
-				if (packet_command_texts[mid].packet_command >
-				    failed_command->cmd[0])
-					hi = mid;
-				else
-					lo = mid+1;
-			}
-
-			printk (KERN_ERR "  The failed \"%s\" packet command was: \n  \"", s);
-			for (i=0; i<sizeof (failed_command->cmd); i++)
-				printk ("%02x ", failed_command->cmd[i]);
-			printk ("\"\n");
-		}
-
-		/* The SKSV bit specifies validity of the sense_key_specific
-		 * in the next two commands. It is bit 7 of the first byte.
-		 * In the case of NOT_READY, if SKSV is set the drive can
-		 * give us nice ETA readings.
-		 */
-		if (sense->sense_key == NOT_READY && (sense->sks[0] & 0x80)) {
-			int progress = (sense->sks[1] << 8 | sense->sks[2]) * 100;
-			printk(KERN_ERR "  Command is %02d%% complete\n", progress / 0xffff);
-
-		}
-
-		if (sense->sense_key == ILLEGAL_REQUEST &&
-		    (sense->sks[0] & 0x80) != 0) {
-			printk(KERN_ERR "  Error in %s byte %d",
-				(sense->sks[0] & 0x40) != 0 ?
-				"command packet" : "command data",
-				(sense->sks[1] << 8) + sense->sks[2]);
-
-			if ((sense->sks[0] & 0x40) != 0)
-				printk (" bit %d", sense->sks[0] & 0x07);
-
-			printk ("\n");
-		}
-	}
-
-#else /* not VERBOSE_IDE_CD_ERRORS */
-
-	/* Suppress printing unit attention and `in progress of becoming ready'
-	   errors when we're not being verbose. */
-
-	if (sense->sense_key == UNIT_ATTENTION ||
-	    (sense->sense_key == NOT_READY && (sense->asc == 4 ||
-						sense->asc == 0x3a)))
-		return;
-
-	printk(KERN_ERR "%s: error code: 0x%02x  sense_key: 0x%02x  asc: 0x%02x  ascq: 0x%02x\n",
-		drive->name,
-		sense->error_code, sense->sense_key,
-		sense->asc, sense->ascq);
-#endif /* not VERBOSE_IDE_CD_ERRORS */
+	ide_cd_log_error(drive->name, failed_command, sense);
 }
 
 /*
  * Initialize a ide-cd packet command request
  */
-static void cdrom_prepare_request(ide_drive_t *drive, struct request *rq)
+void ide_cd_init_rq(ide_drive_t *drive, struct request *rq)
 {
 	struct cdrom_info *cd = drive->driver_data;
 
@@ -611,7 +216,7 @@
 		sense = &info->sense_data;
 
 	/* stuff the sense request in front of our current request */
-	cdrom_prepare_request(drive, rq);
+	ide_cd_init_rq(drive, rq);
 
 	rq->data = sense;
 	rq->cmd[0] = GPCMD_REQUEST_SENSE;
@@ -718,7 +323,6 @@
 
 	} else if (blk_pc_request(rq) || rq->cmd_type == REQ_TYPE_ATA_PC) {
 		/* All other functions, except for READ. */
-		unsigned long flags;
 
 		/*
 		 * if we have an error, pass back CHECK_CONDITION as the
@@ -756,15 +360,7 @@
 		 * remove failed request completely and end it when the
 		 * request sense has completed
 		 */
-		if (stat & ERR_STAT) {
-			spin_lock_irqsave(&ide_lock, flags);
-			blkdev_dequeue_request(rq);
-			HWGROUP(drive)->rq = NULL;
-			spin_unlock_irqrestore(&ide_lock, flags);
-
-			cdrom_queue_request_sense(drive, rq->sense, rq);
-		} else
-			cdrom_end_request(drive, 0);
+		goto end_request;
 
 	} else if (blk_fs_request(rq)) {
 		int do_end_request = 0;
@@ -844,23 +440,15 @@
 		   sense data. We need this in order to perform end of media
 		   processing */
 
-		if (do_end_request) {
-			if (stat & ERR_STAT) {
-				unsigned long flags;
-				spin_lock_irqsave(&ide_lock, flags);
-				blkdev_dequeue_request(rq);
-				HWGROUP(drive)->rq = NULL;
-				spin_unlock_irqrestore(&ide_lock, flags);
+		if (do_end_request)
+			goto end_request;
 
-				cdrom_queue_request_sense(drive, rq->sense, rq);
-			} else
-				cdrom_end_request(drive, 0);
-		} else {
-			/* If we got a CHECK_CONDITION status,
-			   queue a request sense command. */
-			if (stat & ERR_STAT)
-				cdrom_queue_request_sense(drive, NULL, NULL);
-		}
+		/*
+		 * If we got a CHECK_CONDITION status,
+		 * queue a request sense command.
+		 */
+		if (stat & ERR_STAT)
+			cdrom_queue_request_sense(drive, NULL, NULL);
 	} else {
 		blk_dump_rq_flags(rq, "ide-cd: bad rq");
 		cdrom_end_request(drive, 0);
@@ -868,6 +456,21 @@
 
 	/* Retry, or handle the next request. */
 	return 1;
+
+end_request:
+	if (stat & ERR_STAT) {
+		unsigned long flags;
+
+		spin_lock_irqsave(&ide_lock, flags);
+		blkdev_dequeue_request(rq);
+		HWGROUP(drive)->rq = NULL;
+		spin_unlock_irqrestore(&ide_lock, flags);
+
+		cdrom_queue_request_sense(drive, rq->sense, rq);
+	} else
+		cdrom_end_request(drive, 0);
+
+	return 1;
 }
 
 static int cdrom_timer_expiry(ide_drive_t *drive)
@@ -924,8 +527,8 @@
 	/* Set up the controller registers. */
 	ide_pktcmd_tf_load(drive, IDE_TFLAG_OUT_NSECT | IDE_TFLAG_OUT_LBAL |
 			   IDE_TFLAG_NO_SELECT_MASK, xferlen, info->dma);
- 
-	if (CDROM_CONFIG_FLAGS (drive)->drq_interrupt) {
+
+	if (info->cd_flags & IDE_CD_FLAG_DRQ_INTERRUPT) {
 		/* waiting for CDB interrupt, not DMA yet. */
 		if (info->dma)
 			drive->waiting_for_dma = 0;
@@ -951,10 +554,6 @@
    by cdrom_start_packet_command.
    HANDLER is the interrupt handler to call when the command completes
    or there's data ready. */
-/*
- * changed 5 parameters to 3 for dvd-ram
- * struct packet_command *pc; now packet_command_t *pc;
- */
 #define ATAPI_MIN_CDB_BYTES 12
 static ide_startstop_t cdrom_transfer_packet_command (ide_drive_t *drive,
 					  struct request *rq,
@@ -965,7 +564,7 @@
 	struct cdrom_info *info = drive->driver_data;
 	ide_startstop_t startstop;
 
-	if (CDROM_CONFIG_FLAGS(drive)->drq_interrupt) {
+	if (info->cd_flags & IDE_CD_FLAG_DRQ_INTERRUPT) {
 		/* Here we should have been called after receiving an interrupt
 		   from the device.  DRQ should how be set. */
 
@@ -1005,6 +604,27 @@
  * Block read functions.
  */
 
+typedef void (xfer_func_t)(ide_drive_t *, void *, u32);
+
+static void ide_cd_pad_transfer(ide_drive_t *drive, xfer_func_t *xf, int len)
+{
+	while (len > 0) {
+		int dum = 0;
+		xf(drive, &dum, sizeof(dum));
+		len -= sizeof(dum);
+	}
+}
+
+static void ide_cd_drain_data(ide_drive_t *drive, int nsects)
+{
+	while (nsects > 0) {
+		static char dum[SECTOR_SIZE];
+
+		drive->hwif->atapi_input_bytes(drive, dum, sizeof(dum));
+		nsects--;
+	}
+}
+
 /*
  * Buffer up to SECTORS_TO_TRANSFER sectors from the drive in our sector
  * buffer.  Once the first sector is added, any subsequent sectors are
@@ -1043,11 +663,7 @@
 	}
 
 	/* Throw away any remaining data. */
-	while (sectors_to_transfer > 0) {
-		static char dum[SECTOR_SIZE];
-		HWIF(drive)->atapi_input_bytes(drive, dum, sizeof (dum));
-		--sectors_to_transfer;
-	}
+	ide_cd_drain_data(drive, sectors_to_transfer);
 }
 
 /*
@@ -1056,23 +672,25 @@
  * ok; nonzero if the request has been terminated.
  */
 static
-int cdrom_read_check_ireason (ide_drive_t *drive, int len, int ireason)
+int ide_cd_check_ireason(ide_drive_t *drive, int len, int ireason, int rw)
 {
-	if (ireason == 2)
+	/*
+	 * ireason == 0: the drive wants to receive data from us
+	 * ireason == 2: the drive is expecting to transfer data to us
+	 */
+	if (ireason == (!rw << 1))
 		return 0;
-	else if (ireason == 0) {
-		/* Whoops... The drive is expecting to receive data from us! */
+	else if (ireason == (rw << 1)) {
+		ide_hwif_t *hwif = drive->hwif;
+		xfer_func_t *xf;
+
+		/* Whoops... */
 		printk(KERN_ERR "%s: %s: wrong transfer direction!\n",
 				drive->name, __FUNCTION__);
 
-		/* Throw some data at the drive so it doesn't hang
-		   and quit this request. */
-		while (len > 0) {
-			int dum = 0;
-			HWIF(drive)->atapi_output_bytes(drive, &dum, sizeof (dum));
-			len -= sizeof (dum);
-		}
-	} else  if (ireason == 1) {
+		xf = rw ? hwif->atapi_output_bytes : hwif->atapi_input_bytes;
+		ide_cd_pad_transfer(drive, xf, len);
+	} else  if (rw == 0 && ireason == 1) {
 		/* Some drives (ASUS) seem to tell us that status
 		 * info is available. just get it and ignore.
 		 */
@@ -1089,137 +707,28 @@
 }
 
 /*
- * Interrupt routine.  Called when a read request has completed.
+ * Assume that the drive will always provide data in multiples of at least
+ * SECTOR_SIZE, as it gets hairy to keep track of the transfers otherwise.
  */
-static ide_startstop_t cdrom_read_intr (ide_drive_t *drive)
+static int ide_cd_check_transfer_size(ide_drive_t *drive, int len)
 {
-	int stat;
-	int ireason, len, sectors_to_transfer, nskip;
-	struct cdrom_info *info = drive->driver_data;
-	u8 lowcyl = 0, highcyl = 0;
-	int dma = info->dma, dma_error = 0;
+	struct cdrom_info *cd = drive->driver_data;
 
-	struct request *rq = HWGROUP(drive)->rq;
+	if ((len % SECTOR_SIZE) == 0)
+		return 0;
 
-	/*
-	 * handle dma case
-	 */
-	if (dma) {
-		info->dma = 0;
-		dma_error = HWIF(drive)->ide_dma_end(drive);
-		if (dma_error) {
-			printk(KERN_ERR "%s: DMA read error\n", drive->name);
-			ide_dma_off(drive);
-		}
+	printk(KERN_ERR "%s: %s: Bad transfer size %d\n",
+			drive->name, __FUNCTION__, len);
+
+	if (cd->cd_flags & IDE_CD_FLAG_LIMIT_NFRAMES)
+		printk(KERN_ERR "  This drive is not supported by "
+				"this version of the driver\n");
+	else {
+		printk(KERN_ERR "  Trying to limit transfer sizes\n");
+		cd->cd_flags |= IDE_CD_FLAG_LIMIT_NFRAMES;
 	}
 
-	if (cdrom_decode_status(drive, 0, &stat))
-		return ide_stopped;
-
-	if (dma) {
-		if (!dma_error) {
-			ide_end_request(drive, 1, rq->nr_sectors);
-			return ide_stopped;
-		} else
-			return ide_error(drive, "dma error", stat);
-	}
-
-	/* Read the interrupt reason and the transfer length. */
-	ireason = HWIF(drive)->INB(IDE_IREASON_REG) & 0x3;
-	lowcyl  = HWIF(drive)->INB(IDE_BCOUNTL_REG);
-	highcyl = HWIF(drive)->INB(IDE_BCOUNTH_REG);
-
-	len = lowcyl + (256 * highcyl);
-
-	/* If DRQ is clear, the command has completed. */
-	if ((stat & DRQ_STAT) == 0) {
-		/* If we're not done filling the current buffer, complain.
-		   Otherwise, complete the command normally. */
-		if (rq->current_nr_sectors > 0) {
-			printk (KERN_ERR "%s: cdrom_read_intr: data underrun (%d blocks)\n",
-				drive->name, rq->current_nr_sectors);
-			rq->cmd_flags |= REQ_FAILED;
-			cdrom_end_request(drive, 0);
-		} else
-			cdrom_end_request(drive, 1);
-		return ide_stopped;
-	}
-
-	/* Check that the drive is expecting to do the same thing we are. */
-	if (cdrom_read_check_ireason (drive, len, ireason))
-		return ide_stopped;
-
-	/* Assume that the drive will always provide data in multiples
-	   of at least SECTOR_SIZE, as it gets hairy to keep track
-	   of the transfers otherwise. */
-	if ((len % SECTOR_SIZE) != 0) {
-		printk (KERN_ERR "%s: cdrom_read_intr: Bad transfer size %d\n",
-			drive->name, len);
-		if (CDROM_CONFIG_FLAGS(drive)->limit_nframes)
-			printk (KERN_ERR "  This drive is not supported by this version of the driver\n");
-		else {
-			printk (KERN_ERR "  Trying to limit transfer sizes\n");
-			CDROM_CONFIG_FLAGS(drive)->limit_nframes = 1;
-		}
-		cdrom_end_request(drive, 0);
-		return ide_stopped;
-	}
-
-	/* The number of sectors we need to read from the drive. */
-	sectors_to_transfer = len / SECTOR_SIZE;
-
-	/* First, figure out if we need to bit-bucket
-	   any of the leading sectors. */
-	nskip = min_t(int, rq->current_nr_sectors - bio_cur_sectors(rq->bio), sectors_to_transfer);
-
-	while (nskip > 0) {
-		/* We need to throw away a sector. */
-		static char dum[SECTOR_SIZE];
-		HWIF(drive)->atapi_input_bytes(drive, dum, sizeof (dum));
-
-		--rq->current_nr_sectors;
-		--nskip;
-		--sectors_to_transfer;
-	}
-
-	/* Now loop while we still have data to read from the drive. */
-	while (sectors_to_transfer > 0) {
-		int this_transfer;
-
-		/* If we've filled the present buffer but there's another
-		   chained buffer after it, move on. */
-		if (rq->current_nr_sectors == 0 && rq->nr_sectors)
-			cdrom_end_request(drive, 1);
-
-		/* If the buffers are full, cache the rest of the data in our
-		   internal buffer. */
-		if (rq->current_nr_sectors == 0) {
-			cdrom_buffer_sectors(drive, rq->sector, sectors_to_transfer);
-			sectors_to_transfer = 0;
-		} else {
-			/* Transfer data to the buffers.
-			   Figure out how many sectors we can transfer
-			   to the current buffer. */
-			this_transfer = min_t(int, sectors_to_transfer,
-					     rq->current_nr_sectors);
-
-			/* Read this_transfer sectors
-			   into the current buffer. */
-			while (this_transfer > 0) {
-				HWIF(drive)->atapi_input_bytes(drive, rq->buffer, SECTOR_SIZE);
-				rq->buffer += SECTOR_SIZE;
-				--rq->nr_sectors;
-				--rq->current_nr_sectors;
-				++rq->sector;
-				--this_transfer;
-				--sectors_to_transfer;
-			}
-		}
-	}
-
-	/* Done moving data!  Wait for another interrupt. */
-	ide_set_handler(drive, &cdrom_read_intr, ATAPI_WAIT_PC, NULL);
-	return ide_started;
+	return 1;
 }
 
 /*
@@ -1281,48 +790,58 @@
 	return 0;
 }
 
+static ide_startstop_t cdrom_newpc_intr(ide_drive_t *);
+
 /*
- * Routine to send a read packet command to the drive.
- * This is usually called directly from cdrom_start_read.
+ * Routine to send a read/write packet command to the drive.
+ * This is usually called directly from cdrom_start_{read,write}().
  * However, for drq_interrupt devices, it is called from an interrupt
  * when the drive is ready to accept the command.
  */
-static ide_startstop_t cdrom_start_read_continuation (ide_drive_t *drive)
+static ide_startstop_t cdrom_start_rw_cont(ide_drive_t *drive)
 {
 	struct request *rq = HWGROUP(drive)->rq;
-	unsigned short sectors_per_frame;
-	int nskip;
 
-	sectors_per_frame = queue_hardsect_size(drive->queue) >> SECTOR_BITS;
+	if (rq_data_dir(rq) == READ) {
+		unsigned short sectors_per_frame =
+			queue_hardsect_size(drive->queue) >> SECTOR_BITS;
+		int nskip = rq->sector & (sectors_per_frame - 1);
 
-	/* If the requested sector doesn't start on a cdrom block boundary,
-	   we must adjust the start of the transfer so that it does,
-	   and remember to skip the first few sectors.
-	   If the CURRENT_NR_SECTORS field is larger than the size
-	   of the buffer, it will mean that we're to skip a number
-	   of sectors equal to the amount by which CURRENT_NR_SECTORS
-	   is larger than the buffer size. */
-	nskip = rq->sector & (sectors_per_frame - 1);
-	if (nskip > 0) {
-		/* Sanity check... */
-		if (rq->current_nr_sectors != bio_cur_sectors(rq->bio) &&
-			(rq->sector & (sectors_per_frame - 1))) {
-			printk(KERN_ERR "%s: cdrom_start_read_continuation: buffer botch (%u)\n",
-				drive->name, rq->current_nr_sectors);
-			cdrom_end_request(drive, 0);
-			return ide_stopped;
+		/*
+		 * If the requested sector doesn't start on a frame boundary,
+		 * we must adjust the start of the transfer so that it does,
+		 * and remember to skip the first few sectors.
+		 *
+		 * If the rq->current_nr_sectors field is larger than the size
+		 * of the buffer, it will mean that we're to skip a number of
+		 * sectors equal to the amount by which rq->current_nr_sectors
+		 * is larger than the buffer size.
+		 */
+		if (nskip > 0) {
+			/* Sanity check... */
+			if (rq->current_nr_sectors !=
+			    bio_cur_sectors(rq->bio)) {
+				printk(KERN_ERR "%s: %s: buffer botch (%u)\n",
+						drive->name, __FUNCTION__,
+						rq->current_nr_sectors);
+				cdrom_end_request(drive, 0);
+				return ide_stopped;
+			}
+			rq->current_nr_sectors += nskip;
 		}
-		rq->current_nr_sectors += nskip;
 	}
-
+#if 0
+	else
+		/* the immediate bit */
+		rq->cmd[1] = 1 << 3;
+#endif
 	/* Set up the command */
 	rq->timeout = ATAPI_WAIT_PC;
 
 	/* Send the command to the drive and return. */
-	return cdrom_transfer_packet_command(drive, rq, &cdrom_read_intr);
+	return cdrom_transfer_packet_command(drive, rq, cdrom_newpc_intr);
 }
 
-
 #define IDECD_SEEK_THRESHOLD	(1000)			/* 1000 blocks */
 #define IDECD_SEEK_TIMER	(5 * WAIT_MIN_SLEEP)	/* 100 ms */
 #define IDECD_SEEK_TIMEOUT	(2 * WAIT_CMD)		/* 20 sec */
@@ -1335,7 +854,8 @@
 
 	if (cdrom_decode_status(drive, 0, &stat))
 		return ide_stopped;
-	CDROM_CONFIG_FLAGS(drive)->seeking = 1;
+
+	info->cd_flags |= IDE_CD_FLAG_SEEKING;
 
 	if (retry && time_after(jiffies, info->start_seek + IDECD_SEEK_TIMER)) {
 		if (--retry == 0) {
@@ -1391,184 +911,25 @@
 	rq->q->prep_rq_fn(rq->q, rq);
 }
 
-/*
- * Start a read request from the CD-ROM.
- */
-static ide_startstop_t cdrom_start_read (ide_drive_t *drive, unsigned int block)
-{
-	struct cdrom_info *info = drive->driver_data;
-	struct request *rq = HWGROUP(drive)->rq;
-	unsigned short sectors_per_frame;
-
-	sectors_per_frame = queue_hardsect_size(drive->queue) >> SECTOR_BITS;
-
-	/* We may be retrying this request after an error.  Fix up
-	   any weirdness which might be present in the request packet. */
-	restore_request(rq);
-
-	/* Satisfy whatever we can of this request from our cached sector. */
-	if (cdrom_read_from_buffer(drive))
-		return ide_stopped;
-
-	/* Clear the local sector buffer. */
-	info->nsectors_buffered = 0;
-
-	/* use dma, if possible. */
-	info->dma = drive->using_dma;
-	if ((rq->sector & (sectors_per_frame - 1)) ||
-	    (rq->nr_sectors & (sectors_per_frame - 1)))
-		info->dma = 0;
-
-	/* Start sending the read request to the drive. */
-	return cdrom_start_packet_command(drive, 32768, cdrom_start_read_continuation);
-}
-
 /****************************************************************************
  * Execute all other packet commands.
  */
 
-/* Interrupt routine for packet command completion. */
-static ide_startstop_t cdrom_pc_intr (ide_drive_t *drive)
+static void ide_cd_request_sense_fixup(struct request *rq)
 {
-	int ireason, len, thislen;
-	struct request *rq = HWGROUP(drive)->rq;
-	u8 lowcyl = 0, highcyl = 0;
-	int stat;
-
-	/* Check for errors. */
-	if (cdrom_decode_status(drive, 0, &stat))
-		return ide_stopped;
-
-	/* Read the interrupt reason and the transfer length. */
-	ireason = HWIF(drive)->INB(IDE_IREASON_REG) & 0x3;
-	lowcyl  = HWIF(drive)->INB(IDE_BCOUNTL_REG);
-	highcyl = HWIF(drive)->INB(IDE_BCOUNTH_REG);
-
-	len = lowcyl + (256 * highcyl);
-
-	/* If DRQ is clear, the command has completed.
-	   Complain if we still have data left to transfer. */
-	if ((stat & DRQ_STAT) == 0) {
-		/* Some of the trailing request sense fields are optional, and
-		   some drives don't send them.  Sigh. */
-		if (rq->cmd[0] == GPCMD_REQUEST_SENSE &&
-		    rq->data_len > 0 &&
-		    rq->data_len <= 5) {
-			while (rq->data_len > 0) {
-				*(unsigned char *)rq->data++ = 0;
-				--rq->data_len;
-			}
+	/*
+	 * Some of the trailing request sense fields are optional,
+	 * and some drives don't send them.  Sigh.
+	 */
+	if (rq->cmd[0] == GPCMD_REQUEST_SENSE &&
+	    rq->data_len > 0 && rq->data_len <= 5)
+		while (rq->data_len > 0) {
+			*(u8 *)rq->data++ = 0;
+			--rq->data_len;
 		}
-
-		if (rq->data_len == 0)
-			cdrom_end_request(drive, 1);
-		else {
-			/* Comment this out, because this always happens 
-			   right after a reset occurs, and it is annoying to 
-			   always print expected stuff.  */
-			/*
-			printk ("%s: cdrom_pc_intr: data underrun %d\n",
-				drive->name, pc->buflen);
-			*/
-			rq->cmd_flags |= REQ_FAILED;
-			cdrom_end_request(drive, 0);
-		}
-		return ide_stopped;
-	}
-
-	/* Figure out how much data to transfer. */
-	thislen = rq->data_len;
-	if (thislen > len) thislen = len;
-
-	/* The drive wants to be written to. */
-	if (ireason == 0) {
-		if (!rq->data) {
-			blk_dump_rq_flags(rq, "cdrom_pc_intr, write");
-			goto confused;
-		}
-		/* Transfer the data. */
-		HWIF(drive)->atapi_output_bytes(drive, rq->data, thislen);
-
-		/* If we haven't moved enough data to satisfy the drive,
-		   add some padding. */
-		while (len > thislen) {
-			int dum = 0;
-			HWIF(drive)->atapi_output_bytes(drive, &dum, sizeof(dum));
-			len -= sizeof(dum);
-		}
-
-		/* Keep count of how much data we've moved. */
-		rq->data += thislen;
-		rq->data_len -= thislen;
-	}
-
-	/* Same drill for reading. */
-	else if (ireason == 2) {
-		if (!rq->data) {
-			blk_dump_rq_flags(rq, "cdrom_pc_intr, read");
-			goto confused;
-		}
-		/* Transfer the data. */
-		HWIF(drive)->atapi_input_bytes(drive, rq->data, thislen);
-
-		/* If we haven't moved enough data to satisfy the drive,
-		   add some padding. */
-		while (len > thislen) {
-			int dum = 0;
-			HWIF(drive)->atapi_input_bytes(drive, &dum, sizeof(dum));
-			len -= sizeof(dum);
-		}
-
-		/* Keep count of how much data we've moved. */
-		rq->data += thislen;
-		rq->data_len -= thislen;
-
-		if (blk_sense_request(rq))
-			rq->sense_len += thislen;
-	} else {
-confused:
-		printk (KERN_ERR "%s: cdrom_pc_intr: The drive "
-			"appears confused (ireason = 0x%02x). "
-			"Trying to recover by ending request.\n",
-			drive->name, ireason);
-		rq->cmd_flags |= REQ_FAILED;
-		cdrom_end_request(drive, 0);
-		return ide_stopped;
-	}
-
-	/* Now we wait for another interrupt. */
-	ide_set_handler(drive, &cdrom_pc_intr, ATAPI_WAIT_PC, cdrom_timer_expiry);
-	return ide_started;
 }
 
-static ide_startstop_t cdrom_do_pc_continuation (ide_drive_t *drive)
-{
-	struct request *rq = HWGROUP(drive)->rq;
-
-	if (!rq->timeout)
-		rq->timeout = ATAPI_WAIT_PC;
-
-	/* Send the command to the drive and return. */
-	return cdrom_transfer_packet_command(drive, rq, &cdrom_pc_intr);
-}
-
-
-static ide_startstop_t cdrom_do_packet_command (ide_drive_t *drive)
-{
-	int len;
-	struct request *rq = HWGROUP(drive)->rq;
-	struct cdrom_info *info = drive->driver_data;
-
-	info->dma = 0;
-	rq->cmd_flags &= ~REQ_FAILED;
-	len = rq->data_len;
-
-	/* Start sending the command to the drive. */
-	return cdrom_start_packet_command(drive, len, cdrom_do_pc_continuation);
-}
-
-
-static int cdrom_queue_packet_command(ide_drive_t *drive, struct request *rq)
+int ide_cd_queue_pc(ide_drive_t *drive, struct request *rq)
 {
 	struct request_sense sense;
 	int retries = 10;
@@ -1617,37 +978,6 @@
 }
 
 /*
- * Write handling
- */
-static int cdrom_write_check_ireason(ide_drive_t *drive, int len, int ireason)
-{
-	/* Two notes about IDE interrupt reason here - 0 means that
-	 * the drive wants to receive data from us, 2 means that
-	 * the drive is expecting to transfer data to us.
-	 */
-	if (ireason == 0)
-		return 0;
-	else if (ireason == 2) {
-		/* Whoops... The drive wants to send data. */
-		printk(KERN_ERR "%s: %s: wrong transfer direction!\n",
-				drive->name, __FUNCTION__);
-
-		while (len > 0) {
-			int dum = 0;
-			HWIF(drive)->atapi_input_bytes(drive, &dum, sizeof(dum));
-			len -= sizeof(dum);
-		}
-	} else {
-		/* Drive wants a command packet, or invalid ireason... */
-		printk(KERN_ERR "%s: %s: bad interrupt reason 0x%02x\n",
-				drive->name, __FUNCTION__, ireason);
-	}
-
-	cdrom_end_request(drive, 0);
-	return 1;
-}
-
-/*
  * Called from blk_end_request_callback() after the data of the request
  * is completed and before the request is completed.
  * By returning value '1', blk_end_request_callback() returns immediately
@@ -1658,174 +988,25 @@
 	return 1;
 }
 
-typedef void (xfer_func_t)(ide_drive_t *, void *, u32);
-
-/*
- * best way to deal with dma that is not sector aligned right now... note
- * that in this path we are not using ->data or ->buffer at all. this irs
- * can replace cdrom_pc_intr, cdrom_read_intr, and cdrom_write_intr in the
- * future.
- */
 static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
 {
 	struct cdrom_info *info = drive->driver_data;
 	struct request *rq = HWGROUP(drive)->rq;
-	int dma_error, dma, stat, ireason, len, thislen;
-	u8 lowcyl, highcyl;
 	xfer_func_t *xferfunc;
-	unsigned long flags;
+	ide_expiry_t *expiry = NULL;
+	int dma_error = 0, dma, stat, ireason, len, thislen, uptodate = 0;
+	int write = (rq_data_dir(rq) == WRITE) ? 1 : 0;
+	unsigned int timeout;
+	u8 lowcyl, highcyl;
 
 	/* Check for errors. */
-	dma_error = 0;
 	dma = info->dma;
 	if (dma) {
 		info->dma = 0;
 		dma_error = HWIF(drive)->ide_dma_end(drive);
-	}
-
-	if (cdrom_decode_status(drive, 0, &stat))
-		return ide_stopped;
-
-	/*
-	 * using dma, transfer is complete now
-	 */
-	if (dma) {
 		if (dma_error) {
-			printk(KERN_ERR "ide-cd: dma error\n");
-			ide_dma_off(drive);
-			return ide_error(drive, "dma error", stat);
-		}
-
-		spin_lock_irqsave(&ide_lock, flags);
-		if (__blk_end_request(rq, 0, rq->data_len))
-			BUG();
-		HWGROUP(drive)->rq = NULL;
-		spin_unlock_irqrestore(&ide_lock, flags);
-
-		return ide_stopped;
-	}
-
-	/*
-	 * ok we fall to pio :/
-	 */
-	ireason = HWIF(drive)->INB(IDE_IREASON_REG) & 0x3;
-	lowcyl  = HWIF(drive)->INB(IDE_BCOUNTL_REG);
-	highcyl = HWIF(drive)->INB(IDE_BCOUNTH_REG);
-
-	len = lowcyl + (256 * highcyl);
-	thislen = rq->data_len;
-	if (thislen > len)
-		thislen = len;
-
-	/*
-	 * If DRQ is clear, the command has completed.
-	 */
-	if ((stat & DRQ_STAT) == 0) {
-		spin_lock_irqsave(&ide_lock, flags);
-		if (__blk_end_request(rq, 0, rq->data_len))
-			BUG();
-		HWGROUP(drive)->rq = NULL;
-		spin_unlock_irqrestore(&ide_lock, flags);
-
-		return ide_stopped;
-	}
-
-	/*
-	 * check which way to transfer data
-	 */
-	if (rq_data_dir(rq) == WRITE) {
-		/*
-		 * write to drive
-		 */
-		if (cdrom_write_check_ireason(drive, len, ireason))
-			return ide_stopped;
-
-		xferfunc = HWIF(drive)->atapi_output_bytes;
-	} else  {
-		/*
-		 * read from drive
-		 */
-		if (cdrom_read_check_ireason(drive, len, ireason))
-			return ide_stopped;
-
-		xferfunc = HWIF(drive)->atapi_input_bytes;
-	}
-
-	/*
-	 * transfer data
-	 */
-	while (thislen > 0) {
-		int blen = blen = rq->data_len;
-		char *ptr = rq->data;
-
-		/*
-		 * bio backed?
-		 */
-		if (rq->bio) {
-			ptr = bio_data(rq->bio);
-			blen = bio_iovec(rq->bio)->bv_len;
-		}
-
-		if (!ptr) {
-			printk(KERN_ERR "%s: confused, missing data\n", drive->name);
-			break;
-		}
-
-		if (blen > thislen)
-			blen = thislen;
-
-		xferfunc(drive, ptr, blen);
-
-		thislen -= blen;
-		len -= blen;
-		rq->data_len -= blen;
-
-		if (rq->bio)
-			/*
-			 * The request can't be completed until DRQ is cleared.
-			 * So complete the data, but don't complete the request
-			 * using the dummy function for the callback feature
-			 * of blk_end_request_callback().
-			 */
-			blk_end_request_callback(rq, 0, blen,
-						 cdrom_newpc_intr_dummy_cb);
-		else
-			rq->data += blen;
-	}
-
-	/*
-	 * pad, if necessary
-	 */
-	if (len > 0) {
-		while (len > 0) {
-			int pad = 0;
-
-			xferfunc(drive, &pad, sizeof(pad));
-			len -= sizeof(pad);
-		}
-	}
-
-	BUG_ON(HWGROUP(drive)->handler != NULL);
-
-	ide_set_handler(drive, cdrom_newpc_intr, rq->timeout, NULL);
-	return ide_started;
-}
-
-static ide_startstop_t cdrom_write_intr(ide_drive_t *drive)
-{
-	int stat, ireason, len, sectors_to_transfer, uptodate;
-	struct cdrom_info *info = drive->driver_data;
-	int dma_error = 0, dma = info->dma;
-	u8 lowcyl = 0, highcyl = 0;
-
-	struct request *rq = HWGROUP(drive)->rq;
-
-	/* Check for errors. */
-	if (dma) {
-		info->dma = 0;
-		dma_error = HWIF(drive)->ide_dma_end(drive);
-		if (dma_error) {
-			printk(KERN_ERR "%s: DMA write error\n", drive->name);
+			printk(KERN_ERR "%s: DMA %s error\n", drive->name,
+					write ? "write" : "read");
 			ide_dma_off(drive);
 		}
 	}
@@ -1839,124 +1020,256 @@
 	if (dma) {
 		if (dma_error)
 			return ide_error(drive, "dma error", stat);
-
-		ide_end_request(drive, 1, rq->nr_sectors);
-		return ide_stopped;
+		if (blk_fs_request(rq)) {
+			ide_end_request(drive, 1, rq->nr_sectors);
+			return ide_stopped;
+		}
+		goto end_request;
 	}
 
-	/* Read the interrupt reason and the transfer length. */
+	/*
+	 * ok we fall to pio :/
+	 */
 	ireason = HWIF(drive)->INB(IDE_IREASON_REG) & 0x3;
 	lowcyl  = HWIF(drive)->INB(IDE_BCOUNTL_REG);
 	highcyl = HWIF(drive)->INB(IDE_BCOUNTH_REG);
 
 	len = lowcyl + (256 * highcyl);
 
-	/* If DRQ is clear, the command has completed. */
-	if ((stat & DRQ_STAT) == 0) {
-		/* If we're not done writing, complain.
-		 * Otherwise, complete the command normally.
-		 */
-		uptodate = 1;
-		if (rq->current_nr_sectors > 0) {
-			printk(KERN_ERR "%s: %s: data underrun (%d blocks)\n",
-					drive->name, __FUNCTION__,
-					rq->current_nr_sectors);
-			uptodate = 0;
-		}
-		cdrom_end_request(drive, uptodate);
-		return ide_stopped;
-	}
-
-	/* Check that the drive is expecting to do the same thing we are. */
-	if (cdrom_write_check_ireason(drive, len, ireason))
-		return ide_stopped;
-
-	sectors_to_transfer = len / SECTOR_SIZE;
+	thislen = blk_fs_request(rq) ? len : rq->data_len;
+	if (thislen > len)
+		thislen = len;
 
 	/*
-	 * now loop and write out the data
+	 * If DRQ is clear, the command has completed.
 	 */
-	while (sectors_to_transfer > 0) {
-		int this_transfer;
+	if ((stat & DRQ_STAT) == 0) {
+		if (blk_fs_request(rq)) {
+			/*
+			 * If we're not done reading/writing, complain.
+			 * Otherwise, complete the command normally.
+			 */
+			uptodate = 1;
+			if (rq->current_nr_sectors > 0) {
+				printk(KERN_ERR "%s: %s: data underrun "
+						"(%d blocks)\n",
+						drive->name, __FUNCTION__,
+						rq->current_nr_sectors);
+				if (!write)
+					rq->cmd_flags |= REQ_FAILED;
+				uptodate = 0;
+			}
+			cdrom_end_request(drive, uptodate);
+			return ide_stopped;
+		} else if (!blk_pc_request(rq)) {
+			ide_cd_request_sense_fixup(rq);
+			/* Complain if we still have data left to transfer. */
+			uptodate = rq->data_len ? 0 : 1;
+		}
+		goto end_request;
+	}
 
-		if (!rq->current_nr_sectors) {
-			printk(KERN_ERR "%s: %s: confused, missing data\n",
-					drive->name, __FUNCTION__);
+	/*
+	 * check which way to transfer data
+	 */
+	if (blk_fs_request(rq) || blk_pc_request(rq)) {
+		if (ide_cd_check_ireason(drive, len, ireason, write))
+			return ide_stopped;
+
+		if (blk_fs_request(rq) && write == 0) {
+			int nskip;
+
+			if (ide_cd_check_transfer_size(drive, len)) {
+				cdrom_end_request(drive, 0);
+				return ide_stopped;
+			}
+
+			/*
+			 * First, figure out if we need to bit-bucket
+			 * any of the leading sectors.
+			 */
+			nskip = min_t(int, rq->current_nr_sectors
+					   - bio_cur_sectors(rq->bio),
+					   thislen >> 9);
+			if (nskip > 0) {
+				ide_cd_drain_data(drive, nskip);
+				rq->current_nr_sectors -= nskip;
+				thislen -= (nskip << 9);
+			}
+		}
+	}
+
+	if (ireason == 0) {
+		write = 1;
+		xferfunc = HWIF(drive)->atapi_output_bytes;
+	} else if (ireason == 2 || (ireason == 1 &&
+		   (blk_fs_request(rq) || blk_pc_request(rq)))) {
+		write = 0;
+		xferfunc = HWIF(drive)->atapi_input_bytes;
+	} else {
+		printk(KERN_ERR "%s: %s: The drive "
+				"appears confused (ireason = 0x%02x). "
+				"Trying to recover by ending request.\n",
+				drive->name, __FUNCTION__, ireason);
+		goto end_request;
+	}
+
+	/*
+	 * transfer data
+	 */
+	while (thislen > 0) {
+		u8 *ptr = blk_fs_request(rq) ? NULL : rq->data;
+		int blen = rq->data_len;
+
+		/*
+		 * bio backed?
+		 */
+		if (rq->bio) {
+			if (blk_fs_request(rq)) {
+				ptr = rq->buffer;
+				blen = rq->current_nr_sectors << 9;
+			} else {
+				ptr = bio_data(rq->bio);
+				blen = bio_iovec(rq->bio)->bv_len;
+			}
+		}
+
+		if (!ptr) {
+			if (blk_fs_request(rq) && !write)
+				/*
+				 * If the buffers are full, cache the rest
+				 * of the data in our internal buffer.
+				 */
+				cdrom_buffer_sectors(drive, rq->sector,
+						     thislen >> 9);
+			else {
+				printk(KERN_ERR "%s: confused, missing data\n",
+						drive->name);
+				blk_dump_rq_flags(rq, rq_data_dir(rq)
+						  ? "cdrom_newpc_intr, write"
+						  : "cdrom_newpc_intr, read");
+			}
 			break;
 		}
 
-		/*
-		 * Figure out how many sectors we can transfer
-		 */
-		this_transfer = min_t(int, sectors_to_transfer, rq->current_nr_sectors);
+		if (blen > thislen)
+			blen = thislen;
 
-		while (this_transfer > 0) {
-			HWIF(drive)->atapi_output_bytes(drive, rq->buffer, SECTOR_SIZE);
-			rq->buffer += SECTOR_SIZE;
-			--rq->nr_sectors;
-			--rq->current_nr_sectors;
-			++rq->sector;
-			--this_transfer;
-			--sectors_to_transfer;
+		xferfunc(drive, ptr, blen);
+
+		thislen -= blen;
+		len -= blen;
+
+		if (blk_fs_request(rq)) {
+			rq->buffer += blen;
+			rq->nr_sectors -= (blen >> 9);
+			rq->current_nr_sectors -= (blen >> 9);
+			rq->sector += (blen >> 9);
+
+			if (rq->current_nr_sectors == 0 && rq->nr_sectors)
+				cdrom_end_request(drive, 1);
+		} else {
+			rq->data_len -= blen;
+
+			/*
+			 * The request can't be completed until DRQ is cleared.
+			 * So complete the data, but don't complete the request
+			 * using the dummy function for the callback feature
+			 * of blk_end_request_callback().
+			 */
+			if (rq->bio)
+				blk_end_request_callback(rq, 0, blen,
+						 cdrom_newpc_intr_dummy_cb);
+			else
+				rq->data += blen;
 		}
-
-		/*
-		 * current buffer complete, move on
-		 */
-		if (rq->current_nr_sectors == 0 && rq->nr_sectors)
-			cdrom_end_request(drive, 1);
 	}
 
-	/* re-arm handler */
-	ide_set_handler(drive, &cdrom_write_intr, ATAPI_WAIT_PC, NULL);
-	return ide_started;
-}
-
-static ide_startstop_t cdrom_start_write_cont(ide_drive_t *drive)
-{
-	struct request *rq = HWGROUP(drive)->rq;
-
-#if 0	/* the immediate bit */
-	rq->cmd[1] = 1 << 3;
-#endif
-	rq->timeout = ATAPI_WAIT_PC;
-
-	return cdrom_transfer_packet_command(drive, rq, cdrom_write_intr);
-}
-
-static ide_startstop_t cdrom_start_write(ide_drive_t *drive, struct request *rq)
-{
-	struct cdrom_info *info = drive->driver_data;
-	struct gendisk *g = info->disk;
-	unsigned short sectors_per_frame = queue_hardsect_size(drive->queue) >> SECTOR_BITS;
+	if (write && blk_sense_request(rq))
+		rq->sense_len += thislen;
 
 	/*
-	 * writes *must* be hardware frame aligned
+	 * pad, if necessary
+	 */
+	if (!blk_fs_request(rq) && len > 0)
+		ide_cd_pad_transfer(drive, xferfunc, len);
+
+	if (blk_pc_request(rq)) {
+		timeout = rq->timeout;
+	} else {
+		timeout = ATAPI_WAIT_PC;
+		if (!blk_fs_request(rq))
+			expiry = cdrom_timer_expiry;
+	}
+
+	ide_set_handler(drive, cdrom_newpc_intr, timeout, expiry);
+	return ide_started;
+
+end_request:
+	if (blk_pc_request(rq)) {
+		unsigned long flags;
+
+		spin_lock_irqsave(&ide_lock, flags);
+		if (__blk_end_request(rq, 0, rq->data_len))
+			BUG();
+		HWGROUP(drive)->rq = NULL;
+		spin_unlock_irqrestore(&ide_lock, flags);
+	} else {
+		if (!uptodate)
+			rq->cmd_flags |= REQ_FAILED;
+		cdrom_end_request(drive, uptodate);
+	}
+	return ide_stopped;
+}
+
+static ide_startstop_t cdrom_start_rw(ide_drive_t *drive, struct request *rq)
+{
+	struct cdrom_info *cd = drive->driver_data;
+	int write = rq_data_dir(rq) == WRITE;
+	unsigned short sectors_per_frame =
+		queue_hardsect_size(drive->queue) >> SECTOR_BITS;
+
+	if (write) {
+		/*
+		 * disk has become write protected
+		 */
+		if (cd->disk->policy) {
+			cdrom_end_request(drive, 0);
+			return ide_stopped;
+		}
+	} else {
+		/*
+		 * We may be retrying this request after an error.  Fix up any
+		 * weirdness which might be present in the request packet.
+		 */
+		restore_request(rq);
+
+		/* Satisfy whatever we can of this request from our cache. */
+		if (cdrom_read_from_buffer(drive))
+			return ide_stopped;
+	}
+
+	/*
+	 * use DMA, if possible / writes *must* be hardware frame aligned
 	 */
 	if ((rq->nr_sectors & (sectors_per_frame - 1)) ||
 	    (rq->sector & (sectors_per_frame - 1))) {
-		cdrom_end_request(drive, 0);
-		return ide_stopped;
-	}
+		if (write) {
+			cdrom_end_request(drive, 0);
+			return ide_stopped;
+		}
+		cd->dma = 0;
+	} else
+		cd->dma = drive->using_dma;
 
-	/*
-	 * disk has become write protected
-	 */
-	if (g->policy) {
-		cdrom_end_request(drive, 0);
-		return ide_stopped;
-	}
+	/* Clear the local sector buffer. */
+	cd->nsectors_buffered = 0;
 
-	info->nsectors_buffered = 0;
+	if (write)
+		cd->devinfo.media_written = 1;
 
-	/* use dma, if possible. we don't need to check more, since we
-	 * know that the transfer is always (at least!) frame aligned */
-	info->dma = drive->using_dma ? 1 : 0;
-
-	info->devinfo.media_written = 1;
-
-	/* Start sending the write request to the drive. */
-	return cdrom_start_packet_command(drive, 32768, cdrom_start_write_cont);
+	/* Start sending the read/write request to the drive. */
+	return cdrom_start_packet_command(drive, 32768, cdrom_start_rw_cont);
 }
 
 static ide_startstop_t cdrom_do_newpc_cont(ide_drive_t *drive)
@@ -1973,7 +1286,10 @@
 {
 	struct cdrom_info *info = drive->driver_data;
 
-	rq->cmd_flags |= REQ_QUIET;
+	if (blk_pc_request(rq))
+		rq->cmd_flags |= REQ_QUIET;
+	else
+		rq->cmd_flags &= ~REQ_FAILED;
 
 	info->dma = 0;
 
@@ -2010,7 +1326,7 @@
 	struct cdrom_info *info = drive->driver_data;
 
 	if (blk_fs_request(rq)) {
-		if (CDROM_CONFIG_FLAGS(drive)->seeking) {
+		if (info->cd_flags & IDE_CD_FLAG_SEEKING) {
 			unsigned long elapsed = jiffies - info->start_seek;
 			int stat = HWIF(drive)->INB(IDE_STATUS_REG);
 
@@ -2021,22 +1337,16 @@
 				}
 				printk (KERN_ERR "%s: DSC timeout\n", drive->name);
 			}
-			CDROM_CONFIG_FLAGS(drive)->seeking = 0;
+			info->cd_flags &= ~IDE_CD_FLAG_SEEKING;
 		}
 		if ((rq_data_dir(rq) == READ) && IDE_LARGE_SEEK(info->last_block, block, IDECD_SEEK_THRESHOLD) && drive->dsc_overlap) {
 			action = cdrom_start_seek(drive, block);
-		} else {
-			if (rq_data_dir(rq) == READ)
-				action = cdrom_start_read(drive, block);
-			else
-				action = cdrom_start_write(drive, rq);
-		}
+		} else
+			action = cdrom_start_rw(drive, rq);
 		info->last_block = block;
 		return action;
-	} else if (rq->cmd_type == REQ_TYPE_SENSE ||
+	} else if (blk_sense_request(rq) || blk_pc_request(rq) ||
 		   rq->cmd_type == REQ_TYPE_ATA_PC) {
-		return cdrom_do_packet_command(drive);
-	} else if (blk_pc_request(rq)) {
 		return cdrom_do_block_pc(drive, rq);
 	} else if (blk_special_request(rq)) {
 		/*
@@ -2063,141 +1373,33 @@
  * can also be NULL, in which case no sense information is returned.
  */
 
-#if ! STANDARD_ATAPI
-static inline
-int bin2bcd (int x)
-{
-	return (x%10) | ((x/10) << 4);
-}
-
-
-static inline
-int bcd2bin (int x)
-{
-	return (x >> 4) * 10 + (x & 0x0f);
-}
-
 static
 void msf_from_bcd (struct atapi_msf *msf)
 {
-	msf->minute = bcd2bin (msf->minute);
-	msf->second = bcd2bin (msf->second);
-	msf->frame  = bcd2bin (msf->frame);
+	msf->minute = BCD2BIN(msf->minute);
+	msf->second = BCD2BIN(msf->second);
+	msf->frame  = BCD2BIN(msf->frame);
 }
 
-#endif /* not STANDARD_ATAPI */
-
-
-static inline
-void lba_to_msf (int lba, byte *m, byte *s, byte *f)
-{
-	lba += CD_MSF_OFFSET;
-	lba &= 0xffffff;  /* negative lbas use only 24 bits */
-	*m = lba / (CD_SECS * CD_FRAMES);
-	lba %= (CD_SECS * CD_FRAMES);
-	*s = lba / CD_FRAMES;
-	*f = lba % CD_FRAMES;
-}
-
-
-static inline
-int msf_to_lba (byte m, byte s, byte f)
-{
-	return (((m * CD_SECS) + s) * CD_FRAMES + f) - CD_MSF_OFFSET;
-}
-
-static int cdrom_check_status(ide_drive_t *drive, struct request_sense *sense)
+int cdrom_check_status(ide_drive_t *drive, struct request_sense *sense)
 {
 	struct request req;
 	struct cdrom_info *info = drive->driver_data;
 	struct cdrom_device_info *cdi = &info->devinfo;
 
-	cdrom_prepare_request(drive, &req);
+	ide_cd_init_rq(drive, &req);
 
 	req.sense = sense;
 	req.cmd[0] = GPCMD_TEST_UNIT_READY;
 	req.cmd_flags |= REQ_QUIET;
 
-#if ! STANDARD_ATAPI
-        /* the Sanyo 3 CD changer uses byte 7 of TEST_UNIT_READY to 
-           switch CDs instead of supporting the LOAD_UNLOAD opcode   */
-
+	/*
+	 * Sanyo 3 CD changer uses byte 7 of TEST_UNIT_READY to
+	 * switch CDs instead of supporting the LOAD_UNLOAD opcode.
+	 */
 	req.cmd[7] = cdi->sanyo_slot % 3;
-#endif /* not STANDARD_ATAPI */
 
-	return cdrom_queue_packet_command(drive, &req);
-}
-
-
-/* Lock the door if LOCKFLAG is nonzero; unlock it otherwise. */
-static int
-cdrom_lockdoor(ide_drive_t *drive, int lockflag, struct request_sense *sense)
-{
-	struct request_sense my_sense;
-	struct request req;
-	int stat;
-
-	if (sense == NULL)
-		sense = &my_sense;
-
-	/* If the drive cannot lock the door, just pretend. */
-	if (CDROM_CONFIG_FLAGS(drive)->no_doorlock) {
-		stat = 0;
-	} else {
-		cdrom_prepare_request(drive, &req);
-		req.sense = sense;
-		req.cmd[0] = GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL;
-		req.cmd[4] = lockflag ? 1 : 0;
-		stat = cdrom_queue_packet_command(drive, &req);
-	}
-
-	/* If we got an illegal field error, the drive
-	   probably cannot lock the door. */
-	if (stat != 0 &&
-	    sense->sense_key == ILLEGAL_REQUEST &&
-	    (sense->asc == 0x24 || sense->asc == 0x20)) {
-		printk (KERN_ERR "%s: door locking not supported\n",
-			drive->name);
-		CDROM_CONFIG_FLAGS(drive)->no_doorlock = 1;
-		stat = 0;
-	}
-	
-	/* no medium, that's alright. */
-	if (stat != 0 && sense->sense_key == NOT_READY && sense->asc == 0x3a)
-		stat = 0;
-
-	if (stat == 0)
-		CDROM_STATE_FLAGS(drive)->door_locked = lockflag;
-
-	return stat;
-}
-
-
-/* Eject the disk if EJECTFLAG is 0.
-   If EJECTFLAG is 1, try to reload the disk. */
-static int cdrom_eject(ide_drive_t *drive, int ejectflag,
-		       struct request_sense *sense)
-{
-	struct request req;
-	char loej = 0x02;
-
-	if (CDROM_CONFIG_FLAGS(drive)->no_eject && !ejectflag)
-		return -EDRIVE_CANT_DO_THIS;
-	
-	/* reload fails on some drives, if the tray is locked */
-	if (CDROM_STATE_FLAGS(drive)->door_locked && ejectflag)
-		return 0;
-
-	cdrom_prepare_request(drive, &req);
-
-	/* only tell drive to close tray if open, if it can do that */
-	if (ejectflag && !CDROM_CONFIG_FLAGS(drive)->close_tray)
-		loej = 0;
-
-	req.sense = sense;
-	req.cmd[0] = GPCMD_START_STOP_UNIT;
-	req.cmd[4] = loej | (ejectflag != 0);
-	return cdrom_queue_packet_command(drive, &req);
+	return ide_cd_queue_pc(drive, &req);
 }
 
 static int cdrom_read_capacity(ide_drive_t *drive, unsigned long *capacity,
@@ -2212,7 +1414,7 @@
 	int stat;
 	struct request req;
 
-	cdrom_prepare_request(drive, &req);
+	ide_cd_init_rq(drive, &req);
 
 	req.sense = sense;
 	req.cmd[0] = GPCMD_READ_CDVD_CAPACITY;
@@ -2220,7 +1422,7 @@
 	req.data_len = sizeof(capbuf);
 	req.cmd_flags |= REQ_QUIET;
 
-	stat = cdrom_queue_packet_command(drive, &req);
+	stat = ide_cd_queue_pc(drive, &req);
 	if (stat == 0) {
 		*capacity = 1 + be32_to_cpu(capbuf.lba);
 		*sectors_per_frame =
@@ -2236,7 +1438,7 @@
 {
 	struct request req;
 
-	cdrom_prepare_request(drive, &req);
+	ide_cd_init_rq(drive, &req);
 
 	req.sense = sense;
 	req.data =  buf;
@@ -2251,12 +1453,11 @@
 	if (msf_flag)
 		req.cmd[1] = 2;
 
-	return cdrom_queue_packet_command(drive, &req);
+	return ide_cd_queue_pc(drive, &req);
 }
 
-
 /* Try to read the entire TOC for the disk into our internal buffer. */
-static int cdrom_read_toc(ide_drive_t *drive, struct request_sense *sense)
+int ide_cd_read_toc(ide_drive_t *drive, struct request_sense *sense)
 {
 	int stat, ntracks, i;
 	struct cdrom_info *info = drive->driver_data;
@@ -2283,7 +1484,7 @@
 	   If it is, just return. */
 	(void) cdrom_check_status(drive, sense);
 
-	if (CDROM_STATE_FLAGS(drive)->toc_valid)
+	if (info->cd_flags & IDE_CD_FLAG_TOC_VALID)
 		return 0;
 
 	/* Try to get the total cdrom capacity and sector size. */
@@ -2305,12 +1506,10 @@
 	if (stat)
 		return stat;
 
-#if ! STANDARD_ATAPI
-	if (CDROM_CONFIG_FLAGS(drive)->toctracks_as_bcd) {
-		toc->hdr.first_track = bcd2bin(toc->hdr.first_track);
-		toc->hdr.last_track  = bcd2bin(toc->hdr.last_track);
+	if (info->cd_flags & IDE_CD_FLAG_TOCTRACKS_AS_BCD) {
+		toc->hdr.first_track = BCD2BIN(toc->hdr.first_track);
+		toc->hdr.last_track  = BCD2BIN(toc->hdr.last_track);
 	}
-#endif  /* not STANDARD_ATAPI */
 
 	ntracks = toc->hdr.last_track - toc->hdr.first_track + 1;
 	if (ntracks <= 0)
@@ -2342,16 +1541,13 @@
 					   (ntracks + 1) *
 					   sizeof(struct atapi_toc_entry),
 					   sense);
-		if (stat) {
+		if (stat)
 			return stat;
-		}
-#if ! STANDARD_ATAPI
-		if (CDROM_CONFIG_FLAGS(drive)->toctracks_as_bcd) {
-			toc->hdr.first_track = bin2bcd(CDROM_LEADOUT);
-			toc->hdr.last_track = bin2bcd(CDROM_LEADOUT);
-		} else
-#endif  /* not STANDARD_ATAPI */
-		{
+
+		if (info->cd_flags & IDE_CD_FLAG_TOCTRACKS_AS_BCD) {
+			toc->hdr.first_track = (u8)BIN2BCD(CDROM_LEADOUT);
+			toc->hdr.last_track = (u8)BIN2BCD(CDROM_LEADOUT);
+		} else {
 			toc->hdr.first_track = CDROM_LEADOUT;
 			toc->hdr.last_track = CDROM_LEADOUT;
 		}
@@ -2362,21 +1558,17 @@
 
 	toc->hdr.toc_length = ntohs (toc->hdr.toc_length);
 
-#if ! STANDARD_ATAPI
-	if (CDROM_CONFIG_FLAGS(drive)->toctracks_as_bcd) {
-		toc->hdr.first_track = bcd2bin(toc->hdr.first_track);
-		toc->hdr.last_track  = bcd2bin(toc->hdr.last_track);
+	if (info->cd_flags & IDE_CD_FLAG_TOCTRACKS_AS_BCD) {
+		toc->hdr.first_track = BCD2BIN(toc->hdr.first_track);
+		toc->hdr.last_track  = BCD2BIN(toc->hdr.last_track);
 	}
-#endif  /* not STANDARD_ATAPI */
 
-	for (i=0; i<=ntracks; i++) {
-#if ! STANDARD_ATAPI
-		if (CDROM_CONFIG_FLAGS(drive)->tocaddr_as_bcd) {
-			if (CDROM_CONFIG_FLAGS(drive)->toctracks_as_bcd)
-				toc->ent[i].track = bcd2bin(toc->ent[i].track);
+	for (i = 0; i <= ntracks; i++) {
+		if (info->cd_flags & IDE_CD_FLAG_TOCADDR_AS_BCD) {
+			if (info->cd_flags & IDE_CD_FLAG_TOCTRACKS_AS_BCD)
+				toc->ent[i].track = BCD2BIN(toc->ent[i].track);
 			msf_from_bcd(&toc->ent[i].addr.msf);
 		}
-#endif  /* not STANDARD_ATAPI */
 		toc->ent[i].addr.lba = msf_to_lba (toc->ent[i].addr.msf.minute,
 						   toc->ent[i].addr.msf.second,
 						   toc->ent[i].addr.msf.frame);
@@ -2396,8 +1588,7 @@
 		toc->last_session_lba = msf_to_lba(0, 2, 0); /* 0m 2s 0f */
 	}
 
-#if ! STANDARD_ATAPI
-	if (CDROM_CONFIG_FLAGS(drive)->tocaddr_as_bcd) {
+	if (info->cd_flags & IDE_CD_FLAG_TOCADDR_AS_BCD) {
 		/* Re-read multisession information using MSF format */
 		stat = cdrom_read_tocentry(drive, 0, 1, 1, (char *)&ms_tmp,
 					   sizeof(ms_tmp), sense);
@@ -2409,7 +1600,6 @@
 					  	   ms_tmp.ent.addr.msf.second,
 						   ms_tmp.ent.addr.msf.frame);
 	}
-#endif  /* not STANDARD_ATAPI */
 
 	toc->xa_flag = (ms_tmp.hdr.first_track != ms_tmp.hdr.last_track);
 
@@ -2422,278 +1612,22 @@
 	}
 
 	/* Remember that we've read this stuff. */
-	CDROM_STATE_FLAGS(drive)->toc_valid = 1;
+	info->cd_flags |= IDE_CD_FLAG_TOC_VALID;
 
 	return 0;
 }
 
-
-static int cdrom_read_subchannel(ide_drive_t *drive, int format, char *buf,
-				 int buflen, struct request_sense *sense)
-{
-	struct request req;
-
-	cdrom_prepare_request(drive, &req);
-
-	req.sense = sense;
-	req.data = buf;
-	req.data_len = buflen;
-	req.cmd[0] = GPCMD_READ_SUBCHANNEL;
-	req.cmd[1] = 2;     /* MSF addressing */
-	req.cmd[2] = 0x40;  /* request subQ data */
-	req.cmd[3] = format;
-	req.cmd[7] = (buflen >> 8);
-	req.cmd[8] = (buflen & 0xff);
-	return cdrom_queue_packet_command(drive, &req);
-}
-
-/* ATAPI cdrom drives are free to select the speed you request or any slower
-   rate :-( Requesting too fast a speed will _not_ produce an error. */
-static int cdrom_select_speed(ide_drive_t *drive, int speed,
-			      struct request_sense *sense)
-{
-	struct request req;
-	cdrom_prepare_request(drive, &req);
-
-	req.sense = sense;
-	if (speed == 0)
-		speed = 0xffff; /* set to max */
-	else
-		speed *= 177;   /* Nx to kbytes/s */
-
-	req.cmd[0] = GPCMD_SET_SPEED;
-	/* Read Drive speed in kbytes/second MSB */
-	req.cmd[2] = (speed >> 8) & 0xff;	
-	/* Read Drive speed in kbytes/second LSB */
-	req.cmd[3] = speed & 0xff;
-	if (CDROM_CONFIG_FLAGS(drive)->cd_r ||
-	    CDROM_CONFIG_FLAGS(drive)->cd_rw ||
-	    CDROM_CONFIG_FLAGS(drive)->dvd_r) {
-		/* Write Drive speed in kbytes/second MSB */
-		req.cmd[4] = (speed >> 8) & 0xff;
-		/* Write Drive speed in kbytes/second LSB */
-		req.cmd[5] = speed & 0xff;
-       }
-
-	return cdrom_queue_packet_command(drive, &req);
-}
-
-static int cdrom_play_audio(ide_drive_t *drive, int lba_start, int lba_end)
-{
-	struct request_sense sense;
-	struct request req;
-
-	cdrom_prepare_request(drive, &req);
-
-	req.sense = &sense;
-	req.cmd[0] = GPCMD_PLAY_AUDIO_MSF;
-	lba_to_msf(lba_start, &req.cmd[3], &req.cmd[4], &req.cmd[5]);
-	lba_to_msf(lba_end-1, &req.cmd[6], &req.cmd[7], &req.cmd[8]);
-
-	return cdrom_queue_packet_command(drive, &req);
-}
-
-static int cdrom_get_toc_entry(ide_drive_t *drive, int track,
-				struct atapi_toc_entry **ent)
-{
-	struct cdrom_info *info = drive->driver_data;
-	struct atapi_toc *toc = info->toc;
-	int ntracks;
-
-	/*
-	 * don't serve cached data, if the toc isn't valid
-	 */
-	if (!CDROM_STATE_FLAGS(drive)->toc_valid)
-		return -EINVAL;
-
-	/* Check validity of requested track number. */
-	ntracks = toc->hdr.last_track - toc->hdr.first_track + 1;
-	if (toc->hdr.first_track == CDROM_LEADOUT) ntracks = 0;
-	if (track == CDROM_LEADOUT)
-		*ent = &toc->ent[ntracks];
-	else if (track < toc->hdr.first_track ||
-		 track > toc->hdr.last_track)
-		return -EINVAL;
-	else
-		*ent = &toc->ent[track - toc->hdr.first_track];
-
-	return 0;
-}
-
-/* the generic packet interface to cdrom.c */
-static int ide_cdrom_packet(struct cdrom_device_info *cdi,
-			    struct packet_command *cgc)
-{
-	struct request req;
-	ide_drive_t *drive = cdi->handle;
-
-	if (cgc->timeout <= 0)
-		cgc->timeout = ATAPI_WAIT_PC;
-
-	/* here we queue the commands from the uniform CD-ROM
-	   layer. the packet must be complete, as we do not
-	   touch it at all. */
-	cdrom_prepare_request(drive, &req);
-	memcpy(req.cmd, cgc->cmd, CDROM_PACKET_SIZE);
-	if (cgc->sense)
-		memset(cgc->sense, 0, sizeof(struct request_sense));
-	req.data = cgc->buffer;
-	req.data_len = cgc->buflen;
-	req.timeout = cgc->timeout;
-
-	if (cgc->quiet)
-		req.cmd_flags |= REQ_QUIET;
-
-	req.sense = cgc->sense;
-	cgc->stat = cdrom_queue_packet_command(drive, &req);
-	if (!cgc->stat)
-		cgc->buflen -= req.data_len;
-	return cgc->stat;
-}
-
-static
-int ide_cdrom_audio_ioctl (struct cdrom_device_info *cdi,
-			   unsigned int cmd, void *arg)
-			   
-{
-	ide_drive_t *drive = cdi->handle;
-	struct cdrom_info *info = drive->driver_data;
-	int stat;
-
-	switch (cmd) {
-	/*
-	 * emulate PLAY_AUDIO_TI command with PLAY_AUDIO_10, since
-	 * atapi doesn't support it
-	 */
-	case CDROMPLAYTRKIND: {
-		unsigned long lba_start, lba_end;
-		struct cdrom_ti *ti = arg;
-		struct atapi_toc_entry *first_toc, *last_toc;
-
-		stat = cdrom_get_toc_entry(drive, ti->cdti_trk0, &first_toc);
-		if (stat)
-			return stat;
-
-		stat = cdrom_get_toc_entry(drive, ti->cdti_trk1, &last_toc);
-		if (stat)
-			return stat;
-
-		if (ti->cdti_trk1 != CDROM_LEADOUT)
-			++last_toc;
-		lba_start = first_toc->addr.lba;
-		lba_end   = last_toc->addr.lba;
-
-		if (lba_end <= lba_start)
-			return -EINVAL;
-
-		return cdrom_play_audio(drive, lba_start, lba_end);
-	}
-
-	case CDROMREADTOCHDR: {
-		struct cdrom_tochdr *tochdr = arg;
-		struct atapi_toc *toc;
-
-		/* Make sure our saved TOC is valid. */
-		stat = cdrom_read_toc(drive, NULL);
-		if (stat)
-			return stat;
-
-		toc = info->toc;
-		tochdr->cdth_trk0 = toc->hdr.first_track;
-		tochdr->cdth_trk1 = toc->hdr.last_track;
-
-		return 0;
-	}
-
-	case CDROMREADTOCENTRY: {
-		struct cdrom_tocentry *tocentry = arg;
-		struct atapi_toc_entry *toce;
-
-		stat = cdrom_get_toc_entry(drive, tocentry->cdte_track, &toce);
-		if (stat)
-			return stat;
-
-		tocentry->cdte_ctrl = toce->control;
-		tocentry->cdte_adr  = toce->adr;
-		if (tocentry->cdte_format == CDROM_MSF) {
-			lba_to_msf (toce->addr.lba,
-				   &tocentry->cdte_addr.msf.minute,
-				   &tocentry->cdte_addr.msf.second,
-				   &tocentry->cdte_addr.msf.frame);
-		} else
-			tocentry->cdte_addr.lba = toce->addr.lba;
-
-		return 0;
-	}
-
-	default:
-		return -EINVAL;
-	}
-}
-
-static
-int ide_cdrom_reset (struct cdrom_device_info *cdi)
-{
-	ide_drive_t *drive = cdi->handle;
-	struct request_sense sense;
-	struct request req;
-	int ret;
-
-	cdrom_prepare_request(drive, &req);
-	req.cmd_type = REQ_TYPE_SPECIAL;
-	req.cmd_flags = REQ_QUIET;
-	ret = ide_do_drive_cmd(drive, &req, ide_wait);
-
-	/*
-	 * A reset will unlock the door. If it was previously locked,
-	 * lock it again.
-	 */
-	if (CDROM_STATE_FLAGS(drive)->door_locked)
-		(void) cdrom_lockdoor(drive, 1, &sense);
-
-	return ret;
-}
-
-
-static
-int ide_cdrom_tray_move (struct cdrom_device_info *cdi, int position)
-{
-	ide_drive_t *drive = cdi->handle;
-	struct request_sense sense;
-
-	if (position) {
-		int stat = cdrom_lockdoor(drive, 0, &sense);
-		if (stat)
-			return stat;
-	}
-
-	return cdrom_eject(drive, !position, &sense);
-}
-
-static
-int ide_cdrom_lock_door (struct cdrom_device_info *cdi, int lock)
-{
-	ide_drive_t *drive = cdi->handle;
-	return cdrom_lockdoor(drive, lock, NULL);
-}
-
-static
-int ide_cdrom_get_capabilities(ide_drive_t *drive, struct atapi_capabilities_page *cap)
+int ide_cdrom_get_capabilities(ide_drive_t *drive, u8 *buf)
 {
 	struct cdrom_info *info = drive->driver_data;
 	struct cdrom_device_info *cdi = &info->devinfo;
 	struct packet_command cgc;
-	int stat, attempts = 3, size = sizeof(*cap);
+	int stat, attempts = 3, size = ATAPI_CAPABILITIES_PAGE_SIZE;
 
-	/*
-	 * ACER50 (and others?) require the full spec length mode sense
-	 * page capabilities size, but older drives break.
-	 */
-	if (!(!strcmp(drive->id->model, "ATAPI CD ROM DRIVE 50X MAX") ||
-	    !strcmp(drive->id->model, "WPI CDS-32X")))
-		size -= sizeof(cap->pad);
+	if ((info->cd_flags & IDE_CD_FLAG_FULL_CAPS_PAGE) == 0)
+		size -= ATAPI_CAPABILITIES_PAGE_PAD_SIZE;
 
-	init_cdrom_command(&cgc, cap, size, CGC_DATA_UNKNOWN);
+	init_cdrom_command(&cgc, buf, size, CGC_DATA_UNKNOWN);
 	do { /* we seem to get stat=0x01,err=0x00 the first time (??) */
 		stat = cdrom_mode_sense(cdi, &cgc, GPMODE_CAPABILITIES_PAGE, 0);
 		if (!stat)
@@ -2702,177 +1636,33 @@
 	return stat;
 }
 
-static
-void ide_cdrom_update_speed (ide_drive_t *drive, struct atapi_capabilities_page *cap)
+void ide_cdrom_update_speed(ide_drive_t *drive, u8 *buf)
 {
-	/* The ACER/AOpen 24X cdrom has the speed fields byte-swapped */
-	if (!drive->id->model[0] &&
-	    !strncmp(drive->id->fw_rev, "241N", 4)) {
-		CDROM_STATE_FLAGS(drive)->current_speed  =
-			(le16_to_cpu(cap->curspeed) + (176/2)) / 176;
-		CDROM_CONFIG_FLAGS(drive)->max_speed =
-			(le16_to_cpu(cap->maxspeed) + (176/2)) / 176;
+	struct cdrom_info *cd = drive->driver_data;
+	u16 curspeed, maxspeed;
+
+	curspeed = *(u16 *)&buf[8 + 14];
+	maxspeed = *(u16 *)&buf[8 +  8];
+
+	if (cd->cd_flags & IDE_CD_FLAG_LE_SPEED_FIELDS) {
+		curspeed = le16_to_cpu(curspeed);
+		maxspeed = le16_to_cpu(maxspeed);
 	} else {
-		CDROM_STATE_FLAGS(drive)->current_speed  =
-			(be16_to_cpu(cap->curspeed) + (176/2)) / 176;
-		CDROM_CONFIG_FLAGS(drive)->max_speed =
-			(be16_to_cpu(cap->maxspeed) + (176/2)) / 176;
-	}
-}
-
-static
-int ide_cdrom_select_speed (struct cdrom_device_info *cdi, int speed)
-{
-	ide_drive_t *drive = cdi->handle;
-	struct request_sense sense;
-	struct atapi_capabilities_page cap;
-	int stat;
-
-	if ((stat = cdrom_select_speed(drive, speed, &sense)) < 0)
-		return stat;
-
-	if (!ide_cdrom_get_capabilities(drive, &cap)) {
-		ide_cdrom_update_speed(drive, &cap);
-		cdi->speed = CDROM_STATE_FLAGS(drive)->current_speed;
-	}
-        return 0;
-}
-
-/*
- * add logic to try GET_EVENT command first to check for media and tray
- * status. this should be supported by newer cd-r/w and all DVD etc
- * drives
- */
-static
-int ide_cdrom_drive_status (struct cdrom_device_info *cdi, int slot_nr)
-{
-	ide_drive_t *drive = cdi->handle;
-	struct media_event_desc med;
-	struct request_sense sense;
-	int stat;
-
-	if (slot_nr != CDSL_CURRENT)
-		return -EINVAL;
-
-	stat = cdrom_check_status(drive, &sense);
-	if (!stat || sense.sense_key == UNIT_ATTENTION)
-		return CDS_DISC_OK;
-
-	if (!cdrom_get_media_event(cdi, &med)) {
-		if (med.media_present)
-			return CDS_DISC_OK;
-		else if (med.door_open)
-			return CDS_TRAY_OPEN;
-		else
-			return CDS_NO_DISC;
+		curspeed = be16_to_cpu(curspeed);
+		maxspeed = be16_to_cpu(maxspeed);
 	}
 
-	if (sense.sense_key == NOT_READY && sense.asc == 0x04 && sense.ascq == 0x04)
-		return CDS_DISC_OK;
-
-	/*
-	 * If not using Mt Fuji extended media tray reports,
-	 * just return TRAY_OPEN since ATAPI doesn't provide
-	 * any other way to detect this...
-	 */
-	if (sense.sense_key == NOT_READY) {
-		if (sense.asc == 0x3a && sense.ascq == 1)
-			return CDS_NO_DISC;
-		else
-			return CDS_TRAY_OPEN;
-	}
-	return CDS_DRIVE_NOT_READY;
+	cd->current_speed = (curspeed + (176/2)) / 176;
+	cd->max_speed = (maxspeed + (176/2)) / 176;
 }
 
-static
-int ide_cdrom_get_last_session (struct cdrom_device_info *cdi,
-				struct cdrom_multisession *ms_info)
-{
-	struct atapi_toc *toc;
-	ide_drive_t *drive = cdi->handle;
-	struct cdrom_info *info = drive->driver_data;
-	struct request_sense sense;
-	int ret;
+#define IDE_CD_CAPABILITIES \
+	(CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK | CDC_SELECT_SPEED | \
+	 CDC_SELECT_DISC | CDC_MULTI_SESSION | CDC_MCN | CDC_MEDIA_CHANGED | \
+	 CDC_PLAY_AUDIO | CDC_RESET | CDC_DRIVE_STATUS | CDC_CD_R | \
+	 CDC_CD_RW | CDC_DVD | CDC_DVD_R | CDC_DVD_RAM | CDC_GENERIC_PACKET | \
+	 CDC_MO_DRIVE | CDC_MRW | CDC_MRW_W | CDC_RAM)
 
-	if (!CDROM_STATE_FLAGS(drive)->toc_valid || info->toc == NULL)
-		if ((ret = cdrom_read_toc(drive, &sense)))
-			return ret;
-
-	toc = info->toc;
-	ms_info->addr.lba = toc->last_session_lba;
-	ms_info->xa_flag = toc->xa_flag;
-
-	return 0;
-}
-
-static
-int ide_cdrom_get_mcn (struct cdrom_device_info *cdi,
-		       struct cdrom_mcn *mcn_info)
-{
-	int stat;
-	char mcnbuf[24];
-	ide_drive_t *drive = cdi->handle;
-
-/* get MCN */
-	if ((stat = cdrom_read_subchannel(drive, 2, mcnbuf, sizeof (mcnbuf), NULL)))
-		return stat;
-
-	memcpy (mcn_info->medium_catalog_number, mcnbuf+9,
-		sizeof (mcn_info->medium_catalog_number)-1);
-	mcn_info->medium_catalog_number[sizeof (mcn_info->medium_catalog_number)-1]
-		= '\0';
-
-	return 0;
-}
-
-
-
-/****************************************************************************
- * Other driver requests (open, close, check media change).
- */
-
-static
-int ide_cdrom_check_media_change_real (struct cdrom_device_info *cdi,
-				       int slot_nr)
-{
-	ide_drive_t *drive = cdi->handle;
-	int retval;
-	
-	if (slot_nr == CDSL_CURRENT) {
-		(void) cdrom_check_status(drive, NULL);
-		retval = CDROM_STATE_FLAGS(drive)->media_changed;
-		CDROM_STATE_FLAGS(drive)->media_changed = 0;
-		return retval;
-	} else {
-		return -EINVAL;
-	}
-}
-
-
-static
-int ide_cdrom_open_real (struct cdrom_device_info *cdi, int purpose)
-{
-	return 0;
-}
-
-/*
- * Close down the device.  Invalidate all cached blocks.
- */
-
-static
-void ide_cdrom_release_real (struct cdrom_device_info *cdi)
-{
-	ide_drive_t *drive = cdi->handle;
-
-	if (!cdi->use_count)
-		CDROM_STATE_FLAGS(drive)->toc_valid = 0;
-}
-
-
-
-/****************************************************************************
- * Device initialization.
- */
 static struct cdrom_device_ops ide_cdrom_dops = {
 	.open			= ide_cdrom_open_real,
 	.release		= ide_cdrom_release_real,
@@ -2885,14 +1675,7 @@
 	.get_mcn		= ide_cdrom_get_mcn,
 	.reset			= ide_cdrom_reset,
 	.audio_ioctl		= ide_cdrom_audio_ioctl,
-	.capability		= CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK |
-				CDC_SELECT_SPEED | CDC_SELECT_DISC |
-				CDC_MULTI_SESSION | CDC_MCN |
-				CDC_MEDIA_CHANGED | CDC_PLAY_AUDIO | CDC_RESET |
-				CDC_DRIVE_STATUS | CDC_CD_R |
-				CDC_CD_RW | CDC_DVD | CDC_DVD_R| CDC_DVD_RAM |
-				CDC_GENERIC_PACKET | CDC_MO_DRIVE | CDC_MRW |
-				CDC_MRW_W | CDC_RAM,
+	.capability		= IDE_CD_CAPABILITIES,
 	.generic_packet		= ide_cdrom_packet,
 };
 
@@ -2902,35 +1685,12 @@
 	struct cdrom_device_info *devinfo = &info->devinfo;
 
 	devinfo->ops = &ide_cdrom_dops;
-	devinfo->mask = 0;
-	devinfo->speed = CDROM_STATE_FLAGS(drive)->current_speed;
+	devinfo->speed = info->current_speed;
 	devinfo->capacity = nslots;
 	devinfo->handle = drive;
 	strcpy(devinfo->name, drive->name);
-	
-	/* set capability mask to match the probe. */
-	if (!CDROM_CONFIG_FLAGS(drive)->cd_r)
-		devinfo->mask |= CDC_CD_R;
-	if (!CDROM_CONFIG_FLAGS(drive)->cd_rw)
-		devinfo->mask |= CDC_CD_RW;
-	if (!CDROM_CONFIG_FLAGS(drive)->dvd)
-		devinfo->mask |= CDC_DVD;
-	if (!CDROM_CONFIG_FLAGS(drive)->dvd_r)
-		devinfo->mask |= CDC_DVD_R;
-	if (!CDROM_CONFIG_FLAGS(drive)->dvd_ram)
-		devinfo->mask |= CDC_DVD_RAM;
-	if (!CDROM_CONFIG_FLAGS(drive)->is_changer)
-		devinfo->mask |= CDC_SELECT_DISC;
-	if (!CDROM_CONFIG_FLAGS(drive)->audio_play)
-		devinfo->mask |= CDC_PLAY_AUDIO;
-	if (!CDROM_CONFIG_FLAGS(drive)->close_tray)
-		devinfo->mask |= CDC_CLOSE_TRAY;
-	if (!CDROM_CONFIG_FLAGS(drive)->mo_drive)
-		devinfo->mask |= CDC_MO_DRIVE;
-	if (!CDROM_CONFIG_FLAGS(drive)->ram)
-		devinfo->mask |= CDC_RAM;
 
-	if (CDROM_CONFIG_FLAGS(drive)->no_speed_select)
+	if (info->cd_flags & IDE_CD_FLAG_NO_SPEED_SELECT)
 		devinfo->mask |= CDC_SELECT_SPEED;
 
 	devinfo->disk = info->disk;
@@ -2940,22 +1700,25 @@
 static
 int ide_cdrom_probe_capabilities (ide_drive_t *drive)
 {
-	struct cdrom_info *info = drive->driver_data;
-	struct cdrom_device_info *cdi = &info->devinfo;
-	struct atapi_capabilities_page cap;
+	struct cdrom_info *cd = drive->driver_data;
+	struct cdrom_device_info *cdi = &cd->devinfo;
+	u8 buf[ATAPI_CAPABILITIES_PAGE_SIZE];
+	mechtype_t mechtype;
 	int nslots = 1;
 
+	cdi->mask = (CDC_CD_R | CDC_CD_RW | CDC_DVD | CDC_DVD_R |
+		     CDC_DVD_RAM | CDC_SELECT_DISC | CDC_PLAY_AUDIO |
+		     CDC_MO_DRIVE | CDC_RAM);
+
 	if (drive->media == ide_optical) {
-		CDROM_CONFIG_FLAGS(drive)->mo_drive = 1;
-		CDROM_CONFIG_FLAGS(drive)->ram = 1;
+		cdi->mask &= ~(CDC_MO_DRIVE | CDC_RAM);
 		printk(KERN_ERR "%s: ATAPI magneto-optical drive\n", drive->name);
 		return nslots;
 	}
 
-	if (CDROM_CONFIG_FLAGS(drive)->nec260 ||
-	    !strcmp(drive->id->model,"STINGRAY 8422 IDE 8X CD-ROM 7-27-95")) {
-		CDROM_CONFIG_FLAGS(drive)->no_eject = 0;
-		CDROM_CONFIG_FLAGS(drive)->audio_play = 1;
+	if (cd->cd_flags & IDE_CD_FLAG_PRE_ATAPI12) {
+		cd->cd_flags &= ~IDE_CD_FLAG_NO_EJECT;
+		cdi->mask &= ~CDC_PLAY_AUDIO;
 		return nslots;
 	}
 
@@ -2969,83 +1732,66 @@
 	cdi->handle = drive;
 	cdi->ops = &ide_cdrom_dops;
 
-	if (ide_cdrom_get_capabilities(drive, &cap))
+	if (ide_cdrom_get_capabilities(drive, buf))
 		return 0;
 
-	if (cap.lock == 0)
-		CDROM_CONFIG_FLAGS(drive)->no_doorlock = 1;
-	if (cap.eject)
-		CDROM_CONFIG_FLAGS(drive)->no_eject = 0;
-	if (cap.cd_r_write)
-		CDROM_CONFIG_FLAGS(drive)->cd_r = 1;
-	if (cap.cd_rw_write) {
-		CDROM_CONFIG_FLAGS(drive)->cd_rw = 1;
-		CDROM_CONFIG_FLAGS(drive)->ram = 1;
-	}
-	if (cap.test_write)
-		CDROM_CONFIG_FLAGS(drive)->test_write = 1;
-	if (cap.dvd_ram_read || cap.dvd_r_read || cap.dvd_rom)
-		CDROM_CONFIG_FLAGS(drive)->dvd = 1;
-	if (cap.dvd_ram_write) {
-		CDROM_CONFIG_FLAGS(drive)->dvd_ram = 1;
-		CDROM_CONFIG_FLAGS(drive)->ram = 1;
-	}
-	if (cap.dvd_r_write)
-		CDROM_CONFIG_FLAGS(drive)->dvd_r = 1;
-	if (cap.audio_play)
-		CDROM_CONFIG_FLAGS(drive)->audio_play = 1;
-	if (cap.mechtype == mechtype_caddy || cap.mechtype == mechtype_popup)
-		CDROM_CONFIG_FLAGS(drive)->close_tray = 0;
+	if ((buf[8 + 6] & 0x01) == 0)
+		cd->cd_flags |= IDE_CD_FLAG_NO_DOORLOCK;
+	if (buf[8 + 6] & 0x08)
+		cd->cd_flags &= ~IDE_CD_FLAG_NO_EJECT;
+	if (buf[8 + 3] & 0x01)
+		cdi->mask &= ~CDC_CD_R;
+	if (buf[8 + 3] & 0x02)
+		cdi->mask &= ~(CDC_CD_RW | CDC_RAM);
+	if (buf[8 + 2] & 0x38)
+		cdi->mask &= ~CDC_DVD;
+	if (buf[8 + 3] & 0x20)
+		cdi->mask &= ~(CDC_DVD_RAM | CDC_RAM);
+	if (buf[8 + 3] & 0x10)
+		cdi->mask &= ~CDC_DVD_R;
+	if ((buf[8 + 4] & 0x01) || (cd->cd_flags & IDE_CD_FLAG_PLAY_AUDIO_OK))
+		cdi->mask &= ~CDC_PLAY_AUDIO;
 
-	/* Some drives used by Apple don't advertise audio play
-	 * but they do support reading TOC & audio datas
-	 */
-	if (strcmp(drive->id->model, "MATSHITADVD-ROM SR-8187") == 0 ||
-	    strcmp(drive->id->model, "MATSHITADVD-ROM SR-8186") == 0 ||
-	    strcmp(drive->id->model, "MATSHITADVD-ROM SR-8176") == 0 ||
-	    strcmp(drive->id->model, "MATSHITADVD-ROM SR-8174") == 0)
-		CDROM_CONFIG_FLAGS(drive)->audio_play = 1;
+	mechtype = buf[8 + 6] >> 5;
+	if (mechtype == mechtype_caddy || mechtype == mechtype_popup)
+		cdi->mask |= CDC_CLOSE_TRAY;
 
-#if ! STANDARD_ATAPI
 	if (cdi->sanyo_slot > 0) {
-		CDROM_CONFIG_FLAGS(drive)->is_changer = 1;
+		cdi->mask &= ~CDC_SELECT_DISC;
 		nslots = 3;
+	} else if (mechtype == mechtype_individual_changer ||
+		   mechtype == mechtype_cartridge_changer) {
+		nslots = cdrom_number_of_slots(cdi);
+		if (nslots > 1)
+			cdi->mask &= ~CDC_SELECT_DISC;
 	}
 
-	else
-#endif /* not STANDARD_ATAPI */
-	if (cap.mechtype == mechtype_individual_changer ||
-	    cap.mechtype == mechtype_cartridge_changer) {
-		if ((nslots = cdrom_number_of_slots(cdi)) > 1) {
-			CDROM_CONFIG_FLAGS(drive)->is_changer = 1;
-			CDROM_CONFIG_FLAGS(drive)->supp_disc_present = 1;
-		}
-	}
+	ide_cdrom_update_speed(drive, buf);
 
-	ide_cdrom_update_speed(drive, &cap);
-	/* don't print speed if the drive reported 0.
-	 */
 	printk(KERN_INFO "%s: ATAPI", drive->name);
-	if (CDROM_CONFIG_FLAGS(drive)->max_speed)
-		printk(" %dX", CDROM_CONFIG_FLAGS(drive)->max_speed);
-	printk(" %s", CDROM_CONFIG_FLAGS(drive)->dvd ? "DVD-ROM" : "CD-ROM");
 
-	if (CDROM_CONFIG_FLAGS(drive)->dvd_r|CDROM_CONFIG_FLAGS(drive)->dvd_ram)
-        	printk(" DVD%s%s", 
-        	(CDROM_CONFIG_FLAGS(drive)->dvd_r)? "-R" : "", 
-        	(CDROM_CONFIG_FLAGS(drive)->dvd_ram)? "-RAM" : "");
+	/* don't print speed if the drive reported 0 */
+	if (cd->max_speed)
+		printk(KERN_CONT " %dX", cd->max_speed);
 
-        if (CDROM_CONFIG_FLAGS(drive)->cd_r|CDROM_CONFIG_FLAGS(drive)->cd_rw) 
-        	printk(" CD%s%s", 
-        	(CDROM_CONFIG_FLAGS(drive)->cd_r)? "-R" : "", 
-        	(CDROM_CONFIG_FLAGS(drive)->cd_rw)? "/RW" : "");
+	printk(KERN_CONT " %s", (cdi->mask & CDC_DVD) ? "CD-ROM" : "DVD-ROM");
 
-        if (CDROM_CONFIG_FLAGS(drive)->is_changer) 
-        	printk(" changer w/%d slots", nslots);
-        else 	
-        	printk(" drive");
+	if ((cdi->mask & CDC_DVD_R) == 0 || (cdi->mask & CDC_DVD_RAM) == 0)
+		printk(KERN_CONT " DVD%s%s",
+				 (cdi->mask & CDC_DVD_R) ? "" : "-R",
+				 (cdi->mask & CDC_DVD_RAM) ? "" : "-RAM");
 
-	printk(KERN_CONT ", %dkB Cache\n", be16_to_cpu(cap.buffer_size));
+	if ((cdi->mask & CDC_CD_R) == 0 || (cdi->mask & CDC_CD_RW) == 0)
+		printk(KERN_CONT " CD%s%s",
+				 (cdi->mask & CDC_CD_R) ? "" : "-R",
+				 (cdi->mask & CDC_CD_RW) ? "" : "/RW");
+
+	if ((cdi->mask & CDC_SELECT_DISC) == 0)
+		printk(KERN_CONT " changer w/%d slots", nslots);
+	else
+		printk(KERN_CONT " drive");
+
+	printk(KERN_CONT ", %dkB Cache\n", be16_to_cpu(*(u16 *)&buf[8 + 12]));
 
 	return nslots;
 }
@@ -3138,11 +1884,74 @@
 	return 0;
 }
 
+struct cd_list_entry {
+	const char	*id_model;
+	const char	*id_firmware;
+	unsigned int	cd_flags;
+};
+
+static const struct cd_list_entry ide_cd_quirks_list[] = {
+	/* Limit transfer size per interrupt. */
+	{ "SAMSUNG CD-ROM SCR-2430", NULL,   IDE_CD_FLAG_LIMIT_NFRAMES	    },
+	{ "SAMSUNG CD-ROM SCR-2432", NULL,   IDE_CD_FLAG_LIMIT_NFRAMES	    },
+	/* SCR-3231 doesn't support the SET_CD_SPEED command. */
+	{ "SAMSUNG CD-ROM SCR-3231", NULL,   IDE_CD_FLAG_NO_SPEED_SELECT    },
+	/* Old NEC260 (not R) was released before ATAPI 1.2 spec. */
+	{ "NEC CD-ROM DRIVE:260",    "1.01", IDE_CD_FLAG_TOCADDR_AS_BCD |
+					     IDE_CD_FLAG_PRE_ATAPI12,	    },
+	/* Vertos 300, some versions of this drive like to talk BCD. */
+	{ "V003S0DS",		     NULL,   IDE_CD_FLAG_VERTOS_300_SSD,    },
+	/* Vertos 600 ESD. */
+	{ "V006E0DS",		     NULL,   IDE_CD_FLAG_VERTOS_600_ESD,    },
+	/*
+	 * Sanyo 3 CD changer uses a non-standard command for CD changing
+	 * (by default standard ATAPI support for CD changers is used).
+	 */
+	{ "CD-ROM CDR-C3 G",	     NULL,   IDE_CD_FLAG_SANYO_3CD	    },
+	{ "CD-ROM CDR-C3G",	     NULL,   IDE_CD_FLAG_SANYO_3CD	    },
+	{ "CD-ROM CDR_C36",	     NULL,   IDE_CD_FLAG_SANYO_3CD	    },
+	/* Stingray 8X CD-ROM. */
+	{ "STINGRAY 8422 IDE 8X CD-ROM 7-27-95", NULL, IDE_CD_FLAG_PRE_ATAPI12},
+	/*
+	 * ACER 50X CD-ROM and WPI 32X CD-ROM require the full spec length
+	 * mode sense page capabilities size, but older drives break.
+	 */
+	{ "ATAPI CD ROM DRIVE 50X MAX",	NULL,	IDE_CD_FLAG_FULL_CAPS_PAGE  },
+	{ "WPI CDS-32X",		NULL,	IDE_CD_FLAG_FULL_CAPS_PAGE  },
+	/* ACER/AOpen 24X CD-ROM has the speed fields byte-swapped. */
+	{ "",			     "241N", IDE_CD_FLAG_LE_SPEED_FIELDS    },
+	/*
+	 * Some drives used by Apple don't advertise audio play
+	 * but they do support reading TOC & audio datas.
+	 */
+	{ "MATSHITADVD-ROM SR-8187", NULL,   IDE_CD_FLAG_PLAY_AUDIO_OK	    },
+	{ "MATSHITADVD-ROM SR-8186", NULL,   IDE_CD_FLAG_PLAY_AUDIO_OK	    },
+	{ "MATSHITADVD-ROM SR-8176", NULL,   IDE_CD_FLAG_PLAY_AUDIO_OK	    },
+	{ "MATSHITADVD-ROM SR-8174", NULL,   IDE_CD_FLAG_PLAY_AUDIO_OK	    },
+	{ NULL, NULL, 0 }
+};
+
+static unsigned int ide_cd_flags(struct hd_driveid *id)
+{
+	const struct cd_list_entry *cle = ide_cd_quirks_list;
+
+	while (cle->id_model) {
+		if (strcmp(cle->id_model, id->model) == 0 &&
+		    (cle->id_firmware == NULL ||
+		     strstr(id->fw_rev, cle->id_firmware)))
+			return cle->cd_flags;
+		cle++;
+	}
+
+	return 0;
+}
+
 static
 int ide_cdrom_setup (ide_drive_t *drive)
 {
-	struct cdrom_info *info = drive->driver_data;
-	struct cdrom_device_info *cdi = &info->devinfo;
+	struct cdrom_info *cd = drive->driver_data;
+	struct cdrom_device_info *cdi = &cd->devinfo;
+	struct hd_driveid *id = drive->id;
 	int nslots;
 
 	blk_queue_prep_rq(drive->queue, ide_cdrom_prep_fn);
@@ -3153,101 +1962,21 @@
 
 	drive->special.all	= 0;
 
-	CDROM_STATE_FLAGS(drive)->media_changed = 1;
-	CDROM_STATE_FLAGS(drive)->toc_valid     = 0;
-	CDROM_STATE_FLAGS(drive)->door_locked   = 0;
+	cd->cd_flags = IDE_CD_FLAG_MEDIA_CHANGED | IDE_CD_FLAG_NO_EJECT |
+		       ide_cd_flags(id);
 
-#if NO_DOOR_LOCKING
-	CDROM_CONFIG_FLAGS(drive)->no_doorlock = 1;
-#else
-	CDROM_CONFIG_FLAGS(drive)->no_doorlock = 0;
-#endif
+	if ((id->config & 0x0060) == 0x20)
+		cd->cd_flags |= IDE_CD_FLAG_DRQ_INTERRUPT;
 
-	CDROM_CONFIG_FLAGS(drive)->drq_interrupt = ((drive->id->config & 0x0060) == 0x20);
-	CDROM_CONFIG_FLAGS(drive)->is_changer = 0;
-	CDROM_CONFIG_FLAGS(drive)->cd_r = 0;
-	CDROM_CONFIG_FLAGS(drive)->cd_rw = 0;
-	CDROM_CONFIG_FLAGS(drive)->test_write = 0;
-	CDROM_CONFIG_FLAGS(drive)->dvd = 0;
-	CDROM_CONFIG_FLAGS(drive)->dvd_r = 0;
-	CDROM_CONFIG_FLAGS(drive)->dvd_ram = 0;
-	CDROM_CONFIG_FLAGS(drive)->no_eject = 1;
-	CDROM_CONFIG_FLAGS(drive)->supp_disc_present = 0;
-	CDROM_CONFIG_FLAGS(drive)->audio_play = 0;
-	CDROM_CONFIG_FLAGS(drive)->close_tray = 1;
-	
-	/* limit transfer size per interrupt. */
-	CDROM_CONFIG_FLAGS(drive)->limit_nframes = 0;
-	/* a testament to the nice quality of Samsung drives... */
-	if (!strcmp(drive->id->model, "SAMSUNG CD-ROM SCR-2430"))
-		CDROM_CONFIG_FLAGS(drive)->limit_nframes = 1;
-	else if (!strcmp(drive->id->model, "SAMSUNG CD-ROM SCR-2432"))
-		CDROM_CONFIG_FLAGS(drive)->limit_nframes = 1;
-	/* the 3231 model does not support the SET_CD_SPEED command */
-	else if (!strcmp(drive->id->model, "SAMSUNG CD-ROM SCR-3231"))
-		CDROM_CONFIG_FLAGS(drive)->no_speed_select = 1;
-
-#if ! STANDARD_ATAPI
-	/* by default Sanyo 3 CD changer support is turned off and
-           ATAPI Rev 2.2+ standard support for CD changers is used */
-	cdi->sanyo_slot = 0;
-
-	CDROM_CONFIG_FLAGS(drive)->nec260 = 0;
-	CDROM_CONFIG_FLAGS(drive)->toctracks_as_bcd = 0;
-	CDROM_CONFIG_FLAGS(drive)->tocaddr_as_bcd = 0;
-	CDROM_CONFIG_FLAGS(drive)->playmsf_as_bcd = 0;
-	CDROM_CONFIG_FLAGS(drive)->subchan_as_bcd = 0;
-
-	if (strcmp (drive->id->model, "V003S0DS") == 0 &&
-	    drive->id->fw_rev[4] == '1' &&
-	    drive->id->fw_rev[6] <= '2') {
-		/* Vertos 300.
-		   Some versions of this drive like to talk BCD. */
-		CDROM_CONFIG_FLAGS(drive)->toctracks_as_bcd = 1;
-		CDROM_CONFIG_FLAGS(drive)->tocaddr_as_bcd = 1;
-		CDROM_CONFIG_FLAGS(drive)->playmsf_as_bcd = 1;
-		CDROM_CONFIG_FLAGS(drive)->subchan_as_bcd = 1;
-	}
-
-	else if (strcmp (drive->id->model, "V006E0DS") == 0 &&
-	    drive->id->fw_rev[4] == '1' &&
-	    drive->id->fw_rev[6] <= '2') {
-		/* Vertos 600 ESD. */
-		CDROM_CONFIG_FLAGS(drive)->toctracks_as_bcd = 1;
-	}
-	else if (strcmp(drive->id->model, "NEC CD-ROM DRIVE:260") == 0 &&
-		 strncmp(drive->id->fw_rev, "1.01", 4) == 0) { /* FIXME */
-		/* Old NEC260 (not R).
-		   This drive was released before the 1.2 version
-		   of the spec. */
-		CDROM_CONFIG_FLAGS(drive)->tocaddr_as_bcd = 1;
-		CDROM_CONFIG_FLAGS(drive)->playmsf_as_bcd = 1;
-		CDROM_CONFIG_FLAGS(drive)->subchan_as_bcd = 1;
-		CDROM_CONFIG_FLAGS(drive)->nec260         = 1;
-	}
-	else if (strcmp(drive->id->model, "WEARNES CDD-120") == 0 &&
-		 strncmp(drive->id->fw_rev, "A1.1", 4) == 0) { /* FIXME */
-		/* Wearnes */
-		CDROM_CONFIG_FLAGS(drive)->playmsf_as_bcd = 1;
-		CDROM_CONFIG_FLAGS(drive)->subchan_as_bcd = 1;
-	}
-        /* Sanyo 3 CD changer uses a non-standard command
-           for CD changing */
-        else if ((strcmp(drive->id->model, "CD-ROM CDR-C3 G") == 0) ||
-                 (strcmp(drive->id->model, "CD-ROM CDR-C3G") == 0) ||
-                 (strcmp(drive->id->model, "CD-ROM CDR_C36") == 0)) {
-                 /* uses CD in slot 0 when value is set to 3 */
-                 cdi->sanyo_slot = 3;
-        }
-#endif /* not STANDARD_ATAPI */
-
-	info->toc		= NULL;
-	info->buffer		= NULL;
-	info->sector_buffered	= 0;
-	info->nsectors_buffered	= 0;
-	info->changer_info      = NULL;
-	info->last_block	= 0;
-	info->start_seek	= 0;
+	if ((cd->cd_flags & IDE_CD_FLAG_VERTOS_300_SSD) &&
+	    id->fw_rev[4] == '1' && id->fw_rev[6] <= '2')
+		cd->cd_flags |= (IDE_CD_FLAG_TOCTRACKS_AS_BCD |
+				 IDE_CD_FLAG_TOCADDR_AS_BCD);
+	else if ((cd->cd_flags & IDE_CD_FLAG_VERTOS_600_ESD) &&
+		 id->fw_rev[4] == '1' && id->fw_rev[6] <= '2')
+		cd->cd_flags |= IDE_CD_FLAG_TOCTRACKS_AS_BCD;
+	else if (cd->cd_flags & IDE_CD_FLAG_SANYO_3CD)
+		cdi->sanyo_slot = 3;	/* 3 => use CD in slot 0 */
 
 	nslots = ide_cdrom_probe_capabilities (drive);
 
@@ -3262,7 +1991,7 @@
 
 	if (ide_cdrom_register(drive, nslots)) {
 		printk (KERN_ERR "%s: ide_cdrom_setup failed to register device with the cdrom driver.\n", drive->name);
-		info->devinfo.handle = NULL;
+		cd->devinfo.handle = NULL;
 		return 1;
 	}
 	ide_cdrom_add_settings(drive);
@@ -3302,7 +2031,6 @@
 
 	kfree(info->buffer);
 	kfree(info->toc);
-	kfree(info->changer_info);
 	if (devinfo->handle == drive && unregister_cdrom(devinfo))
 		printk(KERN_ERR "%s: %s failed to unregister device from the cdrom "
 				"driver.\n", __FUNCTION__, drive->name);
@@ -3458,7 +2186,9 @@
 {
 	struct cdrom_info *info = ide_cd_g(disk);
 	struct request_sense sense;
-	cdrom_read_toc(info->drive, &sense);
+
+	ide_cd_read_toc(info->drive, &sense);
+
 	return  0;
 }
 
@@ -3533,7 +2263,7 @@
 		goto failed;
 	}
 
-	cdrom_read_toc(drive, &sense);
+	ide_cd_read_toc(drive, &sense);
 	g->fops = &idecd_ops;
 	g->flags |= GENHD_FL_REMOVABLE;
 	add_disk(g);
@@ -3556,6 +2286,7 @@
 }
 
 MODULE_ALIAS("ide:*m-cdrom*");
+MODULE_ALIAS("ide-cd");
 module_init(ide_cdrom_init);
 module_exit(ide_cdrom_exit);
 MODULE_LICENSE("GPL");
diff --git a/drivers/ide/ide-cd.h b/drivers/ide/ide-cd.h
index 1b302fe..22e3751 100644
--- a/drivers/ide/ide-cd.h
+++ b/drivers/ide/ide-cd.h
@@ -1,6 +1,4 @@
 /*
- *  linux/drivers/ide/ide_cd.h
- *
  *  Copyright (C) 1996-98  Erik Andersen
  *  Copyright (C) 1998-2000 Jens Axboe
  */
@@ -10,31 +8,6 @@
 #include <linux/cdrom.h>
 #include <asm/byteorder.h>
 
-/* Turn this on to have the driver print out the meanings of the
-   ATAPI error codes.  This will use up additional kernel-space
-   memory, though. */
-
-#ifndef VERBOSE_IDE_CD_ERRORS
-#define VERBOSE_IDE_CD_ERRORS 1
-#endif
-
-
-/* Turning this on will remove code to work around various nonstandard
-   ATAPI implementations.  If you know your drive follows the standard,
-   this will give you a slightly smaller kernel. */
-
-#ifndef STANDARD_ATAPI
-#define STANDARD_ATAPI 0
-#endif
-
-
-/* Turning this on will disable the door-locking functionality.
-   This is apparently needed for supermount. */
-
-#ifndef NO_DOOR_LOCKING
-#define NO_DOOR_LOCKING 0
-#endif
-
 /*
  * typical timeout for packet command
  */
@@ -49,67 +22,46 @@
 #endif
 #define SECTORS_PER_FRAME	(CD_FRAMESIZE >> SECTOR_BITS)
 #define SECTOR_BUFFER_SIZE	(CD_FRAMESIZE * 32)
-#define SECTORS_BUFFER		(SECTOR_BUFFER_SIZE >> SECTOR_BITS)
-#define SECTORS_MAX		(131072 >> SECTOR_BITS)
 
-#define BLOCKS_PER_FRAME	(CD_FRAMESIZE / BLOCK_SIZE)
+/* Capabilities Page size including 8 bytes of Mode Page Header */
+#define ATAPI_CAPABILITIES_PAGE_SIZE		(8 + 20)
+#define ATAPI_CAPABILITIES_PAGE_PAD_SIZE	4
 
-/* special command codes for strategy routine. */
-#define PACKET_COMMAND        4315
-#define REQUEST_SENSE_COMMAND 4316
-#define RESET_DRIVE_COMMAND   4317
-
-
-/* Configuration flags.  These describe the capabilities of the drive.
-   They generally do not change after initialization, unless we learn
-   more about the drive from stuff failing. */
-struct ide_cd_config_flags {
-	__u8 drq_interrupt	: 1; /* Device sends an interrupt when ready
-					for a packet command. */
-	__u8 no_doorlock	: 1; /* Drive cannot lock the door. */
-	__u8 no_eject		: 1; /* Drive cannot eject the disc. */
-	__u8 nec260		: 1; /* Drive is a pre-1.2 NEC 260 drive. */
-	__u8 playmsf_as_bcd	: 1; /* PLAYMSF command takes BCD args. */
-	__u8 tocaddr_as_bcd	: 1; /* TOC addresses are in BCD. */
-	__u8 toctracks_as_bcd	: 1; /* TOC track numbers are in BCD. */
-	__u8 subchan_as_bcd	: 1; /* Subchannel info is in BCD. */
-	__u8 is_changer		: 1; /* Drive is a changer. */
-	__u8 cd_r		: 1; /* Drive can write to CD-R media . */
-	__u8 cd_rw		: 1; /* Drive can write to CD-R/W media . */
-	__u8 dvd		: 1; /* Drive is a DVD-ROM */
-	__u8 dvd_r		: 1; /* Drive can write DVD-R */
-	__u8 dvd_ram		: 1; /* Drive can write DVD-RAM */
-	__u8 ram		: 1; /* generic WRITE (dvd-ram/mrw) */
-	__u8 test_write		: 1; /* Drive can fake writes */
-	__u8 supp_disc_present	: 1; /* Changer can report exact contents
-					of slots. */
-	__u8 limit_nframes	: 1; /* Drive does not provide data in
-					multiples of SECTOR_SIZE when more
-					than one interrupt is needed. */
-	__u8 seeking		: 1; /* Seeking in progress */
-	__u8 audio_play		: 1; /* can do audio related commands */
-	__u8 close_tray		: 1; /* can close the tray */
-	__u8 writing		: 1; /* pseudo write in progress */
-	__u8 mo_drive		: 1; /* drive is an MO device */
-	__u8 no_speed_select	: 1; /* SET_CD_SPEED command is unsupported. */
-	__u8 reserved		: 1;
-	byte max_speed;		     /* Max speed of the drive */
+enum {
+	/* Device sends an interrupt when ready for a packet command. */
+	IDE_CD_FLAG_DRQ_INTERRUPT	= (1 << 0),
+	/* Drive cannot lock the door. */
+	IDE_CD_FLAG_NO_DOORLOCK		= (1 << 1),
+	/* Drive cannot eject the disc. */
+	IDE_CD_FLAG_NO_EJECT		= (1 << 2),
+	/* Drive is a pre ATAPI 1.2 drive. */
+	IDE_CD_FLAG_PRE_ATAPI12		= (1 << 3),
+	/* TOC addresses are in BCD. */
+	IDE_CD_FLAG_TOCADDR_AS_BCD	= (1 << 4),
+	/* TOC track numbers are in BCD. */
+	IDE_CD_FLAG_TOCTRACKS_AS_BCD	= (1 << 5),
+	/*
+	 * Drive does not provide data in multiples of SECTOR_SIZE
+	 * when more than one interrupt is needed.
+	 */
+	IDE_CD_FLAG_LIMIT_NFRAMES	= (1 << 6),
+	/* Seeking in progress. */
+	IDE_CD_FLAG_SEEKING		= (1 << 7),
+	/* Driver has noticed a media change. */
+	IDE_CD_FLAG_MEDIA_CHANGED	= (1 << 8),
+	/* Saved TOC information is current. */
+	IDE_CD_FLAG_TOC_VALID		= (1 << 9),
+	/* We think that the drive door is locked. */
+	IDE_CD_FLAG_DOOR_LOCKED		= (1 << 10),
+	/* SET_CD_SPEED command is unsupported. */
+	IDE_CD_FLAG_NO_SPEED_SELECT	= (1 << 11),
+	IDE_CD_FLAG_VERTOS_300_SSD	= (1 << 12),
+	IDE_CD_FLAG_VERTOS_600_ESD	= (1 << 13),
+	IDE_CD_FLAG_SANYO_3CD		= (1 << 14),
+	IDE_CD_FLAG_FULL_CAPS_PAGE	= (1 << 15),
+	IDE_CD_FLAG_PLAY_AUDIO_OK	= (1 << 16),
+	IDE_CD_FLAG_LE_SPEED_FIELDS	= (1 << 17),
 };
-#define CDROM_CONFIG_FLAGS(drive) (&(((struct cdrom_info *)(drive->driver_data))->config_flags))
-
- 
-/* State flags.  These give information about the current state of the
-   drive, and will change during normal operation. */
-struct ide_cd_state_flags {
-	__u8 media_changed : 1; /* Driver has noticed a media change. */
-	__u8 toc_valid     : 1; /* Saved TOC information is current. */
-	__u8 door_locked   : 1; /* We think that the drive door is locked. */
-	__u8 writing       : 1; /* the drive is currently writing */
-	__u8 reserved      : 4;
-	byte current_speed;	/* Current speed of the drive */
-};
-
-#define CDROM_STATE_FLAGS(drive) (&(((struct cdrom_info *)(drive->driver_data))->state_flags))
 
 /* Structure of a MSF cdrom address. */
 struct atapi_msf {
@@ -155,310 +107,6 @@
 	  /* One extra for the leadout. */
 };
 
-
-/* This structure is annoyingly close to, but not identical with,
-   the cdrom_subchnl structure from cdrom.h. */
-struct atapi_cdrom_subchnl {
- 	u_char  acdsc_reserved;
- 	u_char  acdsc_audiostatus;
- 	u_short acdsc_length;
-	u_char  acdsc_format;
-
-#if defined(__BIG_ENDIAN_BITFIELD)
-	u_char  acdsc_ctrl:     4;
-	u_char  acdsc_adr:      4;
-#elif defined(__LITTLE_ENDIAN_BITFIELD)
-	u_char  acdsc_adr:	4;
-	u_char  acdsc_ctrl:	4;
-#else
-#error "Please fix <asm/byteorder.h>"
-#endif
-	u_char  acdsc_trk;
-	u_char  acdsc_ind;
-	union {
-		struct atapi_msf msf;
-		int	lba;
-	} acdsc_absaddr;
-	union {
-		struct atapi_msf msf;
-		int	lba;
-	} acdsc_reladdr;
-};
-
-
-
-/* This should probably go into cdrom.h along with the other
- * generic stuff now in the Mt. Fuji spec.
- */
-struct atapi_capabilities_page {
-	struct mode_page_header header;
-#if defined(__BIG_ENDIAN_BITFIELD)
-	__u8 parameters_saveable : 1;
-	__u8 reserved1           : 1;
-	__u8 page_code           : 6;
-#elif defined(__LITTLE_ENDIAN_BITFIELD)
-	__u8 page_code           : 6;
-	__u8 reserved1           : 1;
-	__u8 parameters_saveable : 1;
-#else
-#error "Please fix <asm/byteorder.h>"
-#endif
-
-	byte     page_length;
-
-#if defined(__BIG_ENDIAN_BITFIELD)
-	__u8 reserved2           : 2;
-	/* Drive supports reading of DVD-RAM discs */
-	__u8 dvd_ram_read        : 1;
-	/* Drive supports reading of DVD-R discs */
-	__u8 dvd_r_read          : 1;
-	/* Drive supports reading of DVD-ROM discs */
-	__u8 dvd_rom             : 1;
-	/* Drive supports reading CD-R discs with addressing method 2 */
-	__u8 method2             : 1; /* reserved in 1.2 */
-	/* Drive can read from CD-R/W (CD-E) discs (orange book, part III) */
-	__u8 cd_rw_read		 : 1; /* reserved in 1.2 */
-	/* Drive supports read from CD-R discs (orange book, part II) */
-	__u8 cd_r_read           : 1; /* reserved in 1.2 */
-#elif defined(__LITTLE_ENDIAN_BITFIELD)
-	/* Drive supports read from CD-R discs (orange book, part II) */
-	__u8 cd_r_read           : 1; /* reserved in 1.2 */
-	/* Drive can read from CD-R/W (CD-E) discs (orange book, part III) */
-	__u8 cd_rw_read          : 1; /* reserved in 1.2 */
-	/* Drive supports reading CD-R discs with addressing method 2 */
-	__u8 method2             : 1;
-	/* Drive supports reading of DVD-ROM discs */
-	__u8 dvd_rom             : 1;
-	/* Drive supports reading of DVD-R discs */
-	__u8 dvd_r_read          : 1;
-	/* Drive supports reading of DVD-RAM discs */
-	__u8 dvd_ram_read        : 1;
-	__u8 reserved2		 : 2;
-#else
-#error "Please fix <asm/byteorder.h>"
-#endif
-
-#if defined(__BIG_ENDIAN_BITFIELD)
-	__u8 reserved3           : 2;
-	/* Drive can write DVD-RAM discs */
-	__u8 dvd_ram_write       : 1;
-	/* Drive can write DVD-R discs */
-	__u8 dvd_r_write         : 1;
-	__u8 reserved3a          : 1;
-	/* Drive can fake writes */
-	__u8 test_write          : 1;
-	/* Drive can write to CD-R/W (CD-E) discs (orange book, part III) */
-	__u8 cd_rw_write	 : 1; /* reserved in 1.2 */
-	/* Drive supports write to CD-R discs (orange book, part II) */
-	__u8 cd_r_write          : 1; /* reserved in 1.2 */
-#elif defined(__LITTLE_ENDIAN_BITFIELD)
-	/* Drive can write to CD-R discs (orange book, part II) */
-	__u8 cd_r_write          : 1; /* reserved in 1.2 */
-	/* Drive can write to CD-R/W (CD-E) discs (orange book, part III) */
-	__u8 cd_rw_write	 : 1; /* reserved in 1.2 */
-	/* Drive can fake writes */
-	__u8 test_write          : 1;
-	__u8 reserved3a          : 1;
-	/* Drive can write DVD-R discs */
-	__u8 dvd_r_write         : 1;
-	/* Drive can write DVD-RAM discs */
-	__u8 dvd_ram_write       : 1;
-	__u8 reserved3           : 2;
-#else
-#error "Please fix <asm/byteorder.h>"
-#endif
-
-#if defined(__BIG_ENDIAN_BITFIELD)
-	__u8 reserved4           : 1;
-	/* Drive can read multisession discs. */
-	__u8 multisession        : 1;
-	/* Drive can read mode 2, form 2 data. */
-	__u8 mode2_form2         : 1;
-	/* Drive can read mode 2, form 1 (XA) data. */
-	__u8 mode2_form1         : 1;
-	/* Drive supports digital output on port 2. */
-	__u8 digport2            : 1;
-	/* Drive supports digital output on port 1. */
-	__u8 digport1            : 1;
-	/* Drive can deliver a composite audio/video data stream. */
-	__u8 composite           : 1;
-	/* Drive supports audio play operations. */
-	__u8 audio_play          : 1;
-#elif defined(__LITTLE_ENDIAN_BITFIELD)
-	/* Drive supports audio play operations. */
-	__u8 audio_play          : 1;
-	/* Drive can deliver a composite audio/video data stream. */
-	__u8 composite           : 1;
-	/* Drive supports digital output on port 1. */
-	__u8 digport1            : 1;
-	/* Drive supports digital output on port 2. */
-	__u8 digport2            : 1;
-	/* Drive can read mode 2, form 1 (XA) data. */
-	__u8 mode2_form1         : 1;
-	/* Drive can read mode 2, form 2 data. */
-	__u8 mode2_form2         : 1;
-	/* Drive can read multisession discs. */
-	__u8 multisession        : 1;
-	__u8 reserved4           : 1;
-#else
-#error "Please fix <asm/byteorder.h>"
-#endif
-
-#if defined(__BIG_ENDIAN_BITFIELD)
-	__u8 reserved5           : 1;
-	/* Drive can return Media Catalog Number (UPC) info. */
-	__u8 upc                 : 1;
-	/* Drive can return International Standard Recording Code info. */
-	__u8 isrc                : 1;
-	/* Drive supports C2 error pointers. */
-	__u8 c2_pointers         : 1;
-	/* R-W data will be returned deinterleaved and error corrected. */
-	__u8 rw_corr             : 1;
-	/* Subchannel reads can return combined R-W information. */
-	__u8 rw_supported        : 1;
-	/* Drive can continue a read cdda operation from a loss of streaming.*/
-	__u8 cdda_accurate       : 1;
-	/* Drive can read Red Book audio data. */
-	__u8 cdda                : 1;
-#elif defined(__LITTLE_ENDIAN_BITFIELD)
-	/* Drive can read Red Book audio data. */
-	__u8 cdda                : 1;
-	/* Drive can continue a read cdda operation from a loss of streaming.*/
-	__u8 cdda_accurate       : 1;
-	/* Subchannel reads can return combined R-W information. */
-	__u8 rw_supported        : 1;
-	/* R-W data will be returned deinterleaved and error corrected. */
-	__u8 rw_corr             : 1;
-	/* Drive supports C2 error pointers. */
-	__u8 c2_pointers         : 1;
-	/* Drive can return International Standard Recording Code info. */
-	__u8 isrc                : 1;
-	/* Drive can return Media Catalog Number (UPC) info. */
-	__u8 upc                 : 1;
-	__u8 reserved5           : 1;
-#else
-#error "Please fix <asm/byteorder.h>"
-#endif
-
-#if defined(__BIG_ENDIAN_BITFIELD)
-	/* Drive mechanism types. */
-	mechtype_t mechtype	 : 3;
-	__u8 reserved6           : 1;
-	/* Drive can eject a disc or changer cartridge. */
-	__u8 eject               : 1;
-	/* State of prevent/allow jumper. */
-	__u8 prevent_jumper      : 1;
-	/* Present state of door lock. */
-	__u8 lock_state          : 1;
-	/* Drive can lock the door. */
-	__u8 lock                : 1;
-#elif defined(__LITTLE_ENDIAN_BITFIELD)
-
-	/* Drive can lock the door. */
-	__u8 lock                : 1;
-	/* Present state of door lock. */
-	__u8 lock_state          : 1;
-	/* State of prevent/allow jumper. */
-	__u8 prevent_jumper      : 1;
-	/* Drive can eject a disc or changer cartridge. */
-	__u8 eject               : 1;
-	__u8 reserved6           : 1;
-	/* Drive mechanism types. */
-	mechtype_t mechtype	 : 3;
-#else
-#error "Please fix <asm/byteorder.h>"
-#endif
-
-#if defined(__BIG_ENDIAN_BITFIELD)
-	__u8 reserved7           : 4;
-	/* Drive supports software slot selection. */
-	__u8 sss                 : 1;  /* reserved in 1.2 */
-	/* Changer can report exact contents of slots. */
-	__u8 disc_present        : 1;  /* reserved in 1.2 */
-	/* Audio for each channel can be muted independently. */
-	__u8 separate_mute       : 1;
-	/* Audio level for each channel can be controlled independently. */
-	__u8 separate_volume     : 1;
-#elif defined(__LITTLE_ENDIAN_BITFIELD)
-
-	/* Audio level for each channel can be controlled independently. */
-	__u8 separate_volume     : 1;
-	/* Audio for each channel can be muted independently. */
-	__u8 separate_mute       : 1;
-	/* Changer can report exact contents of slots. */
-	__u8 disc_present        : 1;  /* reserved in 1.2 */
-	/* Drive supports software slot selection. */
-	__u8 sss                 : 1;  /* reserved in 1.2 */
-	__u8 reserved7           : 4;
-#else
-#error "Please fix <asm/byteorder.h>"
-#endif
-
-	/* Note: the following four fields are returned in big-endian form. */
-	/* Maximum speed (in kB/s). */
-	unsigned short maxspeed;
-	/* Number of discrete volume levels. */
-	unsigned short n_vol_levels;
-	/* Size of cache in drive, in kB. */
-	unsigned short buffer_size;
-	/* Current speed (in kB/s). */
-	unsigned short curspeed;
-	char pad[4];
-};
-
-
-struct atapi_mechstat_header {
-#if defined(__BIG_ENDIAN_BITFIELD)
-	__u8 fault         : 1;
-	__u8 changer_state : 2;
-	__u8 curslot       : 5;
-#elif defined(__LITTLE_ENDIAN_BITFIELD)
-	__u8 curslot       : 5;
-	__u8 changer_state : 2;
-	__u8 fault         : 1;
-#else
-#error "Please fix <asm/byteorder.h>"
-#endif
-
-#if defined(__BIG_ENDIAN_BITFIELD)
-	__u8 mech_state    : 3;
-	__u8 door_open     : 1;
-	__u8 reserved1     : 4;
-#elif defined(__LITTLE_ENDIAN_BITFIELD)
-	__u8 reserved1     : 4;
-	__u8 door_open     : 1;
-	__u8 mech_state    : 3;
-#else
-#error "Please fix <asm/byteorder.h>"
-#endif
-
-	byte     curlba[3];
-	byte     nslots;
-	__u16	 slot_tablelen;
-};
-
-
-struct atapi_slot {
-#if defined(__BIG_ENDIAN_BITFIELD)
-	__u8 disc_present : 1;
-	__u8 reserved1    : 6;
-	__u8 change       : 1;
-#elif defined(__LITTLE_ENDIAN_BITFIELD)
-	__u8 change       : 1;
-	__u8 reserved1    : 6;
-	__u8 disc_present : 1;
-#else
-#error "Please fix <asm/byteorder.h>"
-#endif
-
-	byte reserved2[3];
-};
-
-struct atapi_changer_info {
-	struct atapi_mechstat_header hdr;
-	struct atapi_slot slots[0];
-};
-
 /* Extra per-device info for cdrom drives. */
 struct cdrom_info {
 	ide_drive_t	*drive;
@@ -483,11 +131,11 @@
 	int dma;
 	unsigned long last_block;
 	unsigned long start_seek;
-	/* Buffer to hold mechanism status and changer slot table. */
-	struct atapi_changer_info *changer_info;
 
-	struct ide_cd_config_flags	config_flags;
-	struct ide_cd_state_flags	state_flags;
+	unsigned int cd_flags;
+
+	u8 max_speed;		/* Max speed of the drive. */
+	u8 current_speed;	/* Current speed of the drive. */
 
         /* Per-device info needed by cdrom.c generic driver. */
         struct cdrom_device_info devinfo;
@@ -495,250 +143,30 @@
 	unsigned long write_timeout;
 };
 
-/****************************************************************************
- * Descriptions of ATAPI error codes.
- */
+/* ide-cd_verbose.c */
+void ide_cd_log_error(const char *, struct request *, struct request_sense *);
 
-/* This stuff should be in cdrom.h, since it is now generic... */
+/* ide-cd.c functions used by ide-cd_ioctl.c */
+void ide_cd_init_rq(ide_drive_t *, struct request *);
+int ide_cd_queue_pc(ide_drive_t *, struct request *);
+int ide_cd_read_toc(ide_drive_t *, struct request_sense *);
+int ide_cdrom_get_capabilities(ide_drive_t *, u8 *);
+void ide_cdrom_update_speed(ide_drive_t *, u8 *);
+int cdrom_check_status(ide_drive_t *, struct request_sense *);
 
-/* ATAPI sense keys (from table 140 of ATAPI 2.6) */
-#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 ABORTED_COMMAND         0x0b
-#define MISCOMPARE              0x0e
-
- 
-
-/* This stuff should be in cdrom.h, since it is now generic... */
-#if VERBOSE_IDE_CD_ERRORS
-
- /* The generic packet command opcodes for CD/DVD Logical Units,
- * From Table 57 of the SFF8090 Ver. 3 (Mt. Fuji) draft standard. */ 
-static const struct {
-	unsigned short packet_command;
-	const char * const text;
-} packet_command_texts[] = {
-	{ GPCMD_TEST_UNIT_READY, "Test Unit Ready" },
-	{ GPCMD_REQUEST_SENSE, "Request Sense" },
-	{ GPCMD_FORMAT_UNIT, "Format Unit" },
-	{ GPCMD_INQUIRY, "Inquiry" },
-	{ GPCMD_START_STOP_UNIT, "Start/Stop Unit" },
-	{ GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL, "Prevent/Allow Medium Removal" },
-	{ GPCMD_READ_FORMAT_CAPACITIES, "Read Format Capacities" },
-	{ GPCMD_READ_CDVD_CAPACITY, "Read Cd/Dvd Capacity" },
-	{ GPCMD_READ_10, "Read 10" },
-	{ GPCMD_WRITE_10, "Write 10" },
-	{ GPCMD_SEEK, "Seek" },
-	{ GPCMD_WRITE_AND_VERIFY_10, "Write and Verify 10" },
-	{ GPCMD_VERIFY_10, "Verify 10" },
-	{ GPCMD_FLUSH_CACHE, "Flush Cache" },
-	{ GPCMD_READ_SUBCHANNEL, "Read Subchannel" },
-	{ GPCMD_READ_TOC_PMA_ATIP, "Read Table of Contents" },
-	{ GPCMD_READ_HEADER, "Read Header" },
-	{ GPCMD_PLAY_AUDIO_10, "Play Audio 10" },
-	{ GPCMD_GET_CONFIGURATION, "Get Configuration" },
-	{ GPCMD_PLAY_AUDIO_MSF, "Play Audio MSF" },
-	{ GPCMD_PLAYAUDIO_TI, "Play Audio TrackIndex" },
-	{ GPCMD_GET_EVENT_STATUS_NOTIFICATION, "Get Event Status Notification" },
-	{ GPCMD_PAUSE_RESUME, "Pause/Resume" },
-	{ GPCMD_STOP_PLAY_SCAN, "Stop Play/Scan" },
-	{ GPCMD_READ_DISC_INFO, "Read Disc Info" },
-	{ GPCMD_READ_TRACK_RZONE_INFO, "Read Track Rzone Info" },
-	{ GPCMD_RESERVE_RZONE_TRACK, "Reserve Rzone Track" },
-	{ GPCMD_SEND_OPC, "Send OPC" },
-	{ GPCMD_MODE_SELECT_10, "Mode Select 10" },
-	{ GPCMD_REPAIR_RZONE_TRACK, "Repair Rzone Track" },
-	{ GPCMD_MODE_SENSE_10, "Mode Sense 10" },
-	{ GPCMD_CLOSE_TRACK, "Close Track" },
-	{ GPCMD_BLANK, "Blank" },
-	{ GPCMD_SEND_EVENT, "Send Event" },
-	{ GPCMD_SEND_KEY, "Send Key" },
-	{ GPCMD_REPORT_KEY, "Report Key" },
-	{ GPCMD_LOAD_UNLOAD, "Load/Unload" },
-	{ GPCMD_SET_READ_AHEAD, "Set Read-ahead" },
-	{ GPCMD_READ_12, "Read 12" },
-	{ GPCMD_GET_PERFORMANCE, "Get Performance" },
-	{ GPCMD_SEND_DVD_STRUCTURE, "Send DVD Structure" },
-	{ GPCMD_READ_DVD_STRUCTURE, "Read DVD Structure" },
-	{ GPCMD_SET_STREAMING, "Set Streaming" },
-	{ GPCMD_READ_CD_MSF, "Read CD MSF" },
-	{ GPCMD_SCAN, "Scan" },
-	{ GPCMD_SET_SPEED, "Set Speed" },
-	{ GPCMD_PLAY_CD, "Play CD" },
-	{ GPCMD_MECHANISM_STATUS, "Mechanism Status" },
-	{ GPCMD_READ_CD, "Read CD" },
-};
-
-
-
-/* From Table 303 of the SFF8090 Ver. 3 (Mt. Fuji) draft standard. */
-static const char * const sense_key_texts[16] = {
-	"No sense data",
-	"Recovered error",
-	"Not ready",
-	"Medium error",
-	"Hardware error",
-	"Illegal request",
-	"Unit attention",
-	"Data protect",
-	"Blank check",
-	"(reserved)",
-	"(reserved)",
-	"Aborted command",
-	"(reserved)",
-	"(reserved)",
-	"Miscompare",
-	"(reserved)",
-};
-
-/* From Table 304 of the SFF8090 Ver. 3 (Mt. Fuji) draft standard. */
-static const struct {
-	unsigned long asc_ascq;
-	const char * const text;
-} sense_data_texts[] = {
-	{ 0x000000, "No additional sense information" },
-	{ 0x000011, "Play operation in progress" },
-	{ 0x000012, "Play operation paused" },
-	{ 0x000013, "Play operation successfully completed" },
-	{ 0x000014, "Play operation stopped due to error" },
-	{ 0x000015, "No current audio status to return" },
-	{ 0x010c0a, "Write error - padding blocks added" },
-	{ 0x011700, "Recovered data with no error correction applied" },
-	{ 0x011701, "Recovered data with retries" },
-	{ 0x011702, "Recovered data with positive head offset" },
-	{ 0x011703, "Recovered data with negative head offset" },
-	{ 0x011704, "Recovered data with retries and/or CIRC applied" },
-	{ 0x011705, "Recovered data using previous sector ID" },
-	{ 0x011800, "Recovered data with error correction applied" },
-	{ 0x011801, "Recovered data with error correction and retries applied"},
-	{ 0x011802, "Recovered data - the data was auto-reallocated" },
-	{ 0x011803, "Recovered data with CIRC" },
-	{ 0x011804, "Recovered data with L-EC" },
-	{ 0x015d00, 
-	    "Failure prediction threshold exceeded - Predicted logical unit failure" },
-	{ 0x015d01, 
-	    "Failure prediction threshold exceeded - Predicted media failure" },
-	{ 0x015dff, "Failure prediction threshold exceeded - False" },
-	{ 0x017301, "Power calibration area almost full" },
-	{ 0x020400, "Logical unit not ready - cause not reportable" },
-	/* Following is misspelled in ATAPI 2.6, _and_ in Mt. Fuji */
-	{ 0x020401,
-	  "Logical unit not ready - in progress [sic] of becoming ready" },
-	{ 0x020402, "Logical unit not ready - initializing command required" },
-	{ 0x020403, "Logical unit not ready - manual intervention required" },
-	{ 0x020404, "Logical unit not ready - format in progress" },
-	{ 0x020407, "Logical unit not ready - operation in progress" },
-	{ 0x020408, "Logical unit not ready - long write in progress" },
-	{ 0x020600, "No reference position found (media may be upside down)" },
-	{ 0x023000, "Incompatible medium installed" },
-	{ 0x023a00, "Medium not present" },
-	{ 0x025300, "Media load or eject failed" },
-	{ 0x025700, "Unable to recover table of contents" },
-	{ 0x030300, "Peripheral device write fault" },
-	{ 0x030301, "No write current" },
-	{ 0x030302, "Excessive write errors" },
-	{ 0x030c00, "Write error" },
-	{ 0x030c01, "Write error - Recovered with auto reallocation" },
-	{ 0x030c02, "Write error - auto reallocation failed" },
-	{ 0x030c03, "Write error - recommend reassignment" },
-	{ 0x030c04, "Compression check miscompare error" },
-	{ 0x030c05, "Data expansion occurred during compress" },
-	{ 0x030c06, "Block not compressible" },
-	{ 0x030c07, "Write error - recovery needed" },
-	{ 0x030c08, "Write error - recovery failed" },
-	{ 0x030c09, "Write error - loss of streaming" },
-	{ 0x031100, "Unrecovered read error" },
-	{ 0x031106, "CIRC unrecovered error" },
-	{ 0x033101, "Format command failed" },
-	{ 0x033200, "No defect spare location available" },
-	{ 0x033201, "Defect list update failure" },
-	{ 0x035100, "Erase failure" },
-	{ 0x037200, "Session fixation error" },
-	{ 0x037201, "Session fixation error writin lead-in" },
-	{ 0x037202, "Session fixation error writin lead-out" },
-	{ 0x037300, "CD control error" },
-	{ 0x037302, "Power calibration area is full" },
-	{ 0x037303, "Power calibration area error" },
-	{ 0x037304, "Program memory area / RMA update failure" },
-	{ 0x037305, "Program memory area / RMA is full" },
-	{ 0x037306, "Program memory area / RMA is (almost) full" },
-
-	{ 0x040200, "No seek complete" },
-	{ 0x040300, "Write fault" },
-	{ 0x040900, "Track following error" },
-	{ 0x040901, "Tracking servo failure" },
-	{ 0x040902, "Focus servo failure" },
-	{ 0x040903, "Spindle servo failure" },
-	{ 0x041500, "Random positioning error" },
-	{ 0x041501, "Mechanical positioning or changer error" },
-	{ 0x041502, "Positioning error detected by read of medium" },
-	{ 0x043c00, "Mechanical positioning or changer error" },
-	{ 0x044000, "Diagnostic failure on component (ASCQ)" },
-	{ 0x044400, "Internal CD/DVD logical unit failure" },
-	{ 0x04b600, "Media load mechanism failed" },
-	{ 0x051a00, "Parameter list length error" },
-	{ 0x052000, "Invalid command operation code" },
-	{ 0x052100, "Logical block address out of range" },
-	{ 0x052102, "Invalid address for write" },
-	{ 0x052400, "Invalid field in command packet" },
-	{ 0x052600, "Invalid field in parameter list" },
-	{ 0x052601, "Parameter not supported" },
-	{ 0x052602, "Parameter value invalid" },
-	{ 0x052700, "Write protected media" },
-	{ 0x052c00, "Command sequence error" },
-	{ 0x052c03, "Current program area is not empty" },
-	{ 0x052c04, "Current program area is empty" },
-	{ 0x053001, "Cannot read medium - unknown format" },
-	{ 0x053002, "Cannot read medium - incompatible format" },
-	{ 0x053900, "Saving parameters not supported" },
-	{ 0x054e00, "Overlapped commands attempted" },
-	{ 0x055302, "Medium removal prevented" },
-	{ 0x055500, "System resource failure" },
-	{ 0x056300, "End of user area encountered on this track" },
-	{ 0x056400, "Illegal mode for this track or incompatible medium" },
-	{ 0x056f00, "Copy protection key exchange failure - Authentication failure" },
-	{ 0x056f01, "Copy protection key exchange failure - Key not present" },
-	{ 0x056f02, "Copy protection key exchange failure - Key not established" },
-	{ 0x056f03, "Read of scrambled sector without authentication" },
-	{ 0x056f04, "Media region code is mismatched to logical unit" },
-	{ 0x056f05,  "Drive region must be permanent / region reset count error" },
-	{ 0x057203, "Session fixation error - incomplete track in session" },
-	{ 0x057204, "Empty or partially written reserved track" },
-	{ 0x057205, "No more RZONE reservations are allowed" },
-	{ 0x05bf00, "Loss of streaming" },
-	{ 0x062800, "Not ready to ready transition, medium may have changed" },
-	{ 0x062900, "Power on, reset or hardware reset occurred" },
-	{ 0x062a00, "Parameters changed" },
-	{ 0x062a01, "Mode parameters changed" },
-	{ 0x062e00, "Insufficient time for operation" },
-	{ 0x063f00, "Logical unit operating conditions have changed" },
-	{ 0x063f01, "Microcode has been changed" },
-	{ 0x065a00, "Operator request or state change input (unspecified)" },
-	{ 0x065a01, "Operator medium removal request" },
-	{ 0x0bb900, "Play operation aborted" },
-
-	/* Here we use 0xff for the key (not a valid key) to signify
-	 * that these can have _any_ key value associated with them... */
-	{ 0xff0401, "Logical unit is in process of becoming ready" },
-	{ 0xff0400, "Logical unit not ready, cause not reportable" },
-	{ 0xff0402, "Logical unit not ready, initializing command required" },
-	{ 0xff0403, "Logical unit not ready, manual intervention required" },
-	{ 0xff0500, "Logical unit does not respond to selection" },
-	{ 0xff0800, "Logical unit communication failure" },
-	{ 0xff0802, "Logical unit communication parity error" },
-	{ 0xff0801, "Logical unit communication time-out" },
-	{ 0xff2500, "Logical unit not supported" },
-	{ 0xff4c00, "Logical unit failed self-configuration" },
-	{ 0xff3e00, "Logical unit has not self-configured yet" },
-};
-#endif
-
+/* ide-cd_ioctl.c */
+int ide_cdrom_open_real(struct cdrom_device_info *, int);
+void ide_cdrom_release_real(struct cdrom_device_info *);
+int ide_cdrom_drive_status(struct cdrom_device_info *, int);
+int ide_cdrom_check_media_change_real(struct cdrom_device_info *, int);
+int ide_cdrom_tray_move(struct cdrom_device_info *, int);
+int ide_cdrom_lock_door(struct cdrom_device_info *, int);
+int ide_cdrom_select_speed(struct cdrom_device_info *, int);
+int ide_cdrom_get_last_session(struct cdrom_device_info *,
+			       struct cdrom_multisession *);
+int ide_cdrom_get_mcn(struct cdrom_device_info *, struct cdrom_mcn *);
+int ide_cdrom_reset(struct cdrom_device_info *cdi);
+int ide_cdrom_audio_ioctl(struct cdrom_device_info *, unsigned int, void *);
+int ide_cdrom_packet(struct cdrom_device_info *, struct packet_command *);
 
 #endif /* _IDE_CD_H */
diff --git a/drivers/ide/ide-cd_ioctl.c b/drivers/ide/ide-cd_ioctl.c
new file mode 100644
index 0000000..b68284d
--- /dev/null
+++ b/drivers/ide/ide-cd_ioctl.c
@@ -0,0 +1,475 @@
+/*
+ * cdrom.c IOCTLs handling for ide-cd driver.
+ *
+ * Copyright (C) 1994-1996  Scott Snyder <snyder@fnald0.fnal.gov>
+ * Copyright (C) 1996-1998  Erik Andersen <andersee@debian.org>
+ * Copyright (C) 1998-2000  Jens Axboe <axboe@suse.de>
+ */
+
+#include <linux/kernel.h>
+#include <linux/cdrom.h>
+#include <linux/ide.h>
+#include <scsi/scsi.h>
+
+#include "ide-cd.h"
+
+/****************************************************************************
+ * Other driver requests (open, close, check media change).
+ */
+int ide_cdrom_open_real(struct cdrom_device_info *cdi, int purpose)
+{
+	return 0;
+}
+
+/*
+ * Close down the device.  Invalidate all cached blocks.
+ */
+void ide_cdrom_release_real(struct cdrom_device_info *cdi)
+{
+	ide_drive_t *drive = cdi->handle;
+	struct cdrom_info *cd = drive->driver_data;
+
+	if (!cdi->use_count)
+		cd->cd_flags &= ~IDE_CD_FLAG_TOC_VALID;
+}
+
+/*
+ * add logic to try GET_EVENT command first to check for media and tray
+ * status. this should be supported by newer cd-r/w and all DVD etc
+ * drives
+ */
+int ide_cdrom_drive_status(struct cdrom_device_info *cdi, int slot_nr)
+{
+	ide_drive_t *drive = cdi->handle;
+	struct media_event_desc med;
+	struct request_sense sense;
+	int stat;
+
+	if (slot_nr != CDSL_CURRENT)
+		return -EINVAL;
+
+	stat = cdrom_check_status(drive, &sense);
+	if (!stat || sense.sense_key == UNIT_ATTENTION)
+		return CDS_DISC_OK;
+
+	if (!cdrom_get_media_event(cdi, &med)) {
+		if (med.media_present)
+			return CDS_DISC_OK;
+		else if (med.door_open)
+			return CDS_TRAY_OPEN;
+		else
+			return CDS_NO_DISC;
+	}
+
+	if (sense.sense_key == NOT_READY && sense.asc == 0x04
+			&& sense.ascq == 0x04)
+		return CDS_DISC_OK;
+
+	/*
+	 * If not using Mt Fuji extended media tray reports,
+	 * just return TRAY_OPEN since ATAPI doesn't provide
+	 * any other way to detect this...
+	 */
+	if (sense.sense_key == NOT_READY) {
+		if (sense.asc == 0x3a && sense.ascq == 1)
+			return CDS_NO_DISC;
+		else
+			return CDS_TRAY_OPEN;
+	}
+	return CDS_DRIVE_NOT_READY;
+}
+
+int ide_cdrom_check_media_change_real(struct cdrom_device_info *cdi,
+				       int slot_nr)
+{
+	ide_drive_t *drive = cdi->handle;
+	struct cdrom_info *cd = drive->driver_data;
+	int retval;
+
+	if (slot_nr == CDSL_CURRENT) {
+		(void) cdrom_check_status(drive, NULL);
+		retval = (cd->cd_flags & IDE_CD_FLAG_MEDIA_CHANGED) ? 1 : 0;
+		cd->cd_flags &= ~IDE_CD_FLAG_MEDIA_CHANGED;
+		return retval;
+	} else {
+		return -EINVAL;
+	}
+}
+
+/* Eject the disk if EJECTFLAG is 0.
+   If EJECTFLAG is 1, try to reload the disk. */
+static
+int cdrom_eject(ide_drive_t *drive, int ejectflag,
+		struct request_sense *sense)
+{
+	struct cdrom_info *cd = drive->driver_data;
+	struct cdrom_device_info *cdi = &cd->devinfo;
+	struct request req;
+	char loej = 0x02;
+
+	if ((cd->cd_flags & IDE_CD_FLAG_NO_EJECT) && !ejectflag)
+		return -EDRIVE_CANT_DO_THIS;
+
+	/* reload fails on some drives, if the tray is locked */
+	if ((cd->cd_flags & IDE_CD_FLAG_DOOR_LOCKED) && ejectflag)
+		return 0;
+
+	ide_cd_init_rq(drive, &req);
+
+	/* only tell drive to close tray if open, if it can do that */
+	if (ejectflag && (cdi->mask & CDC_CLOSE_TRAY))
+		loej = 0;
+
+	req.sense = sense;
+	req.cmd[0] = GPCMD_START_STOP_UNIT;
+	req.cmd[4] = loej | (ejectflag != 0);
+
+	return ide_cd_queue_pc(drive, &req);
+}
+
+/* Lock the door if LOCKFLAG is nonzero; unlock it otherwise. */
+static
+int ide_cd_lockdoor(ide_drive_t *drive, int lockflag,
+		    struct request_sense *sense)
+{
+	struct cdrom_info *cd = drive->driver_data;
+	struct request_sense my_sense;
+	struct request req;
+	int stat;
+
+	if (sense == NULL)
+		sense = &my_sense;
+
+	/* If the drive cannot lock the door, just pretend. */
+	if (cd->cd_flags & IDE_CD_FLAG_NO_DOORLOCK) {
+		stat = 0;
+	} else {
+		ide_cd_init_rq(drive, &req);
+		req.sense = sense;
+		req.cmd[0] = GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL;
+		req.cmd[4] = lockflag ? 1 : 0;
+		stat = ide_cd_queue_pc(drive, &req);
+	}
+
+	/* If we got an illegal field error, the drive
+	   probably cannot lock the door. */
+	if (stat != 0 &&
+	    sense->sense_key == ILLEGAL_REQUEST &&
+	    (sense->asc == 0x24 || sense->asc == 0x20)) {
+		printk(KERN_ERR "%s: door locking not supported\n",
+			drive->name);
+		cd->cd_flags |= IDE_CD_FLAG_NO_DOORLOCK;
+		stat = 0;
+	}
+
+	/* no medium, that's alright. */
+	if (stat != 0 && sense->sense_key == NOT_READY && sense->asc == 0x3a)
+		stat = 0;
+
+	if (stat == 0) {
+		if (lockflag)
+			cd->cd_flags |= IDE_CD_FLAG_DOOR_LOCKED;
+		else
+			cd->cd_flags &= ~IDE_CD_FLAG_DOOR_LOCKED;
+	}
+
+	return stat;
+}
+
+int ide_cdrom_tray_move(struct cdrom_device_info *cdi, int position)
+{
+	ide_drive_t *drive = cdi->handle;
+	struct request_sense sense;
+
+	if (position) {
+		int stat = ide_cd_lockdoor(drive, 0, &sense);
+
+		if (stat)
+			return stat;
+	}
+
+	return cdrom_eject(drive, !position, &sense);
+}
+
+int ide_cdrom_lock_door(struct cdrom_device_info *cdi, int lock)
+{
+	ide_drive_t *drive = cdi->handle;
+
+	return ide_cd_lockdoor(drive, lock, NULL);
+}
+
+/*
+ * ATAPI devices are free to select the speed you request or any slower
+ * rate. :-(  Requesting too fast a speed will _not_ produce an error.
+ */
+int ide_cdrom_select_speed(struct cdrom_device_info *cdi, int speed)
+{
+	ide_drive_t *drive = cdi->handle;
+	struct cdrom_info *cd = drive->driver_data;
+	struct request rq;
+	struct request_sense sense;
+	u8 buf[ATAPI_CAPABILITIES_PAGE_SIZE];
+	int stat;
+
+	ide_cd_init_rq(drive, &rq);
+
+	rq.sense = &sense;
+
+	if (speed == 0)
+		speed = 0xffff; /* set to max */
+	else
+		speed *= 177;   /* Nx to kbytes/s */
+
+	rq.cmd[0] = GPCMD_SET_SPEED;
+	/* Read Drive speed in kbytes/second MSB/LSB */
+	rq.cmd[2] = (speed >> 8) & 0xff;
+	rq.cmd[3] = speed & 0xff;
+	if ((cdi->mask & (CDC_CD_R | CDC_CD_RW | CDC_DVD_R)) !=
+	    (CDC_CD_R | CDC_CD_RW | CDC_DVD_R)) {
+		/* Write Drive speed in kbytes/second MSB/LSB */
+		rq.cmd[4] = (speed >> 8) & 0xff;
+		rq.cmd[5] = speed & 0xff;
+	}
+
+	stat = ide_cd_queue_pc(drive, &rq);
+
+	if (!ide_cdrom_get_capabilities(drive, buf)) {
+		ide_cdrom_update_speed(drive, buf);
+		cdi->speed = cd->current_speed;
+	}
+
+	return 0;
+}
+
+int ide_cdrom_get_last_session(struct cdrom_device_info *cdi,
+			       struct cdrom_multisession *ms_info)
+{
+	struct atapi_toc *toc;
+	ide_drive_t *drive = cdi->handle;
+	struct cdrom_info *info = drive->driver_data;
+	struct request_sense sense;
+	int ret;
+
+	if ((info->cd_flags & IDE_CD_FLAG_TOC_VALID) == 0 || !info->toc) {
+		ret = ide_cd_read_toc(drive, &sense);
+		if (ret)
+			return ret;
+	}
+
+	toc = info->toc;
+	ms_info->addr.lba = toc->last_session_lba;
+	ms_info->xa_flag = toc->xa_flag;
+
+	return 0;
+}
+
+int ide_cdrom_get_mcn(struct cdrom_device_info *cdi,
+		      struct cdrom_mcn *mcn_info)
+{
+	ide_drive_t *drive = cdi->handle;
+	int stat, mcnlen;
+	struct request rq;
+	char buf[24];
+
+	ide_cd_init_rq(drive, &rq);
+
+	rq.data = buf;
+	rq.data_len = sizeof(buf);
+
+	rq.cmd[0] = GPCMD_READ_SUBCHANNEL;
+	rq.cmd[1] = 2;		/* MSF addressing */
+	rq.cmd[2] = 0x40;	/* request subQ data */
+	rq.cmd[3] = 2;		/* format */
+	rq.cmd[8] = sizeof(buf);
+
+	stat = ide_cd_queue_pc(drive, &rq);
+	if (stat)
+		return stat;
+
+	mcnlen = sizeof(mcn_info->medium_catalog_number) - 1;
+	memcpy(mcn_info->medium_catalog_number, buf + 9, mcnlen);
+	mcn_info->medium_catalog_number[mcnlen] = '\0';
+
+	return 0;
+}
+
+int ide_cdrom_reset(struct cdrom_device_info *cdi)
+{
+	ide_drive_t *drive = cdi->handle;
+	struct cdrom_info *cd = drive->driver_data;
+	struct request_sense sense;
+	struct request req;
+	int ret;
+
+	ide_cd_init_rq(drive, &req);
+	req.cmd_type = REQ_TYPE_SPECIAL;
+	req.cmd_flags = REQ_QUIET;
+	ret = ide_do_drive_cmd(drive, &req, ide_wait);
+
+	/*
+	 * A reset will unlock the door. If it was previously locked,
+	 * lock it again.
+	 */
+	if (cd->cd_flags & IDE_CD_FLAG_DOOR_LOCKED)
+		(void)ide_cd_lockdoor(drive, 1, &sense);
+
+	return ret;
+}
+
+static int ide_cd_get_toc_entry(ide_drive_t *drive, int track,
+				struct atapi_toc_entry **ent)
+{
+	struct cdrom_info *info = drive->driver_data;
+	struct atapi_toc *toc = info->toc;
+	int ntracks;
+
+	/*
+	 * don't serve cached data, if the toc isn't valid
+	 */
+	if ((info->cd_flags & IDE_CD_FLAG_TOC_VALID) == 0)
+		return -EINVAL;
+
+	/* Check validity of requested track number. */
+	ntracks = toc->hdr.last_track - toc->hdr.first_track + 1;
+
+	if (toc->hdr.first_track == CDROM_LEADOUT)
+		ntracks = 0;
+
+	if (track == CDROM_LEADOUT)
+		*ent = &toc->ent[ntracks];
+	else if (track < toc->hdr.first_track || track > toc->hdr.last_track)
+		return -EINVAL;
+	else
+		*ent = &toc->ent[track - toc->hdr.first_track];
+
+	return 0;
+}
+
+static int ide_cd_fake_play_trkind(ide_drive_t *drive, void *arg)
+{
+	struct cdrom_ti *ti = arg;
+	struct atapi_toc_entry *first_toc, *last_toc;
+	unsigned long lba_start, lba_end;
+	int stat;
+	struct request rq;
+	struct request_sense sense;
+
+	stat = ide_cd_get_toc_entry(drive, ti->cdti_trk0, &first_toc);
+	if (stat)
+		return stat;
+
+	stat = ide_cd_get_toc_entry(drive, ti->cdti_trk1, &last_toc);
+	if (stat)
+		return stat;
+
+	if (ti->cdti_trk1 != CDROM_LEADOUT)
+		++last_toc;
+	lba_start = first_toc->addr.lba;
+	lba_end   = last_toc->addr.lba;
+
+	if (lba_end <= lba_start)
+		return -EINVAL;
+
+	ide_cd_init_rq(drive, &rq);
+
+	rq.sense = &sense;
+	rq.cmd[0] = GPCMD_PLAY_AUDIO_MSF;
+	lba_to_msf(lba_start,   &rq.cmd[3], &rq.cmd[4], &rq.cmd[5]);
+	lba_to_msf(lba_end - 1, &rq.cmd[6], &rq.cmd[7], &rq.cmd[8]);
+
+	return ide_cd_queue_pc(drive, &rq);
+}
+
+static int ide_cd_read_tochdr(ide_drive_t *drive, void *arg)
+{
+	struct cdrom_info *cd = drive->driver_data;
+	struct cdrom_tochdr *tochdr = arg;
+	struct atapi_toc *toc;
+	int stat;
+
+	/* Make sure our saved TOC is valid. */
+	stat = ide_cd_read_toc(drive, NULL);
+	if (stat)
+		return stat;
+
+	toc = cd->toc;
+	tochdr->cdth_trk0 = toc->hdr.first_track;
+	tochdr->cdth_trk1 = toc->hdr.last_track;
+
+	return 0;
+}
+
+static int ide_cd_read_tocentry(ide_drive_t *drive, void *arg)
+{
+	struct cdrom_tocentry *tocentry = arg;
+	struct atapi_toc_entry *toce;
+	int stat;
+
+	stat = ide_cd_get_toc_entry(drive, tocentry->cdte_track, &toce);
+	if (stat)
+		return stat;
+
+	tocentry->cdte_ctrl = toce->control;
+	tocentry->cdte_adr  = toce->adr;
+	if (tocentry->cdte_format == CDROM_MSF) {
+		lba_to_msf(toce->addr.lba,
+			   &tocentry->cdte_addr.msf.minute,
+			   &tocentry->cdte_addr.msf.second,
+			   &tocentry->cdte_addr.msf.frame);
+	} else
+		tocentry->cdte_addr.lba = toce->addr.lba;
+
+	return 0;
+}
+
+int ide_cdrom_audio_ioctl(struct cdrom_device_info *cdi,
+			  unsigned int cmd, void *arg)
+{
+	ide_drive_t *drive = cdi->handle;
+
+	switch (cmd) {
+	/*
+	 * emulate PLAY_AUDIO_TI command with PLAY_AUDIO_10, since
+	 * atapi doesn't support it
+	 */
+	case CDROMPLAYTRKIND:
+		return ide_cd_fake_play_trkind(drive, arg);
+	case CDROMREADTOCHDR:
+		return ide_cd_read_tochdr(drive, arg);
+	case CDROMREADTOCENTRY:
+		return ide_cd_read_tocentry(drive, arg);
+	default:
+		return -EINVAL;
+	}
+}
+
+/* the generic packet interface to cdrom.c */
+int ide_cdrom_packet(struct cdrom_device_info *cdi,
+			    struct packet_command *cgc)
+{
+	struct request req;
+	ide_drive_t *drive = cdi->handle;
+
+	if (cgc->timeout <= 0)
+		cgc->timeout = ATAPI_WAIT_PC;
+
+	/* here we queue the commands from the uniform CD-ROM
+	   layer. the packet must be complete, as we do not
+	   touch it at all. */
+	ide_cd_init_rq(drive, &req);
+	memcpy(req.cmd, cgc->cmd, CDROM_PACKET_SIZE);
+	if (cgc->sense)
+		memset(cgc->sense, 0, sizeof(struct request_sense));
+	req.data = cgc->buffer;
+	req.data_len = cgc->buflen;
+	req.timeout = cgc->timeout;
+
+	if (cgc->quiet)
+		req.cmd_flags |= REQ_QUIET;
+
+	req.sense = cgc->sense;
+	cgc->stat = ide_cd_queue_pc(drive, &req);
+	if (!cgc->stat)
+		cgc->buflen -= req.data_len;
+	return cgc->stat;
+}
diff --git a/drivers/ide/ide-cd_verbose.c b/drivers/ide/ide-cd_verbose.c
new file mode 100644
index 0000000..6ed7ca0
--- /dev/null
+++ b/drivers/ide/ide-cd_verbose.c
@@ -0,0 +1,359 @@
+/*
+ * Verbose error logging for ATAPI CD/DVD devices.
+ *
+ * Copyright (C) 1994-1996  Scott Snyder <snyder@fnald0.fnal.gov>
+ * Copyright (C) 1996-1998  Erik Andersen <andersee@debian.org>
+ * Copyright (C) 1998-2000  Jens Axboe <axboe@suse.de>
+ */
+
+#include <linux/kernel.h>
+#include <linux/blkdev.h>
+#include <linux/cdrom.h>
+#include <scsi/scsi.h>
+
+#ifndef CONFIG_BLK_DEV_IDECD_VERBOSE_ERRORS
+void ide_cd_log_error(const char *name, struct request *failed_command,
+		      struct request_sense *sense)
+{
+	/* Suppress printing unit attention and `in progress of becoming ready'
+	   errors when we're not being verbose. */
+	if (sense->sense_key == UNIT_ATTENTION ||
+	    (sense->sense_key == NOT_READY && (sense->asc == 4 ||
+						sense->asc == 0x3a)))
+		return;
+
+	printk(KERN_ERR "%s: error code: 0x%02x  sense_key: 0x%02x  "
+			"asc: 0x%02x  ascq: 0x%02x\n",
+			name, sense->error_code, sense->sense_key,
+			sense->asc, sense->ascq);
+}
+#else
+/* The generic packet command opcodes for CD/DVD Logical Units,
+ * From Table 57 of the SFF8090 Ver. 3 (Mt. Fuji) draft standard. */
+static const struct {
+	unsigned short packet_command;
+	const char * const text;
+} packet_command_texts[] = {
+	{ GPCMD_TEST_UNIT_READY, "Test Unit Ready" },
+	{ GPCMD_REQUEST_SENSE, "Request Sense" },
+	{ GPCMD_FORMAT_UNIT, "Format Unit" },
+	{ GPCMD_INQUIRY, "Inquiry" },
+	{ GPCMD_START_STOP_UNIT, "Start/Stop Unit" },
+	{ GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL, "Prevent/Allow Medium Removal" },
+	{ GPCMD_READ_FORMAT_CAPACITIES, "Read Format Capacities" },
+	{ GPCMD_READ_CDVD_CAPACITY, "Read Cd/Dvd Capacity" },
+	{ GPCMD_READ_10, "Read 10" },
+	{ GPCMD_WRITE_10, "Write 10" },
+	{ GPCMD_SEEK, "Seek" },
+	{ GPCMD_WRITE_AND_VERIFY_10, "Write and Verify 10" },
+	{ GPCMD_VERIFY_10, "Verify 10" },
+	{ GPCMD_FLUSH_CACHE, "Flush Cache" },
+	{ GPCMD_READ_SUBCHANNEL, "Read Subchannel" },
+	{ GPCMD_READ_TOC_PMA_ATIP, "Read Table of Contents" },
+	{ GPCMD_READ_HEADER, "Read Header" },
+	{ GPCMD_PLAY_AUDIO_10, "Play Audio 10" },
+	{ GPCMD_GET_CONFIGURATION, "Get Configuration" },
+	{ GPCMD_PLAY_AUDIO_MSF, "Play Audio MSF" },
+	{ GPCMD_PLAYAUDIO_TI, "Play Audio TrackIndex" },
+	{ GPCMD_GET_EVENT_STATUS_NOTIFICATION,
+		"Get Event Status Notification" },
+	{ GPCMD_PAUSE_RESUME, "Pause/Resume" },
+	{ GPCMD_STOP_PLAY_SCAN, "Stop Play/Scan" },
+	{ GPCMD_READ_DISC_INFO, "Read Disc Info" },
+	{ GPCMD_READ_TRACK_RZONE_INFO, "Read Track Rzone Info" },
+	{ GPCMD_RESERVE_RZONE_TRACK, "Reserve Rzone Track" },
+	{ GPCMD_SEND_OPC, "Send OPC" },
+	{ GPCMD_MODE_SELECT_10, "Mode Select 10" },
+	{ GPCMD_REPAIR_RZONE_TRACK, "Repair Rzone Track" },
+	{ GPCMD_MODE_SENSE_10, "Mode Sense 10" },
+	{ GPCMD_CLOSE_TRACK, "Close Track" },
+	{ GPCMD_BLANK, "Blank" },
+	{ GPCMD_SEND_EVENT, "Send Event" },
+	{ GPCMD_SEND_KEY, "Send Key" },
+	{ GPCMD_REPORT_KEY, "Report Key" },
+	{ GPCMD_LOAD_UNLOAD, "Load/Unload" },
+	{ GPCMD_SET_READ_AHEAD, "Set Read-ahead" },
+	{ GPCMD_READ_12, "Read 12" },
+	{ GPCMD_GET_PERFORMANCE, "Get Performance" },
+	{ GPCMD_SEND_DVD_STRUCTURE, "Send DVD Structure" },
+	{ GPCMD_READ_DVD_STRUCTURE, "Read DVD Structure" },
+	{ GPCMD_SET_STREAMING, "Set Streaming" },
+	{ GPCMD_READ_CD_MSF, "Read CD MSF" },
+	{ GPCMD_SCAN, "Scan" },
+	{ GPCMD_SET_SPEED, "Set Speed" },
+	{ GPCMD_PLAY_CD, "Play CD" },
+	{ GPCMD_MECHANISM_STATUS, "Mechanism Status" },
+	{ GPCMD_READ_CD, "Read CD" },
+};
+
+/* From Table 303 of the SFF8090 Ver. 3 (Mt. Fuji) draft standard. */
+static const char * const sense_key_texts[16] = {
+	"No sense data",
+	"Recovered error",
+	"Not ready",
+	"Medium error",
+	"Hardware error",
+	"Illegal request",
+	"Unit attention",
+	"Data protect",
+	"Blank check",
+	"(reserved)",
+	"(reserved)",
+	"Aborted command",
+	"(reserved)",
+	"(reserved)",
+	"Miscompare",
+	"(reserved)",
+};
+
+/* From Table 304 of the SFF8090 Ver. 3 (Mt. Fuji) draft standard. */
+static const struct {
+	unsigned long asc_ascq;
+	const char * const text;
+} sense_data_texts[] = {
+	{ 0x000000, "No additional sense information" },
+	{ 0x000011, "Play operation in progress" },
+	{ 0x000012, "Play operation paused" },
+	{ 0x000013, "Play operation successfully completed" },
+	{ 0x000014, "Play operation stopped due to error" },
+	{ 0x000015, "No current audio status to return" },
+	{ 0x010c0a, "Write error - padding blocks added" },
+	{ 0x011700, "Recovered data with no error correction applied" },
+	{ 0x011701, "Recovered data with retries" },
+	{ 0x011702, "Recovered data with positive head offset" },
+	{ 0x011703, "Recovered data with negative head offset" },
+	{ 0x011704, "Recovered data with retries and/or CIRC applied" },
+	{ 0x011705, "Recovered data using previous sector ID" },
+	{ 0x011800, "Recovered data with error correction applied" },
+	{ 0x011801, "Recovered data with error correction and retries applied"},
+	{ 0x011802, "Recovered data - the data was auto-reallocated" },
+	{ 0x011803, "Recovered data with CIRC" },
+	{ 0x011804, "Recovered data with L-EC" },
+	{ 0x015d00, "Failure prediction threshold exceeded"
+		    " - Predicted logical unit failure" },
+	{ 0x015d01, "Failure prediction threshold exceeded"
+		    " - Predicted media failure" },
+	{ 0x015dff, "Failure prediction threshold exceeded - False" },
+	{ 0x017301, "Power calibration area almost full" },
+	{ 0x020400, "Logical unit not ready - cause not reportable" },
+	/* Following is misspelled in ATAPI 2.6, _and_ in Mt. Fuji */
+	{ 0x020401, "Logical unit not ready"
+		    " - in progress [sic] of becoming ready" },
+	{ 0x020402, "Logical unit not ready - initializing command required" },
+	{ 0x020403, "Logical unit not ready - manual intervention required" },
+	{ 0x020404, "Logical unit not ready - format in progress" },
+	{ 0x020407, "Logical unit not ready - operation in progress" },
+	{ 0x020408, "Logical unit not ready - long write in progress" },
+	{ 0x020600, "No reference position found (media may be upside down)" },
+	{ 0x023000, "Incompatible medium installed" },
+	{ 0x023a00, "Medium not present" },
+	{ 0x025300, "Media load or eject failed" },
+	{ 0x025700, "Unable to recover table of contents" },
+	{ 0x030300, "Peripheral device write fault" },
+	{ 0x030301, "No write current" },
+	{ 0x030302, "Excessive write errors" },
+	{ 0x030c00, "Write error" },
+	{ 0x030c01, "Write error - Recovered with auto reallocation" },
+	{ 0x030c02, "Write error - auto reallocation failed" },
+	{ 0x030c03, "Write error - recommend reassignment" },
+	{ 0x030c04, "Compression check miscompare error" },
+	{ 0x030c05, "Data expansion occurred during compress" },
+	{ 0x030c06, "Block not compressible" },
+	{ 0x030c07, "Write error - recovery needed" },
+	{ 0x030c08, "Write error - recovery failed" },
+	{ 0x030c09, "Write error - loss of streaming" },
+	{ 0x031100, "Unrecovered read error" },
+	{ 0x031106, "CIRC unrecovered error" },
+	{ 0x033101, "Format command failed" },
+	{ 0x033200, "No defect spare location available" },
+	{ 0x033201, "Defect list update failure" },
+	{ 0x035100, "Erase failure" },
+	{ 0x037200, "Session fixation error" },
+	{ 0x037201, "Session fixation error writin lead-in" },
+	{ 0x037202, "Session fixation error writin lead-out" },
+	{ 0x037300, "CD control error" },
+	{ 0x037302, "Power calibration area is full" },
+	{ 0x037303, "Power calibration area error" },
+	{ 0x037304, "Program memory area / RMA update failure" },
+	{ 0x037305, "Program memory area / RMA is full" },
+	{ 0x037306, "Program memory area / RMA is (almost) full" },
+	{ 0x040200, "No seek complete" },
+	{ 0x040300, "Write fault" },
+	{ 0x040900, "Track following error" },
+	{ 0x040901, "Tracking servo failure" },
+	{ 0x040902, "Focus servo failure" },
+	{ 0x040903, "Spindle servo failure" },
+	{ 0x041500, "Random positioning error" },
+	{ 0x041501, "Mechanical positioning or changer error" },
+	{ 0x041502, "Positioning error detected by read of medium" },
+	{ 0x043c00, "Mechanical positioning or changer error" },
+	{ 0x044000, "Diagnostic failure on component (ASCQ)" },
+	{ 0x044400, "Internal CD/DVD logical unit failure" },
+	{ 0x04b600, "Media load mechanism failed" },
+	{ 0x051a00, "Parameter list length error" },
+	{ 0x052000, "Invalid command operation code" },
+	{ 0x052100, "Logical block address out of range" },
+	{ 0x052102, "Invalid address for write" },
+	{ 0x052400, "Invalid field in command packet" },
+	{ 0x052600, "Invalid field in parameter list" },
+	{ 0x052601, "Parameter not supported" },
+	{ 0x052602, "Parameter value invalid" },
+	{ 0x052700, "Write protected media" },
+	{ 0x052c00, "Command sequence error" },
+	{ 0x052c03, "Current program area is not empty" },
+	{ 0x052c04, "Current program area is empty" },
+	{ 0x053001, "Cannot read medium - unknown format" },
+	{ 0x053002, "Cannot read medium - incompatible format" },
+	{ 0x053900, "Saving parameters not supported" },
+	{ 0x054e00, "Overlapped commands attempted" },
+	{ 0x055302, "Medium removal prevented" },
+	{ 0x055500, "System resource failure" },
+	{ 0x056300, "End of user area encountered on this track" },
+	{ 0x056400, "Illegal mode for this track or incompatible medium" },
+	{ 0x056f00, "Copy protection key exchange failure"
+		    " - Authentication failure" },
+	{ 0x056f01, "Copy protection key exchange failure - Key not present" },
+	{ 0x056f02, "Copy protection key exchange failure"
+		     " - Key not established" },
+	{ 0x056f03, "Read of scrambled sector without authentication" },
+	{ 0x056f04, "Media region code is mismatched to logical unit" },
+	{ 0x056f05, "Drive region must be permanent"
+		    " / region reset count error" },
+	{ 0x057203, "Session fixation error - incomplete track in session" },
+	{ 0x057204, "Empty or partially written reserved track" },
+	{ 0x057205, "No more RZONE reservations are allowed" },
+	{ 0x05bf00, "Loss of streaming" },
+	{ 0x062800, "Not ready to ready transition, medium may have changed" },
+	{ 0x062900, "Power on, reset or hardware reset occurred" },
+	{ 0x062a00, "Parameters changed" },
+	{ 0x062a01, "Mode parameters changed" },
+	{ 0x062e00, "Insufficient time for operation" },
+	{ 0x063f00, "Logical unit operating conditions have changed" },
+	{ 0x063f01, "Microcode has been changed" },
+	{ 0x065a00, "Operator request or state change input (unspecified)" },
+	{ 0x065a01, "Operator medium removal request" },
+	{ 0x0bb900, "Play operation aborted" },
+	/* Here we use 0xff for the key (not a valid key) to signify
+	 * that these can have _any_ key value associated with them... */
+	{ 0xff0401, "Logical unit is in process of becoming ready" },
+	{ 0xff0400, "Logical unit not ready, cause not reportable" },
+	{ 0xff0402, "Logical unit not ready, initializing command required" },
+	{ 0xff0403, "Logical unit not ready, manual intervention required" },
+	{ 0xff0500, "Logical unit does not respond to selection" },
+	{ 0xff0800, "Logical unit communication failure" },
+	{ 0xff0802, "Logical unit communication parity error" },
+	{ 0xff0801, "Logical unit communication time-out" },
+	{ 0xff2500, "Logical unit not supported" },
+	{ 0xff4c00, "Logical unit failed self-configuration" },
+	{ 0xff3e00, "Logical unit has not self-configured yet" },
+};
+
+void ide_cd_log_error(const char *name, struct request *failed_command,
+		      struct request_sense *sense)
+{
+	int i;
+	const char *s = "bad sense key!";
+	char buf[80];
+
+	printk(KERN_ERR "ATAPI device %s:\n", name);
+	if (sense->error_code == 0x70)
+		printk(KERN_CONT "  Error: ");
+	else if (sense->error_code == 0x71)
+		printk("  Deferred Error: ");
+	else if (sense->error_code == 0x7f)
+		printk(KERN_CONT "  Vendor-specific Error: ");
+	else
+		printk(KERN_CONT "  Unknown Error Type: ");
+
+	if (sense->sense_key < ARRAY_SIZE(sense_key_texts))
+		s = sense_key_texts[sense->sense_key];
+
+	printk(KERN_CONT "%s -- (Sense key=0x%02x)\n", s, sense->sense_key);
+
+	if (sense->asc == 0x40) {
+		sprintf(buf, "Diagnostic failure on component 0x%02x",
+			sense->ascq);
+		s = buf;
+	} else {
+		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))
+			key |= sense->ascq;
+		s = NULL;
+
+		while (hi > lo) {
+			mid = (lo + hi) / 2;
+			if (sense_data_texts[mid].asc_ascq == key ||
+			    sense_data_texts[mid].asc_ascq == (0xff0000|key)) {
+				s = sense_data_texts[mid].text;
+				break;
+			} else if (sense_data_texts[mid].asc_ascq > key)
+				hi = mid;
+			else
+				lo = mid + 1;
+		}
+	}
+
+	if (s == NULL) {
+		if (sense->asc > 0x80)
+			s = "(vendor-specific error)";
+		else
+			s = "(reserved error code)";
+	}
+
+	printk(KERN_ERR "  %s -- (asc=0x%02x, ascq=0x%02x)\n",
+			s, sense->asc, sense->ascq);
+
+	if (failed_command != NULL) {
+		int lo = 0, mid, hi = ARRAY_SIZE(packet_command_texts);
+		s = NULL;
+
+		while (hi > lo) {
+			mid = (lo + hi) / 2;
+			if (packet_command_texts[mid].packet_command ==
+			    failed_command->cmd[0]) {
+				s = packet_command_texts[mid].text;
+				break;
+			}
+			if (packet_command_texts[mid].packet_command >
+			    failed_command->cmd[0])
+				hi = mid;
+			else
+				lo = mid + 1;
+		}
+
+		printk(KERN_ERR "  The failed \"%s\" packet command "
+				"was: \n  \"", s);
+		for (i = 0; i < sizeof(failed_command->cmd); i++)
+			printk(KERN_CONT "%02x ", failed_command->cmd[i]);
+		printk(KERN_CONT "\"\n");
+	}
+
+	/* The SKSV bit specifies validity of the sense_key_specific
+	 * in the next two commands. It is bit 7 of the first byte.
+	 * In the case of NOT_READY, if SKSV is set the drive can
+	 * give us nice ETA readings.
+	 */
+	if (sense->sense_key == NOT_READY && (sense->sks[0] & 0x80)) {
+		int progress = (sense->sks[1] << 8 | sense->sks[2]) * 100;
+
+		printk(KERN_ERR "  Command is %02d%% complete\n",
+				progress / 0xffff);
+	}
+
+	if (sense->sense_key == ILLEGAL_REQUEST &&
+	    (sense->sks[0] & 0x80) != 0) {
+		printk(KERN_ERR "  Error in %s byte %d",
+				(sense->sks[0] & 0x40) != 0 ?
+				"command packet" : "command data",
+				(sense->sks[1] << 8) + sense->sks[2]);
+
+		if ((sense->sks[0] & 0x40) != 0)
+			printk(KERN_CONT " bit %d", sense->sks[0] & 0x07);
+
+		printk(KERN_CONT "\n");
+	}
+}
+#endif
diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c
index 717e114..3c69822 100644
--- a/drivers/ide/ide-disk.c
+++ b/drivers/ide/ide-disk.c
@@ -1,10 +1,9 @@
 /*
- *  linux/drivers/ide/ide-disk.c	Version 1.18	Mar 05, 2003
- *
- *  Copyright (C) 1994-1998  Linus Torvalds & authors (see below)
- *  Copyright (C) 1998-2002  Linux ATA Development
- *				Andre Hedrick <andre@linux-ide.org>
- *  Copyright (C) 2003	     Red Hat <alan@redhat.com>
+ *  Copyright (C) 1994-1998	   Linus Torvalds & authors (see below)
+ *  Copyright (C) 1998-2002	   Linux ATA Development
+ *				      Andre Hedrick <andre@linux-ide.org>
+ *  Copyright (C) 2003		   Red Hat <alan@redhat.com>
+ *  Copyright (C) 2003-2005, 2007  Bartlomiej Zolnierkiewicz
  */
 
 /*
diff --git a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c
index 5bf3203..7beaf1e 100644
--- a/drivers/ide/ide-dma.c
+++ b/drivers/ide/ide-dma.c
@@ -1,15 +1,13 @@
 /*
- *  linux/drivers/ide/ide-dma.c		Version 4.10	June 9, 2000
+ *  Copyright (C) 1995-1998   Mark Lord
+ *  Copyright (C) 1999-2000   Andre Hedrick <andre@linux-ide.org>
+ *  Copyright (C) 2004, 2007  Bartlomiej Zolnierkiewicz
  *
- *  Copyright (c) 1999-2000	Andre Hedrick <andre@linux-ide.org>
  *  May be copied or modified under the terms of the GNU General Public License
  */
 
 /*
  *  Special Thanks to Mark for his Six years of work.
- *
- *  Copyright (c) 1995-1998  Mark Lord
- *  May be copied or modified under the terms of the GNU General Public License
  */
 
 /*
@@ -85,6 +83,7 @@
 #include <linux/ide.h>
 #include <linux/delay.h>
 #include <linux/scatterlist.h>
+#include <linux/dma-mapping.h>
 
 #include <asm/io.h>
 #include <asm/irq.h>
@@ -169,16 +168,15 @@
 	return ide_in_drive_list(drive->id, drive_whitelist);
 }
 
-#ifdef CONFIG_BLK_DEV_IDEDMA_PCI
 /**
  *	ide_build_sglist	-	map IDE scatter gather for DMA I/O
  *	@drive: the drive to build the DMA table for
  *	@rq: the request holding the sg list
  *
- *	Perform the PCI mapping magic necessary to access the source or
- *	target buffers of a request via PCI DMA. The lower layers of the
+ *	Perform the DMA mapping magic necessary to access the source or
+ *	target buffers of a request via DMA.  The lower layers of the
  *	kernel provide the necessary cache management so that we can
- *	operate in a portable fashion
+ *	operate in a portable fashion.
  */
 
 int ide_build_sglist(ide_drive_t *drive, struct request *rq)
@@ -186,20 +184,20 @@
 	ide_hwif_t *hwif = HWIF(drive);
 	struct scatterlist *sg = hwif->sg_table;
 
-	BUG_ON((rq->cmd_type == REQ_TYPE_ATA_TASKFILE) && rq->nr_sectors > 256);
-
 	ide_map_sg(drive, rq);
 
 	if (rq_data_dir(rq) == READ)
-		hwif->sg_dma_direction = PCI_DMA_FROMDEVICE;
+		hwif->sg_dma_direction = DMA_FROM_DEVICE;
 	else
-		hwif->sg_dma_direction = PCI_DMA_TODEVICE;
+		hwif->sg_dma_direction = DMA_TO_DEVICE;
 
-	return pci_map_sg(hwif->pci_dev, sg, hwif->sg_nents, hwif->sg_dma_direction);
+	return dma_map_sg(hwif->dev, sg, hwif->sg_nents,
+			  hwif->sg_dma_direction);
 }
 
 EXPORT_SYMBOL_GPL(ide_build_sglist);
 
+#ifdef CONFIG_BLK_DEV_IDEDMA_PCI
 /**
  *	ide_build_dmatable	-	build IDE DMA table
  *
@@ -284,16 +282,17 @@
 			*--table |= cpu_to_le32(0x80000000);
 		return count;
 	}
+
 	printk(KERN_ERR "%s: empty DMA table?\n", drive->name);
+
 use_pio_instead:
-	pci_unmap_sg(hwif->pci_dev,
-		     hwif->sg_table,
-		     hwif->sg_nents,
-		     hwif->sg_dma_direction);
+	ide_destroy_dmatable(drive);
+
 	return 0; /* revert to PIO for this request */
 }
 
 EXPORT_SYMBOL_GPL(ide_build_dmatable);
+#endif
 
 /**
  *	ide_destroy_dmatable	-	clean up DMA mapping
@@ -308,15 +307,15 @@
  
 void ide_destroy_dmatable (ide_drive_t *drive)
 {
-	struct pci_dev *dev = HWIF(drive)->pci_dev;
-	struct scatterlist *sg = HWIF(drive)->sg_table;
-	int nents = HWIF(drive)->sg_nents;
+	ide_hwif_t *hwif = drive->hwif;
 
-	pci_unmap_sg(dev, sg, nents, HWIF(drive)->sg_dma_direction);
+	dma_unmap_sg(hwif->dev, hwif->sg_table, hwif->sg_nents,
+		     hwif->sg_dma_direction);
 }
 
 EXPORT_SYMBOL_GPL(ide_destroy_dmatable);
 
+#ifdef CONFIG_BLK_DEV_IDEDMA_PCI
 /**
  *	config_drive_for_dma	-	attempt to activate IDE DMA
  *	@drive: the drive to place in DMA mode
@@ -474,8 +473,6 @@
 	drive->hwif->dma_host_set(drive, 1);
 }
 
-EXPORT_SYMBOL(ide_dma_on);
-
 #ifdef CONFIG_BLK_DEV_IDEDMA_PCI
 /**
  *	ide_dma_setup	-	begin a DMA phase
@@ -847,10 +844,10 @@
 static void ide_release_dma_engine(ide_hwif_t *hwif)
 {
 	if (hwif->dmatable_cpu) {
-		pci_free_consistent(hwif->pci_dev,
-				    PRD_ENTRIES * PRD_BYTES,
-				    hwif->dmatable_cpu,
-				    hwif->dmatable_dma);
+		struct pci_dev *pdev = to_pci_dev(hwif->dev);
+
+		pci_free_consistent(pdev, PRD_ENTRIES * PRD_BYTES,
+				    hwif->dmatable_cpu, hwif->dmatable_dma);
 		hwif->dmatable_cpu = NULL;
 	}
 }
@@ -878,7 +875,9 @@
 
 static int ide_allocate_dma_engine(ide_hwif_t *hwif)
 {
-	hwif->dmatable_cpu = pci_alloc_consistent(hwif->pci_dev,
+	struct pci_dev *pdev = to_pci_dev(hwif->dev);
+
+	hwif->dmatable_cpu = pci_alloc_consistent(pdev,
 						  PRD_ENTRIES * PRD_BYTES,
 						  &hwif->dmatable_dma);
 
@@ -891,19 +890,19 @@
 	return 1;
 }
 
-static int ide_mapped_mmio_dma(ide_hwif_t *hwif, unsigned long base, unsigned int ports)
+static int ide_mapped_mmio_dma(ide_hwif_t *hwif, unsigned long base)
 {
 	printk(KERN_INFO "    %s: MMIO-DMA ", hwif->name);
 
 	return 0;
 }
 
-static int ide_iomio_dma(ide_hwif_t *hwif, unsigned long base, unsigned int ports)
+static int ide_iomio_dma(ide_hwif_t *hwif, unsigned long base)
 {
 	printk(KERN_INFO "    %s: BM-DMA at 0x%04lx-0x%04lx",
-	       hwif->name, base, base + ports - 1);
+	       hwif->name, base, base + 7);
 
-	if (!request_region(base, ports, hwif->name)) {
+	if (!request_region(base, 8, hwif->name)) {
 		printk(" -- Error, ports in use.\n");
 		return 1;
 	}
@@ -915,7 +914,7 @@
 			if (!request_region(hwif->extra_base,
 					    hwif->cds->extra, hwif->cds->name)) {
 				printk(" -- Error, extra ports in use.\n");
-				release_region(base, ports);
+				release_region(base, 8);
 				return 1;
 			}
 			hwif->extra_ports = hwif->cds->extra;
@@ -925,17 +924,19 @@
 	return 0;
 }
 
-static int ide_dma_iobase(ide_hwif_t *hwif, unsigned long base, unsigned int ports)
+static int ide_dma_iobase(ide_hwif_t *hwif, unsigned long base)
 {
 	if (hwif->mmio)
-		return ide_mapped_mmio_dma(hwif, base,ports);
+		return ide_mapped_mmio_dma(hwif, base);
 
-	return ide_iomio_dma(hwif, base, ports);
+	return ide_iomio_dma(hwif, base);
 }
 
-void ide_setup_dma(ide_hwif_t *hwif, unsigned long base, unsigned num_ports)
+void ide_setup_dma(ide_hwif_t *hwif, unsigned long base)
 {
-	if (ide_dma_iobase(hwif, base, num_ports))
+	u8 dma_stat;
+
+	if (ide_dma_iobase(hwif, base))
 		return;
 
 	if (ide_allocate_dma_engine(hwif)) {
@@ -945,16 +946,16 @@
 
 	hwif->dma_base = base;
 
-	if (!(hwif->dma_command))
-		hwif->dma_command	= hwif->dma_base;
-	if (!(hwif->dma_vendor1))
-		hwif->dma_vendor1	= (hwif->dma_base + 1);
-	if (!(hwif->dma_status))
-		hwif->dma_status	= (hwif->dma_base + 2);
-	if (!(hwif->dma_vendor3))
-		hwif->dma_vendor3	= (hwif->dma_base + 3);
-	if (!(hwif->dma_prdtable))
-		hwif->dma_prdtable	= (hwif->dma_base + 4);
+	if (!hwif->dma_command)
+		hwif->dma_command	= hwif->dma_base + 0;
+	if (!hwif->dma_vendor1)
+		hwif->dma_vendor1	= hwif->dma_base + 1;
+	if (!hwif->dma_status)
+		hwif->dma_status	= hwif->dma_base + 2;
+	if (!hwif->dma_vendor3)
+		hwif->dma_vendor3	= hwif->dma_base + 3;
+	if (!hwif->dma_prdtable)
+		hwif->dma_prdtable	= hwif->dma_base + 4;
 
 	if (!hwif->dma_host_set)
 		hwif->dma_host_set = &ide_dma_host_set;
@@ -973,13 +974,10 @@
 	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);
-		printk(", BIOS settings: %s:%s, %s:%s",
-		       hwif->drives[0].name, (dma_stat & 0x20) ? "DMA" : "pio",
-		       hwif->drives[1].name, (dma_stat & 0x40) ? "DMA" : "pio");
-	}
-	printk("\n");
+	dma_stat = hwif->INB(hwif->dma_status);
+	printk(KERN_CONT ", BIOS settings: %s:%s, %s:%s\n",
+	       hwif->drives[0].name, (dma_stat & 0x20) ? "DMA" : "PIO",
+	       hwif->drives[1].name, (dma_stat & 0x40) ? "DMA" : "PIO");
 }
 
 EXPORT_SYMBOL_GPL(ide_setup_dma);
diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c
index ff8232e..3512637 100644
--- a/drivers/ide/ide-floppy.c
+++ b/drivers/ide/ide-floppy.c
@@ -1,13 +1,12 @@
 /*
- * linux/drivers/ide/ide-floppy.c	Version 0.99	Feb 24 2002
+ * IDE ATAPI floppy driver.
  *
- * Copyright (C) 1996 - 1999 Gadi Oxman <gadio@netvision.net.il>
- * Copyright (C) 2000 - 2002 Paul Bristow <paul@paulbristow.net>
+ * Copyright (C) 1996-1999  Gadi Oxman <gadio@netvision.net.il>
+ * Copyright (C) 2000-2002  Paul Bristow <paul@paulbristow.net>
+ * Copyright (C) 2005       Bartlomiej Zolnierkiewicz
  */
 
 /*
- * IDE ATAPI floppy driver.
- *
  * The driver currently doesn't have any fancy features, just the bare
  * minimum read/write support.
  *
@@ -17,67 +16,8 @@
  * Iomega Zip 100/250
  * Iomega PC Card Clik!/PocketZip
  *
- * Many thanks to Lode Leroy <Lode.Leroy@www.ibase.be>, who tested so many
- * ALPHA patches to this driver on an EASYSTOR LS-120 ATAPI floppy drive.
- *
- * Ver 0.1   Oct 17 96   Initial test version, mostly based on ide-tape.c.
- * Ver 0.2   Oct 31 96   Minor changes.
- * Ver 0.3   Dec  2 96   Fixed error recovery bug.
- * Ver 0.4   Jan 26 97   Add support for the HDIO_GETGEO ioctl.
- * Ver 0.5   Feb 21 97   Add partitions support.
- *                       Use the minimum of the LBA and CHS capacities.
- *                       Avoid hwgroup->rq == NULL on the last irq.
- *                       Fix potential null dereferencing with DEBUG_LOG.
- * Ver 0.8   Dec  7 97   Increase irq timeout from 10 to 50 seconds.
- *                       Add media write-protect detection.
- *                       Issue START command only if TEST UNIT READY fails.
- *                       Add work-around for IOMEGA ZIP revision 21.D.
- *                       Remove idefloppy_get_capabilities().
- * Ver 0.9   Jul  4 99   Fix a bug which might have caused the number of
- *                        bytes requested on each interrupt to be zero.
- *                        Thanks to <shanos@es.co.nz> for pointing this out.
- * Ver 0.9.sv Jan 6 01   Sam Varshavchik <mrsam@courier-mta.com>
- *                       Implement low level formatting.  Reimplemented
- *                       IDEFLOPPY_CAPABILITIES_PAGE, since we need the srfp
- *                       bit.  My LS-120 drive barfs on
- *                       IDEFLOPPY_CAPABILITIES_PAGE, but maybe it's just me.
- *                       Compromise by not reporting a failure to get this
- *                       mode page.  Implemented four IOCTLs in order to
- *                       implement formatting.  IOCTls begin with 0x4600,
- *                       0x46 is 'F' as in Format.
- *            Jan 9 01   Userland option to select format verify.
- *                       Added PC_SUPPRESS_ERROR flag - some idefloppy drives
- *                       do not implement IDEFLOPPY_CAPABILITIES_PAGE, and
- *                       return a sense error.  Suppress error reporting in
- *                       this particular case in order to avoid spurious
- *                       errors in syslog.  The culprit is
- *                       idefloppy_get_capability_page(), so move it to
- *                       idefloppy_begin_format() so that it's not used
- *                       unless absolutely necessary.
- *                       If drive does not support format progress indication
- *                       monitor the dsc bit in the status register.
- *                       Also, O_NDELAY on open will allow the device to be
- *                       opened without a disk available.  This can be used to
- *                       open an unformatted disk, or get the device capacity.
- * Ver 0.91  Dec 11 99   Added IOMEGA Clik! drive support by 
- *     		   <paul@paulbristow.net>
- * Ver 0.92  Oct 22 00   Paul Bristow became official maintainer for this 
- *           		   driver.  Included Powerbook internal zip kludge.
- * Ver 0.93  Oct 24 00   Fixed bugs for Clik! drive
- *                        no disk on insert and disk change now works
- * Ver 0.94  Oct 27 00   Tidied up to remove strstr(Clik) everywhere
- * Ver 0.95  Nov  7 00   Brought across to kernel 2.4
- * Ver 0.96  Jan  7 01   Actually in line with release version of 2.4.0
- *                       including set_bit patch from Rusty Russell
- * Ver 0.97  Jul 22 01   Merge 0.91-0.96 onto 0.9.sv for ac series
- * Ver 0.97.sv Aug 3 01  Backported from 2.4.7-ac3
- * Ver 0.98  Oct 26 01   Split idefloppy_transfer_pc into two pieces to
- *                        fix a lost interrupt problem. It appears the busy
- *                        bit was being deasserted by my IOMEGA ATAPI ZIP 100
- *                        drive before the drive was actually ready.
- * Ver 0.98a Oct 29 01   Expose delay value so we can play.
- * Ver 0.99  Feb 24 02   Remove duplicate code, modify clik! detection code 
- *                        to support new PocketZip drives 
+ * For a historical changelog see
+ * Documentation/ide/ChangeLog.ide-floppy.1996-2002
  */
 
 #define IDEFLOPPY_VERSION "0.99.newide"
@@ -1658,7 +1598,6 @@
 {
 	struct idefloppy_id_gcw gcw;
 #if IDEFLOPPY_DEBUG_INFO
-	u16 mask,i;
 	char buffer[80];
 #endif /* IDEFLOPPY_DEBUG_INFO */
 
@@ -1705,55 +1644,6 @@
 		default: sprintf(buffer, "Reserved");break;
 	}
 	printk(KERN_INFO "Command Packet Size: %s\n", buffer);
-	printk(KERN_INFO "Model: %.40s\n",id->model);
-	printk(KERN_INFO "Firmware Revision: %.8s\n",id->fw_rev);
-	printk(KERN_INFO "Serial Number: %.20s\n",id->serial_no);
-	printk(KERN_INFO "Write buffer size(?): %d bytes\n",id->buf_size*512);
-	printk(KERN_INFO "DMA: %s",id->capability & 0x01 ? "Yes\n":"No\n");
-	printk(KERN_INFO "LBA: %s",id->capability & 0x02 ? "Yes\n":"No\n");
-	printk(KERN_INFO "IORDY can be disabled: %s",id->capability & 0x04 ? "Yes\n":"No\n");
-	printk(KERN_INFO "IORDY supported: %s",id->capability & 0x08 ? "Yes\n":"Unknown\n");
-	printk(KERN_INFO "ATAPI overlap supported: %s",id->capability & 0x20 ? "Yes\n":"No\n");
-	printk(KERN_INFO "PIO Cycle Timing Category: %d\n",id->tPIO);
-	printk(KERN_INFO "DMA Cycle Timing Category: %d\n",id->tDMA);
-	printk(KERN_INFO "Single Word DMA supported modes:\n");
-	for (i=0,mask=1;i<8;i++,mask=mask << 1) {
-		if (id->dma_1word & mask)
-			printk(KERN_INFO "   Mode %d%s\n", i,
-			(id->dma_1word & (mask << 8)) ? " (active)" : "");
-	}
-	printk(KERN_INFO "Multi Word DMA supported modes:\n");
-	for (i=0,mask=1;i<8;i++,mask=mask << 1) {
-		if (id->dma_mword & mask)
-			printk(KERN_INFO "   Mode %d%s\n", i,
-			(id->dma_mword & (mask << 8)) ? " (active)" : "");
-	}
-	if (id->field_valid & 0x0002) {
-		printk(KERN_INFO "Enhanced PIO Modes: %s\n",
-			id->eide_pio_modes & 1 ? "Mode 3":"None");
-		if (id->eide_dma_min == 0)
-			sprintf(buffer, "Not supported");
-		else
-			sprintf(buffer, "%d ns",id->eide_dma_min);
-		printk(KERN_INFO "Minimum Multi-word DMA cycle per word: %s\n", buffer);
-		if (id->eide_dma_time == 0)
-			sprintf(buffer, "Not supported");
-		else
-			sprintf(buffer, "%d ns",id->eide_dma_time);
-		printk(KERN_INFO "Manufacturer\'s Recommended Multi-word cycle: %s\n", buffer);
-		if (id->eide_pio == 0)
-			sprintf(buffer, "Not supported");
-		else
-			sprintf(buffer, "%d ns",id->eide_pio);
-		printk(KERN_INFO "Minimum PIO cycle without IORDY: %s\n",
-			buffer);
-		if (id->eide_pio_iordy == 0)
-			sprintf(buffer, "Not supported");
-		else
-			sprintf(buffer, "%d ns",id->eide_pio_iordy);
-		printk(KERN_INFO "Minimum PIO cycle with IORDY: %s\n", buffer);
-	} else
-		printk(KERN_INFO "According to the device, fields 64-70 are not valid.\n");
 #endif /* IDEFLOPPY_DEBUG_INFO */
 
 	if (gcw.protocol != 2)
diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c
index e6bb9cf..4bddef0 100644
--- a/drivers/ide/ide-io.c
+++ b/drivers/ide/ide-io.c
@@ -1487,7 +1487,7 @@
 		 * remove all the ifdef PCI crap
 		 */
 #ifdef CONFIG_BLK_DEV_IDEPCI
-		if (hwif->pci_dev && !hwif->pci_dev->vendor)
+		if (hwif->chipset != ide_pci)
 #endif	/* CONFIG_BLK_DEV_IDEPCI */
 		{
 			/*
diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c
index e2a7e95..16b1f6e 100644
--- a/drivers/ide/ide-iops.c
+++ b/drivers/ide/ide-iops.c
@@ -1,6 +1,4 @@
 /*
- * linux/drivers/ide/ide-iops.c	Version 0.37	Mar 05, 2003
- *
  *  Copyright (C) 2000-2002	Andre Hedrick <andre@linux-ide.org>
  *  Copyright (C) 2003		Red Hat <alan@redhat.com>
  *
@@ -1168,7 +1166,7 @@
 
 /*
  * ide_wait_not_busy() waits for the currently selected device on the hwif
- * to report a non-busy status, see comments in probe_hwif().
+ * to report a non-busy status, see comments in ide_probe_port().
  */
 int ide_wait_not_busy(ide_hwif_t *hwif, unsigned long timeout)
 {
diff --git a/drivers/ide/ide-lib.c b/drivers/ide/ide-lib.c
index 9b44fbd..b42940d 100644
--- a/drivers/ide/ide-lib.c
+++ b/drivers/ide/ide-lib.c
@@ -358,8 +358,10 @@
 	if (!PCI_DMA_BUS_IS_PHYS) {
 		addr = BLK_BOUNCE_ANY;
 	} else if (on && drive->media == ide_disk) {
-		if (HWIF(drive)->pci_dev)
-			addr = HWIF(drive)->pci_dev->dma_mask;
+		struct device *dev = drive->hwif->dev;
+
+		if (dev && dev->dma_mask)
+			addr = *dev->dma_mask;
 	}
 
 	if (drive->queue)
diff --git a/drivers/ide/ide-pnp.c b/drivers/ide/ide-pnp.c
index cbbb0f7..4bda5cf 100644
--- a/drivers/ide/ide-pnp.c
+++ b/drivers/ide/ide-pnp.c
@@ -1,6 +1,4 @@
 /*
- * linux/drivers/ide/ide-pnp.c
- *
  * This file provides autodetection for ISA PnP IDE interfaces.
  * It was tested with "ESS ES1868 Plug and Play AudioDrive" IDE interface.
  *
diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c
index edf650b..98a8af4 100644
--- a/drivers/ide/ide-probe.c
+++ b/drivers/ide/ide-probe.c
@@ -1,7 +1,6 @@
 /*
- *  linux/drivers/ide/ide-probe.c	Version 1.11	Mar 05, 2003
- *
- *  Copyright (C) 1994-1998  Linus Torvalds & authors (see below)
+ *  Copyright (C) 1994-1998   Linus Torvalds & authors (see below)
+ *  Copyright (C) 2005, 2007  Bartlomiej Zolnierkiewicz
  */
 
 /*
@@ -129,6 +128,10 @@
 
 	drive->id_read = 1;
 	local_irq_enable();
+#ifdef DEBUG
+	printk(KERN_INFO "%s: dumping identify data\n", drive->name);
+	ide_dump_identify((u8 *)id);
+#endif
 	ide_fix_driveid(id);
 
 #if defined (CONFIG_SCSI_EATA_PIO) || defined (CONFIG_SCSI_EATA)
@@ -610,7 +613,7 @@
 	complete(&hwif->gendev_rel_comp);
 }
 
-static void hwif_register (ide_hwif_t *hwif)
+static void ide_register_port(ide_hwif_t *hwif)
 {
 	int ret;
 
@@ -618,8 +621,8 @@
 	strlcpy(hwif->gendev.bus_id,hwif->name,BUS_ID_SIZE);
 	hwif->gendev.driver_data = hwif;
 	if (hwif->gendev.parent == NULL) {
-		if (hwif->pci_dev)
-			hwif->gendev.parent = &hwif->pci_dev->dev;
+		if (hwif->dev)
+			hwif->gendev.parent = hwif->dev;
 		else
 			/* Would like to do = &device_legacy */
 			hwif->gendev.parent = NULL;
@@ -631,7 +634,33 @@
 			__FUNCTION__, ret);
 }
 
-static int wait_hwif_ready(ide_hwif_t *hwif)
+/**
+ *	ide_port_wait_ready	-	wait for port to become ready
+ *	@hwif: IDE port
+ *
+ *	This is needed on some PPCs and a bunch of BIOS-less embedded
+ *	platforms.  Typical cases are:
+ *
+ *	- The firmware hard reset the disk before booting the kernel,
+ *	  the drive is still doing it's poweron-reset sequence, that
+ *	  can take up to 30 seconds.
+ *
+ *	- The firmware does nothing (or no firmware), the device is
+ *	  still in POST state (same as above actually).
+ *
+ *	- Some CD/DVD/Writer combo drives tend to drive the bus during
+ *	  their reset sequence even when they are non-selected slave
+ *	  devices, thus preventing discovery of the main HD.
+ *
+ *	Doing this wait-for-non-busy should not harm any existing
+ *	configuration and fix some issues like the above.
+ *
+ *	BenH.
+ *
+ *	Returns 0 on success, error code (< 0) otherwise.
+ */
+
+static int ide_port_wait_ready(ide_hwif_t *hwif)
 {
 	int unit, rc;
 
@@ -709,36 +738,16 @@
 
 EXPORT_SYMBOL_GPL(ide_undecoded_slave);
 
-/*
- * 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 int ide_probe_port(ide_hwif_t *hwif)
 {
 	unsigned long flags;
 	unsigned int irqd;
-	int unit;
+	int unit, rc = -ENODEV;
+
+	BUG_ON(hwif->present);
 
 	if (hwif->noprobe)
-		return;
-
-	if ((hwif->chipset != ide_4drives || !hwif->mate || !hwif->mate->present) &&
-	    (ide_hwif_request_regions(hwif))) {
-		u16 msgout = 0;
-		for (unit = 0; unit < MAX_DRIVES; ++unit) {
-			ide_drive_t *drive = &hwif->drives[unit];
-			if (drive->present) {
-				drive->present = 0;
-				printk(KERN_ERR "%s: ERROR, PORTS ALREADY IN USE\n",
-					drive->name);
-				msgout = 1;
-			}
-		}
-		if (!msgout)
-			printk(KERN_ERR "%s: ports already in use, skipping probe\n",
-				hwif->name);
-		return;	
-	}
+		return -EACCES;
 
 	/*
 	 * We must always disable IRQ, as probe_for_drive will assert IRQ, but
@@ -750,26 +759,7 @@
 
 	local_irq_set(flags);
 
-	/* This is needed on some PPCs and a bunch of BIOS-less embedded
-	 * platforms. Typical cases are:
-	 * 
-	 *  - The firmware hard reset the disk before booting the kernel,
-	 *    the drive is still doing it's poweron-reset sequence, that
-	 *    can take up to 30 seconds
-	 *  - The firmware does nothing (or no firmware), the device is
-	 *    still in POST state (same as above actually).
-	 *  - Some CD/DVD/Writer combo drives tend to drive the bus during
-	 *    their reset sequence even when they are non-selected slave
-	 *    devices, thus preventing discovery of the main HD
-	 *    
-	 *  Doing this wait-for-busy should not harm any existing configuration
-	 *  (at least things won't be worse than what current code does, that
-	 *  is blindly go & talk to the drive) and fix some issues like the
-	 *  above.
-	 *  
-	 *  BenH.
-	 */
-	if (wait_hwif_ready(hwif) == -EBUSY)
+	if (ide_port_wait_ready(hwif) == -EBUSY)
 		printk(KERN_DEBUG "%s: Wait for ready failed before probe !\n", hwif->name);
 
 	/*
@@ -779,14 +769,8 @@
 		ide_drive_t *drive = &hwif->drives[unit];
 		drive->dn = (hwif->channel ? 2 : 0) + unit;
 		(void) probe_for_drive(drive);
-		if (drive->present && !hwif->present) {
-			hwif->present = 1;
-			if (hwif->chipset != ide_4drives ||
-			    !hwif->mate || 
-			    !hwif->mate->present) {
-				hwif_register(hwif);
-			}
-		}
+		if (drive->present)
+			rc = 0;
 	}
 	if (hwif->io_ports[IDE_CONTROL_OFFSET] && hwif->reset) {
 		printk(KERN_WARNING "%s: reset\n", hwif->name);
@@ -803,10 +787,12 @@
 	if (irqd)
 		enable_irq(irqd);
 
-	if (!hwif->present) {
-		ide_hwif_release_regions(hwif);
-		return;
-	}
+	return rc;
+}
+
+static void ide_port_tune_devices(ide_hwif_t *hwif)
+{
+	int unit;
 
 	for (unit = 0; unit < MAX_DRIVES; unit++) {
 		ide_drive_t *drive = &hwif->drives[unit];
@@ -997,21 +983,17 @@
 		spin_lock_irq(&ide_lock);
 		hwif->next = hwgroup->hwif->next;
 		hwgroup->hwif->next = hwif;
+		BUG_ON(hwif->next == hwif);
 		spin_unlock_irq(&ide_lock);
 	} else {
-		hwgroup = kmalloc_node(sizeof(ide_hwgroup_t),
-					GFP_KERNEL | __GFP_ZERO,
-					hwif_to_node(hwif->drives[0].hwif));
-		if (!hwgroup)
-	       		goto out_up;
+		hwgroup = kmalloc_node(sizeof(*hwgroup), GFP_KERNEL|__GFP_ZERO,
+				       hwif_to_node(hwif));
+		if (hwgroup == NULL)
+			goto out_up;
 
 		hwif->hwgroup = hwgroup;
+		hwgroup->hwif = hwif->next = hwif;
 
-		hwgroup->hwif     = hwif->next = hwif;
-		hwgroup->rq       = NULL;
-		hwgroup->handler  = NULL;
-		hwgroup->drive    = NULL;
-		hwgroup->busy     = 0;
 		init_timer(&hwgroup->timer);
 		hwgroup->timer.function = &ide_timer_expiry;
 		hwgroup->timer.data = (unsigned long) hwgroup;
@@ -1079,25 +1061,7 @@
 	mutex_unlock(&ide_cfg_mtx);
 	return 0;
 out_unlink:
-	spin_lock_irq(&ide_lock);
-	if (hwif->next == hwif) {
-		BUG_ON(match);
-		BUG_ON(hwgroup->hwif != hwif);
-		kfree(hwgroup);
-	} else {
-		ide_hwif_t *g;
-		g = hwgroup->hwif;
-		while (g->next != hwif)
-			g = g->next;
-		g->next = hwif->next;
-		if (hwgroup->hwif == hwif) {
-			/* Impossible. */
-			printk(KERN_ERR "Duh. Uninitialized hwif listed as active hwif.\n");
-			hwgroup->hwif = g;
-		}
-		BUG_ON(hwgroup->hwif == hwif);
-	}
-	spin_unlock_irq(&ide_lock);
+	ide_remove_port_from_hwgroup(hwif);
 out_up:
 	mutex_unlock(&ide_cfg_mtx);
 	return 1;
@@ -1246,28 +1210,21 @@
 {
 	int old_irq;
 
-	/* Return success if no device is connected */
-	if (!hwif->present)
-		return 1;
-
 	if (!hwif->irq) {
 		if (!(hwif->irq = ide_default_irq(hwif->io_ports[IDE_DATA_OFFSET])))
 		{
 			printk("%s: DISABLED, NO IRQ\n", hwif->name);
-			return (hwif->present = 0);
+			return 0;
 		}
 	}
 #ifdef CONFIG_BLK_DEV_HD
 	if (hwif->irq == HD_IRQ && hwif->io_ports[IDE_DATA_OFFSET] != HD_DATA) {
 		printk("%s: CANNOT SHARE IRQ WITH OLD "
 			"HARDDISK DRIVER (hd.c)\n", hwif->name);
-		return (hwif->present = 0);
+		return 0;
 	}
 #endif /* CONFIG_BLK_DEV_HD */
 
-	/* we set it back to 1 if all is ok below */	
-	hwif->present = 0;
-
 	if (register_blkdev(hwif->major, hwif->name))
 		return 0;
 
@@ -1306,10 +1263,7 @@
 
 done:
 	init_gendisk(hwif);
-
 	ide_acpi_init(hwif);
-
-	hwif->present = 1;	/* success */
 	return 1;
 
 out:
@@ -1344,7 +1298,27 @@
 		if (idx[i] == 0xff)
 			continue;
 
-		probe_hwif(&ide_hwifs[idx[i]]);
+		hwif = &ide_hwifs[idx[i]];
+
+		if ((hwif->chipset != ide_4drives || !hwif->mate ||
+		     !hwif->mate->present) && ide_hwif_request_regions(hwif)) {
+			printk(KERN_ERR "%s: ports already in use, "
+					"skipping probe\n", hwif->name);
+			continue;
+		}
+
+		if (ide_probe_port(hwif) < 0) {
+			ide_hwif_release_regions(hwif);
+			continue;
+		}
+
+		hwif->present = 1;
+
+		if (hwif->chipset != ide_4drives || !hwif->mate ||
+		    !hwif->mate->present)
+			ide_register_port(hwif);
+
+		ide_port_tune_devices(hwif);
 	}
 
 	for (i = 0; i < MAX_HWIFS; i++) {
@@ -1353,9 +1327,13 @@
 
 		hwif = &ide_hwifs[idx[i]];
 
+		if (!hwif->present)
+			continue;
+
 		if (hwif_init(hwif) == 0) {
 			printk(KERN_INFO "%s: failed to initialize IDE "
 					 "interface\n", hwif->name);
+			hwif->present = 0;
 			rc = -1;
 			continue;
 		}
diff --git a/drivers/ide/ide-proc.c b/drivers/ide/ide-proc.c
index aa663e7..00c249c 100644
--- a/drivers/ide/ide-proc.c
+++ b/drivers/ide/ide-proc.c
@@ -1,6 +1,4 @@
 /*
- *  linux/drivers/ide/ide-proc.c	Version 1.05	Mar 05, 2003
- *
  *  Copyright (C) 1997-1998	Mark Lord
  *  Copyright (C) 2003		Red Hat <alan@redhat.com>
  *
diff --git a/drivers/ide/ide-scan-pci.c b/drivers/ide/ide-scan-pci.c
index 7ffa332..93d2e41 100644
--- a/drivers/ide/ide-scan-pci.c
+++ b/drivers/ide/ide-scan-pci.c
@@ -81,7 +81,7 @@
  *	module ordering not traditionally ordered.
  */
 
-int __init ide_scan_pcibus(void)
+static int __init ide_scan_pcibus(void)
 {
 	struct pci_dev *dev = NULL;
 	struct pci_driver *d;
@@ -113,9 +113,4 @@
 	return 0;
 }
 
-static int __init ide_scan_pci(void)
-{
-	return ide_scan_pcibus();
-}
-
-module_init(ide_scan_pci);
+module_init(ide_scan_pcibus);
diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c
index d71a584..5aef63a 100644
--- a/drivers/ide/ide-tape.c
+++ b/drivers/ide/ide-tape.c
@@ -1,7 +1,6 @@
 /*
- * linux/drivers/ide/ide-tape.c		Version 1.19	Nov, 2003
- *
- * Copyright (C) 1995 - 1999 Gadi Oxman <gadio@netvision.net.il>
+ * Copyright (C) 1995-1999  Gadi Oxman <gadio@netvision.net.il>
+ * Copyright (C) 2003-2005  Bartlomiej Zolnierkiewicz
  *
  * $Header$
  *
@@ -4291,9 +4290,6 @@
 {
 	struct idetape_id_gcw gcw;
 	struct hd_driveid *id = drive->id;
-#if IDETAPE_DEBUG_INFO
-	unsigned short mask,i;
-#endif /* IDETAPE_DEBUG_INFO */
 
 	if (drive->id_read == 0)
 		return 1;
@@ -4333,62 +4329,6 @@
 		case 1: printk("16 bytes\n");break;
 		default: printk("Reserved\n");break;
 	}
-	printk(KERN_INFO "ide-tape: Model: %.40s\n",id->model);
-	printk(KERN_INFO "ide-tape: Firmware Revision: %.8s\n",id->fw_rev);
-	printk(KERN_INFO "ide-tape: Serial Number: %.20s\n",id->serial_no);
-	printk(KERN_INFO "ide-tape: Write buffer size: %d bytes\n",id->buf_size*512);
-	printk(KERN_INFO "ide-tape: DMA: %s",id->capability & 0x01 ? "Yes\n":"No\n");
-	printk(KERN_INFO "ide-tape: LBA: %s",id->capability & 0x02 ? "Yes\n":"No\n");
-	printk(KERN_INFO "ide-tape: IORDY can be disabled: %s",id->capability & 0x04 ? "Yes\n":"No\n");
-	printk(KERN_INFO "ide-tape: IORDY supported: %s",id->capability & 0x08 ? "Yes\n":"Unknown\n");
-	printk(KERN_INFO "ide-tape: ATAPI overlap supported: %s",id->capability & 0x20 ? "Yes\n":"No\n");
-	printk(KERN_INFO "ide-tape: PIO Cycle Timing Category: %d\n",id->tPIO);
-	printk(KERN_INFO "ide-tape: DMA Cycle Timing Category: %d\n",id->tDMA);
-	printk(KERN_INFO "ide-tape: Single Word DMA supported modes: ");
-	for (i=0,mask=1;i<8;i++,mask=mask << 1) {
-		if (id->dma_1word & mask)
-			printk("%d ",i);
-		if (id->dma_1word & (mask << 8))
-			printk("(active) ");
-	}
-	printk("\n");
-	printk(KERN_INFO "ide-tape: Multi Word DMA supported modes: ");
-	for (i=0,mask=1;i<8;i++,mask=mask << 1) {
-		if (id->dma_mword & mask)
-			printk("%d ",i);
-		if (id->dma_mword & (mask << 8))
-			printk("(active) ");
-	}
-	printk("\n");
-	if (id->field_valid & 0x0002) {
-		printk(KERN_INFO "ide-tape: Enhanced PIO Modes: %s\n",
-			id->eide_pio_modes & 1 ? "Mode 3":"None");
-		printk(KERN_INFO "ide-tape: Minimum Multi-word DMA cycle per word: ");
-		if (id->eide_dma_min == 0)
-			printk("Not supported\n");
-		else
-			printk("%d ns\n",id->eide_dma_min);
-
-		printk(KERN_INFO "ide-tape: Manufacturer\'s Recommended Multi-word cycle: ");
-		if (id->eide_dma_time == 0)
-			printk("Not supported\n");
-		else
-			printk("%d ns\n",id->eide_dma_time);
-
-		printk(KERN_INFO "ide-tape: Minimum PIO cycle without IORDY: ");
-		if (id->eide_pio == 0)
-			printk("Not supported\n");
-		else
-			printk("%d ns\n",id->eide_pio);
-
-		printk(KERN_INFO "ide-tape: Minimum PIO cycle with IORDY: ");
-		if (id->eide_pio_iordy == 0)
-			printk("Not supported\n");
-		else
-			printk("%d ns\n",id->eide_pio_iordy);
-		
-	} else
-		printk(KERN_INFO "ide-tape: According to the device, fields 64-70 are not valid.\n");
 #endif /* IDETAPE_DEBUG_INFO */
 
 	/* Check that we can support this device */
@@ -4591,19 +4531,11 @@
 
 	spin_lock_init(&tape->spinlock);
 	drive->dsc_overlap = 1;
-#ifdef CONFIG_BLK_DEV_IDEPCI
-	if (HWIF(drive)->pci_dev != NULL) {
-		/*
-		 * These two ide-pci host adapters appear to need DSC overlap disabled.
-		 * This probably needs further analysis.
-		 */
-		if ((HWIF(drive)->pci_dev->device == PCI_DEVICE_ID_ARTOP_ATP850UF) ||
-		    (HWIF(drive)->pci_dev->device == PCI_DEVICE_ID_TTI_HPT343)) {
-			printk(KERN_INFO "ide-tape: %s: disabling DSC overlap\n", tape->name);
-		    	drive->dsc_overlap = 0;
-		}
+	if (drive->hwif->host_flags & IDE_HFLAG_NO_DSC) {
+		printk(KERN_INFO "ide-tape: %s: disabling DSC overlap\n",
+				 tape->name);
+		drive->dsc_overlap = 0;
 	}
-#endif /* CONFIG_BLK_DEV_IDEPCI */
 	/* Seagate Travan drives do not support DSC overlap. */
 	if (strstr(drive->id->model, "Seagate STT3401"))
 		drive->dsc_overlap = 0;
diff --git a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c
index 5eb6fa1..16a9a58 100644
--- a/drivers/ide/ide-taskfile.c
+++ b/drivers/ide/ide-taskfile.c
@@ -1,11 +1,9 @@
 /*
- * linux/drivers/ide/ide-taskfile.c	Version 0.38	March 05, 2003
- *
- *  Copyright (C) 2000-2002	Michael Cornwell <cornwell@acm.org>
- *  Copyright (C) 2000-2002	Andre Hedrick <andre@linux-ide.org>
- *  Copyright (C) 2001-2002	Klaus Smolin
+ *  Copyright (C) 2000-2002	   Michael Cornwell <cornwell@acm.org>
+ *  Copyright (C) 2000-2002	   Andre Hedrick <andre@linux-ide.org>
+ *  Copyright (C) 2001-2002	   Klaus Smolin
  *					IBM Storage Technology Division
- *  Copyright (C) 2003-2004	Bartlomiej Zolnierkiewicz
+ *  Copyright (C) 2003-2004, 2007  Bartlomiej Zolnierkiewicz
  *
  *  The big the bad and the ugly.
  */
@@ -260,7 +258,7 @@
 	return ide_stopped;
 }
 
-u8 wait_drive_not_busy(ide_drive_t *drive)
+static u8 wait_drive_not_busy(ide_drive_t *drive)
 {
 	ide_hwif_t *hwif = HWIF(drive);
 	int retries;
diff --git a/drivers/ide/ide-timing.h b/drivers/ide/ide-timing.h
index daffbb9..adeda76 100644
--- a/drivers/ide/ide-timing.h
+++ b/drivers/ide/ide-timing.h
@@ -2,8 +2,6 @@
 #define _IDE_TIMING_H
 
 /*
- * $Id: ide-timing.h,v 1.6 2001/12/23 22:47:56 vojtech Exp $
- *
  *  Copyright (c) 1999-2001 Vojtech Pavlik
  */
 
diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c
index 97894ab..ab9ca2b 100644
--- a/drivers/ide/ide.c
+++ b/drivers/ide/ide.c
@@ -1,7 +1,6 @@
 /*
- *  linux/drivers/ide/ide.c		Version 7.00beta2	Mar 05 2003
- *
- *  Copyright (C) 1994-1998  Linus Torvalds & authors (see below)
+ *  Copyright (C) 1994-1998	    Linus Torvalds & authors (see below)
+ *  Copyrifht (C) 2003-2005, 2007   Bartlomiej Zolnierkiewicz
  */
 
 /*
@@ -46,7 +45,6 @@
  */
 
 #define	REVISION	"Revision: 7.00alpha2"
-#define	VERSION		"Id: ide.c 7.00a2 20020906"
 
 #define _IDE_C			/* Tell ide.h it's really us */
 
@@ -242,22 +240,12 @@
 #define pci_default 0
 #endif /* CONFIG_PCI */
 
-	if (!system_bus_speed) {
-		if (idebus_parameter) {
-			/* user supplied value */
-			system_bus_speed = idebus_parameter;
-		} else if (pci_dev_present(pci_default)) {
-			/* safe default value for PCI */
-			system_bus_speed = 33;
-		} else {
-			/* safe default value for VESA and PCI */
-			system_bus_speed = 50;
-		}
-		printk(KERN_INFO "ide: Assuming %dMHz system bus speed "
-			"for PIO modes%s\n", system_bus_speed,
-			idebus_parameter ? "" : "; override with idebus=xx");
-	}
-	return system_bus_speed;
+	/* user supplied value */
+	if (idebus_parameter)
+		return idebus_parameter;
+
+	/* safe default value for PCI or VESA and PCI*/
+	return pci_dev_present(pci_default) ? 33 : 50;
 }
 
 ide_hwif_t * ide_find_port(unsigned long base)
@@ -405,8 +393,9 @@
 	hwif->chipset			= tmp_hwif->chipset;
 	hwif->hold			= tmp_hwif->hold;
 
+	hwif->dev			= tmp_hwif->dev;
+
 #ifdef CONFIG_BLK_DEV_IDEPCI
-	hwif->pci_dev			= tmp_hwif->pci_dev;
 	hwif->cds			= tmp_hwif->cds;
 #endif
 
@@ -472,6 +461,41 @@
 	hwif->hwif_data			= tmp_hwif->hwif_data;
 }
 
+void ide_remove_port_from_hwgroup(ide_hwif_t *hwif)
+{
+	ide_hwgroup_t *hwgroup = hwif->hwgroup;
+
+	spin_lock_irq(&ide_lock);
+	/*
+	 * Remove us from the hwgroup, and free
+	 * the hwgroup if we were the only member
+	 */
+	if (hwif->next == hwif) {
+		BUG_ON(hwgroup->hwif != hwif);
+		kfree(hwgroup);
+	} else {
+		/* There is another interface in hwgroup.
+		 * Unlink us, and set hwgroup->drive and ->hwif to
+		 * something sane.
+		 */
+		ide_hwif_t *g = hwgroup->hwif;
+
+		while (g->next != hwif)
+			g = g->next;
+		g->next = hwif->next;
+		if (hwgroup->hwif == hwif) {
+			/* Chose a random hwif for hwgroup->hwif.
+			 * It's guaranteed that there are no drives
+			 * left in the hwgroup.
+			 */
+			BUG_ON(hwgroup->drive != NULL);
+			hwgroup->hwif = g;
+		}
+		BUG_ON(hwgroup->hwif == hwif);
+	}
+	spin_unlock_irq(&ide_lock);
+}
+
 /**
  *	ide_unregister		-	free an IDE interface
  *	@index: index of interface (will change soon to a pointer)
@@ -539,43 +563,8 @@
 	if (irq_count == 1)
 		free_irq(hwif->irq, hwgroup);
 
-	spin_lock_irq(&ide_lock);
-	/*
-	 * Note that we only release the standard ports,
-	 * and do not even try to handle any extra ports
-	 * allocated for weird IDE interface chipsets.
-	 */
-	ide_hwif_release_regions(hwif);
+	ide_remove_port_from_hwgroup(hwif);
 
-	/*
-	 * Remove us from the hwgroup, and free
-	 * the hwgroup if we were the only member
-	 */
-	if (hwif->next == hwif) {
-		BUG_ON(hwgroup->hwif != hwif);
-		kfree(hwgroup);
-	} else {
-		/* There is another interface in hwgroup.
-		 * Unlink us, and set hwgroup->drive and ->hwif to
-		 * something sane.
-		 */
-		g = hwgroup->hwif;
-		while (g->next != hwif)
-			g = g->next;
-		g->next = hwif->next;
-		if (hwgroup->hwif == hwif) {
-			/* Chose a random hwif for hwgroup->hwif.
-			 * It's guaranteed that there are no drives
-			 * left in the hwgroup.
-			 */
-			BUG_ON(hwgroup->drive != NULL);
-			hwgroup->hwif = g;
-		}
-		BUG_ON(hwgroup->hwif == hwif);
-	}
-
-	/* More messed up locking ... */
-	spin_unlock_irq(&ide_lock);
 	device_unregister(&hwif->gendev);
 	wait_for_completion(&hwif->gendev_rel_comp);
 
@@ -601,6 +590,13 @@
 		hwif->extra_ports = 0;
 	}
 
+	/*
+	 * Note that we only release the standard ports,
+	 * and do not even try to handle any extra ports
+	 * allocated for weird IDE interface chipsets.
+	 */
+	ide_hwif_release_regions(hwif);
+
 	/* copy original settings */
 	tmp_hwif = *hwif;
 
@@ -913,7 +909,7 @@
 
 int system_bus_clock (void)
 {
-	return((int) ((!system_bus_speed) ? ide_system_bus_speed() : system_bus_speed ));
+	return system_bus_speed;
 }
 
 EXPORT_SYMBOL(system_bus_clock);
@@ -1668,6 +1664,10 @@
 	printk(KERN_INFO "Uniform Multi-Platform E-IDE driver " REVISION "\n");
 	system_bus_speed = ide_system_bus_speed();
 
+	printk(KERN_INFO "ide: Assuming %dMHz system bus speed "
+			 "for PIO modes%s\n", system_bus_speed,
+			idebus_parameter ? "" : "; override with idebus=xx");
+
 	ret = bus_register(&ide_bus_type);
 	if (ret < 0) {
 		printk(KERN_WARNING "IDE: bus_register error: %d\n", ret);
diff --git a/drivers/ide/legacy/ali14xx.c b/drivers/ide/legacy/ali14xx.c
index 5ec0be4..e3ea209 100644
--- a/drivers/ide/legacy/ali14xx.c
+++ b/drivers/ide/legacy/ali14xx.c
@@ -1,6 +1,4 @@
 /*
- *  linux/drivers/ide/legacy/ali14xx.c		Version 0.03	Feb 09, 1996
- *
  *  Copyright (C) 1996  Linus Torvalds & author (see below)
  */
 
diff --git a/drivers/ide/legacy/buddha.c b/drivers/ide/legacy/buddha.c
index 74d28e0..dd3d198 100644
--- a/drivers/ide/legacy/buddha.c
+++ b/drivers/ide/legacy/buddha.c
@@ -1,5 +1,5 @@
 /*
- *  linux/drivers/ide/legacy/buddha.c -- Amiga Buddha, Catweasel and X-Surf IDE Driver
+ *  Amiga Buddha, Catweasel and X-Surf IDE Driver
  *
  *	Copyright (C) 1997, 2001 by Geert Uytterhoeven and others
  *
diff --git a/drivers/ide/legacy/dtc2278.c b/drivers/ide/legacy/dtc2278.c
index 13eee6d..611c970 100644
--- a/drivers/ide/legacy/dtc2278.c
+++ b/drivers/ide/legacy/dtc2278.c
@@ -1,6 +1,4 @@
 /*
- *  linux/drivers/ide/legacy/dtc2278.c		Version 0.02	Feb 10, 1996
- *
  *  Copyright (C) 1996  Linus Torvalds & author (see below)
  */
 
diff --git a/drivers/ide/legacy/falconide.c b/drivers/ide/legacy/falconide.c
index 2860956..c9bd6bf 100644
--- a/drivers/ide/legacy/falconide.c
+++ b/drivers/ide/legacy/falconide.c
@@ -1,5 +1,5 @@
 /*
- *  linux/drivers/ide/legacy/falconide.c -- Atari Falcon IDE Driver
+ *  Atari Falcon IDE Driver
  *
  *     Created 12 Jul 1997 by Geert Uytterhoeven
  *
@@ -66,6 +66,7 @@
 {
     if (MACH_IS_ATARI && ATARIHW_PRESENT(IDE)) {
 	hw_regs_t hw;
+	ide_hwif_t *hwif;
 
 	printk(KERN_INFO "ide: Falcon IDE controller\n");
 
diff --git a/drivers/ide/legacy/gayle.c b/drivers/ide/legacy/gayle.c
index 492fa04..f67c51a 100644
--- a/drivers/ide/legacy/gayle.c
+++ b/drivers/ide/legacy/gayle.c
@@ -1,5 +1,5 @@
 /*
- *  linux/drivers/ide/legacy/gayle.c -- Amiga Gayle IDE Driver
+ *  Amiga Gayle IDE Driver
  *
  *     Created 9 Jul 1997 by Geert Uytterhoeven
  *
diff --git a/drivers/ide/legacy/ht6560b.c b/drivers/ide/legacy/ht6560b.c
index 8da5031..57bc15c 100644
--- a/drivers/ide/legacy/ht6560b.c
+++ b/drivers/ide/legacy/ht6560b.c
@@ -1,6 +1,4 @@
 /*
- *  linux/drivers/ide/legacy/ht6560b.c		Version 0.07	Feb  1, 2000
- *
  *  Copyright (C) 1995-2000  Linus Torvalds & author (see below)
  */
 
diff --git a/drivers/ide/legacy/ide-cs.c b/drivers/ide/legacy/ide-cs.c
index f4ea15b..3bd2967 100644
--- a/drivers/ide/legacy/ide-cs.c
+++ b/drivers/ide/legacy/ide-cs.c
@@ -2,8 +2,6 @@
 
     A driver for PCMCIA IDE/ATA disk cards
 
-    ide-cs.c 1.3 2002/10/26 05:45:31
-
     The contents of this file are subject to the Mozilla Public
     License Version 1.1 (the "License"); you may not use this file
     except in compliance with the License. You may obtain a copy of
diff --git a/drivers/ide/legacy/ide_platform.c b/drivers/ide/legacy/ide_platform.c
index 69a0fb0..7c3231a 100644
--- a/drivers/ide/legacy/ide_platform.c
+++ b/drivers/ide/legacy/ide_platform.c
@@ -21,13 +21,6 @@
 #include <linux/platform_device.h>
 #include <linux/io.h>
 
-static struct {
-	void __iomem *plat_ide_mapbase;
-	void __iomem *plat_ide_alt_mapbase;
-	ide_hwif_t *hwif;
-	int index;
-} hwif_prop;
-
 static void __devinit plat_ide_setup_ports(hw_regs_t *hw,
 					   void __iomem *base,
 					   void __iomem *ctrl,
@@ -54,6 +47,7 @@
 static int __devinit plat_ide_probe(struct platform_device *pdev)
 {
 	struct resource *res_base, *res_alt, *res_irq;
+	void __iomem *base, *alt_base;
 	ide_hwif_t *hwif;
 	struct pata_platform_info *pdata;
 	u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
@@ -84,27 +78,25 @@
 	}
 
 	if (mmio) {
-		hwif_prop.plat_ide_mapbase = devm_ioremap(&pdev->dev,
+		base = devm_ioremap(&pdev->dev,
 			res_base->start, res_base->end - res_base->start + 1);
-		hwif_prop.plat_ide_alt_mapbase = devm_ioremap(&pdev->dev,
+		alt_base = devm_ioremap(&pdev->dev,
 			res_alt->start, res_alt->end - res_alt->start + 1);
 	} else {
-		hwif_prop.plat_ide_mapbase = devm_ioport_map(&pdev->dev,
+		base = devm_ioport_map(&pdev->dev,
 			res_base->start, res_base->end - res_base->start + 1);
-		hwif_prop.plat_ide_alt_mapbase = devm_ioport_map(&pdev->dev,
+		alt_base = devm_ioport_map(&pdev->dev,
 			res_alt->start, res_alt->end - res_alt->start + 1);
 	}
 
-	hwif = ide_find_port((unsigned long)hwif_prop.plat_ide_mapbase);
+	hwif = ide_find_port((unsigned long)base);
 	if (!hwif) {
 		ret = -ENODEV;
 		goto out;
 	}
 
 	memset(&hw, 0, sizeof(hw));
-	plat_ide_setup_ports(&hw, hwif_prop.plat_ide_mapbase,
-			     hwif_prop.plat_ide_alt_mapbase,
-			     pdata, res_irq->start);
+	plat_ide_setup_ports(&hw, base, alt_base, pdata, res_irq->start);
 	hw.dev = &pdev->dev;
 
 	ide_init_port_hw(hwif, &hw);
@@ -114,9 +106,6 @@
 		default_hwif_mmiops(hwif);
 	}
 
-	hwif_prop.hwif = hwif;
-	hwif_prop.index = hwif->index;
-
 	idx[0] = hwif->index;
 
 	ide_device_add(idx);
@@ -133,14 +122,7 @@
 {
 	ide_hwif_t *hwif = pdev->dev.driver_data;
 
-	if (hwif != hwif_prop.hwif) {
-		dev_printk(KERN_DEBUG, &pdev->dev, "%s: hwif value error",
-		           pdev->name);
-	} else {
-		ide_unregister(hwif_prop.index);
-		hwif_prop.index = 0;
-		hwif_prop.hwif = NULL;
-	}
+	ide_unregister(hwif->index);
 
 	return 0;
 }
diff --git a/drivers/ide/legacy/macide.c b/drivers/ide/legacy/macide.c
index 782d4c7..c54d07f 100644
--- a/drivers/ide/legacy/macide.c
+++ b/drivers/ide/legacy/macide.c
@@ -1,5 +1,5 @@
 /*
- *  linux/drivers/ide/legacy/macide.c -- Macintosh IDE Driver
+ *  Macintosh IDE Driver
  *
  *     Copyright (C) 1998 by Michael Schmitz
  *
diff --git a/drivers/ide/legacy/q40ide.c b/drivers/ide/legacy/q40ide.c
index f532973..a9c6b06 100644
--- a/drivers/ide/legacy/q40ide.c
+++ b/drivers/ide/legacy/q40ide.c
@@ -1,5 +1,5 @@
 /*
- *  linux/drivers/ide/legacy/q40ide.c -- Q40 I/O port IDE Driver
+ *  Q40 I/O port IDE Driver
  *
  *     (c) Richard Zidlicky
  *
diff --git a/drivers/ide/legacy/qd65xx.c b/drivers/ide/legacy/qd65xx.c
index 2bac4c1..37534bb 100644
--- a/drivers/ide/legacy/qd65xx.c
+++ b/drivers/ide/legacy/qd65xx.c
@@ -1,6 +1,4 @@
 /*
- *  linux/drivers/ide/legacy/qd65xx.c		Version 0.07	Sep 30, 2001
- *
  *  Copyright (C) 1996-2001  Linus Torvalds & author (see below)
  */
 
diff --git a/drivers/ide/legacy/qd65xx.h b/drivers/ide/legacy/qd65xx.h
index 633a424..28dd50a 100644
--- a/drivers/ide/legacy/qd65xx.h
+++ b/drivers/ide/legacy/qd65xx.h
@@ -1,6 +1,4 @@
 /*
- * linux/drivers/ide/legacy/qd65xx.h
- *
  * Copyright (c) 2000	Linus Torvalds & authors
  */
 
diff --git a/drivers/ide/legacy/umc8672.c b/drivers/ide/legacy/umc8672.c
index a1ae1ae..26f38ce 100644
--- a/drivers/ide/legacy/umc8672.c
+++ b/drivers/ide/legacy/umc8672.c
@@ -1,6 +1,4 @@
 /*
- *  linux/drivers/ide/legacy/umc8672.c		Version 0.05	Jul 31, 1996
- *
  *  Copyright (C) 1995-1996  Linus Torvalds & author (see below)
  */
 
diff --git a/drivers/ide/mips/au1xxx-ide.c b/drivers/ide/mips/au1xxx-ide.c
index 2d3e511..cd42b30 100644
--- a/drivers/ide/mips/au1xxx-ide.c
+++ b/drivers/ide/mips/au1xxx-ide.c
@@ -1,6 +1,4 @@
 /*
- * linux/drivers/ide/mips/au1xxx-ide.c  version 01.30.00        Aug. 02 2005
- *
  * BRIEF MODULE DESCRIPTION
  * AMD Alchemy Au1xxx IDE interface routines over the Static Bus
  *
@@ -50,7 +48,6 @@
 #include <asm/mach-au1x00/au1xxx_ide.h>
 
 #define DRV_NAME	"au1200-ide"
-#define DRV_VERSION	"1.0"
 #define DRV_AUTHOR	"Enrico Walther <enrico.walther@amd.com> / Pete Popov <ppopov@embeddedalley.com>"
 
 /* enable the burstmode in the dbdma */
@@ -209,24 +206,6 @@
  */
 
 #ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
-
-static int auide_build_sglist(ide_drive_t *drive,  struct request *rq)
-{
-	ide_hwif_t *hwif = drive->hwif;
-	_auide_hwif *ahwif = (_auide_hwif*)hwif->hwif_data;
-	struct scatterlist *sg = hwif->sg_table;
-
-	ide_map_sg(drive, rq);
-
-	if (rq_data_dir(rq) == READ)
-		hwif->sg_dma_direction = DMA_FROM_DEVICE;
-	else
-		hwif->sg_dma_direction = DMA_TO_DEVICE;
-
-	return dma_map_sg(ahwif->dev, sg, hwif->sg_nents,
-			  hwif->sg_dma_direction);
-}
-
 static int auide_build_dmatable(ide_drive_t *drive)
 {
 	int i, iswrite, count = 0;
@@ -241,8 +220,7 @@
 	/* Save for interrupt context */
 	ahwif->drive = drive;
 
-	/* Build sglist */
-	hwif->sg_nents = i = auide_build_sglist(drive, rq);
+	hwif->sg_nents = i = ide_build_sglist(drive, rq);
 
 	if (!i)
 		return 0;
@@ -300,10 +278,7 @@
 		return 1;
 
  use_pio_instead:
-	dma_unmap_sg(ahwif->dev,
-		     hwif->sg_table,
-		     hwif->sg_nents,
-		     hwif->sg_dma_direction);
+	ide_destroy_dmatable(drive);
 
 	return 0; /* revert to PIO for this request */
 }
@@ -311,11 +286,9 @@
 static int auide_dma_end(ide_drive_t *drive)
 {
 	ide_hwif_t *hwif = HWIF(drive);
-	_auide_hwif *ahwif = (_auide_hwif*)hwif->hwif_data;
 
 	if (hwif->sg_nents) {
-		dma_unmap_sg(ahwif->dev, hwif->sg_table, hwif->sg_nents,
-			     hwif->sg_dma_direction);
+		ide_destroy_dmatable(drive);
 		hwif->sg_nents = 0;
 	}
 
@@ -504,7 +477,7 @@
 	auide->rx_desc_head = (void*)au1xxx_dbdma_ring_alloc(auide->rx_chan,
 							     NUM_DESCRIPTORS);
  
-	hwif->dmatable_cpu = dma_alloc_coherent(auide->dev,
+	hwif->dmatable_cpu = dma_alloc_coherent(hwif->dev,
 						PRD_ENTRIES * PRD_BYTES,        /* 1 Page */
 						&hwif->dmatable_dma, GFP_KERNEL);
 	
@@ -592,9 +565,6 @@
 #endif
 
 	memset(&auide_hwif, 0, sizeof(_auide_hwif));
-	auide_hwif.dev                  = 0;
-
-	ahwif->dev = dev;
 	ahwif->irq = platform_get_irq(pdev, 0);
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -629,10 +599,13 @@
 	memset(&hw, 0, sizeof(hw));
 	auide_setup_ports(&hw, ahwif);
 	hw.irq = ahwif->irq;
+	hw.dev = dev;
 	hw.chipset = ide_au1xxx;
 
 	ide_init_port_hw(hwif, &hw);
 
+	hwif->dev = dev;
+
 	hwif->ultra_mask                = 0x0;  /* Disable Ultra DMA */
 #ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
 	hwif->mwdma_mask                = 0x07; /* Multimode-2 DMA  */
@@ -715,7 +688,7 @@
 	ide_hwif_t *hwif = dev_get_drvdata(dev);
 	_auide_hwif *ahwif = &auide_hwif;
 
-	ide_unregister(hwif - ide_hwifs);
+	ide_unregister(hwif->index);
 
 	iounmap((void *)ahwif->regbase);
 
diff --git a/drivers/ide/pci/aec62xx.c b/drivers/ide/pci/aec62xx.c
index 7f4d185..824df78 100644
--- a/drivers/ide/pci/aec62xx.c
+++ b/drivers/ide/pci/aec62xx.c
@@ -1,6 +1,4 @@
 /*
- * linux/drivers/ide/pci/aec62xx.c		Version 0.27	Sep 16, 2007
- *
  * Copyright (C) 1999-2002	Andre Hedrick <andre@linux-ide.org>
  * Copyright (C) 2007		MontaVista Software, Inc. <source@mvista.com>
  *
@@ -90,7 +88,7 @@
 static void aec6210_set_mode(ide_drive_t *drive, const u8 speed)
 {
 	ide_hwif_t *hwif	= HWIF(drive);
-	struct pci_dev *dev	= hwif->pci_dev;
+	struct pci_dev *dev	= to_pci_dev(hwif->dev);
 	u16 d_conf		= 0;
 	u8 ultra = 0, ultra_conf = 0;
 	u8 tmp0 = 0, tmp1 = 0, tmp2 = 0;
@@ -116,7 +114,7 @@
 static void aec6260_set_mode(ide_drive_t *drive, const u8 speed)
 {
 	ide_hwif_t *hwif	= HWIF(drive);
-	struct pci_dev *dev	= hwif->pci_dev;
+	struct pci_dev *dev	= to_pci_dev(hwif->dev);
 	u8 unit		= (drive->select.b.unit & 0x01);
 	u8 tmp1 = 0, tmp2 = 0;
 	u8 ultra = 0, drive_conf = 0, ultra_conf = 0;
@@ -170,7 +168,7 @@
 
 static void __devinit init_hwif_aec62xx(ide_hwif_t *hwif)
 {
-	struct pci_dev *dev	= hwif->pci_dev;
+	struct pci_dev *dev = to_pci_dev(hwif->dev);
 
 	hwif->set_pio_mode = &aec_set_pio_mode;
 
@@ -188,7 +186,7 @@
 	if (hwif->cbl != ATA_CBL_PATA40_SHORT) {
 		u8 ata66 = 0, mask = hwif->channel ? 0x02 : 0x01;
 
-		pci_read_config_byte(hwif->pci_dev, 0x49, &ata66);
+		pci_read_config_byte(dev, 0x49, &ata66);
 
 		hwif->cbl = (ata66 & mask) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
 	}
@@ -202,6 +200,7 @@
 		.enablebits	= {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}},
 		.host_flags	= IDE_HFLAG_SERIALIZE |
 				  IDE_HFLAG_NO_ATAPI_DMA |
+				  IDE_HFLAG_NO_DSC |
 				  IDE_HFLAG_ABUSE_SET_DMA_MODE |
 				  IDE_HFLAG_OFF_BOARD,
 		.pio_mask	= ATA_PIO4,
diff --git a/drivers/ide/pci/alim15x3.c b/drivers/ide/pci/alim15x3.c
index 49aa82e..130cc6e 100644
--- a/drivers/ide/pci/alim15x3.c
+++ b/drivers/ide/pci/alim15x3.c
@@ -1,6 +1,4 @@
 /*
- * linux/drivers/ide/pci/alim15x3.c		Version 0.29	Sep 16 2007
- *
  *  Copyright (C) 1998-2000 Michel Aubry, Maintainer
  *  Copyright (C) 1998-2000 Andrzej Krzysztofowicz, Maintainer
  *  Copyright (C) 1999-2000 CJ, cjtsai@ali.com.tw, Maintainer
@@ -293,7 +291,7 @@
 static void ali_set_pio_mode(ide_drive_t *drive, const u8 pio)
 {
 	ide_hwif_t *hwif = HWIF(drive);
-	struct pci_dev *dev = hwif->pci_dev;
+	struct pci_dev *dev = to_pci_dev(hwif->dev);
 	int s_time, a_time, c_time;
 	u8 s_clc, a_clc, r_clc;
 	unsigned long flags;
@@ -396,7 +394,7 @@
 static void ali_set_dma_mode(ide_drive_t *drive, const u8 speed)
 {
 	ide_hwif_t *hwif	= HWIF(drive);
-	struct pci_dev *dev	= hwif->pci_dev;
+	struct pci_dev *dev	= to_pci_dev(hwif->dev);
 	u8 speed1		= speed;
 	u8 unit			= (drive->select.b.unit & 0x01);
 	u8 tmpbyte		= 0x00;
@@ -625,7 +623,7 @@
 
 static u8 __devinit ata66_ali15x3(ide_hwif_t *hwif)
 {
-	struct pci_dev *dev	= hwif->pci_dev;
+	struct pci_dev *dev = to_pci_dev(hwif->dev);
 	unsigned long flags;
 	u8 cbl = ATA_CBL_PATA40, tmpbyte;
 
@@ -688,12 +686,13 @@
 
 static void __devinit init_hwif_ali15x3 (ide_hwif_t *hwif)
 {
+	struct pci_dev *dev = to_pci_dev(hwif->dev);
 	u8 ideic, inmir;
 	s8 irq_routing_table[] = { -1,  9, 3, 10, 4,  5, 7,  6,
 				      1, 11, 0, 12, 0, 14, 0, 15 };
 	int irq = -1;
 
-	if (hwif->pci_dev->device == PCI_DEVICE_ID_AL_M5229)
+	if (dev->device == PCI_DEVICE_ID_AL_M5229)
 		hwif->irq = hwif->channel ? 15 : 14;
 
 	if (isa_dev) {
@@ -745,7 +744,7 @@
 		return;
 	if (!hwif->channel)
 		outb(inb(dmabase + 2) & 0x60, dmabase + 2);
-	ide_setup_dma(hwif, dmabase, 8);
+	ide_setup_dma(hwif, dmabase);
 }
 
 static const struct ide_port_info ali15x3_chipset __devinitdata = {
@@ -775,7 +774,7 @@
 	};
 
 	struct ide_port_info d = ali15x3_chipset;
-	u8 rev = dev->revision;
+	u8 rev = dev->revision, idx = id->driver_data;
 
 	if (pci_dev_present(ati_rs100))
 		printk(KERN_WARNING "alim15x3: ATI Radeon IGP Northbridge is not yet fully tested.\n");
@@ -798,6 +797,9 @@
 			d.udma_mask = ATA_UDMA6;
 	}
 
+	if (idx == 0)
+		d.host_flags |= IDE_HFLAG_CLEAR_SIMPLEX;
+
 #if defined(CONFIG_SPARC64)
 	d.init_hwif = init_hwif_common_ali15x3;
 #endif /* CONFIG_SPARC64 */
@@ -807,7 +809,7 @@
 
 static const struct pci_device_id alim15x3_pci_tbl[] = {
 	{ PCI_VDEVICE(AL, PCI_DEVICE_ID_AL_M5229), 0 },
-	{ PCI_VDEVICE(AL, PCI_DEVICE_ID_AL_M5228), 0 },
+	{ PCI_VDEVICE(AL, PCI_DEVICE_ID_AL_M5228), 1 },
 	{ 0, },
 };
 MODULE_DEVICE_TABLE(pci, alim15x3_pci_tbl);
diff --git a/drivers/ide/pci/amd74xx.c b/drivers/ide/pci/amd74xx.c
index cee51fd..8c52bc9 100644
--- a/drivers/ide/pci/amd74xx.c
+++ b/drivers/ide/pci/amd74xx.c
@@ -1,6 +1,4 @@
 /*
- * Version 2.24
- *
  * AMD 755/756/766/8111 and nVidia nForce/2/2s/3/3s/CK804/MCP04
  * IDE driver for Linux.
  *
@@ -28,81 +26,46 @@
 
 #include "ide-timing.h"
 
-#define AMD_IDE_CONFIG		(0x01 + amd_config->base)
-#define AMD_CABLE_DETECT	(0x02 + amd_config->base)
-#define AMD_DRIVE_TIMING	(0x08 + amd_config->base)
-#define AMD_8BIT_TIMING		(0x0e + amd_config->base)
-#define AMD_ADDRESS_SETUP	(0x0c + amd_config->base)
-#define AMD_UDMA_TIMING		(0x10 + amd_config->base)
-
-#define AMD_CHECK_SWDMA		0x08
-#define AMD_BAD_SWDMA		0x10
-#define AMD_BAD_FIFO		0x20
-#define AMD_CHECK_SERENADE	0x40
-
-/*
- * AMD SouthBridge chips.
- */
-
-static struct amd_ide_chip {
-	unsigned short id;
-	u8 base;
-	u8 udma_mask;
-	u8 flags;
-} amd_ide_chips[] = {
-	{ 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 }
+enum {
+	AMD_IDE_CONFIG		= 0x41,
+	AMD_CABLE_DETECT	= 0x42,
+	AMD_DRIVE_TIMING	= 0x48,
+	AMD_8BIT_TIMING		= 0x4e,
+	AMD_ADDRESS_SETUP	= 0x4c,
+	AMD_UDMA_TIMING		= 0x50,
 };
 
-static struct amd_ide_chip *amd_config;
-static const struct ide_port_info *amd_chipset;
 static unsigned int amd_80w;
 static unsigned int amd_clock;
 
 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 };
 
+static inline u8 amd_offset(struct pci_dev *dev)
+{
+	return (dev->vendor == PCI_VENDOR_ID_NVIDIA) ? 0x10 : 0;
+}
+
 /*
  * amd_set_speed() writes timing values to the chipset registers
  */
 
-static void amd_set_speed(struct pci_dev *dev, unsigned char dn, struct ide_timing *timing)
+static void amd_set_speed(struct pci_dev *dev, u8 dn, u8 udma_mask,
+			  struct ide_timing *timing)
 {
-	unsigned char t;
+	u8 t = 0, offset = amd_offset(dev);
 
-	pci_read_config_byte(dev, AMD_ADDRESS_SETUP, &t);
+	pci_read_config_byte(dev, AMD_ADDRESS_SETUP + offset, &t);
 	t = (t & ~(3 << ((3 - dn) << 1))) | ((FIT(timing->setup, 1, 4) - 1) << ((3 - dn) << 1));
-	pci_write_config_byte(dev, AMD_ADDRESS_SETUP, t);
+	pci_write_config_byte(dev, AMD_ADDRESS_SETUP + offset, t);
 
-	pci_write_config_byte(dev, AMD_8BIT_TIMING + (1 - (dn >> 1)),
+	pci_write_config_byte(dev, AMD_8BIT_TIMING + offset + (1 - (dn >> 1)),
 		((FIT(timing->act8b, 1, 16) - 1) << 4) | (FIT(timing->rec8b, 1, 16) - 1));
 
-	pci_write_config_byte(dev, AMD_DRIVE_TIMING + (3 - dn),
+	pci_write_config_byte(dev, AMD_DRIVE_TIMING + offset + (3 - dn),
 		((FIT(timing->active, 1, 16) - 1) << 4) | (FIT(timing->recover, 1, 16) - 1));
 
-	switch (amd_config->udma_mask) {
+	switch (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;
@@ -110,7 +73,7 @@
 	default: return;
 	}
 
-	pci_write_config_byte(dev, AMD_UDMA_TIMING + (3 - dn), t);
+	pci_write_config_byte(dev, AMD_UDMA_TIMING + offset + (3 - dn), t);
 }
 
 /*
@@ -120,12 +83,15 @@
 
 static void amd_set_drive(ide_drive_t *drive, const u8 speed)
 {
-	ide_drive_t *peer = HWIF(drive)->drives + (~drive->dn & 1);
+	ide_hwif_t *hwif = drive->hwif;
+	struct pci_dev *dev = to_pci_dev(hwif->dev);
+	ide_drive_t *peer = hwif->drives + (~drive->dn & 1);
 	struct ide_timing t, p;
 	int T, UT;
+	u8 udma_mask = hwif->ultra_mask;
 
 	T = 1000000000 / amd_clock;
-	UT = (amd_config->udma_mask == ATA_UDMA2) ? T : (T / 2);
+	UT = (udma_mask == ATA_UDMA2) ? T : (T / 2);
 
 	ide_timing_compute(drive, speed, &t, T, UT);
 
@@ -137,7 +103,7 @@
 	if (speed == XFER_UDMA_5 && amd_clock <= 33333) t.udma = 1;
 	if (speed == XFER_UDMA_6 && amd_clock <= 33333) t.udma = 15;
 
-	amd_set_speed(HWIF(drive)->pci_dev, drive->dn, &t);
+	amd_set_speed(dev, drive->dn, udma_mask, &t);
 }
 
 /*
@@ -149,67 +115,68 @@
 	amd_set_drive(drive, XFER_PIO_0 + pio);
 }
 
-/*
- * The initialization callback. Here we determine the IDE chip type
- * and initialize its drive independent registers.
- */
-
-static unsigned int __devinit init_chipset_amd74xx(struct pci_dev *dev, const char *name)
+static void __devinit amd7409_cable_detect(struct pci_dev *dev,
+					   const char *name)
 {
-	unsigned char t;
-	unsigned int u;
+	/* no host side cable detection */
+	amd_80w = 0x03;
+}
+
+static void __devinit amd7411_cable_detect(struct pci_dev *dev,
+					   const char *name)
+{
 	int i;
+	u32 u = 0;
+	u8 t = 0, offset = amd_offset(dev);
+
+	pci_read_config_byte(dev, AMD_CABLE_DETECT + offset, &t);
+	pci_read_config_dword(dev, AMD_UDMA_TIMING + offset, &u);
+	amd_80w = ((t & 0x3) ? 1 : 0) | ((t & 0xc) ? 2 : 0);
+	for (i = 24; i >= 0; i -= 8)
+		if (((u >> i) & 4) && !(amd_80w & (1 << (1 - (i >> 4))))) {
+			printk(KERN_WARNING "%s: BIOS didn't set cable bits "
+					    "correctly. Enabling workaround.\n",
+					    name);
+			amd_80w |= (1 << (1 - (i >> 4)));
+		}
+}
 
 /*
- * Check for bad SWDMA.
+ * The initialization callback.  Initialize drive independent registers.
  */
 
-	if (amd_config->flags & AMD_CHECK_SWDMA) {
-		if (dev->revision <= 7)
-			amd_config->flags |= AMD_BAD_SWDMA;
-	}
+static unsigned int __devinit init_chipset_amd74xx(struct pci_dev *dev,
+						   const char *name)
+{
+	u8 t = 0, offset = amd_offset(dev);
 
 /*
  * Check 80-wire cable presence.
  */
 
-	switch (amd_config->udma_mask) {
-
-		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);
-			for (i = 24; i >= 0; i -= 8)
-				if (((u >> i) & 4) && !(amd_80w & (1 << (1 - (i >> 4))))) {
-					printk(KERN_WARNING "%s: BIOS didn't set cable bits correctly. Enabling workaround.\n",
-						amd_chipset->name);
-					amd_80w |= (1 << (1 - (i >> 4)));
-				}
-			break;
-
-		case ATA_UDMA4:
-			/* no host side cable detection */
-			amd_80w = 0x03;
-			break;
-	}
+	if (dev->vendor == PCI_VENDOR_ID_AMD &&
+	    dev->device == PCI_DEVICE_ID_AMD_COBRA_7401)
+		; /* no UDMA > 2 */
+	else if (dev->vendor == PCI_VENDOR_ID_AMD &&
+		 dev->device == PCI_DEVICE_ID_AMD_VIPER_7409)
+		amd7409_cable_detect(dev, name);
+	else
+		amd7411_cable_detect(dev, name);
 
 /*
  * Take care of prefetch & postwrite.
  */
 
-	pci_read_config_byte(dev, AMD_IDE_CONFIG, &t);
-	pci_write_config_byte(dev, AMD_IDE_CONFIG,
-		(amd_config->flags & AMD_BAD_FIFO) ? (t & 0x0f) : (t | 0xf0));
-
-/*
- * Take care of incorrectly wired Serenade mainboards.
- */
-
-	if ((amd_config->flags & AMD_CHECK_SERENADE) &&
-		dev->subsystem_vendor == PCI_VENDOR_ID_AMD &&
-		dev->subsystem_device == PCI_DEVICE_ID_AMD_SERENADE)
-			amd_config->udma_mask = ATA_UDMA5;
+	pci_read_config_byte(dev, AMD_IDE_CONFIG + offset, &t);
+	/*
+	 * Check for broken FIFO support.
+	 */
+	if (dev->vendor == PCI_VENDOR_ID_AMD &&
+	    dev->vendor == PCI_DEVICE_ID_AMD_VIPER_7411)
+		t &= 0x0f;
+	else
+		t |= 0xf0;
+	pci_write_config_byte(dev, AMD_IDE_CONFIG + offset, t);
 
 /*
  * Determine the system bus clock.
@@ -225,25 +192,19 @@
 
 	if (amd_clock < 20000 || amd_clock > 50000) {
 		printk(KERN_WARNING "%s: User given PCI clock speed impossible (%d), using 33 MHz instead.\n",
-			amd_chipset->name, amd_clock);
+				    name, amd_clock);
 		amd_clock = 33333;
 	}
 
-/*
- * Print the boot message.
- */
-
-	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]);
-
 	return dev->irq;
 }
 
 static void __devinit init_hwif_amd74xx(ide_hwif_t *hwif)
 {
+	struct pci_dev *dev = to_pci_dev(hwif->dev);
+
 	if (hwif->irq == 0) /* 0 is bogus but will do for now */
-		hwif->irq = pci_get_legacy_ide_irq(hwif->pci_dev, hwif->channel);
+		hwif->irq = pci_get_legacy_ide_irq(dev, hwif->channel);
 
 	hwif->set_pio_mode = &amd_set_pio_mode;
 	hwif->set_dma_mode = &amd_set_drive;
@@ -251,10 +212,6 @@
 	if (!hwif->dma_base)
 		return;
 
-	hwif->ultra_mask = amd_config->udma_mask;
-	if (amd_config->flags & AMD_BAD_SWDMA)
-		hwif->swdma_mask = 0x00;
-
 	if (hwif->cbl != ATA_CBL_PATA40_SHORT) {
 		if ((amd_80w >> hwif->channel) & 1)
 			hwif->cbl = ATA_CBL_PATA80;
@@ -272,7 +229,7 @@
 	 IDE_HFLAG_UNMASK_IRQS | \
 	 IDE_HFLAG_BOOTABLE)
 
-#define DECLARE_AMD_DEV(name_str)					\
+#define DECLARE_AMD_DEV(name_str, swdma, udma)				\
 	{								\
 		.name		= name_str,				\
 		.init_chipset	= init_chipset_amd74xx,			\
@@ -280,11 +237,12 @@
 		.enablebits	= {{0x40,0x02,0x02}, {0x40,0x01,0x01}},	\
 		.host_flags	= IDE_HFLAGS_AMD,			\
 		.pio_mask	= ATA_PIO5,				\
-		.swdma_mask	= ATA_SWDMA2,				\
+		.swdma_mask	= swdma,				\
 		.mwdma_mask	= ATA_MWDMA2,				\
+		.udma_mask	= udma,					\
 	}
 
-#define DECLARE_NV_DEV(name_str)					\
+#define DECLARE_NV_DEV(name_str, udma)					\
 	{								\
 		.name		= name_str,				\
 		.init_chipset	= init_chipset_amd74xx,			\
@@ -294,45 +252,62 @@
 		.pio_mask	= ATA_PIO5,				\
 		.swdma_mask	= ATA_SWDMA2,				\
 		.mwdma_mask	= ATA_MWDMA2,				\
+		.udma_mask	= udma,					\
 	}
 
 static const struct ide_port_info amd74xx_chipsets[] __devinitdata = {
-	/*  0 */ DECLARE_AMD_DEV("AMD7401"),
-	/*  1 */ DECLARE_AMD_DEV("AMD7409"),
-	/*  2 */ DECLARE_AMD_DEV("AMD7411"),
-	/*  3 */ DECLARE_AMD_DEV("AMD7441"),
-	/*  4 */ DECLARE_AMD_DEV("AMD8111"),
+	/*  0 */ DECLARE_AMD_DEV("AMD7401",	  0x00, ATA_UDMA2),
+	/*  1 */ DECLARE_AMD_DEV("AMD7409", ATA_SWDMA2, ATA_UDMA4),
+	/*  2 */ DECLARE_AMD_DEV("AMD7411", ATA_SWDMA2, ATA_UDMA5),
+	/*  3 */ DECLARE_AMD_DEV("AMD7441", ATA_SWDMA2, ATA_UDMA5),
+	/*  4 */ DECLARE_AMD_DEV("AMD8111", ATA_SWDMA2, ATA_UDMA6),
 
-	/*  5 */ DECLARE_NV_DEV("NFORCE"),
-	/*  6 */ DECLARE_NV_DEV("NFORCE2"),
-	/*  7 */ DECLARE_NV_DEV("NFORCE2-U400R"),
-	/*  8 */ DECLARE_NV_DEV("NFORCE2-U400R-SATA"),
-	/*  9 */ DECLARE_NV_DEV("NFORCE3-150"),
-	/* 10 */ DECLARE_NV_DEV("NFORCE3-250"),
-	/* 11 */ DECLARE_NV_DEV("NFORCE3-250-SATA"),
-	/* 12 */ DECLARE_NV_DEV("NFORCE3-250-SATA2"),
-	/* 13 */ DECLARE_NV_DEV("NFORCE-CK804"),
-	/* 14 */ DECLARE_NV_DEV("NFORCE-MCP04"),
-	/* 15 */ DECLARE_NV_DEV("NFORCE-MCP51"),
-	/* 16 */ DECLARE_NV_DEV("NFORCE-MCP55"),
-	/* 17 */ DECLARE_NV_DEV("NFORCE-MCP61"),
-	/* 18 */ DECLARE_NV_DEV("NFORCE-MCP65"),
-	/* 19 */ DECLARE_NV_DEV("NFORCE-MCP67"),
-	/* 20 */ DECLARE_NV_DEV("NFORCE-MCP73"),
-	/* 21 */ DECLARE_NV_DEV("NFORCE-MCP77"),
-	/* 22 */ DECLARE_AMD_DEV("AMD5536"),
+	/*  5 */ DECLARE_NV_DEV("NFORCE",		ATA_UDMA5),
+	/*  6 */ DECLARE_NV_DEV("NFORCE2",		ATA_UDMA6),
+	/*  7 */ DECLARE_NV_DEV("NFORCE2-U400R",	ATA_UDMA6),
+	/*  8 */ DECLARE_NV_DEV("NFORCE2-U400R-SATA",	ATA_UDMA6),
+	/*  9 */ DECLARE_NV_DEV("NFORCE3-150",		ATA_UDMA6),
+	/* 10 */ DECLARE_NV_DEV("NFORCE3-250",		ATA_UDMA6),
+	/* 11 */ DECLARE_NV_DEV("NFORCE3-250-SATA",	ATA_UDMA6),
+	/* 12 */ DECLARE_NV_DEV("NFORCE3-250-SATA2",	ATA_UDMA6),
+	/* 13 */ DECLARE_NV_DEV("NFORCE-CK804",		ATA_UDMA6),
+	/* 14 */ DECLARE_NV_DEV("NFORCE-MCP04",		ATA_UDMA6),
+	/* 15 */ DECLARE_NV_DEV("NFORCE-MCP51",		ATA_UDMA6),
+	/* 16 */ DECLARE_NV_DEV("NFORCE-MCP55",		ATA_UDMA6),
+	/* 17 */ DECLARE_NV_DEV("NFORCE-MCP61",		ATA_UDMA6),
+	/* 18 */ DECLARE_NV_DEV("NFORCE-MCP65",		ATA_UDMA6),
+	/* 19 */ DECLARE_NV_DEV("NFORCE-MCP67",		ATA_UDMA6),
+	/* 20 */ DECLARE_NV_DEV("NFORCE-MCP73",		ATA_UDMA6),
+	/* 21 */ DECLARE_NV_DEV("NFORCE-MCP77",		ATA_UDMA6),
+
+	/* 22 */ DECLARE_AMD_DEV("AMD5536", ATA_SWDMA2, ATA_UDMA5),
 };
 
 static int __devinit amd74xx_probe(struct pci_dev *dev, const struct pci_device_id *id)
 {
-	amd_chipset = amd74xx_chipsets + id->driver_data;
-	amd_config = amd_ide_chips + id->driver_data;
-	if (dev->device != amd_config->id) {
-		printk(KERN_ERR "%s: assertion 0x%02x == 0x%02x failed !\n",
-		       pci_name(dev), dev->device, amd_config->id);
-		return -ENODEV;
+	struct ide_port_info d;
+	u8 idx = id->driver_data;
+
+	d = amd74xx_chipsets[idx];
+
+	/*
+	 * Check for bad SWDMA and incorrectly wired Serenade mainboards.
+	 */
+	if (idx == 1) {
+		if (dev->revision <= 7)
+			d.swdma_mask = 0;
+		d.host_flags |= IDE_HFLAG_CLEAR_SIMPLEX;
+	} else if (idx == 4) {
+		if (dev->subsystem_vendor == PCI_VENDOR_ID_AMD &&
+		    dev->subsystem_device == PCI_DEVICE_ID_AMD_SERENADE)
+			d.udma_mask = ATA_UDMA5;
 	}
-	return ide_setup_pci_device(dev, amd_chipset);
+
+	printk(KERN_INFO "%s: %s (rev %02x) UDMA%s controller\n",
+			 d.name, pci_name(dev), dev->revision,
+			 amd_dma[fls(d.udma_mask) - 1]);
+
+	return ide_setup_pci_device(dev, &d);
 }
 
 static const struct pci_device_id amd74xx_pci_tbl[] = {
diff --git a/drivers/ide/pci/atiixp.c b/drivers/ide/pci/atiixp.c
index 4918719..b56274a 100644
--- a/drivers/ide/pci/atiixp.c
+++ b/drivers/ide/pci/atiixp.c
@@ -1,6 +1,4 @@
 /*
- *  linux/drivers/ide/pci/atiixp.c	Version 0.05	Nov 9 2007
- *
  *  Copyright (C) 2003 ATI Inc. <hyu@ati.com>
  *  Copyright (C) 2004,2007 Bartlomiej Zolnierkiewicz
  */
@@ -55,7 +53,7 @@
 
 static void atiixp_set_pio_mode(ide_drive_t *drive, const u8 pio)
 {
-	struct pci_dev *dev = drive->hwif->pci_dev;
+	struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
 	unsigned long flags;
 	int timing_shift = (drive->dn & 2) ? 16 : 0 + (drive->dn & 1) ? 0 : 8;
 	u32 pio_timing_data;
@@ -88,7 +86,7 @@
 
 static void atiixp_set_dma_mode(ide_drive_t *drive, const u8 speed)
 {
-	struct pci_dev *dev = drive->hwif->pci_dev;
+	struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
 	unsigned long flags;
 	int timing_shift = (drive->dn & 2) ? 16 : 0 + (drive->dn & 1) ? 0 : 8;
 	u32 tmp32;
@@ -133,9 +131,8 @@
 
 static void __devinit init_hwif_atiixp(ide_hwif_t *hwif)
 {
-	u8 udma_mode = 0;
-	u8 ch = hwif->channel;
-	struct pci_dev *pdev = hwif->pci_dev;
+	struct pci_dev *pdev = to_pci_dev(hwif->dev);
+	u8 udma_mode = 0, ch = hwif->channel;
 
 	hwif->set_pio_mode = &atiixp_set_pio_mode;
 	hwif->set_dma_mode = &atiixp_set_dma_mode;
diff --git a/drivers/ide/pci/cmd640.c b/drivers/ide/pci/cmd640.c
index da3565e..7240c20 100644
--- a/drivers/ide/pci/cmd640.c
+++ b/drivers/ide/pci/cmd640.c
@@ -1,6 +1,4 @@
 /*
- *  linux/drivers/ide/pci/cmd640.c		Version 1.02  Sep 01, 1996
- *
  *  Copyright (C) 1995-1996  Linus Torvalds & authors (see below)
  */
 
diff --git a/drivers/ide/pci/cmd64x.c b/drivers/ide/pci/cmd64x.c
index cd4eb9d..04aa9e596 100644
--- a/drivers/ide/pci/cmd64x.c
+++ b/drivers/ide/pci/cmd64x.c
@@ -1,6 +1,4 @@
 /*
- * linux/drivers/ide/pci/cmd64x.c		Version 1.53	Dec 24, 2007
- *
  * cmd64x.c: Enable interrupts at initialization time on Ultra/PCI machines.
  *           Due to massive hardware bugs, UltraDMA is only supported
  *           on the 646U2 and not on the 646U.
@@ -71,7 +69,7 @@
  */
 static void program_cycle_times (ide_drive_t *drive, int cycle_time, int active_time)
 {
-	struct pci_dev *dev	= HWIF(drive)->pci_dev;
+	struct pci_dev *dev	= to_pci_dev(drive->hwif->dev);
 	int clock_time		= 1000 / system_bus_clock();
 	u8  cycle_count, active_count, recovery_count, drwtim;
 	static const u8 recovery_values[] =
@@ -118,7 +116,7 @@
 static void cmd64x_tune_pio(ide_drive_t *drive, const u8 pio)
 {
 	ide_hwif_t *hwif	= HWIF(drive);
-	struct pci_dev *dev	= hwif->pci_dev;
+	struct pci_dev *dev	= to_pci_dev(hwif->dev);
 	unsigned int cycle_time;
 	u8 setup_count, arttim = 0;
 
@@ -183,7 +181,7 @@
 static void cmd64x_set_dma_mode(ide_drive_t *drive, const u8 speed)
 {
 	ide_hwif_t *hwif	= HWIF(drive);
-	struct pci_dev *dev	= hwif->pci_dev;
+	struct pci_dev *dev	= to_pci_dev(hwif->dev);
 	u8 unit			= drive->dn & 0x01;
 	u8 regU = 0, pciU	= hwif->channel ? UDIDETCR1 : UDIDETCR0;
 
@@ -245,7 +243,7 @@
 static int cmd64x_ide_dma_end (ide_drive_t *drive)
 {
 	ide_hwif_t *hwif	= HWIF(drive);
-	struct pci_dev *dev	= hwif->pci_dev;
+	struct pci_dev *dev	= to_pci_dev(hwif->dev);
 	int irq_reg		= hwif->channel ? ARTTIM23 : CFR;
 	u8  irq_mask		= hwif->channel ? ARTTIM23_INTR_CH1 :
 						  CFR_INTR_CH0;
@@ -285,7 +283,7 @@
 static int cmd64x_ide_dma_test_irq (ide_drive_t *drive)
 {
 	ide_hwif_t *hwif	= HWIF(drive);
-	struct pci_dev *dev	= hwif->pci_dev;
+	struct pci_dev *dev	= to_pci_dev(hwif->dev);
 	int irq_reg		= hwif->channel ? ARTTIM23 : CFR;
 	u8  irq_mask		= hwif->channel ? ARTTIM23_INTR_CH1 :
 						  CFR_INTR_CH0;
@@ -375,7 +373,7 @@
 
 static u8 __devinit ata66_cmd64x(ide_hwif_t *hwif)
 {
-	struct pci_dev  *dev	= hwif->pci_dev;
+	struct pci_dev  *dev	= to_pci_dev(hwif->dev);
 	u8 bmidecsr = 0, mask	= hwif->channel ? 0x02 : 0x01;
 
 	switch (dev->device) {
@@ -390,7 +388,7 @@
 
 static void __devinit init_hwif_cmd64x(ide_hwif_t *hwif)
 {
-	struct pci_dev *dev	= hwif->pci_dev;
+	struct pci_dev *dev = to_pci_dev(hwif->dev);
 
 	hwif->set_pio_mode = &cmd64x_set_pio_mode;
 	hwif->set_dma_mode = &cmd64x_set_dma_mode;
@@ -443,7 +441,9 @@
 		.init_chipset	= init_chipset_cmd64x,
 		.init_hwif	= init_hwif_cmd64x,
 		.enablebits	= {{0x00,0x00,0x00}, {0x51,0x08,0x08}},
-		.host_flags	= IDE_HFLAG_ABUSE_PREFETCH | IDE_HFLAG_BOOTABLE,
+		.host_flags	= IDE_HFLAG_CLEAR_SIMPLEX |
+				  IDE_HFLAG_ABUSE_PREFETCH |
+				  IDE_HFLAG_BOOTABLE,
 		.pio_mask	= ATA_PIO5,
 		.mwdma_mask	= ATA_MWDMA2,
 		.udma_mask	= 0x00, /* no udma */
diff --git a/drivers/ide/pci/cs5520.c b/drivers/ide/pci/cs5520.c
index 6ec00b8..eb68a9a 100644
--- a/drivers/ide/pci/cs5520.c
+++ b/drivers/ide/pci/cs5520.c
@@ -69,7 +69,7 @@
 static void cs5520_set_pio_mode(ide_drive_t *drive, const u8 pio)
 {
 	ide_hwif_t *hwif = HWIF(drive);
-	struct pci_dev *pdev = hwif->pci_dev;
+	struct pci_dev *pdev = to_pci_dev(hwif->dev);
 	int controller = drive->dn > 1 ? 1 : 0;
 
 	/* FIXME: if DMA = 1 do we need to set the DMA bit here ? */
@@ -156,8 +156,14 @@
 	ide_setup_pci_noise(dev, d);
 
 	/* We must not grab the entire device, it has 'ISA' space in its
-	   BARS too and we will freak out other bits of the kernel */
-	if (pci_enable_device_bars(dev, 1<<2)) {
+	 * BARS too and we will freak out other bits of the kernel
+	 *
+	 * pci_enable_device_bars() is going away. I replaced it with
+	 * IO only enable for now but I'll need confirmation this is
+	 * allright for that device. If not, it will need some kind of
+	 * quirk. --BenH.
+	 */
+	if (pci_enable_device_io(dev)) {
 		printk(KERN_WARNING "%s: Unable to enable 55x0.\n", d->name);
 		return -ENODEV;
 	}
diff --git a/drivers/ide/pci/cs5530.c b/drivers/ide/pci/cs5530.c
index df5966b..765aac3 100644
--- a/drivers/ide/pci/cs5530.c
+++ b/drivers/ide/pci/cs5530.c
@@ -1,6 +1,4 @@
 /*
- * linux/drivers/ide/pci/cs5530.c		Version 0.77	Sep 24 2007
- *
  * Copyright (C) 2000			Andre Hedrick <andre@linux-ide.org>
  * Copyright (C) 2000			Mark Lord <mlord@pobox.com>
  * Copyright (C) 2007			Bartlomiej Zolnierkiewicz
diff --git a/drivers/ide/pci/cs5535.c b/drivers/ide/pci/cs5535.c
index 50b3d77..66433aa 100644
--- a/drivers/ide/pci/cs5535.c
+++ b/drivers/ide/pci/cs5535.c
@@ -1,6 +1,4 @@
 /*
- * linux/drivers/ide/pci/cs5535.c
- *
  * Copyright (C) 2004-2005 Advanced Micro Devices, Inc.
  * Copyright (C)      2007 Bartlomiej Zolnierkiewicz
  *
@@ -177,13 +175,15 @@
  */
 static void __devinit init_hwif_cs5535(ide_hwif_t *hwif)
 {
+	struct pci_dev *dev = to_pci_dev(hwif->dev);
+
 	hwif->set_pio_mode = &cs5535_set_pio_mode;
 	hwif->set_dma_mode = &cs5535_set_dma_mode;
 
 	if (hwif->dma_base == 0)
 		return;
 
-	hwif->cbl = cs5535_cable_detect(hwif->pci_dev);
+	hwif->cbl = cs5535_cable_detect(dev);
 }
 
 static const struct ide_port_info cs5535_chipset __devinitdata = {
diff --git a/drivers/ide/pci/cy82c693.c b/drivers/ide/pci/cy82c693.c
index 3ec4c659..50100ac 100644
--- a/drivers/ide/pci/cy82c693.c
+++ b/drivers/ide/pci/cy82c693.c
@@ -1,6 +1,4 @@
 /*
- * linux/drivers/ide/pci/cy82c693.c		Version 0.44	Nov 8, 2007
- *
  *  Copyright (C) 1998-2000 Andreas S. Krebs (akrebs@altavista.net), Maintainer
  *  Copyright (C) 1998-2002 Andre Hedrick <andre@linux-ide.org>, Integrator
  *
@@ -228,7 +226,7 @@
 static void cy82c693_set_pio_mode(ide_drive_t *drive, const u8 pio)
 {
 	ide_hwif_t *hwif = HWIF(drive);
-	struct pci_dev *dev = hwif->pci_dev;
+	struct pci_dev *dev = to_pci_dev(hwif->dev);
 	pio_clocks_t pclk;
 	unsigned int addrCtrl;
 
@@ -397,8 +395,9 @@
 static void __devinit init_iops_cy82c693(ide_hwif_t *hwif)
 {
 	static ide_hwif_t *primary;
+	struct pci_dev *dev = to_pci_dev(hwif->dev);
 
-	if (PCI_FUNC(hwif->pci_dev->devfn) == 1)
+	if (PCI_FUNC(dev->devfn) == 1)
 		primary = hwif;
 	else {
 		hwif->mate = primary;
diff --git a/drivers/ide/pci/delkin_cb.c b/drivers/ide/pci/delkin_cb.c
index 26aa492..27e47fc 100644
--- a/drivers/ide/pci/delkin_cb.c
+++ b/drivers/ide/pci/delkin_cb.c
@@ -1,6 +1,4 @@
 /*
- *  linux/drivers/ide/pci/delkin_cb.c
- *
  *  Created 20 Oct 2004 by Mark Lord
  *
  *  Basic support for Delkin/ASKA/Workbit Cardbus CompactFlash adapter
@@ -87,7 +85,7 @@
 		return -ENODEV;
 	}
 	pci_set_drvdata(dev, hwif);
-	hwif->pci_dev = dev;
+	hwif->dev = &dev->dev;
 	drive = &hwif->drives[0];
 	if (drive->present) {
 		drive->io_32bit = 1;
diff --git a/drivers/ide/pci/generic.c b/drivers/ide/pci/generic.c
index 0688569..59ebe84 100644
--- a/drivers/ide/pci/generic.c
+++ b/drivers/ide/pci/generic.c
@@ -1,6 +1,4 @@
 /*
- *  linux/drivers/ide/pci/generic.c	Version 0.11	December 30, 2002
- *
  *  Copyright (C) 2001-2002	Andre Hedrick <andre@linux-ide.org>
  *  Portions (C) Copyright 2002  Red Hat Inc <alan@redhat.com>
  *
@@ -104,7 +102,8 @@
 
 	{	/* 14 */
 		.name		= "Revolution",
-		.host_flags	= IDE_HFLAG_TRUST_BIOS_FOR_DMA |
+		.host_flags	= IDE_HFLAG_CLEAR_SIMPLEX |
+				  IDE_HFLAG_TRUST_BIOS_FOR_DMA |
 				  IDE_HFLAG_OFF_BOARD,
 		.swdma_mask	= ATA_SWDMA2,
 		.mwdma_mask	= ATA_MWDMA2,
diff --git a/drivers/ide/pci/hpt34x.c b/drivers/ide/pci/hpt34x.c
index dfba0d1..25dbb81 100644
--- a/drivers/ide/pci/hpt34x.c
+++ b/drivers/ide/pci/hpt34x.c
@@ -1,7 +1,6 @@
 /*
- * linux/drivers/ide/pci/hpt34x.c		Version 0.40	Sept 10, 2002
- *
  * Copyright (C) 1998-2000	Andre Hedrick <andre@linux-ide.org>
+ *
  * May be copied or modified under the terms of the GNU General Public License
  *
  *
@@ -45,7 +44,7 @@
 
 static void hpt34x_set_mode(ide_drive_t *drive, const u8 speed)
 {
-	struct pci_dev *dev	= HWIF(drive)->pci_dev;
+	struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
 	u32 reg1= 0, tmp1 = 0, reg2 = 0, tmp2 = 0;
 	u8			hi_speed, lo_speed;
 
@@ -131,6 +130,7 @@
 
 #define IDE_HFLAGS_HPT34X \
 	(IDE_HFLAG_NO_ATAPI_DMA | \
+	 IDE_HFLAG_NO_DSC | \
 	 IDE_HFLAG_ABUSE_SET_DMA_MODE | \
 	 IDE_HFLAG_NO_AUTODMA)
 
diff --git a/drivers/ide/pci/hpt366.c b/drivers/ide/pci/hpt366.c
index 1268593..5623cad 100644
--- a/drivers/ide/pci/hpt366.c
+++ b/drivers/ide/pci/hpt366.c
@@ -1,6 +1,4 @@
 /*
- * linux/drivers/ide/pci/hpt366.c		Version 1.30	Dec 12, 2007
- *
  * Copyright (C) 1999-2003		Andre Hedrick <andre@linux-ide.org>
  * Portions Copyright (C) 2001	        Sun Microsystems, Inc.
  * Portions Copyright (C) 2003		Red Hat Inc
@@ -626,7 +624,8 @@
 static u8 hpt3xx_udma_filter(ide_drive_t *drive)
 {
 	ide_hwif_t *hwif	= HWIF(drive);
-	struct hpt_info *info	= pci_get_drvdata(hwif->pci_dev);
+	struct pci_dev *dev	= to_pci_dev(hwif->dev);
+	struct hpt_info *info	= pci_get_drvdata(dev);
 	u8 mask 		= hwif->ultra_mask;
 
 	switch (info->chip_type) {
@@ -665,7 +664,8 @@
 static u8 hpt3xx_mdma_filter(ide_drive_t *drive)
 {
 	ide_hwif_t *hwif	= HWIF(drive);
-	struct hpt_info *info	= pci_get_drvdata(hwif->pci_dev);
+	struct pci_dev *dev	= to_pci_dev(hwif->dev);
+	struct hpt_info *info	= pci_get_drvdata(dev);
 
 	switch (info->chip_type) {
 	case HPT372 :
@@ -699,7 +699,7 @@
 
 static void hpt3xx_set_mode(ide_drive_t *drive, const u8 speed)
 {
-	struct pci_dev  *dev	= HWIF(drive)->pci_dev;
+	struct pci_dev  *dev	= to_pci_dev(drive->hwif->dev);
 	struct hpt_info	*info	= pci_get_drvdata(dev);
 	struct hpt_timings *t	= info->timings;
 	u8  itr_addr		= 0x40 + (drive->dn * 4);
@@ -742,7 +742,7 @@
 static void hpt3xx_maskproc(ide_drive_t *drive, int mask)
 {
 	ide_hwif_t *hwif	= HWIF(drive);
-	struct pci_dev	*dev	= hwif->pci_dev;
+	struct pci_dev	*dev	= to_pci_dev(hwif->dev);
 	struct hpt_info *info	= pci_get_drvdata(dev);
 
 	if (drive->quirk_list) {
@@ -774,7 +774,7 @@
  */
 static void hpt366_dma_lost_irq(ide_drive_t *drive)
 {
-	struct pci_dev *dev = HWIF(drive)->pci_dev;
+	struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
 	u8 mcr1 = 0, mcr3 = 0, scr1 = 0;
 
 	pci_read_config_byte(dev, 0x50, &mcr1);
@@ -790,18 +790,20 @@
 static void hpt370_clear_engine(ide_drive_t *drive)
 {
 	ide_hwif_t *hwif = HWIF(drive);
+	struct pci_dev *dev = to_pci_dev(hwif->dev);
 
-	pci_write_config_byte(hwif->pci_dev, hwif->select_data, 0x37);
+	pci_write_config_byte(dev, hwif->select_data, 0x37);
 	udelay(10);
 }
 
 static void hpt370_irq_timeout(ide_drive_t *drive)
 {
 	ide_hwif_t *hwif	= HWIF(drive);
+	struct pci_dev *dev	= to_pci_dev(hwif->dev);
 	u16 bfifo		= 0;
 	u8  dma_cmd;
 
-	pci_read_config_word(hwif->pci_dev, hwif->select_data + 2, &bfifo);
+	pci_read_config_word(dev, hwif->select_data + 2, &bfifo);
 	printk(KERN_DEBUG "%s: %d bytes in FIFO\n", drive->name, bfifo & 0x1ff);
 
 	/* get DMA command mode */
@@ -844,10 +846,11 @@
 static int hpt374_ide_dma_test_irq(ide_drive_t *drive)
 {
 	ide_hwif_t *hwif	= HWIF(drive);
+	struct pci_dev *dev	= to_pci_dev(hwif->dev);
 	u16 bfifo		= 0;
 	u8  dma_stat;
 
-	pci_read_config_word(hwif->pci_dev, hwif->select_data + 2, &bfifo);
+	pci_read_config_word(dev, hwif->select_data + 2, &bfifo);
 	if (bfifo & 0x1FF) {
 //		printk("%s: %d bytes in FIFO\n", drive->name, bfifo);
 		return 0;
@@ -867,7 +870,7 @@
 static int hpt374_ide_dma_end(ide_drive_t *drive)
 {
 	ide_hwif_t *hwif	= HWIF(drive);
-	struct pci_dev	*dev	= hwif->pci_dev;
+	struct pci_dev *dev	= to_pci_dev(hwif->dev);
 	u8 mcr	= 0, mcr_addr	= hwif->select_data;
 	u8 bwsr = 0, mask	= hwif->channel ? 0x02 : 0x01;
 
@@ -942,7 +945,7 @@
 static int hpt3xx_busproc(ide_drive_t *drive, int state)
 {
 	ide_hwif_t *hwif	= HWIF(drive);
-	struct pci_dev *dev	= hwif->pci_dev;
+	struct pci_dev *dev	= to_pci_dev(hwif->dev);
 	u8  mcr_addr		= hwif->select_data + 2;
 	u8  resetmask		= hwif->channel ? 0x80 : 0x40;
 	u8  bsr2		= 0;
@@ -1278,7 +1281,7 @@
 
 static void __devinit init_hwif_hpt366(ide_hwif_t *hwif)
 {
-	struct pci_dev	*dev	= hwif->pci_dev;
+	struct pci_dev *dev	= to_pci_dev(hwif->dev);
 	struct hpt_info *info	= pci_get_drvdata(dev);
 	int serialize		= HPT_SERIALIZE_IO;
 	u8  scr1 = 0, ata66	= hwif->channel ? 0x01 : 0x02;
@@ -1393,7 +1396,7 @@
 
 static void __devinit init_dma_hpt366(ide_hwif_t *hwif, unsigned long dmabase)
 {
-	struct pci_dev	*dev		= hwif->pci_dev;
+	struct pci_dev *dev = to_pci_dev(hwif->dev);
 	u8 masterdma	= 0, slavedma	= 0;
 	u8 dma_new	= 0, dma_old	= 0;
 	unsigned long flags;
@@ -1413,7 +1416,7 @@
 
 	local_irq_restore(flags);
 
-	ide_setup_dma(hwif, dmabase, 8);
+	ide_setup_dma(hwif, dmabase);
 }
 
 static void __devinit hpt374_init(struct pci_dev *dev, struct pci_dev *dev2)
diff --git a/drivers/ide/pci/it8213.c b/drivers/ide/pci/it8213.c
index 2a0f45c..df74e58 100644
--- a/drivers/ide/pci/it8213.c
+++ b/drivers/ide/pci/it8213.c
@@ -28,7 +28,7 @@
 static void it8213_set_pio_mode(ide_drive_t *drive, const u8 pio)
 {
 	ide_hwif_t *hwif	= HWIF(drive);
-	struct pci_dev *dev	= hwif->pci_dev;
+	struct pci_dev *dev	= to_pci_dev(hwif->dev);
 	int is_slave		= drive->dn & 1;
 	int master_port		= 0x40;
 	int slave_port		= 0x44;
@@ -85,7 +85,7 @@
 static void it8213_set_dma_mode(ide_drive_t *drive, const u8 speed)
 {
 	ide_hwif_t *hwif	= HWIF(drive);
-	struct pci_dev *dev	= hwif->pci_dev;
+	struct pci_dev *dev	= to_pci_dev(hwif->dev);
 	u8 maslave		= 0x40;
 	int a_speed		= 3 << (drive->dn * 4);
 	int u_flag		= 1 << drive->dn;
@@ -152,6 +152,7 @@
 
 static void __devinit init_hwif_it8213(ide_hwif_t *hwif)
 {
+	struct pci_dev *dev = to_pci_dev(hwif->dev);
 	u8 reg42h = 0;
 
 	hwif->set_dma_mode = &it8213_set_dma_mode;
@@ -160,7 +161,7 @@
 	if (!hwif->dma_base)
 		return;
 
-	pci_read_config_byte(hwif->pci_dev, 0x42, &reg42h);
+	pci_read_config_byte(dev, 0x42, &reg42h);
 
 	if (hwif->cbl != ATA_CBL_PATA40_SHORT)
 		hwif->cbl = (reg42h & 0x02) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
diff --git a/drivers/ide/pci/it821x.c b/drivers/ide/pci/it821x.c
index e610a53..938d35f 100644
--- a/drivers/ide/pci/it821x.c
+++ b/drivers/ide/pci/it821x.c
@@ -1,7 +1,4 @@
-
 /*
- * 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
  *
@@ -113,7 +110,8 @@
 
 static void it821x_program(ide_drive_t *drive, u16 timing)
 {
-	ide_hwif_t *hwif	= drive->hwif;
+	ide_hwif_t *hwif = drive->hwif;
+	struct pci_dev *dev = to_pci_dev(hwif->dev);
 	struct it821x_dev *itdev = ide_get_hwifdata(hwif);
 	int channel = hwif->channel;
 	u8 conf;
@@ -123,7 +121,8 @@
 		conf = timing >> 8;
 	else
 		conf = timing & 0xFF;
-	pci_write_config_byte(hwif->pci_dev, 0x54 + 4 * channel, conf);
+
+	pci_write_config_byte(dev, 0x54 + 4 * channel, conf);
 }
 
 /**
@@ -137,7 +136,8 @@
 
 static void it821x_program_udma(ide_drive_t *drive, u16 timing)
 {
-	ide_hwif_t *hwif	= drive->hwif;
+	ide_hwif_t *hwif = drive->hwif;
+	struct pci_dev *dev = to_pci_dev(hwif->dev);
 	struct it821x_dev *itdev = ide_get_hwifdata(hwif);
 	int channel = hwif->channel;
 	int unit = drive->select.b.unit;
@@ -148,11 +148,12 @@
 		conf = timing >> 8;
 	else
 		conf = timing & 0xFF;
-	if(itdev->timing10 == 0)
-		pci_write_config_byte(hwif->pci_dev, 0x56 + 4 * channel + unit, conf);
+
+	if (itdev->timing10 == 0)
+		pci_write_config_byte(dev, 0x56 + 4 * channel + unit, conf);
 	else {
-		pci_write_config_byte(hwif->pci_dev, 0x56 + 4 * channel, conf);
-		pci_write_config_byte(hwif->pci_dev, 0x56 + 4 * channel + 1, conf);
+		pci_write_config_byte(dev, 0x56 + 4 * channel, conf);
+		pci_write_config_byte(dev, 0x56 + 4 * channel + 1, conf);
 	}
 }
 
@@ -167,6 +168,7 @@
 static void it821x_clock_strategy(ide_drive_t *drive)
 {
 	ide_hwif_t *hwif = drive->hwif;
+	struct pci_dev *dev = to_pci_dev(hwif->dev);
 	struct it821x_dev *itdev = ide_get_hwifdata(hwif);
 
 	u8 unit = drive->select.b.unit;
@@ -205,10 +207,11 @@
 		itdev->clock_mode = ATA_50;
 		sel = 1;
 	}
-	pci_read_config_byte(hwif->pci_dev, 0x50, &v);
+
+	pci_read_config_byte(dev, 0x50, &v);
 	v &= ~(1 << (1 + hwif->channel));
 	v |= sel << (1 + hwif->channel);
-	pci_write_config_byte(hwif->pci_dev, 0x50, v);
+	pci_write_config_byte(dev, 0x50, v);
 
 	/*
 	 *	Reprogram the UDMA/PIO of the pair drive for the switch
@@ -282,7 +285,8 @@
 
 static void it821x_tune_mwdma (ide_drive_t *drive, byte mode_wanted)
 {
-	ide_hwif_t *hwif	= drive->hwif;
+	ide_hwif_t *hwif = drive->hwif;
+	struct pci_dev *dev = to_pci_dev(hwif->dev);
 	struct it821x_dev *itdev = (void *)ide_get_hwifdata(hwif);
 	int unit = drive->select.b.unit;
 	int channel = hwif->channel;
@@ -297,12 +301,12 @@
 	itdev->udma[unit] = UDMA_OFF;
 
 	/* UDMA bits off - Revision 0x10 do them in pairs */
-	pci_read_config_byte(hwif->pci_dev, 0x50, &conf);
-	if(itdev->timing10)
+	pci_read_config_byte(dev, 0x50, &conf);
+	if (itdev->timing10)
 		conf |= channel ? 0x60: 0x18;
 	else
 		conf |= 1 << (3 + 2 * channel + unit);
-	pci_write_config_byte(hwif->pci_dev, 0x50, conf);
+	pci_write_config_byte(dev, 0x50, conf);
 
 	it821x_clock_strategy(drive);
 	/* FIXME: do we need to program this ? */
@@ -320,7 +324,8 @@
 
 static void it821x_tune_udma (ide_drive_t *drive, byte mode_wanted)
 {
-	ide_hwif_t *hwif	= drive->hwif;
+	ide_hwif_t *hwif = drive->hwif;
+	struct pci_dev *dev = to_pci_dev(hwif->dev);
 	struct it821x_dev *itdev = ide_get_hwifdata(hwif);
 	int unit = drive->select.b.unit;
 	int channel = hwif->channel;
@@ -337,12 +342,12 @@
 		itdev->udma[unit] |= 0x8080;	/* UDMA 5/6 select on */
 
 	/* UDMA on. Again revision 0x10 must do the pair */
-	pci_read_config_byte(hwif->pci_dev, 0x50, &conf);
-	if(itdev->timing10)
+	pci_read_config_byte(dev, 0x50, &conf);
+	if (itdev->timing10)
 		conf &= channel ? 0x9F: 0xE7;
 	else
 		conf &= ~ (1 << (3 + 2 * channel + unit));
-	pci_write_config_byte(hwif->pci_dev, 0x50, conf);
+	pci_write_config_byte(dev, 0x50, conf);
 
 	it821x_clock_strategy(drive);
 	it821x_program_udma(drive, itdev->udma[unit]);
@@ -520,6 +525,7 @@
 
 static void __devinit init_hwif_it821x(ide_hwif_t *hwif)
 {
+	struct pci_dev *dev = to_pci_dev(hwif->dev);
 	struct it821x_dev *idev = kzalloc(sizeof(struct it821x_dev), GFP_KERNEL);
 	u8 conf;
 
@@ -532,7 +538,7 @@
 
 	ide_set_hwifdata(hwif, idev);
 
-	pci_read_config_byte(hwif->pci_dev, 0x50, &conf);
+	pci_read_config_byte(dev, 0x50, &conf);
 	if (conf & 1) {
 		idev->smart = 1;
 		hwif->host_flags |= IDE_HFLAG_NO_ATAPI_DMA;
@@ -555,7 +561,7 @@
 	 *	this is necessary.
 	 */
 
-	pci_read_config_byte(hwif->pci_dev, 0x08, &conf);
+	pci_read_config_byte(dev, 0x08, &conf);
 	if (conf == 0x10) {
 		idev->timing10 = 1;
 		hwif->host_flags |= IDE_HFLAG_NO_ATAPI_DMA;
diff --git a/drivers/ide/pci/jmicron.c b/drivers/ide/pci/jmicron.c
index 0083eaf..8b40f64 100644
--- a/drivers/ide/pci/jmicron.c
+++ b/drivers/ide/pci/jmicron.c
@@ -30,7 +30,7 @@
 
 static u8 __devinit ata66_jmicron(ide_hwif_t *hwif)
 {
-	struct pci_dev *pdev = hwif->pci_dev;
+	struct pci_dev *pdev = to_pci_dev(hwif->dev);
 
 	u32 control;
 	u32 control5;
diff --git a/drivers/ide/pci/ns87415.c b/drivers/ide/pci/ns87415.c
index d4df464..fc9eee9 100644
--- a/drivers/ide/pci/ns87415.c
+++ b/drivers/ide/pci/ns87415.c
@@ -1,6 +1,4 @@
 /*
- * linux/drivers/ide/pci/ns87415.c		Version 2.00  Sep. 10, 2002
- *
  * Copyright (C) 1997-1998	Mark Lord <mlord@pobox.com>
  * Copyright (C) 1998		Eddie C. Dost <ecd@skynet.be>
  * Copyright (C) 1999-2000	Andre Hedrick <andre@linux-ide.org>
@@ -71,10 +69,9 @@
 
 static void __devinit superio_ide_init_iops (struct hwif_s *hwif)
 {
+	struct pci_dev *pdev = to_pci_dev(hwif->dev);
 	u32 base, dmabase;
-	u8 tmp;
-	struct pci_dev *pdev = hwif->pci_dev;
-	u8 port = hwif->channel;
+	u8 port = hwif->channel, tmp;
 
 	base = pci_resource_start(pdev, port * 2) & ~3;
 	dmabase = pci_resource_start(pdev, 4) & ~3;
@@ -93,10 +90,11 @@
 
 static void __devinit init_iops_ns87415(ide_hwif_t *hwif)
 {
-	if (PCI_SLOT(hwif->pci_dev->devfn) == 0xE) {
+	struct pci_dev *dev = to_pci_dev(hwif->dev);
+
+	if (PCI_SLOT(dev->devfn) == 0xE)
 		/* Built-in - assume it's under superio. */
 		superio_ide_init_iops(hwif);
-	}
 }
 #endif
 
@@ -110,8 +108,8 @@
 static void ns87415_prepare_drive (ide_drive_t *drive, unsigned int use_dma)
 {
 	ide_hwif_t *hwif = HWIF(drive);
+	struct pci_dev *dev = to_pci_dev(hwif->dev);
 	unsigned int bit, other, new, *old = (unsigned int *) hwif->select_data;
-	struct pci_dev *dev = hwif->pci_dev;
 	unsigned long flags;
 
 	local_irq_save(flags);
@@ -189,7 +187,7 @@
 
 static void __devinit init_hwif_ns87415 (ide_hwif_t *hwif)
 {
-	struct pci_dev *dev = hwif->pci_dev;
+	struct pci_dev *dev = to_pci_dev(hwif->dev);
 	unsigned int ctrl, using_inta;
 	u8 progif;
 #ifdef __sparc_v9__
@@ -231,8 +229,8 @@
 
 #ifdef __sparc_v9__
 		/*
-		 * XXX: Reset the device, if we don't it will not respond
-		 *      to SELECT_DRIVE() properly during first probe_hwif().
+		 * XXX: Reset the device, if we don't it will not respond to
+		 *      SELECT_DRIVE() properly during first ide_probe_port().
 		 */
 		timeout = 10000;
 		outb(12, hwif->io_ports[IDE_CONTROL_OFFSET]);
diff --git a/drivers/ide/pci/opti621.c b/drivers/ide/pci/opti621.c
index 8953d9c..0ce92d3 100644
--- a/drivers/ide/pci/opti621.c
+++ b/drivers/ide/pci/opti621.c
@@ -1,6 +1,4 @@
 /*
- *  linux/drivers/ide/pci/opti621.c		Version 0.9	Sep 24, 2007
- *
  *  Copyright (C) 1996-1998  Linus Torvalds & authors (see below)
  */
 
diff --git a/drivers/ide/pci/pdc202xx_new.c b/drivers/ide/pci/pdc202xx_new.c
index 89d2363..bb29db0 100644
--- a/drivers/ide/pci/pdc202xx_new.c
+++ b/drivers/ide/pci/pdc202xx_new.c
@@ -149,6 +149,7 @@
 static void pdcnew_set_dma_mode(ide_drive_t *drive, const u8 speed)
 {
 	ide_hwif_t *hwif	= HWIF(drive);
+	struct pci_dev *dev	= to_pci_dev(hwif->dev);
 	u8 adj			= (drive->dn & 1) ? 0x08 : 0x00;
 
 	/*
@@ -159,7 +160,7 @@
 	 * As we set up the PLL to output 133 MHz for UltraDMA/133 capable
 	 * chips, we must override the default register settings...
 	 */
-	if (max_dma_rate(hwif->pci_dev) == 4) {
+	if (max_dma_rate(dev) == 4) {
 		u8 mode = speed & 0x07;
 
 		if (speed >= XFER_UDMA_0) {
@@ -186,9 +187,10 @@
 static void pdcnew_set_pio_mode(ide_drive_t *drive, const u8 pio)
 {
 	ide_hwif_t *hwif = drive->hwif;
+	struct pci_dev *dev = to_pci_dev(hwif->dev);
 	u8 adj = (drive->dn & 1) ? 0x08 : 0x00;
 
-	if (max_dma_rate(hwif->pci_dev) == 4) {
+	if (max_dma_rate(dev) == 4) {
 		set_indexed_reg(hwif, 0x0c + adj, pio_timings[pio].reg0c);
 		set_indexed_reg(hwif, 0x0d + adj, pio_timings[pio].reg0d);
 		set_indexed_reg(hwif, 0x13 + adj, pio_timings[pio].reg13);
diff --git a/drivers/ide/pci/pdc202xx_old.c b/drivers/ide/pci/pdc202xx_old.c
index 3a1e081..31a13084 100644
--- a/drivers/ide/pci/pdc202xx_old.c
+++ b/drivers/ide/pci/pdc202xx_old.c
@@ -1,6 +1,4 @@
 /*
- *  linux/drivers/ide/pci/pdc202xx_old.c	Version 0.52	Aug 27, 2007
- *
  *  Copyright (C) 1998-2002		Andre Hedrick <andre@linux-ide.org>
  *  Copyright (C) 2006-2007		MontaVista Software, Inc.
  *  Copyright (C) 2007			Bartlomiej Zolnierkiewicz
@@ -66,7 +64,7 @@
 static void pdc202xx_set_mode(ide_drive_t *drive, const u8 speed)
 {
 	ide_hwif_t *hwif	= HWIF(drive);
-	struct pci_dev *dev	= hwif->pci_dev;
+	struct pci_dev *dev	= to_pci_dev(hwif->dev);
 	u8 drive_pci		= 0x60 + (drive->dn << 2);
 
 	u8			AP = 0, BP = 0, CP = 0;
@@ -144,9 +142,10 @@
 
 static u8 pdc202xx_old_cable_detect (ide_hwif_t *hwif)
 {
+	struct pci_dev *dev = to_pci_dev(hwif->dev);
 	u16 CIS = 0, mask = (hwif->channel) ? (1<<11) : (1<<10);
 
-	pci_read_config_word(hwif->pci_dev, 0x50, &CIS);
+	pci_read_config_word(dev, 0x50, &CIS);
 
 	return (CIS & mask) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
 }
@@ -305,12 +304,14 @@
 
 static void __devinit init_hwif_pdc202xx(ide_hwif_t *hwif)
 {
+	struct pci_dev *dev = to_pci_dev(hwif->dev);
+
 	hwif->set_pio_mode = &pdc202xx_set_pio_mode;
 	hwif->set_dma_mode = &pdc202xx_set_mode;
 
 	hwif->quirkproc = &pdc202xx_quirkproc;
 
-	if (hwif->pci_dev->device != PCI_DEVICE_ID_PROMISE_20246)
+	if (dev->device != PCI_DEVICE_ID_PROMISE_20246)
 		hwif->resetproc = &pdc202xx_reset;
 
 	if (hwif->dma_base == 0)
@@ -319,7 +320,7 @@
 	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 (dev->device != PCI_DEVICE_ID_PROMISE_20246) {
 		if (hwif->cbl != ATA_CBL_PATA40_SHORT)
 			hwif->cbl = pdc202xx_old_cable_detect(hwif);
 
@@ -334,7 +335,7 @@
 	u8 udma_speed_flag = 0, primary_mode = 0, secondary_mode = 0;
 
 	if (hwif->channel) {
-		ide_setup_dma(hwif, dmabase, 8);
+		ide_setup_dma(hwif, dmabase);
 		return;
 	}
 
@@ -358,7 +359,7 @@
 	}
 #endif /* CONFIG_PDC202XX_BURST */
 
-	ide_setup_dma(hwif, dmabase, 8);
+	ide_setup_dma(hwif, dmabase);
 }
 
 static void __devinit pdc202ata4_fixup_irq(struct pci_dev *dev,
diff --git a/drivers/ide/pci/piix.c b/drivers/ide/pci/piix.c
index bd6d3f7..c1a6b68 100644
--- a/drivers/ide/pci/piix.c
+++ b/drivers/ide/pci/piix.c
@@ -1,6 +1,4 @@
 /*
- *  linux/drivers/ide/pci/piix.c	Version 0.54	Sep 5, 2007
- *
  *  Copyright (C) 1998-1999 Andrzej Krzysztofowicz, Author and Maintainer
  *  Copyright (C) 1998-2000 Andre Hedrick <andre@linux-ide.org>
  *  Copyright (C) 2003 Red Hat Inc <alan@redhat.com>
@@ -8,53 +6,8 @@
  *
  *  May be copied or modified under the terms of the GNU General Public License
  *
- *  PIO mode setting function for Intel chipsets.
- *  For use instead of BIOS settings.
+ * Documentation:
  *
- * 40-41
- * 42-43
- * 
- *                 41
- *                 43
- *
- * | PIO 0       | c0 | 80 | 0 |
- * | PIO 2 | SW2 | d0 | 90 | 4 |
- * | PIO 3 | MW1 | e1 | a1 | 9 |
- * | PIO 4 | MW2 | e3 | a3 | b |
- *
- * sitre = word40 & 0x4000; primary
- * sitre = word42 & 0x4000; secondary
- *
- * 44 8421|8421    hdd|hdb
- *
- * 48 8421         hdd|hdc|hdb|hda udma enabled
- *
- *    0001         hda
- *    0010         hdb
- *    0100         hdc
- *    1000         hdd
- *
- * 4a 84|21        hdb|hda
- * 4b 84|21        hdd|hdc
- *
- *    ata-33/82371AB
- *    ata-33/82371EB
- *    ata-33/82801AB            ata-66/82801AA
- *    00|00 udma 0              00|00 reserved
- *    01|01 udma 1              01|01 udma 3
- *    10|10 udma 2              10|10 udma 4
- *    11|11 reserved            11|11 reserved
- *
- * 54 8421|8421    ata66 drive|ata66 enable
- *
- * pci_read_config_word(HWIF(drive)->pci_dev, 0x40, &reg40);
- * pci_read_config_word(HWIF(drive)->pci_dev, 0x42, &reg42);
- * pci_read_config_word(HWIF(drive)->pci_dev, 0x44, &reg44);
- * pci_read_config_byte(HWIF(drive)->pci_dev, 0x48, &reg48);
- * pci_read_config_word(HWIF(drive)->pci_dev, 0x4a, &reg4a);
- * pci_read_config_byte(HWIF(drive)->pci_dev, 0x54, &reg54);
- *
- * Documentation
  *	Publically available from Intel web site. Errata documentation
  * is also publically available. As an aide to anyone hacking on this
  * driver the list of errata that are relevant is below.going back to
@@ -116,7 +69,7 @@
 static void piix_set_pio_mode(ide_drive_t *drive, const u8 pio)
 {
 	ide_hwif_t *hwif	= HWIF(drive);
-	struct pci_dev *dev	= hwif->pci_dev;
+	struct pci_dev *dev	= to_pci_dev(hwif->dev);
 	int is_slave		= drive->dn & 1;
 	int master_port		= hwif->channel ? 0x42 : 0x40;
 	int slave_port		= 0x44;
@@ -185,7 +138,7 @@
 static void piix_set_dma_mode(ide_drive_t *drive, const u8 speed)
 {
 	ide_hwif_t *hwif	= HWIF(drive);
-	struct pci_dev *dev	= hwif->pci_dev;
+	struct pci_dev *dev	= to_pci_dev(hwif->dev);
 	u8 maslave		= hwif->channel ? 0x42 : 0x40;
 	int a_speed		= 3 << (drive->dn * 4);
 	int u_flag		= 1 << drive->dn;
@@ -305,7 +258,7 @@
 
 static u8 __devinit piix_cable_detect(ide_hwif_t *hwif)
 {
-	struct pci_dev *pdev = hwif->pci_dev;
+	struct pci_dev *pdev = to_pci_dev(hwif->dev);
 	const struct ich_laptop *lap = &ich_laptop[0];
 	u8 reg54h = 0, mask = hwif->channel ? 0xc0 : 0x30;
 
diff --git a/drivers/ide/pci/rz1000.c b/drivers/ide/pci/rz1000.c
index 6b10ae2..7ed6625 100644
--- a/drivers/ide/pci/rz1000.c
+++ b/drivers/ide/pci/rz1000.c
@@ -1,6 +1,4 @@
 /*
- *  linux/drivers/ide/pci/rz1000.c	Version 0.06	January 12, 2003
- *
  *  Copyright (C) 1995-1998  Linus Torvalds & author (see below)
  */
 
@@ -32,8 +30,8 @@
 
 static void __devinit init_hwif_rz1000 (ide_hwif_t *hwif)
 {
+	struct pci_dev *dev = to_pci_dev(hwif->dev);
 	u16 reg;
-	struct pci_dev *dev = hwif->pci_dev;
 
 	if (!pci_read_config_word (dev, 0x40, &reg) &&
 	    !pci_write_config_word(dev, 0x40, reg & 0xdfff)) {
diff --git a/drivers/ide/pci/sc1200.c b/drivers/ide/pci/sc1200.c
index 32fdf53..af499a6 100644
--- a/drivers/ide/pci/sc1200.c
+++ b/drivers/ide/pci/sc1200.c
@@ -1,6 +1,4 @@
 /*
- * linux/drivers/ide/pci/sc1200.c		Version 0.97	Aug 3 2007
- *
  * Copyright (C) 2000-2002		Mark Lord <mlord@pobox.com>
  * Copyright (C)      2007		Bartlomiej Zolnierkiewicz
  *
@@ -87,7 +85,7 @@
 static void sc1200_tunepio(ide_drive_t *drive, u8 pio)
 {
 	ide_hwif_t *hwif = drive->hwif;
-	struct pci_dev *pdev = hwif->pci_dev;
+	struct pci_dev *pdev = to_pci_dev(hwif->dev);
 	unsigned int basereg = hwif->channel ? 0x50 : 0x40, format = 0;
 
 	pci_read_config_dword(pdev, basereg + 4, &format);
@@ -130,6 +128,7 @@
 static void sc1200_set_dma_mode(ide_drive_t *drive, const u8 mode)
 {
 	ide_hwif_t		*hwif = HWIF(drive);
+	struct pci_dev		*dev = to_pci_dev(hwif->dev);
 	int			unit = drive->select.b.unit;
 	unsigned int		reg, timings;
 	unsigned short		pci_clock;
@@ -160,12 +159,11 @@
 		timings = mwdma_timing[pci_clock][mode - XFER_MW_DMA_0];
 
 	if (unit == 0) {			/* are we configuring drive0? */
-		pci_read_config_dword(hwif->pci_dev, basereg+4, &reg);
+		pci_read_config_dword(dev, basereg + 4, &reg);
 		timings |= reg & 0x80000000;	/* preserve PIO format bit */
-		pci_write_config_dword(hwif->pci_dev, basereg+4, timings);
-	} else {
-		pci_write_config_dword(hwif->pci_dev, basereg+12, timings);
-	}
+		pci_write_config_dword(dev, basereg + 4, timings);
+	} else
+		pci_write_config_dword(dev, basereg + 12, timings);
 }
 
 /*  Replacement for the standard ide_dma_end action in
diff --git a/drivers/ide/pci/scc_pata.c b/drivers/ide/pci/scc_pata.c
index 24a85bb..7694969 100644
--- a/drivers/ide/pci/scc_pata.c
+++ b/drivers/ide/pci/scc_pata.c
@@ -594,7 +594,7 @@
 
 static void __devinit init_mmio_iops_scc(ide_hwif_t *hwif)
 {
-	struct pci_dev *dev = hwif->pci_dev;
+	struct pci_dev *dev = to_pci_dev(hwif->dev);
 	struct scc_ports *ports = pci_get_drvdata(dev);
 	unsigned long dma_base = ports->dma;
 
@@ -620,7 +620,7 @@
 	hwif->io_ports[IDE_STATUS_OFFSET] = dma_base + 0x3c;
 	hwif->io_ports[IDE_CONTROL_OFFSET] = dma_base + 0x40;
 
-	hwif->irq = hwif->pci_dev->irq;
+	hwif->irq = dev->irq;
 	hwif->dma_base = dma_base;
 	hwif->config_data = ports->ctl;
 	hwif->mmio = 1;
@@ -636,7 +636,8 @@
 
 static void __devinit init_iops_scc(ide_hwif_t *hwif)
 {
-	struct pci_dev *dev =  hwif->pci_dev;
+	struct pci_dev *dev = to_pci_dev(hwif->dev);
+
 	hwif->hwif_data = NULL;
 	if (pci_get_drvdata(dev) == NULL)
 		return;
@@ -726,10 +727,8 @@
 	unsigned long dma_size = pci_resource_len(dev, 1);
 
 	if (hwif->dmatable_cpu) {
-		pci_free_consistent(hwif->pci_dev,
-				    PRD_ENTRIES * PRD_BYTES,
-				    hwif->dmatable_cpu,
-				    hwif->dmatable_dma);
+		pci_free_consistent(dev, PRD_ENTRIES * PRD_BYTES,
+				    hwif->dmatable_cpu, hwif->dmatable_dma);
 		hwif->dmatable_cpu = NULL;
 	}
 
diff --git a/drivers/ide/pci/serverworks.c b/drivers/ide/pci/serverworks.c
index 877c09b..f495253 100644
--- a/drivers/ide/pci/serverworks.c
+++ b/drivers/ide/pci/serverworks.c
@@ -1,6 +1,4 @@
 /*
- * linux/drivers/ide/pci/serverworks.c		Version 0.22	Jun 27 2007
- *
  * Copyright (C) 1998-2000 Michel Aubry
  * Copyright (C) 1998-2000 Andrzej Krzysztofowicz
  * Copyright (C) 1998-2000 Andre Hedrick <andre@linux-ide.org>
@@ -67,7 +65,7 @@
 
 static u8 svwks_udma_filter(ide_drive_t *drive)
 {
-	struct pci_dev *dev     = HWIF(drive)->pci_dev;
+	struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
 	u8 mask = 0;
 
 	if (dev->device == PCI_DEVICE_ID_SERVERWORKS_HT1000IDE)
@@ -130,7 +128,7 @@
 	static const u8 pio_modes[] = { 0x5d, 0x47, 0x34, 0x22, 0x20 };
 	static const u8 drive_pci[] = { 0x41, 0x40, 0x43, 0x42 };
 
-	struct pci_dev *dev = drive->hwif->pci_dev;
+	struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
 
 	pci_write_config_byte(dev, drive_pci[drive->dn], pio_modes[pio]);
 
@@ -153,7 +151,7 @@
 	static const u8 drive_pci2[]		= { 0x45, 0x44, 0x47, 0x46 };
 
 	ide_hwif_t *hwif	= HWIF(drive);
-	struct pci_dev *dev	= hwif->pci_dev;
+	struct pci_dev *dev	= to_pci_dev(hwif->dev);
 	u8 unit			= (drive->select.b.unit & 0x01);
 
 	u8 ultra_enable	 = 0, ultra_timing = 0, dma_timing = 0;
@@ -287,7 +285,8 @@
  */
 static u8 __devinit ata66_svwks_dell(ide_hwif_t *hwif)
 {
-	struct pci_dev *dev = hwif->pci_dev;
+	struct pci_dev *dev = to_pci_dev(hwif->dev);
+
 	if (dev->subsystem_vendor == PCI_VENDOR_ID_DELL &&
 	    dev->vendor	== PCI_VENDOR_ID_SERVERWORKS &&
 	    (dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5IDE ||
@@ -305,7 +304,8 @@
  */
 static u8 __devinit ata66_svwks_cobalt(ide_hwif_t *hwif)
 {
-	struct pci_dev *dev = hwif->pci_dev;
+	struct pci_dev *dev = to_pci_dev(hwif->dev);
+
 	if (dev->subsystem_vendor == PCI_VENDOR_ID_SUN &&
 	    dev->vendor	== PCI_VENDOR_ID_SERVERWORKS &&
 	    dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5IDE)
@@ -316,7 +316,7 @@
 
 static u8 __devinit ata66_svwks(ide_hwif_t *hwif)
 {
-	struct pci_dev *dev = hwif->pci_dev;
+	struct pci_dev *dev = to_pci_dev(hwif->dev);
 
 	/* Server Works */
 	if (dev->subsystem_vendor == PCI_VENDOR_ID_SERVERWORKS)
@@ -340,6 +340,8 @@
 
 static void __devinit init_hwif_svwks (ide_hwif_t *hwif)
 {
+	struct pci_dev *dev = to_pci_dev(hwif->dev);
+
 	hwif->set_pio_mode = &svwks_set_pio_mode;
 	hwif->set_dma_mode = &svwks_set_dma_mode;
 	hwif->udma_filter = &svwks_udma_filter;
@@ -347,7 +349,7 @@
 	if (!hwif->dma_base)
 		return;
 
-	if (hwif->pci_dev->device != PCI_DEVICE_ID_SERVERWORKS_OSB4IDE) {
+	if (dev->device != PCI_DEVICE_ID_SERVERWORKS_OSB4IDE) {
 		if (hwif->cbl != ATA_CBL_PATA40_SHORT)
 			hwif->cbl = ata66_svwks(hwif);
 	}
@@ -418,7 +420,9 @@
 
 	d = serverworks_chipsets[idx];
 
-	if (idx == 2 || idx == 3) {
+	if (idx == 1)
+		d.host_flags |= IDE_HFLAG_CLEAR_SIMPLEX;
+	else if (idx == 2 || idx == 3) {
 		if ((PCI_FUNC(dev->devfn) & 1) == 0) {
 			if (pci_resource_start(dev, 0) != 0x01f1)
 				d.host_flags &= ~IDE_HFLAG_BOOTABLE;
diff --git a/drivers/ide/pci/sgiioc4.c b/drivers/ide/pci/sgiioc4.c
index 9e0be7d..8590207 100644
--- a/drivers/ide/pci/sgiioc4.c
+++ b/drivers/ide/pci/sgiioc4.c
@@ -159,6 +159,7 @@
 		}
 
 		if (intr_reg & 0x02) {
+			struct pci_dev *dev = to_pci_dev(hwif->dev);
 			/* Error when transferring DMA data on PCI bus */
 			u32 pci_err_addr_low, pci_err_addr_high,
 			    pci_stat_cmd_reg;
@@ -167,7 +168,7 @@
 				readl((void __iomem *)hwif->io_ports[IDE_IRQ_OFFSET]);
 			pci_err_addr_high =
 				readl((void __iomem *)(hwif->io_ports[IDE_IRQ_OFFSET] + 4));
-			pci_read_config_dword(hwif->pci_dev, PCI_COMMAND,
+			pci_read_config_dword(dev, PCI_COMMAND,
 					      &pci_stat_cmd_reg);
 			printk(KERN_ERR
 			       "%s(%s) : PCI Bus Error when doing DMA:"
@@ -178,8 +179,7 @@
 			       __FUNCTION__, drive->name,
 			       pci_err_addr_high, pci_err_addr_low);
 			/* Clear the PCI Error indicator */
-			pci_write_config_dword(hwif->pci_dev, PCI_COMMAND,
-					       0x00000146);
+			pci_write_config_dword(dev, PCI_COMMAND, 0x00000146);
 		}
 
 		/* Clear the Interrupt, Error bits on the IOC4 */
@@ -334,6 +334,7 @@
 static int __devinit
 ide_dma_sgiioc4(ide_hwif_t * hwif, unsigned long dma_base)
 {
+	struct pci_dev *dev = to_pci_dev(hwif->dev);
 	void __iomem *virt_dma_base;
 	int num_ports = sizeof (ioc4_dma_regs_t);
 	void *pad;
@@ -359,7 +360,7 @@
 	}
 	hwif->dma_base = (unsigned long) virt_dma_base;
 
-	hwif->dmatable_cpu = pci_alloc_consistent(hwif->pci_dev,
+	hwif->dmatable_cpu = pci_alloc_consistent(dev,
 					  IOC4_PRD_ENTRIES * IOC4_PRD_BYTES,
 					  &hwif->dmatable_dma);
 
@@ -368,7 +369,7 @@
 
 	hwif->sg_max_nents = IOC4_PRD_ENTRIES;
 
-	pad = pci_alloc_consistent(hwif->pci_dev, IOC4_IDE_CACHELINE_SIZE,
+	pad = pci_alloc_consistent(dev, IOC4_IDE_CACHELINE_SIZE,
 				   (dma_addr_t *) &(hwif->dma_status));
 
 	if (pad) {
@@ -376,8 +377,7 @@
 		return 0;
 	}
 
-	pci_free_consistent(hwif->pci_dev,
-			    IOC4_PRD_ENTRIES * IOC4_PRD_BYTES,
+	pci_free_consistent(dev, IOC4_PRD_ENTRIES * IOC4_PRD_BYTES,
 			    hwif->dmatable_cpu, hwif->dmatable_dma);
 	printk(KERN_INFO
 	       "%s() -- Error! Unable to allocate DMA Maps for drive %s\n",
@@ -517,8 +517,7 @@
 	}
 
 use_pio_instead:
-	pci_unmap_sg(hwif->pci_dev, hwif->sg_table, hwif->sg_nents,
-		     hwif->sg_dma_direction);
+	ide_destroy_dmatable(drive);
 
 	return 0;		/* revert to PIO for this request */
 }
@@ -641,7 +640,7 @@
 	hw.dev = &dev->dev;
 	ide_init_port_hw(hwif, &hw);
 
-	hwif->pci_dev = dev;
+	hwif->dev = &dev->dev;
 	hwif->channel = 0;	/* Single Channel chip */
 
 	/* The IOC4 uses MMIO rather than Port IO. */
diff --git a/drivers/ide/pci/siimage.c b/drivers/ide/pci/siimage.c
index 908f37b..4877bc8 100644
--- a/drivers/ide/pci/siimage.c
+++ b/drivers/ide/pci/siimage.c
@@ -1,6 +1,4 @@
 /*
- * linux/drivers/ide/pci/siimage.c		Version 1.19	Nov 16 2007
- *
  * Copyright (C) 2001-2002	Andre Hedrick <andre@linux-ide.org>
  * Copyright (C) 2003		Red Hat <alan@redhat.com>
  * Copyright (C) 2007		MontaVista Software, Inc.
@@ -79,7 +77,7 @@
  
 static inline int is_sata(ide_hwif_t *hwif)
 {
-	return pdev_is_sata(hwif->pci_dev);
+	return pdev_is_sata(to_pci_dev(hwif->dev));
 }
 
 /**
@@ -140,13 +138,14 @@
 static u8 sil_pata_udma_filter(ide_drive_t *drive)
 {
 	ide_hwif_t *hwif = drive->hwif;
+	struct pci_dev *dev = to_pci_dev(hwif->dev);
 	unsigned long base = (unsigned long) hwif->hwif_data;
 	u8 mask = 0, scsc = 0;
 
 	if (hwif->mmio)
 		scsc = hwif->INB(base + 0x4A);
 	else
-		pci_read_config_byte(hwif->pci_dev, 0x8A, &scsc);
+		pci_read_config_byte(dev, 0x8A, &scsc);
 
 	if ((scsc & 0x30) == 0x10)	/* 133 */
 		mask = ATA_UDMA6;
@@ -219,19 +218,21 @@
 		mode |= (unit ? 0x10 : 0x01);
 		hwif->OUTB(mode, base + addr_mask);
 	} else {
-		pci_write_config_word(hwif->pci_dev, addr, speedp);
-		pci_write_config_word(hwif->pci_dev, tfaddr, speedt);
-		pci_read_config_word(hwif->pci_dev, tfaddr-2, &speedp);
+		struct pci_dev *dev = to_pci_dev(hwif->dev);
+
+		pci_write_config_word(dev, addr, speedp);
+		pci_write_config_word(dev, tfaddr, speedt);
+		pci_read_config_word(dev, tfaddr - 2, &speedp);
 		speedp &= ~0x200;
 		/* Set IORDY for mode 3 or 4 */
 		if (pio > 2)
 			speedp |= 0x200;
-		pci_write_config_word(hwif->pci_dev, tfaddr-2, speedp);
+		pci_write_config_word(dev, tfaddr - 2, speedp);
 
-		pci_read_config_byte(hwif->pci_dev, addr_mask, &mode);
+		pci_read_config_byte(dev, addr_mask, &mode);
 		mode &= ~(unit ? 0x30 : 0x03);
 		mode |= (unit ? 0x10 : 0x01);
-		pci_write_config_byte(hwif->pci_dev, addr_mask, mode);
+		pci_write_config_byte(dev, addr_mask, mode);
 	}
 }
 
@@ -250,6 +251,7 @@
 	u16 dma[]		= { 0x2208, 0x10C2, 0x10C1 };
 
 	ide_hwif_t *hwif	= HWIF(drive);
+	struct pci_dev *dev	= to_pci_dev(hwif->dev);
 	u16 ultra = 0, multi	= 0;
 	u8 mode = 0, unit	= drive->select.b.unit;
 	unsigned long base	= (unsigned long)hwif->hwif_data;
@@ -266,10 +268,10 @@
 		multi = hwif->INW(ma);
 		ultra = hwif->INW(ua);
 	} else {
-		pci_read_config_byte(hwif->pci_dev, 0x8A, &scsc);
-		pci_read_config_byte(hwif->pci_dev, addr_mask, &mode);
-		pci_read_config_word(hwif->pci_dev, ma, &multi);
-		pci_read_config_word(hwif->pci_dev, ua, &ultra);
+		pci_read_config_byte(dev, 0x8A, &scsc);
+		pci_read_config_byte(dev, addr_mask, &mode);
+		pci_read_config_word(dev, ma, &multi);
+		pci_read_config_word(dev, ua, &ultra);
 	}
 
 	mode &= ~((unit) ? 0x30 : 0x03);
@@ -293,9 +295,9 @@
 		hwif->OUTW(multi, ma);
 		hwif->OUTW(ultra, ua);
 	} else {
-		pci_write_config_byte(hwif->pci_dev, addr_mask, mode);
-		pci_write_config_word(hwif->pci_dev, ma, multi);
-		pci_write_config_word(hwif->pci_dev, ua, ultra);
+		pci_write_config_byte(dev, addr_mask, mode);
+		pci_write_config_word(dev, ma, multi);
+		pci_write_config_word(dev, ua, ultra);
 	}
 }
 
@@ -303,6 +305,7 @@
 static int siimage_io_ide_dma_test_irq (ide_drive_t *drive)
 {
 	ide_hwif_t *hwif	= HWIF(drive);
+	struct pci_dev *dev	= to_pci_dev(hwif->dev);
 	u8 dma_altstat		= 0;
 	unsigned long addr	= siimage_selreg(hwif, 1);
 
@@ -311,7 +314,7 @@
 		return 1;
 
 	/* return 1 if Device INTR asserted */
-	pci_read_config_byte(hwif->pci_dev, addr, &dma_altstat);
+	pci_read_config_byte(dev, addr, &dma_altstat);
 	if (dma_altstat & 8)
 		return 0;	//return 1;
 	return 0;
@@ -377,13 +380,14 @@
 static int sil_sata_busproc(ide_drive_t * drive, int state)
 {
 	ide_hwif_t *hwif	= HWIF(drive);
+	struct pci_dev *dev	= to_pci_dev(hwif->dev);
 	u32 stat_config		= 0;
 	unsigned long addr	= siimage_selreg(hwif, 0);
 
 	if (hwif->mmio)
 		stat_config = readl((void __iomem *)addr);
 	else
-		pci_read_config_dword(hwif->pci_dev, addr, &stat_config);
+		pci_read_config_dword(dev, addr, &stat_config);
 
 	switch (state) {
 		case BUSSTATE_ON:
@@ -643,7 +647,7 @@
 
 static void __devinit init_mmio_iops_siimage(ide_hwif_t *hwif)
 {
-	struct pci_dev *dev	= hwif->pci_dev;
+	struct pci_dev *dev	= to_pci_dev(hwif->dev);
 	void *addr		= pci_get_drvdata(dev);
 	u8 ch			= hwif->channel;
 	hw_regs_t		hw;
@@ -756,12 +760,14 @@
 
 static void __devinit init_iops_siimage(ide_hwif_t *hwif)
 {
+	struct pci_dev *dev = to_pci_dev(hwif->dev);
+
 	hwif->hwif_data = NULL;
 
 	/* Pessimal until we finish probing */
 	hwif->rqsize = 15;
 
-	if (pci_get_drvdata(hwif->pci_dev) == NULL)
+	if (pci_get_drvdata(dev) == NULL)
 		return;
 
 	init_mmio_iops_siimage(hwif);
@@ -777,11 +783,12 @@
 
 static u8 __devinit ata66_siimage(ide_hwif_t *hwif)
 {
+	struct pci_dev *dev = to_pci_dev(hwif->dev);
 	unsigned long addr = siimage_selreg(hwif, 0);
 	u8 ata66 = 0;
 
-	if (pci_get_drvdata(hwif->pci_dev) == NULL)
-		pci_read_config_byte(hwif->pci_dev, addr, &ata66);
+	if (pci_get_drvdata(dev) == NULL)
+		pci_read_config_byte(dev, addr, &ata66);
 	else
 		ata66 = hwif->INB(addr);
 
diff --git a/drivers/ide/pci/sis5513.c b/drivers/ide/pci/sis5513.c
index 85d3699..2a461de 100644
--- a/drivers/ide/pci/sis5513.c
+++ b/drivers/ide/pci/sis5513.c
@@ -1,6 +1,4 @@
 /*
- * linux/drivers/ide/pci/sis5513.c	Version 0.31	Aug 9, 2007
- *
  * Copyright (C) 1999-2000	Andre Hedrick <andre@linux-ide.org>
  * Copyright (C) 2002		Lionel Bouton <Lionel.Bouton@inet6.fr>, Maintainer
  * Copyright (C) 2003		Vojtech Pavlik <vojtech@suse.cz>
@@ -197,7 +195,7 @@
 
 static u8 sis_ata133_get_base(ide_drive_t *drive)
 {
-	struct pci_dev *dev = drive->hwif->pci_dev;
+	struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
 	u32 reg54 = 0;
 
 	pci_read_config_dword(dev, 0x54, &reg54);
@@ -207,7 +205,7 @@
 
 static void sis_ata16_program_timings(ide_drive_t *drive, const u8 mode)
 {
-	struct pci_dev *dev = drive->hwif->pci_dev;
+	struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
 	u16 t1 = 0;
 	u8 drive_pci = 0x40 + drive->dn * 2;
 
@@ -230,7 +228,7 @@
 
 static void sis_ata100_program_timings(ide_drive_t *drive, const u8 mode)
 {
-	struct pci_dev *dev = drive->hwif->pci_dev;
+	struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
 	u8 t1, drive_pci = 0x40 + drive->dn * 2;
 
 	/* timing bits: 7:4 active 3:0 recovery */
@@ -253,7 +251,7 @@
 
 static void sis_ata133_program_timings(ide_drive_t *drive, const u8 mode)
 {
-	struct pci_dev *dev = drive->hwif->pci_dev;
+	struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
 	u32 t1 = 0;
 	u8 drive_pci = sis_ata133_get_base(drive), clk, idx;
 
@@ -286,7 +284,7 @@
 static void config_drive_art_rwp (ide_drive_t *drive)
 {
 	ide_hwif_t *hwif	= HWIF(drive);
-	struct pci_dev *dev	= hwif->pci_dev;
+	struct pci_dev *dev	= to_pci_dev(hwif->dev);
 	u8 reg4bh		= 0;
 	u8 rw_prefetch		= 0;
 
@@ -307,7 +305,7 @@
 
 static void sis_ata133_program_udma_timings(ide_drive_t *drive, const u8 mode)
 {
-	struct pci_dev *dev = drive->hwif->pci_dev;
+	struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
 	u32 regdw = 0;
 	u8 drive_pci = sis_ata133_get_base(drive), clk, idx;
 
@@ -326,7 +324,7 @@
 
 static void sis_ata33_program_udma_timings(ide_drive_t *drive, const u8 mode)
 {
-	struct pci_dev *dev = drive->hwif->pci_dev;
+	struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
 	u8 drive_pci = 0x40 + drive->dn * 2, reg = 0, i = chipset_family;
 
 	pci_read_config_byte(dev, drive_pci + 1, &reg);
@@ -359,7 +357,7 @@
 
 static u8 sis5513_ata133_udma_filter(ide_drive_t *drive)
 {
-	struct pci_dev *dev = drive->hwif->pci_dev;
+	struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
 	u32 regdw = 0;
 	u8 drive_pci = sis_ata133_get_base(drive);
 
@@ -530,7 +528,7 @@
 
 static u8 __devinit ata66_sis5513(ide_hwif_t *hwif)
 {
-	struct pci_dev *pdev = hwif->pci_dev;
+	struct pci_dev *pdev = to_pci_dev(hwif->dev);
 	const struct sis_laptop *lap = &sis_laptop[0];
 	u8 ata66 = 0;
 
@@ -545,12 +543,12 @@
 	if (chipset_family >= ATA_133) {
 		u16 regw = 0;
 		u16 reg_addr = hwif->channel ? 0x52: 0x50;
-		pci_read_config_word(hwif->pci_dev, reg_addr, &regw);
+		pci_read_config_word(pdev, reg_addr, &regw);
 		ata66 = (regw & 0x8000) ? 0 : 1;
 	} else if (chipset_family >= ATA_66) {
 		u8 reg48h = 0;
 		u8 mask = hwif->channel ? 0x20 : 0x10;
-		pci_read_config_byte(hwif->pci_dev, 0x48, &reg48h);
+		pci_read_config_byte(pdev, 0x48, &reg48h);
 		ata66 = (reg48h & mask) ? 0 : 1;
 	}
 
diff --git a/drivers/ide/pci/sl82c105.c b/drivers/ide/pci/sl82c105.c
index c7a125b..da13a12 100644
--- a/drivers/ide/pci/sl82c105.c
+++ b/drivers/ide/pci/sl82c105.c
@@ -1,6 +1,4 @@
 /*
- * linux/drivers/ide/pci/sl82c105.c
- *
  * SL82C105/Winbond 553 IDE driver
  *
  * Maintainer unknown.
@@ -78,7 +76,7 @@
  */
 static void sl82c105_set_pio_mode(ide_drive_t *drive, const u8 pio)
 {
-	struct pci_dev *dev	= HWIF(drive)->pci_dev;
+	struct pci_dev *dev	= to_pci_dev(drive->hwif->dev);
 	int reg			= 0x44 + drive->dn * 4;
 	u16 drv_ctrl;
 
@@ -147,7 +145,7 @@
 static void sl82c105_dma_lost_irq(ide_drive_t *drive)
 {
 	ide_hwif_t *hwif	= HWIF(drive);
-	struct pci_dev *dev	= hwif->pci_dev;
+	struct pci_dev *dev	= to_pci_dev(hwif->dev);
 	u32 val, mask		= hwif->channel ? CTRL_IDE_IRQB : CTRL_IDE_IRQA;
 	u8 dma_cmd;
 
@@ -184,7 +182,7 @@
 static void sl82c105_dma_start(ide_drive_t *drive)
 {
 	ide_hwif_t *hwif	= HWIF(drive);
-	struct pci_dev *dev	= hwif->pci_dev;
+	struct pci_dev *dev	= to_pci_dev(hwif->dev);
 	int reg 		= 0x44 + drive->dn * 4;
 
 	DBG(("%s(drive:%s)\n", __FUNCTION__, drive->name));
@@ -197,15 +195,17 @@
 
 static void sl82c105_dma_timeout(ide_drive_t *drive)
 {
+	struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
+
 	DBG(("sl82c105_dma_timeout(drive:%s)\n", drive->name));
 
-	sl82c105_reset_host(HWIF(drive)->pci_dev);
+	sl82c105_reset_host(dev);
 	ide_dma_timeout(drive);
 }
 
 static int sl82c105_dma_end(ide_drive_t *drive)
 {
-	struct pci_dev *dev	= HWIF(drive)->pci_dev;
+	struct pci_dev *dev	= to_pci_dev(drive->hwif->dev);
 	int reg 		= 0x44 + drive->dn * 4;
 	int ret;
 
@@ -224,7 +224,7 @@
  */
 static void sl82c105_resetproc(ide_drive_t *drive)
 {
-	struct pci_dev *dev = HWIF(drive)->pci_dev;
+	struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
 	u32 val;
 
 	DBG(("sl82c105_resetproc(drive:%s)\n", drive->name));
@@ -293,6 +293,7 @@
  */
 static void __devinit init_hwif_sl82c105(ide_hwif_t *hwif)
 {
+	struct pci_dev *dev = to_pci_dev(hwif->dev);
 	unsigned int rev;
 
 	DBG(("init_hwif_sl82c105(hwif: ide%d)\n", hwif->index));
@@ -304,7 +305,7 @@
 	if (!hwif->dma_base)
 		return;
 
-	rev = sl82c105_bridge_revision(hwif->pci_dev);
+	rev = sl82c105_bridge_revision(dev);
 	if (rev <= 5) {
 		/*
 		 * Never ever EVER under any circumstances enable
diff --git a/drivers/ide/pci/slc90e66.c b/drivers/ide/pci/slc90e66.c
index dbbb468..a6cf810 100644
--- a/drivers/ide/pci/slc90e66.c
+++ b/drivers/ide/pci/slc90e66.c
@@ -1,6 +1,4 @@
 /*
- *  linux/drivers/ide/pci/slc90e66.c	Version 0.19	Sep 24, 2007
- *
  *  Copyright (C) 2000-2002 Andre Hedrick <andre@linux-ide.org>
  *  Copyright (C) 2006-2007 MontaVista Software, Inc. <source@mvista.com>
  *
@@ -26,7 +24,7 @@
 static void slc90e66_set_pio_mode(ide_drive_t *drive, const u8 pio)
 {
 	ide_hwif_t *hwif	= HWIF(drive);
-	struct pci_dev *dev	= hwif->pci_dev;
+	struct pci_dev *dev	= to_pci_dev(hwif->dev);
 	int is_slave		= drive->dn & 1;
 	int master_port		= hwif->channel ? 0x42 : 0x40;
 	int slave_port		= 0x44;
@@ -79,7 +77,7 @@
 static void slc90e66_set_dma_mode(ide_drive_t *drive, const u8 speed)
 {
 	ide_hwif_t *hwif	= HWIF(drive);
-	struct pci_dev *dev	= hwif->pci_dev;
+	struct pci_dev *dev	= to_pci_dev(hwif->dev);
 	u8 maslave		= hwif->channel ? 0x42 : 0x40;
 	int sitre = 0, a_speed	= 7 << (drive->dn * 4);
 	int u_speed = 0, u_flag = 1 << drive->dn;
@@ -122,13 +120,14 @@
 
 static void __devinit init_hwif_slc90e66 (ide_hwif_t *hwif)
 {
+	struct pci_dev *dev = to_pci_dev(hwif->dev);
 	u8 reg47 = 0;
 	u8 mask = hwif->channel ? 0x01 : 0x02;  /* bit0:Primary */
 
 	hwif->set_pio_mode = &slc90e66_set_pio_mode;
 	hwif->set_dma_mode = &slc90e66_set_dma_mode;
 
-	pci_read_config_byte(hwif->pci_dev, 0x47, &reg47);
+	pci_read_config_byte(dev, 0x47, &reg47);
 
 	if (hwif->dma_base == 0)
 		return;
diff --git a/drivers/ide/pci/tc86c001.c b/drivers/ide/pci/tc86c001.c
index e1faf6c..9fbbb4f 100644
--- a/drivers/ide/pci/tc86c001.c
+++ b/drivers/ide/pci/tc86c001.c
@@ -1,6 +1,4 @@
 /*
- * drivers/ide/pci/tc86c001.c	Version 1.01	Sep 5, 2007
- *
  * Copyright (C) 2002 Toshiba Corporation
  * Copyright (C) 2005-2006 MontaVista Software, Inc. <source@mvista.com>
  *
@@ -164,7 +162,8 @@
 
 static void __devinit init_hwif_tc86c001(ide_hwif_t *hwif)
 {
-	unsigned long sc_base	= pci_resource_start(hwif->pci_dev, 5);
+	struct pci_dev *dev	= to_pci_dev(hwif->dev);
+	unsigned long sc_base	= pci_resource_start(dev, 5);
 	u16 scr1		= inw(sc_base + 0x00);
 
 	/* System Control 1 Register bit 15 (Soft Reset) set */
diff --git a/drivers/ide/pci/triflex.c b/drivers/ide/pci/triflex.c
index ae52a96..852b726 100644
--- a/drivers/ide/pci/triflex.c
+++ b/drivers/ide/pci/triflex.c
@@ -1,6 +1,4 @@
 /*
- * triflex.c
- * 
  * IDE Chipset driver for the Compaq TriFlex IDE controller.
  * 
  * Known to work with the Compaq Workstation 5x00 series.
@@ -43,7 +41,7 @@
 static void triflex_set_mode(ide_drive_t *drive, const u8 speed)
 {
 	ide_hwif_t *hwif = HWIF(drive);
-	struct pci_dev *dev = hwif->pci_dev;
+	struct pci_dev *dev = to_pci_dev(hwif->dev);
 	u8 channel_offset = hwif->channel ? 0x74 : 0x70;
 	u16 timing = 0;
 	u32 triflex_timings = 0;
diff --git a/drivers/ide/pci/trm290.c b/drivers/ide/pci/trm290.c
index 04cd893..d9ebb69 100644
--- a/drivers/ide/pci/trm290.c
+++ b/drivers/ide/pci/trm290.c
@@ -1,8 +1,7 @@
 /*
- *  linux/drivers/ide/pci/trm290.c		Version 1.05	Dec. 26, 2007
- *
  *  Copyright (c) 1997-1998  Mark Lord
  *  Copyright (c) 2007       MontaVista Software, Inc. <source@mvista.com>
+ *
  *  May be copied or modified under the terms of the GNU General Public License
  *
  *  June 22, 2004 - get rid of check_region
@@ -209,10 +208,10 @@
 	}
 	/* select DMA xfer */
 	trm290_prepare_drive(drive, 1);
-	outl(hwif->dmatable_dma | rw, hwif->dma_command);
+	outl(hwif->dmatable_dma | rw, hwif->dma_base);
 	drive->waiting_for_dma = 1;
 	/* start DMA */
-	outw((count * 2) - 1, hwif->dma_status);
+	outw(count * 2 - 1, hwif->dma_base + 2);
 	return 0;
 }
 
@@ -222,23 +221,21 @@
 
 static int trm290_ide_dma_end (ide_drive_t *drive)
 {
-	ide_hwif_t *hwif = HWIF(drive);
-	u16 status = 0;
+	u16 status;
 
 	drive->waiting_for_dma = 0;
 	/* purge DMA mappings */
 	ide_destroy_dmatable(drive);
-	status = inw(hwif->dma_status);
-	return (status != 0x00ff);
+	status = inw(HWIF(drive)->dma_base + 2);
+	return status != 0x00ff;
 }
 
 static int trm290_ide_dma_test_irq (ide_drive_t *drive)
 {
-	ide_hwif_t *hwif = HWIF(drive);
-	u16 status = 0;
+	u16 status;
 
-	status = inw(hwif->dma_status);
-	return (status == 0x00ff);
+	status = inw(HWIF(drive)->dma_base + 2);
+	return status == 0x00ff;
 }
 
 static void trm290_dma_host_set(ide_drive_t *drive, int on)
@@ -247,21 +244,37 @@
 
 static void __devinit init_hwif_trm290(ide_hwif_t *hwif)
 {
-	unsigned int cfgbase = 0;
+	struct pci_dev *dev	= to_pci_dev(hwif->dev);
+	unsigned int  cfg_base	= pci_resource_start(dev, 4);
 	unsigned long flags;
 	u8 reg = 0;
-	struct pci_dev *dev = hwif->pci_dev;
 
-	cfgbase = pci_resource_start(dev, 4);
-	if ((dev->class & 5) && cfgbase) {
-		hwif->config_data = cfgbase;
-		printk(KERN_INFO "TRM290: chip config base at 0x%04lx\n",
-			hwif->config_data);
-	} else {
-		hwif->config_data = 0x3df0;
-		printk(KERN_INFO "TRM290: using default config base at 0x%04lx\n",
-			hwif->config_data);
+	if ((dev->class & 5) && cfg_base)
+		printk(KERN_INFO "TRM290: chip");
+	else {
+		cfg_base = 0x3df0;
+		printk(KERN_INFO "TRM290: using default");
 	}
+	printk(KERN_CONT " config base at 0x%04x\n", cfg_base);
+	hwif->config_data = cfg_base;
+	hwif->dma_base = (cfg_base + 4) ^ (hwif->channel ? 0x80 : 0);
+
+	printk(KERN_INFO "    %s: BM-DMA at 0x%04lx-0x%04lx",
+	       hwif->name, hwif->dma_base, hwif->dma_base + 3);
+
+	if (!request_region(hwif->dma_base, 4, hwif->name)) {
+		printk(KERN_CONT " -- Error, ports in use.\n");
+		return;
+	}
+
+	hwif->dmatable_cpu = pci_alloc_consistent(dev, PRD_ENTRIES * PRD_BYTES,
+						  &hwif->dmatable_dma);
+	if (!hwif->dmatable_cpu) {
+		printk(KERN_CONT " -- Error, unable to allocate DMA table.\n");
+		release_region(hwif->dma_base, 4);
+		return;
+	}
+	printk(KERN_CONT "\n");
 
 	local_irq_save(flags);
 	/* put config reg into first byte of hwif->select_data */
@@ -276,15 +289,13 @@
 	outb(reg, hwif->config_data + 3);
 	local_irq_restore(flags);
 
-	if ((reg & 0x10))
+	if (reg & 0x10)
 		/* legacy mode */
 		hwif->irq = hwif->channel ? 15 : 14;
 	else if (!hwif->irq && hwif->mate && hwif->mate->irq)
 		/* sharing IRQ with mate */
 		hwif->irq = hwif->mate->irq;
 
-	ide_setup_dma(hwif, (hwif->config_data + 4) ^ (hwif->channel ? 0x0080 : 0x0000), 3);
-
 	hwif->dma_host_set	= &trm290_dma_host_set;
 	hwif->dma_setup 	= &trm290_dma_setup;
 	hwif->dma_exec_cmd	= &trm290_dma_exec_cmd;
diff --git a/drivers/ide/pci/via82cxxx.c b/drivers/ide/pci/via82cxxx.c
index 4b32c90..24cb904 100644
--- a/drivers/ide/pci/via82cxxx.c
+++ b/drivers/ide/pci/via82cxxx.c
@@ -1,7 +1,4 @@
 /*
- *
- * Version 3.50
- *
  * VIA IDE driver for Linux. Supported southbridges:
  *
  *   vt82c576, vt82c586, vt82c586a, vt82c586b, vt82c596a, vt82c596b,
@@ -121,8 +118,8 @@
 
 static void via_set_speed(ide_hwif_t *hwif, u8 dn, struct ide_timing *timing)
 {
-	struct pci_dev *dev = hwif->pci_dev;
-	struct via82cxxx_dev *vdev = pci_get_drvdata(hwif->pci_dev);
+	struct pci_dev *dev = to_pci_dev(hwif->dev);
+	struct via82cxxx_dev *vdev = pci_get_drvdata(dev);
 	u8 t;
 
 	if (~vdev->via_config->flags & VIA_BAD_AST) {
@@ -159,8 +156,10 @@
 
 static void via_set_drive(ide_drive_t *drive, const u8 speed)
 {
-	ide_drive_t *peer = HWIF(drive)->drives + (~drive->dn & 1);
-	struct via82cxxx_dev *vdev = pci_get_drvdata(drive->hwif->pci_dev);
+	ide_hwif_t *hwif = drive->hwif;
+	ide_drive_t *peer = hwif->drives + (~drive->dn & 1);
+	struct pci_dev *dev = to_pci_dev(hwif->dev);
+	struct via82cxxx_dev *vdev = pci_get_drvdata(dev);
 	struct ide_timing t, p;
 	unsigned int T, UT;
 
@@ -408,7 +407,7 @@
 
 static u8 __devinit via82cxxx_cable_detect(ide_hwif_t *hwif)
 {
-	struct pci_dev *pdev = hwif->pci_dev;
+	struct pci_dev *pdev = to_pci_dev(hwif->dev);
 	struct via82cxxx_dev *vdev = pci_get_drvdata(pdev);
 
 	if (via_cable_override(pdev))
diff --git a/drivers/ide/ppc/mpc8xx.c b/drivers/ide/ppc/mpc8xx.c
index 3fd5d45..45c1d55 100644
--- a/drivers/ide/ppc/mpc8xx.c
+++ b/drivers/ide/ppc/mpc8xx.c
@@ -1,6 +1,4 @@
 /*
- *  linux/drivers/ide/ppc/ide-m8xx.c
- *
  *  Copyright (C) 2000, 2001 Wolfgang Denk, wd@denx.de
  *  Modified for direct IDE interface
  *	by Thomas Lange, thomas@corelatus.com
diff --git a/drivers/ide/ppc/pmac.c b/drivers/ide/ppc/pmac.c
index 736d12c..23112ef 100644
--- a/drivers/ide/ppc/pmac.c
+++ b/drivers/ide/ppc/pmac.c
@@ -1,7 +1,6 @@
 /*
- * linux/drivers/ide/ppc/pmac.c
- *
  * Support for IDE interfaces on PowerMacs.
+ *
  * These IDE interfaces are memory-mapped and have a DBDMA channel
  * for doing DMA.
  *
@@ -1011,7 +1010,7 @@
  * (it is kept in 2.4). This introduce an interface numbering change on some
  * rare machines unfortunately, but it's better this way.
  */
-static int
+static int __devinit
 pmac_ide_setup_device(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif, hw_regs_t *hw)
 {
 	struct device_node *np = pmif->node;
@@ -1200,7 +1199,7 @@
 	base = ioremap(macio_resource_start(mdev, 0), 0x400);
 	regbase = (unsigned long) base;
 
-	hwif->pci_dev = mdev->bus->pdev;
+	hwif->dev = &mdev->bus->pdev->dev;
 
 	pmif->mdev = mdev;
 	pmif->node = mdev->ofdev.node;
@@ -1228,12 +1227,12 @@
 		/* The inteface is released to the common IDE layer */
 		dev_set_drvdata(&mdev->ofdev.dev, NULL);
 		iounmap(base);
-		if (pmif->dma_regs)
+		if (pmif->dma_regs) {
 			iounmap(pmif->dma_regs);
+			macio_release_resource(mdev, 1);
+		}
 		memset(pmif, 0, sizeof(*pmif));
 		macio_release_resource(mdev, 0);
-		if (pmif->dma_regs)
-			macio_release_resource(mdev, 1);
 	}
 
 	return rc;
@@ -1315,7 +1314,7 @@
 		return -ENXIO;
 	}
 
-	hwif->pci_dev = pdev;
+	hwif->dev = &pdev->dev;
 	pmif->mdev = NULL;
 	pmif->node = np;
 
@@ -1535,11 +1534,10 @@
 	}
 
 	printk(KERN_DEBUG "%s: empty DMA table?\n", drive->name);
- use_pio_instead:
-	pci_unmap_sg(hwif->pci_dev,
-		     hwif->sg_table,
-		     hwif->sg_nents,
-		     hwif->sg_dma_direction);
+
+use_pio_instead:
+	ide_destroy_dmatable(drive);
+
 	return 0; /* revert to PIO for this request */
 }
 
@@ -1548,12 +1546,9 @@
 pmac_ide_destroy_dmatable (ide_drive_t *drive)
 {
 	ide_hwif_t *hwif = drive->hwif;
-	struct pci_dev *dev = HWIF(drive)->pci_dev;
-	struct scatterlist *sg = hwif->sg_table;
-	int nents = hwif->sg_nents;
 
-	if (nents) {
-		pci_unmap_sg(dev, sg, nents, hwif->sg_dma_direction);
+	if (hwif->sg_nents) {
+		ide_destroy_dmatable(drive);
 		hwif->sg_nents = 0;
 	}
 }
@@ -1726,13 +1721,15 @@
  * Allocate the data structures needed for using DMA with an interface
  * and fill the proper list of functions pointers
  */
-static void __init 
+static void __devinit
 pmac_ide_setup_dma(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif)
 {
+	struct pci_dev *dev = to_pci_dev(hwif->dev);
+
 	/* We won't need pci_dev if we switch to generic consistent
 	 * DMA routines ...
 	 */
-	if (hwif->pci_dev == NULL)
+	if (dev == NULL)
 		return;
 	/*
 	 * Allocate space for the DBDMA commands.
@@ -1740,7 +1737,7 @@
 	 * aligning the start address to a multiple of 16 bytes.
 	 */
 	pmif->dma_table_cpu = (struct dbdma_cmd*)pci_alloc_consistent(
-		hwif->pci_dev,
+		dev,
 		(MAX_DCMDS + 2) * sizeof(struct dbdma_cmd),
 		&hwif->dmatable_dma);
 	if (pmif->dma_table_cpu == NULL) {
diff --git a/drivers/ide/setup-pci.c b/drivers/ide/setup-pci.c
index 676c66e..05db429 100644
--- a/drivers/ide/setup-pci.c
+++ b/drivers/ide/setup-pci.c
@@ -1,9 +1,8 @@
 /*
- *  linux/drivers/ide/setup-pci.c		Version 1.10	2002/08/19
+ *  Copyright (C) 1998-2000  Andre Hedrick <andre@linux-ide.org>
+ *  Copyright (C) 1995-1998  Mark Lord
+ *  Copyright (C)      2007  Bartlomiej Zolnierkiewicz
  *
- *  Copyright (c) 1998-2000  Andre Hedrick <andre@linux-ide.org>
- *
- *  Copyright (c) 1995-1998  Mark Lord
  *  May be copied or modified under the terms of the GNU General Public License
  */
 
@@ -140,6 +139,16 @@
 }
 
 #ifdef CONFIG_BLK_DEV_IDEDMA_PCI
+static void ide_pci_clear_simplex(unsigned long dma_base, const char *name)
+{
+	u8 dma_stat = inb(dma_base + 2);
+
+	outb(dma_stat & 0x60, dma_base + 2);
+	dma_stat = inb(dma_base + 2);
+	if (dma_stat & 0x80)
+		printk(KERN_INFO "%s: simplex device: DMA forced\n", name);
+}
+
 /**
  *	ide_get_or_set_dma_base		-	setup BMIBA
  *	@d: IDE port info
@@ -152,8 +161,9 @@
 
 static unsigned long ide_get_or_set_dma_base(const struct ide_port_info *d, ide_hwif_t *hwif)
 {
-	unsigned long	dma_base = 0;
-	struct pci_dev	*dev = hwif->pci_dev;
+	struct pci_dev *dev = to_pci_dev(hwif->dev);
+	unsigned long dma_base = 0;
+	u8 dma_stat = 0;
 
 	if (hwif->mmio)
 		return hwif->dma_base;
@@ -174,52 +184,30 @@
 	if (hwif->channel)
 		dma_base += 8;
 
-	if ((d->host_flags & IDE_HFLAG_CS5520) == 0) {
-		u8 simplex_stat = 0;
+	if (d->host_flags & IDE_HFLAG_CS5520)
+		goto out;
 
-		switch(dev->device) {
-			case PCI_DEVICE_ID_AL_M5219:
-			case PCI_DEVICE_ID_AL_M5229:
-			case PCI_DEVICE_ID_AMD_VIPER_7409:
-			case PCI_DEVICE_ID_CMD_643:
-			case PCI_DEVICE_ID_SERVERWORKS_CSB5IDE:
-			case PCI_DEVICE_ID_REVOLUTION:
-				simplex_stat = inb(dma_base + 2);
-				outb(simplex_stat & 0x60, dma_base + 2);
-				simplex_stat = inb(dma_base + 2);
-				if (simplex_stat & 0x80) {
-					printk(KERN_INFO "%s: simplex device: "
-							 "DMA forced\n",
-							 d->name);
-				}
-				break;
-			default:
-				/*
-				 * If the device claims "simplex" DMA,
-				 * this means only one of the two interfaces
-				 * can be trusted with DMA at any point in time.
-				 * So we should enable DMA only on one of the
-				 * two interfaces.
-				 */
-				simplex_stat = hwif->INB(dma_base + 2);
-				if (simplex_stat & 0x80) {
-					/* simplex device? */
-/*
- *	At this point we haven't probed the drives so we can't make the
- *	appropriate decision. Really we should defer this problem
- *	until we tune the drive then try to grab DMA ownership if we want
- *	to be the DMA end. This has to be become dynamic to handle hot
- *	plug.
- */
-					if (hwif->mate && hwif->mate->dma_base) {
-						printk(KERN_INFO "%s: simplex device: "
-								 "DMA disabled\n",
-								 d->name);
-						dma_base = 0;
-					}
-				}
-		}
+	if (d->host_flags & IDE_HFLAG_CLEAR_SIMPLEX) {
+		ide_pci_clear_simplex(dma_base, d->name);
+		goto out;
 	}
+
+	/*
+	 * If the device claims "simplex" DMA, this means that only one of
+	 * the two interfaces can be trusted with DMA at any point in time
+	 * (so we should enable DMA only on one of the two interfaces).
+	 *
+	 * FIXME: At this point we haven't probed the drives so we can't make
+	 * the appropriate decision.  Really we should defer this problem until
+	 * we tune the drive then try to grab DMA ownership if we want to be
+	 * the DMA end.  This has to be become dynamic to handle hot-plug.
+	 */
+	dma_stat = hwif->INB(dma_base + 2);
+	if ((dma_stat & 0x80) && hwif->mate && hwif->mate->dma_base) {
+		printk(KERN_INFO "%s: simplex device: DMA disabled\n", d->name);
+		dma_base = 0;
+	}
+out:
 	return dma_base;
 }
 #endif /* CONFIG_BLK_DEV_IDEDMA_PCI */
@@ -240,7 +228,9 @@
  *	@d: IDE port info
  *
  *	Enable the IDE PCI device. We attempt to enable the device in full
- *	but if that fails then we only need BAR4 so we will enable that.
+ *	but if that fails then we only need IO space. The PCI code should
+ *	have setup the proper resources for us already for controllers in
+ *	legacy mode.
  *	
  *	Returns zero on success or an error code
  */
@@ -250,7 +240,7 @@
 	int ret;
 
 	if (pci_enable_device(dev)) {
-		ret = pci_enable_device_bars(dev, 1 << 4);
+		ret = pci_enable_device_io(dev);
 		if (ret < 0) {
 			printk(KERN_WARNING "%s: (ide_setup_pci_device:) "
 				"Could not enable device.\n", d->name);
@@ -402,7 +392,7 @@
 
 	hwif->noprobe = oldnoprobe;
 
-	hwif->pci_dev = dev;
+	hwif->dev = &dev->dev;
 	hwif->cds = d;
 	hwif->channel = port;
 
@@ -451,7 +441,7 @@
 			if (d->init_dma) {
 				d->init_dma(hwif, dma_base);
 			} else {
-				ide_setup_dma(hwif, dma_base, 8);
+				ide_setup_dma(hwif, dma_base);
 			}
 		} else {
 			printk(KERN_INFO "%s: %s Bus-Master DMA disabled "
diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c
index 9e5ea07..ef5a6a2 100644
--- a/drivers/pci/bus.c
+++ b/drivers/pci/bus.c
@@ -108,6 +108,7 @@
 void pci_bus_add_devices(struct pci_bus *bus)
 {
 	struct pci_dev *dev;
+	struct pci_bus *child_bus;
 	int retval;
 
 	list_for_each_entry(dev, &bus->devices, bus_list) {
@@ -138,11 +139,19 @@
 			       up_write(&pci_bus_sem);
 			}
 			pci_bus_add_devices(dev->subordinate);
-			retval = sysfs_create_link(&dev->subordinate->class_dev.kobj,
-						   &dev->dev.kobj, "bridge");
+
+			/* register the bus with sysfs as the parent is now
+			 * properly registered. */
+			child_bus = dev->subordinate;
+			child_bus->dev.parent = child_bus->bridge;
+			retval = device_register(&child_bus->dev);
+			if (!retval)
+				retval = device_create_file(&child_bus->dev,
+							&dev_attr_cpuaffinity);
 			if (retval)
-				dev_err(&dev->dev, "Error creating sysfs "
-					"bridge symlink, continuing...\n");
+				dev_err(&dev->dev, "Error registering pci_bus"
+					" device bridge symlink,"
+					" continuing...\n");
 		}
 	}
 }
@@ -204,7 +213,6 @@
 	}
 	up_read(&pci_bus_sem);
 }
-EXPORT_SYMBOL_GPL(pci_walk_bus);
 
 EXPORT_SYMBOL(pci_bus_alloc_resource);
 EXPORT_SYMBOL_GPL(pci_bus_add_device);
diff --git a/drivers/pci/dmar.c b/drivers/pci/dmar.c
index 5dfdfda..91b2dc9 100644
--- a/drivers/pci/dmar.c
+++ b/drivers/pci/dmar.c
@@ -25,6 +25,7 @@
 
 #include <linux/pci.h>
 #include <linux/dmar.h>
+#include "iova.h"
 
 #undef PREFIX
 #define PREFIX "DMAR:"
@@ -263,8 +264,8 @@
 	if (!dmar)
 		return -ENODEV;
 
-	if (!dmar->width) {
-		printk (KERN_WARNING PREFIX "Zero: Invalid DMAR haw\n");
+	if (dmar->width < PAGE_SHIFT_4K - 1) {
+		printk(KERN_WARNING PREFIX "Invalid DMAR haw\n");
 		return -EINVAL;
 	}
 
@@ -301,11 +302,24 @@
 int __init dmar_table_init(void)
 {
 
-	parse_dmar_table();
+	int ret;
+
+	ret = parse_dmar_table();
+	if (ret) {
+		printk(KERN_INFO PREFIX "parse DMAR table failure.\n");
+		return ret;
+	}
+
 	if (list_empty(&dmar_drhd_units)) {
 		printk(KERN_INFO PREFIX "No DMAR devices found\n");
 		return -ENODEV;
 	}
+
+	if (list_empty(&dmar_rmrr_units)) {
+		printk(KERN_INFO PREFIX "No RMRR found\n");
+		return -ENODEV;
+	}
+
 	return 0;
 }
 
diff --git a/drivers/pci/hotplug/Kconfig b/drivers/pci/hotplug/Kconfig
index a64449d..2cdd832 100644
--- a/drivers/pci/hotplug/Kconfig
+++ b/drivers/pci/hotplug/Kconfig
@@ -3,8 +3,8 @@
 #
 
 menuconfig HOTPLUG_PCI
-	tristate "Support for PCI Hotplug (EXPERIMENTAL)"
-	depends on PCI && EXPERIMENTAL && HOTPLUG
+	tristate "Support for PCI Hotplug"
+	depends on PCI && HOTPLUG
 	---help---
 	  Say Y here if you have a motherboard with a PCI Hotplug controller.
 	  This allows you to add and remove PCI cards while the machine is
diff --git a/drivers/pci/hotplug/Makefile b/drivers/pci/hotplug/Makefile
index 34a1891..9bdbe1a 100644
--- a/drivers/pci/hotplug/Makefile
+++ b/drivers/pci/hotplug/Makefile
@@ -3,7 +3,6 @@
 #
 
 obj-$(CONFIG_HOTPLUG_PCI)		+= pci_hotplug.o
-obj-$(CONFIG_HOTPLUG_PCI_FAKE)		+= fakephp.o 
 obj-$(CONFIG_HOTPLUG_PCI_COMPAQ)	+= cpqphp.o
 obj-$(CONFIG_HOTPLUG_PCI_IBM)		+= ibmphp.o
 obj-$(CONFIG_HOTPLUG_PCI_ACPI)		+= acpiphp.o
@@ -16,6 +15,9 @@
 obj-$(CONFIG_HOTPLUG_PCI_RPA_DLPAR)	+= rpadlpar_io.o
 obj-$(CONFIG_HOTPLUG_PCI_SGI)		+= sgi_hotplug.o
 
+# Link this last so it doesn't claim devices that have a real hotplug driver
+obj-$(CONFIG_HOTPLUG_PCI_FAKE)		+= fakephp.o
+
 pci_hotplug-objs	:=	pci_hotplug_core.o
 
 ifdef CONFIG_HOTPLUG_PCI_CPCI
diff --git a/drivers/pci/hotplug/acpiphp.h b/drivers/pci/hotplug/acpiphp.h
index 1ef417c..7a29164 100644
--- a/drivers/pci/hotplug/acpiphp.h
+++ b/drivers/pci/hotplug/acpiphp.h
@@ -113,7 +113,6 @@
 	u8		device;		/* pci device# */
 
 	u32		sun;		/* ACPI _SUN (slot unique number) */
-	u32		slotno;		/* slot number relative to bridge */
 	u32		flags;		/* see below */
 };
 
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c
index ff1b1c7..cf22f9e 100644
--- a/drivers/pci/hotplug/acpiphp_glue.c
+++ b/drivers/pci/hotplug/acpiphp_glue.c
@@ -102,7 +102,7 @@
 }
 
 
-/* callback routine to check the existence of ejectable slots */
+/* callback routine to check for the existence of ejectable slots */
 static acpi_status
 is_ejectable_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
 {
@@ -117,7 +117,7 @@
 	}
 }
 
-/* callback routine to check for the existance of a pci dock device */
+/* callback routine to check for the existence of a pci dock device */
 static acpi_status
 is_pci_dock_device(acpi_handle handle, u32 lvl, void *context, void **rv)
 {
@@ -1528,7 +1528,6 @@
 		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 ;
diff --git a/drivers/pci/hotplug/fakephp.c b/drivers/pci/hotplug/fakephp.c
index d7a293e..94b6401 100644
--- a/drivers/pci/hotplug/fakephp.c
+++ b/drivers/pci/hotplug/fakephp.c
@@ -39,6 +39,7 @@
 #include <linux/init.h>
 #include <linux/string.h>
 #include <linux/slab.h>
+#include <linux/workqueue.h>
 #include "../pci.h"
 
 #if !defined(MODULE)
@@ -63,10 +64,16 @@
 	struct list_head node;
 	struct hotplug_slot *slot;
 	struct pci_dev *dev;
+	struct work_struct remove_work;
+	unsigned long removed;
 };
 
 static int debug;
 static LIST_HEAD(slot_list);
+static struct workqueue_struct *dummyphp_wq;
+
+static void pci_rescan_worker(struct work_struct *work);
+static DECLARE_WORK(pci_rescan_work, pci_rescan_worker);
 
 static int enable_slot (struct hotplug_slot *slot);
 static int disable_slot (struct hotplug_slot *slot);
@@ -109,7 +116,7 @@
 	slot->name = &dev->dev.bus_id[0];
 	dbg("slot->name = %s\n", slot->name);
 
-	dslot = kmalloc(sizeof(struct dummy_slot), GFP_KERNEL);
+	dslot = kzalloc(sizeof(struct dummy_slot), GFP_KERNEL);
 	if (!dslot)
 		goto error_info;
 
@@ -164,6 +171,14 @@
 		err("Problem unregistering a slot %s\n", dslot->slot->name);
 }
 
+/* called from the single-threaded workqueue handler to remove a slot */
+static void remove_slot_worker(struct work_struct *work)
+{
+	struct dummy_slot *dslot =
+		container_of(work, struct dummy_slot, remove_work);
+	remove_slot(dslot);
+}
+
 /**
  * pci_rescan_slot - Rescan slot
  * @temp: Device template. Should be set: bus and devfn.
@@ -267,11 +282,17 @@
 	pci_rescan_buses(&pci_root_buses);
 }
 
+/* called from the single-threaded workqueue handler to rescan all pci buses */
+static void pci_rescan_worker(struct work_struct *work)
+{
+	pci_rescan();
+}
 
 static int enable_slot(struct hotplug_slot *hotplug_slot)
 {
 	/* mis-use enable_slot for rescanning of the pci bus */
-	pci_rescan();
+	cancel_work_sync(&pci_rescan_work);
+	queue_work(dummyphp_wq, &pci_rescan_work);
 	return -ENODEV;
 }
 
@@ -306,6 +327,10 @@
 		err("Can't remove PCI devices with other PCI devices behind it yet.\n");
 		return -ENODEV;
 	}
+	if (test_and_set_bit(0, &dslot->removed)) {
+		dbg("Slot already scheduled for removal\n");
+		return -ENODEV;
+	}
 	/* search for subfunctions and disable them first */
 	if (!(dslot->dev->devfn & 7)) {
 		for (func = 1; func < 8; func++) {
@@ -328,8 +353,9 @@
 	/* remove the device from the pci core */
 	pci_remove_bus_device(dslot->dev);
 
-	/* blow away this sysfs entry and other parts. */
-	remove_slot(dslot);
+	/* queue work item to blow away this sysfs entry and other parts. */
+	INIT_WORK(&dslot->remove_work, remove_slot_worker);
+	queue_work(dummyphp_wq, &dslot->remove_work);
 
 	return 0;
 }
@@ -340,6 +366,7 @@
 	struct list_head *next;
 	struct dummy_slot *dslot;
 
+	destroy_workqueue(dummyphp_wq);
 	list_for_each_safe (tmp, next, &slot_list) {
 		dslot = list_entry (tmp, struct dummy_slot, node);
 		remove_slot(dslot);
@@ -351,6 +378,10 @@
 {
 	info(DRIVER_DESC "\n");
 
+	dummyphp_wq = create_singlethread_workqueue(MY_NAME);
+	if (!dummyphp_wq)
+		return -ENOMEM;
+
 	return pci_scan_buses();
 }
 
diff --git a/drivers/pci/hotplug/ibmphp_core.c b/drivers/pci/hotplug/ibmphp_core.c
index a90c28d..87b6b8b 100644
--- a/drivers/pci/hotplug/ibmphp_core.c
+++ b/drivers/pci/hotplug/ibmphp_core.c
@@ -761,10 +761,13 @@
 	debug("func->device << 3 | 0x0  = %x\n", func->device << 3 | 0x0);
 
 	for (j = 0; j < 0x08; j++) {
-		temp = pci_find_slot(func->busno, (func->device << 3) | j);
-		if (temp)
+		temp = pci_get_bus_and_slot(func->busno, (func->device << 3) | j);
+		if (temp) {
 			pci_remove_bus_device(temp);
+			pci_dev_put(temp);
+		}
 	}
+	pci_dev_put(func->dev);
 }
 
 /*
@@ -823,7 +826,7 @@
 	if (!(bus_structure_fixup(func->busno)))
 		flag = 1;
 	if (func->dev == NULL)
-		func->dev = pci_find_slot(func->busno,
+		func->dev = pci_get_bus_and_slot(func->busno,
 				PCI_DEVFN(func->device, func->function));
 
 	if (func->dev == NULL) {
@@ -836,7 +839,7 @@
 		if (num)
 			pci_bus_add_devices(bus);
 
-		func->dev = pci_find_slot(func->busno,
+		func->dev = pci_get_bus_and_slot(func->busno,
 				PCI_DEVFN(func->device, func->function));
 		if (func->dev == NULL) {
 			err("ERROR... : pci_dev still NULL\n");
diff --git a/drivers/pci/hotplug/pci_hotplug_core.c b/drivers/pci/hotplug/pci_hotplug_core.c
index 47bb0e1..dd59a05 100644
--- a/drivers/pci/hotplug/pci_hotplug_core.c
+++ b/drivers/pci/hotplug/pci_hotplug_core.c
@@ -137,7 +137,7 @@
 	int retval = 0;							\
 	if (try_module_get(ops->owner)) {				\
 		if (ops->get_##name)					\
-			retval = ops->get_##name (slot, value);		\
+			retval = ops->get_##name(slot, value);		\
 		else							\
 			*value = slot->info->name;			\
 		module_put(ops->owner);					\
@@ -625,7 +625,7 @@
 	if ((slot->info == NULL) || (slot->ops == NULL))
 		return -EINVAL;
 	if (slot->release == NULL) {
-		dbg("Why are you trying to register a hotplug slot"
+		dbg("Why are you trying to register a hotplug slot "
 		    "without a proper release function?\n");
 		return -EINVAL;
 	}
diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h
index 7959c22..ca656b2 100644
--- a/drivers/pci/hotplug/pciehp.h
+++ b/drivers/pci/hotplug/pciehp.h
@@ -82,24 +82,18 @@
 };
 
 struct controller {
-	struct controller *next;
 	struct mutex crit_sect;		/* critical section mutex */
 	struct mutex ctrl_lock;		/* controller lock */
 	int num_slots;			/* Number of slots on ctlr */
 	int slot_num_inc;		/* 1 or -1 */
 	struct pci_dev *pci_dev;
 	struct list_head slot_list;
-	struct slot *slot;
 	struct hpc_ops *hpc_ops;
 	wait_queue_head_t queue;	/* sleep & wake process */
-	u8 bus;
-	u8 device;
-	u8 function;
 	u8 slot_device_offset;
 	u32 first_slot;		/* First physical slot number */  /* PCIE only has 1 slot */
 	u8 slot_bus;		/* Bus where the slots handled by this controller sit */
 	u8 ctrlcap;
-	u16 vendor_id;
 	u8 cap_base;
 	struct timer_list poll_timer;
 	volatile int cmd_busy;
@@ -161,6 +155,9 @@
 extern int pciehp_unconfigure_device(struct slot *p_slot);
 extern void pciehp_queue_pushbutton_work(struct work_struct *work);
 int pcie_init(struct controller *ctrl, struct pcie_device *dev);
+int pciehp_enable_slot(struct slot *p_slot);
+int pciehp_disable_slot(struct slot *p_slot);
+int pcie_init_hardware_part2(struct controller *ctrl, struct pcie_device *dev);
 
 static inline struct slot *pciehp_find_slot(struct controller *ctrl, u8 device)
 {
diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c
index 6462ac3..7f4836b8 100644
--- a/drivers/pci/hotplug/pciehp_core.c
+++ b/drivers/pci/hotplug/pciehp_core.c
@@ -453,13 +453,9 @@
 
 	pci_set_drvdata(pdev, ctrl);
 
-	ctrl->bus = pdev->bus->number;  /* ctrl bus */
-	ctrl->slot_bus = pdev->subordinate->number;  /* bus controlled by this HPC */
-
-	ctrl->device = PCI_SLOT(pdev->devfn);
-	ctrl->function = PCI_FUNC(pdev->devfn);
-	dbg("%s: ctrl bus=0x%x, device=%x, function=%x, irq=%x\n", __FUNCTION__,
-		ctrl->bus, ctrl->device, ctrl->function, pdev->irq);
+	dbg("%s: ctrl bus=0x%x, device=%x, function=%x, irq=%x\n",
+	    __FUNCTION__, pdev->bus->number, PCI_SLOT(pdev->devfn),
+	    PCI_FUNC(pdev->devfn), pdev->irq);
 
 	/* Setup the slot information structures */
 	rc = init_slots(ctrl);
@@ -471,6 +467,11 @@
 	t_slot = pciehp_find_slot(ctrl, ctrl->slot_device_offset);
 
 	t_slot->hpc_ops->get_adapter_status(t_slot, &value); /* Check if slot is occupied */
+	if (value) {
+		rc = pciehp_enable_slot(t_slot);
+		if (rc)	/* -ENODEV: shouldn't happen, but deal with it */
+			value = 0;
+	}
 	if ((POWER_CTRL(ctrl->ctrlcap)) && !value) {
 		rc = t_slot->hpc_ops->power_off_slot(t_slot); /* Power off slot if not occupied*/
 		if (rc)
@@ -509,6 +510,24 @@
 static int pciehp_resume (struct pcie_device *dev)
 {
 	printk("%s ENTRY\n", __FUNCTION__);
+	if (pciehp_force) {
+		struct pci_dev *pdev = dev->port;
+		struct controller *ctrl = pci_get_drvdata(pdev);
+		struct slot *t_slot;
+		u8 status;
+
+		/* reinitialize the chipset's event detection logic */
+		pcie_init_hardware_part2(ctrl, dev);
+
+		t_slot = pciehp_find_slot(ctrl, ctrl->slot_device_offset);
+
+		/* Check if slot is occupied */
+		t_slot->hpc_ops->get_adapter_status(t_slot, &status);
+		if (status)
+			pciehp_enable_slot(t_slot);
+		else
+			pciehp_disable_slot(t_slot);
+	}
 	return 0;
 }
 #endif
diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c
index f1e0966..b23061c 100644
--- a/drivers/pci/hotplug/pciehp_ctrl.c
+++ b/drivers/pci/hotplug/pciehp_ctrl.c
@@ -37,8 +37,6 @@
 #include "pciehp.h"
 
 static void interrupt_event_handler(struct work_struct *work);
-static int pciehp_enable_slot(struct slot *p_slot);
-static int pciehp_disable_slot(struct slot *p_slot);
 
 static int queue_interrupt_event(struct slot *p_slot, u32 event_type)
 {
@@ -197,12 +195,6 @@
 			    __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);
 	}
 }
 
@@ -215,15 +207,12 @@
  */
 static int board_added(struct slot *p_slot)
 {
-	u8 hp_slot;
 	int retval = 0;
 	struct controller *ctrl = p_slot->ctrl;
 
-	hp_slot = p_slot->device - ctrl->slot_device_offset;
-
 	dbg("%s: slot device, slot offset, hp slot = %d, %d ,%d\n",
 			__FUNCTION__, p_slot->device,
-			ctrl->slot_device_offset, hp_slot);
+			ctrl->slot_device_offset, p_slot->hp_slot);
 
 	if (POWER_CTRL(ctrl->ctrlcap)) {
 		/* Power on slot */
@@ -281,8 +270,6 @@
  */
 static int remove_board(struct slot *p_slot)
 {
-	u8 device;
-	u8 hp_slot;
 	int retval = 0;
 	struct controller *ctrl = p_slot->ctrl;
 
@@ -290,11 +277,7 @@
 	if (retval)
 		return retval;
 
-	device = p_slot->device;
-	hp_slot = p_slot->device - ctrl->slot_device_offset;
-	p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
-
-	dbg("In %s, hp_slot = %d\n", __FUNCTION__, hp_slot);
+	dbg("In %s, hp_slot = %d\n", __FUNCTION__, p_slot->hp_slot);
 
 	if (POWER_CTRL(ctrl->ctrlcap)) {
 		/* power off slot */
@@ -621,12 +604,6 @@
 			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 06d025b..6eba9b2 100644
--- a/drivers/pci/hotplug/pciehp_hpc.c
+++ b/drivers/pci/hotplug/pciehp_hpc.c
@@ -636,15 +636,57 @@
 	return retval;
 }
 
+static inline int pcie_mask_bad_dllp(struct controller *ctrl)
+{
+	struct pci_dev *dev = ctrl->pci_dev;
+	int pos;
+	u32 reg;
+
+	pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
+	if (!pos)
+		return 0;
+	pci_read_config_dword(dev, pos + PCI_ERR_COR_MASK, &reg);
+	if (reg & PCI_ERR_COR_BAD_DLLP)
+		return 0;
+	reg |= PCI_ERR_COR_BAD_DLLP;
+	pci_write_config_dword(dev, pos + PCI_ERR_COR_MASK, reg);
+	return 1;
+}
+
+static inline void pcie_unmask_bad_dllp(struct controller *ctrl)
+{
+	struct pci_dev *dev = ctrl->pci_dev;
+	u32 reg;
+	int pos;
+
+	pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
+	if (!pos)
+		return;
+	pci_read_config_dword(dev, pos + PCI_ERR_COR_MASK, &reg);
+	if (!(reg & PCI_ERR_COR_BAD_DLLP))
+		return;
+	reg &= ~PCI_ERR_COR_BAD_DLLP;
+	pci_write_config_dword(dev, pos + PCI_ERR_COR_MASK, reg);
+}
+
 static int hpc_power_off_slot(struct slot * slot)
 {
 	struct controller *ctrl = slot->ctrl;
 	u16 slot_cmd;
 	u16 cmd_mask;
 	int retval = 0;
+	int changed;
 
 	dbg("%s: slot->hp_slot %x\n", __FUNCTION__, slot->hp_slot);
 
+	/*
+	 * Set Bad DLLP Mask bit in Correctable Error Mask
+	 * Register. This is the workaround against Bad DLLP error
+	 * that sometimes happens during turning power off the slot
+	 * which conforms to PCI Express 1.0a spec.
+	 */
+	changed = pcie_mask_bad_dllp(ctrl);
+
 	slot_cmd = POWER_OFF;
 	cmd_mask = PWR_CTRL;
 	/*
@@ -674,6 +716,16 @@
 	dbg("%s: SLOTCTRL %x write cmd %x\n",
 	    __FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_cmd);
 
+	/*
+	 * 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);
+
+	if (changed)
+		pcie_unmask_bad_dllp(ctrl);
+
 	return retval;
 }
 
@@ -1067,13 +1119,143 @@
 }
 #endif
 
-int pcie_init(struct controller * ctrl, struct pcie_device *dev)
+static int pcie_init_hardware_part1(struct controller *ctrl,
+				    struct pcie_device *dev)
 {
 	int rc;
 	u16 temp_word;
-	u16 cap_reg;
+	u32 slot_cap;
+	u16 slot_status;
+
+	rc = pciehp_readl(ctrl, SLOTCAP, &slot_cap);
+	if (rc) {
+		err("%s: Cannot read SLOTCAP register\n", __FUNCTION__);
+		return -1;
+	}
+
+	/* Mask Hot-plug Interrupt Enable */
+	rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word);
+	if (rc) {
+		err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__);
+		return -1;
+	}
+
+	dbg("%s: SLOTCTRL %x value read %x\n",
+	    __FUNCTION__, ctrl->cap_base + SLOTCTRL, temp_word);
+	temp_word = (temp_word & ~HP_INTR_ENABLE & ~CMD_CMPL_INTR_ENABLE) |
+		0x00;
+
+	rc = pciehp_writew(ctrl, SLOTCTRL, temp_word);
+	if (rc) {
+		err("%s: Cannot write to SLOTCTRL register\n", __FUNCTION__);
+		return -1;
+	}
+
+	rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
+	if (rc) {
+		err("%s: Cannot read SLOTSTATUS register\n", __FUNCTION__);
+		return -1;
+	}
+
+	temp_word = 0x1F; /* Clear all events */
+	rc = pciehp_writew(ctrl, SLOTSTATUS, temp_word);
+	if (rc) {
+		err("%s: Cannot write to SLOTSTATUS register\n", __FUNCTION__);
+		return -1;
+	}
+	return 0;
+}
+
+int pcie_init_hardware_part2(struct controller *ctrl, struct pcie_device *dev)
+{
+	int rc;
+	u16 temp_word;
 	u16 intr_enable = 0;
 	u32 slot_cap;
+	u16 slot_status;
+
+	rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word);
+	if (rc) {
+		err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__);
+		goto abort;
+	}
+
+	intr_enable = intr_enable | PRSN_DETECT_ENABLE;
+
+	rc = pciehp_readl(ctrl, SLOTCAP, &slot_cap);
+	if (rc) {
+		err("%s: Cannot read SLOTCAP register\n", __FUNCTION__);
+		goto abort;
+	}
+
+	if (ATTN_BUTTN(slot_cap))
+		intr_enable = intr_enable | ATTN_BUTTN_ENABLE;
+
+	if (POWER_CTRL(slot_cap))
+		intr_enable = intr_enable | PWR_FAULT_DETECT_ENABLE;
+
+	if (MRL_SENS(slot_cap))
+		intr_enable = intr_enable | MRL_DETECT_ENABLE;
+
+	temp_word = (temp_word & ~intr_enable) | intr_enable;
+
+	if (pciehp_poll_mode) {
+		temp_word = (temp_word & ~HP_INTR_ENABLE) | 0x0;
+	} else {
+		temp_word = (temp_word & ~HP_INTR_ENABLE) | HP_INTR_ENABLE;
+	}
+
+	/*
+	 * Unmask Hot-plug Interrupt Enable for the interrupt
+	 * notification mechanism case.
+	 */
+	rc = pciehp_writew(ctrl, SLOTCTRL, temp_word);
+	if (rc) {
+		err("%s: Cannot write to SLOTCTRL register\n", __FUNCTION__);
+		goto abort;
+	}
+	rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
+	if (rc) {
+		err("%s: Cannot read SLOTSTATUS register\n", __FUNCTION__);
+		goto abort_disable_intr;
+	}
+
+	temp_word =  0x1F; /* Clear all events */
+	rc = pciehp_writew(ctrl, SLOTSTATUS, temp_word);
+	if (rc) {
+		err("%s: Cannot write to SLOTSTATUS register\n", __FUNCTION__);
+		goto abort_disable_intr;
+	}
+
+	if (pciehp_force) {
+		dbg("Bypassing BIOS check for pciehp use on %s\n",
+				pci_name(ctrl->pci_dev));
+	} else {
+		rc = pciehp_get_hp_hw_control_from_firmware(ctrl->pci_dev);
+		if (rc)
+			goto abort_disable_intr;
+	}
+
+	return 0;
+
+	/* We end up here for the many possible ways to fail this API. */
+abort_disable_intr:
+	rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word);
+	if (!rc) {
+		temp_word &= ~(intr_enable | HP_INTR_ENABLE);
+		rc = pciehp_writew(ctrl, SLOTCTRL, temp_word);
+	}
+	if (rc)
+		err("%s : disabling interrupts failed\n", __FUNCTION__);
+abort:
+	return -1;
+}
+
+int pcie_init(struct controller *ctrl, struct pcie_device *dev)
+{
+	int rc;
+	u16 cap_reg;
+	u32 slot_cap;
 	int cap_base;
 	u16 slot_status, slot_ctrl;
 	struct pci_dev *pdev;
@@ -1084,9 +1266,10 @@
 	dbg("%s: hotplug controller vendor id 0x%x device id 0x%x\n",
 			__FUNCTION__, pdev->vendor, pdev->device);
 
-	if ((cap_base = pci_find_capability(pdev, PCI_CAP_ID_EXP)) == 0) {
+	cap_base = pci_find_capability(pdev, PCI_CAP_ID_EXP);
+	if (cap_base == 0) {
 		dbg("%s: Can't find PCI_CAP_ID_EXP (0x10)\n", __FUNCTION__);
-		goto abort_free_ctlr;
+		goto abort;
 	}
 
 	ctrl->cap_base = cap_base;
@@ -1096,7 +1279,7 @@
 	rc = pciehp_readw(ctrl, CAPREG, &cap_reg);
 	if (rc) {
 		err("%s: Cannot read CAPREG register\n", __FUNCTION__);
-		goto abort_free_ctlr;
+		goto abort;
 	}
 	dbg("%s: CAPREG offset %x cap_reg %x\n",
 	    __FUNCTION__, ctrl->cap_base + CAPREG, cap_reg);
@@ -1106,26 +1289,26 @@
 		&& ((cap_reg & DEV_PORT_TYPE) != 0x0060))) {
 		dbg("%s : This is not a root port or the port is not "
 		    "connected to a slot\n", __FUNCTION__);
-		goto abort_free_ctlr;
+		goto abort;
 	}
 
 	rc = pciehp_readl(ctrl, SLOTCAP, &slot_cap);
 	if (rc) {
 		err("%s: Cannot read SLOTCAP register\n", __FUNCTION__);
-		goto abort_free_ctlr;
+		goto abort;
 	}
 	dbg("%s: SLOTCAP offset %x slot_cap %x\n",
 	    __FUNCTION__, ctrl->cap_base + SLOTCAP, slot_cap);
 
 	if (!(slot_cap & HP_CAP)) {
 		dbg("%s : This slot is not hot-plug capable\n", __FUNCTION__);
-		goto abort_free_ctlr;
+		goto abort;
 	}
 	/* For debugging purpose */
 	rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
 	if (rc) {
 		err("%s: Cannot read SLOTSTATUS register\n", __FUNCTION__);
-		goto abort_free_ctlr;
+		goto abort;
 	}
 	dbg("%s: SLOTSTATUS offset %x slot_status %x\n",
 	    __FUNCTION__, ctrl->cap_base + SLOTSTATUS, slot_status);
@@ -1133,7 +1316,7 @@
 	rc = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl);
 	if (rc) {
 		err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__);
-		goto abort_free_ctlr;
+		goto abort;
 	}
 	dbg("%s: SLOTCTRL offset %x slot_ctrl %x\n",
 	    __FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_ctrl);
@@ -1161,36 +1344,9 @@
 	ctrl->first_slot = slot_cap >> 19;
 	ctrl->ctrlcap = slot_cap & 0x0000007f;
 
-	/* Mask Hot-plug Interrupt Enable */
-	rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word);
-	if (rc) {
-		err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__);
-		goto abort_free_ctlr;
-	}
-
-	dbg("%s: SLOTCTRL %x value read %x\n",
-	    __FUNCTION__, ctrl->cap_base + SLOTCTRL, temp_word);
-	temp_word = (temp_word & ~HP_INTR_ENABLE & ~CMD_CMPL_INTR_ENABLE) |
-		0x00;
-
-	rc = pciehp_writew(ctrl, SLOTCTRL, temp_word);
-	if (rc) {
-		err("%s: Cannot write to SLOTCTRL register\n", __FUNCTION__);
-		goto abort_free_ctlr;
-	}
-
-	rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
-	if (rc) {
-		err("%s: Cannot read SLOTSTATUS register\n", __FUNCTION__);
-		goto abort_free_ctlr;
-	}
-
-	temp_word = 0x1F; /* Clear all events */
-	rc = pciehp_writew(ctrl, SLOTSTATUS, temp_word);
-	if (rc) {
-		err("%s: Cannot write to SLOTSTATUS register\n", __FUNCTION__);
-		goto abort_free_ctlr;
-	}
+	rc = pcie_init_hardware_part1(ctrl, dev);
+	if (rc)
+		goto abort;
 
 	if (pciehp_poll_mode) {
 		/* Install interrupt polling timer. Start with 10 sec delay */
@@ -1206,7 +1362,7 @@
 		if (rc) {
 			err("Can't get irq %d for the hotplug controller\n",
 			    ctrl->pci_dev->irq);
-			goto abort_free_ctlr;
+			goto abort;
 		}
 	}
 	dbg("pciehp ctrl b:d:f:irq=0x%x:%x:%x:%x\n", pdev->bus->number,
@@ -1224,82 +1380,16 @@
 		}
 	}
 
-	rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word);
-	if (rc) {
-		err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__);
-		goto abort_free_irq;
+	rc = pcie_init_hardware_part2(ctrl, dev);
+	if (rc == 0) {
+		ctrl->hpc_ops = &pciehp_hpc_ops;
+		return 0;
 	}
-
-	intr_enable = intr_enable | PRSN_DETECT_ENABLE;
-
-	if (ATTN_BUTTN(slot_cap))
-		intr_enable = intr_enable | ATTN_BUTTN_ENABLE;
-
-	if (POWER_CTRL(slot_cap))
-		intr_enable = intr_enable | PWR_FAULT_DETECT_ENABLE;
-
-	if (MRL_SENS(slot_cap))
-		intr_enable = intr_enable | MRL_DETECT_ENABLE;
-
-	temp_word = (temp_word & ~intr_enable) | intr_enable;
-
-	if (pciehp_poll_mode) {
-		temp_word = (temp_word & ~HP_INTR_ENABLE) | 0x0;
-	} else {
-		temp_word = (temp_word & ~HP_INTR_ENABLE) | HP_INTR_ENABLE;
-	}
-
-	/*
-	 * Unmask Hot-plug Interrupt Enable for the interrupt
-	 * notification mechanism case.
-	 */
-	rc = pciehp_writew(ctrl, SLOTCTRL, temp_word);
-	if (rc) {
-		err("%s: Cannot write to SLOTCTRL register\n", __FUNCTION__);
-		goto abort_free_irq;
-	}
-	rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
-	if (rc) {
-		err("%s: Cannot read SLOTSTATUS register\n", __FUNCTION__);
-		goto abort_disable_intr;
-	}
-
-	temp_word =  0x1F; /* Clear all events */
-	rc = pciehp_writew(ctrl, SLOTSTATUS, temp_word);
-	if (rc) {
-		err("%s: Cannot write to SLOTSTATUS register\n", __FUNCTION__);
-		goto abort_disable_intr;
-	}
-
-	if (pciehp_force) {
-		dbg("Bypassing BIOS check for pciehp use on %s\n",
-				pci_name(ctrl->pci_dev));
-	} else {
-		rc = pciehp_get_hp_hw_control_from_firmware(ctrl->pci_dev);
-		if (rc)
-			goto abort_disable_intr;
-	}
-
-	ctrl->hpc_ops = &pciehp_hpc_ops;
-
-	return 0;
-
-	/* We end up here for the many possible ways to fail this API. */
-abort_disable_intr:
-	rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word);
-	if (!rc) {
-		temp_word &= ~(intr_enable | HP_INTR_ENABLE);
-		rc = pciehp_writew(ctrl, SLOTCTRL, temp_word);
-	}
-	if (rc)
-		err("%s : disabling interrupts failed\n", __FUNCTION__);
-
 abort_free_irq:
 	if (pciehp_poll_mode)
 		del_timer_sync(&ctrl->poll_timer);
 	else
 		free_irq(ctrl->pci_dev->irq, ctrl);
-
-abort_free_ctlr:
+abort:
 	return -1;
 }
diff --git a/drivers/pci/hotplug/pciehp_pci.c b/drivers/pci/hotplug/pciehp_pci.c
index c424ade..dd50713 100644
--- a/drivers/pci/hotplug/pciehp_pci.c
+++ b/drivers/pci/hotplug/pciehp_pci.c
@@ -105,12 +105,7 @@
 	}
 
 	/* Find Advanced Error Reporting Enhanced Capability */
-	pos = 256;
-	do {
-		pci_read_config_dword(dev, pos, &reg32);
-		if (PCI_EXT_CAP_ID(reg32) == PCI_EXT_CAP_ID_ERR)
-			break;
-	} while ((pos = PCI_EXT_CAP_NEXT(reg32)));
+	pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
 	if (!pos)
 		return;
 
@@ -248,11 +243,15 @@
 	u8 bctl = 0;
 	u8 presence = 0;
 	struct pci_bus *parent = p_slot->ctrl->pci_dev->subordinate;
+	u16 command;
 
 	dbg("%s: bus/dev = %x/%x\n", __FUNCTION__, p_slot->bus,
 				p_slot->device);
+	ret = p_slot->hpc_ops->get_adapter_status(p_slot, &presence);
+	if (ret)
+		presence = 0;
 
-	for (j=0; j<8 ; j++) {
+	for (j = 0; j < 8; j++) {
 		struct pci_dev* temp = pci_get_slot(parent,
 				(p_slot->device << 3) | j);
 		if (!temp)
@@ -263,21 +262,26 @@
 			pci_dev_put(temp);
 			continue;
 		}
-		if (temp->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
-			ret = p_slot->hpc_ops->get_adapter_status(p_slot,
-								&presence);
-			if (!ret && presence) {
-				pci_read_config_byte(temp, PCI_BRIDGE_CONTROL,
-					&bctl);
-				if (bctl & PCI_BRIDGE_CTL_VGA) {
-					err("Cannot remove display device %s\n",
-						pci_name(temp));
-					pci_dev_put(temp);
-					continue;
-				}
+		if (temp->hdr_type == PCI_HEADER_TYPE_BRIDGE && presence) {
+			pci_read_config_byte(temp, PCI_BRIDGE_CONTROL, &bctl);
+			if (bctl & PCI_BRIDGE_CTL_VGA) {
+				err("Cannot remove display device %s\n",
+				    pci_name(temp));
+				pci_dev_put(temp);
+				continue;
 			}
 		}
 		pci_remove_bus_device(temp);
+		/*
+		 * Ensure that no new Requests will be generated from
+		 * the device.
+		 */
+		if (presence) {
+			pci_read_config_word(temp, PCI_COMMAND, &command);
+			command &= ~(PCI_COMMAND_MASTER | PCI_COMMAND_SERR);
+			command |= PCI_COMMAND_INTX_DISABLE;
+			pci_write_config_word(temp, PCI_COMMAND, command);
+		}
 		pci_dev_put(temp);
 	}
 	/*
@@ -288,4 +292,3 @@
 
 	return rc;
 }
-
diff --git a/drivers/pci/hotplug/rpaphp.h b/drivers/pci/hotplug/rpaphp.h
index c822a77..7d5921b 100644
--- a/drivers/pci/hotplug/rpaphp.h
+++ b/drivers/pci/hotplug/rpaphp.h
@@ -74,7 +74,6 @@
 	u32 type;
 	u32 power_domain;
 	char *name;
-	char *location;
 	struct device_node *dn;
 	struct pci_bus *bus;
 	struct list_head *pci_devs;
diff --git a/drivers/pci/hotplug/rpaphp_pci.c b/drivers/pci/hotplug/rpaphp_pci.c
index 0de8453..6571e9b 100644
--- a/drivers/pci/hotplug/rpaphp_pci.c
+++ b/drivers/pci/hotplug/rpaphp_pci.c
@@ -64,19 +64,6 @@
 	return rc;
 }
 
-static void set_slot_name(struct slot *slot)
-{
-	struct pci_bus *bus = slot->bus;
-	struct pci_dev *bridge;
-
-	bridge = bus->self;
-	if (bridge)
-		strcpy(slot->name, pci_name(bridge));
-	else
-		sprintf(slot->name, "%04x:%02x:00.0", pci_domain_nr(bus),
-			bus->number);
-}
-
 /**
  * rpaphp_enable_slot - record slot state, config pci device
  * @slot: target &slot
@@ -115,7 +102,6 @@
 	info->adapter_status = EMPTY;
 	slot->bus = bus;
 	slot->pci_devs = &bus->devices;
-	set_slot_name(slot);
 
 	/* if there's an adapter in the slot, go add the pci devices */
 	if (state == PRESENT) {
diff --git a/drivers/pci/hotplug/rpaphp_slot.c b/drivers/pci/hotplug/rpaphp_slot.c
index d4ee872..8ad3deb 100644
--- a/drivers/pci/hotplug/rpaphp_slot.c
+++ b/drivers/pci/hotplug/rpaphp_slot.c
@@ -33,23 +33,31 @@
 #include <asm/rtas.h>
 #include "rpaphp.h"
 
-static ssize_t location_read_file (struct hotplug_slot *php_slot, char *buf)
+static ssize_t address_read_file (struct hotplug_slot *php_slot, char *buf)
 {
-	char *value;
-	int retval = -ENOENT;
+	int retval;
 	struct slot *slot = (struct slot *)php_slot->private;
+	struct pci_bus *bus;
 
 	if (!slot)
-		return retval;
+		return -ENOENT;
 
-	value = slot->location;
-	retval = sprintf (buf, "%s\n", value);
+	bus = slot->bus;
+	if (!bus)
+		return -ENOENT;
+
+	if (bus->self)
+		retval = sprintf(buf, pci_name(bus->self));
+	else
+		retval = sprintf(buf, "%04x:%02x:00.0",
+		        pci_domain_nr(bus), bus->number);
+
 	return retval;
 }
 
-static struct hotplug_slot_attribute php_attr_location = {
-	.attr = {.name = "phy_location", .mode = S_IFREG | S_IRUGO},
-	.show = location_read_file,
+static struct hotplug_slot_attribute php_attr_address = {
+	.attr = {.name = "address", .mode = S_IFREG | S_IRUGO},
+	.show = address_read_file,
 };
 
 /* free up the memory used by a slot */
@@ -64,7 +72,6 @@
 	kfree(slot->hotplug_slot->info);
 	kfree(slot->hotplug_slot->name);
 	kfree(slot->hotplug_slot);
-	kfree(slot->location);
 	kfree(slot);
 }
 
@@ -83,16 +90,13 @@
 					   GFP_KERNEL);
 	if (!slot->hotplug_slot->info)
 		goto error_hpslot;
-	slot->hotplug_slot->name = kmalloc(BUS_ID_SIZE + 1, GFP_KERNEL);
+	slot->hotplug_slot->name = kmalloc(strlen(drc_name) + 1, GFP_KERNEL);
 	if (!slot->hotplug_slot->name)
 		goto error_info;	
-	slot->location = kmalloc(strlen(drc_name) + 1, GFP_KERNEL);
-	if (!slot->location)
-		goto error_name;
 	slot->name = slot->hotplug_slot->name;
+	strcpy(slot->name, drc_name);
 	slot->dn = dn;
 	slot->index = drc_index;
-	strcpy(slot->location, drc_name);
 	slot->power_domain = power_domain;
 	slot->hotplug_slot->private = slot;
 	slot->hotplug_slot->ops = &rpaphp_hotplug_slot_ops;
@@ -100,8 +104,6 @@
 	
 	return (slot);
 
-error_name:
-	kfree(slot->hotplug_slot->name);
 error_info:
 	kfree(slot->hotplug_slot->info);
 error_hpslot:
@@ -133,8 +135,8 @@
 
 	list_del(&slot->rpaphp_slot_list);
 	
-	/* remove "phy_location" file */
-	sysfs_remove_file(&php_slot->kobj, &php_attr_location.attr);
+	/* remove "address" file */
+	sysfs_remove_file(&php_slot->kobj, &php_attr_address.attr);
 
 	retval = pci_hp_deregister(php_slot);
 	if (retval)
@@ -166,8 +168,8 @@
 		return retval;
 	}
 
-	/* create "phy_location" file */
-	retval = sysfs_create_file(&php_slot->kobj, &php_attr_location.attr);
+	/* create "address" file */
+	retval = sysfs_create_file(&php_slot->kobj, &php_attr_address.attr);
 	if (retval) {
 		err("sysfs_create_file failed with error %d\n", retval);
 		goto sysfs_fail;
@@ -175,8 +177,7 @@
 
 	/* add slot to our internal list */
 	list_add(&slot->rpaphp_slot_list, &rpaphp_slot_head);
-	info("Slot [%s](PCI location=%s) registered\n", slot->name,
-			slot->location);
+	info("Slot [%s] registered\n", slot->name);
 	return 0;
 
 sysfs_fail:
diff --git a/drivers/pci/hotplug/shpchp_hpc.c b/drivers/pci/hotplug/shpchp_hpc.c
index 5183a45..e8aa138 100644
--- a/drivers/pci/hotplug/shpchp_hpc.c
+++ b/drivers/pci/hotplug/shpchp_hpc.c
@@ -597,7 +597,7 @@
 	cleanup_slots(ctrl);
 
 	/*
-	 * Mask SERR and System Interrut generation
+	 * Mask SERR and System Interrupt generation
 	 */
 	serr_int = shpc_readl(ctrl, SERR_INTR_ENABLE);
 	serr_int |= (GLOBAL_INTR_MASK  | GLOBAL_SERR_MASK |
diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c
index e079a52..4e01df9 100644
--- a/drivers/pci/intel-iommu.c
+++ b/drivers/pci/intel-iommu.c
@@ -1781,7 +1781,7 @@
 		/*
 		 * First try to allocate an io virtual address in
 		 * DMA_32BIT_MASK and if that fails then try allocating
-		 * from higer range
+		 * from higher range
 		 */
 		iova = iommu_alloc_iova(domain, size, DMA_32BIT_MASK);
 		if (!iova)
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index 07c9f09..26938da 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -25,6 +25,51 @@
 
 static int pci_msi_enable = 1;
 
+/* Arch hooks */
+
+int __attribute__ ((weak))
+arch_msi_check_device(struct pci_dev *dev, int nvec, int type)
+{
+	return 0;
+}
+
+int __attribute__ ((weak))
+arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *entry)
+{
+	return 0;
+}
+
+int __attribute__ ((weak))
+arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
+{
+	struct msi_desc *entry;
+	int ret;
+
+	list_for_each_entry(entry, &dev->msi_list, list) {
+		ret = arch_setup_msi_irq(dev, entry);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+void __attribute__ ((weak)) arch_teardown_msi_irq(unsigned int irq)
+{
+	return;
+}
+
+void __attribute__ ((weak))
+arch_teardown_msi_irqs(struct pci_dev *dev)
+{
+	struct msi_desc *entry;
+
+	list_for_each_entry(entry, &dev->msi_list, list) {
+		if (entry->irq != 0)
+			arch_teardown_msi_irq(entry->irq);
+	}
+}
+
 static void msi_set_enable(struct pci_dev *dev, int enable)
 {
 	int pos;
@@ -230,7 +275,6 @@
 		pci_intx(dev, enable);
 }
 
-#ifdef CONFIG_PM
 static void __pci_restore_msi_state(struct pci_dev *dev)
 {
 	int pos;
@@ -288,7 +332,7 @@
 	__pci_restore_msi_state(dev);
 	__pci_restore_msix_state(dev);
 }
-#endif	/* CONFIG_PM */
+EXPORT_SYMBOL_GPL(pci_restore_msi_state);
 
 /**
  * msi_capability_init - configure device's MSI capability structure
@@ -683,49 +727,3 @@
 {
 	INIT_LIST_HEAD(&dev->msi_list);
 }
-
-
-/* Arch hooks */
-
-int __attribute__ ((weak))
-arch_msi_check_device(struct pci_dev* dev, int nvec, int type)
-{
-	return 0;
-}
-
-int __attribute__ ((weak))
-arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *entry)
-{
-	return 0;
-}
-
-int __attribute__ ((weak))
-arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
-{
-	struct msi_desc *entry;
-	int ret;
-
-	list_for_each_entry(entry, &dev->msi_list, list) {
-		ret = arch_setup_msi_irq(dev, entry);
-		if (ret)
-			return ret;
-	}
-
-	return 0;
-}
-
-void __attribute__ ((weak)) arch_teardown_msi_irq(unsigned int irq)
-{
-	return;
-}
-
-void __attribute__ ((weak))
-arch_teardown_msi_irqs(struct pci_dev *dev)
-{
-	struct msi_desc *entry;
-
-	list_for_each_entry(entry, &dev->msi_list, list) {
-		if (entry->irq != 0)
-			arch_teardown_msi_irq(entry->irq);
-	}
-}
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c
index 5c6a5d0..e569645 100644
--- a/drivers/pci/pci-acpi.c
+++ b/drivers/pci/pci-acpi.c
@@ -156,13 +156,13 @@
 }
 
 /**
- * pci_osc_support_set - register OS support to Firmware
+ * __pci_osc_support_set - register OS support to Firmware
  * @flags: OS support bits
  *
  * Update OS support fields and doing a _OSC Query to obtain an update
  * from Firmware on supported control bits.
  **/
-acpi_status pci_osc_support_set(u32 flags)
+acpi_status __pci_osc_support_set(u32 flags, const char *hid)
 {
 	u32 temp;
 	acpi_status retval;
@@ -176,7 +176,7 @@
 	temp = ctrlset_buf[OSC_CONTROL_TYPE];
 	ctrlset_buf[OSC_QUERY_TYPE] = OSC_QUERY_ENABLE;
 	ctrlset_buf[OSC_CONTROL_TYPE] = OSC_CONTROL_MASKS;
-	acpi_get_devices ( PCI_ROOT_HID_STRING,
+	acpi_get_devices(hid,
 			acpi_query_osc,
 			ctrlset_buf,
 			(void **) &retval );
@@ -188,7 +188,6 @@
 	}
 	return AE_OK;
 }
-EXPORT_SYMBOL(pci_osc_support_set);
 
 /**
  * pci_osc_control_set - commit requested control to Firmware
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
index c4fa35d..e571c72 100644
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -186,13 +186,11 @@
 	    set_cpus_allowed(current, node_to_cpumask(node));
 	/* And set default memory allocation policy */
 	oldpol = current->mempolicy;
-	current->mempolicy = &default_policy;
-	mpol_get(current->mempolicy);
+	current->mempolicy = NULL;	/* fall back to system default policy */
 #endif
 	error = drv->probe(dev, id);
 #ifdef CONFIG_NUMA
 	set_cpus_allowed(current, oldmask);
-	mpol_free(current->mempolicy);
 	current->mempolicy = oldpol;
 #endif
 	return error;
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index 7d18773..abf4203 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -21,6 +21,7 @@
 #include <linux/topology.h>
 #include <linux/mm.h>
 #include <linux/capability.h>
+#include <linux/aspm.h>
 #include "pci.h"
 
 static int sysfs_initialized;	/* = 0 */
@@ -358,7 +359,7 @@
 		   char *buf, loff_t off, size_t count)
 {
         struct pci_bus *bus = to_pci_bus(container_of(kobj,
-                                                      struct class_device,
+                                                      struct device,
 						      kobj));
 
         /* Only support 1, 2 or 4 byte accesses */
@@ -383,7 +384,7 @@
 		    char *buf, loff_t off, size_t count)
 {
         struct pci_bus *bus = to_pci_bus(container_of(kobj,
-						      struct class_device,
+						      struct device,
 						      kobj));
         /* Only support 1, 2 or 4 byte accesses */
         if (count != 1 && count != 2 && count != 4)
@@ -407,7 +408,7 @@
                     struct vm_area_struct *vma)
 {
         struct pci_bus *bus = to_pci_bus(container_of(kobj,
-                                                      struct class_device,
+                                                      struct device,
 						      kobj));
 
         return pci_mmap_legacy_page_range(bus, vma);
@@ -650,6 +651,8 @@
 	if (pcibios_add_platform_entries(pdev))
 		goto err_rom_file;
 
+	pcie_aspm_create_sysfs_dev_files(pdev);
+
 	return 0;
 
 err_rom_file:
@@ -679,6 +682,8 @@
 	if (!sysfs_initialized)
 		return;
 
+	pcie_aspm_remove_sysfs_dev_files(pdev);
+
 	if (pdev->cfg_size < 4096)
 		sysfs_remove_bin_file(&pdev->dev.kobj, &pci_config_attr);
 	else
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 71d561fd..b3e9294 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -18,6 +18,7 @@
 #include <linux/spinlock.h>
 #include <linux/string.h>
 #include <linux/log2.h>
+#include <linux/aspm.h>
 #include <asm/dma.h>	/* isa_dma_bridge_buggy */
 #include "pci.h"
 
@@ -314,6 +315,24 @@
 }
 EXPORT_SYMBOL_GPL(pci_find_ht_capability);
 
+void pcie_wait_pending_transaction(struct pci_dev *dev)
+{
+	int pos;
+	u16 reg16;
+
+	pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
+	if (!pos)
+		return;
+	while (1) {
+		pci_read_config_word(dev, pos + PCI_EXP_DEVSTA, &reg16);
+		if (!(reg16 & PCI_EXP_DEVSTA_TRPND))
+			break;
+		cpu_relax();
+	}
+
+}
+EXPORT_SYMBOL_GPL(pcie_wait_pending_transaction);
+
 /**
  * pci_find_parent_resource - return resource region of parent bus of given region
  * @dev: PCI device structure contains resources to be searched
@@ -353,7 +372,7 @@
  * Restore the BAR values for a given device, so as to make it
  * accessible by its driver.
  */
-void
+static void
 pci_restore_bars(struct pci_dev *dev)
 {
 	int i, numres;
@@ -501,6 +520,9 @@
 	if (need_restore)
 		pci_restore_bars(dev);
 
+	if (dev->bus->self)
+		pcie_aspm_pm_state_change(dev->bus->self);
+
 	return 0;
 }
 
@@ -551,6 +573,7 @@
 	int pos, i = 0;
 	struct pci_cap_saved_state *save_state;
 	u16 *cap;
+	int found = 0;
 
 	pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
 	if (pos <= 0)
@@ -559,6 +582,8 @@
 	save_state = pci_find_saved_cap(dev, PCI_CAP_ID_EXP);
 	if (!save_state)
 		save_state = kzalloc(sizeof(*save_state) + sizeof(u16) * 4, GFP_KERNEL);
+	else
+		found = 1;
 	if (!save_state) {
 		dev_err(&dev->dev, "Out of memory in pci_save_pcie_state\n");
 		return -ENOMEM;
@@ -569,7 +594,9 @@
 	pci_read_config_word(dev, pos + PCI_EXP_LNKCTL, &cap[i++]);
 	pci_read_config_word(dev, pos + PCI_EXP_SLTCTL, &cap[i++]);
 	pci_read_config_word(dev, pos + PCI_EXP_RTCTL, &cap[i++]);
-	pci_add_saved_cap(dev, save_state);
+	save_state->cap_nr = PCI_CAP_ID_EXP;
+	if (!found)
+		pci_add_saved_cap(dev, save_state);
 	return 0;
 }
 
@@ -597,14 +624,17 @@
 	int pos, i = 0;
 	struct pci_cap_saved_state *save_state;
 	u16 *cap;
+	int found = 0;
 
 	pos = pci_find_capability(dev, PCI_CAP_ID_PCIX);
 	if (pos <= 0)
 		return 0;
 
-	save_state = pci_find_saved_cap(dev, PCI_CAP_ID_EXP);
+	save_state = pci_find_saved_cap(dev, PCI_CAP_ID_PCIX);
 	if (!save_state)
 		save_state = kzalloc(sizeof(*save_state) + sizeof(u16), GFP_KERNEL);
+	else
+		found = 1;
 	if (!save_state) {
 		dev_err(&dev->dev, "Out of memory in pci_save_pcie_state\n");
 		return -ENOMEM;
@@ -612,7 +642,9 @@
 	cap = (u16 *)&save_state->data[0];
 
 	pci_read_config_word(dev, pos + PCI_X_CMD, &cap[i++]);
-	pci_add_saved_cap(dev, save_state);
+	save_state->cap_nr = PCI_CAP_ID_PCIX;
+	if (!found)
+		pci_add_saved_cap(dev, save_state);
 	return 0;
 }
 
@@ -713,23 +745,19 @@
 	return 0;
 }
 
-/**
- * pci_enable_device_bars - Initialize some of a device for use
- * @dev: PCI device to be initialized
- * @bars: bitmask of BAR's that must be configured
- *
- *  Initialize device before it's used by a driver. Ask low-level code
- *  to enable selected I/O and memory resources. Wake up the device if it
- *  was suspended. Beware, this function can fail.
- */
-int
-pci_enable_device_bars(struct pci_dev *dev, int bars)
+static int __pci_enable_device_flags(struct pci_dev *dev,
+				     resource_size_t flags)
 {
 	int err;
+	int i, bars = 0;
 
 	if (atomic_add_return(1, &dev->enable_cnt) > 1)
 		return 0;		/* already enabled */
 
+	for (i = 0; i < DEVICE_COUNT_RESOURCE; i++)
+		if (dev->resource[i].flags & flags)
+			bars |= (1 << i);
+
 	err = do_pci_enable_device(dev, bars);
 	if (err < 0)
 		atomic_dec(&dev->enable_cnt);
@@ -737,6 +765,32 @@
 }
 
 /**
+ * pci_enable_device_io - Initialize a device for use with IO space
+ * @dev: PCI device to be initialized
+ *
+ *  Initialize device before it's used by a driver. Ask low-level code
+ *  to enable I/O resources. Wake up the device if it was suspended.
+ *  Beware, this function can fail.
+ */
+int pci_enable_device_io(struct pci_dev *dev)
+{
+	return __pci_enable_device_flags(dev, IORESOURCE_IO);
+}
+
+/**
+ * pci_enable_device_mem - Initialize a device for use with Memory space
+ * @dev: PCI device to be initialized
+ *
+ *  Initialize device before it's used by a driver. Ask low-level code
+ *  to enable Memory resources. Wake up the device if it was suspended.
+ *  Beware, this function can fail.
+ */
+int pci_enable_device_mem(struct pci_dev *dev)
+{
+	return __pci_enable_device_flags(dev, IORESOURCE_MEM);
+}
+
+/**
  * pci_enable_device - Initialize device before it's used by a driver.
  * @dev: PCI device to be initialized
  *
@@ -749,7 +803,7 @@
  */
 int pci_enable_device(struct pci_dev *dev)
 {
-	return pci_enable_device_bars(dev, (1 << PCI_NUM_RESOURCES) - 1);
+	return __pci_enable_device_flags(dev, IORESOURCE_MEM | IORESOURCE_IO);
 }
 
 /*
@@ -823,7 +877,8 @@
 	dr = get_pci_dr(pdev);
 	if (unlikely(!dr))
 		return -ENOMEM;
-	WARN_ON(!!dr->enabled);
+	if (dr->enabled)
+		return 0;
 
 	rc = pci_enable_device(pdev);
 	if (!rc) {
@@ -884,6 +939,9 @@
 	if (atomic_sub_return(1, &dev->enable_cnt) != 0)
 		return;
 
+	/* Wait for all transactions are finished before disabling the device */
+	pcie_wait_pending_transaction(dev);
+
 	pci_read_config_word(dev, PCI_COMMAND, &pci_command);
 	if (pci_command & PCI_COMMAND_MASTER) {
 		pci_command &= ~PCI_COMMAND_MASTER;
@@ -1618,9 +1676,9 @@
 
 device_initcall(pci_init);
 
-EXPORT_SYMBOL_GPL(pci_restore_bars);
 EXPORT_SYMBOL(pci_reenable_device);
-EXPORT_SYMBOL(pci_enable_device_bars);
+EXPORT_SYMBOL(pci_enable_device_io);
+EXPORT_SYMBOL(pci_enable_device_mem);
 EXPORT_SYMBOL(pci_enable_device);
 EXPORT_SYMBOL(pcim_enable_device);
 EXPORT_SYMBOL(pcim_pin_device);
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index fc87e14..eabeb1f 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -6,8 +6,10 @@
 extern void pci_cleanup_rom(struct pci_dev *dev);
 
 /* Firmware callbacks */
-extern pci_power_t (*platform_pci_choose_state)(struct pci_dev *dev, pm_message_t state);
-extern int (*platform_pci_set_power_state)(struct pci_dev *dev, pci_power_t state);
+extern pci_power_t (*platform_pci_choose_state)(struct pci_dev *dev,
+						pm_message_t state);
+extern int (*platform_pci_set_power_state)(struct pci_dev *dev,
+						pci_power_t state);
 
 extern int pci_user_read_config_byte(struct pci_dev *dev, int where, u8 *val);
 extern int pci_user_read_config_word(struct pci_dev *dev, int where, u16 *val);
@@ -45,12 +47,6 @@
 static inline void pci_msi_init_pci_dev(struct pci_dev *dev) { }
 #endif
 
-#if defined(CONFIG_PCI_MSI) && defined(CONFIG_PM)
-void pci_restore_msi_state(struct pci_dev *dev);
-#else
-static inline void pci_restore_msi_state(struct pci_dev *dev) {}
-#endif
-
 #ifdef CONFIG_PCIEAER
 void pci_no_aer(void);
 #else
@@ -68,14 +64,14 @@
 }
 extern int pcie_mch_quirk;
 extern struct device_attribute pci_dev_attrs[];
-extern struct class_device_attribute class_device_attr_cpuaffinity;
+extern struct device_attribute dev_attr_cpuaffinity;
 
 /**
  * pci_match_one_device - Tell if a PCI device structure has a matching
  *                        PCI device id structure
  * @id: single PCI device id structure to match
  * @dev: the PCI device structure to match against
- * 
+ *
  * Returns the matching pci_device_id structure or %NULL if there is no match.
  */
 static inline const struct pci_device_id *
diff --git a/drivers/pci/pcie/Kconfig b/drivers/pci/pcie/Kconfig
index 287a931..60104cf 100644
--- a/drivers/pci/pcie/Kconfig
+++ b/drivers/pci/pcie/Kconfig
@@ -26,3 +26,23 @@
 	  When in doubt, say N.
 
 source "drivers/pci/pcie/aer/Kconfig"
+
+#
+# PCI Express ASPM
+#
+config PCIEASPM
+	bool "PCI Express ASPM support(Experimental)"
+	depends on PCI && EXPERIMENTAL
+	default y
+	help
+	  This enables PCI Express ASPM (Active State Power Management) and
+	  Clock Power Management. ASPM supports state L0/L0s/L1.
+
+	  When in doubt, say N.
+config PCIEASPM_DEBUG
+	bool "Debug PCI Express ASPM"
+	depends on PCIEASPM
+	default n
+	help
+	  This enables PCI Express ASPM debug support. It will add per-device
+	  interface to control ASPM.
diff --git a/drivers/pci/pcie/Makefile b/drivers/pci/pcie/Makefile
index e00fb99..11f6bb1e 100644
--- a/drivers/pci/pcie/Makefile
+++ b/drivers/pci/pcie/Makefile
@@ -2,6 +2,9 @@
 # Makefile for PCI-Express PORT Driver
 #
 
+# Build PCI Express ASPM if needed
+obj-$(CONFIG_PCIEASPM)		+= aspm.o
+
 pcieportdrv-y			:= portdrv_core.o portdrv_pci.o portdrv_bus.o
 
 obj-$(CONFIG_PCIEPORTBUS)	+= pcieportdrv.o
diff --git a/drivers/pci/pcie/aer/aerdrv_acpi.c b/drivers/pci/pcie/aer/aerdrv_acpi.c
index 1a1eb45..8c199ae 100644
--- a/drivers/pci/pcie/aer/aerdrv_acpi.c
+++ b/drivers/pci/pcie/aer/aerdrv_acpi.c
@@ -31,26 +31,16 @@
 {
 	acpi_status status = AE_NOT_FOUND;
 	struct pci_dev *pdev = pciedev->port;
-	acpi_handle handle = DEVICE_ACPI_HANDLE(&pdev->dev);
-	struct pci_bus *parent;
+	acpi_handle handle = 0;
 
-	while (!handle) {
-		if (!pdev || !pdev->bus->parent)
-			break;
-		parent = pdev->bus->parent;
-		if (!parent->self)
-			/* Parent must be a host bridge */
-			handle = acpi_get_pci_rootbridge_handle(
-					pci_domain_nr(parent),
-					parent->number);
-		else
-			handle = DEVICE_ACPI_HANDLE(
-					&(parent->self->dev));
-		pdev = parent->self;
-	}
+	/* Find root host bridge */
+	while (pdev->bus && pdev->bus->self)
+		pdev = pdev->bus->self;
+	handle = acpi_get_pci_rootbridge_handle(
+		pci_domain_nr(pdev->bus), pdev->bus->number);
 
 	if (handle) {
-		pci_osc_support_set(OSC_EXT_PCI_CONFIG_SUPPORT);
+		pcie_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);
diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c
new file mode 100644
index 0000000..1a5adeb
--- /dev/null
+++ b/drivers/pci/pcie/aspm.c
@@ -0,0 +1,802 @@
+/*
+ * File:	drivers/pci/pcie/aspm.c
+ * Enabling PCIE link L0s/L1 state and Clock Power Management
+ *
+ * Copyright (C) 2007 Intel
+ * Copyright (C) Zhang Yanmin (yanmin.zhang@intel.com)
+ * Copyright (C) Shaohua Li (shaohua.li@intel.com)
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/pci.h>
+#include <linux/pci_regs.h>
+#include <linux/errno.h>
+#include <linux/pm.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/aspm.h>
+#include <acpi/acpi_bus.h>
+#include <linux/pci-acpi.h>
+#include "../pci.h"
+
+#ifdef MODULE_PARAM_PREFIX
+#undef MODULE_PARAM_PREFIX
+#endif
+#define MODULE_PARAM_PREFIX "pcie_aspm."
+
+struct endpoint_state {
+	unsigned int l0s_acceptable_latency;
+	unsigned int l1_acceptable_latency;
+};
+
+struct pcie_link_state {
+	struct list_head sibiling;
+	struct pci_dev *pdev;
+
+	/* ASPM state */
+	unsigned int support_state;
+	unsigned int enabled_state;
+	unsigned int bios_aspm_state;
+	/* upstream component */
+	unsigned int l0s_upper_latency;
+	unsigned int l1_upper_latency;
+	/* downstream component */
+	unsigned int l0s_down_latency;
+	unsigned int l1_down_latency;
+	/* Clock PM state*/
+	unsigned int clk_pm_capable;
+	unsigned int clk_pm_enabled;
+	unsigned int bios_clk_state;
+
+	/*
+	 * A pcie downstream port only has one slot under it, so at most there
+	 * are 8 functions
+	 */
+	struct endpoint_state endpoints[8];
+};
+
+static int aspm_disabled;
+static DEFINE_MUTEX(aspm_lock);
+static LIST_HEAD(link_list);
+
+#define POLICY_DEFAULT 0	/* BIOS default setting */
+#define POLICY_PERFORMANCE 1	/* high performance */
+#define POLICY_POWERSAVE 2	/* high power saving */
+static int aspm_policy;
+static const char *policy_str[] = {
+	[POLICY_DEFAULT] = "default",
+	[POLICY_PERFORMANCE] = "performance",
+	[POLICY_POWERSAVE] = "powersave"
+};
+
+static int policy_to_aspm_state(struct pci_dev *pdev)
+{
+	struct pcie_link_state *link_state = pdev->link_state;
+
+	switch (aspm_policy) {
+	case POLICY_PERFORMANCE:
+		/* Disable ASPM and Clock PM */
+		return 0;
+	case POLICY_POWERSAVE:
+		/* Enable ASPM L0s/L1 */
+		return PCIE_LINK_STATE_L0S|PCIE_LINK_STATE_L1;
+	case POLICY_DEFAULT:
+		return link_state->bios_aspm_state;
+	}
+	return 0;
+}
+
+static int policy_to_clkpm_state(struct pci_dev *pdev)
+{
+	struct pcie_link_state *link_state = pdev->link_state;
+
+	switch (aspm_policy) {
+	case POLICY_PERFORMANCE:
+		/* Disable ASPM and Clock PM */
+		return 0;
+	case POLICY_POWERSAVE:
+		/* Disable Clock PM */
+		return 1;
+	case POLICY_DEFAULT:
+		return link_state->bios_clk_state;
+	}
+	return 0;
+}
+
+static void pcie_set_clock_pm(struct pci_dev *pdev, int enable)
+{
+	struct pci_dev *child_dev;
+	int pos;
+	u16 reg16;
+	struct pcie_link_state *link_state = pdev->link_state;
+
+	list_for_each_entry(child_dev, &pdev->subordinate->devices, bus_list) {
+		pos = pci_find_capability(child_dev, PCI_CAP_ID_EXP);
+		if (!pos)
+			return;
+		pci_read_config_word(child_dev, pos + PCI_EXP_LNKCTL, &reg16);
+		if (enable)
+			reg16 |= PCI_EXP_LNKCTL_CLKREQ_EN;
+		else
+			reg16 &= ~PCI_EXP_LNKCTL_CLKREQ_EN;
+		pci_write_config_word(child_dev, pos + PCI_EXP_LNKCTL, reg16);
+	}
+	link_state->clk_pm_enabled = !!enable;
+}
+
+static void pcie_check_clock_pm(struct pci_dev *pdev)
+{
+	int pos;
+	u32 reg32;
+	u16 reg16;
+	int capable = 1, enabled = 1;
+	struct pci_dev *child_dev;
+	struct pcie_link_state *link_state = pdev->link_state;
+
+	/* All functions should have the same cap and state, take the worst */
+	list_for_each_entry(child_dev, &pdev->subordinate->devices, bus_list) {
+		pos = pci_find_capability(child_dev, PCI_CAP_ID_EXP);
+		if (!pos)
+			return;
+		pci_read_config_dword(child_dev, pos + PCI_EXP_LNKCAP, &reg32);
+		if (!(reg32 & PCI_EXP_LNKCAP_CLKPM)) {
+			capable = 0;
+			enabled = 0;
+			break;
+		}
+		pci_read_config_word(child_dev, pos + PCI_EXP_LNKCTL, &reg16);
+		if (!(reg16 & PCI_EXP_LNKCTL_CLKREQ_EN))
+			enabled = 0;
+	}
+	link_state->clk_pm_capable = capable;
+	link_state->clk_pm_enabled = enabled;
+	link_state->bios_clk_state = enabled;
+	pcie_set_clock_pm(pdev, policy_to_clkpm_state(pdev));
+}
+
+/*
+ * pcie_aspm_configure_common_clock: check if the 2 ends of a link
+ *   could use common clock. If they are, configure them to use the
+ *   common clock. That will reduce the ASPM state exit latency.
+ */
+static void pcie_aspm_configure_common_clock(struct pci_dev *pdev)
+{
+	int pos, child_pos;
+	u16 reg16 = 0;
+	struct pci_dev *child_dev;
+	int same_clock = 1;
+
+	/*
+	 * all functions of a slot should have the same Slot Clock
+	 * Configuration, so just check one function
+	 * */
+	child_dev = list_entry(pdev->subordinate->devices.next, struct pci_dev,
+		bus_list);
+	BUG_ON(!child_dev->is_pcie);
+
+	/* Check downstream component if bit Slot Clock Configuration is 1 */
+	child_pos = pci_find_capability(child_dev, PCI_CAP_ID_EXP);
+	pci_read_config_word(child_dev, child_pos + PCI_EXP_LNKSTA, &reg16);
+	if (!(reg16 & PCI_EXP_LNKSTA_SLC))
+		same_clock = 0;
+
+	/* Check upstream component if bit Slot Clock Configuration is 1 */
+	pos = pci_find_capability(pdev, PCI_CAP_ID_EXP);
+	pci_read_config_word(pdev, pos + PCI_EXP_LNKSTA, &reg16);
+	if (!(reg16 & PCI_EXP_LNKSTA_SLC))
+		same_clock = 0;
+
+	/* Configure downstream component, all functions */
+	list_for_each_entry(child_dev, &pdev->subordinate->devices, bus_list) {
+		child_pos = pci_find_capability(child_dev, PCI_CAP_ID_EXP);
+		pci_read_config_word(child_dev, child_pos + PCI_EXP_LNKCTL,
+			&reg16);
+		if (same_clock)
+			reg16 |= PCI_EXP_LNKCTL_CCC;
+		else
+			reg16 &= ~PCI_EXP_LNKCTL_CCC;
+		pci_write_config_word(child_dev, child_pos + PCI_EXP_LNKCTL,
+			reg16);
+	}
+
+	/* Configure upstream component */
+	pci_read_config_word(pdev, pos + PCI_EXP_LNKCTL, &reg16);
+	if (same_clock)
+		reg16 |= PCI_EXP_LNKCTL_CCC;
+	else
+		reg16 &= ~PCI_EXP_LNKCTL_CCC;
+	pci_write_config_word(pdev, pos + PCI_EXP_LNKCTL, reg16);
+
+	/* retrain link */
+	reg16 |= PCI_EXP_LNKCTL_RL;
+	pci_write_config_word(pdev, pos + PCI_EXP_LNKCTL, reg16);
+
+	/* Wait for link training end */
+	while (1) {
+		pci_read_config_word(pdev, pos + PCI_EXP_LNKSTA, &reg16);
+		if (!(reg16 & PCI_EXP_LNKSTA_LT))
+			break;
+		cpu_relax();
+	}
+}
+
+/*
+ * calc_L0S_latency: Convert L0s latency encoding to ns
+ */
+static unsigned int calc_L0S_latency(unsigned int latency_encoding, int ac)
+{
+	unsigned int ns = 64;
+
+	if (latency_encoding == 0x7) {
+		if (ac)
+			ns = -1U;
+		else
+			ns = 5*1000; /* > 4us */
+	} else
+		ns *= (1 << latency_encoding);
+	return ns;
+}
+
+/*
+ * calc_L1_latency: Convert L1 latency encoding to ns
+ */
+static unsigned int calc_L1_latency(unsigned int latency_encoding, int ac)
+{
+	unsigned int ns = 1000;
+
+	if (latency_encoding == 0x7) {
+		if (ac)
+			ns = -1U;
+		else
+			ns = 65*1000; /* > 64us */
+	} else
+		ns *= (1 << latency_encoding);
+	return ns;
+}
+
+static void pcie_aspm_get_cap_device(struct pci_dev *pdev, u32 *state,
+	unsigned int *l0s, unsigned int *l1, unsigned int *enabled)
+{
+	int pos;
+	u16 reg16;
+	u32 reg32;
+	unsigned int latency;
+
+	pos = pci_find_capability(pdev, PCI_CAP_ID_EXP);
+	pci_read_config_dword(pdev, pos + PCI_EXP_LNKCAP, &reg32);
+	*state = (reg32 & PCI_EXP_LNKCAP_ASPMS) >> 10;
+	if (*state != PCIE_LINK_STATE_L0S &&
+		*state != (PCIE_LINK_STATE_L1|PCIE_LINK_STATE_L0S))
+		* state = 0;
+	if (*state == 0)
+		return;
+
+	latency = (reg32 & PCI_EXP_LNKCAP_L0SEL) >> 12;
+	*l0s = calc_L0S_latency(latency, 0);
+	if (*state & PCIE_LINK_STATE_L1) {
+		latency = (reg32 & PCI_EXP_LNKCAP_L1EL) >> 15;
+		*l1 = calc_L1_latency(latency, 0);
+	}
+	pci_read_config_word(pdev, pos + PCI_EXP_LNKCTL, &reg16);
+	*enabled = reg16 & (PCIE_LINK_STATE_L0S|PCIE_LINK_STATE_L1);
+}
+
+static void pcie_aspm_cap_init(struct pci_dev *pdev)
+{
+	struct pci_dev *child_dev;
+	u32 state, tmp;
+	struct pcie_link_state *link_state = pdev->link_state;
+
+	/* upstream component states */
+	pcie_aspm_get_cap_device(pdev, &link_state->support_state,
+		&link_state->l0s_upper_latency,
+		&link_state->l1_upper_latency,
+		&link_state->enabled_state);
+	/* downstream component states, all functions have the same setting */
+	child_dev = list_entry(pdev->subordinate->devices.next, struct pci_dev,
+		bus_list);
+	pcie_aspm_get_cap_device(child_dev, &state,
+		&link_state->l0s_down_latency,
+		&link_state->l1_down_latency,
+		&tmp);
+	link_state->support_state &= state;
+	if (!link_state->support_state)
+		return;
+	link_state->enabled_state &= link_state->support_state;
+	link_state->bios_aspm_state = link_state->enabled_state;
+
+	/* ENDPOINT states*/
+	list_for_each_entry(child_dev, &pdev->subordinate->devices, bus_list) {
+		int pos;
+		u32 reg32;
+		unsigned int latency;
+		struct endpoint_state *ep_state =
+			&link_state->endpoints[PCI_FUNC(child_dev->devfn)];
+
+		if (child_dev->pcie_type != PCI_EXP_TYPE_ENDPOINT &&
+			child_dev->pcie_type != PCI_EXP_TYPE_LEG_END)
+			continue;
+
+		pos = pci_find_capability(child_dev, PCI_CAP_ID_EXP);
+		pci_read_config_dword(child_dev, pos + PCI_EXP_DEVCAP, &reg32);
+		latency = (reg32 & PCI_EXP_DEVCAP_L0S) >> 6;
+		latency = calc_L0S_latency(latency, 1);
+		ep_state->l0s_acceptable_latency = latency;
+		if (link_state->support_state & PCIE_LINK_STATE_L1) {
+			latency = (reg32 & PCI_EXP_DEVCAP_L1) >> 9;
+			latency = calc_L1_latency(latency, 1);
+			ep_state->l1_acceptable_latency = latency;
+		}
+	}
+}
+
+static unsigned int __pcie_aspm_check_state_one(struct pci_dev *pdev,
+	unsigned int state)
+{
+	struct pci_dev *parent_dev, *tmp_dev;
+	unsigned int latency, l1_latency = 0;
+	struct pcie_link_state *link_state;
+	struct endpoint_state *ep_state;
+
+	parent_dev = pdev->bus->self;
+	link_state = parent_dev->link_state;
+	state &= link_state->support_state;
+	if (state == 0)
+		return 0;
+	ep_state = &link_state->endpoints[PCI_FUNC(pdev->devfn)];
+
+	/*
+	 * Check latency for endpoint device.
+	 * TBD: The latency from the endpoint to root complex vary per
+	 * switch's upstream link state above the device. Here we just do a
+	 * simple check which assumes all links above the device can be in L1
+	 * state, that is we just consider the worst case. If switch's upstream
+	 * link can't be put into L0S/L1, then our check is too strictly.
+	 */
+	tmp_dev = pdev;
+	while (state & (PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1)) {
+		parent_dev = tmp_dev->bus->self;
+		link_state = parent_dev->link_state;
+		if (state & PCIE_LINK_STATE_L0S) {
+			latency = max_t(unsigned int,
+					link_state->l0s_upper_latency,
+					link_state->l0s_down_latency);
+			if (latency > ep_state->l0s_acceptable_latency)
+				state &= ~PCIE_LINK_STATE_L0S;
+		}
+		if (state & PCIE_LINK_STATE_L1) {
+			latency = max_t(unsigned int,
+					link_state->l1_upper_latency,
+					link_state->l1_down_latency);
+			if (latency + l1_latency >
+					ep_state->l1_acceptable_latency)
+				state &= ~PCIE_LINK_STATE_L1;
+		}
+		if (!parent_dev->bus->self) /* parent_dev is a root port */
+			break;
+		else {
+			/*
+			 * parent_dev is the downstream port of a switch, make
+			 * tmp_dev the upstream port of the switch
+			 */
+			tmp_dev = parent_dev->bus->self;
+			/*
+			 * every switch on the path to root complex need 1 more
+			 * microsecond for L1. Spec doesn't mention L0S.
+			 */
+			if (state & PCIE_LINK_STATE_L1)
+				l1_latency += 1000;
+		}
+	}
+	return state;
+}
+
+static unsigned int pcie_aspm_check_state(struct pci_dev *pdev,
+	unsigned int state)
+{
+	struct pci_dev *child_dev;
+
+	/* If no child, disable the link */
+	if (list_empty(&pdev->subordinate->devices))
+		return 0;
+	list_for_each_entry(child_dev, &pdev->subordinate->devices, bus_list) {
+		if (child_dev->pcie_type == PCI_EXP_TYPE_PCI_BRIDGE) {
+			/*
+			 * If downstream component of a link is pci bridge, we
+			 * disable ASPM for now for the link
+			 * */
+			state = 0;
+			break;
+		}
+		if ((child_dev->pcie_type != PCI_EXP_TYPE_ENDPOINT &&
+			child_dev->pcie_type != PCI_EXP_TYPE_LEG_END))
+			continue;
+		/* Device not in D0 doesn't need check latency */
+		if (child_dev->current_state == PCI_D1 ||
+			child_dev->current_state == PCI_D2 ||
+			child_dev->current_state == PCI_D3hot ||
+			child_dev->current_state == PCI_D3cold)
+			continue;
+		state = __pcie_aspm_check_state_one(child_dev, state);
+	}
+	return state;
+}
+
+static void __pcie_aspm_config_one_dev(struct pci_dev *pdev, unsigned int state)
+{
+	u16 reg16;
+	int pos = pci_find_capability(pdev, PCI_CAP_ID_EXP);
+
+	pci_read_config_word(pdev, pos + PCI_EXP_LNKCTL, &reg16);
+	reg16 &= ~0x3;
+	reg16 |= state;
+	pci_write_config_word(pdev, pos + PCI_EXP_LNKCTL, reg16);
+}
+
+static void __pcie_aspm_config_link(struct pci_dev *pdev, unsigned int state)
+{
+	struct pci_dev *child_dev;
+	int valid = 1;
+	struct pcie_link_state *link_state = pdev->link_state;
+
+	/*
+	 * if the downstream component has pci bridge function, don't do ASPM
+	 * now
+	 */
+	list_for_each_entry(child_dev, &pdev->subordinate->devices, bus_list) {
+		if (child_dev->pcie_type == PCI_EXP_TYPE_PCI_BRIDGE) {
+			valid = 0;
+			break;
+		}
+	}
+	if (!valid)
+		return;
+
+	/*
+	 * spec 2.0 suggests all functions should be configured the same
+	 * setting for ASPM. Enabling ASPM L1 should be done in upstream
+	 * component first and then downstream, and vice versa for disabling
+	 * ASPM L1. Spec doesn't mention L0S.
+	 */
+	if (state & PCIE_LINK_STATE_L1)
+		__pcie_aspm_config_one_dev(pdev, state);
+
+	list_for_each_entry(child_dev, &pdev->subordinate->devices, bus_list)
+		__pcie_aspm_config_one_dev(child_dev, state);
+
+	if (!(state & PCIE_LINK_STATE_L1))
+		__pcie_aspm_config_one_dev(pdev, state);
+
+	link_state->enabled_state = state;
+}
+
+static void __pcie_aspm_configure_link_state(struct pci_dev *pdev,
+	unsigned int state)
+{
+	struct pcie_link_state *link_state = pdev->link_state;
+
+	if (link_state->support_state == 0)
+		return;
+	state &= PCIE_LINK_STATE_L0S|PCIE_LINK_STATE_L1;
+
+	/* state 0 means disabling aspm */
+	state = pcie_aspm_check_state(pdev, state);
+	if (link_state->enabled_state == state)
+		return;
+	__pcie_aspm_config_link(pdev, state);
+}
+
+/*
+ * pcie_aspm_configure_link_state: enable/disable PCI express link state
+ * @pdev: the root port or switch downstream port
+ */
+static void pcie_aspm_configure_link_state(struct pci_dev *pdev,
+	unsigned int state)
+{
+	down_read(&pci_bus_sem);
+	mutex_lock(&aspm_lock);
+	__pcie_aspm_configure_link_state(pdev, state);
+	mutex_unlock(&aspm_lock);
+	up_read(&pci_bus_sem);
+}
+
+static void free_link_state(struct pci_dev *pdev)
+{
+	kfree(pdev->link_state);
+	pdev->link_state = NULL;
+}
+
+/*
+ * pcie_aspm_init_link_state: Initiate PCI express link state.
+ * It is called after the pcie and its children devices are scaned.
+ * @pdev: the root port or switch downstream port
+ */
+void pcie_aspm_init_link_state(struct pci_dev *pdev)
+{
+	unsigned int state;
+	struct pcie_link_state *link_state;
+	int error = 0;
+
+	if (aspm_disabled || !pdev->is_pcie || pdev->link_state)
+		return;
+	if (pdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT &&
+		pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM)
+		return;
+	down_read(&pci_bus_sem);
+	if (list_empty(&pdev->subordinate->devices))
+		goto out;
+
+	mutex_lock(&aspm_lock);
+
+	link_state = kzalloc(sizeof(*link_state), GFP_KERNEL);
+	if (!link_state)
+		goto unlock_out;
+	pdev->link_state = link_state;
+
+	pcie_aspm_configure_common_clock(pdev);
+
+	pcie_aspm_cap_init(pdev);
+
+	/* config link state to avoid BIOS error */
+	state = pcie_aspm_check_state(pdev, policy_to_aspm_state(pdev));
+	__pcie_aspm_config_link(pdev, state);
+
+	pcie_check_clock_pm(pdev);
+
+	link_state->pdev = pdev;
+	list_add(&link_state->sibiling, &link_list);
+
+unlock_out:
+	if (error)
+		free_link_state(pdev);
+	mutex_unlock(&aspm_lock);
+out:
+	up_read(&pci_bus_sem);
+}
+
+/* @pdev: the endpoint device */
+void pcie_aspm_exit_link_state(struct pci_dev *pdev)
+{
+	struct pci_dev *parent = pdev->bus->self;
+	struct pcie_link_state *link_state = parent->link_state;
+
+	if (aspm_disabled || !pdev->is_pcie || !parent || !link_state)
+		return;
+	if (parent->pcie_type != PCI_EXP_TYPE_ROOT_PORT &&
+		parent->pcie_type != PCI_EXP_TYPE_DOWNSTREAM)
+		return;
+	down_read(&pci_bus_sem);
+	mutex_lock(&aspm_lock);
+
+	/*
+	 * All PCIe functions are in one slot, remove one function will remove
+	 * the the whole slot, so just wait
+	 */
+	if (!list_empty(&parent->subordinate->devices))
+		goto out;
+
+	/* All functions are removed, so just disable ASPM for the link */
+	__pcie_aspm_config_one_dev(parent, 0);
+	list_del(&link_state->sibiling);
+	/* Clock PM is for endpoint device */
+
+	free_link_state(parent);
+out:
+	mutex_unlock(&aspm_lock);
+	up_read(&pci_bus_sem);
+}
+
+/* @pdev: the root port or switch downstream port */
+void pcie_aspm_pm_state_change(struct pci_dev *pdev)
+{
+	struct pcie_link_state *link_state = pdev->link_state;
+
+	if (aspm_disabled || !pdev->is_pcie || !pdev->link_state)
+		return;
+	if (pdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT &&
+		pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM)
+		return;
+	/*
+	 * devices changed PM state, we should recheck if latency meets all
+	 * functions' requirement
+	 */
+	pcie_aspm_configure_link_state(pdev, link_state->enabled_state);
+}
+
+/*
+ * pci_disable_link_state - disable pci device's link state, so the link will
+ * never enter specific states
+ */
+void pci_disable_link_state(struct pci_dev *pdev, int state)
+{
+	struct pci_dev *parent = pdev->bus->self;
+	struct pcie_link_state *link_state;
+
+	if (aspm_disabled || !pdev->is_pcie)
+		return;
+	if (pdev->pcie_type == PCI_EXP_TYPE_ROOT_PORT ||
+	    pdev->pcie_type == PCI_EXP_TYPE_DOWNSTREAM)
+		parent = pdev;
+	if (!parent)
+		return;
+
+	down_read(&pci_bus_sem);
+	mutex_lock(&aspm_lock);
+	link_state = parent->link_state;
+	link_state->support_state &=
+		~(state & (PCIE_LINK_STATE_L0S|PCIE_LINK_STATE_L1));
+	if (state & PCIE_LINK_STATE_CLKPM)
+		link_state->clk_pm_capable = 0;
+
+	__pcie_aspm_configure_link_state(parent, link_state->enabled_state);
+	if (!link_state->clk_pm_capable && link_state->clk_pm_enabled)
+		pcie_set_clock_pm(parent, 0);
+	mutex_unlock(&aspm_lock);
+	up_read(&pci_bus_sem);
+}
+EXPORT_SYMBOL(pci_disable_link_state);
+
+static int pcie_aspm_set_policy(const char *val, struct kernel_param *kp)
+{
+	int i;
+	struct pci_dev *pdev;
+	struct pcie_link_state *link_state;
+
+	for (i = 0; i < ARRAY_SIZE(policy_str); i++)
+		if (!strncmp(val, policy_str[i], strlen(policy_str[i])))
+			break;
+	if (i >= ARRAY_SIZE(policy_str))
+		return -EINVAL;
+	if (i == aspm_policy)
+		return 0;
+
+	down_read(&pci_bus_sem);
+	mutex_lock(&aspm_lock);
+	aspm_policy = i;
+	list_for_each_entry(link_state, &link_list, sibiling) {
+		pdev = link_state->pdev;
+		__pcie_aspm_configure_link_state(pdev,
+			policy_to_aspm_state(pdev));
+		if (link_state->clk_pm_capable &&
+		    link_state->clk_pm_enabled != policy_to_clkpm_state(pdev))
+			pcie_set_clock_pm(pdev, policy_to_clkpm_state(pdev));
+
+	}
+	mutex_unlock(&aspm_lock);
+	up_read(&pci_bus_sem);
+	return 0;
+}
+
+static int pcie_aspm_get_policy(char *buffer, struct kernel_param *kp)
+{
+	int i, cnt = 0;
+	for (i = 0; i < ARRAY_SIZE(policy_str); i++)
+		if (i == aspm_policy)
+			cnt += sprintf(buffer + cnt, "[%s] ", policy_str[i]);
+		else
+			cnt += sprintf(buffer + cnt, "%s ", policy_str[i]);
+	return cnt;
+}
+
+module_param_call(policy, pcie_aspm_set_policy, pcie_aspm_get_policy,
+	NULL, 0644);
+
+#ifdef CONFIG_PCIEASPM_DEBUG
+static ssize_t link_state_show(struct device *dev,
+		struct device_attribute *attr,
+		char *buf)
+{
+	struct pci_dev *pci_device = to_pci_dev(dev);
+	struct pcie_link_state *link_state = pci_device->link_state;
+
+	return sprintf(buf, "%d\n", link_state->enabled_state);
+}
+
+static ssize_t link_state_store(struct device *dev,
+		struct device_attribute *attr,
+		const char *buf,
+		size_t n)
+{
+	struct pci_dev *pci_device = to_pci_dev(dev);
+	int state;
+
+	if (n < 1)
+		return -EINVAL;
+	state = buf[0]-'0';
+	if (state >= 0 && state <= 3) {
+		/* setup link aspm state */
+		pcie_aspm_configure_link_state(pci_device, state);
+		return n;
+	}
+
+	return -EINVAL;
+}
+
+static ssize_t clk_ctl_show(struct device *dev,
+		struct device_attribute *attr,
+		char *buf)
+{
+	struct pci_dev *pci_device = to_pci_dev(dev);
+	struct pcie_link_state *link_state = pci_device->link_state;
+
+	return sprintf(buf, "%d\n", link_state->clk_pm_enabled);
+}
+
+static ssize_t clk_ctl_store(struct device *dev,
+		struct device_attribute *attr,
+		const char *buf,
+		size_t n)
+{
+	struct pci_dev *pci_device = to_pci_dev(dev);
+	int state;
+
+	if (n < 1)
+		return -EINVAL;
+	state = buf[0]-'0';
+
+	down_read(&pci_bus_sem);
+	mutex_lock(&aspm_lock);
+	pcie_set_clock_pm(pci_device, !!state);
+	mutex_unlock(&aspm_lock);
+	up_read(&pci_bus_sem);
+
+	return n;
+}
+
+static DEVICE_ATTR(link_state, 0644, link_state_show, link_state_store);
+static DEVICE_ATTR(clk_ctl, 0644, clk_ctl_show, clk_ctl_store);
+
+static char power_group[] = "power";
+void pcie_aspm_create_sysfs_dev_files(struct pci_dev *pdev)
+{
+	struct pcie_link_state *link_state = pdev->link_state;
+
+	if (!pdev->is_pcie || (pdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT &&
+		pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM))
+		return;
+
+	if (link_state->support_state)
+		sysfs_add_file_to_group(&pdev->dev.kobj,
+			&dev_attr_link_state.attr, power_group);
+	if (link_state->clk_pm_capable)
+		sysfs_add_file_to_group(&pdev->dev.kobj,
+			&dev_attr_clk_ctl.attr, power_group);
+}
+
+void pcie_aspm_remove_sysfs_dev_files(struct pci_dev *pdev)
+{
+	struct pcie_link_state *link_state = pdev->link_state;
+
+	if (!pdev->is_pcie || (pdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT &&
+		pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM))
+		return;
+
+	if (link_state->support_state)
+		sysfs_remove_file_from_group(&pdev->dev.kobj,
+			&dev_attr_link_state.attr, power_group);
+	if (link_state->clk_pm_capable)
+		sysfs_remove_file_from_group(&pdev->dev.kobj,
+			&dev_attr_clk_ctl.attr, power_group);
+}
+#endif
+
+static int __init pcie_aspm_disable(char *str)
+{
+	aspm_disabled = 1;
+	return 1;
+}
+
+__setup("pcie_noaspm", pcie_aspm_disable);
+
+static int __init pcie_aspm_init(void)
+{
+	if (aspm_disabled)
+		return 0;
+	pci_osc_support_set(OSC_ACTIVE_STATE_PWR_SUPPORT|
+		OSC_CLOCK_PWR_CAPABILITY_SUPPORT);
+	return 0;
+}
+
+fs_initcall(pcie_aspm_init);
diff --git a/drivers/pci/pcie/portdrv_core.c b/drivers/pci/pcie/portdrv_core.c
index b20a9b8..23d9eb0 100644
--- a/drivers/pci/pcie/portdrv_core.c
+++ b/drivers/pci/pcie/portdrv_core.c
@@ -192,9 +192,8 @@
 		if (reg32 & SLOT_HP_CAPABLE_MASK)
 			services |= PCIE_PORT_SERVICE_HP;
 	} 
-	/* PME Capable */
-	pos = pci_find_capability(dev, PCI_CAP_ID_PME);
-	if (pos) 
+	/* PME Capable - root port capability */
+	if (((reg16 >> 4) & PORT_TYPE_MASK) == PCIE_RC_PORT)
 		services |= PCIE_PORT_SERVICE_PME;
 	
 	pos = PCI_CFG_SPACE_SIZE;
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 5fd5852..8b505bd 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -9,6 +9,7 @@
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/cpumask.h>
+#include <linux/aspm.h>
 #include "pci.h"
 
 #define CARDBUS_LATENCY_TIMER	176	/* secondary latency timer */
@@ -53,7 +54,7 @@
 		b->legacy_io->attr.mode = S_IRUSR | S_IWUSR;
 		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);
+		device_create_bin_file(&b->dev, b->legacy_io);
 
 		/* Allocated above after the legacy_io struct */
 		b->legacy_mem = b->legacy_io + 1;
@@ -61,15 +62,15 @@
 		b->legacy_mem->size = 1024*1024;
 		b->legacy_mem->attr.mode = S_IRUSR | S_IWUSR;
 		b->legacy_mem->mmap = pci_mmap_legacy_mem;
-		class_device_create_bin_file(&b->class_dev, b->legacy_mem);
+		device_create_bin_file(&b->dev, b->legacy_mem);
 	}
 }
 
 void pci_remove_legacy_files(struct pci_bus *b)
 {
 	if (b->legacy_io) {
-		class_device_remove_bin_file(&b->class_dev, b->legacy_io);
-		class_device_remove_bin_file(&b->class_dev, b->legacy_mem);
+		device_remove_bin_file(&b->dev, b->legacy_io);
+		device_remove_bin_file(&b->dev, b->legacy_mem);
 		kfree(b->legacy_io); /* both are allocated here */
 	}
 }
@@ -81,26 +82,27 @@
 /*
  * PCI Bus Class Devices
  */
-static ssize_t pci_bus_show_cpuaffinity(struct class_device *class_dev,
+static ssize_t pci_bus_show_cpuaffinity(struct device *dev,
+					struct device_attribute *attr,
 					char *buf)
 {
 	int ret;
 	cpumask_t cpumask;
 
-	cpumask = pcibus_to_cpumask(to_pci_bus(class_dev));
+	cpumask = pcibus_to_cpumask(to_pci_bus(dev));
 	ret = cpumask_scnprintf(buf, PAGE_SIZE, cpumask);
 	if (ret < PAGE_SIZE)
 		buf[ret++] = '\n';
 	return ret;
 }
-CLASS_DEVICE_ATTR(cpuaffinity, S_IRUGO, pci_bus_show_cpuaffinity, NULL);
+DEVICE_ATTR(cpuaffinity, S_IRUGO, pci_bus_show_cpuaffinity, NULL);
 
 /*
  * PCI Bus Class
  */
-static void release_pcibus_dev(struct class_device *class_dev)
+static void release_pcibus_dev(struct device *dev)
 {
-	struct pci_bus *pci_bus = to_pci_bus(class_dev);
+	struct pci_bus *pci_bus = to_pci_bus(dev);
 
 	if (pci_bus->bridge)
 		put_device(pci_bus->bridge);
@@ -109,7 +111,7 @@
 
 static struct class pcibus_class = {
 	.name		= "pci_bus",
-	.release	= &release_pcibus_dev,
+	.dev_release	= &release_pcibus_dev,
 };
 
 static int __init pcibus_class_init(void)
@@ -392,7 +394,6 @@
 {
 	struct pci_bus *child;
 	int i;
-	int retval;
 
 	/*
 	 * Allocate a new bus, and inherit stuff from the parent..
@@ -408,15 +409,12 @@
 	child->bus_flags = parent->bus_flags;
 	child->bridge = get_device(&bridge->dev);
 
-	child->class_dev.class = &pcibus_class;
-	sprintf(child->class_dev.class_id, "%04x:%02x", pci_domain_nr(child), busnr);
-	retval = class_device_register(&child->class_dev);
-	if (retval)
-		goto error_register;
-	retval = class_device_create_file(&child->class_dev,
-					  &class_device_attr_cpuaffinity);
-	if (retval)
-		goto error_file_create;
+	/* initialize some portions of the bus device, but don't register it
+	 * now as the parent is not properly set up yet.  This device will get
+	 * registered later in pci_bus_add_devices()
+	 */
+	child->dev.class = &pcibus_class;
+	sprintf(child->dev.bus_id, "%04x:%02x", pci_domain_nr(child), busnr);
 
 	/*
 	 * Set up the primary, secondary and subordinate
@@ -434,12 +432,6 @@
 	bridge->subordinate = child;
 
 	return child;
-
-error_file_create:
-	class_device_unregister(&child->class_dev);
-error_register:
-	kfree(child);
-	return NULL;
 }
 
 struct pci_bus *pci_add_new_bus(struct pci_bus *parent, struct pci_dev *dev, int busnr)
@@ -471,8 +463,6 @@
 	}
 }
 
-unsigned int pci_scan_child_bus(struct pci_bus *bus);
-
 /*
  * If it's a bridge, configure it and scan the bus behind it.
  * For CardBus bridges, we don't scan behind as the devices will
@@ -641,13 +631,13 @@
 		    (child->number > bus->subordinate) ||
 		    (child->number < bus->number) ||
 		    (child->subordinate < bus->number)) {
-			pr_debug("PCI: Bus #%02x (-#%02x) is %s"
+			pr_debug("PCI: Bus #%02x (-#%02x) is %s "
 				"hidden behind%s bridge #%02x (-#%02x)\n",
 				child->number, child->subordinate,
 				(bus->number > child->subordinate &&
 				 bus->subordinate < child->number) ?
-					"wholly " : " partially",
-				bus->self->transparent ? " transparent" : " ",
+					"wholly" : "partially",
+				bus->self->transparent ? " transparent" : "",
 				bus->number, bus->subordinate);
 		}
 		bus = bus->parent;
@@ -971,6 +961,7 @@
 
 	return dev;
 }
+EXPORT_SYMBOL(pci_scan_single_device);
 
 /**
  * pci_scan_slot - scan a PCI slot on a bus for devices.
@@ -1011,6 +1002,10 @@
 				break;
 		}
 	}
+
+	if (bus->self)
+		pcie_aspm_init_link_state(bus->self);
+
 	return nr;
 }
 
@@ -1103,32 +1098,27 @@
 		goto dev_reg_err;
 	b->bridge = get_device(dev);
 
-	b->class_dev.class = &pcibus_class;
-	sprintf(b->class_dev.class_id, "%04x:%02x", pci_domain_nr(b), bus);
-	error = class_device_register(&b->class_dev);
+	b->dev.class = &pcibus_class;
+	b->dev.parent = b->bridge;
+	sprintf(b->dev.bus_id, "%04x:%02x", pci_domain_nr(b), bus);
+	error = device_register(&b->dev);
 	if (error)
 		goto class_dev_reg_err;
-	error = class_device_create_file(&b->class_dev, &class_device_attr_cpuaffinity);
+	error = device_create_file(&b->dev, &dev_attr_cpuaffinity);
 	if (error)
-		goto class_dev_create_file_err;
+		goto dev_create_file_err;
 
 	/* Create legacy_io and legacy_mem files for this bus */
 	pci_create_legacy_files(b);
 
-	error = sysfs_create_link(&b->class_dev.kobj, &b->bridge->kobj, "bridge");
-	if (error)
-		goto sys_create_link_err;
-
 	b->number = b->secondary = bus;
 	b->resource[0] = &ioport_resource;
 	b->resource[1] = &iomem_resource;
 
 	return b;
 
-sys_create_link_err:
-	class_device_remove_file(&b->class_dev, &class_device_attr_cpuaffinity);
-class_dev_create_file_err:
-	class_device_unregister(&b->class_dev);
+dev_create_file_err:
+	device_unregister(&b->dev);
 class_dev_reg_err:
 	device_unregister(dev);
 dev_reg_err:
@@ -1140,7 +1130,6 @@
 	kfree(b);
 	return NULL;
 }
-EXPORT_SYMBOL_GPL(pci_create_bus);
 
 struct pci_bus *pci_scan_bus_parented(struct device *parent,
 		int bus, struct pci_ops *ops, void *sysdata)
@@ -1159,7 +1148,6 @@
 EXPORT_SYMBOL(pci_do_scan_bus);
 EXPORT_SYMBOL(pci_scan_slot);
 EXPORT_SYMBOL(pci_scan_bridge);
-EXPORT_SYMBOL(pci_scan_single_device);
 EXPORT_SYMBOL_GPL(pci_scan_child_bus);
 #endif
 
diff --git a/drivers/pci/proc.c b/drivers/pci/proc.c
index 716439e..68aeeb7 100644
--- a/drivers/pci/proc.c
+++ b/drivers/pci/proc.c
@@ -11,6 +11,7 @@
 #include <linux/module.h>
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
+#include <linux/smp_lock.h>
 #include <linux/capability.h>
 #include <asm/uaccess.h>
 #include <asm/byteorder.h>
@@ -202,15 +203,18 @@
 	int write_combine;
 };
 
-static int proc_bus_pci_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+static long proc_bus_pci_ioctl(struct file *file, unsigned int cmd,
+			       unsigned long arg)
 {
-	const struct proc_dir_entry *dp = PDE(inode);
+	const struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode);
 	struct pci_dev *dev = dp->data;
 #ifdef HAVE_PCI_MMAP
 	struct pci_filp_private *fpriv = file->private_data;
 #endif /* HAVE_PCI_MMAP */
 	int ret = 0;
 
+	lock_kernel();
+
 	switch (cmd) {
 	case PCIIOC_CONTROLLER:
 		ret = pci_domain_nr(dev->bus);
@@ -239,6 +243,7 @@
 		break;
 	};
 
+	unlock_kernel();
 	return ret;
 }
 
@@ -291,7 +296,7 @@
 	.llseek		= proc_bus_pci_lseek,
 	.read		= proc_bus_pci_read,
 	.write		= proc_bus_pci_write,
-	.ioctl		= proc_bus_pci_ioctl,
+	.unlocked_ioctl	= proc_bus_pci_ioctl,
 #ifdef HAVE_PCI_MMAP
 	.open		= proc_bus_pci_open,
 	.release	= proc_bus_pci_release,
@@ -370,7 +375,7 @@
 	return 0;
 }
 
-static struct seq_operations proc_bus_pci_devices_op = {
+static const struct seq_operations proc_bus_pci_devices_op = {
 	.start	= pci_seq_start,
 	.next	= pci_seq_next,
 	.stop	= pci_seq_stop,
@@ -480,7 +485,3 @@
 
 __initcall(pci_proc_init);
 
-#ifdef CONFIG_HOTPLUG
-EXPORT_SYMBOL(pci_proc_detach_bus);
-#endif
-
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 72e0bd5..0a953d4 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -21,6 +21,7 @@
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/acpi.h>
+#include <linux/kallsyms.h>
 #include "pci.h"
 
 /* The Mellanox Tavor device gives false positive parity errors
@@ -46,14 +47,14 @@
 	while ((d = pci_get_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371SB_0, d))) {
 		pci_read_config_byte(d, 0x82, &dlc);
 		if (!(dlc & 1<<1)) {
-			printk(KERN_ERR "PCI: PIIX3: Enabling Passive Release on %s\n", pci_name(d));
+			dev_err(&d->dev, "PIIX3: Enabling Passive Release\n");
 			dlc |= 1<<1;
 			pci_write_config_byte(d, 0x82, dlc);
 		}
 	}
 }
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82441,	quirk_passive_release );
-DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82441,	quirk_passive_release );
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82441,	quirk_passive_release);
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82441,	quirk_passive_release);
 
 /*  The VIA VP2/VP3/MVP3 seem to have some 'features'. There may be a workaround
     but VIA don't answer queries. If you happen to have good contacts at VIA
@@ -68,20 +69,20 @@
 {
 	if (!isa_dma_bridge_buggy) {
 		isa_dma_bridge_buggy=1;
-		printk(KERN_INFO "Activating ISA DMA hang workarounds.\n");
+		dev_info(&dev->dev, "Activating ISA DMA hang workarounds\n");
 	}
 }
 	/*
 	 * Its not totally clear which chipsets are the problematic ones
 	 * We know 82C586 and 82C596 variants are affected.
 	 */
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C586_0,	quirk_isa_dma_hangs );
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C596,	quirk_isa_dma_hangs );
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,    PCI_DEVICE_ID_INTEL_82371SB_0,  quirk_isa_dma_hangs );
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AL,	PCI_DEVICE_ID_AL_M1533, 	quirk_isa_dma_hangs );
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NEC,	PCI_DEVICE_ID_NEC_CBUS_1,	quirk_isa_dma_hangs );
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NEC,	PCI_DEVICE_ID_NEC_CBUS_2,	quirk_isa_dma_hangs );
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NEC,	PCI_DEVICE_ID_NEC_CBUS_3,	quirk_isa_dma_hangs );
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C586_0,	quirk_isa_dma_hangs);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C596,	quirk_isa_dma_hangs);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,    PCI_DEVICE_ID_INTEL_82371SB_0,  quirk_isa_dma_hangs);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AL,	PCI_DEVICE_ID_AL_M1533, 	quirk_isa_dma_hangs);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NEC,	PCI_DEVICE_ID_NEC_CBUS_1,	quirk_isa_dma_hangs);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NEC,	PCI_DEVICE_ID_NEC_CBUS_2,	quirk_isa_dma_hangs);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NEC,	PCI_DEVICE_ID_NEC_CBUS_3,	quirk_isa_dma_hangs);
 
 int pci_pci_problems;
 EXPORT_SYMBOL(pci_pci_problems);
@@ -92,12 +93,12 @@
 static void __devinit quirk_nopcipci(struct pci_dev *dev)
 {
 	if ((pci_pci_problems & PCIPCI_FAIL)==0) {
-		printk(KERN_INFO "Disabling direct PCI/PCI transfers.\n");
+		dev_info(&dev->dev, "Disabling direct PCI/PCI transfers\n");
 		pci_pci_problems |= PCIPCI_FAIL;
 	}
 }
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_5597,		quirk_nopcipci );
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_496,		quirk_nopcipci );
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_5597,		quirk_nopcipci);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_496,		quirk_nopcipci);
 
 static void __devinit quirk_nopciamd(struct pci_dev *dev)
 {
@@ -105,11 +106,11 @@
 	pci_read_config_byte(dev, 0x08, &rev);
 	if (rev == 0x13) {
 		/* Erratum 24 */
-		printk(KERN_INFO "Chipset erratum: Disabling direct PCI/AGP transfers.\n");
+		dev_info(&dev->dev, "Chipset erratum: Disabling direct PCI/AGP transfers\n");
 		pci_pci_problems |= PCIAGP_FAIL;
 	}
 }
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD,	PCI_DEVICE_ID_AMD_8151_0,	quirk_nopciamd );
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD,	PCI_DEVICE_ID_AMD_8151_0,	quirk_nopciamd);
 
 /*
  *	Triton requires workarounds to be used by the drivers
@@ -117,14 +118,14 @@
 static void __devinit quirk_triton(struct pci_dev *dev)
 {
 	if ((pci_pci_problems&PCIPCI_TRITON)==0) {
-		printk(KERN_INFO "Limiting direct PCI/PCI transfers.\n");
+		dev_info(&dev->dev, "Limiting direct PCI/PCI transfers\n");
 		pci_pci_problems |= PCIPCI_TRITON;
 	}
 }
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 	PCI_DEVICE_ID_INTEL_82437, 	quirk_triton ); 
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 	PCI_DEVICE_ID_INTEL_82437VX, 	quirk_triton ); 
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 	PCI_DEVICE_ID_INTEL_82439, 	quirk_triton ); 
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 	PCI_DEVICE_ID_INTEL_82439TX, 	quirk_triton ); 
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 	PCI_DEVICE_ID_INTEL_82437, 	quirk_triton);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 	PCI_DEVICE_ID_INTEL_82437VX, 	quirk_triton);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 	PCI_DEVICE_ID_INTEL_82439, 	quirk_triton);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 	PCI_DEVICE_ID_INTEL_82439TX, 	quirk_triton);
 
 /*
  *	VIA Apollo KT133 needs PCI latency patch
@@ -139,25 +140,22 @@
 static void quirk_vialatency(struct pci_dev *dev)
 {
 	struct pci_dev *p;
-	u8 rev;
 	u8 busarb;
 	/* Ok we have a potential problem chipset here. Now see if we have
 	   a buggy southbridge */
 	   
 	p = pci_get_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686, NULL);
 	if (p!=NULL) {
-		pci_read_config_byte(p, PCI_CLASS_REVISION, &rev);
 		/* 0x40 - 0x4f == 686B, 0x10 - 0x2f == 686A; thanks Dan Hollis */
 		/* Check for buggy part revisions */
-		if (rev < 0x40 || rev > 0x42)
+		if (p->revision < 0x40 || p->revision > 0x42)
 			goto exit;
 	} else {
 		p = pci_get_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8231, NULL);
 		if (p==NULL)	/* No problem parts */
 			goto exit;
-		pci_read_config_byte(p, PCI_CLASS_REVISION, &rev);
 		/* Check for buggy part revisions */
-		if (rev < 0x10 || rev > 0x12) 
+		if (p->revision < 0x10 || p->revision > 0x12)
 			goto exit;
 	}
 	
@@ -180,17 +178,17 @@
 	busarb &= ~(1<<5);
 	busarb |= (1<<4);
 	pci_write_config_byte(dev, 0x76, busarb);
-	printk(KERN_INFO "Applying VIA southbridge workaround.\n");
+	dev_info(&dev->dev, "Applying VIA southbridge workaround\n");
 exit:
 	pci_dev_put(p);
 }
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_8363_0,	quirk_vialatency );
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_8371_1,	quirk_vialatency );
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_8361,		quirk_vialatency );
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_8363_0,	quirk_vialatency);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_8371_1,	quirk_vialatency);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_8361,		quirk_vialatency);
 /* Must restore this on a resume from RAM */
-DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_8363_0,	quirk_vialatency );
-DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_8371_1,	quirk_vialatency );
-DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_8361,		quirk_vialatency );
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_8363_0,	quirk_vialatency);
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_8371_1,	quirk_vialatency);
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_8361,		quirk_vialatency);
 
 /*
  *	VIA Apollo VP3 needs ETBF on BT848/878
@@ -198,20 +196,20 @@
 static void __devinit quirk_viaetbf(struct pci_dev *dev)
 {
 	if ((pci_pci_problems&PCIPCI_VIAETBF)==0) {
-		printk(KERN_INFO "Limiting direct PCI/PCI transfers.\n");
+		dev_info(&dev->dev, "Limiting direct PCI/PCI transfers\n");
 		pci_pci_problems |= PCIPCI_VIAETBF;
 	}
 }
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C597_0,	quirk_viaetbf );
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C597_0,	quirk_viaetbf);
 
 static void __devinit quirk_vsfx(struct pci_dev *dev)
 {
 	if ((pci_pci_problems&PCIPCI_VSFX)==0) {
-		printk(KERN_INFO "Limiting direct PCI/PCI transfers.\n");
+		dev_info(&dev->dev, "Limiting direct PCI/PCI transfers\n");
 		pci_pci_problems |= PCIPCI_VSFX;
 	}
 }
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C576,	quirk_vsfx );
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C576,	quirk_vsfx);
 
 /*
  *	Ali Magik requires workarounds to be used by the drivers
@@ -222,12 +220,12 @@
 static void __init quirk_alimagik(struct pci_dev *dev)
 {
 	if ((pci_pci_problems&PCIPCI_ALIMAGIK)==0) {
-		printk(KERN_INFO "Limiting direct PCI/PCI transfers.\n");
+		dev_info(&dev->dev, "Limiting direct PCI/PCI transfers\n");
 		pci_pci_problems |= PCIPCI_ALIMAGIK|PCIPCI_TRITON;
 	}
 }
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AL, 	PCI_DEVICE_ID_AL_M1647, 	quirk_alimagik );
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AL, 	PCI_DEVICE_ID_AL_M1651, 	quirk_alimagik );
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AL, 	PCI_DEVICE_ID_AL_M1647, 	quirk_alimagik);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AL, 	PCI_DEVICE_ID_AL_M1651, 	quirk_alimagik);
 
 /*
  *	Natoma has some interesting boundary conditions with Zoran stuff
@@ -236,16 +234,16 @@
 static void __devinit quirk_natoma(struct pci_dev *dev)
 {
 	if ((pci_pci_problems&PCIPCI_NATOMA)==0) {
-		printk(KERN_INFO "Limiting direct PCI/PCI transfers.\n");
+		dev_info(&dev->dev, "Limiting direct PCI/PCI transfers\n");
 		pci_pci_problems |= PCIPCI_NATOMA;
 	}
 }
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 	PCI_DEVICE_ID_INTEL_82441, 	quirk_natoma ); 
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 	PCI_DEVICE_ID_INTEL_82443LX_0, 	quirk_natoma ); 
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 	PCI_DEVICE_ID_INTEL_82443LX_1, 	quirk_natoma ); 
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 	PCI_DEVICE_ID_INTEL_82443BX_0, 	quirk_natoma ); 
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 	PCI_DEVICE_ID_INTEL_82443BX_1, 	quirk_natoma ); 
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 	PCI_DEVICE_ID_INTEL_82443BX_2, 	quirk_natoma );
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 	PCI_DEVICE_ID_INTEL_82441, 	quirk_natoma);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 	PCI_DEVICE_ID_INTEL_82443LX_0, 	quirk_natoma);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 	PCI_DEVICE_ID_INTEL_82443LX_1, 	quirk_natoma);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 	PCI_DEVICE_ID_INTEL_82443BX_0, 	quirk_natoma);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 	PCI_DEVICE_ID_INTEL_82443BX_1, 	quirk_natoma);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 	PCI_DEVICE_ID_INTEL_82443BX_2, 	quirk_natoma);
 
 /*
  *  This chip can cause PCI parity errors if config register 0xA0 is read
@@ -255,7 +253,7 @@
 {
 	dev->cfg_size = 0xA0;
 }
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_IBM,	PCI_DEVICE_ID_IBM_CITRINE,	quirk_citrine );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_IBM,	PCI_DEVICE_ID_IBM_CITRINE,	quirk_citrine);
 
 /*
  *  S3 868 and 968 chips report region size equal to 32M, but they decode 64M.
@@ -270,8 +268,8 @@
 		r->end = 0x3ffffff;
 	}
 }
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_S3,	PCI_DEVICE_ID_S3_868,		quirk_s3_64M );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_S3,	PCI_DEVICE_ID_S3_968,		quirk_s3_64M );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_S3,	PCI_DEVICE_ID_S3_868,		quirk_s3_64M);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_S3,	PCI_DEVICE_ID_S3_968,		quirk_s3_64M);
 
 static void __devinit quirk_io_region(struct pci_dev *dev, unsigned region,
 	unsigned size, int nr, const char *name)
@@ -292,7 +290,7 @@
 		pcibios_bus_to_resource(dev, res, &bus_region);
 
 		pci_claim_resource(dev, nr);
-		printk("PCI quirk: region %04x-%04x claimed by %s\n", region, region + size - 1, name);
+		dev_info(&dev->dev, "quirk: region %04x-%04x claimed by %s\n", region, region + size - 1, name);
 	}
 }	
 
@@ -302,12 +300,12 @@
  */
 static void __devinit quirk_ati_exploding_mce(struct pci_dev *dev)
 {
-	printk(KERN_INFO "ATI Northbridge, reserving I/O ports 0x3b0 to 0x3bb.\n");
+	dev_info(&dev->dev, "ATI Northbridge, reserving I/O ports 0x3b0 to 0x3bb\n");
 	/* Mae rhaid i ni beidio ag edrych ar y lleoliadiau I/O hyn */
 	request_region(0x3b0, 0x0C, "RadeonIGP");
 	request_region(0x3d3, 0x01, "RadeonIGP");
 }
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI,	PCI_DEVICE_ID_ATI_RS100,   quirk_ati_exploding_mce );
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI,	PCI_DEVICE_ID_ATI_RS100,   quirk_ati_exploding_mce);
 
 /*
  * Let's make the southbridge information explicit instead
@@ -329,7 +327,7 @@
 	pci_read_config_word(dev, 0xE2, &region);
 	quirk_io_region(dev, region, 32, PCI_BRIDGE_RESOURCES+1, "ali7101 SMB");
 }
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL,	PCI_DEVICE_ID_AL_M7101,		quirk_ali7101_acpi );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL,	PCI_DEVICE_ID_AL_M7101,		quirk_ali7101_acpi);
 
 static void piix4_io_quirk(struct pci_dev *dev, const char *name, unsigned int port, unsigned int enable)
 {
@@ -354,7 +352,7 @@
 	 * let's get enough confirmation reports first. 
 	 */
 	base &= -size;
-	printk("%s PIO at %04x-%04x\n", name, base, base + size - 1);
+	dev_info(&dev->dev, "%s PIO at %04x-%04x\n", name, base, base + size - 1);
 }
 
 static void piix4_mem_quirk(struct pci_dev *dev, const char *name, unsigned int port, unsigned int enable)
@@ -379,7 +377,7 @@
 	 * reserve it, but let's get enough confirmation reports first. 
 	 */
 	base &= -size;
-	printk("%s MMIO at %04x-%04x\n", name, base, base + size - 1);
+	dev_info(&dev->dev, "%s MMIO at %04x-%04x\n", name, base, base + size - 1);
 }
 
 /*
@@ -418,8 +416,8 @@
 	piix4_io_quirk(dev, "PIIX4 devres I", 0x78, 1 << 20);
 	piix4_io_quirk(dev, "PIIX4 devres J", 0x7c, 1 << 20);
 }
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82371AB_3,	quirk_piix4_acpi );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82443MX_3,	quirk_piix4_acpi );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82371AB_3,	quirk_piix4_acpi);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82443MX_3,	quirk_piix4_acpi);
 
 /*
  * ICH4, ICH4-M, ICH5, ICH5-M ACPI: Three IO regions pointed to by longwords at
@@ -436,16 +434,16 @@
 	pci_read_config_dword(dev, 0x58, &region);
 	quirk_io_region(dev, region, 64, PCI_BRIDGE_RESOURCES+1, "ICH4 GPIO");
 }
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,    PCI_DEVICE_ID_INTEL_82801AA_0,		quirk_ich4_lpc_acpi );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,    PCI_DEVICE_ID_INTEL_82801AB_0,		quirk_ich4_lpc_acpi );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,    PCI_DEVICE_ID_INTEL_82801BA_0,		quirk_ich4_lpc_acpi );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,    PCI_DEVICE_ID_INTEL_82801BA_10,	quirk_ich4_lpc_acpi );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,    PCI_DEVICE_ID_INTEL_82801CA_0,		quirk_ich4_lpc_acpi );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,    PCI_DEVICE_ID_INTEL_82801CA_12,	quirk_ich4_lpc_acpi );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,    PCI_DEVICE_ID_INTEL_82801DB_0,		quirk_ich4_lpc_acpi );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,    PCI_DEVICE_ID_INTEL_82801DB_12,	quirk_ich4_lpc_acpi );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,    PCI_DEVICE_ID_INTEL_82801EB_0,		quirk_ich4_lpc_acpi );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,    PCI_DEVICE_ID_INTEL_ESB_1,		quirk_ich4_lpc_acpi );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,    PCI_DEVICE_ID_INTEL_82801AA_0,		quirk_ich4_lpc_acpi);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,    PCI_DEVICE_ID_INTEL_82801AB_0,		quirk_ich4_lpc_acpi);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,    PCI_DEVICE_ID_INTEL_82801BA_0,		quirk_ich4_lpc_acpi);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,    PCI_DEVICE_ID_INTEL_82801BA_10,	quirk_ich4_lpc_acpi);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,    PCI_DEVICE_ID_INTEL_82801CA_0,		quirk_ich4_lpc_acpi);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,    PCI_DEVICE_ID_INTEL_82801CA_12,	quirk_ich4_lpc_acpi);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,    PCI_DEVICE_ID_INTEL_82801DB_0,		quirk_ich4_lpc_acpi);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,    PCI_DEVICE_ID_INTEL_82801DB_12,	quirk_ich4_lpc_acpi);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,    PCI_DEVICE_ID_INTEL_82801EB_0,		quirk_ich4_lpc_acpi);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,    PCI_DEVICE_ID_INTEL_ESB_1,		quirk_ich4_lpc_acpi);
 
 static void __devinit quirk_ich6_lpc_acpi(struct pci_dev *dev)
 {
@@ -457,20 +455,20 @@
 	pci_read_config_dword(dev, 0x48, &region);
 	quirk_io_region(dev, region, 64, PCI_BRIDGE_RESOURCES+1, "ICH6 GPIO");
 }
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_ICH6_0, quirk_ich6_lpc_acpi );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_ICH6_1, quirk_ich6_lpc_acpi );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_ICH7_0, quirk_ich6_lpc_acpi );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_ICH7_1, quirk_ich6_lpc_acpi );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_ICH7_31, quirk_ich6_lpc_acpi );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_ICH8_0, quirk_ich6_lpc_acpi );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_ICH8_2, quirk_ich6_lpc_acpi );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_ICH8_3, quirk_ich6_lpc_acpi );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_ICH8_1, quirk_ich6_lpc_acpi );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_ICH8_4, quirk_ich6_lpc_acpi );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_ICH9_2, quirk_ich6_lpc_acpi );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_ICH9_4, quirk_ich6_lpc_acpi );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_ICH9_7, quirk_ich6_lpc_acpi );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_ICH9_8, quirk_ich6_lpc_acpi );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_ICH6_0, quirk_ich6_lpc_acpi);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_ICH6_1, quirk_ich6_lpc_acpi);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_ICH7_0, quirk_ich6_lpc_acpi);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_ICH7_1, quirk_ich6_lpc_acpi);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_ICH7_31, quirk_ich6_lpc_acpi);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_ICH8_0, quirk_ich6_lpc_acpi);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_ICH8_2, quirk_ich6_lpc_acpi);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_ICH8_3, quirk_ich6_lpc_acpi);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_ICH8_1, quirk_ich6_lpc_acpi);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_ICH8_4, quirk_ich6_lpc_acpi);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_ICH9_2, quirk_ich6_lpc_acpi);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_ICH9_4, quirk_ich6_lpc_acpi);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_ICH9_7, quirk_ich6_lpc_acpi);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_ICH9_8, quirk_ich6_lpc_acpi);
 
 /*
  * VIA ACPI: One IO region pointed to by longword at
@@ -486,7 +484,7 @@
 		quirk_io_region(dev, region, 256, PCI_BRIDGE_RESOURCES, "vt82c586 ACPI");
 	}
 }
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C586_3,	quirk_vt82c586_acpi );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C586_3,	quirk_vt82c586_acpi);
 
 /*
  * VIA VT82C686 ACPI: Three IO region pointed to by (long)words at
@@ -509,7 +507,7 @@
 	smb &= PCI_BASE_ADDRESS_IO_MASK;
 	quirk_io_region(dev, smb, 16, PCI_BRIDGE_RESOURCES + 2, "vt82c686 SMB");
 }
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C686_4,	quirk_vt82c686_acpi );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C686_4,	quirk_vt82c686_acpi);
 
 /*
  * VIA VT8235 ISA Bridge: Two IO regions pointed to by words at
@@ -551,14 +549,14 @@
 	else
 		tmp = 0x1f; /* all known bits (4-0) routed to external APIC */
 		
-	printk(KERN_INFO "PCI: %sbling Via external APIC routing\n",
+	dev_info(&dev->dev, "%sbling VIA external APIC routing\n",
 	       tmp == 0 ? "Disa" : "Ena");
 
 	/* Offset 0x58: External APIC IRQ output control */
 	pci_write_config_byte (dev, 0x58, tmp);
 }
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C686,	quirk_via_ioapic );
-DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C686,	quirk_via_ioapic );
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C686,	quirk_via_ioapic);
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C686,	quirk_via_ioapic);
 
 /*
  * VIA 8237: Some BIOSs don't set the 'Bypass APIC De-Assert Message' Bit.
@@ -573,7 +571,7 @@
 
 	pci_read_config_byte(dev, 0x5B, &misc_control2);
 	if (!(misc_control2 & BYPASS_APIC_DEASSERT)) {
-		printk(KERN_INFO "PCI: Bypassing VIA 8237 APIC De-Assert Message\n");
+		dev_info(&dev->dev, "Bypassing VIA 8237 APIC De-Assert Message\n");
 		pci_write_config_byte(dev, 0x5B, misc_control2|BYPASS_APIC_DEASSERT);
 	}
 }
@@ -592,18 +590,18 @@
 static void __devinit quirk_amd_ioapic(struct pci_dev *dev)
 {
 	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");
+		dev_warn(&dev->dev, "I/O APIC: AMD Erratum #22 may be present. In the event of instability try\n");
+		dev_warn(&dev->dev, "        : booting with the \"noapic\" option\n");
 	}
 }
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD,	PCI_DEVICE_ID_AMD_VIPER_7410,	quirk_amd_ioapic );
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD,	PCI_DEVICE_ID_AMD_VIPER_7410,	quirk_amd_ioapic);
 
 static void __init quirk_ioapic_rmw(struct pci_dev *dev)
 {
 	if (dev->devfn == 0 && dev->bus->number == 0)
 		sis_apic_bug = 1;
 }
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SI,	PCI_ANY_ID,			quirk_ioapic_rmw );
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SI,	PCI_ANY_ID,			quirk_ioapic_rmw);
 
 #define AMD8131_revA0        0x01
 #define AMD8131_revB0        0x11
@@ -617,7 +615,7 @@
                 return;
 
         if (dev->revision == AMD8131_revA0 || dev->revision == AMD8131_revB0) {
-                printk(KERN_INFO "Fixing up AMD8131 IOAPIC mode\n"); 
+                dev_info(&dev->dev, "Fixing up AMD8131 IOAPIC mode\n");
                 pci_read_config_byte( dev, AMD8131_MISC, &tmp);
                 tmp &= ~(1 << AMD8131_NIOAMODE_BIT);
                 pci_write_config_byte( dev, AMD8131_MISC, tmp);
@@ -634,8 +632,8 @@
 static void __init quirk_amd_8131_mmrbc(struct pci_dev *dev)
 {
 	if (dev->subordinate && dev->revision <= 0x12) {
-		printk(KERN_INFO "AMD8131 rev %x detected, disabling PCI-X "
-				"MMRBC\n", dev->revision);
+		dev_info(&dev->dev, "AMD8131 rev %x detected; "
+			"disabling PCI-X MMRBC\n", dev->revision);
 		dev->subordinate->bus_flags |= PCI_BUS_FLAGS_NO_MMRBC;
 	}
 }
@@ -660,8 +658,8 @@
 	if (irq && (irq != 2))
 		d->irq = irq;
 }
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C586_3,	quirk_via_acpi );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C686_4,	quirk_via_acpi );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C586_3,	quirk_via_acpi);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C686_4,	quirk_via_acpi);
 
 
 /*
@@ -742,8 +740,8 @@
 
 	pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq);
 	if (new_irq != irq) {
-		printk(KERN_INFO "PCI: VIA VLink IRQ fixup for %s, from %d to %d\n",
-			pci_name(dev), irq, new_irq);
+		dev_info(&dev->dev, "VIA VLink IRQ fixup, from %d to %d\n",
+			irq, new_irq);
 		udelay(15);	/* unknown if delay really needed */
 		pci_write_config_byte(dev, PCI_INTERRUPT_LINE, new_irq);
 	}
@@ -761,7 +759,7 @@
 	pci_write_config_byte(dev, 0xfc, 0);
 	pci_read_config_word(dev, PCI_DEVICE_ID, &dev->device);
 }
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C597_0,	quirk_vt82c598_id );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C597_0,	quirk_vt82c598_id);
 
 /*
  * CardBus controllers have a legacy base address that enables them
@@ -791,15 +789,15 @@
 	pci_read_config_dword(dev, 0x4C, &pcic);
 	if ((pcic&6)!=6) {
 		pcic |= 6;
-		printk(KERN_WARNING "BIOS failed to enable PCI standards compliance, fixing this error.\n");
+		dev_warn(&dev->dev, "BIOS failed to enable PCI standards compliance; fixing this error\n");
 		pci_write_config_dword(dev, 0x4C, pcic);
 		pci_read_config_dword(dev, 0x84, &pcic);
 		pcic |= (1<<23);	/* Required in this mode */
 		pci_write_config_dword(dev, 0x84, pcic);
 	}
 }
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD,	PCI_DEVICE_ID_AMD_FE_GATE_700C, quirk_amd_ordering );
-DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_AMD,	PCI_DEVICE_ID_AMD_FE_GATE_700C, quirk_amd_ordering );
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD,	PCI_DEVICE_ID_AMD_FE_GATE_700C, quirk_amd_ordering);
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_AMD,	PCI_DEVICE_ID_AMD_FE_GATE_700C, quirk_amd_ordering);
 
 /*
  *	DreamWorks provided workaround for Dunord I-3000 problem
@@ -814,7 +812,7 @@
 	r->start = 0;
 	r->end = 0xffffff;
 }
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_DUNORD,	PCI_DEVICE_ID_DUNORD_I3000,	quirk_dunord );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_DUNORD,	PCI_DEVICE_ID_DUNORD_I3000,	quirk_dunord);
 
 /*
  * i82380FB mobile docking controller: its PCI-to-PCI bridge
@@ -826,8 +824,8 @@
 {
 	dev->transparent = 1;
 }
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82380FB,	quirk_transparent_bridge );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TOSHIBA,	0x605,	quirk_transparent_bridge );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82380FB,	quirk_transparent_bridge);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TOSHIBA,	0x605,	quirk_transparent_bridge);
 
 /*
  * Common misconfiguration of the MediaGX/Geode PCI master that will
@@ -841,12 +839,12 @@
 	pci_read_config_byte(dev, 0x41, &reg);
 	if (reg & 2) {
 		reg &= ~2;
-		printk(KERN_INFO "PCI: Fixup for MediaGX/Geode Slave Disconnect Boundary (0x41=0x%02x)\n", reg);
+		dev_info(&dev->dev, "Fixup for MediaGX/Geode Slave Disconnect Boundary (0x41=0x%02x)\n", reg);
                 pci_write_config_byte(dev, 0x41, reg);
 	}
 }
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_CYRIX,	PCI_DEVICE_ID_CYRIX_PCI_MASTER, quirk_mediagx_master );
-DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_CYRIX,	PCI_DEVICE_ID_CYRIX_PCI_MASTER, quirk_mediagx_master );
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_CYRIX,	PCI_DEVICE_ID_CYRIX_PCI_MASTER, quirk_mediagx_master);
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_CYRIX,	PCI_DEVICE_ID_CYRIX_PCI_MASTER, quirk_mediagx_master);
 
 /*
  *	Ensure C0 rev restreaming is off. This is normally done by
@@ -863,11 +861,11 @@
 	if (config & (1<<6)) {
 		config &= ~(1<<6);
 		pci_write_config_word(pdev, 0x40, config);
-		printk(KERN_INFO "PCI: C0 revision 450NX. Disabling PCI restreaming.\n");
+		dev_info(&pdev->dev, "C0 revision 450NX. Disabling PCI restreaming\n");
 	}
 }
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82454NX,	quirk_disable_pxb );
-DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82454NX,	quirk_disable_pxb );
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82454NX,	quirk_disable_pxb);
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82454NX,	quirk_disable_pxb);
 
 
 static void __devinit quirk_sb600_sata(struct pci_dev *pdev)
@@ -902,7 +900,7 @@
 		/* PCI layer will sort out resources */
 	}
 }
-DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB5IDE, quirk_svwks_csb5ide );
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB5IDE, quirk_svwks_csb5ide);
 
 /*
  *	Intel 82801CAM ICH3-M datasheet says IDE modes must be the same
@@ -914,7 +912,7 @@
 	pci_read_config_byte(pdev, PCI_CLASS_PROG, &prog);
 
 	if (((prog & 1) && !(prog & 4)) || ((prog & 4) && !(prog & 1))) {
-		printk(KERN_INFO "PCI: IDE mode mismatch; forcing legacy mode\n");
+		dev_info(&pdev->dev, "IDE mode mismatch; forcing legacy mode\n");
 		prog &= ~5;
 		pdev->class &= ~5;
 		pci_write_config_byte(pdev, PCI_CLASS_PROG, prog);
@@ -929,7 +927,7 @@
 {
 	dev->class = PCI_CLASS_BRIDGE_EISA << 8;
 }
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82375,	quirk_eisa_bridge );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82375,	quirk_eisa_bridge);
 
 
 /*
@@ -1022,6 +1020,11 @@
 			case 0x12bd: /* HP D530 */
 				asus_hides_smbus = 1;
 			}
+		else if (dev->device == PCI_DEVICE_ID_INTEL_82875_HB)
+			switch (dev->subsystem_device) {
+			case 0x12bf: /* HP xw4100 */
+				asus_hides_smbus = 1;
+			}
 		else if (dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB)
 			switch (dev->subsystem_device) {
 			case 0x099c: /* HP Compaq nx6110 */
@@ -1049,17 +1052,18 @@
 			}
 	}
 }
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82845_HB,	asus_hides_smbus_hostbridge );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82845G_HB,	asus_hides_smbus_hostbridge );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82850_HB,	asus_hides_smbus_hostbridge );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82865_HB,	asus_hides_smbus_hostbridge );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_7205_0,	asus_hides_smbus_hostbridge );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_E7501_MCH,	asus_hides_smbus_hostbridge );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82855PM_HB,	asus_hides_smbus_hostbridge );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82855GM_HB,	asus_hides_smbus_hostbridge );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82915GM_HB, asus_hides_smbus_hostbridge );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82845_HB,	asus_hides_smbus_hostbridge);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82845G_HB,	asus_hides_smbus_hostbridge);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82850_HB,	asus_hides_smbus_hostbridge);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82865_HB,	asus_hides_smbus_hostbridge);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82875_HB,	asus_hides_smbus_hostbridge);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_7205_0,	asus_hides_smbus_hostbridge);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_E7501_MCH,	asus_hides_smbus_hostbridge);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82855PM_HB,	asus_hides_smbus_hostbridge);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82855GM_HB,	asus_hides_smbus_hostbridge);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82915GM_HB, asus_hides_smbus_hostbridge);
 
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82810_IG3,	asus_hides_smbus_hostbridge );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82810_IG3,	asus_hides_smbus_hostbridge);
 
 static void asus_hides_smbus_lpc(struct pci_dev *dev)
 {
@@ -1073,25 +1077,25 @@
 		pci_write_config_word(dev, 0xF2, val & (~0x8));
 		pci_read_config_word(dev, 0xF2, &val);
 		if (val & 0x8)
-			printk(KERN_INFO "PCI: i801 SMBus device continues to play 'hide and seek'! 0x%x\n", val);
+			dev_info(&dev->dev, "i801 SMBus device continues to play 'hide and seek'! 0x%x\n", val);
 		else
-			printk(KERN_INFO "PCI: Enabled i801 SMBus device\n");
+			dev_info(&dev->dev, "Enabled i801 SMBus device\n");
 	}
 }
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82801AA_0,	asus_hides_smbus_lpc );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82801DB_0,	asus_hides_smbus_lpc );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82801BA_0,	asus_hides_smbus_lpc );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82801CA_0,	asus_hides_smbus_lpc );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82801CA_12,	asus_hides_smbus_lpc );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82801DB_12,	asus_hides_smbus_lpc );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82801EB_0,	asus_hides_smbus_lpc );
-DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82801AA_0,	asus_hides_smbus_lpc );
-DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82801DB_0,	asus_hides_smbus_lpc );
-DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82801BA_0,	asus_hides_smbus_lpc );
-DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82801CA_0,	asus_hides_smbus_lpc );
-DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82801CA_12,	asus_hides_smbus_lpc );
-DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82801DB_12,	asus_hides_smbus_lpc );
-DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82801EB_0,	asus_hides_smbus_lpc );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82801AA_0,	asus_hides_smbus_lpc);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82801DB_0,	asus_hides_smbus_lpc);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82801BA_0,	asus_hides_smbus_lpc);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82801CA_0,	asus_hides_smbus_lpc);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82801CA_12,	asus_hides_smbus_lpc);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82801DB_12,	asus_hides_smbus_lpc);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82801EB_0,	asus_hides_smbus_lpc);
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82801AA_0,	asus_hides_smbus_lpc);
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82801DB_0,	asus_hides_smbus_lpc);
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82801BA_0,	asus_hides_smbus_lpc);
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82801CA_0,	asus_hides_smbus_lpc);
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82801CA_12,	asus_hides_smbus_lpc);
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82801DB_12,	asus_hides_smbus_lpc);
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82801EB_0,	asus_hides_smbus_lpc);
 
 static void asus_hides_smbus_lpc_ich6(struct pci_dev *dev)
 {
@@ -1106,10 +1110,10 @@
 	val=readl(base + 0x3418); /* read the Function Disable register, dword mode only */
 	writel(val & 0xFFFFFFF7, base + 0x3418); /* enable the SMBus device */
 	iounmap(base);
-	printk(KERN_INFO "PCI: Enabled ICH6/i801 SMBus device\n");
+	dev_info(&dev->dev, "Enabled ICH6/i801 SMBus device\n");
 }
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_ICH6_1,	asus_hides_smbus_lpc_ich6 );
-DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_ICH6_1,	asus_hides_smbus_lpc_ich6 );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_ICH6_1,	asus_hides_smbus_lpc_ich6);
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_ICH6_1,	asus_hides_smbus_lpc_ich6);
 
 /*
  * SiS 96x south bridge: BIOS typically hides SMBus device...
@@ -1119,18 +1123,18 @@
 	u8 val = 0;
 	pci_read_config_byte(dev, 0x77, &val);
 	if (val & 0x10) {
-		printk(KERN_INFO "Enabling SiS 96x SMBus.\n");
+		dev_info(&dev->dev, "Enabling SiS 96x SMBus\n");
 		pci_write_config_byte(dev, 0x77, val & ~0x10);
 	}
 }
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_961,		quirk_sis_96x_smbus );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_962,		quirk_sis_96x_smbus );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_963,		quirk_sis_96x_smbus );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_LPC,		quirk_sis_96x_smbus );
-DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_961,		quirk_sis_96x_smbus );
-DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_962,		quirk_sis_96x_smbus );
-DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_963,		quirk_sis_96x_smbus );
-DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_LPC,		quirk_sis_96x_smbus );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_961,		quirk_sis_96x_smbus);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_962,		quirk_sis_96x_smbus);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_963,		quirk_sis_96x_smbus);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_LPC,		quirk_sis_96x_smbus);
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_961,		quirk_sis_96x_smbus);
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_962,		quirk_sis_96x_smbus);
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_963,		quirk_sis_96x_smbus);
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_LPC,		quirk_sis_96x_smbus);
 
 /*
  * ... This is further complicated by the fact that some SiS96x south
@@ -1163,8 +1167,8 @@
 	dev->device = devid;
 	quirk_sis_96x_smbus(dev);
 }
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_503,		quirk_sis_503 );
-DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_503,		quirk_sis_503 );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_503,		quirk_sis_503);
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_503,		quirk_sis_503);
 
 
 /*
@@ -1191,13 +1195,13 @@
 		pci_write_config_byte(dev, 0x50, val & (~0xc0));
 		pci_read_config_byte(dev, 0x50, &val);
 		if (val & 0xc0)
-			printk(KERN_INFO "PCI: onboard AC97/MC97 devices continue to play 'hide and seek'! 0x%x\n", val);
+			dev_info(&dev->dev, "Onboard AC97/MC97 devices continue to play 'hide and seek'! 0x%x\n", val);
 		else
-			printk(KERN_INFO "PCI: enabled onboard AC97/MC97 devices\n");
+			dev_info(&dev->dev, "Enabled onboard AC97/MC97 devices\n");
 	}
 }
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_8237, asus_hides_ac97_lpc );
-DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_8237, asus_hides_ac97_lpc );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_8237, asus_hides_ac97_lpc);
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_8237, asus_hides_ac97_lpc);
 
 #if defined(CONFIG_ATA) || defined(CONFIG_ATA_MODULE)
 
@@ -1292,7 +1296,7 @@
 	}
 
 }
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_EESSC,	quirk_alder_ioapic );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_EESSC,	quirk_alder_ioapic);
 #endif
 
 int pcie_mch_quirk;
@@ -1302,9 +1306,9 @@
 {
 	pcie_mch_quirk = 1;
 }
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_E7520_MCH,	quirk_pcie_mch );
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_E7320_MCH,	quirk_pcie_mch );
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_E7525_MCH,	quirk_pcie_mch );
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_E7520_MCH,	quirk_pcie_mch);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_E7320_MCH,	quirk_pcie_mch);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_E7525_MCH,	quirk_pcie_mch);
 
 
 /*
@@ -1314,11 +1318,8 @@
 static void __devinit quirk_pcie_pxh(struct pci_dev *dev)
 {
 	pci_msi_off(dev);
-
 	dev->no_msi = 1;
-
-	printk(KERN_WARNING "PCI: PXH quirk detected, "
-		"disabling MSI for SHPC device\n");
+	dev_warn(&dev->dev, "PXH quirk detected; SHPC device MSI disabled\n");
 }
 DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_PXHD_0,	quirk_pcie_pxh);
 DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_PXHD_1,	quirk_pcie_pxh);
@@ -1399,7 +1400,7 @@
 	case PCI_DEVICE_ID_NETMOS_9855:
 		if ((dev->class >> 8) == PCI_CLASS_COMMUNICATION_SERIAL &&
 		    num_parallel) {
-			printk(KERN_INFO "PCI: Netmos %04x (%u parallel, "
+			dev_info(&dev->dev, "Netmos %04x (%u parallel, "
 				"%u serial); changing class SERIAL to OTHER "
 				"(use parport_serial)\n",
 				dev->device, num_parallel, num_serial);
@@ -1412,9 +1413,10 @@
 
 static void __devinit quirk_e100_interrupt(struct pci_dev *dev)
 {
-	u16 command;
+	u16 command, pmcsr;
 	u8 __iomem *csr;
 	u8 cmd_hi;
+	int pm;
 
 	switch (dev->device) {
 	/* PCI IDs taken from drivers/net/e100.c */
@@ -1448,18 +1450,28 @@
 	if (!(command & PCI_COMMAND_MEMORY) || !pci_resource_start(dev, 0))
 		return;
 
+	/*
+	 * Check that the device is in the D0 power state. If it's not,
+	 * there is no point to look any further.
+	 */
+	pm = pci_find_capability(dev, PCI_CAP_ID_PM);
+	if (pm) {
+		pci_read_config_word(dev, pm + PCI_PM_CTRL, &pmcsr);
+		if ((pmcsr & PCI_PM_CTRL_STATE_MASK) != PCI_D0)
+			return;
+	}
+
 	/* Convert from PCI bus to resource space.  */
 	csr = ioremap(pci_resource_start(dev, 0), 8);
 	if (!csr) {
-		printk(KERN_WARNING "PCI: Can't map %s e100 registers\n",
-			pci_name(dev));
+		dev_warn(&dev->dev, "Can't map e100 registers\n");
 		return;
 	}
 
 	cmd_hi = readb(csr + 3);
 	if (cmd_hi == 0) {
-		printk(KERN_WARNING "PCI: Firmware left %s e100 interrupts "
-			"enabled, disabling\n", pci_name(dev));
+		dev_warn(&dev->dev, "Firmware left e100 interrupts enabled; "
+			"disabling\n");
 		writeb(1, csr + 3);
 	}
 
@@ -1474,7 +1486,7 @@
 	 */
 
 	if (dev->class == PCI_CLASS_NOT_DEFINED) {
-		printk(KERN_INFO "NCR 53c810 rev 1 detected, setting PCI class.\n");
+		dev_info(&dev->dev, "NCR 53c810 rev 1 detected; setting PCI class\n");
 		dev->class = PCI_CLASS_STORAGE_SCSI;
 	}
 }
@@ -1485,7 +1497,11 @@
 	while (f < end) {
 		if ((f->vendor == dev->vendor || f->vendor == (u16) PCI_ANY_ID) &&
  		    (f->device == dev->device || f->device == (u16) PCI_ANY_ID)) {
-			pr_debug("PCI: Calling quirk %p for %s\n", f->hook, pci_name(dev));
+#ifdef DEBUG
+			dev_dbg(&dev->dev, "calling quirk 0x%p", f->hook);
+			print_fn_descriptor_symbol(": %s()\n",
+				(unsigned long) f->hook);
+#endif
 			f->hook(dev);
 		}
 		f++;
@@ -1553,7 +1569,7 @@
 	pci_read_config_word(dev, 0x40, &en1k);
 
 	if (en1k & 0x200) {
-		printk(KERN_INFO "PCI: Enable I/O Space to 1 KB Granularity\n");
+		dev_info(&dev->dev, "Enable I/O Space to 1KB granularity\n");
 
 		pci_read_config_byte(dev, PCI_IO_BASE, &io_base_lo);
 		pci_read_config_byte(dev, PCI_IO_LIMIT, &io_limit_lo);
@@ -1585,7 +1601,7 @@
 		iobl_adr_1k = iobl_adr | (res->start >> 8) | (res->end & 0xfc00);
 
 		if (iobl_adr != iobl_adr_1k) {
-			printk(KERN_INFO "PCI: Fixing P64H2 IOBL_ADR from 0x%x to 0x%x for 1 KB Granularity\n",
+			dev_info(&dev->dev, "Fixing P64H2 IOBL_ADR from 0x%x to 0x%x for 1KB granularity\n",
 				iobl_adr,iobl_adr_1k);
 			pci_write_config_word(dev, PCI_IO_BASE, iobl_adr_1k);
 		}
@@ -1603,9 +1619,8 @@
 	if (pci_read_config_byte(dev, 0xf41, &b) == 0) {
 		if (!(b & 0x20)) {
 			pci_write_config_byte(dev, 0xf41, b | 0x20);
-			printk(KERN_INFO
-			       "PCI: Linking AER extended capability on %s\n",
-			       pci_name(dev));
+			dev_info(&dev->dev,
+			       "Linking AER extended capability\n");
 		}
 	}
 }
@@ -1614,6 +1629,34 @@
 DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_NVIDIA,  PCI_DEVICE_ID_NVIDIA_CK804_PCIE,
 			quirk_nvidia_ck804_pcie_aer_ext_cap);
 
+static void __devinit quirk_via_cx700_pci_parking_caching(struct pci_dev *dev)
+{
+	/*
+	 * Disable PCI Bus Parking and PCI Master read caching on CX700
+	 * which causes unspecified timing errors with a VT6212L on the PCI
+	 * bus leading to USB2.0 packet loss. The defaults are that these
+	 * features are turned off but some BIOSes turn them on.
+	 */
+
+	uint8_t b;
+	if (pci_read_config_byte(dev, 0x76, &b) == 0) {
+		if (b & 0x40) {
+			/* Turn off PCI Bus Parking */
+			pci_write_config_byte(dev, 0x76, b ^ 0x40);
+
+			/* Turn off PCI Master read caching */
+			pci_write_config_byte(dev, 0x72, 0x0);
+			pci_write_config_byte(dev, 0x75, 0x1);
+			pci_write_config_byte(dev, 0x77, 0x0);
+
+			printk(KERN_INFO
+				"PCI: VIA CX700 PCI parking/caching fixup on %s\n",
+				pci_name(dev));
+		}
+	}
+}
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_VIA, 0x324e, quirk_via_cx700_pci_parking_caching);
+
 #ifdef CONFIG_PCI_MSI
 /* 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
@@ -1624,7 +1667,7 @@
 static void __init quirk_disable_all_msi(struct pci_dev *dev)
 {
 	pci_no_msi();
-	printk(KERN_WARNING "PCI: MSI quirk detected. MSI deactivated.\n");
+	dev_warn(&dev->dev, "MSI quirk detected; MSI disabled\n");
 }
 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_ATI, PCI_DEVICE_ID_ATI_RS400_200, quirk_disable_all_msi);
@@ -1635,9 +1678,8 @@
 static void __devinit quirk_disable_msi(struct pci_dev *dev)
 {
 	if (dev->subordinate) {
-		printk(KERN_WARNING "PCI: MSI quirk detected. "
-		       "PCI_BUS_FLAGS_NO_MSI set for %s subordinate bus.\n",
-		       pci_name(dev));
+		dev_warn(&dev->dev, "MSI quirk detected; "
+			"subordinate MSI disabled\n");
 		dev->subordinate->bus_flags |= PCI_BUS_FLAGS_NO_MSI;
 	}
 }
@@ -1656,9 +1698,9 @@
 		if (pci_read_config_byte(dev, pos + HT_MSI_FLAGS,
 					 &flags) == 0)
 		{
-			printk(KERN_INFO "PCI: Found %s HT MSI Mapping on %s\n",
+			dev_info(&dev->dev, "Found %s HT MSI Mapping\n",
 				flags & HT_MSI_FLAGS_ENABLE ?
-				"enabled" : "disabled", pci_name(dev));
+				"enabled" : "disabled");
 			return (flags & HT_MSI_FLAGS_ENABLE) != 0;
 		}
 
@@ -1672,17 +1714,40 @@
 static void __devinit quirk_msi_ht_cap(struct pci_dev *dev)
 {
 	if (dev->subordinate && !msi_ht_cap_enabled(dev)) {
-		printk(KERN_WARNING "PCI: MSI quirk detected. "
-		       "MSI disabled on chipset %s.\n",
-		       pci_name(dev));
+		dev_warn(&dev->dev, "MSI quirk detected; "
+			"subordinate MSI disabled\n");
 		dev->subordinate->bus_flags |= PCI_BUS_FLAGS_NO_MSI;
 	}
 }
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_HT2000_PCIE,
 			quirk_msi_ht_cap);
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SERVERWORKS,
-			PCI_DEVICE_ID_SERVERWORKS_HT1000_PXB,
-			quirk_msi_ht_cap);
+
+
+/*
+ *  Force enable MSI mapping capability on HT bridges
+ */
+static void __devinit quirk_msi_ht_cap_enable(struct pci_dev *dev)
+{
+	int pos, ttl = 48;
+
+	pos = pci_find_ht_capability(dev, HT_CAPTYPE_MSI_MAPPING);
+	while (pos && ttl--) {
+		u8 flags;
+
+		if (pci_read_config_byte(dev, pos + HT_MSI_FLAGS, &flags) == 0) {
+			printk(KERN_INFO "PCI: Enabling HT MSI Mapping on %s\n",
+			       pci_name(dev));
+
+			pci_write_config_byte(dev, pos + HT_MSI_FLAGS,
+					      flags | HT_MSI_FLAGS_ENABLE);
+		}
+		pos = pci_find_next_ht_capability(dev, pos,
+						  HT_CAPTYPE_MSI_MAPPING);
+	}
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SERVERWORKS,
+			 PCI_DEVICE_ID_SERVERWORKS_HT1000_PXB,
+			 quirk_msi_ht_cap_enable);
 
 /* The nVidia CK804 chipset may have 2 HT MSI mappings.
  * MSI are supported if the MSI capability set in any of these mappings.
@@ -1701,9 +1766,8 @@
 	if (!pdev)
 		return;
 	if (!msi_ht_cap_enabled(dev) && !msi_ht_cap_enabled(pdev)) {
-		printk(KERN_WARNING "PCI: MSI quirk detected. "
-		       "MSI disabled on chipset %s.\n",
-		       pci_name(dev));
+		dev_warn(&dev->dev, "MSI quirk detected; "
+			"subordinate MSI disabled\n");
 		dev->subordinate->bus_flags |= PCI_BUS_FLAGS_NO_MSI;
 	}
 	pci_dev_put(pdev);
@@ -1715,6 +1779,23 @@
 {
 	dev->dev_flags |= PCI_DEV_FLAGS_MSI_INTX_DISABLE_BUG;
 }
+static void __devinit quirk_msi_intx_disable_ati_bug(struct pci_dev *dev)
+{
+	struct pci_dev *p;
+
+	/* SB700 MSI issue will be fixed at HW level from revision A21,
+	 * we need check PCI REVISION ID of SMBus controller to get SB700
+	 * revision.
+	 */
+	p = pci_get_device(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_SBX00_SMBUS,
+			   NULL);
+	if (!p)
+		return;
+
+	if ((p->revision < 0x3B) && (p->revision >= 0x30))
+		dev->dev_flags |= PCI_DEV_FLAGS_MSI_INTX_DISABLE_BUG;
+	pci_dev_put(p);
+}
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_BROADCOM,
 			PCI_DEVICE_ID_TIGON3_5780,
 			quirk_msi_intx_disable_bug);
@@ -1735,17 +1816,15 @@
 			quirk_msi_intx_disable_bug);
 
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x4390,
-			quirk_msi_intx_disable_bug);
+			quirk_msi_intx_disable_ati_bug);
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x4391,
-			quirk_msi_intx_disable_bug);
+			quirk_msi_intx_disable_ati_bug);
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x4392,
-			quirk_msi_intx_disable_bug);
+			quirk_msi_intx_disable_ati_bug);
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x4393,
-			quirk_msi_intx_disable_bug);
+			quirk_msi_intx_disable_ati_bug);
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x4394,
-			quirk_msi_intx_disable_bug);
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x4395,
-			quirk_msi_intx_disable_bug);
+			quirk_msi_intx_disable_ati_bug);
 
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x4373,
 			quirk_msi_intx_disable_bug);
diff --git a/drivers/pci/remove.c b/drivers/pci/remove.c
index 430281b..ec4a82b 100644
--- a/drivers/pci/remove.c
+++ b/drivers/pci/remove.c
@@ -1,5 +1,6 @@
 #include <linux/pci.h>
 #include <linux/module.h>
+#include <linux/aspm.h>
 #include "pci.h"
 
 static void pci_free_resources(struct pci_dev *dev)
@@ -30,6 +31,9 @@
 		dev->global_list.next = dev->global_list.prev = NULL;
 		up_write(&pci_bus_sem);
 	}
+
+	if (dev->bus->self)
+		pcie_aspm_exit_link_state(dev);
 }
 
 static void pci_destroy_dev(struct pci_dev *dev)
@@ -74,10 +78,8 @@
 	list_del(&pci_bus->node);
 	up_write(&pci_bus_sem);
 	pci_remove_legacy_files(pci_bus);
-	class_device_remove_file(&pci_bus->class_dev,
-		&class_device_attr_cpuaffinity);
-	sysfs_remove_link(&pci_bus->class_dev.kobj, "bridge");
-	class_device_unregister(&pci_bus->class_dev);
+	device_remove_file(&pci_bus->dev, &dev_attr_cpuaffinity);
+	device_unregister(&pci_bus->dev);
 }
 EXPORT_SYMBOL(pci_remove_bus);
 
diff --git a/drivers/pci/rom.c b/drivers/pci/rom.c
index dbbcc04..a98b247 100644
--- a/drivers/pci/rom.c
+++ b/drivers/pci/rom.c
@@ -162,6 +162,7 @@
 	return rom;
 }
 
+#if 0
 /**
  * pci_map_rom_copy - map a PCI ROM to kernel space, create a copy
  * @pdev: pointer to pci device struct
@@ -196,6 +197,7 @@
 
 	return (void __iomem *)(unsigned long)res->start;
 }
+#endif  /*  0  */
 
 /**
  * pci_unmap_rom - unmap the ROM from kernel space
@@ -218,6 +220,7 @@
 		pci_disable_rom(pdev);
 }
 
+#if 0
 /**
  * pci_remove_rom - disable the ROM and remove its sysfs attribute
  * @pdev: pointer to pci device struct
@@ -236,6 +239,7 @@
 			    IORESOURCE_ROM_COPY)))
 		pci_disable_rom(pdev);
 }
+#endif  /*  0  */
 
 /**
  * pci_cleanup_rom - internal routine for freeing the ROM copy created
@@ -256,6 +260,4 @@
 }
 
 EXPORT_SYMBOL(pci_map_rom);
-EXPORT_SYMBOL(pci_map_rom_copy);
 EXPORT_SYMBOL(pci_unmap_rom);
-EXPORT_SYMBOL(pci_remove_rom);
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index 401e03c..8a7232f 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -89,8 +89,9 @@
 		 * The IO resource is allocated a range twice as large as it
 		 * would normally need.  This allows us to set both IO regs.
 		 */
-		printk("  IO window: %08lx-%08lx\n",
-			region.start, region.end);
+		printk(KERN_INFO "  IO window: 0x%08lx-0x%08lx\n",
+		       (unsigned long)region.start,
+		       (unsigned long)region.end);
 		pci_write_config_dword(bridge, PCI_CB_IO_BASE_0,
 					region.start);
 		pci_write_config_dword(bridge, PCI_CB_IO_LIMIT_0,
@@ -99,8 +100,9 @@
 
 	pcibios_resource_to_bus(bridge, &region, bus->resource[1]);
 	if (bus->resource[1]->flags & IORESOURCE_IO) {
-		printk("  IO window: %08lx-%08lx\n",
-			region.start, region.end);
+		printk(KERN_INFO "  IO window: 0x%08lx-0x%08lx\n",
+		       (unsigned long)region.start,
+		       (unsigned long)region.end);
 		pci_write_config_dword(bridge, PCI_CB_IO_BASE_1,
 					region.start);
 		pci_write_config_dword(bridge, PCI_CB_IO_LIMIT_1,
@@ -109,8 +111,9 @@
 
 	pcibios_resource_to_bus(bridge, &region, bus->resource[2]);
 	if (bus->resource[2]->flags & IORESOURCE_MEM) {
-		printk("  PREFETCH window: %08lx-%08lx\n",
-			region.start, region.end);
+		printk(KERN_INFO "  PREFETCH window: 0x%08lx-0x%08lx\n",
+		       (unsigned long)region.start,
+		       (unsigned long)region.end);
 		pci_write_config_dword(bridge, PCI_CB_MEMORY_BASE_0,
 					region.start);
 		pci_write_config_dword(bridge, PCI_CB_MEMORY_LIMIT_0,
@@ -119,8 +122,9 @@
 
 	pcibios_resource_to_bus(bridge, &region, bus->resource[3]);
 	if (bus->resource[3]->flags & IORESOURCE_MEM) {
-		printk("  MEM window: %08lx-%08lx\n",
-			region.start, region.end);
+		printk(KERN_INFO "  MEM window: 0x%08lx-0x%08lx\n",
+		       (unsigned long)region.start,
+		       (unsigned long)region.end);
 		pci_write_config_dword(bridge, PCI_CB_MEMORY_BASE_1,
 					region.start);
 		pci_write_config_dword(bridge, PCI_CB_MEMORY_LIMIT_1,
@@ -145,7 +149,7 @@
 {
 	struct pci_dev *bridge = bus->self;
 	struct pci_bus_region region;
-	u32 l, io_upper16;
+	u32 l, bu, lu, io_upper16;
 
 	DBG(KERN_INFO "PCI: Bridge: %s\n", pci_name(bridge));
 
@@ -159,7 +163,8 @@
 		/* Set up upper 16 bits of I/O base/limit. */
 		io_upper16 = (region.end & 0xffff0000) | (region.start >> 16);
 		DBG(KERN_INFO "  IO window: %04lx-%04lx\n",
-				region.start, region.end);
+		    (unsigned long)region.start,
+		    (unsigned long)region.end);
 	}
 	else {
 		/* Clear upper 16 bits of I/O base/limit. */
@@ -180,8 +185,9 @@
 	if (bus->resource[1]->flags & IORESOURCE_MEM) {
 		l = (region.start >> 16) & 0xfff0;
 		l |= region.end & 0xfff00000;
-		DBG(KERN_INFO "  MEM window: %08lx-%08lx\n",
-				region.start, region.end);
+		DBG(KERN_INFO "  MEM window: 0x%08lx-0x%08lx\n",
+		    (unsigned long)region.start,
+		    (unsigned long)region.end);
 	}
 	else {
 		l = 0x0000fff0;
@@ -195,12 +201,18 @@
 	pci_write_config_dword(bridge, PCI_PREF_LIMIT_UPPER32, 0);
 
 	/* Set up PREF base/limit. */
+	bu = lu = 0;
 	pcibios_resource_to_bus(bridge, &region, bus->resource[2]);
 	if (bus->resource[2]->flags & IORESOURCE_PREFETCH) {
 		l = (region.start >> 16) & 0xfff0;
 		l |= region.end & 0xfff00000;
-		DBG(KERN_INFO "  PREFETCH window: %08lx-%08lx\n",
-				region.start, region.end);
+#ifdef CONFIG_RESOURCES_64BIT
+		bu = region.start >> 32;
+		lu = region.end >> 32;
+#endif
+		DBG(KERN_INFO "  PREFETCH window: 0x%016llx-0x%016llx\n",
+		    (unsigned long long)region.start,
+		    (unsigned long long)region.end);
 	}
 	else {
 		l = 0x0000fff0;
@@ -208,8 +220,9 @@
 	}
 	pci_write_config_dword(bridge, PCI_PREF_MEMORY_BASE, l);
 
-	/* Clear out the upper 32 bits of PREF base. */
-	pci_write_config_dword(bridge, PCI_PREF_BASE_UPPER32, 0);
+	/* Set the upper 32 bits of PREF base & limit. */
+	pci_write_config_dword(bridge, PCI_PREF_BASE_UPPER32, bu);
+	pci_write_config_dword(bridge, PCI_PREF_LIMIT_UPPER32, lu);
 
 	pci_write_config_word(bridge, PCI_BRIDGE_CONTROL, bus->bridge_ctl);
 }
@@ -323,8 +336,8 @@
 static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, unsigned long type)
 {
 	struct pci_dev *dev;
-	unsigned long min_align, align, size;
-	unsigned long aligns[12];	/* Alignments from 1Mb to 2Gb */
+	resource_size_t min_align, align, size;
+	resource_size_t aligns[12];	/* Alignments from 1Mb to 2Gb */
 	int order, max_order;
 	struct resource *b_res = find_free_bus_resource(bus, type);
 
@@ -340,7 +353,7 @@
 		
 		for (i = 0; i < PCI_NUM_RESOURCES; i++) {
 			struct resource *r = &dev->resource[i];
-			unsigned long r_size;
+			resource_size_t r_size;
 
 			if (r->parent || (r->flags & mask) != type)
 				continue;
@@ -350,10 +363,10 @@
 			order = __ffs(align) - 20;
 			if (order > 11) {
 				printk(KERN_WARNING "PCI: region %s/%d "
-				       "too large: %llx-%llx\n",
+				       "too large: 0x%016llx-0x%016llx\n",
 					pci_name(dev), i,
-					(unsigned long long)r->start,
-					(unsigned long long)r->end);
+				       (unsigned long long)r->start,
+				       (unsigned long long)r->end);
 				r->flags = 0;
 				continue;
 			}
@@ -372,8 +385,11 @@
 	align = 0;
 	min_align = 0;
 	for (order = 0; order <= max_order; order++) {
-		unsigned long align1 = 1UL << (order + 20);
-
+#ifdef CONFIG_RESOURCES_64BIT
+		resource_size_t align1 = 1ULL << (order + 20);
+#else
+		resource_size_t align1 = 1U << (order + 20);
+#endif
 		if (!align)
 			min_align = align1;
 		else if (ALIGN(align + min_align, min_align) < align1)
diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c
index 6dfd861..4be7ccf 100644
--- a/drivers/pci/setup-res.c
+++ b/drivers/pci/setup-res.c
@@ -51,10 +51,12 @@
 
 	pcibios_resource_to_bus(dev, &region, res);
 
-	pr_debug("  got res [%llx:%llx] bus [%lx:%lx] flags %lx for "
+	pr_debug("  got res [%llx:%llx] bus [%llx:%llx] flags %lx for "
 		 "BAR %d of %s\n", (unsigned long long)res->start,
 		 (unsigned long long)res->end,
-		 region.start, region.end, res->flags, resno, pci_name(dev));
+		 (unsigned long long)region.start,
+		 (unsigned long long)region.end,
+		 (unsigned long)res->flags, resno, pci_name(dev));
 
 	new = region.start | (res->flags & PCI_REGION_FLAG_MASK);
 	if (res->flags & IORESOURCE_IO)
@@ -125,7 +127,6 @@
 
 	return err;
 }
-EXPORT_SYMBOL_GPL(pci_claim_resource);
 
 int pci_assign_resource(struct pci_dev *dev, int resno)
 {
diff --git a/drivers/pci/syscall.c b/drivers/pci/syscall.c
index 2ac050d..645d7a6 100644
--- a/drivers/pci/syscall.c
+++ b/drivers/pci/syscall.c
@@ -34,7 +34,6 @@
 	if (!dev)
 		goto error;
 
-	lock_kernel();
 	switch (len) {
 	case 1:
 		cfg_ret = pci_user_read_config_byte(dev, off, &byte);
@@ -47,10 +46,8 @@
 		break;
 	default:
 		err = -EINVAL;
-		unlock_kernel();
 		goto error;
 	};
-	unlock_kernel();
 
 	err = -EIO;
 	if (cfg_ret != PCIBIOS_SUCCESSFUL)
@@ -107,7 +104,6 @@
 	if (!dev)
 		return -ENODEV;
 
-	lock_kernel();
 	switch(len) {
 	case 1:
 		err = get_user(byte, (u8 __user *)buf);
@@ -140,7 +136,6 @@
 		err = -EINVAL;
 		break;
 	}
-	unlock_kernel();
 	pci_dev_put(dev);
 	return err;
 }
diff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c
index db8bc20..5ed0006 100644
--- a/drivers/scsi/ide-scsi.c
+++ b/drivers/scsi/ide-scsi.c
@@ -1,7 +1,6 @@
 /*
- * linux/drivers/scsi/ide-scsi.c	Version 0.9		Jul   4, 1999
- *
- * Copyright (C) 1996 - 1999 Gadi Oxman <gadio@netvision.net.il>
+ * Copyright (C) 1996-1999  Gadi Oxman <gadio@netvision.net.il>
+ * Copyright (C) 2004-2005  Bartlomiej Zolnierkiewicz
  */
 
 /*
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index 3205f74..29b4cf9 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -2296,10 +2296,9 @@
 	struct Scsi_Host *shost = pci_get_drvdata(pdev);
 	struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba;
 	struct lpfc_sli *psli = &phba->sli;
-	int bars = pci_select_bars(pdev, IORESOURCE_MEM);
 
 	dev_printk(KERN_INFO, &pdev->dev, "recovering from a slot reset.\n");
-	if (pci_enable_device_bars(pdev, bars)) {
+	if (pci_enable_device_mem(pdev)) {
 		printk(KERN_ERR "lpfc: Cannot re-enable "
 			"PCI device after reset.\n");
 		return PCI_ERS_RESULT_DISCONNECT;
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 6f129da..b72c7f1 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -2268,6 +2268,7 @@
 	spinlock_t		hardware_lock ____cacheline_aligned;
 
 	int		bars;
+	int		mem_only;
 	device_reg_t __iomem *iobase;		/* Base I/O address */
 	resource_size_t pio_address;
 #define MIN_IOBASE_LEN		0x100
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 3954ed2..8f69caf 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -1564,7 +1564,7 @@
 	char pci_info[30];
 	char fw_str[30];
 	struct scsi_host_template *sht;
-	int bars;
+	int bars, mem_only = 0;
 
 	bars = pci_select_bars(pdev, IORESOURCE_MEM | IORESOURCE_IO);
 	sht = &qla2x00_driver_template;
@@ -1575,10 +1575,16 @@
 	    pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2532) {
 		bars = pci_select_bars(pdev, IORESOURCE_MEM);
 		sht = &qla24xx_driver_template;
+		mem_only = 1;
 	}
 
-	if (pci_enable_device_bars(pdev, bars))
-		goto probe_out;
+	if (mem_only) {
+		if (pci_enable_device_mem(pdev))
+			goto probe_out;
+	} else {
+		if (pci_enable_device(pdev))
+			goto probe_out;
+	}
 
 	if (pci_find_aer_capability(pdev))
 		if (pci_enable_pcie_error_reporting(pdev))
@@ -1601,6 +1607,7 @@
 	sprintf(ha->host_str, "%s_%ld", QLA2XXX_DRIVER_NAME, ha->host_no);
 	ha->parent = NULL;
 	ha->bars = bars;
+	ha->mem_only = mem_only;
 
 	/* Set ISP-type information. */
 	qla2x00_set_isp_flags(ha);
@@ -2875,8 +2882,14 @@
 {
 	pci_ers_result_t ret = PCI_ERS_RESULT_DISCONNECT;
 	scsi_qla_host_t *ha = pci_get_drvdata(pdev);
+	int rc;
 
-	if (pci_enable_device_bars(pdev, ha->bars)) {
+	if (ha->mem_only)
+		rc = pci_enable_device_mem(pdev);
+	else
+		rc = pci_enable_device(pdev);
+
+	if (rc) {
 		qla_printk(KERN_WARNING, ha,
 		    "Can't re-enable PCI device after reset.\n");
 
diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig
index 7a64990..755823c 100644
--- a/drivers/usb/Kconfig
+++ b/drivers/usb/Kconfig
@@ -42,6 +42,10 @@
 	default y if PPC_MPC52xx
 	# MIPS:
 	default y if SOC_AU1X00
+	# SH:
+	default y if CPU_SUBTYPE_SH7720
+	default y if CPU_SUBTYPE_SH7721
+	default y if CPU_SUBTYPE_SH7763
 	# more:
 	default PCI
 
@@ -50,6 +54,7 @@
 	boolean
 	default y if PPC_83xx
 	default y if SOC_AU1200
+	default y if ARCH_IXP4XX
 	default PCI
 
 # ARM SA1111 chips have a non-PCI based "OHCI-compatible" USB host interface.
diff --git a/drivers/usb/atm/Kconfig b/drivers/usb/atm/Kconfig
index b450cba..86e6403 100644
--- a/drivers/usb/atm/Kconfig
+++ b/drivers/usb/atm/Kconfig
@@ -2,10 +2,7 @@
 # USB/ATM DSL configuration
 #
 
-menu "USB DSL modem support"
-	depends on USB
-
-config USB_ATM
+menuconfig USB_ATM
 	tristate "USB DSL modem support"
 	depends on USB && ATM
 	select CRC32
@@ -18,6 +15,8 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called usbatm.
 
+if USB_ATM
+
 config USB_SPEEDTOUCH
 	tristate "Speedtouch USB support"
 	depends on USB_ATM
@@ -70,4 +69,4 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called xusbatm.
 
-endmenu
+endif # USB_ATM
diff --git a/drivers/usb/atm/ueagle-atm.c b/drivers/usb/atm/ueagle-atm.c
index 389c5b1..c5ec1a5 100644
--- a/drivers/usb/atm/ueagle-atm.c
+++ b/drivers/usb/atm/ueagle-atm.c
@@ -999,7 +999,7 @@
 		bi.dwAddress = swab32(blockidx->PageAddress);
 
 		uea_dbg(INS_TO_USBDEV(sc),
-		       "sending block %u for DSP page %u size %u adress %x\n",
+		       "sending block %u for DSP page %u size %u address %x\n",
 		       blockno, pageno, blocksize, le32_to_cpu(blockidx->PageAddress));
 
 		/* send block info through the IDMA pipe */
@@ -1990,7 +1990,7 @@
 	return;
 
 bad2:
-	uea_err(INS_TO_USBDEV(sc), "unexpected cmv received,"
+	uea_err(INS_TO_USBDEV(sc), "unexpected cmv received, "
 			"Function : %d, Subfunction : %d\n",
 			E1_FUNCTION_TYPE(cmv->bFunction),
 			E1_FUNCTION_SUBTYPE(cmv->bFunction));
@@ -2038,7 +2038,7 @@
 	return;
 
 bad2:
-	uea_err(INS_TO_USBDEV(sc), "unexpected cmv received,"
+	uea_err(INS_TO_USBDEV(sc), "unexpected cmv received, "
 			"Function : %d, Subfunction : %d\n",
 			E4_FUNCTION_TYPE(cmv->wFunction),
 			E4_FUNCTION_SUBTYPE(cmv->wFunction));
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index 912d97a..bcc4213 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -496,10 +496,19 @@
 	   otherwise it is scheduled, and with high data rates data can get lost. */
 	tty->low_latency = 1;
 
+	if (usb_autopm_get_interface(acm->control)) {
+		mutex_unlock(&open_mutex);
+		return -EIO;
+	}
+
+	mutex_lock(&acm->mutex);
+	mutex_unlock(&open_mutex);
 	if (acm->used++) {
+		usb_autopm_put_interface(acm->control);
 		goto done;
         }
 
+
 	acm->ctrlurb->dev = acm->dev;
 	if (usb_submit_urb(acm->ctrlurb, GFP_KERNEL)) {
 		dbg("usb_submit_urb(ctrl irq) failed");
@@ -526,14 +535,15 @@
 
 done:
 err_out:
-	mutex_unlock(&open_mutex);
+	mutex_unlock(&acm->mutex);
 	return rv;
 
 full_bailout:
 	usb_kill_urb(acm->ctrlurb);
 bail_out:
+	usb_autopm_put_interface(acm->control);
 	acm->used--;
-	mutex_unlock(&open_mutex);
+	mutex_unlock(&acm->mutex);
 	return -EIO;
 }
 
@@ -570,6 +580,7 @@
 			usb_kill_urb(acm->writeurb);
 			for (i = 0; i < nr; i++)
 				usb_kill_urb(acm->ru[i].urb);
+			usb_autopm_put_interface(acm->control);
 		} else
 			acm_tty_unregister(acm);
 	}
@@ -904,7 +915,7 @@
 	}
 	
 	if (data_interface_num != call_interface_num)
-		dev_dbg(&intf->dev,"Seperate call control interface. That is not fully supported.\n");
+		dev_dbg(&intf->dev,"Separate call control interface. That is not fully supported.\n");
 
 skip_normal_probe:
 
@@ -980,6 +991,7 @@
 	spin_lock_init(&acm->throttle_lock);
 	spin_lock_init(&acm->write_lock);
 	spin_lock_init(&acm->read_lock);
+	mutex_init(&acm->mutex);
 	acm->write_ready = 1;
 	acm->rx_endpoint = usb_rcvbulkpipe(usb_dev, epread->bEndpointAddress);
 
@@ -1096,6 +1108,25 @@
 	return -ENOMEM;
 }
 
+static void stop_data_traffic(struct acm *acm)
+{
+	int i;
+
+	tasklet_disable(&acm->urb_task);
+
+	usb_kill_urb(acm->ctrlurb);
+	usb_kill_urb(acm->writeurb);
+	for (i = 0; i < acm->rx_buflimit; i++)
+		usb_kill_urb(acm->ru[i].urb);
+
+	INIT_LIST_HEAD(&acm->filled_read_bufs);
+	INIT_LIST_HEAD(&acm->spare_read_bufs);
+
+	tasklet_enable(&acm->urb_task);
+
+	cancel_work_sync(&acm->work);
+}
+
 static void acm_disconnect(struct usb_interface *intf)
 {
 	struct acm *acm = usb_get_intfdata(intf);
@@ -1123,19 +1154,7 @@
 	usb_set_intfdata(acm->control, NULL);
 	usb_set_intfdata(acm->data, NULL);
 
-	tasklet_disable(&acm->urb_task);
-
-	usb_kill_urb(acm->ctrlurb);
-	usb_kill_urb(acm->writeurb);
-	for (i = 0; i < acm->rx_buflimit; i++)
-		usb_kill_urb(acm->ru[i].urb);
-
-	INIT_LIST_HEAD(&acm->filled_read_bufs);
-	INIT_LIST_HEAD(&acm->spare_read_bufs);
-
-	tasklet_enable(&acm->urb_task);
-
-	flush_scheduled_work(); /* wait for acm_softint */
+	stop_data_traffic(acm);
 
 	acm_write_buffers_free(acm);
 	usb_buffer_free(usb_dev, acm->ctrlsize, acm->ctrl_buffer, acm->ctrl_dma);
@@ -1156,6 +1175,46 @@
 		tty_hangup(acm->tty);
 }
 
+static int acm_suspend(struct usb_interface *intf, pm_message_t message)
+{
+	struct acm *acm = usb_get_intfdata(intf);
+
+	if (acm->susp_count++)
+		return 0;
+	/*
+	we treat opened interfaces differently,
+	we must guard against open
+	*/
+	mutex_lock(&acm->mutex);
+
+	if (acm->used)
+		stop_data_traffic(acm);
+
+	mutex_unlock(&acm->mutex);
+	return 0;
+}
+
+static int acm_resume(struct usb_interface *intf)
+{
+	struct acm *acm = usb_get_intfdata(intf);
+	int rv = 0;
+
+	if (--acm->susp_count)
+		return 0;
+
+	mutex_lock(&acm->mutex);
+	if (acm->used) {
+		rv = usb_submit_urb(acm->ctrlurb, GFP_NOIO);
+		if (rv < 0)
+		goto err_out;
+
+		tasklet_schedule(&acm->urb_task);
+	}
+
+err_out:
+	mutex_unlock(&acm->mutex);
+	return rv;
+}
 /*
  * USB driver structure.
  */
@@ -1208,7 +1267,10 @@
 	.name =		"cdc_acm",
 	.probe =	acm_probe,
 	.disconnect =	acm_disconnect,
+	.suspend =	acm_suspend,
+	.resume =	acm_resume,
 	.id_table =	acm_ids,
+	.supports_autosuspend = 1,
 };
 
 /*
diff --git a/drivers/usb/class/cdc-acm.h b/drivers/usb/class/cdc-acm.h
index 09f7765..8df6a57 100644
--- a/drivers/usb/class/cdc-acm.h
+++ b/drivers/usb/class/cdc-acm.h
@@ -107,6 +107,7 @@
 	int write_used;					/* number of non-empty write buffers */
 	int write_ready;				/* write urb is not running */
 	spinlock_t write_lock;
+	struct mutex mutex;
 	struct usb_cdc_line_coding line;		/* bits, stop, parity */
 	struct work_struct work;			/* work queue entry for line discipline waking up */
 	struct tasklet_struct urb_task;                 /* rx processing */
@@ -120,6 +121,7 @@
 	unsigned char throttle;				/* throttled by tty layer */
 	unsigned char clocal;				/* termios CLOCAL */
 	unsigned int ctrl_caps;				/* control capabilities from the class specific header */
+	unsigned int susp_count;			/* number of suspended interfaces */
 };
 
 #define CDC_DATA_INTERFACE_TYPE	0x0a
diff --git a/drivers/usb/core/Kconfig b/drivers/usb/core/Kconfig
index 97b09f28..5c33cdb 100644
--- a/drivers/usb/core/Kconfig
+++ b/drivers/usb/core/Kconfig
@@ -9,6 +9,21 @@
 	  of debug messages to the system log. Select this if you are having a
 	  problem with USB support and want to see more of what is going on.
 
+config USB_ANNOUNCE_NEW_DEVICES
+	bool "USB announce new devices"
+	depends on USB
+	default N
+	help
+	  Say Y here if you want the USB core to always announce the
+	  idVendor, idProduct, Manufacturer, Product, and SerialNumber
+	  strings for every new USB device to the syslog.  This option is
+	  usually used by distro vendors to help with debugging and to
+	  let users know what specific device was added to the machine
+	  in what location.
+
+	  If you do not want this kind of information sent to the system
+	  log, or have any doubts about this, say N here.
+
 comment "Miscellaneous USB options"
 	depends on USB
 
diff --git a/drivers/usb/core/buffer.c b/drivers/usb/core/buffer.c
index 28d4972..cadb2dc 100644
--- a/drivers/usb/core/buffer.c
+++ b/drivers/usb/core/buffer.c
@@ -53,11 +53,13 @@
 	char		name[16];
 	int 		i, size;
 
-	if (!hcd->self.controller->dma_mask)
+	if (!hcd->self.controller->dma_mask &&
+	    !(hcd->driver->flags & HCD_LOCAL_MEM))
 		return 0;
 
-	for (i = 0; i < HCD_BUFFER_POOLS; i++) { 
-		if (!(size = pool_max [i]))
+	for (i = 0; i < HCD_BUFFER_POOLS; i++) {
+		size = pool_max[i];
+		if (!size)
 			continue;
 		snprintf(name, sizeof name, "buffer-%d", size);
 		hcd->pool[i] = dma_pool_create(name, hcd->self.controller,
@@ -80,10 +82,10 @@
  */
 void hcd_buffer_destroy(struct usb_hcd *hcd)
 {
-	int		i;
+	int i;
 
-	for (i = 0; i < HCD_BUFFER_POOLS; i++) { 
-		struct dma_pool		*pool = hcd->pool[i];
+	for (i = 0; i < HCD_BUFFER_POOLS; i++) {
+		struct dma_pool *pool = hcd->pool[i];
 		if (pool) {
 			dma_pool_destroy(pool);
 			hcd->pool[i] = NULL;
@@ -107,7 +109,8 @@
 	int 			i;
 
 	/* some USB hosts just use PIO */
-	if (!bus->controller->dma_mask) {
+	if (!bus->controller->dma_mask &&
+	    !(hcd->driver->flags & HCD_LOCAL_MEM)) {
 		*dma = ~(dma_addr_t) 0;
 		return kmalloc(size, mem_flags);
 	}
@@ -132,7 +135,8 @@
 	if (!addr)
 		return;
 
-	if (!bus->controller->dma_mask) {
+	if (!bus->controller->dma_mask &&
+	    !(hcd->driver->flags & HCD_LOCAL_MEM)) {
 		kfree(addr);
 		return;
 	}
diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c
index 1a8edce..a92122a 100644
--- a/drivers/usb/core/config.c
+++ b/drivers/usb/core/config.c
@@ -238,7 +238,7 @@
 
 	/* Allocate space for the right(?) number of endpoints */
 	num_ep = num_ep_orig = alt->desc.bNumEndpoints;
-	alt->desc.bNumEndpoints = 0;		// Use as a counter
+	alt->desc.bNumEndpoints = 0;		/* Use as a counter */
 	if (num_ep > USB_MAXENDPOINTS) {
 		dev_warn(ddev, "too many endpoints for config %d interface %d "
 		    "altsetting %d: %d, using maximum allowed: %d\n",
@@ -246,7 +246,8 @@
 		num_ep = USB_MAXENDPOINTS;
 	}
 
-	if (num_ep > 0) {	/* Can't allocate 0 bytes */
+	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)
@@ -475,8 +476,9 @@
 	return 0;
 }
 
-// hub-only!! ... and only exported for reset/reinit path.
-// otherwise used internally on disconnect/destroy path
+/* hub-only!! ... and only exported for reset/reinit path.
+ * otherwise used internally on disconnect/destroy path
+ */
 void usb_destroy_configuration(struct usb_device *dev)
 {
 	int c, i;
@@ -498,7 +500,7 @@
 		kfree(cf->string);
 		for (i = 0; i < cf->desc.bNumInterfaces; i++) {
 			if (cf->intf_cache[i])
-				kref_put(&cf->intf_cache[i]->ref, 
+				kref_put(&cf->intf_cache[i]->ref,
 					  usb_release_interface_cache);
 		}
 	}
@@ -525,7 +527,7 @@
 	unsigned int cfgno, length;
 	unsigned char *buffer;
 	unsigned char *bigbuffer;
- 	struct usb_config_descriptor *desc;
+	struct usb_config_descriptor *desc;
 
 	cfgno = 0;
 	if (dev->authorized == 0)	/* Not really an error */
diff --git a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c
index 87c794d6..83d9dc3 100644
--- a/drivers/usb/core/devices.c
+++ b/drivers/usb/core/devices.c
@@ -89,7 +89,7 @@
 static const char *format_bandwidth =
 /* B:  Alloc=ddd/ddd us (xx%), #Int=ddd, #Iso=ddd */
   "B:  Alloc=%3d/%3d us (%2d%%), #Int=%3d, #Iso=%3d\n";
-  
+
 static const char *format_device1 =
 /* D:  Ver=xx.xx Cls=xx(sssss) Sub=xx Prot=xx MxPS=dd #Cfgs=dd */
   "D:  Ver=%2x.%02x Cls=%02x(%-5s) Sub=%02x Prot=%02x MxPS=%2d #Cfgs=%3d\n";
@@ -101,7 +101,7 @@
 static const char *format_config =
 /* 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";
@@ -122,7 +122,7 @@
  */
 
 static DECLARE_WAIT_QUEUE_HEAD(deviceconndiscwq);
-static unsigned int conndiscevcnt = 0;
+static unsigned int conndiscevcnt;
 
 /* this struct stores the poll state for <mountpoint>/devices pollers */
 struct usb_device_status {
@@ -172,12 +172,8 @@
 	return clas_info[ix].class_name;
 }
 
-static char *usb_dump_endpoint_descriptor(
-	int speed,
-	char *start,
-	char *end,
-	const struct usb_endpoint_descriptor *desc
-)
+static char *usb_dump_endpoint_descriptor(int speed, char *start, char *end,
+				const struct usb_endpoint_descriptor *desc)
 {
 	char dir, unit, *type;
 	unsigned interval, bandwidth = 1;
@@ -235,22 +231,24 @@
 
 	start += sprintf(start, format_endpt, desc->bEndpointAddress, dir,
 			 desc->bmAttributes, type,
-			 (le16_to_cpu(desc->wMaxPacketSize) & 0x07ff) * bandwidth,
+			 (le16_to_cpu(desc->wMaxPacketSize) & 0x07ff) *
+			 bandwidth,
 			 interval, unit);
 	return start;
 }
 
 static char *usb_dump_interface_descriptor(char *start, char *end,
-	const struct usb_interface_cache *intfc,
-	const struct usb_interface *iface,
-	int setno)
+					const struct usb_interface_cache *intfc,
+					const struct usb_interface *iface,
+					int setno)
 {
-	const struct usb_interface_descriptor *desc = &intfc->altsetting[setno].desc;
+	const struct usb_interface_descriptor *desc;
 	const char *driver_name = "";
 	int active = 0;
 
 	if (start > end)
 		return start;
+	desc = &intfc->altsetting[setno].desc;
 	if (iface) {
 		driver_name = (iface->dev.driver
 				? iface->dev.driver->name
@@ -270,14 +268,10 @@
 	return start;
 }
 
-static char *usb_dump_interface(
-	int speed,
-	char *start,
-	char *end,
-	const struct usb_interface_cache *intfc,
-	const struct usb_interface *iface,
-	int setno
-) {
+static char *usb_dump_interface(int speed, char *start, char *end,
+				const struct usb_interface_cache *intfc,
+				const struct usb_interface *iface, int setno)
+{
 	const struct usb_host_interface *desc = &intfc->altsetting[setno];
 	int i;
 
@@ -292,7 +286,7 @@
 }
 
 static char *usb_dump_iad_descriptor(char *start, char *end,
-	const struct usb_interface_assoc_descriptor *iad)
+			const struct usb_interface_assoc_descriptor *iad)
 {
 	if (start > end)
 		return start;
@@ -311,13 +305,15 @@
  * 1. marking active interface altsettings (code lists all, but should mark
  *    which ones are active, if any)
  */
-
-static char *usb_dump_config_descriptor(char *start, char *end, const struct usb_config_descriptor *desc, int active)
+static char *usb_dump_config_descriptor(char *start, char *end,
+				const struct usb_config_descriptor *desc,
+				int active)
 {
 	if (start > end)
 		return start;
 	start += sprintf(start, format_config,
-			 active ? '*' : ' ',	/* mark active/actual/current cfg. */
+			 /* mark active/actual/current cfg. */
+			 active ? '*' : ' ',
 			 desc->bNumInterfaces,
 			 desc->bConfigurationValue,
 			 desc->bmAttributes,
@@ -325,13 +321,8 @@
 	return start;
 }
 
-static char *usb_dump_config (
-	int speed,
-	char *start,
-	char *end,
-	const struct usb_host_config *config,
-	int active
-)
+static char *usb_dump_config(int speed, char *start, char *end,
+			     const struct usb_host_config *config, int active)
 {
 	int i, j;
 	struct usb_interface_cache *intfc;
@@ -339,7 +330,8 @@
 
 	if (start > end)
 		return start;
-	if (!config)		/* getting these some in 2.3.7; none in 2.3.6 */
+	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++) {
@@ -364,7 +356,8 @@
 /*
  * Dump the different USB descriptors.
  */
-static char *usb_dump_device_descriptor(char *start, char *end, const struct usb_device_descriptor *desc)
+static char *usb_dump_device_descriptor(char *start, char *end,
+				const struct usb_device_descriptor *desc)
 {
 	u16 bcdUSB = le16_to_cpu(desc->bcdUSB);
 	u16 bcdDevice = le16_to_cpu(desc->bcdDevice);
@@ -374,7 +367,7 @@
 	start += sprintf(start, format_device1,
 			  bcdUSB >> 8, bcdUSB & 0xff,
 			  desc->bDeviceClass,
-			  class_decode (desc->bDeviceClass),
+			  class_decode(desc->bDeviceClass),
 			  desc->bDeviceSubClass,
 			  desc->bDeviceProtocol,
 			  desc->bMaxPacketSize0,
@@ -391,12 +384,14 @@
 /*
  * Dump the different strings that this device holds.
  */
-static char *usb_dump_device_strings(char *start, char *end, struct usb_device *dev)
+static char *usb_dump_device_strings(char *start, char *end,
+				     struct usb_device *dev)
 {
 	if (start > end)
 		return start;
 	if (dev->manufacturer)
-		start += sprintf(start, format_string_manufacturer, dev->manufacturer);
+		start += sprintf(start, format_string_manufacturer,
+				 dev->manufacturer);
 	if (start > end)
 		goto out;
 	if (dev->product)
@@ -405,7 +400,8 @@
 		goto out;
 #ifdef ALLOW_SERIAL_NUMBER
 	if (dev->serial)
-		start += sprintf(start, format_string_serialnumber, dev->serial);
+		start += sprintf(start, format_string_serialnumber,
+				 dev->serial);
 #endif
  out:
 	return start;
@@ -417,12 +413,12 @@
 
 	if (start > end)
 		return start;
-		
+
 	start = usb_dump_device_descriptor(start, end, &dev->descriptor);
 
 	if (start > end)
 		return start;
-	
+
 	start = usb_dump_device_strings(start, end, dev);
 
 	for (i = 0; i < dev->descriptor.bNumConfigurations; i++) {
@@ -439,7 +435,8 @@
 
 #ifdef PROC_EXTRA /* TBD: may want to add this code later */
 
-static char *usb_dump_hub_descriptor(char *start, char *end, const struct usb_hub_descriptor * desc)
+static char *usb_dump_hub_descriptor(char *start, char *end,
+				     const struct usb_hub_descriptor *desc)
 {
 	int leng = USB_DT_HUB_NONVAR_SIZE;
 	unsigned char *ptr = (unsigned char *)desc;
@@ -455,13 +452,16 @@
 	return start;
 }
 
-static char *usb_dump_string(char *start, char *end, const struct usb_device *dev, char *id, int index)
+static char *usb_dump_string(char *start, char *end,
+			     const struct usb_device *dev, char *id, int index)
 {
 	if (start > end)
 		return start;
 	start += sprintf(start, "Interface:");
-	if (index <= dev->maxstring && dev->stringindex && dev->stringindex[index])
-		start += sprintf(start, "%s: %.100s ", id, dev->stringindex[index]);
+	if (index <= dev->maxstring && dev->stringindex &&
+	    dev->stringindex[index])
+		start += sprintf(start, "%s: %.100s ", id,
+				 dev->stringindex[index]);
 	return start;
 }
 
@@ -476,8 +476,10 @@
  * file_offset - the offset into the devices file on completion
  * The caller must own the device lock.
  */
-static ssize_t usb_device_dump(char __user **buffer, size_t *nbytes, loff_t *skip_bytes, loff_t *file_offset,
-				struct usb_device *usbdev, struct usb_bus *bus, int level, int index, int count)
+static ssize_t usb_device_dump(char __user **buffer, size_t *nbytes,
+			       loff_t *skip_bytes, loff_t *file_offset,
+			       struct usb_device *usbdev, struct usb_bus *bus,
+			       int level, int index, int count)
 {
 	int chix;
 	int ret, cnt = 0;
@@ -485,17 +487,19 @@
 	char *pages_start, *data_end, *speed;
 	unsigned int length;
 	ssize_t total_written = 0;
-	
+
 	/* don't bother with anything else if we're not writing any data */
 	if (*nbytes <= 0)
 		return 0;
-	
+
 	if (level > MAX_TOPO_LEVEL)
 		return 0;
-	/* allocate 2^1 pages = 8K (on i386); should be more than enough for one device */
-        if (!(pages_start = (char*) __get_free_pages(GFP_KERNEL,1)))
-                return -ENOMEM;
-		
+	/* allocate 2^1 pages = 8K (on i386);
+	 * should be more than enough for one device */
+	pages_start = (char *)__get_free_pages(GFP_KERNEL, 1);
+	if (!pages_start)
+		return -ENOMEM;
+
 	if (usbdev->parent && usbdev->parent->devnum != -1)
 		parent_devnum = usbdev->parent->devnum;
 	/*
@@ -541,15 +545,16 @@
 				bus->bandwidth_allocated, max,
 				(100 * bus->bandwidth_allocated + max / 2)
 					/ max,
-			         bus->bandwidth_int_reqs,
-				 bus->bandwidth_isoc_reqs);
-	
+				bus->bandwidth_int_reqs,
+				bus->bandwidth_isoc_reqs);
+
 	}
-	data_end = usb_dump_desc(data_end, pages_start + (2 * PAGE_SIZE) - 256, usbdev);
-	
+	data_end = usb_dump_desc(data_end, pages_start + (2 * PAGE_SIZE) - 256,
+				 usbdev);
+
 	if (data_end > (pages_start + (2 * PAGE_SIZE) - 256))
 		data_end += sprintf(data_end, "(truncated)\n");
-	
+
 	length = data_end - pages_start;
 	/* if we can start copying some data to the user */
 	if (length > *skip_bytes) {
@@ -567,17 +572,18 @@
 		*skip_bytes = 0;
 	} else
 		*skip_bytes -= length;
-	
+
 	free_pages((unsigned long)pages_start, 1);
-	
+
 	/* Now look at all of this device's children. */
 	for (chix = 0; chix < usbdev->maxchild; chix++) {
 		struct usb_device *childdev = usbdev->children[chix];
 
 		if (childdev) {
 			usb_lock_device(childdev);
-			ret = usb_device_dump(buffer, nbytes, skip_bytes, file_offset, childdev,
-					bus, level + 1, chix, ++cnt);
+			ret = usb_device_dump(buffer, nbytes, skip_bytes,
+					      file_offset, childdev, bus,
+					      level + 1, chix, ++cnt);
 			usb_unlock_device(childdev);
 			if (ret == -EFAULT)
 				return total_written;
@@ -587,7 +593,8 @@
 	return total_written;
 }
 
-static ssize_t usb_device_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
+static ssize_t usb_device_read(struct file *file, char __user *buf,
+			       size_t nbytes, loff_t *ppos)
 {
 	struct usb_bus *bus;
 	ssize_t ret, total_written = 0;
@@ -607,7 +614,8 @@
 		if (!bus->root_hub)
 			continue;
 		usb_lock_device(bus->root_hub);
-		ret = usb_device_dump(&buf, &nbytes, &skip_bytes, ppos, bus->root_hub, bus, 0, 0, 0);
+		ret = usb_device_dump(&buf, &nbytes, &skip_bytes, ppos,
+				      bus->root_hub, bus, 0, 0, 0);
 		usb_unlock_device(bus->root_hub);
 		if (ret < 0) {
 			mutex_unlock(&usb_bus_list_lock);
@@ -620,7 +628,8 @@
 }
 
 /* Kernel lock for "lastev" protection */
-static unsigned int usb_device_poll(struct file *file, struct poll_table_struct *wait)
+static unsigned int usb_device_poll(struct file *file,
+				    struct poll_table_struct *wait)
 {
 	struct usb_device_status *st = file->private_data;
 	unsigned int mask = 0;
@@ -629,7 +638,8 @@
 	if (!st) {
 		st = kmalloc(sizeof(struct usb_device_status), GFP_KERNEL);
 
-		/* we may have dropped BKL - need to check for having lost the race */
+		/* we may have dropped BKL -
+		 * need to check for having lost the race */
 		if (file->private_data) {
 			kfree(st);
 			st = file->private_data;
@@ -652,7 +662,7 @@
 	}
 lost_race:
 	if (file->f_mode & FMODE_READ)
-                poll_wait(file, &deviceconndiscwq, wait);
+		poll_wait(file, &deviceconndiscwq, wait);
 	if (st->lastev != conndiscevcnt)
 		mask |= POLLIN;
 	st->lastev = conndiscevcnt;
@@ -662,18 +672,18 @@
 
 static int usb_device_open(struct inode *inode, struct file *file)
 {
-        file->private_data = NULL;
-        return 0;
+	file->private_data = NULL;
+	return 0;
 }
 
 static int usb_device_release(struct inode *inode, struct file *file)
 {
 	kfree(file->private_data);
 	file->private_data = NULL;
-        return 0;
+	return 0;
 }
 
-static loff_t usb_device_lseek(struct file * file, loff_t offset, int orig)
+static loff_t usb_device_lseek(struct file *file, loff_t offset, int orig)
 {
 	loff_t ret;
 
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
index 1f4f6d0..ae94176 100644
--- a/drivers/usb/core/devio.c
+++ b/drivers/usb/core/devio.c
@@ -75,14 +75,14 @@
 	u32 secid;
 };
 
-static int usbfs_snoop = 0;
-module_param (usbfs_snoop, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC (usbfs_snoop, "true to log all usbfs traffic");
+static int usbfs_snoop;
+module_param(usbfs_snoop, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(usbfs_snoop, "true to log all usbfs traffic");
 
 #define snoop(dev, format, arg...)				\
 	do {							\
 		if (usbfs_snoop)				\
-			dev_info( dev , format , ## arg);	\
+			dev_info(dev , format , ## arg);	\
 	} while (0)
 
 #define USB_DEVICE_DEV		MKDEV(USB_DEVICE_MAJOR, 0)
@@ -90,7 +90,7 @@
 
 #define	MAX_USBFS_BUFFER_SIZE	16384
 
-static inline int connected (struct dev_state *ps)
+static inline int connected(struct dev_state *ps)
 {
 	return (!list_empty(&ps->list) &&
 			ps->dev->state != USB_STATE_NOTATTACHED);
@@ -120,7 +120,8 @@
 	return ret;
 }
 
-static ssize_t usbdev_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
+static ssize_t usbdev_read(struct file *file, char __user *buf, size_t nbytes,
+			   loff_t *ppos)
 {
 	struct dev_state *ps = file->private_data;
 	struct usb_device *dev = ps->dev;
@@ -140,7 +141,8 @@
 	}
 
 	if (pos < sizeof(struct usb_device_descriptor)) {
-		struct usb_device_descriptor temp_desc ; /* 18 bytes - fits on the stack */
+		/* 18 bytes - fits on the stack */
+		struct usb_device_descriptor temp_desc;
 
 		memcpy(&temp_desc, &dev->descriptor, sizeof(dev->descriptor));
 		le16_to_cpus(&temp_desc.bcdUSB);
@@ -210,17 +212,17 @@
 
 static struct async *alloc_async(unsigned int numisoframes)
 {
-        unsigned int assize = sizeof(struct async) + numisoframes * sizeof(struct usb_iso_packet_descriptor);
-        struct async *as = kzalloc(assize, GFP_KERNEL);
+	struct async *as;
 
-        if (!as)
-                return NULL;
+	as = kzalloc(sizeof(struct async), GFP_KERNEL);
+	if (!as)
+		return NULL;
 	as->urb = usb_alloc_urb(numisoframes, GFP_KERNEL);
 	if (!as->urb) {
 		kfree(as);
 		return NULL;
 	}
-        return as;
+	return as;
 }
 
 static void free_async(struct async *as)
@@ -234,52 +236,54 @@
 
 static inline void async_newpending(struct async *as)
 {
-        struct dev_state *ps = as->ps;
-        unsigned long flags;
-        
-        spin_lock_irqsave(&ps->lock, flags);
-        list_add_tail(&as->asynclist, &ps->async_pending);
-        spin_unlock_irqrestore(&ps->lock, flags);
+	struct dev_state *ps = as->ps;
+	unsigned long flags;
+
+	spin_lock_irqsave(&ps->lock, flags);
+	list_add_tail(&as->asynclist, &ps->async_pending);
+	spin_unlock_irqrestore(&ps->lock, flags);
 }
 
 static inline void async_removepending(struct async *as)
 {
-        struct dev_state *ps = as->ps;
-        unsigned long flags;
-        
-        spin_lock_irqsave(&ps->lock, flags);
-        list_del_init(&as->asynclist);
-        spin_unlock_irqrestore(&ps->lock, flags);
+	struct dev_state *ps = as->ps;
+	unsigned long flags;
+
+	spin_lock_irqsave(&ps->lock, flags);
+	list_del_init(&as->asynclist);
+	spin_unlock_irqrestore(&ps->lock, flags);
 }
 
 static inline struct async *async_getcompleted(struct dev_state *ps)
 {
-        unsigned long flags;
-        struct async *as = NULL;
+	unsigned long flags;
+	struct async *as = NULL;
 
-        spin_lock_irqsave(&ps->lock, flags);
-        if (!list_empty(&ps->async_completed)) {
-                as = list_entry(ps->async_completed.next, struct async, asynclist);
-                list_del_init(&as->asynclist);
-        }
-        spin_unlock_irqrestore(&ps->lock, flags);
-        return as;
+	spin_lock_irqsave(&ps->lock, flags);
+	if (!list_empty(&ps->async_completed)) {
+		as = list_entry(ps->async_completed.next, struct async,
+				asynclist);
+		list_del_init(&as->asynclist);
+	}
+	spin_unlock_irqrestore(&ps->lock, flags);
+	return as;
 }
 
-static inline struct async *async_getpending(struct dev_state *ps, void __user *userurb)
+static inline struct async *async_getpending(struct dev_state *ps,
+					     void __user *userurb)
 {
-        unsigned long flags;
-        struct async *as;
+	unsigned long flags;
+	struct async *as;
 
-        spin_lock_irqsave(&ps->lock, flags);
+	spin_lock_irqsave(&ps->lock, flags);
 	list_for_each_entry(as, &ps->async_pending, asynclist)
 		if (as->userurb == userurb) {
 			list_del_init(&as->asynclist);
 			spin_unlock_irqrestore(&ps->lock, flags);
 			return as;
 		}
-        spin_unlock_irqrestore(&ps->lock, flags);
-        return NULL;
+	spin_unlock_irqrestore(&ps->lock, flags);
+	return NULL;
 }
 
 static void snoop_urb(struct urb *urb, void __user *userurb)
@@ -298,19 +302,19 @@
 	dev_info(&urb->dev->dev, "actual_length=%d\n", urb->actual_length);
 	dev_info(&urb->dev->dev, "data: ");
 	for (j = 0; j < urb->transfer_buffer_length; ++j)
-		printk ("%02x ", data[j]);
+		printk("%02x ", data[j]);
 	printk("\n");
 }
 
 static void async_completed(struct urb *urb)
 {
-        struct async *as = urb->context;
-        struct dev_state *ps = as->ps;
+	struct async *as = urb->context;
+	struct dev_state *ps = as->ps;
 	struct siginfo sinfo;
 
-        spin_lock(&ps->lock);
-        list_move_tail(&as->asynclist, &ps->async_completed);
-        spin_unlock(&ps->lock);
+	spin_lock(&ps->lock);
+	list_move_tail(&as->asynclist, &ps->async_completed);
+	spin_unlock(&ps->lock);
 	as->status = urb->status;
 	if (as->signr) {
 		sinfo.si_signo = as->signr;
@@ -325,7 +329,7 @@
 	wake_up(&ps->wait);
 }
 
-static void destroy_async (struct dev_state *ps, struct list_head *list)
+static void destroy_async(struct dev_state *ps, struct list_head *list)
 {
 	struct async *as;
 	unsigned long flags;
@@ -348,7 +352,8 @@
 	}
 }
 
-static void destroy_async_on_interface (struct dev_state *ps, unsigned int ifnum)
+static void destroy_async_on_interface(struct dev_state *ps,
+				       unsigned int ifnum)
 {
 	struct list_head *p, *q, hitlist;
 	unsigned long flags;
@@ -364,7 +369,7 @@
 
 static inline void destroy_all_async(struct dev_state *ps)
 {
-	        destroy_async(ps, &ps->async_pending);
+	destroy_async(ps, &ps->async_pending);
 }
 
 /*
@@ -373,15 +378,15 @@
  * they're also undone when devices disconnect.
  */
 
-static int driver_probe (struct usb_interface *intf,
-			 const struct usb_device_id *id)
+static int driver_probe(struct usb_interface *intf,
+			const struct usb_device_id *id)
 {
 	return -ENODEV;
 }
 
 static void driver_disconnect(struct usb_interface *intf)
 {
-	struct dev_state *ps = usb_get_intfdata (intf);
+	struct dev_state *ps = usb_get_intfdata(intf);
 	unsigned int ifnum = intf->altsetting->desc.bInterfaceNumber;
 
 	if (!ps)
@@ -396,16 +401,31 @@
 	else
 		warn("interface number %u out of range", ifnum);
 
-	usb_set_intfdata (intf, NULL);
+	usb_set_intfdata(intf, NULL);
 
 	/* force async requests to complete */
 	destroy_async_on_interface(ps, ifnum);
 }
 
+/* The following routines are merely placeholders.  There is no way
+ * to inform a user task about suspend or resumes.
+ */
+static int driver_suspend(struct usb_interface *intf, pm_message_t msg)
+{
+	return 0;
+}
+
+static int driver_resume(struct usb_interface *intf)
+{
+	return 0;
+}
+
 struct usb_driver usbfs_driver = {
 	.name =		"usbfs",
 	.probe =	driver_probe,
 	.disconnect =	driver_disconnect,
+	.suspend =	driver_suspend,
+	.resume =	driver_resume,
 };
 
 static int claimintf(struct dev_state *ps, unsigned int ifnum)
@@ -459,15 +479,16 @@
 	if (test_bit(ifnum, &ps->ifclaimed))
 		return 0;
 	/* if not yet claimed, claim it for the driver */
-	dev_warn(&ps->dev->dev, "usbfs: process %d (%s) did not claim interface %u before use\n",
-	       task_pid_nr(current), current->comm, ifnum);
+	dev_warn(&ps->dev->dev, "usbfs: process %d (%s) did not claim "
+		 "interface %u before use\n", task_pid_nr(current),
+		 current->comm, ifnum);
 	return claimintf(ps, ifnum);
 }
 
 static int findintfep(struct usb_device *dev, unsigned int ep)
 {
 	unsigned int i, j, e;
-        struct usb_interface *intf;
+	struct usb_interface *intf;
 	struct usb_host_interface *alts;
 	struct usb_endpoint_descriptor *endpt;
 
@@ -478,7 +499,7 @@
 	for (i = 0; i < dev->actconfig->desc.bNumInterfaces; i++) {
 		intf = dev->actconfig->interface[i];
 		for (j = 0; j < intf->num_altsetting; j++) {
-                        alts = &intf->altsetting[j];
+			alts = &intf->altsetting[j];
 			for (e = 0; e < alts->desc.bNumEndpoints; e++) {
 				endpt = &alts->endpoint[e].desc;
 				if (endpt->bEndpointAddress == ep)
@@ -486,10 +507,11 @@
 			}
 		}
 	}
-	return -ENOENT; 
+	return -ENOENT;
 }
 
-static int check_ctrlrecip(struct dev_state *ps, unsigned int requesttype, unsigned int index)
+static int check_ctrlrecip(struct dev_state *ps, unsigned int requesttype,
+			   unsigned int index)
 {
 	int ret = 0;
 
@@ -502,7 +524,8 @@
 	index &= 0xff;
 	switch (requesttype & USB_RECIP_MASK) {
 	case USB_RECIP_ENDPOINT:
-		if ((ret = findintfep(ps->dev, index)) >= 0)
+		ret = findintfep(ps->dev, index);
+		if (ret >= 0)
 			ret = checkintf(ps, ret);
 		break;
 
@@ -546,7 +569,8 @@
 	mutex_lock(&usbfs_mutex);
 
 	ret = -ENOMEM;
-	if (!(ps = kmalloc(sizeof(struct dev_state), GFP_KERNEL)))
+	ps = kmalloc(sizeof(struct dev_state), GFP_KERNEL);
+	if (!ps)
 		goto out;
 
 	ret = -ENOENT;
@@ -627,15 +651,18 @@
 
 	if (copy_from_user(&ctrl, arg, sizeof(ctrl)))
 		return -EFAULT;
-	if ((ret = check_ctrlrecip(ps, ctrl.bRequestType, ctrl.wIndex)))
+	ret = check_ctrlrecip(ps, ctrl.bRequestType, ctrl.wIndex);
+	if (ret)
 		return ret;
 	if (ctrl.wLength > PAGE_SIZE)
 		return -EINVAL;
-	if (!(tbuf = (unsigned char *)__get_free_page(GFP_KERNEL)))
+	tbuf = (unsigned char *)__get_free_page(GFP_KERNEL);
+	if (!tbuf)
 		return -ENOMEM;
 	tmo = ctrl.timeout;
 	if (ctrl.bRequestType & 0x80) {
-		if (ctrl.wLength && !access_ok(VERIFY_WRITE, ctrl.data, ctrl.wLength)) {
+		if (ctrl.wLength && !access_ok(VERIFY_WRITE, ctrl.data,
+					       ctrl.wLength)) {
 			free_page((unsigned long)tbuf);
 			return -EINVAL;
 		}
@@ -646,14 +673,15 @@
 				ctrl.wIndex, ctrl.wLength);
 
 		usb_unlock_device(dev);
-		i = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), ctrl.bRequest, ctrl.bRequestType,
-				       ctrl.wValue, ctrl.wIndex, tbuf, ctrl.wLength, tmo);
+		i = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), ctrl.bRequest,
+				    ctrl.bRequestType, ctrl.wValue, ctrl.wIndex,
+				    tbuf, ctrl.wLength, tmo);
 		usb_lock_device(dev);
 		if ((i > 0) && ctrl.wLength) {
 			if (usbfs_snoop) {
 				dev_info(&dev->dev, "control read: data ");
 				for (j = 0; j < i; ++j)
-					printk("%02x ", (unsigned char)(tbuf)[j]);
+					printk("%02x ", (u8)(tbuf)[j]);
 				printk("\n");
 			}
 			if (copy_to_user(ctrl.data, tbuf, i)) {
@@ -680,12 +708,13 @@
 			printk("\n");
 		}
 		usb_unlock_device(dev);
-		i = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), ctrl.bRequest, ctrl.bRequestType,
-				       ctrl.wValue, ctrl.wIndex, tbuf, ctrl.wLength, tmo);
+		i = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), ctrl.bRequest,
+				    ctrl.bRequestType, ctrl.wValue, ctrl.wIndex,
+				    tbuf, ctrl.wLength, tmo);
 		usb_lock_device(dev);
 	}
 	free_page((unsigned long)tbuf);
-	if (i<0 && i != -EPIPE) {
+	if (i < 0 && i != -EPIPE) {
 		dev_printk(KERN_DEBUG, &dev->dev, "usbfs: USBDEVFS_CONTROL "
 			   "failed cmd %s rqt %u rq %u len %u ret %d\n",
 			   current->comm, ctrl.bRequestType, ctrl.bRequest,
@@ -705,9 +734,11 @@
 
 	if (copy_from_user(&bulk, arg, sizeof(bulk)))
 		return -EFAULT;
-	if ((ret = findintfep(ps->dev, bulk.ep)) < 0)
+	ret = findintfep(ps->dev, bulk.ep);
+	if (ret < 0)
 		return ret;
-	if ((ret = checkintf(ps, ret)))
+	ret = checkintf(ps, ret);
+	if (ret)
 		return ret;
 	if (bulk.ep & USB_DIR_IN)
 		pipe = usb_rcvbulkpipe(dev, bulk.ep & 0x7f);
@@ -735,7 +766,7 @@
 			if (usbfs_snoop) {
 				dev_info(&dev->dev, "bulk read: data ");
 				for (j = 0; j < len2; ++j)
-					printk("%02x ", (unsigned char)(tbuf)[j]);
+					printk("%02x ", (u8)(tbuf)[j]);
 				printk("\n");
 			}
 			if (copy_to_user(bulk.data, tbuf, len2)) {
@@ -775,9 +806,11 @@
 
 	if (get_user(ep, (unsigned int __user *)arg))
 		return -EFAULT;
-	if ((ret = findintfep(ps->dev, ep)) < 0)
+	ret = findintfep(ps->dev, ep);
+	if (ret < 0)
 		return ret;
-	if ((ret = checkintf(ps, ret)))
+	ret = checkintf(ps, ret);
+	if (ret)
 		return ret;
 	usb_settoggle(ps->dev, ep & 0xf, !(ep & USB_DIR_IN), 0);
 	return 0;
@@ -791,18 +824,19 @@
 
 	if (get_user(ep, (unsigned int __user *)arg))
 		return -EFAULT;
-	if ((ret = findintfep(ps->dev, ep)) < 0)
+	ret = findintfep(ps->dev, ep);
+	if (ret < 0)
 		return ret;
-	if ((ret = checkintf(ps, ret)))
+	ret = checkintf(ps, ret);
+	if (ret)
 		return ret;
 	if (ep & USB_DIR_IN)
-                pipe = usb_rcvbulkpipe(ps->dev, ep & 0x7f);
-        else
-                pipe = usb_sndbulkpipe(ps->dev, ep & 0x7f);
+		pipe = usb_rcvbulkpipe(ps->dev, ep & 0x7f);
+	else
+		pipe = usb_sndbulkpipe(ps->dev, ep & 0x7f);
 
 	return usb_clear_halt(ps->dev, pipe);
 }
-		
 
 static int proc_getdriver(struct dev_state *ps, void __user *arg)
 {
@@ -856,23 +890,23 @@
 {
 	int u;
 	int status = 0;
- 	struct usb_host_config *actconfig;
+	struct usb_host_config *actconfig;
 
 	if (get_user(u, (int __user *)arg))
 		return -EFAULT;
 
- 	actconfig = ps->dev->actconfig;
- 
- 	/* Don't touch the device if any interfaces are claimed.
- 	 * It could interfere with other drivers' operations, and if
+	actconfig = ps->dev->actconfig;
+
+	/* Don't touch the device if any interfaces are claimed.
+	 * It could interfere with other drivers' operations, and if
 	 * an interface is claimed by usbfs it could easily deadlock.
 	 */
- 	if (actconfig) {
- 		int i;
- 
- 		for (i = 0; i < actconfig->desc.bNumInterfaces; ++i) {
- 			if (usb_interface_claimed(actconfig->interface[i])) {
-				dev_warn (&ps->dev->dev,
+	if (actconfig) {
+		int i;
+
+		for (i = 0; i < actconfig->desc.bNumInterfaces; ++i) {
+			if (usb_interface_claimed(actconfig->interface[i])) {
+				dev_warn(&ps->dev->dev,
 					"usbfs: interface %d claimed by %s "
 					"while '%s' sets config #%d\n",
 					actconfig->interface[i]
@@ -881,11 +915,11 @@
 					actconfig->interface[i]
 						->dev.driver->name,
 					current->comm, u);
- 				status = -EBUSY;
+				status = -EBUSY;
 				break;
 			}
- 		}
- 	}
+		}
+	}
 
 	/* SET_CONFIGURATION is often abused as a "cheap" driver reset,
 	 * so avoid usb_set_configuration()'s kick to sysfs
@@ -901,8 +935,8 @@
 }
 
 static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
-			     struct usbdevfs_iso_packet_desc __user *iso_frame_desc,
-			     void __user *arg)
+			struct usbdevfs_iso_packet_desc __user *iso_frame_desc,
+			void __user *arg)
 {
 	struct usbdevfs_iso_packet_desc *isopkt = NULL;
 	struct usb_host_endpoint *ep;
@@ -917,12 +951,16 @@
 		return -EINVAL;
 	if (!uurb->buffer)
 		return -EINVAL;
-	if (uurb->signr != 0 && (uurb->signr < SIGRTMIN || uurb->signr > SIGRTMAX))
+	if (uurb->signr != 0 && (uurb->signr < SIGRTMIN ||
+				 uurb->signr > SIGRTMAX))
 		return -EINVAL;
-	if (!(uurb->type == USBDEVFS_URB_TYPE_CONTROL && (uurb->endpoint & ~USB_ENDPOINT_DIR_MASK) == 0)) {
-		if ((ifnum = findintfep(ps->dev, uurb->endpoint)) < 0)
+	if (!(uurb->type == USBDEVFS_URB_TYPE_CONTROL &&
+	    (uurb->endpoint & ~USB_ENDPOINT_DIR_MASK) == 0)) {
+		ifnum = findintfep(ps->dev, uurb->endpoint);
+		if (ifnum < 0)
 			return ifnum;
-		if ((ret = checkintf(ps, ifnum)))
+		ret = checkintf(ps, ifnum);
+		if (ret)
 			return ret;
 	}
 	if ((uurb->endpoint & USB_ENDPOINT_DIR_MASK) != 0) {
@@ -938,10 +976,13 @@
 	case USBDEVFS_URB_TYPE_CONTROL:
 		if (!usb_endpoint_xfer_control(&ep->desc))
 			return -EINVAL;
-		/* min 8 byte setup packet, max 8 byte setup plus an arbitrary data stage */
-		if (uurb->buffer_length < 8 || uurb->buffer_length > (8 + MAX_USBFS_BUFFER_SIZE))
+		/* min 8 byte setup packet,
+		 * max 8 byte setup plus an arbitrary data stage */
+		if (uurb->buffer_length < 8 ||
+		    uurb->buffer_length > (8 + MAX_USBFS_BUFFER_SIZE))
 			return -EINVAL;
-		if (!(dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL)))
+		dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL);
+		if (!dr)
 			return -ENOMEM;
 		if (copy_from_user(dr, uurb->buffer, 8)) {
 			kfree(dr);
@@ -951,7 +992,9 @@
 			kfree(dr);
 			return -EINVAL;
 		}
-		if ((ret = check_ctrlrecip(ps, dr->bRequestType, le16_to_cpup(&dr->wIndex)))) {
+		ret = check_ctrlrecip(ps, dr->bRequestType,
+				      le16_to_cpup(&dr->wIndex));
+		if (ret) {
 			kfree(dr);
 			return ret;
 		}
@@ -997,11 +1040,13 @@
 
 	case USBDEVFS_URB_TYPE_ISO:
 		/* arbitrary limit */
-		if (uurb->number_of_packets < 1 || uurb->number_of_packets > 128)
+		if (uurb->number_of_packets < 1 ||
+		    uurb->number_of_packets > 128)
 			return -EINVAL;
 		if (!usb_endpoint_xfer_isoc(&ep->desc))
 			return -EINVAL;
-		isofrmlen = sizeof(struct usbdevfs_iso_packet_desc) * uurb->number_of_packets;
+		isofrmlen = sizeof(struct usbdevfs_iso_packet_desc) *
+				   uurb->number_of_packets;
 		if (!(isopkt = kmalloc(isofrmlen, GFP_KERNEL)))
 			return -ENOMEM;
 		if (copy_from_user(isopkt, iso_frame_desc, isofrmlen)) {
@@ -1009,7 +1054,8 @@
 			return -EFAULT;
 		}
 		for (totlen = u = 0; u < uurb->number_of_packets; u++) {
-			/* arbitrary limit, sufficient for USB 2.0 high-bandwidth iso */
+			/* arbitrary limit,
+			 * sufficient for USB 2.0 high-bandwidth iso */
 			if (isopkt[u].length > 8192) {
 				kfree(isopkt);
 				return -EINVAL;
@@ -1039,25 +1085,27 @@
 	default:
 		return -EINVAL;
 	}
-	if (!(as = alloc_async(uurb->number_of_packets))) {
+	as = alloc_async(uurb->number_of_packets);
+	if (!as) {
 		kfree(isopkt);
 		kfree(dr);
 		return -ENOMEM;
 	}
-	if (!(as->urb->transfer_buffer = kmalloc(uurb->buffer_length, GFP_KERNEL))) {
+	as->urb->transfer_buffer = kmalloc(uurb->buffer_length, GFP_KERNEL);
+	if (!as->urb->transfer_buffer) {
 		kfree(isopkt);
 		kfree(dr);
 		free_async(as);
 		return -ENOMEM;
 	}
-        as->urb->dev = ps->dev;
-        as->urb->pipe = (uurb->type << 30) |
+	as->urb->dev = ps->dev;
+	as->urb->pipe = (uurb->type << 30) |
 			__create_pipe(ps->dev, uurb->endpoint & 0xf) |
 			(uurb->endpoint & USB_DIR_IN);
-        as->urb->transfer_flags = uurb->flags |
+	as->urb->transfer_flags = uurb->flags |
 			(is_in ? URB_DIR_IN : URB_DIR_OUT);
 	as->urb->transfer_buffer_length = uurb->buffer_length;
-	as->urb->setup_packet = (unsigned char*)dr;
+	as->urb->setup_packet = (unsigned char *)dr;
 	as->urb->start_frame = uurb->start_frame;
 	as->urb->number_of_packets = uurb->number_of_packets;
 	if (uurb->type == USBDEVFS_URB_TYPE_ISO ||
@@ -1065,8 +1113,8 @@
 		as->urb->interval = 1 << min(15, ep->desc.bInterval - 1);
 	else
 		as->urb->interval = ep->desc.bInterval;
-        as->urb->context = as;
-        as->urb->complete = async_completed;
+	as->urb->context = as;
+	as->urb->complete = async_completed;
 	for (totlen = u = 0; u < uurb->number_of_packets; u++) {
 		as->urb->iso_frame_desc[u].offset = totlen;
 		as->urb->iso_frame_desc[u].length = isopkt[u].length;
@@ -1074,7 +1122,7 @@
 	}
 	kfree(isopkt);
 	as->ps = ps;
-        as->userurb = arg;
+	as->userurb = arg;
 	if (uurb->endpoint & USB_DIR_IN)
 		as->userbuffer = uurb->buffer;
 	else
@@ -1093,14 +1141,15 @@
 		}
 	}
 	snoop_urb(as->urb, as->userurb);
-        async_newpending(as);
-        if ((ret = usb_submit_urb(as->urb, GFP_KERNEL))) {
-		dev_printk(KERN_DEBUG, &ps->dev->dev, "usbfs: usb_submit_urb returned %d\n", ret);
-                async_removepending(as);
-                free_async(as);
-                return ret;
-        }
-        return 0;
+	async_newpending(as);
+	if ((ret = usb_submit_urb(as->urb, GFP_KERNEL))) {
+		dev_printk(KERN_DEBUG, &ps->dev->dev,
+			   "usbfs: usb_submit_urb returned %d\n", ret);
+		async_removepending(as);
+		free_async(as);
+		return ret;
+	}
+	return 0;
 }
 
 static int proc_submiturb(struct dev_state *ps, void __user *arg)
@@ -1110,7 +1159,9 @@
 	if (copy_from_user(&uurb, arg, sizeof(uurb)))
 		return -EFAULT;
 
-	return proc_do_submiturb(ps, &uurb, (((struct usbdevfs_urb __user *)arg)->iso_frame_desc), arg);
+	return proc_do_submiturb(ps, &uurb,
+			(((struct usbdevfs_urb __user *)arg)->iso_frame_desc),
+			arg);
 }
 
 static int proc_unlinkurb(struct dev_state *ps, void __user *arg)
@@ -1132,7 +1183,8 @@
 	unsigned int i;
 
 	if (as->userbuffer)
-		if (copy_to_user(as->userbuffer, urb->transfer_buffer, urb->transfer_buffer_length))
+		if (copy_to_user(as->userbuffer, urb->transfer_buffer,
+				 urb->transfer_buffer_length))
 			return -EFAULT;
 	if (put_user(as->status, &userurb->status))
 		return -EFAULT;
@@ -1159,16 +1211,17 @@
 	return 0;
 }
 
-static struct async* reap_as(struct dev_state *ps)
+static struct async *reap_as(struct dev_state *ps)
 {
-        DECLARE_WAITQUEUE(wait, current);
+	DECLARE_WAITQUEUE(wait, current);
 	struct async *as = NULL;
 	struct usb_device *dev = ps->dev;
 
 	add_wait_queue(&ps->wait, &wait);
 	for (;;) {
 		__set_current_state(TASK_INTERRUPTIBLE);
-		if ((as = async_getcompleted(ps)))
+		as = async_getcompleted(ps);
+		if (as)
 			break;
 		if (signal_pending(current))
 			break;
@@ -1232,10 +1285,12 @@
 {
 	struct usbdevfs_urb uurb;
 
-	if (get_urb32(&uurb,(struct usbdevfs_urb32 __user *)arg))
+	if (get_urb32(&uurb, (struct usbdevfs_urb32 __user *)arg))
 		return -EFAULT;
 
-	return proc_do_submiturb(ps, &uurb, ((struct usbdevfs_urb32 __user *)arg)->iso_frame_desc, arg);
+	return proc_do_submiturb(ps, &uurb,
+			((struct usbdevfs_urb32 __user *)arg)->iso_frame_desc,
+			arg);
 }
 
 static int processcompl_compat(struct async *as, void __user * __user *arg)
@@ -1246,7 +1301,8 @@
 	unsigned int i;
 
 	if (as->userbuffer)
-		if (copy_to_user(as->userbuffer, urb->transfer_buffer, urb->transfer_buffer_length))
+		if (copy_to_user(as->userbuffer, urb->transfer_buffer,
+				 urb->transfer_buffer_length))
 			return -EFAULT;
 	if (put_user(as->status, &userurb->status))
 		return -EFAULT;
@@ -1337,16 +1393,16 @@
 	struct usb_driver       *driver = NULL;
 
 	/* alloc buffer */
-	if ((size = _IOC_SIZE (ctl->ioctl_code)) > 0) {
-		if ((buf = kmalloc (size, GFP_KERNEL)) == NULL)
+	if ((size = _IOC_SIZE(ctl->ioctl_code)) > 0) {
+		if ((buf = kmalloc(size, GFP_KERNEL)) == NULL)
 			return -ENOMEM;
 		if ((_IOC_DIR(ctl->ioctl_code) & _IOC_WRITE)) {
-			if (copy_from_user (buf, ctl->data, size)) {
+			if (copy_from_user(buf, ctl->data, size)) {
 				kfree(buf);
 				return -EFAULT;
 			}
 		} else {
-			memset (buf, 0, size);
+			memset(buf, 0, size);
 		}
 	}
 
@@ -1357,15 +1413,15 @@
 
 	if (ps->dev->state != USB_STATE_CONFIGURED)
 		retval = -EHOSTUNREACH;
-	else if (!(intf = usb_ifnum_to_if (ps->dev, ctl->ifno)))
-               retval = -EINVAL;
+	else if (!(intf = usb_ifnum_to_if(ps->dev, ctl->ifno)))
+		retval = -EINVAL;
 	else switch (ctl->ioctl_code) {
 
 	/* disconnect kernel driver from interface */
 	case USBDEVFS_DISCONNECT:
 		if (intf->dev.driver) {
 			driver = to_usb_driver(intf->dev.driver);
-			dev_dbg (&intf->dev, "disconnect by usbfs\n");
+			dev_dbg(&intf->dev, "disconnect by usbfs\n");
 			usb_driver_release_interface(driver, intf);
 		} else
 			retval = -ENODATA;
@@ -1373,9 +1429,10 @@
 
 	/* let kernel drivers try to (re)bind to the interface */
 	case USBDEVFS_CONNECT:
-		usb_unlock_device(ps->dev);
-		retval = bus_rescan_devices(intf->dev.bus);
-		usb_lock_device(ps->dev);
+		if (!intf->dev.driver)
+			retval = device_attach(&intf->dev);
+		else
+			retval = -EBUSY;
 		break;
 
 	/* talk directly to the interface's driver */
@@ -1385,7 +1442,7 @@
 		if (driver == NULL || driver->ioctl == NULL) {
 			retval = -ENOTTY;
 		} else {
-			retval = driver->ioctl (intf, ctl->ioctl_code, buf);
+			retval = driver->ioctl(intf, ctl->ioctl_code, buf);
 			if (retval == -ENOIOCTLCMD)
 				retval = -ENOTTY;
 		}
@@ -1393,9 +1450,9 @@
 
 	/* cleanup and return */
 	if (retval >= 0
-			&& (_IOC_DIR (ctl->ioctl_code) & _IOC_READ) != 0
+			&& (_IOC_DIR(ctl->ioctl_code) & _IOC_READ) != 0
 			&& size > 0
-			&& copy_to_user (ctl->data, buf, size) != 0)
+			&& copy_to_user(ctl->data, buf, size) != 0)
 		retval = -EFAULT;
 
 	kfree(buf);
@@ -1406,7 +1463,7 @@
 {
 	struct usbdevfs_ioctl	ctrl;
 
-	if (copy_from_user(&ctrl, arg, sizeof (ctrl)))
+	if (copy_from_user(&ctrl, arg, sizeof(ctrl)))
 		return -EFAULT;
 	return proc_ioctl(ps, &ctrl);
 }
@@ -1434,7 +1491,8 @@
  * are assuming that somehow the configuration has been prevented from
  * changing.  But there's no mechanism to ensure that...
  */
-static int usbdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+static int usbdev_ioctl(struct inode *inode, struct file *file,
+			unsigned int cmd, unsigned long arg)
 {
 	struct dev_state *ps = file->private_data;
 	struct usb_device *dev = ps->dev;
@@ -1577,7 +1635,8 @@
 }
 
 /* No kernel lock - fine */
-static unsigned int usbdev_poll(struct file *file, struct poll_table_struct *wait)
+static unsigned int usbdev_poll(struct file *file,
+				struct poll_table_struct *wait)
 {
 	struct dev_state *ps = file->private_data;
 	unsigned int mask = 0;
@@ -1648,7 +1707,7 @@
 	int retval;
 
 	retval = register_chrdev_region(USB_DEVICE_DEV, USB_DEVICE_MAX,
-			"usb_device");
+					"usb_device");
 	if (retval) {
 		err("unable to register minors for usb_device");
 		goto out;
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index 7c3aaa9..801b6f1 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -202,10 +202,10 @@
 	intf = to_usb_interface(dev);
 	udev = interface_to_usbdev(intf);
 
- 	if (udev->authorized == 0) {
- 		dev_err(&intf->dev, "Device is not authorized for usage\n");
- 		return -ENODEV;
- 	}
+	if (udev->authorized == 0) {
+		dev_err(&intf->dev, "Device is not authorized for usage\n");
+		return -ENODEV;
+	}
 
 	id = usb_match_id(intf, driver->id_table);
 	if (!id)
@@ -299,7 +299,7 @@
  * lock.
  */
 int usb_driver_claim_interface(struct usb_driver *driver,
-				struct usb_interface *iface, void* priv)
+				struct usb_interface *iface, void *priv)
 {
 	struct device *dev = &iface->dev;
 	struct usb_device *udev = interface_to_usbdev(iface);
@@ -325,7 +325,7 @@
 
 	return retval;
 }
-EXPORT_SYMBOL(usb_driver_claim_interface);
+EXPORT_SYMBOL_GPL(usb_driver_claim_interface);
 
 /**
  * usb_driver_release_interface - unbind a driver from an interface
@@ -370,7 +370,7 @@
 	iface->needs_remote_wakeup = 0;
 	usb_pm_unlock(udev);
 }
-EXPORT_SYMBOL(usb_driver_release_interface);
+EXPORT_SYMBOL_GPL(usb_driver_release_interface);
 
 /* returns 0 if no match, 1 if match */
 int usb_match_device(struct usb_device *dev, const struct usb_device_id *id)
@@ -398,7 +398,7 @@
 		return 0;
 
 	if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_SUBCLASS) &&
-	    (id->bDeviceSubClass!= dev->descriptor.bDeviceSubClass))
+	    (id->bDeviceSubClass != dev->descriptor.bDeviceSubClass))
 		return 0;
 
 	if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_PROTOCOL) &&
@@ -534,15 +534,15 @@
 	   id->driver_info is the way to create an entry that
 	   indicates that the driver want to examine every
 	   device and interface. */
-	for (; id->idVendor || id->bDeviceClass || id->bInterfaceClass ||
-	       id->driver_info; id++) {
+	for (; id->idVendor || id->idProduct || id->bDeviceClass ||
+	       id->bInterfaceClass || id->driver_info; id++) {
 		if (usb_match_one_id(interface, id))
 			return id;
 	}
 
 	return NULL;
 }
-EXPORT_SYMBOL_GPL_FUTURE(usb_match_id);
+EXPORT_SYMBOL_GPL(usb_match_id);
 
 static int usb_device_match(struct device *dev, struct device_driver *drv)
 {
@@ -586,7 +586,7 @@
 	struct usb_device *usb_dev;
 
 	/* driver is often null here; dev_dbg() would oops */
-	pr_debug ("usb %s: uevent\n", dev->bus_id);
+	pr_debug("usb %s: uevent\n", dev->bus_id);
 
 	if (is_usb_device(dev))
 		usb_dev = to_usb_device(dev);
@@ -596,11 +596,11 @@
 	}
 
 	if (usb_dev->devnum < 0) {
-		pr_debug ("usb %s: already deleted?\n", dev->bus_id);
+		pr_debug("usb %s: already deleted?\n", dev->bus_id);
 		return -ENODEV;
 	}
 	if (!usb_dev->bus) {
-		pr_debug ("usb %s: bus removed?\n", dev->bus_id);
+		pr_debug("usb %s: bus removed?\n", dev->bus_id);
 		return -ENODEV;
 	}
 
@@ -745,7 +745,7 @@
 
 	return retval;
 }
-EXPORT_SYMBOL_GPL_FUTURE(usb_register_driver);
+EXPORT_SYMBOL_GPL(usb_register_driver);
 
 /**
  * usb_deregister - unregister a USB interface driver
@@ -769,7 +769,7 @@
 
 	usbfs_update_special();
 }
-EXPORT_SYMBOL_GPL_FUTURE(usb_deregister);
+EXPORT_SYMBOL_GPL(usb_deregister);
 
 #ifdef CONFIG_PM
 
@@ -854,8 +854,10 @@
 			dev_err(&intf->dev, "%s error %d\n",
 					"suspend", status);
 	} else {
-		// FIXME else if there's no suspend method, disconnect...
-		// Not possible if auto_pm is set...
+		/*
+		 * FIXME else if there's no suspend method, disconnect...
+		 * Not possible if auto_pm is set...
+		 */
 		dev_warn(&intf->dev, "no suspend for driver %s?\n",
 				driver->name);
 		mark_quiesced(intf);
@@ -894,7 +896,7 @@
 				dev_err(&intf->dev, "%s error %d\n",
 						"reset_resume", status);
 		} else {
-			// status = -EOPNOTSUPP;
+			/* status = -EOPNOTSUPP; */
 			dev_warn(&intf->dev, "no %s for driver %s?\n",
 					"reset_resume", driver->name);
 		}
@@ -905,7 +907,7 @@
 				dev_err(&intf->dev, "%s error %d\n",
 						"resume", status);
 		} else {
-			// status = -EOPNOTSUPP;
+			/* status = -EOPNOTSUPP; */
 			dev_warn(&intf->dev, "no %s for driver %s?\n",
 					"resume", driver->name);
 		}
@@ -1175,7 +1177,7 @@
 			 * so if a root hub's controller is suspended
 			 * then we're stuck. */
 			status = usb_resume_device(udev);
- 		}
+		}
 	} else {
 
 		/* Needed for setting udev->dev.power.power_state.event,
diff --git a/drivers/usb/core/file.c b/drivers/usb/core/file.c
index 5d860bc..8133c99 100644
--- a/drivers/usb/core/file.c
+++ b/drivers/usb/core/file.c
@@ -204,7 +204,7 @@
 exit:
 	return retval;
 }
-EXPORT_SYMBOL(usb_register_dev);
+EXPORT_SYMBOL_GPL(usb_register_dev);
 
 /**
  * usb_deregister_dev - deregister a USB device's dynamic minor.
@@ -245,4 +245,4 @@
 	intf->minor = -1;
 	destroy_usb_class();
 }
-EXPORT_SYMBOL(usb_deregister_dev);
+EXPORT_SYMBOL_GPL(usb_deregister_dev);
diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c
index 3fb9af8..84760dd 100644
--- a/drivers/usb/core/hcd-pci.c
+++ b/drivers/usb/core/hcd-pci.c
@@ -1,6 +1,6 @@
 /*
  * (C) Copyright David Brownell 2000-2002
- * 
+ *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the
  * Free Software Foundation; either version 2 of the License, or (at your
@@ -55,7 +55,7 @@
  *
  * Store this function in the HCD's struct pci_driver as probe().
  */
-int usb_hcd_pci_probe (struct pci_dev *dev, const struct pci_device_id *id)
+int usb_hcd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
 {
 	struct hc_driver	*driver;
 	struct usb_hcd		*hcd;
@@ -64,66 +64,71 @@
 	if (usb_disabled())
 		return -ENODEV;
 
-	if (!id || !(driver = (struct hc_driver *) id->driver_data))
+	if (!id)
+		return -EINVAL;
+	driver = (struct hc_driver *)id->driver_data;
+	if (!driver)
 		return -EINVAL;
 
-	if (pci_enable_device (dev) < 0)
+	if (pci_enable_device(dev) < 0)
 		return -ENODEV;
 	dev->current_state = PCI_D0;
 	dev->dev.power.power_state = PMSG_ON;
-	
-        if (!dev->irq) {
-        	dev_err (&dev->dev,
+
+	if (!dev->irq) {
+		dev_err(&dev->dev,
 			"Found HC with no IRQ.  Check BIOS/PCI %s setup!\n",
 			pci_name(dev));
-   	        retval = -ENODEV;
+		retval = -ENODEV;
 		goto err1;
-        }
+	}
 
-	hcd = usb_create_hcd (driver, &dev->dev, pci_name(dev));
+	hcd = usb_create_hcd(driver, &dev->dev, pci_name(dev));
 	if (!hcd) {
 		retval = -ENOMEM;
 		goto err1;
 	}
 
-	if (driver->flags & HCD_MEMORY) {	// EHCI, OHCI
-		hcd->rsrc_start = pci_resource_start (dev, 0);
-		hcd->rsrc_len = pci_resource_len (dev, 0);
-		if (!request_mem_region (hcd->rsrc_start, hcd->rsrc_len,
+	if (driver->flags & HCD_MEMORY) {
+		/* EHCI, OHCI */
+		hcd->rsrc_start = pci_resource_start(dev, 0);
+		hcd->rsrc_len = pci_resource_len(dev, 0);
+		if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len,
 				driver->description)) {
-			dev_dbg (&dev->dev, "controller already in use\n");
+			dev_dbg(&dev->dev, "controller already in use\n");
 			retval = -EBUSY;
 			goto err2;
 		}
-		hcd->regs = ioremap_nocache (hcd->rsrc_start, hcd->rsrc_len);
+		hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len);
 		if (hcd->regs == NULL) {
-			dev_dbg (&dev->dev, "error mapping memory\n");
+			dev_dbg(&dev->dev, "error mapping memory\n");
 			retval = -EFAULT;
 			goto err3;
 		}
 
-	} else { 				// UHCI
+	} else {
+		/* UHCI */
 		int	region;
 
 		for (region = 0; region < PCI_ROM_RESOURCE; region++) {
-			if (!(pci_resource_flags (dev, region) &
+			if (!(pci_resource_flags(dev, region) &
 					IORESOURCE_IO))
 				continue;
 
-			hcd->rsrc_start = pci_resource_start (dev, region);
-			hcd->rsrc_len = pci_resource_len (dev, region);
-			if (request_region (hcd->rsrc_start, hcd->rsrc_len,
+			hcd->rsrc_start = pci_resource_start(dev, region);
+			hcd->rsrc_len = pci_resource_len(dev, region);
+			if (request_region(hcd->rsrc_start, hcd->rsrc_len,
 					driver->description))
 				break;
 		}
 		if (region == PCI_ROM_RESOURCE) {
-			dev_dbg (&dev->dev, "no i/o regions available\n");
+			dev_dbg(&dev->dev, "no i/o regions available\n");
 			retval = -EBUSY;
 			goto err1;
 		}
 	}
 
-	pci_set_master (dev);
+	pci_set_master(dev);
 
 	retval = usb_add_hcd(hcd, dev->irq, IRQF_DISABLED | IRQF_SHARED);
 	if (retval != 0)
@@ -132,19 +137,19 @@
 
  err4:
 	if (driver->flags & HCD_MEMORY) {
-		iounmap (hcd->regs);
+		iounmap(hcd->regs);
  err3:
-		release_mem_region (hcd->rsrc_start, hcd->rsrc_len);
+		release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
 	} else
-		release_region (hcd->rsrc_start, hcd->rsrc_len);
+		release_region(hcd->rsrc_start, hcd->rsrc_len);
  err2:
-	usb_put_hcd (hcd);
+	usb_put_hcd(hcd);
  err1:
-	pci_disable_device (dev);
-	dev_err (&dev->dev, "init %s fail, %d\n", pci_name(dev), retval);
+	pci_disable_device(dev);
+	dev_err(&dev->dev, "init %s fail, %d\n", pci_name(dev), retval);
 	return retval;
-} 
-EXPORT_SYMBOL (usb_hcd_pci_probe);
+}
+EXPORT_SYMBOL_GPL(usb_hcd_pci_probe);
 
 
 /* may be called without controller electrically present */
@@ -161,7 +166,7 @@
  *
  * Store this function in the HCD's struct pci_driver as remove().
  */
-void usb_hcd_pci_remove (struct pci_dev *dev)
+void usb_hcd_pci_remove(struct pci_dev *dev)
 {
 	struct usb_hcd		*hcd;
 
@@ -169,17 +174,17 @@
 	if (!hcd)
 		return;
 
-	usb_remove_hcd (hcd);
+	usb_remove_hcd(hcd);
 	if (hcd->driver->flags & HCD_MEMORY) {
-		iounmap (hcd->regs);
-		release_mem_region (hcd->rsrc_start, hcd->rsrc_len);
+		iounmap(hcd->regs);
+		release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
 	} else {
-		release_region (hcd->rsrc_start, hcd->rsrc_len);
+		release_region(hcd->rsrc_start, hcd->rsrc_len);
 	}
-	usb_put_hcd (hcd);
+	usb_put_hcd(hcd);
 	pci_disable_device(dev);
 }
-EXPORT_SYMBOL (usb_hcd_pci_remove);
+EXPORT_SYMBOL_GPL(usb_hcd_pci_remove);
 
 
 #ifdef	CONFIG_PM
@@ -191,7 +196,7 @@
  *
  * Store this function in the HCD's struct pci_driver as suspend().
  */
-int usb_hcd_pci_suspend (struct pci_dev *dev, pm_message_t message)
+int usb_hcd_pci_suspend(struct pci_dev *dev, pm_message_t message)
 {
 	struct usb_hcd		*hcd;
 	int			retval = 0;
@@ -246,12 +251,18 @@
 
 		/* no DMA or IRQs except when HC is active */
 		if (dev->current_state == PCI_D0) {
-			pci_save_state (dev);
-			pci_disable_device (dev);
+			pci_save_state(dev);
+			pci_disable_device(dev);
+		}
+
+		if (message.event == PM_EVENT_FREEZE ||
+				message.event == PM_EVENT_PRETHAW) {
+			dev_dbg(hcd->self.controller, "--> no state change\n");
+			goto done;
 		}
 
 		if (!has_pci_pm) {
-			dev_dbg (hcd->self.controller, "--> PCI D0/legacy\n");
+			dev_dbg(hcd->self.controller, "--> PCI D0/legacy\n");
 			goto done;
 		}
 
@@ -260,30 +271,30 @@
 		 * PCI_D3 (but not PCI_D1 or PCI_D2) is allowed to reset
 		 * some device state (e.g. as part of clock reinit).
 		 */
-		retval = pci_set_power_state (dev, PCI_D3hot);
+		retval = pci_set_power_state(dev, PCI_D3hot);
 		suspend_report_result(pci_set_power_state, retval);
 		if (retval == 0) {
 			int wake = device_can_wakeup(&hcd->self.root_hub->dev);
 
 			wake = wake && device_may_wakeup(hcd->self.controller);
 
-			dev_dbg (hcd->self.controller, "--> PCI D3%s\n",
+			dev_dbg(hcd->self.controller, "--> PCI D3%s\n",
 					wake ? "/wakeup" : "");
 
 			/* Ignore these return values.  We rely on pci code to
 			 * reject requests the hardware can't implement, rather
 			 * than coding the same thing.
 			 */
-			(void) pci_enable_wake (dev, PCI_D3hot, wake);
-			(void) pci_enable_wake (dev, PCI_D3cold, wake);
+			(void) pci_enable_wake(dev, PCI_D3hot, wake);
+			(void) pci_enable_wake(dev, PCI_D3cold, wake);
 		} else {
-			dev_dbg (&dev->dev, "PCI D3 suspend fail, %d\n",
+			dev_dbg(&dev->dev, "PCI D3 suspend fail, %d\n",
 					retval);
-			(void) usb_hcd_pci_resume (dev);
+			(void) usb_hcd_pci_resume(dev);
 		}
 
 	} else if (hcd->state != HC_STATE_HALT) {
-		dev_dbg (hcd->self.controller, "hcd state %d; not suspended\n",
+		dev_dbg(hcd->self.controller, "hcd state %d; not suspended\n",
 			hcd->state);
 		WARN_ON(1);
 		retval = -EINVAL;
@@ -298,7 +309,7 @@
 		if (machine_is(powermac)) {
 			struct device_node	*of_node;
 
-			of_node = pci_device_to_OF_node (dev);
+			of_node = pci_device_to_OF_node(dev);
 			if (of_node)
 				pmac_call_feature(PMAC_FTR_USB_ENABLE,
 							of_node, 0, 0);
@@ -308,7 +319,7 @@
 
 	return retval;
 }
-EXPORT_SYMBOL (usb_hcd_pci_suspend);
+EXPORT_SYMBOL_GPL(usb_hcd_pci_suspend);
 
 /**
  * usb_hcd_pci_resume - power management resume of a PCI-based HCD
@@ -316,14 +327,14 @@
  *
  * Store this function in the HCD's struct pci_driver as resume().
  */
-int usb_hcd_pci_resume (struct pci_dev *dev)
+int usb_hcd_pci_resume(struct pci_dev *dev)
 {
 	struct usb_hcd		*hcd;
 	int			retval;
 
 	hcd = pci_get_drvdata(dev);
 	if (hcd->state != HC_STATE_SUSPENDED) {
-		dev_dbg (hcd->self.controller, 
+		dev_dbg(hcd->self.controller,
 				"can't resume, not suspended!\n");
 		return 0;
 	}
@@ -333,9 +344,9 @@
 	if (machine_is(powermac)) {
 		struct device_node *of_node;
 
-		of_node = pci_device_to_OF_node (dev);
+		of_node = pci_device_to_OF_node(dev);
 		if (of_node)
-			pmac_call_feature (PMAC_FTR_USB_ENABLE,
+			pmac_call_feature(PMAC_FTR_USB_ENABLE,
 						of_node, 0, 1);
 	}
 #endif
@@ -374,8 +385,8 @@
 		}
 #endif
 		/* yes, ignore these results too... */
-		(void) pci_enable_wake (dev, dev->current_state, 0);
-		(void) pci_enable_wake (dev, PCI_D3cold, 0);
+		(void) pci_enable_wake(dev, dev->current_state, 0);
+		(void) pci_enable_wake(dev, PCI_D3cold, 0);
 	} else {
 		/* Same basic cases: clean (powered/not), dirty */
 		dev_dbg(hcd->self.controller, "PCI legacy resume\n");
@@ -386,14 +397,14 @@
 	 * but that won't re-enable bus mastering.  Yet pci_disable_device()
 	 * explicitly disables bus mastering...
 	 */
-	retval = pci_enable_device (dev);
+	retval = pci_enable_device(dev);
 	if (retval < 0) {
-		dev_err (hcd->self.controller,
+		dev_err(hcd->self.controller,
 			"can't re-enable after resume, %d!\n", retval);
 		return retval;
 	}
-	pci_set_master (dev);
-	pci_restore_state (dev);
+	pci_set_master(dev);
+	pci_restore_state(dev);
 
 	dev->dev.power.power_state = PMSG_ON;
 
@@ -402,15 +413,15 @@
 	if (hcd->driver->resume) {
 		retval = hcd->driver->resume(hcd);
 		if (retval) {
-			dev_err (hcd->self.controller,
+			dev_err(hcd->self.controller,
 				"PCI post-resume error %d!\n", retval);
-			usb_hc_died (hcd);
+			usb_hc_died(hcd);
 		}
 	}
 
 	return retval;
 }
-EXPORT_SYMBOL (usb_hcd_pci_resume);
+EXPORT_SYMBOL_GPL(usb_hcd_pci_resume);
 
 #endif	/* CONFIG_PM */
 
@@ -418,7 +429,7 @@
  * usb_hcd_pci_shutdown - shutdown host controller
  * @dev: USB Host Controller being shutdown
  */
-void usb_hcd_pci_shutdown (struct pci_dev *dev)
+void usb_hcd_pci_shutdown(struct pci_dev *dev)
 {
 	struct usb_hcd		*hcd;
 
@@ -429,5 +440,5 @@
 	if (hcd->driver->shutdown)
 		hcd->driver->shutdown(hcd);
 }
-EXPORT_SYMBOL (usb_hcd_pci_shutdown);
+EXPORT_SYMBOL_GPL(usb_hcd_pci_shutdown);
 
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index d5ed3fa..e52ed16 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -35,6 +35,7 @@
 #include <linux/mutex.h>
 #include <asm/irq.h>
 #include <asm/byteorder.h>
+#include <asm/unaligned.h>
 #include <linux/platform_device.h>
 #include <linux/workqueue.h>
 
@@ -131,8 +132,8 @@
 	0x01,       /*  __u8  bDeviceProtocol; [ usb 2.0 single TT ]*/
 	0x40,       /*  __u8  bMaxPacketSize0; 64 Bytes */
 
-	0x00, 0x00, /*  __le16 idVendor; */
- 	0x00, 0x00, /*  __le16 idProduct; */
+	0x6b, 0x1d, /*  __le16 idVendor; Linux Foundation */
+	0x02, 0x00, /*  __le16 idProduct; device 0x0002 */
 	KERNEL_VER, KERNEL_REL, /*  __le16 bcdDevice */
 
 	0x03,       /*  __u8  iManufacturer; */
@@ -154,8 +155,8 @@
 	0x00,       /*  __u8  bDeviceProtocol; [ low/full speeds only ] */
 	0x40,       /*  __u8  bMaxPacketSize0; 64 Bytes */
 
-	0x00, 0x00, /*  __le16 idVendor; */
- 	0x00, 0x00, /*  __le16 idProduct; */
+	0x6b, 0x1d, /*  __le16 idVendor; Linux Foundation */
+	0x01, 0x00, /*  __le16 idProduct; device 0x0001 */
 	KERNEL_VER, KERNEL_REL, /*  __le16 bcdDevice */
 
 	0x03,       /*  __u8  iManufacturer; */
@@ -807,13 +808,13 @@
 	}
 	set_bit (busnum, busmap.busmap);
 	bus->busnum = busnum;
-	bus->class_dev = class_device_create(usb_host_class, NULL, MKDEV(0,0),
-					     bus->controller, "usb_host%d",
-					     busnum);
-	result = PTR_ERR(bus->class_dev);
-	if (IS_ERR(bus->class_dev))
+
+	bus->dev = device_create(usb_host_class, bus->controller, MKDEV(0, 0),
+				 "usb_host%d", busnum);
+	result = PTR_ERR(bus->dev);
+	if (IS_ERR(bus->dev))
 		goto error_create_class_dev;
-	class_set_devdata(bus->class_dev, bus);
+	dev_set_drvdata(bus->dev, bus);
 
 	/* Add it to the local list of buses */
 	list_add (&bus->bus_list, &usb_bus_list);
@@ -857,7 +858,7 @@
 
 	clear_bit (bus->busnum, busmap.busmap);
 
-	class_device_unregister(bus->class_dev);
+	device_unregister(bus->dev);
 }
 
 /**
@@ -970,7 +971,7 @@
 		return -1;
 	}
 }
-EXPORT_SYMBOL (usb_calc_bus_time);
+EXPORT_SYMBOL_GPL(usb_calc_bus_time);
 
 
 /*-------------------------------------------------------------------------*/
@@ -1112,48 +1113,177 @@
 }
 EXPORT_SYMBOL_GPL(usb_hcd_unlink_urb_from_ep);
 
-static void map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb)
+/*
+ * Some usb host controllers can only perform dma using a small SRAM area.
+ * The usb core itself is however optimized for host controllers that can dma
+ * using regular system memory - like pci devices doing bus mastering.
+ *
+ * To support host controllers with limited dma capabilites we provide dma
+ * bounce buffers. This feature can be enabled using the HCD_LOCAL_MEM flag.
+ * For this to work properly the host controller code must first use the
+ * function dma_declare_coherent_memory() to point out which memory area
+ * that should be used for dma allocations.
+ *
+ * The HCD_LOCAL_MEM flag then tells the usb code to allocate all data for
+ * dma using dma_alloc_coherent() which in turn allocates from the memory
+ * area pointed out with dma_declare_coherent_memory().
+ *
+ * So, to summarize...
+ *
+ * - We need "local" memory, canonical example being
+ *   a small SRAM on a discrete controller being the
+ *   only memory that the controller can read ...
+ *   (a) "normal" kernel memory is no good, and
+ *   (b) there's not enough to share
+ *
+ * - The only *portable* hook for such stuff in the
+ *   DMA framework is dma_declare_coherent_memory()
+ *
+ * - So we use that, even though the primary requirement
+ *   is that the memory be "local" (hence addressible
+ *   by that device), not "coherent".
+ *
+ */
+
+static int hcd_alloc_coherent(struct usb_bus *bus,
+			      gfp_t mem_flags, dma_addr_t *dma_handle,
+			      void **vaddr_handle, size_t size,
+			      enum dma_data_direction dir)
 {
+	unsigned char *vaddr;
+
+	vaddr = hcd_buffer_alloc(bus, size + sizeof(vaddr),
+				 mem_flags, dma_handle);
+	if (!vaddr)
+		return -ENOMEM;
+
+	/*
+	 * Store the virtual address of the buffer at the end
+	 * of the allocated dma buffer. The size of the buffer
+	 * may be uneven so use unaligned functions instead
+	 * of just rounding up. It makes sense to optimize for
+	 * memory footprint over access speed since the amount
+	 * of memory available for dma may be limited.
+	 */
+	put_unaligned((unsigned long)*vaddr_handle,
+		      (unsigned long *)(vaddr + size));
+
+	if (dir == DMA_TO_DEVICE)
+		memcpy(vaddr, *vaddr_handle, size);
+
+	*vaddr_handle = vaddr;
+	return 0;
+}
+
+static void hcd_free_coherent(struct usb_bus *bus, dma_addr_t *dma_handle,
+			      void **vaddr_handle, size_t size,
+			      enum dma_data_direction dir)
+{
+	unsigned char *vaddr = *vaddr_handle;
+
+	vaddr = (void *)get_unaligned((unsigned long *)(vaddr + size));
+
+	if (dir == DMA_FROM_DEVICE)
+		memcpy(vaddr, *vaddr_handle, size);
+
+	hcd_buffer_free(bus, size + sizeof(vaddr), *vaddr_handle, *dma_handle);
+
+	*vaddr_handle = vaddr;
+	*dma_handle = 0;
+}
+
+static int map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb,
+			   gfp_t mem_flags)
+{
+	enum dma_data_direction dir;
+	int ret = 0;
+
 	/* Map the URB's buffers for DMA access.
 	 * Lower level HCD code should use *_dma exclusively,
 	 * unless it uses pio or talks to another transport.
 	 */
-	if (hcd->self.uses_dma && !is_root_hub(urb->dev)) {
-		if (usb_endpoint_xfer_control(&urb->ep->desc)
-			&& !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP))
-			urb->setup_dma = dma_map_single (
+	if (is_root_hub(urb->dev))
+		return 0;
+
+	if (usb_endpoint_xfer_control(&urb->ep->desc)
+	    && !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP)) {
+		if (hcd->self.uses_dma)
+			urb->setup_dma = dma_map_single(
 					hcd->self.controller,
 					urb->setup_packet,
-					sizeof (struct usb_ctrlrequest),
+					sizeof(struct usb_ctrlrequest),
 					DMA_TO_DEVICE);
-		if (urb->transfer_buffer_length != 0
-			&& !(urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP))
+		else if (hcd->driver->flags & HCD_LOCAL_MEM)
+			ret = hcd_alloc_coherent(
+					urb->dev->bus, mem_flags,
+					&urb->setup_dma,
+					(void **)&urb->setup_packet,
+					sizeof(struct usb_ctrlrequest),
+					DMA_TO_DEVICE);
+	}
+
+	dir = usb_urb_dir_in(urb) ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
+	if (ret == 0 && urb->transfer_buffer_length != 0
+	    && !(urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP)) {
+		if (hcd->self.uses_dma)
 			urb->transfer_dma = dma_map_single (
 					hcd->self.controller,
 					urb->transfer_buffer,
 					urb->transfer_buffer_length,
-					usb_urb_dir_in(urb)
-					    ? DMA_FROM_DEVICE
-					    : DMA_TO_DEVICE);
+					dir);
+		else if (hcd->driver->flags & HCD_LOCAL_MEM) {
+			ret = hcd_alloc_coherent(
+					urb->dev->bus, mem_flags,
+					&urb->transfer_dma,
+					&urb->transfer_buffer,
+					urb->transfer_buffer_length,
+					dir);
+
+			if (ret && usb_endpoint_xfer_control(&urb->ep->desc)
+			    && !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP))
+				hcd_free_coherent(urb->dev->bus,
+					&urb->setup_dma,
+					(void **)&urb->setup_packet,
+					sizeof(struct usb_ctrlrequest),
+					DMA_TO_DEVICE);
+		}
 	}
+	return ret;
 }
 
 static void unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb)
 {
-	if (hcd->self.uses_dma && !is_root_hub(urb->dev)) {
-		if (usb_endpoint_xfer_control(&urb->ep->desc)
-			&& !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP))
+	enum dma_data_direction dir;
+
+	if (is_root_hub(urb->dev))
+		return;
+
+	if (usb_endpoint_xfer_control(&urb->ep->desc)
+	    && !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP)) {
+		if (hcd->self.uses_dma)
 			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))
+		else if (hcd->driver->flags & HCD_LOCAL_MEM)
+			hcd_free_coherent(urb->dev->bus, &urb->setup_dma,
+					(void **)&urb->setup_packet,
+					sizeof(struct usb_ctrlrequest),
+					DMA_TO_DEVICE);
+	}
+
+	dir = usb_urb_dir_in(urb) ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
+	if (urb->transfer_buffer_length != 0
+	    && !(urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP)) {
+		if (hcd->self.uses_dma)
 			dma_unmap_single(hcd->self.controller,
 					urb->transfer_dma,
 					urb->transfer_buffer_length,
-					usb_urb_dir_in(urb)
-					    ? DMA_FROM_DEVICE
-					    : DMA_TO_DEVICE);
+					dir);
+		else if (hcd->driver->flags & HCD_LOCAL_MEM)
+			hcd_free_coherent(urb->dev->bus, &urb->transfer_dma,
+					&urb->transfer_buffer,
+					urb->transfer_buffer_length,
+					dir);
 	}
 }
 
@@ -1185,7 +1315,12 @@
 	 * URBs must be submitted in process context with interrupts
 	 * enabled.
 	 */
-	map_urb_for_dma(hcd, urb);
+	status = map_urb_for_dma(hcd, urb, mem_flags);
+	if (unlikely(status)) {
+		usbmon_urb_submit_error(&hcd->self, urb, status);
+		goto error;
+	}
+
 	if (is_root_hub(urb->dev))
 		status = rh_urb_enqueue(hcd, urb);
 	else
@@ -1194,6 +1329,7 @@
 	if (unlikely(status)) {
 		usbmon_urb_submit_error(&hcd->self, urb, status);
 		unmap_urb_for_dma(hcd, urb);
+ error:
 		urb->hcpriv = NULL;
 		INIT_LIST_HEAD(&urb->urb_list);
 		atomic_dec(&urb->use_count);
@@ -1291,7 +1427,7 @@
 		wake_up (&usb_kill_urb_queue);
 	usb_put_urb (urb);
 }
-EXPORT_SYMBOL (usb_hcd_giveback_urb);
+EXPORT_SYMBOL_GPL(usb_hcd_giveback_urb);
 
 /*-------------------------------------------------------------------------*/
 
@@ -1531,7 +1667,7 @@
 		mod_timer(&hcd->rh_timer, jiffies + msecs_to_jiffies(10));
 	return status;
 }
-EXPORT_SYMBOL (usb_bus_start_enum);
+EXPORT_SYMBOL_GPL(usb_bus_start_enum);
 
 #endif
 
@@ -1638,7 +1774,7 @@
 			"USB Host Controller";
 	return hcd;
 }
-EXPORT_SYMBOL (usb_create_hcd);
+EXPORT_SYMBOL_GPL(usb_create_hcd);
 
 static void hcd_release (struct kref *kref)
 {
@@ -1653,14 +1789,14 @@
 		kref_get (&hcd->kref);
 	return hcd;
 }
-EXPORT_SYMBOL (usb_get_hcd);
+EXPORT_SYMBOL_GPL(usb_get_hcd);
 
 void usb_put_hcd (struct usb_hcd *hcd)
 {
 	if (hcd)
 		kref_put (&hcd->kref, hcd_release);
 }
-EXPORT_SYMBOL (usb_put_hcd);
+EXPORT_SYMBOL_GPL(usb_put_hcd);
 
 /**
  * usb_add_hcd - finish generic HCD structure initialization and register
@@ -1786,7 +1922,7 @@
 	hcd_buffer_destroy(hcd);
 	return retval;
 } 
-EXPORT_SYMBOL (usb_add_hcd);
+EXPORT_SYMBOL_GPL(usb_add_hcd);
 
 /**
  * usb_remove_hcd - shutdown processing for generic HCDs
@@ -1828,7 +1964,7 @@
 	usb_deregister_bus(&hcd->self);
 	hcd_buffer_destroy(hcd);
 }
-EXPORT_SYMBOL (usb_remove_hcd);
+EXPORT_SYMBOL_GPL(usb_remove_hcd);
 
 void
 usb_hcd_platform_shutdown(struct platform_device* dev)
@@ -1838,7 +1974,7 @@
 	if (hcd->driver->shutdown)
 		hcd->driver->shutdown(hcd);
 }
-EXPORT_SYMBOL (usb_hcd_platform_shutdown);
+EXPORT_SYMBOL_GPL(usb_hcd_platform_shutdown);
 
 /*-------------------------------------------------------------------------*/
 
diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h
index 98e2419..2d1c3d5e 100644
--- a/drivers/usb/core/hcd.h
+++ b/drivers/usb/core/hcd.h
@@ -125,7 +125,7 @@
 
 	/* more shared queuing code would be good; it should support
 	 * smarter scheduling, handle transaction translators, etc;
-	 * input size of periodic table to an interrupt scheduler. 
+	 * input size of periodic table to an interrupt scheduler.
 	 * (ohci 32, uhci 1024, ehci 256/512/1024).
 	 */
 
@@ -133,16 +133,16 @@
 	 * this structure.
 	 */
 	unsigned long hcd_priv[0]
-			__attribute__ ((aligned (sizeof(unsigned long))));
+			__attribute__ ((aligned(sizeof(unsigned long))));
 };
 
 /* 2.4 does this a bit differently ... */
-static inline struct usb_bus *hcd_to_bus (struct usb_hcd *hcd)
+static inline struct usb_bus *hcd_to_bus(struct usb_hcd *hcd)
 {
 	return &hcd->self;
 }
 
-static inline struct usb_hcd *bus_to_hcd (struct usb_bus *bus)
+static inline struct usb_hcd *bus_to_hcd(struct usb_bus *bus)
 {
 	return container_of(bus, struct usb_hcd, self);
 }
@@ -165,6 +165,7 @@
 
 	int	flags;
 #define	HCD_MEMORY	0x0001		/* HC regs use memory (else I/O) */
+#define	HCD_LOCAL_MEM	0x0002		/* HC needs local memory */
 #define	HCD_USB11	0x0010		/* USB 1.1 */
 #define	HCD_USB2	0x0020		/* USB 2.0 */
 
@@ -201,15 +202,18 @@
 			struct usb_host_endpoint *ep);
 
 	/* root hub support */
-	int		(*hub_status_data) (struct usb_hcd *hcd, char *buf);
-	int		(*hub_control) (struct usb_hcd *hcd,
+	int	(*hub_status_data) (struct usb_hcd *hcd, char *buf);
+	int	(*hub_control) (struct usb_hcd *hcd,
 				u16 typeReq, u16 wValue, u16 wIndex,
 				char *buf, u16 wLength);
-	int		(*bus_suspend)(struct usb_hcd *);
-	int		(*bus_resume)(struct usb_hcd *);
-	int		(*start_port_reset)(struct usb_hcd *, unsigned port_num);
-	void		(*hub_irq_enable)(struct usb_hcd *);
+	int	(*bus_suspend)(struct usb_hcd *);
+	int	(*bus_resume)(struct usb_hcd *);
+	int	(*start_port_reset)(struct usb_hcd *, unsigned port_num);
+	void	(*hub_irq_enable)(struct usb_hcd *);
 		/* Needed only if port-change IRQs are level-triggered */
+
+		/* force handover of high-speed port to full-speed companion */
+	void	(*relinquish_port)(struct usb_hcd *, int);
 };
 
 extern int usb_hcd_link_urb_to_ep(struct usb_hcd *hcd, struct urb *urb);
@@ -217,56 +221,56 @@
 		int status);
 extern void usb_hcd_unlink_urb_from_ep(struct usb_hcd *hcd, struct urb *urb);
 
-extern int usb_hcd_submit_urb (struct urb *urb, gfp_t mem_flags);
-extern int usb_hcd_unlink_urb (struct urb *urb, int status);
+extern int usb_hcd_submit_urb(struct urb *urb, gfp_t mem_flags);
+extern int usb_hcd_unlink_urb(struct urb *urb, int status);
 extern void usb_hcd_giveback_urb(struct usb_hcd *hcd, struct urb *urb,
 		int status);
 extern void usb_hcd_flush_endpoint(struct usb_device *udev,
 		struct usb_host_endpoint *ep);
 extern void usb_hcd_disable_endpoint(struct usb_device *udev,
 		struct usb_host_endpoint *ep);
-extern int usb_hcd_get_frame_number (struct usb_device *udev);
+extern int usb_hcd_get_frame_number(struct usb_device *udev);
 
-extern struct usb_hcd *usb_create_hcd (const struct hc_driver *driver,
+extern struct usb_hcd *usb_create_hcd(const struct hc_driver *driver,
 		struct device *dev, char *bus_name);
-extern struct usb_hcd *usb_get_hcd (struct usb_hcd *hcd);
-extern void usb_put_hcd (struct usb_hcd *hcd);
+extern struct usb_hcd *usb_get_hcd(struct usb_hcd *hcd);
+extern void usb_put_hcd(struct usb_hcd *hcd);
 extern int usb_add_hcd(struct usb_hcd *hcd,
 		unsigned int irqnum, unsigned long irqflags);
 extern void usb_remove_hcd(struct usb_hcd *hcd);
 
 struct platform_device;
-extern void usb_hcd_platform_shutdown(struct platform_device* dev);
+extern void usb_hcd_platform_shutdown(struct platform_device *dev);
 
 #ifdef CONFIG_PCI
 struct pci_dev;
 struct pci_device_id;
-extern int usb_hcd_pci_probe (struct pci_dev *dev,
+extern int usb_hcd_pci_probe(struct pci_dev *dev,
 				const struct pci_device_id *id);
-extern void usb_hcd_pci_remove (struct pci_dev *dev);
+extern void usb_hcd_pci_remove(struct pci_dev *dev);
 
 #ifdef CONFIG_PM
-extern int usb_hcd_pci_suspend (struct pci_dev *dev, pm_message_t state);
-extern int usb_hcd_pci_resume (struct pci_dev *dev);
+extern int usb_hcd_pci_suspend(struct pci_dev *dev, pm_message_t state);
+extern int usb_hcd_pci_resume(struct pci_dev *dev);
 #endif /* CONFIG_PM */
 
-extern void usb_hcd_pci_shutdown (struct pci_dev *dev);
+extern void usb_hcd_pci_shutdown(struct pci_dev *dev);
 
 #endif /* CONFIG_PCI */
 
 /* pci-ish (pdev null is ok) buffer alloc/mapping support */
-int hcd_buffer_create (struct usb_hcd *hcd);
-void hcd_buffer_destroy (struct usb_hcd *hcd);
+int hcd_buffer_create(struct usb_hcd *hcd);
+void hcd_buffer_destroy(struct usb_hcd *hcd);
 
-void *hcd_buffer_alloc (struct usb_bus *bus, size_t size,
+void *hcd_buffer_alloc(struct usb_bus *bus, size_t size,
 	gfp_t mem_flags, dma_addr_t *dma);
-void hcd_buffer_free (struct usb_bus *bus, size_t size,
+void hcd_buffer_free(struct usb_bus *bus, size_t size,
 	void *addr, dma_addr_t dma);
 
 /* generic bus glue, needed for host controllers that don't use PCI */
-extern irqreturn_t usb_hcd_irq (int irq, void *__hcd);
+extern irqreturn_t usb_hcd_irq(int irq, void *__hcd);
 
-extern void usb_hc_died (struct usb_hcd *hcd);
+extern void usb_hc_died(struct usb_hcd *hcd);
 extern void usb_hcd_poll_rh_status(struct usb_hcd *hcd);
 
 /* -------------------------------------------------------------------------- */
@@ -319,9 +323,9 @@
  * Generic bandwidth allocation constants/support
  */
 #define FRAME_TIME_USECS	1000L
-#define BitTime(bytecount)  (7 * 8 * bytecount / 6)  /* with integer truncation */
+#define BitTime(bytecount) (7 * 8 * bytecount / 6) /* with integer truncation */
 		/* Trying not to use worst-case bit-stuffing
-                   of (7/6 * 8 * bytecount) = 9.33 * bytecount */
+		 * of (7/6 * 8 * bytecount) = 9.33 * bytecount */
 		/* bytecount = data payload byte count */
 
 #define NS_TO_US(ns)	((ns + 500L) / 1000L)
@@ -333,9 +337,9 @@
  */
 #define BW_HOST_DELAY	1000L		/* nanoseconds */
 #define BW_HUB_LS_SETUP	333L		/* nanoseconds */
-                        /* 4 full-speed bit times (est.) */
+			/* 4 full-speed bit times (est.) */
 
-#define FRAME_TIME_BITS         12000L		/* frame = 1 millisecond */
+#define FRAME_TIME_BITS			12000L	/* frame = 1 millisecond */
 #define FRAME_TIME_MAX_BITS_ALLOC	(90L * FRAME_TIME_BITS / 100L)
 #define FRAME_TIME_MAX_USECS_ALLOC	(90L * FRAME_TIME_USECS / 100L)
 
@@ -345,16 +349,16 @@
  * to preallocate bandwidth)
  */
 #define USB2_HOST_DELAY	5	/* nsec, guess */
-#define HS_NSECS(bytes) ( ((55 * 8 * 2083) \
+#define HS_NSECS(bytes) (((55 * 8 * 2083) \
 	+ (2083UL * (3 + BitTime(bytes))))/1000 \
 	+ USB2_HOST_DELAY)
-#define HS_NSECS_ISO(bytes) ( ((38 * 8 * 2083) \
+#define HS_NSECS_ISO(bytes) (((38 * 8 * 2083) \
 	+ (2083UL * (3 + BitTime(bytes))))/1000 \
 	+ USB2_HOST_DELAY)
 #define HS_USECS(bytes) NS_TO_US (HS_NSECS(bytes))
 #define HS_USECS_ISO(bytes) NS_TO_US (HS_NSECS_ISO(bytes))
 
-extern long usb_calc_bus_time (int speed, int is_input,
+extern long usb_calc_bus_time(int speed, int is_input,
 			int isoc, int bytecount);
 
 /*-------------------------------------------------------------------------*/
@@ -370,16 +374,16 @@
 extern struct mutex usb_bus_list_lock;
 extern wait_queue_head_t usb_kill_urb_queue;
 
-extern void usb_enable_root_hub_irq (struct usb_bus *bus);
+extern void usb_enable_root_hub_irq(struct usb_bus *bus);
 
-extern int usb_find_interface_driver (struct usb_device *dev,
+extern int usb_find_interface_driver(struct usb_device *dev,
 	struct usb_interface *interface);
 
 #define usb_endpoint_out(ep_dir)	(!((ep_dir) & USB_DIR_IN))
 
 #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 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_device *rhdev);
 extern int hcd_bus_resume(struct usb_device *rhdev);
 #else
@@ -399,13 +403,13 @@
  * these are expected to be called from the USB core/hub thread
  * with the kernel lock held
  */
-extern void usbfs_update_special (void);
+extern void usbfs_update_special(void);
 extern int usbfs_init(void);
 extern void usbfs_cleanup(void);
 
 #else /* CONFIG_USB_DEVICEFS */
 
-static inline void usbfs_update_special (void) {}
+static inline void usbfs_update_special(void) {}
 static inline int usbfs_init(void) { return 0; }
 static inline void usbfs_cleanup(void) { }
 
@@ -460,7 +464,7 @@
 /*-------------------------------------------------------------------------*/
 
 /* hub.h ... DeviceRemovable in 2.4.2-ac11, gone in 2.4.10 */
-// bleech -- resurfaced in 2.4.11 or 2.4.12
+/* bleech -- resurfaced in 2.4.11 or 2.4.12 */
 #define bitmap 	DeviceRemovable
 
 
@@ -468,8 +472,8 @@
 
 /* random stuff */
 
-#define	RUN_CONTEXT (in_irq () ? "in_irq" \
-		: (in_interrupt () ? "in_interrupt" : "can sleep"))
+#define	RUN_CONTEXT (in_irq() ? "in_irq" \
+		: (in_interrupt() ? "in_interrupt" : "can sleep"))
 
 
 /* This rwsem is for use only by the hub driver and ehci-hcd.
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index b04d232..68fc521 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -37,6 +37,13 @@
 #define	USB_PERSIST	0
 #endif
 
+/* if we are in debug mode, always announce new devices */
+#ifdef DEBUG
+#ifndef CONFIG_USB_ANNOUNCE_NEW_DEVICES
+#define CONFIG_USB_ANNOUNCE_NEW_DEVICES
+#endif
+#endif
+
 struct usb_hub {
 	struct device		*intfdev;	/* the "interface" device */
 	struct usb_device	*hdev;
@@ -487,6 +494,7 @@
 	schedule_work (&tt->kevent);
 	spin_unlock_irqrestore (&tt->lock, flags);
 }
+EXPORT_SYMBOL_GPL(usb_hub_tt_clear_buffer);
 
 static void hub_power_on(struct usb_hub *hub)
 {
@@ -1027,8 +1035,10 @@
 		if (udev->children[i])
 			recursively_mark_NOTATTACHED(udev->children[i]);
 	}
-	if (udev->state == USB_STATE_SUSPENDED)
+	if (udev->state == USB_STATE_SUSPENDED) {
 		udev->discon_suspended = 1;
+		udev->active_duration -= jiffies;
+	}
 	udev->state = USB_STATE_NOTATTACHED;
 }
 
@@ -1077,6 +1087,12 @@
 			else
 				device_init_wakeup(&udev->dev, 0);
 		}
+		if (udev->state == USB_STATE_SUSPENDED &&
+			new_state != USB_STATE_SUSPENDED)
+			udev->active_duration -= jiffies;
+		else if (new_state == USB_STATE_SUSPENDED &&
+				udev->state != USB_STATE_SUSPENDED)
+			udev->active_duration += jiffies;
 		udev->state = new_state;
 	} else
 		recursively_mark_NOTATTACHED(udev);
@@ -1207,7 +1223,7 @@
 	put_device(&udev->dev);
 }
 
-#ifdef DEBUG
+#ifdef CONFIG_USB_ANNOUNCE_NEW_DEVICES
 static void show_string(struct usb_device *udev, char *id, char *string)
 {
 	if (!string)
@@ -1215,12 +1231,24 @@
 	dev_printk(KERN_INFO, &udev->dev, "%s: %s\n", id, string);
 }
 
+static void announce_device(struct usb_device *udev)
+{
+	dev_info(&udev->dev, "New USB device found, idVendor=%04x, idProduct=%04x\n",
+		le16_to_cpu(udev->descriptor.idVendor),
+		le16_to_cpu(udev->descriptor.idProduct));
+	dev_info(&udev->dev, "New USB device strings: Mfr=%d, Product=%d, "
+		"SerialNumber=%d\n",
+		udev->descriptor.iManufacturer,
+		udev->descriptor.iProduct,
+		udev->descriptor.iSerialNumber);
+	show_string(udev, "Product", udev->product);
+	show_string(udev, "Manufacturer", udev->manufacturer);
+	show_string(udev, "SerialNumber", udev->serial);
+}
 #else
-static inline void show_string(struct usb_device *udev, char *id, char *string)
-{}
+static inline void announce_device(struct usb_device *udev) { }
 #endif
 
-
 #ifdef	CONFIG_USB_OTG
 #include "otg_whitelist.h"
 #endif
@@ -1390,14 +1418,7 @@
 	}
 
 	/* Tell the world! */
-	dev_dbg(&udev->dev, "new device strings: Mfr=%d, Product=%d, "
-		"SerialNumber=%d\n",
-		udev->descriptor.iManufacturer,
-		udev->descriptor.iProduct,
-		udev->descriptor.iSerialNumber);
-	show_string(udev, "Product", udev->product);
-	show_string(udev, "Manufacturer", udev->manufacturer);
-	show_string(udev, "SerialNumber", udev->serial);
+	announce_device(udev);
 	return err;
 
 fail:
@@ -2482,6 +2503,7 @@
 {
 	struct usb_device *hdev = hub->hdev;
 	struct device *hub_dev = hub->intfdev;
+	struct usb_hcd *hcd = bus_to_hcd(hdev->bus);
 	u16 wHubCharacteristics = le16_to_cpu(hub->descriptor->wHubCharacteristics);
 	int status, i;
  
@@ -2645,6 +2667,8 @@
  
 done:
 	hub_port_disable(hub, port1, 1);
+	if (hcd->driver->relinquish_port && !hub->hdev->parent)
+		hcd->driver->relinquish_port(hcd, port1);
 }
 
 static void hub_events(void)
@@ -2946,7 +2970,7 @@
 		if (len < le16_to_cpu(udev->config[index].desc.wTotalLength))
 			len = le16_to_cpu(udev->config[index].desc.wTotalLength);
 	}
-	buf = kmalloc (len, GFP_KERNEL);
+	buf = kmalloc(len, GFP_NOIO);
 	if (buf == NULL) {
 		dev_err(&udev->dev, "no mem to re-read configs after reset\n");
 		/* assume the worst */
@@ -3093,7 +3117,7 @@
 	hub_port_logical_disconnect(parent_hub, port1);
 	return -ENODEV;
 }
-EXPORT_SYMBOL(usb_reset_device);
+EXPORT_SYMBOL_GPL(usb_reset_device);
 
 /**
  * usb_reset_composite_device - warn interface drivers and perform a USB port reset
@@ -3110,16 +3134,12 @@
  * 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().
- *
- * The interface locks are acquired during the pre_reset stage and released
- * during the post_reset stage.  However if iface is not NULL and is
- * currently being probed, we assume that the caller already owns its
- * lock.
  */
 int usb_reset_composite_device(struct usb_device *udev,
 		struct usb_interface *iface)
 {
 	int ret;
+	int i;
 	struct usb_host_config *config = udev->actconfig;
 
 	if (udev->state == USB_STATE_NOTATTACHED ||
@@ -3136,16 +3156,11 @@
 		iface = NULL;
 
 	if (config) {
-		int i;
-		struct usb_interface *cintf;
-		struct usb_driver *drv;
-
 		for (i = 0; i < config->desc.bNumInterfaces; ++i) {
-			cintf = config->interface[i];
-			if (cintf != iface)
-				down(&cintf->dev.sem);
-			if (device_is_registered(&cintf->dev) &&
-					cintf->dev.driver) {
+			struct usb_interface *cintf = config->interface[i];
+			struct usb_driver *drv;
+
+			if (cintf->dev.driver) {
 				drv = to_usb_driver(cintf->dev.driver);
 				if (drv->pre_reset)
 					(drv->pre_reset)(cintf);
@@ -3157,25 +3172,20 @@
 	ret = usb_reset_device(udev);
 
 	if (config) {
-		int i;
-		struct usb_interface *cintf;
-		struct usb_driver *drv;
-
 		for (i = config->desc.bNumInterfaces - 1; i >= 0; --i) {
-			cintf = config->interface[i];
-			if (device_is_registered(&cintf->dev) &&
-					cintf->dev.driver) {
+			struct usb_interface *cintf = config->interface[i];
+			struct usb_driver *drv;
+
+			if (cintf->dev.driver) {
 				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);
 		}
 	}
 
 	usb_autosuspend_device(udev);
 	return ret;
 }
-EXPORT_SYMBOL(usb_reset_composite_device);
+EXPORT_SYMBOL_GPL(usb_reset_composite_device);
diff --git a/drivers/usb/core/hub.h b/drivers/usb/core/hub.h
index cf9559c..1551aed 100644
--- a/drivers/usb/core/hub.h
+++ b/drivers/usb/core/hub.h
@@ -55,16 +55,16 @@
 #define USB_PORT_FEAT_TEST              21
 #define USB_PORT_FEAT_INDICATOR         22
 
-/* 
+/*
  * Hub Status and Hub Change results
  * See USB 2.0 spec Table 11-19 and Table 11-20
  */
 struct usb_port_status {
 	__le16 wPortStatus;
-	__le16 wPortChange;	
+	__le16 wPortChange;
 } __attribute__ ((packed));
 
-/* 
+/*
  * wPortStatus bit field
  * See USB 2.0 spec Table 11-21
  */
@@ -81,7 +81,7 @@
 #define USB_PORT_STAT_INDICATOR         0x1000
 /* bits 13 to 15 are reserved */
 
-/* 
+/*
  * wPortChange bit field
  * See USB 2.0 spec Table 11-22
  * Bits 0 to 4 shown, bits 5 to 15 are reserved
@@ -93,7 +93,7 @@
 #define USB_PORT_STAT_C_RESET		0x0010
 
 /*
- * wHubCharacteristics (masks) 
+ * wHubCharacteristics (masks)
  * See USB 2.0 spec Table 11-13, offset 3
  */
 #define HUB_CHAR_LPSM		0x0003 /* D1 .. D0 */
@@ -119,8 +119,8 @@
 #define HUB_CHANGE_OVERCURRENT	0x0002
 
 
-/* 
- * Hub descriptor 
+/*
+ * Hub descriptor
  * See USB 2.0 spec Table 11-13
  */
 
@@ -134,7 +134,7 @@
 	__le16 wHubCharacteristics;
 	__u8  bPwrOn2PwrGood;
 	__u8  bHubContrCurrent;
-	    	/* add 1 bit for hub status change; round to bytes */
+		/* add 1 bit for hub status change; round to bytes */
 	__u8  DeviceRemovable[(USB_MAXCHILDREN + 1 + 7) / 8];
 	__u8  PortPwrCtrlMask[(USB_MAXCHILDREN + 1 + 7) / 8];
 } __attribute__ ((packed));
@@ -190,6 +190,6 @@
 	u16			devinfo;
 };
 
-extern void usb_hub_tt_clear_buffer (struct usb_device *dev, int pipe);
+extern void usb_hub_tt_clear_buffer(struct usb_device *dev, int pipe);
 
 #endif /* __LINUX_HUB_H */
diff --git a/drivers/usb/core/inode.c b/drivers/usb/core/inode.c
index cd4f111..83a373e 100644
--- a/drivers/usb/core/inode.c
+++ b/drivers/usb/core/inode.c
@@ -38,10 +38,15 @@
 #include <linux/usbdevice_fs.h>
 #include <linux/parser.h>
 #include <linux/notifier.h>
+#include <linux/seq_file.h>
 #include <asm/byteorder.h>
 #include "usb.h"
 #include "hcd.h"
 
+#define USBFS_DEFAULT_DEVMODE (S_IWUSR | S_IRUGO)
+#define USBFS_DEFAULT_BUSMODE (S_IXUGO | S_IRUGO)
+#define USBFS_DEFAULT_LISTMODE S_IRUGO
+
 static struct super_operations usbfs_ops;
 static const struct file_operations default_file_operations;
 static struct vfsmount *usbfs_mount;
@@ -57,9 +62,33 @@
 static gid_t devgid;	/* = 0 */
 static gid_t busgid;	/* = 0 */
 static gid_t listgid;	/* = 0 */
-static umode_t devmode = S_IWUSR | S_IRUGO;
-static umode_t busmode = S_IXUGO | S_IRUGO;
-static umode_t listmode = S_IRUGO;
+static umode_t devmode = USBFS_DEFAULT_DEVMODE;
+static umode_t busmode = USBFS_DEFAULT_BUSMODE;
+static umode_t listmode = USBFS_DEFAULT_LISTMODE;
+
+static int usbfs_show_options(struct seq_file *seq, struct vfsmount *mnt)
+{
+	if (devuid != 0)
+		seq_printf(seq, ",devuid=%u", devuid);
+	if (devgid != 0)
+		seq_printf(seq, ",devgid=%u", devgid);
+	if (devmode != USBFS_DEFAULT_DEVMODE)
+		seq_printf(seq, ",devmode=%o", devmode);
+	if (busuid != 0)
+		seq_printf(seq, ",busuid=%u", busuid);
+	if (busgid != 0)
+		seq_printf(seq, ",busgid=%u", busgid);
+	if (busmode != USBFS_DEFAULT_BUSMODE)
+		seq_printf(seq, ",busmode=%o", busmode);
+	if (listuid != 0)
+		seq_printf(seq, ",listuid=%u", listuid);
+	if (listgid != 0)
+		seq_printf(seq, ",listgid=%u", listgid);
+	if (listmode != USBFS_DEFAULT_LISTMODE)
+		seq_printf(seq, ",listmode=%o", listmode);
+
+	return 0;
+}
 
 enum {
 	Opt_devuid, Opt_devgid, Opt_devmode,
@@ -93,9 +122,9 @@
 	devgid = 0;
 	busgid = 0;
 	listgid = 0;
-	devmode = S_IWUSR | S_IRUGO;
-	busmode = S_IXUGO | S_IRUGO;
-	listmode = S_IRUGO;
+	devmode = USBFS_DEFAULT_DEVMODE;
+	busmode = USBFS_DEFAULT_BUSMODE;
+	listmode = USBFS_DEFAULT_LISTMODE;
 
 	while ((p = strsep(&data, ",")) != NULL) {
 		substring_t args[MAX_OPT_ARGS];
@@ -418,6 +447,7 @@
 	.statfs =	simple_statfs,
 	.drop_inode =	generic_delete_inode,
 	.remount_fs =	remount,
+	.show_options = usbfs_show_options,
 };
 
 static int usbfs_fill_super(struct super_block *sb, void *data, int silent)
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index fcd40ec..fefb922 100644
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -39,7 +39,7 @@
  * own interruptible routines.
  */
 static int usb_start_wait_urb(struct urb *urb, int timeout, int *actual_length)
-{ 
+{
 	struct api_context ctx;
 	unsigned long expire;
 	int retval;
@@ -74,9 +74,9 @@
 }
 
 /*-------------------------------------------------------------------*/
-// returns status (negative) or length (positive)
+/* returns status (negative) or length (positive) */
 static int usb_internal_control_msg(struct usb_device *usb_dev,
-				    unsigned int pipe, 
+				    unsigned int pipe,
 				    struct usb_ctrlrequest *cmd,
 				    void *data, int len, int timeout)
 {
@@ -87,7 +87,7 @@
 	urb = usb_alloc_urb(0, GFP_NOIO);
 	if (!urb)
 		return -ENOMEM;
-  
+
 	usb_fill_control_urb(urb, usb_dev, pipe, (unsigned char *)cmd, data,
 			     len, usb_api_blocking_completion, NULL);
 
@@ -99,47 +99,51 @@
 }
 
 /**
- *	usb_control_msg - Builds a control urb, sends it off and waits for completion
- *	@dev: pointer to the usb device to send the message to
- *	@pipe: endpoint "pipe" to send the message to
- *	@request: USB message request value
- *	@requesttype: USB message request type value
- *	@value: USB message value
- *	@index: USB message index value
- *	@data: pointer to the data to send
- *	@size: length in bytes of the data to send
- *	@timeout: time in msecs to wait for the message to complete before
- *		timing out (if 0 the wait is forever)
- *	Context: !in_interrupt ()
+ * usb_control_msg - Builds a control urb, sends it off and waits for completion
+ * @dev: pointer to the usb device to send the message to
+ * @pipe: endpoint "pipe" to send the message to
+ * @request: USB message request value
+ * @requesttype: USB message request type value
+ * @value: USB message value
+ * @index: USB message index value
+ * @data: pointer to the data to send
+ * @size: length in bytes of the data to send
+ * @timeout: time in msecs to wait for the message to complete before timing
+ *	out (if 0 the wait is forever)
  *
- *	This function sends a simple control message to a specified endpoint
- *	and waits for the message to complete, or timeout.
- *	
- *	If successful, it returns the number of bytes transferred, otherwise a negative error number.
+ * Context: !in_interrupt ()
  *
- *	Don't use this function from within an interrupt context, like a
- *	bottom half handler.  If you need an asynchronous message, or need to send
- *	a message from within interrupt context, use usb_submit_urb()
- *      If a thread in your driver uses this call, make sure your disconnect()
- *      method can wait for it to complete.  Since you don't have a handle on
- *      the URB used, you can't cancel the request.
+ * This function sends a simple control message to a specified endpoint and
+ * waits for the message to complete, or timeout.
+ *
+ * If successful, it returns the number of bytes transferred, otherwise a
+ * negative error number.
+ *
+ * Don't use this function from within an interrupt context, like a bottom half
+ * handler.  If you need an asynchronous message, or need to send a message
+ * from within interrupt context, use usb_submit_urb().
+ * If a thread in your driver uses this call, make sure your disconnect()
+ * method can wait for it to complete.  Since you don't have a handle on the
+ * URB used, you can't cancel the request.
  */
-int usb_control_msg(struct usb_device *dev, unsigned int pipe, __u8 request, __u8 requesttype,
-			 __u16 value, __u16 index, void *data, __u16 size, int timeout)
+int usb_control_msg(struct usb_device *dev, unsigned int pipe, __u8 request,
+		    __u8 requesttype, __u16 value, __u16 index, void *data,
+		    __u16 size, int timeout)
 {
-	struct usb_ctrlrequest *dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_NOIO);
+	struct usb_ctrlrequest *dr;
 	int ret;
-	
+
+	dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_NOIO);
 	if (!dr)
 		return -ENOMEM;
 
-	dr->bRequestType= requesttype;
+	dr->bRequestType = requesttype;
 	dr->bRequest = request;
 	dr->wValue = cpu_to_le16p(&value);
 	dr->wIndex = cpu_to_le16p(&index);
 	dr->wLength = cpu_to_le16p(&size);
 
-	//dbg("usb_control_msg");	
+	/* dbg("usb_control_msg"); */
 
 	ret = usb_internal_control_msg(dev, pipe, dr, data, size, timeout);
 
@@ -147,7 +151,7 @@
 
 	return ret;
 }
-
+EXPORT_SYMBOL_GPL(usb_control_msg);
 
 /**
  * usb_interrupt_msg - Builds an interrupt urb, sends it off and waits for completion
@@ -155,9 +159,11 @@
  * @pipe: endpoint "pipe" to send the message to
  * @data: pointer to the data to send
  * @len: length in bytes of the data to send
- * @actual_length: pointer to a location to put the actual length transferred in bytes
+ * @actual_length: pointer to a location to put the actual length transferred
+ *	in bytes
  * @timeout: time in msecs to wait for the message to complete before
  *	timing out (if 0 the wait is forever)
+ *
  * Context: !in_interrupt ()
  *
  * This function sends a simple interrupt message to a specified endpoint and
@@ -181,38 +187,38 @@
 EXPORT_SYMBOL_GPL(usb_interrupt_msg);
 
 /**
- *	usb_bulk_msg - Builds a bulk urb, sends it off and waits for completion
- *	@usb_dev: pointer to the usb device to send the message to
- *	@pipe: endpoint "pipe" to send the message to
- *	@data: pointer to the data to send
- *	@len: length in bytes of the data to send
- *	@actual_length: pointer to a location to put the actual length transferred in bytes
- *	@timeout: time in msecs to wait for the message to complete before
- *		timing out (if 0 the wait is forever)
- *	Context: !in_interrupt ()
+ * usb_bulk_msg - Builds a bulk urb, sends it off and waits for completion
+ * @usb_dev: pointer to the usb device to send the message to
+ * @pipe: endpoint "pipe" to send the message to
+ * @data: pointer to the data to send
+ * @len: length in bytes of the data to send
+ * @actual_length: pointer to a location to put the actual length transferred
+ *	in bytes
+ * @timeout: time in msecs to wait for the message to complete before
+ *	timing out (if 0 the wait is forever)
  *
- *	This function sends a simple bulk message to a specified endpoint
- *	and waits for the message to complete, or timeout.
- *	
- *	If successful, it returns 0, otherwise a negative error number.
- *	The number of actual bytes transferred will be stored in the 
- *	actual_length paramater.
+ * Context: !in_interrupt ()
  *
- *	Don't use this function from within an interrupt context, like a
- *	bottom half handler.  If you need an asynchronous message, or need to
- *	send a message from within interrupt context, use usb_submit_urb()
- *      If a thread in your driver uses this call, make sure your disconnect()
- *      method can wait for it to complete.  Since you don't have a handle on
- *      the URB used, you can't cancel the request.
+ * This function sends a simple bulk message to a specified endpoint
+ * and waits for the message to complete, or timeout.
  *
- *	Because there is no usb_interrupt_msg() and no USBDEVFS_INTERRUPT
- *	ioctl, users are forced to abuse this routine by using it to submit
- *	URBs for interrupt endpoints.  We will take the liberty of creating
- *	an interrupt URB (with the default interval) if the target is an
- *	interrupt endpoint.
+ * If successful, it returns 0, otherwise a negative error number.  The number
+ * of actual bytes transferred will be stored in the actual_length paramater.
+ *
+ * Don't use this function from within an interrupt context, like a bottom half
+ * handler.  If you need an asynchronous message, or need to send a message
+ * from within interrupt context, use usb_submit_urb() If a thread in your
+ * driver uses this call, make sure your disconnect() method can wait for it to
+ * complete.  Since you don't have a handle on the URB used, you can't cancel
+ * the request.
+ *
+ * Because there is no usb_interrupt_msg() and no USBDEVFS_INTERRUPT ioctl,
+ * users are forced to abuse this routine by using it to submit URBs for
+ * interrupt endpoints.  We will take the liberty of creating an interrupt URB
+ * (with the default interval) if the target is an interrupt endpoint.
  */
-int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe, 
-			void *data, int len, int *actual_length, int timeout)
+int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe,
+		 void *data, int len, int *actual_length, int timeout)
 {
 	struct urb *urb;
 	struct usb_host_endpoint *ep;
@@ -238,29 +244,30 @@
 
 	return usb_start_wait_urb(urb, timeout, actual_length);
 }
+EXPORT_SYMBOL_GPL(usb_bulk_msg);
 
 /*-------------------------------------------------------------------*/
 
-static void sg_clean (struct usb_sg_request *io)
+static void sg_clean(struct usb_sg_request *io)
 {
 	if (io->urbs) {
 		while (io->entries--)
-			usb_free_urb (io->urbs [io->entries]);
-		kfree (io->urbs);
+			usb_free_urb(io->urbs [io->entries]);
+		kfree(io->urbs);
 		io->urbs = NULL;
 	}
 	if (io->dev->dev.dma_mask != NULL)
-		usb_buffer_unmap_sg (io->dev, usb_pipein(io->pipe),
-				io->sg, io->nents);
+		usb_buffer_unmap_sg(io->dev, usb_pipein(io->pipe),
+				    io->sg, io->nents);
 	io->dev = NULL;
 }
 
-static void sg_complete (struct urb *urb)
+static void sg_complete(struct urb *urb)
 {
-	struct usb_sg_request	*io = urb->context;
+	struct usb_sg_request *io = urb->context;
 	int status = urb->status;
 
-	spin_lock (&io->lock);
+	spin_lock(&io->lock);
 
 	/* In 2.5 we require hcds' endpoint queues not to progress after fault
 	 * reports, until the completion callback (this!) returns.  That lets
@@ -276,13 +283,13 @@
 			&& (io->status != -ECONNRESET
 				|| status != -ECONNRESET)
 			&& urb->actual_length) {
-		dev_err (io->dev->bus->controller,
+		dev_err(io->dev->bus->controller,
 			"dev %s ep%d%s scatterlist error %d/%d\n",
 			io->dev->devpath,
 			usb_endpoint_num(&urb->ep->desc),
 			usb_urb_dir_in(urb) ? "in" : "out",
 			status, io->status);
-		// BUG ();
+		/* BUG (); */
 	}
 
 	if (io->status == 0 && status && status != -ECONNRESET) {
@@ -294,22 +301,22 @@
 		 * unlink pending urbs so they won't rx/tx bad data.
 		 * careful: unlink can sometimes be synchronous...
 		 */
-		spin_unlock (&io->lock);
+		spin_unlock(&io->lock);
 		for (i = 0, found = 0; i < io->entries; i++) {
 			if (!io->urbs [i] || !io->urbs [i]->dev)
 				continue;
 			if (found) {
-				retval = usb_unlink_urb (io->urbs [i]);
+				retval = usb_unlink_urb(io->urbs [i]);
 				if (retval != -EINPROGRESS &&
 				    retval != -ENODEV &&
 				    retval != -EBUSY)
-					dev_err (&io->dev->dev,
+					dev_err(&io->dev->dev,
 						"%s, unlink --> %d\n",
 						__FUNCTION__, retval);
 			} else if (urb == io->urbs [i])
 				found = 1;
 		}
-		spin_lock (&io->lock);
+		spin_lock(&io->lock);
 	}
 	urb->dev = NULL;
 
@@ -317,9 +324,9 @@
 	io->bytes += urb->actual_length;
 	io->count--;
 	if (!io->count)
-		complete (&io->complete);
+		complete(&io->complete);
 
-	spin_unlock (&io->lock);
+	spin_unlock(&io->lock);
 }
 
 
@@ -348,28 +355,21 @@
  * The request may be canceled with usb_sg_cancel(), either before or after
  * usb_sg_wait() is called.
  */
-int usb_sg_init (
-	struct usb_sg_request	*io,
-	struct usb_device	*dev,
-	unsigned		pipe, 
-	unsigned		period,
-	struct scatterlist	*sg,
-	int			nents,
-	size_t			length,
-	gfp_t			mem_flags
-)
+int usb_sg_init(struct usb_sg_request *io, struct usb_device *dev,
+		unsigned pipe, unsigned	period, struct scatterlist *sg,
+		int nents, size_t length, gfp_t mem_flags)
 {
-	int			i;
-	int			urb_flags;
-	int			dma;
+	int i;
+	int urb_flags;
+	int dma;
 
 	if (!io || !dev || !sg
-			|| usb_pipecontrol (pipe)
-			|| usb_pipeisoc (pipe)
+			|| usb_pipecontrol(pipe)
+			|| usb_pipeisoc(pipe)
 			|| nents <= 0)
 		return -EINVAL;
 
-	spin_lock_init (&io->lock);
+	spin_lock_init(&io->lock);
 	io->dev = dev;
 	io->pipe = pipe;
 	io->sg = sg;
@@ -381,7 +381,7 @@
 	dma = (dev->dev.dma_mask != NULL);
 	if (dma)
 		io->entries = usb_buffer_map_sg(dev, usb_pipein(pipe),
-				sg, nents);
+						sg, nents);
 	else
 		io->entries = nents;
 
@@ -390,30 +390,30 @@
 		return io->entries;
 
 	io->count = io->entries;
-	io->urbs = kmalloc (io->entries * sizeof *io->urbs, mem_flags);
+	io->urbs = kmalloc(io->entries * sizeof *io->urbs, mem_flags);
 	if (!io->urbs)
 		goto nomem;
 
 	urb_flags = URB_NO_TRANSFER_DMA_MAP | URB_NO_INTERRUPT;
-	if (usb_pipein (pipe))
+	if (usb_pipein(pipe))
 		urb_flags |= URB_SHORT_NOT_OK;
 
 	for (i = 0; i < io->entries; i++) {
-		unsigned		len;
+		unsigned len;
 
-		io->urbs [i] = usb_alloc_urb (0, mem_flags);
-		if (!io->urbs [i]) {
+		io->urbs[i] = usb_alloc_urb(0, mem_flags);
+		if (!io->urbs[i]) {
 			io->entries = i;
 			goto nomem;
 		}
 
-		io->urbs [i]->dev = NULL;
-		io->urbs [i]->pipe = pipe;
-		io->urbs [i]->interval = period;
-		io->urbs [i]->transfer_flags = urb_flags;
+		io->urbs[i]->dev = NULL;
+		io->urbs[i]->pipe = pipe;
+		io->urbs[i]->interval = period;
+		io->urbs[i]->transfer_flags = urb_flags;
 
-		io->urbs [i]->complete = sg_complete;
-		io->urbs [i]->context = io;
+		io->urbs[i]->complete = sg_complete;
+		io->urbs[i]->context = io;
 
 		/*
 		 * Some systems need to revert to PIO when DMA is temporarily
@@ -432,8 +432,8 @@
 		 * to prevent stale pointers and to help spot bugs.
 		 */
 		if (dma) {
-			io->urbs [i]->transfer_dma = sg_dma_address (sg + i);
-			len = sg_dma_len (sg + i);
+			io->urbs[i]->transfer_dma = sg_dma_address(sg + i);
+			len = sg_dma_len(sg + i);
 #if defined(CONFIG_HIGHMEM) || defined(CONFIG_GART_IOMMU)
 			io->urbs[i]->transfer_buffer = NULL;
 #else
@@ -441,31 +441,31 @@
 #endif
 		} else {
 			/* hc may use _only_ transfer_buffer */
-			io->urbs [i]->transfer_buffer = sg_virt(&sg[i]);
-			len = sg [i].length;
+			io->urbs[i]->transfer_buffer = sg_virt(&sg[i]);
+			len = sg[i].length;
 		}
 
 		if (length) {
-			len = min_t (unsigned, len, length);
+			len = min_t(unsigned, len, length);
 			length -= len;
 			if (length == 0)
 				io->entries = i + 1;
 		}
-		io->urbs [i]->transfer_buffer_length = len;
+		io->urbs[i]->transfer_buffer_length = len;
 	}
-	io->urbs [--i]->transfer_flags &= ~URB_NO_INTERRUPT;
+	io->urbs[--i]->transfer_flags &= ~URB_NO_INTERRUPT;
 
 	/* transaction state */
 	io->status = 0;
 	io->bytes = 0;
-	init_completion (&io->complete);
+	init_completion(&io->complete);
 	return 0;
 
 nomem:
-	sg_clean (io);
+	sg_clean(io);
 	return -ENOMEM;
 }
-
+EXPORT_SYMBOL_GPL(usb_sg_init);
 
 /**
  * usb_sg_wait - synchronously execute scatter/gather request
@@ -506,31 +506,32 @@
  * speed interrupt endpoints, which allow at most one packet per millisecond,
  * of at most 8 or 64 bytes (respectively).
  */
-void usb_sg_wait (struct usb_sg_request *io)
+void usb_sg_wait(struct usb_sg_request *io)
 {
-	int		i, entries = io->entries;
+	int i;
+	int entries = io->entries;
 
 	/* queue the urbs.  */
-	spin_lock_irq (&io->lock);
+	spin_lock_irq(&io->lock);
 	i = 0;
 	while (i < entries && !io->status) {
-		int	retval;
+		int retval;
 
-		io->urbs [i]->dev = io->dev;
-		retval = usb_submit_urb (io->urbs [i], GFP_ATOMIC);
+		io->urbs[i]->dev = io->dev;
+		retval = usb_submit_urb(io->urbs [i], GFP_ATOMIC);
 
 		/* after we submit, let completions or cancelations fire;
 		 * we handshake using io->status.
 		 */
-		spin_unlock_irq (&io->lock);
+		spin_unlock_irq(&io->lock);
 		switch (retval) {
 			/* maybe we retrying will recover */
-		case -ENXIO:	// hc didn't queue this one
+		case -ENXIO:	/* hc didn't queue this one */
 		case -EAGAIN:
 		case -ENOMEM:
 			io->urbs[i]->dev = NULL;
 			retval = 0;
-			yield ();
+			yield();
 			break;
 
 			/* no error? continue immediately.
@@ -541,34 +542,35 @@
 			 */
 		case 0:
 			++i;
-			cpu_relax ();
+			cpu_relax();
 			break;
 
 			/* fail any uncompleted urbs */
 		default:
-			io->urbs [i]->dev = NULL;
-			io->urbs [i]->status = retval;
-			dev_dbg (&io->dev->dev, "%s, submit --> %d\n",
+			io->urbs[i]->dev = NULL;
+			io->urbs[i]->status = retval;
+			dev_dbg(&io->dev->dev, "%s, submit --> %d\n",
 				__FUNCTION__, retval);
-			usb_sg_cancel (io);
+			usb_sg_cancel(io);
 		}
-		spin_lock_irq (&io->lock);
+		spin_lock_irq(&io->lock);
 		if (retval && (io->status == 0 || io->status == -ECONNRESET))
 			io->status = retval;
 	}
 	io->count -= entries - i;
 	if (io->count == 0)
-		complete (&io->complete);
-	spin_unlock_irq (&io->lock);
+		complete(&io->complete);
+	spin_unlock_irq(&io->lock);
 
 	/* OK, yes, this could be packaged as non-blocking.
 	 * So could the submit loop above ... but it's easier to
 	 * solve neither problem than to solve both!
 	 */
-	wait_for_completion (&io->complete);
+	wait_for_completion(&io->complete);
 
-	sg_clean (io);
+	sg_clean(io);
 }
+EXPORT_SYMBOL_GPL(usb_sg_wait);
 
 /**
  * usb_sg_cancel - stop scatter/gather i/o issued by usb_sg_wait()
@@ -578,32 +580,33 @@
  * It can also prevents one initialized by usb_sg_init() from starting,
  * so that call just frees resources allocated to the request.
  */
-void usb_sg_cancel (struct usb_sg_request *io)
+void usb_sg_cancel(struct usb_sg_request *io)
 {
-	unsigned long	flags;
+	unsigned long flags;
 
-	spin_lock_irqsave (&io->lock, flags);
+	spin_lock_irqsave(&io->lock, flags);
 
 	/* shut everything down, if it didn't already */
 	if (!io->status) {
-		int	i;
+		int i;
 
 		io->status = -ECONNRESET;
-		spin_unlock (&io->lock);
+		spin_unlock(&io->lock);
 		for (i = 0; i < io->entries; i++) {
-			int	retval;
+			int retval;
 
 			if (!io->urbs [i]->dev)
 				continue;
-			retval = usb_unlink_urb (io->urbs [i]);
+			retval = usb_unlink_urb(io->urbs [i]);
 			if (retval != -EINPROGRESS && retval != -EBUSY)
-				dev_warn (&io->dev->dev, "%s, unlink --> %d\n",
+				dev_warn(&io->dev->dev, "%s, unlink --> %d\n",
 					__FUNCTION__, retval);
 		}
-		spin_lock (&io->lock);
+		spin_lock(&io->lock);
 	}
-	spin_unlock_irqrestore (&io->lock, flags);
+	spin_unlock_irqrestore(&io->lock, flags);
 }
+EXPORT_SYMBOL_GPL(usb_sg_cancel);
 
 /*-------------------------------------------------------------------*/
 
@@ -629,12 +632,13 @@
  * Returns the number of bytes received on success, or else the status code
  * returned by the underlying usb_control_msg() call.
  */
-int usb_get_descriptor(struct usb_device *dev, unsigned char type, unsigned char index, void *buf, int size)
+int usb_get_descriptor(struct usb_device *dev, unsigned char type,
+		       unsigned char index, void *buf, int size)
 {
 	int i;
 	int result;
-	
-	memset(buf,0,size);	// Make sure we parse really received data
+
+	memset(buf, 0, size);	/* Make sure we parse really received data */
 
 	for (i = 0; i < 3; ++i) {
 		/* retry on length 0 or error; some devices are flakey */
@@ -652,6 +656,7 @@
 	}
 	return result;
 }
+EXPORT_SYMBOL_GPL(usb_get_descriptor);
 
 /**
  * usb_get_string - gets a string descriptor
@@ -708,7 +713,7 @@
 }
 
 static int usb_string_sub(struct usb_device *dev, unsigned int langid,
-		unsigned int index, unsigned char *buf)
+			  unsigned int index, unsigned char *buf)
 {
 	int rc;
 
@@ -751,7 +756,7 @@
  * @buf: where to put the string
  * @size: how big is "buf"?
  * Context: !in_interrupt ()
- * 
+ *
  * This converts the UTF-16LE encoded strings returned by devices, from
  * usb_get_string_descriptor(), to null-terminated ISO-8859-1 encoded ones
  * that are more usable in most kernel contexts.  Note that all characters
@@ -787,23 +792,23 @@
 	if (!dev->have_langid) {
 		err = usb_string_sub(dev, 0, 0, tbuf);
 		if (err < 0) {
-			dev_err (&dev->dev,
+			dev_err(&dev->dev,
 				"string descriptor 0 read error: %d\n",
 				err);
 			goto errout;
 		} else if (err < 4) {
-			dev_err (&dev->dev, "string descriptor 0 too short\n");
+			dev_err(&dev->dev, "string descriptor 0 too short\n");
 			err = -EINVAL;
 			goto errout;
 		} else {
 			dev->have_langid = 1;
-			dev->string_langid = tbuf[2] | (tbuf[3]<< 8);
-				/* always use the first langid listed */
-			dev_dbg (&dev->dev, "default language 0x%04x\n",
+			dev->string_langid = tbuf[2] | (tbuf[3] << 8);
+			/* always use the first langid listed */
+			dev_dbg(&dev->dev, "default language 0x%04x\n",
 				dev->string_langid);
 		}
 	}
-	
+
 	err = usb_string_sub(dev, dev->string_langid, index, tbuf);
 	if (err < 0)
 		goto errout;
@@ -821,12 +826,15 @@
 	err = idx;
 
 	if (tbuf[1] != USB_DT_STRING)
-		dev_dbg(&dev->dev, "wrong descriptor type %02x for string %d (\"%s\")\n", tbuf[1], index, buf);
+		dev_dbg(&dev->dev,
+			"wrong descriptor type %02x for string %d (\"%s\")\n",
+			tbuf[1], index, buf);
 
  errout:
 	kfree(tbuf);
 	return err;
 }
+EXPORT_SYMBOL_GPL(usb_string);
 
 /**
  * usb_cache_string - read a string descriptor and cache it for later use
@@ -842,9 +850,15 @@
 	char *smallbuf = NULL;
 	int len;
 
-	if (index > 0 && (buf = kmalloc(256, GFP_KERNEL)) != NULL) {
-		if ((len = usb_string(udev, index, buf, 256)) > 0) {
-			if ((smallbuf = kmalloc(++len, GFP_KERNEL)) == NULL)
+	if (index <= 0)
+		return NULL;
+
+	buf = kmalloc(256, GFP_KERNEL);
+	if (buf) {
+		len = usb_string(udev, index, buf, 256);
+		if (len > 0) {
+			smallbuf = kmalloc(++len, GFP_KERNEL);
+			if (!smallbuf)
 				return buf;
 			memcpy(smallbuf, buf, len);
 		}
@@ -883,7 +897,7 @@
 		return -ENOMEM;
 
 	ret = usb_get_descriptor(dev, USB_DT_DEVICE, 0, desc, size);
-	if (ret >= 0) 
+	if (ret >= 0)
 		memcpy(&dev->descriptor, desc, size);
 	kfree(desc);
 	return ret;
@@ -927,6 +941,7 @@
 	kfree(status);
 	return ret;
 }
+EXPORT_SYMBOL_GPL(usb_get_status);
 
 /**
  * usb_clear_halt - tells device to clear endpoint halt/stall condition
@@ -955,8 +970,8 @@
 {
 	int result;
 	int endp = usb_pipeendpoint(pipe);
-	
-	if (usb_pipein (pipe))
+
+	if (usb_pipein(pipe))
 		endp |= USB_DIR_IN;
 
 	/* we don't care if it wasn't halted first. in fact some devices
@@ -985,6 +1000,7 @@
 
 	return 0;
 }
+EXPORT_SYMBOL_GPL(usb_clear_halt);
 
 /**
  * usb_disable_endpoint -- Disable an endpoint by address
@@ -1038,7 +1054,7 @@
 	}
 }
 
-/*
+/**
  * usb_disable_device - Disable all the endpoints for a USB device
  * @dev: the device whose endpoints are being disabled
  * @skip_ep0: 0 to disable endpoint 0, 1 to skip it.
@@ -1053,7 +1069,7 @@
 	int i;
 
 	dev_dbg(&dev->dev, "%s nuking %s URBs\n", __FUNCTION__,
-			skip_ep0 ? "non-ep0" : "all");
+		skip_ep0 ? "non-ep0" : "all");
 	for (i = skip_ep0; i < 16; ++i) {
 		usb_disable_endpoint(dev, i);
 		usb_disable_endpoint(dev, i + USB_DIR_IN);
@@ -1071,17 +1087,17 @@
 			interface = dev->actconfig->interface[i];
 			if (!device_is_registered(&interface->dev))
 				continue;
-			dev_dbg (&dev->dev, "unregistering interface %s\n",
+			dev_dbg(&dev->dev, "unregistering interface %s\n",
 				interface->dev.bus_id);
 			usb_remove_sysfs_intf_files(interface);
-			device_del (&interface->dev);
+			device_del(&interface->dev);
 		}
 
 		/* Now that the interfaces are unbound, nobody should
 		 * try to access them.
 		 */
 		for (i = 0; i < dev->actconfig->desc.bNumInterfaces; i++) {
-			put_device (&dev->actconfig->interface[i]->dev);
+			put_device(&dev->actconfig->interface[i]->dev);
 			dev->actconfig->interface[i] = NULL;
 		}
 		dev->actconfig = NULL;
@@ -1090,8 +1106,7 @@
 	}
 }
 
-
-/*
+/**
  * usb_enable_endpoint - Enable an endpoint for USB communications
  * @dev: the device whose interface is being enabled
  * @ep: the endpoint
@@ -1116,7 +1131,7 @@
 	ep->enabled = 1;
 }
 
-/*
+/**
  * usb_enable_interface - Enable all the endpoints for an interface
  * @dev: the device whose interface is being enabled
  * @intf: pointer to the interface descriptor
@@ -1172,6 +1187,8 @@
 	struct usb_host_interface *alt;
 	int ret;
 	int manual = 0;
+	unsigned int epaddr;
+	unsigned int pipe;
 
 	if (dev->state == USB_STATE_SUSPENDED)
 		return -EHOSTUNREACH;
@@ -1226,11 +1243,11 @@
 		int i;
 
 		for (i = 0; i < alt->desc.bNumEndpoints; i++) {
-			unsigned int epaddr =
-				alt->endpoint[i].desc.bEndpointAddress;
-			unsigned int pipe =
-	__create_pipe(dev, USB_ENDPOINT_NUMBER_MASK & epaddr)
-	| (usb_endpoint_out(epaddr) ? USB_DIR_OUT : USB_DIR_IN);
+			epaddr = alt->endpoint[i].desc.bEndpointAddress;
+			pipe = __create_pipe(dev,
+					USB_ENDPOINT_NUMBER_MASK & epaddr) |
+					(usb_endpoint_out(epaddr) ?
+					USB_DIR_OUT : USB_DIR_IN);
 
 			usb_clear_halt(dev, pipe);
 		}
@@ -1253,6 +1270,7 @@
 
 	return 0;
 }
+EXPORT_SYMBOL_GPL(usb_set_interface);
 
 /**
  * usb_reset_configuration - lightweight device reset
@@ -1328,6 +1346,7 @@
 	}
 	return 0;
 }
+EXPORT_SYMBOL_GPL(usb_reset_configuration);
 
 static void usb_release_interface(struct device *dev)
 {
@@ -1357,7 +1376,8 @@
 		return -ENOMEM;
 
 	if (add_uevent_var(env,
-		   "MODALIAS=usb:v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02Xic%02Xisc%02Xip%02X",
+		   "MODALIAS=usb:"
+		   "v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02Xic%02Xisc%02Xip%02X",
 		   le16_to_cpu(usb_dev->descriptor.idVendor),
 		   le16_to_cpu(usb_dev->descriptor.idProduct),
 		   le16_to_cpu(usb_dev->descriptor.bcdDevice),
@@ -1387,8 +1407,8 @@
 };
 
 static struct usb_interface_assoc_descriptor *find_iad(struct usb_device *dev,
-						       struct usb_host_config *config,
-						       u8 inum)
+						struct usb_host_config *config,
+						u8 inum)
 {
 	struct usb_interface_assoc_descriptor *retval = NULL;
 	struct usb_interface_assoc_descriptor *intf_assoc;
@@ -1415,7 +1435,6 @@
 	return retval;
 }
 
-
 /*
  * usb_set_configuration - Makes a particular device setting be current
  * @dev: the device whose configuration is being updated
@@ -1533,12 +1552,12 @@
 	 * getting rid of old interfaces means unbinding their drivers.
 	 */
 	if (dev->state != USB_STATE_ADDRESS)
-		usb_disable_device (dev, 1);	// Skip ep0
+		usb_disable_device(dev, 1);	/* Skip ep0 */
 
-	if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
-			USB_REQ_SET_CONFIGURATION, 0, configuration, 0,
-			NULL, 0, USB_CTRL_SET_TIMEOUT)) < 0) {
-
+	ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+			      USB_REQ_SET_CONFIGURATION, 0, configuration, 0,
+			      NULL, 0, USB_CTRL_SET_TIMEOUT);
+	if (ret < 0) {
 		/* All the old state is gone, so what else can we do?
 		 * The device is probably useless now anyway.
 		 */
@@ -1585,11 +1604,11 @@
 		intf->dev.bus = &usb_bus_type;
 		intf->dev.type = &usb_if_device_type;
 		intf->dev.dma_mask = dev->dev.dma_mask;
-		device_initialize (&intf->dev);
+		device_initialize(&intf->dev);
 		mark_quiesced(intf);
-		sprintf (&intf->dev.bus_id[0], "%d-%s:%d.%d",
-			 dev->bus->busnum, dev->devpath,
-			 configuration, alt->desc.bInterfaceNumber);
+		sprintf(&intf->dev.bus_id[0], "%d-%s:%d.%d",
+			dev->bus->busnum, dev->devpath,
+			configuration, alt->desc.bInterfaceNumber);
 	}
 	kfree(new_interfaces);
 
@@ -1605,11 +1624,11 @@
 	for (i = 0; i < nintf; ++i) {
 		struct usb_interface *intf = cp->interface[i];
 
-		dev_dbg (&dev->dev,
+		dev_dbg(&dev->dev,
 			"adding %s (config #%d, interface %d)\n",
 			intf->dev.bus_id, configuration,
 			intf->cur_altsetting->desc.bInterfaceNumber);
-		ret = device_add (&intf->dev);
+		ret = device_add(&intf->dev);
 		if (ret != 0) {
 			dev_err(&dev->dev, "device_add(%s) --> %d\n",
 				intf->dev.bus_id, ret);
@@ -1677,22 +1696,3 @@
 	return 0;
 }
 EXPORT_SYMBOL_GPL(usb_driver_set_configuration);
-
-// synchronous request completion model
-EXPORT_SYMBOL(usb_control_msg);
-EXPORT_SYMBOL(usb_bulk_msg);
-
-EXPORT_SYMBOL(usb_sg_init);
-EXPORT_SYMBOL(usb_sg_cancel);
-EXPORT_SYMBOL(usb_sg_wait);
-
-// synchronous control message convenience routines
-EXPORT_SYMBOL(usb_get_descriptor);
-EXPORT_SYMBOL(usb_get_status);
-EXPORT_SYMBOL(usb_string);
-
-// synchronous calls that also maintain usbcore state
-EXPORT_SYMBOL(usb_clear_halt);
-EXPORT_SYMBOL(usb_reset_configuration);
-EXPORT_SYMBOL(usb_set_interface);
-
diff --git a/drivers/usb/core/notify.c b/drivers/usb/core/notify.c
index 6b36897..7542dce 100644
--- a/drivers/usb/core/notify.c
+++ b/drivers/usb/core/notify.c
@@ -33,7 +33,7 @@
  * usb_unregister_notify - unregister a notifier callback
  * @nb: pointer to the notifier block for the callback events.
  *
- * usb_register_notifier() must have been previously called for this function
+ * usb_register_notify() must have been previously called for this function
  * to work properly.
  */
 void usb_unregister_notify(struct notifier_block *nb)
diff --git a/drivers/usb/core/otg_whitelist.h b/drivers/usb/core/otg_whitelist.h
index 7f31a49..e8cdce5 100644
--- a/drivers/usb/core/otg_whitelist.h
+++ b/drivers/usb/core/otg_whitelist.h
@@ -14,7 +14,7 @@
  * mostly use of USB_DEVICE() or USB_DEVICE_VER() entries..
  *
  * YOU _SHOULD_ CHANGE THIS LIST TO MATCH YOUR PRODUCT AND ITS TESTING!
- */ 
+ */
 
 static struct usb_device_id whitelist_table [] = {
 
@@ -55,7 +55,7 @@
 		return 1;
 
 	/* HNP test device is _never_ targeted (see OTG spec 6.6.6) */
-	if ((le16_to_cpu(dev->descriptor.idVendor) == 0x1a0a && 
+	if ((le16_to_cpu(dev->descriptor.idVendor) == 0x1a0a &&
 	     le16_to_cpu(dev->descriptor.idProduct) == 0xbadd))
 		return 0;
 
@@ -86,7 +86,7 @@
 			continue;
 
 		if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_SUBCLASS) &&
-		    (id->bDeviceSubClass!= dev->descriptor.bDeviceSubClass))
+		    (id->bDeviceSubClass != dev->descriptor.bDeviceSubClass))
 			continue;
 
 		if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_PROTOCOL) &&
diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c
index 32bd130..a37ccbd 100644
--- a/drivers/usb/core/sysfs.c
+++ b/drivers/usb/core/sysfs.c
@@ -72,7 +72,7 @@
 	return (value < 0) ? value : count;
 }
 
-static DEVICE_ATTR(bConfigurationValue, S_IRUGO | S_IWUSR, 
+static DEVICE_ATTR(bConfigurationValue, S_IRUGO | S_IWUSR,
 		show_bConfigurationValue, set_bConfigurationValue);
 
 /* String fields */
@@ -249,6 +249,41 @@
 #ifdef	CONFIG_USB_SUSPEND
 
 static ssize_t
+show_connected_duration(struct device *dev, struct device_attribute *attr,
+		char *buf)
+{
+	struct usb_device *udev = to_usb_device(dev);
+
+	return sprintf(buf, "%u\n",
+			jiffies_to_msecs(jiffies - udev->connect_time));
+}
+
+static DEVICE_ATTR(connected_duration, S_IRUGO, show_connected_duration, NULL);
+
+/*
+ * If the device is resumed, the last time the device was suspended has
+ * been pre-subtracted from active_duration.  We add the current time to
+ * get the duration that the device was actually active.
+ *
+ * If the device is suspended, the active_duration is up-to-date.
+ */
+static ssize_t
+show_active_duration(struct device *dev, struct device_attribute *attr,
+		char *buf)
+{
+	struct usb_device *udev = to_usb_device(dev);
+	int duration;
+
+	if (udev->state != USB_STATE_SUSPENDED)
+		duration = jiffies_to_msecs(jiffies + udev->active_duration);
+	else
+		duration = jiffies_to_msecs(udev->active_duration);
+	return sprintf(buf, "%u\n", duration);
+}
+
+static DEVICE_ATTR(active_duration, S_IRUGO, show_active_duration, NULL);
+
+static ssize_t
 show_autosuspend(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct usb_device *udev = to_usb_device(dev);
@@ -365,6 +400,14 @@
 			rc = sysfs_add_file_to_group(&dev->kobj,
 					&dev_attr_level.attr,
 					power_group);
+		if (rc == 0)
+			rc = sysfs_add_file_to_group(&dev->kobj,
+					&dev_attr_connected_duration.attr,
+					power_group);
+		if (rc == 0)
+			rc = sysfs_add_file_to_group(&dev->kobj,
+					&dev_attr_active_duration.attr,
+					power_group);
 	}
 	return rc;
 }
@@ -372,6 +415,12 @@
 static void remove_power_attributes(struct device *dev)
 {
 	sysfs_remove_file_from_group(&dev->kobj,
+			&dev_attr_active_duration.attr,
+			power_group);
+	sysfs_remove_file_from_group(&dev->kobj,
+			&dev_attr_connected_duration.attr,
+			power_group);
+	sysfs_remove_file_from_group(&dev->kobj,
 			&dev_attr_level.attr,
 			power_group);
 	sysfs_remove_file_from_group(&dev->kobj,
@@ -601,21 +650,21 @@
 /* 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,	\
+show_iad_##field(struct device *dev, struct device_attribute *attr,	\
 		char *buf)						\
 {									\
-	struct usb_interface *intf = to_usb_interface (dev);		\
+	struct usb_interface *intf = to_usb_interface(dev);		\
 									\
-	return sprintf (buf, format_string,				\
-			intf->intf_assoc->field); 		\
+	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")
+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)				\
diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c
index d05ead2..9d7e632 100644
--- a/drivers/usb/core/urb.c
+++ b/drivers/usb/core/urb.c
@@ -42,6 +42,7 @@
 		INIT_LIST_HEAD(&urb->anchor_list);
 	}
 }
+EXPORT_SYMBOL_GPL(usb_init_urb);
 
 /**
  * usb_alloc_urb - creates a new urb for a USB driver to use
@@ -73,6 +74,7 @@
 	usb_init_urb(urb);
 	return urb;
 }
+EXPORT_SYMBOL_GPL(usb_alloc_urb);
 
 /**
  * usb_free_urb - frees the memory used by a urb when all users of it are finished
@@ -89,6 +91,7 @@
 	if (urb)
 		kref_put(&urb->kref, urb_destroy);
 }
+EXPORT_SYMBOL_GPL(usb_free_urb);
 
 /**
  * usb_get_urb - increments the reference count of the urb
@@ -100,12 +103,13 @@
  *
  * A pointer to the urb with the incremented reference counter is returned.
  */
-struct urb * usb_get_urb(struct urb *urb)
+struct urb *usb_get_urb(struct urb *urb)
 {
 	if (urb)
 		kref_get(&urb->kref);
 	return urb;
 }
+EXPORT_SYMBOL_GPL(usb_get_urb);
 
 /**
  * usb_anchor_urb - anchors an URB while it is processed
@@ -172,7 +176,7 @@
  * describing that request to the USB subsystem.  Request completion will
  * be indicated later, asynchronously, by calling the completion handler.
  * The three types of completion are success, error, and unlink
- * (a software-induced fault, also called "request cancellation").  
+ * (a software-induced fault, also called "request cancellation").
  *
  * URBs may be submitted in interrupt context.
  *
@@ -255,7 +259,7 @@
  *       semaphores), or
  *   (c) current->state != TASK_RUNNING, this is the case only after
  *       you've changed it.
- * 
+ *
  * GFP_NOIO is used in the block io path and error handling of storage
  * devices.
  *
@@ -284,7 +288,8 @@
 
 	if (!urb || urb->hcpriv || !urb->complete)
 		return -EINVAL;
-	if (!(dev = urb->dev) || dev->state < USB_STATE_DEFAULT)
+	dev = urb->dev;
+	if ((!dev) || (dev->state < USB_STATE_DEFAULT))
 		return -ENODEV;
 
 	/* For now, get the endpoint from the pipe.  Eventually drivers
@@ -347,11 +352,11 @@
 			max *= mult;
 		}
 
-		if (urb->number_of_packets <= 0)		    
+		if (urb->number_of_packets <= 0)
 			return -EINVAL;
 		for (n = 0; n < urb->number_of_packets; n++) {
 			len = urb->iso_frame_desc[n].length;
-			if (len < 0 || len > max) 
+			if (len < 0 || len > max)
 				return -EMSGSIZE;
 			urb->iso_frame_desc[n].status = -EXDEV;
 			urb->iso_frame_desc[n].actual_length = 0;
@@ -416,7 +421,7 @@
 		/* too big? */
 		switch (dev->speed) {
 		case USB_SPEED_HIGH:	/* units are microframes */
-			// NOTE usb handles 2^15
+			/* NOTE usb handles 2^15 */
 			if (urb->interval > (1024 * 8))
 				urb->interval = 1024 * 8;
 			max = 1024 * 8;
@@ -426,12 +431,12 @@
 			if (xfertype == USB_ENDPOINT_XFER_INT) {
 				if (urb->interval > 255)
 					return -EINVAL;
-				// NOTE ohci only handles up to 32
+				/* NOTE ohci only handles up to 32 */
 				max = 128;
 			} else {
 				if (urb->interval > 1024)
 					urb->interval = 1024;
-				// NOTE usb and ohci handle up to 2^15
+				/* NOTE usb and ohci handle up to 2^15 */
 				max = 1024;
 			}
 			break;
@@ -444,6 +449,7 @@
 
 	return usb_hcd_submit_urb(urb, mem_flags);
 }
+EXPORT_SYMBOL_GPL(usb_submit_urb);
 
 /*-------------------------------------------------------------------*/
 
@@ -514,6 +520,7 @@
 		return -EIDRM;
 	return usb_hcd_unlink_urb(urb, -ECONNRESET);
 }
+EXPORT_SYMBOL_GPL(usb_unlink_urb);
 
 /**
  * usb_kill_urb - cancel a transfer request and wait for it to finish
@@ -553,6 +560,7 @@
 	--urb->reject;
 	mutex_unlock(&reject_mutex);
 }
+EXPORT_SYMBOL_GPL(usb_kill_urb);
 
 /**
  * usb_kill_anchored_urbs - cancel transfer requests en masse
@@ -567,7 +575,8 @@
 
 	spin_lock_irq(&anchor->lock);
 	while (!list_empty(&anchor->urb_list)) {
-		victim = list_entry(anchor->urb_list.prev, struct urb, anchor_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);
@@ -595,11 +604,3 @@
 				  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);
-EXPORT_SYMBOL(usb_get_urb);
-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 8f14237..4e98406 100644
--- a/drivers/usb/core/usb.c
+++ b/drivers/usb/core/usb.c
@@ -96,6 +96,7 @@
 
 	return NULL;
 }
+EXPORT_SYMBOL_GPL(usb_ifnum_to_if);
 
 /**
  * usb_altnum_to_altsetting - get the altsetting structure with a given
@@ -115,8 +116,9 @@
  * Don't call this function unless you are bound to the intf interface
  * or you have locked the device!
  */
-struct usb_host_interface *usb_altnum_to_altsetting(const struct usb_interface *intf,
-						    unsigned int altnum)
+struct usb_host_interface *usb_altnum_to_altsetting(
+					const struct usb_interface *intf,
+					unsigned int altnum)
 {
 	int i;
 
@@ -126,13 +128,14 @@
 	}
 	return NULL;
 }
+EXPORT_SYMBOL_GPL(usb_altnum_to_altsetting);
 
 struct find_interface_arg {
 	int minor;
 	struct usb_interface *interface;
 };
 
-static int __find_interface(struct device * dev, void * data)
+static int __find_interface(struct device *dev, void *data)
 {
 	struct find_interface_arg *arg = data;
 	struct usb_interface *intf;
@@ -154,7 +157,7 @@
  * @drv: the driver whose current configuration is considered
  * @minor: the minor number of the desired device
  *
- * This walks the driver device list and returns a pointer to the interface 
+ * This walks the driver device list and returns a pointer to the interface
  * with the matching minor.  Note, this only works for devices that share the
  * USB major number.
  */
@@ -170,6 +173,7 @@
 					__find_interface);
 	return argb.interface;
 }
+EXPORT_SYMBOL_GPL(usb_find_interface);
 
 /**
  * usb_release_dev - free a usb device structure when all users of it are finished.
@@ -230,7 +234,7 @@
 	 * singlethreaded.  Its job doesn't justify running on more
 	 * than one CPU.
 	 */
-	ksuspend_usb_wq = create_freezeable_workqueue("ksuspend_usbd");
+	ksuspend_usb_wq = create_singlethread_workqueue("ksuspend_usbd");
 	if (!ksuspend_usb_wq)
 		return -ENOMEM;
 	return 0;
@@ -269,8 +273,8 @@
  *
  * This call may not be used in a non-sleeping context.
  */
-struct usb_device *
-usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus, unsigned port1)
+struct usb_device *usb_alloc_dev(struct usb_device *parent,
+				 struct usb_bus *bus, unsigned port1)
 {
 	struct usb_device *dev;
 	struct usb_hcd *usb_hcd = container_of(bus, struct usb_hcd, self);
@@ -339,6 +343,8 @@
 	mutex_init(&dev->pm_mutex);
 	INIT_DELAYED_WORK(&dev->autosuspend, usb_autosuspend_work);
 	dev->autosuspend_delay = usb_autosuspend_delay * HZ;
+	dev->connect_time = jiffies;
+	dev->active_duration = -jiffies;
 #endif
 	if (root_hub)	/* Root hub always ok [and always wired] */
 		dev->authorized = 1;
@@ -367,6 +373,7 @@
 		get_device(&dev->dev);
 	return dev;
 }
+EXPORT_SYMBOL_GPL(usb_get_dev);
 
 /**
  * usb_put_dev - release a use of the usb device structure
@@ -380,6 +387,7 @@
 	if (dev)
 		put_device(&dev->dev);
 }
+EXPORT_SYMBOL_GPL(usb_put_dev);
 
 /**
  * usb_get_intf - increments the reference count of the usb interface structure
@@ -400,6 +408,7 @@
 		get_device(&intf->dev);
 	return intf;
 }
+EXPORT_SYMBOL_GPL(usb_get_intf);
 
 /**
  * usb_put_intf - release a use of the usb interface structure
@@ -414,7 +423,7 @@
 	if (intf)
 		put_device(&intf->dev);
 }
-
+EXPORT_SYMBOL_GPL(usb_put_intf);
 
 /*			USB device locking
  *
@@ -461,11 +470,11 @@
 		return -EHOSTUNREACH;
 	if (iface) {
 		switch (iface->condition) {
-		  case USB_INTERFACE_BINDING:
+		case USB_INTERFACE_BINDING:
 			return 0;
-		  case USB_INTERFACE_BOUND:
+		case USB_INTERFACE_BOUND:
 			break;
-		  default:
+		default:
 			return -EINTR;
 		}
 	}
@@ -487,7 +496,7 @@
 	}
 	return 1;
 }
-
+EXPORT_SYMBOL_GPL(usb_lock_device_for_reset);
 
 static struct usb_device *match_device(struct usb_device *dev,
 				       u16 vendor_id, u16 product_id)
@@ -540,10 +549,10 @@
 	struct list_head *buslist;
 	struct usb_bus *bus;
 	struct usb_device *dev = NULL;
-	
+
 	mutex_lock(&usb_bus_list_lock);
 	for (buslist = usb_bus_list.next;
-	     buslist != &usb_bus_list; 
+	     buslist != &usb_bus_list;
 	     buslist = buslist->next) {
 		bus = container_of(buslist, struct usb_bus, bus_list);
 		if (!bus->root_hub)
@@ -576,6 +585,7 @@
 {
 	return usb_hcd_get_frame_number(dev);
 }
+EXPORT_SYMBOL_GPL(usb_get_current_frame_number);
 
 /*-------------------------------------------------------------------*/
 /*
@@ -584,7 +594,7 @@
  */
 
 int __usb_get_extra_descriptor(char *buffer, unsigned size,
-	unsigned char type, void **ptr)
+			       unsigned char type, void **ptr)
 {
 	struct usb_descriptor_header *header;
 
@@ -595,7 +605,7 @@
 			printk(KERN_ERR
 				"%s: bogus descriptor, type %d length %d\n",
 				usbcore_name,
-				header->bDescriptorType, 
+				header->bDescriptorType,
 				header->bLength);
 			return -1;
 		}
@@ -610,6 +620,7 @@
 	}
 	return -1;
 }
+EXPORT_SYMBOL_GPL(__usb_get_extra_descriptor);
 
 /**
  * usb_buffer_alloc - allocate dma-consistent buffer for URB_NO_xxx_DMA_MAP
@@ -633,17 +644,14 @@
  *
  * When the buffer is no longer used, free it with usb_buffer_free().
  */
-void *usb_buffer_alloc(
-	struct usb_device *dev,
-	size_t size,
-	gfp_t mem_flags,
-	dma_addr_t *dma
-)
+void *usb_buffer_alloc(struct usb_device *dev, size_t size, gfp_t mem_flags,
+		       dma_addr_t *dma)
 {
 	if (!dev || !dev->bus)
 		return NULL;
 	return hcd_buffer_alloc(dev->bus, size, mem_flags, dma);
 }
+EXPORT_SYMBOL_GPL(usb_buffer_alloc);
 
 /**
  * usb_buffer_free - free memory allocated with usb_buffer_alloc()
@@ -656,12 +664,8 @@
  * been allocated using usb_buffer_alloc(), and the parameters must match
  * those provided in that allocation request.
  */
-void usb_buffer_free(
-	struct usb_device *dev,
-	size_t size,
-	void *addr,
-	dma_addr_t dma
-)
+void usb_buffer_free(struct usb_device *dev, size_t size, void *addr,
+		     dma_addr_t dma)
 {
 	if (!dev || !dev->bus)
 		return;
@@ -669,6 +673,7 @@
 		return;
 	hcd_buffer_free(dev->bus, size, addr, dma);
 }
+EXPORT_SYMBOL_GPL(usb_buffer_free);
 
 /**
  * usb_buffer_map - create DMA mapping(s) for an urb
@@ -708,14 +713,15 @@
 					urb->setup_packet,
 					sizeof(struct usb_ctrlrequest),
 					DMA_TO_DEVICE);
-	// FIXME generic api broken like pci, can't report errors
-	// if (urb->transfer_dma == DMA_ADDR_INVALID) return 0;
+	/* FIXME generic api broken like pci, can't report errors */
+	/* if (urb->transfer_dma == DMA_ADDR_INVALID) return 0; */
 	} else
 		urb->transfer_dma = ~0;
 	urb->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP
 				| URB_NO_SETUP_DMA_MAP);
 	return urb;
 }
+EXPORT_SYMBOL_GPL(usb_buffer_map);
 #endif  /*  0  */
 
 /* XXX DISABLED, no users currently.  If you wish to re-enable this
@@ -753,6 +759,7 @@
 					DMA_TO_DEVICE);
 	}
 }
+EXPORT_SYMBOL_GPL(usb_buffer_dmasync);
 #endif
 
 /**
@@ -788,6 +795,7 @@
 	urb->transfer_flags &= ~(URB_NO_TRANSFER_DMA_MAP
 				| URB_NO_SETUP_DMA_MAP);
 }
+EXPORT_SYMBOL_GPL(usb_buffer_unmap);
 #endif  /*  0  */
 
 /**
@@ -828,10 +836,11 @@
 			|| !controller->dma_mask)
 		return -1;
 
-	// FIXME generic api broken like pci, can't report errors
+	/* FIXME generic api broken like pci, can't report errors */
 	return dma_map_sg(controller, sg, nents,
 			is_in ? DMA_FROM_DEVICE : DMA_TO_DEVICE);
 }
+EXPORT_SYMBOL_GPL(usb_buffer_map_sg);
 
 /* XXX DISABLED, no users currently.  If you wish to re-enable this
  * XXX please determine whether the sync is to transfer ownership of
@@ -865,6 +874,7 @@
 	dma_sync_sg(controller, sg, n_hw_ents,
 			is_in ? DMA_FROM_DEVICE : DMA_TO_DEVICE);
 }
+EXPORT_SYMBOL_GPL(usb_buffer_dmasync_sg);
 #endif
 
 /**
@@ -891,6 +901,7 @@
 	dma_unmap_sg(controller, sg, n_hw_ents,
 			is_in ? DMA_FROM_DEVICE : DMA_TO_DEVICE);
 }
+EXPORT_SYMBOL_GPL(usb_buffer_unmap_sg);
 
 /* format to disable USB on kernel command line is: nousb */
 __module_param_call("", nousb, param_set_bool, param_get_bool, &nousb, 0444);
@@ -902,6 +913,7 @@
 {
 	return nousb;
 }
+EXPORT_SYMBOL_GPL(usb_disabled);
 
 /*
  * Init
@@ -918,7 +930,7 @@
 	if (retval)
 		goto out;
 	retval = bus_register(&usb_bus_type);
-	if (retval) 
+	if (retval)
 		goto bus_register_failed;
 	retval = usb_host_init();
 	if (retval)
@@ -983,45 +995,4 @@
 
 subsys_initcall(usb_init);
 module_exit(usb_exit);
-
-/*
- * USB may be built into the kernel or be built as modules.
- * These symbols are exported for device (or host controller)
- * driver modules to use.
- */
-
-EXPORT_SYMBOL(usb_disabled);
-
-EXPORT_SYMBOL_GPL(usb_get_intf);
-EXPORT_SYMBOL_GPL(usb_put_intf);
-
-EXPORT_SYMBOL(usb_put_dev);
-EXPORT_SYMBOL(usb_get_dev);
-EXPORT_SYMBOL(usb_hub_tt_clear_buffer);
-
-EXPORT_SYMBOL(usb_lock_device_for_reset);
-
-EXPORT_SYMBOL(usb_find_interface);
-EXPORT_SYMBOL(usb_ifnum_to_if);
-EXPORT_SYMBOL(usb_altnum_to_altsetting);
-
-EXPORT_SYMBOL(__usb_get_extra_descriptor);
-
-EXPORT_SYMBOL(usb_get_current_frame_number);
-
-EXPORT_SYMBOL(usb_buffer_alloc);
-EXPORT_SYMBOL(usb_buffer_free);
-
-#if 0
-EXPORT_SYMBOL(usb_buffer_map);
-EXPORT_SYMBOL(usb_buffer_dmasync);
-EXPORT_SYMBOL(usb_buffer_unmap);
-#endif
-
-EXPORT_SYMBOL(usb_buffer_map_sg);
-#if 0
-EXPORT_SYMBOL(usb_buffer_dmasync_sg);
-#endif
-EXPORT_SYMBOL(usb_buffer_unmap_sg);
-
 MODULE_LICENSE("GPL");
diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
index c52626c..2375194 100644
--- a/drivers/usb/core/usb.h
+++ b/drivers/usb/core/usb.h
@@ -1,22 +1,23 @@
 /* Functions local to drivers/usb/core/ */
 
-extern int usb_create_sysfs_dev_files (struct usb_device *dev);
-extern void usb_remove_sysfs_dev_files (struct usb_device *dev);
-extern int usb_create_sysfs_intf_files (struct usb_interface *intf);
-extern void usb_remove_sysfs_intf_files (struct usb_interface *intf);
-extern int usb_create_ep_files(struct device *parent, struct usb_host_endpoint *endpoint,
+extern int usb_create_sysfs_dev_files(struct usb_device *dev);
+extern void usb_remove_sysfs_dev_files(struct usb_device *dev);
+extern int usb_create_sysfs_intf_files(struct usb_interface *intf);
+extern void usb_remove_sysfs_intf_files(struct usb_interface *intf);
+extern int usb_create_ep_files(struct device *parent,
+				struct usb_host_endpoint *endpoint,
 				struct usb_device *udev);
 extern void usb_remove_ep_files(struct usb_host_endpoint *endpoint);
 
 extern void usb_enable_endpoint(struct usb_device *dev,
 		struct usb_host_endpoint *ep);
-extern void usb_disable_endpoint (struct usb_device *dev, unsigned int epaddr);
-extern void usb_disable_interface (struct usb_device *dev,
+extern void usb_disable_endpoint(struct usb_device *dev, unsigned int epaddr);
+extern void usb_disable_interface(struct usb_device *dev,
 		struct usb_interface *intf);
 extern void usb_release_interface_cache(struct kref *ref);
-extern void usb_disable_device (struct usb_device *dev, int skip_ep0);
-extern int usb_deauthorize_device (struct usb_device *);
-extern int usb_authorize_device (struct usb_device *);
+extern void usb_disable_device(struct usb_device *dev, int skip_ep0);
+extern int usb_deauthorize_device(struct usb_device *);
+extern int usb_authorize_device(struct usb_device *);
 extern void usb_detect_quirks(struct usb_device *udev);
 
 extern int usb_get_device_descriptor(struct usb_device *dev,
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index 77a3759..c139551 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -12,10 +12,9 @@
 # With help from a special transceiver and a "Mini-AB" jack, systems with
 # both kinds of controller can also support "USB On-the-Go" (CONFIG_USB_OTG).
 #
-menu "USB Gadget Support"
 
-config USB_GADGET
-	tristate "Support for USB Gadgets"
+menuconfig USB_GADGET
+	tristate "USB Gadget Support"
 	help
 	   USB is a master/slave protocol, organized with one master
 	   host (such as a PC) controlling up to 127 peripheral devices.
@@ -42,6 +41,8 @@
 	   For more information, see <http://www.linux-usb.org/gadget> and
 	   the kernel DocBook documentation for this API.
 
+if USB_GADGET
+
 config USB_GADGET_DEBUG
 	boolean "Debugging messages"
 	depends on USB_GADGET && DEBUG_KERNEL && EXPERIMENTAL
@@ -220,6 +221,16 @@
 	default USB_GADGET
 	select USB_GADGET_SELECTED
 
+config SUPERH_BUILT_IN_M66592
+	boolean "Enable SuperH built-in USB like the M66592"
+	depends on USB_GADGET_M66592 && CPU_SUBTYPE_SH7722
+	help
+	   SH7722 has USB like the M66592.
+
+	   The transfer rate is very slow when use "Ethernet Gadget".
+	   However, this problem is improved if change a value of
+	   NET_IP_ALIGN to 4.
+
 config USB_GADGET_GOKU
 	boolean "Toshiba TC86C001 'Goku-S'"
 	depends on PCI
@@ -538,6 +549,20 @@
 	  Say "y" to link the driver statically, or "m" to build a
 	  dynamically linked module called "g_midi".
 
+config USB_G_PRINTER
+	tristate "Printer Gadget"
+	help
+	  The Printer Gadget channels data between the USB host and a
+	  userspace program driving the print engine. The user space
+	  program reads and writes the device file /dev/g_printer to
+	  receive or send printer data. It can use ioctl calls to
+	  the device file to get or set printer status.
+
+	  Say "y" to link the driver statically, or "m" to build a
+	  dynamically linked module called "g_printer".
+
+	  For more information, see Documentation/usb/gadget_printer.txt
+	  which includes sample code for accessing the device file.
 
 # put drivers that need isochronous transfer support (for audio
 # or video class gadget drivers), or specific hardware, here.
@@ -546,4 +571,4 @@
 
 endchoice
 
-endmenu
+endif # USB_GADGET
diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
index 904e57b..c3aab80 100644
--- a/drivers/usb/gadget/Makefile
+++ b/drivers/usb/gadget/Makefile
@@ -28,6 +28,8 @@
 gadgetfs-objs			:= inode.o
 g_file_storage-objs		:= file_storage.o usbstring.o config.o \
 					epautoconf.o
+g_printer-objs			:= printer.o usbstring.o config.o \
+					epautoconf.o
 
 ifeq ($(CONFIG_USB_ETH_RNDIS),y)
 	g_ether-objs		+= rndis.o
@@ -38,5 +40,6 @@
 obj-$(CONFIG_USB_GADGETFS)	+= gadgetfs.o
 obj-$(CONFIG_USB_FILE_STORAGE)	+= g_file_storage.o
 obj-$(CONFIG_USB_G_SERIAL)	+= g_serial.o
+obj-$(CONFIG_USB_G_PRINTER)	+= g_printer.o
 obj-$(CONFIG_USB_MIDI_GADGET)	+= g_midi.o
 
diff --git a/drivers/usb/gadget/amd5536udc.c b/drivers/usb/gadget/amd5536udc.c
index c72e962..b663f23 100644
--- a/drivers/usb/gadget/amd5536udc.c
+++ b/drivers/usb/gadget/amd5536udc.c
@@ -1244,7 +1244,7 @@
 		/* stop OUT naking */
 		if (!ep->in) {
 			if (!use_dma && udc_rxfifo_pending) {
-				DBG(dev, "udc_queue(): pending bytes in"
+				DBG(dev, "udc_queue(): pending bytes in "
 					"rxfifo after nyet\n");
 				/*
 				 * read pending bytes afer nyet:
@@ -2038,6 +2038,7 @@
 	spin_unlock_irqrestore(&dev->lock, flags);
 
 	driver->unbind(&dev->gadget);
+	dev->gadget.dev.driver = NULL;
 	dev->driver = NULL;
 
 	/* set SD */
diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c
index cd62b02..a83e8b7 100644
--- a/drivers/usb/gadget/at91_udc.c
+++ b/drivers/usb/gadget/at91_udc.c
@@ -21,8 +21,7 @@
  * Boston, MA  02111-1307, USA.
  */
 
-#undef	DEBUG
-#undef	VERBOSE
+#undef	VERBOSE_DEBUG
 #undef	PACKET_TRACE
 
 #include <linux/kernel.h>
@@ -46,8 +45,8 @@
 #include <asm/irq.h>
 #include <asm/system.h>
 #include <asm/mach-types.h>
+#include <asm/gpio.h>
 
-#include <asm/arch/gpio.h>
 #include <asm/arch/board.h>
 #include <asm/arch/cpu.h>
 #include <asm/arch/at91sam9261_matrix.h>
@@ -580,7 +579,7 @@
  */
 
 static struct usb_request *
-at91_ep_alloc_request(struct usb_ep *_ep, unsigned int gfp_flags)
+at91_ep_alloc_request(struct usb_ep *_ep, gfp_t gfp_flags)
 {
 	struct at91_request *req;
 
@@ -881,6 +880,8 @@
  */
 static void pullup(struct at91_udc *udc, int is_on)
 {
+	int	active = !udc->board.pullup_active_low;
+
 	if (!udc->enabled || !udc->vbus)
 		is_on = 0;
 	DBG("%sactive\n", is_on ? "" : "in");
@@ -890,7 +891,7 @@
 		at91_udp_write(udc, AT91_UDP_ICR, AT91_UDP_RXRSM);
 		at91_udp_write(udc, AT91_UDP_TXVC, 0);
 		if (cpu_is_at91rm9200())
-			at91_set_gpio_value(udc->board.pullup_pin, 1);
+			gpio_set_value(udc->board.pullup_pin, active);
 		else if (cpu_is_at91sam9260() || cpu_is_at91sam9263()) {
 			u32	txvc = at91_udp_read(udc, AT91_UDP_TXVC);
 
@@ -908,7 +909,7 @@
 		at91_udp_write(udc, AT91_UDP_IDR, AT91_UDP_RXRSM);
 		at91_udp_write(udc, AT91_UDP_TXVC, AT91_UDP_TXVC_TXVDIS);
 		if (cpu_is_at91rm9200())
-			at91_set_gpio_value(udc->board.pullup_pin, 0);
+			gpio_set_value(udc->board.pullup_pin, !active);
 		else if (cpu_is_at91sam9260() || cpu_is_at91sam9263()) {
 			u32	txvc = at91_udp_read(udc, AT91_UDP_TXVC);
 
@@ -1153,7 +1154,7 @@
 			| USB_REQ_GET_STATUS:
 		tmp = w_index & USB_ENDPOINT_NUMBER_MASK;
 		ep = &udc->ep[tmp];
-		if (tmp > NUM_ENDPOINTS || (tmp && !ep->desc))
+		if (tmp >= NUM_ENDPOINTS || (tmp && !ep->desc))
 			goto stall;
 
 		if (tmp) {
@@ -1176,7 +1177,7 @@
 			| USB_REQ_SET_FEATURE:
 		tmp = w_index & USB_ENDPOINT_NUMBER_MASK;
 		ep = &udc->ep[tmp];
-		if (w_value != USB_ENDPOINT_HALT || tmp > NUM_ENDPOINTS)
+		if (w_value != USB_ENDPOINT_HALT || tmp >= NUM_ENDPOINTS)
 			goto stall;
 		if (!ep->desc || ep->is_iso)
 			goto stall;
@@ -1195,7 +1196,7 @@
 			| USB_REQ_CLEAR_FEATURE:
 		tmp = w_index & USB_ENDPOINT_NUMBER_MASK;
 		ep = &udc->ep[tmp];
-		if (w_value != USB_ENDPOINT_HALT || tmp > NUM_ENDPOINTS)
+		if (w_value != USB_ENDPOINT_HALT || tmp >= NUM_ENDPOINTS)
 			goto stall;
 		if (tmp == 0)
 			goto succeed;
@@ -1551,7 +1552,7 @@
 
 	/* vbus needs at least brief debouncing */
 	udelay(10);
-	value = at91_get_gpio_value(udc->board.vbus_pin);
+	value = gpio_get_value(udc->board.vbus_pin);
 	if (value != udc->vbus)
 		at91_vbus_session(&udc->gadget, value);
 
@@ -1616,6 +1617,8 @@
 	local_irq_enable();
 
 	driver->unbind(&udc->gadget);
+	udc->gadget.dev.driver = NULL;
+	udc->gadget.dev.driver_data = NULL;
 	udc->driver = NULL;
 
 	DBG("unbound from %s\n", driver->driver.name);
@@ -1645,12 +1648,12 @@
 	}
 
 	if (pdev->num_resources != 2) {
-		DBG("invalid num_resources");
+		DBG("invalid num_resources\n");
 		return -ENODEV;
 	}
 	if ((pdev->resource[0].flags != IORESOURCE_MEM)
 			|| (pdev->resource[1].flags != IORESOURCE_IRQ)) {
-		DBG("invalid resource type");
+		DBG("invalid resource type\n");
 		return -ENODEV;
 	}
 
@@ -1672,10 +1675,26 @@
 	udc->pdev = pdev;
 	udc->enabled = 0;
 
+	/* rm9200 needs manual D+ pullup; off by default */
+	if (cpu_is_at91rm9200()) {
+		if (udc->board.pullup_pin <= 0) {
+			DBG("no D+ pullup?\n");
+			retval = -ENODEV;
+			goto fail0;
+		}
+		retval = gpio_request(udc->board.pullup_pin, "udc_pullup");
+		if (retval) {
+			DBG("D+ pullup is busy\n");
+			goto fail0;
+		}
+		gpio_direction_output(udc->board.pullup_pin,
+				udc->board.pullup_active_low);
+	}
+
 	udc->udp_baseaddr = ioremap(res->start, res->end - res->start + 1);
 	if (!udc->udp_baseaddr) {
-		release_mem_region(res->start, res->end - res->start + 1);
-		return -ENOMEM;
+		retval = -ENOMEM;
+		goto fail0a;
 	}
 
 	udc_reinit(udc);
@@ -1686,12 +1705,13 @@
 	if (IS_ERR(udc->iclk) || IS_ERR(udc->fclk)) {
 		DBG("clocks missing\n");
 		retval = -ENODEV;
-		goto fail0;
+		/* NOTE: we "know" here that refcounts on these are NOPs */
+		goto fail0b;
 	}
 
 	retval = device_register(&udc->gadget.dev);
 	if (retval < 0)
-		goto fail0;
+		goto fail0b;
 
 	/* don't do anything until we have both gadget driver and VBUS */
 	clk_enable(udc->iclk);
@@ -1703,25 +1723,32 @@
 
 	/* request UDC and maybe VBUS irqs */
 	udc->udp_irq = platform_get_irq(pdev, 0);
-	if (request_irq(udc->udp_irq, at91_udc_irq,
-			IRQF_DISABLED, driver_name, udc)) {
+	retval = request_irq(udc->udp_irq, at91_udc_irq,
+			IRQF_DISABLED, driver_name, udc);
+	if (retval < 0) {
 		DBG("request irq %d failed\n", udc->udp_irq);
-		retval = -EBUSY;
 		goto fail1;
 	}
 	if (udc->board.vbus_pin > 0) {
+		retval = gpio_request(udc->board.vbus_pin, "udc_vbus");
+		if (retval < 0) {
+			DBG("request vbus pin failed\n");
+			goto fail2;
+		}
+		gpio_direction_input(udc->board.vbus_pin);
+
 		/*
 		 * Get the initial state of VBUS - we cannot expect
 		 * a pending interrupt.
 		 */
-		udc->vbus = at91_get_gpio_value(udc->board.vbus_pin);
+		udc->vbus = gpio_get_value(udc->board.vbus_pin);
 		if (request_irq(udc->board.vbus_pin, at91_vbus_irq,
 				IRQF_DISABLED, driver_name, udc)) {
 			DBG("request vbus irq %d failed\n",
 					udc->board.vbus_pin);
 			free_irq(udc->udp_irq, udc);
 			retval = -EBUSY;
-			goto fail1;
+			goto fail3;
 		}
 	} else {
 		DBG("no VBUS detection, assuming always-on\n");
@@ -1734,8 +1761,18 @@
 	INFO("%s version %s\n", driver_name, DRIVER_VERSION);
 	return 0;
 
+fail3:
+	if (udc->board.vbus_pin > 0)
+		gpio_free(udc->board.vbus_pin);
+fail2:
+	free_irq(udc->udp_irq, udc);
 fail1:
 	device_unregister(&udc->gadget.dev);
+fail0b:
+	iounmap(udc->udp_baseaddr);
+fail0a:
+	if (cpu_is_at91rm9200())
+		gpio_free(udc->board.pullup_pin);
 fail0:
 	release_mem_region(res->start, res->end - res->start + 1);
 	DBG("%s probe failed, %d\n", driver_name, retval);
@@ -1756,12 +1793,18 @@
 
 	device_init_wakeup(&pdev->dev, 0);
 	remove_debug_file(udc);
-	if (udc->board.vbus_pin > 0)
+	if (udc->board.vbus_pin > 0) {
 		free_irq(udc->board.vbus_pin, udc);
+		gpio_free(udc->board.vbus_pin);
+	}
 	free_irq(udc->udp_irq, udc);
 	device_unregister(&udc->gadget.dev);
 
 	iounmap(udc->udp_baseaddr);
+
+	if (cpu_is_at91rm9200())
+		gpio_free(udc->board.pullup_pin);
+
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	release_mem_region(res->start, res->end - res->start + 1);
 
diff --git a/drivers/usb/gadget/at91_udc.h b/drivers/usb/gadget/at91_udc.h
index 7e34e2f..a973f2a 100644
--- a/drivers/usb/gadget/at91_udc.h
+++ b/drivers/usb/gadget/at91_udc.h
@@ -53,7 +53,7 @@
 #define     AT91_UDP_RXRSM	(1 <<  9)	/* USB Resume Interrupt Status */
 #define     AT91_UDP_EXTRSM	(1 << 10)	/* External Resume Interrupt Status [AT91RM9200 only] */
 #define     AT91_UDP_SOFINT	(1 << 11)	/* Start of Frame Interrupt Status */
-#define     AT91_UDP_ENDBUSRES	(1 << 12)	/* End of Bus Reset Interrpt Status */
+#define     AT91_UDP_ENDBUSRES	(1 << 12)	/* End of Bus Reset Interrupt Status */
 #define     AT91_UDP_WAKEUP	(1 << 13)	/* USB Wakeup Interrupt Status [AT91RM9200 only] */
 
 #define AT91_UDP_ICR		0x20		/* Interrupt Clear Register */
@@ -158,13 +158,7 @@
 
 /*-------------------------------------------------------------------------*/
 
-#ifdef DEBUG
-#define DBG(stuff...)		printk(KERN_DEBUG "udc: " stuff)
-#else
-#define DBG(stuff...)		do{}while(0)
-#endif
-
-#ifdef VERBOSE
+#ifdef VERBOSE_DEBUG
 #    define VDBG		DBG
 #else
 #    define VDBG(stuff...)	do{}while(0)
@@ -176,9 +170,10 @@
 #    define PACKET(stuff...)	do{}while(0)
 #endif
 
-#define ERR(stuff...)		printk(KERN_ERR "udc: " stuff)
-#define WARN(stuff...)		printk(KERN_WARNING "udc: " stuff)
-#define INFO(stuff...)		printk(KERN_INFO "udc: " stuff)
+#define ERR(stuff...)		pr_err("udc: " stuff)
+#define WARN(stuff...)		pr_warning("udc: " stuff)
+#define INFO(stuff...)		pr_info("udc: " stuff)
+#define DBG(stuff...)		pr_debug("udc: " stuff)
 
 #endif
 
diff --git a/drivers/usb/gadget/atmel_usba_udc.c b/drivers/usb/gadget/atmel_usba_udc.c
index 4fb5ff4..af8b2a3 100644
--- a/drivers/usb/gadget/atmel_usba_udc.c
+++ b/drivers/usb/gadget/atmel_usba_udc.c
@@ -1384,8 +1384,7 @@
 	return retval;
 
 stall:
-	printk(KERN_ERR
-		"udc: %s: Invalid setup request: %02x.%02x v%04x i%04x l%d, "
+	pr_err("udc: %s: Invalid setup request: %02x.%02x v%04x i%04x l%d, "
 		"halting endpoint...\n",
 		ep->ep.name, crq->bRequestType, crq->bRequest,
 		le16_to_cpu(crq->wValue), le16_to_cpu(crq->wIndex),
@@ -1456,8 +1455,7 @@
 				set_protocol_stall(udc, ep);
 			break;
 		default:
-			printk(KERN_ERR
-				"udc: %s: TXCOMP: Invalid endpoint state %d, "
+			pr_err("udc: %s: TXCOMP: Invalid endpoint state %d, "
 				"halting endpoint...\n",
 				ep->ep.name, ep->state);
 			set_protocol_stall(udc, ep);
@@ -1486,8 +1484,7 @@
 		default:
 			usba_ep_writel(ep, CLR_STA, USBA_RX_BK_RDY);
 			usba_ep_writel(ep, CTL_DIS, USBA_RX_BK_RDY);
-			printk(KERN_ERR
-				"udc: %s: RXRDY: Invalid endpoint state %d, "
+			pr_err("udc: %s: RXRDY: Invalid endpoint state %d, "
 				"halting endpoint...\n",
 				ep->ep.name, ep->state);
 			set_protocol_stall(udc, ep);
@@ -1532,7 +1529,7 @@
 		pkt_len = USBA_BFEXT(BYTE_COUNT, usba_ep_readl(ep, STA));
 		DBG(DBG_HW, "Packet length: %u\n", pkt_len);
 		if (pkt_len != sizeof(crq)) {
-			printk(KERN_WARNING "udc: Invalid packet length %u "
+			pr_warning("udc: Invalid packet length %u "
 				"(expected %lu)\n", pkt_len, sizeof(crq));
 			set_protocol_stall(udc, ep);
 			return;
diff --git a/drivers/usb/gadget/atmel_usba_udc.h b/drivers/usb/gadget/atmel_usba_udc.h
index a68304e..08bf6f9 100644
--- a/drivers/usb/gadget/atmel_usba_udc.h
+++ b/drivers/usb/gadget/atmel_usba_udc.h
@@ -216,7 +216,6 @@
 #define FIFO_IOMEM_ID	0
 #define CTRL_IOMEM_ID	1
 
-#ifdef DEBUG
 #define DBG_ERR		0x0001	/* report all error returns */
 #define DBG_HW		0x0002	/* debug hardware initialization */
 #define DBG_GADGET	0x0004	/* calls to/from gadget driver */
@@ -230,14 +229,12 @@
 #define DBG_NONE	0x0000
 
 #define DEBUG_LEVEL	(DBG_ERR)
+
 #define DBG(level, fmt, ...)					\
 	do {							\
 		if ((level) & DEBUG_LEVEL)			\
-			printk(KERN_DEBUG "udc: " fmt, ## __VA_ARGS__);	\
+			pr_debug("udc: " fmt, ## __VA_ARGS__);	\
 	} while (0)
-#else
-#define DBG(level, fmt...)
-#endif
 
 enum usba_ctrl_state {
 	WAIT_FOR_SETUP,
diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
index 9db2482..cbe4453 100644
--- a/drivers/usb/gadget/dummy_hcd.c
+++ b/drivers/usb/gadget/dummy_hcd.c
@@ -61,6 +61,8 @@
 #define DRIVER_DESC	"USB Host+Gadget Emulator"
 #define DRIVER_VERSION	"02 May 2005"
 
+#define POWER_BUDGET	500	/* in mA; use 8 for low-power port testing */
+
 static const char	driver_name [] = "dummy_hcd";
 static const char	driver_desc [] = "USB Host+Gadget Emulator";
 
@@ -772,18 +774,17 @@
 	list_del_init (&dum->ep [0].ep.ep_list);
 	INIT_LIST_HEAD(&dum->fifo_req.queue);
 
+	driver->driver.bus = NULL;
 	dum->driver = driver;
 	dum->gadget.dev.driver = &driver->driver;
 	dev_dbg (udc_dev(dum), "binding gadget driver '%s'\n",
 			driver->driver.name);
-	if ((retval = driver->bind (&dum->gadget)) != 0)
-		goto err_bind_gadget;
-
-	driver->driver.bus = dum->gadget.dev.parent->bus;
-	if ((retval = driver_register (&driver->driver)) != 0)
-		goto err_register;
-	if ((retval = device_bind_driver (&dum->gadget.dev)) != 0)
-		goto err_bind_driver;
+	retval = driver->bind(&dum->gadget);
+	if (retval) {
+		dum->driver = NULL;
+		dum->gadget.dev.driver = NULL;
+		return retval;
+	}
 
 	/* khubd will enumerate this in a while */
 	spin_lock_irq (&dum->lock);
@@ -793,20 +794,6 @@
 
 	usb_hcd_poll_rh_status (dummy_to_hcd (dum));
 	return 0;
-
-err_bind_driver:
-	driver_unregister (&driver->driver);
-err_register:
-	if (driver->unbind)
-		driver->unbind (&dum->gadget);
-	spin_lock_irq (&dum->lock);
-	dum->pullup = 0;
-	set_link_state (dum);
-	spin_unlock_irq (&dum->lock);
-err_bind_gadget:
-	dum->driver = NULL;
-	dum->gadget.dev.driver = NULL;
-	return retval;
 }
 EXPORT_SYMBOL (usb_gadget_register_driver);
 
@@ -830,11 +817,9 @@
 	spin_unlock_irqrestore (&dum->lock, flags);
 
 	driver->unbind (&dum->gadget);
+	dum->gadget.dev.driver = NULL;
 	dum->driver = NULL;
 
-	device_release_driver (&dum->gadget.dev);
-	driver_unregister (&driver->driver);
-
 	spin_lock_irqsave (&dum->lock, flags);
 	dum->pullup = 0;
 	set_link_state (dum);
@@ -1827,8 +1812,7 @@
 
 	INIT_LIST_HEAD (&dum->urbp_list);
 
-	/* only show a low-power port: just 8mA */
-	hcd->power_budget = 8;
+	hcd->power_budget = POWER_BUDGET;
 	hcd->state = HC_STATE_RUNNING;
 	hcd->uses_new_polling = 1;
 
diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c
index 9e732bf..a70e255 100644
--- a/drivers/usb/gadget/ether.c
+++ b/drivers/usb/gadget/ether.c
@@ -1067,19 +1067,19 @@
 
 	/* on error, disable any endpoints  */
 	if (result < 0) {
-		if (!subset_active(dev))
+		if (!subset_active(dev) && dev->status_ep)
 			(void) usb_ep_disable (dev->status_ep);
 		dev->status = NULL;
 		(void) usb_ep_disable (dev->in_ep);
 		(void) usb_ep_disable (dev->out_ep);
 		dev->in = NULL;
 		dev->out = NULL;
-	} else
+	}
 
 	/* activate non-CDC configs right away
 	 * this isn't strictly according to the RNDIS spec
 	 */
-	if (!cdc_active (dev)) {
+	else if (!cdc_active (dev)) {
 		netif_carrier_on (dev->net);
 		if (netif_running (dev->net)) {
 			spin_unlock (&dev->lock);
diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c
index 1d174dc..3301167 100644
--- a/drivers/usb/gadget/file_storage.c
+++ b/drivers/usb/gadget/file_storage.c
@@ -275,19 +275,15 @@
 
 /*-------------------------------------------------------------------------*/
 
-#ifdef DEBUG
 #define LDBG(lun,fmt,args...) \
 	dev_dbg(&(lun)->dev , fmt , ## args)
 #define MDBG(fmt,args...) \
-	printk(KERN_DEBUG DRIVER_NAME ": " fmt , ## args)
-#else
-#define LDBG(lun,fmt,args...) \
-	do { } while (0)
-#define MDBG(fmt,args...) \
-	do { } while (0)
+	pr_debug(DRIVER_NAME ": " fmt , ## args)
+
+#ifndef DEBUG
 #undef VERBOSE_DEBUG
 #undef DUMP_MSGS
-#endif /* DEBUG */
+#endif /* !DEBUG */
 
 #ifdef VERBOSE_DEBUG
 #define VLDBG	LDBG
@@ -304,7 +300,7 @@
 	dev_info(&(lun)->dev , fmt , ## args)
 
 #define MINFO(fmt,args...) \
-	printk(KERN_INFO DRIVER_NAME ": " fmt , ## args)
+	pr_info(DRIVER_NAME ": " fmt , ## args)
 
 #define DBG(d, fmt, args...) \
 	dev_dbg(&(d)->gadget->dev , fmt , ## args)
diff --git a/drivers/usb/gadget/fsl_usb2_udc.c b/drivers/usb/gadget/fsl_usb2_udc.c
index 038e7d7..63e8fa3 100644
--- a/drivers/usb/gadget/fsl_usb2_udc.c
+++ b/drivers/usb/gadget/fsl_usb2_udc.c
@@ -776,7 +776,7 @@
 		VDBG("%s, bad params\n", __FUNCTION__);
 		return -EINVAL;
 	}
-	if (!_ep || (!ep->desc && ep_index(ep))) {
+	if (unlikely(!_ep || !ep->desc)) {
 		VDBG("%s, bad ep\n", __FUNCTION__);
 		return -EINVAL;
 	}
@@ -1896,7 +1896,7 @@
 
 	spin_lock_irqsave(&udc->lock, flags);
 
-	/* ------basic driver infomation ---- */
+	/* ------basic driver information ---- */
 	t = scnprintf(next, size,
 			DRIVER_DESC "\n"
 			"%s version: %s\n"
diff --git a/drivers/usb/gadget/fsl_usb2_udc.h b/drivers/usb/gadget/fsl_usb2_udc.h
index 832ab82..9fb0b1e 100644
--- a/drivers/usb/gadget/fsl_usb2_udc.h
+++ b/drivers/usb/gadget/fsl_usb2_udc.h
@@ -551,9 +551,9 @@
 #define VDBG(stuff...)	do{}while(0)
 #endif
 
-#define ERR(stuff...)		printk(KERN_ERR "udc: " stuff)
-#define WARN(stuff...)		printk(KERN_WARNING "udc: " stuff)
-#define INFO(stuff...)		printk(KERN_INFO "udc: " stuff)
+#define ERR(stuff...)		pr_err("udc: " stuff)
+#define WARN(stuff...)		pr_warning("udc: " stuff)
+#define INFO(stuff...)		pr_info("udc: " stuff)
 
 /*-------------------------------------------------------------------------*/
 
diff --git a/drivers/usb/gadget/gmidi.c b/drivers/usb/gadget/gmidi.c
index 7da7fcb..5b42ccd 100644
--- a/drivers/usb/gadget/gmidi.c
+++ b/drivers/usb/gadget/gmidi.c
@@ -1158,7 +1158,7 @@
 	/* support optional vendor/distro customization */
 	if (idVendor) {
 		if (!idProduct) {
-			printk(KERN_ERR "idVendor needs idProduct!\n");
+			pr_err("idVendor needs idProduct!\n");
 			return -ENODEV;
 		}
 		device_desc.idVendor = cpu_to_le16(idVendor);
@@ -1190,7 +1190,7 @@
 	in_ep = usb_ep_autoconfig(gadget, &bulk_in_desc);
 	if (!in_ep) {
 autoconf_fail:
-		printk(KERN_ERR "%s: can't autoconfigure on %s\n",
+		pr_err("%s: can't autoconfigure on %s\n",
 			shortname, gadget->name);
 		return -ENODEV;
 	}
@@ -1212,7 +1212,7 @@
 		 * it SHOULD NOT have problems with bulk-capable hardware.
 		 * so warn about unrecognized controllers, don't panic.
 		 */
-		printk(KERN_WARNING "%s: controller '%s' not recognized\n",
+		pr_warning("%s: controller '%s' not recognized\n",
 			shortname, gadget->name);
 		device_desc.bcdDevice = __constant_cpu_to_le16(0x9999);
 	}
diff --git a/drivers/usb/gadget/goku_udc.c b/drivers/usb/gadget/goku_udc.c
index 2ec9d19..d3e7025 100644
--- a/drivers/usb/gadget/goku_udc.c
+++ b/drivers/usb/gadget/goku_udc.c
@@ -1422,6 +1422,7 @@
 	spin_unlock_irqrestore(&dev->lock, flags);
 
 	driver->unbind(&dev->gadget);
+	dev->gadget.dev.driver = NULL;
 
 	DBG(dev, "unregistered driver '%s'\n", driver->driver.name);
 	return 0;
diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c
index 47ef8bd..805602a 100644
--- a/drivers/usb/gadget/inode.c
+++ b/drivers/usb/gadget/inode.c
@@ -1699,7 +1699,7 @@
 	if (!dev)
 		return -ESRCH;
 	if (0 != strcmp (CHIP, gadget->name)) {
-		printk (KERN_ERR "%s expected %s controller not %s\n",
+		pr_err("%s expected %s controller not %s\n",
 			shortname, CHIP, gadget->name);
 		return -ENODEV;
 	}
diff --git a/drivers/usb/gadget/lh7a40x_udc.c b/drivers/usb/gadget/lh7a40x_udc.c
index 367b75c..37243ef 100644
--- a/drivers/usb/gadget/lh7a40x_udc.c
+++ b/drivers/usb/gadget/lh7a40x_udc.c
@@ -474,6 +474,7 @@
 	spin_unlock_irqrestore(&dev->lock, flags);
 
 	driver->unbind(&dev->gadget);
+	dev->gadget.dev.driver = NULL;
 	device_del(&dev->gadget.dev);
 
 	udc_disable(dev);
diff --git a/drivers/usb/gadget/m66592-udc.c b/drivers/usb/gadget/m66592-udc.c
index ebc5536a..835948f 100644
--- a/drivers/usb/gadget/m66592-udc.c
+++ b/drivers/usb/gadget/m66592-udc.c
@@ -36,9 +36,14 @@
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Yoshihiro Shimoda");
 
-#define DRIVER_VERSION	"29 May 2007"
+#define DRIVER_VERSION	"18 Oct 2007"
 
 /* module parameters */
+#if defined(CONFIG_SUPERH_BUILT_IN_M66592)
+static unsigned short endian = M66592_LITTLE;
+module_param(endian, ushort, 0644);
+MODULE_PARM_DESC(endian, "data endian: big=0, little=0 (default=0)");
+#else
 static unsigned short clock = M66592_XTAL24;
 module_param(clock, ushort, 0644);
 MODULE_PARM_DESC(clock, "input clock: 48MHz=32768, 24MHz=16384, 12MHz=0 "
@@ -56,6 +61,7 @@
 module_param(irq_sense, ushort, 0644);
 MODULE_PARM_DESC(irq_sense, "IRQ sense: low level=2, falling edge=0 "
 		"(default=2)");
+#endif
 
 static const char udc_name[] = "m66592_udc";
 static const char *m66592_ep_name[] = {
@@ -141,7 +147,7 @@
 		offset = get_pipectr_addr(pipenum);
 		pid = m66592_read(m66592, offset) & M66592_PID;
 	} else
-		printk(KERN_ERR "unexpect pipe num (%d)\n", pipenum);
+		pr_err("unexpect pipe num (%d)\n", pipenum);
 
 	return pid;
 }
@@ -157,7 +163,7 @@
 		offset = get_pipectr_addr(pipenum);
 		m66592_mdfy(m66592, pid, M66592_PID, offset);
 	} else
-		printk(KERN_ERR "unexpect pipe num (%d)\n", pipenum);
+		pr_err("unexpect pipe num (%d)\n", pipenum);
 }
 
 static inline void pipe_start(struct m66592 *m66592, u16 pipenum)
@@ -186,7 +192,7 @@
 		offset = get_pipectr_addr(pipenum);
 		ret = m66592_read(m66592, offset);
 	} else
-		printk(KERN_ERR "unexpect pipe num (%d)\n", pipenum);
+		pr_err("unexpect pipe num (%d)\n", pipenum);
 
 	return ret;
 }
@@ -203,7 +209,7 @@
 		offset = get_pipectr_addr(pipenum);
 		m66592_bset(m66592, M66592_SQCLR, offset);
 	} else
-		printk(KERN_ERR "unexpect pipe num(%d)\n", pipenum);
+		pr_err("unexpect pipe num(%d)\n", pipenum);
 }
 
 static inline int get_buffer_size(struct m66592 *m66592, u16 pipenum)
@@ -285,7 +291,7 @@
 		break;
 	}
 	if (m66592->bi_bufnum > M66592_MAX_BUFNUM) {
-		printk(KERN_ERR "m66592 pipe memory is insufficient(%d)\n",
+		pr_err("m66592 pipe memory is insufficient(%d)\n",
 				m66592->bi_bufnum);
 		return -ENOMEM;
 	}
@@ -326,7 +332,7 @@
 		if (info->type == M66592_BULK)
 			m66592->bulk--;
 	} else
-		printk(KERN_ERR "ep_release: unexpect pipenum (%d)\n",
+		pr_err("ep_release: unexpect pipenum (%d)\n",
 				info->pipe);
 }
 
@@ -360,6 +366,7 @@
 			ep->fifosel = M66592_D0FIFOSEL;
 			ep->fifoctr = M66592_D0FIFOCTR;
 			ep->fifotrn = M66592_D0FIFOTRN;
+#if !defined(CONFIG_SUPERH_BUILT_IN_M66592)
 		} else if (m66592->num_dma == 1) {
 			m66592->num_dma++;
 			ep->use_dma = 1;
@@ -367,6 +374,7 @@
 			ep->fifosel = M66592_D1FIFOSEL;
 			ep->fifoctr = M66592_D1FIFOCTR;
 			ep->fifotrn = M66592_D1FIFOTRN;
+#endif
 		} else {
 			ep->use_dma = 0;
 			ep->fifoaddr = M66592_CFIFO;
@@ -422,7 +430,7 @@
 	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");
+				pr_err("bulk pipe is insufficient\n");
 				return -ENODEV;
 			} else {
 				info.pipe = M66592_BASE_PIPENUM_ISOC
@@ -438,7 +446,7 @@
 		break;
 	case USB_ENDPOINT_XFER_INT:
 		if (m66592->interrupt >= M66592_MAX_NUM_INT) {
-			printk(KERN_ERR "interrupt pipe is insufficient\n");
+			pr_err("interrupt pipe is insufficient\n");
 			return -ENODEV;
 		}
 		info.pipe = M66592_BASE_PIPENUM_INT + m66592->interrupt;
@@ -447,7 +455,7 @@
 		break;
 	case USB_ENDPOINT_XFER_ISOC:
 		if (m66592->isochronous >= M66592_MAX_NUM_ISOC) {
-			printk(KERN_ERR "isochronous pipe is insufficient\n");
+			pr_err("isochronous pipe is insufficient\n");
 			return -ENODEV;
 		}
 		info.pipe = M66592_BASE_PIPENUM_ISOC + m66592->isochronous;
@@ -455,7 +463,7 @@
 		counter = &m66592->isochronous;
 		break;
 	default:
-		printk(KERN_ERR "unexpect xfer type\n");
+		pr_err("unexpect xfer type\n");
 		return -EINVAL;
 	}
 	ep->type = info.type;
@@ -470,7 +478,7 @@
 
 	ret = pipe_buffer_setting(m66592, &info);
 	if (ret < 0) {
-		printk(KERN_ERR "pipe_buffer_setting fail\n");
+		pr_err("pipe_buffer_setting fail\n");
 		return ret;
 	}
 
@@ -606,11 +614,33 @@
 		control_end(ep->m66592, 0);
 		break;
 	default:
-		printk(KERN_ERR "start_ep0: unexpect ctsq(%x)\n", ctsq);
+		pr_err("start_ep0: unexpect ctsq(%x)\n", ctsq);
 		break;
 	}
 }
 
+#if defined(CONFIG_SUPERH_BUILT_IN_M66592)
+static void init_controller(struct m66592 *m66592)
+{
+	usbf_start_clock();
+	m66592_bset(m66592, M66592_HSE, M66592_SYSCFG);		/* High spd */
+	m66592_bclr(m66592, M66592_USBE, M66592_SYSCFG);
+	m66592_bclr(m66592, M66592_DPRPU, M66592_SYSCFG);
+	m66592_bset(m66592, M66592_USBE, M66592_SYSCFG);
+
+	/* This is a workaound for SH7722 2nd cut */
+	m66592_bset(m66592, 0x8000, M66592_DVSTCTR);
+	m66592_bset(m66592, 0x1000, M66592_TESTMODE);
+	m66592_bclr(m66592, 0x8000, M66592_DVSTCTR);
+
+	m66592_bset(m66592, M66592_INTL, M66592_INTENB1);
+
+	m66592_write(m66592, 0, M66592_CFBCFG);
+	m66592_write(m66592, 0, M66592_D0FBCFG);
+	m66592_bset(m66592, endian, M66592_CFBCFG);
+	m66592_bset(m66592, endian, M66592_D0FBCFG);
+}
+#else	/* #if defined(CONFIG_SUPERH_BUILT_IN_M66592) */
 static void init_controller(struct m66592 *m66592)
 {
 	m66592_bset(m66592, (vif & M66592_LDRV) | (endian & M66592_BIGEND),
@@ -636,9 +666,13 @@
 	m66592_write(m66592, M66592_BURST | M66592_CPU_ADR_RD_WR,
 			M66592_DMA0CFG);
 }
+#endif	/* #if defined(CONFIG_SUPERH_BUILT_IN_M66592) */
 
 static void disable_controller(struct m66592 *m66592)
 {
+#if defined(CONFIG_SUPERH_BUILT_IN_M66592)
+	usbf_stop_clock();
+#else
 	m66592_bclr(m66592, M66592_SCKE, M66592_SYSCFG);
 	udelay(1);
 	m66592_bclr(m66592, M66592_PLLC, M66592_SYSCFG);
@@ -646,15 +680,20 @@
 	m66592_bclr(m66592, M66592_RCKE, M66592_SYSCFG);
 	udelay(1);
 	m66592_bclr(m66592, M66592_XCKE, M66592_SYSCFG);
+#endif
 }
 
 static void m66592_start_xclock(struct m66592 *m66592)
 {
+#if defined(CONFIG_SUPERH_BUILT_IN_M66592)
+	usbf_start_clock();
+#else
 	u16 tmp;
 
 	tmp = m66592_read(m66592, M66592_SYSCFG);
 	if (!(tmp & M66592_XCKE))
 		m66592_bset(m66592, M66592_XCKE, M66592_SYSCFG);
+#endif
 }
 
 /*-------------------------------------------------------------------------*/
@@ -709,7 +748,7 @@
 	do {
 		tmp = m66592_read(m66592, ep->fifoctr);
 		if (i++ > 100000) {
-			printk(KERN_ERR "pipe0 is busy. maybe cpu i/o bus"
+			pr_err("pipe0 is busy. maybe cpu i/o bus "
 				"conflict. please power off this controller.");
 			return;
 		}
@@ -759,7 +798,7 @@
 	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);
+		pr_err("write fifo not ready. pipnum=%d\n", pipenum);
 		return;
 	}
 
@@ -808,7 +847,7 @@
 		req->req.status = -EPIPE;
 		pipe_stop(m66592, pipenum);
 		pipe_irq_disable(m66592, pipenum);
-		printk(KERN_ERR "read fifo not ready");
+		pr_err("read fifo not ready");
 		return;
 	}
 
@@ -1063,7 +1102,7 @@
 		break;
 	default:
 		m66592->gadget.speed = USB_SPEED_UNKNOWN;
-		printk(KERN_ERR "USB speed unknown\n");
+		pr_err("USB speed unknown\n");
 	}
 }
 
@@ -1122,7 +1161,7 @@
 		control_end(m66592, 0);
 		break;
 	default:
-		printk(KERN_ERR "ctrl_stage: unexpect ctsq(%x)\n", ctsq);
+		pr_err("ctrl_stage: unexpect ctsq(%x)\n", ctsq);
 		break;
 	}
 }
@@ -1142,6 +1181,19 @@
 	intsts0 = m66592_read(m66592, M66592_INTSTS0);
 	intenb0 = m66592_read(m66592, M66592_INTENB0);
 
+#if defined(CONFIG_SUPERH_BUILT_IN_M66592)
+	if (!intsts0 && !intenb0) {
+		/*
+		 * When USB clock stops, it cannot read register. Even if a
+		 * clock stops, the interrupt occurs. So this driver turn on
+		 * a clock by this timing and do re-reading of register.
+		 */
+		m66592_start_xclock(m66592);
+		intsts0 = m66592_read(m66592, M66592_INTSTS0);
+		intenb0 = m66592_read(m66592, M66592_INTENB0);
+	}
+#endif
+
 	savepipe = m66592_read(m66592, M66592_CFIFOSEL);
 
 	mask0 = intsts0 & intenb0;
@@ -1409,13 +1461,13 @@
 
 	retval = device_add(&m66592->gadget.dev);
 	if (retval) {
-		printk(KERN_ERR "device_add error (%d)\n", retval);
+		pr_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);
+		pr_err("bind to driver error (%d)\n", retval);
 		device_del(&m66592->gadget.dev);
 		goto error;
 	}
@@ -1456,6 +1508,7 @@
 	m66592_bclr(m66592, M66592_VBSE | M66592_URST, M66592_INTENB0);
 
 	driver->unbind(&m66592->gadget);
+	m66592->gadget.dev.driver = NULL;
 
 	init_controller(m66592);
 	disable_controller(m66592);
@@ -1485,6 +1538,7 @@
 	iounmap(m66592->reg);
 	free_irq(platform_get_irq(pdev, 0), m66592);
 	m66592_free_request(&m66592->ep[0].ep, m66592->ep0_req);
+	usbf_stop_clock();
 	kfree(m66592);
 	return 0;
 }
@@ -1508,28 +1562,28 @@
 			(char *)udc_name);
 	if (!res) {
 		ret = -ENODEV;
-		printk(KERN_ERR "platform_get_resource_byname error.\n");
+		pr_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");
+		pr_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");
+		pr_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");
+		pr_err("kzalloc error\n");
 		goto clean_up;
 	}
 
@@ -1555,7 +1609,7 @@
 	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);
+		pr_err("request_irq error (%d)\n", ret);
 		goto clean_up;
 	}
 
diff --git a/drivers/usb/gadget/m66592-udc.h b/drivers/usb/gadget/m66592-udc.h
index bfa0c64..17b792b 100644
--- a/drivers/usb/gadget/m66592-udc.h
+++ b/drivers/usb/gadget/m66592-udc.h
@@ -72,6 +72,11 @@
 #define   M66592_P_TST_J	 0x0001		/* PERI TEST J */
 #define   M66592_P_TST_NORMAL	 0x0000		/* PERI Normal Mode */
 
+#if defined(CONFIG_SUPERH_BUILT_IN_M66592)
+#define M66592_CFBCFG		0x0A
+#define M66592_D0FBCFG		0x0C
+#define M66592_LITTLE		0x0100	/* b8: Little endian mode */
+#else
 #define M66592_PINCFG		0x0A
 #define M66592_LDRV		0x8000	/* b15: Drive Current Adjust */
 #define M66592_BIGEND		0x0100	/* b8: Big endian mode */
@@ -91,6 +96,7 @@
 #define M66592_PKTM		0x0020	/* b5: Packet mode */
 #define M66592_DENDE		0x0010	/* b4: Dend enable */
 #define M66592_OBUS		0x0004	/* b2: OUTbus mode */
+#endif	/* #if defined(CONFIG_SUPERH_BUILT_IN_M66592) */
 
 #define M66592_CFIFO		0x10
 #define M66592_D0FIFO		0x14
@@ -103,9 +109,13 @@
 #define M66592_REW		0x4000	/* b14: Buffer rewind */
 #define M66592_DCLRM		0x2000	/* b13: DMA buffer clear mode */
 #define M66592_DREQE		0x1000	/* b12: DREQ output enable */
+#if defined(CONFIG_SUPERH_BUILT_IN_M66592)
+#define M66592_MBW		0x0800	/* b11: Maximum bit width for FIFO */
+#else
 #define M66592_MBW		0x0400	/* b10: Maximum bit width for FIFO */
 #define   M66592_MBW_8		 0x0000   /*  8bit */
 #define   M66592_MBW_16		 0x0400   /* 16bit */
+#endif	/* #if defined(CONFIG_SUPERH_BUILT_IN_M66592) */
 #define M66592_TRENB		0x0200	/* b9: Transaction counter enable */
 #define M66592_TRCLR		0x0100	/* b8: Transaction counter clear */
 #define M66592_DEZPM		0x0080	/* b7: Zero-length packet mode */
@@ -530,8 +540,13 @@
 {
 	unsigned long fifoaddr = (unsigned long)m66592->reg + offset;
 
+#if defined(CONFIG_SUPERH_BUILT_IN_M66592)
+	len = (len + 3) / 4;
+	insl(fifoaddr, buf, len);
+#else
 	len = (len + 1) / 2;
 	insw(fifoaddr, buf, len);
+#endif
 }
 
 static inline void m66592_write(struct m66592 *m66592, u16 val,
@@ -545,6 +560,24 @@
 		void *buf, unsigned long len)
 {
 	unsigned long fifoaddr = (unsigned long)m66592->reg + offset;
+#if defined(CONFIG_SUPERH_BUILT_IN_M66592)
+	unsigned long count;
+	unsigned char *pb;
+	int i;
+
+	count = len / 4;
+	outsl(fifoaddr, buf, count);
+
+	if (len & 0x00000003) {
+		pb = buf + count * 4;
+		for (i = 0; i < (len & 0x00000003); i++) {
+			if (m66592_read(m66592, M66592_CFBCFG))	/* little */
+				outb(pb[i], fifoaddr + (3 - i));
+			else
+				outb(pb[i], fifoaddr + i);
+		}
+	}
+#else
 	unsigned long odd = len & 0x0001;
 
 	len = len / 2;
@@ -553,6 +586,7 @@
 		unsigned char *p = buf + len*2;
 		outb(*p, fifoaddr);
 	}
+#endif	/* #if defined(CONFIG_SUPERH_BUILT_IN_M66592) */
 }
 
 static inline void m66592_mdfy(struct m66592 *m66592, u16 val, u16 pat,
@@ -570,6 +604,26 @@
 #define m66592_bset(m66592, val, offset)	\
 			m66592_mdfy(m66592, val, 0, offset)
 
+#if defined(CONFIG_SUPERH_BUILT_IN_M66592)
+#include <asm/io.h>
+#define MSTPCR2		0xA4150038	/* for SH7722 */
+#define MSTPCR2_USB	0x00000800
+
+static inline void usbf_start_clock(void)
+{
+	ctrl_outl(ctrl_inl(MSTPCR2) & ~MSTPCR2_USB, MSTPCR2);
+}
+
+static inline void usbf_stop_clock(void)
+{
+	ctrl_outl(ctrl_inl(MSTPCR2) | MSTPCR2_USB, MSTPCR2);
+}
+
+#else
+#define usbf_start_clock(x)
+#define usbf_stop_clock(x)
+#endif	/* if defined(CONFIG_SUPERH_BUILT_IN_M66592) */
+
 #endif	/* ifndef __M66592_UDC_H__ */
 
 
diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c
index d5d473f..33469cf 100644
--- a/drivers/usb/gadget/net2280.c
+++ b/drivers/usb/gadget/net2280.c
@@ -2435,7 +2435,7 @@
 			break;
 		default:
 delegate:
-			VDEBUG (dev, "setup %02x.%02x v%04x i%04x l%04x"
+			VDEBUG (dev, "setup %02x.%02x v%04x i%04x l%04x "
 				"ep_cfg %08x\n",
 				u.r.bRequestType, u.r.bRequest,
 				w_value, w_index, w_length,
diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c
index d377154..e6d68bd 100644
--- a/drivers/usb/gadget/omap_udc.c
+++ b/drivers/usb/gadget/omap_udc.c
@@ -4,6 +4,8 @@
  * Copyright (C) 2004 Texas Instruments, Inc.
  * Copyright (C) 2004-2005 David Brownell
  *
+ * OMAP2 & DMA support by Kyungmin Park <kyungmin.park@samsung.com>
+ *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
@@ -60,11 +62,6 @@
 /* bulk DMA seems to be behaving for both IN and OUT */
 #define	USE_DMA
 
-/* FIXME: OMAP2 currently has some problem in DMA mode */
-#ifdef CONFIG_ARCH_OMAP2
-#undef USE_DMA
-#endif
-
 /* ISO too */
 #define	USE_ISO
 
@@ -73,6 +70,8 @@
 
 #define	DMA_ADDR_INVALID	(~(dma_addr_t)0)
 
+#define OMAP2_DMA_CH(ch)	(((ch) - 1) << 1)
+#define OMAP24XX_DMA(name, ch)	(OMAP24XX_DMA_##name + OMAP2_DMA_CH(ch))
 
 /*
  * The OMAP UDC needs _very_ early endpoint setup:  before enabling the
@@ -571,20 +570,25 @@
 	const int	sync_mode = cpu_is_omap15xx()
 				? OMAP_DMA_SYNC_FRAME
 				: OMAP_DMA_SYNC_ELEMENT;
+	int		dma_trigger = 0;
+
+	if (cpu_is_omap24xx())
+		dma_trigger = OMAP24XX_DMA(USB_W2FC_TX0, ep->dma_channel);
 
 	/* measure length in either bytes or packets */
 	if ((cpu_is_omap16xx() && length <= UDC_TXN_TSC)
+			|| (cpu_is_omap24xx() && length < ep->maxpacket)
 			|| (cpu_is_omap15xx() && length < ep->maxpacket)) {
 		txdma_ctrl = UDC_TXN_EOT | length;
 		omap_set_dma_transfer_params(ep->lch, OMAP_DMA_DATA_TYPE_S8,
-				length, 1, sync_mode, 0, 0);
+				length, 1, sync_mode, dma_trigger, 0);
 	} else {
 		length = min(length / ep->maxpacket,
 				(unsigned) UDC_TXN_TSC + 1);
 		txdma_ctrl = length;
 		omap_set_dma_transfer_params(ep->lch, OMAP_DMA_DATA_TYPE_S16,
 				ep->ep.maxpacket >> 1, length, sync_mode,
-				0, 0);
+				dma_trigger, 0);
 		length *= ep->maxpacket;
 	}
 	omap_set_dma_src_params(ep->lch, OMAP_DMA_PORT_EMIFF,
@@ -622,20 +626,31 @@
 
 static void next_out_dma(struct omap_ep *ep, struct omap_req *req)
 {
-	unsigned packets;
+	unsigned packets = req->req.length - req->req.actual;
+	int dma_trigger = 0;
+
+	if (cpu_is_omap24xx())
+		dma_trigger = OMAP24XX_DMA(USB_W2FC_RX0, ep->dma_channel);
 
 	/* NOTE:  we filtered out "short reads" before, so we know
 	 * the buffer has only whole numbers of packets.
+	 * except MODE SELECT(6) sent the 24 bytes data in OMAP24XX DMA mode
 	 */
-
-	/* set up this DMA transfer, enable the fifo, start */
-	packets = (req->req.length - req->req.actual) / ep->ep.maxpacket;
-	packets = min(packets, (unsigned)UDC_RXN_TC + 1);
-	req->dma_bytes = packets * ep->ep.maxpacket;
-	omap_set_dma_transfer_params(ep->lch, OMAP_DMA_DATA_TYPE_S16,
-			ep->ep.maxpacket >> 1, packets,
-			OMAP_DMA_SYNC_ELEMENT,
-			0, 0);
+	if (cpu_is_omap24xx() && packets < ep->maxpacket) {
+		omap_set_dma_transfer_params(ep->lch, OMAP_DMA_DATA_TYPE_S8,
+				packets, 1, OMAP_DMA_SYNC_ELEMENT,
+				dma_trigger, 0);
+		req->dma_bytes = packets;
+	} else {
+		/* set up this DMA transfer, enable the fifo, start */
+		packets /= ep->ep.maxpacket;
+		packets = min(packets, (unsigned)UDC_RXN_TC + 1);
+		req->dma_bytes = packets * ep->ep.maxpacket;
+		omap_set_dma_transfer_params(ep->lch, OMAP_DMA_DATA_TYPE_S16,
+				ep->ep.maxpacket >> 1, packets,
+				OMAP_DMA_SYNC_ELEMENT,
+				dma_trigger, 0);
+	}
 	omap_set_dma_dest_params(ep->lch, OMAP_DMA_PORT_EMIFF,
 		OMAP_DMA_AMODE_POST_INC, req->req.dma + req->req.actual,
 		0, 0);
@@ -743,6 +758,7 @@
 {
 	u16	reg;
 	int	status, restart, is_in;
+	int	dma_channel;
 
 	is_in = ep->bEndpointAddress & USB_DIR_IN;
 	if (is_in)
@@ -769,11 +785,15 @@
 	ep->dma_channel = channel;
 
 	if (is_in) {
-		status = omap_request_dma(OMAP_DMA_USB_W2FC_TX0 - 1 + channel,
+		if (cpu_is_omap24xx())
+			dma_channel = OMAP24XX_DMA(USB_W2FC_TX0, channel);
+		else
+			dma_channel = OMAP_DMA_USB_W2FC_TX0 - 1 + channel;
+		status = omap_request_dma(dma_channel,
 			ep->ep.name, dma_error, ep, &ep->lch);
 		if (status == 0) {
 			UDC_TXDMA_CFG_REG = reg;
-			/* EMIFF */
+			/* EMIFF or SDRC */
 			omap_set_dma_src_burst_mode(ep->lch,
 						OMAP_DMA_DATA_BURST_4);
 			omap_set_dma_src_data_pack(ep->lch, 1);
@@ -785,7 +805,12 @@
 				0, 0);
 		}
 	} else {
-		status = omap_request_dma(OMAP_DMA_USB_W2FC_RX0 - 1 + channel,
+		if (cpu_is_omap24xx())
+			dma_channel = OMAP24XX_DMA(USB_W2FC_RX0, channel);
+		else
+			dma_channel = OMAP_DMA_USB_W2FC_RX0 - 1 + channel;
+
+		status = omap_request_dma(dma_channel,
 			ep->ep.name, dma_error, ep, &ep->lch);
 		if (status == 0) {
 			UDC_RXDMA_CFG_REG = reg;
@@ -795,7 +820,7 @@
 				OMAP_DMA_AMODE_CONSTANT,
 				(unsigned long) io_v2p((u32)&UDC_DATA_DMA_REG),
 				0, 0);
-			/* EMIFF */
+			/* EMIFF or SDRC */
 			omap_set_dma_dest_burst_mode(ep->lch,
 						OMAP_DMA_DATA_BURST_4);
 			omap_set_dma_dest_data_pack(ep->lch, 1);
@@ -808,7 +833,7 @@
 		omap_disable_dma_irq(ep->lch, OMAP_DMA_BLOCK_IRQ);
 
 		/* channel type P: hw synch (fifo) */
-		if (!cpu_is_omap15xx())
+		if (cpu_class_is_omap1() && !cpu_is_omap15xx())
 			OMAP1_DMA_LCH_CTRL_REG(ep->lch) = 2;
 	}
 
@@ -926,11 +951,13 @@
 
 	/* this isn't bogus, but OMAP DMA isn't the only hardware to
 	 * have a hard time with partial packet reads...  reject it.
+	 * Except OMAP2 can handle the small packets.
 	 */
 	if (use_dma
 			&& ep->has_dma
 			&& ep->bEndpointAddress != 0
 			&& (ep->bEndpointAddress & USB_DIR_IN) == 0
+			&& !cpu_class_is_omap2()
 			&& (req->req.length % ep->ep.maxpacket) != 0) {
 		DBG("%s, no partial packet OUT reads\n", __FUNCTION__);
 		return -EMSGSIZE;
@@ -1001,7 +1028,7 @@
 
 				/* STATUS for zero length DATA stages is
 				 * always an IN ... even for IN transfers,
-				 * a wierd case which seem to stall OMAP.
+				 * a weird case which seem to stall OMAP.
 				 */
 				UDC_EP_NUM_REG = (UDC_EP_SEL|UDC_EP_DIR);
 				UDC_CTRL_REG = UDC_CLR_EP;
diff --git a/drivers/usb/gadget/omap_udc.h b/drivers/usb/gadget/omap_udc.h
index 1dc398b..c6b9cbc 100644
--- a/drivers/usb/gadget/omap_udc.h
+++ b/drivers/usb/gadget/omap_udc.h
@@ -182,21 +182,16 @@
 
 /*-------------------------------------------------------------------------*/
 
-#ifdef DEBUG
-#define DBG(stuff...)		printk(KERN_DEBUG "udc: " stuff)
-#else
-#define DBG(stuff...)		do{}while(0)
-#endif
-
 #ifdef VERBOSE
 #    define VDBG		DBG
 #else
 #    define VDBG(stuff...)	do{}while(0)
 #endif
 
-#define ERR(stuff...)		printk(KERN_ERR "udc: " stuff)
-#define WARN(stuff...)		printk(KERN_WARNING "udc: " stuff)
-#define INFO(stuff...)		printk(KERN_INFO "udc: " stuff)
+#define ERR(stuff...)		pr_err("udc: " stuff)
+#define WARN(stuff...)		pr_warning("udc: " stuff)
+#define INFO(stuff...)		pr_info("udc: " stuff)
+#define DBG(stuff...)		pr_debug("udc: " stuff)
 
 /*-------------------------------------------------------------------------*/
 
diff --git a/drivers/usb/gadget/printer.c b/drivers/usb/gadget/printer.c
new file mode 100644
index 0000000..9fdabc8
--- /dev/null
+++ b/drivers/usb/gadget/printer.c
@@ -0,0 +1,1592 @@
+/*
+ * printer.c -- Printer gadget driver
+ *
+ * Copyright (C) 2003-2005 David Brownell
+ * Copyright (C) 2006 Craig W. Nadler
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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/utsname.h>
+#include <linux/device.h>
+#include <linux/moduleparam.h>
+#include <linux/fs.h>
+#include <linux/poll.h>
+#include <linux/types.h>
+#include <linux/ctype.h>
+#include <linux/cdev.h>
+
+#include <asm/byteorder.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <asm/system.h>
+#include <linux/uaccess.h>
+#include <asm/unaligned.h>
+
+#include <linux/usb/ch9.h>
+#include <linux/usb/gadget.h>
+#include <linux/usb/g_printer.h>
+
+#include "gadget_chips.h"
+
+#define DRIVER_DESC		"Printer Gadget"
+#define DRIVER_VERSION		"2007 OCT 06"
+
+static const char shortname [] = "printer";
+static const char driver_desc [] = DRIVER_DESC;
+
+static dev_t g_printer_devno;
+
+static struct class *usb_gadget_class;
+
+/*-------------------------------------------------------------------------*/
+
+struct printer_dev {
+	spinlock_t		lock;		/* lock this structure */
+	/* lock buffer lists during read/write calls */
+	spinlock_t		lock_printer_io;
+	struct usb_gadget	*gadget;
+	struct usb_request	*req;		/* for control responses */
+	u8			config;
+	s8			interface;
+	struct usb_ep		*in_ep, *out_ep;
+	const struct usb_endpoint_descriptor
+				*in, *out;
+	struct list_head	rx_reqs;	/* List of free RX structs */
+	struct list_head	rx_reqs_active;	/* List of Active RX xfers */
+	struct list_head	rx_buffers;	/* List of completed xfers */
+	/* wait until there is data to be read. */
+	wait_queue_head_t	rx_wait;
+	struct list_head	tx_reqs;	/* List of free TX structs */
+	struct list_head	tx_reqs_active; /* List of Active TX xfers */
+	/* Wait until there are write buffers available to use. */
+	wait_queue_head_t	tx_wait;
+	/* Wait until all write buffers have been sent. */
+	wait_queue_head_t	tx_flush_wait;
+	struct usb_request	*current_rx_req;
+	size_t			current_rx_bytes;
+	u8			*current_rx_buf;
+	u8			printer_status;
+	u8			reset_printer;
+	struct class_device	*printer_class_dev;
+	struct cdev		printer_cdev;
+	struct device		*pdev;
+	u8			printer_cdev_open;
+	wait_queue_head_t	wait;
+};
+
+static struct printer_dev usb_printer_gadget;
+
+/*-------------------------------------------------------------------------*/
+
+/* DO NOT REUSE THESE IDs with a protocol-incompatible driver!!  Ever!!
+ * Instead:  allocate your own, using normal USB-IF procedures.
+ */
+
+/* Thanks to NetChip Technologies for donating this product ID.
+ */
+#define PRINTER_VENDOR_NUM	0x0525		/* NetChip */
+#define PRINTER_PRODUCT_NUM	0xa4a8		/* Linux-USB Printer Gadget */
+
+/* Some systems will want different product identifers published in the
+ * device descriptor, either numbers or strings or both.  These string
+ * parameters are in UTF-8 (superset of ASCII's 7 bit characters).
+ */
+
+static ushort __initdata idVendor;
+module_param(idVendor, ushort, S_IRUGO);
+MODULE_PARM_DESC(idVendor, "USB Vendor ID");
+
+static ushort __initdata idProduct;
+module_param(idProduct, ushort, S_IRUGO);
+MODULE_PARM_DESC(idProduct, "USB Product ID");
+
+static ushort __initdata bcdDevice;
+module_param(bcdDevice, ushort, S_IRUGO);
+MODULE_PARM_DESC(bcdDevice, "USB Device version (BCD)");
+
+static char *__initdata iManufacturer;
+module_param(iManufacturer, charp, S_IRUGO);
+MODULE_PARM_DESC(iManufacturer, "USB Manufacturer string");
+
+static char *__initdata iProduct;
+module_param(iProduct, charp, S_IRUGO);
+MODULE_PARM_DESC(iProduct, "USB Product string");
+
+static char *__initdata iSerialNum;
+module_param(iSerialNum, charp, S_IRUGO);
+MODULE_PARM_DESC(iSerialNum, "1");
+
+static char *__initdata iPNPstring;
+module_param(iPNPstring, charp, S_IRUGO);
+MODULE_PARM_DESC(iPNPstring, "MFG:linux;MDL:g_printer;CLS:PRINTER;SN:1;");
+
+/* Number of requests to allocate per endpoint, not used for ep0. */
+static unsigned qlen = 10;
+module_param(qlen, uint, S_IRUGO|S_IWUSR);
+
+#define QLEN	qlen
+
+#ifdef CONFIG_USB_GADGET_DUALSPEED
+#define DEVSPEED	USB_SPEED_HIGH
+#else   /* full speed (low speed doesn't do bulk) */
+#define DEVSPEED        USB_SPEED_FULL
+#endif
+
+/*-------------------------------------------------------------------------*/
+
+#define xprintk(d, level, fmt, args...) \
+	printk(level "%s: " fmt, DRIVER_DESC, ## args)
+
+#ifdef DEBUG
+#define DBG(dev, fmt, args...) \
+	xprintk(dev, KERN_DEBUG, fmt, ## args)
+#else
+#define DBG(dev, fmt, args...) \
+	do { } while (0)
+#endif /* DEBUG */
+
+#ifdef VERBOSE
+#define VDBG(dev, fmt, args...) \
+	xprintk(dev, KERN_DEBUG, fmt, ## args)
+#else
+#define VDBG(dev, fmt, args...) \
+	do { } while (0)
+#endif /* VERBOSE */
+
+#define ERROR(dev, fmt, args...) \
+	xprintk(dev, KERN_ERR, fmt, ## args)
+#define WARN(dev, fmt, args...) \
+	xprintk(dev, KERN_WARNING, fmt, ## args)
+#define INFO(dev, fmt, args...) \
+	xprintk(dev, KERN_INFO, fmt, ## args)
+
+/*-------------------------------------------------------------------------*/
+
+/* USB DRIVER HOOKUP (to the hardware driver, below us), mostly
+ * ep0 implementation:  descriptors, config management, setup().
+ * also optional class-specific notification interrupt transfer.
+ */
+
+/*
+ * DESCRIPTORS ... most are static, but strings and (full) configuration
+ * descriptors are built on demand.
+ */
+
+#define STRING_MANUFACTURER		1
+#define STRING_PRODUCT			2
+#define STRING_SERIALNUM		3
+
+/* holds our biggest descriptor */
+#define USB_DESC_BUFSIZE		256
+#define USB_BUFSIZE			8192
+
+/* This device advertises one configuration. */
+#define DEV_CONFIG_VALUE		1
+#define	PRINTER_INTERFACE		0
+
+static struct usb_device_descriptor device_desc = {
+	.bLength =		sizeof device_desc,
+	.bDescriptorType =	USB_DT_DEVICE,
+	.bcdUSB =		__constant_cpu_to_le16(0x0200),
+	.bDeviceClass =		USB_CLASS_PER_INTERFACE,
+	.bDeviceSubClass =	0,
+	.bDeviceProtocol =	0,
+	.idVendor =		__constant_cpu_to_le16(PRINTER_VENDOR_NUM),
+	.idProduct =		__constant_cpu_to_le16(PRINTER_PRODUCT_NUM),
+	.iManufacturer =	STRING_MANUFACTURER,
+	.iProduct =		STRING_PRODUCT,
+	.iSerialNumber =	STRING_SERIALNUM,
+	.bNumConfigurations =	1
+};
+
+static struct usb_otg_descriptor otg_desc = {
+	.bLength =		sizeof otg_desc,
+	.bDescriptorType =	USB_DT_OTG,
+	.bmAttributes =		USB_OTG_SRP
+};
+
+static struct usb_config_descriptor config_desc = {
+	.bLength =		sizeof config_desc,
+	.bDescriptorType =	USB_DT_CONFIG,
+
+	/* compute wTotalLength on the fly */
+	.bNumInterfaces =	1,
+	.bConfigurationValue =	DEV_CONFIG_VALUE,
+	.iConfiguration =	0,
+	.bmAttributes =		USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
+	.bMaxPower =		1	/* Self-Powered */
+};
+
+static struct usb_interface_descriptor intf_desc = {
+	.bLength =		sizeof intf_desc,
+	.bDescriptorType =	USB_DT_INTERFACE,
+	.bInterfaceNumber =	PRINTER_INTERFACE,
+	.bNumEndpoints =	2,
+	.bInterfaceClass =	USB_CLASS_PRINTER,
+	.bInterfaceSubClass =	1,	/* Printer Sub-Class */
+	.bInterfaceProtocol =	2,	/* Bi-Directional */
+	.iInterface =		0
+};
+
+static struct usb_endpoint_descriptor fs_ep_in_desc = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+	.bEndpointAddress =	USB_DIR_IN,
+	.bmAttributes =		USB_ENDPOINT_XFER_BULK
+};
+
+static struct usb_endpoint_descriptor fs_ep_out_desc = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+	.bEndpointAddress =	USB_DIR_OUT,
+	.bmAttributes =		USB_ENDPOINT_XFER_BULK
+};
+
+static const struct usb_descriptor_header *fs_printer_function [11] = {
+	(struct usb_descriptor_header *) &otg_desc,
+	(struct usb_descriptor_header *) &intf_desc,
+	(struct usb_descriptor_header *) &fs_ep_in_desc,
+	(struct usb_descriptor_header *) &fs_ep_out_desc,
+	NULL
+};
+
+#ifdef	CONFIG_USB_GADGET_DUALSPEED
+
+/*
+ * usb 2.0 devices need to expose both high speed and full speed
+ * descriptors, unless they only run at full speed.
+ */
+
+static struct usb_endpoint_descriptor hs_ep_in_desc = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
+	.wMaxPacketSize =	__constant_cpu_to_le16(512)
+};
+
+static struct usb_endpoint_descriptor hs_ep_out_desc = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
+	.wMaxPacketSize =	__constant_cpu_to_le16(512)
+};
+
+static struct usb_qualifier_descriptor dev_qualifier = {
+	.bLength =		sizeof dev_qualifier,
+	.bDescriptorType =	USB_DT_DEVICE_QUALIFIER,
+	.bcdUSB =		__constant_cpu_to_le16(0x0200),
+	.bDeviceClass =		USB_CLASS_PRINTER,
+	.bNumConfigurations =	1
+};
+
+static const struct usb_descriptor_header *hs_printer_function [11] = {
+	(struct usb_descriptor_header *) &otg_desc,
+	(struct usb_descriptor_header *) &intf_desc,
+	(struct usb_descriptor_header *) &hs_ep_in_desc,
+	(struct usb_descriptor_header *) &hs_ep_out_desc,
+	NULL
+};
+
+/* maxpacket and other transfer characteristics vary by speed. */
+#define ep_desc(g, hs, fs) (((g)->speed == USB_SPEED_HIGH)?(hs):(fs))
+
+#else
+
+/* if there's no high speed support, maxpacket doesn't change. */
+#define ep_desc(g, hs, fs) (((void)(g)), (fs))
+
+#endif	/* !CONFIG_USB_GADGET_DUALSPEED */
+
+/*-------------------------------------------------------------------------*/
+
+/* descriptors that are built on-demand */
+
+static char				manufacturer [50];
+static char				product_desc [40] = DRIVER_DESC;
+static char				serial_num [40] = "1";
+static char				pnp_string [1024] =
+	"XXMFG:linux;MDL:g_printer;CLS:PRINTER;SN:1;";
+
+/* static strings, in UTF-8 */
+static struct usb_string		strings [] = {
+	{ STRING_MANUFACTURER,	manufacturer, },
+	{ STRING_PRODUCT,	product_desc, },
+	{ STRING_SERIALNUM,	serial_num, },
+	{  }		/* end of list */
+};
+
+static struct usb_gadget_strings	stringtab = {
+	.language	= 0x0409,	/* en-us */
+	.strings	= strings,
+};
+
+/*-------------------------------------------------------------------------*/
+
+static struct usb_request *
+printer_req_alloc(struct usb_ep *ep, unsigned len, gfp_t gfp_flags)
+{
+	struct usb_request	*req;
+
+	req = usb_ep_alloc_request(ep, gfp_flags);
+
+	if (req != NULL) {
+		req->length = len;
+		req->buf = kmalloc(len, gfp_flags);
+		if (req->buf == NULL) {
+			usb_ep_free_request(ep, req);
+			return NULL;
+		}
+	}
+
+	return req;
+}
+
+static void
+printer_req_free(struct usb_ep *ep, struct usb_request *req)
+{
+	if (ep != NULL && req != NULL) {
+		kfree(req->buf);
+		usb_ep_free_request(ep, req);
+	}
+}
+
+/*-------------------------------------------------------------------------*/
+
+static void rx_complete(struct usb_ep *ep, struct usb_request *req)
+{
+	struct printer_dev	*dev = ep->driver_data;
+	int			status = req->status;
+	unsigned long		flags;
+
+	spin_lock_irqsave(&dev->lock, flags);
+
+	list_del_init(&req->list);	/* Remode from Active List */
+
+	switch (status) {
+
+	/* normal completion */
+	case 0:
+		list_add_tail(&req->list, &dev->rx_buffers);
+		wake_up_interruptible(&dev->rx_wait);
+		DBG(dev, "G_Printer : rx length %d\n", req->actual);
+		break;
+
+	/* software-driven interface shutdown */
+	case -ECONNRESET:		/* unlink */
+	case -ESHUTDOWN:		/* disconnect etc */
+		VDBG(dev, "rx shutdown, code %d\n", status);
+		list_add(&req->list, &dev->rx_reqs);
+		break;
+
+	/* for hardware automagic (such as pxa) */
+	case -ECONNABORTED:		/* endpoint reset */
+		DBG(dev, "rx %s reset\n", ep->name);
+		list_add(&req->list, &dev->rx_reqs);
+		break;
+
+	/* data overrun */
+	case -EOVERFLOW:
+		/* FALLTHROUGH */
+
+	default:
+		DBG(dev, "rx status %d\n", status);
+		list_add(&req->list, &dev->rx_reqs);
+		break;
+	}
+	spin_unlock_irqrestore(&dev->lock, flags);
+}
+
+static void tx_complete(struct usb_ep *ep, struct usb_request *req)
+{
+	struct printer_dev	*dev = ep->driver_data;
+
+	switch (req->status) {
+	default:
+		VDBG(dev, "tx err %d\n", req->status);
+		/* FALLTHROUGH */
+	case -ECONNRESET:		/* unlink */
+	case -ESHUTDOWN:		/* disconnect etc */
+		break;
+	case 0:
+		break;
+	}
+
+	spin_lock(&dev->lock);
+	/* Take the request struct off the active list and put it on the
+	 * free list.
+	 */
+	list_del_init(&req->list);
+	list_add(&req->list, &dev->tx_reqs);
+	wake_up_interruptible(&dev->tx_wait);
+	if (likely(list_empty(&dev->tx_reqs_active)))
+		wake_up_interruptible(&dev->tx_flush_wait);
+
+	spin_unlock(&dev->lock);
+}
+
+/*-------------------------------------------------------------------------*/
+
+static int
+printer_open(struct inode *inode, struct file *fd)
+{
+	struct printer_dev	*dev;
+	unsigned long		flags;
+	int			ret = -EBUSY;
+
+	dev = container_of(inode->i_cdev, struct printer_dev, printer_cdev);
+
+	spin_lock_irqsave(&dev->lock, flags);
+
+	if (!dev->printer_cdev_open) {
+		dev->printer_cdev_open = 1;
+		fd->private_data = dev;
+		ret = 0;
+		/* Change the printer status to show that it's on-line. */
+		dev->printer_status |= PRINTER_SELECTED;
+	}
+
+	spin_unlock_irqrestore(&dev->lock, flags);
+
+	DBG(dev, "printer_open returned %x\n", ret);
+
+	return ret;
+}
+
+static int
+printer_close(struct inode *inode, struct file *fd)
+{
+	struct printer_dev	*dev = fd->private_data;
+	unsigned long		flags;
+
+	spin_lock_irqsave(&dev->lock, flags);
+	dev->printer_cdev_open = 0;
+	fd->private_data = NULL;
+	/* Change printer status to show that the printer is off-line. */
+	dev->printer_status &= ~PRINTER_SELECTED;
+	spin_unlock_irqrestore(&dev->lock, flags);
+
+	DBG(dev, "printer_close\n");
+
+	return 0;
+}
+
+static ssize_t
+printer_read(struct file *fd, char __user *buf, size_t len, loff_t *ptr)
+{
+	struct printer_dev		*dev = fd->private_data;
+	unsigned long			flags;
+	size_t				size;
+	size_t				bytes_copied;
+	struct usb_request		*req;
+	/* This is a pointer to the current USB rx request. */
+	struct usb_request		*current_rx_req;
+	/* This is the number of bytes in the current rx buffer. */
+	size_t				current_rx_bytes;
+	/* This is a pointer to the current rx buffer. */
+	u8				*current_rx_buf;
+
+	if (len == 0)
+		return -EINVAL;
+
+	DBG(dev, "printer_read trying to read %d bytes\n", (int)len);
+
+	spin_lock(&dev->lock_printer_io);
+	spin_lock_irqsave(&dev->lock, flags);
+
+	/* We will use this flag later to check if a printer reset happened
+	 * after we turn interrupts back on.
+	 */
+	dev->reset_printer = 0;
+
+	while (likely(!list_empty(&dev->rx_reqs))) {
+		int error;
+
+		req = container_of(dev->rx_reqs.next,
+				struct usb_request, list);
+		list_del_init(&req->list);
+
+		/* The USB Host sends us whatever amount of data it wants to
+		 * so we always set the length field to the full USB_BUFSIZE.
+		 * If the amount of data is more than the read() caller asked
+		 * for it will be stored in the request buffer until it is
+		 * asked for by read().
+		 */
+		req->length = USB_BUFSIZE;
+		req->complete = rx_complete;
+
+		error = usb_ep_queue(dev->out_ep, req, GFP_ATOMIC);
+		if (error) {
+			DBG(dev, "rx submit --> %d\n", error);
+			list_add(&req->list, &dev->rx_reqs);
+			break;
+		} else {
+			list_add(&req->list, &dev->rx_reqs_active);
+		}
+	}
+
+	bytes_copied = 0;
+	current_rx_req = dev->current_rx_req;
+	current_rx_bytes = dev->current_rx_bytes;
+	current_rx_buf = dev->current_rx_buf;
+	dev->current_rx_req = NULL;
+	dev->current_rx_bytes = 0;
+	dev->current_rx_buf = NULL;
+
+	/* Check if there is any data in the read buffers. Please note that
+	 * current_rx_bytes is the number of bytes in the current rx buffer.
+	 * If it is zero then check if there are any other rx_buffers that
+	 * are on the completed list. We are only out of data if all rx
+	 * buffers are empty.
+	 */
+	if ((current_rx_bytes == 0) &&
+			(likely(list_empty(&dev->rx_buffers)))) {
+		/* Turn interrupts back on before sleeping. */
+		spin_unlock_irqrestore(&dev->lock, flags);
+
+		/*
+		 * If no data is available check if this is a NON-Blocking
+		 * call or not.
+		 */
+		if (fd->f_flags & (O_NONBLOCK|O_NDELAY)) {
+			spin_unlock(&dev->lock_printer_io);
+			return -EAGAIN;
+		}
+
+		/* Sleep until data is available */
+		wait_event_interruptible(dev->rx_wait,
+				(likely(!list_empty(&dev->rx_buffers))));
+		spin_lock_irqsave(&dev->lock, flags);
+	}
+
+	/* We have data to return then copy it to the caller's buffer.*/
+	while ((current_rx_bytes || likely(!list_empty(&dev->rx_buffers)))
+			&& len) {
+		if (current_rx_bytes == 0) {
+			req = container_of(dev->rx_buffers.next,
+					struct usb_request, list);
+			list_del_init(&req->list);
+
+			if (req->actual && req->buf) {
+				current_rx_req = req;
+				current_rx_bytes = req->actual;
+				current_rx_buf = req->buf;
+			} else {
+				list_add(&req->list, &dev->rx_reqs);
+				continue;
+			}
+		}
+
+		/* Don't leave irqs off while doing memory copies */
+		spin_unlock_irqrestore(&dev->lock, flags);
+
+		if (len > current_rx_bytes)
+			size = current_rx_bytes;
+		else
+			size = len;
+
+		size -= copy_to_user(buf, current_rx_buf, size);
+		bytes_copied += size;
+		len -= size;
+		buf += size;
+
+		spin_lock_irqsave(&dev->lock, flags);
+
+		/* We've disconnected or reset free the req and buffer */
+		if (dev->reset_printer) {
+			printer_req_free(dev->out_ep, current_rx_req);
+			spin_unlock_irqrestore(&dev->lock, flags);
+			spin_unlock(&dev->lock_printer_io);
+			return -EAGAIN;
+		}
+
+		/* If we not returning all the data left in this RX request
+		 * buffer then adjust the amount of data left in the buffer.
+		 * Othewise if we are done with this RX request buffer then
+		 * requeue it to get any incoming data from the USB host.
+		 */
+		if (size < current_rx_bytes) {
+			current_rx_bytes -= size;
+			current_rx_buf += size;
+		} else {
+			list_add(&current_rx_req->list, &dev->rx_reqs);
+			current_rx_bytes = 0;
+			current_rx_buf = NULL;
+			current_rx_req = NULL;
+		}
+	}
+
+	dev->current_rx_req = current_rx_req;
+	dev->current_rx_bytes = current_rx_bytes;
+	dev->current_rx_buf = current_rx_buf;
+
+	spin_unlock_irqrestore(&dev->lock, flags);
+	spin_unlock(&dev->lock_printer_io);
+
+	DBG(dev, "printer_read returned %d bytes\n", (int)bytes_copied);
+
+	if (bytes_copied)
+		return bytes_copied;
+	else
+		return -EAGAIN;
+}
+
+static ssize_t
+printer_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
+{
+	struct printer_dev	*dev = fd->private_data;
+	unsigned long		flags;
+	size_t			size;	/* Amount of data in a TX request. */
+	size_t			bytes_copied = 0;
+	struct usb_request	*req;
+
+	DBG(dev, "printer_write trying to send %d bytes\n", (int)len);
+
+	if (len == 0)
+		return -EINVAL;
+
+	spin_lock(&dev->lock_printer_io);
+	spin_lock_irqsave(&dev->lock, flags);
+
+	/* Check if a printer reset happens while we have interrupts on */
+	dev->reset_printer = 0;
+
+	/* Check if there is any available write buffers */
+	if (likely(list_empty(&dev->tx_reqs))) {
+		/* Turn interrupts back on before sleeping. */
+		spin_unlock_irqrestore(&dev->lock, flags);
+
+		/*
+		 * If write buffers are available check if this is
+		 * a NON-Blocking call or not.
+		 */
+		if (fd->f_flags & (O_NONBLOCK|O_NDELAY)) {
+			spin_unlock(&dev->lock_printer_io);
+			return -EAGAIN;
+		}
+
+		/* Sleep until a write buffer is available */
+		wait_event_interruptible(dev->tx_wait,
+				(likely(!list_empty(&dev->tx_reqs))));
+		spin_lock_irqsave(&dev->lock, flags);
+	}
+
+	while (likely(!list_empty(&dev->tx_reqs)) && len) {
+
+		if (len > USB_BUFSIZE)
+			size = USB_BUFSIZE;
+		else
+			size = len;
+
+		req = container_of(dev->tx_reqs.next, struct usb_request,
+				list);
+		list_del_init(&req->list);
+
+		req->complete = tx_complete;
+		req->length = size;
+
+		/* Check if we need to send a zero length packet. */
+		if (len > size)
+			/* They will be more TX requests so no yet. */
+			req->zero = 0;
+		else
+			/* If the data amount is not a multple of the
+			 * maxpacket size then send a zero length packet.
+			 */
+			req->zero = ((len % dev->in_ep->maxpacket) == 0);
+
+		/* Don't leave irqs off while doing memory copies */
+		spin_unlock_irqrestore(&dev->lock, flags);
+
+		if (copy_from_user(req->buf, buf, size)) {
+			list_add(&req->list, &dev->tx_reqs);
+			spin_unlock(&dev->lock_printer_io);
+			return bytes_copied;
+		}
+
+		bytes_copied += size;
+		len -= size;
+		buf += size;
+
+		spin_lock_irqsave(&dev->lock, flags);
+
+		/* We've disconnected or reset so free the req and buffer */
+		if (dev->reset_printer) {
+			printer_req_free(dev->in_ep, req);
+			spin_unlock_irqrestore(&dev->lock, flags);
+			spin_unlock(&dev->lock_printer_io);
+			return -EAGAIN;
+		}
+
+		if (usb_ep_queue(dev->in_ep, req, GFP_ATOMIC)) {
+			list_add(&req->list, &dev->tx_reqs);
+			spin_unlock_irqrestore(&dev->lock, flags);
+			spin_unlock(&dev->lock_printer_io);
+			return -EAGAIN;
+		}
+
+		list_add(&req->list, &dev->tx_reqs_active);
+
+	}
+
+	spin_unlock_irqrestore(&dev->lock, flags);
+	spin_unlock(&dev->lock_printer_io);
+
+	DBG(dev, "printer_write sent %d bytes\n", (int)bytes_copied);
+
+	if (bytes_copied) {
+		return bytes_copied;
+	} else {
+		return -EAGAIN;
+	}
+}
+
+static int
+printer_fsync(struct file *fd, struct dentry *dentry, int datasync)
+{
+	struct printer_dev	*dev = fd->private_data;
+	unsigned long		flags;
+	int			tx_list_empty;
+
+	spin_lock_irqsave(&dev->lock, flags);
+	tx_list_empty = (likely(list_empty(&dev->tx_reqs)));
+	spin_unlock_irqrestore(&dev->lock, flags);
+
+	if (!tx_list_empty) {
+		/* Sleep until all data has been sent */
+		wait_event_interruptible(dev->tx_flush_wait,
+				(likely(list_empty(&dev->tx_reqs_active))));
+	}
+
+	return 0;
+}
+
+static unsigned int
+printer_poll(struct file *fd, poll_table *wait)
+{
+	struct printer_dev	*dev = fd->private_data;
+	unsigned long		flags;
+	int			status = 0;
+
+	poll_wait(fd, &dev->rx_wait, wait);
+	poll_wait(fd, &dev->tx_wait, wait);
+
+	spin_lock_irqsave(&dev->lock, flags);
+	if (likely(!list_empty(&dev->tx_reqs)))
+		status |= POLLOUT | POLLWRNORM;
+
+	if (likely(!list_empty(&dev->rx_buffers)))
+		status |= POLLIN | POLLRDNORM;
+
+	spin_unlock_irqrestore(&dev->lock, flags);
+
+	return status;
+}
+
+static int
+printer_ioctl(struct inode *inode, struct file *fd, unsigned int code,
+		unsigned long arg)
+{
+	struct printer_dev	*dev = fd->private_data;
+	unsigned long		flags;
+	int			status = 0;
+
+	DBG(dev, "printer_ioctl: cmd=0x%4.4x, arg=%lu\n", code, arg);
+
+	/* handle ioctls */
+
+	spin_lock_irqsave(&dev->lock, flags);
+
+	switch (code) {
+	case GADGET_GET_PRINTER_STATUS:
+		status = (int)dev->printer_status;
+		break;
+	case GADGET_SET_PRINTER_STATUS:
+		dev->printer_status = (u8)arg;
+		break;
+	default:
+		/* could not handle ioctl */
+		DBG(dev, "printer_ioctl: ERROR cmd=0x%4.4xis not supported\n",
+				code);
+		status = -ENOTTY;
+	}
+
+	spin_unlock_irqrestore(&dev->lock, flags);
+
+	return status;
+}
+
+/* used after endpoint configuration */
+static struct file_operations printer_io_operations = {
+	.owner =	THIS_MODULE,
+	.open =		printer_open,
+	.read =		printer_read,
+	.write =	printer_write,
+	.fsync =	printer_fsync,
+	.poll =		printer_poll,
+	.ioctl =	printer_ioctl,
+	.release =	printer_close
+};
+
+/*-------------------------------------------------------------------------*/
+
+static int
+set_printer_interface(struct printer_dev *dev)
+{
+	int			result = 0;
+
+	dev->in = ep_desc(dev->gadget, &hs_ep_in_desc, &fs_ep_in_desc);
+	dev->in_ep->driver_data = dev;
+
+	dev->out = ep_desc(dev->gadget, &hs_ep_out_desc, &fs_ep_out_desc);
+	dev->out_ep->driver_data = dev;
+
+	result = usb_ep_enable(dev->in_ep, dev->in);
+	if (result != 0) {
+		DBG(dev, "enable %s --> %d\n", dev->in_ep->name, result);
+		goto done;
+	}
+
+	result = usb_ep_enable(dev->out_ep, dev->out);
+	if (result != 0) {
+		DBG(dev, "enable %s --> %d\n", dev->in_ep->name, result);
+		goto done;
+	}
+
+done:
+	/* on error, disable any endpoints  */
+	if (result != 0) {
+		(void) usb_ep_disable(dev->in_ep);
+		(void) usb_ep_disable(dev->out_ep);
+		dev->in = NULL;
+		dev->out = NULL;
+	}
+
+	/* caller is responsible for cleanup on error */
+	return result;
+}
+
+static void printer_reset_interface(struct printer_dev *dev)
+{
+	if (dev->interface < 0)
+		return;
+
+	DBG(dev, "%s\n", __FUNCTION__);
+
+	if (dev->in)
+		usb_ep_disable(dev->in_ep);
+
+	if (dev->out)
+		usb_ep_disable(dev->out_ep);
+
+	dev->interface = -1;
+}
+
+/* change our operational config.  must agree with the code
+ * that returns config descriptors, and altsetting code.
+ */
+static int
+printer_set_config(struct printer_dev *dev, unsigned number)
+{
+	int			result = 0;
+	struct usb_gadget	*gadget = dev->gadget;
+
+	if (gadget_is_sa1100(gadget) && dev->config) {
+		/* tx fifo is full, but we can't clear it...*/
+		INFO(dev, "can't change configurations\n");
+		return -ESPIPE;
+	}
+
+	switch (number) {
+	case DEV_CONFIG_VALUE:
+		result = 0;
+		break;
+	default:
+		result = -EINVAL;
+		/* FALL THROUGH */
+	case 0:
+		break;
+	}
+
+	if (result) {
+		usb_gadget_vbus_draw(dev->gadget,
+				dev->gadget->is_otg ? 8 : 100);
+	} else {
+		char *speed;
+		unsigned power;
+
+		power = 2 * config_desc.bMaxPower;
+		usb_gadget_vbus_draw(dev->gadget, power);
+
+		switch (gadget->speed) {
+		case USB_SPEED_FULL:	speed = "full"; break;
+#ifdef CONFIG_USB_GADGET_DUALSPEED
+		case USB_SPEED_HIGH:	speed = "high"; break;
+#endif
+		default:		speed = "?"; break;
+		}
+
+		dev->config = number;
+		INFO(dev, "%s speed config #%d: %d mA, %s\n",
+				speed, number, power, driver_desc);
+	}
+	return result;
+}
+
+static int
+config_buf(enum usb_device_speed speed, u8 *buf, u8 type, unsigned index,
+		int is_otg)
+{
+	int					len;
+	const struct usb_descriptor_header	**function;
+#ifdef CONFIG_USB_GADGET_DUALSPEED
+	int					hs = (speed == USB_SPEED_HIGH);
+
+	if (type == USB_DT_OTHER_SPEED_CONFIG)
+		hs = !hs;
+
+	if (hs) {
+		function = hs_printer_function;
+	} else {
+		function = fs_printer_function;
+	}
+#else
+	function = fs_printer_function;
+#endif
+
+	if (index >= device_desc.bNumConfigurations)
+		return -EINVAL;
+
+	/* for now, don't advertise srp-only devices */
+	if (!is_otg)
+		function++;
+
+	len = usb_gadget_config_buf(&config_desc, buf, USB_DESC_BUFSIZE,
+			function);
+	if (len < 0)
+		return len;
+	((struct usb_config_descriptor *) buf)->bDescriptorType = type;
+	return len;
+}
+
+/* Change our operational Interface. */
+static int
+set_interface(struct printer_dev *dev, unsigned number)
+{
+	int			result = 0;
+
+	if (gadget_is_sa1100(dev->gadget) && dev->interface < 0) {
+		/* tx fifo is full, but we can't clear it...*/
+		INFO(dev, "can't change interfaces\n");
+		return -ESPIPE;
+	}
+
+	/* Free the current interface */
+	switch (dev->interface) {
+	case PRINTER_INTERFACE:
+		printer_reset_interface(dev);
+		break;
+	}
+
+	switch (number) {
+	case PRINTER_INTERFACE:
+		result = set_printer_interface(dev);
+		if (result) {
+			printer_reset_interface(dev);
+		} else {
+			dev->interface = PRINTER_INTERFACE;
+		}
+		break;
+	default:
+		result = -EINVAL;
+		/* FALL THROUGH */
+	}
+
+	if (!result)
+		INFO(dev, "Using interface %x\n", number);
+
+	return result;
+}
+
+static void printer_setup_complete(struct usb_ep *ep, struct usb_request *req)
+{
+	if (req->status || req->actual != req->length)
+		DBG((struct printer_dev *) ep->driver_data,
+				"setup complete --> %d, %d/%d\n",
+				req->status, req->actual, req->length);
+}
+
+static void printer_soft_reset(struct printer_dev *dev)
+{
+	struct usb_request	*req;
+
+	INFO(dev, "Received Printer Reset Request\n");
+
+	if (usb_ep_disable(dev->in_ep))
+		DBG(dev, "Failed to disable USB in_ep\n");
+	if (usb_ep_disable(dev->out_ep))
+		DBG(dev, "Failed to disable USB out_ep\n");
+
+	if (dev->current_rx_req != NULL) {
+		list_add(&dev->current_rx_req->list, &dev->rx_reqs);
+		dev->current_rx_req = NULL;
+	}
+	dev->current_rx_bytes = 0;
+	dev->current_rx_buf = NULL;
+	dev->reset_printer = 1;
+
+	while (likely(!(list_empty(&dev->rx_buffers)))) {
+		req = container_of(dev->rx_buffers.next, struct usb_request,
+				list);
+		list_del_init(&req->list);
+		list_add(&req->list, &dev->rx_reqs);
+	}
+
+	while (likely(!(list_empty(&dev->rx_reqs_active)))) {
+		req = container_of(dev->rx_buffers.next, struct usb_request,
+				list);
+		list_del_init(&req->list);
+		list_add(&req->list, &dev->rx_reqs);
+	}
+
+	while (likely(!(list_empty(&dev->tx_reqs_active)))) {
+		req = container_of(dev->tx_reqs_active.next,
+				struct usb_request, list);
+		list_del_init(&req->list);
+		list_add(&req->list, &dev->tx_reqs);
+	}
+
+	if (usb_ep_enable(dev->in_ep, dev->in))
+		DBG(dev, "Failed to enable USB in_ep\n");
+	if (usb_ep_enable(dev->out_ep, dev->out))
+		DBG(dev, "Failed to enable USB out_ep\n");
+
+	wake_up_interruptible(&dev->tx_wait);
+	wake_up_interruptible(&dev->tx_flush_wait);
+}
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * The setup() callback implements all the ep0 functionality that's not
+ * handled lower down.
+ */
+static int
+printer_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
+{
+	struct printer_dev	*dev = get_gadget_data(gadget);
+	struct usb_request	*req = dev->req;
+	int			value = -EOPNOTSUPP;
+	u16			wIndex = le16_to_cpu(ctrl->wIndex);
+	u16			wValue = le16_to_cpu(ctrl->wValue);
+	u16			wLength = le16_to_cpu(ctrl->wLength);
+
+	DBG(dev, "ctrl req%02x.%02x v%04x i%04x l%d\n",
+		ctrl->bRequestType, ctrl->bRequest, wValue, wIndex, wLength);
+
+	req->complete = printer_setup_complete;
+
+	switch (ctrl->bRequestType&USB_TYPE_MASK) {
+
+	case USB_TYPE_STANDARD:
+		switch (ctrl->bRequest) {
+
+		case USB_REQ_GET_DESCRIPTOR:
+			if (ctrl->bRequestType != USB_DIR_IN)
+				break;
+			switch (wValue >> 8) {
+
+			case USB_DT_DEVICE:
+				value = min(wLength, (u16) sizeof device_desc);
+				memcpy(req->buf, &device_desc, value);
+				break;
+#ifdef CONFIG_USB_GADGET_DUALSPEED
+			case USB_DT_DEVICE_QUALIFIER:
+				if (!gadget->is_dualspeed)
+					break;
+				value = min(wLength,
+						(u16) sizeof dev_qualifier);
+				memcpy(req->buf, &dev_qualifier, value);
+				break;
+
+			case USB_DT_OTHER_SPEED_CONFIG:
+				if (!gadget->is_dualspeed)
+					break;
+				/* FALLTHROUGH */
+#endif /* CONFIG_USB_GADGET_DUALSPEED */
+			case USB_DT_CONFIG:
+				value = config_buf(gadget->speed, req->buf,
+						wValue >> 8,
+						wValue & 0xff,
+						gadget->is_otg);
+				if (value >= 0)
+					value = min(wLength, (u16) value);
+				break;
+
+			case USB_DT_STRING:
+				value = usb_gadget_get_string(&stringtab,
+						wValue & 0xff, req->buf);
+				if (value >= 0)
+					value = min(wLength, (u16) value);
+				break;
+			}
+			break;
+
+		case USB_REQ_SET_CONFIGURATION:
+			if (ctrl->bRequestType != 0)
+				break;
+			if (gadget->a_hnp_support)
+				DBG(dev, "HNP available\n");
+			else if (gadget->a_alt_hnp_support)
+				DBG(dev, "HNP needs a different root port\n");
+			value = printer_set_config(dev, wValue);
+			break;
+		case USB_REQ_GET_CONFIGURATION:
+			if (ctrl->bRequestType != USB_DIR_IN)
+				break;
+			*(u8 *)req->buf = dev->config;
+			value = min(wLength, (u16) 1);
+			break;
+
+		case USB_REQ_SET_INTERFACE:
+			if (ctrl->bRequestType != USB_RECIP_INTERFACE ||
+					!dev->config)
+				break;
+
+			value = set_interface(dev, PRINTER_INTERFACE);
+			break;
+		case USB_REQ_GET_INTERFACE:
+			if (ctrl->bRequestType !=
+					(USB_DIR_IN|USB_RECIP_INTERFACE)
+					|| !dev->config)
+				break;
+
+			*(u8 *)req->buf = dev->interface;
+			value = min(wLength, (u16) 1);
+			break;
+
+		default:
+			goto unknown;
+		}
+		break;
+
+	case USB_TYPE_CLASS:
+		switch (ctrl->bRequest) {
+		case 0: /* Get the IEEE-1284 PNP String */
+			/* Only one printer interface is supported. */
+			if ((wIndex>>8) != PRINTER_INTERFACE)
+				break;
+
+			value = (pnp_string[0]<<8)|pnp_string[1];
+			memcpy(req->buf, pnp_string, value);
+			DBG(dev, "1284 PNP String: %x %s\n", value,
+					&pnp_string[2]);
+			break;
+
+		case 1: /* Get Port Status */
+			/* Only one printer interface is supported. */
+			if (wIndex != PRINTER_INTERFACE)
+				break;
+
+			*(u8 *)req->buf = dev->printer_status;
+			value = min(wLength, (u16) 1);
+			break;
+
+		case 2: /* Soft Reset */
+			/* Only one printer interface is supported. */
+			if (wIndex != PRINTER_INTERFACE)
+				break;
+
+			printer_soft_reset(dev);
+
+			value = 0;
+			break;
+
+		default:
+			goto unknown;
+		}
+		break;
+
+	default:
+unknown:
+		VDBG(dev,
+			"unknown ctrl req%02x.%02x v%04x i%04x l%d\n",
+			ctrl->bRequestType, ctrl->bRequest,
+			wValue, wIndex, wLength);
+		break;
+	}
+
+	/* respond with data transfer before status phase? */
+	if (value >= 0) {
+		req->length = value;
+		req->zero = value < wLength
+				&& (value % gadget->ep0->maxpacket) == 0;
+		value = usb_ep_queue(gadget->ep0, req, GFP_ATOMIC);
+		if (value < 0) {
+			DBG(dev, "ep_queue --> %d\n", value);
+			req->status = 0;
+			printer_setup_complete(gadget->ep0, req);
+		}
+	}
+
+	/* host either stalls (value < 0) or reports success */
+	return value;
+}
+
+static void
+printer_disconnect(struct usb_gadget *gadget)
+{
+	struct printer_dev	*dev = get_gadget_data(gadget);
+	unsigned long		flags;
+
+	DBG(dev, "%s\n", __FUNCTION__);
+
+	spin_lock_irqsave(&dev->lock, flags);
+
+	printer_reset_interface(dev);
+
+	spin_unlock_irqrestore(&dev->lock, flags);
+}
+
+static void
+printer_unbind(struct usb_gadget *gadget)
+{
+	struct printer_dev	*dev = get_gadget_data(gadget);
+	struct usb_request	*req;
+
+
+	DBG(dev, "%s\n", __FUNCTION__);
+
+	/* Remove sysfs files */
+	device_destroy(usb_gadget_class, g_printer_devno);
+
+	/* Remove Character Device */
+	cdev_del(&dev->printer_cdev);
+
+	/* we must already have been disconnected ... no i/o may be active */
+	WARN_ON(!list_empty(&dev->tx_reqs_active));
+	WARN_ON(!list_empty(&dev->rx_reqs_active));
+
+	/* Free all memory for this driver. */
+	while (!list_empty(&dev->tx_reqs)) {
+		req = container_of(dev->tx_reqs.next, struct usb_request,
+				list);
+		list_del(&req->list);
+		printer_req_free(dev->in_ep, req);
+	}
+
+	if (dev->current_rx_req != NULL);
+		printer_req_free(dev->out_ep, dev->current_rx_req);
+
+	while (!list_empty(&dev->rx_reqs)) {
+		req = container_of(dev->rx_reqs.next,
+				struct usb_request, list);
+		list_del(&req->list);
+		printer_req_free(dev->out_ep, req);
+	}
+
+	while (!list_empty(&dev->rx_buffers)) {
+		req = container_of(dev->rx_buffers.next,
+				struct usb_request, list);
+		list_del(&req->list);
+		printer_req_free(dev->out_ep, req);
+	}
+
+	if (dev->req) {
+		printer_req_free(gadget->ep0, dev->req);
+		dev->req = NULL;
+	}
+
+	set_gadget_data(gadget, NULL);
+}
+
+static int __init
+printer_bind(struct usb_gadget *gadget)
+{
+	struct printer_dev	*dev;
+	struct usb_ep		*in_ep, *out_ep;
+	int			status = -ENOMEM;
+	int			gcnum;
+	size_t			len;
+	u32			i;
+	struct usb_request	*req;
+
+	dev = &usb_printer_gadget;
+
+
+	/* Setup the sysfs files for the printer gadget. */
+	dev->pdev = device_create(usb_gadget_class, NULL, g_printer_devno,
+			"g_printer");
+	if (IS_ERR(dev->pdev)) {
+		ERROR(dev, "Failed to create device: g_printer\n");
+		goto fail;
+	}
+
+	/*
+	 * Register a character device as an interface to a user mode
+	 * program that handles the printer specific functionality.
+	 */
+	cdev_init(&dev->printer_cdev, &printer_io_operations);
+	dev->printer_cdev.owner = THIS_MODULE;
+	status = cdev_add(&dev->printer_cdev, g_printer_devno, 1);
+	if (status) {
+		ERROR(dev, "Failed to open char device\n");
+		goto fail;
+	}
+
+	if (gadget_is_sa1100(gadget)) {
+		/* hardware can't write zero length packets. */
+		ERROR(dev, "SA1100 controller is unsupport by this driver\n");
+		goto fail;
+	}
+
+	gcnum = usb_gadget_controller_number(gadget);
+	if (gcnum >= 0) {
+		device_desc.bcdDevice = cpu_to_le16(0x0200 + gcnum);
+	} else {
+		dev_warn(&gadget->dev, "controller '%s' not recognized\n",
+			gadget->name);
+		/* unrecognized, but safe unless bulk is REALLY quirky */
+		device_desc.bcdDevice =
+			__constant_cpu_to_le16(0xFFFF);
+	}
+	snprintf(manufacturer, sizeof(manufacturer), "%s %s with %s",
+		init_utsname()->sysname, init_utsname()->release,
+		gadget->name);
+
+	device_desc.idVendor =
+		__constant_cpu_to_le16(PRINTER_VENDOR_NUM);
+	device_desc.idProduct =
+		__constant_cpu_to_le16(PRINTER_PRODUCT_NUM);
+
+	/* support optional vendor/distro customization */
+	if (idVendor) {
+		if (!idProduct) {
+			dev_err(&gadget->dev, "idVendor needs idProduct!\n");
+			return -ENODEV;
+		}
+		device_desc.idVendor = cpu_to_le16(idVendor);
+		device_desc.idProduct = cpu_to_le16(idProduct);
+		if (bcdDevice)
+			device_desc.bcdDevice = cpu_to_le16(bcdDevice);
+	}
+
+	if (iManufacturer)
+		strlcpy(manufacturer, iManufacturer, sizeof manufacturer);
+
+	if (iProduct)
+		strlcpy(product_desc, iProduct, sizeof product_desc);
+
+	if (iSerialNum)
+		strlcpy(serial_num, iSerialNum, sizeof serial_num);
+
+	if (iPNPstring)
+		strlcpy(&pnp_string[2], iPNPstring, (sizeof pnp_string)-2);
+
+	len = strlen(pnp_string);
+	pnp_string[0] = (len >> 8) & 0xFF;
+	pnp_string[1] = len & 0xFF;
+
+	/* all we really need is bulk IN/OUT */
+	usb_ep_autoconfig_reset(gadget);
+	in_ep = usb_ep_autoconfig(gadget, &fs_ep_in_desc);
+	if (!in_ep) {
+autoconf_fail:
+		dev_err(&gadget->dev, "can't autoconfigure on %s\n",
+			gadget->name);
+		return -ENODEV;
+	}
+	in_ep->driver_data = in_ep;	/* claim */
+
+	out_ep = usb_ep_autoconfig(gadget, &fs_ep_out_desc);
+	if (!out_ep)
+		goto autoconf_fail;
+	out_ep->driver_data = out_ep;	/* claim */
+
+#ifdef	CONFIG_USB_GADGET_DUALSPEED
+	/* assumes ep0 uses the same value for both speeds ... */
+	dev_qualifier.bMaxPacketSize0 = device_desc.bMaxPacketSize0;
+
+	/* and that all endpoints are dual-speed */
+	hs_ep_in_desc.bEndpointAddress = fs_ep_in_desc.bEndpointAddress;
+	hs_ep_out_desc.bEndpointAddress = fs_ep_out_desc.bEndpointAddress;
+#endif	/* DUALSPEED */
+
+	device_desc.bMaxPacketSize0 = gadget->ep0->maxpacket;
+	usb_gadget_set_selfpowered(gadget);
+
+	if (gadget->is_otg) {
+		otg_desc.bmAttributes |= USB_OTG_HNP,
+		config_desc.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
+		config_desc.bMaxPower = 4;
+	}
+
+	spin_lock_init(&dev->lock);
+	spin_lock_init(&dev->lock_printer_io);
+	INIT_LIST_HEAD(&dev->tx_reqs);
+	INIT_LIST_HEAD(&dev->tx_reqs_active);
+	INIT_LIST_HEAD(&dev->rx_reqs);
+	INIT_LIST_HEAD(&dev->rx_reqs_active);
+	INIT_LIST_HEAD(&dev->rx_buffers);
+	init_waitqueue_head(&dev->rx_wait);
+	init_waitqueue_head(&dev->tx_wait);
+	init_waitqueue_head(&dev->tx_flush_wait);
+
+	dev->config = 0;
+	dev->interface = -1;
+	dev->printer_cdev_open = 0;
+	dev->printer_status = PRINTER_NOT_ERROR;
+	dev->current_rx_req = NULL;
+	dev->current_rx_bytes = 0;
+	dev->current_rx_buf = NULL;
+
+	dev->in_ep = in_ep;
+	dev->out_ep = out_ep;
+
+	/* preallocate control message data and buffer */
+	dev->req = printer_req_alloc(gadget->ep0, USB_DESC_BUFSIZE,
+			GFP_KERNEL);
+	if (!dev->req) {
+		status = -ENOMEM;
+		goto fail;
+	}
+
+	for (i = 0; i < QLEN; i++) {
+		req = printer_req_alloc(dev->in_ep, USB_BUFSIZE, GFP_KERNEL);
+		if (!req) {
+			while (!list_empty(&dev->tx_reqs)) {
+				req = container_of(dev->tx_reqs.next,
+						struct usb_request, list);
+				list_del(&req->list);
+				printer_req_free(dev->in_ep, req);
+			}
+			return -ENOMEM;
+		}
+		list_add(&req->list, &dev->tx_reqs);
+	}
+
+	for (i = 0; i < QLEN; i++) {
+		req = printer_req_alloc(dev->out_ep, USB_BUFSIZE, GFP_KERNEL);
+		if (!req) {
+			while (!list_empty(&dev->rx_reqs)) {
+				req = container_of(dev->rx_reqs.next,
+						struct usb_request, list);
+				list_del(&req->list);
+				printer_req_free(dev->out_ep, req);
+			}
+			return -ENOMEM;
+		}
+		list_add(&req->list, &dev->rx_reqs);
+	}
+
+	dev->req->complete = printer_setup_complete;
+
+	/* finish hookup to lower layer ... */
+	dev->gadget = gadget;
+	set_gadget_data(gadget, dev);
+	gadget->ep0->driver_data = dev;
+
+	INFO(dev, "%s, version: " DRIVER_VERSION "\n", driver_desc);
+	INFO(dev, "using %s, OUT %s IN %s\n", gadget->name, out_ep->name,
+			in_ep->name);
+
+	return 0;
+
+fail:
+	printer_unbind(gadget);
+	return status;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static struct usb_gadget_driver printer_driver = {
+	.speed		= DEVSPEED,
+
+	.function	= (char *) driver_desc,
+	.bind		= printer_bind,
+	.unbind		= printer_unbind,
+
+	.setup		= printer_setup,
+	.disconnect	= printer_disconnect,
+
+	.driver		= {
+		.name		= (char *) shortname,
+		.owner		= THIS_MODULE,
+	},
+};
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_AUTHOR("Craig Nadler");
+MODULE_LICENSE("GPL");
+
+static int __init
+init(void)
+{
+	int status;
+
+	usb_gadget_class = class_create(THIS_MODULE, "usb_printer_gadget");
+	if (IS_ERR(usb_gadget_class)) {
+		status = PTR_ERR(usb_gadget_class);
+		ERROR(dev, "unable to create usb_gadget class %d\n", status);
+		return status;
+	}
+
+	status = alloc_chrdev_region(&g_printer_devno, 0, 1,
+			"USB printer gadget");
+	if (status) {
+		ERROR(dev, "alloc_chrdev_region %d\n", status);
+		class_destroy(usb_gadget_class);
+		return status;
+	}
+
+	status = usb_gadget_register_driver(&printer_driver);
+	if (status) {
+		class_destroy(usb_gadget_class);
+		unregister_chrdev_region(g_printer_devno, 1);
+		DBG(dev, "usb_gadget_register_driver %x\n", status);
+	}
+
+	return status;
+}
+module_init(init);
+
+static void __exit
+cleanup(void)
+{
+	int status;
+
+	spin_lock(&usb_printer_gadget.lock_printer_io);
+	class_destroy(usb_gadget_class);
+	unregister_chrdev_region(g_printer_devno, 2);
+
+	status = usb_gadget_unregister_driver(&printer_driver);
+	if (status)
+		ERROR(dev, "usb_gadget_unregister_driver %x\n", status);
+
+	spin_unlock(&usb_printer_gadget.lock_printer_io);
+}
+module_exit(cleanup);
diff --git a/drivers/usb/gadget/pxa2xx_udc.c b/drivers/usb/gadget/pxa2xx_udc.c
index 3173b39..4402d6f 100644
--- a/drivers/usb/gadget/pxa2xx_udc.c
+++ b/drivers/usb/gadget/pxa2xx_udc.c
@@ -24,7 +24,7 @@
  *
  */
 
-// #define	VERBOSE	DBG_VERBOSE
+/* #define VERBOSE_DEBUG */
 
 #include <linux/device.h>
 #include <linux/module.h>
@@ -38,13 +38,14 @@
 #include <linux/timer.h>
 #include <linux/list.h>
 #include <linux/interrupt.h>
-#include <linux/proc_fs.h>
 #include <linux/mm.h>
 #include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
 #include <linux/irq.h>
 #include <linux/clk.h>
 #include <linux/err.h>
+#include <linux/seq_file.h>
+#include <linux/debugfs.h>
 
 #include <asm/byteorder.h>
 #include <asm/dma.h>
@@ -127,8 +128,10 @@
 {
 	struct pxa2xx_udc_mach_info		*mach = the_controller->mach;
 
-	if (mach->gpio_vbus)
-		return gpio_get_value(mach->gpio_vbus);
+	if (mach->gpio_vbus) {
+		int value = gpio_get_value(mach->gpio_vbus);
+		return mach->gpio_vbus_inverted ? !value : value;
+	}
 	if (mach->udc_is_connected)
 		return mach->udc_is_connected();
 	return 1;
@@ -677,7 +680,7 @@
 
 	/* kickstart this i/o queue? */
 	if (list_empty(&ep->queue) && !ep->stopped) {
-		if (ep->desc == 0 /* ep0 */) {
+		if (ep->desc == NULL/* ep0 */) {
 			unsigned	length = _req->length;
 
 			switch (dev->ep0state) {
@@ -731,7 +734,7 @@
 	}
 
 	/* pio or dma irq handler advances the queue. */
-	if (likely (req != 0))
+	if (likely(req != NULL))
 		list_add_tail(&req->queue, &ep->queue);
 	local_irq_restore(flags);
 
@@ -991,45 +994,32 @@
 
 /*-------------------------------------------------------------------------*/
 
-#ifdef CONFIG_USB_GADGET_DEBUG_FILES
-
-static const char proc_node_name [] = "driver/udc";
+#ifdef CONFIG_USB_GADGET_DEBUG_FS
 
 static int
-udc_proc_read(char *page, char **start, off_t off, int count,
-		int *eof, void *_dev)
+udc_seq_show(struct seq_file *m, void *d)
 {
-	char			*buf = page;
-	struct pxa2xx_udc	*dev = _dev;
-	char			*next = buf;
-	unsigned		size = count;
+	struct pxa2xx_udc	*dev = m->private;
 	unsigned long		flags;
-	int			i, t;
+	int			i;
 	u32			tmp;
 
-	if (off != 0)
-		return 0;
-
 	local_irq_save(flags);
 
 	/* basic device status */
-	t = scnprintf(next, size, DRIVER_DESC "\n"
+	seq_printf(m, DRIVER_DESC "\n"
 		"%s version: %s\nGadget driver: %s\nHost %s\n\n",
 		driver_name, DRIVER_VERSION SIZE_STR "(pio)",
 		dev->driver ? dev->driver->driver.name : "(none)",
 		is_vbus_present() ? "full speed" : "disconnected");
-	size -= t;
-	next += t;
 
 	/* registers for device and ep0 */
-	t = scnprintf(next, size,
+	seq_printf(m,
 		"uicr %02X.%02X, usir %02X.%02x, ufnr %02X.%02X\n",
 		UICR1, UICR0, USIR1, USIR0, UFNRH, UFNRL);
-	size -= t;
-	next += t;
 
 	tmp = UDCCR;
-	t = scnprintf(next, size,
+	seq_printf(m,
 		"udccr %02X =%s%s%s%s%s%s%s%s\n", tmp,
 		(tmp & UDCCR_REM) ? " rem" : "",
 		(tmp & UDCCR_RSTIR) ? " rstir" : "",
@@ -1039,11 +1029,9 @@
 		(tmp & UDCCR_RSM) ? " rsm" : "",
 		(tmp & UDCCR_UDA) ? " uda" : "",
 		(tmp & UDCCR_UDE) ? " ude" : "");
-	size -= t;
-	next += t;
 
 	tmp = UDCCS0;
-	t = scnprintf(next, size,
+	seq_printf(m,
 		"udccs0 %02X =%s%s%s%s%s%s%s%s\n", tmp,
 		(tmp & UDCCS0_SA) ? " sa" : "",
 		(tmp & UDCCS0_RNE) ? " rne" : "",
@@ -1053,28 +1041,22 @@
 		(tmp & UDCCS0_FTF) ? " ftf" : "",
 		(tmp & UDCCS0_IPR) ? " ipr" : "",
 		(tmp & UDCCS0_OPR) ? " opr" : "");
-	size -= t;
-	next += t;
 
 	if (dev->has_cfr) {
 		tmp = UDCCFR;
-		t = scnprintf(next, size,
+		seq_printf(m,
 			"udccfr %02X =%s%s\n", tmp,
 			(tmp & UDCCFR_AREN) ? " aren" : "",
 			(tmp & UDCCFR_ACM) ? " acm" : "");
-		size -= t;
-		next += t;
 	}
 
 	if (!is_vbus_present() || !dev->driver)
 		goto done;
 
-	t = scnprintf(next, size, "ep0 IN %lu/%lu, OUT %lu/%lu\nirqs %lu\n\n",
+	seq_printf(m, "ep0 IN %lu/%lu, OUT %lu/%lu\nirqs %lu\n\n",
 		dev->stats.write.bytes, dev->stats.write.ops,
 		dev->stats.read.bytes, dev->stats.read.ops,
 		dev->stats.irqs);
-	size -= t;
-	next += t;
 
 	/* dump endpoint queues */
 	for (i = 0; i < PXA_UDC_NUM_ENDPOINTS; i++) {
@@ -1082,61 +1064,68 @@
 		struct pxa2xx_request	*req;
 
 		if (i != 0) {
-			const struct usb_endpoint_descriptor	*d;
+			const struct usb_endpoint_descriptor	*desc;
 
-			d = ep->desc;
-			if (!d)
+			desc = ep->desc;
+			if (!desc)
 				continue;
 			tmp = *dev->ep [i].reg_udccs;
-			t = scnprintf(next, size,
+			seq_printf(m,
 				"%s max %d %s udccs %02x irqs %lu\n",
-				ep->ep.name, le16_to_cpu (d->wMaxPacketSize),
+				ep->ep.name, le16_to_cpu(desc->wMaxPacketSize),
 				"pio", tmp, ep->pio_irqs);
 			/* TODO translate all five groups of udccs bits! */
 
 		} else /* ep0 should only have one transfer queued */
-			t = scnprintf(next, size, "ep0 max 16 pio irqs %lu\n",
+			seq_printf(m, "ep0 max 16 pio irqs %lu\n",
 				ep->pio_irqs);
-		if (t <= 0 || t > size)
-			goto done;
-		size -= t;
-		next += t;
 
 		if (list_empty(&ep->queue)) {
-			t = scnprintf(next, size, "\t(nothing queued)\n");
-			if (t <= 0 || t > size)
-				goto done;
-			size -= t;
-			next += t;
+			seq_printf(m, "\t(nothing queued)\n");
 			continue;
 		}
 		list_for_each_entry(req, &ep->queue, queue) {
-			t = scnprintf(next, size,
+			seq_printf(m,
 					"\treq %p len %d/%d buf %p\n",
 					&req->req, req->req.actual,
 					req->req.length, req->req.buf);
-			if (t <= 0 || t > size)
-				goto done;
-			size -= t;
-			next += t;
 		}
 	}
 
 done:
 	local_irq_restore(flags);
-	*eof = 1;
-	return count - size;
+	return 0;
 }
 
-#define create_proc_files() \
-	create_proc_read_entry(proc_node_name, 0, NULL, udc_proc_read, dev)
-#define remove_proc_files() \
-	remove_proc_entry(proc_node_name, NULL)
+static int
+udc_debugfs_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, udc_seq_show, inode->i_private);
+}
+
+static const struct file_operations debug_fops = {
+	.open		= udc_debugfs_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+	.owner		= THIS_MODULE,
+};
+
+#define create_debug_files(dev) \
+	do { \
+		dev->debugfs_udc = debugfs_create_file(dev->gadget.name, \
+			S_IRUGO, NULL, dev, &debug_fops); \
+	} while (0)
+#define remove_debug_files(dev) \
+	do { \
+		if (dev->debugfs_udc) \
+			debugfs_remove(dev->debugfs_udc); \
+	} while (0)
 
 #else	/* !CONFIG_USB_GADGET_DEBUG_FILES */
 
-#define create_proc_files() do {} while (0)
-#define remove_proc_files() do {} while (0)
+#define create_debug_files(dev) do {} while (0)
+#define remove_debug_files(dev) do {} while (0)
 
 #endif	/* CONFIG_USB_GADGET_DEBUG_FILES */
 
@@ -1345,6 +1334,7 @@
 	local_irq_enable();
 
 	driver->unbind(&dev->gadget);
+	dev->gadget.dev.driver = NULL;
 	dev->driver = NULL;
 
 	device_del (&dev->gadget.dev);
@@ -1397,6 +1387,9 @@
 	struct pxa2xx_udc	*dev = _dev;
 	int			vbus = gpio_get_value(dev->mach->gpio_vbus);
 
+	if (dev->mach->gpio_vbus_inverted)
+		vbus = !vbus;
+
 	pxa2xx_udc_vbus_session(&dev->gadget, vbus);
 	return IRQ_HANDLED;
 }
@@ -2099,7 +2092,7 @@
 	/* insist on Intel/ARM/XScale */
 	asm("mrc%? p15, 0, %0, c0, c0" : "=r" (chiprev));
 	if ((chiprev & CP15R0_VENDOR_MASK) != CP15R0_XSCALE_VALUE) {
-		printk(KERN_ERR "%s: not XScale!\n", driver_name);
+		pr_err("%s: not XScale!\n", driver_name);
 		return -ENODEV;
 	}
 
@@ -2128,7 +2121,7 @@
 		break;
 #endif
 	default:
-		printk(KERN_ERR "%s: unrecognized processor: %08x\n",
+		pr_err("%s: unrecognized processor: %08x\n",
 			driver_name, chiprev);
 		/* iop3xx, ixp4xx, ... */
 		return -ENODEV;
@@ -2199,7 +2192,7 @@
 	retval = request_irq(irq, pxa2xx_udc_irq,
 			IRQF_DISABLED, driver_name, dev);
 	if (retval != 0) {
-		printk(KERN_ERR "%s: can't get irq %d, err %d\n",
+		pr_err("%s: can't get irq %d, err %d\n",
 			driver_name, irq, retval);
 		goto err_irq1;
 	}
@@ -2212,7 +2205,7 @@
 				IRQF_DISABLED | IRQF_SAMPLE_RANDOM,
 				driver_name, dev);
 		if (retval != 0) {
-			printk(KERN_ERR "%s: can't get irq %i, err %d\n",
+			pr_err("%s: can't get irq %i, err %d\n",
 				driver_name, LUBBOCK_USB_DISC_IRQ, retval);
 lubbock_fail0:
 			goto err_irq_lub;
@@ -2222,7 +2215,7 @@
 				IRQF_DISABLED | IRQF_SAMPLE_RANDOM,
 				driver_name, dev);
 		if (retval != 0) {
-			printk(KERN_ERR "%s: can't get irq %i, err %d\n",
+			pr_err("%s: can't get irq %i, err %d\n",
 				driver_name, LUBBOCK_USB_IRQ, retval);
 			free_irq(LUBBOCK_USB_DISC_IRQ, dev);
 			goto lubbock_fail0;
@@ -2235,12 +2228,12 @@
 				IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
 				driver_name, dev);
 		if (retval != 0) {
-			printk(KERN_ERR "%s: can't get irq %i, err %d\n",
+			pr_err("%s: can't get irq %i, err %d\n",
 				driver_name, vbus_irq, retval);
 			goto err_vbus_irq;
 		}
 	}
-	create_proc_files();
+	create_debug_files(dev);
 
 	return 0;
 
@@ -2277,7 +2270,7 @@
 		return -EBUSY;
 
 	udc_disable(dev);
-	remove_proc_files();
+	remove_debug_files(dev);
 
 	if (dev->got_irq) {
 		free_irq(platform_get_irq(pdev, 0), dev);
@@ -2361,7 +2354,7 @@
 
 static int __init udc_init(void)
 {
-	printk(KERN_INFO "%s: version %s\n", driver_name, DRIVER_VERSION);
+	pr_info("%s: version %s\n", driver_name, DRIVER_VERSION);
 	return platform_driver_probe(&udc_driver, pxa2xx_udc_probe);
 }
 module_init(udc_init);
diff --git a/drivers/usb/gadget/pxa2xx_udc.h b/drivers/usb/gadget/pxa2xx_udc.h
index 1db46d7..b67e3ff 100644
--- a/drivers/usb/gadget/pxa2xx_udc.h
+++ b/drivers/usb/gadget/pxa2xx_udc.h
@@ -129,6 +129,10 @@
 	struct pxa2xx_udc_mach_info		*mach;
 	u64					dma_mask;
 	struct pxa2xx_ep			ep [PXA_UDC_NUM_ENDPOINTS];
+
+#ifdef CONFIG_USB_GADGET_DEBUG_FS
+	struct dentry				*debugfs_udc;
+#endif
 };
 
 /*-------------------------------------------------------------------------*/
@@ -151,17 +155,19 @@
 #define DBG_NOISY	3	/* ... even more: request level */
 #define DBG_VERY_NOISY	4	/* ... even more: packet level */
 
+#define DMSG(stuff...)	pr_debug("udc: " stuff)
+
 #ifdef DEBUG
 
+static int is_vbus_present(void);
+
 static const char *state_name[] = {
 	"EP0_IDLE",
 	"EP0_IN_DATA_PHASE", "EP0_OUT_DATA_PHASE",
 	"EP0_END_XFER", "EP0_STALL"
 };
 
-#define DMSG(stuff...) printk(KERN_DEBUG "udc: " stuff)
-
-#ifdef VERBOSE
+#ifdef VERBOSE_DEBUG
 #    define UDC_DEBUG DBG_VERBOSE
 #else
 #    define UDC_DEBUG DBG_NORMAL
@@ -207,7 +213,7 @@
 	unsigned	i;
 
 	DMSG("%s %s, uicr %02X.%02X, usir %02X.%02x, ufnr %02X.%02X\n",
-		is_usb_connected() ? "host " : "disconnected",
+		is_vbus_present() ? "host " : "disconnected",
 		state_name[dev->ep0state],
 		UICR1, UICR0, USIR1, USIR0, UFNRH, UFNRL);
 	dump_udccr("udccr");
@@ -224,7 +230,7 @@
 	} else
 		DMSG("ep0 driver '%s'\n", dev->driver->driver.name);
 
-	if (!is_usb_connected())
+	if (!is_vbus_present())
 		return;
 
 	dump_udccs0 ("udccs0");
@@ -233,7 +239,7 @@
 		dev->stats.read.bytes, dev->stats.read.ops);
 
 	for (i = 1; i < PXA_UDC_NUM_ENDPOINTS; i++) {
-		if (dev->ep [i].desc == 0)
+		if (dev->ep [i].desc == NULL)
 			continue;
 		DMSG ("udccs%d = %02x\n", i, *dev->ep->reg_udccs);
 	}
@@ -241,8 +247,6 @@
 
 #else
 
-#define DMSG(stuff...)		do{}while(0)
-
 #define	dump_udccr(x)	do{}while(0)
 #define	dump_udccs0(x)	do{}while(0)
 #define	dump_state(x)	do{}while(0)
@@ -253,8 +257,9 @@
 
 #define DBG(lvl, stuff...) do{if ((lvl) <= UDC_DEBUG) DMSG(stuff);}while(0)
 
-#define WARN(stuff...) printk(KERN_WARNING "udc: " stuff)
-#define INFO(stuff...) printk(KERN_INFO "udc: " stuff)
+#define ERR(stuff...)		pr_err("udc: " stuff)
+#define WARN(stuff...)		pr_warning("udc: " stuff)
+#define INFO(stuff...)		pr_info("udc: " stuff)
 
 
 #endif /* __LINUX_USB_GADGET_PXA2XX_H */
diff --git a/drivers/usb/gadget/rndis.c b/drivers/usb/gadget/rndis.c
index db1b2bf..3d03664 100644
--- a/drivers/usb/gadget/rndis.c
+++ b/drivers/usb/gadget/rndis.c
@@ -53,21 +53,18 @@
  */
 
 #if 0
-#define DBG(str,args...) do { \
-	if (rndis_debug) \
-		printk(KERN_DEBUG str , ## args ); \
-	} while (0)
 static int rndis_debug = 0;
-
 module_param (rndis_debug, int, 0);
 MODULE_PARM_DESC (rndis_debug, "enable debugging");
-
 #else
-
 #define rndis_debug		0
-#define DBG(str,args...)	do{}while(0)
 #endif
 
+#define DBG(str,args...) do { \
+	if (rndis_debug) \
+		pr_debug(str , ## args); \
+	} while (0)
+
 #define RNDIS_MAX_CONFIGS	1
 
 
@@ -679,7 +676,7 @@
 #endif
 
 	default:
-		printk (KERN_WARNING "%s: query unknown OID 0x%08X\n",
+		pr_warning("%s: query unknown OID 0x%08X\n",
 			 __FUNCTION__, OID);
 	}
 	if (retval < 0)
@@ -804,7 +801,7 @@
 #endif	/* RNDIS_PM */
 
 	default:
-		printk (KERN_WARNING "%s: set unknown OID 0x%08X, size %d\n",
+		pr_warning("%s: set unknown OID 0x%08X, size %d\n",
 			 __FUNCTION__, OID, buf_len);
 	}
 
@@ -1126,8 +1123,7 @@
 		 * In one case those messages seemed to relate to the host
 		 * suspending itself.
 		 */
-		printk (KERN_WARNING
-			"%s: unknown RNDIS message 0x%08X len %d\n",
+		pr_warning("%s: unknown RNDIS message 0x%08X len %d\n",
 			__FUNCTION__ , MsgType, MsgLength);
 		{
 			unsigned i;
diff --git a/drivers/usb/gadget/s3c2410_udc.c b/drivers/usb/gadget/s3c2410_udc.c
index 4ce050c..aadc420 100644
--- a/drivers/usb/gadget/s3c2410_udc.c
+++ b/drivers/usb/gadget/s3c2410_udc.c
@@ -893,7 +893,7 @@
 /*
  *	s3c2410_udc_irq - interrupt handler
  */
-static irqreturn_t s3c2410_udc_irq(int irq, void *_dev)
+static irqreturn_t s3c2410_udc_irq(int dummy, void *_dev)
 {
 	struct s3c2410_udc *dev = _dev;
 	int usb_status;
@@ -1016,7 +1016,7 @@
 		}
 	}
 
-	dprintk(DEBUG_VERBOSE, "irq: %d s3c2410_udc_done.\n", irq);
+	dprintk(DEBUG_VERBOSE, "irq: %d s3c2410_udc_done.\n", IRQ_USBD);
 
 	/* Restore old index */
 	udc_write(idx, S3C2410_UDC_INDEX_REG);
diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c
index f5738eb..f5c3896 100644
--- a/drivers/usb/gadget/serial.c
+++ b/drivers/usb/gadget/serial.c
@@ -89,9 +89,9 @@
 #endif
 
 #define gs_debug(format, arg...) \
-	do { if (debug) printk(KERN_DEBUG format, ## arg); } while(0)
+	do { if (debug) pr_debug(format, ## arg); } while (0)
 #define gs_debug_level(level, format, arg...) \
-	do { if (debug>=level) printk(KERN_DEBUG format, ## arg); } while(0)
+	do { if (debug >= level) pr_debug(format, ## arg); } while (0)
 
 
 /* Thanks to NetChip Technologies for donating this product ID.
@@ -553,7 +553,8 @@
 
 	retval = usb_gadget_register_driver(&gs_gadget_driver);
 	if (retval) {
-		printk(KERN_ERR "gs_module_init: cannot register gadget driver, ret=%d\n", retval);
+		pr_err("gs_module_init: cannot register gadget driver, "
+			"ret=%d\n", retval);
 		return retval;
 	}
 
@@ -579,11 +580,13 @@
 	if (retval) {
 		usb_gadget_unregister_driver(&gs_gadget_driver);
 		put_tty_driver(gs_tty_driver);
-		printk(KERN_ERR "gs_module_init: cannot register tty driver, ret=%d\n", retval);
+		pr_err("gs_module_init: cannot register tty driver, "
+				"ret=%d\n", retval);
 		return retval;
 	}
 
-	printk(KERN_INFO "gs_module_init: %s %s loaded\n", GS_LONG_NAME, GS_VERSION_STR);
+	pr_info("gs_module_init: %s %s loaded\n",
+			GS_LONG_NAME, GS_VERSION_STR);
 	return 0;
 }
 
@@ -598,7 +601,8 @@
 	put_tty_driver(gs_tty_driver);
 	usb_gadget_unregister_driver(&gs_gadget_driver);
 
-	printk(KERN_INFO "gs_module_exit: %s %s unloaded\n", GS_LONG_NAME, GS_VERSION_STR);
+	pr_info("gs_module_exit: %s %s unloaded\n",
+			GS_LONG_NAME, GS_VERSION_STR);
 }
 
 /* TTY Driver */
@@ -621,7 +625,7 @@
 	gs_debug("gs_open: (%d,%p,%p)\n", port_num, tty, file);
 
 	if (port_num < 0 || port_num >= GS_NUM_PORTS) {
-		printk(KERN_ERR "gs_open: (%d,%p,%p) invalid port number\n",
+		pr_err("gs_open: (%d,%p,%p) invalid port number\n",
 			port_num, tty, file);
 		return -ENODEV;
 	}
@@ -629,15 +633,14 @@
 	dev = gs_device;
 
 	if (dev == NULL) {
-		printk(KERN_ERR "gs_open: (%d,%p,%p) NULL device pointer\n",
+		pr_err("gs_open: (%d,%p,%p) NULL device pointer\n",
 			port_num, tty, file);
 		return -ENODEV;
 	}
 
 	mtx = &gs_open_close_lock[port_num];
 	if (mutex_lock_interruptible(mtx)) {
-		printk(KERN_ERR
-		"gs_open: (%d,%p,%p) interrupted waiting for mutex\n",
+		pr_err("gs_open: (%d,%p,%p) interrupted waiting for mutex\n",
 			port_num, tty, file);
 		return -ERESTARTSYS;
 	}
@@ -645,8 +648,7 @@
 	spin_lock_irqsave(&dev->dev_lock, flags);
 
 	if (dev->dev_config == GS_NO_CONFIG_ID) {
-		printk(KERN_ERR
-			"gs_open: (%d,%p,%p) device is not connected\n",
+		pr_err("gs_open: (%d,%p,%p) device is not connected\n",
 			port_num, tty, file);
 		ret = -ENODEV;
 		goto exit_unlock_dev;
@@ -655,7 +657,7 @@
 	port = dev->dev_port[port_num];
 
 	if (port == NULL) {
-		printk(KERN_ERR "gs_open: (%d,%p,%p) NULL port pointer\n",
+		pr_err("gs_open: (%d,%p,%p) NULL port pointer\n",
 			port_num, tty, file);
 		ret = -ENODEV;
 		goto exit_unlock_dev;
@@ -665,7 +667,7 @@
 	spin_unlock(&dev->dev_lock);
 
 	if (port->port_dev == NULL) {
-		printk(KERN_ERR "gs_open: (%d,%p,%p) port disconnected (1)\n",
+		pr_err("gs_open: (%d,%p,%p) port disconnected (1)\n",
 			port_num, tty, file);
 		ret = -EIO;
 		goto exit_unlock_port;
@@ -692,8 +694,7 @@
 
 		/* might have been disconnected while asleep, check */
 		if (port->port_dev == NULL) {
-			printk(KERN_ERR
-				"gs_open: (%d,%p,%p) port disconnected (2)\n",
+			pr_err("gs_open: (%d,%p,%p) port disconnected (2)\n",
 				port_num, tty, file);
 			port->port_in_use = 0;
 			ret = -EIO;
@@ -701,7 +702,8 @@
 		}
 
 		if ((port->port_write_buf=buf) == NULL) {
-			printk(KERN_ERR "gs_open: (%d,%p,%p) cannot allocate port write buffer\n",
+			pr_err("gs_open: (%d,%p,%p) cannot allocate "
+				"port write buffer\n",
 				port_num, tty, file);
 			port->port_in_use = 0;
 			ret = -ENOMEM;
@@ -714,7 +716,7 @@
 
 	/* might have been disconnected while asleep, check */
 	if (port->port_dev == NULL) {
-		printk(KERN_ERR "gs_open: (%d,%p,%p) port disconnected (3)\n",
+		pr_err("gs_open: (%d,%p,%p) port disconnected (3)\n",
 			port_num, tty, file);
 		port->port_in_use = 0;
 		ret = -EIO;
@@ -762,7 +764,7 @@
 	struct mutex *mtx;
 
 	if (port == NULL) {
-		printk(KERN_ERR "gs_close: NULL port pointer\n");
+		pr_err("gs_close: NULL port pointer\n");
 		return;
 	}
 
@@ -774,8 +776,7 @@
 	spin_lock_irq(&port->port_lock);
 
 	if (port->port_open_count == 0) {
-		printk(KERN_ERR
-			"gs_close: (%d,%p,%p) port is already closed\n",
+		pr_err("gs_close: (%d,%p,%p) port is already closed\n",
 			port->port_num, tty, file);
 		goto exit;
 	}
@@ -837,7 +838,7 @@
 	int ret;
 
 	if (port == NULL) {
-		printk(KERN_ERR "gs_write: NULL port pointer\n");
+		pr_err("gs_write: NULL port pointer\n");
 		return -EIO;
 	}
 
@@ -850,14 +851,14 @@
 	spin_lock_irqsave(&port->port_lock, flags);
 
 	if (port->port_dev == NULL) {
-		printk(KERN_ERR "gs_write: (%d,%p) port is not connected\n",
+		pr_err("gs_write: (%d,%p) port is not connected\n",
 			port->port_num, tty);
 		ret = -EIO;
 		goto exit;
 	}
 
 	if (port->port_open_count == 0) {
-		printk(KERN_ERR "gs_write: (%d,%p) port is closed\n",
+		pr_err("gs_write: (%d,%p) port is closed\n",
 			port->port_num, tty);
 		ret = -EBADF;
 		goto exit;
@@ -888,7 +889,7 @@
 	struct gs_port *port = tty->driver_data;
 
 	if (port == NULL) {
-		printk(KERN_ERR "gs_put_char: NULL port pointer\n");
+		pr_err("gs_put_char: NULL port pointer\n");
 		return;
 	}
 
@@ -898,13 +899,13 @@
 	spin_lock_irqsave(&port->port_lock, flags);
 
 	if (port->port_dev == NULL) {
-		printk(KERN_ERR "gs_put_char: (%d,%p) port is not connected\n",
+		pr_err("gs_put_char: (%d,%p) port is not connected\n",
 			port->port_num, tty);
 		goto exit;
 	}
 
 	if (port->port_open_count == 0) {
-		printk(KERN_ERR "gs_put_char: (%d,%p) port is closed\n",
+		pr_err("gs_put_char: (%d,%p) port is closed\n",
 			port->port_num, tty);
 		goto exit;
 	}
@@ -924,7 +925,7 @@
 	struct gs_port *port = tty->driver_data;
 
 	if (port == NULL) {
-		printk(KERN_ERR "gs_flush_chars: NULL port pointer\n");
+		pr_err("gs_flush_chars: NULL port pointer\n");
 		return;
 	}
 
@@ -933,14 +934,13 @@
 	spin_lock_irqsave(&port->port_lock, flags);
 
 	if (port->port_dev == NULL) {
-		printk(KERN_ERR
-			"gs_flush_chars: (%d,%p) port is not connected\n",
+		pr_err("gs_flush_chars: (%d,%p) port is not connected\n",
 			port->port_num, tty);
 		goto exit;
 	}
 
 	if (port->port_open_count == 0) {
-		printk(KERN_ERR "gs_flush_chars: (%d,%p) port is closed\n",
+		pr_err("gs_flush_chars: (%d,%p) port is closed\n",
 			port->port_num, tty);
 		goto exit;
 	}
@@ -1038,7 +1038,7 @@
 	struct gs_port *port = tty->driver_data;
 
 	if (port == NULL) {
-		printk(KERN_ERR "gs_ioctl: NULL port pointer\n");
+		pr_err("gs_ioctl: NULL port pointer\n");
 		return -EIO;
 	}
 
@@ -1076,7 +1076,7 @@
 	struct gs_req_entry *req_entry;
 
 	if (dev == NULL) {
-		printk(KERN_ERR "gs_send: NULL device pointer\n");
+		pr_err("gs_send: NULL device pointer\n");
 		return -ENODEV;
 	}
 
@@ -1103,7 +1103,7 @@
 			req->length = len;
 			spin_unlock_irqrestore(&dev->dev_lock, flags);
 			if ((ret=usb_ep_queue(ep, req, GFP_ATOMIC))) {
-				printk(KERN_ERR
+				pr_err(
 				"gs_send: cannot queue read request, ret=%d\n",
 					ret);
 				spin_lock_irqsave(&dev->dev_lock, flags);
@@ -1144,9 +1144,7 @@
 	port = dev->dev_port[0];
 
 	if (port == NULL) {
-		printk(KERN_ERR
-			"gs_send_packet: port=%d, NULL port pointer\n",
-			0);
+		pr_err("gs_send_packet: port=%d, NULL port pointer\n", 0);
 		return -EIO;
 	}
 
@@ -1193,7 +1191,7 @@
 	port = dev->dev_port[0];
 
 	if (port == NULL) {
-		printk(KERN_ERR "gs_recv_packet: port=%d, NULL port pointer\n",
+		pr_err("gs_recv_packet: port=%d, NULL port pointer\n",
 			port->port_num);
 		return -EIO;
 	}
@@ -1201,7 +1199,7 @@
 	spin_lock(&port->port_lock);
 
 	if (port->port_open_count == 0) {
-		printk(KERN_ERR "gs_recv_packet: port=%d, port is closed\n",
+		pr_err("gs_recv_packet: port=%d, port is closed\n",
 			port->port_num);
 		ret = -EIO;
 		goto exit;
@@ -1211,14 +1209,14 @@
 	tty = port->port_tty;
 
 	if (tty == NULL) {
-		printk(KERN_ERR "gs_recv_packet: port=%d, NULL tty pointer\n",
+		pr_err("gs_recv_packet: port=%d, NULL tty pointer\n",
 			port->port_num);
 		ret = -EIO;
 		goto exit;
 	}
 
 	if (port->port_tty->magic != TTY_MAGIC) {
-		printk(KERN_ERR "gs_recv_packet: port=%d, bad tty magic\n",
+		pr_err("gs_recv_packet: port=%d, bad tty magic\n",
 			port->port_num);
 		ret = -EIO;
 		goto exit;
@@ -1245,7 +1243,7 @@
 	struct gs_dev *dev = ep->driver_data;
 
 	if (dev == NULL) {
-		printk(KERN_ERR "gs_read_complete: NULL device pointer\n");
+		pr_err("gs_read_complete: NULL device pointer\n");
 		return;
 	}
 
@@ -1256,7 +1254,7 @@
 requeue:
 		req->length = ep->maxpacket;
 		if ((ret=usb_ep_queue(ep, req, GFP_ATOMIC))) {
-			printk(KERN_ERR
+			pr_err(
 			"gs_read_complete: cannot queue read request, ret=%d\n",
 				ret);
 		}
@@ -1270,7 +1268,7 @@
 
 	default:
 		/* unexpected */
-		printk(KERN_ERR
+		pr_err(
 		"gs_read_complete: unexpected status error, status=%d\n",
 			req->status);
 		goto requeue;
@@ -1287,7 +1285,7 @@
 	struct gs_req_entry *gs_req = req->context;
 
 	if (dev == NULL) {
-		printk(KERN_ERR "gs_write_complete: NULL device pointer\n");
+		pr_err("gs_write_complete: NULL device pointer\n");
 		return;
 	}
 
@@ -1296,8 +1294,7 @@
 		/* normal completion */
 requeue:
 		if (gs_req == NULL) {
-			printk(KERN_ERR
-				"gs_write_complete: NULL request pointer\n");
+			pr_err("gs_write_complete: NULL request pointer\n");
 			return;
 		}
 
@@ -1316,7 +1313,7 @@
 		break;
 
 	default:
-		printk(KERN_ERR
+		pr_err(
 		"gs_write_complete: unexpected status error, status=%d\n",
 			req->status);
 		goto requeue;
@@ -1351,7 +1348,7 @@
 		gs_device_desc.bcdDevice =
 				cpu_to_le16(GS_VERSION_NUM | gcnum);
 	else {
-		printk(KERN_WARNING "gs_bind: controller '%s' not recognized\n",
+		pr_warning("gs_bind: controller '%s' not recognized\n",
 			gadget->name);
 		/* unrecognized, but safe unless bulk is REALLY quirky */
 		gs_device_desc.bcdDevice =
@@ -1375,7 +1372,7 @@
 	if (use_acm) {
 		ep = usb_ep_autoconfig(gadget, &gs_fullspeed_notify_desc);
 		if (!ep) {
-			printk(KERN_ERR "gs_bind: cannot run ACM on %s\n", gadget->name);
+			pr_err("gs_bind: cannot run ACM on %s\n", gadget->name);
 			goto autoconf_fail;
 		}
 		gs_device_desc.idProduct = __constant_cpu_to_le16(
@@ -1425,7 +1422,7 @@
 	set_gadget_data(gadget, dev);
 
 	if ((ret=gs_alloc_ports(dev, GFP_KERNEL)) != 0) {
-		printk(KERN_ERR "gs_bind: cannot allocate ports\n");
+		pr_err("gs_bind: cannot allocate ports\n");
 		gs_unbind(gadget);
 		return ret;
 	}
@@ -1441,13 +1438,13 @@
 
 	gadget->ep0->driver_data = dev;
 
-	printk(KERN_INFO "gs_bind: %s %s bound\n",
+	pr_info("gs_bind: %s %s bound\n",
 		GS_LONG_NAME, GS_VERSION_STR);
 
 	return 0;
 
 autoconf_fail:
-	printk(KERN_ERR "gs_bind: cannot autoconfigure on %s\n", gadget->name);
+	pr_err("gs_bind: cannot autoconfigure on %s\n", gadget->name);
 	return -ENODEV;
 }
 
@@ -1480,7 +1477,7 @@
 		set_gadget_data(gadget, NULL);
 	}
 
-	printk(KERN_INFO "gs_unbind: %s %s unbound\n", GS_LONG_NAME,
+	pr_info("gs_unbind: %s %s unbound\n", GS_LONG_NAME,
 		GS_VERSION_STR);
 }
 
@@ -1513,7 +1510,8 @@
 		break;
 
 	default:
-		printk(KERN_ERR "gs_setup: unknown request, type=%02x, request=%02x, value=%04x, index=%04x, length=%d\n",
+		pr_err("gs_setup: unknown request, type=%02x, request=%02x, "
+			"value=%04x, index=%04x, length=%d\n",
 			ctrl->bRequestType, ctrl->bRequest,
 			wValue, wIndex, wLength);
 		break;
@@ -1526,7 +1524,7 @@
 				&& (ret % gadget->ep0->maxpacket) == 0;
 		ret = usb_ep_queue(gadget->ep0, req, GFP_ATOMIC);
 		if (ret < 0) {
-			printk(KERN_ERR "gs_setup: cannot queue response, ret=%d\n",
+			pr_err("gs_setup: cannot queue response, ret=%d\n",
 				ret);
 			req->status = 0;
 			gs_setup_complete(gadget->ep0, req);
@@ -1656,7 +1654,8 @@
 		break;
 
 	default:
-		printk(KERN_ERR "gs_setup: unknown standard request, type=%02x, request=%02x, value=%04x, index=%04x, length=%d\n",
+		pr_err("gs_setup: unknown standard request, type=%02x, "
+			"request=%02x, value=%04x, index=%04x, length=%d\n",
 			ctrl->bRequestType, ctrl->bRequest,
 			wValue, wIndex, wLength);
 		break;
@@ -1682,7 +1681,7 @@
 		 * handler copy that data to port->port_line_coding (iff
 		 * it's valid) and maybe pass it on.  Until then, fail.
 		 */
-		printk(KERN_WARNING "gs_setup: set_line_coding "
+		pr_warning("gs_setup: set_line_coding "
 				"unuspported\n");
 		break;
 
@@ -1702,12 +1701,12 @@
 		 * handler use that to set the state (iff it's valid) and
 		 * maybe pass it on.  Until then, fail.
 		 */
-		printk(KERN_WARNING "gs_setup: set_control_line_state "
+		pr_warning("gs_setup: set_control_line_state "
 				"unuspported\n");
 		break;
 
 	default:
-		printk(KERN_ERR "gs_setup: unknown class request, "
+		pr_err("gs_setup: unknown class request, "
 				"type=%02x, request=%02x, value=%04x, "
 				"index=%04x, length=%d\n",
 			ctrl->bRequestType, ctrl->bRequest,
@@ -1724,7 +1723,8 @@
 static void gs_setup_complete(struct usb_ep *ep, struct usb_request *req)
 {
 	if (req->status || req->actual != req->length) {
-		printk(KERN_ERR "gs_setup_complete: status error, status=%d, actual=%d, length=%d\n",
+		pr_err("gs_setup_complete: status error, status=%d, "
+			"actual=%d, length=%d\n",
 			req->status, req->actual, req->length);
 	}
 }
@@ -1751,11 +1751,11 @@
 
 	/* re-allocate ports for the next connection */
 	if (gs_alloc_ports(dev, GFP_ATOMIC) != 0)
-		printk(KERN_ERR "gs_disconnect: cannot re-allocate ports\n");
+		pr_err("gs_disconnect: cannot re-allocate ports\n");
 
 	spin_unlock_irqrestore(&dev->dev_lock, flags);
 
-	printk(KERN_INFO "gs_disconnect: %s disconnected\n", GS_LONG_NAME);
+	pr_info("gs_disconnect: %s disconnected\n", GS_LONG_NAME);
 }
 
 /*
@@ -1778,7 +1778,7 @@
 	struct gs_req_entry *req_entry;
 
 	if (dev == NULL) {
-		printk(KERN_ERR "gs_set_config: NULL device pointer\n");
+		pr_err("gs_set_config: NULL device pointer\n");
 		return 0;
 	}
 
@@ -1823,7 +1823,8 @@
 				dev->dev_notify_ep = ep;
 				dev->dev_notify_ep_desc = ep_desc;
 			} else {
-				printk(KERN_ERR "gs_set_config: cannot enable notify endpoint %s, ret=%d\n",
+				pr_err("gs_set_config: cannot enable NOTIFY "
+					"endpoint %s, ret=%d\n",
 					ep->name, ret);
 				goto exit_reset_config;
 			}
@@ -1839,7 +1840,8 @@
 				dev->dev_in_ep = ep;
 				dev->dev_in_ep_desc = ep_desc;
 			} else {
-				printk(KERN_ERR "gs_set_config: cannot enable in endpoint %s, ret=%d\n",
+				pr_err("gs_set_config: cannot enable IN "
+					"endpoint %s, ret=%d\n",
 					ep->name, ret);
 				goto exit_reset_config;
 			}
@@ -1855,7 +1857,8 @@
 				dev->dev_out_ep = ep;
 				dev->dev_out_ep_desc = ep_desc;
 			} else {
-				printk(KERN_ERR "gs_set_config: cannot enable out endpoint %s, ret=%d\n",
+				pr_err("gs_set_config: cannot enable OUT "
+					"endpoint %s, ret=%d\n",
 					ep->name, ret);
 				goto exit_reset_config;
 			}
@@ -1865,7 +1868,7 @@
 
 	if (dev->dev_in_ep == NULL || dev->dev_out_ep == NULL
 	|| (config != GS_BULK_CONFIG_ID && dev->dev_notify_ep == NULL)) {
-		printk(KERN_ERR "gs_set_config: cannot find endpoints\n");
+		pr_err("gs_set_config: cannot find endpoints\n");
 		ret = -ENODEV;
 		goto exit_reset_config;
 	}
@@ -1876,11 +1879,12 @@
 		if ((req=gs_alloc_req(ep, ep->maxpacket, GFP_ATOMIC))) {
 			req->complete = gs_read_complete;
 			if ((ret=usb_ep_queue(ep, req, GFP_ATOMIC))) {
-				printk(KERN_ERR "gs_set_config: cannot queue read request, ret=%d\n",
-					ret);
+				pr_err("gs_set_config: cannot queue read "
+					"request, ret=%d\n", ret);
 			}
 		} else {
-			printk(KERN_ERR "gs_set_config: cannot allocate read requests\n");
+			pr_err("gs_set_config: cannot allocate "
+					"read requests\n");
 			ret = -ENOMEM;
 			goto exit_reset_config;
 		}
@@ -1893,13 +1897,14 @@
 			req_entry->re_req->complete = gs_write_complete;
 			list_add(&req_entry->re_entry, &dev->dev_req_list);
 		} else {
-			printk(KERN_ERR "gs_set_config: cannot allocate write requests\n");
+			pr_err("gs_set_config: cannot allocate "
+					"write requests\n");
 			ret = -ENOMEM;
 			goto exit_reset_config;
 		}
 	}
 
-	printk(KERN_INFO "gs_set_config: %s configured, %s speed %s config\n",
+	pr_info("gs_set_config: %s configured, %s speed %s config\n",
 		GS_LONG_NAME,
 		gadget->speed == USB_SPEED_HIGH ? "high" : "full",
 		config == GS_BULK_CONFIG_ID ? "BULK" : "CDC-ACM");
@@ -1926,7 +1931,7 @@
 	struct gs_req_entry *req_entry;
 
 	if (dev == NULL) {
-		printk(KERN_ERR "gs_reset_config: NULL device pointer\n");
+		pr_err("gs_reset_config: NULL device pointer\n");
 		return;
 	}
 
diff --git a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/zero.c
index fcde5d9..d3d4f40 100644
--- a/drivers/usb/gadget/zero.c
+++ b/drivers/usb/gadget/zero.c
@@ -1115,7 +1115,7 @@
 	ep = usb_ep_autoconfig (gadget, &fs_source_desc);
 	if (!ep) {
 autoconf_fail:
-		printk (KERN_ERR "%s: can't autoconfigure on %s\n",
+		pr_err("%s: can't autoconfigure on %s\n",
 			shortname, gadget->name);
 		return -ENODEV;
 	}
@@ -1139,7 +1139,7 @@
 		 * things like configuration and altsetting numbering
 		 * can need hardware-specific attention though.
 		 */
-		printk (KERN_WARNING "%s: controller '%s' not recognized\n",
+		pr_warning("%s: controller '%s' not recognized\n",
 			shortname, gadget->name);
 		device_desc.bcdDevice = __constant_cpu_to_le16 (0x9999);
 	}
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index 49a91c5e..d97b16b 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -29,15 +29,6 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called ehci-hcd.
 
-config USB_EHCI_SPLIT_ISO
-	bool "Full speed ISO transactions (EXPERIMENTAL)"
-	depends on USB_EHCI_HCD && EXPERIMENTAL
-	default n
-	---help---
-	  This code is new and hasn't been used with many different
-	  EHCI or USB 2.0 transaction translator implementations.
-	  It should work for ISO-OUT transfers, like audio.
-
 config USB_EHCI_ROOT_HUB_TT
 	bool "Root Hub Transaction Translators (EXPERIMENTAL)"
 	depends on USB_EHCI_HCD && EXPERIMENTAL
@@ -69,21 +60,30 @@
 
 config USB_EHCI_BIG_ENDIAN_MMIO
 	bool
-	depends on USB_EHCI_HCD && (PPC_CELLEB || PPC_PS3 || 440EPX)
+	depends on USB_EHCI_HCD && (PPC_CELLEB || PPC_PS3 || 440EPX || ARCH_IXP4XX)
 	default y
 
 config USB_EHCI_BIG_ENDIAN_DESC
 	bool
-	depends on USB_EHCI_HCD && 440EPX
+	depends on USB_EHCI_HCD && (440EPX || ARCH_IXP4XX)
 	default y
 
 config USB_EHCI_FSL
 	bool
+	depends on USB_EHCI_HCD
 	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_EHCI_HCD_PPC_OF
+	bool "EHCI support for PPC USB controller on OF platform bus"
+	depends on USB_EHCI_HCD && PPC_OF
+	default y
+	---help---
+	  Enables support for the USB controller present on the PowerPC
+	  OpenFirmware platform bus.
+
 config USB_ISP116X_HCD
 	tristate "ISP116X HCD support"
 	depends on USB
diff --git a/drivers/usb/host/ehci-au1xxx.c b/drivers/usb/host/ehci-au1xxx.c
index 766ef68..da7532d 100644
--- a/drivers/usb/host/ehci-au1xxx.c
+++ b/drivers/usb/host/ehci-au1xxx.c
@@ -222,6 +222,7 @@
 	.hub_control = ehci_hub_control,
 	.bus_suspend = ehci_bus_suspend,
 	.bus_resume = ehci_bus_resume,
+	.relinquish_port = ehci_relinquish_port,
 };
 
 /*-------------------------------------------------------------------------*/
diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c
index c9cc441..64ebfc5 100644
--- a/drivers/usb/host/ehci-dbg.c
+++ b/drivers/usb/host/ehci-dbg.c
@@ -323,7 +323,43 @@
 
 #else
 
-/* troubleshooting help: expose state in sysfs */
+/* troubleshooting help: expose state in debugfs */
+
+static int debug_async_open(struct inode *, struct file *);
+static int debug_periodic_open(struct inode *, struct file *);
+static int debug_registers_open(struct inode *, struct file *);
+static int debug_async_open(struct inode *, struct file *);
+static ssize_t debug_output(struct file*, char __user*, size_t, loff_t*);
+static int debug_close(struct inode *, struct file *);
+
+static const struct file_operations debug_async_fops = {
+	.owner		= THIS_MODULE,
+	.open		= debug_async_open,
+	.read		= debug_output,
+	.release	= debug_close,
+};
+static const struct file_operations debug_periodic_fops = {
+	.owner		= THIS_MODULE,
+	.open		= debug_periodic_open,
+	.read		= debug_output,
+	.release	= debug_close,
+};
+static const struct file_operations debug_registers_fops = {
+	.owner		= THIS_MODULE,
+	.open		= debug_registers_open,
+	.read		= debug_output,
+	.release	= debug_close,
+};
+
+static struct dentry *ehci_debug_root;
+
+struct debug_buffer {
+	ssize_t (*fill_func)(struct debug_buffer *);	/* fill method */
+	struct usb_bus *bus;
+	struct mutex mutex;	/* protect filling of buffer */
+	size_t count;		/* number of characters filled into buffer */
+	char *page;
+};
 
 #define speed_char(info1) ({ char tmp; \
 		switch (info1 & (3 << 12)) { \
@@ -441,10 +477,8 @@
 	*nextp = next;
 }
 
-static ssize_t
-show_async (struct class_device *class_dev, char *buf)
+static ssize_t fill_async_buffer(struct debug_buffer *buf)
 {
-	struct usb_bus		*bus;
 	struct usb_hcd		*hcd;
 	struct ehci_hcd		*ehci;
 	unsigned long		flags;
@@ -452,14 +486,13 @@
 	char			*next;
 	struct ehci_qh		*qh;
 
-	*buf = 0;
-
-	bus = class_get_devdata(class_dev);
-	hcd = bus_to_hcd(bus);
+	hcd = bus_to_hcd(buf->bus);
 	ehci = hcd_to_ehci (hcd);
-	next = buf;
+	next = buf->page;
 	size = PAGE_SIZE;
 
+	*next = 0;
+
 	/* dumps a snapshot of the async schedule.
 	 * usually empty except for long-term bulk reads, or head.
 	 * one QH per line, and TDs we know about
@@ -477,16 +510,12 @@
 	}
 	spin_unlock_irqrestore (&ehci->lock, flags);
 
-	return strlen (buf);
+	return strlen(buf->page);
 }
-static CLASS_DEVICE_ATTR (async, S_IRUGO, show_async, NULL);
 
 #define DBG_SCHED_LIMIT 64
-
-static ssize_t
-show_periodic (struct class_device *class_dev, char *buf)
+static ssize_t fill_periodic_buffer(struct debug_buffer *buf)
 {
-	struct usb_bus		*bus;
 	struct usb_hcd		*hcd;
 	struct ehci_hcd		*ehci;
 	unsigned long		flags;
@@ -500,10 +529,9 @@
 		return 0;
 	seen_count = 0;
 
-	bus = class_get_devdata(class_dev);
-	hcd = bus_to_hcd(bus);
+	hcd = bus_to_hcd(buf->bus);
 	ehci = hcd_to_ehci (hcd);
-	next = buf;
+	next = buf->page;
 	size = PAGE_SIZE;
 
 	temp = scnprintf (next, size, "size = %d\n", ehci->periodic_size);
@@ -623,14 +651,10 @@
 
 	return PAGE_SIZE - size;
 }
-static CLASS_DEVICE_ATTR (periodic, S_IRUGO, show_periodic, NULL);
-
 #undef DBG_SCHED_LIMIT
 
-static ssize_t
-show_registers (struct class_device *class_dev, char *buf)
+static ssize_t fill_registers_buffer(struct debug_buffer *buf)
 {
-	struct usb_bus		*bus;
 	struct usb_hcd		*hcd;
 	struct ehci_hcd		*ehci;
 	unsigned long		flags;
@@ -639,15 +663,14 @@
 	static char		fmt [] = "%*s\n";
 	static char		label [] = "";
 
-	bus = class_get_devdata(class_dev);
-	hcd = bus_to_hcd(bus);
+	hcd = bus_to_hcd(buf->bus);
 	ehci = hcd_to_ehci (hcd);
-	next = buf;
+	next = buf->page;
 	size = PAGE_SIZE;
 
 	spin_lock_irqsave (&ehci->lock, flags);
 
-	if (bus->controller->power.power_state.event) {
+	if (buf->bus->controller->power.power_state.event) {
 		size = scnprintf (next, size,
 			"bus %s, device %s (driver " DRIVER_VERSION ")\n"
 			"%s\n"
@@ -763,9 +786,7 @@
 	}
 
 	if (ehci->reclaim) {
-		temp = scnprintf (next, size, "reclaim qh %p%s\n",
-				ehci->reclaim,
-				ehci->reclaim_ready ? " ready" : "");
+		temp = scnprintf(next, size, "reclaim qh %p\n", ehci->reclaim);
 		size -= temp;
 		next += temp;
 	}
@@ -789,26 +810,150 @@
 
 	return PAGE_SIZE - size;
 }
-static CLASS_DEVICE_ATTR (registers, S_IRUGO, show_registers, NULL);
+
+static struct debug_buffer *alloc_buffer(struct usb_bus *bus,
+				ssize_t (*fill_func)(struct debug_buffer *))
+{
+	struct debug_buffer *buf;
+
+	buf = kzalloc(sizeof(struct debug_buffer), GFP_KERNEL);
+
+	if (buf) {
+		buf->bus = bus;
+		buf->fill_func = fill_func;
+		mutex_init(&buf->mutex);
+	}
+
+	return buf;
+}
+
+static int fill_buffer(struct debug_buffer *buf)
+{
+	int ret = 0;
+
+	if (!buf->page)
+		buf->page = (char *)get_zeroed_page(GFP_KERNEL);
+
+	if (!buf->page) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	ret = buf->fill_func(buf);
+
+	if (ret >= 0) {
+		buf->count = ret;
+		ret = 0;
+	}
+
+out:
+	return ret;
+}
+
+static ssize_t debug_output(struct file *file, char __user *user_buf,
+			    size_t len, loff_t *offset)
+{
+	struct debug_buffer *buf = file->private_data;
+	int ret = 0;
+
+	mutex_lock(&buf->mutex);
+	if (buf->count == 0) {
+		ret = fill_buffer(buf);
+		if (ret != 0) {
+			mutex_unlock(&buf->mutex);
+			goto out;
+		}
+	}
+	mutex_unlock(&buf->mutex);
+
+	ret = simple_read_from_buffer(user_buf, len, offset,
+				      buf->page, buf->count);
+
+out:
+	return ret;
+
+}
+
+static int debug_close(struct inode *inode, struct file *file)
+{
+	struct debug_buffer *buf = file->private_data;
+
+	if (buf) {
+		if (buf->page)
+			free_page((unsigned long)buf->page);
+		kfree(buf);
+	}
+
+	return 0;
+}
+static int debug_async_open(struct inode *inode, struct file *file)
+{
+	file->private_data = alloc_buffer(inode->i_private, fill_async_buffer);
+
+	return file->private_data ? 0 : -ENOMEM;
+}
+
+static int debug_periodic_open(struct inode *inode, struct file *file)
+{
+	file->private_data = alloc_buffer(inode->i_private,
+					  fill_periodic_buffer);
+
+	return file->private_data ? 0 : -ENOMEM;
+}
+
+static int debug_registers_open(struct inode *inode, struct file *file)
+{
+	file->private_data = alloc_buffer(inode->i_private,
+					  fill_registers_buffer);
+
+	return file->private_data ? 0 : -ENOMEM;
+}
 
 static inline void create_debug_files (struct ehci_hcd *ehci)
 {
-	struct class_device *cldev = ehci_to_hcd(ehci)->self.class_dev;
-	int retval;
+	struct usb_bus *bus = &ehci_to_hcd(ehci)->self;
 
-	retval = class_device_create_file(cldev, &class_device_attr_async);
-	retval = class_device_create_file(cldev, &class_device_attr_periodic);
-	retval = class_device_create_file(cldev, &class_device_attr_registers);
+	ehci->debug_dir = debugfs_create_dir(bus->bus_name, ehci_debug_root);
+	if (!ehci->debug_dir)
+		goto dir_error;
+
+	ehci->debug_async = debugfs_create_file("async", S_IRUGO,
+						ehci->debug_dir, bus,
+						&debug_async_fops);
+	if (!ehci->debug_async)
+		goto async_error;
+
+	ehci->debug_periodic = debugfs_create_file("periodic", S_IRUGO,
+						   ehci->debug_dir, bus,
+						   &debug_periodic_fops);
+	if (!ehci->debug_periodic)
+		goto periodic_error;
+
+	ehci->debug_registers = debugfs_create_file("registers", S_IRUGO,
+						    ehci->debug_dir, bus,
+						    &debug_registers_fops);
+	if (!ehci->debug_registers)
+		goto registers_error;
+	return;
+
+registers_error:
+	debugfs_remove(ehci->debug_periodic);
+periodic_error:
+	debugfs_remove(ehci->debug_async);
+async_error:
+	debugfs_remove(ehci->debug_dir);
+dir_error:
+	ehci->debug_periodic = NULL;
+	ehci->debug_async = NULL;
+	ehci->debug_dir = NULL;
 }
 
 static inline void remove_debug_files (struct ehci_hcd *ehci)
 {
-	struct class_device *cldev = ehci_to_hcd(ehci)->self.class_dev;
-
-	class_device_remove_file(cldev, &class_device_attr_async);
-	class_device_remove_file(cldev, &class_device_attr_periodic);
-	class_device_remove_file(cldev, &class_device_attr_registers);
+	debugfs_remove(ehci->debug_registers);
+	debugfs_remove(ehci->debug_periodic);
+	debugfs_remove(ehci->debug_async);
+	debugfs_remove(ehci->debug_dir);
 }
 
 #endif /* STUB_DEBUG_FILES */
-
diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c
index 430821cb..adb0def 100644
--- a/drivers/usb/host/ehci-fsl.c
+++ b/drivers/usb/host/ehci-fsl.c
@@ -25,7 +25,7 @@
 
 #include "ehci-fsl.h"
 
-/* FIXME: Power Managment is un-ported so temporarily disable it */
+/* FIXME: Power Management is un-ported so temporarily disable it */
 #undef CONFIG_PM
 
 /* PCI-based HCs are common, but plenty of non-PCI HCs are used too */
@@ -323,6 +323,7 @@
 	.hub_control = ehci_hub_control,
 	.bus_suspend = ehci_bus_suspend,
 	.bus_resume = ehci_bus_resume,
+	.relinquish_port = ehci_relinquish_port,
 };
 
 static int ehci_fsl_drv_probe(struct platform_device *pdev)
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 5f2d74e..4caa6a8 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -33,6 +33,7 @@
 #include <linux/usb.h>
 #include <linux/moduleparam.h>
 #include <linux/dma-mapping.h>
+#include <linux/debugfs.h>
 
 #include "../core/hcd.h"
 
@@ -109,7 +110,7 @@
 #define	EHCI_TUNE_MULT_TT	1
 #define	EHCI_TUNE_FLS		2	/* (small) 256 frame schedule */
 
-#define EHCI_IAA_JIFFIES	(HZ/100)	/* arbitrary; ~10 msec */
+#define EHCI_IAA_MSECS		10		/* arbitrary */
 #define EHCI_IO_JIFFIES		(HZ/10)		/* io watchdog > irq_thresh */
 #define EHCI_ASYNC_JIFFIES	(HZ/20)		/* async idle timeout */
 #define EHCI_SHRINK_JIFFIES	(HZ/200)	/* async qh unlink delay */
@@ -266,6 +267,7 @@
 
 /*-------------------------------------------------------------------------*/
 
+static void end_unlink_async(struct ehci_hcd *ehci);
 static void ehci_work(struct ehci_hcd *ehci);
 
 #include "ehci-hub.c"
@@ -275,25 +277,41 @@
 
 /*-------------------------------------------------------------------------*/
 
-static void ehci_watchdog (unsigned long param)
+static void ehci_iaa_watchdog(unsigned long param)
 {
 	struct ehci_hcd		*ehci = (struct ehci_hcd *) param;
 	unsigned long		flags;
+	u32			status, cmd;
 
 	spin_lock_irqsave (&ehci->lock, flags);
+	WARN_ON(!ehci->reclaim);
 
-	/* lost IAA irqs wedge things badly; seen with a vt8235 */
+	status = ehci_readl(ehci, &ehci->regs->status);
+	cmd = ehci_readl(ehci, &ehci->regs->command);
+	ehci_dbg(ehci, "IAA watchdog: status %x cmd %x\n", status, cmd);
+
+	/* lost IAA irqs wedge things badly; seen first with a vt8235 */
 	if (ehci->reclaim) {
-		u32		status = ehci_readl(ehci, &ehci->regs->status);
 		if (status & STS_IAA) {
 			ehci_vdbg (ehci, "lost IAA\n");
 			COUNT (ehci->stats.lost_iaa);
 			ehci_writel(ehci, STS_IAA, &ehci->regs->status);
-			ehci->reclaim_ready = 1;
 		}
+		ehci_writel(ehci, cmd & ~CMD_IAAD, &ehci->regs->command);
+		end_unlink_async(ehci);
 	}
 
- 	/* stop async processing after it's idled a bit */
+	spin_unlock_irqrestore(&ehci->lock, flags);
+}
+
+static void ehci_watchdog(unsigned long param)
+{
+	struct ehci_hcd		*ehci = (struct ehci_hcd *) param;
+	unsigned long		flags;
+
+	spin_lock_irqsave(&ehci->lock, flags);
+
+	/* stop async processing after it's idled a bit */
 	if (test_bit (TIMER_ASYNC_OFF, &ehci->actions))
 		start_unlink_async (ehci, ehci->async);
 
@@ -363,8 +381,6 @@
 static void ehci_work (struct ehci_hcd *ehci)
 {
 	timer_action_done (ehci, TIMER_IO_WATCHDOG);
-	if (ehci->reclaim_ready)
-		end_unlink_async (ehci);
 
 	/* another CPU may drop ehci->lock during a schedule scan while
 	 * it reports urb completions.  this flag guards against bogus
@@ -399,6 +415,7 @@
 
 	/* no more interrupts ... */
 	del_timer_sync (&ehci->watchdog);
+	del_timer_sync(&ehci->iaa_watchdog);
 
 	spin_lock_irq(&ehci->lock);
 	if (HC_IS_RUNNING (hcd->state))
@@ -447,6 +464,10 @@
 	ehci->watchdog.function = ehci_watchdog;
 	ehci->watchdog.data = (unsigned long) ehci;
 
+	init_timer(&ehci->iaa_watchdog);
+	ehci->iaa_watchdog.function = ehci_iaa_watchdog;
+	ehci->iaa_watchdog.data = (unsigned long) ehci;
+
 	/*
 	 * hw default: 1K periodic list heads, one per frame.
 	 * periodic_size can shrink by USBCMD update if hcc_params allows.
@@ -463,7 +484,6 @@
 		ehci->i_thresh = 2 + HCC_ISOC_THRES(hcc_params);
 
 	ehci->reclaim = NULL;
-	ehci->reclaim_ready = 0;
 	ehci->next_uframe = -1;
 
 	/*
@@ -654,8 +674,7 @@
 	/* complete the unlinking of some qh [4.15.2.3] */
 	if (status & STS_IAA) {
 		COUNT (ehci->stats.reclaim);
-		ehci->reclaim_ready = 1;
-		bh = 1;
+		end_unlink_async(ehci);
 	}
 
 	/* remote wakeup [4.3.1] */
@@ -761,10 +780,16 @@
 
 static void unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
 {
-	/* if we need to use IAA and it's busy, defer */
-	if (qh->qh_state == QH_STATE_LINKED
-			&& ehci->reclaim
-			&& HC_IS_RUNNING (ehci_to_hcd(ehci)->state)) {
+	/* failfast */
+	if (!HC_IS_RUNNING(ehci_to_hcd(ehci)->state))
+		end_unlink_async(ehci);
+
+	/* if it's not linked then there's nothing to do */
+	if (qh->qh_state != QH_STATE_LINKED)
+		;
+
+	/* defer till later if busy */
+	else if (ehci->reclaim) {
 		struct ehci_qh		*last;
 
 		for (last = ehci->reclaim;
@@ -774,12 +799,8 @@
 		qh->qh_state = QH_STATE_UNLINK_WAIT;
 		last->reclaim = qh;
 
-	/* bypass IAA if the hc can't care */
-	} else if (!HC_IS_RUNNING (ehci_to_hcd(ehci)->state) && ehci->reclaim)
-		end_unlink_async (ehci);
-
-	/* something else might have unlinked the qh by now */
-	if (qh->qh_state == QH_STATE_LINKED)
+	/* start IAA cycle */
+	} else
 		start_unlink_async (ehci, qh);
 }
 
@@ -806,7 +827,19 @@
 		qh = (struct ehci_qh *) urb->hcpriv;
 		if (!qh)
 			break;
-		unlink_async (ehci, qh);
+		switch (qh->qh_state) {
+		case QH_STATE_LINKED:
+		case QH_STATE_COMPLETING:
+			unlink_async(ehci, qh);
+			break;
+		case QH_STATE_UNLINK:
+		case QH_STATE_UNLINK_WAIT:
+			/* already started */
+			break;
+		case QH_STATE_IDLE:
+			WARN_ON(1);
+			break;
+		}
 		break;
 
 	case PIPE_INTERRUPT:
@@ -829,16 +862,16 @@
 		/* reschedule QH iff another request is queued */
 		if (!list_empty (&qh->qtd_list)
 				&& HC_IS_RUNNING (hcd->state)) {
-			int status;
+			int schedule_status;
 
-			status = qh_schedule (ehci, qh);
+			schedule_status = qh_schedule (ehci, qh);
 			spin_unlock_irqrestore (&ehci->lock, flags);
 
-			if (status != 0) {
+			if (schedule_status != 0) {
 				// shouldn't happen often, but ...
 				// FIXME kill those tds' urbs
 				err ("can't reschedule qh %p, err %d",
-					qh, status);
+					qh, schedule_status);
 			}
 			return status;
 		}
@@ -898,6 +931,7 @@
 		unlink_async (ehci, qh);
 		/* FALL THROUGH */
 	case QH_STATE_UNLINK:		/* wait for hw to finish? */
+	case QH_STATE_UNLINK_WAIT:
 idle_timeout:
 		spin_unlock_irqrestore (&ehci->lock, flags);
 		schedule_timeout_uninterruptible(1);
@@ -959,11 +993,26 @@
 #define	PS3_SYSTEM_BUS_DRIVER	ps3_ehci_driver
 #endif
 
-#ifdef CONFIG_440EPX
+#if defined(CONFIG_440EPX) && !defined(CONFIG_PPC_MERGE)
 #include "ehci-ppc-soc.c"
 #define	PLATFORM_DRIVER		ehci_ppc_soc_driver
 #endif
 
+#ifdef CONFIG_USB_EHCI_HCD_PPC_OF
+#include "ehci-ppc-of.c"
+#define OF_PLATFORM_DRIVER	ehci_hcd_ppc_of_driver
+#endif
+
+#ifdef CONFIG_ARCH_ORION
+#include "ehci-orion.c"
+#define	PLATFORM_DRIVER		ehci_orion_driver
+#endif
+
+#ifdef CONFIG_ARCH_IXP4XX
+#include "ehci-ixp4xx.c"
+#define	PLATFORM_DRIVER		ixp4xx_ehci_driver
+#endif
+
 #if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER) && \
     !defined(PS3_SYSTEM_BUS_DRIVER)
 #error "missing bus glue for ehci-hcd"
@@ -978,41 +1027,66 @@
 		 sizeof(struct ehci_qh), sizeof(struct ehci_qtd),
 		 sizeof(struct ehci_itd), sizeof(struct ehci_sitd));
 
+#ifdef DEBUG
+	ehci_debug_root = debugfs_create_dir("ehci", NULL);
+	if (!ehci_debug_root)
+		return -ENOENT;
+#endif
+
 #ifdef PLATFORM_DRIVER
 	retval = platform_driver_register(&PLATFORM_DRIVER);
 	if (retval < 0)
-		return retval;
+		goto clean0;
 #endif
 
 #ifdef PCI_DRIVER
 	retval = pci_register_driver(&PCI_DRIVER);
-	if (retval < 0) {
-#ifdef PLATFORM_DRIVER
-		platform_driver_unregister(&PLATFORM_DRIVER);
-#endif
-		return retval;
-	}
+	if (retval < 0)
+		goto clean1;
 #endif
 
 #ifdef PS3_SYSTEM_BUS_DRIVER
 	retval = ps3_ehci_driver_register(&PS3_SYSTEM_BUS_DRIVER);
-	if (retval < 0) {
-#ifdef PLATFORM_DRIVER
-		platform_driver_unregister(&PLATFORM_DRIVER);
-#endif
-#ifdef PCI_DRIVER
-		pci_unregister_driver(&PCI_DRIVER);
-#endif
-		return retval;
-	}
+	if (retval < 0)
+		goto clean2;
 #endif
 
+#ifdef OF_PLATFORM_DRIVER
+	retval = of_register_platform_driver(&OF_PLATFORM_DRIVER);
+	if (retval < 0)
+		goto clean3;
+#endif
+	return retval;
+
+#ifdef OF_PLATFORM_DRIVER
+	/* of_unregister_platform_driver(&OF_PLATFORM_DRIVER); */
+clean3:
+#endif
+#ifdef PS3_SYSTEM_BUS_DRIVER
+	ps3_ehci_driver_unregister(&PS3_SYSTEM_BUS_DRIVER);
+clean2:
+#endif
+#ifdef PCI_DRIVER
+	pci_unregister_driver(&PCI_DRIVER);
+clean1:
+#endif
+#ifdef PLATFORM_DRIVER
+	platform_driver_unregister(&PLATFORM_DRIVER);
+clean0:
+#endif
+#ifdef DEBUG
+	debugfs_remove(ehci_debug_root);
+	ehci_debug_root = NULL;
+#endif
 	return retval;
 }
 module_init(ehci_hcd_init);
 
 static void __exit ehci_hcd_cleanup(void)
 {
+#ifdef OF_PLATFORM_DRIVER
+	of_unregister_platform_driver(&OF_PLATFORM_DRIVER);
+#endif
 #ifdef PLATFORM_DRIVER
 	platform_driver_unregister(&PLATFORM_DRIVER);
 #endif
@@ -1022,6 +1096,9 @@
 #ifdef PS3_SYSTEM_BUS_DRIVER
 	ps3_ehci_driver_unregister(&PS3_SYSTEM_BUS_DRIVER);
 #endif
+#ifdef DEBUG
+	debugfs_remove(ehci_debug_root);
+#endif
 }
 module_exit(ehci_hcd_cleanup);
 
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
index 735db4a..40e8240 100644
--- a/drivers/usb/host/ehci-hub.c
+++ b/drivers/usb/host/ehci-hub.c
@@ -123,6 +123,8 @@
 
 	if (time_before (jiffies, ehci->next_statechange))
 		msleep(5);
+	del_timer_sync(&ehci->watchdog);
+	del_timer_sync(&ehci->iaa_watchdog);
 
 	port = HCS_N_PORTS (ehci->hcs_params);
 	spin_lock_irq (&ehci->lock);
@@ -134,7 +136,7 @@
 	}
 	ehci->command = ehci_readl(ehci, &ehci->regs->command);
 	if (ehci->reclaim)
-		ehci->reclaim_ready = 1;
+		end_unlink_async(ehci);
 	ehci_work(ehci);
 
 	/* Unlike other USB host controller types, EHCI doesn't have
@@ -170,8 +172,11 @@
 		}
 	}
 
+	/* Apparently some devices need a >= 1-uframe delay here */
+	if (ehci->bus_suspended)
+		udelay(150);
+
 	/* turn off now-idle HC */
-	del_timer_sync (&ehci->watchdog);
 	ehci_halt (ehci);
 	hcd->state = HC_STATE_SUSPENDED;
 
@@ -291,14 +296,16 @@
 /*-------------------------------------------------------------------------*/
 
 /* Display the ports dedicated to the companion controller */
-static ssize_t show_companion(struct class_device *class_dev, char *buf)
+static ssize_t show_companion(struct device *dev,
+			      struct device_attribute *attr,
+			      char *buf)
 {
 	struct ehci_hcd		*ehci;
 	int			nports, index, n;
 	int			count = PAGE_SIZE;
 	char			*ptr = buf;
 
-	ehci = hcd_to_ehci(bus_to_hcd(class_get_devdata(class_dev)));
+	ehci = hcd_to_ehci(bus_to_hcd(dev_get_drvdata(dev)));
 	nports = HCS_N_PORTS(ehci->hcs_params);
 
 	for (index = 0; index < nports; ++index) {
@@ -312,40 +319,21 @@
 }
 
 /*
- * Dedicate or undedicate a port to the companion controller.
- * Syntax is "[-]portnum", where a leading '-' sign means
- * return control of the port to the EHCI controller.
+ * Sets the owner of a port
  */
-static ssize_t store_companion(struct class_device *class_dev,
-		const char *buf, size_t count)
+static void set_owner(struct ehci_hcd *ehci, int portnum, int new_owner)
 {
-	struct ehci_hcd		*ehci;
-	int			portnum, new_owner, try;
 	u32 __iomem		*status_reg;
 	u32			port_status;
+	int 			try;
 
-	ehci = hcd_to_ehci(bus_to_hcd(class_get_devdata(class_dev)));
-	new_owner = PORT_OWNER;		/* Owned by companion */
-	if (sscanf(buf, "%d", &portnum) != 1)
-		return -EINVAL;
-	if (portnum < 0) {
-		portnum = - portnum;
-		new_owner = 0;		/* Owned by EHCI */
-	}
-	if (portnum <= 0 || portnum > HCS_N_PORTS(ehci->hcs_params))
-		return -ENOENT;
-	status_reg = &ehci->regs->port_status[--portnum];
-	if (new_owner)
-		set_bit(portnum, &ehci->companion_ports);
-	else
-		clear_bit(portnum, &ehci->companion_ports);
+	status_reg = &ehci->regs->port_status[portnum];
 
 	/*
 	 * The controller won't set the OWNER bit if the port is
 	 * enabled, so this loop will sometimes require at least two
 	 * iterations: one to disable the port and one to set OWNER.
 	 */
-
 	for (try = 4; try > 0; --try) {
 		spin_lock_irq(&ehci->lock);
 		port_status = ehci_readl(ehci, status_reg);
@@ -362,9 +350,39 @@
 		if (try > 1)
 			msleep(5);
 	}
+}
+
+/*
+ * Dedicate or undedicate a port to the companion controller.
+ * Syntax is "[-]portnum", where a leading '-' sign means
+ * return control of the port to the EHCI controller.
+ */
+static ssize_t store_companion(struct device *dev,
+			       struct device_attribute *attr,
+			       const char *buf, size_t count)
+{
+	struct ehci_hcd		*ehci;
+	int			portnum, new_owner;
+
+	ehci = hcd_to_ehci(bus_to_hcd(dev_get_drvdata(dev)));
+	new_owner = PORT_OWNER;		/* Owned by companion */
+	if (sscanf(buf, "%d", &portnum) != 1)
+		return -EINVAL;
+	if (portnum < 0) {
+		portnum = - portnum;
+		new_owner = 0;		/* Owned by EHCI */
+	}
+	if (portnum <= 0 || portnum > HCS_N_PORTS(ehci->hcs_params))
+		return -ENOENT;
+	portnum--;
+	if (new_owner)
+		set_bit(portnum, &ehci->companion_ports);
+	else
+		clear_bit(portnum, &ehci->companion_ports);
+	set_owner(ehci, portnum, new_owner);
 	return count;
 }
-static CLASS_DEVICE_ATTR(companion, 0644, show_companion, store_companion);
+static DEVICE_ATTR(companion, 0644, show_companion, store_companion);
 
 static inline void create_companion_file(struct ehci_hcd *ehci)
 {
@@ -372,16 +390,16 @@
 
 	/* with integrated TT there is no companion! */
 	if (!ehci_is_TDI(ehci))
-		i = class_device_create_file(ehci_to_hcd(ehci)->self.class_dev,
-				&class_device_attr_companion);
+		i = device_create_file(ehci_to_hcd(ehci)->self.dev,
+				       &dev_attr_companion);
 }
 
 static inline void remove_companion_file(struct ehci_hcd *ehci)
 {
 	/* with integrated TT there is no companion! */
 	if (!ehci_is_TDI(ehci))
-		class_device_remove_file(ehci_to_hcd(ehci)->self.class_dev,
-				&class_device_attr_companion);
+		device_remove_file(ehci_to_hcd(ehci)->self.dev,
+				   &dev_attr_companion);
 }
 
 
@@ -393,10 +411,8 @@
 	u32 __iomem	*status_reg,
 	int		port_status
 ) {
-	if (!(port_status & PORT_CONNECT)) {
-		ehci->reset_done [index] = 0;
+	if (!(port_status & PORT_CONNECT))
 		return port_status;
-	}
 
 	/* if reset finished and it's still not enabled -- handoff */
 	if (!(port_status & PORT_PE)) {
@@ -475,8 +491,6 @@
 		 * controller by the user.
 		 */
 
-		if (!(temp & PORT_CONNECT))
-			ehci->reset_done [i] = 0;
 		if ((temp & mask) != 0
 				|| ((temp & PORT_RESUME) != 0
 					&& time_after_eq(jiffies,
@@ -864,3 +878,13 @@
 	spin_unlock_irqrestore (&ehci->lock, flags);
 	return retval;
 }
+
+static void ehci_relinquish_port(struct usb_hcd *hcd, int portnum)
+{
+	struct ehci_hcd		*ehci = hcd_to_ehci(hcd);
+
+	if (ehci_is_TDI(ehci))
+		return;
+	set_owner(ehci, --portnum, PORT_OWNER);
+}
+
diff --git a/drivers/usb/host/ehci-ixp4xx.c b/drivers/usb/host/ehci-ixp4xx.c
new file mode 100644
index 0000000..3041d8f
--- /dev/null
+++ b/drivers/usb/host/ehci-ixp4xx.c
@@ -0,0 +1,152 @@
+/*
+ * IXP4XX EHCI Host Controller Driver
+ *
+ * Author: Vladimir Barinov <vbarinov@ru.mvista.com>
+ *
+ * Based on "ehci-fsl.c" by Randy Vinson <rvinson@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>
+
+static int ixp4xx_ehci_init(struct usb_hcd *hcd)
+{
+	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+	int retval = 0;
+
+	ehci->big_endian_desc = 1;
+	ehci->big_endian_mmio = 1;
+
+	ehci->caps = hcd->regs + 0x100;
+	ehci->regs = hcd->regs + 0x100
+		+ HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase));
+	ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
+
+	ehci->is_tdi_rh_tt = 1;
+	ehci_reset(ehci);
+
+	retval = ehci_init(hcd);
+	if (retval)
+		return retval;
+
+	ehci_port_power(ehci, 0);
+
+	return retval;
+}
+
+static const struct hc_driver ixp4xx_ehci_hc_driver = {
+	.description		= hcd_name,
+	.product_desc		= "IXP4XX EHCI Host Controller",
+	.hcd_priv_size		= sizeof(struct ehci_hcd),
+	.irq			= ehci_irq,
+	.flags			= HCD_MEMORY | HCD_USB2,
+	.reset			= ixp4xx_ehci_init,
+	.start			= ehci_run,
+	.stop			= ehci_stop,
+	.shutdown		= ehci_shutdown,
+	.urb_enqueue		= ehci_urb_enqueue,
+	.urb_dequeue		= ehci_urb_dequeue,
+	.endpoint_disable	= ehci_endpoint_disable,
+	.get_frame_number	= ehci_get_frame,
+	.hub_status_data	= ehci_hub_status_data,
+	.hub_control		= ehci_hub_control,
+#if defined(CONFIG_PM)
+	.bus_suspend		= ehci_bus_suspend,
+	.bus_resume		= ehci_bus_resume,
+#endif
+};
+
+static int ixp4xx_ehci_probe(struct platform_device *pdev)
+{
+	struct usb_hcd *hcd;
+	const struct hc_driver *driver = &ixp4xx_ehci_hc_driver;
+	struct resource *res;
+	int irq;
+	int retval;
+
+	if (usb_disabled())
+		return -ENODEV;
+
+	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!res) {
+		dev_err(&pdev->dev,
+			"Found HC with no IRQ. Check %s setup!\n",
+			pdev->dev.bus_id);
+		return -ENODEV;
+	}
+	irq = res->start;
+
+	hcd = usb_create_hcd(driver, &pdev->dev, pdev->dev.bus_id);
+	if (!hcd) {
+		retval = -ENOMEM;
+		goto fail_create_hcd;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&pdev->dev,
+			"Found HC with no register addr. Check %s setup!\n",
+			pdev->dev.bus_id);
+		retval = -ENODEV;
+		goto fail_request_resource;
+	}
+	hcd->rsrc_start = res->start;
+	hcd->rsrc_len = res->end - res->start + 1;
+
+	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len,
+				driver->description)) {
+		dev_dbg(&pdev->dev, "controller already in use\n");
+		retval = -EBUSY;
+		goto fail_request_resource;
+	}
+
+	hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len);
+	if (hcd->regs == NULL) {
+		dev_dbg(&pdev->dev, "error mapping memory\n");
+		retval = -EFAULT;
+		goto fail_ioremap;
+	}
+
+	retval = usb_add_hcd(hcd, irq, IRQF_SHARED);
+	if (retval)
+		goto fail_add_hcd;
+
+	return retval;
+
+fail_add_hcd:
+	iounmap(hcd->regs);
+fail_ioremap:
+	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+fail_request_resource:
+	usb_put_hcd(hcd);
+fail_create_hcd:
+	dev_err(&pdev->dev, "init %s fail, %d\n", pdev->dev.bus_id, retval);
+	return retval;
+}
+
+static int ixp4xx_ehci_remove(struct platform_device *pdev)
+{
+	struct usb_hcd *hcd = platform_get_drvdata(pdev);
+
+	usb_remove_hcd(hcd);
+	iounmap(hcd->regs);
+	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+	usb_put_hcd(hcd);
+
+	return 0;
+}
+
+MODULE_ALIAS("ixp4xx-ehci");
+
+static struct platform_driver ixp4xx_ehci_driver = {
+	.probe = ixp4xx_ehci_probe,
+	.remove = ixp4xx_ehci_remove,
+	.driver = {
+		.name = "ixp4xx-ehci",
+		.bus = &platform_bus_type
+	},
+};
diff --git a/drivers/usb/host/ehci-orion.c b/drivers/usb/host/ehci-orion.c
new file mode 100644
index 0000000..e129981
--- /dev/null
+++ b/drivers/usb/host/ehci-orion.c
@@ -0,0 +1,272 @@
+/*
+ * drivers/usb/host/ehci-orion.c
+ *
+ * Tzachi Perelstein <tzachi@marvell.com>
+ *
+ * This file is licensed under  the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <asm/arch/orion.h>
+
+#define rdl(off)	__raw_readl(hcd->regs + (off))
+#define wrl(off, val)	__raw_writel((val), hcd->regs + (off))
+
+#define USB_CAUSE		0x310
+#define USB_MASK		0x314
+#define USB_CMD			0x140
+#define USB_MODE		0x1a8
+#define USB_IPG			0x360
+#define USB_PHY_PWR_CTRL	0x400
+#define USB_PHY_TX_CTRL		0x420
+#define USB_PHY_RX_CTRL		0x430
+#define USB_PHY_IVREF_CTRL	0x440
+#define USB_PHY_TST_GRP_CTRL	0x450
+
+/*
+ * Implement Orion USB controller specification guidelines
+ */
+static void orion_usb_setup(struct usb_hcd *hcd)
+{
+	/*
+	 * Clear interrupt cause and mask
+	 */
+	wrl(USB_CAUSE, 0);
+	wrl(USB_MASK, 0);
+
+	/*
+	 * Reset controller
+	 */
+	wrl(USB_CMD, rdl(USB_CMD) | 0x2);
+	while (rdl(USB_CMD) & 0x2);
+
+	/*
+	 * GL# USB-10: Set IPG for non start of frame packets
+	 * Bits[14:8]=0xc
+	 */
+	wrl(USB_IPG, (rdl(USB_IPG) & ~0x7f00) | 0xc00);
+
+	/*
+	 * GL# USB-9: USB 2.0 Power Control
+	 * BG_VSEL[7:6]=0x1
+	 */
+	wrl(USB_PHY_PWR_CTRL, (rdl(USB_PHY_PWR_CTRL) & ~0xc0)| 0x40);
+
+	/*
+	 * GL# USB-1: USB PHY Tx Control - force calibration to '8'
+	 * TXDATA_BLOCK_EN[21]=0x1, EXT_RCAL_EN[13]=0x1, IMP_CAL[6:3]=0x8
+	 */
+	wrl(USB_PHY_TX_CTRL, (rdl(USB_PHY_TX_CTRL) & ~0x78) | 0x202040);
+
+	/*
+	 * GL# USB-3 GL# USB-9: USB PHY Rx Control
+	 * RXDATA_BLOCK_LENGHT[31:30]=0x3, EDGE_DET_SEL[27:26]=0,
+	 * CDR_FASTLOCK_EN[21]=0, DISCON_THRESHOLD[9:8]=0, SQ_THRESH[7:4]=0x1
+	 */
+	wrl(USB_PHY_RX_CTRL, (rdl(USB_PHY_RX_CTRL) & ~0xc2003f0) | 0xc0000010);
+
+	/*
+	 * GL# USB-3 GL# USB-9: USB PHY IVREF Control
+	 * PLLVDD12[1:0]=0x2, RXVDD[5:4]=0x3, Reserved[19]=0
+	 */
+	wrl(USB_PHY_IVREF_CTRL, (rdl(USB_PHY_IVREF_CTRL) & ~0x80003 ) | 0x32);
+
+	/*
+	 * GL# USB-3 GL# USB-9: USB PHY Test Group Control
+	 * REG_FIFO_SQ_RST[15]=0
+	 */
+	wrl(USB_PHY_TST_GRP_CTRL, rdl(USB_PHY_TST_GRP_CTRL) & ~0x8000);
+
+	/*
+	 * Stop and reset controller
+	 */
+	wrl(USB_CMD, rdl(USB_CMD) & ~0x1);
+	wrl(USB_CMD, rdl(USB_CMD) | 0x2);
+	while (rdl(USB_CMD) & 0x2);
+
+	/*
+	 * GL# USB-5 Streaming disable REG_USB_MODE[4]=1
+	 * TBD: This need to be done after each reset!
+	 * GL# USB-4 Setup USB Host mode
+	 */
+	wrl(USB_MODE, 0x13);
+}
+
+static int ehci_orion_setup(struct usb_hcd *hcd)
+{
+	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+	int retval;
+
+	retval = ehci_halt(ehci);
+	if (retval)
+		return retval;
+
+	/*
+	 * data structure init
+	 */
+	retval = ehci_init(hcd);
+	if (retval)
+		return retval;
+
+	ehci_reset(ehci);
+	ehci_port_power(ehci, 0);
+
+	return retval;
+}
+
+static const struct hc_driver ehci_orion_hc_driver = {
+	.description = hcd_name,
+	.product_desc = "Marvell Orion EHCI",
+	.hcd_priv_size = sizeof(struct ehci_hcd),
+
+	/*
+	 * generic hardware linkage
+	 */
+	.irq = ehci_irq,
+	.flags = HCD_MEMORY | HCD_USB2,
+
+	/*
+	 * basic lifecycle operations
+	 */
+	.reset = ehci_orion_setup,
+	.start = ehci_run,
+#ifdef CONFIG_PM
+	.suspend = ehci_bus_suspend,
+	.resume = ehci_bus_resume,
+#endif
+	.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,
+	.bus_suspend = ehci_bus_suspend,
+	.bus_resume = ehci_bus_resume,
+};
+
+static int __init ehci_orion_drv_probe(struct platform_device *pdev)
+{
+	struct resource *res;
+	struct usb_hcd *hcd;
+	struct ehci_hcd *ehci;
+	void __iomem *regs;
+	int irq, err;
+
+	if (usb_disabled())
+		return -ENODEV;
+
+	pr_debug("Initializing Orion-SoC USB Host Controller\n");
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq <= 0) {
+		dev_err(&pdev->dev,
+			"Found HC with no IRQ. Check %s setup!\n",
+			pdev->dev.bus_id);
+		err = -ENODEV;
+		goto err1;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&pdev->dev,
+			"Found HC with no register addr. Check %s setup!\n",
+			pdev->dev.bus_id);
+		err = -ENODEV;
+		goto err1;
+	}
+
+	if (!request_mem_region(res->start, res->end - res->start + 1,
+				ehci_orion_hc_driver.description)) {
+		dev_dbg(&pdev->dev, "controller already in use\n");
+		err = -EBUSY;
+		goto err1;
+	}
+
+	regs = ioremap(res->start, res->end - res->start + 1);
+	if (regs == NULL) {
+		dev_dbg(&pdev->dev, "error mapping memory\n");
+		err = -EFAULT;
+		goto err2;
+	}
+
+	hcd = usb_create_hcd(&ehci_orion_hc_driver,
+			&pdev->dev, pdev->dev.bus_id);
+	if (!hcd) {
+		err = -ENOMEM;
+		goto err3;
+	}
+
+	hcd->rsrc_start = res->start;
+	hcd->rsrc_len = res->end - res->start + 1;
+	hcd->regs = regs;
+
+	ehci = hcd_to_ehci(hcd);
+	ehci->caps = hcd->regs + 0x100;
+	ehci->regs = hcd->regs + 0x100 +
+		HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase));
+	ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
+	ehci->is_tdi_rh_tt = 1;
+	ehci->sbrn = 0x20;
+
+	/*
+	 * setup Orion USB controller
+	 */
+	orion_usb_setup(hcd);
+
+	err = usb_add_hcd(hcd, irq, IRQF_SHARED | IRQF_DISABLED);
+	if (err)
+		goto err4;
+
+	return 0;
+
+err4:
+	usb_put_hcd(hcd);
+err3:
+	iounmap(regs);
+err2:
+	release_mem_region(res->start, res->end - res->start + 1);
+err1:
+	dev_err(&pdev->dev, "init %s fail, %d\n",
+		pdev->dev.bus_id, err);
+
+	return err;
+}
+
+static int __exit ehci_orion_drv_remove(struct platform_device *pdev)
+{
+	struct usb_hcd *hcd = platform_get_drvdata(pdev);
+
+	usb_remove_hcd(hcd);
+	iounmap(hcd->regs);
+	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+	usb_put_hcd(hcd);
+
+	return 0;
+}
+
+MODULE_ALIAS("platform:orion-ehci");
+
+static struct platform_driver ehci_orion_driver = {
+	.probe		= ehci_orion_drv_probe,
+	.remove		= __exit_p(ehci_orion_drv_remove),
+	.shutdown	= usb_hcd_platform_shutdown,
+	.driver.name	= "orion-ehci",
+};
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
index ad0d496..3ba0166 100644
--- a/drivers/usb/host/ehci-pci.c
+++ b/drivers/usb/host/ehci-pci.c
@@ -305,7 +305,7 @@
 	/* emptying the schedule aborts any urbs */
 	spin_lock_irq(&ehci->lock);
 	if (ehci->reclaim)
-		ehci->reclaim_ready = 1;
+		end_unlink_async(ehci);
 	ehci_work(ehci);
 	spin_unlock_irq(&ehci->lock);
 
@@ -364,6 +364,7 @@
 	.hub_control =		ehci_hub_control,
 	.bus_suspend =		ehci_bus_suspend,
 	.bus_resume =		ehci_bus_resume,
+	.relinquish_port = 	ehci_relinquish_port,
 };
 
 /*-------------------------------------------------------------------------*/
diff --git a/drivers/usb/host/ehci-ppc-of.c b/drivers/usb/host/ehci-ppc-of.c
new file mode 100644
index 0000000..ee305b1
--- /dev/null
+++ b/drivers/usb/host/ehci-ppc-of.c
@@ -0,0 +1,238 @@
+/*
+ * EHCI HCD (Host Controller Driver) for USB.
+ *
+ * Bus Glue for PPC On-Chip EHCI driver on the of_platform bus
+ * Tested on AMCC PPC 440EPx
+ *
+ * Valentine Barshak <vbarshak@ru.mvista.com>
+ *
+ * Based on "ehci-ppc-soc.c" by Stefan Roese <sr@denx.de>
+ * and "ohci-ppc-of.c" by Sylvain Munaut <tnt@246tNt.com>
+ *
+ * This file is licenced under the GPL.
+ */
+
+#include <linux/signal.h>
+
+#include <linux/of.h>
+#include <linux/of_platform.h>
+
+/* called during probe() after chip reset completes */
+static int ehci_ppc_of_setup(struct usb_hcd *hcd)
+{
+	struct ehci_hcd	*ehci = hcd_to_ehci(hcd);
+	int		retval;
+
+	retval = ehci_halt(ehci);
+	if (retval)
+		return retval;
+
+	retval = ehci_init(hcd);
+	if (retval)
+		return retval;
+
+	ehci->sbrn = 0x20;
+	return ehci_reset(ehci);
+}
+
+
+static const struct hc_driver ehci_ppc_of_hc_driver = {
+	.description		= hcd_name,
+	.product_desc		= "OF EHCI",
+	.hcd_priv_size		= sizeof(struct ehci_hcd),
+
+	/*
+	 * generic hardware linkage
+	 */
+	.irq			= ehci_irq,
+	.flags			= HCD_MEMORY | HCD_USB2,
+
+	/*
+	 * basic lifecycle operations
+	 */
+	.reset			= ehci_ppc_of_setup,
+	.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
+	.bus_suspend		= ehci_bus_suspend,
+	.bus_resume		= ehci_bus_resume,
+#endif
+};
+
+
+/*
+ * 440EPx Errata USBH_3
+ * Fix: Enable Break Memory Transfer (BMT) in INSNREG3
+ */
+#define PPC440EPX_EHCI0_INSREG_BMT	(0x1 << 0)
+static int __devinit
+ppc44x_enable_bmt(struct device_node *dn)
+{
+	__iomem u32 *insreg_virt;
+
+	insreg_virt = of_iomap(dn, 1);
+	if (!insreg_virt)
+		return  -EINVAL;
+
+	out_be32(insreg_virt + 3, PPC440EPX_EHCI0_INSREG_BMT);
+
+	iounmap(insreg_virt);
+	return 0;
+}
+
+
+static int __devinit
+ehci_hcd_ppc_of_probe(struct of_device *op, const struct of_device_id *match)
+{
+	struct device_node *dn = op->node;
+	struct usb_hcd *hcd;
+	struct ehci_hcd	*ehci;
+	struct resource res;
+	int irq;
+	int rv;
+
+	if (usb_disabled())
+		return -ENODEV;
+
+	dev_dbg(&op->dev, "initializing PPC-OF USB Controller\n");
+
+	rv = of_address_to_resource(dn, 0, &res);
+	if (rv)
+		return rv;
+
+	hcd = usb_create_hcd(&ehci_ppc_of_hc_driver, &op->dev, "PPC-OF USB");
+	if (!hcd)
+		return -ENOMEM;
+
+	hcd->rsrc_start = res.start;
+	hcd->rsrc_len = res.end - res.start + 1;
+
+	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
+		printk(KERN_ERR __FILE__ ": request_mem_region failed\n");
+		rv = -EBUSY;
+		goto err_rmr;
+	}
+
+	irq = irq_of_parse_and_map(dn, 0);
+	if (irq == NO_IRQ) {
+		printk(KERN_ERR __FILE__ ": irq_of_parse_and_map failed\n");
+		rv = -EBUSY;
+		goto err_irq;
+	}
+
+	hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
+	if (!hcd->regs) {
+		printk(KERN_ERR __FILE__ ": ioremap failed\n");
+		rv = -ENOMEM;
+		goto err_ioremap;
+	}
+
+	ehci = hcd_to_ehci(hcd);
+
+	if (of_get_property(dn, "big-endian", NULL)) {
+		ehci->big_endian_mmio = 1;
+		ehci->big_endian_desc = 1;
+	}
+	if (of_get_property(dn, "big-endian-regs", NULL))
+		ehci->big_endian_mmio = 1;
+	if (of_get_property(dn, "big-endian-desc", NULL))
+		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 (of_device_is_compatible(dn, "ibm,usb-ehci-440epx")) {
+		rv = ppc44x_enable_bmt(dn);
+		ehci_dbg(ehci, "Break Memory Transfer (BMT) is %senabled!\n",
+				rv ? "NOT ": "");
+	}
+
+	rv = usb_add_hcd(hcd, irq, 0);
+	if (rv == 0)
+		return 0;
+
+	iounmap(hcd->regs);
+err_ioremap:
+	irq_dispose_mapping(irq);
+err_irq:
+	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+err_rmr:
+	usb_put_hcd(hcd);
+
+	return rv;
+}
+
+
+static int ehci_hcd_ppc_of_remove(struct of_device *op)
+{
+	struct usb_hcd *hcd = dev_get_drvdata(&op->dev);
+	dev_set_drvdata(&op->dev, NULL);
+
+	dev_dbg(&op->dev, "stopping PPC-OF USB Controller\n");
+
+	usb_remove_hcd(hcd);
+
+	iounmap(hcd->regs);
+	irq_dispose_mapping(hcd->irq);
+	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+
+	usb_put_hcd(hcd);
+
+	return 0;
+}
+
+
+static int ehci_hcd_ppc_of_shutdown(struct of_device *op)
+{
+	struct usb_hcd *hcd = dev_get_drvdata(&op->dev);
+
+	if (hcd->driver->shutdown)
+		hcd->driver->shutdown(hcd);
+
+	return 0;
+}
+
+
+static struct of_device_id ehci_hcd_ppc_of_match[] = {
+	{
+		.compatible = "usb-ehci",
+	},
+	{},
+};
+MODULE_DEVICE_TABLE(of, ehci_hcd_ppc_of_match);
+
+
+static struct of_platform_driver ehci_hcd_ppc_of_driver = {
+	.name		= "ppc-of-ehci",
+	.match_table	= ehci_hcd_ppc_of_match,
+	.probe		= ehci_hcd_ppc_of_probe,
+	.remove		= ehci_hcd_ppc_of_remove,
+	.shutdown	= ehci_hcd_ppc_of_shutdown,
+	.driver		= {
+		.name	= "ppc-of-ehci",
+		.owner	= THIS_MODULE,
+	},
+};
diff --git a/drivers/usb/host/ehci-ppc-soc.c b/drivers/usb/host/ehci-ppc-soc.c
index 452d4b1..a324907 100644
--- a/drivers/usb/host/ehci-ppc-soc.c
+++ b/drivers/usb/host/ehci-ppc-soc.c
@@ -162,6 +162,7 @@
 	.hub_control = ehci_hub_control,
 	.bus_suspend = ehci_bus_suspend,
 	.bus_resume = ehci_bus_resume,
+	.relinquish_port = ehci_relinquish_port,
 };
 
 static int ehci_hcd_ppc_soc_drv_probe(struct platform_device *pdev)
diff --git a/drivers/usb/host/ehci-ps3.c b/drivers/usb/host/ehci-ps3.c
index 03a6b2f..bbda58e 100644
--- a/drivers/usb/host/ehci-ps3.c
+++ b/drivers/usb/host/ehci-ps3.c
@@ -72,6 +72,7 @@
 	.bus_suspend		= ehci_bus_suspend,
 	.bus_resume		= ehci_bus_resume,
 #endif
+	.relinquish_port	= ehci_relinquish_port,
 };
 
 static int ps3_ehci_probe(struct ps3_system_bus_device *dev)
diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
index b10f39c..776a97f3 100644
--- a/drivers/usb/host/ehci-q.c
+++ b/drivers/usb/host/ehci-q.c
@@ -198,7 +198,8 @@
 
 		/* if async CSPLIT failed, try cleaning out the TT buffer */
 		if (status != -EPIPE
-				&& urb->dev->tt && !usb_pipeint (urb->pipe)
+				&& urb->dev->tt
+				&& !usb_pipeint(urb->pipe)
 				&& ((token & QTD_STS_MMF) != 0
 					|| QTD_CERR(token) == 0)
 				&& (!ehci_is_TDI(ehci)
@@ -211,6 +212,9 @@
 				urb->dev->ttport, urb->dev->devnum,
 				usb_pipeendpoint (urb->pipe), token);
 #endif /* DEBUG */
+			/* REVISIT ARC-derived cores don't clear the root
+			 * hub TT buffer in this way...
+			 */
 			usb_hub_tt_clear_buffer (urb->dev, urb->pipe);
 		}
 	}
@@ -638,6 +642,7 @@
 	u32			info1 = 0, info2 = 0;
 	int			is_input, type;
 	int			maxp = 0;
+	struct usb_tt		*tt = urb->dev->tt;
 
 	if (!qh)
 		return qh;
@@ -661,8 +666,9 @@
 	 * For control/bulk requests, the HC or TT handles these.
 	 */
 	if (type == PIPE_INTERRUPT) {
-		qh->usecs = NS_TO_US (usb_calc_bus_time (USB_SPEED_HIGH, is_input, 0,
-				hb_mult (maxp) * max_packet (maxp)));
+		qh->usecs = NS_TO_US(usb_calc_bus_time(USB_SPEED_HIGH,
+				is_input, 0,
+				hb_mult(maxp) * max_packet(maxp)));
 		qh->start = NO_FRAME;
 
 		if (urb->dev->speed == USB_SPEED_HIGH) {
@@ -680,7 +686,6 @@
 				goto done;
 			}
 		} else {
-			struct usb_tt	*tt = urb->dev->tt;
 			int		think_time;
 
 			/* gap is f(FS/LS transfer times) */
@@ -736,10 +741,8 @@
 		/* set the address of the TT; for TDI's integrated
 		 * root hub tt, leave it zeroed.
 		 */
-		if (!ehci_is_TDI(ehci)
-				|| urb->dev->tt->hub !=
-					ehci_to_hcd(ehci)->self.root_hub)
-			info2 |= urb->dev->tt->hub->devnum << 16;
+		if (tt && tt->hub != ehci_to_hcd(ehci)->self.root_hub)
+			info2 |= tt->hub->devnum << 16;
 
 		/* NOTE:  if (PIPE_INTERRUPT) { scheduler sets c-mask } */
 
@@ -973,7 +976,7 @@
 	struct ehci_qh		*qh = ehci->reclaim;
 	struct ehci_qh		*next;
 
-	timer_action_done (ehci, TIMER_IAA_WATCHDOG);
+	iaa_watchdog_done(ehci);
 
 	// qh->hw_next = cpu_to_hc32(qh->qh_dma);
 	qh->qh_state = QH_STATE_IDLE;
@@ -983,7 +986,6 @@
 	/* other unlink(s) may be pending (in QH_STATE_UNLINK_WAIT) */
 	next = qh->reclaim;
 	ehci->reclaim = next;
-	ehci->reclaim_ready = 0;
 	qh->reclaim = NULL;
 
 	qh_completions (ehci, qh);
@@ -1059,11 +1061,10 @@
 		return;
 	}
 
-	ehci->reclaim_ready = 0;
 	cmd |= CMD_IAAD;
 	ehci_writel(ehci, cmd, &ehci->regs->command);
 	(void)ehci_readl(ehci, &ehci->regs->command);
-	timer_action (ehci, TIMER_IAA_WATCHDOG);
+	iaa_watchdog_start(ehci);
 }
 
 /*-------------------------------------------------------------------------*/
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
index 80d99bc..8a8e08a 100644
--- a/drivers/usb/host/ehci-sched.c
+++ b/drivers/usb/host/ehci-sched.c
@@ -119,7 +119,8 @@
 			q = &q->fstn->fstn_next;
 			break;
 		case Q_TYPE_ITD:
-			usecs += q->itd->usecs [uframe];
+			if (q->itd->hw_transaction[uframe])
+				usecs += q->itd->stream->usecs;
 			hw_p = &q->itd->hw_next;
 			q = &q->itd->itd_next;
 			break;
@@ -211,7 +212,7 @@
  * low/fullspeed transfer can "carry over" from one uframe to the next,
  * since the TT just performs downstream transfers in sequence.
  *
- * For example two seperate 100 usec transfers can start in the same uframe,
+ * For example two separate 100 usec transfers can start in the same uframe,
  * and the second one would "carry over" 75 usecs into the next uframe.
  */
 static void
@@ -1536,7 +1537,6 @@
 		uframe = next_uframe & 0x07;
 		frame = next_uframe >> 3;
 
-		itd->usecs [uframe] = stream->usecs;
 		itd_patch(ehci, itd, iso_sched, packet, uframe);
 
 		next_uframe += stream->interval;
@@ -1565,6 +1565,16 @@
 
 #define	ISO_ERRS (EHCI_ISOC_BUF_ERR | EHCI_ISOC_BABBLE | EHCI_ISOC_XACTERR)
 
+/* Process and recycle a completed ITD.  Return true iff its urb completed,
+ * and hence its completion callback probably added things to the hardware
+ * schedule.
+ *
+ * Note that we carefully avoid recycling this descriptor until after any
+ * completion callback runs, so that it won't be reused quickly.  That is,
+ * assuming (a) no more than two urbs per frame on this endpoint, and also
+ * (b) only this endpoint's completions submit URBs.  It seems some silicon
+ * corrupts things if you reuse completed descriptors very quickly...
+ */
 static unsigned
 itd_complete (
 	struct ehci_hcd	*ehci,
@@ -1577,6 +1587,7 @@
 	int					urb_index = -1;
 	struct ehci_iso_stream			*stream = itd->stream;
 	struct usb_device			*dev;
+	unsigned				retval = false;
 
 	/* for each uframe with a packet */
 	for (uframe = 0; uframe < 8; uframe++) {
@@ -1610,30 +1621,21 @@
 		}
 	}
 
-	usb_put_urb (urb);
-	itd->urb = NULL;
-	itd->stream = NULL;
-	list_move (&itd->itd_list, &stream->free_list);
-	iso_stream_put (ehci, stream);
-
 	/* handle completion now? */
 	if (likely ((urb_index + 1) != urb->number_of_packets))
-		return 0;
+		goto done;
 
 	/* ASSERT: it's really the last itd for this urb
 	list_for_each_entry (itd, &stream->td_list, itd_list)
 		BUG_ON (itd->urb == urb);
 	 */
 
-	/* give urb back to the driver ... can be out-of-order */
+	/* give urb back to the driver; completion often (re)submits */
 	dev = urb->dev;
 	ehci_urb_done(ehci, urb, 0);
+	retval = true;
 	urb = NULL;
-
-	/* defer stopping schedule; completion can submit */
 	ehci->periodic_sched--;
-	if (unlikely (!ehci->periodic_sched))
-		(void) disable_periodic (ehci);
 	ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs--;
 
 	if (unlikely (list_empty (&stream->td_list))) {
@@ -1645,8 +1647,15 @@
 			(stream->bEndpointAddress & USB_DIR_IN) ? "in" : "out");
 	}
 	iso_stream_put (ehci, stream);
+	/* OK to recycle this ITD now that its completion callback ran. */
+done:
+	usb_put_urb(urb);
+	itd->urb = NULL;
+	itd->stream = NULL;
+	list_move(&itd->itd_list, &stream->free_list);
+	iso_stream_put(ehci, stream);
 
-	return 1;
+	return retval;
 }
 
 /*-------------------------------------------------------------------------*/
@@ -1712,8 +1721,6 @@
 	return status;
 }
 
-#ifdef CONFIG_USB_EHCI_SPLIT_ISO
-
 /*-------------------------------------------------------------------------*/
 
 /*
@@ -1950,6 +1957,16 @@
 #define	SITD_ERRS (SITD_STS_ERR | SITD_STS_DBE | SITD_STS_BABBLE \
 				| SITD_STS_XACT | SITD_STS_MMF)
 
+/* Process and recycle a completed SITD.  Return true iff its urb completed,
+ * and hence its completion callback probably added things to the hardware
+ * schedule.
+ *
+ * Note that we carefully avoid recycling this descriptor until after any
+ * completion callback runs, so that it won't be reused quickly.  That is,
+ * assuming (a) no more than two urbs per frame on this endpoint, and also
+ * (b) only this endpoint's completions submit URBs.  It seems some silicon
+ * corrupts things if you reuse completed descriptors very quickly...
+ */
 static unsigned
 sitd_complete (
 	struct ehci_hcd		*ehci,
@@ -1961,6 +1978,7 @@
 	int					urb_index = -1;
 	struct ehci_iso_stream			*stream = sitd->stream;
 	struct usb_device			*dev;
+	unsigned				retval = false;
 
 	urb_index = sitd->index;
 	desc = &urb->iso_frame_desc [urb_index];
@@ -1981,32 +1999,23 @@
 		desc->status = 0;
 		desc->actual_length = desc->length - SITD_LENGTH (t);
 	}
-
-	usb_put_urb (urb);
-	sitd->urb = NULL;
-	sitd->stream = NULL;
-	list_move (&sitd->sitd_list, &stream->free_list);
 	stream->depth -= stream->interval << 3;
-	iso_stream_put (ehci, stream);
 
 	/* handle completion now? */
 	if ((urb_index + 1) != urb->number_of_packets)
-		return 0;
+		goto done;
 
 	/* ASSERT: it's really the last sitd for this urb
 	list_for_each_entry (sitd, &stream->td_list, sitd_list)
 		BUG_ON (sitd->urb == urb);
 	 */
 
-	/* give urb back to the driver */
+	/* give urb back to the driver; completion often (re)submits */
 	dev = urb->dev;
 	ehci_urb_done(ehci, urb, 0);
+	retval = true;
 	urb = NULL;
-
-	/* defer stopping schedule; completion can submit */
 	ehci->periodic_sched--;
-	if (!ehci->periodic_sched)
-		(void) disable_periodic (ehci);
 	ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs--;
 
 	if (list_empty (&stream->td_list)) {
@@ -2018,8 +2027,15 @@
 			(stream->bEndpointAddress & USB_DIR_IN) ? "in" : "out");
 	}
 	iso_stream_put (ehci, stream);
+	/* OK to recycle this SITD now that its completion callback ran. */
+done:
+	usb_put_urb(urb);
+	sitd->urb = NULL;
+	sitd->stream = NULL;
+	list_move(&sitd->sitd_list, &stream->free_list);
+	iso_stream_put(ehci, stream);
 
-	return 1;
+	return retval;
 }
 
 
@@ -2082,26 +2098,6 @@
 	return status;
 }
 
-#else
-
-static inline int
-sitd_submit (struct ehci_hcd *ehci, struct urb *urb, gfp_t mem_flags)
-{
-	ehci_dbg (ehci, "split iso support is disabled\n");
-	return -ENOSYS;
-}
-
-static inline unsigned
-sitd_complete (
-	struct ehci_hcd		*ehci,
-	struct ehci_sitd	*sitd
-) {
-	ehci_err (ehci, "sitd_complete %p?\n", sitd);
-	return 0;
-}
-
-#endif /* USB_EHCI_SPLIT_ISO */
-
 /*-------------------------------------------------------------------------*/
 
 static void
@@ -2127,17 +2123,9 @@
 	for (;;) {
 		union ehci_shadow	q, *q_p;
 		__hc32			type, *hw_p;
-		unsigned		uframes;
+		unsigned		incomplete = false;
 
-		/* don't scan past the live uframe */
 		frame = now_uframe >> 3;
-		if (frame == (clock >> 3))
-			uframes = now_uframe & 0x07;
-		else {
-			/* safe to scan the whole frame at once */
-			now_uframe |= 0x07;
-			uframes = 8;
-		}
 
 restart:
 		/* scan each element in frame's queue for completions */
@@ -2175,12 +2163,15 @@
 				q = q.fstn->fstn_next;
 				break;
 			case Q_TYPE_ITD:
-				/* skip itds for later in the frame */
+				/* If this ITD is still active, leave it for
+				 * later processing ... check the next entry.
+				 */
 				rmb ();
-				for (uf = live ? uframes : 8; uf < 8; uf++) {
+				for (uf = 0; uf < 8 && live; uf++) {
 					if (0 == (q.itd->hw_transaction [uf]
 							& ITD_ACTIVE(ehci)))
 						continue;
+					incomplete = true;
 					q_p = &q.itd->itd_next;
 					hw_p = &q.itd->hw_next;
 					type = Q_NEXT_TYPE(ehci,
@@ -2188,10 +2179,12 @@
 					q = *q_p;
 					break;
 				}
-				if (uf != 8)
+				if (uf < 8 && live)
 					break;
 
-				/* this one's ready ... HC won't cache the
+				/* Take finished ITDs out of the schedule
+				 * and process them:  recycle, maybe report
+				 * URB completion.  HC won't cache the
 				 * pointer for much longer, if at all.
 				 */
 				*q_p = q.itd->itd_next;
@@ -2202,8 +2195,12 @@
 				q = *q_p;
 				break;
 			case Q_TYPE_SITD:
+				/* If this SITD is still active, leave it for
+				 * later processing ... check the next entry.
+				 */
 				if ((q.sitd->hw_results & SITD_ACTIVE(ehci))
 						&& live) {
+					incomplete = true;
 					q_p = &q.sitd->sitd_next;
 					hw_p = &q.sitd->hw_next;
 					type = Q_NEXT_TYPE(ehci,
@@ -2211,6 +2208,11 @@
 					q = *q_p;
 					break;
 				}
+
+				/* Take finished SITDs out of the schedule
+				 * and process them:  recycle, maybe report
+				 * URB completion.
+				 */
 				*q_p = q.sitd->sitd_next;
 				*hw_p = q.sitd->hw_next;
 				type = Q_NEXT_TYPE(ehci, q.sitd->hw_next);
@@ -2226,11 +2228,24 @@
 			}
 
 			/* assume completion callbacks modify the queue */
-			if (unlikely (modified))
-				goto restart;
+			if (unlikely (modified)) {
+				if (likely(ehci->periodic_sched > 0))
+					goto restart;
+				/* maybe we can short-circuit this scan! */
+				disable_periodic(ehci);
+				now_uframe = clock;
+				break;
+			}
 		}
 
-		/* stop when we catch up to the HC */
+		/* If we can tell we caught up to the hardware, stop now.
+		 * We can't advance our scan without collecting the ISO
+		 * transfers that are still pending in this frame.
+		 */
+		if (incomplete && HC_IS_RUNNING(ehci_to_hcd(ehci)->state)) {
+			ehci->next_uframe = now_uframe;
+			break;
+		}
 
 		// FIXME:  this assumes we won't get lapped when
 		// latencies climb; that should be rare, but...
@@ -2243,7 +2258,8 @@
 		if (now_uframe == clock) {
 			unsigned	now;
 
-			if (!HC_IS_RUNNING (ehci_to_hcd(ehci)->state))
+			if (!HC_IS_RUNNING (ehci_to_hcd(ehci)->state)
+					|| ehci->periodic_sched == 0)
 				break;
 			ehci->next_uframe = now_uframe;
 			now = ehci_readl(ehci, &ehci->regs->frame_index) % mod;
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index 951d69f..bf92d20 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -74,7 +74,6 @@
 	/* async schedule support */
 	struct ehci_qh		*async;
 	struct ehci_qh		*reclaim;
-	unsigned		reclaim_ready : 1;
 	unsigned		scanning : 1;
 
 	/* periodic schedule support */
@@ -105,6 +104,7 @@
 	struct dma_pool		*itd_pool;	/* itd per iso urb */
 	struct dma_pool		*sitd_pool;	/* sitd per split iso urb */
 
+	struct timer_list	iaa_watchdog;
 	struct timer_list	watchdog;
 	unsigned long		actions;
 	unsigned		stamp;
@@ -127,6 +127,14 @@
 #else
 #	define COUNT(x) do {} while (0)
 #endif
+
+	/* debug files */
+#ifdef DEBUG
+	struct dentry		*debug_dir;
+	struct dentry		*debug_async;
+	struct dentry		*debug_periodic;
+	struct dentry		*debug_registers;
+#endif
 };
 
 /* convert between an HCD pointer and the corresponding EHCI_HCD */
@@ -140,9 +148,21 @@
 }
 
 
+static inline void
+iaa_watchdog_start(struct ehci_hcd *ehci)
+{
+	WARN_ON(timer_pending(&ehci->iaa_watchdog));
+	mod_timer(&ehci->iaa_watchdog,
+			jiffies + msecs_to_jiffies(EHCI_IAA_MSECS));
+}
+
+static inline void iaa_watchdog_done(struct ehci_hcd *ehci)
+{
+	del_timer(&ehci->iaa_watchdog);
+}
+
 enum ehci_timer_action {
 	TIMER_IO_WATCHDOG,
-	TIMER_IAA_WATCHDOG,
 	TIMER_ASYNC_SHRINK,
 	TIMER_ASYNC_OFF,
 };
@@ -160,9 +180,6 @@
 		unsigned long t;
 
 		switch (action) {
-		case TIMER_IAA_WATCHDOG:
-			t = EHCI_IAA_JIFFIES;
-			break;
 		case TIMER_IO_WATCHDOG:
 			t = EHCI_IO_JIFFIES;
 			break;
@@ -179,8 +196,7 @@
 		// async queue SHRINK often precedes IAA.  while it's ready
 		// to go OFF neither can matter, and afterwards the IO
 		// watchdog stops unless there's still periodic traffic.
-		if (action != TIMER_IAA_WATCHDOG
-				&& t > ehci->watchdog.expires
+		if (time_before_eq(t, ehci->watchdog.expires)
 				&& timer_pending (&ehci->watchdog))
 			return;
 		mod_timer (&ehci->watchdog, t);
@@ -534,8 +550,8 @@
 	 * trusting urb->interval == f(epdesc->bInterval) and
 	 * including the extra info for hw_bufp[0..2]
 	 */
-	u8			interval;
 	u8			usecs, c_usecs;
+	u16			interval;
 	u16			tt_usecs;
 	u16			maxp;
 	u16			raw_mask;
@@ -586,7 +602,6 @@
 	unsigned		frame;		/* where scheduled */
 	unsigned		pg;
 	unsigned		index[8];	/* in urb->iso_frame_desc */
-	u8			usecs[8];
 } __attribute__ ((aligned (32)));
 
 /*-------------------------------------------------------------------------*/
@@ -725,11 +740,16 @@
  * definition below can die once the 4xx support is
  * finally ported over.
  */
-#if defined(CONFIG_PPC)
+#if defined(CONFIG_PPC) && !defined(CONFIG_PPC_MERGE)
 #define readl_be(addr)		in_be32((__force unsigned *)addr)
 #define writel_be(val, addr)	out_be32((__force unsigned *)addr, val)
 #endif
 
+#if defined(CONFIG_ARM) && defined(CONFIG_ARCH_IXP4XX)
+#define readl_be(addr)		__raw_readl((__force unsigned *)addr)
+#define writel_be(val, addr)	__raw_writel(val, (__force unsigned *)addr)
+#endif
+
 static inline unsigned int ehci_readl(const struct ehci_hcd *ehci,
 		__u32 __iomem * regs)
 {
diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c
index c27417f..0130fd8 100644
--- a/drivers/usb/host/isp116x-hcd.c
+++ b/drivers/usb/host/isp116x-hcd.c
@@ -918,7 +918,6 @@
 			      | RH_PS_OCIC | RH_PS_PRSC)) {
 			changed = 1;
 			buf[0] |= 1 << (i + 1);
-			continue;
 		}
 	}
 	spin_unlock_irqrestore(&isp116x->lock, flags);
diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c
index d849c80..126fcbd 100644
--- a/drivers/usb/host/ohci-at91.c
+++ b/drivers/usb/host/ohci-at91.c
@@ -17,6 +17,8 @@
 
 #include <asm/mach-types.h>
 #include <asm/hardware.h>
+#include <asm/gpio.h>
+
 #include <asm/arch/board.h>
 #include <asm/arch/cpu.h>
 
@@ -271,12 +273,41 @@
 
 static int ohci_hcd_at91_drv_probe(struct platform_device *pdev)
 {
+	struct at91_usbh_data	*pdata = pdev->dev.platform_data;
+	int			i;
+
+	if (pdata) {
+		/* REVISIT make the driver support per-port power switching,
+		 * and also overcurrent detection.  Here we assume the ports
+		 * are always powered while this driver is active, and use
+		 * active-low power switches.
+		 */
+		for (i = 0; i < pdata->ports; i++) {
+			if (pdata->vbus_pin[i] <= 0)
+				continue;
+			gpio_request(pdata->vbus_pin[i], "ohci_vbus");
+			gpio_direction_output(pdata->vbus_pin[i], 0);
+		}
+	}
+
 	device_init_wakeup(&pdev->dev, 1);
 	return usb_hcd_at91_probe(&ohci_at91_hc_driver, pdev);
 }
 
 static int ohci_hcd_at91_drv_remove(struct platform_device *pdev)
 {
+	struct at91_usbh_data	*pdata = pdev->dev.platform_data;
+	int			i;
+
+	if (pdata) {
+		for (i = 0; i < pdata->ports; i++) {
+			if (pdata->vbus_pin[i] <= 0)
+				continue;
+			gpio_direction_output(pdata->vbus_pin[i], 1);
+			gpio_free(pdata->vbus_pin[i]);
+		}
+	}
+
 	device_init_wakeup(&pdev->dev, 0);
 	return usb_hcd_at91_remove(platform_get_drvdata(pdev), pdev);
 }
diff --git a/drivers/usb/host/ohci-dbg.c b/drivers/usb/host/ohci-dbg.c
index ebab5ce..a22c30a 100644
--- a/drivers/usb/host/ohci-dbg.c
+++ b/drivers/usb/host/ohci-dbg.c
@@ -401,6 +401,42 @@
 
 #else
 
+static int debug_async_open(struct inode *, struct file *);
+static int debug_periodic_open(struct inode *, struct file *);
+static int debug_registers_open(struct inode *, struct file *);
+static int debug_async_open(struct inode *, struct file *);
+static ssize_t debug_output(struct file*, char __user*, size_t, loff_t*);
+static int debug_close(struct inode *, struct file *);
+
+static const struct file_operations debug_async_fops = {
+	.owner		= THIS_MODULE,
+	.open		= debug_async_open,
+	.read		= debug_output,
+	.release	= debug_close,
+};
+static const struct file_operations debug_periodic_fops = {
+	.owner		= THIS_MODULE,
+	.open		= debug_periodic_open,
+	.read		= debug_output,
+	.release	= debug_close,
+};
+static const struct file_operations debug_registers_fops = {
+	.owner		= THIS_MODULE,
+	.open		= debug_registers_open,
+	.read		= debug_output,
+	.release	= debug_close,
+};
+
+static struct dentry *ohci_debug_root;
+
+struct debug_buffer {
+	ssize_t (*fill_func)(struct debug_buffer *);	/* fill method */
+	struct device *dev;
+	struct mutex mutex;	/* protect filling of buffer */
+	size_t count;		/* number of characters filled into buffer */
+	char *page;
+};
+
 static ssize_t
 show_list (struct ohci_hcd *ohci, char *buf, size_t count, struct ed *ed)
 {
@@ -467,8 +503,7 @@
 	return count - size;
 }
 
-static ssize_t
-show_async (struct class_device *class_dev, char *buf)
+static ssize_t fill_async_buffer(struct debug_buffer *buf)
 {
 	struct usb_bus		*bus;
 	struct usb_hcd		*hcd;
@@ -476,25 +511,23 @@
 	size_t			temp;
 	unsigned long		flags;
 
-	bus = class_get_devdata(class_dev);
+	bus = dev_get_drvdata(buf->dev);
 	hcd = bus_to_hcd(bus);
 	ohci = hcd_to_ohci(hcd);
 
 	/* display control and bulk lists together, for simplicity */
 	spin_lock_irqsave (&ohci->lock, flags);
-	temp = show_list (ohci, buf, PAGE_SIZE, ohci->ed_controltail);
-	temp += show_list (ohci, buf + temp, PAGE_SIZE - temp, ohci->ed_bulktail);
+	temp = show_list(ohci, buf->page, buf->count, ohci->ed_controltail);
+	temp += show_list(ohci, buf->page + temp, buf->count - temp,
+			  ohci->ed_bulktail);
 	spin_unlock_irqrestore (&ohci->lock, flags);
 
 	return temp;
 }
-static CLASS_DEVICE_ATTR (async, S_IRUGO, show_async, NULL);
-
 
 #define DBG_SCHED_LIMIT 64
 
-static ssize_t
-show_periodic (struct class_device *class_dev, char *buf)
+static ssize_t fill_periodic_buffer(struct debug_buffer *buf)
 {
 	struct usb_bus		*bus;
 	struct usb_hcd		*hcd;
@@ -509,10 +542,10 @@
 		return 0;
 	seen_count = 0;
 
-	bus = class_get_devdata(class_dev);
+	bus = (struct usb_bus *)dev_get_drvdata(buf->dev);
 	hcd = bus_to_hcd(bus);
 	ohci = hcd_to_ohci(hcd);
-	next = buf;
+	next = buf->page;
 	size = PAGE_SIZE;
 
 	temp = scnprintf (next, size, "size = %d\n", NUM_INTS);
@@ -589,13 +622,9 @@
 
 	return PAGE_SIZE - size;
 }
-static CLASS_DEVICE_ATTR (periodic, S_IRUGO, show_periodic, NULL);
-
-
 #undef DBG_SCHED_LIMIT
 
-static ssize_t
-show_registers (struct class_device *class_dev, char *buf)
+static ssize_t fill_registers_buffer(struct debug_buffer *buf)
 {
 	struct usb_bus		*bus;
 	struct usb_hcd		*hcd;
@@ -606,11 +635,11 @@
 	char			*next;
 	u32			rdata;
 
-	bus = class_get_devdata(class_dev);
+	bus = (struct usb_bus *)dev_get_drvdata(buf->dev);
 	hcd = bus_to_hcd(bus);
 	ohci = hcd_to_ohci(hcd);
 	regs = ohci->regs;
-	next = buf;
+	next = buf->page;
 	size = PAGE_SIZE;
 
 	spin_lock_irqsave (&ohci->lock, flags);
@@ -677,29 +706,155 @@
 
 done:
 	spin_unlock_irqrestore (&ohci->lock, flags);
+
 	return PAGE_SIZE - size;
 }
-static CLASS_DEVICE_ATTR (registers, S_IRUGO, show_registers, NULL);
 
+static struct debug_buffer *alloc_buffer(struct device *dev,
+				ssize_t (*fill_func)(struct debug_buffer *))
+{
+	struct debug_buffer *buf;
 
+	buf = kzalloc(sizeof(struct debug_buffer), GFP_KERNEL);
+
+	if (buf) {
+		buf->dev = dev;
+		buf->fill_func = fill_func;
+		mutex_init(&buf->mutex);
+	}
+
+	return buf;
+}
+
+static int fill_buffer(struct debug_buffer *buf)
+{
+	int ret = 0;
+
+	if (!buf->page)
+		buf->page = (char *)get_zeroed_page(GFP_KERNEL);
+
+	if (!buf->page) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	ret = buf->fill_func(buf);
+
+	if (ret >= 0) {
+		buf->count = ret;
+		ret = 0;
+	}
+
+out:
+	return ret;
+}
+
+static ssize_t debug_output(struct file *file, char __user *user_buf,
+			size_t len, loff_t *offset)
+{
+	struct debug_buffer *buf = file->private_data;
+	int ret = 0;
+
+	mutex_lock(&buf->mutex);
+	if (buf->count == 0) {
+		ret = fill_buffer(buf);
+		if (ret != 0) {
+			mutex_unlock(&buf->mutex);
+			goto out;
+		}
+	}
+	mutex_unlock(&buf->mutex);
+
+	ret = simple_read_from_buffer(user_buf, len, offset,
+				      buf->page, buf->count);
+
+out:
+	return ret;
+
+}
+
+static int debug_close(struct inode *inode, struct file *file)
+{
+	struct debug_buffer *buf = file->private_data;
+
+	if (buf) {
+		if (buf->page)
+			free_page((unsigned long)buf->page);
+		kfree(buf);
+	}
+
+	return 0;
+}
+static int debug_async_open(struct inode *inode, struct file *file)
+{
+	file->private_data = alloc_buffer(inode->i_private, fill_async_buffer);
+
+	return file->private_data ? 0 : -ENOMEM;
+}
+
+static int debug_periodic_open(struct inode *inode, struct file *file)
+{
+	file->private_data = alloc_buffer(inode->i_private,
+					  fill_periodic_buffer);
+
+	return file->private_data ? 0 : -ENOMEM;
+}
+
+static int debug_registers_open(struct inode *inode, struct file *file)
+{
+	file->private_data = alloc_buffer(inode->i_private,
+					  fill_registers_buffer);
+
+	return file->private_data ? 0 : -ENOMEM;
+}
 static inline void create_debug_files (struct ohci_hcd *ohci)
 {
-	struct class_device *cldev = ohci_to_hcd(ohci)->self.class_dev;
-	int retval;
+	struct usb_bus *bus = &ohci_to_hcd(ohci)->self;
+	struct device *dev = bus->dev;
 
-	retval = class_device_create_file(cldev, &class_device_attr_async);
-	retval = class_device_create_file(cldev, &class_device_attr_periodic);
-	retval = class_device_create_file(cldev, &class_device_attr_registers);
+	ohci->debug_dir = debugfs_create_dir(bus->bus_name, ohci_debug_root);
+	if (!ohci->debug_dir)
+		goto dir_error;
+
+	ohci->debug_async = debugfs_create_file("async", S_IRUGO,
+						ohci->debug_dir, dev,
+						&debug_async_fops);
+	if (!ohci->debug_async)
+		goto async_error;
+
+	ohci->debug_periodic = debugfs_create_file("periodic", S_IRUGO,
+						   ohci->debug_dir, dev,
+						   &debug_periodic_fops);
+	if (!ohci->debug_periodic)
+		goto periodic_error;
+
+	ohci->debug_registers = debugfs_create_file("registers", S_IRUGO,
+						    ohci->debug_dir, dev,
+						    &debug_registers_fops);
+	if (!ohci->debug_registers)
+		goto registers_error;
+
 	ohci_dbg (ohci, "created debug files\n");
+	return;
+
+registers_error:
+	debugfs_remove(ohci->debug_periodic);
+periodic_error:
+	debugfs_remove(ohci->debug_async);
+async_error:
+	debugfs_remove(ohci->debug_dir);
+dir_error:
+	ohci->debug_periodic = NULL;
+	ohci->debug_async = NULL;
+	ohci->debug_dir = NULL;
 }
 
 static inline void remove_debug_files (struct ohci_hcd *ohci)
 {
-	struct class_device *cldev = ohci_to_hcd(ohci)->self.class_dev;
-
-	class_device_remove_file(cldev, &class_device_attr_async);
-	class_device_remove_file(cldev, &class_device_attr_periodic);
-	class_device_remove_file(cldev, &class_device_attr_registers);
+	debugfs_remove(ohci->debug_registers);
+	debugfs_remove(ohci->debug_periodic);
+	debugfs_remove(ohci->debug_async);
+	debugfs_remove(ohci->debug_dir);
 }
 
 #endif
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
index ddd4ee1..dd4798e 100644
--- a/drivers/usb/host/ohci-hcd.c
+++ b/drivers/usb/host/ohci-hcd.c
@@ -36,6 +36,7 @@
 #include <linux/dmapool.h>
 #include <linux/reboot.h>
 #include <linux/workqueue.h>
+#include <linux/debugfs.h>
 
 #include <asm/io.h>
 #include <asm/irq.h>
@@ -809,13 +810,9 @@
 	}
 
 	if (ints & OHCI_INTR_WDH) {
-		if (HC_IS_RUNNING(hcd->state))
-			ohci_writel (ohci, OHCI_INTR_WDH, &regs->intrdisable);
 		spin_lock (&ohci->lock);
 		dl_done_list (ohci);
 		spin_unlock (&ohci->lock);
-		if (HC_IS_RUNNING(hcd->state))
-			ohci_writel (ohci, OHCI_INTR_WDH, &regs->intrenable);
 	}
 
 	if (quirk_zfmicro(ohci) && (ints & OHCI_INTR_SF)) {
@@ -1032,6 +1029,13 @@
 #define PLATFORM_DRIVER		usb_hcd_pnx4008_driver
 #endif
 
+#if defined(CONFIG_CPU_SUBTYPE_SH7720) || \
+    defined(CONFIG_CPU_SUBTYPE_SH7721) || \
+    defined(CONFIG_CPU_SUBTYPE_SH7763)
+#include "ohci-sh.c"
+#define PLATFORM_DRIVER		ohci_hcd_sh_driver
+#endif
+
 
 #ifdef CONFIG_USB_OHCI_HCD_PPC_OF
 #include "ohci-ppc-of.c"
@@ -1048,6 +1052,11 @@
 #define SSB_OHCI_DRIVER		ssb_ohci_driver
 #endif
 
+#ifdef CONFIG_MFD_SM501
+#include "ohci-sm501.c"
+#define PLATFORM_DRIVER		ohci_hcd_sm501_driver
+#endif
+
 #if	!defined(PCI_DRIVER) &&		\
 	!defined(PLATFORM_DRIVER) &&	\
 	!defined(OF_PLATFORM_DRIVER) &&	\
@@ -1068,6 +1077,14 @@
 	pr_debug ("%s: block sizes: ed %Zd td %Zd\n", hcd_name,
 		sizeof (struct ed), sizeof (struct td));
 
+#ifdef DEBUG
+	ohci_debug_root = debugfs_create_dir("ohci", NULL);
+	if (!ohci_debug_root) {
+		retval = -ENOENT;
+		goto error_debug;
+	}
+#endif
+
 #ifdef PS3_SYSTEM_BUS_DRIVER
 	retval = ps3_ohci_driver_register(&PS3_SYSTEM_BUS_DRIVER);
 	if (retval < 0)
@@ -1130,6 +1147,12 @@
 	ps3_ohci_driver_unregister(&PS3_SYSTEM_BUS_DRIVER);
  error_ps3:
 #endif
+#ifdef DEBUG
+	debugfs_remove(ohci_debug_root);
+	ohci_debug_root = NULL;
+ error_debug:
+#endif
+
 	return retval;
 }
 module_init(ohci_hcd_mod_init);
@@ -1154,6 +1177,9 @@
 #ifdef PS3_SYSTEM_BUS_DRIVER
 	ps3_ohci_driver_unregister(&PS3_SYSTEM_BUS_DRIVER);
 #endif
+#ifdef DEBUG
+	debugfs_remove(ohci_debug_root);
+#endif
 }
 module_exit(ohci_hcd_mod_exit);
 
diff --git a/drivers/usb/host/ohci-sh.c b/drivers/usb/host/ohci-sh.c
new file mode 100644
index 0000000..5309ac0
--- /dev/null
+++ b/drivers/usb/host/ohci-sh.c
@@ -0,0 +1,143 @@
+/*
+ * OHCI HCD (Host Controller Driver) for USB.
+ *
+ * Copyright (C) 2008 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/platform_device.h>
+
+static int ohci_sh_start(struct usb_hcd *hcd)
+{
+	struct ohci_hcd	*ohci = hcd_to_ohci(hcd);
+
+	ohci_hcd_init(ohci);
+	ohci_init(ohci);
+	ohci_run(ohci);
+	hcd->state = HC_STATE_RUNNING;
+	return 0;
+}
+
+static const struct hc_driver ohci_sh_hc_driver = {
+	.description =		hcd_name,
+	.product_desc =		"SuperH OHCI",
+	.hcd_priv_size =	sizeof(struct ohci_hcd),
+
+	/*
+	 * generic hardware linkage
+	 */
+	.irq =			ohci_irq,
+	.flags =		HCD_USB11 | HCD_MEMORY,
+
+	/*
+	 * basic lifecycle operations
+	 */
+	.start =		ohci_sh_start,
+	.stop =			ohci_stop,
+	.shutdown =		ohci_shutdown,
+
+	/*
+	 * managing i/o requests and associated device resources
+	 */
+	.urb_enqueue =		ohci_urb_enqueue,
+	.urb_dequeue =		ohci_urb_dequeue,
+	.endpoint_disable =	ohci_endpoint_disable,
+
+	/*
+	 * scheduling support
+	 */
+	.get_frame_number =	ohci_get_frame,
+
+	/*
+	 * root hub support
+	 */
+	.hub_status_data =	ohci_hub_status_data,
+	.hub_control =		ohci_hub_control,
+	.hub_irq_enable =	ohci_rhsc_enable,
+#ifdef	CONFIG_PM
+	.bus_suspend =		ohci_bus_suspend,
+	.bus_resume =		ohci_bus_resume,
+#endif
+	.start_port_reset =	ohci_start_port_reset,
+};
+
+/*-------------------------------------------------------------------------*/
+
+#define resource_len(r) (((r)->end - (r)->start) + 1)
+static int ohci_hcd_sh_probe(struct platform_device *pdev)
+{
+	struct resource *res = NULL;
+	struct usb_hcd *hcd = NULL;
+	int irq = -1;
+	int ret;
+
+	if (usb_disabled())
+		return -ENODEV;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		err("platform_get_resource error.");
+		return -ENODEV;
+	}
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		err("platform_get_irq error.");
+		return -ENODEV;
+	}
+
+	/* initialize hcd */
+	hcd = usb_create_hcd(&ohci_sh_hc_driver, &pdev->dev, (char *)hcd_name);
+	if (!hcd) {
+		err("Failed to create hcd");
+		return -ENOMEM;
+	}
+
+	hcd->regs = (void __iomem *)res->start;
+	hcd->rsrc_start = res->start;
+	hcd->rsrc_len = resource_len(res);
+	ret = usb_add_hcd(hcd, irq, IRQF_DISABLED);
+	if (ret != 0) {
+		err("Failed to add hcd");
+		usb_put_hcd(hcd);
+		return ret;
+	}
+
+	return ret;
+}
+
+static int ohci_hcd_sh_remove(struct platform_device *pdev)
+{
+	struct usb_hcd *hcd = platform_get_drvdata(pdev);
+
+	usb_remove_hcd(hcd);
+	usb_put_hcd(hcd);
+
+	return 0;
+}
+
+static struct platform_driver ohci_hcd_sh_driver = {
+	.probe		= ohci_hcd_sh_probe,
+	.remove		= ohci_hcd_sh_remove,
+	.shutdown	= usb_hcd_platform_shutdown,
+	.driver		= {
+		.name	= "sh_ohci",
+		.owner	= THIS_MODULE,
+	},
+};
+
diff --git a/drivers/usb/host/ohci-sm501.c b/drivers/usb/host/ohci-sm501.c
new file mode 100644
index 0000000..a970701
--- /dev/null
+++ b/drivers/usb/host/ohci-sm501.c
@@ -0,0 +1,264 @@
+/*
+ * OHCI HCD (Host Controller Driver) for USB.
+ *
+ * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
+ * (C) Copyright 2000-2005 David Brownell
+ * (C) Copyright 2002 Hewlett-Packard Company
+ * (C) Copyright 2008 Magnus Damm
+ *
+ * SM501 Bus Glue - based on ohci-omap.c
+ *
+ * This file is licenced under the GPL.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/jiffies.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <linux/sm501.h>
+#include <linux/sm501-regs.h>
+
+static int ohci_sm501_init(struct usb_hcd *hcd)
+{
+	return ohci_init(hcd_to_ohci(hcd));
+}
+
+static int ohci_sm501_start(struct usb_hcd *hcd)
+{
+	struct device *dev = hcd->self.controller;
+	int ret;
+
+	ret = ohci_run(hcd_to_ohci(hcd));
+	if (ret < 0) {
+		dev_err(dev, "can't start %s", hcd->self.bus_name);
+		ohci_stop(hcd);
+	}
+
+	return ret;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static const struct hc_driver ohci_sm501_hc_driver = {
+	.description =		hcd_name,
+	.product_desc =		"SM501 OHCI",
+	.hcd_priv_size =	sizeof(struct ohci_hcd),
+
+	/*
+	 * generic hardware linkage
+	 */
+	.irq =			ohci_irq,
+	.flags =		HCD_USB11 | HCD_MEMORY | HCD_LOCAL_MEM,
+
+	/*
+	 * basic lifecycle operations
+	 */
+	.reset =		ohci_sm501_init,
+	.start =		ohci_sm501_start,
+	.stop =			ohci_stop,
+	.shutdown =		ohci_shutdown,
+
+	/*
+	 * managing i/o requests and associated device resources
+	 */
+	.urb_enqueue =		ohci_urb_enqueue,
+	.urb_dequeue =		ohci_urb_dequeue,
+	.endpoint_disable =	ohci_endpoint_disable,
+
+	/*
+	 * scheduling support
+	 */
+	.get_frame_number =	ohci_get_frame,
+
+	/*
+	 * root hub support
+	 */
+	.hub_status_data =	ohci_hub_status_data,
+	.hub_control =		ohci_hub_control,
+	.hub_irq_enable =	ohci_rhsc_enable,
+#ifdef	CONFIG_PM
+	.bus_suspend =		ohci_bus_suspend,
+	.bus_resume =		ohci_bus_resume,
+#endif
+	.start_port_reset =	ohci_start_port_reset,
+};
+
+/*-------------------------------------------------------------------------*/
+
+static int ohci_hcd_sm501_drv_probe(struct platform_device *pdev)
+{
+	const struct hc_driver *driver = &ohci_sm501_hc_driver;
+	struct device *dev = &pdev->dev;
+	struct resource	*res, *mem;
+	int retval, irq;
+	struct usb_hcd *hcd = 0;
+
+	irq = retval = platform_get_irq(pdev, 0);
+	if (retval < 0)
+		goto err0;
+
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	if (mem == NULL) {
+		dev_err(dev, "no resource definition for memory\n");
+		retval = -ENOENT;
+		goto err0;
+	}
+
+	if (!request_mem_region(mem->start, mem->end - mem->start + 1,
+				pdev->name)) {
+		dev_err(dev, "request_mem_region failed\n");
+		retval = -EBUSY;
+		goto err0;
+	}
+
+	/* The sm501 chip is equipped with local memory that may be used
+	 * by on-chip devices such as the video controller and the usb host.
+	 * This driver uses dma_declare_coherent_memory() to make sure
+	 * usb allocations with dma_alloc_coherent() allocate from
+	 * this local memory. The dma_handle returned by dma_alloc_coherent()
+	 * will be an offset starting from 0 for the first local memory byte.
+	 *
+	 * So as long as data is allocated using dma_alloc_coherent() all is
+	 * fine. This is however not always the case - buffers may be allocated
+	 * using kmalloc() - so the usb core needs to be told that it must copy
+	 * data into our local memory if the buffers happen to be placed in
+	 * regular memory. The HCD_LOCAL_MEM flag does just that.
+	 */
+
+	if (!dma_declare_coherent_memory(dev, mem->start,
+					 mem->start - mem->parent->start,
+					 (mem->end - mem->start) + 1,
+					 DMA_MEMORY_MAP |
+					 DMA_MEMORY_EXCLUSIVE)) {
+		dev_err(dev, "cannot declare coherent memory\n");
+		retval = -ENXIO;
+		goto err1;
+	}
+
+	/* allocate, reserve and remap resources for registers */
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (res == NULL) {
+		dev_err(dev, "no resource definition for registers\n");
+		retval = -ENOENT;
+		goto err2;
+	}
+
+	hcd = usb_create_hcd(driver, &pdev->dev, pdev->dev.bus_id);
+	if (!hcd) {
+		retval = -ENOMEM;
+		goto err2;
+	}
+
+	hcd->rsrc_start = res->start;
+	hcd->rsrc_len = res->end - res->start + 1;
+
+	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len,	pdev->name)) {
+		dev_err(dev, "request_mem_region failed\n");
+		retval = -EBUSY;
+		goto err3;
+	}
+
+	hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
+	if (hcd->regs == NULL) {
+		dev_err(dev, "cannot remap registers\n");
+		retval = -ENXIO;
+		goto err4;
+	}
+
+	ohci_hcd_init(hcd_to_ohci(hcd));
+
+	retval = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED);
+	if (retval)
+		goto err4;
+
+	/* enable power and unmask interrupts */
+
+	sm501_unit_power(dev->parent, SM501_GATE_USB_HOST, 1);
+	sm501_modify_reg(dev->parent, SM501_IRQ_MASK, 1 << 6, 0);
+
+	return 0;
+err4:
+	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+err3:
+	usb_put_hcd(hcd);
+err2:
+	dma_release_declared_memory(dev);
+err1:
+	release_mem_region(mem->start, mem->end - mem->start + 1);
+err0:
+	return retval;
+}
+
+static int ohci_hcd_sm501_drv_remove(struct platform_device *pdev)
+{
+	struct usb_hcd *hcd = platform_get_drvdata(pdev);
+	struct resource	*mem;
+
+	usb_remove_hcd(hcd);
+	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+	usb_put_hcd(hcd);
+	dma_release_declared_memory(&pdev->dev);
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	release_mem_region(mem->start, mem->end - mem->start + 1);
+
+	/* mask interrupts and disable power */
+
+	sm501_modify_reg(pdev->dev.parent, SM501_IRQ_MASK, 0, 1 << 6);
+	sm501_unit_power(pdev->dev.parent, SM501_GATE_USB_HOST, 0);
+
+	platform_set_drvdata(pdev, NULL);
+	return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+#ifdef CONFIG_PM
+static int ohci_sm501_suspend(struct platform_device *pdev, pm_message_t msg)
+{
+	struct device *dev = &pdev->dev;
+	struct ohci_hcd	*ohci = hcd_to_ohci(platform_get_drvdata(pdev));
+
+	if (time_before(jiffies, ohci->next_statechange))
+		msleep(5);
+	ohci->next_statechange = jiffies;
+
+	sm501_unit_power(dev->parent, SM501_GATE_USB_HOST, 0);
+	ohci_to_hcd(ohci)->state = HC_STATE_SUSPENDED;
+	dev->power.power_state = PMSG_SUSPEND;
+	return 0;
+}
+
+static int ohci_sm501_resume(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct ohci_hcd	*ohci = hcd_to_ohci(platform_get_drvdata(pdev));
+
+	if (time_before(jiffies, ohci->next_statechange))
+		msleep(5);
+	ohci->next_statechange = jiffies;
+
+	sm501_unit_power(dev->parent, SM501_GATE_USB_HOST, 1);
+	dev->power.power_state = PMSG_ON;
+	usb_hcd_resume_root_hub(platform_get_drvdata(pdev));
+	return 0;
+}
+#endif
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * Driver definition to register with the SM501 bus
+ */
+static struct platform_driver ohci_hcd_sm501_driver = {
+	.probe		= ohci_hcd_sm501_drv_probe,
+	.remove		= ohci_hcd_sm501_drv_remove,
+	.shutdown	= usb_hcd_platform_shutdown,
+#ifdef	CONFIG_PM
+	.suspend	= ohci_sm501_suspend,
+	.resume		= ohci_sm501_resume,
+#endif
+	.driver		= {
+		.owner	= THIS_MODULE,
+		.name	= "sm501-usb",
+	},
+};
diff --git a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h
index 47c5c66..dc544dd 100644
--- a/drivers/usb/host/ohci.h
+++ b/drivers/usb/host/ohci.h
@@ -408,6 +408,13 @@
 	unsigned		eds_scheduled;
 	struct ed		*ed_to_check;
 	unsigned		zf_delay;
+
+#ifdef DEBUG
+	struct dentry		*debug_dir;
+	struct dentry		*debug_async;
+	struct dentry		*debug_periodic;
+	struct dentry		*debug_registers;
+#endif
 };
 
 #ifdef CONFIG_PCI
diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c
index c225159..0ee694f 100644
--- a/drivers/usb/host/pci-quirks.c
+++ b/drivers/usb/host/pci-quirks.c
@@ -190,9 +190,8 @@
 			msleep(10);
 		}
 		if (wait_time <= 0)
-			printk(KERN_WARNING "%s %s: BIOS handoff "
-					"failed (BIOS bug ?) %08x\n",
-					pdev->dev.bus_id, "OHCI",
+			dev_warn(&pdev->dev, "OHCI: BIOS handoff failed"
+					" (BIOS bug?) %08x\n",
 					readl(base + OHCI_CONTROL));
 
 		/* reset controller, preserving RWC */
@@ -243,8 +242,7 @@
 		switch (cap & 0xff) {
 		case 1:			/* BIOS/SMM/... handoff support */
 			if ((cap & EHCI_USBLEGSUP_BIOS)) {
-				pr_debug("%s %s: BIOS handoff\n",
-						pdev->dev.bus_id, "EHCI");
+				dev_dbg(&pdev->dev, "EHCI: BIOS handoff\n");
 
 #if 0
 /* aleksey_gorelov@phoenix.com reports that some systems need SMI forced on,
@@ -285,9 +283,8 @@
 				/* well, possibly buggy BIOS... try to shut
 				 * it down, and hope nothing goes too wrong
 				 */
-				printk(KERN_WARNING "%s %s: BIOS handoff "
-						"failed (BIOS bug ?) %08x\n",
-					pdev->dev.bus_id, "EHCI", cap);
+				dev_warn(&pdev->dev, "EHCI: BIOS handoff failed"
+						" (BIOS bug?) %08x\n", cap);
 				pci_write_config_byte(pdev, offset + 2, 0);
 			}
 
@@ -306,17 +303,14 @@
 			cap = 0;
 			/* FALLTHROUGH */
 		default:
-			printk(KERN_WARNING "%s %s: unrecognized "
-					"capability %02x\n",
-					pdev->dev.bus_id, "EHCI",
-					cap & 0xff);
+			dev_warn(&pdev->dev, "EHCI: unrecognized capability "
+					"%02x\n", cap & 0xff);
 			break;
 		}
 		offset = (cap >> 8) & 0xff;
 	}
 	if (!count)
-		printk(KERN_DEBUG "%s %s: capability loop?\n",
-				pdev->dev.bus_id, "EHCI");
+		dev_printk(KERN_DEBUG, &pdev->dev, "EHCI: capability loop?\n");
 
 	/*
 	 * halt EHCI & disable its interrupts in any case
diff --git a/drivers/usb/host/r8a66597.h b/drivers/usb/host/r8a66597.h
index fe9ceb0..5738825 100644
--- a/drivers/usb/host/r8a66597.h
+++ b/drivers/usb/host/r8a66597.h
@@ -405,7 +405,7 @@
 
 struct r8a66597_pipe_info {
 	u16 pipenum;
-	u16 address;	/* R8A66597 HCD usb addres */
+	u16 address;	/* R8A66597 HCD usb address */
 	u16 epnum;
 	u16 maxpacket;
 	u16 type;
diff --git a/drivers/usb/image/mdc800.c b/drivers/usb/image/mdc800.c
index d1131a8..0fb114c 100644
--- a/drivers/usb/image/mdc800.c
+++ b/drivers/usb/image/mdc800.c
@@ -478,8 +478,6 @@
 				{
 					irq_interval=intf_desc->endpoint [j].desc.bInterval;
 				}
-
-				continue;
 			}
 		}
 		if (mdc800->endpoint[i] == -1)
diff --git a/drivers/usb/misc/cypress_cy7c63.c b/drivers/usb/misc/cypress_cy7c63.c
index d721380..9379404 100644
--- a/drivers/usb/misc/cypress_cy7c63.c
+++ b/drivers/usb/misc/cypress_cy7c63.c
@@ -1,7 +1,7 @@
 /*
 * cypress_cy7c63.c
 *
-* Copyright (c) 2006 Oliver Bock (o.bock@fh-wolfenbuettel.de)
+* Copyright (c) 2006-2007 Oliver Bock (bock@tfh-berlin.de)
 *
 *	This driver is based on the Cypress USB Driver by Marcus Maul
 *	(cyport) and the 2.0 version of Greg Kroah-Hartman's
@@ -21,6 +21,9 @@
 *	Supported functions:	Read/Write Ports
 *
 *
+*	For up-to-date information please visit:
+*	http://www.obock.de/kernel/cypress
+*
 *	This program is free software; 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.
@@ -31,7 +34,7 @@
 #include <linux/kernel.h>
 #include <linux/usb.h>
 
-#define DRIVER_AUTHOR		"Oliver Bock (o.bock@fh-wolfenbuettel.de)"
+#define DRIVER_AUTHOR		"Oliver Bock (bock@tfh-berlin.de)"
 #define DRIVER_DESC		"Cypress CY7C63xxx USB driver"
 
 #define CYPRESS_VENDOR_ID	0xa2c
diff --git a/drivers/usb/misc/iowarrior.c b/drivers/usb/misc/iowarrior.c
index 764696f..8010705 100644
--- a/drivers/usb/misc/iowarrior.c
+++ b/drivers/usb/misc/iowarrior.c
@@ -715,7 +715,7 @@
  * would use "struct net_driver" instead, and a serial
  * device would use "struct tty_driver".
  */
-static struct file_operations iowarrior_fops = {
+static const struct file_operations iowarrior_fops = {
 	.owner = THIS_MODULE,
 	.write = iowarrior_write,
 	.read = iowarrior_read,
diff --git a/drivers/usb/misc/legousbtower.c b/drivers/usb/misc/legousbtower.c
index aab3200..6664043f 100644
--- a/drivers/usb/misc/legousbtower.c
+++ b/drivers/usb/misc/legousbtower.c
@@ -205,7 +205,7 @@
 
 /* Structure to hold all of our device specific stuff */
 struct lego_usb_tower {
-	struct semaphore	sem;		/* locks this structure */
+	struct mutex		lock;		/* locks this structure */
 	struct usb_device*	udev;		/* save off the usb device pointer */
 	unsigned char		minor;		/* the starting minor number for this device */
 
@@ -361,7 +361,7 @@
 	}
 
 	/* lock this device */
-	if (down_interruptible (&dev->sem)) {
+	if (mutex_lock_interruptible(&dev->lock)) {
 		mutex_unlock(&open_disc_mutex);
 	        retval = -ERESTARTSYS;
 		goto exit;
@@ -421,7 +421,7 @@
 	file->private_data = dev;
 
 unlock_exit:
-	up (&dev->sem);
+	mutex_unlock(&dev->lock);
 
 exit:
 	dbg(2, "%s: leave, return value %d ", __FUNCTION__, retval);
@@ -448,7 +448,7 @@
 	}
 
 	mutex_lock(&open_disc_mutex);
-	if (down_interruptible (&dev->sem)) {
+	if (mutex_lock_interruptible(&dev->lock)) {
 	        retval = -ERESTARTSYS;
 		goto exit;
 	}
@@ -460,7 +460,9 @@
 	}
 	if (dev->udev == NULL) {
 		/* the device was unplugged before the file was released */
-		up (&dev->sem);	/* unlock here as tower_delete frees dev */
+
+		/* unlock here as tower_delete frees dev */
+		mutex_unlock(&dev->lock);
 		tower_delete (dev);
 		goto exit;
 	}
@@ -473,7 +475,7 @@
 	dev->open_count = 0;
 
 unlock_exit:
-	up (&dev->sem);
+	mutex_unlock(&dev->lock);
 
 exit:
 	mutex_unlock(&open_disc_mutex);
@@ -586,7 +588,7 @@
 	dev = (struct lego_usb_tower *)file->private_data;
 
 	/* lock this object */
-	if (down_interruptible (&dev->sem)) {
+	if (mutex_lock_interruptible(&dev->lock)) {
 		retval = -ERESTARTSYS;
 		goto exit;
 	}
@@ -653,7 +655,7 @@
 
 unlock_exit:
 	/* unlock the device */
-	up (&dev->sem);
+	mutex_unlock(&dev->lock);
 
 exit:
 	dbg(2, "%s: leave, return value %d", __FUNCTION__, retval);
@@ -675,7 +677,7 @@
 	dev = (struct lego_usb_tower *)file->private_data;
 
 	/* lock this object */
-	if (down_interruptible (&dev->sem)) {
+	if (mutex_lock_interruptible(&dev->lock)) {
 		retval = -ERESTARTSYS;
 		goto exit;
 	}
@@ -737,7 +739,7 @@
 
 unlock_exit:
 	/* unlock the device */
-	up (&dev->sem);
+	mutex_unlock(&dev->lock);
 
 exit:
 	dbg(2, "%s: leave, return value %d", __FUNCTION__, retval);
@@ -862,7 +864,7 @@
 		goto exit;
 	}
 
-	init_MUTEX (&dev->sem);
+	mutex_init(&dev->lock);
 
 	dev->udev = udev;
 	dev->open_count = 0;
@@ -1007,16 +1009,16 @@
 	/* give back our minor */
 	usb_deregister_dev (interface, &tower_class);
 
-	down (&dev->sem);
+	mutex_lock(&dev->lock);
 	mutex_unlock(&open_disc_mutex);
 
 	/* if the device is not opened, then we clean up right now */
 	if (!dev->open_count) {
-		up (&dev->sem);
+		mutex_unlock(&dev->lock);
 		tower_delete (dev);
 	} else {
 		dev->udev = NULL;
-		up (&dev->sem);
+		mutex_unlock(&dev->lock);
 	}
 
 	info("LEGO USB Tower #%d now disconnected", (minor - LEGO_USB_TOWER_MINOR_BASE));
diff --git a/drivers/usb/misc/sisusbvga/sisusb.c b/drivers/usb/misc/sisusbvga/sisusb.c
index 9244d06..cb7fa0e 100644
--- a/drivers/usb/misc/sisusbvga/sisusb.c
+++ b/drivers/usb/misc/sisusbvga/sisusb.c
@@ -323,7 +323,7 @@
 			usb_kill_urb(urb);
 			retval = -ETIMEDOUT;
 		} else {
-			/* URB completed within timout */
+			/* URB completed within timeout */
 			retval = urb->status;
 			readbytes = urb->actual_length;
 		}
@@ -3195,20 +3195,6 @@
 
 	sisusb->present = 1;
 
-#ifdef SISUSB_OLD_CONFIG_COMPAT
-	{
-	int ret;
-	/* Our ioctls are all "32/64bit compatible" */
-	ret =  register_ioctl32_conversion(SISUSB_GET_CONFIG_SIZE, NULL);
-	ret |= register_ioctl32_conversion(SISUSB_GET_CONFIG,      NULL);
-	ret |= register_ioctl32_conversion(SISUSB_COMMAND,         NULL);
-	if (ret)
-		dev_err(&sisusb->sisusb_dev->dev, "Error registering ioctl32 translations\n");
-	else
-		sisusb->ioctl32registered = 1;
-	}
-#endif
-
 	if (dev->speed == USB_SPEED_HIGH) {
 		int initscreen = 1;
 #ifdef INCL_SISUSB_CON
@@ -3271,19 +3257,6 @@
 
 	usb_set_intfdata(intf, NULL);
 
-#ifdef SISUSB_OLD_CONFIG_COMPAT
-	if (sisusb->ioctl32registered) {
-		int ret;
-		sisusb->ioctl32registered = 0;
-		ret =  unregister_ioctl32_conversion(SISUSB_GET_CONFIG_SIZE);
-		ret |= unregister_ioctl32_conversion(SISUSB_GET_CONFIG);
-		ret |= unregister_ioctl32_conversion(SISUSB_COMMAND);
-		if (ret) {
-			dev_err(&sisusb->sisusb_dev->dev, "Error unregistering ioctl32 translations\n");
-		}
-	}
-#endif
-
 	sisusb->present = 0;
 	sisusb->ready = 0;
 
diff --git a/drivers/usb/misc/sisusbvga/sisusb.h b/drivers/usb/misc/sisusbvga/sisusb.h
index d2d7872..cf0b4a5 100644
--- a/drivers/usb/misc/sisusbvga/sisusb.h
+++ b/drivers/usb/misc/sisusbvga/sisusb.h
@@ -120,9 +120,6 @@
 	int isopen;		/* !=0 if open */
 	int present;		/* !=0 if device is present on the bus */
 	int ready;		/* !=0 if device is ready for userland */
-#ifdef SISUSB_OLD_CONFIG_COMPAT
-	int ioctl32registered;
-#endif
 	int numobufs;		/* number of obufs = number of out urbs */
 	char *obuf[NUMOBUFS], *ibuf;	/* transfer buffers */
 	int obufsize, ibufsize;
diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c
index ea31621..da922df 100644
--- a/drivers/usb/misc/usbtest.c
+++ b/drivers/usb/misc/usbtest.c
@@ -6,6 +6,7 @@
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/scatterlist.h>
+#include <linux/mutex.h>
 
 #include <linux/usb.h>
 
@@ -64,7 +65,7 @@
 	int			in_iso_pipe;
 	int			out_iso_pipe;
 	struct usb_endpoint_descriptor	*iso_in, *iso_out;
-	struct semaphore	sem;
+	struct mutex		lock;
 
 #define TBUF_SIZE	256
 	u8			*buf;
@@ -1151,6 +1152,7 @@
 		dbg ("ep %02x couldn't get halt status, %d", ep, retval);
 		return retval;
 	}
+	le16_to_cpus(&status);
 	if (status != 1) {
 		dbg ("ep %02x bogus status: %04x != 1", ep, status);
 		return -EINVAL;
@@ -1310,7 +1312,7 @@
 		len += vary;
 
 		/* [real world] the "zero bytes IN" case isn't really used.
-		 * hardware can easily trip up in this wierd case, since its
+		 * hardware can easily trip up in this weird case, since its
 		 * status stage is IN, not OUT like other ep0in transfers.
 		 */
 		if (len > length)
@@ -1558,11 +1560,11 @@
 			|| param->sglen < 0 || param->vary < 0)
 		return -EINVAL;
 
-	if (down_interruptible (&dev->sem))
+	if (mutex_lock_interruptible(&dev->lock))
 		return -ERESTARTSYS;
 
 	if (intf->dev.power.power_state.event != PM_EVENT_ON) {
-		up (&dev->sem);
+		mutex_unlock(&dev->lock);
 		return -EHOSTUNREACH;
 	}
 
@@ -1574,7 +1576,7 @@
 	    	int	res;
 
 		if (intf->altsetting->desc.bInterfaceNumber) {
-			up (&dev->sem);
+			mutex_unlock(&dev->lock);
 			return -ENODEV;
 		}
 		res = set_altsetting (dev, dev->info->alt);
@@ -1582,7 +1584,7 @@
 			dev_err (&intf->dev,
 					"set altsetting to %d failed, %d\n",
 					dev->info->alt, res);
-			up (&dev->sem);
+			mutex_unlock(&dev->lock);
 			return res;
 		}
 	}
@@ -1855,7 +1857,7 @@
 		param->duration.tv_usec += 1000 * 1000;
 		param->duration.tv_sec -= 1;
 	}
-	up (&dev->sem);
+	mutex_unlock(&dev->lock);
 	return retval;
 }
 
@@ -1905,7 +1907,7 @@
 		return -ENOMEM;
 	info = (struct usbtest_info *) id->driver_info;
 	dev->info = info;
-	init_MUTEX (&dev->sem);
+	mutex_init(&dev->lock);
 
 	dev->intf = intf;
 
@@ -1990,8 +1992,6 @@
 {
 	struct usbtest_dev	*dev = usb_get_intfdata (intf);
 
-	down (&dev->sem);
-
 	usb_set_intfdata (intf, NULL);
 	dev_dbg (&intf->dev, "disconnect\n");
 	kfree (dev);
diff --git a/drivers/usb/mon/mon_bin.c b/drivers/usb/mon/mon_bin.c
index f06e4e2..1774ba5 100644
--- a/drivers/usb/mon/mon_bin.c
+++ b/drivers/usb/mon/mon_bin.c
@@ -1026,6 +1026,8 @@
 	return mask;
 }
 
+#if 0
+
 /*
  * open and close: just keep track of how many times the device is
  * mapped, to use the proper memory allocation function.
@@ -1045,33 +1047,31 @@
 /*
  * Map ring pages to user space.
  */
-struct page *mon_bin_vma_nopage(struct vm_area_struct *vma,
-                                unsigned long address, int *type)
+static int mon_bin_vma_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 {
 	struct mon_reader_bin *rp = vma->vm_private_data;
 	unsigned long offset, chunk_idx;
 	struct page *pageptr;
 
-	offset = (address - vma->vm_start) + (vma->vm_pgoff << PAGE_SHIFT);
+	offset = vmf->pgoff << PAGE_SHIFT;
 	if (offset >= rp->b_size)
-		return NOPAGE_SIGBUS;
+		return VM_FAULT_SIGBUS;
 	chunk_idx = offset / CHUNK_SIZE;
 	pageptr = rp->b_vec[chunk_idx].pg;
 	get_page(pageptr);
-	if (type)
-		*type = VM_FAULT_MINOR;
-	return pageptr;
+	vmf->page = pageptr;
+	return 0;
 }
 
 struct vm_operations_struct mon_bin_vm_ops = {
 	.open =     mon_bin_vma_open,
 	.close =    mon_bin_vma_close,
-	.nopage =   mon_bin_vma_nopage,
+	.fault =    mon_bin_vma_fault,
 };
 
 int mon_bin_mmap(struct file *filp, struct vm_area_struct *vma)
 {
-	/* don't do anything here: "nopage" will set up page table entries */
+	/* don't do anything here: "fault" will set up page table entries */
 	vma->vm_ops = &mon_bin_vm_ops;
 	vma->vm_flags |= VM_RESERVED;
 	vma->vm_private_data = filp->private_data;
@@ -1079,7 +1079,9 @@
 	return 0;
 }
 
-struct file_operations mon_fops_binary = {
+#endif  /*  0  */
+
+static const struct file_operations mon_fops_binary = {
 	.owner =	THIS_MODULE,
 	.open =		mon_bin_open,
 	.llseek =	no_llseek,
diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig
index 4a86696..c1e65df 100644
--- a/drivers/usb/serial/Kconfig
+++ b/drivers/usb/serial/Kconfig
@@ -2,10 +2,7 @@
 # USB Serial device configuration
 #
 
-menu "USB Serial Converter support"
-	depends on USB!=n
-
-config USB_SERIAL
+menuconfig USB_SERIAL
 	tristate "USB Serial Converter support"
 	depends on USB
 	---help---
@@ -20,6 +17,8 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called usbserial.
 
+if USB_SERIAL
+
 config USB_SERIAL_CONSOLE
 	bool "USB Serial Console device support (EXPERIMENTAL)"
 	depends on USB_SERIAL=y && EXPERIMENTAL
@@ -43,6 +42,12 @@
 
 	  If unsure, say N.
 
+config USB_EZUSB
+	bool "Functions for loading firmware on EZUSB chips"
+	depends on USB_SERIAL
+	help
+	    Say Y here if you need EZUSB device support.
+
 config USB_SERIAL_GENERIC
 	bool "USB Generic Serial Driver"
 	depends on USB_SERIAL
@@ -105,6 +110,7 @@
 config USB_SERIAL_WHITEHEAT
 	tristate "USB ConnectTech WhiteHEAT Serial Driver"
 	depends on USB_SERIAL
+	select USB_EZUSB
 	help
 	  Say Y here if you want to use a ConnectTech WhiteHEAT 4 port
 	  USB to serial converter device.
@@ -282,9 +288,21 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called ipw.
 
+config USB_SERIAL_IUU
+	tristate "USB Infinity USB Unlimited Phoenix Driver (Experimental)"
+	depends on USB_SERIAL && EXPERIMENTAL
+	help
+	  Say Y here if you want to use a IUU in phoenix mode and get
+	  an extra ttyUSBx device. More information available on
+	  http://eczema.ecze.com/iuu_phoenix.html
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called iuu_phoenix.o
+
 config USB_SERIAL_KEYSPAN_PDA
 	tristate "USB Keyspan PDA Single Port Serial Driver"
 	depends on USB_SERIAL
+	select USB_EZUSB
 	help
 	  Say Y here if you want to use a Keyspan PDA single port USB to
 	  serial converter device.  This driver makes use of firmware
@@ -296,6 +314,7 @@
 config USB_SERIAL_KEYSPAN
 	tristate "USB Keyspan USA-xxx Serial Driver"
 	depends on USB_SERIAL
+	select USB_EZUSB
 	---help---
 	  Say Y here if you want to use Keyspan USB to serial converter
 	  devices.  This driver makes use of Keyspan's official firmware
@@ -538,6 +557,7 @@
 config USB_SERIAL_XIRCOM
 	tristate "USB Xircom / Entregra Single Port Serial Driver"
 	depends on USB_SERIAL
+	select USB_EZUSB
 	help
 	  Say Y here if you want to use a Xircom or Entregra single port USB to
 	  serial converter device.  This driver makes use of firmware
@@ -585,11 +605,4 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called usb-debug.
 
-config USB_EZUSB
-	bool
-	depends on USB_SERIAL_KEYSPAN_PDA || USB_SERIAL_XIRCOM || USB_SERIAL_KEYSPAN || USB_SERIAL_WHITEHEAT
-	default y
-
-
-endmenu
-
+endif # USB_SERIAL
diff --git a/drivers/usb/serial/Makefile b/drivers/usb/serial/Makefile
index d6fb384..0db109a 100644
--- a/drivers/usb/serial/Makefile
+++ b/drivers/usb/serial/Makefile
@@ -30,6 +30,7 @@
 obj-$(CONFIG_USB_SERIAL_HP4X)			+= hp4x.o
 obj-$(CONFIG_USB_SERIAL_IPAQ)			+= ipaq.o
 obj-$(CONFIG_USB_SERIAL_IPW)			+= ipw.o
+obj-$(CONFIG_USB_SERIAL_IUU)			+= iuu_phoenix.o
 obj-$(CONFIG_USB_SERIAL_IR)			+= ir-usb.o
 obj-$(CONFIG_USB_SERIAL_KEYSPAN)		+= keyspan.o
 obj-$(CONFIG_USB_SERIAL_KEYSPAN_PDA)		+= keyspan_pda.o
diff --git a/drivers/usb/serial/airprime.c b/drivers/usb/serial/airprime.c
index 77bb893..f156dba 100644
--- a/drivers/usb/serial/airprime.c
+++ b/drivers/usb/serial/airprime.c
@@ -217,7 +217,10 @@
 	priv->rts_state = 0;
 	priv->dtr_state = 0;
 
-	airprime_send_setup(port);
+	mutex_lock(&port->serial->disc_mutex);
+	if (!port->serial->disconnected)
+		airprime_send_setup(port);
+	mutex_lock(&port->serial->disc_mutex);
 
 	for (i = 0; i < NUM_READ_URBS; ++i) {
 		usb_kill_urb (priv->read_urbp[i]);
diff --git a/drivers/usb/serial/ark3116.c b/drivers/usb/serial/ark3116.c
index ddfee91..fe2bfd6 100644
--- a/drivers/usb/serial/ark3116.c
+++ b/drivers/usb/serial/ark3116.c
@@ -151,8 +151,10 @@
 	return 0;
 
 cleanup:
-	for (--i; i >= 0; --i)
+	for (--i; i >= 0; --i) {
+		kfree(usb_get_serial_port_data(serial->port[i]));
 		usb_set_serial_port_data(serial->port[i], NULL);
+	}
 	return -ENOMEM;
 }
 
diff --git a/drivers/usb/serial/belkin_sa.c b/drivers/usb/serial/belkin_sa.c
index 86724e8..df0a2b3 100644
--- a/drivers/usb/serial/belkin_sa.c
+++ b/drivers/usb/serial/belkin_sa.c
@@ -350,14 +350,12 @@
 	unsigned long control_state;
 	int bad_flow_control;
 	speed_t baud;
+	struct ktermios *termios = port->tty->termios;
 	
-	if ((!port->tty) || (!port->tty->termios)) {
-		dbg ("%s - no tty or termios structure", __FUNCTION__);
-		return;
-	}
+	iflag = termios->c_iflag;
+	cflag = termios->c_cflag;
 
-	iflag = port->tty->termios->c_iflag;
-	cflag = port->tty->termios->c_cflag;
+	termios->c_cflag &= ~CMSPAR;
 
 	/* get a local copy of the current port settings */
 	spin_lock_irqsave(&priv->lock, flags);
@@ -369,33 +367,30 @@
 	old_cflag = old_termios->c_cflag;
 
 	/* Set the baud rate */
-	if( (cflag&CBAUD) != (old_cflag&CBAUD) ) {
+	if ((cflag & CBAUD) != (old_cflag & CBAUD)) {
 		/* reassert DTR and (maybe) RTS on transition from B0 */
 		if( (old_cflag&CBAUD) == B0 ) {
 			control_state |= (TIOCM_DTR|TIOCM_RTS);
 			if (BSA_USB_CMD(BELKIN_SA_SET_DTR_REQUEST, 1) < 0)
 				err("Set DTR error");
 			/* don't set RTS if using hardware flow control */
-			if (!(old_cflag&CRTSCTS) )
+			if (!(old_cflag & CRTSCTS))
 				if (BSA_USB_CMD(BELKIN_SA_SET_RTS_REQUEST, 1) < 0)
 					err("Set RTS error");
 		}
 	}
 
 	baud = tty_get_baud_rate(port->tty);
-	if (baud == 0) {
-		dbg("%s - tty_get_baud_rate says 0 baud", __FUNCTION__);
-		return;
-	}
-	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 */
+	if (baud) {
+		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);
 
-	if ((cflag & CBAUD) != B0 ) {
+		/* Report the actual baud rate back to the caller */
+		tty_encode_baud_rate(port->tty, baud, baud);
 		if (BSA_USB_CMD(BELKIN_SA_SET_BAUDRATE_REQUEST, urb_value) < 0)
 			err("Set baudrate error");
 	} else {
diff --git a/drivers/usb/serial/console.c b/drivers/usb/serial/console.c
index 0362654..66ce30c 100644
--- a/drivers/usb/serial/console.c
+++ b/drivers/usb/serial/console.c
@@ -64,8 +64,8 @@
 	struct usb_serial *serial;
 	struct usb_serial_port *port;
 	int retval = 0;
-	struct tty_struct *tty;
-	struct ktermios *termios;
+	struct tty_struct *tty = NULL;
+	struct ktermios *termios = NULL, dummy;
 
 	dbg ("%s", __FUNCTION__);
 
@@ -133,11 +133,14 @@
 	}
 	co->cflag = cflag;
 
-	/* grab the first serial port that happens to be connected */
-	serial = usb_serial_get_by_index(0);
+	/*
+	 * no need to check the index here: if the index is wrong, console
+	 * code won't call us
+	 */
+	serial = usb_serial_get_by_index(co->index);
 	if (serial == NULL) {
 		/* no device is connected yet, sorry :( */
-		err ("No USB device connected to ttyUSB0");
+		err ("No USB device connected to ttyUSB%i", co->index);
 		return -ENODEV;
 	}
 
@@ -148,49 +151,64 @@
 	 
 	++port->open_count;
 	if (port->open_count == 1) {
+		if (serial->type->set_termios) {
+			/*
+			 * allocate a fake tty so the driver can initialize
+			 * the termios structure, then later call set_termios to
+			 * configure according to command line arguments
+			 */
+			tty = kzalloc(sizeof(*tty), GFP_KERNEL);
+			if (!tty) {
+				retval = -ENOMEM;
+				err("no more memory");
+				goto reset_open_count;
+			}
+			termios = kzalloc(sizeof(*termios), GFP_KERNEL);
+			if (!termios) {
+				retval = -ENOMEM;
+				err("no more memory");
+				goto free_tty;
+			}
+			memset(&dummy, 0, sizeof(struct ktermios));
+			tty->termios = termios;
+			port->tty = tty;
+		}
+
 		/* only call the device specific open if this 
 		 * is the first time the port is opened */
 		if (serial->type->open)
 			retval = serial->type->open(port, NULL);
 		else
 			retval = usb_serial_generic_open(port, NULL);
-		if (retval)
-			port->open_count = 0;
-	}
 
-	if (retval) {
-		err ("could not open USB console port");
-		return retval;
-	}
-
-	if (serial->type->set_termios) {
-		struct ktermios dummy;
-		/* build up a fake tty structure so that the open call has something
-		 * to look at to get the cflag value */
-		tty = kzalloc(sizeof(*tty), GFP_KERNEL);
-		if (!tty) {
-			err ("no more memory");
-			return -ENOMEM;
+		if (retval) {
+			err("could not open USB console port");
+			goto free_termios;
 		}
-		termios = kzalloc(sizeof(*termios), GFP_KERNEL);
-		if (!termios) {
-			err ("no more memory");
-			kfree (tty);
-			return -ENOMEM;
-		}
-		memset(&dummy, 0, sizeof(struct ktermios));
-		termios->c_cflag = cflag;
-		tty->termios = termios;
-		port->tty = tty;
 
-		/* set up the initial termios settings */
-		serial->type->set_termios(port, &dummy);
-		port->tty = NULL;
-		kfree (termios);
-		kfree (tty);
+		if (serial->type->set_termios) {
+			termios->c_cflag = cflag;
+			serial->type->set_termios(port, &dummy);
+
+			port->tty = NULL;
+			kfree(termios);
+			kfree(tty);
+		}
 	}
 
+	port->console = 1;
+	retval = 0;
+
+out:
 	return retval;
+free_termios:
+	kfree(termios);
+	port->tty = NULL;
+free_tty:
+	kfree(tty);
+reset_open_count:
+	port->open_count = 0;
+goto out;
 }
 
 static void usb_console_write(struct console *co, const char *buf, unsigned count)
diff --git a/drivers/usb/serial/cp2101.c b/drivers/usb/serial/cp2101.c
index 2283358..f3ca660 100644
--- a/drivers/usb/serial/cp2101.c
+++ b/drivers/usb/serial/cp2101.c
@@ -59,6 +59,7 @@
 	{ USB_DEVICE(0x10A6, 0xAA26) }, /* Knock-off DCU-11 cable */
 	{ USB_DEVICE(0x10AB, 0x10C5) }, /* Siemens MC60 Cable */
 	{ USB_DEVICE(0x10B5, 0xAC70) }, /* Nokia CA-42 USB */
+	{ USB_DEVICE(0x10C4, 0x800A) }, /* SPORTident BSM7-D-USB main station */
 	{ USB_DEVICE(0x10C4, 0x803B) }, /* Pololu USB-serial converter */
 	{ USB_DEVICE(0x10C4, 0x8053) }, /* Enfora EDG1228 */
 	{ USB_DEVICE(0x10C4, 0x8066) }, /* Argussoft In-System Programmer */
@@ -76,8 +77,13 @@
 	{ USB_DEVICE(0x10C4, 0x8218) }, /* Lipowsky Industrie Elektronik GmbH, HARP-1 */
 	{ USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */
 	{ USB_DEVICE(0x10C4, 0xEA61) }, /* Silicon Labs factory default */
+	{ USB_DEVICE(0x10C4, 0xF001) }, /* Elan Digital Systems USBscope50 */
+	{ USB_DEVICE(0x10C4, 0xF002) }, /* Elan Digital Systems USBwave12 */
+	{ USB_DEVICE(0x10C4, 0xF003) }, /* Elan Digital Systems USBpulse100 */
+	{ USB_DEVICE(0x10C4, 0xF004) }, /* Elan Digital Systems USBcount50 */
 	{ USB_DEVICE(0x10C5, 0xEA61) }, /* Silicon Labs MobiData GPRS USB Modem */
 	{ USB_DEVICE(0x13AD, 0x9999) }, /* Baltech card reader */
+	{ USB_DEVICE(0x166A, 0x0303) }, /* Clipsal 5500PCU C-Bus USB interface */
 	{ USB_DEVICE(0x16D6, 0x0001) }, /* Jablotron serial interface */
 	{ } /* Terminating Entry */
 };
@@ -342,7 +348,10 @@
 	usb_kill_urb(port->write_urb);
 	usb_kill_urb(port->read_urb);
 
-	cp2101_set_config_single(port, CP2101_UART, UART_DISABLE);
+	mutex_lock(&port->serial->disc_mutex);
+	if (!port->serial->disconnected)
+		cp2101_set_config_single(port, CP2101_UART, UART_DISABLE);
+	mutex_unlock(&port->serial->disc_mutex);
 }
 
 /*
diff --git a/drivers/usb/serial/cyberjack.c b/drivers/usb/serial/cyberjack.c
index 4353df9..8d9b045 100644
--- a/drivers/usb/serial/cyberjack.c
+++ b/drivers/usb/serial/cyberjack.c
@@ -319,7 +319,6 @@
 	/* React only to interrupts signaling a bulk_in transfer */
 	if( (urb->actual_length==4) && (data[0]==0x01) ) {
 		short old_rdtodo;
-		int result;
 
 		/* This is a announcement of coming bulk_ins. */
 		unsigned short size = ((unsigned short)data[3]<<8)+data[2]+3;
diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c
index 1633863..08c65c1 100644
--- a/drivers/usb/serial/cypress_m8.c
+++ b/drivers/usb/serial/cypress_m8.c
@@ -682,7 +682,6 @@
 {
 	struct cypress_private *priv = usb_get_serial_port_data(port);
 	unsigned int c_cflag;
-	unsigned long flags;
 	int bps;
 	long timeout;
 	wait_queue_t wait;
@@ -690,7 +689,7 @@
 	dbg("%s - port %d", __FUNCTION__, port->number);
 
 	/* wait for data to drain from buffer */
-	spin_lock_irqsave(&priv->lock, flags);
+	spin_lock_irq(&priv->lock);
 	timeout = CYPRESS_CLOSING_WAIT;
 	init_waitqueue_entry(&wait, current);
 	add_wait_queue(&port->tty->write_wait, &wait);
@@ -698,18 +697,25 @@
 		set_current_state(TASK_INTERRUPTIBLE);
 		if (cypress_buf_data_avail(priv->buf) == 0
 		|| timeout == 0 || signal_pending(current)
-		|| !usb_get_intfdata(port->serial->interface))
+		/* without mutex, allowed due to harmless failure mode */
+		|| port->serial->disconnected)
 			break;
-		spin_unlock_irqrestore(&priv->lock, flags);
+		spin_unlock_irq(&priv->lock);
 		timeout = schedule_timeout(timeout);
-		spin_lock_irqsave(&priv->lock, flags);
+		spin_lock_irq(&priv->lock);
 	}
 	set_current_state(TASK_RUNNING);
 	remove_wait_queue(&port->tty->write_wait, &wait);
 	/* clear out any remaining data in the buffer */
 	cypress_buf_clear(priv->buf);
-	spin_unlock_irqrestore(&priv->lock, flags);
-	
+	spin_unlock_irq(&priv->lock);
+
+	/* writing is potentially harmful, lock must be taken */
+	mutex_lock(&port->serial->disc_mutex);
+	if (port->serial->disconnected) {
+		mutex_unlock(&port->serial->disc_mutex);
+		return;
+	}
 	/* wait for characters to drain from device */
 	bps = tty_get_baud_rate(port->tty);
 	if (bps > 1200)
@@ -727,10 +733,10 @@
 		if (c_cflag & HUPCL) {
 			/* drop dtr and rts */
 			priv = usb_get_serial_port_data(port);
-			spin_lock_irqsave(&priv->lock, flags);
+			spin_lock_irq(&priv->lock);
 			priv->line_control = 0;
 			priv->cmd_ctrl = 1;
-			spin_unlock_irqrestore(&priv->lock, flags);
+			spin_unlock_irq(&priv->lock);
 			cypress_write(port, NULL, 0);
 		}
 	}
@@ -738,6 +744,7 @@
 	if (stats)
 		dev_info (&port->dev, "Statistics: %d Bytes In | %d Bytes Out | %d Commands Issued\n",
 		          priv->bytes_in, priv->bytes_out, priv->cmd_count);
+	mutex_unlock(&port->serial->disc_mutex);
 } /* cypress_close */
 
 
diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c
index ae410c4..5f9c6e4 100644
--- a/drivers/usb/serial/digi_acceleport.c
+++ b/drivers/usb/serial/digi_acceleport.c
@@ -1405,19 +1405,19 @@
 	unsigned char buf[32];
 	struct tty_struct *tty = port->tty;
 	struct digi_port *priv = usb_get_serial_port_data(port);
-	unsigned long flags = 0;
 
 	dbg("digi_close: TOP: port=%d, open_count=%d",
 		priv->dp_port_num, port->open_count);
 
+	mutex_lock(&port->serial->disc_mutex);
 	/* if disconnected, just clear flags */
-	if (!usb_get_intfdata(port->serial->interface))
+	if (port->serial->disconnected)
 		goto exit;
 
 	/* do cleanup only after final close on this port */
-	spin_lock_irqsave(&priv->dp_port_lock, flags);
+	spin_lock_irq(&priv->dp_port_lock);
 	priv->dp_in_close = 1;
-	spin_unlock_irqrestore(&priv->dp_port_lock, flags);
+	spin_unlock_irq(&priv->dp_port_lock);
 
 	/* tell line discipline to process only XON/XOFF */
 	tty->closing = 1;
@@ -1482,11 +1482,12 @@
 	}
 	tty->closing = 0;
 exit:
-	spin_lock_irqsave(&priv->dp_port_lock, flags);
+	spin_lock_irq(&priv->dp_port_lock);
 	priv->dp_write_urb_in_use = 0;
 	priv->dp_in_close = 0;
 	wake_up_interruptible(&priv->dp_close_wait);
-	spin_unlock_irqrestore(&priv->dp_port_lock, flags);
+	spin_unlock_irq(&priv->dp_port_lock);
+	mutex_unlock(&port->serial->disc_mutex);
 	dbg("digi_close: done");
 }
 
diff --git a/drivers/usb/serial/ezusb.c b/drivers/usb/serial/ezusb.c
index 97ee718..3f698ba 100644
--- a/drivers/usb/serial/ezusb.c
+++ b/drivers/usb/serial/ezusb.c
@@ -53,6 +53,6 @@
 }
 
 
-EXPORT_SYMBOL(ezusb_writememory);
-EXPORT_SYMBOL(ezusb_set_reset);
+EXPORT_SYMBOL_GPL(ezusb_writememory);
+EXPORT_SYMBOL_GPL(ezusb_set_reset);
 
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index c40e77d..90dcc62 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -17,226 +17,8 @@
  * See http://ftdi-usb-sio.sourceforge.net for upto date testing info
  *	and extra documentation
  *
- * (21/Jul/2004) Ian Abbott
- *      Incorporated Steven Turner's code to add support for the FT2232C chip.
- *      The prelimilary port to the 2.6 kernel was by Rus V. Brushkoff.  I have
- *      fixed a couple of things.
- *
- * (27/May/2004) Ian Abbott
- *      Improved throttling code, mostly stolen from the WhiteHEAT driver.
- *
- * (26/Mar/2004) Jan Capek
- *      Added PID's for ICD-U20/ICD-U40 - incircuit PIC debuggers from CCS Inc.
- *
- * (09/Feb/2004) Ian Abbott
- *      Changed full name of USB-UIRT device to avoid "/" character.
- *      Added FTDI's alternate PID (0x6006) for FT232/245 devices.
- *      Added PID for "ELV USB Module UO100" from Stefan Frings.
- *
- * (21/Oct/2003) Ian Abbott
- *      Renamed some VID/PID macros for Matrix Orbital and Perle Systems
- *      devices.  Removed Matrix Orbital and Perle Systems devices from the
- *      8U232AM device table, but left them in the FT232BM table, as they are
- *      known to use only FT232BM.
- *
- * (17/Oct/2003) Scott Allen
- *      Added vid/pid for Perle Systems UltraPort USB serial converters
- *
- * (21/Sep/2003) Ian Abbott
- *      Added VID/PID for Omnidirectional Control Technology US101 USB to
- *      RS-232 adapter (also rebadged as Dick Smith Electronics XH6381).
- *      VID/PID supplied by Donald Gordon.
- *
- * (19/Aug/2003) Ian Abbott
- *      Freed urb's transfer buffer in write bulk callback.
- *      Omitted some paranoid checks in write bulk callback that don't matter.
- *      Scheduled work in write bulk callback regardless of port's open count.
- *
- * (05/Aug/2003) Ian Abbott
- *      Added VID/PID for ID TECH IDT1221U USB to RS-232 adapter.
- *      VID/PID provided by Steve Briggs.
- *
- * (23/Jul/2003) Ian Abbott
- *      Added PIDs for CrystalFontz 547, 633, 631, 635, 640 and 640 from
- *      Wayne Wylupski.
- *
- * (10/Jul/2003) David Glance
- *      Added PID for DSS-20 SyncStation cradle for Sony-Ericsson P800.
- *
- * (27/Jun/2003) Ian Abbott
- *	Reworked the urb handling logic.  We have no more pool, but dynamically
- *	allocate the urb and the transfer buffer on the fly.  In testing this
- *	does not incure any measurable overhead.  This also relies on the fact
- *	that we have proper reference counting logic for urbs.  I nicked this
- *	from Greg KH's Visor driver.
- *
- * (23/Jun/2003) Ian Abbott
- *      Reduced flip buffer pushes and corrected a data length test in
- *      ftdi_read_bulk_callback.
- *      Defererence pointers after any paranoid checks, not before.
- *
- * (21/Jun/2003) Erik Nygren
- *      Added support for Home Electronics Tira-1 IR transceiver using FT232BM chip.
- *      See <http://www.home-electro.com/tira1.htm>.  Only operates properly
- *      at 100000 and RTS-CTS, so set custom divisor mode on startup.
- *      Also force the Tira-1 and USB-UIRT to only use their custom baud rates.
- *
- * (18/Jun/2003) Ian Abbott
- *      Added Device ID of the USB relais from Rudolf Gugler (backported from
- *      Philipp Gühring's patch for 2.5.x kernel).
- *      Moved read transfer buffer reallocation into startup function.
- *      Free existing write urb and transfer buffer in startup function.
- *      Only use urbs in write urb pool that were successfully allocated.
- *      Moved some constant macros out of functions.
- *      Minor whitespace and comment changes.
- *
- * (12/Jun/2003) David Norwood
- *      Added support for USB-UIRT IR transceiver using 8U232AM chip.
- *      See <http://home.earthlink.net/~jrhees/USBUIRT/index.htm>.  Only
- *      operates properly at 312500, so set custom divisor mode on startup.
- *
- * (12/Jun/2003) Ian Abbott
- *      Added Sealevel SeaLINK+ 210x, 220x, 240x, 280x vid/pids from Tuan Hoang
- *      - I've eliminated some that don't seem to exist!
- *      Added Home Electronics Tira-1 IR transceiver pid from Chris Horn
- *      Some whitespace/coding-style cleanups
- *
- * (11/Jun/2003) Ian Abbott
- *      Fixed unsafe spinlock usage in ftdi_write
- *
- * (24/Feb/2003) Richard Shooter
- *      Increase read buffer size to improve read speeds at higher baud rates
- *      (specifically tested with up to 1Mb/sec at 1.5M baud)
- *
- * (23/Feb/2003) John Wilkins
- *      Added Xon/xoff flow control (activating support in the ftdi device)
- *      Added vid/pid for Videonetworks/Homechoice (UK ISP)
- *
- * (23/Feb/2003) Bill Ryder
- *      Added matrix orb device vid/pids from Wayne Wylupski
- *
- * (19/Feb/2003) Ian Abbott
- *      For TIOCSSERIAL, set alt_speed to 0 when ASYNC_SPD_MASK value has
- *      changed to something other than ASYNC_SPD_HI, ASYNC_SPD_VHI,
- *      ASYNC_SPD_SHI or ASYNC_SPD_WARP.  Also, unless ASYNC_SPD_CUST is in
- *      force, don't bother changing baud rate when custom_divisor has changed.
- *
- * (18/Feb/2003) Ian Abbott
- *      Fixed TIOCMGET handling to include state of DTR and RTS, the state
- *      of which are now saved by set_dtr() and set_rts().
- *      Fixed improper storage class for buf in set_dtr() and set_rts().
- *      Added FT232BM chip type and support for its extra baud rates (compared
- *      to FT8U232AM).
- *      Took account of special case divisor values for highest baud rates of
- *      FT8U232AM and FT232BM.
- *      For TIOCSSERIAL, forced alt_speed to 0 when ASYNC_SPD_CUST kludge used,
- *      as previous alt_speed setting is now stale.
- *      Moved startup code common between the startup routines for the
- *      different chip types into a common subroutine.
- *
- * (17/Feb/2003) Bill Ryder
- *      Added write urb buffer pool on a per device basis
- *      Added more checking for open file on callbacks (fixed OOPS)
- *      Added CrystalFontz 632 and 634 PIDs
- *         (thanx to CrystalFontz for the sample devices - they flushed out
- *           some driver bugs)
- *      Minor debugging message changes
- *      Added throttle, unthrottle and chars_in_buffer functions
- *      Fixed FTDI_SIO (the original device) bug
- *      Fixed some shutdown handling
- *
- *
- *
- *
- * (07/Jun/2002) Kuba Ober
- *	Changed FTDI_SIO_BASE_BAUD_TO_DIVISOR macro into ftdi_baud_to_divisor
- *	function. It was getting too complex.
- *	Fix the divisor calculation logic which was setting divisor of 0.125
- *	instead of 0.5 for fractional parts of divisor equal to 5/8, 6/8, 7/8.
- *	Also make it bump up the divisor to next integer in case of 7/8 - it's
- *	a better approximation.
- *
- * (25/Jul/2002) Bill Ryder inserted Dmitri's TIOCMIWAIT patch
- *      Not tested by me but it doesn't break anything I use.
- *
- * (04/Jan/2002) Kuba Ober
- *	Implemented 38400 baudrate kludge, where it can be substituted with other
- *	  values. That's the only way to set custom baudrates.
- *	Implemented TIOCSSERIAL, TIOCGSERIAL ioctl's so that setserial is happy.
- *	FIXME: both baudrate things should eventually go to usbserial.c as other
- *	  devices may need that functionality too. Actually, it can probably be
- *	  merged in serial.c somehow - too many drivers repeat this code over
- *	  and over.
- *	Fixed baudrate forgetfulness - open() used to reset baudrate to 9600 every time.
- *	Divisors for baudrates are calculated by a macro.
- *	Small code cleanups. Ugly whitespace changes for Plato's sake only ;-].
- *
- * (04/Nov/2001) Bill Ryder
- *	Fixed bug in read_bulk_callback where incorrect urb buffer was used.
- *	Cleaned up write offset calculation
- *	Added write_room since default values can be incorrect for sio
- *	Changed write_bulk_callback to use same queue_task as other drivers
- *        (the previous version caused panics)
- *	Removed port iteration code since the device only has one I/O port and it
- *	  was wrong anyway.
- *
- * (31/May/2001) gkh
- *	Switched from using spinlock to a semaphore, which fixes lots of problems.
- *
- * (23/May/2001)   Bill Ryder
- *	Added runtime debug patch (thanx Tyson D Sawyer).
- *	Cleaned up comments for 8U232
- *	Added parity, framing and overrun error handling
- *	Added receive break handling.
- *
- * (04/08/2001) gb
- *	Identify version on module load.
- *
- * (18/March/2001) Bill Ryder
- *	(Not released)
- *	Added send break handling. (requires kernel patch too)
- *	Fixed 8U232AM hardware RTS/CTS etc status reporting.
- *	Added flipbuf fix copied from generic device
- *
- * (12/3/2000) Bill Ryder
- *	Added support for 8U232AM device.
- *	Moved PID and VIDs into header file only.
- *	Turned on low-latency for the tty (device will do high baudrates)
- *	Added shutdown routine to close files when device removed.
- *	More debug and error message cleanups.
- *
- * (11/13/2000) Bill Ryder
- *	Added spinlock protected open code and close code.
- *	Multiple opens work (sort of - see webpage mentioned above).
- *	Cleaned up comments. Removed multiple PID/VID definitions.
- *	Factorised cts/dtr code
- *	Made use of __FUNCTION__ in dbg's
- *
- * (11/01/2000) Adam J. Richter
- *	usb_device_id table support
- *
- * (10/05/2000) gkh
- *	Fixed bug with urb->dev not being set properly, now that the usb
- *	core needs it.
- *
- * (09/11/2000) gkh
- *	Removed DEBUG #ifdefs with call to usb_serial_debug_data
- *
- * (07/19/2000) gkh
- *	Added module_init and module_exit functions to handle the fact that this
- *	driver is a loadable module now.
- *
- * (04/04/2000) Bill Ryder
- *	Fixed bugs in TCGET/TCSET ioctls (by removing them - they are
- *        handled elsewhere in the tty io driver chain).
- *
- * (03/30/2000) Bill Ryder
- *	Implemented lots of ioctls
- *	Fixed a race condition in write
- *	Changed some dbg's to errs
- *
- * (03/26/2000) gkh
- *	Split driver up into device specific pieces.
+ * Change entries from 2004 and earlier can be found in versions of this
+ * file in kernel versions prior to the 2.6.24 release.
  *
  */
 
@@ -309,12 +91,12 @@
 	void (*port_probe)(struct ftdi_private *); /* Special settings for probed ports. */
 };
 
-static int   ftdi_olimex_probe		(struct usb_serial *serial);
+static int   ftdi_jtag_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_jtag_quirk = {
+	.probe	= ftdi_jtag_probe,
 };
 
 static struct ftdi_sio_quirk ftdi_USB_UIRT_quirk = {
@@ -471,30 +253,28 @@
 	{ USB_DEVICE(FTDI_VID, FTDI_IBS_PEDO_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_IBS_PROD_PID) },
 	/*
-	 * These will probably use user-space drivers.  Uncomment them if
-	 * you need them or use the user-specified vendor/product module
-	 * parameters (see ftdi_sio.h for the numbers).  Make a fuss if
-	 * you think the driver should recognize any of them by default.
+	 * Due to many user requests for multiple ELV devices we enable
+	 * them by default.
 	 */
-	/* { USB_DEVICE(FTDI_VID, FTDI_ELV_CLI7000_PID) }, */
-	/* { USB_DEVICE(FTDI_VID, FTDI_ELV_PPS7330_PID) }, */
-	/* { USB_DEVICE(FTDI_VID, FTDI_ELV_TFM100_PID) }, */
-	/* { USB_DEVICE(FTDI_VID, FTDI_ELV_UDF77_PID) }, */
-	/* { USB_DEVICE(FTDI_VID, FTDI_ELV_UIO88_PID) }, */
-	/* { USB_DEVICE(FTDI_VID, FTDI_ELV_UAD8_PID) }, */
-	/* { USB_DEVICE(FTDI_VID, FTDI_ELV_UDA7_PID) }, */
-	/* { USB_DEVICE(FTDI_VID, FTDI_ELV_USI2_PID) }, */
-	/* { USB_DEVICE(FTDI_VID, FTDI_ELV_T1100_PID) }, */
-	/* { USB_DEVICE(FTDI_VID, FTDI_ELV_PCD200_PID) }, */
-	/* { USB_DEVICE(FTDI_VID, FTDI_ELV_ULA200_PID) }, */
-	/* { USB_DEVICE(FTDI_VID, FTDI_ELV_CSI8_PID) }, */
-	/* { USB_DEVICE(FTDI_VID, FTDI_ELV_EM1000DL_PID) }, */
-	/* { USB_DEVICE(FTDI_VID, FTDI_ELV_PCK100_PID) }, */
-	/* { USB_DEVICE(FTDI_VID, FTDI_ELV_RFP500_PID) }, */
-	/* { USB_DEVICE(FTDI_VID, FTDI_ELV_FS20SIG_PID) }, */
-	/* { USB_DEVICE(FTDI_VID, FTDI_ELV_WS300PC_PID) }, */
-	/* { USB_DEVICE(FTDI_VID, FTDI_ELV_FHZ1300PC_PID) }, */
-	/* { USB_DEVICE(FTDI_VID, FTDI_ELV_WS500_PID) }, */
+	{ USB_DEVICE(FTDI_VID, FTDI_ELV_CLI7000_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_ELV_PPS7330_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_ELV_TFM100_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_ELV_UDF77_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_ELV_UIO88_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_ELV_UAD8_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_ELV_UDA7_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_ELV_USI2_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_ELV_T1100_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_ELV_PCD200_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_ELV_ULA200_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_ELV_CSI8_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_ELV_EM1000DL_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_ELV_PCK100_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_ELV_RFP500_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_ELV_FS20SIG_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_ELV_WS300PC_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_ELV_FHZ1300PC_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_ELV_WS500_PID) },
 	{ USB_DEVICE(FTDI_VID, LINX_SDMUSBQSS_PID) },
 	{ USB_DEVICE(FTDI_VID, LINX_MASTERDEVEL2_PID) },
 	{ USB_DEVICE(FTDI_VID, LINX_FUTURE_0_PID) },
@@ -545,6 +325,7 @@
 	{ USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16C_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16HR_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16HRC_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16IC_PID) },
 	{ USB_DEVICE(KOBIL_VID, KOBIL_CONV_B1_PID) },
 	{ USB_DEVICE(KOBIL_VID, KOBIL_CONV_KAAN_PID) },
 	{ USB_DEVICE(POSIFLEX_VID, POSIFLEX_PP7000_PID) },
@@ -569,8 +350,13 @@
 	{ USB_DEVICE(TELLDUS_VID, TELLDUS_TELLSTICK_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_MAXSTREAM_PID) },
 	{ USB_DEVICE(TML_VID, TML_USB_SERIAL_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_ELSTER_UNICOM_PID) },
 	{ USB_DEVICE(OLIMEX_VID, OLIMEX_ARM_USB_OCD_PID),
-		.driver_info = (kernel_ulong_t)&ftdi_olimex_quirk },
+		.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
+	{ USB_DEVICE(FIC_VID, FIC_NEO1973_DEBUG_PID),
+		.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
+	{ USB_DEVICE(FTDI_VID, FTDI_OOCDLINK_PID),
+		.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
 	{ },					/* Optional parameter entry */
 	{ }					/* Terminating entry */
 };
@@ -1283,10 +1069,11 @@
 } /* ftdi_HE_TIRA1_setup */
 
 /*
- * First port on Olimex arm-usb-ocd is reserved for JTAG interface
- * and can be accessed from userspace using openocd.
+ * First port on JTAG adaptors such as Olimex arm-usb-ocd or the FIC/OpenMoko
+ * Neo1973 Debug Board is reserved for JTAG interface and can be accessed from
+ * userspace using openocd.
  */
-static int ftdi_olimex_probe(struct usb_serial *serial)
+static int ftdi_jtag_probe(struct usb_serial *serial)
 {
 	struct usb_device *udev = serial->dev;
 	struct usb_interface *interface = serial->interface;
@@ -1294,7 +1081,7 @@
 	dbg("%s",__FUNCTION__);
 
 	if (interface == udev->actconfig->interface[0]) {
-		info("Ignoring reserved serial port on Olimex arm-usb-ocd\n");
+		info("Ignoring serial port reserved for JTAG");
 		return -ENODEV;
 	}
 
@@ -1411,7 +1198,8 @@
 
 	dbg("%s", __FUNCTION__);
 
-	if (c_cflag & HUPCL){
+	mutex_lock(&port->serial->disc_mutex);
+	if (c_cflag & HUPCL && !port->serial->disconnected){
 		/* Disable flow control */
 		if (usb_control_msg(port->serial->dev,
 				    usb_sndctrlpipe(port->serial->dev, 0),
@@ -1425,6 +1213,7 @@
 		/* drop RTS and DTR */
 		clear_mctrl(port, TIOCM_DTR | TIOCM_RTS);
 	} /* Note change no line if hupcl is off */
+	mutex_unlock(&port->serial->disc_mutex);
 
 	/* cancel any scheduled reading */
 	cancel_delayed_work(&priv->rx_work);
diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h
index b51cbb0..6eee2ab 100644
--- a/drivers/usb/serial/ftdi_sio.h
+++ b/drivers/usb/serial/ftdi_sio.h
@@ -98,6 +98,10 @@
 #define FTDI_MTXORB_5_PID      0xFA05  /* Matrix Orbital Product Id */
 #define FTDI_MTXORB_6_PID      0xFA06  /* Matrix Orbital Product Id */
 
+/* OOCDlink by Joern Kaipf <joernk@web.de>
+ * (http://www.joernonline.de/dw/doku.php?id=start&idx=projects:oocdlink) */
+#define FTDI_OOCDLINK_PID	0xbaf8	/* Amontec JTAGkey */
+
 /* Interbiometrics USB I/O Board */
 /* Developed for Interbiometrics by Rudolf Gugler */
 #define INTERBIOMETRICS_VID              0x1209
@@ -245,6 +249,7 @@
 #define FTDI_ELV_WS300PC_PID	0xE0F6	/* PC-Wetterstation (WS 300 PC) */
 #define FTDI_ELV_FHZ1300PC_PID	0xE0E8	/* FHZ 1300 PC */
 #define FTDI_ELV_WS500_PID	0xE0E9	/* PC-Wetterstation (WS 500) */
+#define FTDI_ELV_EM1010PC_PID	0xE0EF	/* Engery monitor EM 1010 PC */
 
 /*
  * Definitions for ID TECH (www.idt-net.com) devices
@@ -278,6 +283,7 @@
 #define FTDI_ATIK_ATK16C_PID	0xDF32	/* ATIK ATK-16C Colour Camera */
 #define FTDI_ATIK_ATK16HR_PID	0xDF31	/* ATIK ATK-16HR Grayscale Camera */
 #define FTDI_ATIK_ATK16HRC_PID	0xDF33	/* ATIK ATK-16HRC Colour Camera */
+#define FTDI_ATIK_ATK16IC_PID   0xDF35  /* ATIK ATK-16IC Grayscale Camera */
 
 /*
  * Protego product ids
@@ -534,6 +540,8 @@
 #define OLIMEX_VID			0x15BA
 #define OLIMEX_ARM_USB_OCD_PID		0x0003
 
+/* www.elsterelectricity.com Elster Unicom III Optical Probe */
+#define FTDI_ELSTER_UNICOM_PID		0xE700 /* Product Id */
 
 /*
  * The Mobility Lab (TML)
@@ -556,6 +564,13 @@
 
 
 /*
+ * FIC / OpenMoko, Inc. http://wiki.openmoko.org/wiki/Neo1973_Debug_Board_v3
+ * Submitted by Harald Welte <laforge@openmoko.org>
+ */
+#define	FIC_VID			0x1457
+#define	FIC_NEO1973_DEBUG_PID	0x5118
+
+/*
  *   BmRequestType:  1100 0000b
  *   bRequest:       FTDI_E2_READ
  *   wValue:         0
diff --git a/drivers/usb/serial/garmin_gps.c b/drivers/usb/serial/garmin_gps.c
index f1c90cf..d74e43d 100644
--- a/drivers/usb/serial/garmin_gps.c
+++ b/drivers/usb/serial/garmin_gps.c
@@ -1020,19 +1020,26 @@
 	if (!serial)
 		return;
 
-	garmin_clear(garmin_data_p);
+	mutex_lock(&port->serial->disc_mutex);
+	if (!port->serial->disconnected)
+		garmin_clear(garmin_data_p);
 
 	/* shutdown our urbs */
 	usb_kill_urb (port->read_urb);
 	usb_kill_urb (port->write_urb);
 
-	if (noResponseFromAppLayer(garmin_data_p) ||
-	    ((garmin_data_p->flags & CLEAR_HALT_REQUIRED) != 0)) {
-		process_resetdev_request(port);
-		garmin_data_p->state = STATE_RESET;
+	if (!port->serial->disconnected) {
+		if (noResponseFromAppLayer(garmin_data_p) ||
+		    ((garmin_data_p->flags & CLEAR_HALT_REQUIRED) != 0)) {
+			process_resetdev_request(port);
+			garmin_data_p->state = STATE_RESET;
+		} else {
+			garmin_data_p->state = STATE_DISCONNECTED;
+		}
 	} else {
 		garmin_data_p->state = STATE_DISCONNECTED;
 	}
+	mutex_unlock(&port->serial->disc_mutex);
 }
 
 
diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c
index d415311..97fa3c4 100644
--- a/drivers/usb/serial/generic.c
+++ b/drivers/usb/serial/generic.c
@@ -175,6 +175,14 @@
 	struct usb_serial_port *port;
 	int i, c = 0, r;
 
+#ifdef CONFIG_PM
+	/*
+	 * If this is an autoresume, don't submit URBs.
+	 * They will be submitted in the open function instead.
+	 */
+	if (serial->dev->auto_pm)
+		return 0;
+#endif
 	for (i = 0; i < serial->num_ports; i++) {
 		port = serial->port[i];
 		if (port->open_count && port->read_urb) {
diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c
index a5d2e11..3428ccc 100644
--- a/drivers/usb/serial/io_edgeport.c
+++ b/drivers/usb/serial/io_edgeport.c
@@ -959,7 +959,7 @@
  *
  *	This function will block the close until one of the following:
  *		1. Response to our Chase comes from Edgeport
- *		2. A timout of 10 seconds without activity has expired
+ *		2. A timeout of 10 seconds without activity has expired
  *		   (1K of Edgeport data @ 2400 baud ==> 4 sec to empty)
  *
  ************************************************************************/
@@ -999,7 +999,7 @@
 				return;
 			}
 		} else {
-			// Reset timout value back to 10 seconds
+			// Reset timeout value back to 10 seconds
 			dbg("%s - Last %d, Current %d", __FUNCTION__, lastCredits, edge_port->txCredits);
 			loop = 10;
 		}
@@ -1014,7 +1014,7 @@
  *	This function will block the close until one of the following:
  *		1. TX count are 0
  *		2. The edgeport has stopped
- *		3. A timout of 3 seconds without activity has expired
+ *		3. A timeout of 3 seconds without activity has expired
  *
  ************************************************************************/
 static void block_until_tx_empty (struct edgeport_port *edge_port)
@@ -1050,7 +1050,7 @@
 				return;
 			}
 		} else {
-			// Reset timout value back to seconds
+			// Reset timeout value back to seconds
 			loop = 30;
 		}
 	}
diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c
index b867090..cd34059 100644
--- a/drivers/usb/serial/io_ti.c
+++ b/drivers/usb/serial/io_ti.c
@@ -34,6 +34,7 @@
 #include <linux/tty_flip.h>
 #include <linux/module.h>
 #include <linux/spinlock.h>
+#include <linux/mutex.h>
 #include <linux/serial.h>
 #include <linux/ioctl.h>
 #include <asm/uaccess.h>
@@ -133,7 +134,7 @@
 	struct product_info product_info;
 	u8 TI_I2C_Type;			// Type of I2C in UMP
 	u8 TiReadI2C;			// Set to TRUE if we have read the I2c in Boot Mode
-	struct semaphore es_sem;
+	struct mutex es_lock;
 	int num_ports_open;
 	struct usb_serial *serial;
 };
@@ -1978,7 +1979,7 @@
 	}
 	
 	/* set up the port settings */
-	edge_set_termios (port, NULL);
+	edge_set_termios (port, port->tty->termios);
 
 	/* open up the port */
 
@@ -2044,7 +2045,7 @@
 	dbg ("ShadowMCR 0x%X", edge_port->shadow_mcr);
 
 	edge_serial = edge_port->edge_serial;
-	if (down_interruptible(&edge_serial->es_sem))
+	if (mutex_lock_interruptible(&edge_serial->es_lock))
 		return -ERESTARTSYS;
 	if (edge_serial->num_ports_open == 0) {
 		/* we are the first port to be opened, let's post the interrupt urb */
@@ -2052,7 +2053,7 @@
 		if (!urb) {
 			dev_err (&port->dev, "%s - no interrupt urb present, exiting\n", __FUNCTION__);
 			status = -EINVAL;
-			goto up_es_sem;
+			goto release_es_lock;
 		}
 		urb->complete = edge_interrupt_callback;
 		urb->context = edge_serial;
@@ -2060,7 +2061,7 @@
 		status = usb_submit_urb (urb, GFP_KERNEL);
 		if (status) {
 			dev_err (&port->dev, "%s - usb_submit_urb failed with value %d\n", __FUNCTION__, status);
-			goto up_es_sem;
+			goto release_es_lock;
 		}
 	}
 
@@ -2092,13 +2093,13 @@
 
 	dbg("%s - exited", __FUNCTION__);
 
-	goto up_es_sem;
+	goto release_es_lock;
 
 unlink_int_urb:
 	if (edge_port->edge_serial->num_ports_open == 0)
 		usb_kill_urb(port->serial->port[0]->interrupt_in_urb);
-up_es_sem:
-	up(&edge_serial->es_sem);
+release_es_lock:
+	mutex_unlock(&edge_serial->es_lock);
 	return status;
 }
 
@@ -2137,14 +2138,14 @@
 				     0,
 				     NULL,
 				     0);
-	down(&edge_serial->es_sem);
+	mutex_lock(&edge_serial->es_lock);
 	--edge_port->edge_serial->num_ports_open;
 	if (edge_port->edge_serial->num_ports_open <= 0) {
 		/* last port is now closed, let's shut down our interrupt urb */
 		usb_kill_urb(port->serial->port[0]->interrupt_in_urb);
 		edge_port->edge_serial->num_ports_open = 0;
 	}
-	up(&edge_serial->es_sem);
+	mutex_unlock(&edge_serial->es_lock);
 	edge_port->close_pending = 0;
 
 	dbg("%s - exited", __FUNCTION__);
@@ -2393,11 +2394,6 @@
 	dbg("%s - port %d", __FUNCTION__, edge_port->port->number);
 
 	tty = edge_port->port->tty;
-	if ((!tty) ||
-	    (!tty->termios)) {
-		dbg("%s - no tty structures", __FUNCTION__);
-		return;
-	}
 
 	config = kmalloc (sizeof (*config), GFP_KERNEL);
 	if (!config) {
@@ -2492,15 +2488,21 @@
 		}
 	}
 
+	tty->termios->c_cflag &= ~CMSPAR;
+
 	/* Round the baud rate */
 	baud = tty_get_baud_rate(tty);
 	if (!baud) {
 		/* pick a default, any default... */
 		baud = 9600;
-	}
+	} else
+		tty_encode_baud_rate(tty, baud, baud);
+
 	edge_port->baud_rate = baud;
 	config->wBaudRate = (__u16)((461550L + baud/2) / baud);
 
+	/* FIXME: Recompute actual baud from divisor here */
+
 	dbg ("%s - baud rate = %d, wBaudRate = %d", __FUNCTION__, baud, config->wBaudRate);
 
 	dbg ("wBaudRate:   %d", (int)(461550L / config->wBaudRate));
@@ -2538,19 +2540,12 @@
 	struct tty_struct *tty = port->tty;
 	unsigned int cflag;
 
-	if (!port->tty || !port->tty->termios) {
-		dbg ("%s - no tty or termios", __FUNCTION__);
-		return;
-	}
-
 	cflag = tty->termios->c_cflag;
 
 	dbg("%s - clfag %08x iflag %08x", __FUNCTION__, 
 	    tty->termios->c_cflag, tty->termios->c_iflag);
-	if (old_termios) {
-		dbg("%s - old clfag %08x old iflag %08x", __FUNCTION__,
-		    old_termios->c_cflag, old_termios->c_iflag);
-	}
+	dbg("%s - old clfag %08x old iflag %08x", __FUNCTION__,
+	    old_termios->c_cflag, old_termios->c_iflag);
 
 	dbg("%s - port %d", __FUNCTION__, port->number);
 
@@ -2743,7 +2738,7 @@
 		dev_err(&serial->dev->dev, "%s - Out of memory\n", __FUNCTION__);
 		return -ENOMEM;
 	}
-	sema_init(&edge_serial->es_sem, 1);
+	mutex_init(&edge_serial->es_lock);
 	edge_serial->serial = serial;
 	usb_set_serial_data(serial, edge_serial);
 
diff --git a/drivers/usb/serial/iuu_phoenix.c b/drivers/usb/serial/iuu_phoenix.c
new file mode 100644
index 0000000..fde188e
--- /dev/null
+++ b/drivers/usb/serial/iuu_phoenix.c
@@ -0,0 +1,1217 @@
+/*
+ * Infinity Unlimited USB Phoenix driver
+ *
+ * Copyright (C) 2007 Alain Degreffe (eczema@ecze.com)
+ *
+ * Original code taken from iuutool (Copyright (C) 2006 Juan Carlos Borrás)
+ *
+ *	This program is free software; you can redistribute it and/or modify
+ *	it under the terms of the GNU General Public License as published by
+ *	the Free Software Foundation; either version 2 of the License, or
+ *	(at your option) any later version.
+ *
+ *  And tested with help of WB Electronics
+ *
+ */
+#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/uaccess.h>
+#include <linux/usb.h>
+#include <linux/usb/serial.h>
+#include "iuu_phoenix.h"
+#include <linux/random.h>
+
+
+#ifdef CONFIG_USB_SERIAL_DEBUG
+static int debug = 1;
+#else
+static int debug;
+#endif
+
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v0.5"
+#define DRIVER_DESC "Infinity USB Unlimited Phoenix driver"
+
+static struct usb_device_id id_table[] = {
+	{USB_DEVICE(IUU_USB_VENDOR_ID, IUU_USB_PRODUCT_ID)},
+	{}			/* Terminating entry */
+};
+MODULE_DEVICE_TABLE(usb, id_table);
+
+static struct usb_driver iuu_driver = {
+	.name = "iuu_phoenix",
+	.probe = usb_serial_probe,
+	.disconnect = usb_serial_disconnect,
+	.id_table = id_table,
+	.no_dynamic_id = 1,
+};
+
+/* turbo parameter */
+static int boost = 100;
+static int clockmode = 1;
+static int cdmode = 1;
+static int iuu_cardin;
+static int iuu_cardout;
+static int xmas;
+
+static void read_rxcmd_callback(struct urb *urb);
+
+struct iuu_private {
+	spinlock_t lock;	/* store irq state */
+	wait_queue_head_t delta_msr_wait;
+	u8 line_control;
+	u8 line_status;
+	u8 termios_initialized;
+	int tiostatus;		/* store IUART SIGNAL for tiocmget call */
+	u8 reset;		/* if 1 reset is needed */
+	int poll;		/* number of poll */
+	u8 *writebuf;		/* buffer for writing to device */
+	int writelen;		/* num of byte to write to device */
+	u8 *buf;		/* used for initialize speed */
+	u8 *dbgbuf;		/* debug buffer */
+	u8 len;
+};
+
+
+static void iuu_free_buf(struct iuu_private *priv)
+{
+	kfree(priv->buf);
+	kfree(priv->dbgbuf);
+	kfree(priv->writebuf);
+}
+
+static int iuu_alloc_buf(struct iuu_private *priv)
+{
+	priv->buf = kzalloc(256, GFP_KERNEL);
+	priv->dbgbuf = kzalloc(256, GFP_KERNEL);
+	priv->writebuf = kzalloc(256, GFP_KERNEL);
+	if (!priv->buf || !priv->dbgbuf || !priv->writebuf) {
+		iuu_free_buf(priv);
+		dbg("%s problem allocation buffer", __FUNCTION__);
+		return -ENOMEM;
+	}
+	dbg("%s - Privates buffers allocation success", __FUNCTION__);
+	return 0;
+}
+
+static int iuu_startup(struct usb_serial *serial)
+{
+	struct iuu_private *priv;
+	priv = kzalloc(sizeof(struct iuu_private), GFP_KERNEL);
+	dbg("%s- priv allocation success", __FUNCTION__);
+	if (!priv)
+		return -ENOMEM;
+	if (iuu_alloc_buf(priv)) {
+		kfree(priv);
+		return -ENOMEM;
+	}
+	spin_lock_init(&priv->lock);
+	init_waitqueue_head(&priv->delta_msr_wait);
+	usb_set_serial_port_data(serial->port[0], priv);
+	return 0;
+}
+
+/* Shutdown function */
+static void iuu_shutdown(struct usb_serial *serial)
+{
+	struct usb_serial_port *port = serial->port[0];
+	struct iuu_private *priv = usb_get_serial_port_data(port);
+	if (!port)
+		return;
+
+	dbg("%s", __FUNCTION__);
+
+	if (priv) {
+		iuu_free_buf(priv);
+		dbg("%s - I will free all", __FUNCTION__);
+		usb_set_serial_port_data(port, NULL);
+
+		dbg("%s - priv is not anymore in port structure", __FUNCTION__);
+		kfree(priv);
+
+		dbg("%s priv is now kfree", __FUNCTION__);
+	}
+}
+
+static int iuu_tiocmset(struct usb_serial_port *port, struct file *file,
+			unsigned int set, unsigned int clear)
+{
+	struct iuu_private *priv = usb_get_serial_port_data(port);
+	struct tty_struct *tty;
+	tty = port->tty;
+
+	dbg("%s (%d) msg : SET = 0x%04x, CLEAR = 0x%04x ", __FUNCTION__,
+	    port->number, set, clear);
+	if (set & TIOCM_RTS)
+		priv->tiostatus = TIOCM_RTS;
+
+	if (!(set & TIOCM_RTS) && priv->tiostatus == TIOCM_RTS) {
+		dbg("%s TIOCMSET RESET called !!!", __FUNCTION__);
+		priv->reset = 1;
+		return 0;
+	}
+
+	return 0;
+}
+
+/* This is used to provide a carrier detect mechanism
+ * When a card is present, the response is 0x00
+ * When no card , the reader respond with TIOCM_CD
+ * This is known as CD autodetect mechanism
+ */
+static int iuu_tiocmget(struct usb_serial_port *port, struct file *file)
+{
+	struct iuu_private *priv = usb_get_serial_port_data(port);
+	return priv->tiostatus;
+}
+
+static void iuu_rxcmd(struct urb *urb)
+{
+	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+	int result;
+	dbg("%s - enter", __FUNCTION__);
+
+	if (urb->status) {
+		dbg("%s - urb->status = %d", __FUNCTION__, urb->status);
+		/* error stop all */
+		return;
+	}
+
+
+	memset(port->write_urb->transfer_buffer, IUU_UART_RX, 1);
+	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,
+			  read_rxcmd_callback, port);
+	result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
+}
+
+static int iuu_reset(struct usb_serial_port *port, u8 wt)
+{
+	struct iuu_private *priv = usb_get_serial_port_data(port);
+	int result;
+	char *buf_ptr = port->write_urb->transfer_buffer;
+	dbg("%s - enter", __FUNCTION__);
+
+	/* Prepare the reset sequence */
+
+	*buf_ptr++ = IUU_RST_SET;
+	*buf_ptr++ = IUU_DELAY_MS;
+	*buf_ptr++ = wt;
+	*buf_ptr = IUU_RST_CLEAR;
+
+	/* send the sequence */
+
+	usb_fill_bulk_urb(port->write_urb,
+			  port->serial->dev,
+			  usb_sndbulkpipe(port->serial->dev,
+					  port->bulk_out_endpointAddress),
+			  port->write_urb->transfer_buffer, 4, iuu_rxcmd, port);
+	result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
+	priv->reset = 0;
+	return result;
+}
+
+/* Status Function
+ * Return value is
+ * 0x00 = no card
+ * 0x01 = smartcard
+ * 0x02 = sim card
+ */
+static void iuu_update_status_callback(struct urb *urb)
+{
+	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+	struct iuu_private *priv = usb_get_serial_port_data(port);
+	u8 *st;
+	dbg("%s - enter", __FUNCTION__);
+
+	if (urb->status) {
+		dbg("%s - urb->status = %d", __FUNCTION__, urb->status);
+		/* error stop all */
+		return;
+	}
+
+	st = urb->transfer_buffer;
+	dbg("%s - enter", __FUNCTION__);
+	if (urb->actual_length == 1) {
+		switch (st[0]) {
+		case 0x1:
+			priv->tiostatus = iuu_cardout;
+			break;
+		case 0x0:
+			priv->tiostatus = iuu_cardin;
+			break;
+		default:
+			priv->tiostatus = iuu_cardin;
+		}
+	}
+	iuu_rxcmd(urb);
+}
+
+static void iuu_status_callback(struct urb *urb)
+{
+	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+	int result;
+	dbg("%s - enter", __FUNCTION__);
+
+	dbg("%s - urb->status = %d", __FUNCTION__, urb->status);
+	usb_fill_bulk_urb(port->read_urb, port->serial->dev,
+			  usb_rcvbulkpipe(port->serial->dev,
+					  port->bulk_in_endpointAddress),
+			  port->read_urb->transfer_buffer, 256,
+			  iuu_update_status_callback, port);
+	result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
+}
+
+static int iuu_status(struct usb_serial_port *port)
+{
+	int result;
+
+	dbg("%s - enter", __FUNCTION__);
+
+	memset(port->write_urb->transfer_buffer, IUU_GET_STATE_REGISTER, 1);
+	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,
+			  iuu_status_callback, port);
+	result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
+	return result;
+
+}
+
+static int bulk_immediate(struct usb_serial_port *port, u8 *buf, u8 count)
+{
+	int status;
+	struct usb_serial *serial = port->serial;
+	int actual = 0;
+
+	dbg("%s - enter", __FUNCTION__);
+
+	/* send the data out the bulk port */
+
+	status =
+	    usb_bulk_msg(serial->dev,
+			 usb_sndbulkpipe(serial->dev,
+					 port->bulk_out_endpointAddress), buf,
+			 count, &actual, HZ * 1);
+
+	if (status != IUU_OPERATION_OK) {
+		dbg("%s - error = %2x", __FUNCTION__, status);
+	} else {
+		dbg("%s - write OK !", __FUNCTION__);
+	}
+	return status;
+}
+
+static int read_immediate(struct usb_serial_port *port, u8 *buf, u8 count)
+{
+	int status;
+	struct usb_serial *serial = port->serial;
+	int actual = 0;
+
+	dbg("%s - enter", __FUNCTION__);
+
+	/* send the data out the bulk port */
+
+	status =
+	    usb_bulk_msg(serial->dev,
+			 usb_rcvbulkpipe(serial->dev,
+					 port->bulk_in_endpointAddress), buf,
+			 count, &actual, HZ * 1);
+
+	if (status != IUU_OPERATION_OK) {
+		dbg("%s - error = %2x", __FUNCTION__, status);
+	} else {
+		dbg("%s - read OK !", __FUNCTION__);
+	}
+
+	return status;
+}
+
+static int iuu_led(struct usb_serial_port *port, unsigned int R,
+		   unsigned int G, unsigned int B, u8 f)
+{
+	int status;
+	u8 *buf;
+	buf = kmalloc(8, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	dbg("%s - enter", __FUNCTION__);
+
+	buf[0] = IUU_SET_LED;
+	buf[1] = R & 0xFF;
+	buf[2] = (R >> 8) & 0xFF;
+	buf[3] = G & 0xFF;
+	buf[4] = (G >> 8) & 0xFF;
+	buf[5] = B & 0xFF;
+	buf[6] = (B >> 8) & 0xFF;
+	buf[7] = f;
+	status = bulk_immediate(port, buf, 8);
+	kfree(buf);
+	if (status != IUU_OPERATION_OK)
+		dbg("%s - led error status = %2x", __FUNCTION__, status);
+	else
+		dbg("%s - led OK !", __FUNCTION__);
+	return IUU_OPERATION_OK;
+}
+
+static void iuu_rgbf_fill_buffer(u8 *buf, u8 r1, u8 r2, u8 g1, u8 g2, u8 b1,
+				 u8 b2, u8 freq)
+{
+	*buf++ = IUU_SET_LED;
+	*buf++ = r1;
+	*buf++ = r2;
+	*buf++ = g1;
+	*buf++ = g2;
+	*buf++ = b1;
+	*buf++ = b2;
+	*buf = freq;
+}
+
+static void iuu_led_activity_on(struct urb *urb)
+{
+	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+	int result;
+	char *buf_ptr = port->write_urb->transfer_buffer;
+	*buf_ptr++ = IUU_SET_LED;
+	if (xmas == 1) {
+		get_random_bytes(buf_ptr, 6);
+		*(buf_ptr+7) = 1;
+	} else {
+		iuu_rgbf_fill_buffer(buf_ptr, 255, 255, 0, 0, 0, 0, 255);
+	}
+
+	usb_fill_bulk_urb(port->write_urb, port->serial->dev,
+			  usb_sndbulkpipe(port->serial->dev,
+					  port->bulk_out_endpointAddress),
+			  port->write_urb->transfer_buffer, 8 ,
+			  iuu_rxcmd, port);
+	result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
+}
+
+static void iuu_led_activity_off(struct urb *urb)
+{
+	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+	int result;
+	char *buf_ptr = port->write_urb->transfer_buffer;
+	if (xmas == 1) {
+		iuu_rxcmd(urb);
+		return;
+	} else {
+		*buf_ptr++ = IUU_SET_LED;
+		iuu_rgbf_fill_buffer(buf_ptr, 0, 0, 255, 255, 0, 0, 255);
+	}
+	usb_fill_bulk_urb(port->write_urb, port->serial->dev,
+			  usb_sndbulkpipe(port->serial->dev,
+					  port->bulk_out_endpointAddress),
+			  port->write_urb->transfer_buffer, 8 ,
+			  iuu_rxcmd, port);
+	result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
+}
+
+
+
+static int iuu_clk(struct usb_serial_port *port, int dwFrq)
+{
+	int status;
+	struct iuu_private *priv = usb_get_serial_port_data(port);
+	int Count = 0;
+	u8 FrqGenAdr = 0x69;
+	u8 DIV = 0;		/* 8bit */
+	u8 XDRV = 0;		/* 8bit */
+	u8 PUMP = 0;		/* 3bit */
+	u8 PBmsb = 0;		/* 2bit */
+	u8 PBlsb = 0;		/* 8bit */
+	u8 PO = 0;		/* 1bit */
+	u8 Q = 0;		/* 7bit */
+	/* 24bit = 3bytes */
+	unsigned int P = 0;
+	unsigned int P2 = 0;
+	int frq = (int)dwFrq;
+
+	dbg("%s - enter", __FUNCTION__);
+
+	if (frq == 0) {
+		priv->buf[Count++] = IUU_UART_WRITE_I2C;
+		priv->buf[Count++] = FrqGenAdr << 1;
+		priv->buf[Count++] = 0x09;
+		priv->buf[Count++] = 0x00;
+
+		status = bulk_immediate(port, (u8 *) priv->buf, Count);
+		if (status != 0) {
+			dbg("%s - write error ", __FUNCTION__);
+			return status;
+		}
+	} else if (frq == 3579000) {
+		DIV = 100;
+		P = 1193;
+		Q = 40;
+		XDRV = 0;
+	} else if (frq == 3680000) {
+		DIV = 105;
+		P = 161;
+		Q = 5;
+		XDRV = 0;
+	} else if (frq == 6000000) {
+		DIV = 66;
+		P = 66;
+		Q = 2;
+		XDRV = 0x28;
+	} else {
+		unsigned int result = 0;
+		unsigned int tmp = 0;
+		unsigned int check;
+		unsigned int check2;
+		char found = 0x00;
+		unsigned int lQ = 2;
+		unsigned int lP = 2055;
+		unsigned int lDiv = 4;
+
+		for (lQ = 2; lQ <= 47 && !found; lQ++)
+			for (lP = 2055; lP >= 8 && !found; lP--)
+				for (lDiv = 4; lDiv <= 127 && !found; lDiv++) {
+					tmp = (12000000 / lDiv) * (lP / lQ);
+					if (abs((int)(tmp - frq)) <
+					    abs((int)(frq - result))) {
+						check2 = (12000000 / lQ);
+						if (check2 < 250000)
+							continue;
+						check = (12000000 / lQ) * lP;
+						if (check > 400000000)
+							continue;
+						if (check < 100000000)
+							continue;
+						if (lDiv < 4 || lDiv > 127)
+							continue;
+						result = tmp;
+						P = lP;
+						DIV = lDiv;
+						Q = lQ;
+						if (result == frq)
+							found = 0x01;
+					}
+				}
+	}
+	P2 = ((P - PO) / 2) - 4;
+	DIV = DIV;
+	PUMP = 0x04;
+	PBmsb = (P2 >> 8 & 0x03);
+	PBlsb = P2 & 0xFF;
+	PO = (P >> 10) & 0x01;
+	Q = Q - 2;
+
+	priv->buf[Count++] = IUU_UART_WRITE_I2C;	/* 0x4C */
+	priv->buf[Count++] = FrqGenAdr << 1;
+	priv->buf[Count++] = 0x09;
+	priv->buf[Count++] = 0x20;	/* Adr = 0x09 */
+	priv->buf[Count++] = IUU_UART_WRITE_I2C;	/* 0x4C */
+	priv->buf[Count++] = FrqGenAdr << 1;
+	priv->buf[Count++] = 0x0C;
+	priv->buf[Count++] = DIV;	/* Adr = 0x0C */
+	priv->buf[Count++] = IUU_UART_WRITE_I2C;	/* 0x4C */
+	priv->buf[Count++] = FrqGenAdr << 1;
+	priv->buf[Count++] = 0x12;
+	priv->buf[Count++] = XDRV;	/* Adr = 0x12 */
+	priv->buf[Count++] = IUU_UART_WRITE_I2C;	/*  0x4C */
+	priv->buf[Count++] = FrqGenAdr << 1;
+	priv->buf[Count++] = 0x13;
+	priv->buf[Count++] = 0x6B;	/* Adr = 0x13 */
+	priv->buf[Count++] = IUU_UART_WRITE_I2C;	/*  0x4C */
+	priv->buf[Count++] = FrqGenAdr << 1;
+	priv->buf[Count++] = 0x40;
+	priv->buf[Count++] = (0xC0 | ((PUMP & 0x07) << 2)) |
+			     (PBmsb & 0x03);	/* Adr = 0x40 */
+	priv->buf[Count++] = IUU_UART_WRITE_I2C;	/*  0x4C */
+	priv->buf[Count++] = FrqGenAdr << 1;
+	priv->buf[Count++] = 0x41;
+	priv->buf[Count++] = PBlsb;	/* Adr = 0x41 */
+	priv->buf[Count++] = IUU_UART_WRITE_I2C;	/*  0x4C */
+	priv->buf[Count++] = FrqGenAdr << 1;
+	priv->buf[Count++] = 0x42;
+	priv->buf[Count++] = Q | (((PO & 0x01) << 7));	/* Adr = 0x42 */
+	priv->buf[Count++] = IUU_UART_WRITE_I2C;	/*  0x4C */
+	priv->buf[Count++] = FrqGenAdr << 1;
+	priv->buf[Count++] = 0x44;
+	priv->buf[Count++] = (char)0xFF;	/* Adr = 0x44 */
+	priv->buf[Count++] = IUU_UART_WRITE_I2C;	/*  0x4C */
+	priv->buf[Count++] = FrqGenAdr << 1;
+	priv->buf[Count++] = 0x45;
+	priv->buf[Count++] = (char)0xFE;	/* Adr = 0x45 */
+	priv->buf[Count++] = IUU_UART_WRITE_I2C;	/*  0x4C */
+	priv->buf[Count++] = FrqGenAdr << 1;
+	priv->buf[Count++] = 0x46;
+	priv->buf[Count++] = 0x7F;	/* Adr = 0x46 */
+	priv->buf[Count++] = IUU_UART_WRITE_I2C;	/*  0x4C */
+	priv->buf[Count++] = FrqGenAdr << 1;
+	priv->buf[Count++] = 0x47;
+	priv->buf[Count++] = (char)0x84;	/* Adr = 0x47 */
+
+	status = bulk_immediate(port, (u8 *) priv->buf, Count);
+	if (status != IUU_OPERATION_OK)
+		dbg("%s - write error ", __FUNCTION__);
+	return status;
+}
+
+static int iuu_uart_flush(struct usb_serial_port *port)
+{
+	int i;
+	int status;
+	u8 rxcmd = IUU_UART_RX;
+	struct iuu_private *priv = usb_get_serial_port_data(port);
+
+	dbg("%s - enter", __FUNCTION__);
+
+	if (iuu_led(port, 0xF000, 0, 0, 0xFF) < 0)
+		return -EIO;
+
+	for (i = 0; i < 2; i++) {
+		status = bulk_immediate(port, &rxcmd, 1);
+		if (status != IUU_OPERATION_OK) {
+			dbg("%s - uart_flush_write error", __FUNCTION__);
+			return status;
+		}
+
+		status = read_immediate(port, &priv->len, 1);
+		if (status != IUU_OPERATION_OK) {
+			dbg("%s - uart_flush_read error", __FUNCTION__);
+			return status;
+		}
+
+		if (priv->len > 0) {
+			dbg("%s - uart_flush datalen is : %i ", __FUNCTION__,
+			    priv->len);
+			status = read_immediate(port, priv->buf, priv->len);
+			if (status != IUU_OPERATION_OK) {
+				dbg("%s - uart_flush_read error", __FUNCTION__);
+				return status;
+			}
+		}
+	}
+	dbg("%s - uart_flush_read OK!", __FUNCTION__);
+	iuu_led(port, 0, 0xF000, 0, 0xFF);
+	return status;
+}
+
+static void read_buf_callback(struct urb *urb)
+{
+	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+	unsigned char *data = urb->transfer_buffer;
+	struct tty_struct *tty;
+	dbg("%s - urb->status = %d", __FUNCTION__, urb->status);
+
+	if (urb->status) {
+		dbg("%s - urb->status = %d", __FUNCTION__, urb->status);
+		if (urb->status == -EPROTO) {
+			/* reschedule needed */
+		}
+		return;
+	}
+
+	dbg("%s - %i chars to write", __FUNCTION__, urb->actual_length);
+	tty = port->tty;
+	if (data == NULL)
+		dbg("%s - data is NULL !!!", __FUNCTION__);
+	if (tty && urb->actual_length && data) {
+		tty_insert_flip_string(tty, data, urb->actual_length);
+		tty_flip_buffer_push(tty);
+	}
+	iuu_led_activity_on(urb);
+}
+
+static int iuu_bulk_write(struct usb_serial_port *port)
+{
+	struct iuu_private *priv = usb_get_serial_port_data(port);
+	unsigned int flags;
+	int result;
+	int i;
+	char *buf_ptr = port->write_urb->transfer_buffer;
+	dbg("%s - enter", __FUNCTION__);
+
+	*buf_ptr++ = IUU_UART_ESC;
+	*buf_ptr++ = IUU_UART_TX;
+	*buf_ptr++ = priv->writelen;
+
+	memcpy(buf_ptr, priv->writebuf,
+	       priv->writelen);
+	if (debug == 1) {
+		for (i = 0; i < priv->writelen; i++)
+			sprintf(priv->dbgbuf + i*2 ,
+				"%02X", priv->writebuf[i]);
+		priv->dbgbuf[priv->writelen+i*2] = 0;
+		dbg("%s - writing %i chars : %s", __FUNCTION__,
+		    priv->writelen, priv->dbgbuf);
+	}
+	usb_fill_bulk_urb(port->write_urb, port->serial->dev,
+			  usb_sndbulkpipe(port->serial->dev,
+					  port->bulk_out_endpointAddress),
+			  port->write_urb->transfer_buffer, priv->writelen + 3,
+			  iuu_rxcmd, port);
+	result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
+	spin_lock_irqsave(&priv->lock, flags);
+	priv->writelen = 0;
+	spin_unlock_irqrestore(&priv->lock, flags);
+	usb_serial_port_softint(port);
+	return result;
+}
+
+static int iuu_read_buf(struct usb_serial_port *port, int len)
+{
+	int result;
+	dbg("%s - enter", __FUNCTION__);
+
+	usb_fill_bulk_urb(port->read_urb, port->serial->dev,
+			  usb_rcvbulkpipe(port->serial->dev,
+					  port->bulk_in_endpointAddress),
+			  port->read_urb->transfer_buffer, len,
+			  read_buf_callback, port);
+	result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
+	return result;
+}
+
+static void iuu_uart_read_callback(struct urb *urb)
+{
+	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+	struct iuu_private *priv = usb_get_serial_port_data(port);
+	unsigned int flags;
+	int status;
+	int error = 0;
+	int len = 0;
+	unsigned char *data = urb->transfer_buffer;
+	priv->poll++;
+
+	dbg("%s - enter", __FUNCTION__);
+
+	if (urb->status) {
+		dbg("%s - urb->status = %d", __FUNCTION__, urb->status);
+		/* error stop all */
+		return;
+	}
+	if (data == NULL)
+		dbg("%s - data is NULL !!!", __FUNCTION__);
+
+	if (urb->actual_length == 1  && data != NULL)
+		len = (int) data[0];
+
+	if (urb->actual_length > 1) {
+		dbg("%s - urb->actual_length = %i", __FUNCTION__,
+		    urb->actual_length);
+		error = 1;
+		return;
+	}
+	/* if len > 0 call readbuf */
+
+	if (len > 0 && error == 0) {
+		dbg("%s - call read buf - len to read is %i ",
+			__FUNCTION__, len);
+		status = iuu_read_buf(port, len);
+		return;
+	}
+	/* need to update status  ? */
+	if (priv->poll > 99) {
+		status = iuu_status(port);
+		priv->poll = 0;
+		return;
+	}
+
+	/* reset waiting ? */
+
+	if (priv->reset == 1) {
+		status = iuu_reset(port, 0xC);
+		return;
+	}
+	/* Writebuf is waiting */
+	spin_lock_irqsave(&priv->lock, flags);
+	if (priv->writelen > 0) {
+		spin_unlock_irqrestore(&priv->lock, flags);
+		status = iuu_bulk_write(port);
+		return;
+	}
+	spin_unlock_irqrestore(&priv->lock, flags);
+	/* if nothing to write call again rxcmd */
+	dbg("%s - rxcmd recall", __FUNCTION__);
+	iuu_led_activity_off(urb);
+	return;
+}
+
+static int iuu_uart_write(struct usb_serial_port *port, const u8 *buf,
+			  int count)
+{
+	struct iuu_private *priv = usb_get_serial_port_data(port);
+	unsigned int flags;
+	dbg("%s - enter", __FUNCTION__);
+
+	if (count > 256)
+		return -ENOMEM;
+
+	spin_lock_irqsave(&priv->lock, flags);
+	if (priv->writelen > 0) {
+		/* buffer already filled but not commited */
+		spin_unlock_irqrestore(&priv->lock, flags);
+		return (0);
+	}
+	/* fill the buffer */
+	memcpy(priv->writebuf, buf, count);
+	priv->writelen = count;
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	return (count);
+}
+
+static void read_rxcmd_callback(struct urb *urb)
+{
+	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+	int result;
+	dbg("%s - enter", __FUNCTION__);
+
+	dbg("%s - urb->status = %d", __FUNCTION__, urb->status);
+
+	if (urb->status) {
+		dbg("%s - urb->status = %d", __FUNCTION__, urb->status);
+		/* error stop all */
+		return;
+	}
+
+	usb_fill_bulk_urb(port->read_urb, port->serial->dev,
+			  usb_rcvbulkpipe(port->serial->dev,
+					  port->bulk_in_endpointAddress),
+			  port->read_urb->transfer_buffer, 256,
+			  iuu_uart_read_callback, port);
+	result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
+	dbg("%s - submit result = %d", __FUNCTION__, result);
+	return;
+}
+
+static int iuu_uart_on(struct usb_serial_port *port)
+{
+	int status;
+	u8 *buf;
+
+	buf = kmalloc(sizeof(u8) * 4, GFP_KERNEL);
+
+	if (!buf)
+		return -ENOMEM;
+
+	buf[0] = IUU_UART_ENABLE;
+	buf[1] = (u8) ((IUU_BAUD_9600 >> 8) & 0x00FF);
+	buf[2] = (u8) (0x00FF & IUU_BAUD_9600);
+	buf[3] = (u8) (0x0F0 & IUU_TWO_STOP_BITS) | (0x07 & IUU_PARITY_EVEN);
+
+	status = bulk_immediate(port, buf, 4);
+	if (status != IUU_OPERATION_OK) {
+		dbg("%s - uart_on error", __FUNCTION__);
+		goto uart_enable_failed;
+	}
+	/*  iuu_reset() the card after iuu_uart_on() */
+	status = iuu_uart_flush(port);
+	if (status != IUU_OPERATION_OK)
+		dbg("%s - uart_flush error", __FUNCTION__);
+uart_enable_failed:
+	kfree(buf);
+	return status;
+}
+
+/*  Diables the IUU UART (a.k.a. the Phoenix voiderface) */
+static int iuu_uart_off(struct usb_serial_port *port)
+{
+	int status;
+	u8 *buf;
+	buf = kmalloc(1, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+	buf[0] = IUU_UART_DISABLE;
+
+	status = bulk_immediate(port, buf, 1);
+	if (status != IUU_OPERATION_OK)
+		dbg("%s - uart_off error", __FUNCTION__);
+
+	kfree(buf);
+	return status;
+}
+
+static int iuu_uart_baud(struct usb_serial_port *port, u32 baud,
+			 u32 *actual, u8 parity)
+{
+	int status;
+	u8 *dataout;
+	u8 DataCount = 0;
+	u8 T1Frekvens = 0;
+	u8 T1reload = 0;
+	unsigned int T1FrekvensHZ = 0;
+
+	dataout = kmalloc(sizeof(u8) * 5, GFP_KERNEL);
+
+	if (!dataout)
+		return -ENOMEM;
+
+	if (baud < 1200 || baud > 230400) {
+		kfree(dataout);
+		return IUU_INVALID_PARAMETER;
+	}
+	if (baud > 977) {
+		T1Frekvens = 3;
+		T1FrekvensHZ = 500000;
+	}
+
+	if (baud > 3906) {
+		T1Frekvens = 2;
+		T1FrekvensHZ = 2000000;
+	}
+
+	if (baud > 11718) {
+		T1Frekvens = 1;
+		T1FrekvensHZ = 6000000;
+	}
+
+	if (baud > 46875) {
+		T1Frekvens = 0;
+		T1FrekvensHZ = 24000000;
+	}
+
+	T1reload = 256 - (u8) (T1FrekvensHZ / (baud * 2));
+
+	/*  magic number here:  ENTER_FIRMWARE_UPDATE; */
+	dataout[DataCount++] = IUU_UART_ESC;
+	/*  magic number here:  CHANGE_BAUD; */
+	dataout[DataCount++] = IUU_UART_CHANGE;
+	dataout[DataCount++] = T1Frekvens;
+	dataout[DataCount++] = T1reload;
+
+	*actual = (T1FrekvensHZ / (256 - T1reload)) / 2;
+
+	switch (parity & 0x0F) {
+	case IUU_PARITY_NONE:
+		dataout[DataCount++] = 0x00;
+		break;
+	case IUU_PARITY_EVEN:
+		dataout[DataCount++] = 0x01;
+		break;
+	case IUU_PARITY_ODD:
+		dataout[DataCount++] = 0x02;
+		break;
+	case IUU_PARITY_MARK:
+		dataout[DataCount++] = 0x03;
+		break;
+	case IUU_PARITY_SPACE:
+		dataout[DataCount++] = 0x04;
+		break;
+	default:
+		kfree(dataout);
+		return IUU_INVALID_PARAMETER;
+		break;
+	}
+
+	switch (parity & 0xF0) {
+	case IUU_ONE_STOP_BIT:
+		dataout[DataCount - 1] |= IUU_ONE_STOP_BIT;
+		break;
+
+	case IUU_TWO_STOP_BITS:
+		dataout[DataCount - 1] |= IUU_TWO_STOP_BITS;
+		break;
+	default:
+		kfree(dataout);
+		return IUU_INVALID_PARAMETER;
+		break;
+	}
+
+	status = bulk_immediate(port, dataout, DataCount);
+	if (status != IUU_OPERATION_OK)
+		dbg("%s - uart_off error", __FUNCTION__);
+	kfree(dataout);
+	return status;
+}
+
+static int set_control_lines(struct usb_device *dev, u8 value)
+{
+	return 0;
+}
+
+static void iuu_close(struct usb_serial_port *port, struct file *filp)
+{
+	/* iuu_led (port,255,0,0,0); */
+	struct usb_serial *serial;
+	struct iuu_private *priv = usb_get_serial_port_data(port);
+	unsigned long flags;
+	unsigned int c_cflag;
+
+	serial = port->serial;
+	if (!serial)
+		return;
+
+	dbg("%s - port %d", __FUNCTION__, port->number);
+
+	iuu_uart_off(port);
+	if (serial->dev) {
+		if (port->tty) {
+			c_cflag = port->tty->termios->c_cflag;
+			if (c_cflag & HUPCL) {
+				/* drop DTR and RTS */
+				priv = usb_get_serial_port_data(port);
+				spin_lock_irqsave(&priv->lock, flags);
+				priv->line_control = 0;
+				spin_unlock_irqrestore(&priv->lock, flags);
+				set_control_lines(port->serial->dev, 0);
+			}
+		}
+		/* free writebuf */
+		/* 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);
+		msleep(1000);
+		/* wait one second to free all buffers */
+		iuu_led(port, 0, 0, 0xF000, 0xFF);
+		msleep(1000);
+		usb_reset_device(port->serial->dev);
+	}
+}
+
+static int iuu_open(struct usb_serial_port *port, struct file *filp)
+{
+	struct usb_serial *serial = port->serial;
+	u8 *buf;
+	int result;
+	u32 actual;
+	unsigned long flags;
+	struct iuu_private *priv = usb_get_serial_port_data(port);
+
+	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);
+
+	buf = kmalloc(10, GFP_KERNEL);
+	if (buf == NULL)
+		return -ENOMEM;
+
+	/* fixup the endpoint buffer size */
+	kfree(port->bulk_out_buffer);
+	port->bulk_out_buffer = kmalloc(512, GFP_KERNEL);
+	port->bulk_out_size = 512;
+	kfree(port->bulk_in_buffer);
+	port->bulk_in_buffer = kmalloc(512, GFP_KERNEL);
+	port->bulk_in_size = 512;
+
+	if (!port->bulk_out_buffer || !port->bulk_in_buffer) {
+		kfree(port->bulk_out_buffer);
+		kfree(port->bulk_in_buffer);
+		kfree(buf);
+		return -ENOMEM;
+	}
+
+	usb_fill_bulk_urb(port->write_urb, port->serial->dev,
+			  usb_sndbulkpipe(port->serial->dev,
+					  port->bulk_out_endpointAddress),
+			  port->bulk_out_buffer, 512,
+			  NULL, NULL);
+
+
+	usb_fill_bulk_urb(port->read_urb, port->serial->dev,
+			  usb_rcvbulkpipe(port->serial->dev,
+					  port->bulk_in_endpointAddress),
+			  port->bulk_in_buffer, 512,
+			  NULL, NULL);
+
+	/* set the termios structure */
+	spin_lock_irqsave(&priv->lock, flags);
+	if (!priv->termios_initialized) {
+		*(port->tty->termios) = tty_std_termios;
+		port->tty->termios->c_cflag = CLOCAL | CREAD | CS8 | B9600
+						| TIOCM_CTS | CSTOPB | PARENB;
+		port->tty->termios->c_lflag = 0;
+		port->tty->termios->c_oflag = 0;
+		port->tty->termios->c_iflag = 0;
+		priv->termios_initialized = 1;
+		port->tty->low_latency = 1;
+		priv->poll = 0;
+	 }
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	/* initialize writebuf */
+#define FISH(a, b, c, d) do { \
+	result = usb_control_msg(port->serial->dev,	\
+				usb_rcvctrlpipe(port->serial->dev, 0),	\
+				b, a, c, d, buf, 1, 1000); \
+	dbg("0x%x:0x%x:0x%x:0x%x  %d - %x", a, b, c, d, result, \
+				buf[0]); } while (0);
+
+#define SOUP(a, b, c, d)  do { \
+	result = usb_control_msg(port->serial->dev,	\
+				usb_sndctrlpipe(port->serial->dev, 0),	\
+				b, a, c, d, NULL, 0, 1000); \
+	dbg("0x%x:0x%x:0x%x:0x%x  %d", a, b, c, d, result); } while (0)
+
+	/*  This is not UART related but IUU USB driver related or something */
+	/*  like that. Basically no IUU will accept any commands from the USB */
+	/*  host unless it has received the following message */
+	/* sprintf(buf ,"%c%c%c%c",0x03,0x02,0x02,0x0); */
+
+	SOUP(0x03, 0x02, 0x02, 0x0);
+	kfree(buf);
+	iuu_led(port, 0xF000, 0xF000, 0, 0xFF);
+	iuu_uart_on(port);
+	if (boost < 100)
+		boost = 100;
+	switch (clockmode) {
+	case 2:		/*  3.680 Mhz */
+		iuu_clk(port, IUU_CLK_3680000 * boost / 100);
+		result =
+		    iuu_uart_baud(port, 9600 * boost / 100, &actual,
+				  IUU_PARITY_EVEN);
+		break;
+	case 3:		/*  6.00 Mhz */
+		iuu_clk(port, IUU_CLK_6000000 * boost / 100);
+		result =
+		    iuu_uart_baud(port, 16457 * boost / 100, &actual,
+				  IUU_PARITY_EVEN);
+		break;
+	default:		/*  3.579 Mhz */
+		iuu_clk(port, IUU_CLK_3579000 * boost / 100);
+		result =
+		    iuu_uart_baud(port, 9600 * boost / 100, &actual,
+				  IUU_PARITY_EVEN);
+	}
+
+	/* set the cardin cardout signals */
+	switch (cdmode) {
+	case 0:
+		iuu_cardin = 0;
+		iuu_cardout = 0;
+		break;
+	case 1:
+		iuu_cardin = TIOCM_CD;
+		iuu_cardout =  0;
+		break;
+	case 2:
+		iuu_cardin = 0;
+		iuu_cardout = TIOCM_CD;
+		break;
+	case 3:
+		iuu_cardin = TIOCM_DSR;
+		iuu_cardout = 0;
+		break;
+	case 4:
+		iuu_cardin = 0;
+		iuu_cardout = TIOCM_DSR;
+		break;
+	case 5:
+		iuu_cardin = TIOCM_CTS;
+		iuu_cardout = 0;
+		break;
+	case 6:
+		iuu_cardin = 0;
+		iuu_cardout = TIOCM_CTS;
+		break;
+	case 7:
+		iuu_cardin = TIOCM_RNG;
+		iuu_cardout = 0;
+		break;
+	case 8:
+		iuu_cardin = 0;
+		iuu_cardout = TIOCM_RNG;
+	}
+
+	iuu_uart_flush(port);
+
+	dbg("%s - initialization done", __FUNCTION__);
+
+	memset(port->write_urb->transfer_buffer, IUU_UART_RX, 1);
+	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,
+			  read_rxcmd_callback, port);
+	result = usb_submit_urb(port->write_urb, GFP_KERNEL);
+
+	if (result) {
+		dev_err(&port->dev, "%s - failed submitting read urb,"
+			" error %d\n", __FUNCTION__, result);
+		iuu_close(port, NULL);
+		return -EPROTO;
+	} else {
+		dbg("%s - rxcmd OK", __FUNCTION__);
+	}
+	return result;
+}
+
+static struct usb_serial_driver iuu_device = {
+	.driver = {
+		   .owner = THIS_MODULE,
+		   .name = "iuu_phoenix",
+		   },
+	.id_table = id_table,
+	.num_interrupt_in = NUM_DONT_CARE,
+	.num_bulk_in = 1,
+	.num_bulk_out = 1,
+	.num_ports = 1,
+	.open = iuu_open,
+	.close = iuu_close,
+	.write = iuu_uart_write,
+	.read_bulk_callback = iuu_uart_read_callback,
+	.tiocmget = iuu_tiocmget,
+	.tiocmset = iuu_tiocmset,
+	.attach = iuu_startup,
+	.shutdown = iuu_shutdown,
+};
+
+static int __init iuu_init(void)
+{
+	int retval;
+	retval = usb_serial_register(&iuu_device);
+	if (retval)
+		goto failed_usb_serial_register;
+	retval = usb_register(&iuu_driver);
+	if (retval)
+		goto failed_usb_register;
+	info(DRIVER_DESC " " DRIVER_VERSION);
+	return 0;
+failed_usb_register:
+	usb_serial_deregister(&iuu_device);
+failed_usb_serial_register:
+	return retval;
+}
+
+static void __exit iuu_exit(void)
+{
+	usb_deregister(&iuu_driver);
+	usb_serial_deregister(&iuu_device);
+}
+
+module_init(iuu_init);
+module_exit(iuu_exit);
+
+MODULE_AUTHOR("Alain Degreffe eczema@ecze.com");
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
+
+MODULE_VERSION(DRIVER_VERSION);
+module_param(debug, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "Debug enabled or not");
+
+module_param(xmas, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(xmas, "xmas color enabled or not");
+
+module_param(boost, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(boost, "overclock boost percent 100 to 500");
+
+module_param(clockmode, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(clockmode, "1=3Mhz579,2=3Mhz680,3=6Mhz");
+
+module_param(cdmode, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(cdmode, "Card detect mode 0=none, 1=CD, 2=!CD, 3=DSR, "
+		 "4=!DSR, 5=CTS, 6=!CTS, 7=RING, 8=!RING");
diff --git a/drivers/usb/serial/iuu_phoenix.h b/drivers/usb/serial/iuu_phoenix.h
new file mode 100644
index 0000000..b82630a
--- /dev/null
+++ b/drivers/usb/serial/iuu_phoenix.h
@@ -0,0 +1,122 @@
+/*
+ * Infinity Unlimited USB Phoenix driver
+ *
+ * Copyright (C) 2007 Alain Degreffe (eczema@ecze.com)
+ *
+ *
+ * Original code taken from iuutool ( Copyright (C) 2006 Juan Carlos Borrás )
+ *
+ *	This program is free software; you can redistribute it and/or modify
+ *	it under the terms of the GNU General Public License as published by
+ *	the Free Software Foundation; either version 2 of the License, or
+ *	(at your option) any later version.
+ *
+ *  And tested with help of WB Electronics
+ *
+ */
+
+#define   IUU_USB_VENDOR_ID  0x104f
+#define   IUU_USB_PRODUCT_ID  0x0004
+#define   IUU_USB_OP_TIMEOUT  0x0200
+
+/* Programmer commands */
+
+#define IUU_NO_OPERATION   0x00
+#define IUU_GET_FIRMWARE_VERSION   0x01
+#define IUU_GET_PRODUCT_NAME   0x02
+#define IUU_GET_STATE_REGISTER   0x03
+#define IUU_SET_LED   0x04
+#define IUU_WAIT_MUS   0x05
+#define IUU_WAIT_MS   0x06
+#define IUU_GET_LOADER_VERSION   0x50
+#define IUU_RST_SET   0x52
+#define IUU_RST_CLEAR   0x53
+#define IUU_SET_VCC   0x59
+#define IUU_UART_ENABLE   0x49
+#define IUU_UART_DISABLE   0x4A
+#define IUU_UART_WRITE_I2C   0x4C
+#define IUU_UART_ESC   0x5E
+#define IUU_UART_TRAP   0x54
+#define IUU_UART_TRAP_BREAK   0x5B
+#define IUU_UART_RX   0x56
+#define IUU_AVR_ON   0x21
+#define IUU_AVR_OFF   0x22
+#define IUU_AVR_1CLK   0x23
+#define IUU_AVR_RESET   0x24
+#define IUU_AVR_RESET_PC   0x25
+#define IUU_AVR_INC_PC   0x26
+#define IUU_AVR_INCN_PC   0x27
+#define IUU_AVR_PREAD   0x29
+#define IUU_AVR_PREADN   0x2A
+#define IUU_AVR_PWRITE   0x28
+#define IUU_AVR_DREAD   0x2C
+#define IUU_AVR_DREADN   0x2D
+#define IUU_AVR_DWRITE   0x2B
+#define IUU_AVR_PWRITEN   0x2E
+#define IUU_EEPROM_ON   0x37
+#define IUU_EEPROM_OFF   0x38
+#define IUU_EEPROM_WRITE   0x39
+#define IUU_EEPROM_WRITEX   0x3A
+#define IUU_EEPROM_WRITE8   0x3B
+#define IUU_EEPROM_WRITE16   0x3C
+#define IUU_EEPROM_WRITEX32   0x3D
+#define IUU_EEPROM_WRITEX64   0x3E
+#define IUU_EEPROM_READ   0x3F
+#define IUU_EEPROM_READX   0x40
+#define IUU_EEPROM_BREAD   0x41
+#define IUU_EEPROM_BREADX   0x42
+#define IUU_PIC_CMD   0x0A
+#define IUU_PIC_CMD_LOAD   0x0B
+#define IUU_PIC_CMD_READ   0x0C
+#define IUU_PIC_ON   0x0D
+#define IUU_PIC_OFF   0x0E
+#define IUU_PIC_RESET   0x16
+#define IUU_PIC_INC_PC   0x0F
+#define IUU_PIC_INCN_PC   0x10
+#define IUU_PIC_PWRITE   0x11
+#define IUU_PIC_PREAD   0x12
+#define IUU_PIC_PREADN   0x13
+#define IUU_PIC_DWRITE   0x14
+#define IUU_PIC_DREAD   0x15
+#define IUU_UART_NOP   0x00
+#define IUU_UART_CHANGE   0x02
+#define IUU_UART_TX   0x04
+#define IUU_DELAY_MS   0x06
+
+#define IUU_OPERATION_OK   0x00
+#define IUU_DEVICE_NOT_FOUND   0x01
+#define IUU_INVALID_HANDLE   0x02
+#define IUU_INVALID_PARAMETER   0x03
+#define IUU_INVALID_voidERFACE   0x04
+#define IUU_INVALID_REQUEST_LENGTH   0x05
+#define IUU_UART_NOT_ENABLED   0x06
+#define IUU_WRITE_ERROR   0x07
+#define IUU_READ_ERROR   0x08
+#define IUU_TX_ERROR   0x09
+#define IUU_RX_ERROR   0x0A
+
+#define IUU_PARITY_NONE   0x00
+#define IUU_PARITY_EVEN   0x01
+#define IUU_PARITY_ODD   0x02
+#define IUU_PARITY_MARK   0x03
+#define IUU_PARITY_SPACE   0x04
+#define IUU_SC_INSERTED   0x01
+#define IUU_VERIFY_ERROR   0x02
+#define IUU_SIM_INSERTED   0x04
+#define IUU_TWO_STOP_BITS   0x00
+#define IUU_ONE_STOP_BIT   0x20
+#define IUU_BAUD_2400   0x0398
+#define IUU_BAUD_9600   0x0298
+#define IUU_BAUD_19200   0x0164
+#define IUU_BAUD_28800   0x0198
+#define IUU_BAUD_38400   0x01B2
+#define IUU_BAUD_57600   0x0030
+#define IUU_BAUD_115200   0x0098
+#define IUU_CLK_3579000   3579000
+#define IUU_CLK_3680000   3680000
+#define IUU_CLK_6000000   6000000
+#define IUU_FULLCARD_IN   0x01
+#define IUU_DEV_ERROR   0x02
+#define IUU_MINICARD_IN   0x04
+#define IUU_VCC_5V   0x00
+#define IUU_VCC_3V   0x01
diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c
index 7c069a0..ea7bba6 100644
--- a/drivers/usb/serial/keyspan.c
+++ b/drivers/usb/serial/keyspan.c
@@ -838,7 +838,7 @@
 
 	port = (struct usb_serial_port *) urb->context;
 	tty = port->tty;
-	if (urb->actual_length) {
+	if (tty && urb->actual_length) {
 		/* 0x80 bit is error flag */
 		if ((data[0] & 0x80) == 0) {
 			/* no error on any byte */
diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c
index be9ac20..b1fa5a3 100644
--- a/drivers/usb/serial/keyspan_pda.c
+++ b/drivers/usb/serial/keyspan_pda.c
@@ -303,7 +303,7 @@
 }
 
 
-static int keyspan_pda_setbaud (struct usb_serial *serial, int baud)
+static speed_t keyspan_pda_setbaud (struct usb_serial *serial, speed_t baud)
 {
 	int rc;
 	int bindex;
@@ -319,7 +319,9 @@
 		case 38400: bindex = 7; break;
 		case 57600: bindex = 8; break;
 		case 115200: bindex = 9; break;
-		default: return -EINVAL;
+		default:
+			bindex = 5;	/* Default to 9600 */
+			baud = 9600;
 	}
 
 	/* rather than figure out how to sleep while waiting for this
@@ -334,7 +336,9 @@
 			     NULL, /* &data */
 			     0, /* size */
 			     2000); /* timeout */
-	return(rc);
+	if (rc < 0)
+		return 0;
+	return baud;
 }
 
 
@@ -366,7 +370,7 @@
 				     struct ktermios *old_termios)
 {
 	struct usb_serial *serial = port->serial;
-	unsigned int cflag = port->tty->termios->c_cflag;
+	speed_t speed;
 
 	/* cflag specifies lots of stuff: number of stop bits, parity, number
 	   of data bits, baud. What can the device actually handle?:
@@ -388,22 +392,18 @@
 
 	   For now, just do baud. */
 
-	switch (cflag & CBAUD) {
-		/* we could support more values here, just need to calculate
-		   the necessary divisors in the firmware. <asm/termbits.h>
-		   has the Bnnn constants. */
-		case B110: keyspan_pda_setbaud(serial, 110); break;
-		case B300: keyspan_pda_setbaud(serial, 300); break;
-		case B1200: keyspan_pda_setbaud(serial, 1200); break;
-		case B2400: keyspan_pda_setbaud(serial, 2400); break;
-		case B4800: keyspan_pda_setbaud(serial, 4800); break;
-		case B9600: keyspan_pda_setbaud(serial, 9600); break;
-		case B19200: keyspan_pda_setbaud(serial, 19200); break;
-		case B38400: keyspan_pda_setbaud(serial, 38400); break;
-		case B57600: keyspan_pda_setbaud(serial, 57600); break;
-		case B115200: keyspan_pda_setbaud(serial, 115200); break;
-		default: dbg("can't handle requested baud rate"); break;
+	speed = tty_get_baud_rate(port->tty);
+	speed = keyspan_pda_setbaud(serial, speed);
+
+	if (speed == 0) {
+		dbg("can't handle requested baud rate");
+		/* It hasn't changed so.. */
+		speed = tty_termios_baud_rate(old_termios);
 	}
+	/* Only speed can change so copy the old h/w parameters
+	   then encode the new speed */
+	tty_termios_copy_hw(port->tty->termios, old_termios);
+	tty_encode_baud_rate(port->tty, speed, speed);
 }
 
 
diff --git a/drivers/usb/serial/kl5kusb105.c b/drivers/usb/serial/kl5kusb105.c
index 90e3216..55736df 100644
--- a/drivers/usb/serial/kl5kusb105.c
+++ b/drivers/usb/serial/kl5kusb105.c
@@ -461,17 +461,21 @@
 
 	dbg("%s port %d", __FUNCTION__, port->number);
 
-	/* send READ_OFF */
-	rc = usb_control_msg (port->serial->dev,
-			      usb_sndctrlpipe(port->serial->dev, 0),
-			      KL5KUSB105A_SIO_CONFIGURE,
-			      USB_TYPE_VENDOR | USB_DIR_OUT,
-			      KL5KUSB105A_SIO_CONFIGURE_READ_OFF,
-			      0, /* index */
-			      NULL, 0,
-			      KLSI_TIMEOUT);
-	if (rc < 0)
-		    err("Disabling read failed (error = %d)", rc);
+	mutex_lock(&port->serial->disc_mutex);
+	if (!port->serial->disconnected) {
+		/* send READ_OFF */
+		rc = usb_control_msg (port->serial->dev,
+				      usb_sndctrlpipe(port->serial->dev, 0),
+				      KL5KUSB105A_SIO_CONFIGURE,
+				      USB_TYPE_VENDOR | USB_DIR_OUT,
+				      KL5KUSB105A_SIO_CONFIGURE_READ_OFF,
+				      0, /* index */
+				      NULL, 0,
+				      KLSI_TIMEOUT);
+		if (rc < 0)
+			err("Disabling read failed (error = %d)", rc);
+	}
+	mutex_unlock(&port->serial->disc_mutex);
 
 	/* shutdown our bulk reads and writes */
 	usb_kill_urb(port->write_urb);
diff --git a/drivers/usb/serial/kobil_sct.c b/drivers/usb/serial/kobil_sct.c
index aee4502..17b3bae 100644
--- a/drivers/usb/serial/kobil_sct.c
+++ b/drivers/usb/serial/kobil_sct.c
@@ -114,6 +114,7 @@
 	.usb_driver = 		&kobil_driver,
 	.id_table =		id_table,
 	.num_interrupt_in =	NUM_DONT_CARE,
+	.num_interrupt_out = 	NUM_DONT_CARE,
 	.num_bulk_in =		0,
 	.num_bulk_out =		0,
 	.num_ports =		1,
diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c
index 0dc99f7..fc1cea4 100644
--- a/drivers/usb/serial/mct_u232.c
+++ b/drivers/usb/serial/mct_u232.c
@@ -182,10 +182,11 @@
 /*
  * Later day 2.6.0-test kernels have new baud rates like B230400 which
  * we do not know how to support. We ignore them for the moment.
- * XXX Rate-limit the error message, it's user triggerable.
  */
-static int mct_u232_calculate_baud_rate(struct usb_serial *serial, speed_t value)
+static int mct_u232_calculate_baud_rate(struct usb_serial *serial, speed_t value, speed_t *result)
 {
+	*result = value;
+
 	if (le16_to_cpu(serial->dev->descriptor.idProduct) == MCT_U232_SITECOM_PID
 	  || le16_to_cpu(serial->dev->descriptor.idProduct) == MCT_U232_BELKIN_F5U109_PID) {
 		switch (value) {
@@ -200,11 +201,13 @@
 		case  57600: return 0x0b;
 		case 115200: return 0x0c;
 		default:
-			err("MCT USB-RS232: unsupported baudrate request 0x%x,"
-			    " using default of B9600", value);
+			*result = 9600;
 			return 0x08;
 		}
 	} else {
+		/* FIXME: Can we use any divider - should we do
+		   divider = 115200/value;
+		   real baud = 115200/divider */
 		switch (value) {
 		case 300: break;
 		case 600: break;
@@ -217,9 +220,8 @@
 		case 57600: break;
 		case 115200: break;
 		default:
-			err("MCT USB-RS232: unsupported baudrate request 0x%x,"
-			    " using default of B9600", value);
 			value = 9600;
+			*result = 9600;
 		}
 		return 115200/value;
 	}
@@ -232,16 +234,19 @@
         int rc;
         unsigned char zero_byte = 0;
         unsigned char cts_enable_byte = 0;
+        speed_t speed;
 
-	divisor = cpu_to_le32(mct_u232_calculate_baud_rate(serial, value));
+	divisor = cpu_to_le32(mct_u232_calculate_baud_rate(serial, value, &speed));
 
         rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
                              MCT_U232_SET_BAUD_RATE_REQUEST,
 			     MCT_U232_SET_REQUEST_TYPE,
                              0, 0, &divisor, MCT_U232_SET_BAUD_RATE_SIZE,
 			     WDR_TIMEOUT);
-	if (rc < 0)
+	if (rc < 0)	/*FIXME: What value speed results */
 		err("Set BAUD RATE %d failed (error = %d)", value, rc);
+	else
+		tty_encode_baud_rate(port->tty, speed, speed);
 	dbg("set_baud_rate: value: 0x%x, divisor: 0x%x", value, divisor);
 
 	/* Mimic the MCT-supplied Windows driver (version 1.21P.0104), which
@@ -482,21 +487,22 @@
 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);
+		mutex_lock(&port->serial->disc_mutex);
+		if (c_cflag & HUPCL && !port->serial->disconnected) {
+			/* drop DTR and RTS */
+			spin_lock_irq(&priv->lock);
+			priv->control_state &= ~(TIOCM_DTR | TIOCM_RTS);
+			control_state = priv->control_state;
+			spin_unlock_irq(&priv->lock);
+			mct_u232_set_modem_ctrl(port->serial, control_state);
 		}
+		mutex_unlock(&port->serial->disc_mutex);
 	}
 
 
@@ -608,7 +614,8 @@
 {
 	struct usb_serial *serial = port->serial;
 	struct mct_u232_private *priv = usb_get_serial_port_data(port);
-	unsigned int cflag = port->tty->termios->c_cflag;
+	struct ktermios *termios = port->tty->termios;
+	unsigned int cflag = termios->c_cflag;
 	unsigned int old_cflag = old_termios->c_cflag;
 	unsigned long flags;
 	unsigned int control_state;
@@ -670,6 +677,8 @@
 		break;
 	}
 
+	termios->c_cflag &= ~CMSPAR;
+
 	/* set the number of stop bits */
 	last_lcr |= (cflag & CSTOPB) ?
 		MCT_U232_STOP_BITS_2 : MCT_U232_STOP_BITS_1;
diff --git a/drivers/usb/serial/mct_u232.h b/drivers/usb/serial/mct_u232.h
index aae10c8..07b6bec 100644
--- a/drivers/usb/serial/mct_u232.h
+++ b/drivers/usb/serial/mct_u232.h
@@ -79,7 +79,7 @@
  * and "Intel solution". They are the regular MCT and "Sitecom" for us.
  * This is pointless to document in the header, see the code for the bits.
  */
-static int mct_u232_calculate_baud_rate(struct usb_serial *serial, speed_t value);
+static int mct_u232_calculate_baud_rate(struct usb_serial *serial, speed_t value, speed_t *result);
 
 /*
  * Line Control Register (LCR)
diff --git a/drivers/usb/serial/mos7720.c b/drivers/usb/serial/mos7720.c
index e02c198..40f3a01 100644
--- a/drivers/usb/serial/mos7720.c
+++ b/drivers/usb/serial/mos7720.c
@@ -564,22 +564,25 @@
 	}
 
 	/* While closing port, shutdown all bulk read, write  *
-	 * and interrupt read if they exists                  */
-	if (serial->dev) {
-		dbg("Shutdown bulk write");
-		usb_kill_urb(port->write_urb);
-		dbg("Shutdown bulk read");
-		usb_kill_urb(port->read_urb);
+	 * and interrupt read if they exists, otherwise nop   */
+	dbg("Shutdown bulk write");
+	usb_kill_urb(port->write_urb);
+	dbg("Shutdown bulk read");
+	usb_kill_urb(port->read_urb);
+
+	mutex_lock(&serial->disc_mutex);
+	/* these commands must not be issued if the device has
+	 * been disconnected */
+	if (!serial->disconnected) {
+		data = 0x00;
+		send_mos_cmd(serial, MOS_WRITE, port->number - port->serial->minor,
+			     0x04, &data);
+
+		data = 0x00;
+		send_mos_cmd(serial, MOS_WRITE, port->number - port->serial->minor,
+			     0x01, &data);
 	}
-
-	data = 0x00;
-	send_mos_cmd(serial, MOS_WRITE, port->number - port->serial->minor,
-		     0x04, &data);
-
-	data = 0x00;
-	send_mos_cmd(serial, MOS_WRITE, port->number - port->serial->minor,
-		     0x01, &data);
-
+	mutex_unlock(&serial->disc_mutex);
 	mos7720_port->open = 0;
 
 	dbg("Leaving %s", __FUNCTION__);
@@ -1040,11 +1043,6 @@
 
 	tty = mos7720_port->port->tty;
 
-	if ((!tty) || (!tty->termios)) {
-		dbg("%s - no tty structures", __FUNCTION__);
-		return;
-	}
-
 	dbg("%s: Entering ..........", __FUNCTION__);
 
 	lData = UART_LCR_WLEN8;
@@ -1175,7 +1173,10 @@
 
 	dbg("%s - baud rate = %d", __FUNCTION__, baud);
 	status = send_cmd_write_baud_rate(mos7720_port, baud);
-
+	/* FIXME: needs to write actual resulting baud back not just
+	   blindly do so */
+	if (cflag & CBAUD)
+		tty_encode_baud_rate(tty, baud, baud);
 	/* Enable Interrupts */
 	data = 0x0c;
 	send_mos_cmd(serial, MOS_WRITE, port_number, UART_IER, &data);
@@ -1214,10 +1215,6 @@
 
 	tty = port->tty;
 
-	if (!port->tty || !port->tty->termios) {
-		dbg("%s - no tty or termios", __FUNCTION__);
-		return;
-	}
 
 	if (!mos7720_port->open) {
 		dbg("%s - port not opened", __FUNCTION__);
@@ -1228,19 +1225,13 @@
 
 	cflag = tty->termios->c_cflag;
 
-	if (!cflag) {
-		printk("%s %s\n",__FUNCTION__,"cflag is NULL");
-		return;
-	}
-
-	dbg("%s - clfag %08x iflag %08x", __FUNCTION__,
+	dbg("%s - cflag %08x iflag %08x", __FUNCTION__,
 	    tty->termios->c_cflag,
 	    RELEVANT_IFLAG(tty->termios->c_iflag));
 
-	if (old_termios)
-		dbg("%s - old clfag %08x old iflag %08x", __FUNCTION__,
-		    old_termios->c_cflag,
-		    RELEVANT_IFLAG(old_termios->c_iflag));
+	dbg("%s - old cflag %08x old iflag %08x", __FUNCTION__,
+	    old_termios->c_cflag,
+	    RELEVANT_IFLAG(old_termios->c_iflag));
 
 	dbg("%s - port %d", __FUNCTION__, port->number);
 
diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c
index c29c912..869ecd3 100644
--- a/drivers/usb/serial/mos7840.c
+++ b/drivers/usb/serial/mos7840.c
@@ -1133,7 +1133,7 @@
  *	This function will block the close until one of the following:
  *		1. TX count are 0
  *		2. The mos7840 has stopped
- *		3. A timout of 3 seconds without activity has expired
+ *		3. A timeout of 3 seconds without activity has expired
  *
  ************************************************************************/
 static void mos7840_block_until_tx_empty(struct moschip_port *mos7840_port)
@@ -1161,7 +1161,7 @@
 			dbg("%s - TIMEOUT", __FUNCTION__);
 			return;
 		} else {
-			/* Reset timout value back to seconds */
+			/* Reset timeout value back to seconds */
 			wait = 30;
 		}
 	}
@@ -1275,7 +1275,7 @@
  *
  *	This function will block the close until one of the following:
  *		1. Response to our Chase comes from mos7840
- *		2. A timout of 10 seconds without activity has expired
+ *		2. A timeout of 10 seconds without activity has expired
  *		   (1K of mos7840 data @ 2400 baud ==> 4 sec to empty)
  *
  ************************************************************************/
@@ -1304,7 +1304,7 @@
 			dbg("%s - TIMEOUT", __FUNCTION__);
 			return;
 		} else {
-			/* Reset timout value back to seconds */
+			/* Reset timeout value back to seconds */
 			wait = 10;
 		}
 	}
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index d1185f5..5e8bf1b 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -180,6 +180,7 @@
 	{ USB_DEVICE(DELL_VENDOR_ID, 0x8117) },	/* Dell Wireless 5700 Mobile Broadband CDMA/EVDO ExpressCard == Novatel Merlin XV620 CDMA/EV-DO */
 	{ USB_DEVICE(DELL_VENDOR_ID, 0x8118) },	/* Dell Wireless 5510 Mobile Broadband HSDPA ExpressCard == Novatel Merlin XU870 HSDPA/3G */
 	{ USB_DEVICE(DELL_VENDOR_ID, 0x8128) },	/* Dell Wireless 5700 Mobile Broadband CDMA/EVDO Mini-Card == Novatel Expedite E720 CDMA/EV-DO */
+	{ USB_DEVICE(DELL_VENDOR_ID, 0x8136) },	/* Dell Wireless HSDPA 5520 == Novatel Expedite EU860D */
 	{ USB_DEVICE(DELL_VENDOR_ID, 0x8137) },	/* Dell Wireless HSDPA 5520 */
 	{ USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_E100A) },
 	{ USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_500A) },
@@ -640,7 +641,10 @@
 	portdata->dtr_state = 0;
 
 	if (serial->dev) {
-		option_send_setup(port);
+		mutex_lock(&serial->disc_mutex);
+		if (!serial->disconnected)
+			option_send_setup(port);
+		mutex_unlock(&serial->disc_mutex);
 
 		/* Stop reading/writing urbs */
 		for (i = 0; i < N_IN_URB; i++)
diff --git a/drivers/usb/serial/oti6858.c b/drivers/usb/serial/oti6858.c
index eea226ae..a3847d6 100644
--- a/drivers/usb/serial/oti6858.c
+++ b/drivers/usb/serial/oti6858.c
@@ -79,7 +79,7 @@
 #define PL2303_BUF_SIZE		1024
 #define PL2303_TMP_BUF_SIZE	1024
 
-struct pl2303_buf {
+struct oti6858_buf {
 	unsigned int	buf_size;
 	char		*buf_buf;
 	char		*buf_get;
@@ -161,14 +161,14 @@
 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,
+static struct oti6858_buf *oti6858_buf_alloc(unsigned int size);
+static void oti6858_buf_free(struct oti6858_buf *pb);
+static void oti6858_buf_clear(struct oti6858_buf *pb);
+static unsigned int oti6858_buf_data_avail(struct oti6858_buf *pb);
+static unsigned int oti6858_buf_space_avail(struct oti6858_buf *pb);
+static unsigned int oti6858_buf_put(struct oti6858_buf *pb, const char *buf,
 					unsigned int count);
-static unsigned int pl2303_buf_get(struct pl2303_buf *pb, char *buf,
+static unsigned int oti6858_buf_get(struct oti6858_buf *pb, char *buf,
 					unsigned int count);
 
 
@@ -203,7 +203,7 @@
 struct oti6858_private {
 	spinlock_t lock;
 
-	struct pl2303_buf *buf;
+	struct oti6858_buf *buf;
 	struct oti6858_control_pkt status;
 
 	struct {
@@ -316,7 +316,7 @@
 	}
 	priv->flags.write_urb_in_use = 1;
 
-	count = pl2303_buf_data_avail(priv->buf);
+	count = oti6858_buf_data_avail(priv->buf);
 	spin_unlock_irqrestore(&priv->lock, flags);
 	if (count > port->bulk_out_size)
 		count = port->bulk_out_size;
@@ -345,7 +345,7 @@
 	}
 
 	spin_lock_irqsave(&priv->lock, flags);
-	pl2303_buf_get(priv->buf, port->write_urb->transfer_buffer, count);
+	oti6858_buf_get(priv->buf, port->write_urb->transfer_buffer, count);
 	spin_unlock_irqrestore(&priv->lock, flags);
 
 	port->write_urb->transfer_buffer_length = count;
@@ -370,7 +370,7 @@
 		priv = kzalloc(sizeof(struct oti6858_private), GFP_KERNEL);
 		if (!priv)
 			break;
-		priv->buf = pl2303_buf_alloc(PL2303_BUF_SIZE);
+		priv->buf = oti6858_buf_alloc(PL2303_BUF_SIZE);
 		if (priv->buf == NULL) {
 			kfree(priv);
 			break;
@@ -391,7 +391,7 @@
 
 	for (--i; i >= 0; --i) {
 		priv = usb_get_serial_port_data(serial->port[i]);
-		pl2303_buf_free(priv->buf);
+		oti6858_buf_free(priv->buf);
 		kfree(priv);
 		usb_set_serial_port_data(serial->port[i], NULL);
 	}
@@ -410,7 +410,7 @@
 		return count;
 
 	spin_lock_irqsave(&priv->lock, flags);
-	count = pl2303_buf_put(priv->buf, buf, count);
+	count = oti6858_buf_put(priv->buf, buf, count);
 	spin_unlock_irqrestore(&priv->lock, flags);
 
 	return count;
@@ -425,7 +425,7 @@
 	dbg("%s(port = %d)", __FUNCTION__, port->number);
 
 	spin_lock_irqsave(&priv->lock, flags);
-	room = pl2303_buf_space_avail(priv->buf);
+	room = oti6858_buf_space_avail(priv->buf);
 	spin_unlock_irqrestore(&priv->lock, flags);
 
 	return room;
@@ -440,7 +440,7 @@
 	dbg("%s(port = %d)", __FUNCTION__, port->number);
 
 	spin_lock_irqsave(&priv->lock, flags);
-	chars = pl2303_buf_data_avail(priv->buf);
+	chars = oti6858_buf_data_avail(priv->buf);
 	spin_unlock_irqrestore(&priv->lock, flags);
 
 	return chars;
@@ -458,7 +458,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;
 	}
@@ -468,6 +468,8 @@
 		*(port->tty->termios) = tty_std_termios;
 		port->tty->termios->c_cflag = B38400 | CS8 | CREAD | HUPCL | CLOCAL;
 		priv->flags.termios_initialized = 1;
+		port->tty->termios->c_ispeed = 38400;
+		port->tty->termios->c_ospeed = 38400;
 	}
 	spin_unlock_irqrestore(&priv->lock, flags);
 
@@ -504,19 +506,14 @@
 	br = tty_get_baud_rate(port->tty);
 	if (br == 0) {
 		divisor = 0;
-	} else if (br <= OTI6858_MAX_BAUD_RATE) {
+	} else {
 		int real_br;
+		br = min(br, OTI6858_MAX_BAUD_RATE);
 
 		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;
+		tty_encode_baud_rate(port->tty, real_br, real_br);
 	}
 
 	frame_fmt &= ~FMT_STOP_BITS_MASK;
@@ -650,9 +647,9 @@
 	dbg("%s(): entering wait loop", __FUNCTION__);
 	for (;;) {
 		set_current_state(TASK_INTERRUPTIBLE);
-		if (pl2303_buf_data_avail(priv->buf) == 0
+		if (oti6858_buf_data_avail(priv->buf) == 0
 		|| timeout == 0 || signal_pending(current)
-		|| !usb_get_intfdata(port->serial->interface))	/* disconnect */
+		|| port->serial->disconnected)
 			break;
 		spin_unlock_irqrestore(&priv->lock, flags);
 		timeout = schedule_timeout(timeout);
@@ -663,7 +660,7 @@
 	dbg("%s(): after wait loop", __FUNCTION__);
 
 	/* clear out any remaining data in the buffer */
-	pl2303_buf_clear(priv->buf);
+	oti6858_buf_clear(priv->buf);
 	spin_unlock_irqrestore(&priv->lock, flags);
 
 	/* wait for characters to drain from the device */
@@ -831,21 +828,6 @@
 				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);
@@ -887,7 +869,7 @@
 	for (i = 0; i < serial->num_ports; ++i) {
 		priv = usb_get_serial_port_data(serial->port[i]);
 		if (priv) {
-			pl2303_buf_free(priv->buf);
+			oti6858_buf_free(priv->buf);
 			kfree(priv);
 			usb_set_serial_port_data(serial->port[i], NULL);
 		}
@@ -987,7 +969,7 @@
 
 		spin_lock_irqsave(&priv->lock, flags);
 		if (priv->flags.write_urb_in_use == 0
-				&& pl2303_buf_data_avail(priv->buf) != 0) {
+				&& oti6858_buf_data_avail(priv->buf) != 0) {
 			schedule_delayed_work(&priv->delayed_write_work,0);
 			resubmit = 0;
 		}
@@ -1015,9 +997,8 @@
 	struct tty_struct *tty;
 	unsigned char *data = urb->transfer_buffer;
 	unsigned long flags;
-	int i, result;
 	int status = urb->status;
-	char tty_flag;
+	int result;
 
 	dbg("%s(port = %d, status = %d)",
 				__FUNCTION__, port->number, status);
@@ -1045,27 +1026,9 @@
 		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_insert_flip_string(tty, data, urb->actual_length);
 		tty_flip_buffer_push(tty);
 	}
 
@@ -1133,18 +1096,18 @@
 
 
 /*
- * pl2303_buf_alloc
+ * oti6858_buf_alloc
  *
  * Allocate a circular buffer and all associated memory.
  */
-static struct pl2303_buf *pl2303_buf_alloc(unsigned int size)
+static struct oti6858_buf *oti6858_buf_alloc(unsigned int size)
 {
-	struct pl2303_buf *pb;
+	struct oti6858_buf *pb;
 
 	if (size == 0)
 		return NULL;
 
-	pb = kmalloc(sizeof(struct pl2303_buf), GFP_KERNEL);
+	pb = kmalloc(sizeof(struct oti6858_buf), GFP_KERNEL);
 	if (pb == NULL)
 		return NULL;
 
@@ -1161,11 +1124,11 @@
 }
 
 /*
- * pl2303_buf_free
+ * oti6858_buf_free
  *
  * Free the buffer and all associated memory.
  */
-static void pl2303_buf_free(struct pl2303_buf *pb)
+static void oti6858_buf_free(struct oti6858_buf *pb)
 {
 	if (pb) {
 		kfree(pb->buf_buf);
@@ -1174,11 +1137,11 @@
 }
 
 /*
- * pl2303_buf_clear
+ * oti6858_buf_clear
  *
  * Clear out all data in the circular buffer.
  */
-static void pl2303_buf_clear(struct pl2303_buf *pb)
+static void oti6858_buf_clear(struct oti6858_buf *pb)
 {
 	if (pb != NULL) {
 		/* equivalent to a get of all data available */
@@ -1187,12 +1150,12 @@
 }
 
 /*
- * pl2303_buf_data_avail
+ * oti6858_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)
+static unsigned int oti6858_buf_data_avail(struct oti6858_buf *pb)
 {
 	if (pb == NULL)
 		return 0;
@@ -1200,12 +1163,12 @@
 }
 
 /*
- * pl2303_buf_space_avail
+ * oti6858_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)
+static unsigned int oti6858_buf_space_avail(struct oti6858_buf *pb)
 {
 	if (pb == NULL)
 		return 0;
@@ -1213,14 +1176,14 @@
 }
 
 /*
- * pl2303_buf_put
+ * oti6858_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,
+static unsigned int oti6858_buf_put(struct oti6858_buf *pb, const char *buf,
 					unsigned int count)
 {
 	unsigned int len;
@@ -1228,7 +1191,7 @@
 	if (pb == NULL)
 		return 0;
 
-	len  = pl2303_buf_space_avail(pb);
+	len  = oti6858_buf_space_avail(pb);
 	if (count > len)
 		count = len;
 
@@ -1252,14 +1215,14 @@
 }
 
 /*
- * pl2303_buf_get
+ * oti6858_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,
+static unsigned int oti6858_buf_get(struct oti6858_buf *pb, char *buf,
 					unsigned int count)
 {
 	unsigned int len;
@@ -1267,7 +1230,7 @@
 	if (pb == NULL)
 		return 0;
 
-	len = pl2303_buf_data_avail(pb);
+	len = oti6858_buf_data_avail(pb);
 	if (count > len)
 		count = len;
 
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
index 0da1df9..ae3ec1a 100644
--- a/drivers/usb/serial/pl2303.c
+++ b/drivers/usb/serial/pl2303.c
@@ -65,6 +65,7 @@
 	{ USB_DEVICE(ITEGNO_VENDOR_ID, ITEGNO_PRODUCT_ID_2080) },
 	{ USB_DEVICE(MA620_VENDOR_ID, MA620_PRODUCT_ID) },
 	{ USB_DEVICE(RATOC_VENDOR_ID, RATOC_PRODUCT_ID) },
+	{ USB_DEVICE(RATOC_VENDOR_ID, RATOC_PRODUCT_ID_USB60F) },
 	{ USB_DEVICE(TRIPP_VENDOR_ID, TRIPP_PRODUCT_ID) },
 	{ USB_DEVICE(RADIOSHACK_VENDOR_ID, RADIOSHACK_PRODUCT_ID) },
 	{ USB_DEVICE(DCU10_VENDOR_ID, DCU10_PRODUCT_ID) },
@@ -84,9 +85,10 @@
 	{ USB_DEVICE(DATAPILOT_U2_VENDOR_ID, DATAPILOT_U2_PRODUCT_ID) },
 	{ USB_DEVICE(BELKIN_VENDOR_ID, BELKIN_PRODUCT_ID) },
 	{ USB_DEVICE(ALCOR_VENDOR_ID, ALCOR_PRODUCT_ID) },
-	{ USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_ID) },
 	{ USB_DEVICE(WS002IN_VENDOR_ID, WS002IN_PRODUCT_ID) },
 	{ USB_DEVICE(COREGA_VENDOR_ID, COREGA_PRODUCT_ID) },
+	{ USB_DEVICE(HL340_VENDOR_ID, HL340_PRODUCT_ID) },
+	{ USB_DEVICE(YCCABLE_VENDOR_ID, YCCABLE_PRODUCT_ID) },
 	{ }					/* Terminating entry */
 };
 
@@ -97,7 +99,10 @@
 	.probe =	usb_serial_probe,
 	.disconnect =	usb_serial_disconnect,
 	.id_table =	id_table,
+	.suspend =      usb_serial_suspend,
+	.resume =       usb_serial_resume,
 	.no_dynamic_id = 	1,
+	.supports_autosuspend =	1,
 };
 
 #define SET_LINE_REQUEST_TYPE		0x21
@@ -310,12 +315,39 @@
 	return count;
 }
 
+static int pl2303_vendor_read(__u16 value, __u16 index,
+		struct usb_serial *serial, unsigned char *buf)
+{
+	int res = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
+			VENDOR_READ_REQUEST, VENDOR_READ_REQUEST_TYPE,
+			value, index, buf, 1, 100);
+	dbg("0x%x:0x%x:0x%x:0x%x  %d - %x", VENDOR_READ_REQUEST_TYPE,
+			VENDOR_READ_REQUEST, value, index, res, buf[0]);
+	return res;
+}
+
+static int pl2303_vendor_write(__u16 value, __u16 index,
+		struct usb_serial *serial)
+{
+	int res = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
+			VENDOR_WRITE_REQUEST, VENDOR_WRITE_REQUEST_TYPE,
+			value, index, NULL, 0, 100);
+	dbg("0x%x:0x%x:0x%x:0x%x  %d", VENDOR_WRITE_REQUEST_TYPE,
+			VENDOR_WRITE_REQUEST, value, index, res);
+	return res;
+}
+
 static int pl2303_startup(struct usb_serial *serial)
 {
 	struct pl2303_private *priv;
 	enum pl2303_type type = type_0;
+	unsigned char *buf;
 	int i;
 
+	buf = kmalloc(10, GFP_KERNEL);
+	if (buf == NULL)
+		return -ENOMEM;
+
 	if (serial->dev->descriptor.bDeviceClass == 0x02)
 		type = type_0;
 	else if (serial->dev->descriptor.bMaxPacketSize0 == 0x40)
@@ -340,9 +372,27 @@
 		priv->type = type;
 		usb_set_serial_port_data(serial->port[i], priv);
 	}
+
+	pl2303_vendor_read(0x8484, 0, serial, buf);
+	pl2303_vendor_write(0x0404, 0, serial);
+	pl2303_vendor_read(0x8484, 0, serial, buf);
+	pl2303_vendor_read(0x8383, 0, serial, buf);
+	pl2303_vendor_read(0x8484, 0, serial, buf);
+	pl2303_vendor_write(0x0404, 1, serial);
+	pl2303_vendor_read(0x8484, 0, serial, buf);
+	pl2303_vendor_read(0x8383, 0, serial, buf);
+	pl2303_vendor_write(0, 1, serial);
+	pl2303_vendor_write(1, 0, serial);
+	if (type == HX)
+		pl2303_vendor_write(2, 0x44, serial);
+	else
+		pl2303_vendor_write(2, 0x24, serial);
+
+	kfree(buf);
 	return 0;
 
 cleanup:
+	kfree(buf);
 	for (--i; i>=0; --i) {
 		priv = usb_get_serial_port_data(serial->port[i]);
 		pl2303_buf_free(priv->buf);
@@ -582,24 +632,12 @@
 	     buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]);
 
 	if (cflag & CRTSCTS) {
-		__u16 index;
 		if (priv->type == HX)
-			index = 0x61;
+			pl2303_vendor_write(0x0, 0x61, serial);
 		else
-			index = 0x41;
-		i = usb_control_msg(serial->dev,
-				    usb_sndctrlpipe(serial->dev, 0),
-				    VENDOR_WRITE_REQUEST,
-				    VENDOR_WRITE_REQUEST_TYPE,
-				    0x0, index, NULL, 0, 100);
-		dbg("0x40:0x1:0x0:0x%x  %d", index, i);
+			pl2303_vendor_write(0x0, 0x41, serial);
 	} 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);
+		pl2303_vendor_write(0x0, 0x0, serial);
 	}
 
 	/* FIXME: Need to read back resulting baud rate */
@@ -629,7 +667,7 @@
 		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 */
+		    port->serial->disconnected)
 			break;
 		spin_unlock_irqrestore(&priv->lock, flags);
 		timeout = schedule_timeout(timeout);
@@ -678,7 +716,6 @@
 	struct ktermios tmp_termios;
 	struct usb_serial *serial = port->serial;
 	struct pl2303_private *priv = usb_get_serial_port_data(port);
-	unsigned char *buf;
 	int result;
 
 	dbg("%s -  port %d", __FUNCTION__, port->number);
@@ -686,45 +723,12 @@
 	if (priv->type != HX) {
 		usb_clear_halt(serial->dev, port->write_urb->pipe);
 		usb_clear_halt(serial->dev, port->read_urb->pipe);
-	}
-
-	buf = kmalloc(10, GFP_KERNEL);
-	if (buf==NULL)
-		return -ENOMEM;
-
-#define FISH(a,b,c,d)								\
-	result=usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev,0),	\
-			       b, a, c, d, buf, 1, 100);			\
-	dbg("0x%x:0x%x:0x%x:0x%x  %d - %x",a,b,c,d,result,buf[0]);
-
-#define SOUP(a,b,c,d)								\
-	result=usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev,0),	\
-			       b, a, c, d, NULL, 0, 100);			\
-	dbg("0x%x:0x%x:0x%x:0x%x  %d",a,b,c,d,result);
-
-	FISH (VENDOR_READ_REQUEST_TYPE, VENDOR_READ_REQUEST, 0x8484, 0);
-	SOUP (VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, 0x0404, 0);
-	FISH (VENDOR_READ_REQUEST_TYPE, VENDOR_READ_REQUEST, 0x8484, 0);
-	FISH (VENDOR_READ_REQUEST_TYPE, VENDOR_READ_REQUEST, 0x8383, 0);
-	FISH (VENDOR_READ_REQUEST_TYPE, VENDOR_READ_REQUEST, 0x8484, 0);
-	SOUP (VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, 0x0404, 1);
-	FISH (VENDOR_READ_REQUEST_TYPE, VENDOR_READ_REQUEST, 0x8484, 0);
-	FISH (VENDOR_READ_REQUEST_TYPE, VENDOR_READ_REQUEST, 0x8383, 0);
-	SOUP (VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, 0, 1);
-	SOUP (VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, 1, 0);
-
-	if (priv->type == HX) {
-		/* HX chip */
-		SOUP (VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, 2, 0x44);
-		/* reset upstream data pipes */
-          	SOUP (VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, 8, 0);
-        	SOUP (VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, 9, 0);
 	} else {
-		SOUP (VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, 2, 0x24);
+		/* reset upstream data pipes */
+		pl2303_vendor_write(8, 0, serial);
+		pl2303_vendor_write(9, 0, serial);
 	}
 
-	kfree(buf);
-
 	/* Setup termios */
 	if (port->tty) {
 		pl2303_set_termios(port, &tmp_termios);
diff --git a/drivers/usb/serial/pl2303.h b/drivers/usb/serial/pl2303.h
index d31f5d2..237a41f 100644
--- a/drivers/usb/serial/pl2303.h
+++ b/drivers/usb/serial/pl2303.h
@@ -35,6 +35,7 @@
 
 #define RATOC_VENDOR_ID		0x0584
 #define RATOC_PRODUCT_ID	0xb000
+#define RATOC_PRODUCT_ID_USB60F	0xb020
 
 #define TRIPP_VENDOR_ID		0x2478
 #define TRIPP_PRODUCT_ID	0x2008
@@ -96,10 +97,6 @@
 #define ALCOR_VENDOR_ID		0x058F
 #define ALCOR_PRODUCT_ID	0x9720
 
-/* Huawei E620 UMTS/HSDPA card (ID: 12d1:1001) */
-#define HUAWEI_VENDOR_ID	0x12d1
-#define HUAWEI_PRODUCT_ID	0x1001
-
 /* Willcom WS002IN Data Driver (by NetIndex Inc.) */
 #define WS002IN_VENDOR_ID	0x11f6
 #define WS002IN_PRODUCT_ID	0x2001
@@ -107,3 +104,11 @@
 /* Corega CG-USBRS232R Serial Adapter */
 #define COREGA_VENDOR_ID	0x07aa
 #define COREGA_PRODUCT_ID	0x002a
+
+/* HL HL-340 (ID: 4348:5523) */
+#define HL340_VENDOR_ID		0x4348
+#define HL340_PRODUCT_ID	0x5523
+
+/* Y.C. Cable U.S.A., Inc - USB to RS-232 */
+#define YCCABLE_VENDOR_ID	0x05ad
+#define YCCABLE_PRODUCT_ID	0x0fba
diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c
index c295d04..4c925e3 100644
--- a/drivers/usb/serial/sierra.c
+++ b/drivers/usb/serial/sierra.c
@@ -1,7 +1,7 @@
 /*
   USB Driver for Sierra Wireless
 
-  Copyright (C) 2006, 2007  Kevin Lloyd <linux@sierrawireless.com>
+  Copyright (C) 2006, 2007, 2008  Kevin Lloyd <linux@sierrawireless.com>
 
   IMPORTANT DISCLAIMER: This driver is not commercially supported by
   Sierra Wireless. Use at your own risk.
@@ -14,7 +14,7 @@
   Whom based his on the Keyspan driver by Hugh Blemings <hugh@blemings.org>
 */
 
-#define DRIVER_VERSION "v.1.2.5b"
+#define DRIVER_VERSION "v.1.2.7"
 #define DRIVER_AUTHOR "Kevin Lloyd <linux@sierrawireless.com>"
 #define DRIVER_DESC "USB Driver for Sierra Wireless USB modems"
 
@@ -26,10 +26,12 @@
 #include <linux/module.h>
 #include <linux/usb.h>
 #include <linux/usb/serial.h>
+#include <linux/usb/ch9.h>
 
+#define SWIMS_USB_REQUEST_SetPower	0x00
+#define SWIMS_USB_REQUEST_SetNmea	0x07
 #define SWIMS_USB_REQUEST_SetMode	0x0B
-#define SWIMS_USB_REQUEST_TYPE_SetMode	0x40
-#define SWIMS_USB_INDEX_SetMode		0x0000
+#define SWIMS_USB_REQUEST_TYPE_VSC_SET	0x40
 #define SWIMS_SET_MODE_Modem		0x0001
 
 /* per port private data */
@@ -38,6 +40,8 @@
 #define IN_BUFLEN	4096
 
 static int debug;
+static int nmea;
+static int truinstall = 1;
 
 enum devicetype {
 	DEVICE_3_PORT =		0,
@@ -50,48 +54,96 @@
 	int result;
 	dev_dbg(&udev->dev, "%s", "SET POWER STATE\n");
 	result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
-			0x00,			/* __u8 request      */
-			0x40,			/* __u8 request type */
-			swiState,		/* __u16 value       */
-			0,			/* __u16 index       */
-			NULL,			/* void *data        */
-			0,			/* __u16 size 	     */
-			USB_CTRL_SET_TIMEOUT);	/* int timeout 	     */
+			SWIMS_USB_REQUEST_SetPower,	/* __u8 request      */
+			SWIMS_USB_REQUEST_TYPE_VSC_SET,	/* __u8 request type */
+			swiState,			/* __u16 value       */
+			0,				/* __u16 index       */
+			NULL,				/* void *data        */
+			0,				/* __u16 size 	     */
+			USB_CTRL_SET_TIMEOUT);		/* int timeout 	     */
 	return result;
 }
 
-static int sierra_set_ms_mode(struct usb_device *udev, __u16 eSocMode)
+static int sierra_set_ms_mode(struct usb_device *udev, __u16 eSWocMode)
 {
 	int result;
 	dev_dbg(&udev->dev, "%s", "DEVICE MODE SWITCH\n");
 	result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
 			SWIMS_USB_REQUEST_SetMode,	/* __u8 request      */
-			SWIMS_USB_REQUEST_TYPE_SetMode,	/* __u8 request type */
-			eSocMode,			/* __u16 value       */
-			SWIMS_USB_INDEX_SetMode,	/* __u16 index       */
+			SWIMS_USB_REQUEST_TYPE_VSC_SET,	/* __u8 request type */
+			eSWocMode,			/* __u16 value       */
+			0x0000,				/* __u16 index       */
 			NULL,				/* void *data        */
 			0,				/* __u16 size 	     */
 			USB_CTRL_SET_TIMEOUT);		/* int timeout       */
 	return result;
 }
 
-static int sierra_probe(struct usb_interface *iface,
-			const struct usb_device_id *id)
+static int sierra_vsc_set_nmea(struct usb_device *udev, __u16 enable)
 {
 	int result;
-	struct usb_device *udev;
+	dev_dbg(&udev->dev, "%s", "NMEA Enable sent\n");
+	result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+			SWIMS_USB_REQUEST_SetNmea,	/* __u8 request      */
+			SWIMS_USB_REQUEST_TYPE_VSC_SET,	/* __u8 request type */
+			enable,				/* __u16 value       */
+			0x0000,				/* __u16 index       */
+			NULL,				/* void *data        */
+			0,				/* __u16 size 	     */
+			USB_CTRL_SET_TIMEOUT);		/* int timeout       */
+	return result;
+}
 
-	udev = usb_get_dev(interface_to_usbdev(iface));
+static int sierra_calc_num_ports(struct usb_serial *serial)
+{
+	int result;
+	int *num_ports = usb_get_serial_data(serial);
 
-	/* Check if in installer mode */
-	if (id->driver_info == DEVICE_INSTALLER) {
-		dev_dbg(&udev->dev, "%s", "FOUND DEVICE(SW)\n");
-		result = sierra_set_ms_mode(udev, SWIMS_SET_MODE_Modem);
-		/*We do not want to bind to the device when in installer mode*/
-		return -EIO;
+	result = *num_ports;
+
+	if (result) {
+		kfree(num_ports);
+		usb_set_serial_data(serial, NULL);
 	}
 
-	return usb_serial_probe(iface, id);
+	return result;
+}
+
+static int sierra_probe(struct usb_serial *serial,
+			const struct usb_device_id *id)
+{
+	int result = 0;
+	struct usb_device *udev;
+	int *num_ports;
+	u8 ifnum;
+
+	num_ports = kmalloc(sizeof(*num_ports), GFP_KERNEL);
+	if (!num_ports)
+		return -ENOMEM;
+
+	ifnum = serial->interface->cur_altsetting->desc.bInterfaceNumber;
+	udev = serial->dev;
+
+	/* Check if in installer mode */
+	if (truinstall && id->driver_info == DEVICE_INSTALLER) {
+		dev_dbg(&udev->dev, "%s", "FOUND TRU-INSTALL DEVICE(SW)\n");
+		result = sierra_set_ms_mode(udev, SWIMS_SET_MODE_Modem);
+		/* Don't bind to the device when in installer mode */
+		kfree(num_ports);
+		return -EIO;
+	} else if (id->driver_info == DEVICE_1_PORT)
+		*num_ports = 1;
+	else if (ifnum == 0x99)
+		*num_ports = 0;
+	else
+		*num_ports = 3;
+	/*
+	 * save off our num_ports info so that we can use it in the
+	 * calc_num_ports callback
+	 */
+	usb_set_serial_data(serial, (void *)num_ports);
+
+	return result;
 }
 
 static struct usb_device_id id_table [] = {
@@ -104,6 +156,7 @@
 	{ USB_DEVICE(0x1199, 0x0019) },	/* Sierra Wireless AirCard 595 */
 	{ USB_DEVICE(0x1199, 0x0021) },	/* Sierra Wireless AirCard 597E */
 	{ USB_DEVICE(0x1199, 0x0120) },	/* Sierra Wireless USB Dongle 595U */
+	{ USB_DEVICE(0x1199, 0x0023) },	/* Sierra Wireless AirCard */
 
 	{ USB_DEVICE(0x1199, 0x6802) },	/* Sierra Wireless MC8755 */
 	{ USB_DEVICE(0x1199, 0x6804) },	/* Sierra Wireless MC8755 */
@@ -117,56 +170,29 @@
 	{ USB_DEVICE(0x1199, 0x6851) },	/* Sierra Wireless AirCard 881 */
 	{ USB_DEVICE(0x1199, 0x6852) },	/* Sierra Wireless AirCard 880 E */
 	{ USB_DEVICE(0x1199, 0x6853) },	/* Sierra Wireless AirCard 881 E */
+	{ USB_DEVICE(0x1199, 0x6855) },	/* Sierra Wireless AirCard 880 U */
+	{ USB_DEVICE(0x1199, 0x6856) },	/* Sierra Wireless AirCard 881 U */
+
+	{ USB_DEVICE(0x1199, 0x6468) }, /* Sierra Wireless MP3G - EVDO */
+	{ USB_DEVICE(0x1199, 0x6469) }, /* Sierra Wireless MP3G - UMTS/HSPA */
 
 	{ USB_DEVICE(0x1199, 0x0112), .driver_info = DEVICE_1_PORT }, /* Sierra Wireless AirCard 580 */
 	{ USB_DEVICE(0x0F3D, 0x0112), .driver_info = DEVICE_1_PORT }, /* Airprime/Sierra PC 5220 */
+	{ USB_DEVICE(0x05C6, 0x6613), .driver_info = DEVICE_1_PORT }, /* Onda H600/ZTE MF330 */
 
 	{ USB_DEVICE(0x1199, 0x0FFF), .driver_info = DEVICE_INSTALLER},
 	{ }
 };
 MODULE_DEVICE_TABLE(usb, id_table);
 
-static struct usb_device_id id_table_1port [] = {
-	{ USB_DEVICE(0x1199, 0x0112) }, /* Sierra Wireless AirCard 580 */
-	{ USB_DEVICE(0x0F3D, 0x0112) }, /* AirPrime/Sierra PC 5220 */
-	{ }
-};
-
-static struct usb_device_id id_table_3port [] = {
-	{ USB_DEVICE(0x1199, 0x0017) },	/* Sierra Wireless EM5625 */
-	{ USB_DEVICE(0x1199, 0x0018) },	/* Sierra Wireless MC5720 */
-	{ USB_DEVICE(0x0f30, 0x1b1d) },	/* Sierra Wireless MC5720 */
-	{ USB_DEVICE(0x1199, 0x0218) },	/* Sierra Wireless MC5720 */
-	{ USB_DEVICE(0x1199, 0x0020) },	/* Sierra Wireless MC5725 */
-	{ USB_DEVICE(0x1199, 0x0220) },	/* Sierra Wireless MC5725 */
-	{ USB_DEVICE(0x1199, 0x0019) },	/* Sierra Wireless AirCard 595 */
-	{ USB_DEVICE(0x1199, 0x0021) },	/* Sierra Wireless AirCard 597E */
-	{ USB_DEVICE(0x1199, 0x0120) },	/* Sierra Wireless USB Dongle 595U*/
-
-	{ USB_DEVICE(0x1199, 0x6802) },	/* Sierra Wireless MC8755 */
-	{ USB_DEVICE(0x1199, 0x6804) },	/* Sierra Wireless MC8755 */
-	{ USB_DEVICE(0x1199, 0x6803) },	/* Sierra Wireless MC8765 */
-	{ USB_DEVICE(0x1199, 0x6812) },	/* Sierra Wireless MC8775 & AC 875U */
-	{ USB_DEVICE(0x1199, 0x6813) },	/* Sierra Wireless MC8775 (Thinkpad internal) */
-	{ USB_DEVICE(0x1199, 0x6820) },	/* Sierra Wireless AirCard 875 */
-	{ USB_DEVICE(0x1199, 0x6832) },	/* Sierra Wireless MC8780*/
-	{ USB_DEVICE(0x1199, 0x6833) },	/* Sierra Wireless MC8781*/
-	{ USB_DEVICE(0x1199, 0x6850) },	/* Sierra Wireless AirCard 880 */
-	{ USB_DEVICE(0x1199, 0x6851) },	/* Sierra Wireless AirCard 881 */
-	{ USB_DEVICE(0x1199, 0x6852) },	/* Sierra Wireless AirCard 880E */
-	{ USB_DEVICE(0x1199, 0x6853) },	/* Sierra Wireless AirCard 881E */
-	{ }
-};
-
 static struct usb_driver sierra_driver = {
 	.name       = "sierra",
-	.probe      = sierra_probe,
+	.probe      = usb_serial_probe,
 	.disconnect = usb_serial_disconnect,
 	.id_table   = id_table,
 	.no_dynamic_id = 	1,
 };
 
-
 struct sierra_port_private {
 	spinlock_t lock;	/* lock the structure */
 	int outstanding_urbs;	/* number of out urbs in flight */
@@ -188,6 +214,7 @@
 {
 	struct usb_serial *serial = port->serial;
 	struct sierra_port_private *portdata;
+	__u16 interface = 0;
 
 	dbg("%s", __FUNCTION__);
 
@@ -200,9 +227,18 @@
 		if (portdata->rts_state)
 			val |= 0x02;
 
+		/* Determine which port is targeted */
+		if (port->bulk_out_endpointAddress == 2)
+			interface = 0;
+		else if (port->bulk_out_endpointAddress == 4)
+			interface = 1;
+		else if (port->bulk_out_endpointAddress == 5)
+			interface = 2;
+
 		return usb_control_msg(serial->dev,
 				usb_rcvctrlpipe(serial->dev, 0),
-				0x22,0x21,val,0,NULL,0,USB_CTRL_SET_TIMEOUT);
+				0x22, 0x21, val, interface,
+				NULL, 0, USB_CTRL_SET_TIMEOUT);
 	}
 
 	return 0;
@@ -561,7 +597,10 @@
 	portdata->dtr_state = 0;
 
 	if (serial->dev) {
-		sierra_send_setup(port);
+		mutex_lock(&serial->disc_mutex);
+		if (!serial->disconnected)
+			sierra_send_setup(port);
+		mutex_unlock(&serial->disc_mutex);
 
 		/* Stop reading/writing urbs */
 		for (i = 0; i < N_IN_URB; i++)
@@ -583,9 +622,13 @@
 
 	dbg("%s", __FUNCTION__);
 
-	/*Set Device mode to D0 */
+	/* Set Device mode to D0 */
 	sierra_set_power_state(serial->dev, 0x0000);
 
+	/* Check NMEA and set */
+	if (nmea)
+		sierra_vsc_set_nmea(serial->dev, 1);
+
 	/* Now setup per port private data */
 	for (i = 0; i < serial->num_ports; i++) {
 		port = serial->port[i];
@@ -646,47 +689,19 @@
 	}
 }
 
-static struct usb_serial_driver sierra_1port_device = {
+static struct usb_serial_driver sierra_device = {
 	.driver = {
 		.owner =	THIS_MODULE,
 		.name =		"sierra1",
 	},
-	.description       = "Sierra USB modem (1 port)",
-	.id_table          = id_table_1port,
+	.description       = "Sierra USB modem",
+	.id_table          = id_table,
 	.usb_driver        = &sierra_driver,
 	.num_interrupt_in  = NUM_DONT_CARE,
-	.num_bulk_in       = 1,
-	.num_bulk_out      = 1,
-	.num_ports         = 1,
-	.open              = sierra_open,
-	.close             = sierra_close,
-	.write             = sierra_write,
-	.write_room        = sierra_write_room,
-	.chars_in_buffer   = sierra_chars_in_buffer,
-	.throttle          = sierra_rx_throttle,
-	.unthrottle        = sierra_rx_unthrottle,
-	.ioctl             = sierra_ioctl,
-	.set_termios       = sierra_set_termios,
-	.break_ctl         = sierra_break_ctl,
-	.tiocmget          = sierra_tiocmget,
-	.tiocmset          = sierra_tiocmset,
-	.attach            = sierra_startup,
-	.shutdown          = sierra_shutdown,
-	.read_int_callback = sierra_instat_callback,
-};
-
-static struct usb_serial_driver sierra_3port_device = {
-	.driver = {
-		.owner =	THIS_MODULE,
-		.name =		"sierra3",
-	},
-	.description       = "Sierra USB modem (3 port)",
-	.id_table          = id_table_3port,
-	.usb_driver        = &sierra_driver,
-	.num_interrupt_in  = NUM_DONT_CARE,
-	.num_bulk_in       = 3,
-	.num_bulk_out      = 3,
-	.num_ports         = 3,
+	.num_bulk_in       = NUM_DONT_CARE,
+	.num_bulk_out      = NUM_DONT_CARE,
+	.calc_num_ports	   = sierra_calc_num_ports,
+	.probe		   = sierra_probe,
 	.open              = sierra_open,
 	.close             = sierra_close,
 	.write             = sierra_write,
@@ -708,12 +723,9 @@
 static int __init sierra_init(void)
 {
 	int retval;
-	retval = usb_serial_register(&sierra_1port_device);
+	retval = usb_serial_register(&sierra_device);
 	if (retval)
-		goto failed_1port_device_register;
-	retval = usb_serial_register(&sierra_3port_device);
-	if (retval)
-		goto failed_3port_device_register;
+		goto failed_device_register;
 
 
 	retval = usb_register(&sierra_driver);
@@ -725,18 +737,15 @@
 	return 0;
 
 failed_driver_register:
-	usb_serial_deregister(&sierra_3port_device);
-failed_3port_device_register:
-	usb_serial_deregister(&sierra_1port_device);
-failed_1port_device_register:
+	usb_serial_deregister(&sierra_device);
+failed_device_register:
 	return retval;
 }
 
 static void __exit sierra_exit(void)
 {
 	usb_deregister (&sierra_driver);
-	usb_serial_deregister(&sierra_1port_device);
-	usb_serial_deregister(&sierra_3port_device);
+	usb_serial_deregister(&sierra_device);
 }
 
 module_init(sierra_init);
@@ -747,6 +756,12 @@
 MODULE_VERSION(DRIVER_VERSION);
 MODULE_LICENSE("GPL");
 
+module_param(truinstall, bool, 0);
+MODULE_PARM_DESC(truinstall, "TRU-Install support");
+
+module_param(nmea, bool, 0);
+MODULE_PARM_DESC(nmea, "NMEA streaming");
+
 #ifdef CONFIG_USB_DEBUG
 module_param(debug, bool, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(debug, "Debug messages");
diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c
index 1f01494..b517f93 100644
--- a/drivers/usb/serial/ti_usb_3410_5052.c
+++ b/drivers/usb/serial/ti_usb_3410_5052.c
@@ -80,6 +80,7 @@
 #include <linux/ioctl.h>
 #include <linux/serial.h>
 #include <linux/circ_buf.h>
+#include <linux/mutex.h>
 #include <asm/uaccess.h>
 #include <asm/semaphore.h>
 #include <linux/usb.h>
@@ -139,7 +140,7 @@
 };
 
 struct ti_device {
-	struct semaphore	td_open_close_sem;
+	struct mutex		td_open_close_lock;
 	int			td_open_port_count;
 	struct usb_serial	*td_serial;
 	int			td_is_3410;
@@ -424,7 +425,7 @@
 		dev_err(&dev->dev, "%s - out of memory\n", __FUNCTION__);
 		return -ENOMEM;
 	}
-	sema_init(&tdev->td_open_close_sem, 1);
+	mutex_init(&tdev->td_open_close_lock);
 	tdev->td_serial = serial;
 	usb_set_serial_data(serial, tdev);
 
@@ -547,7 +548,7 @@
 	tdev = tport->tp_tdev;
 
 	/* only one open on any port on a device at a time */
-	if (down_interruptible(&tdev->td_open_close_sem))
+	if (mutex_lock_interruptible(&tdev->td_open_close_lock))
 		return -ERESTARTSYS;
 
 	if (port->tty)
@@ -568,7 +569,7 @@
 		if (!urb) {
 			dev_err(&port->dev, "%s - no interrupt urb\n", __FUNCTION__);
 			status = -EINVAL;
-			goto up_sem;
+			goto release_lock;
 		}
 		urb->complete = ti_interrupt_callback;
 		urb->context = tdev;
@@ -576,11 +577,11 @@
 		status = usb_submit_urb(urb, GFP_KERNEL);
 		if (status) {
 			dev_err(&port->dev, "%s - submit interrupt urb failed, %d\n", __FUNCTION__, status);
-			goto up_sem;
+			goto release_lock;
 		}
 	}
 
-	ti_set_termios(port, NULL);
+	ti_set_termios(port, port->tty->termios);
 
 	dbg("%s - sending TI_OPEN_PORT", __FUNCTION__);
 	status = ti_command_out_sync(tdev, TI_OPEN_PORT,
@@ -617,7 +618,7 @@
 	usb_clear_halt(dev, port->write_urb->pipe);
 	usb_clear_halt(dev, port->read_urb->pipe);
 
-	ti_set_termios(port, NULL);
+	ti_set_termios(port, port->tty->termios);
 
 	dbg("%s - sending TI_OPEN_PORT (2)", __FUNCTION__);
 	status = ti_command_out_sync(tdev, TI_OPEN_PORT,
@@ -656,13 +657,13 @@
 	tport->tp_is_open = 1;
 	++tdev->td_open_port_count;
 
-	goto up_sem;
+	goto release_lock;
 
 unlink_int_urb:
 	if (tdev->td_open_port_count == 0)
 		usb_kill_urb(port->serial->port[0]->interrupt_in_urb);
-up_sem:
-	up(&tdev->td_open_close_sem);
+release_lock:
+	mutex_unlock(&tdev->td_open_close_lock);
 	dbg("%s - exit %d", __FUNCTION__, status);
 	return status;
 }
@@ -674,7 +675,7 @@
 	struct ti_port *tport;
 	int port_number;
 	int status;
-	int do_up;
+	int do_unlock;
 
 	dbg("%s - port %d", __FUNCTION__, port->number);
 			 
@@ -699,16 +700,16 @@
 	if (status)
 		dev_err(&port->dev, "%s - cannot send close port command, %d\n" , __FUNCTION__, status);
 
-	/* if down is interrupted, continue anyway */
-	do_up = !down_interruptible(&tdev->td_open_close_sem);
+	/* if mutex_lock is interrupted, continue anyway */
+	do_unlock = !mutex_lock_interruptible(&tdev->td_open_close_lock);
 	--tport->tp_tdev->td_open_port_count;
 	if (tport->tp_tdev->td_open_port_count <= 0) {
 		/* last port is closed, shut down interrupt urb */
 		usb_kill_urb(port->serial->port[0]->interrupt_in_urb);
 		tport->tp_tdev->td_open_port_count = 0;
 	}
-	if (do_up)
-		up(&tdev->td_open_close_sem);
+	if (do_unlock)
+		mutex_unlock(&tdev->td_open_close_lock);
 
 	dbg("%s - exit", __FUNCTION__);
 }
@@ -896,24 +897,11 @@
 
 	dbg("%s - port %d", __FUNCTION__, port->number);
 
-	if (!tty || !tty->termios) {
-		dbg("%s - no tty or termios", __FUNCTION__);
-		return;
-	}
-
 	cflag = tty->termios->c_cflag;
 	iflag = tty->termios->c_iflag;
 
-	if (old_termios && cflag == old_termios->c_cflag
-	&& iflag == old_termios->c_iflag) {
-		dbg("%s - nothing to change", __FUNCTION__);
-		return;
-	}
-
-	dbg("%s - clfag %08x, iflag %08x", __FUNCTION__, cflag, iflag);
-
-	if (old_termios)
-		dbg("%s - old clfag %08x, old iflag %08x", __FUNCTION__, old_termios->c_cflag, old_termios->c_iflag);
+	dbg("%s - cflag %08x, iflag %08x", __FUNCTION__, cflag, iflag);
+	dbg("%s - old clfag %08x, old iflag %08x", __FUNCTION__, old_termios->c_cflag, old_termios->c_iflag);
 
 	if (tport == NULL)
 		return;
@@ -947,6 +935,9 @@
 			    break;
 	}
 
+	/* CMSPAR isn't supported by this driver */
+	tty->termios->c_cflag &= ~CMSPAR;
+
 	if (cflag & PARENB) {
 		if (cflag & PARODD) {
 			config->wFlags |= TI_UART_ENABLE_PARITY_CHECKING;
@@ -989,12 +980,17 @@
 	}
 
 	baud = tty_get_baud_rate(tty);
-	if (!baud) baud = 9600;
+	if (!baud)
+		baud = 9600;
 	if (tport->tp_tdev->td_is_3410)
 		config->wBaudRate = (__u16)((923077 + baud/2) / baud);
 	else
 		config->wBaudRate = (__u16)((461538 + baud/2) / baud);
 
+	/* FIXME: Should calculate resulting baud here and report it back */
+	if ((cflag & CBAUD) != B0)
+		tty_encode_baud_rate(tty, baud, baud);
+
 	dbg("%s - BaudRate=%d, wBaudRate=%d, wFlags=0x%04X, bDataBits=%d, bParity=%d, bStopBits=%d, cXon=%d, cXoff=%d, bUartMode=%d",
 	__FUNCTION__, baud, config->wBaudRate, config->wFlags, config->bDataBits, config->bParity, config->bStopBits, config->cXon, config->cXoff, config->bUartMode);
 
@@ -1497,11 +1493,10 @@
 	struct ti_device *tdev = tport->tp_tdev;
 	struct usb_serial_port *port = tport->tp_port;
 	wait_queue_t wait;
-	unsigned long flags;
 
 	dbg("%s - port %d", __FUNCTION__, port->number);
 
-	spin_lock_irqsave(&tport->tp_lock, flags);
+	spin_lock_irq(&tport->tp_lock);
 
 	/* wait for data to drain from the buffer */
 	tdev->td_urb_error = 0;
@@ -1512,11 +1507,11 @@
 		if (ti_buf_data_avail(tport->tp_write_buf) == 0
 		|| timeout == 0 || signal_pending(current)
 		|| tdev->td_urb_error
-		|| !usb_get_intfdata(port->serial->interface))  /* disconnect */
+		|| port->serial->disconnected)  /* disconnect */
 			break;
-		spin_unlock_irqrestore(&tport->tp_lock, flags);
+		spin_unlock_irq(&tport->tp_lock);
 		timeout = schedule_timeout(timeout);
-		spin_lock_irqsave(&tport->tp_lock, flags);
+		spin_lock_irq(&tport->tp_lock);
 	}
 	set_current_state(TASK_RUNNING);
 	remove_wait_queue(&tport->tp_write_wait, &wait);
@@ -1525,19 +1520,23 @@
 	if (flush)
 		ti_buf_clear(tport->tp_write_buf);
 
-	spin_unlock_irqrestore(&tport->tp_lock, flags);
+	spin_unlock_irq(&tport->tp_lock);
 
+	mutex_lock(&port->serial->disc_mutex);
 	/* wait for data to drain from the device */
 	/* wait for empty tx register, plus 20 ms */
 	timeout += jiffies;
 	tport->tp_lsr &= ~TI_LSR_TX_EMPTY;
 	while ((long)(jiffies - timeout) < 0 && !signal_pending(current)
 	&& !(tport->tp_lsr&TI_LSR_TX_EMPTY) && !tdev->td_urb_error
-	&& usb_get_intfdata(port->serial->interface)) {  /* not disconnected */
+	&& !port->serial->disconnected) {
 		if (ti_get_lsr(tport))
 			break;
+		mutex_unlock(&port->serial->disc_mutex);
 		msleep_interruptible(20);
+		mutex_lock(&port->serial->disc_mutex);
 	}
+	mutex_unlock(&port->serial->disc_mutex);
 }
 
 
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
index 497e29a..3ce98e8 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -225,16 +225,21 @@
 			goto bailout_mutex_unlock;
 		}
 
+		retval = usb_autopm_get_interface(serial->interface);
+		if (retval)
+			goto bailout_module_put;
 		/* only call the device specific open if this 
 		 * is the first time the port is opened */
 		retval = serial->type->open(port, filp);
 		if (retval)
-			goto bailout_module_put;
+			goto bailout_interface_put;
 	}
 
 	mutex_unlock(&port->mutex);
 	return 0;
 
+bailout_interface_put:
+	usb_autopm_put_interface(serial->interface);
 bailout_module_put:
 	module_put(serial->type->driver.owner);
 bailout_mutex_unlock:
@@ -264,17 +269,21 @@
 	}
 
 	--port->open_count;
-	if (port->open_count == 0) {
+	if (port->open_count == 0)
 		/* only call the device specific close if this 
 		 * port is being closed by the last owner */
 		port->serial->type->close(port, filp);
 
+	if (port->open_count == (port->console? 1 : 0)) {
 		if (port->tty) {
 			if (port->tty->driver_data)
 				port->tty->driver_data = NULL;
 			port->tty = NULL;
 		}
+	}
 
+	if (port->open_count == 0) {
+		usb_autopm_put_interface(port->serial->interface);
 		module_put(port->serial->type->driver.owner);
 	}
 
@@ -625,6 +634,7 @@
 	serial->type = driver;
 	serial->interface = interface;
 	kref_init(&serial->kref);
+	mutex_init(&serial->disc_mutex);
 
 	return serial;
 }
@@ -1080,20 +1090,22 @@
 	usb_serial_console_disconnect(serial);
 	dbg ("%s", __FUNCTION__);
 
+	mutex_lock(&serial->disc_mutex);
 	usb_set_intfdata (interface, NULL);
-	if (serial) {
-		for (i = 0; i < serial->num_ports; ++i) {
-			port = serial->port[i];
-			if (port) {
-				if (port->tty)
-					tty_hangup(port->tty);
-				kill_traffic(port);
-			}
+	/* must set a flag, to signal subdrivers */
+	serial->disconnected = 1;
+	for (i = 0; i < serial->num_ports; ++i) {
+		port = serial->port[i];
+		if (port) {
+			if (port->tty)
+				tty_hangup(port->tty);
+			kill_traffic(port);
 		}
-		/* let the last holder of this object 
-		 * cause it to be cleaned up */
-		usb_serial_put(serial);
 	}
+	/* let the last holder of this object
+	 * cause it to be cleaned up */
+	mutex_unlock(&serial->disc_mutex);
+	usb_serial_put(serial);
 	dev_info(dev, "device disconnected\n");
 }
 
@@ -1103,9 +1115,6 @@
 	struct usb_serial_port *port;
 	int i, r = 0;
 
-	if (!serial) /* device has been disconnected */
-		return 0;
-
 	for (i = 0; i < serial->num_ports; ++i) {
 		port = serial->port[i];
 		if (port)
@@ -1253,6 +1262,7 @@
 	set_to_generic_if_null(device, read_bulk_callback);
 	set_to_generic_if_null(device, write_bulk_callback);
 	set_to_generic_if_null(device, shutdown);
+	set_to_generic_if_null(device, resume);
 }
 
 int usb_serial_register(struct usb_serial_driver *driver) /* must be called with BKL held */
diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c
index 7ee087f..22b3f78 100644
--- a/drivers/usb/serial/visor.c
+++ b/drivers/usb/serial/visor.c
@@ -349,16 +349,20 @@
 	usb_kill_urb(port->read_urb);
 	usb_kill_urb(port->interrupt_in_urb);
 
-	/* Try to send shutdown message, if the device is gone, this will just fail. */
-	transfer_buffer =  kmalloc (0x12, GFP_KERNEL);
-	if (transfer_buffer) {
-		usb_control_msg (port->serial->dev,
-				 usb_rcvctrlpipe(port->serial->dev, 0),
-				 VISOR_CLOSE_NOTIFICATION, 0xc2,
-				 0x0000, 0x0000, 
-				 transfer_buffer, 0x12, 300);
-		kfree (transfer_buffer);
+	mutex_lock(&port->serial->disc_mutex);
+	if (!port->serial->disconnected) {
+		/* Try to send shutdown message, unless the device is gone */
+		transfer_buffer =  kmalloc (0x12, GFP_KERNEL);
+		if (transfer_buffer) {
+			usb_control_msg (port->serial->dev,
+					 usb_rcvctrlpipe(port->serial->dev, 0),
+					 VISOR_CLOSE_NOTIFICATION, 0xc2,
+					 0x0000, 0x0000,
+					 transfer_buffer, 0x12, 300);
+			kfree (transfer_buffer);
+		}
 	}
+	mutex_unlock(&port->serial->disc_mutex);
 
 	if (stats)
 		dev_info(&port->dev, "Bytes In = %d  Bytes Out = %d\n",
diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c
index ee5dd8b..38726ef 100644
--- a/drivers/usb/serial/whiteheat.c
+++ b/drivers/usb/serial/whiteheat.c
@@ -610,8 +610,7 @@
 	if (retval)
 		goto exit;
 
-	if (port->tty)
-		port->tty->low_latency = 1;
+	port->tty->low_latency = 1;
 
 	/* send an open port command */
 	retval = firm_open(port);
@@ -659,11 +658,14 @@
 	struct list_head *tmp2;
 
 	dbg("%s - port %d", __FUNCTION__, port->number);
-	
+
+	mutex_lock(&port->serial->disc_mutex);
 	/* filp is NULL when called from usb_serial_disconnect */
-	if (filp && (tty_hung_up_p(filp))) {
+	if ((filp && (tty_hung_up_p(filp))) || port->serial->disconnected) {
+		mutex_unlock(&port->serial->disc_mutex);
 		return;
 	}
+	mutex_unlock(&port->serial->disc_mutex);
 
 	port->tty->closing = 1;
 
diff --git a/drivers/usb/storage/initializers.c b/drivers/usb/storage/initializers.c
index ee5b42a..187dd1e 100644
--- a/drivers/usb/storage/initializers.c
+++ b/drivers/usb/storage/initializers.c
@@ -66,7 +66,8 @@
 {
 	struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap*) us->iobuf;
 	struct bulk_cs_wrap *bcs = (struct bulk_cs_wrap*) us->iobuf;
-	int res, partial;
+	int res;
+	unsigned int partial;
 	static char init_string[] = "\xec\x0a\x06\x00$PCCHIPS";
 
 	US_DEBUGP("Sending UCR-61S2B initialization packet...\n");
diff --git a/drivers/usb/storage/isd200.c b/drivers/usb/storage/isd200.c
index 0db4886..2ae1e86 100644
--- a/drivers/usb/storage/isd200.c
+++ b/drivers/usb/storage/isd200.c
@@ -48,7 +48,6 @@
 #include <linux/errno.h>
 #include <linux/slab.h>
 #include <linux/hdreg.h>
-#include <linux/ide.h>
 #include <linux/scatterlist.h>
 
 #include <scsi/scsi.h>
@@ -110,6 +109,12 @@
 #define REG_STATUS		0x80
 #define REG_COMMAND		0x80
 
+/* ATA registers offset definitions */
+#define ATA_REG_ERROR_OFFSET		1
+#define ATA_REG_LCYL_OFFSET		4
+#define ATA_REG_HCYL_OFFSET		5
+#define ATA_REG_STATUS_OFFSET		7
+
 /* ATA error definitions not in <linux/hdreg.h> */
 #define ATA_ERROR_MEDIA_CHANGE		0x20
 
@@ -360,7 +365,7 @@
 {
 	struct isd200_info *info = (struct isd200_info *)us->extra;
 	struct sense_data *buf = (struct sense_data *) &srb->sense_buffer[0];
-	unsigned char error = info->ATARegs[IDE_ERROR_OFFSET];
+	unsigned char error = info->ATARegs[ATA_REG_ERROR_OFFSET];
 
 	if(error & ATA_ERROR_MEDIA_CHANGE) {
 		buf->ErrorCode = 0x70 | SENSE_ERRCODE_VALID;
@@ -549,8 +554,8 @@
 		retStatus = ISD200_ERROR;
 	} else {
 		memcpy(info->ATARegs, info->RegsBuf, sizeof(info->ATARegs));
-		US_DEBUGP("   Got ATA Register[IDE_ERROR_OFFSET] = 0x%x\n", 
-			  info->ATARegs[IDE_ERROR_OFFSET]);
+		US_DEBUGP("   Got ATA Register[ATA_REG_ERROR_OFFSET] = 0x%x\n",
+			  info->ATARegs[ATA_REG_ERROR_OFFSET]);
 	}
 
 	return retStatus;
@@ -892,7 +897,7 @@
 			break;
 
 		if (!detect) {
-			if (regs[IDE_STATUS_OFFSET] & BUSY_STAT ) {
+			if (regs[ATA_REG_STATUS_OFFSET] & BUSY_STAT) {
 				US_DEBUGP("   %s status is still BSY, try again...\n",mstr);
 			} else {
 				US_DEBUGP("   %s status !BSY, continue with next operation\n",mstr);
@@ -902,12 +907,12 @@
 		/* check for BUSY_STAT and */
 		/* WRERR_STAT (workaround ATA Zip drive) and */ 
 		/* ERR_STAT (workaround for Archos CD-ROM) */
-		else if (regs[IDE_STATUS_OFFSET] & 
+		else if (regs[ATA_REG_STATUS_OFFSET] &
 			 (BUSY_STAT | WRERR_STAT | ERR_STAT )) {
 			US_DEBUGP("   Status indicates it is not ready, try again...\n");
 		}
 		/* check for DRDY, ATA devices set DRDY after SRST */
-		else if (regs[IDE_STATUS_OFFSET] & READY_STAT) {
+		else if (regs[ATA_REG_STATUS_OFFSET] & READY_STAT) {
 			US_DEBUGP("   Identified ATA device\n");
 			info->DeviceFlags |= DF_ATA_DEVICE;
 			info->DeviceHead = master_slave;
@@ -916,8 +921,8 @@
 		/* check Cylinder High/Low to
 		   determine if it is an ATAPI device
 		*/
-		else if ((regs[IDE_HCYL_OFFSET] == 0xEB) &&
-			 (regs[IDE_LCYL_OFFSET] == 0x14)) {
+		else if (regs[ATA_REG_HCYL_OFFSET] == 0xEB &&
+			 regs[ATA_REG_LCYL_OFFSET] == 0x14) {
 			/* It seems that the RICOH 
 			   MP6200A CD/RW drive will 
 			   report itself okay as a
@@ -1001,12 +1006,6 @@
 	return(retStatus);
 }
 
-/*
- *	We are the last non IDE user of the legacy IDE ident structures
- *	and we thus want to keep a private copy of this function so the
- *	driver can be used without the obsolete drivers/ide layer
- */
-
 static void isd200_fix_driveid (struct hd_driveid *id)
 {
 #ifndef __LITTLE_ENDIAN
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
index 6d6108b..fe12737 100644
--- a/drivers/usb/storage/unusual_devs.h
+++ b/drivers/usb/storage/unusual_devs.h
@@ -86,6 +86,14 @@
 		US_SC_8070, US_PR_USBAT, init_usbat_cd, 0),
 #endif
 
+/* Reported by Grant Grundler <grundler@parisc-linux.org>
+ * HP r707 camera in "Disk" mode with 2.00.23 or 2.00.24 firmware.
+ */
+UNUSUAL_DEV(  0x03f0, 0x4002, 0x0001, 0x0001,
+		"HP",
+		"PhotoSmart R707",
+		US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_CAPACITY),
+
 /* Reported by Sebastian Kapfer <sebastian_kapfer@gmx.net>
  * and Olaf Hering <olh@suse.de> (different bcd's, same vendor/product)
  * for USB floppies that need the SINGLE_LUN enforcement.
diff --git a/drivers/video/sis/sis.h b/drivers/video/sis/sis.h
index d53bf69..9b05da6 100644
--- a/drivers/video/sis/sis.h
+++ b/drivers/video/sis/sis.h
@@ -39,12 +39,7 @@
 #include <linux/spinlock.h>
 
 #ifdef CONFIG_COMPAT
-#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,10)
-#include <linux/ioctl32.h>
-#define SIS_OLD_CONFIG_COMPAT
-#else
 #define SIS_NEW_CONFIG_COMPAT
-#endif
 #endif	/* CONFIG_COMPAT */
 
 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,8)
@@ -607,9 +602,6 @@
 	int		haveXGIROM;
 	int		registered;
 	int		warncount;
-#ifdef SIS_OLD_CONFIG_COMPAT
-	int		ioctl32registered;
-#endif
 
 	int		sisvga_engine;
 	int		hwcursor_size;
diff --git a/drivers/video/sis/sis_main.c b/drivers/video/sis/sis_main.c
index 37bd24b..93ae747 100644
--- a/drivers/video/sis/sis_main.c
+++ b/drivers/video/sis/sis_main.c
@@ -5805,9 +5805,6 @@
 	ivideo->pcifunc = PCI_FUNC(pdev->devfn);
 	ivideo->subsysvendor = pdev->subsystem_vendor;
 	ivideo->subsysdevice = pdev->subsystem_device;
-#ifdef SIS_OLD_CONFIG_COMPAT
-	ivideo->ioctl32registered = 0;
-#endif
 
 #ifndef MODULE
 	if(sisfb_mode_idx == -1) {
@@ -6420,30 +6417,6 @@
 		ivideo->next = card_list;
 		card_list = ivideo;
 
-#ifdef SIS_OLD_CONFIG_COMPAT
-		{
-		int ret;
-		/* Our ioctls are all "32/64bit compatible" */
-		ret =  register_ioctl32_conversion(FBIO_ALLOC,             NULL);
-		ret |= register_ioctl32_conversion(FBIO_FREE,              NULL);
-		ret |= register_ioctl32_conversion(FBIOGET_VBLANK,         NULL);
-		ret |= register_ioctl32_conversion(SISFB_GET_INFO_SIZE,    NULL);
-		ret |= register_ioctl32_conversion(SISFB_GET_INFO,         NULL);
-		ret |= register_ioctl32_conversion(SISFB_GET_TVPOSOFFSET,  NULL);
-		ret |= register_ioctl32_conversion(SISFB_SET_TVPOSOFFSET,  NULL);
-		ret |= register_ioctl32_conversion(SISFB_SET_LOCK,         NULL);
-		ret |= register_ioctl32_conversion(SISFB_GET_VBRSTATUS,    NULL);
-		ret |= register_ioctl32_conversion(SISFB_GET_AUTOMAXIMIZE, NULL);
-		ret |= register_ioctl32_conversion(SISFB_SET_AUTOMAXIMIZE, NULL);
-		ret |= register_ioctl32_conversion(SISFB_COMMAND,          NULL);
-		if(ret)
-			printk(KERN_ERR
-				"sisfb: Error registering ioctl32 translations\n");
-		else
-			ivideo->ioctl32registered = 1;
-		}
-#endif
-
 		printk(KERN_INFO "sisfb: 2D acceleration is %s, y-panning %s\n",
 			ivideo->sisfb_accel ? "enabled" : "disabled",
 			ivideo->sisfb_ypan  ?
@@ -6473,27 +6446,6 @@
 	int			registered = ivideo->registered;
 	int			modechanged = ivideo->modechanged;
 
-#ifdef SIS_OLD_CONFIG_COMPAT
-	if(ivideo->ioctl32registered) {
-		int ret;
-		ret =  unregister_ioctl32_conversion(FBIO_ALLOC);
-		ret |= unregister_ioctl32_conversion(FBIO_FREE);
-		ret |= unregister_ioctl32_conversion(FBIOGET_VBLANK);
-		ret |= unregister_ioctl32_conversion(SISFB_GET_INFO_SIZE);
-		ret |= unregister_ioctl32_conversion(SISFB_GET_INFO);
-		ret |= unregister_ioctl32_conversion(SISFB_GET_TVPOSOFFSET);
-		ret |= unregister_ioctl32_conversion(SISFB_SET_TVPOSOFFSET);
-		ret |= unregister_ioctl32_conversion(SISFB_SET_LOCK);
-		ret |= unregister_ioctl32_conversion(SISFB_GET_VBRSTATUS);
-		ret |= unregister_ioctl32_conversion(SISFB_GET_AUTOMAXIMIZE);
-		ret |= unregister_ioctl32_conversion(SISFB_SET_AUTOMAXIMIZE);
-		ret |= unregister_ioctl32_conversion(SISFB_COMMAND);
-		if(ret)
-			printk(KERN_ERR
-			     "sisfb: Error unregistering ioctl32 translations\n");
-	}
-#endif
-
 	/* Unmap */
 	iounmap(ivideo->mmio_vbase);
 	iounmap(ivideo->video_vbase);
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 9fa9708..3353748 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -984,7 +984,7 @@
 	if (!task)
 		return -ESRCH;
 	length = scnprintf(tmpbuf, TMPBUFLEN, "%u",
-				audit_get_loginuid(task->audit_context));
+				audit_get_loginuid(task));
 	put_task_struct(task);
 	return simple_read_from_buffer(buf, count, ppos, tmpbuf, length);
 }
diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h
index 9512f04..b729e64 100644
--- a/include/acpi/acpixf.h
+++ b/include/acpi/acpixf.h
@@ -335,6 +335,8 @@
 
 acpi_status asmlinkage acpi_enter_sleep_state_s4bios(void);
 
+acpi_status acpi_leave_sleep_state_prep(u8 sleep_state);
+
 acpi_status acpi_leave_sleep_state(u8 sleep_state);
 
 #endif				/* __ACXFACE_H__ */
diff --git a/include/asm-arm/arch-at91/board.h b/include/asm-arm/arch-at91/board.h
index 55b07bd..dc189f0 100644
--- a/include/asm-arm/arch-at91/board.h
+++ b/include/asm-arm/arch-at91/board.h
@@ -40,7 +40,8 @@
  /* USB Device */
 struct at91_udc_data {
 	u8	vbus_pin;		/* high == host powering us */
-	u8	pullup_pin;		/* high == D+ pulled up */
+	u8	pullup_pin;		/* active == D+ pulled up */
+	u8	pullup_active_low;	/* true == pullup_pin is active low */
 };
 extern void __init at91_add_device_udc(struct at91_udc_data *data);
 
diff --git a/include/asm-arm/mach/udc_pxa2xx.h b/include/asm-arm/mach/udc_pxa2xx.h
index ff0a957..f191e14 100644
--- a/include/asm-arm/mach/udc_pxa2xx.h
+++ b/include/asm-arm/mach/udc_pxa2xx.h
@@ -19,7 +19,9 @@
 	 * with on-chip GPIOs not Lubbock's wierd hardware, can have a sane
 	 * VBUS IRQ and omit the methods above.  Store the GPIO number
 	 * here; for GPIO 0, also mask in one of the pxa_gpio_mode() bits.
+	 * Note that sometimes the signals go through inverters...
 	 */
+	bool	gpio_vbus_inverted;
 	u16	gpio_vbus;			/* high == vbus present */
 	u16	gpio_pullup;			/* high == pullup activated */
 };
diff --git a/include/asm-mips/mach-au1x00/au1xxx_ide.h b/include/asm-mips/mach-au1x00/au1xxx_ide.h
index aef0edb..e4fe26c 100644
--- a/include/asm-mips/mach-au1x00/au1xxx_ide.h
+++ b/include/asm-mips/mach-au1x00/au1xxx_ide.h
@@ -74,7 +74,6 @@
         struct dbdma_cmd        *dma_table_cpu;
         dma_addr_t              dma_table_dma;
 #endif
-        struct device           *dev;
 	int			irq;
 	u32			regbase;
 #ifdef CONFIG_PM
diff --git a/include/asm-x86/cpu.h b/include/asm-x86/cpu.h
index 85ece5f..73f2ea8 100644
--- a/include/asm-x86/cpu.h
+++ b/include/asm-x86/cpu.h
@@ -10,8 +10,9 @@
 struct x86_cpu {
 	struct cpu cpu;
 };
-extern int arch_register_cpu(int num);
+
 #ifdef CONFIG_HOTPLUG_CPU
+extern int arch_register_cpu(int num);
 extern void arch_unregister_cpu(int);
 #endif
 
diff --git a/include/asm-x86/e820_64.h b/include/asm-x86/e820_64.h
index 51e4170..a560c4f 100644
--- a/include/asm-x86/e820_64.h
+++ b/include/asm-x86/e820_64.h
@@ -15,7 +15,7 @@
 
 #ifndef __ASSEMBLY__
 extern unsigned long find_e820_area(unsigned long start, unsigned long end, 
-				    unsigned size);
+				    unsigned size, unsigned long align);
 extern void add_memory_region(unsigned long start, unsigned long size, 
 			      int type);
 extern void setup_memory_region(void);
@@ -41,7 +41,7 @@
 extern struct e820map e820;
 extern void update_e820(void);
 
-extern void reserve_early(unsigned long start, unsigned long end);
+extern void reserve_early(unsigned long start, unsigned long end, char *name);
 extern void early_res_to_bootmem(void);
 
 #endif/*!__ASSEMBLY__*/
diff --git a/include/asm-x86/futex.h b/include/asm-x86/futex.h
index 62828d6..9d91926 100644
--- a/include/asm-x86/futex.h
+++ b/include/asm-x86/futex.h
@@ -30,7 +30,7 @@
 "1:	movl	%2, %0\n					\
 	movl	%0, %3\n"					\
 	insn "\n"						\
-"2:	" LOCK_PREFIX "cmpxchgl %3, %2\n			\
+"2:	lock; cmpxchgl %3, %2\n					\
 	jnz	1b\n						\
 3:	.section .fixup,\"ax\"\n				\
 4:	mov	%5, %1\n					\
@@ -72,7 +72,7 @@
 		__futex_atomic_op1("xchgl %0, %2", ret, oldval, uaddr, oparg);
 		break;
 	case FUTEX_OP_ADD:
-		__futex_atomic_op1(LOCK_PREFIX "xaddl %0, %2", ret, oldval,
+		__futex_atomic_op1("lock; xaddl %0, %2", ret, oldval,
 				   uaddr, oparg);
 		break;
 	case FUTEX_OP_OR:
@@ -111,8 +111,8 @@
 		return -EFAULT;
 
 	__asm__ __volatile__(
-		"1:	" LOCK_PREFIX "cmpxchgl %3, %1		\n"
 
+		"1:	lock; cmpxchgl %3, %1			\n"
 		"2:	.section .fixup, \"ax\"			\n"
 		"3:	mov     %2, %0				\n"
 		"	jmp     2b				\n"
diff --git a/include/linux/Kbuild b/include/linux/Kbuild
index 85b2482..c0f9bb7 100644
--- a/include/linux/Kbuild
+++ b/include/linux/Kbuild
@@ -143,6 +143,7 @@
 header-y += sockios.h
 header-y += som.h
 header-y += sound.h
+header-y += suspend_ioctls.h
 header-y += taskstats.h
 header-y += telephony.h
 header-y += termios.h
diff --git a/include/linux/aspm.h b/include/linux/aspm.h
new file mode 100644
index 0000000..f41a698
--- /dev/null
+++ b/include/linux/aspm.h
@@ -0,0 +1,44 @@
+/*
+ *	aspm.h
+ *
+ *	PCI Express ASPM defines and function prototypes
+ *
+ *	Copyright (C) 2007 Intel Corp.
+ *		Zhang Yanmin (yanmin.zhang@intel.com)
+ *		Shaohua Li (shaohua.li@intel.com)
+ *
+ *	For more information, please consult the following manuals (look at
+ *	http://www.pcisig.com/ for how to get them):
+ *
+ *	PCI Express Specification
+ */
+
+#ifndef LINUX_ASPM_H
+#define LINUX_ASPM_H
+
+#include <linux/pci.h>
+
+#define PCIE_LINK_STATE_L0S	1
+#define PCIE_LINK_STATE_L1	2
+#define PCIE_LINK_STATE_CLKPM	4
+
+#ifdef CONFIG_PCIEASPM
+extern void pcie_aspm_init_link_state(struct pci_dev *pdev);
+extern void pcie_aspm_exit_link_state(struct pci_dev *pdev);
+extern void pcie_aspm_pm_state_change(struct pci_dev *pdev);
+extern void pci_disable_link_state(struct pci_dev *pdev, int state);
+#else
+#define pcie_aspm_init_link_state(pdev)		do {} while (0)
+#define pcie_aspm_exit_link_state(pdev)		do {} while (0)
+#define pcie_aspm_pm_state_change(pdev)		do {} while (0)
+#define pci_disable_link_state(pdev, state)	do {} while (0)
+#endif
+
+#ifdef CONFIG_PCIEASPM_DEBUG /* this depends on CONFIG_PCIEASPM */
+extern void pcie_aspm_create_sysfs_dev_files(struct pci_dev *pdev);
+extern void pcie_aspm_remove_sysfs_dev_files(struct pci_dev *pdev);
+#else
+#define pcie_aspm_create_sysfs_dev_files(pdev)	do {} while (0)
+#define pcie_aspm_remove_sysfs_dev_files(pdev)	do {} while (0)
+#endif
+#endif /* LINUX_ASPM_H */
diff --git a/include/linux/audit.h b/include/linux/audit.h
index bdd6f5d..9715302 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -98,6 +98,7 @@
 #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_EOE		1320	/* End of multi-record event */
 
 #define AUDIT_AVC		1400	/* SE Linux avc denial or grant */
 #define AUDIT_SELINUX_ERR	1401	/* Internal SE Linux Errors */
@@ -409,7 +410,8 @@
 extern void auditsc_get_stamp(struct audit_context *ctx,
 			      struct timespec *t, unsigned int *serial);
 extern int  audit_set_loginuid(struct task_struct *task, uid_t loginuid);
-extern uid_t audit_get_loginuid(struct audit_context *ctx);
+#define audit_get_loginuid(t) ((t)->loginuid)
+#define audit_get_sessionid(t) ((t)->sessionid)
 extern void audit_log_task_context(struct audit_buffer *ab);
 extern int __audit_ipc_obj(struct kern_ipc_perm *ipcp);
 extern int __audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode);
@@ -488,7 +490,8 @@
 #define audit_inode_child(d,i,p) do { ; } while (0)
 #define audit_core_dumps(i) do { ; } while (0)
 #define auditsc_get_stamp(c,t,s) do { BUG(); } while (0)
-#define audit_get_loginuid(c) ({ -1; })
+#define audit_get_loginuid(t) (-1)
+#define audit_get_sessionid(t) (-1)
 #define audit_log_task_context(b) do { ; } while (0)
 #define audit_ipc_obj(i) ({ 0; })
 #define audit_ipc_set_perm(q,u,g,m) ({ 0; })
@@ -522,9 +525,11 @@
 extern void		    audit_log_hex(struct audit_buffer *ab,
 					  const unsigned char *buf,
 					  size_t len);
-extern const char *	    audit_log_untrustedstring(struct audit_buffer *ab,
+extern int		    audit_string_contains_control(const char *string,
+							  size_t len);
+extern void		    audit_log_untrustedstring(struct audit_buffer *ab,
 						      const char *string);
-extern const char *	    audit_log_n_untrustedstring(struct audit_buffer *ab,
+extern void		    audit_log_n_untrustedstring(struct audit_buffer *ab,
 							size_t n,
 							const char *string);
 extern void		    audit_log_d_path(struct audit_buffer *ab,
diff --git a/include/linux/cdrom.h b/include/linux/cdrom.h
index fcdc11b..a5cd204 100644
--- a/include/linux/cdrom.h
+++ b/include/linux/cdrom.h
@@ -1187,6 +1187,20 @@
 
 extern int cdrom_get_media_event(struct cdrom_device_info *cdi, struct media_event_desc *med);
 
+static inline void lba_to_msf(int lba, u8 *m, u8 *s, u8 *f)
+{
+	lba += CD_MSF_OFFSET;
+	lba &= 0xffffff;  /* negative lbas use only 24 bits */
+	*m = lba / (CD_SECS * CD_FRAMES);
+	lba %= (CD_SECS * CD_FRAMES);
+	*s = lba / CD_FRAMES;
+	*f = lba % CD_FRAMES;
+}
+
+static inline int msf_to_lba(u8 m, u8 s, u8 f)
+{
+	return (((m * CD_SECS) + s) * CD_FRAMES + f) - CD_MSF_OFFSET;
+}
 #endif  /* End of kernel only stuff */ 
 
 #endif  /* _LINUX_CDROM_H */
diff --git a/include/linux/futex.h b/include/linux/futex.h
index 1a15f8e..90048fb 100644
--- a/include/linux/futex.h
+++ b/include/linux/futex.h
@@ -21,6 +21,8 @@
 #define FUTEX_LOCK_PI		6
 #define FUTEX_UNLOCK_PI		7
 #define FUTEX_TRYLOCK_PI	8
+#define FUTEX_WAIT_BITSET	9
+#define FUTEX_WAKE_BITSET	10
 
 #define FUTEX_PRIVATE_FLAG	128
 #define FUTEX_CMD_MASK		~FUTEX_PRIVATE_FLAG
@@ -33,6 +35,8 @@
 #define FUTEX_LOCK_PI_PRIVATE	(FUTEX_LOCK_PI | FUTEX_PRIVATE_FLAG)
 #define FUTEX_UNLOCK_PI_PRIVATE	(FUTEX_UNLOCK_PI | FUTEX_PRIVATE_FLAG)
 #define FUTEX_TRYLOCK_PI_PRIVATE (FUTEX_TRYLOCK_PI | FUTEX_PRIVATE_FLAG)
+#define FUTEX_WAIT_BITSET_PRIVATE	(FUTEX_WAIT_BITS | FUTEX_PRIVATE_FLAG)
+#define FUTEX_WAKE_BITSET_PRIVATE	(FUTEX_WAKE_BITS | FUTEX_PRIVATE_FLAG)
 
 /*
  * Support for robust futexes: the kernel cleans up held futexes at
@@ -111,6 +115,12 @@
  */
 #define ROBUST_LIST_LIMIT	2048
 
+/*
+ * bitset with all bits set for the FUTEX_xxx_BITSET OPs to request a
+ * match of any bit.
+ */
+#define FUTEX_BITSET_MATCH_ANY	0xffffffff
+
 #ifdef __KERNEL__
 long do_futex(u32 __user *uaddr, int op, u32 val, union ktime *timeout,
 	      u32 __user *uaddr2, u32 val2, u32 val3);
diff --git a/include/linux/hdsmart.h b/include/linux/hdsmart.h
index 7974a47..e691921 100644
--- a/include/linux/hdsmart.h
+++ b/include/linux/hdsmart.h
@@ -17,6 +17,7 @@
 #ifndef _LINUX_HDSMART_H
 #define _LINUX_HDSMART_H
 
+#ifndef __KERNEL
 #define OFFLINE_FULL_SCAN		0
 #define SHORT_SELF_TEST			1
 #define EXTEND_SELF_TEST		2
@@ -120,5 +121,6 @@
 	unsigned char			resevered[2];
 	unsigned char			chksum;
 } __attribute__ ((packed)) ata_smart_selftestlog_t;
+#endif /* __KERNEL__ *
 
 #endif	/* _LINUX_HDSMART_H */
diff --git a/include/linux/ide.h b/include/linux/ide.h
index 27cb39d..ec10b2a 100644
--- a/include/linux/ide.h
+++ b/include/linux/ide.h
@@ -9,7 +9,6 @@
 #include <linux/init.h>
 #include <linux/ioport.h>
 #include <linux/hdreg.h>
-#include <linux/hdsmart.h>
 #include <linux/blkdev.h>
 #include <linux/proc_fs.h>
 #include <linux/interrupt.h>
@@ -503,7 +502,8 @@
 
 	hwif_chipset_t chipset;	/* sub-module for tuning.. */
 
-	struct pci_dev  *pci_dev;	/* for pci chipsets */
+	struct device *dev;
+
 	const struct ide_port_info *cds;	/* chipset device struct */
 
 	ide_ack_intr_t *ack_intr;
@@ -628,8 +628,7 @@
 typedef struct hwgroup_s {
 		/* irq handler, if active */
 	ide_startstop_t	(*handler)(ide_drive_t *);
-		/* irq handler, suspended if active */
-	ide_startstop_t	(*handler_save)(ide_drive_t *);
+
 		/* BOOL: protects all fields below */
 	volatile int busy;
 		/* BOOL: wake us up on timer expiry */
@@ -644,25 +643,18 @@
 		/* ptr to current hwif in linked-list */
 	ide_hwif_t *hwif;
 
-		/* for pci chipsets */
-	struct pci_dev *pci_dev;
-
 		/* current request */
 	struct request *rq;
+
 		/* failsafe timer */
 	struct timer_list timer;
-		/* local copy of current write rq */
-	struct request wrq;
 		/* timeout value during long polls */
 	unsigned long poll_timeout;
 		/* queried upon timeouts */
 	int (*expiry)(ide_drive_t *);
-		/* ide_system_bus_speed */
-	int pio_clock;
+
 	int req_gen;
 	int req_gen_timer;
-
-	unsigned char cmd_buf[4];
 } ide_hwgroup_t;
 
 typedef struct ide_driver_s ide_driver_t;
@@ -986,8 +978,6 @@
 
 void task_end_request(ide_drive_t *, struct request *, u8);
 
-u8 wait_drive_not_busy(ide_drive_t *);
-
 int ide_raw_taskfile(ide_drive_t *, ide_task_t *, u8 *, u16);
 int ide_no_data_taskfile(ide_drive_t *, ide_task_t *);
 
@@ -1017,7 +1007,6 @@
 
 #ifdef CONFIG_IDEPCI_PCIBUS_ORDER
 extern int ide_scan_direction;
-int __init ide_scan_pcibus(void);
 extern int __ide_pci_register_driver(struct pci_driver *driver, struct module *owner, const char *mod_name);
 #define ide_pci_register_driver(d) __ide_pci_register_driver(d, THIS_MODULE, KBUILD_MODNAME)
 #else
@@ -1096,6 +1085,10 @@
 	IDE_HFLAG_ABUSE_SET_DMA_MODE	= (1 << 26),
 	/* host is CY82C693 */
 	IDE_HFLAG_CY82C693		= (1 << 27),
+	/* force host out of "simplex" mode */
+	IDE_HFLAG_CLEAR_SIMPLEX		= (1 << 28),
+	/* DSC overlap is unsupported */
+	IDE_HFLAG_NO_DSC		= (1 << 29),
 };
 
 #ifdef CONFIG_BLK_DEV_OFFBOARD
@@ -1153,12 +1146,13 @@
 int ide_set_dma(ide_drive_t *);
 ide_startstop_t ide_dma_intr(ide_drive_t *);
 
+int ide_build_sglist(ide_drive_t *, struct request *);
+void ide_destroy_dmatable(ide_drive_t *);
+
 #ifdef CONFIG_BLK_DEV_IDEDMA_PCI
-extern int ide_build_sglist(ide_drive_t *, struct request *);
 extern int ide_build_dmatable(ide_drive_t *, struct request *);
-extern void ide_destroy_dmatable(ide_drive_t *);
 extern int ide_release_dma(ide_hwif_t *);
-extern void ide_setup_dma(ide_hwif_t *, unsigned long, unsigned int);
+extern void ide_setup_dma(ide_hwif_t *, unsigned long);
 
 void ide_dma_host_set(ide_drive_t *, int);
 extern int ide_dma_setup(ide_drive_t *);
@@ -1197,6 +1191,7 @@
 static inline void ide_acpi_set_state(ide_hwif_t *hwif, int on) {}
 #endif
 
+void ide_remove_port_from_hwgroup(ide_hwif_t *);
 extern int ide_hwif_request_regions(ide_hwif_t *hwif);
 extern void ide_hwif_release_regions(ide_hwif_t* hwif);
 extern void ide_unregister (unsigned int index);
@@ -1291,9 +1286,14 @@
 #define ide_id_has_flush_cache_ext(id)	\
 	(((id)->cfs_enable_2 & 0x2400) == 0x2400)
 
+static inline void ide_dump_identify(u8 *id)
+{
+	print_hex_dump(KERN_INFO, "", DUMP_PREFIX_NONE, 16, 2, id, 512, 0);
+}
+
 static inline int hwif_to_node(ide_hwif_t *hwif)
 {
-	struct pci_dev *dev = hwif->pci_dev;
+	struct pci_dev *dev = to_pci_dev(hwif->dev);
 	return dev ? pcibus_to_node(dev->bus) : -1;
 }
 
diff --git a/include/linux/init_task.h b/include/linux/init_task.h
index e6b3f70..f42663e 100644
--- a/include/linux/init_task.h
+++ b/include/linux/init_task.h
@@ -114,6 +114,13 @@
 	.pid = &init_struct_pid,				\
 }
 
+#ifdef CONFIG_AUDITSYSCALL
+#define INIT_IDS \
+	.loginuid = -1, \
+	.sessionid = -1,
+#else
+#define INIT_IDS
+#endif
 /*
  *  INIT_TASK is used to set up the first task table, touch at
  * your own risk!. Base=0, limit=0x1fffff (=2MB)
@@ -173,6 +180,7 @@
 		[PIDTYPE_SID]  = INIT_PID_LINK(PIDTYPE_SID),		\
 	},								\
 	.dirties = INIT_PROP_LOCAL_SINGLE(dirties),			\
+	INIT_IDS							\
 	INIT_TRACE_IRQFLAGS						\
 	INIT_LOCKDEP							\
 }
diff --git a/include/linux/notifier.h b/include/linux/notifier.h
index 5dfbc68..f4df400 100644
--- a/include/linux/notifier.h
+++ b/include/linux/notifier.h
@@ -228,6 +228,8 @@
 #define PM_POST_HIBERNATION	0x0002 /* Hibernation finished */
 #define PM_SUSPEND_PREPARE	0x0003 /* Going to suspend the system */
 #define PM_POST_SUSPEND		0x0004 /* Suspend finished */
+#define PM_RESTORE_PREPARE	0x0005 /* Going to restore a saved image */
+#define PM_POST_RESTORE		0x0006 /* Restore failed */
 
 /* Console keyboard events.
  * Note: KBD_KEYCODE is always sent before KBD_UNBOUND_KEYCODE, KBD_UNICODE and
diff --git a/include/linux/pci-acpi.h b/include/linux/pci-acpi.h
index 936ef82..3ba2506 100644
--- a/include/linux/pci-acpi.h
+++ b/include/linux/pci-acpi.h
@@ -48,7 +48,15 @@
 
 #ifdef CONFIG_ACPI
 extern acpi_status pci_osc_control_set(acpi_handle handle, u32 flags);
-extern acpi_status pci_osc_support_set(u32 flags);
+extern acpi_status __pci_osc_support_set(u32 flags, const char *hid);
+static inline acpi_status pci_osc_support_set(u32 flags)
+{
+	return __pci_osc_support_set(flags, PCI_ROOT_HID_STRING);
+}
+static inline acpi_status pcie_osc_support_set(u32 flags)
+{
+	return __pci_osc_support_set(flags, PCI_EXPRESS_ROOT_HID_STRING);
+}
 #else
 #if !defined(AE_ERROR)
 typedef u32 		acpi_status;
@@ -57,6 +65,7 @@
 static inline acpi_status pci_osc_control_set(acpi_handle handle, u32 flags)
 {return AE_ERROR;}
 static inline acpi_status pci_osc_support_set(u32 flags) {return AE_ERROR;} 
+static inline acpi_status pcie_osc_support_set(u32 flags) {return AE_ERROR;}
 #endif
 
 #endif	/* _PCI_ACPI_H_ */
diff --git a/include/linux/pci.h b/include/linux/pci.h
index ae10063..4f96f1d 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -28,7 +28,7 @@
  *	7:3 = slot
  *	2:0 = function
  */
-#define PCI_DEVFN(slot,func)	((((slot) & 0x1f) << 3) | ((func) & 0x07))
+#define PCI_DEVFN(slot, func)	((((slot) & 0x1f) << 3) | ((func) & 0x07))
 #define PCI_SLOT(devfn)		(((devfn) >> 3) & 0x1f)
 #define PCI_FUNC(devfn)		((devfn) & 0x07)
 
@@ -66,7 +66,6 @@
 #define PCI_DMA_FROMDEVICE	2
 #define PCI_DMA_NONE		3
 
-#define DEVICE_COUNT_COMPATIBLE	4
 #define DEVICE_COUNT_RESOURCE	12
 
 typedef int __bitwise pci_power_t;
@@ -129,6 +128,7 @@
 	u32 data[0];
 };
 
+struct pcie_link_state;
 /*
  * The pci_dev structure is used to describe PCI devices.
  */
@@ -164,13 +164,13 @@
 					   this is D0-D3, D0 being fully functional,
 					   and D3 being off. */
 
+#ifdef CONFIG_PCIEASPM
+	struct pcie_link_state	*link_state;	/* ASPM link state. */
+#endif
+
 	pci_channel_state_t error_state;	/* current connectivity state */
 	struct	device	dev;		/* Generic device interface */
 
-	/* device is compatible with these IDs */
-	unsigned short vendor_compatible[DEVICE_COUNT_COMPATIBLE];
-	unsigned short device_compatible[DEVICE_COUNT_COMPATIBLE];
-
 	int		cfg_size;	/* Size of configuration space */
 
 	/*
@@ -219,7 +219,7 @@
 }
 
 static inline struct pci_cap_saved_state *pci_find_saved_cap(
-	struct pci_dev *pci_dev,char cap)
+	struct pci_dev *pci_dev, char cap)
 {
 	struct pci_cap_saved_state *tmp;
 	struct hlist_node *pos;
@@ -278,13 +278,13 @@
 	unsigned short  bridge_ctl;	/* manage NO_ISA/FBB/et al behaviors */
 	pci_bus_flags_t bus_flags;	/* Inherited by child busses */
 	struct device		*bridge;
-	struct class_device	class_dev;
+	struct device		dev;
 	struct bin_attribute	*legacy_io; /* legacy I/O for this bus */
 	struct bin_attribute	*legacy_mem; /* legacy mem */
 };
 
 #define pci_bus_b(n)	list_entry(n, struct pci_bus, node)
-#define to_pci_bus(n)	container_of(n, struct pci_bus, class_dev)
+#define to_pci_bus(n)	container_of(n, struct pci_bus, dev)
 
 /*
  * Error values that may be returned by PCI functions.
@@ -314,8 +314,8 @@
 extern struct pci_raw_ops *raw_pci_ops;
 
 struct pci_bus_region {
-	unsigned long start;
-	unsigned long end;
+	resource_size_t start;
+	resource_size_t end;
 };
 
 struct pci_dynids {
@@ -351,11 +351,10 @@
 };
 
 /* PCI bus error event callbacks */
-struct pci_error_handlers
-{
+struct pci_error_handlers {
 	/* PCI bus error detected on this device */
 	pci_ers_result_t (*error_detected)(struct pci_dev *dev,
-	                      enum pci_channel_state error);
+					   enum pci_channel_state error);
 
 	/* MMIO has been re-enabled, but not DMA */
 	pci_ers_result_t (*mmio_enabled)(struct pci_dev *dev);
@@ -390,7 +389,7 @@
 	struct pci_dynids dynids;
 };
 
-#define	to_pci_driver(drv) container_of(drv,struct pci_driver, driver)
+#define	to_pci_driver(drv) container_of(drv, struct pci_driver, driver)
 
 /**
  * PCI_DEVICE - macro used to describe a specific pci device
@@ -448,7 +447,7 @@
 
 void pcibios_fixup_bus(struct pci_bus *);
 int __must_check pcibios_enable_device(struct pci_dev *, int mask);
-char *pcibios_setup (char *str);
+char *pcibios_setup(char *str);
 
 /* Used only when drivers/pci/setup.c is used */
 void pcibios_align_resource(void *, struct resource *, resource_size_t,
@@ -459,8 +458,10 @@
 
 extern struct pci_bus *pci_find_bus(int domain, int busnr);
 void pci_bus_add_devices(struct pci_bus *bus);
-struct pci_bus *pci_scan_bus_parented(struct device *parent, int bus, struct pci_ops *ops, void *sysdata);
-static inline struct pci_bus *pci_scan_bus(int bus, struct pci_ops *ops, void *sysdata)
+struct pci_bus *pci_scan_bus_parented(struct device *parent, int bus,
+				      struct pci_ops *ops, void *sysdata);
+static inline struct pci_bus *pci_scan_bus(int bus, struct pci_ops *ops,
+					   void *sysdata)
 {
 	struct pci_bus *root_bus;
 	root_bus = pci_scan_bus_parented(NULL, bus, ops, sysdata);
@@ -468,15 +469,18 @@
 		pci_bus_add_devices(root_bus);
 	return root_bus;
 }
-struct pci_bus *pci_create_bus(struct device *parent, int bus, struct pci_ops *ops, void *sysdata);
-struct pci_bus * pci_add_new_bus(struct pci_bus *parent, struct pci_dev *dev, int busnr);
+struct pci_bus *pci_create_bus(struct device *parent, int bus,
+			       struct pci_ops *ops, void *sysdata);
+struct pci_bus *pci_add_new_bus(struct pci_bus *parent, struct pci_dev *dev,
+				int busnr);
 int pci_scan_slot(struct pci_bus *bus, int devfn);
-struct pci_dev * pci_scan_single_device(struct pci_bus *bus, int devfn);
+struct pci_dev *pci_scan_single_device(struct pci_bus *bus, int devfn);
 void pci_device_add(struct pci_dev *dev, struct pci_bus *bus);
 unsigned int pci_scan_child_bus(struct pci_bus *bus);
 int __must_check pci_bus_add_device(struct pci_dev *dev);
 void pci_read_bridge_bases(struct pci_bus *child);
-struct resource *pci_find_parent_resource(const struct pci_dev *dev, struct resource *res);
+struct resource *pci_find_parent_resource(const struct pci_dev *dev,
+					  struct resource *res);
 int pci_get_interrupt_pin(struct pci_dev *dev, struct pci_dev **bridge);
 extern struct pci_dev *pci_dev_get(struct pci_dev *dev);
 extern void pci_dev_put(struct pci_dev *dev);
@@ -489,15 +493,19 @@
 /* Generic PCI functions exported to card drivers */
 
 #ifdef CONFIG_PCI_LEGACY
-struct pci_dev __deprecated *pci_find_device (unsigned int vendor, unsigned int device, const struct pci_dev *from);
-struct pci_dev __deprecated *pci_find_slot (unsigned int bus, unsigned int devfn);
+struct pci_dev __deprecated *pci_find_device(unsigned int vendor,
+					     unsigned int device,
+					     const struct pci_dev *from);
+struct pci_dev __deprecated *pci_find_slot(unsigned int bus,
+					   unsigned int devfn);
 #endif /* CONFIG_PCI_LEGACY */
 
-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);
-int pci_find_ht_capability (struct pci_dev *dev, int ht_cap);
-int pci_find_next_ht_capability (struct pci_dev *dev, int pos, int ht_cap);
+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);
+int pci_find_ht_capability(struct pci_dev *dev, int ht_cap);
+int pci_find_next_ht_capability(struct pci_dev *dev, int pos, int ht_cap);
+void pcie_wait_pending_transaction(struct pci_dev *dev);
 struct pci_bus *pci_find_next_bus(const struct pci_bus *from);
 
 struct pci_dev *pci_get_device(unsigned int vendor, unsigned int device,
@@ -505,49 +513,58 @@
 struct pci_dev *pci_get_device_reverse(unsigned int vendor, unsigned int device,
 				struct pci_dev *from);
 
-struct pci_dev *pci_get_subsys (unsigned int vendor, unsigned int device,
+struct pci_dev *pci_get_subsys(unsigned int vendor, unsigned int device,
 				unsigned int ss_vendor, unsigned int ss_device,
 				struct pci_dev *from);
-struct pci_dev *pci_get_slot (struct pci_bus *bus, unsigned int devfn);
-struct pci_dev *pci_get_bus_and_slot (unsigned int bus, unsigned int devfn);
-struct pci_dev *pci_get_class (unsigned int class, struct pci_dev *from);
+struct pci_dev *pci_get_slot(struct pci_bus *bus, unsigned int devfn);
+struct pci_dev *pci_get_bus_and_slot(unsigned int bus, unsigned int devfn);
+struct pci_dev *pci_get_class(unsigned int class, struct pci_dev *from);
 int pci_dev_present(const struct pci_device_id *ids);
 const struct pci_device_id *pci_find_present(const struct pci_device_id *ids);
 
-int pci_bus_read_config_byte (struct pci_bus *bus, unsigned int devfn, int where, u8 *val);
-int pci_bus_read_config_word (struct pci_bus *bus, unsigned int devfn, int where, u16 *val);
-int pci_bus_read_config_dword (struct pci_bus *bus, unsigned int devfn, int where, u32 *val);
-int pci_bus_write_config_byte (struct pci_bus *bus, unsigned int devfn, int where, u8 val);
-int pci_bus_write_config_word (struct pci_bus *bus, unsigned int devfn, int where, u16 val);
-int pci_bus_write_config_dword (struct pci_bus *bus, unsigned int devfn, int where, u32 val);
+int pci_bus_read_config_byte(struct pci_bus *bus, unsigned int devfn,
+			     int where, u8 *val);
+int pci_bus_read_config_word(struct pci_bus *bus, unsigned int devfn,
+			     int where, u16 *val);
+int pci_bus_read_config_dword(struct pci_bus *bus, unsigned int devfn,
+			      int where, u32 *val);
+int pci_bus_write_config_byte(struct pci_bus *bus, unsigned int devfn,
+			      int where, u8 val);
+int pci_bus_write_config_word(struct pci_bus *bus, unsigned int devfn,
+			      int where, u16 val);
+int pci_bus_write_config_dword(struct pci_bus *bus, unsigned int devfn,
+			       int where, u32 val);
 
 static inline int pci_read_config_byte(struct pci_dev *dev, int where, u8 *val)
 {
-	return pci_bus_read_config_byte (dev->bus, dev->devfn, where, val);
+	return pci_bus_read_config_byte(dev->bus, dev->devfn, where, val);
 }
 static inline int pci_read_config_word(struct pci_dev *dev, int where, u16 *val)
 {
-	return pci_bus_read_config_word (dev->bus, dev->devfn, where, val);
+	return pci_bus_read_config_word(dev->bus, dev->devfn, where, val);
 }
-static inline int pci_read_config_dword(struct pci_dev *dev, int where, u32 *val)
+static inline int pci_read_config_dword(struct pci_dev *dev, int where,
+					u32 *val)
 {
-	return pci_bus_read_config_dword (dev->bus, dev->devfn, where, val);
+	return pci_bus_read_config_dword(dev->bus, dev->devfn, where, val);
 }
 static inline int pci_write_config_byte(struct pci_dev *dev, int where, u8 val)
 {
-	return pci_bus_write_config_byte (dev->bus, dev->devfn, where, val);
+	return pci_bus_write_config_byte(dev->bus, dev->devfn, where, val);
 }
 static inline int pci_write_config_word(struct pci_dev *dev, int where, u16 val)
 {
-	return pci_bus_write_config_word (dev->bus, dev->devfn, where, val);
+	return pci_bus_write_config_word(dev->bus, dev->devfn, where, val);
 }
-static inline int pci_write_config_dword(struct pci_dev *dev, int where, u32 val)
+static inline int pci_write_config_dword(struct pci_dev *dev, int where,
+					 u32 val)
 {
-	return pci_bus_write_config_dword (dev->bus, dev->devfn, where, val);
+	return pci_bus_write_config_dword(dev->bus, dev->devfn, where, val);
 }
 
 int __must_check pci_enable_device(struct pci_dev *dev);
-int __must_check pci_enable_device_bars(struct pci_dev *dev, int mask);
+int __must_check pci_enable_device_io(struct pci_dev *dev);
+int __must_check pci_enable_device_mem(struct pci_dev *dev);
 int __must_check pci_reenable_device(struct pci_dev *);
 int __must_check pcim_enable_device(struct pci_dev *pdev);
 void pcim_pin_device(struct pci_dev *pdev);
@@ -576,14 +593,11 @@
 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);
-void pci_restore_bars(struct pci_dev *dev);
 int pci_select_bars(struct pci_dev *dev, unsigned long flags);
 
 /* ROM control related routines */
 void __iomem __must_check *pci_map_rom(struct pci_dev *pdev, size_t *size);
-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 */
@@ -594,7 +608,7 @@
 int pci_enable_wake(struct pci_dev *dev, pci_power_t state, int enable);
 
 /* Functions for PCI Hotplug drivers to use */
-int pci_bus_find_capability (struct pci_bus *bus, unsigned int devfn, int cap);
+int pci_bus_find_capability(struct pci_bus *bus, unsigned int devfn, int cap);
 
 /* Helper functions for low-level code (drivers/pci/setup-[bus,res].c) */
 void pci_bus_assign_resources(struct pci_bus *bus);
@@ -631,16 +645,18 @@
 	return __pci_register_driver(driver, THIS_MODULE, KBUILD_MODNAME);
 }
 
-void pci_unregister_driver(struct pci_driver *);
-void pci_remove_behind_bridge(struct pci_dev *);
-struct pci_driver *pci_dev_driver(const struct pci_dev *);
-const struct pci_device_id *pci_match_id(const struct pci_device_id *ids, struct pci_dev *dev);
-int pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max, int pass);
+void pci_unregister_driver(struct pci_driver *dev);
+void pci_remove_behind_bridge(struct pci_dev *dev);
+struct pci_driver *pci_dev_driver(const struct pci_dev *dev);
+const struct pci_device_id *pci_match_id(const struct pci_device_id *ids,
+					 struct pci_dev *dev);
+int pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max,
+		    int pass);
 
 void pci_walk_bus(struct pci_bus *top, void (*cb)(struct pci_dev *, void *),
 		  void *userdata);
 int pci_cfg_space_size(struct pci_dev *dev);
-unsigned char pci_bus_max_busnr(struct pci_bus* bus);
+unsigned char pci_bus_max_busnr(struct pci_bus *bus);
 
 /* kmem_cache style wrapper around pci_alloc_consistent() */
 
@@ -669,19 +685,36 @@
 
 
 #ifndef CONFIG_PCI_MSI
-static inline int pci_enable_msi(struct pci_dev *dev) {return -1;}
-static inline void pci_disable_msi(struct pci_dev *dev) {}
-static inline int pci_enable_msix(struct pci_dev* dev,
-	struct msix_entry *entries, int nvec) {return -1;}
-static inline void pci_disable_msix(struct pci_dev *dev) {}
-static inline void msi_remove_pci_irq_vectors(struct pci_dev *dev) {}
+static inline int pci_enable_msi(struct pci_dev *dev)
+{
+	return -1;
+}
+
+static inline void pci_disable_msi(struct pci_dev *dev)
+{ }
+
+static inline int pci_enable_msix(struct pci_dev *dev,
+				  struct msix_entry *entries, int nvec)
+{
+	return -1;
+}
+
+static inline void pci_disable_msix(struct pci_dev *dev)
+{ }
+
+static inline void msi_remove_pci_irq_vectors(struct pci_dev *dev)
+{ }
+
+static inline void pci_restore_msi_state(struct pci_dev *dev)
+{ }
 #else
 extern int pci_enable_msi(struct pci_dev *dev);
 extern void pci_disable_msi(struct pci_dev *dev);
-extern int pci_enable_msix(struct pci_dev* dev,
+extern int pci_enable_msix(struct pci_dev *dev,
 	struct msix_entry *entries, int nvec);
 extern void pci_disable_msix(struct pci_dev *dev);
 extern void msi_remove_pci_irq_vectors(struct pci_dev *dev);
+extern void pci_restore_msi_state(struct pci_dev *dev);
 #endif
 
 #ifdef CONFIG_HT_IRQ
@@ -702,7 +735,11 @@
 extern int pci_domains_supported;
 #else
 enum { pci_domains_supported = 0 };
-static inline int pci_domain_nr(struct pci_bus *bus) { return 0; }
+static inline int pci_domain_nr(struct pci_bus *bus)
+{
+	return 0;
+}
+
 static inline int pci_proc_domain(struct pci_bus *bus)
 {
 	return 0;
@@ -716,67 +753,161 @@
  *  these as simple inline functions to avoid hair in drivers.
  */
 
-#define _PCI_NOP(o,s,t) \
-	static inline int pci_##o##_config_##s (struct pci_dev *dev, int where, t val) \
+#define _PCI_NOP(o, s, t) \
+	static inline int pci_##o##_config_##s(struct pci_dev *dev, \
+						int where, t val) \
 		{ return PCIBIOS_FUNC_NOT_SUPPORTED; }
-#define _PCI_NOP_ALL(o,x)	_PCI_NOP(o,byte,u8 x) \
-				_PCI_NOP(o,word,u16 x) \
-				_PCI_NOP(o,dword,u32 x)
+
+#define _PCI_NOP_ALL(o, x)	_PCI_NOP(o, byte, u8 x) \
+				_PCI_NOP(o, word, u16 x) \
+				_PCI_NOP(o, dword, u32 x)
 _PCI_NOP_ALL(read, *)
 _PCI_NOP_ALL(write,)
 
-static inline struct pci_dev *pci_find_device(unsigned int vendor, unsigned int device, const struct pci_dev *from)
-{ return NULL; }
+static inline struct pci_dev *pci_find_device(unsigned int vendor,
+					      unsigned int device,
+					      const struct pci_dev *from)
+{
+	return NULL;
+}
 
-static inline struct pci_dev *pci_find_slot(unsigned int bus, unsigned int devfn)
-{ return NULL; }
+static inline struct pci_dev *pci_find_slot(unsigned int bus,
+					    unsigned int devfn)
+{
+	return NULL;
+}
 
 static inline struct pci_dev *pci_get_device(unsigned int vendor,
-				unsigned int device, struct pci_dev *from)
-{ return NULL; }
+					     unsigned int device,
+					     struct pci_dev *from)
+{
+	return NULL;
+}
 
 static inline struct pci_dev *pci_get_device_reverse(unsigned int vendor,
-				unsigned int device, struct pci_dev *from)
-{ return NULL; }
+						     unsigned int device,
+						     struct pci_dev *from)
+{
+	return NULL;
+}
 
-static inline struct pci_dev *pci_get_subsys (unsigned int vendor, unsigned int device,
-unsigned int ss_vendor, unsigned int ss_device, struct pci_dev *from)
-{ return NULL; }
+static inline struct pci_dev *pci_get_subsys(unsigned int vendor,
+					     unsigned int device,
+					     unsigned int ss_vendor,
+					     unsigned int ss_device,
+					     struct pci_dev *from)
+{
+	return NULL;
+}
 
-static inline struct pci_dev *pci_get_class(unsigned int class, struct pci_dev *from)
-{ return NULL; }
+static inline struct pci_dev *pci_get_class(unsigned int class,
+					    struct pci_dev *from)
+{
+	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)
 
-static inline void pci_set_master(struct pci_dev *dev) { }
-static inline int pci_enable_device(struct pci_dev *dev) { return -EIO; }
-static inline void pci_disable_device(struct pci_dev *dev) { }
-static inline int pci_set_dma_mask(struct pci_dev *dev, u64 mask) { return -EIO; }
-static inline int pci_assign_resource(struct pci_dev *dev, int i) { return -EBUSY;}
-static inline int __pci_register_driver(struct pci_driver *drv, struct module *owner) { return 0;}
-static inline int pci_register_driver(struct pci_driver *drv) { return 0;}
-static inline void pci_unregister_driver(struct pci_driver *drv) { }
-static inline int pci_find_capability (struct pci_dev *dev, int cap) {return 0; }
-static inline int pci_find_next_capability (struct pci_dev *dev, u8 post, int cap) { return 0; }
-static inline int pci_find_ext_capability (struct pci_dev *dev, int cap) {return 0; }
+static inline void pci_set_master(struct pci_dev *dev)
+{ }
+
+static inline int pci_enable_device(struct pci_dev *dev)
+{
+	return -EIO;
+}
+
+static inline void pci_disable_device(struct pci_dev *dev)
+{ }
+
+static inline int pci_set_dma_mask(struct pci_dev *dev, u64 mask)
+{
+	return -EIO;
+}
+
+static inline int pci_assign_resource(struct pci_dev *dev, int i)
+{
+	return -EBUSY;
+}
+
+static inline int __pci_register_driver(struct pci_driver *drv,
+					struct module *owner)
+{
+	return 0;
+}
+
+static inline int pci_register_driver(struct pci_driver *drv)
+{
+	return 0;
+}
+
+static inline void pci_unregister_driver(struct pci_driver *drv)
+{ }
+
+static inline int pci_find_capability(struct pci_dev *dev, int cap)
+{
+	return 0;
+}
+
+static inline int pci_find_next_capability(struct pci_dev *dev, u8 post,
+					   int cap)
+{
+	return 0;
+}
+
+static inline int pci_find_ext_capability(struct pci_dev *dev, int cap)
+{
+	return 0;
+}
+
+static inline void pcie_wait_pending_transaction(struct pci_dev *dev)
+{ }
 
 /* Power management related routines */
-static inline int pci_save_state(struct pci_dev *dev) { return 0; }
-static inline int pci_restore_state(struct pci_dev *dev) { return 0; }
-static inline int pci_set_power_state(struct pci_dev *dev, pci_power_t state) { return 0; }
-static inline pci_power_t pci_choose_state(struct pci_dev *dev, pm_message_t state) { return PCI_D0; }
-static inline int pci_enable_wake(struct pci_dev *dev, pci_power_t state, int enable) { return 0; }
+static inline int pci_save_state(struct pci_dev *dev)
+{
+	return 0;
+}
 
-static inline int pci_request_regions(struct pci_dev *dev, const char *res_name) { return -EIO; }
-static inline void pci_release_regions(struct pci_dev *dev) { }
+static inline int pci_restore_state(struct pci_dev *dev)
+{
+	return 0;
+}
+
+static inline int pci_set_power_state(struct pci_dev *dev, pci_power_t state)
+{
+	return 0;
+}
+
+static inline pci_power_t pci_choose_state(struct pci_dev *dev,
+					   pm_message_t state)
+{
+	return PCI_D0;
+}
+
+static inline int pci_enable_wake(struct pci_dev *dev, pci_power_t state,
+				  int enable)
+{
+	return 0;
+}
+
+static inline int pci_request_regions(struct pci_dev *dev, const char *res_name)
+{
+	return -EIO;
+}
+
+static inline void pci_release_regions(struct pci_dev *dev)
+{ }
 
 #define pci_dma_burst_advice(pdev, strat, strategy_parameter) do { } while (0)
 
-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 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; }
@@ -797,27 +928,27 @@
 
 /* these helpers provide future and backwards compatibility
  * for accessing popular PCI BAR info */
-#define pci_resource_start(dev,bar)   ((dev)->resource[(bar)].start)
-#define pci_resource_end(dev,bar)     ((dev)->resource[(bar)].end)
-#define pci_resource_flags(dev,bar)   ((dev)->resource[(bar)].flags)
+#define pci_resource_start(dev, bar)	((dev)->resource[(bar)].start)
+#define pci_resource_end(dev, bar)	((dev)->resource[(bar)].end)
+#define pci_resource_flags(dev, bar)	((dev)->resource[(bar)].flags)
 #define pci_resource_len(dev,bar) \
-	((pci_resource_start((dev),(bar)) == 0 &&	\
-	  pci_resource_end((dev),(bar)) ==		\
-	  pci_resource_start((dev),(bar))) ? 0 :	\
-	  						\
-	 (pci_resource_end((dev),(bar)) -		\
-	  pci_resource_start((dev),(bar)) + 1))
+	((pci_resource_start((dev), (bar)) == 0 &&	\
+	  pci_resource_end((dev), (bar)) ==		\
+	  pci_resource_start((dev), (bar))) ? 0 :	\
+							\
+	 (pci_resource_end((dev), (bar)) -		\
+	  pci_resource_start((dev), (bar)) + 1))
 
 /* Similar to the helpers above, these manipulate per-pci_dev
  * driver-specific data.  They are really just a wrapper around
  * the generic device structure functions of these calls.
  */
-static inline void *pci_get_drvdata (struct pci_dev *pdev)
+static inline void *pci_get_drvdata(struct pci_dev *pdev)
 {
 	return dev_get_drvdata(&pdev->dev);
 }
 
-static inline void pci_set_drvdata (struct pci_dev *pdev, void *data)
+static inline void pci_set_drvdata(struct pci_dev *pdev, void *data)
 {
 	dev_set_drvdata(&pdev->dev, data);
 }
@@ -836,7 +967,7 @@
  */
 #ifndef HAVE_ARCH_PCI_RESOURCE_TO_USER
 static inline void pci_resource_to_user(const struct pci_dev *dev, int bar,
-                const struct resource *rsrc, resource_size_t *start,
+		const struct resource *rsrc, resource_size_t *start,
 		resource_size_t *end)
 {
 	*start = rsrc->start;
@@ -888,9 +1019,9 @@
 
 void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev);
 
-void __iomem * pcim_iomap(struct pci_dev *pdev, int bar, unsigned long maxlen);
+void __iomem *pcim_iomap(struct pci_dev *pdev, int bar, unsigned long maxlen);
 void pcim_iounmap(struct pci_dev *pdev, void __iomem *addr);
-void __iomem * const * pcim_iomap_table(struct pci_dev *pdev);
+void __iomem * const *pcim_iomap_table(struct pci_dev *pdev);
 int pcim_iomap_regions(struct pci_dev *pdev, u16 mask, const char *name);
 void pcim_iounmap_regions(struct pci_dev *pdev, u16 mask);
 
diff --git a/include/linux/pci_regs.h b/include/linux/pci_regs.h
index c1914a8..c0c1223 100644
--- a/include/linux/pci_regs.h
+++ b/include/linux/pci_regs.h
@@ -395,9 +395,17 @@
 #define  PCI_EXP_DEVSTA_AUXPD	0x10	/* AUX Power Detected */
 #define  PCI_EXP_DEVSTA_TRPND	0x20	/* Transactions Pending */
 #define PCI_EXP_LNKCAP		12	/* Link Capabilities */
+#define  PCI_EXP_LNKCAP_ASPMS	0xc00	/* ASPM Support */
+#define  PCI_EXP_LNKCAP_L0SEL	0x7000	/* L0s Exit Latency */
+#define  PCI_EXP_LNKCAP_L1EL	0x38000	/* L1 Exit Latency */
+#define  PCI_EXP_LNKCAP_CLKPM	0x40000	/* L1 Clock Power Management */
 #define PCI_EXP_LNKCTL		16	/* Link Control */
+#define  PCI_EXP_LNKCTL_RL	0x20	/* Retrain Link */
+#define  PCI_EXP_LNKCTL_CCC	0x40	/* Common Clock COnfiguration */
 #define  PCI_EXP_LNKCTL_CLKREQ_EN 0x100	/* Enable clkreq */
 #define PCI_EXP_LNKSTA		18	/* Link Status */
+#define  PCI_EXP_LNKSTA_LT	0x800	/* Link Training */
+#define  PCI_EXP_LNKSTA_SLC	0x1000	/* Slot Clock Configuration */
 #define PCI_EXP_SLTCAP		20	/* Slot Capabilities */
 #define PCI_EXP_SLTCTL		24	/* Slot Control */
 #define PCI_EXP_SLTSTA		26	/* Slot Status */
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 6c33357..af6947e 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1139,6 +1139,10 @@
 	void *security;
 #endif
 	struct audit_context *audit_context;
+#ifdef CONFIG_AUDITSYSCALL
+	uid_t loginuid;
+	unsigned int sessionid;
+#endif
 	seccomp_t seccomp;
 
 /* Thread group tracking */
diff --git a/include/linux/suspend.h b/include/linux/suspend.h
index 40280df..646ce2d 100644
--- a/include/linux/suspend.h
+++ b/include/linux/suspend.h
@@ -38,18 +38,16 @@
  *	There is the %suspend_valid_only_mem function available that can be
  *	assigned to this if the platform only supports mem sleep.
  *
- * @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),
+ * @begin: Initialise a transition to given system sleep state.
+ *	@begin() is executed right prior to suspending devices.  The information
+ *	conveyed to the platform code by @begin() should be disregarded by it as
+ *	soon as @end() is executed.  If @begin() 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 @enter() is meaningless and should be ignored.
+ *	passed to @enter() is redundant and should be ignored.
  *
  * @prepare: Prepare the platform for entering the system sleep state indicated
- *	by @set_target().
+ *	by @begin().
  *	@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).
@@ -57,8 +55,8 @@
  *	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.
+ * @enter: Enter the system sleep state indicated by @begin() or represented by
+ *	the argument if @begin() 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.
@@ -69,13 +67,22 @@
  *	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).
+ *
+ * @end: Called by the PM core right after resuming devices, to indicate to
+ *	the platform that the system has returned to the working state or
+ *	the transition to the sleep state has been aborted.
+ *	This callback is optional, but should be implemented by the platforms
+ *	that implement @begin(), but platforms implementing @begin() should
+ *	also provide a @end() which cleans up transitions aborted before
+ *	@enter().
  */
 struct platform_suspend_ops {
 	int (*valid)(suspend_state_t state);
-	int (*set_target)(suspend_state_t state);
+	int (*begin)(suspend_state_t state);
 	int (*prepare)(void);
 	int (*enter)(suspend_state_t state);
 	void (*finish)(void);
+	void (*end)(void);
 };
 
 #ifdef CONFIG_SUSPEND
@@ -129,14 +136,17 @@
 /**
  * struct platform_hibernation_ops - hibernation platform support
  *
- * The methods in this structure allow a platform to override the default
- * mechanism of shutting down the machine during a hibernation transition.
+ * The methods in this structure allow a platform to carry out special
+ * operations required by it during a hibernation transition.
  *
- * All three methods must be assigned.
+ * All the methods below must be implemented.
  *
- * @start: Tell the platform driver that we're starting hibernation.
+ * @begin: Tell the platform driver that we're starting hibernation.
  *	Called right after shrinking memory and before freezing devices.
  *
+ * @end: Called by the PM core right after resuming devices, to indicate to
+ *	the platform that the system has returned to the working state.
+ *
  * @pre_snapshot: Prepare the platform for creating the hibernation image.
  *	Called right after devices have been frozen and before the nonboot
  *	CPUs are disabled (runs with IRQs on).
@@ -171,7 +181,8 @@
  *	thawing devices (runs with IRQs on).
  */
 struct platform_hibernation_ops {
-	int (*start)(void);
+	int (*begin)(void);
+	void (*end)(void);
 	int (*pre_snapshot)(void);
 	void (*finish)(void);
 	int (*prepare)(void);
@@ -213,17 +224,8 @@
 void restore_processor_state(void);
 
 /* kernel/power/main.c */
-extern struct blocking_notifier_head pm_chain_head;
-
-static inline int register_pm_notifier(struct notifier_block *nb)
-{
-	return blocking_notifier_chain_register(&pm_chain_head, nb);
-}
-
-static inline int unregister_pm_notifier(struct notifier_block *nb)
-{
-	return blocking_notifier_chain_unregister(&pm_chain_head, nb);
-}
+extern int register_pm_notifier(struct notifier_block *nb);
+extern int unregister_pm_notifier(struct notifier_block *nb);
 
 #define pm_notifier(fn, pri) {				\
 	static struct notifier_block fn##_nb =			\
diff --git a/include/linux/suspend_ioctls.h b/include/linux/suspend_ioctls.h
new file mode 100644
index 0000000..2c6faec
--- /dev/null
+++ b/include/linux/suspend_ioctls.h
@@ -0,0 +1,32 @@
+#ifndef _LINUX_SUSPEND_IOCTLS_H
+#define _LINUX_SUSPEND_IOCTLS_H
+
+/*
+ * This structure is used to pass the values needed for the identification
+ * of the resume swap area from a user space to the kernel via the
+ * SNAPSHOT_SET_SWAP_AREA ioctl
+ */
+struct resume_swap_area {
+	loff_t offset;
+	u_int32_t dev;
+} __attribute__((packed));
+
+#define SNAPSHOT_IOC_MAGIC	'3'
+#define SNAPSHOT_FREEZE			_IO(SNAPSHOT_IOC_MAGIC, 1)
+#define SNAPSHOT_UNFREEZE		_IO(SNAPSHOT_IOC_MAGIC, 2)
+#define SNAPSHOT_ATOMIC_RESTORE		_IO(SNAPSHOT_IOC_MAGIC, 4)
+#define SNAPSHOT_FREE			_IO(SNAPSHOT_IOC_MAGIC, 5)
+#define SNAPSHOT_FREE_SWAP_PAGES	_IO(SNAPSHOT_IOC_MAGIC, 9)
+#define SNAPSHOT_S2RAM			_IO(SNAPSHOT_IOC_MAGIC, 11)
+#define SNAPSHOT_SET_SWAP_AREA		_IOW(SNAPSHOT_IOC_MAGIC, 13, \
+							struct resume_swap_area)
+#define SNAPSHOT_GET_IMAGE_SIZE		_IOR(SNAPSHOT_IOC_MAGIC, 14, loff_t)
+#define SNAPSHOT_PLATFORM_SUPPORT	_IO(SNAPSHOT_IOC_MAGIC, 15)
+#define SNAPSHOT_POWER_OFF		_IO(SNAPSHOT_IOC_MAGIC, 16)
+#define SNAPSHOT_CREATE_IMAGE		_IOW(SNAPSHOT_IOC_MAGIC, 17, int)
+#define SNAPSHOT_PREF_IMAGE_SIZE	_IO(SNAPSHOT_IOC_MAGIC, 18)
+#define SNAPSHOT_AVAIL_SWAP_SIZE	_IOR(SNAPSHOT_IOC_MAGIC, 19, loff_t)
+#define SNAPSHOT_ALLOC_SWAP_PAGE	_IOR(SNAPSHOT_IOC_MAGIC, 20, loff_t)
+#define SNAPSHOT_IOC_MAXNR	20
+
+#endif /* _LINUX_SUSPEND_IOCTLS_H */
diff --git a/include/linux/thread_info.h b/include/linux/thread_info.h
index dfbdfb98..421323e 100644
--- a/include/linux/thread_info.h
+++ b/include/linux/thread_info.h
@@ -23,6 +23,7 @@
 			u32 *uaddr;
 			u32 val;
 			u32 flags;
+			u32 bitset;
 			u64 time;
 		} futex;
 	};
diff --git a/include/linux/tick.h b/include/linux/tick.h
index 0fadf95d..a881c65 100644
--- a/include/linux/tick.h
+++ b/include/linux/tick.h
@@ -39,6 +39,8 @@
  * @idle_calls:		Total number of idle calls
  * @idle_sleeps:	Number of idle calls, where the sched tick was stopped
  * @idle_entrytime:	Time when the idle call was entered
+ * @idle_waketime:	Time when the idle was interrupted
+ * @idle_exittime:	Time when the idle state was left
  * @idle_sleeptime:	Sum of the time slept in idle with sched tick stopped
  * @sleep_length:	Duration of the current idle sleep
  */
@@ -53,6 +55,8 @@
 	unsigned long			idle_sleeps;
 	int				idle_active;
 	ktime_t				idle_entrytime;
+	ktime_t				idle_waketime;
+	ktime_t				idle_exittime;
 	ktime_t				idle_sleeptime;
 	ktime_t				idle_lastupdate;
 	ktime_t				sleep_length;
diff --git a/include/linux/time.h b/include/linux/time.h
index b04136d..ceaab9f 100644
--- a/include/linux/time.h
+++ b/include/linux/time.h
@@ -122,6 +122,7 @@
 extern struct timespec timespec_trunc(struct timespec t, unsigned gran);
 extern int timekeeping_is_continuous(void);
 extern void update_wall_time(void);
+extern void update_xtime_cache(u64 nsec);
 
 /**
  * timespec_to_ns - Convert timespec to nanoseconds
diff --git a/include/linux/usb.h b/include/linux/usb.h
index 5fc8ff7..2372e2e 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -162,19 +162,19 @@
 	unsigned needs_remote_wakeup:1;	/* driver requires remote wakeup */
 
 	struct device dev;		/* interface specific device info */
-	struct device *usb_dev;		/* pointer to the usb class's device, if any */
+	struct device *usb_dev;
 	int pm_usage_cnt;		/* usage counter for autosuspend */
 };
 #define	to_usb_interface(d) container_of(d, struct usb_interface, dev)
 #define	interface_to_usbdev(intf) \
 	container_of(intf->dev.parent, struct usb_device, dev)
 
-static inline void *usb_get_intfdata (struct usb_interface *intf)
+static inline void *usb_get_intfdata(struct usb_interface *intf)
 {
-	return dev_get_drvdata (&intf->dev);
+	return dev_get_drvdata(&intf->dev);
 }
 
-static inline void usb_set_intfdata (struct usb_interface *intf, void *data)
+static inline void usb_set_intfdata(struct usb_interface *intf, void *data)
 {
 	dev_set_drvdata(&intf->dev, data);
 }
@@ -275,9 +275,10 @@
 
 int __usb_get_extra_descriptor(char *buffer, unsigned size,
 	unsigned char type, void **ptr);
-#define usb_get_extra_descriptor(ifpoint,type,ptr)\
-	__usb_get_extra_descriptor((ifpoint)->extra,(ifpoint)->extralen,\
-		type,(void**)ptr)
+#define usb_get_extra_descriptor(ifpoint, type, ptr) \
+				__usb_get_extra_descriptor((ifpoint)->extra, \
+				(ifpoint)->extralen, \
+				type, (void **)ptr)
 
 /* ----------------------------------------------------------------------- */
 
@@ -318,7 +319,7 @@
 #ifdef CONFIG_USB_DEVICEFS
 	struct dentry *usbfs_dentry;	/* usbfs dentry entry for the bus */
 #endif
-	struct class_device *class_dev;	/* class device for this bus */
+	struct device *dev;		/* device for this bus */
 
 #if defined(CONFIG_USB_MON)
 	struct mon_bus *mon_bus;	/* non-null when associated */
@@ -388,7 +389,7 @@
 	unsigned can_submit:1;		/* URBs may be submitted */
 	unsigned discon_suspended:1;	/* Disconnected while suspended */
 	unsigned have_langid:1;		/* whether string_langid is valid */
-	unsigned authorized:1;		/* Policy has determined we can use it */
+	unsigned authorized:1;		/* Policy has said we can use it */
 	unsigned wusb:1;		/* Device is Wireless USB */
 	int string_langid;		/* language ID for strings */
 
@@ -417,7 +418,10 @@
 
 	int pm_usage_cnt;		/* usage counter for autosuspend */
 	u32 quirks;			/* quirks of the whole device */
-	atomic_t urbnum;		/* number of URBs submitted for the whole device */
+	atomic_t urbnum;		/* number of URBs submitted for
+					   the whole device */
+
+	unsigned long active_duration;	/* total time device is not suspended */
 
 #ifdef CONFIG_PM
 	struct delayed_work autosuspend; /* for delayed autosuspends */
@@ -425,6 +429,7 @@
 
 	unsigned long last_busy;	/* time of last use */
 	int autosuspend_delay;		/* in jiffies */
+	unsigned long connect_time;	/* time device was first connected */
 
 	unsigned auto_pm:1;		/* autosuspend/resume in progress */
 	unsigned do_remote_wakeup:1;	/* remote wakeup should be enabled */
@@ -498,11 +503,11 @@
 /*-------------------------------------------------------------------------*/
 
 /* for drivers using iso endpoints */
-extern int usb_get_current_frame_number (struct usb_device *usb_dev);
+extern int usb_get_current_frame_number(struct usb_device *usb_dev);
 
 /* used these for multi-interface device registration */
 extern int usb_driver_claim_interface(struct usb_driver *driver,
-			struct usb_interface *iface, void* priv);
+			struct usb_interface *iface, void *priv);
 
 /**
  * usb_interface_claimed - returns true iff an interface is claimed
@@ -514,7 +519,8 @@
  * may need to explicitly claim that lock.
  *
  */
-static inline int usb_interface_claimed(struct usb_interface *iface) {
+static inline int usb_interface_claimed(struct usb_interface *iface)
+{
 	return (iface->dev.driver != NULL);
 }
 
@@ -557,12 +563,11 @@
  * USB 2.0 root hubs (EHCI host controllers) will get one path ID if they are
  * high speed, and a different one if they are full or low speed.
  */
-static inline int usb_make_path (struct usb_device *dev, char *buf,
-		size_t size)
+static inline int usb_make_path(struct usb_device *dev, char *buf, size_t size)
 {
 	int actual;
-	actual = snprintf (buf, size, "usb-%s-%s", dev->bus->bus_name,
-			dev->devpath);
+	actual = snprintf(buf, size, "usb-%s-%s", dev->bus->bus_name,
+			  dev->devpath);
 	return (actual >= (int)size) ? -1 : actual;
 }
 
@@ -608,7 +613,8 @@
  *
  * Returns true if the endpoint is of type OUT, otherwise it returns false.
  */
-static inline int usb_endpoint_dir_out(const struct usb_endpoint_descriptor *epd)
+static inline int usb_endpoint_dir_out(
+				const struct usb_endpoint_descriptor *epd)
 {
 	return ((epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT);
 }
@@ -619,7 +625,8 @@
  *
  * Returns true if the endpoint is of type bulk, otherwise it returns false.
  */
-static inline int usb_endpoint_xfer_bulk(const struct usb_endpoint_descriptor *epd)
+static inline int usb_endpoint_xfer_bulk(
+				const struct usb_endpoint_descriptor *epd)
 {
 	return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
 		USB_ENDPOINT_XFER_BULK);
@@ -631,7 +638,8 @@
  *
  * Returns true if the endpoint is of type control, otherwise it returns false.
  */
-static inline int usb_endpoint_xfer_control(const struct usb_endpoint_descriptor *epd)
+static inline int usb_endpoint_xfer_control(
+				const struct usb_endpoint_descriptor *epd)
 {
 	return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
 		USB_ENDPOINT_XFER_CONTROL);
@@ -644,7 +652,8 @@
  * Returns true if the endpoint is of type interrupt, otherwise it returns
  * false.
  */
-static inline int usb_endpoint_xfer_int(const struct usb_endpoint_descriptor *epd)
+static inline int usb_endpoint_xfer_int(
+				const struct usb_endpoint_descriptor *epd)
 {
 	return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
 		USB_ENDPOINT_XFER_INT);
@@ -657,7 +666,8 @@
  * Returns true if the endpoint is of type isochronous, otherwise it returns
  * false.
  */
-static inline int usb_endpoint_xfer_isoc(const struct usb_endpoint_descriptor *epd)
+static inline int usb_endpoint_xfer_isoc(
+				const struct usb_endpoint_descriptor *epd)
 {
 	return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
 		USB_ENDPOINT_XFER_ISOC);
@@ -670,7 +680,8 @@
  * Returns true if the endpoint has bulk transfer type and IN direction,
  * otherwise it returns false.
  */
-static inline int usb_endpoint_is_bulk_in(const struct usb_endpoint_descriptor *epd)
+static inline int usb_endpoint_is_bulk_in(
+				const struct usb_endpoint_descriptor *epd)
 {
 	return (usb_endpoint_xfer_bulk(epd) && usb_endpoint_dir_in(epd));
 }
@@ -682,7 +693,8 @@
  * Returns true if the endpoint has bulk transfer type and OUT direction,
  * otherwise it returns false.
  */
-static inline int usb_endpoint_is_bulk_out(const struct usb_endpoint_descriptor *epd)
+static inline int usb_endpoint_is_bulk_out(
+				const struct usb_endpoint_descriptor *epd)
 {
 	return (usb_endpoint_xfer_bulk(epd) && usb_endpoint_dir_out(epd));
 }
@@ -694,7 +706,8 @@
  * Returns true if the endpoint has interrupt transfer type and IN direction,
  * otherwise it returns false.
  */
-static inline int usb_endpoint_is_int_in(const struct usb_endpoint_descriptor *epd)
+static inline int usb_endpoint_is_int_in(
+				const struct usb_endpoint_descriptor *epd)
 {
 	return (usb_endpoint_xfer_int(epd) && usb_endpoint_dir_in(epd));
 }
@@ -706,7 +719,8 @@
  * Returns true if the endpoint has interrupt transfer type and OUT direction,
  * otherwise it returns false.
  */
-static inline int usb_endpoint_is_int_out(const struct usb_endpoint_descriptor *epd)
+static inline int usb_endpoint_is_int_out(
+				const struct usb_endpoint_descriptor *epd)
 {
 	return (usb_endpoint_xfer_int(epd) && usb_endpoint_dir_out(epd));
 }
@@ -718,7 +732,8 @@
  * Returns true if the endpoint has isochronous transfer type and IN direction,
  * otherwise it returns false.
  */
-static inline int usb_endpoint_is_isoc_in(const struct usb_endpoint_descriptor *epd)
+static inline int usb_endpoint_is_isoc_in(
+				const struct usb_endpoint_descriptor *epd)
 {
 	return (usb_endpoint_xfer_isoc(epd) && usb_endpoint_dir_in(epd));
 }
@@ -730,7 +745,8 @@
  * Returns true if the endpoint has isochronous transfer type and OUT direction,
  * otherwise it returns false.
  */
-static inline int usb_endpoint_is_isoc_out(const struct usb_endpoint_descriptor *epd)
+static inline int usb_endpoint_is_isoc_out(
+				const struct usb_endpoint_descriptor *epd)
 {
 	return (usb_endpoint_xfer_isoc(epd) && usb_endpoint_dir_out(epd));
 }
@@ -761,8 +777,9 @@
  * specific device.
  */
 #define USB_DEVICE(vend,prod) \
-	.match_flags = USB_DEVICE_ID_MATCH_DEVICE, .idVendor = (vend), \
-			.idProduct = (prod)
+	.match_flags = USB_DEVICE_ID_MATCH_DEVICE, \
+	.idVendor = (vend), \
+	.idProduct = (prod)
 /**
  * USB_DEVICE_VER - macro used to describe a specific usb device with a
  *		version range
@@ -774,10 +791,12 @@
  * This macro is used to create a struct usb_device_id that matches a
  * specific device, with a version range.
  */
-#define USB_DEVICE_VER(vend,prod,lo,hi) \
+#define USB_DEVICE_VER(vend, prod, lo, hi) \
 	.match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION, \
-	.idVendor = (vend), .idProduct = (prod), \
-	.bcdDevice_lo = (lo), .bcdDevice_hi = (hi)
+	.idVendor = (vend), \
+	.idProduct = (prod), \
+	.bcdDevice_lo = (lo), \
+	.bcdDevice_hi = (hi)
 
 /**
  * USB_DEVICE_INTERFACE_PROTOCOL - macro used to describe a usb
@@ -789,8 +808,9 @@
  * 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, \
+#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)
@@ -804,12 +824,14 @@
  * This macro is used to create a struct usb_device_id that matches a
  * specific class of devices.
  */
-#define USB_DEVICE_INFO(cl,sc,pr) \
-	.match_flags = USB_DEVICE_ID_MATCH_DEV_INFO, .bDeviceClass = (cl), \
-	.bDeviceSubClass = (sc), .bDeviceProtocol = (pr)
+#define USB_DEVICE_INFO(cl, sc, pr) \
+	.match_flags = USB_DEVICE_ID_MATCH_DEV_INFO, \
+	.bDeviceClass = (cl), \
+	.bDeviceSubClass = (sc), \
+	.bDeviceProtocol = (pr)
 
 /**
- * USB_INTERFACE_INFO - macro used to describe a class of usb interfaces 
+ * USB_INTERFACE_INFO - macro used to describe a class of usb interfaces
  * @cl: bInterfaceClass value
  * @sc: bInterfaceSubClass value
  * @pr: bInterfaceProtocol value
@@ -817,9 +839,11 @@
  * This macro is used to create a struct usb_device_id that matches a
  * specific class of interfaces.
  */
-#define USB_INTERFACE_INFO(cl,sc,pr) \
-	.match_flags = USB_DEVICE_ID_MATCH_INT_INFO, .bInterfaceClass = (cl), \
-	.bInterfaceSubClass = (sc), .bInterfaceProtocol = (pr)
+#define USB_INTERFACE_INFO(cl, sc, pr) \
+	.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
@@ -836,12 +860,14 @@
  * 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) \
+#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), \
+	.idVendor = (vend), \
+	.idProduct = (prod), \
 	.bInterfaceClass = (cl), \
-	.bInterfaceSubClass = (sc), .bInterfaceProtocol = (pr)
+	.bInterfaceSubClass = (sc), \
+	.bInterfaceProtocol = (pr)
 
 /* ----------------------------------------------------------------------- */
 
@@ -1119,7 +1145,7 @@
  *	transferred.  It will normally be the same as requested, unless
  *	either an error was reported or a short read was performed.
  *	The URB_SHORT_NOT_OK transfer flag may be used to make such
- *	short reads be reported as errors. 
+ *	short reads be reported as errors.
  * @setup_packet: Only used for control transfers, this points to eight bytes
  *	of setup data.  Control transfers always start by sending this data
  *	to the device.  Then transfer_buffer is read or written, if needed.
@@ -1138,7 +1164,7 @@
  * @complete: Completion handler. This URB is passed as the parameter to the
  *	completion function.  The completion function may then do what
  *	it likes with the URB, including resubmitting or freeing it.
- * @iso_frame_desc: Used to provide arrays of ISO transfer buffers and to 
+ * @iso_frame_desc: Used to provide arrays of ISO transfer buffers and to
  *	collect the transfer status for each buffer.
  *
  * This structure identifies USB transfer requests.  URBs must be allocated by
@@ -1242,8 +1268,7 @@
  * when the urb is owned by the hcd, that is, since the call to
  * usb_submit_urb() till the entry into the completion routine.
  */
-struct urb
-{
+struct urb {
 	/* private: usb core and host controller only fields in the urb */
 	struct kref kref;		/* reference count of the URB */
 	void *hcpriv;			/* private data for host controller */
@@ -1254,10 +1279,10 @@
 	/* 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 list_head anchor_list;	/* the URB may be anchored */
 	struct usb_anchor *anchor;
 	struct usb_device *dev; 	/* (in) pointer to associated device */
-	struct usb_host_endpoint *ep;	/* (internal) pointer to endpoint struct */
+	struct usb_host_endpoint *ep;	/* (internal) pointer to endpoint */
 	unsigned int pipe;		/* (in) pipe information */
 	int status;			/* (return) non-ISO status */
 	unsigned int transfer_flags;	/* (in) URB_SHORT_NOT_OK | ...*/
@@ -1294,14 +1319,14 @@
  * Initializes a control urb with the proper information needed to submit
  * it to a device.
  */
-static inline void usb_fill_control_urb (struct urb *urb,
-					 struct usb_device *dev,
-					 unsigned int pipe,
-					 unsigned char *setup_packet,
-					 void *transfer_buffer,
-					 int buffer_length,
-					 usb_complete_t complete_fn,
-					 void *context)
+static inline void usb_fill_control_urb(struct urb *urb,
+					struct usb_device *dev,
+					unsigned int pipe,
+					unsigned char *setup_packet,
+					void *transfer_buffer,
+					int buffer_length,
+					usb_complete_t complete_fn,
+					void *context)
 {
 	urb->dev = dev;
 	urb->pipe = pipe;
@@ -1325,13 +1350,13 @@
  * Initializes a bulk urb with the proper information needed to submit it
  * to a device.
  */
-static inline void usb_fill_bulk_urb (struct urb *urb,
-				      struct usb_device *dev,
-				      unsigned int pipe,
-				      void *transfer_buffer,
-				      int buffer_length,
-				      usb_complete_t complete_fn,
-				      void *context)
+static inline void usb_fill_bulk_urb(struct urb *urb,
+				     struct usb_device *dev,
+				     unsigned int pipe,
+				     void *transfer_buffer,
+				     int buffer_length,
+				     usb_complete_t complete_fn,
+				     void *context)
 {
 	urb->dev = dev;
 	urb->pipe = pipe;
@@ -1359,14 +1384,14 @@
  * the endpoint interval, and express polling intervals in microframes
  * (eight per millisecond) rather than in frames (one per millisecond).
  */
-static inline void usb_fill_int_urb (struct urb *urb,
-				     struct usb_device *dev,
-				     unsigned int pipe,
-				     void *transfer_buffer,
-				     int buffer_length,
-				     usb_complete_t complete_fn,
-				     void *context,
-				     int interval)
+static inline void usb_fill_int_urb(struct urb *urb,
+				    struct usb_device *dev,
+				    unsigned int pipe,
+				    void *transfer_buffer,
+				    int buffer_length,
+				    usb_complete_t complete_fn,
+				    void *context,
+				    int interval)
 {
 	urb->dev = dev;
 	urb->pipe = pipe;
@@ -1419,15 +1444,15 @@
 	return (urb->transfer_flags & URB_DIR_MASK) == URB_DIR_OUT;
 }
 
-void *usb_buffer_alloc (struct usb_device *dev, size_t size,
+void *usb_buffer_alloc(struct usb_device *dev, size_t size,
 	gfp_t mem_flags, dma_addr_t *dma);
-void usb_buffer_free (struct usb_device *dev, size_t size,
+void usb_buffer_free(struct usb_device *dev, size_t size,
 	void *addr, dma_addr_t dma);
 
 #if 0
-struct urb *usb_buffer_map (struct urb *urb);
-void usb_buffer_dmasync (struct urb *urb);
-void usb_buffer_unmap (struct urb *urb);
+struct urb *usb_buffer_map(struct urb *urb);
+void usb_buffer_dmasync(struct urb *urb);
+void usb_buffer_unmap(struct urb *urb);
 #endif
 
 struct scatterlist;
@@ -1499,7 +1524,7 @@
 	int			status;
 	size_t			bytes;
 
-	/* 
+	/*
 	 * members below are private: to usbcore,
 	 * and are not provided for driver access!
 	 */
@@ -1517,18 +1542,18 @@
 	struct completion	complete;
 };
 
-int usb_sg_init (
+int usb_sg_init(
 	struct usb_sg_request	*io,
 	struct usb_device	*dev,
-	unsigned		pipe, 
+	unsigned		pipe,
 	unsigned		period,
 	struct scatterlist	*sg,
 	int			nents,
 	size_t			length,
 	gfp_t			mem_flags
 );
-void usb_sg_cancel (struct usb_sg_request *io);
-void usb_sg_wait (struct usb_sg_request *io);
+void usb_sg_cancel(struct usb_sg_request *io);
+void usb_sg_wait(struct usb_sg_request *io);
 
 
 /* ----------------------------------------------------------------------- */
@@ -1585,21 +1610,21 @@
 
 /* Create various pipes... */
 #define usb_sndctrlpipe(dev,endpoint)	\
-	((PIPE_CONTROL << 30) | __create_pipe(dev,endpoint))
+	((PIPE_CONTROL << 30) | __create_pipe(dev, endpoint))
 #define usb_rcvctrlpipe(dev,endpoint)	\
-	((PIPE_CONTROL << 30) | __create_pipe(dev,endpoint) | USB_DIR_IN)
+	((PIPE_CONTROL << 30) | __create_pipe(dev, endpoint) | USB_DIR_IN)
 #define usb_sndisocpipe(dev,endpoint)	\
-	((PIPE_ISOCHRONOUS << 30) | __create_pipe(dev,endpoint))
+	((PIPE_ISOCHRONOUS << 30) | __create_pipe(dev, endpoint))
 #define usb_rcvisocpipe(dev,endpoint)	\
-	((PIPE_ISOCHRONOUS << 30) | __create_pipe(dev,endpoint) | USB_DIR_IN)
+	((PIPE_ISOCHRONOUS << 30) | __create_pipe(dev, endpoint) | USB_DIR_IN)
 #define usb_sndbulkpipe(dev,endpoint)	\
-	((PIPE_BULK << 30) | __create_pipe(dev,endpoint))
+	((PIPE_BULK << 30) | __create_pipe(dev, endpoint))
 #define usb_rcvbulkpipe(dev,endpoint)	\
-	((PIPE_BULK << 30) | __create_pipe(dev,endpoint) | USB_DIR_IN)
+	((PIPE_BULK << 30) | __create_pipe(dev, endpoint) | USB_DIR_IN)
 #define usb_sndintpipe(dev,endpoint)	\
-	((PIPE_INTERRUPT << 30) | __create_pipe(dev,endpoint))
+	((PIPE_INTERRUPT << 30) | __create_pipe(dev, endpoint))
 #define usb_rcvintpipe(dev,endpoint)	\
-	((PIPE_INTERRUPT << 30) | __create_pipe(dev,endpoint) | USB_DIR_IN)
+	((PIPE_INTERRUPT << 30) | __create_pipe(dev, endpoint) | USB_DIR_IN)
 
 /*-------------------------------------------------------------------------*/
 
diff --git a/include/linux/usb/Kbuild b/include/linux/usb/Kbuild
index 6ce42bf..b8cba1d 100644
--- a/include/linux/usb/Kbuild
+++ b/include/linux/usb/Kbuild
@@ -1,6 +1,7 @@
-unifdef-y += audio.h
-unifdef-y += cdc.h
-unifdef-y += ch9.h
-unifdef-y += gadgetfs.h
-unifdef-y += midi.h
+header-y += audio.h
+header-y += cdc.h
+header-y += ch9.h
+header-y += gadgetfs.h
+header-y += midi.h
+unifdef-y += g_printer.h
 
diff --git a/include/linux/usb/audio.h b/include/linux/usb/audio.h
index 6bd2359..2dfeef1 100644
--- a/include/linux/usb/audio.h
+++ b/include/linux/usb/audio.h
@@ -27,13 +27,13 @@
 
 /* 4.3.2  Class-Specific AC Interface Descriptor */
 struct usb_ac_header_descriptor {
-	__u8  bLength;			// 8+n
-	__u8  bDescriptorType;		// USB_DT_CS_INTERFACE
-	__u8  bDescriptorSubtype;	// USB_MS_HEADER
-	__le16 bcdADC;			// 0x0100
-	__le16 wTotalLength;		// includes Unit and Terminal desc.
-	__u8  bInCollection;		// n
-	__u8  baInterfaceNr[];		// [n]
+	__u8  bLength;			/* 8+n */
+	__u8  bDescriptorType;		/* USB_DT_CS_INTERFACE */
+	__u8  bDescriptorSubtype;	/* USB_MS_HEADER */
+	__le16 bcdADC;			/* 0x0100 */
+	__le16 wTotalLength;		/* includes Unit and Terminal desc. */
+	__u8  bInCollection;		/* n */
+	__u8  baInterfaceNr[];		/* [n] */
 } __attribute__ ((packed));
 
 #define USB_DT_AC_HEADER_SIZE(n)	(8+(n))
diff --git a/include/linux/usb/cdc.h b/include/linux/usb/cdc.h
index 2204ae2..94ee4ec 100644
--- a/include/linux/usb/cdc.h
+++ b/include/linux/usb/cdc.h
@@ -29,16 +29,16 @@
  * Class-Specific descriptors ... there are a couple dozen of them
  */
 
-#define USB_CDC_HEADER_TYPE		0x00		/* header_desc */
-#define USB_CDC_CALL_MANAGEMENT_TYPE	0x01		/* call_mgmt_descriptor */
-#define USB_CDC_ACM_TYPE		0x02		/* acm_descriptor */
-#define USB_CDC_UNION_TYPE		0x06		/* union_desc */
+#define USB_CDC_HEADER_TYPE		0x00	/* header_desc */
+#define USB_CDC_CALL_MANAGEMENT_TYPE	0x01	/* call_mgmt_descriptor */
+#define USB_CDC_ACM_TYPE		0x02	/* acm_descriptor */
+#define USB_CDC_UNION_TYPE		0x06	/* union_desc */
 #define USB_CDC_COUNTRY_TYPE		0x07
-#define USB_CDC_NETWORK_TERMINAL_TYPE	0x0a		/* network_terminal_desc */
-#define USB_CDC_ETHERNET_TYPE		0x0f		/* ether_desc */
+#define USB_CDC_NETWORK_TERMINAL_TYPE	0x0a	/* network_terminal_desc */
+#define USB_CDC_ETHERNET_TYPE		0x0f	/* ether_desc */
 #define USB_CDC_WHCM_TYPE		0x11
-#define USB_CDC_MDLM_TYPE		0x12		/* mdlm_desc */
-#define USB_CDC_MDLM_DETAIL_TYPE	0x13		/* mdlm_detail_desc */
+#define USB_CDC_MDLM_TYPE		0x12	/* mdlm_desc */
+#define USB_CDC_MDLM_DETAIL_TYPE	0x13	/* mdlm_detail_desc */
 #define USB_CDC_DMM_TYPE		0x14
 #define USB_CDC_OBEX_TYPE		0x15
 
diff --git a/include/linux/usb/g_printer.h b/include/linux/usb/g_printer.h
new file mode 100644
index 0000000..0c5ea1e
--- /dev/null
+++ b/include/linux/usb/g_printer.h
@@ -0,0 +1,31 @@
+/*
+ * g_printer.h -- Header file for USB Printer gadget driver
+ *
+ * Copyright (C) 2007 Craig W. Nadler
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#define PRINTER_NOT_ERROR	0x08
+#define PRINTER_SELECTED	0x10
+#define PRINTER_PAPER_EMPTY	0x20
+
+/* The 'g' code is also used by gadgetfs ioctl requests.
+ * Don't add any colliding codes to either driver, and keep
+ * them in unique ranges (size 0x20 for now).
+ */
+#define GADGET_GET_PRINTER_STATUS	_IOR('g', 0x21, unsigned char)
+#define GADGET_SET_PRINTER_STATUS	_IOWR('g', 0x22, unsigned char)
diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h
index c1527c2..aa3047f 100644
--- a/include/linux/usb/gadget.h
+++ b/include/linux/usb/gadget.h
@@ -70,9 +70,10 @@
  *
  * Bulk endpoints can use any size buffers, and can also be used for interrupt
  * transfers. interrupt-only endpoints can be much less functional.
+ *
+ * NOTE:  this is analagous to 'struct urb' on the host side, except that
+ * it's thinner and promotes more pre-allocation.
  */
-	// NOTE this is analagous to 'struct urb' on the host side,
-	// except that it's thinner and promotes more pre-allocation.
 
 struct usb_request {
 	void			*buf;
@@ -168,10 +169,10 @@
  *
  * returns zero, or a negative error code.
  */
-static inline int
-usb_ep_enable (struct usb_ep *ep, const struct usb_endpoint_descriptor *desc)
+static inline int usb_ep_enable(struct usb_ep *ep,
+				const struct usb_endpoint_descriptor *desc)
 {
-	return ep->ops->enable (ep, desc);
+	return ep->ops->enable(ep, desc);
 }
 
 /**
@@ -186,10 +187,9 @@
  *
  * returns zero, or a negative error code.
  */
-static inline int
-usb_ep_disable (struct usb_ep *ep)
+static inline int usb_ep_disable(struct usb_ep *ep)
 {
-	return ep->ops->disable (ep);
+	return ep->ops->disable(ep);
 }
 
 /**
@@ -206,10 +206,10 @@
  *
  * Returns the request, or null if one could not be allocated.
  */
-static inline struct usb_request *
-usb_ep_alloc_request (struct usb_ep *ep, gfp_t gfp_flags)
+static inline struct usb_request *usb_ep_alloc_request(struct usb_ep *ep,
+						       gfp_t gfp_flags)
 {
-	return ep->ops->alloc_request (ep, gfp_flags);
+	return ep->ops->alloc_request(ep, gfp_flags);
 }
 
 /**
@@ -221,10 +221,10 @@
  * Caller guarantees the request is not queued, and that it will
  * no longer be requeued (or otherwise used).
  */
-static inline void
-usb_ep_free_request (struct usb_ep *ep, struct usb_request *req)
+static inline void usb_ep_free_request(struct usb_ep *ep,
+				       struct usb_request *req)
 {
-	ep->ops->free_request (ep, req);
+	ep->ops->free_request(ep, req);
 }
 
 /**
@@ -281,10 +281,10 @@
  * report errors; errors will also be
  * reported when the usb peripheral is disconnected.
  */
-static inline int
-usb_ep_queue (struct usb_ep *ep, struct usb_request *req, gfp_t gfp_flags)
+static inline int usb_ep_queue(struct usb_ep *ep,
+			       struct usb_request *req, gfp_t gfp_flags)
 {
-	return ep->ops->queue (ep, req, gfp_flags);
+	return ep->ops->queue(ep, req, gfp_flags);
 }
 
 /**
@@ -301,9 +301,9 @@
  * restrictions prevent drivers from supporting configuration changes,
  * even to configuration zero (a "chapter 9" requirement).
  */
-static inline int usb_ep_dequeue (struct usb_ep *ep, struct usb_request *req)
+static inline int usb_ep_dequeue(struct usb_ep *ep, struct usb_request *req)
 {
-	return ep->ops->dequeue (ep, req);
+	return ep->ops->dequeue(ep, req);
 }
 
 /**
@@ -327,10 +327,9 @@
  * transfer requests are still queued, or if the controller hardware
  * (usually a FIFO) still holds bytes that the host hasn't collected.
  */
-static inline int
-usb_ep_set_halt (struct usb_ep *ep)
+static inline int usb_ep_set_halt(struct usb_ep *ep)
 {
-	return ep->ops->set_halt (ep, 1);
+	return ep->ops->set_halt(ep, 1);
 }
 
 /**
@@ -346,10 +345,9 @@
  * Note that some hardware can't support this request (like pxa2xx_udc),
  * and accordingly can't correctly implement interface altsettings.
  */
-static inline int
-usb_ep_clear_halt (struct usb_ep *ep)
+static inline int usb_ep_clear_halt(struct usb_ep *ep)
 {
-	return ep->ops->set_halt (ep, 0);
+	return ep->ops->set_halt(ep, 0);
 }
 
 /**
@@ -367,11 +365,10 @@
  * errno if the endpoint doesn't use a FIFO or doesn't support such
  * precise handling.
  */
-static inline int
-usb_ep_fifo_status (struct usb_ep *ep)
+static inline int usb_ep_fifo_status(struct usb_ep *ep)
 {
 	if (ep->ops->fifo_status)
-		return ep->ops->fifo_status (ep);
+		return ep->ops->fifo_status(ep);
 	else
 		return -EOPNOTSUPP;
 }
@@ -385,11 +382,10 @@
  * must never be used except when endpoint is not being used for any
  * protocol translation.
  */
-static inline void
-usb_ep_fifo_flush (struct usb_ep *ep)
+static inline void usb_ep_fifo_flush(struct usb_ep *ep)
 {
 	if (ep->ops->fifo_flush)
-		ep->ops->fifo_flush (ep);
+		ep->ops->fifo_flush(ep);
 }
 
 
@@ -469,10 +465,10 @@
 	struct device			dev;
 };
 
-static inline void set_gadget_data (struct usb_gadget *gadget, void *data)
-	{ dev_set_drvdata (&gadget->dev, data); }
-static inline void *get_gadget_data (struct usb_gadget *gadget)
-	{ return dev_get_drvdata (&gadget->dev); }
+static inline void set_gadget_data(struct usb_gadget *gadget, void *data)
+	{ dev_set_drvdata(&gadget->dev, data); }
+static inline void *get_gadget_data(struct usb_gadget *gadget)
+	{ return dev_get_drvdata(&gadget->dev); }
 
 /* iterates the non-control endpoints; 'tmp' is a struct usb_ep pointer */
 #define gadget_for_each_ep(tmp,gadget) \
@@ -511,7 +507,6 @@
 #endif
 }
 
-
 /**
  * usb_gadget_frame_number - returns the current frame number
  * @gadget: controller that reports the frame number
@@ -519,9 +514,9 @@
  * Returns the usb frame number, normally eleven bits from a SOF packet,
  * or negative errno if this device doesn't support this capability.
  */
-static inline int usb_gadget_frame_number (struct usb_gadget *gadget)
+static inline int usb_gadget_frame_number(struct usb_gadget *gadget)
 {
-	return gadget->ops->get_frame (gadget);
+	return gadget->ops->get_frame(gadget);
 }
 
 /**
@@ -537,11 +532,11 @@
  * even if OTG isn't otherwise in use.  OTG devices may also start
  * remote wakeup even when hosts don't explicitly enable it.
  */
-static inline int usb_gadget_wakeup (struct usb_gadget *gadget)
+static inline int usb_gadget_wakeup(struct usb_gadget *gadget)
 {
 	if (!gadget->ops->wakeup)
 		return -EOPNOTSUPP;
-	return gadget->ops->wakeup (gadget);
+	return gadget->ops->wakeup(gadget);
 }
 
 /**
@@ -553,12 +548,11 @@
  *
  * returns zero on success, else negative errno.
  */
-static inline int
-usb_gadget_set_selfpowered (struct usb_gadget *gadget)
+static inline int usb_gadget_set_selfpowered(struct usb_gadget *gadget)
 {
 	if (!gadget->ops->set_selfpowered)
 		return -EOPNOTSUPP;
-	return gadget->ops->set_selfpowered (gadget, 1);
+	return gadget->ops->set_selfpowered(gadget, 1);
 }
 
 /**
@@ -571,12 +565,11 @@
  *
  * returns zero on success, else negative errno.
  */
-static inline int
-usb_gadget_clear_selfpowered (struct usb_gadget *gadget)
+static inline int usb_gadget_clear_selfpowered(struct usb_gadget *gadget)
 {
 	if (!gadget->ops->set_selfpowered)
 		return -EOPNOTSUPP;
-	return gadget->ops->set_selfpowered (gadget, 0);
+	return gadget->ops->set_selfpowered(gadget, 0);
 }
 
 /**
@@ -591,12 +584,11 @@
  *
  * Returns zero on success, else negative errno.
  */
-static inline int
-usb_gadget_vbus_connect(struct usb_gadget *gadget)
+static inline int usb_gadget_vbus_connect(struct usb_gadget *gadget)
 {
 	if (!gadget->ops->vbus_session)
 		return -EOPNOTSUPP;
-	return gadget->ops->vbus_session (gadget, 1);
+	return gadget->ops->vbus_session(gadget, 1);
 }
 
 /**
@@ -611,12 +603,11 @@
  *
  * Returns zero on success, else negative errno.
  */
-static inline int
-usb_gadget_vbus_draw(struct usb_gadget *gadget, unsigned mA)
+static inline int usb_gadget_vbus_draw(struct usb_gadget *gadget, unsigned mA)
 {
 	if (!gadget->ops->vbus_draw)
 		return -EOPNOTSUPP;
-	return gadget->ops->vbus_draw (gadget, mA);
+	return gadget->ops->vbus_draw(gadget, mA);
 }
 
 /**
@@ -629,12 +620,11 @@
  *
  * Returns zero on success, else negative errno.
  */
-static inline int
-usb_gadget_vbus_disconnect(struct usb_gadget *gadget)
+static inline int usb_gadget_vbus_disconnect(struct usb_gadget *gadget)
 {
 	if (!gadget->ops->vbus_session)
 		return -EOPNOTSUPP;
-	return gadget->ops->vbus_session (gadget, 0);
+	return gadget->ops->vbus_session(gadget, 0);
 }
 
 /**
@@ -648,12 +638,11 @@
  *
  * Returns zero on success, else negative errno.
  */
-static inline int
-usb_gadget_connect (struct usb_gadget *gadget)
+static inline int usb_gadget_connect(struct usb_gadget *gadget)
 {
 	if (!gadget->ops->pullup)
 		return -EOPNOTSUPP;
-	return gadget->ops->pullup (gadget, 1);
+	return gadget->ops->pullup(gadget, 1);
 }
 
 /**
@@ -671,16 +660,14 @@
  *
  * Returns zero on success, else negative errno.
  */
-static inline int
-usb_gadget_disconnect (struct usb_gadget *gadget)
+static inline int usb_gadget_disconnect(struct usb_gadget *gadget)
 {
 	if (!gadget->ops->pullup)
 		return -EOPNOTSUPP;
-	return gadget->ops->pullup (gadget, 0);
+	return gadget->ops->pullup(gadget, 0);
 }
 
 
-
 /*-------------------------------------------------------------------------*/
 
 /**
@@ -764,7 +751,7 @@
 	void			(*suspend)(struct usb_gadget *);
 	void			(*resume)(struct usb_gadget *);
 
-	// FIXME support safe rmmod
+	/* FIXME support safe rmmod */
 	struct device_driver	driver;
 };
 
@@ -790,7 +777,7 @@
  * the bind() functions will be in init sections.
  * This function must be called in a context that can sleep.
  */
-int usb_gadget_register_driver (struct usb_gadget_driver *driver);
+int usb_gadget_register_driver(struct usb_gadget_driver *driver);
 
 /**
  * usb_gadget_unregister_driver - unregister a gadget driver
@@ -805,7 +792,7 @@
  * will in in exit sections, so may not be linked in some kernels.
  * This function must be called in a context that can sleep.
  */
-int usb_gadget_unregister_driver (struct usb_gadget_driver *driver);
+int usb_gadget_unregister_driver(struct usb_gadget_driver *driver);
 
 /*-------------------------------------------------------------------------*/
 
@@ -838,7 +825,7 @@
 };
 
 /* put descriptor for string with that id into buf (buflen >= 256) */
-int usb_gadget_get_string (struct usb_gadget_strings *table, int id, u8 *buf);
+int usb_gadget_get_string(struct usb_gadget_strings *table, int id, u8 *buf);
 
 /*-------------------------------------------------------------------------*/
 
@@ -856,10 +843,10 @@
 
 /* utility wrapping a simple endpoint selection policy */
 
-extern struct usb_ep *usb_ep_autoconfig (struct usb_gadget *,
+extern struct usb_ep *usb_ep_autoconfig(struct usb_gadget *,
 			struct usb_endpoint_descriptor *) __devinit;
 
-extern void usb_ep_autoconfig_reset (struct usb_gadget *) __devinit;
+extern void usb_ep_autoconfig_reset(struct usb_gadget *) __devinit;
 
 #endif  /* __KERNEL__ */
 
diff --git a/include/linux/usb/gadgetfs.h b/include/linux/usb/gadgetfs.h
index e8654c3..c291ab1 100644
--- a/include/linux/usb/gadgetfs.h
+++ b/include/linux/usb/gadgetfs.h
@@ -36,7 +36,7 @@
 	GADGETFS_DISCONNECT,
 	GADGETFS_SETUP,
 	GADGETFS_SUSPEND,
-	// and likely more !
+	/* and likely more ! */
 };
 
 /* NOTE:  this structure must stay the same size and layout on
@@ -44,21 +44,28 @@
  */
 struct usb_gadgetfs_event {
 	union {
-		// NOP, DISCONNECT, SUSPEND: nothing
-		// ... some hardware can't report disconnection
+		/* NOP, DISCONNECT, SUSPEND: nothing
+		 * ... some hardware can't report disconnection
+		 */
 
-		// CONNECT: just the speed
+		/* 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
+		/* 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;
 };
 
 
+/* The 'g' code is also used by printer gadget ioctl requests.
+ * Don't add any colliding codes to either driver, and keep
+ * them in unique ranges (size 0x20 for now).
+ */
+
 /* endpoint ioctls */
 
 /* IN transfers may be reported to the gadget driver as complete
@@ -68,14 +75,14 @@
  * 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)
+#define	GADGETFS_FIFO_STATUS	_IO('g', 1)
 
 /* discards any unclaimed data in the fifo. */
-#define	GADGETFS_FIFO_FLUSH	_IO('g',2)
+#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)
+#define	GADGETFS_CLEAR_HALT	_IO('g', 3)
 
 #endif /* __LINUX_USB_GADGETFS_H */
diff --git a/include/linux/usb/iowarrior.h b/include/linux/usb/iowarrior.h
index cbbe020..de6f380 100644
--- a/include/linux/usb/iowarrior.h
+++ b/include/linux/usb/iowarrior.h
@@ -14,14 +14,23 @@
    this information.
 */
 struct iowarrior_info {
-	__u32 vendor;		/* vendor id : supposed to be USB_VENDOR_ID_CODEMERCS in all cases */
-	__u32 product;		/* product id : depends on type of chip (USB_DEVICE_ID_CODEMERCS_XXXXX) */
-	__u8 serial[9];		/* the serial number of our chip (if a serial-number is not available this is empty string) */
-	__u32 revision;		/* revision number of the chip */
-	__u32 speed;		/* USB-speed of the device (0=UNKNOWN, 1=LOW, 2=FULL 3=HIGH) */
-	__u32 power;		/* power consumption of the device in mA */
-	__u32 if_num;		/* the number of the endpoint */
-	__u32 report_size;	/* size of the data-packets on this interface */
+	/* vendor id : supposed to be USB_VENDOR_ID_CODEMERCS in all cases */
+	__u32 vendor;
+	/* product id : depends on type of chip (USB_DEVICE_ID_CODEMERCS_X) */
+	__u32 product;
+	/* the serial number of our chip (if a serial-number is not available
+	 * this is empty string) */
+	__u8 serial[9];
+	/* revision number of the chip */
+	__u32 revision;
+	/* USB-speed of the device (0=UNKNOWN, 1=LOW, 2=FULL 3=HIGH) */
+	__u32 speed;
+	/* power consumption of the device in mA */
+	__u32 power;
+	/* the number of the endpoint */
+	__u32 if_num;
+	/* size of the data-packets on this interface */
+	__u32 report_size;
 };
 
 /*
diff --git a/include/linux/usb/isp116x.h b/include/linux/usb/isp116x.h
index 436dd8a..67d2826 100644
--- a/include/linux/usb/isp116x.h
+++ b/include/linux/usb/isp116x.h
@@ -25,5 +25,5 @@
 	   300ns delay between access to ADDR_REG and DATA_REG
 	   OE, WE MUST NOT be changed during these intervals
 	 */
-	void (*delay) (struct device * dev, int delay);
+	void (*delay) (struct device *dev, int delay);
 };
diff --git a/include/linux/usb/midi.h b/include/linux/usb/midi.h
index 11a97d5..80624c5 100644
--- a/include/linux/usb/midi.h
+++ b/include/linux/usb/midi.h
@@ -47,9 +47,9 @@
 /* 6.1.2.2  MIDI IN Jack Descriptor */
 struct usb_midi_in_jack_descriptor {
 	__u8  bLength;
-	__u8  bDescriptorType;		// USB_DT_CS_INTERFACE
-	__u8  bDescriptorSubtype;	// USB_MS_MIDI_IN_JACK
-	__u8  bJackType;		// USB_MS_EMBEDDED/EXTERNAL
+	__u8  bDescriptorType;		/* USB_DT_CS_INTERFACE */
+	__u8  bDescriptorSubtype;	/* USB_MS_MIDI_IN_JACK */
+	__u8  bJackType;		/* USB_MS_EMBEDDED/EXTERNAL */
 	__u8  bJackID;
 	__u8  iJack;
 } __attribute__ ((packed));
@@ -64,12 +64,12 @@
 /* 6.1.2.3  MIDI OUT Jack Descriptor */
 struct usb_midi_out_jack_descriptor {
 	__u8  bLength;
-	__u8  bDescriptorType;		// USB_DT_CS_INTERFACE
-	__u8  bDescriptorSubtype;	// USB_MS_MIDI_OUT_JACK
-	__u8  bJackType;		// USB_MS_EMBEDDED/EXTERNAL
+	__u8  bDescriptorType;		/* USB_DT_CS_INTERFACE */
+	__u8  bDescriptorSubtype;	/* USB_MS_MIDI_OUT_JACK */
+	__u8  bJackType;		/* USB_MS_EMBEDDED/EXTERNAL */
 	__u8  bJackID;
-	__u8  bNrInputPins;		// p
-	struct usb_midi_source_pin pins[]; // [p]
+	__u8  bNrInputPins;		/* p */
+	struct usb_midi_source_pin pins[]; /* [p] */
 	/*__u8  iJack;  -- ommitted due to variable-sized pins[] */
 } __attribute__ ((packed));
 
@@ -90,11 +90,11 @@
 
 /* 6.2.2  Class-Specific MS Bulk Data Endpoint Descriptor */
 struct usb_ms_endpoint_descriptor {
-	__u8  bLength;			// 4+n
-	__u8  bDescriptorType;		// USB_DT_CS_ENDPOINT
-	__u8  bDescriptorSubtype;	// USB_MS_GENERAL
-	__u8  bNumEmbMIDIJack;		// n
-	__u8  baAssocJackID[];		// [n]
+	__u8  bLength;			/* 4+n */
+	__u8  bDescriptorType;		/* USB_DT_CS_ENDPOINT */
+	__u8  bDescriptorSubtype;	/* USB_MS_GENERAL */
+	__u8  bNumEmbMIDIJack;		/* n */
+	__u8  baAssocJackID[];		/* [n] */
 } __attribute__ ((packed));
 
 #define USB_DT_MS_ENDPOINT_SIZE(n)	(4 + (n))
diff --git a/include/linux/usb/net2280.h b/include/linux/usb/net2280.h
index c602f88..ec897cb 100644
--- a/include/linux/usb/net2280.h
+++ b/include/linux/usb/net2280.h
@@ -37,7 +37,7 @@
 
 /* main registers, BAR0 + 0x0000 */
 struct net2280_regs {
-	// offset 0x0000
+	/* offset 0x0000 */
 	u32		devinit;
 #define     LOCAL_CLOCK_FREQUENCY                               8
 #define     FORCE_PCI_RESET                                     7
@@ -61,7 +61,7 @@
 #define     EEPROM_WRITE_DATA                                   0
 	u32		eeclkfreq;
 	u32		_unused0;
-	// offset 0x0010
+	/* offset 0x0010 */
 
 	u32		pciirqenb0;		/* interrupt PCI master ... */
 #define     SETUP_PACKET_INTERRUPT_ENABLE                       7
@@ -131,7 +131,7 @@
 #define     RESUME_INTERRUPT_ENABLE                             1
 #define     SOF_INTERRUPT_ENABLE                                0
 
-	// offset 0x0020
+	/* offset 0x0020 */
 	u32		_unused1;
 	u32		usbirqenb1;
 #define     USB_INTERRUPT_ENABLE                                31
@@ -195,7 +195,7 @@
 #define     SUSPEND_REQUEST_CHANGE_INTERRUPT                    2
 #define     RESUME_INTERRUPT                                    1
 #define     SOF_INTERRUPT                                       0
-	// offset 0x0030
+	/* offset 0x0030 */
 	u32		idxaddr;
 	u32		idxdata;
 	u32		fifoctl;
@@ -204,7 +204,7 @@
 #define     PCI_BASE2_SELECT                                    2
 #define     FIFO_CONFIGURATION_SELECT                           0
 	u32		_unused2;
-	// offset 0x0040
+	/* offset 0x0040 */
 	u32		memaddr;
 #define     START                                               28
 #define     DIRECTION                                           27
@@ -213,7 +213,7 @@
 	u32		memdata0;
 	u32		memdata1;
 	u32		_unused3;
-	// offset 0x0050
+	/* offset 0x0050 */
 	u32		gpioctl;
 #define     GPIO3_LED_SELECT                                    12
 #define     GPIO3_INTERRUPT_ENABLE                              11
@@ -237,7 +237,7 @@
 
 /* usb control, BAR0 + 0x0080 */
 struct net2280_usb_regs {
-	// offset 0x0080
+	/* offset 0x0080 */
 	u32		stdrsp;
 #define     STALL_UNSUPPORTED_REQUESTS                          31
 #define     SET_TEST_MODE                                       16
@@ -275,7 +275,7 @@
 #define     PME_WAKEUP_ENABLE                                   2
 #define     DEVICE_REMOTE_WAKEUP_ENABLE                         1
 #define     SELF_POWERED_STATUS                                 0
-	// offset 0x0090
+	/* offset 0x0090 */
 	u32		usbstat;
 #define     HIGH_SPEED                                          7
 #define     FULL_SPEED                                          6
@@ -291,7 +291,7 @@
 #define     TERMINATION_SELECT                                  0
 	u32		setup0123;
 	u32		setup4567;
-	// offset 0x0090
+	/* offset 0x0090 */
 	u32		_unused0;
 	u32		ouraddr;
 #define     FORCE_IMMEDIATE                                     7
@@ -301,7 +301,7 @@
 
 /* pci control, BAR0 + 0x0100 */
 struct net2280_pci_regs {
-	// offset 0x0100
+	/* offset 0x0100 */
 	u32		 pcimstctl;
 #define     PCI_ARBITER_PARK_SELECT                             13
 #define     PCI_MULTI LEVEL_ARBITER                             12
@@ -331,7 +331,7 @@
  * that can be loaded into some of these registers.
  */
 struct net2280_dma_regs {	/* [11.7] */
-	// offset 0x0180, 0x01a0, 0x01c0, 0x01e0,
+	/* offset 0x0180, 0x01a0, 0x01c0, 0x01e0, */
 	u32		dmactl;
 #define     DMA_SCATTER_GATHER_DONE_INTERRUPT_ENABLE            25
 #define     DMA_CLEAR_COUNT_ENABLE                              21
@@ -355,7 +355,7 @@
 #define     DMA_ABORT                                           1
 #define     DMA_START                                           0
 	u32		_unused0 [2];
-	// offset 0x0190, 0x01b0, 0x01d0, 0x01f0,
+	/* offset 0x0190, 0x01b0, 0x01d0, 0x01f0, */
 	u32		dmacount;
 #define     VALID_BIT                                           31
 #define     DMA_DIRECTION                                       30
@@ -371,9 +371,9 @@
 /* dedicated endpoint registers, BAR0 + 0x0200 */
 
 struct net2280_dep_regs {	/* [11.8] */
-	// offset 0x0200, 0x0210, 0x220, 0x230, 0x240
+	/* offset 0x0200, 0x0210, 0x220, 0x230, 0x240 */
 	u32		dep_cfg;
-	// offset 0x0204, 0x0214, 0x224, 0x234, 0x244
+	/* offset 0x0204, 0x0214, 0x224, 0x234, 0x244 */
 	u32		dep_rsp;
 	u32		_unused [2];
 } __attribute__ ((packed));
@@ -383,7 +383,7 @@
  * ep0 reserved for control; E and F have only 64 bytes of fifo
  */
 struct net2280_ep_regs {	/* [11.9] */
-	// offset 0x0300, 0x0320, 0x0340, 0x0360, 0x0380, 0x03a0, 0x03c0
+	/* offset 0x0300, 0x0320, 0x0340, 0x0360, 0x0380, 0x03a0, 0x03c0 */
 	u32		ep_cfg;
 #define     ENDPOINT_BYTE_COUNT                                 16
 #define     ENDPOINT_ENABLE                                     10
@@ -435,7 +435,7 @@
 #define     DATA_PACKET_TRANSMITTED_INTERRUPT                   2
 #define     DATA_OUT_PING_TOKEN_INTERRUPT                       1
 #define     DATA_IN_TOKEN_INTERRUPT                             0
-	// offset 0x0310, 0x0330, 0x0350, 0x0370, 0x0390, 0x03b0, 0x03d0
+	/* offset 0x0310, 0x0330, 0x0350, 0x0370, 0x0390, 0x03b0, 0x03d0 */
 	u32		ep_avail;
 	u32		ep_data;
 	u32		_unused0 [2];
diff --git a/include/linux/usb/otg.h b/include/linux/usb/otg.h
index 9897f7a..e007074 100644
--- a/include/linux/usb/otg.h
+++ b/include/linux/usb/otg.h
@@ -1,4 +1,4 @@
-// include/linux/usb/otg.h
+/* USB OTG (On The Go) defines */
 
 /*
  * These APIs may be used between USB controllers.  USB device drivers
diff --git a/include/linux/usb/serial.h b/include/linux/usb/serial.h
index 488ce12..21b4a1c 100644
--- a/include/linux/usb/serial.h
+++ b/include/linux/usb/serial.h
@@ -20,7 +20,8 @@
 #define SERIAL_TTY_MAJOR	188	/* Nice legal number now */
 #define SERIAL_TTY_MINORS	255	/* loads of devices :) */
 
-#define MAX_NUM_PORTS		8	/* The maximum number of ports one device can grab at once */
+/* The maximum number of ports one device can grab at once */
+#define MAX_NUM_PORTS		8
 
 /* parity check flag */
 #define RELEVANT_IFLAG(iflag)	(iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
@@ -61,29 +62,29 @@
  * ports of a device.
  */
 struct usb_serial_port {
-	struct usb_serial *	serial;
-	struct tty_struct *	tty;
+	struct usb_serial	*serial;
+	struct tty_struct	*tty;
 	spinlock_t		lock;
 	struct mutex            mutex;
 	unsigned char		number;
 
-	unsigned char *		interrupt_in_buffer;
-	struct urb *		interrupt_in_urb;
+	unsigned char		*interrupt_in_buffer;
+	struct urb		*interrupt_in_urb;
 	__u8			interrupt_in_endpointAddress;
 
-	unsigned char *		interrupt_out_buffer;
+	unsigned char		*interrupt_out_buffer;
 	int			interrupt_out_size;
-	struct urb *		interrupt_out_urb;
+	struct urb		*interrupt_out_urb;
 	__u8			interrupt_out_endpointAddress;
 
-	unsigned char *		bulk_in_buffer;
+	unsigned char		*bulk_in_buffer;
 	int			bulk_in_size;
-	struct urb *		read_urb;
+	struct urb		*read_urb;
 	__u8			bulk_in_endpointAddress;
 
-	unsigned char *		bulk_out_buffer;
+	unsigned char		*bulk_out_buffer;
 	int			bulk_out_size;
-	struct urb *		write_urb;
+	struct urb		*write_urb;
 	int			write_urb_busy;
 	__u8			bulk_out_endpointAddress;
 
@@ -92,17 +93,19 @@
 	int			open_count;
 	char			throttled;
 	char			throttle_req;
+	char			console;
 	struct device		dev;
 };
 #define to_usb_serial_port(d) container_of(d, struct usb_serial_port, dev)
 
 /* get and set the port private data pointer helper functions */
-static inline void *usb_get_serial_port_data (struct usb_serial_port *port)
+static inline void *usb_get_serial_port_data(struct usb_serial_port *port)
 {
 	return dev_get_drvdata(&port->dev);
 }
 
-static inline void usb_set_serial_port_data (struct usb_serial_port *port, void *data)
+static inline void usb_set_serial_port_data(struct usb_serial_port *port,
+					    void *data)
 {
 	dev_set_drvdata(&port->dev, data);
 }
@@ -125,9 +128,10 @@
  *	usb_set_serial_data() to access this.
  */
 struct usb_serial {
-	struct usb_device *		dev;
-	struct usb_serial_driver *	type;
-	struct usb_interface *		interface;
+	struct usb_device		*dev;
+	struct usb_serial_driver	*type;
+	struct usb_interface		*interface;
+	unsigned char			disconnected;
 	unsigned char			minor;
 	unsigned char			num_ports;
 	unsigned char			num_port_pointers;
@@ -135,29 +139,30 @@
 	char				num_interrupt_out;
 	char				num_bulk_in;
 	char				num_bulk_out;
-	struct usb_serial_port *	port[MAX_NUM_PORTS];
+	struct usb_serial_port		*port[MAX_NUM_PORTS];
 	struct kref			kref;
-	void *				private;
+	struct mutex			disc_mutex;
+	void				*private;
 };
 #define to_usb_serial(d) container_of(d, struct usb_serial, kref)
 
 #define NUM_DONT_CARE	99
 
 /* get and set the serial private data pointer helper functions */
-static inline void *usb_get_serial_data (struct usb_serial *serial)
+static inline void *usb_get_serial_data(struct usb_serial *serial)
 {
 	return serial->private;
 }
 
-static inline void usb_set_serial_data (struct usb_serial *serial, void *data)
+static inline void usb_set_serial_data(struct usb_serial *serial, void *data)
 {
 	serial->private = data;
 }
 
 /**
  * usb_serial_driver - describes a usb serial driver
- * @description: pointer to a string that describes this driver.  This string used
- *	in the syslog messages when a device is inserted or removed.
+ * @description: pointer to a string that describes this driver.  This string
+ *	used in the syslog messages when a device is inserted or removed.
  * @id_table: pointer to a list of usb_device_id structures that define all
  *	of the devices this structure can support.
  * @num_interrupt_in: If a device doesn't have this many interrupt-in
@@ -218,82 +223,91 @@
 	struct usb_driver	*usb_driver;
 	struct usb_dynids	dynids;
 
-	int (*probe) (struct usb_serial *serial, const struct usb_device_id *id);
-	int (*attach) (struct usb_serial *serial);
+	int (*probe)(struct usb_serial *serial, const struct usb_device_id *id);
+	int (*attach)(struct usb_serial *serial);
 	int (*calc_num_ports) (struct usb_serial *serial);
 
-	void (*shutdown) (struct usb_serial *serial);
+	void (*shutdown)(struct usb_serial *serial);
 
-	int (*port_probe) (struct usb_serial_port *port);
-	int (*port_remove) (struct usb_serial_port *port);
+	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);
+	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);
-	int  (*write)		(struct usb_serial_port *port, const unsigned char *buf, int count);
-	int  (*write_room)	(struct usb_serial_port *port);
-	int  (*ioctl)		(struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg);
-	void (*set_termios)	(struct usb_serial_port *port, struct ktermios * old);
-	void (*break_ctl)	(struct usb_serial_port *port, int break_state);
-	int  (*chars_in_buffer)	(struct usb_serial_port *port);
-	void (*throttle)	(struct usb_serial_port *port);
-	void (*unthrottle)	(struct usb_serial_port *port);
-	int  (*tiocmget)	(struct usb_serial_port *port, struct file *file);
-	int  (*tiocmset)	(struct usb_serial_port *port, struct file *file, unsigned int set, unsigned int clear);
+	int  (*open)(struct usb_serial_port *port, struct file *filp);
+	void (*close)(struct usb_serial_port *port, struct file *filp);
+	int  (*write)(struct usb_serial_port *port, const unsigned char *buf,
+		      int count);
+	int  (*write_room)(struct usb_serial_port *port);
+	int  (*ioctl)(struct usb_serial_port *port, struct file *file,
+		      unsigned int cmd, unsigned long arg);
+	void (*set_termios)(struct usb_serial_port *port, struct ktermios *old);
+	void (*break_ctl)(struct usb_serial_port *port, int break_state);
+	int  (*chars_in_buffer)(struct usb_serial_port *port);
+	void (*throttle)(struct usb_serial_port *port);
+	void (*unthrottle)(struct usb_serial_port *port);
+	int  (*tiocmget)(struct usb_serial_port *port, struct file *file);
+	int  (*tiocmset)(struct usb_serial_port *port, struct file *file,
+			 unsigned int set, unsigned int clear);
 
 	void (*read_int_callback)(struct urb *urb);
 	void (*write_int_callback)(struct urb *urb);
 	void (*read_bulk_callback)(struct urb *urb);
 	void (*write_bulk_callback)(struct urb *urb);
 };
-#define to_usb_serial_driver(d) container_of(d, struct usb_serial_driver, driver)
+#define to_usb_serial_driver(d) \
+	container_of(d, struct usb_serial_driver, driver)
 
 extern int  usb_serial_register(struct usb_serial_driver *driver);
 extern void usb_serial_deregister(struct usb_serial_driver *driver);
 extern void usb_serial_port_softint(struct usb_serial_port *port);
 
-extern int usb_serial_probe(struct usb_interface *iface, const struct usb_device_id *id);
+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);
+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);
 
 /* USB Serial console functions */
 #ifdef CONFIG_USB_SERIAL_CONSOLE
-extern void usb_serial_console_init (int debug, int minor);
-extern void usb_serial_console_exit (void);
+extern void usb_serial_console_init(int debug, int minor);
+extern void usb_serial_console_exit(void);
 extern void usb_serial_console_disconnect(struct usb_serial *serial);
 #else
-static inline void usb_serial_console_init (int debug, int minor) { }
-static inline void usb_serial_console_exit (void) { }
+static inline void usb_serial_console_init(int debug, int minor) { }
+static inline void usb_serial_console_exit(void) { }
 static inline void usb_serial_console_disconnect(struct usb_serial *serial) {}
 #endif
 
 /* Functions needed by other parts of the usbserial core */
-extern struct usb_serial *usb_serial_get_by_index (unsigned int minor);
+extern struct usb_serial *usb_serial_get_by_index(unsigned int minor);
 extern void usb_serial_put(struct usb_serial *serial);
-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);
-extern void usb_serial_generic_write_bulk_callback (struct urb *urb);
-extern void usb_serial_generic_throttle (struct usb_serial_port *port);
-extern void usb_serial_generic_unthrottle (struct usb_serial_port *port);
-extern void usb_serial_generic_shutdown (struct usb_serial *serial);
-extern int usb_serial_generic_register (int debug);
-extern void usb_serial_generic_deregister (void);
+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);
+extern void usb_serial_generic_write_bulk_callback(struct urb *urb);
+extern void usb_serial_generic_throttle(struct usb_serial_port *port);
+extern void usb_serial_generic_unthrottle(struct usb_serial_port *port);
+extern void usb_serial_generic_shutdown(struct usb_serial *serial);
+extern int usb_serial_generic_register(int debug);
+extern void usb_serial_generic_deregister(void);
 
-extern int usb_serial_bus_register (struct usb_serial_driver *device);
-extern void usb_serial_bus_deregister (struct usb_serial_driver *device);
+extern int usb_serial_bus_register(struct usb_serial_driver *device);
+extern void usb_serial_bus_deregister(struct usb_serial_driver *device);
 
 extern struct usb_serial_driver usb_serial_generic_device;
 extern struct bus_type usb_serial_bus_type;
@@ -307,16 +321,22 @@
 	int i;
 
 	if (debug) {
-		dev_printk(KERN_DEBUG, dev, "%s - length = %d, data = ", function, size);
+		dev_printk(KERN_DEBUG, dev, "%s - length = %d, data = ",
+			   function, size);
 		for (i = 0; i < size; ++i)
-			printk ("%.2x ", data[i]);
-		printk ("\n");
+			printk("%.2x ", data[i]);
+		printk("\n");
 	}
 }
 
 /* Use our own dbg macro */
 #undef dbg
-#define dbg(format, arg...) do { if (debug) printk(KERN_DEBUG "%s: " format "\n" , __FILE__ , ## arg); } while (0)
+#define dbg(format, arg...) \
+	do { \
+		if (debug) \
+			printk(KERN_DEBUG "%s: " format "\n" , __FILE__ , \
+				## arg); \
+	} while (0)
 
 
 
diff --git a/include/linux/usb/sl811.h b/include/linux/usb/sl811.h
index 397ee3b..877373d 100644
--- a/include/linux/usb/sl811.h
+++ b/include/linux/usb/sl811.h
@@ -19,8 +19,8 @@
 	/* pulse sl811 nRST (probably with a GPIO) */
 	void		(*reset)(struct device *dev);
 
-	// some boards need something like these:
-	// int		(*check_overcurrent)(struct device *dev);
-	// void		(*clock_enable)(struct device *dev, int is_on);
+	/* some boards need something like these: */
+	/* int		(*check_overcurrent)(struct device *dev); */
+	/* void		(*clock_enable)(struct device *dev, int is_on); */
 };
 
diff --git a/include/linux/usb_usual.h b/include/linux/usb_usual.h
index a417b09..cee0623 100644
--- a/include/linux/usb_usual.h
+++ b/include/linux/usb_usual.h
@@ -80,10 +80,9 @@
 #define US_SC_UFI	0x04		/* Floppy */
 #define US_SC_8070	0x05		/* Removable media */
 #define US_SC_SCSI	0x06		/* Transparent */
-#define US_SC_ISD200    0x07		/* ISD200 ATA */
-#define US_SC_MIN	US_SC_RBC
-#define US_SC_MAX	US_SC_ISD200
+#define US_SC_LOCKABLE	0x07		/* Password-protected */
 
+#define US_SC_ISD200    0xf0		/* ISD200 ATA */
 #define US_SC_DEVICE	0xff		/* Use device's value */
 
 /* Protocols */
diff --git a/include/linux/usbdevice_fs.h b/include/linux/usbdevice_fs.h
index 8ca5a7f..17cb108 100644
--- a/include/linux/usbdevice_fs.h
+++ b/include/linux/usbdevice_fs.h
@@ -104,7 +104,7 @@
 	int error_count;
 	unsigned int signr;	/* signal to be sent on completion,
 				  or 0 if none should be sent. */
-	void *usercontext;
+	void __user *usercontext;
 	struct usbdevfs_iso_packet_desc iso_frame_desc[0];
 };
 
diff --git a/kernel/audit.c b/kernel/audit.c
index 801c946..c8555b1 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -66,10 +66,11 @@
  * (Initialization happens after skb_init is called.) */
 static int	audit_initialized;
 
-/* 0 - no auditing
- * 1 - auditing enabled
- * 2 - auditing enabled and configuration is locked/unchangeable. */
+#define AUDIT_OFF	0
+#define AUDIT_ON	1
+#define AUDIT_LOCKED	2
 int		audit_enabled;
+int		audit_ever_enabled;
 
 /* Default state when kernel boots without any parameters. */
 static int	audit_default;
@@ -152,8 +153,10 @@
 
 static void audit_set_pid(struct audit_buffer *ab, pid_t pid)
 {
-	struct nlmsghdr *nlh = nlmsg_hdr(ab->skb);
-	nlh->nlmsg_pid = pid;
+	if (ab) {
+		struct nlmsghdr *nlh = nlmsg_hdr(ab->skb);
+		nlh->nlmsg_pid = pid;
+	}
 }
 
 void audit_panic(const char *message)
@@ -163,7 +166,8 @@
 	case AUDIT_FAIL_SILENT:
 		break;
 	case AUDIT_FAIL_PRINTK:
-		printk(KERN_ERR "audit: %s\n", message);
+		if (printk_ratelimit())
+			printk(KERN_ERR "audit: %s\n", message);
 		break;
 	case AUDIT_FAIL_PANIC:
 		panic("audit: %s\n", message);
@@ -231,161 +235,107 @@
 	}
 
 	if (print) {
-		printk(KERN_WARNING
-		       "audit: audit_lost=%d audit_rate_limit=%d audit_backlog_limit=%d\n",
-		       atomic_read(&audit_lost),
-		       audit_rate_limit,
-		       audit_backlog_limit);
+		if (printk_ratelimit())
+			printk(KERN_WARNING
+				"audit: audit_lost=%d audit_rate_limit=%d "
+				"audit_backlog_limit=%d\n",
+				atomic_read(&audit_lost),
+				audit_rate_limit,
+				audit_backlog_limit);
 		audit_panic(message);
 	}
 }
 
-static int audit_set_rate_limit(int limit, uid_t loginuid, u32 sid)
+static int audit_log_config_change(char *function_name, int new, int old,
+				   uid_t loginuid, u32 sid, int allow_changes)
 {
-	int res, rc = 0, old = audit_rate_limit;
+	struct audit_buffer *ab;
+	int rc = 0;
 
-	/* check if we are locked */
-	if (audit_enabled == 2)
-		res = 0;
-	else
-		res = 1;
-
+	ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE);
+	audit_log_format(ab, "%s=%d old=%d by auid=%u", function_name, new,
+			 old, loginuid);
 	if (sid) {
 		char *ctx = NULL;
 		u32 len;
-		if ((rc = selinux_sid_to_string(sid, &ctx, &len)) == 0) {
-			audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
-				"audit_rate_limit=%d old=%d by auid=%u"
-				" subj=%s res=%d",
-				limit, old, loginuid, ctx, res);
+
+		rc = selinux_sid_to_string(sid, &ctx, &len);
+		if (rc) {
+			audit_log_format(ab, " sid=%u", sid);
+			allow_changes = 0; /* Something weird, deny request */
+		} else {
+			audit_log_format(ab, " subj=%s", ctx);
 			kfree(ctx);
-		} else
-			res = 0; /* Something weird, deny request */
+		}
 	}
-	audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
-		"audit_rate_limit=%d old=%d by auid=%u res=%d",
-		limit, old, loginuid, res);
+	audit_log_format(ab, " res=%d", allow_changes);
+	audit_log_end(ab);
+	return rc;
+}
+
+static int audit_do_config_change(char *function_name, int *to_change,
+				  int new, uid_t loginuid, u32 sid)
+{
+	int allow_changes, rc = 0, old = *to_change;
+
+	/* check if we are locked */
+	if (audit_enabled == AUDIT_LOCKED)
+		allow_changes = 0;
+	else
+		allow_changes = 1;
+
+	if (audit_enabled != AUDIT_OFF) {
+		rc = audit_log_config_change(function_name, new, old,
+					     loginuid, sid, allow_changes);
+		if (rc)
+			allow_changes = 0;
+	}
 
 	/* If we are allowed, make the change */
-	if (res == 1)
-		audit_rate_limit = limit;
+	if (allow_changes == 1)
+		*to_change = new;
 	/* Not allowed, update reason */
 	else if (rc == 0)
 		rc = -EPERM;
 	return rc;
 }
 
+static int audit_set_rate_limit(int limit, uid_t loginuid, u32 sid)
+{
+	return audit_do_config_change("audit_rate_limit", &audit_rate_limit,
+				      limit, loginuid, sid);
+}
+
 static int audit_set_backlog_limit(int limit, uid_t loginuid, u32 sid)
 {
-	int res, rc = 0, old = audit_backlog_limit;
-
-	/* check if we are locked */
-	if (audit_enabled == 2)
-		res = 0;
-	else
-		res = 1;
-
-	if (sid) {
-		char *ctx = NULL;
-		u32 len;
-		if ((rc = selinux_sid_to_string(sid, &ctx, &len)) == 0) {
-			audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
-				"audit_backlog_limit=%d old=%d by auid=%u"
-				" subj=%s res=%d",
-				limit, old, loginuid, ctx, res);
-			kfree(ctx);
-		} else
-			res = 0; /* Something weird, deny request */
-	}
-	audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
-		"audit_backlog_limit=%d old=%d by auid=%u res=%d",
-		limit, old, loginuid, res);
-
-	/* If we are allowed, make the change */
-	if (res == 1)
-		audit_backlog_limit = limit;
-	/* Not allowed, update reason */
-	else if (rc == 0)
-		rc = -EPERM;
-	return rc;
+	return audit_do_config_change("audit_backlog_limit", &audit_backlog_limit,
+				      limit, loginuid, sid);
 }
 
 static int audit_set_enabled(int state, uid_t loginuid, u32 sid)
 {
-	int res, rc = 0, old = audit_enabled;
-
-	if (state < 0 || state > 2)
+	int rc;
+	if (state < AUDIT_OFF || state > AUDIT_LOCKED)
 		return -EINVAL;
 
-	/* check if we are locked */
-	if (audit_enabled == 2)
-		res = 0;
-	else
-		res = 1;
+	rc =  audit_do_config_change("audit_enabled", &audit_enabled, state,
+				     loginuid, sid);
 
-	if (sid) {
-		char *ctx = NULL;
-		u32 len;
-		if ((rc = selinux_sid_to_string(sid, &ctx, &len)) == 0) {
-			audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
-				"audit_enabled=%d old=%d by auid=%u"
-				" subj=%s res=%d",
-				state, old, loginuid, ctx, res);
-			kfree(ctx);
-		} else
-			res = 0; /* Something weird, deny request */
-	}
-	audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
-		"audit_enabled=%d old=%d by auid=%u res=%d",
-		state, old, loginuid, res);
+	if (!rc)
+		audit_ever_enabled |= !!state;
 
-	/* If we are allowed, make the change */
-	if (res == 1)
-		audit_enabled = state;
-	/* Not allowed, update reason */
-	else if (rc == 0)
-		rc = -EPERM;
 	return rc;
 }
 
 static int audit_set_failure(int state, uid_t loginuid, u32 sid)
 {
-	int res, rc = 0, old = audit_failure;
-
 	if (state != AUDIT_FAIL_SILENT
 	    && state != AUDIT_FAIL_PRINTK
 	    && state != AUDIT_FAIL_PANIC)
 		return -EINVAL;
 
-	/* check if we are locked */
-	if (audit_enabled == 2)
-		res = 0;
-	else
-		res = 1;
-
-	if (sid) {
-		char *ctx = NULL;
-		u32 len;
-		if ((rc = selinux_sid_to_string(sid, &ctx, &len)) == 0) {
-			audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
-				"audit_failure=%d old=%d by auid=%u"
-				" subj=%s res=%d",
-				state, old, loginuid, ctx, res);
-			kfree(ctx);
-		} else
-			res = 0; /* Something weird, deny request */
-	}
-	audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
-		"audit_failure=%d old=%d by auid=%u res=%d",
-		state, old, loginuid, res);
-
-	/* If we are allowed, make the change */
-	if (res == 1)
-		audit_failure = state;
-	/* Not allowed, update reason */
-	else if (rc == 0)
-		rc = -EPERM;
-	return rc;
+	return audit_do_config_change("audit_failure", &audit_failure, state,
+				      loginuid, sid);
 }
 
 static int kauditd_thread(void *dummy)
@@ -405,7 +355,11 @@
 					audit_pid = 0;
 				}
 			} else {
-				printk(KERN_NOTICE "%s\n", skb->data + NLMSG_SPACE(0));
+				if (printk_ratelimit())
+					printk(KERN_NOTICE "%s\n", skb->data +
+						NLMSG_SPACE(0));
+				else
+					audit_log_lost("printk limit exceeded\n");
 				kfree_skb(skb);
 			}
 		} else {
@@ -573,6 +527,33 @@
 	return err;
 }
 
+static int audit_log_common_recv_msg(struct audit_buffer **ab, u16 msg_type,
+				     u32 pid, u32 uid, uid_t auid, u32 sid)
+{
+	int rc = 0;
+	char *ctx = NULL;
+	u32 len;
+
+	if (!audit_enabled) {
+		*ab = NULL;
+		return rc;
+	}
+
+	*ab = audit_log_start(NULL, GFP_KERNEL, msg_type);
+	audit_log_format(*ab, "user pid=%d uid=%u auid=%u",
+			 pid, uid, auid);
+	if (sid) {
+		rc = selinux_sid_to_string(sid, &ctx, &len);
+		if (rc)
+			audit_log_format(*ab, " ssid=%u", sid);
+		else
+			audit_log_format(*ab, " subj=%s", ctx);
+		kfree(ctx);
+	}
+
+	return rc;
+}
+
 static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
 {
 	u32			uid, pid, seq, sid;
@@ -583,7 +564,7 @@
 	u16			msg_type = nlh->nlmsg_type;
 	uid_t			loginuid; /* loginuid of sender */
 	struct audit_sig_info   *sig_data;
-	char			*ctx;
+	char			*ctx = NULL;
 	u32			len;
 
 	err = audit_netlink_ok(skb, msg_type);
@@ -634,23 +615,14 @@
 			if (err < 0) return err;
 		}
 		if (status_get->mask & AUDIT_STATUS_PID) {
-			int old   = audit_pid;
-			if (sid) {
-				if ((err = selinux_sid_to_string(
-						sid, &ctx, &len)))
-					return err;
-				else
-					audit_log(NULL, GFP_KERNEL,
-						AUDIT_CONFIG_CHANGE,
-						"audit_pid=%d old=%d by auid=%u subj=%s",
-						status_get->pid, old,
-						loginuid, ctx);
-				kfree(ctx);
-			} else
-				audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
-					"audit_pid=%d old=%d by auid=%u",
-					  status_get->pid, old, loginuid);
-			audit_pid = status_get->pid;
+			int new_pid = status_get->pid;
+
+			if (audit_enabled != AUDIT_OFF)
+				audit_log_config_change("audit_pid", new_pid,
+							audit_pid, loginuid,
+							sid, 1);
+
+			audit_pid = new_pid;
 		}
 		if (status_get->mask & AUDIT_STATUS_RATE_LIMIT)
 			err = audit_set_rate_limit(status_get->rate_limit,
@@ -673,64 +645,35 @@
 				if (err)
 					break;
 			}
-			ab = audit_log_start(NULL, GFP_KERNEL, msg_type);
-			if (ab) {
-				audit_log_format(ab,
-						 "user pid=%d uid=%u auid=%u",
-						 pid, uid, loginuid);
-				if (sid) {
-					if (selinux_sid_to_string(
-							sid, &ctx, &len)) {
-						audit_log_format(ab,
-							" ssid=%u", sid);
-						/* Maybe call audit_panic? */
-					} else
-						audit_log_format(ab,
-							" subj=%s", ctx);
-					kfree(ctx);
-				}
-				if (msg_type != AUDIT_USER_TTY)
-					audit_log_format(ab, " msg='%.1024s'",
-							 (char *)data);
-				else {
-					int size;
+			audit_log_common_recv_msg(&ab, msg_type, pid, uid,
+						  loginuid, sid);
 
-					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);
+			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);
 		}
 		break;
 	case AUDIT_ADD:
 	case AUDIT_DEL:
 		if (nlmsg_len(nlh) < sizeof(struct audit_rule))
 			return -EINVAL;
-		if (audit_enabled == 2) {
-			ab = audit_log_start(NULL, GFP_KERNEL,
-					AUDIT_CONFIG_CHANGE);
-			if (ab) {
-				audit_log_format(ab,
-						 "pid=%d uid=%u auid=%u",
-						 pid, uid, loginuid);
-				if (sid) {
-					if (selinux_sid_to_string(
-							sid, &ctx, &len)) {
-						audit_log_format(ab,
-							" ssid=%u", sid);
-						/* Maybe call audit_panic? */
-					} else
-						audit_log_format(ab,
-							" subj=%s", ctx);
-					kfree(ctx);
-				}
-				audit_log_format(ab, " audit_enabled=%d res=0",
-					audit_enabled);
-				audit_log_end(ab);
-			}
+		if (audit_enabled == AUDIT_LOCKED) {
+			audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE, pid,
+						  uid, loginuid, sid);
+
+			audit_log_format(ab, " audit_enabled=%d res=0",
+					 audit_enabled);
+			audit_log_end(ab);
 			return -EPERM;
 		}
 		/* fallthrough */
@@ -743,28 +686,13 @@
 	case AUDIT_DEL_RULE:
 		if (nlmsg_len(nlh) < sizeof(struct audit_rule_data))
 			return -EINVAL;
-		if (audit_enabled == 2) {
-			ab = audit_log_start(NULL, GFP_KERNEL,
-					AUDIT_CONFIG_CHANGE);
-			if (ab) {
-				audit_log_format(ab,
-						 "pid=%d uid=%u auid=%u",
-						 pid, uid, loginuid);
-				if (sid) {
-					if (selinux_sid_to_string(
-							sid, &ctx, &len)) {
-						audit_log_format(ab,
-							" ssid=%u", sid);
-						/* Maybe call audit_panic? */
-					} else
-						audit_log_format(ab,
-							" subj=%s", ctx);
-					kfree(ctx);
-				}
-				audit_log_format(ab, " audit_enabled=%d res=0",
-					audit_enabled);
-				audit_log_end(ab);
-			}
+		if (audit_enabled == AUDIT_LOCKED) {
+			audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE, pid,
+						  uid, loginuid, sid);
+
+			audit_log_format(ab, " audit_enabled=%d res=0",
+					 audit_enabled);
+			audit_log_end(ab);
 			return -EPERM;
 		}
 		/* fallthrough */
@@ -775,19 +703,10 @@
 		break;
 	case AUDIT_TRIM:
 		audit_trim_trees();
-		ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE);
-		if (!ab)
-			break;
-		audit_log_format(ab, "auid=%u", loginuid);
-		if (sid) {
-			u32 len;
-			ctx = NULL;
-			if (selinux_sid_to_string(sid, &ctx, &len))
-				audit_log_format(ab, " ssid=%u", sid);
-			else
-				audit_log_format(ab, " subj=%s", ctx);
-			kfree(ctx);
-		}
+
+		audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE, pid,
+					  uid, loginuid, sid);
+
 		audit_log_format(ab, " op=trim res=1");
 		audit_log_end(ab);
 		break;
@@ -817,22 +736,9 @@
 		/* OK, here comes... */
 		err = audit_tag_tree(old, new);
 
-		ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE);
-		if (!ab) {
-			kfree(old);
-			kfree(new);
-			break;
-		}
-		audit_log_format(ab, "auid=%u", loginuid);
-		if (sid) {
-			u32 len;
-			ctx = NULL;
-			if (selinux_sid_to_string(sid, &ctx, &len))
-				audit_log_format(ab, " ssid=%u", sid);
-			else
-				audit_log_format(ab, " subj=%s", ctx);
-			kfree(ctx);
-		}
+		audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE, pid,
+					  uid, loginuid, sid);
+
 		audit_log_format(ab, " op=make_equiv old=");
 		audit_log_untrustedstring(ab, old);
 		audit_log_format(ab, " new=");
@@ -965,6 +871,7 @@
 	skb_queue_head_init(&audit_skb_queue);
 	audit_initialized = 1;
 	audit_enabled = audit_default;
+	audit_ever_enabled |= !!audit_default;
 
 	/* Register the callback with selinux.  This callback will be invoked
 	 * when a new policy is loaded. */
@@ -992,8 +899,10 @@
 	printk(KERN_INFO "audit: %s%s\n",
 	       audit_default ? "enabled" : "disabled",
 	       audit_initialized ? "" : " (after initialization)");
-	if (audit_initialized)
+	if (audit_initialized) {
 		audit_enabled = audit_default;
+		audit_ever_enabled |= !!audit_default;
+	}
 	return 1;
 }
 
@@ -1130,7 +1039,7 @@
 {
 	struct audit_buffer	*ab	= NULL;
 	struct timespec		t;
-	unsigned int		serial;
+	unsigned int		uninitialized_var(serial);
 	int reserve;
 	unsigned long timeout_start = jiffies;
 
@@ -1164,7 +1073,7 @@
 			remove_wait_queue(&audit_backlog_wait, &wait);
 			continue;
 		}
-		if (audit_rate_check())
+		if (audit_rate_check() && printk_ratelimit())
 			printk(KERN_WARNING
 			       "audit: audit_backlog=%d > "
 			       "audit_backlog_limit=%d\n",
@@ -1249,6 +1158,7 @@
 			goto out;
 		len = vsnprintf(skb_tail_pointer(skb), avail, fmt, args2);
 	}
+	va_end(args2);
 	if (len > 0)
 		skb_put(skb, len);
 out:
@@ -1350,6 +1260,21 @@
 }
 
 /**
+ * audit_string_contains_control - does a string need to be logged in hex
+ * @string - string to be checked
+ * @len - max length of the string to check
+ */
+int audit_string_contains_control(const char *string, size_t len)
+{
+	const unsigned char *p;
+	for (p = string; p < (const unsigned char *)string + len && *p; p++) {
+		if (*p == '"' || *p < 0x21 || *p > 0x7f)
+			return 1;
+	}
+	return 0;
+}
+
+/**
  * audit_log_n_untrustedstring - log a string that may contain random characters
  * @ab: audit_buffer
  * @len: lenth of string (not including trailing null)
@@ -1363,19 +1288,13 @@
  * The caller specifies the number of characters in the string to log, which may
  * or may not be the entire string.
  */
-const char *audit_log_n_untrustedstring(struct audit_buffer *ab, size_t len,
-					const char *string)
+void audit_log_n_untrustedstring(struct audit_buffer *ab, size_t len,
+				 const char *string)
 {
-	const unsigned char *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;
-		}
-	}
-	audit_log_n_string(ab, len, string);
-	return p + 1;
+	if (audit_string_contains_control(string, len))
+		audit_log_hex(ab, string, len);
+	else
+		audit_log_n_string(ab, len, string);
 }
 
 /**
@@ -1386,9 +1305,9 @@
  * 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)
+void audit_log_untrustedstring(struct audit_buffer *ab, const char *string)
 {
-	return audit_log_n_untrustedstring(ab, strlen(string), string);
+	audit_log_n_untrustedstring(ab, strlen(string), string);
 }
 
 /* This is a helper-function to print the escaped d_path */
@@ -1437,8 +1356,11 @@
 			skb_queue_tail(&audit_skb_queue, ab->skb);
 			ab->skb = NULL;
 			wake_up_interruptible(&kauditd_wait);
+		} else if (printk_ratelimit()) {
+			struct nlmsghdr *nlh = nlmsg_hdr(ab->skb);
+			printk(KERN_NOTICE "type=%d %s\n", nlh->nlmsg_type, ab->skb->data + NLMSG_SPACE(0));
 		} else {
-			printk(KERN_NOTICE "%s\n", ab->skb->data + NLMSG_SPACE(0));
+			audit_log_lost("printk limit exceeded\n");
 		}
 	}
 	audit_buffer_free(ab);
diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c
index 5d96f2c..6f19fd4 100644
--- a/kernel/auditfilter.c
+++ b/kernel/auditfilter.c
@@ -95,6 +95,8 @@
 /* Inotify events we care about. */
 #define AUDIT_IN_WATCH IN_MOVE|IN_CREATE|IN_DELETE|IN_DELETE_SELF|IN_MOVE_SELF
 
+extern int audit_enabled;
+
 void audit_free_parent(struct inotify_watch *i_watch)
 {
 	struct audit_parent *parent;
@@ -974,7 +976,6 @@
 	struct audit_watch *owatch, *nwatch, *nextw;
 	struct audit_krule *r, *nextr;
 	struct audit_entry *oentry, *nentry;
-	struct audit_buffer *ab;
 
 	mutex_lock(&audit_filter_mutex);
 	list_for_each_entry_safe(owatch, nextw, &parent->watches, wlist) {
@@ -1014,13 +1015,18 @@
 			call_rcu(&oentry->rcu, audit_free_rule_rcu);
 		}
 
-		ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE);
-		audit_log_format(ab, "op=updated rules specifying path=");
-		audit_log_untrustedstring(ab, owatch->path);
-		audit_log_format(ab, " with dev=%u ino=%lu\n", dev, ino);
-		audit_log_format(ab, " list=%d res=1", r->listnr);
-		audit_log_end(ab);
-
+		if (audit_enabled) {
+			struct audit_buffer *ab;
+			ab = audit_log_start(NULL, GFP_KERNEL,
+				AUDIT_CONFIG_CHANGE);
+			audit_log_format(ab,
+				"op=updated rules specifying path=");
+			audit_log_untrustedstring(ab, owatch->path);
+			audit_log_format(ab, " with dev=%u ino=%lu\n",
+				 dev, ino);
+			audit_log_format(ab, " list=%d res=1", r->listnr);
+			audit_log_end(ab);
+		}
 		audit_remove_watch(owatch);
 		goto add_watch_to_parent; /* event applies to a single watch */
 	}
@@ -1039,25 +1045,28 @@
 	struct audit_watch *w, *nextw;
 	struct audit_krule *r, *nextr;
 	struct audit_entry *e;
-	struct audit_buffer *ab;
 
 	mutex_lock(&audit_filter_mutex);
 	parent->flags |= AUDIT_PARENT_INVALID;
 	list_for_each_entry_safe(w, nextw, &parent->watches, wlist) {
 		list_for_each_entry_safe(r, nextr, &w->rules, rlist) {
 			e = container_of(r, struct audit_entry, rule);
-
-			ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE);
-			audit_log_format(ab, "op=remove rule path=");
-			audit_log_untrustedstring(ab, w->path);
-			if (r->filterkey) {
-				audit_log_format(ab, " key=");
-				audit_log_untrustedstring(ab, r->filterkey);
-			} else
-				audit_log_format(ab, " key=(null)");
-			audit_log_format(ab, " list=%d res=1", r->listnr);
-			audit_log_end(ab);
-
+			if (audit_enabled) {
+				struct audit_buffer *ab;
+				ab = audit_log_start(NULL, GFP_KERNEL,
+					AUDIT_CONFIG_CHANGE);
+				audit_log_format(ab, "op=remove rule path=");
+				audit_log_untrustedstring(ab, w->path);
+				if (r->filterkey) {
+					audit_log_format(ab, " key=");
+					audit_log_untrustedstring(ab,
+							r->filterkey);
+				} else
+					audit_log_format(ab, " key=(null)");
+				audit_log_format(ab, " list=%d res=1",
+					r->listnr);
+				audit_log_end(ab);
+			}
 			list_del(&r->rlist);
 			list_del_rcu(&e->list);
 			call_rcu(&e->rcu, audit_free_rule_rcu);
@@ -1495,6 +1504,9 @@
 {
 	struct audit_buffer *ab;
 
+	if (!audit_enabled)
+		return;
+
 	ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE);
 	if (!ab)
 		return;
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index bce9ecd..1c06ecf 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -70,6 +70,7 @@
 #include "audit.h"
 
 extern struct list_head audit_filter_list[];
+extern int audit_ever_enabled;
 
 /* AUDIT_NAMES is the number of slots we reserve in the audit_context
  * for saving names from getname(). */
@@ -78,6 +79,9 @@
 /* Indicates that audit should log the full pathname. */
 #define AUDIT_NAME_FULL -1
 
+/* no execve audit message should be longer than this (userspace limits) */
+#define MAX_EXECVE_AUDIT_LEN 7500
+
 /* number of audit rules */
 int audit_n_rules;
 
@@ -176,7 +180,11 @@
 struct audit_aux_data_pids {
 	struct audit_aux_data	d;
 	pid_t			target_pid[AUDIT_AUX_PIDS];
+	uid_t			target_auid[AUDIT_AUX_PIDS];
+	uid_t			target_uid[AUDIT_AUX_PIDS];
+	unsigned int		target_sessionid[AUDIT_AUX_PIDS];
 	u32			target_sid[AUDIT_AUX_PIDS];
+	char 			target_comm[AUDIT_AUX_PIDS][TASK_COMM_LEN];
 	int			pid_count;
 };
 
@@ -192,7 +200,6 @@
 	enum audit_state    state;
 	unsigned int	    serial;     /* serial number for record */
 	struct timespec	    ctime;      /* time of syscall entry */
-	uid_t		    loginuid;   /* login uid (identity) */
 	int		    major;      /* syscall number */
 	unsigned long	    argv[4];    /* syscall arguments */
 	int		    return_valid; /* return code is valid */
@@ -215,7 +222,11 @@
 	int		    arch;
 
 	pid_t		    target_pid;
+	uid_t		    target_auid;
+	uid_t		    target_uid;
+	unsigned int	    target_sessionid;
 	u32		    target_sid;
+	char		    target_comm[TASK_COMM_LEN];
 
 	struct audit_tree_refs *trees, *first_trees;
 	int tree_count;
@@ -506,7 +517,7 @@
 		case AUDIT_LOGINUID:
 			result = 0;
 			if (ctx)
-				result = audit_comparator(ctx->loginuid, f->op, f->val);
+				result = audit_comparator(tsk->loginuid, f->op, f->val);
 			break;
 		case AUDIT_SUBJ_USER:
 		case AUDIT_SUBJ_ROLE:
@@ -702,7 +713,24 @@
 	if (likely(!context))
 		return NULL;
 	context->return_valid = return_valid;
-	context->return_code  = return_code;
+
+	/*
+	 * we need to fix up the return code in the audit logs if the actual
+	 * return codes are later going to be fixed up by the arch specific
+	 * signal handlers
+	 *
+	 * This is actually a test for:
+	 * (rc == ERESTARTSYS ) || (rc == ERESTARTNOINTR) ||
+	 * (rc == ERESTARTNOHAND) || (rc == ERESTART_RESTARTBLOCK)
+	 *
+	 * but is faster than a bunch of ||
+	 */
+	if (unlikely(return_code <= -ERESTARTSYS) &&
+	    (return_code >= -ERESTART_RESTARTBLOCK) &&
+	    (return_code != -ENOIOCTLCMD))
+		context->return_code = -EINTR;
+	else
+		context->return_code  = return_code;
 
 	if (context->in_syscall && !context->dummy && !context->auditable) {
 		enum audit_state state;
@@ -783,11 +811,8 @@
 static inline void audit_zero_context(struct audit_context *context,
 				      enum audit_state state)
 {
-	uid_t loginuid = context->loginuid;
-
 	memset(context, 0, sizeof(*context));
 	context->state      = state;
-	context->loginuid   = loginuid;
 }
 
 static inline struct audit_context *audit_alloc_context(enum audit_state state)
@@ -814,7 +839,7 @@
 	struct audit_context *context;
 	enum audit_state     state;
 
-	if (likely(!audit_enabled))
+	if (likely(!audit_ever_enabled))
 		return 0; /* Return if not auditing. */
 
 	state = audit_filter_task(tsk);
@@ -826,11 +851,6 @@
 		return -ENOMEM;
 	}
 
-				/* Preserve login uid */
-	context->loginuid = -1;
-	if (current->audit_context)
-		context->loginuid = current->audit_context->loginuid;
-
 	tsk->audit_context  = context;
 	set_tsk_thread_flag(tsk, TIF_SYSCALL_AUDIT);
 	return 0;
@@ -922,7 +942,8 @@
 }
 
 static int audit_log_pid_context(struct audit_context *context, pid_t pid,
-				 u32 sid)
+				 uid_t auid, uid_t uid, unsigned int sessionid,
+				 u32 sid, char *comm)
 {
 	struct audit_buffer *ab;
 	char *s = NULL;
@@ -931,52 +952,71 @@
 
 	ab = audit_log_start(context, GFP_KERNEL, AUDIT_OBJ_PID);
 	if (!ab)
-		return 1;
+		return rc;
 
+	audit_log_format(ab, "opid=%d oauid=%d ouid=%d oses=%d", pid, auid,
+			 uid, sessionid);
 	if (selinux_sid_to_string(sid, &s, &len)) {
-		audit_log_format(ab, "opid=%d obj=(none)", pid);
+		audit_log_format(ab, " obj=(none)");
 		rc = 1;
 	} else
-		audit_log_format(ab, "opid=%d  obj=%s", pid, s);
+		audit_log_format(ab, " obj=%s", s);
+	audit_log_format(ab, " ocomm=");
+	audit_log_untrustedstring(ab, comm);
 	audit_log_end(ab);
 	kfree(s);
 
 	return rc;
 }
 
-static void audit_log_execve_info(struct audit_buffer *ab,
-		struct audit_aux_data_execve *axi)
+/*
+ * to_send and len_sent accounting are very loose estimates.  We aren't
+ * really worried about a hard cap to MAX_EXECVE_AUDIT_LEN so much as being
+ * within about 500 bytes (next page boundry)
+ *
+ * why snprintf?  an int is up to 12 digits long.  if we just assumed when
+ * logging that a[%d]= was going to be 16 characters long we would be wasting
+ * space in every audit message.  In one 7500 byte message we can log up to
+ * about 1000 min size arguments.  That comes down to about 50% waste of space
+ * if we didn't do the snprintf to find out how long arg_num_len was.
+ */
+static int audit_log_single_execve_arg(struct audit_context *context,
+					struct audit_buffer **ab,
+					int arg_num,
+					size_t *len_sent,
+					const char __user *p,
+					char *buf)
 {
-	int i;
-	long len, ret;
-	const char __user *p;
-	char *buf;
+	char arg_num_len_buf[12];
+	const char __user *tmp_p = p;
+	/* how many digits are in arg_num? 3 is the length of a=\n */
+	size_t arg_num_len = snprintf(arg_num_len_buf, 12, "%d", arg_num) + 3;
+	size_t len, len_left, to_send;
+	size_t max_execve_audit_len = MAX_EXECVE_AUDIT_LEN;
+	unsigned int i, has_cntl = 0, too_long = 0;
+	int ret;
 
-	if (axi->mm != current->mm)
-		return; /* execve failed, no additional info */
+	/* strnlen_user includes the null we don't want to send */
+	len_left = len = strnlen_user(p, MAX_ARG_STRLEN) - 1;
 
-	p = (const char __user *)axi->mm->arg_start;
+	/*
+	 * We just created this mm, if we can't find the strings
+	 * we just copied into it something is _very_ wrong. Similar
+	 * for strings that are too long, we should not have created
+	 * any.
+	 */
+	if (unlikely((len  = -1) || len > MAX_ARG_STRLEN - 1)) {
+		WARN_ON(1);
+		send_sig(SIGKILL, current, 0);
+	}
 
-	for (i = 0; i < axi->argc; i++, p += len) {
-		len = strnlen_user(p, MAX_ARG_STRLEN);
-		/*
-		 * We just created this mm, if we can't find the strings
-		 * we just copied into it something is _very_ wrong. Similar
-		 * for strings that are too long, we should not have created
-		 * any.
-		 */
-		if (!len || len > MAX_ARG_STRLEN) {
-			WARN_ON(1);
-			send_sig(SIGKILL, current, 0);
-		}
-
-		buf = kmalloc(len, GFP_KERNEL);
-		if (!buf) {
-			audit_panic("out of memory for argv string\n");
-			break;
-		}
-
-		ret = copy_from_user(buf, p, len);
+	/* walk the whole argument looking for non-ascii chars */
+	do {
+		if (len_left > MAX_EXECVE_AUDIT_LEN)
+			to_send = MAX_EXECVE_AUDIT_LEN;
+		else
+			to_send = len_left;
+		ret = copy_from_user(buf, tmp_p, to_send);
 		/*
 		 * There is no reason for this copy to be short. We just
 		 * copied them here, and the mm hasn't been exposed to user-
@@ -986,13 +1026,130 @@
 			WARN_ON(1);
 			send_sig(SIGKILL, current, 0);
 		}
+		buf[to_send] = '\0';
+		has_cntl = audit_string_contains_control(buf, to_send);
+		if (has_cntl) {
+			/*
+			 * hex messages get logged as 2 bytes, so we can only
+			 * send half as much in each message
+			 */
+			max_execve_audit_len = MAX_EXECVE_AUDIT_LEN / 2;
+			break;
+		}
+		len_left -= to_send;
+		tmp_p += to_send;
+	} while (len_left > 0);
 
-		audit_log_format(ab, "a%d=", i);
-		audit_log_untrustedstring(ab, buf);
-		audit_log_format(ab, "\n");
+	len_left = len;
 
-		kfree(buf);
+	if (len > max_execve_audit_len)
+		too_long = 1;
+
+	/* rewalk the argument actually logging the message */
+	for (i = 0; len_left > 0; i++) {
+		int room_left;
+
+		if (len_left > max_execve_audit_len)
+			to_send = max_execve_audit_len;
+		else
+			to_send = len_left;
+
+		/* do we have space left to send this argument in this ab? */
+		room_left = MAX_EXECVE_AUDIT_LEN - arg_num_len - *len_sent;
+		if (has_cntl)
+			room_left -= (to_send * 2);
+		else
+			room_left -= to_send;
+		if (room_left < 0) {
+			*len_sent = 0;
+			audit_log_end(*ab);
+			*ab = audit_log_start(context, GFP_KERNEL, AUDIT_EXECVE);
+			if (!*ab)
+				return 0;
+		}
+
+		/*
+		 * first record needs to say how long the original string was
+		 * so we can be sure nothing was lost.
+		 */
+		if ((i == 0) && (too_long))
+			audit_log_format(*ab, "a%d_len=%ld ", arg_num,
+					 has_cntl ? 2*len : len);
+
+		/*
+		 * normally arguments are small enough to fit and we already
+		 * filled buf above when we checked for control characters
+		 * so don't bother with another copy_from_user
+		 */
+		if (len >= max_execve_audit_len)
+			ret = copy_from_user(buf, p, to_send);
+		else
+			ret = 0;
+		if (ret) {
+			WARN_ON(1);
+			send_sig(SIGKILL, current, 0);
+		}
+		buf[to_send] = '\0';
+
+		/* actually log it */
+		audit_log_format(*ab, "a%d", arg_num);
+		if (too_long)
+			audit_log_format(*ab, "[%d]", i);
+		audit_log_format(*ab, "=");
+		if (has_cntl)
+			audit_log_hex(*ab, buf, to_send);
+		else
+			audit_log_format(*ab, "\"%s\"", buf);
+		audit_log_format(*ab, "\n");
+
+		p += to_send;
+		len_left -= to_send;
+		*len_sent += arg_num_len;
+		if (has_cntl)
+			*len_sent += to_send * 2;
+		else
+			*len_sent += to_send;
 	}
+	/* include the null we didn't log */
+	return len + 1;
+}
+
+static void audit_log_execve_info(struct audit_context *context,
+				  struct audit_buffer **ab,
+				  struct audit_aux_data_execve *axi)
+{
+	int i;
+	size_t len, len_sent = 0;
+	const char __user *p;
+	char *buf;
+
+	if (axi->mm != current->mm)
+		return; /* execve failed, no additional info */
+
+	p = (const char __user *)axi->mm->arg_start;
+
+	audit_log_format(*ab, "argc=%d ", axi->argc);
+
+	/*
+	 * we need some kernel buffer to hold the userspace args.  Just
+	 * allocate one big one rather than allocating one of the right size
+	 * for every single argument inside audit_log_single_execve_arg()
+	 * should be <8k allocation so should be pretty safe.
+	 */
+	buf = kmalloc(MAX_EXECVE_AUDIT_LEN + 1, GFP_KERNEL);
+	if (!buf) {
+		audit_panic("out of memory for argv string\n");
+		return;
+	}
+
+	for (i = 0; i < axi->argc; i++) {
+		len = audit_log_single_execve_arg(context, ab, i,
+						  &len_sent, p, buf);
+		if (len <= 0)
+			break;
+		p += len;
+	}
+	kfree(buf);
 }
 
 static void audit_log_exit(struct audit_context *context, struct task_struct *tsk)
@@ -1039,7 +1196,7 @@
 		  " a0=%lx a1=%lx a2=%lx a3=%lx items=%d"
 		  " ppid=%d pid=%d auid=%u uid=%u gid=%u"
 		  " euid=%u suid=%u fsuid=%u"
-		  " egid=%u sgid=%u fsgid=%u tty=%s",
+		  " egid=%u sgid=%u fsgid=%u tty=%s ses=%u",
 		  context->argv[0],
 		  context->argv[1],
 		  context->argv[2],
@@ -1047,11 +1204,12 @@
 		  context->name_count,
 		  context->ppid,
 		  context->pid,
-		  context->loginuid,
+		  tsk->loginuid,
 		  context->uid,
 		  context->gid,
 		  context->euid, context->suid, context->fsuid,
-		  context->egid, context->sgid, context->fsgid, tty);
+		  context->egid, context->sgid, context->fsgid, tty,
+		  tsk->sessionid);
 
 	mutex_unlock(&tty_mutex);
 
@@ -1135,7 +1293,7 @@
 
 		case AUDIT_EXECVE: {
 			struct audit_aux_data_execve *axi = (void *)aux;
-			audit_log_execve_info(ab, axi);
+			audit_log_execve_info(context, &ab, axi);
 			break; }
 
 		case AUDIT_SOCKETCALL: {
@@ -1168,13 +1326,19 @@
 
 		for (i = 0; i < axs->pid_count; i++)
 			if (audit_log_pid_context(context, axs->target_pid[i],
-						  axs->target_sid[i]))
+						  axs->target_auid[i],
+						  axs->target_uid[i],
+						  axs->target_sessionid[i],
+						  axs->target_sid[i],
+						  axs->target_comm[i]))
 				call_panic = 1;
 	}
 
 	if (context->target_pid &&
 	    audit_log_pid_context(context, context->target_pid,
-				  context->target_sid))
+				  context->target_auid, context->target_uid,
+				  context->target_sessionid,
+				  context->target_sid, context->target_comm))
 			call_panic = 1;
 
 	if (context->pwd && context->pwdmnt) {
@@ -1242,6 +1406,11 @@
 
 		audit_log_end(ab);
 	}
+
+	/* Send end of event record to help user space know we are finished */
+	ab = audit_log_start(context, GFP_KERNEL, AUDIT_EOE);
+	if (ab)
+		audit_log_end(ab);
 	if (call_panic)
 		audit_panic("error converting sid to string");
 }
@@ -1766,6 +1935,9 @@
 	ctx->auditable = 1;
 }
 
+/* global counter which is incremented every time something logs in */
+static atomic_t session_id = ATOMIC_INIT(0);
+
 /**
  * audit_set_loginuid - set a task's audit_context loginuid
  * @task: task whose audit context is being modified
@@ -1777,41 +1949,29 @@
  */
 int audit_set_loginuid(struct task_struct *task, uid_t loginuid)
 {
+	unsigned int sessionid = atomic_inc_return(&session_id);
 	struct audit_context *context = task->audit_context;
 
-	if (context) {
-		/* Only log if audit is enabled */
-		if (context->in_syscall) {
-			struct audit_buffer *ab;
+	if (context && context->in_syscall) {
+		struct audit_buffer *ab;
 
-			ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_LOGIN);
-			if (ab) {
-				audit_log_format(ab, "login pid=%d uid=%u "
-					"old auid=%u new auid=%u",
-					task->pid, task->uid,
-					context->loginuid, loginuid);
-				audit_log_end(ab);
-			}
+		ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_LOGIN);
+		if (ab) {
+			audit_log_format(ab, "login pid=%d uid=%u "
+				"old auid=%u new auid=%u"
+				" old ses=%u new ses=%u",
+				task->pid, task->uid,
+				task->loginuid, loginuid,
+				task->sessionid, sessionid);
+			audit_log_end(ab);
 		}
-		context->loginuid = loginuid;
 	}
+	task->sessionid = sessionid;
+	task->loginuid = loginuid;
 	return 0;
 }
 
 /**
- * audit_get_loginuid - get the loginuid for an audit_context
- * @ctx: the audit_context
- *
- * Returns the context's loginuid or -1 if @ctx is NULL.
- */
-uid_t audit_get_loginuid(struct audit_context *ctx)
-{
-	return ctx ? ctx->loginuid : -1;
-}
-
-EXPORT_SYMBOL(audit_get_loginuid);
-
-/**
  * __audit_mq_open - record audit data for a POSIX MQ open
  * @oflag: open flag
  * @mode: mode bits
@@ -2070,8 +2230,6 @@
 	return 0;
 }
 
-int audit_argv_kb = 32;
-
 int audit_bprm(struct linux_binprm *bprm)
 {
 	struct audit_aux_data_execve *ax;
@@ -2080,14 +2238,6 @@
 	if (likely(!audit_enabled || !context || context->dummy))
 		return 0;
 
-	/*
-	 * Even though the stack code doesn't limit the arg+env size any more,
-	 * the audit code requires that _all_ arguments be logged in a single
-	 * netlink skb. Hence cap it :-(
-	 */
-	if (bprm->argv_len > (audit_argv_kb << 10))
-		return -E2BIG;
-
 	ax = kmalloc(sizeof(*ax), GFP_KERNEL);
 	if (!ax)
 		return -ENOMEM;
@@ -2193,7 +2343,11 @@
 	struct audit_context *context = current->audit_context;
 
 	context->target_pid = t->pid;
+	context->target_auid = audit_get_loginuid(t);
+	context->target_uid = t->uid;
+	context->target_sessionid = audit_get_sessionid(t);
 	selinux_get_task_sid(t, &context->target_sid);
+	memcpy(context->target_comm, t->comm, TASK_COMM_LEN);
 }
 
 /**
@@ -2216,8 +2370,8 @@
 	if (audit_pid && t->tgid == audit_pid) {
 		if (sig == SIGTERM || sig == SIGHUP || sig == SIGUSR1) {
 			audit_sig_pid = tsk->pid;
-			if (ctx)
-				audit_sig_uid = ctx->loginuid;
+			if (tsk->loginuid != -1)
+				audit_sig_uid = tsk->loginuid;
 			else
 				audit_sig_uid = tsk->uid;
 			selinux_get_task_sid(tsk, &audit_sig_sid);
@@ -2230,7 +2384,11 @@
 	 * in audit_context */
 	if (!ctx->target_pid) {
 		ctx->target_pid = t->tgid;
+		ctx->target_auid = audit_get_loginuid(t);
+		ctx->target_uid = t->uid;
+		ctx->target_sessionid = audit_get_sessionid(t);
 		selinux_get_task_sid(t, &ctx->target_sid);
+		memcpy(ctx->target_comm, t->comm, TASK_COMM_LEN);
 		return 0;
 	}
 
@@ -2247,7 +2405,11 @@
 	BUG_ON(axp->pid_count >= AUDIT_AUX_PIDS);
 
 	axp->target_pid[axp->pid_count] = t->tgid;
+	axp->target_auid[axp->pid_count] = audit_get_loginuid(t);
+	axp->target_uid[axp->pid_count] = t->uid;
+	axp->target_sessionid[axp->pid_count] = audit_get_sessionid(t);
 	selinux_get_task_sid(t, &axp->target_sid[axp->pid_count]);
+	memcpy(axp->target_comm[axp->pid_count], t->comm, TASK_COMM_LEN);
 	axp->pid_count++;
 
 	return 0;
@@ -2264,6 +2426,8 @@
 {
 	struct audit_buffer *ab;
 	u32 sid;
+	uid_t auid = audit_get_loginuid(current);
+	unsigned int sessionid = audit_get_sessionid(current);
 
 	if (!audit_enabled)
 		return;
@@ -2272,9 +2436,8 @@
 		return;
 
 	ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_ANOM_ABEND);
-	audit_log_format(ab, "auid=%u uid=%u gid=%u",
-			audit_get_loginuid(current->audit_context),
-			current->uid, current->gid);
+	audit_log_format(ab, "auid=%u uid=%u gid=%u ses=%u",
+			auid, current->uid, current->gid, sessionid);
 	selinux_get_task_sid(current, &sid);
 	if (sid) {
 		char *ctx = NULL;
diff --git a/kernel/futex.c b/kernel/futex.c
index db9824d..a6baaec 100644
--- a/kernel/futex.c
+++ b/kernel/futex.c
@@ -109,6 +109,9 @@
 	/* Optional priority inheritance state: */
 	struct futex_pi_state *pi_state;
 	struct task_struct *task;
+
+	/* Bitset for the optional bitmasked wakeup */
+	u32 bitset;
 };
 
 /*
@@ -722,7 +725,7 @@
  * to this virtual address:
  */
 static int futex_wake(u32 __user *uaddr, struct rw_semaphore *fshared,
-		      int nr_wake)
+		      int nr_wake, u32 bitset)
 {
 	struct futex_hash_bucket *hb;
 	struct futex_q *this, *next;
@@ -730,6 +733,9 @@
 	union futex_key key;
 	int ret;
 
+	if (!bitset)
+		return -EINVAL;
+
 	futex_lock_mm(fshared);
 
 	ret = get_futex_key(uaddr, fshared, &key);
@@ -746,6 +752,11 @@
 				ret = -EINVAL;
 				break;
 			}
+
+			/* Check if one of the bits is set in both bitsets */
+			if (!(this->bitset & bitset))
+				continue;
+
 			wake_futex(this);
 			if (++ret >= nr_wake)
 				break;
@@ -1156,7 +1167,7 @@
 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)
+		      u32 val, ktime_t *abs_time, u32 bitset)
 {
 	struct task_struct *curr = current;
 	DECLARE_WAITQUEUE(wait, curr);
@@ -1167,7 +1178,11 @@
 	struct hrtimer_sleeper t;
 	int rem = 0;
 
+	if (!bitset)
+		return -EINVAL;
+
 	q.pi_state = NULL;
+	q.bitset = bitset;
  retry:
 	futex_lock_mm(fshared);
 
@@ -1252,6 +1267,8 @@
 			t.timer.expires = *abs_time;
 
 			hrtimer_start(&t.timer, t.timer.expires, HRTIMER_MODE_ABS);
+			if (!hrtimer_active(&t.timer))
+				t.task = NULL;
 
 			/*
 			 * the timer could have already expired, in which
@@ -1293,6 +1310,7 @@
 		restart->futex.uaddr = (u32 *)uaddr;
 		restart->futex.val = val;
 		restart->futex.time = abs_time->tv64;
+		restart->futex.bitset = bitset;
 		restart->futex.flags = 0;
 
 		if (fshared)
@@ -1319,7 +1337,8 @@
 	restart->fn = do_no_restart_syscall;
 	if (restart->futex.flags & FLAGS_SHARED)
 		fshared = &current->mm->mmap_sem;
-	return (long)futex_wait(uaddr, fshared, restart->futex.val, &t);
+	return (long)futex_wait(uaddr, fshared, restart->futex.val, &t,
+				restart->futex.bitset);
 }
 
 
@@ -1535,9 +1554,6 @@
 				owner = rt_mutex_owner(&q.pi_state->pi_mutex);
 				res = fixup_pi_state_owner(uaddr, &q, owner);
 
-				WARN_ON(rt_mutex_owner(&q.pi_state->pi_mutex) !=
-					owner);
-
 				/* propagate -EFAULT, if the fixup failed */
 				if (res)
 					ret = res;
@@ -1943,7 +1959,8 @@
 		 * PI futexes happens in exit_pi_state():
 		 */
 		if (!pi && (uval & FUTEX_WAITERS))
-				futex_wake(uaddr, &curr->mm->mmap_sem, 1);
+			futex_wake(uaddr, &curr->mm->mmap_sem, 1,
+				   FUTEX_BITSET_MATCH_ANY);
 	}
 	return 0;
 }
@@ -2043,10 +2060,14 @@
 
 	switch (cmd) {
 	case FUTEX_WAIT:
-		ret = futex_wait(uaddr, fshared, val, timeout);
+		val3 = FUTEX_BITSET_MATCH_ANY;
+	case FUTEX_WAIT_BITSET:
+		ret = futex_wait(uaddr, fshared, val, timeout, val3);
 		break;
 	case FUTEX_WAKE:
-		ret = futex_wake(uaddr, fshared, val);
+		val3 = FUTEX_BITSET_MATCH_ANY;
+	case FUTEX_WAKE_BITSET:
+		ret = futex_wake(uaddr, fshared, val, val3);
 		break;
 	case FUTEX_FD:
 		/* non-zero val means F_SETOWN(getpid()) & F_SETSIG(val) */
@@ -2086,7 +2107,8 @@
 	u32 val2 = 0;
 	int cmd = op & FUTEX_CMD_MASK;
 
-	if (utime && (cmd == FUTEX_WAIT || cmd == FUTEX_LOCK_PI)) {
+	if (utime && (cmd == FUTEX_WAIT || cmd == FUTEX_LOCK_PI ||
+		      cmd == FUTEX_WAIT_BITSET)) {
 		if (copy_from_user(&ts, utime, sizeof(ts)) != 0)
 			return -EFAULT;
 		if (!timespec_valid(&ts))
diff --git a/kernel/futex_compat.c b/kernel/futex_compat.c
index 0a43def..133d558d 100644
--- a/kernel/futex_compat.c
+++ b/kernel/futex_compat.c
@@ -167,7 +167,8 @@
 	int val2 = 0;
 	int cmd = op & FUTEX_CMD_MASK;
 
-	if (utime && (cmd == FUTEX_WAIT || cmd == FUTEX_LOCK_PI)) {
+	if (utime && (cmd == FUTEX_WAIT || cmd == FUTEX_LOCK_PI ||
+		      cmd == FUTEX_WAIT_BITSET)) {
 		if (get_compat_timespec(&ts, utime))
 			return -EFAULT;
 		if (!timespec_valid(&ts))
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c
index bd5d6b5..1069998 100644
--- a/kernel/hrtimer.c
+++ b/kernel/hrtimer.c
@@ -1315,6 +1315,8 @@
 
 	} while (t->task && !signal_pending(current));
 
+	__set_current_state(TASK_RUNNING);
+
 	return t->task == NULL;
 }
 
diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig
index 8e186c6..ef9b802 100644
--- a/kernel/power/Kconfig
+++ b/kernel/power/Kconfig
@@ -44,9 +44,30 @@
 	---help---
 	This option enables verbose messages from the Power Management code.
 
+config CAN_PM_TRACE
+	def_bool y
+	depends on PM_DEBUG && PM_SLEEP && EXPERIMENTAL
+
 config PM_TRACE
+	bool
+	help
+	  This enables code to save the last PM event point across
+	  reboot. The architecture needs to support this, x86 for
+	  example does by saving things in the RTC, see below.
+
+	  The architecture specific code must provide the extern
+	  functions from <linux/resume-trace.h> as well as the
+	  <asm/resume-trace.h> header with a TRACE_RESUME() macro.
+
+	  The way the information is presented is architecture-
+	  dependent, x86 will print the information during a
+	  late_initcall.
+
+config PM_TRACE_RTC
 	bool "Suspend/resume event tracing"
-	depends on PM_DEBUG && X86 && PM_SLEEP && EXPERIMENTAL
+	depends on CAN_PM_TRACE
+	depends on X86
+	select PM_TRACE
 	default n
 	---help---
 	This enables some cheesy code to save the last PM event point in the
@@ -63,7 +84,8 @@
 
 config PM_SLEEP_SMP
 	bool
-	depends on SUSPEND_SMP_POSSIBLE || HIBERNATION_SMP_POSSIBLE
+	depends on SMP
+	depends on ARCH_SUSPEND_POSSIBLE || ARCH_HIBERNATION_POSSIBLE
 	depends on PM_SLEEP
 	select HOTPLUG_CPU
 	default y
@@ -73,46 +95,29 @@
 	depends on SUSPEND || HIBERNATION
 	default y
 
-config SUSPEND_UP_POSSIBLE
-	bool
-	depends on (X86 && !X86_VOYAGER) || PPC || ARM || BLACKFIN || MIPS \
-		   || SUPERH || FRV
-	depends on !SMP
-	default y
-
-config SUSPEND_SMP_POSSIBLE
-	bool
-	depends on (X86 && !X86_VOYAGER) \
-		   || (PPC && (PPC_PSERIES || PPC_PMAC)) || ARM
-	depends on SMP
-	default y
-
 config SUSPEND
 	bool "Suspend to RAM and standby"
-	depends on PM
-	depends on SUSPEND_UP_POSSIBLE || SUSPEND_SMP_POSSIBLE
+	depends on PM && ARCH_SUSPEND_POSSIBLE
 	default y
 	---help---
 	  Allow the system to enter sleep states in which main memory is
 	  powered and thus its contents are preserved, such as the
-	  suspend-to-RAM state (i.e. the ACPI S3 state).
+	  suspend-to-RAM state (e.g. the ACPI S3 state).
 
-config HIBERNATION_UP_POSSIBLE
-	bool
-	depends on X86 || PPC64_SWSUSP || PPC32
-	depends on !SMP
+config SUSPEND_FREEZER
+	bool "Enable freezer for suspend to RAM/standby" \
+		if ARCH_WANTS_FREEZER_CONTROL || BROKEN
+	depends on SUSPEND
 	default y
+	help
+	  This allows you to turn off the freezer for suspend. If this is
+	  done, no tasks are frozen for suspend to RAM/standby.
 
-config HIBERNATION_SMP_POSSIBLE
-	bool
-	depends on (X86 && !X86_VOYAGER) || PPC64_SWSUSP
-	depends on SMP
-	default y
+	  Turning OFF this setting is NOT recommended! If in doubt, say Y.
 
 config HIBERNATION
 	bool "Hibernation (aka 'suspend to disk')"
-	depends on PM && SWAP
-	depends on HIBERNATION_UP_POSSIBLE || HIBERNATION_SMP_POSSIBLE
+	depends on PM && SWAP && ARCH_HIBERNATION_POSSIBLE
 	---help---
 	  Enable the suspend to disk (STD) functionality, which is usually
 	  called "hibernation" in user interfaces.  STD checkpoints the
diff --git a/kernel/power/disk.c b/kernel/power/disk.c
index b138b43..d09da08 100644
--- a/kernel/power/disk.c
+++ b/kernel/power/disk.c
@@ -54,8 +54,8 @@
 
 void hibernation_set_ops(struct platform_hibernation_ops *ops)
 {
-	if (ops && !(ops->start && ops->pre_snapshot && ops->finish
-	    && ops->prepare && ops->enter && ops->pre_restore
+	if (ops && !(ops->begin && ops->end &&  ops->pre_snapshot
+	    && ops->prepare && ops->finish && ops->enter && ops->pre_restore
 	    && ops->restore_cleanup)) {
 		WARN_ON(1);
 		return;
@@ -70,15 +70,55 @@
 	mutex_unlock(&pm_mutex);
 }
 
+#ifdef CONFIG_PM_DEBUG
+static void hibernation_debug_sleep(void)
+{
+	printk(KERN_INFO "hibernation debug: Waiting for 5 seconds.\n");
+	mdelay(5000);
+}
+
+static int hibernation_testmode(int mode)
+{
+	if (hibernation_mode == mode) {
+		hibernation_debug_sleep();
+		return 1;
+	}
+	return 0;
+}
+
+static int hibernation_test(int level)
+{
+	if (pm_test_level == level) {
+		hibernation_debug_sleep();
+		return 1;
+	}
+	return 0;
+}
+#else /* !CONFIG_PM_DEBUG */
+static int hibernation_testmode(int mode) { return 0; }
+static int hibernation_test(int level) { return 0; }
+#endif /* !CONFIG_PM_DEBUG */
+
 /**
- *	platform_start - tell the platform driver that we're starting
+ *	platform_begin - tell the platform driver that we're starting
  *	hibernation
  */
 
-static int platform_start(int platform_mode)
+static int platform_begin(int platform_mode)
 {
 	return (platform_mode && hibernation_ops) ?
-		hibernation_ops->start() : 0;
+		hibernation_ops->begin() : 0;
+}
+
+/**
+ *	platform_end - tell the platform driver that we've entered the
+ *	working state
+ */
+
+static void platform_end(int platform_mode)
+{
+	if (platform_mode && hibernation_ops)
+		hibernation_ops->end();
 }
 
 /**
@@ -162,19 +202,25 @@
 	 */
 	error = device_power_down(PMSG_FREEZE);
 	if (error) {
-		printk(KERN_ERR "Some devices failed to power down, "
-			KERN_ERR "aborting suspend\n");
+		printk(KERN_ERR "PM: Some devices failed to power down, "
+			"aborting hibernation\n");
 		goto Enable_irqs;
 	}
 
+	if (hibernation_test(TEST_CORE))
+		goto Power_up;
+
+	in_suspend = 1;
 	save_processor_state();
 	error = swsusp_arch_suspend();
 	if (error)
-		printk(KERN_ERR "Error %d while creating the image\n", error);
+		printk(KERN_ERR "PM: Error %d creating hibernation image\n",
+			error);
 	/* Restore control flow magically appears here */
 	restore_processor_state();
 	if (!in_suspend)
 		platform_leave(platform_mode);
+ Power_up:
 	/* NOTE:  device_power_up() is just a resume() for devices
 	 * that suspended with irqs off ... no overall powerup.
 	 */
@@ -202,36 +248,90 @@
 	if (error)
 		return error;
 
-	error = platform_start(platform_mode);
+	error = platform_begin(platform_mode);
 	if (error)
-		return error;
+		goto Close;
 
 	suspend_console();
 	error = device_suspend(PMSG_FREEZE);
 	if (error)
 		goto Resume_console;
 
-	error = platform_pre_snapshot(platform_mode);
-	if (error)
+	if (hibernation_test(TEST_DEVICES))
 		goto Resume_devices;
 
+	error = platform_pre_snapshot(platform_mode);
+	if (error || hibernation_test(TEST_PLATFORM))
+		goto Finish;
+
 	error = disable_nonboot_cpus();
 	if (!error) {
-		if (hibernation_mode != HIBERNATION_TEST) {
-			in_suspend = 1;
-			error = create_image(platform_mode);
-			/* Control returns here after successful restore */
-		} else {
-			printk("swsusp debug: Waiting for 5 seconds.\n");
-			mdelay(5000);
-		}
+		if (hibernation_test(TEST_CPUS))
+			goto Enable_cpus;
+
+		if (hibernation_testmode(HIBERNATION_TEST))
+			goto Enable_cpus;
+
+		error = create_image(platform_mode);
+		/* Control returns here after successful restore */
 	}
+ Enable_cpus:
 	enable_nonboot_cpus();
- Resume_devices:
+ Finish:
 	platform_finish(platform_mode);
+ Resume_devices:
 	device_resume();
  Resume_console:
 	resume_console();
+ Close:
+	platform_end(platform_mode);
+	return error;
+}
+
+/**
+ *	resume_target_kernel - prepare devices that need to be suspended with
+ *	interrupts off, restore the contents of highmem that have not been
+ *	restored yet from the image and run the low level code that will restore
+ *	the remaining contents of memory and switch to the just restored target
+ *	kernel.
+ */
+
+static int resume_target_kernel(void)
+{
+	int error;
+
+	local_irq_disable();
+	error = device_power_down(PMSG_PRETHAW);
+	if (error) {
+		printk(KERN_ERR "PM: Some devices failed to power down, "
+			"aborting resume\n");
+		goto Enable_irqs;
+	}
+	/* We'll ignore saved state, but this gets preempt count (etc) right */
+	save_processor_state();
+	error = restore_highmem();
+	if (!error) {
+		error = swsusp_arch_resume();
+		/*
+		 * The code below is only ever reached in case of a failure.
+		 * Otherwise execution continues at place where
+		 * swsusp_arch_suspend() was called
+		 */
+		BUG_ON(!error);
+		/* This call to restore_highmem() undos the previous one */
+		restore_highmem();
+	}
+	/*
+	 * The only reason why swsusp_arch_resume() can fail is memory being
+	 * very tight, so we have to free it as soon as we can to avoid
+	 * subsequent failures
+	 */
+	swsusp_free();
+	restore_processor_state();
+	touch_softlockup_watchdog();
+	device_power_up();
+ Enable_irqs:
+	local_irq_enable();
 	return error;
 }
 
@@ -258,7 +358,7 @@
 	if (!error) {
 		error = disable_nonboot_cpus();
 		if (!error)
-			error = swsusp_resume();
+			error = resume_target_kernel();
 		enable_nonboot_cpus();
 	}
 	platform_restore_cleanup(platform_mode);
@@ -286,9 +386,9 @@
 	 * hibernation_ops->finish() before saving the image, so we should let
 	 * the firmware know that we're going to enter the sleep state after all
 	 */
-	error = hibernation_ops->start();
+	error = hibernation_ops->begin();
 	if (error)
-		return error;
+		goto Close;
 
 	suspend_console();
 	error = device_suspend(PMSG_SUSPEND);
@@ -322,6 +422,8 @@
 	device_resume();
  Resume_console:
 	resume_console();
+ Close:
+	hibernation_ops->end();
 	return error;
 }
 
@@ -352,24 +454,17 @@
 	 * Valid image is on the disk, if we continue we risk serious data
 	 * corruption after resume.
 	 */
-	printk(KERN_CRIT "Please power me down manually\n");
+	printk(KERN_CRIT "PM: Please power down manually\n");
 	while(1);
 }
 
-static void unprepare_processes(void)
-{
-	thaw_processes();
-	pm_restore_console();
-}
-
 static int prepare_processes(void)
 {
 	int error = 0;
 
-	pm_prepare_console();
 	if (freeze_processes()) {
 		error = -EBUSY;
-		unprepare_processes();
+		thaw_processes();
 	}
 	return error;
 }
@@ -389,6 +484,7 @@
 		goto Unlock;
 	}
 
+	pm_prepare_console();
 	error = pm_notifier_call_chain(PM_HIBERNATION_PREPARE);
 	if (error)
 		goto Exit;
@@ -398,7 +494,7 @@
 	if (error)
 		goto Exit;
 
-	printk("Syncing filesystems ... ");
+	printk(KERN_INFO "PM: Syncing filesystems ... ");
 	sys_sync();
 	printk("done.\n");
 
@@ -406,11 +502,12 @@
 	if (error)
 		goto Finish;
 
-	if (hibernation_mode == HIBERNATION_TESTPROC) {
-		printk("swsusp debug: Waiting for 5 seconds.\n");
-		mdelay(5000);
+	if (hibernation_test(TEST_FREEZER))
 		goto Thaw;
-	}
+
+	if (hibernation_testmode(HIBERNATION_TESTPROC))
+		goto Thaw;
+
 	error = hibernation_snapshot(hibernation_mode == HIBERNATION_PLATFORM);
 	if (in_suspend && !error) {
 		unsigned int flags = 0;
@@ -427,11 +524,12 @@
 		swsusp_free();
 	}
  Thaw:
-	unprepare_processes();
+	thaw_processes();
  Finish:
 	free_basic_memory_bitmaps();
  Exit:
 	pm_notifier_call_chain(PM_POST_HIBERNATION);
+	pm_restore_console();
 	atomic_inc(&snapshot_device_available);
  Unlock:
 	mutex_unlock(&pm_mutex);
@@ -473,22 +571,23 @@
 			return -ENOENT;
 		}
 		swsusp_resume_device = name_to_dev_t(resume_file);
-		pr_debug("swsusp: Resume From Partition %s\n", resume_file);
+		pr_debug("PM: Resume from partition %s\n", resume_file);
 	} else {
-		pr_debug("swsusp: Resume From Partition %d:%d\n",
-			 MAJOR(swsusp_resume_device), MINOR(swsusp_resume_device));
+		pr_debug("PM: Resume from partition %d:%d\n",
+				MAJOR(swsusp_resume_device),
+				MINOR(swsusp_resume_device));
 	}
 
 	if (noresume) {
 		/**
-		 * FIXME: If noresume is specified, we need to find the partition
-		 * and reset it back to normal swap space.
+		 * FIXME: If noresume is specified, we need to find the
+		 * partition and reset it back to normal swap space.
 		 */
 		mutex_unlock(&pm_mutex);
 		return 0;
 	}
 
-	pr_debug("PM: Checking swsusp image.\n");
+	pr_debug("PM: Checking hibernation image.\n");
 	error = swsusp_check();
 	if (error)
 		goto Unlock;
@@ -499,6 +598,11 @@
 		goto Unlock;
 	}
 
+	pm_prepare_console();
+	error = pm_notifier_call_chain(PM_RESTORE_PREPARE);
+	if (error)
+		goto Finish;
+
 	error = create_basic_memory_bitmaps();
 	if (error)
 		goto Finish;
@@ -510,7 +614,7 @@
 		goto Done;
 	}
 
-	pr_debug("PM: Reading swsusp image.\n");
+	pr_debug("PM: Reading hibernation image.\n");
 
 	error = swsusp_read(&flags);
 	if (!error)
@@ -518,10 +622,12 @@
 
 	printk(KERN_ERR "PM: Restore failed, recovering.\n");
 	swsusp_free();
-	unprepare_processes();
+	thaw_processes();
  Done:
 	free_basic_memory_bitmaps();
  Finish:
+	pm_notifier_call_chain(PM_POST_RESTORE);
+	pm_restore_console();
 	atomic_inc(&snapshot_device_available);
 	/* For success case, the suspend path will release the lock */
  Unlock:
@@ -636,7 +742,7 @@
 		error = -EINVAL;
 
 	if (!error)
-		pr_debug("PM: suspend-to-disk mode set to '%s'\n",
+		pr_debug("PM: Hibernation mode set to '%s'\n",
 			 hibernation_modes[mode]);
 	mutex_unlock(&pm_mutex);
 	return error ? error : n;
@@ -668,7 +774,7 @@
 	mutex_lock(&pm_mutex);
 	swsusp_resume_device = res;
 	mutex_unlock(&pm_mutex);
-	printk("Attempting manual resume\n");
+	printk(KERN_INFO "PM: Starting manual resume from disk\n");
 	noresume = 0;
 	software_resume();
 	ret = n;
diff --git a/kernel/power/main.c b/kernel/power/main.c
index efc0836..6a6d5eb 100644
--- a/kernel/power/main.c
+++ b/kernel/power/main.c
@@ -24,13 +24,112 @@
 
 #include "power.h"
 
-BLOCKING_NOTIFIER_HEAD(pm_chain_head);
-
 DEFINE_MUTEX(pm_mutex);
 
 unsigned int pm_flags;
 EXPORT_SYMBOL(pm_flags);
 
+#ifdef CONFIG_PM_SLEEP
+
+/* Routines for PM-transition notifications */
+
+static BLOCKING_NOTIFIER_HEAD(pm_chain_head);
+
+int register_pm_notifier(struct notifier_block *nb)
+{
+	return blocking_notifier_chain_register(&pm_chain_head, nb);
+}
+EXPORT_SYMBOL_GPL(register_pm_notifier);
+
+int unregister_pm_notifier(struct notifier_block *nb)
+{
+	return blocking_notifier_chain_unregister(&pm_chain_head, nb);
+}
+EXPORT_SYMBOL_GPL(unregister_pm_notifier);
+
+int pm_notifier_call_chain(unsigned long val)
+{
+	return (blocking_notifier_call_chain(&pm_chain_head, val, NULL)
+			== NOTIFY_BAD) ? -EINVAL : 0;
+}
+
+#ifdef CONFIG_PM_DEBUG
+int pm_test_level = TEST_NONE;
+
+static int suspend_test(int level)
+{
+	if (pm_test_level == level) {
+		printk(KERN_INFO "suspend debug: Waiting for 5 seconds.\n");
+		mdelay(5000);
+		return 1;
+	}
+	return 0;
+}
+
+static const char * const pm_tests[__TEST_AFTER_LAST] = {
+	[TEST_NONE] = "none",
+	[TEST_CORE] = "core",
+	[TEST_CPUS] = "processors",
+	[TEST_PLATFORM] = "platform",
+	[TEST_DEVICES] = "devices",
+	[TEST_FREEZER] = "freezer",
+};
+
+static ssize_t pm_test_show(struct kobject *kobj, struct kobj_attribute *attr,
+				char *buf)
+{
+	char *s = buf;
+	int level;
+
+	for (level = TEST_FIRST; level <= TEST_MAX; level++)
+		if (pm_tests[level]) {
+			if (level == pm_test_level)
+				s += sprintf(s, "[%s] ", pm_tests[level]);
+			else
+				s += sprintf(s, "%s ", pm_tests[level]);
+		}
+
+	if (s != buf)
+		/* convert the last space to a newline */
+		*(s-1) = '\n';
+
+	return (s - buf);
+}
+
+static ssize_t pm_test_store(struct kobject *kobj, struct kobj_attribute *attr,
+				const char *buf, size_t n)
+{
+	const char * const *s;
+	int level;
+	char *p;
+	int len;
+	int error = -EINVAL;
+
+	p = memchr(buf, '\n', n);
+	len = p ? p - buf : n;
+
+	mutex_lock(&pm_mutex);
+
+	level = TEST_FIRST;
+	for (s = &pm_tests[level]; level <= TEST_MAX; s++, level++)
+		if (*s && len == strlen(*s) && !strncmp(buf, *s, len)) {
+			pm_test_level = level;
+			error = 0;
+			break;
+		}
+
+	mutex_unlock(&pm_mutex);
+
+	return error ? error : n;
+}
+
+power_attr(pm_test);
+#else /* !CONFIG_PM_DEBUG */
+static inline int suspend_test(int level) { return 0; }
+#endif /* !CONFIG_PM_DEBUG */
+
+#endif /* CONFIG_PM_SLEEP */
+
 #ifdef CONFIG_SUSPEND
 
 /* This is just an arbitrary number */
@@ -76,13 +175,13 @@
 	if (!suspend_ops || !suspend_ops->enter)
 		return -EPERM;
 
+	pm_prepare_console();
+
 	error = pm_notifier_call_chain(PM_SUSPEND_PREPARE);
 	if (error)
 		goto Finish;
 
-	pm_prepare_console();
-
-	if (freeze_processes()) {
+	if (suspend_freeze_processes()) {
 		error = -EAGAIN;
 		goto Thaw;
 	}
@@ -100,10 +199,10 @@
 		return 0;
 
  Thaw:
-	thaw_processes();
-	pm_restore_console();
+	suspend_thaw_processes();
  Finish:
 	pm_notifier_call_chain(PM_POST_SUSPEND);
+	pm_restore_console();
 	return error;
 }
 
@@ -133,10 +232,13 @@
 	BUG_ON(!irqs_disabled());
 
 	if ((error = device_power_down(PMSG_SUSPEND))) {
-		printk(KERN_ERR "Some devices failed to power down\n");
+		printk(KERN_ERR "PM: Some devices failed to power down\n");
 		goto Done;
 	}
-	error = suspend_ops->enter(state);
+
+	if (!suspend_test(TEST_CORE))
+		error = suspend_ops->enter(state);
+
 	device_power_up();
  Done:
 	arch_suspend_enable_irqs();
@@ -145,8 +247,8 @@
 }
 
 /**
- *	suspend_devices_and_enter - suspend devices and enter the desired system sleep
- *			  state.
+ *	suspend_devices_and_enter - suspend devices and enter the desired system
+ *				    sleep state.
  *	@state:		  state to enter
  */
 int suspend_devices_and_enter(suspend_state_t state)
@@ -156,33 +258,45 @@
 	if (!suspend_ops)
 		return -ENOSYS;
 
-	if (suspend_ops->set_target) {
-		error = suspend_ops->set_target(state);
+	if (suspend_ops->begin) {
+		error = suspend_ops->begin(state);
 		if (error)
-			return error;
+			goto Close;
 	}
 	suspend_console();
 	error = device_suspend(PMSG_SUSPEND);
 	if (error) {
-		printk(KERN_ERR "Some devices failed to suspend\n");
+		printk(KERN_ERR "PM: Some devices failed to suspend\n");
 		goto Resume_console;
 	}
+
+	if (suspend_test(TEST_DEVICES))
+		goto Resume_devices;
+
 	if (suspend_ops->prepare) {
 		error = suspend_ops->prepare();
 		if (error)
 			goto Resume_devices;
 	}
+
+	if (suspend_test(TEST_PLATFORM))
+		goto Finish;
+
 	error = disable_nonboot_cpus();
-	if (!error)
+	if (!error && !suspend_test(TEST_CPUS))
 		suspend_enter(state);
 
 	enable_nonboot_cpus();
+ Finish:
 	if (suspend_ops->finish)
 		suspend_ops->finish();
  Resume_devices:
 	device_resume();
  Resume_console:
 	resume_console();
+ Close:
+	if (suspend_ops->end)
+		suspend_ops->end();
 	return error;
 }
 
@@ -194,9 +308,9 @@
  */
 static void suspend_finish(void)
 {
-	thaw_processes();
-	pm_restore_console();
+	suspend_thaw_processes();
 	pm_notifier_call_chain(PM_POST_SUSPEND);
+	pm_restore_console();
 }
 
 
@@ -238,17 +352,22 @@
 	if (!mutex_trylock(&pm_mutex))
 		return -EBUSY;
 
-	printk("Syncing filesystems ... ");
+	printk(KERN_INFO "PM: Syncing filesystems ... ");
 	sys_sync();
 	printk("done.\n");
 
 	pr_debug("PM: Preparing system for %s sleep\n", pm_states[state]);
-	if ((error = suspend_prepare()))
+	error = suspend_prepare();
+	if (error)
 		goto Unlock;
 
+	if (suspend_test(TEST_FREEZER))
+		goto Finish;
+
 	pr_debug("PM: Entering %s sleep\n", pm_states[state]);
 	error = suspend_devices_and_enter(state);
 
+ Finish:
 	pr_debug("PM: Finishing wakeup.\n");
 	suspend_finish();
  Unlock:
@@ -369,18 +488,18 @@
 }
 
 power_attr(pm_trace);
+#endif /* CONFIG_PM_TRACE */
 
 static struct attribute * g[] = {
 	&state_attr.attr,
+#ifdef CONFIG_PM_TRACE
 	&pm_trace_attr.attr,
+#endif
+#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_PM_DEBUG)
+	&pm_test_attr.attr,
+#endif
 	NULL,
 };
-#else
-static struct attribute * g[] = {
-	&state_attr.attr,
-	NULL,
-};
-#endif /* CONFIG_PM_TRACE */
 
 static struct attribute_group attr_group = {
 	.attrs = g,
diff --git a/kernel/power/power.h b/kernel/power/power.h
index 2093c3a..700f44e 100644
--- a/kernel/power/power.h
+++ b/kernel/power/power.h
@@ -1,5 +1,7 @@
 #include <linux/suspend.h>
+#include <linux/suspend_ioctls.h>
 #include <linux/utsname.h>
+#include <linux/freezer.h>
 
 struct swsusp_info {
 	struct new_utsname	uts;
@@ -128,42 +130,12 @@
 #define data_of(handle)	((handle).buffer + (handle).buf_offset)
 
 extern unsigned int snapshot_additional_pages(struct zone *zone);
+extern unsigned long snapshot_get_image_size(void);
 extern int snapshot_read_next(struct snapshot_handle *handle, size_t count);
 extern int snapshot_write_next(struct snapshot_handle *handle, size_t count);
 extern void snapshot_write_finalize(struct snapshot_handle *handle);
 extern int snapshot_image_loaded(struct snapshot_handle *handle);
 
-/*
- * This structure is used to pass the values needed for the identification
- * of the resume swap area from a user space to the kernel via the
- * SNAPSHOT_SET_SWAP_AREA ioctl
- */
-struct resume_swap_area {
-	loff_t offset;
-	u_int32_t dev;
-} __attribute__((packed));
-
-#define SNAPSHOT_IOC_MAGIC	'3'
-#define SNAPSHOT_FREEZE			_IO(SNAPSHOT_IOC_MAGIC, 1)
-#define SNAPSHOT_UNFREEZE		_IO(SNAPSHOT_IOC_MAGIC, 2)
-#define SNAPSHOT_ATOMIC_SNAPSHOT	_IOW(SNAPSHOT_IOC_MAGIC, 3, void *)
-#define SNAPSHOT_ATOMIC_RESTORE		_IO(SNAPSHOT_IOC_MAGIC, 4)
-#define SNAPSHOT_FREE			_IO(SNAPSHOT_IOC_MAGIC, 5)
-#define SNAPSHOT_SET_IMAGE_SIZE		_IOW(SNAPSHOT_IOC_MAGIC, 6, unsigned long)
-#define SNAPSHOT_AVAIL_SWAP		_IOR(SNAPSHOT_IOC_MAGIC, 7, void *)
-#define SNAPSHOT_GET_SWAP_PAGE		_IOR(SNAPSHOT_IOC_MAGIC, 8, void *)
-#define SNAPSHOT_FREE_SWAP_PAGES	_IO(SNAPSHOT_IOC_MAGIC, 9)
-#define SNAPSHOT_SET_SWAP_FILE		_IOW(SNAPSHOT_IOC_MAGIC, 10, unsigned int)
-#define SNAPSHOT_S2RAM			_IO(SNAPSHOT_IOC_MAGIC, 11)
-#define SNAPSHOT_PMOPS			_IOW(SNAPSHOT_IOC_MAGIC, 12, unsigned int)
-#define SNAPSHOT_SET_SWAP_AREA		_IOW(SNAPSHOT_IOC_MAGIC, 13, \
-							struct resume_swap_area)
-#define SNAPSHOT_IOC_MAXNR	13
-
-#define PMOPS_PREPARE	1
-#define PMOPS_ENTER	2
-#define PMOPS_FINISH	3
-
 /* If unset, the snapshot device cannot be open. */
 extern atomic_t snapshot_device_available;
 
@@ -181,7 +153,6 @@
 extern int swsusp_check(void);
 extern int swsusp_shrink_memory(void);
 extern void swsusp_free(void);
-extern int swsusp_resume(void);
 extern int swsusp_read(unsigned int *flags_p);
 extern int swsusp_write(unsigned int flags);
 extern void swsusp_close(void);
@@ -201,11 +172,56 @@
 }
 #endif /* !CONFIG_SUSPEND */
 
-/* kernel/power/common.c */
-extern struct blocking_notifier_head pm_chain_head;
+#ifdef CONFIG_PM_SLEEP
+/* kernel/power/main.c */
+extern int pm_notifier_call_chain(unsigned long val);
+#endif
 
-static inline int pm_notifier_call_chain(unsigned long val)
+#ifdef CONFIG_HIGHMEM
+unsigned int count_highmem_pages(void);
+int restore_highmem(void);
+#else
+static inline unsigned int count_highmem_pages(void) { return 0; }
+static inline int restore_highmem(void) { return 0; }
+#endif
+
+/*
+ * Suspend test levels
+ */
+enum {
+	/* keep first */
+	TEST_NONE,
+	TEST_CORE,
+	TEST_CPUS,
+	TEST_PLATFORM,
+	TEST_DEVICES,
+	TEST_FREEZER,
+	/* keep last */
+	__TEST_AFTER_LAST
+};
+
+#define TEST_FIRST	TEST_NONE
+#define TEST_MAX	(__TEST_AFTER_LAST - 1)
+
+extern int pm_test_level;
+
+#ifdef CONFIG_SUSPEND_FREEZER
+static inline int suspend_freeze_processes(void)
 {
-	return (blocking_notifier_call_chain(&pm_chain_head, val, NULL)
-			== NOTIFY_BAD) ? -EINVAL : 0;
+	return freeze_processes();
 }
+
+static inline void suspend_thaw_processes(void)
+{
+	thaw_processes();
+}
+#else
+static inline int suspend_freeze_processes(void)
+{
+	return 0;
+}
+
+static inline void suspend_thaw_processes(void)
+{
+}
+#endif
diff --git a/kernel/power/snapshot.c b/kernel/power/snapshot.c
index 78039b4..f6a5df9 100644
--- a/kernel/power/snapshot.c
+++ b/kernel/power/snapshot.c
@@ -635,7 +635,7 @@
 	region->end_pfn = end_pfn;
 	list_add_tail(&region->list, &nosave_regions);
  Report:
-	printk("swsusp: Registered nosave memory region: %016lx - %016lx\n",
+	printk(KERN_INFO "PM: Registered nosave memory: %016lx - %016lx\n",
 		start_pfn << PAGE_SHIFT, end_pfn << PAGE_SHIFT);
 }
 
@@ -704,7 +704,7 @@
 	list_for_each_entry(region, &nosave_regions, list) {
 		unsigned long pfn;
 
-		printk("swsusp: Marking nosave pages: %016lx - %016lx\n",
+		pr_debug("PM: Marking nosave pages: %016lx - %016lx\n",
 				region->start_pfn << PAGE_SHIFT,
 				region->end_pfn << PAGE_SHIFT);
 
@@ -749,7 +749,7 @@
 	free_pages_map = bm2;
 	mark_nosave_pages(forbidden_pages_map);
 
-	printk("swsusp: Basic memory bitmaps created\n");
+	pr_debug("PM: Basic memory bitmaps created\n");
 
 	return 0;
 
@@ -784,7 +784,7 @@
 	memory_bm_free(bm2, PG_UNSAFE_CLEAR);
 	kfree(bm2);
 
-	printk("swsusp: Basic memory bitmaps freed\n");
+	pr_debug("PM: Basic memory bitmaps freed\n");
 }
 
 /**
@@ -872,7 +872,6 @@
 }
 #else
 static inline void *saveable_highmem_page(unsigned long pfn) { return NULL; }
-static inline unsigned int count_highmem_pages(void) { return 0; }
 #endif /* CONFIG_HIGHMEM */
 
 /**
@@ -1089,7 +1088,7 @@
 	}
 
 	nr_pages += count_pages_for_highmem(nr_highmem);
-	pr_debug("swsusp: Normal pages needed: %u + %u + %u, available pages: %u\n",
+	pr_debug("PM: Normal pages needed: %u + %u + %u, available pages: %u\n",
 		nr_pages, PAGES_FOR_IO, meta, free);
 
 	return free > nr_pages + PAGES_FOR_IO + meta;
@@ -1202,20 +1201,20 @@
 {
 	unsigned int nr_pages, nr_highmem;
 
-	printk("swsusp: critical section: \n");
+	printk(KERN_INFO "PM: Creating hibernation image: \n");
 
 	drain_local_pages();
 	nr_pages = count_data_pages();
 	nr_highmem = count_highmem_pages();
-	printk("swsusp: Need to copy %u pages\n", nr_pages + nr_highmem);
+	printk(KERN_INFO "PM: Need to copy %u pages\n", nr_pages + nr_highmem);
 
 	if (!enough_free_mem(nr_pages, nr_highmem)) {
-		printk(KERN_ERR "swsusp: Not enough free memory\n");
+		printk(KERN_ERR "PM: Not enough free memory\n");
 		return -ENOMEM;
 	}
 
 	if (swsusp_alloc(&orig_bm, &copy_bm, nr_pages, nr_highmem)) {
-		printk(KERN_ERR "swsusp: Memory allocation failed\n");
+		printk(KERN_ERR "PM: Memory allocation failed\n");
 		return -ENOMEM;
 	}
 
@@ -1235,7 +1234,8 @@
 	nr_copy_pages = nr_pages;
 	nr_meta_pages = DIV_ROUND_UP(nr_pages * sizeof(long), PAGE_SIZE);
 
-	printk("swsusp: critical section: done (%d pages copied)\n", nr_pages);
+	printk(KERN_INFO "PM: Hibernation image created (%d pages copied)\n",
+		nr_pages);
 
 	return 0;
 }
@@ -1264,12 +1264,17 @@
 }
 #endif /* CONFIG_ARCH_HIBERNATION_HEADER */
 
+unsigned long snapshot_get_image_size(void)
+{
+	return nr_copy_pages + nr_meta_pages + 1;
+}
+
 static int init_header(struct swsusp_info *info)
 {
 	memset(info, 0, sizeof(struct swsusp_info));
 	info->num_physpages = num_physpages;
 	info->image_pages = nr_copy_pages;
-	info->pages = nr_copy_pages + nr_meta_pages + 1;
+	info->pages = snapshot_get_image_size();
 	info->size = info->pages;
 	info->size <<= PAGE_SHIFT;
 	return init_header_complete(info);
@@ -1429,7 +1434,7 @@
 	if (!reason && info->num_physpages != num_physpages)
 		reason = "memory size";
 	if (reason) {
-		printk(KERN_ERR "swsusp: Resume mismatch: %s\n", reason);
+		printk(KERN_ERR "PM: Image mismatch: %s\n", reason);
 		return -EPERM;
 	}
 	return 0;
diff --git a/kernel/power/swap.c b/kernel/power/swap.c
index 917aba1..a0abf9a 100644
--- a/kernel/power/swap.c
+++ b/kernel/power/swap.c
@@ -28,8 +28,6 @@
 
 #include "power.h"
 
-extern char resume_file[];
-
 #define SWSUSP_SIG	"S1SUSPEND"
 
 struct swsusp_header {
@@ -73,7 +71,8 @@
 	bio->bi_end_io = end_swap_bio_read;
 
 	if (bio_add_page(bio, page, PAGE_SIZE, 0) < PAGE_SIZE) {
-		printk("swsusp: ERROR: adding page to bio at %ld\n", page_off);
+		printk(KERN_ERR "PM: Adding page to bio failed at %ld\n",
+			page_off);
 		bio_put(bio);
 		return -EFAULT;
 	}
@@ -153,7 +152,7 @@
 		error = bio_write_page(swsusp_resume_block,
 					swsusp_header, NULL);
 	} else {
-		printk(KERN_ERR "swsusp: Swap header not found!\n");
+		printk(KERN_ERR "PM: Swap header not found!\n");
 		error = -ENODEV;
 	}
 	return error;
@@ -325,7 +324,8 @@
 	struct timeval start;
 	struct timeval stop;
 
-	printk("Saving image data pages (%u pages) ...     ", nr_to_write);
+	printk(KERN_INFO "PM: Saving image data pages (%u pages) ...     ",
+		nr_to_write);
 	m = nr_to_write / 100;
 	if (!m)
 		m = 1;
@@ -365,7 +365,7 @@
 {
 	unsigned int free_swap = count_swap_pages(root_swap, 1);
 
-	pr_debug("swsusp: free swap pages: %u\n", free_swap);
+	pr_debug("PM: Free swap pages: %u\n", free_swap);
 	return free_swap > nr_pages + PAGES_FOR_IO;
 }
 
@@ -388,7 +388,7 @@
 
 	error = swsusp_swap_check();
 	if (error) {
-		printk(KERN_ERR "swsusp: Cannot find swap device, try "
+		printk(KERN_ERR "PM: Cannot find swap device, try "
 				"swapon -a.\n");
 		return error;
 	}
@@ -402,7 +402,7 @@
 	}
 	header = (struct swsusp_info *)data_of(snapshot);
 	if (!enough_swap(header->pages)) {
-		printk(KERN_ERR "swsusp: Not enough free swap\n");
+		printk(KERN_ERR "PM: Not enough free swap\n");
 		error = -ENOSPC;
 		goto out;
 	}
@@ -417,7 +417,7 @@
 
 		if (!error) {
 			flush_swap_writer(&handle);
-			printk("S");
+			printk(KERN_INFO "PM: S");
 			error = mark_swapfiles(start, flags);
 			printk("|\n");
 		}
@@ -507,7 +507,8 @@
 	int err2;
 	unsigned nr_pages;
 
-	printk("Loading image data pages (%u pages) ...     ", nr_to_read);
+	printk(KERN_INFO "PM: Loading image data pages (%u pages) ...     ",
+		nr_to_read);
 	m = nr_to_read / 100;
 	if (!m)
 		m = 1;
@@ -558,7 +559,7 @@
 
 	*flags_p = swsusp_header->flags;
 	if (IS_ERR(resume_bdev)) {
-		pr_debug("swsusp: block device not initialised\n");
+		pr_debug("PM: Image device not initialised\n");
 		return PTR_ERR(resume_bdev);
 	}
 
@@ -577,9 +578,9 @@
 	blkdev_put(resume_bdev);
 
 	if (!error)
-		pr_debug("swsusp: Reading resume file was successful\n");
+		pr_debug("PM: Image successfully loaded\n");
 	else
-		pr_debug("swsusp: Error %d resuming\n", error);
+		pr_debug("PM: Error %d resuming\n", error);
 	return error;
 }
 
@@ -611,13 +612,13 @@
 		if (error)
 			blkdev_put(resume_bdev);
 		else
-			pr_debug("swsusp: Signature found, resuming\n");
+			pr_debug("PM: Signature found, resuming\n");
 	} else {
 		error = PTR_ERR(resume_bdev);
 	}
 
 	if (error)
-		pr_debug("swsusp: Error %d check for resume file\n", error);
+		pr_debug("PM: Error %d checking image file\n", error);
 
 	return error;
 }
@@ -629,7 +630,7 @@
 void swsusp_close(void)
 {
 	if (IS_ERR(resume_bdev)) {
-		pr_debug("swsusp: block device not initialised\n");
+		pr_debug("PM: Image device not initialised\n");
 		return;
 	}
 
diff --git a/kernel/power/swsusp.c b/kernel/power/swsusp.c
index e1722d3..023ff2a 100644
--- a/kernel/power/swsusp.c
+++ b/kernel/power/swsusp.c
@@ -64,14 +64,6 @@
 
 int in_suspend __nosavedata = 0;
 
-#ifdef CONFIG_HIGHMEM
-unsigned int count_highmem_pages(void);
-int restore_highmem(void);
-#else
-static inline int restore_highmem(void) { return 0; }
-static inline unsigned int count_highmem_pages(void) { return 0; }
-#endif
-
 /**
  *	The following functions are used for tracing the allocated
  *	swap pages, so that they can be freed in case of an error.
@@ -196,7 +188,8 @@
 		centisecs = 1;	/* avoid div-by-zero */
 	k = nr_pages * (PAGE_SIZE / 1024);
 	kps = (k * 100) / centisecs;
-	printk("%s %d kbytes in %d.%02d seconds (%d.%02d MB/s)\n", msg, k,
+	printk(KERN_INFO "PM: %s %d kbytes in %d.%02d seconds (%d.%02d MB/s)\n",
+			msg, k,
 			centisecs / 100, centisecs % 100,
 			kps / 1000, (kps % 1000) / 10);
 }
@@ -227,7 +220,7 @@
 	char *p = "-\\|/";
 	struct timeval start, stop;
 
-	printk("Shrinking memory...  ");
+	printk(KERN_INFO "PM: Shrinking memory...  ");
 	do_gettimeofday(&start);
 	do {
 		long size, highmem_size;
@@ -269,38 +262,3 @@
 
 	return 0;
 }
-
-int swsusp_resume(void)
-{
-	int error;
-
-	local_irq_disable();
-	/* NOTE:  device_power_down() is just a suspend() with irqs off;
-	 * it has no special "power things down" semantics
-	 */
-	if (device_power_down(PMSG_PRETHAW))
-		printk(KERN_ERR "Some devices failed to power down, very bad\n");
-	/* We'll ignore saved state, but this gets preempt count (etc) right */
-	save_processor_state();
-	error = restore_highmem();
-	if (!error) {
-		error = swsusp_arch_resume();
-		/* The code below is only ever reached in case of a failure.
-		 * Otherwise execution continues at place where
-		 * swsusp_arch_suspend() was called
-        	 */
-		BUG_ON(!error);
-		/* This call to restore_highmem() undos the previous one */
-		restore_highmem();
-	}
-	/* The only reason why swsusp_arch_resume() can fail is memory being
-	 * very tight, so we have to free it as soon as we can to avoid
-	 * subsequent failures
-	 */
-	swsusp_free();
-	restore_processor_state();
-	touch_softlockup_watchdog();
-	device_power_up();
-	local_irq_enable();
-	return error;
-}
diff --git a/kernel/power/user.c b/kernel/power/user.c
index 5bd321b..f5512cb 100644
--- a/kernel/power/user.c
+++ b/kernel/power/user.c
@@ -28,6 +28,29 @@
 
 #include "power.h"
 
+/*
+ * NOTE: The SNAPSHOT_SET_SWAP_FILE and SNAPSHOT_PMOPS ioctls are obsolete and
+ * will be removed in the future.  They are only preserved here for
+ * compatibility with existing userland utilities.
+ */
+#define SNAPSHOT_SET_SWAP_FILE	_IOW(SNAPSHOT_IOC_MAGIC, 10, unsigned int)
+#define SNAPSHOT_PMOPS		_IOW(SNAPSHOT_IOC_MAGIC, 12, unsigned int)
+
+#define PMOPS_PREPARE	1
+#define PMOPS_ENTER	2
+#define PMOPS_FINISH	3
+
+/*
+ * NOTE: The following ioctl definitions are wrong and have been replaced with
+ * correct ones.  They are only preserved here for compatibility with existing
+ * userland utilities and will be removed in the future.
+ */
+#define SNAPSHOT_ATOMIC_SNAPSHOT	_IOW(SNAPSHOT_IOC_MAGIC, 3, void *)
+#define SNAPSHOT_SET_IMAGE_SIZE		_IOW(SNAPSHOT_IOC_MAGIC, 6, unsigned long)
+#define SNAPSHOT_AVAIL_SWAP		_IOR(SNAPSHOT_IOC_MAGIC, 7, void *)
+#define SNAPSHOT_GET_SWAP_PAGE		_IOR(SNAPSHOT_IOC_MAGIC, 8, void *)
+
+
 #define SNAPSHOT_MINOR	231
 
 static struct snapshot_data {
@@ -36,7 +59,7 @@
 	int mode;
 	char frozen;
 	char ready;
-	char platform_suspend;
+	char platform_support;
 } snapshot_state;
 
 atomic_t snapshot_device_available = ATOMIC_INIT(1);
@@ -44,6 +67,7 @@
 static int snapshot_open(struct inode *inode, struct file *filp)
 {
 	struct snapshot_data *data;
+	int error;
 
 	if (!atomic_add_unless(&snapshot_device_available, -1, 0))
 		return -EBUSY;
@@ -64,13 +88,23 @@
 		data->swap = swsusp_resume_device ?
 			swap_type_of(swsusp_resume_device, 0, NULL) : -1;
 		data->mode = O_RDONLY;
+		error = pm_notifier_call_chain(PM_RESTORE_PREPARE);
+		if (error)
+			pm_notifier_call_chain(PM_POST_RESTORE);
 	} else {
 		data->swap = -1;
 		data->mode = O_WRONLY;
+		error = pm_notifier_call_chain(PM_HIBERNATION_PREPARE);
+		if (error)
+			pm_notifier_call_chain(PM_POST_HIBERNATION);
+	}
+	if (error) {
+		atomic_inc(&snapshot_device_available);
+		return error;
 	}
 	data->frozen = 0;
 	data->ready = 0;
-	data->platform_suspend = 0;
+	data->platform_support = 0;
 
 	return 0;
 }
@@ -88,6 +122,8 @@
 		thaw_processes();
 		mutex_unlock(&pm_mutex);
 	}
+	pm_notifier_call_chain(data->mode == O_WRONLY ?
+			PM_POST_HIBERNATION : PM_POST_RESTORE);
 	atomic_inc(&snapshot_device_available);
 	return 0;
 }
@@ -133,7 +169,7 @@
 {
 	int error = 0;
 	struct snapshot_data *data;
-	loff_t avail;
+	loff_t size;
 	sector_t offset;
 
 	if (_IOC_TYPE(cmd) != SNAPSHOT_IOC_MAGIC)
@@ -151,18 +187,13 @@
 		if (data->frozen)
 			break;
 		mutex_lock(&pm_mutex);
-		error = pm_notifier_call_chain(PM_HIBERNATION_PREPARE);
-		if (!error) {
-			printk("Syncing filesystems ... ");
-			sys_sync();
-			printk("done.\n");
+		printk("Syncing filesystems ... ");
+		sys_sync();
+		printk("done.\n");
 
-			error = freeze_processes();
-			if (error)
-				thaw_processes();
-		}
+		error = freeze_processes();
 		if (error)
-			pm_notifier_call_chain(PM_POST_HIBERNATION);
+			thaw_processes();
 		mutex_unlock(&pm_mutex);
 		if (!error)
 			data->frozen = 1;
@@ -173,19 +204,19 @@
 			break;
 		mutex_lock(&pm_mutex);
 		thaw_processes();
-		pm_notifier_call_chain(PM_POST_HIBERNATION);
 		mutex_unlock(&pm_mutex);
 		data->frozen = 0;
 		break;
 
+	case SNAPSHOT_CREATE_IMAGE:
 	case SNAPSHOT_ATOMIC_SNAPSHOT:
 		if (data->mode != O_RDONLY || !data->frozen  || data->ready) {
 			error = -EPERM;
 			break;
 		}
-		error = hibernation_snapshot(data->platform_suspend);
+		error = hibernation_snapshot(data->platform_support);
 		if (!error)
-			error = put_user(in_suspend, (unsigned int __user *)arg);
+			error = put_user(in_suspend, (int __user *)arg);
 		if (!error)
 			data->ready = 1;
 		break;
@@ -197,7 +228,7 @@
 			error = -EPERM;
 			break;
 		}
-		error = hibernation_restore(data->platform_suspend);
+		error = hibernation_restore(data->platform_support);
 		break;
 
 	case SNAPSHOT_FREE:
@@ -206,16 +237,29 @@
 		data->ready = 0;
 		break;
 
+	case SNAPSHOT_PREF_IMAGE_SIZE:
 	case SNAPSHOT_SET_IMAGE_SIZE:
 		image_size = arg;
 		break;
 
-	case SNAPSHOT_AVAIL_SWAP:
-		avail = count_swap_pages(data->swap, 1);
-		avail <<= PAGE_SHIFT;
-		error = put_user(avail, (loff_t __user *)arg);
+	case SNAPSHOT_GET_IMAGE_SIZE:
+		if (!data->ready) {
+			error = -ENODATA;
+			break;
+		}
+		size = snapshot_get_image_size();
+		size <<= PAGE_SHIFT;
+		error = put_user(size, (loff_t __user *)arg);
 		break;
 
+	case SNAPSHOT_AVAIL_SWAP_SIZE:
+	case SNAPSHOT_AVAIL_SWAP:
+		size = count_swap_pages(data->swap, 1);
+		size <<= PAGE_SHIFT;
+		error = put_user(size, (loff_t __user *)arg);
+		break;
+
+	case SNAPSHOT_ALLOC_SWAP_PAGE:
 	case SNAPSHOT_GET_SWAP_PAGE:
 		if (data->swap < 0 || data->swap >= MAX_SWAPFILES) {
 			error = -ENODEV;
@@ -224,7 +268,7 @@
 		offset = alloc_swapdev_block(data->swap);
 		if (offset) {
 			offset <<= PAGE_SHIFT;
-			error = put_user(offset, (sector_t __user *)arg);
+			error = put_user(offset, (loff_t __user *)arg);
 		} else {
 			error = -ENOSPC;
 		}
@@ -238,7 +282,7 @@
 		free_all_swap_pages(data->swap);
 		break;
 
-	case SNAPSHOT_SET_SWAP_FILE:
+	case SNAPSHOT_SET_SWAP_FILE: /* This ioctl is deprecated */
 		if (!swsusp_swap_in_use()) {
 			/*
 			 * User space encodes device types as two-byte values,
@@ -275,26 +319,33 @@
 		mutex_unlock(&pm_mutex);
 		break;
 
-	case SNAPSHOT_PMOPS:
+	case SNAPSHOT_PLATFORM_SUPPORT:
+		data->platform_support = !!arg;
+		break;
+
+	case SNAPSHOT_POWER_OFF:
+		if (data->platform_support)
+			error = hibernation_platform_enter();
+		break;
+
+	case SNAPSHOT_PMOPS: /* This ioctl is deprecated */
 		error = -EINVAL;
 
 		switch (arg) {
 
 		case PMOPS_PREPARE:
-			data->platform_suspend = 1;
+			data->platform_support = 1;
 			error = 0;
 			break;
 
 		case PMOPS_ENTER:
-			if (data->platform_suspend)
+			if (data->platform_support)
 				error = hibernation_platform_enter();
-
 			break;
 
 		case PMOPS_FINISH:
-			if (data->platform_suspend)
+			if (data->platform_support)
 				error = 0;
-
 			break;
 
 		default:
diff --git a/kernel/softlockup.c b/kernel/softlockup.c
index c1d7655..7c2da88 100644
--- a/kernel/softlockup.c
+++ b/kernel/softlockup.c
@@ -101,6 +101,10 @@
 
 	now = get_timestamp(this_cpu);
 
+	/* Wake up the high-prio watchdog task every second: */
+	if (now > (touch_timestamp + 1))
+		wake_up_process(per_cpu(watchdog_task, this_cpu));
+
 	/* Warn about unreasonable delays: */
 	if (now <= (touch_timestamp + softlockup_thresh))
 		return;
@@ -191,11 +195,11 @@
 	read_lock(&tasklist_lock);
 	do_each_thread(g, t) {
 		if (!--max_count)
-			break;
+			goto unlock;
 		if (t->state & TASK_UNINTERRUPTIBLE)
 			check_hung_task(t, now);
 	} while_each_thread(g, t);
-
+ unlock:
 	read_unlock(&tasklist_lock);
 }
 
@@ -218,14 +222,19 @@
 	 * debug-printout triggers in softlockup_tick().
 	 */
 	while (!kthread_should_stop()) {
+		set_current_state(TASK_INTERRUPTIBLE);
 		touch_softlockup_watchdog();
-		msleep_interruptible(10000);
+		schedule();
+
+		if (kthread_should_stop())
+			break;
 
 		if (this_cpu != check_cpu)
 			continue;
 
 		if (sysctl_hung_task_timeout_secs)
 			check_hung_uninterruptible_tasks(this_cpu);
+
 	}
 
 	return 0;
@@ -259,13 +268,6 @@
 		wake_up_process(per_cpu(watchdog_task, hotcpu));
 		break;
 #ifdef CONFIG_HOTPLUG_CPU
-	case CPU_UP_CANCELED:
-	case CPU_UP_CANCELED_FROZEN:
-		if (!per_cpu(watchdog_task, hotcpu))
-			break;
-		/* Unbind so it can run.  Fall thru. */
-		kthread_bind(per_cpu(watchdog_task, hotcpu),
-			     any_online_cpu(cpu_online_map));
 	case CPU_DOWN_PREPARE:
 	case CPU_DOWN_PREPARE_FROZEN:
 		if (hotcpu == check_cpu) {
@@ -275,6 +277,14 @@
 			check_cpu = any_online_cpu(temp_cpu_online_map);
 		}
 		break;
+
+	case CPU_UP_CANCELED:
+	case CPU_UP_CANCELED_FROZEN:
+		if (!per_cpu(watchdog_task, hotcpu))
+			break;
+		/* Unbind so it can run.  Fall thru. */
+		kthread_bind(per_cpu(watchdog_task, hotcpu),
+			     any_online_cpu(cpu_online_map));
 	case CPU_DEAD:
 	case CPU_DEAD_FROZEN:
 		p = per_cpu(watchdog_task, hotcpu);
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 357b68b..7cb1ac3 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -81,7 +81,6 @@
 extern int compat_log;
 extern int maps_protect;
 extern int sysctl_stat_interval;
-extern int audit_argv_kb;
 extern int latencytop_enabled;
 
 /* Constants used for minimum and  maximum */
@@ -390,16 +389,6 @@
 		.mode		= 0644,
 		.proc_handler	= &proc_dointvec,
 	},
-#ifdef CONFIG_AUDITSYSCALL
-	{
-		.ctl_name	= CTL_UNNUMBERED,
-		.procname	= "audit_argv_kb",
-		.data		= &audit_argv_kb,
-		.maxlen		= sizeof(int),
-		.mode		= 0644,
-		.proc_handler	= &proc_dointvec,
-	},
-#endif
 	{
 		.ctl_name	= KERN_CORE_PATTERN,
 		.procname	= "core_pattern",
diff --git a/kernel/time.c b/kernel/time.c
index 09d3c45..4064c05 100644
--- a/kernel/time.c
+++ b/kernel/time.c
@@ -129,6 +129,7 @@
 	write_seqlock_irq(&xtime_lock);
 	wall_to_monotonic.tv_sec -= sys_tz.tz_minuteswest * 60;
 	xtime.tv_sec += sys_tz.tz_minuteswest * 60;
+	update_xtime_cache(0);
 	write_sequnlock_irq(&xtime_lock);
 	clock_was_set();
 }
diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c
index 63f24b5..88267f0 100644
--- a/kernel/time/tick-sched.c
+++ b/kernel/time/tick-sched.c
@@ -137,6 +137,7 @@
 
 	cpu_clear(cpu, nohz_cpu_mask);
 	now = ktime_get();
+	ts->idle_waketime = now;
 
 	local_irq_save(flags);
 	tick_do_update_jiffies64(now);
@@ -400,6 +401,7 @@
 	 * Cancel the scheduled timer and restore the tick
 	 */
 	ts->tick_stopped  = 0;
+	ts->idle_exittime = now;
 	hrtimer_cancel(&ts->sched_timer);
 	ts->sched_timer.expires = ts->idle_tick;
 
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c
index 092a236..cd5dbc4 100644
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
@@ -47,7 +47,7 @@
 static unsigned long total_sleep_time;		/* seconds */
 
 static struct timespec xtime_cache __attribute__ ((aligned (16)));
-static inline void update_xtime_cache(u64 nsec)
+void update_xtime_cache(u64 nsec)
 {
 	xtime_cache = xtime;
 	timespec_add_ns(&xtime_cache, nsec);
@@ -145,6 +145,7 @@
 
 	set_normalized_timespec(&xtime, sec, nsec);
 	set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
+	update_xtime_cache(0);
 
 	clock->error = 0;
 	ntp_clear();
@@ -252,8 +253,8 @@
 	xtime.tv_nsec = 0;
 	set_normalized_timespec(&wall_to_monotonic,
 		-xtime.tv_sec, -xtime.tv_nsec);
+	update_xtime_cache(0);
 	total_sleep_time = 0;
-
 	write_sequnlock_irqrestore(&xtime_lock, flags);
 }
 
@@ -290,6 +291,7 @@
 	}
 	/* Make sure that we have the correct xtime reference */
 	timespec_add_ns(&xtime, timekeeping_suspend_nsecs);
+	update_xtime_cache(0);
 	/* re-base the last cycle value */
 	clock->cycle_last = clocksource_read(clock);
 	clock->error = 0;
diff --git a/kernel/time/timer_list.c b/kernel/time/timer_list.c
index 12c5f4c..d3d94c1 100644
--- a/kernel/time/timer_list.c
+++ b/kernel/time/timer_list.c
@@ -166,6 +166,8 @@
 		P(idle_calls);
 		P(idle_sleeps);
 		P_ns(idle_entrytime);
+		P_ns(idle_waketime);
+		P_ns(idle_exittime);
 		P_ns(idle_sleeptime);
 		P(last_jiffies);
 		P(next_jiffies);
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index 89f4035b..0d8a5a4 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -581,7 +581,7 @@
 	select STACKTRACE
 	select SCHEDSTATS
 	select SCHED_DEBUG
-	depends on X86 || X86_64
+	depends on HAVE_LATENCYTOP_SUPPORT
 	help
 	  Enable this option if you want to use the LatencyTOP tool
 	  to find out which userspace is blocking on what kernel operations.
diff --git a/net/core/dev.c b/net/core/dev.c
index edaff27..9549417 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -2752,12 +2752,15 @@
 		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 (audit_enabled)
+			audit_log(current->audit_context, GFP_ATOMIC,
+				AUDIT_ANOM_PROMISCUOUS,
+				"dev=%s prom=%d old_prom=%d auid=%u uid=%u gid=%u ses=%u",
+				dev->name, (dev->flags & IFF_PROMISC),
+				(old_flags & IFF_PROMISC),
+				audit_get_loginuid(current),
+				current->uid, current->gid,
+				audit_get_sessionid(current));
 
 		if (dev->change_rx_flags)
 			dev->change_rx_flags(dev, IFF_PROMISC);
diff --git a/net/key/af_key.c b/net/key/af_key.c
index 16b72b5..45c3c27 100644
--- a/net/key/af_key.c
+++ b/net/key/af_key.c
@@ -1466,7 +1466,7 @@
 		err = xfrm_state_update(x);
 
 	xfrm_audit_state_add(x, err ? 0 : 1,
-			     audit_get_loginuid(current->audit_context), 0);
+			     audit_get_loginuid(current), 0);
 
 	if (err < 0) {
 		x->km.state = XFRM_STATE_DEAD;
@@ -1520,7 +1520,7 @@
 	km_state_notify(x, &c);
 out:
 	xfrm_audit_state_delete(x, err ? 0 : 1,
-			       audit_get_loginuid(current->audit_context), 0);
+			       audit_get_loginuid(current), 0);
 	xfrm_state_put(x);
 
 	return err;
@@ -1695,7 +1695,7 @@
 	if (proto == 0)
 		return -EINVAL;
 
-	audit_info.loginuid = audit_get_loginuid(current->audit_context);
+	audit_info.loginuid = audit_get_loginuid(current);
 	audit_info.secid = 0;
 	err = xfrm_state_flush(proto, &audit_info);
 	if (err)
@@ -2273,7 +2273,7 @@
 				 hdr->sadb_msg_type != SADB_X_SPDUPDATE);
 
 	xfrm_audit_policy_add(xp, err ? 0 : 1,
-			     audit_get_loginuid(current->audit_context), 0);
+			     audit_get_loginuid(current), 0);
 
 	if (err)
 		goto out;
@@ -2356,7 +2356,7 @@
 		return -ENOENT;
 
 	xfrm_audit_policy_delete(xp, err ? 0 : 1,
-				audit_get_loginuid(current->audit_context), 0);
+				audit_get_loginuid(current), 0);
 
 	if (err)
 		goto out;
@@ -2617,7 +2617,7 @@
 
 	if (delete) {
 		xfrm_audit_policy_delete(xp, err ? 0 : 1,
-				audit_get_loginuid(current->audit_context), 0);
+				audit_get_loginuid(current), 0);
 
 		if (err)
 			goto out;
@@ -2694,7 +2694,7 @@
 	struct xfrm_audit audit_info;
 	int err;
 
-	audit_info.loginuid = audit_get_loginuid(current->audit_context);
+	audit_info.loginuid = audit_get_loginuid(current);
 	audit_info.secid = 0;
 	err = xfrm_policy_flush(XFRM_POLICY_TYPE_MAIN, &audit_info);
 	if (err)
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index ff9fb6b..1ab0da2 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -1238,7 +1238,7 @@
 
 	NETLINK_CB(skb).pid	= nlk->pid;
 	NETLINK_CB(skb).dst_group = dst_group;
-	NETLINK_CB(skb).loginuid = audit_get_loginuid(current->audit_context);
+	NETLINK_CB(skb).loginuid = audit_get_loginuid(current);
 	selinux_get_task_sid(current, &(NETLINK_CB(skb).sid));
 	memcpy(NETLINK_CREDS(skb), &siocb->scm->creds, sizeof(struct ucred));
 
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index 3ff76e8..7ba65e8 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -493,7 +493,7 @@
 		km_state_expired(x, 1, 0);
 
 	xfrm_audit_state_delete(x, err ? 0 : 1,
-				audit_get_loginuid(current->audit_context), 0);
+				audit_get_loginuid(current), 0);
 
 out:
 	spin_unlock(&x->lock);
diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c
index d802b5a..9ddf944 100644
--- a/scripts/mod/file2alias.c
+++ b/scripts/mod/file2alias.c
@@ -155,7 +155,7 @@
 	 * Some modules (visor) have empty slots as placeholder for
 	 * run-time specification that results in catch-all alias
 	 */
-	if (!(id->idVendor | id->bDeviceClass | id->bInterfaceClass))
+	if (!(id->idVendor | id->idProduct | id->bDeviceClass | id->bInterfaceClass))
 		return;
 
 	/* Convert numeric bcdDevice range into fnmatch-able pattern(s) */
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
index a857405..0341567 100644
--- a/security/selinux/selinuxfs.c
+++ b/security/selinux/selinuxfs.c
@@ -172,9 +172,10 @@
 		if (length)
 			goto out;
 		audit_log(current->audit_context, GFP_KERNEL, AUDIT_MAC_STATUS,
-			"enforcing=%d old_enforcing=%d auid=%u", new_value, 
-			selinux_enforcing,
-			audit_get_loginuid(current->audit_context));
+			"enforcing=%d old_enforcing=%d auid=%u ses=%u",
+			new_value, selinux_enforcing,
+			audit_get_loginuid(current),
+			audit_get_sessionid(current));
 		selinux_enforcing = new_value;
 		if (selinux_enforcing)
 			avc_ss_reset(0);
@@ -243,8 +244,9 @@
 		if (length < 0)
 			goto out;
 		audit_log(current->audit_context, GFP_KERNEL, AUDIT_MAC_STATUS,
-			"selinux=0 auid=%u",
-			audit_get_loginuid(current->audit_context));
+			"selinux=0 auid=%u ses=%u",
+			audit_get_loginuid(current),
+			audit_get_sessionid(current));
 	}
 
 	length = count;
@@ -356,8 +358,9 @@
 		(security_get_allow_unknown() ? "allow" : "deny")));
 
 	audit_log(current->audit_context, GFP_KERNEL, AUDIT_MAC_POLICY_LOAD,
-		"policy loaded auid=%u",
-		audit_get_loginuid(current->audit_context));
+		"policy loaded auid=%u ses=%u",
+		audit_get_loginuid(current),
+		audit_get_sessionid(current));
 out:
 	mutex_unlock(&sel_mutex);
 	vfree(data);
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index 880d455..fced6bc 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -1905,11 +1905,12 @@
 		if (!!values[i] != policydb.bool_val_to_struct[i]->state) {
 			audit_log(current->audit_context, GFP_ATOMIC,
 				AUDIT_MAC_CONFIG_CHANGE,
-				"bool=%s val=%d old_val=%d auid=%u",
+				"bool=%s val=%d old_val=%d auid=%u ses=%u",
 				policydb.p_bool_val_to_name[i],
 				!!values[i],
 				policydb.bool_val_to_struct[i]->state,
-				audit_get_loginuid(current->audit_context));
+				audit_get_loginuid(current),
+				audit_get_sessionid(current));
 		}
 		if (values[i]) {
 			policydb.bool_val_to_struct[i]->state = 1;