Merge tag 'iio-for-3.15c' of git://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio into staging-next

Jonathan writes:

Third IIO new drivers and cleanups series for 3.15.

New driver
* Xilinx XADC driver -  This has been ready for a while but was awaiting
  a device tree ack (or as it turns out 3+ weeks).

Cleanup
* Drop some unreachable code from mag3110 highlighted by smatch.

Fix
* vf610 - introduced this cycle - put a possible negative error code
  into an unsigned long. Another smatch find - this one promoted by
  guilt that Dan was busy fixing all our messups.
diff --git a/Documentation/ABI/testing/sysfs-tty b/Documentation/ABI/testing/sysfs-tty
index a2ccec3..ad22fb0 100644
--- a/Documentation/ABI/testing/sysfs-tty
+++ b/Documentation/ABI/testing/sysfs-tty
@@ -3,8 +3,7 @@
 Contact:	Kay Sievers <kay.sievers@vrfy.org>
 Description:
 		 Shows the list of currently configured
-		 tty devices used for the console,
-		 like 'tty1 ttyS0'.
+		 console devices, like 'tty1 ttyS0'.
 		 The last entry in the file is the active
 		 device connected to /dev/console.
 		 The file supports poll() to detect virtual
diff --git a/Documentation/PCI/MSI-HOWTO.txt b/Documentation/PCI/MSI-HOWTO.txt
index a8d0100..10a9369 100644
--- a/Documentation/PCI/MSI-HOWTO.txt
+++ b/Documentation/PCI/MSI-HOWTO.txt
@@ -82,7 +82,19 @@
 has to request that the PCI layer set up the MSI capability for this
 device.
 
-4.2.1 pci_enable_msi_range
+4.2.1 pci_enable_msi
+
+int pci_enable_msi(struct pci_dev *dev)
+
+A successful call allocates ONE interrupt to the device, regardless
+of how many MSIs the device supports.  The device is switched from
+pin-based interrupt mode to MSI mode.  The dev->irq number is changed
+to a new number which represents the message signaled interrupt;
+consequently, this function should be called before the driver calls
+request_irq(), because an MSI is delivered via a vector that is
+different from the vector of a pin-based interrupt.
+
+4.2.2 pci_enable_msi_range
 
 int pci_enable_msi_range(struct pci_dev *dev, int minvec, int maxvec)
 
@@ -147,6 +159,11 @@
 	return pci_enable_msi_range(pdev, nvec, nvec);
 }
 
+Note, unlike pci_enable_msi_exact() function, which could be also used to
+enable a particular number of MSI-X interrupts, pci_enable_msi_range()
+returns either a negative errno or 'nvec' (not negative errno or 0 - as
+pci_enable_msi_exact() does).
+
 4.2.1.3 Single MSI mode
 
 The most notorious example of the request type described above is
@@ -158,7 +175,27 @@
 	return pci_enable_msi_range(pdev, 1, 1);
 }
 
-4.2.2 pci_disable_msi
+Note, unlike pci_enable_msi() function, which could be also used to
+enable the single MSI mode, pci_enable_msi_range() returns either a
+negative errno or 1 (not negative errno or 0 - as pci_enable_msi()
+does).
+
+4.2.3 pci_enable_msi_exact
+
+int pci_enable_msi_exact(struct pci_dev *dev, int nvec)
+
+This variation on pci_enable_msi_range() call allows a device driver to
+request exactly 'nvec' MSIs.
+
+If this function returns a negative number, it indicates an error and
+the driver should not attempt to request any more MSI interrupts for
+this device.
+
+By contrast with pci_enable_msi_range() function, pci_enable_msi_exact()
+returns zero in case of success, which indicates MSI interrupts have been
+successfully allocated.
+
+4.2.4 pci_disable_msi
 
 void pci_disable_msi(struct pci_dev *dev)
 
@@ -172,7 +209,7 @@
 Failure to do so results in a BUG_ON(), leaving the device with
 MSI enabled and thus leaking its vector.
 
-4.2.3 pci_msi_vec_count
+4.2.4 pci_msi_vec_count
 
 int pci_msi_vec_count(struct pci_dev *dev)
 
@@ -257,8 +294,8 @@
 
 static int foo_driver_enable_msix(struct foo_adapter *adapter, int nvec)
 {
-	return pci_enable_msi_range(adapter->pdev, adapter->msix_entries,
-				    1, nvec);
+	return pci_enable_msix_range(adapter->pdev, adapter->msix_entries,
+				     1, nvec);
 }
 
 Note the value of 'minvec' parameter is 1.  As 'minvec' is inclusive,
@@ -269,8 +306,8 @@
 
 static int foo_driver_enable_msix(struct foo_adapter *adapter, int nvec)
 {
-	return pci_enable_msi_range(adapter->pdev, adapter->msix_entries,
-				    FOO_DRIVER_MINIMUM_NVEC, nvec);
+	return pci_enable_msix_range(adapter->pdev, adapter->msix_entries,
+				     FOO_DRIVER_MINIMUM_NVEC, nvec);
 }
 
 4.3.1.2 Exact number of MSI-X interrupts
@@ -282,10 +319,15 @@
 
 static int foo_driver_enable_msix(struct foo_adapter *adapter, int nvec)
 {
-	return pci_enable_msi_range(adapter->pdev, adapter->msix_entries,
-				    nvec, nvec);
+	return pci_enable_msix_range(adapter->pdev, adapter->msix_entries,
+				     nvec, nvec);
 }
 
+Note, unlike pci_enable_msix_exact() function, which could be also used to
+enable a particular number of MSI-X interrupts, pci_enable_msix_range()
+returns either a negative errno or 'nvec' (not negative errno or 0 - as
+pci_enable_msix_exact() does).
+
 4.3.1.3 Specific requirements to the number of MSI-X interrupts
 
 As noted above, there could be devices that can not operate with just any
@@ -332,7 +374,64 @@
 any error code other than -ENOSPC indicates a fatal error and should not
 be retried.
 
-4.3.2 pci_disable_msix
+4.3.2 pci_enable_msix_exact
+
+int pci_enable_msix_exact(struct pci_dev *dev,
+			  struct msix_entry *entries, int nvec)
+
+This variation on pci_enable_msix_range() call allows a device driver to
+request exactly 'nvec' MSI-Xs.
+
+If this function returns a negative number, it indicates an error and
+the driver should not attempt to allocate any more MSI-X interrupts for
+this device.
+
+By contrast with pci_enable_msix_range() function, pci_enable_msix_exact()
+returns zero in case of success, which indicates MSI-X interrupts have been
+successfully allocated.
+
+Another version of a routine that enables MSI-X mode for a device with
+specific requirements described in chapter 4.3.1.3 might look like this:
+
+/*
+ * Assume 'minvec' and 'maxvec' are non-zero
+ */
+static int foo_driver_enable_msix(struct foo_adapter *adapter,
+				  int minvec, int maxvec)
+{
+	int rc;
+
+	minvec = roundup_pow_of_two(minvec);
+	maxvec = rounddown_pow_of_two(maxvec);
+
+	if (minvec > maxvec)
+		return -ERANGE;
+
+retry:
+	rc = pci_enable_msix_exact(adapter->pdev,
+				   adapter->msix_entries, maxvec);
+
+	/*
+	 * -ENOSPC is the only error code allowed to be analyzed
+	 */
+	if (rc == -ENOSPC) {
+		if (maxvec == 1)
+			return -ENOSPC;
+
+		maxvec /= 2;
+
+		if (minvec > maxvec)
+			return -ENOSPC;
+
+		goto retry;
+	} else if (rc < 0) {
+		return rc;
+	}
+
+	return maxvec;
+}
+
+4.3.3 pci_disable_msix
 
 void pci_disable_msix(struct pci_dev *dev)
 
diff --git a/Documentation/devicetree/bindings/arm/omap/omap.txt b/Documentation/devicetree/bindings/arm/omap/omap.txt
index 34dc40c..af9b4a0 100644
--- a/Documentation/devicetree/bindings/arm/omap/omap.txt
+++ b/Documentation/devicetree/bindings/arm/omap/omap.txt
@@ -91,7 +91,7 @@
   compatible = "ti,omap3-beagle", "ti,omap3"
 
 - OMAP3 Tobi with Overo : Commercial expansion board with daughter board
-  compatible = "ti,omap3-tobi", "ti,omap3-overo", "ti,omap3"
+  compatible = "gumstix,omap3-overo-tobi", "gumstix,omap3-overo", "ti,omap3"
 
 - OMAP4 SDP : Software Development Board
   compatible = "ti,omap4-sdp", "ti,omap4430"
diff --git a/Documentation/devicetree/bindings/dma/fsl-imx-sdma.txt b/Documentation/devicetree/bindings/dma/fsl-imx-sdma.txt
index 68b83ec..ee9be99 100644
--- a/Documentation/devicetree/bindings/dma/fsl-imx-sdma.txt
+++ b/Documentation/devicetree/bindings/dma/fsl-imx-sdma.txt
@@ -1,12 +1,16 @@
 * Freescale Smart Direct Memory Access (SDMA) Controller for i.MX
 
 Required properties:
-- compatible : Should be "fsl,imx31-sdma", "fsl,imx31-to1-sdma",
-  "fsl,imx31-to2-sdma", "fsl,imx35-sdma", "fsl,imx35-to1-sdma",
-  "fsl,imx35-to2-sdma", "fsl,imx51-sdma", "fsl,imx53-sdma" or
-  "fsl,imx6q-sdma". The -to variants should be preferred since they
-  allow to determnine the correct ROM script addresses needed for
-  the driver to work without additional firmware.
+- compatible : Should be one of
+      "fsl,imx25-sdma"
+      "fsl,imx31-sdma", "fsl,imx31-to1-sdma", "fsl,imx31-to2-sdma"
+      "fsl,imx35-sdma", "fsl,imx35-to1-sdma", "fsl,imx35-to2-sdma"
+      "fsl,imx51-sdma"
+      "fsl,imx53-sdma"
+      "fsl,imx6q-sdma"
+  The -to variants should be preferred since they allow to determnine the
+  correct ROM script addresses needed for the driver to work without additional
+  firmware.
 - reg : Should contain SDMA registers location and length
 - interrupts : Should contain SDMA interrupt
 - #dma-cells : Must be <3>.
diff --git a/Documentation/devicetree/bindings/net/sti-dwmac.txt b/Documentation/devicetree/bindings/net/sti-dwmac.txt
new file mode 100644
index 0000000..3dd3d0b
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/sti-dwmac.txt
@@ -0,0 +1,58 @@
+STMicroelectronics SoC DWMAC glue layer controller
+
+The device node has following properties.
+
+Required properties:
+ - compatible	: Can be "st,stih415-dwmac", "st,stih416-dwmac" or
+   "st,stid127-dwmac".
+ - reg		: Offset of the glue configuration register map in system
+   configuration regmap pointed by st,syscon property and size.
+
+ - reg-names	: Should be "sti-ethconf".
+
+ - st,syscon	: Should be phandle to system configuration node which
+   encompases this glue registers.
+
+ - st,tx-retime-src: On STi Parts for Giga bit speeds, 125Mhz clocks can be
+   wired up in from different sources. One via TXCLK pin and other via CLK_125
+   pin. This wiring is totally board dependent. However the retiming glue
+   logic should be configured accordingly. Possible values for this property
+
+	   "txclk" - if 125Mhz clock is wired up via txclk line.
+	   "clk_125" - if 125Mhz clock is wired up via clk_125 line.
+
+   This property is only valid for Giga bit setup( GMII, RGMII), and it is
+   un-used for non-giga bit (MII and RMII) setups. Also note that internal
+   clockgen can not generate stable 125Mhz clock.
+
+ - st,ext-phyclk: This boolean property indicates who is generating the clock
+  for tx and rx. This property is only valid for RMII case where the clock can
+  be generated from the MAC or PHY.
+
+ - clock-names: should be "sti-ethclk".
+ - clocks: Should point to ethernet clockgen which can generate phyclk.
+
+
+Example:
+
+ethernet0: dwmac@fe810000 {
+	device_type 	= "network";
+	compatible	= "st,stih416-dwmac", "snps,dwmac", "snps,dwmac-3.710";
+	reg 		= <0xfe810000 0x8000>, <0x8bc 0x4>;
+	reg-names	= "stmmaceth", "sti-ethconf";
+	interrupts	= <0 133 0>, <0 134 0>, <0 135 0>;
+	interrupt-names	= "macirq", "eth_wake_irq", "eth_lpi";
+	phy-mode	= "mii";
+
+	st,syscon	= <&syscfg_rear>;
+
+	snps,pbl 	= <32>;
+	snps,mixed-burst;
+
+	resets		= <&softreset STIH416_ETH0_SOFTRESET>;
+	reset-names	= "stmmaceth";
+	pinctrl-0	= <&pinctrl_mii0>;
+	pinctrl-names 	= "default";
+	clocks		= <&CLK_S_GMAC0_PHY>;
+	clock-names	= "stmmaceth";
+};
diff --git a/Documentation/networking/3c505.txt b/Documentation/networking/3c505.txt
deleted file mode 100644
index 72f38b1..0000000
--- a/Documentation/networking/3c505.txt
+++ /dev/null
@@ -1,45 +0,0 @@
-The 3Com Etherlink Plus (3c505) driver.
-
-This driver now uses DMA.  There is currently no support for PIO operation.
-The default DMA channel is 6; this is _not_ autoprobed, so you must
-make sure you configure it correctly.  If loading the driver as a
-module, you can do this with "modprobe 3c505 dma=n".  If the driver is
-linked statically into the kernel, you must either use an "ether="
-statement on the command line, or change the definition of ELP_DMA in 3c505.h.
-
-The driver will warn you if it has to fall back on the compiled in
-default DMA channel. 
-
-If no base address is given at boot time, the driver will autoprobe
-ports 0x300, 0x280 and 0x310 (in that order).  If no IRQ is given, the driver
-will try to probe for it.
-
-The driver can be used as a loadable module.
-
-Theoretically, one instance of the driver can now run multiple cards,
-in the standard way (when loading a module, say "modprobe 3c505
-io=0x300,0x340 irq=10,11 dma=6,7" or whatever).  I have not tested
-this, though.
-
-The driver may now support revision 2 hardware; the dependency on
-being able to read the host control register has been removed.  This
-is also untested, since I don't have a suitable card.
-
-Known problems:
- I still see "DMA upload timed out" messages from time to time.  These
-seem to be fairly non-fatal though.
- The card is old and slow.
-
-To do:
- Improve probe/setup code
- Test multicast and promiscuous operation
-
-Authors:
- The driver is mainly written by Craig Southeren, email
- <craigs@ineluki.apana.org.au>.
- Parts of the driver (adapting the driver to 1.1.4+ kernels,
- IRQ/address detection, some changes) and this README by
- Juha Laiho <jlaiho@ichaos.nullnet.fi>.
- DMA mode, more fixes, etc, by Philip Blundell <pjb27@cam.ac.uk>
- Multicard support, Software configurable DMA, etc., by
- Christopher Collins <ccollins@pcug.org.au>
diff --git a/MAINTAINERS b/MAINTAINERS
index 9e484c0..c3ff623 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -538,7 +538,7 @@
 ALTERA UART/JTAG UART SERIAL DRIVERS
 M:	Tobias Klauser <tklauser@distanz.ch>
 L:	linux-serial@vger.kernel.org
-L:	nios2-dev@sopc.et.ntust.edu.tw (moderated for non-subscribers)
+L:	nios2-dev@lists.rocketboards.org (moderated for non-subscribers)
 S:	Maintained
 F:	drivers/tty/serial/altera_uart.c
 F:	drivers/tty/serial/altera_jtaguart.c
@@ -1860,6 +1860,7 @@
 
 BROADCOM BCM281XX/BCM11XXX ARM ARCHITECTURE
 M:	Christian Daudt <bcm@fixthebug.org>
+M:	Matt Porter <mporter@linaro.org>
 L:	bcm-kernel-feedback-list@broadcom.com
 T:	git git://git.github.com/broadcom/bcm11351
 S:	Maintained
@@ -2408,8 +2409,10 @@
 
 CPUSETS
 M:	Li Zefan <lizefan@huawei.com>
+L:	cgroups@vger.kernel.org
 W:	http://www.bullopensource.org/cpuset/
 W:	http://oss.sgi.com/projects/cpusets/
+T:	git git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup.git
 S:	Maintained
 F:	Documentation/cgroups/cpusets.txt
 F:	include/linux/cpuset.h
@@ -2608,9 +2611,9 @@
 M:	Oliver Neukum <oliver@neukum.org>
 M:	Ali Akcaagac <aliakc@web.de>
 M:	Jamie Lenehan <lenehan@twibble.org>
-W:	http://twibble.org/dist/dc395x/
 L:	dc395x@twibble.org
-L:	http://lists.twibble.org/mailman/listinfo/dc395x/
+W:	http://twibble.org/dist/dc395x/
+W:	http://lists.twibble.org/mailman/listinfo/dc395x/
 S:	Maintained
 F:	Documentation/scsi/dc395x.txt
 F:	drivers/scsi/dc395x.*
@@ -2845,12 +2848,22 @@
 DRM DRIVERS
 M:	David Airlie <airlied@linux.ie>
 L:	dri-devel@lists.freedesktop.org
-T:	git git://git.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6.git
+T:	git git://people.freedesktop.org/~airlied/linux
 S:	Maintained
 F:	drivers/gpu/drm/
 F:	include/drm/
 F:	include/uapi/drm/
 
+RADEON DRM DRIVERS
+M:	Alex Deucher <alexander.deucher@amd.com>
+M:	Christian König <christian.koenig@amd.com>
+L:	dri-devel@lists.freedesktop.org
+T:	git git://people.freedesktop.org/~agd5f/linux
+S:	Supported
+F:	drivers/gpu/drm/radeon/
+F:	include/drm/radeon*
+F:	include/uapi/drm/radeon*
+
 INTEL DRM DRIVERS (excluding Poulsbo, Moorestown and derivative chipsets)
 M:	Daniel Vetter <daniel.vetter@ffwll.ch>
 M:	Jani Nikula <jani.nikula@linux.intel.com>
@@ -3324,6 +3337,17 @@
 F:	include/linux/netfilter_bridge/
 F:	net/bridge/
 
+ETHERNET PHY LIBRARY
+M:	Florian Fainelli <f.fainelli@gmail.com>
+L:	netdev@vger.kernel.org
+S:	Maintained
+F:	include/linux/phy.h
+F:	include/linux/phy_fixed.h
+F:	drivers/net/phy/
+F:	Documentation/networking/phy.txt
+F:	drivers/of/of_mdio.c
+F:	drivers/of/of_net.c
+
 EXT2 FILE SYSTEM
 M:	Jan Kara <jack@suse.cz>
 L:	linux-ext4@vger.kernel.org
@@ -5487,6 +5511,11 @@
 L:	linux-man@vger.kernel.org
 S:	Maintained
 
+MARVELL ARMADA DRM SUPPORT
+M:	Russell King <rmk+kernel@arm.linux.org.uk>
+S:	Maintained
+F:	drivers/gpu/drm/armada/
+
 MARVELL GIGABIT ETHERNET DRIVERS (skge/sky2)
 M:	Mirko Lindner <mlindner@marvell.com>
 M:	Stephen Hemminger <stephen@networkplumber.org>
@@ -8435,8 +8464,8 @@
 M:	Nicholas A. Bellinger <nab@linux-iscsi.org>
 L:	linux-scsi@vger.kernel.org
 L:	target-devel@vger.kernel.org
-L:	http://groups.google.com/group/linux-iscsi-target-dev
 W:	http://www.linux-iscsi.org
+W:	http://groups.google.com/group/linux-iscsi-target-dev
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending.git master
 S:	Supported
 F:	drivers/target/
@@ -9721,7 +9750,6 @@
 XFS FILESYSTEM
 P:	Silicon Graphics Inc
 M:	Dave Chinner <david@fromorbit.com>
-M:	Ben Myers <bpm@sgi.com>
 M:	xfs@oss.sgi.com
 L:	xfs@oss.sgi.com
 W:	http://oss.sgi.com/projects/xfs
diff --git a/Makefile b/Makefile
index 893d6f0e..78209ee 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 3
 PATCHLEVEL = 14
 SUBLEVEL = 0
-EXTRAVERSION = -rc3
+EXTRAVERSION = -rc5
 NAME = Shuffling Zombie Juror
 
 # *DOCUMENTATION*
@@ -605,10 +605,11 @@
 ifdef CONFIG_CC_STACKPROTECTOR_REGULAR
   stackp-flag := -fstack-protector
   ifeq ($(call cc-option, $(stackp-flag)),)
-    $(warning Cannot use CONFIG_CC_STACKPROTECTOR: \
-	      -fstack-protector not supported by compiler))
+    $(warning Cannot use CONFIG_CC_STACKPROTECTOR_REGULAR: \
+             -fstack-protector not supported by compiler)
   endif
-else ifdef CONFIG_CC_STACKPROTECTOR_STRONG
+else
+ifdef CONFIG_CC_STACKPROTECTOR_STRONG
   stackp-flag := -fstack-protector-strong
   ifeq ($(call cc-option, $(stackp-flag)),)
     $(warning Cannot use CONFIG_CC_STACKPROTECTOR_STRONG: \
@@ -618,6 +619,7 @@
   # Force off for distro compilers that enable stack protector by default.
   stackp-flag := $(call cc-option, -fno-stack-protector)
 endif
+endif
 KBUILD_CFLAGS += $(stackp-flag)
 
 # This warning generated too much noise in a regular build.
diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index 6d1e43d..0320303 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -209,7 +209,8 @@
 	omap3-n900.dtb \
 	omap3-n9.dtb \
 	omap3-n950.dtb \
-	omap3-tobi.dtb \
+	omap3-overo-tobi.dtb \
+	omap3-overo-storm-tobi.dtb \
 	omap3-gta04.dtb \
 	omap3-igep0020.dtb \
 	omap3-igep0030.dtb \
diff --git a/arch/arm/boot/dts/am335x-evmsk.dts b/arch/arm/boot/dts/am335x-evmsk.dts
index 4718ec4..486880b 100644
--- a/arch/arm/boot/dts/am335x-evmsk.dts
+++ b/arch/arm/boot/dts/am335x-evmsk.dts
@@ -121,7 +121,7 @@
 		ti,model = "AM335x-EVMSK";
 		ti,audio-codec = <&tlv320aic3106>;
 		ti,mcasp-controller = <&mcasp1>;
-		ti,codec-clock-rate = <24576000>;
+		ti,codec-clock-rate = <24000000>;
 		ti,audio-routing =
 			"Headphone Jack",       "HPLOUT",
 			"Headphone Jack",       "HPROUT";
@@ -256,6 +256,12 @@
 		>;
 	};
 
+	mmc1_pins: pinmux_mmc1_pins {
+		pinctrl-single,pins = <
+			0x160 (PIN_INPUT | MUX_MODE7) /* spi0_cs1.gpio0_6 */
+		>;
+	};
+
 	mcasp1_pins: mcasp1_pins {
 		pinctrl-single,pins = <
 			0x10c (PIN_INPUT_PULLDOWN | MUX_MODE4) /* mii1_crs.mcasp1_aclkx */
@@ -456,6 +462,9 @@
 	status = "okay";
 	vmmc-supply = <&vmmc_reg>;
 	bus-width = <4>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&mmc1_pins>;
+	cd-gpios = <&gpio0 6 GPIO_ACTIVE_HIGH>;
 };
 
 &sham {
diff --git a/arch/arm/boot/dts/armada-xp-mv78260.dtsi b/arch/arm/boot/dts/armada-xp-mv78260.dtsi
index 6660968..9480cf8 100644
--- a/arch/arm/boot/dts/armada-xp-mv78260.dtsi
+++ b/arch/arm/boot/dts/armada-xp-mv78260.dtsi
@@ -23,6 +23,7 @@
 		gpio0 = &gpio0;
 		gpio1 = &gpio1;
 		gpio2 = &gpio2;
+		eth3 = &eth3;
 	};
 
 	cpus {
@@ -291,7 +292,7 @@
 				interrupts = <91>;
 			};
 
-			ethernet@34000 {
+			eth3: ethernet@34000 {
 				compatible = "marvell,armada-370-neta";
 				reg = <0x34000 0x4000>;
 				interrupts = <14>;
diff --git a/arch/arm/boot/dts/dove.dtsi b/arch/arm/boot/dts/dove.dtsi
index 2b76524..187fd46 100644
--- a/arch/arm/boot/dts/dove.dtsi
+++ b/arch/arm/boot/dts/dove.dtsi
@@ -379,15 +379,6 @@
 				#clock-cells = <1>;
 			};
 
-			pmu_intc: pmu-interrupt-ctrl@d0050 {
-				compatible = "marvell,dove-pmu-intc";
-				interrupt-controller;
-				#interrupt-cells = <1>;
-				reg = <0xd0050 0x8>;
-				interrupts = <33>;
-				marvell,#interrupts = <7>;
-			};
-
 			pinctrl: pin-ctrl@d0200 {
 				compatible = "marvell,dove-pinctrl";
 				reg = <0xd0200 0x10>;
@@ -610,8 +601,6 @@
 			rtc: real-time-clock@d8500 {
 				compatible = "marvell,orion-rtc";
 				reg = <0xd8500 0x20>;
-				interrupt-parent = <&pmu_intc>;
-				interrupts = <5>;
 			};
 
 			gpio2: gpio-ctrl@e8400 {
diff --git a/arch/arm/boot/dts/imx51-babbage.dts b/arch/arm/boot/dts/imx51-babbage.dts
index be1407c..6ff15a0 100644
--- a/arch/arm/boot/dts/imx51-babbage.dts
+++ b/arch/arm/boot/dts/imx51-babbage.dts
@@ -21,7 +21,7 @@
 		reg = <0x90000000 0x20000000>;
 	};
 
-	display@di0 {
+	display0: display@di0 {
 		compatible = "fsl,imx-parallel-display";
 		crtcs = <&ipu 0>;
 		interface-pix-fmt = "rgb24";
@@ -43,7 +43,7 @@
 		};
 	};
 
-	display@di1 {
+	display1: display@di1 {
 		compatible = "fsl,imx-parallel-display";
 		crtcs = <&ipu 1>;
 		interface-pix-fmt = "rgb565";
@@ -81,6 +81,12 @@
 		};
 	};
 
+	imx-drm {
+		compatible = "fsl,imx-drm";
+		crtcs = <&ipu 0>, <&ipu 1>;
+		connectors = <&display0>, <&display1>;
+	};
+
 	sound {
 		compatible = "fsl,imx51-babbage-sgtl5000",
 			     "fsl,imx-audio-sgtl5000";
diff --git a/arch/arm/boot/dts/imx53-m53evk.dts b/arch/arm/boot/dts/imx53-m53evk.dts
index 7d304d0..ee6107b 100644
--- a/arch/arm/boot/dts/imx53-m53evk.dts
+++ b/arch/arm/boot/dts/imx53-m53evk.dts
@@ -21,7 +21,7 @@
 	};
 
 	soc {
-		display@di1 {
+		display1: display@di1 {
 			compatible = "fsl,imx-parallel-display";
 			crtcs = <&ipu 1>;
 			interface-pix-fmt = "bgr666";
@@ -53,6 +53,12 @@
 		default-brightness-level = <6>;
 	};
 
+	imx-drm {
+		compatible = "fsl,imx-drm";
+		crtcs = <&ipu 1>;
+		connectors = <&display1>;
+	};
+
 	leds {
 		compatible = "gpio-leds";
 		pinctrl-names = "default";
diff --git a/arch/arm/boot/dts/imx53-mba53.dts b/arch/arm/boot/dts/imx53-mba53.dts
index a630902..9b6e769 100644
--- a/arch/arm/boot/dts/imx53-mba53.dts
+++ b/arch/arm/boot/dts/imx53-mba53.dts
@@ -43,6 +43,12 @@
 		status = "disabled";
 	};
 
+	imx-drm {
+		compatible = "fsl,imx-drm";
+		crtcs = <&ipu 1>;
+		connectors = <&disp1>, <&tve>;
+	};
+
 	reg_3p2v: 3p2v {
 		compatible = "regulator-fixed";
 		regulator-name = "3P2V";
diff --git a/arch/arm/boot/dts/imx53-qsb.dts b/arch/arm/boot/dts/imx53-qsb.dts
index 91a5935..3cb4f77 100644
--- a/arch/arm/boot/dts/imx53-qsb.dts
+++ b/arch/arm/boot/dts/imx53-qsb.dts
@@ -21,7 +21,7 @@
 		reg = <0x70000000 0x40000000>;
 	};
 
-	display@di0 {
+	display0: display@di0 {
 		compatible = "fsl,imx-parallel-display";
 		crtcs = <&ipu 0>;
 		interface-pix-fmt = "rgb565";
@@ -72,6 +72,12 @@
 		};
 	};
 
+	imx-drm {
+		compatible = "fsl,imx-drm";
+		crtcs = <&ipu 0>;
+		connectors = <&display0>;
+	};
+
 	leds {
 		compatible = "gpio-leds";
 		pinctrl-names = "default";
diff --git a/arch/arm/boot/dts/imx6dl-hummingboard.dts b/arch/arm/boot/dts/imx6dl-hummingboard.dts
index fd8fc7c..5bfae54 100644
--- a/arch/arm/boot/dts/imx6dl-hummingboard.dts
+++ b/arch/arm/boot/dts/imx6dl-hummingboard.dts
@@ -52,12 +52,6 @@
 		};
 	};
 
-	codec: spdif-transmitter {
-		compatible = "linux,spdif-dit";
-		pinctrl-names = "default";
-		pinctrl-0 = <&pinctrl_hummingboard_spdif>;
-	};
-
 	sound-spdif {
 		compatible = "fsl,imx-audio-spdif";
 		model = "imx-spdif";
@@ -111,7 +105,7 @@
 		};
 
 		pinctrl_hummingboard_spdif: hummingboard-spdif {
-			fsl,pins = <MX6QDL_PAD_GPIO_17__SPDIF_OUT 0x1b0b0>;
+			fsl,pins = <MX6QDL_PAD_GPIO_17__SPDIF_OUT 0x13091>;
 		};
 
 		pinctrl_hummingboard_usbh1_vbus: hummingboard-usbh1-vbus {
@@ -142,6 +136,8 @@
 };
 
 &spdif {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_hummingboard_spdif>;
 	status = "okay";
 };
 
diff --git a/arch/arm/boot/dts/imx6dl.dtsi b/arch/arm/boot/dts/imx6dl.dtsi
index 9e8ae11..6dc3970 100644
--- a/arch/arm/boot/dts/imx6dl.dtsi
+++ b/arch/arm/boot/dts/imx6dl.dtsi
@@ -88,3 +88,8 @@
 		crtcs = <&ipu1 0>, <&ipu1 1>;
 	};
 };
+
+&hdmi {
+	compatible = "fsl,imx6dl-hdmi";
+	crtcs = <&ipu1 0>, <&ipu1 1>;
+};
diff --git a/arch/arm/boot/dts/imx6q-sabresd.dts b/arch/arm/boot/dts/imx6q-sabresd.dts
index 9cbdfe7..66f220a 100644
--- a/arch/arm/boot/dts/imx6q-sabresd.dts
+++ b/arch/arm/boot/dts/imx6q-sabresd.dts
@@ -20,6 +20,10 @@
 	compatible = "fsl,imx6q-sabresd", "fsl,imx6q";
 };
 
+&imx_drm {
+	crtcs = <&ipu1 0>, <&ipu1 1>, <&ipu2 0>, <&ipu2 1>;
+};
+
 &sata {
 	status = "okay";
 };
diff --git a/arch/arm/boot/dts/imx6q.dtsi b/arch/arm/boot/dts/imx6q.dtsi
index f024ef2..187fe33 100644
--- a/arch/arm/boot/dts/imx6q.dtsi
+++ b/arch/arm/boot/dts/imx6q.dtsi
@@ -159,3 +159,8 @@
 		crtcs = <&ipu1 0>, <&ipu1 1>, <&ipu2 0>, <&ipu2 1>;
 	};
 };
+
+&hdmi {
+	compatible = "fsl,imx6q-hdmi";
+	crtcs = <&ipu1 0>, <&ipu1 1>, <&ipu2 0>, <&ipu2 1>;
+};
diff --git a/arch/arm/boot/dts/imx6qdl-cubox-i.dtsi b/arch/arm/boot/dts/imx6qdl-cubox-i.dtsi
index 64daa3b..c2a2488 100644
--- a/arch/arm/boot/dts/imx6qdl-cubox-i.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-cubox-i.dtsi
@@ -46,12 +46,6 @@
 		};
 	};
 
-	codec: spdif-transmitter {
-		compatible = "linux,spdif-dit";
-		pinctrl-names = "default";
-		pinctrl-0 = <&pinctrl_cubox_i_spdif>;
-	};
-
 	sound-spdif {
 		compatible = "fsl,imx-audio-spdif";
 		model = "imx-spdif";
@@ -89,7 +83,7 @@
 		};
 
 		pinctrl_cubox_i_spdif: cubox-i-spdif {
-			fsl,pins = <MX6QDL_PAD_GPIO_17__SPDIF_OUT 0x1b0b0>;
+			fsl,pins = <MX6QDL_PAD_GPIO_17__SPDIF_OUT 0x13091>;
 		};
 
 		pinctrl_cubox_i_usbh1_vbus: cubox-i-usbh1-vbus {
@@ -121,6 +115,8 @@
 };
 
 &spdif {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_cubox_i_spdif>;
 	status = "okay";
 };
 
diff --git a/arch/arm/boot/dts/imx6qdl-sabresd.dtsi b/arch/arm/boot/dts/imx6qdl-sabresd.dtsi
index e75e11b..dfca3e0 100644
--- a/arch/arm/boot/dts/imx6qdl-sabresd.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-sabresd.dtsi
@@ -62,6 +62,12 @@
 		};
 	};
 
+	imx_drm: imx-drm {
+		compatible = "fsl,imx-drm";
+		crtcs = <&ipu1 0>, <&ipu1 1>;
+		connectors = <&ldb>;
+	};
+
 	sound {
 		compatible = "fsl,imx6q-sabresd-wm8962",
 			   "fsl,imx-audio-wm8962";
diff --git a/arch/arm/boot/dts/imx6qdl.dtsi b/arch/arm/boot/dts/imx6qdl.dtsi
index fb28b2e..930ebe0 100644
--- a/arch/arm/boot/dts/imx6qdl.dtsi
+++ b/arch/arm/boot/dts/imx6qdl.dtsi
@@ -1368,6 +1368,15 @@
 				};
 			};
 
+			hdmi: hdmi@0120000 {
+				reg = <0x00120000 0x9000>;
+				interrupts = <0 115 0x04>;
+				gpr = <&gpr>;
+				clocks = <&clks 123>, <&clks 124>;
+				clock-names = "iahb", "isfr";
+				status = "disabled";
+			};
+
 			dcic1: dcic@020e4000 {
 				reg = <0x020e4000 0x4000>;
 				interrupts = <0 124 0x04>;
diff --git a/arch/arm/boot/dts/omap3-gta04.dts b/arch/arm/boot/dts/omap3-gta04.dts
index b9b55c9..c551e4a 100644
--- a/arch/arm/boot/dts/omap3-gta04.dts
+++ b/arch/arm/boot/dts/omap3-gta04.dts
@@ -32,7 +32,7 @@
 		aux-button {
 			label = "aux";
 			linux,code = <169>;
-			gpios = <&gpio1 7 GPIO_ACTIVE_LOW>;
+			gpios = <&gpio1 7 GPIO_ACTIVE_HIGH>;
 			gpio-key,wakeup;
 		};
 	};
@@ -92,6 +92,8 @@
 	bmp085@77 {
 		compatible = "bosch,bmp085";
 		reg = <0x77>;
+		interrupt-parent = <&gpio4>;
+		interrupts = <17 IRQ_TYPE_EDGE_RISING>;
 	};
 
 	/* leds */
@@ -141,8 +143,8 @@
 	pinctrl-names = "default";
 	pinctrl-0 = <&mmc1_pins>;
 	vmmc-supply = <&vmmc1>;
-	vmmc_aux-supply = <&vsim>;
 	bus-width = <4>;
+	ti,non-removable;
 };
 
 &mmc2 {
diff --git a/arch/arm/boot/dts/omap3-n9.dts b/arch/arm/boot/dts/omap3-n9.dts
index 39828ce..9938b5d 100644
--- a/arch/arm/boot/dts/omap3-n9.dts
+++ b/arch/arm/boot/dts/omap3-n9.dts
@@ -14,5 +14,5 @@
 
 / {
 	model = "Nokia N9";
-	compatible = "nokia,omap3-n9", "ti,omap3";
+	compatible = "nokia,omap3-n9", "ti,omap36xx", "ti,omap3";
 };
diff --git a/arch/arm/boot/dts/omap3-n900.dts b/arch/arm/boot/dts/omap3-n900.dts
index 6fc85f9..0bf40c9 100644
--- a/arch/arm/boot/dts/omap3-n900.dts
+++ b/arch/arm/boot/dts/omap3-n900.dts
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2013 Pavel Machek <pavel@ucw.cz>
- * Copyright 2013 Aaro Koskinen <aaro.koskinen@iki.fi>
+ * Copyright (C) 2013-2014 Aaro Koskinen <aaro.koskinen@iki.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 (or later) as
@@ -13,7 +13,7 @@
 
 / {
 	model = "Nokia N900";
-	compatible = "nokia,omap3-n900", "ti,omap3";
+	compatible = "nokia,omap3-n900", "ti,omap3430", "ti,omap3";
 
 	cpus {
 		cpu@0 {
diff --git a/arch/arm/boot/dts/omap3-n950.dts b/arch/arm/boot/dts/omap3-n950.dts
index b076a52..261c558 100644
--- a/arch/arm/boot/dts/omap3-n950.dts
+++ b/arch/arm/boot/dts/omap3-n950.dts
@@ -14,5 +14,5 @@
 
 / {
 	model = "Nokia N950";
-	compatible = "nokia,omap3-n950", "ti,omap3";
+	compatible = "nokia,omap3-n950", "ti,omap36xx", "ti,omap3";
 };
diff --git a/arch/arm/boot/dts/omap3-overo-storm-tobi.dts b/arch/arm/boot/dts/omap3-overo-storm-tobi.dts
new file mode 100644
index 0000000..966b5c9
--- /dev/null
+++ b/arch/arm/boot/dts/omap3-overo-storm-tobi.dts
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2012 Florian Vaussard, EPFL Mobots group
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/*
+ * Tobi expansion board is manufactured by Gumstix Inc.
+ */
+
+/dts-v1/;
+
+#include "omap36xx.dtsi"
+#include "omap3-overo-tobi-common.dtsi"
+
+/ {
+	model = "OMAP36xx/AM37xx/DM37xx Gumstix Overo on Tobi";
+	compatible = "gumstix,omap3-overo-tobi", "gumstix,omap3-overo", "ti,omap36xx", "ti,omap3";
+};
+
diff --git a/arch/arm/boot/dts/omap3-tobi.dts b/arch/arm/boot/dts/omap3-overo-tobi-common.dtsi
similarity index 93%
rename from arch/arm/boot/dts/omap3-tobi.dts
rename to arch/arm/boot/dts/omap3-overo-tobi-common.dtsi
index 7e4ad2a..4edc013 100644
--- a/arch/arm/boot/dts/omap3-tobi.dts
+++ b/arch/arm/boot/dts/omap3-overo-tobi-common.dtsi
@@ -13,9 +13,6 @@
 #include "omap3-overo.dtsi"
 
 / {
-	model = "TI OMAP3 Gumstix Overo on Tobi";
-	compatible = "ti,omap3-tobi", "ti,omap3-overo", "ti,omap3";
-
 	leds {
 		compatible = "gpio-leds";
 		heartbeat {
diff --git a/arch/arm/boot/dts/omap3-overo-tobi.dts b/arch/arm/boot/dts/omap3-overo-tobi.dts
new file mode 100644
index 0000000..de5653e
--- /dev/null
+++ b/arch/arm/boot/dts/omap3-overo-tobi.dts
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2012 Florian Vaussard, EPFL Mobots group
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/*
+ * Tobi expansion board is manufactured by Gumstix Inc.
+ */
+
+/dts-v1/;
+
+#include "omap34xx.dtsi"
+#include "omap3-overo-tobi-common.dtsi"
+
+/ {
+	model = "OMAP35xx Gumstix Overo on Tobi";
+	compatible = "gumstix,omap3-overo-tobi", "gumstix,omap3-overo", "ti,omap3430", "ti,omap3";
+};
+
diff --git a/arch/arm/boot/dts/omap3-overo.dtsi b/arch/arm/boot/dts/omap3-overo.dtsi
index a461d2f..5970999 100644
--- a/arch/arm/boot/dts/omap3-overo.dtsi
+++ b/arch/arm/boot/dts/omap3-overo.dtsi
@@ -9,9 +9,6 @@
 /*
  * The Gumstix Overo must be combined with an expansion board.
  */
-/dts-v1/;
-
-#include "omap34xx.dtsi"
 
 / {
 	pwmleds {
diff --git a/arch/arm/boot/dts/tegra114.dtsi b/arch/arm/boot/dts/tegra114.dtsi
index 389e987..44ec401 100644
--- a/arch/arm/boot/dts/tegra114.dtsi
+++ b/arch/arm/boot/dts/tegra114.dtsi
@@ -57,6 +57,8 @@
 			resets = <&tegra_car 27>;
 			reset-names = "dc";
 
+			nvidia,head = <0>;
+
 			rgb {
 				status = "disabled";
 			};
@@ -72,6 +74,8 @@
 			resets = <&tegra_car 26>;
 			reset-names = "dc";
 
+			nvidia,head = <1>;
+
 			rgb {
 				status = "disabled";
 			};
diff --git a/arch/arm/boot/dts/tegra20.dtsi b/arch/arm/boot/dts/tegra20.dtsi
index 480ecda..48d2a7f 100644
--- a/arch/arm/boot/dts/tegra20.dtsi
+++ b/arch/arm/boot/dts/tegra20.dtsi
@@ -94,6 +94,8 @@
 			resets = <&tegra_car 27>;
 			reset-names = "dc";
 
+			nvidia,head = <0>;
+
 			rgb {
 				status = "disabled";
 			};
@@ -109,6 +111,8 @@
 			resets = <&tegra_car 26>;
 			reset-names = "dc";
 
+			nvidia,head = <1>;
+
 			rgb {
 				status = "disabled";
 			};
diff --git a/arch/arm/boot/dts/tegra30-cardhu.dtsi b/arch/arm/boot/dts/tegra30-cardhu.dtsi
index 9104224..1e156d9 100644
--- a/arch/arm/boot/dts/tegra30-cardhu.dtsi
+++ b/arch/arm/boot/dts/tegra30-cardhu.dtsi
@@ -28,7 +28,7 @@
 	compatible = "nvidia,cardhu", "nvidia,tegra30";
 
 	aliases {
-		rtc0 = "/i2c@7000d000/tps6586x@34";
+		rtc0 = "/i2c@7000d000/tps65911@2d";
 		rtc1 = "/rtc@7000e000";
 	};
 
diff --git a/arch/arm/boot/dts/tegra30.dtsi b/arch/arm/boot/dts/tegra30.dtsi
index ed8e770..19a84e9 100644
--- a/arch/arm/boot/dts/tegra30.dtsi
+++ b/arch/arm/boot/dts/tegra30.dtsi
@@ -170,6 +170,8 @@
 			resets = <&tegra_car 27>;
 			reset-names = "dc";
 
+			nvidia,head = <0>;
+
 			rgb {
 				status = "disabled";
 			};
@@ -185,6 +187,8 @@
 			resets = <&tegra_car 26>;
 			reset-names = "dc";
 
+			nvidia,head = <1>;
+
 			rgb {
 				status = "disabled";
 			};
diff --git a/arch/arm/boot/dts/testcases/tests.dtsi b/arch/arm/boot/dts/testcases/tests.dtsi
deleted file mode 100644
index 3f123ec..0000000
--- a/arch/arm/boot/dts/testcases/tests.dtsi
+++ /dev/null
@@ -1,2 +0,0 @@
-/include/ "tests-phandle.dtsi"
-/include/ "tests-interrupts.dtsi"
diff --git a/arch/arm/boot/dts/versatile-pb.dts b/arch/arm/boot/dts/versatile-pb.dts
index f43907c..65f6577 100644
--- a/arch/arm/boot/dts/versatile-pb.dts
+++ b/arch/arm/boot/dts/versatile-pb.dts
@@ -1,4 +1,4 @@
-/include/ "versatile-ab.dts"
+#include <versatile-ab.dts>
 
 / {
 	model = "ARM Versatile PB";
@@ -47,4 +47,4 @@
 	};
 };
 
-/include/ "testcases/tests.dtsi"
+#include <testcases.dtsi>
diff --git a/arch/arm/include/asm/cacheflush.h b/arch/arm/include/asm/cacheflush.h
index e9a49fe..8b8b616 100644
--- a/arch/arm/include/asm/cacheflush.h
+++ b/arch/arm/include/asm/cacheflush.h
@@ -212,6 +212,7 @@
 static inline void __flush_icache_all(void)
 {
 	__flush_icache_preferred();
+	dsb();
 }
 
 /*
diff --git a/arch/arm/include/asm/pgtable-3level.h b/arch/arm/include/asm/pgtable-3level.h
index 03243f7..85c60ad 100644
--- a/arch/arm/include/asm/pgtable-3level.h
+++ b/arch/arm/include/asm/pgtable-3level.h
@@ -120,13 +120,16 @@
 /*
  * 2nd stage PTE definitions for LPAE.
  */
-#define L_PTE_S2_MT_UNCACHED	 (_AT(pteval_t, 0x5) << 2) /* MemAttr[3:0] */
-#define L_PTE_S2_MT_WRITETHROUGH (_AT(pteval_t, 0xa) << 2) /* MemAttr[3:0] */
-#define L_PTE_S2_MT_WRITEBACK	 (_AT(pteval_t, 0xf) << 2) /* MemAttr[3:0] */
-#define L_PTE_S2_RDONLY		 (_AT(pteval_t, 1) << 6)   /* HAP[1]   */
-#define L_PTE_S2_RDWR		 (_AT(pteval_t, 3) << 6)   /* HAP[2:1] */
+#define L_PTE_S2_MT_UNCACHED		(_AT(pteval_t, 0x0) << 2) /* strongly ordered */
+#define L_PTE_S2_MT_WRITETHROUGH	(_AT(pteval_t, 0xa) << 2) /* normal inner write-through */
+#define L_PTE_S2_MT_WRITEBACK		(_AT(pteval_t, 0xf) << 2) /* normal inner write-back */
+#define L_PTE_S2_MT_DEV_SHARED		(_AT(pteval_t, 0x1) << 2) /* device */
+#define L_PTE_S2_MT_MASK		(_AT(pteval_t, 0xf) << 2)
 
-#define L_PMD_S2_RDWR		 (_AT(pmdval_t, 3) << 6)   /* HAP[2:1] */
+#define L_PTE_S2_RDONLY			(_AT(pteval_t, 1) << 6)   /* HAP[1]   */
+#define L_PTE_S2_RDWR			(_AT(pteval_t, 3) << 6)   /* HAP[2:1] */
+
+#define L_PMD_S2_RDWR			(_AT(pmdval_t, 3) << 6)   /* HAP[2:1] */
 
 /*
  * Hyp-mode PL2 PTE definitions for LPAE.
diff --git a/arch/arm/include/asm/spinlock.h b/arch/arm/include/asm/spinlock.h
index ef3c607..ac4bfae 100644
--- a/arch/arm/include/asm/spinlock.h
+++ b/arch/arm/include/asm/spinlock.h
@@ -37,18 +37,9 @@
 
 static inline void dsb_sev(void)
 {
-#if __LINUX_ARM_ARCH__ >= 7
-	__asm__ __volatile__ (
-		"dsb ishst\n"
-		SEV
-	);
-#else
-	__asm__ __volatile__ (
-		"mcr p15, 0, %0, c7, c10, 4\n"
-		SEV
-		: : "r" (0)
-	);
-#endif
+
+	dsb(ishst);
+	__asm__(SEV);
 }
 
 /*
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index b0df976..1e8b030 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -731,7 +731,7 @@
 	kernel_data.end     = virt_to_phys(_end - 1);
 
 	for_each_memblock(memory, region) {
-		res = memblock_virt_alloc_low(sizeof(*res), 0);
+		res = memblock_virt_alloc(sizeof(*res), 0);
 		res->name  = "System RAM";
 		res->start = __pfn_to_phys(memblock_region_memory_base_pfn(region));
 		res->end = __pfn_to_phys(memblock_region_memory_end_pfn(region)) - 1;
diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
index 1d8248e..bd18bb8 100644
--- a/arch/arm/kvm/arm.c
+++ b/arch/arm/kvm/arm.c
@@ -878,7 +878,8 @@
 				    unsigned long cmd,
 				    void *v)
 {
-	if (cmd == CPU_PM_EXIT) {
+	if (cmd == CPU_PM_EXIT &&
+	    __hyp_get_vectors() == hyp_default_vectors) {
 		cpu_init_hyp_mode(NULL);
 		return NOTIFY_OK;
 	}
diff --git a/arch/arm/kvm/interrupts.S b/arch/arm/kvm/interrupts.S
index ddc1553..0d68d40 100644
--- a/arch/arm/kvm/interrupts.S
+++ b/arch/arm/kvm/interrupts.S
@@ -220,6 +220,10 @@
  * in Hyp mode (see init_hyp_mode in arch/arm/kvm/arm.c).  Return values are
  * passed in r0 and r1.
  *
+ * A function pointer with a value of 0xffffffff has a special meaning,
+ * and is used to implement __hyp_get_vectors in the same way as in
+ * arch/arm/kernel/hyp_stub.S.
+ *
  * The calling convention follows the standard AAPCS:
  *   r0 - r3: caller save
  *   r12:     caller save
@@ -363,6 +367,11 @@
 host_switch_to_hyp:
 	pop	{r0, r1, r2}
 
+	/* Check for __hyp_get_vectors */
+	cmp	r0, #-1
+	mrceq	p15, 4, r0, c12, c0, 0	@ get HVBAR
+	beq	1f
+
 	push	{lr}
 	mrs	lr, SPSR
 	push	{lr}
@@ -378,7 +387,7 @@
 	pop	{lr}
 	msr	SPSR_csxf, lr
 	pop	{lr}
-	eret
+1:	eret
 
 guest_trap:
 	load_vcpu			@ Load VCPU pointer to r0
diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile
index befcaf5..ec41964 100644
--- a/arch/arm/mach-imx/Makefile
+++ b/arch/arm/mach-imx/Makefile
@@ -101,11 +101,9 @@
 obj-$(CONFIG_SOC_IMX6Q) += clk-imx6q.o mach-imx6q.o
 obj-$(CONFIG_SOC_IMX6SL) += clk-imx6sl.o mach-imx6sl.o
 
-ifeq ($(CONFIG_PM),y)
 obj-$(CONFIG_SOC_IMX6Q) += pm-imx6q.o headsmp.o
 # i.MX6SL reuses i.MX6Q code
 obj-$(CONFIG_SOC_IMX6SL) += pm-imx6q.o headsmp.o
-endif
 
 # i.MX5 based machines
 obj-$(CONFIG_MACH_MX51_BABBAGE) += mach-mx51_babbage.o
diff --git a/arch/arm/mach-imx/common.h b/arch/arm/mach-imx/common.h
index 59c3b9b..baf439d 100644
--- a/arch/arm/mach-imx/common.h
+++ b/arch/arm/mach-imx/common.h
@@ -144,13 +144,11 @@
 void imx_cpu_die(unsigned int cpu);
 int imx_cpu_kill(unsigned int cpu);
 
-#ifdef CONFIG_PM
 void imx6q_pm_init(void);
 void imx6q_pm_set_ccm_base(void __iomem *base);
+#ifdef CONFIG_PM
 void imx5_pm_init(void);
 #else
-static inline void imx6q_pm_init(void) {}
-static inline void imx6q_pm_set_ccm_base(void __iomem *base) {}
 static inline void imx5_pm_init(void) {}
 #endif
 
diff --git a/arch/arm/mach-omap1/board-nokia770.c b/arch/arm/mach-omap1/board-nokia770.c
index 91449c5..85089d8 100644
--- a/arch/arm/mach-omap1/board-nokia770.c
+++ b/arch/arm/mach-omap1/board-nokia770.c
@@ -156,6 +156,7 @@
 	.register_dev	= 1,
 	.hmc_mode	= 16,
 	.pins[0]	= 6,
+	.extcon		= "tahvo-usb",
 };
 
 #if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE)
diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig
index e2ce4f8..0af7ca0 100644
--- a/arch/arm/mach-omap2/Kconfig
+++ b/arch/arm/mach-omap2/Kconfig
@@ -50,6 +50,7 @@
 	bool "TI OMAP5"
 	depends on ARCH_MULTI_V7
 	select ARCH_OMAP2PLUS
+	select ARCH_HAS_OPP
 	select ARM_CPU_SUSPEND if PM
 	select ARM_GIC
 	select CPU_V7
@@ -63,6 +64,7 @@
 	bool "TI AM33XX"
 	depends on ARCH_MULTI_V7
 	select ARCH_OMAP2PLUS
+	select ARCH_HAS_OPP
 	select ARM_CPU_SUSPEND if PM
 	select CPU_V7
 	select MULTI_IRQ_HANDLER
@@ -72,6 +74,7 @@
 	depends on ARCH_MULTI_V7
 	select CPU_V7
 	select ARCH_OMAP2PLUS
+	select ARCH_HAS_OPP
 	select MULTI_IRQ_HANDLER
 	select ARM_GIC
 	select MACH_OMAP_GENERIC
@@ -80,6 +83,7 @@
 	bool "TI DRA7XX"
 	depends on ARCH_MULTI_V7
 	select ARCH_OMAP2PLUS
+	select ARCH_HAS_OPP
 	select ARM_CPU_SUSPEND if PM
 	select ARM_GIC
 	select CPU_V7
@@ -268,9 +272,6 @@
 	default y
 	select OMAP_PACKAGE_CBB
 
-config MACH_NOKIA_N800
-       bool
-
 config MACH_NOKIA_N810
        bool
 
@@ -281,7 +282,6 @@
 	bool "Nokia N800/N810"
 	depends on SOC_OMAP2420
 	default y
-	select MACH_NOKIA_N800
 	select MACH_NOKIA_N810
 	select MACH_NOKIA_N810_WIMAX
 	select OMAP_PACKAGE_ZAC
diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
index d24926e..ab43755 100644
--- a/arch/arm/mach-omap2/gpmc.c
+++ b/arch/arm/mach-omap2/gpmc.c
@@ -1339,7 +1339,7 @@
 		of_property_read_bool(np, "gpmc,time-para-granularity");
 }
 
-#ifdef CONFIG_MTD_NAND
+#if IS_ENABLED(CONFIG_MTD_NAND)
 
 static const char * const nand_xfer_types[] = {
 	[NAND_OMAP_PREFETCH_POLLED]		= "prefetch-polled",
@@ -1429,7 +1429,7 @@
 }
 #endif
 
-#ifdef CONFIG_MTD_ONENAND
+#if IS_ENABLED(CONFIG_MTD_ONENAND)
 static int gpmc_probe_onenand_child(struct platform_device *pdev,
 				 struct device_node *child)
 {
diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c
index d408b15..af432b1 100644
--- a/arch/arm/mach-omap2/io.c
+++ b/arch/arm/mach-omap2/io.c
@@ -179,15 +179,6 @@
 		.length		= L4_EMU_34XX_SIZE,
 		.type		= MT_DEVICE
 	},
-#if defined(CONFIG_DEBUG_LL) &&							\
-	(defined(CONFIG_MACH_OMAP_ZOOM2) || defined(CONFIG_MACH_OMAP_ZOOM3))
-	{
-		.virtual	= ZOOM_UART_VIRT,
-		.pfn		= __phys_to_pfn(ZOOM_UART_BASE),
-		.length		= SZ_1M,
-		.type		= MT_DEVICE
-	},
-#endif
 };
 #endif
 
diff --git a/arch/arm/mach-pxa/mioa701.c b/arch/arm/mach-pxa/mioa701.c
index f70583f..29997bd 100644
--- a/arch/arm/mach-pxa/mioa701.c
+++ b/arch/arm/mach-pxa/mioa701.c
@@ -38,6 +38,7 @@
 #include <linux/mtd/physmap.h>
 #include <linux/usb/gpio_vbus.h>
 #include <linux/reboot.h>
+#include <linux/regulator/fixed.h>
 #include <linux/regulator/max1586.h>
 #include <linux/slab.h>
 #include <linux/i2c/pxa-i2c.h>
@@ -714,6 +715,10 @@
 	{ GPIO56_MT9M111_nOE, GPIOF_OUT_INIT_LOW, "Camera nOE" },
 };
 
+static struct regulator_consumer_supply fixed_5v0_consumers[] = {
+	REGULATOR_SUPPLY("power", "pwm-backlight"),
+};
+
 static void __init mioa701_machine_init(void)
 {
 	int rc;
@@ -753,6 +758,10 @@
 	pxa_set_i2c_info(&i2c_pdata);
 	pxa27x_set_i2c_power_info(NULL);
 	pxa_set_camera_info(&mioa701_pxacamera_platform_data);
+
+	regulator_register_always_on(0, "fixed-5.0V", fixed_5v0_consumers,
+				     ARRAY_SIZE(fixed_5v0_consumers),
+				     5000000);
 }
 
 static void mioa701_machine_exit(void)
diff --git a/arch/arm/mach-tegra/pm.c b/arch/arm/mach-tegra/pm.c
index 4ae0286..f55b05a 100644
--- a/arch/arm/mach-tegra/pm.c
+++ b/arch/arm/mach-tegra/pm.c
@@ -24,6 +24,7 @@
 #include <linux/cpu_pm.h>
 #include <linux/suspend.h>
 #include <linux/err.h>
+#include <linux/slab.h>
 #include <linux/clk/tegra.h>
 
 #include <asm/smp_plat.h>
diff --git a/arch/arm/mach-tegra/tegra.c b/arch/arm/mach-tegra/tegra.c
index 303a285..6191603 100644
--- a/arch/arm/mach-tegra/tegra.c
+++ b/arch/arm/mach-tegra/tegra.c
@@ -73,10 +73,20 @@
 static void __init tegra_init_cache(void)
 {
 #ifdef CONFIG_CACHE_L2X0
+	static const struct of_device_id pl310_ids[] __initconst = {
+		{ .compatible = "arm,pl310-cache",  },
+		{}
+	};
+
+	struct device_node *np;
 	int ret;
 	void __iomem *p = IO_ADDRESS(TEGRA_ARM_PERIF_BASE) + 0x3000;
 	u32 aux_ctrl, cache_type;
 
+	np = of_find_matching_node(NULL, pl310_ids);
+	if (!np)
+		return;
+
 	cache_type = readl(p + L2X0_CACHE_TYPE);
 	aux_ctrl = (cache_type & 0x700) << (17-8);
 	aux_ctrl |= 0x7C400001;
diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index 1a77450..11b3914 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -1358,7 +1358,7 @@
 	*handle = DMA_ERROR_CODE;
 	size = PAGE_ALIGN(size);
 
-	if (gfp & GFP_ATOMIC)
+	if (!(gfp & __GFP_WAIT))
 		return __iommu_alloc_atomic(dev, size, handle);
 
 	/*
diff --git a/arch/arm/mm/mm.h b/arch/arm/mm/mm.h
index d5a982d..7ea641b 100644
--- a/arch/arm/mm/mm.h
+++ b/arch/arm/mm/mm.h
@@ -38,6 +38,7 @@
 
 struct mem_type {
 	pteval_t prot_pte;
+	pteval_t prot_pte_s2;
 	pmdval_t prot_l1;
 	pmdval_t prot_sect;
 	unsigned int domain;
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index 4f08c13..a623cb3 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -232,12 +232,16 @@
 #endif /* ifdef CONFIG_CPU_CP15 / else */
 
 #define PROT_PTE_DEVICE		L_PTE_PRESENT|L_PTE_YOUNG|L_PTE_DIRTY|L_PTE_XN
+#define PROT_PTE_S2_DEVICE	PROT_PTE_DEVICE
 #define PROT_SECT_DEVICE	PMD_TYPE_SECT|PMD_SECT_AP_WRITE
 
 static struct mem_type mem_types[] = {
 	[MT_DEVICE] = {		  /* Strongly ordered / ARMv6 shared device */
 		.prot_pte	= PROT_PTE_DEVICE | L_PTE_MT_DEV_SHARED |
 				  L_PTE_SHARED,
+		.prot_pte_s2	= s2_policy(PROT_PTE_S2_DEVICE) |
+				  s2_policy(L_PTE_S2_MT_DEV_SHARED) |
+				  L_PTE_SHARED,
 		.prot_l1	= PMD_TYPE_TABLE,
 		.prot_sect	= PROT_SECT_DEVICE | PMD_SECT_S,
 		.domain		= DOMAIN_IO,
@@ -508,7 +512,8 @@
 	cp = &cache_policies[cachepolicy];
 	vecs_pgprot = kern_pgprot = user_pgprot = cp->pte;
 	s2_pgprot = cp->pte_s2;
-	hyp_device_pgprot = s2_device_pgprot = mem_types[MT_DEVICE].prot_pte;
+	hyp_device_pgprot = mem_types[MT_DEVICE].prot_pte;
+	s2_device_pgprot = mem_types[MT_DEVICE].prot_pte_s2;
 
 	/*
 	 * ARMv6 and above have extended page tables.
diff --git a/arch/arm/mm/proc-v6.S b/arch/arm/mm/proc-v6.S
index 45dc29f..32b3558 100644
--- a/arch/arm/mm/proc-v6.S
+++ b/arch/arm/mm/proc-v6.S
@@ -208,7 +208,6 @@
 	mcr	p15, 0, r0, c7, c14, 0		@ clean+invalidate D cache
 	mcr	p15, 0, r0, c7, c5, 0		@ invalidate I cache
 	mcr	p15, 0, r0, c7, c15, 0		@ clean+invalidate cache
-	mcr	p15, 0, r0, c7, c10, 4		@ drain write buffer
 #ifdef CONFIG_MMU
 	mcr	p15, 0, r0, c8, c7, 0		@ invalidate I + D TLBs
 	mcr	p15, 0, r0, c2, c0, 2		@ TTB control register
@@ -218,6 +217,8 @@
 	ALT_UP(orr	r8, r8, #TTB_FLAGS_UP)
 	mcr	p15, 0, r8, c2, c0, 1		@ load TTB1
 #endif /* CONFIG_MMU */
+	mcr	p15, 0, r0, c7, c10, 4		@ drain write buffer and
+						@ complete invalidations
 	adr	r5, v6_crval
 	ldmia	r5, {r5, r6}
  ARM_BE8(orr	r6, r6, #1 << 25)		@ big-endian page tables
diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S
index bd17819..74f6033 100644
--- a/arch/arm/mm/proc-v7.S
+++ b/arch/arm/mm/proc-v7.S
@@ -351,7 +351,6 @@
 
 4:	mov	r10, #0
 	mcr	p15, 0, r10, c7, c5, 0		@ I+BTB cache invalidate
-	dsb
 #ifdef CONFIG_MMU
 	mcr	p15, 0, r10, c8, c7, 0		@ invalidate I + D TLBs
 	v7_ttb_setup r10, r4, r8, r5		@ TTBCR, TTBRx setup
@@ -360,6 +359,7 @@
 	mcr	p15, 0, r5, c10, c2, 0		@ write PRRR
 	mcr	p15, 0, r6, c10, c2, 1		@ write NMRR
 #endif
+	dsb					@ Complete invalidations
 #ifndef CONFIG_ARM_THUMBEE
 	mrc	p15, 0, r0, c0, c1, 0		@ read ID_PFR0 for ThumbEE
 	and	r0, r0, #(0xf << 12)		@ ThumbEE enabled field
diff --git a/arch/arm64/include/asm/percpu.h b/arch/arm64/include/asm/percpu.h
index 13fb0b3..453a179 100644
--- a/arch/arm64/include/asm/percpu.h
+++ b/arch/arm64/include/asm/percpu.h
@@ -16,6 +16,8 @@
 #ifndef __ASM_PERCPU_H
 #define __ASM_PERCPU_H
 
+#ifdef CONFIG_SMP
+
 static inline void set_my_cpu_offset(unsigned long off)
 {
 	asm volatile("msr tpidr_el1, %0" :: "r" (off) : "memory");
@@ -36,6 +38,12 @@
 }
 #define __my_cpu_offset __my_cpu_offset()
 
+#else	/* !CONFIG_SMP */
+
+#define set_my_cpu_offset(x)	do { } while (0)
+
+#endif /* CONFIG_SMP */
+
 #include <asm-generic/percpu.h>
 
 #endif /* __ASM_PERCPU_H */
diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h
index b524dcd..aa3917c 100644
--- a/arch/arm64/include/asm/pgtable.h
+++ b/arch/arm64/include/asm/pgtable.h
@@ -136,11 +136,11 @@
 /*
  * The following only work if pte_present(). Undefined behaviour otherwise.
  */
-#define pte_present(pte)	(pte_val(pte) & (PTE_VALID | PTE_PROT_NONE))
-#define pte_dirty(pte)		(pte_val(pte) & PTE_DIRTY)
-#define pte_young(pte)		(pte_val(pte) & PTE_AF)
-#define pte_special(pte)	(pte_val(pte) & PTE_SPECIAL)
-#define pte_write(pte)		(pte_val(pte) & PTE_WRITE)
+#define pte_present(pte)	(!!(pte_val(pte) & (PTE_VALID | PTE_PROT_NONE)))
+#define pte_dirty(pte)		(!!(pte_val(pte) & PTE_DIRTY))
+#define pte_young(pte)		(!!(pte_val(pte) & PTE_AF))
+#define pte_special(pte)	(!!(pte_val(pte) & PTE_SPECIAL))
+#define pte_write(pte)		(!!(pte_val(pte) & PTE_WRITE))
 #define pte_exec(pte)		(!(pte_val(pte) & PTE_UXN))
 
 #define pte_valid_user(pte) \
diff --git a/arch/arm64/kernel/stacktrace.c b/arch/arm64/kernel/stacktrace.c
index c3b6c63..38f0558 100644
--- a/arch/arm64/kernel/stacktrace.c
+++ b/arch/arm64/kernel/stacktrace.c
@@ -48,7 +48,11 @@
 
 	frame->sp = fp + 0x10;
 	frame->fp = *(unsigned long *)(fp);
-	frame->pc = *(unsigned long *)(fp + 8);
+	/*
+	 * -4 here because we care about the PC at time of bl,
+	 * not where the return will go.
+	 */
+	frame->pc = *(unsigned long *)(fp + 8) - 4;
 
 	return 0;
 }
diff --git a/arch/arm64/kvm/hyp.S b/arch/arm64/kvm/hyp.S
index 3b47c36..2c56012 100644
--- a/arch/arm64/kvm/hyp.S
+++ b/arch/arm64/kvm/hyp.S
@@ -694,6 +694,24 @@
 
 	.align	2
 
+/*
+ * u64 kvm_call_hyp(void *hypfn, ...);
+ *
+ * This is not really a variadic function in the classic C-way and care must
+ * be taken when calling this to ensure parameters are passed in registers
+ * only, since the stack will change between the caller and the callee.
+ *
+ * Call the function with the first argument containing a pointer to the
+ * function you wish to call in Hyp mode, and subsequent arguments will be
+ * passed as x0, x1, and x2 (a maximum of 3 arguments in addition to the
+ * function pointer can be passed).  The function being called must be mapped
+ * in Hyp mode (see init_hyp_mode in arch/arm/kvm/arm.c).  Return values are
+ * passed in r0 and r1.
+ *
+ * A function pointer with a value of 0 has a special meaning, and is
+ * used to implement __hyp_get_vectors in the same way as in
+ * arch/arm64/kernel/hyp_stub.S.
+ */
 ENTRY(kvm_call_hyp)
 	hvc	#0
 	ret
@@ -737,7 +755,12 @@
 	pop	x2, x3
 	pop	x0, x1
 
-	push	lr, xzr
+	/* Check for __hyp_get_vectors */
+	cbnz	x0, 1f
+	mrs	x0, vbar_el2
+	b	2f
+
+1:	push	lr, xzr
 
 	/*
 	 * Compute the function address in EL2, and shuffle the parameters.
@@ -750,7 +773,7 @@
 	blr	lr
 
 	pop	lr, xzr
-	eret
+2:	eret
 
 el1_trap:
 	/*
diff --git a/arch/avr32/Makefile b/arch/avr32/Makefile
index 22fb665..dba48a5d 100644
--- a/arch/avr32/Makefile
+++ b/arch/avr32/Makefile
@@ -11,7 +11,7 @@
 
 KBUILD_DEFCONFIG	:= atstk1002_defconfig
 
-KBUILD_CFLAGS	+= -pipe -fno-builtin -mno-pic
+KBUILD_CFLAGS	+= -pipe -fno-builtin -mno-pic -D__linux__
 KBUILD_AFLAGS	+= -mrelax -mno-pic
 KBUILD_CFLAGS_MODULE += -mno-relax
 LDFLAGS_vmlinux	+= --relax
diff --git a/arch/avr32/boards/mimc200/fram.c b/arch/avr32/boards/mimc200/fram.c
index 9764a1a..c1466a8 100644
--- a/arch/avr32/boards/mimc200/fram.c
+++ b/arch/avr32/boards/mimc200/fram.c
@@ -11,6 +11,7 @@
 #define FRAM_VERSION	"1.0"
 
 #include <linux/miscdevice.h>
+#include <linux/module.h>
 #include <linux/proc_fs.h>
 #include <linux/mm.h>
 #include <linux/io.h>
diff --git a/arch/avr32/include/asm/Kbuild b/arch/avr32/include/asm/Kbuild
index cfb9fe1..c7c64a6 100644
--- a/arch/avr32/include/asm/Kbuild
+++ b/arch/avr32/include/asm/Kbuild
@@ -17,5 +17,6 @@
 generic-y       += sections.h
 generic-y       += topology.h
 generic-y	+= trace_clock.h
+generic-y += vga.h
 generic-y       += xor.h
 generic-y	+= hash.h
diff --git a/arch/avr32/include/asm/io.h b/arch/avr32/include/asm/io.h
index fc6483f..4f5ec2b 100644
--- a/arch/avr32/include/asm/io.h
+++ b/arch/avr32/include/asm/io.h
@@ -295,6 +295,8 @@
 #define iounmap(addr)				\
 	__iounmap(addr)
 
+#define ioremap_wc ioremap_nocache
+
 #define cached(addr) P1SEGADDR(addr)
 #define uncached(addr) P2SEGADDR(addr)
 
diff --git a/arch/m68k/include/asm/Kbuild b/arch/m68k/include/asm/Kbuild
index 7cc8c36..6fb9e81 100644
--- a/arch/m68k/include/asm/Kbuild
+++ b/arch/m68k/include/asm/Kbuild
@@ -1,4 +1,4 @@
-
+generic-y += barrier.h
 generic-y += bitsperlong.h
 generic-y += clkdev.h
 generic-y += cputime.h
@@ -6,6 +6,7 @@
 generic-y += emergency-restart.h
 generic-y += errno.h
 generic-y += exec.h
+generic-y += hash.h
 generic-y += hw_irq.h
 generic-y += ioctl.h
 generic-y += ipcbuf.h
@@ -18,6 +19,7 @@
 generic-y += mman.h
 generic-y += mutex.h
 generic-y += percpu.h
+generic-y += preempt.h
 generic-y += resource.h
 generic-y += scatterlist.h
 generic-y += sections.h
@@ -31,5 +33,3 @@
 generic-y += types.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
-generic-y += preempt.h
-generic-y += hash.h
diff --git a/arch/m68k/include/asm/barrier.h b/arch/m68k/include/asm/barrier.h
deleted file mode 100644
index 15c5f77..0000000
--- a/arch/m68k/include/asm/barrier.h
+++ /dev/null
@@ -1,8 +0,0 @@
-#ifndef _M68K_BARRIER_H
-#define _M68K_BARRIER_H
-
-#define nop()		do { asm volatile ("nop"); barrier(); } while (0)
-
-#include <asm-generic/barrier.h>
-
-#endif /* _M68K_BARRIER_H */
diff --git a/arch/m68k/include/asm/unistd.h b/arch/m68k/include/asm/unistd.h
index 014f288..9d38b73 100644
--- a/arch/m68k/include/asm/unistd.h
+++ b/arch/m68k/include/asm/unistd.h
@@ -4,7 +4,7 @@
 #include <uapi/asm/unistd.h>
 
 
-#define NR_syscalls		349
+#define NR_syscalls		351
 
 #define __ARCH_WANT_OLD_READDIR
 #define __ARCH_WANT_OLD_STAT
diff --git a/arch/m68k/include/uapi/asm/unistd.h b/arch/m68k/include/uapi/asm/unistd.h
index 625f321..b932dd4 100644
--- a/arch/m68k/include/uapi/asm/unistd.h
+++ b/arch/m68k/include/uapi/asm/unistd.h
@@ -354,5 +354,7 @@
 #define __NR_process_vm_writev	346
 #define __NR_kcmp		347
 #define __NR_finit_module	348
+#define __NR_sched_setattr	349
+#define __NR_sched_getattr	350
 
 #endif /* _UAPI_ASM_M68K_UNISTD_H_ */
diff --git a/arch/m68k/kernel/syscalltable.S b/arch/m68k/kernel/syscalltable.S
index 3f04ea0..b6223dc4 100644
--- a/arch/m68k/kernel/syscalltable.S
+++ b/arch/m68k/kernel/syscalltable.S
@@ -369,4 +369,6 @@
 	.long sys_process_vm_writev
 	.long sys_kcmp
 	.long sys_finit_module
+	.long sys_sched_setattr
+	.long sys_sched_getattr		/* 350 */
 
diff --git a/arch/powerpc/include/asm/compat.h b/arch/powerpc/include/asm/compat.h
index 84fdf68..a613d2c 100644
--- a/arch/powerpc/include/asm/compat.h
+++ b/arch/powerpc/include/asm/compat.h
@@ -200,10 +200,11 @@
 
 	/*
 	 * We can't access below the stack pointer in the 32bit ABI and
-	 * can access 288 bytes in the 64bit ABI
+	 * can access 288 bytes in the 64bit big-endian ABI,
+	 * or 512 bytes with the new ELFv2 little-endian ABI.
 	 */
 	if (!is_32bit_task())
-		usp -= 288;
+		usp -= USER_REDZONE_SIZE;
 
 	return (void __user *) (usp - len);
 }
diff --git a/arch/powerpc/include/asm/eeh.h b/arch/powerpc/include/asm/eeh.h
index 9e39ceb..d4dd41f 100644
--- a/arch/powerpc/include/asm/eeh.h
+++ b/arch/powerpc/include/asm/eeh.h
@@ -172,10 +172,20 @@
 };
 
 extern struct eeh_ops *eeh_ops;
-extern int eeh_subsystem_enabled;
+extern bool eeh_subsystem_enabled;
 extern raw_spinlock_t confirm_error_lock;
 extern int eeh_probe_mode;
 
+static inline bool eeh_enabled(void)
+{
+	return eeh_subsystem_enabled;
+}
+
+static inline void eeh_set_enable(bool mode)
+{
+	eeh_subsystem_enabled = mode;
+}
+
 #define EEH_PROBE_MODE_DEV	(1<<0)	/* From PCI device	*/
 #define EEH_PROBE_MODE_DEVTREE	(1<<1)	/* From device tree	*/
 
@@ -246,7 +256,7 @@
  * If this macro yields TRUE, the caller relays to eeh_check_failure()
  * which does further tests out of line.
  */
-#define EEH_POSSIBLE_ERROR(val, type)	((val) == (type)~0 && eeh_subsystem_enabled)
+#define EEH_POSSIBLE_ERROR(val, type)	((val) == (type)~0 && eeh_enabled())
 
 /*
  * Reads from a device which has been isolated by EEH will return
@@ -257,6 +267,13 @@
 
 #else /* !CONFIG_EEH */
 
+static inline bool eeh_enabled(void)
+{
+        return false;
+}
+
+static inline void eeh_set_enable(bool mode) { }
+
 static inline int eeh_init(void)
 {
 	return 0;
diff --git a/arch/powerpc/include/asm/hugetlb.h b/arch/powerpc/include/asm/hugetlb.h
index d750336..623f297 100644
--- a/arch/powerpc/include/asm/hugetlb.h
+++ b/arch/powerpc/include/asm/hugetlb.h
@@ -127,7 +127,7 @@
 					    unsigned long addr, pte_t *ptep)
 {
 #ifdef CONFIG_PPC64
-	return __pte(pte_update(mm, addr, ptep, ~0UL, 1));
+	return __pte(pte_update(mm, addr, ptep, ~0UL, 0, 1));
 #else
 	return __pte(pte_update(ptep, ~0UL, 0));
 #endif
diff --git a/arch/powerpc/include/asm/opal.h b/arch/powerpc/include/asm/opal.h
index 40157e2..ed82142 100644
--- a/arch/powerpc/include/asm/opal.h
+++ b/arch/powerpc/include/asm/opal.h
@@ -816,8 +816,8 @@
 int64_t opal_pci_poll(uint64_t phb_id);
 int64_t opal_return_cpu(void);
 
-int64_t opal_xscom_read(uint32_t gcid, uint32_t pcb_addr, __be64 *val);
-int64_t opal_xscom_write(uint32_t gcid, uint32_t pcb_addr, uint64_t val);
+int64_t opal_xscom_read(uint32_t gcid, uint64_t pcb_addr, __be64 *val);
+int64_t opal_xscom_write(uint32_t gcid, uint64_t pcb_addr, uint64_t val);
 
 int64_t opal_lpc_write(uint32_t chip_id, enum OpalLPCAddressType addr_type,
 		       uint32_t addr, uint32_t data, uint32_t sz);
diff --git a/arch/powerpc/include/asm/pgtable-ppc64.h b/arch/powerpc/include/asm/pgtable-ppc64.h
index bc141c9..eb92610 100644
--- a/arch/powerpc/include/asm/pgtable-ppc64.h
+++ b/arch/powerpc/include/asm/pgtable-ppc64.h
@@ -195,6 +195,7 @@
 static inline unsigned long pte_update(struct mm_struct *mm,
 				       unsigned long addr,
 				       pte_t *ptep, unsigned long clr,
+				       unsigned long set,
 				       int huge)
 {
 #ifdef PTE_ATOMIC_UPDATES
@@ -205,14 +206,15 @@
 	andi.	%1,%0,%6\n\
 	bne-	1b \n\
 	andc	%1,%0,%4 \n\
+	or	%1,%1,%7\n\
 	stdcx.	%1,0,%3 \n\
 	bne-	1b"
 	: "=&r" (old), "=&r" (tmp), "=m" (*ptep)
-	: "r" (ptep), "r" (clr), "m" (*ptep), "i" (_PAGE_BUSY)
+	: "r" (ptep), "r" (clr), "m" (*ptep), "i" (_PAGE_BUSY), "r" (set)
 	: "cc" );
 #else
 	unsigned long old = pte_val(*ptep);
-	*ptep = __pte(old & ~clr);
+	*ptep = __pte((old & ~clr) | set);
 #endif
 	/* huge pages use the old page table lock */
 	if (!huge)
@@ -231,9 +233,9 @@
 {
 	unsigned long old;
 
-       	if ((pte_val(*ptep) & (_PAGE_ACCESSED | _PAGE_HASHPTE)) == 0)
+	if ((pte_val(*ptep) & (_PAGE_ACCESSED | _PAGE_HASHPTE)) == 0)
 		return 0;
-	old = pte_update(mm, addr, ptep, _PAGE_ACCESSED, 0);
+	old = pte_update(mm, addr, ptep, _PAGE_ACCESSED, 0, 0);
 	return (old & _PAGE_ACCESSED) != 0;
 }
 #define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
@@ -252,7 +254,7 @@
 	if ((pte_val(*ptep) & _PAGE_RW) == 0)
 		return;
 
-	pte_update(mm, addr, ptep, _PAGE_RW, 0);
+	pte_update(mm, addr, ptep, _PAGE_RW, 0, 0);
 }
 
 static inline void huge_ptep_set_wrprotect(struct mm_struct *mm,
@@ -261,7 +263,7 @@
 	if ((pte_val(*ptep) & _PAGE_RW) == 0)
 		return;
 
-	pte_update(mm, addr, ptep, _PAGE_RW, 1);
+	pte_update(mm, addr, ptep, _PAGE_RW, 0, 1);
 }
 
 /*
@@ -284,14 +286,14 @@
 static inline pte_t ptep_get_and_clear(struct mm_struct *mm,
 				       unsigned long addr, pte_t *ptep)
 {
-	unsigned long old = pte_update(mm, addr, ptep, ~0UL, 0);
+	unsigned long old = pte_update(mm, addr, ptep, ~0UL, 0, 0);
 	return __pte(old);
 }
 
 static inline void pte_clear(struct mm_struct *mm, unsigned long addr,
 			     pte_t * ptep)
 {
-	pte_update(mm, addr, ptep, ~0UL, 0);
+	pte_update(mm, addr, ptep, ~0UL, 0, 0);
 }
 
 
@@ -506,7 +508,9 @@
 
 extern unsigned long pmd_hugepage_update(struct mm_struct *mm,
 					 unsigned long addr,
-					 pmd_t *pmdp, unsigned long clr);
+					 pmd_t *pmdp,
+					 unsigned long clr,
+					 unsigned long set);
 
 static inline int __pmdp_test_and_clear_young(struct mm_struct *mm,
 					      unsigned long addr, pmd_t *pmdp)
@@ -515,7 +519,7 @@
 
 	if ((pmd_val(*pmdp) & (_PAGE_ACCESSED | _PAGE_HASHPTE)) == 0)
 		return 0;
-	old = pmd_hugepage_update(mm, addr, pmdp, _PAGE_ACCESSED);
+	old = pmd_hugepage_update(mm, addr, pmdp, _PAGE_ACCESSED, 0);
 	return ((old & _PAGE_ACCESSED) != 0);
 }
 
@@ -542,7 +546,7 @@
 	if ((pmd_val(*pmdp) & _PAGE_RW) == 0)
 		return;
 
-	pmd_hugepage_update(mm, addr, pmdp, _PAGE_RW);
+	pmd_hugepage_update(mm, addr, pmdp, _PAGE_RW, 0);
 }
 
 #define __HAVE_ARCH_PMDP_SPLITTING_FLUSH
diff --git a/arch/powerpc/include/asm/pgtable.h b/arch/powerpc/include/asm/pgtable.h
index f83b6f3..3ebb188 100644
--- a/arch/powerpc/include/asm/pgtable.h
+++ b/arch/powerpc/include/asm/pgtable.h
@@ -75,12 +75,34 @@
 	return pte;
 }
 
+#define ptep_set_numa ptep_set_numa
+static inline void ptep_set_numa(struct mm_struct *mm, unsigned long addr,
+				 pte_t *ptep)
+{
+	if ((pte_val(*ptep) & _PAGE_PRESENT) == 0)
+		VM_BUG_ON(1);
+
+	pte_update(mm, addr, ptep, _PAGE_PRESENT, _PAGE_NUMA, 0);
+	return;
+}
+
 #define pmd_numa pmd_numa
 static inline int pmd_numa(pmd_t pmd)
 {
 	return pte_numa(pmd_pte(pmd));
 }
 
+#define pmdp_set_numa pmdp_set_numa
+static inline void pmdp_set_numa(struct mm_struct *mm, unsigned long addr,
+				 pmd_t *pmdp)
+{
+	if ((pmd_val(*pmdp) & _PAGE_PRESENT) == 0)
+		VM_BUG_ON(1);
+
+	pmd_hugepage_update(mm, addr, pmdp, _PAGE_PRESENT, _PAGE_NUMA);
+	return;
+}
+
 #define pmd_mknonnuma pmd_mknonnuma
 static inline pmd_t pmd_mknonnuma(pmd_t pmd)
 {
diff --git a/arch/powerpc/include/asm/ptrace.h b/arch/powerpc/include/asm/ptrace.h
index becc08e..279b80f 100644
--- a/arch/powerpc/include/asm/ptrace.h
+++ b/arch/powerpc/include/asm/ptrace.h
@@ -28,11 +28,23 @@
 
 #ifdef __powerpc64__
 
+/*
+ * Size of redzone that userspace is allowed to use below the stack
+ * pointer.  This is 288 in the 64-bit big-endian ELF ABI, and 512 in
+ * the new ELFv2 little-endian ABI, so we allow the larger amount.
+ *
+ * For kernel code we allow a 288-byte redzone, in order to conserve
+ * kernel stack space; gcc currently only uses 288 bytes, and will
+ * hopefully allow explicit control of the redzone size in future.
+ */
+#define USER_REDZONE_SIZE	512
+#define KERNEL_REDZONE_SIZE	288
+
 #define STACK_FRAME_OVERHEAD	112	/* size of minimum stack frame */
 #define STACK_FRAME_LR_SAVE	2	/* Location of LR in stack frame */
 #define STACK_FRAME_REGS_MARKER	ASM_CONST(0x7265677368657265)
 #define STACK_INT_FRAME_SIZE	(sizeof(struct pt_regs) + \
-					STACK_FRAME_OVERHEAD + 288)
+				 STACK_FRAME_OVERHEAD + KERNEL_REDZONE_SIZE)
 #define STACK_FRAME_MARKER	12
 
 /* Size of dummy stack frame allocated when calling signal handler. */
@@ -41,6 +53,8 @@
 
 #else /* __powerpc64__ */
 
+#define USER_REDZONE_SIZE	0
+#define KERNEL_REDZONE_SIZE	0
 #define STACK_FRAME_OVERHEAD	16	/* size of minimum stack frame */
 #define STACK_FRAME_LR_SAVE	1	/* Location of LR in stack frame */
 #define STACK_FRAME_REGS_MARKER	ASM_CONST(0x72656773)
diff --git a/arch/powerpc/include/asm/vdso.h b/arch/powerpc/include/asm/vdso.h
index 0d9cecd..c53f5f6 100644
--- a/arch/powerpc/include/asm/vdso.h
+++ b/arch/powerpc/include/asm/vdso.h
@@ -4,11 +4,11 @@
 #ifdef __KERNEL__
 
 /* Default link addresses for the vDSOs */
-#define VDSO32_LBASE	0x100000
-#define VDSO64_LBASE	0x100000
+#define VDSO32_LBASE	0x0
+#define VDSO64_LBASE	0x0
 
 /* Default map addresses for 32bit vDSO */
-#define VDSO32_MBASE	VDSO32_LBASE
+#define VDSO32_MBASE	0x100000
 
 #define VDSO_VERSION_STRING	LINUX_2.6.15
 
diff --git a/arch/powerpc/kernel/crash_dump.c b/arch/powerpc/kernel/crash_dump.c
index 11c1d06..7a13f37 100644
--- a/arch/powerpc/kernel/crash_dump.c
+++ b/arch/powerpc/kernel/crash_dump.c
@@ -98,17 +98,19 @@
 			size_t csize, unsigned long offset, int userbuf)
 {
 	void  *vaddr;
+	phys_addr_t paddr;
 
 	if (!csize)
 		return 0;
 
 	csize = min_t(size_t, csize, PAGE_SIZE);
+	paddr = pfn << PAGE_SHIFT;
 
-	if ((min_low_pfn < pfn) && (pfn < max_pfn)) {
-		vaddr = __va(pfn << PAGE_SHIFT);
+	if (memblock_is_region_memory(paddr, csize)) {
+		vaddr = __va(paddr);
 		csize = copy_oldmem_vaddr(vaddr, buf, csize, offset, userbuf);
 	} else {
-		vaddr = __ioremap(pfn << PAGE_SHIFT, PAGE_SIZE, 0);
+		vaddr = __ioremap(paddr, PAGE_SIZE, 0);
 		csize = copy_oldmem_vaddr(vaddr, buf, csize, offset, userbuf);
 		iounmap(vaddr);
 	}
diff --git a/arch/powerpc/kernel/eeh.c b/arch/powerpc/kernel/eeh.c
index 148db72..e7b76a6 100644
--- a/arch/powerpc/kernel/eeh.c
+++ b/arch/powerpc/kernel/eeh.c
@@ -28,6 +28,7 @@
 #include <linux/pci.h>
 #include <linux/proc_fs.h>
 #include <linux/rbtree.h>
+#include <linux/reboot.h>
 #include <linux/seq_file.h>
 #include <linux/spinlock.h>
 #include <linux/export.h>
@@ -89,7 +90,7 @@
 /* Platform dependent EEH operations */
 struct eeh_ops *eeh_ops = NULL;
 
-int eeh_subsystem_enabled;
+bool eeh_subsystem_enabled = false;
 EXPORT_SYMBOL(eeh_subsystem_enabled);
 
 /*
@@ -364,7 +365,7 @@
 
 	eeh_stats.total_mmio_ffs++;
 
-	if (!eeh_subsystem_enabled)
+	if (!eeh_enabled())
 		return 0;
 
 	if (!edev) {
@@ -747,6 +748,17 @@
 	return -EEXIST;
 }
 
+static int eeh_reboot_notifier(struct notifier_block *nb,
+			       unsigned long action, void *unused)
+{
+	eeh_set_enable(false);
+	return NOTIFY_DONE;
+}
+
+static struct notifier_block eeh_reboot_nb = {
+	.notifier_call = eeh_reboot_notifier,
+};
+
 /**
  * eeh_init - EEH initialization
  *
@@ -778,6 +790,14 @@
 	if (machine_is(powernv) && cnt++ <= 0)
 		return ret;
 
+	/* Register reboot notifier */
+	ret = register_reboot_notifier(&eeh_reboot_nb);
+	if (ret) {
+		pr_warn("%s: Failed to register notifier (%d)\n",
+			__func__, ret);
+		return ret;
+	}
+
 	/* call platform initialization function */
 	if (!eeh_ops) {
 		pr_warning("%s: Platform EEH operation not found\n",
@@ -822,7 +842,7 @@
 			return ret;
 	}
 
-	if (eeh_subsystem_enabled)
+	if (eeh_enabled())
 		pr_info("EEH: PCI Enhanced I/O Error Handling Enabled\n");
 	else
 		pr_warning("EEH: No capable adapters found\n");
@@ -897,7 +917,7 @@
 	struct device_node *dn;
 	struct eeh_dev *edev;
 
-	if (!dev || !eeh_subsystem_enabled)
+	if (!dev || !eeh_enabled())
 		return;
 
 	pr_debug("EEH: Adding device %s\n", pci_name(dev));
@@ -1005,7 +1025,7 @@
 {
 	struct eeh_dev *edev;
 
-	if (!dev || !eeh_subsystem_enabled)
+	if (!dev || !eeh_enabled())
 		return;
 	edev = pci_dev_to_eeh_dev(dev);
 
@@ -1045,7 +1065,7 @@
 
 static int proc_eeh_show(struct seq_file *m, void *v)
 {
-	if (0 == eeh_subsystem_enabled) {
+	if (!eeh_enabled()) {
 		seq_printf(m, "EEH Subsystem is globally disabled\n");
 		seq_printf(m, "eeh_total_mmio_ffs=%llu\n", eeh_stats.total_mmio_ffs);
 	} else {
diff --git a/arch/powerpc/kernel/ftrace.c b/arch/powerpc/kernel/ftrace.c
index 9b27b29..b0ded97 100644
--- a/arch/powerpc/kernel/ftrace.c
+++ b/arch/powerpc/kernel/ftrace.c
@@ -74,6 +74,7 @@
  */
 static int test_24bit_addr(unsigned long ip, unsigned long addr)
 {
+	addr = ppc_function_entry((void *)addr);
 
 	/* use the create_branch to verify that this offset can be branched */
 	return create_branch((unsigned int *)ip, addr, 0);
diff --git a/arch/powerpc/kernel/misc_32.S b/arch/powerpc/kernel/misc_32.S
index 879f096..7c6bb4b 100644
--- a/arch/powerpc/kernel/misc_32.S
+++ b/arch/powerpc/kernel/misc_32.S
@@ -57,11 +57,14 @@
 	mtlr	r0
 	blr
 
+/*
+ * void call_do_irq(struct pt_regs *regs, struct thread_info *irqtp);
+ */
 _GLOBAL(call_do_irq)
 	mflr	r0
 	stw	r0,4(r1)
 	lwz	r10,THREAD+KSP_LIMIT(r2)
-	addi	r11,r3,THREAD_INFO_GAP
+	addi	r11,r4,THREAD_INFO_GAP
 	stwu	r1,THREAD_SIZE-STACK_FRAME_OVERHEAD(r4)
 	mr	r1,r4
 	stw	r10,8(r1)
diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c
index e35bf77..8d253c2 100644
--- a/arch/powerpc/kernel/signal_64.c
+++ b/arch/powerpc/kernel/signal_64.c
@@ -65,8 +65,8 @@
 	struct siginfo __user *pinfo;
 	void __user *puc;
 	struct siginfo info;
-	/* 64 bit ABI allows for 288 bytes below sp before decrementing it. */
-	char abigap[288];
+	/* New 64 bit little-endian ABI allows redzone of 512 bytes below sp */
+	char abigap[USER_REDZONE_SIZE];
 } __attribute__ ((aligned (16)));
 
 static const char fmt32[] = KERN_INFO \
diff --git a/arch/powerpc/kernel/vdso32/vdso32_wrapper.S b/arch/powerpc/kernel/vdso32/vdso32_wrapper.S
index 79683d0..6ac107a 100644
--- a/arch/powerpc/kernel/vdso32/vdso32_wrapper.S
+++ b/arch/powerpc/kernel/vdso32/vdso32_wrapper.S
@@ -6,7 +6,7 @@
 	.globl vdso32_start, vdso32_end
 	.balign PAGE_SIZE
 vdso32_start:
-	.incbin "arch/powerpc/kernel/vdso32/vdso32.so"
+	.incbin "arch/powerpc/kernel/vdso32/vdso32.so.dbg"
 	.balign PAGE_SIZE
 vdso32_end:
 
diff --git a/arch/powerpc/kernel/vdso64/vdso64_wrapper.S b/arch/powerpc/kernel/vdso64/vdso64_wrapper.S
index 8df9e24..df60fca 100644
--- a/arch/powerpc/kernel/vdso64/vdso64_wrapper.S
+++ b/arch/powerpc/kernel/vdso64/vdso64_wrapper.S
@@ -6,7 +6,7 @@
 	.globl vdso64_start, vdso64_end
 	.balign PAGE_SIZE
 vdso64_start:
-	.incbin "arch/powerpc/kernel/vdso64/vdso64.so"
+	.incbin "arch/powerpc/kernel/vdso64/vdso64.so.dbg"
 	.balign PAGE_SIZE
 vdso64_end:
 
diff --git a/arch/powerpc/mm/pgtable_64.c b/arch/powerpc/mm/pgtable_64.c
index 65b7b65..62bf5e8 100644
--- a/arch/powerpc/mm/pgtable_64.c
+++ b/arch/powerpc/mm/pgtable_64.c
@@ -510,7 +510,8 @@
 }
 
 unsigned long pmd_hugepage_update(struct mm_struct *mm, unsigned long addr,
-				  pmd_t *pmdp, unsigned long clr)
+				  pmd_t *pmdp, unsigned long clr,
+				  unsigned long set)
 {
 
 	unsigned long old, tmp;
@@ -526,14 +527,15 @@
 		andi.	%1,%0,%6\n\
 		bne-	1b \n\
 		andc	%1,%0,%4 \n\
+		or	%1,%1,%7\n\
 		stdcx.	%1,0,%3 \n\
 		bne-	1b"
 	: "=&r" (old), "=&r" (tmp), "=m" (*pmdp)
-	: "r" (pmdp), "r" (clr), "m" (*pmdp), "i" (_PAGE_BUSY)
+	: "r" (pmdp), "r" (clr), "m" (*pmdp), "i" (_PAGE_BUSY), "r" (set)
 	: "cc" );
 #else
 	old = pmd_val(*pmdp);
-	*pmdp = __pmd(old & ~clr);
+	*pmdp = __pmd((old & ~clr) | set);
 #endif
 	if (old & _PAGE_HASHPTE)
 		hpte_do_hugepage_flush(mm, addr, pmdp);
@@ -708,7 +710,7 @@
 void pmdp_invalidate(struct vm_area_struct *vma, unsigned long address,
 		     pmd_t *pmdp)
 {
-	pmd_hugepage_update(vma->vm_mm, address, pmdp, _PAGE_PRESENT);
+	pmd_hugepage_update(vma->vm_mm, address, pmdp, _PAGE_PRESENT, 0);
 }
 
 /*
@@ -835,7 +837,7 @@
 	unsigned long old;
 	pgtable_t *pgtable_slot;
 
-	old = pmd_hugepage_update(mm, addr, pmdp, ~0UL);
+	old = pmd_hugepage_update(mm, addr, pmdp, ~0UL, 0);
 	old_pmd = __pmd(old);
 	/*
 	 * We have pmd == none and we are holding page_table_lock.
diff --git a/arch/powerpc/mm/subpage-prot.c b/arch/powerpc/mm/subpage-prot.c
index a770df2d..6c0b1f5 100644
--- a/arch/powerpc/mm/subpage-prot.c
+++ b/arch/powerpc/mm/subpage-prot.c
@@ -78,7 +78,7 @@
 	pte = pte_offset_map_lock(mm, pmd, addr, &ptl);
 	arch_enter_lazy_mmu_mode();
 	for (; npages > 0; --npages) {
-		pte_update(mm, addr, pte, 0, 0);
+		pte_update(mm, addr, pte, 0, 0, 0);
 		addr += PAGE_SIZE;
 		++pte;
 	}
diff --git a/arch/powerpc/platforms/powernv/eeh-ioda.c b/arch/powerpc/platforms/powernv/eeh-ioda.c
index e1e7161..253fefe 100644
--- a/arch/powerpc/platforms/powernv/eeh-ioda.c
+++ b/arch/powerpc/platforms/powernv/eeh-ioda.c
@@ -44,7 +44,8 @@
 
 	/* We simply send special EEH event */
 	if ((changed_evts & OPAL_EVENT_PCI_ERROR) &&
-	    (events & OPAL_EVENT_PCI_ERROR))
+	    (events & OPAL_EVENT_PCI_ERROR) &&
+	    eeh_enabled())
 		eeh_send_failure_event(NULL);
 
 	return 0;
@@ -113,6 +114,7 @@
 			ioda_eeh_inbB_dbgfs_set, "0x%llx\n");
 #endif /* CONFIG_DEBUG_FS */
 
+
 /**
  * ioda_eeh_post_init - Chip dependent post initialization
  * @hose: PCI controller
@@ -220,6 +222,22 @@
 	return ret;
 }
 
+static void ioda_eeh_phb_diag(struct pci_controller *hose)
+{
+	struct pnv_phb *phb = hose->private_data;
+	long rc;
+
+	rc = opal_pci_get_phb_diag_data2(phb->opal_id, phb->diag.blob,
+					 PNV_PCI_DIAG_BUF_SIZE);
+	if (rc != OPAL_SUCCESS) {
+		pr_warning("%s: Failed to get diag-data for PHB#%x (%ld)\n",
+			    __func__, hose->global_number, rc);
+		return;
+	}
+
+	pnv_pci_dump_phb_diag_data(hose, phb->diag.blob);
+}
+
 /**
  * ioda_eeh_get_state - Retrieve the state of PE
  * @pe: EEH PE
@@ -271,6 +289,9 @@
 			result |= EEH_STATE_DMA_ACTIVE;
 			result |= EEH_STATE_MMIO_ENABLED;
 			result |= EEH_STATE_DMA_ENABLED;
+		} else if (!(pe->state & EEH_PE_ISOLATED)) {
+			eeh_pe_state_mark(pe, EEH_PE_ISOLATED);
+			ioda_eeh_phb_diag(hose);
 		}
 
 		return result;
@@ -314,6 +335,15 @@
 			   __func__, fstate, hose->global_number, pe_no);
 	}
 
+	/* Dump PHB diag-data for frozen PE */
+	if (result != EEH_STATE_NOT_SUPPORT &&
+	    (result & (EEH_STATE_MMIO_ACTIVE | EEH_STATE_DMA_ACTIVE)) !=
+	    (EEH_STATE_MMIO_ACTIVE | EEH_STATE_DMA_ACTIVE) &&
+	    !(pe->state & EEH_PE_ISOLATED)) {
+		eeh_pe_state_mark(pe, EEH_PE_ISOLATED);
+		ioda_eeh_phb_diag(hose);
+	}
+
 	return result;
 }
 
@@ -489,8 +519,7 @@
 static int ioda_eeh_reset(struct eeh_pe *pe, int option)
 {
 	struct pci_controller *hose = pe->phb;
-	struct eeh_dev *edev;
-	struct pci_dev *dev;
+	struct pci_bus *bus;
 	int ret;
 
 	/*
@@ -519,73 +548,17 @@
 	if (pe->type & EEH_PE_PHB) {
 		ret = ioda_eeh_phb_reset(hose, option);
 	} else {
-		if (pe->type & EEH_PE_DEVICE) {
-			/*
-			 * If it's device PE, we didn't refer to the parent
-			 * PCI bus yet. So we have to figure it out indirectly.
-			 */
-			edev = list_first_entry(&pe->edevs,
-					struct eeh_dev, list);
-			dev = eeh_dev_to_pci_dev(edev);
-			dev = dev->bus->self;
-		} else {
-			/*
-			 * If it's bus PE, the parent PCI bus is already there
-			 * and just pick it up.
-			 */
-			dev = pe->bus->self;
-		}
-
-		/*
-		 * Do reset based on the fact that the direct upstream bridge
-		 * is root bridge (port) or not.
-		 */
-		if (dev->bus->number == 0)
+		bus = eeh_pe_bus_get(pe);
+		if (pci_is_root_bus(bus))
 			ret = ioda_eeh_root_reset(hose, option);
 		else
-			ret = ioda_eeh_bridge_reset(hose, dev, option);
+			ret = ioda_eeh_bridge_reset(hose, bus->self, option);
 	}
 
 	return ret;
 }
 
 /**
- * ioda_eeh_get_log - Retrieve error log
- * @pe: EEH PE
- * @severity: Severity level of the log
- * @drv_log: buffer to store the log
- * @len: space of the log buffer
- *
- * The function is used to retrieve error log from P7IOC.
- */
-static int ioda_eeh_get_log(struct eeh_pe *pe, int severity,
-			    char *drv_log, unsigned long len)
-{
-	s64 ret;
-	unsigned long flags;
-	struct pci_controller *hose = pe->phb;
-	struct pnv_phb *phb = hose->private_data;
-
-	spin_lock_irqsave(&phb->lock, flags);
-
-	ret = opal_pci_get_phb_diag_data2(phb->opal_id,
-			phb->diag.blob, PNV_PCI_DIAG_BUF_SIZE);
-	if (ret) {
-		spin_unlock_irqrestore(&phb->lock, flags);
-		pr_warning("%s: Can't get log for PHB#%x-PE#%x (%lld)\n",
-			   __func__, hose->global_number, pe->addr, ret);
-		return -EIO;
-	}
-
-	/* The PHB diag-data is always indicative */
-	pnv_pci_dump_phb_diag_data(hose, phb->diag.blob);
-
-	spin_unlock_irqrestore(&phb->lock, flags);
-
-	return 0;
-}
-
-/**
  * ioda_eeh_configure_bridge - Configure the PCI bridges for the indicated PE
  * @pe: EEH PE
  *
@@ -666,22 +639,6 @@
 	}
 }
 
-static void ioda_eeh_phb_diag(struct pci_controller *hose)
-{
-	struct pnv_phb *phb = hose->private_data;
-	long rc;
-
-	rc = opal_pci_get_phb_diag_data2(phb->opal_id, phb->diag.blob,
-					 PNV_PCI_DIAG_BUF_SIZE);
-	if (rc != OPAL_SUCCESS) {
-		pr_warning("%s: Failed to get diag-data for PHB#%x (%ld)\n",
-			    __func__, hose->global_number, rc);
-		return;
-	}
-
-	pnv_pci_dump_phb_diag_data(hose, phb->diag.blob);
-}
-
 static int ioda_eeh_get_phb_pe(struct pci_controller *hose,
 			       struct eeh_pe **pe)
 {
@@ -855,6 +812,20 @@
 		}
 
 		/*
+		 * EEH core will try recover from fenced PHB or
+		 * frozen PE. In the time for frozen PE, EEH core
+		 * enable IO path for that before collecting logs,
+		 * but it ruins the site. So we have to dump the
+		 * log in advance here.
+		 */
+		if ((ret == EEH_NEXT_ERR_FROZEN_PE  ||
+		    ret == EEH_NEXT_ERR_FENCED_PHB) &&
+		    !((*pe)->state & EEH_PE_ISOLATED)) {
+			eeh_pe_state_mark(*pe, EEH_PE_ISOLATED);
+			ioda_eeh_phb_diag(hose);
+		}
+
+		/*
 		 * If we have no errors on the specific PHB or only
 		 * informative error there, we continue poking it.
 		 * Otherwise, we need actions to be taken by upper
@@ -872,7 +843,6 @@
 	.set_option		= ioda_eeh_set_option,
 	.get_state		= ioda_eeh_get_state,
 	.reset			= ioda_eeh_reset,
-	.get_log		= ioda_eeh_get_log,
 	.configure_bridge	= ioda_eeh_configure_bridge,
 	.next_error		= ioda_eeh_next_error
 };
diff --git a/arch/powerpc/platforms/powernv/eeh-powernv.c b/arch/powerpc/platforms/powernv/eeh-powernv.c
index a79fddc..a59788e 100644
--- a/arch/powerpc/platforms/powernv/eeh-powernv.c
+++ b/arch/powerpc/platforms/powernv/eeh-powernv.c
@@ -145,7 +145,7 @@
 	 * Enable EEH explicitly so that we will do EEH check
 	 * while accessing I/O stuff
 	 */
-	eeh_subsystem_enabled = 1;
+	eeh_set_enable(true);
 
 	/* Save memory bars */
 	eeh_save_bars(edev);
diff --git a/arch/powerpc/platforms/powernv/opal-xscom.c b/arch/powerpc/platforms/powernv/opal-xscom.c
index 4fbf276..4cd2ea6 100644
--- a/arch/powerpc/platforms/powernv/opal-xscom.c
+++ b/arch/powerpc/platforms/powernv/opal-xscom.c
@@ -71,11 +71,11 @@
 	}
 }
 
-static u64 opal_scom_unmangle(u64 reg)
+static u64 opal_scom_unmangle(u64 addr)
 {
 	/*
 	 * XSCOM indirect addresses have the top bit set. Additionally
-	 * the reset of the top 3 nibbles is always 0.
+	 * the rest of the top 3 nibbles is always 0.
 	 *
 	 * Because the debugfs interface uses signed offsets and shifts
 	 * the address left by 3, we basically cannot use the top 4 bits
@@ -86,10 +86,13 @@
 	 * conversion here. To leave room for further xscom address
 	 * expansion, we only clear out the top byte
 	 *
+	 * For in-kernel use, we also support the real indirect bit, so
+	 * we test for any of the top 5 bits
+	 *
 	 */
-	if (reg & (1ull << 59))
-		reg = (reg & ~(0xffull << 56)) | (1ull << 63);
-	return reg;
+	if (addr & (0x1full << 59))
+		addr = (addr & ~(0xffull << 56)) | (1ull << 63);
+	return addr;
 }
 
 static int opal_scom_read(scom_map_t map, u64 reg, u64 *value)
@@ -98,8 +101,8 @@
 	int64_t rc;
 	__be64 v;
 
-	reg = opal_scom_unmangle(reg);
-	rc = opal_xscom_read(m->chip, m->addr + reg, (__be64 *)__pa(&v));
+	reg = opal_scom_unmangle(m->addr + reg);
+	rc = opal_xscom_read(m->chip, reg, (__be64 *)__pa(&v));
 	*value = be64_to_cpu(v);
 	return opal_xscom_err_xlate(rc);
 }
@@ -109,8 +112,8 @@
 	struct opal_scom_map *m = map;
 	int64_t rc;
 
-	reg = opal_scom_unmangle(reg);
-	rc = opal_xscom_write(m->chip, m->addr + reg, value);
+	reg = opal_scom_unmangle(m->addr + reg);
+	rc = opal_xscom_write(m->chip, reg, value);
 	return opal_xscom_err_xlate(rc);
 }
 
diff --git a/arch/powerpc/platforms/powernv/pci.c b/arch/powerpc/platforms/powernv/pci.c
index 95633d7..8518817 100644
--- a/arch/powerpc/platforms/powernv/pci.c
+++ b/arch/powerpc/platforms/powernv/pci.c
@@ -134,57 +134,72 @@
 	pr_info("P7IOC PHB#%d Diag-data (Version: %d)\n\n",
 		hose->global_number, common->version);
 
-	pr_info("  brdgCtl:              %08x\n", data->brdgCtl);
-
-	pr_info("  portStatusReg:        %08x\n", data->portStatusReg);
-	pr_info("  rootCmplxStatus:      %08x\n", data->rootCmplxStatus);
-	pr_info("  busAgentStatus:       %08x\n", data->busAgentStatus);
-
-	pr_info("  deviceStatus:         %08x\n", data->deviceStatus);
-	pr_info("  slotStatus:           %08x\n", data->slotStatus);
-	pr_info("  linkStatus:           %08x\n", data->linkStatus);
-	pr_info("  devCmdStatus:         %08x\n", data->devCmdStatus);
-	pr_info("  devSecStatus:         %08x\n", data->devSecStatus);
-
-	pr_info("  rootErrorStatus:      %08x\n", data->rootErrorStatus);
-	pr_info("  uncorrErrorStatus:    %08x\n", data->uncorrErrorStatus);
-	pr_info("  corrErrorStatus:      %08x\n", data->corrErrorStatus);
-	pr_info("  tlpHdr1:              %08x\n", data->tlpHdr1);
-	pr_info("  tlpHdr2:              %08x\n", data->tlpHdr2);
-	pr_info("  tlpHdr3:              %08x\n", data->tlpHdr3);
-	pr_info("  tlpHdr4:              %08x\n", data->tlpHdr4);
-	pr_info("  sourceId:             %08x\n", data->sourceId);
-	pr_info("  errorClass:           %016llx\n", data->errorClass);
-	pr_info("  correlator:           %016llx\n", data->correlator);
-	pr_info("  p7iocPlssr:           %016llx\n", data->p7iocPlssr);
-	pr_info("  p7iocCsr:             %016llx\n", data->p7iocCsr);
-	pr_info("  lemFir:               %016llx\n", data->lemFir);
-	pr_info("  lemErrorMask:         %016llx\n", data->lemErrorMask);
-	pr_info("  lemWOF:               %016llx\n", data->lemWOF);
-	pr_info("  phbErrorStatus:       %016llx\n", data->phbErrorStatus);
-	pr_info("  phbFirstErrorStatus:  %016llx\n", data->phbFirstErrorStatus);
-	pr_info("  phbErrorLog0:         %016llx\n", data->phbErrorLog0);
-	pr_info("  phbErrorLog1:         %016llx\n", data->phbErrorLog1);
-	pr_info("  mmioErrorStatus:      %016llx\n", data->mmioErrorStatus);
-	pr_info("  mmioFirstErrorStatus: %016llx\n", data->mmioFirstErrorStatus);
-	pr_info("  mmioErrorLog0:        %016llx\n", data->mmioErrorLog0);
-	pr_info("  mmioErrorLog1:        %016llx\n", data->mmioErrorLog1);
-	pr_info("  dma0ErrorStatus:      %016llx\n", data->dma0ErrorStatus);
-	pr_info("  dma0FirstErrorStatus: %016llx\n", data->dma0FirstErrorStatus);
-	pr_info("  dma0ErrorLog0:        %016llx\n", data->dma0ErrorLog0);
-	pr_info("  dma0ErrorLog1:        %016llx\n", data->dma0ErrorLog1);
-	pr_info("  dma1ErrorStatus:      %016llx\n", data->dma1ErrorStatus);
-	pr_info("  dma1FirstErrorStatus: %016llx\n", data->dma1FirstErrorStatus);
-	pr_info("  dma1ErrorLog0:        %016llx\n", data->dma1ErrorLog0);
-	pr_info("  dma1ErrorLog1:        %016llx\n", data->dma1ErrorLog1);
+	if (data->brdgCtl)
+		pr_info("  brdgCtl:     %08x\n",
+			data->brdgCtl);
+	if (data->portStatusReg || data->rootCmplxStatus ||
+	    data->busAgentStatus)
+		pr_info("  UtlSts:      %08x %08x %08x\n",
+			data->portStatusReg, data->rootCmplxStatus,
+			data->busAgentStatus);
+	if (data->deviceStatus || data->slotStatus   ||
+	    data->linkStatus   || data->devCmdStatus ||
+	    data->devSecStatus)
+		pr_info("  RootSts:     %08x %08x %08x %08x %08x\n",
+			data->deviceStatus, data->slotStatus,
+			data->linkStatus, data->devCmdStatus,
+			data->devSecStatus);
+	if (data->rootErrorStatus   || data->uncorrErrorStatus ||
+	    data->corrErrorStatus)
+		pr_info("  RootErrSts:  %08x %08x %08x\n",
+			data->rootErrorStatus, data->uncorrErrorStatus,
+			data->corrErrorStatus);
+	if (data->tlpHdr1 || data->tlpHdr2 ||
+	    data->tlpHdr3 || data->tlpHdr4)
+		pr_info("  RootErrLog:  %08x %08x %08x %08x\n",
+			data->tlpHdr1, data->tlpHdr2,
+			data->tlpHdr3, data->tlpHdr4);
+	if (data->sourceId || data->errorClass ||
+	    data->correlator)
+		pr_info("  RootErrLog1: %08x %016llx %016llx\n",
+			data->sourceId, data->errorClass,
+			data->correlator);
+	if (data->p7iocPlssr || data->p7iocCsr)
+		pr_info("  PhbSts:      %016llx %016llx\n",
+			data->p7iocPlssr, data->p7iocCsr);
+	if (data->lemFir || data->lemErrorMask ||
+	    data->lemWOF)
+		pr_info("  Lem:         %016llx %016llx %016llx\n",
+			data->lemFir, data->lemErrorMask,
+			data->lemWOF);
+	if (data->phbErrorStatus || data->phbFirstErrorStatus ||
+	    data->phbErrorLog0   || data->phbErrorLog1)
+		pr_info("  PhbErr:      %016llx %016llx %016llx %016llx\n",
+			data->phbErrorStatus, data->phbFirstErrorStatus,
+			data->phbErrorLog0, data->phbErrorLog1);
+	if (data->mmioErrorStatus || data->mmioFirstErrorStatus ||
+	    data->mmioErrorLog0   || data->mmioErrorLog1)
+		pr_info("  OutErr:      %016llx %016llx %016llx %016llx\n",
+			data->mmioErrorStatus, data->mmioFirstErrorStatus,
+			data->mmioErrorLog0, data->mmioErrorLog1);
+	if (data->dma0ErrorStatus || data->dma0FirstErrorStatus ||
+	    data->dma0ErrorLog0   || data->dma0ErrorLog1)
+		pr_info("  InAErr:      %016llx %016llx %016llx %016llx\n",
+			data->dma0ErrorStatus, data->dma0FirstErrorStatus,
+			data->dma0ErrorLog0, data->dma0ErrorLog1);
+	if (data->dma1ErrorStatus || data->dma1FirstErrorStatus ||
+	    data->dma1ErrorLog0   || data->dma1ErrorLog1)
+		pr_info("  InBErr:      %016llx %016llx %016llx %016llx\n",
+			data->dma1ErrorStatus, data->dma1FirstErrorStatus,
+			data->dma1ErrorLog0, data->dma1ErrorLog1);
 
 	for (i = 0; i < OPAL_P7IOC_NUM_PEST_REGS; i++) {
 		if ((data->pestA[i] >> 63) == 0 &&
 		    (data->pestB[i] >> 63) == 0)
 			continue;
 
-		pr_info("  PE[%3d] PESTA:        %016llx\n", i, data->pestA[i]);
-		pr_info("          PESTB:        %016llx\n", data->pestB[i]);
+		pr_info("  PE[%3d] A/B: %016llx %016llx\n",
+			i, data->pestA[i], data->pestB[i]);
 	}
 }
 
@@ -197,62 +212,77 @@
 	data = (struct OpalIoPhb3ErrorData*)common;
 	pr_info("PHB3 PHB#%d Diag-data (Version: %d)\n\n",
 		hose->global_number, common->version);
-
-	pr_info("  brdgCtl:              %08x\n", data->brdgCtl);
-
-	pr_info("  portStatusReg:        %08x\n", data->portStatusReg);
-	pr_info("  rootCmplxStatus:      %08x\n", data->rootCmplxStatus);
-	pr_info("  busAgentStatus:       %08x\n", data->busAgentStatus);
-
-	pr_info("  deviceStatus:         %08x\n", data->deviceStatus);
-	pr_info("  slotStatus:           %08x\n", data->slotStatus);
-	pr_info("  linkStatus:           %08x\n", data->linkStatus);
-	pr_info("  devCmdStatus:         %08x\n", data->devCmdStatus);
-	pr_info("  devSecStatus:         %08x\n", data->devSecStatus);
-
-	pr_info("  rootErrorStatus:      %08x\n", data->rootErrorStatus);
-	pr_info("  uncorrErrorStatus:    %08x\n", data->uncorrErrorStatus);
-	pr_info("  corrErrorStatus:      %08x\n", data->corrErrorStatus);
-	pr_info("  tlpHdr1:              %08x\n", data->tlpHdr1);
-	pr_info("  tlpHdr2:              %08x\n", data->tlpHdr2);
-	pr_info("  tlpHdr3:              %08x\n", data->tlpHdr3);
-	pr_info("  tlpHdr4:              %08x\n", data->tlpHdr4);
-	pr_info("  sourceId:             %08x\n", data->sourceId);
-	pr_info("  errorClass:           %016llx\n", data->errorClass);
-	pr_info("  correlator:           %016llx\n", data->correlator);
-
-	pr_info("  nFir:                 %016llx\n", data->nFir);
-	pr_info("  nFirMask:             %016llx\n", data->nFirMask);
-	pr_info("  nFirWOF:              %016llx\n", data->nFirWOF);
-	pr_info("  PhbPlssr:             %016llx\n", data->phbPlssr);
-	pr_info("  PhbCsr:               %016llx\n", data->phbCsr);
-	pr_info("  lemFir:               %016llx\n", data->lemFir);
-	pr_info("  lemErrorMask:         %016llx\n", data->lemErrorMask);
-	pr_info("  lemWOF:               %016llx\n", data->lemWOF);
-	pr_info("  phbErrorStatus:       %016llx\n", data->phbErrorStatus);
-	pr_info("  phbFirstErrorStatus:  %016llx\n", data->phbFirstErrorStatus);
-	pr_info("  phbErrorLog0:         %016llx\n", data->phbErrorLog0);
-	pr_info("  phbErrorLog1:         %016llx\n", data->phbErrorLog1);
-	pr_info("  mmioErrorStatus:      %016llx\n", data->mmioErrorStatus);
-	pr_info("  mmioFirstErrorStatus: %016llx\n", data->mmioFirstErrorStatus);
-	pr_info("  mmioErrorLog0:        %016llx\n", data->mmioErrorLog0);
-	pr_info("  mmioErrorLog1:        %016llx\n", data->mmioErrorLog1);
-	pr_info("  dma0ErrorStatus:      %016llx\n", data->dma0ErrorStatus);
-	pr_info("  dma0FirstErrorStatus: %016llx\n", data->dma0FirstErrorStatus);
-	pr_info("  dma0ErrorLog0:        %016llx\n", data->dma0ErrorLog0);
-	pr_info("  dma0ErrorLog1:        %016llx\n", data->dma0ErrorLog1);
-	pr_info("  dma1ErrorStatus:      %016llx\n", data->dma1ErrorStatus);
-	pr_info("  dma1FirstErrorStatus: %016llx\n", data->dma1FirstErrorStatus);
-	pr_info("  dma1ErrorLog0:        %016llx\n", data->dma1ErrorLog0);
-	pr_info("  dma1ErrorLog1:        %016llx\n", data->dma1ErrorLog1);
+	if (data->brdgCtl)
+		pr_info("  brdgCtl:     %08x\n",
+			data->brdgCtl);
+	if (data->portStatusReg || data->rootCmplxStatus ||
+	    data->busAgentStatus)
+		pr_info("  UtlSts:      %08x %08x %08x\n",
+			data->portStatusReg, data->rootCmplxStatus,
+			data->busAgentStatus);
+	if (data->deviceStatus || data->slotStatus   ||
+	    data->linkStatus   || data->devCmdStatus ||
+	    data->devSecStatus)
+		pr_info("  RootSts:     %08x %08x %08x %08x %08x\n",
+			data->deviceStatus, data->slotStatus,
+			data->linkStatus, data->devCmdStatus,
+			data->devSecStatus);
+	if (data->rootErrorStatus || data->uncorrErrorStatus ||
+	    data->corrErrorStatus)
+		pr_info("  RootErrSts:  %08x %08x %08x\n",
+			data->rootErrorStatus, data->uncorrErrorStatus,
+			data->corrErrorStatus);
+	if (data->tlpHdr1 || data->tlpHdr2 ||
+	    data->tlpHdr3 || data->tlpHdr4)
+		pr_info("  RootErrLog:  %08x %08x %08x %08x\n",
+			data->tlpHdr1, data->tlpHdr2,
+			data->tlpHdr3, data->tlpHdr4);
+	if (data->sourceId || data->errorClass ||
+	    data->correlator)
+		pr_info("  RootErrLog1: %08x %016llx %016llx\n",
+			data->sourceId, data->errorClass,
+			data->correlator);
+	if (data->nFir || data->nFirMask ||
+	    data->nFirWOF)
+		pr_info("  nFir:        %016llx %016llx %016llx\n",
+			data->nFir, data->nFirMask,
+			data->nFirWOF);
+	if (data->phbPlssr || data->phbCsr)
+		pr_info("  PhbSts:      %016llx %016llx\n",
+			data->phbPlssr, data->phbCsr);
+	if (data->lemFir || data->lemErrorMask ||
+	    data->lemWOF)
+		pr_info("  Lem:         %016llx %016llx %016llx\n",
+			data->lemFir, data->lemErrorMask,
+			data->lemWOF);
+	if (data->phbErrorStatus || data->phbFirstErrorStatus ||
+	    data->phbErrorLog0   || data->phbErrorLog1)
+		pr_info("  PhbErr:      %016llx %016llx %016llx %016llx\n",
+			data->phbErrorStatus, data->phbFirstErrorStatus,
+			data->phbErrorLog0, data->phbErrorLog1);
+	if (data->mmioErrorStatus || data->mmioFirstErrorStatus ||
+	    data->mmioErrorLog0   || data->mmioErrorLog1)
+		pr_info("  OutErr:      %016llx %016llx %016llx %016llx\n",
+			data->mmioErrorStatus, data->mmioFirstErrorStatus,
+			data->mmioErrorLog0, data->mmioErrorLog1);
+	if (data->dma0ErrorStatus || data->dma0FirstErrorStatus ||
+	    data->dma0ErrorLog0   || data->dma0ErrorLog1)
+		pr_info("  InAErr:      %016llx %016llx %016llx %016llx\n",
+			data->dma0ErrorStatus, data->dma0FirstErrorStatus,
+			data->dma0ErrorLog0, data->dma0ErrorLog1);
+	if (data->dma1ErrorStatus || data->dma1FirstErrorStatus ||
+	    data->dma1ErrorLog0   || data->dma1ErrorLog1)
+		pr_info("  InBErr:      %016llx %016llx %016llx %016llx\n",
+			data->dma1ErrorStatus, data->dma1FirstErrorStatus,
+			data->dma1ErrorLog0, data->dma1ErrorLog1);
 
 	for (i = 0; i < OPAL_PHB3_NUM_PEST_REGS; i++) {
 		if ((data->pestA[i] >> 63) == 0 &&
 		    (data->pestB[i] >> 63) == 0)
 			continue;
 
-		pr_info("  PE[%3d] PESTA:        %016llx\n", i, data->pestA[i]);
-		pr_info("          PESTB:        %016llx\n", data->pestB[i]);
+		pr_info("  PE[%3d] A/B: %016llx %016llx\n",
+			i, data->pestA[i], data->pestB[i]);
 	}
 }
 
diff --git a/arch/powerpc/platforms/pseries/eeh_pseries.c b/arch/powerpc/platforms/pseries/eeh_pseries.c
index 9ef3cc8..8a8f047 100644
--- a/arch/powerpc/platforms/pseries/eeh_pseries.c
+++ b/arch/powerpc/platforms/pseries/eeh_pseries.c
@@ -265,7 +265,7 @@
 			enable = 1;
 
 		if (enable) {
-			eeh_subsystem_enabled = 1;
+			eeh_set_enable(true);
 			eeh_add_to_parent_pe(edev);
 
 			pr_debug("%s: EEH enabled on %s PHB#%d-PE#%x, config addr#%x\n",
diff --git a/arch/powerpc/platforms/pseries/hotplug-cpu.c b/arch/powerpc/platforms/pseries/hotplug-cpu.c
index 82789e7..0ea99e3 100644
--- a/arch/powerpc/platforms/pseries/hotplug-cpu.c
+++ b/arch/powerpc/platforms/pseries/hotplug-cpu.c
@@ -35,12 +35,7 @@
 #include "offline_states.h"
 
 /* This version can't take the spinlock, because it never returns */
-static struct rtas_args rtas_stop_self_args = {
-	.token = RTAS_UNKNOWN_SERVICE,
-	.nargs = 0,
-	.nret = 1,
-	.rets = &rtas_stop_self_args.args[0],
-};
+static int rtas_stop_self_token = RTAS_UNKNOWN_SERVICE;
 
 static DEFINE_PER_CPU(enum cpu_state_vals, preferred_offline_state) =
 							CPU_STATE_OFFLINE;
@@ -93,15 +88,20 @@
 
 static void rtas_stop_self(void)
 {
-	struct rtas_args *args = &rtas_stop_self_args;
+	struct rtas_args args = {
+		.token = cpu_to_be32(rtas_stop_self_token),
+		.nargs = 0,
+		.nret = 1,
+		.rets = &args.args[0],
+	};
 
 	local_irq_disable();
 
-	BUG_ON(args->token == RTAS_UNKNOWN_SERVICE);
+	BUG_ON(rtas_stop_self_token == RTAS_UNKNOWN_SERVICE);
 
 	printk("cpu %u (hwid %u) Ready to die...\n",
 	       smp_processor_id(), hard_smp_processor_id());
-	enter_rtas(__pa(args));
+	enter_rtas(__pa(&args));
 
 	panic("Alas, I survived.\n");
 }
@@ -392,10 +392,10 @@
 		}
 	}
 
-	rtas_stop_self_args.token = rtas_token("stop-self");
+	rtas_stop_self_token = rtas_token("stop-self");
 	qcss_tok = rtas_token("query-cpu-stopped-state");
 
-	if (rtas_stop_self_args.token == RTAS_UNKNOWN_SERVICE ||
+	if (rtas_stop_self_token == RTAS_UNKNOWN_SERVICE ||
 			qcss_tok == RTAS_UNKNOWN_SERVICE) {
 		printk(KERN_INFO "CPU Hotplug not supported by firmware "
 				"- disabling.\n");
diff --git a/arch/powerpc/platforms/pseries/pci.c b/arch/powerpc/platforms/pseries/pci.c
index 70670a2..c413ec1 100644
--- a/arch/powerpc/platforms/pseries/pci.c
+++ b/arch/powerpc/platforms/pseries/pci.c
@@ -113,7 +113,8 @@
 {
 	struct device_node *dn, *pdn;
 	struct pci_bus *bus;
-	const __be32 *pcie_link_speed_stats;
+	u32 pcie_link_speed_stats[2];
+	int rc;
 
 	bus = bridge->bus;
 
@@ -122,38 +123,45 @@
 		return 0;
 
 	for (pdn = dn; pdn != NULL; pdn = of_get_next_parent(pdn)) {
-		pcie_link_speed_stats = of_get_property(pdn,
-			"ibm,pcie-link-speed-stats", NULL);
-		if (pcie_link_speed_stats)
+		rc = of_property_read_u32_array(pdn,
+				"ibm,pcie-link-speed-stats",
+				&pcie_link_speed_stats[0], 2);
+		if (!rc)
 			break;
 	}
 
 	of_node_put(pdn);
 
-	if (!pcie_link_speed_stats) {
+	if (rc) {
 		pr_err("no ibm,pcie-link-speed-stats property\n");
 		return 0;
 	}
 
-	switch (be32_to_cpup(pcie_link_speed_stats)) {
+	switch (pcie_link_speed_stats[0]) {
 	case 0x01:
 		bus->max_bus_speed = PCIE_SPEED_2_5GT;
 		break;
 	case 0x02:
 		bus->max_bus_speed = PCIE_SPEED_5_0GT;
 		break;
+	case 0x04:
+		bus->max_bus_speed = PCIE_SPEED_8_0GT;
+		break;
 	default:
 		bus->max_bus_speed = PCI_SPEED_UNKNOWN;
 		break;
 	}
 
-	switch (be32_to_cpup(pcie_link_speed_stats)) {
+	switch (pcie_link_speed_stats[1]) {
 	case 0x01:
 		bus->cur_bus_speed = PCIE_SPEED_2_5GT;
 		break;
 	case 0x02:
 		bus->cur_bus_speed = PCIE_SPEED_5_0GT;
 		break;
+	case 0x04:
+		bus->cur_bus_speed = PCIE_SPEED_8_0GT;
+		break;
 	default:
 		bus->cur_bus_speed = PCI_SPEED_UNKNOWN;
 		break;
diff --git a/arch/s390/kernel/compat_wrapper.S b/arch/s390/kernel/compat_wrapper.S
index 59c8efc..0248949 100644
--- a/arch/s390/kernel/compat_wrapper.S
+++ b/arch/s390/kernel/compat_wrapper.S
@@ -1421,5 +1421,5 @@
 ENTRY(sys_sched_getattr_wrapper)
 	lgfr	%r2,%r2			# pid_t
 	llgtr	%r3,%r3			# const char __user *
-	llgfr	%r3,%r3			# unsigned int
+	llgfr	%r4,%r4			# unsigned int
 	jg	sys_sched_getattr
diff --git a/arch/s390/pci/pci_dma.c b/arch/s390/pci/pci_dma.c
index 60c11a6..f91c031 100644
--- a/arch/s390/pci/pci_dma.c
+++ b/arch/s390/pci/pci_dma.c
@@ -206,11 +206,13 @@
 	zdev->dma_table = NULL;
 }
 
-static unsigned long __dma_alloc_iommu(struct zpci_dev *zdev, unsigned long start,
-				   int size)
+static unsigned long __dma_alloc_iommu(struct zpci_dev *zdev,
+				       unsigned long start, int size)
 {
-	unsigned long boundary_size = 0x1000000;
+	unsigned long boundary_size;
 
+	boundary_size = ALIGN(dma_get_seg_boundary(&zdev->pdev->dev) + 1,
+			      PAGE_SIZE) >> PAGE_SHIFT;
 	return iommu_area_alloc(zdev->iommu_bitmap, zdev->iommu_pages,
 				start, size, 0, boundary_size, 0);
 }
diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig
index c51efdc..7d8b7e9 100644
--- a/arch/sparc/Kconfig
+++ b/arch/sparc/Kconfig
@@ -27,7 +27,7 @@
 	select RTC_DRV_M48T59
 	select HAVE_DMA_ATTRS
 	select HAVE_DMA_API_DEBUG
-	select HAVE_ARCH_JUMP_LABEL
+	select HAVE_ARCH_JUMP_LABEL if SPARC64
 	select GENERIC_IRQ_SHOW
 	select ARCH_WANT_IPC_PARSE_VERSION
 	select GENERIC_PCI_IOMAP
diff --git a/arch/sparc/mm/srmmu.c b/arch/sparc/mm/srmmu.c
index 869023a..cfbe53c 100644
--- a/arch/sparc/mm/srmmu.c
+++ b/arch/sparc/mm/srmmu.c
@@ -14,6 +14,7 @@
 #include <linux/pagemap.h>
 #include <linux/vmalloc.h>
 #include <linux/kdebug.h>
+#include <linux/export.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/log2.h>
@@ -62,6 +63,7 @@
 static pgd_t *srmmu_swapper_pg_dir;
 
 const struct sparc32_cachetlb_ops *sparc32_cachetlb_ops;
+EXPORT_SYMBOL(sparc32_cachetlb_ops);
 
 #ifdef CONFIG_SMP
 const struct sparc32_cachetlb_ops *local_ops;
diff --git a/arch/x86/boot/compressed/aslr.c b/arch/x86/boot/compressed/aslr.c
index 90a21f4..4dbf967 100644
--- a/arch/x86/boot/compressed/aslr.c
+++ b/arch/x86/boot/compressed/aslr.c
@@ -111,7 +111,7 @@
 };
 
 #define MEM_AVOID_MAX 5
-struct mem_vector mem_avoid[MEM_AVOID_MAX];
+static struct mem_vector mem_avoid[MEM_AVOID_MAX];
 
 static bool mem_contains(struct mem_vector *region, struct mem_vector *item)
 {
@@ -180,7 +180,7 @@
 }
 
 /* Does this memory vector overlap a known avoided area? */
-bool mem_avoid_overlap(struct mem_vector *img)
+static bool mem_avoid_overlap(struct mem_vector *img)
 {
 	int i;
 
@@ -192,8 +192,9 @@
 	return false;
 }
 
-unsigned long slots[CONFIG_RANDOMIZE_BASE_MAX_OFFSET / CONFIG_PHYSICAL_ALIGN];
-unsigned long slot_max = 0;
+static unsigned long slots[CONFIG_RANDOMIZE_BASE_MAX_OFFSET /
+			   CONFIG_PHYSICAL_ALIGN];
+static unsigned long slot_max;
 
 static void slots_append(unsigned long addr)
 {
diff --git a/arch/x86/include/asm/tsc.h b/arch/x86/include/asm/tsc.h
index 57ae63c..94605c0 100644
--- a/arch/x86/include/asm/tsc.h
+++ b/arch/x86/include/asm/tsc.h
@@ -66,6 +66,6 @@
 extern void tsc_restore_sched_clock_state(void);
 
 /* MSR based TSC calibration for Intel Atom SoC platforms */
-int try_msr_calibrate_tsc(unsigned long *fast_calibrate);
+unsigned long try_msr_calibrate_tsc(void);
 
 #endif /* _ASM_X86_TSC_H */
diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c
index b886451..79f9f84 100644
--- a/arch/x86/kernel/cpu/perf_event.c
+++ b/arch/x86/kernel/cpu/perf_event.c
@@ -1192,6 +1192,9 @@
 	for (i = 0; i < cpuc->n_events; i++) {
 		if (event == cpuc->event_list[i]) {
 
+			if (i >= cpuc->n_events - cpuc->n_added)
+				--cpuc->n_added;
+
 			if (x86_pmu.put_event_constraints)
 				x86_pmu.put_event_constraints(cpuc, event);
 
@@ -1521,6 +1524,8 @@
 
 	pr_cont("%s PMU driver.\n", x86_pmu.name);
 
+	x86_pmu.attr_rdpmc = 1; /* enable userspace RDPMC usage by default */
+
 	for (quirk = x86_pmu.quirks; quirk; quirk = quirk->next)
 		quirk->func();
 
@@ -1534,7 +1539,6 @@
 		__EVENT_CONSTRAINT(0, (1ULL << x86_pmu.num_counters) - 1,
 				   0, x86_pmu.num_counters, 0, 0);
 
-	x86_pmu.attr_rdpmc = 1; /* enable userspace RDPMC usage by default */
 	x86_pmu_format_group.attrs = x86_pmu.format_attrs;
 
 	if (x86_pmu.event_attrs)
@@ -1820,9 +1824,12 @@
 	if (ret)
 		return ret;
 
+	if (x86_pmu.attr_rdpmc_broken)
+		return -ENOTSUPP;
+
 	if (!!val != !!x86_pmu.attr_rdpmc) {
 		x86_pmu.attr_rdpmc = !!val;
-		smp_call_function(change_rdpmc, (void *)val, 1);
+		on_each_cpu(change_rdpmc, (void *)val, 1);
 	}
 
 	return count;
diff --git a/arch/x86/kernel/cpu/perf_event.h b/arch/x86/kernel/cpu/perf_event.h
index c1a8618..4972c24 100644
--- a/arch/x86/kernel/cpu/perf_event.h
+++ b/arch/x86/kernel/cpu/perf_event.h
@@ -409,6 +409,7 @@
 	/*
 	 * sysfs attrs
 	 */
+	int		attr_rdpmc_broken;
 	int		attr_rdpmc;
 	struct attribute **format_attrs;
 	struct attribute **event_attrs;
diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c
index 0fa4f24..aa333d9 100644
--- a/arch/x86/kernel/cpu/perf_event_intel.c
+++ b/arch/x86/kernel/cpu/perf_event_intel.c
@@ -1361,10 +1361,8 @@
 	intel_pmu_disable_all();
 	handled = intel_pmu_drain_bts_buffer();
 	status = intel_pmu_get_status();
-	if (!status) {
-		intel_pmu_enable_all(0);
-		return handled;
-	}
+	if (!status)
+		goto done;
 
 	loops = 0;
 again:
@@ -2310,10 +2308,7 @@
 	if (version > 1)
 		x86_pmu.num_counters_fixed = max((int)edx.split.num_counters_fixed, 3);
 
-	/*
-	 * v2 and above have a perf capabilities MSR
-	 */
-	if (version > 1) {
+	if (boot_cpu_has(X86_FEATURE_PDCM)) {
 		u64 capabilities;
 
 		rdmsrl(MSR_IA32_PERF_CAPABILITIES, capabilities);
diff --git a/arch/x86/kernel/cpu/perf_event_intel_uncore.c b/arch/x86/kernel/cpu/perf_event_intel_uncore.c
index 29c2487..c88f7f4 100644
--- a/arch/x86/kernel/cpu/perf_event_intel_uncore.c
+++ b/arch/x86/kernel/cpu/perf_event_intel_uncore.c
@@ -501,8 +501,11 @@
 	SNBEP_CBO_EVENT_EXTRA_REG(SNBEP_CBO_PMON_CTL_TID_EN,
 				  SNBEP_CBO_PMON_CTL_TID_EN, 0x1),
 	SNBEP_CBO_EVENT_EXTRA_REG(0x0334, 0xffff, 0x4),
+	SNBEP_CBO_EVENT_EXTRA_REG(0x4334, 0xffff, 0x6),
 	SNBEP_CBO_EVENT_EXTRA_REG(0x0534, 0xffff, 0x4),
+	SNBEP_CBO_EVENT_EXTRA_REG(0x4534, 0xffff, 0x6),
 	SNBEP_CBO_EVENT_EXTRA_REG(0x0934, 0xffff, 0x4),
+	SNBEP_CBO_EVENT_EXTRA_REG(0x4934, 0xffff, 0x6),
 	SNBEP_CBO_EVENT_EXTRA_REG(0x4134, 0xffff, 0x6),
 	SNBEP_CBO_EVENT_EXTRA_REG(0x0135, 0xffff, 0x8),
 	SNBEP_CBO_EVENT_EXTRA_REG(0x0335, 0xffff, 0x8),
@@ -1178,10 +1181,15 @@
 	SNBEP_CBO_EVENT_EXTRA_REG(SNBEP_CBO_PMON_CTL_TID_EN,
 				  SNBEP_CBO_PMON_CTL_TID_EN, 0x1),
 	SNBEP_CBO_EVENT_EXTRA_REG(0x1031, 0x10ff, 0x2),
-	SNBEP_CBO_EVENT_EXTRA_REG(0x0334, 0xffff, 0x4),
-	SNBEP_CBO_EVENT_EXTRA_REG(0x0534, 0xffff, 0x4),
-	SNBEP_CBO_EVENT_EXTRA_REG(0x0934, 0xffff, 0x4),
+	SNBEP_CBO_EVENT_EXTRA_REG(0x1134, 0xffff, 0x4),
 	SNBEP_CBO_EVENT_EXTRA_REG(0x4134, 0xffff, 0xc),
+	SNBEP_CBO_EVENT_EXTRA_REG(0x5134, 0xffff, 0xc),
+	SNBEP_CBO_EVENT_EXTRA_REG(0x0334, 0xffff, 0x4),
+	SNBEP_CBO_EVENT_EXTRA_REG(0x4334, 0xffff, 0xc),
+	SNBEP_CBO_EVENT_EXTRA_REG(0x0534, 0xffff, 0x4),
+	SNBEP_CBO_EVENT_EXTRA_REG(0x4534, 0xffff, 0xc),
+	SNBEP_CBO_EVENT_EXTRA_REG(0x0934, 0xffff, 0x4),
+	SNBEP_CBO_EVENT_EXTRA_REG(0x4934, 0xffff, 0xc),
 	SNBEP_CBO_EVENT_EXTRA_REG(0x0135, 0xffff, 0x10),
 	SNBEP_CBO_EVENT_EXTRA_REG(0x0335, 0xffff, 0x10),
 	SNBEP_CBO_EVENT_EXTRA_REG(0x2135, 0xffff, 0x10),
diff --git a/arch/x86/kernel/cpu/perf_event_p6.c b/arch/x86/kernel/cpu/perf_event_p6.c
index b1e2fe1..7c1a0c0 100644
--- a/arch/x86/kernel/cpu/perf_event_p6.c
+++ b/arch/x86/kernel/cpu/perf_event_p6.c
@@ -231,31 +231,49 @@
 
 };
 
+static __init void p6_pmu_rdpmc_quirk(void)
+{
+	if (boot_cpu_data.x86_mask < 9) {
+		/*
+		 * PPro erratum 26; fixed in stepping 9 and above.
+		 */
+		pr_warn("Userspace RDPMC support disabled due to a CPU erratum\n");
+		x86_pmu.attr_rdpmc_broken = 1;
+		x86_pmu.attr_rdpmc = 0;
+	}
+}
+
 __init int p6_pmu_init(void)
 {
+	x86_pmu = p6_pmu;
+
 	switch (boot_cpu_data.x86_model) {
-	case 1:
-	case 3:  /* Pentium Pro */
-	case 5:
-	case 6:  /* Pentium II */
-	case 7:
-	case 8:
-	case 11: /* Pentium III */
-	case 9:
-	case 13:
-		/* Pentium M */
+	case  1: /* Pentium Pro */
+		x86_add_quirk(p6_pmu_rdpmc_quirk);
 		break;
+
+	case  3: /* Pentium II - Klamath */
+	case  5: /* Pentium II - Deschutes */
+	case  6: /* Pentium II - Mendocino */
+		break;
+
+	case  7: /* Pentium III - Katmai */
+	case  8: /* Pentium III - Coppermine */
+	case 10: /* Pentium III Xeon */
+	case 11: /* Pentium III - Tualatin */
+		break;
+
+	case  9: /* Pentium M - Banias */
+	case 13: /* Pentium M - Dothan */
+		break;
+
 	default:
-		pr_cont("unsupported p6 CPU model %d ",
-			boot_cpu_data.x86_model);
+		pr_cont("unsupported p6 CPU model %d ", boot_cpu_data.x86_model);
 		return -ENODEV;
 	}
 
-	x86_pmu = p6_pmu;
-
 	memcpy(hw_cache_event_ids, p6_hw_cache_event_ids,
 		sizeof(hw_cache_event_ids));
 
-
 	return 0;
 }
diff --git a/arch/x86/kernel/machine_kexec_64.c b/arch/x86/kernel/machine_kexec_64.c
index 4eabc16..679cef0 100644
--- a/arch/x86/kernel/machine_kexec_64.c
+++ b/arch/x86/kernel/machine_kexec_64.c
@@ -279,5 +279,7 @@
 	VMCOREINFO_SYMBOL(node_data);
 	VMCOREINFO_LENGTH(node_data, MAX_NUMNODES);
 #endif
+	vmcoreinfo_append_str("KERNELOFFSET=%lx\n",
+			      (unsigned long)&_text - __START_KERNEL);
 }
 
diff --git a/arch/x86/kernel/pci-dma.c b/arch/x86/kernel/pci-dma.c
index 872079a..f7d0672 100644
--- a/arch/x86/kernel/pci-dma.c
+++ b/arch/x86/kernel/pci-dma.c
@@ -100,8 +100,10 @@
 	flag |= __GFP_ZERO;
 again:
 	page = NULL;
-	if (!(flag & GFP_ATOMIC))
+	/* CMA can be used only in the context which permits sleeping */
+	if (flag & __GFP_WAIT)
 		page = dma_alloc_from_contiguous(dev, count, get_order(size));
+	/* fallback */
 	if (!page)
 		page = alloc_pages_node(dev_to_node(dev), flag, get_order(size));
 	if (!page)
diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c
index acb3b60..cfbe99f 100644
--- a/arch/x86/kernel/tsc.c
+++ b/arch/x86/kernel/tsc.c
@@ -653,13 +653,10 @@
 
 	/* Calibrate TSC using MSR for Intel Atom SoCs */
 	local_irq_save(flags);
-	i = try_msr_calibrate_tsc(&fast_calibrate);
+	fast_calibrate = try_msr_calibrate_tsc();
 	local_irq_restore(flags);
-	if (i >= 0) {
-		if (i == 0)
-			pr_warn("Fast TSC calibration using MSR failed\n");
+	if (fast_calibrate)
 		return fast_calibrate;
-	}
 
 	local_irq_save(flags);
 	fast_calibrate = quick_pit_calibrate();
diff --git a/arch/x86/kernel/tsc_msr.c b/arch/x86/kernel/tsc_msr.c
index 8b5434f..92ae6ac 100644
--- a/arch/x86/kernel/tsc_msr.c
+++ b/arch/x86/kernel/tsc_msr.c
@@ -53,7 +53,7 @@
 	/* TNG */
 	{ 6, 0x4a, 1, { 0, FREQ_100, FREQ_133, 0, 0, 0, 0, 0 } },
 	/* VLV2 */
-	{ 6, 0x37, 1, { 0, FREQ_100, FREQ_133, FREQ_166, 0, 0, 0, 0 } },
+	{ 6, 0x37, 1, { FREQ_83, FREQ_100, FREQ_133, FREQ_166, 0, 0, 0, 0 } },
 	/* ANN */
 	{ 6, 0x5a, 1, { FREQ_83, FREQ_100, FREQ_133, FREQ_100, 0, 0, 0, 0 } },
 };
@@ -77,21 +77,18 @@
 
 /*
  * Do MSR calibration only for known/supported CPUs.
- * Return values:
- * -1: CPU is unknown/unsupported for MSR based calibration
- *  0: CPU is known/supported, but calibration failed
- *  1: CPU is known/supported, and calibration succeeded
+ *
+ * Returns the calibration value or 0 if MSR calibration failed.
  */
-int try_msr_calibrate_tsc(unsigned long *fast_calibrate)
+unsigned long try_msr_calibrate_tsc(void)
 {
-	int cpu_index;
 	u32 lo, hi, ratio, freq_id, freq;
+	unsigned long res;
+	int cpu_index;
 
 	cpu_index = match_cpu(boot_cpu_data.x86, boot_cpu_data.x86_model);
 	if (cpu_index < 0)
-		return -1;
-
-	*fast_calibrate = 0;
+		return 0;
 
 	if (freq_desc_tables[cpu_index].msr_plat) {
 		rdmsr(MSR_PLATFORM_INFO, lo, hi);
@@ -103,7 +100,7 @@
 	pr_info("Maximum core-clock to bus-clock ratio: 0x%x\n", ratio);
 
 	if (!ratio)
-		return 0;
+		goto fail;
 
 	/* Get FSB FREQ ID */
 	rdmsr(MSR_FSB_FREQ, lo, hi);
@@ -112,16 +109,19 @@
 	pr_info("Resolved frequency ID: %u, frequency: %u KHz\n",
 				freq_id, freq);
 	if (!freq)
-		return 0;
+		goto fail;
 
 	/* TSC frequency = maximum resolved freq * maximum resolved bus ratio */
-	*fast_calibrate = freq * ratio;
-	pr_info("TSC runs at %lu KHz\n", *fast_calibrate);
+	res = freq * ratio;
+	pr_info("TSC runs at %lu KHz\n", res);
 
 #ifdef CONFIG_X86_LOCAL_APIC
 	lapic_timer_frequency = (freq * 1000) / HZ;
 	pr_info("lapic_timer_frequency = %d\n", lapic_timer_frequency);
 #endif
+	return res;
 
-	return 1;
+fail:
+	pr_warn("Fast TSC calibration using MSR failed\n");
+	return 0;
 }
diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
index e50425d..9b53135 100644
--- a/arch/x86/kvm/mmu.c
+++ b/arch/x86/kvm/mmu.c
@@ -2672,6 +2672,7 @@
 			break;
 		}
 
+		drop_large_spte(vcpu, iterator.sptep);
 		if (!is_shadow_present_pte(*iterator.sptep)) {
 			u64 base_addr = iterator.addr;
 
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index a06f101..3927528 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -6688,7 +6688,7 @@
 		else if (is_page_fault(intr_info))
 			return enable_ept;
 		else if (is_no_device(intr_info) &&
-			 !(nested_read_cr0(vmcs12) & X86_CR0_TS))
+			 !(vmcs12->guest_cr0 & X86_CR0_TS))
 			return 0;
 		return vmcs12->exception_bitmap &
 				(1u << (intr_info & INTR_INFO_VECTOR_MASK));
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 39c28f09..2b85784 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -6186,7 +6186,7 @@
 		frag->len -= len;
 	}
 
-	if (vcpu->mmio_cur_fragment == vcpu->mmio_nr_fragments) {
+	if (vcpu->mmio_cur_fragment >= vcpu->mmio_nr_fragments) {
 		vcpu->mmio_needed = 0;
 
 		/* FIXME: return into emulator if single-stepping.  */
diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig
index ba56e11..c87ae7c 100644
--- a/arch/xtensa/Kconfig
+++ b/arch/xtensa/Kconfig
@@ -20,6 +20,7 @@
 	select HAVE_FUNCTION_TRACER
 	select HAVE_IRQ_TIME_ACCOUNTING
 	select HAVE_PERF_EVENTS
+	select COMMON_CLK
 	help
 	  Xtensa processors are 32-bit RISC machines designed by Tensilica
 	  primarily for embedded systems.  These processors are both
@@ -80,7 +81,6 @@
 config XTENSA_VARIANT_FSF
 	bool "fsf - default (not generic) configuration"
 	select MMU
-	select HAVE_XTENSA_GPIO32
 
 config XTENSA_VARIANT_DC232B
 	bool "dc232b - Diamond 232L Standard Core Rev.B (LE)"
@@ -135,7 +135,6 @@
 config SMP
 	bool "Enable Symmetric multi-processing support"
 	depends on HAVE_SMP
-	select USE_GENERIC_SMP_HELPERS
 	select GENERIC_SMP_IDLE_THREAD
 	help
 	  Enabled SMP Software; allows more than one CPU/CORE
diff --git a/arch/xtensa/boot/dts/xtfpga.dtsi b/arch/xtensa/boot/dts/xtfpga.dtsi
index 46b4f5e..e7370b1 100644
--- a/arch/xtensa/boot/dts/xtfpga.dtsi
+++ b/arch/xtensa/boot/dts/xtfpga.dtsi
@@ -35,6 +35,13 @@
 		interrupt-controller;
 	};
 
+	clocks {
+		osc: main-oscillator {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+		};
+	};
+
 	serial0: serial@fd050020 {
 		device_type = "serial";
 		compatible = "ns16550a";
@@ -42,9 +49,7 @@
 		reg = <0xfd050020 0x20>;
 		reg-shift = <2>;
 		interrupts = <0 1>; /* external irq 0 */
-		/* Filled in by platform_setup from FPGA register
-		 * clock-frequency = <100000000>;
-		 */
+		clocks = <&osc>;
 	};
 
 	enet0: ethoc@fd030000 {
@@ -52,5 +57,6 @@
 		reg = <0xfd030000 0x4000 0xfd800000 0x4000>;
 		interrupts = <1 1>; /* external irq 1 */
 		local-mac-address = [00 50 c2 13 6f 00];
+		clocks = <&osc>;
 	};
 };
diff --git a/arch/xtensa/include/asm/io.h b/arch/xtensa/include/asm/io.h
index 2a042d4..7494420 100644
--- a/arch/xtensa/include/asm/io.h
+++ b/arch/xtensa/include/asm/io.h
@@ -25,7 +25,7 @@
 
 #ifdef CONFIG_MMU
 
-#if XCHAL_HAVE_PTP_MMU && XCHAL_HAVE_SPANNING_WAY && CONFIG_OF
+#if XCHAL_HAVE_PTP_MMU && XCHAL_HAVE_SPANNING_WAY && defined(CONFIG_OF)
 extern unsigned long xtensa_kio_paddr;
 
 static inline unsigned long xtensa_get_kio_paddr(void)
diff --git a/arch/xtensa/include/asm/traps.h b/arch/xtensa/include/asm/traps.h
index 8c194f6..677bfcf 100644
--- a/arch/xtensa/include/asm/traps.h
+++ b/arch/xtensa/include/asm/traps.h
@@ -23,25 +23,37 @@
 
 static inline void spill_registers(void)
 {
-
+#if XCHAL_NUM_AREGS > 16
 	__asm__ __volatile__ (
-		"movi	a14, "__stringify((1 << PS_EXCM_BIT) | LOCKLEVEL)"\n\t"
-		"mov	a12, a0\n\t"
-		"rsr	a13, sar\n\t"
-		"xsr	a14, ps\n\t"
-		"movi	a0, _spill_registers\n\t"
-		"rsync\n\t"
-		"callx0 a0\n\t"
-		"mov	a0, a12\n\t"
-		"wsr	a13, sar\n\t"
-		"wsr	a14, ps\n\t"
-		: :
-#if defined(CONFIG_FRAME_POINTER)
-		: "a2", "a3", "a4",       "a11", "a12", "a13", "a14", "a15",
-#else
-		: "a2", "a3", "a4", "a7", "a11", "a12", "a13", "a14", "a15",
+		"	call12	1f\n"
+		"	_j	2f\n"
+		"	retw\n"
+		"	.align	4\n"
+		"1:\n"
+		"	_entry	a1, 48\n"
+		"	addi	a12, a0, 3\n"
+#if XCHAL_NUM_AREGS > 32
+		"	.rept	(" __stringify(XCHAL_NUM_AREGS) " - 32) / 12\n"
+		"	_entry	a1, 48\n"
+		"	mov	a12, a0\n"
+		"	.endr\n"
 #endif
-		  "memory");
+		"	_entry	a1, 48\n"
+#if XCHAL_NUM_AREGS % 12 == 0
+		"	mov	a8, a8\n"
+#elif XCHAL_NUM_AREGS % 12 == 4
+		"	mov	a12, a12\n"
+#elif XCHAL_NUM_AREGS % 12 == 8
+		"	mov	a4, a4\n"
+#endif
+		"	retw\n"
+		"2:\n"
+		: : : "a12", "a13", "memory");
+#else
+	__asm__ __volatile__ (
+		"	mov	a12, a12\n"
+		: : : "memory");
+#endif
 }
 
 #endif /* _XTENSA_TRAPS_H */
diff --git a/arch/xtensa/include/asm/vectors.h b/arch/xtensa/include/asm/vectors.h
index 5791b45..f74ddfb 100644
--- a/arch/xtensa/include/asm/vectors.h
+++ b/arch/xtensa/include/asm/vectors.h
@@ -25,7 +25,7 @@
 #define XCHAL_KIO_DEFAULT_PADDR		0xf0000000
 #define XCHAL_KIO_SIZE			0x10000000
 
-#if XCHAL_HAVE_PTP_MMU && XCHAL_HAVE_SPANNING_WAY && CONFIG_OF
+#if XCHAL_HAVE_PTP_MMU && XCHAL_HAVE_SPANNING_WAY && defined(CONFIG_OF)
 #define XCHAL_KIO_PADDR			xtensa_get_kio_paddr()
 #else
 #define XCHAL_KIO_PADDR			XCHAL_KIO_DEFAULT_PADDR
diff --git a/arch/xtensa/include/uapi/asm/unistd.h b/arch/xtensa/include/uapi/asm/unistd.h
index 51940fe..b939552 100644
--- a/arch/xtensa/include/uapi/asm/unistd.h
+++ b/arch/xtensa/include/uapi/asm/unistd.h
@@ -734,7 +734,12 @@
 #define __NR_accept4				333
 __SYSCALL(333, sys_accept4, 4)
 
-#define __NR_syscall_count			334
+#define __NR_sched_setattr			334
+__SYSCALL(334, sys_sched_setattr, 2)
+#define __NR_sched_getattr			335
+__SYSCALL(335, sys_sched_getattr, 3)
+
+#define __NR_syscall_count			336
 
 /*
  * sysxtensa syscall handler
diff --git a/arch/xtensa/kernel/entry.S b/arch/xtensa/kernel/entry.S
index 21dbe6b..ef7f499 100644
--- a/arch/xtensa/kernel/entry.S
+++ b/arch/xtensa/kernel/entry.S
@@ -1081,34 +1081,202 @@
 
 	rsr	a0, sar
 	s32i	a3, a2, PT_AREG3
+	s32i	a0, a2, PT_SAR
+
+	/* The spill routine might clobber a4, a7, a8, a11, a12, and a15. */
+
 	s32i	a4, a2, PT_AREG4
-	s32i	a0, a2, PT_AREG5	# store SAR to PT_AREG5
-
-	/* The spill routine might clobber a7, a11, and a15. */
-
 	s32i	a7, a2, PT_AREG7
+	s32i	a8, a2, PT_AREG8
 	s32i	a11, a2, PT_AREG11
+	s32i	a12, a2, PT_AREG12
 	s32i	a15, a2, PT_AREG15
 
-	call0	_spill_registers	# destroys a3, a4, and SAR
+	/*
+	 * Rotate ws so that the current windowbase is at bit 0.
+	 * Assume ws = xxxwww1yy (www1 current window frame).
+	 * Rotate ws right so that a4 = yyxxxwww1.
+	 */
+
+	rsr	a0, windowbase
+	rsr	a3, windowstart		# a3 = xxxwww1yy
+	ssr	a0			# holds WB
+	slli	a0, a3, WSBITS
+	or	a3, a3, a0		# a3 = xxxwww1yyxxxwww1yy
+	srl	a3, a3			# a3 = 00xxxwww1yyxxxwww1
+
+	/* We are done if there are no more than the current register frame. */
+
+	extui	a3, a3, 1, WSBITS-1	# a3 = 0yyxxxwww
+	movi	a0, (1 << (WSBITS-1))
+	_beqz	a3, .Lnospill		# only one active frame? jump
+
+	/* We want 1 at the top, so that we return to the current windowbase */
+
+	or	a3, a3, a0		# 1yyxxxwww
+
+	/* Skip empty frames - get 'oldest' WINDOWSTART-bit. */
+
+	wsr	a3, windowstart		# save shifted windowstart
+	neg	a0, a3
+	and	a3, a0, a3		# first bit set from right: 000010000
+
+	ffs_ws	a0, a3			# a0: shifts to skip empty frames
+	movi	a3, WSBITS
+	sub	a0, a3, a0		# WSBITS-a0:number of 0-bits from right
+	ssr	a0			# save in SAR for later.
+
+	rsr	a3, windowbase
+	add	a3, a3, a0
+	wsr	a3, windowbase
+	rsync
+
+	rsr	a3, windowstart
+	srl	a3, a3			# shift windowstart
+
+	/* WB is now just one frame below the oldest frame in the register
+	   window. WS is shifted so the oldest frame is in bit 0, thus, WB
+	   and WS differ by one 4-register frame. */
+
+	/* Save frames. Depending what call was used (call4, call8, call12),
+	 * we have to save 4,8. or 12 registers.
+	 */
+
+
+.Lloop: _bbsi.l	a3, 1, .Lc4
+	_bbci.l	a3, 2, .Lc12
+
+.Lc8:	s32e	a4, a13, -16
+	l32e	a4, a5, -12
+	s32e	a8, a4, -32
+	s32e	a5, a13, -12
+	s32e	a6, a13, -8
+	s32e	a7, a13, -4
+	s32e	a9, a4, -28
+	s32e	a10, a4, -24
+	s32e	a11, a4, -20
+	srli	a11, a3, 2		# shift windowbase by 2
+	rotw	2
+	_bnei	a3, 1, .Lloop
+	j	.Lexit
+
+.Lc4:	s32e	a4, a9, -16
+	s32e	a5, a9, -12
+	s32e	a6, a9, -8
+	s32e	a7, a9, -4
+
+	srli	a7, a3, 1
+	rotw	1
+	_bnei	a3, 1, .Lloop
+	j	.Lexit
+
+.Lc12:	_bbci.l	a3, 3, .Linvalid_mask	# bit 2 shouldn't be zero!
+
+	/* 12-register frame (call12) */
+
+	l32e	a0, a5, -12
+	s32e	a8, a0, -48
+	mov	a8, a0
+
+	s32e	a9, a8, -44
+	s32e	a10, a8, -40
+	s32e	a11, a8, -36
+	s32e	a12, a8, -32
+	s32e	a13, a8, -28
+	s32e	a14, a8, -24
+	s32e	a15, a8, -20
+	srli	a15, a3, 3
+
+	/* The stack pointer for a4..a7 is out of reach, so we rotate the
+	 * window, grab the stackpointer, and rotate back.
+	 * Alternatively, we could also use the following approach, but that
+	 * makes the fixup routine much more complicated:
+	 * rotw	1
+	 * s32e	a0, a13, -16
+	 * ...
+	 * rotw 2
+	 */
+
+	rotw	1
+	mov	a4, a13
+	rotw	-1
+
+	s32e	a4, a8, -16
+	s32e	a5, a8, -12
+	s32e	a6, a8, -8
+	s32e	a7, a8, -4
+
+	rotw	3
+
+	_beqi	a3, 1, .Lexit
+	j	.Lloop
+
+.Lexit:
+
+	/* Done. Do the final rotation and set WS */
+
+	rotw	1
+	rsr	a3, windowbase
+	ssl	a3
+	movi	a3, 1
+	sll	a3, a3
+	wsr	a3, windowstart
+.Lnospill:
 
 	/* Advance PC, restore registers and SAR, and return from exception. */
 
-	l32i	a3, a2, PT_AREG5
-	l32i	a4, a2, PT_AREG4
+	l32i	a3, a2, PT_SAR
 	l32i	a0, a2, PT_AREG0
 	wsr	a3, sar
 	l32i	a3, a2, PT_AREG3
 
 	/* Restore clobbered registers. */
 
+	l32i	a4, a2, PT_AREG4
 	l32i	a7, a2, PT_AREG7
+	l32i	a8, a2, PT_AREG8
 	l32i	a11, a2, PT_AREG11
+	l32i	a12, a2, PT_AREG12
 	l32i	a15, a2, PT_AREG15
 
 	movi	a2, 0
 	rfe
 
+.Linvalid_mask:
+
+	/* We get here because of an unrecoverable error in the window
+	 * registers, so set up a dummy frame and kill the user application.
+	 * Note: We assume EXC_TABLE_KSTK contains a valid stack pointer.
+	 */
+
+	movi	a0, 1
+	movi	a1, 0
+
+	wsr	a0, windowstart
+	wsr	a1, windowbase
+	rsync
+
+	movi	a0, 0
+
+	rsr	a3, excsave1
+	l32i	a1, a3, EXC_TABLE_KSTK
+
+	movi	a4, (1 << PS_WOE_BIT) | LOCKLEVEL
+	wsr	a4, ps
+	rsync
+
+	movi	a6, SIGSEGV
+	movi	a4, do_exit
+	callx4	a4
+
+	/* shouldn't return, so panic */
+
+	wsr	a0, excsave1
+	movi	a0, unrecoverable_exception
+	callx0	a0		# should not return
+1:	j	1b
+
+
 ENDPROC(fast_syscall_spill_registers)
 
 /* Fixup handler.
@@ -1117,6 +1285,13 @@
  * We basically restore WINDOWBASE and WINDOWSTART to the condition when
  * we entered the spill routine and jump to the user exception handler.
  *
+ * Note that we only need to restore the bits in windowstart that have not
+ * been spilled yet by the _spill_register routine. Luckily, a3 contains a
+ * rotated windowstart with only those bits set for frames that haven't been
+ * spilled yet. Because a3 is rotated such that bit 0 represents the register
+ * frame for the current windowbase - 1, we need to rotate a3 left by the
+ * value of the current windowbase + 1 and move it to windowstart.
+ *
  * a0: value of depc, original value in depc
  * a2: trashed, original value in EXC_TABLE_DOUBLE_SAVE
  * a3: exctable, original value in excsave1
@@ -1131,10 +1306,15 @@
 	/* We need to make sure the current registers (a0-a3) are preserved.
 	 * To do this, we simply set the bit for the current window frame
 	 * in WS, so that the exception handlers save them to the task stack.
+	 *
+	 * Note: we use a3 to set the windowbase, so we take a special care
+	 * of it, saving it in the original _spill_registers frame across
+	 * the exception handler call.
 	 */
 
 	xsr	a3, excsave1	# get spill-mask
 	slli	a3, a3, 1	# shift left by one
+	addi	a3, a3, 1	# set the bit for the current window frame
 
 	slli	a2, a3, 32-WSBITS
 	src	a2, a3, a2	# a2 = xxwww1yyxxxwww1yy......
@@ -1220,209 +1400,6 @@
 
 ENDPROC(fast_syscall_spill_registers_fixup_return)
 
-/*
- * spill all registers.
- *
- * This is not a real function. The following conditions must be met:
- *
- *  - must be called with call0.
- *  - uses a3, a4 and SAR.
- *  - the last 'valid' register of each frame are clobbered.
- *  - the caller must have registered a fixup handler
- *    (or be inside a critical section)
- *  - PS_EXCM must be set (PS_WOE cleared?)
- */
-
-ENTRY(_spill_registers)
-
-	/*
-	 * Rotate ws so that the current windowbase is at bit 0.
-	 * Assume ws = xxxwww1yy (www1 current window frame).
-	 * Rotate ws right so that a4 = yyxxxwww1.
-	 */
-
-	rsr	a4, windowbase
-	rsr	a3, windowstart		# a3 = xxxwww1yy
-	ssr	a4			# holds WB
-	slli	a4, a3, WSBITS
-	or	a3, a3, a4		# a3 = xxxwww1yyxxxwww1yy
-	srl	a3, a3			# a3 = 00xxxwww1yyxxxwww1
-
-	/* We are done if there are no more than the current register frame. */
-
-	extui	a3, a3, 1, WSBITS-1	# a3 = 0yyxxxwww
-	movi	a4, (1 << (WSBITS-1))
-	_beqz	a3, .Lnospill		# only one active frame? jump
-
-	/* We want 1 at the top, so that we return to the current windowbase */
-
-	or	a3, a3, a4		# 1yyxxxwww
-
-	/* Skip empty frames - get 'oldest' WINDOWSTART-bit. */
-
-	wsr	a3, windowstart		# save shifted windowstart
-	neg	a4, a3
-	and	a3, a4, a3		# first bit set from right: 000010000
-
-	ffs_ws	a4, a3			# a4: shifts to skip empty frames
-	movi	a3, WSBITS
-	sub	a4, a3, a4		# WSBITS-a4:number of 0-bits from right
-	ssr	a4			# save in SAR for later.
-
-	rsr	a3, windowbase
-	add	a3, a3, a4
-	wsr	a3, windowbase
-	rsync
-
-	rsr	a3, windowstart
-	srl	a3, a3			# shift windowstart
-
-	/* WB is now just one frame below the oldest frame in the register
-	   window. WS is shifted so the oldest frame is in bit 0, thus, WB
-	   and WS differ by one 4-register frame. */
-
-	/* Save frames. Depending what call was used (call4, call8, call12),
-	 * we have to save 4,8. or 12 registers.
-	 */
-
-	_bbsi.l	a3, 1, .Lc4
-	_bbsi.l	a3, 2, .Lc8
-
-	/* Special case: we have a call12-frame starting at a4. */
-
-	_bbci.l	a3, 3, .Lc12	# bit 3 shouldn't be zero! (Jump to Lc12 first)
-
-	s32e	a4, a1, -16	# a1 is valid with an empty spill area
-	l32e	a4, a5, -12
-	s32e	a8, a4, -48
-	mov	a8, a4
-	l32e	a4, a1, -16
-	j	.Lc12c
-
-.Lnospill:
-	ret
-
-.Lloop: _bbsi.l	a3, 1, .Lc4
-	_bbci.l	a3, 2, .Lc12
-
-.Lc8:	s32e	a4, a13, -16
-	l32e	a4, a5, -12
-	s32e	a8, a4, -32
-	s32e	a5, a13, -12
-	s32e	a6, a13, -8
-	s32e	a7, a13, -4
-	s32e	a9, a4, -28
-	s32e	a10, a4, -24
-	s32e	a11, a4, -20
-
-	srli	a11, a3, 2		# shift windowbase by 2
-	rotw	2
-	_bnei	a3, 1, .Lloop
-
-.Lexit: /* Done. Do the final rotation, set WS, and return. */
-
-	rotw	1
-	rsr	a3, windowbase
-	ssl	a3
-	movi	a3, 1
-	sll	a3, a3
-	wsr	a3, windowstart
-	ret
-
-.Lc4:	s32e	a4, a9, -16
-	s32e	a5, a9, -12
-	s32e	a6, a9, -8
-	s32e	a7, a9, -4
-
-	srli	a7, a3, 1
-	rotw	1
-	_bnei	a3, 1, .Lloop
-	j	.Lexit
-
-.Lc12:	_bbci.l	a3, 3, .Linvalid_mask	# bit 2 shouldn't be zero!
-
-	/* 12-register frame (call12) */
-
-	l32e	a2, a5, -12
-	s32e	a8, a2, -48
-	mov	a8, a2
-
-.Lc12c: s32e	a9, a8, -44
-	s32e	a10, a8, -40
-	s32e	a11, a8, -36
-	s32e	a12, a8, -32
-	s32e	a13, a8, -28
-	s32e	a14, a8, -24
-	s32e	a15, a8, -20
-	srli	a15, a3, 3
-
-	/* The stack pointer for a4..a7 is out of reach, so we rotate the
-	 * window, grab the stackpointer, and rotate back.
-	 * Alternatively, we could also use the following approach, but that
-	 * makes the fixup routine much more complicated:
-	 * rotw	1
-	 * s32e	a0, a13, -16
-	 * ...
-	 * rotw 2
-	 */
-
-	rotw	1
-	mov	a5, a13
-	rotw	-1
-
-	s32e	a4, a9, -16
-	s32e	a5, a9, -12
-	s32e	a6, a9, -8
-	s32e	a7, a9, -4
-
-	rotw	3
-
-	_beqi	a3, 1, .Lexit
-	j	.Lloop
-
-.Linvalid_mask:
-
-	/* We get here because of an unrecoverable error in the window
-	 * registers. If we are in user space, we kill the application,
-	 * however, this condition is unrecoverable in kernel space.
-	 */
-
-	rsr	a0, ps
-	_bbci.l	a0, PS_UM_BIT, 1f
-
-	/* User space: Setup a dummy frame and kill application.
-	 * Note: We assume EXC_TABLE_KSTK contains a valid stack pointer.
-	 */
-
-	movi	a0, 1
-	movi	a1, 0
-
-	wsr	a0, windowstart
-	wsr	a1, windowbase
-	rsync
-
-	movi	a0, 0
-
-	rsr	a3, excsave1
-	l32i	a1, a3, EXC_TABLE_KSTK
-
-	movi	a4, (1 << PS_WOE_BIT) | LOCKLEVEL
-	wsr	a4, ps
-	rsync
-
-	movi	a6, SIGSEGV
-	movi	a4, do_exit
-	callx4	a4
-
-1:	/* Kernel space: PANIC! */
-
-	wsr	a0, excsave1
-	movi	a0, unrecoverable_exception
-	callx0	a0		# should not return
-1:	j	1b
-
-ENDPROC(_spill_registers)
-
 #ifdef CONFIG_MMU
 /*
  * We should never get here. Bail out!
@@ -1794,6 +1771,43 @@
 
 ENDPROC(system_call)
 
+/*
+ * Spill live registers on the kernel stack macro.
+ *
+ * Entry condition: ps.woe is set, ps.excm is cleared
+ * Exit condition: windowstart has single bit set
+ * May clobber: a12, a13
+ */
+	.macro	spill_registers_kernel
+
+#if XCHAL_NUM_AREGS > 16
+	call12	1f
+	_j	2f
+	retw
+	.align	4
+1:
+	_entry	a1, 48
+	addi	a12, a0, 3
+#if XCHAL_NUM_AREGS > 32
+	.rept	(XCHAL_NUM_AREGS - 32) / 12
+	_entry	a1, 48
+	mov	a12, a0
+	.endr
+#endif
+	_entry	a1, 48
+#if XCHAL_NUM_AREGS % 12 == 0
+	mov	a8, a8
+#elif XCHAL_NUM_AREGS % 12 == 4
+	mov	a12, a12
+#elif XCHAL_NUM_AREGS % 12 == 8
+	mov	a4, a4
+#endif
+	retw
+2:
+#else
+	mov	a12, a12
+#endif
+	.endm
 
 /*
  * Task switch.
@@ -1806,21 +1820,20 @@
 
 	entry	a1, 16
 
-	mov	a12, a2			# preserve 'prev' (a2)
-	mov	a13, a3			# and 'next' (a3)
+	mov	a10, a2			# preserve 'prev' (a2)
+	mov	a11, a3			# and 'next' (a3)
 
 	l32i	a4, a2, TASK_THREAD_INFO
 	l32i	a5, a3, TASK_THREAD_INFO
 
-	save_xtregs_user a4 a6 a8 a9 a10 a11 THREAD_XTREGS_USER
+	save_xtregs_user a4 a6 a8 a9 a12 a13 THREAD_XTREGS_USER
 
-	s32i	a0, a12, THREAD_RA	# save return address
-	s32i	a1, a12, THREAD_SP	# save stack pointer
+	s32i	a0, a10, THREAD_RA	# save return address
+	s32i	a1, a10, THREAD_SP	# save stack pointer
 
 	/* Disable ints while we manipulate the stack pointer. */
 
-	movi	a14, (1 << PS_EXCM_BIT) | LOCKLEVEL
-	xsr	a14, ps
+	rsil	a14, LOCKLEVEL
 	rsr	a3, excsave1
 	rsync
 	s32i	a3, a3, EXC_TABLE_FIXUP	/* enter critical section */
@@ -1835,7 +1848,7 @@
 
 	/* Flush register file. */
 
-	call0	_spill_registers	# destroys a3, a4, and SAR
+	spill_registers_kernel
 
 	/* Set kernel stack (and leave critical section)
 	 * Note: It's save to set it here. The stack will not be overwritten
@@ -1851,13 +1864,13 @@
 
 	/* restore context of the task 'next' */
 
-	l32i	a0, a13, THREAD_RA	# restore return address
-	l32i	a1, a13, THREAD_SP	# restore stack pointer
+	l32i	a0, a11, THREAD_RA	# restore return address
+	l32i	a1, a11, THREAD_SP	# restore stack pointer
 
-	load_xtregs_user a5 a6 a8 a9 a10 a11 THREAD_XTREGS_USER
+	load_xtregs_user a5 a6 a8 a9 a12 a13 THREAD_XTREGS_USER
 
 	wsr	a14, ps
-	mov	a2, a12			# return 'prev'
+	mov	a2, a10			# return 'prev'
 	rsync
 
 	retw
diff --git a/arch/xtensa/kernel/setup.c b/arch/xtensa/kernel/setup.c
index 7d12af1..84fe931 100644
--- a/arch/xtensa/kernel/setup.c
+++ b/arch/xtensa/kernel/setup.c
@@ -22,6 +22,7 @@
 #include <linux/bootmem.h>
 #include <linux/kernel.h>
 #include <linux/percpu.h>
+#include <linux/clk-provider.h>
 #include <linux/cpu.h>
 #include <linux/of_fdt.h>
 #include <linux/of_platform.h>
@@ -276,6 +277,7 @@
 
 static int __init xtensa_device_probe(void)
 {
+	of_clk_init(NULL);
 	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 	return 0;
 }
diff --git a/arch/xtensa/kernel/time.c b/arch/xtensa/kernel/time.c
index 08b769d..2a1823d 100644
--- a/arch/xtensa/kernel/time.c
+++ b/arch/xtensa/kernel/time.c
@@ -30,6 +30,7 @@
 #include <asm/platform.h>
 
 unsigned long ccount_freq;		/* ccount Hz */
+EXPORT_SYMBOL(ccount_freq);
 
 static cycle_t ccount_read(struct clocksource *cs)
 {
diff --git a/arch/xtensa/kernel/vectors.S b/arch/xtensa/kernel/vectors.S
index cb8fd44..f9e1ec3 100644
--- a/arch/xtensa/kernel/vectors.S
+++ b/arch/xtensa/kernel/vectors.S
@@ -235,7 +235,7 @@
 
 	/* Check for overflow/underflow exception, jump if overflow. */
 
-	_bbci.l	a0, 6, _DoubleExceptionVector_WindowOverflow
+	bbci.l	a0, 6, _DoubleExceptionVector_WindowOverflow
 
 	/*
 	 * Restart window underflow exception.
diff --git a/arch/xtensa/kernel/xtensa_ksyms.c b/arch/xtensa/kernel/xtensa_ksyms.c
index 74a60c7..80b33ed 100644
--- a/arch/xtensa/kernel/xtensa_ksyms.c
+++ b/arch/xtensa/kernel/xtensa_ksyms.c
@@ -122,9 +122,7 @@
 EXPORT_SYMBOL(insl);
 
 extern long common_exception_return;
-extern long _spill_registers;
 EXPORT_SYMBOL(common_exception_return);
-EXPORT_SYMBOL(_spill_registers);
 
 #ifdef CONFIG_FUNCTION_TRACER
 EXPORT_SYMBOL(_mcount);
diff --git a/arch/xtensa/mm/init.c b/arch/xtensa/mm/init.c
index 479d753..aff108d 100644
--- a/arch/xtensa/mm/init.c
+++ b/arch/xtensa/mm/init.c
@@ -90,7 +90,7 @@
 
 
 /*
- * Initialize the bootmem system and give it all the memory we have available.
+ * Initialize the bootmem system and give it all low memory we have available.
  */
 
 void __init bootmem_init(void)
@@ -142,9 +142,14 @@
 
 	/* Add all remaining memory pieces into the bootmem map */
 
-	for (i=0; i<sysmem.nr_banks; i++)
-		free_bootmem(sysmem.bank[i].start,
-			     sysmem.bank[i].end - sysmem.bank[i].start);
+	for (i = 0; i < sysmem.nr_banks; i++) {
+		if (sysmem.bank[i].start >> PAGE_SHIFT < max_low_pfn) {
+			unsigned long end = min(max_low_pfn << PAGE_SHIFT,
+						sysmem.bank[i].end);
+			free_bootmem(sysmem.bank[i].start,
+				     end - sysmem.bank[i].start);
+		}
+	}
 
 }
 
diff --git a/arch/xtensa/mm/mmu.c b/arch/xtensa/mm/mmu.c
index 36ec171..861203e 100644
--- a/arch/xtensa/mm/mmu.c
+++ b/arch/xtensa/mm/mmu.c
@@ -39,7 +39,7 @@
 	set_itlbcfg_register(0);
 	set_dtlbcfg_register(0);
 #endif
-#if XCHAL_HAVE_PTP_MMU && XCHAL_HAVE_SPANNING_WAY && CONFIG_OF
+#if XCHAL_HAVE_PTP_MMU && XCHAL_HAVE_SPANNING_WAY && defined(CONFIG_OF)
 	/*
 	 * Update the IO area mapping in case xtensa_kio_paddr has changed
 	 */
diff --git a/arch/xtensa/platforms/xtfpga/setup.c b/arch/xtensa/platforms/xtfpga/setup.c
index 8002278..57fd08b 100644
--- a/arch/xtensa/platforms/xtfpga/setup.c
+++ b/arch/xtensa/platforms/xtfpga/setup.c
@@ -135,11 +135,11 @@
 
 static int __init machine_setup(void)
 {
-	struct device_node *serial;
+	struct device_node *clock;
 	struct device_node *eth = NULL;
 
-	for_each_compatible_node(serial, NULL, "ns16550a")
-		update_clock_frequency(serial);
+	for_each_node_by_name(clock, "main-oscillator")
+		update_clock_frequency(clock);
 
 	if ((eth = of_find_compatible_node(eth, NULL, "opencores,ethoc")))
 		update_local_mac(eth);
@@ -290,6 +290,7 @@
 	 * knows whether they set it correctly on the DIP switches.
 	 */
 	pr_info("XTFPGA: Ethernet MAC %pM\n", ethoc_pdata.hwaddr);
+	ethoc_pdata.eth_clkfreq = *(long *)XTFPGA_CLKFRQ_VADDR;
 
 	return 0;
 }
diff --git a/arch/xtensa/variants/fsf/include/variant/tie.h b/arch/xtensa/variants/fsf/include/variant/tie.h
index bf40201..244cdea 100644
--- a/arch/xtensa/variants/fsf/include/variant/tie.h
+++ b/arch/xtensa/variants/fsf/include/variant/tie.h
@@ -18,13 +18,6 @@
 #define XCHAL_CP_MASK			0x00	/* bitmask of all CPs by ID */
 #define XCHAL_CP_PORT_MASK		0x00	/* bitmask of only port CPs */
 
-/*  Basic parameters of each coprocessor:  */
-#define XCHAL_CP7_NAME			"XTIOP"
-#define XCHAL_CP7_IDENT			XTIOP
-#define XCHAL_CP7_SA_SIZE		0	/* size of state save area */
-#define XCHAL_CP7_SA_ALIGN		1	/* min alignment of save area */
-#define XCHAL_CP_ID_XTIOP		7	/* coprocessor ID (0..7) */
-
 /*  Filler info for unassigned coprocessors, to simplify arrays etc:  */
 #define XCHAL_NCP_SA_SIZE		0
 #define XCHAL_NCP_SA_ALIGN		1
@@ -42,6 +35,8 @@
 #define XCHAL_CP5_SA_ALIGN		1
 #define XCHAL_CP6_SA_SIZE		0
 #define XCHAL_CP6_SA_ALIGN		1
+#define XCHAL_CP7_SA_SIZE		0
+#define XCHAL_CP7_SA_ALIGN		1
 
 /*  Save area for non-coprocessor optional and custom (TIE) state:  */
 #define XCHAL_NCP_SA_SIZE		0
diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c
index e7515aa..6f190bc 100644
--- a/drivers/acpi/ac.c
+++ b/drivers/acpi/ac.c
@@ -243,6 +243,8 @@
 		kobject_uevent(&ac->charger.dev->kobj, KOBJ_CHANGE);
 	return 0;
 }
+#else
+#define acpi_ac_resume NULL
 #endif
 static SIMPLE_DEV_PM_OPS(acpi_ac_pm_ops, NULL, acpi_ac_resume);
 
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c
index 018a428..797a693 100644
--- a/drivers/acpi/battery.c
+++ b/drivers/acpi/battery.c
@@ -841,6 +841,8 @@
 	acpi_battery_update(battery);
 	return 0;
 }
+#else
+#define acpi_battery_resume NULL
 #endif
 
 static SIMPLE_DEV_PM_OPS(acpi_battery_pm, NULL, acpi_battery_resume);
diff --git a/drivers/acpi/blacklist.c b/drivers/acpi/blacklist.c
index 10e4964..afec452 100644
--- a/drivers/acpi/blacklist.c
+++ b/drivers/acpi/blacklist.c
@@ -260,14 +260,6 @@
 	},
 	{
 	.callback = dmi_disable_osi_win8,
-	.ident = "Dell Inspiron 15R SE",
-	.matches = {
-		     DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
-		     DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 7520"),
-		},
-	},
-	{
-	.callback = dmi_disable_osi_win8,
 	.ident = "ThinkPad Edge E530",
 	.matches = {
 		     DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
@@ -322,56 +314,6 @@
 		     DMI_MATCH(DMI_PRODUCT_VERSION, "2349D15"),
 		},
 	},
-	{
-	.callback = dmi_disable_osi_win8,
-	.ident = "HP ProBook 2013 models",
-	.matches = {
-		     DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
-		     DMI_MATCH(DMI_PRODUCT_NAME, "HP ProBook "),
-		     DMI_MATCH(DMI_PRODUCT_NAME, " G1"),
-		},
-	},
-	{
-	.callback = dmi_disable_osi_win8,
-	.ident = "HP EliteBook 2013 models",
-	.matches = {
-		     DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
-		     DMI_MATCH(DMI_PRODUCT_NAME, "HP EliteBook "),
-		     DMI_MATCH(DMI_PRODUCT_NAME, " G1"),
-		},
-	},
-	{
-	.callback = dmi_disable_osi_win8,
-	.ident = "HP ZBook 14",
-	.matches = {
-		     DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
-		     DMI_MATCH(DMI_PRODUCT_NAME, "HP ZBook 14"),
-		},
-	},
-	{
-	.callback = dmi_disable_osi_win8,
-	.ident = "HP ZBook 15",
-	.matches = {
-		     DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
-		     DMI_MATCH(DMI_PRODUCT_NAME, "HP ZBook 15"),
-		},
-	},
-	{
-	.callback = dmi_disable_osi_win8,
-	.ident = "HP ZBook 17",
-	.matches = {
-		     DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
-		     DMI_MATCH(DMI_PRODUCT_NAME, "HP ZBook 17"),
-		},
-	},
-	{
-	.callback = dmi_disable_osi_win8,
-	.ident = "HP EliteBook 8780w",
-	.matches = {
-		     DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
-		     DMI_MATCH(DMI_PRODUCT_NAME, "HP EliteBook 8780w"),
-		},
-	},
 
 	/*
 	 * BIOS invocation of _OSI(Linux) is almost always a BIOS bug.
diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c
index 11c11f6..714e957 100644
--- a/drivers/acpi/button.c
+++ b/drivers/acpi/button.c
@@ -80,6 +80,8 @@
 
 #ifdef CONFIG_PM_SLEEP
 static int acpi_button_resume(struct device *dev);
+#else
+#define acpi_button_resume NULL
 #endif
 static SIMPLE_DEV_PM_OPS(acpi_button_pm, NULL, acpi_button_resume);
 
diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c
index e9b3081..5bfd769 100644
--- a/drivers/acpi/dock.c
+++ b/drivers/acpi/dock.c
@@ -713,13 +713,11 @@
 static ssize_t show_docked(struct device *dev,
 			   struct device_attribute *attr, char *buf)
 {
-	struct acpi_device *tmp;
-
 	struct dock_station *dock_station = dev->platform_data;
+	struct acpi_device *adev = NULL;
 
-	if (!acpi_bus_get_device(dock_station->handle, &tmp))
-		return snprintf(buf, PAGE_SIZE, "1\n");
-	return snprintf(buf, PAGE_SIZE, "0\n");
+	acpi_bus_get_device(dock_station->handle, &adev);
+	return snprintf(buf, PAGE_SIZE, "%u\n", acpi_device_enumerated(adev));
 }
 static DEVICE_ATTR(docked, S_IRUGO, show_docked, NULL);
 
diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c
index 1fb6290..09e423f 100644
--- a/drivers/acpi/fan.c
+++ b/drivers/acpi/fan.c
@@ -55,6 +55,9 @@
 #ifdef CONFIG_PM_SLEEP
 static int acpi_fan_suspend(struct device *dev);
 static int acpi_fan_resume(struct device *dev);
+#else
+#define acpi_fan_suspend NULL
+#define acpi_fan_resume NULL
 #endif
 static SIMPLE_DEV_PM_OPS(acpi_fan_pm, acpi_fan_suspend, acpi_fan_resume);
 
diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c
index 52d45ea..361b40c 100644
--- a/drivers/acpi/pci_irq.c
+++ b/drivers/acpi/pci_irq.c
@@ -430,6 +430,7 @@
 				 pin_name(pin));
 		}
 
+		kfree(entry);
 		return 0;
 	}
 
diff --git a/drivers/acpi/processor_throttling.c b/drivers/acpi/processor_throttling.c
index 28baa05..84243c3 100644
--- a/drivers/acpi/processor_throttling.c
+++ b/drivers/acpi/processor_throttling.c
@@ -56,6 +56,12 @@
 	int target_state;		/* target T-state */
 };
 
+struct acpi_processor_throttling_arg {
+	struct acpi_processor *pr;
+	int target_state;
+	bool force;
+};
+
 #define THROTTLING_PRECHANGE       (1)
 #define THROTTLING_POSTCHANGE      (2)
 
@@ -1060,16 +1066,24 @@
 	return 0;
 }
 
+static long acpi_processor_throttling_fn(void *data)
+{
+	struct acpi_processor_throttling_arg *arg = data;
+	struct acpi_processor *pr = arg->pr;
+
+	return pr->throttling.acpi_processor_set_throttling(pr,
+			arg->target_state, arg->force);
+}
+
 int acpi_processor_set_throttling(struct acpi_processor *pr,
 						int state, bool force)
 {
-	cpumask_var_t saved_mask;
 	int ret = 0;
 	unsigned int i;
 	struct acpi_processor *match_pr;
 	struct acpi_processor_throttling *p_throttling;
+	struct acpi_processor_throttling_arg arg;
 	struct throttling_tstate t_state;
-	cpumask_var_t online_throttling_cpus;
 
 	if (!pr)
 		return -EINVAL;
@@ -1080,14 +1094,6 @@
 	if ((state < 0) || (state > (pr->throttling.state_count - 1)))
 		return -EINVAL;
 
-	if (!alloc_cpumask_var(&saved_mask, GFP_KERNEL))
-		return -ENOMEM;
-
-	if (!alloc_cpumask_var(&online_throttling_cpus, GFP_KERNEL)) {
-		free_cpumask_var(saved_mask);
-		return -ENOMEM;
-	}
-
 	if (cpu_is_offline(pr->id)) {
 		/*
 		 * the cpu pointed by pr->id is offline. Unnecessary to change
@@ -1096,17 +1102,15 @@
 		return -ENODEV;
 	}
 
-	cpumask_copy(saved_mask, &current->cpus_allowed);
 	t_state.target_state = state;
 	p_throttling = &(pr->throttling);
-	cpumask_and(online_throttling_cpus, cpu_online_mask,
-		    p_throttling->shared_cpu_map);
+
 	/*
 	 * The throttling notifier will be called for every
 	 * affected cpu in order to get one proper T-state.
 	 * The notifier event is THROTTLING_PRECHANGE.
 	 */
-	for_each_cpu(i, online_throttling_cpus) {
+	for_each_cpu_and(i, cpu_online_mask, p_throttling->shared_cpu_map) {
 		t_state.cpu = i;
 		acpi_processor_throttling_notifier(THROTTLING_PRECHANGE,
 							&t_state);
@@ -1118,21 +1122,18 @@
 	 * it can be called only for the cpu pointed by pr.
 	 */
 	if (p_throttling->shared_type == DOMAIN_COORD_TYPE_SW_ANY) {
-		/* FIXME: use work_on_cpu() */
-		if (set_cpus_allowed_ptr(current, cpumask_of(pr->id))) {
-			/* Can't migrate to the pr->id CPU. Exit */
-			ret = -ENODEV;
-			goto exit;
-		}
-		ret = p_throttling->acpi_processor_set_throttling(pr,
-						t_state.target_state, force);
+		arg.pr = pr;
+		arg.target_state = state;
+		arg.force = force;
+		ret = work_on_cpu(pr->id, acpi_processor_throttling_fn, &arg);
 	} else {
 		/*
 		 * When the T-state coordination is SW_ALL or HW_ALL,
 		 * it is necessary to set T-state for every affected
 		 * cpus.
 		 */
-		for_each_cpu(i, online_throttling_cpus) {
+		for_each_cpu_and(i, cpu_online_mask,
+		    p_throttling->shared_cpu_map) {
 			match_pr = per_cpu(processors, i);
 			/*
 			 * If the pointer is invalid, we will report the
@@ -1153,13 +1154,12 @@
 					"on CPU %d\n", i));
 				continue;
 			}
-			t_state.cpu = i;
-			/* FIXME: use work_on_cpu() */
-			if (set_cpus_allowed_ptr(current, cpumask_of(i)))
-				continue;
-			ret = match_pr->throttling.
-				acpi_processor_set_throttling(
-				match_pr, t_state.target_state, force);
+
+			arg.pr = match_pr;
+			arg.target_state = state;
+			arg.force = force;
+			ret = work_on_cpu(pr->id, acpi_processor_throttling_fn,
+				&arg);
 		}
 	}
 	/*
@@ -1168,17 +1168,12 @@
 	 * affected cpu to update the T-states.
 	 * The notifier event is THROTTLING_POSTCHANGE
 	 */
-	for_each_cpu(i, online_throttling_cpus) {
+	for_each_cpu_and(i, cpu_online_mask, p_throttling->shared_cpu_map) {
 		t_state.cpu = i;
 		acpi_processor_throttling_notifier(THROTTLING_POSTCHANGE,
 							&t_state);
 	}
-	/* restore the previous state */
-	/* FIXME: use work_on_cpu() */
-	set_cpus_allowed_ptr(current, saved_mask);
-exit:
-	free_cpumask_var(online_throttling_cpus);
-	free_cpumask_var(saved_mask);
+
 	return ret;
 }
 
diff --git a/drivers/acpi/sbs.c b/drivers/acpi/sbs.c
index d465ae6..dbd4849 100644
--- a/drivers/acpi/sbs.c
+++ b/drivers/acpi/sbs.c
@@ -450,7 +450,7 @@
 {
 	unsigned long x;
 	struct acpi_battery *battery = to_acpi_battery(dev_get_drvdata(dev));
-	if (sscanf(buf, "%ld\n", &x) == 1)
+	if (sscanf(buf, "%lu\n", &x) == 1)
 		battery->alarm_capacity = x /
 			(1000 * acpi_battery_scale(battery));
 	if (battery->present)
@@ -668,6 +668,8 @@
 	acpi_sbs_callback(sbs);
 	return 0;
 }
+#else
+#define acpi_sbs_resume NULL
 #endif
 
 static SIMPLE_DEV_PM_OPS(acpi_sbs_pm, NULL, acpi_sbs_resume);
diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
index 8349a55..08626c8 100644
--- a/drivers/acpi/thermal.c
+++ b/drivers/acpi/thermal.c
@@ -102,6 +102,8 @@
 
 #ifdef CONFIG_PM_SLEEP
 static int acpi_thermal_resume(struct device *dev);
+#else
+#define acpi_thermal_resume NULL
 #endif
 static SIMPLE_DEV_PM_OPS(acpi_thermal_pm, NULL, acpi_thermal_resume);
 
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c
index b727d10..b6ba88e 100644
--- a/drivers/acpi/video.c
+++ b/drivers/acpi/video.c
@@ -81,11 +81,12 @@
 module_param(allow_duplicates, bool, 0644);
 
 /*
- * For Windows 8 systems: if set ture and the GPU driver has
- * registered a backlight interface, skip registering ACPI video's.
+ * For Windows 8 systems: used to decide if video module
+ * should skip registering backlight interface of its own.
  */
-static bool use_native_backlight = false;
-module_param(use_native_backlight, bool, 0644);
+static int use_native_backlight_param = -1;
+module_param_named(use_native_backlight, use_native_backlight_param, int, 0444);
+static bool use_native_backlight_dmi = false;
 
 static int register_count;
 static struct mutex video_list_lock;
@@ -231,9 +232,17 @@
 static int acpi_video_switch_brightness(struct acpi_video_device *device,
 					 int event);
 
+static bool acpi_video_use_native_backlight(void)
+{
+	if (use_native_backlight_param != -1)
+		return use_native_backlight_param;
+	else
+		return use_native_backlight_dmi;
+}
+
 static bool acpi_video_verify_backlight_support(void)
 {
-	if (acpi_osi_is_win8() && use_native_backlight &&
+	if (acpi_osi_is_win8() && acpi_video_use_native_backlight() &&
 	    backlight_device_registered(BACKLIGHT_RAW))
 		return false;
 	return acpi_video_backlight_support();
@@ -398,6 +407,12 @@
 	return 0;
 }
 
+static int __init video_set_use_native_backlight(const struct dmi_system_id *d)
+{
+	use_native_backlight_dmi = true;
+	return 0;
+}
+
 static struct dmi_system_id video_dmi_table[] __initdata = {
 	/*
 	 * Broken _BQC workaround http://bugzilla.kernel.org/show_bug.cgi?id=13121
@@ -442,6 +457,120 @@
 		DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 7720"),
 		},
 	},
+	{
+	 .callback = video_set_use_native_backlight,
+	 .ident = "ThinkPad T430s",
+	 .matches = {
+		DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+		DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T430s"),
+		},
+	},
+	{
+	 .callback = video_set_use_native_backlight,
+	 .ident = "ThinkPad X230",
+	 .matches = {
+		DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+		DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X230"),
+		},
+	},
+	{
+	.callback = video_set_use_native_backlight,
+	.ident = "ThinkPad X1 Carbon",
+	.matches = {
+		DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+		DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X1 Carbon"),
+		},
+	},
+	{
+	 .callback = video_set_use_native_backlight,
+	 .ident = "Lenovo Yoga 13",
+	 .matches = {
+		DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+		DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo IdeaPad Yoga 13"),
+		},
+	},
+	{
+	 .callback = video_set_use_native_backlight,
+	 .ident = "Dell Inspiron 7520",
+	 .matches = {
+		DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+		DMI_MATCH(DMI_PRODUCT_VERSION, "Inspiron 7520"),
+		},
+	},
+	{
+	 .callback = video_set_use_native_backlight,
+	 .ident = "Acer Aspire 5733Z",
+	 .matches = {
+		DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+		DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5733Z"),
+		},
+	},
+	{
+	 .callback = video_set_use_native_backlight,
+	 .ident = "Acer Aspire V5-431",
+	 .matches = {
+		DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+		DMI_MATCH(DMI_PRODUCT_NAME, "Aspire V5-431"),
+		},
+	},
+	{
+	.callback = video_set_use_native_backlight,
+	.ident = "HP ProBook 4340s",
+	.matches = {
+		DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+		DMI_MATCH(DMI_PRODUCT_VERSION, "HP ProBook 4340s"),
+		},
+	},
+	{
+	.callback = video_set_use_native_backlight,
+	.ident = "HP ProBook 2013 models",
+	.matches = {
+		DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+		DMI_MATCH(DMI_PRODUCT_NAME, "HP ProBook "),
+		DMI_MATCH(DMI_PRODUCT_NAME, " G1"),
+		},
+	},
+	{
+	.callback = video_set_use_native_backlight,
+	.ident = "HP EliteBook 2013 models",
+	.matches = {
+		DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+		DMI_MATCH(DMI_PRODUCT_NAME, "HP EliteBook "),
+		DMI_MATCH(DMI_PRODUCT_NAME, " G1"),
+		},
+	},
+	{
+	.callback = video_set_use_native_backlight,
+	.ident = "HP ZBook 14",
+	.matches = {
+		DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+		DMI_MATCH(DMI_PRODUCT_NAME, "HP ZBook 14"),
+		},
+	},
+	{
+	.callback = video_set_use_native_backlight,
+	.ident = "HP ZBook 15",
+	.matches = {
+		DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+		DMI_MATCH(DMI_PRODUCT_NAME, "HP ZBook 15"),
+		},
+	},
+	{
+	.callback = video_set_use_native_backlight,
+	.ident = "HP ZBook 17",
+	.matches = {
+		DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+		DMI_MATCH(DMI_PRODUCT_NAME, "HP ZBook 17"),
+		},
+	},
+	{
+	.callback = video_set_use_native_backlight,
+	.ident = "HP EliteBook 8780w",
+	.matches = {
+		DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+		DMI_MATCH(DMI_PRODUCT_NAME, "HP EliteBook 8780w"),
+		},
+	},
 	{}
 };
 
@@ -685,6 +814,7 @@
 	union acpi_object *o;
 	struct acpi_video_device_brightness *br = NULL;
 	int result = -EINVAL;
+	u32 value;
 
 	if (!ACPI_SUCCESS(acpi_video_device_lcd_query_levels(device, &obj))) {
 		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Could not query available "
@@ -715,7 +845,12 @@
 			printk(KERN_ERR PREFIX "Invalid data\n");
 			continue;
 		}
-		br->levels[count] = (u32) o->integer.value;
+		value = (u32) o->integer.value;
+		/* Skip duplicate entries */
+		if (count > 2 && br->levels[count - 1] == value)
+			continue;
+
+		br->levels[count] = value;
 
 		if (br->levels[count] > max_level)
 			max_level = br->levels[count];
diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c
index a697b77..19080c8 100644
--- a/drivers/acpi/video_detect.c
+++ b/drivers/acpi/video_detect.c
@@ -168,22 +168,6 @@
 		DMI_MATCH(DMI_PRODUCT_NAME, "UL30A"),
 		},
 	},
-	{
-	.callback = video_detect_force_vendor,
-	.ident = "HP EliteBook Revolve 810",
-	.matches = {
-		DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
-		DMI_MATCH(DMI_PRODUCT_NAME, "HP EliteBook Revolve 810 G1"),
-		},
-	},
-	{
-	.callback = video_detect_force_vendor,
-	.ident = "Lenovo Yoga 13",
-	.matches = {
-		DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
-		DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo IdeaPad Yoga 13"),
-		},
-	},
 	{ },
 };
 
diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
index 4e73772..868429a 100644
--- a/drivers/ata/Kconfig
+++ b/drivers/ata/Kconfig
@@ -247,6 +247,7 @@
 
 config SATA_MV
 	tristate "Marvell SATA support"
+	select GENERIC_PHY
 	help
 	  This option enables support for the Marvell Serial ATA family.
 	  Currently supports 88SX[56]0[48][01] PCI(-X) chips,
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index dc2756f..c81d809 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -61,6 +61,7 @@
 	/* board IDs by feature in alphabetical order */
 	board_ahci,
 	board_ahci_ign_iferr,
+	board_ahci_noncq,
 	board_ahci_nosntf,
 	board_ahci_yes_fbs,
 
@@ -121,6 +122,13 @@
 		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &ahci_ops,
 	},
+	[board_ahci_noncq] = {
+		AHCI_HFLAGS	(AHCI_HFLAG_NO_NCQ),
+		.flags		= AHCI_FLAG_COMMON,
+		.pio_mask	= ATA_PIO4,
+		.udma_mask	= ATA_UDMA6,
+		.port_ops	= &ahci_ops,
+	},
 	[board_ahci_nosntf] = {
 		AHCI_HFLAGS	(AHCI_HFLAG_NO_SNTF),
 		.flags		= AHCI_FLAG_COMMON,
@@ -452,6 +460,12 @@
 	{ PCI_VDEVICE(ASMEDIA, 0x0611), board_ahci },	/* ASM1061 */
 	{ PCI_VDEVICE(ASMEDIA, 0x0612), board_ahci },	/* ASM1062 */
 
+	/*
+	 * Samsung SSDs found on some macbooks.  NCQ times out.
+	 * https://bugzilla.kernel.org/show_bug.cgi?id=60731
+	 */
+	{ PCI_VDEVICE(SAMSUNG, 0x1600), board_ahci_noncq },
+
 	/* Enmotus */
 	{ PCI_DEVICE(0x1c44, 0x8000), board_ahci },
 
@@ -1170,8 +1184,10 @@
 
 	nvec = rc;
 	rc = pci_enable_msi_block(pdev, nvec);
-	if (rc)
+	if (rc < 0)
 		goto intx;
+	else if (rc > 0)
+		goto single_msi;
 
 	return nvec;
 
diff --git a/drivers/ata/libata-pmp.c b/drivers/ata/libata-pmp.c
index 20fd337..7ccc084 100644
--- a/drivers/ata/libata-pmp.c
+++ b/drivers/ata/libata-pmp.c
@@ -447,8 +447,11 @@
 		 * otherwise.  Don't try hard to recover it.
 		 */
 		ap->pmp_link[ap->nr_pmp_links - 1].flags |= ATA_LFLAG_NO_RETRY;
-	} else if (vendor == 0x197b && devid == 0x2352) {
-		/* chip found in Thermaltake BlackX Duet, jmicron JMB350? */
+	} else if (vendor == 0x197b && (devid == 0x2352 || devid == 0x0325)) {
+		/*
+		 * 0x2352: found in Thermaltake BlackX Duet, jmicron JMB350?
+		 * 0x0325: jmicron JMB394.
+		 */
 		ata_for_each_link(link, ap, EDGE) {
 			/* SRST breaks detection and disks get misclassified
 			 * LPM disabled to avoid potential problems
diff --git a/drivers/ata/pata_imx.c b/drivers/ata/pata_imx.c
index 26386f0..b0b18ec 100644
--- a/drivers/ata/pata_imx.c
+++ b/drivers/ata/pata_imx.c
@@ -119,7 +119,9 @@
 		return PTR_ERR(priv->clk);
 	}
 
-	clk_prepare_enable(priv->clk);
+	ret = clk_prepare_enable(priv->clk);
+	if (ret)
+		return ret;
 
 	host = ata_host_alloc(&pdev->dev, 1);
 	if (!host) {
@@ -212,7 +214,9 @@
 	struct ata_host *host = dev_get_drvdata(dev);
 	struct pata_imx_priv *priv = host->private_data;
 
-	clk_prepare_enable(priv->clk);
+	int ret = clk_prepare_enable(priv->clk);
+	if (ret)
+		return ret;
 
 	__raw_writel(priv->ata_ctl, priv->host_regs + PATA_IMX_ATA_CONTROL);
 
diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c
index 52b8181..05c8a44 100644
--- a/drivers/ata/sata_mv.c
+++ b/drivers/ata/sata_mv.c
@@ -4104,7 +4104,6 @@
 	if (!hpriv->port_phys)
 		return -ENOMEM;
 	host->private_data = hpriv;
-	hpriv->n_ports = n_ports;
 	hpriv->board_idx = chip_soc;
 
 	host->iomap = NULL;
@@ -4132,13 +4131,18 @@
 			rc = PTR_ERR(hpriv->port_phys[port]);
 			hpriv->port_phys[port] = NULL;
 			if (rc != -EPROBE_DEFER)
-				dev_warn(&pdev->dev, "error getting phy %d",
-					rc);
+				dev_warn(&pdev->dev, "error getting phy %d", rc);
+
+			/* Cleanup only the initialized ports */
+			hpriv->n_ports = port;
 			goto err;
 		} else
 			phy_power_on(hpriv->port_phys[port]);
 	}
 
+	/* All the ports have been initialized */
+	hpriv->n_ports = n_ports;
+
 	/*
 	 * (Re-)program MBUS remapping windows if we are asked to.
 	 */
@@ -4176,7 +4180,7 @@
 		clk_disable_unprepare(hpriv->clk);
 		clk_put(hpriv->clk);
 	}
-	for (port = 0; port < n_ports; port++) {
+	for (port = 0; port < hpriv->n_ports; port++) {
 		if (!IS_ERR(hpriv->port_clks[port])) {
 			clk_disable_unprepare(hpriv->port_clks[port]);
 			clk_put(hpriv->port_clks[port]);
diff --git a/drivers/ata/sata_sil.c b/drivers/ata/sata_sil.c
index d67fc35..b7695e8 100644
--- a/drivers/ata/sata_sil.c
+++ b/drivers/ata/sata_sil.c
@@ -157,6 +157,7 @@
 	{ "ST380011ASL",	SIL_QUIRK_MOD15WRITE },
 	{ "ST3120022ASL",	SIL_QUIRK_MOD15WRITE },
 	{ "ST3160021ASL",	SIL_QUIRK_MOD15WRITE },
+	{ "TOSHIBA MK2561GSYN",	SIL_QUIRK_MOD15WRITE },
 	{ "Maxtor 4D060H3",	SIL_QUIRK_UDMA5MAX },
 	{ }
 };
diff --git a/drivers/base/dma-buf.c b/drivers/base/dma-buf.c
index 1e16cbd..61d6d62 100644
--- a/drivers/base/dma-buf.c
+++ b/drivers/base/dma-buf.c
@@ -616,36 +616,35 @@
 	if (ret)
 		return ret;
 
-	seq_printf(s, "\nDma-buf Objects:\n");
-	seq_printf(s, "\texp_name\tsize\tflags\tmode\tcount\n");
+	seq_puts(s, "\nDma-buf Objects:\n");
+	seq_puts(s, "size\tflags\tmode\tcount\texp_name\n");
 
 	list_for_each_entry(buf_obj, &db_list.head, list_node) {
 		ret = mutex_lock_interruptible(&buf_obj->lock);
 
 		if (ret) {
-			seq_printf(s,
-				  "\tERROR locking buffer object: skipping\n");
+			seq_puts(s,
+				 "\tERROR locking buffer object: skipping\n");
 			continue;
 		}
 
-		seq_printf(s, "\t");
-
-		seq_printf(s, "\t%s\t%08zu\t%08x\t%08x\t%08ld\n",
-				buf_obj->exp_name, buf_obj->size,
+		seq_printf(s, "%08zu\t%08x\t%08x\t%08ld\t%s\n",
+				buf_obj->size,
 				buf_obj->file->f_flags, buf_obj->file->f_mode,
-				(long)(buf_obj->file->f_count.counter));
+				(long)(buf_obj->file->f_count.counter),
+				buf_obj->exp_name);
 
-		seq_printf(s, "\t\tAttached Devices:\n");
+		seq_puts(s, "\tAttached Devices:\n");
 		attach_count = 0;
 
 		list_for_each_entry(attach_obj, &buf_obj->attachments, node) {
-			seq_printf(s, "\t\t");
+			seq_puts(s, "\t");
 
-			seq_printf(s, "%s\n", attach_obj->dev->init_name);
+			seq_printf(s, "%s\n", dev_name(attach_obj->dev));
 			attach_count++;
 		}
 
-		seq_printf(s, "\n\t\tTotal %d devices attached\n",
+		seq_printf(s, "Total %d devices attached\n\n",
 				attach_count);
 
 		count++;
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index 8a97ddf..c30df50e 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -1580,6 +1580,7 @@
 	switch (mode) {
 	case PM_HIBERNATION_PREPARE:
 	case PM_SUSPEND_PREPARE:
+	case PM_RESTORE_PREPARE:
 		kill_requests_without_uevent();
 		device_cache_fw_images();
 		break;
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 08ca8c9..cb003a6 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -1323,8 +1323,7 @@
 	up_read(&policy->rwsem);
 
 	if (cpu != policy->cpu) {
-		if (!frozen)
-			sysfs_remove_link(&dev->kobj, "cpufreq");
+		sysfs_remove_link(&dev->kobj, "cpufreq");
 	} else if (cpus > 1) {
 		new_cpu = cpufreq_nominate_new_policy_cpu(policy, cpu);
 		if (new_cpu >= 0) {
diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c
index c788abf..2cd36b9 100644
--- a/drivers/cpufreq/intel_pstate.c
+++ b/drivers/cpufreq/intel_pstate.c
@@ -34,12 +34,15 @@
 
 #define SAMPLE_COUNT		3
 
-#define BYT_RATIOS	0x66a
-#define BYT_VIDS        0x66b
+#define BYT_RATIOS		0x66a
+#define BYT_VIDS		0x66b
+#define BYT_TURBO_RATIOS	0x66c
 
-#define FRAC_BITS 8
+
+#define FRAC_BITS 6
 #define int_tofp(X) ((int64_t)(X) << FRAC_BITS)
 #define fp_toint(X) ((X) >> FRAC_BITS)
+#define FP_ROUNDUP(X) ((X) += 1 << FRAC_BITS)
 
 static inline int32_t mul_fp(int32_t x, int32_t y)
 {
@@ -357,7 +360,7 @@
 {
 	u64 value;
 	rdmsrl(BYT_RATIOS, value);
-	return value & 0xFF;
+	return (value >> 8) & 0xFF;
 }
 
 static int byt_get_max_pstate(void)
@@ -367,6 +370,13 @@
 	return (value >> 16) & 0xFF;
 }
 
+static int byt_get_turbo_pstate(void)
+{
+	u64 value;
+	rdmsrl(BYT_TURBO_RATIOS, value);
+	return value & 0x3F;
+}
+
 static void byt_set_pstate(struct cpudata *cpudata, int pstate)
 {
 	u64 val;
@@ -469,7 +479,7 @@
 	.funcs = {
 		.get_max = byt_get_max_pstate,
 		.get_min = byt_get_min_pstate,
-		.get_turbo = byt_get_max_pstate,
+		.get_turbo = byt_get_turbo_pstate,
 		.set = byt_set_pstate,
 		.get_vid = byt_get_vid,
 	},
@@ -547,18 +557,20 @@
 static inline void intel_pstate_calc_busy(struct cpudata *cpu,
 					struct sample *sample)
 {
-	u64 core_pct;
-	u64 c0_pct;
+	int32_t core_pct;
+	int32_t c0_pct;
 
-	core_pct = div64_u64(sample->aperf * 100, sample->mperf);
+	core_pct = div_fp(int_tofp((sample->aperf)),
+			int_tofp((sample->mperf)));
+	core_pct = mul_fp(core_pct, int_tofp(100));
+	FP_ROUNDUP(core_pct);
 
-	c0_pct = div64_u64(sample->mperf * 100, sample->tsc);
+	c0_pct = div_fp(int_tofp(sample->mperf), int_tofp(sample->tsc));
+
 	sample->freq = fp_toint(
-		mul_fp(int_tofp(cpu->pstate.max_pstate),
-			int_tofp(core_pct * 1000)));
+		mul_fp(int_tofp(cpu->pstate.max_pstate * 1000), core_pct));
 
-	sample->core_pct_busy = mul_fp(int_tofp(core_pct),
-				div_fp(int_tofp(c0_pct + 1), int_tofp(100)));
+	sample->core_pct_busy = mul_fp(core_pct, c0_pct);
 }
 
 static inline void intel_pstate_sample(struct cpudata *cpu)
@@ -570,6 +582,10 @@
 	rdmsrl(MSR_IA32_MPERF, mperf);
 	tsc = native_read_tsc();
 
+	aperf = aperf >> FRAC_BITS;
+	mperf = mperf >> FRAC_BITS;
+	tsc = tsc >> FRAC_BITS;
+
 	cpu->sample_ptr = (cpu->sample_ptr + 1) % SAMPLE_COUNT;
 	cpu->samples[cpu->sample_ptr].aperf = aperf;
 	cpu->samples[cpu->sample_ptr].mperf = mperf;
@@ -601,7 +617,8 @@
 	core_busy = cpu->samples[cpu->sample_ptr].core_pct_busy;
 	max_pstate = int_tofp(cpu->pstate.max_pstate);
 	current_pstate = int_tofp(cpu->pstate.current_pstate);
-	return mul_fp(core_busy, div_fp(max_pstate, current_pstate));
+	core_busy = mul_fp(core_busy, div_fp(max_pstate, current_pstate));
+	return FP_ROUNDUP(core_busy);
 }
 
 static inline void intel_pstate_adjust_busy_pstate(struct cpudata *cpu)
diff --git a/drivers/cpufreq/powernow-k8.c b/drivers/cpufreq/powernow-k8.c
index e10b646..6684e03 100644
--- a/drivers/cpufreq/powernow-k8.c
+++ b/drivers/cpufreq/powernow-k8.c
@@ -1076,7 +1076,7 @@
 {
 	struct powernow_k8_data *data;
 	struct init_on_cpu init_on_cpu;
-	int rc;
+	int rc, cpu;
 
 	smp_call_function_single(pol->cpu, check_supported_cpu, &rc, 1);
 	if (rc)
@@ -1140,7 +1140,9 @@
 	pr_debug("cpu_init done, current fid 0x%x, vid 0x%x\n",
 		 data->currfid, data->currvid);
 
-	per_cpu(powernow_data, pol->cpu) = data;
+	/* Point all the CPUs in this policy to the same data */
+	for_each_cpu(cpu, pol->cpus)
+		per_cpu(powernow_data, cpu) = data;
 
 	return 0;
 
@@ -1155,6 +1157,7 @@
 static int powernowk8_cpu_exit(struct cpufreq_policy *pol)
 {
 	struct powernow_k8_data *data = per_cpu(powernow_data, pol->cpu);
+	int cpu;
 
 	if (!data)
 		return -EINVAL;
@@ -1165,7 +1168,8 @@
 
 	kfree(data->powernow_table);
 	kfree(data);
-	per_cpu(powernow_data, pol->cpu) = NULL;
+	for_each_cpu(cpu, pol->cpus)
+		per_cpu(powernow_data, cpu) = NULL;
 
 	return 0;
 }
diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
index 4e79183..19041ce 100644
--- a/drivers/dma/imx-sdma.c
+++ b/drivers/dma/imx-sdma.c
@@ -449,6 +449,7 @@
 	{ .compatible = "fsl,imx51-sdma", .data = &sdma_imx51, },
 	{ .compatible = "fsl,imx35-sdma", .data = &sdma_imx35, },
 	{ .compatible = "fsl,imx31-sdma", .data = &sdma_imx31, },
+	{ .compatible = "fsl,imx25-sdma", .data = &sdma_imx25, },
 	{ /* sentinel */ }
 };
 MODULE_DEVICE_TABLE(of, sdma_dt_ids);
diff --git a/drivers/dma/ioat/dma.c b/drivers/dma/ioat/dma.c
index 8752918..4e3549a 100644
--- a/drivers/dma/ioat/dma.c
+++ b/drivers/dma/ioat/dma.c
@@ -77,7 +77,8 @@
 	attnstatus = readl(instance->reg_base + IOAT_ATTNSTATUS_OFFSET);
 	for_each_set_bit(bit, &attnstatus, BITS_PER_LONG) {
 		chan = ioat_chan_by_index(instance, bit);
-		tasklet_schedule(&chan->cleanup_task);
+		if (test_bit(IOAT_RUN, &chan->state))
+			tasklet_schedule(&chan->cleanup_task);
 	}
 
 	writeb(intrctrl, instance->reg_base + IOAT_INTRCTRL_OFFSET);
@@ -93,7 +94,8 @@
 {
 	struct ioat_chan_common *chan = data;
 
-	tasklet_schedule(&chan->cleanup_task);
+	if (test_bit(IOAT_RUN, &chan->state))
+		tasklet_schedule(&chan->cleanup_task);
 
 	return IRQ_HANDLED;
 }
@@ -116,7 +118,6 @@
 	chan->timer.function = device->timer_fn;
 	chan->timer.data = data;
 	tasklet_init(&chan->cleanup_task, device->cleanup_fn, data);
-	tasklet_disable(&chan->cleanup_task);
 }
 
 /**
@@ -354,13 +355,49 @@
 	writel(((u64) chan->completion_dma) >> 32,
 	       chan->reg_base + IOAT_CHANCMP_OFFSET_HIGH);
 
-	tasklet_enable(&chan->cleanup_task);
+	set_bit(IOAT_RUN, &chan->state);
 	ioat1_dma_start_null_desc(ioat);  /* give chain to dma device */
 	dev_dbg(to_dev(chan), "%s: allocated %d descriptors\n",
 		__func__, ioat->desccount);
 	return ioat->desccount;
 }
 
+void ioat_stop(struct ioat_chan_common *chan)
+{
+	struct ioatdma_device *device = chan->device;
+	struct pci_dev *pdev = device->pdev;
+	int chan_id = chan_num(chan);
+	struct msix_entry *msix;
+
+	/* 1/ stop irq from firing tasklets
+	 * 2/ stop the tasklet from re-arming irqs
+	 */
+	clear_bit(IOAT_RUN, &chan->state);
+
+	/* flush inflight interrupts */
+	switch (device->irq_mode) {
+	case IOAT_MSIX:
+		msix = &device->msix_entries[chan_id];
+		synchronize_irq(msix->vector);
+		break;
+	case IOAT_MSI:
+	case IOAT_INTX:
+		synchronize_irq(pdev->irq);
+		break;
+	default:
+		break;
+	}
+
+	/* flush inflight timers */
+	del_timer_sync(&chan->timer);
+
+	/* flush inflight tasklet runs */
+	tasklet_kill(&chan->cleanup_task);
+
+	/* final cleanup now that everything is quiesced and can't re-arm */
+	device->cleanup_fn((unsigned long) &chan->common);
+}
+
 /**
  * ioat1_dma_free_chan_resources - release all the descriptors
  * @chan: the channel to be cleaned
@@ -379,9 +416,7 @@
 	if (ioat->desccount == 0)
 		return;
 
-	tasklet_disable(&chan->cleanup_task);
-	del_timer_sync(&chan->timer);
-	ioat1_cleanup(ioat);
+	ioat_stop(chan);
 
 	/* Delay 100ms after reset to allow internal DMA logic to quiesce
 	 * before removing DMA descriptor resources.
@@ -526,8 +561,11 @@
 static void ioat1_cleanup_event(unsigned long data)
 {
 	struct ioat_dma_chan *ioat = to_ioat_chan((void *) data);
+	struct ioat_chan_common *chan = &ioat->base;
 
 	ioat1_cleanup(ioat);
+	if (!test_bit(IOAT_RUN, &chan->state))
+		return;
 	writew(IOAT_CHANCTRL_RUN, ioat->base.reg_base + IOAT_CHANCTRL_OFFSET);
 }
 
diff --git a/drivers/dma/ioat/dma.h b/drivers/dma/ioat/dma.h
index 11fb877..e982f00 100644
--- a/drivers/dma/ioat/dma.h
+++ b/drivers/dma/ioat/dma.h
@@ -356,6 +356,7 @@
 void ioat_kobject_add(struct ioatdma_device *device, struct kobj_type *type);
 void ioat_kobject_del(struct ioatdma_device *device);
 int ioat_dma_setup_interrupts(struct ioatdma_device *device);
+void ioat_stop(struct ioat_chan_common *chan);
 extern const struct sysfs_ops ioat_sysfs_ops;
 extern struct ioat_sysfs_entry ioat_version_attr;
 extern struct ioat_sysfs_entry ioat_cap_attr;
diff --git a/drivers/dma/ioat/dma_v2.c b/drivers/dma/ioat/dma_v2.c
index 5d3affe..8d10580 100644
--- a/drivers/dma/ioat/dma_v2.c
+++ b/drivers/dma/ioat/dma_v2.c
@@ -190,8 +190,11 @@
 void ioat2_cleanup_event(unsigned long data)
 {
 	struct ioat2_dma_chan *ioat = to_ioat2_chan((void *) data);
+	struct ioat_chan_common *chan = &ioat->base;
 
 	ioat2_cleanup(ioat);
+	if (!test_bit(IOAT_RUN, &chan->state))
+		return;
 	writew(IOAT_CHANCTRL_RUN, ioat->base.reg_base + IOAT_CHANCTRL_OFFSET);
 }
 
@@ -553,10 +556,10 @@
 	ioat->issued = 0;
 	ioat->tail = 0;
 	ioat->alloc_order = order;
+	set_bit(IOAT_RUN, &chan->state);
 	spin_unlock_bh(&ioat->prep_lock);
 	spin_unlock_bh(&chan->cleanup_lock);
 
-	tasklet_enable(&chan->cleanup_task);
 	ioat2_start_null_desc(ioat);
 
 	/* check that we got off the ground */
@@ -566,7 +569,6 @@
 	} while (i++ < 20 && !is_ioat_active(status) && !is_ioat_idle(status));
 
 	if (is_ioat_active(status) || is_ioat_idle(status)) {
-		set_bit(IOAT_RUN, &chan->state);
 		return 1 << ioat->alloc_order;
 	} else {
 		u32 chanerr = readl(chan->reg_base + IOAT_CHANERR_OFFSET);
@@ -809,11 +811,8 @@
 	if (!ioat->ring)
 		return;
 
-	tasklet_disable(&chan->cleanup_task);
-	del_timer_sync(&chan->timer);
-	device->cleanup_fn((unsigned long) c);
+	ioat_stop(chan);
 	device->reset_hw(chan);
-	clear_bit(IOAT_RUN, &chan->state);
 
 	spin_lock_bh(&chan->cleanup_lock);
 	spin_lock_bh(&ioat->prep_lock);
diff --git a/drivers/dma/ioat/dma_v3.c b/drivers/dma/ioat/dma_v3.c
index 820817e9..b9b38a1 100644
--- a/drivers/dma/ioat/dma_v3.c
+++ b/drivers/dma/ioat/dma_v3.c
@@ -464,8 +464,11 @@
 static void ioat3_cleanup_event(unsigned long data)
 {
 	struct ioat2_dma_chan *ioat = to_ioat2_chan((void *) data);
+	struct ioat_chan_common *chan = &ioat->base;
 
 	ioat3_cleanup(ioat);
+	if (!test_bit(IOAT_RUN, &chan->state))
+		return;
 	writew(IOAT_CHANCTRL_RUN, ioat->base.reg_base + IOAT_CHANCTRL_OFFSET);
 }
 
diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c
index 00a2de9..bf18c78 100644
--- a/drivers/dma/ste_dma40.c
+++ b/drivers/dma/ste_dma40.c
@@ -1641,6 +1641,7 @@
 	struct d40_chan *d40c = (struct d40_chan *) data;
 	struct d40_desc *d40d;
 	unsigned long flags;
+	bool callback_active;
 	dma_async_tx_callback callback;
 	void *callback_param;
 
@@ -1668,6 +1669,7 @@
 	}
 
 	/* Callback to client */
+	callback_active = !!(d40d->txd.flags & DMA_PREP_INTERRUPT);
 	callback = d40d->txd.callback;
 	callback_param = d40d->txd.callback_param;
 
@@ -1690,7 +1692,7 @@
 
 	spin_unlock_irqrestore(&d40c->lock, flags);
 
-	if (callback && (d40d->txd.flags & DMA_PREP_INTERRUPT))
+	if (callback_active && callback)
 		callback(callback_param);
 
 	return;
diff --git a/drivers/edac/i7300_edac.c b/drivers/edac/i7300_edac.c
index d63f479..57e96a3 100644
--- a/drivers/edac/i7300_edac.c
+++ b/drivers/edac/i7300_edac.c
@@ -943,33 +943,35 @@
 
 	/* Attempt to 'get' the MCH register we want */
 	pdev = NULL;
-	while (!pvt->pci_dev_16_1_fsb_addr_map ||
-	       !pvt->pci_dev_16_2_fsb_err_regs) {
-		pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
-				      PCI_DEVICE_ID_INTEL_I7300_MCH_ERR, pdev);
-		if (!pdev) {
-			/* End of list, leave */
-			i7300_printk(KERN_ERR,
-				"'system address,Process Bus' "
-				"device not found:"
-				"vendor 0x%x device 0x%x ERR funcs "
-				"(broken BIOS?)\n",
-				PCI_VENDOR_ID_INTEL,
-				PCI_DEVICE_ID_INTEL_I7300_MCH_ERR);
-			goto error;
-		}
-
+	while ((pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
+				      PCI_DEVICE_ID_INTEL_I7300_MCH_ERR,
+				      pdev))) {
 		/* Store device 16 funcs 1 and 2 */
 		switch (PCI_FUNC(pdev->devfn)) {
 		case 1:
-			pvt->pci_dev_16_1_fsb_addr_map = pdev;
+			if (!pvt->pci_dev_16_1_fsb_addr_map)
+				pvt->pci_dev_16_1_fsb_addr_map =
+							pci_dev_get(pdev);
 			break;
 		case 2:
-			pvt->pci_dev_16_2_fsb_err_regs = pdev;
+			if (!pvt->pci_dev_16_2_fsb_err_regs)
+				pvt->pci_dev_16_2_fsb_err_regs =
+							pci_dev_get(pdev);
 			break;
 		}
 	}
 
+	if (!pvt->pci_dev_16_1_fsb_addr_map ||
+	    !pvt->pci_dev_16_2_fsb_err_regs) {
+		/* At least one device was not found */
+		i7300_printk(KERN_ERR,
+			"'system address,Process Bus' device not found:"
+			"vendor 0x%x device 0x%x ERR funcs (broken BIOS?)\n",
+			PCI_VENDOR_ID_INTEL,
+			PCI_DEVICE_ID_INTEL_I7300_MCH_ERR);
+		goto error;
+	}
+
 	edac_dbg(1, "System Address, processor bus- PCI Bus ID: %s  %x:%x\n",
 		 pci_name(pvt->pci_dev_16_0_fsb_ctlr),
 		 pvt->pci_dev_16_0_fsb_ctlr->vendor,
diff --git a/drivers/edac/i7core_edac.c b/drivers/edac/i7core_edac.c
index 87533ca..d871275 100644
--- a/drivers/edac/i7core_edac.c
+++ b/drivers/edac/i7core_edac.c
@@ -1334,14 +1334,19 @@
 	 * is at addr 8086:2c40, instead of 8086:2c41. So, we need
 	 * to probe for the alternate address in case of failure
 	 */
-	if (dev_descr->dev_id == PCI_DEVICE_ID_INTEL_I7_NONCORE && !pdev)
+	if (dev_descr->dev_id == PCI_DEVICE_ID_INTEL_I7_NONCORE && !pdev) {
+		pci_dev_get(*prev);	/* pci_get_device will put it */
 		pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
 				      PCI_DEVICE_ID_INTEL_I7_NONCORE_ALT, *prev);
+	}
 
-	if (dev_descr->dev_id == PCI_DEVICE_ID_INTEL_LYNNFIELD_NONCORE && !pdev)
+	if (dev_descr->dev_id == PCI_DEVICE_ID_INTEL_LYNNFIELD_NONCORE &&
+	    !pdev) {
+		pci_dev_get(*prev);	/* pci_get_device will put it */
 		pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
 				      PCI_DEVICE_ID_INTEL_LYNNFIELD_NONCORE_ALT,
 				      *prev);
+	}
 
 	if (!pdev) {
 		if (*prev) {
diff --git a/drivers/extcon/extcon-arizona.c b/drivers/extcon/extcon-arizona.c
index c20602f..98a14f6 100644
--- a/drivers/extcon/extcon-arizona.c
+++ b/drivers/extcon/extcon-arizona.c
@@ -222,27 +222,19 @@
 	struct snd_soc_dapm_context *dapm = arizona->dapm;
 	int ret;
 
-	mutex_lock(&dapm->card->dapm_mutex);
-
 	ret = snd_soc_dapm_force_enable_pin(dapm, widget);
 	if (ret != 0)
 		dev_warn(arizona->dev, "Failed to enable %s: %d\n",
 			 widget, ret);
 
-	mutex_unlock(&dapm->card->dapm_mutex);
-
 	snd_soc_dapm_sync(dapm);
 
 	if (!arizona->pdata.micd_force_micbias) {
-		mutex_lock(&dapm->card->dapm_mutex);
-
 		ret = snd_soc_dapm_disable_pin(arizona->dapm, widget);
 		if (ret != 0)
 			dev_warn(arizona->dev, "Failed to disable %s: %d\n",
 				 widget, ret);
 
-		mutex_unlock(&dapm->card->dapm_mutex);
-
 		snd_soc_dapm_sync(dapm);
 	}
 }
@@ -304,16 +296,12 @@
 				 ARIZONA_MICD_ENA, 0,
 				 &change);
 
-	mutex_lock(&dapm->card->dapm_mutex);
-
 	ret = snd_soc_dapm_disable_pin(dapm, widget);
 	if (ret != 0)
 		dev_warn(arizona->dev,
 			 "Failed to disable %s: %d\n",
 			 widget, ret);
 
-	mutex_unlock(&dapm->card->dapm_mutex);
-
 	snd_soc_dapm_sync(dapm);
 
 	if (info->micd_reva) {
diff --git a/drivers/fmc/fmc-write-eeprom.c b/drivers/fmc/fmc-write-eeprom.c
index ee5b479..9bb2cbd 100644
--- a/drivers/fmc/fmc-write-eeprom.c
+++ b/drivers/fmc/fmc-write-eeprom.c
@@ -27,7 +27,7 @@
 /* The "file=" is like the generic "gateware=" used elsewhere */
 static char *fwe_file[FMC_MAX_CARDS];
 static int fwe_file_n;
-module_param_array_named(file, fwe_file, charp, &fwe_file_n, 444);
+module_param_array_named(file, fwe_file, charp, &fwe_file_n, 0444);
 
 static int fwe_run_tlv(struct fmc_device *fmc, const struct firmware *fw,
 	int write)
diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c
index dffc836..f4dc9b7 100644
--- a/drivers/gpu/drm/drm_ioctl.c
+++ b/drivers/gpu/drm/drm_ioctl.c
@@ -296,6 +296,18 @@
 	case DRM_CAP_ASYNC_PAGE_FLIP:
 		req->value = dev->mode_config.async_page_flip;
 		break;
+	case DRM_CAP_CURSOR_WIDTH:
+		if (dev->mode_config.cursor_width)
+			req->value = dev->mode_config.cursor_width;
+		else
+			req->value = 64;
+		break;
+	case DRM_CAP_CURSOR_HEIGHT:
+		if (dev->mode_config.cursor_height)
+			req->value = dev->mode_config.cursor_height;
+		else
+			req->value = 64;
+		break;
 	default:
 		return -EINVAL;
 	}
diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c
index fa18cf3..faa77f5 100644
--- a/drivers/gpu/drm/i2c/tda998x_drv.c
+++ b/drivers/gpu/drm/i2c/tda998x_drv.c
@@ -1151,8 +1151,10 @@
 
 	priv->current_page = 0xff;
 	priv->cec = i2c_new_dummy(client->adapter, 0x34);
-	if (!priv->cec)
+	if (!priv->cec) {
+		kfree(priv);
 		return -ENODEV;
+	}
 	priv->dpms = DRM_MODE_DPMS_OFF;
 
 	encoder_slave->slave_priv = priv;
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 9fa2434..4c16728 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -8586,6 +8586,20 @@
 	if (ring->id == RCS)
 		len += 6;
 
+	/*
+	 * BSpec MI_DISPLAY_FLIP for IVB:
+	 * "The full packet must be contained within the same cache line."
+	 *
+	 * Currently the LRI+SRM+MI_DISPLAY_FLIP all fit within the same
+	 * cacheline, if we ever start emitting more commands before
+	 * the MI_DISPLAY_FLIP we may need to first emit everything else,
+	 * then do the cacheline alignment, and finally emit the
+	 * MI_DISPLAY_FLIP.
+	 */
+	ret = intel_ring_cacheline_align(ring);
+	if (ret)
+		goto err_unpin;
+
 	ret = intel_ring_begin(ring, len);
 	if (ret)
 		goto err_unpin;
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 2f517b8..57552eb 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -537,6 +537,7 @@
 	uint8_t	msg[20];
 	int msg_bytes;
 	uint8_t	ack;
+	int retry;
 
 	if (WARN_ON(send_bytes > 16))
 		return -E2BIG;
@@ -548,19 +549,21 @@
 	msg[3] = send_bytes - 1;
 	memcpy(&msg[4], send, send_bytes);
 	msg_bytes = send_bytes + 4;
-	for (;;) {
+	for (retry = 0; retry < 7; retry++) {
 		ret = intel_dp_aux_ch(intel_dp, msg, msg_bytes, &ack, 1);
 		if (ret < 0)
 			return ret;
 		ack >>= 4;
 		if ((ack & DP_AUX_NATIVE_REPLY_MASK) == DP_AUX_NATIVE_REPLY_ACK)
-			break;
+			return send_bytes;
 		else if ((ack & DP_AUX_NATIVE_REPLY_MASK) == DP_AUX_NATIVE_REPLY_DEFER)
-			udelay(100);
+			usleep_range(400, 500);
 		else
 			return -EIO;
 	}
-	return send_bytes;
+
+	DRM_ERROR("too many retries, giving up\n");
+	return -EIO;
 }
 
 /* Write a single byte to the aux channel in native mode */
@@ -582,6 +585,7 @@
 	int reply_bytes;
 	uint8_t ack;
 	int ret;
+	int retry;
 
 	if (WARN_ON(recv_bytes > 19))
 		return -E2BIG;
@@ -595,7 +599,7 @@
 	msg_bytes = 4;
 	reply_bytes = recv_bytes + 1;
 
-	for (;;) {
+	for (retry = 0; retry < 7; retry++) {
 		ret = intel_dp_aux_ch(intel_dp, msg, msg_bytes,
 				      reply, reply_bytes);
 		if (ret == 0)
@@ -608,10 +612,13 @@
 			return ret - 1;
 		}
 		else if ((ack & DP_AUX_NATIVE_REPLY_MASK) == DP_AUX_NATIVE_REPLY_DEFER)
-			udelay(100);
+			usleep_range(400, 500);
 		else
 			return -EIO;
 	}
+
+	DRM_ERROR("too many retries, giving up\n");
+	return -EIO;
 }
 
 static int
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c
index b7f1742..31b36c5 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.c
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
@@ -1653,6 +1653,27 @@
 	return 0;
 }
 
+/* Align the ring tail to a cacheline boundary */
+int intel_ring_cacheline_align(struct intel_ring_buffer *ring)
+{
+	int num_dwords = (64 - (ring->tail & 63)) / sizeof(uint32_t);
+	int ret;
+
+	if (num_dwords == 0)
+		return 0;
+
+	ret = intel_ring_begin(ring, num_dwords);
+	if (ret)
+		return ret;
+
+	while (num_dwords--)
+		intel_ring_emit(ring, MI_NOOP);
+
+	intel_ring_advance(ring);
+
+	return 0;
+}
+
 void intel_ring_init_seqno(struct intel_ring_buffer *ring, u32 seqno)
 {
 	struct drm_i915_private *dev_priv = ring->dev->dev_private;
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h
index 71a73f4..0b243ce 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.h
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.h
@@ -233,6 +233,7 @@
 void intel_cleanup_ring_buffer(struct intel_ring_buffer *ring);
 
 int __must_check intel_ring_begin(struct intel_ring_buffer *ring, int n);
+int __must_check intel_ring_cacheline_align(struct intel_ring_buffer *ring);
 static inline void intel_ring_emit(struct intel_ring_buffer *ring,
 				   u32 data)
 {
diff --git a/drivers/gpu/drm/nouveau/Makefile b/drivers/gpu/drm/nouveau/Makefile
index e88145b..d310c19 100644
--- a/drivers/gpu/drm/nouveau/Makefile
+++ b/drivers/gpu/drm/nouveau/Makefile
@@ -141,6 +141,7 @@
 nouveau-y += core/subdev/mc/nv04.o
 nouveau-y += core/subdev/mc/nv40.o
 nouveau-y += core/subdev/mc/nv44.o
+nouveau-y += core/subdev/mc/nv4c.o
 nouveau-y += core/subdev/mc/nv50.o
 nouveau-y += core/subdev/mc/nv94.o
 nouveau-y += core/subdev/mc/nv98.o
diff --git a/drivers/gpu/drm/nouveau/core/engine/device/nv40.c b/drivers/gpu/drm/nouveau/core/engine/device/nv40.c
index 1b653dd..08b8859 100644
--- a/drivers/gpu/drm/nouveau/core/engine/device/nv40.c
+++ b/drivers/gpu/drm/nouveau/core/engine/device/nv40.c
@@ -311,7 +311,7 @@
 		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;
 		device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
 		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
-		device->oclass[NVDEV_SUBDEV_MC     ] =  nv44_mc_oclass;
+		device->oclass[NVDEV_SUBDEV_MC     ] =  nv4c_mc_oclass;
 		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv31_bus_oclass;
 		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
 		device->oclass[NVDEV_SUBDEV_FB     ] =  nv46_fb_oclass;
@@ -334,7 +334,7 @@
 		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;
 		device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
 		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
-		device->oclass[NVDEV_SUBDEV_MC     ] =  nv44_mc_oclass;
+		device->oclass[NVDEV_SUBDEV_MC     ] =  nv4c_mc_oclass;
 		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv31_bus_oclass;
 		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
 		device->oclass[NVDEV_SUBDEV_FB     ] =  nv4e_fb_oclass;
@@ -357,7 +357,7 @@
 		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;
 		device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
 		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
-		device->oclass[NVDEV_SUBDEV_MC     ] =  nv44_mc_oclass;
+		device->oclass[NVDEV_SUBDEV_MC     ] =  nv4c_mc_oclass;
 		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv31_bus_oclass;
 		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
 		device->oclass[NVDEV_SUBDEV_FB     ] =  nv46_fb_oclass;
@@ -380,7 +380,7 @@
 		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;
 		device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
 		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
-		device->oclass[NVDEV_SUBDEV_MC     ] =  nv44_mc_oclass;
+		device->oclass[NVDEV_SUBDEV_MC     ] =  nv4c_mc_oclass;
 		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv31_bus_oclass;
 		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
 		device->oclass[NVDEV_SUBDEV_FB     ] =  nv46_fb_oclass;
@@ -403,7 +403,7 @@
 		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;
 		device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
 		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
-		device->oclass[NVDEV_SUBDEV_MC     ] =  nv44_mc_oclass;
+		device->oclass[NVDEV_SUBDEV_MC     ] =  nv4c_mc_oclass;
 		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv31_bus_oclass;
 		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
 		device->oclass[NVDEV_SUBDEV_FB     ] =  nv46_fb_oclass;
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c
index 940eaa5..9ad722e 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c
@@ -1142,7 +1142,7 @@
 	if (conf != ~0) {
 		if (outp.location == 0 && outp.type == DCB_OUTPUT_DP) {
 			u32 soff = (ffs(outp.or) - 1) * 0x08;
-			u32 ctrl = nv_rd32(priv, 0x610798 + soff);
+			u32 ctrl = nv_rd32(priv, 0x610794 + soff);
 			u32 datarate;
 
 			switch ((ctrl & 0x000f0000) >> 16) {
diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c
index 9a850fe..54c1b5b 100644
--- a/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c
@@ -112,7 +112,7 @@
 
 	nv_wr32(priv, 0x002270, cur->addr >> 12);
 	nv_wr32(priv, 0x002274, (engine << 20) | (p >> 3));
-	if (!nv_wait(priv, 0x002284 + (engine * 4), 0x00100000, 0x00000000))
+	if (!nv_wait(priv, 0x002284 + (engine * 8), 0x00100000, 0x00000000))
 		nv_error(priv, "runlist %d update timeout\n", engine);
 	mutex_unlock(&nv_subdev(priv)->mutex);
 }
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c
index 30ed19c..7a367c4 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c
@@ -539,7 +539,7 @@
 				ustatus &= ~0x04030000;
 			}
 			if (ustatus && display) {
-				nv_error("%s - TP%d:", name, i);
+				nv_error(priv, "%s - TP%d:", name, i);
 				nouveau_bitfield_print(nv50_mpc_traps, ustatus);
 				pr_cont("\n");
 				ustatus = 0;
diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/mc.h b/drivers/gpu/drm/nouveau/core/include/subdev/mc.h
index adc88b7..3c6738e 100644
--- a/drivers/gpu/drm/nouveau/core/include/subdev/mc.h
+++ b/drivers/gpu/drm/nouveau/core/include/subdev/mc.h
@@ -47,6 +47,7 @@
 extern struct nouveau_oclass *nv04_mc_oclass;
 extern struct nouveau_oclass *nv40_mc_oclass;
 extern struct nouveau_oclass *nv44_mc_oclass;
+extern struct nouveau_oclass *nv4c_mc_oclass;
 extern struct nouveau_oclass *nv50_mc_oclass;
 extern struct nouveau_oclass *nv94_mc_oclass;
 extern struct nouveau_oclass *nv98_mc_oclass;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/base.c b/drivers/gpu/drm/nouveau/core/subdev/bios/base.c
index aa0fbbe..ef0c9c4 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/bios/base.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/bios/base.c
@@ -130,6 +130,10 @@
 	u16 pcir;
 	int i;
 
+	/* there is no prom on nv4x IGP's */
+	if (device->card_type == NV_40 && device->chipset >= 0x4c)
+		return;
+
 	/* enable access to rom */
 	if (device->card_type >= NV_50)
 		pcireg = 0x088050;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nv1a.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nv1a.c
index 9159a5c..265d125 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/fb/nv1a.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nv1a.c
@@ -36,7 +36,7 @@
 		.fini = _nouveau_fb_fini,
 	},
 	.base.memtype = nv04_fb_memtype_valid,
-	.base.ram = &nv10_ram_oclass,
+	.base.ram = &nv1a_ram_oclass,
 	.tile.regions = 8,
 	.tile.init = nv10_fb_tile_init,
 	.tile.fini = nv10_fb_tile_fini,
diff --git a/drivers/gpu/drm/nouveau/core/subdev/mc/nv04.h b/drivers/gpu/drm/nouveau/core/subdev/mc/nv04.h
index b0d5c31..81a408e 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/mc/nv04.h
+++ b/drivers/gpu/drm/nouveau/core/subdev/mc/nv04.h
@@ -14,6 +14,7 @@
 extern const struct nouveau_mc_intr nv04_mc_intr[];
 int  nv04_mc_init(struct nouveau_object *);
 void nv40_mc_msi_rearm(struct nouveau_mc *);
+int  nv44_mc_init(struct nouveau_object *object);
 int  nv50_mc_init(struct nouveau_object *);
 extern const struct nouveau_mc_intr nv50_mc_intr[];
 extern const struct nouveau_mc_intr nvc0_mc_intr[];
diff --git a/drivers/gpu/drm/nouveau/core/subdev/mc/nv44.c b/drivers/gpu/drm/nouveau/core/subdev/mc/nv44.c
index 3bfee5c..cc4d0d2 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/mc/nv44.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/mc/nv44.c
@@ -24,7 +24,7 @@
 
 #include "nv04.h"
 
-static int
+int
 nv44_mc_init(struct nouveau_object *object)
 {
 	struct nv04_mc_priv *priv = (void *)object;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/mc/nv4c.c b/drivers/gpu/drm/nouveau/core/subdev/mc/nv4c.c
new file mode 100644
index 0000000..a75c35c
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/subdev/mc/nv4c.c
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2014 Ilia Mirkin
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ilia Mirkin
+ */
+
+#include "nv04.h"
+
+static void
+nv4c_mc_msi_rearm(struct nouveau_mc *pmc)
+{
+	struct nv04_mc_priv *priv = (void *)pmc;
+	nv_wr08(priv, 0x088050, 0xff);
+}
+
+struct nouveau_oclass *
+nv4c_mc_oclass = &(struct nouveau_mc_oclass) {
+	.base.handle = NV_SUBDEV(MC, 0x4c),
+	.base.ofuncs = &(struct nouveau_ofuncs) {
+		.ctor = nv04_mc_ctor,
+		.dtor = _nouveau_mc_dtor,
+		.init = nv44_mc_init,
+		.fini = _nouveau_mc_fini,
+	},
+	.intr = nv04_mc_intr,
+	.msi_rearm = nv4c_mc_msi_rearm,
+}.base;
diff --git a/drivers/gpu/drm/nouveau/nouveau_acpi.c b/drivers/gpu/drm/nouveau/nouveau_acpi.c
index 4ef83df..83face3 100644
--- a/drivers/gpu/drm/nouveau/nouveau_acpi.c
+++ b/drivers/gpu/drm/nouveau/nouveau_acpi.c
@@ -106,6 +106,29 @@
 	return 0;
 }
 
+/*
+ * On some platforms, _DSM(nouveau_op_dsm_muid, func0) has special
+ * requirements on the fourth parameter, so a private implementation
+ * instead of using acpi_check_dsm().
+ */
+static int nouveau_check_optimus_dsm(acpi_handle handle)
+{
+	int result;
+
+	/*
+	 * Function 0 returns a Buffer containing available functions.
+	 * The args parameter is ignored for function 0, so just put 0 in it
+	 */
+	if (nouveau_optimus_dsm(handle, 0, 0, &result))
+		return 0;
+
+	/*
+	 * ACPI Spec v4 9.14.1: if bit 0 is zero, no function is supported.
+	 * If the n-th bit is enabled, function n is supported
+	 */
+	return result & 1 && result & (1 << NOUVEAU_DSM_OPTIMUS_CAPS);
+}
+
 static int nouveau_dsm(acpi_handle handle, int func, int arg)
 {
 	int ret = 0;
@@ -207,8 +230,7 @@
 			   1 << NOUVEAU_DSM_POWER))
 		retval |= NOUVEAU_DSM_HAS_MUX;
 
-	if (acpi_check_dsm(dhandle, nouveau_op_dsm_muid, 0x00000100,
-			   1 << NOUVEAU_DSM_OPTIMUS_CAPS))
+	if (nouveau_check_optimus_dsm(dhandle))
 		retval |= NOUVEAU_DSM_HAS_OPT;
 
 	if (retval & NOUVEAU_DSM_HAS_OPT) {
diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c
index 488686d..4aed171 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bo.c
+++ b/drivers/gpu/drm/nouveau/nouveau_bo.c
@@ -1249,7 +1249,7 @@
 			mem->bus.is_iomem = !dev->agp->cant_use_aperture;
 		}
 #endif
-		if (!node->memtype)
+		if (nv_device(drm->device)->card_type < NV_50 || !node->memtype)
 			/* untiled */
 			break;
 		/* fallthrough, tiled memory */
diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c
index 78c8e71..89c484d 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drm.c
+++ b/drivers/gpu/drm/nouveau/nouveau_drm.c
@@ -376,6 +376,8 @@
 	if (ret)
 		goto fail_device;
 
+	dev->irq_enabled = true;
+
 	/* workaround an odd issue on nvc1 by disabling the device's
 	 * nosnoop capability.  hopefully won't cause issues until a
 	 * better fix is found - assuming there is one...
@@ -475,6 +477,7 @@
 	struct nouveau_drm *drm = nouveau_drm(dev);
 	struct nouveau_object *device;
 
+	dev->irq_enabled = false;
 	device = drm->client.base.device;
 	drm_put_dev(dev);
 
diff --git a/drivers/gpu/drm/nouveau/nouveau_vga.c b/drivers/gpu/drm/nouveau/nouveau_vga.c
index 81638d7..471347e 100644
--- a/drivers/gpu/drm/nouveau/nouveau_vga.c
+++ b/drivers/gpu/drm/nouveau/nouveau_vga.c
@@ -14,7 +14,9 @@
 {
 	struct nouveau_device *device = nouveau_dev(priv);
 
-	if (device->chipset >= 0x40)
+	if (device->card_type == NV_40 && device->chipset >= 0x4c)
+		nv_wr32(device, 0x088060, state);
+	else if (device->chipset >= 0x40)
 		nv_wr32(device, 0x088054, state);
 	else
 		nv_wr32(device, 0x001854, state);
diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c
index a9338c8..daa4dd3 100644
--- a/drivers/gpu/drm/radeon/atombios_crtc.c
+++ b/drivers/gpu/drm/radeon/atombios_crtc.c
@@ -559,7 +559,7 @@
 	u32 adjusted_clock = mode->clock;
 	int encoder_mode = atombios_get_encoder_mode(encoder);
 	u32 dp_clock = mode->clock;
-	int bpc = radeon_get_monitor_bpc(connector);
+	int bpc = radeon_crtc->bpc;
 	bool is_duallink = radeon_dig_monitor_is_duallink(encoder, mode->clock);
 
 	/* reset the pll flags */
@@ -1176,7 +1176,7 @@
 		evergreen_tiling_fields(tiling_flags, &bankw, &bankh, &mtaspect, &tile_split);
 
 		/* Set NUM_BANKS. */
-		if (rdev->family >= CHIP_BONAIRE) {
+		if (rdev->family >= CHIP_TAHITI) {
 			unsigned tileb, index, num_banks, tile_split_bytes;
 
 			/* Calculate the macrotile mode index. */
@@ -1194,13 +1194,14 @@
 				return -EINVAL;
 			}
 
-			num_banks = (rdev->config.cik.macrotile_mode_array[index] >> 6) & 0x3;
+			if (rdev->family >= CHIP_BONAIRE)
+				num_banks = (rdev->config.cik.macrotile_mode_array[index] >> 6) & 0x3;
+			else
+				num_banks = (rdev->config.si.tile_mode_array[index] >> 20) & 0x3;
 			fb_format |= EVERGREEN_GRPH_NUM_BANKS(num_banks);
 		} else {
-			/* SI and older. */
-			if (rdev->family >= CHIP_TAHITI)
-				tmp = rdev->config.si.tile_config;
-			else if (rdev->family >= CHIP_CAYMAN)
+			/* NI and older. */
+			if (rdev->family >= CHIP_CAYMAN)
 				tmp = rdev->config.cayman.tile_config;
 			else
 				tmp = rdev->config.evergreen.tile_config;
@@ -1773,6 +1774,20 @@
 			return ATOM_PPLL1;
 		DRM_ERROR("unable to allocate a PPLL\n");
 		return ATOM_PPLL_INVALID;
+	} else if (ASIC_IS_DCE41(rdev)) {
+		/* Don't share PLLs on DCE4.1 chips */
+		if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(radeon_crtc->encoder))) {
+			if (rdev->clock.dp_extclk)
+				/* skip PPLL programming if using ext clock */
+				return ATOM_PPLL_INVALID;
+		}
+		pll_in_use = radeon_get_pll_use_mask(crtc);
+		if (!(pll_in_use & (1 << ATOM_PPLL1)))
+			return ATOM_PPLL1;
+		if (!(pll_in_use & (1 << ATOM_PPLL2)))
+			return ATOM_PPLL2;
+		DRM_ERROR("unable to allocate a PPLL\n");
+		return ATOM_PPLL_INVALID;
 	} else if (ASIC_IS_DCE4(rdev)) {
 		/* in DP mode, the DP ref clock can come from PPLL, DCPLL, or ext clock,
 		 * depending on the asic:
@@ -1800,7 +1815,7 @@
 				if (pll != ATOM_PPLL_INVALID)
 					return pll;
 			}
-		} else if (!ASIC_IS_DCE41(rdev)) { /* Don't share PLLs on DCE4.1 chips */
+		} else {
 			/* use the same PPLL for all monitors with the same clock */
 			pll = radeon_get_shared_nondp_ppll(crtc);
 			if (pll != ATOM_PPLL_INVALID)
diff --git a/drivers/gpu/drm/radeon/atombios_encoders.c b/drivers/gpu/drm/radeon/atombios_encoders.c
index a42d615..2cec2ab 100644
--- a/drivers/gpu/drm/radeon/atombios_encoders.c
+++ b/drivers/gpu/drm/radeon/atombios_encoders.c
@@ -464,11 +464,12 @@
 
 static u8 radeon_atom_get_bpc(struct drm_encoder *encoder)
 {
-	struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
 	int bpc = 8;
 
-	if (connector)
-		bpc = radeon_get_monitor_bpc(connector);
+	if (encoder->crtc) {
+		struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
+		bpc = radeon_crtc->bpc;
+	}
 
 	switch (bpc) {
 	case 0:
diff --git a/drivers/gpu/drm/radeon/dce6_afmt.c b/drivers/gpu/drm/radeon/dce6_afmt.c
index 713a5d3..94e8587 100644
--- a/drivers/gpu/drm/radeon/dce6_afmt.c
+++ b/drivers/gpu/drm/radeon/dce6_afmt.c
@@ -278,13 +278,15 @@
 	return !ASIC_IS_NODCE(rdev);
 }
 
-static void dce6_audio_enable(struct radeon_device *rdev,
-			      struct r600_audio_pin *pin,
-			      bool enable)
+void dce6_audio_enable(struct radeon_device *rdev,
+		       struct r600_audio_pin *pin,
+		       bool enable)
 {
+	if (!pin)
+		return;
+
 	WREG32_ENDPOINT(pin->offset, AZ_F0_CODEC_PIN_CONTROL_HOTPLUG_CONTROL,
-			AUDIO_ENABLED);
-	DRM_INFO("%s audio %d support\n", enable ? "Enabling" : "Disabling", pin->id);
+			enable ? AUDIO_ENABLED : 0);
 }
 
 static const u32 pin_offsets[7] =
@@ -323,7 +325,8 @@
 		rdev->audio.pin[i].connected = false;
 		rdev->audio.pin[i].offset = pin_offsets[i];
 		rdev->audio.pin[i].id = i;
-		dce6_audio_enable(rdev, &rdev->audio.pin[i], true);
+		/* disable audio.  it will be set up later */
+		dce6_audio_enable(rdev, &rdev->audio.pin[i], false);
 	}
 
 	return 0;
diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c
index f2b9e21..8a2c010 100644
--- a/drivers/gpu/drm/radeon/evergreen.c
+++ b/drivers/gpu/drm/radeon/evergreen.c
@@ -1680,7 +1680,7 @@
 	case RADEON_HPD_6:
 		if (RREG32(DC_HPD6_INT_STATUS) & DC_HPDx_SENSE)
 			connected = true;
-			break;
+		break;
 	default:
 		break;
 	}
@@ -5475,9 +5475,9 @@
 	radeon_wb_fini(rdev);
 	radeon_ib_pool_fini(rdev);
 	radeon_irq_kms_fini(rdev);
-	evergreen_pcie_gart_fini(rdev);
 	uvd_v1_0_fini(rdev);
 	radeon_uvd_fini(rdev);
+	evergreen_pcie_gart_fini(rdev);
 	r600_vram_scratch_fini(rdev);
 	radeon_gem_fini(rdev);
 	radeon_fence_driver_fini(rdev);
diff --git a/drivers/gpu/drm/radeon/evergreen_hdmi.c b/drivers/gpu/drm/radeon/evergreen_hdmi.c
index 0c6d5ce..05b0c95 100644
--- a/drivers/gpu/drm/radeon/evergreen_hdmi.c
+++ b/drivers/gpu/drm/radeon/evergreen_hdmi.c
@@ -306,6 +306,15 @@
 		return;
 	offset = dig->afmt->offset;
 
+	/* disable audio prior to setting up hw */
+	if (ASIC_IS_DCE6(rdev)) {
+		dig->afmt->pin = dce6_audio_get_pin(rdev);
+		dce6_audio_enable(rdev, dig->afmt->pin, false);
+	} else {
+		dig->afmt->pin = r600_audio_get_pin(rdev);
+		r600_audio_enable(rdev, dig->afmt->pin, false);
+	}
+
 	evergreen_audio_set_dto(encoder, mode->clock);
 
 	WREG32(HDMI_VBI_PACKET_CONTROL + offset,
@@ -409,12 +418,16 @@
 	WREG32(AFMT_RAMP_CONTROL1 + offset, 0x007FFFFF);
 	WREG32(AFMT_RAMP_CONTROL2 + offset, 0x00000001);
 	WREG32(AFMT_RAMP_CONTROL3 + offset, 0x00000001);
+
+	/* enable audio after to setting up hw */
+	if (ASIC_IS_DCE6(rdev))
+		dce6_audio_enable(rdev, dig->afmt->pin, true);
+	else
+		r600_audio_enable(rdev, dig->afmt->pin, true);
 }
 
 void evergreen_hdmi_enable(struct drm_encoder *encoder, bool enable)
 {
-	struct drm_device *dev = encoder->dev;
-	struct radeon_device *rdev = dev->dev_private;
 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
 	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
 
@@ -427,15 +440,6 @@
 	if (!enable && !dig->afmt->enabled)
 		return;
 
-	if (enable) {
-		if (ASIC_IS_DCE6(rdev))
-			dig->afmt->pin = dce6_audio_get_pin(rdev);
-		else
-			dig->afmt->pin = r600_audio_get_pin(rdev);
-	} else {
-		dig->afmt->pin = NULL;
-	}
-
 	dig->afmt->enabled = enable;
 
 	DRM_DEBUG("%sabling HDMI interface @ 0x%04X for encoder 0x%x\n",
diff --git a/drivers/gpu/drm/radeon/ni_dpm.c b/drivers/gpu/drm/radeon/ni_dpm.c
index 1217fbc..ca81427 100644
--- a/drivers/gpu/drm/radeon/ni_dpm.c
+++ b/drivers/gpu/drm/radeon/ni_dpm.c
@@ -2588,7 +2588,7 @@
 	if (NISLANDS_DPM2_SQ_RAMP_STI_SIZE > (STI_SIZE_MASK >> STI_SIZE_SHIFT))
 		enable_sq_ramping = false;
 
-	if (NISLANDS_DPM2_SQ_RAMP_LTI_RATIO <= (LTI_RATIO_MASK >> LTI_RATIO_SHIFT))
+	if (NISLANDS_DPM2_SQ_RAMP_LTI_RATIO > (LTI_RATIO_MASK >> LTI_RATIO_SHIFT))
 		enable_sq_ramping = false;
 
 	for (i = 0; i < state->performance_level_count; i++) {
diff --git a/drivers/gpu/drm/radeon/r600_audio.c b/drivers/gpu/drm/radeon/r600_audio.c
index 47fc2b8..bffac10 100644
--- a/drivers/gpu/drm/radeon/r600_audio.c
+++ b/drivers/gpu/drm/radeon/r600_audio.c
@@ -142,12 +142,15 @@
 }
 
 /* enable the audio stream */
-static void r600_audio_enable(struct radeon_device *rdev,
-			      struct r600_audio_pin *pin,
-			      bool enable)
+void r600_audio_enable(struct radeon_device *rdev,
+		       struct r600_audio_pin *pin,
+		       bool enable)
 {
 	u32 value = 0;
 
+	if (!pin)
+		return;
+
 	if (ASIC_IS_DCE4(rdev)) {
 		if (enable) {
 			value |= 0x81000000; /* Required to enable audio */
@@ -158,7 +161,6 @@
 		WREG32_P(R600_AUDIO_ENABLE,
 			 enable ? 0x81000000 : 0x0, ~0x81000000);
 	}
-	DRM_INFO("%s audio %d support\n", enable ? "Enabling" : "Disabling", pin->id);
 }
 
 /*
@@ -178,8 +180,8 @@
 	rdev->audio.pin[0].status_bits = 0;
 	rdev->audio.pin[0].category_code = 0;
 	rdev->audio.pin[0].id = 0;
-
-	r600_audio_enable(rdev, &rdev->audio.pin[0], true);
+	/* disable audio.  it will be set up later */
+	r600_audio_enable(rdev, &rdev->audio.pin[0], false);
 
 	return 0;
 }
diff --git a/drivers/gpu/drm/radeon/r600_hdmi.c b/drivers/gpu/drm/radeon/r600_hdmi.c
index 3016fc1..85a2bb2 100644
--- a/drivers/gpu/drm/radeon/r600_hdmi.c
+++ b/drivers/gpu/drm/radeon/r600_hdmi.c
@@ -329,9 +329,6 @@
 	u8 *sadb;
 	int sad_count;
 
-	/* XXX: setting this register causes hangs on some asics */
-	return;
-
 	list_for_each_entry(connector, &encoder->dev->mode_config.connector_list, head) {
 		if (connector->encoder == encoder) {
 			radeon_connector = to_radeon_connector(connector);
@@ -460,6 +457,10 @@
 		return;
 	offset = dig->afmt->offset;
 
+	/* disable audio prior to setting up hw */
+	dig->afmt->pin = r600_audio_get_pin(rdev);
+	r600_audio_enable(rdev, dig->afmt->pin, false);
+
 	r600_audio_set_dto(encoder, mode->clock);
 
 	WREG32(HDMI0_VBI_PACKET_CONTROL + offset,
@@ -531,6 +532,9 @@
 	WREG32(HDMI0_RAMP_CONTROL3 + offset, 0x00000001);
 
 	r600_hdmi_audio_workaround(encoder);
+
+	/* enable audio after to setting up hw */
+	r600_audio_enable(rdev, dig->afmt->pin, true);
 }
 
 /*
@@ -651,11 +655,6 @@
 	if (!enable && !dig->afmt->enabled)
 		return;
 
-	if (enable)
-		dig->afmt->pin = r600_audio_get_pin(rdev);
-	else
-		dig->afmt->pin = NULL;
-
 	/* Older chipsets require setting HDMI and routing manually */
 	if (!ASIC_IS_DCE3(rdev)) {
 		if (enable)
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index 4a8ac1c..e887d02 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -135,6 +135,9 @@
 /* R600+ */
 #define R600_RING_TYPE_UVD_INDEX	5
 
+/* number of hw syncs before falling back on blocking */
+#define RADEON_NUM_SYNCS			4
+
 /* hardcode those limit for now */
 #define RADEON_VA_IB_OFFSET			(1 << 20)
 #define RADEON_VA_RESERVED_SIZE			(8 << 20)
@@ -554,7 +557,6 @@
 /*
  * Semaphores.
  */
-/* everything here is constant */
 struct radeon_semaphore {
 	struct radeon_sa_bo		*sa_bo;
 	signed				waiters;
@@ -2745,6 +2747,12 @@
 void r600_audio_update_hdmi(struct work_struct *work);
 struct r600_audio_pin *r600_audio_get_pin(struct radeon_device *rdev);
 struct r600_audio_pin *dce6_audio_get_pin(struct radeon_device *rdev);
+void r600_audio_enable(struct radeon_device *rdev,
+		       struct r600_audio_pin *pin,
+		       bool enable);
+void dce6_audio_enable(struct radeon_device *rdev,
+		       struct r600_audio_pin *pin,
+		       bool enable);
 
 /*
  * R600 vram scratch functions
diff --git a/drivers/gpu/drm/radeon/radeon_atpx_handler.c b/drivers/gpu/drm/radeon/radeon_atpx_handler.c
index 485848f..fa9a9c0 100644
--- a/drivers/gpu/drm/radeon/radeon_atpx_handler.c
+++ b/drivers/gpu/drm/radeon/radeon_atpx_handler.c
@@ -219,7 +219,8 @@
 	memcpy(&output, info->buffer.pointer, size);
 
 	/* TODO: check version? */
-	printk("ATPX version %u\n", output.version);
+	printk("ATPX version %u, functions 0x%08x\n",
+	       output.version, output.function_bits);
 
 	radeon_atpx_parse_functions(&atpx->functions, output.function_bits);
 
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c
index d680608..fbd8b93 100644
--- a/drivers/gpu/drm/radeon/radeon_display.c
+++ b/drivers/gpu/drm/radeon/radeon_display.c
@@ -571,6 +571,8 @@
 		radeon_crtc->max_cursor_width = CURSOR_WIDTH;
 		radeon_crtc->max_cursor_height = CURSOR_HEIGHT;
 	}
+	dev->mode_config.cursor_width = radeon_crtc->max_cursor_width;
+	dev->mode_config.cursor_height = radeon_crtc->max_cursor_height;
 
 #if 0
 	radeon_crtc->mode_set.crtc = &radeon_crtc->base;
diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c
index 114d167..2aecd6d 100644
--- a/drivers/gpu/drm/radeon/radeon_kms.c
+++ b/drivers/gpu/drm/radeon/radeon_kms.c
@@ -537,6 +537,10 @@
 
 		radeon_vm_init(rdev, &fpriv->vm);
 
+		r = radeon_bo_reserve(rdev->ring_tmp_bo.bo, false);
+		if (r)
+			return r;
+
 		/* map the ib pool buffer read only into
 		 * virtual address space */
 		bo_va = radeon_vm_bo_add(rdev, &fpriv->vm,
@@ -544,6 +548,8 @@
 		r = radeon_vm_bo_set_addr(rdev, bo_va, RADEON_VA_IB_OFFSET,
 					  RADEON_VM_PAGE_READABLE |
 					  RADEON_VM_PAGE_SNOOPED);
+
+		radeon_bo_unreserve(rdev->ring_tmp_bo.bo);
 		if (r) {
 			radeon_vm_fini(rdev, &fpriv->vm);
 			kfree(fpriv);
diff --git a/drivers/gpu/drm/radeon/radeon_ring.c b/drivers/gpu/drm/radeon/radeon_ring.c
index 1b783f0..15e44a7 100644
--- a/drivers/gpu/drm/radeon/radeon_ring.c
+++ b/drivers/gpu/drm/radeon/radeon_ring.c
@@ -139,7 +139,7 @@
 	}
 
 	/* 64 dwords should be enough for fence too */
-	r = radeon_ring_lock(rdev, ring, 64 + RADEON_NUM_RINGS * 8);
+	r = radeon_ring_lock(rdev, ring, 64 + RADEON_NUM_SYNCS * 8);
 	if (r) {
 		dev_err(rdev->dev, "scheduling IB failed (%d).\n", r);
 		return r;
diff --git a/drivers/gpu/drm/radeon/radeon_semaphore.c b/drivers/gpu/drm/radeon/radeon_semaphore.c
index 2b42aa1..9006b32 100644
--- a/drivers/gpu/drm/radeon/radeon_semaphore.c
+++ b/drivers/gpu/drm/radeon/radeon_semaphore.c
@@ -34,14 +34,15 @@
 int radeon_semaphore_create(struct radeon_device *rdev,
 			    struct radeon_semaphore **semaphore)
 {
+	uint32_t *cpu_addr;
 	int i, r;
 
 	*semaphore = kmalloc(sizeof(struct radeon_semaphore), GFP_KERNEL);
 	if (*semaphore == NULL) {
 		return -ENOMEM;
 	}
-	r = radeon_sa_bo_new(rdev, &rdev->ring_tmp_bo,
-			     &(*semaphore)->sa_bo, 8, 8, true);
+	r = radeon_sa_bo_new(rdev, &rdev->ring_tmp_bo, &(*semaphore)->sa_bo,
+			     8 * RADEON_NUM_SYNCS, 8, true);
 	if (r) {
 		kfree(*semaphore);
 		*semaphore = NULL;
@@ -49,7 +50,10 @@
 	}
 	(*semaphore)->waiters = 0;
 	(*semaphore)->gpu_addr = radeon_sa_bo_gpu_addr((*semaphore)->sa_bo);
-	*((uint64_t*)radeon_sa_bo_cpu_addr((*semaphore)->sa_bo)) = 0;
+
+	cpu_addr = radeon_sa_bo_cpu_addr((*semaphore)->sa_bo);
+	for (i = 0; i < RADEON_NUM_SYNCS; ++i)
+		cpu_addr[i] = 0;
 
 	for (i = 0; i < RADEON_NUM_RINGS; ++i)
 		(*semaphore)->sync_to[i] = NULL;
@@ -125,6 +129,7 @@
 				struct radeon_semaphore *semaphore,
 				int ring)
 {
+	unsigned count = 0;
 	int i, r;
 
         for (i = 0; i < RADEON_NUM_RINGS; ++i) {
@@ -140,6 +145,12 @@
 			return -EINVAL;
 		}
 
+		if (++count > RADEON_NUM_SYNCS) {
+			/* not enough room, wait manually */
+			radeon_fence_wait_locked(fence);
+			continue;
+		}
+
 		/* allocate enough space for sync command */
 		r = radeon_ring_alloc(rdev, &rdev->ring[i], 16);
 		if (r) {
@@ -164,6 +175,8 @@
 
 		radeon_ring_commit(rdev, &rdev->ring[i]);
 		radeon_fence_note_sync(fence, ring);
+
+		semaphore->gpu_addr += 8;
 	}
 
 	return 0;
diff --git a/drivers/gpu/drm/radeon/radeon_uvd.c b/drivers/gpu/drm/radeon/radeon_uvd.c
index 6781fee..3e6804b 100644
--- a/drivers/gpu/drm/radeon/radeon_uvd.c
+++ b/drivers/gpu/drm/radeon/radeon_uvd.c
@@ -171,6 +171,8 @@
 
 	radeon_bo_unref(&rdev->uvd.vcpu_bo);
 
+	radeon_ring_fini(rdev, &rdev->ring[R600_RING_TYPE_UVD_INDEX]);
+
 	release_firmware(rdev->uvd_fw);
 }
 
diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c
index 6c772e5..4e37a42 100644
--- a/drivers/gpu/drm/radeon/rv770.c
+++ b/drivers/gpu/drm/radeon/rv770.c
@@ -1955,9 +1955,9 @@
 	radeon_wb_fini(rdev);
 	radeon_ib_pool_fini(rdev);
 	radeon_irq_kms_fini(rdev);
-	rv770_pcie_gart_fini(rdev);
 	uvd_v1_0_fini(rdev);
 	radeon_uvd_fini(rdev);
+	rv770_pcie_gart_fini(rdev);
 	r600_vram_scratch_fini(rdev);
 	radeon_gem_fini(rdev);
 	radeon_fence_driver_fini(rdev);
diff --git a/drivers/gpu/drm/radeon/rv770_dpm.c b/drivers/gpu/drm/radeon/rv770_dpm.c
index 5b2ea8a..b5f63f5 100644
--- a/drivers/gpu/drm/radeon/rv770_dpm.c
+++ b/drivers/gpu/drm/radeon/rv770_dpm.c
@@ -2526,14 +2526,7 @@
 bool rv770_dpm_vblank_too_short(struct radeon_device *rdev)
 {
 	u32 vblank_time = r600_dpm_get_vblank_time(rdev);
-	u32 switch_limit = 300;
-
-	/* quirks */
-	/* ASUS K70AF */
-	if ((rdev->pdev->device == 0x9553) &&
-	    (rdev->pdev->subsystem_vendor == 0x1043) &&
-	    (rdev->pdev->subsystem_device == 0x1c42))
-		switch_limit = 200;
+	u32 switch_limit = 200; /* 300 */
 
 	/* RV770 */
 	/* mclk switching doesn't seem to work reliably on desktop RV770s */
diff --git a/drivers/gpu/drm/radeon/si_dpm.c b/drivers/gpu/drm/radeon/si_dpm.c
index eafb0e6..0a2f5b4 100644
--- a/drivers/gpu/drm/radeon/si_dpm.c
+++ b/drivers/gpu/drm/radeon/si_dpm.c
@@ -2395,7 +2395,7 @@
 	if (SISLANDS_DPM2_SQ_RAMP_STI_SIZE > (STI_SIZE_MASK >> STI_SIZE_SHIFT))
 		enable_sq_ramping = false;
 
-	if (SISLANDS_DPM2_SQ_RAMP_LTI_RATIO <= (LTI_RATIO_MASK >> LTI_RATIO_SHIFT))
+	if (SISLANDS_DPM2_SQ_RAMP_LTI_RATIO > (LTI_RATIO_MASK >> LTI_RATIO_SHIFT))
 		enable_sq_ramping = false;
 
 	for (i = 0; i < state->performance_level_count; i++) {
diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c
index 88a5290..c715947 100644
--- a/drivers/gpu/drm/tegra/drm.c
+++ b/drivers/gpu/drm/tegra/drm.c
@@ -104,7 +104,7 @@
 
 static void tegra_drm_lastclose(struct drm_device *drm)
 {
-#ifdef CONFIG_TEGRA_DRM_FBDEV
+#ifdef CONFIG_DRM_TEGRA_FBDEV
 	struct tegra_drm *tegra = drm->dev_private;
 
 	tegra_fbdev_restore_mode(tegra->fbdev);
diff --git a/drivers/gpu/drm/tegra/rgb.c b/drivers/gpu/drm/tegra/rgb.c
index 338f7f6..0266fb4 100644
--- a/drivers/gpu/drm/tegra/rgb.c
+++ b/drivers/gpu/drm/tegra/rgb.c
@@ -15,6 +15,7 @@
 struct tegra_rgb {
 	struct tegra_output output;
 	struct tegra_dc *dc;
+	bool enabled;
 
 	struct clk *clk_parent;
 	struct clk *clk;
@@ -89,6 +90,9 @@
 	struct tegra_rgb *rgb = to_rgb(output);
 	unsigned long value;
 
+	if (rgb->enabled)
+		return 0;
+
 	tegra_dc_write_regs(rgb->dc, rgb_enable, ARRAY_SIZE(rgb_enable));
 
 	value = DE_SELECT_ACTIVE | DE_CONTROL_NORMAL;
@@ -122,6 +126,8 @@
 	tegra_dc_writel(rgb->dc, GENERAL_ACT_REQ << 8, DC_CMD_STATE_CONTROL);
 	tegra_dc_writel(rgb->dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL);
 
+	rgb->enabled = true;
+
 	return 0;
 }
 
@@ -130,6 +136,9 @@
 	struct tegra_rgb *rgb = to_rgb(output);
 	unsigned long value;
 
+	if (!rgb->enabled)
+		return 0;
+
 	value = tegra_dc_readl(rgb->dc, DC_CMD_DISPLAY_POWER_CONTROL);
 	value &= ~(PW0_ENABLE | PW1_ENABLE | PW2_ENABLE | PW3_ENABLE |
 		   PW4_ENABLE | PM0_ENABLE | PM1_ENABLE);
@@ -144,6 +153,8 @@
 
 	tegra_dc_write_regs(rgb->dc, rgb_disable, ARRAY_SIZE(rgb_disable));
 
+	rgb->enabled = false;
+
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/ttm/ttm_agp_backend.c b/drivers/gpu/drm/ttm/ttm_agp_backend.c
index 3302f99e..764be36 100644
--- a/drivers/gpu/drm/ttm/ttm_agp_backend.c
+++ b/drivers/gpu/drm/ttm/ttm_agp_backend.c
@@ -126,6 +126,7 @@
 	agp_be->ttm.func = &ttm_agp_func;
 
 	if (ttm_tt_init(&agp_be->ttm, bdev, size, page_flags, dummy_read_page)) {
+		kfree(agp_be);
 		return NULL;
 	}
 
diff --git a/drivers/gpu/drm/vmwgfx/svga3d_reg.h b/drivers/gpu/drm/vmwgfx/svga3d_reg.h
index b645647..f58dc7d 100644
--- a/drivers/gpu/drm/vmwgfx/svga3d_reg.h
+++ b/drivers/gpu/drm/vmwgfx/svga3d_reg.h
@@ -261,12 +261,7 @@
    /* Planar video formats. */
    SVGA3D_YV12                         = 121,
 
-   /* Shader constant formats. */
-   SVGA3D_SURFACE_SHADERCONST_FLOAT    = 122,
-   SVGA3D_SURFACE_SHADERCONST_INT      = 123,
-   SVGA3D_SURFACE_SHADERCONST_BOOL     = 124,
-
-   SVGA3D_FORMAT_MAX                   = 125,
+   SVGA3D_FORMAT_MAX                   = 122,
 } SVGA3dSurfaceFormat;
 
 typedef uint32 SVGA3dColor; /* a, r, g, b */
@@ -1223,9 +1218,19 @@
 #define SVGA_3D_CMD_INVALIDATE_GB_IMAGE_PARTIAL 1129
 
 #define SVGA_3D_CMD_SET_GB_SHADERCONSTS_INLINE  1130
-
+#define SVGA_3D_CMD_GB_SCREEN_DMA               1131
+#define SVGA_3D_CMD_BIND_GB_SURFACE_WITH_PITCH  1132
+#define SVGA_3D_CMD_GB_MOB_FENCE                1133
+#define SVGA_3D_CMD_DEFINE_GB_SURFACE_V2        1134
 #define SVGA_3D_CMD_DEFINE_GB_MOB64          1135
 #define SVGA_3D_CMD_REDEFINE_GB_MOB64        1136
+#define SVGA_3D_CMD_NOP_ERROR                1137
+
+#define SVGA_3D_CMD_RESERVED1                1138
+#define SVGA_3D_CMD_RESERVED2                1139
+#define SVGA_3D_CMD_RESERVED3                1140
+#define SVGA_3D_CMD_RESERVED4                1141
+#define SVGA_3D_CMD_RESERVED5                1142
 
 #define SVGA_3D_CMD_MAX                      1142
 #define SVGA_3D_CMD_FUTURE_MAX               3000
@@ -1973,8 +1978,7 @@
    uint32 sizeInBytes;
    uint32 validSizeInBytes;
    SVGAMobFormat ptDepth;
-}
-__attribute__((__packed__))
+} __packed
 SVGA3dCmdSetOTableBase;  /* SVGA_3D_CMD_SET_OTABLE_BASE */
 
 typedef
@@ -1984,15 +1988,13 @@
    uint32 sizeInBytes;
    uint32 validSizeInBytes;
    SVGAMobFormat ptDepth;
-}
-__attribute__((__packed__))
+} __packed
 SVGA3dCmdSetOTableBase64;  /* SVGA_3D_CMD_SET_OTABLE_BASE64 */
 
 typedef
 struct {
    SVGAOTableType type;
-}
-__attribute__((__packed__))
+} __packed
 SVGA3dCmdReadbackOTable;  /* SVGA_3D_CMD_READBACK_OTABLE */
 
 /*
@@ -2005,8 +2007,7 @@
    SVGAMobFormat ptDepth;
    PPN base;
    uint32 sizeInBytes;
-}
-__attribute__((__packed__))
+} __packed
 SVGA3dCmdDefineGBMob;   /* SVGA_3D_CMD_DEFINE_GB_MOB */
 
 
@@ -2017,8 +2018,7 @@
 typedef
 struct SVGA3dCmdDestroyGBMob {
    SVGAMobId mobid;
-}
-__attribute__((__packed__))
+} __packed
 SVGA3dCmdDestroyGBMob;   /* SVGA_3D_CMD_DESTROY_GB_MOB */
 
 /*
@@ -2031,8 +2031,7 @@
    SVGAMobFormat ptDepth;
    PPN base;
    uint32 sizeInBytes;
-}
-__attribute__((__packed__))
+} __packed
 SVGA3dCmdRedefineGBMob;   /* SVGA_3D_CMD_REDEFINE_GB_MOB */
 
 /*
@@ -2045,8 +2044,7 @@
    SVGAMobFormat ptDepth;
    PPN64 base;
    uint32 sizeInBytes;
-}
-__attribute__((__packed__))
+} __packed
 SVGA3dCmdDefineGBMob64;   /* SVGA_3D_CMD_DEFINE_GB_MOB64 */
 
 /*
@@ -2059,8 +2057,7 @@
    SVGAMobFormat ptDepth;
    PPN64 base;
    uint32 sizeInBytes;
-}
-__attribute__((__packed__))
+} __packed
 SVGA3dCmdRedefineGBMob64;   /* SVGA_3D_CMD_REDEFINE_GB_MOB64 */
 
 /*
@@ -2070,8 +2067,7 @@
 typedef
 struct SVGA3dCmdUpdateGBMobMapping {
    SVGAMobId mobid;
-}
-__attribute__((__packed__))
+} __packed
 SVGA3dCmdUpdateGBMobMapping;   /* SVGA_3D_CMD_UPDATE_GB_MOB_MAPPING */
 
 /*
@@ -2087,7 +2083,8 @@
    uint32 multisampleCount;
    SVGA3dTextureFilter autogenFilter;
    SVGA3dSize size;
-} SVGA3dCmdDefineGBSurface;   /* SVGA_3D_CMD_DEFINE_GB_SURFACE */
+} __packed
+SVGA3dCmdDefineGBSurface;   /* SVGA_3D_CMD_DEFINE_GB_SURFACE */
 
 /*
  * Destroy a guest-backed surface.
@@ -2096,7 +2093,8 @@
 typedef
 struct SVGA3dCmdDestroyGBSurface {
    uint32 sid;
-} SVGA3dCmdDestroyGBSurface;   /* SVGA_3D_CMD_DESTROY_GB_SURFACE */
+} __packed
+SVGA3dCmdDestroyGBSurface;   /* SVGA_3D_CMD_DESTROY_GB_SURFACE */
 
 /*
  * Bind a guest-backed surface to an object.
@@ -2106,7 +2104,8 @@
 struct SVGA3dCmdBindGBSurface {
    uint32 sid;
    SVGAMobId mobid;
-} SVGA3dCmdBindGBSurface;   /* SVGA_3D_CMD_BIND_GB_SURFACE */
+} __packed
+SVGA3dCmdBindGBSurface;   /* SVGA_3D_CMD_BIND_GB_SURFACE */
 
 /*
  * Conditionally bind a mob to a guest backed surface if testMobid
@@ -2123,7 +2122,7 @@
    SVGAMobId testMobid;
    SVGAMobId mobid;
    uint32 flags;
-}
+} __packed
 SVGA3dCmdCondBindGBSurface;          /* SVGA_3D_CMD_COND_BIND_GB_SURFACE */
 
 /*
@@ -2135,7 +2134,8 @@
 struct SVGA3dCmdUpdateGBImage {
    SVGA3dSurfaceImageId image;
    SVGA3dBox box;
-} SVGA3dCmdUpdateGBImage;   /* SVGA_3D_CMD_UPDATE_GB_IMAGE */
+} __packed
+SVGA3dCmdUpdateGBImage;   /* SVGA_3D_CMD_UPDATE_GB_IMAGE */
 
 /*
  * Update an entire guest-backed surface.
@@ -2145,7 +2145,8 @@
 typedef
 struct SVGA3dCmdUpdateGBSurface {
    uint32 sid;
-} SVGA3dCmdUpdateGBSurface;   /* SVGA_3D_CMD_UPDATE_GB_SURFACE */
+} __packed
+SVGA3dCmdUpdateGBSurface;   /* SVGA_3D_CMD_UPDATE_GB_SURFACE */
 
 /*
  * Readback an image in a guest-backed surface.
@@ -2155,7 +2156,8 @@
 typedef
 struct SVGA3dCmdReadbackGBImage {
    SVGA3dSurfaceImageId image;
-} SVGA3dCmdReadbackGBImage;   /* SVGA_3D_CMD_READBACK_GB_IMAGE*/
+} __packed
+SVGA3dCmdReadbackGBImage;   /* SVGA_3D_CMD_READBACK_GB_IMAGE*/
 
 /*
  * Readback an entire guest-backed surface.
@@ -2165,7 +2167,8 @@
 typedef
 struct SVGA3dCmdReadbackGBSurface {
    uint32 sid;
-} SVGA3dCmdReadbackGBSurface;   /* SVGA_3D_CMD_READBACK_GB_SURFACE */
+} __packed
+SVGA3dCmdReadbackGBSurface;   /* SVGA_3D_CMD_READBACK_GB_SURFACE */
 
 /*
  * Readback a sub rect of an image in a guest-backed surface.  After
@@ -2179,7 +2182,7 @@
    SVGA3dSurfaceImageId image;
    SVGA3dBox box;
    uint32 invertBox;
-}
+} __packed
 SVGA3dCmdReadbackGBImagePartial; /* SVGA_3D_CMD_READBACK_GB_IMAGE_PARTIAL */
 
 /*
@@ -2190,7 +2193,8 @@
 typedef
 struct SVGA3dCmdInvalidateGBImage {
    SVGA3dSurfaceImageId image;
-} SVGA3dCmdInvalidateGBImage;   /* SVGA_3D_CMD_INVALIDATE_GB_IMAGE */
+} __packed
+SVGA3dCmdInvalidateGBImage;   /* SVGA_3D_CMD_INVALIDATE_GB_IMAGE */
 
 /*
  * Invalidate an entire guest-backed surface.
@@ -2200,7 +2204,8 @@
 typedef
 struct SVGA3dCmdInvalidateGBSurface {
    uint32 sid;
-} SVGA3dCmdInvalidateGBSurface; /* SVGA_3D_CMD_INVALIDATE_GB_SURFACE */
+} __packed
+SVGA3dCmdInvalidateGBSurface; /* SVGA_3D_CMD_INVALIDATE_GB_SURFACE */
 
 /*
  * Invalidate a sub rect of an image in a guest-backed surface.  After
@@ -2214,7 +2219,7 @@
    SVGA3dSurfaceImageId image;
    SVGA3dBox box;
    uint32 invertBox;
-}
+} __packed
 SVGA3dCmdInvalidateGBImagePartial; /* SVGA_3D_CMD_INVALIDATE_GB_IMAGE_PARTIAL */
 
 /*
@@ -2224,7 +2229,8 @@
 typedef
 struct SVGA3dCmdDefineGBContext {
    uint32 cid;
-} SVGA3dCmdDefineGBContext;   /* SVGA_3D_CMD_DEFINE_GB_CONTEXT */
+} __packed
+SVGA3dCmdDefineGBContext;   /* SVGA_3D_CMD_DEFINE_GB_CONTEXT */
 
 /*
  * Destroy a guest-backed context.
@@ -2233,7 +2239,8 @@
 typedef
 struct SVGA3dCmdDestroyGBContext {
    uint32 cid;
-} SVGA3dCmdDestroyGBContext;   /* SVGA_3D_CMD_DESTROY_GB_CONTEXT */
+} __packed
+SVGA3dCmdDestroyGBContext;   /* SVGA_3D_CMD_DESTROY_GB_CONTEXT */
 
 /*
  * Bind a guest-backed context.
@@ -2252,7 +2259,8 @@
    uint32 cid;
    SVGAMobId mobid;
    uint32 validContents;
-} SVGA3dCmdBindGBContext;   /* SVGA_3D_CMD_BIND_GB_CONTEXT */
+} __packed
+SVGA3dCmdBindGBContext;   /* SVGA_3D_CMD_BIND_GB_CONTEXT */
 
 /*
  * Readback a guest-backed context.
@@ -2262,7 +2270,8 @@
 typedef
 struct SVGA3dCmdReadbackGBContext {
    uint32 cid;
-} SVGA3dCmdReadbackGBContext;   /* SVGA_3D_CMD_READBACK_GB_CONTEXT */
+} __packed
+SVGA3dCmdReadbackGBContext;   /* SVGA_3D_CMD_READBACK_GB_CONTEXT */
 
 /*
  * Invalidate a guest-backed context.
@@ -2270,7 +2279,8 @@
 typedef
 struct SVGA3dCmdInvalidateGBContext {
    uint32 cid;
-} SVGA3dCmdInvalidateGBContext;   /* SVGA_3D_CMD_INVALIDATE_GB_CONTEXT */
+} __packed
+SVGA3dCmdInvalidateGBContext;   /* SVGA_3D_CMD_INVALIDATE_GB_CONTEXT */
 
 /*
  * Define a guest-backed shader.
@@ -2281,7 +2291,8 @@
    uint32 shid;
    SVGA3dShaderType type;
    uint32 sizeInBytes;
-} SVGA3dCmdDefineGBShader;   /* SVGA_3D_CMD_DEFINE_GB_SHADER */
+} __packed
+SVGA3dCmdDefineGBShader;   /* SVGA_3D_CMD_DEFINE_GB_SHADER */
 
 /*
  * Bind a guest-backed shader.
@@ -2291,7 +2302,8 @@
    uint32 shid;
    SVGAMobId mobid;
    uint32 offsetInBytes;
-} SVGA3dCmdBindGBShader;   /* SVGA_3D_CMD_BIND_GB_SHADER */
+} __packed
+SVGA3dCmdBindGBShader;   /* SVGA_3D_CMD_BIND_GB_SHADER */
 
 /*
  * Destroy a guest-backed shader.
@@ -2299,7 +2311,8 @@
 
 typedef struct SVGA3dCmdDestroyGBShader {
    uint32 shid;
-} SVGA3dCmdDestroyGBShader;   /* SVGA_3D_CMD_DESTROY_GB_SHADER */
+} __packed
+SVGA3dCmdDestroyGBShader;   /* SVGA_3D_CMD_DESTROY_GB_SHADER */
 
 typedef
 struct {
@@ -2314,14 +2327,16 @@
     * Note that FLOAT and INT constants are 4-dwords in length, while
     * BOOL constants are 1-dword in length.
     */
-} SVGA3dCmdSetGBShaderConstInline;
+} __packed
+SVGA3dCmdSetGBShaderConstInline;
 /* SVGA_3D_CMD_SET_GB_SHADERCONSTS_INLINE */
 
 typedef
 struct {
    uint32               cid;
    SVGA3dQueryType      type;
-} SVGA3dCmdBeginGBQuery;           /* SVGA_3D_CMD_BEGIN_GB_QUERY */
+} __packed
+SVGA3dCmdBeginGBQuery;           /* SVGA_3D_CMD_BEGIN_GB_QUERY */
 
 typedef
 struct {
@@ -2329,7 +2344,8 @@
    SVGA3dQueryType      type;
    SVGAMobId mobid;
    uint32 offset;
-} SVGA3dCmdEndGBQuery;                  /* SVGA_3D_CMD_END_GB_QUERY */
+} __packed
+SVGA3dCmdEndGBQuery;                  /* SVGA_3D_CMD_END_GB_QUERY */
 
 
 /*
@@ -2346,21 +2362,22 @@
    SVGA3dQueryType      type;
    SVGAMobId mobid;
    uint32 offset;
-} SVGA3dCmdWaitForGBQuery;          /* SVGA_3D_CMD_WAIT_FOR_GB_QUERY */
+} __packed
+SVGA3dCmdWaitForGBQuery;          /* SVGA_3D_CMD_WAIT_FOR_GB_QUERY */
 
 typedef
 struct {
    SVGAMobId mobid;
    uint32 fbOffset;
    uint32 initalized;
-}
+} __packed
 SVGA3dCmdEnableGart;              /* SVGA_3D_CMD_ENABLE_GART */
 
 typedef
 struct {
    SVGAMobId mobid;
    uint32 gartOffset;
-}
+} __packed
 SVGA3dCmdMapMobIntoGart;          /* SVGA_3D_CMD_MAP_MOB_INTO_GART */
 
 
@@ -2368,7 +2385,7 @@
 struct {
    uint32 gartOffset;
    uint32 numPages;
-}
+} __packed
 SVGA3dCmdUnmapGartRange;          /* SVGA_3D_CMD_UNMAP_GART_RANGE */
 
 
@@ -2385,27 +2402,27 @@
    int32 xRoot;
    int32 yRoot;
    uint32 flags;
-}
+} __packed
 SVGA3dCmdDefineGBScreenTarget;    /* SVGA_3D_CMD_DEFINE_GB_SCREENTARGET */
 
 typedef
 struct {
    uint32 stid;
-}
+} __packed
 SVGA3dCmdDestroyGBScreenTarget;  /* SVGA_3D_CMD_DESTROY_GB_SCREENTARGET */
 
 typedef
 struct {
    uint32 stid;
    SVGA3dSurfaceImageId image;
-}
+} __packed
 SVGA3dCmdBindGBScreenTarget;  /* SVGA_3D_CMD_BIND_GB_SCREENTARGET */
 
 typedef
 struct {
    uint32 stid;
    SVGA3dBox box;
-}
+} __packed
 SVGA3dCmdUpdateGBScreenTarget;  /* SVGA_3D_CMD_UPDATE_GB_SCREENTARGET */
 
 /*
diff --git a/drivers/gpu/drm/vmwgfx/svga3d_surfacedefs.h b/drivers/gpu/drm/vmwgfx/svga3d_surfacedefs.h
index 8369c3b..ef33850 100644
--- a/drivers/gpu/drm/vmwgfx/svga3d_surfacedefs.h
+++ b/drivers/gpu/drm/vmwgfx/svga3d_surfacedefs.h
@@ -38,8 +38,11 @@
 
 #define DIV_ROUND_UP(x, y)  (((x) + (y) - 1) / (y))
 #define max_t(type, x, y)  ((x) > (y) ? (x) : (y))
+#define min_t(type, x, y)  ((x) < (y) ? (x) : (y))
 #define surf_size_struct SVGA3dSize
 #define u32 uint32
+#define u64 uint64_t
+#define U32_MAX ((u32)~0U)
 
 #endif /* __KERNEL__ */
 
@@ -704,8 +707,8 @@
 
 static inline u32 clamped_umul32(u32 a, u32 b)
 {
-	uint64_t tmp = (uint64_t) a*b;
-	return (tmp > (uint64_t) ((u32) -1)) ? (u32) -1 : tmp;
+	u64 tmp = (u64) a*b;
+	return (tmp > (u64) U32_MAX) ? U32_MAX : tmp;
 }
 
 static inline const struct svga3d_surface_desc *
@@ -834,7 +837,7 @@
 				  bool cubemap)
 {
 	const struct svga3d_surface_desc *desc = svga3dsurface_get_desc(format);
-	u32 total_size = 0;
+	u64 total_size = 0;
 	u32 mip;
 
 	for (mip = 0; mip < num_mip_levels; mip++) {
@@ -847,7 +850,7 @@
 	if (cubemap)
 		total_size *= SVGA3D_MAX_SURFACE_FACES;
 
-	return total_size;
+	return (u32) min_t(u64, total_size, (u64) U32_MAX);
 }
 
 
diff --git a/drivers/gpu/drm/vmwgfx/svga_reg.h b/drivers/gpu/drm/vmwgfx/svga_reg.h
index 71defa4..11323dd 100644
--- a/drivers/gpu/drm/vmwgfx/svga_reg.h
+++ b/drivers/gpu/drm/vmwgfx/svga_reg.h
@@ -169,10 +169,17 @@
    SVGA_REG_TRACES = 45,            /* Enable trace-based updates even when FIFO is on */
    SVGA_REG_GMRS_MAX_PAGES = 46,    /* Maximum number of 4KB pages for all GMRs */
    SVGA_REG_MEMORY_SIZE = 47,       /* Total dedicated device memory excluding FIFO */
+   SVGA_REG_COMMAND_LOW = 48,       /* Lower 32 bits and submits commands */
+   SVGA_REG_COMMAND_HIGH = 49,      /* Upper 32 bits of command buffer PA */
    SVGA_REG_MAX_PRIMARY_BOUNDING_BOX_MEM = 50,   /* Max primary memory */
    SVGA_REG_SUGGESTED_GBOBJECT_MEM_SIZE_KB = 51, /* Suggested limit on mob mem */
    SVGA_REG_DEV_CAP = 52,           /* Write dev cap index, read value */
-   SVGA_REG_TOP = 53,               /* Must be 1 more than the last register */
+   SVGA_REG_CMD_PREPEND_LOW = 53,
+   SVGA_REG_CMD_PREPEND_HIGH = 54,
+   SVGA_REG_SCREENTARGET_MAX_WIDTH = 55,
+   SVGA_REG_SCREENTARGET_MAX_HEIGHT = 56,
+   SVGA_REG_MOB_MAX_SIZE = 57,
+   SVGA_REG_TOP = 58,               /* Must be 1 more than the last register */
 
    SVGA_PALETTE_BASE = 1024,        /* Base of SVGA color map */
    /* Next 768 (== 256*3) registers exist for colormap */
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_context.c b/drivers/gpu/drm/vmwgfx/vmwgfx_context.c
index 9426c53..1e80152 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_context.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_context.c
@@ -551,8 +551,7 @@
 	cmd->header.size = sizeof(cmd->body);
 	cmd->body.cid = bi->ctx->id;
 	cmd->body.type = bi->i1.shader_type;
-	cmd->body.shid =
-		cpu_to_le32((rebind) ? bi->res->id : SVGA3D_INVALID_ID);
+	cmd->body.shid = ((rebind) ? bi->res->id : SVGA3D_INVALID_ID);
 	vmw_fifo_commit(dev_priv, sizeof(*cmd));
 
 	return 0;
@@ -585,8 +584,7 @@
 	cmd->header.size = sizeof(cmd->body);
 	cmd->body.cid = bi->ctx->id;
 	cmd->body.type = bi->i1.rt_type;
-	cmd->body.target.sid =
-		cpu_to_le32((rebind) ? bi->res->id : SVGA3D_INVALID_ID);
+	cmd->body.target.sid = ((rebind) ? bi->res->id : SVGA3D_INVALID_ID);
 	cmd->body.target.face = 0;
 	cmd->body.target.mipmap = 0;
 	vmw_fifo_commit(dev_priv, sizeof(*cmd));
@@ -628,8 +626,7 @@
 	cmd->body.c.cid = bi->ctx->id;
 	cmd->body.s1.stage = bi->i1.texture_stage;
 	cmd->body.s1.name = SVGA3D_TS_BIND_TEXTURE;
-	cmd->body.s1.value =
-		cpu_to_le32((rebind) ? bi->res->id : SVGA3D_INVALID_ID);
+	cmd->body.s1.value = ((rebind) ? bi->res->id : SVGA3D_INVALID_ID);
 	vmw_fifo_commit(dev_priv, sizeof(*cmd));
 
 	return 0;
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
index 3bdc0ad..0083cbf 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
@@ -667,6 +667,7 @@
 		dev_priv->memory_size = 512*1024*1024;
 	}
 	dev_priv->max_mob_pages = 0;
+	dev_priv->max_mob_size = 0;
 	if (dev_priv->capabilities & SVGA_CAP_GBOBJECTS) {
 		uint64_t mem_size =
 			vmw_read(dev_priv,
@@ -676,6 +677,8 @@
 		dev_priv->prim_bb_mem =
 			vmw_read(dev_priv,
 				 SVGA_REG_MAX_PRIMARY_BOUNDING_BOX_MEM);
+		dev_priv->max_mob_size =
+			vmw_read(dev_priv, SVGA_REG_MOB_MAX_SIZE);
 	} else
 		dev_priv->prim_bb_mem = dev_priv->vram_size;
 
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
index ecaa302..0783155 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
@@ -40,7 +40,7 @@
 #include <drm/ttm/ttm_module.h>
 #include "vmwgfx_fence.h"
 
-#define VMWGFX_DRIVER_DATE "20121114"
+#define VMWGFX_DRIVER_DATE "20140228"
 #define VMWGFX_DRIVER_MAJOR 2
 #define VMWGFX_DRIVER_MINOR 5
 #define VMWGFX_DRIVER_PATCHLEVEL 0
@@ -386,6 +386,7 @@
 	uint32_t max_gmr_ids;
 	uint32_t max_gmr_pages;
 	uint32_t max_mob_pages;
+	uint32_t max_mob_size;
 	uint32_t memory_size;
 	bool has_gmr;
 	bool has_mob;
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
index 269b85c..efb575a 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
@@ -602,7 +602,7 @@
 {
 	struct vmw_cid_cmd {
 		SVGA3dCmdHeader header;
-		__le32 cid;
+		uint32_t cid;
 	} *cmd;
 
 	cmd = container_of(header, struct vmw_cid_cmd, header);
@@ -1835,7 +1835,7 @@
 	return 0;
 }
 
-static const struct vmw_cmd_entry const vmw_cmd_entries[SVGA_3D_CMD_MAX] = {
+static const struct vmw_cmd_entry vmw_cmd_entries[SVGA_3D_CMD_MAX] = {
 	VMW_CMD_DEF(SVGA_3D_CMD_SURFACE_DEFINE, &vmw_cmd_invalid,
 		    false, false, false),
 	VMW_CMD_DEF(SVGA_3D_CMD_SURFACE_DESTROY, &vmw_cmd_invalid,
@@ -2032,6 +2032,9 @@
 		goto out_invalid;
 
 	entry = &vmw_cmd_entries[cmd_id];
+	if (unlikely(!entry->func))
+		goto out_invalid;
+
 	if (unlikely(!entry->user_allow && !sw_context->kernel))
 		goto out_privileged;
 
@@ -2469,7 +2472,7 @@
 	if (dev_priv->has_mob) {
 		ret = vmw_rebind_contexts(sw_context);
 		if (unlikely(ret != 0))
-			goto out_err;
+			goto out_unlock_binding;
 	}
 
 	cmd = vmw_fifo_reserve(dev_priv, command_size);
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c
index f9881f9..47b7094 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c
@@ -102,6 +102,9 @@
 		vmw_fp->gb_aware = true;
 		param->value = dev_priv->max_mob_pages * PAGE_SIZE;
 		break;
+	case DRM_VMW_PARAM_MAX_MOB_SIZE:
+		param->value = dev_priv->max_mob_size;
+		break;
 	default:
 		DRM_ERROR("Illegal vmwgfx get param request: %d\n",
 			  param->param);
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_mob.c b/drivers/gpu/drm/vmwgfx/vmwgfx_mob.c
index d4a5a19..04a64b8 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_mob.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_mob.c
@@ -188,18 +188,20 @@
 
 	bo = otable->page_table->pt_bo;
 	cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
-	if (unlikely(cmd == NULL))
-		DRM_ERROR("Failed reserving FIFO space for OTable setup.\n");
-
-	memset(cmd, 0, sizeof(*cmd));
-	cmd->header.id = SVGA_3D_CMD_SET_OTABLE_BASE;
-	cmd->header.size = sizeof(cmd->body);
-	cmd->body.type = type;
-	cmd->body.baseAddress = 0;
-	cmd->body.sizeInBytes = 0;
-	cmd->body.validSizeInBytes = 0;
-	cmd->body.ptDepth = SVGA3D_MOBFMT_INVALID;
-	vmw_fifo_commit(dev_priv, sizeof(*cmd));
+	if (unlikely(cmd == NULL)) {
+		DRM_ERROR("Failed reserving FIFO space for OTable "
+			  "takedown.\n");
+	} else {
+		memset(cmd, 0, sizeof(*cmd));
+		cmd->header.id = SVGA_3D_CMD_SET_OTABLE_BASE;
+		cmd->header.size = sizeof(cmd->body);
+		cmd->body.type = type;
+		cmd->body.baseAddress = 0;
+		cmd->body.sizeInBytes = 0;
+		cmd->body.validSizeInBytes = 0;
+		cmd->body.ptDepth = SVGA3D_MOBFMT_INVALID;
+		vmw_fifo_commit(dev_priv, sizeof(*cmd));
+	}
 
 	if (bo) {
 		int ret;
@@ -562,11 +564,12 @@
 	if (unlikely(cmd == NULL)) {
 		DRM_ERROR("Failed reserving FIFO space for Memory "
 			  "Object unbinding.\n");
+	} else {
+		cmd->header.id = SVGA_3D_CMD_DESTROY_GB_MOB;
+		cmd->header.size = sizeof(cmd->body);
+		cmd->body.mobid = mob->id;
+		vmw_fifo_commit(dev_priv, sizeof(*cmd));
 	}
-	cmd->header.id = SVGA_3D_CMD_DESTROY_GB_MOB;
-	cmd->header.size = sizeof(cmd->body);
-	cmd->body.mobid = mob->id;
-	vmw_fifo_commit(dev_priv, sizeof(*cmd));
 	if (bo) {
 		vmw_fence_single_bo(bo, NULL);
 		ttm_bo_unreserve(bo);
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
index 2aa4bc6..9757b57 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
@@ -427,8 +427,7 @@
 	INIT_LIST_HEAD(&vmw_bo->res_list);
 
 	ret = ttm_bo_init(bdev, &vmw_bo->base, size,
-			  (user) ? ttm_bo_type_device :
-			  ttm_bo_type_kernel, placement,
+			  ttm_bo_type_device, placement,
 			  0, interruptible,
 			  NULL, acc_size, NULL, bo_free);
 	return ret;
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c b/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c
index 217d941..ee38565 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c
@@ -371,13 +371,13 @@
 					 TTM_REF_USAGE);
 }
 
-int vmw_shader_alloc(struct vmw_private *dev_priv,
-		     struct vmw_dma_buffer *buffer,
-		     size_t shader_size,
-		     size_t offset,
-		     SVGA3dShaderType shader_type,
-		     struct ttm_object_file *tfile,
-		     u32 *handle)
+static int vmw_shader_alloc(struct vmw_private *dev_priv,
+			    struct vmw_dma_buffer *buffer,
+			    size_t shader_size,
+			    size_t offset,
+			    SVGA3dShaderType shader_type,
+			    struct ttm_object_file *tfile,
+			    u32 *handle)
 {
 	struct vmw_user_shader *ushader;
 	struct vmw_resource *res, *tmp;
@@ -779,6 +779,8 @@
 	int ret;
 
 	man = kzalloc(sizeof(*man), GFP_KERNEL);
+	if (man == NULL)
+		return ERR_PTR(-ENOMEM);
 
 	man->dev_priv = dev_priv;
 	INIT_LIST_HEAD(&man->list);
diff --git a/drivers/gpu/host1x/job.c b/drivers/gpu/host1x/job.c
index 1146e3b..112f27e 100644
--- a/drivers/gpu/host1x/job.c
+++ b/drivers/gpu/host1x/job.c
@@ -538,7 +538,7 @@
 
 		g->base = job->gather_addr_phys[i];
 
-		for (j = 0; j < job->num_gathers; j++)
+		for (j = i + 1; j < job->num_gathers; j++)
 			if (job->gathers[j].bo == g->bo)
 				job->gathers[j].handled = true;
 
diff --git a/drivers/hid/hid-apple.c b/drivers/hid/hid-apple.c
index 4975581..f822fd2 100644
--- a/drivers/hid/hid-apple.c
+++ b/drivers/hid/hid-apple.c
@@ -469,6 +469,9 @@
 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE,
 				USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ANSI),
 		.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
+	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE,
+				USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_JIS),
+		.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_JIS),
 		.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_ANSI),
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 3bfac3a..cc32a6f 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1679,6 +1679,7 @@
 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS) },
 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ANSI) },
 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ISO) },
+	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_JIS) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_AUREAL, USB_DEVICE_ID_AUREAL_W01RN) },
@@ -1779,6 +1780,8 @@
 	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_USB) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_DIGITAL_MEDIA_3K) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_2) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TOUCH_COVER_2) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_MONTEREY, USB_DEVICE_ID_GENIUS_KB29E) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_1) },
diff --git a/drivers/hid/hid-hyperv.c b/drivers/hid/hid-hyperv.c
index 8fae6d1..c24908f 100644
--- a/drivers/hid/hid-hyperv.c
+++ b/drivers/hid/hid-hyperv.c
@@ -157,6 +157,7 @@
 	u32			report_desc_size;
 	struct hv_input_dev_info hid_dev_info;
 	struct hid_device       *hid_device;
+	u8			input_buf[HID_MAX_BUFFER_SIZE];
 };
 
 
@@ -256,6 +257,7 @@
 	struct synthhid_msg *hid_msg;
 	struct mousevsc_dev *input_dev = hv_get_drvdata(device);
 	struct synthhid_input_report *input_report;
+	size_t len;
 
 	pipe_msg = (struct pipe_prt_msg *)((unsigned long)packet +
 						(packet->offset8 << 3));
@@ -300,9 +302,12 @@
 			(struct synthhid_input_report *)pipe_msg->data;
 		if (!input_dev->init_complete)
 			break;
-		hid_input_report(input_dev->hid_device,
-				HID_INPUT_REPORT, input_report->buffer,
-				input_report->header.size, 1);
+
+		len = min(input_report->header.size,
+			  (u32)sizeof(input_dev->input_buf));
+		memcpy(input_dev->input_buf, input_report->buffer, len);
+		hid_input_report(input_dev->hid_device, HID_INPUT_REPORT,
+				 input_dev->input_buf, len, 1);
 		break;
 	default:
 		pr_err("unsupported hid msg type - type %d len %d",
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index 5a5248f..22f28d6 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -135,6 +135,7 @@
 #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS   0x023b
 #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ANSI  0x0255
 #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ISO   0x0256
+#define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_JIS   0x0257
 #define USB_DEVICE_ID_APPLE_WELLSPRING8_ANSI	0x0290
 #define USB_DEVICE_ID_APPLE_WELLSPRING8_ISO	0x0291
 #define USB_DEVICE_ID_APPLE_WELLSPRING8_JIS	0x0292
@@ -240,6 +241,7 @@
 
 #define USB_VENDOR_ID_CYGNAL		0x10c4
 #define USB_DEVICE_ID_CYGNAL_RADIO_SI470X	0x818a
+#define USB_DEVICE_ID_FOCALTECH_FTXXXX_MULTITOUCH	0x81b9
 
 #define USB_DEVICE_ID_CYGNAL_RADIO_SI4713       0x8244
 
@@ -451,6 +453,9 @@
 #define USB_VENDOR_ID_INTEL_1		0x8087
 #define USB_DEVICE_ID_INTEL_HID_SENSOR	0x09fa
 
+#define USB_VENDOR_ID_STM_0             0x0483
+#define USB_DEVICE_ID_STM_HID_SENSOR    0x91d1
+
 #define USB_VENDOR_ID_ION		0x15e4
 #define USB_DEVICE_ID_ICADE		0x0132
 
@@ -619,6 +624,8 @@
 #define USB_DEVICE_ID_MS_PRESENTER_8K_USB	0x0713
 #define USB_DEVICE_ID_MS_DIGITAL_MEDIA_3K	0x0730
 #define USB_DEVICE_ID_MS_COMFORT_MOUSE_4500	0x076c
+#define USB_DEVICE_ID_MS_TOUCH_COVER_2	0x07a7
+#define USB_DEVICE_ID_MS_TYPE_COVER_2	0x07a9
 
 #define USB_VENDOR_ID_MOJO		0x8282
 #define USB_DEVICE_ID_RETRO_ADAPTER	0x3201
@@ -644,6 +651,7 @@
 
 #define USB_VENDOR_ID_NEXIO		0x1870
 #define USB_DEVICE_ID_NEXIO_MULTITOUCH_420	0x010d
+#define USB_DEVICE_ID_NEXIO_MULTITOUCH_PTI0750	0x0110
 
 #define USB_VENDOR_ID_NEXTWINDOW	0x1926
 #define USB_DEVICE_ID_NEXTWINDOW_TOUCHSCREEN	0x0003
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
index d50e731..a713e62 100644
--- a/drivers/hid/hid-input.c
+++ b/drivers/hid/hid-input.c
@@ -1178,7 +1178,7 @@
 
 	/* fall back to generic raw-output-report */
 	len = ((report->size - 1) >> 3) + 1 + (report->id > 0);
-	buf = kmalloc(len, GFP_KERNEL);
+	buf = hid_alloc_report_buf(report, GFP_KERNEL);
 	if (!buf)
 		return;
 
diff --git a/drivers/hid/hid-microsoft.c b/drivers/hid/hid-microsoft.c
index c6ef6ee..404a3a8 100644
--- a/drivers/hid/hid-microsoft.c
+++ b/drivers/hid/hid-microsoft.c
@@ -208,6 +208,10 @@
 		.driver_data = MS_NOGET },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_COMFORT_MOUSE_4500),
 		.driver_data = MS_DUPLICATE_USAGES },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_2),
+		.driver_data = 0 },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TOUCH_COVER_2),
+		.driver_data = 0 },
 
 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_BT),
 		.driver_data = MS_PRESENTER },
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
index f134d73..221d503 100644
--- a/drivers/hid/hid-multitouch.c
+++ b/drivers/hid/hid-multitouch.c
@@ -1166,6 +1166,11 @@
 		MT_USB_DEVICE(USB_VENDOR_ID_FLATFROG,
 			USB_DEVICE_ID_MULTITOUCH_3200) },
 
+	/* FocalTech Panels */
+	{ .driver_data = MT_CLS_SERIAL,
+		MT_USB_DEVICE(USB_VENDOR_ID_CYGNAL,
+			USB_DEVICE_ID_FOCALTECH_FTXXXX_MULTITOUCH) },
+
 	/* GeneralTouch panel */
 	{ .driver_data = MT_CLS_GENERALTOUCH_TWOFINGERS,
 		MT_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH,
diff --git a/drivers/hid/hid-sensor-hub.c b/drivers/hid/hid-sensor-hub.c
index 46f4480..9c22e14 100644
--- a/drivers/hid/hid-sensor-hub.c
+++ b/drivers/hid/hid-sensor-hub.c
@@ -665,6 +665,9 @@
 	{ HID_DEVICE(HID_BUS_ANY, HID_GROUP_SENSOR_HUB, USB_VENDOR_ID_INTEL_1,
 			USB_DEVICE_ID_INTEL_HID_SENSOR),
 			.driver_data = HID_SENSOR_HUB_ENUM_QUIRK},
+	{ HID_DEVICE(HID_BUS_ANY, HID_GROUP_SENSOR_HUB, USB_VENDOR_ID_STM_0,
+			USB_DEVICE_ID_STM_HID_SENSOR),
+			.driver_data = HID_SENSOR_HUB_ENUM_QUIRK},
 	{ HID_DEVICE(HID_BUS_ANY, HID_GROUP_SENSOR_HUB, HID_ANY_ID,
 		     HID_ANY_ID) },
 	{ }
diff --git a/drivers/hid/i2c-hid/i2c-hid.c b/drivers/hid/i2c-hid/i2c-hid.c
index d1f81f5..42eebd1 100644
--- a/drivers/hid/i2c-hid/i2c-hid.c
+++ b/drivers/hid/i2c-hid/i2c-hid.c
@@ -582,7 +582,7 @@
 	int ret;
 	int len = i2c_hid_get_report_length(rep) - 2;
 
-	buf = kzalloc(len, GFP_KERNEL);
+	buf = hid_alloc_report_buf(rep, GFP_KERNEL);
 	if (!buf)
 		return;
 
diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c
index 175ec0a..dbd8387 100644
--- a/drivers/hid/usbhid/hid-quirks.c
+++ b/drivers/hid/usbhid/hid-quirks.c
@@ -74,6 +74,7 @@
 	{ USB_VENDOR_ID_FREESCALE, USB_DEVICE_ID_FREESCALE_MX28, HID_QUIRK_NOGET },
 	{ USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS, HID_QUIRK_NOGET },
 	{ USB_VENDOR_ID_MSI, USB_DEVICE_ID_MSI_GX680R_LED_PANEL, HID_QUIRK_NO_INIT_REPORTS },
+	{ USB_VENDOR_ID_NEXIO, USB_DEVICE_ID_NEXIO_MULTITOUCH_PTI0750, HID_QUIRK_NO_INIT_REPORTS },
 	{ USB_VENDOR_ID_NOVATEK, USB_DEVICE_ID_NOVATEK_MOUSE, HID_QUIRK_NO_INIT_REPORTS },
 	{ USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN, HID_QUIRK_NO_INIT_REPORTS },
 	{ USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN1, HID_QUIRK_NO_INIT_REPORTS },
diff --git a/drivers/hwmon/max1668.c b/drivers/hwmon/max1668.c
index a762635..029b65e 100644
--- a/drivers/hwmon/max1668.c
+++ b/drivers/hwmon/max1668.c
@@ -243,7 +243,7 @@
 	data->temp_min[index] = clamp_val(temp/1000, -128, 127);
 	if (i2c_smbus_write_byte_data(client,
 					MAX1668_REG_LIML_WR(index),
-					data->temp_max[index]))
+					data->temp_min[index]))
 		count = -EIO;
 	mutex_unlock(&data->update_lock);
 
diff --git a/drivers/iio/gyro/Kconfig b/drivers/iio/gyro/Kconfig
index 41c64a4..ac2d69e 100644
--- a/drivers/iio/gyro/Kconfig
+++ b/drivers/iio/gyro/Kconfig
@@ -70,7 +70,7 @@
 	select IIO_TRIGGERED_BUFFER if (IIO_BUFFER)
 	help
 	  Say yes here to build support for STMicroelectronics gyroscopes:
-	  L3G4200D, LSM330DL, L3GD20, L3GD20H, LSM330DLC, L3G4IS, LSM330.
+	  L3G4200D, LSM330DL, L3GD20, LSM330DLC, L3G4IS, LSM330.
 
 	  This driver can also be built as a module. If so, these modules
 	  will be created:
diff --git a/drivers/iio/gyro/st_gyro.h b/drivers/iio/gyro/st_gyro.h
index f8f2bf8..c197360 100644
--- a/drivers/iio/gyro/st_gyro.h
+++ b/drivers/iio/gyro/st_gyro.h
@@ -19,7 +19,6 @@
 #define LSM330DL_GYRO_DEV_NAME		"lsm330dl_gyro"
 #define LSM330DLC_GYRO_DEV_NAME		"lsm330dlc_gyro"
 #define L3GD20_GYRO_DEV_NAME		"l3gd20"
-#define L3GD20H_GYRO_DEV_NAME		"l3gd20h"
 #define L3G4IS_GYRO_DEV_NAME		"l3g4is_ui"
 #define LSM330_GYRO_DEV_NAME		"lsm330_gyro"
 
diff --git a/drivers/iio/gyro/st_gyro_core.c b/drivers/iio/gyro/st_gyro_core.c
index d53d91a..a8e174a 100644
--- a/drivers/iio/gyro/st_gyro_core.c
+++ b/drivers/iio/gyro/st_gyro_core.c
@@ -167,11 +167,10 @@
 		.wai = ST_GYRO_2_WAI_EXP,
 		.sensors_supported = {
 			[0] = L3GD20_GYRO_DEV_NAME,
-			[1] = L3GD20H_GYRO_DEV_NAME,
-			[2] = LSM330D_GYRO_DEV_NAME,
-			[3] = LSM330DLC_GYRO_DEV_NAME,
-			[4] = L3G4IS_GYRO_DEV_NAME,
-			[5] = LSM330_GYRO_DEV_NAME,
+			[1] = LSM330D_GYRO_DEV_NAME,
+			[2] = LSM330DLC_GYRO_DEV_NAME,
+			[3] = L3G4IS_GYRO_DEV_NAME,
+			[4] = LSM330_GYRO_DEV_NAME,
 		},
 		.ch = (struct iio_chan_spec *)st_gyro_16bit_channels,
 		.odr = {
diff --git a/drivers/iio/gyro/st_gyro_i2c.c b/drivers/iio/gyro/st_gyro_i2c.c
index 16b8b8d..23c12f3 100644
--- a/drivers/iio/gyro/st_gyro_i2c.c
+++ b/drivers/iio/gyro/st_gyro_i2c.c
@@ -55,7 +55,6 @@
 	{ LSM330DL_GYRO_DEV_NAME },
 	{ LSM330DLC_GYRO_DEV_NAME },
 	{ L3GD20_GYRO_DEV_NAME },
-	{ L3GD20H_GYRO_DEV_NAME },
 	{ L3G4IS_GYRO_DEV_NAME },
 	{ LSM330_GYRO_DEV_NAME },
 	{},
diff --git a/drivers/iio/gyro/st_gyro_spi.c b/drivers/iio/gyro/st_gyro_spi.c
index 94763e2..b4ad3be 100644
--- a/drivers/iio/gyro/st_gyro_spi.c
+++ b/drivers/iio/gyro/st_gyro_spi.c
@@ -54,7 +54,6 @@
 	{ LSM330DL_GYRO_DEV_NAME },
 	{ LSM330DLC_GYRO_DEV_NAME },
 	{ L3GD20_GYRO_DEV_NAME },
-	{ L3GD20H_GYRO_DEV_NAME },
 	{ L3G4IS_GYRO_DEV_NAME },
 	{ LSM330_GYRO_DEV_NAME },
 	{},
diff --git a/drivers/iio/light/cm32181.c b/drivers/iio/light/cm32181.c
index f17b4e6..47a6dba 100644
--- a/drivers/iio/light/cm32181.c
+++ b/drivers/iio/light/cm32181.c
@@ -103,13 +103,13 @@
 /**
  *  cm32181_read_als_it() - Get sensor integration time (ms)
  *  @cm32181:	pointer of struct cm32181
- *  @val:	pointer of int to load the als_it value.
+ *  @val2:	pointer of int to load the als_it value.
  *
  *  Report the current integartion time by millisecond.
  *
- *  Return: IIO_VAL_INT for success, otherwise -EINVAL.
+ *  Return: IIO_VAL_INT_PLUS_MICRO for success, otherwise -EINVAL.
  */
-static int cm32181_read_als_it(struct cm32181_chip *cm32181, int *val)
+static int cm32181_read_als_it(struct cm32181_chip *cm32181, int *val2)
 {
 	u16 als_it;
 	int i;
@@ -119,8 +119,8 @@
 	als_it >>= CM32181_CMD_ALS_IT_SHIFT;
 	for (i = 0; i < ARRAY_SIZE(als_it_bits); i++) {
 		if (als_it == als_it_bits[i]) {
-			*val = als_it_value[i];
-			return IIO_VAL_INT;
+			*val2 = als_it_value[i];
+			return IIO_VAL_INT_PLUS_MICRO;
 		}
 	}
 
@@ -221,7 +221,7 @@
 		*val = cm32181->calibscale;
 		return IIO_VAL_INT;
 	case IIO_CHAN_INFO_INT_TIME:
-		ret = cm32181_read_als_it(cm32181, val);
+		ret = cm32181_read_als_it(cm32181, val2);
 		return ret;
 	}
 
@@ -240,7 +240,7 @@
 		cm32181->calibscale = val;
 		return val;
 	case IIO_CHAN_INFO_INT_TIME:
-		ret = cm32181_write_als_it(cm32181, val);
+		ret = cm32181_write_als_it(cm32181, val2);
 		return ret;
 	}
 
@@ -264,7 +264,7 @@
 
 	n = ARRAY_SIZE(als_it_value);
 	for (i = 0, len = 0; i < n; i++)
-		len += sprintf(buf + len, "%d ", als_it_value[i]);
+		len += sprintf(buf + len, "0.%06u ", als_it_value[i]);
 	return len + sprintf(buf + len, "\n");
 }
 
diff --git a/drivers/iio/light/cm36651.c b/drivers/iio/light/cm36651.c
index 0a142af..a45e074 100644
--- a/drivers/iio/light/cm36651.c
+++ b/drivers/iio/light/cm36651.c
@@ -50,10 +50,10 @@
 #define CM36651_CS_CONF2_DEFAULT_BIT	0x08
 
 /* CS_CONF3 channel integration time */
-#define CM36651_CS_IT1			0x00 /* Integration time 80000 usec */
-#define CM36651_CS_IT2			0x40 /* Integration time 160000 usec */
-#define CM36651_CS_IT3			0x80 /* Integration time 320000 usec */
-#define CM36651_CS_IT4			0xC0 /* Integration time 640000 usec */
+#define CM36651_CS_IT1			0x00 /* Integration time 80 msec */
+#define CM36651_CS_IT2			0x40 /* Integration time 160 msec */
+#define CM36651_CS_IT3			0x80 /* Integration time 320 msec */
+#define CM36651_CS_IT4			0xC0 /* Integration time 640 msec */
 
 /* PS_CONF1 command code */
 #define CM36651_PS_ENABLE		0x00
@@ -64,10 +64,10 @@
 #define CM36651_PS_PERS4		0x0C
 
 /* PS_CONF1 command code: integration time */
-#define CM36651_PS_IT1			0x00 /* Integration time 320 usec */
-#define CM36651_PS_IT2			0x10 /* Integration time 420 usec */
-#define CM36651_PS_IT3			0x20 /* Integration time 520 usec */
-#define CM36651_PS_IT4			0x30 /* Integration time 640 usec */
+#define CM36651_PS_IT1			0x00 /* Integration time 0.32 msec */
+#define CM36651_PS_IT2			0x10 /* Integration time 0.42 msec */
+#define CM36651_PS_IT3			0x20 /* Integration time 0.52 msec */
+#define CM36651_PS_IT4			0x30 /* Integration time 0.64 msec */
 
 /* PS_CONF1 command code: duty ratio */
 #define CM36651_PS_DR1			0x00 /* Duty ratio 1/80 */
@@ -93,8 +93,8 @@
 #define CM36651_CLOSE_PROXIMITY		0x32
 #define CM36651_FAR_PROXIMITY			0x33
 
-#define CM36651_CS_INT_TIME_AVAIL	"80000 160000 320000 640000"
-#define CM36651_PS_INT_TIME_AVAIL	"320 420 520 640"
+#define CM36651_CS_INT_TIME_AVAIL	"0.08 0.16 0.32 0.64"
+#define CM36651_PS_INT_TIME_AVAIL	"0.000320 0.000420 0.000520 0.000640"
 
 enum cm36651_operation_mode {
 	CM36651_LIGHT_EN,
@@ -356,30 +356,30 @@
 }
 
 static int cm36651_read_int_time(struct cm36651_data *cm36651,
-				struct iio_chan_spec const *chan, int *val)
+				struct iio_chan_spec const *chan, int *val2)
 {
 	switch (chan->type) {
 	case IIO_LIGHT:
 		if (cm36651->cs_int_time[chan->address] == CM36651_CS_IT1)
-			*val = 80000;
+			*val2 = 80000;
 		else if (cm36651->cs_int_time[chan->address] == CM36651_CS_IT2)
-			*val = 160000;
+			*val2 = 160000;
 		else if (cm36651->cs_int_time[chan->address] == CM36651_CS_IT3)
-			*val = 320000;
+			*val2 = 320000;
 		else if (cm36651->cs_int_time[chan->address] == CM36651_CS_IT4)
-			*val = 640000;
+			*val2 = 640000;
 		else
 			return -EINVAL;
 		break;
 	case IIO_PROXIMITY:
 		if (cm36651->ps_int_time == CM36651_PS_IT1)
-			*val = 320;
+			*val2 = 320;
 		else if (cm36651->ps_int_time == CM36651_PS_IT2)
-			*val = 420;
+			*val2 = 420;
 		else if (cm36651->ps_int_time == CM36651_PS_IT3)
-			*val = 520;
+			*val2 = 520;
 		else if (cm36651->ps_int_time == CM36651_PS_IT4)
-			*val = 640;
+			*val2 = 640;
 		else
 			return -EINVAL;
 		break;
@@ -387,7 +387,7 @@
 		return -EINVAL;
 	}
 
-	return IIO_VAL_INT;
+	return IIO_VAL_INT_PLUS_MICRO;
 }
 
 static int cm36651_write_int_time(struct cm36651_data *cm36651,
@@ -459,7 +459,8 @@
 		ret = cm36651_read_channel(cm36651, chan, val);
 		break;
 	case IIO_CHAN_INFO_INT_TIME:
-		ret = cm36651_read_int_time(cm36651, chan, val);
+		*val = 0;
+		ret = cm36651_read_int_time(cm36651, chan, val2);
 		break;
 	default:
 		ret = -EINVAL;
@@ -479,7 +480,7 @@
 	int ret = -EINVAL;
 
 	if (mask == IIO_CHAN_INFO_INT_TIME) {
-		ret = cm36651_write_int_time(cm36651, chan, val);
+		ret = cm36651_write_int_time(cm36651, chan, val2);
 		if (ret < 0)
 			dev_err(&client->dev, "Integration time write failed\n");
 	}
diff --git a/drivers/input/misc/arizona-haptics.c b/drivers/input/misc/arizona-haptics.c
index 7a04f54..ef2e281 100644
--- a/drivers/input/misc/arizona-haptics.c
+++ b/drivers/input/misc/arizona-haptics.c
@@ -37,7 +37,6 @@
 						       struct arizona_haptics,
 						       work);
 	struct arizona *arizona = haptics->arizona;
-	struct mutex *dapm_mutex = &arizona->dapm->card->dapm_mutex;
 	int ret;
 
 	if (!haptics->arizona->dapm) {
@@ -67,13 +66,10 @@
 			return;
 		}
 
-		mutex_lock_nested(dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
-
 		ret = snd_soc_dapm_enable_pin(arizona->dapm, "HAPTICS");
 		if (ret != 0) {
 			dev_err(arizona->dev, "Failed to start HAPTICS: %d\n",
 				ret);
-			mutex_unlock(dapm_mutex);
 			return;
 		}
 
@@ -81,21 +77,14 @@
 		if (ret != 0) {
 			dev_err(arizona->dev, "Failed to sync DAPM: %d\n",
 				ret);
-			mutex_unlock(dapm_mutex);
 			return;
 		}
-
-		mutex_unlock(dapm_mutex);
-
 	} else {
 		/* This disable sequence will be a noop if already enabled */
-		mutex_lock_nested(dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
-
 		ret = snd_soc_dapm_disable_pin(arizona->dapm, "HAPTICS");
 		if (ret != 0) {
 			dev_err(arizona->dev, "Failed to disable HAPTICS: %d\n",
 				ret);
-			mutex_unlock(dapm_mutex);
 			return;
 		}
 
@@ -103,12 +92,9 @@
 		if (ret != 0) {
 			dev_err(arizona->dev, "Failed to sync DAPM: %d\n",
 				ret);
-			mutex_unlock(dapm_mutex);
 			return;
 		}
 
-		mutex_unlock(dapm_mutex);
-
 		ret = regmap_update_bits(arizona->regmap,
 					 ARIZONA_HAPTICS_CONTROL_1,
 					 ARIZONA_HAP_CTRL_MASK,
@@ -155,16 +141,11 @@
 static void arizona_haptics_close(struct input_dev *input)
 {
 	struct arizona_haptics *haptics = input_get_drvdata(input);
-	struct mutex *dapm_mutex = &haptics->arizona->dapm->card->dapm_mutex;
 
 	cancel_work_sync(&haptics->work);
 
-	mutex_lock_nested(dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
-
 	if (haptics->arizona->dapm)
 		snd_soc_dapm_disable_pin(haptics->arizona->dapm, "HAPTICS");
-
-	mutex_unlock(dapm_mutex);
 }
 
 static int arizona_haptics_probe(struct platform_device *pdev)
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index 8911850..1d9ab39 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -79,7 +79,6 @@
 
 #define ARM_SMMU_PTE_CONT_SIZE		(PAGE_SIZE * ARM_SMMU_PTE_CONT_ENTRIES)
 #define ARM_SMMU_PTE_CONT_MASK		(~(ARM_SMMU_PTE_CONT_SIZE - 1))
-#define ARM_SMMU_PTE_HWTABLE_SIZE	(PTRS_PER_PTE * sizeof(pte_t))
 
 /* Stage-1 PTE */
 #define ARM_SMMU_PTE_AP_UNPRIV		(((pteval_t)1) << 6)
@@ -191,6 +190,9 @@
 #define ARM_SMMU_GR1_CBAR(n)		(0x0 + ((n) << 2))
 #define CBAR_VMID_SHIFT			0
 #define CBAR_VMID_MASK			0xff
+#define CBAR_S1_BPSHCFG_SHIFT		8
+#define CBAR_S1_BPSHCFG_MASK		3
+#define CBAR_S1_BPSHCFG_NSH		3
 #define CBAR_S1_MEMATTR_SHIFT		12
 #define CBAR_S1_MEMATTR_MASK		0xf
 #define CBAR_S1_MEMATTR_WB		0xf
@@ -393,7 +395,7 @@
 	struct arm_smmu_cfg		root_cfg;
 	phys_addr_t			output_mask;
 
-	struct mutex			lock;
+	spinlock_t			lock;
 };
 
 static DEFINE_SPINLOCK(arm_smmu_devices_lock);
@@ -632,6 +634,28 @@
 	return IRQ_HANDLED;
 }
 
+static void arm_smmu_flush_pgtable(struct arm_smmu_device *smmu, void *addr,
+				   size_t size)
+{
+	unsigned long offset = (unsigned long)addr & ~PAGE_MASK;
+
+
+	/* Ensure new page tables are visible to the hardware walker */
+	if (smmu->features & ARM_SMMU_FEAT_COHERENT_WALK) {
+		dsb();
+	} else {
+		/*
+		 * If the SMMU can't walk tables in the CPU caches, treat them
+		 * like non-coherent DMA since we need to flush the new entries
+		 * all the way out to memory. There's no possibility of
+		 * recursion here as the SMMU table walker will not be wired
+		 * through another SMMU.
+		 */
+		dma_map_page(smmu->dev, virt_to_page(addr), offset, size,
+				DMA_TO_DEVICE);
+	}
+}
+
 static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain)
 {
 	u32 reg;
@@ -650,11 +674,16 @@
 	if (smmu->version == 1)
 	      reg |= root_cfg->irptndx << CBAR_IRPTNDX_SHIFT;
 
-	/* Use the weakest memory type, so it is overridden by the pte */
-	if (stage1)
-		reg |= (CBAR_S1_MEMATTR_WB << CBAR_S1_MEMATTR_SHIFT);
-	else
+	/*
+	 * Use the weakest shareability/memory types, so they are
+	 * overridden by the ttbcr/pte.
+	 */
+	if (stage1) {
+		reg |= (CBAR_S1_BPSHCFG_NSH << CBAR_S1_BPSHCFG_SHIFT) |
+			(CBAR_S1_MEMATTR_WB << CBAR_S1_MEMATTR_SHIFT);
+	} else {
 		reg |= ARM_SMMU_CB_VMID(root_cfg) << CBAR_VMID_SHIFT;
+	}
 	writel_relaxed(reg, gr1_base + ARM_SMMU_GR1_CBAR(root_cfg->cbndx));
 
 	if (smmu->version > 1) {
@@ -715,6 +744,8 @@
 	}
 
 	/* TTBR0 */
+	arm_smmu_flush_pgtable(smmu, root_cfg->pgd,
+			       PTRS_PER_PGD * sizeof(pgd_t));
 	reg = __pa(root_cfg->pgd);
 	writel_relaxed(reg, cb_base + ARM_SMMU_CB_TTBR0_LO);
 	reg = (phys_addr_t)__pa(root_cfg->pgd) >> 32;
@@ -901,7 +932,7 @@
 		goto out_free_domain;
 	smmu_domain->root_cfg.pgd = pgd;
 
-	mutex_init(&smmu_domain->lock);
+	spin_lock_init(&smmu_domain->lock);
 	domain->priv = smmu_domain;
 	return 0;
 
@@ -1128,6 +1159,7 @@
 	struct arm_smmu_domain *smmu_domain = domain->priv;
 	struct arm_smmu_device *device_smmu = dev->archdata.iommu;
 	struct arm_smmu_master *master;
+	unsigned long flags;
 
 	if (!device_smmu) {
 		dev_err(dev, "cannot attach to SMMU, is it on the same bus?\n");
@@ -1138,7 +1170,7 @@
 	 * Sanity check the domain. We don't currently support domains
 	 * that cross between different SMMU chains.
 	 */
-	mutex_lock(&smmu_domain->lock);
+	spin_lock_irqsave(&smmu_domain->lock, flags);
 	if (!smmu_domain->leaf_smmu) {
 		/* Now that we have a master, we can finalise the domain */
 		ret = arm_smmu_init_domain_context(domain, dev);
@@ -1153,7 +1185,7 @@
 			dev_name(device_smmu->dev));
 		goto err_unlock;
 	}
-	mutex_unlock(&smmu_domain->lock);
+	spin_unlock_irqrestore(&smmu_domain->lock, flags);
 
 	/* Looks ok, so add the device to the domain */
 	master = find_smmu_master(smmu_domain->leaf_smmu, dev->of_node);
@@ -1163,7 +1195,7 @@
 	return arm_smmu_domain_add_master(smmu_domain, master);
 
 err_unlock:
-	mutex_unlock(&smmu_domain->lock);
+	spin_unlock_irqrestore(&smmu_domain->lock, flags);
 	return ret;
 }
 
@@ -1177,23 +1209,6 @@
 		arm_smmu_domain_remove_master(smmu_domain, master);
 }
 
-static void arm_smmu_flush_pgtable(struct arm_smmu_device *smmu, void *addr,
-				   size_t size)
-{
-	unsigned long offset = (unsigned long)addr & ~PAGE_MASK;
-
-	/*
-	 * If the SMMU can't walk tables in the CPU caches, treat them
-	 * like non-coherent DMA since we need to flush the new entries
-	 * all the way out to memory. There's no possibility of recursion
-	 * here as the SMMU table walker will not be wired through another
-	 * SMMU.
-	 */
-	if (!(smmu->features & ARM_SMMU_FEAT_COHERENT_WALK))
-		dma_map_page(smmu->dev, virt_to_page(addr), offset, size,
-			     DMA_TO_DEVICE);
-}
-
 static bool arm_smmu_pte_is_contiguous_range(unsigned long addr,
 					     unsigned long end)
 {
@@ -1210,12 +1225,11 @@
 
 	if (pmd_none(*pmd)) {
 		/* Allocate a new set of tables */
-		pgtable_t table = alloc_page(PGALLOC_GFP);
+		pgtable_t table = alloc_page(GFP_ATOMIC|__GFP_ZERO);
 		if (!table)
 			return -ENOMEM;
 
-		arm_smmu_flush_pgtable(smmu, page_address(table),
-				       ARM_SMMU_PTE_HWTABLE_SIZE);
+		arm_smmu_flush_pgtable(smmu, page_address(table), PAGE_SIZE);
 		if (!pgtable_page_ctor(table)) {
 			__free_page(table);
 			return -ENOMEM;
@@ -1317,9 +1331,15 @@
 
 #ifndef __PAGETABLE_PMD_FOLDED
 	if (pud_none(*pud)) {
-		pmd = pmd_alloc_one(NULL, addr);
+		pmd = (pmd_t *)get_zeroed_page(GFP_ATOMIC);
 		if (!pmd)
 			return -ENOMEM;
+
+		arm_smmu_flush_pgtable(smmu, pmd, PAGE_SIZE);
+		pud_populate(NULL, pud, pmd);
+		arm_smmu_flush_pgtable(smmu, pud, sizeof(*pud));
+
+		pmd += pmd_index(addr);
 	} else
 #endif
 		pmd = pmd_offset(pud, addr);
@@ -1328,8 +1348,6 @@
 		next = pmd_addr_end(addr, end);
 		ret = arm_smmu_alloc_init_pte(smmu, pmd, addr, end, pfn,
 					      flags, stage);
-		pud_populate(NULL, pud, pmd);
-		arm_smmu_flush_pgtable(smmu, pud, sizeof(*pud));
 		phys += next - addr;
 	} while (pmd++, addr = next, addr < end);
 
@@ -1346,9 +1364,15 @@
 
 #ifndef __PAGETABLE_PUD_FOLDED
 	if (pgd_none(*pgd)) {
-		pud = pud_alloc_one(NULL, addr);
+		pud = (pud_t *)get_zeroed_page(GFP_ATOMIC);
 		if (!pud)
 			return -ENOMEM;
+
+		arm_smmu_flush_pgtable(smmu, pud, PAGE_SIZE);
+		pgd_populate(NULL, pgd, pud);
+		arm_smmu_flush_pgtable(smmu, pgd, sizeof(*pgd));
+
+		pud += pud_index(addr);
 	} else
 #endif
 		pud = pud_offset(pgd, addr);
@@ -1357,8 +1381,6 @@
 		next = pud_addr_end(addr, end);
 		ret = arm_smmu_alloc_init_pmd(smmu, pud, addr, next, phys,
 					      flags, stage);
-		pgd_populate(NULL, pud, pgd);
-		arm_smmu_flush_pgtable(smmu, pgd, sizeof(*pgd));
 		phys += next - addr;
 	} while (pud++, addr = next, addr < end);
 
@@ -1375,6 +1397,7 @@
 	struct arm_smmu_cfg *root_cfg = &smmu_domain->root_cfg;
 	pgd_t *pgd = root_cfg->pgd;
 	struct arm_smmu_device *smmu = root_cfg->smmu;
+	unsigned long irqflags;
 
 	if (root_cfg->cbar == CBAR_TYPE_S2_TRANS) {
 		stage = 2;
@@ -1397,7 +1420,7 @@
 	if (paddr & ~output_mask)
 		return -ERANGE;
 
-	mutex_lock(&smmu_domain->lock);
+	spin_lock_irqsave(&smmu_domain->lock, irqflags);
 	pgd += pgd_index(iova);
 	end = iova + size;
 	do {
@@ -1413,11 +1436,7 @@
 	} while (pgd++, iova != end);
 
 out_unlock:
-	mutex_unlock(&smmu_domain->lock);
-
-	/* Ensure new page tables are visible to the hardware walker */
-	if (smmu->features & ARM_SMMU_FEAT_COHERENT_WALK)
-		dsb();
+	spin_unlock_irqrestore(&smmu_domain->lock, irqflags);
 
 	return ret;
 }
@@ -1987,8 +2006,10 @@
 	if (!iommu_present(&platform_bus_type))
 		bus_set_iommu(&platform_bus_type, &arm_smmu_ops);
 
+#ifdef CONFIG_ARM_AMBA
 	if (!iommu_present(&amba_bustype))
 		bus_set_iommu(&amba_bustype, &arm_smmu_ops);
+#endif
 
 	return 0;
 }
diff --git a/drivers/iommu/omap-iommu-debug.c b/drivers/iommu/omap-iommu-debug.c
index d97fbe4..80fffba 100644
--- a/drivers/iommu/omap-iommu-debug.c
+++ b/drivers/iommu/omap-iommu-debug.c
@@ -354,8 +354,8 @@
 			return -ENOMEM;					\
 	}
 
-#define DEBUG_ADD_FILE(name) __DEBUG_ADD_FILE(name, 600)
-#define DEBUG_ADD_FILE_RO(name) __DEBUG_ADD_FILE(name, 400)
+#define DEBUG_ADD_FILE(name) __DEBUG_ADD_FILE(name, 0600)
+#define DEBUG_ADD_FILE_RO(name) __DEBUG_ADD_FILE(name, 0400)
 
 static int iommu_debug_register(struct device *dev, void *data)
 {
diff --git a/drivers/irqchip/irq-metag-ext.c b/drivers/irqchip/irq-metag-ext.c
index 92c41ab..2cb474a 100644
--- a/drivers/irqchip/irq-metag-ext.c
+++ b/drivers/irqchip/irq-metag-ext.c
@@ -515,7 +515,7 @@
 	 * one cpu (the interrupt code doesn't support it), so we just
 	 * pick the first cpu we find in 'cpumask'.
 	 */
-	cpu = cpumask_any(cpumask);
+	cpu = cpumask_any_and(cpumask, cpu_online_mask);
 	thread = cpu_2_hwthread_id[cpu];
 
 	metag_out32(TBI_TRIG_VEC(TBID_SIGNUM_TR2(thread)), vec_addr);
diff --git a/drivers/irqchip/irq-metag.c b/drivers/irqchip/irq-metag.c
index 8e94d7a..c16c186 100644
--- a/drivers/irqchip/irq-metag.c
+++ b/drivers/irqchip/irq-metag.c
@@ -201,7 +201,7 @@
 	 * one cpu (the interrupt code doesn't support it), so we just
 	 * pick the first cpu we find in 'cpumask'.
 	 */
-	cpu = cpumask_any(cpumask);
+	cpu = cpumask_any_and(cpumask, cpu_online_mask);
 	thread = cpu_2_hwthread_id[cpu];
 
 	metag_out32(TBI_TRIG_VEC(TBID_SIGNUM_TR1(thread)),
diff --git a/drivers/irqchip/irq-orion.c b/drivers/irqchip/irq-orion.c
index e51d400..8e41be6 100644
--- a/drivers/irqchip/irq-orion.c
+++ b/drivers/irqchip/irq-orion.c
@@ -111,7 +111,8 @@
 static void orion_bridge_irq_handler(unsigned int irq, struct irq_desc *desc)
 {
 	struct irq_domain *d = irq_get_handler_data(irq);
-	struct irq_chip_generic *gc = irq_get_domain_generic_chip(d, irq);
+
+	struct irq_chip_generic *gc = irq_get_domain_generic_chip(d, 0);
 	u32 stat = readl_relaxed(gc->reg_base + ORION_BRIDGE_IRQ_CAUSE) &
 		   gc->mask_cache;
 
@@ -123,6 +124,19 @@
 	}
 }
 
+/*
+ * Bridge IRQ_CAUSE is asserted regardless of IRQ_MASK register.
+ * To avoid interrupt events on stale irqs, we clear them before unmask.
+ */
+static unsigned int orion_bridge_irq_startup(struct irq_data *d)
+{
+	struct irq_chip_type *ct = irq_data_get_chip_type(d);
+
+	ct->chip.irq_ack(d);
+	ct->chip.irq_unmask(d);
+	return 0;
+}
+
 static int __init orion_bridge_irq_init(struct device_node *np,
 					struct device_node *parent)
 {
@@ -143,7 +157,7 @@
 	}
 
 	ret = irq_alloc_domain_generic_chips(domain, nrirqs, 1, np->name,
-			     handle_level_irq, clr, 0, IRQ_GC_INIT_MASK_CACHE);
+			     handle_edge_irq, clr, 0, IRQ_GC_INIT_MASK_CACHE);
 	if (ret) {
 		pr_err("%s: unable to alloc irq domain gc\n", np->name);
 		return ret;
@@ -176,12 +190,14 @@
 
 	gc->chip_types[0].regs.ack = ORION_BRIDGE_IRQ_CAUSE;
 	gc->chip_types[0].regs.mask = ORION_BRIDGE_IRQ_MASK;
+	gc->chip_types[0].chip.irq_startup = orion_bridge_irq_startup;
 	gc->chip_types[0].chip.irq_ack = irq_gc_ack_clr_bit;
 	gc->chip_types[0].chip.irq_mask = irq_gc_mask_clr_bit;
 	gc->chip_types[0].chip.irq_unmask = irq_gc_mask_set_bit;
 
-	/* mask all interrupts */
+	/* mask and clear all interrupts */
 	writel(0, gc->reg_base + ORION_BRIDGE_IRQ_MASK);
+	writel(0, gc->reg_base + ORION_BRIDGE_IRQ_CAUSE);
 
 	irq_set_handler_data(irq, domain);
 	irq_set_chained_handler(irq, orion_bridge_irq_handler);
diff --git a/drivers/md/dm-cache-target.c b/drivers/md/dm-cache-target.c
index ffd472e..1af7014 100644
--- a/drivers/md/dm-cache-target.c
+++ b/drivers/md/dm-cache-target.c
@@ -289,6 +289,7 @@
 	bool tick:1;
 	unsigned req_nr:2;
 	struct dm_deferred_entry *all_io_entry;
+	struct dm_hook_info hook_info;
 
 	/*
 	 * writethrough fields.  These MUST remain at the end of this
@@ -297,7 +298,6 @@
 	 */
 	struct cache *cache;
 	dm_cblock_t cblock;
-	struct dm_hook_info hook_info;
 	struct dm_bio_details bio_details;
 };
 
@@ -671,15 +671,16 @@
 			   dm_cblock_t cblock)
 {
 	sector_t bi_sector = bio->bi_iter.bi_sector;
+	sector_t block = from_cblock(cblock);
 
 	bio->bi_bdev = cache->cache_dev->bdev;
 	if (!block_size_is_power_of_two(cache))
 		bio->bi_iter.bi_sector =
-			(from_cblock(cblock) * cache->sectors_per_block) +
+			(block * cache->sectors_per_block) +
 			sector_div(bi_sector, cache->sectors_per_block);
 	else
 		bio->bi_iter.bi_sector =
-			(from_cblock(cblock) << cache->sectors_per_block_shift) |
+			(block << cache->sectors_per_block_shift) |
 			(bi_sector & (cache->sectors_per_block - 1));
 }
 
@@ -1010,13 +1011,15 @@
 	struct per_bio_data *pb = get_per_bio_data(bio, pb_data_size);
 	unsigned long flags;
 
+	dm_unhook_bio(&pb->hook_info, bio);
+
 	if (err)
 		mg->err = true;
 
+	mg->requeue_holder = false;
+
 	spin_lock_irqsave(&cache->lock, flags);
 	list_add_tail(&mg->list, &cache->completed_migrations);
-	dm_unhook_bio(&pb->hook_info, bio);
-	mg->requeue_holder = false;
 	spin_unlock_irqrestore(&cache->lock, flags);
 
 	wake_worker(cache);
diff --git a/drivers/md/dm-io.c b/drivers/md/dm-io.c
index b2b8a10..3842ac7 100644
--- a/drivers/md/dm-io.c
+++ b/drivers/md/dm-io.c
@@ -201,29 +201,28 @@
 /*
  * Functions for getting the pages from a bvec.
  */
-static void bio_get_page(struct dpages *dp,
-		  struct page **p, unsigned long *len, unsigned *offset)
+static void bio_get_page(struct dpages *dp, struct page **p,
+			 unsigned long *len, unsigned *offset)
 {
-	struct bio *bio = dp->context_ptr;
-	struct bio_vec bvec = bio_iovec(bio);
-	*p = bvec.bv_page;
-	*len = bvec.bv_len;
-	*offset = bvec.bv_offset;
+	struct bio_vec *bvec = dp->context_ptr;
+	*p = bvec->bv_page;
+	*len = bvec->bv_len - dp->context_u;
+	*offset = bvec->bv_offset + dp->context_u;
 }
 
 static void bio_next_page(struct dpages *dp)
 {
-	struct bio *bio = dp->context_ptr;
-	struct bio_vec bvec = bio_iovec(bio);
-
-	bio_advance(bio, bvec.bv_len);
+	struct bio_vec *bvec = dp->context_ptr;
+	dp->context_ptr = bvec + 1;
+	dp->context_u = 0;
 }
 
 static void bio_dp_init(struct dpages *dp, struct bio *bio)
 {
 	dp->get_page = bio_get_page;
 	dp->next_page = bio_next_page;
-	dp->context_ptr = bio;
+	dp->context_ptr = __bvec_iter_bvec(bio->bi_io_vec, bio->bi_iter);
+	dp->context_u = bio->bi_iter.bi_bvec_done;
 }
 
 /*
diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c
index 6eb9dc9..422a9fde 100644
--- a/drivers/md/dm-mpath.c
+++ b/drivers/md/dm-mpath.c
@@ -1626,8 +1626,11 @@
 	/*
 	 * Only pass ioctls through if the device sizes match exactly.
 	 */
-	if (!r && ti->len != i_size_read(bdev->bd_inode) >> SECTOR_SHIFT)
-		r = scsi_verify_blk_ioctl(NULL, cmd);
+	if (!bdev || ti->len != i_size_read(bdev->bd_inode) >> SECTOR_SHIFT) {
+		int err = scsi_verify_blk_ioctl(NULL, cmd);
+		if (err)
+			r = err;
+	}
 
 	if (r == -ENOTCONN && !fatal_signal_pending(current))
 		queue_work(kmultipathd, &m->process_queued_ios);
diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c
index f284e0b..7dfdb5c 100644
--- a/drivers/md/dm-raid1.c
+++ b/drivers/md/dm-raid1.c
@@ -1244,6 +1244,9 @@
 
 			dm_bio_restore(bd, bio);
 			bio_record->details.bi_bdev = NULL;
+
+			atomic_inc(&bio->bi_remaining);
+
 			queue_bio(ms, bio, rw);
 			return DM_ENDIO_INCOMPLETE;
 		}
diff --git a/drivers/md/dm-thin-metadata.c b/drivers/md/dm-thin-metadata.c
index 7da3476..baa87ff 100644
--- a/drivers/md/dm-thin-metadata.c
+++ b/drivers/md/dm-thin-metadata.c
@@ -483,7 +483,7 @@
 
 	disk_super->data_mapping_root = cpu_to_le64(pmd->root);
 	disk_super->device_details_root = cpu_to_le64(pmd->details_root);
-	disk_super->metadata_block_size = cpu_to_le32(THIN_METADATA_BLOCK_SIZE >> SECTOR_SHIFT);
+	disk_super->metadata_block_size = cpu_to_le32(THIN_METADATA_BLOCK_SIZE);
 	disk_super->metadata_nr_blocks = cpu_to_le64(bdev_size >> SECTOR_TO_BLOCK_SHIFT);
 	disk_super->data_block_size = cpu_to_le32(pmd->data_block_size);
 
@@ -651,7 +651,7 @@
 {
 	int r;
 
-	pmd->bm = dm_block_manager_create(pmd->bdev, THIN_METADATA_BLOCK_SIZE,
+	pmd->bm = dm_block_manager_create(pmd->bdev, THIN_METADATA_BLOCK_SIZE << SECTOR_SHIFT,
 					  THIN_METADATA_CACHE_SIZE,
 					  THIN_MAX_CONCURRENT_LOCKS);
 	if (IS_ERR(pmd->bm)) {
@@ -1489,6 +1489,23 @@
 	return r;
 }
 
+bool dm_pool_changed_this_transaction(struct dm_pool_metadata *pmd)
+{
+	bool r = false;
+	struct dm_thin_device *td, *tmp;
+
+	down_read(&pmd->root_lock);
+	list_for_each_entry_safe(td, tmp, &pmd->thin_devices, list) {
+		if (td->changed) {
+			r = td->changed;
+			break;
+		}
+	}
+	up_read(&pmd->root_lock);
+
+	return r;
+}
+
 bool dm_thin_aborted_changes(struct dm_thin_device *td)
 {
 	bool r;
diff --git a/drivers/md/dm-thin-metadata.h b/drivers/md/dm-thin-metadata.h
index 9a36856..82ea384 100644
--- a/drivers/md/dm-thin-metadata.h
+++ b/drivers/md/dm-thin-metadata.h
@@ -9,16 +9,14 @@
 
 #include "persistent-data/dm-block-manager.h"
 #include "persistent-data/dm-space-map.h"
+#include "persistent-data/dm-space-map-metadata.h"
 
-#define THIN_METADATA_BLOCK_SIZE 4096
+#define THIN_METADATA_BLOCK_SIZE DM_SM_METADATA_BLOCK_SIZE
 
 /*
  * The metadata device is currently limited in size.
- *
- * We have one block of index, which can hold 255 index entries.  Each
- * index entry contains allocation info about 16k metadata blocks.
  */
-#define THIN_METADATA_MAX_SECTORS (255 * (1 << 14) * (THIN_METADATA_BLOCK_SIZE / (1 << SECTOR_SHIFT)))
+#define THIN_METADATA_MAX_SECTORS DM_SM_METADATA_MAX_SECTORS
 
 /*
  * A metadata device larger than 16GB triggers a warning.
@@ -161,6 +159,8 @@
  */
 bool dm_thin_changed_this_transaction(struct dm_thin_device *td);
 
+bool dm_pool_changed_this_transaction(struct dm_pool_metadata *pmd);
+
 bool dm_thin_aborted_changes(struct dm_thin_device *td);
 
 int dm_thin_get_highest_mapped_block(struct dm_thin_device *td,
diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c
index faaf944..7e84bac 100644
--- a/drivers/md/dm-thin.c
+++ b/drivers/md/dm-thin.c
@@ -1357,7 +1357,8 @@
 	bio_list_init(&pool->deferred_flush_bios);
 	spin_unlock_irqrestore(&pool->lock, flags);
 
-	if (bio_list_empty(&bios) && !need_commit_due_to_time(pool))
+	if (bio_list_empty(&bios) &&
+	    !(dm_pool_changed_this_transaction(pool->pmd) && need_commit_due_to_time(pool)))
 		return;
 
 	if (commit(pool)) {
@@ -1999,16 +2000,27 @@
 	dm_table_event(pool->ti->table);
 }
 
-static sector_t get_metadata_dev_size(struct block_device *bdev)
+static sector_t get_dev_size(struct block_device *bdev)
 {
-	sector_t metadata_dev_size = i_size_read(bdev->bd_inode) >> SECTOR_SHIFT;
+	return i_size_read(bdev->bd_inode) >> SECTOR_SHIFT;
+}
+
+static void warn_if_metadata_device_too_big(struct block_device *bdev)
+{
+	sector_t metadata_dev_size = get_dev_size(bdev);
 	char buffer[BDEVNAME_SIZE];
 
-	if (metadata_dev_size > THIN_METADATA_MAX_SECTORS_WARNING) {
+	if (metadata_dev_size > THIN_METADATA_MAX_SECTORS_WARNING)
 		DMWARN("Metadata device %s is larger than %u sectors: excess space will not be used.",
 		       bdevname(bdev, buffer), THIN_METADATA_MAX_SECTORS);
-		metadata_dev_size = THIN_METADATA_MAX_SECTORS_WARNING;
-	}
+}
+
+static sector_t get_metadata_dev_size(struct block_device *bdev)
+{
+	sector_t metadata_dev_size = get_dev_size(bdev);
+
+	if (metadata_dev_size > THIN_METADATA_MAX_SECTORS)
+		metadata_dev_size = THIN_METADATA_MAX_SECTORS;
 
 	return metadata_dev_size;
 }
@@ -2017,7 +2029,7 @@
 {
 	sector_t metadata_dev_size = get_metadata_dev_size(bdev);
 
-	sector_div(metadata_dev_size, THIN_METADATA_BLOCK_SIZE >> SECTOR_SHIFT);
+	sector_div(metadata_dev_size, THIN_METADATA_BLOCK_SIZE);
 
 	return metadata_dev_size;
 }
@@ -2095,12 +2107,7 @@
 		ti->error = "Error opening metadata block device";
 		goto out_unlock;
 	}
-
-	/*
-	 * Run for the side-effect of possibly issuing a warning if the
-	 * device is too big.
-	 */
-	(void) get_metadata_dev_size(metadata_dev->bdev);
+	warn_if_metadata_device_too_big(metadata_dev->bdev);
 
 	r = dm_get_device(ti, argv[1], FMODE_READ | FMODE_WRITE, &data_dev);
 	if (r) {
@@ -2287,6 +2294,7 @@
 		return -EINVAL;
 
 	} else if (metadata_dev_size > sb_metadata_dev_size) {
+		warn_if_metadata_device_too_big(pool->md_dev);
 		DMINFO("%s: growing the metadata device from %llu to %llu blocks",
 		       dm_device_name(pool->pool_md),
 		       sb_metadata_dev_size, metadata_dev_size);
@@ -2894,6 +2902,7 @@
 
 	if (get_pool_mode(tc->pool) == PM_FAIL) {
 		ti->error = "Couldn't open thin device, Pool is in fail mode";
+		r = -EINVAL;
 		goto bad_thin_open;
 	}
 
@@ -2905,7 +2914,7 @@
 
 	r = dm_set_target_max_io_len(ti, tc->pool->sectors_per_block);
 	if (r)
-		goto bad_thin_open;
+		goto bad_target_max_io_len;
 
 	ti->num_flush_bios = 1;
 	ti->flush_supported = true;
@@ -2926,6 +2935,8 @@
 
 	return 0;
 
+bad_target_max_io_len:
+	dm_pool_close_thin_device(tc->td);
 bad_thin_open:
 	__pool_dec(tc->pool);
 bad_pool_lookup:
diff --git a/drivers/md/persistent-data/dm-space-map-metadata.c b/drivers/md/persistent-data/dm-space-map-metadata.c
index 536782e..e9bdd46 100644
--- a/drivers/md/persistent-data/dm-space-map-metadata.c
+++ b/drivers/md/persistent-data/dm-space-map-metadata.c
@@ -680,6 +680,8 @@
 	if (r)
 		return r;
 
+	if (nr_blocks > DM_SM_METADATA_MAX_BLOCKS)
+		nr_blocks = DM_SM_METADATA_MAX_BLOCKS;
 	r = sm_ll_extend(&smm->ll, nr_blocks);
 	if (r)
 		return r;
diff --git a/drivers/md/persistent-data/dm-space-map-metadata.h b/drivers/md/persistent-data/dm-space-map-metadata.h
index 39bba08..64df923 100644
--- a/drivers/md/persistent-data/dm-space-map-metadata.h
+++ b/drivers/md/persistent-data/dm-space-map-metadata.h
@@ -9,6 +9,17 @@
 
 #include "dm-transaction-manager.h"
 
+#define DM_SM_METADATA_BLOCK_SIZE (4096 >> SECTOR_SHIFT)
+
+/*
+ * The metadata device is currently limited in size.
+ *
+ * We have one block of index, which can hold 255 index entries.  Each
+ * index entry contains allocation info about ~16k metadata blocks.
+ */
+#define DM_SM_METADATA_MAX_BLOCKS (255 * ((1 << 14) - 64))
+#define DM_SM_METADATA_MAX_SECTORS (DM_SM_METADATA_MAX_BLOCKS * DM_SM_METADATA_BLOCK_SIZE)
+
 /*
  * Unfortunately we have to use two-phase construction due to the cycle
  * between the tm and sm.
diff --git a/drivers/mfd/da9055-i2c.c b/drivers/mfd/da9055-i2c.c
index 13af7e5..8103e43 100644
--- a/drivers/mfd/da9055-i2c.c
+++ b/drivers/mfd/da9055-i2c.c
@@ -53,17 +53,25 @@
 	return 0;
 }
 
+/*
+ * DO NOT change the device Ids. The naming is intentionally specific as both
+ * the PMIC and CODEC parts of this chip are instantiated separately as I2C
+ * devices (both have configurable I2C addresses, and are to all intents and
+ * purposes separate). As a result there are specific DA9055 ids for PMIC
+ * and CODEC, which must be different to operate together.
+ */
 static struct i2c_device_id da9055_i2c_id[] = {
-	{"da9055", 0},
+	{"da9055-pmic", 0},
 	{ }
 };
+MODULE_DEVICE_TABLE(i2c, da9055_i2c_id);
 
 static struct i2c_driver da9055_i2c_driver = {
 	.probe = da9055_i2c_probe,
 	.remove = da9055_i2c_remove,
 	.id_table = da9055_i2c_id,
 	.driver = {
-		.name = "da9055",
+		.name = "da9055-pmic",
 		.owner = THIS_MODULE,
 	},
 };
diff --git a/drivers/mfd/max14577.c b/drivers/mfd/max14577.c
index ac514fb..71aa14a 100644
--- a/drivers/mfd/max14577.c
+++ b/drivers/mfd/max14577.c
@@ -173,6 +173,7 @@
 };
 MODULE_DEVICE_TABLE(i2c, max14577_i2c_id);
 
+#ifdef CONFIG_PM_SLEEP
 static int max14577_suspend(struct device *dev)
 {
 	struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
@@ -208,6 +209,7 @@
 
 	return 0;
 }
+#endif /* CONFIG_PM_SLEEP */
 
 static struct of_device_id max14577_dt_match[] = {
 	{ .compatible = "maxim,max14577", },
diff --git a/drivers/mfd/max8997.c b/drivers/mfd/max8997.c
index be88a3b..5adede0 100644
--- a/drivers/mfd/max8997.c
+++ b/drivers/mfd/max8997.c
@@ -164,15 +164,15 @@
 	return pd;
 }
 
-static inline int max8997_i2c_get_driver_data(struct i2c_client *i2c,
+static inline unsigned long max8997_i2c_get_driver_data(struct i2c_client *i2c,
 						const struct i2c_device_id *id)
 {
 	if (IS_ENABLED(CONFIG_OF) && i2c->dev.of_node) {
 		const struct of_device_id *match;
 		match = of_match_node(max8997_pmic_dt_match, i2c->dev.of_node);
-		return (int)match->data;
+		return (unsigned long)match->data;
 	}
-	return (int)id->driver_data;
+	return id->driver_data;
 }
 
 static int max8997_i2c_probe(struct i2c_client *i2c,
diff --git a/drivers/mfd/max8998.c b/drivers/mfd/max8998.c
index 612ca40..5d5e186 100644
--- a/drivers/mfd/max8998.c
+++ b/drivers/mfd/max8998.c
@@ -169,16 +169,16 @@
 	return pd;
 }
 
-static inline int max8998_i2c_get_driver_data(struct i2c_client *i2c,
+static inline unsigned long max8998_i2c_get_driver_data(struct i2c_client *i2c,
 						const struct i2c_device_id *id)
 {
 	if (IS_ENABLED(CONFIG_OF) && i2c->dev.of_node) {
 		const struct of_device_id *match;
 		match = of_match_node(max8998_dt_match, i2c->dev.of_node);
-		return (int)(long)match->data;
+		return (unsigned long)match->data;
 	}
 
-	return (int)id->driver_data;
+	return id->driver_data;
 }
 
 static int max8998_i2c_probe(struct i2c_client *i2c,
diff --git a/drivers/mfd/sec-core.c b/drivers/mfd/sec-core.c
index a139798..714e213 100644
--- a/drivers/mfd/sec-core.c
+++ b/drivers/mfd/sec-core.c
@@ -315,6 +315,7 @@
 	return 0;
 }
 
+#ifdef CONFIG_PM_SLEEP
 static int sec_pmic_suspend(struct device *dev)
 {
 	struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
@@ -349,6 +350,7 @@
 
 	return 0;
 }
+#endif /* CONFIG_PM_SLEEP */
 
 static SIMPLE_DEV_PM_OPS(sec_pmic_pm_ops, sec_pmic_suspend, sec_pmic_resume);
 
diff --git a/drivers/mfd/tps65217.c b/drivers/mfd/tps65217.c
index 966cf65..3cc4c70 100644
--- a/drivers/mfd/tps65217.c
+++ b/drivers/mfd/tps65217.c
@@ -158,7 +158,7 @@
 {
 	struct tps65217 *tps;
 	unsigned int version;
-	unsigned int chip_id = ids->driver_data;
+	unsigned long chip_id = ids->driver_data;
 	const struct of_device_id *match;
 	bool status_off = false;
 	int ret;
@@ -170,7 +170,7 @@
 				"Failed to find matching dt id\n");
 			return -EINVAL;
 		}
-		chip_id = (unsigned int)(unsigned long)match->data;
+		chip_id = (unsigned long)match->data;
 		status_off = of_property_read_bool(client->dev.of_node,
 					"ti,pmic-shutdown-controller");
 	}
diff --git a/drivers/mfd/wm8994-core.c b/drivers/mfd/wm8994-core.c
index ba04f1b..e6fab94 100644
--- a/drivers/mfd/wm8994-core.c
+++ b/drivers/mfd/wm8994-core.c
@@ -636,7 +636,7 @@
 	if (i2c->dev.of_node) {
 		of_id = of_match_device(wm8994_of_match, &i2c->dev);
 		if (of_id)
-			wm8994->type = (int)of_id->data;
+			wm8994->type = (enum wm8994_type)of_id->data;
 	} else {
 		wm8994->type = id->driver_data;
 	}
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 6cb388e..3816b59 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -526,4 +526,5 @@
 source "drivers/misc/vmw_vmci/Kconfig"
 source "drivers/misc/mic/Kconfig"
 source "drivers/misc/genwqe/Kconfig"
+source "drivers/misc/echo/Kconfig"
 endmenu
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 99b9424..7eb4b69 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -54,3 +54,4 @@
 obj-$(CONFIG_SRAM)		+= sram.o
 obj-y				+= mic/
 obj-$(CONFIG_GENWQE)		+= genwqe/
+obj-$(CONFIG_ECHO)		+= echo/
diff --git a/drivers/staging/echo/Kconfig b/drivers/misc/echo/Kconfig
similarity index 100%
rename from drivers/staging/echo/Kconfig
rename to drivers/misc/echo/Kconfig
diff --git a/drivers/staging/echo/Makefile b/drivers/misc/echo/Makefile
similarity index 100%
rename from drivers/staging/echo/Makefile
rename to drivers/misc/echo/Makefile
diff --git a/drivers/staging/echo/echo.c b/drivers/misc/echo/echo.c
similarity index 100%
rename from drivers/staging/echo/echo.c
rename to drivers/misc/echo/echo.c
diff --git a/drivers/staging/echo/echo.h b/drivers/misc/echo/echo.h
similarity index 100%
rename from drivers/staging/echo/echo.h
rename to drivers/misc/echo/echo.h
diff --git a/drivers/staging/echo/fir.h b/drivers/misc/echo/fir.h
similarity index 100%
rename from drivers/staging/echo/fir.h
rename to drivers/misc/echo/fir.h
diff --git a/drivers/staging/echo/oslec.h b/drivers/misc/echo/oslec.h
similarity index 100%
rename from drivers/staging/echo/oslec.h
rename to drivers/misc/echo/oslec.h
diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c
index 9b809cf..89a5579 100644
--- a/drivers/misc/mei/client.c
+++ b/drivers/misc/mei/client.c
@@ -666,7 +666,6 @@
 		goto err;
 
 	cb->fop_type = MEI_FOP_READ;
-	cl->read_cb = cb;
 	if (dev->hbuf_is_ready) {
 		dev->hbuf_is_ready = false;
 		if (mei_hbm_cl_flow_control_req(dev, cl)) {
@@ -678,6 +677,9 @@
 	} else {
 		list_add_tail(&cb->list, &dev->ctrl_wr_list.list);
 	}
+
+	cl->read_cb = cb;
+
 	return rets;
 err:
 	mei_io_cb_free(cb);
diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c
index 357bbc5..3e049c1 100644
--- a/drivers/mmc/card/queue.c
+++ b/drivers/mmc/card/queue.c
@@ -197,7 +197,7 @@
 	struct mmc_queue_req *mqrq_prev = &mq->mqrq[1];
 
 	if (mmc_dev(host)->dma_mask && *mmc_dev(host)->dma_mask)
-		limit = dma_max_pfn(mmc_dev(host)) << PAGE_SHIFT;
+		limit = (u64)dma_max_pfn(mmc_dev(host)) << PAGE_SHIFT;
 
 	mq->card = card;
 	mq->queue = blk_init_queue(mmc_request_fn, lock);
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index 59eba5d..9715a7b 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -1584,7 +1584,7 @@
 			}
 
 			if (mtd->ecc_stats.failed - ecc_failures) {
-				if (retry_mode + 1 <= chip->read_retries) {
+				if (retry_mode + 1 < chip->read_retries) {
 					retry_mode++;
 					ret = nand_setup_read_retry(mtd,
 							retry_mode);
diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
index ef4190a..bf642ce 100644
--- a/drivers/mtd/nand/omap2.c
+++ b/drivers/mtd/nand/omap2.c
@@ -1633,6 +1633,7 @@
 	int				i;
 	dma_cap_mask_t			mask;
 	unsigned			sig;
+	unsigned			oob_index;
 	struct resource			*res;
 	struct mtd_part_parser_data	ppdata = {};
 
@@ -1826,11 +1827,14 @@
 							(mtd->writesize /
 							nand_chip->ecc.size);
 		if (nand_chip->options & NAND_BUSWIDTH_16)
-			ecclayout->eccpos[0]	= BADBLOCK_MARKER_LENGTH;
+			oob_index		= BADBLOCK_MARKER_LENGTH;
 		else
-			ecclayout->eccpos[0]	= 1;
-		ecclayout->oobfree->offset	= ecclayout->eccpos[0] +
-							ecclayout->eccbytes;
+			oob_index		= 1;
+		for (i = 0; i < ecclayout->eccbytes; i++, oob_index++)
+			ecclayout->eccpos[i]	= oob_index;
+		/* no reserved-marker in ecclayout for this ecc-scheme */
+		ecclayout->oobfree->offset	=
+				ecclayout->eccpos[ecclayout->eccbytes - 1] + 1;
 		break;
 
 	case OMAP_ECC_BCH4_CODE_HW_DETECTION_SW:
@@ -1847,9 +1851,15 @@
 		ecclayout->eccbytes		= nand_chip->ecc.bytes *
 							(mtd->writesize /
 							nand_chip->ecc.size);
-		ecclayout->eccpos[0]		= BADBLOCK_MARKER_LENGTH;
-		ecclayout->oobfree->offset	= ecclayout->eccpos[0] +
-							ecclayout->eccbytes;
+		oob_index			= BADBLOCK_MARKER_LENGTH;
+		for (i = 0; i < ecclayout->eccbytes; i++, oob_index++) {
+			ecclayout->eccpos[i] = oob_index;
+			if (((i + 1) % nand_chip->ecc.bytes) == 0)
+				oob_index++;
+		}
+		/* include reserved-marker in ecclayout->oobfree calculation */
+		ecclayout->oobfree->offset	= 1 +
+				ecclayout->eccpos[ecclayout->eccbytes - 1] + 1;
 		/* software bch library is used for locating errors */
 		nand_chip->ecc.priv		= nand_bch_init(mtd,
 							nand_chip->ecc.size,
@@ -1883,9 +1893,12 @@
 		ecclayout->eccbytes		= nand_chip->ecc.bytes *
 							(mtd->writesize /
 							nand_chip->ecc.size);
-		ecclayout->eccpos[0]		= BADBLOCK_MARKER_LENGTH;
-		ecclayout->oobfree->offset	= ecclayout->eccpos[0] +
-							ecclayout->eccbytes;
+		oob_index			= BADBLOCK_MARKER_LENGTH;
+		for (i = 0; i < ecclayout->eccbytes; i++, oob_index++)
+			ecclayout->eccpos[i]	= oob_index;
+		/* reserved marker already included in ecclayout->eccbytes */
+		ecclayout->oobfree->offset	=
+				ecclayout->eccpos[ecclayout->eccbytes - 1] + 1;
 		/* This ECC scheme requires ELM H/W block */
 		if (is_elm_present(info, pdata->elm_of_node, BCH4_ECC) < 0) {
 			pr_err("nand: error: could not initialize ELM\n");
@@ -1913,9 +1926,15 @@
 		ecclayout->eccbytes		= nand_chip->ecc.bytes *
 							(mtd->writesize /
 							nand_chip->ecc.size);
-		ecclayout->eccpos[0]		= BADBLOCK_MARKER_LENGTH;
-		ecclayout->oobfree->offset	= ecclayout->eccpos[0] +
-							ecclayout->eccbytes;
+		oob_index			= BADBLOCK_MARKER_LENGTH;
+		for (i = 0; i < ecclayout->eccbytes; i++, oob_index++) {
+			ecclayout->eccpos[i] = oob_index;
+			if (((i + 1) % nand_chip->ecc.bytes) == 0)
+				oob_index++;
+		}
+		/* include reserved-marker in ecclayout->oobfree calculation */
+		ecclayout->oobfree->offset	= 1 +
+				ecclayout->eccpos[ecclayout->eccbytes - 1] + 1;
 		/* software bch library is used for locating errors */
 		nand_chip->ecc.priv		= nand_bch_init(mtd,
 							nand_chip->ecc.size,
@@ -1956,9 +1975,12 @@
 		ecclayout->eccbytes		= nand_chip->ecc.bytes *
 							(mtd->writesize /
 							nand_chip->ecc.size);
-		ecclayout->eccpos[0]		= BADBLOCK_MARKER_LENGTH;
-		ecclayout->oobfree->offset	= ecclayout->eccpos[0] +
-							ecclayout->eccbytes;
+		oob_index			= BADBLOCK_MARKER_LENGTH;
+		for (i = 0; i < ecclayout->eccbytes; i++, oob_index++)
+			ecclayout->eccpos[i]	= oob_index;
+		/* reserved marker already included in ecclayout->eccbytes */
+		ecclayout->oobfree->offset	=
+				ecclayout->eccpos[ecclayout->eccbytes - 1] + 1;
 		break;
 #else
 		pr_err("nand: error: CONFIG_MTD_NAND_OMAP_BCH not enabled\n");
@@ -1972,11 +1994,8 @@
 		goto return_error;
 	}
 
-	/* populate remaining ECC layout data */
-	ecclayout->oobfree->length = mtd->oobsize - (BADBLOCK_MARKER_LENGTH +
-							ecclayout->eccbytes);
-	for (i = 1; i < ecclayout->eccbytes; i++)
-		ecclayout->eccpos[i] = ecclayout->eccpos[0] + i;
+	/* all OOB bytes from oobfree->offset till end off OOB are free */
+	ecclayout->oobfree->length = mtd->oobsize - ecclayout->oobfree->offset;
 	/* check if NAND device's OOB is enough to store ECC signatures */
 	if (mtd->oobsize < (ecclayout->eccbytes + BADBLOCK_MARKER_LENGTH)) {
 		pr_err("not enough OOB bytes required = %d, available=%d\n",
diff --git a/drivers/mtd/ubi/fastmap.c b/drivers/mtd/ubi/fastmap.c
index ead8613..c5dad65 100644
--- a/drivers/mtd/ubi/fastmap.c
+++ b/drivers/mtd/ubi/fastmap.c
@@ -463,8 +463,8 @@
 				}
 			}
 			if (found_orphan) {
-				kmem_cache_free(ai->aeb_slab_cache, tmp_aeb);
 				list_del(&tmp_aeb->u.list);
+				kmem_cache_free(ai->aeb_slab_cache, tmp_aeb);
 			}
 
 			new_aeb = kmem_cache_alloc(ai->aeb_slab_cache,
@@ -846,16 +846,16 @@
 	ret = UBI_BAD_FASTMAP;
 fail:
 	list_for_each_entry_safe(tmp_aeb, _tmp_aeb, &used, u.list) {
-		kmem_cache_free(ai->aeb_slab_cache, tmp_aeb);
 		list_del(&tmp_aeb->u.list);
+		kmem_cache_free(ai->aeb_slab_cache, tmp_aeb);
 	}
 	list_for_each_entry_safe(tmp_aeb, _tmp_aeb, &eba_orphans, u.list) {
-		kmem_cache_free(ai->aeb_slab_cache, tmp_aeb);
 		list_del(&tmp_aeb->u.list);
+		kmem_cache_free(ai->aeb_slab_cache, tmp_aeb);
 	}
 	list_for_each_entry_safe(tmp_aeb, _tmp_aeb, &free, u.list) {
-		kmem_cache_free(ai->aeb_slab_cache, tmp_aeb);
 		list_del(&tmp_aeb->u.list);
+		kmem_cache_free(ai->aeb_slab_cache, tmp_aeb);
 	}
 
 	return ret;
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index f342278..494b888 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -139,7 +139,7 @@
 	  This adds a specialized tap character device driver that is based
 	  on the MAC-VLAN network interface, called macvtap. A macvtap device
 	  can be added in the same way as a macvlan device, using 'type
-	  macvlan', and then be accessed through the tap user space interface.
+	  macvtap', and then be accessed through the tap user space interface.
 
 	  To compile this driver as a module, choose M here: the module
 	  will be called macvtap.
diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c
index cce1f1b..6d20fbd 100644
--- a/drivers/net/bonding/bond_3ad.c
+++ b/drivers/net/bonding/bond_3ad.c
@@ -1796,8 +1796,6 @@
 	BOND_AD_INFO(bond).agg_select_timer = timeout;
 }
 
-static u16 aggregator_identifier;
-
 /**
  * bond_3ad_initialize - initialize a bond's 802.3ad parameters and structures
  * @bond: bonding struct to work on
@@ -1811,7 +1809,7 @@
 	if (!MAC_ADDRESS_EQUAL(&(BOND_AD_INFO(bond).system.sys_mac_addr),
 				bond->dev->dev_addr)) {
 
-		aggregator_identifier = 0;
+		BOND_AD_INFO(bond).aggregator_identifier = 0;
 
 		BOND_AD_INFO(bond).system.sys_priority = 0xFFFF;
 		BOND_AD_INFO(bond).system.sys_mac_addr = *((struct mac_addr *)bond->dev->dev_addr);
@@ -1880,7 +1878,7 @@
 		ad_initialize_agg(aggregator);
 
 		aggregator->aggregator_mac_address = *((struct mac_addr *)bond->dev->dev_addr);
-		aggregator->aggregator_identifier = (++aggregator_identifier);
+		aggregator->aggregator_identifier = ++BOND_AD_INFO(bond).aggregator_identifier;
 		aggregator->slave = slave;
 		aggregator->is_active = 0;
 		aggregator->num_of_ports = 0;
diff --git a/drivers/net/bonding/bond_3ad.h b/drivers/net/bonding/bond_3ad.h
index 13dc9d3..f4dd959 100644
--- a/drivers/net/bonding/bond_3ad.h
+++ b/drivers/net/bonding/bond_3ad.h
@@ -253,6 +253,7 @@
 struct ad_bond_info {
 	struct ad_system system;	    /* 802.3ad system structure */
 	u32 agg_select_timer;	    // Timer to select aggregator after all adapter's hand shakes
+	u16 aggregator_identifier;
 };
 
 struct ad_slave_info {
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 71ba18e..1c6104d 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -1543,9 +1543,11 @@
 	bond_set_carrier(bond);
 
 	if (USES_PRIMARY(bond->params.mode)) {
+		block_netpoll_tx();
 		write_lock_bh(&bond->curr_slave_lock);
 		bond_select_active_slave(bond);
 		write_unlock_bh(&bond->curr_slave_lock);
+		unblock_netpoll_tx();
 	}
 
 	pr_info("%s: enslaving %s as a%s interface with a%s link.\n",
@@ -1571,10 +1573,12 @@
 	if (bond->primary_slave == new_slave)
 		bond->primary_slave = NULL;
 	if (bond->curr_active_slave == new_slave) {
+		block_netpoll_tx();
 		write_lock_bh(&bond->curr_slave_lock);
 		bond_change_active_slave(bond, NULL);
 		bond_select_active_slave(bond);
 		write_unlock_bh(&bond->curr_slave_lock);
+		unblock_netpoll_tx();
 	}
 	slave_disable_netpoll(new_slave);
 
@@ -2864,9 +2868,12 @@
 		pr_info("%s: Primary slave changed to %s, reselecting active slave.\n",
 			bond->dev->name, bond->primary_slave ? slave_dev->name :
 							       "none");
+
+		block_netpoll_tx();
 		write_lock_bh(&bond->curr_slave_lock);
 		bond_select_active_slave(bond);
 		write_unlock_bh(&bond->curr_slave_lock);
+		unblock_netpoll_tx();
 		break;
 	case NETDEV_FEAT_CHANGE:
 		bond_compute_features(bond);
@@ -3700,7 +3707,7 @@
 
 
 static u16 bond_select_queue(struct net_device *dev, struct sk_buff *skb,
-			     void *accel_priv)
+			     void *accel_priv, select_queue_fallback_t fallback)
 {
 	/*
 	 * This helper function exists to help dev_pick_tx get the correct
diff --git a/drivers/net/bonding/bond_options.c b/drivers/net/bonding/bond_options.c
index 11cb943..c378784 100644
--- a/drivers/net/bonding/bond_options.c
+++ b/drivers/net/bonding/bond_options.c
@@ -14,7 +14,7 @@
 #include <linux/errno.h>
 #include <linux/if.h>
 #include <linux/netdevice.h>
-#include <linux/rwlock.h>
+#include <linux/spinlock.h>
 #include <linux/rcupdate.h>
 #include <linux/ctype.h>
 #include <linux/inet.h>
diff --git a/drivers/net/can/usb/kvaser_usb.c b/drivers/net/can/usb/kvaser_usb.c
index 6c859bb..e77d110 100644
--- a/drivers/net/can/usb/kvaser_usb.c
+++ b/drivers/net/can/usb/kvaser_usb.c
@@ -473,6 +473,8 @@
 		return err;
 
 	dev->nchannels = msg.u.cardinfo.nchannels;
+	if (dev->nchannels > MAX_NET_DEVICES)
+		return -EINVAL;
 
 	return 0;
 }
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
index 9d7419e..66c0df7 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
@@ -1873,7 +1873,7 @@
 }
 
 u16 bnx2x_select_queue(struct net_device *dev, struct sk_buff *skb,
-		       void *accel_priv)
+		       void *accel_priv, select_queue_fallback_t fallback)
 {
 	struct bnx2x *bp = netdev_priv(dev);
 
@@ -1895,7 +1895,7 @@
 	}
 
 	/* select a non-FCoE queue */
-	return __netdev_pick_tx(dev, skb) % BNX2X_NUM_ETH_QUEUES(bp);
+	return fallback(dev, skb) % BNX2X_NUM_ETH_QUEUES(bp);
 }
 
 void bnx2x_set_num_queues(struct bnx2x *bp)
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h
index bfc58d4..a89a40f 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h
@@ -496,7 +496,7 @@
 
 /* select_queue callback */
 u16 bnx2x_select_queue(struct net_device *dev, struct sk_buff *skb,
-		       void *accel_priv);
+		       void *accel_priv, select_queue_fallback_t fallback);
 
 static inline void bnx2x_update_rx_prod(struct bnx2x *bp,
 					struct bnx2x_fastpath *fp,
diff --git a/drivers/net/ethernet/dec/tulip/tulip_core.c b/drivers/net/ethernet/dec/tulip/tulip_core.c
index add05f1..1642de7 100644
--- a/drivers/net/ethernet/dec/tulip/tulip_core.c
+++ b/drivers/net/ethernet/dec/tulip/tulip_core.c
@@ -1939,6 +1939,7 @@
 	pci_iounmap(pdev, tp->base_addr);
 	free_netdev (dev);
 	pci_release_regions (pdev);
+	pci_disable_device(pdev);
 
 	/* pci_power_off (pdev, -1); */
 }
diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index d4782b4..903362a 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -1778,8 +1778,6 @@
 	struct fec_enet_private *fep = netdev_priv(ndev);
 	int ret;
 
-	napi_enable(&fep->napi);
-
 	/* I should reset the ring buffers here, but I don't yet know
 	 * a simple way to do that.
 	 */
@@ -1794,6 +1792,8 @@
 		fec_enet_free_buffers(ndev);
 		return ret;
 	}
+
+	napi_enable(&fep->napi);
 	phy_start(fep->phy_dev);
 	netif_start_queue(ndev);
 	fep->opened = 1;
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index 6d4ada7..18076c4 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -6881,7 +6881,7 @@
 }
 
 static u16 ixgbe_select_queue(struct net_device *dev, struct sk_buff *skb,
-			      void *accel_priv)
+			      void *accel_priv, select_queue_fallback_t fallback)
 {
 	struct ixgbe_fwd_adapter *fwd_adapter = accel_priv;
 #ifdef IXGBE_FCOE
@@ -6907,7 +6907,7 @@
 		if (adapter->flags & IXGBE_FLAG_FCOE_ENABLED)
 			break;
 	default:
-		return __netdev_pick_tx(dev, skb);
+		return fallback(dev, skb);
 	}
 
 	f = &adapter->ring_feature[RING_F_FCOE];
@@ -6920,7 +6920,7 @@
 
 	return txq + f->offset;
 #else
-	return __netdev_pick_tx(dev, skb);
+	return fallback(dev, skb);
 #endif
 }
 
diff --git a/drivers/net/ethernet/lantiq_etop.c b/drivers/net/ethernet/lantiq_etop.c
index 8f9266c..fd4b6ae 100644
--- a/drivers/net/ethernet/lantiq_etop.c
+++ b/drivers/net/ethernet/lantiq_etop.c
@@ -619,7 +619,7 @@
 
 static u16
 ltq_etop_select_queue(struct net_device *dev, struct sk_buff *skb,
-		      void *accel_priv)
+		      void *accel_priv, select_queue_fallback_t fallback)
 {
 	/* we are currently only using the first queue */
 	return 0;
diff --git a/drivers/net/ethernet/marvell/Kconfig b/drivers/net/ethernet/marvell/Kconfig
index 6300fd2..68e6a66 100644
--- a/drivers/net/ethernet/marvell/Kconfig
+++ b/drivers/net/ethernet/marvell/Kconfig
@@ -43,12 +43,12 @@
 	  This driver is used by the MV643XX_ETH and MVNETA drivers.
 
 config MVNETA
-	tristate "Marvell Armada 370/XP network interface support"
-	depends on MACH_ARMADA_370_XP
+	tristate "Marvell Armada 370/38x/XP network interface support"
+	depends on PLAT_ORION
 	select MVMDIO
 	---help---
 	  This driver supports the network interface units in the
-	  Marvell ARMADA XP and ARMADA 370 SoC family.
+	  Marvell ARMADA XP, ARMADA 370 and ARMADA 38x SoC family.
 
 	  Note that this driver is distinct from the mv643xx_eth
 	  driver, which should be used for the older Marvell SoCs
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_tx.c b/drivers/net/ethernet/mellanox/mlx4/en_tx.c
index 8e8a7eb..1345703 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_tx.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_tx.c
@@ -629,7 +629,7 @@
 }
 
 u16 mlx4_en_select_queue(struct net_device *dev, struct sk_buff *skb,
-			 void *accel_priv)
+			 void *accel_priv, select_queue_fallback_t fallback)
 {
 	struct mlx4_en_priv *priv = netdev_priv(dev);
 	u16 rings_p_up = priv->num_tx_rings_p_up;
@@ -641,7 +641,7 @@
 	if (vlan_tx_tag_present(skb))
 		up = vlan_tx_tag_get(skb) >> VLAN_PRIO_SHIFT;
 
-	return __netdev_pick_tx(dev, skb) % rings_p_up + up * rings_p_up;
+	return fallback(dev, skb) % rings_p_up + up * rings_p_up;
 }
 
 static void mlx4_bf_copy(void __iomem *dst, unsigned long *src, unsigned bytecnt)
diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
index 3af04c3..9ca223b 100644
--- a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
+++ b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
@@ -723,7 +723,7 @@
 
 void mlx4_en_tx_irq(struct mlx4_cq *mcq);
 u16 mlx4_en_select_queue(struct net_device *dev, struct sk_buff *skb,
-			 void *accel_priv);
+			 void *accel_priv, select_queue_fallback_t fallback);
 netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev);
 
 int mlx4_en_create_tx_ring(struct mlx4_en_priv *priv,
diff --git a/drivers/net/ethernet/stmicro/stmmac/Kconfig b/drivers/net/ethernet/stmicro/stmmac/Kconfig
index e2f202e..f2d7c70 100644
--- a/drivers/net/ethernet/stmicro/stmmac/Kconfig
+++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig
@@ -37,6 +37,17 @@
 	  stmmac device driver. This driver is used for A20/A31
 	  GMAC 	  ethernet controller.
 
+config DWMAC_STI
+	bool "STi GMAC support"
+	depends on STMMAC_PLATFORM && ARCH_STI
+	default y
+	---help---
+	  Support for ethernet controller on STi SOCs.
+
+	  This selects STi SoC glue layer support for the stmmac
+	  device driver. This driver is used on for the STi series
+	  SOCs GMAC ethernet controller.
+
 config STMMAC_PCI
 	bool "STMMAC PCI bus support"
 	depends on STMMAC_ETH && PCI
diff --git a/drivers/net/ethernet/stmicro/stmmac/Makefile b/drivers/net/ethernet/stmicro/stmmac/Makefile
index ecadece..dcef287 100644
--- a/drivers/net/ethernet/stmicro/stmmac/Makefile
+++ b/drivers/net/ethernet/stmicro/stmmac/Makefile
@@ -2,6 +2,7 @@
 stmmac-$(CONFIG_STMMAC_PLATFORM) += stmmac_platform.o
 stmmac-$(CONFIG_STMMAC_PCI) += stmmac_pci.o
 stmmac-$(CONFIG_DWMAC_SUNXI) += dwmac-sunxi.o
+stmmac-$(CONFIG_DWMAC_STI) += dwmac-sti.o
 stmmac-objs:= stmmac_main.o stmmac_ethtool.o stmmac_mdio.o ring_mode.o	\
 	      chain_mode.o dwmac_lib.o dwmac1000_core.o  dwmac1000_dma.o \
 	      dwmac100_core.o dwmac100_dma.o enh_desc.o  norm_desc.o \
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c
new file mode 100644
index 0000000..552bbc1
--- /dev/null
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c
@@ -0,0 +1,330 @@
+/**
+ * dwmac-sti.c - STMicroelectronics DWMAC Specific Glue layer
+ *
+ * Copyright (C) 2003-2014 STMicroelectronics (R&D) Limited
+ * Author: Srinivas Kandagatla <srinivas.kandagatla@st.com>
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/stmmac.h>
+#include <linux/phy.h>
+#include <linux/mfd/syscon.h>
+#include <linux/regmap.h>
+#include <linux/clk.h>
+#include <linux/of.h>
+#include <linux/of_net.h>
+
+/**
+ *			STi GMAC glue logic.
+ *			--------------------
+ *
+ *		 _
+ *		|  \
+ *	--------|0  \ ETH_SEL_INTERNAL_NOTEXT_PHYCLK
+ * phyclk	|    |___________________________________________
+ *		|    |	|			(phyclk-in)
+ *	--------|1  /	|
+ * int-clk	|_ /	|
+ *			|	 _
+ *			|	|  \
+ *			|_______|1  \ ETH_SEL_TX_RETIME_CLK
+ *				|    |___________________________
+ *				|    |		(tx-retime-clk)
+ *			 _______|0  /
+ *			|	|_ /
+ *		 _	|
+ *		|  \	|
+ *	--------|0  \	|
+ * clk_125	|    |__|
+ *		|    |	ETH_SEL_TXCLK_NOT_CLK125
+ *	--------|1  /
+ * txclk	|_ /
+ *
+ *
+ * ETH_SEL_INTERNAL_NOTEXT_PHYCLK is valid only for RMII where PHY can
+ * generate 50MHz clock or MAC can generate it.
+ * This bit is configured by "st,ext-phyclk" property.
+ *
+ * ETH_SEL_TXCLK_NOT_CLK125 is only valid for gigabit modes, where the 125Mhz
+ * clock either comes from clk-125 pin or txclk pin. This configuration is
+ * totally driven by the board wiring. This bit is configured by
+ * "st,tx-retime-src" property.
+ *
+ * TXCLK configuration is different for different phy interface modes
+ * and changes according to link speed in modes like RGMII.
+ *
+ * Below table summarizes the clock requirement and clock sources for
+ * supported phy interface modes with link speeds.
+ * ________________________________________________
+ *|  PHY_MODE	| 1000 Mbit Link | 100 Mbit Link   |
+ * ------------------------------------------------
+ *|	MII	|	n/a	 |	25Mhz	   |
+ *|		|		 |	txclk	   |
+ * ------------------------------------------------
+ *|	GMII	|     125Mhz	 |	25Mhz	   |
+ *|		|  clk-125/txclk |	txclk	   |
+ * ------------------------------------------------
+ *|	RGMII	|     125Mhz	 |	25Mhz	   |
+ *|		|  clk-125/txclk |	clkgen     |
+ * ------------------------------------------------
+ *|	RMII	|	n/a	 |	25Mhz	   |
+ *|		|		 |clkgen/phyclk-in |
+ * ------------------------------------------------
+ *
+ * TX lines are always retimed with a clk, which can vary depending
+ * on the board configuration. Below is the table of these bits
+ * in eth configuration register depending on source of retime clk.
+ *
+ *---------------------------------------------------------------
+ * src	 | tx_rt_clk	| int_not_ext_phyclk	| txclk_n_clk125|
+ *---------------------------------------------------------------
+ * txclk |	0	|	n/a		|	1	|
+ *---------------------------------------------------------------
+ * ck_125|	0	|	n/a		|	0	|
+ *---------------------------------------------------------------
+ * phyclk|	1	|	0		|	n/a	|
+ *---------------------------------------------------------------
+ * clkgen|	1	|	1		|	n/a	|
+ *---------------------------------------------------------------
+ */
+
+ /* Register definition */
+
+ /* 3 bits [8:6]
+  *  [6:6]      ETH_SEL_TXCLK_NOT_CLK125
+  *  [7:7]      ETH_SEL_INTERNAL_NOTEXT_PHYCLK
+  *  [8:8]      ETH_SEL_TX_RETIME_CLK
+  *
+  */
+
+#define TX_RETIME_SRC_MASK		GENMASK(8, 6)
+#define ETH_SEL_TX_RETIME_CLK		BIT(8)
+#define ETH_SEL_INTERNAL_NOTEXT_PHYCLK	BIT(7)
+#define ETH_SEL_TXCLK_NOT_CLK125	BIT(6)
+
+#define ENMII_MASK			GENMASK(5, 5)
+#define ENMII				BIT(5)
+
+/**
+ * 3 bits [4:2]
+ *	000-GMII/MII
+ *	001-RGMII
+ *	010-SGMII
+ *	100-RMII
+*/
+#define MII_PHY_SEL_MASK		GENMASK(4, 2)
+#define ETH_PHY_SEL_RMII		BIT(4)
+#define ETH_PHY_SEL_SGMII		BIT(3)
+#define ETH_PHY_SEL_RGMII		BIT(2)
+#define ETH_PHY_SEL_GMII		0x0
+#define ETH_PHY_SEL_MII			0x0
+
+#define IS_PHY_IF_MODE_RGMII(iface)	(iface == PHY_INTERFACE_MODE_RGMII || \
+			iface == PHY_INTERFACE_MODE_RGMII_ID || \
+			iface == PHY_INTERFACE_MODE_RGMII_RXID || \
+			iface == PHY_INTERFACE_MODE_RGMII_TXID)
+
+#define IS_PHY_IF_MODE_GBIT(iface)	(IS_PHY_IF_MODE_RGMII(iface) || \
+			iface == PHY_INTERFACE_MODE_GMII)
+
+struct sti_dwmac {
+	int interface;
+	bool ext_phyclk;
+	bool is_tx_retime_src_clk_125;
+	struct clk *clk;
+	int reg;
+	struct device *dev;
+	struct regmap *regmap;
+};
+
+static u32 phy_intf_sels[] = {
+	[PHY_INTERFACE_MODE_MII] = ETH_PHY_SEL_MII,
+	[PHY_INTERFACE_MODE_GMII] = ETH_PHY_SEL_GMII,
+	[PHY_INTERFACE_MODE_RGMII] = ETH_PHY_SEL_RGMII,
+	[PHY_INTERFACE_MODE_RGMII_ID] = ETH_PHY_SEL_RGMII,
+	[PHY_INTERFACE_MODE_SGMII] = ETH_PHY_SEL_SGMII,
+	[PHY_INTERFACE_MODE_RMII] = ETH_PHY_SEL_RMII,
+};
+
+enum {
+	TX_RETIME_SRC_NA = 0,
+	TX_RETIME_SRC_TXCLK = 1,
+	TX_RETIME_SRC_CLK_125,
+	TX_RETIME_SRC_PHYCLK,
+	TX_RETIME_SRC_CLKGEN,
+};
+
+static const char *const tx_retime_srcs[] = {
+	[TX_RETIME_SRC_NA] = "",
+	[TX_RETIME_SRC_TXCLK] = "txclk",
+	[TX_RETIME_SRC_CLK_125] = "clk_125",
+	[TX_RETIME_SRC_PHYCLK] = "phyclk",
+	[TX_RETIME_SRC_CLKGEN] = "clkgen",
+};
+
+static u32 tx_retime_val[] = {
+	[TX_RETIME_SRC_TXCLK] = ETH_SEL_TXCLK_NOT_CLK125,
+	[TX_RETIME_SRC_CLK_125] = 0x0,
+	[TX_RETIME_SRC_PHYCLK] = ETH_SEL_TX_RETIME_CLK,
+	[TX_RETIME_SRC_CLKGEN] = ETH_SEL_TX_RETIME_CLK |
+	    ETH_SEL_INTERNAL_NOTEXT_PHYCLK,
+};
+
+static void setup_retime_src(struct sti_dwmac *dwmac, u32 spd)
+{
+	u32 src = 0, freq = 0;
+
+	if (spd == SPEED_100) {
+		if (dwmac->interface == PHY_INTERFACE_MODE_MII ||
+		    dwmac->interface == PHY_INTERFACE_MODE_GMII) {
+			src = TX_RETIME_SRC_TXCLK;
+		} else if (dwmac->interface == PHY_INTERFACE_MODE_RMII) {
+			if (dwmac->ext_phyclk) {
+				src = TX_RETIME_SRC_PHYCLK;
+			} else {
+				src = TX_RETIME_SRC_CLKGEN;
+				freq = 50000000;
+			}
+
+		} else if (IS_PHY_IF_MODE_RGMII(dwmac->interface)) {
+			src = TX_RETIME_SRC_CLKGEN;
+			freq = 25000000;
+		}
+
+		if (src == TX_RETIME_SRC_CLKGEN && dwmac->clk)
+			clk_set_rate(dwmac->clk, freq);
+
+	} else if (spd == SPEED_1000) {
+		if (dwmac->is_tx_retime_src_clk_125)
+			src = TX_RETIME_SRC_CLK_125;
+		else
+			src = TX_RETIME_SRC_TXCLK;
+	}
+
+	regmap_update_bits(dwmac->regmap, dwmac->reg,
+			   TX_RETIME_SRC_MASK, tx_retime_val[src]);
+}
+
+static void sti_dwmac_exit(struct platform_device *pdev, void *priv)
+{
+	struct sti_dwmac *dwmac = priv;
+
+	if (dwmac->clk)
+		clk_disable_unprepare(dwmac->clk);
+}
+
+static void sti_fix_mac_speed(void *priv, unsigned int spd)
+{
+	struct sti_dwmac *dwmac = priv;
+
+	setup_retime_src(dwmac, spd);
+
+	return;
+}
+
+static int sti_dwmac_parse_data(struct sti_dwmac *dwmac,
+				struct platform_device *pdev)
+{
+	struct resource *res;
+	struct device *dev = &pdev->dev;
+	struct device_node *np = dev->of_node;
+	struct regmap *regmap;
+	int err;
+
+	if (!np)
+		return -EINVAL;
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "sti-ethconf");
+	if (!res)
+		return -ENODATA;
+
+	regmap = syscon_regmap_lookup_by_phandle(np, "st,syscon");
+	if (IS_ERR(regmap))
+		return PTR_ERR(regmap);
+
+	dwmac->dev = dev;
+	dwmac->interface = of_get_phy_mode(np);
+	dwmac->regmap = regmap;
+	dwmac->reg = res->start;
+	dwmac->ext_phyclk = of_property_read_bool(np, "st,ext-phyclk");
+	dwmac->is_tx_retime_src_clk_125 = false;
+
+	if (IS_PHY_IF_MODE_GBIT(dwmac->interface)) {
+		const char *rs;
+
+		err = of_property_read_string(np, "st,tx-retime-src", &rs);
+		if (err < 0) {
+			dev_err(dev, "st,tx-retime-src not specified\n");
+			return err;
+		}
+
+		if (!strcasecmp(rs, "clk_125"))
+			dwmac->is_tx_retime_src_clk_125 = true;
+	}
+
+	dwmac->clk = devm_clk_get(dev, "sti-ethclk");
+
+	if (IS_ERR(dwmac->clk))
+		dwmac->clk = NULL;
+
+	return 0;
+}
+
+static int sti_dwmac_init(struct platform_device *pdev, void *priv)
+{
+	struct sti_dwmac *dwmac = priv;
+	struct regmap *regmap = dwmac->regmap;
+	int iface = dwmac->interface;
+	u32 reg = dwmac->reg;
+	u32 val, spd;
+
+	if (dwmac->clk)
+		clk_prepare_enable(dwmac->clk);
+
+	regmap_update_bits(regmap, reg, MII_PHY_SEL_MASK, phy_intf_sels[iface]);
+
+	val = (iface == PHY_INTERFACE_MODE_REVMII) ? 0 : ENMII;
+	regmap_update_bits(regmap, reg, ENMII_MASK, val);
+
+	if (IS_PHY_IF_MODE_GBIT(iface))
+		spd = SPEED_1000;
+	else
+		spd = SPEED_100;
+
+	setup_retime_src(dwmac, spd);
+
+	return 0;
+}
+
+static void *sti_dwmac_setup(struct platform_device *pdev)
+{
+	struct sti_dwmac *dwmac;
+	int ret;
+
+	dwmac = devm_kzalloc(&pdev->dev, sizeof(*dwmac), GFP_KERNEL);
+	if (!dwmac)
+		return ERR_PTR(-ENOMEM);
+
+	ret = sti_dwmac_parse_data(dwmac, pdev);
+	if (ret) {
+		dev_err(&pdev->dev, "Unable to parse OF data\n");
+		return ERR_PTR(ret);
+	}
+
+	return dwmac;
+}
+
+const struct stmmac_of_data sti_gmac_data = {
+	.fix_mac_speed = sti_fix_mac_speed,
+	.setup = sti_dwmac_setup,
+	.init = sti_dwmac_init,
+	.exit = sti_dwmac_exit,
+};
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
index d9af26e..f9e60d7 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
@@ -133,6 +133,9 @@
 #ifdef CONFIG_DWMAC_SUNXI
 extern const struct stmmac_of_data sun7i_gmac_data;
 #endif
+#ifdef CONFIG_DWMAC_STI
+extern const struct stmmac_of_data sti_gmac_data;
+#endif
 extern struct platform_driver stmmac_pltfr_driver;
 static inline int stmmac_register_platform(void)
 {
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
index 5884a7d..c61bc72b 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
@@ -33,6 +33,11 @@
 #ifdef CONFIG_DWMAC_SUNXI
 	{ .compatible = "allwinner,sun7i-a20-gmac", .data = &sun7i_gmac_data},
 #endif
+#ifdef CONFIG_DWMAC_STI
+	{ .compatible = "st,stih415-dwmac", .data = &sti_gmac_data},
+	{ .compatible = "st,stih416-dwmac", .data = &sti_gmac_data},
+	{ .compatible = "st,stih127-dwmac", .data = &sti_gmac_data},
+#endif
 	/* SoC specific glue layers should come before generic bindings */
 	{ .compatible = "st,spear600-gmac"},
 	{ .compatible = "snps,dwmac-3.610"},
diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index 1d860ce..651087b 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -554,7 +554,7 @@
 		 * common for both the interface as the interface shares
 		 * the same hardware resource.
 		 */
-		for (i = 0; i <= priv->data.slaves; i++)
+		for (i = 0; i < priv->data.slaves; i++)
 			if (priv->slaves[i].ndev->flags & IFF_PROMISC)
 				flag = true;
 
@@ -578,7 +578,7 @@
 			unsigned long timeout = jiffies + HZ;
 
 			/* Disable Learn for all ports */
-			for (i = 0; i <= priv->data.slaves; i++) {
+			for (i = 0; i < priv->data.slaves; i++) {
 				cpsw_ale_control_set(ale, i,
 						     ALE_PORT_NOLEARN, 1);
 				cpsw_ale_control_set(ale, i,
@@ -606,7 +606,7 @@
 			cpsw_ale_control_set(ale, 0, ALE_P0_UNI_FLOOD, 0);
 
 			/* Enable Learn for all ports */
-			for (i = 0; i <= priv->data.slaves; i++) {
+			for (i = 0; i < priv->data.slaves; i++) {
 				cpsw_ale_control_set(ale, i,
 						     ALE_PORT_NOLEARN, 0);
 				cpsw_ale_control_set(ale, i,
@@ -1896,6 +1896,11 @@
 			memcpy(slave_data->mac_addr, mac_addr, ETH_ALEN);
 
 		slave_data->phy_if = of_get_phy_mode(slave_node);
+		if (slave_data->phy_if < 0) {
+			pr_err("Missing or malformed slave[%d] phy-mode property\n",
+			       i);
+			return slave_data->phy_if;
+		}
 
 		if (data->dual_emac) {
 			if (of_property_read_u32(slave_node, "dual_emac_res_vlan",
diff --git a/drivers/net/ethernet/tile/tilegx.c b/drivers/net/ethernet/tile/tilegx.c
index 023237a..17503da 100644
--- a/drivers/net/ethernet/tile/tilegx.c
+++ b/drivers/net/ethernet/tile/tilegx.c
@@ -2071,7 +2071,7 @@
 
 /* Return subqueue id on this core (one per core). */
 static u16 tile_net_select_queue(struct net_device *dev, struct sk_buff *skb,
-				 void *accel_priv)
+				 void *accel_priv, select_queue_fallback_t fallback)
 {
 	return smp_processor_id();
 }
diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
index 1ec65fe..4bfdf8c 100644
--- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
+++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
@@ -26,6 +26,7 @@
 #include <linux/netdevice.h>
 #include <linux/of_mdio.h>
 #include <linux/of_platform.h>
+#include <linux/of_irq.h>
 #include <linux/of_address.h>
 #include <linux/skbuff.h>
 #include <linux/spinlock.h>
@@ -600,7 +601,8 @@
 		size += status & XAXIDMA_BD_STS_ACTUAL_LEN_MASK;
 		packets++;
 
-		lp->tx_bd_ci = ++lp->tx_bd_ci % TX_BD_NUM;
+		++lp->tx_bd_ci;
+		lp->tx_bd_ci %= TX_BD_NUM;
 		cur_p = &lp->tx_bd_v[lp->tx_bd_ci];
 		status = cur_p->status;
 	}
@@ -686,7 +688,8 @@
 				     skb_headlen(skb), DMA_TO_DEVICE);
 
 	for (ii = 0; ii < num_frag; ii++) {
-		lp->tx_bd_tail = ++lp->tx_bd_tail % TX_BD_NUM;
+		++lp->tx_bd_tail;
+		lp->tx_bd_tail %= TX_BD_NUM;
 		cur_p = &lp->tx_bd_v[lp->tx_bd_tail];
 		frag = &skb_shinfo(skb)->frags[ii];
 		cur_p->phys = dma_map_single(ndev->dev.parent,
@@ -702,7 +705,8 @@
 	tail_p = lp->tx_bd_p + sizeof(*lp->tx_bd_v) * lp->tx_bd_tail;
 	/* Start the transfer */
 	axienet_dma_out32(lp, XAXIDMA_TX_TDESC_OFFSET, tail_p);
-	lp->tx_bd_tail = ++lp->tx_bd_tail % TX_BD_NUM;
+	++lp->tx_bd_tail;
+	lp->tx_bd_tail %= TX_BD_NUM;
 
 	return NETDEV_TX_OK;
 }
@@ -774,7 +778,8 @@
 		cur_p->status = 0;
 		cur_p->sw_id_offset = (u32) new_skb;
 
-		lp->rx_bd_ci = ++lp->rx_bd_ci % RX_BD_NUM;
+		++lp->rx_bd_ci;
+		lp->rx_bd_ci %= RX_BD_NUM;
 		cur_p = &lp->rx_bd_v[lp->rx_bd_ci];
 	}
 
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
index 7756118..7141a19 100644
--- a/drivers/net/hyperv/netvsc_drv.c
+++ b/drivers/net/hyperv/netvsc_drv.c
@@ -88,8 +88,12 @@
 {
 	struct net_device_context *net_device_ctx = netdev_priv(net);
 	struct hv_device *device_obj = net_device_ctx->device_ctx;
+	struct netvsc_device *nvdev;
+	struct rndis_device *rdev;
 	int ret = 0;
 
+	netif_carrier_off(net);
+
 	/* Open up the device */
 	ret = rndis_filter_open(device_obj);
 	if (ret != 0) {
@@ -99,6 +103,11 @@
 
 	netif_start_queue(net);
 
+	nvdev = hv_get_drvdata(device_obj);
+	rdev = nvdev->extension;
+	if (!rdev->link_state)
+		netif_carrier_on(net);
+
 	return ret;
 }
 
@@ -229,23 +238,24 @@
 	struct net_device *net;
 	struct net_device_context *ndev_ctx;
 	struct netvsc_device *net_device;
+	struct rndis_device *rdev;
 
 	net_device = hv_get_drvdata(device_obj);
+	rdev = net_device->extension;
+
+	rdev->link_state = status != 1;
+
 	net = net_device->ndev;
 
-	if (!net) {
-		netdev_err(net, "got link status but net device "
-				"not initialized yet\n");
+	if (!net || net->reg_state != NETREG_REGISTERED)
 		return;
-	}
 
+	ndev_ctx = netdev_priv(net);
 	if (status == 1) {
-		netif_carrier_on(net);
-		ndev_ctx = netdev_priv(net);
 		schedule_delayed_work(&ndev_ctx->dwork, 0);
 		schedule_delayed_work(&ndev_ctx->dwork, msecs_to_jiffies(20));
 	} else {
-		netif_carrier_off(net);
+		schedule_delayed_work(&ndev_ctx->dwork, 0);
 	}
 }
 
@@ -388,17 +398,35 @@
  * current context when receiving RNDIS_STATUS_MEDIA_CONNECT event. So, add
  * another netif_notify_peers() into a delayed work, otherwise GARP packet
  * will not be sent after quick migration, and cause network disconnection.
+ * Also, we update the carrier status here.
  */
-static void netvsc_send_garp(struct work_struct *w)
+static void netvsc_link_change(struct work_struct *w)
 {
 	struct net_device_context *ndev_ctx;
 	struct net_device *net;
 	struct netvsc_device *net_device;
+	struct rndis_device *rdev;
+	bool notify;
+
+	rtnl_lock();
 
 	ndev_ctx = container_of(w, struct net_device_context, dwork.work);
 	net_device = hv_get_drvdata(ndev_ctx->device_ctx);
+	rdev = net_device->extension;
 	net = net_device->ndev;
-	netdev_notify_peers(net);
+
+	if (rdev->link_state) {
+		netif_carrier_off(net);
+		notify = false;
+	} else {
+		netif_carrier_on(net);
+		notify = true;
+	}
+
+	rtnl_unlock();
+
+	if (notify)
+		netdev_notify_peers(net);
 }
 
 
@@ -414,13 +442,10 @@
 	if (!net)
 		return -ENOMEM;
 
-	/* Set initial state */
-	netif_carrier_off(net);
-
 	net_device_ctx = netdev_priv(net);
 	net_device_ctx->device_ctx = dev;
 	hv_set_drvdata(dev, net);
-	INIT_DELAYED_WORK(&net_device_ctx->dwork, netvsc_send_garp);
+	INIT_DELAYED_WORK(&net_device_ctx->dwork, netvsc_link_change);
 	INIT_WORK(&net_device_ctx->work, do_set_multicast);
 
 	net->netdev_ops = &device_ops;
@@ -443,8 +468,6 @@
 	}
 	memcpy(net->dev_addr, device_info.mac_adr, ETH_ALEN);
 
-	netif_carrier_on(net);
-
 	ret = register_netdev(net);
 	if (ret != 0) {
 		pr_err("Unable to register netdev.\n");
diff --git a/drivers/net/irda/irtty-sir.c b/drivers/net/irda/irtty-sir.c
index 177441a..24b6ddd 100644
--- a/drivers/net/irda/irtty-sir.c
+++ b/drivers/net/irda/irtty-sir.c
@@ -522,7 +522,6 @@
 	sirdev_put_instance(priv->dev);
 
 	/* Stop tty */
-	irtty_stop_receiver(tty, TRUE);
 	clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
 	if (tty->ops->stop)
 		tty->ops->stop(tty);
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
index 8433de4..a5d2189 100644
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -879,14 +879,15 @@
 	dev->priv_flags |= IFF_MACVLAN;
 	err = netdev_upper_dev_link(lowerdev, dev);
 	if (err)
-		goto destroy_port;
-
+		goto unregister_netdev;
 
 	list_add_tail_rcu(&vlan->list, &port->vlans);
 	netif_stacked_transfer_operstate(lowerdev, dev);
 
 	return 0;
 
+unregister_netdev:
+	unregister_netdevice(dev);
 destroy_port:
 	port->count -= 1;
 	if (!port->count)
diff --git a/drivers/net/phy/dp83640.c b/drivers/net/phy/dp83640.c
index 9414fa2..98e7cbf 100644
--- a/drivers/net/phy/dp83640.c
+++ b/drivers/net/phy/dp83640.c
@@ -1006,11 +1006,6 @@
 	} else
 		list_add_tail(&dp83640->list, &clock->phylist);
 
-	if (clock->chosen && !list_empty(&clock->phylist))
-		recalibrate(clock);
-	else
-		enable_broadcast(dp83640->phydev, clock->page, 1);
-
 	dp83640_clock_put(clock);
 	return 0;
 
@@ -1063,6 +1058,14 @@
 
 static int dp83640_config_init(struct phy_device *phydev)
 {
+	struct dp83640_private *dp83640 = phydev->priv;
+	struct dp83640_clock *clock = dp83640->clock;
+
+	if (clock->chosen && !list_empty(&clock->phylist))
+		recalibrate(clock);
+	else
+		enable_broadcast(phydev, clock->page, 1);
+
 	enable_status_frames(phydev, true);
 	ext_write(0, phydev, PAGE4, PTP_CTL, PTP_ENABLE);
 	return 0;
diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c
index 2840742..c8624a8 100644
--- a/drivers/net/team/team.c
+++ b/drivers/net/team/team.c
@@ -1648,7 +1648,7 @@
 }
 
 static u16 team_select_queue(struct net_device *dev, struct sk_buff *skb,
-			     void *accel_priv)
+			     void *accel_priv, select_queue_fallback_t fallback)
 {
 	/*
 	 * This helper function exists to help dev_pick_tx get the correct
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index 44c4db8..8fe9cb7 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -366,7 +366,7 @@
  * hope the rxq no. may help here.
  */
 static u16 tun_select_queue(struct net_device *dev, struct sk_buff *skb,
-			    void *accel_priv)
+			    void *accel_priv, select_queue_fallback_t fallback)
 {
 	struct tun_struct *tun = netdev_priv(dev);
 	struct tun_flow_entry *e;
diff --git a/drivers/net/usb/Kconfig b/drivers/net/usb/Kconfig
index 409499f..7e7269f 100644
--- a/drivers/net/usb/Kconfig
+++ b/drivers/net/usb/Kconfig
@@ -296,7 +296,6 @@
 	tristate "CoreChip-sz SR9800 based USB 2.0 10/100 ethernet devices"
 	depends on USB_USBNET
 	select CRC32
-	default y
 	---help---
 	  Say Y if you want to use one of the following 100Mbps USB Ethernet
 	  device based on the CoreChip-sz SR9800 chip.
diff --git a/drivers/net/usb/asix_devices.c b/drivers/net/usb/asix_devices.c
index 9765a7d..5d19409 100644
--- a/drivers/net/usb/asix_devices.c
+++ b/drivers/net/usb/asix_devices.c
@@ -917,7 +917,8 @@
 	.status = asix_status,
 	.link_reset = ax88178_link_reset,
 	.reset = ax88178_reset,
-	.flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_LINK_INTR,
+	.flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_LINK_INTR |
+		 FLAG_MULTI_PACKET,
 	.rx_fixup = asix_rx_fixup_common,
 	.tx_fixup = asix_tx_fixup,
 };
diff --git a/drivers/net/usb/ax88179_178a.c b/drivers/net/usb/ax88179_178a.c
index d6f64da..955df81 100644
--- a/drivers/net/usb/ax88179_178a.c
+++ b/drivers/net/usb/ax88179_178a.c
@@ -1118,6 +1118,10 @@
 	u16 hdr_off;
 	u32 *pkt_hdr;
 
+	/* This check is no longer done by usbnet */
+	if (skb->len < dev->net->hard_header_len)
+		return 0;
+
 	skb_trim(skb, skb->len - 4);
 	memcpy(&rx_hdr, skb_tail_pointer(skb), 4);
 	le32_to_cpus(&rx_hdr);
diff --git a/drivers/net/usb/gl620a.c b/drivers/net/usb/gl620a.c
index e4a8a93..1cc24e6 100644
--- a/drivers/net/usb/gl620a.c
+++ b/drivers/net/usb/gl620a.c
@@ -84,6 +84,10 @@
 	u32			size;
 	u32			count;
 
+	/* This check is no longer done by usbnet */
+	if (skb->len < dev->net->hard_header_len)
+		return 0;
+
 	header = (struct gl_header *) skb->data;
 
 	// get the packet count of the received skb
diff --git a/drivers/net/usb/mcs7830.c b/drivers/net/usb/mcs7830.c
index a305a7b..82d844a 100644
--- a/drivers/net/usb/mcs7830.c
+++ b/drivers/net/usb/mcs7830.c
@@ -526,8 +526,9 @@
 {
 	u8 status;
 
-	if (skb->len == 0) {
-		dev_err(&dev->udev->dev, "unexpected empty rx frame\n");
+	/* This check is no longer done by usbnet */
+	if (skb->len < dev->net->hard_header_len) {
+		dev_err(&dev->udev->dev, "unexpected tiny rx frame\n");
 		return 0;
 	}
 
diff --git a/drivers/net/usb/net1080.c b/drivers/net/usb/net1080.c
index 0a85d92..4cbdb13 100644
--- a/drivers/net/usb/net1080.c
+++ b/drivers/net/usb/net1080.c
@@ -364,6 +364,10 @@
 	struct nc_trailer	*trailer;
 	u16			hdr_len, packet_len;
 
+	/* This check is no longer done by usbnet */
+	if (skb->len < dev->net->hard_header_len)
+		return 0;
+
 	if (!(skb->len & 0x01)) {
 		netdev_dbg(dev->net, "rx framesize %d range %d..%d mtu %d\n",
 			   skb->len, dev->net->hard_header_len, dev->hard_mtu,
diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c
index ff5c871..313cb6c 100644
--- a/drivers/net/usb/qmi_wwan.c
+++ b/drivers/net/usb/qmi_wwan.c
@@ -80,10 +80,10 @@
 {
 	__be16 proto;
 
-	/* usbnet rx_complete guarantees that skb->len is at least
-	 * hard_header_len, so we can inspect the dest address without
-	 * checking skb->len
-	 */
+	/* This check is no longer done by usbnet */
+	if (skb->len < dev->net->hard_header_len)
+		return 0;
+
 	switch (skb->data[0] & 0xf0) {
 	case 0x40:
 		proto = htons(ETH_P_IP);
@@ -732,6 +732,7 @@
 	{QMI_FIXED_INTF(0x1bc7, 0x1201, 2)},	/* Telit LE920 */
 	{QMI_FIXED_INTF(0x0b3c, 0xc005, 6)},    /* Olivetti Olicard 200 */
 	{QMI_FIXED_INTF(0x1e2d, 0x0060, 4)},	/* Cinterion PLxx */
+	{QMI_FIXED_INTF(0x1e2d, 0x0053, 4)},	/* Cinterion PHxx,PXxx */
 
 	/* 4. Gobi 1000 devices */
 	{QMI_GOBI1K_DEVICE(0x05c6, 0x9212)},	/* Acer Gobi Modem Device */
diff --git a/drivers/net/usb/rndis_host.c b/drivers/net/usb/rndis_host.c
index a48bc0f..524a47a281 100644
--- a/drivers/net/usb/rndis_host.c
+++ b/drivers/net/usb/rndis_host.c
@@ -492,6 +492,10 @@
  */
 int rndis_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
 {
+	/* This check is no longer done by usbnet */
+	if (skb->len < dev->net->hard_header_len)
+		return 0;
+
 	/* peripheral may have batched packets to us... */
 	while (likely(skb->len)) {
 		struct rndis_data_hdr	*hdr = (void *)skb->data;
diff --git a/drivers/net/usb/smsc75xx.c b/drivers/net/usb/smsc75xx.c
index f17b9e0..d9e7892 100644
--- a/drivers/net/usb/smsc75xx.c
+++ b/drivers/net/usb/smsc75xx.c
@@ -2106,6 +2106,10 @@
 
 static int smsc75xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
 {
+	/* This check is no longer done by usbnet */
+	if (skb->len < dev->net->hard_header_len)
+		return 0;
+
 	while (skb->len > 0) {
 		u32 rx_cmd_a, rx_cmd_b, align_count, size;
 		struct sk_buff *ax_skb;
diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c
index 8dd54a0..424db65e 100644
--- a/drivers/net/usb/smsc95xx.c
+++ b/drivers/net/usb/smsc95xx.c
@@ -1723,6 +1723,10 @@
 
 static int smsc95xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
 {
+	/* This check is no longer done by usbnet */
+	if (skb->len < dev->net->hard_header_len)
+		return 0;
+
 	while (skb->len > 0) {
 		u32 header, align_count;
 		struct sk_buff *ax_skb;
diff --git a/drivers/net/usb/sr9800.c b/drivers/net/usb/sr9800.c
index 4175eb9..b94a0fb 100644
--- a/drivers/net/usb/sr9800.c
+++ b/drivers/net/usb/sr9800.c
@@ -63,6 +63,10 @@
 {
 	int offset = 0;
 
+	/* This check is no longer done by usbnet */
+	if (skb->len < dev->net->hard_header_len)
+		return 0;
+
 	while (offset + sizeof(u32) < skb->len) {
 		struct sk_buff *sr_skb;
 		u16 size;
@@ -823,7 +827,7 @@
 		dev->rx_urb_size =
 			SR9800_BULKIN_SIZE[SR9800_MAX_BULKIN_2K].size;
 	}
-	netdev_dbg(dev->net, "%s : setting rx_urb_size with : %ld\n", __func__,
+	netdev_dbg(dev->net, "%s : setting rx_urb_size with : %zu\n", __func__,
 		   dev->rx_urb_size);
 	return 0;
 
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
index 4671da7..dd10d58 100644
--- a/drivers/net/usb/usbnet.c
+++ b/drivers/net/usb/usbnet.c
@@ -542,17 +542,19 @@
 	}
 	// else network stack removes extra byte if we forced a short packet
 
-	if (skb->len) {
-		/* all data was already cloned from skb inside the driver */
-		if (dev->driver_info->flags & FLAG_MULTI_PACKET)
-			dev_kfree_skb_any(skb);
-		else
-			usbnet_skb_return(dev, skb);
+	/* all data was already cloned from skb inside the driver */
+	if (dev->driver_info->flags & FLAG_MULTI_PACKET)
+		goto done;
+
+	if (skb->len < ETH_HLEN) {
+		dev->net->stats.rx_errors++;
+		dev->net->stats.rx_length_errors++;
+		netif_dbg(dev, rx_err, dev->net, "rx length %d\n", skb->len);
+	} else {
+		usbnet_skb_return(dev, skb);
 		return;
 	}
 
-	netif_dbg(dev, rx_err, dev->net, "drop\n");
-	dev->net->stats.rx_errors++;
 done:
 	skb_queue_tail(&dev->done, skb);
 }
@@ -574,13 +576,6 @@
 	switch (urb_status) {
 	/* success */
 	case 0:
-		if (skb->len < dev->net->hard_header_len) {
-			state = rx_cleanup;
-			dev->net->stats.rx_errors++;
-			dev->net->stats.rx_length_errors++;
-			netif_dbg(dev, rx_err, dev->net,
-				  "rx length %d\n", skb->len);
-		}
 		break;
 
 	/* stalls need manual reset. this is rare ... except that
diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c
index d6bc7cb..1a2973b 100644
--- a/drivers/net/wireless/ath/ath5k/phy.c
+++ b/drivers/net/wireless/ath/ath5k/phy.c
@@ -110,7 +110,7 @@
 		ath5k_hw_reg_write(ah, 0x00010000, AR5K_PHY(0x20));
 
 	if (ah->ah_version == AR5K_AR5210) {
-		srev = ath5k_hw_reg_read(ah, AR5K_PHY(256) >> 28) & 0xf;
+		srev = (ath5k_hw_reg_read(ah, AR5K_PHY(256)) >> 28) & 0xf;
 		ret = (u16)ath5k_hw_bitswap(srev, 4) + 1;
 	} else {
 		srev = (ath5k_hw_reg_read(ah, AR5K_PHY(0x100)) >> 24) & 0xff;
diff --git a/drivers/net/wireless/hostap/hostap_proc.c b/drivers/net/wireless/hostap/hostap_proc.c
index aa7ad3a7..4e5c0f8 100644
--- a/drivers/net/wireless/hostap/hostap_proc.c
+++ b/drivers/net/wireless/hostap/hostap_proc.c
@@ -496,7 +496,7 @@
 
 void hostap_remove_proc(local_info_t *local)
 {
-	remove_proc_subtree(local->ddev->name, hostap_proc);
+	proc_remove(local->proc);
 }
 
 
diff --git a/drivers/net/wireless/iwlwifi/dvm/mac80211.c b/drivers/net/wireless/iwlwifi/dvm/mac80211.c
index c24d1d3..73086c1 100644
--- a/drivers/net/wireless/iwlwifi/dvm/mac80211.c
+++ b/drivers/net/wireless/iwlwifi/dvm/mac80211.c
@@ -696,6 +696,24 @@
 	return ret;
 }
 
+static inline bool iwl_enable_rx_ampdu(const struct iwl_cfg *cfg)
+{
+	if (iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_RXAGG)
+		return false;
+	return true;
+}
+
+static inline bool iwl_enable_tx_ampdu(const struct iwl_cfg *cfg)
+{
+	if (iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_TXAGG)
+		return false;
+	if (iwlwifi_mod_params.disable_11n & IWL_ENABLE_HT_TXAGG)
+		return true;
+
+	/* disabled by default */
+	return false;
+}
+
 static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw,
 				   struct ieee80211_vif *vif,
 				   enum ieee80211_ampdu_mlme_action action,
@@ -717,7 +735,7 @@
 
 	switch (action) {
 	case IEEE80211_AMPDU_RX_START:
-		if (iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_RXAGG)
+		if (!iwl_enable_rx_ampdu(priv->cfg))
 			break;
 		IWL_DEBUG_HT(priv, "start Rx\n");
 		ret = iwl_sta_rx_agg_start(priv, sta, tid, *ssn);
@@ -729,7 +747,7 @@
 	case IEEE80211_AMPDU_TX_START:
 		if (!priv->trans->ops->txq_enable)
 			break;
-		if (iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_TXAGG)
+		if (!iwl_enable_tx_ampdu(priv->cfg))
 			break;
 		IWL_DEBUG_HT(priv, "start Tx\n");
 		ret = iwlagn_tx_agg_start(priv, vif, sta, tid, ssn);
diff --git a/drivers/net/wireless/iwlwifi/iwl-drv.c b/drivers/net/wireless/iwlwifi/iwl-drv.c
index c372816..7510355 100644
--- a/drivers/net/wireless/iwlwifi/iwl-drv.c
+++ b/drivers/net/wireless/iwlwifi/iwl-drv.c
@@ -1286,7 +1286,7 @@
 MODULE_PARM_DESC(swcrypto, "using crypto in software (default 0 [hardware])");
 module_param_named(11n_disable, iwlwifi_mod_params.disable_11n, uint, S_IRUGO);
 MODULE_PARM_DESC(11n_disable,
-	"disable 11n functionality, bitmap: 1: full, 2: agg TX, 4: agg RX");
+	"disable 11n functionality, bitmap: 1: full, 2: disable agg TX, 4: disable agg RX, 8 enable agg TX");
 module_param_named(amsdu_size_8K, iwlwifi_mod_params.amsdu_size_8K,
 		   int, S_IRUGO);
 MODULE_PARM_DESC(amsdu_size_8K, "enable 8K amsdu size (default 0)");
diff --git a/drivers/net/wireless/iwlwifi/iwl-modparams.h b/drivers/net/wireless/iwlwifi/iwl-modparams.h
index 0a84ade..b29075c 100644
--- a/drivers/net/wireless/iwlwifi/iwl-modparams.h
+++ b/drivers/net/wireless/iwlwifi/iwl-modparams.h
@@ -79,9 +79,12 @@
 	IWL_POWER_NUM
 };
 
-#define IWL_DISABLE_HT_ALL	BIT(0)
-#define IWL_DISABLE_HT_TXAGG	BIT(1)
-#define IWL_DISABLE_HT_RXAGG	BIT(2)
+enum iwl_disable_11n {
+	IWL_DISABLE_HT_ALL	 = BIT(0),
+	IWL_DISABLE_HT_TXAGG	 = BIT(1),
+	IWL_DISABLE_HT_RXAGG	 = BIT(2),
+	IWL_ENABLE_HT_TXAGG	 = BIT(3),
+};
 
 /**
  * struct iwl_mod_params
@@ -90,7 +93,7 @@
  *
  * @sw_crypto: using hardware encryption, default = 0
  * @disable_11n: disable 11n capabilities, default = 0,
- *	use IWL_DISABLE_HT_* constants
+ *	use IWL_[DIS,EN]ABLE_HT_* constants
  * @amsdu_size_8K: enable 8K amsdu size, default = 0
  * @restart_fw: restart firmware, default = 1
  * @wd_disable: enable stuck queue check, default = 0
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c
index 6bf9766..c35b866 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c
@@ -328,6 +328,24 @@
 	ieee80211_free_txskb(hw, skb);
 }
 
+static inline bool iwl_enable_rx_ampdu(const struct iwl_cfg *cfg)
+{
+	if (iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_RXAGG)
+		return false;
+	return true;
+}
+
+static inline bool iwl_enable_tx_ampdu(const struct iwl_cfg *cfg)
+{
+	if (iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_TXAGG)
+		return false;
+	if (iwlwifi_mod_params.disable_11n & IWL_ENABLE_HT_TXAGG)
+		return true;
+
+	/* enabled by default */
+	return true;
+}
+
 static int iwl_mvm_mac_ampdu_action(struct ieee80211_hw *hw,
 				    struct ieee80211_vif *vif,
 				    enum ieee80211_ampdu_mlme_action action,
@@ -347,7 +365,7 @@
 
 	switch (action) {
 	case IEEE80211_AMPDU_RX_START:
-		if (iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_RXAGG) {
+		if (!iwl_enable_rx_ampdu(mvm->cfg)) {
 			ret = -EINVAL;
 			break;
 		}
@@ -357,7 +375,7 @@
 		ret = iwl_mvm_sta_rx_agg(mvm, sta, tid, 0, false);
 		break;
 	case IEEE80211_AMPDU_TX_START:
-		if (iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_TXAGG) {
+		if (!iwl_enable_tx_ampdu(mvm->cfg)) {
 			ret = -EINVAL;
 			break;
 		}
diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c
index 4d79761..9d3d275 100644
--- a/drivers/net/wireless/mwifiex/main.c
+++ b/drivers/net/wireless/mwifiex/main.c
@@ -748,7 +748,7 @@
 
 static u16
 mwifiex_netdev_select_wmm_queue(struct net_device *dev, struct sk_buff *skb,
-				void *accel_priv)
+				void *accel_priv, select_queue_fallback_t fallback)
 {
 	skb->priority = cfg80211_classify8021d(skb, NULL);
 	return mwifiex_1d_to_wmm_queue[skb->priority];
diff --git a/drivers/net/wireless/rtl818x/rtl8187/rtl8187.h b/drivers/net/wireless/rtl818x/rtl8187/rtl8187.h
index 56aee06..a6ad79f 100644
--- a/drivers/net/wireless/rtl818x/rtl8187/rtl8187.h
+++ b/drivers/net/wireless/rtl818x/rtl8187/rtl8187.h
@@ -15,6 +15,8 @@
 #ifndef RTL8187_H
 #define RTL8187_H
 
+#include <linux/cache.h>
+
 #include "rtl818x.h"
 #include "leds.h"
 
@@ -139,7 +141,10 @@
 	u8 aifsn[4];
 	u8 rfkill_mask;
 	struct {
-		__le64 buf;
+		union {
+			__le64 buf;
+			u8 dummy1[L1_CACHE_BYTES];
+		} ____cacheline_aligned;
 		struct sk_buff_head queue;
 	} b_tx_status; /* This queue is used by both -b and non-b devices */
 	struct mutex io_mutex;
@@ -147,7 +152,8 @@
 		u8 bits8;
 		__le16 bits16;
 		__le32 bits32;
-	} *io_dmabuf;
+		u8 dummy2[L1_CACHE_BYTES];
+	} *io_dmabuf ____cacheline_aligned;
 	bool rfkill_off;
 	u16 seqno;
 };
diff --git a/drivers/net/wireless/rtlwifi/ps.c b/drivers/net/wireless/rtlwifi/ps.c
index deedae3..d1c0191 100644
--- a/drivers/net/wireless/rtlwifi/ps.c
+++ b/drivers/net/wireless/rtlwifi/ps.c
@@ -48,7 +48,7 @@
 
 	/*<2> Enable Adapter */
 	if (rtlpriv->cfg->ops->hw_init(hw))
-		return 1;
+		return false;
 	RT_CLEAR_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC);
 
 	/*<3> Enable Interrupt */
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c
index a82b30a..2eb0b38 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c
@@ -937,14 +937,26 @@
 	bool is92c;
 	int err;
 	u8 tmp_u1b;
+	unsigned long flags;
 
 	rtlpci->being_init_adapter = true;
+
+	/* Since this function can take a very long time (up to 350 ms)
+	 * and can be called with irqs disabled, reenable the irqs
+	 * to let the other devices continue being serviced.
+	 *
+	 * It is safe doing so since our own interrupts will only be enabled
+	 * in a subsequent step.
+	 */
+	local_save_flags(flags);
+	local_irq_enable();
+
 	rtlpriv->intf_ops->disable_aspm(hw);
 	rtstatus = _rtl92ce_init_mac(hw);
 	if (!rtstatus) {
 		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Init MAC failed\n");
 		err = 1;
-		return err;
+		goto exit;
 	}
 
 	err = rtl92c_download_fw(hw);
@@ -952,7 +964,7 @@
 		RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
 			 "Failed to download FW. Init HW without FW now..\n");
 		err = 1;
-		return err;
+		goto exit;
 	}
 
 	rtlhal->last_hmeboxnum = 0;
@@ -1032,6 +1044,8 @@
 		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "under 1.5V\n");
 	}
 	rtl92c_dm_init(hw);
+exit:
+	local_irq_restore(flags);
 	rtlpci->being_init_adapter = false;
 	return err;
 }
diff --git a/drivers/of/base.c b/drivers/of/base.c
index 10b5110..89e888a 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -342,27 +342,72 @@
 }
 EXPORT_SYMBOL(of_get_cpu_node);
 
-/** Checks if the given "compat" string matches one of the strings in
- * the device's "compatible" property
+/**
+ * __of_device_is_compatible() - Check if the node matches given constraints
+ * @device: pointer to node
+ * @compat: required compatible string, NULL or "" for any match
+ * @type: required device_type value, NULL or "" for any match
+ * @name: required node name, NULL or "" for any match
+ *
+ * Checks if the given @compat, @type and @name strings match the
+ * properties of the given @device. A constraints can be skipped by
+ * passing NULL or an empty string as the constraint.
+ *
+ * Returns 0 for no match, and a positive integer on match. The return
+ * value is a relative score with larger values indicating better
+ * matches. The score is weighted for the most specific compatible value
+ * to get the highest score. Matching type is next, followed by matching
+ * name. Practically speaking, this results in the following priority
+ * order for matches:
+ *
+ * 1. specific compatible && type && name
+ * 2. specific compatible && type
+ * 3. specific compatible && name
+ * 4. specific compatible
+ * 5. general compatible && type && name
+ * 6. general compatible && type
+ * 7. general compatible && name
+ * 8. general compatible
+ * 9. type && name
+ * 10. type
+ * 11. name
  */
 static int __of_device_is_compatible(const struct device_node *device,
-				     const char *compat)
+				     const char *compat, const char *type, const char *name)
 {
-	const char* cp;
-	int cplen, l;
+	struct property *prop;
+	const char *cp;
+	int index = 0, score = 0;
 
-	cp = __of_get_property(device, "compatible", &cplen);
-	if (cp == NULL)
-		return 0;
-	while (cplen > 0) {
-		if (of_compat_cmp(cp, compat, strlen(compat)) == 0)
-			return 1;
-		l = strlen(cp) + 1;
-		cp += l;
-		cplen -= l;
+	/* Compatible match has highest priority */
+	if (compat && compat[0]) {
+		prop = __of_find_property(device, "compatible", NULL);
+		for (cp = of_prop_next_string(prop, NULL); cp;
+		     cp = of_prop_next_string(prop, cp), index++) {
+			if (of_compat_cmp(cp, compat, strlen(compat)) == 0) {
+				score = INT_MAX/2 - (index << 2);
+				break;
+			}
+		}
+		if (!score)
+			return 0;
 	}
 
-	return 0;
+	/* Matching type is better than matching name */
+	if (type && type[0]) {
+		if (!device->type || of_node_cmp(type, device->type))
+			return 0;
+		score += 2;
+	}
+
+	/* Matching name is a bit better than not */
+	if (name && name[0]) {
+		if (!device->name || of_node_cmp(name, device->name))
+			return 0;
+		score++;
+	}
+
+	return score;
 }
 
 /** Checks if the given "compat" string matches one of the strings in
@@ -375,7 +420,7 @@
 	int res;
 
 	raw_spin_lock_irqsave(&devtree_lock, flags);
-	res = __of_device_is_compatible(device, compat);
+	res = __of_device_is_compatible(device, compat, NULL, NULL);
 	raw_spin_unlock_irqrestore(&devtree_lock, flags);
 	return res;
 }
@@ -681,10 +726,7 @@
 	raw_spin_lock_irqsave(&devtree_lock, flags);
 	np = from ? from->allnext : of_allnodes;
 	for (; np; np = np->allnext) {
-		if (type
-		    && !(np->type && (of_node_cmp(np->type, type) == 0)))
-			continue;
-		if (__of_device_is_compatible(np, compatible) &&
+		if (__of_device_is_compatible(np, compatible, type, NULL) &&
 		    of_node_get(np))
 			break;
 	}
@@ -730,65 +772,26 @@
 }
 EXPORT_SYMBOL(of_find_node_with_property);
 
-static const struct of_device_id *
-of_match_compatible(const struct of_device_id *matches,
-			const struct device_node *node)
-{
-	const char *cp;
-	int cplen, l;
-	const struct of_device_id *m;
-
-	cp = __of_get_property(node, "compatible", &cplen);
-	while (cp && (cplen > 0)) {
-		m = matches;
-		while (m->name[0] || m->type[0] || m->compatible[0]) {
-			/* Only match for the entries without type and name */
-			if (m->name[0] || m->type[0] ||
-				of_compat_cmp(m->compatible, cp,
-					 strlen(m->compatible)))
-				m++;
-			else
-				return m;
-		}
-
-		/* Get node's next compatible string */
-		l = strlen(cp) + 1;
-		cp += l;
-		cplen -= l;
-	}
-
-	return NULL;
-}
-
 static
 const struct of_device_id *__of_match_node(const struct of_device_id *matches,
 					   const struct device_node *node)
 {
-	const struct of_device_id *m;
+	const struct of_device_id *best_match = NULL;
+	int score, best_score = 0;
 
 	if (!matches)
 		return NULL;
 
-	m = of_match_compatible(matches, node);
-	if (m)
-		return m;
-
-	while (matches->name[0] || matches->type[0] || matches->compatible[0]) {
-		int match = 1;
-		if (matches->name[0])
-			match &= node->name
-				&& !strcmp(matches->name, node->name);
-		if (matches->type[0])
-			match &= node->type
-				&& !strcmp(matches->type, node->type);
-		if (matches->compatible[0])
-			match &= __of_device_is_compatible(node,
-							   matches->compatible);
-		if (match)
-			return matches;
-		matches++;
+	for (; matches->name[0] || matches->type[0] || matches->compatible[0]; matches++) {
+		score = __of_device_is_compatible(node, matches->compatible,
+						  matches->type, matches->name);
+		if (score > best_score) {
+			best_match = matches;
+			best_score = score;
+		}
 	}
-	return NULL;
+
+	return best_match;
 }
 
 /**
@@ -796,12 +799,7 @@
  *	@matches:	array of of device match structures to search in
  *	@node:		the of device structure to match against
  *
- *	Low level utility function used by device matching. We have two ways
- *	of matching:
- *	- Try to find the best compatible match by comparing each compatible
- *	  string of device node with all the given matches respectively.
- *	- If the above method failed, then try to match the compatible by using
- *	  __of_device_is_compatible() besides the match in type and name.
+ *	Low level utility function used by device matching.
  */
 const struct of_device_id *of_match_node(const struct of_device_id *matches,
 					 const struct device_node *node)
diff --git a/drivers/of/of_mdio.c b/drivers/of/of_mdio.c
index 875b7b6..5b3c24f 100644
--- a/drivers/of/of_mdio.c
+++ b/drivers/of/of_mdio.c
@@ -24,7 +24,11 @@
 
 static void of_set_phy_supported(struct phy_device *phydev, u32 max_speed)
 {
-	phydev->supported |= PHY_DEFAULT_FEATURES;
+	/* The default values for phydev->supported are provided by the PHY
+	 * driver "features" member, we want to reset to sane defaults fist
+	 * before supporting higher speeds.
+	 */
+	phydev->supported &= PHY_DEFAULT_FEATURES;
 
 	switch (max_speed) {
 	default:
@@ -44,7 +48,7 @@
 {
 	struct phy_device *phy;
 	bool is_c45;
-	int rc, prev_irq;
+	int rc;
 	u32 max_speed = 0;
 
 	is_c45 = of_device_is_compatible(child,
@@ -54,12 +58,14 @@
 	if (!phy || IS_ERR(phy))
 		return 1;
 
-	if (mdio->irq) {
-		prev_irq = mdio->irq[addr];
-		mdio->irq[addr] =
-			irq_of_parse_and_map(child, 0);
-		if (!mdio->irq[addr])
-			mdio->irq[addr] = prev_irq;
+	rc = irq_of_parse_and_map(child, 0);
+	if (rc > 0) {
+		phy->irq = rc;
+		if (mdio->irq)
+			mdio->irq[addr] = rc;
+	} else {
+		if (mdio->irq)
+			phy->irq = mdio->irq[addr];
 	}
 
 	/* Associate the OF node with the device structure so it
diff --git a/drivers/of/selftest.c b/drivers/of/selftest.c
index e21012b..6643d19 100644
--- a/drivers/of/selftest.c
+++ b/drivers/of/selftest.c
@@ -300,6 +300,72 @@
 	of_node_put(np);
 }
 
+static struct of_device_id match_node_table[] = {
+	{ .data = "A", .name = "name0", }, /* Name alone is lowest priority */
+	{ .data = "B", .type = "type1", }, /* followed by type alone */
+
+	{ .data = "Ca", .name = "name2", .type = "type1", }, /* followed by both together */
+	{ .data = "Cb", .name = "name2", }, /* Only match when type doesn't match */
+	{ .data = "Cc", .name = "name2", .type = "type2", },
+
+	{ .data = "E", .compatible = "compat3" },
+	{ .data = "G", .compatible = "compat2", },
+	{ .data = "H", .compatible = "compat2", .name = "name5", },
+	{ .data = "I", .compatible = "compat2", .type = "type1", },
+	{ .data = "J", .compatible = "compat2", .type = "type1", .name = "name8", },
+	{ .data = "K", .compatible = "compat2", .name = "name9", },
+	{}
+};
+
+static struct {
+	const char *path;
+	const char *data;
+} match_node_tests[] = {
+	{ .path = "/testcase-data/match-node/name0", .data = "A", },
+	{ .path = "/testcase-data/match-node/name1", .data = "B", },
+	{ .path = "/testcase-data/match-node/a/name2", .data = "Ca", },
+	{ .path = "/testcase-data/match-node/b/name2", .data = "Cb", },
+	{ .path = "/testcase-data/match-node/c/name2", .data = "Cc", },
+	{ .path = "/testcase-data/match-node/name3", .data = "E", },
+	{ .path = "/testcase-data/match-node/name4", .data = "G", },
+	{ .path = "/testcase-data/match-node/name5", .data = "H", },
+	{ .path = "/testcase-data/match-node/name6", .data = "G", },
+	{ .path = "/testcase-data/match-node/name7", .data = "I", },
+	{ .path = "/testcase-data/match-node/name8", .data = "J", },
+	{ .path = "/testcase-data/match-node/name9", .data = "K", },
+};
+
+static void __init of_selftest_match_node(void)
+{
+	struct device_node *np;
+	const struct of_device_id *match;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(match_node_tests); i++) {
+		np = of_find_node_by_path(match_node_tests[i].path);
+		if (!np) {
+			selftest(0, "missing testcase node %s\n",
+				match_node_tests[i].path);
+			continue;
+		}
+
+		match = of_match_node(match_node_table, np);
+		if (!match) {
+			selftest(0, "%s didn't match anything\n",
+				match_node_tests[i].path);
+			continue;
+		}
+
+		if (strcmp(match->data, match_node_tests[i].data) != 0) {
+			selftest(0, "%s got wrong match. expected %s, got %s\n",
+				match_node_tests[i].path, match_node_tests[i].data,
+				(const char *)match->data);
+			continue;
+		}
+		selftest(1, "passed");
+	}
+}
+
 static int __init of_selftest(void)
 {
 	struct device_node *np;
@@ -316,6 +382,7 @@
 	of_selftest_property_match_string();
 	of_selftest_parse_interrupts();
 	of_selftest_parse_interrupts_extended();
+	of_selftest_match_node();
 	pr_info("end of selftest - %i passed, %i failed\n",
 		selftest_results.passed, selftest_results.failed);
 	return 0;
diff --git a/drivers/of/testcase-data/testcases.dtsi b/drivers/of/testcase-data/testcases.dtsi
new file mode 100644
index 0000000..3a5b75a
--- /dev/null
+++ b/drivers/of/testcase-data/testcases.dtsi
@@ -0,0 +1,3 @@
+#include "tests-phandle.dtsi"
+#include "tests-interrupts.dtsi"
+#include "tests-match.dtsi"
diff --git a/arch/arm/boot/dts/testcases/tests-interrupts.dtsi b/drivers/of/testcase-data/tests-interrupts.dtsi
similarity index 100%
rename from arch/arm/boot/dts/testcases/tests-interrupts.dtsi
rename to drivers/of/testcase-data/tests-interrupts.dtsi
diff --git a/drivers/of/testcase-data/tests-match.dtsi b/drivers/of/testcase-data/tests-match.dtsi
new file mode 100644
index 0000000..c9e5411
--- /dev/null
+++ b/drivers/of/testcase-data/tests-match.dtsi
@@ -0,0 +1,19 @@
+
+/ {
+	testcase-data {
+		match-node {
+			name0 { };
+			name1 { device_type = "type1"; };
+			a { name2 { device_type = "type1"; }; };
+			b { name2 { }; };
+			c { name2 { device_type = "type2"; }; };
+			name3 { compatible = "compat3"; };
+			name4 { compatible = "compat2", "compat3"; };
+			name5 { compatible = "compat2", "compat3"; };
+			name6 { compatible = "compat1", "compat2", "compat3"; };
+			name7 { compatible = "compat2"; device_type = "type1"; };
+			name8 { compatible = "compat2"; device_type = "type1"; };
+			name9 { compatible = "compat2"; };
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/testcases/tests-phandle.dtsi b/drivers/of/testcase-data/tests-phandle.dtsi
similarity index 100%
rename from arch/arm/boot/dts/testcases/tests-phandle.dtsi
rename to drivers/of/testcase-data/tests-phandle.dtsi
diff --git a/drivers/pci/host/pci-mvebu.c b/drivers/pci/host/pci-mvebu.c
index 13478ec..0e79665 100644
--- a/drivers/pci/host/pci-mvebu.c
+++ b/drivers/pci/host/pci-mvebu.c
@@ -60,14 +60,6 @@
 #define PCIE_DEBUG_CTRL         0x1a60
 #define  PCIE_DEBUG_SOFT_RESET		BIT(20)
 
-/*
- * This product ID is registered by Marvell, and used when the Marvell
- * SoC is not the root complex, but an endpoint on the PCIe bus. It is
- * therefore safe to re-use this PCI ID for our emulated PCI-to-PCI
- * bridge.
- */
-#define MARVELL_EMULATED_PCI_PCI_BRIDGE_ID 0x7846
-
 /* PCI configuration space of a PCI-to-PCI bridge */
 struct mvebu_sw_pci_bridge {
 	u16 vendor;
@@ -388,7 +380,8 @@
 
 	bridge->class = PCI_CLASS_BRIDGE_PCI;
 	bridge->vendor = PCI_VENDOR_ID_MARVELL;
-	bridge->device = MARVELL_EMULATED_PCI_PCI_BRIDGE_ID;
+	bridge->device = mvebu_readl(port, PCIE_DEV_ID_OFF) >> 16;
+	bridge->revision = mvebu_readl(port, PCIE_DEV_REV_OFF) & 0xff;
 	bridge->header_type = PCI_HEADER_TYPE_BRIDGE;
 	bridge->cache_line_size = 0x10;
 
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index 7a0fec6..955ab79 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -545,9 +545,15 @@
 		return -ENOMEM;
 	list_for_each_entry(entry, &pdev->msi_list, list) {
 		char *name = kmalloc(20, GFP_KERNEL);
-		msi_dev_attr = kzalloc(sizeof(*msi_dev_attr), GFP_KERNEL);
-		if (!msi_dev_attr)
+		if (!name)
 			goto error_attrs;
+
+		msi_dev_attr = kzalloc(sizeof(*msi_dev_attr), GFP_KERNEL);
+		if (!msi_dev_attr) {
+			kfree(name);
+			goto error_attrs;
+		}
+
 		sprintf(name, "%d", entry->irq);
 		sysfs_attr_init(&msi_dev_attr->attr);
 		msi_dev_attr->attr.name = name;
@@ -589,6 +595,7 @@
 		++count;
 		msi_attr = msi_attrs[count];
 	}
+	kfree(msi_attrs);
 	return ret;
 }
 
@@ -959,7 +966,6 @@
 /**
  * pci_msix_vec_count - return the number of device's MSI-X table entries
  * @dev: pointer to the pci_dev data structure of MSI-X device function
-
  * This function returns the number of device's MSI-X table entries and
  * therefore the number of MSI-X vectors device is capable of sending.
  * It returns a negative errno if the device is not capable of sending MSI-X
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 1febe90..6b05f61 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -1181,6 +1181,8 @@
 static int do_pci_enable_device(struct pci_dev *dev, int bars)
 {
 	int err;
+	u16 cmd;
+	u8 pin;
 
 	err = pci_set_power_state(dev, PCI_D0);
 	if (err < 0 && err != -EIO)
@@ -1190,6 +1192,14 @@
 		return err;
 	pci_fixup_device(pci_fixup_enable, dev);
 
+	pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
+	if (pin) {
+		pci_read_config_word(dev, PCI_COMMAND, &cmd);
+		if (cmd & PCI_COMMAND_INTX_DISABLE)
+			pci_write_config_word(dev, PCI_COMMAND,
+					      cmd & ~PCI_COMMAND_INTX_DISABLE);
+	}
+
 	return 0;
 }
 
diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index afa2354..c7a551c 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -5,7 +5,7 @@
 menu "PHY Subsystem"
 
 config GENERIC_PHY
-	tristate "PHY Core"
+	bool "PHY Core"
 	help
 	  Generic PHY support.
 
@@ -61,6 +61,7 @@
 config BCM_KONA_USB2_PHY
 	tristate "Broadcom Kona USB2 PHY Driver"
 	depends on GENERIC_PHY
+	depends on HAS_IOMEM
 	help
 	  Enable this to support the Broadcom Kona USB 2.0 PHY.
 
diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c
index 5f5b0f4..6c73837 100644
--- a/drivers/phy/phy-core.c
+++ b/drivers/phy/phy-core.c
@@ -176,6 +176,8 @@
 			dev_err(&phy->dev, "phy init failed --> %d\n", ret);
 			goto out;
 		}
+	} else {
+		ret = 0; /* Override possible ret == -ENOTSUPP */
 	}
 	++phy->init_count;
 
@@ -232,6 +234,8 @@
 			dev_err(&phy->dev, "phy poweron failed --> %d\n", ret);
 			goto out;
 		}
+	} else {
+		ret = 0; /* Override possible ret == -ENOTSUPP */
 	}
 	++phy->power_count;
 	mutex_unlock(&phy->mutex);
@@ -404,17 +408,11 @@
 		index = of_property_match_string(dev->of_node, "phy-names",
 			string);
 		phy = of_phy_get(dev, index);
-		if (IS_ERR(phy)) {
-			dev_err(dev, "unable to find phy\n");
-			return phy;
-		}
 	} else {
 		phy = phy_lookup(dev, string);
-		if (IS_ERR(phy)) {
-			dev_err(dev, "unable to find phy\n");
-			return phy;
-		}
 	}
+	if (IS_ERR(phy))
+		return phy;
 
 	if (!try_module_get(phy->ops->owner))
 		return ERR_PTR(-EPROBE_DEFER);
diff --git a/drivers/phy/phy-exynos-dp-video.c b/drivers/phy/phy-exynos-dp-video.c
index 1dbe6ce..0786fef 100644
--- a/drivers/phy/phy-exynos-dp-video.c
+++ b/drivers/phy/phy-exynos-dp-video.c
@@ -76,10 +76,6 @@
 	if (IS_ERR(state->regs))
 		return PTR_ERR(state->regs);
 
-	phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
-	if (IS_ERR(phy_provider))
-		return PTR_ERR(phy_provider);
-
 	phy = devm_phy_create(dev, &exynos_dp_video_phy_ops, NULL);
 	if (IS_ERR(phy)) {
 		dev_err(dev, "failed to create Display Port PHY\n");
@@ -87,6 +83,10 @@
 	}
 	phy_set_drvdata(phy, state);
 
+	phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
+	if (IS_ERR(phy_provider))
+		return PTR_ERR(phy_provider);
+
 	return 0;
 }
 
diff --git a/drivers/phy/phy-exynos-mipi-video.c b/drivers/phy/phy-exynos-mipi-video.c
index 0c5efab..7f13932 100644
--- a/drivers/phy/phy-exynos-mipi-video.c
+++ b/drivers/phy/phy-exynos-mipi-video.c
@@ -134,11 +134,6 @@
 	dev_set_drvdata(dev, state);
 	spin_lock_init(&state->slock);
 
-	phy_provider = devm_of_phy_provider_register(dev,
-					exynos_mipi_video_phy_xlate);
-	if (IS_ERR(phy_provider))
-		return PTR_ERR(phy_provider);
-
 	for (i = 0; i < EXYNOS_MIPI_PHYS_NUM; i++) {
 		struct phy *phy = devm_phy_create(dev,
 					&exynos_mipi_video_phy_ops, NULL);
@@ -152,6 +147,11 @@
 		phy_set_drvdata(phy, &state->phys[i]);
 	}
 
+	phy_provider = devm_of_phy_provider_register(dev,
+					exynos_mipi_video_phy_xlate);
+	if (IS_ERR(phy_provider))
+		return PTR_ERR(phy_provider);
+
 	return 0;
 }
 
diff --git a/drivers/phy/phy-mvebu-sata.c b/drivers/phy/phy-mvebu-sata.c
index d43786f..d70ecd6 100644
--- a/drivers/phy/phy-mvebu-sata.c
+++ b/drivers/phy/phy-mvebu-sata.c
@@ -99,17 +99,17 @@
 	if (IS_ERR(priv->clk))
 		return PTR_ERR(priv->clk);
 
-	phy_provider = devm_of_phy_provider_register(&pdev->dev,
-						     of_phy_simple_xlate);
-	if (IS_ERR(phy_provider))
-		return PTR_ERR(phy_provider);
-
 	phy = devm_phy_create(&pdev->dev, &phy_mvebu_sata_ops, NULL);
 	if (IS_ERR(phy))
 		return PTR_ERR(phy);
 
 	phy_set_drvdata(phy, priv);
 
+	phy_provider = devm_of_phy_provider_register(&pdev->dev,
+						     of_phy_simple_xlate);
+	if (IS_ERR(phy_provider))
+		return PTR_ERR(phy_provider);
+
 	/* The boot loader may of left it on. Turn it off. */
 	phy_mvebu_sata_power_off(phy);
 
diff --git a/drivers/phy/phy-omap-usb2.c b/drivers/phy/phy-omap-usb2.c
index bfc5c33..7699752 100644
--- a/drivers/phy/phy-omap-usb2.c
+++ b/drivers/phy/phy-omap-usb2.c
@@ -177,11 +177,6 @@
 	phy->phy.otg		= otg;
 	phy->phy.type		= USB_PHY_TYPE_USB2;
 
-	phy_provider = devm_of_phy_provider_register(phy->dev,
-			of_phy_simple_xlate);
-	if (IS_ERR(phy_provider))
-		return PTR_ERR(phy_provider);
-
 	control_node = of_parse_phandle(node, "ctrl-module", 0);
 	if (!control_node) {
 		dev_err(&pdev->dev, "Failed to get control device phandle\n");
@@ -214,6 +209,11 @@
 
 	phy_set_drvdata(generic_phy, phy);
 
+	phy_provider = devm_of_phy_provider_register(phy->dev,
+			of_phy_simple_xlate);
+	if (IS_ERR(phy_provider))
+		return PTR_ERR(phy_provider);
+
 	phy->wkupclk = devm_clk_get(phy->dev, "usb_phy_cm_clk32k");
 	if (IS_ERR(phy->wkupclk)) {
 		dev_err(&pdev->dev, "unable to get usb_phy_cm_clk32k\n");
diff --git a/drivers/phy/phy-twl4030-usb.c b/drivers/phy/phy-twl4030-usb.c
index daf65e6..c3ace1d 100644
--- a/drivers/phy/phy-twl4030-usb.c
+++ b/drivers/phy/phy-twl4030-usb.c
@@ -695,11 +695,6 @@
 	otg->set_host		= twl4030_set_host;
 	otg->set_peripheral	= twl4030_set_peripheral;
 
-	phy_provider = devm_of_phy_provider_register(twl->dev,
-		of_phy_simple_xlate);
-	if (IS_ERR(phy_provider))
-		return PTR_ERR(phy_provider);
-
 	phy = devm_phy_create(twl->dev, &ops, init_data);
 	if (IS_ERR(phy)) {
 		dev_dbg(&pdev->dev, "Failed to create PHY\n");
@@ -708,6 +703,11 @@
 
 	phy_set_drvdata(phy, twl);
 
+	phy_provider = devm_of_phy_provider_register(twl->dev,
+		of_phy_simple_xlate);
+	if (IS_ERR(phy_provider))
+		return PTR_ERR(phy_provider);
+
 	/* init spinlock for workqueue */
 	spin_lock_init(&twl->lock);
 
diff --git a/drivers/pwm/pwm-lp3943.c b/drivers/pwm/pwm-lp3943.c
index 8a843a0..a40b9c3 100644
--- a/drivers/pwm/pwm-lp3943.c
+++ b/drivers/pwm/pwm-lp3943.c
@@ -52,8 +52,10 @@
 		offset = pwm_map->output[i];
 
 		/* Return an error if the pin is already assigned */
-		if (test_and_set_bit(offset, &lp3943->pin_used))
+		if (test_and_set_bit(offset, &lp3943->pin_used)) {
+			kfree(pwm_map);
 			return ERR_PTR(-EBUSY);
+		}
 	}
 
 	return pwm_map;
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index 16a309e..d1ac4ca 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -1359,7 +1359,7 @@
 		goto found;
 	/* Don't log an error when called from regulator_get_optional() */
 	} else if (!have_full_constraints() || exclusive) {
-		dev_err(dev, "dummy supplies not allowed\n");
+		dev_warn(dev, "dummy supplies not allowed\n");
 	}
 
 	mutex_unlock(&regulator_list_mutex);
diff --git a/drivers/regulator/da9063-regulator.c b/drivers/regulator/da9063-regulator.c
index 56727eb..91e99a2 100644
--- a/drivers/regulator/da9063-regulator.c
+++ b/drivers/regulator/da9063-regulator.c
@@ -1,3 +1,4 @@
+
 /*
  * Regulator driver for DA9063 PMIC series
  *
@@ -60,7 +61,8 @@
 	.desc.ops = &da9063_ldo_ops, \
 	.desc.min_uV = (min_mV) * 1000, \
 	.desc.uV_step = (step_mV) * 1000, \
-	.desc.n_voltages = (((max_mV) - (min_mV))/(step_mV) + 1), \
+	.desc.n_voltages = (((max_mV) - (min_mV))/(step_mV) + 1 \
+		+ (DA9063_V##regl_name##_BIAS)), \
 	.desc.enable_reg = DA9063_REG_##regl_name##_CONT, \
 	.desc.enable_mask = DA9063_LDO_EN, \
 	.desc.vsel_reg = DA9063_REG_V##regl_name##_A, \
diff --git a/drivers/regulator/max14577.c b/drivers/regulator/max14577.c
index 186df87..e061952 100644
--- a/drivers/regulator/max14577.c
+++ b/drivers/regulator/max14577.c
@@ -166,9 +166,10 @@
 
 	ret = of_regulator_match(&pdev->dev, np, max14577_regulator_matches,
 			MAX14577_REG_MAX);
-	if (ret < 0) {
+	if (ret < 0)
 		dev_err(&pdev->dev, "Error parsing regulator init data: %d\n", ret);
-	}
+	else
+		ret = 0;
 
 	of_node_put(np);
 
diff --git a/drivers/regulator/s5m8767.c b/drivers/regulator/s5m8767.c
index d7164bb..d958dfa 100644
--- a/drivers/regulator/s5m8767.c
+++ b/drivers/regulator/s5m8767.c
@@ -535,7 +535,7 @@
 		return -ENODEV;
 	}
 
-	regulators_np = of_find_node_by_name(pmic_np, "regulators");
+	regulators_np = of_get_child_by_name(pmic_np, "regulators");
 	if (!regulators_np) {
 		dev_err(iodev->dev, "could not find regulators sub-node\n");
 		return -EINVAL;
@@ -591,6 +591,8 @@
 		rmode++;
 	}
 
+	of_node_put(regulators_np);
+
 	if (of_get_property(pmic_np, "s5m8767,pmic-buck2-uses-gpio-dvs", NULL)) {
 		pdata->buck2_gpiodvs = true;
 
diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c
index f6b9188..9f0ea6c 100644
--- a/drivers/s390/cio/chsc.c
+++ b/drivers/s390/cio/chsc.c
@@ -610,6 +610,7 @@
 		css_wait_for_slow_path();
 		for_each_subchannel_staged(__s390_process_res_acc, NULL,
 					   &link);
+		css_schedule_reprobe();
 	}
 }
 
diff --git a/drivers/s390/crypto/zcrypt_msgtype6.c b/drivers/s390/crypto/zcrypt_msgtype6.c
index dc542e0..0bc91e4 100644
--- a/drivers/s390/crypto/zcrypt_msgtype6.c
+++ b/drivers/s390/crypto/zcrypt_msgtype6.c
@@ -311,7 +311,7 @@
 	} __packed * msg = ap_msg->message;
 
 	int rcblen = CEIL4(xcRB->request_control_blk_length);
-	int replylen;
+	int replylen, req_sumlen, resp_sumlen;
 	char *req_data = ap_msg->message + sizeof(struct type6_hdr) + rcblen;
 	char *function_code;
 
@@ -321,12 +321,34 @@
 		xcRB->request_data_length;
 	if (ap_msg->length > MSGTYPE06_MAX_MSG_SIZE)
 		return -EINVAL;
+
+	/* Overflow check
+	   sum must be greater (or equal) than the largest operand */
+	req_sumlen = CEIL4(xcRB->request_control_blk_length) +
+			xcRB->request_data_length;
+	if ((CEIL4(xcRB->request_control_blk_length) <=
+						xcRB->request_data_length) ?
+		(req_sumlen < xcRB->request_data_length) :
+		(req_sumlen < CEIL4(xcRB->request_control_blk_length))) {
+		return -EINVAL;
+	}
+
 	replylen = sizeof(struct type86_fmt2_msg) +
 		CEIL4(xcRB->reply_control_blk_length) +
 		xcRB->reply_data_length;
 	if (replylen > MSGTYPE06_MAX_MSG_SIZE)
 		return -EINVAL;
 
+	/* Overflow check
+	   sum must be greater (or equal) than the largest operand */
+	resp_sumlen = CEIL4(xcRB->reply_control_blk_length) +
+			xcRB->reply_data_length;
+	if ((CEIL4(xcRB->reply_control_blk_length) <= xcRB->reply_data_length) ?
+		(resp_sumlen < xcRB->reply_data_length) :
+		(resp_sumlen < CEIL4(xcRB->reply_control_blk_length))) {
+		return -EINVAL;
+	}
+
 	/* prepare type6 header */
 	msg->hdr = static_type6_hdrX;
 	memcpy(msg->hdr.agent_id , &(xcRB->agent_ID), sizeof(xcRB->agent_ID));
diff --git a/drivers/sbus/char/jsflash.c b/drivers/sbus/char/jsflash.c
index 6b4678a..4ccb5d8 100644
--- a/drivers/sbus/char/jsflash.c
+++ b/drivers/sbus/char/jsflash.c
@@ -507,7 +507,6 @@
 	}
 
 	/* Let us be really paranoid for modifications to probing code. */
-	/* extern enum sparc_cpu sparc_cpu_model; */ /* in <asm/system.h> */
 	if (sparc_cpu_model != sun4m) {
 		/* We must be on sun4m because we use MMU Bypass ASI. */
 		return -ENXIO;
diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c
index 2eb97d7..0cb7307 100644
--- a/drivers/scsi/qla2xxx/qla_target.c
+++ b/drivers/scsi/qla2xxx/qla_target.c
@@ -790,17 +790,32 @@
 }
 
 /* Called by tcm_qla2xxx configfs code */
-void qlt_stop_phase1(struct qla_tgt *tgt)
+int qlt_stop_phase1(struct qla_tgt *tgt)
 {
 	struct scsi_qla_host *vha = tgt->vha;
 	struct qla_hw_data *ha = tgt->ha;
 	unsigned long flags;
 
+	mutex_lock(&qla_tgt_mutex);
+	if (!vha->fc_vport) {
+		struct Scsi_Host *sh = vha->host;
+		struct fc_host_attrs *fc_host = shost_to_fc_host(sh);
+		bool npiv_vports;
+
+		spin_lock_irqsave(sh->host_lock, flags);
+		npiv_vports = (fc_host->npiv_vports_inuse);
+		spin_unlock_irqrestore(sh->host_lock, flags);
+
+		if (npiv_vports) {
+			mutex_unlock(&qla_tgt_mutex);
+			return -EPERM;
+		}
+	}
 	if (tgt->tgt_stop || tgt->tgt_stopped) {
 		ql_dbg(ql_dbg_tgt_mgt, vha, 0xf04e,
 		    "Already in tgt->tgt_stop or tgt_stopped state\n");
-		dump_stack();
-		return;
+		mutex_unlock(&qla_tgt_mutex);
+		return -EPERM;
 	}
 
 	ql_dbg(ql_dbg_tgt, vha, 0xe003, "Stopping target for host %ld(%p)\n",
@@ -815,6 +830,7 @@
 	qlt_clear_tgt_db(tgt, true);
 	spin_unlock_irqrestore(&ha->hardware_lock, flags);
 	mutex_unlock(&vha->vha_tgt.tgt_mutex);
+	mutex_unlock(&qla_tgt_mutex);
 
 	flush_delayed_work(&tgt->sess_del_work);
 
@@ -841,6 +857,7 @@
 
 	/* Wait for sessions to clear out (just in case) */
 	wait_event(tgt->waitQ, test_tgt_sess_count(tgt));
+	return 0;
 }
 EXPORT_SYMBOL(qlt_stop_phase1);
 
@@ -3185,7 +3202,8 @@
 		ql_dbg(ql_dbg_tgt_mgt, vha, 0xf02c,
 		    "SRR cmd %p (se_cmd %p, tag %d, op %x), "
 		    "sg_cnt=%d, offset=%d", cmd, &cmd->se_cmd, cmd->tag,
-		    se_cmd->t_task_cdb[0], cmd->sg_cnt, cmd->offset);
+		    se_cmd->t_task_cdb ? se_cmd->t_task_cdb[0] : 0,
+		    cmd->sg_cnt, cmd->offset);
 
 		qlt_handle_srr(vha, sctio, imm);
 
@@ -4181,6 +4199,9 @@
 	tgt->datasegs_per_cmd = QLA_TGT_DATASEGS_PER_CMD_24XX;
 	tgt->datasegs_per_cont = QLA_TGT_DATASEGS_PER_CONT_24XX;
 
+	if (base_vha->fc_vport)
+		return 0;
+
 	mutex_lock(&qla_tgt_mutex);
 	list_add_tail(&tgt->tgt_list_entry, &qla_tgt_glist);
 	mutex_unlock(&qla_tgt_mutex);
@@ -4194,6 +4215,10 @@
 	if (!vha->vha_tgt.qla_tgt)
 		return 0;
 
+	if (vha->fc_vport) {
+		qlt_release(vha->vha_tgt.qla_tgt);
+		return 0;
+	}
 	mutex_lock(&qla_tgt_mutex);
 	list_del(&vha->vha_tgt.qla_tgt->tgt_list_entry);
 	mutex_unlock(&qla_tgt_mutex);
@@ -4265,6 +4290,12 @@
 			spin_unlock_irqrestore(&ha->hardware_lock, flags);
 			continue;
 		}
+		if (tgt->tgt_stop) {
+			pr_debug("MODE_TARGET in shutdown on qla2xxx(%d)\n",
+				 host->host_no);
+			spin_unlock_irqrestore(&ha->hardware_lock, flags);
+			continue;
+		}
 		spin_unlock_irqrestore(&ha->hardware_lock, flags);
 
 		if (!scsi_host_get(host)) {
@@ -4279,12 +4310,11 @@
 			scsi_host_put(host);
 			continue;
 		}
-		mutex_unlock(&qla_tgt_mutex);
-
 		rc = (*callback)(vha, target_lport_ptr, npiv_wwpn, npiv_wwnn);
 		if (rc != 0)
 			scsi_host_put(host);
 
+		mutex_unlock(&qla_tgt_mutex);
 		return rc;
 	}
 	mutex_unlock(&qla_tgt_mutex);
diff --git a/drivers/scsi/qla2xxx/qla_target.h b/drivers/scsi/qla2xxx/qla_target.h
index 66e755c..ce33d8c 100644
--- a/drivers/scsi/qla2xxx/qla_target.h
+++ b/drivers/scsi/qla2xxx/qla_target.h
@@ -1001,7 +1001,7 @@
 extern void qlt_probe_one_stage1(struct scsi_qla_host *, struct qla_hw_data *);
 extern int qlt_mem_alloc(struct qla_hw_data *);
 extern void qlt_mem_free(struct qla_hw_data *);
-extern void qlt_stop_phase1(struct qla_tgt *);
+extern int qlt_stop_phase1(struct qla_tgt *);
 extern void qlt_stop_phase2(struct qla_tgt *);
 extern irqreturn_t qla83xx_msix_atio_q(int, void *);
 extern void qlt_83xx_iospace_config(struct qla_hw_data *);
diff --git a/drivers/scsi/qla2xxx/tcm_qla2xxx.c b/drivers/scsi/qla2xxx/tcm_qla2xxx.c
index 75a141b..788c4fe 100644
--- a/drivers/scsi/qla2xxx/tcm_qla2xxx.c
+++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.c
@@ -182,20 +182,6 @@
 	return 0;
 }
 
-static ssize_t tcm_qla2xxx_npiv_format_wwn(char *buf, size_t len,
-					u64 wwpn, u64 wwnn)
-{
-	u8 b[8], b2[8];
-
-	put_unaligned_be64(wwpn, b);
-	put_unaligned_be64(wwnn, b2);
-	return snprintf(buf, len,
-		"%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x,"
-		"%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x",
-		b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7],
-		b2[0], b2[1], b2[2], b2[3], b2[4], b2[5], b2[6], b2[7]);
-}
-
 static char *tcm_qla2xxx_npiv_get_fabric_name(void)
 {
 	return "qla2xxx_npiv";
@@ -227,15 +213,6 @@
 	return lport->lport_naa_name;
 }
 
-static char *tcm_qla2xxx_npiv_get_fabric_wwn(struct se_portal_group *se_tpg)
-{
-	struct tcm_qla2xxx_tpg *tpg = container_of(se_tpg,
-				struct tcm_qla2xxx_tpg, se_tpg);
-	struct tcm_qla2xxx_lport *lport = tpg->lport;
-
-	return &lport->lport_npiv_name[0];
-}
-
 static u16 tcm_qla2xxx_get_tag(struct se_portal_group *se_tpg)
 {
 	struct tcm_qla2xxx_tpg *tpg = container_of(se_tpg,
@@ -941,15 +918,41 @@
 			atomic_read(&tpg->lport_tpg_enabled));
 }
 
+static void tcm_qla2xxx_depend_tpg(struct work_struct *work)
+{
+	struct tcm_qla2xxx_tpg *base_tpg = container_of(work,
+				struct tcm_qla2xxx_tpg, tpg_base_work);
+	struct se_portal_group *se_tpg = &base_tpg->se_tpg;
+	struct scsi_qla_host *base_vha = base_tpg->lport->qla_vha;
+
+	if (!configfs_depend_item(se_tpg->se_tpg_tfo->tf_subsys,
+				  &se_tpg->tpg_group.cg_item)) {
+		atomic_set(&base_tpg->lport_tpg_enabled, 1);
+		qlt_enable_vha(base_vha);
+	}
+	complete(&base_tpg->tpg_base_comp);
+}
+
+static void tcm_qla2xxx_undepend_tpg(struct work_struct *work)
+{
+	struct tcm_qla2xxx_tpg *base_tpg = container_of(work,
+				struct tcm_qla2xxx_tpg, tpg_base_work);
+	struct se_portal_group *se_tpg = &base_tpg->se_tpg;
+	struct scsi_qla_host *base_vha = base_tpg->lport->qla_vha;
+
+	if (!qlt_stop_phase1(base_vha->vha_tgt.qla_tgt)) {
+		atomic_set(&base_tpg->lport_tpg_enabled, 0);
+		configfs_undepend_item(se_tpg->se_tpg_tfo->tf_subsys,
+				       &se_tpg->tpg_group.cg_item);
+	}
+	complete(&base_tpg->tpg_base_comp);
+}
+
 static ssize_t tcm_qla2xxx_tpg_store_enable(
 	struct se_portal_group *se_tpg,
 	const char *page,
 	size_t count)
 {
-	struct se_wwn *se_wwn = se_tpg->se_tpg_wwn;
-	struct tcm_qla2xxx_lport *lport = container_of(se_wwn,
-			struct tcm_qla2xxx_lport, lport_wwn);
-	struct scsi_qla_host *vha = lport->qla_vha;
 	struct tcm_qla2xxx_tpg *tpg = container_of(se_tpg,
 			struct tcm_qla2xxx_tpg, se_tpg);
 	unsigned long op;
@@ -964,19 +967,28 @@
 		pr_err("Illegal value for tpg_enable: %lu\n", op);
 		return -EINVAL;
 	}
+	if (op) {
+		if (atomic_read(&tpg->lport_tpg_enabled))
+			return -EEXIST;
+
+		INIT_WORK(&tpg->tpg_base_work, tcm_qla2xxx_depend_tpg);
+	} else {
+		if (!atomic_read(&tpg->lport_tpg_enabled))
+			return count;
+
+		INIT_WORK(&tpg->tpg_base_work, tcm_qla2xxx_undepend_tpg);
+	}
+	init_completion(&tpg->tpg_base_comp);
+	schedule_work(&tpg->tpg_base_work);
+	wait_for_completion(&tpg->tpg_base_comp);
 
 	if (op) {
-		atomic_set(&tpg->lport_tpg_enabled, 1);
-		qlt_enable_vha(vha);
-	} else {
-		if (!vha->vha_tgt.qla_tgt) {
-			pr_err("struct qla_hw_data *vha->vha_tgt.qla_tgt is NULL\n");
+		if (!atomic_read(&tpg->lport_tpg_enabled))
 			return -ENODEV;
-		}
-		atomic_set(&tpg->lport_tpg_enabled, 0);
-		qlt_stop_phase1(vha->vha_tgt.qla_tgt);
+	} else {
+		if (atomic_read(&tpg->lport_tpg_enabled))
+			return -EPERM;
 	}
-
 	return count;
 }
 
@@ -1053,11 +1065,64 @@
 	/*
 	 * Clear local TPG=1 pointer for non NPIV mode.
 	 */
-		lport->tpg_1 = NULL;
-
+	lport->tpg_1 = NULL;
 	kfree(tpg);
 }
 
+static ssize_t tcm_qla2xxx_npiv_tpg_show_enable(
+	struct se_portal_group *se_tpg,
+	char *page)
+{
+	return tcm_qla2xxx_tpg_show_enable(se_tpg, page);
+}
+
+static ssize_t tcm_qla2xxx_npiv_tpg_store_enable(
+	struct se_portal_group *se_tpg,
+	const char *page,
+	size_t count)
+{
+	struct se_wwn *se_wwn = se_tpg->se_tpg_wwn;
+	struct tcm_qla2xxx_lport *lport = container_of(se_wwn,
+			struct tcm_qla2xxx_lport, lport_wwn);
+	struct scsi_qla_host *vha = lport->qla_vha;
+	struct tcm_qla2xxx_tpg *tpg = container_of(se_tpg,
+			struct tcm_qla2xxx_tpg, se_tpg);
+	unsigned long op;
+	int rc;
+
+	rc = kstrtoul(page, 0, &op);
+	if (rc < 0) {
+		pr_err("kstrtoul() returned %d\n", rc);
+		return -EINVAL;
+	}
+	if ((op != 1) && (op != 0)) {
+		pr_err("Illegal value for tpg_enable: %lu\n", op);
+		return -EINVAL;
+	}
+	if (op) {
+		if (atomic_read(&tpg->lport_tpg_enabled))
+			return -EEXIST;
+
+		atomic_set(&tpg->lport_tpg_enabled, 1);
+		qlt_enable_vha(vha);
+	} else {
+		if (!atomic_read(&tpg->lport_tpg_enabled))
+			return count;
+
+		atomic_set(&tpg->lport_tpg_enabled, 0);
+		qlt_stop_phase1(vha->vha_tgt.qla_tgt);
+	}
+
+	return count;
+}
+
+TF_TPG_BASE_ATTR(tcm_qla2xxx_npiv, enable, S_IRUGO | S_IWUSR);
+
+static struct configfs_attribute *tcm_qla2xxx_npiv_tpg_attrs[] = {
+        &tcm_qla2xxx_npiv_tpg_enable.attr,
+        NULL,
+};
+
 static struct se_portal_group *tcm_qla2xxx_npiv_make_tpg(
 	struct se_wwn *wwn,
 	struct config_group *group,
@@ -1650,6 +1715,9 @@
 	struct scsi_qla_host *npiv_vha;
 	struct tcm_qla2xxx_lport *lport =
 			(struct tcm_qla2xxx_lport *)target_lport_ptr;
+	struct tcm_qla2xxx_lport *base_lport =
+			(struct tcm_qla2xxx_lport *)base_vha->vha_tgt.target_lport_ptr;
+	struct tcm_qla2xxx_tpg *base_tpg;
 	struct fc_vport_identifiers vport_id;
 
 	if (!qla_tgt_mode_enabled(base_vha)) {
@@ -1657,6 +1725,13 @@
 		return -EPERM;
 	}
 
+	if (!base_lport || !base_lport->tpg_1 ||
+	    !atomic_read(&base_lport->tpg_1->lport_tpg_enabled)) {
+		pr_err("qla2xxx base_lport or tpg_1 not available\n");
+		return -EPERM;
+	}
+	base_tpg = base_lport->tpg_1;
+
 	memset(&vport_id, 0, sizeof(vport_id));
 	vport_id.port_name = npiv_wwpn;
 	vport_id.node_name = npiv_wwnn;
@@ -1675,7 +1750,6 @@
 	npiv_vha = (struct scsi_qla_host *)vport->dd_data;
 	npiv_vha->vha_tgt.target_lport_ptr = target_lport_ptr;
 	lport->qla_vha = npiv_vha;
-
 	scsi_host_get(npiv_vha->host);
 	return 0;
 }
@@ -1714,8 +1788,6 @@
 	}
 	lport->lport_npiv_wwpn = npiv_wwpn;
 	lport->lport_npiv_wwnn = npiv_wwnn;
-	tcm_qla2xxx_npiv_format_wwn(&lport->lport_npiv_name[0],
-			TCM_QLA2XXX_NAMELEN, npiv_wwpn, npiv_wwnn);
 	sprintf(lport->lport_naa_name, "naa.%016llx", (unsigned long long) npiv_wwpn);
 
 	ret = tcm_qla2xxx_init_lport(lport);
@@ -1824,7 +1896,7 @@
 static struct target_core_fabric_ops tcm_qla2xxx_npiv_ops = {
 	.get_fabric_name		= tcm_qla2xxx_npiv_get_fabric_name,
 	.get_fabric_proto_ident		= tcm_qla2xxx_get_fabric_proto_ident,
-	.tpg_get_wwn			= tcm_qla2xxx_npiv_get_fabric_wwn,
+	.tpg_get_wwn			= tcm_qla2xxx_get_fabric_wwn,
 	.tpg_get_tag			= tcm_qla2xxx_get_tag,
 	.tpg_get_default_depth		= tcm_qla2xxx_get_default_depth,
 	.tpg_get_pr_transport_id	= tcm_qla2xxx_get_pr_transport_id,
@@ -1935,7 +2007,7 @@
 	 */
 	npiv_fabric->tf_cit_tmpl.tfc_wwn_cit.ct_attrs = tcm_qla2xxx_wwn_attrs;
 	npiv_fabric->tf_cit_tmpl.tfc_tpg_base_cit.ct_attrs =
-	    tcm_qla2xxx_tpg_attrs;
+	    tcm_qla2xxx_npiv_tpg_attrs;
 	npiv_fabric->tf_cit_tmpl.tfc_tpg_attrib_cit.ct_attrs = NULL;
 	npiv_fabric->tf_cit_tmpl.tfc_tpg_param_cit.ct_attrs = NULL;
 	npiv_fabric->tf_cit_tmpl.tfc_tpg_np_base_cit.ct_attrs = NULL;
diff --git a/drivers/scsi/qla2xxx/tcm_qla2xxx.h b/drivers/scsi/qla2xxx/tcm_qla2xxx.h
index 275d8b9..33aaac8 100644
--- a/drivers/scsi/qla2xxx/tcm_qla2xxx.h
+++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.h
@@ -4,8 +4,6 @@
 #define TCM_QLA2XXX_VERSION	"v0.1"
 /* length of ASCII WWPNs including pad */
 #define TCM_QLA2XXX_NAMELEN	32
-/* lenth of ASCII NPIV 'WWPN+WWNN' including pad */
-#define TCM_QLA2XXX_NPIV_NAMELEN 66
 
 #include "qla_target.h"
 
@@ -43,6 +41,9 @@
 	struct tcm_qla2xxx_tpg_attrib tpg_attrib;
 	/* Returned by tcm_qla2xxx_make_tpg() */
 	struct se_portal_group se_tpg;
+	/* Items for dealing with configfs_depend_item */
+	struct completion tpg_base_comp;
+	struct work_struct tpg_base_work;
 };
 
 struct tcm_qla2xxx_fc_loopid {
@@ -62,8 +63,6 @@
 	char lport_name[TCM_QLA2XXX_NAMELEN];
 	/* ASCII formatted naa WWPN for VPD page 83 etc */
 	char lport_naa_name[TCM_QLA2XXX_NAMELEN];
-	/* ASCII formatted WWPN+WWNN for NPIV FC Target Lport */
-	char lport_npiv_name[TCM_QLA2XXX_NPIV_NAMELEN];
 	/* map for fc_port pointers in 24-bit FC Port ID space */
 	struct btree_head32 lport_fcport_map;
 	/* vmalloc-ed memory for fc_port pointers for 16-bit FC loop ID */
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index 7bd7f0d..62ec84b 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -1684,7 +1684,7 @@
 
 	host_dev = scsi_get_device(shost);
 	if (host_dev && host_dev->dma_mask)
-		bounce_limit = dma_max_pfn(host_dev) << PAGE_SHIFT;
+		bounce_limit = (u64)dma_max_pfn(host_dev) << PAGE_SHIFT;
 
 	return bounce_limit;
 }
diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig
index babb1cf..47cf175 100644
--- a/drivers/staging/Kconfig
+++ b/drivers/staging/Kconfig
@@ -34,8 +34,6 @@
 
 source "drivers/staging/wlan-ng/Kconfig"
 
-source "drivers/staging/echo/Kconfig"
-
 source "drivers/staging/comedi/Kconfig"
 
 source "drivers/staging/olpc_dcon/Kconfig"
@@ -82,8 +80,6 @@
 
 source "drivers/staging/wlags49_h25/Kconfig"
 
-source "drivers/staging/sm7xxfb/Kconfig"
-
 source "drivers/staging/crystalhd/Kconfig"
 
 source "drivers/staging/cxt1e1/Kconfig"
@@ -128,8 +124,6 @@
 
 source "drivers/staging/dgrp/Kconfig"
 
-source "drivers/staging/sb105x/Kconfig"
-
 source "drivers/staging/fwserial/Kconfig"
 
 source "drivers/staging/goldfish/Kconfig"
@@ -150,4 +144,6 @@
 
 source "drivers/staging/nokia_h4p/Kconfig"
 
+source "drivers/staging/unisys/Kconfig"
+
 endif # STAGING
diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile
index 2c4949a..d12f618 100644
--- a/drivers/staging/Makefile
+++ b/drivers/staging/Makefile
@@ -9,7 +9,6 @@
 obj-$(CONFIG_USBIP_CORE)	+= usbip/
 obj-$(CONFIG_W35UND)		+= winbond/
 obj-$(CONFIG_PRISM2_USB)	+= wlan-ng/
-obj-$(CONFIG_ECHO)		+= echo/
 obj-$(CONFIG_COMEDI)		+= comedi/
 obj-$(CONFIG_FB_OLPC_DCON)	+= olpc_dcon/
 obj-$(CONFIG_PANEL)		+= panel/
@@ -35,7 +34,6 @@
 obj-$(CONFIG_IIO)		+= iio/
 obj-$(CONFIG_WLAGS49_H2)	+= wlags49_h2/
 obj-$(CONFIG_WLAGS49_H25)	+= wlags49_h25/
-obj-$(CONFIG_FB_SM7XX)		+= sm7xxfb/
 obj-$(CONFIG_CRYSTALHD)		+= crystalhd/
 obj-$(CONFIG_CXT1E1)		+= cxt1e1/
 obj-$(CONFIG_FB_XGI)		+= xgifb/
@@ -57,7 +55,6 @@
 obj-$(CONFIG_CED1401)		+= ced1401/
 obj-$(CONFIG_DRM_IMX)		+= imx-drm/
 obj-$(CONFIG_DGRP)		+= dgrp/
-obj-$(CONFIG_SB105X)		+= sb105x/
 obj-$(CONFIG_FIREWIRE_SERIAL)	+= fwserial/
 obj-$(CONFIG_GOLDFISH)		+= goldfish/
 obj-$(CONFIG_LUSTRE_FS)		+= lustre/
@@ -67,3 +64,4 @@
 obj-$(CONFIG_MTD_SPINAND_MT29F)	+= mt29f_spinand/
 obj-$(CONFIG_GS_FPGABOOT)	+= gs_fpgaboot/
 obj-$(CONFIG_BT_NOKIA_H4P)	+= nokia_h4p/
+obj-$(CONFIG_UNISYSSPAR)	+= unisys/
diff --git a/drivers/staging/android/Kconfig b/drivers/staging/android/Kconfig
index b91c758..ab28d2b 100644
--- a/drivers/staging/android/Kconfig
+++ b/drivers/staging/android/Kconfig
@@ -20,6 +20,19 @@
 	  Android process, using Binder to identify, invoke and pass arguments
 	  between said processes.
 
+config ANDROID_BINDER_IPC_32BIT
+	bool
+	depends on !64BIT && ANDROID_BINDER_IPC
+	default y
+	---help---
+	  The Binder API has been changed to support both 32 and 64bit
+	  applications in a mixed environment.
+
+	  Enable this to support an old 32-bit Android user-space (v4.4 and
+	  earlier).
+
+	  Note that enabling this will break newer Android user-space.
+
 config ASHMEM
 	bool "Enable the Anonymous Shared Memory Subsystem"
 	default n
diff --git a/drivers/staging/android/binder.c b/drivers/staging/android/binder.c
index eaec1da..cfe4bc8 100644
--- a/drivers/staging/android/binder.c
+++ b/drivers/staging/android/binder.c
@@ -228,8 +228,8 @@
 	int internal_strong_refs;
 	int local_weak_refs;
 	int local_strong_refs;
-	void __user *ptr;
-	void __user *cookie;
+	binder_uintptr_t ptr;
+	binder_uintptr_t cookie;
 	unsigned has_strong_ref:1;
 	unsigned pending_strong_ref:1;
 	unsigned has_weak_ref:1;
@@ -242,7 +242,7 @@
 
 struct binder_ref_death {
 	struct binder_work work;
-	void __user *cookie;
+	binder_uintptr_t cookie;
 };
 
 struct binder_ref {
@@ -515,14 +515,14 @@
 }
 
 static struct binder_buffer *binder_buffer_lookup(struct binder_proc *proc,
-						  void __user *user_ptr)
+						  uintptr_t user_ptr)
 {
 	struct rb_node *n = proc->allocated_buffers.rb_node;
 	struct binder_buffer *buffer;
 	struct binder_buffer *kern_ptr;
 
-	kern_ptr = user_ptr - proc->user_buffer_offset
-		- offsetof(struct binder_buffer, data);
+	kern_ptr = (struct binder_buffer *)(user_ptr - proc->user_buffer_offset
+		- offsetof(struct binder_buffer, data));
 
 	while (n) {
 		buffer = rb_entry(n, struct binder_buffer, rb_node);
@@ -856,7 +856,7 @@
 }
 
 static struct binder_node *binder_get_node(struct binder_proc *proc,
-					   void __user *ptr)
+					   binder_uintptr_t ptr)
 {
 	struct rb_node *n = proc->nodes.rb_node;
 	struct binder_node *node;
@@ -875,8 +875,8 @@
 }
 
 static struct binder_node *binder_new_node(struct binder_proc *proc,
-					   void __user *ptr,
-					   void __user *cookie)
+					   binder_uintptr_t ptr,
+					   binder_uintptr_t cookie)
 {
 	struct rb_node **p = &proc->nodes.rb_node;
 	struct rb_node *parent = NULL;
@@ -908,9 +908,9 @@
 	INIT_LIST_HEAD(&node->work.entry);
 	INIT_LIST_HEAD(&node->async_todo);
 	binder_debug(BINDER_DEBUG_INTERNAL_REFS,
-		     "%d:%d node %d u%p c%p created\n",
+		     "%d:%d node %d u%016llx c%016llx created\n",
 		     proc->pid, current->pid, node->debug_id,
-		     node->ptr, node->cookie);
+		     (u64)node->ptr, (u64)node->cookie);
 	return node;
 }
 
@@ -1226,9 +1226,9 @@
 
 static void binder_transaction_buffer_release(struct binder_proc *proc,
 					      struct binder_buffer *buffer,
-					      size_t *failed_at)
+					      binder_size_t *failed_at)
 {
-	size_t *offp, *off_end;
+	binder_size_t *offp, *off_end;
 	int debug_id = buffer->debug_id;
 
 	binder_debug(BINDER_DEBUG_TRANSACTION,
@@ -1239,7 +1239,8 @@
 	if (buffer->target_node)
 		binder_dec_node(buffer->target_node, 1, 0);
 
-	offp = (size_t *)(buffer->data + ALIGN(buffer->data_size, sizeof(void *)));
+	offp = (binder_size_t *)(buffer->data +
+				 ALIGN(buffer->data_size, sizeof(void *)));
 	if (failed_at)
 		off_end = failed_at;
 	else
@@ -1249,8 +1250,8 @@
 		if (*offp > buffer->data_size - sizeof(*fp) ||
 		    buffer->data_size < sizeof(*fp) ||
 		    !IS_ALIGNED(*offp, sizeof(u32))) {
-			pr_err("transaction release %d bad offset %zd, size %zd\n",
-			 debug_id, *offp, buffer->data_size);
+			pr_err("transaction release %d bad offset %lld, size %zd\n",
+			       debug_id, (u64)*offp, buffer->data_size);
 			continue;
 		}
 		fp = (struct flat_binder_object *)(buffer->data + *offp);
@@ -1259,13 +1260,13 @@
 		case BINDER_TYPE_WEAK_BINDER: {
 			struct binder_node *node = binder_get_node(proc, fp->binder);
 			if (node == NULL) {
-				pr_err("transaction release %d bad node %p\n",
-					debug_id, fp->binder);
+				pr_err("transaction release %d bad node %016llx\n",
+				       debug_id, (u64)fp->binder);
 				break;
 			}
 			binder_debug(BINDER_DEBUG_TRANSACTION,
-				     "        node %d u%p\n",
-				     node->debug_id, node->ptr);
+				     "        node %d u%016llx\n",
+				     node->debug_id, (u64)node->ptr);
 			binder_dec_node(node, fp->type == BINDER_TYPE_BINDER, 0);
 		} break;
 		case BINDER_TYPE_HANDLE:
@@ -1303,7 +1304,7 @@
 {
 	struct binder_transaction *t;
 	struct binder_work *tcomplete;
-	size_t *offp, *off_end;
+	binder_size_t *offp, *off_end;
 	struct binder_proc *target_proc;
 	struct binder_thread *target_thread = NULL;
 	struct binder_node *target_node = NULL;
@@ -1432,18 +1433,20 @@
 
 	if (reply)
 		binder_debug(BINDER_DEBUG_TRANSACTION,
-			     "%d:%d BC_REPLY %d -> %d:%d, data %p-%p size %zd-%zd\n",
+			     "%d:%d BC_REPLY %d -> %d:%d, data %016llx-%016llx size %lld-%lld\n",
 			     proc->pid, thread->pid, t->debug_id,
 			     target_proc->pid, target_thread->pid,
-			     tr->data.ptr.buffer, tr->data.ptr.offsets,
-			     tr->data_size, tr->offsets_size);
+			     (u64)tr->data.ptr.buffer,
+			     (u64)tr->data.ptr.offsets,
+			     (u64)tr->data_size, (u64)tr->offsets_size);
 	else
 		binder_debug(BINDER_DEBUG_TRANSACTION,
-			     "%d:%d BC_TRANSACTION %d -> %d - node %d, data %p-%p size %zd-%zd\n",
+			     "%d:%d BC_TRANSACTION %d -> %d - node %d, data %016llx-%016llx size %lld-%lld\n",
 			     proc->pid, thread->pid, t->debug_id,
 			     target_proc->pid, target_node->debug_id,
-			     tr->data.ptr.buffer, tr->data.ptr.offsets,
-			     tr->data_size, tr->offsets_size);
+			     (u64)tr->data.ptr.buffer,
+			     (u64)tr->data.ptr.offsets,
+			     (u64)tr->data_size, (u64)tr->offsets_size);
 
 	if (!reply && !(tr->flags & TF_ONE_WAY))
 		t->from = thread;
@@ -1472,23 +1475,26 @@
 	if (target_node)
 		binder_inc_node(target_node, 1, 0, NULL);
 
-	offp = (size_t *)(t->buffer->data + ALIGN(tr->data_size, sizeof(void *)));
+	offp = (binder_size_t *)(t->buffer->data +
+				 ALIGN(tr->data_size, sizeof(void *)));
 
-	if (copy_from_user(t->buffer->data, tr->data.ptr.buffer, tr->data_size)) {
+	if (copy_from_user(t->buffer->data, (const void __user *)(uintptr_t)
+			   tr->data.ptr.buffer, tr->data_size)) {
 		binder_user_error("%d:%d got transaction with invalid data ptr\n",
 				proc->pid, thread->pid);
 		return_error = BR_FAILED_REPLY;
 		goto err_copy_data_failed;
 	}
-	if (copy_from_user(offp, tr->data.ptr.offsets, tr->offsets_size)) {
+	if (copy_from_user(offp, (const void __user *)(uintptr_t)
+			   tr->data.ptr.offsets, tr->offsets_size)) {
 		binder_user_error("%d:%d got transaction with invalid offsets ptr\n",
 				proc->pid, thread->pid);
 		return_error = BR_FAILED_REPLY;
 		goto err_copy_data_failed;
 	}
-	if (!IS_ALIGNED(tr->offsets_size, sizeof(size_t))) {
-		binder_user_error("%d:%d got transaction with invalid offsets size, %zd\n",
-				proc->pid, thread->pid, tr->offsets_size);
+	if (!IS_ALIGNED(tr->offsets_size, sizeof(binder_size_t))) {
+		binder_user_error("%d:%d got transaction with invalid offsets size, %lld\n",
+				proc->pid, thread->pid, (u64)tr->offsets_size);
 		return_error = BR_FAILED_REPLY;
 		goto err_bad_offset;
 	}
@@ -1498,8 +1504,8 @@
 		if (*offp > t->buffer->data_size - sizeof(*fp) ||
 		    t->buffer->data_size < sizeof(*fp) ||
 		    !IS_ALIGNED(*offp, sizeof(u32))) {
-			binder_user_error("%d:%d got transaction with invalid offset, %zd\n",
-					proc->pid, thread->pid, *offp);
+			binder_user_error("%d:%d got transaction with invalid offset, %lld\n",
+					  proc->pid, thread->pid, (u64)*offp);
 			return_error = BR_FAILED_REPLY;
 			goto err_bad_offset;
 		}
@@ -1519,10 +1525,10 @@
 				node->accept_fds = !!(fp->flags & FLAT_BINDER_FLAG_ACCEPTS_FDS);
 			}
 			if (fp->cookie != node->cookie) {
-				binder_user_error("%d:%d sending u%p node %d, cookie mismatch %p != %p\n",
+				binder_user_error("%d:%d sending u%016llx node %d, cookie mismatch %016llx != %016llx\n",
 					proc->pid, thread->pid,
-					fp->binder, node->debug_id,
-					fp->cookie, node->cookie);
+					(u64)fp->binder, node->debug_id,
+					(u64)fp->cookie, (u64)node->cookie);
 				goto err_binder_get_ref_for_node_failed;
 			}
 			ref = binder_get_ref_for_node(target_proc, node);
@@ -1540,9 +1546,9 @@
 
 			trace_binder_transaction_node_to_ref(t, node, ref);
 			binder_debug(BINDER_DEBUG_TRANSACTION,
-				     "        node %d u%p -> ref %d desc %d\n",
-				     node->debug_id, node->ptr, ref->debug_id,
-				     ref->desc);
+				     "        node %d u%016llx -> ref %d desc %d\n",
+				     node->debug_id, (u64)node->ptr,
+				     ref->debug_id, ref->desc);
 		} break;
 		case BINDER_TYPE_HANDLE:
 		case BINDER_TYPE_WEAK_HANDLE: {
@@ -1564,9 +1570,9 @@
 				binder_inc_node(ref->node, fp->type == BINDER_TYPE_BINDER, 0, NULL);
 				trace_binder_transaction_ref_to_node(t, ref);
 				binder_debug(BINDER_DEBUG_TRANSACTION,
-					     "        ref %d desc %d -> node %d u%p\n",
+					     "        ref %d desc %d -> node %d u%016llx\n",
 					     ref->debug_id, ref->desc, ref->node->debug_id,
-					     ref->node->ptr);
+					     (u64)ref->node->ptr);
 			} else {
 				struct binder_ref *new_ref;
 				new_ref = binder_get_ref_for_node(target_proc, ref->node);
@@ -1682,9 +1688,9 @@
 err_invalid_target_handle:
 err_no_context_mgr_node:
 	binder_debug(BINDER_DEBUG_FAILED_TRANSACTION,
-		     "%d:%d transaction failed %d, size %zd-%zd\n",
+		     "%d:%d transaction failed %d, size %lld-%lld\n",
 		     proc->pid, thread->pid, return_error,
-		     tr->data_size, tr->offsets_size);
+		     (u64)tr->data_size, (u64)tr->offsets_size);
 
 	{
 		struct binder_transaction_log_entry *fe;
@@ -1702,9 +1708,11 @@
 
 static int binder_thread_write(struct binder_proc *proc,
 			struct binder_thread *thread,
-			void __user *buffer, size_t size, size_t *consumed)
+			binder_uintptr_t binder_buffer, size_t size,
+			binder_size_t *consumed)
 {
 	uint32_t cmd;
+	void __user *buffer = (void __user *)(uintptr_t)binder_buffer;
 	void __user *ptr = buffer + *consumed;
 	void __user *end = buffer + size;
 
@@ -1773,33 +1781,33 @@
 		}
 		case BC_INCREFS_DONE:
 		case BC_ACQUIRE_DONE: {
-			void __user *node_ptr;
-			void __user *cookie;
+			binder_uintptr_t node_ptr;
+			binder_uintptr_t cookie;
 			struct binder_node *node;
 
-			if (get_user(node_ptr, (void * __user *)ptr))
+			if (get_user(node_ptr, (binder_uintptr_t __user *)ptr))
 				return -EFAULT;
-			ptr += sizeof(void *);
-			if (get_user(cookie, (void * __user *)ptr))
+			ptr += sizeof(binder_uintptr_t);
+			if (get_user(cookie, (binder_uintptr_t __user *)ptr))
 				return -EFAULT;
-			ptr += sizeof(void *);
+			ptr += sizeof(binder_uintptr_t);
 			node = binder_get_node(proc, node_ptr);
 			if (node == NULL) {
-				binder_user_error("%d:%d %s u%p no match\n",
+				binder_user_error("%d:%d %s u%016llx no match\n",
 					proc->pid, thread->pid,
 					cmd == BC_INCREFS_DONE ?
 					"BC_INCREFS_DONE" :
 					"BC_ACQUIRE_DONE",
-					node_ptr);
+					(u64)node_ptr);
 				break;
 			}
 			if (cookie != node->cookie) {
-				binder_user_error("%d:%d %s u%p node %d cookie mismatch %p != %p\n",
+				binder_user_error("%d:%d %s u%016llx node %d cookie mismatch %016llx != %016llx\n",
 					proc->pid, thread->pid,
 					cmd == BC_INCREFS_DONE ?
 					"BC_INCREFS_DONE" : "BC_ACQUIRE_DONE",
-					node_ptr, node->debug_id,
-					cookie, node->cookie);
+					(u64)node_ptr, node->debug_id,
+					(u64)cookie, (u64)node->cookie);
 				break;
 			}
 			if (cmd == BC_ACQUIRE_DONE) {
@@ -1835,27 +1843,28 @@
 			return -EINVAL;
 
 		case BC_FREE_BUFFER: {
-			void __user *data_ptr;
+			binder_uintptr_t data_ptr;
 			struct binder_buffer *buffer;
 
-			if (get_user(data_ptr, (void * __user *)ptr))
+			if (get_user(data_ptr, (binder_uintptr_t __user *)ptr))
 				return -EFAULT;
-			ptr += sizeof(void *);
+			ptr += sizeof(binder_uintptr_t);
 
 			buffer = binder_buffer_lookup(proc, data_ptr);
 			if (buffer == NULL) {
-				binder_user_error("%d:%d BC_FREE_BUFFER u%p no match\n",
-					proc->pid, thread->pid, data_ptr);
+				binder_user_error("%d:%d BC_FREE_BUFFER u%016llx no match\n",
+					proc->pid, thread->pid, (u64)data_ptr);
 				break;
 			}
 			if (!buffer->allow_user_free) {
-				binder_user_error("%d:%d BC_FREE_BUFFER u%p matched unreturned buffer\n",
-					proc->pid, thread->pid, data_ptr);
+				binder_user_error("%d:%d BC_FREE_BUFFER u%016llx matched unreturned buffer\n",
+					proc->pid, thread->pid, (u64)data_ptr);
 				break;
 			}
 			binder_debug(BINDER_DEBUG_FREE_BUFFER,
-				     "%d:%d BC_FREE_BUFFER u%p found buffer %d for %s transaction\n",
-				     proc->pid, thread->pid, data_ptr, buffer->debug_id,
+				     "%d:%d BC_FREE_BUFFER u%016llx found buffer %d for %s transaction\n",
+				     proc->pid, thread->pid, (u64)data_ptr,
+				     buffer->debug_id,
 				     buffer->transaction ? "active" : "finished");
 
 			if (buffer->transaction) {
@@ -1925,16 +1934,16 @@
 		case BC_REQUEST_DEATH_NOTIFICATION:
 		case BC_CLEAR_DEATH_NOTIFICATION: {
 			uint32_t target;
-			void __user *cookie;
+			binder_uintptr_t cookie;
 			struct binder_ref *ref;
 			struct binder_ref_death *death;
 
 			if (get_user(target, (uint32_t __user *)ptr))
 				return -EFAULT;
 			ptr += sizeof(uint32_t);
-			if (get_user(cookie, (void __user * __user *)ptr))
+			if (get_user(cookie, (binder_uintptr_t __user *)ptr))
 				return -EFAULT;
-			ptr += sizeof(void *);
+			ptr += sizeof(binder_uintptr_t);
 			ref = binder_get_ref(proc, target);
 			if (ref == NULL) {
 				binder_user_error("%d:%d %s invalid ref %d\n",
@@ -1947,12 +1956,12 @@
 			}
 
 			binder_debug(BINDER_DEBUG_DEATH_NOTIFICATION,
-				     "%d:%d %s %p ref %d desc %d s %d w %d for node %d\n",
+				     "%d:%d %s %016llx ref %d desc %d s %d w %d for node %d\n",
 				     proc->pid, thread->pid,
 				     cmd == BC_REQUEST_DEATH_NOTIFICATION ?
 				     "BC_REQUEST_DEATH_NOTIFICATION" :
 				     "BC_CLEAR_DEATH_NOTIFICATION",
-				     cookie, ref->debug_id, ref->desc,
+				     (u64)cookie, ref->debug_id, ref->desc,
 				     ref->strong, ref->weak, ref->node->debug_id);
 
 			if (cmd == BC_REQUEST_DEATH_NOTIFICATION) {
@@ -1990,9 +1999,10 @@
 				}
 				death = ref->death;
 				if (death->cookie != cookie) {
-					binder_user_error("%d:%d BC_CLEAR_DEATH_NOTIFICATION death notification cookie mismatch %p != %p\n",
+					binder_user_error("%d:%d BC_CLEAR_DEATH_NOTIFICATION death notification cookie mismatch %016llx != %016llx\n",
 						proc->pid, thread->pid,
-						death->cookie, cookie);
+						(u64)death->cookie,
+						(u64)cookie);
 					break;
 				}
 				ref->death = NULL;
@@ -2012,9 +2022,9 @@
 		} break;
 		case BC_DEAD_BINDER_DONE: {
 			struct binder_work *w;
-			void __user *cookie;
+			binder_uintptr_t cookie;
 			struct binder_ref_death *death = NULL;
-			if (get_user(cookie, (void __user * __user *)ptr))
+			if (get_user(cookie, (binder_uintptr_t __user *)ptr))
 				return -EFAULT;
 
 			ptr += sizeof(void *);
@@ -2026,11 +2036,12 @@
 				}
 			}
 			binder_debug(BINDER_DEBUG_DEAD_BINDER,
-				     "%d:%d BC_DEAD_BINDER_DONE %p found %p\n",
-				     proc->pid, thread->pid, cookie, death);
+				     "%d:%d BC_DEAD_BINDER_DONE %016llx found %p\n",
+				     proc->pid, thread->pid, (u64)cookie,
+				     death);
 			if (death == NULL) {
-				binder_user_error("%d:%d BC_DEAD_BINDER_DONE %p not found\n",
-					proc->pid, thread->pid, cookie);
+				binder_user_error("%d:%d BC_DEAD_BINDER_DONE %016llx not found\n",
+					proc->pid, thread->pid, (u64)cookie);
 				break;
 			}
 
@@ -2082,9 +2093,10 @@
 
 static int binder_thread_read(struct binder_proc *proc,
 			      struct binder_thread *thread,
-			      void  __user *buffer, size_t size,
-			      size_t *consumed, int non_block)
+			      binder_uintptr_t binder_buffer, size_t size,
+			      binder_size_t *consumed, int non_block)
 {
+	void __user *buffer = (void __user *)(uintptr_t)binder_buffer;
 	void __user *ptr = buffer + *consumed;
 	void __user *end = buffer + size;
 
@@ -2229,32 +2241,40 @@
 				if (put_user(cmd, (uint32_t __user *)ptr))
 					return -EFAULT;
 				ptr += sizeof(uint32_t);
-				if (put_user(node->ptr, (void * __user *)ptr))
+				if (put_user(node->ptr,
+					     (binder_uintptr_t __user *)ptr))
 					return -EFAULT;
-				ptr += sizeof(void *);
-				if (put_user(node->cookie, (void * __user *)ptr))
+				ptr += sizeof(binder_uintptr_t);
+				if (put_user(node->cookie,
+					     (binder_uintptr_t __user *)ptr))
 					return -EFAULT;
-				ptr += sizeof(void *);
+				ptr += sizeof(binder_uintptr_t);
 
 				binder_stat_br(proc, thread, cmd);
 				binder_debug(BINDER_DEBUG_USER_REFS,
-					     "%d:%d %s %d u%p c%p\n",
-					     proc->pid, thread->pid, cmd_name, node->debug_id, node->ptr, node->cookie);
+					     "%d:%d %s %d u%016llx c%016llx\n",
+					     proc->pid, thread->pid, cmd_name,
+					     node->debug_id,
+					     (u64)node->ptr, (u64)node->cookie);
 			} else {
 				list_del_init(&w->entry);
 				if (!weak && !strong) {
 					binder_debug(BINDER_DEBUG_INTERNAL_REFS,
-						     "%d:%d node %d u%p c%p deleted\n",
-						     proc->pid, thread->pid, node->debug_id,
-						     node->ptr, node->cookie);
+						     "%d:%d node %d u%016llx c%016llx deleted\n",
+						     proc->pid, thread->pid,
+						     node->debug_id,
+						     (u64)node->ptr,
+						     (u64)node->cookie);
 					rb_erase(&node->rb_node, &proc->nodes);
 					kfree(node);
 					binder_stats_deleted(BINDER_STAT_NODE);
 				} else {
 					binder_debug(BINDER_DEBUG_INTERNAL_REFS,
-						     "%d:%d node %d u%p c%p state unchanged\n",
-						     proc->pid, thread->pid, node->debug_id, node->ptr,
-						     node->cookie);
+						     "%d:%d node %d u%016llx c%016llx state unchanged\n",
+						     proc->pid, thread->pid,
+						     node->debug_id,
+						     (u64)node->ptr,
+						     (u64)node->cookie);
 				}
 			}
 		} break;
@@ -2272,17 +2292,18 @@
 			if (put_user(cmd, (uint32_t __user *)ptr))
 				return -EFAULT;
 			ptr += sizeof(uint32_t);
-			if (put_user(death->cookie, (void * __user *)ptr))
+			if (put_user(death->cookie,
+				     (binder_uintptr_t __user *)ptr))
 				return -EFAULT;
-			ptr += sizeof(void *);
+			ptr += sizeof(binder_uintptr_t);
 			binder_stat_br(proc, thread, cmd);
 			binder_debug(BINDER_DEBUG_DEATH_NOTIFICATION,
-				     "%d:%d %s %p\n",
+				     "%d:%d %s %016llx\n",
 				      proc->pid, thread->pid,
 				      cmd == BR_DEAD_BINDER ?
 				      "BR_DEAD_BINDER" :
 				      "BR_CLEAR_DEATH_NOTIFICATION_DONE",
-				      death->cookie);
+				      (u64)death->cookie);
 
 			if (w->type == BINDER_WORK_CLEAR_DEATH_NOTIFICATION) {
 				list_del(&w->entry);
@@ -2312,8 +2333,8 @@
 				binder_set_nice(target_node->min_priority);
 			cmd = BR_TRANSACTION;
 		} else {
-			tr.target.ptr = NULL;
-			tr.cookie = NULL;
+			tr.target.ptr = 0;
+			tr.cookie = 0;
 			cmd = BR_REPLY;
 		}
 		tr.code = t->code;
@@ -2330,8 +2351,9 @@
 
 		tr.data_size = t->buffer->data_size;
 		tr.offsets_size = t->buffer->offsets_size;
-		tr.data.ptr.buffer = (void *)t->buffer->data +
-					proc->user_buffer_offset;
+		tr.data.ptr.buffer = (binder_uintptr_t)(
+					(uintptr_t)t->buffer->data +
+					proc->user_buffer_offset);
 		tr.data.ptr.offsets = tr.data.ptr.buffer +
 					ALIGN(t->buffer->data_size,
 					    sizeof(void *));
@@ -2346,14 +2368,14 @@
 		trace_binder_transaction_received(t);
 		binder_stat_br(proc, thread, cmd);
 		binder_debug(BINDER_DEBUG_TRANSACTION,
-			     "%d:%d %s %d %d:%d, cmd %d size %zd-%zd ptr %p-%p\n",
+			     "%d:%d %s %d %d:%d, cmd %d size %zd-%zd ptr %016llx-%016llx\n",
 			     proc->pid, thread->pid,
 			     (cmd == BR_TRANSACTION) ? "BR_TRANSACTION" :
 			     "BR_REPLY",
 			     t->debug_id, t->from ? t->from->proc->pid : 0,
 			     t->from ? t->from->pid : 0, cmd,
 			     t->buffer->data_size, t->buffer->offsets_size,
-			     tr.data.ptr.buffer, tr.data.ptr.offsets);
+			     (u64)tr.data.ptr.buffer, (u64)tr.data.ptr.offsets);
 
 		list_del(&t->work.entry);
 		t->buffer->allow_user_free = 1;
@@ -2423,8 +2445,8 @@
 
 			death = container_of(w, struct binder_ref_death, work);
 			binder_debug(BINDER_DEBUG_DEAD_TRANSACTION,
-				"undelivered death notification, %p\n",
-				death->cookie);
+				"undelivered death notification, %016llx\n",
+				(u64)death->cookie);
 			kfree(death);
 			binder_stats_deleted(BINDER_STAT_DEATH);
 		} break;
@@ -2580,12 +2602,16 @@
 			goto err;
 		}
 		binder_debug(BINDER_DEBUG_READ_WRITE,
-			     "%d:%d write %zd at %016lx, read %zd at %016lx\n",
-			     proc->pid, thread->pid, bwr.write_size,
-			     bwr.write_buffer, bwr.read_size, bwr.read_buffer);
+			     "%d:%d write %lld at %016llx, read %lld at %016llx\n",
+			     proc->pid, thread->pid,
+			     (u64)bwr.write_size, (u64)bwr.write_buffer,
+			     (u64)bwr.read_size, (u64)bwr.read_buffer);
 
 		if (bwr.write_size > 0) {
-			ret = binder_thread_write(proc, thread, (void __user *)bwr.write_buffer, bwr.write_size, &bwr.write_consumed);
+			ret = binder_thread_write(proc, thread,
+						  bwr.write_buffer,
+						  bwr.write_size,
+						  &bwr.write_consumed);
 			trace_binder_write_done(ret);
 			if (ret < 0) {
 				bwr.read_consumed = 0;
@@ -2595,7 +2621,10 @@
 			}
 		}
 		if (bwr.read_size > 0) {
-			ret = binder_thread_read(proc, thread, (void __user *)bwr.read_buffer, bwr.read_size, &bwr.read_consumed, filp->f_flags & O_NONBLOCK);
+			ret = binder_thread_read(proc, thread, bwr.read_buffer,
+						 bwr.read_size,
+						 &bwr.read_consumed,
+						 filp->f_flags & O_NONBLOCK);
 			trace_binder_read_done(ret);
 			if (!list_empty(&proc->todo))
 				wake_up_interruptible(&proc->wait);
@@ -2606,9 +2635,10 @@
 			}
 		}
 		binder_debug(BINDER_DEBUG_READ_WRITE,
-			     "%d:%d wrote %zd of %zd, read return %zd of %zd\n",
-			     proc->pid, thread->pid, bwr.write_consumed, bwr.write_size,
-			     bwr.read_consumed, bwr.read_size);
+			     "%d:%d wrote %lld of %lld, read return %lld of %lld\n",
+			     proc->pid, thread->pid,
+			     (u64)bwr.write_consumed, (u64)bwr.write_size,
+			     (u64)bwr.read_consumed, (u64)bwr.read_size);
 		if (copy_to_user(ubuf, &bwr, sizeof(bwr))) {
 			ret = -EFAULT;
 			goto err;
@@ -2637,7 +2667,7 @@
 			}
 		} else
 			binder_context_mgr_uid = current->cred->euid;
-		binder_context_mgr_node = binder_new_node(proc, NULL, NULL);
+		binder_context_mgr_node = binder_new_node(proc, 0, 0);
 		if (binder_context_mgr_node == NULL) {
 			ret = -ENOMEM;
 			goto err;
@@ -2904,7 +2934,7 @@
 		refs++;
 
 		if (!ref->death)
-			goto out;
+			continue;
 
 		death++;
 
@@ -2917,7 +2947,6 @@
 			BUG();
 	}
 
-out:
 	binder_debug(BINDER_DEBUG_DEAD_BINDER,
 		     "node %d now dead, refs %d, death %d\n",
 		     node->debug_id, refs, death);
@@ -3133,8 +3162,9 @@
 		break;
 	case BINDER_WORK_NODE:
 		node = container_of(w, struct binder_node, work);
-		seq_printf(m, "%snode work %d: u%p c%p\n",
-			   prefix, node->debug_id, node->ptr, node->cookie);
+		seq_printf(m, "%snode work %d: u%016llx c%016llx\n",
+			   prefix, node->debug_id,
+			   (u64)node->ptr, (u64)node->cookie);
 		break;
 	case BINDER_WORK_DEAD_BINDER:
 		seq_printf(m, "%shas dead binder\n", prefix);
@@ -3194,8 +3224,8 @@
 	hlist_for_each_entry(ref, &node->refs, node_entry)
 		count++;
 
-	seq_printf(m, "  node %d: u%p c%p hs %d hw %d ls %d lw %d is %d iw %d",
-		   node->debug_id, node->ptr, node->cookie,
+	seq_printf(m, "  node %d: u%016llx c%016llx hs %d hw %d ls %d lw %d is %d iw %d",
+		   node->debug_id, (u64)node->ptr, (u64)node->cookie,
 		   node->has_strong_ref, node->has_weak_ref,
 		   node->local_strong_refs, node->local_weak_refs,
 		   node->internal_strong_refs, count);
@@ -3497,6 +3527,7 @@
 	.owner = THIS_MODULE,
 	.poll = binder_poll,
 	.unlocked_ioctl = binder_ioctl,
+	.compat_ioctl = binder_ioctl,
 	.mmap = binder_mmap,
 	.open = binder_open,
 	.flush = binder_flush,
diff --git a/drivers/staging/android/binder.h b/drivers/staging/android/binder.h
index d4101a6..eb08346 100644
--- a/drivers/staging/android/binder.h
+++ b/drivers/staging/android/binder.h
@@ -20,6 +20,10 @@
 #ifndef _LINUX_BINDER_H
 #define _LINUX_BINDER_H
 
+#ifdef CONFIG_ANDROID_BINDER_IPC_32BIT
+#define BINDER_IPC_32BIT 1
+#endif
+
 #include "uapi/binder.h"
 
 #endif /* _LINUX_BINDER_H */
diff --git a/drivers/staging/android/binder_trace.h b/drivers/staging/android/binder_trace.h
index 82a567c..7f20f3d 100644
--- a/drivers/staging/android/binder_trace.h
+++ b/drivers/staging/android/binder_trace.h
@@ -152,7 +152,7 @@
 	TP_STRUCT__entry(
 		__field(int, debug_id)
 		__field(int, node_debug_id)
-		__field(void __user *, node_ptr)
+		__field(binder_uintptr_t, node_ptr)
 		__field(int, ref_debug_id)
 		__field(uint32_t, ref_desc)
 	),
@@ -163,8 +163,9 @@
 		__entry->ref_debug_id = ref->debug_id;
 		__entry->ref_desc = ref->desc;
 	),
-	TP_printk("transaction=%d node=%d src_ptr=0x%p ==> dest_ref=%d dest_desc=%d",
-		  __entry->debug_id, __entry->node_debug_id, __entry->node_ptr,
+	TP_printk("transaction=%d node=%d src_ptr=0x%016llx ==> dest_ref=%d dest_desc=%d",
+		  __entry->debug_id, __entry->node_debug_id,
+		  (u64)__entry->node_ptr,
 		  __entry->ref_debug_id, __entry->ref_desc)
 );
 
@@ -177,7 +178,7 @@
 		__field(int, ref_debug_id)
 		__field(uint32_t, ref_desc)
 		__field(int, node_debug_id)
-		__field(void __user *, node_ptr)
+		__field(binder_uintptr_t, node_ptr)
 	),
 	TP_fast_assign(
 		__entry->debug_id = t->debug_id;
@@ -186,9 +187,10 @@
 		__entry->node_debug_id = ref->node->debug_id;
 		__entry->node_ptr = ref->node->ptr;
 	),
-	TP_printk("transaction=%d node=%d src_ref=%d src_desc=%d ==> dest_ptr=0x%p",
+	TP_printk("transaction=%d node=%d src_ref=%d src_desc=%d ==> dest_ptr=0x%016llx",
 		  __entry->debug_id, __entry->node_debug_id,
-		  __entry->ref_debug_id, __entry->ref_desc, __entry->node_ptr)
+		  __entry->ref_debug_id, __entry->ref_desc,
+		  (u64)__entry->node_ptr)
 );
 
 TRACE_EVENT(binder_transaction_ref_to_ref,
diff --git a/drivers/staging/android/lowmemorykiller.c b/drivers/staging/android/lowmemorykiller.c
index 4bcf00a..b545d3d 100644
--- a/drivers/staging/android/lowmemorykiller.c
+++ b/drivers/staging/android/lowmemorykiller.c
@@ -88,7 +88,8 @@
 	int array_size = ARRAY_SIZE(lowmem_adj);
 	int other_free = global_page_state(NR_FREE_PAGES) - totalreserve_pages;
 	int other_file = global_page_state(NR_FILE_PAGES) -
-						global_page_state(NR_SHMEM);
+						global_page_state(NR_SHMEM) -
+						total_swapcache_pages();
 
 	if (lowmem_adj_size < array_size)
 		array_size = lowmem_adj_size;
diff --git a/drivers/staging/android/uapi/binder.h b/drivers/staging/android/uapi/binder.h
index 2b1eb81..904adb7 100644
--- a/drivers/staging/android/uapi/binder.h
+++ b/drivers/staging/android/uapi/binder.h
@@ -39,6 +39,14 @@
 	FLAT_BINDER_FLAG_ACCEPTS_FDS = 0x100,
 };
 
+#ifdef BINDER_IPC_32BIT
+typedef __u32 binder_size_t;
+typedef __u32 binder_uintptr_t;
+#else
+typedef __u64 binder_size_t;
+typedef __u64 binder_uintptr_t;
+#endif
+
 /*
  * This is the flattened representation of a Binder object for transfer
  * between processes.  The 'offsets' supplied as part of a binder transaction
@@ -53,12 +61,12 @@
 
 	/* 8 bytes of data. */
 	union {
-		void __user	*binder;	/* local object */
-		__u32	    handle;		/* remote object */
+		binder_uintptr_t	binder;	/* local object */
+		__u32			handle;	/* remote object */
 	};
 
 	/* extra data associated with local object */
-	void __user		*cookie;
+	binder_uintptr_t	cookie;
 };
 
 /*
@@ -67,12 +75,12 @@
  */
 
 struct binder_write_read {
-	size_t write_size;	/* bytes to write */
-	size_t write_consumed;	/* bytes consumed by driver */
-	unsigned long	write_buffer;
-	size_t read_size;	/* bytes to read */
-	size_t read_consumed;	/* bytes consumed by driver */
-	unsigned long	read_buffer;
+	binder_size_t		write_size;	/* bytes to write */
+	binder_size_t		write_consumed;	/* bytes consumed by driver */
+	binder_uintptr_t	write_buffer;
+	binder_size_t		read_size;	/* bytes to read */
+	binder_size_t		read_consumed;	/* bytes consumed by driver */
+	binder_uintptr_t	read_buffer;
 };
 
 /* Use with BINDER_VERSION, driver fills in fields. */
@@ -82,7 +90,11 @@
 };
 
 /* This is the current protocol version. */
+#ifdef BINDER_IPC_32BIT
 #define BINDER_CURRENT_PROTOCOL_VERSION 7
+#else
+#define BINDER_CURRENT_PROTOCOL_VERSION 8
+#endif
 
 #define BINDER_WRITE_READ		_IOWR('b', 1, struct binder_write_read)
 #define BINDER_SET_IDLE_TIMEOUT		_IOW('b', 3, __s64)
@@ -119,18 +131,20 @@
 	 * identifying the target and contents of the transaction.
 	 */
 	union {
-		__u32	handle;	/* target descriptor of command transaction */
-		void	*ptr;	/* target descriptor of return transaction */
+		/* target descriptor of command transaction */
+		__u32	handle;
+		/* target descriptor of return transaction */
+		binder_uintptr_t ptr;
 	} target;
-	void		*cookie;	/* target object cookie */
+	binder_uintptr_t	cookie;	/* target object cookie */
 	__u32		code;		/* transaction command */
 
 	/* General information about the transaction. */
 	__u32	        flags;
 	pid_t		sender_pid;
 	uid_t		sender_euid;
-	size_t		data_size;	/* number of bytes of data */
-	size_t		offsets_size;	/* number of bytes of offsets */
+	binder_size_t	data_size;	/* number of bytes of data */
+	binder_size_t	offsets_size;	/* number of bytes of offsets */
 
 	/* If this transaction is inline, the data immediately
 	 * follows here; otherwise, it ends with a pointer to
@@ -139,19 +153,24 @@
 	union {
 		struct {
 			/* transaction data */
-			const void __user	*buffer;
+			binder_uintptr_t	buffer;
 			/* offsets from buffer to flat_binder_object structs */
-			const void __user	*offsets;
+			binder_uintptr_t	offsets;
 		} ptr;
 		__u8	buf[8];
 	} data;
 };
 
 struct binder_ptr_cookie {
-	void *ptr;
-	void *cookie;
+	binder_uintptr_t ptr;
+	binder_uintptr_t cookie;
 };
 
+struct binder_handle_cookie {
+	__u32 handle;
+	binder_uintptr_t cookie;
+} __attribute__((packed));
+
 struct binder_pri_desc {
 	__s32 priority;
 	__u32 desc;
@@ -159,8 +178,8 @@
 
 struct binder_pri_ptr_cookie {
 	__s32 priority;
-	void *ptr;
-	void *cookie;
+	binder_uintptr_t ptr;
+	binder_uintptr_t cookie;
 };
 
 enum binder_driver_return_protocol {
@@ -235,11 +254,11 @@
 	 * stop threadpool thread
 	 */
 
-	BR_DEAD_BINDER = _IOR('r', 15, void *),
+	BR_DEAD_BINDER = _IOR('r', 15, binder_uintptr_t),
 	/*
 	 * void *: cookie
 	 */
-	BR_CLEAR_DEATH_NOTIFICATION_DONE = _IOR('r', 16, void *),
+	BR_CLEAR_DEATH_NOTIFICATION_DONE = _IOR('r', 16, binder_uintptr_t),
 	/*
 	 * void *: cookie
 	 */
@@ -265,7 +284,7 @@
 	 * Else you have acquired a primary reference on the object.
 	 */
 
-	BC_FREE_BUFFER = _IOW('c', 3, void *),
+	BC_FREE_BUFFER = _IOW('c', 3, binder_uintptr_t),
 	/*
 	 * void *: ptr to transaction data received on a read
 	 */
@@ -308,19 +327,21 @@
 	 * of looping threads it has available.
 	 */
 
-	BC_REQUEST_DEATH_NOTIFICATION = _IOW('c', 14, struct binder_ptr_cookie),
+	BC_REQUEST_DEATH_NOTIFICATION = _IOW('c', 14,
+						struct binder_handle_cookie),
 	/*
-	 * void *: ptr to binder
+	 * int: handle
 	 * void *: cookie
 	 */
 
-	BC_CLEAR_DEATH_NOTIFICATION = _IOW('c', 15, struct binder_ptr_cookie),
+	BC_CLEAR_DEATH_NOTIFICATION = _IOW('c', 15,
+						struct binder_handle_cookie),
 	/*
-	 * void *: ptr to binder
+	 * int: handle
 	 * void *: cookie
 	 */
 
-	BC_DEAD_BINDER_DONE = _IOW('c', 16, void *),
+	BC_DEAD_BINDER_DONE = _IOW('c', 16, binder_uintptr_t),
 	/*
 	 * void *: cookie
 	 */
diff --git a/drivers/staging/bcm/Bcmnet.c b/drivers/staging/bcm/Bcmnet.c
index 8dfdd27..95a2358 100644
--- a/drivers/staging/bcm/Bcmnet.c
+++ b/drivers/staging/bcm/Bcmnet.c
@@ -40,7 +40,7 @@
 }
 
 static u16 bcm_select_queue(struct net_device *dev, struct sk_buff *skb,
-			    void *accel_priv)
+			    void *accel_priv, select_queue_fallback_t fallback)
 {
 	return ClassifyPacket(netdev_priv(dev), skb);
 }
diff --git a/drivers/staging/bcm/InterfaceInit.c b/drivers/staging/bcm/InterfaceInit.c
index 94f3272..5b03a19 100644
--- a/drivers/staging/bcm/InterfaceInit.c
+++ b/drivers/staging/bcm/InterfaceInit.c
@@ -1,5 +1,5 @@
 #include "headers.h"
-
+#include <linux/usb/ch9.h>
 static struct usb_device_id InterfaceUsbtable[] = {
 	{ USB_DEVICE(BCM_USB_VENDOR_ID_T3, BCM_USB_PRODUCT_ID_T3) },
 	{ USB_DEVICE(BCM_USB_VENDOR_ID_T3, BCM_USB_PRODUCT_ID_T3B) },
@@ -347,81 +347,6 @@
 	return 0;
 }
 
-
-static inline int bcm_usb_endpoint_num(const struct usb_endpoint_descriptor *epd)
-{
-	return epd->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
-}
-
-static inline int bcm_usb_endpoint_type(const struct usb_endpoint_descriptor *epd)
-{
-	return epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
-}
-
-static inline int bcm_usb_endpoint_dir_in(const struct usb_endpoint_descriptor *epd)
-{
-	return ((epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN);
-}
-
-static inline int bcm_usb_endpoint_dir_out(const struct usb_endpoint_descriptor *epd)
-{
-	return ((epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT);
-}
-
-static inline int bcm_usb_endpoint_xfer_bulk(const struct usb_endpoint_descriptor *epd)
-{
-	return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
-		USB_ENDPOINT_XFER_BULK);
-}
-
-static inline int bcm_usb_endpoint_xfer_control(const struct usb_endpoint_descriptor *epd)
-{
-	return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
-		USB_ENDPOINT_XFER_CONTROL);
-}
-
-static inline int bcm_usb_endpoint_xfer_int(const struct usb_endpoint_descriptor *epd)
-{
-	return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
-		USB_ENDPOINT_XFER_INT);
-}
-
-static inline int bcm_usb_endpoint_xfer_isoc(const struct usb_endpoint_descriptor *epd)
-{
-	return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
-		USB_ENDPOINT_XFER_ISOC);
-}
-
-static inline int bcm_usb_endpoint_is_bulk_in(const struct usb_endpoint_descriptor *epd)
-{
-	return bcm_usb_endpoint_xfer_bulk(epd) && bcm_usb_endpoint_dir_in(epd);
-}
-
-static inline int bcm_usb_endpoint_is_bulk_out(const struct usb_endpoint_descriptor *epd)
-{
-	return bcm_usb_endpoint_xfer_bulk(epd) && bcm_usb_endpoint_dir_out(epd);
-}
-
-static inline int bcm_usb_endpoint_is_int_in(const struct usb_endpoint_descriptor *epd)
-{
-	return bcm_usb_endpoint_xfer_int(epd) && bcm_usb_endpoint_dir_in(epd);
-}
-
-static inline int bcm_usb_endpoint_is_int_out(const struct usb_endpoint_descriptor *epd)
-{
-	return bcm_usb_endpoint_xfer_int(epd) && bcm_usb_endpoint_dir_out(epd);
-}
-
-static inline int bcm_usb_endpoint_is_isoc_in(const struct usb_endpoint_descriptor *epd)
-{
-	return bcm_usb_endpoint_xfer_isoc(epd) && bcm_usb_endpoint_dir_in(epd);
-}
-
-static inline int bcm_usb_endpoint_is_isoc_out(const struct usb_endpoint_descriptor *epd)
-{
-	return bcm_usb_endpoint_xfer_isoc(epd) && bcm_usb_endpoint_dir_out(epd);
-}
-
 static int InterfaceAdapterInit(struct bcm_interface_adapter *psIntfAdapter)
 {
 	struct usb_host_interface *iface_desc;
@@ -481,8 +406,8 @@
 				 * If Modem is high speed device EP2 should be INT OUT End point
 				 * If Mode is FS then EP2 should be bulk end point
 				 */
-				if (((psIntfAdapter->bHighSpeedDevice == TRUE) && (bcm_usb_endpoint_is_int_out(endpoint) == false))
-					|| ((psIntfAdapter->bHighSpeedDevice == false) && (bcm_usb_endpoint_is_bulk_out(endpoint) == false))) {
+				if (((psIntfAdapter->bHighSpeedDevice == TRUE) && (usb_endpoint_is_int_out(endpoint) == false))
+					|| ((psIntfAdapter->bHighSpeedDevice == false) && (usb_endpoint_is_bulk_out(endpoint) == false))) {
 					BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL,
 						"Configuring the EEPROM\n");
 					/* change the EP2, EP4 to INT OUT end point */
@@ -501,7 +426,7 @@
 					}
 
 				}
-				if ((psIntfAdapter->bHighSpeedDevice == false) && bcm_usb_endpoint_is_bulk_out(endpoint)) {
+				if ((psIntfAdapter->bHighSpeedDevice == false) && usb_endpoint_is_bulk_out(endpoint)) {
 					/* Once BULK is selected in FS mode. Revert it back to INT. Else USB_IF will fail. */
 					UINT _uiData = ntohl(EP2_CFG_INT);
 					BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL,
@@ -513,7 +438,7 @@
 				endpoint = &iface_desc->endpoint[EP4].desc;
 				BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL,
 					"Choosing AltSetting as a default setting.\n");
-				if (bcm_usb_endpoint_is_int_out(endpoint) == false) {
+				if (usb_endpoint_is_int_out(endpoint) == false) {
 					BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL,
 						"Dongle does not have BCM16 Fix.\n");
 					/* change the EP2, EP4 to INT OUT end point and use EP4 in altsetting */
@@ -541,7 +466,7 @@
 	for (value = 0; value < iface_desc->desc.bNumEndpoints; ++value) {
 		endpoint = &iface_desc->endpoint[value].desc;
 
-		if (!psIntfAdapter->sBulkIn.bulk_in_endpointAddr && bcm_usb_endpoint_is_bulk_in(endpoint)) {
+		if (!psIntfAdapter->sBulkIn.bulk_in_endpointAddr && usb_endpoint_is_bulk_in(endpoint)) {
 			buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
 			psIntfAdapter->sBulkIn.bulk_in_size = buffer_size;
 			psIntfAdapter->sBulkIn.bulk_in_endpointAddr = endpoint->bEndpointAddress;
@@ -550,14 +475,14 @@
 								psIntfAdapter->sBulkIn.bulk_in_endpointAddr);
 		}
 
-		if (!psIntfAdapter->sBulkOut.bulk_out_endpointAddr && bcm_usb_endpoint_is_bulk_out(endpoint)) {
+		if (!psIntfAdapter->sBulkOut.bulk_out_endpointAddr && usb_endpoint_is_bulk_out(endpoint)) {
 			psIntfAdapter->sBulkOut.bulk_out_endpointAddr = endpoint->bEndpointAddress;
 			psIntfAdapter->sBulkOut.bulk_out_pipe =
 				usb_sndbulkpipe(psIntfAdapter->udev,
 					psIntfAdapter->sBulkOut.bulk_out_endpointAddr);
 		}
 
-		if (!psIntfAdapter->sIntrIn.int_in_endpointAddr && bcm_usb_endpoint_is_int_in(endpoint)) {
+		if (!psIntfAdapter->sIntrIn.int_in_endpointAddr && usb_endpoint_is_int_in(endpoint)) {
 			buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
 			psIntfAdapter->sIntrIn.int_in_size = buffer_size;
 			psIntfAdapter->sIntrIn.int_in_endpointAddr = endpoint->bEndpointAddress;
@@ -568,7 +493,7 @@
 				return -EINVAL;
 		}
 
-		if (!psIntfAdapter->sIntrOut.int_out_endpointAddr && bcm_usb_endpoint_is_int_out(endpoint)) {
+		if (!psIntfAdapter->sIntrOut.int_out_endpointAddr && usb_endpoint_is_int_out(endpoint)) {
 			if (!psIntfAdapter->sBulkOut.bulk_out_endpointAddr &&
 				(psIntfAdapter->psAdapter->chip_id == T3B) && (value == usedIntOutForBulkTransfer)) {
 				/* use first intout end point as a bulk out end point */
diff --git a/drivers/staging/bcm/Qos.c b/drivers/staging/bcm/Qos.c
index 0727599..4f31583 100644
--- a/drivers/staging/bcm/Qos.c
+++ b/drivers/staging/bcm/Qos.c
@@ -222,10 +222,7 @@
 
 		//Checking classifier validity
 		if (!pstClassifierRule->bUsed || pstClassifierRule->ucDirection == DOWNLINK_DIR)
-		{
-			bClassificationSucceed = false;
 			break;
-		}
 
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "is IPv6 check!");
 		if (pstClassifierRule->bIpv6Protocol)
@@ -233,51 +230,47 @@
 
 		//**************Checking IP header parameter**************************//
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Trying to match Source IP Address");
-		if (false == (bClassificationSucceed =
-			MatchSrcIpAddress(pstClassifierRule, iphd->saddr)))
+		if (!MatchSrcIpAddress(pstClassifierRule, iphd->saddr))
 			break;
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Source IP Address Matched");
 
-		if (false == (bClassificationSucceed =
-			MatchDestIpAddress(pstClassifierRule, iphd->daddr)))
+		if (!MatchDestIpAddress(pstClassifierRule, iphd->daddr))
 			break;
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Destination IP Address Matched");
 
-		if (false == (bClassificationSucceed =
-			MatchTos(pstClassifierRule, iphd->tos)))
-		{
+		if (!MatchTos(pstClassifierRule, iphd->tos)) {
 			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "TOS Match failed\n");
 			break;
 		}
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "TOS Matched");
 
-		if (false == (bClassificationSucceed =
-			MatchProtocol(pstClassifierRule, iphd->protocol)))
+		if (!MatchProtocol(pstClassifierRule, iphd->protocol))
 			break;
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Protocol Matched");
 
 		//if protocol is not TCP or UDP then no need of comparing source port and destination port
-		if (iphd->protocol != TCP && iphd->protocol != UDP)
+		if (iphd->protocol != TCP && iphd->protocol != UDP) {
+			bClassificationSucceed = TRUE;
 			break;
+		}
 		//******************Checking Transport Layer Header field if present *****************//
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Source Port %04x",
 			(iphd->protocol == UDP) ? xprt_hdr->uhdr.source : xprt_hdr->thdr.source);
 
-		if (false == (bClassificationSucceed =
-			MatchSrcPort(pstClassifierRule,
-				ntohs((iphd->protocol == UDP) ?
-				xprt_hdr->uhdr.source : xprt_hdr->thdr.source))))
+		if (!MatchSrcPort(pstClassifierRule,
+				  ntohs((iphd->protocol == UDP) ?
+				  xprt_hdr->uhdr.source : xprt_hdr->thdr.source)))
 			break;
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Src Port Matched");
 
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Destination Port %04x",
 			(iphd->protocol == UDP) ? xprt_hdr->uhdr.dest :
 			xprt_hdr->thdr.dest);
-		if (false == (bClassificationSucceed =
-			MatchDestPort(pstClassifierRule,
-			ntohs((iphd->protocol == UDP) ?
-			xprt_hdr->uhdr.dest : xprt_hdr->thdr.dest))))
+		if (!MatchDestPort(pstClassifierRule,
+				   ntohs((iphd->protocol == UDP) ?
+				   xprt_hdr->uhdr.dest : xprt_hdr->thdr.dest)))
 			break;
+		bClassificationSucceed = TRUE;
 	} while (0);
 
 	if (TRUE == bClassificationSucceed)
diff --git a/drivers/staging/ced1401/usb1401.c b/drivers/staging/ced1401/usb1401.c
index f441e33..c281fda 100644
--- a/drivers/staging/ced1401/usb1401.c
+++ b/drivers/staging/ced1401/usb1401.c
@@ -1054,7 +1054,6 @@
 				/*  This can never happen, really */
 				dev_err(&pdx->interface->dev,
 					"ERROR: DMA setup while transfer still waiting\n");
-				spin_unlock(&pdx->stagedLock);
 			} else {
 				if ((wTransType == TM_EXTTOHOST)
 				    || (wTransType == TM_EXTTO1401)) {
diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c
index ac1edd9..a819e54 100644
--- a/drivers/staging/comedi/comedi_fops.c
+++ b/drivers/staging/comedi/comedi_fops.c
@@ -1481,7 +1481,8 @@
 	async->cmd.data = NULL;
 	/* load channel/gain list */
 	async->cmd.chanlist = memdup_user(user_chanlist,
-					  async->cmd.chanlist_len * sizeof(int));
+					  async->cmd.chanlist_len *
+					  sizeof(int));
 	if (IS_ERR(async->cmd.chanlist)) {
 		ret = PTR_ERR(async->cmd.chanlist);
 		async->cmd.chanlist = NULL;
diff --git a/drivers/staging/comedi/comedidev.h b/drivers/staging/comedi/comedidev.h
index f36bf3e..d46123a 100644
--- a/drivers/staging/comedi/comedidev.h
+++ b/drivers/staging/comedi/comedidev.h
@@ -61,31 +61,31 @@
 
 	unsigned int *chanlist;	/* driver-owned chanlist (not used) */
 
-	int (*insn_read) (struct comedi_device *, struct comedi_subdevice *,
+	int (*insn_read)(struct comedi_device *, struct comedi_subdevice *,
+			 struct comedi_insn *, unsigned int *);
+	int (*insn_write)(struct comedi_device *, struct comedi_subdevice *,
 			  struct comedi_insn *, unsigned int *);
-	int (*insn_write) (struct comedi_device *, struct comedi_subdevice *,
+	int (*insn_bits)(struct comedi_device *, struct comedi_subdevice *,
+			 struct comedi_insn *, unsigned int *);
+	int (*insn_config)(struct comedi_device *, struct comedi_subdevice *,
 			   struct comedi_insn *, unsigned int *);
-	int (*insn_bits) (struct comedi_device *, struct comedi_subdevice *,
-			  struct comedi_insn *, unsigned int *);
-	int (*insn_config) (struct comedi_device *, struct comedi_subdevice *,
-			    struct comedi_insn *, unsigned int *);
 
-	int (*do_cmd) (struct comedi_device *, struct comedi_subdevice *);
-	int (*do_cmdtest) (struct comedi_device *, struct comedi_subdevice *,
-			   struct comedi_cmd *);
-	int (*poll) (struct comedi_device *, struct comedi_subdevice *);
-	int (*cancel) (struct comedi_device *, struct comedi_subdevice *);
+	int (*do_cmd)(struct comedi_device *, struct comedi_subdevice *);
+	int (*do_cmdtest)(struct comedi_device *, struct comedi_subdevice *,
+			  struct comedi_cmd *);
+	int (*poll)(struct comedi_device *, struct comedi_subdevice *);
+	int (*cancel)(struct comedi_device *, struct comedi_subdevice *);
 	/* int (*do_lock)(struct comedi_device *, struct comedi_subdevice *); */
 	/* int (*do_unlock)(struct comedi_device *, \
 			struct comedi_subdevice *); */
 
 	/* called when the buffer changes */
-	int (*buf_change) (struct comedi_device *dev,
-			   struct comedi_subdevice *s, unsigned long new_size);
+	int (*buf_change)(struct comedi_device *dev,
+			  struct comedi_subdevice *s, unsigned long new_size);
 
-	void (*munge) (struct comedi_device *dev, struct comedi_subdevice *s,
-		       void *data, unsigned int num_bytes,
-		       unsigned int start_chan_index);
+	void (*munge)(struct comedi_device *dev, struct comedi_subdevice *s,
+		      void *data, unsigned int num_bytes,
+		      unsigned int start_chan_index);
 	enum dma_data_direction async_dma_dir;
 
 	unsigned int state;
@@ -146,8 +146,8 @@
 
 	unsigned int cb_mask;
 
-	int (*inttrig) (struct comedi_device *dev, struct comedi_subdevice *s,
-			unsigned int x);
+	int (*inttrig)(struct comedi_device *dev, struct comedi_subdevice *s,
+		       unsigned int x);
 };
 
 struct comedi_driver {
@@ -155,9 +155,9 @@
 
 	const char *driver_name;
 	struct module *module;
-	int (*attach) (struct comedi_device *, struct comedi_devconfig *);
-	void (*detach) (struct comedi_device *);
-	int (*auto_attach) (struct comedi_device *, unsigned long);
+	int (*attach)(struct comedi_device *, struct comedi_devconfig *);
+	void (*detach)(struct comedi_device *);
+	int (*auto_attach)(struct comedi_device *, unsigned long);
 
 	/* number of elements in board_name and board_id arrays */
 	unsigned int num_names;
@@ -202,8 +202,8 @@
 
 	struct fasync_struct *async_queue;
 
-	int (*open) (struct comedi_device *dev);
-	void (*close) (struct comedi_device *dev);
+	int (*open)(struct comedi_device *dev);
+	void (*close)(struct comedi_device *dev);
 };
 
 static inline const void *comedi_board(const struct comedi_device *dev)
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.c
index 8ce3335..80cca95 100644
--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.c
+++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.c
@@ -169,9 +169,9 @@
 					 unsigned int *data)
 {
 	struct addi_private *devpriv = dev->private;
-	unsigned int ui_Status = 0;
-	unsigned int ui_Command = 0;
-	unsigned int ui_Mode = 0;
+	unsigned int ui_Status;
+	unsigned int ui_Command;
+	unsigned int ui_Mode;
 
 	i_Temp = 0;
 	devpriv->tsk_Current = current;
@@ -182,23 +182,18 @@
 	else
 		ui_Mode = 0;
 
-/* ui_Command = inl(devpriv->iobase+((i_WatchdogNbr-1)*32)+12); */
 	ui_Command = 0;
-/* ui_Command = ui_Command & 0xFFFFF9FEUL; */
 	outl(ui_Command, devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
-	ui_Command = 0;
+
 	ui_Command = inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
-	/************************/
+
 	/* Set the reload value */
-	/************************/
 	outl(data[3], devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 4);
-	/*********************/
+
 	/* Set the time unit */
-	/*********************/
 	outl(data[2], devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 8);
 	if (data[0] == ADDIDATA_TIMER) {
 
-		/******************************/
 		/* Set the mode :             */
 		/* - Disable the hardware     */
 		/* - Disable the counter mode */
@@ -206,101 +201,82 @@
 		/* - Disable the reset        */
 		/* - Enable the timer mode    */
 		/* - Set the timer mode       */
-		/******************************/
 
 		ui_Command =
 			(ui_Command & 0xFFF719E2UL) | ui_Mode << 13UL | 0x10UL;
 
-	}			/* if (data[0] == ADDIDATA_TIMER) */
-	else {
-		if (data[0] == ADDIDATA_WATCHDOG) {
+	} else if (data[0] == ADDIDATA_WATCHDOG) {
 
-			/******************************/
-			/* Set the mode :             */
-			/* - Disable the hardware     */
-			/* - Disable the counter mode */
-			/* - Disable the warning      */
-			/* - Disable the reset        */
-			/* - Disable the timer mode   */
-			/******************************/
+		/* Set the mode :             */
+		/* - Disable the hardware     */
+		/* - Disable the counter mode */
+		/* - Disable the warning      */
+		/* - Disable the reset        */
+		/* - Disable the timer mode   */
 
-			ui_Command = ui_Command & 0xFFF819E2UL;
+		ui_Command = ui_Command & 0xFFF819E2UL;
 
-		} else {
-			dev_err(dev->class_dev, "The parameter for Timer/watchdog selection is in error\n");
-			return -EINVAL;
-		}
+	} else {
+		dev_err(dev->class_dev, "The parameter for Timer/watchdog selection is in error\n");
+		return -EINVAL;
 	}
+
 	outl(ui_Command, devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
-	ui_Command = 0;
+
 	ui_Command = inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
-	/********************************/
+
 	/* Disable the hardware trigger */
-	/********************************/
 	ui_Command = ui_Command & 0xFFFFF89FUL;
 	if (data[4] == ADDIDATA_ENABLE) {
-		/**********************************/
+
 		/* Set the hardware trigger level */
-		/**********************************/
 		ui_Command = ui_Command | (data[5] << 5);
 	}
 	outl(ui_Command, devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
-	ui_Command = 0;
+
 	ui_Command = inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
-	/*****************************/
+
 	/* Disable the hardware gate */
-	/*****************************/
 	ui_Command = ui_Command & 0xFFFFF87FUL;
 	if (data[6] == ADDIDATA_ENABLE) {
-		/*******************************/
+
 		/* Set the hardware gate level */
-		/*******************************/
 		ui_Command = ui_Command | (data[7] << 7);
 	}
 	outl(ui_Command, devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
-	ui_Command = 0;
+
 	ui_Command = inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
-	/*******************************/
+
 	/* Disable the hardware output */
-	/*******************************/
 	ui_Command = ui_Command & 0xFFFFF9FBUL;
-	/*********************************/
+
 	/* Set the hardware output level */
-	/*********************************/
 	ui_Command = ui_Command | (data[8] << 2);
 	outl(ui_Command, devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
 	if (data[9] == ADDIDATA_ENABLE) {
-		/************************/
+
 		/* Set the reload value */
-		/************************/
 		outl(data[11],
 			devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 24);
-		/**********************/
+
 		/* Set the time unite */
-		/**********************/
 		outl(data[10],
 			devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 28);
 	}
 
-	ui_Command = 0;
 	ui_Command = inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
-	/*******************************/
+
 	/* Disable the hardware output */
-	/*******************************/
 	ui_Command = ui_Command & 0xFFFFF9F7UL;
-	/*********************************/
+
 	/* Set the hardware output level */
-	/*********************************/
 	ui_Command = ui_Command | (data[12] << 3);
 	outl(ui_Command, devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
-	/*************************************/
-	/**  Enable the watchdog interrupt  **/
-	/*************************************/
-	ui_Command = 0;
+
+	/* Enable the watchdog interrupt */
 	ui_Command = inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
-	/*******************************/
+
 	/* Set the interrupt selection */
-	/*******************************/
 	ui_Status = inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 16);
 
 	ui_Command = (ui_Command & 0xFFFFF9FDUL) | (data[13] << 1);
@@ -342,25 +318,23 @@
 						 unsigned int *data)
 {
 	struct addi_private *devpriv = dev->private;
-	unsigned int ui_Command = 0;
-	int i_Count = 0;
+	unsigned int ui_Command;
+	int i_Count;
 
 	if (data[0] == 1) {
 		ui_Command =
 			inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
-		/**********************/
+
 		/* Start the hardware */
-		/**********************/
 		ui_Command = (ui_Command & 0xFFFFF9FFUL) | 0x1UL;
 		outl(ui_Command,
 			devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
-	}			/*  if  (data[0]==1) */
+	}
 	if (data[0] == 2) {
 		ui_Command =
 			inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
-		/***************************/
+
 		/* Set the trigger command */
-		/***************************/
 		ui_Command = (ui_Command & 0xFFFFF9FFUL) | 0x200UL;
 		outl(ui_Command,
 			devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
@@ -375,7 +349,7 @@
 		*/
 		outl(ui_Command,
 			devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
-	}			/*   if (data[1]==0) */
+	}
 	if (data[0] == 3) {
 		/* stop all Watchdogs */
 		ui_Command = 0;
@@ -459,32 +433,23 @@
 				       unsigned int *data)
 {
 	struct addi_private *devpriv = dev->private;
-	unsigned int ui_Status = 0;	/*  Status register */
+	unsigned int ui_Status;	/*  Status register */
 
 	i_WatchdogNbr = insn->unused[0];
 
-	/******************/
 	/* Get the status */
-	/******************/
-
 	ui_Status = inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 16);
 
-	/***********************************/
 	/* Get the software trigger status */
-	/***********************************/
-
 	data[0] = ((ui_Status >> 1) & 1);
-	/***********************************/
+
 	/* Get the hardware trigger status */
-	/***********************************/
 	data[1] = ((ui_Status >> 2) & 1);
-	/*********************************/
+
 	/* Get the software clear status */
-	/*********************************/
 	data[2] = ((ui_Status >> 3) & 1);
-	/***************************/
+
 	/* Get the overflow status */
-	/***************************/
 	data[3] = ((ui_Status >> 0) & 1);
 	if (devpriv->b_TimerSelectMode == ADDIDATA_TIMER)
 		data[4] = inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 0);
@@ -525,9 +490,8 @@
 	devpriv->tsk_Current = current;
 	outl(0x200 | 0, devpriv->iobase + 128 + 0x4);
 	outl(0, devpriv->iobase + 128 + 0);
-	/********************************/
+
 	/* Initialise the warning value */
-	/********************************/
 	outl(0x300 | 0, devpriv->iobase + 128 + 0x4);
 	outl((data[0] << 8), devpriv->iobase + 128 + 0);
 	outl(0x200000UL, devpriv->iobase + 128 + 12);
@@ -562,20 +526,15 @@
 				     unsigned int *data)
 {
 	struct addi_private *devpriv = dev->private;
-	unsigned int ui_CommandRegister = 0;
+	unsigned int ui_CommandRegister;
 
-	/******************/
 	/*  Set the start */
-	/******************/
 	ui_CommandRegister = 0x80000;
-	/******************************/
+
 	/* Write the command register */
-	/******************************/
 	outl(ui_CommandRegister, devpriv->iobase + 128 + 8);
 
-	/***************************************/
 	/* Read the digital value of the input */
-	/***************************************/
 	data[0] = inl(devpriv->iobase + 128 + 28);
 	return insn->n;
 }
@@ -598,11 +557,13 @@
 static int i_APCI035_Reset(struct comedi_device *dev)
 {
 	struct addi_private *devpriv = dev->private;
-	int i_Count = 0;
+	int i_Count;
 
 	for (i_Count = 1; i_Count <= 4; i_Count++) {
 		i_WatchdogNbr = i_Count;
-		outl(0x0, devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 0);	/* stop all timers */
+
+		/* stop all timers */
+		outl(0x0, devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 0);
 	}
 	outl(0x0, devpriv->iobase + 128 + 12);	/* Disable the warning delay */
 
@@ -630,50 +591,45 @@
 {
 	struct comedi_device *dev = d;
 	struct addi_private *devpriv = dev->private;
-	unsigned int ui_StatusRegister1 = 0;
-	unsigned int ui_StatusRegister2 = 0;
-	unsigned int ui_ReadCommand = 0;
-	unsigned int ui_ChannelNumber = 0;
-	unsigned int ui_DigitalTemperature = 0;
+	unsigned int ui_StatusRegister1;
+	unsigned int ui_StatusRegister2;
+	unsigned int ui_ReadCommand;
+	unsigned int ui_ChannelNumber;
+	unsigned int ui_DigitalTemperature;
 
 	if (i_Temp == 1) {
 		i_WatchdogNbr = i_Flag;
 		i_Flag = i_Flag + 1;
 	}
-	/**************************************/
-	/* Read the interrupt status register of temperature Warning */
-	/**************************************/
-	ui_StatusRegister1 = inl(devpriv->iobase + 128 + 16);
-	/**************************************/
-	/* Read the interrupt status register for Watchdog/timer */
-	/**************************************/
 
+	/* Read the interrupt status register of temperature Warning */
+	ui_StatusRegister1 = inl(devpriv->iobase + 128 + 16);
+
+	/* Read the interrupt status register for Watchdog/timer */
 	ui_StatusRegister2 =
 		inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 20);
 
 	/* Test if warning relay interrupt */
 	if ((((ui_StatusRegister1) & 0x8) == 0x8)) {
-		/**********************************/
+
 		/* Disable the temperature warning */
-		/**********************************/
 		ui_ReadCommand = inl(devpriv->iobase + 128 + 12);
 		ui_ReadCommand = ui_ReadCommand & 0xFFDF0000UL;
 		outl(ui_ReadCommand, devpriv->iobase + 128 + 12);
-		/***************************/
-		/* Read the channel number */
-		/***************************/
-		ui_ChannelNumber = inl(devpriv->iobase + 128 + 60);
-		/**************************************/
-		/* Read the digital temperature value */
-		/**************************************/
-		ui_DigitalTemperature = inl(devpriv->iobase + 128 + 60);
-		send_sig(SIGIO, devpriv->tsk_Current, 0);	/*  send signal to the sample */
-	}			/* if (((ui_StatusRegister1 & 0x8) == 0x8)) */
 
-	else {
-		if ((ui_StatusRegister2 & 0x1) == 0x1)
-			send_sig(SIGIO, devpriv->tsk_Current, 0);	/*  send signal to the sample */
-	}			/* else if (((ui_StatusRegister1 & 0x8) == 0x8)) */
+		/* Read the channel number */
+		ui_ChannelNumber = inl(devpriv->iobase + 128 + 60);
+
+		/* Read the digital temperature value */
+		ui_DigitalTemperature = inl(devpriv->iobase + 128 + 60);
+
+		/*  send signal to the sample */
+		send_sig(SIGIO, devpriv->tsk_Current, 0);
+
+	} else if ((ui_StatusRegister2 & 0x1) == 0x1) {
+		/*  send signal to the sample */
+		send_sig(SIGIO, devpriv->tsk_Current, 0);
+	}
 
 	return;
 }
diff --git a/drivers/staging/comedi/drivers/ke_counter.c b/drivers/staging/comedi/drivers/ke_counter.c
index 1c32816..ec43c38 100644
--- a/drivers/staging/comedi/drivers/ke_counter.c
+++ b/drivers/staging/comedi/drivers/ke_counter.c
@@ -1,92 +1,113 @@
 /*
-    comedi/drivers/ke_counter.c
-    Comedi driver for Kolter-Electronic PCI Counter 1 Card
+ * ke_counter.c
+ * Comedi driver for Kolter-Electronic PCI Counter 1 Card
+ *
+ * COMEDI - Linux Control and Measurement Device Interface
+ * Copyright (C) 2000 David A. Schleef <ds@schleef.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
 
-    COMEDI - Linux Control and Measurement Device Interface
-    Copyright (C) 2000 David A. Schleef <ds@schleef.org>
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-*/
 /*
-Driver: ke_counter
-Description: Driver for Kolter Electronic Counter Card
-Devices: [Kolter Electronic] PCI Counter Card (ke_counter)
-Author: Michael Hillmann
-Updated: Mon, 14 Apr 2008 15:42:42 +0100
-Status: tested
-
-Configuration Options: not applicable, uses PCI auto config
-
-This driver is a simple driver to read the counter values from
-Kolter Electronic PCI Counter Card.
-*/
+ * Driver: ke_counter
+ * Description: Driver for Kolter Electronic Counter Card
+ * Devices: (Kolter Electronic) PCI Counter Card [ke_counter]
+ * Author: Michael Hillmann
+ * Updated: Mon, 14 Apr 2008 15:42:42 +0100
+ * Status: tested
+ *
+ * Configuration Options: not applicable, uses PCI auto config
+ */
 
 #include <linux/module.h>
 #include <linux/pci.h>
 
 #include "../comedidev.h"
 
-#define CNT_CARD_DEVICE_ID      0x0014
+/*
+ * PCI BAR 0 Register I/O map
+ */
+#define KE_RESET_REG(x)			(0x00 + ((x) * 0x20))
+#define KE_LATCH_REG(x)			(0x00 + ((x) * 0x20))
+#define KE_LSB_REG(x)			(0x04 + ((x) * 0x20))
+#define KE_MID_REG(x)			(0x08 + ((x) * 0x20))
+#define KE_MSB_REG(x)			(0x0c + ((x) * 0x20))
+#define KE_SIGN_REG(x)			(0x10 + ((x) * 0x20))
+#define KE_OSC_SEL_REG			0xf8
+#define KE_OSC_SEL_EXT			(1 << 0)
+#define KE_OSC_SEL_4MHZ			(2 << 0)
+#define KE_OSC_SEL_20MHZ		(3 << 0)
+#define KE_DO_REG			0xfc
 
-/*-- counter write ----------------------------------------------------------*/
-
-/* This should be used only for resetting the counters; maybe it is better
-   to make a special command 'reset'. */
-static int cnt_winsn(struct comedi_device *dev,
-		     struct comedi_subdevice *s, struct comedi_insn *insn,
-		     unsigned int *data)
+static int ke_counter_insn_write(struct comedi_device *dev,
+				 struct comedi_subdevice *s,
+				 struct comedi_insn *insn,
+				 unsigned int *data)
 {
-	int chan = CR_CHAN(insn->chanspec);
+	unsigned int chan = CR_CHAN(insn->chanspec);
+	unsigned int val;
+	int i;
 
-	outb((unsigned char)((data[0] >> 24) & 0xff),
-	     dev->iobase + chan * 0x20 + 0x10);
-	outb((unsigned char)((data[0] >> 16) & 0xff),
-	     dev->iobase + chan * 0x20 + 0x0c);
-	outb((unsigned char)((data[0] >> 8) & 0xff),
-	     dev->iobase + chan * 0x20 + 0x08);
-	outb((unsigned char)((data[0] >> 0) & 0xff),
-	     dev->iobase + chan * 0x20 + 0x04);
+	for (i = 0; i < insn->n; i++) {
+		val = data[0];
 
-	/* return the number of samples written */
-	return 1;
+		/* Order matters */
+		outb((val >> 24) & 0xff, dev->iobase + KE_SIGN_REG(chan));
+		outb((val >> 16) & 0xff, dev->iobase + KE_MSB_REG(chan));
+		outb((val >> 8) & 0xff, dev->iobase + KE_MID_REG(chan));
+		outb((val >> 0) & 0xff, dev->iobase + KE_LSB_REG(chan));
+	}
+
+	return insn->n;
 }
 
-/*-- counter read -----------------------------------------------------------*/
-
-static int cnt_rinsn(struct comedi_device *dev,
-		     struct comedi_subdevice *s, struct comedi_insn *insn,
-		     unsigned int *data)
+static int ke_counter_insn_read(struct comedi_device *dev,
+				struct comedi_subdevice *s,
+				struct comedi_insn *insn,
+				unsigned int *data)
 {
-	unsigned char a0, a1, a2, a3, a4;
-	int chan = CR_CHAN(insn->chanspec);
-	int result;
+	unsigned int chan = CR_CHAN(insn->chanspec);
+	unsigned int val;
+	int i;
 
-	a0 = inb(dev->iobase + chan * 0x20);
-	a1 = inb(dev->iobase + chan * 0x20 + 0x04);
-	a2 = inb(dev->iobase + chan * 0x20 + 0x08);
-	a3 = inb(dev->iobase + chan * 0x20 + 0x0c);
-	a4 = inb(dev->iobase + chan * 0x20 + 0x10);
+	for (i = 0; i < insn->n; i++) {
+		/* Order matters */
+		inb(dev->iobase + KE_LATCH_REG(chan));
 
-	result = (a1 + (a2 * 256) + (a3 * 65536));
-	if (a4 > 0)
-		result = result - s->maxdata;
+		val = inb(dev->iobase + KE_LSB_REG(chan));
+		val |= (inb(dev->iobase + KE_MID_REG(chan)) << 8);
+		val |= (inb(dev->iobase + KE_MSB_REG(chan)) << 16);
+		val |= (inb(dev->iobase + KE_SIGN_REG(chan)) << 24);
 
-	*data = (unsigned int)result;
+		data[i] = val;
+	}
 
-	/* return the number of samples read */
-	return 1;
+	return insn->n;
 }
 
-static int cnt_auto_attach(struct comedi_device *dev,
-				     unsigned long context_unused)
+static int ke_counter_do_insn_bits(struct comedi_device *dev,
+				   struct comedi_subdevice *s,
+				   struct comedi_insn *insn,
+				   unsigned int *data)
+{
+	if (comedi_dio_update_state(s, data))
+		outb(s->state, dev->iobase + KE_DO_REG);
+
+	data[1] = s->state;
+
+	return insn->n;
+}
+
+static int ke_counter_auto_attach(struct comedi_device *dev,
+				  unsigned long context_unused)
 {
 	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
 	struct comedi_subdevice *s;
@@ -97,27 +118,32 @@
 		return ret;
 	dev->iobase = pci_resource_start(pcidev, 0);
 
-	ret = comedi_alloc_subdevices(dev, 1);
+	ret = comedi_alloc_subdevices(dev, 2);
 	if (ret)
 		return ret;
 
 	s = &dev->subdevices[0];
-	dev->read_subdev = s;
+	s->type		= COMEDI_SUBD_COUNTER;
+	s->subdev_flags	= SDF_READABLE;
+	s->n_chan	= 3;
+	s->maxdata	= 0x01ffffff;
+	s->range_table	= &range_unknown;
+	s->insn_read	= ke_counter_insn_read;
+	s->insn_write	= ke_counter_insn_write;
 
-	s->type = COMEDI_SUBD_COUNTER;
-	s->subdev_flags = SDF_READABLE /* | SDF_COMMON */ ;
-	s->n_chan = 3;
-	s->maxdata = 0x00ffffff;
-	s->insn_read = cnt_rinsn;
-	s->insn_write = cnt_winsn;
+	s = &dev->subdevices[1];
+	s->type		= COMEDI_SUBD_DO;
+	s->subdev_flags	= SDF_WRITABLE;
+	s->n_chan	= 3;
+	s->maxdata	= 1;
+	s->range_table	= &range_digital;
+	s->insn_bits	= ke_counter_do_insn_bits;
 
-	/*  select 20MHz clock */
-	outb(3, dev->iobase + 248);
+	outb(KE_OSC_SEL_20MHZ, dev->iobase + KE_OSC_SEL_REG);
 
-	/*  reset all counters */
-	outb(0, dev->iobase);
-	outb(0, dev->iobase + 0x20);
-	outb(0, dev->iobase + 0x40);
+	outb(0, dev->iobase + KE_RESET_REG(0));
+	outb(0, dev->iobase + KE_RESET_REG(1));
+	outb(0, dev->iobase + KE_RESET_REG(2));
 
 	return 0;
 }
@@ -125,7 +151,7 @@
 static struct comedi_driver ke_counter_driver = {
 	.driver_name	= "ke_counter",
 	.module		= THIS_MODULE,
-	.auto_attach	= cnt_auto_attach,
+	.auto_attach	= ke_counter_auto_attach,
 	.detach		= comedi_pci_disable,
 };
 
@@ -137,7 +163,7 @@
 }
 
 static const struct pci_device_id ke_counter_pci_table[] = {
-	{ PCI_DEVICE(PCI_VENDOR_ID_KOLTER, CNT_CARD_DEVICE_ID) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_KOLTER, 0x0014) },
 	{ 0 }
 };
 MODULE_DEVICE_TABLE(pci, ke_counter_pci_table);
@@ -151,5 +177,5 @@
 module_comedi_pci_driver(ke_counter_driver, ke_counter_pci_driver);
 
 MODULE_AUTHOR("Comedi http://www.comedi.org");
-MODULE_DESCRIPTION("Comedi low-level driver");
+MODULE_DESCRIPTION("Comedi driver for Kolter Electronic Counter Card");
 MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/ni_mio_common.c b/drivers/staging/comedi/drivers/ni_mio_common.c
index 8adb535..3a86d48 100644
--- a/drivers/staging/comedi/drivers/ni_mio_common.c
+++ b/drivers/staging/comedi/drivers/ni_mio_common.c
@@ -4407,6 +4407,9 @@
 							&ni_gpct_read_register,
 							counter_variant,
 							NUM_GPCT);
+	if (!devpriv->counter_dev)
+		return -ENOMEM;
+
 	/* General purpose counters */
 	for (j = 0; j < NUM_GPCT; ++j) {
 		s = &dev->subdevices[NI_GPCT_SUBDEV(j)];
diff --git a/drivers/staging/cxt1e1/comet_tables.c b/drivers/staging/cxt1e1/comet_tables.c
index 8493111..e96665e 100644
--- a/drivers/staging/cxt1e1/comet_tables.c
+++ b/drivers/staging/cxt1e1/comet_tables.c
@@ -19,6 +19,7 @@
  */
 
 #include <linux/types.h>
+#include "comet_tables.h"
 
 /*****************************************************************************
 *
diff --git a/drivers/staging/cxt1e1/functions.c b/drivers/staging/cxt1e1/functions.c
index f5ce852..40dbe2c 100644
--- a/drivers/staging/cxt1e1/functions.c
+++ b/drivers/staging/cxt1e1/functions.c
@@ -25,7 +25,8 @@
 #include "pmcc4.h"
 
 #if defined(CONFIG_SBE_HDLC_V7) || defined(CONFIG_SBE_WAN256T3_HDLC_V7) || \
-    defined(CONFIG_SBE_HDLC_V7_MODULE) || defined(CONFIG_SBE_WAN256T3_HDLC_V7_MODULE)
+defined(CONFIG_SBE_HDLC_V7_MODULE) || \
+defined(CONFIG_SBE_WAN256T3_HDLC_V7_MODULE)
 #define _v7_hdlc_  1
 #else
 #define _v7_hdlc_  0
@@ -33,9 +34,9 @@
 
 #if _v7_hdlc_
 #define V7(x) (x ## _v7)
-extern int  hdlc_netif_rx_v7 (hdlc_device *, struct sk_buff *);
-extern int  register_hdlc_device_v7 (hdlc_device *);
-extern int  unregister_hdlc_device_v7 (hdlc_device *);
+extern int  hdlc_netif_rx_v7(hdlc_device *, struct sk_buff *);
+extern int  register_hdlc_device_v7(hdlc_device *);
+extern int  unregister_hdlc_device_v7(hdlc_device *);
 
 #else
 #define V7(x) x
@@ -53,49 +54,49 @@
 
 #if 1
 u_int32_t
-pci_read_32 (u_int32_t *p)
+pci_read_32(u_int32_t *p)
 {
 #ifdef FLOW_DEBUG
-    u_int32_t   v;
+	u_int32_t   v;
 
-    FLUSH_PCI_READ ();
-    v = le32_to_cpu (*p);
-    if (cxt1e1_log_level >= LOG_DEBUG)
-        pr_info("pci_read : %x = %x\n", (u_int32_t) p, v);
-    return v;
+	FLUSH_PCI_READ();
+	v = le32_to_cpu(*p);
+	if (cxt1e1_log_level >= LOG_DEBUG)
+		pr_info("pci_read : %x = %x\n", (u_int32_t) p, v);
+	return v;
 #else
-    FLUSH_PCI_READ ();              /* */
-    return le32_to_cpu (*p);
+	FLUSH_PCI_READ();              /* */
+	return le32_to_cpu(*p);
 #endif
 }
 
 void
-pci_write_32 (u_int32_t *p, u_int32_t v)
+pci_write_32(u_int32_t *p, u_int32_t v)
 {
 #ifdef FLOW_DEBUG
-    if (cxt1e1_log_level >= LOG_DEBUG)
-        pr_info("pci_write: %x = %x\n", (u_int32_t) p, v);
+	if (cxt1e1_log_level >= LOG_DEBUG)
+		pr_info("pci_write: %x = %x\n", (u_int32_t) p, v);
 #endif
-    *p = cpu_to_le32 (v);
-    FLUSH_PCI_WRITE ();             /* This routine is called from routines
-                                     * which do multiple register writes
-                                     * which themselves need flushing between
-                                     * writes in order to guarantee write
-                                     * ordering.  It is less code-cumbersome
-                                     * to flush here-in then to investigate
-                                     * and code the many other register
-                                     * writing routines. */
+	*p = cpu_to_le32 (v);
+	FLUSH_PCI_WRITE();             /* This routine is called from routines
+					* which do multiple register writes
+					* which themselves need flushing between
+					* writes in order to guarantee write
+					* ordering.  It is less code-cumbersome
+					* to flush here-in then to investigate
+					* and code the many other register
+					* writing routines. */
 }
 #endif
 
 
 void
-pci_flush_write (ci_t *ci)
+pci_flush_write(ci_t *ci)
 {
-    volatile u_int32_t v;
+	volatile u_int32_t v;
 
     /* issue a PCI read to flush PCI write thru bridge */
-    v = *(u_int32_t *) &ci->reg->glcd;  /* any address would do */
+	v = *(u_int32_t *) &ci->reg->glcd;  /* any address would do */
 
     /*
      * return nothing, this just reads PCI bridge interface to flush
@@ -105,55 +106,53 @@
 
 
 static void
-watchdog_func (unsigned long arg)
+watchdog_func(unsigned long arg)
 {
-    struct watchdog *wd = (void *) arg;
+	struct watchdog *wd = (void *) arg;
 
-    if (drvr_state != SBE_DRVR_AVAILABLE)
-    {
-        if (cxt1e1_log_level >= LOG_MONITOR)
-            pr_warning("%s: drvr not available (%x)\n", __func__, drvr_state);
-        return;
-    }
-    schedule_work (&wd->work);
-    mod_timer (&wd->h, jiffies + wd->ticks);
+	if (drvr_state != SBE_DRVR_AVAILABLE) {
+		if (cxt1e1_log_level >= LOG_MONITOR)
+			pr_warning("%s: drvr not available (%x)\n",
+				   __func__, drvr_state);
+		return;
+	}
+	schedule_work(&wd->work);
+	mod_timer(&wd->h, jiffies + wd->ticks);
 }
 
-int OS_init_watchdog(struct watchdog *wdp, void (*f) (void *), void *c, int usec)
+int OS_init_watchdog(struct watchdog *wdp, void (*f) (void *),
+		     void *c, int usec)
 {
-    wdp->func = f;
-    wdp->softc = c;
-    wdp->ticks = (HZ) * (usec / 1000) / 1000;
-    INIT_WORK(&wdp->work, (void *)f);
-    init_timer (&wdp->h);
-    {
-        ci_t       *ci = (ci_t *) c;
+	wdp->func = f;
+	wdp->softc = c;
+	wdp->ticks = (HZ) * (usec / 1000) / 1000;
+	INIT_WORK(&wdp->work, (void *)f);
+	init_timer(&wdp->h);
+	{
+		ci_t       *ci = (ci_t *) c;
 
-        wdp->h.data = (unsigned long) &ci->wd;
-    }
-    wdp->h.function = watchdog_func;
-    return 0;
+		wdp->h.data = (unsigned long) &ci->wd;
+	}
+	wdp->h.function = watchdog_func;
+	return 0;
 }
 
 void
-OS_uwait (int usec, char *description)
+OS_uwait(int usec, char *description)
 {
-    int         tmp;
+	int         tmp;
 
-    if (usec >= 1000)
-    {
-        mdelay (usec / 1000);
-        /* now delay residual */
-        tmp = (usec / 1000) * 1000; /* round */
-        tmp = usec - tmp;           /* residual */
-        if (tmp)
-        {                           /* wait on residual */
-            udelay (tmp);
-        }
-    } else
-    {
-        udelay (usec);
-    }
+	if (usec >= 1000) {
+		mdelay(usec / 1000);
+		/* now delay residual */
+		tmp = (usec / 1000) * 1000; /* round */
+		tmp = usec - tmp;           /* residual */
+		if (tmp) {                           /* wait on residual */
+			udelay(tmp);
+		}
+	} else {
+		udelay(usec);
+	}
 }
 
 /* dummy short delay routine called as a subroutine so that compiler
@@ -161,96 +160,95 @@
  */
 
 void
-OS_uwait_dummy (void)
+OS_uwait_dummy(void)
 {
 #ifndef USE_MAX_INT_DELAY
-    dummy++;
+	dummy++;
 #else
-    udelay (1);
+	udelay(1);
 #endif
 }
 
 
 void
-OS_sem_init (void *sem, int state)
+OS_sem_init(void *sem, int state)
 {
-    switch (state)
-    {
-        case SEM_TAKEN:
-		sema_init((struct semaphore *) sem, 0);
-        break;
-    case SEM_AVAILABLE:
+	switch (state) {
+	case SEM_TAKEN:
+	    sema_init((struct semaphore *) sem, 0);
+	    break;
+	case SEM_AVAILABLE:
 	    sema_init((struct semaphore *) sem, 1);
-        break;
-    default:                        /* otherwise, set sem.count to state's
-                                     * value */
-        sema_init (sem, state);
-        break;
-    }
+	    break;
+	default:                        /* otherwise, set sem.count to state's
+					* value */
+	    sema_init(sem, state);
+	    break;
+	}
 }
 
 
 int
-sd_line_is_ok (void *user)
+sd_line_is_ok(void *user)
 {
-    struct net_device *ndev = (struct net_device *) user;
+	struct net_device *ndev = (struct net_device *) user;
 
-    return netif_carrier_ok (ndev);
+	return netif_carrier_ok(ndev);
 }
 
 void
-sd_line_is_up (void *user)
+sd_line_is_up(void *user)
 {
-    struct net_device *ndev = (struct net_device *) user;
+	struct net_device *ndev = (struct net_device *) user;
 
-    netif_carrier_on (ndev);
-    return;
+	netif_carrier_on(ndev);
+	return;
 }
 
 void
-sd_line_is_down (void *user)
+sd_line_is_down(void *user)
 {
-    struct net_device *ndev = (struct net_device *) user;
+	struct net_device *ndev = (struct net_device *) user;
 
-    netif_carrier_off (ndev);
-    return;
+	netif_carrier_off(ndev);
+	return;
 }
 
 void
-sd_disable_xmit (void *user)
+sd_disable_xmit(void *user)
 {
-    struct net_device *dev = (struct net_device *) user;
+	struct net_device *dev = (struct net_device *) user;
 
-    netif_stop_queue (dev);
-    return;
+	netif_stop_queue(dev);
+	return;
 }
 
 void
-sd_enable_xmit (void *user)
+sd_enable_xmit(void *user)
 {
-    struct net_device *dev = (struct net_device *) user;
+	struct net_device *dev = (struct net_device *) user;
 
-    netif_wake_queue (dev);
-    return;
+	netif_wake_queue(dev);
+	return;
 }
 
 int
-sd_queue_stopped (void *user)
+sd_queue_stopped(void *user)
 {
-    struct net_device *ndev = (struct net_device *) user;
+	struct net_device *ndev = (struct net_device *) user;
 
-    return netif_queue_stopped (ndev);
+	return netif_queue_stopped(ndev);
 }
 
 void sd_recv_consume(void *token, size_t len, void *user)
 {
-    struct net_device *ndev = user;
-    struct sk_buff *skb = token;
+	struct net_device *ndev = user;
+	struct sk_buff *skb = token;
 
-    skb->dev = ndev;
-    skb_put (skb, len);
-    skb->protocol = hdlc_type_trans(skb, ndev);
-    netif_rx(skb);
+	skb->dev = ndev;
+	skb_put(skb, len);
+	skb->protocol = hdlc_type_trans(skb, ndev);
+	netif_rx(skb);
 }
 
 
@@ -263,77 +261,76 @@
 
 extern ci_t *CI;                /* dummy pointer to board ZERO's data */
 void
-VMETRO_TRIGGER (ci_t *ci, int x)
+VMETRO_TRIGGER(ci_t *ci, int x)
 {
-    struct s_comet_reg    *comet;
-    volatile u_int32_t data;
+	struct s_comet_reg    *comet;
+	volatile u_int32_t data;
 
-    comet = ci->port[0].cometbase;  /* default to COMET # 0 */
+	comet = ci->port[0].cometbase;  /* default to COMET # 0 */
 
-    switch (x)
-    {
-    default:
-    case 0:
-        data = pci_read_32 ((u_int32_t *) &comet->__res24);     /* 0x90 */
-        break;
-    case 1:
-        data = pci_read_32 ((u_int32_t *) &comet->__res25);     /* 0x94 */
-        break;
-    case 2:
-        data = pci_read_32 ((u_int32_t *) &comet->__res26);     /* 0x98 */
-        break;
-    case 3:
-        data = pci_read_32 ((u_int32_t *) &comet->__res27);     /* 0x9C */
-        break;
-    case 4:
-        data = pci_read_32 ((u_int32_t *) &comet->__res88);     /* 0x220 */
-        break;
-    case 5:
-        data = pci_read_32 ((u_int32_t *) &comet->__res89);     /* 0x224 */
-        break;
-    case 6:
-        data = pci_read_32 ((u_int32_t *) &comet->__res8A);     /* 0x228 */
-        break;
-    case 7:
-        data = pci_read_32 ((u_int32_t *) &comet->__res8B);     /* 0x22C */
-        break;
-    case 8:
-        data = pci_read_32 ((u_int32_t *) &comet->__resA0);     /* 0x280 */
-        break;
-    case 9:
-        data = pci_read_32 ((u_int32_t *) &comet->__resA1);     /* 0x284 */
-        break;
-    case 10:
-        data = pci_read_32 ((u_int32_t *) &comet->__resA2);     /* 0x288 */
-        break;
-    case 11:
-        data = pci_read_32 ((u_int32_t *) &comet->__resA3);     /* 0x28C */
-        break;
-    case 12:
-        data = pci_read_32 ((u_int32_t *) &comet->__resA4);     /* 0x290 */
-        break;
-    case 13:
-        data = pci_read_32 ((u_int32_t *) &comet->__resA5);     /* 0x294 */
-        break;
-    case 14:
-        data = pci_read_32 ((u_int32_t *) &comet->__resA6);     /* 0x298 */
-        break;
-    case 15:
-        data = pci_read_32 ((u_int32_t *) &comet->__resA7);     /* 0x29C */
-        break;
-    case 16:
-        data = pci_read_32 ((u_int32_t *) &comet->__res74);     /* 0x1D0 */
-        break;
-    case 17:
-        data = pci_read_32 ((u_int32_t *) &comet->__res75);     /* 0x1D4 */
-        break;
-    case 18:
-        data = pci_read_32 ((u_int32_t *) &comet->__res76);     /* 0x1D8 */
-        break;
-    case 19:
-        data = pci_read_32 ((u_int32_t *) &comet->__res77);     /* 0x1DC */
-        break;
-    }
+	switch (x) {
+	default:
+	case 0:
+	    data = pci_read_32((u_int32_t *) &comet->__res24);     /* 0x90 */
+	    break;
+	case 1:
+	    data = pci_read_32((u_int32_t *) &comet->__res25);     /* 0x94 */
+	    break;
+	case 2:
+	    data = pci_read_32((u_int32_t *) &comet->__res26);     /* 0x98 */
+	    break;
+	case 3:
+	    data = pci_read_32((u_int32_t *) &comet->__res27);     /* 0x9C */
+	    break;
+	case 4:
+	    data = pci_read_32((u_int32_t *) &comet->__res88);     /* 0x220 */
+	    break;
+	case 5:
+	    data = pci_read_32((u_int32_t *) &comet->__res89);     /* 0x224 */
+	    break;
+	case 6:
+	    data = pci_read_32((u_int32_t *) &comet->__res8A);     /* 0x228 */
+	    break;
+	case 7:
+	    data = pci_read_32((u_int32_t *) &comet->__res8B);     /* 0x22C */
+	    break;
+	case 8:
+	    data = pci_read_32((u_int32_t *) &comet->__resA0);     /* 0x280 */
+	    break;
+	case 9:
+	    data = pci_read_32((u_int32_t *) &comet->__resA1);     /* 0x284 */
+	    break;
+	case 10:
+	    data = pci_read_32((u_int32_t *) &comet->__resA2);     /* 0x288 */
+	    break;
+	case 11:
+	    data = pci_read_32((u_int32_t *) &comet->__resA3);     /* 0x28C */
+	    break;
+	case 12:
+	    data = pci_read_32((u_int32_t *) &comet->__resA4);     /* 0x290 */
+	    break;
+	case 13:
+	    data = pci_read_32((u_int32_t *) &comet->__resA5);     /* 0x294 */
+	    break;
+	case 14:
+	    data = pci_read_32((u_int32_t *) &comet->__resA6);     /* 0x298 */
+	    break;
+	case 15:
+	    data = pci_read_32((u_int32_t *) &comet->__resA7);     /* 0x29C */
+	    break;
+	case 16:
+	    data = pci_read_32((u_int32_t *) &comet->__res74);     /* 0x1D0 */
+	    break;
+	case 17:
+	    data = pci_read_32((u_int32_t *) &comet->__res75);     /* 0x1D4 */
+	    break;
+	case 18:
+	    data = pci_read_32((u_int32_t *) &comet->__res76);     /* 0x1D8 */
+	    break;
+	case 19:
+	    data = pci_read_32((u_int32_t *) &comet->__res77);     /* 0x1DC */
+	    break;
+	}
 }
 
 
diff --git a/drivers/staging/cxt1e1/hwprobe.c b/drivers/staging/cxt1e1/hwprobe.c
index 02b4f8f..d87a011 100644
--- a/drivers/staging/cxt1e1/hwprobe.c
+++ b/drivers/staging/cxt1e1/hwprobe.c
@@ -36,355 +36,354 @@
 extern int  drvr_state;
 
 /* forward references */
-void        c4_stopwd (ci_t *);
-struct net_device * __init c4_add_dev (hdw_info_t *, int, unsigned long, unsigned long, int, int);
+void        c4_stopwd(ci_t *);
+struct net_device * __init c4_add_dev(hdw_info_t *, int, unsigned long,
+				      unsigned long, int, int);
 
 
 struct s_hdw_info hdw_info[MAX_BOARDS];
 
 
-void        __init
-show_two (hdw_info_t *hi, int brdno)
+void __init
+show_two(hdw_info_t *hi, int brdno)
 {
-    ci_t       *ci;
-    struct pci_dev *pdev;
-    char       *bid;
-    char       *bp, banner[80];
-    char        sn[6];
+	ci_t       *ci;
+	struct pci_dev *pdev;
+	char       *bid;
+	char       banner[80];
+	char	sn[6];
 
-    bp = banner;
-    memset (banner, 0, 80);         /* clear print buffer */
+	/* clear print buffer */
+	memset(banner, 0, 80);
 
-    ci = (ci_t *)(netdev_priv(hi->ndev));
-    bid = sbeid_get_bdname (ci);
-    switch (hi->promfmt)
-    {
-    case PROM_FORMAT_TYPE1:
-        memcpy (sn, (FLD_TYPE1 *) (hi->mfg_info.pft1.Serial), 6);
-        break;
-    case PROM_FORMAT_TYPE2:
-        memcpy (sn, (FLD_TYPE2 *) (hi->mfg_info.pft2.Serial), 6);
-        break;
-    default:
-        memset (sn, 0, 6);
-        break;
-    }
+	ci = (ci_t *)(netdev_priv(hi->ndev));
+	bid = sbeid_get_bdname(ci);
+	switch (hi->promfmt) {
+	case PROM_FORMAT_TYPE1:
+		memcpy(sn, (FLD_TYPE1 *)(hi->mfg_info.pft1.Serial), 6);
+		break;
+	case PROM_FORMAT_TYPE2:
+		memcpy(sn, (FLD_TYPE2 *)(hi->mfg_info.pft2.Serial), 6);
+		break;
+	default:
+		memset(sn, 0, 6);
+		break;
+	}
 
-    sprintf (banner, "%s: %s  S/N %06X, MUSYCC Rev %02X",
-             hi->devname, bid,
-             ((sn[3] << 16) & 0xff0000) |
-              ((sn[4] << 8) & 0x00ff00) |
-              (sn[5] & 0x0000ff),
-             (u_int8_t) hi->revid[0]);
+	sprintf(banner, "%s: %s  S/N %06X, MUSYCC Rev %02X",
+		hi->devname, bid,
+		((sn[3] << 16) & 0xff0000) |
+		((sn[4] << 8) & 0x00ff00) |
+		(sn[5] & 0x0000ff),
+		(u_int8_t) hi->revid[0]);
 
-    pr_info("%s\n", banner);
+	pr_info("%s\n", banner);
 
-    pdev = hi->pdev[0];
-    pr_info("%s: %s at v/p=%lx/%lx (%02x:%02x.%x) irq %d\n",
-            hi->devname, "MUSYCC",
-            (unsigned long) hi->addr_mapped[0], hi->addr[0],
-            hi->pci_busno, (u_int8_t) PCI_SLOT (pdev->devfn),
-            (u_int8_t) PCI_FUNC (pdev->devfn), pdev->irq);
+	pdev = hi->pdev[0];
+	pr_info("%s: %s at v/p=%lx/%lx (%02x:%02x.%x) irq %d\n",
+		hi->devname, "MUSYCC",
+		(unsigned long) hi->addr_mapped[0], hi->addr[0],
+		hi->pci_busno, (u_int8_t) PCI_SLOT(pdev->devfn),
+		(u_int8_t) PCI_FUNC(pdev->devfn), pdev->irq);
 
-    pdev = hi->pdev[1];
-    pr_info("%s: %s at v/p=%lx/%lx (%02x:%02x.%x) irq %d\n",
-            hi->devname, "EBUS  ",
-            (unsigned long) hi->addr_mapped[1], hi->addr[1],
-            hi->pci_busno, (u_int8_t) PCI_SLOT (pdev->devfn),
-            (u_int8_t) PCI_FUNC (pdev->devfn), pdev->irq);
+	pdev = hi->pdev[1];
+	pr_info("%s: %s at v/p=%lx/%lx (%02x:%02x.%x) irq %d\n",
+		hi->devname, "EBUS  ",
+		(unsigned long) hi->addr_mapped[1], hi->addr[1],
+		hi->pci_busno, (u_int8_t) PCI_SLOT(pdev->devfn),
+		(u_int8_t) PCI_FUNC(pdev->devfn), pdev->irq);
 }
 
 
-void        __init
-hdw_sn_get (hdw_info_t *hi, int brdno)
+void __init
+hdw_sn_get(hdw_info_t *hi, int brdno)
 {
-    /* obtain hardware EEPROM information */
-    long        addr;
+	/* obtain hardware EEPROM information */
+	long        addr;
 
-    addr = (long) hi->addr_mapped[1] + EEPROM_OFFSET;
+	addr = (long) hi->addr_mapped[1] + EEPROM_OFFSET;
 
-    /* read EEPROM with largest known format size... */
-    pmc_eeprom_read_buffer (addr, 0, (char *) hi->mfg_info.data, sizeof (FLD_TYPE2));
+	/* read EEPROM with largest known format size... */
+	pmc_eeprom_read_buffer(addr, 0, (char *)hi->mfg_info.data,
+			       sizeof(FLD_TYPE2));
 
 #if 0
-    {
-        unsigned char *ucp = (unsigned char *) &hi->mfg_info.data;
+	{
+		unsigned char *ucp = (unsigned char *) &hi->mfg_info.data;
 
-        pr_info("eeprom[00]:  %02x %02x %02x %02x  %02x %02x %02x %02x\n",
-                *(ucp + 0), *(ucp + 1), *(ucp + 2), *(ucp + 3), *(ucp + 4), *(ucp + 5), *(ucp + 6), *(ucp + 7));
-        pr_info("eeprom[08]:  %02x %02x %02x %02x  %02x %02x %02x %02x\n",
-                *(ucp + 8), *(ucp + 9), *(ucp + 10), *(ucp + 11), *(ucp + 12), *(ucp + 13), *(ucp + 14), *(ucp + 15));
-        pr_info("eeprom[16]:  %02x %02x %02x %02x  %02x %02x %02x %02x\n",
-                *(ucp + 16), *(ucp + 17), *(ucp + 18), *(ucp + 19), *(ucp + 20), *(ucp + 21), *(ucp + 22), *(ucp + 23));
-        pr_info("eeprom[24]:  %02x %02x %02x %02x  %02x %02x %02x %02x\n",
-                *(ucp + 24), *(ucp + 25), *(ucp + 26), *(ucp + 27), *(ucp + 28), *(ucp + 29), *(ucp + 30), *(ucp + 31));
-        pr_info("eeprom[32]:  %02x %02x %02x %02x  %02x %02x %02x %02x\n",
-                *(ucp + 32), *(ucp + 33), *(ucp + 34), *(ucp + 35), *(ucp + 36), *(ucp + 37), *(ucp + 38), *(ucp + 39));
-        pr_info("eeprom[40]:  %02x %02x %02x %02x  %02x %02x %02x %02x\n",
-                *(ucp + 40), *(ucp + 41), *(ucp + 42), *(ucp + 43), *(ucp + 44), *(ucp + 45), *(ucp + 46), *(ucp + 47));
-    }
+		pr_info("eeprom[00]:  %02x %02x %02x %02x  %02x %02x %02x %02x\n",
+			*(ucp + 0), *(ucp + 1), *(ucp + 2), *(ucp + 3),
+			*(ucp + 4), *(ucp + 5), *(ucp + 6), *(ucp + 7));
+		pr_info("eeprom[08]:  %02x %02x %02x %02x  %02x %02x %02x %02x\n",
+			*(ucp + 8), *(ucp + 9), *(ucp + 10), *(ucp + 11),
+			*(ucp + 12), *(ucp + 13), *(ucp + 14), *(ucp + 15));
+		pr_info("eeprom[16]:  %02x %02x %02x %02x  %02x %02x %02x %02x\n",
+			*(ucp + 16), *(ucp + 17), *(ucp + 18), *(ucp + 19),
+			*(ucp + 20), *(ucp + 21), *(ucp + 22), *(ucp + 23));
+		pr_info("eeprom[24]:  %02x %02x %02x %02x  %02x %02x %02x %02x\n",
+			*(ucp + 24), *(ucp + 25), *(ucp + 26), *(ucp + 27),
+			*(ucp + 28), *(ucp + 29), *(ucp + 30), *(ucp + 31));
+		pr_info("eeprom[32]:  %02x %02x %02x %02x  %02x %02x %02x %02x\n",
+			*(ucp + 32), *(ucp + 33), *(ucp + 34), *(ucp + 35),
+			*(ucp + 36), *(ucp + 37), *(ucp + 38), *(ucp + 39));
+		pr_info("eeprom[40]:  %02x %02x %02x %02x  %02x %02x %02x %02x\n",
+			*(ucp + 40), *(ucp + 41), *(ucp + 42), *(ucp + 43),
+			*(ucp + 44), *(ucp + 45), *(ucp + 46), *(ucp + 47));
+	}
 #endif
 #if 0
-    pr_info("sn: %x %x %x %x %x %x\n",
-            hi->mfg_info.Serial[0],
-            hi->mfg_info.Serial[1],
-            hi->mfg_info.Serial[2],
-            hi->mfg_info.Serial[3],
-            hi->mfg_info.Serial[4],
-            hi->mfg_info.Serial[5]);
+	pr_info("sn: %x %x %x %x %x %x\n",
+			hi->mfg_info.Serial[0],
+			hi->mfg_info.Serial[1],
+			hi->mfg_info.Serial[2],
+			hi->mfg_info.Serial[3],
+			hi->mfg_info.Serial[4],
+			hi->mfg_info.Serial[5]);
 #endif
 
-    if ((hi->promfmt = pmc_verify_cksum (&hi->mfg_info.data)) == PROM_FORMAT_Unk)
-    {
-        /* bad crc, data is suspect */
-        if (cxt1e1_log_level >= LOG_WARN)
-            pr_info("%s: EEPROM cksum error\n", hi->devname);
-        hi->mfg_info_sts = EEPROM_CRCERR;
-    } else
-        hi->mfg_info_sts = EEPROM_OK;
+	hi->promfmt = pmc_verify_cksum(&hi->mfg_info.data);
+	if (hi->promfmt == PROM_FORMAT_Unk) {
+		/* bad crc, data is suspect */
+		if (cxt1e1_log_level >= LOG_WARN)
+			pr_info("%s: EEPROM cksum error\n", hi->devname);
+		hi->mfg_info_sts = EEPROM_CRCERR;
+	} else
+		hi->mfg_info_sts = EEPROM_OK;
 }
 
 
-void        __init
-prep_hdw_info (void)
+	void __init
+prep_hdw_info(void)
 {
-    hdw_info_t *hi;
-    int         i;
+	hdw_info_t *hi;
+	int         i;
 
-    for (i = 0, hi = hdw_info; i < MAX_BOARDS; i++, hi++)
-    {
-        hi->pci_busno = 0xff;
-        hi->pci_slot = 0xff;
-        hi->pci_pin[0] = 0;
-        hi->pci_pin[1] = 0;
-        hi->ndev = NULL;
-        hi->addr[0] = 0L;
-        hi->addr[1] = 0L;
-        hi->addr_mapped[0] = 0L;
-        hi->addr_mapped[1] = 0L;
-    }
+	for (i = 0, hi = hdw_info; i < MAX_BOARDS; i++, hi++) {
+		hi->pci_busno = 0xff;
+		hi->pci_slot = 0xff;
+		hi->pci_pin[0] = 0;
+		hi->pci_pin[1] = 0;
+		hi->ndev = NULL;
+		hi->addr[0] = 0L;
+		hi->addr[1] = 0L;
+		hi->addr_mapped[0] = 0L;
+		hi->addr_mapped[1] = 0L;
+	}
 }
 
 void
-cleanup_ioremap (void)
+cleanup_ioremap(void)
 {
-    hdw_info_t *hi;
-    int         i;
+	hdw_info_t *hi;
+	int         i;
 
-    for (i = 0, hi = hdw_info; i < MAX_BOARDS; i++, hi++)
-    {
-        if (hi->pci_slot == 0xff)
-            break;
-        if (hi->addr_mapped[0])
-        {
-            iounmap ((void *) (hi->addr_mapped[0]));
-            release_mem_region ((long) hi->addr[0], hi->len[0]);
-            hi->addr_mapped[0] = 0;
-        }
-        if (hi->addr_mapped[1])
-        {
-            iounmap ((void *) (hi->addr_mapped[1]));
-            release_mem_region ((long) hi->addr[1], hi->len[1]);
-            hi->addr_mapped[1] = 0;
-        }
-    }
+	for (i = 0, hi = hdw_info; i < MAX_BOARDS; i++, hi++) {
+		if (hi->pci_slot == 0xff)
+			break;
+		if (hi->addr_mapped[0]) {
+			iounmap((void *)(hi->addr_mapped[0]));
+			release_mem_region((long) hi->addr[0], hi->len[0]);
+			hi->addr_mapped[0] = 0;
+		}
+		if (hi->addr_mapped[1]) {
+			iounmap((void *)(hi->addr_mapped[1]));
+			release_mem_region((long) hi->addr[1], hi->len[1]);
+			hi->addr_mapped[1] = 0;
+		}
+	}
 }
 
 
 void
-cleanup_devs (void)
+cleanup_devs(void)
 {
-    hdw_info_t *hi;
-    int         i;
+	hdw_info_t *hi;
+	int         i;
 
-    for (i = 0, hi = hdw_info; i < MAX_BOARDS; i++, hi++)
-    {
-        if (hi->pci_slot == 0xff || !hi->ndev)
-            break;
-        c4_stopwd(netdev_priv(hi->ndev));
+	for (i = 0, hi = hdw_info; i < MAX_BOARDS; i++, hi++) {
+		if (hi->pci_slot == 0xff || !hi->ndev)
+			break;
+		c4_stopwd(netdev_priv(hi->ndev));
 #ifdef CONFIG_PROC_FS
-        sbecom_proc_brd_cleanup(netdev_priv(hi->ndev));
+		sbecom_proc_brd_cleanup(netdev_priv(hi->ndev));
 #endif
-        unregister_netdev (hi->ndev);
-        free_irq (hi->pdev[0]->irq, hi->ndev);
+		unregister_netdev(hi->ndev);
+		free_irq(hi->pdev[0]->irq, hi->ndev);
 #ifdef CONFIG_SBE_PMCC4_NCOMM
-        free_irq (hi->pdev[1]->irq, hi->ndev);
+		free_irq(hi->pdev[1]->irq, hi->ndev);
 #endif
-        OS_kfree (hi->ndev);
-    }
+		OS_kfree(hi->ndev);
+	}
 }
 
 
 static int  __init
-c4_hdw_init (struct pci_dev *pdev, int found)
+c4_hdw_init(struct pci_dev *pdev, int found)
 {
-    hdw_info_t *hi;
-    int         i;
-    int         fun, slot;
-    unsigned char busno = 0xff;
+	hdw_info_t *hi;
+	int         i;
+	int         fun, slot;
+	unsigned char busno = 0xff;
 
-    /* our MUSYCC chip supports two functions, 0 & 1 */
-    if ((fun = PCI_FUNC (pdev->devfn)) > 1)
-    {
-        pr_warning("unexpected devfun: 0x%x\n", pdev->devfn);
-        return 0;
-    }
-    if (pdev->bus)                  /* obtain bus number */
-        busno = pdev->bus->number;
-    else
-        busno = 0;                  /* default for system PCI inconsistency */
-    slot = pdev->devfn & ~0x07;
+	/* our MUSYCC chip supports two functions, 0 & 1 */
+	fun = PCI_FUNC(pdev->devfn);
+	if (fun > 1) {
+		pr_warning("unexpected devfun: 0x%x\n", pdev->devfn);
+		return 0;
+	}
 
-    /*
-     * Functions 0 & 1 for a given board (identified by same bus(busno) and
-     * slot(slot)) are placed into the same 'hardware' structure.  The first
-     * part of the board's functionality will be placed into an unpopulated
-     * element, identified by "slot==(0xff)".  The second part of a board's
-     * functionality will match the previously loaded slot/busno.
-     */
-    for (i = 0, hi = hdw_info; i < MAX_BOARDS; i++, hi++)
-    {
-        /*
-         * match with board's first found interface, otherwise this is first
-         * found
-         */
-        if ((hi->pci_slot == 0xff) ||   /* new board */
-            ((hi->pci_slot == slot) && (hi->bus == pdev->bus)))
-            break;                  /* found for-loop exit */
-    }
-    if (i == MAX_BOARDS)            /* no match in above loop means MAX
-                                     * exceeded */
-    {
-        pr_warning("exceeded number of allowed devices (>%d)?\n", MAX_BOARDS);
-        return 0;
-    }
-    if (pdev->bus)
-        hi->pci_busno = pdev->bus->number;
-    else
-        hi->pci_busno = 0;          /* default for system PCI inconsistency */
-    hi->pci_slot = slot;
-    pci_read_config_byte (pdev, PCI_INTERRUPT_PIN, &hi->pci_pin[fun]);
-    pci_read_config_byte (pdev, PCI_REVISION_ID, &hi->revid[fun]);
-    hi->bus = pdev->bus;
-    hi->addr[fun] = pci_resource_start (pdev, 0);
-    hi->len[fun] = pci_resource_end (pdev, 0) - hi->addr[fun] + 1;
-    hi->pdev[fun] = pdev;
+	/* obtain bus number */
+	if (pdev->bus)
+		busno = pdev->bus->number;
+	else
+		busno = 0; /* default for system PCI inconsistency */
+	slot = pdev->devfn & ~0x07;
 
-    {
-        /*
-         * create device name from module name, plus add the appropriate
-         * board number
-         */
-        char       *cp = hi->devname;
+	/*
+	 * Functions 0 & 1 for a given board (identified by same bus(busno) and
+	 * slot(slot)) are placed into the same 'hardware' structure.  The first
+	 * part of the board's functionality will be placed into an unpopulated
+	 * element, identified by "slot==(0xff)".  The second part of a board's
+	 * functionality will match the previously loaded slot/busno.
+	 */
+	for (i = 0, hi = hdw_info; i < MAX_BOARDS; i++, hi++) {
+		/*
+		 * match with board's first found interface, otherwise this is
+		 * fisrt found
+		 */
+		if ((hi->pci_slot == 0xff) ||   /* new board */
+		    ((hi->pci_slot == slot) && (hi->bus == pdev->bus)))
+			break;                  /* found for-loop exit */
+	}
 
-        strcpy (cp, KBUILD_MODNAME);
-        cp += strlen (cp);          /* reposition */
-        *cp++ = '-';
-        *cp++ = '0' + (found / 2);  /* there are two found interfaces per
-                                     * board */
-        *cp = 0;                    /* termination */
-    }
+	/* no match in above loop means MAX exceeded */
+	if (i == MAX_BOARDS) {
+		pr_warning("exceeded number of allowed devices (>%d)?\n",
+			   MAX_BOARDS);
+		return 0;
+	}
 
-    return 1;
+	if (pdev->bus)
+		hi->pci_busno = pdev->bus->number;
+	else
+		hi->pci_busno = 0; /* default for system PCI inconsistency */
+
+	hi->pci_slot = slot;
+	pci_read_config_byte(pdev, PCI_INTERRUPT_PIN, &hi->pci_pin[fun]);
+	pci_read_config_byte(pdev, PCI_REVISION_ID, &hi->revid[fun]);
+	hi->bus = pdev->bus;
+	hi->addr[fun] = pci_resource_start(pdev, 0);
+	hi->len[fun] = pci_resource_end(pdev, 0) - hi->addr[fun] + 1;
+	hi->pdev[fun] = pdev;
+
+	{
+		/*
+		 * create device name from module name, plus add the appropriate
+		 * board number
+		 */
+		char       *cp = hi->devname;
+
+		strcpy(cp, KBUILD_MODNAME);
+		cp += strlen(cp);          /* reposition */
+		*cp++ = '-';
+		*cp++ = '0' + (found / 2);  /* there are two found interfaces per
+		* board */
+		*cp = 0;                    /* termination */
+	}
+
+	return 1;
 }
 
-
-status_t    __init
-c4hw_attach_all (void)
+status_t __init
+c4hw_attach_all(void)
 {
-    hdw_info_t *hi;
-    struct pci_dev *pdev = NULL;
-    int         found = 0, i, j;
+	hdw_info_t *hi;
+	struct pci_dev *pdev = NULL;
+	int         found = 0, i, j;
 
-    error_flag = 0;
-    prep_hdw_info ();
-    /*** scan PCI bus for all possible boards */
-    while ((pdev = pci_get_device (PCI_VENDOR_ID_CONEXANT,
-                                    PCI_DEVICE_ID_CN8474,
-                                    pdev)))
-    {
-        if (c4_hdw_init (pdev, found))
-            found++;
-    }
-    if (!found)
-    {
-        pr_warning("No boards found\n");
-        return -ENODEV;
-    }
-    /* sanity check for consistent hardware found */
-    for (i = 0, hi = hdw_info; i < MAX_BOARDS; i++, hi++)
-    {
-        if (hi->pci_slot != 0xff && (!hi->addr[0] || !hi->addr[1]))
-        {
-            pr_warning("%s: something very wrong with pci_get_device\n",
-                       hi->devname);
-            return -EIO;
-        }
-    }
-    /* bring board's memory regions on/line */
-    for (i = 0, hi = hdw_info; i < MAX_BOARDS; i++, hi++)
-    {
-        if (hi->pci_slot == 0xff)
-            break;
-        for (j = 0; j < 2; j++)
-        {
-	    if (!request_mem_region (hi->addr[j], hi->len[j], hi->devname))
-            {
-                pr_warning("%s: memory in use, addr=0x%lx, len=0x%lx ?\n",
-                           hi->devname, hi->addr[j], hi->len[j]);
-                cleanup_ioremap ();
-                return -ENOMEM;
-            }
-            hi->addr_mapped[j] = (unsigned long) ioremap (hi->addr[j], hi->len[j]);
-            if (!hi->addr_mapped[j])
-            {
-                pr_warning("%s: ioremap fails, addr=0x%lx, len=0x%lx ?\n",
-                           hi->devname, hi->addr[j], hi->len[j]);
-                cleanup_ioremap ();
-                return -ENOMEM;
-            }
+	error_flag = 0;
+	prep_hdw_info();
+	/*** scan PCI bus for all possible boards */
+	while ((pdev = pci_get_device(PCI_VENDOR_ID_CONEXANT,
+				      PCI_DEVICE_ID_CN8474,
+				      pdev))) {
+		if (c4_hdw_init(pdev, found))
+			found++;
+	}
+
+	if (!found) {
+		pr_warning("No boards found\n");
+		return -ENODEV;
+	}
+
+	/* sanity check for consistent hardware found */
+	for (i = 0, hi = hdw_info; i < MAX_BOARDS; i++, hi++) {
+		if (hi->pci_slot != 0xff && (!hi->addr[0] || !hi->addr[1])) {
+			pr_warning("%s: something very wrong with pci_get_device\n",
+				   hi->devname);
+			return -EIO;
+		}
+	}
+	/* bring board's memory regions on/line */
+	for (i = 0, hi = hdw_info; i < MAX_BOARDS; i++, hi++) {
+		if (hi->pci_slot == 0xff)
+			break;
+		for (j = 0; j < 2; j++) {
+			if (!request_mem_region(hi->addr[j], hi->len[j], hi->devname)) {
+				pr_warning("%s: memory in use, addr=0x%lx, len=0x%lx ?\n",
+					   hi->devname, hi->addr[j], hi->len[j]);
+				cleanup_ioremap();
+				return -ENOMEM;
+			}
+
+			hi->addr_mapped[j] = (unsigned long)ioremap(hi->addr[j], hi->len[j]);
+			if (!hi->addr_mapped[j]) {
+				pr_warning("%s: ioremap fails, addr=0x%lx, len=0x%lx ?\n",
+					   hi->devname, hi->addr[j], hi->len[j]);
+				cleanup_ioremap();
+				return -ENOMEM;
+			}
 #ifdef SBE_MAP_DEBUG
-            pr_warning("%s: io remapped from phys %x to virt %x\n",
-                       hi->devname, (u_int32_t) hi->addr[j], (u_int32_t) hi->addr_mapped[j]);
+			pr_warning("%s: io remapped from phys %x to virt %x\n",
+				   hi->devname, (u_int32_t) hi->addr[j],
+				   (u_int32_t) hi->addr_mapped[j]);
 #endif
-        }
-    }
+		}
+	}
 
-    drvr_state = SBE_DRVR_AVAILABLE;
+	drvr_state = SBE_DRVR_AVAILABLE;
 
-    /* Have now memory mapped all boards.  Now allow board's access to system */
-    for (i = 0, hi = hdw_info; i < MAX_BOARDS; i++, hi++)
-    {
-        if (hi->pci_slot == 0xff)
-            break;
-        if (pci_enable_device (hi->pdev[0]) ||
-            pci_enable_device (hi->pdev[1]))
-        {
-            drvr_state = SBE_DRVR_DOWN;
-            pr_warning("%s: failed to enable card %d slot %d\n",
-                       hi->devname, i, hi->pci_slot);
-            cleanup_devs ();
-            cleanup_ioremap ();
-            return -EIO;
-        }
-        pci_set_master (hi->pdev[0]);
-        pci_set_master (hi->pdev[1]);
-        if (!(hi->ndev = c4_add_dev (hi, i, (long) hi->addr_mapped[0],
-                                     (long) hi->addr_mapped[1],
-                                     hi->pdev[0]->irq,
-                                     hi->pdev[1]->irq)))
-        {
-            drvr_state = SBE_DRVR_DOWN;
-            cleanup_ioremap ();
-            /* NOTE: c4_add_dev() does its own device cleanup */
+	/* Have now memory mapped all boards.  Now allow board's access to system */
+	for (i = 0, hi = hdw_info; i < MAX_BOARDS; i++, hi++) {
+		if (hi->pci_slot == 0xff)
+			break;
+		if (pci_enable_device(hi->pdev[0]) ||
+		    pci_enable_device(hi->pdev[1])) {
+			drvr_state = SBE_DRVR_DOWN;
+			pr_warning("%s: failed to enable card %d slot %d\n",
+				   hi->devname, i, hi->pci_slot);
+			cleanup_devs();
+			cleanup_ioremap();
+			return -EIO;
+		}
+		pci_set_master(hi->pdev[0]);
+		pci_set_master(hi->pdev[1]);
+		hi->ndev = c4_add_dev(hi, i, (long) hi->addr_mapped[0],
+				      (long) hi->addr_mapped[1],
+				      hi->pdev[0]->irq,
+				      hi->pdev[1]->irq);
+		if (!hi->ndev) {
+			drvr_state = SBE_DRVR_DOWN;
+			cleanup_ioremap();
+			/* NOTE: c4_add_dev() does its own device cleanup */
 #if 0
-            cleanup_devs ();
+			cleanup_devs();
 #endif
-            return error_flag;      /* error_flag set w/in add_dev() */
-        }
-        show_two (hi, i);           /* displays found information */
-    }
-    return 0;
+			return error_flag; /* error_flag set w/in add_dev() */
+		}
+		show_two(hi, i); /* displays found information */
+	}
+	return 0;
 }
 
 /***  End-of-File  ***/
diff --git a/drivers/staging/cxt1e1/linux.c b/drivers/staging/cxt1e1/linux.c
index 4a08e16..579e68e 100644
--- a/drivers/staging/cxt1e1/linux.c
+++ b/drivers/staging/cxt1e1/linux.c
@@ -31,7 +31,7 @@
 #include "pmcc4_private.h"
 #include "sbeproc.h"
 
-/*****************************************************************************************
+/*******************************************************************************
  * Error out early if we have compiler trouble.
  *
  *   (This section is included from the kernel's init/main.c as a friendly
@@ -50,43 +50,43 @@
 #warning gcc-4.1.0 is known to miscompile the kernel.  A different compiler version is recommended.
 #endif
 
-/*****************************************************************************************/
+/*******************************************************************************/
 
 #define CHANNAME "hdlc"
 
 /*******************************************************************/
 /* forward references */
-status_t    c4_chan_work_init (mpi_t *, mch_t *);
-void        musycc_wq_chan_restart (void *);
-status_t __init c4_init (ci_t *, u_char *, u_char *);
-status_t __init c4_init2 (ci_t *);
-ci_t       *__init c4_new (void *);
-int __init  c4hw_attach_all (void);
-void __init hdw_sn_get (hdw_info_t *, int);
+status_t    c4_chan_work_init(mpi_t *, mch_t *);
+void        musycc_wq_chan_restart(void *);
+status_t __init c4_init(ci_t *, u_char *, u_char *);
+status_t __init c4_init2(ci_t *);
+ci_t       *__init c4_new(void *);
+int __init  c4hw_attach_all(void);
+void __init hdw_sn_get(hdw_info_t *, int);
 
 #ifdef CONFIG_SBE_PMCC4_NCOMM
-irqreturn_t c4_ebus_intr_th_handler (void *);
+irqreturn_t c4_ebus_intr_th_handler(void *);
 
 #endif
-int         c4_frame_rw (ci_t *, struct sbecom_port_param *);
-status_t    c4_get_port (ci_t *, int);
-int         c4_loop_port (ci_t *, int, u_int8_t);
-int         c4_musycc_rw (ci_t *, struct c4_musycc_param *);
-int         c4_new_chan (ci_t *, int, int, void *);
-status_t    c4_set_port (ci_t *, int);
-int         c4_pld_rw (ci_t *, struct sbecom_port_param *);
-void        cleanup_devs (void);
-void        cleanup_ioremap (void);
-status_t    musycc_chan_down (ci_t *, int);
-irqreturn_t musycc_intr_th_handler (void *);
-int         musycc_start_xmit (ci_t *, int, void *);
+int         c4_frame_rw(ci_t *, struct sbecom_port_param *);
+status_t    c4_get_port(ci_t *, int);
+int         c4_loop_port(ci_t *, int, u_int8_t);
+int         c4_musycc_rw(ci_t *, struct c4_musycc_param *);
+int         c4_new_chan(ci_t *, int, int, void *);
+status_t    c4_set_port(ci_t *, int);
+int         c4_pld_rw(ci_t *, struct sbecom_port_param *);
+void        cleanup_devs(void);
+void        cleanup_ioremap(void);
+status_t    musycc_chan_down(ci_t *, int);
+irqreturn_t musycc_intr_th_handler(void *);
+int         musycc_start_xmit(ci_t *, int, void *);
 
 extern char pmcc4_OSSI_release[];
 extern ci_t *CI;
 extern struct s_hdw_info hdw_info[];
 
 #if defined(CONFIG_SBE_HDLC_V7) || defined(CONFIG_SBE_WAN256T3_HDLC_V7) || \
-    defined(CONFIG_SBE_HDLC_V7_MODULE) || defined(CONFIG_SBE_WAN256T3_HDLC_V7_MODULE)
+	defined(CONFIG_SBE_HDLC_V7_MODULE) || defined(CONFIG_SBE_WAN256T3_HDLC_V7_MODULE)
 #define _v7_hdlc_  1
 #else
 #define _v7_hdlc_  0
@@ -94,9 +94,9 @@
 
 #if _v7_hdlc_
 #define V7(x) (x ## _v7)
-extern int  hdlc_netif_rx_v7 (hdlc_device *, struct sk_buff *);
-extern int  register_hdlc_device_v7 (hdlc_device *);
-extern int  unregister_hdlc_device_v7 (hdlc_device *);
+extern int  hdlc_netif_rx_v7(hdlc_device *, struct sk_buff *);
+extern int  register_hdlc_device_v7(hdlc_device *);
+extern int  unregister_hdlc_device_v7(hdlc_device *);
 
 #else
 #define V7(x) x
@@ -127,33 +127,33 @@
 /****************************************************************************/
 /****************************************************************************/
 
-void       *
-getuserbychan (int channum)
+void *
+getuserbychan(int channum)
 {
-    mch_t      *ch;
+	mch_t      *ch;
 
-    ch = c4_find_chan (channum);
-    return ch ? ch->user : NULL;
+	ch = c4_find_chan(channum);
+	return ch ? ch->user : NULL;
 }
 
 
-char       *
-get_hdlc_name (hdlc_device *hdlc)
+char *
+get_hdlc_name(hdlc_device *hdlc)
 {
-    struct c4_priv *priv = hdlc->priv;
-    struct net_device *dev = getuserbychan (priv->channum);
+	struct c4_priv *priv = hdlc->priv;
+	struct net_device *dev = getuserbychan(priv->channum);
 
-    return dev->name;
+	return dev->name;
 }
 
 
-static      status_t
-mkret (int bsd)
+static status_t
+mkret(int bsd)
 {
-    if (bsd > 0)
-        return -bsd;
-    else
-        return bsd;
+	if (bsd > 0)
+		return -bsd;
+	else
+		return bsd;
 }
 
 /***************************************************************************/
@@ -179,956 +179,978 @@
  * within a port's group.
  */
 void
-c4_wk_chan_restart (mch_t *ch)
+c4_wk_chan_restart(mch_t *ch)
 {
-    mpi_t      *pi = ch->up;
+	mpi_t      *pi = ch->up;
 
 #ifdef RLD_RESTART_DEBUG
-    pr_info(">> %s: queueing Port %d Chan %d, mch_t @ %p\n",
-            __func__, pi->portnum, ch->channum, ch);
+	pr_info(">> %s: queueing Port %d Chan %d, mch_t @ %p\n",
+		__func__, pi->portnum, ch->channum, ch);
 #endif
 
-    /* create new entry w/in workqueue for this channel and let'er rip */
+	/* create new entry w/in workqueue for this channel and let'er rip */
 
-    /** queue_work (struct workqueue_struct *queue,
-     **             struct work_struct *work);
-     **/
-    queue_work (pi->wq_port, &ch->ch_work);
+	/** queue_work(struct workqueue_struct *queue,
+	 **            struct work_struct *work);
+	 **/
+	queue_work(pi->wq_port, &ch->ch_work);
 }
 
 status_t
-c4_wk_chan_init (mpi_t *pi, mch_t *ch)
+c4_wk_chan_init(mpi_t *pi, mch_t *ch)
 {
-    /*
-     * this will be used to restart a stopped channel
-     */
+	/*
+	 * this will be used to restart a stopped channel
+	 */
 
-    /** INIT_WORK (struct work_struct *work,
-     **            void (*function)(void *),
-     **            void *data);
-     **/
-    INIT_WORK(&ch->ch_work, (void *)musycc_wq_chan_restart);
-    return 0;                       /* success */
+	/** INIT_WORK(struct work_struct *work,
+	 **           void (*function)(void *),
+	 **           void *data);
+	 **/
+	INIT_WORK(&ch->ch_work, (void *)musycc_wq_chan_restart);
+	return 0;                       /* success */
 }
 
 status_t
-c4_wq_port_init (mpi_t *pi)
+c4_wq_port_init(mpi_t *pi)
 {
 
-    char        name[16], *np;  /* NOTE: name of the queue limited by system
-                                 * to 10 characters */
+	char        name[16], *np;  /* NOTE: name of the queue limited by system
+				     * to 10 characters */
 
-    if (pi->wq_port)
-        return 0;                   /* already initialized */
+	if (pi->wq_port)
+		return 0;                   /* already initialized */
 
-    np = name;
-    memset (name, 0, 16);
-    sprintf (np, "%s%d", pi->up->devname, pi->portnum); /* IE pmcc4-01) */
+	np = name;
+	memset(name, 0, 16);
+	sprintf(np, "%s%d", pi->up->devname, pi->portnum); /* IE pmcc4-01) */
 
 #ifdef RLD_RESTART_DEBUG
-    pr_info(">> %s: creating workqueue <%s> for Port %d.\n",
-            __func__, name, pi->portnum); /* RLD DEBUG */
+	pr_info(">> %s: creating workqueue <%s> for Port %d.\n",
+		__func__, name, pi->portnum); /* RLD DEBUG */
 #endif
-    if (!(pi->wq_port = create_singlethread_workqueue (name)))
-        return -ENOMEM;
-    return 0;                       /* success */
+	if (!(pi->wq_port = create_singlethread_workqueue(name)))
+		return -ENOMEM;
+	return 0;                       /* success */
 }
 
 void
-c4_wq_port_cleanup (mpi_t *pi)
+c4_wq_port_cleanup(mpi_t *pi)
 {
-    /*
-     * PORT POINT: cannot call this if WQ is statically allocated w/in
-     * structure since it calls kfree(wq);
-     */
-    if (pi->wq_port)
-    {
-        destroy_workqueue (pi->wq_port);        /* this also calls
-                                                 * flush_workqueue() */
-        pi->wq_port = NULL;
-    }
+	/*
+	 * PORT POINT: cannot call this if WQ is statically allocated w/in
+	 * structure since it calls kfree(wq);
+	 */
+	if (pi->wq_port)
+	{
+		destroy_workqueue(pi->wq_port);        /* this also calls
+							* flush_workqueue() */
+		pi->wq_port = NULL;
+	}
 }
 
 /***************************************************************************/
 
 irqreturn_t
-c4_linux_interrupt (int irq, void *dev_instance)
+c4_linux_interrupt(int irq, void *dev_instance)
 {
-    struct net_device *ndev = dev_instance;
+	struct net_device *ndev = dev_instance;
 
-    return musycc_intr_th_handler(netdev_priv(ndev));
+	return musycc_intr_th_handler(netdev_priv(ndev));
 }
 
 
 #ifdef CONFIG_SBE_PMCC4_NCOMM
 irqreturn_t
-c4_ebus_interrupt (int irq, void *dev_instance)
+c4_ebus_interrupt(int irq, void *dev_instance)
 {
-    struct net_device *ndev = dev_instance;
+	struct net_device *ndev = dev_instance;
 
-    return c4_ebus_intr_th_handler(netdev_priv(ndev));
+	return c4_ebus_intr_th_handler(netdev_priv(ndev));
 }
 #endif
 
 
 static int
-void_open (struct net_device *ndev)
+void_open(struct net_device *ndev)
 {
-    pr_info("%s: trying to open master device !\n", ndev->name);
-    return -1;
+	pr_info("%s: trying to open master device !\n", ndev->name);
+	return -1;
 }
 
 
 static int
-chan_open (struct net_device *ndev)
+chan_open(struct net_device *ndev)
 {
-    hdlc_device *hdlc = dev_to_hdlc (ndev);
-    const struct c4_priv *priv = hdlc->priv;
-    int         ret;
+	hdlc_device *hdlc = dev_to_hdlc(ndev);
+	const struct c4_priv *priv = hdlc->priv;
+	int         ret;
 
-    if ((ret = hdlc_open (ndev)))
-    {
-        pr_info("hdlc_open failure, err %d.\n", ret);
-        return ret;
-    }
-    if ((ret = c4_chan_up (priv->ci, priv->channum)))
-        return -ret;
-    try_module_get (THIS_MODULE);
-    netif_start_queue (ndev);
-    return 0;                       /* no error = success */
+	if ((ret = hdlc_open(ndev)))
+	{
+		pr_info("hdlc_open failure, err %d.\n", ret);
+		return ret;
+	}
+	if ((ret = c4_chan_up(priv->ci, priv->channum)))
+		return -ret;
+	try_module_get(THIS_MODULE);
+	netif_start_queue(ndev);
+	return 0;                       /* no error = success */
 }
 
 
 static int
-chan_close (struct net_device *ndev)
+chan_close(struct net_device *ndev)
 {
-    hdlc_device *hdlc = dev_to_hdlc (ndev);
-    const struct c4_priv *priv = hdlc->priv;
+	hdlc_device *hdlc = dev_to_hdlc(ndev);
+	const struct c4_priv *priv = hdlc->priv;
 
-    netif_stop_queue (ndev);
-    musycc_chan_down ((ci_t *) 0, priv->channum);
-    hdlc_close (ndev);
-    module_put (THIS_MODULE);
-    return 0;
+	netif_stop_queue(ndev);
+	musycc_chan_down((ci_t *) 0, priv->channum);
+	hdlc_close(ndev);
+	module_put(THIS_MODULE);
+	return 0;
 }
 
 
 static int
-chan_dev_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
+chan_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 {
-    return hdlc_ioctl (dev, ifr, cmd);
+	return hdlc_ioctl(dev, ifr, cmd);
 }
 
 
 static int
-chan_attach_noop (struct net_device *ndev, unsigned short foo_1, unsigned short foo_2)
+chan_attach_noop(struct net_device *ndev, unsigned short foo_1,
+		 unsigned short foo_2)
 {
-    return 0;                   /* our driver has nothing to do here, show's
-                                 * over, go home */
+	/* our driver has nothing to do here, show's
+	 * over, go home
+	 */
+	return 0;
 }
 
 
 static struct net_device_stats *
-chan_get_stats (struct net_device *ndev)
+chan_get_stats(struct net_device *ndev)
 {
-    mch_t      *ch;
-    struct net_device_stats *nstats;
-    struct sbecom_chan_stats *stats;
-    int         channum;
+	mch_t      *ch;
+	struct net_device_stats *nstats;
+	struct sbecom_chan_stats *stats;
+	int         channum;
 
-    {
-        struct c4_priv *priv;
+	{
+		struct c4_priv *priv;
 
-        priv = (struct c4_priv *) dev_to_hdlc (ndev)->priv;
-        channum = priv->channum;
-    }
+		priv = (struct c4_priv *)dev_to_hdlc(ndev)->priv;
+		channum = priv->channum;
+	}
 
-    ch = c4_find_chan (channum);
-    if (ch == NULL)
-        return NULL;
+	ch = c4_find_chan(channum);
+	if (ch == NULL)
+		return NULL;
 
-    nstats = &ndev->stats;
-    stats = &ch->s;
+	nstats = &ndev->stats;
+	stats = &ch->s;
 
-    memset (nstats, 0, sizeof (struct net_device_stats));
-    nstats->rx_packets = stats->rx_packets;
-    nstats->tx_packets = stats->tx_packets;
-    nstats->rx_bytes = stats->rx_bytes;
-    nstats->tx_bytes = stats->tx_bytes;
-    nstats->rx_errors = stats->rx_length_errors +
-        stats->rx_over_errors +
-        stats->rx_crc_errors +
-        stats->rx_frame_errors +
-        stats->rx_fifo_errors +
-        stats->rx_missed_errors;
-    nstats->tx_errors = stats->tx_dropped +
-        stats->tx_aborted_errors +
-        stats->tx_fifo_errors;
-    nstats->rx_dropped = stats->rx_dropped;
-    nstats->tx_dropped = stats->tx_dropped;
+	memset(nstats, 0, sizeof(struct net_device_stats));
+	nstats->rx_packets = stats->rx_packets;
+	nstats->tx_packets = stats->tx_packets;
+	nstats->rx_bytes = stats->rx_bytes;
+	nstats->tx_bytes = stats->tx_bytes;
+	nstats->rx_errors = stats->rx_length_errors +
+		stats->rx_over_errors +
+		stats->rx_crc_errors +
+		stats->rx_frame_errors +
+		stats->rx_fifo_errors +
+		stats->rx_missed_errors;
+	nstats->tx_errors = stats->tx_dropped +
+		stats->tx_aborted_errors +
+		stats->tx_fifo_errors;
+	nstats->rx_dropped = stats->rx_dropped;
+	nstats->tx_dropped = stats->tx_dropped;
 
-    nstats->rx_length_errors = stats->rx_length_errors;
-    nstats->rx_over_errors = stats->rx_over_errors;
-    nstats->rx_crc_errors = stats->rx_crc_errors;
-    nstats->rx_frame_errors = stats->rx_frame_errors;
-    nstats->rx_fifo_errors = stats->rx_fifo_errors;
-    nstats->rx_missed_errors = stats->rx_missed_errors;
+	nstats->rx_length_errors = stats->rx_length_errors;
+	nstats->rx_over_errors = stats->rx_over_errors;
+	nstats->rx_crc_errors = stats->rx_crc_errors;
+	nstats->rx_frame_errors = stats->rx_frame_errors;
+	nstats->rx_fifo_errors = stats->rx_fifo_errors;
+	nstats->rx_missed_errors = stats->rx_missed_errors;
 
-    nstats->tx_aborted_errors = stats->tx_aborted_errors;
-    nstats->tx_fifo_errors = stats->tx_fifo_errors;
+	nstats->tx_aborted_errors = stats->tx_aborted_errors;
+	nstats->tx_fifo_errors = stats->tx_fifo_errors;
 
-    return nstats;
+	return nstats;
 }
 
 
 static ci_t *
-get_ci_by_dev (struct net_device *ndev)
+get_ci_by_dev(struct net_device *ndev)
 {
-    return (ci_t *)(netdev_priv(ndev));
+	return (ci_t *)(netdev_priv(ndev));
 }
 
 
 static int
-c4_linux_xmit (struct sk_buff *skb, struct net_device *ndev)
+c4_linux_xmit(struct sk_buff *skb, struct net_device *ndev)
 {
-    const struct c4_priv *priv;
-    int         rval;
+	const struct c4_priv *priv;
+	int         rval;
 
-    hdlc_device *hdlc = dev_to_hdlc (ndev);
+	hdlc_device *hdlc = dev_to_hdlc(ndev);
 
-    priv = hdlc->priv;
+	priv = hdlc->priv;
 
-    rval = musycc_start_xmit (priv->ci, priv->channum, skb);
-    return rval;
+	rval = musycc_start_xmit(priv->ci, priv->channum, skb);
+	return rval;
 }
 
 static const struct net_device_ops chan_ops = {
-       .ndo_open       = chan_open,
-       .ndo_stop       = chan_close,
-       .ndo_start_xmit = c4_linux_xmit,
-       .ndo_do_ioctl   = chan_dev_ioctl,
-       .ndo_get_stats  = chan_get_stats,
+	.ndo_open       = chan_open,
+	.ndo_stop       = chan_close,
+	.ndo_start_xmit = c4_linux_xmit,
+	.ndo_do_ioctl   = chan_dev_ioctl,
+	.ndo_get_stats  = chan_get_stats,
 };
 
 static struct net_device *
-create_chan (struct net_device *ndev, ci_t *ci,
-             struct sbecom_chan_param *cp)
+create_chan(struct net_device *ndev, ci_t *ci,
+	    struct sbecom_chan_param *cp)
 {
-    hdlc_device *hdlc;
-    struct net_device *dev;
-    hdw_info_t *hi;
-    int         ret;
+	hdlc_device *hdlc;
+	struct net_device *dev;
+	hdw_info_t *hi;
+	int         ret;
 
-    if (c4_find_chan (cp->channum))
-        return NULL;                   /* channel already exists */
+	if (c4_find_chan(cp->channum))
+		return NULL;                   /* channel already exists */
 
-    {
-        struct c4_priv *priv;
+	{
+		struct c4_priv *priv;
 
-        /* allocate then fill in private data structure */
-        priv = OS_kmalloc (sizeof (struct c4_priv));
-        if (!priv)
-        {
-            pr_warning("%s: no memory for net_device !\n", ci->devname);
-	    return NULL;
-        }
-        dev = alloc_hdlcdev (priv);
-        if (!dev)
-        {
-            pr_warning("%s: no memory for hdlc_device !\n", ci->devname);
-            OS_kfree (priv);
-	    return NULL;
-        }
-        priv->ci = ci;
-        priv->channum = cp->channum;
-    }
+		/* allocate then fill in private data structure */
+		priv = OS_kmalloc(sizeof(struct c4_priv));
+		if (!priv)
+		{
+			pr_warning("%s: no memory for net_device !\n",
+				   ci->devname);
+			return NULL;
+		}
+		dev = alloc_hdlcdev(priv);
+		if (!dev)
+		{
+			pr_warning("%s: no memory for hdlc_device !\n",
+				   ci->devname);
+			OS_kfree(priv);
+			return NULL;
+		}
+		priv->ci = ci;
+		priv->channum = cp->channum;
+	}
 
-    hdlc = dev_to_hdlc (dev);
+	hdlc = dev_to_hdlc(dev);
 
-    dev->base_addr = 0;             /* not I/O mapped */
-    dev->irq = ndev->irq;
-    dev->type = ARPHRD_RAWHDLC;
-    *dev->name = 0;                 /* default ifconfig name = "hdlc" */
+	dev->base_addr = 0;             /* not I/O mapped */
+	dev->irq = ndev->irq;
+	dev->type = ARPHRD_RAWHDLC;
+	*dev->name = 0;                 /* default ifconfig name = "hdlc" */
 
-    hi = (hdw_info_t *) ci->hdw_info;
-    if (hi->mfg_info_sts == EEPROM_OK)
-    {
-        switch (hi->promfmt)
-        {
-        case PROM_FORMAT_TYPE1:
-            memcpy (dev->dev_addr, (FLD_TYPE1 *) (hi->mfg_info.pft1.Serial), 6);
-            break;
-        case PROM_FORMAT_TYPE2:
-            memcpy (dev->dev_addr, (FLD_TYPE2 *) (hi->mfg_info.pft2.Serial), 6);
-            break;
-        default:
-            memset (dev->dev_addr, 0, 6);
-            break;
-        }
-    } else
-    {
-        memset (dev->dev_addr, 0, 6);
-    }
+	hi = (hdw_info_t *)ci->hdw_info;
+	if (hi->mfg_info_sts == EEPROM_OK)
+	{
+		switch (hi->promfmt)
+		{
+		case PROM_FORMAT_TYPE1:
+			memcpy(dev->dev_addr,
+			       (FLD_TYPE1 *) (hi->mfg_info.pft1.Serial), 6);
+			break;
+		case PROM_FORMAT_TYPE2:
+			memcpy(dev->dev_addr,
+			       (FLD_TYPE2 *) (hi->mfg_info.pft2.Serial), 6);
+			break;
+		default:
+			memset(dev->dev_addr, 0, 6);
+			break;
+		}
+	} else
+	{
+		memset(dev->dev_addr, 0, 6);
+	}
 
-    hdlc->xmit = c4_linux_xmit;
+	hdlc->xmit = c4_linux_xmit;
 
-    dev->netdev_ops = &chan_ops;
-    /*
-     * The native hdlc stack calls this 'attach' routine during
-     * hdlc_raw_ioctl(), passing parameters for line encoding and parity.
-     * Since hdlc_raw_ioctl() stack does not interrogate whether an 'attach'
-     * routine is actually registered or not, we supply a dummy routine which
-     * does nothing (since encoding and parity are setup for our driver via a
-     * special configuration application).
-     */
+	dev->netdev_ops = &chan_ops;
+	/*
+	 * The native hdlc stack calls this 'attach' routine during
+	 * hdlc_raw_ioctl(), passing parameters for line encoding and parity.
+	 * Since hdlc_raw_ioctl() stack does not interrogate whether an 'attach'
+	 * routine is actually registered or not, we supply a dummy routine which
+	 * does nothing (since encoding and parity are setup for our driver via a
+	 * special configuration application).
+	 */
 
-    hdlc->attach = chan_attach_noop;
+	hdlc->attach = chan_attach_noop;
 
-    rtnl_unlock ();                 /* needed due to Ioctl calling sequence */
-    ret = register_hdlc_device (dev);
-    /* NOTE: <stats> setting must occur AFTER registration in order to "take" */
-    dev->tx_queue_len = MAX_DEFAULT_IFQLEN;
+	/* needed due to Ioctl calling sequence */
+	rtnl_unlock();
+	ret = register_hdlc_device(dev);
+	/* NOTE: <stats> setting must occur AFTER registration in order to "take" */
+	dev->tx_queue_len = MAX_DEFAULT_IFQLEN;
 
-    rtnl_lock ();                   /* needed due to Ioctl calling sequence */
-    if (ret)
-    {
-        if (cxt1e1_log_level >= LOG_WARN)
-            pr_info("%s: create_chan[%d] registration error = %d.\n",
-                    ci->devname, cp->channum, ret);
-        free_netdev (dev);          /* cleanup */
-	return NULL;		/* failed to register */
-    }
-    return dev;
+	/* needed due to Ioctl calling sequence */
+	rtnl_lock();
+	if (ret)
+	{
+		if (cxt1e1_log_level >= LOG_WARN)
+			pr_info("%s: create_chan[%d] registration error = %d.\n",
+				ci->devname, cp->channum, ret);
+		/* cleanup */
+		free_netdev(dev);
+		/* failed to register */
+		return NULL;
+	}
+	return dev;
 }
 
 
 /* the idea here is to get port information and pass it back (using pointer) */
-static      status_t
-do_get_port (struct net_device *ndev, void *data)
+static status_t
+do_get_port(struct net_device *ndev, void *data)
 {
-    int         ret;
-    ci_t       *ci;             /* ci stands for card information */
-    struct sbecom_port_param pp;/* copy data to kernel land */
+	int         ret;
+	ci_t       *ci;             /* ci stands for card information */
+	struct sbecom_port_param pp;/* copy data to kernel land */
 
-    if (copy_from_user (&pp, data, sizeof (struct sbecom_port_param)))
-        return -EFAULT;
-    if (pp.portnum >= MUSYCC_NPORTS)
-        return -EFAULT;
-    ci = get_ci_by_dev (ndev);
-    if (!ci)
-        return -EINVAL;             /* get card info */
+	if (copy_from_user(&pp, data, sizeof(struct sbecom_port_param)))
+		return -EFAULT;
+	if (pp.portnum >= MUSYCC_NPORTS)
+		return -EFAULT;
+	ci = get_ci_by_dev(ndev);
+	if (!ci)
+		return -EINVAL;             /* get card info */
 
-    ret = mkret (c4_get_port (ci, pp.portnum));
-    if (ret)
-        return ret;
-    if (copy_to_user (data, &ci->port[pp.portnum].p,
-                      sizeof (struct sbecom_port_param)))
-        return -EFAULT;
-    return 0;
+	ret = mkret(c4_get_port(ci, pp.portnum));
+	if (ret)
+		return ret;
+	if (copy_to_user(data, &ci->port[pp.portnum].p,
+			 sizeof(struct sbecom_port_param)))
+		return -EFAULT;
+	return 0;
 }
 
 /* this function copys the user data and then calls the real action function */
-static      status_t
-do_set_port (struct net_device *ndev, void *data)
+static status_t
+do_set_port(struct net_device *ndev, void *data)
 {
-    ci_t       *ci;             /* ci stands for card information */
-    struct sbecom_port_param pp;/* copy data to kernel land */
+	ci_t       *ci;             /* ci stands for card information */
+	struct sbecom_port_param pp;/* copy data to kernel land */
 
-    if (copy_from_user (&pp, data, sizeof (struct sbecom_port_param)))
-        return -EFAULT;
-    if (pp.portnum >= MUSYCC_NPORTS)
-        return -EFAULT;
-    ci = get_ci_by_dev (ndev);
-    if (!ci)
-        return -EINVAL;             /* get card info */
+	if (copy_from_user(&pp, data, sizeof(struct sbecom_port_param)))
+		return -EFAULT;
+	if (pp.portnum >= MUSYCC_NPORTS)
+		return -EFAULT;
+	ci = get_ci_by_dev(ndev);
+	if (!ci)
+		return -EINVAL;             /* get card info */
 
-    if (pp.portnum >= ci->max_port) /* sanity check */
-        return -ENXIO;
+	if (pp.portnum >= ci->max_port) /* sanity check */
+		return -ENXIO;
 
-    memcpy (&ci->port[pp.portnum].p, &pp, sizeof (struct sbecom_port_param));
-    return mkret (c4_set_port (ci, pp.portnum));
+	memcpy(&ci->port[pp.portnum].p, &pp, sizeof(struct sbecom_port_param));
+	return mkret(c4_set_port(ci, pp.portnum));
 }
 
 /* work the port loopback mode as per directed */
-static      status_t
-do_port_loop (struct net_device *ndev, void *data)
+static status_t
+do_port_loop(struct net_device *ndev, void *data)
 {
-    struct sbecom_port_param pp;
-    ci_t       *ci;
+	struct sbecom_port_param pp;
+	ci_t       *ci;
 
-    if (copy_from_user (&pp, data, sizeof (struct sbecom_port_param)))
-        return -EFAULT;
-    ci = get_ci_by_dev (ndev);
-    if (!ci)
-        return -EINVAL;
-    return mkret (c4_loop_port (ci, pp.portnum, pp.port_mode));
+	if (copy_from_user(&pp, data, sizeof(struct sbecom_port_param)))
+		return -EFAULT;
+	ci = get_ci_by_dev(ndev);
+	if (!ci)
+		return -EINVAL;
+	return mkret(c4_loop_port(ci, pp.portnum, pp.port_mode));
 }
 
 /* set the specified register with the given value / or just read it */
-static      status_t
-do_framer_rw (struct net_device *ndev, void *data)
+static status_t
+do_framer_rw(struct net_device *ndev, void *data)
 {
-    struct sbecom_port_param pp;
-    ci_t       *ci;
-    int         ret;
+	struct sbecom_port_param pp;
+	ci_t       *ci;
+	int         ret;
 
-    if (copy_from_user (&pp, data, sizeof (struct sbecom_port_param)))
-        return -EFAULT;
-    ci = get_ci_by_dev (ndev);
-    if (!ci)
-        return -EINVAL;
-    ret = mkret (c4_frame_rw (ci, &pp));
-    if (ret)
-        return ret;
-    if (copy_to_user (data, &pp, sizeof (struct sbecom_port_param)))
-        return -EFAULT;
-    return 0;
+	if (copy_from_user(&pp, data, sizeof(struct sbecom_port_param)))
+		return -EFAULT;
+	ci = get_ci_by_dev(ndev);
+	if (!ci)
+		return -EINVAL;
+	ret = mkret(c4_frame_rw(ci, &pp));
+	if (ret)
+		return ret;
+	if (copy_to_user(data, &pp, sizeof(struct sbecom_port_param)))
+		return -EFAULT;
+	return 0;
 }
 
 /* set the specified register with the given value / or just read it */
-static      status_t
-do_pld_rw (struct net_device *ndev, void *data)
+static status_t
+do_pld_rw(struct net_device *ndev, void *data)
 {
-    struct sbecom_port_param pp;
-    ci_t       *ci;
-    int         ret;
+	struct sbecom_port_param pp;
+	ci_t       *ci;
+	int         ret;
 
-    if (copy_from_user (&pp, data, sizeof (struct sbecom_port_param)))
-        return -EFAULT;
-    ci = get_ci_by_dev (ndev);
-    if (!ci)
-        return -EINVAL;
-    ret = mkret (c4_pld_rw (ci, &pp));
-    if (ret)
-        return ret;
-    if (copy_to_user (data, &pp, sizeof (struct sbecom_port_param)))
-        return -EFAULT;
-    return 0;
+	if (copy_from_user(&pp, data, sizeof(struct sbecom_port_param)))
+		return -EFAULT;
+	ci = get_ci_by_dev(ndev);
+	if (!ci)
+		return -EINVAL;
+	ret = mkret(c4_pld_rw(ci, &pp));
+	if (ret)
+		return ret;
+	if (copy_to_user(data, &pp, sizeof(struct sbecom_port_param)))
+		return -EFAULT;
+	return 0;
 }
 
 /* set the specified register with the given value / or just read it */
-static      status_t
-do_musycc_rw (struct net_device *ndev, void *data)
+static status_t
+do_musycc_rw(struct net_device *ndev, void *data)
 {
-    struct c4_musycc_param mp;
-    ci_t       *ci;
-    int         ret;
+	struct c4_musycc_param mp;
+	ci_t       *ci;
+	int         ret;
 
-    if (copy_from_user (&mp, data, sizeof (struct c4_musycc_param)))
-        return -EFAULT;
-    ci = get_ci_by_dev (ndev);
-    if (!ci)
-        return -EINVAL;
-    ret = mkret (c4_musycc_rw (ci, &mp));
-    if (ret)
-        return ret;
-    if (copy_to_user (data, &mp, sizeof (struct c4_musycc_param)))
-        return -EFAULT;
-    return 0;
+	if (copy_from_user(&mp, data, sizeof(struct c4_musycc_param)))
+		return -EFAULT;
+	ci = get_ci_by_dev(ndev);
+	if (!ci)
+		return -EINVAL;
+	ret = mkret(c4_musycc_rw(ci, &mp));
+	if (ret)
+		return ret;
+	if (copy_to_user(data, &mp, sizeof(struct c4_musycc_param)))
+		return -EFAULT;
+	return 0;
 }
 
-static      status_t
-do_get_chan (struct net_device *ndev, void *data)
+static status_t
+do_get_chan(struct net_device *ndev, void *data)
 {
-    struct sbecom_chan_param cp;
-    int         ret;
+	struct sbecom_chan_param cp;
+	int         ret;
 
-    if (copy_from_user (&cp, data,
-                        sizeof (struct sbecom_chan_param)))
-        return -EFAULT;
+	if (copy_from_user(&cp, data,
+				sizeof(struct sbecom_chan_param)))
+		return -EFAULT;
 
-    if ((ret = mkret (c4_get_chan (cp.channum, &cp))))
-        return ret;
+	if ((ret = mkret(c4_get_chan(cp.channum, &cp))))
+		return ret;
 
-    if (copy_to_user (data, &cp, sizeof (struct sbecom_chan_param)))
-        return -EFAULT;
-    return 0;
+	if (copy_to_user(data, &cp, sizeof(struct sbecom_chan_param)))
+		return -EFAULT;
+	return 0;
 }
 
-static      status_t
-do_set_chan (struct net_device *ndev, void *data)
+static status_t
+do_set_chan(struct net_device *ndev, void *data)
 {
-    struct sbecom_chan_param cp;
-    int         ret;
-    ci_t       *ci;
+	struct sbecom_chan_param cp;
+	int         ret;
+	ci_t       *ci;
 
-    if (copy_from_user (&cp, data, sizeof (struct sbecom_chan_param)))
-        return -EFAULT;
-    ci = get_ci_by_dev (ndev);
-    if (!ci)
-        return -EINVAL;
-    switch (ret = mkret (c4_set_chan (cp.channum, &cp)))
-    {
-    case 0:
-        return 0;
-    default:
-        return ret;
-    }
+	if (copy_from_user(&cp, data, sizeof(struct sbecom_chan_param)))
+		return -EFAULT;
+	ci = get_ci_by_dev(ndev);
+	if (!ci)
+		return -EINVAL;
+	switch (ret = mkret(c4_set_chan(cp.channum, &cp)))
+	{
+	case 0:
+		return 0;
+	default:
+		return ret;
+	}
 }
 
-static      status_t
-do_create_chan (struct net_device *ndev, void *data)
+static status_t
+do_create_chan(struct net_device *ndev, void *data)
 {
-    ci_t       *ci;
-    struct net_device *dev;
-    struct sbecom_chan_param cp;
-    int         ret;
+	ci_t       *ci;
+	struct net_device *dev;
+	struct sbecom_chan_param cp;
+	int         ret;
 
-    if (copy_from_user (&cp, data, sizeof (struct sbecom_chan_param)))
-        return -EFAULT;
-    ci = get_ci_by_dev (ndev);
-    if (!ci)
-        return -EINVAL;
-    dev = create_chan (ndev, ci, &cp);
-    if (!dev)
-        return -EBUSY;
-    ret = mkret (c4_new_chan (ci, cp.port, cp.channum, dev));
-    if (ret)
-    {
-        rtnl_unlock ();             /* needed due to Ioctl calling sequence */
-        unregister_hdlc_device (dev);
-        rtnl_lock ();               /* needed due to Ioctl calling sequence */
-        free_netdev (dev);
-    }
-    return ret;
+	if (copy_from_user(&cp, data, sizeof(struct sbecom_chan_param)))
+		return -EFAULT;
+	ci = get_ci_by_dev(ndev);
+	if (!ci)
+		return -EINVAL;
+	dev = create_chan(ndev, ci, &cp);
+	if (!dev)
+		return -EBUSY;
+	ret = mkret(c4_new_chan(ci, cp.port, cp.channum, dev));
+	if (ret)
+	{
+		/* needed due to Ioctl calling sequence */
+		rtnl_unlock();
+		unregister_hdlc_device(dev);
+		/* needed due to Ioctl calling sequence */
+		rtnl_lock();
+		free_netdev(dev);
+	}
+	return ret;
 }
 
-static      status_t
-do_get_chan_stats (struct net_device *ndev, void *data)
+static status_t
+do_get_chan_stats(struct net_device *ndev, void *data)
 {
-    struct c4_chan_stats_wrap ccs;
-    int         ret;
+	struct c4_chan_stats_wrap ccs;
+	int         ret;
 
-    if (copy_from_user (&ccs, data,
-                        sizeof (struct c4_chan_stats_wrap)))
-        return -EFAULT;
-    switch (ret = mkret (c4_get_chan_stats (ccs.channum, &ccs.stats)))
-    {
-    case 0:
-        break;
-    default:
-        return ret;
-    }
-    if (copy_to_user (data, &ccs,
-                      sizeof (struct c4_chan_stats_wrap)))
-        return -EFAULT;
-    return 0;
+	if (copy_from_user(&ccs, data,
+			   sizeof(struct c4_chan_stats_wrap)))
+		return -EFAULT;
+	switch (ret = mkret(c4_get_chan_stats(ccs.channum, &ccs.stats)))
+	{
+	case 0:
+		break;
+	default:
+		return ret;
+	}
+	if (copy_to_user(data, &ccs,
+			 sizeof(struct c4_chan_stats_wrap)))
+		return -EFAULT;
+	return 0;
 }
-static      status_t
-do_set_loglevel (struct net_device *ndev, void *data)
+static status_t
+do_set_loglevel(struct net_device *ndev, void *data)
 {
-    unsigned int cxt1e1_log_level;
+	unsigned int cxt1e1_log_level;
 
-    if (copy_from_user (&cxt1e1_log_level, data, sizeof (int)))
-        return -EFAULT;
-    sbecom_set_loglevel (cxt1e1_log_level);
-    return 0;
+	if (copy_from_user(&cxt1e1_log_level, data, sizeof(int)))
+		return -EFAULT;
+	sbecom_set_loglevel(cxt1e1_log_level);
+	return 0;
 }
 
-static      status_t
-do_deluser (struct net_device *ndev, int lockit)
+static status_t
+do_deluser(struct net_device *ndev, int lockit)
 {
-    if (ndev->flags & IFF_UP)
-        return -EBUSY;
+	if (ndev->flags & IFF_UP)
+		return -EBUSY;
 
-    {
-        ci_t       *ci;
-        mch_t      *ch;
-        const struct c4_priv *priv;
-        int         channum;
+	{
+		ci_t       *ci;
+		mch_t      *ch;
+		const struct c4_priv *priv;
+		int         channum;
 
-        priv = (struct c4_priv *) dev_to_hdlc (ndev)->priv;
-        ci = priv->ci;
-        channum = priv->channum;
+		priv = (struct c4_priv *)dev_to_hdlc(ndev)->priv;
+		ci = priv->ci;
+		channum = priv->channum;
 
-        ch = c4_find_chan (channum);
-        if (ch == NULL)
-            return -ENOENT;
-	ch->user = NULL;	/* will be freed, below */
-    }
+		ch = c4_find_chan(channum);
+		if (ch == NULL)
+			return -ENOENT;
+		ch->user = NULL;	/* will be freed, below */
+	}
 
-    if (lockit)
-        rtnl_unlock ();             /* needed if Ioctl calling sequence */
-    unregister_hdlc_device (ndev);
-    if (lockit)
-        rtnl_lock ();               /* needed if Ioctl calling sequence */
-    free_netdev (ndev);
-    return 0;
+	/* needed if Ioctl calling sequence */
+	if (lockit)
+		rtnl_unlock();
+	unregister_hdlc_device(ndev);
+	/* needed if Ioctl calling sequence */
+	if (lockit)
+		rtnl_lock();
+	free_netdev(ndev);
+	return 0;
 }
 
 int
-do_del_chan (struct net_device *musycc_dev, void *data)
+do_del_chan(struct net_device *musycc_dev, void *data)
 {
-    struct sbecom_chan_param cp;
-    char        buf[sizeof (CHANNAME) + 3];
-    struct net_device *dev;
-    int         ret;
+	struct sbecom_chan_param cp;
+	char        buf[sizeof(CHANNAME) + 3];
+	struct net_device *dev;
+	int         ret;
 
-    if (copy_from_user (&cp, data,
-                        sizeof (struct sbecom_chan_param)))
-        return -EFAULT;
-    if (cp.channum > 999)
-        return -EINVAL;
-    snprintf (buf, sizeof(buf), CHANNAME "%d", cp.channum);
+	if (copy_from_user(&cp, data,
+			   sizeof(struct sbecom_chan_param)))
+		return -EFAULT;
+	if (cp.channum > 999)
+		return -EINVAL;
+	snprintf(buf, sizeof(buf), CHANNAME "%d", cp.channum);
 	dev = __dev_get_by_name(&init_net, buf);
 	if (!dev)
 		return -ENODEV;
-    ret = do_deluser (dev, 1);
-    if (ret)
-        return ret;
-    return c4_del_chan (cp.channum);
+	ret = do_deluser(dev, 1);
+	if (ret)
+		return ret;
+	return c4_del_chan(cp.channum);
 }
-int         c4_reset_board (void *);
+int c4_reset_board(void *);
 
 int
-do_reset (struct net_device *musycc_dev, void *data)
+do_reset(struct net_device *musycc_dev, void *data)
 {
-    const struct c4_priv *priv;
-    int         i;
+	const struct c4_priv *priv;
+	int         i;
 
-    for (i = 0; i < 128; i++)
-    {
-        struct net_device *ndev;
-        char        buf[sizeof (CHANNAME) + 3];
+	for (i = 0; i < 128; i++)
+	{
+		struct net_device *ndev;
+		char        buf[sizeof(CHANNAME) + 3];
 
-        sprintf (buf, CHANNAME "%d", i);
-	ndev = __dev_get_by_name(&init_net, buf);
-	if (!ndev)
-		continue;
-        priv = dev_to_hdlc (ndev)->priv;
+		sprintf(buf, CHANNAME "%d", i);
+		ndev = __dev_get_by_name(&init_net, buf);
+		if (!ndev)
+			continue;
+		priv = dev_to_hdlc(ndev)->priv;
 
-        if ((unsigned long) (priv->ci) ==
-            (unsigned long) (netdev_priv(musycc_dev)))
-        {
-            ndev->flags &= ~IFF_UP;
-            netif_stop_queue (ndev);
-            do_deluser (ndev, 1);
+		if ((unsigned long) (priv->ci) ==
+			(unsigned long) (netdev_priv(musycc_dev)))
+		{
+			ndev->flags &= ~IFF_UP;
+			netif_stop_queue(ndev);
+			do_deluser(ndev, 1);
+		}
 	}
-    }
-    return 0;
+	return 0;
 }
 
 int
-do_reset_chan_stats (struct net_device *musycc_dev, void *data)
+do_reset_chan_stats(struct net_device *musycc_dev, void *data)
 {
-    struct sbecom_chan_param cp;
+	struct sbecom_chan_param cp;
 
-    if (copy_from_user (&cp, data,
-                        sizeof (struct sbecom_chan_param)))
-        return -EFAULT;
-    return mkret (c4_del_chan_stats (cp.channum));
+	if (copy_from_user(&cp, data,
+			   sizeof(struct sbecom_chan_param)))
+		return -EFAULT;
+	return mkret(c4_del_chan_stats(cp.channum));
 }
 
-static      status_t
-c4_ioctl (struct net_device *ndev, struct ifreq *ifr, int cmd)
+static status_t
+c4_ioctl(struct net_device *ndev, struct ifreq *ifr, int cmd)
 {
-    ci_t       *ci;
-    void       *data;
-    int         iocmd, iolen;
-    status_t    ret;
-    static struct data
-    {
-        union
-        {
-            u_int8_t c;
-            u_int32_t i;
-            struct sbe_brd_info bip;
-            struct sbe_drv_info dip;
-            struct sbe_iid_info iip;
-            struct sbe_brd_addr bap;
-            struct sbecom_chan_stats stats;
-            struct sbecom_chan_param param;
-            struct temux_card_stats cards;
-            struct sbecom_card_param cardp;
-            struct sbecom_framer_param frp;
-        }           u;
-    }           arg;
+	ci_t       *ci;
+	void       *data;
+	int         iocmd, iolen;
+	status_t    ret;
+	static struct data
+	{
+		union
+		{
+			u_int8_t c;
+			u_int32_t i;
+			struct sbe_brd_info bip;
+			struct sbe_drv_info dip;
+			struct sbe_iid_info iip;
+			struct sbe_brd_addr bap;
+			struct sbecom_chan_stats stats;
+			struct sbecom_chan_param param;
+			struct temux_card_stats cards;
+			struct sbecom_card_param cardp;
+			struct sbecom_framer_param frp;
+		} u;
+	} arg;
 
 
-    if (!capable (CAP_SYS_ADMIN))
-        return -EPERM;
-    if (cmd != SIOCDEVPRIVATE + 15)
-        return -EINVAL;
-    if (!(ci = get_ci_by_dev (ndev)))
-        return -EINVAL;
-    if (ci->state != C_RUNNING)
-        return -ENODEV;
-    if (copy_from_user (&iocmd, ifr->ifr_data, sizeof (iocmd)))
-        return -EFAULT;
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+	if (cmd != SIOCDEVPRIVATE + 15)
+		return -EINVAL;
+	if (!(ci = get_ci_by_dev(ndev)))
+		return -EINVAL;
+	if (ci->state != C_RUNNING)
+		return -ENODEV;
+	if (copy_from_user(&iocmd, ifr->ifr_data, sizeof(iocmd)))
+		return -EFAULT;
 #if 0
-    if (copy_from_user (&len, ifr->ifr_data + sizeof (iocmd), sizeof (len)))
-        return -EFAULT;
+	if (copy_from_user(&len, ifr->ifr_data + sizeof(iocmd), sizeof(len)))
+		return -EFAULT;
 #endif
 
 #if 0
-    pr_info("c4_ioctl: iocmd %x, dir %x type %x nr %x iolen %d.\n", iocmd,
-            _IOC_DIR (iocmd), _IOC_TYPE (iocmd), _IOC_NR (iocmd),
-            _IOC_SIZE (iocmd));
+	pr_info("c4_ioctl: iocmd %x, dir %x type %x nr %x iolen %d.\n", iocmd,
+		_IOC_DIR(iocmd), _IOC_TYPE(iocmd), _IOC_NR(iocmd),
+		_IOC_SIZE(iocmd));
 #endif
-    iolen = _IOC_SIZE (iocmd);
-    data = ifr->ifr_data + sizeof (iocmd);
-    if (copy_from_user (&arg, data, iolen))
-        return -EFAULT;
+	iolen = _IOC_SIZE(iocmd);
+	data = ifr->ifr_data + sizeof(iocmd);
+	if (copy_from_user(&arg, data, iolen))
+		return -EFAULT;
 
-    ret = 0;
-    switch (iocmd)
-    {
-    case SBE_IOC_PORT_GET:
-        //pr_info(">> SBE_IOC_PORT_GET Ioctl...\n");
-        ret = do_get_port (ndev, data);
-        break;
-    case SBE_IOC_PORT_SET:
-        //pr_info(">> SBE_IOC_PORT_SET Ioctl...\n");
-        ret = do_set_port (ndev, data);
-        break;
-    case SBE_IOC_CHAN_GET:
-        //pr_info(">> SBE_IOC_CHAN_GET Ioctl...\n");
-        ret = do_get_chan (ndev, data);
-        break;
-    case SBE_IOC_CHAN_SET:
-        //pr_info(">> SBE_IOC_CHAN_SET Ioctl...\n");
-        ret = do_set_chan (ndev, data);
-        break;
-    case C4_DEL_CHAN:
-        //pr_info(">> C4_DEL_CHAN Ioctl...\n");
-        ret = do_del_chan (ndev, data);
-        break;
-    case SBE_IOC_CHAN_NEW:
-        ret = do_create_chan (ndev, data);
-        break;
-    case SBE_IOC_CHAN_GET_STAT:
-        ret = do_get_chan_stats (ndev, data);
-        break;
-    case SBE_IOC_LOGLEVEL:
-        ret = do_set_loglevel (ndev, data);
-        break;
-    case SBE_IOC_RESET_DEV:
-        ret = do_reset (ndev, data);
-        break;
-    case SBE_IOC_CHAN_DEL_STAT:
-        ret = do_reset_chan_stats (ndev, data);
-        break;
-    case C4_LOOP_PORT:
-        ret = do_port_loop (ndev, data);
-        break;
-    case C4_RW_FRMR:
-        ret = do_framer_rw (ndev, data);
-        break;
-    case C4_RW_MSYC:
-        ret = do_musycc_rw (ndev, data);
-        break;
-    case C4_RW_PLD:
-        ret = do_pld_rw (ndev, data);
-        break;
-    case SBE_IOC_IID_GET:
-        ret = (iolen == sizeof (struct sbe_iid_info)) ? c4_get_iidinfo (ci, &arg.u.iip) : -EFAULT;
-        if (ret == 0)               /* no error, copy data */
-            if (copy_to_user (data, &arg, iolen))
-                return -EFAULT;
-        break;
-    default:
-        //pr_info(">> c4_ioctl: EINVAL - unknown iocmd <%x>\n", iocmd);
-        ret = -EINVAL;
-        break;
-    }
-    return mkret (ret);
+	ret = 0;
+	switch (iocmd)
+	{
+	case SBE_IOC_PORT_GET:
+		//pr_info(">> SBE_IOC_PORT_GET Ioctl...\n");
+		ret = do_get_port(ndev, data);
+		break;
+	case SBE_IOC_PORT_SET:
+		//pr_info(">> SBE_IOC_PORT_SET Ioctl...\n");
+		ret = do_set_port(ndev, data);
+		break;
+	case SBE_IOC_CHAN_GET:
+		//pr_info(">> SBE_IOC_CHAN_GET Ioctl...\n");
+		ret = do_get_chan(ndev, data);
+		break;
+	case SBE_IOC_CHAN_SET:
+		//pr_info(">> SBE_IOC_CHAN_SET Ioctl...\n");
+		ret = do_set_chan(ndev, data);
+		break;
+	case C4_DEL_CHAN:
+		//pr_info(">> C4_DEL_CHAN Ioctl...\n");
+		ret = do_del_chan(ndev, data);
+		break;
+	case SBE_IOC_CHAN_NEW:
+		ret = do_create_chan(ndev, data);
+		break;
+	case SBE_IOC_CHAN_GET_STAT:
+		ret = do_get_chan_stats(ndev, data);
+		break;
+	case SBE_IOC_LOGLEVEL:
+		ret = do_set_loglevel(ndev, data);
+		break;
+	case SBE_IOC_RESET_DEV:
+		ret = do_reset(ndev, data);
+		break;
+	case SBE_IOC_CHAN_DEL_STAT:
+		ret = do_reset_chan_stats(ndev, data);
+		break;
+	case C4_LOOP_PORT:
+		ret = do_port_loop(ndev, data);
+		break;
+	case C4_RW_FRMR:
+		ret = do_framer_rw(ndev, data);
+		break;
+	case C4_RW_MSYC:
+		ret = do_musycc_rw(ndev, data);
+		break;
+	case C4_RW_PLD:
+		ret = do_pld_rw(ndev, data);
+		break;
+	case SBE_IOC_IID_GET:
+		ret = (iolen == sizeof(struct sbe_iid_info)) ?
+		       c4_get_iidinfo(ci, &arg.u.iip) : -EFAULT;
+		if (ret == 0)               /* no error, copy data */
+			if (copy_to_user(data, &arg, iolen))
+				return -EFAULT;
+		break;
+	default:
+		//pr_info(">> c4_ioctl: EINVAL - unknown iocmd <%x>\n", iocmd);
+		ret = -EINVAL;
+		break;
+	}
+	return mkret(ret);
 }
 
 static const struct net_device_ops c4_ops = {
-       .ndo_open       = void_open,
-       .ndo_start_xmit = c4_linux_xmit,
-       .ndo_do_ioctl   = c4_ioctl,
+	.ndo_open       = void_open,
+	.ndo_start_xmit = c4_linux_xmit,
+	.ndo_do_ioctl   = c4_ioctl,
 };
 
 static void c4_setup(struct net_device *dev)
 {
-       dev->type = ARPHRD_VOID;
-       dev->netdev_ops = &c4_ops;
+	dev->type = ARPHRD_VOID;
+	dev->netdev_ops = &c4_ops;
 }
 
 struct net_device *__init
-c4_add_dev (hdw_info_t *hi, int brdno, unsigned long f0, unsigned long f1,
-            int irq0, int irq1)
+c4_add_dev(hdw_info_t *hi, int brdno, unsigned long f0, unsigned long f1,
+	   int irq0, int irq1)
 {
-    struct net_device *ndev;
-    ci_t       *ci;
+	struct net_device *ndev;
+	ci_t       *ci;
 
-    ndev = alloc_netdev(sizeof(ci_t), SBE_IFACETMPL, c4_setup);
-    if (!ndev)
-    {
-        pr_warning("%s: no memory for struct net_device !\n", hi->devname);
-        error_flag = ENOMEM;
-	return NULL;
-    }
-    ci = (ci_t *)(netdev_priv(ndev));
-    ndev->irq = irq0;
+	ndev = alloc_netdev(sizeof(ci_t), SBE_IFACETMPL, c4_setup);
+	if (!ndev)
+	{
+		pr_warning("%s: no memory for struct net_device !\n",
+			   hi->devname);
+		error_flag = ENOMEM;
+		return NULL;
+	}
+	ci = (ci_t *)(netdev_priv(ndev));
+	ndev->irq = irq0;
 
-    ci->hdw_info = hi;
-    ci->state = C_INIT;         /* mark as hardware not available */
-    ci->next = c4_list;
-    c4_list = ci;
-    ci->brdno = ci->next ? ci->next->brdno + 1 : 0;
+	ci->hdw_info = hi;
+	ci->state = C_INIT;         /* mark as hardware not available */
+	ci->next = c4_list;
+	c4_list = ci;
+	ci->brdno = ci->next ? ci->next->brdno + 1 : 0;
 
-    if (!CI)
-        CI = ci;                    /* DEBUG, only board 0 usage */
+	if (!CI)
+		CI = ci;                    /* DEBUG, only board 0 usage */
 
-    strcpy (ci->devname, hi->devname);
-    ci->release = &pmcc4_OSSI_release[0];
+	strcpy(ci->devname, hi->devname);
+	ci->release = &pmcc4_OSSI_release[0];
 
-    /* tasklet */
+	/* tasklet */
 #if defined(SBE_ISR_TASKLET)
-    tasklet_init (&ci->ci_musycc_isr_tasklet,
-                  (void (*) (unsigned long)) musycc_intr_bh_tasklet,
-                  (unsigned long) ci);
+	tasklet_init(&ci->ci_musycc_isr_tasklet,
+		     (void (*) (unsigned long)) musycc_intr_bh_tasklet,
+		     (unsigned long) ci);
 
-    if (atomic_read (&ci->ci_musycc_isr_tasklet.count) == 0)
-        tasklet_disable_nosync (&ci->ci_musycc_isr_tasklet);
+	if (atomic_read(&ci->ci_musycc_isr_tasklet.count) == 0)
+		tasklet_disable_nosync(&ci->ci_musycc_isr_tasklet);
 #elif defined(SBE_ISR_IMMEDIATE)
-    ci->ci_musycc_isr_tq.routine = (void *) (unsigned long) musycc_intr_bh_tasklet;
-    ci->ci_musycc_isr_tq.data = ci;
+	ci->ci_musycc_isr_tq.routine = (void *)(unsigned long)musycc_intr_bh_tasklet;
+	ci->ci_musycc_isr_tq.data = ci;
 #endif
 
 
-    if (register_netdev (ndev) ||
-        (c4_init (ci, (u_char *) f0, (u_char *) f1) != SBE_DRVR_SUCCESS))
-    {
-        OS_kfree (netdev_priv(ndev));
-        OS_kfree (ndev);
-        error_flag = ENODEV;
-	return NULL;
-    }
-    /*************************************************************
-     *  int request_irq(unsigned int irq,
-     *                  void (*handler)(int, void *, struct pt_regs *),
-     *                  unsigned long flags, const char *dev_name, void *dev_id);
-     *  wherein:
-     *  irq      -> The interrupt number that is being requested.
-     *  handler  -> Pointer to handling function being installed.
-     *  flags    -> A bit mask of options related to interrupt management.
-     *  dev_name -> String used in /proc/interrupts to show owner of interrupt.
-     *  dev_id   -> Pointer (for shared interrupt lines) to point to its own
-     *              private data area (to identify which device is interrupting).
-     *
-     *  extern void free_irq(unsigned int irq, void *dev_id);
-     **************************************************************/
+	if (register_netdev(ndev) ||
+		(c4_init(ci, (u_char *) f0, (u_char *) f1) != SBE_DRVR_SUCCESS))
+	{
+		OS_kfree(netdev_priv(ndev));
+		OS_kfree(ndev);
+		error_flag = ENODEV;
+		return NULL;
+	}
+	/*************************************************************
+	 *  int request_irq(unsigned int irq,
+	 *                  void (*handler)(int, void *, struct pt_regs *),
+	 *                  unsigned long flags, const char *dev_name, void *dev_id);
+	 *  wherein:
+	 *  irq      -> The interrupt number that is being requested.
+	 *  handler  -> Pointer to handling function being installed.
+	 *  flags    -> A bit mask of options related to interrupt management.
+	 *  dev_name -> String used in /proc/interrupts to show owner of interrupt.
+	 *  dev_id   -> Pointer (for shared interrupt lines) to point to its own
+	 *              private data area (to identify which device is interrupting).
+	 *
+	 *  extern void free_irq(unsigned int irq, void *dev_id);
+	 **************************************************************/
 
-    if (request_irq (irq0, &c4_linux_interrupt,
-                     IRQF_SHARED,
-                     ndev->name, ndev))
-    {
-        pr_warning("%s: MUSYCC could not get irq: %d\n", ndev->name, irq0);
-        unregister_netdev (ndev);
-        OS_kfree (netdev_priv(ndev));
-        OS_kfree (ndev);
-        error_flag = EIO;
-	return NULL;
-    }
+	if (request_irq(irq0, &c4_linux_interrupt,
+			IRQF_SHARED,
+			ndev->name, ndev))
+	{
+		pr_warning("%s: MUSYCC could not get irq: %d\n",
+			   ndev->name, irq0);
+		unregister_netdev(ndev);
+		OS_kfree(netdev_priv(ndev));
+		OS_kfree(ndev);
+		error_flag = EIO;
+		return NULL;
+	}
 #ifdef CONFIG_SBE_PMCC4_NCOMM
-    if (request_irq (irq1, &c4_ebus_interrupt, IRQF_SHARED, ndev->name, ndev))
-    {
-        pr_warning("%s: EBUS could not get irq: %d\n", hi->devname, irq1);
-        unregister_netdev (ndev);
-        free_irq (irq0, ndev);
-        OS_kfree (netdev_priv(ndev));
-        OS_kfree (ndev);
-        error_flag = EIO;
-	return NULL;
-    }
+	if (request_irq(irq1, &c4_ebus_interrupt, IRQF_SHARED, ndev->name, ndev))
+	{
+		pr_warning("%s: EBUS could not get irq: %d\n", hi->devname, irq1);
+		unregister_netdev(ndev);
+		free_irq(irq0, ndev);
+		OS_kfree(netdev_priv(ndev));
+		OS_kfree(ndev);
+		error_flag = EIO;
+		return NULL;
+	}
 #endif
 
-    /* setup board identification information */
+	/* setup board identification information */
 
-    {
-        u_int32_t   tmp;
+	{
+		u_int32_t   tmp;
 
-        hdw_sn_get (hi, brdno);     /* also sets PROM format type (promfmt)
-                                     * for later usage */
+		/* also sets PROM format type (promfmt) for later usage */
+		hdw_sn_get(hi, brdno);
 
-        switch (hi->promfmt)
-        {
-        case PROM_FORMAT_TYPE1:
-            memcpy (ndev->dev_addr, (FLD_TYPE1 *) (hi->mfg_info.pft1.Serial), 6);
-            memcpy (&tmp, (FLD_TYPE1 *) (hi->mfg_info.pft1.Id), 4);     /* unaligned data
-                                                                         * acquisition */
-            ci->brd_id = cpu_to_be32 (tmp);
-            break;
-        case PROM_FORMAT_TYPE2:
-            memcpy (ndev->dev_addr, (FLD_TYPE2 *) (hi->mfg_info.pft2.Serial), 6);
-            memcpy (&tmp, (FLD_TYPE2 *) (hi->mfg_info.pft2.Id), 4);     /* unaligned data
-                                                                         * acquisition */
-            ci->brd_id = cpu_to_be32 (tmp);
-            break;
-        default:
-            ci->brd_id = 0;
-            memset (ndev->dev_addr, 0, 6);
-            break;
-        }
+		switch (hi->promfmt)
+		{
+		case PROM_FORMAT_TYPE1:
+			memcpy(ndev->dev_addr,
+			       (FLD_TYPE1 *) (hi->mfg_info.pft1.Serial), 6);
+			/* unaligned data acquisition */
+			memcpy(&tmp, (FLD_TYPE1 *) (hi->mfg_info.pft1.Id), 4);
+			ci->brd_id = cpu_to_be32(tmp);
+			break;
+		case PROM_FORMAT_TYPE2:
+			memcpy(ndev->dev_addr,
+			       (FLD_TYPE2 *) (hi->mfg_info.pft2.Serial), 6);
+			/* unaligned data acquisition */
+			memcpy(&tmp, (FLD_TYPE2 *) (hi->mfg_info.pft2.Id), 4);
+			ci->brd_id = cpu_to_be32(tmp);
+			break;
+		default:
+			ci->brd_id = 0;
+			memset(ndev->dev_addr, 0, 6);
+			break;
+		}
 
 #if 1
-        sbeid_set_hdwbid (ci);      /* requires bid to be preset */
+		/* requires bid to be preset */
+		sbeid_set_hdwbid(ci);
 #else
-        sbeid_set_bdtype (ci);      /* requires hdw_bid to be preset */
+		/* requires hdw_bid to be preset */
+		sbeid_set_bdtype(ci);
 #endif
-
-    }
+	}
 
 #ifdef CONFIG_PROC_FS
-    sbecom_proc_brd_init (ci);
+	sbecom_proc_brd_init(ci);
 #endif
 #if defined(SBE_ISR_TASKLET)
-    tasklet_enable (&ci->ci_musycc_isr_tasklet);
+	tasklet_enable(&ci->ci_musycc_isr_tasklet);
 #endif
 
 
-    if ((error_flag = c4_init2 (ci)) != SBE_DRVR_SUCCESS)
-    {
+	if ((error_flag = c4_init2(ci)) != SBE_DRVR_SUCCESS)
+	{
 #ifdef CONFIG_PROC_FS
-        sbecom_proc_brd_cleanup (ci);
+		sbecom_proc_brd_cleanup(ci);
 #endif
-        unregister_netdev (ndev);
-        free_irq (irq1, ndev);
-        free_irq (irq0, ndev);
-        OS_kfree (netdev_priv(ndev));
-        OS_kfree (ndev);
-	return NULL;		/* failure, error_flag is set */
-    }
-    return ndev;
+		unregister_netdev(ndev);
+		free_irq(irq1, ndev);
+		free_irq(irq0, ndev);
+		OS_kfree(netdev_priv(ndev));
+		OS_kfree(ndev);
+		/* failure, error_flag is set */
+		return NULL;
+	}
+	return ndev;
 }
 
 static int  __init
-c4_mod_init (void)
+c4_mod_init(void)
 {
-    int         rtn;
+	int         rtn;
 
-    pr_warning("%s\n", pmcc4_OSSI_release);
-    if ((rtn = c4hw_attach_all ()))
-        return -rtn;                /* installation failure - see system log */
+	pr_warning("%s\n", pmcc4_OSSI_release);
+	if ((rtn = c4hw_attach_all()))
+		return -rtn; /* installation failure - see system log */
 
-    /* housekeeping notifications */
-    if (cxt1e1_log_level != log_level_default)
-        pr_info("NOTE: driver parameter <cxt1e1_log_level> changed from default %d to %d.\n",
-                log_level_default, cxt1e1_log_level);
-       if (cxt1e1_max_mru != max_mru_default)
-               pr_info("NOTE: driver parameter <cxt1e1_max_mru> changed from default %d to %d.\n",
-                               max_mru_default, cxt1e1_max_mru);
-       if (cxt1e1_max_mtu != max_mtu_default)
-               pr_info("NOTE: driver parameter <cxt1e1_max_mtu> changed from default %d to %d.\n",
-                               max_mtu_default, cxt1e1_max_mtu);
-    if (max_rxdesc_used != max_rxdesc_default)
-    {
-        if (max_rxdesc_used > 2000)
-            max_rxdesc_used = 2000; /* out-of-bounds reset */
-        pr_info("NOTE: driver parameter <max_rxdesc_used> changed from default %d to %d.\n",
-                max_rxdesc_default, max_rxdesc_used);
-    }
-    if (max_txdesc_used != max_txdesc_default)
-    {
-        if (max_txdesc_used > 1000)
-            max_txdesc_used = 1000; /* out-of-bounds reset */
-        pr_info("NOTE: driver parameter <max_txdesc_used> changed from default %d to %d.\n",
-                max_txdesc_default, max_txdesc_used);
-    }
-    return 0;                       /* installation success */
+	/* housekeeping notifications */
+	if (cxt1e1_log_level != log_level_default)
+		pr_info("NOTE: driver parameter <cxt1e1_log_level> changed from default %d to %d.\n",
+			log_level_default, cxt1e1_log_level);
+	if (cxt1e1_max_mru != max_mru_default)
+		pr_info("NOTE: driver parameter <cxt1e1_max_mru> changed from default %d to %d.\n",
+			max_mru_default, cxt1e1_max_mru);
+	if (cxt1e1_max_mtu != max_mtu_default)
+		pr_info("NOTE: driver parameter <cxt1e1_max_mtu> changed from default %d to %d.\n",
+			max_mtu_default, cxt1e1_max_mtu);
+	if (max_rxdesc_used != max_rxdesc_default)
+	{
+		if (max_rxdesc_used > 2000)
+			max_rxdesc_used = 2000; /* out-of-bounds reset */
+		pr_info("NOTE: driver parameter <max_rxdesc_used> changed from default %d to %d.\n",
+			max_rxdesc_default, max_rxdesc_used);
+	}
+	if (max_txdesc_used != max_txdesc_default)
+	{
+		if (max_txdesc_used > 1000)
+			max_txdesc_used = 1000; /* out-of-bounds reset */
+		pr_info("NOTE: driver parameter <max_txdesc_used> changed from default %d to %d.\n",
+			max_txdesc_default, max_txdesc_used);
+	}
+	return 0;                       /* installation success */
 }
 
 
@@ -1138,31 +1160,31 @@
   */
 
 static void __exit
-cleanup_hdlc (void)
+cleanup_hdlc(void)
 {
-    hdw_info_t *hi;
-    ci_t       *ci;
-    struct net_device *ndev;
-    int         i, j, k;
+	hdw_info_t *hi;
+	ci_t       *ci;
+	struct net_device *ndev;
+	int         i, j, k;
 
-    for (i = 0, hi = hdw_info; i < MAX_BOARDS; i++, hi++)
-    {
-        if (hi->ndev)               /* a board has been attached */
-        {
-            ci = (ci_t *)(netdev_priv(hi->ndev));
-            for (j = 0; j < ci->max_port; j++)
-                for (k = 0; k < MUSYCC_NCHANS; k++)
-                    if ((ndev = ci->port[j].chan[k]->user))
-                    {
-                        do_deluser (ndev, 0);
-                    }
-        }
-    }
+	for (i = 0, hi = hdw_info; i < MAX_BOARDS; i++, hi++)
+	{
+		if (hi->ndev)               /* a board has been attached */
+		{
+			ci = (ci_t *)(netdev_priv(hi->ndev));
+			for (j = 0; j < ci->max_port; j++)
+				for (k = 0; k < MUSYCC_NCHANS; k++)
+					if ((ndev = ci->port[j].chan[k]->user))
+					{
+						do_deluser(ndev, 0);
+					}
+		}
+	}
 }
 
 
 static void __exit
-c4_mod_remove (void)
+c4_mod_remove(void)
 {
 	cleanup_hdlc();            /* delete any missed channels */
 	cleanup_devs();
@@ -1171,13 +1193,13 @@
 	pr_info("SBE - driver removed.\n");
 }
 
-module_init (c4_mod_init);
-module_exit (c4_mod_remove);
+module_init(c4_mod_init);
+module_exit(c4_mod_remove);
 
-MODULE_AUTHOR ("SBE Technical Services <support@sbei.com>");
-MODULE_DESCRIPTION ("wanPCI-CxT1E1 Generic HDLC WAN Driver module");
+MODULE_AUTHOR("SBE Technical Services <support@sbei.com>");
+MODULE_DESCRIPTION("wanPCI-CxT1E1 Generic HDLC WAN Driver module");
 #ifdef MODULE_LICENSE
-MODULE_LICENSE ("GPL");
+MODULE_LICENSE("GPL");
 #endif
 
 /***  End-of-File  ***/
diff --git a/drivers/staging/dgap/Makefile b/drivers/staging/dgap/Makefile
index 3abe8d2..0063d04 100644
--- a/drivers/staging/dgap/Makefile
+++ b/drivers/staging/dgap/Makefile
@@ -1,7 +1 @@
 obj-$(CONFIG_DGAP) += dgap.o
-
-
-dgap-objs :=	dgap_driver.o   dgap_fep5.o \
-		dgap_parse.o	dgap_trace.o \
-		dgap_tty.o	dgap_sysfs.o
-
diff --git a/drivers/staging/dgap/dgap.c b/drivers/staging/dgap/dgap.c
new file mode 100644
index 0000000..cbce457
--- /dev/null
+++ b/drivers/staging/dgap/dgap.c
@@ -0,0 +1,7857 @@
+/*
+ * Copyright 2003 Digi International (www.digi.com)
+ *	Scott H Kilau <Scott_Kilau at digi dot com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE.  See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ *	NOTE TO LINUX KERNEL HACKERS:  DO NOT REFORMAT THIS CODE!
+ *
+ *	This is shared code between Digi's CVS archive and the
+ *	Linux Kernel sources.
+ *	Changing the source just for reformatting needlessly breaks
+ *	our CVS diff history.
+ *
+ *	Send any bug fixes/changes to:  Eng.Linux at digi dot com.
+ *	Thank you.
+ *
+ */
+
+/*
+ *      In the original out of kernel Digi dgap driver, firmware
+ *      loading was done via user land to driver handshaking.
+ *
+ *      For cards that support a concentrator (port expander),
+ *      I believe the concentrator its self told the card which
+ *      concentrator is actually attached and then that info
+ *      was used to tell user land which concentrator firmware
+ *      image was to be downloaded. I think even the BIOS or
+ *      FEP images required could change with the connection
+ *      of a particular concentrator.
+ *
+ *      Since I have no access to any of these cards or
+ *      concentrators, I cannot put the correct concentrator
+ *      firmware file names into the firmware_info structure
+ *      as is now done for the BIOS and FEP images.
+ *
+ *      I think, but am not certain, that the cards supporting
+ *      concentrators will function without them. So support
+ *      of these cards has been left in this driver.
+ *
+ *      In order to fully support those cards, they would
+ *      either have to be acquired for dissection or maybe
+ *      Digi International could provide some assistance.
+ */
+#undef DIGI_CONCENTRATORS_SUPPORTED
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/delay.h>	/* For udelay */
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+#include <linux/sched.h>
+
+#include <linux/interrupt.h>	/* For tasklet and interrupt structs/defines */
+#include <linux/ctype.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/serial_reg.h>
+#include <linux/io.h>		/* For read[bwl]/write[bwl] */
+
+#include <linux/string.h>
+#include <linux/device.h>
+#include <linux/kdev_t.h>
+#include <linux/firmware.h>
+
+#include "dgap.h"
+
+#define init_MUTEX(sem)         sema_init(sem, 1)
+#define DECLARE_MUTEX(name)     \
+	struct semaphore name = __SEMAPHORE_INITIALIZER(name, 1)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Digi International, http://www.digi.com");
+MODULE_DESCRIPTION("Driver for the Digi International EPCA PCI based product line");
+MODULE_SUPPORTED_DEVICE("dgap");
+
+/*
+ * insmod command line overrideable parameters
+ *
+ * NOTE: we use a set of macros to create the variables, which allows
+ * us to specify the variable type, name, initial value, and description.
+ */
+PARM_INT(rawreadok,	1,		0644,	"Bypass flip buffers on input");
+
+
+/**************************************************************************
+ *
+ * protos for this file
+ *
+ */
+
+static int dgap_start(void);
+static void dgap_init_globals(void);
+static int dgap_found_board(struct pci_dev *pdev, int id);
+static void dgap_cleanup_board(struct board_t *brd);
+static void dgap_poll_handler(ulong dummy);
+static int dgap_init_pci(void);
+static int dgap_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
+static void dgap_remove_one(struct pci_dev *dev);
+static int dgap_probe1(struct pci_dev *pdev, int card_type);
+static int dgap_do_remap(struct board_t *brd);
+static irqreturn_t dgap_intr(int irq, void *voidbrd);
+
+/* Our function prototypes */
+static int dgap_tty_open(struct tty_struct *tty, struct file *file);
+static void dgap_tty_close(struct tty_struct *tty, struct file *file);
+static int dgap_block_til_ready(struct tty_struct *tty, struct file *file, struct channel_t *ch);
+static int dgap_tty_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg);
+static int dgap_tty_digigeta(struct tty_struct *tty, struct digi_t __user *retinfo);
+static int dgap_tty_digiseta(struct tty_struct *tty, struct digi_t __user *new_info);
+static int dgap_tty_digigetedelay(struct tty_struct *tty, int __user *retinfo);
+static int dgap_tty_digisetedelay(struct tty_struct *tty, int __user *new_info);
+static int dgap_tty_write_room(struct tty_struct *tty);
+static int dgap_tty_chars_in_buffer(struct tty_struct *tty);
+static void dgap_tty_start(struct tty_struct *tty);
+static void dgap_tty_stop(struct tty_struct *tty);
+static void dgap_tty_throttle(struct tty_struct *tty);
+static void dgap_tty_unthrottle(struct tty_struct *tty);
+static void dgap_tty_flush_chars(struct tty_struct *tty);
+static void dgap_tty_flush_buffer(struct tty_struct *tty);
+static void dgap_tty_hangup(struct tty_struct *tty);
+static int dgap_wait_for_drain(struct tty_struct *tty);
+static int dgap_set_modem_info(struct tty_struct *tty, unsigned int command, unsigned int __user *value);
+static int dgap_get_modem_info(struct channel_t *ch, unsigned int __user *value);
+static int dgap_tty_digisetcustombaud(struct tty_struct *tty, int __user *new_info);
+static int dgap_tty_digigetcustombaud(struct tty_struct *tty, int __user *retinfo);
+static int dgap_tty_tiocmget(struct tty_struct *tty);
+static int dgap_tty_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear);
+static int dgap_tty_send_break(struct tty_struct *tty, int msec);
+static void dgap_tty_wait_until_sent(struct tty_struct *tty, int timeout);
+static int dgap_tty_write(struct tty_struct *tty, const unsigned char *buf, int count);
+static void dgap_tty_set_termios(struct tty_struct *tty, struct ktermios *old_termios);
+static int dgap_tty_put_char(struct tty_struct *tty, unsigned char c);
+static void dgap_tty_send_xchar(struct tty_struct *tty, char ch);
+
+static int dgap_tty_register(struct board_t *brd);
+static int dgap_tty_preinit(void);
+static int dgap_tty_init(struct board_t *);
+static void dgap_tty_post_uninit(void);
+static void dgap_tty_uninit(struct board_t *);
+static void dgap_carrier(struct channel_t *ch);
+static void dgap_input(struct channel_t *ch);
+
+/*
+ * Our function prototypes from dgap_fep5
+ */
+static void dgap_cmdw_ext(struct channel_t *ch, u16 cmd, u16 word, uint ncmds);
+static int dgap_event(struct board_t *bd);
+
+static void dgap_poll_tasklet(unsigned long data);
+static void dgap_cmdb(struct channel_t *ch, uchar cmd, uchar byte1, uchar byte2, uint ncmds);
+static void dgap_cmdw(struct channel_t *ch, uchar cmd, u16 word, uint ncmds);
+static void dgap_wmove(struct channel_t *ch, char *buf, uint cnt);
+static int dgap_param(struct tty_struct *tty);
+static void dgap_parity_scan(struct channel_t *ch, unsigned char *cbuf, unsigned char *fbuf, int *len);
+static uint dgap_get_custom_baud(struct channel_t *ch);
+static void dgap_firmware_reset_port(struct channel_t *ch);
+
+/*
+ * Function prototypes from dgap_parse.c.
+ */
+static int dgap_gettok(char **in, struct cnode *p);
+static char *dgap_getword(char **in);
+static char *dgap_savestring(char *s);
+static struct cnode *dgap_newnode(int t);
+static int dgap_checknode(struct cnode *p);
+static void dgap_err(char *s);
+
+/*
+ * Function prototypes from dgap_sysfs.h
+ */
+struct board_t;
+struct channel_t;
+struct un_t;
+struct pci_driver;
+struct class_device;
+
+static void dgap_create_ports_sysfiles(struct board_t *bd);
+static void dgap_remove_ports_sysfiles(struct board_t *bd);
+
+static void dgap_create_driver_sysfiles(struct pci_driver *);
+static void dgap_remove_driver_sysfiles(struct pci_driver *);
+
+static void dgap_create_tty_sysfs(struct un_t *un, struct device *c);
+static void dgap_remove_tty_sysfs(struct device *c);
+
+/*
+ * Function prototypes from dgap_parse.h
+ */
+static int dgap_parsefile(char **in, int Remove);
+static struct cnode *dgap_find_config(int type, int bus, int slot);
+static uint dgap_config_get_number_of_ports(struct board_t *bd);
+static char *dgap_create_config_string(struct board_t *bd, char *string);
+static uint dgap_config_get_useintr(struct board_t *bd);
+static uint dgap_config_get_altpin(struct board_t *bd);
+
+static int dgap_ms_sleep(ulong ms);
+static void dgap_do_bios_load(struct board_t *brd, uchar __user *ubios, int len);
+static void dgap_do_fep_load(struct board_t *brd, uchar __user *ufep, int len);
+#ifdef DIGI_CONCENTRATORS_SUPPORTED
+static void dgap_do_conc_load(struct board_t *brd, uchar *uaddr, int len);
+#endif
+static int dgap_after_config_loaded(int board);
+static int dgap_finalize_board_init(struct board_t *brd);
+
+static void dgap_get_vpd(struct board_t *brd);
+static void dgap_do_reset_board(struct board_t *brd);
+static void dgap_do_wait_for_bios(struct board_t *brd);
+static void dgap_do_wait_for_fep(struct board_t *brd);
+static int dgap_tty_register_ports(struct board_t *brd);
+static int dgap_firmware_load(struct pci_dev *pdev, int card_type);
+
+/* Driver load/unload functions */
+int			dgap_init_module(void);
+void			dgap_cleanup_module(void);
+
+module_init(dgap_init_module);
+module_exit(dgap_cleanup_module);
+
+/*
+ * File operations permitted on Control/Management major.
+ */
+static const struct file_operations DgapBoardFops = {
+	.owner	= THIS_MODULE,
+};
+
+/*
+ * Globals
+ */
+static uint dgap_NumBoards;
+static struct board_t *dgap_Board[MAXBOARDS];
+DEFINE_SPINLOCK(dgap_global_lock);
+static ulong dgap_poll_counter;
+static char *dgap_config_buf;
+static int dgap_driver_state = DRIVER_INITIALIZED;
+DEFINE_SPINLOCK(dgap_dl_lock);
+static wait_queue_head_t dgap_dl_wait;
+static int dgap_dl_action;
+static int dgap_poll_tick = 20;	/* Poll interval - 20 ms */
+
+/*
+ * Static vars.
+ */
+static int dgap_Major_Control_Registered = FALSE;
+static uint dgap_driver_start = FALSE;
+
+static struct class *dgap_class;
+
+static struct board_t *dgap_BoardsByMajor[256];
+static uchar *dgap_TmpWriteBuf = NULL;
+DECLARE_MUTEX(dgap_TmpWriteSem);
+static uint dgap_count = 500;
+
+/*
+ * Poller stuff
+ */
+DEFINE_SPINLOCK(dgap_poll_lock);	/* Poll scheduling lock */
+static ulong dgap_poll_time;		/* Time of next poll */
+static uint dgap_poll_stop;		/* Used to tell poller to stop */
+static struct timer_list dgap_poll_timer;
+
+/*
+     SUPPORTED PRODUCTS
+
+     Card Model               Number of Ports      Interface
+     ----------------------------------------------------------------
+     Acceleport Xem           4 - 64              (EIA232 & EIA422)
+     Acceleport Xr            4 & 8               (EIA232)
+     Acceleport Xr 920        4 & 8               (EIA232)
+     Acceleport C/X           8 - 128             (EIA232)
+     Acceleport EPC/X         8 - 224             (EIA232)
+     Acceleport Xr/422        4 & 8               (EIA422)
+     Acceleport 2r/920        2                   (EIA232)
+     Acceleport 4r/920        4                   (EIA232)
+     Acceleport 8r/920        8                   (EIA232)
+
+     IBM 8-Port Asynchronous PCI Adapter          (EIA232)
+     IBM 128-Port Asynchronous PCI Adapter        (EIA232 & EIA422)
+*/
+
+static struct pci_device_id dgap_pci_tbl[] = {
+	{       DIGI_VID, PCI_DEVICE_XEM_DID,	PCI_ANY_ID, PCI_ANY_ID, 0, 0,	0 },
+	{       DIGI_VID, PCI_DEVICE_CX_DID,	PCI_ANY_ID, PCI_ANY_ID, 0, 0,   1 },
+	{       DIGI_VID, PCI_DEVICE_CX_IBM_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0,	2 },
+	{       DIGI_VID, PCI_DEVICE_EPCJ_DID,	PCI_ANY_ID, PCI_ANY_ID, 0, 0,	3 },
+	{       DIGI_VID, PCI_DEVICE_920_2_DID,	PCI_ANY_ID, PCI_ANY_ID, 0, 0,	4 },
+	{       DIGI_VID, PCI_DEVICE_920_4_DID,	PCI_ANY_ID, PCI_ANY_ID, 0, 0,	5 },
+	{       DIGI_VID, PCI_DEVICE_920_8_DID,	PCI_ANY_ID, PCI_ANY_ID, 0, 0,	6 },
+	{       DIGI_VID, PCI_DEVICE_XR_DID,	PCI_ANY_ID, PCI_ANY_ID, 0, 0,	7 },
+	{       DIGI_VID, PCI_DEVICE_XRJ_DID,	PCI_ANY_ID, PCI_ANY_ID, 0, 0,	8 },
+	{       DIGI_VID, PCI_DEVICE_XR_422_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0,	9 },
+	{       DIGI_VID, PCI_DEVICE_XR_IBM_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0,	10 },
+	{       DIGI_VID, PCI_DEVICE_XR_SAIP_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0,	11 },
+	{       DIGI_VID, PCI_DEVICE_XR_BULL_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0,	12 },
+	{       DIGI_VID, PCI_DEVICE_920_8_HP_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 13 },
+	{       DIGI_VID, PCI_DEVICE_XEM_HP_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0,	14 },
+	{0,}					/* 0 terminated list. */
+};
+MODULE_DEVICE_TABLE(pci, dgap_pci_tbl);
+
+/*
+ * A generic list of Product names, PCI Vendor ID, and PCI Device ID.
+ */
+struct board_id {
+	uint config_type;
+	uchar *name;
+	uint maxports;
+	uint dpatype;
+};
+
+static struct board_id dgap_Ids[] = {
+	{	PPCM,		PCI_DEVICE_XEM_NAME,	64,	(T_PCXM | T_PCLITE | T_PCIBUS)	},
+	{	PCX,		PCI_DEVICE_CX_NAME,	128,	(T_CX | T_PCIBUS)		},
+	{	PCX,		PCI_DEVICE_CX_IBM_NAME,	128,	(T_CX | T_PCIBUS)		},
+	{	PEPC,		PCI_DEVICE_EPCJ_NAME,	224,	(T_EPC  | T_PCIBUS)		},
+	{	APORT2_920P,	PCI_DEVICE_920_2_NAME,	2,	(T_PCXR | T_PCLITE | T_PCIBUS)	},
+	{	APORT4_920P,	PCI_DEVICE_920_4_NAME,	4,	(T_PCXR | T_PCLITE | T_PCIBUS)	},
+	{	APORT8_920P,	PCI_DEVICE_920_8_NAME,	8,	(T_PCXR | T_PCLITE | T_PCIBUS)	},
+	{	PAPORT8,	PCI_DEVICE_XR_NAME,	8,	(T_PCXR | T_PCLITE | T_PCIBUS)	},
+	{	PAPORT8,	PCI_DEVICE_XRJ_NAME,	8,	(T_PCXR | T_PCLITE | T_PCIBUS)	},
+	{	PAPORT8,	PCI_DEVICE_XR_422_NAME,	8,	(T_PCXR | T_PCLITE | T_PCIBUS)	},
+	{	PAPORT8,	PCI_DEVICE_XR_IBM_NAME,	8,	(T_PCXR | T_PCLITE | T_PCIBUS)	},
+	{	PAPORT8,	PCI_DEVICE_XR_SAIP_NAME, 8,	(T_PCXR | T_PCLITE | T_PCIBUS)	},
+	{	PAPORT8,	PCI_DEVICE_XR_BULL_NAME, 8,	(T_PCXR | T_PCLITE | T_PCIBUS)	},
+	{	APORT8_920P,	PCI_DEVICE_920_8_HP_NAME, 8,	(T_PCXR | T_PCLITE | T_PCIBUS)	},
+	{	PPCM,		PCI_DEVICE_XEM_HP_NAME,	64,	(T_PCXM | T_PCLITE | T_PCIBUS)	},
+	{0,}						/* 0 terminated list. */
+};
+
+static struct pci_driver dgap_driver = {
+	.name		= "dgap",
+	.probe		= dgap_init_one,
+	.id_table	= dgap_pci_tbl,
+	.remove		= dgap_remove_one,
+};
+
+struct firmware_info {
+	uchar *conf_name;       /* dgap.conf */
+	uchar *bios_name;	/* BIOS filename */
+	uchar *fep_name;	/* FEP  filename */
+	uchar *con_name;	/* Concentrator filename  FIXME*/
+	int num;                /* sequence number */
+};
+
+/*
+ * Firmware - BIOS, FEP, and CONC filenames
+ */
+static struct firmware_info fw_info[] = {
+	{ "dgap/dgap.conf", "dgap/sxbios.bin",  "dgap/sxfep.bin",  0, 0 },
+	{ "dgap/dgap.conf", "dgap/cxpbios.bin", "dgap/cxpfep.bin", 0, 1 },
+	{ "dgap/dgap.conf", "dgap/cxpbios.bin", "dgap/cxpfep.bin", 0, 2 },
+	{ "dgap/dgap.conf", "dgap/pcibios.bin", "dgap/pcifep.bin", 0, 3 },
+	{ "dgap/dgap.conf", "dgap/xrbios.bin",  "dgap/xrfep.bin",  0, 4 },
+	{ "dgap/dgap.conf", "dgap/xrbios.bin",  "dgap/xrfep.bin",  0, 5 },
+	{ "dgap/dgap.conf", "dgap/xrbios.bin",  "dgap/xrfep.bin",  0, 6 },
+	{ "dgap/dgap.conf", "dgap/xrbios.bin",  "dgap/xrfep.bin",  0, 7 },
+	{ "dgap/dgap.conf", "dgap/xrbios.bin",  "dgap/xrfep.bin",  0, 8 },
+	{ "dgap/dgap.conf", "dgap/xrbios.bin",  "dgap/xrfep.bin",  0, 9 },
+	{ "dgap/dgap.conf", "dgap/xrbios.bin",  "dgap/xrfep.bin",  0, 10 },
+	{ "dgap/dgap.conf", "dgap/xrbios.bin",  "dgap/xrfep.bin",  0, 11 },
+	{ "dgap/dgap.conf", "dgap/xrbios.bin",  "dgap/xrfep.bin",  0, 12 },
+	{ "dgap/dgap.conf", "dgap/xrbios.bin",  "dgap/xrfep.bin",  0, 13 },
+	{ "dgap/dgap.conf", "dgap/sxbios.bin",  "dgap/sxfep.bin",  0, 14 },
+	{0,}
+};
+
+static char *dgap_driver_state_text[] = {
+	"Driver Initialized",
+	"Driver needs configuration load.",
+	"Driver requested configuration from download daemon.",
+	"Driver Ready."
+};
+
+/*
+ * Default transparent print information.
+ */
+static struct digi_t dgap_digi_init = {
+	.digi_flags =	DIGI_COOK,	/* Flags			*/
+	.digi_maxcps =	100,		/* Max CPS			*/
+	.digi_maxchar =	50,		/* Max chars in print queue	*/
+	.digi_bufsize =	100,		/* Printer buffer size		*/
+	.digi_onlen =	4,		/* size of printer on string	*/
+	.digi_offlen =	4,		/* size of printer off string	*/
+	.digi_onstr =	"\033[5i",	/* ANSI printer on string ]	*/
+	.digi_offstr =	"\033[4i",	/* ANSI printer off string ]	*/
+	.digi_term =	"ansi"		/* default terminal type	*/
+};
+
+/*
+ * Define a local default termios struct. All ports will be created
+ * with this termios initially.
+ *
+ * This defines a raw port at 9600 baud, 8 data bits, no parity,
+ * 1 stop bit.
+ */
+
+static struct ktermios DgapDefaultTermios = {
+	.c_iflag =	(DEFAULT_IFLAGS),	/* iflags */
+	.c_oflag =	(DEFAULT_OFLAGS),	/* oflags */
+	.c_cflag =	(DEFAULT_CFLAGS),	/* cflags */
+	.c_lflag =	(DEFAULT_LFLAGS),	/* lflags */
+	.c_cc =		INIT_C_CC,
+	.c_line =	0,
+};
+
+static const struct tty_operations dgap_tty_ops = {
+	.open = dgap_tty_open,
+	.close = dgap_tty_close,
+	.write = dgap_tty_write,
+	.write_room = dgap_tty_write_room,
+	.flush_buffer = dgap_tty_flush_buffer,
+	.chars_in_buffer = dgap_tty_chars_in_buffer,
+	.flush_chars = dgap_tty_flush_chars,
+	.ioctl = dgap_tty_ioctl,
+	.set_termios = dgap_tty_set_termios,
+	.stop = dgap_tty_stop,
+	.start = dgap_tty_start,
+	.throttle = dgap_tty_throttle,
+	.unthrottle = dgap_tty_unthrottle,
+	.hangup = dgap_tty_hangup,
+	.put_char = dgap_tty_put_char,
+	.tiocmget = dgap_tty_tiocmget,
+	.tiocmset = dgap_tty_tiocmset,
+	.break_ctl = dgap_tty_send_break,
+	.wait_until_sent = dgap_tty_wait_until_sent,
+	.send_xchar = dgap_tty_send_xchar
+};
+
+/*
+ * Our needed internal static variables from dgap_parse.c
+ */
+static struct cnode dgap_head;
+#define MAXCWORD 200
+static char dgap_cword[MAXCWORD];
+
+struct toklist {
+	int	token;
+	char	*string;
+};
+
+static struct toklist dgap_tlist[] = {
+	{	BEGIN,		"config_begin"			},
+	{	END,		"config_end"			},
+	{	BOARD,		"board"				},
+	{	PCX,		"Digi_AccelePort_C/X_PCI"	},	/* C/X_PCI */
+	{	PEPC,		"Digi_AccelePort_EPC/X_PCI"	},	/* EPC/X_PCI */
+	{	PPCM,		"Digi_AccelePort_Xem_PCI"	},	/* PCI/Xem */
+	{	APORT2_920P,	"Digi_AccelePort_2r_920_PCI"	},
+	{	APORT4_920P,	"Digi_AccelePort_4r_920_PCI"	},
+	{	APORT8_920P,	"Digi_AccelePort_8r_920_PCI"	},
+	{	PAPORT4,	"Digi_AccelePort_4r_PCI(EIA-232/RS-422)" },
+	{	PAPORT8,	"Digi_AccelePort_8r_PCI(EIA-232/RS-422)" },
+	{	IO,		"io"				},
+	{	PCIINFO,	"pciinfo"			},
+	{	LINE,		"line"				},
+	{	CONC,		"conc"				},
+	{	CONC,		"concentrator"			},
+	{	CX,		"cx"				},
+	{	CX,		"ccon"				},
+	{	EPC,		"epccon"			},
+	{	EPC,		"epc"				},
+	{	MOD,		"module"			},
+	{	ID,		"id"				},
+	{	STARTO,		"start"				},
+	{	SPEED,		"speed"				},
+	{	CABLE,		"cable"				},
+	{	CONNECT,	"connect"			},
+	{	METHOD,		"method"			},
+	{	STATUS,		"status"			},
+	{	CUSTOM,		"Custom"			},
+	{	BASIC,		"Basic"				},
+	{	MEM,		"mem"				},
+	{	MEM,		"memory"			},
+	{	PORTS,		"ports"				},
+	{	MODEM,		"modem"				},
+	{	NPORTS,		"nports"			},
+	{	TTYN,		"ttyname"			},
+	{	CU,		"cuname"			},
+	{	PRINT,		"prname"			},
+	{	CMAJOR,		"major"				},
+	{	ALTPIN,		"altpin"			},
+	{	USEINTR,	"useintr"			},
+	{	TTSIZ,		"ttysize"			},
+	{	CHSIZ,		"chsize"			},
+	{	BSSIZ,		"boardsize"			},
+	{	UNTSIZ,		"schedsize"			},
+	{	F2SIZ,		"f2200size"			},
+	{	VPSIZ,		"vpixsize"			},
+	{	0,		NULL				}
+};
+
+/************************************************************************
+ *
+ * Driver load/unload functions
+ *
+ ************************************************************************/
+
+/*
+ * init_module()
+ *
+ * Module load.  This is where it all starts.
+ */
+int dgap_init_module(void)
+{
+	int rc = 0;
+
+	pr_info("%s, Digi International Part Number %s\n", DG_NAME, DG_PART);
+
+	dgap_driver_state = DRIVER_NEED_CONFIG_LOAD;
+
+	/*
+	 * Initialize global stuff
+	 */
+	rc = dgap_start();
+
+	if (rc < 0)
+		return rc;
+
+	/*
+	 * Find and configure all the cards
+	 */
+	rc = dgap_init_pci();
+
+	/*
+	 * If something went wrong in the scan, bail out of driver.
+	 */
+	if (rc < 0) {
+		/* Only unregister the pci driver if it was actually registered. */
+		if (dgap_NumBoards)
+			pci_unregister_driver(&dgap_driver);
+		else
+			printk("WARNING: dgap driver load failed.  No DGAP boards found.\n");
+
+		dgap_cleanup_module();
+	} else {
+		dgap_create_driver_sysfiles(&dgap_driver);
+		dgap_driver_state = DRIVER_READY;
+	}
+
+	return rc;
+}
+
+/*
+ * Start of driver.
+ */
+static int dgap_start(void)
+{
+	int rc = 0;
+	unsigned long flags;
+
+	if (dgap_driver_start == FALSE) {
+
+		dgap_driver_start = TRUE;
+
+		/*
+		 * make sure that the globals are
+		 * init'd before we do anything else
+		 */
+		dgap_init_globals();
+
+		dgap_NumBoards = 0;
+
+		pr_info("For the tools package please visit http://www.digi.com\n");
+
+		/*
+		 * Register our base character device into the kernel.
+		 * This allows the download daemon to connect to the downld device
+		 * before any of the boards are init'ed.
+		 */
+		if (!dgap_Major_Control_Registered) {
+			/*
+			 * Register management/dpa devices
+			 */
+			rc = register_chrdev(DIGI_DGAP_MAJOR, "dgap", &DgapBoardFops);
+			if (rc < 0)
+				return rc;
+
+			dgap_class = class_create(THIS_MODULE, "dgap_mgmt");
+			device_create(dgap_class, NULL,
+				MKDEV(DIGI_DGAP_MAJOR, 0),
+				NULL, "dgap_mgmt");
+			dgap_Major_Control_Registered = TRUE;
+		}
+
+		/*
+		 * Init any global tty stuff.
+		 */
+		rc = dgap_tty_preinit();
+
+		if (rc < 0)
+			return rc;
+
+		/* Start the poller */
+		DGAP_LOCK(dgap_poll_lock, flags);
+		init_timer(&dgap_poll_timer);
+		dgap_poll_timer.function = dgap_poll_handler;
+		dgap_poll_timer.data = 0;
+		dgap_poll_time = jiffies + dgap_jiffies_from_ms(dgap_poll_tick);
+		dgap_poll_timer.expires = dgap_poll_time;
+		DGAP_UNLOCK(dgap_poll_lock, flags);
+
+		add_timer(&dgap_poll_timer);
+
+		dgap_driver_state = DRIVER_NEED_CONFIG_LOAD;
+	}
+
+	return rc;
+}
+
+/*
+ * Register pci driver, and return how many boards we have.
+ */
+static int dgap_init_pci(void)
+{
+	return pci_register_driver(&dgap_driver);
+}
+
+/* returns count (>= 0), or negative on error */
+static int dgap_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+	int rc;
+
+	/* wake up and enable device */
+	rc = pci_enable_device(pdev);
+
+	if (rc < 0) {
+		rc = -EIO;
+	} else {
+		rc = dgap_probe1(pdev, ent->driver_data);
+		if (rc == 0) {
+			dgap_NumBoards++;
+			rc = dgap_firmware_load(pdev, ent->driver_data);
+		}
+	}
+	return rc;
+}
+
+static int dgap_probe1(struct pci_dev *pdev, int card_type)
+{
+	return dgap_found_board(pdev, card_type);
+}
+
+static void dgap_remove_one(struct pci_dev *dev)
+{
+	/* Do Nothing */
+}
+
+/*
+ * dgap_cleanup_module()
+ *
+ * Module unload.  This is where it all ends.
+ */
+void dgap_cleanup_module(void)
+{
+	int i;
+	ulong lock_flags;
+
+	DGAP_LOCK(dgap_poll_lock, lock_flags);
+	dgap_poll_stop = 1;
+	DGAP_UNLOCK(dgap_poll_lock, lock_flags);
+
+	/* Turn off poller right away. */
+	del_timer_sync(&dgap_poll_timer);
+
+	dgap_remove_driver_sysfiles(&dgap_driver);
+
+
+	if (dgap_Major_Control_Registered) {
+		device_destroy(dgap_class, MKDEV(DIGI_DGAP_MAJOR, 0));
+		device_destroy(dgap_class, MKDEV(DIGI_DGAP_MAJOR, 1));
+		class_destroy(dgap_class);
+		unregister_chrdev(DIGI_DGAP_MAJOR, "dgap");
+	}
+
+	kfree(dgap_config_buf);
+
+	for (i = 0; i < dgap_NumBoards; ++i) {
+		dgap_remove_ports_sysfiles(dgap_Board[i]);
+		dgap_tty_uninit(dgap_Board[i]);
+		dgap_cleanup_board(dgap_Board[i]);
+	}
+
+	dgap_tty_post_uninit();
+
+#if defined(DGAP_TRACER)
+	/* last thing, make sure we release the tracebuffer */
+	dgap_tracer_free();
+#endif
+	if (dgap_NumBoards)
+		pci_unregister_driver(&dgap_driver);
+}
+
+/*
+ * dgap_cleanup_board()
+ *
+ * Free all the memory associated with a board
+ */
+static void dgap_cleanup_board(struct board_t *brd)
+{
+	int i = 0;
+
+	if (!brd || brd->magic != DGAP_BOARD_MAGIC)
+		return;
+
+	if (brd->intr_used && brd->irq)
+		free_irq(brd->irq, brd);
+
+	tasklet_kill(&brd->helper_tasklet);
+
+	if (brd->re_map_port) {
+		release_mem_region(brd->membase + 0x200000, 0x200000);
+		iounmap(brd->re_map_port);
+		brd->re_map_port = NULL;
+	}
+
+	if (brd->re_map_membase) {
+		release_mem_region(brd->membase, 0x200000);
+		iounmap(brd->re_map_membase);
+		brd->re_map_membase = NULL;
+	}
+
+	if (brd->msgbuf_head) {
+		unsigned long flags;
+
+		DGAP_LOCK(dgap_global_lock, flags);
+		brd->msgbuf = NULL;
+		printk("%s", brd->msgbuf_head);
+		kfree(brd->msgbuf_head);
+		brd->msgbuf_head = NULL;
+		DGAP_UNLOCK(dgap_global_lock, flags);
+	}
+
+	/* Free all allocated channels structs */
+	for (i = 0; i < MAXPORTS ; i++) {
+		if (brd->channels[i]) {
+			kfree(brd->channels[i]);
+			brd->channels[i] = NULL;
+		}
+	}
+
+	kfree(brd->flipbuf);
+	kfree(brd->flipflagbuf);
+
+	dgap_Board[brd->boardnum] = NULL;
+
+	kfree(brd);
+}
+
+/*
+ * dgap_found_board()
+ *
+ * A board has been found, init it.
+ */
+static int dgap_found_board(struct pci_dev *pdev, int id)
+{
+	struct board_t *brd;
+	unsigned int pci_irq;
+	int i = 0;
+	unsigned long flags;
+
+	/* get the board structure and prep it */
+	brd = dgap_Board[dgap_NumBoards] =
+	(struct board_t *) kzalloc(sizeof(struct board_t), GFP_KERNEL);
+	if (!brd)
+		return -ENOMEM;
+
+	/* make a temporary message buffer for the boot messages */
+	brd->msgbuf = brd->msgbuf_head =
+		(char *) kzalloc(sizeof(char) * 8192, GFP_KERNEL);
+	if (!brd->msgbuf) {
+		kfree(brd);
+		return -ENOMEM;
+	}
+
+	/* store the info for the board we've found */
+	brd->magic = DGAP_BOARD_MAGIC;
+	brd->boardnum = dgap_NumBoards;
+	brd->firstminor = 0;
+	brd->vendor = dgap_pci_tbl[id].vendor;
+	brd->device = dgap_pci_tbl[id].device;
+	brd->pdev = pdev;
+	brd->pci_bus = pdev->bus->number;
+	brd->pci_slot = PCI_SLOT(pdev->devfn);
+	brd->name = dgap_Ids[id].name;
+	brd->maxports = dgap_Ids[id].maxports;
+	brd->type = dgap_Ids[id].config_type;
+	brd->dpatype = dgap_Ids[id].dpatype;
+	brd->dpastatus = BD_NOFEP;
+	init_waitqueue_head(&brd->state_wait);
+
+	DGAP_SPINLOCK_INIT(brd->bd_lock);
+
+	brd->state		= BOARD_FOUND;
+	brd->runwait		= 0;
+	brd->inhibit_poller	= FALSE;
+	brd->wait_for_bios	= 0;
+	brd->wait_for_fep	= 0;
+
+	for (i = 0; i < MAXPORTS; i++)
+		brd->channels[i] = NULL;
+
+	/* store which card & revision we have */
+	pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, &brd->subvendor);
+	pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, &brd->subdevice);
+	pci_read_config_byte(pdev, PCI_REVISION_ID, &brd->rev);
+
+	pci_irq = pdev->irq;
+	brd->irq = pci_irq;
+
+	/* get the PCI Base Address Registers */
+
+	/* Xr Jupiter and EPC use BAR 2 */
+	if (brd->device == PCI_DEVICE_XRJ_DID || brd->device == PCI_DEVICE_EPCJ_DID) {
+		brd->membase     = pci_resource_start(pdev, 2);
+		brd->membase_end = pci_resource_end(pdev, 2);
+	}
+	/* Everyone else uses BAR 0 */
+	else {
+		brd->membase     = pci_resource_start(pdev, 0);
+		brd->membase_end = pci_resource_end(pdev, 0);
+	}
+
+	if (!brd->membase)
+		return -ENODEV;
+
+	if (brd->membase & 1)
+		brd->membase &= ~3;
+	else
+		brd->membase &= ~15;
+
+	/*
+	 * On the PCI boards, there is no IO space allocated
+	 * The I/O registers will be in the first 3 bytes of the
+	 * upper 2MB of the 4MB memory space.  The board memory
+	 * will be mapped into the low 2MB of the 4MB memory space
+	 */
+	brd->port = brd->membase + PCI_IO_OFFSET;
+	brd->port_end = brd->port + PCI_IO_SIZE;
+
+	/*
+	 * Special initialization for non-PLX boards
+	 */
+	if (brd->device != PCI_DEVICE_XRJ_DID && brd->device != PCI_DEVICE_EPCJ_DID) {
+		unsigned short cmd;
+
+		pci_write_config_byte(pdev, 0x40, 0);
+		pci_write_config_byte(pdev, 0x46, 0);
+
+		/* Limit burst length to 2 doubleword transactions */
+		pci_write_config_byte(pdev, 0x42, 1);
+
+		/*
+		 * Enable IO and mem if not already done.
+		 * This was needed for support on Itanium.
+		 */
+		pci_read_config_word(pdev, PCI_COMMAND, &cmd);
+		cmd |= (PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
+		pci_write_config_word(pdev, PCI_COMMAND, cmd);
+	}
+
+	/* init our poll helper tasklet */
+	tasklet_init(&brd->helper_tasklet, dgap_poll_tasklet, (unsigned long) brd);
+
+	DGAP_LOCK(dgap_global_lock, flags);
+	brd->msgbuf = NULL;
+	printk("%s", brd->msgbuf_head);
+	kfree(brd->msgbuf_head);
+	brd->msgbuf_head = NULL;
+	DGAP_UNLOCK(dgap_global_lock, flags);
+
+	i = dgap_do_remap(brd);
+	if (i)
+		brd->state = BOARD_FAILED;
+	else
+		brd->state = NEED_RESET;
+
+	return 0;
+}
+
+
+static int dgap_finalize_board_init(struct board_t *brd)
+{
+	int rc;
+
+	if (!brd || brd->magic != DGAP_BOARD_MAGIC)
+		return -ENODEV;
+
+	brd->use_interrupts = dgap_config_get_useintr(brd);
+
+	/*
+	 * Set up our interrupt handler if we are set to do interrupts.
+	 */
+	if (brd->use_interrupts && brd->irq) {
+
+		rc = request_irq(brd->irq, dgap_intr, IRQF_SHARED, "DGAP", brd);
+
+		if (rc)
+			brd->intr_used = 0;
+		else
+			brd->intr_used = 1;
+	} else {
+		brd->intr_used = 0;
+	}
+
+	return 0;
+}
+
+static int dgap_firmware_load(struct pci_dev *pdev, int card_type)
+{
+	struct board_t *brd = dgap_Board[dgap_NumBoards - 1];
+	const struct firmware *fw;
+	int ret;
+
+	dgap_get_vpd(brd);
+	dgap_do_reset_board(brd);
+
+	if ((fw_info[card_type].conf_name) &&
+	    (dgap_driver_state == DRIVER_NEED_CONFIG_LOAD)) {
+		ret = request_firmware(&fw, fw_info[card_type].conf_name,
+					 &pdev->dev);
+		if (ret) {
+			pr_err("dgap: config file %s not found\n",
+				fw_info[card_type].conf_name);
+			return ret;
+		}
+		if (!dgap_config_buf) {
+			dgap_config_buf = kmalloc(fw->size + 1, GFP_ATOMIC);
+			if (!dgap_config_buf) {
+				release_firmware(fw);
+				return -ENOMEM;
+			}
+		}
+
+		memcpy(dgap_config_buf, fw->data, fw->size);
+		release_firmware(fw);
+		dgap_config_buf[fw->size + 1] = '\0';
+
+		if (dgap_parsefile(&dgap_config_buf, TRUE) != 0)
+			return -EINVAL;
+
+		dgap_driver_state = -1;
+	}
+
+	ret = dgap_after_config_loaded(brd->boardnum);
+	if (ret)
+		return ret;
+	/*
+	 * Match this board to a config the user created for us.
+	 */
+	brd->bd_config =
+		dgap_find_config(brd->type, brd->pci_bus, brd->pci_slot);
+
+	/*
+	 * Because the 4 port Xr products share the same PCI ID
+	 * as the 8 port Xr products, if we receive a NULL config
+	 * back, and this is a PAPORT8 board, retry with a
+	 * PAPORT4 attempt as well.
+	 */
+	if (brd->type == PAPORT8 && !brd->bd_config)
+		brd->bd_config =
+			dgap_find_config(PAPORT4, brd->pci_bus, brd->pci_slot);
+
+	if (!brd->bd_config) {
+		pr_err("dgap: No valid configuration found\n");
+		return -EINVAL;
+	}
+
+	dgap_tty_register(brd);
+	dgap_finalize_board_init(brd);
+
+	if (fw_info[card_type].bios_name) {
+		ret = request_firmware(&fw, fw_info[card_type].bios_name,
+					&pdev->dev);
+		if (ret) {
+			pr_err("dgap: bios file %s not found\n",
+				fw_info[card_type].bios_name);
+			return ret;
+		}
+		dgap_do_bios_load(brd, (char *)fw->data, fw->size);
+		release_firmware(fw);
+
+		/* Wait for BIOS to test board... */
+		dgap_do_wait_for_bios(brd);
+
+		if (brd->state != FINISHED_BIOS_LOAD)
+			return -ENXIO;
+	}
+
+	if (fw_info[card_type].fep_name) {
+		ret = request_firmware(&fw, fw_info[card_type].fep_name,
+					&pdev->dev);
+		if (ret) {
+			pr_err("dgap: fep file %s not found\n",
+				fw_info[card_type].fep_name);
+			return ret;
+		}
+		dgap_do_fep_load(brd, (char *)fw->data, fw->size);
+		release_firmware(fw);
+
+		/* Wait for FEP to load on board... */
+		dgap_do_wait_for_fep(brd);
+
+		if (brd->state != FINISHED_FEP_LOAD)
+			return -ENXIO;
+	}
+
+#ifdef DIGI_CONCENTRATORS_SUPPORTED
+	/*
+	 * If this is a CX or EPCX, we need to see if the firmware
+	 * is requesting a concentrator image from us.
+	 */
+	if ((bd->type == PCX) || (bd->type == PEPC)) {
+		chk_addr = (u16 *) (vaddr + DOWNREQ);
+		/* Nonzero if FEP is requesting concentrator image. */
+		check = readw(chk_addr);
+		vaddr = brd->re_map_membase;
+	}
+
+	if (fw_info[card_type].con_name && check && vaddr) {
+		ret = request_firmware(&fw, fw_info[card_type].con_name,
+					&pdev->dev);
+		if (ret) {
+			pr_err("dgap: conc file %s not found\n",
+				fw_info[card_type].con_name);
+			return ret;
+		}
+		/* Put concentrator firmware loading code here */
+		offset = readw((u16 *) (vaddr + DOWNREQ));
+		memcpy_toio(offset, fw->data, fw->size);
+
+		dgap_do_conc_load(brd, (char *)fw->data, fw->size)
+		release_firmware(fw);
+	}
+#endif
+	/*
+	 * Do tty device initialization.
+	 */
+	ret = dgap_tty_init(brd);
+	if (ret < 0) {
+		dgap_tty_uninit(brd);
+		return ret;
+	}
+
+	ret = dgap_tty_register_ports(brd);
+	if (ret)
+		return ret;
+
+	brd->state = BOARD_READY;
+	brd->dpastatus = BD_RUNNING;
+
+	return 0;
+}
+
+/*
+ * Remap PCI memory.
+ */
+static int dgap_do_remap(struct board_t *brd)
+{
+	if (!brd || brd->magic != DGAP_BOARD_MAGIC)
+		return -ENXIO;
+
+	if (!request_mem_region(brd->membase, 0x200000, "dgap"))
+		return -ENOMEM;
+
+	if (!request_mem_region(brd->membase + PCI_IO_OFFSET, 0x200000, "dgap")) {
+		release_mem_region(brd->membase, 0x200000);
+		return -ENOMEM;
+	}
+
+	brd->re_map_membase = ioremap(brd->membase, 0x200000);
+	if (!brd->re_map_membase) {
+		release_mem_region(brd->membase, 0x200000);
+		release_mem_region(brd->membase + PCI_IO_OFFSET, 0x200000);
+		return -ENOMEM;
+	}
+
+	brd->re_map_port = ioremap((brd->membase + PCI_IO_OFFSET), 0x200000);
+	if (!brd->re_map_port) {
+		release_mem_region(brd->membase, 0x200000);
+		release_mem_region(brd->membase + PCI_IO_OFFSET, 0x200000);
+		iounmap(brd->re_map_membase);
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
+/*****************************************************************************
+*
+* Function:
+*
+*    dgap_poll_handler
+*
+* Author:
+*
+*    Scott H Kilau
+*
+* Parameters:
+*
+*    dummy -- ignored
+*
+* Return Values:
+*
+*    none
+*
+* Description:
+*
+*    As each timer expires, it determines (a) whether the "transmit"
+*    waiter needs to be woken up, and (b) whether the poller needs to
+*    be rescheduled.
+*
+******************************************************************************/
+
+static void dgap_poll_handler(ulong dummy)
+{
+	int i;
+	struct board_t *brd;
+	unsigned long lock_flags;
+	ulong new_time;
+
+	dgap_poll_counter++;
+
+	/*
+	 * Do not start the board state machine until
+	 * driver tells us its up and running, and has
+	 * everything it needs.
+	 */
+	if (dgap_driver_state != DRIVER_READY)
+		goto schedule_poller;
+
+	/*
+	 * If we have just 1 board, or the system is not SMP,
+	 * then use the typical old style poller.
+	 * Otherwise, use our new tasklet based poller, which should
+	 * speed things up for multiple boards.
+	 */
+	if ((dgap_NumBoards == 1) || (num_online_cpus() <= 1)) {
+		for (i = 0; i < dgap_NumBoards; i++) {
+
+			brd = dgap_Board[i];
+
+			if (brd->state == BOARD_FAILED)
+				continue;
+			if (!brd->intr_running)
+				/* Call the real board poller directly */
+				dgap_poll_tasklet((unsigned long) brd);
+		}
+	} else {
+		/* Go thru each board, kicking off a tasklet for each if needed */
+		for (i = 0; i < dgap_NumBoards; i++) {
+			brd = dgap_Board[i];
+
+			/*
+			 * Attempt to grab the board lock.
+			 *
+			 * If we can't get it, no big deal, the next poll will get it.
+			 * Basically, I just really don't want to spin in here, because I want
+			 * to kick off my tasklets as fast as I can, and then get out the poller.
+			 */
+			if (!spin_trylock(&brd->bd_lock))
+				continue;
+
+			/* If board is in a failed state, don't bother scheduling a tasklet */
+			if (brd->state == BOARD_FAILED) {
+				spin_unlock(&brd->bd_lock);
+				continue;
+			}
+
+			/* Schedule a poll helper task */
+			if (!brd->intr_running)
+				tasklet_schedule(&brd->helper_tasklet);
+
+			/*
+			 * Can't do DGAP_UNLOCK here, as we don't have
+			 * lock_flags because we did a trylock above.
+			 */
+			spin_unlock(&brd->bd_lock);
+		}
+	}
+
+schedule_poller:
+
+	/*
+	 * Schedule ourself back at the nominal wakeup interval.
+	 */
+	DGAP_LOCK(dgap_poll_lock, lock_flags);
+	dgap_poll_time +=  dgap_jiffies_from_ms(dgap_poll_tick);
+
+	new_time = dgap_poll_time - jiffies;
+
+	if ((ulong) new_time >= 2 * dgap_poll_tick)
+		dgap_poll_time = jiffies +  dgap_jiffies_from_ms(dgap_poll_tick);
+
+	dgap_poll_timer.function = dgap_poll_handler;
+	dgap_poll_timer.data = 0;
+	dgap_poll_timer.expires = dgap_poll_time;
+	DGAP_UNLOCK(dgap_poll_lock, lock_flags);
+
+	if (!dgap_poll_stop)
+		add_timer(&dgap_poll_timer);
+}
+
+/*
+ * dgap_intr()
+ *
+ * Driver interrupt handler.
+ */
+static irqreturn_t dgap_intr(int irq, void *voidbrd)
+{
+	struct board_t *brd = (struct board_t *) voidbrd;
+
+	if (!brd)
+		return IRQ_NONE;
+
+	/*
+	 * Check to make sure its for us.
+	 */
+	if (brd->magic != DGAP_BOARD_MAGIC)
+		return IRQ_NONE;
+
+	brd->intr_count++;
+
+	/*
+	 * Schedule tasklet to run at a better time.
+	 */
+	tasklet_schedule(&brd->helper_tasklet);
+	return IRQ_HANDLED;
+}
+
+/*
+ * dgap_init_globals()
+ *
+ * This is where we initialize the globals from the static insmod
+ * configuration variables.  These are declared near the head of
+ * this file.
+ */
+static void dgap_init_globals(void)
+{
+	int i = 0;
+
+	dgap_rawreadok		= rawreadok;
+
+	for (i = 0; i < MAXBOARDS; i++)
+		dgap_Board[i] = NULL;
+
+	init_timer(&dgap_poll_timer);
+
+	init_waitqueue_head(&dgap_dl_wait);
+	dgap_dl_action = 0;
+}
+
+/************************************************************************
+ *
+ * Utility functions
+ *
+ ************************************************************************/
+
+/*
+ * dgap_ms_sleep()
+ *
+ * Put the driver to sleep for x ms's
+ *
+ * Returns 0 if timed out, !0 (showing signal) if interrupted by a signal.
+ */
+static int dgap_ms_sleep(ulong ms)
+{
+	current->state = TASK_INTERRUPTIBLE;
+	schedule_timeout((ms * HZ) / 1000);
+	return signal_pending(current);
+}
+
+/************************************************************************
+ *
+ * TTY Initialization/Cleanup Functions
+ *
+ ************************************************************************/
+
+/*
+ * dgap_tty_preinit()
+ *
+ * Initialize any global tty related data before we download any boards.
+ */
+static int dgap_tty_preinit(void)
+{
+	unsigned long flags;
+
+	DGAP_LOCK(dgap_global_lock, flags);
+
+	/*
+	 * Allocate a buffer for doing the copy from user space to
+	 * kernel space in dgap_input().  We only use one buffer and
+	 * control access to it with a semaphore.  If we are paging, we
+	 * are already in trouble so one buffer won't hurt much anyway.
+	 */
+	dgap_TmpWriteBuf = kmalloc(WRITEBUFLEN, GFP_ATOMIC);
+
+	if (!dgap_TmpWriteBuf) {
+		DGAP_UNLOCK(dgap_global_lock, flags);
+		return -ENOMEM;
+	}
+
+	DGAP_UNLOCK(dgap_global_lock, flags);
+	return 0;
+}
+
+/*
+ * dgap_tty_register()
+ *
+ * Init the tty subsystem for this board.
+ */
+static int dgap_tty_register(struct board_t *brd)
+{
+	int rc = 0;
+
+	brd->SerialDriver = alloc_tty_driver(MAXPORTS);
+
+	snprintf(brd->SerialName, MAXTTYNAMELEN, "tty_dgap_%d_", brd->boardnum);
+	brd->SerialDriver->name = brd->SerialName;
+	brd->SerialDriver->name_base = 0;
+	brd->SerialDriver->major = 0;
+	brd->SerialDriver->minor_start = 0;
+	brd->SerialDriver->type = TTY_DRIVER_TYPE_SERIAL;
+	brd->SerialDriver->subtype = SERIAL_TYPE_NORMAL;
+	brd->SerialDriver->init_termios = DgapDefaultTermios;
+	brd->SerialDriver->driver_name = DRVSTR;
+	brd->SerialDriver->flags = (TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV | TTY_DRIVER_HARDWARE_BREAK);
+
+	/* The kernel wants space to store pointers to tty_structs */
+	brd->SerialDriver->ttys = kzalloc(MAXPORTS * sizeof(struct tty_struct *), GFP_KERNEL);
+	if (!brd->SerialDriver->ttys)
+		return -ENOMEM;
+
+	/*
+	 * Entry points for driver.  Called by the kernel from
+	 * tty_io.c and n_tty.c.
+	 */
+	tty_set_operations(brd->SerialDriver, &dgap_tty_ops);
+
+	/*
+	 * If we're doing transparent print, we have to do all of the above
+	 * again, separately so we don't get the LD confused about what major
+	 * we are when we get into the dgap_tty_open() routine.
+	 */
+	brd->PrintDriver = alloc_tty_driver(MAXPORTS);
+
+	snprintf(brd->PrintName, MAXTTYNAMELEN, "pr_dgap_%d_", brd->boardnum);
+	brd->PrintDriver->name = brd->PrintName;
+	brd->PrintDriver->name_base = 0;
+	brd->PrintDriver->major = 0;
+	brd->PrintDriver->minor_start = 0;
+	brd->PrintDriver->type = TTY_DRIVER_TYPE_SERIAL;
+	brd->PrintDriver->subtype = SERIAL_TYPE_NORMAL;
+	brd->PrintDriver->init_termios = DgapDefaultTermios;
+	brd->PrintDriver->driver_name = DRVSTR;
+	brd->PrintDriver->flags = (TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV | TTY_DRIVER_HARDWARE_BREAK);
+
+	/* The kernel wants space to store pointers to tty_structs */
+	brd->PrintDriver->ttys = kzalloc(MAXPORTS * sizeof(struct tty_struct *), GFP_KERNEL);
+	if (!brd->PrintDriver->ttys)
+		return -ENOMEM;
+
+	/*
+	 * Entry points for driver.  Called by the kernel from
+	 * tty_io.c and n_tty.c.
+	 */
+	tty_set_operations(brd->PrintDriver, &dgap_tty_ops);
+
+	if (!brd->dgap_Major_Serial_Registered) {
+		/* Register tty devices */
+		rc = tty_register_driver(brd->SerialDriver);
+		if (rc < 0)
+			return rc;
+		brd->dgap_Major_Serial_Registered = TRUE;
+		dgap_BoardsByMajor[brd->SerialDriver->major] = brd;
+		brd->dgap_Serial_Major = brd->SerialDriver->major;
+	}
+
+	if (!brd->dgap_Major_TransparentPrint_Registered) {
+		/* Register Transparent Print devices */
+		rc = tty_register_driver(brd->PrintDriver);
+		if (rc < 0)
+			return rc;
+		brd->dgap_Major_TransparentPrint_Registered = TRUE;
+		dgap_BoardsByMajor[brd->PrintDriver->major] = brd;
+		brd->dgap_TransparentPrint_Major = brd->PrintDriver->major;
+	}
+
+	return rc;
+}
+
+/*
+ * dgap_tty_init()
+ *
+ * Init the tty subsystem.  Called once per board after board has been
+ * downloaded and init'ed.
+ */
+static int dgap_tty_init(struct board_t *brd)
+{
+	int i;
+	int tlw;
+	uint true_count = 0;
+	uchar *vaddr;
+	uchar modem = 0;
+	struct channel_t *ch;
+	struct bs_t *bs;
+	struct cm_t *cm;
+
+	if (!brd)
+		return -ENXIO;
+
+	/*
+	 * Initialize board structure elements.
+	 */
+
+	vaddr = brd->re_map_membase;
+	true_count = readw((vaddr + NCHAN));
+
+	brd->nasync = dgap_config_get_number_of_ports(brd);
+
+	if (!brd->nasync)
+		brd->nasync = brd->maxports;
+
+	if (brd->nasync > brd->maxports)
+		brd->nasync = brd->maxports;
+
+	if (true_count != brd->nasync) {
+		if ((brd->type == PPCM) && (true_count == 64))
+			pr_warn("dgap: %s configured for %d ports, has %d ports.\nPlease make SURE the EBI cable running from the card\nto each EM module is plugged into EBI IN!\n",
+				brd->name, brd->nasync, true_count);
+		else if ((brd->type == PPCM) && (true_count == 0))
+			pr_warn("dgap: %s configured for %d ports, has %d ports.\nPlease make SURE the EBI cable running from the card\nto each EM module is plugged into EBI IN!\n",
+				brd->name, brd->nasync, true_count);
+		else
+			pr_warn("dgap: %s configured for %d ports, has %d ports.\n",
+				brd->name, brd->nasync, true_count);
+
+		brd->nasync = true_count;
+
+		/* If no ports, don't bother going any further */
+		if (!brd->nasync) {
+			brd->state = BOARD_FAILED;
+			brd->dpastatus = BD_NOFEP;
+			return -ENXIO;
+		}
+	}
+
+	/*
+	 * Allocate channel memory that might not have been allocated
+	 * when the driver was first loaded.
+	 */
+	for (i = 0; i < brd->nasync; i++) {
+		if (!brd->channels[i]) {
+			brd->channels[i] = kzalloc(sizeof(struct channel_t), GFP_ATOMIC);
+			if (!brd->channels[i])
+				return -ENOMEM;
+		}
+	}
+
+	ch = brd->channels[0];
+	vaddr = brd->re_map_membase;
+
+	bs = (struct bs_t *) ((ulong) vaddr + CHANBUF);
+	cm = (struct cm_t *) ((ulong) vaddr + CMDBUF);
+
+	brd->bd_bs = bs;
+
+	/* Set up channel variables */
+	for (i = 0; i < brd->nasync; i++, ch = brd->channels[i], bs++) {
+
+		if (!brd->channels[i])
+			continue;
+
+		DGAP_SPINLOCK_INIT(ch->ch_lock);
+
+		/* Store all our magic numbers */
+		ch->magic = DGAP_CHANNEL_MAGIC;
+		ch->ch_tun.magic = DGAP_UNIT_MAGIC;
+		ch->ch_tun.un_type = DGAP_SERIAL;
+		ch->ch_tun.un_ch = ch;
+		ch->ch_tun.un_dev = i;
+
+		ch->ch_pun.magic = DGAP_UNIT_MAGIC;
+		ch->ch_pun.un_type = DGAP_PRINT;
+		ch->ch_pun.un_ch = ch;
+		ch->ch_pun.un_dev = i;
+
+		ch->ch_vaddr = vaddr;
+		ch->ch_bs = bs;
+		ch->ch_cm = cm;
+		ch->ch_bd = brd;
+		ch->ch_portnum = i;
+		ch->ch_digi = dgap_digi_init;
+
+		/*
+		 * Set up digi dsr and dcd bits based on altpin flag.
+		 */
+		if (dgap_config_get_altpin(brd)) {
+			ch->ch_dsr	= DM_CD;
+			ch->ch_cd	= DM_DSR;
+			ch->ch_digi.digi_flags |= DIGI_ALTPIN;
+		} else {
+			ch->ch_cd	= DM_CD;
+			ch->ch_dsr	= DM_DSR;
+		}
+
+		ch->ch_taddr = vaddr + ((ch->ch_bs->tx_seg) << 4);
+		ch->ch_raddr = vaddr + ((ch->ch_bs->rx_seg) << 4);
+		ch->ch_tx_win = 0;
+		ch->ch_rx_win = 0;
+		ch->ch_tsize = readw(&(ch->ch_bs->tx_max)) + 1;
+		ch->ch_rsize = readw(&(ch->ch_bs->rx_max)) + 1;
+		ch->ch_tstart = 0;
+		ch->ch_rstart = 0;
+
+		/* .25 second delay */
+		ch->ch_close_delay = 250;
+
+		/*
+		 * Set queue water marks, interrupt mask,
+		 * and general tty parameters.
+		 */
+		ch->ch_tlw = tlw = ch->ch_tsize >= 2000 ? ((ch->ch_tsize * 5) / 8) : ch->ch_tsize / 2;
+
+		dgap_cmdw(ch, STLOW, tlw, 0);
+
+		dgap_cmdw(ch, SRLOW, ch->ch_rsize / 2, 0);
+
+		dgap_cmdw(ch, SRHIGH, 7 * ch->ch_rsize / 8, 0);
+
+		ch->ch_mistat = readb(&(ch->ch_bs->m_stat));
+
+		init_waitqueue_head(&ch->ch_flags_wait);
+		init_waitqueue_head(&ch->ch_tun.un_flags_wait);
+		init_waitqueue_head(&ch->ch_pun.un_flags_wait);
+		init_waitqueue_head(&ch->ch_sniff_wait);
+
+		/* Turn on all modem interrupts for now */
+		modem = (DM_CD | DM_DSR | DM_CTS | DM_RI);
+		writeb(modem, &(ch->ch_bs->m_int));
+
+		/*
+		 * Set edelay to 0 if interrupts are turned on,
+		 * otherwise set edelay to the usual 100.
+		 */
+		if (brd->intr_used)
+			writew(0, &(ch->ch_bs->edelay));
+		else
+			writew(100, &(ch->ch_bs->edelay));
+
+		writeb(1, &(ch->ch_bs->idata));
+	}
+
+	return 0;
+}
+
+/*
+ * dgap_tty_post_uninit()
+ *
+ * UnInitialize any global tty related data.
+ */
+static void dgap_tty_post_uninit(void)
+{
+	kfree(dgap_TmpWriteBuf);
+	dgap_TmpWriteBuf = NULL;
+}
+
+/*
+ * dgap_tty_uninit()
+ *
+ * Uninitialize the TTY portion of this driver.  Free all memory and
+ * resources.
+ */
+static void dgap_tty_uninit(struct board_t *brd)
+{
+	int i = 0;
+
+	if (brd->dgap_Major_Serial_Registered) {
+		dgap_BoardsByMajor[brd->SerialDriver->major] = NULL;
+		brd->dgap_Serial_Major = 0;
+		for (i = 0; i < brd->nasync; i++) {
+			tty_port_destroy(&brd->SerialPorts[i]);
+			dgap_remove_tty_sysfs(brd->channels[i]->ch_tun.un_sysfs);
+			tty_unregister_device(brd->SerialDriver, i);
+		}
+		tty_unregister_driver(brd->SerialDriver);
+		kfree(brd->SerialDriver->ttys);
+		brd->SerialDriver->ttys = NULL;
+		put_tty_driver(brd->SerialDriver);
+		kfree(brd->SerialPorts);
+		brd->dgap_Major_Serial_Registered = FALSE;
+	}
+
+	if (brd->dgap_Major_TransparentPrint_Registered) {
+		dgap_BoardsByMajor[brd->PrintDriver->major] = NULL;
+		brd->dgap_TransparentPrint_Major = 0;
+		for (i = 0; i < brd->nasync; i++) {
+			tty_port_destroy(&brd->PrinterPorts[i]);
+			dgap_remove_tty_sysfs(brd->channels[i]->ch_pun.un_sysfs);
+			tty_unregister_device(brd->PrintDriver, i);
+		}
+		tty_unregister_driver(brd->PrintDriver);
+		kfree(brd->PrintDriver->ttys);
+		brd->PrintDriver->ttys = NULL;
+		put_tty_driver(brd->PrintDriver);
+		kfree(brd->PrinterPorts);
+		brd->dgap_Major_TransparentPrint_Registered = FALSE;
+	}
+}
+
+#define TMPBUFLEN (1024)
+/*
+ * dgap_sniff - Dump data out to the "sniff" buffer if the
+ * proc sniff file is opened...
+ */
+static void dgap_sniff_nowait_nolock(struct channel_t *ch, uchar *text, uchar *buf, int len)
+{
+	struct timeval tv;
+	int n;
+	int r;
+	int nbuf;
+	int i;
+	int tmpbuflen;
+	char tmpbuf[TMPBUFLEN];
+	char *p = tmpbuf;
+	int too_much_data;
+
+	/* Leave if sniff not open */
+	if (!(ch->ch_sniff_flags & SNIFF_OPEN))
+		return;
+
+	do_gettimeofday(&tv);
+
+	/* Create our header for data dump */
+	p += sprintf(p, "<%ld %ld><%s><", tv.tv_sec, tv.tv_usec, text);
+	tmpbuflen = p - tmpbuf;
+
+	do {
+		too_much_data = 0;
+
+		for (i = 0; i < len && tmpbuflen < (TMPBUFLEN - 4); i++) {
+			p += sprintf(p, "%02x ", *buf);
+			buf++;
+			tmpbuflen = p - tmpbuf;
+		}
+
+		if (tmpbuflen < (TMPBUFLEN - 4)) {
+			if (i > 0)
+				p += sprintf(p - 1, "%s\n", ">");
+			else
+				p += sprintf(p, "%s\n", ">");
+		} else {
+			too_much_data = 1;
+			len -= i;
+		}
+
+		nbuf = strlen(tmpbuf);
+		p = tmpbuf;
+
+		/*
+		 *  Loop while data remains.
+		 */
+		while (nbuf > 0 && ch->ch_sniff_buf) {
+			/*
+			 *  Determine the amount of available space left in the
+			 *  buffer.  If there's none, wait until some appears.
+			 */
+			n = (ch->ch_sniff_out - ch->ch_sniff_in - 1) & SNIFF_MASK;
+
+			/*
+			 * If there is no space left to write to in our sniff buffer,
+			 * we have no choice but to drop the data.
+			 * We *cannot* sleep here waiting for space, because this
+			 * function was probably called by the interrupt/timer routines!
+			 */
+			if (n == 0)
+				return;
+
+			/*
+			 * Copy as much data as will fit.
+			 */
+
+			if (n > nbuf)
+				n = nbuf;
+
+			r = SNIFF_MAX - ch->ch_sniff_in;
+
+			if (r <= n) {
+				memcpy(ch->ch_sniff_buf + ch->ch_sniff_in, p, r);
+
+				n -= r;
+				ch->ch_sniff_in = 0;
+				p += r;
+				nbuf -= r;
+			}
+
+			memcpy(ch->ch_sniff_buf + ch->ch_sniff_in, p, n);
+
+			ch->ch_sniff_in += n;
+			p += n;
+			nbuf -= n;
+
+			/*
+			 *  Wakeup any thread waiting for data
+			 */
+			if (ch->ch_sniff_flags & SNIFF_WAIT_DATA) {
+				ch->ch_sniff_flags &= ~SNIFF_WAIT_DATA;
+				wake_up_interruptible(&ch->ch_sniff_wait);
+			}
+		}
+
+		/*
+		 * If the user sent us too much data to push into our tmpbuf,
+		 * we need to keep looping around on all the data.
+		 */
+		if (too_much_data) {
+			p = tmpbuf;
+			tmpbuflen = 0;
+		}
+
+	} while (too_much_data);
+}
+
+/*=======================================================================
+ *
+ *      dgap_input - Process received data.
+ *
+ *              ch      - Pointer to channel structure.
+ *
+ *=======================================================================*/
+
+static void dgap_input(struct channel_t *ch)
+{
+	struct board_t *bd;
+	struct bs_t	*bs;
+	struct tty_struct *tp;
+	struct tty_ldisc *ld;
+	uint	rmask;
+	uint	head;
+	uint	tail;
+	int	data_len;
+	ulong	lock_flags;
+	ulong   lock_flags2;
+	int flip_len;
+	int len = 0;
+	int n = 0;
+	uchar *buf;
+	uchar tmpchar;
+	int s = 0;
+
+	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+		return;
+
+	tp = ch->ch_tun.un_tty;
+
+	bs  = ch->ch_bs;
+	if (!bs)
+		return;
+
+	bd = ch->ch_bd;
+	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
+		return;
+
+	DGAP_LOCK(bd->bd_lock, lock_flags);
+	DGAP_LOCK(ch->ch_lock, lock_flags2);
+
+	/*
+	 *      Figure the number of characters in the buffer.
+	 *      Exit immediately if none.
+	 */
+
+	rmask = ch->ch_rsize - 1;
+
+	head = readw(&(bs->rx_head));
+	head &= rmask;
+	tail = readw(&(bs->rx_tail));
+	tail &= rmask;
+
+	data_len = (head - tail) & rmask;
+
+	if (data_len == 0) {
+		writeb(1, &(bs->idata));
+		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+		DGAP_UNLOCK(bd->bd_lock, lock_flags);
+		return;
+	}
+
+	/*
+	 * If the device is not open, or CREAD is off, flush
+	 * input data and return immediately.
+	 */
+	if ((bd->state != BOARD_READY) || !tp  ||
+	    (tp->magic != TTY_MAGIC) ||
+	    !(ch->ch_tun.un_flags & UN_ISOPEN) ||
+	    !(tp->termios.c_cflag & CREAD) ||
+	    (ch->ch_tun.un_flags & UN_CLOSING)) {
+
+		writew(head, &(bs->rx_tail));
+		writeb(1, &(bs->idata));
+		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+		DGAP_UNLOCK(bd->bd_lock, lock_flags);
+		return;
+	}
+
+	/*
+	 * If we are throttled, simply don't read any data.
+	 */
+	if (ch->ch_flags & CH_RXBLOCK) {
+		writeb(1, &(bs->idata));
+		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+		DGAP_UNLOCK(bd->bd_lock, lock_flags);
+		return;
+	}
+
+	/*
+	 *      Ignore oruns.
+	 */
+	tmpchar = readb(&(bs->orun));
+	if (tmpchar) {
+		ch->ch_err_overrun++;
+		writeb(0, &(bs->orun));
+	}
+
+	/* Decide how much data we can send into the tty layer */
+	flip_len = TTY_FLIPBUF_SIZE;
+
+	/* Chop down the length, if needed */
+	len = min(data_len, flip_len);
+	len = min(len, (N_TTY_BUF_SIZE - 1));
+
+	ld = tty_ldisc_ref(tp);
+
+#ifdef TTY_DONT_FLIP
+	/*
+	 * If the DONT_FLIP flag is on, don't flush our buffer, and act
+	 * like the ld doesn't have any space to put the data right now.
+	 */
+	if (test_bit(TTY_DONT_FLIP, &tp->flags))
+		len = 0;
+#endif
+
+	/*
+	 * If we were unable to get a reference to the ld,
+	 * don't flush our buffer, and act like the ld doesn't
+	 * have any space to put the data right now.
+	 */
+	if (!ld) {
+		len = 0;
+	} else {
+		/*
+		 * If ld doesn't have a pointer to a receive_buf function,
+		 * flush the data, then act like the ld doesn't have any
+		 * space to put the data right now.
+		 */
+		if (!ld->ops->receive_buf) {
+			writew(head, &(bs->rx_tail));
+			len = 0;
+		}
+	}
+
+	if (len <= 0) {
+		writeb(1, &(bs->idata));
+		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+		DGAP_UNLOCK(bd->bd_lock, lock_flags);
+		if (ld)
+			tty_ldisc_deref(ld);
+		return;
+	}
+
+	buf = ch->ch_bd->flipbuf;
+	n = len;
+
+	/*
+	 * n now contains the most amount of data we can copy,
+	 * bounded either by our buffer size or the amount
+	 * of data the card actually has pending...
+	 */
+	while (n) {
+
+		s = ((head >= tail) ? head : ch->ch_rsize) - tail;
+		s = min(s, n);
+
+		if (s <= 0)
+			break;
+
+		memcpy_fromio(buf, (char *) ch->ch_raddr + tail, s);
+		dgap_sniff_nowait_nolock(ch, "USER READ", buf, s);
+
+		tail += s;
+		buf += s;
+
+		n -= s;
+		/* Flip queue if needed */
+		tail &= rmask;
+	}
+
+	writew(tail, &(bs->rx_tail));
+	writeb(1, &(bs->idata));
+	ch->ch_rxcount += len;
+
+	/*
+	 * If we are completely raw, we don't need to go through a lot
+	 * of the tty layers that exist.
+	 * In this case, we take the shortest and fastest route we
+	 * can to relay the data to the user.
+	 *
+	 * On the other hand, if we are not raw, we need to go through
+	 * the tty layer, which has its API more well defined.
+	 */
+	if (I_PARMRK(tp) || I_BRKINT(tp) || I_INPCK(tp)) {
+		dgap_parity_scan(ch, ch->ch_bd->flipbuf, ch->ch_bd->flipflagbuf, &len);
+
+		len = tty_buffer_request_room(tp->port, len);
+		tty_insert_flip_string_flags(tp->port, ch->ch_bd->flipbuf,
+			ch->ch_bd->flipflagbuf, len);
+	} else {
+		len = tty_buffer_request_room(tp->port, len);
+		tty_insert_flip_string(tp->port, ch->ch_bd->flipbuf, len);
+	}
+
+	DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+	DGAP_UNLOCK(bd->bd_lock, lock_flags);
+
+	/* Tell the tty layer its okay to "eat" the data now */
+	tty_flip_buffer_push(tp->port);
+
+	if (ld)
+		tty_ldisc_deref(ld);
+
+}
+
+/************************************************************************
+ * Determines when CARRIER changes state and takes appropriate
+ * action.
+ ************************************************************************/
+static void dgap_carrier(struct channel_t *ch)
+{
+	struct board_t *bd;
+
+	int virt_carrier = 0;
+	int phys_carrier = 0;
+
+	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+		return;
+
+	bd = ch->ch_bd;
+
+	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
+		return;
+
+	/* Make sure altpin is always set correctly */
+	if (ch->ch_digi.digi_flags & DIGI_ALTPIN) {
+		ch->ch_dsr      = DM_CD;
+		ch->ch_cd       = DM_DSR;
+	} else {
+		ch->ch_dsr      = DM_DSR;
+		ch->ch_cd       = DM_CD;
+	}
+
+	if (ch->ch_mistat & D_CD(ch))
+		phys_carrier = 1;
+
+	if (ch->ch_digi.digi_flags & DIGI_FORCEDCD)
+		virt_carrier = 1;
+
+	if (ch->ch_c_cflag & CLOCAL)
+		virt_carrier = 1;
+
+	/*
+	 * Test for a VIRTUAL carrier transition to HIGH.
+	 */
+	if (((ch->ch_flags & CH_FCAR) == 0) && (virt_carrier == 1)) {
+
+		/*
+		 * When carrier rises, wake any threads waiting
+		 * for carrier in the open routine.
+		 */
+
+		if (waitqueue_active(&(ch->ch_flags_wait)))
+			wake_up_interruptible(&ch->ch_flags_wait);
+	}
+
+	/*
+	 * Test for a PHYSICAL carrier transition to HIGH.
+	 */
+	if (((ch->ch_flags & CH_CD) == 0) && (phys_carrier == 1)) {
+
+		/*
+		 * When carrier rises, wake any threads waiting
+		 * for carrier in the open routine.
+		 */
+
+		if (waitqueue_active(&(ch->ch_flags_wait)))
+			wake_up_interruptible(&ch->ch_flags_wait);
+	}
+
+	/*
+	 *  Test for a PHYSICAL transition to low, so long as we aren't
+	 *  currently ignoring physical transitions (which is what "virtual
+	 *  carrier" indicates).
+	 *
+	 *  The transition of the virtual carrier to low really doesn't
+	 *  matter... it really only means "ignore carrier state", not
+	 *  "make pretend that carrier is there".
+	 */
+	if ((virt_carrier == 0) &&
+	    ((ch->ch_flags & CH_CD) != 0) &&
+	    (phys_carrier == 0)) {
+
+		/*
+		 *   When carrier drops:
+		 *
+		 *   Drop carrier on all open units.
+		 *
+		 *   Flush queues, waking up any task waiting in the
+		 *   line discipline.
+		 *
+		 *   Send a hangup to the control terminal.
+		 *
+		 *   Enable all select calls.
+		 */
+		if (waitqueue_active(&(ch->ch_flags_wait)))
+			wake_up_interruptible(&ch->ch_flags_wait);
+
+		if (ch->ch_tun.un_open_count > 0)
+			tty_hangup(ch->ch_tun.un_tty);
+
+		if (ch->ch_pun.un_open_count > 0)
+			tty_hangup(ch->ch_pun.un_tty);
+	}
+
+	/*
+	 *  Make sure that our cached values reflect the current reality.
+	 */
+	if (virt_carrier == 1)
+		ch->ch_flags |= CH_FCAR;
+	else
+		ch->ch_flags &= ~CH_FCAR;
+
+	if (phys_carrier == 1)
+		ch->ch_flags |= CH_CD;
+	else
+		ch->ch_flags &= ~CH_CD;
+}
+
+/************************************************************************
+ *
+ * TTY Entry points and helper functions
+ *
+ ************************************************************************/
+
+/*
+ * dgap_tty_open()
+ *
+ */
+static int dgap_tty_open(struct tty_struct *tty, struct file *file)
+{
+	struct board_t	*brd;
+	struct channel_t *ch;
+	struct un_t	*un;
+	struct bs_t	*bs;
+	uint		major = 0;
+	uint		minor = 0;
+	int		rc = 0;
+	ulong		lock_flags;
+	ulong		lock_flags2;
+	u16		head;
+
+	rc = 0;
+
+	major = MAJOR(tty_devnum(tty));
+	minor = MINOR(tty_devnum(tty));
+
+	if (major > 255)
+		return -ENXIO;
+
+	/* Get board pointer from our array of majors we have allocated */
+	brd = dgap_BoardsByMajor[major];
+	if (!brd)
+		return -ENXIO;
+
+	/*
+	 * If board is not yet up to a state of READY, go to
+	 * sleep waiting for it to happen or they cancel the open.
+	 */
+	rc = wait_event_interruptible(brd->state_wait,
+		(brd->state & BOARD_READY));
+
+	if (rc)
+		return rc;
+
+	DGAP_LOCK(brd->bd_lock, lock_flags);
+
+	/* The wait above should guarantee this cannot happen */
+	if (brd->state != BOARD_READY) {
+		DGAP_UNLOCK(brd->bd_lock, lock_flags);
+		return -ENXIO;
+	}
+
+	/* If opened device is greater than our number of ports, bail. */
+	if (MINOR(tty_devnum(tty)) > brd->nasync) {
+		DGAP_UNLOCK(brd->bd_lock, lock_flags);
+		return -ENXIO;
+	}
+
+	ch = brd->channels[minor];
+	if (!ch) {
+		DGAP_UNLOCK(brd->bd_lock, lock_flags);
+		return -ENXIO;
+	}
+
+	/* Grab channel lock */
+	DGAP_LOCK(ch->ch_lock, lock_flags2);
+
+	/* Figure out our type */
+	if (major == brd->dgap_Serial_Major) {
+		un = &brd->channels[minor]->ch_tun;
+		un->un_type = DGAP_SERIAL;
+	} else if (major == brd->dgap_TransparentPrint_Major) {
+		un = &brd->channels[minor]->ch_pun;
+		un->un_type = DGAP_PRINT;
+	} else {
+		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+		DGAP_UNLOCK(brd->bd_lock, lock_flags);
+		return -ENXIO;
+	}
+
+	/* Store our unit into driver_data, so we always have it available. */
+	tty->driver_data = un;
+
+	/*
+	 * Error if channel info pointer is NULL.
+	 */
+	bs = ch->ch_bs;
+	if (!bs) {
+		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+		DGAP_UNLOCK(brd->bd_lock, lock_flags);
+		return -ENXIO;
+	}
+
+	/*
+	 * Initialize tty's
+	 */
+	if (!(un->un_flags & UN_ISOPEN)) {
+		/* Store important variables. */
+		un->un_tty     = tty;
+
+		/* Maybe do something here to the TTY struct as well? */
+	}
+
+	/*
+	 * Initialize if neither terminal or printer is open.
+	 */
+	if (!((ch->ch_tun.un_flags | ch->ch_pun.un_flags) & UN_ISOPEN)) {
+
+		ch->ch_mforce = 0;
+		ch->ch_mval = 0;
+
+		/*
+		 * Flush input queue.
+		 */
+		head = readw(&(bs->rx_head));
+		writew(head, &(bs->rx_tail));
+
+		ch->ch_flags = 0;
+		ch->pscan_state = 0;
+		ch->pscan_savechar = 0;
+
+		ch->ch_c_cflag   = tty->termios.c_cflag;
+		ch->ch_c_iflag   = tty->termios.c_iflag;
+		ch->ch_c_oflag   = tty->termios.c_oflag;
+		ch->ch_c_lflag   = tty->termios.c_lflag;
+		ch->ch_startc = tty->termios.c_cc[VSTART];
+		ch->ch_stopc  = tty->termios.c_cc[VSTOP];
+
+		/* TODO: flush our TTY struct here? */
+	}
+
+	dgap_carrier(ch);
+	/*
+	 * Run param in case we changed anything
+	 */
+	dgap_param(tty);
+
+	/*
+	 * follow protocol for opening port
+	 */
+
+	DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+	DGAP_UNLOCK(brd->bd_lock, lock_flags);
+
+	rc = dgap_block_til_ready(tty, file, ch);
+
+	if (!un->un_tty)
+		return -ENODEV;
+
+	/* No going back now, increment our unit and channel counters */
+	DGAP_LOCK(ch->ch_lock, lock_flags);
+	ch->ch_open_count++;
+	un->un_open_count++;
+	un->un_flags |= (UN_ISOPEN);
+	DGAP_UNLOCK(ch->ch_lock, lock_flags);
+
+	return rc;
+}
+
+/*
+ * dgap_block_til_ready()
+ *
+ * Wait for DCD, if needed.
+ */
+static int dgap_block_til_ready(struct tty_struct *tty, struct file *file, struct channel_t *ch)
+{
+	int retval = 0;
+	struct un_t *un = NULL;
+	ulong   lock_flags;
+	uint	old_flags = 0;
+	int sleep_on_un_flags = 0;
+
+	if (!tty || tty->magic != TTY_MAGIC || !file || !ch ||
+		ch->magic != DGAP_CHANNEL_MAGIC)
+		return -ENXIO;
+
+	un = tty->driver_data;
+	if (!un || un->magic != DGAP_UNIT_MAGIC)
+		return -ENXIO;
+
+	DGAP_LOCK(ch->ch_lock, lock_flags);
+
+	ch->ch_wopen++;
+
+	/* Loop forever */
+	while (1) {
+
+		sleep_on_un_flags = 0;
+
+		/*
+		 * If board has failed somehow during our sleep, bail with error.
+		 */
+		if (ch->ch_bd->state == BOARD_FAILED) {
+			retval = -ENXIO;
+			break;
+		}
+
+		/* If tty was hung up, break out of loop and set error. */
+		if (tty_hung_up_p(file)) {
+			retval = -EAGAIN;
+			break;
+		}
+
+		/*
+		 * If either unit is in the middle of the fragile part of close,
+		 * we just cannot touch the channel safely.
+		 * Go back to sleep, knowing that when the channel can be
+		 * touched safely, the close routine will signal the
+		 * ch_wait_flags to wake us back up.
+		 */
+		if (!((ch->ch_tun.un_flags | ch->ch_pun.un_flags) & UN_CLOSING)) {
+
+			/*
+			 * Our conditions to leave cleanly and happily:
+			 * 1) NONBLOCKING on the tty is set.
+			 * 2) CLOCAL is set.
+			 * 3) DCD (fake or real) is active.
+			 */
+
+			if (file->f_flags & O_NONBLOCK)
+				break;
+
+			if (tty->flags & (1 << TTY_IO_ERROR))
+				break;
+
+			if (ch->ch_flags & CH_CD)
+				break;
+
+			if (ch->ch_flags & CH_FCAR)
+				break;
+		} else {
+			sleep_on_un_flags = 1;
+		}
+
+		/*
+		 * If there is a signal pending, the user probably
+		 * interrupted (ctrl-c) us.
+		 * Leave loop with error set.
+		 */
+		if (signal_pending(current)) {
+			retval = -ERESTARTSYS;
+			break;
+		}
+
+		/*
+		 * Store the flags before we let go of channel lock
+		 */
+		if (sleep_on_un_flags)
+			old_flags = ch->ch_tun.un_flags | ch->ch_pun.un_flags;
+		else
+			old_flags = ch->ch_flags;
+
+		/*
+		 * Let go of channel lock before calling schedule.
+		 * Our poller will get any FEP events and wake us up when DCD
+		 * eventually goes active.
+		 */
+
+		DGAP_UNLOCK(ch->ch_lock, lock_flags);
+
+		/*
+		 * Wait for something in the flags to change from the current value.
+		 */
+		if (sleep_on_un_flags) {
+			retval = wait_event_interruptible(un->un_flags_wait,
+				(old_flags != (ch->ch_tun.un_flags | ch->ch_pun.un_flags)));
+		} else {
+			retval = wait_event_interruptible(ch->ch_flags_wait,
+				(old_flags != ch->ch_flags));
+		}
+
+		/*
+		 * We got woken up for some reason.
+		 * Before looping around, grab our channel lock.
+		 */
+		DGAP_LOCK(ch->ch_lock, lock_flags);
+	}
+
+	ch->ch_wopen--;
+
+	DGAP_UNLOCK(ch->ch_lock, lock_flags);
+
+	if (retval)
+		return retval;
+
+	return 0;
+}
+
+/*
+ * dgap_tty_hangup()
+ *
+ * Hangup the port.  Like a close, but don't wait for output to drain.
+ */
+static void dgap_tty_hangup(struct tty_struct *tty)
+{
+	struct board_t	*bd;
+	struct channel_t *ch;
+	struct un_t	*un;
+
+	if (!tty || tty->magic != TTY_MAGIC)
+		return;
+
+	un = tty->driver_data;
+	if (!un || un->magic != DGAP_UNIT_MAGIC)
+		return;
+
+	ch = un->un_ch;
+	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+		return;
+
+	bd = ch->ch_bd;
+	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
+		return;
+
+	/* flush the transmit queues */
+	dgap_tty_flush_buffer(tty);
+
+}
+
+/*
+ * dgap_tty_close()
+ *
+ */
+static void dgap_tty_close(struct tty_struct *tty, struct file *file)
+{
+	struct ktermios *ts;
+	struct board_t *bd;
+	struct channel_t *ch;
+	struct un_t *un;
+	ulong lock_flags;
+	int rc = 0;
+
+	if (!tty || tty->magic != TTY_MAGIC)
+		return;
+
+	un = tty->driver_data;
+	if (!un || un->magic != DGAP_UNIT_MAGIC)
+		return;
+
+	ch = un->un_ch;
+	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+		return;
+
+	bd = ch->ch_bd;
+	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
+		return;
+
+	ts = &tty->termios;
+
+	DGAP_LOCK(ch->ch_lock, lock_flags);
+
+	/*
+	 * Determine if this is the last close or not - and if we agree about
+	 * which type of close it is with the Line Discipline
+	 */
+	if ((tty->count == 1) && (un->un_open_count != 1))
+		/*
+		 * Uh, oh.  tty->count is 1, which means that the tty
+		 * structure will be freed.  un_open_count should always
+		 * be one in these conditions.  If it's greater than
+		 * one, we've got real problems, since it means the
+		 * serial port won't be shutdown.
+		 */
+		un->un_open_count = 1;
+
+	if (--un->un_open_count < 0)
+		un->un_open_count = 0;
+
+	ch->ch_open_count--;
+
+	if (ch->ch_open_count && un->un_open_count) {
+		DGAP_UNLOCK(ch->ch_lock, lock_flags);
+		return;
+	}
+
+	/* OK, its the last close on the unit */
+
+	un->un_flags |= UN_CLOSING;
+
+	tty->closing = 1;
+
+	/*
+	 * Only officially close channel if count is 0 and
+	 * DIGI_PRINTER bit is not set.
+	 */
+	if ((ch->ch_open_count == 0) && !(ch->ch_digi.digi_flags & DIGI_PRINTER)) {
+
+		ch->ch_flags &= ~(CH_RXBLOCK);
+
+		DGAP_UNLOCK(ch->ch_lock, lock_flags);
+
+		/* wait for output to drain */
+		/* This will also return if we take an interrupt */
+
+		rc = dgap_wait_for_drain(tty);
+
+		dgap_tty_flush_buffer(tty);
+		tty_ldisc_flush(tty);
+
+		DGAP_LOCK(ch->ch_lock, lock_flags);
+
+		tty->closing = 0;
+
+		/*
+		 * If we have HUPCL set, lower DTR and RTS
+		 */
+		if (ch->ch_c_cflag & HUPCL) {
+			ch->ch_mostat &= ~(D_RTS(ch)|D_DTR(ch));
+			dgap_cmdb(ch, SMODEM, 0, D_DTR(ch)|D_RTS(ch), 0);
+
+			/*
+			 * Go to sleep to ensure RTS/DTR
+			 * have been dropped for modems to see it.
+			 */
+			if (ch->ch_close_delay) {
+				DGAP_UNLOCK(ch->ch_lock, lock_flags);
+				dgap_ms_sleep(ch->ch_close_delay);
+				DGAP_LOCK(ch->ch_lock, lock_flags);
+			}
+		}
+
+		ch->pscan_state = 0;
+		ch->pscan_savechar = 0;
+		ch->ch_baud_info = 0;
+
+	}
+
+	/*
+	 * turn off print device when closing print device.
+	 */
+	if ((un->un_type == DGAP_PRINT)  && (ch->ch_flags & CH_PRON)) {
+		dgap_wmove(ch, ch->ch_digi.digi_offstr,
+			(int) ch->ch_digi.digi_offlen);
+		ch->ch_flags &= ~CH_PRON;
+	}
+
+	un->un_tty = NULL;
+	un->un_flags &= ~(UN_ISOPEN | UN_CLOSING);
+	tty->driver_data = NULL;
+
+	wake_up_interruptible(&ch->ch_flags_wait);
+	wake_up_interruptible(&un->un_flags_wait);
+
+	DGAP_UNLOCK(ch->ch_lock, lock_flags);
+}
+
+/*
+ * dgap_tty_chars_in_buffer()
+ *
+ * Return number of characters that have not been transmitted yet.
+ *
+ * This routine is used by the line discipline to determine if there
+ * is data waiting to be transmitted/drained/flushed or not.
+ */
+static int dgap_tty_chars_in_buffer(struct tty_struct *tty)
+{
+	struct board_t *bd = NULL;
+	struct channel_t *ch = NULL;
+	struct un_t *un = NULL;
+	struct bs_t *bs = NULL;
+	uchar tbusy;
+	uint chars = 0;
+	u16 thead, ttail, tmask, chead, ctail;
+	ulong   lock_flags = 0;
+	ulong   lock_flags2 = 0;
+
+	if (tty == NULL)
+		return 0;
+
+	un = tty->driver_data;
+	if (!un || un->magic != DGAP_UNIT_MAGIC)
+		return 0;
+
+	ch = un->un_ch;
+	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+		return 0;
+
+	bd = ch->ch_bd;
+	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
+		return 0;
+
+	bs = ch->ch_bs;
+	if (!bs)
+		return 0;
+
+	DGAP_LOCK(bd->bd_lock, lock_flags);
+	DGAP_LOCK(ch->ch_lock, lock_flags2);
+
+	tmask = (ch->ch_tsize - 1);
+
+	/* Get Transmit queue pointers */
+	thead = readw(&(bs->tx_head)) & tmask;
+	ttail = readw(&(bs->tx_tail)) & tmask;
+
+	/* Get tbusy flag */
+	tbusy = readb(&(bs->tbusy));
+
+	/* Get Command queue pointers */
+	chead = readw(&(ch->ch_cm->cm_head));
+	ctail = readw(&(ch->ch_cm->cm_tail));
+
+	DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+	DGAP_UNLOCK(bd->bd_lock, lock_flags);
+
+	/*
+	 * The only way we know for sure if there is no pending
+	 * data left to be transferred, is if:
+	 * 1) Transmit head and tail are equal (empty).
+	 * 2) Command queue head and tail are equal (empty).
+	 * 3) The "TBUSY" flag is 0. (Transmitter not busy).
+	 */
+
+	if ((ttail == thead) && (tbusy == 0) && (chead == ctail)) {
+		chars = 0;
+	} else {
+		if (thead >= ttail)
+			chars = thead - ttail;
+		else
+			chars = thead - ttail + ch->ch_tsize;
+		/*
+		 * Fudge factor here.
+		 * If chars is zero, we know that the command queue had
+		 * something in it or tbusy was set.  Because we cannot
+		 * be sure if there is still some data to be transmitted,
+		 * lets lie, and tell ld we have 1 byte left.
+		 */
+		if (chars == 0) {
+			/*
+			 * If TBUSY is still set, and our tx buffers are empty,
+			 * force the firmware to send me another wakeup after
+			 * TBUSY has been cleared.
+			 */
+			if (tbusy != 0) {
+				DGAP_LOCK(ch->ch_lock, lock_flags);
+				un->un_flags |= UN_EMPTY;
+				writeb(1, &(bs->iempty));
+				DGAP_UNLOCK(ch->ch_lock, lock_flags);
+			}
+			chars = 1;
+		}
+	}
+
+	return chars;
+}
+
+static int dgap_wait_for_drain(struct tty_struct *tty)
+{
+	struct channel_t *ch;
+	struct un_t *un;
+	struct bs_t *bs;
+	int ret = -EIO;
+	uint count = 1;
+	ulong   lock_flags = 0;
+
+	if (!tty || tty->magic != TTY_MAGIC)
+		return ret;
+
+	un = tty->driver_data;
+	if (!un || un->magic != DGAP_UNIT_MAGIC)
+		return ret;
+
+	ch = un->un_ch;
+	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+		return ret;
+
+	bs = ch->ch_bs;
+	if (!bs)
+		return ret;
+
+	ret = 0;
+
+	/* Loop until data is drained */
+	while (count != 0) {
+
+		count = dgap_tty_chars_in_buffer(tty);
+
+		if (count == 0)
+			break;
+
+		/* Set flag waiting for drain */
+		DGAP_LOCK(ch->ch_lock, lock_flags);
+		un->un_flags |= UN_EMPTY;
+		writeb(1, &(bs->iempty));
+		DGAP_UNLOCK(ch->ch_lock, lock_flags);
+
+		/* Go to sleep till we get woken up */
+		ret = wait_event_interruptible(un->un_flags_wait, ((un->un_flags & UN_EMPTY) == 0));
+		/* If ret is non-zero, user ctrl-c'ed us */
+		if (ret)
+			break;
+	}
+
+	DGAP_LOCK(ch->ch_lock, lock_flags);
+	un->un_flags &= ~(UN_EMPTY);
+	DGAP_UNLOCK(ch->ch_lock, lock_flags);
+
+	return ret;
+}
+
+/*
+ * dgap_maxcps_room
+ *
+ * Reduces bytes_available to the max number of characters
+ * that can be sent currently given the maxcps value, and
+ * returns the new bytes_available.  This only affects printer
+ * output.
+ */
+static int dgap_maxcps_room(struct tty_struct *tty, int bytes_available)
+{
+	struct channel_t *ch = NULL;
+	struct un_t *un = NULL;
+
+	if (tty == NULL)
+		return bytes_available;
+
+	un = tty->driver_data;
+	if (!un || un->magic != DGAP_UNIT_MAGIC)
+		return bytes_available;
+
+	ch = un->un_ch;
+	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+		return bytes_available;
+
+	/*
+	 * If its not the Transparent print device, return
+	 * the full data amount.
+	 */
+	if (un->un_type != DGAP_PRINT)
+		return bytes_available;
+
+	if (ch->ch_digi.digi_maxcps > 0 && ch->ch_digi.digi_bufsize > 0) {
+		int cps_limit = 0;
+		unsigned long current_time = jiffies;
+		unsigned long buffer_time = current_time +
+			(HZ * ch->ch_digi.digi_bufsize) / ch->ch_digi.digi_maxcps;
+
+		if (ch->ch_cpstime < current_time) {
+			/* buffer is empty */
+			ch->ch_cpstime = current_time;            /* reset ch_cpstime */
+			cps_limit = ch->ch_digi.digi_bufsize;
+		} else if (ch->ch_cpstime < buffer_time) {
+			/* still room in the buffer */
+			cps_limit = ((buffer_time - ch->ch_cpstime) * ch->ch_digi.digi_maxcps) / HZ;
+		} else {
+			/* no room in the buffer */
+			cps_limit = 0;
+		}
+
+		bytes_available = min(cps_limit, bytes_available);
+	}
+
+	return bytes_available;
+}
+
+static inline void dgap_set_firmware_event(struct un_t *un, unsigned int event)
+{
+	struct channel_t *ch = NULL;
+	struct bs_t *bs = NULL;
+
+	if (!un || un->magic != DGAP_UNIT_MAGIC)
+		return;
+	ch = un->un_ch;
+	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+		return;
+	bs = ch->ch_bs;
+	if (!bs)
+		return;
+
+	if ((event & UN_LOW) != 0) {
+		if ((un->un_flags & UN_LOW) == 0) {
+			un->un_flags |= UN_LOW;
+			writeb(1, &(bs->ilow));
+		}
+	}
+	if ((event & UN_LOW) != 0) {
+		if ((un->un_flags & UN_EMPTY) == 0) {
+			un->un_flags |= UN_EMPTY;
+			writeb(1, &(bs->iempty));
+		}
+	}
+}
+
+/*
+ * dgap_tty_write_room()
+ *
+ * Return space available in Tx buffer
+ */
+static int dgap_tty_write_room(struct tty_struct *tty)
+{
+	struct channel_t *ch = NULL;
+	struct un_t *un = NULL;
+	struct bs_t *bs = NULL;
+	u16 head, tail, tmask;
+	int ret = 0;
+	ulong   lock_flags = 0;
+
+	if (tty == NULL || dgap_TmpWriteBuf == NULL)
+		return 0;
+
+	un = tty->driver_data;
+	if (!un || un->magic != DGAP_UNIT_MAGIC)
+		return 0;
+
+	ch = un->un_ch;
+	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+		return 0;
+
+	bs = ch->ch_bs;
+	if (!bs)
+		return 0;
+
+	DGAP_LOCK(ch->ch_lock, lock_flags);
+
+	tmask = ch->ch_tsize - 1;
+	head = readw(&(bs->tx_head)) & tmask;
+	tail = readw(&(bs->tx_tail)) & tmask;
+
+	ret = tail - head - 1;
+	if (ret < 0)
+		ret += ch->ch_tsize;
+
+	/* Limit printer to maxcps */
+	ret = dgap_maxcps_room(tty, ret);
+
+	/*
+	 * If we are printer device, leave space for
+	 * possibly both the on and off strings.
+	 */
+	if (un->un_type == DGAP_PRINT) {
+		if (!(ch->ch_flags & CH_PRON))
+			ret -= ch->ch_digi.digi_onlen;
+		ret -= ch->ch_digi.digi_offlen;
+	} else {
+		if (ch->ch_flags & CH_PRON)
+			ret -= ch->ch_digi.digi_offlen;
+	}
+
+	if (ret < 0)
+		ret = 0;
+
+	/*
+	 * Schedule FEP to wake us up if needed.
+	 *
+	 * TODO:  This might be overkill...
+	 * Do we really need to schedule callbacks from the FEP
+	 * in every case?  Can we get smarter based on ret?
+	 */
+	dgap_set_firmware_event(un, UN_LOW | UN_EMPTY);
+	DGAP_UNLOCK(ch->ch_lock, lock_flags);
+
+	return ret;
+}
+
+/*
+ * dgap_tty_put_char()
+ *
+ * Put a character into ch->ch_buf
+ *
+ *      - used by the line discipline for OPOST processing
+ */
+static int dgap_tty_put_char(struct tty_struct *tty, unsigned char c)
+{
+	/*
+	 * Simply call tty_write.
+	 */
+	dgap_tty_write(tty, &c, 1);
+	return 1;
+}
+
+/*
+ * dgap_tty_write()
+ *
+ * Take data from the user or kernel and send it out to the FEP.
+ * In here exists all the Transparent Print magic as well.
+ */
+static int dgap_tty_write(struct tty_struct *tty, const unsigned char *buf, int count)
+{
+	struct channel_t *ch = NULL;
+	struct un_t *un = NULL;
+	struct bs_t *bs = NULL;
+	char *vaddr = NULL;
+	u16 head, tail, tmask, remain;
+	int bufcount = 0, n = 0;
+	int orig_count = 0;
+	ulong lock_flags;
+	int from_user = 0;
+
+	if (tty == NULL || dgap_TmpWriteBuf == NULL)
+		return 0;
+
+	un = tty->driver_data;
+	if (!un || un->magic != DGAP_UNIT_MAGIC)
+		return 0;
+
+	ch = un->un_ch;
+	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+		return 0;
+
+	bs = ch->ch_bs;
+	if (!bs)
+		return 0;
+
+	if (!count)
+		return 0;
+
+	/*
+	 * Store original amount of characters passed in.
+	 * This helps to figure out if we should ask the FEP
+	 * to send us an event when it has more space available.
+	 */
+	orig_count = count;
+
+	DGAP_LOCK(ch->ch_lock, lock_flags);
+
+	/* Get our space available for the channel from the board */
+	tmask = ch->ch_tsize - 1;
+	head = readw(&(bs->tx_head)) & tmask;
+	tail = readw(&(bs->tx_tail)) & tmask;
+
+	bufcount = tail - head - 1;
+	if (bufcount < 0)
+		bufcount += ch->ch_tsize;
+
+	/*
+	 * Limit printer output to maxcps overall, with bursts allowed
+	 * up to bufsize characters.
+	 */
+	bufcount = dgap_maxcps_room(tty, bufcount);
+
+	/*
+	 * Take minimum of what the user wants to send, and the
+	 * space available in the FEP buffer.
+	 */
+	count = min(count, bufcount);
+
+	/*
+	 * Bail if no space left.
+	 */
+	if (count <= 0) {
+		dgap_set_firmware_event(un, UN_LOW | UN_EMPTY);
+		DGAP_UNLOCK(ch->ch_lock, lock_flags);
+		return 0;
+	}
+
+	/*
+	 * Output the printer ON string, if we are in terminal mode, but
+	 * need to be in printer mode.
+	 */
+	if ((un->un_type == DGAP_PRINT) && !(ch->ch_flags & CH_PRON)) {
+		dgap_wmove(ch, ch->ch_digi.digi_onstr,
+		    (int) ch->ch_digi.digi_onlen);
+		head = readw(&(bs->tx_head)) & tmask;
+		ch->ch_flags |= CH_PRON;
+	}
+
+	/*
+	 * On the other hand, output the printer OFF string, if we are
+	 * currently in printer mode, but need to output to the terminal.
+	 */
+	if ((un->un_type != DGAP_PRINT) && (ch->ch_flags & CH_PRON)) {
+		dgap_wmove(ch, ch->ch_digi.digi_offstr,
+			(int) ch->ch_digi.digi_offlen);
+		head = readw(&(bs->tx_head)) & tmask;
+		ch->ch_flags &= ~CH_PRON;
+	}
+
+	/*
+	 * If there is nothing left to copy, or I can't handle any more data, leave.
+	 */
+	if (count <= 0) {
+		dgap_set_firmware_event(un, UN_LOW | UN_EMPTY);
+		DGAP_UNLOCK(ch->ch_lock, lock_flags);
+		return 0;
+	}
+
+	if (from_user) {
+
+		count = min(count, WRITEBUFLEN);
+
+		DGAP_UNLOCK(ch->ch_lock, lock_flags);
+
+		/*
+		 * If data is coming from user space, copy it into a temporary
+		 * buffer so we don't get swapped out while doing the copy to
+		 * the board.
+		 */
+		/* we're allowed to block if it's from_user */
+		if (down_interruptible(&dgap_TmpWriteSem))
+			return -EINTR;
+
+		if (copy_from_user(dgap_TmpWriteBuf, (const uchar __user *) buf, count)) {
+			up(&dgap_TmpWriteSem);
+			printk("Write: Copy from user failed!\n");
+			return -EFAULT;
+		}
+
+		DGAP_LOCK(ch->ch_lock, lock_flags);
+
+		buf = dgap_TmpWriteBuf;
+	}
+
+	n = count;
+
+	/*
+	 * If the write wraps over the top of the circular buffer,
+	 * move the portion up to the wrap point, and reset the
+	 * pointers to the bottom.
+	 */
+	remain = ch->ch_tstart + ch->ch_tsize - head;
+
+	if (n >= remain) {
+		n -= remain;
+		vaddr = ch->ch_taddr + head;
+
+		memcpy_toio(vaddr, (uchar *) buf, remain);
+		dgap_sniff_nowait_nolock(ch, "USER WRITE", (uchar *) buf, remain);
+
+		head = ch->ch_tstart;
+		buf += remain;
+	}
+
+	if (n > 0) {
+
+		/*
+		 * Move rest of data.
+		 */
+		vaddr = ch->ch_taddr + head;
+		remain = n;
+
+		memcpy_toio(vaddr, (uchar *) buf, remain);
+		dgap_sniff_nowait_nolock(ch, "USER WRITE", (uchar *) buf, remain);
+
+		head += remain;
+
+	}
+
+	if (count) {
+		ch->ch_txcount += count;
+		head &= tmask;
+		writew(head, &(bs->tx_head));
+	}
+
+	dgap_set_firmware_event(un, UN_LOW | UN_EMPTY);
+
+	/*
+	 * If this is the print device, and the
+	 * printer is still on, we need to turn it
+	 * off before going idle.  If the buffer is
+	 * non-empty, wait until it goes empty.
+	 * Otherwise turn it off right now.
+	 */
+	if ((un->un_type == DGAP_PRINT) && (ch->ch_flags & CH_PRON)) {
+		tail = readw(&(bs->tx_tail)) & tmask;
+
+		if (tail != head) {
+			un->un_flags |= UN_EMPTY;
+			writeb(1, &(bs->iempty));
+		} else {
+			dgap_wmove(ch, ch->ch_digi.digi_offstr,
+				(int) ch->ch_digi.digi_offlen);
+			head = readw(&(bs->tx_head)) & tmask;
+			ch->ch_flags &= ~CH_PRON;
+		}
+	}
+
+	/* Update printer buffer empty time. */
+	if ((un->un_type == DGAP_PRINT) && (ch->ch_digi.digi_maxcps > 0)
+	    && (ch->ch_digi.digi_bufsize > 0)) {
+		ch->ch_cpstime += (HZ * count) / ch->ch_digi.digi_maxcps;
+	}
+
+	if (from_user) {
+		DGAP_UNLOCK(ch->ch_lock, lock_flags);
+		up(&dgap_TmpWriteSem);
+	} else
+		DGAP_UNLOCK(ch->ch_lock, lock_flags);
+
+	return count;
+}
+
+/*
+ * Return modem signals to ld.
+ */
+static int dgap_tty_tiocmget(struct tty_struct *tty)
+{
+	struct channel_t *ch;
+	struct un_t *un;
+	int result = -EIO;
+	uchar mstat = 0;
+	ulong lock_flags;
+
+	if (!tty || tty->magic != TTY_MAGIC)
+		return result;
+
+	un = tty->driver_data;
+	if (!un || un->magic != DGAP_UNIT_MAGIC)
+		return result;
+
+	ch = un->un_ch;
+	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+		return result;
+
+	DGAP_LOCK(ch->ch_lock, lock_flags);
+
+	mstat = readb(&(ch->ch_bs->m_stat));
+	/* Append any outbound signals that might be pending... */
+	mstat |= ch->ch_mostat;
+
+	DGAP_UNLOCK(ch->ch_lock, lock_flags);
+
+	result = 0;
+
+	if (mstat & D_DTR(ch))
+		result |= TIOCM_DTR;
+	if (mstat & D_RTS(ch))
+		result |= TIOCM_RTS;
+	if (mstat & D_CTS(ch))
+		result |= TIOCM_CTS;
+	if (mstat & D_DSR(ch))
+		result |= TIOCM_DSR;
+	if (mstat & D_RI(ch))
+		result |= TIOCM_RI;
+	if (mstat & D_CD(ch))
+		result |= TIOCM_CD;
+
+	return result;
+}
+
+/*
+ * dgap_tty_tiocmset()
+ *
+ * Set modem signals, called by ld.
+ */
+static int dgap_tty_tiocmset(struct tty_struct *tty,
+		unsigned int set, unsigned int clear)
+{
+	struct board_t *bd;
+	struct channel_t *ch;
+	struct un_t *un;
+	int ret = -EIO;
+	ulong lock_flags;
+	ulong lock_flags2;
+
+	if (!tty || tty->magic != TTY_MAGIC)
+		return ret;
+
+	un = tty->driver_data;
+	if (!un || un->magic != DGAP_UNIT_MAGIC)
+		return ret;
+
+	ch = un->un_ch;
+	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+		return ret;
+
+	bd = ch->ch_bd;
+	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
+		return ret;
+
+	DGAP_LOCK(bd->bd_lock, lock_flags);
+	DGAP_LOCK(ch->ch_lock, lock_flags2);
+
+	if (set & TIOCM_RTS) {
+		ch->ch_mforce |= D_RTS(ch);
+		ch->ch_mval   |= D_RTS(ch);
+	}
+
+	if (set & TIOCM_DTR) {
+		ch->ch_mforce |= D_DTR(ch);
+		ch->ch_mval   |= D_DTR(ch);
+	}
+
+	if (clear & TIOCM_RTS) {
+		ch->ch_mforce |= D_RTS(ch);
+		ch->ch_mval   &= ~(D_RTS(ch));
+	}
+
+	if (clear & TIOCM_DTR) {
+		ch->ch_mforce |= D_DTR(ch);
+		ch->ch_mval   &= ~(D_DTR(ch));
+	}
+
+	dgap_param(tty);
+
+	DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+	DGAP_UNLOCK(bd->bd_lock, lock_flags);
+
+	return 0;
+}
+
+/*
+ * dgap_tty_send_break()
+ *
+ * Send a Break, called by ld.
+ */
+static int dgap_tty_send_break(struct tty_struct *tty, int msec)
+{
+	struct board_t *bd;
+	struct channel_t *ch;
+	struct un_t *un;
+	int ret = -EIO;
+	ulong lock_flags;
+	ulong lock_flags2;
+
+	if (!tty || tty->magic != TTY_MAGIC)
+		return ret;
+
+	un = tty->driver_data;
+	if (!un || un->magic != DGAP_UNIT_MAGIC)
+		return ret;
+
+	ch = un->un_ch;
+	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+		return ret;
+
+	bd = ch->ch_bd;
+	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
+		return ret;
+
+	switch (msec) {
+	case -1:
+		msec = 0xFFFF;
+		break;
+	case 0:
+		msec = 1;
+		break;
+	default:
+		msec /= 10;
+		break;
+	}
+
+	DGAP_LOCK(bd->bd_lock, lock_flags);
+	DGAP_LOCK(ch->ch_lock, lock_flags2);
+#if 0
+	dgap_cmdw(ch, SBREAK, (u16) SBREAK_TIME, 0);
+#endif
+	dgap_cmdw(ch, SBREAK, (u16) msec, 0);
+
+	DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+	DGAP_UNLOCK(bd->bd_lock, lock_flags);
+
+	return 0;
+}
+
+/*
+ * dgap_tty_wait_until_sent()
+ *
+ * wait until data has been transmitted, called by ld.
+ */
+static void dgap_tty_wait_until_sent(struct tty_struct *tty, int timeout)
+{
+	dgap_wait_for_drain(tty);
+}
+
+/*
+ * dgap_send_xchar()
+ *
+ * send a high priority character, called by ld.
+ */
+static void dgap_tty_send_xchar(struct tty_struct *tty, char c)
+{
+	struct board_t *bd;
+	struct channel_t *ch;
+	struct un_t *un;
+	ulong lock_flags;
+	ulong lock_flags2;
+
+	if (!tty || tty->magic != TTY_MAGIC)
+		return;
+
+	un = tty->driver_data;
+	if (!un || un->magic != DGAP_UNIT_MAGIC)
+		return;
+
+	ch = un->un_ch;
+	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+		return;
+
+	bd = ch->ch_bd;
+	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
+		return;
+
+	DGAP_LOCK(bd->bd_lock, lock_flags);
+	DGAP_LOCK(ch->ch_lock, lock_flags2);
+
+	/*
+	 * This is technically what we should do.
+	 * However, the NIST tests specifically want
+	 * to see each XON or XOFF character that it
+	 * sends, so lets just send each character
+	 * by hand...
+	 */
+#if 0
+	if (c == STOP_CHAR(tty))
+		dgap_cmdw(ch, RPAUSE, 0, 0);
+	else if (c == START_CHAR(tty))
+		dgap_cmdw(ch, RRESUME, 0, 0);
+	else
+		dgap_wmove(ch, &c, 1);
+#else
+	dgap_wmove(ch, &c, 1);
+#endif
+
+	DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+	DGAP_UNLOCK(bd->bd_lock, lock_flags);
+
+	return;
+}
+
+/*
+ * Return modem signals to ld.
+ */
+static int dgap_get_modem_info(struct channel_t *ch, unsigned int __user *value)
+{
+	int result = 0;
+	uchar mstat = 0;
+	ulong lock_flags;
+	int rc = 0;
+
+	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+		return -ENXIO;
+
+	DGAP_LOCK(ch->ch_lock, lock_flags);
+
+	mstat = readb(&(ch->ch_bs->m_stat));
+	/* Append any outbound signals that might be pending... */
+	mstat |= ch->ch_mostat;
+
+	DGAP_UNLOCK(ch->ch_lock, lock_flags);
+
+	result = 0;
+
+	if (mstat & D_DTR(ch))
+		result |= TIOCM_DTR;
+	if (mstat & D_RTS(ch))
+		result |= TIOCM_RTS;
+	if (mstat & D_CTS(ch))
+		result |= TIOCM_CTS;
+	if (mstat & D_DSR(ch))
+		result |= TIOCM_DSR;
+	if (mstat & D_RI(ch))
+		result |= TIOCM_RI;
+	if (mstat & D_CD(ch))
+		result |= TIOCM_CD;
+
+	rc = put_user(result, value);
+
+	return rc;
+}
+
+/*
+ * dgap_set_modem_info()
+ *
+ * Set modem signals, called by ld.
+ */
+static int dgap_set_modem_info(struct tty_struct *tty, unsigned int command, unsigned int __user *value)
+{
+	struct board_t *bd;
+	struct channel_t *ch;
+	struct un_t *un;
+	int ret = -ENXIO;
+	unsigned int arg = 0;
+	ulong lock_flags;
+	ulong lock_flags2;
+
+	if (!tty || tty->magic != TTY_MAGIC)
+		return ret;
+
+	un = tty->driver_data;
+	if (!un || un->magic != DGAP_UNIT_MAGIC)
+		return ret;
+
+	ch = un->un_ch;
+	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+		return ret;
+
+	bd = ch->ch_bd;
+	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
+		return ret;
+
+	ret = get_user(arg, value);
+	if (ret)
+		return ret;
+
+	switch (command) {
+	case TIOCMBIS:
+		if (arg & TIOCM_RTS) {
+			ch->ch_mforce |= D_RTS(ch);
+			ch->ch_mval   |= D_RTS(ch);
+		}
+
+		if (arg & TIOCM_DTR) {
+			ch->ch_mforce |= D_DTR(ch);
+			ch->ch_mval   |= D_DTR(ch);
+		}
+
+		break;
+
+	case TIOCMBIC:
+		if (arg & TIOCM_RTS) {
+			ch->ch_mforce |= D_RTS(ch);
+			ch->ch_mval   &= ~(D_RTS(ch));
+		}
+
+		if (arg & TIOCM_DTR) {
+			ch->ch_mforce |= D_DTR(ch);
+			ch->ch_mval   &= ~(D_DTR(ch));
+		}
+
+		break;
+
+	case TIOCMSET:
+		ch->ch_mforce = D_DTR(ch)|D_RTS(ch);
+
+		if (arg & TIOCM_RTS)
+			ch->ch_mval |= D_RTS(ch);
+		else
+			ch->ch_mval &= ~(D_RTS(ch));
+
+		if (arg & TIOCM_DTR)
+			ch->ch_mval |= (D_DTR(ch));
+		else
+			ch->ch_mval &= ~(D_DTR(ch));
+
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	DGAP_LOCK(bd->bd_lock, lock_flags);
+	DGAP_LOCK(ch->ch_lock, lock_flags2);
+
+	dgap_param(tty);
+
+	DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+	DGAP_UNLOCK(bd->bd_lock, lock_flags);
+
+	return 0;
+}
+
+/*
+ * dgap_tty_digigeta()
+ *
+ * Ioctl to get the information for ditty.
+ *
+ *
+ *
+ */
+static int dgap_tty_digigeta(struct tty_struct *tty, struct digi_t __user *retinfo)
+{
+	struct channel_t *ch;
+	struct un_t *un;
+	struct digi_t tmp;
+	ulong lock_flags;
+
+	if (!retinfo)
+		return -EFAULT;
+
+	if (!tty || tty->magic != TTY_MAGIC)
+		return -EFAULT;
+
+	un = tty->driver_data;
+	if (!un || un->magic != DGAP_UNIT_MAGIC)
+		return -EFAULT;
+
+	ch = un->un_ch;
+	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+		return -EFAULT;
+
+	memset(&tmp, 0, sizeof(tmp));
+
+	DGAP_LOCK(ch->ch_lock, lock_flags);
+	memcpy(&tmp, &ch->ch_digi, sizeof(tmp));
+	DGAP_UNLOCK(ch->ch_lock, lock_flags);
+
+	if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
+		return -EFAULT;
+
+	return 0;
+}
+
+/*
+ * dgap_tty_digiseta()
+ *
+ * Ioctl to set the information for ditty.
+ *
+ *
+ *
+ */
+static int dgap_tty_digiseta(struct tty_struct *tty, struct digi_t __user *new_info)
+{
+	struct board_t *bd;
+	struct channel_t *ch;
+	struct un_t *un;
+	struct digi_t new_digi;
+	ulong   lock_flags = 0;
+	unsigned long lock_flags2;
+
+	if (!tty || tty->magic != TTY_MAGIC)
+		return -EFAULT;
+
+	un = tty->driver_data;
+	if (!un || un->magic != DGAP_UNIT_MAGIC)
+		return -EFAULT;
+
+	ch = un->un_ch;
+	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+		return -EFAULT;
+
+	bd = ch->ch_bd;
+	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
+		return -EFAULT;
+
+	if (copy_from_user(&new_digi, new_info, sizeof(struct digi_t)))
+		return -EFAULT;
+
+	DGAP_LOCK(bd->bd_lock, lock_flags);
+	DGAP_LOCK(ch->ch_lock, lock_flags2);
+
+	memcpy(&ch->ch_digi, &new_digi, sizeof(struct digi_t));
+
+	if (ch->ch_digi.digi_maxcps < 1)
+		ch->ch_digi.digi_maxcps = 1;
+
+	if (ch->ch_digi.digi_maxcps > 10000)
+		ch->ch_digi.digi_maxcps = 10000;
+
+	if (ch->ch_digi.digi_bufsize < 10)
+		ch->ch_digi.digi_bufsize = 10;
+
+	if (ch->ch_digi.digi_maxchar < 1)
+		ch->ch_digi.digi_maxchar = 1;
+
+	if (ch->ch_digi.digi_maxchar > ch->ch_digi.digi_bufsize)
+		ch->ch_digi.digi_maxchar = ch->ch_digi.digi_bufsize;
+
+	if (ch->ch_digi.digi_onlen > DIGI_PLEN)
+		ch->ch_digi.digi_onlen = DIGI_PLEN;
+
+	if (ch->ch_digi.digi_offlen > DIGI_PLEN)
+		ch->ch_digi.digi_offlen = DIGI_PLEN;
+
+	dgap_param(tty);
+
+	DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+	DGAP_UNLOCK(bd->bd_lock, lock_flags);
+
+	return 0;
+}
+
+/*
+ * dgap_tty_digigetedelay()
+ *
+ * Ioctl to get the current edelay setting.
+ *
+ *
+ *
+ */
+static int dgap_tty_digigetedelay(struct tty_struct *tty, int __user *retinfo)
+{
+	struct channel_t *ch;
+	struct un_t *un;
+	int tmp;
+	ulong lock_flags;
+
+	if (!retinfo)
+		return -EFAULT;
+
+	if (!tty || tty->magic != TTY_MAGIC)
+		return -EFAULT;
+
+	un = tty->driver_data;
+	if (!un || un->magic != DGAP_UNIT_MAGIC)
+		return -EFAULT;
+
+	ch = un->un_ch;
+	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+		return -EFAULT;
+
+	memset(&tmp, 0, sizeof(tmp));
+
+	DGAP_LOCK(ch->ch_lock, lock_flags);
+	tmp = readw(&(ch->ch_bs->edelay));
+	DGAP_UNLOCK(ch->ch_lock, lock_flags);
+
+	if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
+		return -EFAULT;
+
+	return 0;
+}
+
+/*
+ * dgap_tty_digisetedelay()
+ *
+ * Ioctl to set the EDELAY setting
+ *
+ */
+static int dgap_tty_digisetedelay(struct tty_struct *tty, int __user *new_info)
+{
+	struct board_t *bd;
+	struct channel_t *ch;
+	struct un_t *un;
+	int new_digi;
+	ulong lock_flags;
+	ulong lock_flags2;
+
+	if (!tty || tty->magic != TTY_MAGIC)
+		return -EFAULT;
+
+	un = tty->driver_data;
+	if (!un || un->magic != DGAP_UNIT_MAGIC)
+		return -EFAULT;
+
+	ch = un->un_ch;
+	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+		return -EFAULT;
+
+	bd = ch->ch_bd;
+	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
+		return -EFAULT;
+
+	if (copy_from_user(&new_digi, new_info, sizeof(int)))
+		return -EFAULT;
+
+	DGAP_LOCK(bd->bd_lock, lock_flags);
+	DGAP_LOCK(ch->ch_lock, lock_flags2);
+
+	writew((u16) new_digi, &(ch->ch_bs->edelay));
+
+	dgap_param(tty);
+
+	DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+	DGAP_UNLOCK(bd->bd_lock, lock_flags);
+
+	return 0;
+}
+
+/*
+ * dgap_tty_digigetcustombaud()
+ *
+ * Ioctl to get the current custom baud rate setting.
+ */
+static int dgap_tty_digigetcustombaud(struct tty_struct *tty, int __user *retinfo)
+{
+	struct channel_t *ch;
+	struct un_t *un;
+	int tmp;
+	ulong lock_flags;
+
+	if (!retinfo)
+		return -EFAULT;
+
+	if (!tty || tty->magic != TTY_MAGIC)
+		return -EFAULT;
+
+	un = tty->driver_data;
+	if (!un || un->magic != DGAP_UNIT_MAGIC)
+		return -EFAULT;
+
+	ch = un->un_ch;
+	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+		return -EFAULT;
+
+	memset(&tmp, 0, sizeof(tmp));
+
+	DGAP_LOCK(ch->ch_lock, lock_flags);
+	tmp = dgap_get_custom_baud(ch);
+	DGAP_UNLOCK(ch->ch_lock, lock_flags);
+
+	if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
+		return -EFAULT;
+
+	return 0;
+}
+
+/*
+ * dgap_tty_digisetcustombaud()
+ *
+ * Ioctl to set the custom baud rate setting
+ */
+static int dgap_tty_digisetcustombaud(struct tty_struct *tty, int __user *new_info)
+{
+	struct board_t *bd;
+	struct channel_t *ch;
+	struct un_t *un;
+	uint new_rate;
+	ulong lock_flags;
+	ulong lock_flags2;
+
+	if (!tty || tty->magic != TTY_MAGIC)
+		return -EFAULT;
+
+	un = tty->driver_data;
+	if (!un || un->magic != DGAP_UNIT_MAGIC)
+		return -EFAULT;
+
+	ch = un->un_ch;
+	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+		return -EFAULT;
+
+	bd = ch->ch_bd;
+	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
+		return -EFAULT;
+
+
+	if (copy_from_user(&new_rate, new_info, sizeof(unsigned int)))
+		return -EFAULT;
+
+	if (bd->bd_flags & BD_FEP5PLUS) {
+
+		DGAP_LOCK(bd->bd_lock, lock_flags);
+		DGAP_LOCK(ch->ch_lock, lock_flags2);
+
+		ch->ch_custom_speed = new_rate;
+
+		dgap_param(tty);
+
+		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+		DGAP_UNLOCK(bd->bd_lock, lock_flags);
+	}
+
+	return 0;
+}
+
+/*
+ * dgap_set_termios()
+ */
+static void dgap_tty_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
+{
+	struct board_t *bd;
+	struct channel_t *ch;
+	struct un_t *un;
+	unsigned long lock_flags;
+	unsigned long lock_flags2;
+
+	if (!tty || tty->magic != TTY_MAGIC)
+		return;
+
+	un = tty->driver_data;
+	if (!un || un->magic != DGAP_UNIT_MAGIC)
+		return;
+
+	ch = un->un_ch;
+	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+		return;
+
+	bd = ch->ch_bd;
+	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
+		return;
+
+	DGAP_LOCK(bd->bd_lock, lock_flags);
+	DGAP_LOCK(ch->ch_lock, lock_flags2);
+
+	ch->ch_c_cflag   = tty->termios.c_cflag;
+	ch->ch_c_iflag   = tty->termios.c_iflag;
+	ch->ch_c_oflag   = tty->termios.c_oflag;
+	ch->ch_c_lflag   = tty->termios.c_lflag;
+	ch->ch_startc    = tty->termios.c_cc[VSTART];
+	ch->ch_stopc     = tty->termios.c_cc[VSTOP];
+
+	dgap_carrier(ch);
+	dgap_param(tty);
+
+	DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+	DGAP_UNLOCK(bd->bd_lock, lock_flags);
+}
+
+static void dgap_tty_throttle(struct tty_struct *tty)
+{
+	struct board_t *bd;
+	struct channel_t *ch;
+	struct un_t *un;
+	ulong   lock_flags;
+	ulong   lock_flags2;
+
+	if (!tty || tty->magic != TTY_MAGIC)
+		return;
+
+	un = tty->driver_data;
+	if (!un || un->magic != DGAP_UNIT_MAGIC)
+		return;
+
+	ch = un->un_ch;
+	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+		return;
+
+	bd = ch->ch_bd;
+	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
+		return;
+
+	DGAP_LOCK(bd->bd_lock, lock_flags);
+	DGAP_LOCK(ch->ch_lock, lock_flags2);
+
+	ch->ch_flags |= (CH_RXBLOCK);
+#if 1
+	dgap_cmdw(ch, RPAUSE, 0, 0);
+#endif
+
+	DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+	DGAP_UNLOCK(bd->bd_lock, lock_flags);
+
+}
+
+static void dgap_tty_unthrottle(struct tty_struct *tty)
+{
+	struct board_t *bd;
+	struct channel_t *ch;
+	struct un_t *un;
+	ulong   lock_flags;
+	ulong   lock_flags2;
+
+	if (!tty || tty->magic != TTY_MAGIC)
+		return;
+
+	un = tty->driver_data;
+	if (!un || un->magic != DGAP_UNIT_MAGIC)
+		return;
+
+	ch = un->un_ch;
+	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+		return;
+
+	bd = ch->ch_bd;
+	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
+		return;
+
+	DGAP_LOCK(bd->bd_lock, lock_flags);
+	DGAP_LOCK(ch->ch_lock, lock_flags2);
+
+	ch->ch_flags &= ~(CH_RXBLOCK);
+
+#if 1
+	dgap_cmdw(ch, RRESUME, 0, 0);
+#endif
+
+	DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+	DGAP_UNLOCK(bd->bd_lock, lock_flags);
+}
+
+static void dgap_tty_start(struct tty_struct *tty)
+{
+	struct board_t *bd;
+	struct channel_t *ch;
+	struct un_t *un;
+	ulong   lock_flags;
+	ulong   lock_flags2;
+
+	if (!tty || tty->magic != TTY_MAGIC)
+		return;
+
+	un = tty->driver_data;
+	if (!un || un->magic != DGAP_UNIT_MAGIC)
+		return;
+
+	ch = un->un_ch;
+	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+		return;
+
+	bd = ch->ch_bd;
+	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
+		return;
+
+	DGAP_LOCK(bd->bd_lock, lock_flags);
+	DGAP_LOCK(ch->ch_lock, lock_flags2);
+
+	dgap_cmdw(ch, RESUMETX, 0, 0);
+
+	DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+	DGAP_UNLOCK(bd->bd_lock, lock_flags);
+
+}
+
+static void dgap_tty_stop(struct tty_struct *tty)
+{
+	struct board_t *bd;
+	struct channel_t *ch;
+	struct un_t *un;
+	ulong   lock_flags;
+	ulong   lock_flags2;
+
+	if (!tty || tty->magic != TTY_MAGIC)
+		return;
+
+	un = tty->driver_data;
+	if (!un || un->magic != DGAP_UNIT_MAGIC)
+		return;
+
+	ch = un->un_ch;
+	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+		return;
+
+	bd = ch->ch_bd;
+	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
+		return;
+
+	DGAP_LOCK(bd->bd_lock, lock_flags);
+	DGAP_LOCK(ch->ch_lock, lock_flags2);
+
+	dgap_cmdw(ch, PAUSETX, 0, 0);
+
+	DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+	DGAP_UNLOCK(bd->bd_lock, lock_flags);
+
+}
+
+/*
+ * dgap_tty_flush_chars()
+ *
+ * Flush the cook buffer
+ *
+ * Note to self, and any other poor souls who venture here:
+ *
+ * flush in this case DOES NOT mean dispose of the data.
+ * instead, it means "stop buffering and send it if you
+ * haven't already."  Just guess how I figured that out...   SRW 2-Jun-98
+ *
+ * It is also always called in interrupt context - JAR 8-Sept-99
+ */
+static void dgap_tty_flush_chars(struct tty_struct *tty)
+{
+	struct board_t *bd;
+	struct channel_t *ch;
+	struct un_t *un;
+	ulong   lock_flags;
+	ulong   lock_flags2;
+
+	if (!tty || tty->magic != TTY_MAGIC)
+		return;
+
+	un = tty->driver_data;
+	if (!un || un->magic != DGAP_UNIT_MAGIC)
+		return;
+
+	ch = un->un_ch;
+	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+		return;
+
+	bd = ch->ch_bd;
+	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
+		return;
+
+	DGAP_LOCK(bd->bd_lock, lock_flags);
+	DGAP_LOCK(ch->ch_lock, lock_flags2);
+
+	/* TODO: Do something here */
+
+	DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+	DGAP_UNLOCK(bd->bd_lock, lock_flags);
+}
+
+/*
+ * dgap_tty_flush_buffer()
+ *
+ * Flush Tx buffer (make in == out)
+ */
+static void dgap_tty_flush_buffer(struct tty_struct *tty)
+{
+	struct board_t *bd;
+	struct channel_t *ch;
+	struct un_t *un;
+	ulong   lock_flags;
+	ulong   lock_flags2;
+	u16	head = 0;
+
+	if (!tty || tty->magic != TTY_MAGIC)
+		return;
+
+	un = tty->driver_data;
+	if (!un || un->magic != DGAP_UNIT_MAGIC)
+		return;
+
+	ch = un->un_ch;
+	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+		return;
+
+	bd = ch->ch_bd;
+	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
+		return;
+
+	DGAP_LOCK(bd->bd_lock, lock_flags);
+	DGAP_LOCK(ch->ch_lock, lock_flags2);
+
+	ch->ch_flags &= ~CH_STOP;
+	head = readw(&(ch->ch_bs->tx_head));
+	dgap_cmdw(ch, FLUSHTX, (u16) head, 0);
+	dgap_cmdw(ch, RESUMETX, 0, 0);
+	if (ch->ch_tun.un_flags & (UN_LOW|UN_EMPTY)) {
+		ch->ch_tun.un_flags &= ~(UN_LOW|UN_EMPTY);
+		wake_up_interruptible(&ch->ch_tun.un_flags_wait);
+	}
+	if (ch->ch_pun.un_flags & (UN_LOW|UN_EMPTY)) {
+		ch->ch_pun.un_flags &= ~(UN_LOW|UN_EMPTY);
+		wake_up_interruptible(&ch->ch_pun.un_flags_wait);
+	}
+
+	DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+	DGAP_UNLOCK(bd->bd_lock, lock_flags);
+	if (waitqueue_active(&tty->write_wait))
+		wake_up_interruptible(&tty->write_wait);
+	tty_wakeup(tty);
+}
+
+/*****************************************************************************
+ *
+ * The IOCTL function and all of its helpers
+ *
+ *****************************************************************************/
+
+/*
+ * dgap_tty_ioctl()
+ *
+ * The usual assortment of ioctl's
+ */
+static int dgap_tty_ioctl(struct tty_struct *tty, unsigned int cmd,
+		unsigned long arg)
+{
+	struct board_t *bd;
+	struct channel_t *ch;
+	struct un_t *un;
+	int rc;
+	u16	head = 0;
+	ulong   lock_flags = 0;
+	ulong   lock_flags2 = 0;
+	void __user *uarg = (void __user *) arg;
+
+	if (!tty || tty->magic != TTY_MAGIC)
+		return -ENODEV;
+
+	un = tty->driver_data;
+	if (!un || un->magic != DGAP_UNIT_MAGIC)
+		return -ENODEV;
+
+	ch = un->un_ch;
+	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+		return -ENODEV;
+
+	bd = ch->ch_bd;
+	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
+		return -ENODEV;
+
+	DGAP_LOCK(bd->bd_lock, lock_flags);
+	DGAP_LOCK(ch->ch_lock, lock_flags2);
+
+	if (un->un_open_count <= 0) {
+		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+		DGAP_UNLOCK(bd->bd_lock, lock_flags);
+		return -EIO;
+	}
+
+	switch (cmd) {
+
+	/* Here are all the standard ioctl's that we MUST implement */
+
+	case TCSBRK:
+		/*
+		 * TCSBRK is SVID version: non-zero arg --> no break
+		 * this behaviour is exploited by tcdrain().
+		 *
+		 * According to POSIX.1 spec (7.2.2.1.2) breaks should be
+		 * between 0.25 and 0.5 seconds so we'll ask for something
+		 * in the middle: 0.375 seconds.
+		 */
+		rc = tty_check_change(tty);
+		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+		DGAP_UNLOCK(bd->bd_lock, lock_flags);
+		if (rc)
+			return rc;
+
+		rc = dgap_wait_for_drain(tty);
+
+		if (rc)
+			return -EINTR;
+
+		DGAP_LOCK(bd->bd_lock, lock_flags);
+		DGAP_LOCK(ch->ch_lock, lock_flags2);
+
+		if (((cmd == TCSBRK) && (!arg)) || (cmd == TCSBRKP))
+			dgap_cmdw(ch, SBREAK, (u16) SBREAK_TIME, 0);
+
+		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+		DGAP_UNLOCK(bd->bd_lock, lock_flags);
+
+		return 0;
+
+	case TCSBRKP:
+		/* support for POSIX tcsendbreak()
+
+		 * According to POSIX.1 spec (7.2.2.1.2) breaks should be
+		 * between 0.25 and 0.5 seconds so we'll ask for something
+		 * in the middle: 0.375 seconds.
+		 */
+		rc = tty_check_change(tty);
+		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+		DGAP_UNLOCK(bd->bd_lock, lock_flags);
+		if (rc)
+			return rc;
+
+		rc = dgap_wait_for_drain(tty);
+		if (rc)
+			return -EINTR;
+
+		DGAP_LOCK(bd->bd_lock, lock_flags);
+		DGAP_LOCK(ch->ch_lock, lock_flags2);
+
+		dgap_cmdw(ch, SBREAK, (u16) SBREAK_TIME, 0);
+
+		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+		DGAP_UNLOCK(bd->bd_lock, lock_flags);
+
+		return 0;
+
+	case TIOCSBRK:
+		/*
+		 * FEP5 doesn't support turning on a break unconditionally.
+		 * The FEP5 device will stop sending a break automatically
+		 * after the specified time value that was sent when turning on
+		 * the break.
+		 */
+		rc = tty_check_change(tty);
+		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+		DGAP_UNLOCK(bd->bd_lock, lock_flags);
+		if (rc)
+			return rc;
+
+		rc = dgap_wait_for_drain(tty);
+		if (rc)
+			return -EINTR;
+
+		DGAP_LOCK(bd->bd_lock, lock_flags);
+		DGAP_LOCK(ch->ch_lock, lock_flags2);
+
+		dgap_cmdw(ch, SBREAK, (u16) SBREAK_TIME, 0);
+
+		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+		DGAP_UNLOCK(bd->bd_lock, lock_flags);
+
+		return 0;
+
+	case TIOCCBRK:
+		/*
+		 * FEP5 doesn't support turning off a break unconditionally.
+		 * The FEP5 device will stop sending a break automatically
+		 * after the specified time value that was sent when turning on
+		 * the break.
+		 */
+		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+		DGAP_UNLOCK(bd->bd_lock, lock_flags);
+		return 0;
+
+	case TIOCGSOFTCAR:
+
+		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+		DGAP_UNLOCK(bd->bd_lock, lock_flags);
+
+		rc = put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned long __user *) arg);
+		return rc;
+
+	case TIOCSSOFTCAR:
+		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+		DGAP_UNLOCK(bd->bd_lock, lock_flags);
+
+		rc = get_user(arg, (unsigned long __user *) arg);
+		if (rc)
+			return rc;
+
+		DGAP_LOCK(bd->bd_lock, lock_flags);
+		DGAP_LOCK(ch->ch_lock, lock_flags2);
+		tty->termios.c_cflag = ((tty->termios.c_cflag & ~CLOCAL) | (arg ? CLOCAL : 0));
+		dgap_param(tty);
+		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+		DGAP_UNLOCK(bd->bd_lock, lock_flags);
+
+		return 0;
+
+	case TIOCMGET:
+		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+		DGAP_UNLOCK(bd->bd_lock, lock_flags);
+		return dgap_get_modem_info(ch, uarg);
+
+	case TIOCMBIS:
+	case TIOCMBIC:
+	case TIOCMSET:
+		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+		DGAP_UNLOCK(bd->bd_lock, lock_flags);
+		return dgap_set_modem_info(tty, cmd, uarg);
+
+		/*
+		 * Here are any additional ioctl's that we want to implement
+		 */
+
+	case TCFLSH:
+		/*
+		 * The linux tty driver doesn't have a flush
+		 * input routine for the driver, assuming all backed
+		 * up data is in the line disc. buffers.  However,
+		 * we all know that's not the case.  Here, we
+		 * act on the ioctl, but then lie and say we didn't
+		 * so the line discipline will process the flush
+		 * also.
+		 */
+		rc = tty_check_change(tty);
+		if (rc) {
+			DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+			DGAP_UNLOCK(bd->bd_lock, lock_flags);
+			return rc;
+		}
+
+		if ((arg == TCIFLUSH) || (arg == TCIOFLUSH)) {
+			if (!(un->un_type == DGAP_PRINT)) {
+				head = readw(&(ch->ch_bs->rx_head));
+				writew(head, &(ch->ch_bs->rx_tail));
+				writeb(0, &(ch->ch_bs->orun));
+			}
+		}
+
+		if ((arg == TCOFLUSH) || (arg == TCIOFLUSH)) {
+			ch->ch_flags &= ~CH_STOP;
+			head = readw(&(ch->ch_bs->tx_head));
+			dgap_cmdw(ch, FLUSHTX, (u16) head, 0);
+			dgap_cmdw(ch, RESUMETX, 0, 0);
+			if (ch->ch_tun.un_flags & (UN_LOW|UN_EMPTY)) {
+				ch->ch_tun.un_flags &= ~(UN_LOW|UN_EMPTY);
+				wake_up_interruptible(&ch->ch_tun.un_flags_wait);
+			}
+			if (ch->ch_pun.un_flags & (UN_LOW|UN_EMPTY)) {
+				ch->ch_pun.un_flags &= ~(UN_LOW|UN_EMPTY);
+				wake_up_interruptible(&ch->ch_pun.un_flags_wait);
+			}
+			if (waitqueue_active(&tty->write_wait))
+				wake_up_interruptible(&tty->write_wait);
+
+			/* Can't hold any locks when calling tty_wakeup! */
+			DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+			DGAP_UNLOCK(bd->bd_lock, lock_flags);
+			tty_wakeup(tty);
+			DGAP_LOCK(bd->bd_lock, lock_flags);
+			DGAP_LOCK(ch->ch_lock, lock_flags2);
+		}
+
+		/* pretend we didn't recognize this IOCTL */
+		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+		DGAP_UNLOCK(bd->bd_lock, lock_flags);
+
+		return -ENOIOCTLCMD;
+
+	case TCSETSF:
+	case TCSETSW:
+		/*
+		 * The linux tty driver doesn't have a flush
+		 * input routine for the driver, assuming all backed
+		 * up data is in the line disc. buffers.  However,
+		 * we all know that's not the case.  Here, we
+		 * act on the ioctl, but then lie and say we didn't
+		 * so the line discipline will process the flush
+		 * also.
+		 */
+		if (cmd == TCSETSF) {
+			/* flush rx */
+			ch->ch_flags &= ~CH_STOP;
+			head = readw(&(ch->ch_bs->rx_head));
+			writew(head, &(ch->ch_bs->rx_tail));
+		}
+
+		/* now wait for all the output to drain */
+		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+		DGAP_UNLOCK(bd->bd_lock, lock_flags);
+		rc = dgap_wait_for_drain(tty);
+		if (rc)
+			return -EINTR;
+
+		/* pretend we didn't recognize this */
+		return -ENOIOCTLCMD;
+
+	case TCSETAW:
+
+		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+		DGAP_UNLOCK(bd->bd_lock, lock_flags);
+		rc = dgap_wait_for_drain(tty);
+		if (rc)
+			return -EINTR;
+
+		/* pretend we didn't recognize this */
+		return -ENOIOCTLCMD;
+
+	case TCXONC:
+		/*
+		 * The Linux Line Discipline (LD) would do this for us if we
+		 * let it, but we have the special firmware options to do this
+		 * the "right way" regardless of hardware or software flow
+		 * control so we'll do it outselves instead of letting the LD
+		 * do it.
+		 */
+		rc = tty_check_change(tty);
+		if (rc) {
+			DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+			DGAP_UNLOCK(bd->bd_lock, lock_flags);
+			return rc;
+		}
+
+		switch (arg) {
+
+		case TCOON:
+			DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+			DGAP_UNLOCK(bd->bd_lock, lock_flags);
+			dgap_tty_start(tty);
+			return 0;
+		case TCOOFF:
+			DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+			DGAP_UNLOCK(bd->bd_lock, lock_flags);
+			dgap_tty_stop(tty);
+			return 0;
+		case TCION:
+			DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+			DGAP_UNLOCK(bd->bd_lock, lock_flags);
+			/* Make the ld do it */
+			return -ENOIOCTLCMD;
+		case TCIOFF:
+			DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+			DGAP_UNLOCK(bd->bd_lock, lock_flags);
+			/* Make the ld do it */
+			return -ENOIOCTLCMD;
+		default:
+			DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+			DGAP_UNLOCK(bd->bd_lock, lock_flags);
+			return -EINVAL;
+		}
+
+	case DIGI_GETA:
+		/* get information for ditty */
+		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+		DGAP_UNLOCK(bd->bd_lock, lock_flags);
+		return dgap_tty_digigeta(tty, uarg);
+
+	case DIGI_SETAW:
+	case DIGI_SETAF:
+
+		/* set information for ditty */
+		if (cmd == (DIGI_SETAW)) {
+
+			DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+			DGAP_UNLOCK(bd->bd_lock, lock_flags);
+			rc = dgap_wait_for_drain(tty);
+			if (rc)
+				return -EINTR;
+			DGAP_LOCK(bd->bd_lock, lock_flags);
+			DGAP_LOCK(ch->ch_lock, lock_flags2);
+		} else
+			tty_ldisc_flush(tty);
+		/* fall thru */
+
+	case DIGI_SETA:
+		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+		DGAP_UNLOCK(bd->bd_lock, lock_flags);
+		return dgap_tty_digiseta(tty, uarg);
+
+	case DIGI_GEDELAY:
+		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+		DGAP_UNLOCK(bd->bd_lock, lock_flags);
+		return dgap_tty_digigetedelay(tty, uarg);
+
+	case DIGI_SEDELAY:
+		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+		DGAP_UNLOCK(bd->bd_lock, lock_flags);
+		return dgap_tty_digisetedelay(tty, uarg);
+
+	case DIGI_GETCUSTOMBAUD:
+		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+		DGAP_UNLOCK(bd->bd_lock, lock_flags);
+		return dgap_tty_digigetcustombaud(tty, uarg);
+
+	case DIGI_SETCUSTOMBAUD:
+		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+		DGAP_UNLOCK(bd->bd_lock, lock_flags);
+		return dgap_tty_digisetcustombaud(tty, uarg);
+
+	case DIGI_RESET_PORT:
+		dgap_firmware_reset_port(ch);
+		dgap_param(tty);
+		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+		DGAP_UNLOCK(bd->bd_lock, lock_flags);
+		return 0;
+
+	default:
+		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+		DGAP_UNLOCK(bd->bd_lock, lock_flags);
+
+		return -ENOIOCTLCMD;
+	}
+}
+
+static int dgap_after_config_loaded(int board)
+{
+	/*
+	 * Initialize KME waitqueues...
+	 */
+	init_waitqueue_head(&(dgap_Board[board]->kme_wait));
+
+	/*
+	 * allocate flip buffer for board.
+	 */
+	dgap_Board[board]->flipbuf = kmalloc(MYFLIPLEN, GFP_ATOMIC);
+	if (!dgap_Board[board]->flipbuf)
+		return -ENOMEM;
+
+	dgap_Board[board]->flipflagbuf = kmalloc(MYFLIPLEN, GFP_ATOMIC);
+	if (!dgap_Board[board]->flipflagbuf) {
+		kfree(dgap_Board[board]->flipbuf);
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
+/*
+ * Create pr and tty device entries
+ */
+static int dgap_tty_register_ports(struct board_t *brd)
+{
+	struct channel_t *ch;
+	int i;
+
+	brd->SerialPorts = kcalloc(brd->nasync, sizeof(*brd->SerialPorts),
+					GFP_KERNEL);
+	if (brd->SerialPorts == NULL)
+		return -ENOMEM;
+	for (i = 0; i < brd->nasync; i++)
+		tty_port_init(&brd->SerialPorts[i]);
+
+	brd->PrinterPorts = kcalloc(brd->nasync, sizeof(*brd->PrinterPorts),
+					GFP_KERNEL);
+	if (brd->PrinterPorts == NULL) {
+		kfree(brd->SerialPorts);
+		return -ENOMEM;
+	}
+	for (i = 0; i < brd->nasync; i++)
+		tty_port_init(&brd->PrinterPorts[i]);
+
+	ch = brd->channels[0];
+	for (i = 0; i < brd->nasync; i++, ch = brd->channels[i]) {
+
+		struct device *classp;
+
+		classp = tty_port_register_device(&brd->SerialPorts[i],
+					brd->SerialDriver,
+					brd->firstminor + i, NULL);
+
+		dgap_create_tty_sysfs(&ch->ch_tun, classp);
+		ch->ch_tun.un_sysfs = classp;
+
+		classp = tty_port_register_device(&brd->PrinterPorts[i],
+					brd->PrintDriver,
+					brd->firstminor + i, NULL);
+
+		dgap_create_tty_sysfs(&ch->ch_pun, classp);
+		ch->ch_pun.un_sysfs = classp;
+	}
+	dgap_create_ports_sysfiles(brd);
+
+	return 0;
+}
+
+/*
+ * Copies the BIOS code from the user to the board,
+ * and starts the BIOS running.
+ */
+static void dgap_do_bios_load(struct board_t *brd, uchar __user *ubios, int len)
+{
+	uchar *addr;
+	uint offset;
+	int i;
+
+	if (!brd || (brd->magic != DGAP_BOARD_MAGIC) || !brd->re_map_membase)
+		return;
+
+	addr = brd->re_map_membase;
+
+	/*
+	 * clear POST area
+	 */
+	for (i = 0; i < 16; i++)
+		writeb(0, addr + POSTAREA + i);
+
+	/*
+	 * Download bios
+	 */
+	offset = 0x1000;
+	memcpy_toio(addr + offset, ubios, len);
+
+	writel(0x0bf00401, addr);
+	writel(0, (addr + 4));
+
+	/* Clear the reset, and change states. */
+	writeb(FEPCLR, brd->re_map_port);
+}
+
+/*
+ * Checks to see if the BIOS completed running on the card.
+ */
+static void dgap_do_wait_for_bios(struct board_t *brd)
+{
+	uchar *addr;
+	u16 word;
+	u16 err1;
+	u16 err2;
+
+	if (!brd || (brd->magic != DGAP_BOARD_MAGIC) || !brd->re_map_membase)
+		return;
+
+	addr = brd->re_map_membase;
+	word = readw(addr + POSTAREA);
+
+	/*
+	 * It can take 5-6 seconds for a board to
+	 * pass the bios self test and post results.
+	 * Give it 10 seconds.
+	 */
+	brd->wait_for_bios = 0;
+	while (brd->wait_for_bios < 1000) {
+		/* Check to see if BIOS thinks board is good. (GD). */
+		if (word == *(u16 *) "GD") {
+			brd->state = FINISHED_BIOS_LOAD;
+			return;
+		}
+		msleep_interruptible(10);
+		brd->wait_for_bios++;
+		word = readw(addr + POSTAREA);
+	}
+
+	/* Gave up on board after too long of time taken */
+	err1 = readw(addr + SEQUENCE);
+	err2 = readw(addr + ERROR);
+	pr_warn("dgap: %s failed diagnostics.  Error #(%x,%x).\n",
+		brd->name, err1, err2);
+	brd->state = BOARD_FAILED;
+	brd->dpastatus = BD_NOBIOS;
+}
+
+/*
+ * Copies the FEP code from the user to the board,
+ * and starts the FEP running.
+ */
+static void dgap_do_fep_load(struct board_t *brd, uchar *ufep, int len)
+{
+	uchar *addr;
+	uint offset;
+
+	if (!brd || (brd->magic != DGAP_BOARD_MAGIC) || !brd->re_map_membase)
+		return;
+
+	addr = brd->re_map_membase;
+
+	/*
+	 * Download FEP
+	 */
+	offset = 0x1000;
+	memcpy_toio(addr + offset, ufep, len);
+
+	/*
+	 * If board is a concentrator product, we need to give
+	 * it its config string describing how the concentrators look.
+	 */
+	if ((brd->type == PCX) || (brd->type == PEPC)) {
+		uchar string[100];
+		uchar *config, *xconfig;
+		int i = 0;
+
+		xconfig = dgap_create_config_string(brd, string);
+
+		/* Write string to board memory */
+		config = addr + CONFIG;
+		for (; i < CONFIGSIZE; i++, config++, xconfig++) {
+			writeb(*xconfig, config);
+			if ((*xconfig & 0xff) == 0xff)
+				break;
+		}
+	}
+
+	writel(0xbfc01004, (addr + 0xc34));
+	writel(0x3, (addr + 0xc30));
+
+}
+
+/*
+ * Waits for the FEP to report thats its ready for us to use.
+ */
+static void dgap_do_wait_for_fep(struct board_t *brd)
+{
+	uchar *addr;
+	u16 word;
+	u16 err1;
+	u16 err2;
+
+	if (!brd || (brd->magic != DGAP_BOARD_MAGIC) || !brd->re_map_membase)
+		return;
+
+	addr = brd->re_map_membase;
+	word = readw(addr + FEPSTAT);
+
+	/*
+	 * It can take 2-3 seconds for the FEP to
+	 * be up and running. Give it 5 secs.
+	 */
+	brd->wait_for_fep = 0;
+	while (brd->wait_for_fep < 500) {
+		/* Check to see if FEP is up and running now. */
+		if (word == *(u16 *) "OS") {
+			brd->state = FINISHED_FEP_LOAD;
+			/*
+			 * Check to see if the board can support FEP5+ commands.
+			*/
+			word = readw(addr + FEP5_PLUS);
+			if (word == *(u16 *) "5A")
+				brd->bd_flags |= BD_FEP5PLUS;
+
+			return;
+		}
+		msleep_interruptible(10);
+		brd->wait_for_fep++;
+		word = readw(addr + FEPSTAT);
+	}
+
+	/* Gave up on board after too long of time taken */
+	err1 = readw(addr + SEQUENCE);
+	err2 = readw(addr + ERROR);
+	pr_warn("dgap: FEPOS for %s not functioning.  Error #(%x,%x).\n",
+		brd->name, err1, err2);
+	brd->state = BOARD_FAILED;
+	brd->dpastatus = BD_NOFEP;
+}
+
+/*
+ * Physically forces the FEP5 card to reset itself.
+ */
+static void dgap_do_reset_board(struct board_t *brd)
+{
+	uchar check;
+	u32 check1;
+	u32 check2;
+	int i = 0;
+
+	if (!brd || (brd->magic != DGAP_BOARD_MAGIC) ||
+	    !brd->re_map_membase || !brd->re_map_port)
+		return;
+
+	/* FEPRST does not vary among supported boards */
+	writeb(FEPRST, brd->re_map_port);
+
+	for (i = 0; i <= 1000; i++) {
+		check = readb(brd->re_map_port) & 0xe;
+		if (check == FEPRST)
+			break;
+		udelay(10);
+
+	}
+	if (i > 1000) {
+		pr_warn("dgap: Board not resetting...  Failing board.\n");
+		brd->state = BOARD_FAILED;
+		brd->dpastatus = BD_NOFEP;
+		return;
+	}
+
+	/*
+	 * Make sure there really is memory out there.
+	 */
+	writel(0xa55a3cc3, (brd->re_map_membase + LOWMEM));
+	writel(0x5aa5c33c, (brd->re_map_membase + HIGHMEM));
+	check1 = readl(brd->re_map_membase + LOWMEM);
+	check2 = readl(brd->re_map_membase + HIGHMEM);
+
+	if ((check1 != 0xa55a3cc3) || (check2 != 0x5aa5c33c)) {
+		pr_warn("dgap: No memory at %p for board.\n",
+			brd->re_map_membase);
+		brd->state = BOARD_FAILED;
+		brd->dpastatus = BD_NOFEP;
+		return;
+	}
+
+	if (brd->state != BOARD_FAILED)
+		brd->state = FINISHED_RESET;
+}
+
+#ifdef DIGI_CONCENTRATORS_SUPPORTED
+/*
+ * Sends a concentrator image into the FEP5 board.
+ */
+static void dgap_do_conc_load(struct board_t *brd, uchar *uaddr, int len)
+{
+	char *vaddr;
+	u16 offset = 0;
+	struct downld_t *to_dp;
+
+	if (!brd || (brd->magic != DGAP_BOARD_MAGIC) || !brd->re_map_membase)
+		return;
+
+	vaddr = brd->re_map_membase;
+
+	offset = readw((u16 *) (vaddr + DOWNREQ));
+	to_dp = (struct downld_t *) (vaddr + (int) offset);
+	memcpy_toio(to_dp, uaddr, len);
+
+	/* Tell card we have data for it */
+	writew(0, vaddr + (DOWNREQ));
+
+	brd->conc_dl_status = NO_PENDING_CONCENTRATOR_REQUESTS;
+}
+#endif
+
+#define EXPANSION_ROM_SIZE	(64 * 1024)
+#define FEP5_ROM_MAGIC		(0xFEFFFFFF)
+
+static void dgap_get_vpd(struct board_t *brd)
+{
+	u32 magic;
+	u32 base_offset;
+	u16 rom_offset;
+	u16 vpd_offset;
+	u16 image_length;
+	u16 i;
+	uchar byte1;
+	uchar byte2;
+
+	/*
+	 * Poke the magic number at the PCI Rom Address location.
+	 * If VPD is supported, the value read from that address
+	 * will be non-zero.
+	 */
+	magic = FEP5_ROM_MAGIC;
+	pci_write_config_dword(brd->pdev, PCI_ROM_ADDRESS, magic);
+	pci_read_config_dword(brd->pdev, PCI_ROM_ADDRESS, &magic);
+
+	/* VPD not supported, bail */
+	if (!magic)
+		return;
+
+	/*
+	 * To get to the OTPROM memory, we have to send the boards base
+	 * address or'ed with 1 into the PCI Rom Address location.
+	 */
+	magic = brd->membase | 0x01;
+	pci_write_config_dword(brd->pdev, PCI_ROM_ADDRESS, magic);
+	pci_read_config_dword(brd->pdev, PCI_ROM_ADDRESS, &magic);
+
+	byte1 = readb(brd->re_map_membase);
+	byte2 = readb(brd->re_map_membase + 1);
+
+	/*
+	 * If the board correctly swapped to the OTPROM memory,
+	 * the first 2 bytes (header) should be 0x55, 0xAA
+	 */
+	if (byte1 == 0x55 && byte2 == 0xAA) {
+
+		base_offset = 0;
+
+		/*
+		 * We have to run through all the OTPROM memory looking
+		 * for the VPD offset.
+		 */
+		while (base_offset <= EXPANSION_ROM_SIZE) {
+
+			/*
+			 * Lots of magic numbers here.
+			 *
+			 * The VPD offset is located inside the ROM Data Structure.
+			 * We also have to remember the length of each
+			 * ROM Data Structure, so we can "hop" to the next
+			 * entry if the VPD isn't in the current
+			 * ROM Data Structure.
+			 */
+			rom_offset = readw(brd->re_map_membase + base_offset + 0x18);
+			image_length = readw(brd->re_map_membase + rom_offset + 0x10) * 512;
+			vpd_offset = readw(brd->re_map_membase + rom_offset + 0x08);
+
+			/* Found the VPD entry */
+			if (vpd_offset)
+				break;
+
+			/* We didn't find a VPD entry, go to next ROM entry. */
+			base_offset += image_length;
+
+			byte1 = readb(brd->re_map_membase + base_offset);
+			byte2 = readb(brd->re_map_membase + base_offset + 1);
+
+			/*
+			 * If the new ROM offset doesn't have 0x55, 0xAA
+			 * as its header, we have run out of ROM.
+			 */
+			if (byte1 != 0x55 || byte2 != 0xAA)
+				break;
+		}
+
+		/*
+		 * If we have a VPD offset, then mark the board
+		 * as having a valid VPD, and copy VPDSIZE (512) bytes of
+		 * that VPD to the buffer we have in our board structure.
+		 */
+		if (vpd_offset) {
+			brd->bd_flags |= BD_HAS_VPD;
+			for (i = 0; i < VPDSIZE; i++)
+				brd->vpd[i] = readb(brd->re_map_membase + vpd_offset + i);
+		}
+	}
+
+	/*
+	 * We MUST poke the magic number at the PCI Rom Address location again.
+	 * This makes the card report the regular board memory back to us,
+	 * rather than the OTPROM memory.
+	 */
+	magic = FEP5_ROM_MAGIC;
+	pci_write_config_dword(brd->pdev, PCI_ROM_ADDRESS, magic);
+}
+
+/*
+ * Our board poller function.
+ */
+static void dgap_poll_tasklet(unsigned long data)
+{
+	struct board_t *bd = (struct board_t *) data;
+	ulong  lock_flags;
+	ulong  lock_flags2;
+	char *vaddr;
+	u16 head, tail;
+
+	if (!bd || (bd->magic != DGAP_BOARD_MAGIC))
+		return;
+
+	if (bd->inhibit_poller)
+		return;
+
+	DGAP_LOCK(bd->bd_lock, lock_flags);
+
+	vaddr = bd->re_map_membase;
+
+	/*
+	 * If board is ready, parse deeper to see if there is anything to do.
+	 */
+	if (bd->state == BOARD_READY) {
+
+		struct ev_t *eaddr = NULL;
+
+		if (!bd->re_map_membase) {
+			DGAP_UNLOCK(bd->bd_lock, lock_flags);
+			return;
+		}
+		if (!bd->re_map_port) {
+			DGAP_UNLOCK(bd->bd_lock, lock_flags);
+			return;
+		}
+
+		if (!bd->nasync)
+			goto out;
+
+		eaddr = (struct ev_t *) (vaddr + EVBUF);
+
+		/* Get our head and tail */
+		head = readw(&(eaddr->ev_head));
+		tail = readw(&(eaddr->ev_tail));
+
+		/*
+		 * If there is an event pending. Go service it.
+		 */
+		if (head != tail) {
+			DGAP_UNLOCK(bd->bd_lock, lock_flags);
+			dgap_event(bd);
+			DGAP_LOCK(bd->bd_lock, lock_flags);
+		}
+
+out:
+		/*
+		 * If board is doing interrupts, ACK the interrupt.
+		 */
+		if (bd && bd->intr_running)
+			readb(bd->re_map_port + 2);
+
+		DGAP_UNLOCK(bd->bd_lock, lock_flags);
+		return;
+	}
+
+	/* Our state machine to get the board up and running */
+
+	/* Reset board */
+	if (bd->state == NEED_RESET) {
+
+		/* Get VPD info */
+		dgap_get_vpd(bd);
+
+		dgap_do_reset_board(bd);
+	}
+
+	/* Move to next state */
+	if (bd->state == FINISHED_RESET)
+		bd->state = NEED_CONFIG;
+
+	if (bd->state == NEED_CONFIG) {
+		/*
+		 * Match this board to a config the user created for us.
+		 */
+		bd->bd_config = dgap_find_config(bd->type, bd->pci_bus, bd->pci_slot);
+
+		/*
+		 * Because the 4 port Xr products share the same PCI ID
+		 * as the 8 port Xr products, if we receive a NULL config
+		 * back, and this is a PAPORT8 board, retry with a
+		 * PAPORT4 attempt as well.
+		 */
+		if (bd->type == PAPORT8 && !bd->bd_config)
+			bd->bd_config = dgap_find_config(PAPORT4, bd->pci_bus, bd->pci_slot);
+
+		/*
+		 * Register the ttys (if any) into the kernel.
+		 */
+		if (bd->bd_config)
+			bd->state = FINISHED_CONFIG;
+		else
+			bd->state = CONFIG_NOT_FOUND;
+	}
+
+	/* Move to next state */
+	if (bd->state == FINISHED_CONFIG)
+		bd->state = NEED_DEVICE_CREATION;
+
+	/* Move to next state */
+	if (bd->state == NEED_DEVICE_CREATION) {
+		/*
+		 * Signal downloader, its got some work to do.
+		 */
+		DGAP_LOCK(dgap_dl_lock, lock_flags2);
+		if (dgap_dl_action != 1) {
+			dgap_dl_action = 1;
+			wake_up_interruptible(&dgap_dl_wait);
+		}
+		DGAP_UNLOCK(dgap_dl_lock, lock_flags2);
+	}
+
+	/* Move to next state */
+	if (bd->state == FINISHED_DEVICE_CREATION)
+		bd->state = NEED_BIOS_LOAD;
+
+	/* Move to next state */
+	if (bd->state == NEED_BIOS_LOAD) {
+		/*
+		 * Signal downloader, its got some work to do.
+		 */
+		DGAP_LOCK(dgap_dl_lock, lock_flags2);
+		if (dgap_dl_action != 1) {
+			dgap_dl_action = 1;
+			wake_up_interruptible(&dgap_dl_wait);
+		}
+		DGAP_UNLOCK(dgap_dl_lock, lock_flags2);
+	}
+
+	/* Wait for BIOS to test board... */
+	if (bd->state == WAIT_BIOS_LOAD)
+		dgap_do_wait_for_bios(bd);
+
+	/* Move to next state */
+	if (bd->state == FINISHED_BIOS_LOAD) {
+		bd->state = NEED_FEP_LOAD;
+
+		/*
+		 * Signal downloader, its got some work to do.
+		 */
+		DGAP_LOCK(dgap_dl_lock, lock_flags2);
+		if (dgap_dl_action != 1) {
+			dgap_dl_action = 1;
+			wake_up_interruptible(&dgap_dl_wait);
+		}
+		DGAP_UNLOCK(dgap_dl_lock, lock_flags2);
+	}
+
+	/* Wait for FEP to load on board... */
+	if (bd->state == WAIT_FEP_LOAD)
+		dgap_do_wait_for_fep(bd);
+
+	/* Move to next state */
+	if (bd->state == FINISHED_FEP_LOAD) {
+
+		/*
+		 * Do tty device initialization.
+		 */
+		int rc = dgap_tty_init(bd);
+
+		if (rc < 0) {
+			dgap_tty_uninit(bd);
+			bd->state = BOARD_FAILED;
+			bd->dpastatus = BD_NOFEP;
+		} else {
+			bd->state = NEED_PROC_CREATION;
+
+			/*
+			 * Signal downloader, its got some work to do.
+			 */
+			DGAP_LOCK(dgap_dl_lock, lock_flags2);
+			if (dgap_dl_action != 1) {
+				dgap_dl_action = 1;
+				wake_up_interruptible(&dgap_dl_wait);
+			}
+			DGAP_UNLOCK(dgap_dl_lock, lock_flags2);
+		}
+	}
+
+	/* Move to next state */
+	if (bd->state == FINISHED_PROC_CREATION) {
+
+		bd->state = BOARD_READY;
+		bd->dpastatus = BD_RUNNING;
+
+		/*
+		 * If user requested the board to run in interrupt mode,
+		 * go and set it up on the board.
+		 */
+		if (bd->intr_used) {
+			writew(1, (bd->re_map_membase + ENABLE_INTR));
+			/*
+			 * Tell the board to poll the UARTS as fast as possible.
+			 */
+			writew(FEPPOLL_MIN, (bd->re_map_membase + FEPPOLL));
+			bd->intr_running = 1;
+		}
+
+		/* Wake up anyone waiting for board state to change to ready */
+		wake_up_interruptible(&bd->state_wait);
+	}
+
+	DGAP_UNLOCK(bd->bd_lock, lock_flags);
+}
+
+/*=======================================================================
+ *
+ *      dgap_cmdb - Sends a 2 byte command to the FEP.
+ *
+ *              ch      - Pointer to channel structure.
+ *              cmd     - Command to be sent.
+ *              byte1   - Integer containing first byte to be sent.
+ *              byte2   - Integer containing second byte to be sent.
+ *              ncmds   - Wait until ncmds or fewer cmds are left
+ *                        in the cmd buffer before returning.
+ *
+ *=======================================================================*/
+static void dgap_cmdb(struct channel_t *ch, uchar cmd, uchar byte1, uchar byte2, uint ncmds)
+{
+	char		*vaddr = NULL;
+	struct cm_t	*cm_addr = NULL;
+	uint		count;
+	uint		n;
+	u16		head;
+	u16		tail;
+
+	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+		return;
+
+	/*
+	 * Check if board is still alive.
+	 */
+	if (ch->ch_bd->state == BOARD_FAILED)
+		return;
+
+	/*
+	 * Make sure the pointers are in range before
+	 * writing to the FEP memory.
+	 */
+	vaddr = ch->ch_bd->re_map_membase;
+
+	if (!vaddr)
+		return;
+
+	cm_addr = (struct cm_t *) (vaddr + CMDBUF);
+	head = readw(&(cm_addr->cm_head));
+
+	/*
+	 * Forget it if pointers out of range.
+	 */
+	if (head >= (CMDMAX - CMDSTART) || (head & 03)) {
+		ch->ch_bd->state = BOARD_FAILED;
+		return;
+	}
+
+	/*
+	 * Put the data in the circular command buffer.
+	 */
+	writeb(cmd, (char *) (vaddr + head + CMDSTART + 0));
+	writeb((uchar) ch->ch_portnum, (char *) (vaddr + head + CMDSTART + 1));
+	writeb(byte1, (char *) (vaddr + head + CMDSTART + 2));
+	writeb(byte2, (char *) (vaddr + head + CMDSTART + 3));
+
+	head = (head + 4) & (CMDMAX - CMDSTART - 4);
+
+	writew(head, &(cm_addr->cm_head));
+
+	/*
+	 * Wait if necessary before updating the head
+	 * pointer to limit the number of outstanding
+	 * commands to the FEP.   If the time spent waiting
+	 * is outlandish, declare the FEP dead.
+	 */
+	for (count = dgap_count ;;) {
+
+		head = readw(&(cm_addr->cm_head));
+		tail = readw(&(cm_addr->cm_tail));
+
+		n = (head - tail) & (CMDMAX - CMDSTART - 4);
+
+		if (n <= ncmds * sizeof(struct cm_t))
+			break;
+
+		if (--count == 0) {
+			ch->ch_bd->state = BOARD_FAILED;
+			return;
+		}
+		udelay(10);
+	}
+}
+
+/*=======================================================================
+ *
+ *      dgap_cmdw - Sends a 1 word command to the FEP.
+ *
+ *              ch      - Pointer to channel structure.
+ *              cmd     - Command to be sent.
+ *              word    - Integer containing word to be sent.
+ *              ncmds   - Wait until ncmds or fewer cmds are left
+ *                        in the cmd buffer before returning.
+ *
+ *=======================================================================*/
+static void dgap_cmdw(struct channel_t *ch, uchar cmd, u16 word, uint ncmds)
+{
+	char		*vaddr = NULL;
+	struct cm_t	*cm_addr = NULL;
+	uint		count;
+	uint		n;
+	u16		head;
+	u16		tail;
+
+	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+		return;
+
+	/*
+	 * Check if board is still alive.
+	 */
+	if (ch->ch_bd->state == BOARD_FAILED)
+		return;
+
+	/*
+	 * Make sure the pointers are in range before
+	 * writing to the FEP memory.
+	 */
+	vaddr = ch->ch_bd->re_map_membase;
+	if (!vaddr)
+		return;
+
+	cm_addr = (struct cm_t *) (vaddr + CMDBUF);
+	head = readw(&(cm_addr->cm_head));
+
+	/*
+	 * Forget it if pointers out of range.
+	 */
+	if (head >= (CMDMAX - CMDSTART) || (head & 03)) {
+		ch->ch_bd->state = BOARD_FAILED;
+		return;
+	}
+
+	/*
+	 * Put the data in the circular command buffer.
+	 */
+	writeb(cmd, (char *) (vaddr + head + CMDSTART + 0));
+	writeb((uchar) ch->ch_portnum, (char *) (vaddr + head + CMDSTART + 1));
+	writew((u16) word, (char *) (vaddr + head + CMDSTART + 2));
+
+	head = (head + 4) & (CMDMAX - CMDSTART - 4);
+
+	writew(head, &(cm_addr->cm_head));
+
+	/*
+	 * Wait if necessary before updating the head
+	 * pointer to limit the number of outstanding
+	 * commands to the FEP.   If the time spent waiting
+	 * is outlandish, declare the FEP dead.
+	 */
+	for (count = dgap_count ;;) {
+
+		head = readw(&(cm_addr->cm_head));
+		tail = readw(&(cm_addr->cm_tail));
+
+		n = (head - tail) & (CMDMAX - CMDSTART - 4);
+
+		if (n <= ncmds * sizeof(struct cm_t))
+			break;
+
+		if (--count == 0) {
+			ch->ch_bd->state = BOARD_FAILED;
+			return;
+		}
+		udelay(10);
+	}
+}
+
+/*=======================================================================
+ *
+ *      dgap_cmdw_ext - Sends a extended word command to the FEP.
+ *
+ *              ch      - Pointer to channel structure.
+ *              cmd     - Command to be sent.
+ *              word    - Integer containing word to be sent.
+ *              ncmds   - Wait until ncmds or fewer cmds are left
+ *                        in the cmd buffer before returning.
+ *
+ *=======================================================================*/
+static void dgap_cmdw_ext(struct channel_t *ch, u16 cmd, u16 word, uint ncmds)
+{
+	char		*vaddr = NULL;
+	struct cm_t	*cm_addr = NULL;
+	uint		count;
+	uint		n;
+	u16		head;
+	u16		tail;
+
+	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+		return;
+
+	/*
+	 * Check if board is still alive.
+	 */
+	if (ch->ch_bd->state == BOARD_FAILED)
+		return;
+
+	/*
+	 * Make sure the pointers are in range before
+	 * writing to the FEP memory.
+	 */
+	vaddr = ch->ch_bd->re_map_membase;
+	if (!vaddr)
+		return;
+
+	cm_addr = (struct cm_t *) (vaddr + CMDBUF);
+	head = readw(&(cm_addr->cm_head));
+
+	/*
+	 * Forget it if pointers out of range.
+	 */
+	if (head >= (CMDMAX - CMDSTART) || (head & 03)) {
+		ch->ch_bd->state = BOARD_FAILED;
+		return;
+	}
+
+	/*
+	 * Put the data in the circular command buffer.
+	 */
+
+	/* Write an FF to tell the FEP that we want an extended command */
+	writeb((uchar) 0xff, (char *) (vaddr + head + CMDSTART + 0));
+
+	writeb((uchar) ch->ch_portnum, (uchar *) (vaddr + head + CMDSTART + 1));
+	writew((u16) cmd, (char *) (vaddr + head + CMDSTART + 2));
+
+	/*
+	 * If the second part of the command won't fit,
+	 * put it at the beginning of the circular buffer.
+	 */
+	if (((head + 4) >= ((CMDMAX - CMDSTART)) || (head & 03)))
+		writew((u16) word, (char *) (vaddr + CMDSTART));
+	else
+		writew((u16) word, (char *) (vaddr + head + CMDSTART + 4));
+
+	head = (head + 8) & (CMDMAX - CMDSTART - 4);
+
+	writew(head, &(cm_addr->cm_head));
+
+	/*
+	 * Wait if necessary before updating the head
+	 * pointer to limit the number of outstanding
+	 * commands to the FEP.   If the time spent waiting
+	 * is outlandish, declare the FEP dead.
+	 */
+	for (count = dgap_count ;;) {
+
+		head = readw(&(cm_addr->cm_head));
+		tail = readw(&(cm_addr->cm_tail));
+
+		n = (head - tail) & (CMDMAX - CMDSTART - 4);
+
+		if (n <= ncmds * sizeof(struct cm_t))
+			break;
+
+		if (--count == 0) {
+			ch->ch_bd->state = BOARD_FAILED;
+			return;
+		}
+		udelay(10);
+	}
+}
+
+/*=======================================================================
+ *
+ *      dgap_wmove - Write data to FEP buffer.
+ *
+ *              ch      - Pointer to channel structure.
+ *              buf     - Poiter to characters to be moved.
+ *              cnt     - Number of characters to move.
+ *
+ *=======================================================================*/
+static void dgap_wmove(struct channel_t *ch, char *buf, uint cnt)
+{
+	int    n;
+	char   *taddr;
+	struct bs_t    *bs;
+	u16    head;
+
+	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+		return;
+
+	/*
+	 * Check parameters.
+	 */
+	bs   = ch->ch_bs;
+	head = readw(&(bs->tx_head));
+
+	/*
+	 * If pointers are out of range, just return.
+	 */
+	if ((cnt > ch->ch_tsize) ||
+	    (unsigned)(head - ch->ch_tstart) >= ch->ch_tsize)
+		return;
+
+	/*
+	 * If the write wraps over the top of the circular buffer,
+	 * move the portion up to the wrap point, and reset the
+	 * pointers to the bottom.
+	 */
+	n = ch->ch_tstart + ch->ch_tsize - head;
+
+	if (cnt >= n) {
+		cnt -= n;
+		taddr = ch->ch_taddr + head;
+		memcpy_toio(taddr, buf, n);
+		head = ch->ch_tstart;
+		buf += n;
+	}
+
+	/*
+	 * Move rest of data.
+	 */
+	taddr = ch->ch_taddr + head;
+	n = cnt;
+	memcpy_toio(taddr, buf, n);
+	head += cnt;
+
+	writew(head, &(bs->tx_head));
+}
+
+/*
+ * Retrives the current custom baud rate from FEP memory,
+ * and returns it back to the user.
+ * Returns 0 on error.
+ */
+static uint dgap_get_custom_baud(struct channel_t *ch)
+{
+	uchar *vaddr;
+	ulong offset = 0;
+	uint value = 0;
+
+	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+		return 0;
+
+	if (!ch->ch_bd || ch->ch_bd->magic != DGAP_BOARD_MAGIC)
+		return 0;
+
+	if (!(ch->ch_bd->bd_flags & BD_FEP5PLUS))
+		return 0;
+
+	vaddr = ch->ch_bd->re_map_membase;
+
+	if (!vaddr)
+		return 0;
+
+	/*
+	 * Go get from fep mem, what the fep
+	 * believes the custom baud rate is.
+	 */
+	offset = ((((*(unsigned short *)(vaddr + ECS_SEG)) << 4) +
+		(ch->ch_portnum * 0x28) + LINE_SPEED));
+
+	value = readw(vaddr + offset);
+	return value;
+}
+
+/*
+ * Calls the firmware to reset this channel.
+ */
+static void dgap_firmware_reset_port(struct channel_t *ch)
+{
+	dgap_cmdb(ch, CHRESET, 0, 0, 0);
+
+	/*
+	 * Now that the channel is reset, we need to make sure
+	 * all the current settings get reapplied to the port
+	 * in the firmware.
+	 *
+	 * So we will set the driver's cache of firmware
+	 * settings all to 0, and then call param.
+	 */
+	ch->ch_fepiflag = 0;
+	ch->ch_fepcflag = 0;
+	ch->ch_fepoflag = 0;
+	ch->ch_fepstartc = 0;
+	ch->ch_fepstopc = 0;
+	ch->ch_fepastartc = 0;
+	ch->ch_fepastopc = 0;
+	ch->ch_mostat = 0;
+	ch->ch_hflow = 0;
+}
+
+/*=======================================================================
+ *
+ *      dgap_param - Set Digi parameters.
+ *
+ *              struct tty_struct *     - TTY for port.
+ *
+ *=======================================================================*/
+static int dgap_param(struct tty_struct *tty)
+{
+	struct ktermios *ts;
+	struct board_t *bd;
+	struct channel_t *ch;
+	struct bs_t   *bs;
+	struct un_t   *un;
+	u16	head;
+	u16	cflag;
+	u16	iflag;
+	uchar	mval;
+	uchar	hflow;
+
+	if (!tty || tty->magic != TTY_MAGIC)
+		return -ENXIO;
+
+	un = (struct un_t *) tty->driver_data;
+	if (!un || un->magic != DGAP_UNIT_MAGIC)
+		return -ENXIO;
+
+	ch = un->un_ch;
+	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+		return -ENXIO;
+
+	bd = ch->ch_bd;
+	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
+		return -ENXIO;
+
+	bs = ch->ch_bs;
+	if (!bs)
+		return -ENXIO;
+
+	ts = &tty->termios;
+
+	/*
+	 * If baud rate is zero, flush queues, and set mval to drop DTR.
+	 */
+	if ((ch->ch_c_cflag & (CBAUD)) == 0) {
+
+		/* flush rx */
+		head = readw(&(ch->ch_bs->rx_head));
+		writew(head, &(ch->ch_bs->rx_tail));
+
+		/* flush tx */
+		head = readw(&(ch->ch_bs->tx_head));
+		writew(head, &(ch->ch_bs->tx_tail));
+
+		ch->ch_flags |= (CH_BAUD0);
+
+		/* Drop RTS and DTR */
+		ch->ch_mval &= ~(D_RTS(ch)|D_DTR(ch));
+		mval = D_DTR(ch) | D_RTS(ch);
+		ch->ch_baud_info = 0;
+
+	} else if (ch->ch_custom_speed && (bd->bd_flags & BD_FEP5PLUS)) {
+		/*
+		 * Tell the fep to do the command
+		 */
+
+		dgap_cmdw_ext(ch, 0xff01, ch->ch_custom_speed, 0);
+
+		/*
+		 * Now go get from fep mem, what the fep
+		 * believes the custom baud rate is.
+		 */
+		ch->ch_baud_info = ch->ch_custom_speed = dgap_get_custom_baud(ch);
+
+		/* Handle transition from B0 */
+		if (ch->ch_flags & CH_BAUD0) {
+			ch->ch_flags &= ~(CH_BAUD0);
+			ch->ch_mval |= (D_RTS(ch)|D_DTR(ch));
+		}
+		mval = D_DTR(ch) | D_RTS(ch);
+
+	} else {
+		/*
+		 * Set baud rate, character size, and parity.
+		 */
+
+
+		int iindex = 0;
+		int jindex = 0;
+		int baud = 0;
+
+		ulong bauds[4][16] = {
+			{ /* slowbaud */
+				0,	50,	75,	110,
+				134,	150,	200,	300,
+				600,	1200,	1800,	2400,
+				4800,	9600,	19200,	38400 },
+			{ /* slowbaud & CBAUDEX */
+				0,	57600,	115200,	230400,
+				460800,	150,	200,	921600,
+				600,	1200,	1800,	2400,
+				4800,	9600,	19200,	38400 },
+			{ /* fastbaud */
+				0,	57600,	76800,	115200,
+				14400,	57600,	230400,	76800,
+				115200,	230400,	28800,	460800,
+				921600,	9600,	19200,	38400 },
+			{ /* fastbaud & CBAUDEX */
+				0,	57600,	115200,	230400,
+				460800,	150,	200,	921600,
+				600,	1200,	1800,	2400,
+				4800,	9600,	19200,	38400 }
+		};
+
+		/* Only use the TXPrint baud rate if the terminal unit is NOT open */
+		if (!(ch->ch_tun.un_flags & UN_ISOPEN) && (un->un_type == DGAP_PRINT))
+			baud = C_BAUD(ch->ch_pun.un_tty) & 0xff;
+		else
+			baud = C_BAUD(ch->ch_tun.un_tty) & 0xff;
+
+		if (ch->ch_c_cflag & CBAUDEX)
+			iindex = 1;
+
+		if (ch->ch_digi.digi_flags & DIGI_FAST)
+			iindex += 2;
+
+		jindex = baud;
+
+		if ((iindex >= 0) && (iindex < 4) &&
+		    (jindex >= 0) && (jindex < 16))
+			baud = bauds[iindex][jindex];
+		else
+			baud = 0;
+
+		if (baud == 0)
+			baud = 9600;
+
+		ch->ch_baud_info = baud;
+
+		/*
+		 * CBAUD has bit position 0x1000 set these days to indicate Linux
+		 * baud rate remap.
+		 * We use a different bit assignment for high speed.  Clear this
+		 * bit out while grabbing the parts of "cflag" we want.
+		 */
+		cflag = ch->ch_c_cflag & ((CBAUD ^ CBAUDEX) | PARODD | PARENB | CSTOPB | CSIZE);
+
+		/*
+		 * HUPCL bit is used by FEP to indicate fast baud
+		 * table is to be used.
+		 */
+		if ((ch->ch_digi.digi_flags & DIGI_FAST) || (ch->ch_c_cflag & CBAUDEX))
+			cflag |= HUPCL;
+
+		if ((ch->ch_c_cflag & CBAUDEX) && !(ch->ch_digi.digi_flags & DIGI_FAST)) {
+		/*
+		 * The below code is trying to guarantee that only baud rates
+		 * 115200, 230400, 460800, 921600 are remapped.  We use exclusive or
+		 * because the various baud rates share common bit positions
+		 * and therefore can't be tested for easily.
+		 */
+			tcflag_t tcflag = (ch->ch_c_cflag & CBAUD) | CBAUDEX;
+			int baudpart = 0;
+
+			/* Map high speed requests to index into FEP's baud table */
+			switch (tcflag) {
+			case B57600:
+				baudpart = 1;
+				break;
+#ifdef B76800
+			case B76800:
+				baudpart = 2;
+				break;
+#endif
+			case B115200:
+				baudpart = 3;
+				break;
+			case B230400:
+				baudpart = 9;
+				break;
+			case B460800:
+				baudpart = 11;
+				break;
+#ifdef B921600
+			case B921600:
+				baudpart = 12;
+				break;
+#endif
+			default:
+				baudpart = 0;
+			}
+
+			if (baudpart)
+				cflag = (cflag & ~(CBAUD | CBAUDEX)) | baudpart;
+		}
+
+		cflag &= 0xffff;
+
+		if (cflag != ch->ch_fepcflag) {
+			ch->ch_fepcflag = (u16) (cflag & 0xffff);
+
+			/* Okay to have channel and board locks held calling this */
+			dgap_cmdw(ch, SCFLAG, (u16) cflag, 0);
+		}
+
+		/* Handle transition from B0 */
+		if (ch->ch_flags & CH_BAUD0) {
+			ch->ch_flags &= ~(CH_BAUD0);
+			ch->ch_mval |= (D_RTS(ch)|D_DTR(ch));
+		}
+		mval = D_DTR(ch) | D_RTS(ch);
+	}
+
+	/*
+	 * Get input flags.
+	 */
+	iflag = ch->ch_c_iflag & (IGNBRK | BRKINT | IGNPAR | PARMRK | INPCK | ISTRIP | IXON | IXANY | IXOFF);
+
+	if ((ch->ch_startc == _POSIX_VDISABLE) || (ch->ch_stopc == _POSIX_VDISABLE)) {
+		iflag &= ~(IXON | IXOFF);
+		ch->ch_c_iflag &= ~(IXON | IXOFF);
+	}
+
+	/*
+	 * Only the IBM Xr card can switch between
+	 * 232 and 422 modes on the fly
+	 */
+	if (bd->device == PCI_DEVICE_XR_IBM_DID) {
+		if (ch->ch_digi.digi_flags & DIGI_422)
+			dgap_cmdb(ch, SCOMMODE, MODE_422, 0, 0);
+		else
+			dgap_cmdb(ch, SCOMMODE, MODE_232, 0, 0);
+	}
+
+	if (ch->ch_digi.digi_flags & DIGI_ALTPIN)
+		iflag |= IALTPIN;
+
+	if (iflag != ch->ch_fepiflag) {
+		ch->ch_fepiflag = iflag;
+
+		/* Okay to have channel and board locks held calling this */
+		dgap_cmdw(ch, SIFLAG, (u16) ch->ch_fepiflag, 0);
+	}
+
+	/*
+	 * Select hardware handshaking.
+	 */
+	hflow = 0;
+
+	if (ch->ch_c_cflag & CRTSCTS)
+		hflow |= (D_RTS(ch) | D_CTS(ch));
+	if (ch->ch_digi.digi_flags & RTSPACE)
+		hflow |= D_RTS(ch);
+	if (ch->ch_digi.digi_flags & DTRPACE)
+		hflow |= D_DTR(ch);
+	if (ch->ch_digi.digi_flags & CTSPACE)
+		hflow |= D_CTS(ch);
+	if (ch->ch_digi.digi_flags & DSRPACE)
+		hflow |= D_DSR(ch);
+	if (ch->ch_digi.digi_flags & DCDPACE)
+		hflow |= D_CD(ch);
+
+	if (hflow != ch->ch_hflow) {
+		ch->ch_hflow = hflow;
+
+		/* Okay to have channel and board locks held calling this */
+		dgap_cmdb(ch, SHFLOW, (uchar) hflow, 0xff, 0);
+	}
+
+
+	/*
+	 * Set RTS and/or DTR Toggle if needed, but only if product is FEP5+ based.
+	 */
+	if (bd->bd_flags & BD_FEP5PLUS) {
+		u16 hflow2 = 0;
+		if (ch->ch_digi.digi_flags & DIGI_RTS_TOGGLE)
+			hflow2 |= (D_RTS(ch));
+		if (ch->ch_digi.digi_flags & DIGI_DTR_TOGGLE)
+			hflow2 |= (D_DTR(ch));
+
+		dgap_cmdw_ext(ch, 0xff03, hflow2, 0);
+	}
+
+	/*
+	 * Set modem control lines.
+	 */
+
+	mval ^= ch->ch_mforce & (mval ^ ch->ch_mval);
+
+	if (ch->ch_mostat ^ mval) {
+		ch->ch_mostat = mval;
+
+		/* Okay to have channel and board locks held calling this */
+		dgap_cmdb(ch, SMODEM, (uchar) mval, D_RTS(ch)|D_DTR(ch), 0);
+	}
+
+	/*
+	 * Read modem signals, and then call carrier function.
+	 */
+	ch->ch_mistat = readb(&(bs->m_stat));
+	dgap_carrier(ch);
+
+	/*
+	 * Set the start and stop characters.
+	 */
+	if (ch->ch_startc != ch->ch_fepstartc || ch->ch_stopc != ch->ch_fepstopc) {
+		ch->ch_fepstartc = ch->ch_startc;
+		ch->ch_fepstopc =  ch->ch_stopc;
+
+		/* Okay to have channel and board locks held calling this */
+		dgap_cmdb(ch, SFLOWC, ch->ch_fepstartc, ch->ch_fepstopc, 0);
+	}
+
+	/*
+	 * Set the Auxiliary start and stop characters.
+	 */
+	if (ch->ch_astartc != ch->ch_fepastartc || ch->ch_astopc != ch->ch_fepastopc) {
+		ch->ch_fepastartc = ch->ch_astartc;
+		ch->ch_fepastopc = ch->ch_astopc;
+
+		/* Okay to have channel and board locks held calling this */
+		dgap_cmdb(ch, SAFLOWC, ch->ch_fepastartc, ch->ch_fepastopc, 0);
+	}
+
+	return 0;
+}
+
+/*
+ * dgap_parity_scan()
+ *
+ * Convert the FEP5 way of reporting parity errors and breaks into
+ * the Linux line discipline way.
+ */
+static void dgap_parity_scan(struct channel_t *ch, unsigned char *cbuf, unsigned char *fbuf, int *len)
+{
+	int l = *len;
+	int count = 0;
+	unsigned char *in, *cout, *fout;
+	unsigned char c;
+
+	in = cbuf;
+	cout = cbuf;
+	fout = fbuf;
+
+	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+		return;
+
+	while (l--) {
+		c = *in++;
+		switch (ch->pscan_state) {
+		default:
+			/* reset to sanity and fall through */
+			ch->pscan_state = 0;
+
+		case 0:
+			/* No FF seen yet */
+			if (c == (unsigned char) '\377')
+				/* delete this character from stream */
+				ch->pscan_state = 1;
+			else {
+				*cout++ = c;
+				*fout++ = TTY_NORMAL;
+				count += 1;
+			}
+			break;
+
+		case 1:
+			/* first FF seen */
+			if (c == (unsigned char) '\377') {
+				/* doubled ff, transform to single ff */
+				*cout++ = c;
+				*fout++ = TTY_NORMAL;
+				count += 1;
+				ch->pscan_state = 0;
+			} else {
+				/* save value examination in next state */
+				ch->pscan_savechar = c;
+				ch->pscan_state = 2;
+			}
+			break;
+
+		case 2:
+			/* third character of ff sequence */
+
+			*cout++ = c;
+
+			if (ch->pscan_savechar == 0x0) {
+
+				if (c == 0x0) {
+					ch->ch_err_break++;
+					*fout++ = TTY_BREAK;
+				} else {
+					ch->ch_err_parity++;
+					*fout++ = TTY_PARITY;
+				}
+			}
+
+			count += 1;
+			ch->pscan_state = 0;
+		}
+	}
+	*len = count;
+}
+
+/*=======================================================================
+ *
+ *      dgap_event - FEP to host event processing routine.
+ *
+ *              bd     - Board of current event.
+ *
+ *=======================================================================*/
+static int dgap_event(struct board_t *bd)
+{
+	struct channel_t *ch;
+	ulong		lock_flags;
+	ulong		lock_flags2;
+	struct bs_t	*bs;
+	uchar		*event;
+	uchar		*vaddr = NULL;
+	struct ev_t	*eaddr = NULL;
+	uint		head;
+	uint		tail;
+	int		port;
+	int		reason;
+	int		modem;
+	int		b1;
+
+	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
+		return -ENXIO;
+
+	DGAP_LOCK(bd->bd_lock, lock_flags);
+
+	vaddr = bd->re_map_membase;
+
+	if (!vaddr) {
+		DGAP_UNLOCK(bd->bd_lock, lock_flags);
+		return -ENXIO;
+	}
+
+	eaddr = (struct ev_t *) (vaddr + EVBUF);
+
+	/* Get our head and tail */
+	head = readw(&(eaddr->ev_head));
+	tail = readw(&(eaddr->ev_tail));
+
+	/*
+	 * Forget it if pointers out of range.
+	 */
+
+	if (head >= EVMAX - EVSTART || tail >= EVMAX - EVSTART ||
+	    (head | tail) & 03) {
+		/* Let go of board lock */
+		DGAP_UNLOCK(bd->bd_lock, lock_flags);
+		return -ENXIO;
+	}
+
+	/*
+	 * Loop to process all the events in the buffer.
+	 */
+	while (tail != head) {
+
+		/*
+		 * Get interrupt information.
+		 */
+
+		event = bd->re_map_membase + tail + EVSTART;
+
+		port   = event[0];
+		reason = event[1];
+		modem  = event[2];
+		b1     = event[3];
+
+		/*
+		 * Make sure the interrupt is valid.
+		 */
+		if (port >= bd->nasync)
+			goto next;
+
+		if (!(reason & (IFMODEM | IFBREAK | IFTLW | IFTEM | IFDATA)))
+			goto next;
+
+		ch = bd->channels[port];
+
+		if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+			goto next;
+
+		/*
+		 * If we have made it here, the event was valid.
+		 * Lock down the channel.
+		 */
+		DGAP_LOCK(ch->ch_lock, lock_flags2);
+
+		bs = ch->ch_bs;
+
+		if (!bs) {
+			DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+			goto next;
+		}
+
+		/*
+		 * Process received data.
+		 */
+		if (reason & IFDATA) {
+
+			/*
+			 * ALL LOCKS *MUST* BE DROPPED BEFORE CALLING INPUT!
+			 * input could send some data to ld, which in turn
+			 * could do a callback to one of our other functions.
+			 */
+			DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+			DGAP_UNLOCK(bd->bd_lock, lock_flags);
+
+			dgap_input(ch);
+
+			DGAP_LOCK(bd->bd_lock, lock_flags);
+			DGAP_LOCK(ch->ch_lock, lock_flags2);
+
+			if (ch->ch_flags & CH_RACTIVE)
+				ch->ch_flags |= CH_RENABLE;
+			else
+				writeb(1, &(bs->idata));
+
+			if (ch->ch_flags & CH_RWAIT) {
+				ch->ch_flags &= ~CH_RWAIT;
+
+				wake_up_interruptible(&ch->ch_tun.un_flags_wait);
+			}
+		}
+
+		/*
+		 * Process Modem change signals.
+		 */
+		if (reason & IFMODEM) {
+			ch->ch_mistat = modem;
+			dgap_carrier(ch);
+		}
+
+		/*
+		 * Process break.
+		 */
+		if (reason & IFBREAK) {
+
+			if (ch->ch_tun.un_tty) {
+				/* A break has been indicated */
+				ch->ch_err_break++;
+				tty_buffer_request_room(ch->ch_tun.un_tty->port, 1);
+				tty_insert_flip_char(ch->ch_tun.un_tty->port, 0, TTY_BREAK);
+				tty_flip_buffer_push(ch->ch_tun.un_tty->port);
+			}
+		}
+
+		/*
+		 * Process Transmit low.
+		 */
+		if (reason & IFTLW) {
+
+			if (ch->ch_tun.un_flags & UN_LOW) {
+				ch->ch_tun.un_flags &= ~UN_LOW;
+
+				if (ch->ch_tun.un_flags & UN_ISOPEN) {
+					if ((ch->ch_tun.un_tty->flags &
+					   (1 << TTY_DO_WRITE_WAKEUP)) &&
+						ch->ch_tun.un_tty->ldisc->ops->write_wakeup) {
+						DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+						DGAP_UNLOCK(bd->bd_lock, lock_flags);
+						(ch->ch_tun.un_tty->ldisc->ops->write_wakeup)(ch->ch_tun.un_tty);
+						DGAP_LOCK(bd->bd_lock, lock_flags);
+						DGAP_LOCK(ch->ch_lock, lock_flags2);
+					}
+					wake_up_interruptible(&ch->ch_tun.un_tty->write_wait);
+					wake_up_interruptible(&ch->ch_tun.un_flags_wait);
+				}
+			}
+
+			if (ch->ch_pun.un_flags & UN_LOW) {
+				ch->ch_pun.un_flags &= ~UN_LOW;
+				if (ch->ch_pun.un_flags & UN_ISOPEN) {
+					if ((ch->ch_pun.un_tty->flags &
+					   (1 << TTY_DO_WRITE_WAKEUP)) &&
+						ch->ch_pun.un_tty->ldisc->ops->write_wakeup) {
+						DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+						DGAP_UNLOCK(bd->bd_lock, lock_flags);
+						(ch->ch_pun.un_tty->ldisc->ops->write_wakeup)(ch->ch_pun.un_tty);
+						DGAP_LOCK(bd->bd_lock, lock_flags);
+						DGAP_LOCK(ch->ch_lock, lock_flags2);
+					}
+					wake_up_interruptible(&ch->ch_pun.un_tty->write_wait);
+					wake_up_interruptible(&ch->ch_pun.un_flags_wait);
+				}
+			}
+
+			if (ch->ch_flags & CH_WLOW) {
+				ch->ch_flags &= ~CH_WLOW;
+				wake_up_interruptible(&ch->ch_flags_wait);
+			}
+		}
+
+		/*
+		 * Process Transmit empty.
+		 */
+		if (reason & IFTEM) {
+			if (ch->ch_tun.un_flags & UN_EMPTY) {
+				ch->ch_tun.un_flags &= ~UN_EMPTY;
+				if (ch->ch_tun.un_flags & UN_ISOPEN) {
+					if ((ch->ch_tun.un_tty->flags &
+					   (1 << TTY_DO_WRITE_WAKEUP)) &&
+						ch->ch_tun.un_tty->ldisc->ops->write_wakeup) {
+						DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+						DGAP_UNLOCK(bd->bd_lock, lock_flags);
+
+						(ch->ch_tun.un_tty->ldisc->ops->write_wakeup)(ch->ch_tun.un_tty);
+						DGAP_LOCK(bd->bd_lock, lock_flags);
+						DGAP_LOCK(ch->ch_lock, lock_flags2);
+					}
+					wake_up_interruptible(&ch->ch_tun.un_tty->write_wait);
+					wake_up_interruptible(&ch->ch_tun.un_flags_wait);
+				}
+			}
+
+			if (ch->ch_pun.un_flags & UN_EMPTY) {
+				ch->ch_pun.un_flags &= ~UN_EMPTY;
+				if (ch->ch_pun.un_flags & UN_ISOPEN) {
+					if ((ch->ch_pun.un_tty->flags &
+					   (1 << TTY_DO_WRITE_WAKEUP)) &&
+						ch->ch_pun.un_tty->ldisc->ops->write_wakeup) {
+						DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+						DGAP_UNLOCK(bd->bd_lock, lock_flags);
+						(ch->ch_pun.un_tty->ldisc->ops->write_wakeup)(ch->ch_pun.un_tty);
+						DGAP_LOCK(bd->bd_lock, lock_flags);
+						DGAP_LOCK(ch->ch_lock, lock_flags2);
+					}
+					wake_up_interruptible(&ch->ch_pun.un_tty->write_wait);
+					wake_up_interruptible(&ch->ch_pun.un_flags_wait);
+				}
+			}
+
+
+			if (ch->ch_flags & CH_WEMPTY) {
+				ch->ch_flags &= ~CH_WEMPTY;
+				wake_up_interruptible(&ch->ch_flags_wait);
+			}
+		}
+
+		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
+
+next:
+		tail = (tail + 4) & (EVMAX - EVSTART - 4);
+	}
+
+	writew(tail, &(eaddr->ev_tail));
+	DGAP_UNLOCK(bd->bd_lock, lock_flags);
+
+	return 0;
+}
+
+static ssize_t dgap_driver_version_show(struct device_driver *ddp, char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%s\n", DG_PART);
+}
+static DRIVER_ATTR(version, S_IRUSR, dgap_driver_version_show, NULL);
+
+
+static ssize_t dgap_driver_boards_show(struct device_driver *ddp, char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%d\n", dgap_NumBoards);
+}
+static DRIVER_ATTR(boards, S_IRUSR, dgap_driver_boards_show, NULL);
+
+
+static ssize_t dgap_driver_maxboards_show(struct device_driver *ddp, char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%d\n", MAXBOARDS);
+}
+static DRIVER_ATTR(maxboards, S_IRUSR, dgap_driver_maxboards_show, NULL);
+
+
+static ssize_t dgap_driver_pollcounter_show(struct device_driver *ddp, char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%ld\n", dgap_poll_counter);
+}
+static DRIVER_ATTR(pollcounter, S_IRUSR, dgap_driver_pollcounter_show, NULL);
+
+
+static ssize_t dgap_driver_state_show(struct device_driver *ddp, char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%s\n", dgap_driver_state_text[dgap_driver_state]);
+}
+static DRIVER_ATTR(state, S_IRUSR, dgap_driver_state_show, NULL);
+
+static ssize_t dgap_driver_rawreadok_show(struct device_driver *ddp, char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "0x%x\n", dgap_rawreadok);
+}
+
+static ssize_t dgap_driver_rawreadok_store(struct device_driver *ddp, const char *buf, size_t count)
+{
+	sscanf(buf, "0x%x\n", &dgap_rawreadok);
+	return count;
+}
+static DRIVER_ATTR(rawreadok, (S_IRUSR | S_IWUSR), dgap_driver_rawreadok_show, dgap_driver_rawreadok_store);
+
+
+static ssize_t dgap_driver_pollrate_show(struct device_driver *ddp, char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%dms\n", dgap_poll_tick);
+}
+
+static ssize_t dgap_driver_pollrate_store(struct device_driver *ddp, const char *buf, size_t count)
+{
+	sscanf(buf, "%d\n", &dgap_poll_tick);
+	return count;
+}
+static DRIVER_ATTR(pollrate, (S_IRUSR | S_IWUSR), dgap_driver_pollrate_show, dgap_driver_pollrate_store);
+
+static void dgap_create_driver_sysfiles(struct pci_driver *dgap_driver)
+{
+	int rc = 0;
+	struct device_driver *driverfs = &dgap_driver->driver;
+
+	rc |= driver_create_file(driverfs, &driver_attr_version);
+	rc |= driver_create_file(driverfs, &driver_attr_boards);
+	rc |= driver_create_file(driverfs, &driver_attr_maxboards);
+	rc |= driver_create_file(driverfs, &driver_attr_rawreadok);
+	rc |= driver_create_file(driverfs, &driver_attr_pollrate);
+	rc |= driver_create_file(driverfs, &driver_attr_pollcounter);
+	rc |= driver_create_file(driverfs, &driver_attr_state);
+	if (rc)
+		printk(KERN_ERR "DGAP: sysfs driver_create_file failed!\n");
+}
+
+static void dgap_remove_driver_sysfiles(struct pci_driver *dgap_driver)
+{
+	struct device_driver *driverfs = &dgap_driver->driver;
+	driver_remove_file(driverfs, &driver_attr_version);
+	driver_remove_file(driverfs, &driver_attr_boards);
+	driver_remove_file(driverfs, &driver_attr_maxboards);
+	driver_remove_file(driverfs, &driver_attr_rawreadok);
+	driver_remove_file(driverfs, &driver_attr_pollrate);
+	driver_remove_file(driverfs, &driver_attr_pollcounter);
+	driver_remove_file(driverfs, &driver_attr_state);
+}
+
+#define DGAP_VERIFY_BOARD(p, bd)			\
+	if (!p)						\
+		return 0;				\
+							\
+	bd = dev_get_drvdata(p);			\
+	if (!bd || bd->magic != DGAP_BOARD_MAGIC)	\
+		return 0;				\
+	if (bd->state != BOARD_READY)			\
+		return 0;				\
+
+static ssize_t dgap_ports_state_show(struct device *p, struct device_attribute *attr, char *buf)
+{
+	struct board_t *bd;
+	int count = 0;
+	int i = 0;
+
+	DGAP_VERIFY_BOARD(p, bd);
+
+	for (i = 0; i < bd->nasync; i++) {
+		count += snprintf(buf + count, PAGE_SIZE - count,
+			"%d %s\n", bd->channels[i]->ch_portnum,
+			bd->channels[i]->ch_open_count ? "Open" : "Closed");
+	}
+	return count;
+}
+static DEVICE_ATTR(ports_state, S_IRUSR, dgap_ports_state_show, NULL);
+
+static ssize_t dgap_ports_baud_show(struct device *p, struct device_attribute *attr, char *buf)
+{
+	struct board_t *bd;
+	int count = 0;
+	int i = 0;
+
+	DGAP_VERIFY_BOARD(p, bd);
+
+	for (i = 0; i < bd->nasync; i++) {
+		count +=  snprintf(buf + count, PAGE_SIZE - count,
+			"%d %d\n", bd->channels[i]->ch_portnum, bd->channels[i]->ch_baud_info);
+	}
+	return count;
+}
+static DEVICE_ATTR(ports_baud, S_IRUSR, dgap_ports_baud_show, NULL);
+
+static ssize_t dgap_ports_msignals_show(struct device *p, struct device_attribute *attr, char *buf)
+{
+	struct board_t *bd;
+	int count = 0;
+	int i = 0;
+
+	DGAP_VERIFY_BOARD(p, bd);
+
+	for (i = 0; i < bd->nasync; i++) {
+		if (bd->channels[i]->ch_open_count)
+			count += snprintf(buf + count, PAGE_SIZE - count,
+				"%d %s %s %s %s %s %s\n", bd->channels[i]->ch_portnum,
+				(bd->channels[i]->ch_mostat & UART_MCR_RTS) ? "RTS" : "",
+				(bd->channels[i]->ch_mistat & UART_MSR_CTS) ? "CTS" : "",
+				(bd->channels[i]->ch_mostat & UART_MCR_DTR) ? "DTR" : "",
+				(bd->channels[i]->ch_mistat & UART_MSR_DSR) ? "DSR" : "",
+				(bd->channels[i]->ch_mistat & UART_MSR_DCD) ? "DCD" : "",
+				(bd->channels[i]->ch_mistat & UART_MSR_RI)  ? "RI"  : "");
+		else
+			count += snprintf(buf + count, PAGE_SIZE - count,
+				"%d\n", bd->channels[i]->ch_portnum);
+	}
+	return count;
+}
+static DEVICE_ATTR(ports_msignals, S_IRUSR, dgap_ports_msignals_show, NULL);
+
+static ssize_t dgap_ports_iflag_show(struct device *p, struct device_attribute *attr, char *buf)
+{
+	struct board_t *bd;
+	int count = 0;
+	int i = 0;
+
+	DGAP_VERIFY_BOARD(p, bd);
+
+	for (i = 0; i < bd->nasync; i++)
+		count += snprintf(buf + count, PAGE_SIZE - count, "%d %x\n",
+			bd->channels[i]->ch_portnum, bd->channels[i]->ch_c_iflag);
+	return count;
+}
+static DEVICE_ATTR(ports_iflag, S_IRUSR, dgap_ports_iflag_show, NULL);
+
+static ssize_t dgap_ports_cflag_show(struct device *p, struct device_attribute *attr, char *buf)
+{
+	struct board_t *bd;
+	int count = 0;
+	int i = 0;
+
+	DGAP_VERIFY_BOARD(p, bd);
+
+	for (i = 0; i < bd->nasync; i++)
+		count += snprintf(buf + count, PAGE_SIZE - count, "%d %x\n",
+			bd->channels[i]->ch_portnum, bd->channels[i]->ch_c_cflag);
+	return count;
+}
+static DEVICE_ATTR(ports_cflag, S_IRUSR, dgap_ports_cflag_show, NULL);
+
+static ssize_t dgap_ports_oflag_show(struct device *p, struct device_attribute *attr, char *buf)
+{
+	struct board_t *bd;
+	int count = 0;
+	int i = 0;
+
+	DGAP_VERIFY_BOARD(p, bd);
+
+	for (i = 0; i < bd->nasync; i++)
+		count += snprintf(buf + count, PAGE_SIZE - count, "%d %x\n",
+			bd->channels[i]->ch_portnum, bd->channels[i]->ch_c_oflag);
+	return count;
+}
+static DEVICE_ATTR(ports_oflag, S_IRUSR, dgap_ports_oflag_show, NULL);
+
+static ssize_t dgap_ports_lflag_show(struct device *p, struct device_attribute *attr, char *buf)
+{
+	struct board_t *bd;
+	int count = 0;
+	int i = 0;
+
+	DGAP_VERIFY_BOARD(p, bd);
+
+	for (i = 0; i < bd->nasync; i++)
+		count += snprintf(buf + count, PAGE_SIZE - count, "%d %x\n",
+			bd->channels[i]->ch_portnum, bd->channels[i]->ch_c_lflag);
+	return count;
+}
+static DEVICE_ATTR(ports_lflag, S_IRUSR, dgap_ports_lflag_show, NULL);
+
+static ssize_t dgap_ports_digi_flag_show(struct device *p, struct device_attribute *attr, char *buf)
+{
+	struct board_t *bd;
+	int count = 0;
+	int i = 0;
+
+	DGAP_VERIFY_BOARD(p, bd);
+
+	for (i = 0; i < bd->nasync; i++)
+		count += snprintf(buf + count, PAGE_SIZE - count, "%d %x\n",
+			bd->channels[i]->ch_portnum, bd->channels[i]->ch_digi.digi_flags);
+	return count;
+}
+static DEVICE_ATTR(ports_digi_flag, S_IRUSR, dgap_ports_digi_flag_show, NULL);
+
+static ssize_t dgap_ports_rxcount_show(struct device *p, struct device_attribute *attr, char *buf)
+{
+	struct board_t *bd;
+	int count = 0;
+	int i = 0;
+
+	DGAP_VERIFY_BOARD(p, bd);
+
+	for (i = 0; i < bd->nasync; i++)
+		count += snprintf(buf + count, PAGE_SIZE - count, "%d %ld\n",
+			bd->channels[i]->ch_portnum, bd->channels[i]->ch_rxcount);
+	return count;
+}
+static DEVICE_ATTR(ports_rxcount, S_IRUSR, dgap_ports_rxcount_show, NULL);
+
+static ssize_t dgap_ports_txcount_show(struct device *p, struct device_attribute *attr, char *buf)
+{
+	struct board_t *bd;
+	int count = 0;
+	int i = 0;
+
+	DGAP_VERIFY_BOARD(p, bd);
+
+	for (i = 0; i < bd->nasync; i++)
+		count += snprintf(buf + count, PAGE_SIZE - count, "%d %ld\n",
+			bd->channels[i]->ch_portnum, bd->channels[i]->ch_txcount);
+	return count;
+}
+static DEVICE_ATTR(ports_txcount, S_IRUSR, dgap_ports_txcount_show, NULL);
+
+/* this function creates the sys files that will export each signal status
+ * to sysfs each value will be put in a separate filename
+ */
+static void dgap_create_ports_sysfiles(struct board_t *bd)
+{
+	int rc = 0;
+
+	dev_set_drvdata(&bd->pdev->dev, bd);
+	rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_state);
+	rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_baud);
+	rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_msignals);
+	rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_iflag);
+	rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_cflag);
+	rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_oflag);
+	rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_lflag);
+	rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_digi_flag);
+	rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_rxcount);
+	rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_txcount);
+	if (rc)
+		printk(KERN_ERR "DGAP: sysfs device_create_file failed!\n");
+}
+
+/* removes all the sys files created for that port */
+static void dgap_remove_ports_sysfiles(struct board_t *bd)
+{
+	device_remove_file(&(bd->pdev->dev), &dev_attr_ports_state);
+	device_remove_file(&(bd->pdev->dev), &dev_attr_ports_baud);
+	device_remove_file(&(bd->pdev->dev), &dev_attr_ports_msignals);
+	device_remove_file(&(bd->pdev->dev), &dev_attr_ports_iflag);
+	device_remove_file(&(bd->pdev->dev), &dev_attr_ports_cflag);
+	device_remove_file(&(bd->pdev->dev), &dev_attr_ports_oflag);
+	device_remove_file(&(bd->pdev->dev), &dev_attr_ports_lflag);
+	device_remove_file(&(bd->pdev->dev), &dev_attr_ports_digi_flag);
+	device_remove_file(&(bd->pdev->dev), &dev_attr_ports_rxcount);
+	device_remove_file(&(bd->pdev->dev), &dev_attr_ports_txcount);
+}
+
+static ssize_t dgap_tty_state_show(struct device *d, struct device_attribute *attr, char *buf)
+{
+	struct board_t *bd;
+	struct channel_t *ch;
+	struct un_t *un;
+
+	if (!d)
+		return 0;
+	un = dev_get_drvdata(d);
+	if (!un || un->magic != DGAP_UNIT_MAGIC)
+		return 0;
+	ch = un->un_ch;
+	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+		return 0;
+	bd = ch->ch_bd;
+	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
+		return 0;
+	if (bd->state != BOARD_READY)
+		return 0;
+
+	return snprintf(buf, PAGE_SIZE, "%s", un->un_open_count ? "Open" : "Closed");
+}
+static DEVICE_ATTR(state, S_IRUSR, dgap_tty_state_show, NULL);
+
+static ssize_t dgap_tty_baud_show(struct device *d, struct device_attribute *attr, char *buf)
+{
+	struct board_t *bd;
+	struct channel_t *ch;
+	struct un_t *un;
+
+	if (!d)
+		return 0;
+	un = dev_get_drvdata(d);
+	if (!un || un->magic != DGAP_UNIT_MAGIC)
+		return 0;
+	ch = un->un_ch;
+	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+		return 0;
+	bd = ch->ch_bd;
+	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
+		return 0;
+	if (bd->state != BOARD_READY)
+		return 0;
+
+	return snprintf(buf, PAGE_SIZE, "%d\n", ch->ch_baud_info);
+}
+static DEVICE_ATTR(baud, S_IRUSR, dgap_tty_baud_show, NULL);
+
+static ssize_t dgap_tty_msignals_show(struct device *d, struct device_attribute *attr, char *buf)
+{
+	struct board_t *bd;
+	struct channel_t *ch;
+	struct un_t *un;
+
+	if (!d)
+		return 0;
+	un = dev_get_drvdata(d);
+	if (!un || un->magic != DGAP_UNIT_MAGIC)
+		return 0;
+	ch = un->un_ch;
+	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+		return 0;
+	bd = ch->ch_bd;
+	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
+		return 0;
+	if (bd->state != BOARD_READY)
+		return 0;
+
+	if (ch->ch_open_count) {
+		return snprintf(buf, PAGE_SIZE, "%s %s %s %s %s %s\n",
+			(ch->ch_mostat & UART_MCR_RTS) ? "RTS" : "",
+			(ch->ch_mistat & UART_MSR_CTS) ? "CTS" : "",
+			(ch->ch_mostat & UART_MCR_DTR) ? "DTR" : "",
+			(ch->ch_mistat & UART_MSR_DSR) ? "DSR" : "",
+			(ch->ch_mistat & UART_MSR_DCD) ? "DCD" : "",
+			(ch->ch_mistat & UART_MSR_RI)  ? "RI"  : "");
+	}
+	return 0;
+}
+static DEVICE_ATTR(msignals, S_IRUSR, dgap_tty_msignals_show, NULL);
+
+static ssize_t dgap_tty_iflag_show(struct device *d, struct device_attribute *attr, char *buf)
+{
+	struct board_t *bd;
+	struct channel_t *ch;
+	struct un_t *un;
+
+	if (!d)
+		return 0;
+	un = dev_get_drvdata(d);
+	if (!un || un->magic != DGAP_UNIT_MAGIC)
+		return 0;
+	ch = un->un_ch;
+	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+		return 0;
+	bd = ch->ch_bd;
+	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
+		return 0;
+	if (bd->state != BOARD_READY)
+		return 0;
+
+	return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_c_iflag);
+}
+static DEVICE_ATTR(iflag, S_IRUSR, dgap_tty_iflag_show, NULL);
+
+static ssize_t dgap_tty_cflag_show(struct device *d, struct device_attribute *attr, char *buf)
+{
+	struct board_t *bd;
+	struct channel_t *ch;
+	struct un_t *un;
+
+	if (!d)
+		return 0;
+	un = dev_get_drvdata(d);
+	if (!un || un->magic != DGAP_UNIT_MAGIC)
+		return 0;
+	ch = un->un_ch;
+	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+		return 0;
+	bd = ch->ch_bd;
+	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
+		return 0;
+	if (bd->state != BOARD_READY)
+		return 0;
+
+	return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_c_cflag);
+}
+static DEVICE_ATTR(cflag, S_IRUSR, dgap_tty_cflag_show, NULL);
+
+static ssize_t dgap_tty_oflag_show(struct device *d, struct device_attribute *attr, char *buf)
+{
+	struct board_t *bd;
+	struct channel_t *ch;
+	struct un_t *un;
+
+	if (!d)
+		return 0;
+	un = dev_get_drvdata(d);
+	if (!un || un->magic != DGAP_UNIT_MAGIC)
+		return 0;
+	ch = un->un_ch;
+	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+		return 0;
+	bd = ch->ch_bd;
+	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
+		return 0;
+	if (bd->state != BOARD_READY)
+		return 0;
+
+	return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_c_oflag);
+}
+static DEVICE_ATTR(oflag, S_IRUSR, dgap_tty_oflag_show, NULL);
+
+static ssize_t dgap_tty_lflag_show(struct device *d, struct device_attribute *attr, char *buf)
+{
+	struct board_t *bd;
+	struct channel_t *ch;
+	struct un_t *un;
+
+	if (!d)
+		return 0;
+	un = dev_get_drvdata(d);
+	if (!un || un->magic != DGAP_UNIT_MAGIC)
+		return 0;
+	ch = un->un_ch;
+	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+		return 0;
+	bd = ch->ch_bd;
+	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
+		return 0;
+	if (bd->state != BOARD_READY)
+		return 0;
+
+	return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_c_lflag);
+}
+static DEVICE_ATTR(lflag, S_IRUSR, dgap_tty_lflag_show, NULL);
+
+static ssize_t dgap_tty_digi_flag_show(struct device *d, struct device_attribute *attr, char *buf)
+{
+	struct board_t *bd;
+	struct channel_t *ch;
+	struct un_t *un;
+
+	if (!d)
+		return 0;
+	un = dev_get_drvdata(d);
+	if (!un || un->magic != DGAP_UNIT_MAGIC)
+		return 0;
+	ch = un->un_ch;
+	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+		return 0;
+	bd = ch->ch_bd;
+	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
+		return 0;
+	if (bd->state != BOARD_READY)
+		return 0;
+
+	return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_digi.digi_flags);
+}
+static DEVICE_ATTR(digi_flag, S_IRUSR, dgap_tty_digi_flag_show, NULL);
+
+static ssize_t dgap_tty_rxcount_show(struct device *d, struct device_attribute *attr, char *buf)
+{
+	struct board_t *bd;
+	struct channel_t *ch;
+	struct un_t *un;
+
+	if (!d)
+		return 0;
+	un = dev_get_drvdata(d);
+	if (!un || un->magic != DGAP_UNIT_MAGIC)
+		return 0;
+	ch = un->un_ch;
+	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+		return 0;
+	bd = ch->ch_bd;
+	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
+		return 0;
+	if (bd->state != BOARD_READY)
+		return 0;
+
+	return snprintf(buf, PAGE_SIZE, "%ld\n", ch->ch_rxcount);
+}
+static DEVICE_ATTR(rxcount, S_IRUSR, dgap_tty_rxcount_show, NULL);
+
+static ssize_t dgap_tty_txcount_show(struct device *d, struct device_attribute *attr, char *buf)
+{
+	struct board_t *bd;
+	struct channel_t *ch;
+	struct un_t *un;
+
+	if (!d)
+		return 0;
+	un = dev_get_drvdata(d);
+	if (!un || un->magic != DGAP_UNIT_MAGIC)
+		return 0;
+	ch = un->un_ch;
+	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+		return 0;
+	bd = ch->ch_bd;
+	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
+		return 0;
+	if (bd->state != BOARD_READY)
+		return 0;
+
+	return snprintf(buf, PAGE_SIZE, "%ld\n", ch->ch_txcount);
+}
+static DEVICE_ATTR(txcount, S_IRUSR, dgap_tty_txcount_show, NULL);
+
+static ssize_t dgap_tty_name_show(struct device *d, struct device_attribute *attr, char *buf)
+{
+	struct board_t *bd;
+	struct channel_t *ch;
+	struct un_t *un;
+	int	cn;
+	int	bn;
+	struct cnode *cptr = NULL;
+	int found = FALSE;
+	int ncount = 0;
+	int starto = 0;
+	int i = 0;
+
+	if (!d)
+		return 0;
+	un = dev_get_drvdata(d);
+	if (!un || un->magic != DGAP_UNIT_MAGIC)
+		return 0;
+	ch = un->un_ch;
+	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+		return 0;
+	bd = ch->ch_bd;
+	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
+		return 0;
+	if (bd->state != BOARD_READY)
+		return 0;
+
+	bn = bd->boardnum;
+	cn = ch->ch_portnum;
+
+	for (cptr = bd->bd_config; cptr; cptr = cptr->next) {
+
+		if ((cptr->type == BNODE) &&
+		    ((cptr->u.board.type == APORT2_920P) || (cptr->u.board.type == APORT4_920P) ||
+		     (cptr->u.board.type == APORT8_920P) || (cptr->u.board.type == PAPORT4) ||
+		     (cptr->u.board.type == PAPORT8))) {
+
+				found = TRUE;
+				if (cptr->u.board.v_start)
+					starto = cptr->u.board.start;
+				else
+					starto = 1;
+		}
+
+		if (cptr->type == TNODE && found == TRUE) {
+			char *ptr1;
+			if (strstr(cptr->u.ttyname, "tty")) {
+				ptr1 = cptr->u.ttyname;
+				ptr1 += 3;
+			} else
+				ptr1 = cptr->u.ttyname;
+
+			for (i = 0; i < dgap_config_get_number_of_ports(bd); i++) {
+				if (cn == i)
+					return snprintf(buf, PAGE_SIZE, "%s%s%02d\n",
+						(un->un_type == DGAP_PRINT) ? "pr" : "tty",
+						ptr1, i + starto);
+			}
+		}
+
+		if (cptr->type == CNODE) {
+
+			for (i = 0; i < cptr->u.conc.nport; i++) {
+				if (cn == (i + ncount))
+
+					return snprintf(buf, PAGE_SIZE, "%s%s%02d\n",
+						(un->un_type == DGAP_PRINT) ? "pr" : "tty",
+						cptr->u.conc.id,
+						i + (cptr->u.conc.v_start ? cptr->u.conc.start : 1));
+			}
+
+			ncount += cptr->u.conc.nport;
+		}
+
+		if (cptr->type == MNODE) {
+
+			for (i = 0; i < cptr->u.module.nport; i++) {
+				if (cn == (i + ncount))
+					return snprintf(buf, PAGE_SIZE, "%s%s%02d\n",
+						(un->un_type == DGAP_PRINT) ? "pr" : "tty",
+						cptr->u.module.id,
+						i + (cptr->u.module.v_start ? cptr->u.module.start : 1));
+			}
+
+			ncount += cptr->u.module.nport;
+
+		}
+	}
+
+	return snprintf(buf, PAGE_SIZE, "%s_dgap_%d_%d\n",
+		(un->un_type == DGAP_PRINT) ? "pr" : "tty", bn, cn);
+
+}
+static DEVICE_ATTR(custom_name, S_IRUSR, dgap_tty_name_show, NULL);
+
+static struct attribute *dgap_sysfs_tty_entries[] = {
+	&dev_attr_state.attr,
+	&dev_attr_baud.attr,
+	&dev_attr_msignals.attr,
+	&dev_attr_iflag.attr,
+	&dev_attr_cflag.attr,
+	&dev_attr_oflag.attr,
+	&dev_attr_lflag.attr,
+	&dev_attr_digi_flag.attr,
+	&dev_attr_rxcount.attr,
+	&dev_attr_txcount.attr,
+	&dev_attr_custom_name.attr,
+	NULL
+};
+
+static struct attribute_group dgap_tty_attribute_group = {
+	.name = NULL,
+	.attrs = dgap_sysfs_tty_entries,
+};
+
+static void dgap_create_tty_sysfs(struct un_t *un, struct device *c)
+{
+	int ret;
+
+	ret = sysfs_create_group(&c->kobj, &dgap_tty_attribute_group);
+	if (ret) {
+		printk(KERN_ERR "dgap: failed to create sysfs tty device attributes.\n");
+		sysfs_remove_group(&c->kobj, &dgap_tty_attribute_group);
+		return;
+	}
+
+	dev_set_drvdata(c, un);
+
+}
+
+static void dgap_remove_tty_sysfs(struct device *c)
+{
+	sysfs_remove_group(&c->kobj, &dgap_tty_attribute_group);
+}
+
+/*
+ * Parse a configuration file read into memory as a string.
+ */
+static int	dgap_parsefile(char **in, int Remove)
+{
+	struct cnode *p, *brd, *line, *conc;
+	int	rc;
+	char	*s = NULL, *s2 = NULL;
+	int	linecnt = 0;
+
+	p = &dgap_head;
+	brd = line = conc = NULL;
+
+	/* perhaps we are adding to an existing list? */
+	while (p->next != NULL)
+		p = p->next;
+
+	/* file must start with a BEGIN */
+	while ((rc = dgap_gettok(in, p)) != BEGIN) {
+		if (rc == 0) {
+			dgap_err("unexpected EOF");
+			return -1;
+		}
+	}
+
+	for (; ;) {
+		rc = dgap_gettok(in, p);
+		if (rc == 0) {
+			dgap_err("unexpected EOF");
+			return -1;
+		}
+
+		switch (rc) {
+		case 0:
+			dgap_err("unexpected end of file");
+			return -1;
+
+		case BEGIN:	/* should only be 1 begin */
+			dgap_err("unexpected config_begin\n");
+			return -1;
+
+		case END:
+			return 0;
+
+		case BOARD:	/* board info */
+			if (dgap_checknode(p))
+				return -1;
+			p->next = dgap_newnode(BNODE);
+			if (!p->next) {
+				dgap_err("out of memory");
+				return -1;
+			}
+			p = p->next;
+
+			p->u.board.status = dgap_savestring("No");
+			line = conc = NULL;
+			brd = p;
+			linecnt = -1;
+			break;
+
+		case APORT2_920P:	/* AccelePort_4 */
+			if (p->type != BNODE) {
+				dgap_err("unexpected Digi_2r_920 string");
+				return -1;
+			}
+			p->u.board.type = APORT2_920P;
+			p->u.board.v_type = 1;
+			break;
+
+		case APORT4_920P:	/* AccelePort_4 */
+			if (p->type != BNODE) {
+				dgap_err("unexpected Digi_4r_920 string");
+				return -1;
+			}
+			p->u.board.type = APORT4_920P;
+			p->u.board.v_type = 1;
+			break;
+
+		case APORT8_920P:	/* AccelePort_8 */
+			if (p->type != BNODE) {
+				dgap_err("unexpected Digi_8r_920 string");
+				return -1;
+			}
+			p->u.board.type = APORT8_920P;
+			p->u.board.v_type = 1;
+			break;
+
+		case PAPORT4:	/* AccelePort_4 PCI */
+			if (p->type != BNODE) {
+				dgap_err("unexpected Digi_4r(PCI) string");
+				return -1;
+			}
+			p->u.board.type = PAPORT4;
+			p->u.board.v_type = 1;
+			break;
+
+		case PAPORT8:	/* AccelePort_8 PCI */
+			if (p->type != BNODE) {
+				dgap_err("unexpected Digi_8r string");
+				return -1;
+			}
+			p->u.board.type = PAPORT8;
+			p->u.board.v_type = 1;
+			break;
+
+		case PCX:	/* PCI C/X */
+			if (p->type != BNODE) {
+				dgap_err("unexpected Digi_C/X_(PCI) string");
+				return -1;
+			}
+			p->u.board.type = PCX;
+			p->u.board.v_type = 1;
+			p->u.board.conc1 = 0;
+			p->u.board.conc2 = 0;
+			p->u.board.module1 = 0;
+			p->u.board.module2 = 0;
+			break;
+
+		case PEPC:	/* PCI EPC/X */
+			if (p->type != BNODE) {
+				dgap_err("unexpected \"Digi_EPC/X_(PCI)\" string");
+				return -1;
+			}
+			p->u.board.type = PEPC;
+			p->u.board.v_type = 1;
+			p->u.board.conc1 = 0;
+			p->u.board.conc2 = 0;
+			p->u.board.module1 = 0;
+			p->u.board.module2 = 0;
+			break;
+
+		case PPCM:	/* PCI/Xem */
+			if (p->type != BNODE) {
+				dgap_err("unexpected PCI/Xem string");
+				return -1;
+			}
+			p->u.board.type = PPCM;
+			p->u.board.v_type = 1;
+			p->u.board.conc1 = 0;
+			p->u.board.conc2 = 0;
+			break;
+
+		case IO:	/* i/o port */
+			if (p->type != BNODE) {
+				dgap_err("IO port only vaild for boards");
+				return -1;
+			}
+			s = dgap_getword(in);
+			if (s == NULL) {
+				dgap_err("unexpected end of file");
+				return -1;
+			}
+			p->u.board.portstr = dgap_savestring(s);
+			p->u.board.port = (short)simple_strtol(s, &s2, 0);
+			if ((short)strlen(s) > (short)(s2 - s)) {
+				dgap_err("bad number for IO port");
+				return -1;
+			}
+			p->u.board.v_port = 1;
+			break;
+
+		case MEM:	/* memory address */
+			if (p->type != BNODE) {
+				dgap_err("memory address only vaild for boards");
+				return -1;
+			}
+			s = dgap_getword(in);
+			if (s == NULL) {
+				dgap_err("unexpected end of file");
+				return -1;
+			}
+			p->u.board.addrstr = dgap_savestring(s);
+			p->u.board.addr = simple_strtoul(s, &s2, 0);
+			if ((int)strlen(s) > (int)(s2 - s)) {
+				dgap_err("bad number for memory address");
+				return -1;
+			}
+			p->u.board.v_addr = 1;
+			break;
+
+		case PCIINFO:	/* pci information */
+			if (p->type != BNODE) {
+				dgap_err("memory address only vaild for boards");
+				return -1;
+			}
+			s = dgap_getword(in);
+			if (s == NULL) {
+				dgap_err("unexpected end of file");
+				return -1;
+			}
+			p->u.board.pcibusstr = dgap_savestring(s);
+			p->u.board.pcibus = simple_strtoul(s, &s2, 0);
+			if ((int)strlen(s) > (int)(s2 - s)) {
+				dgap_err("bad number for pci bus");
+				return -1;
+			}
+			p->u.board.v_pcibus = 1;
+			s = dgap_getword(in);
+			if (s == NULL) {
+				dgap_err("unexpected end of file");
+				return -1;
+			}
+			p->u.board.pcislotstr = dgap_savestring(s);
+			p->u.board.pcislot = simple_strtoul(s, &s2, 0);
+			if ((int)strlen(s) > (int)(s2 - s)) {
+				dgap_err("bad number for pci slot");
+				return -1;
+			}
+			p->u.board.v_pcislot = 1;
+			break;
+
+		case METHOD:
+			if (p->type != BNODE) {
+				dgap_err("install method only vaild for boards");
+				return -1;
+			}
+			s = dgap_getword(in);
+			if (s == NULL) {
+				dgap_err("unexpected end of file");
+				return -1;
+			}
+			p->u.board.method = dgap_savestring(s);
+			p->u.board.v_method = 1;
+			break;
+
+		case STATUS:
+			if (p->type != BNODE) {
+				dgap_err("config status only vaild for boards");
+				return -1;
+			}
+			s = dgap_getword(in);
+			if (s == NULL) {
+				dgap_err("unexpected end of file");
+				return -1;
+			}
+			p->u.board.status = dgap_savestring(s);
+			break;
+
+		case NPORTS:	/* number of ports */
+			if (p->type == BNODE) {
+				s = dgap_getword(in);
+				if (s == NULL) {
+					dgap_err("unexpected end of file");
+					return -1;
+				}
+				p->u.board.nport = (char)simple_strtol(s, &s2, 0);
+				if ((int)strlen(s) > (int)(s2 - s)) {
+					dgap_err("bad number for number of ports");
+					return -1;
+				}
+				p->u.board.v_nport = 1;
+			} else if (p->type == CNODE) {
+				s = dgap_getword(in);
+				if (s == NULL) {
+					dgap_err("unexpected end of file");
+					return -1;
+				}
+				p->u.conc.nport = (char)simple_strtol(s, &s2, 0);
+				if ((int)strlen(s) > (int)(s2 - s)) {
+					dgap_err("bad number for number of ports");
+					return -1;
+				}
+				p->u.conc.v_nport = 1;
+			} else if (p->type == MNODE) {
+				s = dgap_getword(in);
+				if (s == NULL) {
+					dgap_err("unexpected end of file");
+					return -1;
+				}
+				p->u.module.nport = (char)simple_strtol(s, &s2, 0);
+				if ((int)strlen(s) > (int)(s2 - s)) {
+					dgap_err("bad number for number of ports");
+					return -1;
+				}
+				p->u.module.v_nport = 1;
+			} else {
+				dgap_err("nports only valid for concentrators or modules");
+				return -1;
+			}
+			break;
+
+		case ID:	/* letter ID used in tty name */
+			s = dgap_getword(in);
+			if (s == NULL) {
+				dgap_err("unexpected end of file");
+				return -1;
+			}
+
+			p->u.board.status = dgap_savestring(s);
+
+			if (p->type == CNODE) {
+				p->u.conc.id = dgap_savestring(s);
+				p->u.conc.v_id = 1;
+			} else if (p->type == MNODE) {
+				p->u.module.id = dgap_savestring(s);
+				p->u.module.v_id = 1;
+			} else {
+				dgap_err("id only valid for concentrators or modules");
+				return -1;
+			}
+			break;
+
+		case STARTO:	/* start offset of ID */
+			if (p->type == BNODE) {
+				s = dgap_getword(in);
+				if (s == NULL) {
+					dgap_err("unexpected end of file");
+					return -1;
+				}
+				p->u.board.start = simple_strtol(s, &s2, 0);
+				if ((int)strlen(s) > (int)(s2 - s)) {
+					dgap_err("bad number for start of tty count");
+					return -1;
+				}
+				p->u.board.v_start = 1;
+			} else if (p->type == CNODE) {
+				s = dgap_getword(in);
+				if (s == NULL) {
+					dgap_err("unexpected end of file");
+					return -1;
+				}
+				p->u.conc.start = simple_strtol(s, &s2, 0);
+				if ((int)strlen(s) > (int)(s2 - s)) {
+					dgap_err("bad number for start of tty count");
+					return -1;
+				}
+				p->u.conc.v_start = 1;
+			} else if (p->type == MNODE) {
+				s = dgap_getword(in);
+				if (s == NULL) {
+					dgap_err("unexpected end of file");
+					return -1;
+				}
+				p->u.module.start = simple_strtol(s, &s2, 0);
+				if ((int)strlen(s) > (int)(s2 - s)) {
+					dgap_err("bad number for start of tty count");
+					return -1;
+				}
+				p->u.module.v_start = 1;
+			} else {
+				dgap_err("start only valid for concentrators or modules");
+				return -1;
+			}
+			break;
+
+		case TTYN:	/* tty name prefix */
+			if (dgap_checknode(p))
+				return -1;
+			p->next = dgap_newnode(TNODE);
+			if (!p->next) {
+				dgap_err("out of memory");
+				return -1;
+			}
+			p = p->next;
+			s = dgap_getword(in);
+			if (!s) {
+				dgap_err("unexpeced end of file");
+				return -1;
+			}
+			p->u.ttyname = dgap_savestring(s);
+			if (!p->u.ttyname) {
+				dgap_err("out of memory");
+				return -1;
+			}
+			break;
+
+		case CU:	/* cu name prefix */
+			if (dgap_checknode(p))
+				return -1;
+			p->next = dgap_newnode(CUNODE);
+			if (!p->next) {
+				dgap_err("out of memory");
+				return -1;
+			}
+			p = p->next;
+			s = dgap_getword(in);
+			if (!s) {
+				dgap_err("unexpeced end of file");
+				return -1;
+			}
+			p->u.cuname = dgap_savestring(s);
+			if (!p->u.cuname) {
+				dgap_err("out of memory");
+				return -1;
+			}
+			break;
+
+		case LINE:	/* line information */
+			if (dgap_checknode(p))
+				return -1;
+			if (brd == NULL) {
+				dgap_err("must specify board before line info");
+				return -1;
+			}
+			switch (brd->u.board.type) {
+			case PPCM:
+				dgap_err("line not vaild for PC/em");
+				return -1;
+			}
+			p->next = dgap_newnode(LNODE);
+			if (!p->next) {
+				dgap_err("out of memory");
+				return -1;
+			}
+			p = p->next;
+			conc = NULL;
+			line = p;
+			linecnt++;
+			break;
+
+		case CONC:	/* concentrator information */
+			if (dgap_checknode(p))
+				return -1;
+			if (line == NULL) {
+				dgap_err("must specify line info before concentrator");
+				return -1;
+			}
+			p->next = dgap_newnode(CNODE);
+			if (!p->next) {
+				dgap_err("out of memory");
+				return -1;
+			}
+			p = p->next;
+			conc = p;
+			if (linecnt)
+				brd->u.board.conc2++;
+			else
+				brd->u.board.conc1++;
+
+			break;
+
+		case CX:	/* c/x type concentrator */
+			if (p->type != CNODE) {
+				dgap_err("cx only valid for concentrators");
+				return -1;
+			}
+			p->u.conc.type = CX;
+			p->u.conc.v_type = 1;
+			break;
+
+		case EPC:	/* epc type concentrator */
+			if (p->type != CNODE) {
+				dgap_err("cx only valid for concentrators");
+				return -1;
+			}
+			p->u.conc.type = EPC;
+			p->u.conc.v_type = 1;
+			break;
+
+		case MOD:	/* EBI module */
+			if (dgap_checknode(p))
+				return -1;
+			if (brd == NULL) {
+				dgap_err("must specify board info before EBI modules");
+				return -1;
+			}
+			switch (brd->u.board.type) {
+			case PPCM:
+				linecnt = 0;
+				break;
+			default:
+				if (conc == NULL) {
+					dgap_err("must specify concentrator info before EBI module");
+					return -1;
+				}
+			}
+			p->next = dgap_newnode(MNODE);
+			if (!p->next) {
+				dgap_err("out of memory");
+				return -1;
+			}
+			p = p->next;
+			if (linecnt)
+				brd->u.board.module2++;
+			else
+				brd->u.board.module1++;
+
+			break;
+
+		case PORTS:	/* ports type EBI module */
+			if (p->type != MNODE) {
+				dgap_err("ports only valid for EBI modules");
+				return -1;
+			}
+			p->u.module.type = PORTS;
+			p->u.module.v_type = 1;
+			break;
+
+		case MODEM:	/* ports type EBI module */
+			if (p->type != MNODE) {
+				dgap_err("modem only valid for modem modules");
+				return -1;
+			}
+			p->u.module.type = MODEM;
+			p->u.module.v_type = 1;
+			break;
+
+		case CABLE:
+			if (p->type == LNODE) {
+				s = dgap_getword(in);
+				if (!s) {
+					dgap_err("unexpected end of file");
+					return -1;
+				}
+				p->u.line.cable = dgap_savestring(s);
+				p->u.line.v_cable = 1;
+			}
+			break;
+
+		case SPEED:	/* sync line speed indication */
+			if (p->type == LNODE) {
+				s = dgap_getword(in);
+				if (s == NULL) {
+					dgap_err("unexpected end of file");
+					return -1;
+				}
+				p->u.line.speed = (char)simple_strtol(s, &s2, 0);
+				if ((short)strlen(s) > (short)(s2 - s)) {
+					dgap_err("bad number for line speed");
+					return -1;
+				}
+				p->u.line.v_speed = 1;
+			} else if (p->type == CNODE) {
+				s = dgap_getword(in);
+				if (s == NULL) {
+					dgap_err("unexpected end of file");
+					return -1;
+				}
+				p->u.conc.speed = (char)simple_strtol(s, &s2, 0);
+				if ((short)strlen(s) > (short)(s2 - s)) {
+					dgap_err("bad number for line speed");
+					return -1;
+				}
+				p->u.conc.v_speed = 1;
+			} else {
+				dgap_err("speed valid only for lines or concentrators.");
+				return -1;
+			}
+			break;
+
+		case CONNECT:
+			if (p->type == CNODE) {
+				s = dgap_getword(in);
+				if (!s) {
+					dgap_err("unexpected end of file");
+					return -1;
+				}
+				p->u.conc.connect = dgap_savestring(s);
+				p->u.conc.v_connect = 1;
+			}
+			break;
+		case PRINT:	/* transparent print name prefix */
+			if (dgap_checknode(p))
+				return -1;
+			p->next = dgap_newnode(PNODE);
+			if (!p->next) {
+				dgap_err("out of memory");
+				return -1;
+			}
+			p = p->next;
+			s = dgap_getword(in);
+			if (!s) {
+				dgap_err("unexpeced end of file");
+				return -1;
+			}
+			p->u.printname = dgap_savestring(s);
+			if (!p->u.printname) {
+				dgap_err("out of memory");
+				return -1;
+			}
+			break;
+
+		case CMAJOR:	/* major number */
+			if (dgap_checknode(p))
+				return -1;
+			p->next = dgap_newnode(JNODE);
+			if (!p->next) {
+				dgap_err("out of memory");
+				return -1;
+			}
+			p = p->next;
+			s = dgap_getword(in);
+			if (s == NULL) {
+				dgap_err("unexpected end of file");
+				return -1;
+			}
+			p->u.majornumber = simple_strtol(s, &s2, 0);
+			if ((int)strlen(s) > (int)(s2 - s)) {
+				dgap_err("bad number for major number");
+				return -1;
+			}
+			break;
+
+		case ALTPIN:	/* altpin setting */
+			if (dgap_checknode(p))
+				return -1;
+			p->next = dgap_newnode(ANODE);
+			if (!p->next) {
+				dgap_err("out of memory");
+				return -1;
+			}
+			p = p->next;
+			s = dgap_getword(in);
+			if (s == NULL) {
+				dgap_err("unexpected end of file");
+				return -1;
+			}
+			p->u.altpin = simple_strtol(s, &s2, 0);
+			if ((int)strlen(s) > (int)(s2 - s)) {
+				dgap_err("bad number for altpin");
+				return -1;
+			}
+			break;
+
+		case USEINTR:		/* enable interrupt setting */
+			if (dgap_checknode(p))
+				return -1;
+			p->next = dgap_newnode(INTRNODE);
+			if (!p->next) {
+				dgap_err("out of memory");
+				return -1;
+			}
+			p = p->next;
+			s = dgap_getword(in);
+			if (s == NULL) {
+				dgap_err("unexpected end of file");
+				return -1;
+			}
+			p->u.useintr = simple_strtol(s, &s2, 0);
+			if ((int)strlen(s) > (int)(s2 - s)) {
+				dgap_err("bad number for useintr");
+				return -1;
+			}
+			break;
+
+		case TTSIZ:	/* size of tty structure */
+			if (dgap_checknode(p))
+				return -1;
+			p->next = dgap_newnode(TSNODE);
+			if (!p->next) {
+				dgap_err("out of memory");
+				return -1;
+			}
+			p = p->next;
+			s = dgap_getword(in);
+			if (s == NULL) {
+				dgap_err("unexpected end of file");
+				return -1;
+			}
+			p->u.ttysize = simple_strtol(s, &s2, 0);
+			if ((int)strlen(s) > (int)(s2 - s)) {
+				dgap_err("bad number for ttysize");
+				return -1;
+			}
+			break;
+
+		case CHSIZ:	/* channel structure size */
+			if (dgap_checknode(p))
+				return -1;
+			p->next = dgap_newnode(CSNODE);
+			if (!p->next) {
+				dgap_err("out of memory");
+				return -1;
+			}
+			p = p->next;
+			s = dgap_getword(in);
+			if (s == NULL) {
+				dgap_err("unexpected end of file");
+				return -1;
+			}
+			p->u.chsize = simple_strtol(s, &s2, 0);
+			if ((int)strlen(s) > (int)(s2 - s)) {
+				dgap_err("bad number for chsize");
+				return -1;
+			}
+			break;
+
+		case BSSIZ:	/* board structure size */
+			if (dgap_checknode(p))
+				return -1;
+			p->next = dgap_newnode(BSNODE);
+			if (!p->next) {
+				dgap_err("out of memory");
+				return -1;
+			}
+			p = p->next;
+			s = dgap_getword(in);
+			if (s == NULL) {
+				dgap_err("unexpected end of file");
+				return -1;
+			}
+			p->u.bssize = simple_strtol(s, &s2, 0);
+			if ((int)strlen(s) > (int)(s2 - s)) {
+				dgap_err("bad number for bssize");
+				return -1;
+			}
+			break;
+
+		case UNTSIZ:	/* sched structure size */
+			if (dgap_checknode(p))
+				return -1;
+			p->next = dgap_newnode(USNODE);
+			if (!p->next) {
+				dgap_err("out of memory");
+				return -1;
+			}
+			p = p->next;
+			s = dgap_getword(in);
+			if (s == NULL) {
+				dgap_err("unexpected end of file");
+				return -1;
+			}
+			p->u.unsize = simple_strtol(s, &s2, 0);
+			if ((int)strlen(s) > (int)(s2 - s)) {
+				dgap_err("bad number for schedsize");
+				return -1;
+			}
+			break;
+
+		case F2SIZ:	/* f2200 structure size */
+			if (dgap_checknode(p))
+				return -1;
+			p->next = dgap_newnode(FSNODE);
+			if (!p->next) {
+				dgap_err("out of memory");
+				return -1;
+			}
+			p = p->next;
+			s = dgap_getword(in);
+			if (s == NULL) {
+				dgap_err("unexpected end of file");
+				return -1;
+			}
+			p->u.f2size = simple_strtol(s, &s2, 0);
+			if ((int)strlen(s) > (int)(s2 - s)) {
+				dgap_err("bad number for f2200size");
+				return -1;
+			}
+			break;
+
+		case VPSIZ:	/* vpix structure size */
+			if (dgap_checknode(p))
+				return -1;
+			p->next = dgap_newnode(VSNODE);
+			if (!p->next) {
+				dgap_err("out of memory");
+				return -1;
+			}
+			p = p->next;
+			s = dgap_getword(in);
+			if (s == NULL) {
+				dgap_err("unexpected end of file");
+				return -1;
+			}
+			p->u.vpixsize = simple_strtol(s, &s2, 0);
+			if ((int)strlen(s) > (int)(s2 - s)) {
+				dgap_err("bad number for vpixsize");
+				return -1;
+			}
+			break;
+		}
+	}
+}
+
+/*
+ * dgap_sindex: much like index(), but it looks for a match of any character in
+ * the group, and returns that position.  If the first character is a ^, then
+ * this will match the first occurrence not in that group.
+ */
+static char *dgap_sindex (char *string, char *group)
+{
+	char    *ptr;
+
+	if (!string || !group)
+		return (char *) NULL;
+
+	if (*group == '^') {
+		group++;
+		for (; *string; string++) {
+			for (ptr = group; *ptr; ptr++) {
+				if (*ptr == *string)
+					break;
+			}
+			if (*ptr == '\0')
+				return string;
+		}
+	} else {
+		for (; *string; string++) {
+			for (ptr = group; *ptr; ptr++) {
+				if (*ptr == *string)
+					return string;
+			}
+		}
+	}
+
+	return (char *) NULL;
+}
+
+/*
+ * Get a token from the input file; return 0 if end of file is reached
+ */
+static int dgap_gettok(char **in, struct cnode *p)
+{
+	char	*w;
+	struct toklist *t;
+
+	if (strstr(dgap_cword, "boar")) {
+		w = dgap_getword(in);
+		snprintf(dgap_cword, MAXCWORD, "%s", w);
+		for (t = dgap_tlist; t->token != 0; t++) {
+			if (!strcmp(w, t->string))
+				return t->token;
+		}
+		dgap_err("board !!type not specified");
+		return 1;
+	} else {
+		while ( (w = dgap_getword(in)) != NULL ) {
+			snprintf(dgap_cword, MAXCWORD, "%s", w);
+			for (t = dgap_tlist; t->token != 0; t++) {
+				if (!strcmp(w, t->string))
+					return t->token;
+			}
+		}
+		return 0;
+	}
+}
+
+/*
+ * get a word from the input stream, also keep track of current line number.
+ * words are separated by whitespace.
+ */
+static char *dgap_getword(char **in)
+{
+	char *ret_ptr = *in;
+
+	char *ptr = dgap_sindex(*in, " \t\n");
+
+	/* If no word found, return null */
+	if (!ptr)
+		return NULL;
+
+	/* Mark new location for our buffer */
+	*ptr = '\0';
+	*in = ptr + 1;
+
+	/* Eat any extra spaces/tabs/newlines that might be present */
+	while (*in && **in && ((**in == ' ') || (**in == '\t') || (**in == '\n'))) {
+		**in = '\0';
+		*in = *in + 1;
+	}
+
+	return ret_ptr;
+}
+
+/*
+ * print an error message, giving the line number in the file where
+ * the error occurred.
+ */
+static void dgap_err(char *s)
+{
+	printk("DGAP: parse: %s\n", s);
+}
+
+/*
+ * allocate a new configuration node of type t
+ */
+static struct cnode *dgap_newnode(int t)
+{
+	struct cnode *n;
+
+	n = kmalloc(sizeof(struct cnode), GFP_ATOMIC);
+	if (n != NULL) {
+		memset((char *)n, 0, sizeof(struct cnode));
+		n->type = t;
+	}
+	return n;
+}
+
+/*
+ * dgap_checknode: see if all the necessary info has been supplied for a node
+ * before creating the next node.
+ */
+static int dgap_checknode(struct cnode *p)
+{
+	switch (p->type) {
+	case BNODE:
+		if (p->u.board.v_type == 0) {
+			dgap_err("board type !not specified");
+			return 1;
+		}
+
+		return 0;
+
+	case LNODE:
+		if (p->u.line.v_speed == 0) {
+			dgap_err("line speed not specified");
+			return 1;
+		}
+		return 0;
+
+	case CNODE:
+		if (p->u.conc.v_type == 0) {
+			dgap_err("concentrator type not specified");
+			return 1;
+		}
+		if (p->u.conc.v_speed == 0) {
+			dgap_err("concentrator line speed not specified");
+			return 1;
+		}
+		if (p->u.conc.v_nport == 0) {
+			dgap_err("number of ports on concentrator not specified");
+			return 1;
+		}
+		if (p->u.conc.v_id == 0) {
+			dgap_err("concentrator id letter not specified");
+			return 1;
+		}
+		return 0;
+
+	case MNODE:
+		if (p->u.module.v_type == 0) {
+			dgap_err("EBI module type not specified");
+			return 1;
+		}
+		if (p->u.module.v_nport == 0) {
+			dgap_err("number of ports on EBI module not specified");
+			return 1;
+		}
+		if (p->u.module.v_id == 0) {
+			dgap_err("EBI module id letter not specified");
+			return 1;
+		}
+		return 0;
+	}
+	return 0;
+}
+
+/*
+ * save a string somewhere
+ */
+static char	*dgap_savestring(char *s)
+{
+	char	*p;
+
+	p = kmalloc(strlen(s) + 1, GFP_ATOMIC);
+	if (p)
+		strcpy(p, s);
+	return p;
+}
+
+/*
+ * Given a board pointer, returns whether we should use interrupts or not.
+ */
+static uint dgap_config_get_useintr(struct board_t *bd)
+{
+	struct cnode *p = NULL;
+
+	if (!bd)
+		return 0;
+
+	for (p = bd->bd_config; p; p = p->next) {
+		switch (p->type) {
+		case INTRNODE:
+			/*
+			 * check for pcxr types.
+			 */
+			return p->u.useintr;
+		default:
+			break;
+		}
+	}
+
+	/* If not found, then don't turn on interrupts. */
+	return 0;
+}
+
+/*
+ * Given a board pointer, returns whether we turn on altpin or not.
+ */
+static uint dgap_config_get_altpin(struct board_t *bd)
+{
+	struct cnode *p = NULL;
+
+	if (!bd)
+		return 0;
+
+	for (p = bd->bd_config; p; p = p->next) {
+		switch (p->type) {
+		case ANODE:
+			/*
+			 * check for pcxr types.
+			 */
+			return p->u.altpin;
+		default:
+			break;
+		}
+	}
+
+	/* If not found, then don't turn on interrupts. */
+	return 0;
+}
+
+/*
+ * Given a specific type of board, if found, detached link and
+ * returns the first occurrence in the list.
+ */
+static struct cnode *dgap_find_config(int type, int bus, int slot)
+{
+	struct cnode *p, *prev = NULL, *prev2 = NULL, *found = NULL;
+
+	p = &dgap_head;
+
+	while (p->next != NULL) {
+		prev = p;
+		p = p->next;
+
+		if (p->type == BNODE) {
+
+			if (p->u.board.type == type) {
+
+				if (p->u.board.v_pcibus &&
+				    p->u.board.pcibus != bus)
+					continue;
+				if (p->u.board.v_pcislot &&
+				    p->u.board.pcislot != slot)
+					continue;
+
+				found = p;
+				/*
+				 * Keep walking thru the list till we find the next board.
+				 */
+				while (p->next != NULL) {
+					prev2 = p;
+					p = p->next;
+					if (p->type == BNODE) {
+
+						/*
+						 * Mark the end of our 1 board chain of configs.
+						 */
+						prev2->next = NULL;
+
+						/*
+						 * Link the "next" board to the previous board,
+						 * effectively "unlinking" our board from the main config.
+						 */
+						prev->next = p;
+
+						return found;
+					}
+				}
+				/*
+				 * It must be the last board in the list.
+				 */
+				prev->next = NULL;
+				return found;
+			}
+		}
+	}
+	return NULL;
+}
+
+/*
+ * Given a board pointer, walks the config link, counting up
+ * all ports user specified should be on the board.
+ * (This does NOT mean they are all actually present right now tho)
+ */
+static uint dgap_config_get_number_of_ports(struct board_t *bd)
+{
+	int count = 0;
+	struct cnode *p = NULL;
+
+	if (!bd)
+		return 0;
+
+	for (p = bd->bd_config; p; p = p->next) {
+
+		switch (p->type) {
+		case BNODE:
+			/*
+			 * check for pcxr types.
+			 */
+			if (p->u.board.type > EPCFE)
+				count += p->u.board.nport;
+			break;
+		case CNODE:
+			count += p->u.conc.nport;
+			break;
+		case MNODE:
+			count += p->u.module.nport;
+			break;
+		}
+	}
+	return count;
+}
+
+static char *dgap_create_config_string(struct board_t *bd, char *string)
+{
+	char *ptr = string;
+	struct cnode *p = NULL;
+	struct cnode *q = NULL;
+	int speed;
+
+	if (!bd) {
+		*ptr = 0xff;
+		return string;
+	}
+
+	for (p = bd->bd_config; p; p = p->next) {
+
+		switch (p->type) {
+		case LNODE:
+			*ptr = '\0';
+			ptr++;
+			*ptr = p->u.line.speed;
+			ptr++;
+			break;
+		case CNODE:
+			/*
+			 * Because the EPC/con concentrators can have EM modules
+			 * hanging off of them, we have to walk ahead in the list
+			 * and keep adding the number of ports on each EM to the config.
+			 * UGH!
+			 */
+			speed = p->u.conc.speed;
+			q = p->next;
+			if ((q != NULL) && (q->type == MNODE)) {
+				*ptr = (p->u.conc.nport + 0x80);
+				ptr++;
+				p = q;
+				while ((q->next != NULL) && (q->next->type) == MNODE) {
+					*ptr = (q->u.module.nport + 0x80);
+					ptr++;
+					p = q;
+					q = q->next;
+				}
+				*ptr = q->u.module.nport;
+				ptr++;
+			} else {
+				*ptr = p->u.conc.nport;
+				ptr++;
+			}
+
+			*ptr = speed;
+			ptr++;
+			break;
+		}
+	}
+
+	*ptr = 0xff;
+	return string;
+}
diff --git a/drivers/staging/dgap/dgap.h b/drivers/staging/dgap/dgap.h
new file mode 100644
index 0000000..e33e591
--- /dev/null
+++ b/drivers/staging/dgap/dgap.h
@@ -0,0 +1,1408 @@
+/*
+ * Copyright 2003 Digi International (www.digi.com)
+ *      Scott H Kilau <Scott_Kilau at digi dot com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE.  See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *	NOTE: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!!
+ *
+ *************************************************************************
+ *
+ * Driver includes
+ *
+ *************************************************************************/
+
+#ifndef __DGAP_DRIVER_H
+#define __DGAP_DRIVER_H
+
+#include <linux/types.h>        /* To pick up the varions Linux types */
+#include <linux/tty.h>          /* To pick up the various tty structs/defines */
+#include <linux/interrupt.h>    /* For irqreturn_t type */
+
+#ifndef TRUE
+# define TRUE 1
+#endif
+
+#ifndef FALSE
+# define FALSE 0
+#endif
+
+/* Required for our shared headers! */
+typedef unsigned char		uchar;
+
+#if !defined(TTY_FLIPBUF_SIZE)
+# define TTY_FLIPBUF_SIZE 512
+#endif
+
+/* Sparse stuff */
+# ifndef __user
+#  define __user
+#  define __kernel
+#  define __safe
+#  define __force
+#  define __chk_user_ptr(x) (void)0
+# endif
+
+
+#  define PARM_STR(VAR, INIT, PERM, DESC) \
+		static char *VAR = INIT; \
+		char *dgap_##VAR; \
+		module_param(VAR, charp, PERM); \
+		MODULE_PARM_DESC(VAR, DESC);
+
+#  define PARM_INT(VAR, INIT, PERM, DESC) \
+		static int VAR = INIT; \
+		int dgap_##VAR; \
+		module_param(VAR, int, PERM); \
+		MODULE_PARM_DESC(VAR, DESC);
+
+#  define PARM_ULONG(VAR, INIT, PERM, DESC) \
+		static ulong VAR = INIT; \
+		ulong dgap_##VAR; \
+		module_param(VAR, long, PERM); \
+		MODULE_PARM_DESC(VAR, DESC);
+
+/*************************************************************************
+ *
+ * Driver defines
+ *
+ *************************************************************************/
+
+/*
+ * Driver identification, error and debugging statments
+ *
+ * In theory, you can change all occurrences of "digi" in the next
+ * three lines, and the driver printk's will all automagically change.
+ *
+ * APR((fmt, args, ...));	Always prints message
+ * DPR((fmt, args, ...));	Only prints if DGAP_TRACER is defined at
+ *				  compile time and dgap_debug!=0
+ */
+#define	DG_NAME		"dgap-1.3-16"
+#define	DG_PART		"40002347_C"
+
+#define	PROCSTR		"dgap"			/* /proc entries	 */
+#define	DEVSTR		"/dev/dg/dgap"		/* /dev entries		 */
+#define	DRVSTR		"dgap"			/* Driver name string
+						 * displayed by APR	 */
+#define	APR(args)	do { PRINTF_TO_KMEM(args); printk(DRVSTR": "); printk args; \
+			   } while (0)
+#define	RAPR(args)	do { PRINTF_TO_KMEM(args); printk args; } while (0)
+
+#define TRC_TO_CONSOLE 1
+
+/*
+ * defines from dgap_pci.h
+ */ 
+#define PCIMAX 32			/* maximum number of PCI boards */
+
+#define DIGI_VID		0x114F
+
+#define PCI_DEVICE_EPC_DID	0x0002
+#define PCI_DEVICE_XEM_DID	0x0004
+#define PCI_DEVICE_XR_DID	0x0005
+#define PCI_DEVICE_CX_DID	0x0006
+#define PCI_DEVICE_XRJ_DID	0x0009	/* PLX-based Xr adapter */
+#define PCI_DEVICE_XR_IBM_DID	0x0011	/* IBM 8-port Async Adapter */
+#define PCI_DEVICE_XR_BULL_DID	0x0013	/* BULL 8-port Async Adapter */
+#define PCI_DEVICE_XR_SAIP_DID	0x001c	/* SAIP card - Xr adapter */
+#define PCI_DEVICE_XR_422_DID	0x0012	/* Xr-422 */
+#define PCI_DEVICE_920_2_DID	0x0034	/* XR-Plus 920 K, 2 port */
+#define PCI_DEVICE_920_4_DID	0x0026	/* XR-Plus 920 K, 4 port */
+#define PCI_DEVICE_920_8_DID	0x0027	/* XR-Plus 920 K, 8 port */
+#define PCI_DEVICE_EPCJ_DID	0x000a	/* PLX 9060 chip for PCI  */
+#define PCI_DEVICE_CX_IBM_DID	0x001b	/* IBM 128-port Async Adapter */
+#define PCI_DEVICE_920_8_HP_DID	0x0058	/* HP XR-Plus 920 K, 8 port */
+#define PCI_DEVICE_XEM_HP_DID	0x0059  /* HP Xem PCI */
+
+#define PCI_DEVICE_XEM_NAME	"AccelePort XEM"
+#define PCI_DEVICE_CX_NAME	"AccelePort CX"
+#define PCI_DEVICE_XR_NAME	"AccelePort Xr"
+#define PCI_DEVICE_XRJ_NAME	"AccelePort Xr (PLX)"
+#define PCI_DEVICE_XR_SAIP_NAME	"AccelePort Xr (SAIP)"
+#define PCI_DEVICE_920_2_NAME	"AccelePort Xr920 2 port"
+#define PCI_DEVICE_920_4_NAME	"AccelePort Xr920 4 port"
+#define PCI_DEVICE_920_8_NAME	"AccelePort Xr920 8 port"
+#define PCI_DEVICE_XR_422_NAME	"AccelePort Xr 422"
+#define PCI_DEVICE_EPCJ_NAME	"AccelePort EPC (PLX)"
+#define PCI_DEVICE_XR_BULL_NAME	"AccelePort Xr (BULL)"
+#define PCI_DEVICE_XR_IBM_NAME	"AccelePort Xr (IBM)"
+#define PCI_DEVICE_CX_IBM_NAME	"AccelePort CX (IBM)"
+#define PCI_DEVICE_920_8_HP_NAME "AccelePort Xr920 8 port (HP)"
+#define PCI_DEVICE_XEM_HP_NAME	"AccelePort XEM (HP)"
+
+/*
+ * On the PCI boards, there is no IO space allocated
+ * The I/O registers will be in the first 3 bytes of the
+ * upper 2MB of the 4MB memory space.  The board memory
+ * will be mapped into the low 2MB of the 4MB memory space
+ */
+
+/* Potential location of PCI Bios from E0000 to FFFFF*/
+#define PCI_BIOS_SIZE		0x00020000
+
+/* Size of Memory and I/O for PCI (4MB) */
+#define PCI_RAM_SIZE		0x00400000
+
+/* Size of Memory (2MB) */
+#define PCI_MEM_SIZE		0x00200000
+
+/* Max PCI Window Size (2MB) */
+#define PCI_WIN_SIZE		0x00200000
+
+#define PCI_WIN_SHIFT		21 /* 21 bits max */
+
+/* Offset of I/0 in Memory (2MB) */
+#define PCI_IO_OFFSET		0x00200000
+
+/* Size of IO (2MB) */
+#define PCI_IO_SIZE		0x00200000
+
+/* Number of boards we support at once. */
+#define	MAXBOARDS	32
+#define	MAXPORTS	224
+#define MAXTTYNAMELEN	200
+
+/* Our 3 magic numbers for our board, channel and unit structs */
+#define DGAP_BOARD_MAGIC	0x5c6df104
+#define DGAP_CHANNEL_MAGIC	0x6c6df104
+#define DGAP_UNIT_MAGIC		0x7c6df104
+
+/* Serial port types */
+#define DGAP_SERIAL		0
+#define DGAP_PRINT		1
+
+#define	SERIAL_TYPE_NORMAL	1
+
+/* 4 extra for alignment play space */
+#define WRITEBUFLEN		((4096) + 4)
+#define MYFLIPLEN		N_TTY_BUF_SIZE
+
+#define SBREAK_TIME 0x25
+#define U2BSIZE 0x400
+
+#define dgap_jiffies_from_ms(a) (((a) * HZ) / 1000)
+
+/*
+ * Our major for the mgmt devices.
+ *
+ * We can use 22, because Digi was allocated 22 and 23 for the epca driver.
+ * 22 has now become obsolete now that the "cu" devices have
+ * been removed from 2.6.
+ * Also, this *IS* the epca driver, just PCI only now.
+ */
+#ifndef DIGI_DGAP_MAJOR
+# define DIGI_DGAP_MAJOR         22
+#endif
+
+/*
+ * The parameters we use to define the periods of the moving averages.
+ */
+#define		MA_PERIOD	(HZ / 10)
+#define		SMA_DUR		(1 * HZ)
+#define		EMA_DUR		(1 * HZ)
+#define		SMA_NPERIODS	(SMA_DUR / MA_PERIOD)
+#define		EMA_NPERIODS	(EMA_DUR / MA_PERIOD)
+
+/*
+ * Define a local default termios struct. All ports will be created
+ * with this termios initially.  This is the same structure that is defined
+ * as the default in tty_io.c with the same settings overriden as in serial.c
+ *
+ * In short, this should match the internal serial ports' defaults.
+ */
+#define	DEFAULT_IFLAGS	(ICRNL | IXON)
+#define	DEFAULT_OFLAGS	(OPOST | ONLCR)
+#define	DEFAULT_CFLAGS	(B9600 | CS8 | CREAD | HUPCL | CLOCAL)
+#define	DEFAULT_LFLAGS	(ISIG | ICANON | ECHO | ECHOE | ECHOK | \
+			ECHOCTL | ECHOKE | IEXTEN)
+
+#ifndef _POSIX_VDISABLE
+#define   _POSIX_VDISABLE '\0'
+#endif
+
+#define SNIFF_MAX	65536		/* Sniff buffer size (2^n) */
+#define SNIFF_MASK	(SNIFF_MAX - 1)	/* Sniff wrap mask */
+
+#define VPDSIZE (512)
+
+/*
+ * Lock function/defines.
+ * Makes spotting lock/unlock locations easier.
+ */
+# define DGAP_SPINLOCK_INIT(x)		spin_lock_init(&(x))
+# define DGAP_LOCK(x,y)			spin_lock_irqsave(&(x), y)
+# define DGAP_UNLOCK(x,y)		spin_unlock_irqrestore(&(x), y)
+# define DGAP_TRYLOCK(x,y)		spin_trylock(&(x))
+
+/************************************************************************
+ *      FEP memory offsets
+ ************************************************************************/
+#define START           0x0004L         /* Execution start address      */
+
+#define CMDBUF          0x0d10L         /* Command (cm_t) structure offset */
+#define CMDSTART        0x0400L         /* Start of command buffer      */
+#define CMDMAX          0x0800L         /* End of command buffer        */
+
+#define EVBUF           0x0d18L         /* Event (ev_t) structure       */
+#define EVSTART         0x0800L         /* Start of event buffer        */
+#define EVMAX           0x0c00L         /* End of event buffer          */
+#define FEP5_PLUS       0x0E40          /* ASCII '5' and ASCII 'A' is here  */
+#define ECS_SEG         0x0E44          /* Segment of the extended channel structure */
+#define LINE_SPEED      0x10            /* Offset into ECS_SEG for line speed   */
+                                        /* if the fep has extended capabilities */
+
+/* BIOS MAGIC SPOTS */
+#define ERROR           0x0C14L		/* BIOS error code              */
+#define SEQUENCE	0x0C12L		/* BIOS sequence indicator      */
+#define POSTAREA	0x0C00L		/* POST complete message area   */
+
+/* FEP MAGIC SPOTS */
+#define FEPSTAT         POSTAREA        /* OS here when FEP comes up    */
+#define NCHAN           0x0C02L         /* number of ports FEP sees     */
+#define PANIC           0x0C10L         /* PANIC area for FEP           */
+#define KMEMEM          0x0C30L         /* Memory for KME use           */
+#define CONFIG          0x0CD0L         /* Concentrator configuration info */
+#define CONFIGSIZE      0x0030          /* configuration info size      */
+#define DOWNREQ         0x0D00          /* Download request buffer pointer */
+
+#define CHANBUF         0x1000L         /* Async channel (bs_t) structs */
+#define FEPOSSIZE       0x1FFF          /* 8K FEPOS                     */
+
+#define XEMPORTS    0xC02	/*
+				 * Offset in board memory where FEP5 stores
+				 * how many ports it has detected.
+				 * NOTE: FEP5 reports 64 ports when the user
+				 * has the cable in EBI OUT instead of EBI IN.
+				 */
+
+#define FEPCLR      0x00
+#define FEPMEM      0x02
+#define FEPRST      0x04
+#define FEPINT      0x08
+#define FEPMASK     0x0e
+#define FEPWIN      0x80
+
+#define LOWMEM      0x0100
+#define HIGHMEM     0x7f00
+
+#define FEPTIMEOUT 200000
+
+#define ENABLE_INTR		0x0e04		/* Enable interrupts flag */
+#define FEPPOLL_MIN		1		/* minimum of 1 millisecond */
+#define FEPPOLL_MAX		20		/* maximum of 20 milliseconds */
+#define FEPPOLL			0x0c26		/* Fep event poll interval */
+
+#define	IALTPIN			0x0080		/* Input flag to swap DSR <-> DCD */
+
+/************************************************************************
+ * FEP supported functions
+ ************************************************************************/
+#define SRLOW		0xe0		/* Set receive low water	*/
+#define SRHIGH		0xe1		/* Set receive high water	*/
+#define FLUSHTX		0xe2		/* Flush transmit buffer	*/
+#define PAUSETX		0xe3		/* Pause data transmission	*/
+#define RESUMETX	0xe4		/* Resume data transmission	*/
+#define SMINT		0xe5		/* Set Modem Interrupt		*/
+#define SAFLOWC		0xe6		/* Set Aux. flow control chars	*/
+#define SBREAK		0xe8		/* Send break			*/
+#define SMODEM		0xe9		/* Set 8530 modem control lines	*/
+#define SIFLAG		0xea		/* Set UNIX iflags		*/
+#define SFLOWC		0xeb		/* Set flow control characters	*/
+#define STLOW		0xec		/* Set transmit low water mark	*/
+#define RPAUSE		0xee		/* Pause receive		*/
+#define RRESUME		0xef		/* Resume receive		*/
+#define CHRESET		0xf0		/* Reset Channel		*/
+#define BUFSETALL	0xf2		/* Set Tx & Rx buffer size avail*/
+#define SOFLAG		0xf3		/* Set UNIX oflags		*/
+#define SHFLOW		0xf4		/* Set hardware handshake	*/
+#define SCFLAG		0xf5		/* Set UNIX cflags		*/
+#define SVNEXT		0xf6		/* Set VNEXT character		*/
+#define SPINTFC		0xfc		/* Reserved			*/
+#define SCOMMODE	0xfd		/* Set RS232/422 mode		*/
+
+
+/************************************************************************
+ *	Modes for SCOMMODE
+ ************************************************************************/
+#define MODE_232	0x00
+#define MODE_422	0x01
+
+
+/************************************************************************
+ *      Event flags.
+ ************************************************************************/
+#define IFBREAK         0x01            /* Break received               */
+#define IFTLW           0x02            /* Transmit low water           */
+#define IFTEM           0x04            /* Transmitter empty            */
+#define IFDATA          0x08            /* Receive data present         */
+#define IFMODEM         0x20            /* Modem status change          */
+
+/************************************************************************
+ *      Modem flags
+ ************************************************************************/
+#       define  DM_RTS          0x02    /* Request to send              */
+#       define  DM_CD           0x80    /* Carrier detect               */
+#       define  DM_DSR          0x20    /* Data set ready               */
+#       define  DM_CTS          0x10    /* Clear to send                */
+#       define  DM_RI           0x40    /* Ring indicator               */
+#       define  DM_DTR          0x01    /* Data terminal ready          */
+
+/*
+ * defines from dgap_conf.h
+ */
+#define NULLNODE 0		/* header node, not used */
+#define BNODE 1			/* Board node */
+#define LNODE 2			/* Line node */
+#define CNODE 3			/* Concentrator node */
+#define MNODE 4			/* EBI Module node */
+#define TNODE 5			/* tty name prefix node */
+#define	CUNODE 6		/* cu name prefix (non-SCO) */
+#define PNODE 7			/* trans. print prefix node */
+#define JNODE 8			/* maJor number node */
+#define ANODE 9			/* altpin */
+#define	TSNODE 10		/* tty structure size */
+#define CSNODE 11		/* channel structure size */
+#define BSNODE 12		/* board structure size */
+#define USNODE 13		/* unit schedule structure size */
+#define FSNODE 14		/* f2200 structure size */
+#define VSNODE 15		/* size of VPIX structures */
+#define INTRNODE 16		/* enable interrupt */
+
+/* Enumeration of tokens */
+#define	BEGIN	1
+#define	END	2
+#define	BOARD	10
+
+#define EPCFS	11 /* start of EPC family definitions */
+#define	ICX		11
+#define	MCX		13
+#define PCX	14
+#define	IEPC	15
+#define	EEPC	16
+#define	MEPC	17
+#define	IPCM	18
+#define	EPCM	19
+#define	MPCM	20
+#define PEPC	21
+#define PPCM	22
+#ifdef CP
+#define ICP     23
+#define ECP     24
+#define MCP     25
+#endif
+#define EPCFE	25 /* end of EPC family definitions */
+#define	PC2E	26
+#define	PC4E	27
+#define	PC4E8K	28
+#define	PC8E	29
+#define	PC8E8K	30
+#define	PC16E	31
+#define MC2E8K  34
+#define MC4E8K  35
+#define MC8E8K  36
+
+#define AVANFS	42	/* start of Avanstar family definitions */
+#define A8P 	42
+#define A16P	43
+#define AVANFE	43	/* end of Avanstar family definitions */
+
+#define DA2000FS	44	/* start of AccelePort 2000 family definitions */
+#define DA22 		44 /* AccelePort 2002 */
+#define DA24 		45 /* AccelePort 2004 */
+#define DA28		46 /* AccelePort 2008 */
+#define DA216		47 /* AccelePort 2016 */
+#define DAR4		48 /* AccelePort RAS 4 port */
+#define DAR8		49 /* AccelePort RAS 8 port */
+#define DDR24		50 /* DataFire RAS 24 port */
+#define DDR30		51 /* DataFire RAS 30 port */
+#define DDR48		52 /* DataFire RAS 48 port */
+#define DDR60		53 /* DataFire RAS 60 port */
+#define DA2000FE	53 /* end of AccelePort 2000/RAS family definitions */
+
+#define PCXRFS	106	/* start of PCXR family definitions */
+#define	APORT4	106
+#define	APORT8	107
+#define PAPORT4 108
+#define PAPORT8 109
+#define APORT4_920I	110
+#define APORT8_920I	111
+#define APORT4_920P	112
+#define APORT8_920P	113
+#define APORT2_920P 114
+#define PCXRFE	117	/* end of PCXR family definitions */
+
+#define	LINE	82
+#ifdef T1
+#define T1M	83
+#define E1M	84
+#endif
+#define	CONC	64
+#define	CX	65
+#define	EPC	66
+#define	MOD	67
+#define	PORTS	68
+#define METHOD	69
+#define CUSTOM	70
+#define BASIC	71
+#define STATUS	72
+#define MODEM	73
+/* The following tokens can appear in multiple places */
+#define	SPEED	74
+#define	NPORTS	75
+#define	ID	76
+#define CABLE	77
+#define CONNECT	78
+#define	IO	79
+#define	MEM	80
+#define DPSZ	81
+
+#define	TTYN	90
+#define	CU	91
+#define	PRINT	92
+#define	XPRINT	93
+#define CMAJOR   94
+#define ALTPIN  95
+#define STARTO 96
+#define USEINTR  97
+#define PCIINFO  98
+
+#define	TTSIZ	100
+#define	CHSIZ	101
+#define BSSIZ	102
+#define	UNTSIZ	103
+#define	F2SIZ	104
+#define	VPSIZ	105
+
+#define	TOTAL_BOARD	2
+#define	CURRENT_BRD	4
+#define	BOARD_TYPE	6
+#define	IO_ADDRESS	8
+#define	MEM_ADDRESS	10
+
+#define	FIELDS_PER_PAGE	18
+
+#define TB_FIELD	1
+#define CB_FIELD	3
+#define BT_FIELD	5
+#define IO_FIELD	7
+#define ID_FIELD	8
+#define ME_FIELD	9
+#define TTY_FIELD	11
+#define CU_FIELD	13
+#define PR_FIELD	15
+#define MPR_FIELD	17
+
+#define	MAX_FIELD	512
+
+#define	INIT		0
+#define	NITEMS		128
+#define MAX_ITEM	512
+
+#define	DSCRINST	1
+#define	DSCRNUM		3
+#define	ALTPINQ		5
+#define	SSAVE		7
+
+#define	DSCR		"32"
+#define	ONETONINE	"123456789"
+#define	ALL		"1234567890"
+
+/*
+ * All the possible states the driver can be while being loaded.
+ */
+enum {
+	DRIVER_INITIALIZED = 0,
+	DRIVER_NEED_CONFIG_LOAD,
+	DRIVER_REQUESTED_CONFIG,
+	DRIVER_READY
+};
+
+/*
+ * All the possible states the board can be while booting up.
+ */
+enum {
+	BOARD_FAILED = 0,
+	CONFIG_NOT_FOUND,
+	BOARD_FOUND,
+	NEED_RESET,
+	FINISHED_RESET,
+	NEED_CONFIG,
+	FINISHED_CONFIG,
+	NEED_DEVICE_CREATION,
+	REQUESTED_DEVICE_CREATION,
+	FINISHED_DEVICE_CREATION,
+	NEED_BIOS_LOAD,
+	REQUESTED_BIOS,
+	WAIT_BIOS_LOAD,
+	FINISHED_BIOS_LOAD,
+	NEED_FEP_LOAD,
+	REQUESTED_FEP,
+	WAIT_FEP_LOAD,
+	FINISHED_FEP_LOAD,
+	NEED_PROC_CREATION,
+	FINISHED_PROC_CREATION,
+	BOARD_READY
+};
+
+/*
+ * All the possible states that a requested concentrator image can be in.
+ */
+enum {
+	NO_PENDING_CONCENTRATOR_REQUESTS = 0,
+	NEED_CONCENTRATOR,
+	REQUESTED_CONCENTRATOR
+};
+
+
+
+/*
+ * Modem line constants are defined as macros because DSR and
+ * DCD are swapable using the ditty altpin option.
+ */
+#define D_CD(ch)        ch->ch_cd       /* Carrier detect       */
+#define D_DSR(ch)       ch->ch_dsr      /* Data set ready       */
+#define D_RTS(ch)       DM_RTS          /* Request to send      */
+#define D_CTS(ch)       DM_CTS          /* Clear to send        */
+#define D_RI(ch)        DM_RI           /* Ring indicator       */
+#define D_DTR(ch)       DM_DTR          /* Data terminal ready  */
+
+
+/*************************************************************************
+ *
+ * Structures and closely related defines.
+ *
+ *************************************************************************/
+
+
+/*
+ * A structure to hold a statistics counter.  We also
+ * compute moving averages for this counter.
+ */
+struct macounter
+{
+	u32		cnt;	/* Total count */
+	ulong		accum;	/* Acuumulator per period */
+	ulong		sma;	/* Simple moving average */
+	ulong		ema;	/* Exponential moving average */
+};
+
+
+/************************************************************************
+ * Device flag definitions for bd_flags.
+ ************************************************************************/
+#define	BD_FEP5PLUS	0x0001          /* Supports FEP5 Plus commands */
+#define BD_HAS_VPD	0x0002		/* Board has VPD info available */
+
+/*
+ *	Per-board information
+ */
+struct board_t
+{
+	int		magic;		/* Board Magic number.  */
+	int		boardnum;	/* Board number: 0-3 */
+	int		firstminor;	/* First minor, e.g. 0, 30, 60 */
+
+	int		type;		/* Type of board */
+	char		*name;		/* Product Name */
+	struct pci_dev	*pdev;		/* Pointer to the pci_dev struct */
+	u16		vendor;		/* PCI vendor ID */
+	u16		device;		/* PCI device ID */
+	u16		subvendor;	/* PCI subsystem vendor ID */
+	u16		subdevice;	/* PCI subsystem device ID */
+	uchar		rev;		/* PCI revision ID */
+	uint		pci_bus;	/* PCI bus value */
+	uint		pci_slot;	/* PCI slot value */
+	u16		maxports;	/* MAX ports this board can handle */
+	uchar		vpd[VPDSIZE];	/* VPD of board, if found */
+	u32		bd_flags;	/* Board flags */
+
+	spinlock_t	bd_lock;	/* Used to protect board */
+
+	u32		state;		/* State of card. */
+	wait_queue_head_t state_wait;	/* Place to sleep on for state change */
+
+	struct		tasklet_struct helper_tasklet; /* Poll helper tasklet */
+
+	u32		wait_for_bios;
+	u32		wait_for_fep;
+
+	struct cnode *  bd_config;	/* Config of board */
+
+	u16		nasync;		/* Number of ports on card */
+
+	u32		use_interrupts;	/* Should we be interrupt driven? */
+	ulong		irq;		/* Interrupt request number */
+	ulong		intr_count;	/* Count of interrupts */
+	u32		intr_used;	/* Non-zero if using interrupts */
+	u32		intr_running;	/* Non-zero if FEP knows its doing interrupts */
+
+	ulong		port;		/* Start of base io port of the card */
+	ulong		port_end;	/* End of base io port of the card */
+	ulong		membase;	/* Start of base memory of the card */
+	ulong		membase_end;	/* End of base memory of the card */
+
+	uchar 		*re_map_port;	/* Remapped io port of the card */
+	uchar		*re_map_membase;/* Remapped memory of the card */
+
+	uchar		runwait;	/* # Processes waiting for FEP  */
+	uchar		inhibit_poller; /* Tells  the poller to leave us alone */
+
+	struct channel_t *channels[MAXPORTS]; /* array of pointers to our channels. */
+
+	struct tty_driver	*SerialDriver;
+	struct tty_port *SerialPorts;
+	char		SerialName[200];
+	struct tty_driver	*PrintDriver;
+	struct tty_port *PrinterPorts;
+	char		PrintName[200];
+
+	u32		dgap_Major_Serial_Registered;
+	u32		dgap_Major_TransparentPrint_Registered;
+
+	u32		dgap_Serial_Major;
+	u32		dgap_TransparentPrint_Major;
+
+	struct bs_t	*bd_bs;			/* Base structure pointer       */
+
+	char	*flipbuf;		/* Our flip buffer, alloced if board is found */
+	char	*flipflagbuf;		/* Our flip flag buffer, alloced if board is found */
+
+	u16		dpatype;	/* The board "type", as defined by DPA */
+	u16		dpastatus;	/* The board "status", as defined by DPA */
+	wait_queue_head_t kme_wait;	/* Needed for DPA support */
+
+	u32		conc_dl_status;	/* Status of any pending conc download */
+	/*
+	 *	Mgmt data.
+	 */
+        char		*msgbuf_head;
+        char		*msgbuf;
+};
+
+
+
+/************************************************************************
+ * Unit flag definitions for un_flags.
+ ************************************************************************/
+#define UN_ISOPEN	0x0001		/* Device is open		*/
+#define UN_CLOSING	0x0002		/* Line is being closed		*/
+#define UN_IMM		0x0004		/* Service immediately		*/
+#define UN_BUSY		0x0008		/* Some work this channel	*/
+#define UN_BREAKI	0x0010		/* Input break received		*/
+#define UN_PWAIT	0x0020		/* Printer waiting for terminal	*/
+#define UN_TIME		0x0040		/* Waiting on time		*/
+#define UN_EMPTY	0x0080		/* Waiting output queue empty	*/
+#define UN_LOW		0x0100		/* Waiting output low water mark*/
+#define UN_EXCL_OPEN	0x0200		/* Open for exclusive use	*/
+#define UN_WOPEN	0x0400		/* Device waiting for open	*/
+#define UN_WIOCTL	0x0800		/* Device waiting for open	*/
+#define UN_HANGUP	0x8000		/* Carrier lost			*/
+
+struct device;
+
+/************************************************************************
+ * Structure for terminal or printer unit.
+ ************************************************************************/
+struct un_t {
+	int	magic;		/* Unit Magic Number.			*/
+	struct	channel_t *un_ch;
+	u32	un_time;
+	u32	un_type;
+	u32	un_open_count;	/* Counter of opens to port		*/
+	struct tty_struct *un_tty;/* Pointer to unit tty structure	*/
+	u32	un_flags;	/* Unit flags				*/
+	wait_queue_head_t un_flags_wait; /* Place to sleep to wait on unit */
+	u32	un_dev;		/* Minor device number			*/
+	tcflag_t un_oflag;	/* oflags being done on board		*/
+	tcflag_t un_lflag;	/* lflags being done on board		*/
+	struct device *un_sysfs;
+};
+
+
+/************************************************************************
+ * Device flag definitions for ch_flags.
+ ************************************************************************/
+#define CH_PRON         0x0001          /* Printer on string                */
+#define CH_OUT          0x0002          /* Dial-out device open             */
+#define CH_STOP         0x0004          /* Output is stopped                */
+#define CH_STOPI        0x0008          /* Input is stopped                 */
+#define CH_CD           0x0010          /* Carrier is present               */
+#define CH_FCAR         0x0020          /* Carrier forced on                */
+
+#define CH_RXBLOCK      0x0080          /* Enable rx blocked flag           */
+#define CH_WLOW         0x0100          /* Term waiting low event           */
+#define CH_WEMPTY       0x0200          /* Term waiting empty event         */
+#define CH_RENABLE      0x0400          /* Buffer just emptied          */
+#define CH_RACTIVE      0x0800          /* Process active in xxread()   */
+#define CH_RWAIT        0x1000          /* Process waiting in xxread()  */
+#define CH_BAUD0	0x2000		/* Used for checking B0 transitions */
+#define CH_HANGUP       0x8000		/* Hangup received                  */
+
+/*
+ * Definitions for ch_sniff_flags
+ */
+#define SNIFF_OPEN	0x1
+#define SNIFF_WAIT_DATA	0x2
+#define SNIFF_WAIT_SPACE 0x4
+
+
+/************************************************************************
+ ***	Definitions for Digi ditty(1) command.
+ ************************************************************************/
+
+
+/*
+ * Copyright (c) 1988-96 Digi International Inc., All Rights Reserved.
+ */
+
+/************************************************************************
+ * This module provides application access to special Digi
+ * serial line enhancements which are not standard UNIX(tm) features.
+ ************************************************************************/
+
+#if !defined(TIOCMODG)
+
+#define	TIOCMODG	('d'<<8) | 250		/* get modem ctrl state	*/
+#define	TIOCMODS	('d'<<8) | 251		/* set modem ctrl state	*/
+
+#ifndef TIOCM_LE
+#define		TIOCM_LE	0x01		/* line enable		*/
+#define		TIOCM_DTR	0x02		/* data terminal ready	*/
+#define		TIOCM_RTS	0x04		/* request to send	*/
+#define		TIOCM_ST	0x08		/* secondary transmit	*/
+#define		TIOCM_SR	0x10		/* secondary receive	*/
+#define		TIOCM_CTS	0x20		/* clear to send	*/
+#define		TIOCM_CAR	0x40		/* carrier detect	*/
+#define		TIOCM_RNG	0x80		/* ring	indicator	*/
+#define		TIOCM_DSR	0x100		/* data set ready	*/
+#define		TIOCM_RI	TIOCM_RNG	/* ring (alternate)	*/
+#define		TIOCM_CD	TIOCM_CAR	/* carrier detect (alt)	*/
+#endif
+
+#endif
+
+#if !defined(TIOCMSET)
+#define	TIOCMSET	('d'<<8) | 252		/* set modem ctrl state	*/
+#define	TIOCMGET	('d'<<8) | 253		/* set modem ctrl state	*/
+#endif
+
+#if !defined(TIOCMBIC)
+#define	TIOCMBIC	('d'<<8) | 254		/* set modem ctrl state */
+#define	TIOCMBIS	('d'<<8) | 255		/* set modem ctrl state */
+#endif
+
+
+#if !defined(TIOCSDTR)
+#define	TIOCSDTR	('e'<<8) | 0		/* set DTR		*/
+#define	TIOCCDTR	('e'<<8) | 1		/* clear DTR		*/
+#endif
+
+/************************************************************************
+ * Ioctl command arguments for DIGI parameters.
+ ************************************************************************/
+#define DIGI_GETA	('e'<<8) | 94		/* Read params		*/
+
+#define DIGI_SETA	('e'<<8) | 95		/* Set params		*/
+#define DIGI_SETAW	('e'<<8) | 96		/* Drain & set params	*/
+#define DIGI_SETAF	('e'<<8) | 97		/* Drain, flush & set params */
+
+#define DIGI_KME	('e'<<8) | 98		/* Read/Write Host	*/
+						/* Adapter Memory	*/
+
+#define	DIGI_GETFLOW	('e'<<8) | 99		/* Get startc/stopc flow */
+						/* control characters 	 */
+#define	DIGI_SETFLOW	('e'<<8) | 100		/* Set startc/stopc flow */
+						/* control characters	 */
+#define	DIGI_GETAFLOW	('e'<<8) | 101		/* Get Aux. startc/stopc */
+						/* flow control chars 	 */
+#define	DIGI_SETAFLOW	('e'<<8) | 102		/* Set Aux. startc/stopc */
+						/* flow control chars	 */
+
+#define DIGI_GEDELAY	('d'<<8) | 246		/* Get edelay */
+#define DIGI_SEDELAY	('d'<<8) | 247		/* Set edelay */
+
+struct	digiflow_t {
+	unsigned char	startc;				/* flow cntl start char	*/
+	unsigned char	stopc;				/* flow cntl stop char	*/
+};
+
+
+#ifdef	FLOW_2200
+#define	F2200_GETA	('e'<<8) | 104		/* Get 2x36 flow cntl flags */
+#define	F2200_SETAW	('e'<<8) | 105		/* Set 2x36 flow cntl flags */
+#define		F2200_MASK	0x03		/* 2200 flow cntl bit mask  */
+#define		FCNTL_2200	0x01		/* 2x36 terminal flow cntl  */
+#define		PCNTL_2200	0x02		/* 2x36 printer flow cntl   */
+#define	F2200_XON	0xf8
+#define	P2200_XON	0xf9
+#define	F2200_XOFF	0xfa
+#define	P2200_XOFF	0xfb
+
+#define	FXOFF_MASK	0x03			/* 2200 flow status mask    */
+#define	RCVD_FXOFF	0x01			/* 2x36 Terminal XOFF rcvd  */
+#define	RCVD_PXOFF	0x02			/* 2x36 Printer XOFF rcvd   */
+#endif
+
+/************************************************************************
+ * Values for digi_flags
+ ************************************************************************/
+#define DIGI_IXON	0x0001		/* Handle IXON in the FEP	*/
+#define DIGI_FAST	0x0002		/* Fast baud rates		*/
+#define RTSPACE		0x0004		/* RTS input flow control	*/
+#define CTSPACE		0x0008		/* CTS output flow control	*/
+#define DSRPACE		0x0010		/* DSR output flow control	*/
+#define DCDPACE		0x0020		/* DCD output flow control	*/
+#define DTRPACE		0x0040		/* DTR input flow control	*/
+#define DIGI_COOK	0x0080		/* Cooked processing done in FEP */
+#define DIGI_FORCEDCD	0x0100		/* Force carrier		*/
+#define	DIGI_ALTPIN	0x0200		/* Alternate RJ-45 pin config	*/
+#define	DIGI_AIXON	0x0400		/* Aux flow control in fep	*/
+#define	DIGI_PRINTER	0x0800		/* Hold port open for flow cntrl*/
+#define DIGI_PP_INPUT	0x1000		/* Change parallel port to input*/
+#define DIGI_DTR_TOGGLE 0x2000		/* Support DTR Toggle		*/
+#define	DIGI_422	0x4000		/* for 422/232 selectable panel */
+#define DIGI_RTS_TOGGLE	0x8000		/* Support RTS Toggle		*/
+
+/************************************************************************
+ * These options are not supported on the comxi.
+ ************************************************************************/
+#define	DIGI_COMXI	(DIGI_FAST|DIGI_COOK|DSRPACE|DCDPACE|DTRPACE)
+
+#define DIGI_PLEN	28		/* String length		*/
+#define	DIGI_TSIZ	10		/* Terminal string len		*/
+
+/************************************************************************
+ * Structure used with ioctl commands for DIGI parameters.
+ ************************************************************************/
+struct digi_t {
+	unsigned short	digi_flags;		/* Flags (see above)	*/
+	unsigned short	digi_maxcps;		/* Max printer CPS	*/
+	unsigned short	digi_maxchar;		/* Max chars in print queue */
+	unsigned short	digi_bufsize;		/* Buffer size		*/
+	unsigned char	digi_onlen;		/* Length of ON string	*/
+	unsigned char	digi_offlen;		/* Length of OFF string	*/
+	char		digi_onstr[DIGI_PLEN];	/* Printer on string	*/
+	char		digi_offstr[DIGI_PLEN];	/* Printer off string	*/
+	char		digi_term[DIGI_TSIZ];	/* terminal string	*/
+};
+
+/************************************************************************
+ * KME definitions and structures.
+ ************************************************************************/
+#define	RW_IDLE		0	/* Operation complete			*/
+#define	RW_READ		1	/* Read Concentrator Memory		*/
+#define	RW_WRITE	2	/* Write Concentrator Memory		*/
+
+struct rw_t {
+	unsigned char	rw_req;		/* Request type			*/
+	unsigned char	rw_board;	/* Host Adapter board number	*/
+	unsigned char	rw_conc;	/* Concentrator number		*/
+	unsigned char	rw_reserved;	/* Reserved for expansion	*/
+	unsigned long	rw_addr;	/* Address in concentrator	*/
+	unsigned short	rw_size;	/* Read/write request length	*/
+	unsigned char	rw_data[128];	/* Data to read/write		*/
+};
+
+/***********************************************************************
+ * Shrink Buffer and Board Information definitions and structures.
+
+ ************************************************************************/
+			/* Board type return codes */
+#define	PCXI_TYPE 1     /* Board type at the designated port is a PC/Xi */
+#define PCXM_TYPE 2     /* Board type at the designated port is a PC/Xm */
+#define	PCXE_TYPE 3     /* Board type at the designated port is a PC/Xe */
+#define	MCXI_TYPE 4     /* Board type at the designated port is a MC/Xi */
+#define COMXI_TYPE 5     /* Board type at the designated port is a COM/Xi */
+
+			 /* Non-Zero Result codes. */
+#define RESULT_NOBDFND 1 /* A Digi product at that port is not config installed */
+#define RESULT_NODESCT 2 /* A memory descriptor was not obtainable */
+#define RESULT_NOOSSIG 3 /* FEP/OS signature was not detected on the board */
+#define RESULT_TOOSML  4 /* Too small an area to shrink.  */
+#define RESULT_NOCHAN  5 /* Channel structure for the board was not found */
+
+struct shrink_buf_struct {
+	unsigned long	shrink_buf_vaddr;	/* Virtual address of board */
+	unsigned long	shrink_buf_phys;	/* Physical address of board */
+	unsigned long	shrink_buf_bseg;	/* Amount of board memory */
+	unsigned long	shrink_buf_hseg;	/* '186 Beginning of Dual-Port */
+
+	unsigned long	shrink_buf_lseg;	/* '186 Beginning of freed memory						*/
+	unsigned long	shrink_buf_mseg;	/* Linear address from start of
+						   dual-port were freed memory
+						   begins, host viewpoint. */
+
+	unsigned long	shrink_buf_bdparam;	/* Parameter for xxmemon and
+						   xxmemoff */
+
+	unsigned long	shrink_buf_reserva;	/* Reserved */
+	unsigned long	shrink_buf_reservb;	/* Reserved */
+	unsigned long	shrink_buf_reservc;	/* Reserved */
+	unsigned long	shrink_buf_reservd;	/* Reserved */
+
+	unsigned char	shrink_buf_result;	/* Reason for call failing
+						   Zero is Good return */
+	unsigned char	shrink_buf_init;	/* Non-Zero if it caused an
+						   xxinit call. */
+
+	unsigned char	shrink_buf_anports;	/* Number of async ports  */
+	unsigned char	shrink_buf_snports; 	/* Number of sync  ports */
+	unsigned char	shrink_buf_type;	/* Board type 1 = PC/Xi,
+							      2 = PC/Xm,
+							      3 = PC/Xe
+							      4 = MC/Xi
+							      5 = COMX/i */
+	unsigned char	shrink_buf_card;	/* Card number */
+
+};
+
+/************************************************************************
+ * Structure to get driver status information
+ ************************************************************************/
+struct digi_dinfo {
+	unsigned long	dinfo_nboards;		/* # boards configured	*/
+	char		dinfo_reserved[12];	/* for future expansion */
+	char		dinfo_version[16];	/* driver version       */
+};
+
+#define	DIGI_GETDD	('d'<<8) | 248		/* get driver info      */
+
+/************************************************************************
+ * Structure used with ioctl commands for per-board information
+ *
+ * physsize and memsize differ when board has "windowed" memory
+ ************************************************************************/
+struct digi_info {
+	unsigned long	info_bdnum;		/* Board number (0 based)  */
+	unsigned long	info_ioport;		/* io port address         */
+	unsigned long	info_physaddr;		/* memory address          */
+	unsigned long	info_physsize;		/* Size of host mem window */
+	unsigned long	info_memsize;		/* Amount of dual-port mem */
+						/* on board                */
+	unsigned short	info_bdtype;		/* Board type              */
+	unsigned short	info_nports;		/* number of ports         */
+	char		info_bdstate;		/* board state             */
+	char		info_reserved[7];	/* for future expansion    */
+};
+
+#define	DIGI_GETBD	('d'<<8) | 249		/* get board info          */
+
+struct digi_stat {
+	unsigned int	info_chan;		/* Channel number (0 based)  */
+	unsigned int	info_brd;		/* Board number (0 based)  */
+	unsigned long	info_cflag;		/* cflag for channel       */
+	unsigned long	info_iflag;		/* iflag for channel       */
+	unsigned long	info_oflag;		/* oflag for channel       */
+	unsigned long	info_mstat;		/* mstat for channel       */
+	unsigned long	info_tx_data;		/* tx_data for channel       */
+	unsigned long	info_rx_data;		/* rx_data for channel       */
+	unsigned long	info_hflow;		/* hflow for channel       */
+	unsigned long	info_reserved[8];	/* for future expansion    */
+};
+
+#define	DIGI_GETSTAT	('d'<<8) | 244		/* get board info          */
+/************************************************************************
+ *
+ * Structure used with ioctl commands for per-channel information
+ *
+ ************************************************************************/
+struct digi_ch {
+	unsigned long	info_bdnum;		/* Board number (0 based)  */
+	unsigned long	info_channel;		/* Channel index number    */
+	unsigned long	info_ch_cflag;		/* Channel cflag   	   */
+	unsigned long	info_ch_iflag;		/* Channel iflag   	   */
+	unsigned long	info_ch_oflag;		/* Channel oflag   	   */
+	unsigned long	info_chsize;		/* Channel structure size  */
+	unsigned long	info_sleep_stat;	/* sleep status		   */
+	dev_t		info_dev;		/* device number	   */
+	unsigned char	info_initstate;		/* Channel init state	   */
+	unsigned char	info_running;		/* Channel running state   */
+	long		reserved[8];		/* reserved for future use */
+};
+
+/*
+* This structure is used with the DIGI_FEPCMD ioctl to
+* tell the driver which port to send the command for.
+*/
+struct digi_cmd {
+	int	cmd;
+	int	word;
+	int	ncmds;
+	int	chan; /* channel index (zero based) */
+	int	bdid; /* board index (zero based) */
+};
+
+/*
+*  info_sleep_stat defines
+*/
+#define INFO_RUNWAIT	0x0001
+#define INFO_WOPEN	0x0002
+#define INFO_TTIOW	0x0004
+#define INFO_CH_RWAIT	0x0008
+#define INFO_CH_WEMPTY	0x0010
+#define INFO_CH_WLOW	0x0020
+#define INFO_XXBUF_BUSY 0x0040
+
+#define	DIGI_GETCH	('d'<<8) | 245		/* get board info          */
+
+/* Board type definitions */
+
+#define	SUBTYPE		0007
+#define	T_PCXI		0000
+#define T_PCXM		0001
+#define T_PCXE		0002
+#define T_PCXR		0003
+#define T_SP		0004
+#define T_SP_PLUS	0005
+#	define T_HERC	0000
+#	define T_HOU	0001
+#	define T_LON	0002
+#	define T_CHA	0003
+#define FAMILY		0070
+#define T_COMXI		0000
+#define T_PCXX		0010
+#define T_CX		0020
+#define T_EPC		0030
+#define	T_PCLITE	0040
+#define	T_SPXX		0050
+#define	T_AVXX		0060
+#define T_DXB		0070
+#define T_A2K_4_8	0070
+#define BUSTYPE		0700
+#define T_ISABUS	0000
+#define T_MCBUS		0100
+#define	T_EISABUS	0200
+#define	T_PCIBUS	0400
+
+/* Board State Definitions */
+
+#define	BD_RUNNING	0x0
+#define	BD_REASON	0x7f
+#define	BD_NOTFOUND	0x1
+#define	BD_NOIOPORT	0x2
+#define	BD_NOMEM	0x3
+#define	BD_NOBIOS	0x4
+#define	BD_NOFEP	0x5
+#define	BD_FAILED	0x6
+#define BD_ALLOCATED	0x7
+#define BD_TRIBOOT	0x8
+#define	BD_BADKME	0x80
+
+#define DIGI_LOOPBACK	      ('d'<<8) | 252		/* Enable/disable UART internal loopback */
+#define DIGI_SPOLL            ('d'<<8) | 254		/* change poller rate   */
+
+#define DIGI_SETCUSTOMBAUD	_IOW('e', 106, int)	/* Set integer baud rate */
+#define DIGI_GETCUSTOMBAUD	_IOR('e', 107, int)	/* Get integer baud rate */
+#define DIGI_RESET_PORT		('e'<<8) | 93		/* Reset port		*/
+
+/************************************************************************
+ * Channel information structure.
+ ************************************************************************/
+struct channel_t {
+	int magic;			/* Channel Magic Number		*/
+	struct bs_t	*ch_bs;		/* Base structure pointer       */
+	struct cm_t	*ch_cm;		/* Command queue pointer        */
+	struct board_t *ch_bd;		/* Board structure pointer      */
+	unsigned char *ch_vaddr;	/* FEP memory origin            */
+	unsigned char *ch_taddr;	/* Write buffer origin          */
+	unsigned char *ch_raddr;	/* Read buffer origin           */
+	struct digi_t  ch_digi;		/* Transparent Print structure  */
+	struct un_t ch_tun;		/* Terminal unit info           */
+	struct un_t ch_pun;		/* Printer unit info            */
+
+	spinlock_t	ch_lock;	/* provide for serialization */
+	wait_queue_head_t ch_flags_wait;
+
+	u32	pscan_state;
+	uchar	pscan_savechar;
+
+	u32 ch_portnum;			/* Port number, 0 offset.	*/
+	u32 ch_open_count;		/* open count			*/
+	u32	ch_flags;		/* Channel flags                */
+
+
+	u32	ch_close_delay;		/* How long we should drop RTS/DTR for */
+
+	u32	ch_cpstime;		/* Time for CPS calculations    */
+
+	tcflag_t ch_c_iflag;		/* channel iflags               */
+	tcflag_t ch_c_cflag;		/* channel cflags               */
+	tcflag_t ch_c_oflag;		/* channel oflags               */
+	tcflag_t ch_c_lflag;		/* channel lflags               */
+
+	u16  ch_fepiflag;            /* FEP tty iflags               */
+	u16  ch_fepcflag;		/* FEP tty cflags               */
+	u16  ch_fepoflag;		/* FEP tty oflags               */
+	u16  ch_wopen;			/* Waiting for open process cnt */
+	u16  ch_tstart;			/* Transmit buffer start        */
+	u16  ch_tsize;			/* Transmit buffer size         */
+	u16  ch_rstart;			/* Receive buffer start         */
+	u16  ch_rsize;			/* Receive buffer size          */
+	u16  ch_rdelay;			/* Receive delay time           */
+
+	u16	ch_tlw;			/* Our currently set low water mark */
+
+	u16  ch_cook;			/* Output character mask        */
+
+	uchar   ch_card;		/* Card channel is on           */
+	uchar   ch_stopc;		/* Stop character               */
+	uchar   ch_startc;		/* Start character              */
+
+	uchar   ch_mostat;		/* FEP output modem status      */
+	uchar   ch_mistat;		/* FEP input modem status       */
+	uchar   ch_mforce;		/* Modem values to be forced    */
+	uchar   ch_mval;		/* Force values                 */
+	uchar   ch_fepstopc;		/* FEP stop character           */
+	uchar   ch_fepstartc;		/* FEP start character          */
+
+	uchar   ch_astopc;		/* Auxiliary Stop character     */
+	uchar   ch_astartc;		/* Auxiliary Start character    */
+	uchar   ch_fepastopc;		/* Auxiliary FEP stop char      */
+	uchar   ch_fepastartc;		/* Auxiliary FEP start char     */
+
+	uchar   ch_hflow;		/* FEP hardware handshake       */
+	uchar   ch_dsr;			/* stores real dsr value        */
+	uchar   ch_cd;			/* stores real cd value         */
+	uchar   ch_tx_win;		/* channel tx buffer window     */
+	uchar   ch_rx_win;		/* channel rx buffer window     */
+	uint	ch_custom_speed;	/* Custom baud, if set		*/
+	uint	ch_baud_info;		/* Current baud info for /proc output	*/
+	ulong	ch_rxcount;		/* total of data received so far	*/
+	ulong	ch_txcount;		/* total of data transmitted so far	*/
+	ulong	ch_err_parity;		/* Count of parity errors on channel	*/
+	ulong	ch_err_frame;		/* Count of framing errors on channel	*/
+	ulong	ch_err_break;		/* Count of breaks on channel	*/
+	ulong	ch_err_overrun;		/* Count of overruns on channel	*/
+
+	uint ch_sniff_in;
+	uint ch_sniff_out;
+	char *ch_sniff_buf;		/* Sniff buffer for proc */
+	ulong ch_sniff_flags;		/* Channel flags                */
+	wait_queue_head_t ch_sniff_wait;
+};
+
+/************************************************************************
+ * Command structure definition.
+ ************************************************************************/
+struct cm_t {
+	volatile unsigned short cm_head;	/* Command buffer head offset	*/
+	volatile unsigned short cm_tail;	/* Command buffer tail offset	*/
+	volatile unsigned short cm_start;	/* start offset of buffer	*/
+	volatile unsigned short cm_max;		/* last offset of buffer	*/
+};
+
+/************************************************************************
+ * Event structure definition.
+ ************************************************************************/
+struct ev_t {
+	volatile unsigned short ev_head;	/* Command buffer head offset	*/
+	volatile unsigned short ev_tail;	/* Command buffer tail offset	*/
+	volatile unsigned short ev_start;	/* start offset of buffer	*/
+	volatile unsigned short ev_max;		/* last offset of buffer	*/
+};
+
+/************************************************************************
+ * Download buffer structure.
+ ************************************************************************/
+struct downld_t {
+	uchar	dl_type;		/* Header                       */
+	uchar	dl_seq;			/* Download sequence            */
+	ushort	dl_srev;		/* Software revision number     */
+	ushort	dl_lrev;		/* Low revision number          */
+	ushort	dl_hrev;		/* High revision number         */
+	ushort	dl_seg;			/* Start segment address        */
+	ushort	dl_size;		/* Number of bytes to download  */
+	uchar	dl_data[1024];		/* Download data                */
+};
+
+/************************************************************************
+ * Per channel buffer structure
+ ************************************************************************
+ *              Base Structure Entries Usage Meanings to Host           *
+ *                                                                      *
+ *        W = read write        R = read only                           *
+ *        C = changed by commands only                                  *
+ *        U = unknown (may be changed w/o notice)                       *
+ ************************************************************************/
+struct bs_t {
+	volatile unsigned short  tp_jmp;	/* Transmit poll jump		 */
+	volatile unsigned short  tc_jmp;	/* Cooked procedure jump	 */
+	volatile unsigned short  ri_jmp;	/* Not currently used		 */
+	volatile unsigned short  rp_jmp;	/* Receive poll jump		 */
+
+	volatile unsigned short  tx_seg;	/* W  Tx segment	 */
+	volatile unsigned short  tx_head;	/* W  Tx buffer head offset	*/
+	volatile unsigned short  tx_tail;	/* R  Tx buffer tail offset	*/
+	volatile unsigned short  tx_max;	/* W  Tx buffer size - 1	 */
+
+	volatile unsigned short  rx_seg;	/* W  Rx segment		*/
+	volatile unsigned short  rx_head;	/* W  Rx buffer head offset	*/
+	volatile unsigned short  rx_tail;	/* R  Rx buffer tail offset	*/
+	volatile unsigned short  rx_max;	/* W  Rx buffer size - 1	 */
+
+	volatile unsigned short  tx_lw;		/* W  Tx buffer low water mark  */
+	volatile unsigned short  rx_lw;		/* W  Rx buffer low water mark  */
+	volatile unsigned short  rx_hw;		/* W  Rx buffer high water mark */
+	volatile unsigned short  incr;		/* W  Increment to next channel */
+
+	volatile unsigned short  fepdev;	/* U  SCC device base address    */
+	volatile unsigned short  edelay;	/* W  Exception delay            */
+	volatile unsigned short  blen;		/* W  Break length              */
+	volatile unsigned short  btime;		/* U  Break complete time       */
+
+	volatile unsigned short  iflag;		/* C  UNIX input flags          */
+	volatile unsigned short  oflag;		/* C  UNIX output flags         */
+	volatile unsigned short  cflag;		/* C  UNIX control flags        */
+	volatile unsigned short  wfill[13];	/* U  Reserved for expansion    */
+
+	volatile unsigned char   num;		/* U  Channel number            */
+	volatile unsigned char   ract;		/* U  Receiver active counter   */
+	volatile unsigned char   bstat;		/* U  Break status bits         */
+	volatile unsigned char   tbusy;		/* W  Transmit busy             */
+	volatile unsigned char   iempty;	/* W  Transmit empty event enable */
+	volatile unsigned char   ilow;		/* W  Transmit low-water event enable */
+	volatile unsigned char   idata;		/* W  Receive data interrupt enable */
+	volatile unsigned char   eflag;		/* U  Host event flags          */
+
+	volatile unsigned char   tflag;		/* U  Transmit flags            */
+	volatile unsigned char   rflag;		/* U  Receive flags             */
+	volatile unsigned char   xmask;		/* U  Transmit ready flags      */
+	volatile unsigned char   xval;		/* U  Transmit ready value      */
+	volatile unsigned char   m_stat;	/* RC Modem status bits          */
+	volatile unsigned char   m_change;	/* U  Modem bits which changed  */
+	volatile unsigned char   m_int;		/* W  Modem interrupt enable bits */
+	volatile unsigned char   m_last;	/* U  Last modem status         */
+
+	volatile unsigned char   mtran;		/* C   Unreported modem trans   */
+	volatile unsigned char   orun;		/* C   Buffer overrun occurred  */
+	volatile unsigned char   astartc;	/* W   Auxiliary Xon char       */
+	volatile unsigned char   astopc;	/* W   Auxiliary Xoff char      */
+	volatile unsigned char   startc;	/* W   Xon character             */
+	volatile unsigned char   stopc;		/* W   Xoff character           */
+	volatile unsigned char   vnextc;	/* W   Vnext character           */
+	volatile unsigned char   hflow;		/* C   Software flow control    */
+	
+	volatile unsigned char   fillc;		/* U   Delay Fill character     */
+	volatile unsigned char   ochar;		/* U   Saved output character   */
+	volatile unsigned char   omask;		/* U   Output character mask    */
+
+	volatile unsigned char   bfill[13];	/* U   Reserved for expansion   */
+
+	volatile unsigned char   scc[16];	/* U   SCC registers            */
+};
+
+struct cnode {
+	struct cnode *next;
+	int type;
+	int numbrd;
+
+	union {
+		struct {
+			char  type;	/* Board Type 		*/
+			short port;	/* I/O Address		*/
+			char  *portstr; /* I/O Address in string */
+			long  addr;	/* Memory Address	*/
+			char  *addrstr; /* Memory Address in string */
+			long  pcibus;	/* PCI BUS		*/
+			char  *pcibusstr; /* PCI BUS in string */
+			long  pcislot;	/* PCI SLOT		*/
+			char  *pcislotstr; /* PCI SLOT in string */
+			char  nport;	/* Number of Ports	*/
+			char  *id;	/* tty id		*/
+			int   start;	/* start of tty counting */
+			char  *method;  /* Install method       */
+			char  v_type;
+			char  v_port;
+			char  v_addr;
+			char  v_pcibus;
+			char  v_pcislot;
+			char  v_nport;
+			char  v_id;
+			char  v_start;
+			char  v_method;
+			char  line1;
+			char  line2;
+			char  conc1;   /* total concs in line1 */
+			char  conc2;   /* total concs in line2 */
+			char  module1; /* total modules for line1 */
+			char  module2; /* total modules for line2 */
+			char  *status; /* config status */
+			char  *dimstatus;	 /* Y/N */
+			int   status_index; /* field pointer */
+		} board;
+
+		struct {
+			char  *cable;
+			char  v_cable;
+			char  speed;
+			char  v_speed;
+		} line;
+
+		struct {
+			char  type;
+			char  *connect;
+			char  speed;
+			char  nport;
+			char  *id;
+			char  *idstr;
+			int   start;
+			char  v_type;
+			char  v_connect;
+			char  v_speed;
+			char  v_nport;
+			char  v_id;
+			char  v_start;
+		} conc;
+
+		struct {
+			char type;
+			char nport;
+			char *id;
+			char *idstr;
+			int  start;
+			char v_type;
+			char v_nport;
+			char v_id;
+			char v_start;
+		} module;
+
+		char *ttyname;
+
+		char *cuname;
+
+		char *printname;
+
+		int  majornumber;
+
+		int  altpin;
+
+		int  ttysize;
+
+		int  chsize;
+
+		int  bssize;
+
+		int  unsize;
+
+		int  f2size;
+
+		int  vpixsize;
+
+		int  useintr;
+	} u;
+};
+
+#endif
diff --git a/drivers/staging/dgap/dgap_conf.h b/drivers/staging/dgap/dgap_conf.h
deleted file mode 100644
index 484ed72..0000000
--- a/drivers/staging/dgap/dgap_conf.h
+++ /dev/null
@@ -1,290 +0,0 @@
-/*
- * Copyright 2003 Digi International (www.digi.com)
- *	Scott H Kilau <Scott_Kilau at digi dot com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
- * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- * PURPOSE.  See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- *****************************************************************************
- *
- *	dgap_conf.h - Header file for installations and parse files.
- *
- *	$Id: dgap_conf.h,v 1.1 2009/10/23 14:01:57 markh Exp $
- *
- *	NOTE: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!!
- */
-
-#ifndef _DGAP_CONF_H
-#define _DGAP_CONF_H
-
-#define NULLNODE 0		/* header node, not used */
-#define BNODE 1			/* Board node */
-#define LNODE 2			/* Line node */
-#define CNODE 3			/* Concentrator node */
-#define MNODE 4			/* EBI Module node */
-#define TNODE 5			/* tty name prefix node */
-#define	CUNODE 6		/* cu name prefix (non-SCO) */
-#define PNODE 7			/* trans. print prefix node */
-#define JNODE 8			/* maJor number node */
-#define ANODE 9			/* altpin */
-#define	TSNODE 10		/* tty structure size */
-#define CSNODE 11		/* channel structure size */
-#define BSNODE 12		/* board structure size */
-#define USNODE 13		/* unit schedule structure size */
-#define FSNODE 14		/* f2200 structure size */
-#define VSNODE 15		/* size of VPIX structures */
-#define INTRNODE 16		/* enable interrupt */
-
-/* Enumeration of tokens */
-#define	BEGIN	1
-#define	END	2
-#define	BOARD	10
-
-#define EPCFS	11 /* start of EPC family definitions */
-#define	ICX		11
-#define	MCX		13
-#define PCX	14
-#define	IEPC	15
-#define	EEPC	16
-#define	MEPC	17
-#define	IPCM	18
-#define	EPCM	19
-#define	MPCM	20
-#define PEPC	21
-#define PPCM	22
-#ifdef CP
-#define ICP     23
-#define ECP     24
-#define MCP     25
-#endif
-#define EPCFE	25 /* end of EPC family definitions */
-#define	PC2E	26
-#define	PC4E	27
-#define	PC4E8K	28
-#define	PC8E	29
-#define	PC8E8K	30
-#define	PC16E	31
-#define MC2E8K  34
-#define MC4E8K  35
-#define MC8E8K  36
-
-#define AVANFS	42	/* start of Avanstar family definitions */
-#define A8P 	42
-#define A16P	43
-#define AVANFE	43	/* end of Avanstar family definitions */
-
-#define DA2000FS	44	/* start of AccelePort 2000 family definitions */
-#define DA22 		44 /* AccelePort 2002 */
-#define DA24 		45 /* AccelePort 2004 */
-#define DA28		46 /* AccelePort 2008 */
-#define DA216		47 /* AccelePort 2016 */
-#define DAR4		48 /* AccelePort RAS 4 port */
-#define DAR8		49 /* AccelePort RAS 8 port */
-#define DDR24		50 /* DataFire RAS 24 port */
-#define DDR30		51 /* DataFire RAS 30 port */
-#define DDR48		52 /* DataFire RAS 48 port */
-#define DDR60		53 /* DataFire RAS 60 port */
-#define DA2000FE	53 /* end of AccelePort 2000/RAS family definitions */
-
-#define PCXRFS	106	/* start of PCXR family definitions */
-#define	APORT4	106
-#define	APORT8	107
-#define PAPORT4 108
-#define PAPORT8 109
-#define APORT4_920I	110
-#define APORT8_920I	111
-#define APORT4_920P	112
-#define APORT8_920P	113
-#define APORT2_920P 114
-#define PCXRFE	117	/* end of PCXR family definitions */
-
-#define	LINE	82
-#ifdef T1
-#define T1M	83
-#define E1M	84
-#endif
-#define	CONC	64
-#define	CX	65
-#define	EPC	66
-#define	MOD	67
-#define	PORTS	68
-#define METHOD	69
-#define CUSTOM	70
-#define BASIC	71
-#define STATUS	72
-#define MODEM	73
-/* The following tokens can appear in multiple places */
-#define	SPEED	74
-#define	NPORTS	75
-#define	ID	76
-#define CABLE	77
-#define CONNECT	78
-#define	IO	79
-#define	MEM	80
-#define DPSZ	81
-
-#define	TTYN	90
-#define	CU	91
-#define	PRINT	92
-#define	XPRINT	93
-#define CMAJOR   94
-#define ALTPIN  95
-#define STARTO 96
-#define USEINTR  97
-#define PCIINFO  98
-
-#define	TTSIZ	100
-#define	CHSIZ	101
-#define BSSIZ	102
-#define	UNTSIZ	103
-#define	F2SIZ	104
-#define	VPSIZ	105
-
-#define	TOTAL_BOARD	2
-#define	CURRENT_BRD	4
-#define	BOARD_TYPE	6
-#define	IO_ADDRESS	8
-#define	MEM_ADDRESS	10
-
-#define	FIELDS_PER_PAGE	18
-
-#define TB_FIELD	1
-#define CB_FIELD	3
-#define BT_FIELD	5
-#define IO_FIELD	7
-#define ID_FIELD	8
-#define ME_FIELD	9
-#define TTY_FIELD	11
-#define CU_FIELD	13
-#define PR_FIELD	15
-#define MPR_FIELD	17
-
-#define	MAX_FIELD	512
-
-#define	INIT		0
-#define	NITEMS		128
-#define MAX_ITEM	512
-
-#define	DSCRINST	1
-#define	DSCRNUM		3
-#define	ALTPINQ		5
-#define	SSAVE		7
-
-#define	DSCR		"32"
-#define	ONETONINE	"123456789"
-#define	ALL		"1234567890"
-
-
-struct cnode {
-	struct cnode *next;
-	int type;
-	int numbrd;
-
-	union {
-		struct {
-			char  type;	/* Board Type 		*/
-			short port;	/* I/O Address		*/
-			char  *portstr; /* I/O Address in string */
-			long  addr;	/* Memory Address	*/
-			char  *addrstr; /* Memory Address in string */
-			long  pcibus;	/* PCI BUS		*/
-			char  *pcibusstr; /* PCI BUS in string */
-			long  pcislot;	/* PCI SLOT		*/
-			char  *pcislotstr; /* PCI SLOT in string */
-			char  nport;	/* Number of Ports	*/
-			char  *id;	/* tty id		*/
-			int   start;	/* start of tty counting */
-			char  *method;  /* Install method       */
-			char  v_type;
-			char  v_port;
-			char  v_addr;
-			char  v_pcibus;
-			char  v_pcislot;
-			char  v_nport;
-			char  v_id;
-			char  v_start;
-			char  v_method;
-			char  line1;
-			char  line2;
-			char  conc1;   /* total concs in line1 */
-			char  conc2;   /* total concs in line2 */
-			char  module1; /* total modules for line1 */
-			char  module2; /* total modules for line2 */
-			char  *status; /* config status */
-			char  *dimstatus;	 /* Y/N */
-			int   status_index; /* field pointer */
-		} board;
-
-		struct {
-			char  *cable;
-			char  v_cable;
-			char  speed;
-			char  v_speed;
-		} line;
-
-		struct {
-			char  type;
-			char  *connect;
-			char  speed;
-			char  nport;
-			char  *id;
-			char  *idstr;
-			int   start;
-			char  v_type;
-			char  v_connect;
-			char  v_speed;
-			char  v_nport;
-			char  v_id;
-			char  v_start;
-		} conc;
-
-		struct {
-			char type;
-			char nport;
-			char *id;
-			char *idstr;
-			int  start;
-			char v_type;
-			char v_nport;
-			char v_id;
-			char v_start;
-		} module;
-
-		char *ttyname;
-
-		char *cuname;
-
-		char *printname;
-
-		int  majornumber;
-
-		int  altpin;
-
-		int  ttysize;
-
-		int  chsize;
-
-		int  bssize;
-
-		int  unsize;
-
-		int  f2size;
-
-		int  vpixsize;
-
-		int  useintr;
-	} u;
-};
-
-#endif
diff --git a/drivers/staging/dgap/dgap_downld.h b/drivers/staging/dgap/dgap_downld.h
deleted file mode 100644
index 910a45d..0000000
--- a/drivers/staging/dgap/dgap_downld.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright 2003 Digi International (www.digi.com)
- *      Scott H Kilau <Scott_Kilau at digi dot com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
- * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- * PURPOSE.  See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * $Id: dgap_downld.h,v 1.1 2009/10/23 14:01:57 markh Exp $
- *
- *	NOTE: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!!
- *
- */
-
-/*
-** downld.h
-**  - describes the interface between the user level download process
-**    and the concentrator download driver.
-*/
-
-#ifndef _DGAP_DOWNLD_H_
-#define _DGAP_DOWNLD_H_
-
-
-struct fepimg {
-    int type;				/* board type */
-    int	len;				/* length of image */
-    char fepimage[1];			/* beginning of image */
-};
-
-struct downldio {
-    unsigned int req_type;		/* FEP or concentrator */
-    unsigned int bdid;			/* opaque board identifier */
-    union {
-	struct downld_t dl;		/* download structure */
-	struct fepimg   fi;		/* fep/bios image structure */
-    } image;
-};
-
-#define DIGI_DLREQ_GET	(('d'<<8) | 220)
-#define DIGI_DLREQ_SET	(('d'<<8) | 221)
-
-#define DIGI_DL_NUKE    (('d'<<8) | 222) /* Not really a dl request, but
-					  dangerous enuff to not put in
-					  digi.h */
-/* Packed bits of intarg for DIGI_DL_NUKE */
-#define DIGI_NUKE_RESET_ALL	 (1 << 31)
-#define DIGI_NUKE_INHIBIT_POLLER (1 << 30)
-#define DIGI_NUKE_BRD_NUMB        0x0f
-
-
-
-#define	DLREQ_BIOS	0
-#define	DLREQ_FEP	1
-#define	DLREQ_CONC	2
-#define	DLREQ_CONFIG	3
-#define DLREQ_DEVCREATE 4
-
-#endif
diff --git a/drivers/staging/dgap/dgap_driver.c b/drivers/staging/dgap/dgap_driver.c
deleted file mode 100644
index 11dd6dd..0000000
--- a/drivers/staging/dgap/dgap_driver.c
+++ /dev/null
@@ -1,1030 +0,0 @@
-/*
- * Copyright 2003 Digi International (www.digi.com)
- *	Scott H Kilau <Scott_Kilau at digi dot com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
- * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- * PURPOSE.  See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- *
- *	NOTE TO LINUX KERNEL HACKERS:  DO NOT REFORMAT THIS CODE!
- *
- *	This is shared code between Digi's CVS archive and the
- *	Linux Kernel sources.
- *	Changing the source just for reformatting needlessly breaks
- *	our CVS diff history.
- *
- *	Send any bug fixes/changes to:  Eng.Linux at digi dot com.
- *	Thank you.
- *
- * $Id: dgap_driver.c,v 1.3 2011/06/21 10:35:16 markh Exp $
- */
-
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/delay.h>	/* For udelay */
-#include <linux/slab.h>
-#include <asm/uaccess.h>	/* For copy_from_user/copy_to_user */
-#include <linux/sched.h>
-
-#include "dgap_driver.h"
-#include "dgap_pci.h"
-#include "dgap_fep5.h"
-#include "dgap_tty.h"
-#include "dgap_conf.h"
-#include "dgap_parse.h"
-#include "dgap_trace.h"
-#include "dgap_sysfs.h"
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Digi International, http://www.digi.com");
-MODULE_DESCRIPTION("Driver for the Digi International EPCA PCI based product line");
-MODULE_SUPPORTED_DEVICE("dgap");
-
-/*
- * insmod command line overrideable parameters
- *
- * NOTE: we use a set of macros to create the variables, which allows
- * us to specify the variable type, name, initial value, and description.
- */
-PARM_INT(debug,		0x00,		0644,	"Driver debugging level");
-PARM_INT(rawreadok,	1,		0644,	"Bypass flip buffers on input");
-PARM_INT(trcbuf_size,	0x100000,	0644,	"Debugging trace buffer size.");
-
-
-/**************************************************************************
- *
- * protos for this file
- *
- */
-
-static int		dgap_start(void);
-static void		dgap_init_globals(void);
-static int		dgap_found_board(struct pci_dev *pdev, int id);
-static void		dgap_cleanup_board(struct board_t *brd);
-static void		dgap_poll_handler(ulong dummy);
-static int		dgap_init_pci(void);
-static int		dgap_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
-static void		dgap_remove_one(struct pci_dev *dev);
-static int		dgap_probe1(struct pci_dev *pdev, int card_type);
-static void		dgap_mbuf(struct board_t *brd, const char *fmt, ...);
-static int		dgap_do_remap(struct board_t *brd);
-static irqreturn_t	dgap_intr(int irq, void *voidbrd);
-
-/* Driver load/unload functions */
-int			dgap_init_module(void);
-void			dgap_cleanup_module(void);
-
-module_init(dgap_init_module);
-module_exit(dgap_cleanup_module);
-
-
-/*
- * File operations permitted on Control/Management major.
- */
-static struct file_operations DgapBoardFops =
-{
-	.owner		=	THIS_MODULE,
-};
-
-
-/*
- * Globals
- */
-uint			dgap_NumBoards;
-struct board_t		*dgap_Board[MAXBOARDS];
-DEFINE_SPINLOCK(dgap_global_lock);
-ulong			dgap_poll_counter;
-char			*dgap_config_buf;
-int			dgap_driver_state = DRIVER_INITIALIZED;
-DEFINE_SPINLOCK(dgap_dl_lock);
-wait_queue_head_t	dgap_dl_wait;
-int			dgap_dl_action;
-int			dgap_poll_tick = 20;	/* Poll interval - 20 ms */
-
-/*
- * Static vars.
- */
-static int		dgap_Major_Control_Registered = FALSE;
-static uint		dgap_driver_start = FALSE;
-
-static struct class *	dgap_class;
-
-/*
- * Poller stuff
- */
-static 			DEFINE_SPINLOCK(dgap_poll_lock);	/* Poll scheduling lock */
-static ulong		dgap_poll_time;				/* Time of next poll */
-static uint		dgap_poll_stop;				/* Used to tell poller to stop */
-static struct timer_list dgap_poll_timer;
-
-
-static struct pci_device_id dgap_pci_tbl[] = {
-	{       DIGI_VID, PCI_DEVICE_XEM_DID,	PCI_ANY_ID, PCI_ANY_ID, 0, 0,	0 },
-	{       DIGI_VID, PCI_DEVICE_CX_DID,	PCI_ANY_ID, PCI_ANY_ID, 0, 0,   1 },
-	{       DIGI_VID, PCI_DEVICE_CX_IBM_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0,	2 },
-	{       DIGI_VID, PCI_DEVICE_EPCJ_DID,	PCI_ANY_ID, PCI_ANY_ID, 0, 0,	3 },
-	{       DIGI_VID, PCI_DEVICE_920_2_DID,	PCI_ANY_ID, PCI_ANY_ID, 0, 0,	4 },
-	{       DIGI_VID, PCI_DEVICE_920_4_DID,	PCI_ANY_ID, PCI_ANY_ID, 0, 0,	5 },
-	{       DIGI_VID, PCI_DEVICE_920_8_DID,	PCI_ANY_ID, PCI_ANY_ID, 0, 0,	6 },
-	{       DIGI_VID, PCI_DEVICE_XR_DID,	PCI_ANY_ID, PCI_ANY_ID, 0, 0,	7 },
-	{       DIGI_VID, PCI_DEVICE_XRJ_DID,	PCI_ANY_ID, PCI_ANY_ID, 0, 0,	8 },
-	{       DIGI_VID, PCI_DEVICE_XR_422_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0,	9 },
-	{       DIGI_VID, PCI_DEVICE_XR_IBM_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0,	10 },
-	{       DIGI_VID, PCI_DEVICE_XR_SAIP_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0,	11 },
-	{       DIGI_VID, PCI_DEVICE_XR_BULL_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0,	12 },
-	{       DIGI_VID, PCI_DEVICE_920_8_HP_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 13 },
-	{       DIGI_VID, PCI_DEVICE_XEM_HP_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0,	14 },
-	{0,}					/* 0 terminated list. */
-};
-MODULE_DEVICE_TABLE(pci, dgap_pci_tbl);
-
-
-/*
- * A generic list of Product names, PCI Vendor ID, and PCI Device ID.
- */
-struct board_id {
-	uint config_type;
-	uchar *name;
-	uint maxports;
-	uint dpatype;
-};
-
-static struct board_id dgap_Ids[] =
-{
-	{	PPCM,		PCI_DEVICE_XEM_NAME,	64,	(T_PCXM | T_PCLITE | T_PCIBUS)	},
-	{	PCX,		PCI_DEVICE_CX_NAME,	128,	(T_CX | T_PCIBUS)		},
-	{	PCX,		PCI_DEVICE_CX_IBM_NAME,	128,	(T_CX | T_PCIBUS)		},
-	{	PEPC,		PCI_DEVICE_EPCJ_NAME,	224,	(T_EPC  | T_PCIBUS)		},
-	{	APORT2_920P,	PCI_DEVICE_920_2_NAME,	2,	(T_PCXR | T_PCLITE | T_PCIBUS)	},
-	{	APORT4_920P,	PCI_DEVICE_920_4_NAME,	4,	(T_PCXR | T_PCLITE | T_PCIBUS)	},
-	{	APORT8_920P,	PCI_DEVICE_920_8_NAME,	8,	(T_PCXR | T_PCLITE | T_PCIBUS)	},
-	{	PAPORT8,	PCI_DEVICE_XR_NAME,	8,	(T_PCXR | T_PCLITE | T_PCIBUS)	},
-	{	PAPORT8,	PCI_DEVICE_XRJ_NAME,	8,	(T_PCXR | T_PCLITE | T_PCIBUS)	},
-	{	PAPORT8,	PCI_DEVICE_XR_422_NAME,	8,	(T_PCXR | T_PCLITE | T_PCIBUS)	},
-	{	PAPORT8,	PCI_DEVICE_XR_IBM_NAME,	8,	(T_PCXR | T_PCLITE | T_PCIBUS)	},
-	{	PAPORT8,	PCI_DEVICE_XR_SAIP_NAME, 8,	(T_PCXR | T_PCLITE | T_PCIBUS)	},
-	{	PAPORT8,	PCI_DEVICE_XR_BULL_NAME, 8,	(T_PCXR | T_PCLITE | T_PCIBUS)	},
-	{	APORT8_920P,	PCI_DEVICE_920_8_HP_NAME, 8,	(T_PCXR | T_PCLITE | T_PCIBUS)	},
-	{	PPCM,		PCI_DEVICE_XEM_HP_NAME,	64,	(T_PCXM | T_PCLITE | T_PCIBUS)	},
-	{0,}						/* 0 terminated list. */
-};
-
-static struct pci_driver dgap_driver = {
-	.name		= "dgap",
-	.probe		= dgap_init_one,
-	.id_table	= dgap_pci_tbl,
-	.remove		= dgap_remove_one,
-};
-
-
-char *dgap_state_text[] = {
-	"Board Failed",
-	"Configuration for board not found.\n\t\t\tRun mpi to configure board.",
-	"Board Found",
-	"Need Reset",
-	"Finished Reset",
-	"Need Config",
-	"Finished Config",
-	"Need Device Creation",
-	"Requested Device Creation",
-	"Finished Device Creation",
-	"Need BIOS Load",
-	"Requested BIOS",
-	"Doing BIOS Load",
-	"Finished BIOS Load",
-	"Need FEP Load",
-	"Requested FEP",
-	"Doing FEP Load",
-	"Finished FEP Load",
-	"Requested PROC creation",
-	"Finished PROC creation",
-	"Board READY",
-};
-
-char *dgap_driver_state_text[] = {
-	"Driver Initialized",
-	"Driver needs configuration load.",
-	"Driver requested configuration from download daemon.",
-	"Driver Ready."
-};
-
-
-
-/************************************************************************
- *
- * Driver load/unload functions
- *
- ************************************************************************/
-
-/*
- * init_module()
- *
- * Module load.  This is where it all starts.
- */
-int dgap_init_module(void)
-{
-	int rc = 0;
-
-	APR(("%s, Digi International Part Number %s\n", DG_NAME, DG_PART));
-
-	/*
-	 * Initialize global stuff
-	 */
-	rc = dgap_start();
-
-	if (rc < 0) {
-		return(rc);
-	}
-
-	/*
-	 * Find and configure all the cards
-	 */
-	rc = dgap_init_pci();
-
-	/*
-	 * If something went wrong in the scan, bail out of driver.
-	 */
-	if (rc < 0) {
-		/* Only unregister the pci driver if it was actually registered. */
-		if (dgap_NumBoards)
-			pci_unregister_driver(&dgap_driver);
-		else
-			printk("WARNING: dgap driver load failed.  No DGAP boards found.\n");
-
-		dgap_cleanup_module();
-	}
-	else {
-		dgap_create_driver_sysfiles(&dgap_driver);
-	}
-
-	DPR_INIT(("Finished init_module. Returning %d\n", rc));
-	return (rc);
-}
-
-
-/*
- * Start of driver.
- */
-static int dgap_start(void)
-{
-	int rc = 0;
-	unsigned long flags;
-
-	if (dgap_driver_start == FALSE) {
-
-		dgap_driver_start = TRUE;
-
-	        /* make sure that the globals are init'd before we do anything else */
-	        dgap_init_globals();
-
-		dgap_NumBoards = 0;
-
-		APR(("For the tools package or updated drivers please visit http://www.digi.com\n"));
-
-		/*
-		 * Register our base character device into the kernel.
-		 * This allows the download daemon to connect to the downld device
-		 * before any of the boards are init'ed.
-		 */
-		if (!dgap_Major_Control_Registered) {
-			/*
-			 * Register management/dpa devices
-			 */
-			rc = register_chrdev(DIGI_DGAP_MAJOR, "dgap", &DgapBoardFops);
-			if (rc < 0) {
-				APR(("Can't register dgap driver device (%d)\n", rc));
-				return (rc);
-			}
-
-			dgap_class = class_create(THIS_MODULE, "dgap_mgmt");
-			device_create(dgap_class, NULL,
-				MKDEV(DIGI_DGAP_MAJOR, 0),
-				NULL, "dgap_mgmt");
-			device_create(dgap_class, NULL,
-				MKDEV(DIGI_DGAP_MAJOR, 1),
-				NULL, "dgap_downld");
-			dgap_Major_Control_Registered = TRUE;
-		}
-
-		/*
-		 * Init any global tty stuff.
-		 */
-		rc = dgap_tty_preinit();
-
-		if (rc < 0) {
-			APR(("tty preinit - not enough memory (%d)\n", rc));
-			return(rc);
-		}
-
-		/* Start the poller */
-		DGAP_LOCK(dgap_poll_lock, flags);
-		init_timer(&dgap_poll_timer);
-		dgap_poll_timer.function = dgap_poll_handler;
-		dgap_poll_timer.data = 0;
-		dgap_poll_time = jiffies + dgap_jiffies_from_ms(dgap_poll_tick);
-		dgap_poll_timer.expires = dgap_poll_time;
-		DGAP_UNLOCK(dgap_poll_lock, flags);
-
-		add_timer(&dgap_poll_timer);
-
-		dgap_driver_state = DRIVER_NEED_CONFIG_LOAD;
-	}
-
-	return (rc);
-}
-
-
-/*
- * Register pci driver, and return how many boards we have.
- */
-static int dgap_init_pci(void)
-{
-	return pci_register_driver(&dgap_driver);
-}
-
-
-/* returns count (>= 0), or negative on error */
-static int dgap_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
-{
-	int rc;
-
-	/* wake up and enable device */
-	rc = pci_enable_device(pdev);
-
-	if (rc < 0) {
-		rc = -EIO;
-	} else {
-		rc = dgap_probe1(pdev, ent->driver_data);
-		if (rc == 0) {
-			dgap_NumBoards++;
-			DPR_INIT(("Incrementing numboards to %d\n", dgap_NumBoards));
-		}
-	}
-	return rc;
-}
-
-
-static int dgap_probe1(struct pci_dev *pdev, int card_type)
-{
-	return dgap_found_board(pdev, card_type);
-}
-
-
-static void dgap_remove_one(struct pci_dev *dev)
-{
-	/* Do Nothing */
-}
-
-
-/*
- * dgap_cleanup_module()
- *
- * Module unload.  This is where it all ends.
- */
-void dgap_cleanup_module(void)
-{
-	int i;
-	ulong lock_flags;
-
-	DGAP_LOCK(dgap_poll_lock, lock_flags);
-	dgap_poll_stop = 1;
-	DGAP_UNLOCK(dgap_poll_lock, lock_flags);
-
-	/* Turn off poller right away. */
-	del_timer_sync( &dgap_poll_timer);
-
-	dgap_remove_driver_sysfiles(&dgap_driver);
-
-
-	if (dgap_Major_Control_Registered) {
-		device_destroy(dgap_class, MKDEV(DIGI_DGAP_MAJOR, 0));
-		device_destroy(dgap_class, MKDEV(DIGI_DGAP_MAJOR, 1));
-		class_destroy(dgap_class);
-		unregister_chrdev(DIGI_DGAP_MAJOR, "dgap");
-	}
-
-	kfree(dgap_config_buf);
-
-	for (i = 0; i < dgap_NumBoards; ++i) {
-		dgap_remove_ports_sysfiles(dgap_Board[i]);
-		dgap_tty_uninit(dgap_Board[i]);
-		dgap_cleanup_board(dgap_Board[i]);
-	}
-
-	dgap_tty_post_uninit();
-
-#if defined(DGAP_TRACER)
-	/* last thing, make sure we release the tracebuffer */
-	dgap_tracer_free();
-#endif
-	if (dgap_NumBoards)
-		pci_unregister_driver(&dgap_driver);
-}
-
-
-/*
- * dgap_cleanup_board()
- *
- * Free all the memory associated with a board
- */
-static void dgap_cleanup_board(struct board_t *brd)
-{
-	int i = 0;
-
-        if(!brd || brd->magic != DGAP_BOARD_MAGIC)
-                return;
-
-	if (brd->intr_used && brd->irq)
-		free_irq(brd->irq, brd);
-
-	tasklet_kill(&brd->helper_tasklet);
-
-	if (brd->re_map_port) {
-		release_mem_region(brd->membase + 0x200000, 0x200000);
-		iounmap(brd->re_map_port);
-		brd->re_map_port = NULL;
-	}
-
-	if (brd->re_map_membase) {
-		release_mem_region(brd->membase, 0x200000);
-		iounmap(brd->re_map_membase);
-		brd->re_map_membase = NULL;
-	}
-
-        if (brd->msgbuf_head) {
-                unsigned long flags;
-
-                DGAP_LOCK(dgap_global_lock, flags);
-                brd->msgbuf = NULL;
-                printk("%s", brd->msgbuf_head);
-                kfree(brd->msgbuf_head);
-                brd->msgbuf_head = NULL;
-                DGAP_UNLOCK(dgap_global_lock, flags);
-        }
-
-	/* Free all allocated channels structs */
-	for (i = 0; i < MAXPORTS ; i++) {
-		if (brd->channels[i]) {
-			kfree(brd->channels[i]);
-			brd->channels[i] = NULL;
-		}
-	}
-
-	kfree(brd->flipbuf);
-	kfree(brd->flipflagbuf);
-
-	dgap_Board[brd->boardnum] = NULL;
-
-        kfree(brd);
-}
-
-
-/*
- * dgap_found_board()
- *
- * A board has been found, init it.
- */
-static int dgap_found_board(struct pci_dev *pdev, int id)
-{
-	struct board_t *brd;
-	unsigned int pci_irq;
-	int i = 0;
-	unsigned long flags;
-
-	/* get the board structure and prep it */
-	brd = dgap_Board[dgap_NumBoards] =
-	(struct board_t *) kzalloc(sizeof(struct board_t), GFP_KERNEL);
-	if (!brd) {
-		APR(("memory allocation for board structure failed\n"));
-		return(-ENOMEM);
-	}
-
-	/* make a temporary message buffer for the boot messages */
-	brd->msgbuf = brd->msgbuf_head =
-		(char *) kzalloc(sizeof(char) * 8192, GFP_KERNEL);
-	if(!brd->msgbuf) {
-		kfree(brd);
-		APR(("memory allocation for board msgbuf failed\n"));
-		return(-ENOMEM);
-	}
-
-	/* store the info for the board we've found */
-	brd->magic = DGAP_BOARD_MAGIC;
-	brd->boardnum = dgap_NumBoards;
-	brd->firstminor = 0;
-	brd->vendor = dgap_pci_tbl[id].vendor;
-	brd->device = dgap_pci_tbl[id].device;
-	brd->pdev = pdev;
-	brd->pci_bus = pdev->bus->number;
-	brd->pci_slot = PCI_SLOT(pdev->devfn);
-	brd->name = dgap_Ids[id].name;
-	brd->maxports = dgap_Ids[id].maxports;
-	brd->type = dgap_Ids[id].config_type;
-	brd->dpatype = dgap_Ids[id].dpatype;
-	brd->dpastatus = BD_NOFEP;
-	init_waitqueue_head(&brd->state_wait);
-
-	DGAP_SPINLOCK_INIT(brd->bd_lock);
-
-	brd->state		= BOARD_FOUND;
-	brd->runwait		= 0;
-	brd->inhibit_poller	= FALSE;
-	brd->wait_for_bios	= 0;
-	brd->wait_for_fep	= 0;
-
-	for (i = 0; i < MAXPORTS; i++) {
-		brd->channels[i] = NULL;
-	}
-
-	/* store which card & revision we have */
-	pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, &brd->subvendor);
-	pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, &brd->subdevice);
-	pci_read_config_byte(pdev, PCI_REVISION_ID, &brd->rev);
-
-	pci_irq = pdev->irq;
-	brd->irq = pci_irq;
-
-	/* get the PCI Base Address Registers */
-
-	/* Xr Jupiter and EPC use BAR 2 */
-	if (brd->device == PCI_DEVICE_XRJ_DID || brd->device == PCI_DEVICE_EPCJ_DID) {
-		brd->membase     = pci_resource_start(pdev, 2);
-		brd->membase_end = pci_resource_end(pdev, 2);
-	}
-	/* Everyone else uses BAR 0 */
-	else {
-		brd->membase     = pci_resource_start(pdev, 0);
-		brd->membase_end = pci_resource_end(pdev, 0);
-	}
-
-	if (!brd->membase) {
-		APR(("card has no PCI IO resources, failing board.\n"));
-		return -ENODEV;
-	}
-
-	if (brd->membase & 1)
-		brd->membase &= ~3;
-	else
-		brd->membase &= ~15;
-
-	/*
-	 * On the PCI boards, there is no IO space allocated
-	 * The I/O registers will be in the first 3 bytes of the
-	 * upper 2MB of the 4MB memory space.  The board memory
-	 * will be mapped into the low 2MB of the 4MB memory space
-	 */
-	brd->port = brd->membase + PCI_IO_OFFSET;
-	brd->port_end = brd->port + PCI_IO_SIZE;
-
-
-	/*
-	 * Special initialization for non-PLX boards
-	 */
-	if (brd->device != PCI_DEVICE_XRJ_DID && brd->device != PCI_DEVICE_EPCJ_DID) {
-		unsigned short cmd;
-
-		pci_write_config_byte(pdev, 0x40, 0);
-		pci_write_config_byte(pdev, 0x46, 0);
-
-		/* Limit burst length to 2 doubleword transactions */
-		pci_write_config_byte(pdev, 0x42, 1);
-
-		/*
-		 * Enable IO and mem if not already done.
-		 * This was needed for support on Itanium.
-		 */
-		pci_read_config_word(pdev, PCI_COMMAND, &cmd);
-		cmd |= (PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
-		pci_write_config_word(pdev, PCI_COMMAND, cmd);
-	}
-
-	/* init our poll helper tasklet */
-	tasklet_init(&brd->helper_tasklet, dgap_poll_tasklet, (unsigned long) brd);
-
-	 /* Log the information about the board */
-	dgap_mbuf(brd, DRVSTR": board %d: %s (rev %d), irq %d\n",
-		dgap_NumBoards, brd->name, brd->rev, brd->irq);
-
-	DPR_INIT(("dgap_scan(%d) - printing out the msgbuf\n", i));
-	DGAP_LOCK(dgap_global_lock, flags);
-	brd->msgbuf = NULL;
-	printk("%s", brd->msgbuf_head);
-	kfree(brd->msgbuf_head);
-	brd->msgbuf_head = NULL;
-	DGAP_UNLOCK(dgap_global_lock, flags);
-
-	i = dgap_do_remap(brd);
-	if (i)
-		brd->state = BOARD_FAILED;
-	else
-		brd->state = NEED_RESET;
-
-        return(0);
-}
-
-
-int dgap_finalize_board_init(struct board_t *brd) {
-
-        int rc;
-
-        DPR_INIT(("dgap_finalize_board_init() - start\n"));
-
-	if (!brd || brd->magic != DGAP_BOARD_MAGIC)
-                return(-ENODEV);
-
-        DPR_INIT(("dgap_finalize_board_init() - start #2\n"));
-
-	brd->use_interrupts = dgap_config_get_useintr(brd);
-
-	/*
-	 * Set up our interrupt handler if we are set to do interrupts.
-	 */
-	if (brd->use_interrupts && brd->irq) {
-
-		rc = request_irq(brd->irq, dgap_intr, IRQF_SHARED, "DGAP", brd);
-
-		if (rc) {
-			dgap_mbuf(brd, DRVSTR": Failed to hook IRQ %d. Board will work in poll mode.\n",
-                                  brd->irq);
-			brd->intr_used = 0;
-		}
-		else
-			brd->intr_used = 1;
-	} else {
-		brd->intr_used = 0;
-	}
-
-	return(0);
-}
-
-
-/*
- * Remap PCI memory.
- */
-static int dgap_do_remap(struct board_t *brd)
-{
-	if (!brd || brd->magic != DGAP_BOARD_MAGIC)
-		return -ENXIO;
-
-	if (!request_mem_region(brd->membase, 0x200000, "dgap")) {
-		APR(("dgap: mem_region %lx already in use.\n", brd->membase));
-		return -ENOMEM;
-        }
-
-	if (!request_mem_region(brd->membase + PCI_IO_OFFSET, 0x200000, "dgap")) {
-		APR(("dgap: mem_region IO %lx already in use.\n",
-			brd->membase + PCI_IO_OFFSET));
-		release_mem_region(brd->membase, 0x200000);
-		return -ENOMEM;
-        }
-
-	brd->re_map_membase = ioremap(brd->membase, 0x200000);
-	if (!brd->re_map_membase) {
-		APR(("dgap: ioremap mem %lx cannot be mapped.\n", brd->membase));
-		release_mem_region(brd->membase, 0x200000);
-		release_mem_region(brd->membase + PCI_IO_OFFSET, 0x200000);
-		return -ENOMEM;
-	}
-
-	brd->re_map_port = ioremap((brd->membase + PCI_IO_OFFSET), 0x200000);
-	if (!brd->re_map_port) {
-		release_mem_region(brd->membase, 0x200000);
-		release_mem_region(brd->membase + PCI_IO_OFFSET, 0x200000);
-		iounmap(brd->re_map_membase);
-		APR(("dgap: ioremap IO mem %lx cannot be mapped.\n",
-			brd->membase + PCI_IO_OFFSET));
-		return -ENOMEM;
-	}
-
-	DPR_INIT(("remapped io: 0x%p  remapped mem: 0x%p\n",
-		brd->re_map_port, brd->re_map_membase));
-	return 0;
-}
-
-
-/*****************************************************************************
-*
-* Function:
-*
-*    dgap_poll_handler
-*
-* Author:
-*
-*    Scott H Kilau
-*
-* Parameters:
-*
-*    dummy -- ignored
-*
-* Return Values:
-*
-*    none
-*
-* Description:
-*
-*    As each timer expires, it determines (a) whether the "transmit"
-*    waiter needs to be woken up, and (b) whether the poller needs to
-*    be rescheduled.
-*
-******************************************************************************/
-
-static void dgap_poll_handler(ulong dummy)
-{
-	int i;
-        struct board_t *brd;
-        unsigned long lock_flags;
-        unsigned long lock_flags2;
-	ulong new_time;
-
-	dgap_poll_counter++;
-
-
-	/*
-	 * If driver needs the config file still,
-	 * keep trying to wake up the downloader to
-	 * send us the file.
-	 */
-        if (dgap_driver_state == DRIVER_NEED_CONFIG_LOAD) {
-		/*
-		 * Signal downloader, its got some work to do.
-		 */
-		DGAP_LOCK(dgap_dl_lock, lock_flags2);
-		if (dgap_dl_action != 1) {
-			dgap_dl_action = 1;
-			wake_up_interruptible(&dgap_dl_wait);
-		}
-		DGAP_UNLOCK(dgap_dl_lock, lock_flags2);
-		goto schedule_poller;
-        }
-	/*
-	 * Do not start the board state machine until
-	 * driver tells us its up and running, and has
-	 * everything it needs.
-	 */
-	else if (dgap_driver_state != DRIVER_READY) {
-		goto schedule_poller;
-	}
-
-	/*
-	 * If we have just 1 board, or the system is not SMP,
-	 * then use the typical old style poller.
-	 * Otherwise, use our new tasklet based poller, which should
-	 * speed things up for multiple boards.
-	 */
-	if ( (dgap_NumBoards == 1) || (num_online_cpus() <= 1) ) {
-		for (i = 0; i < dgap_NumBoards; i++) {
-
-			brd = dgap_Board[i];
-
-			if (brd->state == BOARD_FAILED) {
-				continue;
-			}
-			if (!brd->intr_running) {
-				/* Call the real board poller directly */
-				dgap_poll_tasklet((unsigned long) brd);
-			}
-		}
-	}
-	else {
-		/* Go thru each board, kicking off a tasklet for each if needed */
-		for (i = 0; i < dgap_NumBoards; i++) {
-			brd = dgap_Board[i];
-
-			/*
-			 * Attempt to grab the board lock.
-			 *
-			 * If we can't get it, no big deal, the next poll will get it.
-			 * Basically, I just really don't want to spin in here, because I want
-			 * to kick off my tasklets as fast as I can, and then get out the poller.
-			 */
-			if (!spin_trylock(&brd->bd_lock)) {
-				continue;
-			}
-
-			/* If board is in a failed state, don't bother scheduling a tasklet */
-			if (brd->state == BOARD_FAILED) {
-				spin_unlock(&brd->bd_lock);
-				continue;
-			}
-
-			/* Schedule a poll helper task */
-			if (!brd->intr_running) {
-				tasklet_schedule(&brd->helper_tasklet);
-			}
-
-			/*
-			 * Can't do DGAP_UNLOCK here, as we don't have
-			 * lock_flags because we did a trylock above.
-			 */
-			spin_unlock(&brd->bd_lock);
-		}
-	}
-
-schedule_poller:
-
-	/*
-	 * Schedule ourself back at the nominal wakeup interval.
-	 */
-	DGAP_LOCK(dgap_poll_lock, lock_flags );
-	dgap_poll_time +=  dgap_jiffies_from_ms(dgap_poll_tick);
-
-	new_time = dgap_poll_time - jiffies;
-
-	if ((ulong) new_time >= 2 * dgap_poll_tick) {
-		dgap_poll_time = jiffies +  dgap_jiffies_from_ms(dgap_poll_tick);
-	}
-
-	dgap_poll_timer.function = dgap_poll_handler;
-	dgap_poll_timer.data = 0;
-	dgap_poll_timer.expires = dgap_poll_time;
-	DGAP_UNLOCK(dgap_poll_lock, lock_flags );
-
-	if (!dgap_poll_stop)
-		add_timer(&dgap_poll_timer);
-}
-
-
-
-
-/*
- * dgap_intr()
- *
- * Driver interrupt handler.
- */
-static irqreturn_t dgap_intr(int irq, void *voidbrd)
-{
-	struct board_t *brd = (struct board_t *) voidbrd;
-
-	if (!brd) {
-		APR(("Received interrupt (%d) with null board associated\n", irq));
-		return IRQ_NONE;
-	}
-
-	/*
-	 * Check to make sure its for us.
-	 */
-	if (brd->magic != DGAP_BOARD_MAGIC) {
-		APR(("Received interrupt (%d) with a board pointer that wasn't ours!\n", irq));
-		return IRQ_NONE;
-	}
-
-	brd->intr_count++;
-
-	/*
-	 * Schedule tasklet to run at a better time.
-	 */
-	tasklet_schedule(&brd->helper_tasklet);
-	return IRQ_HANDLED;
-}
-
-
-/*
- * dgap_init_globals()
- *
- * This is where we initialize the globals from the static insmod
- * configuration variables.  These are declared near the head of
- * this file.
- */
-static void dgap_init_globals(void)
-{
-	int i = 0;
-
-	dgap_rawreadok		= rawreadok;
-        dgap_trcbuf_size	= trcbuf_size;
-	dgap_debug		= debug;
-
-	for (i = 0; i < MAXBOARDS; i++) {
-		dgap_Board[i] = NULL;
-	}
-
-	init_timer( &dgap_poll_timer );
-
-	init_waitqueue_head(&dgap_dl_wait);
-	dgap_dl_action = 0;
-}
-
-
-/************************************************************************
- *
- * Utility functions
- *
- ************************************************************************/
-
-
-/*
- * dgap_mbuf()
- *
- * Used to print to the message buffer during board init.
- */
-static void dgap_mbuf(struct board_t *brd, const char *fmt, ...) {
-	va_list		ap;
-	char		buf[1024];
-	int		i;
-	unsigned long	flags;
-	size_t		length;
-
-	DGAP_LOCK(dgap_global_lock, flags);
-
-	/* Format buf using fmt and arguments contained in ap. */
-	va_start(ap, fmt);
-	i = vsnprintf(buf, sizeof(buf), fmt,  ap);
-	va_end(ap);
-
-	DPR((buf));
-
-	if (!brd || !brd->msgbuf) {
-		printk("%s", buf);
-		DGAP_UNLOCK(dgap_global_lock, flags);
-		return;
-	}
-
-	length = strlen(buf) + 1;
-	if (brd->msgbuf - brd->msgbuf_head < length)
-		length = brd->msgbuf - brd->msgbuf_head;
-	memcpy(brd->msgbuf, buf, length);
-	brd->msgbuf += length;
-
-	DGAP_UNLOCK(dgap_global_lock, flags);
-}
-
-
-/*
- * dgap_ms_sleep()
- *
- * Put the driver to sleep for x ms's
- *
- * Returns 0 if timed out, !0 (showing signal) if interrupted by a signal.
- */
-int dgap_ms_sleep(ulong ms)
-{
-	current->state = TASK_INTERRUPTIBLE;
-	schedule_timeout((ms * HZ) / 1000);
-	return (signal_pending(current));
-}
-
-
-
-/*
- *      dgap_ioctl_name() : Returns a text version of each ioctl value.
- */
-char *dgap_ioctl_name(int cmd)
-{
-	switch(cmd) {
-
-	case TCGETA:		return("TCGETA");
-	case TCGETS:		return("TCGETS");
-	case TCSETA:		return("TCSETA");
-	case TCSETS:		return("TCSETS");
-	case TCSETAW:		return("TCSETAW");
-	case TCSETSW:		return("TCSETSW");
-	case TCSETAF:		return("TCSETAF");
-	case TCSETSF:		return("TCSETSF");
-	case TCSBRK:		return("TCSBRK");
-	case TCXONC:		return("TCXONC");
-	case TCFLSH:		return("TCFLSH");
-	case TIOCGSID:		return("TIOCGSID");
-
-	case TIOCGETD:		return("TIOCGETD");
-	case TIOCSETD:		return("TIOCSETD");
-	case TIOCGWINSZ:	return("TIOCGWINSZ");
-	case TIOCSWINSZ:	return("TIOCSWINSZ");
-
-	case TIOCMGET:		return("TIOCMGET");
-	case TIOCMSET:		return("TIOCMSET");
-	case TIOCMBIS:		return("TIOCMBIS");
-	case TIOCMBIC:		return("TIOCMBIC");
-
-	/* from digi.h */
-	case DIGI_SETA:		return("DIGI_SETA");
-	case DIGI_SETAW:	return("DIGI_SETAW");
-	case DIGI_SETAF:	return("DIGI_SETAF");
-	case DIGI_SETFLOW:	return("DIGI_SETFLOW");
-	case DIGI_SETAFLOW:	return("DIGI_SETAFLOW");
-	case DIGI_GETFLOW:	return("DIGI_GETFLOW");
-	case DIGI_GETAFLOW:	return("DIGI_GETAFLOW");
-	case DIGI_GETA:		return("DIGI_GETA");
-	case DIGI_GEDELAY:	return("DIGI_GEDELAY");
-	case DIGI_SEDELAY:	return("DIGI_SEDELAY");
-	case DIGI_GETCUSTOMBAUD: return("DIGI_GETCUSTOMBAUD");
-	case DIGI_SETCUSTOMBAUD: return("DIGI_SETCUSTOMBAUD");
-	case TIOCMODG:		return("TIOCMODG");
-	case TIOCMODS:		return("TIOCMODS");
-	case TIOCSDTR:		return("TIOCSDTR");
-	case TIOCCDTR:		return("TIOCCDTR");
-
-	default:		return("unknown");
-	}
-}
diff --git a/drivers/staging/dgap/dgap_driver.h b/drivers/staging/dgap/dgap_driver.h
deleted file mode 100644
index 9296adc..0000000
--- a/drivers/staging/dgap/dgap_driver.h
+++ /dev/null
@@ -1,615 +0,0 @@
-/*
- * Copyright 2003 Digi International (www.digi.com)
- *      Scott H Kilau <Scott_Kilau at digi dot com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
- * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- * PURPOSE.  See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- *	NOTE: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!!
- *
- *************************************************************************
- *
- * Driver includes
- *
- *************************************************************************/
-
-#ifndef __DGAP_DRIVER_H
-#define __DGAP_DRIVER_H
-
-#include <linux/types.h>        /* To pick up the varions Linux types */
-#include <linux/tty.h>          /* To pick up the various tty structs/defines */
-#include <linux/interrupt.h>    /* For irqreturn_t type */
-
-#include "dgap_types.h"         /* Additional types needed by the Digi header files */
-#include "digi.h"               /* Digi specific ioctl header */
-#include "dgap_kcompat.h"       /* Kernel 2.4/2.6 compat includes */
-#include "dgap_sysfs.h"		/* Support for SYSFS */
-
-/*************************************************************************
- *
- * Driver defines
- *
- *************************************************************************/
-
-/*
- * Driver identification, error and debugging statments
- *
- * In theory, you can change all occurrences of "digi" in the next
- * three lines, and the driver printk's will all automagically change.
- *
- * APR((fmt, args, ...));	Always prints message
- * DPR((fmt, args, ...));	Only prints if DGAP_TRACER is defined at
- *				  compile time and dgap_debug!=0
- */
-#define	DG_NAME		"dgap-1.3-16"
-#define	DG_PART		"40002347_C"
-
-#define	PROCSTR		"dgap"			/* /proc entries	 */
-#define	DEVSTR		"/dev/dg/dgap"		/* /dev entries		 */
-#define	DRVSTR		"dgap"			/* Driver name string
-						 * displayed by APR	 */
-#define	APR(args)	do { PRINTF_TO_KMEM(args); printk(DRVSTR": "); printk args; \
-			   } while (0)
-#define	RAPR(args)	do { PRINTF_TO_KMEM(args); printk args; } while (0)
-
-#define TRC_TO_CONSOLE 1
-
-/*
- * Debugging levels can be set using debug insmod variable
- * They can also be compiled out completely.
- */
-
-#define	DBG_INIT		(dgap_debug & 0x01)
-#define	DBG_BASIC		(dgap_debug & 0x02)
-#define	DBG_CORE		(dgap_debug & 0x04)
-
-#define	DBG_OPEN		(dgap_debug & 0x08)
-#define	DBG_CLOSE		(dgap_debug & 0x10)
-#define	DBG_READ		(dgap_debug & 0x20)
-#define	DBG_WRITE		(dgap_debug & 0x40)
-
-#define	DBG_IOCTL		(dgap_debug & 0x80)
-
-#define	DBG_PROC		(dgap_debug & 0x100)
-#define	DBG_PARAM		(dgap_debug & 0x200)
-#define	DBG_PSCAN		(dgap_debug & 0x400)
-#define	DBG_EVENT		(dgap_debug & 0x800)
-
-#define	DBG_DRAIN		(dgap_debug & 0x1000)
-#define	DBG_CARR		(dgap_debug & 0x2000)
-
-#define	DBG_MGMT		(dgap_debug & 0x4000)
-
-
-#if defined(DGAP_TRACER)
-
-# if defined(TRC_TO_KMEM)
-/* Choose one: */
-#  define TRC_ON_OVERFLOW_WRAP_AROUND
-#  undef  TRC_ON_OVERFLOW_SHIFT_BUFFER
-# endif //TRC_TO_KMEM
-
-# define TRC_MAXMSG		1024
-# define TRC_OVERFLOW		"(OVERFLOW)"
-# define TRC_DTRC		"/usr/bin/dtrc"
-
-#if defined TRC_TO_CONSOLE
-#define PRINTF_TO_CONSOLE(args) { printk(DRVSTR": "); printk args; }
-#else //!defined TRACE_TO_CONSOLE
-#define PRINTF_TO_CONSOLE(args)
-#endif
-
-#if defined TRC_TO_KMEM
-#define PRINTF_TO_KMEM(args) dgap_tracef args
-#else //!defined TRC_TO_KMEM
-#define PRINTF_TO_KMEM(args)
-#endif
-
-#define	TRC(args)	{ PRINTF_TO_KMEM(args); PRINTF_TO_CONSOLE(args) }
-
-# define DPR_INIT(ARGS)		if (DBG_INIT) TRC(ARGS)
-# define DPR_BASIC(ARGS)	if (DBG_BASIC) TRC(ARGS)
-# define DPR_CORE(ARGS)		if (DBG_CORE) TRC(ARGS)
-# define DPR_OPEN(ARGS)		if (DBG_OPEN)  TRC(ARGS)
-# define DPR_CLOSE(ARGS)	if (DBG_CLOSE)  TRC(ARGS)
-# define DPR_READ(ARGS)		if (DBG_READ)  TRC(ARGS)
-# define DPR_WRITE(ARGS)	if (DBG_WRITE) TRC(ARGS)
-# define DPR_IOCTL(ARGS)	if (DBG_IOCTL) TRC(ARGS)
-# define DPR_PROC(ARGS)		if (DBG_PROC)  TRC(ARGS)
-# define DPR_PARAM(ARGS)	if (DBG_PARAM)  TRC(ARGS)
-# define DPR_PSCAN(ARGS)	if (DBG_PSCAN)  TRC(ARGS)
-# define DPR_EVENT(ARGS)	if (DBG_EVENT)  TRC(ARGS)
-# define DPR_DRAIN(ARGS)	if (DBG_DRAIN)  TRC(ARGS)
-# define DPR_CARR(ARGS)		if (DBG_CARR)  TRC(ARGS)
-# define DPR_MGMT(ARGS)		if (DBG_MGMT)  TRC(ARGS)
-
-# define DPR(ARGS)		if (dgap_debug) TRC(ARGS)
-# define P(X)			dgap_tracef(#X "=%p\n", X)
-# define X(X)			dgap_tracef(#X "=%x\n", X)
-
-#else//!defined DGAP_TRACER
-
-#define PRINTF_TO_KMEM(args)
-# define TRC(ARGS)
-# define DPR_INIT(ARGS)
-# define DPR_BASIC(ARGS)
-# define DPR_CORE(ARGS)
-# define DPR_OPEN(ARGS)
-# define DPR_CLOSE(ARGS)
-# define DPR_READ(ARGS)
-# define DPR_WRITE(ARGS)
-# define DPR_IOCTL(ARGS)
-# define DPR_PROC(ARGS)
-# define DPR_PARAM(ARGS)
-# define DPR_PSCAN(ARGS)
-# define DPR_EVENT(ARGS)
-# define DPR_DRAIN(ARGS)
-# define DPR_CARR(ARGS)
-# define DPR_MGMT(ARGS)
-
-# define DPR(args)
-
-#endif//DGAP_TRACER
-
-/* Number of boards we support at once. */
-#define	MAXBOARDS	32
-#define	MAXPORTS	224
-#define MAXTTYNAMELEN	200
-
-/* Our 3 magic numbers for our board, channel and unit structs */
-#define DGAP_BOARD_MAGIC	0x5c6df104
-#define DGAP_CHANNEL_MAGIC	0x6c6df104
-#define DGAP_UNIT_MAGIC		0x7c6df104
-
-/* Serial port types */
-#define DGAP_SERIAL		0
-#define DGAP_PRINT		1
-
-#define	SERIAL_TYPE_NORMAL	1
-
-/* 4 extra for alignment play space */
-#define WRITEBUFLEN		((4096) + 4)
-#define MYFLIPLEN		N_TTY_BUF_SIZE
-
-#define SBREAK_TIME 0x25
-#define U2BSIZE 0x400
-
-#define dgap_jiffies_from_ms(a) (((a) * HZ) / 1000)
-
-/*
- * Our major for the mgmt devices.
- *
- * We can use 22, because Digi was allocated 22 and 23 for the epca driver.
- * 22 has now become obsolete now that the "cu" devices have
- * been removed from 2.6.
- * Also, this *IS* the epca driver, just PCI only now.
- */
-#ifndef DIGI_DGAP_MAJOR
-# define DIGI_DGAP_MAJOR         22
-#endif
-
-/*
- * The parameters we use to define the periods of the moving averages.
- */
-#define		MA_PERIOD	(HZ / 10)
-#define		SMA_DUR		(1 * HZ)
-#define		EMA_DUR		(1 * HZ)
-#define		SMA_NPERIODS	(SMA_DUR / MA_PERIOD)
-#define		EMA_NPERIODS	(EMA_DUR / MA_PERIOD)
-
-/*
- * Define a local default termios struct. All ports will be created
- * with this termios initially.  This is the same structure that is defined
- * as the default in tty_io.c with the same settings overriden as in serial.c
- *
- * In short, this should match the internal serial ports' defaults.
- */
-#define	DEFAULT_IFLAGS	(ICRNL | IXON)
-#define	DEFAULT_OFLAGS	(OPOST | ONLCR)
-#define	DEFAULT_CFLAGS	(B9600 | CS8 | CREAD | HUPCL | CLOCAL)
-#define	DEFAULT_LFLAGS	(ISIG | ICANON | ECHO | ECHOE | ECHOK | \
-			ECHOCTL | ECHOKE | IEXTEN)
-
-#ifndef _POSIX_VDISABLE
-#define   _POSIX_VDISABLE '\0'
-#endif
-
-#define SNIFF_MAX	65536		/* Sniff buffer size (2^n) */
-#define SNIFF_MASK	(SNIFF_MAX - 1)	/* Sniff wrap mask */
-
-#define VPDSIZE (512)
-
-/*
- * Lock function/defines.
- * Makes spotting lock/unlock locations easier.
- */
-# define DGAP_SPINLOCK_INIT(x)		spin_lock_init(&(x))
-# define DGAP_LOCK(x,y)			spin_lock_irqsave(&(x), y)
-# define DGAP_UNLOCK(x,y)		spin_unlock_irqrestore(&(x), y)
-# define DGAP_TRYLOCK(x,y)		spin_trylock(&(x))
-
-/*
- * All the possible states the driver can be while being loaded.
- */
-enum {
-	DRIVER_INITIALIZED = 0,
-	DRIVER_NEED_CONFIG_LOAD,
-	DRIVER_REQUESTED_CONFIG,
-	DRIVER_READY
-};
-
-/*
- * All the possible states the board can be while booting up.
- */
-enum {
-	BOARD_FAILED = 0,
-	CONFIG_NOT_FOUND,
-	BOARD_FOUND,
-	NEED_RESET,
-	FINISHED_RESET,
-	NEED_CONFIG,
-	FINISHED_CONFIG,
-	NEED_DEVICE_CREATION,
-	REQUESTED_DEVICE_CREATION,
-	FINISHED_DEVICE_CREATION,
-	NEED_BIOS_LOAD,
-	REQUESTED_BIOS,
-	WAIT_BIOS_LOAD,
-	FINISHED_BIOS_LOAD,
-	NEED_FEP_LOAD,
-	REQUESTED_FEP,
-	WAIT_FEP_LOAD,
-	FINISHED_FEP_LOAD,
-	NEED_PROC_CREATION,
-	FINISHED_PROC_CREATION,
-	BOARD_READY
-};
-
-/*
- * All the possible states that a requested concentrator image can be in.
- */
-enum {
-	NO_PENDING_CONCENTRATOR_REQUESTS = 0,
-	NEED_CONCENTRATOR,
-	REQUESTED_CONCENTRATOR
-};
-
-extern char *dgap_state_text[];
-extern char *dgap_driver_state_text[];
-
-
-/*
- * Modem line constants are defined as macros because DSR and
- * DCD are swapable using the ditty altpin option.
- */
-#define D_CD(ch)        ch->ch_cd       /* Carrier detect       */
-#define D_DSR(ch)       ch->ch_dsr      /* Data set ready       */
-#define D_RTS(ch)       DM_RTS          /* Request to send      */
-#define D_CTS(ch)       DM_CTS          /* Clear to send        */
-#define D_RI(ch)        DM_RI           /* Ring indicator       */
-#define D_DTR(ch)       DM_DTR          /* Data terminal ready  */
-
-
-/*************************************************************************
- *
- * Structures and closely related defines.
- *
- *************************************************************************/
-
-
-/*
- * A structure to hold a statistics counter.  We also
- * compute moving averages for this counter.
- */
-struct macounter
-{
-	u32		cnt;	/* Total count */
-	ulong		accum;	/* Acuumulator per period */
-	ulong		sma;	/* Simple moving average */
-	ulong		ema;	/* Exponential moving average */
-};
-
-
-/************************************************************************
- * Device flag definitions for bd_flags.
- ************************************************************************/
-#define	BD_FEP5PLUS	0x0001          /* Supports FEP5 Plus commands */
-#define BD_HAS_VPD	0x0002		/* Board has VPD info available */
-
-
-/*
- *	Per-board information
- */
-struct board_t
-{
-	int		magic;		/* Board Magic number.  */
-	int		boardnum;	/* Board number: 0-3 */
-	int		firstminor;	/* First minor, e.g. 0, 30, 60 */
-
-	int		type;		/* Type of board */
-	char		*name;		/* Product Name */
-	struct pci_dev	*pdev;		/* Pointer to the pci_dev struct */
-	u16		vendor;		/* PCI vendor ID */
-	u16		device;		/* PCI device ID */
-	u16		subvendor;	/* PCI subsystem vendor ID */
-	u16		subdevice;	/* PCI subsystem device ID */
-	uchar		rev;		/* PCI revision ID */
-	uint		pci_bus;	/* PCI bus value */
-	uint		pci_slot;	/* PCI slot value */
-	u16		maxports;	/* MAX ports this board can handle */
-	uchar		vpd[VPDSIZE];	/* VPD of board, if found */
-	u32		bd_flags;	/* Board flags */
-
-	spinlock_t	bd_lock;	/* Used to protect board */
-
-	u32		state;		/* State of card. */
-	wait_queue_head_t state_wait;	/* Place to sleep on for state change */
-
-	struct		tasklet_struct helper_tasklet; /* Poll helper tasklet */
-
-	u32		wait_for_bios;
-	u32		wait_for_fep;
-
-	struct cnode *  bd_config;	/* Config of board */
-
-	u16		nasync;		/* Number of ports on card */
-
-	u32		use_interrupts;	/* Should we be interrupt driven? */
-	ulong		irq;		/* Interrupt request number */
-	ulong		intr_count;	/* Count of interrupts */
-	u32		intr_used;	/* Non-zero if using interrupts */
-	u32		intr_running;	/* Non-zero if FEP knows its doing interrupts */
-
-	ulong		port;		/* Start of base io port of the card */
-	ulong		port_end;	/* End of base io port of the card */
-	ulong		membase;	/* Start of base memory of the card */
-	ulong		membase_end;	/* End of base memory of the card */
-
-	uchar 		*re_map_port;	/* Remapped io port of the card */
-	uchar		*re_map_membase;/* Remapped memory of the card */
-
-	uchar		runwait;	/* # Processes waiting for FEP  */
-	uchar		inhibit_poller; /* Tells  the poller to leave us alone */
-
-	struct channel_t *channels[MAXPORTS]; /* array of pointers to our channels. */
-
-	struct tty_driver	*SerialDriver;
-	char		SerialName[200];
-	struct tty_driver	*PrintDriver;
-	char		PrintName[200];
-
-	u32		dgap_Major_Serial_Registered;
-	u32		dgap_Major_TransparentPrint_Registered;
-
-	u32		dgap_Serial_Major;
-	u32		dgap_TransparentPrint_Major;
-
-	struct bs_t	*bd_bs;			/* Base structure pointer       */
-
-	char	*flipbuf;		/* Our flip buffer, alloced if board is found */
-	char	*flipflagbuf;		/* Our flip flag buffer, alloced if board is found */
-
-	u16		dpatype;	/* The board "type", as defined by DPA */
-	u16		dpastatus;	/* The board "status", as defined by DPA */
-	wait_queue_head_t kme_wait;	/* Needed for DPA support */
-
-	u32		conc_dl_status;	/* Status of any pending conc download */
-	/*
-	 *	Mgmt data.
-	 */
-        char		*msgbuf_head;
-        char		*msgbuf;
-};
-
-
-
-/************************************************************************
- * Unit flag definitions for un_flags.
- ************************************************************************/
-#define UN_ISOPEN	0x0001		/* Device is open		*/
-#define UN_CLOSING	0x0002		/* Line is being closed		*/
-#define UN_IMM		0x0004		/* Service immediately		*/
-#define UN_BUSY		0x0008		/* Some work this channel	*/
-#define UN_BREAKI	0x0010		/* Input break received		*/
-#define UN_PWAIT	0x0020		/* Printer waiting for terminal	*/
-#define UN_TIME		0x0040		/* Waiting on time		*/
-#define UN_EMPTY	0x0080		/* Waiting output queue empty	*/
-#define UN_LOW		0x0100		/* Waiting output low water mark*/
-#define UN_EXCL_OPEN	0x0200		/* Open for exclusive use	*/
-#define UN_WOPEN	0x0400		/* Device waiting for open	*/
-#define UN_WIOCTL	0x0800		/* Device waiting for open	*/
-#define UN_HANGUP	0x8000		/* Carrier lost			*/
-
-struct device;
-
-/************************************************************************
- * Structure for terminal or printer unit.
- ************************************************************************/
-struct un_t {
-	int	magic;		/* Unit Magic Number.			*/
-	struct	channel_t *un_ch;
-	u32	un_time;
-	u32	un_type;
-	u32	un_open_count;	/* Counter of opens to port		*/
-	struct tty_struct *un_tty;/* Pointer to unit tty structure	*/
-	u32	un_flags;	/* Unit flags				*/
-	wait_queue_head_t un_flags_wait; /* Place to sleep to wait on unit */
-	u32	un_dev;		/* Minor device number			*/
-	tcflag_t un_oflag;	/* oflags being done on board		*/
-	tcflag_t un_lflag;	/* lflags being done on board		*/
-	struct device *un_sysfs;
-};
-
-
-/************************************************************************
- * Device flag definitions for ch_flags.
- ************************************************************************/
-#define CH_PRON         0x0001          /* Printer on string                */
-#define CH_OUT          0x0002          /* Dial-out device open             */
-#define CH_STOP         0x0004          /* Output is stopped                */
-#define CH_STOPI        0x0008          /* Input is stopped                 */
-#define CH_CD           0x0010          /* Carrier is present               */
-#define CH_FCAR         0x0020          /* Carrier forced on                */
-
-#define CH_RXBLOCK      0x0080          /* Enable rx blocked flag           */
-#define CH_WLOW         0x0100          /* Term waiting low event           */
-#define CH_WEMPTY       0x0200          /* Term waiting empty event         */
-#define CH_RENABLE      0x0400          /* Buffer just emptied          */
-#define CH_RACTIVE      0x0800          /* Process active in xxread()   */
-#define CH_RWAIT        0x1000          /* Process waiting in xxread()  */
-#define CH_BAUD0	0x2000		/* Used for checking B0 transitions */
-#define CH_HANGUP       0x8000		/* Hangup received                  */
-
-/*
- * Definitions for ch_sniff_flags
- */
-#define SNIFF_OPEN	0x1
-#define SNIFF_WAIT_DATA	0x2
-#define SNIFF_WAIT_SPACE 0x4
-
-
-/************************************************************************
- * Channel information structure.
- ************************************************************************/
-struct channel_t {
-	int magic;			/* Channel Magic Number		*/
-	struct bs_t	*ch_bs;		/* Base structure pointer       */
-	struct cm_t	*ch_cm;		/* Command queue pointer        */
-	struct board_t *ch_bd;		/* Board structure pointer      */
-	unsigned char *ch_vaddr;	/* FEP memory origin            */
-	unsigned char *ch_taddr;	/* Write buffer origin          */
-	unsigned char *ch_raddr;	/* Read buffer origin           */
-	struct digi_t  ch_digi;		/* Transparent Print structure  */
-	struct un_t ch_tun;		/* Terminal unit info           */
-	struct un_t ch_pun;		/* Printer unit info            */
-
-	spinlock_t	ch_lock;	/* provide for serialization */
-	wait_queue_head_t ch_flags_wait;
-
-	u32	pscan_state;
-	uchar	pscan_savechar;
-
-	u32 ch_portnum;			/* Port number, 0 offset.	*/
-	u32 ch_open_count;		/* open count			*/
-	u32	ch_flags;		/* Channel flags                */
-
-
-	u32	ch_close_delay;		/* How long we should drop RTS/DTR for */
-
-	u32	ch_cpstime;		/* Time for CPS calculations    */
-
-	tcflag_t ch_c_iflag;		/* channel iflags               */
-	tcflag_t ch_c_cflag;		/* channel cflags               */
-	tcflag_t ch_c_oflag;		/* channel oflags               */
-	tcflag_t ch_c_lflag;		/* channel lflags               */
-
-	u16  ch_fepiflag;            /* FEP tty iflags               */
-	u16  ch_fepcflag;		/* FEP tty cflags               */
-	u16  ch_fepoflag;		/* FEP tty oflags               */
-	u16  ch_wopen;			/* Waiting for open process cnt */
-	u16  ch_tstart;			/* Transmit buffer start        */
-	u16  ch_tsize;			/* Transmit buffer size         */
-	u16  ch_rstart;			/* Receive buffer start         */
-	u16  ch_rsize;			/* Receive buffer size          */
-	u16  ch_rdelay;			/* Receive delay time           */
-
-	u16	ch_tlw;			/* Our currently set low water mark */
-
-	u16  ch_cook;			/* Output character mask        */
-
-	uchar   ch_card;		/* Card channel is on           */
-	uchar   ch_stopc;		/* Stop character               */
-	uchar   ch_startc;		/* Start character              */
-
-	uchar   ch_mostat;		/* FEP output modem status      */
-	uchar   ch_mistat;		/* FEP input modem status       */
-	uchar   ch_mforce;		/* Modem values to be forced    */
-	uchar   ch_mval;		/* Force values                 */
-	uchar   ch_fepstopc;		/* FEP stop character           */
-	uchar   ch_fepstartc;		/* FEP start character          */
-
-	uchar   ch_astopc;		/* Auxiliary Stop character     */
-	uchar   ch_astartc;		/* Auxiliary Start character    */
-	uchar   ch_fepastopc;		/* Auxiliary FEP stop char      */
-	uchar   ch_fepastartc;		/* Auxiliary FEP start char     */
-
-	uchar   ch_hflow;		/* FEP hardware handshake       */
-	uchar   ch_dsr;			/* stores real dsr value        */
-	uchar   ch_cd;			/* stores real cd value         */
-	uchar   ch_tx_win;		/* channel tx buffer window     */
-	uchar   ch_rx_win;		/* channel rx buffer window     */
-	uint	ch_custom_speed;	/* Custom baud, if set		*/
-	uint	ch_baud_info;		/* Current baud info for /proc output	*/
-	ulong	ch_rxcount;		/* total of data received so far	*/
-	ulong	ch_txcount;		/* total of data transmitted so far	*/
-	ulong	ch_err_parity;		/* Count of parity errors on channel	*/
-	ulong	ch_err_frame;		/* Count of framing errors on channel	*/
-	ulong	ch_err_break;		/* Count of breaks on channel	*/
-	ulong	ch_err_overrun;		/* Count of overruns on channel	*/
-
-	uint ch_sniff_in;
-	uint ch_sniff_out;
-	char *ch_sniff_buf;		/* Sniff buffer for proc */
-	ulong ch_sniff_flags;		/* Channel flags                */
-	wait_queue_head_t ch_sniff_wait;
-};
-
-
-/*************************************************************************
- *
- * Prototypes for non-static functions used in more than one module
- *
- *************************************************************************/
-
-extern int		dgap_ms_sleep(ulong ms);
-extern char		*dgap_ioctl_name(int cmd);
-extern void		dgap_do_bios_load(struct board_t *brd, uchar __user *ubios, int len);
-extern void		dgap_do_fep_load(struct board_t *brd, uchar __user *ufep, int len);
-extern void		dgap_do_conc_load(struct board_t *brd, uchar *uaddr, int len);
-extern void		dgap_do_config_load(uchar __user *uaddr, int len);
-extern int		dgap_after_config_loaded(void);
-extern int		dgap_finalize_board_init(struct board_t *brd);
-
-/*
- * Our Global Variables.
- */
-extern int		dgap_driver_state;	/* The state of the driver	*/
-extern int		dgap_debug;		/* Debug variable		*/
-extern int		dgap_rawreadok;		/* Set if user wants rawreads	*/
-extern int		dgap_poll_tick;		/* Poll interval - 20 ms	*/
-extern spinlock_t	dgap_global_lock;	/* Driver global spinlock	*/
-extern uint		dgap_NumBoards;		/* Total number of boards	*/
-extern struct board_t	*dgap_Board[MAXBOARDS];	/* Array of board structs	*/
-extern ulong		dgap_poll_counter;	/* Times the poller has run	*/
-extern char		*dgap_config_buf;	/* The config file buffer	*/
-extern spinlock_t	dgap_dl_lock;		/* Downloader spinlock		*/
-extern wait_queue_head_t dgap_dl_wait;		/* Wait queue for downloader	*/
-extern int		dgap_dl_action;		/* Action flag for downloader	*/
-extern int		dgap_registerttyswithsysfs; /* Should we register the	*/
-						    /* ttys with sysfs or not	*/
-
-/*
- * Global functions declared in dgap_fep5.c, but must be hidden from
- * user space programs.
- */
-extern void	dgap_poll_tasklet(unsigned long data);
-extern void	dgap_cmdb(struct channel_t *ch, uchar cmd, uchar byte1, uchar byte2, uint ncmds);
-extern void	dgap_cmdw(struct channel_t *ch, uchar cmd, u16 word, uint ncmds);
-extern void	dgap_wmove(struct channel_t *ch, char *buf, uint cnt);
-extern int	dgap_param(struct tty_struct *tty);
-extern void	dgap_parity_scan(struct channel_t *ch, unsigned char *cbuf, unsigned char *fbuf, int *len);
-extern uint	dgap_get_custom_baud(struct channel_t *ch);
-extern void	dgap_firmware_reset_port(struct channel_t *ch);
-
-#endif
diff --git a/drivers/staging/dgap/dgap_fep5.c b/drivers/staging/dgap/dgap_fep5.c
deleted file mode 100644
index 51cda71..0000000
--- a/drivers/staging/dgap/dgap_fep5.c
+++ /dev/null
@@ -1,1903 +0,0 @@
-/*
- * Copyright 2003 Digi International (www.digi.com)
- *	Scott H Kilau <Scott_Kilau at digi dot com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- *	NOTE TO LINUX KERNEL HACKERS:  DO NOT REFORMAT THIS CODE!
- *
- *	This is shared code between Digi's CVS archive and the
- *	Linux Kernel sources.
- *	Changing the source just for reformatting needlessly breaks
- *	our CVS diff history.
- *
- *	Send any bug fixes/changes to:  Eng.Linux at digi dot com.
- *	Thank you.
- *
- * $Id: dgap_fep5.c,v 1.2 2011/06/21 10:35:40 markh Exp $
- */
-
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/delay.h>	/* For udelay */
-#include <asm/uaccess.h>	/* For copy_from_user/copy_to_user */
-#include <linux/tty.h>
-#include <linux/tty_flip.h>	/* For tty_schedule_flip */
-#include <linux/slab.h>
-#include <linux/sched.h>
-
-#include "dgap_driver.h"
-#include "dgap_pci.h"
-#include "dgap_fep5.h"
-#include "dgap_tty.h"
-#include "dgap_conf.h"
-#include "dgap_parse.h"
-#include "dgap_trace.h"
-
-/*
- * Our function prototypes
- */
-static void dgap_cmdw_ext(struct channel_t *ch, u16 cmd, u16 word, uint ncmds);
-static int dgap_event(struct board_t *bd);
-
-/*
- * internal variables
- */
-static uint dgap_count = 500;
-
-
-/*
- * Loads the dgap.conf config file from the user.
- */
-void dgap_do_config_load(uchar __user *uaddr, int len)
-{
-	int orig_len = len;
-	char *to_addr;
-	uchar __user *from_addr = uaddr;
-	char buf[U2BSIZE];
-	int n;
-
-	to_addr = dgap_config_buf = kzalloc(len + 1, GFP_ATOMIC);
-	if (!dgap_config_buf) {
-		DPR_INIT(("dgap_do_config_load - unable to allocate memory for file\n"));
-		dgap_driver_state = DRIVER_NEED_CONFIG_LOAD;
-		return;
-	}
-
-	n = U2BSIZE;
-	while (len) {
-
-		if (n > len)
-			n = len;
-
-		if (copy_from_user((char *) &buf, from_addr, n) == -1 )
-			return;
-
-		/* Copy data from buffer to kernel memory */
-		memcpy(to_addr, buf, n);
-
-		/* increment counts */
-		len -= n;
-		to_addr += n;
-		from_addr += n;
-		n = U2BSIZE;
-	}
-
-	dgap_config_buf[orig_len] = '\0';
-
-	to_addr = dgap_config_buf;
-	dgap_parsefile(&to_addr, TRUE);
-
-	DPR_INIT(("dgap_config_load() finish\n"));
-
-	return;
-}
-
-
-int dgap_after_config_loaded(void)
-{
-	int i = 0;
-	int rc = 0;
-
-	/*
-	 * Register our ttys, now that we have the config loaded.
-	 */
-	for (i = 0; i < dgap_NumBoards; ++i) {
-
-		/*
-		 * Initialize KME waitqueues...
-		 */
-		init_waitqueue_head(&(dgap_Board[i]->kme_wait));
-
-		/*
-		 * allocate flip buffer for board.
-		 */
-		dgap_Board[i]->flipbuf = kzalloc(MYFLIPLEN, GFP_ATOMIC);
-		dgap_Board[i]->flipflagbuf = kzalloc(MYFLIPLEN, GFP_ATOMIC);
-	}
-
-	return rc;
-}
-
-
-
-/*=======================================================================
- *
- *      usertoboard - copy from user space to board space.
- *
- *=======================================================================*/
-static int dgap_usertoboard(struct board_t *brd, char *to_addr, char __user *from_addr, int len)
-{
-	char buf[U2BSIZE];
-	int n = U2BSIZE;
-
-	if (!brd || brd->magic != DGAP_BOARD_MAGIC)
-		return -EFAULT;
-
-	while (len) {
-		if (n > len)
-			n = len;
-
-		if (copy_from_user((char *) &buf, from_addr, n) == -1 ) {
-			return -EFAULT;
-		}
-
-		/* Copy data from buffer to card memory */
-		memcpy_toio(to_addr, buf, n);
-
-		/* increment counts */
-		len -= n;
-		to_addr += n;
-		from_addr += n;
-		n = U2BSIZE;
-	}
-	return 0;
-}
-
-
-/*
- * Copies the BIOS code from the user to the board,
- * and starts the BIOS running.
- */
-void dgap_do_bios_load(struct board_t *brd, uchar __user *ubios, int len)
-{
-	uchar *addr;
-	uint offset;
-	int i;
-
-	if (!brd || (brd->magic != DGAP_BOARD_MAGIC) || !brd->re_map_membase)
-		return;
-
-	DPR_INIT(("dgap_do_bios_load() start\n"));
-
-	addr = brd->re_map_membase;
-
-	/*
-	 * clear POST area
-	 */
-	for (i = 0; i < 16; i++)
-		writeb(0, addr + POSTAREA + i);
-
-	/*
-	 * Download bios
-	 */
-	offset = 0x1000;
-	if (dgap_usertoboard(brd, addr + offset, ubios, len) == -1 ) {
-		brd->state = BOARD_FAILED;
-		brd->dpastatus = BD_NOFEP;
-		return;
-	}
-
-	writel(0x0bf00401, addr);
-	writel(0, (addr + 4));
-
-	/* Clear the reset, and change states. */
-	writeb(FEPCLR, brd->re_map_port);
-	brd->state = WAIT_BIOS_LOAD;
-}
-
-
-/*
- * Checks to see if the BIOS completed running on the card.
- */
-static void dgap_do_wait_for_bios(struct board_t *brd)
-{
-	uchar *addr;
-	u16 word;
-
-	if (!brd || (brd->magic != DGAP_BOARD_MAGIC) || !brd->re_map_membase)
-		return;
-
-	addr = brd->re_map_membase;
-	word = readw(addr + POSTAREA);
-
-	/* Check to see if BIOS thinks board is good. (GD). */
-	if (word == *(u16 *) "GD") {
-		DPR_INIT(("GOT GD in memory, moving states.\n"));
-		brd->state = FINISHED_BIOS_LOAD;
-		return;
-	}
-
-	/* Give up on board after too long of time taken */
-	if (brd->wait_for_bios++ > 5000) {
-		u16 err1 = readw(addr + SEQUENCE);
-		u16 err2 = readw(addr + ERROR);
-		APR(("***WARNING*** %s failed diagnostics.  Error #(%x,%x).\n",
-			brd->name, err1, err2));
-		brd->state = BOARD_FAILED;
-		brd->dpastatus = BD_NOFEP;
-	}
-}
-
-
-/*
- * Copies the FEP code from the user to the board,
- * and starts the FEP running.
- */
-void dgap_do_fep_load(struct board_t *brd, uchar __user *ufep, int len)
-{
-	uchar *addr;
-	uint offset;
-
-	if (!brd || (brd->magic != DGAP_BOARD_MAGIC) || !brd->re_map_membase)
-		return;
-
-	addr = brd->re_map_membase;
-
-	DPR_INIT(("dgap_do_fep_load() for board %s : start\n", brd->name));
-
-	/*
-	 * Download FEP
-	 */
-	offset = 0x1000;
-	if (dgap_usertoboard(brd, addr + offset, ufep, len) == -1 ) {
-		brd->state = BOARD_FAILED;
-		brd->dpastatus = BD_NOFEP;
-		return;
-	}
-
-	/*
-	 * If board is a concentrator product, we need to give
-	 * it its config string describing how the concentrators look.
-	 */
-	if ((brd->type == PCX) || (brd->type == PEPC)) {
-		uchar string[100];
-		uchar *config, *xconfig;
-		int i = 0;
-
-		xconfig = dgap_create_config_string(brd, string);
-
-		/* Write string to board memory */
-		config = addr + CONFIG;
-		for (; i < CONFIGSIZE; i++, config++, xconfig++) {
-			writeb(*xconfig, config);
-			if ((*xconfig & 0xff) == 0xff)
-				break;
-		}
-	}
-
-	writel(0xbfc01004, (addr + 0xc34));
-	writel(0x3, (addr + 0xc30));
-
-	/* change states. */
-	brd->state = WAIT_FEP_LOAD;
-
-	DPR_INIT(("dgap_do_fep_load() for board %s : finish\n", brd->name));
-
-}
-
-
-/*
- * Waits for the FEP to report thats its ready for us to use.
- */
-static void dgap_do_wait_for_fep(struct board_t *brd)
-{
-	uchar *addr;
-	u16 word;
-
-	if (!brd || (brd->magic != DGAP_BOARD_MAGIC) || !brd->re_map_membase)
-		return;
-
-	addr = brd->re_map_membase;
-
-	DPR_INIT(("dgap_do_wait_for_fep() for board %s : start. addr: %p\n", brd->name, addr));
-
-	word = readw(addr + FEPSTAT);
-
-	/* Check to see if FEP is up and running now. */
-	if (word == *(u16 *) "OS") {
-		DPR_INIT(("GOT OS in memory for board %s, moving states.\n", brd->name));
-		brd->state = FINISHED_FEP_LOAD;
-
-		/*
-		 * Check to see if the board can support FEP5+ commands.
-		 */
-		word = readw(addr + FEP5_PLUS);
-		if (word == *(u16 *) "5A") {
-			DPR_INIT(("GOT 5A in memory for board %s, board supports extended FEP5 commands.\n", brd->name));
-			brd->bd_flags |= BD_FEP5PLUS;
-		}
-
-		return;
-	}
-
-	/* Give up on board after too long of time taken */
-	if (brd->wait_for_fep++ > 5000) {
-		u16 err1 = readw(addr + SEQUENCE);
-		u16 err2 = readw(addr + ERROR);
-		APR(("***WARNING*** FEPOS for %s not functioning.  Error #(%x,%x).\n",
-			brd->name, err1, err2));
-		brd->state = BOARD_FAILED;
-		brd->dpastatus = BD_NOFEP;
-	}
-
-	DPR_INIT(("dgap_do_wait_for_fep() for board %s : finish\n", brd->name));
-}
-
-
-/*
- * Physically forces the FEP5 card to reset itself.
- */
-static void dgap_do_reset_board(struct board_t *brd)
-{
-	uchar check;
-	u32 check1;
-	u32 check2;
-	int i = 0;
-
-	if (!brd || (brd->magic != DGAP_BOARD_MAGIC) || !brd->re_map_membase || !brd->re_map_port) {
-		DPR_INIT(("dgap_do_reset_board() start. bad values. brd: %p mem: %p io: %p\n",
-			brd, brd ? brd->re_map_membase : 0, brd ? brd->re_map_port : 0));
-		return;
-	}
-
-	DPR_INIT(("dgap_do_reset_board() start. io: %p\n", brd->re_map_port));
-
-	/* FEPRST does not vary among supported boards */
-	writeb(FEPRST, brd->re_map_port);
-
-	for (i = 0; i <= 1000; i++) {
-		check = readb(brd->re_map_port) & 0xe;
-		if (check == FEPRST)
-			break;
-		udelay(10);
-
-	}
-	if (i > 1000) {
-		APR(("*** WARNING *** Board not resetting...  Failing board.\n"));
-		brd->state = BOARD_FAILED;
-		brd->dpastatus = BD_NOFEP;
-		goto failed;
-	}
-
-	/*
-	 * Make sure there really is memory out there.
-	 */
-	writel(0xa55a3cc3, (brd->re_map_membase + LOWMEM));
-	writel(0x5aa5c33c, (brd->re_map_membase + HIGHMEM));
-	check1 = readl(brd->re_map_membase + LOWMEM);
-	check2 = readl(brd->re_map_membase + HIGHMEM);
-
-	if ((check1 != 0xa55a3cc3) || (check2 != 0x5aa5c33c)) {
-		APR(("*** Warning *** No memory at %p for board.\n", brd->re_map_membase));
-		brd->state = BOARD_FAILED;
-		brd->dpastatus = BD_NOFEP;
-		goto failed;
-	}
-
-	if (brd->state != BOARD_FAILED)
-		brd->state = FINISHED_RESET;
-
-failed:
-	DPR_INIT(("dgap_do_reset_board() finish\n"));
-}
-
-
-/*
- * Sends a concentrator image into the FEP5 board.
- */
-void dgap_do_conc_load(struct board_t *brd, uchar *uaddr, int len)
-{
-	char *vaddr;
-	u16 offset = 0;
-	struct downld_t *to_dp;
-
-	if (!brd || (brd->magic != DGAP_BOARD_MAGIC) || !brd->re_map_membase)
-		return;
-
-	vaddr = brd->re_map_membase;
-
-	offset = readw((u16 *) (vaddr + DOWNREQ));
-	to_dp = (struct downld_t *) (vaddr + (int) offset);
-
-	/*
-	 * The image was already read into kernel space,
-	 * we do NOT need a user space read here
-	 */
-	memcpy_toio((char *) to_dp, uaddr, sizeof(struct downld_t));
-
-	/* Tell card we have data for it */
-	writew(0, vaddr + (DOWNREQ));
-
-	brd->conc_dl_status = NO_PENDING_CONCENTRATOR_REQUESTS;
-}
-
-
-#define EXPANSION_ROM_SIZE	(64 * 1024)
-#define FEP5_ROM_MAGIC		(0xFEFFFFFF)
-
-static void dgap_get_vpd(struct board_t *brd)
-{
-	u32 magic;
-	u32 base_offset;
-	u16 rom_offset;
-	u16 vpd_offset;
-	u16 image_length;
-	u16 i;
-	uchar byte1;
-	uchar byte2;
-
-	/*
-	 * Poke the magic number at the PCI Rom Address location.
-	 * If VPD is supported, the value read from that address
-	 * will be non-zero.
-	 */
-	magic = FEP5_ROM_MAGIC;
-	pci_write_config_dword(brd->pdev, PCI_ROM_ADDRESS, magic);
-	pci_read_config_dword(brd->pdev, PCI_ROM_ADDRESS, &magic);
-
-	/* VPD not supported, bail */
-	if (!magic)
-		return;
-
-	/*
-	 * To get to the OTPROM memory, we have to send the boards base
-	 * address or'ed with 1 into the PCI Rom Address location.
-	 */
-	magic = brd->membase | 0x01;
-	pci_write_config_dword(brd->pdev, PCI_ROM_ADDRESS, magic);
-	pci_read_config_dword(brd->pdev, PCI_ROM_ADDRESS, &magic);
-
-	byte1 = readb(brd->re_map_membase);
-	byte2 = readb(brd->re_map_membase + 1);
-
-	/*
-	 * If the board correctly swapped to the OTPROM memory,
-	 * the first 2 bytes (header) should be 0x55, 0xAA
-	 */
-	if (byte1 == 0x55 && byte2 == 0xAA) {
-
-		base_offset = 0;
-
-		/*
-		 * We have to run through all the OTPROM memory looking
-		 * for the VPD offset.
-		 */
-		while (base_offset <= EXPANSION_ROM_SIZE) {
-
-			/*
-			 * Lots of magic numbers here.
-			 *
-			 * The VPD offset is located inside the ROM Data Structure.
-			 * We also have to remember the length of each
-			 * ROM Data Structure, so we can "hop" to the next
-			 * entry if the VPD isn't in the current
-			 * ROM Data Structure.
-			 */
-			rom_offset = readw(brd->re_map_membase + base_offset + 0x18);
-			image_length = readw(brd->re_map_membase + rom_offset + 0x10) * 512;
-			vpd_offset = readw(brd->re_map_membase + rom_offset + 0x08);
-
-			/* Found the VPD entry */
-			if (vpd_offset)
-				break;
-
-			/* We didn't find a VPD entry, go to next ROM entry. */
-			base_offset += image_length;
-
-			byte1 = readb(brd->re_map_membase + base_offset);
-			byte2 = readb(brd->re_map_membase + base_offset + 1);
-
-			/*
-			 * If the new ROM offset doesn't have 0x55, 0xAA
-			 * as its header, we have run out of ROM.
-			 */
-			if (byte1 != 0x55 || byte2 != 0xAA)
-				break;
-		}
-
-		/*
-		 * If we have a VPD offset, then mark the board
-		 * as having a valid VPD, and copy VPDSIZE (512) bytes of
-		 * that VPD to the buffer we have in our board structure.
-		 */
-		if (vpd_offset) {
-			brd->bd_flags |= BD_HAS_VPD;
-			for (i = 0; i < VPDSIZE; i++)
-				brd->vpd[i] = readb(brd->re_map_membase + vpd_offset + i);
-		}
-	}
-
-	/*
-	 * We MUST poke the magic number at the PCI Rom Address location again.
-	 * This makes the card report the regular board memory back to us,
-	 * rather than the OTPROM memory.
-	 */
-	magic = FEP5_ROM_MAGIC;
-	pci_write_config_dword(brd->pdev, PCI_ROM_ADDRESS, magic);
-}
-
-
-/*
- * Our board poller function.
- */
-void dgap_poll_tasklet(unsigned long data)
-{
-	struct board_t *bd = (struct board_t *) data;
-	ulong  lock_flags;
-	ulong  lock_flags2;
-	char *vaddr;
-	u16 head, tail;
-	u16 *chk_addr;
-	u16 check = 0;
-
-	if (!bd || (bd->magic != DGAP_BOARD_MAGIC)) {
-		APR(("dgap_poll_tasklet() - NULL or bad bd.\n"));
-		return;
-	}
-
-	if (bd->inhibit_poller)
-		return;
-
-	DGAP_LOCK(bd->bd_lock, lock_flags);
-
-	vaddr = bd->re_map_membase;
-
-	/*
-	 * If board is ready, parse deeper to see if there is anything to do.
-	 */
-	if (bd->state == BOARD_READY) {
-
-		struct ev_t *eaddr = NULL;
-
-		if (!bd->re_map_membase) {
-			DGAP_UNLOCK(bd->bd_lock, lock_flags);
-			return;
-		}
-		if (!bd->re_map_port) {
-			DGAP_UNLOCK(bd->bd_lock, lock_flags);
-			return;
-		}
-
-		if (!bd->nasync) {
-			goto out;
-		}
-
-		/*
-		 * If this is a CX or EPCX, we need to see if the firmware
-		 * is requesting a concentrator image from us.
-		 */
-		if ((bd->type == PCX) || (bd->type == PEPC)) {
-			chk_addr = (u16 *) (vaddr + DOWNREQ);
-			check = readw(chk_addr);
-			/* Nonzero if FEP is requesting concentrator image. */
-			if (check) {
-				if (bd->conc_dl_status == NO_PENDING_CONCENTRATOR_REQUESTS)
-					bd->conc_dl_status = NEED_CONCENTRATOR;
-				/*
-				 * Signal downloader, its got some work to do.
-				 */
-				DGAP_LOCK(dgap_dl_lock, lock_flags2);
-				if (dgap_dl_action != 1) {
-					dgap_dl_action = 1;
-					wake_up_interruptible(&dgap_dl_wait);
-				}
-				DGAP_UNLOCK(dgap_dl_lock, lock_flags2);
-
-			}
-		}
-
-		eaddr = (struct ev_t *) (vaddr + EVBUF);
-
-		/* Get our head and tail */
-		head = readw(&(eaddr->ev_head));
-		tail = readw(&(eaddr->ev_tail));
-
-		/*
-		 * If there is an event pending. Go service it.
-		 */
-		if (head != tail) {
-			DGAP_UNLOCK(bd->bd_lock, lock_flags);
-			dgap_event(bd);
-			DGAP_LOCK(bd->bd_lock, lock_flags);
-		}
-
-out:
-		/*
-		 * If board is doing interrupts, ACK the interrupt.
-		 */
-		if (bd && bd->intr_running) {
-			readb(bd->re_map_port + 2);
-		}
-
-		DGAP_UNLOCK(bd->bd_lock, lock_flags);
-		return;
-	}
-
-	/* Our state machine to get the board up and running */
-
-	/* Reset board */
-	if (bd->state == NEED_RESET) {
-
-		/* Get VPD info */
-		dgap_get_vpd(bd);
-
-		dgap_do_reset_board(bd);
-	}
-
-	/* Move to next state */
-	if (bd->state == FINISHED_RESET) {
-		bd->state = NEED_CONFIG;
-	}
-
-	if (bd->state == NEED_CONFIG) {
-		/*
-		 * Match this board to a config the user created for us.
-		 */
-		bd->bd_config = dgap_find_config(bd->type, bd->pci_bus, bd->pci_slot);
-
-		/*
-		 * Because the 4 port Xr products share the same PCI ID
-		 * as the 8 port Xr products, if we receive a NULL config
-		 * back, and this is a PAPORT8 board, retry with a
-		 * PAPORT4 attempt as well.
-		 */
-		if (bd->type == PAPORT8 && !bd->bd_config) {
-			bd->bd_config = dgap_find_config(PAPORT4, bd->pci_bus, bd->pci_slot);
-		}
-
-		/*
-		 * Register the ttys (if any) into the kernel.
-		 */
-		if (bd->bd_config) {
-			bd->state = FINISHED_CONFIG;
-		}
-		else {
-			bd->state = CONFIG_NOT_FOUND;
-		}
-	}
-
-	/* Move to next state */
-	if (bd->state == FINISHED_CONFIG) {
-		bd->state = NEED_DEVICE_CREATION;
-	}
-
-	/* Move to next state */
-	if (bd->state == NEED_DEVICE_CREATION) {
-		/*
-		 * Signal downloader, its got some work to do.
-		 */
-		DGAP_LOCK(dgap_dl_lock, lock_flags2);
-		if (dgap_dl_action != 1) {
-			dgap_dl_action = 1;
-			wake_up_interruptible(&dgap_dl_wait);
-		}
-		DGAP_UNLOCK(dgap_dl_lock, lock_flags2);
-	}
-
-	/* Move to next state */
-	if (bd->state == FINISHED_DEVICE_CREATION) {
-		bd->state = NEED_BIOS_LOAD;
-	}
-
-	/* Move to next state */
-	if (bd->state == NEED_BIOS_LOAD) {
-		/*
-		 * Signal downloader, its got some work to do.
-		 */
-		DGAP_LOCK(dgap_dl_lock, lock_flags2);
-		if (dgap_dl_action != 1) {
-			dgap_dl_action = 1;
-			wake_up_interruptible(&dgap_dl_wait);
-		}
-		DGAP_UNLOCK(dgap_dl_lock, lock_flags2);
-	}
-
-	/* Wait for BIOS to test board... */
-	if (bd->state == WAIT_BIOS_LOAD) {
-		dgap_do_wait_for_bios(bd);
-	}
-
-	/* Move to next state */
-	if (bd->state == FINISHED_BIOS_LOAD) {
-		bd->state = NEED_FEP_LOAD;
-
-		/*
-		 * Signal downloader, its got some work to do.
-		 */
-		DGAP_LOCK(dgap_dl_lock, lock_flags2);
-		if (dgap_dl_action != 1) {
-			dgap_dl_action = 1;
-			wake_up_interruptible(&dgap_dl_wait);
-		}
-		DGAP_UNLOCK(dgap_dl_lock, lock_flags2);
-	}
-
-	/* Wait for FEP to load on board... */
-	if (bd->state == WAIT_FEP_LOAD) {
-		dgap_do_wait_for_fep(bd);
-	}
-
-
-	/* Move to next state */
-	if (bd->state == FINISHED_FEP_LOAD) {
-
-		/*
-		 * Do tty device initialization.
-		 */
-		int rc = dgap_tty_init(bd);
-
-		if (rc < 0) {
-			dgap_tty_uninit(bd);
-			APR(("Can't init tty devices (%d)\n", rc));
-			bd->state = BOARD_FAILED;
-			bd->dpastatus = BD_NOFEP;
-		}
-		else {
-			bd->state = NEED_PROC_CREATION;
-
-			/*
-			 * Signal downloader, its got some work to do.
-			 */
-			DGAP_LOCK(dgap_dl_lock, lock_flags2);
-			if (dgap_dl_action != 1) {
-				dgap_dl_action = 1;
-				wake_up_interruptible(&dgap_dl_wait);
-			}
-			DGAP_UNLOCK(dgap_dl_lock, lock_flags2);
-		}
-	}
-
-	/* Move to next state */
-	if (bd->state == FINISHED_PROC_CREATION) {
-
-		bd->state = BOARD_READY;
-		bd->dpastatus = BD_RUNNING;
-
-		/*
-		 * If user requested the board to run in interrupt mode,
-		 * go and set it up on the board.
-		 */
-		if (bd->intr_used) {
-			writew(1, (bd->re_map_membase + ENABLE_INTR));
-			/*
-			 * Tell the board to poll the UARTS as fast as possible.
-			 */
-			writew(FEPPOLL_MIN, (bd->re_map_membase + FEPPOLL));
-			bd->intr_running = 1;
-		}
-
-		/* Wake up anyone waiting for board state to change to ready */
-		wake_up_interruptible(&bd->state_wait);
-	}
-
-	DGAP_UNLOCK(bd->bd_lock, lock_flags);
-}
-
-
-/*=======================================================================
- *
- *      dgap_cmdb - Sends a 2 byte command to the FEP.
- *
- *              ch      - Pointer to channel structure.
- *              cmd     - Command to be sent.
- *              byte1   - Integer containing first byte to be sent.
- *              byte2   - Integer containing second byte to be sent.
- *              ncmds   - Wait until ncmds or fewer cmds are left
- *                        in the cmd buffer before returning.
- *
- *=======================================================================*/
-void dgap_cmdb(struct channel_t *ch, uchar cmd, uchar byte1, uchar byte2, uint ncmds)
-{
-	char		*vaddr = NULL;
-	struct cm_t	*cm_addr = NULL;
-	uint		count;
-	uint		n;
-	u16		head;
-	u16		tail;
-
-	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-		return;
-
-	/*
-	 * Check if board is still alive.
-	 */
-	if (ch->ch_bd->state == BOARD_FAILED) {
-		DPR_CORE(("%s:%d board is in failed state.\n", __FILE__, __LINE__));
-		return;
-	}
-
-	/*
-	 * Make sure the pointers are in range before
-	 * writing to the FEP memory.
-	 */
-	vaddr = ch->ch_bd->re_map_membase;
-
-	if (!vaddr)
-		return;
-
-	cm_addr = (struct cm_t *) (vaddr + CMDBUF);
-	head = readw(&(cm_addr->cm_head));
-
-	/*
-	 * Forget it if pointers out of range.
-	 */
-	if (head >= (CMDMAX - CMDSTART) || (head & 03)) {
-		DPR_CORE(("%s:%d pointers out of range, failing board!\n", __FILE__, __LINE__));
-		ch->ch_bd->state = BOARD_FAILED;
-		return;
-	}
-
-	/*
-	 * Put the data in the circular command buffer.
-	 */
-	writeb(cmd, (char *) (vaddr + head + CMDSTART + 0));
-	writeb((uchar) ch->ch_portnum, (char *) (vaddr + head + CMDSTART + 1));
-	writeb(byte1, (char *) (vaddr + head + CMDSTART + 2));
-	writeb(byte2, (char *) (vaddr + head + CMDSTART + 3));
-
-	head = (head + 4) & (CMDMAX - CMDSTART - 4);
-
-	writew(head, &(cm_addr->cm_head));
-
-	/*
-	 * Wait if necessary before updating the head
-	 * pointer to limit the number of outstanding
-	 * commands to the FEP.   If the time spent waiting
-	 * is outlandish, declare the FEP dead.
-	 */
-	for (count = dgap_count ;;) {
-
-		head = readw(&(cm_addr->cm_head));
-		tail = readw(&(cm_addr->cm_tail));
-
-		n = (head - tail) & (CMDMAX - CMDSTART - 4);
-
-		if (n <= ncmds * sizeof(struct cm_t))
-			break;
-
-		if (--count == 0) {
-			DPR_CORE(("%s:%d failing board.\n",__FILE__, __LINE__));
-			ch->ch_bd->state = BOARD_FAILED;
-			return;
-		}
-		udelay(10);
-	}
-}
-
-
-/*=======================================================================
- *
- *      dgap_cmdw - Sends a 1 word command to the FEP.
- *
- *              ch      - Pointer to channel structure.
- *              cmd     - Command to be sent.
- *              word    - Integer containing word to be sent.
- *              ncmds   - Wait until ncmds or fewer cmds are left
- *                        in the cmd buffer before returning.
- *
- *=======================================================================*/
-void dgap_cmdw(struct channel_t *ch, uchar cmd, u16 word, uint ncmds)
-{
-	char		*vaddr = NULL;
-	struct cm_t	*cm_addr = NULL;
-	uint		count;
-	uint		n;
-	u16		head;
-	u16		tail;
-
-	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-		return;
-
-	/*
-	 * Check if board is still alive.
-	 */
-	if (ch->ch_bd->state == BOARD_FAILED) {
-		DPR_CORE(("%s:%d board is failed!\n", __FILE__, __LINE__));
-		return;
-	}
-
-	/*
-	 * Make sure the pointers are in range before
-	 * writing to the FEP memory.
-	 */
-	vaddr = ch->ch_bd->re_map_membase;
-	if (!vaddr)
-		return;
-
-	cm_addr = (struct cm_t *) (vaddr + CMDBUF);
-	head = readw(&(cm_addr->cm_head));
-
-	/*
-	 * Forget it if pointers out of range.
-	 */
-	if (head >= (CMDMAX - CMDSTART) || (head & 03)) {
-		DPR_CORE(("%s:%d Pointers out of range.  Failing board.\n",__FILE__, __LINE__));
-		ch->ch_bd->state = BOARD_FAILED;
-		return;
-	}
-
-	/*
-	 * Put the data in the circular command buffer.
-	 */
-	writeb(cmd, (char *) (vaddr + head + CMDSTART + 0));
-	writeb((uchar) ch->ch_portnum, (char *) (vaddr + head + CMDSTART + 1));
-	writew((u16) word, (char *) (vaddr + head + CMDSTART + 2));
-
-	head = (head + 4) & (CMDMAX - CMDSTART - 4);
-
-	writew(head, &(cm_addr->cm_head));
-
-	/*
-	 * Wait if necessary before updating the head
-	 * pointer to limit the number of outstanding
-	 * commands to the FEP.   If the time spent waiting
-	 * is outlandish, declare the FEP dead.
-	 */
-	for (count = dgap_count ;;) {
-
-		head = readw(&(cm_addr->cm_head));
-		tail = readw(&(cm_addr->cm_tail));
-
-		n = (head - tail) & (CMDMAX - CMDSTART - 4);
-
-		if (n <= ncmds * sizeof(struct cm_t))
-			break;
-
-		if (--count == 0) {
-			DPR_CORE(("%s:%d Failing board.\n",__FILE__, __LINE__));
-			ch->ch_bd->state = BOARD_FAILED;
-			return;
-		}
-		udelay(10);
-	}
-}
-
-
-
-/*=======================================================================
- *
- *      dgap_cmdw_ext - Sends a extended word command to the FEP.
- *
- *              ch      - Pointer to channel structure.
- *              cmd     - Command to be sent.
- *              word    - Integer containing word to be sent.
- *              ncmds   - Wait until ncmds or fewer cmds are left
- *                        in the cmd buffer before returning.
- *
- *=======================================================================*/
-static void dgap_cmdw_ext(struct channel_t *ch, u16 cmd, u16 word, uint ncmds)
-{
-	char		*vaddr = NULL;
-	struct cm_t	*cm_addr = NULL;
-	uint		count;
-	uint		n;
-	u16		head;
-	u16		tail;
-
-	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-		return;
-
-	/*
-	 * Check if board is still alive.
-	 */
-	if (ch->ch_bd->state == BOARD_FAILED) {
-		DPR_CORE(("%s:%d board is failed!\n", __FILE__, __LINE__));
-		return;
-	}
-
-	/*
-	 * Make sure the pointers are in range before
-	 * writing to the FEP memory.
-	 */
-	vaddr = ch->ch_bd->re_map_membase;
-	if (!vaddr)
-		return;
-
-	cm_addr = (struct cm_t *) (vaddr + CMDBUF);
-	head = readw(&(cm_addr->cm_head));
-
-	/*
-	 * Forget it if pointers out of range.
-	 */
-	if (head >= (CMDMAX - CMDSTART) || (head & 03)) {
-		DPR_CORE(("%s:%d Pointers out of range.  Failing board.\n",__FILE__, __LINE__));
-		ch->ch_bd->state = BOARD_FAILED;
-		return;
-	}
-
-	/*
-	 * Put the data in the circular command buffer.
-	 */
-
-	/* Write an FF to tell the FEP that we want an extended command */
-	writeb((uchar) 0xff, (char *) (vaddr + head + CMDSTART + 0));
-
-	writeb((uchar) ch->ch_portnum, (uchar *) (vaddr + head + CMDSTART + 1));
-	writew((u16) cmd, (char *) (vaddr + head + CMDSTART + 2));
-
-	/*
-	 * If the second part of the command won't fit,
-	 * put it at the beginning of the circular buffer.
-	 */
-	if (((head + 4) >= ((CMDMAX - CMDSTART)) || (head & 03))) {
-		writew((u16) word, (char *) (vaddr + CMDSTART));
-	} else {
-		writew((u16) word, (char *) (vaddr + head + CMDSTART + 4));
-	}
-
-	head = (head + 8) & (CMDMAX - CMDSTART - 4);
-
-	writew(head, &(cm_addr->cm_head));
-
-	/*
-	 * Wait if necessary before updating the head
-	 * pointer to limit the number of outstanding
-	 * commands to the FEP.   If the time spent waiting
-	 * is outlandish, declare the FEP dead.
-	 */
-	for (count = dgap_count ;;) {
-
-		head = readw(&(cm_addr->cm_head));
-		tail = readw(&(cm_addr->cm_tail));
-
-		n = (head - tail) & (CMDMAX - CMDSTART - 4);
-
-		if (n <= ncmds * sizeof(struct cm_t))
-			break;
-
-		if (--count == 0) {
-			DPR_CORE(("%s:%d Failing board.\n",__FILE__, __LINE__));
-			ch->ch_bd->state = BOARD_FAILED;
-			return;
-		}
-		udelay(10);
-	}
-}
-
-
-/*=======================================================================
- *
- *      dgap_wmove - Write data to FEP buffer.
- *
- *              ch      - Pointer to channel structure.
- *              buf     - Poiter to characters to be moved.
- *              cnt     - Number of characters to move.
- *
- *=======================================================================*/
-void dgap_wmove(struct channel_t *ch, char *buf, uint cnt)
-{
-	int    n;
-	char   *taddr;
-	struct bs_t    *bs;
-	u16    head;
-
-	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-		return;
-
-	/*
-	 * Check parameters.
-	 */
-	bs   = ch->ch_bs;
-	head = readw(&(bs->tx_head));
-
-	/*
-	 * If pointers are out of range, just return.
-	 */
-	if ((cnt > ch->ch_tsize) || (unsigned)(head - ch->ch_tstart) >= ch->ch_tsize) {
-		DPR_CORE(("%s:%d pointer out of range", __FILE__, __LINE__));
-		return;
-	}
-
-	/*
-	 * If the write wraps over the top of the circular buffer,
-	 * move the portion up to the wrap point, and reset the
-	 * pointers to the bottom.
-	 */
-	n = ch->ch_tstart + ch->ch_tsize - head;
-
-	if (cnt >= n) {
-		cnt -= n;
-		taddr = ch->ch_taddr + head;
-		memcpy_toio(taddr, buf, n);
-		head = ch->ch_tstart;
-		buf += n;
-	}
-
-	/*
-	 * Move rest of data.
-	 */
-	taddr = ch->ch_taddr + head;
-	n = cnt;
-	memcpy_toio(taddr, buf, n);
-	head += cnt;
-
-	writew(head, &(bs->tx_head));
-}
-
-/*
- * Retrives the current custom baud rate from FEP memory,
- * and returns it back to the user.
- * Returns 0 on error.
- */
-uint dgap_get_custom_baud(struct channel_t *ch)
-{
-	uchar *vaddr;
-	ulong offset = 0;
-	uint value = 0;
-
-	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC) {
-		return 0;
-	}
-
-	if (!ch->ch_bd || ch->ch_bd->magic != DGAP_BOARD_MAGIC) {
-		return 0;
-	}
-
-	if (!(ch->ch_bd->bd_flags & BD_FEP5PLUS))
-		return 0;
-
-	vaddr = ch->ch_bd->re_map_membase;
-
-	if (!vaddr)
-		return 0;
-
-	/*
-	 * Go get from fep mem, what the fep
-	 * believes the custom baud rate is.
-	 */
-	offset = ((((*(unsigned short *)(vaddr + ECS_SEG)) << 4) +
-		(ch->ch_portnum * 0x28) + LINE_SPEED));
-
-	value = readw(vaddr + offset);
-	return value;
-}
-
-
-/*
- * Calls the firmware to reset this channel.
- */
-void dgap_firmware_reset_port(struct channel_t *ch)
-{
-	dgap_cmdb(ch, CHRESET, 0, 0, 0);
-
-	/*
-	 * Now that the channel is reset, we need to make sure
-	 * all the current settings get reapplied to the port
-	 * in the firmware.
-	 *
-	 * So we will set the driver's cache of firmware
-	 * settings all to 0, and then call param.
-	 */
-	ch->ch_fepiflag = 0;
-	ch->ch_fepcflag = 0;
-	ch->ch_fepoflag = 0;
-	ch->ch_fepstartc = 0;
-	ch->ch_fepstopc = 0;
-	ch->ch_fepastartc = 0;
-	ch->ch_fepastopc = 0;
-	ch->ch_mostat = 0;
-	ch->ch_hflow = 0;
-}
-
-
-/*=======================================================================
- *
- *      dgap_param - Set Digi parameters.
- *
- *              struct tty_struct *     - TTY for port.
- *
- *=======================================================================*/
-int dgap_param(struct tty_struct *tty)
-{
-	struct ktermios *ts;
-	struct board_t *bd;
-	struct channel_t *ch;
-	struct bs_t   *bs;
-	struct un_t   *un;
-	u16	head;
-	u16	cflag;
-	u16	iflag;
-	uchar	mval;
-	uchar	hflow;
-
-	if (!tty || tty->magic != TTY_MAGIC)
-		return -ENXIO;
-
-	un = (struct un_t *) tty->driver_data;
-	if (!un || un->magic != DGAP_UNIT_MAGIC)
-		return -ENXIO;
-
-	ch = un->un_ch;
-	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-		return -ENXIO;
-
-	bd = ch->ch_bd;
-	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
-		return -ENXIO;
-
-	bs = ch->ch_bs;
-	if (!bs)
-		return -ENXIO;
-
-	DPR_PARAM(("param start: tdev: %x cflags: %x oflags: %x iflags: %x\n",
-		ch->ch_tun.un_dev, ch->ch_c_cflag, ch->ch_c_oflag, ch->ch_c_iflag));
-
-	ts = &tty->termios;
-
-	/*
-	 * If baud rate is zero, flush queues, and set mval to drop DTR.
-	 */
-	if ((ch->ch_c_cflag & (CBAUD)) == 0) {
-
-		/* flush rx */
-		head = readw(&(ch->ch_bs->rx_head));
-		writew(head, &(ch->ch_bs->rx_tail));
-
-		/* flush tx */
-		head = readw(&(ch->ch_bs->tx_head));
-		writew(head, &(ch->ch_bs->tx_tail));
-
-		ch->ch_flags |= (CH_BAUD0);
-
-		/* Drop RTS and DTR */
-		ch->ch_mval &= ~(D_RTS(ch)|D_DTR(ch));
-		mval = D_DTR(ch) | D_RTS(ch);
-		ch->ch_baud_info = 0;
-
-	} else if (ch->ch_custom_speed && (bd->bd_flags & BD_FEP5PLUS)) {
-		/*
-		 * Tell the fep to do the command
-		 */
-
-		DPR_PARAM(("param: Want %d speed\n", ch->ch_custom_speed));
-
-		dgap_cmdw_ext(ch, 0xff01, ch->ch_custom_speed, 0);
-
-		/*
-		 * Now go get from fep mem, what the fep
-		 * believes the custom baud rate is.
-		 */
-		ch->ch_baud_info = ch->ch_custom_speed = dgap_get_custom_baud(ch);
-
-		DPR_PARAM(("param: Got %d speed\n", ch->ch_custom_speed));
-
-		/* Handle transition from B0 */
-		if (ch->ch_flags & CH_BAUD0) {
-			ch->ch_flags &= ~(CH_BAUD0);
-			ch->ch_mval |= (D_RTS(ch)|D_DTR(ch));
-		}
-		mval = D_DTR(ch) | D_RTS(ch);
-
-	} else {
-		/*
-		 * Set baud rate, character size, and parity.
-		 */
-
-
-		int iindex = 0;
-		int jindex = 0;
-		int baud = 0;
-
-		ulong bauds[4][16] = {
-			{ /* slowbaud */
-				0,	50,	75,	110,
-				134,	150,	200,	300,
-				600,	1200,	1800,	2400,
-				4800,	9600,	19200,	38400 },
-			{ /* slowbaud & CBAUDEX */
-				0,	57600,	115200,	230400,
-				460800,	150,	200,	921600,
-				600,	1200,	1800,	2400,
-				4800,	9600,	19200,	38400 },
-			{ /* fastbaud */
-				0,	57600,	76800,	115200,
-				14400,	57600,	230400,	76800,
-				115200,	230400,	28800,	460800,
-				921600,	9600,	19200,	38400 },
-			{ /* fastbaud & CBAUDEX */
-				0,	57600,	115200,	230400,
-				460800,	150,	200,	921600,
-				600,	1200,	1800,	2400,
-				4800,	9600,	19200,	38400 }
-		};
-
-		/* Only use the TXPrint baud rate if the terminal unit is NOT open */
-		if (!(ch->ch_tun.un_flags & UN_ISOPEN) && (un->un_type == DGAP_PRINT))
-			baud = C_BAUD(ch->ch_pun.un_tty) & 0xff;
-		else
-			baud = C_BAUD(ch->ch_tun.un_tty) & 0xff;
-
-		if (ch->ch_c_cflag & CBAUDEX)
-			iindex = 1;
-
-		if (ch->ch_digi.digi_flags & DIGI_FAST)
-			iindex += 2;
-
-		jindex = baud;
-
-		if ((iindex >= 0) && (iindex < 4) && (jindex >= 0) && (jindex < 16)) {
-			baud = bauds[iindex][jindex];
-		} else {
-			DPR_IOCTL(("baud indices were out of range (%d)(%d)",
-				iindex, jindex));
-			baud = 0;
-		}
-
-		if (baud == 0)
-			baud = 9600;
-
-		ch->ch_baud_info = baud;
-
-
-		/*
-		 * CBAUD has bit position 0x1000 set these days to indicate Linux
-		 * baud rate remap.
-		 * We use a different bit assignment for high speed.  Clear this
-		 * bit out while grabbing the parts of "cflag" we want.
-		 */
-		cflag = ch->ch_c_cflag & ((CBAUD ^ CBAUDEX) | PARODD | PARENB | CSTOPB | CSIZE);
-
-		/*
-		 * HUPCL bit is used by FEP to indicate fast baud
-		 * table is to be used.
-		 */
-		if ((ch->ch_digi.digi_flags & DIGI_FAST) || (ch->ch_c_cflag & CBAUDEX))
-			cflag |= HUPCL;
-
-
-		if ((ch->ch_c_cflag & CBAUDEX) && !(ch->ch_digi.digi_flags & DIGI_FAST)) {
-		/*
-		 * The below code is trying to guarantee that only baud rates
-		 * 115200, 230400, 460800, 921600 are remapped.  We use exclusive or
-		 * because the various baud rates share common bit positions
-		 * and therefore can't be tested for easily.
-		 */
-			tcflag_t tcflag = (ch->ch_c_cflag & CBAUD) | CBAUDEX;
-			int baudpart = 0;
-
-			/* Map high speed requests to index into FEP's baud table */
-			switch (tcflag) {
-			case B57600 :
-				baudpart = 1;
-				break;
-#ifdef B76800
-			case B76800 :
-				baudpart = 2;
-				break;
-#endif
-			case B115200 :
-				baudpart = 3;
-				break;
-			case B230400 :
-				baudpart = 9;
-				break;
-			case B460800 :
-				baudpart = 11;
-				break;
-#ifdef B921600
-			case B921600 :
-				baudpart = 12;
-				break;
-#endif
-			default:
-				baudpart = 0;
-			}
-
-			if (baudpart)
-				cflag = (cflag & ~(CBAUD | CBAUDEX)) | baudpart;
-		}
-
-		cflag &= 0xffff;
-
-		if (cflag != ch->ch_fepcflag) {
-			ch->ch_fepcflag = (u16) (cflag & 0xffff);
-
-			/* Okay to have channel and board locks held calling this */
-			dgap_cmdw(ch, SCFLAG, (u16) cflag, 0);
-		}
-
-		/* Handle transition from B0 */
-		if (ch->ch_flags & CH_BAUD0) {
-			ch->ch_flags &= ~(CH_BAUD0);
-			ch->ch_mval |= (D_RTS(ch)|D_DTR(ch));
-		}
-		mval = D_DTR(ch) | D_RTS(ch);
-	}
-
-	/*
-	 * Get input flags.
-	 */
-	iflag = ch->ch_c_iflag & (IGNBRK | BRKINT | IGNPAR | PARMRK | INPCK | ISTRIP | IXON | IXANY | IXOFF);
-
-	if ((ch->ch_startc == _POSIX_VDISABLE) || (ch->ch_stopc == _POSIX_VDISABLE)) {
-		iflag &= ~(IXON | IXOFF);
-		ch->ch_c_iflag &= ~(IXON | IXOFF);
-	}
-
-	/*
-	 * Only the IBM Xr card can switch between
-	 * 232 and 422 modes on the fly
-	 */
-	if (bd->device == PCI_DEVICE_XR_IBM_DID) {
-		if (ch->ch_digi.digi_flags & DIGI_422)
-			dgap_cmdb(ch, SCOMMODE, MODE_422, 0, 0);
-		else
-			dgap_cmdb(ch, SCOMMODE, MODE_232, 0, 0);
-	}
-
-	if (ch->ch_digi.digi_flags & DIGI_ALTPIN)
-		iflag |= IALTPIN ;
-
-	if (iflag != ch->ch_fepiflag) {
-		ch->ch_fepiflag = iflag;
-
-		/* Okay to have channel and board locks held calling this */
-		dgap_cmdw(ch, SIFLAG, (u16) ch->ch_fepiflag, 0);
-	}
-
-	/*
-	 * Select hardware handshaking.
-	 */
-	hflow = 0;
-
-	if (ch->ch_c_cflag & CRTSCTS) {
-		hflow |= (D_RTS(ch) | D_CTS(ch));
-	}
-	if (ch->ch_digi.digi_flags & RTSPACE)
-		hflow |= D_RTS(ch);
-	if (ch->ch_digi.digi_flags & DTRPACE)
-		hflow |= D_DTR(ch);
-	if (ch->ch_digi.digi_flags & CTSPACE)
-		hflow |= D_CTS(ch);
-	if (ch->ch_digi.digi_flags & DSRPACE)
-		hflow |= D_DSR(ch);
-	if (ch->ch_digi.digi_flags & DCDPACE)
-		hflow |= D_CD(ch);
-
-	if (hflow != ch->ch_hflow) {
-		ch->ch_hflow = hflow;
-
-		/* Okay to have channel and board locks held calling this */
-		dgap_cmdb(ch, SHFLOW, (uchar) hflow, 0xff, 0);
-	}
-
-
-	/*
-	 * Set RTS and/or DTR Toggle if needed, but only if product is FEP5+ based.
-	 */
-	if (bd->bd_flags & BD_FEP5PLUS) {
-		u16 hflow2 = 0;
-		if (ch->ch_digi.digi_flags & DIGI_RTS_TOGGLE) {
-			hflow2 |= (D_RTS(ch));
-		}
-		if (ch->ch_digi.digi_flags & DIGI_DTR_TOGGLE) {
-			hflow2 |= (D_DTR(ch));
-		}
-
-		dgap_cmdw_ext(ch, 0xff03, hflow2, 0);
-	}
-
-	/*
-	 * Set modem control lines.
-	 */
-
-	mval ^= ch->ch_mforce & (mval ^ ch->ch_mval);
-
-	DPR_PARAM(("dgap_param: mval: %x ch_mforce: %x ch_mval: %x ch_mostat: %x\n",
-		mval, ch->ch_mforce, ch->ch_mval, ch->ch_mostat));
-
-	if (ch->ch_mostat ^ mval) {
-		ch->ch_mostat = mval;
-
-		/* Okay to have channel and board locks held calling this */
-		DPR_PARAM(("dgap_param: Sending SMODEM mval: %x\n", mval));
-		dgap_cmdb(ch, SMODEM, (uchar) mval, D_RTS(ch)|D_DTR(ch), 0);
-	}
-
-	/*
-	 * Read modem signals, and then call carrier function.
-	 */
-	ch->ch_mistat = readb(&(bs->m_stat));
-	dgap_carrier(ch);
-
-	/*
-	 * Set the start and stop characters.
-	 */
-	if (ch->ch_startc != ch->ch_fepstartc || ch->ch_stopc != ch->ch_fepstopc) {
-		ch->ch_fepstartc = ch->ch_startc;
-		ch->ch_fepstopc =  ch->ch_stopc;
-
-		/* Okay to have channel and board locks held calling this */
-		dgap_cmdb(ch, SFLOWC, ch->ch_fepstartc, ch->ch_fepstopc, 0);
-	}
-
-	/*
-	 * Set the Auxiliary start and stop characters.
-	 */
-	if (ch->ch_astartc != ch->ch_fepastartc || ch->ch_astopc != ch->ch_fepastopc) {
-		ch->ch_fepastartc = ch->ch_astartc;
-		ch->ch_fepastopc = ch->ch_astopc;
-
-		/* Okay to have channel and board locks held calling this */
-		dgap_cmdb(ch, SAFLOWC, ch->ch_fepastartc, ch->ch_fepastopc, 0);
-	}
-
-	DPR_PARAM(("param finish\n"));
-
-	return 0;
-}
-
-
-/*
- * dgap_parity_scan()
- *
- * Convert the FEP5 way of reporting parity errors and breaks into
- * the Linux line discipline way.
- */
-void dgap_parity_scan(struct channel_t *ch, unsigned char *cbuf, unsigned char *fbuf, int *len)
-{
-	int l = *len;
-	int count = 0;
-	unsigned char *in, *cout, *fout;
-	unsigned char c;
-
-	in = cbuf;
-	cout = cbuf;
-	fout = fbuf;
-
-	DPR_PSCAN(("dgap_parity_scan start\n"));
-
-	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-		return;
-
-	while (l--) {
-		c = *in++;
-		switch (ch->pscan_state) {
-		default:
-			/* reset to sanity and fall through */
-			ch->pscan_state = 0;
-
-		case 0:
-			/* No FF seen yet */
-			if (c == (unsigned char) '\377') {
-				/* delete this character from stream */
-				ch->pscan_state = 1;
-			} else {
-				*cout++ = c;
-				*fout++ = TTY_NORMAL;
-				count += 1;
-			}
-			break;
-
-		case 1:
-			/* first FF seen */
-			if (c == (unsigned char) '\377') {
-				/* doubled ff, transform to single ff */
-				*cout++ = c;
-				*fout++ = TTY_NORMAL;
-				count += 1;
-				ch->pscan_state = 0;
-			} else {
-				/* save value examination in next state */
-				ch->pscan_savechar = c;
-				ch->pscan_state = 2;
-			}
-			break;
-
-		case 2:
-			/* third character of ff sequence */
-
-			*cout++ = c;
-
-			if (ch->pscan_savechar == 0x0) {
-
-				if (c == 0x0) {
-					DPR_PSCAN(("dgap_parity_scan in 3rd char of ff seq. c: %x setting break.\n", c));
-					ch->ch_err_break++;
-					*fout++ = TTY_BREAK;
-				}
-				else {
-					DPR_PSCAN(("dgap_parity_scan in 3rd char of ff seq. c: %x setting parity.\n", c));
-					ch->ch_err_parity++;
-					*fout++ = TTY_PARITY;
-				}
-			}
-			else {
-				DPR_PSCAN(("%s:%d Logic Error.\n", __FILE__, __LINE__));
-			}
-
-			count += 1;
-			ch->pscan_state = 0;
-		}
-	}
-	*len = count;
-	DPR_PSCAN(("dgap_parity_scan finish\n"));
-}
-
-
-
-
-/*=======================================================================
- *
- *      dgap_event - FEP to host event processing routine.
- *
- *              bd     - Board of current event.
- *
- *=======================================================================*/
-static int dgap_event(struct board_t *bd)
-{
-	struct channel_t *ch;
-	ulong		lock_flags;
-	ulong		lock_flags2;
-	struct bs_t	*bs;
-	uchar		*event;
-	uchar		*vaddr = NULL;
-	struct ev_t	*eaddr = NULL;
-	uint		head;
-	uint		tail;
-	int		port;
-	int		reason;
-	int		modem;
-	int		b1;
-
-	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
-		return -ENXIO;
-
-	DGAP_LOCK(bd->bd_lock, lock_flags);
-
-	vaddr = bd->re_map_membase;
-
-	if (!vaddr) {
-		DGAP_UNLOCK(bd->bd_lock, lock_flags);
-		return -ENXIO;
-	}
-
-	eaddr = (struct ev_t *) (vaddr + EVBUF);
-
-	/* Get our head and tail */
-	head = readw(&(eaddr->ev_head));
-	tail = readw(&(eaddr->ev_tail));
-
-	/*
-	 * Forget it if pointers out of range.
-	 */
-
-	if (head >= EVMAX - EVSTART || tail >= EVMAX - EVSTART ||
-	    (head | tail) & 03) {
-		DPR_EVENT(("should be calling xxfail %d\n", __LINE__));
-		/* Let go of board lock */
-		DGAP_UNLOCK(bd->bd_lock, lock_flags);
-		return -ENXIO;
-	}
-
-	/*
-	 * Loop to process all the events in the buffer.
-	 */
-	while (tail != head) {
-
-		/*
-		 * Get interrupt information.
-		 */
-
-		event = bd->re_map_membase + tail + EVSTART;
-
-		port   = event[0];
-		reason = event[1];
-		modem  = event[2];
-		b1     = event[3];
-
-		DPR_EVENT(("event: jiffies: %ld port: %d reason: %x modem: %x\n",
-			jiffies, port, reason, modem));
-
-		/*
-		 * Make sure the interrupt is valid.
-		 */
-		if (port >= bd->nasync)
-			goto next;
-
-		if (!(reason & (IFMODEM | IFBREAK | IFTLW | IFTEM | IFDATA))) {
-			goto next;
-		}
-
-		ch = bd->channels[port];
-
-		if (!ch || ch->magic != DGAP_CHANNEL_MAGIC) {
-			goto next;
-		}
-
-		/*
-		 * If we have made it here, the event was valid.
-		 * Lock down the channel.
-		 */
-		DGAP_LOCK(ch->ch_lock, lock_flags2);
-
-		bs = ch->ch_bs;
-
-		if (!bs) {
-			DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-			goto next;
-		}
-
-		/*
-		 * Process received data.
-		 */
-		if (reason & IFDATA) {
-
-			/*
-			 * ALL LOCKS *MUST* BE DROPPED BEFORE CALLING INPUT!
-			 * input could send some data to ld, which in turn
-			 * could do a callback to one of our other functions.
-			 */
-			DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-			DGAP_UNLOCK(bd->bd_lock, lock_flags);
-
-			dgap_input(ch);
-
-			DGAP_LOCK(bd->bd_lock, lock_flags);
-			DGAP_LOCK(ch->ch_lock, lock_flags2);
-
-			if (ch->ch_flags & CH_RACTIVE)
-				ch->ch_flags |= CH_RENABLE;
-			else
-				writeb(1, &(bs->idata));
-
-			if (ch->ch_flags & CH_RWAIT) {
-				ch->ch_flags &= ~CH_RWAIT;
-
-				wake_up_interruptible(&ch->ch_tun.un_flags_wait);
-			}
-		}
-
-		/*
-		 * Process Modem change signals.
-		 */
-		if (reason & IFMODEM) {
-			ch->ch_mistat = modem;
-			dgap_carrier(ch);
-		}
-
-		/*
-		 * Process break.
-		 */
-		if (reason & IFBREAK) {
-
-			DPR_EVENT(("got IFBREAK\n"));
-
-			if (ch->ch_tun.un_tty) {
-				/* A break has been indicated */
-				ch->ch_err_break++;
-				tty_buffer_request_room(ch->ch_tun.un_tty->port, 1);
-				tty_insert_flip_char(ch->ch_tun.un_tty->port, 0, TTY_BREAK);
-				tty_flip_buffer_push(ch->ch_tun.un_tty->port);
-			}
-		}
-
-		/*
-		 * Process Transmit low.
-		 */
-		if (reason & IFTLW) {
-
-			DPR_EVENT(("event: got low event\n"));
-
-			if (ch->ch_tun.un_flags & UN_LOW) {
-				ch->ch_tun.un_flags &= ~UN_LOW;
-
-				if (ch->ch_tun.un_flags & UN_ISOPEN) {
-					if ((ch->ch_tun.un_tty->flags &
-					   (1 << TTY_DO_WRITE_WAKEUP)) &&
-						ch->ch_tun.un_tty->ldisc->ops->write_wakeup)
-					{
-						DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-						DGAP_UNLOCK(bd->bd_lock, lock_flags);
-						(ch->ch_tun.un_tty->ldisc->ops->write_wakeup)(ch->ch_tun.un_tty);
-						DGAP_LOCK(bd->bd_lock, lock_flags);
-						DGAP_LOCK(ch->ch_lock, lock_flags2);
-					}
-					wake_up_interruptible(&ch->ch_tun.un_tty->write_wait);
-					wake_up_interruptible(&ch->ch_tun.un_flags_wait);
-
-					DPR_EVENT(("event: Got low event. jiffies: %lu\n", jiffies));
-				}
-			}
-
-			if (ch->ch_pun.un_flags & UN_LOW) {
-				ch->ch_pun.un_flags &= ~UN_LOW;
-				if (ch->ch_pun.un_flags & UN_ISOPEN) {
-					if ((ch->ch_pun.un_tty->flags &
-					   (1 << TTY_DO_WRITE_WAKEUP)) &&
-						ch->ch_pun.un_tty->ldisc->ops->write_wakeup)
-					{
-						DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-						DGAP_UNLOCK(bd->bd_lock, lock_flags);
-						(ch->ch_pun.un_tty->ldisc->ops->write_wakeup)(ch->ch_pun.un_tty);
-						DGAP_LOCK(bd->bd_lock, lock_flags);
-						DGAP_LOCK(ch->ch_lock, lock_flags2);
-					}
-					wake_up_interruptible(&ch->ch_pun.un_tty->write_wait);
-					wake_up_interruptible(&ch->ch_pun.un_flags_wait);
-				}
-			}
-
-			if (ch->ch_flags & CH_WLOW) {
-				ch->ch_flags &= ~CH_WLOW;
-				wake_up_interruptible(&ch->ch_flags_wait);
-			}
-		}
-
-		/*
-		 * Process Transmit empty.
-		 */
-		if (reason & IFTEM) {
-			DPR_EVENT(("event: got empty event\n"));
-
-			if (ch->ch_tun.un_flags & UN_EMPTY) {
-				ch->ch_tun.un_flags &= ~UN_EMPTY;
-				if (ch->ch_tun.un_flags & UN_ISOPEN) {
-					if ((ch->ch_tun.un_tty->flags &
-					   (1 << TTY_DO_WRITE_WAKEUP)) &&
-						ch->ch_tun.un_tty->ldisc->ops->write_wakeup)
-					{
-						DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-						DGAP_UNLOCK(bd->bd_lock, lock_flags);
-
-						(ch->ch_tun.un_tty->ldisc->ops->write_wakeup)(ch->ch_tun.un_tty);
-						DGAP_LOCK(bd->bd_lock, lock_flags);
-						DGAP_LOCK(ch->ch_lock, lock_flags2);
-					}
-					wake_up_interruptible(&ch->ch_tun.un_tty->write_wait);
-					wake_up_interruptible(&ch->ch_tun.un_flags_wait);
-				}
-			}
-
-			if (ch->ch_pun.un_flags & UN_EMPTY) {
-				ch->ch_pun.un_flags &= ~UN_EMPTY;
-				if (ch->ch_pun.un_flags & UN_ISOPEN) {
-					if ((ch->ch_pun.un_tty->flags &
-					   (1 << TTY_DO_WRITE_WAKEUP)) &&
-						ch->ch_pun.un_tty->ldisc->ops->write_wakeup)
-					{
-						DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-						DGAP_UNLOCK(bd->bd_lock, lock_flags);
-						(ch->ch_pun.un_tty->ldisc->ops->write_wakeup)(ch->ch_pun.un_tty);
-						DGAP_LOCK(bd->bd_lock, lock_flags);
-						DGAP_LOCK(ch->ch_lock, lock_flags2);
-					}
-					wake_up_interruptible(&ch->ch_pun.un_tty->write_wait);
-					wake_up_interruptible(&ch->ch_pun.un_flags_wait);
-				}
-			}
-
-
-			if (ch->ch_flags & CH_WEMPTY) {
-				ch->ch_flags &= ~CH_WEMPTY;
-				wake_up_interruptible(&ch->ch_flags_wait);
-			}
-		}
-
-		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-
-next:
-		tail = (tail + 4) & (EVMAX - EVSTART - 4);
-	}
-
-	writew(tail, &(eaddr->ev_tail));
-	DGAP_UNLOCK(bd->bd_lock, lock_flags);
-
-	return 0;
-}
diff --git a/drivers/staging/dgap/dgap_fep5.h b/drivers/staging/dgap/dgap_fep5.h
deleted file mode 100644
index d0650ae..0000000
--- a/drivers/staging/dgap/dgap_fep5.h
+++ /dev/null
@@ -1,253 +0,0 @@
-/*
- * Copyright 2003 Digi International (www.digi.com)
- *	Scott H Kilau <Scott_Kilau at digi dot com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
- * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- * PURPOSE.  See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- *	NOTE: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!!
- *
- ************************************************************************
- ***	FEP Version 5 dependent definitions
- ************************************************************************/
-
-#ifndef __DGAP_FEP5_H
-#define __DGAP_FEP5_H
-
-/************************************************************************
- *      FEP memory offsets
- ************************************************************************/
-#define START           0x0004L         /* Execution start address      */
-
-#define CMDBUF          0x0d10L         /* Command (cm_t) structure offset */
-#define CMDSTART        0x0400L         /* Start of command buffer      */
-#define CMDMAX          0x0800L         /* End of command buffer        */
-
-#define EVBUF           0x0d18L         /* Event (ev_t) structure       */
-#define EVSTART         0x0800L         /* Start of event buffer        */
-#define EVMAX           0x0c00L         /* End of event buffer          */
-#define FEP5_PLUS       0x0E40          /* ASCII '5' and ASCII 'A' is here  */
-#define ECS_SEG         0x0E44          /* Segment of the extended channel structure */
-#define LINE_SPEED      0x10            /* Offset into ECS_SEG for line speed   */
-                                        /* if the fep has extended capabilities */
-
-/* BIOS MAGIC SPOTS */
-#define ERROR           0x0C14L		/* BIOS error code              */
-#define SEQUENCE	0x0C12L		/* BIOS sequence indicator      */
-#define POSTAREA	0x0C00L		/* POST complete message area   */
-
-/* FEP MAGIC SPOTS */
-#define FEPSTAT         POSTAREA        /* OS here when FEP comes up    */
-#define NCHAN           0x0C02L         /* number of ports FEP sees     */
-#define PANIC           0x0C10L         /* PANIC area for FEP           */
-#define KMEMEM          0x0C30L         /* Memory for KME use           */
-#define CONFIG          0x0CD0L         /* Concentrator configuration info */
-#define CONFIGSIZE      0x0030          /* configuration info size      */
-#define DOWNREQ         0x0D00          /* Download request buffer pointer */
-
-#define CHANBUF         0x1000L         /* Async channel (bs_t) structs */
-#define FEPOSSIZE       0x1FFF          /* 8K FEPOS                     */
-
-#define XEMPORTS    0xC02	/*
-				 * Offset in board memory where FEP5 stores
-				 * how many ports it has detected.
-				 * NOTE: FEP5 reports 64 ports when the user
-				 * has the cable in EBI OUT instead of EBI IN.
-				 */
-
-#define FEPCLR      0x00
-#define FEPMEM      0x02
-#define FEPRST      0x04
-#define FEPINT      0x08
-#define FEPMASK     0x0e
-#define FEPWIN      0x80
-
-#define LOWMEM      0x0100
-#define HIGHMEM     0x7f00
-
-#define FEPTIMEOUT 200000
-
-#define ENABLE_INTR		0x0e04		/* Enable interrupts flag */
-#define FEPPOLL_MIN		1		/* minimum of 1 millisecond */
-#define FEPPOLL_MAX		20		/* maximum of 20 milliseconds */
-#define FEPPOLL			0x0c26		/* Fep event poll interval */
-
-#define	IALTPIN			0x0080		/* Input flag to swap DSR <-> DCD */
-
-/************************************************************************
- * Command structure definition.
- ************************************************************************/
-struct cm_t {
-	volatile unsigned short cm_head;	/* Command buffer head offset	*/
-	volatile unsigned short cm_tail;	/* Command buffer tail offset	*/
-	volatile unsigned short cm_start;	/* start offset of buffer	*/
-	volatile unsigned short cm_max;		/* last offset of buffer	*/
-};
-
-/************************************************************************
- * Event structure definition.
- ************************************************************************/
-struct ev_t {
-	volatile unsigned short ev_head;	/* Command buffer head offset	*/
-	volatile unsigned short ev_tail;	/* Command buffer tail offset	*/
-	volatile unsigned short ev_start;	/* start offset of buffer	*/
-	volatile unsigned short ev_max;		/* last offset of buffer	*/
-};
-
-/************************************************************************
- * Download buffer structure.
- ************************************************************************/
-struct downld_t {
-	uchar	dl_type;		/* Header                       */
-	uchar	dl_seq;			/* Download sequence            */
-	ushort	dl_srev;		/* Software revision number     */
-	ushort	dl_lrev;		/* Low revision number          */
-	ushort	dl_hrev;		/* High revision number         */
-	ushort	dl_seg;			/* Start segment address        */
-	ushort	dl_size;		/* Number of bytes to download  */
-	uchar	dl_data[1024];		/* Download data                */
-};
-
-/************************************************************************
- * Per channel buffer structure
- ************************************************************************
- *              Base Structure Entries Usage Meanings to Host           *
- *                                                                      *
- *        W = read write        R = read only                           *
- *        C = changed by commands only                                  *
- *        U = unknown (may be changed w/o notice)                       *
- ************************************************************************/
-struct bs_t {
-	volatile unsigned short  tp_jmp;	/* Transmit poll jump		 */
-	volatile unsigned short  tc_jmp;	/* Cooked procedure jump	 */
-	volatile unsigned short  ri_jmp;	/* Not currently used		 */
-	volatile unsigned short  rp_jmp;	/* Receive poll jump		 */
-
-	volatile unsigned short  tx_seg;	/* W  Tx segment	 */
-	volatile unsigned short  tx_head;	/* W  Tx buffer head offset	*/
-	volatile unsigned short  tx_tail;	/* R  Tx buffer tail offset	*/
-	volatile unsigned short  tx_max;	/* W  Tx buffer size - 1	 */
-
-	volatile unsigned short  rx_seg;	/* W  Rx segment		*/
-	volatile unsigned short  rx_head;	/* W  Rx buffer head offset	*/
-	volatile unsigned short  rx_tail;	/* R  Rx buffer tail offset	*/
-	volatile unsigned short  rx_max;	/* W  Rx buffer size - 1	 */
-
-	volatile unsigned short  tx_lw;		/* W  Tx buffer low water mark  */
-	volatile unsigned short  rx_lw;		/* W  Rx buffer low water mark  */
-	volatile unsigned short  rx_hw;		/* W  Rx buffer high water mark */
-	volatile unsigned short  incr;		/* W  Increment to next channel */
-
-	volatile unsigned short  fepdev;	/* U  SCC device base address    */
-	volatile unsigned short  edelay;	/* W  Exception delay            */
-	volatile unsigned short  blen;		/* W  Break length              */
-	volatile unsigned short  btime;		/* U  Break complete time       */
-
-	volatile unsigned short  iflag;		/* C  UNIX input flags          */
-	volatile unsigned short  oflag;		/* C  UNIX output flags         */
-	volatile unsigned short  cflag;		/* C  UNIX control flags        */
-	volatile unsigned short  wfill[13];	/* U  Reserved for expansion    */
-
-	volatile unsigned char   num;		/* U  Channel number            */
-	volatile unsigned char   ract;		/* U  Receiver active counter   */
-	volatile unsigned char   bstat;		/* U  Break status bits         */
-	volatile unsigned char   tbusy;		/* W  Transmit busy             */
-	volatile unsigned char   iempty;	/* W  Transmit empty event enable */
-	volatile unsigned char   ilow;		/* W  Transmit low-water event enable */
-	volatile unsigned char   idata;		/* W  Receive data interrupt enable */
-	volatile unsigned char   eflag;		/* U  Host event flags          */
-
-	volatile unsigned char   tflag;		/* U  Transmit flags            */
-	volatile unsigned char   rflag;		/* U  Receive flags             */
-	volatile unsigned char   xmask;		/* U  Transmit ready flags      */
-	volatile unsigned char   xval;		/* U  Transmit ready value      */
-	volatile unsigned char   m_stat;	/* RC Modem status bits          */
-	volatile unsigned char   m_change;	/* U  Modem bits which changed  */
-	volatile unsigned char   m_int;		/* W  Modem interrupt enable bits */
-	volatile unsigned char   m_last;	/* U  Last modem status         */
-
-	volatile unsigned char   mtran;		/* C   Unreported modem trans   */
-	volatile unsigned char   orun;		/* C   Buffer overrun occurred  */
-	volatile unsigned char   astartc;	/* W   Auxiliary Xon char       */
-	volatile unsigned char   astopc;	/* W   Auxiliary Xoff char      */
-	volatile unsigned char   startc;	/* W   Xon character             */
-	volatile unsigned char   stopc;		/* W   Xoff character           */
-	volatile unsigned char   vnextc;	/* W   Vnext character           */
-	volatile unsigned char   hflow;		/* C   Software flow control    */
-
-	volatile unsigned char   fillc;		/* U   Delay Fill character     */
-	volatile unsigned char   ochar;		/* U   Saved output character   */
-	volatile unsigned char   omask;		/* U   Output character mask    */
-
-	volatile unsigned char   bfill[13];	/* U   Reserved for expansion   */
-
-	volatile unsigned char   scc[16];	/* U   SCC registers            */
-};
-
-
-/************************************************************************
- * FEP supported functions
- ************************************************************************/
-#define SRLOW		0xe0		/* Set receive low water	*/
-#define SRHIGH		0xe1		/* Set receive high water	*/
-#define FLUSHTX		0xe2		/* Flush transmit buffer	*/
-#define PAUSETX		0xe3		/* Pause data transmission	*/
-#define RESUMETX	0xe4		/* Resume data transmission	*/
-#define SMINT		0xe5		/* Set Modem Interrupt		*/
-#define SAFLOWC		0xe6		/* Set Aux. flow control chars	*/
-#define SBREAK		0xe8		/* Send break			*/
-#define SMODEM		0xe9		/* Set 8530 modem control lines	*/
-#define SIFLAG		0xea		/* Set UNIX iflags		*/
-#define SFLOWC		0xeb		/* Set flow control characters	*/
-#define STLOW		0xec		/* Set transmit low water mark	*/
-#define RPAUSE		0xee		/* Pause receive		*/
-#define RRESUME		0xef		/* Resume receive		*/
-#define CHRESET		0xf0		/* Reset Channel		*/
-#define BUFSETALL	0xf2		/* Set Tx & Rx buffer size avail*/
-#define SOFLAG		0xf3		/* Set UNIX oflags		*/
-#define SHFLOW		0xf4		/* Set hardware handshake	*/
-#define SCFLAG		0xf5		/* Set UNIX cflags		*/
-#define SVNEXT		0xf6		/* Set VNEXT character		*/
-#define SPINTFC		0xfc		/* Reserved			*/
-#define SCOMMODE	0xfd		/* Set RS232/422 mode		*/
-
-
-/************************************************************************
- *	Modes for SCOMMODE
- ************************************************************************/
-#define MODE_232	0x00
-#define MODE_422	0x01
-
-
-/************************************************************************
- *      Event flags.
- ************************************************************************/
-#define IFBREAK         0x01            /* Break received               */
-#define IFTLW           0x02            /* Transmit low water           */
-#define IFTEM           0x04            /* Transmitter empty            */
-#define IFDATA          0x08            /* Receive data present         */
-#define IFMODEM         0x20            /* Modem status change          */
-
-/************************************************************************
- *      Modem flags
- ************************************************************************/
-#       define  DM_RTS          0x02    /* Request to send              */
-#       define  DM_CD           0x80    /* Carrier detect               */
-#       define  DM_DSR          0x20    /* Data set ready               */
-#       define  DM_CTS          0x10    /* Clear to send                */
-#       define  DM_RI           0x40    /* Ring indicator               */
-#       define  DM_DTR          0x01    /* Data terminal ready          */
-
-
-#endif
diff --git a/drivers/staging/dgap/dgap_kcompat.h b/drivers/staging/dgap/dgap_kcompat.h
deleted file mode 100644
index 0dc2404..0000000
--- a/drivers/staging/dgap/dgap_kcompat.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright 2004 Digi International (www.digi.com)
- *      Scott H Kilau <Scott_Kilau at digi dot com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
- * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- * PURPOSE.  See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- *	NOTE: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!!
- *
- *************************************************************************
- *
- * This file is intended to contain all the kernel "differences" between the
- * various kernels that we support.
- *
- *************************************************************************/
-
-#ifndef __DGAP_KCOMPAT_H
-#define __DGAP_KCOMPAT_H
-
-#if !defined(TTY_FLIPBUF_SIZE)
-# define TTY_FLIPBUF_SIZE 512
-#endif
-
-
-/* Sparse stuff */
-# ifndef __user
-#  define __user
-#  define __kernel
-#  define __safe
-#  define __force
-#  define __chk_user_ptr(x) (void)0
-# endif
-
-
-#  define PARM_STR(VAR, INIT, PERM, DESC) \
-		static char *VAR = INIT; \
-		char *dgap_##VAR; \
-		module_param(VAR, charp, PERM); \
-		MODULE_PARM_DESC(VAR, DESC);
-
-#  define PARM_INT(VAR, INIT, PERM, DESC) \
-		static int VAR = INIT; \
-		int dgap_##VAR; \
-		module_param(VAR, int, PERM); \
-		MODULE_PARM_DESC(VAR, DESC);
-
-#  define PARM_ULONG(VAR, INIT, PERM, DESC) \
-		static ulong VAR = INIT; \
-		ulong dgap_##VAR; \
-		module_param(VAR, long, PERM); \
-		MODULE_PARM_DESC(VAR, DESC);
-
-#endif /* ! __DGAP_KCOMPAT_H */
diff --git a/drivers/staging/dgap/dgap_parse.c b/drivers/staging/dgap/dgap_parse.c
deleted file mode 100644
index 7bc5bc3..0000000
--- a/drivers/staging/dgap/dgap_parse.c
+++ /dev/null
@@ -1,1374 +0,0 @@
-/*
- * Copyright 2003 Digi International (www.digi.com)
- *	Scott H Kilau <Scott_Kilau at digi dot com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
- * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- * PURPOSE.  See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- *
- *	NOTE TO LINUX KERNEL HACKERS:  DO NOT REFORMAT THIS CODE!
- *
- *	This is shared code between Digi's CVS archive and the
- *	Linux Kernel sources.
- *	Changing the source just for reformatting needlessly breaks
- *	our CVS diff history.
- *
- *	Send any bug fixes/changes to:  Eng.Linux at digi dot com.
- *	Thank you.
- *
- *
- *****************************************************************************
- *
- * dgap_parse.c - Parses the configuration information from the input file.
- *
- * $Id: dgap_parse.c,v 1.1 2009/10/23 14:01:57 markh Exp $
- *
- */
-#include <linux/kernel.h>
-#include <linux/ctype.h>
-#include <linux/slab.h>
-
-#include "dgap_types.h"
-#include "dgap_fep5.h"
-#include "dgap_driver.h"
-#include "dgap_parse.h"
-#include "dgap_conf.h"
-
-
-/*
- * Function prototypes.
- */
-static int dgap_gettok(char **in, struct cnode *p);
-static char *dgap_getword(char **in);
-static char *dgap_savestring(char *s);
-static struct cnode *dgap_newnode(int t);
-static int dgap_checknode(struct cnode *p);
-static void dgap_err(char *s);
-
-/*
- * Our needed internal static variables...
- */
-static struct cnode dgap_head;
-#define MAXCWORD 200
-static char dgap_cword[MAXCWORD];
-
-struct toklist {
-	int	token;
-	char	*string;
-};
-
-static struct toklist dgap_tlist[] = {
-	{	BEGIN,		"config_begin"			},
-	{	END,		"config_end"			},
-	{	BOARD,		"board"				},
-	{	PCX,		"Digi_AccelePort_C/X_PCI"	},	/* C/X_PCI */
-	{	PEPC,		"Digi_AccelePort_EPC/X_PCI"	},	/* EPC/X_PCI */
-	{	PPCM,		"Digi_AccelePort_Xem_PCI"	},	/* PCI/Xem */
-	{	APORT2_920P,	"Digi_AccelePort_2r_920_PCI"	},
-	{	APORT4_920P,	"Digi_AccelePort_4r_920_PCI"	},
-	{	APORT8_920P,	"Digi_AccelePort_8r_920_PCI"	},
-	{	PAPORT4,	"Digi_AccelePort_4r_PCI(EIA-232/RS-422)" },
-	{	PAPORT8,	"Digi_AccelePort_8r_PCI(EIA-232/RS-422)" },
-	{	IO,		"io"				},
-	{	PCIINFO,	"pciinfo"			},
-	{	LINE,		"line"				},
-	{	CONC,		"conc"				},
-	{	CONC,		"concentrator"			},
-	{	CX,		"cx"				},
-	{	CX,		"ccon"				},
-	{	EPC,		"epccon"			},
-	{	EPC,		"epc"				},
-	{	MOD,		"module"			},
-	{	ID,		"id"				},
-	{	STARTO,		"start"				},
-	{	SPEED,		"speed"				},
-	{	CABLE,		"cable"				},
-	{	CONNECT,	"connect"			},
-	{	METHOD,		"method"			},
-	{	STATUS,		"status"			},
-	{	CUSTOM,		"Custom"			},
-	{	BASIC,		"Basic"				},
-	{	MEM,		"mem"				},
-	{	MEM,		"memory"			},
-	{	PORTS,		"ports"				},
-	{	MODEM,		"modem"				},
-	{	NPORTS,		"nports"			},
-	{	TTYN,		"ttyname"			},
-	{	CU,		"cuname"			},
-	{	PRINT,		"prname"			},
-	{	CMAJOR,		"major"				},
-	{	ALTPIN,		"altpin"			},
-	{	USEINTR,	"useintr"			},
-	{	TTSIZ,		"ttysize"			},
-	{	CHSIZ,		"chsize"			},
-	{	BSSIZ,		"boardsize"			},
-	{	UNTSIZ,		"schedsize"			},
-	{	F2SIZ,		"f2200size"			},
-	{	VPSIZ,		"vpixsize"			},
-	{	0,		NULL				}
-};
-
-
-/*
- * Parse a configuration file read into memory as a string.
- */
-int	dgap_parsefile(char **in, int Remove)
-{
-	struct cnode *p, *brd, *line, *conc;
-	int	rc;
-	char	*s = NULL, *s2 = NULL;
-	int	linecnt = 0;
-
-	p = &dgap_head;
-	brd = line = conc = NULL;
-
-	/* perhaps we are adding to an existing list? */
-	while (p->next != NULL) {
-		p = p->next;
-	}
-
-	/* file must start with a BEGIN */
-	while ( (rc = dgap_gettok(in,p)) != BEGIN ) {
-		if (rc == 0) {
-			dgap_err("unexpected EOF");
-			return(-1);
-		}
-	}
-
-	for (; ; ) {
-		rc = dgap_gettok(in,p);
-		if (rc == 0) {
-			dgap_err("unexpected EOF");
-			return(-1);
-		}
-
-		switch (rc) {
-		case 0:
-			dgap_err("unexpected end of file");
-			return(-1);
-
-		case BEGIN:	/* should only be 1 begin */
-			dgap_err("unexpected config_begin\n");
-			return(-1);
-
-		case END:
-			return(0);
-
-		case BOARD:	/* board info */
-			if (dgap_checknode(p))
-				return(-1);
-			if ( (p->next = dgap_newnode(BNODE)) == NULL ) {
-				dgap_err("out of memory");
-				return(-1);
-			}
-			p = p->next;
-
-			p->u.board.status = dgap_savestring("No");
-			line = conc = NULL;
-			brd = p;
-			linecnt = -1;
-			break;
-
-		case APORT2_920P:	/* AccelePort_4 */
-			if (p->type != BNODE) {
-				dgap_err("unexpected Digi_2r_920 string");
-				return(-1);
-			}
-			p->u.board.type = APORT2_920P;
-			p->u.board.v_type = 1;
-			DPR_INIT(("Adding Digi_2r_920 PCI to config...\n"));
-			break;
-
-		case APORT4_920P:	/* AccelePort_4 */
-			if (p->type != BNODE) {
-				dgap_err("unexpected Digi_4r_920 string");
-				return(-1);
-			}
-			p->u.board.type = APORT4_920P;
-			p->u.board.v_type = 1;
-			DPR_INIT(("Adding Digi_4r_920 PCI to config...\n"));
-			break;
-
-		case APORT8_920P:	/* AccelePort_8 */
-			if (p->type != BNODE) {
-				dgap_err("unexpected Digi_8r_920 string");
-				return(-1);
-			}
-			p->u.board.type = APORT8_920P;
-			p->u.board.v_type = 1;
-			DPR_INIT(("Adding Digi_8r_920 PCI to config...\n"));
-			break;
-
-		case PAPORT4:	/* AccelePort_4 PCI */
-			if (p->type != BNODE) {
-				dgap_err("unexpected Digi_4r(PCI) string");
-				return(-1);
-			}
-			p->u.board.type = PAPORT4;
-			p->u.board.v_type = 1;
-			DPR_INIT(("Adding Digi_4r PCI to config...\n"));
-			break;
-
-		case PAPORT8:	/* AccelePort_8 PCI */
-			if (p->type != BNODE) {
-				dgap_err("unexpected Digi_8r string");
-				return(-1);
-			}
-			p->u.board.type = PAPORT8;
-			p->u.board.v_type = 1;
-			DPR_INIT(("Adding Digi_8r PCI to config...\n"));
-			break;
-
-		case PCX:	/* PCI C/X */
-			if (p->type != BNODE) {
-				dgap_err("unexpected Digi_C/X_(PCI) string");
-				return(-1);
-			}
-			p->u.board.type = PCX;
-			p->u.board.v_type = 1;
-			p->u.board.conc1 = 0;
-			p->u.board.conc2 = 0;
-			p->u.board.module1 = 0;
-			p->u.board.module2 = 0;
-			DPR_INIT(("Adding PCI C/X to config...\n"));
-			break;
-
-		case PEPC:	/* PCI EPC/X */
-			if (p->type != BNODE) {
-				dgap_err("unexpected \"Digi_EPC/X_(PCI)\" string");
-				return(-1);
-			}
-			p->u.board.type = PEPC;
-			p->u.board.v_type = 1;
-			p->u.board.conc1 = 0;
-			p->u.board.conc2 = 0;
-			p->u.board.module1 = 0;
-			p->u.board.module2 = 0;
-			DPR_INIT(("Adding PCI EPC/X to config...\n"));
-			break;
-
-		case PPCM:	/* PCI/Xem */
-			if (p->type != BNODE) {
-				dgap_err("unexpected PCI/Xem string");
-				return(-1);
-			}
-			p->u.board.type = PPCM;
-			p->u.board.v_type = 1;
-			p->u.board.conc1 = 0;
-			p->u.board.conc2 = 0;
-			DPR_INIT(("Adding PCI XEM to config...\n"));
-			break;
-
-		case IO:	/* i/o port */
-			if (p->type != BNODE) {
-				dgap_err("IO port only vaild for boards");
-				return(-1);
-			}
-			s = dgap_getword(in);
-			if (s == NULL) {
-				dgap_err("unexpected end of file");
-				return(-1);
-			}
-			p->u.board.portstr = dgap_savestring(s);
-			p->u.board.port = (short)simple_strtol(s, &s2, 0);
-			if ((short)strlen(s) > (short)(s2 - s)) {
-				dgap_err("bad number for IO port");
-				return(-1);
-			}
-			p->u.board.v_port = 1;
-			DPR_INIT(("Adding IO (%s) to config...\n", s));
-			break;
-
-		case MEM:	/* memory address */
-			if (p->type != BNODE) {
-				dgap_err("memory address only vaild for boards");
-				return(-1);
-			}
-			s = dgap_getword(in);
-			if (s == NULL) {
-				dgap_err("unexpected end of file");
-				return(-1);
-			}
-			p->u.board.addrstr = dgap_savestring(s);
-			p->u.board.addr = simple_strtoul(s, &s2, 0);
-			if ((int)strlen(s) > (int)(s2 - s)) {
-				dgap_err("bad number for memory address");
-				return(-1);
-			}
-			p->u.board.v_addr = 1;
-			DPR_INIT(("Adding MEM (%s) to config...\n", s));
-			break;
-
-		case PCIINFO:	/* pci information */
-			if (p->type != BNODE) {
-				dgap_err("memory address only vaild for boards");
-				return(-1);
-			}
-			s = dgap_getword(in);
-			if (s == NULL) {
-				dgap_err("unexpected end of file");
-				return(-1);
-			}
-			p->u.board.pcibusstr = dgap_savestring(s);
-			p->u.board.pcibus = simple_strtoul(s, &s2, 0);
-			if ((int)strlen(s) > (int)(s2 - s)) {
-				dgap_err("bad number for pci bus");
-				return(-1);
-			}
-			p->u.board.v_pcibus = 1;
-			s = dgap_getword(in);
-			if (s == NULL) {
-				dgap_err("unexpected end of file");
-				return(-1);
-			}
-			p->u.board.pcislotstr = dgap_savestring(s);
-			p->u.board.pcislot = simple_strtoul(s, &s2, 0);
-			if ((int)strlen(s) > (int)(s2 - s)) {
-				dgap_err("bad number for pci slot");
-				return(-1);
-			}
-			p->u.board.v_pcislot = 1;
-
-			DPR_INIT(("Adding PCIINFO (%s %s) to config...\n", p->u.board.pcibusstr,
-				p->u.board.pcislotstr));
-			break;
-
-		case METHOD:
-			if (p->type != BNODE) {
-				dgap_err("install method only vaild for boards");
-				return(-1);
-			}
-			s = dgap_getword(in);
-			if (s == NULL) {
-				dgap_err("unexpected end of file");
-				return(-1);
-			}
-			p->u.board.method = dgap_savestring(s);
-			p->u.board.v_method = 1;
-			DPR_INIT(("Adding METHOD (%s) to config...\n", s));
-			break;
-
-		case STATUS:
-			if (p->type != BNODE) {
-				dgap_err("config status only vaild for boards");
-				return(-1);
-			}
-			s = dgap_getword(in);
-			if (s == NULL) {
-				dgap_err("unexpected end of file");
-				return(-1);
-			}
-			p->u.board.status = dgap_savestring(s);
-			DPR_INIT(("Adding STATUS (%s) to config...\n", s));
-			break;
-
-		case NPORTS:	/* number of ports */
-			if (p->type == BNODE) {
-				s = dgap_getword(in);
-				if (s == NULL) {
-					dgap_err("unexpected end of file");
-					return(-1);
-				}
-				p->u.board.nport = (char)simple_strtol(s, &s2, 0);
-				if ((int)strlen(s) > (int)(s2 - s)) {
-					dgap_err("bad number for number of ports");
-					return(-1);
-				}
-				p->u.board.v_nport = 1;
-			} else if (p->type == CNODE) {
-				s = dgap_getword(in);
-				if (s == NULL) {
-					dgap_err("unexpected end of file");
-					return(-1);
-				}
-				p->u.conc.nport = (char)simple_strtol(s, &s2, 0);
-				if ((int)strlen(s) > (int)(s2 - s)) {
-					dgap_err("bad number for number of ports");
-					return(-1);
-				}
-				p->u.conc.v_nport = 1;
-			} else if (p->type == MNODE) {
-				s = dgap_getword(in);
-				if (s == NULL) {
-					dgap_err("unexpected end of file");
-					return(-1);
-				}
-				p->u.module.nport = (char)simple_strtol(s, &s2, 0);
-				if ((int)strlen(s) > (int)(s2 - s)) {
-					dgap_err("bad number for number of ports");
-					return(-1);
-				}
-				p->u.module.v_nport = 1;
-			} else {
-				dgap_err("nports only valid for concentrators or modules");
-				return(-1);
-			}
-			DPR_INIT(("Adding NPORTS (%s) to config...\n", s));
-			break;
-
-		case ID:	/* letter ID used in tty name */
-			s = dgap_getword(in);
-			if (s == NULL) {
-				dgap_err("unexpected end of file");
-				return(-1);
-			}
-
-			p->u.board.status = dgap_savestring(s);
-
-			if (p->type == CNODE) {
-				p->u.conc.id = dgap_savestring(s);
-				p->u.conc.v_id = 1;
-			} else if (p->type == MNODE) {
-				p->u.module.id = dgap_savestring(s);
-				p->u.module.v_id = 1;
-			} else {
-				dgap_err("id only valid for concentrators or modules");
-				return(-1);
-			}
-			DPR_INIT(("Adding ID (%s) to config...\n", s));
-			break;
-
-		case STARTO:	/* start offset of ID */
-			if (p->type == BNODE) {
-				s = dgap_getword(in);
-				if (s == NULL) {
-					dgap_err("unexpected end of file");
-					return(-1);
-				}
-				p->u.board.start = simple_strtol(s, &s2, 0);
-				if ((int)strlen(s) > (int)(s2 - s)) {
-					dgap_err("bad number for start of tty count");
-					return(-1);
-				}
-				p->u.board.v_start = 1;
-			} else if (p->type == CNODE) {
-				s = dgap_getword(in);
-				if (s == NULL) {
-					dgap_err("unexpected end of file");
-					return(-1);
-				}
-				p->u.conc.start = simple_strtol(s, &s2, 0);
-				if ((int)strlen(s) > (int)(s2 - s)) {
-					dgap_err("bad number for start of tty count");
-					return(-1);
-				}
-				p->u.conc.v_start = 1;
-			} else if (p->type == MNODE) {
-				s = dgap_getword(in);
-				if (s == NULL) {
-					dgap_err("unexpected end of file");
-					return(-1);
-				}
-				p->u.module.start = simple_strtol(s, &s2, 0);
-				if ((int)strlen(s) > (int)(s2 - s)) {
-					dgap_err("bad number for start of tty count");
-					return(-1);
-				}
-				p->u.module.v_start = 1;
-			} else {
-				dgap_err("start only valid for concentrators or modules");
-				return(-1);
-			}
-			DPR_INIT(("Adding START (%s) to config...\n", s));
-			break;
-
-		case TTYN:	/* tty name prefix */
-			if (dgap_checknode(p))
-				return(-1);
-			if ( (p->next = dgap_newnode(TNODE)) == NULL ) {
-				dgap_err("out of memory");
-				return(-1);
-			}
-			p = p->next;
-			if ( (s = dgap_getword(in)) == NULL ) {
-				dgap_err("unexpeced end of file");
-				return(-1);
-			}
-			if ( (p->u.ttyname = dgap_savestring(s)) == NULL ) {
-				dgap_err("out of memory");
-				return(-1);
-			}
-			DPR_INIT(("Adding TTY (%s) to config...\n", s));
-			break;
-
-		case CU:	/* cu name prefix */
-			if (dgap_checknode(p))
-				return(-1);
-			if ( (p->next = dgap_newnode(CUNODE)) == NULL ) {
-				dgap_err("out of memory");
-				return(-1);
-			}
-			p = p->next;
-			if ( (s = dgap_getword(in)) == NULL ) {
-				dgap_err("unexpeced end of file");
-				return(-1);
-			}
-			if ( (p->u.cuname = dgap_savestring(s)) == NULL ) {
-				dgap_err("out of memory");
-				return(-1);
-			}
-			DPR_INIT(("Adding CU (%s) to config...\n", s));
-			break;
-
-		case LINE:	/* line information */
-			if (dgap_checknode(p))
-				return(-1);
-			if (brd == NULL) {
-				dgap_err("must specify board before line info");
-				return(-1);
-			}
-			switch (brd->u.board.type) {
-			case PPCM:
-				dgap_err("line not vaild for PC/em");
-				return(-1);
-			}
-			if ( (p->next = dgap_newnode(LNODE)) == NULL ) {
-				dgap_err("out of memory");
-				return(-1);
-			}
-			p = p->next;
-			conc = NULL;
-			line = p;
-			linecnt++;
-			DPR_INIT(("Adding LINE to config...\n"));
-			break;
-
-		case CONC:	/* concentrator information */
-			if (dgap_checknode(p))
-				return(-1);
-			if (line == NULL) {
-				dgap_err("must specify line info before concentrator");
-				return(-1);
-			}
-			if ( (p->next = dgap_newnode(CNODE)) == NULL ) {
-				dgap_err("out of memory");
-				return(-1);
-			}
-			p = p->next;
-			conc = p;
-			if (linecnt)
-				brd->u.board.conc2++;
-			else
-				brd->u.board.conc1++;
-
-			DPR_INIT(("Adding CONC to config...\n"));
-			break;
-
-		case CX:	/* c/x type concentrator */
-			if (p->type != CNODE) {
-				dgap_err("cx only valid for concentrators");
-				return(-1);
-			}
-			p->u.conc.type = CX;
-			p->u.conc.v_type = 1;
-			DPR_INIT(("Adding CX to config...\n"));
-			break;
-
-		case EPC:	/* epc type concentrator */
-			if (p->type != CNODE) {
-				dgap_err("cx only valid for concentrators");
-				return(-1);
-			}
-			p->u.conc.type = EPC;
-			p->u.conc.v_type = 1;
-			DPR_INIT(("Adding EPC to config...\n"));
-			break;
-
-		case MOD:	/* EBI module */
-			if (dgap_checknode(p))
-				return(-1);
-			if (brd == NULL) {
-				dgap_err("must specify board info before EBI modules");
-				return(-1);
-			}
-			switch (brd->u.board.type) {
-			case PPCM:
-				linecnt = 0;
-				break;
-			default:
-				if (conc == NULL) {
-					dgap_err("must specify concentrator info before EBI module");
-					return(-1);
-				}
-			}
-			if ( (p->next = dgap_newnode(MNODE)) == NULL ) {
-				dgap_err("out of memory");
-				return(-1);
-			}
-			p = p->next;
-			if (linecnt)
-				brd->u.board.module2++;
-			else
-				brd->u.board.module1++;
-
-			DPR_INIT(("Adding MOD to config...\n"));
-			break;
-
-		case PORTS:	/* ports type EBI module */
-			if (p->type != MNODE) {
-				dgap_err("ports only valid for EBI modules");
-				return(-1);
-			}
-			p->u.module.type = PORTS;
-			p->u.module.v_type = 1;
-			DPR_INIT(("Adding PORTS to config...\n"));
-			break;
-
-		case MODEM:	/* ports type EBI module */
-			if (p->type != MNODE) {
-				dgap_err("modem only valid for modem modules");
-				return(-1);
-			}
-			p->u.module.type = MODEM;
-			p->u.module.v_type = 1;
-			DPR_INIT(("Adding MODEM to config...\n"));
-			break;
-
-		case CABLE:
-			if (p->type == LNODE) {
-				if ((s = dgap_getword(in)) == NULL) {
-					dgap_err("unexpected end of file");
-					return(-1);
-				}
-				p->u.line.cable = dgap_savestring(s);
-				p->u.line.v_cable = 1;
-			}
-			DPR_INIT(("Adding CABLE (%s) to config...\n", s));
-			break;
-
-		case SPEED:	/* sync line speed indication */
-			if (p->type == LNODE) {
-				s = dgap_getword(in);
-				if (s == NULL) {
-					dgap_err("unexpected end of file");
-					return(-1);
-				}
-				p->u.line.speed = (char)simple_strtol(s, &s2, 0);
-				if ((short)strlen(s) > (short)(s2 - s)) {
-					dgap_err("bad number for line speed");
-					return(-1);
-				}
-				p->u.line.v_speed = 1;
-			} else if (p->type == CNODE) {
-				s = dgap_getword(in);
-				if (s == NULL) {
-					dgap_err("unexpected end of file");
-					return(-1);
-				}
-				p->u.conc.speed = (char)simple_strtol(s, &s2, 0);
-				if ((short)strlen(s) > (short)(s2 - s)) {
-					dgap_err("bad number for line speed");
-					return(-1);
-				}
-				p->u.conc.v_speed = 1;
-			} else {
-				dgap_err("speed valid only for lines or concentrators.");
-				return(-1);
-			}
-			DPR_INIT(("Adding SPEED (%s) to config...\n", s));
-			break;
-
-		case CONNECT:
-			if (p->type == CNODE) {
-				if ((s = dgap_getword(in)) == NULL) {
-					dgap_err("unexpected end of file");
-					return(-1);
-				}
-				p->u.conc.connect = dgap_savestring(s);
-				p->u.conc.v_connect = 1;
-			}
-			DPR_INIT(("Adding CONNECT (%s) to config...\n", s));
-			break;
-		case PRINT:	/* transparent print name prefix */
-			if (dgap_checknode(p))
-				return(-1);
-			if ( (p->next = dgap_newnode(PNODE)) == NULL ) {
-				dgap_err("out of memory");
-				return(-1);
-			}
-			p = p->next;
-			if ( (s = dgap_getword(in)) == NULL ) {
-				dgap_err("unexpeced end of file");
-				return(-1);
-			}
-			if ( (p->u.printname = dgap_savestring(s)) == NULL ) {
-				dgap_err("out of memory");
-				return(-1);
-			}
-			DPR_INIT(("Adding PRINT (%s) to config...\n", s));
-			break;
-
-		case CMAJOR:	/* major number */
-			if (dgap_checknode(p))
-				return(-1);
-			if ( (p->next = dgap_newnode(JNODE)) == NULL ) {
-				dgap_err("out of memory");
-				return(-1);
-			}
-			p = p->next;
-			s = dgap_getword(in);
-			if (s == NULL) {
-				dgap_err("unexpected end of file");
-				return(-1);
-			}
-			p->u.majornumber = simple_strtol(s, &s2, 0);
-			if ((int)strlen(s) > (int)(s2 - s)) {
-				dgap_err("bad number for major number");
-				return(-1);
-			}
-			DPR_INIT(("Adding CMAJOR (%s) to config...\n", s));
-			break;
-
-		case ALTPIN:	/* altpin setting */
-			if (dgap_checknode(p))
-				return(-1);
-			if ( (p->next = dgap_newnode(ANODE)) == NULL ) {
-				dgap_err("out of memory");
-				return(-1);
-			}
-			p = p->next;
-			s = dgap_getword(in);
-			if (s == NULL) {
-				dgap_err("unexpected end of file");
-				return(-1);
-			}
-			p->u.altpin = simple_strtol(s, &s2, 0);
-			if ((int)strlen(s) > (int)(s2 - s)) {
-				dgap_err("bad number for altpin");
-				return(-1);
-			}
-			DPR_INIT(("Adding ALTPIN (%s) to config...\n", s));
-			break;
-
-		case USEINTR:		/* enable interrupt setting */
-			if (dgap_checknode(p))
-				return(-1);
-			if ( (p->next = dgap_newnode(INTRNODE)) == NULL ) {
-				dgap_err("out of memory");
-				return(-1);
-			}
-			p = p->next;
-			s = dgap_getword(in);
-			if (s == NULL) {
-				dgap_err("unexpected end of file");
-				return(-1);
-			}
-			p->u.useintr = simple_strtol(s, &s2, 0);
-			if ((int)strlen(s) > (int)(s2 - s)) {
-				dgap_err("bad number for useintr");
-				return(-1);
-			}
-			DPR_INIT(("Adding USEINTR (%s) to config...\n", s));
-			break;
-
-		case TTSIZ:	/* size of tty structure */
-			if (dgap_checknode(p))
-				return(-1);
-			if ( (p->next = dgap_newnode(TSNODE)) == NULL ) {
-				dgap_err("out of memory");
-				return(-1);
-			}
-			p = p->next;
-			s = dgap_getword(in);
-			if (s == NULL) {
-				dgap_err("unexpected end of file");
-				return(-1);
-			}
-			p->u.ttysize = simple_strtol(s, &s2, 0);
-			if ((int)strlen(s) > (int)(s2 - s)) {
-				dgap_err("bad number for ttysize");
-				return(-1);
-			}
-			DPR_INIT(("Adding TTSIZ (%s) to config...\n", s));
-			break;
-
-		case CHSIZ:	/* channel structure size */
-			if (dgap_checknode(p))
-				return(-1);
-			if ( (p->next = dgap_newnode(CSNODE)) == NULL ) {
-				dgap_err("out of memory");
-				return(-1);
-			}
-			p = p->next;
-			s = dgap_getword(in);
-			if (s == NULL) {
-				dgap_err("unexpected end of file");
-				return(-1);
-			}
-			p->u.chsize = simple_strtol(s, &s2, 0);
-			if ((int)strlen(s) > (int)(s2 - s)) {
-				dgap_err("bad number for chsize");
-				return(-1);
-			}
-			DPR_INIT(("Adding CHSIZE (%s) to config...\n", s));
-			break;
-
-		case BSSIZ:	/* board structure size */
-			if (dgap_checknode(p))
-				return(-1);
-			if ( (p->next = dgap_newnode(BSNODE)) == NULL ) {
-				dgap_err("out of memory");
-				return(-1);
-			}
-			p = p->next;
-			s = dgap_getword(in);
-			if (s == NULL) {
-				dgap_err("unexpected end of file");
-				return(-1);
-			}
-			p->u.bssize = simple_strtol(s, &s2, 0);
-			if ((int)strlen(s) > (int)(s2 - s)) {
-				dgap_err("bad number for bssize");
-				return(-1);
-			}
-			DPR_INIT(("Adding BSSIZ (%s) to config...\n", s));
-			break;
-
-		case UNTSIZ:	/* sched structure size */
-			if (dgap_checknode(p))
-				return(-1);
-			if ( (p->next = dgap_newnode(USNODE)) == NULL ) {
-				dgap_err("out of memory");
-				return(-1);
-			}
-			p = p->next;
-			s = dgap_getword(in);
-			if (s == NULL) {
-				dgap_err("unexpected end of file");
-				return(-1);
-			}
-			p->u.unsize = simple_strtol(s, &s2, 0);
-			if ((int)strlen(s) > (int)(s2 - s)) {
-				dgap_err("bad number for schedsize");
-				return(-1);
-			}
-			DPR_INIT(("Adding UNTSIZ (%s) to config...\n", s));
-			break;
-
-		case F2SIZ:	/* f2200 structure size */
-			if (dgap_checknode(p))
-				return(-1);
-			if ( (p->next = dgap_newnode(FSNODE)) == NULL ) {
-				dgap_err("out of memory");
-				return(-1);
-			}
-			p = p->next;
-			s = dgap_getword(in);
-			if (s == NULL) {
-				dgap_err("unexpected end of file");
-				return(-1);
-			}
-			p->u.f2size = simple_strtol(s, &s2, 0);
-			if ((int)strlen(s) > (int)(s2 - s)) {
-				dgap_err("bad number for f2200size");
-				return(-1);
-			}
-			DPR_INIT(("Adding F2SIZ (%s) to config...\n", s));
-			break;
-
-		case VPSIZ:	/* vpix structure size */
-			if (dgap_checknode(p))
-				return(-1);
-			if ( (p->next = dgap_newnode(VSNODE)) == NULL ) {
-				dgap_err("out of memory");
-				return(-1);
-			}
-			p = p->next;
-			s = dgap_getword(in);
-			if (s == NULL) {
-				dgap_err("unexpected end of file");
-				return(-1);
-			}
-			p->u.vpixsize = simple_strtol(s, &s2, 0);
-			if ((int)strlen(s) > (int)(s2 - s)) {
-				dgap_err("bad number for vpixsize");
-				return(-1);
-			}
-			DPR_INIT(("Adding VPSIZ (%s) to config...\n", s));
-			break;
-		}
-	}
-}
-
-
-/*
- * dgap_sindex: much like index(), but it looks for a match of any character in
- * the group, and returns that position.  If the first character is a ^, then
- * this will match the first occurrence not in that group.
- */
-static char *dgap_sindex (char *string, char *group)
-{
-	char    *ptr;
-
-	if (!string || !group)
-		return (char *) NULL;
-
-	if (*group == '^') {
-		group++;
-		for (; *string; string++) {
-			for (ptr = group; *ptr; ptr++) {
-				if (*ptr == *string)
-					break;
-			}
-			if (*ptr == '\0')
-				return string;
-		}
-	}
-	else {
-		for (; *string; string++) {
-			for (ptr = group; *ptr; ptr++) {
-				if (*ptr == *string)
-					return string;
-			}
-		}
-	}
-
-	return (char *) NULL;
-}
-
-
-/*
- * Get a token from the input file; return 0 if end of file is reached
- */
-static int dgap_gettok(char **in, struct cnode *p)
-{
-	char	*w;
-	struct toklist *t;
-
-	if (strstr(dgap_cword, "boar")) {
-		w = dgap_getword(in);
-		snprintf(dgap_cword, MAXCWORD, "%s", w);
-		for (t = dgap_tlist; t->token != 0; t++) {
-			if ( !strcmp(w, t->string)) {
-				return(t->token);
-			}
-		}
-		dgap_err("board !!type not specified");
-		return(1);
-	}
-	else {
-		while ( (w = dgap_getword(in)) != NULL ) {
-			snprintf(dgap_cword, MAXCWORD, "%s", w);
-			for (t = dgap_tlist; t->token != 0; t++) {
-				if ( !strcmp(w, t->string) )
-					return(t->token);
-			}
-		}
-		return(0);
-	}
-}
-
-
-/*
- * get a word from the input stream, also keep track of current line number.
- * words are separated by whitespace.
- */
-static char *dgap_getword(char **in)
-{
-	char *ret_ptr = *in;
-
-        char *ptr = dgap_sindex(*in, " \t\n");
-
-	/* If no word found, return null */
-	if (!ptr)
-		return NULL;
-
-	/* Mark new location for our buffer */
-	*ptr = '\0';
-	*in = ptr + 1;
-
-	/* Eat any extra spaces/tabs/newlines that might be present */
-	while (*in && **in && ((**in == ' ') || (**in == '\t') || (**in == '\n'))) {
-		**in = '\0';
-		*in = *in + 1;
-	}
-
-	return ret_ptr;
-}
-
-
-/*
- * print an error message, giving the line number in the file where
- * the error occurred.
- */
-static void dgap_err(char *s)
-{
-	printk("DGAP: parse: %s\n", s);
-}
-
-
-/*
- * allocate a new configuration node of type t
- */
-static struct cnode *dgap_newnode(int t)
-{
-	struct cnode *n;
-
-	n = kmalloc(sizeof(struct cnode), GFP_ATOMIC);
-	if (n != NULL) {
-		memset((char *)n, 0, sizeof(struct cnode));
-		n->type = t;
-	}
-	return(n);
-}
-
-
-/*
- * dgap_checknode: see if all the necessary info has been supplied for a node
- * before creating the next node.
- */
-static int dgap_checknode(struct cnode *p)
-{
-	switch (p->type) {
-	case BNODE:
-		if (p->u.board.v_type == 0) {
-			dgap_err("board type !not specified");
-			return(1);
-		}
-
-		return(0);
-
-	case LNODE:
-		if (p->u.line.v_speed == 0) {
-			dgap_err("line speed not specified");
-			return(1);
-		}
-		return(0);
-
-	case CNODE:
-		if (p->u.conc.v_type == 0) {
-			dgap_err("concentrator type not specified");
-			return(1);
-		}
-		if (p->u.conc.v_speed == 0) {
-			dgap_err("concentrator line speed not specified");
-			return(1);
-		}
-		if (p->u.conc.v_nport == 0) {
-			dgap_err("number of ports on concentrator not specified");
-			return(1);
-		}
-		if (p->u.conc.v_id == 0) {
-			dgap_err("concentrator id letter not specified");
-			return(1);
-		}
-		return(0);
-
-	case MNODE:
-		if (p->u.module.v_type == 0) {
-			dgap_err("EBI module type not specified");
-			return(1);
-		}
-		if (p->u.module.v_nport == 0) {
-			dgap_err("number of ports on EBI module not specified");
-			return(1);
-		}
-		if (p->u.module.v_id == 0) {
-			dgap_err("EBI module id letter not specified");
-			return(1);
-		}
-		return(0);
-	}
-	return(0);
-}
-
-/*
- * save a string somewhere
- */
-static char	*dgap_savestring(char *s)
-{
-	char	*p;
-	if ( (p = kmalloc(strlen(s) + 1, GFP_ATOMIC) ) != NULL) {
-		strcpy(p, s);
-	}
-	return(p);
-}
-
-
-/*
- * Given a board pointer, returns whether we should use interrupts or not.
- */
-uint dgap_config_get_useintr(struct board_t *bd)
-{
-	struct cnode *p = NULL;
-
-	if (!bd)
-		return(0);
-
-	for (p = bd->bd_config; p; p = p->next) {
-		switch (p->type) {
-		case INTRNODE:
-			/*
-			 * check for pcxr types.
-			 */
-			return p->u.useintr;
-		default:
-			break;
-		}
-	}
-
-	/* If not found, then don't turn on interrupts. */
-	return 0;
-}
-
-
-/*
- * Given a board pointer, returns whether we turn on altpin or not.
- */
-uint dgap_config_get_altpin(struct board_t *bd)
-{
-	struct cnode *p = NULL;
-
-	if (!bd)
-		return(0);
-
-	for (p = bd->bd_config; p; p = p->next) {
-		switch (p->type) {
-		case ANODE:
-			/*
-			 * check for pcxr types.
-			 */
-			return p->u.altpin;
-		default:
-			break;
-		}
-	}
-
-	/* If not found, then don't turn on interrupts. */
-	return 0;
-}
-
-
-
-/*
- * Given a specific type of board, if found, detached link and
- * returns the first occurrence in the list.
- */
-struct cnode *dgap_find_config(int type, int bus, int slot)
-{
-	struct cnode *p, *prev = NULL, *prev2 = NULL, *found = NULL;
-
-	p = &dgap_head;
-
-	while (p->next != NULL) {
-		prev = p;
-		p = p->next;
-
-		if (p->type == BNODE) {
-
-			if (p->u.board.type == type) {
-
-				if (p->u.board.v_pcibus && p->u.board.pcibus != bus) {
-					DPR(("Found matching board, but wrong bus position. System says bus %d, we want bus %ld\n",
-						bus, p->u.board.pcibus));
-					continue;
-				}
-				if (p->u.board.v_pcislot && p->u.board.pcislot != slot) {
-					DPR_INIT(("Found matching board, but wrong slot position. System says slot %d, we want slot %ld\n",
-						slot, p->u.board.pcislot));
-					continue;
-				}
-
-				DPR_INIT(("Matched type in config file\n"));
-
-				found = p;
-				/*
-				 * Keep walking thru the list till we find the next board.
-				 */
-				while (p->next != NULL) {
-					prev2 = p;
-					p = p->next;
-					if (p->type == BNODE) {
-
-						/*
-						 * Mark the end of our 1 board chain of configs.
-						 */
-						prev2->next = NULL;
-
-						/*
-						 * Link the "next" board to the previous board,
-						 * effectively "unlinking" our board from the main config.
-						 */
-						prev->next = p;
-
-						return found;
-					}
-				}
-				/*
-				 * It must be the last board in the list.
-				 */
-				prev->next = NULL;
-				return found;
-			}
-		}
-	}
-	return NULL;
-}
-
-/*
- * Given a board pointer, walks the config link, counting up
- * all ports user specified should be on the board.
- * (This does NOT mean they are all actually present right now tho)
- */
-uint dgap_config_get_number_of_ports(struct board_t *bd)
-{
-	int count = 0;
-	struct cnode *p = NULL;
-
-	if (!bd)
-		return(0);
-
-	for (p = bd->bd_config; p; p = p->next) {
-
-		switch (p->type) {
-		case BNODE:
-			/*
-			 * check for pcxr types.
-			 */
-			if (p->u.board.type > EPCFE)
-				count += p->u.board.nport;
-			break;
-		case CNODE:
-			count += p->u.conc.nport;
-			break;
-		case MNODE:
-			count += p->u.module.nport;
-			break;
-		}
-	}
-	return (count);
-}
-
-char *dgap_create_config_string(struct board_t *bd, char *string)
-{
-	char *ptr = string;
-	struct cnode *p = NULL;
-	struct cnode *q = NULL;
-	int speed;
-
-	if (!bd) {
-		*ptr = 0xff;
-		return string;
-	}
-
-	for (p = bd->bd_config; p; p = p->next) {
-
-		switch (p->type) {
-		case LNODE:
-			*ptr = '\0';
-			ptr++;
-			*ptr = p->u.line.speed;
-			ptr++;
-			break;
-		case CNODE:
-			/*
-			 * Because the EPC/con concentrators can have EM modules
-			 * hanging off of them, we have to walk ahead in the list
-			 * and keep adding the number of ports on each EM to the config.
-			 * UGH!
-			 */
-			speed = p->u.conc.speed;
-			q = p->next;
-			if ((q != NULL) && (q->type == MNODE) ) {
-				*ptr = (p->u.conc.nport + 0x80);
-				ptr++;
-				p = q;
-				while ((q->next != NULL) && (q->next->type) == MNODE) {
-					*ptr = (q->u.module.nport + 0x80);
-					ptr++;
-					p = q;
-					q = q->next;
-				}
-				*ptr = q->u.module.nport;
-				ptr++;
-			} else {
-				*ptr = p->u.conc.nport;
-				ptr++;
-			}
-
-			*ptr = speed;
-			ptr++;
-			break;
-		}
-	}
-
-	*ptr = 0xff;
-	return string;
-}
-
-
-
-char *dgap_get_config_letters(struct board_t *bd, char *string)
-{
-	int found = FALSE;
-	char *ptr = string;
-	struct cnode *cptr = NULL;
-	int len = 0;
-	int left = MAXTTYNAMELEN;
-
-	if (!bd) {
-		return "<NULL>";
-	}
-
-	for (cptr = bd->bd_config; cptr; cptr = cptr->next) {
-
-		if ((cptr->type == BNODE) &&
-		     ((cptr->u.board.type == APORT2_920P) || (cptr->u.board.type == APORT4_920P) ||
-		     (cptr->u.board.type == APORT8_920P) || (cptr->u.board.type == PAPORT4) ||
-		     (cptr->u.board.type == PAPORT8))) {
-
-			found = TRUE;
-		}
-
-		if (cptr->type == TNODE && found == TRUE) {
-			char *ptr1;
-			if (strstr(cptr->u.ttyname, "tty")) {
-				ptr1 = cptr->u.ttyname;
-				ptr1 += 3;
-			}
-			else {
-				ptr1 = cptr->u.ttyname;
-			}
-			if (ptr1) {
-				len = snprintf(ptr, left, "%s", ptr1);
-				left -= len;
-				ptr  += len;
-				if (left <= 0)
-					break;
-			}
-		}
-
-		if (cptr->type == CNODE) {
-			if (cptr->u.conc.id) {
-				len = snprintf(ptr, left, "%s", cptr->u.conc.id);
-				left -= len;
-				ptr  += len;
-				if (left <= 0)
-					break;
-			}
-                }
-
-		if (cptr->type == MNODE) {
-			if (cptr->u.module.id) {
-				len = snprintf(ptr, left, "%s", cptr->u.module.id);
-				left -= len;
-				ptr  += len;
-				if (left <= 0)
-					break;
-			}
-		}
-	}
-
-	return string;
-}
diff --git a/drivers/staging/dgap/dgap_parse.h b/drivers/staging/dgap/dgap_parse.h
deleted file mode 100644
index 8128c47..0000000
--- a/drivers/staging/dgap/dgap_parse.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright 2003 Digi International (www.digi.com)
- *	Scott H Kilau <Scott_Kilau at digi dot com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
- * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- * PURPOSE.  See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- *	NOTE: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!!
- */
-
-#ifndef _DGAP_PARSE_H
-#define _DGAP_PARSE_H
-
-#include "dgap_driver.h"
-
-extern int dgap_parsefile(char **in, int Remove);
-extern struct cnode *dgap_find_config(int type, int bus, int slot);
-extern uint dgap_config_get_number_of_ports(struct board_t *bd);
-extern char *dgap_create_config_string(struct board_t *bd, char *string);
-extern char *dgap_get_config_letters(struct board_t *bd, char *string);
-extern uint dgap_config_get_useintr(struct board_t *bd);
-extern uint dgap_config_get_altpin(struct board_t *bd);
-
-#endif
diff --git a/drivers/staging/dgap/dgap_pci.h b/drivers/staging/dgap/dgap_pci.h
deleted file mode 100644
index 05ed374..0000000
--- a/drivers/staging/dgap/dgap_pci.h
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright 2003 Digi International (www.digi.com)
- *	Scott H Kilau <Scott_Kilau at digi dot com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
- * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- * PURPOSE.  See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- *	NOTE: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!!
- */
-
-/* $Id: dgap_pci.h,v 1.1 2009/10/23 14:01:57 markh Exp $ */
-
-#ifndef __DGAP_PCI_H
-#define __DGAP_PCI_H
-
-#define PCIMAX 32			/* maximum number of PCI boards */
-
-#define DIGI_VID		0x114F
-
-#define PCI_DEVICE_EPC_DID	0x0002
-#define PCI_DEVICE_XEM_DID	0x0004
-#define PCI_DEVICE_XR_DID	0x0005
-#define PCI_DEVICE_CX_DID	0x0006
-#define PCI_DEVICE_XRJ_DID	0x0009	/* PLX-based Xr adapter */
-#define PCI_DEVICE_XR_IBM_DID	0x0011	/* IBM 8-port Async Adapter */
-#define PCI_DEVICE_XR_BULL_DID	0x0013	/* BULL 8-port Async Adapter */
-#define PCI_DEVICE_XR_SAIP_DID	0x001c	/* SAIP card - Xr adapter */
-#define PCI_DEVICE_XR_422_DID	0x0012	/* Xr-422 */
-#define PCI_DEVICE_920_2_DID	0x0034	/* XR-Plus 920 K, 2 port */
-#define PCI_DEVICE_920_4_DID	0x0026	/* XR-Plus 920 K, 4 port */
-#define PCI_DEVICE_920_8_DID	0x0027	/* XR-Plus 920 K, 8 port */
-#define PCI_DEVICE_EPCJ_DID	0x000a	/* PLX 9060 chip for PCI  */
-#define PCI_DEVICE_CX_IBM_DID	0x001b	/* IBM 128-port Async Adapter */
-#define PCI_DEVICE_920_8_HP_DID	0x0058	/* HP XR-Plus 920 K, 8 port */
-#define PCI_DEVICE_XEM_HP_DID	0x0059  /* HP Xem PCI */
-
-#define PCI_DEVICE_XEM_NAME	"AccelePort XEM"
-#define PCI_DEVICE_CX_NAME	"AccelePort CX"
-#define PCI_DEVICE_XR_NAME	"AccelePort Xr"
-#define PCI_DEVICE_XRJ_NAME	"AccelePort Xr (PLX)"
-#define PCI_DEVICE_XR_SAIP_NAME	"AccelePort Xr (SAIP)"
-#define PCI_DEVICE_920_2_NAME	"AccelePort Xr920 2 port"
-#define PCI_DEVICE_920_4_NAME	"AccelePort Xr920 4 port"
-#define PCI_DEVICE_920_8_NAME	"AccelePort Xr920 8 port"
-#define PCI_DEVICE_XR_422_NAME	"AccelePort Xr 422"
-#define PCI_DEVICE_EPCJ_NAME	"AccelePort EPC (PLX)"
-#define PCI_DEVICE_XR_BULL_NAME	"AccelePort Xr (BULL)"
-#define PCI_DEVICE_XR_IBM_NAME	"AccelePort Xr (IBM)"
-#define PCI_DEVICE_CX_IBM_NAME	"AccelePort CX (IBM)"
-#define PCI_DEVICE_920_8_HP_NAME "AccelePort Xr920 8 port (HP)"
-#define PCI_DEVICE_XEM_HP_NAME	"AccelePort XEM (HP)"
-
-
-/*
- * On the PCI boards, there is no IO space allocated
- * The I/O registers will be in the first 3 bytes of the
- * upper 2MB of the 4MB memory space.  The board memory
- * will be mapped into the low 2MB of the 4MB memory space
- */
-
-/* Potential location of PCI Bios from E0000 to FFFFF*/
-#define PCI_BIOS_SIZE		0x00020000
-
-/* Size of Memory and I/O for PCI (4MB) */
-#define PCI_RAM_SIZE		0x00400000
-
-/* Size of Memory (2MB) */
-#define PCI_MEM_SIZE		0x00200000
-
-/* Max PCI Window Size (2MB) */
-#define PCI_WIN_SIZE		0x00200000
-
-#define PCI_WIN_SHIFT		21 /* 21 bits max */
-
-/* Offset of I/0 in Memory (2MB) */
-#define PCI_IO_OFFSET		0x00200000
-
-/* Size of IO (2MB) */
-#define PCI_IO_SIZE		0x00200000
-
-#endif
diff --git a/drivers/staging/dgap/dgap_sysfs.c b/drivers/staging/dgap/dgap_sysfs.c
deleted file mode 100644
index aa7e36f..0000000
--- a/drivers/staging/dgap/dgap_sysfs.c
+++ /dev/null
@@ -1,793 +0,0 @@
-/*
- * Copyright 2004 Digi International (www.digi.com)
- *      Scott H Kilau <Scott_Kilau at digi dot com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
- * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- * PURPOSE.  See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- *
- *      NOTE TO LINUX KERNEL HACKERS:  DO NOT REFORMAT THIS CODE!
- *
- *      This is shared code between Digi's CVS archive and the
- *      Linux Kernel sources.
- *      Changing the source just for reformatting needlessly breaks
- *      our CVS diff history.
- *
- *      Send any bug fixes/changes to:  Eng.Linux at digi dot com.
- *      Thank you.
- *
- *
- *
- * $Id: dgap_sysfs.c,v 1.1 2009/10/23 14:01:57 markh Exp $
- */
-
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/ctype.h>
-#include <linux/string.h>
-#include <linux/serial_reg.h>
-#include <linux/device.h>
-#include <linux/pci.h>
-#include <linux/kdev_t.h>
-
-#include "dgap_driver.h"
-#include "dgap_conf.h"
-#include "dgap_parse.h"
-
-
-static ssize_t dgap_driver_version_show(struct device_driver *ddp, char *buf)
-{
-	return snprintf(buf, PAGE_SIZE, "%s\n", DG_PART);
-}
-static DRIVER_ATTR(version, S_IRUSR, dgap_driver_version_show, NULL);
-
-
-static ssize_t dgap_driver_boards_show(struct device_driver *ddp, char *buf)
-{
-	return snprintf(buf, PAGE_SIZE, "%d\n", dgap_NumBoards);
-}
-static DRIVER_ATTR(boards, S_IRUSR, dgap_driver_boards_show, NULL);
-
-
-static ssize_t dgap_driver_maxboards_show(struct device_driver *ddp, char *buf)
-{
-	return snprintf(buf, PAGE_SIZE, "%d\n", MAXBOARDS);
-}
-static DRIVER_ATTR(maxboards, S_IRUSR, dgap_driver_maxboards_show, NULL);
-
-
-static ssize_t dgap_driver_pollcounter_show(struct device_driver *ddp, char *buf)
-{
-	return snprintf(buf, PAGE_SIZE, "%ld\n", dgap_poll_counter);
-}
-static DRIVER_ATTR(pollcounter, S_IRUSR, dgap_driver_pollcounter_show, NULL);
-
-
-static ssize_t dgap_driver_state_show(struct device_driver *ddp, char *buf)
-{
-	return snprintf(buf, PAGE_SIZE, "%s\n", dgap_driver_state_text[dgap_driver_state]);
-}
-static DRIVER_ATTR(state, S_IRUSR, dgap_driver_state_show, NULL);
-
-
-static ssize_t dgap_driver_debug_show(struct device_driver *ddp, char *buf)
-{
-	return snprintf(buf, PAGE_SIZE, "0x%x\n", dgap_debug);
-}
-
-static ssize_t dgap_driver_debug_store(struct device_driver *ddp, const char *buf, size_t count)
-{
-	sscanf(buf, "0x%x\n", &dgap_debug);
-	return count;
-}
-static DRIVER_ATTR(debug, (S_IRUSR | S_IWUSR), dgap_driver_debug_show, dgap_driver_debug_store);
-
-
-static ssize_t dgap_driver_rawreadok_show(struct device_driver *ddp, char *buf)
-{
-	return snprintf(buf, PAGE_SIZE, "0x%x\n", dgap_rawreadok);
-}
-
-static ssize_t dgap_driver_rawreadok_store(struct device_driver *ddp, const char *buf, size_t count)
-{
-	sscanf(buf, "0x%x\n", &dgap_rawreadok);
-	return count;
-}
-static DRIVER_ATTR(rawreadok, (S_IRUSR | S_IWUSR), dgap_driver_rawreadok_show, dgap_driver_rawreadok_store);
-
-
-static ssize_t dgap_driver_pollrate_show(struct device_driver *ddp, char *buf)
-{
-	return snprintf(buf, PAGE_SIZE, "%dms\n", dgap_poll_tick);
-}
-
-static ssize_t dgap_driver_pollrate_store(struct device_driver *ddp, const char *buf, size_t count)
-{
-	sscanf(buf, "%d\n", &dgap_poll_tick);
-	return count;
-}
-static DRIVER_ATTR(pollrate, (S_IRUSR | S_IWUSR), dgap_driver_pollrate_show, dgap_driver_pollrate_store);
-
-
-void dgap_create_driver_sysfiles(struct pci_driver *dgap_driver)
-{
-	int rc = 0;
-	struct device_driver *driverfs = &dgap_driver->driver;
-
-	rc |= driver_create_file(driverfs, &driver_attr_version);
-	rc |= driver_create_file(driverfs, &driver_attr_boards);
-	rc |= driver_create_file(driverfs, &driver_attr_maxboards);
-	rc |= driver_create_file(driverfs, &driver_attr_debug);
-	rc |= driver_create_file(driverfs, &driver_attr_rawreadok);
-	rc |= driver_create_file(driverfs, &driver_attr_pollrate);
-	rc |= driver_create_file(driverfs, &driver_attr_pollcounter);
-	rc |= driver_create_file(driverfs, &driver_attr_state);
-	if (rc) {
-		printk(KERN_ERR "DGAP: sysfs driver_create_file failed!\n");
-	}
-}
-
-
-void dgap_remove_driver_sysfiles(struct pci_driver *dgap_driver)
-{
-	struct device_driver *driverfs = &dgap_driver->driver;
-	driver_remove_file(driverfs, &driver_attr_version);
-	driver_remove_file(driverfs, &driver_attr_boards);
-	driver_remove_file(driverfs, &driver_attr_maxboards);
-	driver_remove_file(driverfs, &driver_attr_debug);
-	driver_remove_file(driverfs, &driver_attr_rawreadok);
-	driver_remove_file(driverfs, &driver_attr_pollrate);
-	driver_remove_file(driverfs, &driver_attr_pollcounter);
-	driver_remove_file(driverfs, &driver_attr_state);
-}
-
-
-#define DGAP_VERIFY_BOARD(p, bd)			\
-	if (!p)						\
-		return (0);				\
-							\
-	bd = dev_get_drvdata(p);			\
-	if (!bd || bd->magic != DGAP_BOARD_MAGIC)	\
-		return (0);				\
-	if (bd->state != BOARD_READY)			\
-		return (0);				\
-
-
-static ssize_t dgap_ports_state_show(struct device *p, struct device_attribute *attr, char *buf)
-{
-	struct board_t *bd;
-	int count = 0;
-	int i = 0;
-
-	DGAP_VERIFY_BOARD(p, bd);
-
-	for (i = 0; i < bd->nasync; i++) {
-		count += snprintf(buf + count, PAGE_SIZE - count,
-			"%d %s\n", bd->channels[i]->ch_portnum,
-			bd->channels[i]->ch_open_count ? "Open" : "Closed");
-	}
-	return count;
-}
-static DEVICE_ATTR(ports_state, S_IRUSR, dgap_ports_state_show, NULL);
-
-
-static ssize_t dgap_ports_baud_show(struct device *p, struct device_attribute *attr, char *buf)
-{
-	struct board_t *bd;
-	int count = 0;
-	int i = 0;
-
-	DGAP_VERIFY_BOARD(p, bd);
-
-	for (i = 0; i < bd->nasync; i++) {
-		count +=  snprintf(buf + count, PAGE_SIZE - count,
-			"%d %d\n", bd->channels[i]->ch_portnum, bd->channels[i]->ch_baud_info);
-	}
-	return count;
-}
-static DEVICE_ATTR(ports_baud, S_IRUSR, dgap_ports_baud_show, NULL);
-
-
-static ssize_t dgap_ports_msignals_show(struct device *p, struct device_attribute *attr, char *buf)
-{
-	struct board_t *bd;
-	int count = 0;
-	int i = 0;
-
-	DGAP_VERIFY_BOARD(p, bd);
-
-	for (i = 0; i < bd->nasync; i++) {
-		if (bd->channels[i]->ch_open_count) {
-			count += snprintf(buf + count, PAGE_SIZE - count,
-				"%d %s %s %s %s %s %s\n", bd->channels[i]->ch_portnum,
-				(bd->channels[i]->ch_mostat & UART_MCR_RTS) ? "RTS" : "",
-				(bd->channels[i]->ch_mistat & UART_MSR_CTS) ? "CTS" : "",
-				(bd->channels[i]->ch_mostat & UART_MCR_DTR) ? "DTR" : "",
-				(bd->channels[i]->ch_mistat & UART_MSR_DSR) ? "DSR" : "",
-				(bd->channels[i]->ch_mistat & UART_MSR_DCD) ? "DCD" : "",
-				(bd->channels[i]->ch_mistat & UART_MSR_RI)  ? "RI"  : "");
-		} else {
-			count += snprintf(buf + count, PAGE_SIZE - count,
-				"%d\n", bd->channels[i]->ch_portnum);
-		}
-	}
-	return count;
-}
-static DEVICE_ATTR(ports_msignals, S_IRUSR, dgap_ports_msignals_show, NULL);
-
-
-static ssize_t dgap_ports_iflag_show(struct device *p, struct device_attribute *attr, char *buf)
-{
-	struct board_t *bd;
-	int count = 0;
-	int i = 0;
-
-	DGAP_VERIFY_BOARD(p, bd);
-
-	for (i = 0; i < bd->nasync; i++) {
-		count += snprintf(buf + count, PAGE_SIZE - count, "%d %x\n",
-			bd->channels[i]->ch_portnum, bd->channels[i]->ch_c_iflag);
-	}
-	return count;
-}
-static DEVICE_ATTR(ports_iflag, S_IRUSR, dgap_ports_iflag_show, NULL);
-
-
-static ssize_t dgap_ports_cflag_show(struct device *p, struct device_attribute *attr, char *buf)
-{
-	struct board_t *bd;
-	int count = 0;
-	int i = 0;
-
-	DGAP_VERIFY_BOARD(p, bd);
-
-	for (i = 0; i < bd->nasync; i++) {
-		count += snprintf(buf + count, PAGE_SIZE - count, "%d %x\n",
-			bd->channels[i]->ch_portnum, bd->channels[i]->ch_c_cflag);
-	}
-	return count;
-}
-static DEVICE_ATTR(ports_cflag, S_IRUSR, dgap_ports_cflag_show, NULL);
-
-
-static ssize_t dgap_ports_oflag_show(struct device *p, struct device_attribute *attr, char *buf)
-{
-	struct board_t *bd;
-	int count = 0;
-	int i = 0;
-
-	DGAP_VERIFY_BOARD(p, bd);
-
-	for (i = 0; i < bd->nasync; i++) {
-		count += snprintf(buf + count, PAGE_SIZE - count, "%d %x\n",
-			bd->channels[i]->ch_portnum, bd->channels[i]->ch_c_oflag);
-	}
-	return count;
-}
-static DEVICE_ATTR(ports_oflag, S_IRUSR, dgap_ports_oflag_show, NULL);
-
-
-static ssize_t dgap_ports_lflag_show(struct device *p, struct device_attribute *attr, char *buf)
-{
-	struct board_t *bd;
-	int count = 0;
-	int i = 0;
-
-	DGAP_VERIFY_BOARD(p, bd);
-
-	for (i = 0; i < bd->nasync; i++) {
-		count += snprintf(buf + count, PAGE_SIZE - count, "%d %x\n",
-			bd->channels[i]->ch_portnum, bd->channels[i]->ch_c_lflag);
-	}
-	return count;
-}
-static DEVICE_ATTR(ports_lflag, S_IRUSR, dgap_ports_lflag_show, NULL);
-
-
-static ssize_t dgap_ports_digi_flag_show(struct device *p, struct device_attribute *attr, char *buf)
-{
-	struct board_t *bd;
-	int count = 0;
-	int i = 0;
-
-	DGAP_VERIFY_BOARD(p, bd);
-
-	for (i = 0; i < bd->nasync; i++) {
-		count += snprintf(buf + count, PAGE_SIZE - count, "%d %x\n",
-			bd->channels[i]->ch_portnum, bd->channels[i]->ch_digi.digi_flags);
-	}
-	return count;
-}
-static DEVICE_ATTR(ports_digi_flag, S_IRUSR, dgap_ports_digi_flag_show, NULL);
-
-
-static ssize_t dgap_ports_rxcount_show(struct device *p, struct device_attribute *attr, char *buf)
-{
-	struct board_t *bd;
-	int count = 0;
-	int i = 0;
-
-	DGAP_VERIFY_BOARD(p, bd);
-
-	for (i = 0; i < bd->nasync; i++) {
-		count += snprintf(buf + count, PAGE_SIZE - count, "%d %ld\n",
-			bd->channels[i]->ch_portnum, bd->channels[i]->ch_rxcount);
-	}
-	return count;
-}
-static DEVICE_ATTR(ports_rxcount, S_IRUSR, dgap_ports_rxcount_show, NULL);
-
-
-static ssize_t dgap_ports_txcount_show(struct device *p, struct device_attribute *attr, char *buf)
-{
-	struct board_t *bd;
-	int count = 0;
-	int i = 0;
-
-	DGAP_VERIFY_BOARD(p, bd);
-
-	for (i = 0; i < bd->nasync; i++) {
-		count += snprintf(buf + count, PAGE_SIZE - count, "%d %ld\n",
-			bd->channels[i]->ch_portnum, bd->channels[i]->ch_txcount);
-	}
-	return count;
-}
-static DEVICE_ATTR(ports_txcount, S_IRUSR, dgap_ports_txcount_show, NULL);
-
-
-/* this function creates the sys files that will export each signal status
- * to sysfs each value will be put in a separate filename
- */
-void dgap_create_ports_sysfiles(struct board_t *bd)
-{
-	int rc = 0;
-
-	dev_set_drvdata(&bd->pdev->dev, bd);
-	rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_state);
-	rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_baud);
-	rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_msignals);
-	rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_iflag);
-	rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_cflag);
-	rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_oflag);
-	rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_lflag);
-	rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_digi_flag);
-	rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_rxcount);
-	rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_txcount);
-	if (rc) {
-		printk(KERN_ERR "DGAP: sysfs device_create_file failed!\n");
-	}
-}
-
-
-/* removes all the sys files created for that port */
-void dgap_remove_ports_sysfiles(struct board_t *bd)
-{
-	device_remove_file(&(bd->pdev->dev), &dev_attr_ports_state);
-	device_remove_file(&(bd->pdev->dev), &dev_attr_ports_baud);
-	device_remove_file(&(bd->pdev->dev), &dev_attr_ports_msignals);
-	device_remove_file(&(bd->pdev->dev), &dev_attr_ports_iflag);
-	device_remove_file(&(bd->pdev->dev), &dev_attr_ports_cflag);
-	device_remove_file(&(bd->pdev->dev), &dev_attr_ports_oflag);
-	device_remove_file(&(bd->pdev->dev), &dev_attr_ports_lflag);
-	device_remove_file(&(bd->pdev->dev), &dev_attr_ports_digi_flag);
-	device_remove_file(&(bd->pdev->dev), &dev_attr_ports_rxcount);
-	device_remove_file(&(bd->pdev->dev), &dev_attr_ports_txcount);
-}
-
-
-static ssize_t dgap_tty_state_show(struct device *d, struct device_attribute *attr, char *buf)
-{
-	struct board_t *bd;
-	struct channel_t *ch;
-	struct un_t *un;
-
-	if (!d)
-		return (0);
-	un = dev_get_drvdata(d);
-	if (!un || un->magic != DGAP_UNIT_MAGIC)
-		return (0);
-	ch = un->un_ch;
-	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-		return (0);
-	bd = ch->ch_bd;
-	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
-		return (0);
-	if (bd->state != BOARD_READY)
-		return (0);
-
-	return snprintf(buf, PAGE_SIZE, "%s", un->un_open_count ? "Open" : "Closed");
-}
-static DEVICE_ATTR(state, S_IRUSR, dgap_tty_state_show, NULL);
-
-
-static ssize_t dgap_tty_baud_show(struct device *d, struct device_attribute *attr, char *buf)
-{
-	struct board_t *bd;
-	struct channel_t *ch;
-	struct un_t *un;
-
-	if (!d)
-		return (0);
-	un = dev_get_drvdata(d);
-	if (!un || un->magic != DGAP_UNIT_MAGIC)
-		return (0);
-	ch = un->un_ch;
-	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-		return (0);
-	bd = ch->ch_bd;
-	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
-		return (0);
-	if (bd->state != BOARD_READY)
-		return (0);
-
-	return snprintf(buf, PAGE_SIZE, "%d\n", ch->ch_baud_info);
-}
-static DEVICE_ATTR(baud, S_IRUSR, dgap_tty_baud_show, NULL);
-
-
-static ssize_t dgap_tty_msignals_show(struct device *d, struct device_attribute *attr, char *buf)
-{
-	struct board_t *bd;
-	struct channel_t *ch;
-	struct un_t *un;
-
-	if (!d)
-		return (0);
-	un = dev_get_drvdata(d);
-	if (!un || un->magic != DGAP_UNIT_MAGIC)
-		return (0);
-	ch = un->un_ch;
-	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-		return (0);
-	bd = ch->ch_bd;
-	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
-		return (0);
-	if (bd->state != BOARD_READY)
-		return (0);
-
-	if (ch->ch_open_count) {
-		return snprintf(buf, PAGE_SIZE, "%s %s %s %s %s %s\n",
-			(ch->ch_mostat & UART_MCR_RTS) ? "RTS" : "",
-			(ch->ch_mistat & UART_MSR_CTS) ? "CTS" : "",
-			(ch->ch_mostat & UART_MCR_DTR) ? "DTR" : "",
-			(ch->ch_mistat & UART_MSR_DSR) ? "DSR" : "",
-			(ch->ch_mistat & UART_MSR_DCD) ? "DCD" : "",
-			(ch->ch_mistat & UART_MSR_RI)  ? "RI"  : "");
-	}
-	return 0;
-}
-static DEVICE_ATTR(msignals, S_IRUSR, dgap_tty_msignals_show, NULL);
-
-
-static ssize_t dgap_tty_iflag_show(struct device *d, struct device_attribute *attr, char *buf)
-{
-	struct board_t *bd;
-	struct channel_t *ch;
-	struct un_t *un;
-
-	if (!d)
-		return (0);
-	un = dev_get_drvdata(d);
-	if (!un || un->magic != DGAP_UNIT_MAGIC)
-		return (0);
-	ch = un->un_ch;
-	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-		return (0);
-	bd = ch->ch_bd;
-	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
-		return (0);
-	if (bd->state != BOARD_READY)
-		return (0);
-
-	return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_c_iflag);
-}
-static DEVICE_ATTR(iflag, S_IRUSR, dgap_tty_iflag_show, NULL);
-
-
-static ssize_t dgap_tty_cflag_show(struct device *d, struct device_attribute *attr, char *buf)
-{
-	struct board_t *bd;
-	struct channel_t *ch;
-	struct un_t *un;
-
-	if (!d)
-		return (0);
-	un = dev_get_drvdata(d);
-	if (!un || un->magic != DGAP_UNIT_MAGIC)
-		return (0);
-	ch = un->un_ch;
-	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-		return (0);
-	bd = ch->ch_bd;
-	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
-		return (0);
-	if (bd->state != BOARD_READY)
-		return (0);
-
-	return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_c_cflag);
-}
-static DEVICE_ATTR(cflag, S_IRUSR, dgap_tty_cflag_show, NULL);
-
-
-static ssize_t dgap_tty_oflag_show(struct device *d, struct device_attribute *attr, char *buf)
-{
-	struct board_t *bd;
-	struct channel_t *ch;
-	struct un_t *un;
-
-	if (!d)
-		return (0);
-	un = dev_get_drvdata(d);
-	if (!un || un->magic != DGAP_UNIT_MAGIC)
-		return (0);
-	ch = un->un_ch;
-	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-		return (0);
-	bd = ch->ch_bd;
-	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
-		return (0);
-	if (bd->state != BOARD_READY)
-		return (0);
-
-	return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_c_oflag);
-}
-static DEVICE_ATTR(oflag, S_IRUSR, dgap_tty_oflag_show, NULL);
-
-
-static ssize_t dgap_tty_lflag_show(struct device *d, struct device_attribute *attr, char *buf)
-{
-	struct board_t *bd;
-	struct channel_t *ch;
-	struct un_t *un;
-
-	if (!d)
-		return (0);
-	un = dev_get_drvdata(d);
-	if (!un || un->magic != DGAP_UNIT_MAGIC)
-		return (0);
-	ch = un->un_ch;
-	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-		return (0);
-	bd = ch->ch_bd;
-	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
-		return (0);
-	if (bd->state != BOARD_READY)
-		return (0);
-
-	return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_c_lflag);
-}
-static DEVICE_ATTR(lflag, S_IRUSR, dgap_tty_lflag_show, NULL);
-
-
-static ssize_t dgap_tty_digi_flag_show(struct device *d, struct device_attribute *attr, char *buf)
-{
-	struct board_t *bd;
-	struct channel_t *ch;
-	struct un_t *un;
-
-	if (!d)
-		return (0);
-	un = dev_get_drvdata(d);
-	if (!un || un->magic != DGAP_UNIT_MAGIC)
-		return (0);
-	ch = un->un_ch;
-	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-		return (0);
-	bd = ch->ch_bd;
-	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
-		return (0);
-	if (bd->state != BOARD_READY)
-		return (0);
-
-	return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_digi.digi_flags);
-}
-static DEVICE_ATTR(digi_flag, S_IRUSR, dgap_tty_digi_flag_show, NULL);
-
-
-static ssize_t dgap_tty_rxcount_show(struct device *d, struct device_attribute *attr, char *buf)
-{
-	struct board_t *bd;
-	struct channel_t *ch;
-	struct un_t *un;
-
-	if (!d)
-		return (0);
-	un = dev_get_drvdata(d);
-	if (!un || un->magic != DGAP_UNIT_MAGIC)
-		return (0);
-	ch = un->un_ch;
-	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-		return (0);
-	bd = ch->ch_bd;
-	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
-		return (0);
-	if (bd->state != BOARD_READY)
-		return (0);
-
-	return snprintf(buf, PAGE_SIZE, "%ld\n", ch->ch_rxcount);
-}
-static DEVICE_ATTR(rxcount, S_IRUSR, dgap_tty_rxcount_show, NULL);
-
-
-static ssize_t dgap_tty_txcount_show(struct device *d, struct device_attribute *attr, char *buf)
-{
-	struct board_t *bd;
-	struct channel_t *ch;
-	struct un_t *un;
-
-	if (!d)
-		return (0);
-	un = dev_get_drvdata(d);
-	if (!un || un->magic != DGAP_UNIT_MAGIC)
-		return (0);
-	ch = un->un_ch;
-	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-		return (0);
-	bd = ch->ch_bd;
-	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
-		return (0);
-	if (bd->state != BOARD_READY)
-		return (0);
-
-	return snprintf(buf, PAGE_SIZE, "%ld\n", ch->ch_txcount);
-}
-static DEVICE_ATTR(txcount, S_IRUSR, dgap_tty_txcount_show, NULL);
-
-
-static ssize_t dgap_tty_name_show(struct device *d, struct device_attribute *attr, char *buf)
-{
-	struct board_t *bd;
-	struct channel_t *ch;
-	struct un_t *un;
-	int	cn;
-	int	bn;
-	struct cnode *cptr = NULL;
-	int found = FALSE;
-	int ncount = 0;
-	int starto = 0;
-	int i = 0;
-
-	if (!d)
-		return (0);
-	un = dev_get_drvdata(d);
-	if (!un || un->magic != DGAP_UNIT_MAGIC)
-		return (0);
-	ch = un->un_ch;
-	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-		return (0);
-	bd = ch->ch_bd;
-	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
-		return (0);
-	if (bd->state != BOARD_READY)
-		return (0);
-
-        bn = bd->boardnum;
-	cn = ch->ch_portnum;
-
-	for (cptr = bd->bd_config; cptr; cptr = cptr->next) {
-
-		if ((cptr->type == BNODE) &&
-		    ((cptr->u.board.type == APORT2_920P) || (cptr->u.board.type == APORT4_920P) ||
-		     (cptr->u.board.type == APORT8_920P) || (cptr->u.board.type == PAPORT4) ||
-		     (cptr->u.board.type == PAPORT8))) {
-
-				found = TRUE;
-				if (cptr->u.board.v_start)
-					starto = cptr->u.board.start;
-				else
-					starto = 1;
-		}
-
-		if (cptr->type == TNODE && found == TRUE) {
-			char *ptr1;
-			if (strstr(cptr->u.ttyname, "tty")) {
-				ptr1 = cptr->u.ttyname;
-				ptr1 += 3;
-			}
-			else {
-				ptr1 = cptr->u.ttyname;
-			}
-
-			for (i = 0; i < dgap_config_get_number_of_ports(bd); i++) {
-				if (cn == i) {
-					return snprintf(buf, PAGE_SIZE, "%s%s%02d\n",
-						(un->un_type == DGAP_PRINT) ? "pr" : "tty",
-						ptr1, i + starto);
-				}
-			}
-		}
-
-		if (cptr->type == CNODE) {
-
-			for (i = 0; i < cptr->u.conc.nport; i++) {
-				if (cn == (i + ncount)) {
-
-					return snprintf(buf, PAGE_SIZE, "%s%s%02d\n",
-						(un->un_type == DGAP_PRINT) ? "pr" : "tty",
-						cptr->u.conc.id,
-						i + (cptr->u.conc.v_start ? cptr->u.conc.start : 1));
-				}
-			}
-
-			ncount += cptr->u.conc.nport;
-		}
-
-		if (cptr->type == MNODE) {
-
-			for (i = 0; i < cptr->u.module.nport; i++) {
-				if (cn == (i + ncount)) {
-					return snprintf(buf, PAGE_SIZE, "%s%s%02d\n",
-						(un->un_type == DGAP_PRINT) ? "pr" : "tty",
-						cptr->u.module.id,
-						i + (cptr->u.module.v_start ? cptr->u.module.start : 1));
-				}
-			}
-
-			ncount += cptr->u.module.nport;
-
-		}
-	}
-
-	return snprintf(buf, PAGE_SIZE, "%s_dgap_%d_%d\n",
-		(un->un_type == DGAP_PRINT) ? "pr" : "tty", bn, cn);
-
-}
-static DEVICE_ATTR(custom_name, S_IRUSR, dgap_tty_name_show, NULL);
-
-
-static struct attribute *dgap_sysfs_tty_entries[] = {
-	&dev_attr_state.attr,
-	&dev_attr_baud.attr,
-	&dev_attr_msignals.attr,
-	&dev_attr_iflag.attr,
-	&dev_attr_cflag.attr,
-	&dev_attr_oflag.attr,
-	&dev_attr_lflag.attr,
-	&dev_attr_digi_flag.attr,
-	&dev_attr_rxcount.attr,
-	&dev_attr_txcount.attr,
-	&dev_attr_custom_name.attr,
-	NULL
-};
-
-
-static struct attribute_group dgap_tty_attribute_group = {
-	.name = NULL,
-	.attrs = dgap_sysfs_tty_entries,
-};
-
-
-
-
-void dgap_create_tty_sysfs(struct un_t *un, struct device *c)
-{
-	int ret;
-
-	ret = sysfs_create_group(&c->kobj, &dgap_tty_attribute_group);
-	if (ret) {
-		printk(KERN_ERR "dgap: failed to create sysfs tty device attributes.\n");
-		sysfs_remove_group(&c->kobj, &dgap_tty_attribute_group);
-		return;
-	}
-
-	dev_set_drvdata(c, un);
-
-}
-
-
-void dgap_remove_tty_sysfs(struct device *c)
-{
-	sysfs_remove_group(&c->kobj, &dgap_tty_attribute_group);
-}
diff --git a/drivers/staging/dgap/dgap_sysfs.h b/drivers/staging/dgap/dgap_sysfs.h
deleted file mode 100644
index 151f1b3..0000000
--- a/drivers/staging/dgap/dgap_sysfs.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright 2003 Digi International (www.digi.com)
- *	Scott H Kilau <Scott_Kilau at digi dot com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
- * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- * PURPOSE.  See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- *	NOTE: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!!
- */
-
-#ifndef __DGAP_SYSFS_H
-#define __DGAP_SYSFS_H
-
-#include "dgap_driver.h"
-
-#include <linux/device.h>
-
-struct board_t;
-struct channel_t;
-struct un_t;
-struct pci_driver;
-struct class_device;
-
-extern void dgap_create_ports_sysfiles(struct board_t *bd);
-extern void dgap_remove_ports_sysfiles(struct board_t *bd);
-
-extern void dgap_create_driver_sysfiles(struct pci_driver *);
-extern void dgap_remove_driver_sysfiles(struct pci_driver *);
-
-extern int dgap_tty_class_init(void);
-extern int dgap_tty_class_destroy(void);
-
-extern void dgap_create_tty_sysfs(struct un_t *un, struct device *c);
-extern void dgap_remove_tty_sysfs(struct device *c);
-
-
-#endif
diff --git a/drivers/staging/dgap/dgap_trace.c b/drivers/staging/dgap/dgap_trace.c
deleted file mode 100644
index a53db9e..0000000
--- a/drivers/staging/dgap/dgap_trace.c
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * Copyright 2003 Digi International (www.digi.com)
- *	Scott H Kilau <Scott_Kilau at digi dot com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
- * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- * PURPOSE.  See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- *
- *	NOTE TO LINUX KERNEL HACKERS:  DO NOT REFORMAT THIS CODE!
- *
- *	This is shared code between Digi's CVS archive and the
- *	Linux Kernel sources.
- *	Changing the source just for reformatting needlessly breaks
- *	our CVS diff history.
- *
- *	Send any bug fixes/changes to:  Eng.Linux at digi dot com.
- *	Thank you.
- *
- */
-
-/* $Id: dgap_trace.c,v 1.1 2009/10/23 14:01:57 markh Exp $ */
-
-#include <linux/kernel.h>
-#include <linux/sched.h>	/* For jiffies, task states */
-#include <linux/interrupt.h>	/* For tasklet and interrupt structs/defines */
-#include <linux/vmalloc.h>
-
-#include "dgap_driver.h"
-#include "dgap_trace.h"
-
-#define TRC_TO_CONSOLE 1
-
-/* file level globals */
-static char *dgap_trcbuf;		/* the ringbuffer */
-
-#if defined(TRC_TO_KMEM)
-static int dgap_trcbufi = 0;		/* index of the tilde at the end of */
-#endif
-
-extern int dgap_trcbuf_size;		/* size of the ringbuffer */
-
-#if defined(TRC_TO_KMEM)
-static DEFINE_SPINLOCK(dgap_tracef_lock);
-#endif
-
-#if 0
-
-#if !defined(TRC_TO_KMEM) && !defined(TRC_TO_CONSOLE)
-void dgap_tracef(const char *fmt, ...)
-{
-	return;
-}
-
-#else /* !defined(TRC_TO_KMEM) && !defined(TRC_TO_CONSOLE) */
-
-void dgap_tracef(const char *fmt, ...)
-{
-	va_list	         ap;
-	char  	         buf[TRC_MAXMSG+1];
-	size_t		 lenbuf;
-	int		 i;
-	static int	 failed = FALSE;
-# if defined(TRC_TO_KMEM)
-	unsigned long	 flags;
-#endif
-
-	if(failed)
-		return;
-# if defined(TRC_TO_KMEM)
-	DGAP_LOCK(dgap_tracef_lock, flags);
-#endif
-
-	/* Format buf using fmt and arguments contained in ap. */
-	va_start(ap, fmt);
-	i = vsprintf(buf, fmt,  ap);
-	va_end(ap);
-	lenbuf = strlen(buf);
-
-# if defined(TRC_TO_KMEM)
-	{
-		static int	 initd=0;
-
-		/*
-		 * Now, in addition to (or instead of) printing this stuff out
-		 * (which is a buffered operation), also tuck it away into a
-		 * corner of memory which can be examined post-crash in kdb.
-		 */
-		if (!initd) {
-			dgap_trcbuf = (char *) vmalloc(dgap_trcbuf_size);
-			if(!dgap_trcbuf) {
-				failed = TRUE;
-				printk("dgap: tracing init failed!\n");
-				return;
-			}
-
-			memset(dgap_trcbuf, '\0',  dgap_trcbuf_size);
-			dgap_trcbufi = 0;
-			initd++;
-
-			printk("dgap: tracing enabled - " TRC_DTRC
-				" 0x%lx 0x%x\n",
-				(unsigned long)dgap_trcbuf,
-				dgap_trcbuf_size);
-		}
-
-#  if defined(TRC_ON_OVERFLOW_WRAP_AROUND)
-		/*
-		 * This is the less CPU-intensive way to do things.  We simply
-		 * wrap around before we fall off the end of the buffer.  A
-		 * tilde (~) demarcates the current end of the trace.
-		 *
-		 * This method should be used if you are concerned about race
-		 * conditions as it is less likely to affect the timing of
-		 * things.
-		 */
-
-		if (dgap_trcbufi + lenbuf >= dgap_trcbuf_size) {
-			/* We are wrapping, so wipe out the last tilde. */
-			dgap_trcbuf[dgap_trcbufi] = '\0';
-			/* put the new string at the beginning of the buffer */
-			dgap_trcbufi = 0;
-		}
-
-		strcpy(&dgap_trcbuf[dgap_trcbufi], buf);
-		dgap_trcbufi += lenbuf;
-		dgap_trcbuf[dgap_trcbufi] = '~';
-
-#  elif defined(TRC_ON_OVERFLOW_SHIFT_BUFFER)
-		/*
-		 * This is the more CPU-intensive way to do things.  If we
-		 * venture into the last 1/8 of the buffer, we shift the
-		 * last 7/8 of the buffer forward, wiping out the first 1/8.
-		 * Advantage: No wrap-around, only truncation from the
-		 * beginning.
-		 *
-		 * This method should not be used if you are concerned about
-		 * timing changes affecting the behaviour of the driver (ie,
-		 * race conditions).
-		 */
-		strcpy(&dgap_trcbuf[dgap_trcbufi], buf);
-		dgap_trcbufi += lenbuf;
-		dgap_trcbuf[dgap_trcbufi] = '~';
-		dgap_trcbuf[dgap_trcbufi+1] = '\0';
-
-		/* If we're near the end of the trace buffer... */
-		if (dgap_trcbufi > (dgap_trcbuf_size/8)*7) {
-			/* Wipe out the first eighth to make some more room. */
-			strcpy(dgap_trcbuf, &dgap_trcbuf[dgap_trcbuf_size/8]);
-			dgap_trcbufi = strlen(dgap_trcbuf)-1;
-			/* Plop overflow message at the top of the buffer. */
-			bcopy(TRC_OVERFLOW, dgap_trcbuf, strlen(TRC_OVERFLOW));
-		}
-#  else
-#   error "TRC_ON_OVERFLOW_WRAP_AROUND or TRC_ON_OVERFLOW_SHIFT_BUFFER?"
-#  endif
-	}
-	DGAP_UNLOCK(dgap_tracef_lock, flags);
-
-# endif /* defined(TRC_TO_KMEM) */
-}
-
-#endif /* !defined(TRC_TO_KMEM) && !defined(TRC_TO_CONSOLE) */
-
-#endif
-
-/*
- * dgap_tracer_free()
- *
- *
- */
-void dgap_tracer_free(void)
-{
-	if(dgap_trcbuf)
-		vfree(dgap_trcbuf);
-}
diff --git a/drivers/staging/dgap/dgap_trace.h b/drivers/staging/dgap/dgap_trace.h
deleted file mode 100644
index b21f461..0000000
--- a/drivers/staging/dgap/dgap_trace.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright 2003 Digi International (www.digi.com)
- *	Scott H Kilau <Scott_Kilau at digi dot com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
- * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- * PURPOSE.  See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- *	NOTE: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!!
- *
- *****************************************************************************
- * Header file for dgap_trace.c
- *
- * $Id: dgap_trace.h,v 1.1 2009/10/23 14:01:57 markh Exp $
- */
-
-#ifndef __DGAP_TRACE_H
-#define __DGAP_TRACE_H
-
-#include "dgap_driver.h"
-
-void dgap_tracef(const char *fmt, ...);
-void dgap_tracer_free(void);
-
-#endif
-
diff --git a/drivers/staging/dgap/dgap_tty.c b/drivers/staging/dgap/dgap_tty.c
deleted file mode 100644
index 565319f..0000000
--- a/drivers/staging/dgap/dgap_tty.c
+++ /dev/null
@@ -1,3556 +0,0 @@
-/*
- * Copyright 2003 Digi International (www.digi.com)
- *	Scott H Kilau <Scott_Kilau at digi dot com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
- * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- * PURPOSE.  See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- *
- *	NOTE TO LINUX KERNEL HACKERS:  DO NOT REFORMAT THIS CODE!
- *
- *	This is shared code between Digi's CVS archive and the
- *	Linux Kernel sources.
- *	Changing the source just for reformatting needlessly breaks
- *	our CVS diff history.
- *
- *	Send any bug fixes/changes to:  Eng.Linux at digi dot com.
- *	Thank you.
- */
-
-/************************************************************************
- *
- * This file implements the tty driver functionality for the
- * FEP5 based product lines.
- *
- ************************************************************************
- *
- * $Id: dgap_tty.c,v 1.3 2011/06/23 12:11:31 markh Exp $
- */
-
-#include <linux/kernel.h>
-#include <linux/sched.h>	/* For jiffies, task states */
-#include <linux/interrupt.h>	/* For tasklet and interrupt structs/defines */
-#include <linux/module.h>
-#include <linux/ctype.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/serial_reg.h>
-#include <linux/slab.h>
-#include <linux/delay.h>	/* For udelay */
-#include <asm/uaccess.h>	/* For copy_from_user/copy_to_user */
-#include <asm/io.h>		/* For read[bwl]/write[bwl] */
-#include <linux/pci.h>
-
-#include "dgap_driver.h"
-#include "dgap_tty.h"
-#include "dgap_types.h"
-#include "dgap_fep5.h"
-#include "dgap_parse.h"
-#include "dgap_conf.h"
-#include "dgap_sysfs.h"
-
-#define init_MUTEX(sem)         sema_init(sem, 1)
-#define DECLARE_MUTEX(name)     \
-        struct semaphore name = __SEMAPHORE_INITIALIZER(name, 1)
-
-/*
- * internal variables
- */
-static struct board_t	*dgap_BoardsByMajor[256];
-static uchar		*dgap_TmpWriteBuf = NULL;
-static DECLARE_MUTEX(dgap_TmpWriteSem);
-
-/*
- * Default transparent print information.
- */
-static struct digi_t dgap_digi_init = {
-	.digi_flags =	DIGI_COOK,	/* Flags			*/
-	.digi_maxcps =	100,		/* Max CPS			*/
-	.digi_maxchar =	50,		/* Max chars in print queue	*/
-	.digi_bufsize =	100,		/* Printer buffer size		*/
-	.digi_onlen =	4,		/* size of printer on string	*/
-	.digi_offlen =	4,		/* size of printer off string	*/
-	.digi_onstr =	"\033[5i",	/* ANSI printer on string ]	*/
-	.digi_offstr =	"\033[4i",	/* ANSI printer off string ]	*/
-	.digi_term =	"ansi"		/* default terminal type	*/
-};
-
-
-/*
- * Define a local default termios struct. All ports will be created
- * with this termios initially.
- *
- * This defines a raw port at 9600 baud, 8 data bits, no parity,
- * 1 stop bit.
- */
-
-static struct ktermios DgapDefaultTermios =
-{
-	.c_iflag =	(DEFAULT_IFLAGS),	/* iflags */
-	.c_oflag =	(DEFAULT_OFLAGS),	/* oflags */
-	.c_cflag =	(DEFAULT_CFLAGS),	/* cflags */
-	.c_lflag =	(DEFAULT_LFLAGS),	/* lflags */
-	.c_cc =		INIT_C_CC,
-	.c_line = 	0,
-};
-
-/* Our function prototypes */
-static int dgap_tty_open(struct tty_struct *tty, struct file *file);
-static void dgap_tty_close(struct tty_struct *tty, struct file *file);
-static int dgap_block_til_ready(struct tty_struct *tty, struct file *file, struct channel_t *ch);
-static int dgap_tty_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg);
-static int dgap_tty_digigeta(struct tty_struct *tty, struct digi_t __user *retinfo);
-static int dgap_tty_digiseta(struct tty_struct *tty, struct digi_t __user *new_info);
-static int dgap_tty_digigetedelay(struct tty_struct *tty, int __user *retinfo);
-static int dgap_tty_digisetedelay(struct tty_struct *tty, int __user *new_info);
-static int dgap_tty_write_room(struct tty_struct* tty);
-static int dgap_tty_chars_in_buffer(struct tty_struct* tty);
-static void dgap_tty_start(struct tty_struct *tty);
-static void dgap_tty_stop(struct tty_struct *tty);
-static void dgap_tty_throttle(struct tty_struct *tty);
-static void dgap_tty_unthrottle(struct tty_struct *tty);
-static void dgap_tty_flush_chars(struct tty_struct *tty);
-static void dgap_tty_flush_buffer(struct tty_struct *tty);
-static void dgap_tty_hangup(struct tty_struct *tty);
-static int dgap_wait_for_drain(struct tty_struct *tty);
-static int dgap_set_modem_info(struct tty_struct *tty, unsigned int command, unsigned int __user *value);
-static int dgap_get_modem_info(struct channel_t *ch, unsigned int __user *value);
-static int dgap_tty_digisetcustombaud(struct tty_struct *tty, int __user *new_info);
-static int dgap_tty_digigetcustombaud(struct tty_struct *tty, int __user *retinfo);
-static int dgap_tty_tiocmget(struct tty_struct *tty);
-static int dgap_tty_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear);
-static int dgap_tty_send_break(struct tty_struct *tty, int msec);
-static void dgap_tty_wait_until_sent(struct tty_struct *tty, int timeout);
-static int dgap_tty_write(struct tty_struct *tty, const unsigned char *buf, int count);
-static void dgap_tty_set_termios(struct tty_struct *tty, struct ktermios *old_termios);
-static int dgap_tty_put_char(struct tty_struct *tty, unsigned char c);
-static void dgap_tty_send_xchar(struct tty_struct *tty, char ch);
-
-static const struct tty_operations dgap_tty_ops = {
-	.open = dgap_tty_open,
-	.close = dgap_tty_close,
-	.write = dgap_tty_write,
-	.write_room = dgap_tty_write_room,
-	.flush_buffer = dgap_tty_flush_buffer,
-	.chars_in_buffer = dgap_tty_chars_in_buffer,
-	.flush_chars = dgap_tty_flush_chars,
-	.ioctl = dgap_tty_ioctl,
-	.set_termios = dgap_tty_set_termios,
-	.stop = dgap_tty_stop,
-	.start = dgap_tty_start,
-	.throttle = dgap_tty_throttle,
-	.unthrottle = dgap_tty_unthrottle,
-	.hangup = dgap_tty_hangup,
-	.put_char = dgap_tty_put_char,
-	.tiocmget = dgap_tty_tiocmget,
-	.tiocmset = dgap_tty_tiocmset,
-	.break_ctl = dgap_tty_send_break,
-	.wait_until_sent = dgap_tty_wait_until_sent,
-	.send_xchar = dgap_tty_send_xchar
-};
-
-
-
-
-
-/************************************************************************
- *
- * TTY Initialization/Cleanup Functions
- *
- ************************************************************************/
-
-/*
- * dgap_tty_preinit()
- *
- * Initialize any global tty related data before we download any boards.
- */
-int dgap_tty_preinit(void)
-{
-	unsigned long flags;
-
-	DGAP_LOCK(dgap_global_lock, flags);
-
-	/*
-	 * Allocate a buffer for doing the copy from user space to
-	 * kernel space in dgap_input().  We only use one buffer and
-	 * control access to it with a semaphore.  If we are paging, we
-	 * are already in trouble so one buffer won't hurt much anyway.
-	 */
-	dgap_TmpWriteBuf = kmalloc(WRITEBUFLEN, GFP_ATOMIC);
-
-	if (!dgap_TmpWriteBuf) {
-		DGAP_UNLOCK(dgap_global_lock, flags);
-		DPR_INIT(("unable to allocate tmp write buf"));
-		return (-ENOMEM);
-	}
-
-        DGAP_UNLOCK(dgap_global_lock, flags);
-        return(0);
-}
-
-
-/*
- * dgap_tty_register()
- *
- * Init the tty subsystem for this board.
- */
-int dgap_tty_register(struct board_t *brd)
-{
-	int rc = 0;
-
-	DPR_INIT(("tty_register start"));
-
-	brd->SerialDriver = alloc_tty_driver(MAXPORTS);
-
-	snprintf(brd->SerialName, MAXTTYNAMELEN, "tty_dgap_%d_", brd->boardnum);
-	brd->SerialDriver->name = brd->SerialName;
-	brd->SerialDriver->name_base = 0;
-	brd->SerialDriver->major = 0;
-	brd->SerialDriver->minor_start = 0;
-	brd->SerialDriver->type = TTY_DRIVER_TYPE_SERIAL;
-	brd->SerialDriver->subtype = SERIAL_TYPE_NORMAL;
-	brd->SerialDriver->init_termios = DgapDefaultTermios;
-	brd->SerialDriver->driver_name = DRVSTR;
-	brd->SerialDriver->flags = (TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV | TTY_DRIVER_HARDWARE_BREAK);
-
-	/* The kernel wants space to store pointers to tty_structs */
-	brd->SerialDriver->ttys = kzalloc(MAXPORTS * sizeof(struct tty_struct *), GFP_KERNEL);
-	if (!brd->SerialDriver->ttys)
-		return(-ENOMEM);
-
-	/*
-	 * Entry points for driver.  Called by the kernel from
-	 * tty_io.c and n_tty.c.
-	 */
-	tty_set_operations(brd->SerialDriver, &dgap_tty_ops);
-
-	/*
-	 * If we're doing transparent print, we have to do all of the above
-	 * again, separately so we don't get the LD confused about what major
-	 * we are when we get into the dgap_tty_open() routine.
-	 */
-	brd->PrintDriver = alloc_tty_driver(MAXPORTS);
-
-	snprintf(brd->PrintName, MAXTTYNAMELEN, "pr_dgap_%d_", brd->boardnum);
-	brd->PrintDriver->name = brd->PrintName;
-	brd->PrintDriver->name_base = 0;
-	brd->PrintDriver->major = 0;
-	brd->PrintDriver->minor_start = 0;
-	brd->PrintDriver->type = TTY_DRIVER_TYPE_SERIAL;
-	brd->PrintDriver->subtype = SERIAL_TYPE_NORMAL;
-	brd->PrintDriver->init_termios = DgapDefaultTermios;
-	brd->PrintDriver->driver_name = DRVSTR;
-	brd->PrintDriver->flags = (TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV | TTY_DRIVER_HARDWARE_BREAK);
-
-	/* The kernel wants space to store pointers to tty_structs */
-	brd->PrintDriver->ttys = kzalloc(MAXPORTS * sizeof(struct tty_struct *), GFP_KERNEL);
-	if (!brd->PrintDriver->ttys)
-		return(-ENOMEM);
-
-	/*
-	 * Entry points for driver.  Called by the kernel from
-	 * tty_io.c and n_tty.c.
-	 */
-	tty_set_operations(brd->PrintDriver, &dgap_tty_ops);
-
-	if (!brd->dgap_Major_Serial_Registered) {
-		/* Register tty devices */
-		rc = tty_register_driver(brd->SerialDriver);
-		if (rc < 0) {
-			APR(("Can't register tty device (%d)\n", rc));
-			return(rc);
-		}
-		brd->dgap_Major_Serial_Registered = TRUE;
-		dgap_BoardsByMajor[brd->SerialDriver->major] = brd;
-		brd->dgap_Serial_Major = brd->SerialDriver->major;
-	}
-
-	if (!brd->dgap_Major_TransparentPrint_Registered) {
-		/* Register Transparent Print devices */
- 		rc = tty_register_driver(brd->PrintDriver);
-		if (rc < 0) {
-			APR(("Can't register Transparent Print device (%d)\n", rc));
-			return(rc);
-		}
-		brd->dgap_Major_TransparentPrint_Registered = TRUE;
-		dgap_BoardsByMajor[brd->PrintDriver->major] = brd;
-		brd->dgap_TransparentPrint_Major = brd->PrintDriver->major;
-	}
-
-	DPR_INIT(("DGAP REGISTER TTY: MAJORS: %d %d\n", brd->SerialDriver->major,
-		brd->PrintDriver->major));
-
-	return (rc);
-}
-
-
-/*
- * dgap_tty_init()
- *
- * Init the tty subsystem.  Called once per board after board has been
- * downloaded and init'ed.
- */
-int dgap_tty_init(struct board_t *brd)
-{
-	int i;
-	int tlw;
-	uint true_count = 0;
-	uchar *vaddr;
-	uchar modem = 0;
-	struct channel_t *ch;
-	struct bs_t *bs;
-	struct cm_t *cm;
-
-	if (!brd)
-		return (-ENXIO);
-
-	DPR_INIT(("dgap_tty_init start\n"));
-
-	/*
-	 * Initialize board structure elements.
-	 */
-
-	vaddr = brd->re_map_membase;
-	true_count = readw((vaddr + NCHAN));
-
-	brd->nasync = dgap_config_get_number_of_ports(brd);
-
-	if (!brd->nasync) {
-		brd->nasync = brd->maxports;
-	}
-
-	if (brd->nasync > brd->maxports) {
-		brd->nasync = brd->maxports;
-	}
-
-	if (true_count != brd->nasync) {
-		if ((brd->type == PPCM) && (true_count == 64)) {
-			APR(("***WARNING**** %s configured for %d ports, has %d ports.\nPlease make SURE the EBI cable running from the card\nto each EM module is plugged into EBI IN!\n",
-				brd->name, brd->nasync, true_count));
-		}
-		else if ((brd->type == PPCM) && (true_count == 0)) {
-			APR(("***WARNING**** %s configured for %d ports, has %d ports.\nPlease make SURE the EBI cable running from the card\nto each EM module is plugged into EBI IN!\n",
-				brd->name, brd->nasync, true_count));
-		}
-		else {
-			APR(("***WARNING**** %s configured for %d ports, has %d ports.\n",
-				brd->name, brd->nasync, true_count));
-		}
-
-		brd->nasync = true_count;
-
-		/* If no ports, don't bother going any further */
-		if (!brd->nasync) {
-			brd->state = BOARD_FAILED;
-			brd->dpastatus = BD_NOFEP;
-			return(-ENXIO);
-		}
-	}
-
-	/*
-	 * Allocate channel memory that might not have been allocated
-	 * when the driver was first loaded.
-	 */
-	for (i = 0; i < brd->nasync; i++) {
-		if (!brd->channels[i]) {
-			brd->channels[i] = kzalloc(sizeof(struct channel_t), GFP_ATOMIC);
-			if (!brd->channels[i]) {
-				DPR_CORE(("%s:%d Unable to allocate memory for channel struct\n",
-				    __FILE__, __LINE__));
-			}
-		}
-	}
-
-	ch = brd->channels[0];
-	vaddr = brd->re_map_membase;
-
-	bs = (struct bs_t *) ((ulong) vaddr + CHANBUF);
-	cm = (struct cm_t *) ((ulong) vaddr + CMDBUF);
-
-	brd->bd_bs = bs;
-
-	/* Set up channel variables */
-	for (i = 0; i < brd->nasync; i++, ch = brd->channels[i], bs++) {
-
-		if (!brd->channels[i])
-			continue;
-
-		DGAP_SPINLOCK_INIT(ch->ch_lock);
-
-		/* Store all our magic numbers */
-		ch->magic = DGAP_CHANNEL_MAGIC;
-		ch->ch_tun.magic = DGAP_UNIT_MAGIC;
-		ch->ch_tun.un_type = DGAP_SERIAL;
-		ch->ch_tun.un_ch = ch;
-		ch->ch_tun.un_dev = i;
-
-		ch->ch_pun.magic = DGAP_UNIT_MAGIC;
-		ch->ch_pun.un_type = DGAP_PRINT;
-		ch->ch_pun.un_ch = ch;
-		ch->ch_pun.un_dev = i;
-
-		ch->ch_vaddr = vaddr;
-		ch->ch_bs = bs;
-		ch->ch_cm = cm;
-		ch->ch_bd = brd;
-		ch->ch_portnum = i;
-		ch->ch_digi = dgap_digi_init;
-
-		/*
-		 * Set up digi dsr and dcd bits based on altpin flag.
-		 */
-		if (dgap_config_get_altpin(brd)) {
-			ch->ch_dsr	= DM_CD;
-			ch->ch_cd	= DM_DSR;
-			ch->ch_digi.digi_flags |= DIGI_ALTPIN;
-		}
-		else {
-			ch->ch_cd	= DM_CD;
-			ch->ch_dsr	= DM_DSR;
-		}
-
-		ch->ch_taddr = vaddr + ((ch->ch_bs->tx_seg) << 4);
-		ch->ch_raddr = vaddr + ((ch->ch_bs->rx_seg) << 4);
-		ch->ch_tx_win = 0;
-		ch->ch_rx_win = 0;
-		ch->ch_tsize = readw(&(ch->ch_bs->tx_max)) + 1;
-		ch->ch_rsize = readw(&(ch->ch_bs->rx_max)) + 1;
-		ch->ch_tstart = 0;
-		ch->ch_rstart = 0;
-
-		/* .25 second delay */
-		ch->ch_close_delay = 250;
-
-		/*
-		 * Set queue water marks, interrupt mask,
-		 * and general tty parameters.
-		 */
-		ch->ch_tlw = tlw = ch->ch_tsize >= 2000 ? ((ch->ch_tsize * 5) / 8) : ch->ch_tsize / 2;
-
-		dgap_cmdw(ch, STLOW, tlw, 0);
-
-		dgap_cmdw(ch, SRLOW, ch->ch_rsize / 2, 0);
-
-		dgap_cmdw(ch, SRHIGH, 7 * ch->ch_rsize / 8, 0);
-
-		ch->ch_mistat = readb(&(ch->ch_bs->m_stat));
-
-		init_waitqueue_head(&ch->ch_flags_wait);
-		init_waitqueue_head(&ch->ch_tun.un_flags_wait);
-		init_waitqueue_head(&ch->ch_pun.un_flags_wait);
-		init_waitqueue_head(&ch->ch_sniff_wait);
-
-		/* Turn on all modem interrupts for now */
-		modem = (DM_CD | DM_DSR | DM_CTS | DM_RI);
-		writeb(modem, &(ch->ch_bs->m_int));
-
-		/*
-		 * Set edelay to 0 if interrupts are turned on,
-		 * otherwise set edelay to the usual 100.
-		 */
-		if (brd->intr_used)
-			writew(0, &(ch->ch_bs->edelay));
-		else
-			writew(100, &(ch->ch_bs->edelay));
-
-		writeb(1, &(ch->ch_bs->idata));
-	}
-
-
-	DPR_INIT(("dgap_tty_init finish\n"));
-
-	return (0);
-}
-
-
-/*
- * dgap_tty_post_uninit()
- *
- * UnInitialize any global tty related data.
- */
-void dgap_tty_post_uninit(void)
-{
-	kfree(dgap_TmpWriteBuf);
-	dgap_TmpWriteBuf = NULL;
-}
-
-
-/*
- * dgap_tty_uninit()
- *
- * Uninitialize the TTY portion of this driver.  Free all memory and
- * resources.
- */
-void dgap_tty_uninit(struct board_t *brd)
-{
-	int i = 0;
-
-	if (brd->dgap_Major_Serial_Registered) {
-		dgap_BoardsByMajor[brd->SerialDriver->major] = NULL;
-		brd->dgap_Serial_Major = 0;
-		for (i = 0; i < brd->nasync; i++) {
-			dgap_remove_tty_sysfs(brd->channels[i]->ch_tun.un_sysfs);
-			tty_unregister_device(brd->SerialDriver, i);
-		}
-		tty_unregister_driver(brd->SerialDriver);
-		kfree(brd->SerialDriver->ttys);
-		brd->SerialDriver->ttys = NULL;
-		put_tty_driver(brd->SerialDriver);
-		brd->dgap_Major_Serial_Registered = FALSE;
-	}
-
-	if (brd->dgap_Major_TransparentPrint_Registered) {
-		dgap_BoardsByMajor[brd->PrintDriver->major] = NULL;
-		brd->dgap_TransparentPrint_Major = 0;
-		for (i = 0; i < brd->nasync; i++) {
-			dgap_remove_tty_sysfs(brd->channels[i]->ch_pun.un_sysfs);
-			tty_unregister_device(brd->PrintDriver, i);
-		}
-		tty_unregister_driver(brd->PrintDriver);
-		kfree(brd->PrintDriver->ttys);
-		brd->PrintDriver->ttys = NULL;
-		put_tty_driver(brd->PrintDriver);
-		brd->dgap_Major_TransparentPrint_Registered = FALSE;
-	}
-}
-
-
-#define TMPBUFLEN (1024)
-
-/*
- * dgap_sniff - Dump data out to the "sniff" buffer if the
- * proc sniff file is opened...
- */
-static void dgap_sniff_nowait_nolock(struct channel_t *ch, uchar *text, uchar *buf, int len)
-{
-	struct timeval tv;
-	int n;
-	int r;
-	int nbuf;
-	int i;
-	int tmpbuflen;
-	char tmpbuf[TMPBUFLEN];
-	char *p = tmpbuf;
-	int too_much_data;
-
-	/* Leave if sniff not open */
-	if (!(ch->ch_sniff_flags & SNIFF_OPEN))
-		return;
-
-	do_gettimeofday(&tv);
-
-	/* Create our header for data dump */
-	p += sprintf(p, "<%ld %ld><%s><", tv.tv_sec, tv.tv_usec, text);
-	tmpbuflen = p - tmpbuf;
-
-	do {
-		too_much_data = 0;
-
-		for (i = 0; i < len && tmpbuflen < (TMPBUFLEN - 4); i++) {
-			p += sprintf(p, "%02x ", *buf);
-			buf++;
-			tmpbuflen = p - tmpbuf;
-		}
-
-		if (tmpbuflen < (TMPBUFLEN - 4)) {
-			if (i > 0)
-				p += sprintf(p - 1, "%s\n", ">");
-			else
-				p += sprintf(p, "%s\n", ">");
-		} else {
-			too_much_data = 1;
-			len -= i;
-		}
-
-		nbuf = strlen(tmpbuf);
-		p = tmpbuf;
-
-		/*
-		 *  Loop while data remains.
-		 */
-		while (nbuf > 0 && ch->ch_sniff_buf) {
-			/*
-			 *  Determine the amount of available space left in the
-			 *  buffer.  If there's none, wait until some appears.
-			 */
-			n = (ch->ch_sniff_out - ch->ch_sniff_in - 1) & SNIFF_MASK;
-
-			/*
-			 * If there is no space left to write to in our sniff buffer,
-			 * we have no choice but to drop the data.
-			 * We *cannot* sleep here waiting for space, because this
-			 * function was probably called by the interrupt/timer routines!
-			 */
-			if (n == 0) {
-				return;
-			}
-
-			/*
-			 * Copy as much data as will fit.
-			 */
-
-			if (n > nbuf)
-				n = nbuf;
-
-			r = SNIFF_MAX - ch->ch_sniff_in;
-
-			if (r <= n) {
-				memcpy(ch->ch_sniff_buf + ch->ch_sniff_in, p, r);
-
-				n -= r;
-				ch->ch_sniff_in = 0;
-				p += r;
-				nbuf -= r;
-			}
-
-			memcpy(ch->ch_sniff_buf + ch->ch_sniff_in, p, n);
-
-			ch->ch_sniff_in += n;
-			p += n;
-			nbuf -= n;
-
-			/*
-			 *  Wakeup any thread waiting for data
-			 */
-			if (ch->ch_sniff_flags & SNIFF_WAIT_DATA) {
-				ch->ch_sniff_flags &= ~SNIFF_WAIT_DATA;
-				wake_up_interruptible(&ch->ch_sniff_wait);
-			}
-		}
-
-		/*
-		 * If the user sent us too much data to push into our tmpbuf,
-		 * we need to keep looping around on all the data.
-		 */
-		if (too_much_data) {
-			p = tmpbuf;
-			tmpbuflen = 0;
-		}
-
-	} while (too_much_data);
-}
-
-
-/*=======================================================================
- *
- *      dgap_input - Process received data.
- *
- *              ch      - Pointer to channel structure.
- *
- *=======================================================================*/
-
-void dgap_input(struct channel_t *ch)
-{
-	struct board_t *bd;
-	struct bs_t	*bs;
-	struct tty_struct *tp;
-	struct tty_ldisc *ld;
-	uint	rmask;
-	uint	head;
-	uint	tail;
-	int	data_len;
-	ulong	lock_flags;
-	ulong   lock_flags2;
-	int flip_len;
-	int len = 0;
-	int n = 0;
-	uchar *buf;
-	uchar tmpchar;
-	int s = 0;
-
-	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-		return;
-
-	tp = ch->ch_tun.un_tty;
-
-	bs  = ch->ch_bs;
-	if (!bs) {
-		return;
-	}
-
-	bd = ch->ch_bd;
-	if(!bd || bd->magic != DGAP_BOARD_MAGIC)
-		return;
-
-	DPR_READ(("dgap_input start\n"));
-
-	DGAP_LOCK(bd->bd_lock, lock_flags);
-	DGAP_LOCK(ch->ch_lock, lock_flags2);
-
-	/*
-	 *      Figure the number of characters in the buffer.
-	 *      Exit immediately if none.
-	 */
-
-	rmask = ch->ch_rsize - 1;
-
-	head = readw(&(bs->rx_head));
-	head &= rmask;
-	tail = readw(&(bs->rx_tail));
-	tail &= rmask;
-
-	data_len = (head - tail) & rmask;
-
-	if (data_len == 0) {
-		writeb(1, &(bs->idata));
-		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-		DGAP_UNLOCK(bd->bd_lock, lock_flags);
-		DPR_READ(("No data on port %d\n", ch->ch_portnum));
-		return;
-	}
-
-	/*
-	 * If the device is not open, or CREAD is off, flush
-	 * input data and return immediately.
-	 */
-	if ((bd->state != BOARD_READY) || !tp  || (tp->magic != TTY_MAGIC) ||
-            !(ch->ch_tun.un_flags & UN_ISOPEN) || !(tp->termios.c_cflag & CREAD) ||
-	    (ch->ch_tun.un_flags & UN_CLOSING)) {
-
-		DPR_READ(("input. dropping %d bytes on port %d...\n", data_len, ch->ch_portnum));
-		DPR_READ(("input. tp: %p tp->magic: %x MAGIC:%x ch flags: %x\n",
-			tp, tp ? tp->magic : 0, TTY_MAGIC, ch->ch_tun.un_flags));
-		writew(head, &(bs->rx_tail));
-		writeb(1, &(bs->idata));
-		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-		DGAP_UNLOCK(bd->bd_lock, lock_flags);
-		return;
-	}
-
-	/*
-	 * If we are throttled, simply don't read any data.
-	 */
-	if (ch->ch_flags & CH_RXBLOCK) {
-		writeb(1, &(bs->idata));
-		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-		DGAP_UNLOCK(bd->bd_lock, lock_flags);
-		DPR_READ(("Port %d throttled, not reading any data. head: %x tail: %x\n",
-			ch->ch_portnum, head, tail));
-		return;
-	}
-
-	/*
-	 *      Ignore oruns.
-	 */
-	tmpchar = readb(&(bs->orun));
-	if (tmpchar) {
-		ch->ch_err_overrun++;
-		writeb(0, &(bs->orun));
-	}
-
-	DPR_READ(("dgap_input start 2\n"));
-
-	/* Decide how much data we can send into the tty layer */
-	flip_len = TTY_FLIPBUF_SIZE;
-
-	/* Chop down the length, if needed */
-	len = min(data_len, flip_len);
-	len = min(len, (N_TTY_BUF_SIZE - 1));
-
-	ld = tty_ldisc_ref(tp);
-
-#ifdef TTY_DONT_FLIP
-	/*
-	 * If the DONT_FLIP flag is on, don't flush our buffer, and act
-	 * like the ld doesn't have any space to put the data right now.
-	 */
-	if (test_bit(TTY_DONT_FLIP, &tp->flags))
-		len = 0;
-#endif
-
-	/*
-	 * If we were unable to get a reference to the ld,
-	 * don't flush our buffer, and act like the ld doesn't
-	 * have any space to put the data right now.
-	 */
-	if (!ld) {
-		len = 0;
-	} else {
-		/*
-		 * If ld doesn't have a pointer to a receive_buf function,
-		 * flush the data, then act like the ld doesn't have any
-		 * space to put the data right now.
-		 */
-		if (!ld->ops->receive_buf) {
-			writew(head, &(bs->rx_tail));
-			len = 0;
-		}
-	}
-
-	if (len <= 0) {
-		writeb(1, &(bs->idata));
-		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-		DGAP_UNLOCK(bd->bd_lock, lock_flags);
-		DPR_READ(("dgap_input 1 - finish\n"));
-		if (ld)
-			tty_ldisc_deref(ld);
-		return;
-	}
-
-	buf = ch->ch_bd->flipbuf;
-	n = len;
-
-	/*
-	 * n now contains the most amount of data we can copy,
-	 * bounded either by our buffer size or the amount
-	 * of data the card actually has pending...
-	 */
-	while (n) {
-
-		s = ((head >= tail) ? head : ch->ch_rsize) - tail;
-		s = min(s, n);
-
-		if (s <= 0)
-			break;
-
-		memcpy_fromio(buf, (char *) ch->ch_raddr + tail, s);
-		dgap_sniff_nowait_nolock(ch, "USER READ", buf, s);
-
-		tail += s;
-		buf += s;
-
-		n -= s;
-		/* Flip queue if needed */
-		tail &= rmask;
-	}
-
-	writew(tail, &(bs->rx_tail));
-	writeb(1, &(bs->idata));
-	ch->ch_rxcount += len;
-
-	/*
-	 * If we are completely raw, we don't need to go through a lot
-	 * of the tty layers that exist.
-	 * In this case, we take the shortest and fastest route we
-	 * can to relay the data to the user.
-	 *
-	 * On the other hand, if we are not raw, we need to go through
-	 * the tty layer, which has its API more well defined.
-	 */
-	if (I_PARMRK(tp) || I_BRKINT(tp) || I_INPCK(tp)) {
-		dgap_parity_scan(ch, ch->ch_bd->flipbuf, ch->ch_bd->flipflagbuf, &len);
-
-		len = tty_buffer_request_room(tp->port, len);
-		tty_insert_flip_string_flags(tp->port, ch->ch_bd->flipbuf,
-			ch->ch_bd->flipflagbuf, len);
-	}
-	else {
-		len = tty_buffer_request_room(tp->port, len);
-		tty_insert_flip_string(tp->port, ch->ch_bd->flipbuf, len);
-	}
-
-	DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-	DGAP_UNLOCK(bd->bd_lock, lock_flags);
-
-	/* Tell the tty layer its okay to "eat" the data now */
-	tty_flip_buffer_push(tp->port);
-
-	if (ld)
-		tty_ldisc_deref(ld);
-
-	DPR_READ(("dgap_input - finish\n"));
-}
-
-
-/************************************************************************
- * Determines when CARRIER changes state and takes appropriate
- * action.
- ************************************************************************/
-void dgap_carrier(struct channel_t *ch)
-{
-	struct board_t *bd;
-
-        int virt_carrier = 0;
-        int phys_carrier = 0;
-
-	DPR_CARR(("dgap_carrier called...\n"));
-
-	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-		return;
-
-	bd = ch->ch_bd;
-
-	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
-		return;
-
-	/* Make sure altpin is always set correctly */
-	if (ch->ch_digi.digi_flags & DIGI_ALTPIN) {
-		ch->ch_dsr      = DM_CD;
-		ch->ch_cd       = DM_DSR;
-	}
-	else {
-		ch->ch_dsr      = DM_DSR;
-		ch->ch_cd       = DM_CD;
-	}
-
-	if (ch->ch_mistat & D_CD(ch)) {
-		DPR_CARR(("mistat: %x  D_CD: %x\n", ch->ch_mistat, D_CD(ch)));
-		phys_carrier = 1;
-	}
-
-	if (ch->ch_digi.digi_flags & DIGI_FORCEDCD) {
-		virt_carrier = 1;
-	}
-
-	if (ch->ch_c_cflag & CLOCAL) {
-		virt_carrier = 1;
-	}
-
-
-	DPR_CARR(("DCD: physical: %d virt: %d\n", phys_carrier, virt_carrier));
-
-	/*
-	 * Test for a VIRTUAL carrier transition to HIGH.
-	 */
-	if (((ch->ch_flags & CH_FCAR) == 0) && (virt_carrier == 1)) {
-
-		/*
-		 * When carrier rises, wake any threads waiting
-		 * for carrier in the open routine.
-		 */
-
-		DPR_CARR(("carrier: virt DCD rose\n"));
-
-		if (waitqueue_active(&(ch->ch_flags_wait)))
-			wake_up_interruptible(&ch->ch_flags_wait);
-	}
-
-	/*
-	 * Test for a PHYSICAL carrier transition to HIGH.
-	 */
-	if (((ch->ch_flags & CH_CD) == 0) && (phys_carrier == 1)) {
-
-		/*
-		 * When carrier rises, wake any threads waiting
-		 * for carrier in the open routine.
-		 */
-
-		DPR_CARR(("carrier: physical DCD rose\n"));
-
-		if (waitqueue_active(&(ch->ch_flags_wait)))
-			wake_up_interruptible(&ch->ch_flags_wait);
-	}
-
-	/*
-	 *  Test for a PHYSICAL transition to low, so long as we aren't
-	 *  currently ignoring physical transitions (which is what "virtual
-	 *  carrier" indicates).
-	 *
-	 *  The transition of the virtual carrier to low really doesn't
-	 *  matter... it really only means "ignore carrier state", not
-	 *  "make pretend that carrier is there".
-	 */
-	if ((virt_carrier == 0) && ((ch->ch_flags & CH_CD) != 0) &&
-	    (phys_carrier == 0))
-	{
-
-		/*
-		 *   When carrier drops:
-		 *
-		 *   Drop carrier on all open units.
-		 *
-		 *   Flush queues, waking up any task waiting in the
-		 *   line discipline.
-		 *
-		 *   Send a hangup to the control terminal.
-		 *
-		 *   Enable all select calls.
-		 */
-		if (waitqueue_active(&(ch->ch_flags_wait)))
-			wake_up_interruptible(&ch->ch_flags_wait);
-
-		if (ch->ch_tun.un_open_count > 0) {
-			DPR_CARR(("Sending tty hangup\n"));
-			tty_hangup(ch->ch_tun.un_tty);
-		}
-
-		if (ch->ch_pun.un_open_count > 0) {
-			DPR_CARR(("Sending pr hangup\n"));
-			tty_hangup(ch->ch_pun.un_tty);
-		}
-	}
-
-	/*
-	 *  Make sure that our cached values reflect the current reality.
-	 */
-	if (virt_carrier == 1)
-		ch->ch_flags |= CH_FCAR;
-	else
-		ch->ch_flags &= ~CH_FCAR;
-
-	if (phys_carrier == 1)
-		ch->ch_flags |= CH_CD;
-	else
-		ch->ch_flags &= ~CH_CD;
-}
-
-
-/************************************************************************
- *
- * TTY Entry points and helper functions
- *
- ************************************************************************/
-
-/*
- * dgap_tty_open()
- *
- */
-static int dgap_tty_open(struct tty_struct *tty, struct file *file)
-{
-	struct board_t	*brd;
-	struct channel_t *ch;
-	struct un_t	*un;
-	struct bs_t	*bs;
-	uint		major = 0;
-	uint		minor = 0;
-	int		rc = 0;
-	ulong		lock_flags;
-	ulong		lock_flags2;
-	u16		head;
-
-	rc = 0;
-
-	major = MAJOR(tty_devnum(tty));
-	minor = MINOR(tty_devnum(tty));
-
-	if (major > 255) {
-		return -ENXIO;
-	}
-
-	/* Get board pointer from our array of majors we have allocated */
-	brd = dgap_BoardsByMajor[major];
-	if (!brd) {
-		return -ENXIO;
-	}
-
-	/*
-	 * If board is not yet up to a state of READY, go to
-	 * sleep waiting for it to happen or they cancel the open.
-	 */
-	rc = wait_event_interruptible(brd->state_wait,
-		(brd->state & BOARD_READY));
-
-	if (rc) {
-		return rc;
-	}
-
-	DGAP_LOCK(brd->bd_lock, lock_flags);
-
-	/* The wait above should guarantee this cannot happen */
-	if (brd->state != BOARD_READY) {
-		DGAP_UNLOCK(brd->bd_lock, lock_flags);
-		return -ENXIO;
-	}
-
-	/* If opened device is greater than our number of ports, bail. */
-	if (MINOR(tty_devnum(tty)) > brd->nasync) {
-		DGAP_UNLOCK(brd->bd_lock, lock_flags);
-		return -ENXIO;
-	}
-
-	ch = brd->channels[minor];
-	if (!ch) {
-		DGAP_UNLOCK(brd->bd_lock, lock_flags);
-		return -ENXIO;
-	}
-
-	/* Grab channel lock */
-	DGAP_LOCK(ch->ch_lock, lock_flags2);
-
-	/* Figure out our type */
-	if (major == brd->dgap_Serial_Major) {
-		un = &brd->channels[minor]->ch_tun;
-		un->un_type = DGAP_SERIAL;
-	}
-	else if (major == brd->dgap_TransparentPrint_Major) {
-		un = &brd->channels[minor]->ch_pun;
-		un->un_type = DGAP_PRINT;
-	}
-	else {
-		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-		DGAP_UNLOCK(brd->bd_lock, lock_flags);
-		DPR_OPEN(("%d Unknown TYPE!\n", __LINE__));
-		return -ENXIO;
-	}
-
-	/* Store our unit into driver_data, so we always have it available. */
-	tty->driver_data = un;
-
-	DPR_OPEN(("Open called. MAJOR: %d MINOR:%d unit: %p NAME: %s\n",
-		MAJOR(tty_devnum(tty)), MINOR(tty_devnum(tty)), un, brd->name));
-
-	/*
-	 * Error if channel info pointer is NULL.
-	 */
-	bs = ch->ch_bs;
-	if (!bs) {
-		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-		DGAP_UNLOCK(brd->bd_lock, lock_flags);
-		DPR_OPEN(("%d BS is 0!\n", __LINE__));
-		return -ENXIO;
-        }
-
-	DPR_OPEN(("%d: tflag=%x  pflag=%x\n", __LINE__, ch->ch_tun.un_flags, ch->ch_pun.un_flags));
-
-	/*
-	 * Initialize tty's
-	 */
-	if (!(un->un_flags & UN_ISOPEN)) {
-		/* Store important variables. */
-		un->un_tty     = tty;
-
-		/* Maybe do something here to the TTY struct as well? */
-	}
-
-	/*
-	 * Initialize if neither terminal or printer is open.
-	 */
-	if (!((ch->ch_tun.un_flags | ch->ch_pun.un_flags) & UN_ISOPEN)) {
-
-		DPR_OPEN(("dgap_open: initializing channel in open...\n"));
-
-		ch->ch_mforce = 0;
-		ch->ch_mval = 0;
-
-		/*
-		 * Flush input queue.
-		 */
-		head = readw(&(bs->rx_head));
-		writew(head, &(bs->rx_tail));
-
-		ch->ch_flags = 0;
-		ch->pscan_state = 0;
-		ch->pscan_savechar = 0;
-
-		ch->ch_c_cflag   = tty->termios.c_cflag;
-		ch->ch_c_iflag   = tty->termios.c_iflag;
-		ch->ch_c_oflag   = tty->termios.c_oflag;
-		ch->ch_c_lflag   = tty->termios.c_lflag;
-		ch->ch_startc = tty->termios.c_cc[VSTART];
-		ch->ch_stopc  = tty->termios.c_cc[VSTOP];
-
-		/* TODO: flush our TTY struct here? */
-	}
-
-	dgap_carrier(ch);
-	/*
-	 * Run param in case we changed anything
-	 */
-	dgap_param(tty);
-
-	/*
-	 * follow protocol for opening port
-	 */
-
-	DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-	DGAP_UNLOCK(brd->bd_lock, lock_flags);
-
-	rc = dgap_block_til_ready(tty, file, ch);
-
-	if (!un->un_tty) {
-		return -ENODEV;
-	}
-
-	if (rc) {
-		DPR_OPEN(("dgap_tty_open returning after dgap_block_til_ready "
-			"with %d\n", rc));
-	}
-
-	/* No going back now, increment our unit and channel counters */
-	DGAP_LOCK(ch->ch_lock, lock_flags);
-	ch->ch_open_count++;
-	un->un_open_count++;
-	un->un_flags |= (UN_ISOPEN);
-	DGAP_UNLOCK(ch->ch_lock, lock_flags);
-
-	DPR_OPEN(("dgap_tty_open finished\n"));
-	return (rc);
-}
-
-
-/*
- * dgap_block_til_ready()
- *
- * Wait for DCD, if needed.
- */
-static int dgap_block_til_ready(struct tty_struct *tty, struct file *file, struct channel_t *ch)
-{
-	int retval = 0;
-	struct un_t *un = NULL;
-	ulong   lock_flags;
-	uint	old_flags = 0;
-	int sleep_on_un_flags = 0;
-
-	if (!tty || tty->magic != TTY_MAGIC || !file || !ch || ch->magic != DGAP_CHANNEL_MAGIC) {
-		return (-ENXIO);
-	}
-
-	un = tty->driver_data;
-	if (!un || un->magic != DGAP_UNIT_MAGIC) {
-		return (-ENXIO);
-	}
-
-	DPR_OPEN(("dgap_block_til_ready - before block.\n"));
-
-	DGAP_LOCK(ch->ch_lock, lock_flags);
-
-	ch->ch_wopen++;
-
-	/* Loop forever */
-	while (1) {
-
-		sleep_on_un_flags = 0;
-
-		/*
-		 * If board has failed somehow during our sleep, bail with error.
-		 */
-		if (ch->ch_bd->state == BOARD_FAILED) {
-			retval = -ENXIO;
-			break;
-		}
-
-		/* If tty was hung up, break out of loop and set error. */
-		if (tty_hung_up_p(file)) {
-			retval = -EAGAIN;
-			break;
-		}
-
-		/*
-		 * If either unit is in the middle of the fragile part of close,
-		 * we just cannot touch the channel safely.
-		 * Go back to sleep, knowing that when the channel can be
-		 * touched safely, the close routine will signal the
-		 * ch_wait_flags to wake us back up.
-		 */
-		if (!((ch->ch_tun.un_flags | ch->ch_pun.un_flags) & UN_CLOSING)) {
-
-			/*
-			 * Our conditions to leave cleanly and happily:
-			 * 1) NONBLOCKING on the tty is set.
-			 * 2) CLOCAL is set.
-			 * 3) DCD (fake or real) is active.
-			 */
-
-			if (file->f_flags & O_NONBLOCK) {
-				break;
-			}
-
-			if (tty->flags & (1 << TTY_IO_ERROR)) {
-				break;
-			}
-
-			if (ch->ch_flags & CH_CD) {
-				DPR_OPEN(("%d: ch_flags: %x\n", __LINE__, ch->ch_flags));
-				break;
-			}
-
-			if (ch->ch_flags & CH_FCAR) {
-				DPR_OPEN(("%d: ch_flags: %x\n", __LINE__, ch->ch_flags));
-				break;
-			}
-		}
-		else {
-			sleep_on_un_flags = 1;
-		}
-
-		/*
-		 * If there is a signal pending, the user probably
-		 * interrupted (ctrl-c) us.
-		 * Leave loop with error set.
-		 */
-		if (signal_pending(current)) {
-			DPR_OPEN(("%d: signal pending...\n", __LINE__));
-			retval = -ERESTARTSYS;
-			break;
-		}
-
-		DPR_OPEN(("dgap_block_til_ready - blocking.\n"));
-
-		/*
-		 * Store the flags before we let go of channel lock
-		 */
-		if (sleep_on_un_flags)
-			old_flags = ch->ch_tun.un_flags | ch->ch_pun.un_flags;
-		else
-			old_flags = ch->ch_flags;
-
-		/*
-		 * Let go of channel lock before calling schedule.
-		 * Our poller will get any FEP events and wake us up when DCD
-		 * eventually goes active.
-		 */
-
-		DGAP_UNLOCK(ch->ch_lock, lock_flags);
-
-		DPR_OPEN(("Going to sleep on %s flags...\n",
-			(sleep_on_un_flags ? "un" : "ch")));
-
-		/*
-		 * Wait for something in the flags to change from the current value.
-		 */
-		if (sleep_on_un_flags) {
-			retval = wait_event_interruptible(un->un_flags_wait,
-				(old_flags != (ch->ch_tun.un_flags | ch->ch_pun.un_flags)));
-		}
-		else {
-			retval = wait_event_interruptible(ch->ch_flags_wait,
-				(old_flags != ch->ch_flags));
-		}
-
-		DPR_OPEN(("After sleep... retval: %x\n", retval));
-
-		/*
-		 * We got woken up for some reason.
-		 * Before looping around, grab our channel lock.
-		 */
-		DGAP_LOCK(ch->ch_lock, lock_flags);
-	}
-
-	ch->ch_wopen--;
-
-	DGAP_UNLOCK(ch->ch_lock, lock_flags);
-
-	DPR_OPEN(("dgap_block_til_ready - after blocking.\n"));
-
-	if (retval) {
-		DPR_OPEN(("dgap_block_til_ready - done. error. retval: %x\n", retval));
-		return(retval);
-	}
-
-	DPR_OPEN(("dgap_block_til_ready - done no error. jiffies: %lu\n", jiffies));
-
-	return(0);
-}
-
-
-/*
- * dgap_tty_hangup()
- *
- * Hangup the port.  Like a close, but don't wait for output to drain.
- */
-static void dgap_tty_hangup(struct tty_struct *tty)
-{
-	struct board_t	*bd;
-	struct channel_t *ch;
-	struct un_t	*un;
-
-	if (!tty || tty->magic != TTY_MAGIC)
-		return;
-
-	un = tty->driver_data;
-	if (!un || un->magic != DGAP_UNIT_MAGIC)
-		return;
-
-	ch = un->un_ch;
-	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-		return;
-
-	bd = ch->ch_bd;
-	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
-		return;
-
-	DPR_CLOSE(("dgap_hangup called. ch->ch_open_count: %d un->un_open_count: %d\n",
-		ch->ch_open_count, un->un_open_count));
-
-	/* flush the transmit queues */
-	dgap_tty_flush_buffer(tty);
-
-	DPR_CLOSE(("dgap_hangup finished. ch->ch_open_count: %d un->un_open_count: %d\n",
-		ch->ch_open_count, un->un_open_count));
-}
-
-
-
-/*
- * dgap_tty_close()
- *
- */
-static void dgap_tty_close(struct tty_struct *tty, struct file *file)
-{
-	struct ktermios *ts;
-	struct board_t *bd;
-	struct channel_t *ch;
-	struct un_t *un;
-	ulong lock_flags;
-	int rc = 0;
-
-	if (!tty || tty->magic != TTY_MAGIC)
-		return;
-
-	un = tty->driver_data;
-	if (!un || un->magic != DGAP_UNIT_MAGIC)
-		return;
-
-	ch = un->un_ch;
-	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-		return;
-
-	bd = ch->ch_bd;
-	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
-		return;
-
-	ts = &tty->termios;
-
-	DPR_CLOSE(("Close called\n"));
-
-	DGAP_LOCK(ch->ch_lock, lock_flags);
-
-	/*
-	 * Determine if this is the last close or not - and if we agree about
-	 * which type of close it is with the Line Discipline
-	 */
-	if ((tty->count == 1) && (un->un_open_count != 1)) {
-		/*
-		 * Uh, oh.  tty->count is 1, which means that the tty
-		 * structure will be freed.  un_open_count should always
-		 * be one in these conditions.  If it's greater than
-		 * one, we've got real problems, since it means the
-		 * serial port won't be shutdown.
-		 */
-		APR(("tty->count is 1, un open count is %d\n", un->un_open_count));
-		un->un_open_count = 1;
-	}
-
-	if (--un->un_open_count < 0) {
-		APR(("bad serial port open count of %d\n", un->un_open_count));
-		un->un_open_count = 0;
-	}
-
-	ch->ch_open_count--;
-
-	if (ch->ch_open_count && un->un_open_count) {
-		DPR_CLOSE(("dgap_tty_close: not last close ch: %d un:%d\n",
-			ch->ch_open_count, un->un_open_count));
-
-		DGAP_UNLOCK(ch->ch_lock, lock_flags);
-                return;
-        }
-
-	/* OK, its the last close on the unit */
-	DPR_CLOSE(("dgap_tty_close - last close on unit procedures\n"));
-
-	un->un_flags |= UN_CLOSING;
-
-	tty->closing = 1;
-
-	/*
-	 * Only officially close channel if count is 0 and
-         * DIGI_PRINTER bit is not set.
-	 */
-	if ((ch->ch_open_count == 0) && !(ch->ch_digi.digi_flags & DIGI_PRINTER)) {
-
-		ch->ch_flags &= ~(CH_RXBLOCK);
-
-		DGAP_UNLOCK(ch->ch_lock, lock_flags);
-
-		/* wait for output to drain */
-		/* This will also return if we take an interrupt */
-
-		DPR_CLOSE(("Calling wait_for_drain\n"));
-		rc = dgap_wait_for_drain(tty);
-		DPR_CLOSE(("After calling wait_for_drain\n"));
-
-		if (rc) {
-			DPR_BASIC(("dgap_tty_close - bad return: %d ", rc));
-		}
-
-		dgap_tty_flush_buffer(tty);
-		tty_ldisc_flush(tty);
-
-		DGAP_LOCK(ch->ch_lock, lock_flags);
-
-		tty->closing = 0;
-
-		/*
-		 * If we have HUPCL set, lower DTR and RTS
-		 */
-		if (ch->ch_c_cflag & HUPCL ) {
-			DPR_CLOSE(("Close. HUPCL set, dropping DTR/RTS\n"));
-			ch->ch_mostat &= ~(D_RTS(ch)|D_DTR(ch));
-			dgap_cmdb( ch, SMODEM, 0, D_DTR(ch)|D_RTS(ch), 0 );
-
-			/*
-			 * Go to sleep to ensure RTS/DTR
-			 * have been dropped for modems to see it.
-			 */
-			if (ch->ch_close_delay) {
-				DPR_CLOSE(("Close. Sleeping for RTS/DTR drop\n"));
-
-				DGAP_UNLOCK(ch->ch_lock, lock_flags);
-				dgap_ms_sleep(ch->ch_close_delay);
-				DGAP_LOCK(ch->ch_lock, lock_flags);
-
-				DPR_CLOSE(("Close. After sleeping for RTS/DTR drop\n"));
-			}
-		}
-
-		ch->pscan_state = 0;
-		ch->pscan_savechar = 0;
-		ch->ch_baud_info = 0;
-
-	}
-
-	/*
-	 * turn off print device when closing print device.
-	 */
-	if ((un->un_type == DGAP_PRINT)  && (ch->ch_flags & CH_PRON) ) {
-		dgap_wmove(ch, ch->ch_digi.digi_offstr,
-			(int) ch->ch_digi.digi_offlen);
-		ch->ch_flags &= ~CH_PRON;
-	}
-
-	un->un_tty = NULL;
-	un->un_flags &= ~(UN_ISOPEN | UN_CLOSING);
-	tty->driver_data = NULL;
-
-	DPR_CLOSE(("Close. Doing wakeups\n"));
-	wake_up_interruptible(&ch->ch_flags_wait);
-	wake_up_interruptible(&un->un_flags_wait);
-
-	DGAP_UNLOCK(ch->ch_lock, lock_flags);
-
-        DPR_BASIC(("dgap_tty_close - complete\n"));
-}
-
-
-/*
- * dgap_tty_chars_in_buffer()
- *
- * Return number of characters that have not been transmitted yet.
- *
- * This routine is used by the line discipline to determine if there
- * is data waiting to be transmitted/drained/flushed or not.
- */
-static int dgap_tty_chars_in_buffer(struct tty_struct *tty)
-{
-	struct board_t *bd = NULL;
-	struct channel_t *ch = NULL;
-	struct un_t *un = NULL;
-	struct bs_t *bs = NULL;
-	uchar tbusy;
-	uint chars = 0;
-	u16 thead, ttail, tmask, chead, ctail;
-	ulong   lock_flags = 0;
-	ulong   lock_flags2 = 0;
-
-	if (tty == NULL)
-		return(0);
-
-	un = tty->driver_data;
-	if (!un || un->magic != DGAP_UNIT_MAGIC)
-		return (0);
-
-	ch = un->un_ch;
-	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-		return (0);
-
-	bd = ch->ch_bd;
-	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
-		return (0);
-
-        bs = ch->ch_bs;
-	if (!bs)
-		return (0);
-
-	DGAP_LOCK(bd->bd_lock, lock_flags);
-	DGAP_LOCK(ch->ch_lock, lock_flags2);
-
-	tmask = (ch->ch_tsize - 1);
-
-	/* Get Transmit queue pointers */
-	thead = readw(&(bs->tx_head)) & tmask;
-	ttail = readw(&(bs->tx_tail)) & tmask;
-
-	/* Get tbusy flag */
-	tbusy = readb(&(bs->tbusy));
-
-	/* Get Command queue pointers */
-	chead = readw(&(ch->ch_cm->cm_head));
-	ctail = readw(&(ch->ch_cm->cm_tail));
-
-	DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-	DGAP_UNLOCK(bd->bd_lock, lock_flags);
-
-	/*
-	 * The only way we know for sure if there is no pending
-	 * data left to be transferred, is if:
-	 * 1) Transmit head and tail are equal (empty).
-	 * 2) Command queue head and tail are equal (empty).
-	 * 3) The "TBUSY" flag is 0. (Transmitter not busy).
- 	 */
-
-	if ((ttail == thead) && (tbusy == 0) && (chead == ctail)) {
-		chars = 0;
-	}
-	else {
-		if (thead >= ttail)
-			chars = thead - ttail;
-		else
-			chars = thead - ttail + ch->ch_tsize;
-		/*
-		 * Fudge factor here.
-		 * If chars is zero, we know that the command queue had
-		 * something in it or tbusy was set.  Because we cannot
-		 * be sure if there is still some data to be transmitted,
-		 * lets lie, and tell ld we have 1 byte left.
-		 */
-		if (chars == 0) {
-			/*
-			 * If TBUSY is still set, and our tx buffers are empty,
-			 * force the firmware to send me another wakeup after
-			 * TBUSY has been cleared.
-			 */
-			if (tbusy != 0) {
-				DGAP_LOCK(ch->ch_lock, lock_flags);
-				un->un_flags |= UN_EMPTY;
-				writeb(1, &(bs->iempty));
-				DGAP_UNLOCK(ch->ch_lock, lock_flags);
-			}
-			chars = 1;
-		}
-	}
-
- 	DPR_WRITE(("dgap_tty_chars_in_buffer. Port: %x - %d (head: %d tail: %d tsize: %d)\n",
-		ch->ch_portnum, chars, thead, ttail, ch->ch_tsize));
-        return(chars);
-}
-
-
-static int dgap_wait_for_drain(struct tty_struct *tty)
-{
-	struct channel_t *ch;
-	struct un_t *un;
-	struct bs_t *bs;
-	int ret = -EIO;
-	uint count = 1;
-	ulong   lock_flags = 0;
-
-	if (!tty || tty->magic != TTY_MAGIC)
-		return ret;
-
-	un = tty->driver_data;
-	if (!un || un->magic != DGAP_UNIT_MAGIC)
-		return ret;
-
-	ch = un->un_ch;
-	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-		return ret;
-
-        bs = ch->ch_bs;
-	if (!bs)
-		return ret;
-
-	ret = 0;
-
-	DPR_DRAIN(("dgap_wait_for_drain start\n"));
-
-	/* Loop until data is drained */
-	while (count != 0) {
-
-		count = dgap_tty_chars_in_buffer(tty);
-
-		if (count == 0)
-			break;
-
-		/* Set flag waiting for drain */
-		DGAP_LOCK(ch->ch_lock, lock_flags);
-		un->un_flags |= UN_EMPTY;
-		writeb(1, &(bs->iempty));
-		DGAP_UNLOCK(ch->ch_lock, lock_flags);
-
-		/* Go to sleep till we get woken up */
-		ret = wait_event_interruptible(un->un_flags_wait, ((un->un_flags & UN_EMPTY) == 0));
-		/* If ret is non-zero, user ctrl-c'ed us */
-		if (ret) {
-			break;
-		}
-	}
-
-	DGAP_LOCK(ch->ch_lock, lock_flags);
-	un->un_flags &= ~(UN_EMPTY);
-	DGAP_UNLOCK(ch->ch_lock, lock_flags);
-
-	DPR_DRAIN(("dgap_wait_for_drain finish\n"));
-	return (ret);
-}
-
-
-/*
- * dgap_maxcps_room
- *
- * Reduces bytes_available to the max number of characters
- * that can be sent currently given the maxcps value, and
- * returns the new bytes_available.  This only affects printer
- * output.
- */
-static int dgap_maxcps_room(struct tty_struct *tty, int bytes_available)
-{
-	struct channel_t *ch = NULL;
-	struct un_t *un = NULL;
-
-	if (tty == NULL)
-		return (bytes_available);
-
-	un = tty->driver_data;
-	if (!un || un->magic != DGAP_UNIT_MAGIC)
-		return (bytes_available);
-
-	ch = un->un_ch;
-	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-		return (bytes_available);
-
-	/*
-	 * If its not the Transparent print device, return
-	 * the full data amount.
-	 */
-	if (un->un_type != DGAP_PRINT)
-		return (bytes_available);
-
-	if (ch->ch_digi.digi_maxcps > 0 && ch->ch_digi.digi_bufsize > 0 ) {
-		int cps_limit = 0;
-		unsigned long current_time = jiffies;
-		unsigned long buffer_time = current_time +
-			(HZ * ch->ch_digi.digi_bufsize) / ch->ch_digi.digi_maxcps;
-
-		if (ch->ch_cpstime < current_time) {
-			/* buffer is empty */
-			ch->ch_cpstime = current_time;            /* reset ch_cpstime */
-			cps_limit = ch->ch_digi.digi_bufsize;
-		}
-		else if (ch->ch_cpstime < buffer_time) {
-			/* still room in the buffer */
-			cps_limit = ((buffer_time - ch->ch_cpstime) * ch->ch_digi.digi_maxcps) / HZ;
-		}
-		else {
-			/* no room in the buffer */
-			cps_limit = 0;
-		}
-
-		bytes_available = min(cps_limit, bytes_available);
-	}
-
-	return (bytes_available);
-}
-
-
-static inline void dgap_set_firmware_event(struct un_t *un, unsigned int event)
-{
-	struct channel_t *ch = NULL;
-	struct bs_t *bs = NULL;
-
-	if (!un || un->magic != DGAP_UNIT_MAGIC)
-		return;
-	ch = un->un_ch;
-	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-		return;
-        bs = ch->ch_bs;
-	if (!bs)
-		return;
-
-	if ((event & UN_LOW) != 0) {
-		if ((un->un_flags & UN_LOW) == 0) {
-			un->un_flags |= UN_LOW;
-			writeb(1, &(bs->ilow));
-		}
-	}
-	if ((event & UN_LOW) != 0) {
-		if ((un->un_flags & UN_EMPTY) == 0) {
-			un->un_flags |= UN_EMPTY;
-			writeb(1, &(bs->iempty));
-		}
-	}
-}
-
-
-/*
- * dgap_tty_write_room()
- *
- * Return space available in Tx buffer
- */
-static int dgap_tty_write_room(struct tty_struct *tty)
-{
-	struct channel_t *ch = NULL;
-	struct un_t *un = NULL;
-	struct bs_t *bs = NULL;
-	u16 head, tail, tmask;
-	int ret = 0;
-	ulong   lock_flags = 0;
-
-	if (tty == NULL || dgap_TmpWriteBuf == NULL)
-		return(0);
-
-	un = tty->driver_data;
-	if (!un || un->magic != DGAP_UNIT_MAGIC)
-		return (0);
-
-	ch = un->un_ch;
-	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-		return (0);
-
-        bs = ch->ch_bs;
-	if (!bs)
-		return (0);
-
-	DGAP_LOCK(ch->ch_lock, lock_flags);
-
-	tmask = ch->ch_tsize - 1;
-	head = readw(&(bs->tx_head)) & tmask;
-	tail = readw(&(bs->tx_tail)) & tmask;
-
-        if ((ret = tail - head - 1) < 0)
-                ret += ch->ch_tsize;
-
-	/* Limit printer to maxcps */
-	ret = dgap_maxcps_room(tty, ret);
-
-	/*
-	 * If we are printer device, leave space for
-	 * possibly both the on and off strings.
-	 */
-	if (un->un_type == DGAP_PRINT) {
-		if (!(ch->ch_flags & CH_PRON))
-			ret -= ch->ch_digi.digi_onlen;
-		ret -= ch->ch_digi.digi_offlen;
-	}
-	else {
-		if (ch->ch_flags & CH_PRON)
-			ret -= ch->ch_digi.digi_offlen;
-	}
-
-	if (ret < 0)
-		ret = 0;
-
-	/*
-	 * Schedule FEP to wake us up if needed.
-	 *
-	 * TODO:  This might be overkill...
-	 * Do we really need to schedule callbacks from the FEP
-	 * in every case?  Can we get smarter based on ret?
-	 */
-	dgap_set_firmware_event(un, UN_LOW | UN_EMPTY);
-	DGAP_UNLOCK(ch->ch_lock, lock_flags);
-
-	DPR_WRITE(("dgap_tty_write_room - %d tail: %d head: %d\n", ret, tail, head));
-
-        return(ret);
-}
-
-
-/*
- * dgap_tty_put_char()
- *
- * Put a character into ch->ch_buf
- *
- *      - used by the line discipline for OPOST processing
- */
-static int dgap_tty_put_char(struct tty_struct *tty, unsigned char c)
-{
-	/*
-	 * Simply call tty_write.
-	 */
-	DPR_WRITE(("dgap_tty_put_char called\n"));
-	dgap_tty_write(tty, &c, 1);
-	return 1;
-}
-
-
-/*
- * dgap_tty_write()
- *
- * Take data from the user or kernel and send it out to the FEP.
- * In here exists all the Transparent Print magic as well.
- */
-static int dgap_tty_write(struct tty_struct *tty, const unsigned char *buf, int count)
-{
-	struct channel_t *ch = NULL;
-	struct un_t *un = NULL;
-	struct bs_t *bs = NULL;
-	char *vaddr = NULL;
-	u16 head, tail, tmask, remain;
-	int bufcount = 0, n = 0;
-	int orig_count = 0;
-	ulong lock_flags;
-	int from_user = 0;
-
-	if (tty == NULL || dgap_TmpWriteBuf == NULL)
-		return(0);
-
-	un = tty->driver_data;
-	if (!un || un->magic != DGAP_UNIT_MAGIC)
-		return (0);
-
-	ch = un->un_ch;
-	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-		return(0);
-
-        bs = ch->ch_bs;
-	if (!bs)
-		return(0);
-
-	if (!count)
-		return(0);
-
-	DPR_WRITE(("dgap_tty_write: Port: %x tty=%p user=%d len=%d\n",
-		ch->ch_portnum, tty, from_user, count));
-
-	/*
-	 * Store original amount of characters passed in.
-	 * This helps to figure out if we should ask the FEP
-	 * to send us an event when it has more space available.
-	 */
-	orig_count = count;
-
-	DGAP_LOCK(ch->ch_lock, lock_flags);
-
-	/* Get our space available for the channel from the board */
-	tmask = ch->ch_tsize - 1;
-	head = readw(&(bs->tx_head)) & tmask;
-	tail = readw(&(bs->tx_tail)) & tmask;
-
-	if ((bufcount = tail - head - 1) < 0)
-		bufcount += ch->ch_tsize;
-
-	DPR_WRITE(("%d: bufcount: %x count: %x tail: %x head: %x tmask: %x\n",
-		__LINE__, bufcount, count, tail, head, tmask));
-
-	/*
-	 * Limit printer output to maxcps overall, with bursts allowed
-	 * up to bufsize characters.
-	 */
-	bufcount = dgap_maxcps_room(tty, bufcount);
-
-	/*
-	 * Take minimum of what the user wants to send, and the
-	 * space available in the FEP buffer.
-	 */
-	count = min(count, bufcount);
-
-	/*
-	 * Bail if no space left.
-	 */
-	if (count <= 0) {
-		dgap_set_firmware_event(un, UN_LOW | UN_EMPTY);
-		DGAP_UNLOCK(ch->ch_lock, lock_flags);
-		return(0);
-	}
-
-	/*
-	 * Output the printer ON string, if we are in terminal mode, but
-	 * need to be in printer mode.
-	 */
-	if ((un->un_type == DGAP_PRINT) && !(ch->ch_flags & CH_PRON)) {
-		dgap_wmove(ch, ch->ch_digi.digi_onstr,
-		    (int) ch->ch_digi.digi_onlen);
-		head = readw(&(bs->tx_head)) & tmask;
-		ch->ch_flags |= CH_PRON;
-	}
-
-	/*
-	 * On the other hand, output the printer OFF string, if we are
-	 * currently in printer mode, but need to output to the terminal.
-	 */
-	if ((un->un_type != DGAP_PRINT) && (ch->ch_flags & CH_PRON)) {
-		dgap_wmove(ch, ch->ch_digi.digi_offstr,
-			(int) ch->ch_digi.digi_offlen);
-		head = readw(&(bs->tx_head)) & tmask;
-		ch->ch_flags &= ~CH_PRON;
-	}
-
-	/*
-	 * If there is nothing left to copy, or I can't handle any more data, leave.
-	 */
-	if (count <= 0) {
-		dgap_set_firmware_event(un, UN_LOW | UN_EMPTY);
-		DGAP_UNLOCK(ch->ch_lock, lock_flags);
-		return(0);
-	}
-
-	if (from_user) {
-
-		count = min(count, WRITEBUFLEN);
-
-		DGAP_UNLOCK(ch->ch_lock, lock_flags);
-
-		/*
-		 * If data is coming from user space, copy it into a temporary
-		 * buffer so we don't get swapped out while doing the copy to
-		 * the board.
-		 */
-		/* we're allowed to block if it's from_user */
-		if (down_interruptible(&dgap_TmpWriteSem)) {
-			return (-EINTR);
-		}
-
-		if (copy_from_user(dgap_TmpWriteBuf, (const uchar __user *) buf, count)) {
-			up(&dgap_TmpWriteSem);
-			printk("Write: Copy from user failed!\n");
-			return -EFAULT;
-		}
-
-		DGAP_LOCK(ch->ch_lock, lock_flags);
-
-		buf = dgap_TmpWriteBuf;
-	}
-
-	n = count;
-
-	/*
-	 * If the write wraps over the top of the circular buffer,
-	 * move the portion up to the wrap point, and reset the
-	 * pointers to the bottom.
-	 */
-	remain = ch->ch_tstart + ch->ch_tsize - head;
-
-	if (n >= remain) {
-		n -= remain;
-		vaddr = ch->ch_taddr + head;
-
-		memcpy_toio(vaddr, (uchar *) buf, remain);
-		dgap_sniff_nowait_nolock(ch, "USER WRITE", (uchar *) buf, remain);
-
-		head = ch->ch_tstart;
-		buf += remain;
-	}
-
-	if (n > 0) {
-
-		/*
-		 * Move rest of data.
-		 */
-		vaddr = ch->ch_taddr + head;
-		remain = n;
-
-		memcpy_toio(vaddr, (uchar *) buf, remain);
-		dgap_sniff_nowait_nolock(ch, "USER WRITE", (uchar *) buf, remain);
-
-		head += remain;
-
-	}
-
-	if (count) {
-		ch->ch_txcount += count;
-		head &= tmask;
-		writew(head, &(bs->tx_head));
-	}
-
-
-	dgap_set_firmware_event(un, UN_LOW | UN_EMPTY);
-
-	/*
-	 * If this is the print device, and the
-	 * printer is still on, we need to turn it
-	 * off before going idle.  If the buffer is
-	 * non-empty, wait until it goes empty.
-	 * Otherwise turn it off right now.
-	 */
-	if ((un->un_type == DGAP_PRINT) && (ch->ch_flags & CH_PRON)) {
-		tail = readw(&(bs->tx_tail)) & tmask;
-
-		if (tail != head) {
-			un->un_flags |= UN_EMPTY;
-			writeb(1, &(bs->iempty));
-		}
-		else {
-			dgap_wmove(ch, ch->ch_digi.digi_offstr,
-				(int) ch->ch_digi.digi_offlen);
-			head = readw(&(bs->tx_head)) & tmask;
-			ch->ch_flags &= ~CH_PRON;
-		}
-	}
-
-	/* Update printer buffer empty time. */
-	if ((un->un_type == DGAP_PRINT) && (ch->ch_digi.digi_maxcps > 0)
-	    && (ch->ch_digi.digi_bufsize > 0)) {
-                ch->ch_cpstime += (HZ * count) / ch->ch_digi.digi_maxcps;
-	}
-
-	if (from_user) {
-		DGAP_UNLOCK(ch->ch_lock, lock_flags);
-		up(&dgap_TmpWriteSem);
-	}
-	else {
-		DGAP_UNLOCK(ch->ch_lock, lock_flags);
-	}
-
-	DPR_WRITE(("Write finished - Write %d bytes of %d.\n", count, orig_count));
-
-	return (count);
-}
-
-
-
-/*
- * Return modem signals to ld.
- */
-static int dgap_tty_tiocmget(struct tty_struct *tty)
-{
-	struct channel_t *ch;
-	struct un_t *un;
-	int result = -EIO;
-	uchar mstat = 0;
-	ulong lock_flags;
-
-	if (!tty || tty->magic != TTY_MAGIC)
-		return result;
-
-	un = tty->driver_data;
-	if (!un || un->magic != DGAP_UNIT_MAGIC)
-		return result;
-
-	ch = un->un_ch;
-	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-		return result;
-
-	DPR_IOCTL(("dgap_tty_tiocmget start\n"));
-
-	DGAP_LOCK(ch->ch_lock, lock_flags);
-
-	mstat = readb(&(ch->ch_bs->m_stat));
-        /* Append any outbound signals that might be pending... */
-        mstat |= ch->ch_mostat;
-
-	DGAP_UNLOCK(ch->ch_lock, lock_flags);
-
-	result = 0;
-
-	if (mstat & D_DTR(ch))
-		result |= TIOCM_DTR;
-	if (mstat & D_RTS(ch))
-		result |= TIOCM_RTS;
-	if (mstat & D_CTS(ch))
-		result |= TIOCM_CTS;
-	if (mstat & D_DSR(ch))
-		result |= TIOCM_DSR;
-	if (mstat & D_RI(ch))
-		result |= TIOCM_RI;
-	if (mstat & D_CD(ch))
-		result |= TIOCM_CD;
-
-	DPR_IOCTL(("dgap_tty_tiocmget finish\n"));
-
-	return result;
-}
-
-
-/*
- * dgap_tty_tiocmset()
- *
- * Set modem signals, called by ld.
- */
-
-static int dgap_tty_tiocmset(struct tty_struct *tty,
-                unsigned int set, unsigned int clear)
-{
-	struct board_t *bd;
-	struct channel_t *ch;
-	struct un_t *un;
-	int ret = -EIO;
-	ulong lock_flags;
-	ulong lock_flags2;
-
-	if (!tty || tty->magic != TTY_MAGIC)
-		return ret;
-
-	un = tty->driver_data;
-	if (!un || un->magic != DGAP_UNIT_MAGIC)
-		return ret;
-
-	ch = un->un_ch;
-	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-		return ret;
-
-	bd = ch->ch_bd;
-	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
-		return ret;
-
-	DPR_IOCTL(("dgap_tty_tiocmset start\n"));
-
-	DGAP_LOCK(bd->bd_lock, lock_flags);
-	DGAP_LOCK(ch->ch_lock, lock_flags2);
-
-	if (set & TIOCM_RTS) {
-		ch->ch_mforce |= D_RTS(ch);
-		ch->ch_mval   |= D_RTS(ch);
-        }
-
-	if (set & TIOCM_DTR) {
-		ch->ch_mforce |= D_DTR(ch);
-		ch->ch_mval   |= D_DTR(ch);
-        }
-
-	if (clear & TIOCM_RTS) {
-		ch->ch_mforce |= D_RTS(ch);
-		ch->ch_mval   &= ~(D_RTS(ch));
-        }
-
-	if (clear & TIOCM_DTR) {
-		ch->ch_mforce |= D_DTR(ch);
-		ch->ch_mval   &= ~(D_DTR(ch));
-        }
-
-	dgap_param(tty);
-
-	DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-	DGAP_UNLOCK(bd->bd_lock, lock_flags);
-
-	DPR_IOCTL(("dgap_tty_tiocmset finish\n"));
-
-	return (0);
-}
-
-
-
-/*
- * dgap_tty_send_break()
- *
- * Send a Break, called by ld.
- */
-static int dgap_tty_send_break(struct tty_struct *tty, int msec)
-{
-	struct board_t *bd;
-	struct channel_t *ch;
-	struct un_t *un;
-	int ret = -EIO;
-	ulong lock_flags;
-	ulong lock_flags2;
-
-	if (!tty || tty->magic != TTY_MAGIC)
-		return ret;
-
-	un = tty->driver_data;
-	if (!un || un->magic != DGAP_UNIT_MAGIC)
-		return ret;
-
-	ch = un->un_ch;
-	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-		return ret;
-
-	bd = ch->ch_bd;
-	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
-		return ret;
-
-	switch (msec) {
-	case -1:
-		msec = 0xFFFF;
-		break;
-	case 0:
-		msec = 1;
-		break;
-	default:
-		msec /= 10;
-		break;
-	}
-
-	DPR_IOCTL(("dgap_tty_send_break start 1.  %lx\n", jiffies));
-
-	DGAP_LOCK(bd->bd_lock, lock_flags);
-	DGAP_LOCK(ch->ch_lock, lock_flags2);
-#if 0
-	dgap_cmdw(ch, SBREAK, (u16) SBREAK_TIME, 0);
-#endif
-	dgap_cmdw(ch, SBREAK, (u16) msec, 0);
-
-	DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-	DGAP_UNLOCK(bd->bd_lock, lock_flags);
-
-	DPR_IOCTL(("dgap_tty_send_break finish\n"));
-
-	return (0);
-}
-
-
-
-
-/*
- * dgap_tty_wait_until_sent()
- *
- * wait until data has been transmitted, called by ld.
- */
-static void dgap_tty_wait_until_sent(struct tty_struct *tty, int timeout)
-{
-	int rc;
-	rc = dgap_wait_for_drain(tty);
-	if (rc) {
-		DPR_IOCTL(("dgap_tty_ioctl - bad return: %d ", rc));
-		return;
-	}
-	return;
-}
-
-
-
-/*
- * dgap_send_xchar()
- *
- * send a high priority character, called by ld.
- */
-static void dgap_tty_send_xchar(struct tty_struct *tty, char c)
-{
-	struct board_t *bd;
-	struct channel_t *ch;
-	struct un_t *un;
-	ulong lock_flags;
-	ulong lock_flags2;
-
-	if (!tty || tty->magic != TTY_MAGIC)
-		return;
-
-	un = tty->driver_data;
-	if (!un || un->magic != DGAP_UNIT_MAGIC)
-		return;
-
-	ch = un->un_ch;
-	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-		return;
-
-	bd = ch->ch_bd;
-	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
-		return;
-
-	DPR_IOCTL(("dgap_tty_send_xchar start 1.  %lx\n", jiffies));
-
-	DGAP_LOCK(bd->bd_lock, lock_flags);
-	DGAP_LOCK(ch->ch_lock, lock_flags2);
-
-	/*
-	 * This is technically what we should do.
-	 * However, the NIST tests specifically want
-	 * to see each XON or XOFF character that it
-	 * sends, so lets just send each character
-	 * by hand...
-	 */
-#if 0
-	if (c == STOP_CHAR(tty)) {
-		dgap_cmdw(ch, RPAUSE, 0, 0);
-	}
-	else if (c == START_CHAR(tty)) {
-		dgap_cmdw(ch, RRESUME, 0, 0);
-	}
-	else {
-		dgap_wmove(ch, &c, 1);
-	}
-#else
-	dgap_wmove(ch, &c, 1);
-#endif
-
-	DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-	DGAP_UNLOCK(bd->bd_lock, lock_flags);
-
-	DPR_IOCTL(("dgap_tty_send_xchar finish\n"));
-
-	return;
-}
-
-
-
-
-/*
- * Return modem signals to ld.
- */
-static int dgap_get_modem_info(struct channel_t *ch, unsigned int __user *value)
-{
-	int result = 0;
-	uchar mstat = 0;
-	ulong lock_flags;
-	int rc = 0;
-
-	DPR_IOCTL(("dgap_get_modem_info start\n"));
-
-	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-		return(-ENXIO);
-
-	DGAP_LOCK(ch->ch_lock, lock_flags);
-
-	mstat = readb(&(ch->ch_bs->m_stat));
-	/* Append any outbound signals that might be pending... */
-	mstat |= ch->ch_mostat;
-
-	DGAP_UNLOCK(ch->ch_lock, lock_flags);
-
-	result = 0;
-
-	if (mstat & D_DTR(ch))
-		result |= TIOCM_DTR;
-	if (mstat & D_RTS(ch))
-		result |= TIOCM_RTS;
-	if (mstat & D_CTS(ch))
-		result |= TIOCM_CTS;
-	if (mstat & D_DSR(ch))
-		result |= TIOCM_DSR;
-	if (mstat & D_RI(ch))
-		result |= TIOCM_RI;
-	if (mstat & D_CD(ch))
-		result |= TIOCM_CD;
-
-	rc = put_user(result, value);
-
-	DPR_IOCTL(("dgap_get_modem_info finish\n"));
-	return(rc);
-}
-
-
-/*
- * dgap_set_modem_info()
- *
- * Set modem signals, called by ld.
- */
-static int dgap_set_modem_info(struct tty_struct *tty, unsigned int command, unsigned int __user *value)
-{
-	struct board_t *bd;
-	struct channel_t *ch;
-	struct un_t *un;
-	int ret = -ENXIO;
-	unsigned int arg = 0;
-	ulong lock_flags;
-	ulong lock_flags2;
-
-	if (!tty || tty->magic != TTY_MAGIC)
-		return ret;
-
-	un = tty->driver_data;
-	if (!un || un->magic != DGAP_UNIT_MAGIC)
-		return ret;
-
-	ch = un->un_ch;
-	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-		return ret;
-
-	bd = ch->ch_bd;
-	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
-		return ret;
-
-	DPR_IOCTL(("dgap_set_modem_info() start\n"));
-
-	ret = get_user(arg, value);
-	if (ret) {
-		DPR_IOCTL(("dgap_set_modem_info %d ret: %x. finished.\n", __LINE__, ret));
-		return(ret);
-	}
-
-	DPR_IOCTL(("dgap_set_modem_info: command: %x arg: %x\n", command, arg));
-
-	switch (command) {
-	case TIOCMBIS:
-		if (arg & TIOCM_RTS) {
-			ch->ch_mforce |= D_RTS(ch);
-			ch->ch_mval   |= D_RTS(ch);
-        	}
-
-		if (arg & TIOCM_DTR) {
-			ch->ch_mforce |= D_DTR(ch);
-			ch->ch_mval   |= D_DTR(ch);
-        	}
-
-		break;
-
-	case TIOCMBIC:
-		if (arg & TIOCM_RTS) {
-			ch->ch_mforce |= D_RTS(ch);
-			ch->ch_mval   &= ~(D_RTS(ch));
-        	}
-
-		if (arg & TIOCM_DTR) {
-			ch->ch_mforce |= D_DTR(ch);
-			ch->ch_mval   &= ~(D_DTR(ch));
-        	}
-
-		break;
-
-        case TIOCMSET:
-		ch->ch_mforce = D_DTR(ch)|D_RTS(ch);
-
-		if (arg & TIOCM_RTS) {
-			ch->ch_mval |= D_RTS(ch);
-        	}
-		else {
-			ch->ch_mval &= ~(D_RTS(ch));
-		}
-
-		if (arg & TIOCM_DTR) {
-			ch->ch_mval |= (D_DTR(ch));
-        	}
-		else {
-			ch->ch_mval &= ~(D_DTR(ch));
-		}
-
-		break;
-
-	default:
-		return(-EINVAL);
-	}
-
-	DGAP_LOCK(bd->bd_lock, lock_flags);
-	DGAP_LOCK(ch->ch_lock, lock_flags2);
-
-	dgap_param(tty);
-
-	DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-	DGAP_UNLOCK(bd->bd_lock, lock_flags);
-
-	DPR_IOCTL(("dgap_set_modem_info finish\n"));
-
-	return (0);
-}
-
-
-/*
- * dgap_tty_digigeta()
- *
- * Ioctl to get the information for ditty.
- *
- *
- *
- */
-static int dgap_tty_digigeta(struct tty_struct *tty, struct digi_t __user *retinfo)
-{
-	struct channel_t *ch;
-	struct un_t *un;
-	struct digi_t tmp;
-	ulong lock_flags;
-
-	if (!retinfo)
-		return (-EFAULT);
-
-	if (!tty || tty->magic != TTY_MAGIC)
-		return (-EFAULT);
-
-	un = tty->driver_data;
-	if (!un || un->magic != DGAP_UNIT_MAGIC)
-		return (-EFAULT);
-
-	ch = un->un_ch;
-	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-		return (-EFAULT);
-
-	memset(&tmp, 0, sizeof(tmp));
-
-	DGAP_LOCK(ch->ch_lock, lock_flags);
-	memcpy(&tmp, &ch->ch_digi, sizeof(tmp));
-	DGAP_UNLOCK(ch->ch_lock, lock_flags);
-
-	if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
-		return (-EFAULT);
-
-	return (0);
-}
-
-
-/*
- * dgap_tty_digiseta()
- *
- * Ioctl to set the information for ditty.
- *
- *
- *
- */
-static int dgap_tty_digiseta(struct tty_struct *tty, struct digi_t __user *new_info)
-{
-	struct board_t *bd;
-	struct channel_t *ch;
-	struct un_t *un;
-	struct digi_t new_digi;
-	ulong   lock_flags = 0;
-	unsigned long lock_flags2;
-
-	DPR_IOCTL(("DIGI_SETA start\n"));
-
-	if (!tty || tty->magic != TTY_MAGIC)
-		return (-EFAULT);
-
-	un = tty->driver_data;
-	if (!un || un->magic != DGAP_UNIT_MAGIC)
-		return (-EFAULT);
-
-	ch = un->un_ch;
-	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-		return (-EFAULT);
-
-	bd = ch->ch_bd;
-	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
-		return (-EFAULT);
-
-        if (copy_from_user(&new_digi, new_info, sizeof(struct digi_t))) {
-		DPR_IOCTL(("DIGI_SETA failed copy_from_user\n"));
-                return(-EFAULT);
-	}
-
-	DGAP_LOCK(bd->bd_lock, lock_flags);
-	DGAP_LOCK(ch->ch_lock, lock_flags2);
-
-	memcpy(&ch->ch_digi, &new_digi, sizeof(struct digi_t));
-
-	if (ch->ch_digi.digi_maxcps < 1)
-		ch->ch_digi.digi_maxcps = 1;
-
-	if (ch->ch_digi.digi_maxcps > 10000)
-		ch->ch_digi.digi_maxcps = 10000;
-
-	if (ch->ch_digi.digi_bufsize < 10)
-		ch->ch_digi.digi_bufsize = 10;
-
-	if (ch->ch_digi.digi_maxchar < 1)
-		ch->ch_digi.digi_maxchar = 1;
-
-	if (ch->ch_digi.digi_maxchar > ch->ch_digi.digi_bufsize)
-		ch->ch_digi.digi_maxchar = ch->ch_digi.digi_bufsize;
-
-	if (ch->ch_digi.digi_onlen > DIGI_PLEN)
-		ch->ch_digi.digi_onlen = DIGI_PLEN;
-
-	if (ch->ch_digi.digi_offlen > DIGI_PLEN)
-		ch->ch_digi.digi_offlen = DIGI_PLEN;
-
-	dgap_param(tty);
-
-	DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-	DGAP_UNLOCK(bd->bd_lock, lock_flags);
-
-	DPR_IOCTL(("DIGI_SETA finish\n"));
-
-	return(0);
-}
-
-
-/*
- * dgap_tty_digigetedelay()
- *
- * Ioctl to get the current edelay setting.
- *
- *
- *
- */
-static int dgap_tty_digigetedelay(struct tty_struct *tty, int __user *retinfo)
-{
-	struct channel_t *ch;
-	struct un_t *un;
-	int tmp;
-	ulong lock_flags;
-
-	if (!retinfo)
-		return (-EFAULT);
-
-	if (!tty || tty->magic != TTY_MAGIC)
-		return (-EFAULT);
-
-	un = tty->driver_data;
-	if (!un || un->magic != DGAP_UNIT_MAGIC)
-		return (-EFAULT);
-
-	ch = un->un_ch;
-	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-		return (-EFAULT);
-
-	memset(&tmp, 0, sizeof(tmp));
-
-	DGAP_LOCK(ch->ch_lock, lock_flags);
-	tmp = readw(&(ch->ch_bs->edelay));
-	DGAP_UNLOCK(ch->ch_lock, lock_flags);
-
-	if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
-		return (-EFAULT);
-
-	return (0);
-}
-
-
-/*
- * dgap_tty_digisetedelay()
- *
- * Ioctl to set the EDELAY setting
- *
- */
-static int dgap_tty_digisetedelay(struct tty_struct *tty, int __user *new_info)
-{
-	struct board_t *bd;
-	struct channel_t *ch;
-	struct un_t *un;
-	int new_digi;
-	ulong lock_flags;
-	ulong lock_flags2;
-
-	DPR_IOCTL(("DIGI_SETA start\n"));
-
-	if (!tty || tty->magic != TTY_MAGIC)
-		return (-EFAULT);
-
-	un = tty->driver_data;
-	if (!un || un->magic != DGAP_UNIT_MAGIC)
-		return (-EFAULT);
-
-	ch = un->un_ch;
-	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-		return (-EFAULT);
-
-	bd = ch->ch_bd;
-	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
-		return (-EFAULT);
-
-        if (copy_from_user(&new_digi, new_info, sizeof(int))) {
-		DPR_IOCTL(("DIGI_SETEDELAY failed copy_from_user\n"));
-                return(-EFAULT);
-	}
-
-	DGAP_LOCK(bd->bd_lock, lock_flags);
-	DGAP_LOCK(ch->ch_lock, lock_flags2);
-
-	writew((u16) new_digi, &(ch->ch_bs->edelay));
-
-	dgap_param(tty);
-
-	DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-	DGAP_UNLOCK(bd->bd_lock, lock_flags);
-
-	DPR_IOCTL(("DIGI_SETA finish\n"));
-
-	return(0);
-}
-
-
-/*
- * dgap_tty_digigetcustombaud()
- *
- * Ioctl to get the current custom baud rate setting.
- */
-static int dgap_tty_digigetcustombaud(struct tty_struct *tty, int __user *retinfo)
-{
-	struct channel_t *ch;
-	struct un_t *un;
-	int tmp;
-	ulong lock_flags;
-
-	if (!retinfo)
-		return (-EFAULT);
-
-	if (!tty || tty->magic != TTY_MAGIC)
-		return (-EFAULT);
-
-	un = tty->driver_data;
-	if (!un || un->magic != DGAP_UNIT_MAGIC)
-		return (-EFAULT);
-
-	ch = un->un_ch;
-	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-		return (-EFAULT);
-
-	memset(&tmp, 0, sizeof(tmp));
-
-	DGAP_LOCK(ch->ch_lock, lock_flags);
-	tmp = dgap_get_custom_baud(ch);
-	DGAP_UNLOCK(ch->ch_lock, lock_flags);
-
-	DPR_IOCTL(("DIGI_GETCUSTOMBAUD. Returning %d\n", tmp));
-
-	if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
-		return (-EFAULT);
-
-	return (0);
-}
-
-
-/*
- * dgap_tty_digisetcustombaud()
- *
- * Ioctl to set the custom baud rate setting
- */
-static int dgap_tty_digisetcustombaud(struct tty_struct *tty, int __user *new_info)
-{
-	struct board_t *bd;
-	struct channel_t *ch;
-	struct un_t *un;
-	uint new_rate;
-	ulong lock_flags;
-	ulong lock_flags2;
-
-	DPR_IOCTL(("DIGI_SETCUSTOMBAUD start\n"));
-
-	if (!tty || tty->magic != TTY_MAGIC)
-		return (-EFAULT);
-
-	un = tty->driver_data;
-	if (!un || un->magic != DGAP_UNIT_MAGIC)
-		return (-EFAULT);
-
-	ch = un->un_ch;
-	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-		return (-EFAULT);
-
-	bd = ch->ch_bd;
-	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
-		return (-EFAULT);
-
-
-	if (copy_from_user(&new_rate, new_info, sizeof(unsigned int))) {
-		DPR_IOCTL(("DIGI_SETCUSTOMBAUD failed copy_from_user\n"));
-		return(-EFAULT);
-	}
-
-	if (bd->bd_flags & BD_FEP5PLUS) {
-
-		DPR_IOCTL(("DIGI_SETCUSTOMBAUD. Setting %d\n", new_rate));
-
-		DGAP_LOCK(bd->bd_lock, lock_flags);
-		DGAP_LOCK(ch->ch_lock, lock_flags2);
-
-		ch->ch_custom_speed = new_rate;
-
-		dgap_param(tty);
-
-		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-		DGAP_UNLOCK(bd->bd_lock, lock_flags);
-	}
-
-	DPR_IOCTL(("DIGI_SETCUSTOMBAUD finish\n"));
-
-	return(0);
-}
-
-
-/*
- * dgap_set_termios()
- */
-static void dgap_tty_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
-{
-	struct board_t *bd;
-	struct channel_t *ch;
-	struct un_t *un;
-	unsigned long lock_flags;
-	unsigned long lock_flags2;
-
-	if (!tty || tty->magic != TTY_MAGIC)
-		return;
-
-	un = tty->driver_data;
-	if (!un || un->magic != DGAP_UNIT_MAGIC)
-		return;
-
-	ch = un->un_ch;
-	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-		return;
-
-	bd = ch->ch_bd;
-	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
-		return;
-
-	DGAP_LOCK(bd->bd_lock, lock_flags);
-	DGAP_LOCK(ch->ch_lock, lock_flags2);
-
-	ch->ch_c_cflag   = tty->termios.c_cflag;
-	ch->ch_c_iflag   = tty->termios.c_iflag;
-	ch->ch_c_oflag   = tty->termios.c_oflag;
-	ch->ch_c_lflag   = tty->termios.c_lflag;
-	ch->ch_startc    = tty->termios.c_cc[VSTART];
-	ch->ch_stopc     = tty->termios.c_cc[VSTOP];
-
-	dgap_carrier(ch);
-	dgap_param(tty);
-
-	DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-	DGAP_UNLOCK(bd->bd_lock, lock_flags);
-}
-
-
-static void dgap_tty_throttle(struct tty_struct *tty)
-{
-	struct board_t *bd;
-	struct channel_t *ch;
-	struct un_t *un;
-	ulong   lock_flags;
-	ulong   lock_flags2;
-
-	if (!tty || tty->magic != TTY_MAGIC)
-		return;
-
-	un = tty->driver_data;
-	if (!un || un->magic != DGAP_UNIT_MAGIC)
-		return;
-
-        ch = un->un_ch;
-        if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-                return;
-
-	bd = ch->ch_bd;
-	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
-		return;
-
-	DPR_IOCTL(("dgap_tty_throttle start\n"));
-
-	DGAP_LOCK(bd->bd_lock, lock_flags);
-	DGAP_LOCK(ch->ch_lock, lock_flags2);
-
-	ch->ch_flags |= (CH_RXBLOCK);
-#if 1
-	dgap_cmdw(ch, RPAUSE, 0, 0);
-#endif
-
-	DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-	DGAP_UNLOCK(bd->bd_lock, lock_flags);
-
-	DPR_IOCTL(("dgap_tty_throttle finish\n"));
-}
-
-
-static void dgap_tty_unthrottle(struct tty_struct *tty)
-{
-	struct board_t *bd;
-	struct channel_t *ch;
-	struct un_t *un;
-	ulong   lock_flags;
-	ulong   lock_flags2;
-
-	if (!tty || tty->magic != TTY_MAGIC)
-		return;
-
-	un = tty->driver_data;
-	if (!un || un->magic != DGAP_UNIT_MAGIC)
-		return;
-
-        ch = un->un_ch;
-        if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-                return;
-
-	bd = ch->ch_bd;
-	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
-		return;
-
-	DPR_IOCTL(("dgap_tty_unthrottle start\n"));
-
-	DGAP_LOCK(bd->bd_lock, lock_flags);
-	DGAP_LOCK(ch->ch_lock, lock_flags2);
-
-	ch->ch_flags &= ~(CH_RXBLOCK);
-
-#if 1
-	dgap_cmdw(ch, RRESUME, 0, 0);
-#endif
-
-	DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-	DGAP_UNLOCK(bd->bd_lock, lock_flags);
-
-	DPR_IOCTL(("dgap_tty_unthrottle finish\n"));
-}
-
-
-static void dgap_tty_start(struct tty_struct *tty)
-{
-	struct board_t *bd;
-	struct channel_t *ch;
-	struct un_t *un;
-	ulong   lock_flags;
-	ulong   lock_flags2;
-
-	if (!tty || tty->magic != TTY_MAGIC)
-		return;
-
-	un = tty->driver_data;
-	if (!un || un->magic != DGAP_UNIT_MAGIC)
-		return;
-
-        ch = un->un_ch;
-        if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-                return;
-
-	bd = ch->ch_bd;
-	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
-		return;
-
-	DPR_IOCTL(("dgap_tty_start start\n"));
-
-	DGAP_LOCK(bd->bd_lock, lock_flags);
-	DGAP_LOCK(ch->ch_lock, lock_flags2);
-
-	dgap_cmdw(ch, RESUMETX, 0, 0);
-
-	DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-	DGAP_UNLOCK(bd->bd_lock, lock_flags);
-
-	DPR_IOCTL(("dgap_tty_start finish\n"));
-}
-
-
-static void dgap_tty_stop(struct tty_struct *tty)
-{
-	struct board_t *bd;
-	struct channel_t *ch;
-	struct un_t *un;
-	ulong   lock_flags;
-	ulong   lock_flags2;
-
-	if (!tty || tty->magic != TTY_MAGIC)
-		return;
-
-	un = tty->driver_data;
-	if (!un || un->magic != DGAP_UNIT_MAGIC)
-		return;
-
-        ch = un->un_ch;
-        if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-                return;
-
-	bd = ch->ch_bd;
-	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
-		return;
-
-	DPR_IOCTL(("dgap_tty_stop start\n"));
-
-	DGAP_LOCK(bd->bd_lock, lock_flags);
-	DGAP_LOCK(ch->ch_lock, lock_flags2);
-
-	dgap_cmdw(ch, PAUSETX, 0, 0);
-
-	DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-	DGAP_UNLOCK(bd->bd_lock, lock_flags);
-
-	DPR_IOCTL(("dgap_tty_stop finish\n"));
-}
-
-
-/*
- * dgap_tty_flush_chars()
- *
- * Flush the cook buffer
- *
- * Note to self, and any other poor souls who venture here:
- *
- * flush in this case DOES NOT mean dispose of the data.
- * instead, it means "stop buffering and send it if you
- * haven't already."  Just guess how I figured that out...   SRW 2-Jun-98
- *
- * It is also always called in interrupt context - JAR 8-Sept-99
- */
-static void dgap_tty_flush_chars(struct tty_struct *tty)
-{
-	struct board_t *bd;
-	struct channel_t *ch;
-	struct un_t *un;
-	ulong   lock_flags;
-	ulong   lock_flags2;
-
-	if (!tty || tty->magic != TTY_MAGIC)
-		return;
-
-	un = tty->driver_data;
-	if (!un || un->magic != DGAP_UNIT_MAGIC)
-		return;
-
-        ch = un->un_ch;
-        if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-                return;
-
-	bd = ch->ch_bd;
-	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
-		return;
-
-	DPR_IOCTL(("dgap_tty_flush_chars start\n"));
-
-	DGAP_LOCK(bd->bd_lock, lock_flags);
-	DGAP_LOCK(ch->ch_lock, lock_flags2);
-
-	/* TODO: Do something here */
-
-	DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-	DGAP_UNLOCK(bd->bd_lock, lock_flags);
-
-	DPR_IOCTL(("dgap_tty_flush_chars finish\n"));
-}
-
-
-
-/*
- * dgap_tty_flush_buffer()
- *
- * Flush Tx buffer (make in == out)
- */
-static void dgap_tty_flush_buffer(struct tty_struct *tty)
-{
-	struct board_t *bd;
-	struct channel_t *ch;
-	struct un_t *un;
-	ulong   lock_flags;
-	ulong   lock_flags2;
-	u16	head = 0;
-
-	if (!tty || tty->magic != TTY_MAGIC)
-		return;
-
-	un = tty->driver_data;
-	if (!un || un->magic != DGAP_UNIT_MAGIC)
-		return;
-
-        ch = un->un_ch;
-        if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-                return;
-
-	bd = ch->ch_bd;
-	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
-		return;
-
-	DPR_IOCTL(("dgap_tty_flush_buffer on port: %d start\n", ch->ch_portnum));
-
-	DGAP_LOCK(bd->bd_lock, lock_flags);
-	DGAP_LOCK(ch->ch_lock, lock_flags2);
-
-	ch->ch_flags &= ~CH_STOP;
-	head = readw(&(ch->ch_bs->tx_head));
-	dgap_cmdw(ch, FLUSHTX, (u16) head, 0);
-	dgap_cmdw(ch, RESUMETX, 0, 0);
-	if (ch->ch_tun.un_flags & (UN_LOW|UN_EMPTY)) {
-		ch->ch_tun.un_flags &= ~(UN_LOW|UN_EMPTY);
-		wake_up_interruptible(&ch->ch_tun.un_flags_wait);
-	}
-	if (ch->ch_pun.un_flags & (UN_LOW|UN_EMPTY)) {
-		ch->ch_pun.un_flags &= ~(UN_LOW|UN_EMPTY);
-		wake_up_interruptible(&ch->ch_pun.un_flags_wait);
-	}
-
-	DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-	DGAP_UNLOCK(bd->bd_lock, lock_flags);
-	if (waitqueue_active(&tty->write_wait))
-		wake_up_interruptible(&tty->write_wait);
-	tty_wakeup(tty);
-
-	DPR_IOCTL(("dgap_tty_flush_buffer finish\n"));
-}
-
-
-
-/*****************************************************************************
- *
- * The IOCTL function and all of its helpers
- *
- *****************************************************************************/
-
-/*
- * dgap_tty_ioctl()
- *
- * The usual assortment of ioctl's
- */
-static int dgap_tty_ioctl(struct tty_struct *tty, unsigned int cmd,
-		unsigned long arg)
-{
-	struct board_t *bd;
-	struct channel_t *ch;
-	struct un_t *un;
-	int rc;
-	u16	head = 0;
-	ulong   lock_flags = 0;
-	ulong   lock_flags2 = 0;
-	void __user *uarg = (void __user *) arg;
-
-	if (!tty || tty->magic != TTY_MAGIC)
-		return (-ENODEV);
-
-	un = tty->driver_data;
-	if (!un || un->magic != DGAP_UNIT_MAGIC)
-		return (-ENODEV);
-
-	ch = un->un_ch;
-	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
-		return (-ENODEV);
-
-	bd = ch->ch_bd;
-	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
-		return (-ENODEV);
-
-	DPR_IOCTL(("dgap_tty_ioctl start on port %d - cmd %s (%x), arg %lx\n",
-		ch->ch_portnum, dgap_ioctl_name(cmd), cmd, arg));
-
-	DGAP_LOCK(bd->bd_lock, lock_flags);
-	DGAP_LOCK(ch->ch_lock, lock_flags2);
-
-	if (un->un_open_count <= 0) {
-		DPR_BASIC(("dgap_tty_ioctl - unit not open.\n"));
-		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-		DGAP_UNLOCK(bd->bd_lock, lock_flags);
-		return(-EIO);
-	}
-
-	switch (cmd) {
-
-	/* Here are all the standard ioctl's that we MUST implement */
-
-	case TCSBRK:
-		/*
-		 * TCSBRK is SVID version: non-zero arg --> no break
-		 * this behaviour is exploited by tcdrain().
-		 *
-		 * According to POSIX.1 spec (7.2.2.1.2) breaks should be
-		 * between 0.25 and 0.5 seconds so we'll ask for something
-		 * in the middle: 0.375 seconds.
-		 */
-		rc = tty_check_change(tty);
-		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-		DGAP_UNLOCK(bd->bd_lock, lock_flags);
-		if (rc) {
-			return(rc);
-		}
-
-		rc = dgap_wait_for_drain(tty);
-
-		if (rc) {
-			DPR_IOCTL(("dgap_tty_ioctl - bad return: %d ", rc));
-			return(-EINTR);
-		}
-
-		DGAP_LOCK(bd->bd_lock, lock_flags);
-		DGAP_LOCK(ch->ch_lock, lock_flags2);
-
-		if(((cmd == TCSBRK) && (!arg)) || (cmd == TCSBRKP)) {
-			dgap_cmdw(ch, SBREAK, (u16) SBREAK_TIME, 0);
-		}
-
-		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-		DGAP_UNLOCK(bd->bd_lock, lock_flags);
-
-		DPR_IOCTL(("dgap_tty_ioctl finish on port %d - cmd %s (%x), arg %lx\n",
-			ch->ch_portnum, dgap_ioctl_name(cmd), cmd, arg));
-
-                return(0);
-
-
-	case TCSBRKP:
- 		/* support for POSIX tcsendbreak()
-
-		 * According to POSIX.1 spec (7.2.2.1.2) breaks should be
-		 * between 0.25 and 0.5 seconds so we'll ask for something
-		 * in the middle: 0.375 seconds.
-		 */
-		rc = tty_check_change(tty);
-		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-		DGAP_UNLOCK(bd->bd_lock, lock_flags);
-		if (rc) {
-			return(rc);
-		}
-
-		rc = dgap_wait_for_drain(tty);
-		if (rc) {
-			DPR_IOCTL(("dgap_tty_ioctl - bad return: %d ", rc));
-			return(-EINTR);
-		}
-
-		DGAP_LOCK(bd->bd_lock, lock_flags);
-		DGAP_LOCK(ch->ch_lock, lock_flags2);
-
-		dgap_cmdw(ch, SBREAK, (u16) SBREAK_TIME, 0);
-
-		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-		DGAP_UNLOCK(bd->bd_lock, lock_flags);
-
-		DPR_IOCTL(("dgap_tty_ioctl finish on port %d - cmd %s (%x), arg %lx\n",
-			ch->ch_portnum, dgap_ioctl_name(cmd), cmd, arg));
-
-		return(0);
-
-        case TIOCSBRK:
-		/*
-		 * FEP5 doesn't support turning on a break unconditionally.
-		 * The FEP5 device will stop sending a break automatically
-		 * after the specified time value that was sent when turning on
-		 * the break.
-		 */
-		rc = tty_check_change(tty);
-		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-		DGAP_UNLOCK(bd->bd_lock, lock_flags);
-		if (rc) {
-			return(rc);
-		}
-
-		rc = dgap_wait_for_drain(tty);
-		if (rc) {
-			DPR_IOCTL(("dgap_tty_ioctl - bad return: %d ", rc));
-			return(-EINTR);
-		}
-
-		DGAP_LOCK(bd->bd_lock, lock_flags);
-		DGAP_LOCK(ch->ch_lock, lock_flags2);
-
-		dgap_cmdw(ch, SBREAK, (u16) SBREAK_TIME, 0);
-
-		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-		DGAP_UNLOCK(bd->bd_lock, lock_flags);
-
-		DPR_IOCTL(("dgap_tty_ioctl finish on port %d - cmd %s (%x), arg %lx\n",
-			ch->ch_portnum, dgap_ioctl_name(cmd), cmd, arg));
-
-		return 0;
-
-        case TIOCCBRK:
-		/*
-		 * FEP5 doesn't support turning off a break unconditionally.
-		 * The FEP5 device will stop sending a break automatically
-		 * after the specified time value that was sent when turning on
-		 * the break.
-		 */
-		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-		DGAP_UNLOCK(bd->bd_lock, lock_flags);
-		return 0;
-
-	case TIOCGSOFTCAR:
-
-		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-		DGAP_UNLOCK(bd->bd_lock, lock_flags);
-
-		rc = put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned long __user *) arg);
-		return(rc);
-
-	case TIOCSSOFTCAR:
-		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-		DGAP_UNLOCK(bd->bd_lock, lock_flags);
-
-		rc = get_user(arg, (unsigned long __user *) arg);
-		if (rc)
-			return(rc);
-
-		DGAP_LOCK(bd->bd_lock, lock_flags);
-		DGAP_LOCK(ch->ch_lock, lock_flags2);
-		tty->termios.c_cflag = ((tty->termios.c_cflag & ~CLOCAL) | (arg ? CLOCAL : 0));
-		dgap_param(tty);
-		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-		DGAP_UNLOCK(bd->bd_lock, lock_flags);
-
-		return(0);
-
-	case TIOCMGET:
-		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-		DGAP_UNLOCK(bd->bd_lock, lock_flags);
-                return(dgap_get_modem_info(ch, uarg));
-
-	case TIOCMBIS:
-	case TIOCMBIC:
-	case TIOCMSET:
-		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-		DGAP_UNLOCK(bd->bd_lock, lock_flags);
-		return(dgap_set_modem_info(tty, cmd, uarg));
-
-		/*
-		 * Here are any additional ioctl's that we want to implement
-		 */
-
-	case TCFLSH:
-		/*
-		 * The linux tty driver doesn't have a flush
-		 * input routine for the driver, assuming all backed
-		 * up data is in the line disc. buffers.  However,
-		 * we all know that's not the case.  Here, we
-		 * act on the ioctl, but then lie and say we didn't
-		 * so the line discipline will process the flush
-		 * also.
-		 */
-		rc = tty_check_change(tty);
-		if (rc) {
-			DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-			DGAP_UNLOCK(bd->bd_lock, lock_flags);
-			return(rc);
-		}
-
-		if ((arg == TCIFLUSH) || (arg == TCIOFLUSH)) {
-			if (!(un->un_type == DGAP_PRINT)) {
-				head = readw(&(ch->ch_bs->rx_head));
-				writew(head, &(ch->ch_bs->rx_tail));
-				writeb(0, &(ch->ch_bs->orun));
-			}
-		}
-
-		if ((arg == TCOFLUSH) || (arg == TCIOFLUSH)) {
-			ch->ch_flags &= ~CH_STOP;
-			head = readw(&(ch->ch_bs->tx_head));
-			dgap_cmdw(ch, FLUSHTX, (u16) head, 0 );
-			dgap_cmdw(ch, RESUMETX, 0, 0);
-			if (ch->ch_tun.un_flags & (UN_LOW|UN_EMPTY)) {
-				ch->ch_tun.un_flags &= ~(UN_LOW|UN_EMPTY);
-				wake_up_interruptible(&ch->ch_tun.un_flags_wait);
-			}
-			if (ch->ch_pun.un_flags & (UN_LOW|UN_EMPTY)) {
-				ch->ch_pun.un_flags &= ~(UN_LOW|UN_EMPTY);
-				wake_up_interruptible(&ch->ch_pun.un_flags_wait);
-			}
-			if (waitqueue_active(&tty->write_wait))
-				wake_up_interruptible(&tty->write_wait);
-
-			/* Can't hold any locks when calling tty_wakeup! */
-			DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-			DGAP_UNLOCK(bd->bd_lock, lock_flags);
-			tty_wakeup(tty);
-			DGAP_LOCK(bd->bd_lock, lock_flags);
-			DGAP_LOCK(ch->ch_lock, lock_flags2);
-		}
-
-		/* pretend we didn't recognize this IOCTL */
-		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-		DGAP_UNLOCK(bd->bd_lock, lock_flags);
-
-		DPR_IOCTL(("dgap_tty_ioctl (LINE:%d) finish on port %d - cmd %s (%x), arg %lx\n",
-			__LINE__, ch->ch_portnum, dgap_ioctl_name(cmd), cmd, arg));
-
-		return(-ENOIOCTLCMD);
-
-	case TCSETSF:
-	case TCSETSW:
-		/*
-		 * The linux tty driver doesn't have a flush
-		 * input routine for the driver, assuming all backed
-		 * up data is in the line disc. buffers.  However,
-		 * we all know that's not the case.  Here, we
-		 * act on the ioctl, but then lie and say we didn't
-		 * so the line discipline will process the flush
-		 * also.
-		 */
-		if (cmd == TCSETSF) {
-			/* flush rx */
-			ch->ch_flags &= ~CH_STOP;
-			head = readw(&(ch->ch_bs->rx_head));
-			writew(head, &(ch->ch_bs->rx_tail));
-		}
-
-		/* now wait for all the output to drain */
-		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-		DGAP_UNLOCK(bd->bd_lock, lock_flags);
-		rc = dgap_wait_for_drain(tty);
-		if (rc) {
-			DPR_IOCTL(("dgap_tty_ioctl - bad return: %d ", rc));
-			return(-EINTR);
-		}
-
-		DPR_IOCTL(("dgap_tty_ioctl finish on port %d - cmd %s (%x), arg %lx\n",
-			ch->ch_portnum, dgap_ioctl_name(cmd), cmd, arg));
-
-		/* pretend we didn't recognize this */
-		return(-ENOIOCTLCMD);
-
-	case TCSETAW:
-
-		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-		DGAP_UNLOCK(bd->bd_lock, lock_flags);
-		rc = dgap_wait_for_drain(tty);
-		if (rc) {
-			DPR_IOCTL(("dgap_tty_ioctl - bad return: %d ", rc));
-			return(-EINTR);
-		}
-
-		/* pretend we didn't recognize this */
-		return(-ENOIOCTLCMD);
-
-	case TCXONC:
-		/*
-		 * The Linux Line Discipline (LD) would do this for us if we
-		 * let it, but we have the special firmware options to do this
-		 * the "right way" regardless of hardware or software flow
-		 * control so we'll do it outselves instead of letting the LD
-		 * do it.
-		 */
-		rc = tty_check_change(tty);
-		if (rc) {
-			DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-			DGAP_UNLOCK(bd->bd_lock, lock_flags);
-			return(rc);
-		}
-
-		DPR_IOCTL(("dgap_ioctl - in TCXONC - %d\n", cmd));
-		switch (arg) {
-
-		case TCOON:
-			DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-			DGAP_UNLOCK(bd->bd_lock, lock_flags);
-			dgap_tty_start(tty);
-			return(0);
-		case TCOOFF:
-			DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-			DGAP_UNLOCK(bd->bd_lock, lock_flags);
-			dgap_tty_stop(tty);
-			return(0);
-		case TCION:
-			DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-			DGAP_UNLOCK(bd->bd_lock, lock_flags);
-			/* Make the ld do it */
-			return(-ENOIOCTLCMD);
-		case TCIOFF:
-			DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-			DGAP_UNLOCK(bd->bd_lock, lock_flags);
-			/* Make the ld do it */
-			return(-ENOIOCTLCMD);
-		default:
-			DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-			DGAP_UNLOCK(bd->bd_lock, lock_flags);
-			return(-EINVAL);
-		}
-
-	case DIGI_GETA:
-		/* get information for ditty */
-		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-		DGAP_UNLOCK(bd->bd_lock, lock_flags);
-		return(dgap_tty_digigeta(tty, uarg));
-
-	case DIGI_SETAW:
-	case DIGI_SETAF:
-
-		/* set information for ditty */
-		if (cmd == (DIGI_SETAW)) {
-
-			DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-			DGAP_UNLOCK(bd->bd_lock, lock_flags);
-			rc = dgap_wait_for_drain(tty);
-			if (rc) {
-				DPR_IOCTL(("dgap_tty_ioctl - bad return: %d ", rc));
-				return(-EINTR);
-			}
-			DGAP_LOCK(bd->bd_lock, lock_flags);
-			DGAP_LOCK(ch->ch_lock, lock_flags2);
-		}
-		else {
-			tty_ldisc_flush(tty);
-		}
-		/* fall thru */
-
-	case DIGI_SETA:
-		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-		DGAP_UNLOCK(bd->bd_lock, lock_flags);
-		return(dgap_tty_digiseta(tty, uarg));
-
-	case DIGI_GEDELAY:
-		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-		DGAP_UNLOCK(bd->bd_lock, lock_flags);
-		return(dgap_tty_digigetedelay(tty, uarg));
-
-	case DIGI_SEDELAY:
-		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-		DGAP_UNLOCK(bd->bd_lock, lock_flags);
-		return(dgap_tty_digisetedelay(tty, uarg));
-
-	case DIGI_GETCUSTOMBAUD:
-		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-		DGAP_UNLOCK(bd->bd_lock, lock_flags);
-		return(dgap_tty_digigetcustombaud(tty, uarg));
-
-	case DIGI_SETCUSTOMBAUD:
-		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-		DGAP_UNLOCK(bd->bd_lock, lock_flags);
-		return(dgap_tty_digisetcustombaud(tty, uarg));
-
-	case DIGI_RESET_PORT:
-		dgap_firmware_reset_port(ch);
-		dgap_param(tty);
-		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-		DGAP_UNLOCK(bd->bd_lock, lock_flags);
-		return 0;
-
-	default:
-		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-		DGAP_UNLOCK(bd->bd_lock, lock_flags);
-
-		DPR_IOCTL(("dgap_tty_ioctl - in default\n"));
-		DPR_IOCTL(("dgap_tty_ioctl end - cmd %s (%x), arg %lx\n",
-			dgap_ioctl_name(cmd), cmd, arg));
-
-		return(-ENOIOCTLCMD);
-	}
-}
diff --git a/drivers/staging/dgap/dgap_tty.h b/drivers/staging/dgap/dgap_tty.h
deleted file mode 100644
index 464a460..0000000
--- a/drivers/staging/dgap/dgap_tty.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright 2003 Digi International (www.digi.com)
- *	Scott H Kilau <Scott_Kilau at digi dot com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
- * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- * PURPOSE.  See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- *	NOTE: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!!
- */
-
-#ifndef __DGAP_TTY_H
-#define __DGAP_TTY_H
-
-#include "dgap_driver.h"
-
-int	dgap_tty_register(struct board_t *brd);
-
-int	dgap_tty_preinit(void);
-int     dgap_tty_init(struct board_t *);
-
-void	dgap_tty_post_uninit(void);
-void	dgap_tty_uninit(struct board_t *);
-
-void	dgap_carrier(struct channel_t *ch);
-void	dgap_input(struct channel_t *ch);
-
-
-#endif
diff --git a/drivers/staging/dgap/dgap_types.h b/drivers/staging/dgap/dgap_types.h
deleted file mode 100644
index eca38c7..0000000
--- a/drivers/staging/dgap/dgap_types.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright 2003 Digi International (www.digi.com)
- *	Scott H Kilau <Scott_Kilau at digi dot com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
- * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- * PURPOSE.  See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- *	NOTE: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!!
- */
-
-#ifndef __DGAP_TYPES_H
-#define __DGAP_TYPES_H
-
-#ifndef TRUE
-# define TRUE 1
-#endif
-
-#ifndef FALSE
-# define FALSE 0
-#endif
-
-/* Required for our shared headers! */
-typedef unsigned char		uchar;
-
-#endif
diff --git a/drivers/staging/dgap/digi.h b/drivers/staging/dgap/digi.h
deleted file mode 100644
index fe87903..0000000
--- a/drivers/staging/dgap/digi.h
+++ /dev/null
@@ -1,376 +0,0 @@
-/*
- * Copyright 2003 Digi International (www.digi.com)
- *	Scott H Kilau <Scott_Kilau at digi dot com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
- * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- * PURPOSE.  See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * $Id: digi.h,v 1.1 2009/10/23 14:01:57 markh Exp $
- *
- *	NOTE: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!!
- */
-
-#ifndef __DIGI_H
-#define __DIGI_H
-
-/************************************************************************
- ***	Definitions for Digi ditty(1) command.
- ************************************************************************/
-
-
-/*
- * Copyright (c) 1988-96 Digi International Inc., All Rights Reserved.
- */
-
-/************************************************************************
- * This module provides application access to special Digi
- * serial line enhancements which are not standard UNIX(tm) features.
- ************************************************************************/
-
-#if !defined(TIOCMODG)
-
-#define	TIOCMODG	('d'<<8) | 250		/* get modem ctrl state	*/
-#define	TIOCMODS	('d'<<8) | 251		/* set modem ctrl state	*/
-
-#ifndef TIOCM_LE
-#define		TIOCM_LE	0x01		/* line enable		*/
-#define		TIOCM_DTR	0x02		/* data terminal ready	*/
-#define		TIOCM_RTS	0x04		/* request to send	*/
-#define		TIOCM_ST	0x08		/* secondary transmit	*/
-#define		TIOCM_SR	0x10		/* secondary receive	*/
-#define		TIOCM_CTS	0x20		/* clear to send	*/
-#define		TIOCM_CAR	0x40		/* carrier detect	*/
-#define		TIOCM_RNG	0x80		/* ring	indicator	*/
-#define		TIOCM_DSR	0x100		/* data set ready	*/
-#define		TIOCM_RI	TIOCM_RNG	/* ring (alternate)	*/
-#define		TIOCM_CD	TIOCM_CAR	/* carrier detect (alt)	*/
-#endif
-
-#endif
-
-#if !defined(TIOCMSET)
-#define	TIOCMSET	('d'<<8) | 252		/* set modem ctrl state	*/
-#define	TIOCMGET	('d'<<8) | 253		/* set modem ctrl state	*/
-#endif
-
-#if !defined(TIOCMBIC)
-#define	TIOCMBIC	('d'<<8) | 254		/* set modem ctrl state */
-#define	TIOCMBIS	('d'<<8) | 255		/* set modem ctrl state */
-#endif
-
-
-#if !defined(TIOCSDTR)
-#define	TIOCSDTR	('e'<<8) | 0		/* set DTR		*/
-#define	TIOCCDTR	('e'<<8) | 1		/* clear DTR		*/
-#endif
-
-/************************************************************************
- * Ioctl command arguments for DIGI parameters.
- ************************************************************************/
-#define DIGI_GETA	('e'<<8) | 94		/* Read params		*/
-
-#define DIGI_SETA	('e'<<8) | 95		/* Set params		*/
-#define DIGI_SETAW	('e'<<8) | 96		/* Drain & set params	*/
-#define DIGI_SETAF	('e'<<8) | 97		/* Drain, flush & set params */
-
-#define DIGI_KME	('e'<<8) | 98		/* Read/Write Host	*/
-						/* Adapter Memory	*/
-
-#define	DIGI_GETFLOW	('e'<<8) | 99		/* Get startc/stopc flow */
-						/* control characters 	 */
-#define	DIGI_SETFLOW	('e'<<8) | 100		/* Set startc/stopc flow */
-						/* control characters	 */
-#define	DIGI_GETAFLOW	('e'<<8) | 101		/* Get Aux. startc/stopc */
-						/* flow control chars 	 */
-#define	DIGI_SETAFLOW	('e'<<8) | 102		/* Set Aux. startc/stopc */
-						/* flow control chars	 */
-
-#define DIGI_GEDELAY	('d'<<8) | 246		/* Get edelay */
-#define DIGI_SEDELAY	('d'<<8) | 247		/* Set edelay */
-
-struct	digiflow_t {
-	unsigned char	startc;				/* flow cntl start char	*/
-	unsigned char	stopc;				/* flow cntl stop char	*/
-};
-
-
-#ifdef	FLOW_2200
-#define	F2200_GETA	('e'<<8) | 104		/* Get 2x36 flow cntl flags */
-#define	F2200_SETAW	('e'<<8) | 105		/* Set 2x36 flow cntl flags */
-#define		F2200_MASK	0x03		/* 2200 flow cntl bit mask  */
-#define		FCNTL_2200	0x01		/* 2x36 terminal flow cntl  */
-#define		PCNTL_2200	0x02		/* 2x36 printer flow cntl   */
-#define	F2200_XON	0xf8
-#define	P2200_XON	0xf9
-#define	F2200_XOFF	0xfa
-#define	P2200_XOFF	0xfb
-
-#define	FXOFF_MASK	0x03			/* 2200 flow status mask    */
-#define	RCVD_FXOFF	0x01			/* 2x36 Terminal XOFF rcvd  */
-#define	RCVD_PXOFF	0x02			/* 2x36 Printer XOFF rcvd   */
-#endif
-
-/************************************************************************
- * Values for digi_flags
- ************************************************************************/
-#define DIGI_IXON	0x0001		/* Handle IXON in the FEP	*/
-#define DIGI_FAST	0x0002		/* Fast baud rates		*/
-#define RTSPACE		0x0004		/* RTS input flow control	*/
-#define CTSPACE		0x0008		/* CTS output flow control	*/
-#define DSRPACE		0x0010		/* DSR output flow control	*/
-#define DCDPACE		0x0020		/* DCD output flow control	*/
-#define DTRPACE		0x0040		/* DTR input flow control	*/
-#define DIGI_COOK	0x0080		/* Cooked processing done in FEP */
-#define DIGI_FORCEDCD	0x0100		/* Force carrier		*/
-#define	DIGI_ALTPIN	0x0200		/* Alternate RJ-45 pin config	*/
-#define	DIGI_AIXON	0x0400		/* Aux flow control in fep	*/
-#define	DIGI_PRINTER	0x0800		/* Hold port open for flow cntrl*/
-#define DIGI_PP_INPUT	0x1000		/* Change parallel port to input*/
-#define DIGI_DTR_TOGGLE 0x2000		/* Support DTR Toggle		*/
-#define	DIGI_422	0x4000		/* for 422/232 selectable panel */
-#define DIGI_RTS_TOGGLE	0x8000		/* Support RTS Toggle		*/
-
-/************************************************************************
- * These options are not supported on the comxi.
- ************************************************************************/
-#define	DIGI_COMXI	(DIGI_FAST|DIGI_COOK|DSRPACE|DCDPACE|DTRPACE)
-
-#define DIGI_PLEN	28		/* String length		*/
-#define	DIGI_TSIZ	10		/* Terminal string len		*/
-
-/************************************************************************
- * Structure used with ioctl commands for DIGI parameters.
- ************************************************************************/
-struct digi_t {
-	unsigned short	digi_flags;		/* Flags (see above)	*/
-	unsigned short	digi_maxcps;		/* Max printer CPS	*/
-	unsigned short	digi_maxchar;		/* Max chars in print queue */
-	unsigned short	digi_bufsize;		/* Buffer size		*/
-	unsigned char	digi_onlen;		/* Length of ON string	*/
-	unsigned char	digi_offlen;		/* Length of OFF string	*/
-	char		digi_onstr[DIGI_PLEN];	/* Printer on string	*/
-	char		digi_offstr[DIGI_PLEN];	/* Printer off string	*/
-	char		digi_term[DIGI_TSIZ];	/* terminal string	*/
-};
-
-/************************************************************************
- * KME definitions and structures.
- ************************************************************************/
-#define	RW_IDLE		0	/* Operation complete			*/
-#define	RW_READ		1	/* Read Concentrator Memory		*/
-#define	RW_WRITE	2	/* Write Concentrator Memory		*/
-
-struct rw_t {
-	unsigned char	rw_req;		/* Request type			*/
-	unsigned char	rw_board;	/* Host Adapter board number	*/
-	unsigned char	rw_conc;	/* Concentrator number		*/
-	unsigned char	rw_reserved;	/* Reserved for expansion	*/
-	unsigned long	rw_addr;	/* Address in concentrator	*/
-	unsigned short	rw_size;	/* Read/write request length	*/
-	unsigned char	rw_data[128];	/* Data to read/write		*/
-};
-
-/***********************************************************************
- * Shrink Buffer and Board Information definitions and structures.
-
- ************************************************************************/
-			/* Board type return codes */
-#define	PCXI_TYPE 1     /* Board type at the designated port is a PC/Xi */
-#define PCXM_TYPE 2     /* Board type at the designated port is a PC/Xm */
-#define	PCXE_TYPE 3     /* Board type at the designated port is a PC/Xe */
-#define	MCXI_TYPE 4     /* Board type at the designated port is a MC/Xi */
-#define COMXI_TYPE 5     /* Board type at the designated port is a COM/Xi */
-
-			 /* Non-Zero Result codes. */
-#define RESULT_NOBDFND 1 /* A Digi product at that port is not config installed */
-#define RESULT_NODESCT 2 /* A memory descriptor was not obtainable */
-#define RESULT_NOOSSIG 3 /* FEP/OS signature was not detected on the board */
-#define RESULT_TOOSML  4 /* Too small an area to shrink.  */
-#define RESULT_NOCHAN  5 /* Channel structure for the board was not found */
-
-struct shrink_buf_struct {
-	unsigned long	shrink_buf_vaddr;	/* Virtual address of board */
-	unsigned long	shrink_buf_phys;	/* Physical address of board */
-	unsigned long	shrink_buf_bseg;	/* Amount of board memory */
-	unsigned long	shrink_buf_hseg;	/* '186 Beginning of Dual-Port */
-
-	unsigned long	shrink_buf_lseg;	/* '186 Beginning of freed memory						*/
-	unsigned long	shrink_buf_mseg;	/* Linear address from start of
-						   dual-port were freed memory
-						   begins, host viewpoint. */
-
-	unsigned long	shrink_buf_bdparam;	/* Parameter for xxmemon and
-						   xxmemoff */
-
-	unsigned long	shrink_buf_reserva;	/* Reserved */
-	unsigned long	shrink_buf_reservb;	/* Reserved */
-	unsigned long	shrink_buf_reservc;	/* Reserved */
-	unsigned long	shrink_buf_reservd;	/* Reserved */
-
-	unsigned char	shrink_buf_result;	/* Reason for call failing
-						   Zero is Good return */
-	unsigned char	shrink_buf_init;	/* Non-Zero if it caused an
-						   xxinit call. */
-
-	unsigned char	shrink_buf_anports;	/* Number of async ports  */
-	unsigned char	shrink_buf_snports; 	/* Number of sync  ports */
-	unsigned char	shrink_buf_type;	/* Board type 1 = PC/Xi,
-							      2 = PC/Xm,
-							      3 = PC/Xe
-							      4 = MC/Xi
-							      5 = COMX/i */
-	unsigned char	shrink_buf_card;	/* Card number */
-
-};
-
-/************************************************************************
- * Structure to get driver status information
- ************************************************************************/
-struct digi_dinfo {
-	unsigned long	dinfo_nboards;		/* # boards configured	*/
-	char		dinfo_reserved[12];	/* for future expansion */
-	char		dinfo_version[16];	/* driver version       */
-};
-
-#define	DIGI_GETDD	('d'<<8) | 248		/* get driver info      */
-
-/************************************************************************
- * Structure used with ioctl commands for per-board information
- *
- * physsize and memsize differ when board has "windowed" memory
- ************************************************************************/
-struct digi_info {
-	unsigned long	info_bdnum;		/* Board number (0 based)  */
-	unsigned long	info_ioport;		/* io port address         */
-	unsigned long	info_physaddr;		/* memory address          */
-	unsigned long	info_physsize;		/* Size of host mem window */
-	unsigned long	info_memsize;		/* Amount of dual-port mem */
-						/* on board                */
-	unsigned short	info_bdtype;		/* Board type              */
-	unsigned short	info_nports;		/* number of ports         */
-	char		info_bdstate;		/* board state             */
-	char		info_reserved[7];	/* for future expansion    */
-};
-
-#define	DIGI_GETBD	('d'<<8) | 249		/* get board info          */
-
-struct digi_stat {
-	unsigned int	info_chan;		/* Channel number (0 based)  */
-	unsigned int	info_brd;		/* Board number (0 based)  */
-	unsigned long	info_cflag;		/* cflag for channel       */
-	unsigned long	info_iflag;		/* iflag for channel       */
-	unsigned long	info_oflag;		/* oflag for channel       */
-	unsigned long	info_mstat;		/* mstat for channel       */
-	unsigned long	info_tx_data;		/* tx_data for channel       */
-	unsigned long	info_rx_data;		/* rx_data for channel       */
-	unsigned long	info_hflow;		/* hflow for channel       */
-	unsigned long	info_reserved[8];	/* for future expansion    */
-};
-
-#define	DIGI_GETSTAT	('d'<<8) | 244		/* get board info          */
-/************************************************************************
- *
- * Structure used with ioctl commands for per-channel information
- *
- ************************************************************************/
-struct digi_ch {
-	unsigned long	info_bdnum;		/* Board number (0 based)  */
-	unsigned long	info_channel;		/* Channel index number    */
-	unsigned long	info_ch_cflag;		/* Channel cflag   	   */
-	unsigned long	info_ch_iflag;		/* Channel iflag   	   */
-	unsigned long	info_ch_oflag;		/* Channel oflag   	   */
-	unsigned long	info_chsize;		/* Channel structure size  */
-	unsigned long	info_sleep_stat;	/* sleep status		   */
-	dev_t		info_dev;		/* device number	   */
-	unsigned char	info_initstate;		/* Channel init state	   */
-	unsigned char	info_running;		/* Channel running state   */
-	long		reserved[8];		/* reserved for future use */
-};
-
-/*
-* This structure is used with the DIGI_FEPCMD ioctl to
-* tell the driver which port to send the command for.
-*/
-struct digi_cmd {
-	int	cmd;
-	int	word;
-	int	ncmds;
-	int	chan; /* channel index (zero based) */
-	int	bdid; /* board index (zero based) */
-};
-
-/*
-*  info_sleep_stat defines
-*/
-#define INFO_RUNWAIT	0x0001
-#define INFO_WOPEN	0x0002
-#define INFO_TTIOW	0x0004
-#define INFO_CH_RWAIT	0x0008
-#define INFO_CH_WEMPTY	0x0010
-#define INFO_CH_WLOW	0x0020
-#define INFO_XXBUF_BUSY 0x0040
-
-#define	DIGI_GETCH	('d'<<8) | 245		/* get board info          */
-
-/* Board type definitions */
-
-#define	SUBTYPE		0007
-#define	T_PCXI		0000
-#define T_PCXM		0001
-#define T_PCXE		0002
-#define T_PCXR		0003
-#define T_SP		0004
-#define T_SP_PLUS	0005
-#	define T_HERC	0000
-#	define T_HOU	0001
-#	define T_LON	0002
-#	define T_CHA	0003
-#define FAMILY		0070
-#define T_COMXI		0000
-#define T_PCXX		0010
-#define T_CX		0020
-#define T_EPC		0030
-#define	T_PCLITE	0040
-#define	T_SPXX		0050
-#define	T_AVXX		0060
-#define T_DXB		0070
-#define T_A2K_4_8	0070
-#define BUSTYPE		0700
-#define T_ISABUS	0000
-#define T_MCBUS		0100
-#define	T_EISABUS	0200
-#define	T_PCIBUS	0400
-
-/* Board State Definitions */
-
-#define	BD_RUNNING	0x0
-#define	BD_REASON	0x7f
-#define	BD_NOTFOUND	0x1
-#define	BD_NOIOPORT	0x2
-#define	BD_NOMEM	0x3
-#define	BD_NOBIOS	0x4
-#define	BD_NOFEP	0x5
-#define	BD_FAILED	0x6
-#define BD_ALLOCATED	0x7
-#define BD_TRIBOOT	0x8
-#define	BD_BADKME	0x80
-
-#define DIGI_LOOPBACK	      ('d'<<8) | 252		/* Enable/disable UART internal loopback */
-#define DIGI_SPOLL            ('d'<<8) | 254		/* change poller rate   */
-
-#define DIGI_SETCUSTOMBAUD	_IOW('e', 106, int)	/* Set integer baud rate */
-#define DIGI_GETCUSTOMBAUD	_IOR('e', 107, int)	/* Get integer baud rate */
-#define DIGI_RESET_PORT		('e'<<8) | 93		/* Reset port		*/
-
-#endif /* DIGI_H */
diff --git a/drivers/staging/dgap/downld.c b/drivers/staging/dgap/downld.c
deleted file mode 100644
index 1f4aa2e..0000000
--- a/drivers/staging/dgap/downld.c
+++ /dev/null
@@ -1,798 +0,0 @@
-/*
- * Copyright 2003 Digi International (www.digi.com)
- *	Scott H Kilau <Scott_Kilau at digi dot com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
- * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- * PURPOSE.  See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * $Id: downld.c,v 1.6 2009/01/14 14:10:54 markh Exp $
- */
-
-/*
-** downld.c
-**
-**  This is the daemon that sends the fep, bios, and concentrator images
-**  from user space to the driver.
-** BUGS:
-**  If the file changes in the middle of the download, you probably
-**     will get what you deserve.
-**
-*/
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <fcntl.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/errno.h>
-
-#include "dgap_types.h"
-#include "digi.h"
-#include "dgap_fep5.h"
-
-#include "dgap_downld.h"
-
-#include <string.h>
-#include <malloc.h>
-#include <stddef.h>
-#include <unistd.h>
-
-char		*pgm;
-void		myperror();
-
-/*
-**  This structure is used to keep track of the different images available
-**  to give to the driver.  It is arranged so that the things that are
-**  constants or that have defaults are first inthe strucutre to simplify
-**  the table of initializers.
-*/
-struct image_info {
-	short	type;		/* bios, fep, conc */
-	short	family;		/* boards this applies to */
-	short	subtype;	/* subtype */
-	int	len;		/* size of image */
-	char	*image;		/* ioctl struct + image */
-	char	*name;
-	char	*fname;		/* filename of binary (i.e. "asfep.bin") */
-	char	*pathname;	/* pathname to this binary ("/etc/dgap/xrfep.bin"); */
-	time_t	mtime;		/* Last modification time */
-};
-
-#define IBIOS	0
-#define	IFEP	1
-#define	ICONC	2
-#define ICONFIG	3
-#define	IBAD	4
-
-#define DEFAULT_LOC "/lib/firmware/dgap/"
-
-struct image_info	*image_list;
-int			nimages, count;
-
-struct image_info images[] = {
-{IBIOS, T_EPC,      SUBTYPE, 0, NULL, "EPC/X",	"fxbios.bin", DEFAULT_LOC "fxbios.bin", 0 },
-{IFEP,  T_EPC,      SUBTYPE, 0, NULL, "EPC/X",	"fxfep.bin", DEFAULT_LOC "fxfep.bin", 0 },
-{ICONC, T_EPC,      SUBTYPE, 0, NULL, "EPC/X",	"fxcon.bin", DEFAULT_LOC "fxcon.bin", 0 },
-
-{IBIOS, T_CX,       SUBTYPE, 0, NULL, "C/X",	"cxbios.bin", DEFAULT_LOC "cxbios.bin", 0 },
-{IFEP,  T_CX,       SUBTYPE, 0, NULL, "C/X",	"cxhost.bin", DEFAULT_LOC "cxhost.bin", 0 },
-
-{IBIOS, T_CX,       T_PCIBUS, 0, NULL, "C/X PCI", "cxpbios.bin", DEFAULT_LOC "cxpbios.bin", 0 },
-{IFEP,  T_CX,       T_PCIBUS, 0, NULL, "C/X PCI", "cxpfep.bin", DEFAULT_LOC "cxpfep.bin", 0 },
-
-{ICONC, T_CX,       SUBTYPE, 0, NULL, "C/X",	"cxcon.bin", DEFAULT_LOC "cxcon.bin", 0 },
-{ICONC, T_CX,       SUBTYPE, 0, NULL, "C/X",	"ibmcxcon.bin", DEFAULT_LOC "ibmcxcon.bin", 0 },
-{ICONC, T_CX,       SUBTYPE, 0, NULL, "C/X",	"ibmencon.bin", DEFAULT_LOC "ibmencon.bin", 0 },
-
-{IBIOS, FAMILY,   T_PCXR, 0, NULL, "PCXR",	"xrbios.bin", DEFAULT_LOC "xrbios.bin", 0 },
-{IFEP,  FAMILY,   T_PCXR, 0,  NULL,  "PCXR",	"xrfep.bin", DEFAULT_LOC "xrfep.bin", 0  },
-
-{IBIOS, T_PCLITE,   SUBTYPE, 0, NULL, "X/em",	"sxbios.bin", DEFAULT_LOC "sxbios.bin", 0 },
-{IFEP,  T_PCLITE,   SUBTYPE, 0,  NULL,  "X/em",	"sxfep.bin", DEFAULT_LOC "sxfep.bin", 0  },
-
-{IBIOS, T_EPC,      T_PCIBUS, 0, NULL, "PCI",	"pcibios.bin", DEFAULT_LOC "pcibios.bin", 0 },
-{IFEP,  T_EPC,      T_PCIBUS, 0, NULL, "PCI",	"pcifep.bin", DEFAULT_LOC "pcifep.bin", 0 },
-{ICONFIG, 0,	    0, 0, NULL,         NULL,	"dgap.conf",	"/etc/dgap.conf", 0 },
-
-/* IBAD/NULL entry indicating end-of-table */
-
-{IBAD,  0,     0, 0,  NULL,  NULL, NULL, NULL, 0 }
-
-} ;
-
-int 	errorprint = 1;
-int 	nodldprint = 1;
-int	debugflag;
-int 	fd;
-
-struct downld_t *ip;	/* Image pointer in current image  */
-struct downld_t *dp; 	/* conc. download */
-
-
-/*
- * The same for either the FEP or the BIOS.
- *  Append the downldio header, issue the ioctl, then free
- *  the buffer.  Not horribly CPU efficient, but quite RAM efficient.
- */
-
-void squirt(int req_type, int bdid, struct image_info *ii)
-{
-	struct downldio	*dliop;
-	int size_buf;
-	int sfd;
-	struct stat sb;
-
-	/*
-	 * If this binary comes from a file, stat it to see how
-	 * large it is. Yes, we intentionally do this each
-	 * time for the binary may change between loads.
-	 */
-
-	if (ii->pathname) {
-		sfd = open(ii->pathname, O_RDONLY);
-
-		if (sfd < 0 ) {
-			myperror(ii->pathname);
-			goto squirt_end;
-		}
-
-		if (fstat(sfd, &sb) == -1 ) {
-			myperror(ii->pathname);
-			goto squirt_end;
-		}
-
-		ii->len = sb.st_size;
-	}
-
-	size_buf = ii->len + sizeof(struct downldio);
-
-	/*
-	 * This buffer will be freed at the end of this function.  It is
-	 * not resilient and should be around only long enough for the d/l
-	 * to happen.
-	 */
-	dliop = (struct downldio *) malloc(size_buf);
-
-	if (dliop == NULL) {
-		fprintf(stderr,"%s: can't get %d bytes of memory; aborting\n",
-			pgm, size_buf);
-		exit (1);
-	}
-
-	/* Now, stick the image in fepimage.  This can come from either
-	 *  the compiled-in image or from the filesystem.
-	 */
-	if (ii->pathname)
-		read(sfd, dliop->image.fi.fepimage, ii->len);
-	else
-		memcpy(dliop ->image.fi.fepimage, ii->image, ii->len);
-
-	dliop->req_type = req_type;
-	dliop->bdid = bdid;
-
-	dliop->image.fi.len = ii->len;
-
-	if (debugflag)
-		printf("sending %d bytes of %s %s from %s\n",
-			ii->len,
-			(ii->type == IFEP) ? "FEP" : (ii->type == IBIOS) ? "BIOS" : "CONFIG",
-			ii->name ? ii->name : "",
-			(ii->pathname) ? ii->pathname : "internal image" );
-
-	if (ioctl(fd, DIGI_DLREQ_SET, (char *) dliop) == -1) {
-		if(errorprint) {
-			fprintf(stderr,
-				"%s: warning - download ioctl failed\n",pgm);
-			errorprint = 0;
-		}
-		sleep(2);
-	}
-
-squirt_end:
-
-	if (ii->pathname) {
-		close(sfd);
-	}
-	free(dliop);
-}
-
-
-/*
- *  See if we need to reload the download image in core
- *
- */
-void consider_file_rescan(struct image_info *ii)
-{
-	int sfd;
-	int len;
-	struct stat 	sb;
-
-	/* This operation only makes sense when we're working from a file */
-
-	if (ii->pathname) {
-
-		sfd = open (ii->pathname, O_RDONLY) ;
-		if (sfd < 0 ) {
-			myperror(ii->pathname);
-			exit(1) ;
-		}
-
-		if( fstat(sfd,&sb) == -1 ) {
-			myperror(ii->pathname);
-			exit(1);
-		}
-
-		/* If the file hasn't changed since we last did this,
-		 * and we have not done a free() on the image, bail
-		 */
-		if (ii->image && (sb.st_mtime == ii->mtime))
-			goto end_rescan;
-
-		ii->len = len = sb.st_size;
-
-		/* Record the timestamp of the file */
-		ii->mtime = sb.st_mtime;
-
-		/* image should be NULL unless there is an image malloced
-		 * in already.  Before we malloc again, make sure we don't
-		 * have a memory leak.
-		 */
-		if ( ii->image ) {
-			free( ii->image );
-			/* ii->image = NULL; */ /* not necessary */
-		}
-
-		/* This image will be kept only long enough for the
-		 * download to happen.  After sending the last block,
-		 * it will be freed
-		 */
-		ii->image = malloc(len) ;
-
-		if (ii->image == NULL) {
-			fprintf(stderr,
-				"%s: can't get %d bytes of memory; aborting\n",
-				 pgm, len);
-			exit (1);
-		}
-
-		if (read(sfd, ii->image, len) < len) {
-			fprintf(stderr,"%s: read error on %s; aborting\n",
-				pgm, ii->pathname);
-			exit (1);
-		}
-
-end_rescan:
-		close(sfd);
-
-	}
-}
-
-/*
- * Scan for images to match the driver requests
- */
-
-struct image_info * find_conc_image()
-{
-	int x;
-	struct image_info *i = NULL;
-
-	for ( x = 0; x < nimages; x++ ) {
-		i=&image_list[x];
-
-		if(i->type != ICONC)
-			continue;
-
-		consider_file_rescan(i) ;
-
-		ip = (struct downld_t *) image_list[x].image;
-		if (ip == NULL) continue;
-
-		/*
-		 * When I removed Clusterport, I kept only the code that I
-		 * was SURE wasn't ClusterPort.  We may not need the next two
-		 * lines of code.
-		 */
-		if ((dp->dl_type != 'P' ) && ( ip->dl_srev == dp->dl_srev ))
-			return i;
-	}
-	return NULL;
-}
-
-
-int main(int argc, char **argv)
-{
-	struct downldio	dlio;
-	int 		offset, bsize;
-	int 		x;
-	char 		*down, *image, *fname;
-	struct image_info *ii;
-
-	pgm = argv[0];
-	dp = &dlio.image.dl;		/* conc. download */
-
-	while((argc > 2) && !strcmp(argv[1],"-d")) {
-		debugflag++ ;
-		argc-- ;
-		argv++ ;
-	}
-
-	if(argc < 2) {
-		fprintf(stderr,
-			"usage: %s download-device [image-file] ...\n",
-			pgm);
-		exit(1);
-	}
-
-
-
-	/*
-	 * Daemonize, unless debugging is turned on.
-	 */
-	if (debugflag == 0) {
-		switch (fork())
-		{
-		case 0:
-			break;
-
-		case -1:
-			return 1;
-
-		default:
-			return 0;
-		}
-
-		setsid();
-
-		/*
-		 * The child no longer needs "stdin", "stdout", or "stderr",
-		 * and should not block processes waiting for them to close.
-		 */
-		fclose(stdin);
-		fclose(stdout);
-		fclose(stderr);
-
-	}
-
-	while (1) {
-		if( (fd = open(argv[1], O_RDWR)) == -1 ) {
-			sleep(1);
-		}
-		else
-			break;
-	}
-
-	/*
-	** create a list of images to search through when trying to match
-	** requests from the driver.  Put images from the command line in
-	** the list before built in images so that the command line images
-	** can override the built in ones.
-	*/
-
-	/* allocate space for the list */
-
-	nimages = argc - 2;
-
-	/* count the number of default list entries */
-
-	for (count = 0; images[count].type != IBAD; ++count) ;
-
-	nimages += count;
-
-	/* Really should just remove the variable "image_list".... robertl */
-	image_list = images;
-
-	/* get the images from the command line */
-	for(x = 2; x < argc; x++) {
-		int xx;
-
-		/*
-		 * strip off any leading path information for
-		 * determining file type
-		 */
-		if( (fname = strrchr(argv[x],'/')) == NULL)
-			fname = argv[x];
-		else
-			fname++;	/* skip the slash */
-
-		for (xx = 0; xx < count; xx++) {
-			if (strcmp(fname, images[xx].fname) == 0 ) {
-				images[xx].pathname = argv[x];
-
-				/* image should be NULL until */
-				/* space is malloced */
-				images[xx].image = NULL;
-			}
-		}
-	}
-
-        sleep(3);
-
-	/*
-	** Endless loop: get a request from the fep, and service that request.
-	*/
-	for(;;) {
-		/* get the request */
-		if (debugflag)
-			printf("b4 get ioctl...");
-
-		if (ioctl(fd,DIGI_DLREQ_GET, &dlio) == -1 ) {
-			if (errorprint) {
-				fprintf(stderr,
-					"%s: warning - download ioctl failed\n",
-					pgm);
-				errorprint = 0;
-			}
-			sleep(2);
-		} else {
-			if (debugflag)
-				printf("dlio.req_type is %d bd %d\n",
-					dlio.req_type,dlio.bdid);
-
-			switch(dlio.req_type) {
-			case DLREQ_BIOS:
-				/*
-				** find the bios image for this type
-				*/
-				for ( x = 0; x < nimages; x++ ) {
-					if(image_list[x].type != IBIOS)
-						continue;
-
-					if ((dlio.image.fi.type & FAMILY) ==
-						image_list[x].family) {
-
-						if ( image_list[x].family == T_CX   ) {
-							if ((dlio.image.fi.type & BUSTYPE)
-								== T_PCIBUS ) {
-								if ( image_list[x].subtype
-									== T_PCIBUS )
-									break;
-							}
-							else {
-								break;
-							}
-						}
-						else if ( image_list[x].family == T_EPC ) {
-						/* If subtype of image is T_PCIBUS, it is */
-						/* a PCI EPC image, so the board must */
-						/* have bus type T_PCIBUS to match */
-							if ((dlio.image.fi.type & BUSTYPE)
-								== T_PCIBUS ) {
-								if ( image_list[x].subtype
-									== T_PCIBUS )
-									break;
-							}
-							else {
-							/* NON PCI EPC doesn't use PCI image */
-								if ( image_list[x].subtype
-									!= T_PCIBUS )
-									break;
-							}
-						}
-						else
-							break;
-					}
-					else if ((dlio.image.fi.type & SUBTYPE) == image_list[x].subtype) {
-						/* PCXR board will break out of the loop here */
-						if ( image_list[x].subtype == T_PCXR   ) {
-									break;
-						}
-					}
-				}
-
-				if ( x >= nimages) {
-					/*
-					** no valid images exist
-					*/
-					if(nodldprint) {
-						fprintf(stderr,
-						"%s: cannot find correct BIOS image\n",
-							pgm);
-						nodldprint = 0;
-					}
-					dlio.image.fi.type = -1;
-					if (ioctl(fd, DIGI_DLREQ_SET, &dlio) == -1) {
-						if (errorprint) {
-							fprintf(stderr,
-							"%s: warning - download ioctl failed\n",
-							pgm);
-							errorprint = 0;
-						}
-						sleep(2);
-					}
-					break;
-				}
-				squirt(dlio.req_type, dlio.bdid, &image_list[x]);
-				break ;
-
-			case DLREQ_FEP:
-				/*
-				** find the fep image for this type
-				*/
-				for ( x = 0; x < nimages; x++ ) {
-					if(image_list[x].type != IFEP)
-						continue;
-					if( (dlio.image.fi.type & FAMILY) ==
-						image_list[x].family ) {
-						if ( image_list[x].family == T_CX   ) {
-							/* C/X PCI board */
-							if ((dlio.image.fi.type & BUSTYPE)
-								== T_PCIBUS ) {
-								if ( image_list[x].subtype
-									== T_PCIBUS )
-									break;
-							}
-							else {
-							/* Regular CX */
-								break;
-							}
-						}
-						else if ( image_list[x].family == T_EPC   )  {
-						/* If subtype of image is T_PCIBUS, it is */
-						/* a PCI EPC image, so the board must */
-						/* have bus type T_PCIBUS to match */
-							if ((dlio.image.fi.type & BUSTYPE)
-								== T_PCIBUS ) {
-								if ( image_list[x].subtype
-									== T_PCIBUS )
-									break;
-							}
-							else {
-							/* NON PCI EPC doesn't use PCI image */
-								if ( image_list[x].subtype
-									!= T_PCIBUS )
-									break;
-							}
-						}
-						else
-							break;
-					}
-					else if ((dlio.image.fi.type & SUBTYPE) == image_list[x].subtype) {
-						/* PCXR board will break out of the loop here */
-						if ( image_list[x].subtype == T_PCXR   ) {
-									break;
-						}
-					}
-				}
-
-				if ( x >= nimages) {
-					/*
-					** no valid images exist
-					*/
-					if(nodldprint) {
-						fprintf(stderr,
-						"%s: cannot find correct FEP image\n",
-							pgm);
-						nodldprint = 0;
-					}
-					dlio.image.fi.type=-1;
-					if( ioctl(fd,DIGI_DLREQ_SET,&dlio) == -1 ) {
-						if(errorprint) {
-							fprintf(stderr,
-						"%s: warning - download ioctl failed\n",
-								pgm);
-							errorprint=0;
-						}
-						sleep(2);
-					}
-					break;
-				}
-				squirt(dlio.req_type, dlio.bdid, &image_list[x]);
-				break;
-
-			case DLREQ_DEVCREATE:
-				{
-					char string[1024];
-#if 0
-					sprintf(string, "%s /proc/dgap/%d/mknod", DEFSHELL, dlio.bdid);
-#endif
-					sprintf(string, "%s /usr/sbin/dgap_updatedevs %d", DEFSHELL, dlio.bdid);
-					system(string);
-
-					if (debugflag)
-						printf("Created Devices.\n");
-					if (ioctl(fd, DIGI_DLREQ_SET, &dlio) == -1 ) {
-						if(errorprint) {
-							fprintf(stderr, "%s: warning - DEVCREATE ioctl failed\n",pgm);
-							errorprint = 0;
-						}
-						sleep(2);
-					}
-					if (debugflag)
-						printf("After ioctl set - Created Device.\n");
-				}
-
-				break;
-
-			case DLREQ_CONFIG:
-				for ( x = 0; x < nimages; x++ ) {
-					if(image_list[x].type != ICONFIG)
-						continue;
-					else
-						break;
-				}
-
-				if ( x >= nimages) {
-					/*
-					** no valid images exist
-					*/
-					if(nodldprint) {
-						fprintf(stderr,
-						"%s: cannot find correct CONFIG image\n",
-							pgm);
-						nodldprint = 0;
-					}
-					dlio.image.fi.type=-1;
-					if (ioctl(fd, DIGI_DLREQ_SET, &dlio) == -1 ) {
-						if(errorprint) {
-							fprintf(stderr,
-						"%s: warning - download ioctl failed\n",
-								pgm);
-							errorprint=0;
-						}
-						sleep(2);
-					}
-					break;
-				}
-
-				squirt(dlio.req_type, dlio.bdid, &image_list[x]);
-				break;
-
-			case DLREQ_CONC:
-				/*
-				** find the image needed for this download
-				*/
-				if ( dp->dl_seq == 0 ) {
-					/*
-					** find image for hardware rev range
-					*/
-					for ( x = 0; x < nimages; x++ ) {
-						ii=&image_list[x];
-
-						if(image_list[x].type != ICONC)
-							continue;
-
-						consider_file_rescan(ii) ;
-
-						ip = (struct downld_t *) image_list[x].image;
-						if (ip == NULL) continue;
-
-						/*
-						 * When I removed Clusterport, I kept only the
-						 * code that I was SURE wasn't ClusterPort.
-						 * We may not need the next four lines of code.
-						 */
-
-						if ((dp->dl_type != 'P' ) &&
-						 (ip->dl_lrev <= dp->dl_lrev ) &&
-						 ( dp->dl_lrev <= ip->dl_hrev))
-							break;
-					}
-
-					if ( x >= nimages ) {
-						/*
-						** No valid images exist
-						*/
-						if(nodldprint) {
-							fprintf(stderr,
-						"%s: cannot find correct download image %d\n",
-								pgm, dp->dl_lrev);
-							nodldprint=0;
-						}
-						continue;
-					}
-
-				} else {
-					/*
-					** find image version required
-					*/
-					if ((ii = find_conc_image()) == NULL ) {
-						/*
-						** No valid images exist
-						*/
-						fprintf(stderr,
-						"%s: can't find rest of download image??\n",
-							pgm);
-						continue;
-					}
-				}
-
-				/*
-				** download block of image
-				*/
-
-				offset = 1024 * dp->dl_seq;
-
-				/*
-				** test if block requested within image
-				*/
-				if ( offset < ii->len ) {
-
-					/*
-					** if it is, determine block size, set segment,
-					** set size, set pointers, and copy block
-					*/
-					if (( bsize = ii->len - offset ) > 1024 )
-						bsize = 1024;
-
-					/*
-					** copy image version info to download area
-					*/
-					dp->dl_srev = ip->dl_srev;
-					dp->dl_lrev = ip->dl_lrev;
-					dp->dl_hrev = ip->dl_hrev;
-
-					dp->dl_seg = (64 * dp->dl_seq) + ip->dl_seg;
-					dp->dl_size = bsize;
-
-					down = (char *)&dp->dl_data[0];
-					image = (char *)((char *)ip + offset);
-
-					memcpy(down, image, bsize);
-				}
-				else {
-					/*
-					** Image has been downloaded, set segment and
-					** size to indicate no more blocks
-					*/
-					dp->dl_seg = ip->dl_seg;
-					dp->dl_size = 0;
-
-					/* Now, we can release the concentrator */
-					/* image from memory if we're running  */
-					/* from filesystem images */
-
-					if (ii->pathname)
-						if (ii->image) {
-							free(ii->image);
-							ii->image = NULL;
-						}
-				}
-
-				if (debugflag)
-						printf(
-						"sending conc dl section %d to %s from %s\n",
-							dp->dl_seq, ii->name,
-						ii->pathname ? ii->pathname : "Internal Image");
-
-				if (ioctl(fd, DIGI_DLREQ_SET, &dlio) == -1 ) {
-					if (errorprint) {
-						fprintf(stderr,
-						"%s: warning - download ioctl failed\n",
-							pgm);
-						errorprint=0;
-					}
-					sleep(2);
-				}
-				break;
-			} /* switch */
-		}
-		if (debugflag > 1) {
-			printf("pausing: "); fflush(stdout);
-			fflush(stdin);
-			while(getchar() != '\n');
-				printf("continuing\n");
-		}
-	}
-}
-
-/*
-** myperror()
-**
-**  Same as normal perror(), but places the program name at the beginning
-**  of the message.
-*/
-void myperror(char *s)
-{
-	fprintf(stderr,"%s: %s: %s.\n",pgm, s, strerror(errno));
-}
diff --git a/drivers/staging/echo/TODO b/drivers/staging/echo/TODO
deleted file mode 100644
index 72a311a..0000000
--- a/drivers/staging/echo/TODO
+++ /dev/null
@@ -1,5 +0,0 @@
-TODO:
-	- send to lkml for review
-
-Please send patches to Greg Kroah-Hartman <greg@kroah.com> and Cc: Steve
-Underwood <steveu@coppice.org> and David Rowe <david@rowetel.com>
diff --git a/drivers/staging/iio/adc/mxs-lradc.c b/drivers/staging/iio/adc/mxs-lradc.c
index ab3c0d4..25bea055 100644
--- a/drivers/staging/iio/adc/mxs-lradc.c
+++ b/drivers/staging/iio/adc/mxs-lradc.c
@@ -757,6 +757,7 @@
 	}
 
 	/* if it is released, wait for the next touch via IRQ */
+	lradc->cur_plate = LRADC_TOUCH;
 	mxs_lradc_reg_clear(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ, LRADC_CTRL1);
 	mxs_lradc_reg_set(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ_EN, LRADC_CTRL1);
 }
diff --git a/drivers/staging/imx-drm/Kconfig b/drivers/staging/imx-drm/Kconfig
index 78319ad..c6e8ba7 100644
--- a/drivers/staging/imx-drm/Kconfig
+++ b/drivers/staging/imx-drm/Kconfig
@@ -20,6 +20,7 @@
 
 config DRM_IMX_PARALLEL_DISPLAY
 	tristate "Support for parallel displays"
+	select DRM_PANEL
 	depends on DRM_IMX
 	select VIDEOMODE_HELPERS
 
diff --git a/drivers/staging/imx-drm/Makefile b/drivers/staging/imx-drm/Makefile
index 4677585..129e3a3 100644
--- a/drivers/staging/imx-drm/Makefile
+++ b/drivers/staging/imx-drm/Makefile
@@ -1,12 +1,11 @@
 
-imxdrm-objs := imx-drm-core.o imx-fb.o
+imxdrm-objs := imx-drm-core.o
 
 obj-$(CONFIG_DRM_IMX) += imxdrm.o
 
 obj-$(CONFIG_DRM_IMX_PARALLEL_DISPLAY) += parallel-display.o
 obj-$(CONFIG_DRM_IMX_TVE) += imx-tve.o
 obj-$(CONFIG_DRM_IMX_LDB) += imx-ldb.o
-obj-$(CONFIG_DRM_IMX_FB_HELPER) += imx-fbdev.o
 obj-$(CONFIG_DRM_IMX_IPUV3_CORE) += ipu-v3/
 
 imx-ipuv3-crtc-objs  := ipuv3-crtc.o ipuv3-plane.o
diff --git a/drivers/staging/imx-drm/imx-drm-core.c b/drivers/staging/imx-drm/imx-drm-core.c
index 236ed66..6b91c8e 100644
--- a/drivers/staging/imx-drm/imx-drm-core.c
+++ b/drivers/staging/imx-drm/imx-drm-core.c
@@ -13,14 +13,14 @@
  * GNU General Public License for more details.
  *
  */
-
+#include <linux/component.h>
 #include <linux/device.h>
+#include <linux/fb.h>
+#include <linux/module.h>
 #include <linux/platform_device.h>
 #include <drm/drmP.h>
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_crtc_helper.h>
-#include <linux/fb.h>
-#include <linux/module.h>
 #include <drm/drm_gem_cma_helper.h>
 #include <drm/drm_fb_cma_helper.h>
 
@@ -28,45 +28,26 @@
 
 #define MAX_CRTC	4
 
-struct crtc_cookie {
-	void *cookie;
-	int id;
-	struct list_head list;
-};
+struct imx_drm_crtc;
 
 struct imx_drm_device {
 	struct drm_device			*drm;
-	struct device				*dev;
-	struct list_head			crtc_list;
-	struct list_head			encoder_list;
-	struct list_head			connector_list;
-	struct mutex				mutex;
+	struct imx_drm_crtc			*crtc[MAX_CRTC];
 	int					pipes;
 	struct drm_fbdev_cma			*fbhelper;
 };
 
 struct imx_drm_crtc {
 	struct drm_crtc				*crtc;
-	struct list_head			list;
-	struct imx_drm_device			*imxdrm;
 	int					pipe;
 	struct imx_drm_crtc_helper_funcs	imx_drm_helper_funcs;
-	struct module				*owner;
-	struct crtc_cookie			cookie;
+	void					*cookie;
+	int					id;
+	int					mux_id;
 };
 
-struct imx_drm_encoder {
-	struct drm_encoder			*encoder;
-	struct list_head			list;
-	struct module				*owner;
-	struct list_head			possible_crtcs;
-};
-
-struct imx_drm_connector {
-	struct drm_connector			*connector;
-	struct list_head			list;
-	struct module				*owner;
-};
+static int legacyfb_depth = 16;
+module_param(legacyfb_depth, int, 0444);
 
 int imx_drm_crtc_id(struct imx_drm_crtc *crtc)
 {
@@ -76,69 +57,71 @@
 
 static void imx_drm_driver_lastclose(struct drm_device *drm)
 {
+#if IS_ENABLED(CONFIG_DRM_IMX_FB_HELPER)
 	struct imx_drm_device *imxdrm = drm->dev_private;
 
 	if (imxdrm->fbhelper)
 		drm_fbdev_cma_restore_mode(imxdrm->fbhelper);
+#endif
 }
 
 static int imx_drm_driver_unload(struct drm_device *drm)
 {
+#if IS_ENABLED(CONFIG_DRM_IMX_FB_HELPER)
 	struct imx_drm_device *imxdrm = drm->dev_private;
+#endif
 
-	imx_drm_device_put();
+	drm_kms_helper_poll_fini(drm);
+
+#if IS_ENABLED(CONFIG_DRM_IMX_FB_HELPER)
+	if (imxdrm->fbhelper)
+		drm_fbdev_cma_fini(imxdrm->fbhelper);
+#endif
+
+	component_unbind_all(drm->dev, drm);
 
 	drm_vblank_cleanup(drm);
-	drm_kms_helper_poll_fini(drm);
 	drm_mode_config_cleanup(drm);
 
 	return 0;
 }
 
-/*
- * We don't care at all for crtc numbers, but the core expects the
- * crtcs to be numbered
- */
-static struct imx_drm_crtc *imx_drm_crtc_by_num(struct imx_drm_device *imxdrm,
-		int num)
+static struct imx_drm_crtc *imx_drm_find_crtc(struct drm_crtc *crtc)
 {
-	struct imx_drm_crtc *imx_drm_crtc;
+	struct imx_drm_device *imxdrm = crtc->dev->dev_private;
+	unsigned i;
 
-	list_for_each_entry(imx_drm_crtc, &imxdrm->crtc_list, list)
-		if (imx_drm_crtc->pipe == num)
-			return imx_drm_crtc;
+	for (i = 0; i < MAX_CRTC; i++)
+		if (imxdrm->crtc[i] && imxdrm->crtc[i]->crtc == crtc)
+			return imxdrm->crtc[i];
+
 	return NULL;
 }
 
-int imx_drm_crtc_panel_format_pins(struct drm_crtc *crtc, u32 encoder_type,
+int imx_drm_panel_format_pins(struct drm_encoder *encoder,
 		u32 interface_pix_fmt, int hsync_pin, int vsync_pin)
 {
-	struct imx_drm_device *imxdrm = crtc->dev->dev_private;
-	struct imx_drm_crtc *imx_crtc;
 	struct imx_drm_crtc_helper_funcs *helper;
+	struct imx_drm_crtc *imx_crtc;
 
-	list_for_each_entry(imx_crtc, &imxdrm->crtc_list, list)
-		if (imx_crtc->crtc == crtc)
-			goto found;
+	imx_crtc = imx_drm_find_crtc(encoder->crtc);
+	if (!imx_crtc)
+		return -EINVAL;
 
-	return -EINVAL;
-found:
 	helper = &imx_crtc->imx_drm_helper_funcs;
 	if (helper->set_interface_pix_fmt)
-		return helper->set_interface_pix_fmt(crtc,
-				encoder_type, interface_pix_fmt,
+		return helper->set_interface_pix_fmt(encoder->crtc,
+				encoder->encoder_type, interface_pix_fmt,
 				hsync_pin, vsync_pin);
 	return 0;
 }
-EXPORT_SYMBOL_GPL(imx_drm_crtc_panel_format_pins);
+EXPORT_SYMBOL_GPL(imx_drm_panel_format_pins);
 
-int imx_drm_crtc_panel_format(struct drm_crtc *crtc, u32 encoder_type,
-		u32 interface_pix_fmt)
+int imx_drm_panel_format(struct drm_encoder *encoder, u32 interface_pix_fmt)
 {
-	return imx_drm_crtc_panel_format_pins(crtc, encoder_type,
-					      interface_pix_fmt, 2, 3);
+	return imx_drm_panel_format_pins(encoder, interface_pix_fmt, 2, 3);
 }
-EXPORT_SYMBOL_GPL(imx_drm_crtc_panel_format);
+EXPORT_SYMBOL_GPL(imx_drm_panel_format);
 
 int imx_drm_crtc_vblank_get(struct imx_drm_crtc *imx_drm_crtc)
 {
@@ -161,10 +144,9 @@
 static int imx_drm_enable_vblank(struct drm_device *drm, int crtc)
 {
 	struct imx_drm_device *imxdrm = drm->dev_private;
-	struct imx_drm_crtc *imx_drm_crtc;
+	struct imx_drm_crtc *imx_drm_crtc = imxdrm->crtc[crtc];
 	int ret;
 
-	imx_drm_crtc = imx_drm_crtc_by_num(imxdrm, crtc);
 	if (!imx_drm_crtc)
 		return -EINVAL;
 
@@ -180,9 +162,8 @@
 static void imx_drm_disable_vblank(struct drm_device *drm, int crtc)
 {
 	struct imx_drm_device *imxdrm = drm->dev_private;
-	struct imx_drm_crtc *imx_drm_crtc;
+	struct imx_drm_crtc *imx_drm_crtc = imxdrm->crtc[crtc];
 
-	imx_drm_crtc = imx_drm_crtc_by_num(imxdrm, crtc);
 	if (!imx_drm_crtc)
 		return;
 
@@ -215,172 +196,54 @@
 	.llseek = noop_llseek,
 };
 
-static struct imx_drm_device *imx_drm_device;
-
-static struct imx_drm_device *__imx_drm_device(void)
+int imx_drm_connector_mode_valid(struct drm_connector *connector,
+	struct drm_display_mode *mode)
 {
-	return imx_drm_device;
+	return MODE_OK;
+}
+EXPORT_SYMBOL(imx_drm_connector_mode_valid);
+
+void imx_drm_connector_destroy(struct drm_connector *connector)
+{
+	drm_sysfs_connector_remove(connector);
+	drm_connector_cleanup(connector);
+}
+EXPORT_SYMBOL_GPL(imx_drm_connector_destroy);
+
+void imx_drm_encoder_destroy(struct drm_encoder *encoder)
+{
+	drm_encoder_cleanup(encoder);
+}
+EXPORT_SYMBOL_GPL(imx_drm_encoder_destroy);
+
+static void imx_drm_output_poll_changed(struct drm_device *drm)
+{
+#if IS_ENABLED(CONFIG_DRM_IMX_FB_HELPER)
+	struct imx_drm_device *imxdrm = drm->dev_private;
+
+	drm_fbdev_cma_hotplug_event(imxdrm->fbhelper);
+#endif
 }
 
-struct drm_device *imx_drm_device_get(void)
-{
-	struct imx_drm_device *imxdrm = __imx_drm_device();
-	struct imx_drm_encoder *enc;
-	struct imx_drm_connector *con;
-	struct imx_drm_crtc *crtc;
-
-	list_for_each_entry(enc, &imxdrm->encoder_list, list) {
-		if (!try_module_get(enc->owner)) {
-			dev_err(imxdrm->dev, "could not get module %s\n",
-					module_name(enc->owner));
-			goto unwind_enc;
-		}
-	}
-
-	list_for_each_entry(con, &imxdrm->connector_list, list) {
-		if (!try_module_get(con->owner)) {
-			dev_err(imxdrm->dev, "could not get module %s\n",
-					module_name(con->owner));
-			goto unwind_con;
-		}
-	}
-
-	list_for_each_entry(crtc, &imxdrm->crtc_list, list) {
-		if (!try_module_get(crtc->owner)) {
-			dev_err(imxdrm->dev, "could not get module %s\n",
-					module_name(crtc->owner));
-			goto unwind_crtc;
-		}
-	}
-
-	return imxdrm->drm;
-
-unwind_crtc:
-	list_for_each_entry_continue_reverse(crtc, &imxdrm->crtc_list, list)
-		module_put(crtc->owner);
-unwind_con:
-	list_for_each_entry_continue_reverse(con, &imxdrm->connector_list, list)
-		module_put(con->owner);
-unwind_enc:
-	list_for_each_entry_continue_reverse(enc, &imxdrm->encoder_list, list)
-		module_put(enc->owner);
-
-	mutex_unlock(&imxdrm->mutex);
-
-	return NULL;
-
-}
-EXPORT_SYMBOL_GPL(imx_drm_device_get);
-
-void imx_drm_device_put(void)
-{
-	struct imx_drm_device *imxdrm = __imx_drm_device();
-	struct imx_drm_encoder *enc;
-	struct imx_drm_connector *con;
-	struct imx_drm_crtc *crtc;
-
-	mutex_lock(&imxdrm->mutex);
-
-	list_for_each_entry(crtc, &imxdrm->crtc_list, list)
-		module_put(crtc->owner);
-
-	list_for_each_entry(con, &imxdrm->connector_list, list)
-		module_put(con->owner);
-
-	list_for_each_entry(enc, &imxdrm->encoder_list, list)
-		module_put(enc->owner);
-
-	mutex_unlock(&imxdrm->mutex);
-}
-EXPORT_SYMBOL_GPL(imx_drm_device_put);
-
-static int drm_mode_group_reinit(struct drm_device *dev)
-{
-	struct drm_mode_group *group = &dev->primary->mode_group;
-	uint32_t *id_list = group->id_list;
-	int ret;
-
-	ret = drm_mode_group_init_legacy_group(dev, group);
-	if (ret < 0)
-		return ret;
-
-	kfree(id_list);
-	return 0;
-}
+static struct drm_mode_config_funcs imx_drm_mode_config_funcs = {
+	.fb_create = drm_fb_cma_create,
+	.output_poll_changed = imx_drm_output_poll_changed,
+};
 
 /*
- * register an encoder to the drm core
- */
-static int imx_drm_encoder_register(struct imx_drm_encoder *imx_drm_encoder)
-{
-	struct imx_drm_device *imxdrm = __imx_drm_device();
-
-	INIT_LIST_HEAD(&imx_drm_encoder->possible_crtcs);
-
-	drm_encoder_init(imxdrm->drm, imx_drm_encoder->encoder,
-			imx_drm_encoder->encoder->funcs,
-			imx_drm_encoder->encoder->encoder_type);
-
-	drm_mode_group_reinit(imxdrm->drm);
-
-	return 0;
-}
-
-/*
- * unregister an encoder from the drm core
- */
-static void imx_drm_encoder_unregister(struct imx_drm_encoder
-		*imx_drm_encoder)
-{
-	struct imx_drm_device *imxdrm = __imx_drm_device();
-
-	drm_encoder_cleanup(imx_drm_encoder->encoder);
-
-	drm_mode_group_reinit(imxdrm->drm);
-}
-
-/*
- * register a connector to the drm core
- */
-static int imx_drm_connector_register(
-		struct imx_drm_connector *imx_drm_connector)
-{
-	struct imx_drm_device *imxdrm = __imx_drm_device();
-
-	drm_connector_init(imxdrm->drm, imx_drm_connector->connector,
-			imx_drm_connector->connector->funcs,
-			imx_drm_connector->connector->connector_type);
-	drm_mode_group_reinit(imxdrm->drm);
-
-	return drm_sysfs_connector_add(imx_drm_connector->connector);
-}
-
-/*
- * unregister a connector from the drm core
- */
-static void imx_drm_connector_unregister(
-		struct imx_drm_connector *imx_drm_connector)
-{
-	struct imx_drm_device *imxdrm = __imx_drm_device();
-
-	drm_sysfs_connector_remove(imx_drm_connector->connector);
-	drm_connector_cleanup(imx_drm_connector->connector);
-
-	drm_mode_group_reinit(imxdrm->drm);
-}
-
-/*
- * Called by the CRTC driver when all CRTCs are registered. This
- * puts all the pieces together and initializes the driver.
- * Once this is called no more CRTCs can be registered since
- * the drm core has hardcoded the number of crtcs in several
- * places.
+ * Main DRM initialisation. This binds, initialises and registers
+ * with DRM the subcomponents of the driver.
  */
 static int imx_drm_driver_load(struct drm_device *drm, unsigned long flags)
 {
-	struct imx_drm_device *imxdrm = __imx_drm_device();
+	struct imx_drm_device *imxdrm;
+	struct drm_connector *connector;
 	int ret;
 
+	imxdrm = devm_kzalloc(drm->dev, sizeof(*imxdrm), GFP_KERNEL);
+	if (!imxdrm)
+		return -ENOMEM;
+
 	imxdrm->drm = drm;
 
 	drm->dev_private = imxdrm;
@@ -396,120 +259,123 @@
 	 */
 	drm->irq_enabled = true;
 
+	/*
+	 * set max width and height as default value(4096x4096).
+	 * this value would be used to check framebuffer size limitation
+	 * at drm_mode_addfb().
+	 */
+	drm->mode_config.min_width = 64;
+	drm->mode_config.min_height = 64;
+	drm->mode_config.max_width = 4096;
+	drm->mode_config.max_height = 4096;
+	drm->mode_config.funcs = &imx_drm_mode_config_funcs;
+
 	drm_mode_config_init(drm);
-	imx_drm_mode_config_init(drm);
-
-	mutex_lock(&imxdrm->mutex);
-
-	drm_kms_helper_poll_init(drm);
-
-	/* setup the grouping for the legacy output */
-	ret = drm_mode_group_init_legacy_group(drm,
-			&drm->primary->mode_group);
-	if (ret)
-		goto err_kms;
 
 	ret = drm_vblank_init(drm, MAX_CRTC);
 	if (ret)
 		goto err_kms;
 
 	/*
-	 * with vblank_disable_allowed = true, vblank interrupt will be disabled
-	 * by drm timer once a current process gives up ownership of
-	 * vblank event.(after drm_vblank_put function is called)
+	 * with vblank_disable_allowed = true, vblank interrupt will be
+	 * disabled by drm timer once a current process gives up ownership
+	 * of vblank event. (after drm_vblank_put function is called)
 	 */
 	drm->vblank_disable_allowed = true;
 
-	if (!imx_drm_device_get()) {
-		ret = -EINVAL;
+	platform_set_drvdata(drm->platformdev, drm);
+
+	/* Now try and bind all our sub-components */
+	ret = component_bind_all(drm->dev, drm);
+	if (ret)
 		goto err_vblank;
+
+	/*
+	 * All components are now added, we can publish the connector sysfs
+	 * entries to userspace.  This will generate hotplug events and so
+	 * userspace will expect to be able to access DRM at this point.
+	 */
+	list_for_each_entry(connector, &drm->mode_config.connector_list, head) {
+		ret = drm_sysfs_connector_add(connector);
+		if (ret) {
+			dev_err(drm->dev,
+				"[CONNECTOR:%d:%s] drm_sysfs_connector_add failed: %d\n",
+				connector->base.id,
+				drm_get_connector_name(connector), ret);
+			goto err_unbind;
+		}
 	}
 
-	platform_set_drvdata(drm->platformdev, drm);
-	mutex_unlock(&imxdrm->mutex);
+	/*
+	 * All components are now initialised, so setup the fb helper.
+	 * The fb helper takes copies of key hardware information, so the
+	 * crtcs/connectors/encoders must not change after this point.
+	 */
+#if IS_ENABLED(CONFIG_DRM_IMX_FB_HELPER)
+	if (legacyfb_depth != 16 && legacyfb_depth != 32) {
+		dev_warn(drm->dev, "Invalid legacyfb_depth.  Defaulting to 16bpp\n");
+		legacyfb_depth = 16;
+	}
+	imxdrm->fbhelper = drm_fbdev_cma_init(drm, legacyfb_depth,
+				drm->mode_config.num_crtc, MAX_CRTC);
+	if (IS_ERR(imxdrm->fbhelper)) {
+		ret = PTR_ERR(imxdrm->fbhelper);
+		imxdrm->fbhelper = NULL;
+		goto err_unbind;
+	}
+#endif
+
+	drm_kms_helper_poll_init(drm);
+
 	return 0;
 
+err_unbind:
+	component_unbind_all(drm->dev, drm);
 err_vblank:
 	drm_vblank_cleanup(drm);
 err_kms:
-	drm_kms_helper_poll_fini(drm);
 	drm_mode_config_cleanup(drm);
-	mutex_unlock(&imxdrm->mutex);
 
 	return ret;
 }
 
-static void imx_drm_update_possible_crtcs(void)
-{
-	struct imx_drm_device *imxdrm = __imx_drm_device();
-	struct imx_drm_crtc *imx_drm_crtc;
-	struct imx_drm_encoder *enc;
-	struct crtc_cookie *cookie;
-
-	list_for_each_entry(enc, &imxdrm->encoder_list, list) {
-		u32 possible_crtcs = 0;
-
-		list_for_each_entry(cookie, &enc->possible_crtcs, list) {
-			list_for_each_entry(imx_drm_crtc, &imxdrm->crtc_list, list) {
-				if (imx_drm_crtc->cookie.cookie == cookie->cookie &&
-						imx_drm_crtc->cookie.id == cookie->id) {
-					possible_crtcs |= 1 << imx_drm_crtc->pipe;
-				}
-			}
-		}
-		enc->encoder->possible_crtcs = possible_crtcs;
-		enc->encoder->possible_clones = possible_crtcs;
-	}
-}
-
 /*
  * imx_drm_add_crtc - add a new crtc
  *
  * The return value if !NULL is a cookie for the caller to pass to
  * imx_drm_remove_crtc later.
  */
-int imx_drm_add_crtc(struct drm_crtc *crtc,
+int imx_drm_add_crtc(struct drm_device *drm, struct drm_crtc *crtc,
 		struct imx_drm_crtc **new_crtc,
 		const struct imx_drm_crtc_helper_funcs *imx_drm_helper_funcs,
-		struct module *owner, void *cookie, int id)
+		void *cookie, int id)
 {
-	struct imx_drm_device *imxdrm = __imx_drm_device();
+	struct imx_drm_device *imxdrm = drm->dev_private;
 	struct imx_drm_crtc *imx_drm_crtc;
 	int ret;
 
-	mutex_lock(&imxdrm->mutex);
-
 	/*
 	 * The vblank arrays are dimensioned by MAX_CRTC - we can't
 	 * pass IDs greater than this to those functions.
 	 */
-	if (imxdrm->pipes >= MAX_CRTC) {
-		ret = -EINVAL;
-		goto err_busy;
-	}
+	if (imxdrm->pipes >= MAX_CRTC)
+		return -EINVAL;
 
-	if (imxdrm->drm->open_count) {
-		ret = -EBUSY;
-		goto err_busy;
-	}
+	if (imxdrm->drm->open_count)
+		return -EBUSY;
 
 	imx_drm_crtc = kzalloc(sizeof(*imx_drm_crtc), GFP_KERNEL);
-	if (!imx_drm_crtc) {
-		ret = -ENOMEM;
-		goto err_alloc;
-	}
+	if (!imx_drm_crtc)
+		return -ENOMEM;
 
 	imx_drm_crtc->imx_drm_helper_funcs = *imx_drm_helper_funcs;
 	imx_drm_crtc->pipe = imxdrm->pipes++;
-	imx_drm_crtc->cookie.cookie = cookie;
-	imx_drm_crtc->cookie.id = id;
-
+	imx_drm_crtc->cookie = cookie;
+	imx_drm_crtc->id = id;
+	imx_drm_crtc->mux_id = imx_drm_crtc->pipe;
 	imx_drm_crtc->crtc = crtc;
-	imx_drm_crtc->imxdrm = imxdrm;
 
-	imx_drm_crtc->owner = owner;
-
-	list_add_tail(&imx_drm_crtc->list, &imxdrm->crtc_list);
+	imxdrm->crtc[imx_drm_crtc->pipe] = imx_drm_crtc;
 
 	*new_crtc = imx_drm_crtc;
 
@@ -520,23 +386,14 @@
 	drm_crtc_helper_add(crtc,
 			imx_drm_crtc->imx_drm_helper_funcs.crtc_helper_funcs);
 
-	drm_crtc_init(imxdrm->drm, crtc,
+	drm_crtc_init(drm, crtc,
 			imx_drm_crtc->imx_drm_helper_funcs.crtc_funcs);
 
-	drm_mode_group_reinit(imxdrm->drm);
-
-	imx_drm_update_possible_crtcs();
-
-	mutex_unlock(&imxdrm->mutex);
-
 	return 0;
 
 err_register:
-	list_del(&imx_drm_crtc->list);
+	imxdrm->crtc[imx_drm_crtc->pipe] = NULL;
 	kfree(imx_drm_crtc);
-err_alloc:
-err_busy:
-	mutex_unlock(&imxdrm->mutex);
 	return ret;
 }
 EXPORT_SYMBOL_GPL(imx_drm_add_crtc);
@@ -546,17 +403,11 @@
  */
 int imx_drm_remove_crtc(struct imx_drm_crtc *imx_drm_crtc)
 {
-	struct imx_drm_device *imxdrm = imx_drm_crtc->imxdrm;
-
-	mutex_lock(&imxdrm->mutex);
+	struct imx_drm_device *imxdrm = imx_drm_crtc->crtc->dev->dev_private;
 
 	drm_crtc_cleanup(imx_drm_crtc->crtc);
 
-	list_del(&imx_drm_crtc->list);
-
-	drm_mode_group_reinit(imxdrm->drm);
-
-	mutex_unlock(&imxdrm->mutex);
+	imxdrm->crtc[imx_drm_crtc->pipe] = NULL;
 
 	kfree(imx_drm_crtc);
 
@@ -565,221 +416,79 @@
 EXPORT_SYMBOL_GPL(imx_drm_remove_crtc);
 
 /*
- * imx_drm_add_encoder - add a new encoder
+ * Find the DRM CRTC possible mask for the device node cookie/id.
+ *
+ * The encoder possible masks are defined by their position in the
+ * mode_config crtc_list.  This means that CRTCs must not be added
+ * or removed once the DRM device has been fully initialised.
  */
-int imx_drm_add_encoder(struct drm_encoder *encoder,
-		struct imx_drm_encoder **newenc, struct module *owner)
+static uint32_t imx_drm_find_crtc_mask(struct imx_drm_device *imxdrm,
+	void *cookie, int id)
 {
-	struct imx_drm_device *imxdrm = __imx_drm_device();
-	struct imx_drm_encoder *imx_drm_encoder;
-	int ret;
+	unsigned i;
 
-	mutex_lock(&imxdrm->mutex);
-
-	if (imxdrm->drm->open_count) {
-		ret = -EBUSY;
-		goto err_busy;
+	for (i = 0; i < MAX_CRTC; i++) {
+		struct imx_drm_crtc *imx_drm_crtc = imxdrm->crtc[i];
+		if (imx_drm_crtc && imx_drm_crtc->id == id &&
+		    imx_drm_crtc->cookie == cookie)
+			return drm_crtc_mask(imx_drm_crtc->crtc);
 	}
 
-	imx_drm_encoder = kzalloc(sizeof(*imx_drm_encoder), GFP_KERNEL);
-	if (!imx_drm_encoder) {
-		ret = -ENOMEM;
-		goto err_alloc;
-	}
-
-	imx_drm_encoder->encoder = encoder;
-	imx_drm_encoder->owner = owner;
-
-	ret = imx_drm_encoder_register(imx_drm_encoder);
-	if (ret) {
-		ret = -ENOMEM;
-		goto err_register;
-	}
-
-	list_add_tail(&imx_drm_encoder->list, &imxdrm->encoder_list);
-
-	*newenc = imx_drm_encoder;
-
-	mutex_unlock(&imxdrm->mutex);
-
 	return 0;
-
-err_register:
-	kfree(imx_drm_encoder);
-err_alloc:
-err_busy:
-	mutex_unlock(&imxdrm->mutex);
-
-	return ret;
 }
-EXPORT_SYMBOL_GPL(imx_drm_add_encoder);
 
-int imx_drm_encoder_add_possible_crtcs(
-		struct imx_drm_encoder *imx_drm_encoder,
-		struct device_node *np)
+int imx_drm_encoder_parse_of(struct drm_device *drm,
+	struct drm_encoder *encoder, struct device_node *np)
 {
-	struct imx_drm_device *imxdrm = __imx_drm_device();
-	struct of_phandle_args args;
-	struct crtc_cookie *c;
-	int ret = 0;
-	int i;
-
-	if (!list_empty(&imx_drm_encoder->possible_crtcs))
-		return -EBUSY;
+	struct imx_drm_device *imxdrm = drm->dev_private;
+	uint32_t crtc_mask = 0;
+	int i, ret = 0;
 
 	for (i = 0; !ret; i++) {
-		ret = of_parse_phandle_with_args(np, "crtcs",
-				"#crtc-cells", i, &args);
-		if (ret < 0)
+		struct of_phandle_args args;
+		uint32_t mask;
+		int id;
+
+		ret = of_parse_phandle_with_args(np, "crtcs", "#crtc-cells", i,
+						 &args);
+		if (ret == -ENOENT)
 			break;
+		if (ret < 0)
+			return ret;
 
-		c = kzalloc(sizeof(*c), GFP_KERNEL);
-		if (!c) {
-			of_node_put(args.np);
-			return -ENOMEM;
-		}
-
-		c->cookie = args.np;
-		c->id = args.args_count > 0 ? args.args[0] : 0;
-
+		id = args.args_count > 0 ? args.args[0] : 0;
+		mask = imx_drm_find_crtc_mask(imxdrm, args.np, id);
 		of_node_put(args.np);
 
-		mutex_lock(&imxdrm->mutex);
+		/*
+		 * If we failed to find the CRTC(s) which this encoder is
+		 * supposed to be connected to, it's because the CRTC has
+		 * not been registered yet.  Defer probing, and hope that
+		 * the required CRTC is added later.
+		 */
+		if (mask == 0)
+			return -EPROBE_DEFER;
 
-		list_add_tail(&c->list, &imx_drm_encoder->possible_crtcs);
-
-		mutex_unlock(&imxdrm->mutex);
+		crtc_mask |= mask;
 	}
 
-	imx_drm_update_possible_crtcs();
+	encoder->possible_crtcs = crtc_mask;
+
+	/* FIXME: this is the mask of outputs which can clone this output. */
+	encoder->possible_clones = ~0;
 
 	return 0;
 }
-EXPORT_SYMBOL_GPL(imx_drm_encoder_add_possible_crtcs);
+EXPORT_SYMBOL_GPL(imx_drm_encoder_parse_of);
 
-int imx_drm_encoder_get_mux_id(struct imx_drm_encoder *imx_drm_encoder,
-		struct drm_crtc *crtc)
+int imx_drm_encoder_get_mux_id(struct drm_encoder *encoder)
 {
-	struct imx_drm_device *imxdrm = __imx_drm_device();
-	struct imx_drm_crtc *imx_crtc;
-	int i = 0;
+	struct imx_drm_crtc *imx_crtc = imx_drm_find_crtc(encoder->crtc);
 
-	list_for_each_entry(imx_crtc, &imxdrm->crtc_list, list) {
-		if (imx_crtc->crtc == crtc)
-			goto found;
-		i++;
-	}
-
-	return -EINVAL;
-found:
-	return i;
+	return imx_crtc ? imx_crtc->mux_id : -EINVAL;
 }
 EXPORT_SYMBOL_GPL(imx_drm_encoder_get_mux_id);
 
-/*
- * imx_drm_remove_encoder - remove an encoder
- */
-int imx_drm_remove_encoder(struct imx_drm_encoder *imx_drm_encoder)
-{
-	struct imx_drm_device *imxdrm = __imx_drm_device();
-	struct crtc_cookie *c, *tmp;
-
-	mutex_lock(&imxdrm->mutex);
-
-	imx_drm_encoder_unregister(imx_drm_encoder);
-
-	list_del(&imx_drm_encoder->list);
-
-	list_for_each_entry_safe(c, tmp, &imx_drm_encoder->possible_crtcs,
-			list)
-		kfree(c);
-
-	mutex_unlock(&imxdrm->mutex);
-
-	kfree(imx_drm_encoder);
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(imx_drm_remove_encoder);
-
-/*
- * imx_drm_add_connector - add a connector
- */
-int imx_drm_add_connector(struct drm_connector *connector,
-		struct imx_drm_connector **new_con,
-		struct module *owner)
-{
-	struct imx_drm_device *imxdrm = __imx_drm_device();
-	struct imx_drm_connector *imx_drm_connector;
-	int ret;
-
-	mutex_lock(&imxdrm->mutex);
-
-	if (imxdrm->drm->open_count) {
-		ret = -EBUSY;
-		goto err_busy;
-	}
-
-	imx_drm_connector = kzalloc(sizeof(*imx_drm_connector), GFP_KERNEL);
-	if (!imx_drm_connector) {
-		ret = -ENOMEM;
-		goto err_alloc;
-	}
-
-	imx_drm_connector->connector = connector;
-	imx_drm_connector->owner = owner;
-
-	ret = imx_drm_connector_register(imx_drm_connector);
-	if (ret)
-		goto err_register;
-
-	list_add_tail(&imx_drm_connector->list, &imxdrm->connector_list);
-
-	*new_con = imx_drm_connector;
-
-	mutex_unlock(&imxdrm->mutex);
-
-	return 0;
-
-err_register:
-	kfree(imx_drm_connector);
-err_alloc:
-err_busy:
-	mutex_unlock(&imxdrm->mutex);
-
-	return ret;
-}
-EXPORT_SYMBOL_GPL(imx_drm_add_connector);
-
-void imx_drm_fb_helper_set(struct drm_fbdev_cma *fbdev_helper)
-{
-	struct imx_drm_device *imxdrm = __imx_drm_device();
-
-	imxdrm->fbhelper = fbdev_helper;
-}
-EXPORT_SYMBOL_GPL(imx_drm_fb_helper_set);
-
-/*
- * imx_drm_remove_connector - remove a connector
- */
-int imx_drm_remove_connector(struct imx_drm_connector *imx_drm_connector)
-{
-	struct imx_drm_device *imxdrm = __imx_drm_device();
-
-	mutex_lock(&imxdrm->mutex);
-
-	imx_drm_connector_unregister(imx_drm_connector);
-
-	list_del(&imx_drm_connector->list);
-
-	mutex_unlock(&imxdrm->mutex);
-
-	kfree(imx_drm_connector);
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(imx_drm_remove_connector);
-
 static const struct drm_ioctl_desc imx_drm_ioctls[] = {
 	/* none so far */
 };
@@ -819,6 +528,70 @@
 	.patchlevel		= 0,
 };
 
+static int compare_parent_of(struct device *dev, void *data)
+{
+	struct of_phandle_args *args = data;
+	return dev->parent && dev->parent->of_node == args->np;
+}
+
+static int compare_of(struct device *dev, void *data)
+{
+	return dev->of_node == data;
+}
+
+static int imx_drm_add_components(struct device *master, struct master *m)
+{
+	struct device_node *np = master->of_node;
+	unsigned i;
+	int ret;
+
+	for (i = 0; ; i++) {
+		struct of_phandle_args args;
+
+		ret = of_parse_phandle_with_fixed_args(np, "crtcs", 1,
+						       i, &args);
+		if (ret)
+			break;
+
+		ret = component_master_add_child(m, compare_parent_of, &args);
+		of_node_put(args.np);
+
+		if (ret)
+			return ret;
+	}
+
+	for (i = 0; ; i++) {
+		struct device_node *node;
+
+		node = of_parse_phandle(np, "connectors", i);
+		if (!node)
+			break;
+
+		ret = component_master_add_child(m, compare_of, node);
+		of_node_put(node);
+
+		if (ret)
+			return ret;
+	}
+	return 0;
+}
+
+static int imx_drm_bind(struct device *dev)
+{
+	return drm_platform_init(&imx_drm_driver, to_platform_device(dev));
+}
+
+static void imx_drm_unbind(struct device *dev)
+{
+	drm_put_dev(dev_get_drvdata(dev));
+}
+
+static const struct component_master_ops imx_drm_ops = {
+	.add_components = imx_drm_add_components,
+	.bind = imx_drm_bind,
+	.unbind = imx_drm_unbind,
+};
+
 static int imx_drm_platform_probe(struct platform_device *pdev)
 {
 	int ret;
@@ -827,72 +600,31 @@
 	if (ret)
 		return ret;
 
-	imx_drm_device->dev = &pdev->dev;
-
-	return drm_platform_init(&imx_drm_driver, pdev);
+	return component_master_add(&pdev->dev, &imx_drm_ops);
 }
 
 static int imx_drm_platform_remove(struct platform_device *pdev)
 {
-	drm_put_dev(platform_get_drvdata(pdev));
-
+	component_master_del(&pdev->dev, &imx_drm_ops);
 	return 0;
 }
 
+static const struct of_device_id imx_drm_dt_ids[] = {
+	{ .compatible = "fsl,imx-drm", },
+	{ /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, imx_drm_dt_ids);
+
 static struct platform_driver imx_drm_pdrv = {
 	.probe		= imx_drm_platform_probe,
 	.remove		= imx_drm_platform_remove,
 	.driver		= {
 		.owner	= THIS_MODULE,
 		.name	= "imx-drm",
+		.of_match_table = imx_drm_dt_ids,
 	},
 };
-
-static struct platform_device *imx_drm_pdev;
-
-static int __init imx_drm_init(void)
-{
-	int ret;
-
-	imx_drm_device = kzalloc(sizeof(*imx_drm_device), GFP_KERNEL);
-	if (!imx_drm_device)
-		return -ENOMEM;
-
-	mutex_init(&imx_drm_device->mutex);
-	INIT_LIST_HEAD(&imx_drm_device->crtc_list);
-	INIT_LIST_HEAD(&imx_drm_device->connector_list);
-	INIT_LIST_HEAD(&imx_drm_device->encoder_list);
-
-	imx_drm_pdev = platform_device_register_simple("imx-drm", -1, NULL, 0);
-	if (IS_ERR(imx_drm_pdev)) {
-		ret = PTR_ERR(imx_drm_pdev);
-		goto err_pdev;
-	}
-
-	ret = platform_driver_register(&imx_drm_pdrv);
-	if (ret)
-		goto err_pdrv;
-
-	return 0;
-
-err_pdrv:
-	platform_device_unregister(imx_drm_pdev);
-err_pdev:
-	kfree(imx_drm_device);
-
-	return ret;
-}
-
-static void __exit imx_drm_exit(void)
-{
-	platform_device_unregister(imx_drm_pdev);
-	platform_driver_unregister(&imx_drm_pdrv);
-
-	kfree(imx_drm_device);
-}
-
-module_init(imx_drm_init);
-module_exit(imx_drm_exit);
+module_platform_driver(imx_drm_pdrv);
 
 MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>");
 MODULE_DESCRIPTION("i.MX drm driver core");
diff --git a/drivers/staging/imx-drm/imx-drm.h b/drivers/staging/imx-drm/imx-drm.h
index ae90c9c..035ab62 100644
--- a/drivers/staging/imx-drm/imx-drm.h
+++ b/drivers/staging/imx-drm/imx-drm.h
@@ -1,17 +1,15 @@
 #ifndef _IMX_DRM_H_
 #define _IMX_DRM_H_
 
-#include <linux/videodev2.h>
-
-#define IPU_PIX_FMT_GBR24	v4l2_fourcc('G', 'B', 'R', '3')
-
+struct device_node;
 struct drm_crtc;
 struct drm_connector;
 struct drm_device;
+struct drm_display_mode;
 struct drm_encoder;
-struct imx_drm_crtc;
 struct drm_fbdev_cma;
 struct drm_framebuffer;
+struct imx_drm_crtc;
 struct platform_device;
 
 int imx_drm_crtc_id(struct imx_drm_crtc *crtc);
@@ -25,10 +23,10 @@
 	const struct drm_crtc_funcs *crtc_funcs;
 };
 
-int imx_drm_add_crtc(struct drm_crtc *crtc,
+int imx_drm_add_crtc(struct drm_device *drm, struct drm_crtc *crtc,
 		struct imx_drm_crtc **new_crtc,
 		const struct imx_drm_crtc_helper_funcs *imx_helper_funcs,
-		struct module *owner, void *cookie, int id);
+		void *cookie, int id);
 int imx_drm_remove_crtc(struct imx_drm_crtc *);
 int imx_drm_init_drm(struct platform_device *pdev,
 		int preferred_bpp);
@@ -38,35 +36,22 @@
 void imx_drm_crtc_vblank_put(struct imx_drm_crtc *imx_drm_crtc);
 void imx_drm_handle_vblank(struct imx_drm_crtc *imx_drm_crtc);
 
-struct imx_drm_encoder;
-int imx_drm_add_encoder(struct drm_encoder *encoder,
-		struct imx_drm_encoder **new_enc,
-		struct module *owner);
-int imx_drm_remove_encoder(struct imx_drm_encoder *);
-
-struct imx_drm_connector;
-int imx_drm_add_connector(struct drm_connector *connector,
-		struct imx_drm_connector **new_con,
-		struct module *owner);
-int imx_drm_remove_connector(struct imx_drm_connector *);
-
 void imx_drm_mode_config_init(struct drm_device *drm);
 
 struct drm_gem_cma_object *imx_drm_fb_get_obj(struct drm_framebuffer *fb);
 
-struct drm_device *imx_drm_device_get(void);
-void imx_drm_device_put(void);
-int imx_drm_crtc_panel_format_pins(struct drm_crtc *crtc, u32 encoder_type,
+int imx_drm_panel_format_pins(struct drm_encoder *encoder,
 		u32 interface_pix_fmt, int hsync_pin, int vsync_pin);
-int imx_drm_crtc_panel_format(struct drm_crtc *crtc, u32 encoder_type,
+int imx_drm_panel_format(struct drm_encoder *encoder,
 		u32 interface_pix_fmt);
-void imx_drm_fb_helper_set(struct drm_fbdev_cma *fbdev_helper);
 
-struct device_node;
+int imx_drm_encoder_get_mux_id(struct drm_encoder *encoder);
+int imx_drm_encoder_parse_of(struct drm_device *drm,
+	struct drm_encoder *encoder, struct device_node *np);
 
-int imx_drm_encoder_get_mux_id(struct imx_drm_encoder *imx_drm_encoder,
-		struct drm_crtc *crtc);
-int imx_drm_encoder_add_possible_crtcs(struct imx_drm_encoder *imx_drm_encoder,
-		struct device_node *np);
+int imx_drm_connector_mode_valid(struct drm_connector *connector,
+	struct drm_display_mode *mode);
+void imx_drm_connector_destroy(struct drm_connector *connector);
+void imx_drm_encoder_destroy(struct drm_encoder *encoder);
 
 #endif /* _IMX_DRM_H_ */
diff --git a/drivers/staging/imx-drm/imx-fb.c b/drivers/staging/imx-drm/imx-fb.c
deleted file mode 100644
index 03a7b4e..0000000
--- a/drivers/staging/imx-drm/imx-fb.c
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * i.MX drm driver
- *
- * Copyright (C) 2012 Sascha Hauer, Pengutronix
- *
- * Based on Samsung Exynos code
- *
- * Copyright (c) 2011 Samsung Electronics Co., Ltd.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-#include <linux/module.h>
-#include <drm/drmP.h>
-#include <drm/drm_crtc.h>
-#include <drm/drm_crtc_helper.h>
-#include <drm/drm_gem_cma_helper.h>
-#include <drm/drm_fb_cma_helper.h>
-
-#include "imx-drm.h"
-
-static struct drm_mode_config_funcs imx_drm_mode_config_funcs = {
-	.fb_create = drm_fb_cma_create,
-};
-
-void imx_drm_mode_config_init(struct drm_device *dev)
-{
-	dev->mode_config.min_width = 64;
-	dev->mode_config.min_height = 64;
-
-	/*
-	 * set max width and height as default value(4096x4096).
-	 * this value would be used to check framebuffer size limitation
-	 * at drm_mode_addfb().
-	 */
-	dev->mode_config.max_width = 4096;
-	dev->mode_config.max_height = 4096;
-
-	dev->mode_config.funcs = &imx_drm_mode_config_funcs;
-}
diff --git a/drivers/staging/imx-drm/imx-fbdev.c b/drivers/staging/imx-drm/imx-fbdev.c
deleted file mode 100644
index 8331739..0000000
--- a/drivers/staging/imx-drm/imx-fbdev.c
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * i.MX drm driver
- *
- * Copyright (C) 2012 Sascha Hauer, Pengutronix
- *
- * Based on Samsung Exynos code
- *
- * Copyright (c) 2011 Samsung Electronics Co., Ltd.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-#include <linux/module.h>
-#include <drm/drmP.h>
-#include <drm/drm_crtc.h>
-#include <drm/drm_crtc_helper.h>
-#include <drm/drm_fb_cma_helper.h>
-
-#include "imx-drm.h"
-
-#define MAX_CONNECTOR		4
-#define PREFERRED_BPP		16
-
-static struct drm_fbdev_cma *fbdev_cma;
-
-static int legacyfb_depth = 16;
-
-module_param(legacyfb_depth, int, 0444);
-
-static int __init imx_fb_helper_init(void)
-{
-	struct drm_device *drm = imx_drm_device_get();
-
-	if (!drm)
-		return -EINVAL;
-
-	if (legacyfb_depth != 16 && legacyfb_depth != 32) {
-		pr_warn("i.MX legacyfb: invalid legacyfb_depth setting. defaulting to 16bpp\n");
-		legacyfb_depth = 16;
-	}
-
-	fbdev_cma = drm_fbdev_cma_init(drm, legacyfb_depth,
-			drm->mode_config.num_crtc, MAX_CONNECTOR);
-
-	if (IS_ERR(fbdev_cma)) {
-		imx_drm_device_put();
-		return PTR_ERR(fbdev_cma);
-	}
-
-	imx_drm_fb_helper_set(fbdev_cma);
-
-	return 0;
-}
-
-static void __exit imx_fb_helper_exit(void)
-{
-	imx_drm_fb_helper_set(NULL);
-	drm_fbdev_cma_fini(fbdev_cma);
-	imx_drm_device_put();
-}
-
-late_initcall(imx_fb_helper_init);
-module_exit(imx_fb_helper_exit);
-
-MODULE_DESCRIPTION("Freescale i.MX legacy fb driver");
-MODULE_AUTHOR("Sascha Hauer, Pengutronix");
-MODULE_LICENSE("GPL");
diff --git a/drivers/staging/imx-drm/imx-hdmi.c b/drivers/staging/imx-drm/imx-hdmi.c
index f1aa48c..8384cea 100644
--- a/drivers/staging/imx-drm/imx-hdmi.c
+++ b/drivers/staging/imx-drm/imx-hdmi.c
@@ -12,6 +12,7 @@
  * Copyright (C) 2010, Guennadi Liakhovetski <g.liakhovetski@gmx.de>
  */
 
+#include <linux/component.h>
 #include <linux/irq.h>
 #include <linux/delay.h>
 #include <linux/err.h>
@@ -112,15 +113,15 @@
 
 struct imx_hdmi {
 	struct drm_connector connector;
-	struct imx_drm_connector *imx_drm_connector;
 	struct drm_encoder encoder;
-	struct imx_drm_encoder *imx_drm_encoder;
 
 	enum imx_hdmi_devtype dev_type;
 	struct device *dev;
 	struct clk *isfr_clk;
 	struct clk *iahb_clk;
 
+	enum drm_connector_status connector_status;
+
 	struct hdmi_data_info hdmi_data;
 	int vic;
 
@@ -134,7 +135,6 @@
 	struct i2c_adapter *ddc;
 	void __iomem *regs;
 
-	unsigned long pixel_clk_rate;
 	unsigned int sample_rate;
 	int ratio;
 };
@@ -156,37 +156,34 @@
 	return readb(hdmi->regs + offset);
 }
 
+static void hdmi_modb(struct imx_hdmi *hdmi, u8 data, u8 mask, unsigned reg)
+{
+	u8 val = hdmi_readb(hdmi, reg) & ~mask;
+	val |= data & mask;
+	hdmi_writeb(hdmi, val, reg);
+}
+
 static void hdmi_mask_writeb(struct imx_hdmi *hdmi, u8 data, unsigned int reg,
 		      u8 shift, u8 mask)
 {
-	u8 value = hdmi_readb(hdmi, reg) & ~mask;
-	value |= (data << shift) & mask;
-	hdmi_writeb(hdmi, value, reg);
+	hdmi_modb(hdmi, data << shift, mask, reg);
 }
 
 static void hdmi_set_clock_regenerator_n(struct imx_hdmi *hdmi,
 					 unsigned int value)
 {
-	u8 val;
-
 	hdmi_writeb(hdmi, value & 0xff, HDMI_AUD_N1);
 	hdmi_writeb(hdmi, (value >> 8) & 0xff, HDMI_AUD_N2);
 	hdmi_writeb(hdmi, (value >> 16) & 0x0f, HDMI_AUD_N3);
 
 	/* nshift factor = 0 */
-	val = hdmi_readb(hdmi, HDMI_AUD_CTS3);
-	val &= ~HDMI_AUD_CTS3_N_SHIFT_MASK;
-	hdmi_writeb(hdmi, val, HDMI_AUD_CTS3);
+	hdmi_modb(hdmi, 0, HDMI_AUD_CTS3_N_SHIFT_MASK, HDMI_AUD_CTS3);
 }
 
 static void hdmi_regenerate_cts(struct imx_hdmi *hdmi, unsigned int cts)
 {
-	u8 val;
-
 	/* Must be set/cleared first */
-	val = hdmi_readb(hdmi, HDMI_AUD_CTS3);
-	val &= ~HDMI_AUD_CTS3_CTS_MANUAL;
-	hdmi_writeb(hdmi, val, HDMI_AUD_CTS3);
+	hdmi_modb(hdmi, 0, HDMI_AUD_CTS3_CTS_MANUAL, HDMI_AUD_CTS3);
 
 	hdmi_writeb(hdmi, cts & 0xff, HDMI_AUD_CTS1);
 	hdmi_writeb(hdmi, (cts >> 8) & 0xff, HDMI_AUD_CTS2);
@@ -331,34 +328,25 @@
 		return (cts * ratio) / 100;
 }
 
-static void hdmi_get_pixel_clk(struct imx_hdmi *hdmi)
-{
-	unsigned long rate;
-
-	rate = 65000000; /* FIXME */
-
-	if (rate)
-		hdmi->pixel_clk_rate = rate;
-}
-
-static void hdmi_set_clk_regenerator(struct imx_hdmi *hdmi)
+static void hdmi_set_clk_regenerator(struct imx_hdmi *hdmi,
+	unsigned long pixel_clk)
 {
 	unsigned int clk_n, clk_cts;
 
-	clk_n = hdmi_compute_n(hdmi->sample_rate, hdmi->pixel_clk_rate,
+	clk_n = hdmi_compute_n(hdmi->sample_rate, pixel_clk,
 			       hdmi->ratio);
-	clk_cts = hdmi_compute_cts(hdmi->sample_rate, hdmi->pixel_clk_rate,
+	clk_cts = hdmi_compute_cts(hdmi->sample_rate, pixel_clk,
 				   hdmi->ratio);
 
 	if (!clk_cts) {
 		dev_dbg(hdmi->dev, "%s: pixel clock not supported: %lu\n",
-			 __func__, hdmi->pixel_clk_rate);
+			 __func__, pixel_clk);
 		return;
 	}
 
 	dev_dbg(hdmi->dev, "%s: samplerate=%d  ratio=%d  pixelclk=%lu  N=%d cts=%d\n",
 		__func__, hdmi->sample_rate, hdmi->ratio,
-		hdmi->pixel_clk_rate, clk_n, clk_cts);
+		pixel_clk, clk_n, clk_cts);
 
 	hdmi_set_clock_regenerator_n(hdmi, clk_n);
 	hdmi_regenerate_cts(hdmi, clk_cts);
@@ -366,32 +354,12 @@
 
 static void hdmi_init_clk_regenerator(struct imx_hdmi *hdmi)
 {
-	unsigned int clk_n, clk_cts;
-
-	clk_n = hdmi_compute_n(hdmi->sample_rate, hdmi->pixel_clk_rate,
-			       hdmi->ratio);
-	clk_cts = hdmi_compute_cts(hdmi->sample_rate, hdmi->pixel_clk_rate,
-				   hdmi->ratio);
-
-	if (!clk_cts) {
-		dev_dbg(hdmi->dev, "%s: pixel clock not supported: %lu\n",
-			 __func__, hdmi->pixel_clk_rate);
-		return;
-	}
-
-	dev_dbg(hdmi->dev, "%s: samplerate=%d  ratio=%d  pixelclk=%lu  N=%d cts=%d\n",
-		__func__, hdmi->sample_rate, hdmi->ratio,
-		hdmi->pixel_clk_rate, clk_n, clk_cts);
-
-	hdmi_set_clock_regenerator_n(hdmi, clk_n);
-	hdmi_regenerate_cts(hdmi, clk_cts);
+	hdmi_set_clk_regenerator(hdmi, 74250000);
 }
 
 static void hdmi_clk_regenerator_update_pixel_clock(struct imx_hdmi *hdmi)
 {
-	/* Get pixel clock from ipu */
-	hdmi_get_pixel_clk(hdmi);
-	hdmi_set_clk_regenerator(hdmi);
+	hdmi_set_clk_regenerator(hdmi, hdmi->hdmi_data.video_mode.mpixelclock);
 }
 
 /*
@@ -485,8 +453,8 @@
 static void imx_hdmi_update_csc_coeffs(struct imx_hdmi *hdmi)
 {
 	const u16 (*csc_coeff)[3][4] = &csc_coeff_default;
+	unsigned i;
 	u32 csc_scale = 1;
-	u8 val;
 
 	if (is_color_space_conversion(hdmi)) {
 		if (hdmi->hdmi_data.enc_out_format == RGB) {
@@ -503,37 +471,22 @@
 		}
 	}
 
-	hdmi_writeb(hdmi, ((*csc_coeff)[0][0] & 0xff), HDMI_CSC_COEF_A1_LSB);
-	hdmi_writeb(hdmi, ((*csc_coeff)[0][0] >> 8), HDMI_CSC_COEF_A1_MSB);
-	hdmi_writeb(hdmi, ((*csc_coeff)[0][1] & 0xff), HDMI_CSC_COEF_A2_LSB);
-	hdmi_writeb(hdmi, ((*csc_coeff)[0][1] >> 8), HDMI_CSC_COEF_A2_MSB);
-	hdmi_writeb(hdmi, ((*csc_coeff)[0][2] & 0xff), HDMI_CSC_COEF_A3_LSB);
-	hdmi_writeb(hdmi, ((*csc_coeff)[0][2] >> 8), HDMI_CSC_COEF_A3_MSB);
-	hdmi_writeb(hdmi, ((*csc_coeff)[0][3] & 0xff), HDMI_CSC_COEF_A4_LSB);
-	hdmi_writeb(hdmi, ((*csc_coeff)[0][3] >> 8), HDMI_CSC_COEF_A4_MSB);
+	/* The CSC registers are sequential, alternating MSB then LSB */
+	for (i = 0; i < ARRAY_SIZE(csc_coeff_default[0]); i++) {
+		u16 coeff_a = (*csc_coeff)[0][i];
+		u16 coeff_b = (*csc_coeff)[1][i];
+		u16 coeff_c = (*csc_coeff)[2][i];
 
-	hdmi_writeb(hdmi, ((*csc_coeff)[1][0] & 0xff), HDMI_CSC_COEF_B1_LSB);
-	hdmi_writeb(hdmi, ((*csc_coeff)[1][0] >> 8), HDMI_CSC_COEF_B1_MSB);
-	hdmi_writeb(hdmi, ((*csc_coeff)[1][1] & 0xff), HDMI_CSC_COEF_B2_LSB);
-	hdmi_writeb(hdmi, ((*csc_coeff)[1][1] >> 8), HDMI_CSC_COEF_B2_MSB);
-	hdmi_writeb(hdmi, ((*csc_coeff)[1][2] & 0xff), HDMI_CSC_COEF_B3_LSB);
-	hdmi_writeb(hdmi, ((*csc_coeff)[1][2] >> 8), HDMI_CSC_COEF_B3_MSB);
-	hdmi_writeb(hdmi, ((*csc_coeff)[1][3] & 0xff), HDMI_CSC_COEF_B4_LSB);
-	hdmi_writeb(hdmi, ((*csc_coeff)[1][3] >> 8), HDMI_CSC_COEF_B4_MSB);
+		hdmi_writeb(hdmi, coeff_a & 0xff, HDMI_CSC_COEF_A1_LSB + i * 2);
+		hdmi_writeb(hdmi, coeff_a >> 8, HDMI_CSC_COEF_A1_MSB + i * 2);
+		hdmi_writeb(hdmi, coeff_b & 0xff, HDMI_CSC_COEF_B1_LSB + i * 2);
+		hdmi_writeb(hdmi, coeff_b >> 8, HDMI_CSC_COEF_B1_MSB + i * 2);
+		hdmi_writeb(hdmi, coeff_c & 0xff, HDMI_CSC_COEF_C1_LSB + i * 2);
+		hdmi_writeb(hdmi, coeff_c >> 8, HDMI_CSC_COEF_C1_MSB + i * 2);
+	}
 
-	hdmi_writeb(hdmi, ((*csc_coeff)[2][0] & 0xff), HDMI_CSC_COEF_C1_LSB);
-	hdmi_writeb(hdmi, ((*csc_coeff)[2][0] >> 8), HDMI_CSC_COEF_C1_MSB);
-	hdmi_writeb(hdmi, ((*csc_coeff)[2][1] & 0xff), HDMI_CSC_COEF_C2_LSB);
-	hdmi_writeb(hdmi, ((*csc_coeff)[2][1] >> 8), HDMI_CSC_COEF_C2_MSB);
-	hdmi_writeb(hdmi, ((*csc_coeff)[2][2] & 0xff), HDMI_CSC_COEF_C3_LSB);
-	hdmi_writeb(hdmi, ((*csc_coeff)[2][2] >> 8), HDMI_CSC_COEF_C3_MSB);
-	hdmi_writeb(hdmi, ((*csc_coeff)[2][3] & 0xff), HDMI_CSC_COEF_C4_LSB);
-	hdmi_writeb(hdmi, ((*csc_coeff)[2][3] >> 8), HDMI_CSC_COEF_C4_MSB);
-
-	val = hdmi_readb(hdmi, HDMI_CSC_SCALE);
-	val &= ~HDMI_CSC_SCALE_CSCSCALE_MASK;
-	val |= csc_scale & HDMI_CSC_SCALE_CSCSCALE_MASK;
-	hdmi_writeb(hdmi, val, HDMI_CSC_SCALE);
+	hdmi_modb(hdmi, csc_scale, HDMI_CSC_SCALE_CSCSCALE_MASK,
+		  HDMI_CSC_SCALE);
 }
 
 static void hdmi_video_csc(struct imx_hdmi *hdmi)
@@ -541,7 +494,6 @@
 	int color_depth = 0;
 	int interpolation = HDMI_CSC_CFG_INTMODE_DISABLE;
 	int decimation = 0;
-	u8 val;
 
 	/* YCC422 interpolation to 444 mode */
 	if (is_color_space_interpolation(hdmi))
@@ -562,10 +514,8 @@
 
 	/* Configure the CSC registers */
 	hdmi_writeb(hdmi, interpolation | decimation, HDMI_CSC_CFG);
-	val = hdmi_readb(hdmi, HDMI_CSC_SCALE);
-	val &= ~HDMI_CSC_SCALE_CSC_COLORDE_PTH_MASK;
-	val |= color_depth;
-	hdmi_writeb(hdmi, val, HDMI_CSC_SCALE);
+	hdmi_modb(hdmi, color_depth, HDMI_CSC_SCALE_CSC_COLORDE_PTH_MASK,
+		  HDMI_CSC_SCALE);
 
 	imx_hdmi_update_csc_coeffs(hdmi);
 }
@@ -581,7 +531,7 @@
 	unsigned int remap_size = HDMI_VP_REMAP_YCC422_16bit;
 	unsigned int output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_PP;
 	struct hdmi_data_info *hdmi_data = &hdmi->hdmi_data;
-	u8 val;
+	u8 val, vp_conf;
 
 	if (hdmi_data->enc_out_format == RGB
 		|| hdmi_data->enc_out_format == YCBCR444) {
@@ -620,107 +570,75 @@
 		HDMI_VP_PR_CD_DESIRED_PR_FACTOR_MASK);
 	hdmi_writeb(hdmi, val, HDMI_VP_PR_CD);
 
-	val = hdmi_readb(hdmi, HDMI_VP_STUFF);
-	val &= ~HDMI_VP_STUFF_PR_STUFFING_MASK;
-	val |= HDMI_VP_STUFF_PR_STUFFING_STUFFING_MODE;
-	hdmi_writeb(hdmi, val, HDMI_VP_STUFF);
+	hdmi_modb(hdmi, HDMI_VP_STUFF_PR_STUFFING_STUFFING_MODE,
+		  HDMI_VP_STUFF_PR_STUFFING_MASK, HDMI_VP_STUFF);
 
 	/* Data from pixel repeater block */
 	if (hdmi_data->pix_repet_factor > 1) {
-		val = hdmi_readb(hdmi, HDMI_VP_CONF);
-		val &= ~(HDMI_VP_CONF_PR_EN_MASK |
-			HDMI_VP_CONF_BYPASS_SELECT_MASK);
-		val |= HDMI_VP_CONF_PR_EN_ENABLE |
-			HDMI_VP_CONF_BYPASS_SELECT_PIX_REPEATER;
-		hdmi_writeb(hdmi, val, HDMI_VP_CONF);
+		vp_conf = HDMI_VP_CONF_PR_EN_ENABLE |
+			  HDMI_VP_CONF_BYPASS_SELECT_PIX_REPEATER;
 	} else { /* data from packetizer block */
-		val = hdmi_readb(hdmi, HDMI_VP_CONF);
-		val &= ~(HDMI_VP_CONF_PR_EN_MASK |
-			HDMI_VP_CONF_BYPASS_SELECT_MASK);
-		val |= HDMI_VP_CONF_PR_EN_DISABLE |
-			HDMI_VP_CONF_BYPASS_SELECT_VID_PACKETIZER;
-		hdmi_writeb(hdmi, val, HDMI_VP_CONF);
+		vp_conf = HDMI_VP_CONF_PR_EN_DISABLE |
+			  HDMI_VP_CONF_BYPASS_SELECT_VID_PACKETIZER;
 	}
 
-	val = hdmi_readb(hdmi, HDMI_VP_STUFF);
-	val &= ~HDMI_VP_STUFF_IDEFAULT_PHASE_MASK;
-	val |= 1 << HDMI_VP_STUFF_IDEFAULT_PHASE_OFFSET;
-	hdmi_writeb(hdmi, val, HDMI_VP_STUFF);
+	hdmi_modb(hdmi, vp_conf,
+		  HDMI_VP_CONF_PR_EN_MASK |
+		  HDMI_VP_CONF_BYPASS_SELECT_MASK, HDMI_VP_CONF);
+
+	hdmi_modb(hdmi, 1 << HDMI_VP_STUFF_IDEFAULT_PHASE_OFFSET,
+		  HDMI_VP_STUFF_IDEFAULT_PHASE_MASK, HDMI_VP_STUFF);
 
 	hdmi_writeb(hdmi, remap_size, HDMI_VP_REMAP);
 
 	if (output_select == HDMI_VP_CONF_OUTPUT_SELECTOR_PP) {
-		val = hdmi_readb(hdmi, HDMI_VP_CONF);
-		val &= ~(HDMI_VP_CONF_BYPASS_EN_MASK |
-			HDMI_VP_CONF_PP_EN_ENMASK |
-			HDMI_VP_CONF_YCC422_EN_MASK);
-		val |= HDMI_VP_CONF_BYPASS_EN_DISABLE |
-			HDMI_VP_CONF_PP_EN_ENABLE |
-			HDMI_VP_CONF_YCC422_EN_DISABLE;
-		hdmi_writeb(hdmi, val, HDMI_VP_CONF);
+		vp_conf = HDMI_VP_CONF_BYPASS_EN_DISABLE |
+			  HDMI_VP_CONF_PP_EN_ENABLE |
+			  HDMI_VP_CONF_YCC422_EN_DISABLE;
 	} else if (output_select == HDMI_VP_CONF_OUTPUT_SELECTOR_YCC422) {
-		val = hdmi_readb(hdmi, HDMI_VP_CONF);
-		val &= ~(HDMI_VP_CONF_BYPASS_EN_MASK |
-			HDMI_VP_CONF_PP_EN_ENMASK |
-			HDMI_VP_CONF_YCC422_EN_MASK);
-		val |= HDMI_VP_CONF_BYPASS_EN_DISABLE |
-			HDMI_VP_CONF_PP_EN_DISABLE |
-			HDMI_VP_CONF_YCC422_EN_ENABLE;
-		hdmi_writeb(hdmi, val, HDMI_VP_CONF);
+		vp_conf = HDMI_VP_CONF_BYPASS_EN_DISABLE |
+			  HDMI_VP_CONF_PP_EN_DISABLE |
+			  HDMI_VP_CONF_YCC422_EN_ENABLE;
 	} else if (output_select == HDMI_VP_CONF_OUTPUT_SELECTOR_BYPASS) {
-		val = hdmi_readb(hdmi, HDMI_VP_CONF);
-		val &= ~(HDMI_VP_CONF_BYPASS_EN_MASK |
-			HDMI_VP_CONF_PP_EN_ENMASK |
-			HDMI_VP_CONF_YCC422_EN_MASK);
-		val |= HDMI_VP_CONF_BYPASS_EN_ENABLE |
-			HDMI_VP_CONF_PP_EN_DISABLE |
-			HDMI_VP_CONF_YCC422_EN_DISABLE;
-		hdmi_writeb(hdmi, val, HDMI_VP_CONF);
+		vp_conf = HDMI_VP_CONF_BYPASS_EN_ENABLE |
+			  HDMI_VP_CONF_PP_EN_DISABLE |
+			  HDMI_VP_CONF_YCC422_EN_DISABLE;
 	} else {
 		return;
 	}
 
-	val = hdmi_readb(hdmi, HDMI_VP_STUFF);
-	val &= ~(HDMI_VP_STUFF_PP_STUFFING_MASK |
-		HDMI_VP_STUFF_YCC422_STUFFING_MASK);
-	val |= HDMI_VP_STUFF_PP_STUFFING_STUFFING_MODE |
-		HDMI_VP_STUFF_YCC422_STUFFING_STUFFING_MODE;
-	hdmi_writeb(hdmi, val, HDMI_VP_STUFF);
+	hdmi_modb(hdmi, vp_conf,
+		  HDMI_VP_CONF_BYPASS_EN_MASK | HDMI_VP_CONF_PP_EN_ENMASK |
+		  HDMI_VP_CONF_YCC422_EN_MASK, HDMI_VP_CONF);
 
-	val = hdmi_readb(hdmi, HDMI_VP_CONF);
-	val &= ~HDMI_VP_CONF_OUTPUT_SELECTOR_MASK;
-	val |= output_select;
-	hdmi_writeb(hdmi, val, HDMI_VP_CONF);
+	hdmi_modb(hdmi, HDMI_VP_STUFF_PP_STUFFING_STUFFING_MODE |
+			HDMI_VP_STUFF_YCC422_STUFFING_STUFFING_MODE,
+		  HDMI_VP_STUFF_PP_STUFFING_MASK |
+		  HDMI_VP_STUFF_YCC422_STUFFING_MASK, HDMI_VP_STUFF);
+
+	hdmi_modb(hdmi, output_select, HDMI_VP_CONF_OUTPUT_SELECTOR_MASK,
+		  HDMI_VP_CONF);
 }
 
 static inline void hdmi_phy_test_clear(struct imx_hdmi *hdmi,
 						unsigned char bit)
 {
-	u8 val = hdmi_readb(hdmi, HDMI_PHY_TST0);
-	val &= ~HDMI_PHY_TST0_TSTCLR_MASK;
-	val |= (bit << HDMI_PHY_TST0_TSTCLR_OFFSET) &
-		HDMI_PHY_TST0_TSTCLR_MASK;
-	hdmi_writeb(hdmi, val, HDMI_PHY_TST0);
+	hdmi_modb(hdmi, bit << HDMI_PHY_TST0_TSTCLR_OFFSET,
+		  HDMI_PHY_TST0_TSTCLR_MASK, HDMI_PHY_TST0);
 }
 
 static inline void hdmi_phy_test_enable(struct imx_hdmi *hdmi,
 						unsigned char bit)
 {
-	u8 val = hdmi_readb(hdmi, HDMI_PHY_TST0);
-	val &= ~HDMI_PHY_TST0_TSTEN_MASK;
-	val |= (bit << HDMI_PHY_TST0_TSTEN_OFFSET) &
-		HDMI_PHY_TST0_TSTEN_MASK;
-	hdmi_writeb(hdmi, val, HDMI_PHY_TST0);
+	hdmi_modb(hdmi, bit << HDMI_PHY_TST0_TSTEN_OFFSET,
+		  HDMI_PHY_TST0_TSTEN_MASK, HDMI_PHY_TST0);
 }
 
 static inline void hdmi_phy_test_clock(struct imx_hdmi *hdmi,
 						unsigned char bit)
 {
-	u8 val = hdmi_readb(hdmi, HDMI_PHY_TST0);
-	val &= ~HDMI_PHY_TST0_TSTCLK_MASK;
-	val |= (bit << HDMI_PHY_TST0_TSTCLK_OFFSET) &
-		HDMI_PHY_TST0_TSTCLK_MASK;
-	hdmi_writeb(hdmi, val, HDMI_PHY_TST0);
+	hdmi_modb(hdmi, bit << HDMI_PHY_TST0_TSTCLK_OFFSET,
+		  HDMI_PHY_TST0_TSTCLK_MASK, HDMI_PHY_TST0);
 }
 
 static inline void hdmi_phy_test_din(struct imx_hdmi *hdmi,
@@ -811,19 +729,94 @@
 			 HDMI_PHY_CONF0_SELDIPIF_MASK);
 }
 
+enum {
+	RES_8,
+	RES_10,
+	RES_12,
+	RES_MAX,
+};
+
+struct mpll_config {
+	unsigned long mpixelclock;
+	struct {
+		u16 cpce;
+		u16 gmp;
+	} res[RES_MAX];
+};
+
+static const struct mpll_config mpll_config[] = {
+	{
+		45250000, {
+			{ 0x01e0, 0x0000 },
+			{ 0x21e1, 0x0000 },
+			{ 0x41e2, 0x0000 }
+		},
+	}, {
+		92500000, {
+			{ 0x0140, 0x0005 },
+			{ 0x2141, 0x0005 },
+			{ 0x4142, 0x0005 },
+		},
+	}, {
+		148500000, {
+			{ 0x00a0, 0x000a },
+			{ 0x20a1, 0x000a },
+			{ 0x40a2, 0x000a },
+		},
+	}, {
+		~0UL, {
+			{ 0x00a0, 0x000a },
+			{ 0x2001, 0x000f },
+			{ 0x4002, 0x000f },
+		},
+	}
+};
+
+struct curr_ctrl {
+	unsigned long mpixelclock;
+	u16 curr[RES_MAX];
+};
+
+static const struct curr_ctrl curr_ctrl[] = {
+	/*	pixelclk     bpp8    bpp10   bpp12 */
+	{
+		 54000000, { 0x091c, 0x091c, 0x06dc },
+	}, {
+		 58400000, { 0x091c, 0x06dc, 0x06dc },
+	}, {
+		 72000000, { 0x06dc, 0x06dc, 0x091c },
+	}, {
+		 74250000, { 0x06dc, 0x0b5c, 0x091c },
+	}, {
+		118800000, { 0x091c, 0x091c, 0x06dc },
+	}, {
+		216000000, { 0x06dc, 0x0b5c, 0x091c },
+	}
+};
+
 static int hdmi_phy_configure(struct imx_hdmi *hdmi, unsigned char prep,
 			      unsigned char res, int cscon)
 {
+	unsigned res_idx, i;
 	u8 val, msec;
 
-	/* color resolution 0 is 8 bit colour depth */
-	if (!res)
-		res = 8;
-
 	if (prep)
 		return -EINVAL;
-	else if (res != 8 && res != 12)
+
+	switch (res) {
+	case 0:	/* color resolution 0 is 8 bit colour depth */
+	case 8:
+		res_idx = RES_8;
+		break;
+	case 10:
+		res_idx = RES_10;
+		break;
+	case 12:
+		res_idx = RES_12;
+		break;
+	default:
 		return -EINVAL;
+	}
 
 	/* Enable csc path */
 	if (cscon)
@@ -850,165 +843,30 @@
 			HDMI_PHY_I2CM_SLAVE_ADDR);
 	hdmi_phy_test_clear(hdmi, 0);
 
-	if (hdmi->hdmi_data.video_mode.mpixelclock <= 45250000) {
-		switch (res) {
-		case 8:
-			/* PLL/MPLL Cfg */
-			hdmi_phy_i2c_write(hdmi, 0x01e0, 0x06);
-			hdmi_phy_i2c_write(hdmi, 0x0000, 0x15);  /* GMPCTRL */
+	/* PLL/MPLL Cfg - always match on final entry */
+	for (i = 0; i < ARRAY_SIZE(mpll_config) - 1; i++)
+		if (hdmi->hdmi_data.video_mode.mpixelclock <=
+		    mpll_config[i].mpixelclock)
 			break;
-		case 10:
-			hdmi_phy_i2c_write(hdmi, 0x21e1, 0x06);
-			hdmi_phy_i2c_write(hdmi, 0x0000, 0x15);
-			break;
-		case 12:
-			hdmi_phy_i2c_write(hdmi, 0x41e2, 0x06);
-			hdmi_phy_i2c_write(hdmi, 0x0000, 0x15);
-			break;
-		default:
-			return -EINVAL;
-		}
-	} else if (hdmi->hdmi_data.video_mode.mpixelclock <= 92500000) {
-		switch (res) {
-		case 8:
-			hdmi_phy_i2c_write(hdmi, 0x0140, 0x06);
-			hdmi_phy_i2c_write(hdmi, 0x0005, 0x15);
-			break;
-		case 10:
-			hdmi_phy_i2c_write(hdmi, 0x2141, 0x06);
-			hdmi_phy_i2c_write(hdmi, 0x0005, 0x15);
-			break;
-		case 12:
-			hdmi_phy_i2c_write(hdmi, 0x4142, 0x06);
-			hdmi_phy_i2c_write(hdmi, 0x0005, 0x15);
-		default:
-			return -EINVAL;
-		}
-	} else if (hdmi->hdmi_data.video_mode.mpixelclock <= 148500000) {
-		switch (res) {
-		case 8:
-			hdmi_phy_i2c_write(hdmi, 0x00a0, 0x06);
-			hdmi_phy_i2c_write(hdmi, 0x000a, 0x15);
-			break;
-		case 10:
-			hdmi_phy_i2c_write(hdmi, 0x20a1, 0x06);
-			hdmi_phy_i2c_write(hdmi, 0x000a, 0x15);
-			break;
-		case 12:
-			hdmi_phy_i2c_write(hdmi, 0x40a2, 0x06);
-			hdmi_phy_i2c_write(hdmi, 0x000a, 0x15);
-		default:
-			return -EINVAL;
-		}
-	} else {
-		switch (res) {
-		case 8:
-			hdmi_phy_i2c_write(hdmi, 0x00a0, 0x06);
-			hdmi_phy_i2c_write(hdmi, 0x000a, 0x15);
-			break;
-		case 10:
-			hdmi_phy_i2c_write(hdmi, 0x2001, 0x06);
-			hdmi_phy_i2c_write(hdmi, 0x000f, 0x15);
-			break;
-		case 12:
-			hdmi_phy_i2c_write(hdmi, 0x4002, 0x06);
-			hdmi_phy_i2c_write(hdmi, 0x000f, 0x15);
-		default:
-			return -EINVAL;
-		}
-	}
 
-	if (hdmi->hdmi_data.video_mode.mpixelclock <= 54000000) {
-		switch (res) {
-		case 8:
-			hdmi_phy_i2c_write(hdmi, 0x091c, 0x10);  /* CURRCTRL */
+	hdmi_phy_i2c_write(hdmi, mpll_config[i].res[res_idx].cpce, 0x06);
+	hdmi_phy_i2c_write(hdmi, mpll_config[i].res[res_idx].gmp, 0x15);
+
+	for (i = 0; i < ARRAY_SIZE(curr_ctrl); i++)
+		if (hdmi->hdmi_data.video_mode.mpixelclock <=
+		    curr_ctrl[i].mpixelclock)
 			break;
-		case 10:
-			hdmi_phy_i2c_write(hdmi, 0x091c, 0x10);
-			break;
-		case 12:
-			hdmi_phy_i2c_write(hdmi, 0x06dc, 0x10);
-			break;
-		default:
-			return -EINVAL;
-		}
-	} else if (hdmi->hdmi_data.video_mode.mpixelclock <= 58400000) {
-		switch (res) {
-		case 8:
-			hdmi_phy_i2c_write(hdmi, 0x091c, 0x10);
-			break;
-		case 10:
-			hdmi_phy_i2c_write(hdmi, 0x06dc, 0x10);
-			break;
-		case 12:
-			hdmi_phy_i2c_write(hdmi, 0x06dc, 0x10);
-			break;
-		default:
-			return -EINVAL;
-		}
-	} else if (hdmi->hdmi_data.video_mode.mpixelclock <= 72000000) {
-		switch (res) {
-		case 8:
-			hdmi_phy_i2c_write(hdmi, 0x06dc, 0x10);
-			break;
-		case 10:
-			hdmi_phy_i2c_write(hdmi, 0x06dc, 0x10);
-			break;
-		case 12:
-			hdmi_phy_i2c_write(hdmi, 0x091c, 0x10);
-			break;
-		default:
-			return -EINVAL;
-		}
-	} else if (hdmi->hdmi_data.video_mode.mpixelclock <= 74250000) {
-		switch (res) {
-		case 8:
-			hdmi_phy_i2c_write(hdmi, 0x06dc, 0x10);
-			break;
-		case 10:
-			hdmi_phy_i2c_write(hdmi, 0x0b5c, 0x10);
-			break;
-		case 12:
-			hdmi_phy_i2c_write(hdmi, 0x091c, 0x10);
-			break;
-		default:
-			return -EINVAL;
-		}
-	} else if (hdmi->hdmi_data.video_mode.mpixelclock <= 118800000) {
-		switch (res) {
-		case 8:
-			hdmi_phy_i2c_write(hdmi, 0x091c, 0x10);
-			break;
-		case 10:
-			hdmi_phy_i2c_write(hdmi, 0x091c, 0x10);
-			break;
-		case 12:
-			hdmi_phy_i2c_write(hdmi, 0x06dc, 0x10);
-			break;
-		default:
-			return -EINVAL;
-		}
-	} else if (hdmi->hdmi_data.video_mode.mpixelclock <= 216000000) {
-		switch (res) {
-		case 8:
-			hdmi_phy_i2c_write(hdmi, 0x06dc, 0x10);
-			break;
-		case 10:
-			hdmi_phy_i2c_write(hdmi, 0x0b5c, 0x10);
-			break;
-		case 12:
-			hdmi_phy_i2c_write(hdmi, 0x091c, 0x10);
-			break;
-		default:
-			return -EINVAL;
-		}
-	} else {
+
+	if (i >= ARRAY_SIZE(curr_ctrl)) {
 		dev_err(hdmi->dev,
 				"Pixel clock %d - unsupported by HDMI\n",
 				hdmi->hdmi_data.video_mode.mpixelclock);
 		return -EINVAL;
 	}
 
+	/* CURRCTRL */
+	hdmi_phy_i2c_write(hdmi, curr_ctrl[i].curr[res_idx], 0x10);
+
 	hdmi_phy_i2c_write(hdmi, 0x0000, 0x13);  /* PLLPHBYCTRL */
 	hdmi_phy_i2c_write(hdmi, 0x0006, 0x17);
 	/* RESISTANCE TERM 133Ohm Cfg */
@@ -1077,7 +935,7 @@
 
 static void hdmi_tx_hdcp_config(struct imx_hdmi *hdmi)
 {
-	u8 de, val;
+	u8 de;
 
 	if (hdmi->hdmi_data.video_mode.mdataenablepolarity)
 		de = HDMI_A_VIDPOLCFG_DATAENPOL_ACTIVE_HIGH;
@@ -1085,20 +943,13 @@
 		de = HDMI_A_VIDPOLCFG_DATAENPOL_ACTIVE_LOW;
 
 	/* disable rx detect */
-	val = hdmi_readb(hdmi, HDMI_A_HDCPCFG0);
-	val &= HDMI_A_HDCPCFG0_RXDETECT_MASK;
-	val |= HDMI_A_HDCPCFG0_RXDETECT_DISABLE;
-	hdmi_writeb(hdmi, val, HDMI_A_HDCPCFG0);
+	hdmi_modb(hdmi, HDMI_A_HDCPCFG0_RXDETECT_DISABLE,
+		  HDMI_A_HDCPCFG0_RXDETECT_MASK, HDMI_A_HDCPCFG0);
 
-	val = hdmi_readb(hdmi, HDMI_A_VIDPOLCFG);
-	val &= HDMI_A_VIDPOLCFG_DATAENPOL_MASK;
-	val |= de;
-	hdmi_writeb(hdmi, val, HDMI_A_VIDPOLCFG);
+	hdmi_modb(hdmi, de, HDMI_A_VIDPOLCFG_DATAENPOL_MASK, HDMI_A_VIDPOLCFG);
 
-	val = hdmi_readb(hdmi, HDMI_A_HDCPCFG1);
-	val &= HDMI_A_HDCPCFG1_ENCRYPTIONDISABLE_MASK;
-	val |= HDMI_A_HDCPCFG1_ENCRYPTIONDISABLE_DISABLE;
-	hdmi_writeb(hdmi, val, HDMI_A_HDCPCFG1);
+	hdmi_modb(hdmi, HDMI_A_HDCPCFG1_ENCRYPTIONDISABLE_DISABLE,
+		  HDMI_A_HDCPCFG1_ENCRYPTIONDISABLE_MASK, HDMI_A_HDCPCFG1);
 }
 
 static void hdmi_config_AVI(struct imx_hdmi *hdmi)
@@ -1322,11 +1173,7 @@
 
 static void hdmi_enable_audio_clk(struct imx_hdmi *hdmi)
 {
-	u8 clkdis;
-
-	clkdis = hdmi_readb(hdmi, HDMI_MC_CLKDIS);
-	clkdis &= ~HDMI_MC_CLKDIS_AUDCLK_DISABLE;
-	hdmi_writeb(hdmi, clkdis, HDMI_MC_CLKDIS);
+	hdmi_modb(hdmi, 0, HDMI_MC_CLKDIS_AUDCLK_DISABLE, HDMI_MC_CLKDIS);
 }
 
 /* Workaround to clear the overflow condition */
@@ -1461,9 +1308,6 @@
 	/* Clear Hotplug interrupts */
 	hdmi_writeb(hdmi, HDMI_IH_PHY_STAT0_HPD, HDMI_IH_PHY_STAT0);
 
-	/* Unmute interrupts */
-	hdmi_writeb(hdmi, ~HDMI_IH_PHY_STAT0_HPD, HDMI_IH_MUTE_PHY_STAT0);
-
 	return 0;
 }
 
@@ -1532,12 +1376,9 @@
 static enum drm_connector_status imx_hdmi_connector_detect(struct drm_connector
 							*connector, bool force)
 {
-	/* FIXME */
-	return connector_status_connected;
-}
-
-static void imx_hdmi_connector_destroy(struct drm_connector *connector)
-{
+	struct imx_hdmi *hdmi = container_of(connector, struct imx_hdmi,
+					     connector);
+	return hdmi->connector_status;
 }
 
 static int imx_hdmi_connector_get_modes(struct drm_connector *connector)
@@ -1565,13 +1406,6 @@
 	return 0;
 }
 
-static int imx_hdmi_connector_mode_valid(struct drm_connector *connector,
-			  struct drm_display_mode *mode)
-{
-
-	return MODE_OK;
-}
-
 static struct drm_encoder *imx_hdmi_connector_best_encoder(struct drm_connector
 							   *connector)
 {
@@ -1619,28 +1453,21 @@
 	struct imx_hdmi *hdmi = container_of(encoder, struct imx_hdmi, encoder);
 
 	imx_hdmi_poweroff(hdmi);
-	imx_drm_crtc_panel_format(encoder->crtc, DRM_MODE_ENCODER_NONE,
-				  V4L2_PIX_FMT_RGB24);
+	imx_drm_panel_format(encoder, V4L2_PIX_FMT_RGB24);
 }
 
 static void imx_hdmi_encoder_commit(struct drm_encoder *encoder)
 {
 	struct imx_hdmi *hdmi = container_of(encoder, struct imx_hdmi, encoder);
-	int mux = imx_drm_encoder_get_mux_id(hdmi->imx_drm_encoder,
-					     encoder->crtc);
+	int mux = imx_drm_encoder_get_mux_id(encoder);
 
 	imx_hdmi_set_ipu_di_mux(hdmi, mux);
 
 	imx_hdmi_poweron(hdmi);
 }
 
-static void imx_hdmi_encoder_destroy(struct drm_encoder *encoder)
-{
-	return;
-}
-
 static struct drm_encoder_funcs imx_hdmi_encoder_funcs = {
-	.destroy = imx_hdmi_encoder_destroy,
+	.destroy = imx_drm_encoder_destroy,
 };
 
 static struct drm_encoder_helper_funcs imx_hdmi_encoder_helper_funcs = {
@@ -1656,21 +1483,32 @@
 	.dpms = drm_helper_connector_dpms,
 	.fill_modes = drm_helper_probe_single_connector_modes,
 	.detect = imx_hdmi_connector_detect,
-	.destroy = imx_hdmi_connector_destroy,
+	.destroy = imx_drm_connector_destroy,
 };
 
 static struct drm_connector_helper_funcs imx_hdmi_connector_helper_funcs = {
 	.get_modes = imx_hdmi_connector_get_modes,
-	.mode_valid = imx_hdmi_connector_mode_valid,
+	.mode_valid = imx_drm_connector_mode_valid,
 	.best_encoder = imx_hdmi_connector_best_encoder,
 };
 
+static irqreturn_t imx_hdmi_hardirq(int irq, void *dev_id)
+{
+	struct imx_hdmi *hdmi = dev_id;
+	u8 intr_stat;
+
+	intr_stat = hdmi_readb(hdmi, HDMI_IH_PHY_STAT0);
+	if (intr_stat)
+		hdmi_writeb(hdmi, ~0, HDMI_IH_MUTE_PHY_STAT0);
+
+	return intr_stat ? IRQ_WAKE_THREAD : IRQ_NONE;
+}
+
 static irqreturn_t imx_hdmi_irq(int irq, void *dev_id)
 {
 	struct imx_hdmi *hdmi = dev_id;
 	u8 intr_stat;
 	u8 phy_int_pol;
-	u8 val;
 
 	intr_stat = hdmi_readb(hdmi, HDMI_IH_PHY_STAT0);
 
@@ -1680,55 +1518,46 @@
 		if (phy_int_pol & HDMI_PHY_HPD) {
 			dev_dbg(hdmi->dev, "EVENT=plugin\n");
 
-			val = hdmi_readb(hdmi, HDMI_PHY_POL0);
-			val &= ~HDMI_PHY_HPD;
-			hdmi_writeb(hdmi, val, HDMI_PHY_POL0);
+			hdmi_modb(hdmi, 0, HDMI_PHY_HPD, HDMI_PHY_POL0);
 
+			hdmi->connector_status = connector_status_connected;
 			imx_hdmi_poweron(hdmi);
 		} else {
 			dev_dbg(hdmi->dev, "EVENT=plugout\n");
 
-			val = hdmi_readb(hdmi, HDMI_PHY_POL0);
-			val |= HDMI_PHY_HPD;
-			hdmi_writeb(hdmi, val, HDMI_PHY_POL0);
+			hdmi_modb(hdmi, HDMI_PHY_HPD, HDMI_PHY_HPD, HDMI_PHY_POL0);
 
+			hdmi->connector_status = connector_status_disconnected;
 			imx_hdmi_poweroff(hdmi);
 		}
+		drm_helper_hpd_irq_event(hdmi->connector.dev);
 	}
 
 	hdmi_writeb(hdmi, intr_stat, HDMI_IH_PHY_STAT0);
+	hdmi_writeb(hdmi, ~HDMI_IH_PHY_STAT0_HPD, HDMI_IH_MUTE_PHY_STAT0);
 
 	return IRQ_HANDLED;
 }
 
-static int imx_hdmi_register(struct imx_hdmi *hdmi)
+static int imx_hdmi_register(struct drm_device *drm, struct imx_hdmi *hdmi)
 {
 	int ret;
 
-	hdmi->connector.funcs = &imx_hdmi_connector_funcs;
-	hdmi->encoder.funcs = &imx_hdmi_encoder_funcs;
+	ret = imx_drm_encoder_parse_of(drm, &hdmi->encoder,
+				       hdmi->dev->of_node);
+	if (ret)
+		return ret;
 
-	hdmi->encoder.encoder_type = DRM_MODE_ENCODER_TMDS;
-	hdmi->connector.connector_type = DRM_MODE_CONNECTOR_HDMIA;
+	hdmi->connector.polled = DRM_CONNECTOR_POLL_HPD;
 
 	drm_encoder_helper_add(&hdmi->encoder, &imx_hdmi_encoder_helper_funcs);
-	ret = imx_drm_add_encoder(&hdmi->encoder, &hdmi->imx_drm_encoder,
-			THIS_MODULE);
-	if (ret) {
-		dev_err(hdmi->dev, "adding encoder failed: %d\n", ret);
-		return ret;
-	}
+	drm_encoder_init(drm, &hdmi->encoder, &imx_hdmi_encoder_funcs,
+			 DRM_MODE_ENCODER_TMDS);
 
 	drm_connector_helper_add(&hdmi->connector,
 			&imx_hdmi_connector_helper_funcs);
-
-	ret = imx_drm_add_connector(&hdmi->connector,
-			&hdmi->imx_drm_connector, THIS_MODULE);
-	if (ret) {
-		imx_drm_remove_encoder(hdmi->imx_drm_encoder);
-		dev_err(hdmi->dev, "adding connector failed: %d\n", ret);
-		return ret;
-	}
+	drm_connector_init(drm, &hdmi->connector, &imx_hdmi_connector_funcs,
+			   DRM_MODE_CONNECTOR_HDMIA);
 
 	hdmi->connector.encoder = &hdmi->encoder;
 
@@ -1755,21 +1584,26 @@
 };
 MODULE_DEVICE_TABLE(of, imx_hdmi_dt_ids);
 
-static int imx_hdmi_platform_probe(struct platform_device *pdev)
+static int imx_hdmi_bind(struct device *dev, struct device *master, void *data)
 {
+	struct platform_device *pdev = to_platform_device(dev);
 	const struct of_device_id *of_id =
-				of_match_device(imx_hdmi_dt_ids, &pdev->dev);
-	struct device_node *np = pdev->dev.of_node;
+				of_match_device(imx_hdmi_dt_ids, dev);
+	struct drm_device *drm = data;
+	struct device_node *np = dev->of_node;
 	struct device_node *ddc_node;
 	struct imx_hdmi *hdmi;
 	struct resource *iores;
 	int ret, irq;
 
-	hdmi = devm_kzalloc(&pdev->dev, sizeof(*hdmi), GFP_KERNEL);
+	hdmi = devm_kzalloc(dev, sizeof(*hdmi), GFP_KERNEL);
 	if (!hdmi)
 		return -ENOMEM;
 
-	hdmi->dev = &pdev->dev;
+	hdmi->dev = dev;
+	hdmi->connector_status = connector_status_disconnected;
+	hdmi->sample_rate = 48000;
+	hdmi->ratio = 100;
 
 	if (of_id) {
 		const struct platform_device_id *device_id = of_id->data;
@@ -1791,13 +1625,14 @@
 	if (irq < 0)
 		return -EINVAL;
 
-	ret = devm_request_irq(&pdev->dev, irq, imx_hdmi_irq, 0,
-			       dev_name(&pdev->dev), hdmi);
+	ret = devm_request_threaded_irq(dev, irq, imx_hdmi_hardirq,
+					imx_hdmi_irq, IRQF_SHARED,
+					dev_name(dev), hdmi);
 	if (ret)
 		return ret;
 
 	iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	hdmi->regs = devm_ioremap_resource(&pdev->dev, iores);
+	hdmi->regs = devm_ioremap_resource(dev, iores);
 	if (IS_ERR(hdmi->regs))
 		return PTR_ERR(hdmi->regs);
 
@@ -1836,7 +1671,7 @@
 	}
 
 	/* Product and revision IDs */
-	dev_info(&pdev->dev,
+	dev_info(dev,
 		"Detected HDMI controller 0x%x:0x%x:0x%x:0x%x\n",
 		hdmi_readb(hdmi, HDMI_DESIGN_ID),
 		hdmi_readb(hdmi, HDMI_REVISION_ID),
@@ -1864,13 +1699,14 @@
 	if (ret)
 		goto err_iahb;
 
-	ret = imx_hdmi_register(hdmi);
+	ret = imx_hdmi_register(drm, hdmi);
 	if (ret)
 		goto err_iahb;
 
-	imx_drm_encoder_add_possible_crtcs(hdmi->imx_drm_encoder, np);
+	/* Unmute interrupts */
+	hdmi_writeb(hdmi, ~HDMI_IH_PHY_STAT0_HPD, HDMI_IH_MUTE_PHY_STAT0);
 
-	platform_set_drvdata(pdev, hdmi);
+	dev_set_drvdata(dev, hdmi);
 
 	return 0;
 
@@ -1882,20 +1718,35 @@
 	return ret;
 }
 
-static int imx_hdmi_platform_remove(struct platform_device *pdev)
+static void imx_hdmi_unbind(struct device *dev, struct device *master,
+	void *data)
 {
-	struct imx_hdmi *hdmi = platform_get_drvdata(pdev);
-	struct drm_connector *connector = &hdmi->connector;
-	struct drm_encoder *encoder = &hdmi->encoder;
+	struct imx_hdmi *hdmi = dev_get_drvdata(dev);
 
-	drm_mode_connector_detach_encoder(connector, encoder);
-	imx_drm_remove_connector(hdmi->imx_drm_connector);
-	imx_drm_remove_encoder(hdmi->imx_drm_encoder);
+	/* Disable all interrupts */
+	hdmi_writeb(hdmi, ~0, HDMI_IH_MUTE_PHY_STAT0);
+
+	hdmi->connector.funcs->destroy(&hdmi->connector);
+	hdmi->encoder.funcs->destroy(&hdmi->encoder);
 
 	clk_disable_unprepare(hdmi->iahb_clk);
 	clk_disable_unprepare(hdmi->isfr_clk);
 	i2c_put_adapter(hdmi->ddc);
+}
 
+static const struct component_ops hdmi_ops = {
+	.bind	= imx_hdmi_bind,
+	.unbind	= imx_hdmi_unbind,
+};
+
+static int imx_hdmi_platform_probe(struct platform_device *pdev)
+{
+	return component_add(&pdev->dev, &hdmi_ops);
+}
+
+static int imx_hdmi_platform_remove(struct platform_device *pdev)
+{
+	component_del(&pdev->dev, &hdmi_ops);
 	return 0;
 }
 
diff --git a/drivers/staging/imx-drm/imx-ldb.c b/drivers/staging/imx-drm/imx-ldb.c
index 7e59329..daa54df 100644
--- a/drivers/staging/imx-drm/imx-ldb.c
+++ b/drivers/staging/imx-drm/imx-ldb.c
@@ -20,6 +20,7 @@
 
 #include <linux/module.h>
 #include <linux/clk.h>
+#include <linux/component.h>
 #include <drm/drmP.h>
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_crtc_helper.h>
@@ -58,9 +59,8 @@
 struct imx_ldb_channel {
 	struct imx_ldb *ldb;
 	struct drm_connector connector;
-	struct imx_drm_connector *imx_drm_connector;
 	struct drm_encoder encoder;
-	struct imx_drm_encoder *imx_drm_encoder;
+	struct device_node *child;
 	int chno;
 	void *edid;
 	int edid_len;
@@ -91,11 +91,6 @@
 	return connector_status_connected;
 }
 
-static void imx_ldb_connector_destroy(struct drm_connector *connector)
-{
-	/* do not free here */
-}
-
 static int imx_ldb_connector_get_modes(struct drm_connector *connector)
 {
 	struct imx_ldb_channel *imx_ldb_ch = con_to_imx_ldb_ch(connector);
@@ -111,6 +106,8 @@
 		struct drm_display_mode *mode;
 
 		mode = drm_mode_create(connector->dev);
+		if (!mode)
+			return -EINVAL;
 		drm_mode_copy(mode, &imx_ldb_ch->mode);
 		mode->type |= DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
 		drm_mode_probed_add(connector, mode);
@@ -120,12 +117,6 @@
 	return num_modes;
 }
 
-static int imx_ldb_connector_mode_valid(struct drm_connector *connector,
-			  struct drm_display_mode *mode)
-{
-	return 0;
-}
-
 static struct drm_encoder *imx_ldb_connector_best_encoder(
 		struct drm_connector *connector)
 {
@@ -179,8 +170,7 @@
 	u32 pixel_fmt;
 	unsigned long serial_clk;
 	unsigned long di_clk = mode->clock * 1000;
-	int mux = imx_drm_encoder_get_mux_id(imx_ldb_ch->imx_drm_encoder,
-					     encoder->crtc);
+	int mux = imx_drm_encoder_get_mux_id(encoder);
 
 	if (ldb->ldb_ctrl & LDB_SPLIT_MODE_EN) {
 		/* dual channel LVDS mode */
@@ -207,8 +197,7 @@
 		pixel_fmt = V4L2_PIX_FMT_RGB24;
 	}
 
-	imx_drm_crtc_panel_format(encoder->crtc, DRM_MODE_ENCODER_LVDS,
-			pixel_fmt);
+	imx_drm_panel_format(encoder, pixel_fmt);
 }
 
 static void imx_ldb_encoder_commit(struct drm_encoder *encoder)
@@ -216,8 +205,7 @@
 	struct imx_ldb_channel *imx_ldb_ch = enc_to_imx_ldb_ch(encoder);
 	struct imx_ldb *ldb = imx_ldb_ch->ldb;
 	int dual = ldb->ldb_ctrl & LDB_SPLIT_MODE_EN;
-	int mux = imx_drm_encoder_get_mux_id(imx_ldb_ch->imx_drm_encoder,
-					     encoder->crtc);
+	int mux = imx_drm_encoder_get_mux_id(encoder);
 
 	if (dual) {
 		clk_prepare_enable(ldb->clk[0]);
@@ -316,26 +304,21 @@
 	}
 }
 
-static void imx_ldb_encoder_destroy(struct drm_encoder *encoder)
-{
-	/* do not free here */
-}
-
 static struct drm_connector_funcs imx_ldb_connector_funcs = {
 	.dpms = drm_helper_connector_dpms,
 	.fill_modes = drm_helper_probe_single_connector_modes,
 	.detect = imx_ldb_connector_detect,
-	.destroy = imx_ldb_connector_destroy,
+	.destroy = imx_drm_connector_destroy,
 };
 
 static struct drm_connector_helper_funcs imx_ldb_connector_helper_funcs = {
 	.get_modes = imx_ldb_connector_get_modes,
 	.best_encoder = imx_ldb_connector_best_encoder,
-	.mode_valid = imx_ldb_connector_mode_valid,
+	.mode_valid = imx_drm_connector_mode_valid,
 };
 
 static struct drm_encoder_funcs imx_ldb_encoder_funcs = {
-	.destroy = imx_ldb_encoder_destroy,
+	.destroy = imx_drm_encoder_destroy,
 };
 
 static struct drm_encoder_helper_funcs imx_ldb_encoder_helper_funcs = {
@@ -351,56 +334,47 @@
 {
 	char clkname[16];
 
-	sprintf(clkname, "di%d", chno);
+	snprintf(clkname, sizeof(clkname), "di%d", chno);
 	ldb->clk[chno] = devm_clk_get(ldb->dev, clkname);
 	if (IS_ERR(ldb->clk[chno]))
 		return PTR_ERR(ldb->clk[chno]);
 
-	sprintf(clkname, "di%d_pll", chno);
+	snprintf(clkname, sizeof(clkname), "di%d_pll", chno);
 	ldb->clk_pll[chno] = devm_clk_get(ldb->dev, clkname);
 
 	return PTR_ERR_OR_ZERO(ldb->clk_pll[chno]);
 }
 
-static int imx_ldb_register(struct imx_ldb_channel *imx_ldb_ch)
+static int imx_ldb_register(struct drm_device *drm,
+	struct imx_ldb_channel *imx_ldb_ch)
 {
-	int ret;
 	struct imx_ldb *ldb = imx_ldb_ch->ldb;
+	int ret;
+
+	ret = imx_drm_encoder_parse_of(drm, &imx_ldb_ch->encoder,
+				       imx_ldb_ch->child);
+	if (ret)
+		return ret;
 
 	ret = imx_ldb_get_clk(ldb, imx_ldb_ch->chno);
 	if (ret)
 		return ret;
+
 	if (ldb->ldb_ctrl & LDB_SPLIT_MODE_EN) {
-		ret |= imx_ldb_get_clk(ldb, 1);
+		ret = imx_ldb_get_clk(ldb, 1);
 		if (ret)
 			return ret;
 	}
 
-	imx_ldb_ch->connector.funcs = &imx_ldb_connector_funcs;
-	imx_ldb_ch->encoder.funcs = &imx_ldb_encoder_funcs;
-
-	imx_ldb_ch->encoder.encoder_type = DRM_MODE_ENCODER_LVDS;
-	imx_ldb_ch->connector.connector_type = DRM_MODE_CONNECTOR_LVDS;
-
 	drm_encoder_helper_add(&imx_ldb_ch->encoder,
 			&imx_ldb_encoder_helper_funcs);
-	ret = imx_drm_add_encoder(&imx_ldb_ch->encoder,
-			&imx_ldb_ch->imx_drm_encoder, THIS_MODULE);
-	if (ret) {
-		dev_err(ldb->dev, "adding encoder failed with %d\n", ret);
-		return ret;
-	}
+	drm_encoder_init(drm, &imx_ldb_ch->encoder, &imx_ldb_encoder_funcs,
+			 DRM_MODE_ENCODER_LVDS);
 
 	drm_connector_helper_add(&imx_ldb_ch->connector,
 			&imx_ldb_connector_helper_funcs);
-
-	ret = imx_drm_add_connector(&imx_ldb_ch->connector,
-			&imx_ldb_ch->imx_drm_connector, THIS_MODULE);
-	if (ret) {
-		imx_drm_remove_encoder(imx_ldb_ch->imx_drm_encoder);
-		dev_err(ldb->dev, "adding connector failed with %d\n", ret);
-		return ret;
-	}
+	drm_connector_init(drm, &imx_ldb_ch->connector,
+			   &imx_ldb_connector_funcs, DRM_MODE_CONNECTOR_LVDS);
 
 	drm_mode_connector_attach_encoder(&imx_ldb_ch->connector,
 			&imx_ldb_ch->encoder);
@@ -459,11 +433,12 @@
 };
 MODULE_DEVICE_TABLE(of, imx_ldb_dt_ids);
 
-static int imx_ldb_probe(struct platform_device *pdev)
+static int imx_ldb_bind(struct device *dev, struct device *master, void *data)
 {
-	struct device_node *np = pdev->dev.of_node;
+	struct drm_device *drm = data;
+	struct device_node *np = dev->of_node;
 	const struct of_device_id *of_id =
-			of_match_device(imx_ldb_dt_ids, &pdev->dev);
+			of_match_device(imx_ldb_dt_ids, dev);
 	struct device_node *child;
 	const u8 *edidp;
 	struct imx_ldb *imx_ldb;
@@ -473,17 +448,17 @@
 	int ret;
 	int i;
 
-	imx_ldb = devm_kzalloc(&pdev->dev, sizeof(*imx_ldb), GFP_KERNEL);
+	imx_ldb = devm_kzalloc(dev, sizeof(*imx_ldb), GFP_KERNEL);
 	if (!imx_ldb)
 		return -ENOMEM;
 
 	imx_ldb->regmap = syscon_regmap_lookup_by_phandle(np, "gpr");
 	if (IS_ERR(imx_ldb->regmap)) {
-		dev_err(&pdev->dev, "failed to get parent regmap\n");
+		dev_err(dev, "failed to get parent regmap\n");
 		return PTR_ERR(imx_ldb->regmap);
 	}
 
-	imx_ldb->dev = &pdev->dev;
+	imx_ldb->dev = dev;
 
 	if (of_id)
 		imx_ldb->lvds_mux = of_id->data;
@@ -521,7 +496,7 @@
 			return -EINVAL;
 
 		if (dual && i > 0) {
-			dev_warn(&pdev->dev, "dual-channel mode, ignoring second output\n");
+			dev_warn(dev, "dual-channel mode, ignoring second output\n");
 			continue;
 		}
 
@@ -531,6 +506,7 @@
 		channel = &imx_ldb->channel[i];
 		channel->ldb = imx_ldb;
 		channel->chno = i;
+		channel->child = child;
 
 		edidp = of_get_property(child, "edid", &channel->edid_len);
 		if (edidp) {
@@ -560,7 +536,7 @@
 			break;
 		case LVDS_BIT_MAP_JEIDA:
 			if (datawidth == 18) {
-				dev_err(&pdev->dev, "JEIDA standard only supported in 24 bit\n");
+				dev_err(dev, "JEIDA standard only supported in 24 bit\n");
 				return -EINVAL;
 			}
 			if (i == 0 || dual)
@@ -569,38 +545,47 @@
 				imx_ldb->ldb_ctrl |= LDB_DATA_WIDTH_CH1_24 | LDB_BIT_MAP_CH1_JEIDA;
 			break;
 		default:
-			dev_err(&pdev->dev, "data mapping not specified or invalid\n");
+			dev_err(dev, "data mapping not specified or invalid\n");
 			return -EINVAL;
 		}
 
-		ret = imx_ldb_register(channel);
+		ret = imx_ldb_register(drm, channel);
 		if (ret)
 			return ret;
-
-		imx_drm_encoder_add_possible_crtcs(channel->imx_drm_encoder, child);
 	}
 
-	platform_set_drvdata(pdev, imx_ldb);
+	dev_set_drvdata(dev, imx_ldb);
 
 	return 0;
 }
 
-static int imx_ldb_remove(struct platform_device *pdev)
+static void imx_ldb_unbind(struct device *dev, struct device *master,
+	void *data)
 {
-	struct imx_ldb *imx_ldb = platform_get_drvdata(pdev);
+	struct imx_ldb *imx_ldb = dev_get_drvdata(dev);
 	int i;
 
 	for (i = 0; i < 2; i++) {
 		struct imx_ldb_channel *channel = &imx_ldb->channel[i];
-		struct drm_connector *connector = &channel->connector;
-		struct drm_encoder *encoder = &channel->encoder;
 
-		drm_mode_connector_detach_encoder(connector, encoder);
-
-		imx_drm_remove_connector(channel->imx_drm_connector);
-		imx_drm_remove_encoder(channel->imx_drm_encoder);
+		channel->connector.funcs->destroy(&channel->connector);
+		channel->encoder.funcs->destroy(&channel->encoder);
 	}
+}
 
+static const struct component_ops imx_ldb_ops = {
+	.bind	= imx_ldb_bind,
+	.unbind	= imx_ldb_unbind,
+};
+
+static int imx_ldb_probe(struct platform_device *pdev)
+{
+	return component_add(&pdev->dev, &imx_ldb_ops);
+}
+
+static int imx_ldb_remove(struct platform_device *pdev)
+{
+	component_del(&pdev->dev, &imx_ldb_ops);
 	return 0;
 }
 
diff --git a/drivers/staging/imx-drm/imx-tve.c b/drivers/staging/imx-drm/imx-tve.c
index 9abc7ca..50b25f1 100644
--- a/drivers/staging/imx-drm/imx-tve.c
+++ b/drivers/staging/imx-drm/imx-tve.c
@@ -20,6 +20,7 @@
 
 #include <linux/clk.h>
 #include <linux/clk-provider.h>
+#include <linux/component.h>
 #include <linux/module.h>
 #include <linux/i2c.h>
 #include <linux/regmap.h>
@@ -30,6 +31,7 @@
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_crtc_helper.h>
 
+#include "ipu-v3/imx-ipu-v3.h"
 #include "imx-drm.h"
 
 #define TVE_COM_CONF_REG	0x00
@@ -110,9 +112,7 @@
 
 struct imx_tve {
 	struct drm_connector connector;
-	struct imx_drm_connector *imx_drm_connector;
 	struct drm_encoder encoder;
-	struct imx_drm_encoder *imx_drm_encoder;
 	struct device *dev;
 	spinlock_t lock;	/* register lock */
 	bool enabled;
@@ -225,11 +225,6 @@
 	return connector_status_connected;
 }
 
-static void imx_tve_connector_destroy(struct drm_connector *connector)
-{
-	/* do not free here */
-}
-
 static int imx_tve_connector_get_modes(struct drm_connector *connector)
 {
 	struct imx_tve *tve = con_to_tve(connector);
@@ -254,6 +249,11 @@
 {
 	struct imx_tve *tve = con_to_tve(connector);
 	unsigned long rate;
+	int ret;
+
+	ret = imx_drm_connector_mode_valid(connector, mode);
+	if (ret != MODE_OK)
+		return ret;
 
 	/* pixel clock with 2x oversampling */
 	rate = clk_round_rate(tve->clk, 2000UL * mode->clock) / 2000;
@@ -305,13 +305,11 @@
 
 	switch (tve->mode) {
 	case TVE_MODE_VGA:
-		imx_drm_crtc_panel_format_pins(encoder->crtc,
-				DRM_MODE_ENCODER_DAC, IPU_PIX_FMT_GBR24,
+		imx_drm_panel_format_pins(encoder, IPU_PIX_FMT_GBR24,
 				tve->hsync_pin, tve->vsync_pin);
 		break;
 	case TVE_MODE_TVOUT:
-		imx_drm_crtc_panel_format(encoder->crtc, DRM_MODE_ENCODER_TVDAC,
-					  V4L2_PIX_FMT_YUV444);
+		imx_drm_panel_format(encoder, V4L2_PIX_FMT_YUV444);
 		break;
 	}
 }
@@ -364,16 +362,11 @@
 	tve_disable(tve);
 }
 
-static void imx_tve_encoder_destroy(struct drm_encoder *encoder)
-{
-	/* do not free here */
-}
-
 static struct drm_connector_funcs imx_tve_connector_funcs = {
 	.dpms = drm_helper_connector_dpms,
 	.fill_modes = drm_helper_probe_single_connector_modes,
 	.detect = imx_tve_connector_detect,
-	.destroy = imx_tve_connector_destroy,
+	.destroy = imx_drm_connector_destroy,
 };
 
 static struct drm_connector_helper_funcs imx_tve_connector_helper_funcs = {
@@ -383,7 +376,7 @@
 };
 
 static struct drm_encoder_funcs imx_tve_encoder_funcs = {
-	.destroy = imx_tve_encoder_destroy,
+	.destroy = imx_drm_encoder_destroy,
 };
 
 static struct drm_encoder_helper_funcs imx_tve_encoder_helper_funcs = {
@@ -503,34 +496,27 @@
 	return 0;
 }
 
-static int imx_tve_register(struct imx_tve *tve)
+static int imx_tve_register(struct drm_device *drm, struct imx_tve *tve)
 {
+	int encoder_type;
 	int ret;
 
-	tve->connector.funcs = &imx_tve_connector_funcs;
-	tve->encoder.funcs = &imx_tve_encoder_funcs;
+	encoder_type = tve->mode == TVE_MODE_VGA ?
+				DRM_MODE_ENCODER_DAC : DRM_MODE_ENCODER_TVDAC;
 
-	tve->encoder.encoder_type = DRM_MODE_ENCODER_NONE;
-	tve->connector.connector_type = DRM_MODE_CONNECTOR_VGA;
+	ret = imx_drm_encoder_parse_of(drm, &tve->encoder,
+				       tve->dev->of_node);
+	if (ret)
+		return ret;
 
 	drm_encoder_helper_add(&tve->encoder, &imx_tve_encoder_helper_funcs);
-	ret = imx_drm_add_encoder(&tve->encoder, &tve->imx_drm_encoder,
-			THIS_MODULE);
-	if (ret) {
-		dev_err(tve->dev, "adding encoder failed with %d\n", ret);
-		return ret;
-	}
+	drm_encoder_init(drm, &tve->encoder, &imx_tve_encoder_funcs,
+			 encoder_type);
 
 	drm_connector_helper_add(&tve->connector,
 			&imx_tve_connector_helper_funcs);
-
-	ret = imx_drm_add_connector(&tve->connector,
-			&tve->imx_drm_connector, THIS_MODULE);
-	if (ret) {
-		imx_drm_remove_encoder(tve->imx_drm_encoder);
-		dev_err(tve->dev, "adding connector failed with %d\n", ret);
-		return ret;
-	}
+	drm_connector_init(drm, &tve->connector, &imx_tve_connector_funcs,
+			   DRM_MODE_CONNECTOR_VGA);
 
 	drm_mode_connector_attach_encoder(&tve->connector, &tve->encoder);
 
@@ -576,9 +562,11 @@
 	return -EINVAL;
 }
 
-static int imx_tve_probe(struct platform_device *pdev)
+static int imx_tve_bind(struct device *dev, struct device *master, void *data)
 {
-	struct device_node *np = pdev->dev.of_node;
+	struct platform_device *pdev = to_platform_device(dev);
+	struct drm_device *drm = data;
+	struct device_node *np = dev->of_node;
 	struct device_node *ddc_node;
 	struct imx_tve *tve;
 	struct resource *res;
@@ -587,11 +575,11 @@
 	int irq;
 	int ret;
 
-	tve = devm_kzalloc(&pdev->dev, sizeof(*tve), GFP_KERNEL);
+	tve = devm_kzalloc(dev, sizeof(*tve), GFP_KERNEL);
 	if (!tve)
 		return -ENOMEM;
 
-	tve->dev = &pdev->dev;
+	tve->dev = dev;
 	spin_lock_init(&tve->lock);
 
 	ddc_node = of_parse_phandle(np, "ddc", 0);
@@ -602,7 +590,7 @@
 
 	tve->mode = of_get_tve_mode(np);
 	if (tve->mode != TVE_MODE_VGA) {
-		dev_err(&pdev->dev, "only VGA mode supported, currently\n");
+		dev_err(dev, "only VGA mode supported, currently\n");
 		return -EINVAL;
 	}
 
@@ -611,7 +599,7 @@
 					   &tve->hsync_pin);
 
 		if (ret < 0) {
-			dev_err(&pdev->dev, "failed to get vsync pin\n");
+			dev_err(dev, "failed to get vsync pin\n");
 			return ret;
 		}
 
@@ -619,40 +607,40 @@
 					    &tve->vsync_pin);
 
 		if (ret < 0) {
-			dev_err(&pdev->dev, "failed to get vsync pin\n");
+			dev_err(dev, "failed to get vsync pin\n");
 			return ret;
 		}
 	}
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	base = devm_ioremap_resource(&pdev->dev, res);
+	base = devm_ioremap_resource(dev, res);
 	if (IS_ERR(base))
 		return PTR_ERR(base);
 
 	tve_regmap_config.lock_arg = tve;
-	tve->regmap = devm_regmap_init_mmio_clk(&pdev->dev, "tve", base,
+	tve->regmap = devm_regmap_init_mmio_clk(dev, "tve", base,
 						&tve_regmap_config);
 	if (IS_ERR(tve->regmap)) {
-		dev_err(&pdev->dev, "failed to init regmap: %ld\n",
+		dev_err(dev, "failed to init regmap: %ld\n",
 			PTR_ERR(tve->regmap));
 		return PTR_ERR(tve->regmap);
 	}
 
 	irq = platform_get_irq(pdev, 0);
 	if (irq < 0) {
-		dev_err(&pdev->dev, "failed to get irq\n");
+		dev_err(dev, "failed to get irq\n");
 		return irq;
 	}
 
-	ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
+	ret = devm_request_threaded_irq(dev, irq, NULL,
 					imx_tve_irq_handler, IRQF_ONESHOT,
 					"imx-tve", tve);
 	if (ret < 0) {
-		dev_err(&pdev->dev, "failed to request irq: %d\n", ret);
+		dev_err(dev, "failed to request irq: %d\n", ret);
 		return ret;
 	}
 
-	tve->dac_reg = devm_regulator_get(&pdev->dev, "dac");
+	tve->dac_reg = devm_regulator_get(dev, "dac");
 	if (!IS_ERR(tve->dac_reg)) {
 		regulator_set_voltage(tve->dac_reg, 2750000, 2750000);
 		ret = regulator_enable(tve->dac_reg);
@@ -660,17 +648,17 @@
 			return ret;
 	}
 
-	tve->clk = devm_clk_get(&pdev->dev, "tve");
+	tve->clk = devm_clk_get(dev, "tve");
 	if (IS_ERR(tve->clk)) {
-		dev_err(&pdev->dev, "failed to get high speed tve clock: %ld\n",
+		dev_err(dev, "failed to get high speed tve clock: %ld\n",
 			PTR_ERR(tve->clk));
 		return PTR_ERR(tve->clk);
 	}
 
 	/* this is the IPU DI clock input selector, can be parented to tve_di */
-	tve->di_sel_clk = devm_clk_get(&pdev->dev, "di_sel");
+	tve->di_sel_clk = devm_clk_get(dev, "di_sel");
 	if (IS_ERR(tve->di_sel_clk)) {
-		dev_err(&pdev->dev, "failed to get ipu di mux clock: %ld\n",
+		dev_err(dev, "failed to get ipu di mux clock: %ld\n",
 			PTR_ERR(tve->di_sel_clk));
 		return PTR_ERR(tve->di_sel_clk);
 	}
@@ -681,42 +669,51 @@
 
 	ret = regmap_read(tve->regmap, TVE_COM_CONF_REG, &val);
 	if (ret < 0) {
-		dev_err(&pdev->dev, "failed to read configuration register: %d\n", ret);
+		dev_err(dev, "failed to read configuration register: %d\n", ret);
 		return ret;
 	}
 	if (val != 0x00100000) {
-		dev_err(&pdev->dev, "configuration register default value indicates this is not a TVEv2\n");
+		dev_err(dev, "configuration register default value indicates this is not a TVEv2\n");
 		return -ENODEV;
 	}
 
 	/* disable cable detection for VGA mode */
 	ret = regmap_write(tve->regmap, TVE_CD_CONT_REG, 0);
 
-	ret = imx_tve_register(tve);
+	ret = imx_tve_register(drm, tve);
 	if (ret)
 		return ret;
 
-	ret = imx_drm_encoder_add_possible_crtcs(tve->imx_drm_encoder, np);
-
-	platform_set_drvdata(pdev, tve);
+	dev_set_drvdata(dev, tve);
 
 	return 0;
 }
 
-static int imx_tve_remove(struct platform_device *pdev)
+static void imx_tve_unbind(struct device *dev, struct device *master,
+	void *data)
 {
-	struct imx_tve *tve = platform_get_drvdata(pdev);
-	struct drm_connector *connector = &tve->connector;
-	struct drm_encoder *encoder = &tve->encoder;
+	struct imx_tve *tve = dev_get_drvdata(dev);
 
-	drm_mode_connector_detach_encoder(connector, encoder);
-
-	imx_drm_remove_connector(tve->imx_drm_connector);
-	imx_drm_remove_encoder(tve->imx_drm_encoder);
+	tve->connector.funcs->destroy(&tve->connector);
+	tve->encoder.funcs->destroy(&tve->encoder);
 
 	if (!IS_ERR(tve->dac_reg))
 		regulator_disable(tve->dac_reg);
+}
 
+static const struct component_ops imx_tve_ops = {
+	.bind	= imx_tve_bind,
+	.unbind	= imx_tve_unbind,
+};
+
+static int imx_tve_probe(struct platform_device *pdev)
+{
+	return component_add(&pdev->dev, &imx_tve_ops);
+}
+
+static int imx_tve_remove(struct platform_device *pdev)
+{
+	component_del(&pdev->dev, &imx_tve_ops);
 	return 0;
 }
 
diff --git a/drivers/staging/imx-drm/ipu-v3/imx-ipu-v3.h b/drivers/staging/imx-drm/ipu-v3/imx-ipu-v3.h
index 4826b5c..c4d14ea 100644
--- a/drivers/staging/imx-drm/ipu-v3/imx-ipu-v3.h
+++ b/drivers/staging/imx-drm/ipu-v3/imx-ipu-v3.h
@@ -25,6 +25,8 @@
 	IPUV3H,
 };
 
+#define IPU_PIX_FMT_GBR24	v4l2_fourcc('G', 'B', 'R', '3')
+
 /*
  * Bitfield of Display Interface signal polarities.
  */
diff --git a/drivers/staging/imx-drm/ipu-v3/ipu-dc.c b/drivers/staging/imx-drm/ipu-v3/ipu-dc.c
index d0e3bc3..d5de8bb 100644
--- a/drivers/staging/imx-drm/ipu-v3/ipu-dc.c
+++ b/drivers/staging/imx-drm/ipu-v3/ipu-dc.c
@@ -262,7 +262,7 @@
 
 	/* Wait for DC triple buffer to empty */
 	while ((readl(priv->dc_reg + DC_STAT) & val) != val) {
-		msleep(2);
+		usleep_range(2000, 20000);
 		timeout -= 2;
 		if (timeout <= 0)
 			break;
diff --git a/drivers/staging/imx-drm/ipu-v3/ipu-di.c b/drivers/staging/imx-drm/ipu-v3/ipu-di.c
index 948a49b..82a9eba 100644
--- a/drivers/staging/imx-drm/ipu-v3/ipu-di.c
+++ b/drivers/staging/imx-drm/ipu-v3/ipu-di.c
@@ -19,9 +19,6 @@
 #include <linux/io.h>
 #include <linux/err.h>
 #include <linux/platform_device.h>
-#include <linux/clk.h>
-#include <linux/clk-provider.h>
-#include <linux/clkdev.h>
 
 #include "imx-ipu-v3.h"
 #include "ipu-prv.h"
@@ -33,10 +30,7 @@
 	struct clk *clk_di;	/* display input clock */
 	struct clk *clk_ipu;	/* IPU bus clock */
 	struct clk *clk_di_pixel; /* resulting pixel clock */
-	struct clk_hw clk_hw_out;
-	char *clk_name;
 	bool inuse;
-	unsigned long clkflags;
 	struct ipu_soc *ipu;
 };
 
@@ -141,130 +135,6 @@
 	writel(value, di->base + offset);
 }
 
-static int ipu_di_clk_calc_div(unsigned long inrate, unsigned long outrate)
-{
-	u64 tmp = inrate;
-	int div;
-
-	tmp *= 16;
-
-	do_div(tmp, outrate);
-
-	div = tmp;
-
-	if (div < 0x10)
-		div = 0x10;
-
-#ifdef WTF_IS_THIS
-	/*
-	 * Freescale has this in their Kernel. It is neither clear what
-	 * it does nor why it does it
-	 */
-	if (div & 0x10)
-		div &= ~0x7;
-	else {
-		/* Round up divider if it gets us closer to desired pix clk */
-		if ((div & 0xC) == 0xC) {
-			div += 0x10;
-			div &= ~0xF;
-		}
-	}
-#endif
-	return div;
-}
-
-static unsigned long clk_di_recalc_rate(struct clk_hw *hw,
-		unsigned long parent_rate)
-{
-	struct ipu_di *di = container_of(hw, struct ipu_di, clk_hw_out);
-	unsigned long outrate;
-	u32 div = ipu_di_read(di, DI_BS_CLKGEN0);
-
-	if (div < 0x10)
-		div = 0x10;
-
-	outrate = (parent_rate / div) * 16;
-
-	return outrate;
-}
-
-static long clk_di_round_rate(struct clk_hw *hw, unsigned long rate,
-				unsigned long *prate)
-{
-	struct ipu_di *di = container_of(hw, struct ipu_di, clk_hw_out);
-	unsigned long outrate;
-	int div;
-	u32 val;
-
-	div = ipu_di_clk_calc_div(*prate, rate);
-
-	outrate = (*prate / div) * 16;
-
-	val = ipu_di_read(di, DI_GENERAL);
-
-	if (!(val & DI_GEN_DI_CLK_EXT) && outrate > *prate / 2)
-		outrate = *prate / 2;
-
-	dev_dbg(di->ipu->dev,
-		"%s: inrate: %ld div: 0x%08x outrate: %ld wanted: %ld\n",
-			__func__, *prate, div, outrate, rate);
-
-	return outrate;
-}
-
-static int clk_di_set_rate(struct clk_hw *hw, unsigned long rate,
-				unsigned long parent_rate)
-{
-	struct ipu_di *di = container_of(hw, struct ipu_di, clk_hw_out);
-	int div;
-	u32 clkgen0;
-
-	clkgen0 = ipu_di_read(di, DI_BS_CLKGEN0) & ~0xfff;
-
-	div = ipu_di_clk_calc_div(parent_rate, rate);
-
-	ipu_di_write(di, clkgen0 | div, DI_BS_CLKGEN0);
-
-	dev_dbg(di->ipu->dev, "%s: inrate: %ld desired: %ld div: 0x%08x\n",
-			__func__, parent_rate, rate, div);
-	return 0;
-}
-
-static u8 clk_di_get_parent(struct clk_hw *hw)
-{
-	struct ipu_di *di = container_of(hw, struct ipu_di, clk_hw_out);
-	u32 val;
-
-	val = ipu_di_read(di, DI_GENERAL);
-
-	return val & DI_GEN_DI_CLK_EXT ? 1 : 0;
-}
-
-static int clk_di_set_parent(struct clk_hw *hw, u8 index)
-{
-	struct ipu_di *di = container_of(hw, struct ipu_di, clk_hw_out);
-	u32 val;
-
-	val = ipu_di_read(di, DI_GENERAL);
-
-	if (index)
-		val |= DI_GEN_DI_CLK_EXT;
-	else
-		val &= ~DI_GEN_DI_CLK_EXT;
-
-	ipu_di_write(di, val, DI_GENERAL);
-
-	return 0;
-}
-
-static struct clk_ops clk_di_ops = {
-	.round_rate = clk_di_round_rate,
-	.set_rate = clk_di_set_rate,
-	.recalc_rate = clk_di_recalc_rate,
-	.set_parent = clk_di_set_parent,
-	.get_parent = clk_di_get_parent,
-};
-
 static void ipu_di_data_wave_config(struct ipu_di *di,
 				     int wave_gen,
 				     int access_size, int component_size)
@@ -528,15 +398,125 @@
 		ipu_di_sync_config(di, cfg_vga, 0, ARRAY_SIZE(cfg_vga));
 }
 
+static void ipu_di_config_clock(struct ipu_di *di,
+	const struct ipu_di_signal_cfg *sig)
+{
+	struct clk *clk;
+	unsigned clkgen0;
+	uint32_t val;
+
+	if (sig->clkflags & IPU_DI_CLKMODE_EXT) {
+		/*
+		 * CLKMODE_EXT means we must use the DI clock: this is
+		 * needed for things like LVDS which needs to feed the
+		 * DI and LDB with the same pixel clock.
+		 */
+		clk = di->clk_di;
+
+		if (sig->clkflags & IPU_DI_CLKMODE_SYNC) {
+			/*
+			 * CLKMODE_SYNC means that we want the DI to be
+			 * clocked at the same rate as the parent clock.
+			 * This is needed (eg) for LDB which needs to be
+			 * fed with the same pixel clock.  We assume that
+			 * the LDB clock has already been set correctly.
+			 */
+			clkgen0 = 1 << 4;
+		} else {
+			/*
+			 * We can use the divider.  We should really have
+			 * a flag here indicating whether the bridge can
+			 * cope with a fractional divider or not.  For the
+			 * time being, let's go for simplicitly and
+			 * reliability.
+			 */
+			unsigned long in_rate;
+			unsigned div;
+
+			clk_set_rate(clk, sig->pixelclock);
+
+			in_rate = clk_get_rate(clk);
+			div = (in_rate + sig->pixelclock / 2) / sig->pixelclock;
+			if (div == 0)
+				div = 1;
+
+			clkgen0 = div << 4;
+		}
+	} else {
+		/*
+		 * For other interfaces, we can arbitarily select between
+		 * the DI specific clock and the internal IPU clock.  See
+		 * DI_GENERAL bit 20.  We select the IPU clock if it can
+		 * give us a clock rate within 1% of the requested frequency,
+		 * otherwise we use the DI clock.
+		 */
+		unsigned long rate, clkrate;
+		unsigned div, error;
+
+		clkrate = clk_get_rate(di->clk_ipu);
+		div = (clkrate + sig->pixelclock / 2) / sig->pixelclock;
+		rate = clkrate / div;
+
+		error = rate / (sig->pixelclock / 1000);
+
+		dev_dbg(di->ipu->dev, "  IPU clock can give %lu with divider %u, error %d.%u%%\n",
+			rate, div, (signed)(error - 1000) / 10, error % 10);
+
+		/* Allow a 1% error */
+		if (error < 1010 && error >= 990) {
+			clk = di->clk_ipu;
+
+			clkgen0 = div << 4;
+		} else {
+			unsigned long in_rate;
+			unsigned div;
+
+			clk = di->clk_di;
+
+			clk_set_rate(clk, sig->pixelclock);
+
+			in_rate = clk_get_rate(clk);
+			div = (in_rate + sig->pixelclock / 2) / sig->pixelclock;
+			if (div == 0)
+				div = 1;
+
+			clkgen0 = div << 4;
+		}
+	}
+
+	di->clk_di_pixel = clk;
+
+	/* Set the divider */
+	ipu_di_write(di, clkgen0, DI_BS_CLKGEN0);
+
+	/*
+	 * Set the high/low periods.  Bits 24:16 give us the falling edge,
+	 * and bits 8:0 give the rising edge.  LSB is fraction, and is
+	 * based on the divider above.  We want a 50% duty cycle, so set
+	 * the falling edge to be half the divider.
+	 */
+	ipu_di_write(di, (clkgen0 >> 4) << 16, DI_BS_CLKGEN1);
+
+	/* Finally select the input clock */
+	val = ipu_di_read(di, DI_GENERAL) & ~DI_GEN_DI_CLK_EXT;
+	if (clk == di->clk_di)
+		val |= DI_GEN_DI_CLK_EXT;
+	ipu_di_write(di, val, DI_GENERAL);
+
+	dev_dbg(di->ipu->dev, "Want %luHz IPU %luHz DI %luHz using %s, %luHz\n",
+		sig->pixelclock,
+		clk_get_rate(di->clk_ipu),
+		clk_get_rate(di->clk_di),
+		clk == di->clk_di ? "DI" : "IPU",
+		clk_get_rate(di->clk_di_pixel) / (clkgen0 >> 4));
+}
+
 int ipu_di_init_sync_panel(struct ipu_di *di, struct ipu_di_signal_cfg *sig)
 {
 	u32 reg;
 	u32 di_gen, vsync_cnt;
 	u32 div;
 	u32 h_total, v_total;
-	int ret;
-	unsigned long round;
-	struct clk *parent;
 
 	dev_dbg(di->ipu->dev, "disp %d: panel size = %d x %d\n",
 		di->id, sig->width, sig->height);
@@ -544,33 +524,20 @@
 	if ((sig->v_sync_width == 0) || (sig->h_sync_width == 0))
 		return -EINVAL;
 
-	if (sig->clkflags & IPU_DI_CLKMODE_EXT)
-		parent = di->clk_di;
-	else
-		parent = di->clk_ipu;
-
-	ret = clk_set_parent(di->clk_di_pixel, parent);
-	if (ret) {
-		dev_err(di->ipu->dev,
-			"setting pixel clock to parent %s failed with %d\n",
-				__clk_get_name(parent), ret);
-		return ret;
-	}
-
-	if (sig->clkflags & IPU_DI_CLKMODE_SYNC)
-		round = clk_get_rate(parent);
-	else
-		round = clk_round_rate(di->clk_di_pixel, sig->pixelclock);
-
-	ret = clk_set_rate(di->clk_di_pixel, round);
-
 	h_total = sig->width + sig->h_sync_width + sig->h_start_width +
 		sig->h_end_width;
 	v_total = sig->height + sig->v_sync_width + sig->v_start_width +
 		sig->v_end_width;
 
+	dev_dbg(di->ipu->dev, "Clocks: IPU %luHz DI %luHz Needed %luHz\n",
+		clk_get_rate(di->clk_ipu),
+		clk_get_rate(di->clk_di),
+		sig->pixelclock);
+
 	mutex_lock(&di_mutex);
 
+	ipu_di_config_clock(di, sig);
+
 	div = ipu_di_read(di, DI_BS_CLKGEN0) & 0xfff;
 	div = div / 16;		/* Now divider is integer portion */
 
@@ -654,7 +621,11 @@
 
 int ipu_di_enable(struct ipu_di *di)
 {
-	int ret = clk_prepare_enable(di->clk_di_pixel);
+	int ret;
+
+	WARN_ON(IS_ERR(di->clk_di_pixel));
+
+	ret = clk_prepare_enable(di->clk_di_pixel);
 	if (ret)
 		return ret;
 
@@ -666,6 +637,8 @@
 
 int ipu_di_disable(struct ipu_di *di)
 {
+	WARN_ON(IS_ERR(di->clk_di_pixel));
+
 	ipu_module_disable(di->ipu, di->module);
 
 	clk_disable_unprepare(di->clk_di_pixel);
@@ -721,13 +694,6 @@
 		u32 module, struct clk *clk_ipu)
 {
 	struct ipu_di *di;
-	int ret;
-	const char *di_parent[2];
-	struct clk_init_data init = {
-		.ops = &clk_di_ops,
-		.num_parents = 2,
-		.flags = 0,
-	};
 
 	if (id > 1)
 		return -ENODEV;
@@ -749,45 +715,16 @@
 	if (!di->base)
 		return -ENOMEM;
 
-	di_parent[0] = __clk_get_name(di->clk_ipu);
-	di_parent[1] = __clk_get_name(di->clk_di);
-
 	ipu_di_write(di, 0x10, DI_BS_CLKGEN0);
 
-	init.parent_names = (const char **)&di_parent;
-	di->clk_name = kasprintf(GFP_KERNEL, "%s_di%d_pixel",
-			dev_name(dev), id);
-	if (!di->clk_name)
-		return -ENOMEM;
-
-	init.name = di->clk_name;
-
-	di->clk_hw_out.init = &init;
-	di->clk_di_pixel = clk_register(dev, &di->clk_hw_out);
-
-	if (IS_ERR(di->clk_di_pixel)) {
-		ret = PTR_ERR(di->clk_di_pixel);
-		goto failed_clk_register;
-	}
-
 	dev_dbg(dev, "DI%d base: 0x%08lx remapped to %p\n",
 			id, base, di->base);
 	di->inuse = false;
 	di->ipu = ipu;
 
 	return 0;
-
-failed_clk_register:
-
-	kfree(di->clk_name);
-
-	return ret;
 }
 
 void ipu_di_exit(struct ipu_soc *ipu, int id)
 {
-	struct ipu_di *di = ipu->di_priv[id];
-
-	clk_unregister(di->clk_di_pixel);
-	kfree(di->clk_name);
 }
diff --git a/drivers/staging/imx-drm/ipu-v3/ipu-dmfc.c b/drivers/staging/imx-drm/ipu-v3/ipu-dmfc.c
index 98070dd..4521301 100644
--- a/drivers/staging/imx-drm/ipu-v3/ipu-dmfc.c
+++ b/drivers/staging/imx-drm/ipu-v3/ipu-dmfc.c
@@ -161,9 +161,6 @@
 			"dmfc: using %d slots starting from segment %d for IPU channel %d\n",
 			slots, segment, dmfc->data->ipu_channel);
 
-	if (!dmfc)
-		return -EINVAL;
-
 	switch (slots) {
 	case 1:
 		field = DMFC_FIFO_SIZE_64;
diff --git a/drivers/staging/imx-drm/ipuv3-crtc.c b/drivers/staging/imx-drm/ipuv3-crtc.c
index 22be104..e646017 100644
--- a/drivers/staging/imx-drm/ipuv3-crtc.c
+++ b/drivers/staging/imx-drm/ipuv3-crtc.c
@@ -17,6 +17,7 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
  * MA 02110-1301, USA.
  */
+#include <linux/component.h>
 #include <linux/module.h>
 #include <linux/export.h>
 #include <linux/device.h>
@@ -284,6 +285,7 @@
 		ipu_crtc->di_clkflags = IPU_DI_CLKMODE_SYNC |
 			IPU_DI_CLKMODE_EXT;
 		break;
+	case DRM_MODE_ENCODER_TMDS:
 	case DRM_MODE_ENCODER_NONE:
 		ipu_crtc->di_clkflags = 0;
 		break;
@@ -334,7 +336,7 @@
 }
 
 static int ipu_crtc_init(struct ipu_crtc *ipu_crtc,
-		struct ipu_client_platformdata *pdata)
+	struct ipu_client_platformdata *pdata, struct drm_device *drm)
 {
 	struct ipu_soc *ipu = dev_get_drvdata(ipu_crtc->dev->parent);
 	int dp = -EINVAL;
@@ -348,9 +350,9 @@
 		return ret;
 	}
 
-	ret = imx_drm_add_crtc(&ipu_crtc->base,
+	ret = imx_drm_add_crtc(drm, &ipu_crtc->base,
 			&ipu_crtc->imx_crtc,
-			&ipu_crtc_helper_funcs, THIS_MODULE,
+			&ipu_crtc_helper_funcs,
 			ipu_crtc->dev->parent->of_node, pdata->di);
 	if (ret) {
 		dev_err(ipu_crtc->dev, "adding crtc failed with %d.\n", ret);
@@ -399,43 +401,61 @@
 	return ret;
 }
 
-static int ipu_drm_probe(struct platform_device *pdev)
+static int ipu_drm_bind(struct device *dev, struct device *master, void *data)
 {
-	struct ipu_client_platformdata *pdata = pdev->dev.platform_data;
+	struct ipu_client_platformdata *pdata = dev->platform_data;
+	struct drm_device *drm = data;
 	struct ipu_crtc *ipu_crtc;
 	int ret;
 
-	if (!pdata)
+	ipu_crtc = devm_kzalloc(dev, sizeof(*ipu_crtc), GFP_KERNEL);
+	if (!ipu_crtc)
+		return -ENOMEM;
+
+	ipu_crtc->dev = dev;
+
+	ret = ipu_crtc_init(ipu_crtc, pdata, drm);
+	if (ret)
+		return ret;
+
+	dev_set_drvdata(dev, ipu_crtc);
+
+	return 0;
+}
+
+static void ipu_drm_unbind(struct device *dev, struct device *master,
+	void *data)
+{
+	struct ipu_crtc *ipu_crtc = dev_get_drvdata(dev);
+
+	imx_drm_remove_crtc(ipu_crtc->imx_crtc);
+
+	ipu_plane_put_resources(ipu_crtc->plane[0]);
+	ipu_put_resources(ipu_crtc);
+}
+
+static const struct component_ops ipu_crtc_ops = {
+	.bind = ipu_drm_bind,
+	.unbind = ipu_drm_unbind,
+};
+
+static int ipu_drm_probe(struct platform_device *pdev)
+{
+	int ret;
+
+	if (!pdev->dev.platform_data)
 		return -EINVAL;
 
 	ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
 	if (ret)
 		return ret;
 
-	ipu_crtc = devm_kzalloc(&pdev->dev, sizeof(*ipu_crtc), GFP_KERNEL);
-	if (!ipu_crtc)
-		return -ENOMEM;
-
-	ipu_crtc->dev = &pdev->dev;
-
-	ret = ipu_crtc_init(ipu_crtc, pdata);
-	if (ret)
-		return ret;
-
-	platform_set_drvdata(pdev, ipu_crtc);
-
-	return 0;
+	return component_add(&pdev->dev, &ipu_crtc_ops);
 }
 
 static int ipu_drm_remove(struct platform_device *pdev)
 {
-	struct ipu_crtc *ipu_crtc = platform_get_drvdata(pdev);
-
-	imx_drm_remove_crtc(ipu_crtc->imx_crtc);
-
-	ipu_plane_put_resources(ipu_crtc->plane[0]);
-	ipu_put_resources(ipu_crtc);
-
+	component_del(&pdev->dev, &ipu_crtc_ops);
 	return 0;
 }
 
diff --git a/drivers/staging/imx-drm/ipuv3-plane.c b/drivers/staging/imx-drm/ipuv3-plane.c
index 34b642a..b0c9b6c 100644
--- a/drivers/staging/imx-drm/ipuv3-plane.c
+++ b/drivers/staging/imx-drm/ipuv3-plane.c
@@ -72,8 +72,8 @@
 		return -EFAULT;
 	}
 
-	dev_dbg(ipu_plane->base.dev->dev, "phys = 0x%x, x = %d, y = %d",
-		cma_obj->paddr, x, y);
+	dev_dbg(ipu_plane->base.dev->dev, "phys = %pad, x = %d, y = %d",
+		&cma_obj->paddr, x, y);
 
 	cpmem = ipu_get_cpmem(ipu_plane->ipu_ch);
 	ipu_cpmem_set_stride(cpmem, fb->pitches[0]);
diff --git a/drivers/staging/imx-drm/parallel-display.c b/drivers/staging/imx-drm/parallel-display.c
index 351d61d..c60b6c6 100644
--- a/drivers/staging/imx-drm/parallel-display.c
+++ b/drivers/staging/imx-drm/parallel-display.c
@@ -18,10 +18,12 @@
  * MA 02110-1301, USA.
  */
 
+#include <linux/component.h>
 #include <linux/module.h>
 #include <drm/drmP.h>
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_crtc_helper.h>
+#include <drm/drm_panel.h>
 #include <linux/videodev2.h>
 #include <video/of_display_timing.h>
 
@@ -32,15 +34,14 @@
 
 struct imx_parallel_display {
 	struct drm_connector connector;
-	struct imx_drm_connector *imx_drm_connector;
 	struct drm_encoder encoder;
-	struct imx_drm_encoder *imx_drm_encoder;
 	struct device *dev;
 	void *edid;
 	int edid_len;
 	u32 interface_pix_fmt;
 	int mode_valid;
 	struct drm_display_mode mode;
+	struct drm_panel *panel;
 };
 
 static enum drm_connector_status imx_pd_connector_detect(
@@ -49,17 +50,19 @@
 	return connector_status_connected;
 }
 
-static void imx_pd_connector_destroy(struct drm_connector *connector)
-{
-	/* do not free here */
-}
-
 static int imx_pd_connector_get_modes(struct drm_connector *connector)
 {
 	struct imx_parallel_display *imxpd = con_to_imxpd(connector);
 	struct device_node *np = imxpd->dev->of_node;
 	int num_modes = 0;
 
+	if (imxpd->panel && imxpd->panel->funcs &&
+	    imxpd->panel->funcs->get_modes) {
+		num_modes = imxpd->panel->funcs->get_modes(imxpd->panel);
+		if (num_modes > 0)
+			return num_modes;
+	}
+
 	if (imxpd->edid) {
 		drm_mode_connector_update_edid_property(connector, imxpd->edid);
 		num_modes = drm_add_edid_modes(connector, imxpd->edid);
@@ -67,6 +70,8 @@
 
 	if (imxpd->mode_valid) {
 		struct drm_display_mode *mode = drm_mode_create(connector->dev);
+		if (!mode)
+			return -EINVAL;
 		drm_mode_copy(mode, &imxpd->mode);
 		mode->type |= DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
 		drm_mode_probed_add(connector, mode);
@@ -75,6 +80,8 @@
 
 	if (np) {
 		struct drm_display_mode *mode = drm_mode_create(connector->dev);
+		if (!mode)
+			return -EINVAL;
 		of_get_drm_display_mode(np, &imxpd->mode, OF_USE_NATIVE_MODE);
 		drm_mode_copy(mode, &imxpd->mode);
 		mode->type |= DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
@@ -85,12 +92,6 @@
 	return num_modes;
 }
 
-static int imx_pd_connector_mode_valid(struct drm_connector *connector,
-			  struct drm_display_mode *mode)
-{
-	return 0;
-}
-
 static struct drm_encoder *imx_pd_connector_best_encoder(
 		struct drm_connector *connector)
 {
@@ -101,6 +102,12 @@
 
 static void imx_pd_encoder_dpms(struct drm_encoder *encoder, int mode)
 {
+	struct imx_parallel_display *imxpd = enc_to_imxpd(encoder);
+
+	if (mode != DRM_MODE_DPMS_ON)
+		drm_panel_disable(imxpd->panel);
+	else
+		drm_panel_enable(imxpd->panel);
 }
 
 static bool imx_pd_encoder_mode_fixup(struct drm_encoder *encoder,
@@ -114,8 +121,7 @@
 {
 	struct imx_parallel_display *imxpd = enc_to_imxpd(encoder);
 
-	imx_drm_crtc_panel_format(encoder->crtc, DRM_MODE_ENCODER_NONE,
-			imxpd->interface_pix_fmt);
+	imx_drm_panel_format(encoder, imxpd->interface_pix_fmt);
 }
 
 static void imx_pd_encoder_commit(struct drm_encoder *encoder)
@@ -132,26 +138,21 @@
 {
 }
 
-static void imx_pd_encoder_destroy(struct drm_encoder *encoder)
-{
-	/* do not free here */
-}
-
 static struct drm_connector_funcs imx_pd_connector_funcs = {
 	.dpms = drm_helper_connector_dpms,
 	.fill_modes = drm_helper_probe_single_connector_modes,
 	.detect = imx_pd_connector_detect,
-	.destroy = imx_pd_connector_destroy,
+	.destroy = imx_drm_connector_destroy,
 };
 
 static struct drm_connector_helper_funcs imx_pd_connector_helper_funcs = {
 	.get_modes = imx_pd_connector_get_modes,
 	.best_encoder = imx_pd_connector_best_encoder,
-	.mode_valid = imx_pd_connector_mode_valid,
+	.mode_valid = imx_drm_connector_mode_valid,
 };
 
 static struct drm_encoder_funcs imx_pd_encoder_funcs = {
-	.destroy = imx_pd_encoder_destroy,
+	.destroy = imx_drm_encoder_destroy,
 };
 
 static struct drm_encoder_helper_funcs imx_pd_encoder_helper_funcs = {
@@ -163,51 +164,46 @@
 	.disable = imx_pd_encoder_disable,
 };
 
-static int imx_pd_register(struct imx_parallel_display *imxpd)
+static int imx_pd_register(struct drm_device *drm,
+	struct imx_parallel_display *imxpd)
 {
 	int ret;
 
-	drm_mode_connector_attach_encoder(&imxpd->connector, &imxpd->encoder);
-
-	imxpd->connector.funcs = &imx_pd_connector_funcs;
-	imxpd->encoder.funcs = &imx_pd_encoder_funcs;
-
-	imxpd->encoder.encoder_type = DRM_MODE_ENCODER_NONE;
-	imxpd->connector.connector_type = DRM_MODE_CONNECTOR_VGA;
+	ret = imx_drm_encoder_parse_of(drm, &imxpd->encoder,
+				       imxpd->dev->of_node);
+	if (ret)
+		return ret;
 
 	drm_encoder_helper_add(&imxpd->encoder, &imx_pd_encoder_helper_funcs);
-	ret = imx_drm_add_encoder(&imxpd->encoder, &imxpd->imx_drm_encoder,
-			THIS_MODULE);
-	if (ret) {
-		dev_err(imxpd->dev, "adding encoder failed with %d\n", ret);
-		return ret;
-	}
+	drm_encoder_init(drm, &imxpd->encoder, &imx_pd_encoder_funcs,
+			 DRM_MODE_ENCODER_NONE);
 
 	drm_connector_helper_add(&imxpd->connector,
 			&imx_pd_connector_helper_funcs);
+	drm_connector_init(drm, &imxpd->connector, &imx_pd_connector_funcs,
+			   DRM_MODE_CONNECTOR_VGA);
 
-	ret = imx_drm_add_connector(&imxpd->connector,
-			&imxpd->imx_drm_connector, THIS_MODULE);
-	if (ret) {
-		imx_drm_remove_encoder(imxpd->imx_drm_encoder);
-		dev_err(imxpd->dev, "adding connector failed with %d\n", ret);
-		return ret;
-	}
+	if (imxpd->panel)
+		drm_panel_attach(imxpd->panel, &imxpd->connector);
+
+	drm_mode_connector_attach_encoder(&imxpd->connector, &imxpd->encoder);
 
 	imxpd->connector.encoder = &imxpd->encoder;
 
 	return 0;
 }
 
-static int imx_pd_probe(struct platform_device *pdev)
+static int imx_pd_bind(struct device *dev, struct device *master, void *data)
 {
-	struct device_node *np = pdev->dev.of_node;
+	struct drm_device *drm = data;
+	struct device_node *np = dev->of_node;
+	struct device_node *panel_node;
 	const u8 *edidp;
 	struct imx_parallel_display *imxpd;
 	int ret;
 	const char *fmt;
 
-	imxpd = devm_kzalloc(&pdev->dev, sizeof(*imxpd), GFP_KERNEL);
+	imxpd = devm_kzalloc(dev, sizeof(*imxpd), GFP_KERNEL);
 	if (!imxpd)
 		return -ENOMEM;
 
@@ -225,30 +221,43 @@
 			imxpd->interface_pix_fmt = V4L2_PIX_FMT_BGR666;
 	}
 
-	imxpd->dev = &pdev->dev;
+	panel_node = of_parse_phandle(np, "fsl,panel", 0);
+	if (panel_node)
+		imxpd->panel = of_drm_find_panel(panel_node);
 
-	ret = imx_pd_register(imxpd);
+	imxpd->dev = dev;
+
+	ret = imx_pd_register(drm, imxpd);
 	if (ret)
 		return ret;
 
-	ret = imx_drm_encoder_add_possible_crtcs(imxpd->imx_drm_encoder, np);
-
-	platform_set_drvdata(pdev, imxpd);
+	dev_set_drvdata(dev, imxpd);
 
 	return 0;
 }
 
+static void imx_pd_unbind(struct device *dev, struct device *master,
+	void *data)
+{
+	struct imx_parallel_display *imxpd = dev_get_drvdata(dev);
+
+	imxpd->encoder.funcs->destroy(&imxpd->encoder);
+	imxpd->connector.funcs->destroy(&imxpd->connector);
+}
+
+static const struct component_ops imx_pd_ops = {
+	.bind	= imx_pd_bind,
+	.unbind	= imx_pd_unbind,
+};
+
+static int imx_pd_probe(struct platform_device *pdev)
+{
+	return component_add(&pdev->dev, &imx_pd_ops);
+}
+
 static int imx_pd_remove(struct platform_device *pdev)
 {
-	struct imx_parallel_display *imxpd = platform_get_drvdata(pdev);
-	struct drm_connector *connector = &imxpd->connector;
-	struct drm_encoder *encoder = &imxpd->encoder;
-
-	drm_mode_connector_detach_encoder(connector, encoder);
-
-	imx_drm_remove_connector(imxpd->imx_drm_connector);
-	imx_drm_remove_encoder(imxpd->imx_drm_encoder);
-
+	component_del(&pdev->dev, &imx_pd_ops);
 	return 0;
 }
 
diff --git a/drivers/staging/line6/driver.c b/drivers/staging/line6/driver.c
index 7a6d85e..e7a9d8d 100644
--- a/drivers/staging/line6/driver.c
+++ b/drivers/staging/line6/driver.c
@@ -217,7 +217,7 @@
 	Setup and start timer.
 */
 void line6_start_timer(struct timer_list *timer, unsigned int msecs,
-		       void (*function) (unsigned long), unsigned long data)
+		       void (*function)(unsigned long), unsigned long data)
 {
 	setup_timer(timer, function, data);
 	timer->expires = jiffies + msecs * HZ / 1000;
diff --git a/drivers/staging/line6/driver.h b/drivers/staging/line6/driver.h
index 34ae95e..16e3fc2 100644
--- a/drivers/staging/line6/driver.h
+++ b/drivers/staging/line6/driver.h
@@ -204,7 +204,7 @@
 extern ssize_t line6_set_raw(struct device *dev, struct device_attribute *attr,
 			     const char *buf, size_t count);
 extern void line6_start_timer(struct timer_list *timer, unsigned int msecs,
-			      void (*function) (unsigned long),
+			      void (*function)(unsigned long),
 			      unsigned long data);
 extern int line6_transmit_parameter(struct usb_line6 *line6, int param,
 				    u8 value);
diff --git a/drivers/staging/line6/usbdefs.h b/drivers/staging/line6/usbdefs.h
index 90caddd..eda0456 100644
--- a/drivers/staging/line6/usbdefs.h
+++ b/drivers/staging/line6/usbdefs.h
@@ -91,9 +91,9 @@
 	LINE6_BITS_PODXTALL = LINE6_BIT_PODXT | LINE6_BIT_PODXTLIVE |
 			      LINE6_BIT_PODXTPRO,
 	LINE6_BITS_PODX3ALL = LINE6_BIT_PODX3 | LINE6_BIT_PODX3LIVE,
-	LINE6_BITS_PODHDALL = 	LINE6_BIT_PODHD300 |
-				LINE6_BIT_PODHD400 |
-				LINE6_BIT_PODHD500,
+	LINE6_BITS_PODHDALL = LINE6_BIT_PODHD300 |
+			      LINE6_BIT_PODHD400 |
+			      LINE6_BIT_PODHD500,
 	LINE6_BITS_BASSPODXTALL	= LINE6_BIT_BASSPODXT |
 				  LINE6_BIT_BASSPODXTLIVE |
 				  LINE6_BIT_BASSPODXTPRO
diff --git a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c
index 644a000..0727998 100644
--- a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c
+++ b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c
@@ -41,7 +41,7 @@
 #include "o2iblnd.h"
 #include <asm/div64.h>
 
-lnd_t the_o2iblnd = {
+static lnd_t the_o2iblnd = {
 	.lnd_type       = O2IBLND,
 	.lnd_startup    = kiblnd_startup,
 	.lnd_shutdown   = kiblnd_shutdown,
@@ -53,8 +53,8 @@
 
 kib_data_t	      kiblnd_data;
 
-__u32
-kiblnd_cksum (void *ptr, int nob)
+static __u32
+kiblnd_cksum(void *ptr, int nob)
 {
 	char  *c  = ptr;
 	__u32  sum = 0;
@@ -429,8 +429,8 @@
 	kiblnd_peer_decref(peer);
 }
 
-int
-kiblnd_get_peer_info (lnet_ni_t *ni, int index,
+static int
+kiblnd_get_peer_info(lnet_ni_t *ni, int index,
 		      lnet_nid_t *nidp, int *count)
 {
 	kib_peer_t	    *peer;
@@ -468,8 +468,8 @@
 	return -ENOENT;
 }
 
-void
-kiblnd_del_peer_locked (kib_peer_t *peer)
+static void
+kiblnd_del_peer_locked(kib_peer_t *peer)
 {
 	struct list_head	   *ctmp;
 	struct list_head	   *cnxt;
@@ -489,8 +489,8 @@
 	 * last ref on it. */
 }
 
-int
-kiblnd_del_peer (lnet_ni_t *ni, lnet_nid_t nid)
+static int
+kiblnd_del_peer(lnet_ni_t *ni, lnet_nid_t nid)
 {
 	LIST_HEAD	 (zombies);
 	struct list_head	    *ptmp;
@@ -543,8 +543,8 @@
 	return rc;
 }
 
-kib_conn_t *
-kiblnd_get_conn_by_idx (lnet_ni_t *ni, int index)
+static kib_conn_t *
+kiblnd_get_conn_by_idx(lnet_ni_t *ni, int index)
 {
 	kib_peer_t	    *peer;
 	struct list_head	    *ptmp;
@@ -584,16 +584,16 @@
 	return NULL;
 }
 
-void
-kiblnd_debug_rx (kib_rx_t *rx)
+static void
+kiblnd_debug_rx(kib_rx_t *rx)
 {
 	CDEBUG(D_CONSOLE, "      %p status %d msg_type %x cred %d\n",
 	       rx, rx->rx_status, rx->rx_msg->ibm_type,
 	       rx->rx_msg->ibm_credits);
 }
 
-void
-kiblnd_debug_tx (kib_tx_t *tx)
+static void
+kiblnd_debug_tx(kib_tx_t *tx)
 {
 	CDEBUG(D_CONSOLE, "      %p snd %d q %d w %d rc %d dl %lx "
 	       "cookie "LPX64" msg %s%s type %x cred %d\n",
@@ -604,8 +604,8 @@
 	       tx->tx_msg->ibm_type, tx->tx_msg->ibm_credits);
 }
 
-void
-kiblnd_debug_conn (kib_conn_t *conn)
+static void
+kiblnd_debug_conn(kib_conn_t *conn)
 {
 	struct list_head	*tmp;
 	int		i;
@@ -1039,8 +1039,8 @@
 	return count;
 }
 
-int
-kiblnd_close_matching_conns (lnet_ni_t *ni, lnet_nid_t nid)
+static int
+kiblnd_close_matching_conns(lnet_ni_t *ni, lnet_nid_t nid)
 {
 	kib_peer_t	     *peer;
 	struct list_head	     *ptmp;
@@ -1440,7 +1440,7 @@
 	return mr;
 }
 
-void
+static void
 kiblnd_destroy_fmr_pool(kib_fmr_pool_t *pool)
 {
 	LASSERT (pool->fpo_map_count == 0);
@@ -1454,7 +1454,7 @@
 	LIBCFS_FREE(pool, sizeof(kib_fmr_pool_t));
 }
 
-void
+static void
 kiblnd_destroy_fmr_pool_list(struct list_head *head)
 {
 	kib_fmr_pool_t *pool;
@@ -1480,7 +1480,7 @@
 	return max(IBLND_FMR_POOL_FLUSH, size);
 }
 
-int
+static int
 kiblnd_create_fmr_pool(kib_fmr_poolset_t *fps, kib_fmr_pool_t **pp_fpo)
 {
 	/* FMR pool for RDMA */
@@ -1719,7 +1719,7 @@
 	pool->po_size     = size;
 }
 
-void
+static void
 kiblnd_destroy_pool_list(struct list_head *head)
 {
 	kib_pool_t *pool;
@@ -2192,7 +2192,7 @@
 	tx->tx_cookie = tps->tps_next_tx_cookie ++;
 }
 
-void
+static void
 kiblnd_net_fini_pools(kib_net_t *net)
 {
 	int	i;
@@ -2234,7 +2234,7 @@
 	}
 }
 
-int
+static int
 kiblnd_net_init_pools(kib_net_t *net, __u32 *cpts, int ncpts)
 {
 	unsigned long	flags;
@@ -2408,7 +2408,7 @@
 	return -EINVAL;
 }
 
-void
+static void
 kiblnd_hdev_cleanup_mrs(kib_hca_dev_t *hdev)
 {
 	int     i;
@@ -2442,7 +2442,7 @@
 	LIBCFS_FREE(hdev, sizeof(*hdev));
 }
 
-int
+static int
 kiblnd_hdev_setup_mrs(kib_hca_dev_t *hdev)
 {
 	struct ib_mr *mr;
@@ -2746,7 +2746,7 @@
 	LIBCFS_FREE(dev, sizeof(*dev));
 }
 
-kib_dev_t *
+static kib_dev_t *
 kiblnd_create_dev(char *ifname)
 {
 	struct net_device *netdev;
@@ -2800,7 +2800,7 @@
 	return dev;
 }
 
-void
+static void
 kiblnd_base_shutdown(void)
 {
 	struct kib_sched_info	*sched;
@@ -2940,7 +2940,7 @@
 	return;
 }
 
-int
+static int
 kiblnd_base_startup(void)
 {
 	struct kib_sched_info	*sched;
@@ -3030,7 +3030,7 @@
 	return -ENETDOWN;
 }
 
-int
+static int
 kiblnd_start_schedulers(struct kib_sched_info *sched)
 {
 	int	rc = 0;
@@ -3071,7 +3071,7 @@
 	return rc;
 }
 
-int
+static int
 kiblnd_dev_start_threads(kib_dev_t *dev, int newdev, __u32 *cpts, int ncpts)
 {
 	int	cpt;
@@ -3097,7 +3097,7 @@
 	return 0;
 }
 
-kib_dev_t *
+static kib_dev_t *
 kiblnd_dev_search(char *ifname)
 {
 	kib_dev_t	*alias = NULL;
@@ -3226,13 +3226,13 @@
 	return -ENETDOWN;
 }
 
-void __exit
+static void __exit
 kiblnd_module_fini (void)
 {
 	lnet_unregister_lnd(&the_o2iblnd);
 }
 
-int __init
+static int __init
 kiblnd_module_init (void)
 {
 	int    rc;
diff --git a/drivers/staging/lustre/lustre/include/cl_object.h b/drivers/staging/lustre/lustre/include/cl_object.h
index 4d692dc..76e1b68 100644
--- a/drivers/staging/lustre/lustre/include/cl_object.h
+++ b/drivers/staging/lustre/lustre/include/cl_object.h
@@ -2392,7 +2392,11 @@
 	/**
 	 * file is released, restore has to to be triggered by vvp layer
 	 */
-			     ci_restore_needed:1;
+			     ci_restore_needed:1,
+	/**
+	 * O_NOATIME
+	 */
+			     ci_noatime:1;
 	/**
 	 * Number of pages owned by this IO. For invariant checking.
 	 */
diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h
index 4183a35..5f5b0ba 100644
--- a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h
+++ b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h
@@ -1305,6 +1305,7 @@
 #define OBD_CONNECT_SHORTIO     0x2000000000000ULL/* short io */
 #define OBD_CONNECT_PINGLESS	0x4000000000000ULL/* pings not required */
 #define OBD_CONNECT_FLOCK_DEAD	0x8000000000000ULL/* flock deadlock detection */
+#define OBD_CONNECT_DISP_STRIPE 0x10000000000000ULL/*create stripe disposition*/
 
 /* XXX README XXX:
  * Please DO NOT add flag values here before first ensuring that this same
@@ -1344,7 +1345,9 @@
 				OBD_CONNECT_LIGHTWEIGHT | OBD_CONNECT_UMASK | \
 				OBD_CONNECT_LVB_TYPE | OBD_CONNECT_LAYOUTLOCK |\
 				OBD_CONNECT_PINGLESS | OBD_CONNECT_MAX_EASIZE |\
-				OBD_CONNECT_FLOCK_DEAD)
+				OBD_CONNECT_FLOCK_DEAD | \
+				OBD_CONNECT_DISP_STRIPE)
+
 #define OST_CONNECT_SUPPORTED  (OBD_CONNECT_SRVLOCK | OBD_CONNECT_GRANT | \
 				OBD_CONNECT_REQPORTAL | OBD_CONNECT_VERSION | \
 				OBD_CONNECT_TRUNCLOCK | OBD_CONNECT_INDEX | \
@@ -2109,19 +2112,32 @@
 #define DISP_LOOKUP_POS      0x00000008
 #define DISP_OPEN_CREATE     0x00000010
 #define DISP_OPEN_OPEN       0x00000020
-#define DISP_ENQ_COMPLETE    0x00400000
+#define DISP_ENQ_COMPLETE    0x00400000		/* obsolete and unused */
 #define DISP_ENQ_OPEN_REF    0x00800000
 #define DISP_ENQ_CREATE_REF  0x01000000
 #define DISP_OPEN_LOCK       0x02000000
 #define DISP_OPEN_LEASE      0x04000000
+#define DISP_OPEN_STRIPE     0x08000000
 
 /* INODE LOCK PARTS */
-#define MDS_INODELOCK_LOOKUP 0x000001       /* dentry, mode, owner, group */
-#define MDS_INODELOCK_UPDATE 0x000002       /* size, links, timestamps */
-#define MDS_INODELOCK_OPEN   0x000004       /* For opened files */
-#define MDS_INODELOCK_LAYOUT 0x000008       /* for layout */
-#define MDS_INODELOCK_PERM   0x000010       /* for permission */
-#define MDS_INODELOCK_XATTR  0x000020       /* extended attributes */
+#define MDS_INODELOCK_LOOKUP 0x000001	/* For namespace, dentry etc, and also
+					 * was used to protect permission (mode,
+					 * owner, group etc) before 2.4. */
+#define MDS_INODELOCK_UPDATE 0x000002	/* size, links, timestamps */
+#define MDS_INODELOCK_OPEN   0x000004	/* For opened files */
+#define MDS_INODELOCK_LAYOUT 0x000008	/* for layout */
+
+/* The PERM bit is added int 2.4, and it is used to protect permission(mode,
+ * owner, group, acl etc), so to separate the permission from LOOKUP lock.
+ * Because for remote directories(in DNE), these locks will be granted by
+ * different MDTs(different ldlm namespace).
+ *
+ * For local directory, MDT will always grant UPDATE_LOCK|PERM_LOCK together.
+ * For Remote directory, the master MDT, where the remote directory is, will
+ * grant UPDATE_LOCK|PERM_LOCK, and the remote MDT, where the name entry is,
+ * will grant LOOKUP_LOCK. */
+#define MDS_INODELOCK_PERM   0x000010
+#define MDS_INODELOCK_XATTR  0x000020	/* extended attributes */
 
 #define MDS_INODELOCK_MAXSHIFT 5
 /* This FULL lock is useful to take on unlink sort of operations */
diff --git a/drivers/staging/lustre/lustre/include/lustre_export.h b/drivers/staging/lustre/lustre/include/lustre_export.h
index 2feb38b..6f7f48c 100644
--- a/drivers/staging/lustre/lustre/include/lustre_export.h
+++ b/drivers/staging/lustre/lustre/include/lustre_export.h
@@ -380,6 +380,23 @@
 		return false;
 }
 
+static inline __u64 exp_connect_ibits(struct obd_export *exp)
+{
+	struct obd_connect_data *ocd;
+
+	ocd = &exp->exp_connect_data;
+	return ocd->ocd_ibits_known;
+}
+
+static inline bool imp_connect_disp_stripe(struct obd_import *imp)
+{
+	struct obd_connect_data *ocd;
+
+	LASSERT(imp != NULL);
+	ocd = &imp->imp_connect_data;
+	return ocd->ocd_connect_flags & OBD_CONNECT_DISP_STRIPE;
+}
+
 extern struct obd_export *class_conn2export(struct lustre_handle *conn);
 extern struct obd_device *class_conn2obd(struct lustre_handle *conn);
 
diff --git a/drivers/staging/lustre/lustre/include/lustre_import.h b/drivers/staging/lustre/lustre/include/lustre_import.h
index 67259eb..e9833ae 100644
--- a/drivers/staging/lustre/lustre/include/lustre_import.h
+++ b/drivers/staging/lustre/lustre/include/lustre_import.h
@@ -180,6 +180,17 @@
 	struct list_head		imp_delayed_list;
 	/** @} */
 
+	/**
+	 * List of requests that are retained for committed open replay. Once
+	 * open is committed, open replay request will be moved from the
+	 * imp_replay_list into the imp_committed_list.
+	 * The imp_replay_cursor is for accelerating searching during replay.
+	 * @{
+	 */
+	struct list_head		imp_committed_list;
+	struct list_head	       *imp_replay_cursor;
+	/** @} */
+
 	/** obd device for this import */
 	struct obd_device	*imp_obd;
 
diff --git a/drivers/staging/lustre/lustre/include/lustre_net.h b/drivers/staging/lustre/lustre/include/lustre_net.h
index d8d0880..11382ab 100644
--- a/drivers/staging/lustre/lustre/include/lustre_net.h
+++ b/drivers/staging/lustre/lustre/include/lustre_net.h
@@ -2621,6 +2621,8 @@
  * request queues, request management, etc.
  * @{
  */
+void ptlrpc_request_committed(struct ptlrpc_request *req, int force);
+
 void ptlrpc_init_client(int req_portal, int rep_portal, char *name,
 			struct ptlrpc_client *);
 void ptlrpc_cleanup_client(struct obd_import *imp);
diff --git a/drivers/staging/lustre/lustre/include/obd.h b/drivers/staging/lustre/lustre/include/obd.h
index c3470ce..1b38695 100644
--- a/drivers/staging/lustre/lustre/include/obd.h
+++ b/drivers/staging/lustre/lustre/include/obd.h
@@ -1323,7 +1323,8 @@
 	struct obd_client_handle *mod_och;
 	struct ptlrpc_request    *mod_open_req;
 	struct ptlrpc_request    *mod_close_req;
-	atomic_t	      mod_refcount;
+	atomic_t		  mod_refcount;
+	bool			  mod_is_create;
 };
 
 struct lookup_intent;
@@ -1392,7 +1393,7 @@
 
 	int (*m_set_open_replay_data)(struct obd_export *,
 				      struct obd_client_handle *,
-				      struct ptlrpc_request *);
+				      struct lookup_intent *);
 	int (*m_clear_open_replay_data)(struct obd_export *,
 					struct obd_client_handle *);
 	int (*m_set_lock_data)(struct obd_export *, __u64 *, void *, __u64 *);
diff --git a/drivers/staging/lustre/lustre/include/obd_class.h b/drivers/staging/lustre/lustre/include/obd_class.h
index 1c2ba19..0a18820 100644
--- a/drivers/staging/lustre/lustre/include/obd_class.h
+++ b/drivers/staging/lustre/lustre/include/obd_class.h
@@ -2001,11 +2001,11 @@
 
 static inline int md_set_open_replay_data(struct obd_export *exp,
 					  struct obd_client_handle *och,
-					  struct ptlrpc_request *open_req)
+					  struct lookup_intent *it)
 {
 	EXP_CHECK_MD_OP(exp, set_open_replay_data);
 	EXP_MD_COUNTER_INCREMENT(exp, set_open_replay_data);
-	return MDP(exp->exp_obd, set_open_replay_data)(exp, och, open_req);
+	return MDP(exp->exp_obd, set_open_replay_data)(exp, och, it);
 }
 
 static inline int md_clear_open_replay_data(struct obd_export *exp,
diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c b/drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c
index 3ed020e..d87048d 100644
--- a/drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c
+++ b/drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c
@@ -228,6 +228,7 @@
 
 			lock_res_and_lock(lock);
 			LASSERT(lock->l_lvb_data == NULL);
+			lock->l_lvb_type = LVB_T_LAYOUT;
 			lock->l_lvb_data = lvb_data;
 			lock->l_lvb_len = lvb_len;
 			unlock_res_and_lock(lock);
diff --git a/drivers/staging/lustre/lustre/libcfs/linux/linux-cpu.c b/drivers/staging/lustre/lustre/libcfs/linux/linux-cpu.c
index 58bb256..77b1ef6 100644
--- a/drivers/staging/lustre/lustre/libcfs/linux/linux-cpu.c
+++ b/drivers/staging/lustre/lustre/libcfs/linux/linux-cpu.c
@@ -952,6 +952,7 @@
 cfs_cpu_notify(struct notifier_block *self, unsigned long action, void *hcpu)
 {
 	unsigned int  cpu = (unsigned long)hcpu;
+	bool	     warn;
 
 	switch (action) {
 	case CPU_DEAD:
@@ -962,9 +963,21 @@
 		cpt_data.cpt_version++;
 		spin_unlock(&cpt_data.cpt_lock);
 	default:
-		CWARN("Lustre: can't support CPU hotplug well now, "
-		      "performance and stability could be impacted"
-		      "[CPU %u notify: %lx]\n", cpu, action);
+		if (action != CPU_DEAD && action != CPU_DEAD_FROZEN) {
+			CDEBUG(D_INFO, "CPU changed [cpu %u action %lx]\n",
+			       cpu, action);
+			break;
+		}
+
+		down(&cpt_data.cpt_mutex);
+		/* if all HTs in a core are offline, it may break affinity */
+		cfs_cpu_ht_siblings(cpu, cpt_data.cpt_cpumask);
+		warn = any_online_cpu(*cpt_data.cpt_cpumask) >= nr_cpu_ids;
+		up(&cpt_data.cpt_mutex);
+		CDEBUG(warn ? D_WARNING : D_INFO,
+		       "Lustre: can't support CPU plug-out well now, "
+		       "performance and stability could be impacted "
+		       "[CPU %u action: %lx]\n", cpu, action);
 	}
 
 	return NOTIFY_OK;
diff --git a/drivers/staging/lustre/lustre/libcfs/workitem.c b/drivers/staging/lustre/lustre/libcfs/workitem.c
index 1a55c81..53813fc 100644
--- a/drivers/staging/lustre/lustre/libcfs/workitem.c
+++ b/drivers/staging/lustre/lustre/libcfs/workitem.c
@@ -389,11 +389,11 @@
 		spin_unlock(&cfs_wi_data.wi_glock);
 
 		if (sched->ws_cptab != NULL && sched->ws_cpt >= 0) {
-			snprintf(name, sizeof(name), "%s_%02d_%02d",
+			snprintf(name, sizeof(name), "%s_%02d_%02u",
 				 sched->ws_name, sched->ws_cpt,
 				 sched->ws_nthreads);
 		} else {
-			snprintf(name, sizeof(name), "%s_%02d",
+			snprintf(name, sizeof(name), "%s_%02u",
 				 sched->ws_name, sched->ws_nthreads);
 		}
 
diff --git a/drivers/staging/lustre/lustre/llite/dcache.c b/drivers/staging/lustre/lustre/llite/dcache.c
index 3907c87..f971a54 100644
--- a/drivers/staging/lustre/lustre/llite/dcache.c
+++ b/drivers/staging/lustre/lustre/llite/dcache.c
@@ -241,9 +241,6 @@
 		 ptlrpc_req_finished(it->d.lustre.it_data); /* ll_file_open */
 	if (it_disposition(it, DISP_ENQ_CREATE_REF)) /* create rec */
 		ptlrpc_req_finished(it->d.lustre.it_data);
-	if (it_disposition(it, DISP_ENQ_COMPLETE)) /* saved req from revalidate
-						    * to lookup */
-		ptlrpc_req_finished(it->d.lustre.it_data);
 
 	it->d.lustre.it_disposition = 0;
 	it->d.lustre.it_data = NULL;
@@ -328,262 +325,32 @@
 
 }
 
-int ll_revalidate_it(struct dentry *de, int lookup_flags,
-		     struct lookup_intent *it)
+static int ll_revalidate_dentry(struct dentry *dentry,
+				unsigned int lookup_flags)
 {
-	struct md_op_data *op_data;
-	struct ptlrpc_request *req = NULL;
-	struct lookup_intent lookup_it = { .it_op = IT_LOOKUP };
-	struct obd_export *exp;
-	struct inode *parent = de->d_parent->d_inode;
-	int rc;
+	struct inode *dir = dentry->d_parent->d_inode;
 
-	CDEBUG(D_VFSTRACE, "VFS Op:name=%s,intent=%s\n", de->d_name.name,
-	       LL_IT2STR(it));
+	/*
+	 * if open&create is set, talk to MDS to make sure file is created if
+	 * necessary, because we can't do this in ->open() later since that's
+	 * called on an inode. return 0 here to let lookup to handle this.
+	 */
+	if ((lookup_flags & (LOOKUP_OPEN | LOOKUP_CREATE)) ==
+	    (LOOKUP_OPEN | LOOKUP_CREATE))
+		return 0;
 
-	LASSERT(de != de->d_sb->s_root);
-
-	if (de->d_inode == NULL) {
-		__u64 ibits;
-
-		/* We can only use negative dentries if this is stat or lookup,
-		   for opens and stuff we do need to query server. */
-		/* If there is IT_CREAT in intent op set, then we must throw
-		   away this negative dentry and actually do the request to
-		   kernel to create whatever needs to be created (if possible)*/
-		if (it && (it->it_op & IT_CREAT))
-			return 0;
-
-		if (d_lustre_invalid(de))
-			return 0;
-
-		ibits = MDS_INODELOCK_UPDATE;
-		rc = ll_have_md_lock(parent, &ibits, LCK_MINMODE);
-		GOTO(out_sa, rc);
-	}
-
-	/* Never execute intents for mount points.
-	 * Attributes will be fixed up in ll_inode_revalidate_it */
-	if (d_mountpoint(de))
-		GOTO(out_sa, rc = 1);
-
-	exp = ll_i2mdexp(de->d_inode);
-
-	OBD_FAIL_TIMEOUT(OBD_FAIL_MDC_REVALIDATE_PAUSE, 5);
-	ll_frob_intent(&it, &lookup_it);
-	LASSERT(it);
-
-	if (it->it_op == IT_LOOKUP && !d_lustre_invalid(de))
+	if (lookup_flags & (LOOKUP_PARENT | LOOKUP_OPEN | LOOKUP_CREATE))
 		return 1;
 
-	if (it->it_op == IT_OPEN) {
-		struct inode *inode = de->d_inode;
-		struct ll_inode_info *lli = ll_i2info(inode);
-		struct obd_client_handle **och_p;
-		__u64 ibits;
+	if (d_need_statahead(dir, dentry) <= 0)
+		return 1;
 
-		/*
-		 * We used to check for MDS_INODELOCK_OPEN here, but in fact
-		 * just having LOOKUP lock is enough to justify inode is the
-		 * same. And if inode is the same and we have suitable
-		 * openhandle, then there is no point in doing another OPEN RPC
-		 * just to throw away newly received openhandle.  There are no
-		 * security implications too, if file owner or access mode is
-		 * change, LOOKUP lock is revoked.
-		 */
+	if (lookup_flags & LOOKUP_RCU)
+		return -ECHILD;
 
-
-		if (it->it_flags & FMODE_WRITE)
-			och_p = &lli->lli_mds_write_och;
-		else if (it->it_flags & FMODE_EXEC)
-			och_p = &lli->lli_mds_exec_och;
-		else
-			och_p = &lli->lli_mds_read_och;
-
-		/* Check for the proper lock. */
-		ibits = MDS_INODELOCK_LOOKUP;
-		if (!ll_have_md_lock(inode, &ibits, LCK_MINMODE))
-			goto do_lock;
-		mutex_lock(&lli->lli_och_mutex);
-		if (*och_p) { /* Everything is open already, do nothing */
-			/* Originally it was idea to do not let them steal our
-			 * open handle from under us by (*och_usecount)++ here.
-			 * But in case we have the handle, but we cannot use it
-			 * due to later checks (e.g. O_CREAT|O_EXCL flags set),
-			 * nobody would decrement counter increased here. So we
-			 * just hope the lock won't be invalidated in between.
-			 * But if it would be, we'll reopen the open request to
-			 * MDS later during file open path.
-			 */
-			mutex_unlock(&lli->lli_och_mutex);
-			return 1;
-		}
-		mutex_unlock(&lli->lli_och_mutex);
-	}
-
-	if (it->it_op == IT_GETATTR) {
-		rc = ll_statahead_enter(parent, &de, 0);
-		if (rc == 1)
-			goto mark;
-		else if (rc != -EAGAIN && rc != 0)
-			GOTO(out, rc = 0);
-	}
-
-do_lock:
-	op_data = ll_prep_md_op_data(NULL, parent, de->d_inode,
-				     de->d_name.name, de->d_name.len,
-				     0, LUSTRE_OPC_ANY, NULL);
-	if (IS_ERR(op_data))
-		return PTR_ERR(op_data);
-
-	if (!IS_POSIXACL(parent) || !exp_connect_umask(exp))
-		it->it_create_mode &= ~current_umask();
-	it->it_create_mode |= M_CHECK_STALE;
-	rc = md_intent_lock(exp, op_data, NULL, 0, it,
-			    lookup_flags,
-			    &req, ll_md_blocking_ast, 0);
-	it->it_create_mode &= ~M_CHECK_STALE;
-	ll_finish_md_op_data(op_data);
-
-	/* If req is NULL, then md_intent_lock only tried to do a lock match;
-	 * if all was well, it will return 1 if it found locks, 0 otherwise. */
-	if (req == NULL && rc >= 0) {
-		if (!rc)
-			goto do_lookup;
-		GOTO(out, rc);
-	}
-
-	if (rc < 0) {
-		if (rc != -ESTALE) {
-			CDEBUG(D_INFO, "ll_intent_lock: rc %d : it->it_status "
-			       "%d\n", rc, it->d.lustre.it_status);
-		}
-		GOTO(out, rc = 0);
-	}
-
-revalidate_finish:
-	rc = ll_revalidate_it_finish(req, it, de);
-	if (rc != 0) {
-		if (rc != -ESTALE && rc != -ENOENT)
-			ll_intent_release(it);
-		GOTO(out, rc = 0);
-	}
-
-	if ((it->it_op & IT_OPEN) && de->d_inode &&
-	    !S_ISREG(de->d_inode->i_mode) &&
-	    !S_ISDIR(de->d_inode->i_mode)) {
-		ll_release_openhandle(de, it);
-	}
-	rc = 1;
-
-out:
-	/* We do not free request as it may be reused during following lookup
-	 * (see comment in mdc/mdc_locks.c::mdc_intent_lock()), request will
-	 * be freed in ll_lookup_it or in ll_intent_release. But if
-	 * request was not completed, we need to free it. (bug 5154, 9903) */
-	if (req != NULL && !it_disposition(it, DISP_ENQ_COMPLETE))
-		ptlrpc_req_finished(req);
-	if (rc == 0) {
-		/* mdt may grant layout lock for the newly created file, so
-		 * release the lock to avoid leaking */
-		ll_intent_drop_lock(it);
-		ll_invalidate_aliases(de->d_inode);
-	} else {
-		__u64 bits = 0;
-		__u64 matched_bits = 0;
-
-		CDEBUG(D_DENTRY, "revalidated dentry %.*s (%p) parent %p "
-		       "inode %p refc %d\n", de->d_name.len,
-		       de->d_name.name, de, de->d_parent, de->d_inode,
-		       d_count(de));
-
-		ll_set_lock_data(exp, de->d_inode, it, &bits);
-
-		/* Note: We have to match both LOOKUP and PERM lock
-		 * here to make sure the dentry is valid and no one
-		 * changing the permission.
-		 * But if the client connects < 2.4 server, which will
-		 * only grant LOOKUP lock, so we can only Match LOOKUP
-		 * lock for old server */
-		if (exp_connect_flags(ll_i2mdexp(de->d_inode)) &&
-							OBD_CONNECT_LVB_TYPE)
-			matched_bits =
-				MDS_INODELOCK_LOOKUP | MDS_INODELOCK_PERM;
-		else
-			matched_bits = MDS_INODELOCK_LOOKUP;
-
-		if (((bits & matched_bits) == matched_bits) &&
-		    d_lustre_invalid(de))
-			d_lustre_revalidate(de);
-		ll_lookup_finish_locks(it, de);
-	}
-
-mark:
-	if (it != NULL && it->it_op == IT_GETATTR && rc > 0)
-		ll_statahead_mark(parent, de);
-	return rc;
-
-	/*
-	 * This part is here to combat evil-evil race in real_lookup on 2.6
-	 * kernels.  The race details are: We enter do_lookup() looking for some
-	 * name, there is nothing in dcache for this name yet and d_lookup()
-	 * returns NULL.  We proceed to real_lookup(), and while we do this,
-	 * another process does open on the same file we looking up (most simple
-	 * reproducer), open succeeds and the dentry is added. Now back to
-	 * us. In real_lookup() we do d_lookup() again and suddenly find the
-	 * dentry, so we call d_revalidate on it, but there is no lock, so
-	 * without this code we would return 0, but unpatched real_lookup just
-	 * returns -ENOENT in such a case instead of retrying the lookup. Once
-	 * this is dealt with in real_lookup(), all of this ugly mess can go and
-	 * we can just check locks in ->d_revalidate without doing any RPCs
-	 * ever.
-	 */
-do_lookup:
-	if (it != &lookup_it) {
-		/* MDS_INODELOCK_UPDATE needed for IT_GETATTR case. */
-		if (it->it_op == IT_GETATTR)
-			lookup_it.it_op = IT_GETATTR;
-		ll_lookup_finish_locks(it, de);
-		it = &lookup_it;
-	}
-
-	/* Do real lookup here. */
-	op_data = ll_prep_md_op_data(NULL, parent, NULL, de->d_name.name,
-				     de->d_name.len, 0, (it->it_op & IT_CREAT ?
-							 LUSTRE_OPC_CREATE :
-							 LUSTRE_OPC_ANY), NULL);
-	if (IS_ERR(op_data))
-		return PTR_ERR(op_data);
-
-	rc = md_intent_lock(exp, op_data, NULL, 0,  it, 0, &req,
-			    ll_md_blocking_ast, 0);
-	if (rc >= 0) {
-		struct mdt_body *mdt_body;
-		struct lu_fid fid = {.f_seq = 0, .f_oid = 0, .f_ver = 0};
-		mdt_body = req_capsule_server_get(&req->rq_pill, &RMF_MDT_BODY);
-
-		if (de->d_inode)
-			fid = *ll_inode2fid(de->d_inode);
-
-		/* see if we got same inode, if not - return error */
-		if (lu_fid_eq(&fid, &mdt_body->fid1)) {
-			ll_finish_md_op_data(op_data);
-			op_data = NULL;
-			goto revalidate_finish;
-		}
-		ll_intent_release(it);
-	}
-	ll_finish_md_op_data(op_data);
-	GOTO(out, rc = 0);
-
-out_sa:
-	/*
-	 * For rc == 1 case, should not return directly to prevent losing
-	 * statahead windows; for rc == 0 case, the "lookup" will be done later.
-	 */
-	if (it != NULL && it->it_op == IT_GETATTR && rc == 1)
-		ll_statahead_enter(parent, &de, 1);
-	goto mark;
+	do_statahead_enter(dir, &dentry, dentry->d_inode == NULL);
+	ll_statahead_mark(dir, dentry);
+	return 1;
 }
 
 /*
@@ -591,24 +358,13 @@
  */
 int ll_revalidate_nd(struct dentry *dentry, unsigned int flags)
 {
-	struct inode *parent = dentry->d_parent->d_inode;
-	int unplug = 0;
+	int rc;
 
-	CDEBUG(D_VFSTRACE, "VFS Op:name=%s,flags=%u\n",
+	CDEBUG(D_VFSTRACE, "VFS Op:name=%s, flags=%u\n",
 	       dentry->d_name.name, flags);
 
-	if (!(flags & (LOOKUP_PARENT|LOOKUP_OPEN|LOOKUP_CREATE)) &&
-	    ll_need_statahead(parent, dentry) > 0) {
-		if (flags & LOOKUP_RCU)
-			return -ECHILD;
-
-		if (dentry->d_inode == NULL)
-			unplug = 1;
-		do_statahead_enter(parent, &dentry, unplug);
-		ll_statahead_mark(parent, dentry);
-	}
-
-	return 1;
+	rc = ll_revalidate_dentry(dentry, flags);
+	return rc;
 }
 
 
diff --git a/drivers/staging/lustre/lustre/llite/dir.c b/drivers/staging/lustre/lustre/llite/dir.c
index fd0dd20e..7fbc18e 100644
--- a/drivers/staging/lustre/lustre/llite/dir.c
+++ b/drivers/staging/lustre/lustre/llite/dir.c
@@ -362,7 +362,7 @@
 		struct ptlrpc_request *request;
 		struct md_op_data *op_data;
 
-		op_data = ll_prep_md_op_data(NULL, dir, NULL, NULL, 0, 0,
+		op_data = ll_prep_md_op_data(NULL, dir, dir, NULL, 0, 0,
 		LUSTRE_OPC_ANY, NULL);
 		if (IS_ERR(op_data))
 			return (void *)op_data;
diff --git a/drivers/staging/lustre/lustre/llite/file.c b/drivers/staging/lustre/lustre/llite/file.c
index 4c28f39..70b48ab 100644
--- a/drivers/staging/lustre/lustre/llite/file.c
+++ b/drivers/staging/lustre/lustre/llite/file.c
@@ -205,7 +205,7 @@
 	return rc;
 }
 
-int ll_md_real_close(struct inode *inode, int flags)
+int ll_md_real_close(struct inode *inode, fmode_t fmode)
 {
 	struct ll_inode_info *lli = ll_i2info(inode);
 	struct obd_client_handle **och_p;
@@ -213,30 +213,33 @@
 	__u64 *och_usecount;
 	int rc = 0;
 
-	if (flags & FMODE_WRITE) {
+	if (fmode & FMODE_WRITE) {
 		och_p = &lli->lli_mds_write_och;
 		och_usecount = &lli->lli_open_fd_write_count;
-	} else if (flags & FMODE_EXEC) {
+	} else if (fmode & FMODE_EXEC) {
 		och_p = &lli->lli_mds_exec_och;
 		och_usecount = &lli->lli_open_fd_exec_count;
 	} else {
-		LASSERT(flags & FMODE_READ);
+		LASSERT(fmode & FMODE_READ);
 		och_p = &lli->lli_mds_read_och;
 		och_usecount = &lli->lli_open_fd_read_count;
 	}
 
 	mutex_lock(&lli->lli_och_mutex);
-	if (*och_usecount) { /* There are still users of this handle, so
-				skip freeing it. */
+	if (*och_usecount > 0) {
+		/* There are still users of this handle, so skip
+		 * freeing it. */
 		mutex_unlock(&lli->lli_och_mutex);
 		return 0;
 	}
+
 	och=*och_p;
 	*och_p = NULL;
 	mutex_unlock(&lli->lli_och_mutex);
 
-	if (och) { /* There might be a race and somebody have freed this och
-		      already */
+	if (och != NULL) {
+		/* There might be a race and this handle may already
+		   be closed. */
 		rc = ll_close_inode_openhandle(ll_i2sbi(inode)->ll_md_exp,
 					       inode, och, NULL);
 	}
@@ -443,8 +446,7 @@
 				 itp, NULL);
 
 out:
-	ptlrpc_req_finished(itp->d.lustre.it_data);
-	it_clear_disposition(itp, DISP_ENQ_COMPLETE);
+	ptlrpc_req_finished(req);
 	ll_intent_drop_lock(itp);
 
 	return rc;
@@ -477,7 +479,7 @@
 	och->och_magic = OBD_CLIENT_HANDLE_MAGIC;
 	och->och_flags = it->it_flags;
 
-	return md_set_open_replay_data(md_exp, och, req);
+	return md_set_open_replay_data(md_exp, och, it);
 }
 
 int ll_local_open(struct file *file, struct lookup_intent *it,
@@ -812,10 +814,7 @@
 	 * doesn't deal with openhandle, so normal openhandle will be leaked. */
 				LDLM_FL_NO_LRU | LDLM_FL_EXCL);
 	ll_finish_md_op_data(op_data);
-	if (req != NULL) {
-		ptlrpc_req_finished(req);
-		it_clear_disposition(&it, DISP_ENQ_COMPLETE);
-	}
+	ptlrpc_req_finished(req);
 	if (rc < 0)
 		GOTO(out_release_it, rc);
 
@@ -1032,6 +1031,33 @@
 	return rc;
 }
 
+static bool file_is_noatime(const struct file *file)
+{
+	const struct vfsmount *mnt = file->f_path.mnt;
+	const struct inode *inode = file->f_path.dentry->d_inode;
+
+	/* Adapted from file_accessed() and touch_atime().*/
+	if (file->f_flags & O_NOATIME)
+		return true;
+
+	if (inode->i_flags & S_NOATIME)
+		return true;
+
+	if (IS_NOATIME(inode))
+		return true;
+
+	if (mnt->mnt_flags & (MNT_NOATIME | MNT_READONLY))
+		return true;
+
+	if ((mnt->mnt_flags & MNT_NODIRATIME) && S_ISDIR(inode->i_mode))
+		return true;
+
+	if ((inode->i_sb->s_flags & MS_NODIRATIME) && S_ISDIR(inode->i_mode))
+		return true;
+
+	return false;
+}
+
 void ll_io_init(struct cl_io *io, const struct file *file, int write)
 {
 	struct inode *inode = file->f_dentry->d_inode;
@@ -1051,6 +1077,8 @@
 	} else if (file->f_flags & O_APPEND) {
 		io->ci_lockreq = CILR_MANDATORY;
 	}
+
+	io->ci_noatime = file_is_noatime(file);
 }
 
 static ssize_t
@@ -2888,7 +2916,7 @@
 			oit.it_op = IT_LOOKUP;
 
 		/* Call getattr by fid, so do not provide name at all. */
-		op_data = ll_prep_md_op_data(NULL, dentry->d_parent->d_inode,
+		op_data = ll_prep_md_op_data(NULL, dentry->d_inode,
 					     dentry->d_inode, NULL, 0, 0,
 					     LUSTRE_OPC_ANY, NULL);
 		if (IS_ERR(op_data))
diff --git a/drivers/staging/lustre/lustre/llite/llite_internal.h b/drivers/staging/lustre/lustre/llite/llite_internal.h
index e27efd1..f67c508 100644
--- a/drivers/staging/lustre/lustre/llite/llite_internal.h
+++ b/drivers/staging/lustre/lustre/llite/llite_internal.h
@@ -775,7 +775,7 @@
 int ll_release_openhandle(struct dentry *, struct lookup_intent *);
 int ll_md_close(struct obd_export *md_exp, struct inode *inode,
 		struct file *file);
-int ll_md_real_close(struct inode *inode, int flags);
+int ll_md_real_close(struct inode *inode, fmode_t fmode);
 void ll_ioepoch_close(struct inode *inode, struct md_op_data *op_data,
 		      struct obd_client_handle **och, unsigned long flags);
 void ll_done_writing_attr(struct inode *inode, struct md_op_data *op_data);
@@ -1309,7 +1309,7 @@
 }
 
 static inline int
-ll_need_statahead(struct inode *dir, struct dentry *dentryp)
+d_need_statahead(struct inode *dir, struct dentry *dentryp)
 {
 	struct ll_inode_info  *lli;
 	struct ll_dentry_data *ldd;
@@ -1354,7 +1354,7 @@
 {
 	int ret;
 
-	ret = ll_need_statahead(dir, *dentryp);
+	ret = d_need_statahead(dir, *dentryp);
 	if (ret <= 0)
 		return ret;
 
diff --git a/drivers/staging/lustre/lustre/llite/llite_lib.c b/drivers/staging/lustre/lustre/llite/llite_lib.c
index 85c01e1..7427f69 100644
--- a/drivers/staging/lustre/lustre/llite/llite_lib.c
+++ b/drivers/staging/lustre/lustre/llite/llite_lib.c
@@ -208,7 +208,8 @@
 				  OBD_CONNECT_LAYOUTLOCK |
 				  OBD_CONNECT_PINGLESS |
 				  OBD_CONNECT_MAX_EASIZE |
-				  OBD_CONNECT_FLOCK_DEAD;
+				  OBD_CONNECT_FLOCK_DEAD |
+				  OBD_CONNECT_DISP_STRIPE;
 
 	if (sbi->ll_flags & LL_SBI_SOM_PREVIEW)
 		data->ocd_connect_flags |= OBD_CONNECT_SOM;
diff --git a/drivers/staging/lustre/lustre/llite/namei.c b/drivers/staging/lustre/lustre/llite/namei.c
index 93c3744..86ff708 100644
--- a/drivers/staging/lustre/lustre/llite/namei.c
+++ b/drivers/staging/lustre/lustre/llite/namei.c
@@ -195,101 +195,107 @@
 int ll_md_blocking_ast(struct ldlm_lock *lock, struct ldlm_lock_desc *desc,
 		       void *data, int flag)
 {
-	int rc;
 	struct lustre_handle lockh;
+	int rc;
 
 	switch (flag) {
 	case LDLM_CB_BLOCKING:
 		ldlm_lock2handle(lock, &lockh);
 		rc = ldlm_cli_cancel(&lockh, LCF_ASYNC);
 		if (rc < 0) {
-			CDEBUG(D_INODE, "ldlm_cli_cancel: %d\n", rc);
+			CDEBUG(D_INODE, "ldlm_cli_cancel: rc = %d\n", rc);
 			return rc;
 		}
 		break;
 	case LDLM_CB_CANCELING: {
 		struct inode *inode = ll_inode_from_resource_lock(lock);
-		struct ll_inode_info *lli;
 		__u64 bits = lock->l_policy_data.l_inodebits.bits;
-		struct lu_fid *fid;
-		ldlm_mode_t mode = lock->l_req_mode;
 
 		/* Inode is set to lock->l_resource->lr_lvb_inode
 		 * for mdc - bug 24555 */
 		LASSERT(lock->l_ast_data == NULL);
 
-		/* Invalidate all dentries associated with this inode */
 		if (inode == NULL)
 			break;
 
+		/* Invalidate all dentries associated with this inode */
 		LASSERT(lock->l_flags & LDLM_FL_CANCELING);
 
-		if (bits & MDS_INODELOCK_XATTR)
+		if (!fid_res_name_eq(ll_inode2fid(inode),
+				     &lock->l_resource->lr_name)) {
+			LDLM_ERROR(lock, "data mismatch with object "DFID"(%p)",
+				   PFID(ll_inode2fid(inode)), inode);
+			LBUG();
+		}
+
+		if (bits & MDS_INODELOCK_XATTR) {
 			ll_xattr_cache_destroy(inode);
+			bits &= ~MDS_INODELOCK_XATTR;
+		}
 
 		/* For OPEN locks we differentiate between lock modes
 		 * LCK_CR, LCK_CW, LCK_PR - bug 22891 */
+		if (bits & MDS_INODELOCK_OPEN)
+			ll_have_md_lock(inode, &bits, lock->l_req_mode);
+
+		if (bits & MDS_INODELOCK_OPEN) {
+			fmode_t fmode;
+
+			switch (lock->l_req_mode) {
+			case LCK_CW:
+				fmode = FMODE_WRITE;
+				break;
+			case LCK_PR:
+				fmode = FMODE_EXEC;
+				break;
+			case LCK_CR:
+				fmode = FMODE_READ;
+				break;
+			default:
+				LDLM_ERROR(lock, "bad lock mode for OPEN lock");
+				LBUG();
+			}
+
+			ll_md_real_close(inode, fmode);
+		}
+
 		if (bits & (MDS_INODELOCK_LOOKUP | MDS_INODELOCK_UPDATE |
 			    MDS_INODELOCK_LAYOUT | MDS_INODELOCK_PERM))
 			ll_have_md_lock(inode, &bits, LCK_MINMODE);
 
-		if (bits & MDS_INODELOCK_OPEN)
-			ll_have_md_lock(inode, &bits, mode);
-
-		fid = ll_inode2fid(inode);
-		if (!fid_res_name_eq(fid, &lock->l_resource->lr_name))
-			LDLM_ERROR(lock, "data mismatch with object "
-				   DFID" (%p)", PFID(fid), inode);
-
-		if (bits & MDS_INODELOCK_OPEN) {
-			int flags = 0;
-			switch (lock->l_req_mode) {
-			case LCK_CW:
-				flags = FMODE_WRITE;
-				break;
-			case LCK_PR:
-				flags = FMODE_EXEC;
-				break;
-			case LCK_CR:
-				flags = FMODE_READ;
-				break;
-			default:
-				CERROR("Unexpected lock mode for OPEN lock "
-				       "%d, inode %ld\n", lock->l_req_mode,
-				       inode->i_ino);
-			}
-			ll_md_real_close(inode, flags);
-		}
-
-		lli = ll_i2info(inode);
 		if (bits & MDS_INODELOCK_LAYOUT) {
-			struct cl_object_conf conf = { { 0 } };
+			struct cl_object_conf conf = {
+				.coc_opc = OBJECT_CONF_INVALIDATE,
+				.coc_inode = inode,
+			};
 
-			conf.coc_opc = OBJECT_CONF_INVALIDATE;
-			conf.coc_inode = inode;
 			rc = ll_layout_conf(inode, &conf);
-			if (rc)
-				CDEBUG(D_INODE, "invaliding layout %d.\n", rc);
+			if (rc < 0)
+				CDEBUG(D_INODE, "cannot invalidate layout of "
+				       DFID": rc = %d\n",
+				       PFID(ll_inode2fid(inode)), rc);
 		}
 
 		if (bits & MDS_INODELOCK_UPDATE) {
+			struct ll_inode_info *lli = ll_i2info(inode);
+
 			spin_lock(&lli->lli_lock);
 			lli->lli_flags &= ~LLIF_MDS_SIZE_LOCK;
 			spin_unlock(&lli->lli_lock);
 		}
 
-		if (S_ISDIR(inode->i_mode) &&
-		     (bits & MDS_INODELOCK_UPDATE)) {
+		if ((bits & MDS_INODELOCK_UPDATE) && S_ISDIR(inode->i_mode)) {
 			CDEBUG(D_INODE, "invalidating inode %lu\n",
 			       inode->i_ino);
 			truncate_inode_pages(inode->i_mapping, 0);
 			ll_invalidate_negative_children(inode);
 		}
 
-		if (inode->i_sb->s_root &&
-		    inode != inode->i_sb->s_root->d_inode &&
-		    (bits & (MDS_INODELOCK_LOOKUP | MDS_INODELOCK_PERM)))
+		if ((bits & (MDS_INODELOCK_LOOKUP | MDS_INODELOCK_PERM)) &&
+		    inode->i_sb->s_root != NULL &&
+		    inode != inode->i_sb->s_root->d_inode)
 			ll_invalidate_aliases(inode);
+
 		iput(inode);
 		break;
 	}
diff --git a/drivers/staging/lustre/lustre/lmv/lmv_intent.c b/drivers/staging/lustre/lustre/lmv/lmv_intent.c
index 56dedce..9ba5a0a 100644
--- a/drivers/staging/lustre/lustre/lmv/lmv_intent.c
+++ b/drivers/staging/lustre/lustre/lmv/lmv_intent.c
@@ -119,7 +119,6 @@
 	CDEBUG(D_INODE, "REMOTE_INTENT with fid="DFID" -> mds #%d\n",
 	       PFID(&body->fid1), tgt->ltd_idx);
 
-	it->d.lustre.it_disposition &= ~DISP_ENQ_COMPLETE;
 	rc = md_intent_lock(tgt->ltd_exp, op_data, lmm, lmmsize, it,
 			    flags, &req, cb_blocking, extra_lock_flags);
 	if (rc)
diff --git a/drivers/staging/lustre/lustre/lmv/lmv_obd.c b/drivers/staging/lustre/lustre/lmv/lmv_obd.c
index 1bddd8f..3ba0a0a 100644
--- a/drivers/staging/lustre/lustre/lmv/lmv_obd.c
+++ b/drivers/staging/lustre/lustre/lmv/lmv_obd.c
@@ -1744,7 +1744,6 @@
 	it->d.lustre.it_data = NULL;
 	fid1 = body->fid1;
 
-	it->d.lustre.it_disposition &= ~DISP_ENQ_COMPLETE;
 	ptlrpc_req_finished(req);
 
 	tgt = lmv_find_target(lmv, &fid1);
@@ -2593,7 +2592,7 @@
 
 int lmv_set_open_replay_data(struct obd_export *exp,
 			     struct obd_client_handle *och,
-			     struct ptlrpc_request *open_req)
+			     struct lookup_intent *it)
 {
 	struct obd_device       *obd = exp->exp_obd;
 	struct lmv_obd	  *lmv = &obd->u.lmv;
@@ -2603,7 +2602,7 @@
 	if (IS_ERR(tgt))
 		return PTR_ERR(tgt);
 
-	return md_set_open_replay_data(tgt->ltd_exp, och, open_req);
+	return md_set_open_replay_data(tgt->ltd_exp, och, it);
 }
 
 int lmv_clear_open_replay_data(struct obd_export *exp,
diff --git a/drivers/staging/lustre/lustre/lov/lov_io.c b/drivers/staging/lustre/lustre/lov/lov_io.c
index 5a6ab70..65133ea 100644
--- a/drivers/staging/lustre/lustre/lov/lov_io.c
+++ b/drivers/staging/lustre/lustre/lov/lov_io.c
@@ -194,6 +194,7 @@
 		sub_io->ci_lockreq = io->ci_lockreq;
 		sub_io->ci_type    = io->ci_type;
 		sub_io->ci_no_srvlock = io->ci_no_srvlock;
+		sub_io->ci_noatime = io->ci_noatime;
 
 		lov_sub_enter(sub);
 		result = cl_io_sub_init(sub->sub_env, sub_io,
diff --git a/drivers/staging/lustre/lustre/mdc/mdc_internal.h b/drivers/staging/lustre/lustre/mdc/mdc_internal.h
index fc21777..c78bf00 100644
--- a/drivers/staging/lustre/lustre/mdc/mdc_internal.h
+++ b/drivers/staging/lustre/lustre/mdc/mdc_internal.h
@@ -122,7 +122,7 @@
 
 int mdc_set_open_replay_data(struct obd_export *exp,
 			     struct obd_client_handle *och,
-			     struct ptlrpc_request *open_req);
+			     struct lookup_intent *it);
 
 int mdc_clear_open_replay_data(struct obd_export *exp,
 			       struct obd_client_handle *och);
diff --git a/drivers/staging/lustre/lustre/mdc/mdc_locks.c b/drivers/staging/lustre/lustre/mdc/mdc_locks.c
index 288a41e..b0d0e2a 100644
--- a/drivers/staging/lustre/lustre/mdc/mdc_locks.c
+++ b/drivers/staging/lustre/lustre/mdc/mdc_locks.c
@@ -37,15 +37,15 @@
 #define DEBUG_SUBSYSTEM S_MDC
 
 # include <linux/module.h>
-# include <linux/pagemap.h>
-# include <linux/miscdevice.h>
 
-#include <lustre_acl.h>
+#include <linux/lustre_intent.h>
+#include <obd.h>
 #include <obd_class.h>
 #include <lustre_dlm.h>
-/* fid_res_name_eq() */
-#include <lustre_fid.h>
-#include <lprocfs_status.h>
+#include <lustre_fid.h> /* fid_res_name_eq() */
+#include <lustre_mdc.h>
+#include <lustre_net.h>
+#include <lustre_req_layout.h>
 #include "mdc_internal.h"
 
 struct mdc_getattr_args {
@@ -160,6 +160,8 @@
 	ldlm_mode_t rc;
 
 	fid_build_reg_res_name(fid, &res_id);
+	/* LU-4405: Clear bits not supported by server */
+	policy->l_inodebits.bits &= exp_connect_ibits(exp);
 	rc = ldlm_lock_match(class_exp2obd(exp)->obd_namespace, flags,
 			     &res_id, type, policy, mode, lockh, 0);
 	return rc;
@@ -334,9 +336,9 @@
 			     max(lmmsize, obddev->u.cli.cl_default_mds_easize));
 
 	rc = ldlm_prep_enqueue_req(exp, req, &cancels, count);
-	if (rc) {
+	if (rc < 0) {
 		ptlrpc_request_free(req);
-		return NULL;
+		return ERR_PTR(rc);
 	}
 
 	spin_lock(&req->rq_lock);
@@ -639,7 +641,7 @@
 			 * happens immediately after swabbing below, new reply
 			 * is swabbed by that handler correctly.
 			 */
-			mdc_set_open_replay_data(NULL, NULL, req);
+			mdc_set_open_replay_data(NULL, NULL, it);
 		}
 
 		if ((body->valid & (OBD_MD_FLDIREA | OBD_MD_FLEASIZE)) != 0) {
@@ -751,6 +753,7 @@
 		/* install lvb_data */
 		lock_res_and_lock(lock);
 		if (lock->l_lvb_data == NULL) {
+			lock->l_lvb_type = LVB_T_LAYOUT;
 			lock->l_lvb_data = lmm;
 			lock->l_lvb_len = lvb_len;
 			lmm = NULL;
@@ -966,7 +969,6 @@
 	if (fid_is_sane(&op_data->op_fid2) &&
 	    it->it_create_mode & M_CHECK_STALE &&
 	    it->it_op != IT_GETATTR) {
-		it_set_disposition(it, DISP_ENQ_COMPLETE);
 
 		/* Also: did we find the same inode? */
 		/* sever can return one of two fids:
@@ -1061,7 +1063,23 @@
 		fid_build_reg_res_name(fid, &res_id);
 		switch (it->it_op) {
 		case IT_GETATTR:
-			policy.l_inodebits.bits = MDS_INODELOCK_UPDATE;
+			/* File attributes are held under multiple bits:
+			 * nlink is under lookup lock, size and times are
+			 * under UPDATE lock and recently we've also got
+			 * a separate permissions lock for owner/group/acl that
+			 * were protected by lookup lock before.
+			 * Getattr must provide all of that information,
+			 * so we need to ensure we have all of those locks.
+			 * Unfortunately, if the bits are split across multiple
+			 * locks, there's no easy way to match all of them here,
+			 * so an extra RPC would be performed to fetch all
+			 * of those bits at once for now. */
+			/* For new MDTs(> 2.4), UPDATE|PERM should be enough,
+			 * but for old MDTs (< 2.4), permission is covered
+			 * by LOOKUP lock, so it needs to match all bits here.*/
+			policy.l_inodebits.bits = MDS_INODELOCK_UPDATE |
+						  MDS_INODELOCK_LOOKUP |
+						  MDS_INODELOCK_PERM;
 			break;
 		case IT_LAYOUT:
 			policy.l_inodebits.bits = MDS_INODELOCK_LAYOUT;
@@ -1070,10 +1088,11 @@
 			policy.l_inodebits.bits = MDS_INODELOCK_LOOKUP;
 			break;
 		}
-		mode = ldlm_lock_match(exp->exp_obd->obd_namespace,
-				       LDLM_FL_BLOCK_GRANTED, &res_id,
+
+		mode = mdc_lock_match(exp, LDLM_FL_BLOCK_GRANTED, fid,
 				       LDLM_IBITS, &policy,
-				       LCK_CR|LCK_CW|LCK_PR|LCK_PW, &lockh, 0);
+				      LCK_CR | LCK_CW | LCK_PR | LCK_PW,
+				      &lockh);
 	}
 
 	if (mode) {
@@ -1120,6 +1139,12 @@
 		    ldlm_blocking_callback cb_blocking,
 		    __u64 extra_lock_flags)
 {
+	struct ldlm_enqueue_info einfo = {
+		.ei_type	= LDLM_IBITS,
+		.ei_mode	= it_to_lock_mode(it),
+		.ei_cb_bl	= cb_blocking,
+		.ei_cb_cp	= ldlm_completion_ast,
+	};
 	struct lustre_handle lockh;
 	int rc = 0;
 
@@ -1145,42 +1170,19 @@
 			return rc;
 	}
 
-	/* lookup_it may be called only after revalidate_it has run, because
-	 * revalidate_it cannot return errors, only zero.  Returning zero causes
-	 * this call to lookup, which *can* return an error.
-	 *
-	 * We only want to execute the request associated with the intent one
-	 * time, however, so don't send the request again.  Instead, skip past
-	 * this and use the request from revalidate.  In this case, revalidate
-	 * never dropped its reference, so the refcounts are all OK */
-	if (!it_disposition(it, DISP_ENQ_COMPLETE)) {
-		struct ldlm_enqueue_info einfo = {
-			.ei_type	= LDLM_IBITS,
-			.ei_mode	= it_to_lock_mode(it),
-			.ei_cb_bl	= cb_blocking,
-			.ei_cb_cp	= ldlm_completion_ast,
-		};
-
-		/* For case if upper layer did not alloc fid, do it now. */
-		if (!fid_is_sane(&op_data->op_fid2) && it->it_op & IT_CREAT) {
-			rc = mdc_fid_alloc(exp, &op_data->op_fid2, op_data);
-			if (rc < 0) {
-				CERROR("Can't alloc new fid, rc %d\n", rc);
-				return rc;
-			}
-		}
-		rc = mdc_enqueue(exp, &einfo, it, op_data, &lockh,
-				 lmm, lmmsize, NULL, extra_lock_flags);
-		if (rc < 0)
+	/* For case if upper layer did not alloc fid, do it now. */
+	if (!fid_is_sane(&op_data->op_fid2) && it->it_op & IT_CREAT) {
+		rc = mdc_fid_alloc(exp, &op_data->op_fid2, op_data);
+		if (rc < 0) {
+			CERROR("Can't alloc new fid, rc %d\n", rc);
 			return rc;
-	} else if (!fid_is_sane(&op_data->op_fid2) ||
-		   !(it->it_create_mode & M_CHECK_STALE)) {
-		/* DISP_ENQ_COMPLETE set means there is extra reference on
-		 * request referenced from this intent, saved for subsequent
-		 * lookup.  This path is executed when we proceed to this
-		 * lookup, so we clear DISP_ENQ_COMPLETE */
-		it_clear_disposition(it, DISP_ENQ_COMPLETE);
+		}
 	}
+	rc = mdc_enqueue(exp, &einfo, it, op_data, &lockh, lmm, lmmsize, NULL,
+			 extra_lock_flags);
+	if (rc < 0)
+		return rc;
+
 	*reqp = it->d.lustre.it_data;
 	rc = mdc_finish_intent_lock(exp, *reqp, op_data, it, &lockh);
 	return rc;
@@ -1262,8 +1264,8 @@
 
 	fid_build_reg_res_name(&op_data->op_fid1, &res_id);
 	req = mdc_intent_getattr_pack(exp, it, op_data);
-	if (!req)
-		return -ENOMEM;
+	if (IS_ERR(req))
+		return PTR_ERR(req);
 
 	rc = mdc_enter_request(&obddev->u.cli);
 	if (rc != 0) {
diff --git a/drivers/staging/lustre/lustre/mdc/mdc_reint.c b/drivers/staging/lustre/lustre/mdc/mdc_reint.c
index 1aea154..d79aa16 100644
--- a/drivers/staging/lustre/lustre/mdc/mdc_reint.c
+++ b/drivers/staging/lustre/lustre/mdc/mdc_reint.c
@@ -165,6 +165,7 @@
 			req->rq_cb_data = *mod;
 			(*mod)->mod_open_req = req;
 			req->rq_commit_cb = mdc_commit_open;
+			(*mod)->mod_is_create = true;
 			/**
 			 * Take an extra reference on \var mod, it protects \var
 			 * mod from being freed on eviction (commit callback is
diff --git a/drivers/staging/lustre/lustre/mdc/mdc_request.c b/drivers/staging/lustre/lustre/mdc/mdc_request.c
index 17c8e14..d9ddb39 100644
--- a/drivers/staging/lustre/lustre/mdc/mdc_request.c
+++ b/drivers/staging/lustre/lustre/mdc/mdc_request.c
@@ -722,11 +722,12 @@
 
 int mdc_set_open_replay_data(struct obd_export *exp,
 			     struct obd_client_handle *och,
-			     struct ptlrpc_request *open_req)
+			     struct lookup_intent *it)
 {
 	struct md_open_data   *mod;
 	struct mdt_rec_create *rec;
 	struct mdt_body       *body;
+	struct ptlrpc_request *open_req = it->d.lustre.it_data;
 	struct obd_import     *imp = open_req->rq_import;
 
 	if (!open_req->rq_replay)
@@ -760,6 +761,8 @@
 		spin_lock(&open_req->rq_lock);
 		och->och_mod = mod;
 		mod->mod_och = och;
+		mod->mod_is_create = it_disposition(it, DISP_OPEN_CREATE) ||
+				     it_disposition(it, DISP_OPEN_STRIPE);
 		mod->mod_open_req = open_req;
 		open_req->rq_cb_data = mod;
 		open_req->rq_commit_cb = mdc_commit_open;
@@ -780,6 +783,23 @@
 	return 0;
 }
 
+static void mdc_free_open(struct md_open_data *mod)
+{
+	int committed = 0;
+
+	if (mod->mod_is_create == 0 &&
+	    imp_connect_disp_stripe(mod->mod_open_req->rq_import))
+		committed = 1;
+
+	LASSERT(mod->mod_open_req->rq_replay == 0);
+
+	DEBUG_REQ(D_RPCTRACE, mod->mod_open_req, "free open request\n");
+
+	ptlrpc_request_committed(mod->mod_open_req, committed);
+	if (mod->mod_close_req)
+		ptlrpc_request_committed(mod->mod_close_req, committed);
+}
+
 int mdc_clear_open_replay_data(struct obd_export *exp,
 			       struct obd_client_handle *och)
 {
@@ -793,6 +813,8 @@
 		return 0;
 
 	LASSERT(mod != LP_POISON);
+	LASSERT(mod->mod_open_req != NULL);
+	mdc_free_open(mod);
 
 	mod->mod_och = NULL;
 	och->och_mod = NULL;
@@ -991,6 +1013,9 @@
 	if (mod) {
 		if (rc != 0)
 			mod->mod_close_req = NULL;
+		LASSERT(mod->mod_open_req != NULL);
+		mdc_free_open(mod);
+
 		/* Since now, mod is accessed through setattr req only,
 		 * thus DW req does not keep a reference on mod anymore. */
 		obd_mod_put(mod);
diff --git a/drivers/staging/lustre/lustre/obdclass/genops.c b/drivers/staging/lustre/lustre/obdclass/genops.c
index d27f041..169c9ed 100644
--- a/drivers/staging/lustre/lustre/obdclass/genops.c
+++ b/drivers/staging/lustre/lustre/obdclass/genops.c
@@ -1010,6 +1010,8 @@
 	INIT_LIST_HEAD(&imp->imp_replay_list);
 	INIT_LIST_HEAD(&imp->imp_sending_list);
 	INIT_LIST_HEAD(&imp->imp_delayed_list);
+	INIT_LIST_HEAD(&imp->imp_committed_list);
+	imp->imp_replay_cursor = &imp->imp_committed_list;
 	spin_lock_init(&imp->imp_lock);
 	imp->imp_last_success_conn = 0;
 	imp->imp_state = LUSTRE_IMP_NEW;
diff --git a/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c b/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c
index 6e7d2e5..1432dd7 100644
--- a/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c
+++ b/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c
@@ -99,6 +99,7 @@
 	"short_io",
 	"pingless",
 	"flock_deadlock",
+	"disp_stripe",
 	"unknown",
 	NULL
 };
diff --git a/drivers/staging/lustre/lustre/osc/osc_cache.c b/drivers/staging/lustre/lustre/osc/osc_cache.c
index b92a02e..af25c19 100644
--- a/drivers/staging/lustre/lustre/osc/osc_cache.c
+++ b/drivers/staging/lustre/lustre/osc/osc_cache.c
@@ -2394,6 +2394,12 @@
 		 * really sending the RPC. */
 	case OES_TRUNC:
 		/* race with truncate, page will be redirtied */
+	case OES_ACTIVE:
+		/* The extent is active so we need to abort and let the caller
+		 * re-dirty the page. If we continued on here, and we were the
+		 * one making the extent active, we could deadlock waiting for
+		 * the page writeback to clear but it won't because the extent
+		 * is active and won't be written out. */
 		GOTO(out, rc = -EAGAIN);
 	default:
 		break;
diff --git a/drivers/staging/lustre/lustre/osc/osc_io.c b/drivers/staging/lustre/lustre/osc/osc_io.c
index 777ae24..5f3c545 100644
--- a/drivers/staging/lustre/lustre/osc/osc_io.c
+++ b/drivers/staging/lustre/lustre/osc/osc_io.c
@@ -512,19 +512,15 @@
 	struct osc_io    *oio   = cl2osc_io(env, slice);
 	struct cl_object *obj   = slice->cis_obj;
 	struct cl_attr   *attr  = &osc_env_info(env)->oti_attr;
-	int	      result = 0;
+	int rc = 0;
 
-	if (oio->oi_lockless == 0) {
+	if (oio->oi_lockless == 0 && !slice->cis_io->ci_noatime) {
 		cl_object_attr_lock(obj);
-		result = cl_object_attr_get(env, obj, attr);
-		if (result == 0) {
-			attr->cat_atime = LTIME_S(CURRENT_TIME);
-			result = cl_object_attr_set(env, obj, attr,
-						    CAT_ATIME);
-		}
+		attr->cat_atime = LTIME_S(CURRENT_TIME);
+		rc = cl_object_attr_set(env, obj, attr, CAT_ATIME);
 		cl_object_attr_unlock(obj);
 	}
-	return result;
+	return rc;
 }
 
 static int osc_io_write_start(const struct lu_env *env,
diff --git a/drivers/staging/lustre/lustre/osc/osc_quota.c b/drivers/staging/lustre/lustre/osc/osc_quota.c
index 6045a78..f395ae4 100644
--- a/drivers/staging/lustre/lustre/osc/osc_quota.c
+++ b/drivers/staging/lustre/lustre/osc/osc_quota.c
@@ -51,11 +51,8 @@
 
 		oqi = cfs_hash_lookup(cli->cl_quota_hash[type], &qid[type]);
 		if (oqi) {
-			obd_uid id = oqi->oqi_id;
-
-			LASSERTF(id == qid[type],
-				 "The ids don't match %u != %u\n",
-				 id, qid[type]);
+			/* do not try to access oqi here, it could have been
+			 * freed by osc_quota_setdq() */
 
 			/* the slot is busy, the user is about to run out of
 			 * quota space on this OST */
diff --git a/drivers/staging/lustre/lustre/ptlrpc/client.c b/drivers/staging/lustre/lustre/ptlrpc/client.c
index eb33bb7..4c9e006 100644
--- a/drivers/staging/lustre/lustre/ptlrpc/client.c
+++ b/drivers/staging/lustre/lustre/ptlrpc/client.c
@@ -48,6 +48,7 @@
 #include "ptlrpc_internal.h"
 
 static int ptlrpc_send_new_req(struct ptlrpc_request *req);
+static int ptlrpcd_check_work(struct ptlrpc_request *req);
 
 /**
  * Initialize passed in client structure \a cl.
@@ -1190,7 +1191,9 @@
 		 * will roundup it */
 		req->rq_replen       = req->rq_nob_received;
 		req->rq_nob_received = 0;
+		spin_lock(&req->rq_lock);
 		req->rq_resend       = 1;
+		spin_unlock(&req->rq_lock);
 		return 0;
 	}
 
@@ -1313,7 +1316,11 @@
 			/** version recovery */
 			ptlrpc_save_versions(req);
 			ptlrpc_retain_replayable_request(req, imp);
-		} else if (req->rq_commit_cb != NULL) {
+		} else if (req->rq_commit_cb != NULL &&
+			   list_empty(&req->rq_replay_list)) {
+			/* NB: don't call rq_commit_cb if it's already on
+			 * rq_replay_list, ptlrpc_free_committed() will call
+			 * it later, see LU-3618 for details */
 			spin_unlock(&imp->imp_lock);
 			req->rq_commit_cb(req);
 			spin_lock(&imp->imp_lock);
@@ -1408,7 +1415,9 @@
 			req->rq_status = rc;
 			return 1;
 		} else {
+			spin_lock(&req->rq_lock);
 			req->rq_wait_ctx = 1;
+			spin_unlock(&req->rq_lock);
 			return 0;
 		}
 	}
@@ -1423,7 +1432,9 @@
 	rc = ptl_send_rpc(req, 0);
 	if (rc) {
 		DEBUG_REQ(D_HA, req, "send failed (%d); expect timeout", rc);
+		spin_lock(&req->rq_lock);
 		req->rq_net_err = 1;
+		spin_unlock(&req->rq_lock);
 		return rc;
 	}
 	return 0;
@@ -1688,6 +1699,7 @@
 					spin_lock(&req->rq_lock);
 					req->rq_net_err = 1;
 					spin_unlock(&req->rq_lock);
+					continue;
 				}
 				/* need to reset the timeout */
 				force_timer_recalc = 1;
@@ -1773,6 +1785,10 @@
 
 		ptlrpc_req_interpret(env, req, req->rq_status);
 
+		if (ptlrpcd_check_work(req)) {
+			atomic_dec(&set->set_remaining);
+			continue;
+		}
 		ptlrpc_rqphase_move(req, RQ_PHASE_COMPLETE);
 
 		CDEBUG(req->rq_reqmsg != NULL ? D_RPCTRACE : 0,
@@ -2360,6 +2376,39 @@
 }
 EXPORT_SYMBOL(ptlrpc_unregister_reply);
 
+static void ptlrpc_free_request(struct ptlrpc_request *req)
+{
+	spin_lock(&req->rq_lock);
+	req->rq_replay = 0;
+	spin_unlock(&req->rq_lock);
+
+	if (req->rq_commit_cb != NULL)
+		req->rq_commit_cb(req);
+	list_del_init(&req->rq_replay_list);
+
+	__ptlrpc_req_finished(req, 1);
+}
+
+/**
+ * the request is committed and dropped from the replay list of its import
+ */
+void ptlrpc_request_committed(struct ptlrpc_request *req, int force)
+{
+	struct obd_import	*imp = req->rq_import;
+
+	spin_lock(&imp->imp_lock);
+	if (list_empty(&req->rq_replay_list)) {
+		spin_unlock(&imp->imp_lock);
+		return;
+	}
+
+	if (force || req->rq_transno <= imp->imp_peer_committed_transno)
+		ptlrpc_free_request(req);
+
+	spin_unlock(&imp->imp_lock);
+}
+EXPORT_SYMBOL(ptlrpc_request_committed);
+
 /**
  * Iterates through replay_list on import and prunes
  * all requests have transno smaller than last_committed for the
@@ -2370,9 +2419,9 @@
  */
 void ptlrpc_free_committed(struct obd_import *imp)
 {
-	struct list_head *tmp, *saved;
-	struct ptlrpc_request *req;
+	struct ptlrpc_request *req, *saved;
 	struct ptlrpc_request *last_req = NULL; /* temporary fire escape */
+	bool		       skip_committed_list = true;
 
 	LASSERT(imp != NULL);
 
@@ -2388,13 +2437,15 @@
 	CDEBUG(D_RPCTRACE, "%s: committing for last_committed "LPU64" gen %d\n",
 	       imp->imp_obd->obd_name, imp->imp_peer_committed_transno,
 	       imp->imp_generation);
+
+	if (imp->imp_generation != imp->imp_last_generation_checked)
+		skip_committed_list = false;
+
 	imp->imp_last_transno_checked = imp->imp_peer_committed_transno;
 	imp->imp_last_generation_checked = imp->imp_generation;
 
-	list_for_each_safe(tmp, saved, &imp->imp_replay_list) {
-		req = list_entry(tmp, struct ptlrpc_request,
-				     rq_replay_list);
-
+	list_for_each_entry_safe(req, saved, &imp->imp_replay_list,
+				 rq_replay_list) {
 		/* XXX ok to remove when 1357 resolved - rread 05/29/03  */
 		LASSERT(req != last_req);
 		last_req = req;
@@ -2408,27 +2459,34 @@
 			GOTO(free_req, 0);
 		}
 
-		if (req->rq_replay) {
-			DEBUG_REQ(D_RPCTRACE, req, "keeping (FL_REPLAY)");
-			continue;
-		}
-
 		/* not yet committed */
 		if (req->rq_transno > imp->imp_peer_committed_transno) {
 			DEBUG_REQ(D_RPCTRACE, req, "stopping search");
 			break;
 		}
 
+		if (req->rq_replay) {
+			DEBUG_REQ(D_RPCTRACE, req, "keeping (FL_REPLAY)");
+			list_move_tail(&req->rq_replay_list,
+				       &imp->imp_committed_list);
+			continue;
+		}
+
 		DEBUG_REQ(D_INFO, req, "commit (last_committed "LPU64")",
 			  imp->imp_peer_committed_transno);
 free_req:
-		spin_lock(&req->rq_lock);
-		req->rq_replay = 0;
-		spin_unlock(&req->rq_lock);
-		if (req->rq_commit_cb != NULL)
-			req->rq_commit_cb(req);
-		list_del_init(&req->rq_replay_list);
-		__ptlrpc_req_finished(req, 1);
+		ptlrpc_free_request(req);
+	}
+	if (skip_committed_list)
+		return;
+
+	list_for_each_entry_safe(req, saved, &imp->imp_committed_list,
+				 rq_replay_list) {
+		LASSERT(req->rq_transno != 0);
+		if (req->rq_import_generation < imp->imp_generation) {
+			DEBUG_REQ(D_RPCTRACE, req, "free stale open request");
+			ptlrpc_free_request(req);
+		}
 	}
 }
 
@@ -2904,22 +2962,50 @@
  *    have delay before it really runs by ptlrpcd thread.
  */
 struct ptlrpc_work_async_args {
-	__u64   magic;
 	int   (*cb)(const struct lu_env *, void *);
 	void   *cbdata;
 };
 
-#define PTLRPC_WORK_MAGIC 0x6655436b676f4f44ULL /* magic code */
+static void ptlrpcd_add_work_req(struct ptlrpc_request *req)
+{
+	/* re-initialize the req */
+	req->rq_timeout		= obd_timeout;
+	req->rq_sent		= cfs_time_current_sec();
+	req->rq_deadline	= req->rq_sent + req->rq_timeout;
+	req->rq_reply_deadline	= req->rq_deadline;
+	req->rq_phase		= RQ_PHASE_INTERPRET;
+	req->rq_next_phase	= RQ_PHASE_COMPLETE;
+	req->rq_xid		= ptlrpc_next_xid();
+	req->rq_import_generation = req->rq_import->imp_generation;
+
+	ptlrpcd_add_req(req, PDL_POLICY_ROUND, -1);
+}
 
 static int work_interpreter(const struct lu_env *env,
 			    struct ptlrpc_request *req, void *data, int rc)
 {
 	struct ptlrpc_work_async_args *arg = data;
 
-	LASSERT(arg->magic == PTLRPC_WORK_MAGIC);
+	LASSERT(ptlrpcd_check_work(req));
 	LASSERT(arg->cb != NULL);
 
-	return arg->cb(env, arg->cbdata);
+	rc = arg->cb(env, arg->cbdata);
+
+	list_del_init(&req->rq_set_chain);
+	req->rq_set = NULL;
+
+	if (atomic_dec_return(&req->rq_refcount) > 1) {
+		atomic_set(&req->rq_refcount, 2);
+		ptlrpcd_add_work_req(req);
+	}
+	return rc;
+}
+
+static int worker_format;
+
+static int ptlrpcd_check_work(struct ptlrpc_request *req)
+{
+	return req->rq_pill.rc_fmt == (void *)&worker_format;
 }
 
 /**
@@ -2952,6 +3038,7 @@
 	req->rq_receiving_reply = 0;
 	req->rq_must_unlink = 0;
 	req->rq_no_delay = req->rq_no_resend = 1;
+	req->rq_pill.rc_fmt = (void *)&worker_format;
 
 	spin_lock_init(&req->rq_lock);
 	INIT_LIST_HEAD(&req->rq_list);
@@ -2965,7 +3052,6 @@
 
 	CLASSERT(sizeof(*args) <= sizeof(req->rq_async_args));
 	args = ptlrpc_req_async_args(req);
-	args->magic  = PTLRPC_WORK_MAGIC;
 	args->cb     = cb;
 	args->cbdata = cbdata;
 
@@ -2995,25 +3081,8 @@
 	 * req as opaque data. - Jinshan
 	 */
 	LASSERT(atomic_read(&req->rq_refcount) > 0);
-	if (atomic_read(&req->rq_refcount) > 1)
-		return -EBUSY;
-
-	if (atomic_inc_return(&req->rq_refcount) > 2) { /* race */
-		atomic_dec(&req->rq_refcount);
-		return -EBUSY;
-	}
-
-	/* re-initialize the req */
-	req->rq_timeout	= obd_timeout;
-	req->rq_sent	   = cfs_time_current_sec();
-	req->rq_deadline       = req->rq_sent + req->rq_timeout;
-	req->rq_reply_deadline = req->rq_deadline;
-	req->rq_phase	  = RQ_PHASE_INTERPRET;
-	req->rq_next_phase     = RQ_PHASE_COMPLETE;
-	req->rq_xid	    = ptlrpc_next_xid();
-	req->rq_import_generation = req->rq_import->imp_generation;
-
-	ptlrpcd_add_req(req, PDL_POLICY_ROUND, -1);
+	if (atomic_inc_return(&req->rq_refcount) == 2)
+		ptlrpcd_add_work_req(req);
 	return 0;
 }
 EXPORT_SYMBOL(ptlrpcd_queue_work);
diff --git a/drivers/staging/lustre/lustre/ptlrpc/import.c b/drivers/staging/lustre/lustre/ptlrpc/import.c
index 82db0ed..537aa62 100644
--- a/drivers/staging/lustre/lustre/ptlrpc/import.c
+++ b/drivers/staging/lustre/lustre/ptlrpc/import.c
@@ -560,17 +560,30 @@
 	struct ptlrpc_request *req;
 	struct list_head *tmp;
 
-	if (list_empty(&imp->imp_replay_list))
-		return 0;
-	tmp = imp->imp_replay_list.next;
-	req = list_entry(tmp, struct ptlrpc_request, rq_replay_list);
-	*transno = req->rq_transno;
-	if (req->rq_transno == 0) {
-		DEBUG_REQ(D_ERROR, req, "zero transno in replay");
-		LBUG();
+	/* The requests in committed_list always have smaller transnos than
+	 * the requests in replay_list */
+	if (!list_empty(&imp->imp_committed_list)) {
+		tmp = imp->imp_committed_list.next;
+		req = list_entry(tmp, struct ptlrpc_request, rq_replay_list);
+		*transno = req->rq_transno;
+		if (req->rq_transno == 0) {
+			DEBUG_REQ(D_ERROR, req,
+				  "zero transno in committed_list");
+			LBUG();
+		}
+		return 1;
 	}
-
-	return 1;
+	if (!list_empty(&imp->imp_replay_list)) {
+		tmp = imp->imp_replay_list.next;
+		req = list_entry(tmp, struct ptlrpc_request, rq_replay_list);
+		*transno = req->rq_transno;
+		if (req->rq_transno == 0) {
+			DEBUG_REQ(D_ERROR, req, "zero transno in replay_list");
+			LBUG();
+		}
+		return 1;
+	}
+	return 0;
 }
 
 /**
diff --git a/drivers/staging/lustre/lustre/ptlrpc/niobuf.c b/drivers/staging/lustre/lustre/ptlrpc/niobuf.c
index 1e94597..a47a8d8 100644
--- a/drivers/staging/lustre/lustre/ptlrpc/niobuf.c
+++ b/drivers/staging/lustre/lustre/ptlrpc/niobuf.c
@@ -511,7 +511,9 @@
 		CDEBUG(D_HA, "muting rpc for failed imp obd %s\n",
 		       request->rq_import->imp_obd->obd_name);
 		/* this prevents us from waiting in ptlrpc_queue_wait */
+		spin_lock(&request->rq_lock);
 		request->rq_err = 1;
+		spin_unlock(&request->rq_lock);
 		request->rq_status = -ENODEV;
 		return -ENODEV;
 	}
@@ -553,7 +555,9 @@
 			if (rc) {
 				/* this prevents us from looping in
 				 * ptlrpc_queue_wait */
+				spin_lock(&request->rq_lock);
 				request->rq_err = 1;
+				spin_unlock(&request->rq_lock);
 				request->rq_status = rc;
 				GOTO(cleanup_bulk, rc);
 			}
diff --git a/drivers/staging/lustre/lustre/ptlrpc/recover.c b/drivers/staging/lustre/lustre/ptlrpc/recover.c
index 84c39e0..48ae328 100644
--- a/drivers/staging/lustre/lustre/ptlrpc/recover.c
+++ b/drivers/staging/lustre/lustre/ptlrpc/recover.c
@@ -105,24 +105,59 @@
 	 * imp_lock is being held by ptlrpc_replay, but it's not. it's
 	 * just a little race...
 	 */
-	list_for_each_safe(tmp, pos, &imp->imp_replay_list) {
+
+	/* Replay all the committed open requests on committed_list first */
+	if (!list_empty(&imp->imp_committed_list)) {
+		tmp = imp->imp_committed_list.prev;
 		req = list_entry(tmp, struct ptlrpc_request,
 				     rq_replay_list);
 
-		/* If need to resend the last sent transno (because a
-		   reconnect has occurred), then stop on the matching
-		   req and send it again. If, however, the last sent
-		   transno has been committed then we continue replay
-		   from the next request. */
+		/* The last request on committed_list hasn't been replayed */
 		if (req->rq_transno > last_transno) {
-			if (imp->imp_resend_replay)
-				lustre_msg_add_flags(req->rq_reqmsg,
-						     MSG_RESENT);
-			break;
+			/* Since the imp_committed_list is immutable before
+			 * all of it's requests being replayed, it's safe to
+			 * use a cursor to accelerate the search */
+			imp->imp_replay_cursor = imp->imp_replay_cursor->next;
+
+			while (imp->imp_replay_cursor !=
+			       &imp->imp_committed_list) {
+				req = list_entry(imp->imp_replay_cursor,
+						 struct ptlrpc_request,
+						 rq_replay_list);
+				if (req->rq_transno > last_transno)
+					break;
+
+				req = NULL;
+				imp->imp_replay_cursor =
+					imp->imp_replay_cursor->next;
+			}
+		} else {
+			/* All requests on committed_list have been replayed */
+			imp->imp_replay_cursor = &imp->imp_committed_list;
+			req = NULL;
 		}
-		req = NULL;
 	}
 
+	/* All the requests in committed list have been replayed, let's replay
+	 * the imp_replay_list */
+	if (req == NULL) {
+		list_for_each_safe(tmp, pos, &imp->imp_replay_list) {
+			req = list_entry(tmp, struct ptlrpc_request,
+					 rq_replay_list);
+
+			if (req->rq_transno > last_transno)
+				break;
+			req = NULL;
+		}
+	}
+
+	/* If need to resend the last sent transno (because a reconnect
+	 * has occurred), then stop on the matching req and send it again.
+	 * If, however, the last sent transno has been committed then we
+	 * continue replay from the next request. */
+	if (req != NULL && imp->imp_resend_replay)
+		lustre_msg_add_flags(req->rq_reqmsg, MSG_RESENT);
+
 	spin_lock(&imp->imp_lock);
 	imp->imp_resend_replay = 0;
 	spin_unlock(&imp->imp_lock);
diff --git a/drivers/staging/netlogic/xlr_net.c b/drivers/staging/netlogic/xlr_net.c
index d8ea254..31b269a 100644
--- a/drivers/staging/netlogic/xlr_net.c
+++ b/drivers/staging/netlogic/xlr_net.c
@@ -307,7 +307,7 @@
 }
 
 static u16 xlr_net_select_queue(struct net_device *ndev, struct sk_buff *skb,
-				void *accel_priv)
+				void *accel_priv, select_queue_fallback_t fallback)
 {
 	return (u16)smp_processor_id();
 }
diff --git a/drivers/staging/octeon/ethernet-defines.h b/drivers/staging/octeon/ethernet-defines.h
index bdaec8d..2a98a21 100644
--- a/drivers/staging/octeon/ethernet-defines.h
+++ b/drivers/staging/octeon/ethernet-defines.h
@@ -33,10 +33,6 @@
  *      driver will use this memory instead of kernel memory for pools. This
  *      allows 32bit userspace application to access the buffers, but also
  *      requires all received packets to be copied.
- *  CONFIG_CAVIUM_OCTEON_NUM_PACKET_BUFFERS
- *      This kernel config option allows the user to control the number of
- *      packet and work queue buffers allocated by the driver. If this is zero,
- *      the driver uses the default from below.
  *  USE_SKBUFFS_IN_HW
  *      Tells the driver to populate the packet buffers with kernel skbuffs.
  *      This allows the driver to receive packets without copying them. It also
diff --git a/drivers/staging/octeon/ethernet-mem.c b/drivers/staging/octeon/ethernet-mem.c
index 199059d..55c1348 100644
--- a/drivers/staging/octeon/ethernet-mem.c
+++ b/drivers/staging/octeon/ethernet-mem.c
@@ -30,6 +30,7 @@
 
 #include <asm/octeon/octeon.h>
 
+#include "ethernet-mem.h"
 #include "ethernet-defines.h"
 
 #include <asm/octeon/cvmx-fpa.h>
diff --git a/drivers/staging/octeon/ethernet-rgmii.c b/drivers/staging/octeon/ethernet-rgmii.c
index ea53af3..40297ce 100644
--- a/drivers/staging/octeon/ethernet-rgmii.c
+++ b/drivers/staging/octeon/ethernet-rgmii.c
@@ -43,7 +43,7 @@
 #include <asm/octeon/cvmx-npi-defs.h>
 #include <asm/octeon/cvmx-gmxx-defs.h>
 
-DEFINE_SPINLOCK(global_register_lock);
+static DEFINE_SPINLOCK(global_register_lock);
 
 static int number_rgmii_ports;
 
diff --git a/drivers/staging/octeon/ethernet-tx.c b/drivers/staging/octeon/ethernet-tx.c
index 47541e1..8ca55c4 100644
--- a/drivers/staging/octeon/ethernet-tx.c
+++ b/drivers/staging/octeon/ethernet-tx.c
@@ -95,7 +95,7 @@
 	cvmx_write_csr(CVMX_CIU_TIMX(1), ciu_timx.u64);
 }
 
-void cvm_oct_free_tx_skbs(struct net_device *dev)
+static void cvm_oct_free_tx_skbs(struct net_device *dev)
 {
 	int32_t skb_to_free;
 	int qos, queues_per_port;
diff --git a/drivers/staging/octeon/ethernet.c b/drivers/staging/octeon/ethernet.c
index 089dc4b..ff7214a 100644
--- a/drivers/staging/octeon/ethernet.c
+++ b/drivers/staging/octeon/ethernet.c
@@ -55,17 +55,11 @@
 #include <asm/octeon/cvmx-gmxx-defs.h>
 #include <asm/octeon/cvmx-smix-defs.h>
 
-#if defined(CONFIG_CAVIUM_OCTEON_NUM_PACKET_BUFFERS) \
-	&& CONFIG_CAVIUM_OCTEON_NUM_PACKET_BUFFERS
-int num_packet_buffers = CONFIG_CAVIUM_OCTEON_NUM_PACKET_BUFFERS;
-#else
-int num_packet_buffers = 1024;
-#endif
+static int num_packet_buffers = 1024;
 module_param(num_packet_buffers, int, 0444);
 MODULE_PARM_DESC(num_packet_buffers, "\n"
 	"\tNumber of packet buffers to allocate and store in the\n"
-	"\tFPA. By default, 1024 packet buffers are used unless\n"
-	"\tCONFIG_CAVIUM_OCTEON_NUM_PACKET_BUFFERS is defined.");
+	"\tFPA. By default, 1024 packet buffers are used.\n");
 
 int pow_receive_group = 15;
 module_param(pow_receive_group, int, 0444);
diff --git a/drivers/staging/ozwpan/ozpd.c b/drivers/staging/ozwpan/ozpd.c
index 7436950..29a23a3 100644
--- a/drivers/staging/ozwpan/ozpd.c
+++ b/drivers/staging/ozwpan/ozpd.c
@@ -284,11 +284,11 @@
 					  ai->app_id);
 				break;
 			}
-			oz_polling_lock_bh();
+			spin_lock_bh(&g_polling_lock);
 			pd->total_apps |= (1<<ai->app_id);
 			if (resume)
 				pd->paused_apps &= ~(1<<ai->app_id);
-			oz_polling_unlock_bh();
+			spin_unlock_bh(&g_polling_lock);
 		}
 	}
 	return rc;
@@ -304,14 +304,14 @@
 	oz_pd_dbg(pd, ON, "%s: (0x%x) pause(%d)\n", __func__, apps, pause);
 	for (ai = g_app_if; ai < &g_app_if[OZ_APPID_MAX]; ai++) {
 		if (apps & (1<<ai->app_id)) {
-			oz_polling_lock_bh();
+			spin_lock_bh(&g_polling_lock);
 			if (pause) {
 				pd->paused_apps |= (1<<ai->app_id);
 			} else {
 				pd->total_apps &= ~(1<<ai->app_id);
 				pd->paused_apps &= ~(1<<ai->app_id);
 			}
-			oz_polling_unlock_bh();
+			spin_unlock_bh(&g_polling_lock);
 			ai->stop(pd, pause);
 		}
 	}
@@ -349,17 +349,17 @@
 
 	oz_dbg(ON, "oz_pd_stop() State = 0x%x\n", pd->state);
 	oz_pd_indicate_farewells(pd);
-	oz_polling_lock_bh();
+	spin_lock_bh(&g_polling_lock);
 	stop_apps = pd->total_apps;
 	pd->total_apps = 0;
 	pd->paused_apps = 0;
-	oz_polling_unlock_bh();
+	spin_unlock_bh(&g_polling_lock);
 	oz_services_stop(pd, stop_apps, 0);
-	oz_polling_lock_bh();
+	spin_lock_bh(&g_polling_lock);
 	oz_pd_set_state(pd, OZ_PD_S_STOPPED);
 	/* Remove from PD list.*/
 	list_del(&pd->link);
-	oz_polling_unlock_bh();
+	spin_unlock_bh(&g_polling_lock);
 	oz_dbg(ON, "pd ref count = %d\n", atomic_read(&pd->ref_count));
 	oz_pd_put(pd);
 }
@@ -372,9 +372,9 @@
 	int do_stop = 0;
 	u16 stop_apps;
 
-	oz_polling_lock_bh();
+	spin_lock_bh(&g_polling_lock);
 	if (pd->state & (OZ_PD_S_SLEEP | OZ_PD_S_STOPPED)) {
-		oz_polling_unlock_bh();
+		spin_unlock_bh(&g_polling_lock);
 		return 0;
 	}
 	if (pd->keep_alive && pd->session_id)
@@ -383,7 +383,7 @@
 		do_stop = 1;
 
 	stop_apps = pd->total_apps;
-	oz_polling_unlock_bh();
+	spin_unlock_bh(&g_polling_lock);
 	if (do_stop) {
 		oz_pd_stop(pd);
 	} else {
@@ -999,15 +999,15 @@
 	const struct oz_app_if *ai = &g_app_if[OZ_APPID_USB-1];
 
 	while (1) {
-		oz_polling_lock_bh();
+		spin_lock_bh(&g_polling_lock);
 		if (list_empty(&pd->farewell_list)) {
-			oz_polling_unlock_bh();
+			spin_unlock_bh(&g_polling_lock);
 			break;
 		}
 		f = list_first_entry(&pd->farewell_list,
 				struct oz_farewell, link);
 		list_del(&f->link);
-		oz_polling_unlock_bh();
+		spin_unlock_bh(&g_polling_lock);
 		if (ai->farewell)
 			ai->farewell(pd, f->ep_num, f->report, f->len);
 		kfree(f);
diff --git a/drivers/staging/ozwpan/ozpd.h b/drivers/staging/ozwpan/ozpd.h
index 12c7129..56e6fdf 100644
--- a/drivers/staging/ozwpan/ozpd.h
+++ b/drivers/staging/ozwpan/ozpd.h
@@ -22,6 +22,11 @@
 #define OZ_TIMER_HEARTBEAT	2
 #define OZ_TIMER_STOP		3
 
+/* 
+ *External spinlock variable
+ */
+extern spinlock_t g_polling_lock;
+
 /* Data structure that hold information on a frame for transmisson. This is
  * built when the frame is first transmitted and is used to rebuild the frame
  * if a re-transmission is required.
diff --git a/drivers/staging/ozwpan/ozproto.c b/drivers/staging/ozwpan/ozproto.c
index e7138ed..c1325a6 100644
--- a/drivers/staging/ozwpan/ozproto.c
+++ b/drivers/staging/ozwpan/ozproto.c
@@ -38,9 +38,13 @@
 };
 
 /*
+ * External variable
+ */
+
+DEFINE_SPINLOCK(g_polling_lock);
+/*
  * Static external variables.
  */
-static DEFINE_SPINLOCK(g_polling_lock);
 static LIST_HEAD(g_pd_list);
 static LIST_HEAD(g_binding);
 static DEFINE_SPINLOCK(g_binding_lock);
@@ -794,12 +798,3 @@
 	return count;
 }
 
-void oz_polling_lock_bh(void)
-{
-	spin_lock_bh(&g_polling_lock);
-}
-
-void oz_polling_unlock_bh(void)
-{
-	spin_unlock_bh(&g_polling_lock);
-}
diff --git a/drivers/staging/ozwpan/ozproto.h b/drivers/staging/ozwpan/ozproto.h
index 0c49c8a..cb38e02 100644
--- a/drivers/staging/ozwpan/ozproto.h
+++ b/drivers/staging/ozwpan/ozproto.h
@@ -59,8 +59,6 @@
 void oz_timer_add(struct oz_pd *pd, int type, unsigned long due_time);
 void oz_timer_delete(struct oz_pd *pd, int type);
 void oz_pd_request_heartbeat(struct oz_pd *pd);
-void oz_polling_lock_bh(void);
-void oz_polling_unlock_bh(void);
 void oz_pd_heartbeat_handler(unsigned long data);
 void oz_pd_timeout_handler(unsigned long data);
 enum hrtimer_restart oz_pd_heartbeat_event(struct hrtimer *timer);
diff --git a/drivers/staging/panel/panel.c b/drivers/staging/panel/panel.c
index ec4b1fd..08f9a48 100644
--- a/drivers/staging/panel/panel.c
+++ b/drivers/staging/panel/panel.c
@@ -171,8 +171,8 @@
 
 	union {
 		struct {	/* valid when type == INPUT_TYPE_STD */
-			void (*press_fct) (int);
-			void (*release_fct) (int);
+			void (*press_fct)(int);
+			void (*release_fct)(int);
 			int press_data;
 			int release_data;
 		} std;
@@ -417,9 +417,9 @@
 static char lcd_left_shift;
 static char init_in_progress;
 
-static void (*lcd_write_cmd) (int);
-static void (*lcd_write_data) (int);
-static void (*lcd_clear_fast) (void);
+static void (*lcd_write_cmd)(int);
+static void (*lcd_write_data)(int);
+static void (*lcd_clear_fast)(void);
 
 static DEFINE_SPINLOCK(pprt_lock);
 static struct timer_list scan_timer;
@@ -457,14 +457,12 @@
 static int lcd_type = -1;
 module_param(lcd_type, int, 0000);
 MODULE_PARM_DESC(lcd_type,
-		 "LCD type: 0=none, 1=old //, 2=serial ks0074, "
-		 "3=hantronix //, 4=nexcom //, 5=compiled-in");
+		 "LCD type: 0=none, 1=old //, 2=serial ks0074, 3=hantronix //, 4=nexcom //, 5=compiled-in");
 
 static int lcd_proto = -1;
 module_param(lcd_proto, int, 0000);
 MODULE_PARM_DESC(lcd_proto,
-		"LCD communication: 0=parallel (//), 1=serial,"
-		"2=TI LCD Interface");
+		"LCD communication: 0=parallel (//), 1=serial, 2=TI LCD Interface");
 
 static int lcd_charset = -1;
 module_param(lcd_charset, int, 0000);
@@ -473,8 +471,7 @@
 static int keypad_type = -1;
 module_param(keypad_type, int, 0000);
 MODULE_PARM_DESC(keypad_type,
-		 "Keypad type: 0=none, 1=old 6 keys, 2=new 6+1 keys, "
-		 "3=nexcom 4 keys");
+		 "Keypad type: 0=none, 1=old 6 keys, 2=new 6+1 keys, 3=nexcom 4 keys");
 
 static int profile = DEFAULT_PROFILE;
 module_param(profile, int, 0000);
@@ -494,38 +491,32 @@
 static int lcd_e_pin  = PIN_NOT_SET;
 module_param(lcd_e_pin, int, 0000);
 MODULE_PARM_DESC(lcd_e_pin,
-		 "# of the // port pin connected to LCD 'E' signal, "
-		 "with polarity (-17..17)");
+		 "# of the // port pin connected to LCD 'E' signal, with polarity (-17..17)");
 
 static int lcd_rs_pin = PIN_NOT_SET;
 module_param(lcd_rs_pin, int, 0000);
 MODULE_PARM_DESC(lcd_rs_pin,
-		 "# of the // port pin connected to LCD 'RS' signal, "
-		 "with polarity (-17..17)");
+		 "# of the // port pin connected to LCD 'RS' signal, with polarity (-17..17)");
 
 static int lcd_rw_pin = PIN_NOT_SET;
 module_param(lcd_rw_pin, int, 0000);
 MODULE_PARM_DESC(lcd_rw_pin,
-		 "# of the // port pin connected to LCD 'RW' signal, "
-		 "with polarity (-17..17)");
+		 "# of the // port pin connected to LCD 'RW' signal, with polarity (-17..17)");
 
 static int lcd_bl_pin = PIN_NOT_SET;
 module_param(lcd_bl_pin, int, 0000);
 MODULE_PARM_DESC(lcd_bl_pin,
-		 "# of the // port pin connected to LCD backlight, "
-		 "with polarity (-17..17)");
+		 "# of the // port pin connected to LCD backlight, with polarity (-17..17)");
 
 static int lcd_da_pin = PIN_NOT_SET;
 module_param(lcd_da_pin, int, 0000);
 MODULE_PARM_DESC(lcd_da_pin,
-		 "# of the // port pin connected to serial LCD 'SDA' "
-		 "signal, with polarity (-17..17)");
+		 "# of the // port pin connected to serial LCD 'SDA' signal, with polarity (-17..17)");
 
 static int lcd_cl_pin = PIN_NOT_SET;
 module_param(lcd_cl_pin, int, 0000);
 MODULE_PARM_DESC(lcd_cl_pin,
-		 "# of the // port pin connected to serial LCD 'SCL' "
-		 "signal, with polarity (-17..17)");
+		 "# of the // port pin connected to serial LCD 'SCL' signal, with polarity (-17..17)");
 
 static const unsigned char *lcd_char_conv;
 
@@ -2017,9 +2008,9 @@
  * be bound.
  */
 static struct logical_input *panel_bind_callback(char *name,
-						 void (*press_fct) (int),
+						 void (*press_fct)(int),
 						 int press_data,
-						 void (*release_fct) (int),
+						 void (*release_fct)(int),
 						 int release_data)
 {
 	struct logical_input *callback;
diff --git a/drivers/staging/rtl8187se/Module.symvers b/drivers/staging/rtl8187se/Module.symvers
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/drivers/staging/rtl8187se/Module.symvers
diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211.h b/drivers/staging/rtl8187se/ieee80211/ieee80211.h
index 09ffd9b..4978b2b 100644
--- a/drivers/staging/rtl8187se/ieee80211/ieee80211.h
+++ b/drivers/staging/rtl8187se/ieee80211/ieee80211.h
@@ -709,10 +709,10 @@
 
 #define MAX_IE_LEN						0xFF //+YJ,080625
 
-typedef struct _CHANNEL_LIST{
-	u8	Channel[MAX_CHANNEL_NUMBER + 1];
-	u8	Len;
-}CHANNEL_LIST, *PCHANNEL_LIST;
+struct rtl8187se_channel_list {
+	u8	channel[MAX_CHANNEL_NUMBER + 1];
+	u8	len;
+};
 
 //by amy for ps
 #define IEEE80211_WATCH_DOG_TIME    2000
diff --git a/drivers/staging/rtl8187se/r8180.h b/drivers/staging/rtl8187se/r8180.h
index 8999ec6..5ac4673 100644
--- a/drivers/staging/rtl8187se/r8180.h
+++ b/drivers/staging/rtl8187se/r8180.h
@@ -1,19 +1,18 @@
 /*
-   This is part of rtl8180 OpenSource driver.
-   Copyright (C) Andrea Merello 2004-2005  <andrea.merello@gmail.com>
-   Released under the terms of GPL (General Public Licence)
-
-   Parts of this driver are based on the GPL part of the
-   official realtek driver
-
-   Parts of this driver are based on the rtl8180 driver skeleton
-   from Patric Schenke & Andres Salomon
-
-   Parts of this driver are based on the Intel Pro Wireless 2100 GPL driver
-
-   We want to thanks the Authors of those projects and the Ndiswrapper
-   project Authors.
-*/
+ * This is part of rtl8180 OpenSource driver.
+ * Copyright (C) Andrea Merello 2004-2005  <andrea.merello@gmail.com>
+ * Released under the terms of GPL (General Public Licence)
+ *
+ * Parts of this driver are based on the GPL part of the official realtek driver
+ *
+ * Parts of this driver are based on the rtl8180 driver skeleton from Patric
+ * Schenke & Andres Salomon
+ *
+ * Parts of this driver are based on the Intel Pro Wireless 2100 GPL driver
+ *
+ * We want to thanks the Authors of those projects and the Ndiswrapper project
+ * Authors.
+ */
 
 #ifndef R8180H
 #define R8180H
@@ -21,13 +20,13 @@
 #include <linux/interrupt.h>
 
 #define RTL8180_MODULE_NAME "r8180"
-#define DMESG(x,a...) printk(KERN_INFO RTL8180_MODULE_NAME ": " x "\n", ## a)
-#define DMESGW(x,a...) printk(KERN_WARNING RTL8180_MODULE_NAME ": WW:" x "\n", ## a)
-#define DMESGE(x,a...) printk(KERN_WARNING RTL8180_MODULE_NAME ": EE:" x "\n", ## a)
+#define DMESG(x, a...) printk(KERN_INFO RTL8180_MODULE_NAME ": " x "\n", ## a)
+#define DMESGW(x, a...) printk(KERN_WARNING RTL8180_MODULE_NAME ": WW:" x "\n", ## a)
+#define DMESGE(x, a...) printk(KERN_WARNING RTL8180_MODULE_NAME ": EE:" x "\n", ## a)
 
 #include <linux/module.h>
 #include <linux/kernel.h>
-//#include <linux/config.h>
+/* #include <linux/config.h> */
 #include <linux/ioport.h>
 #include <linux/sched.h>
 #include <linux/types.h>
@@ -36,22 +35,22 @@
 #include <linux/pci.h>
 #include <linux/etherdevice.h>
 #include <linux/delay.h>
-#include <linux/rtnetlink.h>	//for rtnl_lock()
+#include <linux/rtnetlink.h> /* for rtnl_lock() */
 #include <linux/wireless.h>
 #include <linux/timer.h>
-#include <linux/proc_fs.h>	// Necessary because we use the proc fs
+#include <linux/proc_fs.h> /* Necessary because we use the proc fs. */
 #include <linux/if_arp.h>
 #include "ieee80211/ieee80211.h"
 #include <asm/io.h>
-//#include <asm/semaphore.h>
+/* #include <asm/semaphore.h> */
 
 #define EPROM_93c46 0
 #define EPROM_93c56 1
 
-#define RTL_IOCTL_WPA_SUPPLICANT		SIOCIWFIRSTPRIV+30
+#define RTL_IOCTL_WPA_SUPPLICANT (SIOCIWFIRSTPRIV + 30)
 
 #define DEFAULT_FRAG_THRESHOLD 2342U
-#define MIN_FRAG_THRESHOLD     256U
+#define MIN_FRAG_THRESHOLD 256U
 #define DEFAULT_RTS_THRESHOLD 2342U
 #define MIN_RTS_THRESHOLD 0U
 #define MAX_RTS_THRESHOLD 2342U
@@ -60,14 +59,14 @@
 #define DEFAULT_RETRY_RTS 7
 #define DEFAULT_RETRY_DATA 7
 
-#define BEACON_QUEUE					6
+#define BEACON_QUEUE 6
 
-#define aSifsTime 	10
+#define aSifsTime 10
 
-#define sCrcLng         4
-#define sAckCtsLng	112		// bits in ACK and CTS frames
-//+by amy 080312
-#define RATE_ADAPTIVE_TIMER_PERIOD	300
+#define sCrcLng 4
+#define sAckCtsLng 112 /* bits in ACK and CTS frames. */
+/* +by amy 080312. */
+#define RATE_ADAPTIVE_TIMER_PERIOD 300
 
 typedef enum _WIRELESS_MODE {
 	WIRELESS_MODE_UNKNOWN = 0x00,
@@ -77,115 +76,111 @@
 	WIRELESS_MODE_AUTO = 0x08,
 } WIRELESS_MODE;
 
-typedef struct 	ChnlAccessSetting {
-	u16 SIFS_Timer;
-	u16 DIFS_Timer;
-	u16 SlotTimeTimer;
-	u16 EIFS_Timer;
-	u16 CWminIndex;
-	u16 CWmaxIndex;
-}*PCHANNEL_ACCESS_SETTING,CHANNEL_ACCESS_SETTING;
+struct chnl_access_setting {
+	u16 sifs_timer;
+	u16 difs_timer;
+	u16 slot_time_timer;
+	u16 eifs_timer;
+	u16 cwmin_index;
+	u16 cwmax_index;
+};
 
-typedef enum{
-        NIC_8185 = 1,
-        NIC_8185B
-        } nic_t;
+typedef enum {
+	NIC_8185 = 1,
+	NIC_8185B
+	} nic_t;
 
 typedef u32 AC_CODING;
-#define AC0_BE	0		// ACI: 0x00	// Best Effort
-#define AC1_BK	1		// ACI: 0x01	// Background
-#define AC2_VI	2		// ACI: 0x10	// Video
-#define AC3_VO	3		// ACI: 0x11	// Voice
-#define AC_MAX	4		// Max: define total number; Should not to be used as a real enum.
+#define AC0_BE	0 /* ACI: 0x00 */ /* Best Effort. */
+#define AC1_BK	1 /* ACI: 0x01 */ /* Background. */
+#define AC2_VI	2 /* ACI: 0x10 */ /* Video. */
+#define AC3_VO	3 /* ACI: 0x11 */ /* Voice. */
+#define AC_MAX	4 /* Max: define total number; Should not to be used as a real
+		   * enum.
+		   */
 
-//
-// ECWmin/ECWmax field.
-// Ref: WMM spec 2.2.2: WME Parameter Element, p.13.
-//
-typedef	union _ECW{
-	u8	charData;
-	struct
-	{
-		u8	ECWmin:4;
-		u8	ECWmax:4;
-	}f;	// Field
-}ECW, *PECW;
+/*
+ * ECWmin/ECWmax field.
+ * Ref: WMM spec 2.2.2: WME Parameter Element, p.13.
+ */
+typedef union _ECW {
+	u8 charData;
+	struct {
+		u8 ECWmin:4;
+		u8 ECWmax:4;
+	} f;	/* Field */
+} ECW, *PECW;
 
-//
-// ACI/AIFSN Field.
-// Ref: WMM spec 2.2.2: WME Parameter Element, p.12.
-//
-typedef	union _ACI_AIFSN{
-	u8	charData;
+/*
+ * ACI/AIFSN Field. Ref: WMM spec 2.2.2: WME Parameter Element, p.12.
+ */
+typedef union _ACI_AIFSN {
+	u8 charData;
 
-	struct
-	{
-		u8	AIFSN:4;
-		u8	ACM:1;
-		u8	ACI:2;
-		u8	Reserved:1;
-	}f;	// Field
-}ACI_AIFSN, *PACI_AIFSN;
+	struct {
+		u8 AIFSN:4;
+		u8 ACM:1;
+		u8 ACI:2;
+		u8 Reserved:1;
+	} f;	/* Field */
+} ACI_AIFSN, *PACI_AIFSN;
 
-//
-// AC Parameters Record Format.
-// Ref: WMM spec 2.2.2: WME Parameter Element, p.12.
-//
-typedef	union _AC_PARAM{
-	u32	longData;
-	u8	charData[4];
+/*
+ * AC Parameters Record Format.
+ * Ref: WMM spec 2.2.2: WME Parameter Element, p.12.
+ */
+typedef union _AC_PARAM {
+	u32 longData;
+	u8 charData[4];
 
-	struct
-	{
-		ACI_AIFSN	AciAifsn;
-		ECW		Ecw;
-		u16		TXOPLimit;
-	}f;	// Field
-}AC_PARAM, *PAC_PARAM;
+	struct {
+		ACI_AIFSN AciAifsn;
+		ECW Ecw;
+		u16 TXOPLimit;
+	} f;	/* Field */
+} AC_PARAM, *PAC_PARAM;
 
 /* it is a wrong definition. -xiong-2006-11-17
-typedef struct ThreeWireReg {
-	u16	longData;
-	struct {
-		u8	enableB;
-		u8	data;
-		u8	clk;
-		u8	read_write;
+ * typedef struct ThreeWireReg {
+ *	u16	longData;
+ *	struct {
+ *		u8 enableB;
+ *		u8 data;
+ *		u8 clk;
+ *		u8 read_write;
+ *	} struc;
+ * } ThreeWireReg;
+ */
+
+typedef union _ThreeWire {
+	struct _ThreeWireStruc {
+		u16 data:1;
+		u16 clk:1;
+		u16 enableB:1;
+		u16 read_write:1;
+		u16 resv1:12;
+		/* u2Byte resv2:14; */
+		/* u2Byte ThreeWireEnable:1; */
+		/* u2Byte resv3:1; */
 	} struc;
+	u16 longData;
 } ThreeWireReg;
-*/
-
-typedef	union _ThreeWire{
-	struct _ThreeWireStruc{
-		u16		data:1;
-		u16		clk:1;
-		u16		enableB:1;
-		u16		read_write:1;
-		u16		resv1:12;
-//		u2Byte	resv2:14;
-//		u2Byte	ThreeWireEnable:1;
-//		u2Byte	resv3:1;
-	}struc;
-	u16			longData;
-}ThreeWireReg;
 
 
-typedef struct buffer
-{
+typedef struct buffer {
 	struct buffer *next;
 	u32 *buf;
 	dma_addr_t dma;
 } buffer;
 
-//YJ,modified,080828
-typedef struct Stats
-{
+/* YJ,modified,080828. */
+struct stats {
 	unsigned long txrdu;
 	unsigned long rxrdu;
 	unsigned long rxnolast;
 	unsigned long rxnodata;
-//	unsigned long rxreset;
-//	unsigned long rxwrkaround;
+	/* unsigned long rxreset; */
+	/* unsigned long rxwrkaround; */
 	unsigned long rxnopointer;
 	unsigned long txnperr;
 	unsigned long txresumed;
@@ -207,52 +202,59 @@
 	unsigned long txbeaconerr;
 	unsigned long txlpokint;
 	unsigned long txlperr;
-	unsigned long txretry;//retry number  tony 20060601
-	unsigned long rxcrcerrmin;//crc error (0-500)
-	unsigned long rxcrcerrmid;//crc error (500-1000)
-	unsigned long rxcrcerrmax;//crc error (>1000)
-	unsigned long rxicverr;//ICV error
-} Stats;
+	unsigned long txretry; /* retry number tony 20060601 */
+	unsigned long rxcrcerrmin; /* crc error (0-500) */
+	unsigned long rxcrcerrmid; /* crc error (500-1000) */
+	unsigned long rxcrcerrmax; /* crc error (>1000) */
+	unsigned long rxicverr; /* ICV error */
+};
 
 #define MAX_LD_SLOT_NUM 10
-#define KEEP_ALIVE_INTERVAL 				20 // in seconds.
-#define CHECK_FOR_HANG_PERIOD			2 //be equal to watchdog check time
-#define DEFAULT_KEEP_ALIVE_LEVEL			1
-#define DEFAULT_SLOT_NUM					2
-#define POWER_PROFILE_AC					0
-#define POWER_PROFILE_BATTERY			1
+#define KEEP_ALIVE_INTERVAL 20 /* in seconds. */
+#define CHECK_FOR_HANG_PERIOD 2 /* be equal to watchdog check time. */
+#define DEFAULT_KEEP_ALIVE_LEVEL 1
+#define DEFAULT_SLOT_NUM 2
+#define POWER_PROFILE_AC 0
+#define POWER_PROFILE_BATTERY 1
 
-typedef struct _link_detect_t
-{
-	u32				RxFrameNum[MAX_LD_SLOT_NUM];	// number of Rx Frame / CheckForHang_period  to determine link status
-	u16				SlotNum;	// number of CheckForHang period to determine link status, default is 2
-	u16				SlotIndex;
+struct link_detect_t {
+	u32 rx_frame_num[MAX_LD_SLOT_NUM]; /* number of Rx Frame.
+					    * CheckForHang_period  to determine
+					    * link status.
+					    */
+	u16 slot_num; /* number of CheckForHang period to determine link status,
+		       * default is 2.
+		       */
+	u16 slot_index;
+	u32 num_tx_ok_in_period; /* number of packet transmitted during
+				  * CheckForHang.
+				  */
+	u32 num_rx_ok_in_period; /* number of packet received during
+				  * CheckForHang.
+				  */
+	u8 idle_count; /* (KEEP_ALIVE_INTERVAL / CHECK_FOR_HANG_PERIOD) */
+	u32 last_num_tx_unicast;
+	u32 last_num_rx_unicast;
 
-	u32				NumTxOkInPeriod;  //number of packet transmitted during CheckForHang
-	u32				NumRxOkInPeriod;  //number of packet received during CheckForHang
+	bool b_busy_traffic; /* when it is set to 1, UI cann't scan at will. */
+};
 
-	u8				IdleCount;     // (KEEP_ALIVE_INTERVAL / CHECK_FOR_HANG_PERIOD)
-	u32				LastNumTxUnicast;
-	u32				LastNumRxUnicast;
+/* YJ,modified,080828,end */
 
-	bool				bBusyTraffic;    //when it is set to 1, UI cann't scan at will.
-}link_detect_t, *plink_detect_t;
-
-//YJ,modified,080828,end
-
-//by amy for led
-//================================================================================
-// LED customization.
-//================================================================================
-
-typedef	enum _LED_STRATEGY_8185{
-	SW_LED_MODE0, //
-	SW_LED_MODE1, //
-	HW_LED, // HW control 2 LEDs, LED0 and LED1 (there are 4 different control modes)
-}LED_STRATEGY_8185, *PLED_STRATEGY_8185;
-//by amy for led
-//by amy for power save
-typedef	enum _LED_CTL_MODE{
+/* by amy for led
+ * ==========================================================================
+ * LED customization.
+ * ==========================================================================
+ */
+typedef enum _LED_STRATEGY_8185 {
+	SW_LED_MODE0,
+	SW_LED_MODE1,
+	HW_LED, /* HW control 2 LEDs, LED0 and LED1 (there are 4 different
+		 * control modes). */
+} LED_STRATEGY_8185, *PLED_STRATEGY_8185;
+/* by amy for led. */
+/* by amy for power save. */
+typedef enum _LED_CTL_MODE {
 	LED_CTL_POWER_ON = 1,
 	LED_CTL_LINK = 2,
 	LED_CTL_NO_LINK = 3,
@@ -260,73 +262,74 @@
 	LED_CTL_RX = 5,
 	LED_CTL_SITE_SURVEY = 6,
 	LED_CTL_POWER_OFF = 7
-}LED_CTL_MODE;
+} LED_CTL_MODE;
 
-typedef	enum _RT_RF_POWER_STATE
-{
+typedef enum _RT_RF_POWER_STATE {
 	eRfOn,
 	eRfSleep,
 	eRfOff
-}RT_RF_POWER_STATE;
+} RT_RF_POWER_STATE;
 
-enum	_ReasonCode{
-	unspec_reason	= 0x1,
-	auth_not_valid	= 0x2,
-	deauth_lv_ss	= 0x3,
-	inactivity		= 0x4,
-	ap_overload		= 0x5,
-	class2_err		= 0x6,
-	class3_err		= 0x7,
-	disas_lv_ss		= 0x8,
-	asoc_not_auth	= 0x9,
+enum _ReasonCode {
+	unspec_reason = 0x1,
+	auth_not_valid = 0x2,
+	deauth_lv_ss = 0x3,
+	inactivity = 0x4,
+	ap_overload = 0x5,
+	class2_err = 0x6,
+	class3_err = 0x7,
+	disas_lv_ss = 0x8,
+	asoc_not_auth = 0x9,
 
-	//----MIC_CHECK
-	mic_failure		= 0xe,
-	//----END MIC_CHECK
+	/* ----MIC_CHECK */
+	mic_failure = 0xe,
+	/* ----END MIC_CHECK */
 
-	// Reason code defined in 802.11i D10.0 p.28.
-	invalid_IE		= 0x0d,
-	four_way_tmout	= 0x0f,
-	two_way_tmout	= 0x10,
-	IE_dismatch		= 0x11,
+	/* Reason code defined in 802.11i D10.0 p.28. */
+	invalid_IE = 0x0d,
+	four_way_tmout = 0x0f,
+	two_way_tmout = 0x10,
+	IE_dismatch = 0x11,
 	invalid_Gcipher	= 0x12,
 	invalid_Pcipher	= 0x13,
-	invalid_AKMP	= 0x14,
+	invalid_AKMP = 0x14,
 	unsup_RSNIEver = 0x15,
-	invalid_RSNIE	= 0x16,
-	auth_802_1x_fail= 0x17,
-	ciper_reject		= 0x18,
+	invalid_RSNIE = 0x16,
+	auth_802_1x_fail = 0x17,
+	ciper_reject = 0x18,
 
-	// Reason code defined in 7.3.1.7, 802.1e D13.0, p.42. Added by Annie, 2005-11-15.
-	QoS_unspec		= 0x20,	// 32
-	QAP_bandwidth	= 0x21,	// 33
-	poor_condition	= 0x22,	// 34
-	no_facility		= 0x23,	// 35
-							// Where is 36???
-	req_declined	= 0x25,	// 37
-	invalid_param	= 0x26,	// 38
-	req_not_honored= 0x27,	// 39
-	TS_not_created	= 0x2F,	// 47
-	DL_not_allowed	= 0x30,	// 48
-	dest_not_exist	= 0x31,	// 49
-	dest_not_QSTA	= 0x32,	// 50
+	/* Reason code defined in 7.3.1.7, 802.1e D13.0, p.42. Added by Annie,
+	 * 2005-11-15.
+	 */
+	QoS_unspec = 0x20, /* 32 */
+	QAP_bandwidth = 0x21, /* 33 */
+	poor_condition = 0x22, /* 34 */
+	no_facility = 0x23, /* 35 */
+	/* Where is 36??? */
+	req_declined = 0x25, /* 37 */
+	invalid_param = 0x26, /* 38 */
+	req_not_honored = 0x27, /* 39 */
+	TS_not_created = 0x2F, /* 47 */
+	DL_not_allowed = 0x30, /* 48 */
+	dest_not_exist = 0x31, /* 49 */
+	dest_not_QSTA = 0x32, /* 50 */
 };
-typedef	enum _RT_PS_MODE
-{
-	eActive,	// Active/Continuous access.
-	eMaxPs,		// Max power save mode.
-	eFastPs		// Fast power save mode.
-}RT_PS_MODE;
-//by amy for power save
-typedef struct r8180_priv
-{
+
+typedef enum _RT_PS_MODE {
+	eActive, /* Active/Continuous access. */
+	eMaxPs,	/* Max power save mode. */
+	eFastPs /* Fast power save mode. */
+} RT_PS_MODE;
+
+/* by amy for power save. */
+typedef struct r8180_priv {
 	struct pci_dev *pdev;
 
 	short epromtype;
 	int irq;
 	struct ieee80211_device *ieee80211;
 
-	short plcp_preamble_mode; // 0:auto 1:short 2:long
+	short plcp_preamble_mode; /* 0:auto 1:short 2:long */
 
 	spinlock_t irq_th_lock;
 	spinlock_t tx_lock;
@@ -339,19 +342,20 @@
 	short chan;
 	short sens;
 	short max_sens;
-	u8 chtxpwr[15]; //channels from 1 to 14, 0 not used
-	u8 chtxpwr_ofdm[15]; //channels from 1 to 14, 0 not used
-	//u8 challow[15]; //channels from 1 to 14, 0 not used
-	u8 channel_plan;  // it's the channel plan index
+	u8 chtxpwr[15]; /* channels from 1 to 14, 0 not used. */
+	u8 chtxpwr_ofdm[15]; /* channels from 1 to 14, 0 not used. */
+	/* u8 challow[15]; */ /* channels from 1 to 14, 0 not used. */
+	u8 channel_plan;  /* it's the channel plan index. */
 	short up;
-	short crcmon; //if 1 allow bad crc frame reception in monitor mode
+	short crcmon; /* if 1 allow bad crc frame reception in monitor mode. */
 
 	struct timer_list scan_timer;
-	/*short scanpending;
-	short stopscan;*/
+	/* short scanpending;
+	 * short stopscan;
+	 */
 	spinlock_t scan_lock;
 	u8 active_probe;
-	//u8 active_scan_num;
+	/* u8 active_scan_num; */
 	struct semaphore wx_sem;
 	short hw_wep;
 
@@ -359,20 +363,20 @@
 	short antb;
 	short diversity;
 	u32 key0[4];
-	short (*rf_set_sens)(struct net_device *dev,short sens);
-	void (*rf_set_chan)(struct net_device *dev,short ch);
+	short (*rf_set_sens)(struct net_device *dev, short sens);
+	void (*rf_set_chan)(struct net_device *dev, short ch);
 	void (*rf_close)(struct net_device *dev);
 	void (*rf_init)(struct net_device *dev);
 	void (*rf_sleep)(struct net_device *dev);
 	void (*rf_wakeup)(struct net_device *dev);
-	//short rate;
+	/* short rate; */
 	short promisc;
-	/*stats*/
-	struct Stats stats;
-	struct _link_detect_t link_detect;  //YJ,add,080828
+	/* stats */
+	struct stats stats;
+	struct link_detect_t link_detect; /* YJ,add,080828 */
 	struct iw_statistics wstats;
 
-	/*RX stuff*/
+	/* RX stuff. */
 	u32 *rxring;
 	u32 *rxringtail;
 	dma_addr_t rxringdma;
@@ -387,27 +391,27 @@
 
 	u32 rx_prevlen;
 
-	/*TX stuff*/
-/*
-	u32 *txlpring;
-	u32 *txhpring;
-	u32 *txnpring;
-	dma_addr_t txlpringdma;
-	dma_addr_t txhpringdma;
-	dma_addr_t txnpringdma;
-	u32 *txlpringtail;
-	u32 *txhpringtail;
-	u32 *txnpringtail;
-	u32 *txlpringhead;
-	u32 *txhpringhead;
-	u32 *txnpringhead;
-	struct buffer *txlpbufs;
-	struct buffer *txhpbufs;
-	struct buffer *txnpbufs;
-	struct buffer *txlpbufstail;
-	struct buffer *txhpbufstail;
-	struct buffer *txnpbufstail;
-*/
+	/* TX stuff */
+	/*
+	 * u32 *txlpring;
+	 * u32 *txhpring;
+	 * u32 *txnpring;
+	 * dma_addr_t txlpringdma;
+	 * dma_addr_t txhpringdma;
+	 * dma_addr_t txnpringdma;
+	 * u32 *txlpringtail;
+	 * u32 *txhpringtail;
+	 * u32 *txnpringtail;
+	 * u32 *txlpringhead;
+	 * u32 *txhpringhead;
+	 * u32 *txnpringhead;
+	 * struct buffer *txlpbufs;
+	 * struct buffer *txhpbufs;
+	 * struct buffer *txnpbufs;
+	 * struct buffer *txlpbufstail;
+	 * struct buffer *txhpbufstail;
+	 * struct buffer *txnpbufstail;
+	 */
 	u32 *txmapring;
 	u32 *txbkpring;
 	u32 *txbepring;
@@ -447,54 +451,56 @@
 
 	int txringcount;
 	int txbuffsize;
-	//struct tx_pendingbuf txnp_pending;
-	//struct tasklet_struct irq_tx_tasklet;
+	/* struct tx_pendingbuf txnp_pending; */
+	/* struct tasklet_struct irq_tx_tasklet; */
 	struct tasklet_struct irq_rx_tasklet;
 	u8 dma_poll_mask;
-	//short tx_suspend;
+	/* short tx_suspend; */
 
-	/* adhoc/master mode stuff */
+	/* adhoc/master mode stuff. */
 	u32 *txbeaconringtail;
 	dma_addr_t txbeaconringdma;
 	u32 *txbeaconring;
 	int txbeaconcount;
 	struct buffer *txbeaconbufs;
 	struct buffer *txbeaconbufstail;
-	//char *master_essid;
-	//u16 master_beaconinterval;
-	//u32 master_beaconsize;
-	//u16 beacon_interval;
+	/* char *master_essid; */
+	/* u16 master_beaconinterval; */
+	/* u32 master_beaconsize; */
+	/* u16 beacon_interval; */
 
 	u8 retry_data;
 	u8 retry_rts;
 	u16 rts;
 
-//by amy for led
+	/* by amy for led. */
 	LED_STRATEGY_8185 LedStrategy;
-//by amy for led
+	/* by amy for led. */
 
-//by amy for power save
+	/* by amy for power save. */
 	struct timer_list watch_dog_timer;
 	bool bInactivePs;
 	bool bSwRfProcessing;
-	RT_RF_POWER_STATE	eInactivePowerState;
+	RT_RF_POWER_STATE eInactivePowerState;
 	RT_RF_POWER_STATE eRFPowerState;
 	u32 RfOffReason;
 	bool RFChangeInProgress;
 	bool SetRFPowerStateInProgress;
-	u8   RFProgType;
+	u8 RFProgType;
 	bool bLeisurePs;
 	RT_PS_MODE dot11PowerSaveMode;
-	//u32 NumRxOkInPeriod;   //YJ,del,080828
-	//u32 NumTxOkInPeriod;   //YJ,del,080828
-	u8   TxPollingTimes;
+	/* u32 NumRxOkInPeriod;*/ /* YJ,del,080828 */
+	/* u32 NumTxOkInPeriod;*/ /* YJ,del,080828 */
+	u8 TxPollingTimes;
 
-	bool	bApBufOurFrame;// TRUE if AP buffer our unicast data , we will keep eAwake until receive data or timeout.
-	u8	WaitBufDataBcnCount;
-	u8	WaitBufDataTimeOut;
+	bool bApBufOurFrame; /* TRUE if AP buffer our unicast data , we will
+			      * keep eAwake until receive data or timeout.
+			      */
+	u8 WaitBufDataBcnCount;
+	u8 WaitBufDataTimeOut;
 
-//by amy for power save
-//by amy for antenna
+	/* by amy for power save. */
+	/* by amy for antenna. */
 	u8 EEPROMSwAntennaDiversity;
 	bool EEPROMDefaultAntenna1;
 	u8 RegSwAntennaDiversityMechanism;
@@ -503,115 +509,133 @@
 	bool bDefaultAntenna1;
 	u8 SignalStrength;
 	long Stats_SignalStrength;
-	long LastSignalStrengthInPercent; // In percentage, used for smoothing, e.g. Moving Average.
-	u8	 SignalQuality; // in 0-100 index.
+	long LastSignalStrengthInPercent; /* In percentage, used for smoothing,
+					   * e.g. Moving Average.
+					   */
+	u8 SignalQuality; /* in 0-100 index. */
 	long Stats_SignalQuality;
-	long RecvSignalPower; // in dBm.
+	long RecvSignalPower; /* in dBm. */
 	long Stats_RecvSignalPower;
-	u8	 LastRxPktAntenna;	// +by amy 080312 Antenna which received the lasted packet. 0: Aux, 1:Main. Added by Roger, 2008.01.25.
+	u8 LastRxPktAntenna; /* +by amy 080312 Antenna which received the lasted
+			      * packet. 0: Aux, 1:Main. Added by Roger,
+			      * 2008.01.25.
+			      */
 	u32 AdRxOkCnt;
 	long AdRxSignalStrength;
-	u8 CurrAntennaIndex;			// Index to current Antenna (both Tx and Rx).
-	u8 AdTickCount;				// Times of SwAntennaDiversityTimer happened.
-	u8 AdCheckPeriod;				// # of period SwAntennaDiversityTimer to check Rx signal strength for SW Antenna Diversity.
-	u8 AdMinCheckPeriod;			// Min value of AdCheckPeriod.
-	u8 AdMaxCheckPeriod;			// Max value of AdCheckPeriod.
-	long AdRxSsThreshold;			// Signal strength threshold to switch antenna.
-	long AdMaxRxSsThreshold;			// Max value of AdRxSsThreshold.
-	bool bAdSwitchedChecking;		// TRUE if we shall shall check Rx signal strength for last time switching antenna.
-	long AdRxSsBeforeSwitched;		// Rx signal strength before we switched antenna.
+	u8 CurrAntennaIndex; /* Index to current Antenna (both Tx and Rx). */
+	u8 AdTickCount; /* Times of SwAntennaDiversityTimer happened. */
+	u8 AdCheckPeriod; /* # of period SwAntennaDiversityTimer to check Rx
+			   * signal strength for SW Antenna Diversity.
+			   */
+	u8 AdMinCheckPeriod; /* Min value of AdCheckPeriod. */
+	u8 AdMaxCheckPeriod; /* Max value of AdCheckPeriod. */
+	long AdRxSsThreshold; /* Signal strength threshold to switch antenna. */
+	long AdMaxRxSsThreshold; /* Max value of AdRxSsThreshold. */
+	bool bAdSwitchedChecking; /* TRUE if we shall shall check Rx signal
+				   * strength for last time switching antenna.
+				   */
+	long AdRxSsBeforeSwitched; /* Rx signal strength before we switched
+				    * antenna.
+				    */
 	struct timer_list SwAntennaDiversityTimer;
-//by amy for antenna
-//{by amy 080312
-//
-	// Crystal calibration.
-	// Added by Roger, 2007.12.11.
-	//
-	bool		bXtalCalibration; // Crystal calibration.
-	u8			XtalCal_Xin; // Crystal calibration for Xin. 0~7.5pF
-	u8			XtalCal_Xout; // Crystal calibration for Xout. 0~7.5pF
-	//
-	// Tx power tracking with thermal meter indication.
-	// Added by Roger, 2007.12.11.
-	//
-	bool		bTxPowerTrack; // Tx Power tracking.
-	u8			ThermalMeter; // Thermal meter reference indication.
-	//
-	// Dynamic Initial Gain Adjustment Mechanism. Added by Bruce, 2007-02-14.
-	//
-	bool				bDigMechanism; // TRUE if DIG is enabled, FALSE ow.
-	bool				bRegHighPowerMechanism; // For High Power Mechanism. 061010, by rcnjko.
-	u32					FalseAlarmRegValue;
-	u8					RegDigOfdmFaUpTh; // Upper threshold of OFDM false alarm, which is used in DIG.
-	u8					DIG_NumberFallbackVote;
-	u8					DIG_NumberUpgradeVote;
-	// For HW antenna diversity, added by Roger, 2008.01.30.
-	u32			AdMainAntennaRxOkCnt;		// Main antenna Rx OK count.
-	u32			AdAuxAntennaRxOkCnt;		// Aux antenna Rx OK count.
-	bool		bHWAdSwitched;				// TRUE if we has switched default antenna by HW evaluation.
-	// RF High Power upper/lower threshold.
-	u8					RegHiPwrUpperTh;
-	u8					RegHiPwrLowerTh;
-	// RF RSSI High Power upper/lower Threshold.
-	u8					RegRSSIHiPwrUpperTh;
-	u8					RegRSSIHiPwrLowerTh;
-	// Current CCK RSSI value to determine CCK high power, asked by SD3 DZ, by Bruce, 2007-04-12.
-	u8			CurCCKRSSI;
-	bool        bCurCCKPkt;
-	//
-	// High Power Mechanism. Added by amy, 080312.
-	//
-	bool					bToUpdateTxPwr;
-	long					UndecoratedSmoothedSS;
-	long					UndercorateSmoothedRxPower;
-	u8						RSSI;
-	char					RxPower;
-	 u8 InitialGain;
-	 //For adjust Dig Threshold during Legacy/Leisure Power Save Mode
-	u32				DozePeriodInPast2Sec;
-	 // Don't access BB/RF under disable PLL situation.
-	u8					InitialGainBackUp;
-	 u8 RegBModeGainStage;
-//by amy for rate adaptive
-    struct timer_list rateadapter_timer;
-	u32    RateAdaptivePeriod;
-	bool   bEnhanceTxPwr;
-	bool   bUpdateARFR;
-	int	   ForcedDataRate; // Force Data Rate. 0: Auto, 0x02: 1M ~ 0x6C: 54M.)
-	u32     NumTxUnicast; //YJ,add,080828,for keep alive
-	u8      keepAliveLevel; //YJ,add,080828,for KeepAlive
-	unsigned long 	NumTxOkTotal;
-	u16                                 LastRetryCnt;
-        u16                                     LastRetryRate;
-        unsigned long       LastTxokCnt;
-        unsigned long           LastRxokCnt;
-        u16                                     CurrRetryCnt;
-        unsigned long           LastTxOKBytes;
-	unsigned long 		    NumTxOkBytesTotal;
-        u8                          LastFailTxRate;
-        long                        LastFailTxRateSS;
-        u8                          FailTxRateCount;
-        u32                         LastTxThroughput;
-        //for up rate
-        unsigned short          bTryuping;
-        u8                                      CurrTxRate;     //the rate before up
-        u16                                     CurrRetryRate;
-        u16                                     TryupingCount;
-        u8                                      TryDownCountLowData;
-        u8                                      TryupingCountNoData;
+	/* by amy for antenna {by amy 080312 */
 
-        u8                  CurrentOperaRate;
-//by amy for rate adaptive
-//by amy 080312}
-//	short wq_hurryup;
-//	struct workqueue_struct *workqueue;
+	/* Crystal calibration. Added by Roger, 2007.12.11. */
+
+	bool bXtalCalibration; /* Crystal calibration.*/
+	u8 XtalCal_Xin; /* Crystal calibration for Xin. 0~7.5pF */
+	u8 XtalCal_Xout; /* Crystal calibration for Xout. 0~7.5pF */
+
+	/* Tx power tracking with thermal meter indication.
+	 * Added by Roger, 2007.12.11.
+	 */
+
+	bool bTxPowerTrack; /* Tx Power tracking. */
+	u8 ThermalMeter; /* Thermal meter reference indication. */
+
+	/* Dynamic Initial Gain Adjustment Mechanism. Added by Bruce,
+	 * 2007-02-14.
+	 */
+	bool bDigMechanism; /* TRUE if DIG is enabled, FALSE ow. */
+	bool bRegHighPowerMechanism; /* For High Power Mechanism. 061010,
+				      * by rcnjko.
+				      */
+	u32 FalseAlarmRegValue;
+	u8 RegDigOfdmFaUpTh; /* Upper threshold of OFDM false alarm, which is
+			      * used in DIG.
+			      */
+	u8 DIG_NumberFallbackVote;
+	u8 DIG_NumberUpgradeVote;
+	/* For HW antenna diversity, added by Roger, 2008.01.30. */
+	u32 AdMainAntennaRxOkCnt; /* Main antenna Rx OK count. */
+	u32 AdAuxAntennaRxOkCnt; /* Aux antenna Rx OK count. */
+	bool bHWAdSwitched; /* TRUE if we has switched default antenna by HW
+			     * evaluation.
+			     */
+	/* RF High Power upper/lower threshold. */
+	u8 RegHiPwrUpperTh;
+	u8 RegHiPwrLowerTh;
+	/* RF RSSI High Power upper/lower Threshold. */
+	u8 RegRSSIHiPwrUpperTh;
+	u8 RegRSSIHiPwrLowerTh;
+	/* Current CCK RSSI value to determine CCK high power, asked by SD3 DZ,
+	 * by Bruce, 2007-04-12.
+	 */
+	u8 CurCCKRSSI;
+	bool bCurCCKPkt;
+	/* High Power Mechanism. Added by amy, 080312. */
+	bool bToUpdateTxPwr;
+	long UndecoratedSmoothedSS;
+	long UndecoratedSmoothedRxPower;
+	u8 RSSI;
+	char RxPower;
+	u8 InitialGain;
+	/* For adjust Dig Threshold during Legacy/Leisure Power Save Mode. */
+	u32 DozePeriodInPast2Sec;
+	/* Don't access BB/RF under disable PLL situation. */
+	u8 InitialGainBackUp;
+	u8 RegBModeGainStage;
+	/* by amy for rate adaptive */
+	struct timer_list rateadapter_timer;
+	u32 RateAdaptivePeriod;
+	bool bEnhanceTxPwr;
+	bool bUpdateARFR;
+	int ForcedDataRate; /* Force Data Rate. 0: Auto, 0x02: 1M ~ 0x6C: 54M.)
+			     */
+	u32 NumTxUnicast; /* YJ,add,080828,for keep alive. */
+	u8 keepAliveLevel; /*YJ,add,080828,for KeepAlive. */
+	unsigned long NumTxOkTotal;
+	u16 LastRetryCnt;
+	u16 LastRetryRate;
+	unsigned long LastTxokCnt;
+	unsigned long LastRxokCnt;
+	u16 CurrRetryCnt;
+	unsigned long LastTxOKBytes;
+	unsigned long NumTxOkBytesTotal;
+	u8 LastFailTxRate;
+	long LastFailTxRateSS;
+	u8 FailTxRateCount;
+	u32 LastTxThroughput;
+	/* for up rate. */
+	unsigned short bTryuping;
+	u8 CurrTxRate; /* the rate before up. */
+	u16 CurrRetryRate;
+	u16 TryupingCount;
+	u8 TryDownCountLowData;
+	u8 TryupingCountNoData;
+
+	u8 CurrentOperaRate;
+	/* by amy for rate adaptive. */
+	/* by amy 080312} */
+	/* short wq_hurryup; */
+	/* struct workqueue_struct *workqueue; */
 	struct work_struct reset_wq;
 	struct work_struct watch_dog_wq;
 	short ack_tx_to_ieee;
 
 	u8 dma_poll_stop_mask;
 
-	//u8 RegThreeWireMode;
+	/* u8 RegThreeWireMode; */
 	u16 ShortRetryLimit;
 	u16 LongRetryLimit;
 	u16 EarlyRxThreshold;
@@ -619,8 +643,8 @@
 	u32 ReceiveConfig;
 	u32 IntrMask;
 
-	struct 	ChnlAccessSetting  ChannelAccessSetting;
-}r8180_priv;
+	struct chnl_access_setting ChannelAccessSetting;
+} r8180_priv;
 
 #define MANAGE_PRIORITY 0
 #define BK_PRIORITY 1
@@ -632,7 +656,7 @@
 
 #define LOW_PRIORITY VI_PRIORITY
 #define NORM_PRIORITY VO_PRIORITY
-//AC2Queue mapping
+/* AC2Queue mapping. */
 #define AC2Q(_ac) (((_ac) == WME_AC_VO) ? VO_PRIORITY : \
 		((_ac) == WME_AC_VI) ? VI_PRIORITY : \
 		((_ac) == WME_AC_BK) ? BK_PRIORITY : \
@@ -673,7 +697,7 @@
 bool SetAntennaConfig87SE(struct net_device *dev, u8 DefaultAnt,
 			  bool bAntDiversity);
 
-//#ifdef CONFIG_RTL8185B
+/* #ifdef CONFIG_RTL8185B */
 void rtl8185b_adapter_start(struct net_device *dev);
 void rtl8185b_rx_enable(struct net_device *dev);
 void rtl8185b_tx_enable(struct net_device *dev);
@@ -682,8 +706,8 @@
 void fix_rx_fifo(struct net_device *dev);
 void fix_tx_fifo(struct net_device *dev);
 void rtl8225z2_SetTXPowerLevel(struct net_device *dev, short ch);
-void rtl8180_rate_adapter(struct work_struct * work);
-//#endif
+void rtl8180_rate_adapter(struct work_struct *work);
+/* #endif */
 bool MgntActSet_RF_State(struct net_device *dev, RT_RF_POWER_STATE StateToSet,
 			 u32 ChangeSource);
 
diff --git a/drivers/staging/rtl8187se/r8180_core.c b/drivers/staging/rtl8187se/r8180_core.c
index 6cafee2..dc434b8 100644
--- a/drivers/staging/rtl8187se/r8180_core.c
+++ b/drivers/staging/rtl8187se/r8180_core.c
@@ -1,31 +1,31 @@
 /*
-   This is part of rtl818x pci OpenSource driver - v 0.1
-   Copyright (C) Andrea Merello 2004-2005  <andrea.merello@gmail.com>
-   Released under the terms of GPL (General Public License)
-
-   Parts of this driver are based on the GPL part of the official
-   Realtek driver.
-
-   Parts of this driver are based on the rtl8180 driver skeleton
-   from Patric Schenke & Andres Salomon.
-
-   Parts of this driver are based on the Intel Pro Wireless 2100 GPL driver.
-
-   Parts of BB/RF code are derived from David Young rtl8180 netbsd driver.
-
-   RSSI calc function from 'The Deuce'
-
-   Some ideas borrowed from the 8139too.c driver included in linux kernel.
-
-   We (I?) want to thanks the Authors of those projecs and also the
-   Ndiswrapper's project Authors.
-
-   A big big thanks goes also to Realtek corp. for their help in my attempt to
-   add RTL8185 and RTL8225 support, and to David Young also.
-
-   Power management interface routines.
-   Written by Mariusz Matuszek.
-*/
+ * This is part of rtl818x pci OpenSource driver - v 0.1
+ * Copyright (C) Andrea Merello 2004-2005  <andrea.merello@gmail.com>
+ * Released under the terms of GPL (General Public License)
+ *
+ * Parts of this driver are based on the GPL part of the official
+ * Realtek driver.
+ *
+ * Parts of this driver are based on the rtl8180 driver skeleton
+ * from Patric Schenke & Andres Salomon.
+ *
+ * Parts of this driver are based on the Intel Pro Wireless 2100 GPL driver.
+ *
+ * Parts of BB/RF code are derived from David Young rtl8180 netbsd driver.
+ *
+ * RSSI calc function from 'The Deuce'
+ *
+ * Some ideas borrowed from the 8139too.c driver included in linux kernel.
+ *
+ * We (I?) want to thanks the Authors of those projecs and also the
+ * Ndiswrapper's project Authors.
+ *
+ * A big big thanks goes also to Realtek corp. for their help in my attempt to
+ * add RTL8185 and RTL8225 support, and to David Young also.
+ *
+ * Power management interface routines.
+ * Written by Mariusz Matuszek.
+ */
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
@@ -258,7 +258,9 @@
 	struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
 	unsigned long totalOK;
 
-	totalOK = priv->stats.txnpokint+priv->stats.txhpokint+priv->stats.txlpokint;
+	totalOK = priv->stats.txnpokint + priv->stats.txhpokint +
+		priv->stats.txlpokint;
+
 	seq_printf(m,
 		"TX OK: %lu\n"
 		"TX Error: %lu\n"
@@ -347,9 +349,9 @@
 }
 
 /*
-  FIXME: check if we can use some standard already-existent
-  data type+functions in kernel
-*/
+ * FIXME: check if we can use some standard already-existent
+ * data type+functions in kernel.
+ */
 
 static short buffer_add(struct buffer **buffer, u32 *buf, dma_addr_t dma,
 			struct buffer **bufferhead)
@@ -468,9 +470,11 @@
 {
 	struct r8180_priv *priv = ieee80211_priv(dev);
 	struct ieee80211_device *ieee = netdev_priv(dev);
-	int requiredbyte, required;
+	int requiredbyte;
+	int required;
 
-	requiredbyte = priv->ieee80211->fts + sizeof(struct ieee80211_header_data);
+	requiredbyte = priv->ieee80211->fts +
+		sizeof(struct ieee80211_header_data);
 
 	if (ieee->current_network.QoS_Enable)
 		requiredbyte += 2;
@@ -484,7 +488,7 @@
 	 * between the tail and the head
 	 */
 
-	return (required+2 < get_curr_tx_free_desc(dev, priority));
+	return required + 2 < get_curr_tx_free_desc(dev, priority);
 }
 
 void fix_tx_fifo(struct net_device *dev)
@@ -649,7 +653,7 @@
 	struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
 
 	if ((ch > 14) || (ch < 1)) {
-		printk("In %s: Invalid chnanel %d\n", __func__, ch);
+		netdev_err(dev, "In %s: Invalid channel %d\n", __func__, ch);
 		return;
 	}
 
@@ -742,43 +746,50 @@
 
 		switch (addr) {
 		case TX_MANAGEPRIORITY_RING_ADDR:
-			if (-1 == buffer_add(&(priv->txmapbufs), buf, dma_tmp, NULL)) {
+			if (-1 == buffer_add(&priv->txmapbufs,
+				buf, dma_tmp, NULL)) {
 				DMESGE("Unable to allocate mem for buffer NP");
 				return -ENOMEM;
 			}
 			break;
 		case TX_BKPRIORITY_RING_ADDR:
-			if (-1 == buffer_add(&(priv->txbkpbufs), buf, dma_tmp, NULL)) {
+			if (-1 == buffer_add(&priv->txbkpbufs,
+				buf, dma_tmp, NULL)) {
 				DMESGE("Unable to allocate mem for buffer LP");
 				return -ENOMEM;
 			}
 			break;
 		case TX_BEPRIORITY_RING_ADDR:
-			if (-1 == buffer_add(&(priv->txbepbufs), buf, dma_tmp, NULL)) {
+			if (-1 == buffer_add(&priv->txbepbufs,
+				buf, dma_tmp, NULL)) {
 				DMESGE("Unable to allocate mem for buffer NP");
 				return -ENOMEM;
 			}
 			break;
 		case TX_VIPRIORITY_RING_ADDR:
-			if (-1 == buffer_add(&(priv->txvipbufs), buf, dma_tmp, NULL)) {
+			if (-1 == buffer_add(&priv->txvipbufs,
+				buf, dma_tmp, NULL)) {
 				DMESGE("Unable to allocate mem for buffer LP");
 				return -ENOMEM;
 			}
 			break;
 		case TX_VOPRIORITY_RING_ADDR:
-			if (-1 == buffer_add(&(priv->txvopbufs), buf, dma_tmp, NULL)) {
+			if (-1 == buffer_add(&priv->txvopbufs,
+				buf, dma_tmp, NULL)) {
 				DMESGE("Unable to allocate mem for buffer NP");
 				return -ENOMEM;
 			}
 			break;
 		case TX_HIGHPRIORITY_RING_ADDR:
-			if (-1 == buffer_add(&(priv->txhpbufs), buf, dma_tmp, NULL)) {
+			if (-1 == buffer_add(&priv->txhpbufs,
+				buf, dma_tmp, NULL)) {
 				DMESGE("Unable to allocate mem for buffer HP");
 				return -ENOMEM;
 			}
 			break;
 		case TX_BEACON_RING_ADDR:
-			if (-1 == buffer_add(&(priv->txbeaconbufs), buf, dma_tmp, NULL)) {
+			if (-1 == buffer_add(&priv->txbeaconbufs,
+				buf, dma_tmp, NULL)) {
 				DMESGE("Unable to allocate mem for buffer BP");
 				return -ENOMEM;
 			}
@@ -897,8 +908,8 @@
 		return -1;
 	}
 
-	desc = (u32 *)pci_alloc_consistent(pdev, sizeof(u32)*rx_desc_size*count+256,
-					  &dma_desc);
+	desc = (u32 *)pci_alloc_consistent(pdev,
+		sizeof(u32) * rx_desc_size * count + 256, &dma_desc);
 
 	if (dma_desc & 0xff)
 		/*
@@ -935,7 +946,8 @@
 		tmp = tmp+rx_desc_size;
 	}
 
-	*(tmp-rx_desc_size) = *(tmp-rx_desc_size) | (1<<30); /* this is the last descriptor */
+	/* this is the last descriptor */
+	*(tmp - rx_desc_size) = *(tmp - rx_desc_size) | (1 << 30);
 
 	return 0;
 }
@@ -1009,7 +1021,8 @@
 	}
 }
 
-static u16 rtl_rate[] = {10, 20, 55, 110, 60, 90, 120, 180, 240, 360, 480, 540, 720};
+static u16 rtl_rate[] = {10, 20, 55, 110, 60,
+	90, 120, 180, 240, 360, 480, 540, 720};
 
 inline u16 rtl8180_rate2rate(short rate)
 {
@@ -1143,23 +1156,30 @@
 /*
  * Perform signal smoothing for dynamic mechanism.
  * This is different with PerformSignalSmoothing8185 in smoothing formula.
- * No dramatic adjustion is apply because dynamic mechanism need some degree
- * of correctness. Ported from 8187B.
+ * No dramatic adjustment is applied because dynamic mechanism need some
+ * degree of correctness. Ported from 8187B.
  */
 static void PerformUndecoratedSignalSmoothing8185(struct r8180_priv *priv,
 						  bool bCckRate)
 {
-	/* Determin the current packet is CCK rate. */
+	long smoothedSS;
+	long smoothedRx;
+
+	/* Determine the current packet is CCK rate. */
 	priv->bCurCCKPkt = bCckRate;
 
-	if (priv->UndecoratedSmoothedSS >= 0)
-		priv->UndecoratedSmoothedSS = ((priv->UndecoratedSmoothedSS * 5) +
-					       (priv->SignalStrength * 10)) / 6;
-	else
-		priv->UndecoratedSmoothedSS = priv->SignalStrength * 10;
+	smoothedSS = priv->SignalStrength * 10;
 
-	priv->UndercorateSmoothedRxPower = ((priv->UndercorateSmoothedRxPower * 50) +
-					    (priv->RxPower * 11)) / 60;
+	if (priv->UndecoratedSmoothedSS >= 0)
+		smoothedSS = ((priv->UndecoratedSmoothedSS * 5) +
+				smoothedSS) / 6;
+
+	priv->UndecoratedSmoothedSS = smoothedSS;
+
+	smoothedRx = ((priv->UndecoratedSmoothedRxPower * 50) +
+			(priv->RxPower * 11)) / 60;
+
+	priv->UndecoratedSmoothedRxPower = smoothedRx;
 
 	if (bCckRate)
 		priv->CurCCKRSSI = priv->RSSI;
@@ -1206,8 +1226,9 @@
 	rx_desc_size = 8;
 
 	if ((*(priv->rxringtail)) & (1<<31)) {
-		/* we have got an RX int, but the descriptor
-		 * we are pointing is empty */
+		/* we have got an RX int, but the descriptor. we are pointing
+		 * is empty.
+		 */
 
 		priv->stats.rxnodata++;
 		priv->ieee80211->stats.rx_errors++;
@@ -1216,7 +1237,8 @@
 		tmp = priv->rxringtail;
 		do {
 			if (tmp == priv->rxring)
-				tmp  = priv->rxring + (priv->rxringcount - 1)*rx_desc_size;
+				tmp  = priv->rxring + (priv->rxringcount - 1) *
+					rx_desc_size;
 			else
 				tmp -= rx_desc_size;
 
@@ -1254,10 +1276,9 @@
 		if (last) {
 			lastlen = ((*priv->rxringtail) & 0xfff);
 
-			/* if the last descriptor (that should
-			 * tell us the total packet len) tell
-			 * us something less than the descriptors
-			 * len we had until now, then there is some
+			/* if the last descriptor (that should tell us the total
+			 * packet len) tell us something less than the
+			 * descriptors len we had until now, then there is some
 			 * problem..
 			 * workaround to prevent kernel panic
 			 */
@@ -1293,31 +1314,36 @@
 		priv->rx_prevlen += len;
 
 		if (priv->rx_prevlen > MAX_FRAG_THRESHOLD + 100) {
-			/* HW is probably passing several buggy frames
-			* without FD or LD flag set.
-			* Throw this garbage away to prevent skb
-			* memory exhausting
-			*/
+			/* HW is probably passing several buggy frames without
+			 * FD or LD flag set.
+			 * Throw this garbage away to prevent skb memory
+			 * exhausting
+			 */
 			if (!priv->rx_skb_complete)
 				dev_kfree_skb_any(priv->rx_skb);
 			priv->rx_skb_complete = 1;
 		}
 
-		signal = (unsigned char)(((*(priv->rxringtail+3)) & (0x00ff0000))>>16);
+		signal = (unsigned char)(*(priv->rxringtail + 3) &
+			0x00ff0000) >> 16;
 		signal = (signal & 0xfe) >> 1;
 
 		quality = (unsigned char)((*(priv->rxringtail+3)) & (0xff));
 
 		stats.mac_time[0] = *(priv->rxringtail+1);
 		stats.mac_time[1] = *(priv->rxringtail+2);
-		rxpower = ((char)(((*(priv->rxringtail+4)) & (0x00ff0000))>>16))/2 - 42;
-		RSSI = ((u8)(((*(priv->rxringtail+3)) & (0x0000ff00))>>8)) & (0x7f);
+
+		rxpower = ((char)((*(priv->rxringtail + 4) &
+			0x00ff0000) >> 16)) / 2 - 42;
+
+		RSSI = ((u8)((*(priv->rxringtail + 3) &
+			0x0000ff00) >> 8)) & 0x7f;
 
 		rate = ((*(priv->rxringtail)) &
 			((1<<23)|(1<<22)|(1<<21)|(1<<20)))>>20;
 
 		stats.rate = rtl8180_rate2rate(rate);
-		Antenna = (((*(priv->rxringtail+3)) & (0x00008000)) == 0) ? 0 : 1;
+		Antenna = (*(priv->rxringtail + 3) & 0x00008000) == 0 ? 0 : 1;
 		if (!rtl8180_IsWirelessBMode(stats.rate)) { /* OFDM rate. */
 			RxAGC_dBm = rxpower+1;	/* bias */
 		} else { /* CCK rate. */
@@ -1326,7 +1352,8 @@
 			LNA = (u8) (RxAGC_dBm & 0x60) >> 5; /* bit 6~ bit 5 */
 			BB  = (u8) (RxAGC_dBm & 0x1F); /* bit 4 ~ bit 0 */
 
-			RxAGC_dBm = -(LNA_gain[LNA] + (BB*2)); /* Pin_11b=-(LNA_gain+BB_gain) (dBm) */
+			/* Pin_11b=-(LNA_gain+BB_gain) (dBm) */
+			RxAGC_dBm = -(LNA_gain[LNA] + (BB * 2));
 
 			RxAGC_dBm += 4; /* bias */
 		}
@@ -1354,21 +1381,25 @@
 		priv->RSSI = RSSI;
 		/* SQ translation formula is provided by SD3 DZ. 2006.06.27 */
 		if (quality >= 127)
-			quality = 1; /*0; */ /* 0 will cause epc to show signal zero , walk around now; */
+			/* 0 causes epc to show signal zero, walk around now */
+			quality = 1;
 		else if (quality < 27)
 			quality = 100;
 		else
 			quality = 127 - quality;
 		priv->SignalQuality = quality;
 
-		stats.signal = (u8)quality; /*priv->wstats.qual.level = priv->SignalStrength; */
+		/*priv->wstats.qual.level = priv->SignalStrength; */
+		stats.signal = (u8) quality;
+
 		stats.signalstrength = RXAGC;
 		if (stats.signalstrength > 100)
 			stats.signalstrength = 100;
-		stats.signalstrength = (stats.signalstrength * 70)/100 + 30;
+		stats.signalstrength = (stats.signalstrength * 70) / 100 + 30;
 		/* printk("==========================>rx : RXAGC is %d,signalstrength is %d\n",RXAGC,stats.signalstrength); */
 		stats.rssi = priv->wstats.qual.qual = priv->SignalQuality;
-		stats.noise = priv->wstats.qual.noise = 100 - priv->wstats.qual.qual;
+		stats.noise = priv->wstats.qual.noise =
+			100 - priv->wstats.qual.qual;
 		bHwError = (((*(priv->rxringtail)) & (0x00000fff)) == 4080) |
 			   (((*(priv->rxringtail)) & (0x04000000)) != 0) |
 			   (((*(priv->rxringtail)) & (0x08000000)) != 0) |
@@ -1397,27 +1428,40 @@
 
 			/* For good-looking singal strength. */
 			SignalStrengthIndex = NetgearSignalStrengthTranslate(
-							priv->LastSignalStrengthInPercent,
-							priv->SignalStrength);
+				priv->LastSignalStrengthInPercent,
+				priv->SignalStrength);
 
 			priv->LastSignalStrengthInPercent = SignalStrengthIndex;
-			priv->Stats_SignalStrength = TranslateToDbm8185((u8)SignalStrengthIndex);
-		/*
-		 * We need more correct power of received packets and the  "SignalStrength" of RxStats is beautified,
-		 * so we record the correct power here.
-		 */
-			priv->Stats_SignalQuality = (long)(priv->Stats_SignalQuality * 5 + (long)priv->SignalQuality + 5) / 6;
-			priv->Stats_RecvSignalPower = (long)(priv->Stats_RecvSignalPower * 5 + priv->RecvSignalPower - 1) / 6;
+			priv->Stats_SignalStrength =
+				TranslateToDbm8185((u8)SignalStrengthIndex);
 
-		/* Figure out which antenna that received the last packet. */
-			priv->LastRxPktAntenna = Antenna ? 1 : 0; /* 0: aux, 1: main. */
+			/*
+			 * We need more correct power of received packets and
+			 * the "SignalStrength" of RxStats is beautified, so we
+			 * record the correct power here.
+			 */
+
+			priv->Stats_SignalQuality = (long)(
+				priv->Stats_SignalQuality * 5 +
+				(long)priv->SignalQuality + 5) / 6;
+
+			priv->Stats_RecvSignalPower = (long)(
+				priv->Stats_RecvSignalPower * 5 +
+				priv->RecvSignalPower - 1) / 6;
+
+			/*
+			 * Figure out which antenna received the last packet.
+			 * 0: aux, 1: main
+			 */
+			priv->LastRxPktAntenna = Antenna ? 1 : 0;
 			SwAntennaDiversityRxOk8185(dev, priv->SignalStrength);
 		}
 
 		if (first) {
 			if (!priv->rx_skb_complete) {
 				/* seems that HW sometimes fails to receive and
-				   doesn't provide the last descriptor */
+				 * doesn't provide the last descriptor.
+				 */
 				dev_kfree_skb_any(priv->rx_skb);
 				priv->stats.rxnolast++;
 			}
@@ -1428,15 +1472,16 @@
 			priv->rx_skb_complete = 0;
 			priv->rx_skb->dev = dev;
 		} else {
-			/* if we are here we should have already RXed
-			* the first frame.
-			* If we get here and the skb is not allocated then
-			* we have just throw out garbage (skb not allocated)
-			* and we are still rxing garbage....
-			*/
+			/* if we are here we should have already RXed the first
+			 * frame.
+			 * If we get here and the skb is not allocated then
+			 * we have just throw out garbage (skb not allocated)
+			 * and we are still rxing garbage....
+			 */
 			if (!priv->rx_skb_complete) {
 
-				tmp_skb = dev_alloc_skb(priv->rx_skb->len+len+2);
+				tmp_skb = dev_alloc_skb(
+					priv->rx_skb->len + len + 2);
 
 				if (!tmp_skb)
 					goto drop;
@@ -1454,13 +1499,8 @@
 		}
 
 		if (!priv->rx_skb_complete) {
-			if (padding) {
-				memcpy(skb_put(priv->rx_skb, len),
-					(((unsigned char *)priv->rxbuffer->buf) + 2), len);
-			} else {
-				memcpy(skb_put(priv->rx_skb, len),
-					priv->rxbuffer->buf, len);
-			}
+			memcpy(skb_put(priv->rx_skb, len), ((unsigned char *)
+				priv->rxbuffer->buf) + (padding ? 2 : 0), len);
 		}
 
 		if (last && !priv->rx_skb_complete) {
@@ -1538,7 +1578,7 @@
 {
 	struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
 	int mode;
-	struct ieee80211_hdr_3addr *h = (struct ieee80211_hdr_3addr *) skb->data;
+	struct ieee80211_hdr_3addr *h = (struct ieee80211_hdr_3addr *)skb->data;
 	short morefrag = (h->frame_control) & IEEE80211_FCTL_MOREFRAGS;
 	unsigned long flags;
 	int priority;
@@ -1547,11 +1587,10 @@
 
 	rate = ieeerate2rtlrate(rate);
 	/*
-	 * This function doesn't require lock because we make
-	 * sure it's called with the tx_lock already acquired.
-	 * this come from the kernel's hard_xmit callback (through
-	 * the ieee stack, or from the try_wake_queue (again through
-	 * the ieee stack.
+	 * This function doesn't require lock because we make sure it's called
+	 * with the tx_lock already acquired.
+	 * This come from the kernel's hard_xmit callback (through the ieee
+	 * stack, or from the try_wake_queue (again through the ieee stack.
 	 */
 	priority = AC2Q(skb->priority);
 	spin_lock_irqsave(&priv->tx_lock, flags);
@@ -1613,55 +1652,6 @@
 	return NETDEV_TX_OK;
 }
 
-/* longpre 144+48 shortpre 72+24 */
-u16 rtl8180_len2duration(u32 len, short rate, short *ext)
-{
-	u16 duration;
-	u16 drift;
-	*ext = 0;
-
-	switch (rate) {
-	case 0: /* 1mbps */
-		*ext = 0;
-		duration = ((len+4)<<4) / 0x2;
-		drift = ((len+4)<<4) % 0x2;
-		if (drift == 0)
-			break;
-		duration++;
-		break;
-	case 1: /* 2mbps */
-		*ext = 0;
-		duration = ((len+4)<<4) / 0x4;
-		drift = ((len+4)<<4) % 0x4;
-		if (drift == 0)
-			break;
-		duration++;
-		break;
-	case 2: /* 5.5mbps */
-		*ext = 0;
-		duration = ((len+4)<<4) / 0xb;
-		drift = ((len+4)<<4) % 0xb;
-		if (drift == 0)
-			break;
-		duration++;
-		break;
-	default:
-	case 3: /* 11mbps */
-		*ext = 0;
-		duration = ((len+4)<<4) / 0x16;
-		drift = ((len+4)<<4) % 0x16;
-		if (drift == 0)
-			break;
-		duration++;
-		if (drift > 6)
-			break;
-		*ext = 1;
-		break;
-	}
-
-	return duration;
-}
-
 static void rtl8180_prepare_beacon(struct net_device *dev)
 {
 	struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
@@ -1669,7 +1659,10 @@
 
 	u16 word  = read_nic_word(dev, BcnItv);
 	word &= ~BcnItv_BcnItv; /* clear Bcn_Itv */
-	word |= cpu_to_le16(priv->ieee80211->current_network.beacon_interval); /* 0x64; */
+
+	/* word |= 0x64; */
+	word |= cpu_to_le16(priv->ieee80211->current_network.beacon_interval);
+
 	write_nic_word(dev, BcnItv, word);
 
 	skb = ieee80211_get_beacon(priv->ieee80211);
@@ -1681,9 +1674,9 @@
 }
 
 /*
- * This function do the real dirty work: it enqueues a TX command
- * descriptor in the ring buffer, copyes the frame in a TX buffer
- * and kicks the NIC to ensure it does the DMA transfer.
+ * This function do the real dirty work: it enqueues a TX command descriptor in
+ * the ring buffer, copyes the frame in a TX buffer and kicks the NIC to ensure
+ * it does the DMA transfer.
  */
 short rtl8180_tx(struct net_device *dev, u8 *txbuf, int len, int priority,
 		 short morefrag, short descfrag, int rate)
@@ -1697,16 +1690,17 @@
 	int buflen;
 	int count;
 	struct buffer *buflist;
-	struct ieee80211_hdr_3addr *frag_hdr = (struct ieee80211_hdr_3addr *)txbuf;
+	struct ieee80211_hdr_3addr *frag_hdr =
+		(struct ieee80211_hdr_3addr *)txbuf;
 	u8 dest[ETH_ALEN];
-	u8			bUseShortPreamble = 0;
-	u8			bCTSEnable = 0;
-	u8			bRTSEnable = 0;
-	u16			Duration = 0;
-	u16			RtsDur = 0;
-	u16			ThisFrameTime = 0;
-	u16			TxDescDuration = 0;
-	bool			ownbit_flag = false;
+	u8 bUseShortPreamble = 0;
+	u8 bCTSEnable = 0;
+	u8 bRTSEnable = 0;
+	u16 Duration = 0;
+	u16 RtsDur = 0;
+	u16 ThisFrameTime = 0;
+	u16 TxDescDuration = 0;
+	bool ownbit_flag = false;
 
 	switch (priority) {
 	case MANAGE_PRIORITY:
@@ -1756,74 +1750,80 @@
 		break;
 	}
 
-		memcpy(&dest, frag_hdr->addr1, ETH_ALEN);
-		if (is_multicast_ether_addr(dest)) {
-			Duration = 0;
-			RtsDur = 0;
-			bRTSEnable = 0;
+	memcpy(&dest, frag_hdr->addr1, ETH_ALEN);
+	if (is_multicast_ether_addr(dest)) {
+		Duration = 0;
+		RtsDur = 0;
+		bRTSEnable = 0;
+		bCTSEnable = 0;
+
+		ThisFrameTime = ComputeTxTime(len + sCrcLng,
+			rtl8180_rate2rate(rate), 0, bUseShortPreamble);
+		TxDescDuration = ThisFrameTime;
+	} else { /* Unicast packet */
+		u16 AckTime;
+
+		/* YJ,add,080828,for Keep alive */
+		priv->NumTxUnicast++;
+
+		/* Figure out ACK rate according to BSS basic rate
+		 * and Tx rate.
+		 * AckCTSLng = 14 use 1M bps send
+		 */
+		AckTime = ComputeTxTime(14, 10, 0, 0);
+
+		if (((len + sCrcLng) > priv->rts) && priv->rts) { /* RTS/CTS. */
+			u16 RtsTime, CtsTime;
+			/* u16 CtsRate; */
+			bRTSEnable = 1;
 			bCTSEnable = 0;
 
-			ThisFrameTime = ComputeTxTime(len + sCrcLng, rtl8180_rate2rate(rate),
-						      0, bUseShortPreamble);
-			TxDescDuration = ThisFrameTime;
-		} else { /* Unicast packet */
-			u16 AckTime;
+			/* Rate and time required for RTS. */
+			RtsTime = ComputeTxTime(sAckCtsLng / 8,
+				priv->ieee80211->basic_rate, 0, 0);
 
-			/* YJ,add,080828,for Keep alive */
-			priv->NumTxUnicast++;
+			/* Rate and time required for CTS.
+			 * AckCTSLng = 14 use 1M bps send
+			 */
+			CtsTime = ComputeTxTime(14, 10, 0, 0);
 
-			/* Figure out ACK rate according to BSS basic rate
-			 * and Tx rate. */
-			AckTime = ComputeTxTime(14, 10, 0, 0);	/* AckCTSLng = 14 use 1M bps send */
+			/* Figure out time required to transmit this frame. */
+			ThisFrameTime = ComputeTxTime(len + sCrcLng,
+				rtl8180_rate2rate(rate), 0,
+				bUseShortPreamble);
 
-			if (((len + sCrcLng) > priv->rts) && priv->rts) { /* RTS/CTS. */
-				u16 RtsTime, CtsTime;
-				/* u16 CtsRate; */
-				bRTSEnable = 1;
-				bCTSEnable = 0;
+			/* RTS-CTS-ThisFrame-ACK. */
+			RtsDur = CtsTime + ThisFrameTime +
+				AckTime + 3 * aSifsTime;
 
-				/* Rate and time required for RTS. */
-				RtsTime = ComputeTxTime(sAckCtsLng/8, priv->ieee80211->basic_rate, 0, 0);
-				/* Rate and time required for CTS. */
-				CtsTime = ComputeTxTime(14, 10, 0, 0);	/* AckCTSLng = 14 use 1M bps send */
+			TxDescDuration = RtsTime + RtsDur;
+		} else { /* Normal case. */
+			bCTSEnable = 0;
+			bRTSEnable = 0;
+			RtsDur = 0;
 
-				/* Figure out time required to transmit this frame. */
-				ThisFrameTime = ComputeTxTime(len + sCrcLng,
-						rtl8180_rate2rate(rate),
-						0,
-						bUseShortPreamble);
+			ThisFrameTime = ComputeTxTime(len + sCrcLng,
+				rtl8180_rate2rate(rate), 0, bUseShortPreamble);
+			TxDescDuration = ThisFrameTime + aSifsTime + AckTime;
+		}
 
-				/* RTS-CTS-ThisFrame-ACK. */
-				RtsDur = CtsTime + ThisFrameTime + AckTime + 3*aSifsTime;
+		if (!(frag_hdr->frame_control & IEEE80211_FCTL_MOREFRAGS)) {
+			/* ThisFrame-ACK. */
+			Duration = aSifsTime + AckTime;
+		} else { /* One or more fragments remained. */
+			u16 NextFragTime;
 
-				TxDescDuration = RtsTime + RtsDur;
-			} else { /* Normal case. */
-				bCTSEnable = 0;
-				bRTSEnable = 0;
-				RtsDur = 0;
+			/* pretend following packet length = current packet */
+			NextFragTime = ComputeTxTime(len + sCrcLng,
+				rtl8180_rate2rate(rate), 0, bUseShortPreamble);
 
-				ThisFrameTime = ComputeTxTime(len + sCrcLng, rtl8180_rate2rate(rate),
-							      0, bUseShortPreamble);
-				TxDescDuration = ThisFrameTime + aSifsTime + AckTime;
-			}
+			/* ThisFrag-ACk-NextFrag-ACK. */
+			Duration = NextFragTime + 3 * aSifsTime + 2 * AckTime;
+		}
 
-			if (!(frag_hdr->frame_control & IEEE80211_FCTL_MOREFRAGS)) {
-				/* ThisFrame-ACK. */
-				Duration = aSifsTime + AckTime;
-			} else { /* One or more fragments remained. */
-				u16 NextFragTime;
-				NextFragTime = ComputeTxTime(len + sCrcLng, /* pretend following packet length equal current packet */
-						rtl8180_rate2rate(rate),
-						0,
-						bUseShortPreamble);
+	} /* End of Unicast packet */
 
-				/* ThisFrag-ACk-NextFrag-ACK. */
-				Duration = NextFragTime + 3*aSifsTime + 2*AckTime;
-			}
-
-		} /* End of Unicast packet */
-
-		frag_hdr->duration_id = Duration;
+	frag_hdr->duration_id = Duration;
 
 	buflen = priv->txbuffsize;
 	remain = len;
@@ -1832,7 +1832,8 @@
 	while (remain != 0) {
 		mb();
 		if (!buflist) {
-			DMESGE("TX buffer error, cannot TX frames. pri %d.", priority);
+			DMESGE("TX buffer error, cannot TX frames. pri %d.",
+				priority);
 			return -1;
 		}
 		buf = buflist->buf;
@@ -1851,43 +1852,54 @@
 		*(tail+6) = 0;
 		*(tail+7) = 0;
 
-		/* FIXME: this should be triggered by HW encryption parameters.*/
+		/* FIXME: should be triggered by HW encryption parameters.*/
 		*tail |= (1<<15); /* no encrypt */
 
 		if (remain == len && !descfrag) {
 			ownbit_flag = false;
-			*tail = *tail | (1<<29); /* fist segment of the packet */
+			*tail = *tail | (1 << 29); /* first segment of packet */
 			*tail = *tail | (len);
 		} else {
 			ownbit_flag = true;
 		}
 
 		for (i = 0; i < buflen && remain > 0; i++, remain--) {
-			((u8 *)buf)[i] = txbuf[i]; /* copy data into descriptor pointed DMAble buffer */
+			/* copy data into descriptor pointed DMAble buffer */
+			((u8 *)buf)[i] = txbuf[i];
+
 			if (remain == 4 && i+4 >= buflen)
 				break;
 			/* ensure the last desc has at least 4 bytes payload */
-
 		}
 		txbuf = txbuf + i;
 		*(tail+3) = *(tail+3) & ~0xfff;
 		*(tail+3) = *(tail+3) | i; /* buffer length */
-		/* Use short preamble or not */
-		if (priv->ieee80211->current_network.capability&WLAN_CAPABILITY_SHORT_PREAMBLE)
-			if (priv->plcp_preamble_mode == 1 && rate != 0)	/*  short mode now, not long! */
-			; /* *tail |= (1<<16); */				/* enable short preamble mode. */
+
+		/* Use short preamble or not - if true, enable short preamble */
+		/*
+		if (priv->ieee80211->current_network.capability &
+			WLAN_CAPABILITY_SHORT_PREAMBLE &&
+			priv->plcp_preamble_mode == 1 && rate != 0) {
+			*tail |= (1 << 16);
+		}
+		*/
 
 		if (bCTSEnable)
 			*tail |= (1<<18);
 
 		if (bRTSEnable) { /* rts enable */
-			*tail |= ((ieeerate2rtlrate(priv->ieee80211->basic_rate))<<19); /* RTS RATE */
+			/* RTS RATE */
+			*tail |= (ieeerate2rtlrate(
+				priv->ieee80211->basic_rate) << 19);
+
 			*tail |= (1<<23); /* rts enable */
 			*(tail+1) |= (RtsDur&0xffff); /* RTS Duration */
 		}
 		*(tail+3) |= ((TxDescDuration&0xffff)<<16); /* DURATION */
 		/* *(tail+3) |= (0xe6<<16); */
-		*(tail+5) |= (11<<8); /* (priv->retry_data<<8); */ /* retry lim; */
+
+		/* (priv->retry_data<<8); */
+		*(tail + 5) |= (11 << 8); /* retry lim; */
 
 		*tail = *tail | ((rate&0xf) << 24);
 
@@ -1901,7 +1913,8 @@
 
 		wmb();
 		if (ownbit_flag)
-			*tail = *tail | (1<<31); /* descriptor ready to be txed */
+			/* descriptor ready to be txed */
+			*tail |= (1 << 31);
 
 		if ((tail - begin)/8 == count-1)
 			tail = begin;
@@ -1983,7 +1996,8 @@
 
 	struct r8180_priv *priv = ieee80211_priv(dev);
 
-	write_nic_byte(dev, CONFIG4, read_nic_byte(dev, CONFIG4) | CONFIG4_PWRMGT);
+	write_nic_byte(dev, CONFIG4,
+		read_nic_byte(dev, CONFIG4) | CONFIG4_PWRMGT);
 	priv->ack_tx_to_ieee = 1;
 }
 
@@ -2031,7 +2045,8 @@
 	struct r8180_priv *priv = ieee80211_priv(dev);
 
 	spin_lock_irqsave(&priv->ps_lock, flags);
-	write_nic_byte(dev, CONFIG4, read_nic_byte(dev, CONFIG4) & ~CONFIG4_PWRMGT);
+	write_nic_byte(dev, CONFIG4,
+		read_nic_byte(dev, CONFIG4) & ~CONFIG4_PWRMGT);
 	if (priv->rf_wakeup)
 		priv->rf_wakeup(dev);
 	spin_unlock_irqrestore(&priv->ps_lock, flags);
@@ -2063,13 +2078,13 @@
 	tl -= MSECS(4+16+7);
 
 	/*
-	 * If the interval in witch we are requested to sleep is too
+	 * If the interval in which we are requested to sleep is too
 	 * short then give up and remain awake
 	 */
 	if (((tl >= rb) && (tl-rb) <= MSECS(MIN_SLEEP_TIME))
 		|| ((rb > tl) && (rb-tl) < MSECS(MIN_SLEEP_TIME))) {
 		spin_unlock_irqrestore(&priv->ps_lock, flags);
-		printk("too short to sleep\n");
+		netdev_warn(dev, "too short to sleep\n");
 		return;
 	}
 
@@ -2078,7 +2093,8 @@
 
 		priv->DozePeriodInPast2Sec += jiffies_to_msecs(tmp);
 		/* as tl may be less than rb */
-		queue_delayed_work(priv->ieee80211->wq, &priv->ieee80211->hw_wakeup_wq, tmp);
+		queue_delayed_work(priv->ieee80211->wq,
+			&priv->ieee80211->hw_wakeup_wq, tmp);
 	}
 	/*
 	 * If we suspect the TimerInt is gone beyond tl
@@ -2095,16 +2111,49 @@
 	spin_unlock_irqrestore(&priv->ps_lock, flags);
 }
 
+static void rtl8180_wmm_single_param_update(struct net_device *dev,
+	u8 mode, AC_CODING eACI, PAC_PARAM param)
+{
+	u8 u1bAIFS;
+	u32 u4bAcParam;
+
+	/* Retrieve parameters to update. */
+	/* Mode G/A: slotTimeTimer = 9; Mode B: 20 */
+	u1bAIFS = param->f.AciAifsn.f.AIFSN * ((mode & IEEE_G) == IEEE_G ?
+		9 : 20) + aSifsTime;
+	u4bAcParam = (((u32)param->f.TXOPLimit << AC_PARAM_TXOP_LIMIT_OFFSET) |
+		((u32)param->f.Ecw.f.ECWmax << AC_PARAM_ECW_MAX_OFFSET) |
+		((u32)param->f.Ecw.f.ECWmin << AC_PARAM_ECW_MIN_OFFSET) |
+		((u32)u1bAIFS << AC_PARAM_AIFS_OFFSET));
+
+	switch (eACI) {
+	case AC1_BK:
+		write_nic_dword(dev, AC_BK_PARAM, u4bAcParam);
+		return;
+	case AC0_BE:
+		write_nic_dword(dev, AC_BE_PARAM, u4bAcParam);
+		return;
+	case AC2_VI:
+		write_nic_dword(dev, AC_VI_PARAM, u4bAcParam);
+		return;
+	case AC3_VO:
+		write_nic_dword(dev, AC_VO_PARAM, u4bAcParam);
+		return;
+	default:
+		pr_warn("SetHwReg8185(): invalid ACI: %d!\n", eACI);
+		return;
+	}
+}
+
 static void rtl8180_wmm_param_update(struct work_struct *work)
 {
-	struct ieee80211_device *ieee = container_of(work, struct ieee80211_device, wmm_param_update_wq);
+	struct ieee80211_device *ieee = container_of(work,
+		struct ieee80211_device, wmm_param_update_wq);
 	struct net_device *dev = ieee->dev;
 	u8 *ac_param = (u8 *)(ieee->current_network.wmm_param);
 	u8 mode = ieee->current_network.mode;
-	AC_CODING	eACI;
-	AC_PARAM	AcParam;
-	PAC_PARAM	pAcParam;
-	u8 i;
+	AC_CODING eACI;
+	AC_PARAM AcParam;
 
 	if (!ieee->current_network.QoS_Enable) {
 		/* legacy ac_xx_param update */
@@ -2114,78 +2163,24 @@
 		AcParam.f.Ecw.f.ECWmin = 3; /* Follow 802.11 CWmin. */
 		AcParam.f.Ecw.f.ECWmax = 7; /* Follow 802.11 CWmax. */
 		AcParam.f.TXOPLimit = 0;
+
 		for (eACI = 0; eACI < AC_MAX; eACI++) {
 			AcParam.f.AciAifsn.f.ACI = (u8)eACI;
-			{
-				u8		u1bAIFS;
-				u32		u4bAcParam;
-				pAcParam = (PAC_PARAM)(&AcParam);
-				/* Retrieve parameters to update. */
-				u1bAIFS = pAcParam->f.AciAifsn.f.AIFSN * (((mode&IEEE_G) == IEEE_G) ? 9 : 20) + aSifsTime;
-				u4bAcParam = ((((u32)(pAcParam->f.TXOPLimit))<<AC_PARAM_TXOP_LIMIT_OFFSET)|
-					      (((u32)(pAcParam->f.Ecw.f.ECWmax))<<AC_PARAM_ECW_MAX_OFFSET)|
-					      (((u32)(pAcParam->f.Ecw.f.ECWmin))<<AC_PARAM_ECW_MIN_OFFSET)|
-					       (((u32)u1bAIFS) << AC_PARAM_AIFS_OFFSET));
-				switch (eACI) {
-				case AC1_BK:
-					write_nic_dword(dev, AC_BK_PARAM, u4bAcParam);
-					break;
-				case AC0_BE:
-					write_nic_dword(dev, AC_BE_PARAM, u4bAcParam);
-					break;
-				case AC2_VI:
-					write_nic_dword(dev, AC_VI_PARAM, u4bAcParam);
-					break;
-				case AC3_VO:
-					write_nic_dword(dev, AC_VO_PARAM, u4bAcParam);
-					break;
-				default:
-					pr_warn("SetHwReg8185():invalid ACI: %d!\n",
-						eACI);
-					break;
-				}
-			}
+
+			rtl8180_wmm_single_param_update(dev, mode, eACI,
+				(PAC_PARAM)&AcParam);
 		}
 		return;
 	}
 
-	for (i = 0; i < AC_MAX; i++) {
+	for (eACI = 0; eACI < AC_MAX; eACI++) {
 		/* AcParam.longData = 0; */
-		pAcParam = (AC_PARAM *)ac_param;
-		{
-			AC_CODING	eACI;
-			u8		u1bAIFS;
-			u32		u4bAcParam;
 
-			/* Retrieve parameters to update. */
-			eACI = pAcParam->f.AciAifsn.f.ACI;
-			/* Mode G/A: slotTimeTimer = 9; Mode B: 20 */
-			u1bAIFS = pAcParam->f.AciAifsn.f.AIFSN * (((mode&IEEE_G) == IEEE_G) ? 9 : 20) + aSifsTime;
-			u4bAcParam = ((((u32)(pAcParam->f.TXOPLimit)) << AC_PARAM_TXOP_LIMIT_OFFSET)	|
-					(((u32)(pAcParam->f.Ecw.f.ECWmax)) << AC_PARAM_ECW_MAX_OFFSET)	|
-					(((u32)(pAcParam->f.Ecw.f.ECWmin)) << AC_PARAM_ECW_MIN_OFFSET)	|
-					(((u32)u1bAIFS) << AC_PARAM_AIFS_OFFSET));
+		rtl8180_wmm_single_param_update(dev, mode,
+			((PAC_PARAM)ac_param)->f.AciAifsn.f.ACI,
+			(PAC_PARAM)ac_param);
 
-			switch (eACI) {
-			case AC1_BK:
-				write_nic_dword(dev, AC_BK_PARAM, u4bAcParam);
-				break;
-			case AC0_BE:
-				write_nic_dword(dev, AC_BE_PARAM, u4bAcParam);
-				break;
-			case AC2_VI:
-				write_nic_dword(dev, AC_VI_PARAM, u4bAcParam);
-				break;
-			case AC3_VO:
-				write_nic_dword(dev, AC_VO_PARAM, u4bAcParam);
-				break;
-			default:
-				pr_warn("SetHwReg8185(): invalid ACI: %d !\n",
-					eACI);
-				break;
-			}
-		}
-		ac_param += (sizeof(AC_PARAM));
+		ac_param += sizeof(AC_PARAM);
 	}
 }
 
@@ -2208,7 +2203,8 @@
 
 	/* Tx High Power Mechanism. */
 	if (CheckHighPower((struct net_device *)data))
-		queue_work(priv->ieee80211->wq, (void *)&priv->ieee80211->tx_pw_wq);
+		queue_work(priv->ieee80211->wq,
+			(void *)&priv->ieee80211->tx_pw_wq);
 
 	/* Tx Power Tracking on 87SE. */
 	if (CheckTxPwrTracking((struct net_device *)data))
@@ -2216,27 +2212,59 @@
 
 	/* Perform DIG immediately. */
 	if (CheckDig((struct net_device *)data))
-		queue_work(priv->ieee80211->wq, (void *)&priv->ieee80211->hw_dig_wq);
+		queue_work(priv->ieee80211->wq,
+			(void *)&priv->ieee80211->hw_dig_wq);
+
 	rtl8180_watch_dog((struct net_device *)data);
 
-	queue_work(priv->ieee80211->wq, (void *)&priv->ieee80211->GPIOChangeRFWorkItem);
+	queue_work(priv->ieee80211->wq,
+		(void *)&priv->ieee80211->GPIOChangeRFWorkItem);
 
-	priv->watch_dog_timer.expires = jiffies + MSECS(IEEE80211_WATCH_DOG_TIME);
+	priv->watch_dog_timer.expires = jiffies +
+		MSECS(IEEE80211_WATCH_DOG_TIME);
+
 	add_timer(&priv->watch_dog_timer);
 }
 
-static CHANNEL_LIST ChannelPlan[] = {
-	{{1,2,3,4,5,6,7,8,9,10,11,36,40,44,48,52,56,60,64},19},		/* FCC */
-	{{1,2,3,4,5,6,7,8,9,10,11},11},					/* IC */
-	{{1,2,3,4,5,6,7,8,9,10,11,12,13,36,40,44,48,52,56,60,64},21},	/* ETSI */
-	{{1,2,3,4,5,6,7,8,9,10,11,12,13,36,40,44,48,52,56,60,64},21},	/* Spain. Change to ETSI. */
-	{{1,2,3,4,5,6,7,8,9,10,11,12,13,36,40,44,48,52,56,60,64},21},	/* France. Change to ETSI. */
-	{{14,36,40,44,48,52,56,60,64},9},				/* MKK */
-	{{1,2,3,4,5,6,7,8,9,10,11,12,13,14, 36,40,44,48,52,56,60,64},22},/* MKK1 */
-	{{1,2,3,4,5,6,7,8,9,10,11,12,13,36,40,44,48,52,56,60,64},21},	/* Israel. */
-	{{1,2,3,4,5,6,7,8,9,10,11,12,13,34,38,42,46},17},		/* For 11a , TELEC */
-	{{1,2,3,4,5,6,7,8,9,10,11,12,13,14},14},  /* For Global Domain. 1-11:active scan, 12-14 passive scan. //+YJ, 080626 */
-	{{1,2,3,4,5,6,7,8,9,10,11,12,13},13} /* world wide 13: ch1~ch11 active scan, ch12~13 passive //lzm add 080826 */
+static struct rtl8187se_channel_list channel_plan_list[] = {
+	/* FCC */
+	{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 36, 40,
+		44, 48, 52, 56, 60, 64}, 19},
+
+	/* IC */
+	{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, 11},
+
+	/* ETSI */
+	{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 36, 40,
+		44, 48, 52, 56, 60, 64}, 21},
+
+	/* Spain. Change to ETSI. */
+	{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 36, 40,
+		44, 48, 52, 56, 60, 64}, 21},
+
+	/* France. Change to ETSI. */
+	{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 36, 40,
+		44, 48, 52, 56, 60, 64}, 21},
+
+	/* MKK */
+	{{14, 36, 40, 44, 48, 52, 56, 60, 64}, 9},
+
+	/* MKK1 */
+	{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 36,
+		40, 44, 48, 52, 56, 60, 64}, 22},
+
+	/* Israel. */
+	{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 36, 40,
+		44, 48, 52, 56, 60, 64}, 21},
+
+	/* For 11a , TELEC */
+	{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 34, 38, 42, 46}, 17},
+
+	/* For Global Domain. 1-11 active, 12-14 passive. //+YJ, 080626 */
+	{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}, 14},
+
+	/* world wide 13: ch1~ch11 active, ch12~13 passive //lzm add 080826 */
+	{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 13}
 };
 
 static void rtl8180_set_channel_map(u8 channel_plan,
@@ -2261,13 +2289,13 @@
 		{
 			Dot11d_Init(ieee);
 			ieee->bGlobalDomain = false;
-			if (ChannelPlan[channel_plan].Len != 0) {
+			if (channel_plan_list[channel_plan].len != 0) {
 				/* Clear old channel map */
 				memset(GET_DOT11D_INFO(ieee)->channel_map, 0, sizeof(GET_DOT11D_INFO(ieee)->channel_map));
 				/* Set new channel map */
-				for (i = 0; i < ChannelPlan[channel_plan].Len; i++) {
-					if (ChannelPlan[channel_plan].Channel[i] <= 14)
-						GET_DOT11D_INFO(ieee)->channel_map[ChannelPlan[channel_plan].Channel[i]] = 1;
+				for (i = 0; i < channel_plan_list[channel_plan].len; i++) {
+					if (channel_plan_list[channel_plan].channel[i] <= 14)
+						GET_DOT11D_INFO(ieee)->channel_map[channel_plan_list[channel_plan].channel[i]] = 1;
 				}
 			}
 			break;
@@ -2300,15 +2328,15 @@
 void GPIOChangeRFWorkItemCallBack(struct work_struct *work);
 
 /* YJ,add,080828 */
-static void rtl8180_statistics_init(struct Stats *pstats)
+static void rtl8180_statistics_init(struct stats *pstats)
 {
-	memset(pstats, 0, sizeof(struct Stats));
+	memset(pstats, 0, sizeof(struct stats));
 }
 
-static void rtl8180_link_detect_init(plink_detect_t plink_detect)
+static void rtl8180_link_detect_init(struct link_detect_t *plink_detect)
 {
-	memset(plink_detect, 0, sizeof(link_detect_t));
-	plink_detect->SlotNum = DEFAULT_SLOT_NUM;
+	memset(plink_detect, 0, sizeof(struct link_detect_t));
+	plink_detect->slot_num = DEFAULT_SLOT_NUM;
 }
 
 /* YJ,add,080828,end */
@@ -2360,7 +2388,7 @@
 	eeprom_93cx6_read(&eeprom, EEPROM_COUNTRY_CODE>>1, &eeprom_val);
 	priv->channel_plan = eeprom_val & 0xFF;
 	if (priv->channel_plan > COUNTRY_CODE_GLOBAL_DOMAIN) {
-		printk("rtl8180_init:Error channel plan! Set to default.\n");
+		netdev_err(dev, "rtl8180_init: Invalid channel plan! Set to default.\n");
 		priv->channel_plan = 0;
 	}
 
@@ -2385,7 +2413,8 @@
 	rtl8180_link_detect_init(&priv->link_detect);
 
 	priv->ack_tx_to_ieee = 0;
-	priv->ieee80211->current_network.beacon_interval = DEFAULT_BEACONINTERVAL;
+	priv->ieee80211->current_network.beacon_interval =
+		DEFAULT_BEACONINTERVAL;
 	priv->ieee80211->iw_mode = IW_MODE_INFRA;
 	priv->ieee80211->softmac_features  = IEEE_SOFTMAC_SCAN |
 		IEEE_SOFTMAC_ASSOCIATE | IEEE_SOFTMAC_PROBERQ |
@@ -2431,7 +2460,8 @@
 	priv->AdRxSsBeforeSwitched = 0;
 	init_timer(&priv->SwAntennaDiversityTimer);
 	priv->SwAntennaDiversityTimer.data = (unsigned long)dev;
-	priv->SwAntennaDiversityTimer.function = (void *)SwAntennaDiversityTimerCallback;
+	priv->SwAntennaDiversityTimer.function =
+		(void *)SwAntennaDiversityTimerCallback;
 	priv->bDigMechanism = true;
 	priv->InitialGain = 6;
 	priv->bXtalCalibration = false;
@@ -2440,7 +2470,8 @@
 	priv->bTxPowerTrack = false;
 	priv->ThermalMeter = 0;
 	priv->FalseAlarmRegValue = 0;
-	priv->RegDigOfdmFaUpTh = 0xc; /* Upper threshold of OFDM false alarm, which is used in DIG. */
+	priv->RegDigOfdmFaUpTh = 0xc; /* Upper threshold of OFDM false alarm,
+					which is used in DIG. */
 	priv->DIG_NumberFallbackVote = 0;
 	priv->DIG_NumberUpgradeVote = 0;
 	priv->LastSignalStrengthInPercent = 0;
@@ -2585,7 +2616,8 @@
 		priv->bSwAntennaDiverity = priv->EEPROMSwAntennaDiversity;
 	else
 		/* 1:disable antenna diversity, 2: enable antenna diversity. */
-		priv->bSwAntennaDiverity = priv->RegSwAntennaDiversityMechanism == 2;
+		priv->bSwAntennaDiverity =
+			priv->RegSwAntennaDiversityMechanism == 2;
 
 	if (priv->RegDefaultAntenna == 0)
 		/* 0: default from EEPROM. */
@@ -2669,7 +2701,8 @@
 				  TX_BEACON_RING_ADDR))
 		return -ENOMEM;
 
-	if (request_irq(dev->irq, rtl8180_interrupt, IRQF_SHARED, dev->name, dev)) {
+	if (request_irq(dev->irq, rtl8180_interrupt,
+		IRQF_SHARED, dev->name, dev)) {
 		DMESGE("Error allocating IRQ %d", dev->irq);
 		return -1;
 	} else {
@@ -2768,16 +2801,19 @@
 
 	phyw = ((data<<8) | adr);
 
-	/* Note that, we must write 0xff7c after 0x7d-0x7f to write BB register. */
+	/* Note: we must write 0xff7c after 0x7d-0x7f to write BB register. */
 	write_nic_byte(dev, 0x7f, ((phyw & 0xff000000) >> 24));
 	write_nic_byte(dev, 0x7e, ((phyw & 0x00ff0000) >> 16));
 	write_nic_byte(dev, 0x7d, ((phyw & 0x0000ff00) >> 8));
 	write_nic_byte(dev, 0x7c, ((phyw & 0x000000ff)));
 
-	/* this is ok to fail when we write AGC table. check for AGC table might be
-	 * done by masking with 0x7f instead of 0xff
+	/* this is ok to fail when we write AGC table. check for AGC table
+	 * might be done by masking with 0x7f instead of 0xff
 	 */
-	/* if (phyr != (data&0xff)) DMESGW("Phy write timeout %x %x %x", phyr, data, adr); */
+	/*
+	if (phyr != (data&0xff))
+		DMESGW("Phy write timeout %x %x %x", phyr, data, adr);
+	*/
 }
 
 inline void write_phy_ofdm(struct net_device *dev, u8 adr, u32 data)
@@ -2812,9 +2848,9 @@
 	word  = read_nic_word(dev, BintrItv);
 	word &= ~BintrItv_BintrItv;
 	word |= 1000; /* priv->ieee80211->current_network.beacon_interval *
-		((priv->txbeaconcount > 1)?(priv->txbeaconcount-1):1);
-	// FIXME: check if correct ^^ worked with 0x3e8;
-	*/
+		       * ((priv->txbeaconcount > 1)?(priv->txbeaconcount-1):1);
+		       * FIXME: check if correct ^^ worked with 0x3e8;
+		       */
 	write_nic_word(dev, BintrItv, word);
 
 	rtl8180_set_mode(dev, EPROM_CMD_NORMAL);
@@ -2846,25 +2882,26 @@
 
 static void LeisurePSEnter(struct r8180_priv *priv)
 {
-	if (priv->bLeisurePs) {
+	if (priv->bLeisurePs)
 		if (priv->ieee80211->ps == IEEE80211_PS_DISABLED)
 			/* IEEE80211_PS_ENABLE */
-			MgntActSet_802_11_PowerSaveMode(priv, IEEE80211_PS_MBCAST|IEEE80211_PS_UNICAST);
-	}
+			MgntActSet_802_11_PowerSaveMode(priv,
+				IEEE80211_PS_MBCAST | IEEE80211_PS_UNICAST);
 }
 
 static void LeisurePSLeave(struct r8180_priv *priv)
 {
-	if (priv->bLeisurePs) {
+	if (priv->bLeisurePs)
 		if (priv->ieee80211->ps != IEEE80211_PS_DISABLED)
-			MgntActSet_802_11_PowerSaveMode(priv, IEEE80211_PS_DISABLED);
-	}
+			MgntActSet_802_11_PowerSaveMode(
+				priv, IEEE80211_PS_DISABLED);
 }
 
 void rtl8180_hw_wakeup_wq(struct work_struct *work)
 {
 	struct delayed_work *dwork = to_delayed_work(work);
-	struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, hw_wakeup_wq);
+	struct ieee80211_device *ieee = container_of(
+		dwork, struct ieee80211_device, hw_wakeup_wq);
 	struct net_device *dev = ieee->dev;
 
 	rtl8180_hw_wakeup(dev);
@@ -2873,7 +2910,8 @@
 void rtl8180_hw_sleep_wq(struct work_struct *work)
 {
 	struct delayed_work *dwork = to_delayed_work(work);
-	struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, hw_sleep_wq);
+	struct ieee80211_device *ieee = container_of(
+		dwork, struct ieee80211_device, hw_sleep_wq);
 	struct net_device *dev = ieee->dev;
 
 	rtl8180_hw_sleep_down(dev);
@@ -2890,23 +2928,30 @@
 		 */
 
 		if ((priv->keepAliveLevel == 2) ||
-			(priv->link_detect.LastNumTxUnicast == priv->NumTxUnicast &&
-			priv->link_detect.LastNumRxUnicast == priv->ieee80211->NumRxUnicast)
+			(priv->link_detect.last_num_tx_unicast ==
+				priv->NumTxUnicast &&
+			priv->link_detect.last_num_rx_unicast ==
+				priv->ieee80211->NumRxUnicast)
 			) {
-			priv->link_detect.IdleCount++;
+			priv->link_detect.idle_count++;
 
 			/*
-			 * Send a Keep-Alive packet packet to AP if we had been idle for a while.
+			 * Send a Keep-Alive packet packet to AP if we had
+			 * been idle for a while.
 			 */
-			if (priv->link_detect.IdleCount >= ((KEEP_ALIVE_INTERVAL / CHECK_FOR_HANG_PERIOD)-1)) {
-				priv->link_detect.IdleCount = 0;
-				ieee80211_sta_ps_send_null_frame(priv->ieee80211, false);
+			if (priv->link_detect.idle_count >=
+				KEEP_ALIVE_INTERVAL /
+				CHECK_FOR_HANG_PERIOD - 1) {
+				priv->link_detect.idle_count = 0;
+				ieee80211_sta_ps_send_null_frame(
+					priv->ieee80211, false);
 			}
 		} else {
-			priv->link_detect.IdleCount = 0;
+			priv->link_detect.idle_count = 0;
 		}
-		priv->link_detect.LastNumTxUnicast = priv->NumTxUnicast;
-		priv->link_detect.LastNumRxUnicast = priv->ieee80211->NumRxUnicast;
+		priv->link_detect.last_num_tx_unicast = priv->NumTxUnicast;
+		priv->link_detect.last_num_rx_unicast =
+			priv->ieee80211->NumRxUnicast;
 	}
 }
 
@@ -2926,15 +2971,22 @@
 			IPSEnter(dev);
 	}
 	/* YJ,add,080828,for link state check */
-	if ((priv->ieee80211->state == IEEE80211_LINKED) && (priv->ieee80211->iw_mode == IW_MODE_INFRA)) {
-		SlotIndex = (priv->link_detect.SlotIndex++) % priv->link_detect.SlotNum;
-		priv->link_detect.RxFrameNum[SlotIndex] = priv->ieee80211->NumRxDataInPeriod + priv->ieee80211->NumRxBcnInPeriod;
-		for (i = 0; i < priv->link_detect.SlotNum; i++)
-			TotalRxNum += priv->link_detect.RxFrameNum[i];
+	if ((priv->ieee80211->state == IEEE80211_LINKED) &&
+		(priv->ieee80211->iw_mode == IW_MODE_INFRA)) {
+		SlotIndex = (priv->link_detect.slot_index++) %
+			priv->link_detect.slot_num;
+
+		priv->link_detect.rx_frame_num[SlotIndex] =
+			priv->ieee80211->NumRxDataInPeriod +
+			priv->ieee80211->NumRxBcnInPeriod;
+
+		for (i = 0; i < priv->link_detect.slot_num; i++)
+			TotalRxNum += priv->link_detect.rx_frame_num[i];
 
 		if (TotalRxNum == 0) {
 			priv->ieee80211->state = IEEE80211_ASSOCIATING;
-			queue_work(priv->ieee80211->wq, &priv->ieee80211->associate_procedure_wq);
+			queue_work(priv->ieee80211->wq,
+				&priv->ieee80211->associate_procedure_wq);
 		}
 	}
 
@@ -2945,13 +2997,15 @@
 	LeisurePSLeave(priv);
 
 	if (priv->ieee80211->state == IEEE80211_LINKED) {
-		priv->link_detect.NumRxOkInPeriod = priv->ieee80211->NumRxDataInPeriod;
-		if (priv->link_detect.NumRxOkInPeriod > 666 ||
-			priv->link_detect.NumTxOkInPeriod > 666) {
+		priv->link_detect.num_rx_ok_in_period =
+			priv->ieee80211->NumRxDataInPeriod;
+		if (priv->link_detect.num_rx_ok_in_period > 666 ||
+			priv->link_detect.num_tx_ok_in_period > 666) {
 			bBusyTraffic = true;
 		}
-		if (((priv->link_detect.NumRxOkInPeriod + priv->link_detect.NumTxOkInPeriod) > 8)
-			|| (priv->link_detect.NumRxOkInPeriod > 2)) {
+		if ((priv->link_detect.num_rx_ok_in_period +
+			priv->link_detect.num_tx_ok_in_period > 8)
+			|| (priv->link_detect.num_rx_ok_in_period > 2)) {
 			bEnterPS = false;
 		} else
 			bEnterPS = true;
@@ -2962,9 +3016,9 @@
 			LeisurePSLeave(priv);
 	} else
 		LeisurePSLeave(priv);
-	priv->link_detect.bBusyTraffic = bBusyTraffic;
-	priv->link_detect.NumRxOkInPeriod = 0;
-	priv->link_detect.NumTxOkInPeriod = 0;
+	priv->link_detect.b_busy_traffic = bBusyTraffic;
+	priv->link_detect.num_rx_ok_in_period = 0;
+	priv->link_detect.num_tx_ok_in_period = 0;
 	priv->ieee80211->NumRxDataInPeriod = 0;
 	priv->ieee80211->NumRxBcnInPeriod = 0;
 }
@@ -3048,14 +3102,16 @@
 	cancel_delayed_work(&priv->ieee80211->tx_pw_wq);
 	del_timer_sync(&priv->SwAntennaDiversityTimer);
 	SetZebraRFPowerState8185(dev, eRfOff);
-	memset(&(priv->ieee80211->current_network), 0, sizeof(struct ieee80211_network));
+	memset(&priv->ieee80211->current_network,
+		0, sizeof(struct ieee80211_network));
 	priv->ieee80211->state = IEEE80211_NOLINK;
 	return 0;
 }
 
 void rtl8180_restart_wq(struct work_struct *work)
 {
-	struct r8180_priv *priv = container_of(work, struct r8180_priv, reset_wq);
+	struct r8180_priv *priv = container_of(
+		work, struct r8180_priv, reset_wq);
 	struct net_device *dev = priv->dev;
 
 	down(&priv->wx_sem);
@@ -3116,7 +3172,8 @@
 	memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN);
 
 	if (priv->ieee80211->iw_mode == IW_MODE_MASTER)
-		memcpy(priv->ieee80211->current_network.bssid, dev->dev_addr, ETH_ALEN);
+		memcpy(priv->ieee80211->current_network.bssid,
+			dev->dev_addr, ETH_ALEN);
 
 	if (priv->up) {
 		rtl8180_down(dev);
@@ -3137,7 +3194,8 @@
 
 	switch (cmd) {
 	case RTL_IOCTL_WPA_SUPPLICANT:
-		ret = ieee80211_wpa_supplicant_ioctl(priv->ieee80211, &wrq->u.data);
+		ret = ieee80211_wpa_supplicant_ioctl(
+			priv->ieee80211, &wrq->u.data);
 		return ret;
 	default:
 		return -EOPNOTSUPP;
@@ -3586,7 +3644,7 @@
 	}
 
 	if (inta & ISR_THPDOK) { /* High priority tx ok */
-		priv->link_detect.NumTxOkInPeriod++; /* YJ,add,080828 */
+		priv->link_detect.num_tx_ok_in_period++; /* YJ,add,080828 */
 		priv->stats.txhpokint++;
 		rtl8180_tx_isr(dev, HI_PRIORITY, 0);
 	}
@@ -3649,14 +3707,14 @@
 		priv->stats.txoverflow++;
 
 	if (inta & ISR_TNPDOK) { /* Normal priority tx ok */
-		priv->link_detect.NumTxOkInPeriod++; /* YJ,add,080828 */
+		priv->link_detect.num_tx_ok_in_period++; /* YJ,add,080828 */
 		priv->stats.txnpokint++;
 		rtl8180_tx_isr(dev, NORM_PRIORITY, 0);
 		rtl8180_try_wake_queue(dev, NORM_PRIORITY);
 	}
 
 	if (inta & ISR_TLPDOK) { /* Low priority tx ok */
-		priv->link_detect.NumTxOkInPeriod++; /* YJ,add,080828 */
+		priv->link_detect.num_tx_ok_in_period++; /* YJ,add,080828 */
 		priv->stats.txlpokint++;
 		rtl8180_tx_isr(dev, LOW_PRIORITY, 0);
 		rtl8180_try_wake_queue(dev, LOW_PRIORITY);
@@ -3664,14 +3722,14 @@
 
 	if (inta & ISR_TBKDOK) { /* corresponding to BK_PRIORITY */
 		priv->stats.txbkpokint++;
-		priv->link_detect.NumTxOkInPeriod++; /* YJ,add,080828 */
+		priv->link_detect.num_tx_ok_in_period++; /* YJ,add,080828 */
 		rtl8180_tx_isr(dev, BK_PRIORITY, 0);
 		rtl8180_try_wake_queue(dev, BE_PRIORITY);
 	}
 
 	if (inta & ISR_TBEDOK) { /* corresponding to BE_PRIORITY */
 		priv->stats.txbeperr++;
-		priv->link_detect.NumTxOkInPeriod++; /* YJ,add,080828 */
+		priv->link_detect.num_tx_ok_in_period++; /* YJ,add,080828 */
 		rtl8180_tx_isr(dev, BE_PRIORITY, 0);
 		rtl8180_try_wake_queue(dev, BE_PRIORITY);
 	}
@@ -3688,7 +3746,8 @@
 
 void GPIOChangeRFWorkItemCallBack(struct work_struct *work)
 {
-	struct ieee80211_device *ieee = container_of(work, struct ieee80211_device, GPIOChangeRFWorkItem.work);
+	struct ieee80211_device *ieee = container_of(
+		work, struct ieee80211_device, GPIOChangeRFWorkItem.work);
 	struct net_device *dev = ieee->dev;
 	struct r8180_priv *priv = ieee80211_priv(dev);
 	u8 btPSR;
@@ -3698,7 +3757,8 @@
 
 	char *argv[3];
 	static char *RadioPowerPath = "/etc/acpi/events/RadioPower.sh";
-	static char *envp[] = {"HOME=/", "TERM=linux", "PATH=/usr/bin:/bin", NULL};
+	static char *envp[] = {"HOME=/", "TERM=linux",
+		"PATH=/usr/bin:/bin", NULL};
 	static int readf_count;
 
 	readf_count = (readf_count+1)%0xffff;
diff --git a/drivers/staging/rtl8187se/r8180_wx.c b/drivers/staging/rtl8187se/r8180_wx.c
index 9b676e0..b552491 100644
--- a/drivers/staging/rtl8187se/r8180_wx.c
+++ b/drivers/staging/rtl8187se/r8180_wx.c
@@ -29,7 +29,7 @@
 
 #define RATE_COUNT ARRAY_SIZE(rtl8180_rates)
 
-static CHANNEL_LIST DefaultChannelPlan[] = {
+static struct rtl8187se_channel_list default_channel_plan[] = {
 	{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 36, 40, 44, 48, 52, 56, 60, 64}, 19},		/* FCC */
 	{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, 11},						/* IC */
 	{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 36, 40, 44, 48, 52, 56, 60, 64}, 21},	/* ETSI	*/
@@ -337,7 +337,7 @@
 		}	else	{
 			/* prevent scan in BusyTraffic */
 			/* FIXME: Need to consider last scan time */
-			if ((priv->link_detect.bBusyTraffic) && (true))	{
+			if ((priv->link_detect.b_busy_traffic) && (true)) {
 				ret = 0;
 				printk("Now traffic is busy, please try later!\n");
 			}	else
@@ -1030,15 +1030,15 @@
 
 	/* unsigned long flags; */
 	down(&priv->wx_sem);
-	if (DefaultChannelPlan[*val].Len != 0)	{
+	if (default_channel_plan[*val].len != 0) {
 		priv->channel_plan = *val;
 		/* Clear old channel map 8 */
 		for (i = 1; i <= MAX_CHANNEL_NUMBER; i++)
 			GET_DOT11D_INFO(priv->ieee80211)->channel_map[i] = 0;
 
 		/* Set new channel map */
-		for (i = 1; i <= DefaultChannelPlan[*val].Len; i++)
-			GET_DOT11D_INFO(priv->ieee80211)->channel_map[DefaultChannelPlan[*val].Channel[i-1]] = 1;
+		for (i = 1; i <= default_channel_plan[*val].len; i++)
+			GET_DOT11D_INFO(priv->ieee80211)->channel_map[default_channel_plan[*val].channel[i-1]] = 1;
 
 	}
 	up(&priv->wx_sem);
diff --git a/drivers/staging/rtl8187se/r8185b_init.c b/drivers/staging/rtl8187se/r8185b_init.c
index c8b9baf..48eda55 100644
--- a/drivers/staging/rtl8187se/r8185b_init.c
+++ b/drivers/staging/rtl8187se/r8185b_init.c
@@ -873,7 +873,7 @@
 static void
 ActUpdateChannelAccessSetting(struct net_device *dev,
 			      WIRELESS_MODE WirelessMode,
-			      PCHANNEL_ACCESS_SETTING ChnlAccessSetting)
+			      struct chnl_access_setting *chnl_access_setting)
 {
 	AC_CODING	eACI;
 
@@ -890,25 +890,25 @@
 	 */
 
 	/* Suggested by Jong, 2005.12.08. */
-	ChnlAccessSetting->SIFS_Timer = 0x22;
-	ChnlAccessSetting->DIFS_Timer = 0x1C; /* 2006.06.02, by rcnjko. */
-	ChnlAccessSetting->SlotTimeTimer = 9; /* 2006.06.02, by rcnjko. */
+	chnl_access_setting->sifs_timer = 0x22;
+	chnl_access_setting->difs_timer = 0x1C; /* 2006.06.02, by rcnjko. */
+	chnl_access_setting->slot_time_timer = 9; /* 2006.06.02, by rcnjko. */
 	/*
 	 * Suggested by wcchu, it is the default value of EIFS register,
 	 * 2005.12.08.
 	 */
-	ChnlAccessSetting->EIFS_Timer = 0x5B;
-	ChnlAccessSetting->CWminIndex = 3; /* 2006.06.02, by rcnjko. */
-	ChnlAccessSetting->CWmaxIndex = 7; /* 2006.06.02, by rcnjko. */
+	chnl_access_setting->eifs_timer = 0x5B;
+	chnl_access_setting->cwmin_index = 3; /* 2006.06.02, by rcnjko. */
+	chnl_access_setting->cwmax_index = 7; /* 2006.06.02, by rcnjko. */
 
-	write_nic_byte(dev, SIFS, ChnlAccessSetting->SIFS_Timer);
+	write_nic_byte(dev, SIFS, chnl_access_setting->sifs_timer);
 	/*
 	 * Rewrited from directly use PlatformEFIOWrite1Byte(),
 	 * by Annie, 2006-03-29.
 	 */
-	write_nic_byte(dev, SLOT, ChnlAccessSetting->SlotTimeTimer);
+	write_nic_byte(dev, SLOT, chnl_access_setting->slot_time_timer);
 
-	write_nic_byte(dev, EIFS, ChnlAccessSetting->EIFS_Timer);
+	write_nic_byte(dev, EIFS, chnl_access_setting->eifs_timer);
 
 	/*
 	 * <RJ_EXPR_QOS> Suggested by wcchu, it is the default value of EIFS
diff --git a/drivers/staging/rtl8188eu/core/rtw_ap.c b/drivers/staging/rtl8188eu/core/rtw_ap.c
index 62a6147..0f1c1e5 100644
--- a/drivers/staging/rtl8188eu/core/rtw_ap.c
+++ b/drivers/staging/rtl8188eu/core/rtw_ap.c
@@ -94,7 +94,7 @@
 		} else {
 			tim_ielen = 0;
 
-			/* calucate head_len */
+			/* calculate head_len */
 			offset = _FIXED_IE_LENGTH_;
 			offset += pnetwork_mlmeext->Ssid.SsidLength + 2;
 
@@ -129,7 +129,7 @@
 		*dst_ie++ = tim_ielen;
 
 		*dst_ie++ = 0;/* DTIM count */
-		*dst_ie++ = 1;/* DTIM peroid */
+		*dst_ie++ = 1;/* DTIM period */
 
 		if (pstapriv->tim_bitmap&BIT(0))/* for bc/mc frames */
 			*dst_ie++ = BIT(0);/* bitmap ctrl */
@@ -821,7 +821,7 @@
 	/* update cur_wireless_mode */
 	update_wireless_mode(padapter);
 
-	/* udpate capability after cur_wireless_mode updated */
+	/* update capability after cur_wireless_mode updated */
 	update_capinfo(padapter, rtw_get_capability((struct wlan_bssid_ex *)pnetwork));
 
 	/* let pnetwork_mlmeext == pnetwork_mlme. */
@@ -1415,7 +1415,7 @@
 
 /*
 op_mode
-Set to 0 (HT pure) under the followign conditions
+Set to 0 (HT pure) under the following conditions
 	- all STAs in the BSS are 20/40 MHz HT in 20/40 MHz BSS or
 	- all STAs in the BSS are 20 MHz HT in 20 MHz BSS
 Set to 1 (HT non-member protection) if there may be non-HT STAs
@@ -1494,7 +1494,7 @@
 
 void associated_clients_update(struct adapter *padapter, u8 updated)
 {
-	/* update associcated stations cap. */
+	/* update associated stations cap. */
 	if (updated) {
 		struct list_head *phead, *plist;
 		struct sta_info *psta = NULL;
@@ -1647,7 +1647,7 @@
 		update_beacon(padapter, _HT_ADD_INFO_IE_, NULL, true);
 	}
 
-	/* update associcated stations cap. */
+	/* update associated stations cap. */
 	associated_clients_update(padapter,  beacon_updated);
 
 	DBG_88E("%s, updated =%d\n", __func__, beacon_updated);
@@ -1711,7 +1711,7 @@
 		update_beacon(padapter, _HT_ADD_INFO_IE_, NULL, true);
 	}
 
-	/* update associcated stations cap. */
+	/* update associated stations cap. */
 
 	DBG_88E("%s, updated =%d\n", __func__, beacon_updated);
 
diff --git a/drivers/staging/rtl8188eu/core/rtw_br_ext.c b/drivers/staging/rtl8188eu/core/rtw_br_ext.c
index 75e38d4..96c8a93 100644
--- a/drivers/staging/rtl8188eu/core/rtw_br_ext.c
+++ b/drivers/staging/rtl8188eu/core/rtw_br_ext.c
@@ -543,10 +543,10 @@
 			if (!__nat25_db_network_lookup_and_replace(priv, skb, networkAddr)) {
 				if (*((unsigned char *)&iph->daddr + 3) == 0xff) {
 					/*  L2 is unicast but L3 is broadcast, make L2 bacome broadcast */
-					DEBUG_INFO("NAT25: Set DA as boardcast\n");
+					DEBUG_INFO("NAT25: Set DA as broadcast\n");
 					memset(skb->data, 0xff, ETH_ALEN);
 				} else {
-					/*  forward unknow IP packet to upper TCP/IP */
+					/*  forward unknown IP packet to upper TCP/IP */
 					DEBUG_INFO("NAT25: Replace DA with BR's MAC\n");
 					if ((*(u32 *)priv->br_mac) == 0 && (*(u16 *)(priv->br_mac+4)) == 0) {
 						printk("Re-init netdev_br_init() due to br_mac == 0!\n");
@@ -932,7 +932,7 @@
 						(ph->code == PADO_CODE ? "PADO" : "PADS"),	skb->dev->name);
 				} else { /*  not add relay tag */
 					if (!priv->pppoe_connection_in_progress) {
-						DEBUG_ERR("Discard PPPoE packet due to no connection in progresss!\n");
+						DEBUG_ERR("Discard PPPoE packet due to no connection in progress!\n");
 						return -1;
 					}
 					memcpy(skb->data, priv->pppoe_addr, ETH_ALEN);
diff --git a/drivers/staging/rtl8188eu/core/rtw_debug.c b/drivers/staging/rtl8188eu/core/rtw_debug.c
index 1812ba9..78a7adf 100644
--- a/drivers/staging/rtl8188eu/core/rtw_debug.c
+++ b/drivers/staging/rtl8188eu/core/rtw_debug.c
@@ -233,7 +233,7 @@
 	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
 	int len = 0;
 
-	len += snprintf(page + len, count - len, "cur_ch=%d, cur_bw=%d, cur_ch_offet=%d\n",
+	len += snprintf(page + len, count - len, "cur_ch=%d, cur_bw=%d, cur_ch_offset=%d\n",
 					pmlmeext->cur_channel, pmlmeext->cur_bwmode, pmlmeext->cur_ch_offset);
 	*eof = 1;
 	return len;
diff --git a/drivers/staging/rtl8188eu/core/rtw_ioctl_set.c b/drivers/staging/rtl8188eu/core/rtw_ioctl_set.c
index 807b7d4..2a54e33 100644
--- a/drivers/staging/rtl8188eu/core/rtw_ioctl_set.c
+++ b/drivers/staging/rtl8188eu/core/rtw_ioctl_set.c
@@ -401,7 +401,7 @@
 
 		if ((*pold_state == Ndis802_11Infrastructure) || (*pold_state == Ndis802_11IBSS)) {
 			if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
-				rtw_indicate_disconnect(padapter); /* will clr Linked_state; before this function, we must have chked whether  issue dis-assoc_cmd or not */
+				rtw_indicate_disconnect(padapter); /* will clr Linked_state; before this function, we must have checked whether  issue dis-assoc_cmd or not */
 	       }
 
 		*pold_state = networktype;
@@ -563,7 +563,7 @@
 		break;
 	}
 	RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
-		 ("rtw_set_802_11_add_wep:befor memcpy, wep->KeyLength = 0x%x wep->KeyIndex = 0x%x  keyid =%x\n",
+		 ("rtw_set_802_11_add_wep:before memcpy, wep->KeyLength = 0x%x wep->KeyIndex = 0x%x  keyid =%x\n",
 		 wep->KeyLength, wep->KeyIndex, keyid));
 
 	memcpy(&(psecuritypriv->dot11DefKey[keyid].skey[0]), &(wep->KeyMaterial), wep->KeyLength);
diff --git a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c
index c197b22..4942759 100644
--- a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c
+++ b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c
@@ -171,7 +171,7 @@
 	{0x03},	/* 0x41, RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN_2G */
 };
 
-static struct rt_channel_plan_map RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE = {0x03}; /* use the conbination for max channel numbers */
+static struct rt_channel_plan_map RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE = {0x03}; /* use the combination for max channel numbers */
 
 /*
  * Search the @param channel_num in given @param channel_set
@@ -1942,7 +1942,7 @@
 	p2pie[p2pielen++] = 0x09;	/*	WFA P2P v1.0 */
 
 	/*	Commented by Albert 20110306 */
-	/*	According to the P2P Specification, the group negoitation request frame should contain 9 P2P attributes */
+	/*	According to the P2P Specification, the group negotiation request frame should contain 9 P2P attributes */
 	/*	1. P2P Capability */
 	/*	2. Group Owner Intent */
 	/*	3. Configuration Timeout */
@@ -2307,7 +2307,7 @@
 	p2pie[p2pielen++] = 0x09;	/*	WFA P2P v1.0 */
 
 	/*	Commented by Albert 20100908 */
-	/*	According to the P2P Specification, the group negoitation response frame should contain 9 P2P attributes */
+	/*	According to the P2P Specification, the group negotiation response frame should contain 9 P2P attributes */
 	/*	1. Status */
 	/*	2. P2P Capability */
 	/*	3. Group Owner Intent */
@@ -2609,7 +2609,7 @@
 	p2pie[p2pielen++] = 0x09;	/*	WFA P2P v1.0 */
 
 	/*	Commented by Albert 20110306 */
-	/*	According to the P2P Specification, the group negoitation request frame should contain 5 P2P attributes */
+	/*	According to the P2P Specification, the group negotiation request frame should contain 5 P2P attributes */
 	/*	1. Status */
 	/*	2. P2P Capability */
 	/*	3. Operating Channel */
@@ -4347,7 +4347,7 @@
 
 /****************************************************************************
 
-Following are some TX fuctions for WiFi MLME
+Following are some TX functions for WiFi MLME
 
 *****************************************************************************/
 
@@ -5001,7 +5001,7 @@
 	return ret;
 }
 
-/*  if psta == NULL, indiate we are station(client) now... */
+/*  if psta == NULL, indicate we are station(client) now... */
 void issue_auth(struct adapter *padapter, struct sta_info *psta, unsigned short status)
 {
 	struct xmit_frame *pmgntframe;
@@ -5612,7 +5612,7 @@
 	return;
 }
 
-/* when wait_ack is ture, this function shoule be called at process context */
+/* when wait_ack is true, this function should be called at process context */
 static int _issue_nulldata(struct adapter *padapter, unsigned char *da, unsigned int power_mode, int wait_ack)
 {
 	int ret = _FAIL;
@@ -5682,7 +5682,7 @@
 }
 
 
-/* when wait_ms > 0 , this function shoule be called at process context */
+/* when wait_ms > 0 , this function should be called at process context */
 /* da == NULL for station mode */
 int issue_nulldata(struct adapter *padapter, unsigned char *da, unsigned int power_mode, int try_cnt, int wait_ms)
 {
@@ -5692,7 +5692,7 @@
 	struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);
 	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
 
-	/* da == NULL, assum it's null data for sta to ap*/
+	/* da == NULL, assume it's null data for sta to ap*/
 	if (da == NULL)
 		da = get_my_bssid(&(pmlmeinfo->network));
 
@@ -5727,7 +5727,7 @@
 	return ret;
 }
 
-/* when wait_ack is ture, this function shoule be called at process context */
+/* when wait_ack is true, this function should be called at process context */
 static int _issue_qos_nulldata(struct adapter *padapter, unsigned char *da, u16 tid, int wait_ack)
 {
 	int ret = _FAIL;
@@ -5805,7 +5805,7 @@
 	return ret;
 }
 
-/* when wait_ms > 0 , this function shoule be called at process context */
+/* when wait_ms > 0 , this function should be called at process context */
 /* da == NULL for station mode */
 int issue_qos_nulldata(struct adapter *padapter, unsigned char *da, u16 tid, int try_cnt, int wait_ms)
 {
@@ -5815,7 +5815,7 @@
 	struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);
 	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
 
-	/* da == NULL, assum it's null data for sta to ap*/
+	/* da == NULL, assume it's null data for sta to ap*/
 	if (da == NULL)
 		da = get_my_bssid(&(pmlmeinfo->network));
 
@@ -6361,7 +6361,7 @@
 
 /****************************************************************************
 
-Following are some utitity fuctions for WiFi MLME
+Following are some utility functions for WiFi MLME
 
 *****************************************************************************/
 
@@ -6474,7 +6474,7 @@
 		{
 			/*  20100721:Interrupt scan operation here. */
 			/*  For SW antenna diversity before link, it needs to switch to another antenna and scan again. */
-			/*  It compares the scan result and select beter one to do connection. */
+			/*  It compares the scan result and select better one to do connection. */
 			if (rtw_hal_antdiv_before_linked(padapter)) {
 				pmlmeext->sitesurvey_res.bss_cnt = 0;
 				pmlmeext->sitesurvey_res.channel_idx = -1;
@@ -6713,7 +6713,7 @@
 	/* update wireless mode */
 	update_wireless_mode(padapter);
 
-	/* udpate capability */
+	/* update capability */
 	caps = rtw_get_capability((struct wlan_bssid_ex *)pnetwork);
 	update_capinfo(padapter, caps);
 	if (caps&cap_IBSS) {/* adhoc master */
@@ -6765,7 +6765,7 @@
 	/* update wireless mode */
 	update_wireless_mode(padapter);
 
-	/* udpate capability */
+	/* update capability */
 	caps = rtw_get_capability((struct wlan_bssid_ex *)pnetwork);
 	update_capinfo(padapter, caps);
 	if (caps&cap_ESS) {
@@ -7378,7 +7378,7 @@
 	/* turn on dynamic functions */
 	Switch_DM_Func(padapter, DYNAMIC_ALL_FUNC_ENABLE, true);
 
-	/*  update IOT-releated issue */
+	/*  update IOT-related issue */
 	update_IOT_info(padapter);
 
 	rtw_hal_set_hwreg(padapter, HW_VAR_BASIC_RATE, cur_network->SupportedRates);
@@ -7386,7 +7386,7 @@
 	/* BCN interval */
 	rtw_hal_set_hwreg(padapter, HW_VAR_BEACON_INTERVAL, (u8 *)(&pmlmeinfo->bcn_interval));
 
-	/* udpate capability */
+	/* update capability */
 	update_capinfo(padapter, pmlmeinfo->capability);
 
 	/* WMM, Update EDCA param */
diff --git a/drivers/staging/rtl8188eu/core/rtw_mp.c b/drivers/staging/rtl8188eu/core/rtw_mp.c
index 99c06c4..2e02b20 100644
--- a/drivers/staging/rtl8188eu/core/rtw_mp.c
+++ b/drivers/staging/rtl8188eu/core/rtw_mp.c
@@ -407,7 +407,7 @@
 		goto end_of_mp_start_test;
 	}
 
-	/* 3 3. join psudo AdHoc */
+	/* 3 3. join pseudo AdHoc */
 	tgt_network->join_res = 1;
 	tgt_network->aid = 1;
 	psta->aid = 1;
@@ -443,7 +443,7 @@
 		if (check_fwstate(pmlmepriv, WIFI_MP_STATE) == false)
 			goto end_of_mp_stop_test;
 
-		/* 3 1. disconnect psudo AdHoc */
+		/* 3 1. disconnect pseudo AdHoc */
 		rtw_indicate_disconnect(padapter);
 
 		/* 3 2. clear psta used in mp test mode. */
diff --git a/drivers/staging/rtl8188eu/core/rtw_pwrctrl.c b/drivers/staging/rtl8188eu/core/rtw_pwrctrl.c
index 491d6af..f658373 100644
--- a/drivers/staging/rtl8188eu/core/rtw_pwrctrl.c
+++ b/drivers/staging/rtl8188eu/core/rtw_pwrctrl.c
@@ -515,7 +515,7 @@
 /*
 * rtw_pwr_wakeup - Wake the NIC up from: 1)IPS. 2)USB autosuspend
 * @adapter: pointer to struct adapter structure
-* @ips_deffer_ms: the ms wiil prevent from falling into IPS after wakeup
+* @ips_deffer_ms: the ms will prevent from falling into IPS after wakeup
 * Return _SUCCESS or _FAIL
 */
 
diff --git a/drivers/staging/rtl8188eu/core/rtw_recv.c b/drivers/staging/rtl8188eu/core/rtw_recv.c
index 0c8b338..636ec55 100644
--- a/drivers/staging/rtl8188eu/core/rtw_recv.c
+++ b/drivers/staging/rtl8188eu/core/rtw_recv.c
@@ -1123,7 +1123,7 @@
 				if (psta->sleepq_len == 0) {
 					pstapriv->tim_bitmap &= ~BIT(psta->aid);
 
-					/* upate BCN for TIM IE */
+					/* update BCN for TIM IE */
 					/* update_BCNTIM(padapter); */
 					update_beacon(padapter, _TIM_IE_, NULL, false);
 				}
@@ -1141,7 +1141,7 @@
 
 					pstapriv->tim_bitmap &= ~BIT(psta->aid);
 
-					/* upate BCN for TIM IE */
+					/* update BCN for TIM IE */
 					/* update_BCNTIM(padapter); */
 					update_beacon(padapter, _TIM_IE_, NULL, false);
 				}
@@ -2236,13 +2236,13 @@
 	} else {
 		if (recvpriv->signal_strength_data.update_req == 0) {/*  update_req is clear, means we got rx */
 			avg_signal_strength = recvpriv->signal_strength_data.avg_val;
-			/*  after avg_vals are accquired, we can re-stat the signal values */
+			/*  after avg_vals are acquired, we can re-stat the signal values */
 			recvpriv->signal_strength_data.update_req = 1;
 		}
 
 		if (recvpriv->signal_qual_data.update_req == 0) {/*  update_req is clear, means we got rx */
 			avg_signal_qual = recvpriv->signal_qual_data.avg_val;
-			/*  after avg_vals are accquired, we can re-stat the signal values */
+			/*  after avg_vals are acquired, we can re-stat the signal values */
 			recvpriv->signal_qual_data.update_req = 1;
 		}
 
diff --git a/drivers/staging/rtl8188eu/core/rtw_wlan_util.c b/drivers/staging/rtl8188eu/core/rtw_wlan_util.c
index f64b979..3dd9059 100644
--- a/drivers/staging/rtl8188eu/core/rtw_wlan_util.c
+++ b/drivers/staging/rtl8188eu/core/rtw_wlan_util.c
@@ -1050,7 +1050,7 @@
 	}
 
 	if (cur_network->BcnInfo.encryp_protocol != encryp_protocol) {
-		DBG_88E("%s(): enctyp is not match , return FAIL\n", __func__);
+		DBG_88E("%s(): encryption protocol is not match , return FAIL\n", __func__);
 		goto _mismatch;
 	}
 
diff --git a/drivers/staging/rtl8188eu/core/rtw_xmit.c b/drivers/staging/rtl8188eu/core/rtw_xmit.c
index b0e9798..8d4265f 100644
--- a/drivers/staging/rtl8188eu/core/rtw_xmit.c
+++ b/drivers/staging/rtl8188eu/core/rtw_xmit.c
@@ -1950,7 +1950,7 @@
 			pstapriv->tim_bitmap |= BIT(0);/*  */
 			pstapriv->sta_dz_bitmap |= BIT(0);
 
-			update_beacon(padapter, _TIM_IE_, NULL, false);/* tx bc/mc packets after upate bcn */
+			update_beacon(padapter, _TIM_IE_, NULL, false);/* tx bc/mc packets after update bcn */
 
 			ret = true;
 		}
@@ -2000,7 +2000,7 @@
 				pstapriv->tim_bitmap |= BIT(psta->aid);
 
 				if (psta->sleepq_len == 1) {
-					/* upate BCN for TIM IE */
+					/* update BCN for TIM IE */
 					update_beacon(padapter, _TIM_IE_, NULL, false);
 				}
 			}
@@ -2269,7 +2269,7 @@
 		if ((psta->sleepq_ac_len == 0) && (!psta->has_legacy_ac) && (wmmps_ac)) {
 			pstapriv->tim_bitmap &= ~BIT(psta->aid);
 
-			/* upate BCN for TIM IE */
+			/* update BCN for TIM IE */
 			update_beacon(padapter, _TIM_IE_, NULL, false);
 		}
 	}
diff --git a/drivers/staging/rtl8188eu/os_dep/os_intfs.c b/drivers/staging/rtl8188eu/os_dep/os_intfs.c
index f123a93..b225d1c 100644
--- a/drivers/staging/rtl8188eu/os_dep/os_intfs.c
+++ b/drivers/staging/rtl8188eu/os_dep/os_intfs.c
@@ -651,7 +651,7 @@
 }
 
 static u16 rtw_select_queue(struct net_device *dev, struct sk_buff *skb,
-			    void *accel_priv)
+			    void *accel_priv, select_queue_fallback_t fallback)
 {
 	struct adapter	*padapter = rtw_netdev_priv(dev);
 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
diff --git a/drivers/staging/rtl8188eu/os_dep/usb_intf.c b/drivers/staging/rtl8188eu/os_dep/usb_intf.c
index 6f3a609..2e49cd5 100644
--- a/drivers/staging/rtl8188eu/os_dep/usb_intf.c
+++ b/drivers/staging/rtl8188eu/os_dep/usb_intf.c
@@ -56,6 +56,7 @@
 	/****** 8188EUS ********/
 	{USB_DEVICE(0x07b8, 0x8179)}, /* Abocom - Abocom */
 	{USB_DEVICE(0x2001, 0x330F)}, /* DLink DWA-125 REV D1 */
+	{USB_DEVICE(0x2001, 0x3310)}, /* Dlink DWA-123 REV D1 */
 	{}	/* Terminating entry */
 };
 
diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_pci.h b/drivers/staging/rtl8192e/rtl8192e/rtl_pci.h
index 356aec4..4b94653 100644
--- a/drivers/staging/rtl8192e/rtl8192e/rtl_pci.h
+++ b/drivers/staging/rtl8192e/rtl8192e/rtl_pci.h
@@ -28,31 +28,6 @@
 #include <linux/types.h>
 #include <linux/pci.h>
 
-static inline void NdisRawWritePortUlong(u32 port,  u32 val)
-{
-	outl(val, port);
-}
-
-static inline void NdisRawWritePortUchar(u32 port,  u8 val)
-{
-	outb(val, port);
-}
-
-static inline void NdisRawReadPortUchar(u32 port, u8 *pval)
-{
-	*pval = inb(port);
-}
-
-static inline void NdisRawReadPortUshort(u32 port, u16 *pval)
-{
-	*pval = inw(port);
-}
-
-static inline void NdisRawReadPortUlong(u32 port, u32 *pval)
-{
-	*pval = inl(port);
-}
-
 struct mp_adapter {
 	u8		LinkCtrlReg;
 
@@ -70,33 +45,6 @@
 	u8		PciBridgeLinkCtrlReg;
 };
 
-struct rt_pci_capab_header {
-	unsigned char   CapabilityID;
-	unsigned char   Next;
-};
-
-#define PCI_MAX_BRIDGE_NUMBER				255
-#define PCI_MAX_DEVICES						32
-#define PCI_MAX_FUNCTION					8
-
-#define PCI_CONF_ADDRESS					0x0CF8
-#define PCI_CONF_DATA						0x0CFC
-
-#define	PCI_CLASS_BRIDGE_DEV				0x06
-#define	PCI_SUBCLASS_BR_PCI_TO_PCI		0x04
-
-#define	U1DONTCARE						0xFF
-#define	U2DONTCARE						0xFFFF
-#define	U4DONTCARE						0xFFFFFFFF
-
-#define	INTEL_VENDOR_ID					0x8086
-#define	SIS_VENDOR_ID						0x1039
-#define	ATI_VENDOR_ID						0x1002
-#define	ATI_DEVICE_ID						0x7914
-#define	AMD_VENDOR_ID						0x1022
-
-#define PCI_CAPABILITY_ID_PCI_EXPRESS		0x10
-
 struct net_device;
 bool rtl8192_pci_findadapter(struct pci_dev *pdev, struct net_device *dev);
 
diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_wx.c b/drivers/staging/rtl8192e/rtl8192e/rtl_wx.c
index 6202358..498995d 100644
--- a/drivers/staging/rtl8192e/rtl8192e/rtl_wx.c
+++ b/drivers/staging/rtl8192e/rtl8192e/rtl_wx.c
@@ -609,7 +609,7 @@
 	if (wrqu->data.length > IW_ESSID_MAX_SIZE)
 		return -E2BIG;
 	down(&priv->wx_sem);
-	wrqu->data.length = min((size_t) wrqu->data.length, sizeof(priv->nick));
+	wrqu->data.length = min_t(size_t, wrqu->data.length, sizeof(priv->nick));
 	memset(priv->nick, 0, sizeof(priv->nick));
 	memcpy(priv->nick, extra, wrqu->data.length);
 	up(&priv->wx_sem);
diff --git a/drivers/staging/rtl8821ae/base.c b/drivers/staging/rtl8821ae/base.c
index da04f03..fce9c3f 100644
--- a/drivers/staging/rtl8821ae/base.c
+++ b/drivers/staging/rtl8821ae/base.c
@@ -39,10 +39,10 @@
 #include "pci.h"
 
 /*
- *NOTICE!!!: This file will be very big, we hsould
- *keep it clear under follwing roles:
+ *NOTICE!!!: This file will be very big, we should
+ *keep it clear under following roles:
  *
- *This file include follwing part, so, if you add new
+ *This file include following part, so, if you add new
  *functions into this file, please check which part it
  *should includes. or check if you should add new part
  *for this file:
@@ -662,7 +662,7 @@
 
 	if (rtlpriv->dm.b_useramask) {
 		tcb_desc->ratr_index = ratr_index;
-		/* TODO we will differentiate adhoc and station futrue  */
+		/* TODO we will differentiate adhoc and station future  */
 		if (mac->opmode == NL80211_IFTYPE_STATION ||
 			mac->opmode == NL80211_IFTYPE_MESH_POINT) {
 			tcb_desc->mac_id = 0;
@@ -772,10 +772,10 @@
 			tcb_desc->disable_ratefallback = 1;
 		} else {
 			/*
-			 *because hw will nerver use hw_rate
+			 *because hw will never use hw_rate
 			 *when tcb_desc->use_driver_rate = false
 			 *so we never set highest N rate here,
-			 *and N rate will all be controled by FW
+			 *and N rate will all be controlled by FW
 			 *when tcb_desc->use_driver_rate = false
 			 */
 			if (sta && (sta->ht_cap.ht_supported)) {
@@ -1671,7 +1671,7 @@
 		(memcmp(mac->bssid, ap4_2, 3) == 0) ||
 		(memcmp(mac->bssid, ap4_3, 3) == 0) ||
 		vendor == PEER_RAL) {
-		RT_TRACE(COMP_MAC80211, DBG_LOUD, ("=>ral findn\n"));
+		RT_TRACE(COMP_MAC80211, DBG_LOUD, ("=>ral find\n"));
 		vendor = PEER_RAL;
 	} else if (memcmp(mac->bssid, ap6_1, 3) == 0 ||
 		vendor == PEER_CISCO) {
diff --git a/drivers/staging/rtl8821ae/btcoexist/HalBtc8812a1Ant.c b/drivers/staging/rtl8821ae/btcoexist/HalBtc8812a1Ant.c
index b30f17a..5a54bb1 100644
--- a/drivers/staging/rtl8821ae/btcoexist/HalBtc8812a1Ant.c
+++ b/drivers/staging/rtl8821ae/btcoexist/HalBtc8812a1Ant.c
@@ -1653,7 +1653,7 @@
 	}
 	else
 	{
-		//accquire the BT TRx retry count from BT_Info byte2
+		//acquire the BT TRx retry count from BT_Info byte2
 		retry_count = coex_sta->bt_retry_cnt;
 		bt_info_ext = coex_sta->bt_info_ext;
 		BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, ("[BTCoex], retry_count = %d\n", retry_count));
diff --git a/drivers/staging/rtl8821ae/btcoexist/habtc8723a1ant.c b/drivers/staging/rtl8821ae/btcoexist/habtc8723a1ant.c
index e619923..8e4293a 100644
--- a/drivers/staging/rtl8821ae/btcoexist/habtc8723a1ant.c
+++ b/drivers/staging/rtl8821ae/btcoexist/habtc8723a1ant.c
@@ -629,7 +629,7 @@
 	}
 	else
 	{
-		//accquire the BT TRx retry count from BT_Info byte2
+		//acquire the BT TRx retry count from BT_Info byte2
 		retryCount = pCoexSta->btRetryCnt;
 		BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], retryCount = %d\n", retryCount));
 		result = 0;
diff --git a/drivers/staging/rtl8821ae/btcoexist/halbtc8192e1ant.c b/drivers/staging/rtl8821ae/btcoexist/halbtc8192e1ant.c
index 973d0ea..1b04530 100644
--- a/drivers/staging/rtl8821ae/btcoexist/halbtc8192e1ant.c
+++ b/drivers/staging/rtl8821ae/btcoexist/halbtc8192e1ant.c
@@ -1721,7 +1721,7 @@
 	}
 	else
 	{
-		//accquire the BT TRx retry count from BT_Info byte2
+		//acquire the BT TRx retry count from BT_Info byte2
 		retryCount = pCoexSta->btRetryCnt;
 		btInfoExt = pCoexSta->btInfoExt;
 		BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, ("[BTCoex], retryCount = %d\n", retryCount));
diff --git a/drivers/staging/rtl8821ae/btcoexist/halbtc8192e2ant.c b/drivers/staging/rtl8821ae/btcoexist/halbtc8192e2ant.c
index 44ec785..1159089 100644
--- a/drivers/staging/rtl8821ae/btcoexist/halbtc8192e2ant.c
+++ b/drivers/staging/rtl8821ae/btcoexist/halbtc8192e2ant.c
@@ -1803,7 +1803,7 @@
 		result = 0;
 		wait_cnt = 0;
 	} else {
-		/* accquire the BT TRx retry count from BT_Info byte2 */
+		/* acquire the BT TRx retry count from BT_Info byte2 */
 		retry_cnt = coex_sta->bt_retry_cnt;
 		BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL,
 			  "[BTCoex], retry_cnt = %d\n", retry_cnt);
diff --git a/drivers/staging/rtl8821ae/btcoexist/halbtc8723a2ant.c b/drivers/staging/rtl8821ae/btcoexist/halbtc8723a2ant.c
index 180d6f1..3f5c4fd 100644
--- a/drivers/staging/rtl8821ae/btcoexist/halbtc8723a2ant.c
+++ b/drivers/staging/rtl8821ae/btcoexist/halbtc8723a2ant.c
@@ -1687,7 +1687,7 @@
 	}
 	else
 	{
-		//accquire the BT TRx retry count from BT_Info byte2
+		//acquire the BT TRx retry count from BT_Info byte2
 		retryCount = pCoexSta->btRetryCnt;
 		BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, ("[BTCoex], retryCount = %d\n", retryCount));
 		BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, ("[BTCoex], up=%d, dn=%d, m=%d, n=%d, WaitCount=%d\n", 
diff --git a/drivers/staging/rtl8821ae/btcoexist/halbtc8723b1ant.c b/drivers/staging/rtl8821ae/btcoexist/halbtc8723b1ant.c
index 3414ba7..9677943 100644
--- a/drivers/staging/rtl8821ae/btcoexist/halbtc8723b1ant.c
+++ b/drivers/staging/rtl8821ae/btcoexist/halbtc8723b1ant.c
@@ -1950,7 +1950,7 @@
 		result = 0;
 		wait_count = 0;
 	} else {
-		/*accquire the BT TRx retry count from BT_Info byte2 */
+		/*acquire the BT TRx retry count from BT_Info byte2 */
 		retry_count = coex_sta->bt_retry_cnt;
 		bt_info_ext = coex_sta->bt_info_ext;
 		result = 0;
diff --git a/drivers/staging/rtl8821ae/btcoexist/halbtc8723b2ant.c b/drivers/staging/rtl8821ae/btcoexist/halbtc8723b2ant.c
index 83b1b42..d337bd0 100644
--- a/drivers/staging/rtl8821ae/btcoexist/halbtc8723b2ant.c
+++ b/drivers/staging/rtl8821ae/btcoexist/halbtc8723b2ant.c
@@ -1830,7 +1830,7 @@
 		result = 0;
 		wait_count = 0;
 	} else {
-		/*accquire the BT TRx retry count from BT_Info byte2*/
+		/*acquire the BT TRx retry count from BT_Info byte2*/
 		retryCount = coex_sta->bt_retry_cnt;
 		BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL,
 			  "[BTCoex], retryCount = %d\n", retryCount);
diff --git a/drivers/staging/rtl8821ae/core.c b/drivers/staging/rtl8821ae/core.c
index 40de608..ff3139b 100644
--- a/drivers/staging/rtl8821ae/core.c
+++ b/drivers/staging/rtl8821ae/core.c
@@ -373,7 +373,7 @@
 			/* sleep here is must, or we may recv the beacon and
 			 * cause mac80211 into wrong ps state, this will cause
 			 * power save nullfunc send fail, and further cause
-			 * pkt loss, So sleep must quickly but not immediatly
+			 * pkt loss, So sleep must quickly but not immediately
 			 * because that will cause nullfunc send by mac80211
 			 * fail, and cause pkt loss, we have tested that 5mA
 			 * is worked very well */
@@ -1200,8 +1200,8 @@
 		key_type = AESCMAC_ENCRYPTION;
 		RT_TRACE(COMP_SEC, DBG_DMESG, ("alg:CMAC\n"));
 		RT_TRACE(COMP_SEC, DBG_DMESG,
-				("HW don't support CMAC encrypiton, "
-				"use software CMAC encrypiton\n"));
+				("HW don't support CMAC encryption, "
+				"use software CMAC encryption\n"));
 		err = -EOPNOTSUPP;
 		goto out_unlock;
 	default:
@@ -1235,8 +1235,8 @@
 		key_type = AESCMAC_ENCRYPTION;
 		RT_TRACE(COMP_SEC, DBG_DMESG, ("alg:CMAC\n"));
 		RT_TRACE(COMP_SEC, DBG_DMESG,
-			 ("HW don't support CMAC encrypiton, "
-			  "use software CMAC encrypiton\n"));
+			 ("HW don't support CMAC encryption, "
+			  "use software CMAC encryption\n"));
 		err = -EOPNOTSUPP;
 		goto out_unlock;
 	default:
@@ -1411,7 +1411,7 @@
 }
 
 /* this function is called by mac80211 to flush tx buffer
- * before switch channle or power save, or tx buffer packet
+ * before switch channel or power save, or tx buffer packet
  * maybe send after offchannel or rf sleep, this may cause
  * dis-association by AP */
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0))
diff --git a/drivers/staging/rtl8821ae/core.h b/drivers/staging/rtl8821ae/core.h
index 4b247db..f0c74e9 100644
--- a/drivers/staging/rtl8821ae/core.h
+++ b/drivers/staging/rtl8821ae/core.h
@@ -2,20 +2,20 @@
  *
  * Copyright(c) 2009-2010  Realtek Corporation.
  *
- * Tmis program is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of version 2 of the GNU General Public License as
  * published by the Free Software Foundation.
  *
- * Tmis program is distributed in the hope that it will be useful, but WITHOUT
+ * 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
- * tmis program; if not, write to the Free Software Foundation, Inc.,
+ * this program; if not, write to the Free Software Foundation, Inc.,
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
  *
- * Tme full GNU General Public License is included in this distribution in the
+ * The full GNU General Public License is included in this distribution in the
  * file called LICENSE.
  *
  * Contact Information:
diff --git a/drivers/staging/rtl8821ae/debug.c b/drivers/staging/rtl8821ae/debug.c
index cb05122..8a6c794 100644
--- a/drivers/staging/rtl8821ae/debug.c
+++ b/drivers/staging/rtl8821ae/debug.c
@@ -2,20 +2,20 @@
  *
  * Copyright(c) 2009-2010  Realtek Corporation.
  *
- * Tmis program is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of version 2 of the GNU General Public License as
  * published by the Free Software Foundation.
  *
- * Tmis program is distributed in the hope that it will be useful, but WITHOUT
+ * 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
- * tmis program; if not, write to the Free Software Foundation, Inc.,
+ * this program; if not, write to the Free Software Foundation, Inc.,
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
  *
- * Tme full GNU General Public License is included in this distribution in the
+ * The full GNU General Public License is included in this distribution in the
  * file called LICENSE.
  *
  * Contact Information:
@@ -985,4 +985,4 @@
 {
 	if (proc_topdir)
 		remove_proc_entry("rtlwifi", init_net.proc_net);
-}
\ No newline at end of file
+}
diff --git a/drivers/staging/rtl8821ae/debug.h b/drivers/staging/rtl8821ae/debug.h
index 5eb6251..6c0a553 100644
--- a/drivers/staging/rtl8821ae/debug.h
+++ b/drivers/staging/rtl8821ae/debug.h
@@ -2,20 +2,20 @@
  *
  * Copyright(c) 2009-2010  Realtek Corporation.
  *
- * Tmis program is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of version 2 of the GNU General Public License as
  * published by the Free Software Foundation.
  *
- * Tmis program is distributed in the hope that it will be useful, but WITHOUT
+ * 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
- * tmis program; if not, write to the Free Software Foundation, Inc.,
+ * this program; if not, write to the Free Software Foundation, Inc.,
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
  *
- * Tme full GNU General Public License is included in this distribution in the
+ * The full GNU General Public License is included in this distribution in the
  * file called LICENSE.
  *
  * Contact Information:
@@ -44,7 +44,7 @@
 #define DBG_EMERG			0
 
 /*
- *Abnormal, rare, or unexpeted cases.
+ *Abnormal, rare, or unexpected cases.
  *For example, Packet/IO Ctl canceled,
  *device suprisely unremoved and so on.
  */
@@ -54,7 +54,7 @@
  *Normal case driver developer should
  *open, we can see link status like
  *assoc/AddBA/DHCP/adapter start and
- *so on basic and useful infromations.
+ *so on basic and useful informations.
  */
 #define DBG_DMESG			3
 
diff --git a/drivers/staging/rtl8821ae/efuse.c b/drivers/staging/rtl8821ae/efuse.c
index 74c19ec..250aae1 100644
--- a/drivers/staging/rtl8821ae/efuse.c
+++ b/drivers/staging/rtl8821ae/efuse.c
@@ -2,20 +2,20 @@
  *
  * Copyright(c) 2009-2010  Realtek Corporation.
  *
- * Tmis program is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
  * under the terms of version 2 of the GNU General Public License as
  * published by the Free Software Foundation.
  *
- * Tmis program is distributed in the hope that it will be useful, but WITHOUT
+ * 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
- * tmis program; if not, write to the Free Software Foundation, Inc.,
+ * this program; if not, write to the Free Software Foundation, Inc.,
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
  *
- * Tme full GNU General Public License is included in this distribution in the
+ * The full GNU General Public License is included in this distribution in the
  * file called LICENSE.
  *
  * Contact Information:
@@ -149,7 +149,7 @@
 		return 0xFF;
 
 }
-//EXPORT_SYMBOL(efuse_read_1byte);
+/* EXPORT_SYMBOL(efuse_read_1byte); */
 
 void efuse_write_1byte(struct ieee80211_hw *hw, u16 address, u8 value)
 {
@@ -517,7 +517,7 @@
 			rtlpriv->cfg->maps[EFUSE_HWSET_MAX_SIZE]);
 
 }
-//EXPORT_SYMBOL(rtl_efuse_shadow_map_update);
+/* EXPORT_SYMBOL(rtl_efuse_shadow_map_update); */
 
 void efuse_force_write_vendor_Id(struct ieee80211_hw *hw)
 {
@@ -628,7 +628,7 @@
 	}
 	return bresult;
 }
-//EXPORT_SYMBOL(efuse_one_byte_read);
+/* EXPORT_SYMBOL(efuse_one_byte_read); */
 
 static int efuse_one_byte_write(struct ieee80211_hw *hw, u16 addr, u8 data)
 {
@@ -1120,16 +1120,16 @@
 		{
 			rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_ACCESS], 0x69);
 
-			// 1.2V Power: From VDDON with Power Cut(0x0000h[15]), defualt valid
+			/* 1.2V Power: From VDDON with Power Cut(0x0000h[15]), default valid */
 			tmpV16 = rtl_read_word(rtlpriv,
 					       rtlpriv->cfg->maps[SYS_ISO_CTRL]);
 
 			printk("SYS_ISO_CTRL=%04x.\n",tmpV16);
 			if( ! (tmpV16 & PWC_EV12V ) ){
 				tmpV16 |= PWC_EV12V ;
-				 //PlatformEFIOWrite2Byte(pAdapter,REG_SYS_ISO_CTRL,tmpV16);
+				 /* PlatformEFIOWrite2Byte(pAdapter,REG_SYS_ISO_CTRL,tmpV16); */
 			}
-			// Reset: 0x0000h[28], default valid
+			/* Reset: 0x0000h[28], default valid */
  			tmpV16 = rtl_read_word(rtlpriv,  rtlpriv->cfg->maps[SYS_FUNC_EN]);
 			printk("SYS_FUNC_EN=%04x.\n",tmpV16);
 			if( !(tmpV16 & FEN_ELDR) ){
@@ -1137,7 +1137,7 @@
 				rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[SYS_FUNC_EN], tmpV16);
 			}
 
-			// Clock: Gated(0x0008h[5]) 8M(0x0008h[1]) clock from ANA, default valid
+			/* Clock: Gated(0x0008h[5]) 8M(0x0008h[1]) clock from ANA, default valid */
 			tmpV16 = rtl_read_word(rtlpriv,  rtlpriv->cfg->maps[SYS_CLK] );
 			printk("SYS_CLK=%04x.\n",tmpV16);
 			if( (!(tmpV16 & LOADER_CLK_EN) )  ||(!(tmpV16 & ANA8M) ) )
@@ -1148,7 +1148,7 @@
 
 			if(bwrite == true)
 			{
-				// Enable LDO 2.5V before read/write action
+				/* Enable LDO 2.5V before read/write action */
 				tempval = rtl_read_word(rtlpriv,  rtlpriv->cfg->maps[EFUSE_TEST] + 3);
 				printk("EFUSE_TEST=%04x.\n",tmpV16);
 				tempval &= ~(BIT(3) | BIT(4) |BIT(5) | BIT(6));
@@ -1161,7 +1161,7 @@
 		{
 			rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_ACCESS], 0x00);
 			if(bwrite == true){
-				// Disable LDO 2.5V after read/write action
+				/* Disable LDO 2.5V after read/write action */
 				tempval = rtl_read_word(rtlpriv,  rtlpriv->cfg->maps[EFUSE_TEST] + 3);
 				rtl_write_byte(rtlpriv,  rtlpriv->cfg->maps[EFUSE_TEST] + 3, (tempval & 0x7F));
 			}
diff --git a/drivers/staging/rtl8821ae/pci.c b/drivers/staging/rtl8821ae/pci.c
index 618a3cb..a562aa6 100644
--- a/drivers/staging/rtl8821ae/pci.c
+++ b/drivers/staging/rtl8821ae/pci.c
@@ -583,7 +583,7 @@
 		(rtlpriv->buddy_priv &&
 		 rtlpriv->buddy_priv->easy_concurrent_ctl.bswitch_in_process)))
 		return;
-	/* we juse use em for BE/BK/VI/VO */
+	/* we just use em for BE/BK/VI/VO */
 	for (tid = 7; tid >= 0; tid--) {
 		u8 hw_queue = ac_to_hwq[rtl_tid_to_ac(hw, tid)];
 		struct rtl8192_tx_ring *ring = &rtlpci->tx_ring[hw_queue];
@@ -672,7 +672,7 @@
 		}
 
 		/* for sw LPS, just after NULL skb send out, we can
-		 * sure AP kown we are sleeped, our we should not let
+		 * sure AP known we are slept, our we should not let
 		 * rf to sleep*/
 		fc = rtl_get_fc(skb);
 		if (ieee80211_is_nullfunc(fc)) {
@@ -772,7 +772,7 @@
 	return 1;
 }
 
-/* inorder to receive 8K AMSDU we have set skb to
+/* In order to receive 8K AMSDU we have set skb to
  * 9100bytes in init rx ring, but if this packet is
  * not a AMSDU, this so big packet will be sent to
  * TCP/IP directly, this cause big packet ping fail
@@ -783,7 +783,7 @@
 /* but some platform will fail when alloc skb sometimes.
  * in this condition, we will send the old skb to
  * mac80211 directly, this will not cause any other
- * issues, but only be losted by TCP/IP */
+ * issues, but only be lost by TCP/IP */
 static void _rtl_pci_rx_to_mac80211(struct ieee80211_hw *hw,
 	struct sk_buff *skb, struct ieee80211_rx_status rx_status)
 {
@@ -1029,7 +1029,7 @@
 	rtlpriv->cfg->ops->interrupt_recognized(hw, &inta, &intb);
 
 
-	/*Shared IRQ or HW disappared */
+	/*Shared IRQ or HW disappeared */
 	if (!inta || inta == 0xffff)
 		goto done;
 	/*<1> beacon related */
@@ -1936,7 +1936,7 @@
 	u8 RFInProgressTimeOut = 0;
 
 	/*
-	 *should before disable interrrupt&adapter
+	 *should before disable interrupt&adapter
 	 *and will do it immediately.
 	 */
 	set_hal_stop(rtlhal);
@@ -2293,7 +2293,7 @@
 	/*
 	 *init dbgp flags before all
 	 *other functions, because we will
-	 *use it in other funtions like
+	 *use it in other functions like
 	 *RT_TRACE/RT_PRINT/RTL_PRINT_DATA
 	 *you can not use these macro
 	 *before this
@@ -2428,13 +2428,13 @@
 	return -ENODEV;
 
 }
-//EXPORT_SYMBOL(rtl_pci_probe);
+/* EXPORT_SYMBOL(rtl_pci_probe); */
 
 struct ieee80211_hw *rtl_pci_get_hw_pointer(void)
 {
 	return hw_export;
 }
-//EXPORT_SYMBOL(rtl_pci_get_hw_pointer);
+/* EXPORT_SYMBOL(rtl_pci_get_hw_pointer); */
 
 void rtl_pci_disconnect(struct pci_dev *pdev)
 {
@@ -2491,7 +2491,7 @@
 
 	ieee80211_free_hw(hw);
 }
-//EXPORT_SYMBOL(rtl_pci_disconnect);
+/* EXPORT_SYMBOL(rtl_pci_disconnect); */
 
 /***************************************
 kernel pci power state define:
@@ -2519,7 +2519,7 @@
 
 	return 0;
 }
-//EXPORT_SYMBOL(rtl_pci_suspend);
+/* EXPORT_SYMBOL(rtl_pci_suspend); */
 
 int rtl_pci_resume(struct device *dev)
 {
@@ -2532,7 +2532,7 @@
 
 	return 0;
 }
-//EXPORT_SYMBOL(rtl_pci_resume);
+/* EXPORT_SYMBOL(rtl_pci_resume); */
 
 struct rtl_intf_ops rtl_pci_ops = {
 	.read_efuse_byte = read_efuse_byte,
diff --git a/drivers/staging/rtl8821ae/pci.h b/drivers/staging/rtl8821ae/pci.h
index 9f20655..06eaa52 100644
--- a/drivers/staging/rtl8821ae/pci.h
+++ b/drivers/staging/rtl8821ae/pci.h
@@ -148,11 +148,11 @@
   * RX wifi info == RX descriptor in old flow */
 struct rtl_tx_buffer_desc {
 #if (RTL8192EE_SEG_NUM == 2)
-	u32 dword[2*(DMA_IS_64BIT + 1)*8]; //seg = 8
+	u32 dword[2*(DMA_IS_64BIT + 1)*8]; /* seg = 8 */
 #elif (RTL8192EE_SEG_NUM == 1)
-	u32 dword[2*(DMA_IS_64BIT + 1)*4]; //seg = 4
+	u32 dword[2*(DMA_IS_64BIT + 1)*4]; /* seg = 4 */
 #elif (RTL8192EE_SEG_NUM == 0)
-	u32 dword[2*(DMA_IS_64BIT + 1)*2]; //seg = 2
+	u32 dword[2*(DMA_IS_64BIT + 1)*2]; /* seg = 2 */
 #endif
 } __packed;
 
@@ -187,7 +187,7 @@
 };
 
 struct rtl8192_rx_ring {
-	struct rtl_rx_desc *desc;/*for old trx flow, not uesd in new trx*/
+	struct rtl_rx_desc *desc;/*for old trx flow, not used in new trx*/
 	/*dma matches either 'desc' or 'buffer_desc'*/
 	dma_addr_t dma;
 	unsigned int idx;
diff --git a/drivers/staging/rtl8821ae/ps.c b/drivers/staging/rtl8821ae/ps.c
index f12ffa8..7876442 100644
--- a/drivers/staging/rtl8821ae/ps.c
+++ b/drivers/staging/rtl8821ae/ps.c
@@ -257,7 +257,7 @@
 		 *Do not enter IPS in the following conditions:
 		 *(1) RF is already OFF or Sleep
 		 *(2) b_swrf_processing (indicates the IPS is still under going)
-		 *(3) Connectted (only disconnected can trigger IPS)
+		 *(3) Connected (only disconnected can trigger IPS)
 		 *(4) IBSS (send Beacon)
 		 *(5) AP mode (send Beacon)
 		 *(6) monitor mode (rcv packet)
diff --git a/drivers/staging/rtl8821ae/regd.c b/drivers/staging/rtl8821ae/regd.c
index d89f15c..0a4b398 100644
--- a/drivers/staging/rtl8821ae/regd.c
+++ b/drivers/staging/rtl8821ae/regd.c
@@ -243,7 +243,7 @@
 	}
 
 	/*
-	 *If a country IE has been recieved check its rule for this
+	 *If a country IE has been received check its rule for this
 	 *channel first before enabling active scan. The passive scan
 	 *would have been enforced by the initial processing of our
 	 *custom regulatory domain.
@@ -455,7 +455,7 @@
 
 	if (rtlpriv->regd.country_code >= COUNTRY_CODE_MAX) {
 		RT_TRACE(COMP_REGD, DBG_DMESG,
-			 (KERN_DEBUG "rtl: EEPROM indicates invalid contry code"
+			 (KERN_DEBUG "rtl: EEPROM indicates invalid country code"
 			  "world wide 13 should be used\n"));
 
 		rtlpriv->regd.country_code = COUNTRY_CODE_WORLD_WIDE_13;
diff --git a/drivers/staging/rtl8821ae/rtl8821ae/dm.c b/drivers/staging/rtl8821ae/rtl8821ae/dm.c
index 8634206..e0efcd2 100644
--- a/drivers/staging/rtl8821ae/rtl8821ae/dm.c
+++ b/drivers/staging/rtl8821ae/rtl8821ae/dm.c
@@ -731,7 +731,7 @@
 		rtl_dm_dig->min_undecorated_pwdb_for_dm =
 		    rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb;
 		RT_TRACE(COMP_BB_POWERSAVING, DBG_LOUD,
-			 ("AP Ext Port or disconnet PWDB = 0x%x \n",
+			 ("AP Ext Port or disconnect PWDB = 0x%x \n",
 			  rtl_dm_dig->min_undecorated_pwdb_for_dm));
 	}
 	RT_TRACE(COMP_DIG, DBG_LOUD, ("MinUndecoratedPWDBForDM =%d\n",
@@ -925,7 +925,7 @@
 
 	if (rtlpriv->falsealm_cnt.cnt_all > 10000) {
 		RT_TRACE(COMP_DIG, DBG_LOUD,
-			("rtl8821ae_dm_dig(): Abnornally false alarm case. \n"));
+			("rtl8821ae_dm_dig(): Abnormally false alarm case. \n"));
 
 		if (dm_digtable.large_fa_hit != 3)
 		        dm_digtable.large_fa_hit++;
@@ -1087,7 +1087,7 @@
 	else
 		falsealm_cnt->cnt_all = falsealm_cnt->cnt_ofdm_fail;
 
-	/*reset OFDM FA coutner*/
+	/*reset OFDM FA counter*/
 	rtl_set_bbreg(hw, ODM_REG_OFDM_FA_RST_11AC, BIT(17), 1);
 	rtl_set_bbreg(hw, ODM_REG_OFDM_FA_RST_11AC, BIT(17), 0);
 	/* reset CCK FA counter*/
@@ -1316,7 +1316,7 @@
 /*-----------------------------------------------------------------------------
  * Function:	odm_TxPwrTrackSetPwr88E()
  *
- * Overview:	88E change all channel tx power accordign to flag.
+ * Overview:	88E change all channel tx power according to flag.
  *				OFDM & CCK are all different.
  *
  * Input:		NONE
@@ -1537,7 +1537,7 @@
 					rtldm->modify_txagc_flag_path_b = false;
 
 					RT_TRACE(COMP_POWER_TRACKING, DBG_LOUD,
-						("******Path_B pDM_Odm->Modify_TxAGC_Flag = FALSE \n"));
+						("******Path_B dm_Odm->Modify_TxAGC_Flag = FALSE \n"));
 				}
 			}
 		}
@@ -1654,7 +1654,7 @@
 
 	if (delta > 0 && rtldm->txpower_track_control)
 	{
-		/*"delta" here is used to record the absolute value of differrence.*/
+		/*"delta" here is used to record the absolute value of difference.*/
 	    	delta = thermal_value > rtlefuse->eeprom_thermalmeter ? \
 		    	(thermal_value - rtlefuse->eeprom_thermalmeter) : \
 		    	(rtlefuse->eeprom_thermalmeter - thermal_value);
@@ -1976,7 +1976,7 @@
 /*-----------------------------------------------------------------------------
  * Function:	odm_TxPwrTrackSetPwr88E()
  *
- * Overview:	88E change all channel tx power accordign to flag.
+ * Overview:	88E change all channel tx power according to flag.
  *				OFDM & CCK are all different.
  *
  * Input:		NONE
@@ -2159,7 +2159,7 @@
 	u8 *delta_swing_table_idx_tup_b;
 	u8 *delta_swing_table_idx_tdown_b;
 
-	/*2. Initilization ( 7 steps in total )*/
+	/*2. Initialization ( 7 steps in total )*/
 	rtl8821ae_get_delta_swing_table(hw, (u8**)&delta_swing_table_idx_tup_a,
 									(u8**)&delta_swing_table_idx_tdown_a,
 									  (u8**)&delta_swing_table_idx_tup_b,
@@ -2244,7 +2244,7 @@
 
 	if (delta > 0 && rtldm->txpower_track_control)
 	{
-		/*"delta" here is used to record the absolute value of differrence.*/
+		/*"delta" here is used to record the absolute value of difference.*/
 	    	delta = thermal_value > rtlefuse->eeprom_thermalmeter ? \
 		    	(thermal_value - rtlefuse->eeprom_thermalmeter) : \
 		    	(rtlefuse->eeprom_thermalmeter - thermal_value);
@@ -2613,11 +2613,11 @@
 	RT_TRACE(COMP_TURBO, DBG_LOUD,
 		("rtl8821ae_dm_check_edca_turbo=====>"));
 	RT_TRACE(COMP_TURBO, DBG_LOUD,
-		("Orginial BE PARAM: 0x%x\n",
+		("Original BE PARAM: 0x%x\n",
 		rtl_read_dword(rtlpriv, DM_REG_EDCA_BE_11N)));
 
 	/*===============================
-	list paramter for different platform
+	list parameter for different platform
 	===============================*/
 	b_last_is_cur_rdl_state = rtlpriv->dm.bis_cur_rdlstate;
 	pb_is_cur_rdl_state = &( rtlpriv->dm.bis_cur_rdlstate);
@@ -2963,7 +2963,7 @@
 			"Crystal cap = 0x%x, Crystal cap offset = %d\n",
 			rtldm->crystal_cap, adjust_xtal));
 
-		/*3.Adjudt Crystal Cap.*/
+		/*3.Adjust Crystal Cap.*/
 		if (adjust_xtal != 0){
 			rtldm->is_freeze = 0;
 			rtldm->crystal_cap += adjust_xtal;
diff --git a/drivers/staging/rtl8821ae/rtl8821ae/fw.c b/drivers/staging/rtl8821ae/rtl8821ae/fw.c
index 4083cab..46eb412 100644
--- a/drivers/staging/rtl8821ae/rtl8821ae/fw.c
+++ b/drivers/staging/rtl8821ae/rtl8821ae/fw.c
@@ -164,7 +164,7 @@
 
 	if (counter >= FW_8821AE_POLLING_TIMEOUT_COUNT) {
 		RT_TRACE(COMP_ERR, DBG_LOUD,
-			 ("chksum report faill ! REG_MCUFWDL:0x%08x .\n",
+			 ("chksum report fail ! REG_MCUFWDL:0x%08x .\n",
 			  value32));
 		goto exit;
 	}
@@ -368,7 +368,7 @@
 				wait_h2c_limmit--;
 				if (wait_h2c_limmit == 0) {
 					RT_TRACE(COMP_CMD, DBG_LOUD,
-						 ("Wating too long for FW read "
+						 ("Waiting too long for FW read "
 						  "clear HMEBox(%d)!\n", boxnum));
 					break;
 				}
@@ -378,7 +378,7 @@
 				isfw_read = _rtl8821ae_check_fw_read_last_h2c(hw, boxnum);
 				u1b_tmp = rtl_read_byte(rtlpriv, 0x130);
 				RT_TRACE(COMP_CMD, DBG_LOUD,
-					 ("Wating for FW read clear HMEBox(%d)!!! "
+					 ("Waiting for FW read clear HMEBox(%d)!!! "
 					  "0x130 = %2x\n", boxnum, u1b_tmp));
 			}
 		}
@@ -1179,7 +1179,7 @@
 			 ("Set RSVD page location to Fw FAIL!!!!!!.\n"));
 }
 
-/*Shoud check FW support p2p or not.*/
+/*Should check FW support p2p or not.*/
 void rtl8821ae_set_p2p_ctw_period_cmd(struct ieee80211_hw *hw, u8 ctwindow)
 {
 	u8 u1_ctwindow_period[1] ={ ctwindow};
diff --git a/drivers/staging/rtl8821ae/rtl8821ae/hal_bt_coexist.h b/drivers/staging/rtl8821ae/rtl8821ae/hal_bt_coexist.h
index 799cc6f..b365f82 100644
--- a/drivers/staging/rtl8821ae/rtl8821ae/hal_bt_coexist.h
+++ b/drivers/staging/rtl8821ae/rtl8821ae/hal_bt_coexist.h
@@ -142,7 +142,7 @@
 long rtl8821ae_dm_bt_get_rx_ss(struct ieee80211_hw *hw);
 void rtl8821ae_dm_bt_balance(struct ieee80211_hw *hw,
 			bool b_balance_on, u8 ms0, u8 ms1);
-void rtl8821ae_dm_bt_agc_table(struct ieee80211_hw *hw, u8 tyep);
+void rtl8821ae_dm_bt_agc_table(struct ieee80211_hw *hw, u8 type);
 void rtl8821ae_dm_bt_bb_back_off_level(struct ieee80211_hw *hw, u8 type);
 u8 rtl8821ae_dm_bt_check_coex_rssi_state(struct ieee80211_hw *hw,
 						u8	level_num, u8	rssi_thresh, u8 rssi_thresh1);
diff --git a/drivers/staging/rtl8821ae/rtl8821ae/hal_btc.c b/drivers/staging/rtl8821ae/rtl8821ae/hal_btc.c
index 79386ee..6898868 100644
--- a/drivers/staging/rtl8821ae/rtl8821ae/hal_btc.c
+++ b/drivers/staging/rtl8821ae/rtl8821ae/hal_btc.c
@@ -157,7 +157,7 @@
 		&&(rtlpcipriv->btcoexist.previous_state_h
 		== rtlpcipriv->btcoexist.current_state_h)) {
 		RT_TRACE(COMP_BT_COEXIST, DBG_DMESG,
-				("[DM][BT], Coexist state do not chang!!\n"));
+				("[DM][BT], Coexist state do not change!!\n"));
 		return true;
 	} else {
 		RT_TRACE(COMP_BT_COEXIST, DBG_DMESG,
@@ -902,7 +902,7 @@
 
 	/*
 	 * Note:
-	 * We should add delay for making sure sw DacSwing can be set sucessfully.
+	 * We should add delay for making sure sw DacSwing can be set successfully.
 	 * because of that rtl8821ae_dm_bt_set_fw_2_ant_hid() and rtl8821ae_dm_bt_set_fw_tdma_ctrl()
 	 * will overwrite the reg 0x880.
 	*/
diff --git a/drivers/staging/rtl8821ae/rtl8821ae/hw.c b/drivers/staging/rtl8821ae/rtl8821ae/hw.c
index d3e9b93..1b8583b 100644
--- a/drivers/staging/rtl8821ae/rtl8821ae/hw.c
+++ b/drivers/staging/rtl8821ae/rtl8821ae/hw.c
@@ -1017,7 +1017,7 @@
 	/* ARFB table 12 for 11ac 24G 1SS */
 	rtl_write_dword(rtlpriv, REG_ARFR3, 0x00000015);
 	rtl_write_dword(rtlpriv, REG_ARFR3 + 4, 0xffcff000);
-	/* 0x420[7] = 0 , enable retry AMPDU in new AMPD not singal MPDU. */
+	/* 0x420[7] = 0 , enable retry AMPDU in new AMPD not signal MPDU. */
 	rtl_write_word(rtlpriv, REG_FWHW_TXQ_CTRL, 0x1F00);
 	rtl_write_byte(rtlpriv, REG_AMPDU_MAX_TIME, 0x70);
 
@@ -1407,7 +1407,7 @@
 	rtl8821ae_phy_mac_config(hw);
 	/* because last function modify RCR, so we update
 	 * rcr var here, or TP will unstable for receive_config
-	 * is wrong, RX RCR_ACRC32 will cause TP unstabel & Rx
+	 * is wrong, RX RCR_ACRC32 will cause TP unstable & Rx
 	 * RCR_APP_ICV will cause mac80211 unassoc for cisco 1252
 	rtlpci->receive_config = rtl_read_dword(rtlpriv, REG_RCR);
 	rtlpci->receive_config &= ~(RCR_ACRC32 | RCR_AICV);
@@ -1563,7 +1563,7 @@
 			break;
 		default:
 			RT_TRACE(COMP_INIT, DBG_LOUD,
-				("Chip Version ID: Unknow (0x%X).\n", version));
+				("Chip Version ID: Unknown (0x%X).\n", version));
 			break;
 	}
 
@@ -2372,7 +2372,7 @@
 	if (rtlefuse->eeprom_channelplan == 0xff)
 		rtlefuse->eeprom_channelplan = 0x7F;
 
-	/* set channel paln to world wide 13 */
+	/* set channel plan to world wide 13 */
 	//rtlefuse->channel_plan = (u8) rtlefuse->eeprom_channelplan;
 
 	/*parse xtal*/
@@ -2535,7 +2535,7 @@
 	if (rtlefuse->eeprom_channelplan == 0xff)
 		rtlefuse->eeprom_channelplan = 0x7F;
 
-	/* set channel paln to world wide 13 */
+	/* set channel plan to world wide 13 */
 	//rtlefuse->channel_plan = (u8) rtlefuse->eeprom_channelplan;
 
 	/*parse xtal*/
diff --git a/drivers/staging/rtl8821ae/rtl8821ae/phy.c b/drivers/staging/rtl8821ae/rtl8821ae/phy.c
index d02fca3..c661290 100644
--- a/drivers/staging/rtl8821ae/rtl8821ae/phy.c
+++ b/drivers/staging/rtl8821ae/rtl8821ae/phy.c
@@ -86,7 +86,7 @@
 			/* 0x8AC[11:10] = 2'b10*/
 
 
-		/* <20120914, Kordan> A workarould to resolve
+		/* <20120914, Kordan> A workaround to resolve
 		2480Mhz spur by setting ADC clock as 160M. (Asked by Binson)*/
 		if (band_width == HT_CHANNEL_WIDTH_20 &&
 			(channel == 13 || channel == 14)) {
@@ -107,7 +107,7 @@
 	}
 	else if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE)
 	{
-		/* <20120914, Kordan> A workarould to resolve
+		/* <20120914, Kordan> A workaround to resolve
 		2480Mhz spur by setting ADC clock as 160M. (Asked by Binson)*/
 		if (band_width == HT_CHANNEL_WIDTH_20 &&
 			(channel == 13 || channel == 14))
diff --git a/drivers/staging/rtl8821ae/rtl8821ae/phy.h b/drivers/staging/rtl8821ae/rtl8821ae/phy.h
index a932d8c..a80bf73 100644
--- a/drivers/staging/rtl8821ae/rtl8821ae/phy.h
+++ b/drivers/staging/rtl8821ae/rtl8821ae/phy.h
@@ -30,7 +30,7 @@
 #ifndef __RTL8821AE_PHY_H__
 #define __RTL8821AE_PHY_H__
 
-/*It must always set to 4, otherwise read efuse table secquence will be wrong.*/
+/*It must always set to 4, otherwise read efuse table sequence will be wrong.*/
 #define MAX_TX_COUNT	4
 #define	TX_1S			0
 #define	TX_2S			1
diff --git a/drivers/staging/rtl8821ae/rtl8821ae/pwrseq.h b/drivers/staging/rtl8821ae/rtl8821ae/pwrseq.h
index 8b39c04..480a6bb 100644
--- a/drivers/staging/rtl8821ae/rtl8821ae/pwrseq.h
+++ b/drivers/staging/rtl8821ae/rtl8821ae/pwrseq.h
@@ -81,7 +81,7 @@
 	{0x0047, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, 0xFF, 0},/* 0x47[7:0] = 00 gpio mode */	\
 	{0x0007, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, 0xFF, 0},/* suspend option all off */	\
 	{0x0014, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, 0x80, BIT7},/*0x14[7] = 1 turn on ZCD */	\
-	{0x0015, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, 0x01, BIT0},/* 0x15[0] =1 trun on ZCD */	\
+	{0x0015, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, 0x01, BIT0},/* 0x15[0] =1 turn on ZCD */	\
 	{0x0023, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, 0x10, BIT4},/*0x23[4] = 1 hpon LDO sleep mode */	\
 	{0x0008, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, 0x02, 0},/*0x8[1] = 0 ANA clk =500k */	\
 	{0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, BIT3, BIT3}, /*0x04[11] = 2b'11 enable WL suspend for PCIe*/
@@ -91,7 +91,7 @@
 	/* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, // comments here*/								\
 	{0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, BIT3, 0}, /*0x04[11] = 2b'01enable WL suspend*/   \
 	{0x0023, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, 0x10, 0},/*0x23[4] = 0 hpon LDO sleep mode leave */	\
-	{0x0015, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, 0x01, 0},/* 0x15[0] =0 trun off ZCD */	\
+	{0x0015, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, 0x01, 0},/* 0x15[0] =0 turn off ZCD */	\
 	{0x0014, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, 0x80, 0},/*0x14[7] = 0 turn off ZCD */	\
 	{0x0046, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, 0xFF, 0x00},/* gpio0~7 input mode */	\
 	{0x0043, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, 0xFF, 0x00},/* gpio11 input mode, gpio10~8 input mode */
@@ -110,7 +110,7 @@
 	{0x0046, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, 0xFF, 0xff},/* gpio0~7 output mode */	\
 	{0x0047, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, 0xFF, 0},/* 0x47[7:0] = 00 gpio mode */	\
 	{0x0014, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, 0x80, BIT7},/*0x14[7] = 1 turn on ZCD */	\
-	{0x0015, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, 0x01, BIT0},/* 0x15[0] =1 trun on ZCD */	\
+	{0x0015, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, 0x01, BIT0},/* 0x15[0] =1 turn on ZCD */	\
 	{0x0012, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, 0x01, 0},/*0x12[0] = 0 force PFM mode */	\
 	{0x0023, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, 0x10, BIT4},/*0x23[4] = 1 hpon LDO sleep mode */	\
 	{0x0008, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, 0x02, 0},/*0x8[1] = 0 ANA clk =500k */	\
@@ -124,7 +124,7 @@
 	/* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, // comments here*/                       \
 	{0x0012, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, BIT0, BIT0},/*0x12[0] = 1 force PWM mode */	\
 	{0x0014, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, 0x80, 0},/*0x14[7] = 0 turn off ZCD */	\
-	{0x0015, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, 0x01, 0},/* 0x15[0] =0 trun off ZCD */	\
+	{0x0015, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, 0x01, 0},/* 0x15[0] =0 turn off ZCD */	\
 	{0x0023, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, 0x10, 0},/*0x23[4] = 0 hpon LDO leave sleep mode */	\
 	{0x0046, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, 0xFF, 0x00},/* gpio0~7 input mode */	\
 	{0x0043, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, 0xFF, 0x00},/* gpio11 input mode, gpio10~8 input mode */ \
@@ -204,7 +204,7 @@
 	4: LPS--Low Power State
 	5: SUS--Suspend
 
-	The transision from different states are defined below
+	The transition from different states are defined below
 	TRANS_CARDEMU_TO_ACT
 	TRANS_ACT_TO_CARDEMU
 	TRANS_CARDEMU_TO_SUS
diff --git a/drivers/staging/rtl8821ae/rtl8821ae/pwrseqcmd.c b/drivers/staging/rtl8821ae/rtl8821ae/pwrseqcmd.c
index 710bc01..ff18871 100644
--- a/drivers/staging/rtl8821ae/rtl8821ae/pwrseqcmd.c
+++ b/drivers/staging/rtl8821ae/rtl8821ae/pwrseqcmd.c
@@ -82,7 +82,7 @@
 					value = value | (GET_PWR_CFG_VALUE(pwr_cfg_cmd)
 							& GET_PWR_CFG_MASK(pwr_cfg_cmd));
 
-					/*Write the value back to sytem register*/
+					/*Write the value back to system register*/
 					rtl_write_byte(rtlpriv, offset, value);
 				}
 				break;
diff --git a/drivers/staging/rtl8821ae/rtl8821ae/reg.h b/drivers/staging/rtl8821ae/rtl8821ae/reg.h
index 09c5f00..beffb42 100644
--- a/drivers/staging/rtl8821ae/rtl8821ae/reg.h
+++ b/drivers/staging/rtl8821ae/rtl8821ae/reg.h
@@ -596,13 +596,13 @@
 #define	IMR_BCNDMAINT3			BIT(23)		/* Beacon DMA Interrupt 3		*/
 #define	IMR_BCNDMAINT2			BIT(22)		/* Beacon DMA Interrupt 2		*/
 #define	IMR_BCNDMAINT1			BIT(21)		/* Beacon DMA Interrupt 1		*/
-#define	IMR_BCNDOK7				BIT(20)		/* Beacon Queue DMA OK Interrup 7 */
-#define	IMR_BCNDOK6				BIT(19)		/* Beacon Queue DMA OK Interrup 6 */
-#define	IMR_BCNDOK5				BIT(18)		/* Beacon Queue DMA OK Interrup 5 */
-#define	IMR_BCNDOK4				BIT(17)		/* Beacon Queue DMA OK Interrup 4 */
-#define	IMR_BCNDOK3				BIT(16)		/* Beacon Queue DMA OK Interrup 3 */
-#define	IMR_BCNDOK2				BIT(15)		/* Beacon Queue DMA OK Interrup 2 */
-#define	IMR_BCNDOK1				BIT(14)		/* Beacon Queue DMA OK Interrup 1 */
+#define	IMR_BCNDOK7				BIT(20)		/* Beacon Queue DMA OK Interrupt 7 */
+#define	IMR_BCNDOK6				BIT(19)		/* Beacon Queue DMA OK Interrupt 6 */
+#define	IMR_BCNDOK5				BIT(18)		/* Beacon Queue DMA OK Interrupt 5 */
+#define	IMR_BCNDOK4				BIT(17)		/* Beacon Queue DMA OK Interrupt 4 */
+#define	IMR_BCNDOK3				BIT(16)		/* Beacon Queue DMA OK Interrupt 3 */
+#define	IMR_BCNDOK2				BIT(15)		/* Beacon Queue DMA OK Interrupt 2 */
+#define	IMR_BCNDOK1				BIT(14)		/* Beacon Queue DMA OK Interrupt 1 */
 #define	IMR_ATIMEND_E		BIT(13)		/* ATIM Window End Extension for Win7 */
 #define	IMR_TXERR				BIT(11)		/* Tx Error Flag Interrupt Status, write 1 clear. */
 #define	IMR_RXERR				BIT(10)		/* Rx Error Flag INT Status, Write 1 clear */
@@ -613,7 +613,7 @@
 #define	HWSET_MAX_SIZE				512
 #define   EFUSE_MAX_SECTION			64
 #define   EFUSE_REAL_CONTENT_LEN			256
-#define 	EFUSE_OOB_PROTECT_BYTES    	18 	/* PG data exclude header, dummy 7 bytes frome CP test and reserved 1byte.*/
+#define 	EFUSE_OOB_PROTECT_BYTES    	18 	/* PG data exclude header, dummy 7 bytes from CP test and reserved 1byte.*/
 
 
 #define	EEPROM_DEFAULT_TSSI					0x0
@@ -1511,7 +1511,7 @@
 #define	ROFDM0_TXCOEFF5				0xcb4
 #define	ROFDM0_TXCOEFF6				0xcb8
 
-/*Path_A RFE cotrol */
+/*Path_A RFE control */
 #define	RA_RFE_CTRL_8812				0xcb8
 /*Path_B RFE control*/
 #define	RB_RFE_CTRL_8812				0xeb8
@@ -2336,19 +2336,19 @@
 #define		WOL_REASON_DEAUTH			BIT(3)
 #define		WOL_REASON_FW_DISCONNECT	BIT(4)
 
-#define		RA_RFE_PINMUX	0xcb0  /* Path_A RFE cotrol pinmux*/
+#define		RA_RFE_PINMUX	0xcb0  /* Path_A RFE control pinmux*/
 #define		RB_RFE_PINMUX	0xeb0 /* Path_B RFE control pinmux*/
 
 #define		RA_RFE_INV 0xcb4
 #define		RB_RFE_INV 0xeb4
 
 /* RXIQC */
-#define		RA_RXIQC_AB    	0xc10  /*RxIQ imblance matrix coeff. A & B*/
-#define		RA_RXIQC_CD    	0xc14  /*RxIQ imblance matrix coeff. C & D*/
+#define		RA_RXIQC_AB    	0xc10  /*RxIQ imbalance matrix coeff. A & B*/
+#define		RA_RXIQC_CD    	0xc14  /*RxIQ imbalance matrix coeff. C & D*/
 #define	 	RA_TXSCALE 		0xc1c  /* Pah_A TX scaling factor*/
 #define		RB_TXSCALE 		0xe1c  /* Path_B TX scaling factor*/
-#define		RB_RXIQC_AB    	0xe10  /*RxIQ imblance matrix coeff. A & B*/
-#define		RB_RXIQC_CD    	0xe14  /*RxIQ imblance matrix coeff. C & D*/
+#define		RB_RXIQC_AB    	0xe10  /*RxIQ imbalance matrix coeff. A & B*/
+#define		RB_RXIQC_CD    	0xe14  /*RxIQ imbalance matrix coeff. C & D*/
 #define		RXIQC_AC		0x02ff  /*bit mask for IQC matrix element A & C*/
 #define		RXIQC_BD		0x02ff0000 /*bit mask for IQC matrix element A & C*/
 
diff --git a/drivers/staging/rtl8821ae/rtl8821ae/sw.c b/drivers/staging/rtl8821ae/rtl8821ae/sw.c
index 85a3474..a8d1755 100644
--- a/drivers/staging/rtl8821ae/rtl8821ae/sw.c
+++ b/drivers/staging/rtl8821ae/rtl8821ae/sw.c
@@ -57,9 +57,9 @@
 	 * 0 - Disable ASPM,
 	 * 1 - Enable ASPM without Clock Req,
 	 * 2 - Enable ASPM with Clock Req,
-	 * 3 - Alwyas Enable ASPM with Clock Req,
+	 * 3 - Always Enable ASPM with Clock Req,
 	 * 4 - Always Enable ASPM without Clock Req.
-	 * set defult to RTL8192CE:3 RTL8192E:2
+	 * set default to RTL8192CE:3 RTL8192E:2
 	 * */
 	rtlpci->const_pci_aspm = 3;
 
diff --git a/drivers/staging/rtl8821ae/rtl8821ae/trx.c b/drivers/staging/rtl8821ae/rtl8821ae/trx.c
index f82ed51..5f32464 100644
--- a/drivers/staging/rtl8821ae/rtl8821ae/trx.c
+++ b/drivers/staging/rtl8821ae/rtl8821ae/trx.c
@@ -244,7 +244,7 @@
 		cck_agc_rpt = cck_buf->cck_agc_rpt;
 
 		/* (1)Hardware does not provide RSSI for CCK */
-		/* (2)PWDB, Average PWDB cacluated by
+		/* (2)PWDB, Average PWDB calculated by
 		 * hardware (for rate adaptive) */
 		if (ppsc->rfpwr_state == ERFON)
 			cck_highpwr = (u8) rtl_get_bbreg(hw, RFPGA0_XA_HSSIPARAMETER2,
@@ -363,7 +363,7 @@
 				pstatus->rx_mimo_signalstrength[i] = (u8) rssi;
 		}
 
-		/* (2)PWDB, Average PWDB cacluated by
+		/* (2)PWDB, Average PWDB calculated by
 		 * hardware (for rate adaptive) */
 		rx_pwr_all = ((p_drvinfo->pwdb_all >> 1) & 0x7f) - 110;
 
@@ -603,7 +603,7 @@
 
 	/* hw will set status->decrypted true, if it finds the
 	 * frame is open data frame or mgmt frame. */
-	/* So hw will not decryption robust managment frame
+	/* So hw will not decryption robust management frame
 	 * for IEEE80211w but still set status->decrypted
 	 * true, so here we should set it back to undecrypted
 	 * for IEEE80211w frame, and mac80211 sw will help
diff --git a/drivers/staging/rtl8821ae/wifi.h b/drivers/staging/rtl8821ae/wifi.h
index 3b5b2e7..17a9d9f 100644
--- a/drivers/staging/rtl8821ae/wifi.h
+++ b/drivers/staging/rtl8821ae/wifi.h
@@ -76,7 +76,7 @@
 #define RTL_SLOT_TIME_20		20
 
 /*related with tcp/ip. */
-/*if_ehther.h*/
+/*if_ether.h*/
 #define ETH_P_PAE			0x888E	/*Port Access Entity
 						 *(IEEE 802.1X) */
 #define ETH_P_IP			0x0800	/*Internet Protocol packet */
@@ -112,7 +112,7 @@
 #define MAX_NUM_RATES			264
 
 /*for 88E use*/
-/*It must always set to 4, otherwise read efuse table secquence will be wrong.*/
+/*It must always set to 4, otherwise read efuse table sequence will be wrong.*/
 #define MAX_TX_COUNT			4
 #define	MAX_RF_PATH			4
 #define	MAX_CHNL_GROUP_24G		6
@@ -435,7 +435,7 @@
 	HT_CHANNEL_WIDTH_80 = 2,
 };
 
-/* Ref: 802.11i sepc D10.0 7.3.2.25.1
+/* Ref: 802.11i spec D10.0 7.3.2.25.1
 Cipher Suites Encryption Algorithms */
 enum rt_enc_alg {
 	NO_ENCRYPTION = 0,
@@ -499,14 +499,14 @@
 	RTL_IMR_BCNDMAINT3,	/*Beacon DMA Interrupt 3 */
 	RTL_IMR_BCNDMAINT2,	/*Beacon DMA Interrupt 2 */
 	RTL_IMR_BCNDMAINT1,	/*Beacon DMA Interrupt 1 */
-	RTL_IMR_BCNDOK8,	/*Beacon Queue DMA OK Interrup 8 */
-	RTL_IMR_BCNDOK7,	/*Beacon Queue DMA OK Interrup 7 */
-	RTL_IMR_BCNDOK6,	/*Beacon Queue DMA OK Interrup 6 */
-	RTL_IMR_BCNDOK5,	/*Beacon Queue DMA OK Interrup 5 */
-	RTL_IMR_BCNDOK4,	/*Beacon Queue DMA OK Interrup 4 */
-	RTL_IMR_BCNDOK3,	/*Beacon Queue DMA OK Interrup 3 */
-	RTL_IMR_BCNDOK2,	/*Beacon Queue DMA OK Interrup 2 */
-	RTL_IMR_BCNDOK1,	/*Beacon Queue DMA OK Interrup 1 */
+	RTL_IMR_BCNDOK8,	/*Beacon Queue DMA OK Interrupt 8 */
+	RTL_IMR_BCNDOK7,	/*Beacon Queue DMA OK Interrupt 7 */
+	RTL_IMR_BCNDOK6,	/*Beacon Queue DMA OK Interrupt 6 */
+	RTL_IMR_BCNDOK5,	/*Beacon Queue DMA OK Interrupt 5 */
+	RTL_IMR_BCNDOK4,	/*Beacon Queue DMA OK Interrupt 4 */
+	RTL_IMR_BCNDOK3,	/*Beacon Queue DMA OK Interrupt 3 */
+	RTL_IMR_BCNDOK2,	/*Beacon Queue DMA OK Interrupt 2 */
+	RTL_IMR_BCNDOK1,	/*Beacon Queue DMA OK Interrupt 1 */
 	RTL_IMR_TIMEOUT2,	/*Timeout interrupt 2 */
 	RTL_IMR_TIMEOUT1,	/*Timeout interrupt 1 */
 	RTL_IMR_TXFOVW,		/*Transmit FIFO Overflow */
@@ -515,10 +515,10 @@
 	RTL_IMR_RXFOVW,		/*Receive FIFO Overflow */
 	RTL_IMR_RDU,		/*Receive Descriptor Unavailable */
 	RTL_IMR_ATIMEND,	/*For 92C,ATIM Window End Interrupt */
-	RTL_IMR_BDOK,		/*Beacon Queue DMA OK Interrup */
+	RTL_IMR_BDOK,		/*Beacon Queue DMA OK Interrupt */
 	RTL_IMR_HIGHDOK,	/*High Queue DMA OK Interrupt */
 	RTL_IMR_COMDOK,		/*Command Queue DMA OK Interrupt*/
-	RTL_IMR_TBDOK,		/*Transmit Beacon OK interrup */
+	RTL_IMR_TBDOK,		/*Transmit Beacon OK interrupt */
 	RTL_IMR_MGNTDOK,	/*Management Queue DMA OK Interrupt */
 	RTL_IMR_TBDER,		/*For 92C,Transmit Beacon Error Interrupt */
 	RTL_IMR_BKDOK,		/*AC_BK DMA OK Interrupt */
@@ -1256,7 +1256,7 @@
 	bool use_defaultkey;
 	/*Encryption Algorithm for Unicast Packet */
 	enum rt_enc_alg pairwise_enc_algorithm;
-	/*Encryption Algorithm for Brocast/Multicast */
+	/*Encryption Algorithm for Broadcast/Multicast */
 	enum rt_enc_alg group_enc_algorithm;
 	/*Cam Entry Bitmap */
 	u32 hwsec_cam_bitmap;
@@ -1691,7 +1691,7 @@
 };
 
 struct rt_link_detect {
-	/* count for raoming */
+	/* count for roaming */
 	u32 bcn_rx_inperiod;
 	u32 roam_times;
 
@@ -2089,7 +2089,7 @@
 
 	/*
 	 *hal_cfg : for diff cards
-	 *intf_ops : for diff interrface usb/pcie
+	 *intf_ops : for diff interface usb/pcie
 	 */
 	struct rtl_hal_cfg *cfg;
 	struct rtl_intf_ops *intf_ops;
@@ -2107,7 +2107,7 @@
 	/*for bt coexist use*/
 	struct rtl_bt_coexist btcoexist;
 
-	/* seperate 92ee from other ICs,
+	/* separate 92ee from other ICs,
 	  * 92ee use new trx flow. */
 	bool use_new_trx_flow;
 	/*This must be the last item so
@@ -2385,7 +2385,7 @@
 #define	RT_RF_PS_LEVEL_ALWAYS_ASPM	BIT(6)
 /* no matter RFOFF or SLEEP we set PS_ASPM_LEVL*/
 #define	RT_PS_LEVEL_ASPM		BIT(7)
-/*When LPS is on, disable 2R if no packet is received or transmittd.*/
+/*When LPS is on, disable 2R if no packet is received or transmitted.*/
 #define	RT_RF_LPS_DISALBE_2R		BIT(30)
 #define	RT_RF_LPS_LEVEL_ASPM		BIT(31)	/*LPS with ASPM */
 #define	RT_IN_PS_LEVEL(ppsc, _ps_flg)		\
diff --git a/drivers/staging/rts5208/ms.c b/drivers/staging/rts5208/ms.c
index edf979f..d22916a 100644
--- a/drivers/staging/rts5208/ms.c
+++ b/drivers/staging/rts5208/ms.c
@@ -259,7 +259,7 @@
 		MS_TRANSFER_END, MS_TRANSFER_END);
 
 	for (i = 0; i < data_len - 1; i++)
-	       rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + i, 0, 0);
+		rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + i, 0, 0);
 
 	if (data_len % 2)
 		rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + data_len, 0, 0);
diff --git a/drivers/staging/sb105x/Kconfig b/drivers/staging/sb105x/Kconfig
deleted file mode 100644
index 245e784..0000000
--- a/drivers/staging/sb105x/Kconfig
+++ /dev/null
@@ -1,9 +0,0 @@
-config SB105X
-	tristate "SystemBase PCI Multiport UART"
-	select SERIAL_CORE
-	depends on PCI && X86 && TTY && BROKEN
-	help
-	  A driver for the SystemBase Multi-2/PCI serial card
-
-	  To compile this driver a module, choose M here: the module
-	  will be called "sb105x".
diff --git a/drivers/staging/sb105x/Makefile b/drivers/staging/sb105x/Makefile
deleted file mode 100644
index b1bf377..0000000
--- a/drivers/staging/sb105x/Makefile
+++ /dev/null
@@ -1,3 +0,0 @@
-obj-$(CONFIG_SB105X) +=	sb105x.o
-
-sb105x-y :=  sb_pci_mp.o
diff --git a/drivers/staging/sb105x/sb_mp_register.h b/drivers/staging/sb105x/sb_mp_register.h
deleted file mode 100644
index 276c1bb..0000000
--- a/drivers/staging/sb105x/sb_mp_register.h
+++ /dev/null
@@ -1,295 +0,0 @@
-
-/*
- * SB105X_UART.h
- *
- * Copyright (C) 2008 systembase
- *
- * UART registers.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#ifndef UART_SB105X_H
-#define UART_SB105X_H
-
-/*
- * option register
- */
-
-/* Device Information Register */
-#define MP_OPTR_DIR0		0x04 	/* port0 ~ port8 */
-#define MP_OPTR_DIR1		0x05 	/* port8 ~ port15 */
-#define MP_OPTR_DIR2		0x06 	/* port16 ~ port23 */
-#define MP_OPTR_DIR3		0x07 	/* port24 ~ port31 */
-
-#define DIR_UART_16C550 	0
-#define DIR_UART_16C1050	1
-#define DIR_UART_16C1050A	2
-
-#define	DIR_CLK_1843200		0x0		/* input clock 1843200 Hz */
-#define	DIR_CLK_3686400		0x1		/* input clock 3686400 Hz */
-#define	DIR_CLK_7372800		0x2		/* input clock 7372800 Hz */
-#define	DIR_CLK_14745600	0x3		/* input clock 14745600 Hz */
-#define	DIR_CLK_29491200	0x4		/* input clock 29491200 Hz */
-#define	DIR_CLK_58985400	0x5		/* input clock 58985400 Hz */
-
-/* Interface Information Register */
-#define MP_OPTR_IIR0		0x08 	/* port0 ~ port8 */
-#define MP_OPTR_IIR1		0x09 	/* port8 ~ port15 */
-#define MP_OPTR_IIR2		0x0A 	/* port16 ~ port23 */
-#define MP_OPTR_IIR3		0x0B 	/* port24 ~ port31 */
-
-#define IIR_RS232		0x00		/* RS232 type */
-#define IIR_RS422		0x10		/* RS422 type */
-#define IIR_RS485		0x20		/* RS485 type */
-#define IIR_TYPE_MASK		0x30
-
-/* Interrupt Mask Register */
-#define MP_OPTR_IMR0		0x0C 	/* port0 ~ port8 */
-#define MP_OPTR_IMR1		0x0D 	/* port8 ~ port15 */
-#define MP_OPTR_IMR2		0x0E 	/* port16 ~ port23 */
-#define MP_OPTR_IMR3		0x0F 	/* port24 ~ port31 */
-
-/* Interrupt Poll Register */
-#define MP_OPTR_IPR0		0x10 	/* port0 ~ port8 */
-#define MP_OPTR_IPR1		0x11 	/* port8 ~ port15 */
-#define MP_OPTR_IPR2		0x12 	/* port16 ~ port23 */
-#define MP_OPTR_IPR3		0x13 	/* port24 ~ port31 */
-
-/* General Purpose Output Control Register */
-#define MP_OPTR_GPOCR		0x20
-
-/* General Purpose Output Data Register */
-#define MP_OPTR_GPODR		0x21
-
-/* Parallel Additional Function Register */
-#define MP_OPTR_PAFR		0x23
-
-/*
- * systembase 16c105x UART register
- */
-
-#define PAGE_0 0
-#define PAGE_1 1
-#define PAGE_2 2
-#define PAGE_3 3
-#define PAGE_4 4
-
-/*
- *  ******************************************************************
- *  * DLAB=0                  ===============       Page 0 Registers *
- *  ******************************************************************
- */
-
-#define SB105X_RX		0	/* In:  Receive buffer */
-#define SB105X_TX		0	/* Out: Transmit buffer */
-
-#define SB105X_IER		1	/* Out: Interrupt Enable Register */
-
-#define SB105X_IER_CTSI	  	0x80	/* CTS# Interrupt Enable (Requires EFR[4] = 1) */
-#define SB105X_IER_RTSI	  	0x40	/* RTS# Interrupt Enable (Requires EFR[4] = 1) */
-#define SB105X_IER_XOI	  	0x20	/* Xoff Interrupt Enable (Requires EFR[4] = 1) */
-#define SB105X_IER_SME	  	0x10	/* Sleep Mode Enable (Requires EFR[4] = 1) */
-#define SB105X_IER_MSI	  	0x08	/* Enable Modem status interrupt */
-#define SB105X_IER_RLSI	  	0x04	/* Enable receiver line status interrupt */
-#define SB105X_IER_THRI	  	0x02	/* Enable Transmitter holding register int. */
-#define SB105X_IER_RDI	  	0x01	/* Enable receiver data interrupt */
-
-#define SB105X_ISR		2	/* In:  Interrupt ID Register */
-
-#define SB105X_ISR_NOINT	0x01	/* No interrupts pending */
-#define SB105X_ISR_RLSI	  	0x06	/* Receiver line status interrupt (Priority = 1)*/
-#define SB105X_ISR_RDAI	  	0x0c	/* Receive Data Available interrupt */
-#define SB105X_ISR_CTII	  	0x04	/* Character Timeout Indication interrupt */
-#define SB105X_ISR_THRI	  	0x02	/* Transmitter holding register empty */
-#define SB105X_ISR_MSI	  	0x00	/* Modem status interrupt */
-#define SB105X_ISR_RXCI	  	0x10	/* Receive Xoff or Special Character interrupt */
-#define SB105X_ISR_RCSI	  	0x20	/* RTS#, CTS# status interrupt during Auto RTS/CTS flow control */
-
-#define SB105X_FCR		2	/* Out: FIFO Control Register */
-
-#define SB105X_FCR_FEN    	0x01	/* FIFO Enable */
-#define SB105X_FCR_RXFR	  	0x02	/* RX FIFO Reset */
-#define SB105X_FCR_TXFR	  	0x04	/* TX FIFO Reset */
-#define SB105X_FCR_DMS	  	0x08	/* DMA Mode Select */
-
-#define SB105X_FCR_RTR08  	0x00  /* Receive Trigger Level set at 8 */
-#define SB105X_FCR_RTR16  	0x40  /* Receive Trigger Level set at 16 */
-#define SB105X_FCR_RTR56  	0x80  /* Receive Trigger Level set at 56 */
-#define SB105X_FCR_RTR60  	0xc0  /* Receive Trigger Level set at 60 */
-#define SB105X_FCR_TTR08  	0x00  /* Transmit Trigger Level set at 8 */
-#define SB105X_FCR_TTR16	0x10  /* Transmit Trigger Level set at 16 */
-#define SB105X_FCR_TTR32	0x20  /* Transmit Trigger Level set at 32 */
-#define SB105X_FCR_TTR56	0x30  /* Transmit Trigger Level set at 56 */
-
-#define SB105X_LCR		3	/* Out: Line Control Register */
-/*
- *  * Note: if the word length is 5 bits (SB105X_LCR_WLEN5), then setting 
- *  * SB105X_LCR_STOP will select 1.5 stop bits, not 2 stop bits.
- */
-#define SB105X_LCR_DLAB   	0x80  /* Divisor Latch Enable */
-#define SB105X_LCR_SBC    	0x40  /* Break Enable*/
-#define SB105X_LCR_SPAR   	0x20  /* Set Stick parity */
-#define SB105X_LCR_EPAR   	0x10  /* Even parity select */
-#define SB105X_LCR_PAREN  	0x08  /* Parity Enable */
-#define SB105X_LCR_STOP   	0x04  /* Stop bits: 0->1 bit, 1->2 bits, 1 and SB105X_LCR_WLEN5 -> 1.5 bit */
-#define SB105X_LCR_WLEN5  	0x00  /* Wordlength: 5 bits */
-#define SB105X_LCR_WLEN6  	0x01  /* Wordlength: 6 bits */
-#define SB105X_LCR_WLEN7  	0x02  /* Wordlength: 7 bits */
-#define SB105X_LCR_WLEN8  	0x03  /* Wordlength: 8 bits */
-
-#define SB105X_LCR_BF		0xBF
-
-#define SB105X_MCR		4	/* Out: Modem Control Register */
-#define SB105X_MCR_CPS    	0x80  /* Clock Prescaler Select */
-#define SB105X_MCR_P2S    	0x40  /* Page 2 Select /Xoff Re-Transmit Access Enable */
-#define SB105X_MCR_XOA    	0x20  /* Xon Any Enable */
-#define SB105X_MCR_ILB		0x10  /* Internal Loopback Enable */
-#define SB105X_MCR_OUT2		0x08  /* Out2/Interrupt Output Enable*/
-#define SB105X_MCR_OUT1		0x04  /* Out1/Interrupt Output Enable */
-#define SB105X_MCR_RTS    	0x02  /* RTS# Output */
-#define SB105X_MCR_DTR    	0x01  /* DTR# Output */
-
-#define SB105X_LSR		5	/* In:  Line Status Register */
-#define SB105X_LSR_RFEI   	0x80  /* Receive FIFO data error Indicator */
-#define SB105X_LSR_TEMI   	0x40  /* THR and TSR Empty Indicator */
-#define SB105X_LSR_THRE		0x20  /* THR Empty Indicator */
-#define SB105X_LSR_BII		0x10  /* Break interrupt indicator */
-#define SB105X_LSR_FEI		0x08  /* Frame error indicator */
-#define SB105X_LSR_PEI		0x04  /* Parity error indicator */
-#define SB105X_LSR_OEI		0x02  /* Overrun error indicator */
-#define SB105X_LSR_RDRI		0x01  /* Receive data ready Indicator*/
-
-#define SB105X_MSR		6	/* In:  Modem Status Register */
-#define SB105X_MSR_DCD		0x80  /* Data Carrier Detect */
-#define SB105X_MSR_RI		0x40  /* Ring Indicator */
-#define SB105X_MSR_DSR		0x20  /* Data Set Ready */
-#define SB105X_MSR_CTS		0x10  /* Clear to Send */
-#define SB105X_MSR_DDCD		0x08  /* Delta DCD */
-#define SB105X_MSR_DRI		0x04  /* Delta ring indicator */
-#define SB105X_MSR_DDSR		0x02  /* Delta DSR */
-#define SB105X_MSR_DCTS		0x01  /* Delta CTS */
-
-#define SB105XA_MDR		6	/* Out: Multi Drop mode Register */
-#define SB105XA_MDR_NPS		0x08  /* 9th Bit Polarity Select */
-#define SB105XA_MDR_AME		0x02  /* Auto Multi-drop Enable */
-#define SB105XA_MDR_MDE		0x01  /* Multi Drop Enable */
-
-#define SB105X_SPR		7	/* I/O: Scratch Register */
-
-/*
- * DLAB=1
- */
-#define SB105X_DLL		0	/* Out: Divisor Latch Low */
-#define SB105X_DLM		1	/* Out: Divisor Latch High */
-
-/*
- *  ******************************************************************
- *  * DLAB(LCR[7]) = 0 , MCR[6] = 1  =============  Page 2 Registers *
- *  ******************************************************************
- */
-#define SB105X_GICR		1	/* Global Interrupt Control Register */
-#define SB105X_GICR_GIM   	0x01  /* Global Interrupt Mask */
-
-#define SB105X_GISR		2	/* Global Interrupt Status Register */
-#define SB105X_GISR_MGICR0  	0x80  /* Mirror the content of GICR[0] */
-#define SB105X_GISR_CS3IS   	0x08  /* SB105X of CS3# Interrupt Status */
-#define SB105X_GISR_CS2IS   	0x04  /* SB105X of CS2# Interrupt Status */
-#define SB105X_GISR_CS1IS   	0x02  /* SB105X of CS1# Interrupt Status */
-#define SB105X_GISR_CS0IS   	0x01  /* SB105X of CS0# Interrupt Status */
-
-#define SB105X_TFCR		5	/* Transmit FIFO Count Register */
-
-#define SB105X_RFCR		6	/* Receive FIFO Count Register */
-
-#define	SB105X_FSR		7	/* Flow Control Status Register */
-#define SB105X_FSR_THFS     	0x20  /* Transmit Hardware Flow Control Status */
-#define SB105X_FSR_TSFS     	0x10  /* Transmit Software Flow Control Status */
-#define SB105X_FSR_RHFS     	0x02  /* Receive Hardware Flow Control Status */
-#define SB105X_FSR_RSFS     	0x01  /* Receive Software Flow Control Status */
-
-/*
- *  ******************************************************************
- *  * LCR = 0xBF, PSR[0] = 0       =============    Page 3 Registers *
- *  ******************************************************************
- */
-
-#define SB105X_PSR		0	/* Page Select Register */
-#define SB105X_PSR_P3KEY    	0xA4 /* Page 3 Select Key */
-#define SB105X_PSR_P4KEY    	0xA5 /* Page 5 Select Key */
-
-#define SB105X_ATR		1	/* Auto Toggle Control Register */
-#define SB105X_ATR_RPS      	0x80  /* RXEN Polarity Select */
-#define SB105X_ATR_RCMS     	0x40  /* RXEN Control Mode Select */
-#define SB105X_ATR_TPS      	0x20  /* TXEN Polarity Select */
-#define SB105X_ATR_TCMS     	0x10  /* TXEN Control Mode Select */
-#define SB105X_ATR_ATDIS    	0x00  /* Auto Toggle is disabled */
-#define SB105X_ATR_ART      	0x01  /* RTS#/TXEN pin operates as TXEN */
-#define SB105X_ATR_ADT      	0x02  /* DTR#/TXEN pin operates as TXEN */
-#define SB105X_ATR_A80      	0x03  /* only in 80 pin use */
-
-#define SB105X_EFR		2	/* (Auto) Enhanced Feature Register */
-#define SB105X_EFR_ACTS     	0x80  /* Auto-CTS Flow Control Enable */
-#define SB105X_EFR_ARTS     	0x40  /* Auto-RTS Flow Control Enable */
-#define SB105X_EFR_SCD      	0x20  /* Special Character Detect */
-#define SB105X_EFR_EFBEN    	0x10  /* Enhanced Function Bits Enable */
-
-#define SB105X_XON1		4	/* Xon1 Character Register */
-#define SB105X_XON2		5	/* Xon2 Character Register */
-#define SB105X_XOFF1		6	/* Xoff1 Character Register */
-#define SB105X_XOFF2		7	/* Xoff2 Character Register */
-
-/*
- *  ******************************************************************
- *  * LCR = 0xBF, PSR[0] = 1       ============     Page 4 Registers *
- *  ******************************************************************
- */
-
-#define SB105X_AFR		1	/* Additional Feature Register */
-#define SB105X_AFR_GIPS     	0x20  /* Global Interrupt Polarity Select */
-#define SB105X_AFR_GIEN     	0x10  /* Global Interrupt Enable */
-#define SB105X_AFR_AFEN     	0x01  /* 256-byte FIFO Enable */
-
-#define SB105X_XRCR		2	/* Xoff Re-transmit Count Register */
-#define SB105X_XRCR_NRC1    	0x00  /* Transmits Xoff Character whenever the number of received data is 1 during XOFF status */
-#define SB105X_XRCR_NRC4    	0x01  /* Transmits Xoff Character whenever the number of received data is 4 during XOFF status */
-#define SB105X_XRCR_NRC8    	0x02  /* Transmits Xoff Character whenever the number of received data is 8 during XOFF status */
-#define SB105X_XRCR_NRC16   	0x03  /* Transmits Xoff Character whenever the number of received data is 16 during XOFF status */
-
-#define SB105X_TTR		4	/* Transmit FIFO Trigger Level Register */
-#define SB105X_RTR		5	/* Receive FIFO Trigger Level Register */
-#define SB105X_FUR		6	/* Flow Control Upper Threshold Register */
-#define SB105X_FLR		7	/* Flow Control Lower Threshold Register */
-
-
-/* page 0 */
-
-#define SB105X_GET_CHAR(port)	inb((port)->iobase + SB105X_RX)
-#define SB105X_GET_IER(port)	inb((port)->iobase + SB105X_IER)
-#define SB105X_GET_ISR(port)	inb((port)->iobase + SB105X_ISR)
-#define SB105X_GET_LCR(port)	inb((port)->iobase + SB105X_LCR)
-#define SB105X_GET_MCR(port)	inb((port)->iobase + SB105X_MCR)
-#define SB105X_GET_LSR(port)	inb((port)->iobase + SB105X_LSR)
-#define SB105X_GET_MSR(port)	inb((port)->iobase + SB105X_MSR)
-#define SB105X_GET_SPR(port)	inb((port)->iobase + SB105X_SPR)
-
-#define SB105X_PUT_CHAR(port,v)	outb((v),(port)->iobase + SB105X_TX )
-#define SB105X_PUT_IER(port,v)	outb((v),(port)->iobase + SB105X_IER )
-#define SB105X_PUT_FCR(port,v)	outb((v),(port)->iobase + SB105X_FCR )
-#define SB105X_PUT_LCR(port,v)	outb((v),(port)->iobase + SB105X_LCR )
-#define SB105X_PUT_MCR(port,v)	outb((v),(port)->iobase + SB105X_MCR )
-#define SB105X_PUT_SPR(port,v)	outb((v),(port)->iobase + SB105X_SPR )
-
-
-/* page 1 */
-#define SB105X_GET_REG(port,reg)	inb((port)->iobase + (reg))
-#define SB105X_PUT_REG(port,reg,v)	outb((v),(port)->iobase + (reg))
-
-/* page 2 */
-
-#define SB105X_PUT_PSR(port,v)	outb((v),(port)->iobase + SB105X_PSR )
-
-#endif 
diff --git a/drivers/staging/sb105x/sb_pci_mp.c b/drivers/staging/sb105x/sb_pci_mp.c
deleted file mode 100644
index c9d6ee3..0000000
--- a/drivers/staging/sb105x/sb_pci_mp.c
+++ /dev/null
@@ -1,3189 +0,0 @@
-#include "sb_pci_mp.h"
-#include <linux/module.h>
-#include <linux/parport.h>
-
-extern struct parport *parport_pc_probe_port(unsigned long base_lo,
-		unsigned long base_hi,
-		int irq, int dma,
-		struct device *dev,
-		int irqflags);
-
-static struct mp_device_t mp_devs[MAX_MP_DEV];
-static int mp_nrpcibrds = sizeof(mp_pciboards)/sizeof(mppcibrd_t);
-static int NR_BOARD=0;
-static int NR_PORTS=0;
-static struct mp_port multi_ports[MAX_MP_PORT];
-static struct irq_info irq_lists[NR_IRQS];
-
-static _INLINE_ unsigned int serial_in(struct mp_port *mtpt, int offset);
-static _INLINE_ void serial_out(struct mp_port *mtpt, int offset, int value);
-static _INLINE_ unsigned int read_option_register(struct mp_port *mtpt, int offset);
-static int sb1054_get_register(struct sb_uart_port *port, int page, int reg);
-static int sb1054_set_register(struct sb_uart_port *port, int page, int reg, int value);
-static void SendATCommand(struct mp_port *mtpt);
-static int set_deep_fifo(struct sb_uart_port *port, int status);
-static int get_deep_fifo(struct sb_uart_port *port);
-static int get_device_type(int arg);
-static int set_auto_rts(struct sb_uart_port *port, int status);
-static void mp_stop(struct tty_struct *tty);
-static void __mp_start(struct tty_struct *tty);
-static void mp_start(struct tty_struct *tty);
-static void mp_tasklet_action(unsigned long data);
-static inline void mp_update_mctrl(struct sb_uart_port *port, unsigned int set, unsigned int clear);
-static int mp_startup(struct sb_uart_state *state, int init_hw);
-static void mp_shutdown(struct sb_uart_state *state);
-static void mp_change_speed(struct sb_uart_state *state, struct MP_TERMIOS *old_termios);
-
-static inline int __mp_put_char(struct sb_uart_port *port, struct circ_buf *circ, unsigned char c);
-static int mp_put_char(struct tty_struct *tty, unsigned char ch);
-
-static void mp_put_chars(struct tty_struct *tty);
-static int mp_write(struct tty_struct *tty, const unsigned char *buf, int count);
-static int mp_write_room(struct tty_struct *tty);
-static int mp_chars_in_buffer(struct tty_struct *tty);
-static void mp_flush_buffer(struct tty_struct *tty);
-static void mp_send_xchar(struct tty_struct *tty, char ch);
-static void mp_throttle(struct tty_struct *tty);
-static void mp_unthrottle(struct tty_struct *tty);
-static int mp_get_info(struct sb_uart_state *state, struct serial_struct *retinfo);
-static int mp_set_info(struct sb_uart_state *state, struct serial_struct *newinfo);
-static int mp_get_lsr_info(struct sb_uart_state *state, unsigned int *value);
-
-static int mp_tiocmget(struct tty_struct *tty);
-static int mp_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear);
-static int mp_break_ctl(struct tty_struct *tty, int break_state);
-static int mp_do_autoconfig(struct sb_uart_state *state);
-static int mp_wait_modem_status(struct sb_uart_state *state, unsigned long arg);
-static int mp_get_count(struct sb_uart_state *state, struct serial_icounter_struct *icnt);
-static int mp_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg);
-static void mp_set_termios(struct tty_struct *tty, struct MP_TERMIOS *old_termios);
-static void mp_close(struct tty_struct *tty, struct file *filp);
-static void mp_wait_until_sent(struct tty_struct *tty, int timeout);
-static void mp_hangup(struct tty_struct *tty);
-static void mp_update_termios(struct sb_uart_state *state);
-static int mp_block_til_ready(struct file *filp, struct sb_uart_state *state);
-static struct sb_uart_state *uart_get(struct uart_driver *drv, int line);
-static int mp_open(struct tty_struct *tty, struct file *filp);
-static const char *mp_type(struct sb_uart_port *port);
-static void mp_change_pm(struct sb_uart_state *state, int pm_state);
-static inline void mp_report_port(struct uart_driver *drv, struct sb_uart_port *port);
-static void mp_configure_port(struct uart_driver *drv, struct sb_uart_state *state, struct sb_uart_port *port);
-static void mp_unconfigure_port(struct uart_driver *drv, struct sb_uart_state *state);
-static int mp_register_driver(struct uart_driver *drv);
-static void mp_unregister_driver(struct uart_driver *drv);
-static int mp_add_one_port(struct uart_driver *drv, struct sb_uart_port *port);
-static int mp_remove_one_port(struct uart_driver *drv, struct sb_uart_port *port);
-static void autoconfig(struct mp_port *mtpt, unsigned int probeflags);
-static void autoconfig_irq(struct mp_port *mtpt);
-static void multi_stop_tx(struct sb_uart_port *port);
-static void multi_start_tx(struct sb_uart_port *port);
-static void multi_stop_rx(struct sb_uart_port *port);
-static void multi_enable_ms(struct sb_uart_port *port);
-static _INLINE_ void receive_chars(struct mp_port *mtpt, int *status );
-static _INLINE_ void transmit_chars(struct mp_port *mtpt);
-static _INLINE_ void check_modem_status(struct mp_port *mtpt);
-static inline void multi_handle_port(struct mp_port *mtpt);
-static irqreturn_t multi_interrupt(int irq, void *dev_id);
-static void serial_do_unlink(struct irq_info *i, struct mp_port *mtpt);
-static int serial_link_irq_chain(struct mp_port *mtpt);
-static void serial_unlink_irq_chain(struct mp_port *mtpt);
-static void multi_timeout(unsigned long data);
-static unsigned int multi_tx_empty(struct sb_uart_port *port);
-static unsigned int multi_get_mctrl(struct sb_uart_port *port);
-static void multi_set_mctrl(struct sb_uart_port *port, unsigned int mctrl);
-static void multi_break_ctl(struct sb_uart_port *port, int break_state);
-static int multi_startup(struct sb_uart_port *port);
-static void multi_shutdown(struct sb_uart_port *port);
-static unsigned int multi_get_divisor(struct sb_uart_port *port, unsigned int baud);
-static void multi_set_termios(struct sb_uart_port *port, struct MP_TERMIOS *termios, struct MP_TERMIOS *old);
-static void multi_pm(struct sb_uart_port *port, unsigned int state, unsigned int oldstate);
-static void multi_release_std_resource(struct mp_port *mtpt);
-static void multi_release_port(struct sb_uart_port *port);
-static int multi_request_port(struct sb_uart_port *port);
-static void multi_config_port(struct sb_uart_port *port, int flags);
-static int multi_verify_port(struct sb_uart_port *port, struct serial_struct *ser);
-static const char *multi_type(struct sb_uart_port *port);
-static void __init multi_init_ports(void);
-static void __init multi_register_ports(struct uart_driver *drv);
-static int init_mp_dev(struct pci_dev *pcidev, mppcibrd_t brd);
-
-static int deep[256];
-static int deep_count;
-static int fcr_arr[256];
-static int fcr_count;
-static int ttr[256];
-static int ttr_count;
-static int rtr[256];
-static int rtr_count;
-
-module_param_array(deep,int,&deep_count,0);
-module_param_array(fcr_arr,int,&fcr_count,0);
-module_param_array(ttr,int,&ttr_count,0);
-module_param_array(rtr,int,&rtr_count,0);
-
-static _INLINE_ unsigned int serial_in(struct mp_port *mtpt, int offset)
-{
-	return inb(mtpt->port.iobase + offset);
-}
-
-static _INLINE_ void serial_out(struct mp_port *mtpt, int offset, int value)
-{
-	outb(value, mtpt->port.iobase + offset);
-}
-
-static _INLINE_ unsigned int read_option_register(struct mp_port *mtpt, int offset)
-{
-	return inb(mtpt->option_base_addr + offset);
-}
-
-static int sb1053a_get_interface(struct mp_port *mtpt, int port_num)
-{
-	unsigned long option_base_addr = mtpt->option_base_addr;
-	unsigned int  interface = 0;
-
-	switch (port_num)
-	{
-		case 0:
-		case 1:
-			/* set GPO[1:0] = 00 */
-			outb(0x00, option_base_addr + MP_OPTR_GPODR);
-			break;
-		case 2:
-		case 3:
-			/* set GPO[1:0] = 01 */
-			outb(0x01, option_base_addr + MP_OPTR_GPODR);
-			break;
-		case 4:
-		case 5:
-			/* set GPO[1:0] = 10 */
-			outb(0x02, option_base_addr + MP_OPTR_GPODR);
-			break;
-		default:
-			break;
-	}
-
-	port_num &= 0x1;
-
-	/* get interface */
-	interface = inb(option_base_addr + MP_OPTR_IIR0 + port_num);
-
-	/* set GPO[1:0] = 11 */
-	outb(0x03, option_base_addr + MP_OPTR_GPODR);
-
-	return (interface);
-}
-		
-static int sb1054_get_register(struct sb_uart_port *port, int page, int reg)
-{
-	int ret = 0;
-	unsigned int lcr = 0;
-	unsigned int mcr = 0;
-	unsigned int tmp = 0;
-
-	if( page <= 0)
-	{
-		printk(" page 0 can not use this function\n");
-		return -1;
-	}
-
-	switch(page)
-	{
-		case 1:
-			lcr = SB105X_GET_LCR(port);
-			tmp = lcr | SB105X_LCR_DLAB;
-			SB105X_PUT_LCR(port, tmp);
-
-			tmp = SB105X_GET_LCR(port);
-
-			ret = SB105X_GET_REG(port,reg);
-			SB105X_PUT_LCR(port,lcr);
-			break;
-		case 2:
-			mcr = SB105X_GET_MCR(port);
-			tmp = mcr | SB105X_MCR_P2S;
-			SB105X_PUT_MCR(port,tmp);
-
-			ret = SB105X_GET_REG(port,reg);
-
-			SB105X_PUT_MCR(port,mcr);
-			break;
-		case 3:
-			lcr = SB105X_GET_LCR(port);
-			tmp = lcr | SB105X_LCR_BF;
-			SB105X_PUT_LCR(port,tmp);
-			SB105X_PUT_REG(port,SB105X_PSR,SB105X_PSR_P3KEY);
-
-			ret = SB105X_GET_REG(port,reg);
-
-			SB105X_PUT_LCR(port,lcr);
-			break;
-		case 4:
-			lcr = SB105X_GET_LCR(port);
-			tmp = lcr | SB105X_LCR_BF;
-			SB105X_PUT_LCR(port,tmp);
-			SB105X_PUT_REG(port,SB105X_PSR,SB105X_PSR_P4KEY);
-
-			ret = SB105X_GET_REG(port,reg);
-
-			SB105X_PUT_LCR(port,lcr);
-			break;
-		default:
-			printk(" error invalid page number \n");
-			return -1;
-	}
-
-	return ret;
-}
-
-static int sb1054_set_register(struct sb_uart_port *port, int page, int reg, int value)
-{  
-	int lcr = 0;
-	int mcr = 0;
-	int ret = 0;
-
-	if( page <= 0)
-	{
-		printk(" page 0 can not use this function\n");
-		return -1;
-	}
-	switch(page)
-	{
-		case 1:
-			lcr = SB105X_GET_LCR(port);
-			SB105X_PUT_LCR(port, lcr | SB105X_LCR_DLAB);
-
-			SB105X_PUT_REG(port,reg,value);
-
-			SB105X_PUT_LCR(port, lcr);
-			ret = 1;
-			break;
-		case 2:
-			mcr = SB105X_GET_MCR(port);
-			SB105X_PUT_MCR(port, mcr | SB105X_MCR_P2S);
-
-			SB105X_PUT_REG(port,reg,value);
-
-			SB105X_PUT_MCR(port, mcr);
-			ret = 1;
-			break;
-		case 3:
-			lcr = SB105X_GET_LCR(port);
-			SB105X_PUT_LCR(port, lcr | SB105X_LCR_BF);
-			SB105X_PUT_PSR(port, SB105X_PSR_P3KEY);
-
-			SB105X_PUT_REG(port,reg,value);
-
-			SB105X_PUT_LCR(port, lcr);
-			ret = 1;
-			break;
-		case 4:
-			lcr = SB105X_GET_LCR(port);
-			SB105X_PUT_LCR(port, lcr | SB105X_LCR_BF);
-			SB105X_PUT_PSR(port, SB105X_PSR_P4KEY);
-
-			SB105X_PUT_REG(port,reg,value);
-
-			SB105X_PUT_LCR(port, lcr);
-			ret = 1;
-			break;
-		default:
-			printk(" error invalid page number \n");
-			return -1;
-	}
-
-	return ret;
-}
-
-static int set_multidrop_mode(struct sb_uart_port *port, unsigned int mode)
-{
-	int mdr = SB105XA_MDR_NPS;
-
-	if (mode & MDMODE_ENABLE)
-	{
-		mdr |= SB105XA_MDR_MDE;
-	}
-
-	if (1) //(mode & MDMODE_AUTO)
-	{
-		int efr = 0;
-		mdr |= SB105XA_MDR_AME;
-		efr = sb1054_get_register(port, PAGE_3, SB105X_EFR);
-		efr |= SB105X_EFR_SCD;
-		sb1054_set_register(port, PAGE_3, SB105X_EFR, efr);
-	}
-
-	sb1054_set_register(port, PAGE_1, SB105XA_MDR, mdr);
-	port->mdmode &= ~0x6;
-	port->mdmode |= mode;
-	printk("[%d] multidrop init: %x\n", port->line, port->mdmode);
-
-	return 0;
-}
-
-static int get_multidrop_addr(struct sb_uart_port *port)
-{
-	return sb1054_get_register(port, PAGE_3, SB105X_XOFF2);
-}
-
-static int set_multidrop_addr(struct sb_uart_port *port, unsigned int addr)
-{
-	sb1054_set_register(port, PAGE_3, SB105X_XOFF2, addr);
-
-	return 0;
-}
-
-static void SendATCommand(struct mp_port *mtpt)
-{
-	//		      a    t	cr   lf
-	unsigned char ch[] = {0x61,0x74,0x0d,0x0a,0x0};
-	unsigned char lineControl;
-	unsigned char i=0;
-	unsigned char Divisor = 0xc;
-
-	lineControl = serial_inp(mtpt,UART_LCR);
-	serial_outp(mtpt,UART_LCR,(lineControl | UART_LCR_DLAB));
-	serial_outp(mtpt,UART_DLL,(Divisor & 0xff));
-	serial_outp(mtpt,UART_DLM,(Divisor & 0xff00)>>8); //baudrate is 4800
-
-
-	serial_outp(mtpt,UART_LCR,lineControl);	
-	serial_outp(mtpt,UART_LCR,0x03); // N-8-1
-	serial_outp(mtpt,UART_FCR,7); 
-	serial_outp(mtpt,UART_MCR,0x3);
-	while(ch[i]){
-		while((serial_inp(mtpt,UART_LSR) & 0x60) !=0x60){
-			;
-		}
-		serial_outp(mtpt,0,ch[i++]);
-	}
-
-
-}// end of SendATCommand()
-
-static int set_deep_fifo(struct sb_uart_port *port, int status)
-{
-	int afr_status = 0;
-	afr_status = sb1054_get_register(port, PAGE_4, SB105X_AFR);
-
-	if(status == ENABLE)
-	{
-		afr_status |= SB105X_AFR_AFEN;
-	}
-	else
-	{
-		afr_status &= ~SB105X_AFR_AFEN;
-	}
-		
-	sb1054_set_register(port,PAGE_4,SB105X_AFR,afr_status);
-	sb1054_set_register(port,PAGE_4,SB105X_TTR,ttr[port->line]); 
-	sb1054_set_register(port,PAGE_4,SB105X_RTR,rtr[port->line]); 
-	afr_status = sb1054_get_register(port, PAGE_4, SB105X_AFR);
-		
-	return afr_status;
-}
-
-static int get_device_type(int arg)
-{
-	int ret;
-        ret = inb(mp_devs[arg].option_reg_addr+MP_OPTR_DIR0);
-        ret = (ret & 0xf0) >> 4;
-        switch (ret)
-        {
-               case DIR_UART_16C550:
-                    return PORT_16C55X;
-               case DIR_UART_16C1050:
-                    return PORT_16C105X;
-               case DIR_UART_16C1050A:
-               /*
-               if (mtpt->port.line < 2)
-               {
-                    return PORT_16C105XA;
-               }
-               else
-               {
-                   if (mtpt->device->device_id & 0x50)
-                   {
-                       return PORT_16C55X;
-                   }
-                   else
-                   {
-                       return PORT_16C105X;
-                   }
-               }*/
-               return PORT_16C105XA;
-               default:
-                    return PORT_UNKNOWN;
-        }
-
-}
-static int get_deep_fifo(struct sb_uart_port *port)
-{
-	int afr_status = 0;
-	afr_status = sb1054_get_register(port, PAGE_4, SB105X_AFR);
-	return afr_status;
-}
-
-static int set_auto_rts(struct sb_uart_port *port, int status)
-{
-	int atr_status = 0;
-
-#if 0
-	int efr_status = 0;
-
-	efr_status = sb1054_get_register(port, PAGE_3, SB105X_EFR);
-	if(status == ENABLE)
-		efr_status |= SB105X_EFR_ARTS;
-	else
-		efr_status &= ~SB105X_EFR_ARTS;
-	sb1054_set_register(port,PAGE_3,SB105X_EFR,efr_status);
-	efr_status = sb1054_get_register(port, PAGE_3, SB105X_EFR);
-#endif
-		
-//ATR
-	atr_status = sb1054_get_register(port, PAGE_3, SB105X_ATR);
-	switch(status)
-	{
-		case RS422PTP:
-			atr_status = (SB105X_ATR_TPS) | (SB105X_ATR_A80);
-			break;
-		case RS422MD:
-			atr_status = (SB105X_ATR_TPS) | (SB105X_ATR_TCMS) | (SB105X_ATR_A80);
-			break;
-		case RS485NE:
-			atr_status = (SB105X_ATR_RCMS) | (SB105X_ATR_TPS) | (SB105X_ATR_TCMS) | (SB105X_ATR_A80);
-			break;
-		case RS485ECHO:
-			atr_status = (SB105X_ATR_TPS) | (SB105X_ATR_TCMS) | (SB105X_ATR_A80);
-			break;
-	}
-
-	sb1054_set_register(port,PAGE_3,SB105X_ATR,atr_status);
-	atr_status = sb1054_get_register(port, PAGE_3, SB105X_ATR);
-
-	return atr_status;
-}
-
-static void mp_stop(struct tty_struct *tty)
-{
-	struct sb_uart_state *state = tty->driver_data;
-	struct sb_uart_port *port = state->port;
-	unsigned long flags;
-
-	spin_lock_irqsave(&port->lock, flags);
-	port->ops->stop_tx(port);
-	spin_unlock_irqrestore(&port->lock, flags);
-}
-
-static void __mp_start(struct tty_struct *tty)
-{
-	struct sb_uart_state *state = tty->driver_data;
-	struct sb_uart_port *port = state->port;
-
-	if (!uart_circ_empty(&state->info->xmit) && state->info->xmit.buf &&
-			!tty->stopped && !tty->hw_stopped)
-		port->ops->start_tx(port);
-}
-
-static void mp_start(struct tty_struct *tty)
-{
-	__mp_start(tty);
-}
-
-static void mp_tasklet_action(unsigned long data)
-{
-	struct sb_uart_state *state = (struct sb_uart_state *)data;
-	struct tty_struct *tty;
-
-	printk("tasklet is called!\n");
-	tty = state->info->tty;
-	tty_wakeup(tty);
-}
-
-static inline void mp_update_mctrl(struct sb_uart_port *port, unsigned int set, unsigned int clear)
-{
-	unsigned int old;
-
-	old = port->mctrl;
-	port->mctrl = (old & ~clear) | set;
-	if (old != port->mctrl)
-		port->ops->set_mctrl(port, port->mctrl);
-}
-
-#define uart_set_mctrl(port,set)	mp_update_mctrl(port,set,0)
-#define uart_clear_mctrl(port,clear)	mp_update_mctrl(port,0,clear)
-
-static int mp_startup(struct sb_uart_state *state, int init_hw)
-{
-	struct sb_uart_info *info = state->info;
-	struct sb_uart_port *port = state->port;
-	unsigned long page;
-	int retval = 0;
-
-	if (info->flags & UIF_INITIALIZED)
-		return 0;
-
-	if (info->tty)
-		set_bit(TTY_IO_ERROR, &info->tty->flags);
-
-	if (port->type == PORT_UNKNOWN)
-		return 0;
-
-	if (!info->xmit.buf) {
-		page = get_zeroed_page(GFP_KERNEL);
-		if (!page)
-			return -ENOMEM;
-
-		info->xmit.buf = (unsigned char *) page;
-			
-		uart_circ_clear(&info->xmit);
-	}
-
-	retval = port->ops->startup(port);
-	if (retval == 0) {
-		if (init_hw) {
-			mp_change_speed(state, NULL);
-
-			if (info->tty && (info->tty->termios.c_cflag & CBAUD))
-				uart_set_mctrl(port, TIOCM_RTS | TIOCM_DTR);
-		}
-
-		info->flags |= UIF_INITIALIZED;
-
-		if (info->tty)
-			clear_bit(TTY_IO_ERROR, &info->tty->flags);
-	}
-
-	if (retval && capable(CAP_SYS_ADMIN))
-		retval = 0;
-
-	return retval;
-}
-
-static void mp_shutdown(struct sb_uart_state *state)
-{
-	struct sb_uart_info *info = state->info;
-	struct sb_uart_port *port = state->port;
-
-	if (info->tty)
-		set_bit(TTY_IO_ERROR, &info->tty->flags);
-
-	if (info->flags & UIF_INITIALIZED) {
-		info->flags &= ~UIF_INITIALIZED;
-
-		if (!info->tty || (info->tty->termios.c_cflag & HUPCL))
-			uart_clear_mctrl(port, TIOCM_DTR | TIOCM_RTS);
-
-		wake_up_interruptible(&info->delta_msr_wait);
-
-		port->ops->shutdown(port);
-
-		synchronize_irq(port->irq);
-	}
-	tasklet_kill(&info->tlet);
-
-	if (info->xmit.buf) {
-		free_page((unsigned long)info->xmit.buf);
-		info->xmit.buf = NULL;
-	}
-}
-
-static void mp_change_speed(struct sb_uart_state *state, struct MP_TERMIOS *old_termios)
-{
-	struct tty_struct *tty = state->info->tty;
-	struct sb_uart_port *port = state->port;
-
-	if (!tty || port->type == PORT_UNKNOWN)
-		return;
-
-	if (tty->termios.c_cflag & CRTSCTS)
-		state->info->flags |= UIF_CTS_FLOW;
-	else
-		state->info->flags &= ~UIF_CTS_FLOW;
-
-	if (tty->termios.c_cflag & CLOCAL)
-		state->info->flags &= ~UIF_CHECK_CD;
-	else
-		state->info->flags |= UIF_CHECK_CD;
-
-	port->ops->set_termios(port, &tty->termios, old_termios);
-}
-
-static inline int __mp_put_char(struct sb_uart_port *port, struct circ_buf *circ, unsigned char c)
-{
-	unsigned long flags;
-	int ret = 0;
-
-	if (!circ->buf)
-		return 0;
-
-	spin_lock_irqsave(&port->lock, flags);
-	if (uart_circ_chars_free(circ) != 0) {
-		circ->buf[circ->head] = c;
-		circ->head = (circ->head + 1) & (UART_XMIT_SIZE - 1);
-		ret = 1;
-	}
-	spin_unlock_irqrestore(&port->lock, flags);
-	return ret;
-}
-
-static int mp_put_char(struct tty_struct *tty, unsigned char ch)
-{
-	struct sb_uart_state *state = tty->driver_data;
-
-	return __mp_put_char(state->port, &state->info->xmit, ch);
-}
-
-static void mp_put_chars(struct tty_struct *tty)
-{
-	mp_start(tty);
-}
-
-static int mp_write(struct tty_struct *tty, const unsigned char *buf, int count)
-{
-	struct sb_uart_state *state = tty->driver_data;
-	struct sb_uart_port *port;
-	struct circ_buf *circ;
-	int c, ret = 0;
-
-	if (!state || !state->info) {
-		return -EL3HLT;
-	}
-
-	port = state->port;
-	circ = &state->info->xmit;
-
-	if (!circ->buf)
-		return 0;
-		
-	while (1) {
-		c = CIRC_SPACE_TO_END(circ->head, circ->tail, UART_XMIT_SIZE);
-		if (count < c)
-			c = count;
-		if (c <= 0)
-			break;
-	memcpy(circ->buf + circ->head, buf, c);
-
-		circ->head = (circ->head + c) & (UART_XMIT_SIZE - 1);
-		buf += c;
-		count -= c;
-		ret += c;
-	}
-	mp_start(tty);
-	return ret;
-}
-
-static int mp_write_room(struct tty_struct *tty)
-{
-	struct sb_uart_state *state = tty->driver_data;
-
-	return uart_circ_chars_free(&state->info->xmit);
-}
-
-static int mp_chars_in_buffer(struct tty_struct *tty)
-{
-	struct sb_uart_state *state = tty->driver_data;
-
-	return uart_circ_chars_pending(&state->info->xmit);
-}
-
-static void mp_flush_buffer(struct tty_struct *tty)
-{
-	struct sb_uart_state *state = tty->driver_data;
-	struct sb_uart_port *port;
-	unsigned long flags;
-
-	if (!state || !state->info) {
-		return;
-	}
-
-	port = state->port;
-	spin_lock_irqsave(&port->lock, flags);
-	uart_circ_clear(&state->info->xmit);
-	spin_unlock_irqrestore(&port->lock, flags);
-	wake_up_interruptible(&tty->write_wait);
-	tty_wakeup(tty);
-}
-
-static void mp_send_xchar(struct tty_struct *tty, char ch)
-{
-	struct sb_uart_state *state = tty->driver_data;
-	struct sb_uart_port *port = state->port;
-	unsigned long flags;
-
-	if (port->ops->send_xchar)
-		port->ops->send_xchar(port, ch);
-	else {
-		port->x_char = ch;
-		if (ch) {
-			spin_lock_irqsave(&port->lock, flags);
-			port->ops->start_tx(port);
-			spin_unlock_irqrestore(&port->lock, flags);
-		}
-	}
-}
-
-static void mp_throttle(struct tty_struct *tty)
-{
-	struct sb_uart_state *state = tty->driver_data;
-
-	if (I_IXOFF(tty))
-		mp_send_xchar(tty, STOP_CHAR(tty));
-
-	if (tty->termios.c_cflag & CRTSCTS)
-		uart_clear_mctrl(state->port, TIOCM_RTS);
-}
-
-static void mp_unthrottle(struct tty_struct *tty)
-{
-	struct sb_uart_state *state = tty->driver_data;
-	struct sb_uart_port *port = state->port;
-
-	if (I_IXOFF(tty)) {
-		if (port->x_char)
-			port->x_char = 0;
-		else
-			mp_send_xchar(tty, START_CHAR(tty));
-	}
-
-	if (tty->termios.c_cflag & CRTSCTS)
-		uart_set_mctrl(port, TIOCM_RTS);
-}
-
-static int mp_get_info(struct sb_uart_state *state, struct serial_struct *retinfo)
-{
-	struct sb_uart_port *port = state->port;
-	struct serial_struct tmp;
-
-	memset(&tmp, 0, sizeof(tmp));
-	tmp.type	    = port->type;
-	tmp.line	    = port->line;
-	tmp.port	    = port->iobase;
-	if (HIGH_BITS_OFFSET)
-		tmp.port_high = (long) port->iobase >> HIGH_BITS_OFFSET;
-	tmp.irq		    = port->irq;
-	tmp.flags	    = port->flags;
-	tmp.xmit_fifo_size  = port->fifosize;
-	tmp.baud_base	    = port->uartclk / 16;
-	tmp.close_delay	    = state->close_delay;
-	tmp.closing_wait    = state->closing_wait == USF_CLOSING_WAIT_NONE ?
-		ASYNC_CLOSING_WAIT_NONE :
-		state->closing_wait;
-	tmp.custom_divisor  = port->custom_divisor;
-	tmp.hub6	    = port->hub6;
-	tmp.io_type         = port->iotype;
-	tmp.iomem_reg_shift = port->regshift;
-	tmp.iomem_base      = (void *)port->mapbase;
-
-	if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
-		return -EFAULT;
-	return 0;
-}
-
-static int mp_set_info(struct sb_uart_state *state, struct serial_struct *newinfo)
-{
-	struct serial_struct new_serial;
-	struct sb_uart_port *port = state->port;
-	unsigned long new_port;
-	unsigned int change_irq, change_port, closing_wait;
-	unsigned int old_custom_divisor;
-	unsigned int old_flags, new_flags;
-	int retval = 0;
-
-	if (copy_from_user(&new_serial, newinfo, sizeof(new_serial)))
-		return -EFAULT;
-
-	new_port = new_serial.port;
-	if (HIGH_BITS_OFFSET)
-		new_port += (unsigned long) new_serial.port_high << HIGH_BITS_OFFSET;
-
-	new_serial.irq = irq_canonicalize(new_serial.irq);
-
-	closing_wait = new_serial.closing_wait == ASYNC_CLOSING_WAIT_NONE ?
-		USF_CLOSING_WAIT_NONE : new_serial.closing_wait;
-	MP_STATE_LOCK(state);
-
-	change_irq  = new_serial.irq != port->irq;
-	change_port = new_port != port->iobase ||
-		(unsigned long)new_serial.iomem_base != port->mapbase ||
-		new_serial.hub6 != port->hub6 ||
-		new_serial.io_type != port->iotype ||
-		new_serial.iomem_reg_shift != port->regshift ||
-		new_serial.type != port->type;
-	old_flags = port->flags;
-	new_flags = new_serial.flags;
-	old_custom_divisor = port->custom_divisor;
-
-	if (!capable(CAP_SYS_ADMIN)) {
-		retval = -EPERM;
-		if (change_irq || change_port ||
-				(new_serial.baud_base != port->uartclk / 16) ||
-				(new_serial.close_delay != state->close_delay) ||
-				(closing_wait != state->closing_wait) ||
-				(new_serial.xmit_fifo_size != port->fifosize) ||
-				(((new_flags ^ old_flags) & ~UPF_USR_MASK) != 0))
-			goto exit;
-		port->flags = ((port->flags & ~UPF_USR_MASK) |
-				(new_flags & UPF_USR_MASK));
-		port->custom_divisor = new_serial.custom_divisor;
-		goto check_and_exit;
-	}
-
-	if (port->ops->verify_port)
-		retval = port->ops->verify_port(port, &new_serial);
-
-	if ((new_serial.irq >= NR_IRQS) || (new_serial.irq < 0) ||
-			(new_serial.baud_base < 9600))
-		retval = -EINVAL;
-
-	if (retval)
-		goto exit;
-
-	if (change_port || change_irq) {
-		retval = -EBUSY;
-
-		if (uart_users(state) > 1)
-			goto exit;
-
-		mp_shutdown(state);
-	}
-
-	if (change_port) {
-		unsigned long old_iobase, old_mapbase;
-		unsigned int old_type, old_iotype, old_hub6, old_shift;
-
-		old_iobase = port->iobase;
-		old_mapbase = port->mapbase;
-		old_type = port->type;
-		old_hub6 = port->hub6;
-		old_iotype = port->iotype;
-		old_shift = port->regshift;
-
-		if (old_type != PORT_UNKNOWN)
-			port->ops->release_port(port);
-
-		port->iobase = new_port;
-		port->type = new_serial.type;
-		port->hub6 = new_serial.hub6;
-		port->iotype = new_serial.io_type;
-		port->regshift = new_serial.iomem_reg_shift;
-		port->mapbase = (unsigned long)new_serial.iomem_base;
-
-		if (port->type != PORT_UNKNOWN) {
-			retval = port->ops->request_port(port);
-		} else {
-			retval = 0;
-		}
-
-		if (retval && old_type != PORT_UNKNOWN) {
-			port->iobase = old_iobase;
-			port->type = old_type;
-			port->hub6 = old_hub6;
-			port->iotype = old_iotype;
-			port->regshift = old_shift;
-			port->mapbase = old_mapbase;
-			retval = port->ops->request_port(port);
-			if (retval)
-				port->type = PORT_UNKNOWN;
-
-			retval = -EBUSY;
-		}
-	}
-
-	port->irq              = new_serial.irq;
-	port->uartclk          = new_serial.baud_base * 16;
-	port->flags            = (port->flags & ~UPF_CHANGE_MASK) |
-		(new_flags & UPF_CHANGE_MASK);
-	port->custom_divisor   = new_serial.custom_divisor;
-	state->close_delay     = new_serial.close_delay;
-	state->closing_wait    = closing_wait;
-	port->fifosize         = new_serial.xmit_fifo_size;
-	if (state->info->tty)
-		state->info->tty->low_latency =
-			(port->flags & UPF_LOW_LATENCY) ? 1 : 0;
-
-check_and_exit:
-	retval = 0;
-	if (port->type == PORT_UNKNOWN)
-		goto exit;
-	if (state->info->flags & UIF_INITIALIZED) {
-		if (((old_flags ^ port->flags) & UPF_SPD_MASK) ||
-				old_custom_divisor != port->custom_divisor) {
-			if (port->flags & UPF_SPD_MASK) {
-				printk(KERN_NOTICE
-						"%s sets custom speed on ttyMP%d. This "
-						"is deprecated.\n", current->comm,
-						port->line);
-			}
-			mp_change_speed(state, NULL);
-		}
-	} else
-		retval = mp_startup(state, 1);
-exit:
-	MP_STATE_UNLOCK(state);
-	return retval;
-}
-
-
-static int mp_get_lsr_info(struct sb_uart_state *state, unsigned int *value)
-{
-	struct sb_uart_port *port = state->port;
-	unsigned int result;
-
-	result = port->ops->tx_empty(port);
-
-	if (port->x_char ||
-			((uart_circ_chars_pending(&state->info->xmit) > 0) &&
-				!state->info->tty->stopped && !state->info->tty->hw_stopped))
-		result &= ~TIOCSER_TEMT;
-
-	return put_user(result, value);
-}
-
-static int mp_tiocmget(struct tty_struct *tty)
-{
-	struct sb_uart_state *state = tty->driver_data;
-	struct sb_uart_port *port = state->port;
-	int result = -EIO;
-
-	MP_STATE_LOCK(state);
-	if (!(tty->flags & (1 << TTY_IO_ERROR))) {
-		result = port->mctrl;
-		spin_lock_irq(&port->lock);
-		result |= port->ops->get_mctrl(port);
-		spin_unlock_irq(&port->lock);
-	}
-	MP_STATE_UNLOCK(state);
-	return result;
-}
-
-static int mp_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear)
-{
-	struct sb_uart_state *state = tty->driver_data;
-	struct sb_uart_port *port = state->port;
-	int ret = -EIO;
-
-
-	MP_STATE_LOCK(state);
-	if (!(tty->flags & (1 << TTY_IO_ERROR))) {
-		mp_update_mctrl(port, set, clear);
-		ret = 0;
-	}
-	MP_STATE_UNLOCK(state);
-
-	return ret;
-}
-
-static int mp_break_ctl(struct tty_struct *tty, int break_state)
-{
-	struct sb_uart_state *state = tty->driver_data;
-	struct sb_uart_port *port = state->port;
-
-	MP_STATE_LOCK(state);
-
-	if (port->type != PORT_UNKNOWN)
-		port->ops->break_ctl(port, break_state);
-
-	MP_STATE_UNLOCK(state);
-	return 0;
-}
-
-static int mp_do_autoconfig(struct sb_uart_state *state)
-{
-	struct sb_uart_port *port = state->port;
-	int flags, ret;
-
-	if (!capable(CAP_SYS_ADMIN))
-		return -EPERM;
-
-	if (mutex_lock_interruptible(&state->mutex))
-		return -ERESTARTSYS;
-	ret = -EBUSY;
-	if (uart_users(state) == 1) {
-		mp_shutdown(state);
-
-		if (port->type != PORT_UNKNOWN)
-			port->ops->release_port(port);
-
-		flags = UART_CONFIG_TYPE;
-		if (port->flags & UPF_AUTO_IRQ)
-			flags |= UART_CONFIG_IRQ;
-
-		port->ops->config_port(port, flags);
-
-		ret = mp_startup(state, 1);
-	}
-	MP_STATE_UNLOCK(state);
-	return ret;
-}
-
-static int mp_wait_modem_status(struct sb_uart_state *state, unsigned long arg)
-{
-	struct sb_uart_port *port = state->port;
-	DECLARE_WAITQUEUE(wait, current);
-	struct sb_uart_icount cprev, cnow;
-	int ret;
-
-	spin_lock_irq(&port->lock);
-	memcpy(&cprev, &port->icount, sizeof(struct sb_uart_icount));
-
-	port->ops->enable_ms(port);
-	spin_unlock_irq(&port->lock);
-
-	add_wait_queue(&state->info->delta_msr_wait, &wait);
-	for (;;) {
-		spin_lock_irq(&port->lock);
-		memcpy(&cnow, &port->icount, sizeof(struct sb_uart_icount));
-		spin_unlock_irq(&port->lock);
-
-		set_current_state(TASK_INTERRUPTIBLE);
-
-		if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
-				((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
-				((arg & TIOCM_CD)  && (cnow.dcd != cprev.dcd)) ||
-				((arg & TIOCM_CTS) && (cnow.cts != cprev.cts))) {
-			ret = 0;
-			break;
-		}
-
-		schedule();
-
-		if (signal_pending(current)) {
-			ret = -ERESTARTSYS;
-			break;
-		}
-
-		cprev = cnow;
-	}
-
-	current->state = TASK_RUNNING;
-	remove_wait_queue(&state->info->delta_msr_wait, &wait);
-
-	return ret;
-}
-
-static int mp_get_count(struct sb_uart_state *state, struct serial_icounter_struct *icnt)
-{
-	struct serial_icounter_struct icount = {};
-	struct sb_uart_icount cnow;
-	struct sb_uart_port *port = state->port;
-
-	spin_lock_irq(&port->lock);
-	memcpy(&cnow, &port->icount, sizeof(struct sb_uart_icount));
-	spin_unlock_irq(&port->lock);
-
-	icount.cts         = cnow.cts;
-	icount.dsr         = cnow.dsr;
-	icount.rng         = cnow.rng;
-	icount.dcd         = cnow.dcd;
-	icount.rx          = cnow.rx;
-	icount.tx          = cnow.tx;
-	icount.frame       = cnow.frame;
-	icount.overrun     = cnow.overrun;
-	icount.parity      = cnow.parity;
-	icount.brk         = cnow.brk;
-	icount.buf_overrun = cnow.buf_overrun;
-
-	return copy_to_user(icnt, &icount, sizeof(icount)) ? -EFAULT : 0;
-}
-
-static int mp_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg)
-{
-	struct sb_uart_state *state = tty->driver_data;
-	struct mp_port *info = (struct mp_port *)state->port;
-	int ret = -ENOIOCTLCMD;
-
-
-	switch (cmd) {
-		case TIOCSMULTIDROP:
-			/* set multi-drop mode enable or disable, and default operation mode is H/W mode */
-			if (info->port.type == PORT_16C105XA)
-			{
-				//arg &= ~0x6;
-				//state->port->mdmode = 0;
-				return set_multidrop_mode((struct sb_uart_port *)info, (unsigned int)arg);
-			}
-			ret = -ENOTSUPP;
-			break;
-		case GETDEEPFIFO:
-			ret = get_deep_fifo(state->port);
-			return ret;
-		case SETDEEPFIFO:
-			ret = set_deep_fifo(state->port,arg);
-			deep[state->port->line] = arg;
-			return ret;
-		case SETTTR:
-			if (info->port.type == PORT_16C105X || info->port.type == PORT_16C105XA){
-				ret = sb1054_set_register(state->port,PAGE_4,SB105X_TTR,arg);
-				ttr[state->port->line] = arg;
-			}
-			return ret;
-		case SETRTR:
-			if (info->port.type == PORT_16C105X || info->port.type == PORT_16C105XA){
-				ret = sb1054_set_register(state->port,PAGE_4,SB105X_RTR,arg);
-				rtr[state->port->line] = arg;
-			}
-			return ret;
-		case GETTTR:
-			if (info->port.type == PORT_16C105X || info->port.type == PORT_16C105XA){
-				ret = sb1054_get_register(state->port,PAGE_4,SB105X_TTR);
-			}
-			return ret;
-		case GETRTR:
-			if (info->port.type == PORT_16C105X || info->port.type == PORT_16C105XA){
-				ret = sb1054_get_register(state->port,PAGE_4,SB105X_RTR);
-			}
-			return ret;
-
-		case SETFCR:
-			if (info->port.type == PORT_16C105X || info->port.type == PORT_16C105XA){
-				ret = sb1054_set_register(state->port,PAGE_1,SB105X_FCR,arg);
-			}
-			else{
-				serial_out(info,2,arg);
-			}
-
-			return ret;
-		case TIOCSMDADDR:
-			/* set multi-drop address */
-			if (info->port.type == PORT_16C105XA)
-			{
-				state->port->mdmode |= MDMODE_ADDR;
-				return set_multidrop_addr((struct sb_uart_port *)info, (unsigned int)arg);
-			}
-			ret = -ENOTSUPP;
-			break;
-
-		case TIOCGMDADDR:
-			/* set multi-drop address */
-			if ((info->port.type == PORT_16C105XA) && (state->port->mdmode & MDMODE_ADDR))
-			{
-				return get_multidrop_addr((struct sb_uart_port *)info);
-			}
-			ret = -ENOTSUPP;
-			break;
-
-		case TIOCSENDADDR:
-			/* send address in multi-drop mode */
-			if ((info->port.type == PORT_16C105XA) 
-					&& (state->port->mdmode & (MDMODE_ENABLE)))
-			{
-				if (mp_chars_in_buffer(tty) > 0)
-				{
-					tty_wait_until_sent(tty, 0);
-				}
-				//while ((serial_in(info, UART_LSR) & 0x60) != 0x60);
-				//while (sb1054_get_register(state->port, PAGE_2, SB105X_TFCR) != 0);
-				while ((serial_in(info, UART_LSR) & 0x60) != 0x60);
-				serial_out(info, UART_SCR, (int)arg);
-			}
-			break;
-
-		case TIOCGSERIAL:
-			ret = mp_get_info(state, (struct serial_struct *)arg);
-			break;
-
-		case TIOCSSERIAL:
-			ret = mp_set_info(state, (struct serial_struct *)arg);
-			break;
-
-		case TIOCSERCONFIG:
-			ret = mp_do_autoconfig(state);
-			break;
-
-		case TIOCSERGWILD: /* obsolete */
-		case TIOCSERSWILD: /* obsolete */
-			ret = 0;
-			break;
-			/* for Multiport */
-		case TIOCGNUMOFPORT: /* Get number of ports */
-			return NR_PORTS;
-		case TIOCGGETDEVID:
-			return mp_devs[arg].device_id;
-		case TIOCGGETREV:
-			return mp_devs[arg].revision;
-		case TIOCGGETNRPORTS:
-			return mp_devs[arg].nr_ports;
-		case TIOCGGETBDNO:
-			return NR_BOARD;
-		case TIOCGGETINTERFACE:
-			if (mp_devs[arg].revision == 0xc0)
-			{
-				/* for SB16C1053APCI */
-				return (sb1053a_get_interface(info, info->port.line));
-			}
-			else
-			{
-				return (inb(mp_devs[arg].option_reg_addr+MP_OPTR_IIR0+(state->port->line/8)));
-			}
-		case TIOCGGETPORTTYPE:
-			ret = get_device_type(arg);
-			return ret;
-		case TIOCSMULTIECHO: /* set to multi-drop mode(RS422) or echo mode(RS485)*/
-			outb( ( inb(info->interface_config_addr) & ~0x03 ) | 0x01 ,  
-					info->interface_config_addr);
-			return 0;
-		case TIOCSPTPNOECHO: /* set to multi-drop mode(RS422) or echo mode(RS485) */
-			outb( ( inb(info->interface_config_addr) & ~0x03 )  ,             
-					info->interface_config_addr);
-			return 0;
-	}
-
-	if (ret != -ENOIOCTLCMD)
-		goto out;
-
-	if (tty->flags & (1 << TTY_IO_ERROR)) {
-		ret = -EIO;
-		goto out;
-	}
-
-	switch (cmd) {
-		case TIOCMIWAIT:
-			ret = mp_wait_modem_status(state, arg);
-			break;
-
-		case TIOCGICOUNT:
-			ret = mp_get_count(state, (struct serial_icounter_struct *)arg);
-			break;
-	}
-
-	if (ret != -ENOIOCTLCMD)
-		goto out;
-
-	MP_STATE_LOCK(state);
-	switch (cmd) {
-		case TIOCSERGETLSR: /* Get line status register */
-			ret = mp_get_lsr_info(state, (unsigned int *)arg);
-			break;
-
-		default: {
-					struct sb_uart_port *port = state->port;
-					if (port->ops->ioctl)
-						ret = port->ops->ioctl(port, cmd, arg);
-					break;
-				}
-	}
-
-	MP_STATE_UNLOCK(state);
-out:
-	return ret;
-}
-
-static void mp_set_termios(struct tty_struct *tty, struct MP_TERMIOS *old_termios)
-{
-	struct sb_uart_state *state = tty->driver_data;
-	unsigned long flags;
-	unsigned int cflag = tty->termios.c_cflag;
-
-#define RELEVANT_IFLAG(iflag)	((iflag) & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
-
-	if ((cflag ^ old_termios->c_cflag) == 0 &&
-			RELEVANT_IFLAG(tty->termios.c_iflag ^ old_termios->c_iflag) == 0)
-		return;
-
-	mp_change_speed(state, old_termios);
-
-	if ((old_termios->c_cflag & CBAUD) && !(cflag & CBAUD))
-		uart_clear_mctrl(state->port, TIOCM_RTS | TIOCM_DTR);
-
-	if (!(old_termios->c_cflag & CBAUD) && (cflag & CBAUD)) {
-		unsigned int mask = TIOCM_DTR;
-		if (!(cflag & CRTSCTS) ||
-				!test_bit(TTY_THROTTLED, &tty->flags))
-			mask |= TIOCM_RTS;
-		uart_set_mctrl(state->port, mask);
-	}
-
-	if ((old_termios->c_cflag & CRTSCTS) && !(cflag & CRTSCTS)) {
-		spin_lock_irqsave(&state->port->lock, flags);
-		tty->hw_stopped = 0;
-		__mp_start(tty);
-		spin_unlock_irqrestore(&state->port->lock, flags);
-	}
-
-	if (!(old_termios->c_cflag & CRTSCTS) && (cflag & CRTSCTS)) {
-		spin_lock_irqsave(&state->port->lock, flags);
-		if (!(state->port->ops->get_mctrl(state->port) & TIOCM_CTS)) {
-			tty->hw_stopped = 1;
-			state->port->ops->stop_tx(state->port);
-		}
-		spin_unlock_irqrestore(&state->port->lock, flags);
-	}
-}
-
-static void mp_close(struct tty_struct *tty, struct file *filp)
-{
-	struct sb_uart_state *state = tty->driver_data;
-	struct sb_uart_port *port;
-
-	printk("mp_close!\n");
-	if (!state || !state->port)
-		return;
-
-	port = state->port;
-
-	printk("close1 %d\n", __LINE__);
-	MP_STATE_LOCK(state);
-
-	printk("close2 %d\n", __LINE__);
-	if (tty_hung_up_p(filp))
-		goto done;
-
-	printk("close3 %d\n", __LINE__);
-	if ((tty->count == 1) && (state->count != 1)) {
-		printk("mp_close: bad serial port count; tty->count is 1, "
-				"state->count is %d\n", state->count);
-		state->count = 1;
-	}
-	printk("close4 %d\n", __LINE__);
-	if (--state->count < 0) {
-		printk("rs_close: bad serial port count for ttyMP%d: %d\n",
-				port->line, state->count);
-		state->count = 0;
-	}
-	if (state->count)
-		goto done;
-
-	tty->closing = 1;
-
-	printk("close5 %d\n", __LINE__);
-	if (state->closing_wait != USF_CLOSING_WAIT_NONE)
-		tty_wait_until_sent(tty, state->closing_wait);
-
-	printk("close6 %d\n", __LINE__);
-	if (state->info->flags & UIF_INITIALIZED) {
-		unsigned long flags;
-		spin_lock_irqsave(&port->lock, flags);
-		port->ops->stop_rx(port);
-		spin_unlock_irqrestore(&port->lock, flags);
-		mp_wait_until_sent(tty, port->timeout);
-	}
-	printk("close7 %d\n", __LINE__);
-
-	mp_shutdown(state);
-	printk("close8 %d\n", __LINE__);
-	mp_flush_buffer(tty);
-	tty_ldisc_flush(tty);
-	tty->closing = 0;
-	state->info->tty = NULL;
-	if (state->info->blocked_open) 
-	{
-		if (state->close_delay)
-		{
-			set_current_state(TASK_INTERRUPTIBLE);
-			schedule_timeout(state->close_delay);
-		}
-	}
-	else
-	{
-		mp_change_pm(state, 3);
-	}
-	printk("close8 %d\n", __LINE__);
-
-	state->info->flags &= ~UIF_NORMAL_ACTIVE;
-	wake_up_interruptible(&state->info->open_wait);
-
-done:
-	printk("close done\n");
-	MP_STATE_UNLOCK(state);
-	module_put(THIS_MODULE);
-}
-
-static void mp_wait_until_sent(struct tty_struct *tty, int timeout)
-{
-	struct sb_uart_state *state = tty->driver_data;
-	struct sb_uart_port *port = state->port;
-	unsigned long char_time, expire;
-
-	if (port->type == PORT_UNKNOWN || port->fifosize == 0)
-		return;
-
-	char_time = (port->timeout - HZ/50) / port->fifosize;
-	char_time = char_time / 5;
-	if (char_time == 0)
-		char_time = 1;
-	if (timeout && timeout < char_time)
-		char_time = timeout;
-
-	if (timeout == 0 || timeout > 2 * port->timeout)
-		timeout = 2 * port->timeout;
-
-	expire = jiffies + timeout;
-
-	while (!port->ops->tx_empty(port)) {
-		set_current_state(TASK_INTERRUPTIBLE);
-		schedule_timeout(char_time);
-		if (signal_pending(current))
-			break;
-		if (time_after(jiffies, expire))
-			break;
-	}
-	set_current_state(TASK_RUNNING); /* might not be needed */
-}
-
-static void mp_hangup(struct tty_struct *tty)
-{
-	struct sb_uart_state *state = tty->driver_data;
-
-	MP_STATE_LOCK(state);
-	if (state->info && state->info->flags & UIF_NORMAL_ACTIVE) {
-		mp_flush_buffer(tty);
-		mp_shutdown(state);
-		state->count = 0;
-		state->info->flags &= ~UIF_NORMAL_ACTIVE;
-		state->info->tty = NULL;
-		wake_up_interruptible(&state->info->open_wait);
-		wake_up_interruptible(&state->info->delta_msr_wait);
-	}
-	MP_STATE_UNLOCK(state);
-}
-
-static void mp_update_termios(struct sb_uart_state *state)
-{
-	struct tty_struct *tty = state->info->tty;
-	struct sb_uart_port *port = state->port;
-
-	if (!(tty->flags & (1 << TTY_IO_ERROR))) {
-		mp_change_speed(state, NULL);
-
-		if (tty->termios.c_cflag & CBAUD)
-			uart_set_mctrl(port, TIOCM_DTR | TIOCM_RTS);
-	}
-}
-
-static int mp_block_til_ready(struct file *filp, struct sb_uart_state *state)
-{
-	DECLARE_WAITQUEUE(wait, current);
-	struct sb_uart_info *info = state->info;
-	struct sb_uart_port *port = state->port;
-	unsigned int mctrl;
-
-	info->blocked_open++;
-	state->count--;
-
-	add_wait_queue(&info->open_wait, &wait);
-	while (1) {
-		set_current_state(TASK_INTERRUPTIBLE);
-
-		if (tty_hung_up_p(filp) || info->tty == NULL)
-			break;
-
-		if (!(info->flags & UIF_INITIALIZED))
-			break;
-
-		if ((filp->f_flags & O_NONBLOCK) ||
-				(info->tty->termios.c_cflag & CLOCAL) ||
-				(info->tty->flags & (1 << TTY_IO_ERROR))) {
-			break;
-		}
-
-		if (info->tty->termios.c_cflag & CBAUD)
-			uart_set_mctrl(port, TIOCM_DTR);
-
-		spin_lock_irq(&port->lock);
-		port->ops->enable_ms(port);
-		mctrl = port->ops->get_mctrl(port);
-		spin_unlock_irq(&port->lock);
-		if (mctrl & TIOCM_CAR)
-			break;
-
-		MP_STATE_UNLOCK(state);
-		schedule();
-		MP_STATE_LOCK(state);
-
-		if (signal_pending(current))
-			break;
-	}
-	set_current_state(TASK_RUNNING);
-	remove_wait_queue(&info->open_wait, &wait);
-
-	state->count++;
-	info->blocked_open--;
-
-	if (signal_pending(current))
-		return -ERESTARTSYS;
-
-	if (!info->tty || tty_hung_up_p(filp))
-		return -EAGAIN;
-
-	return 0;
-}
-
-static struct sb_uart_state *uart_get(struct uart_driver *drv, int line)
-{
-	struct sb_uart_state *state;
-
-	MP_MUTEX_LOCK(mp_mutex);
-	state = drv->state + line;
-	if (mutex_lock_interruptible(&state->mutex)) {
-		state = ERR_PTR(-ERESTARTSYS);
-		goto out;
-	}
-	state->count++;
-	if (!state->port) {
-		state->count--;
-		MP_STATE_UNLOCK(state);
-		state = ERR_PTR(-ENXIO);
-		goto out;
-	}
-
-	if (!state->info) {
-		state->info = kmalloc(sizeof(struct sb_uart_info), GFP_KERNEL);
-		if (state->info) {
-			memset(state->info, 0, sizeof(struct sb_uart_info));
-			init_waitqueue_head(&state->info->open_wait);
-			init_waitqueue_head(&state->info->delta_msr_wait);
-
-			state->port->info = state->info;
-
-			tasklet_init(&state->info->tlet, mp_tasklet_action,
-					(unsigned long)state);
-		} else {
-			state->count--;
-			MP_STATE_UNLOCK(state);
-			state = ERR_PTR(-ENOMEM);
-		}
-	}
-
-out:
-	MP_MUTEX_UNLOCK(mp_mutex);
-	return state;
-}
-
-static int mp_open(struct tty_struct *tty, struct file *filp)
-{
-	struct uart_driver *drv = (struct uart_driver *)tty->driver->driver_state;
-	struct sb_uart_state *state;
-	int retval;
-	int  line = tty->index;
-	struct mp_port *mtpt;
-
-	retval = -ENODEV;
-	if (line >= tty->driver->num)
-		goto fail;
-
-	state = uart_get(drv, line);
-
-	if (IS_ERR(state)) {
-		retval = PTR_ERR(state);
-		goto fail;
-	}
-
-	mtpt  = (struct mp_port *)state->port;
-
-	tty->driver_data = state;
-	tty->low_latency = (state->port->flags & UPF_LOW_LATENCY) ? 1 : 0;
-	tty->alt_speed = 0;
-	state->info->tty = tty;
-
-	if (tty_hung_up_p(filp)) {
-		retval = -EAGAIN;
-		state->count--;
-		MP_STATE_UNLOCK(state);
-		goto fail;
-	}
-
-	if (state->count == 1)
-		mp_change_pm(state, 0);
-
-	retval = mp_startup(state, 0);
-
-	if (retval == 0)
-		retval = mp_block_til_ready(filp, state);
-	MP_STATE_UNLOCK(state);
-
-	if (retval == 0 && !(state->info->flags & UIF_NORMAL_ACTIVE)) {
-		state->info->flags |= UIF_NORMAL_ACTIVE;
-
-		mp_update_termios(state);
-	}
-
-	uart_clear_mctrl(state->port, TIOCM_RTS);
-	try_module_get(THIS_MODULE);
-fail:
-	return retval;
-}
-
-
-static const char *mp_type(struct sb_uart_port *port)
-{
-	const char *str = NULL;
-
-	if (port->ops->type)
-		str = port->ops->type(port);
-
-	if (!str)
-		str = "unknown";
-
-	return str;
-}
-
-static void mp_change_pm(struct sb_uart_state *state, int pm_state)
-{
-	struct sb_uart_port *port = state->port;
-	if (port->ops->pm)
-		port->ops->pm(port, pm_state, state->pm_state);
-	state->pm_state = pm_state;
-}
-
-static inline void mp_report_port(struct uart_driver *drv, struct sb_uart_port *port)
-{
-	char address[64];
-
-	switch (port->iotype) {
-		case UPIO_PORT:
-			snprintf(address, sizeof(address),"I/O 0x%x", port->iobase);
-			break;
-		case UPIO_HUB6:
-			snprintf(address, sizeof(address),"I/O 0x%x offset 0x%x", port->iobase, port->hub6);
-			break;
-		case UPIO_MEM:
-			snprintf(address, sizeof(address),"MMIO 0x%lx", port->mapbase);
-			break;
-		default:
-			snprintf(address, sizeof(address),"*unknown*" );
-			strlcpy(address, "*unknown*", sizeof(address));
-			break;
-	}
-
-	printk( "%s%d at %s (irq = %d) is a %s\n",
-			drv->dev_name, port->line, address, port->irq, mp_type(port));
-
-}
-
-static void mp_configure_port(struct uart_driver *drv, struct sb_uart_state *state, struct sb_uart_port *port)
-{
-	unsigned int flags;
-
-
-	if (!port->iobase && !port->mapbase && !port->membase)
-	{
-		DPRINTK("%s error \n",__FUNCTION__);
-		return;
-	}
-	flags = UART_CONFIG_TYPE;
-	if (port->flags & UPF_AUTO_IRQ)
-		flags |= UART_CONFIG_IRQ;
-	if (port->flags & UPF_BOOT_AUTOCONF) {
-		port->type = PORT_UNKNOWN;
-		port->ops->config_port(port, flags);
-	}
-
-	if (port->type != PORT_UNKNOWN) {
-		unsigned long flags;
-
-		mp_report_port(drv, port);
-
-		spin_lock_irqsave(&port->lock, flags);
-		port->ops->set_mctrl(port, 0);
-		spin_unlock_irqrestore(&port->lock, flags);
-
-		mp_change_pm(state, 3);
-	}
-}
-
-static void mp_unconfigure_port(struct uart_driver *drv, struct sb_uart_state *state)
-{
-	struct sb_uart_port *port = state->port;
-	struct sb_uart_info *info = state->info;
-
-	if (info && info->tty)
-		tty_hangup(info->tty);
-
-	MP_STATE_LOCK(state);
-
-	state->info = NULL;
-
-	if (port->type != PORT_UNKNOWN)
-		port->ops->release_port(port);
-
-	port->type = PORT_UNKNOWN;
-
-	if (info) {
-		tasklet_kill(&info->tlet);
-		kfree(info);
-	}
-
-	MP_STATE_UNLOCK(state);
-}
-static struct tty_operations mp_ops = {
-	.open		= mp_open,
-	.close		= mp_close,
-	.write		= mp_write,
-	.put_char	= mp_put_char,
-	.flush_chars	= mp_put_chars,
-	.write_room	= mp_write_room,
-	.chars_in_buffer= mp_chars_in_buffer,
-	.flush_buffer	= mp_flush_buffer,
-	.ioctl		= mp_ioctl,
-	.throttle	= mp_throttle,
-	.unthrottle	= mp_unthrottle,
-	.send_xchar	= mp_send_xchar,
-	.set_termios	= mp_set_termios,
-	.stop		= mp_stop,
-	.start		= mp_start,
-	.hangup		= mp_hangup,
-	.break_ctl	= mp_break_ctl,
-	.wait_until_sent= mp_wait_until_sent,
-#ifdef CONFIG_PROC_FS
-	.proc_fops	= NULL,
-#endif
-	.tiocmget	= mp_tiocmget,
-	.tiocmset	= mp_tiocmset,
-};
-
-static int mp_register_driver(struct uart_driver *drv)
-{
-	struct tty_driver *normal = NULL;
-	int i, retval;
-
-	drv->state = kmalloc(sizeof(struct sb_uart_state) * drv->nr, GFP_KERNEL);
-	retval = -ENOMEM;
-	if (!drv->state)
-	{
-		printk("SB PCI Error: Kernel memory allocation error!\n");
-		goto out;
-	}
-	memset(drv->state, 0, sizeof(struct sb_uart_state) * drv->nr);
-
-	normal = alloc_tty_driver(drv->nr);
-	if (!normal)
-	{
-		printk("SB PCI Error: tty allocation error!\n");
-		goto out;
-	}
-
-	drv->tty_driver = normal;
-
-	normal->owner           = drv->owner;
-	normal->magic		= TTY_DRIVER_MAGIC;
-	normal->driver_name     = drv->driver_name;
-	normal->name		= drv->dev_name;
-	normal->major		= drv->major;
-	normal->minor_start	= drv->minor;
-
-	normal->num		= MAX_MP_PORT ; 
-
-	normal->type		= TTY_DRIVER_TYPE_SERIAL;
-	normal->subtype		= SERIAL_TYPE_NORMAL;
-	normal->init_termios	= tty_std_termios;
-	normal->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
-	normal->flags		= TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
-	normal->driver_state    = drv;
-
-	tty_set_operations(normal, &mp_ops);
-
-for (i = 0; i < drv->nr; i++) {
-	struct sb_uart_state *state = drv->state + i;
-
-	state->close_delay     = 500;   
-	state->closing_wait    = 30000; 
-
-	mutex_init(&state->mutex);
-	}
-
-	retval = tty_register_driver(normal);
-out:
-	if (retval < 0) {
-		printk("Register tty driver Fail!\n");
-		put_tty_driver(normal);
-		kfree(drv->state);
-	}
-
-	return retval;
-}
-
-void mp_unregister_driver(struct uart_driver *drv)
-{
-    struct tty_driver *normal = NULL;
-
-    normal = drv->tty_driver;
-
-    if (!normal)
-    {
-        return;
-    }
-
-    tty_unregister_driver(normal);
-    put_tty_driver(normal);
-    drv->tty_driver = NULL;
-
-
-    kfree(drv->state);
-
-}
-
-static int mp_add_one_port(struct uart_driver *drv, struct sb_uart_port *port)
-{
-	struct sb_uart_state *state;
-	int ret = 0;
-
-
-	if (port->line >= drv->nr)
-		return -EINVAL;
-
-	state = drv->state + port->line;
-
-	MP_MUTEX_LOCK(mp_mutex);
-	if (state->port) {
-		ret = -EINVAL;
-		goto out;
-	}
-
-	state->port = port;
-
-	spin_lock_init(&port->lock);
-	port->cons = drv->cons;
-	port->info = state->info;
-
-	mp_configure_port(drv, state, port);
-
-	tty_register_device(drv->tty_driver, port->line, port->dev);
-
-out:
-	MP_MUTEX_UNLOCK(mp_mutex);
-
-
-	return ret;
-}
-
-static int mp_remove_one_port(struct uart_driver *drv, struct sb_uart_port *port)
-{
-	struct sb_uart_state *state = drv->state + port->line;
-
-	if (state->port != port)
-		printk(KERN_ALERT "Removing wrong port: %p != %p\n",
-				state->port, port);
-
-	MP_MUTEX_LOCK(mp_mutex);
-
-	tty_unregister_device(drv->tty_driver, port->line);
-
-	mp_unconfigure_port(drv, state);
-	state->port = NULL;
-	MP_MUTEX_UNLOCK(mp_mutex);
-
-	return 0;
-}
-
-static void autoconfig(struct mp_port *mtpt, unsigned int probeflags)
-{
-	unsigned char status1, scratch, scratch2, scratch3;
-	unsigned char save_lcr, save_mcr;
-	unsigned long flags;
-
-	unsigned char u_type;
-	unsigned char b_ret = 0;
-
-	if (!mtpt->port.iobase && !mtpt->port.mapbase && !mtpt->port.membase)
-		return;
-
-	DEBUG_AUTOCONF("ttyMP%d: autoconf (0x%04x, 0x%p): ",
-			mtpt->port.line, mtpt->port.iobase, mtpt->port.membase);
-
-	spin_lock_irqsave(&mtpt->port.lock, flags);
-
-	if (!(mtpt->port.flags & UPF_BUGGY_UART)) {
-		scratch = serial_inp(mtpt, UART_IER);
-		serial_outp(mtpt, UART_IER, 0);
-#ifdef __i386__
-		outb(0xff, 0x080);
-#endif
-		scratch2 = serial_inp(mtpt, UART_IER) & 0x0f;
-		serial_outp(mtpt, UART_IER, 0x0F);
-#ifdef __i386__
-		outb(0, 0x080);
-#endif
-		scratch3 = serial_inp(mtpt, UART_IER) & 0x0F;
-		serial_outp(mtpt, UART_IER, scratch);
-		if (scratch2 != 0 || scratch3 != 0x0F) {
-			DEBUG_AUTOCONF("IER test failed (%02x, %02x) ",
-					scratch2, scratch3);
-			goto out;
-		}
-	}
-
-	save_mcr = serial_in(mtpt, UART_MCR);
-	save_lcr = serial_in(mtpt, UART_LCR);
-
-	if (!(mtpt->port.flags & UPF_SKIP_TEST)) {
-		serial_outp(mtpt, UART_MCR, UART_MCR_LOOP | 0x0A);
-		status1 = serial_inp(mtpt, UART_MSR) & 0xF0;
-		serial_outp(mtpt, UART_MCR, save_mcr);
-		if (status1 != 0x90) {
-			DEBUG_AUTOCONF("LOOP test failed (%02x) ",
-					status1);
-			goto out;
-		}
-	}
-
-	serial_outp(mtpt, UART_LCR, 0xBF);
-	serial_outp(mtpt, UART_EFR, 0);
-	serial_outp(mtpt, UART_LCR, 0);
-
-	serial_outp(mtpt, UART_FCR, UART_FCR_ENABLE_FIFO);
-	scratch = serial_in(mtpt, UART_IIR) >> 6;
-
-	DEBUG_AUTOCONF("iir=%d ", scratch);
-	if(mtpt->device->nr_ports >= 8)
-		b_ret = read_option_register(mtpt,(MP_OPTR_DIR0 + ((mtpt->port.line)/8)));
-	else	
-		b_ret = read_option_register(mtpt,MP_OPTR_DIR0);
-	u_type = (b_ret & 0xf0) >> 4;
-	if(mtpt->port.type == PORT_UNKNOWN )
-	{
-		switch (u_type)
-		{
-			case DIR_UART_16C550:
-				mtpt->port.type = PORT_16C55X;
-				break;
-			case DIR_UART_16C1050:
-				mtpt->port.type = PORT_16C105X;
-				break;
-			case DIR_UART_16C1050A:
-				if (mtpt->port.line < 2)
-				{
-					mtpt->port.type = PORT_16C105XA;
-				}
-				else
-				{
-					if (mtpt->device->device_id & 0x50)
-					{
-						mtpt->port.type = PORT_16C55X;
-					}
-					else
-					{
-						mtpt->port.type = PORT_16C105X;
-					}
-				}
-				break;
-			default:	
-				mtpt->port.type = PORT_UNKNOWN;
-				break;
-		}
-	}
-
-	if(mtpt->port.type == PORT_UNKNOWN )
-	{
-printk("unknow2\n");
-		switch (scratch) {
-			case 0:
-			case 1:
-				mtpt->port.type = PORT_UNKNOWN;
-				break;
-			case 2:
-			case 3:
-				mtpt->port.type = PORT_16C55X;
-				break;
-		}
-	}
-
-	serial_outp(mtpt, UART_LCR, save_lcr);
-
-	mtpt->port.fifosize = uart_config[mtpt->port.type].dfl_xmit_fifo_size;
-	mtpt->capabilities = uart_config[mtpt->port.type].flags;
-
-	if (mtpt->port.type == PORT_UNKNOWN)
-		goto out;
-	serial_outp(mtpt, UART_MCR, save_mcr);
-	serial_outp(mtpt, UART_FCR, (UART_FCR_ENABLE_FIFO |
-				UART_FCR_CLEAR_RCVR |
-				UART_FCR_CLEAR_XMIT));
-	serial_outp(mtpt, UART_FCR, 0);
-	(void)serial_in(mtpt, UART_RX);
-	serial_outp(mtpt, UART_IER, 0);
-
-out:
-	spin_unlock_irqrestore(&mtpt->port.lock, flags);
-	DEBUG_AUTOCONF("type=%s\n", uart_config[mtpt->port.type].name);
-}
-
-static void autoconfig_irq(struct mp_port *mtpt)
-{
-	unsigned char save_mcr, save_ier;
-	unsigned long irqs;
-	int irq;
-
-	/* forget possible initially masked and pending IRQ */
-	probe_irq_off(probe_irq_on());
-	save_mcr = serial_inp(mtpt, UART_MCR);
-	save_ier = serial_inp(mtpt, UART_IER);
-	serial_outp(mtpt, UART_MCR, UART_MCR_OUT1 | UART_MCR_OUT2);
-
-	irqs = probe_irq_on();
-	serial_outp(mtpt, UART_MCR, 0);
-	serial_outp(mtpt, UART_MCR,
-		UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2);
-
-	serial_outp(mtpt, UART_IER, 0x0f);    /* enable all intrs */
-	(void)serial_inp(mtpt, UART_LSR);
-	(void)serial_inp(mtpt, UART_RX);
-	(void)serial_inp(mtpt, UART_IIR);
-	(void)serial_inp(mtpt, UART_MSR);
-	serial_outp(mtpt, UART_TX, 0xFF);
-	irq = probe_irq_off(irqs);
-
-	serial_outp(mtpt, UART_MCR, save_mcr);
-	serial_outp(mtpt, UART_IER, save_ier);
-
-	mtpt->port.irq = (irq > 0) ? irq : 0;
-}
-
-static void multi_stop_tx(struct sb_uart_port *port)
-{
-	struct mp_port *mtpt = (struct mp_port *)port;
-
-	if (mtpt->ier & UART_IER_THRI) {
-		mtpt->ier &= ~UART_IER_THRI;
-		serial_out(mtpt, UART_IER, mtpt->ier);
-	}
-
-	tasklet_schedule(&port->info->tlet);
-}
-
-static void multi_start_tx(struct sb_uart_port *port)
-{
-	struct mp_port *mtpt = (struct mp_port *)port;
-
-	if (!(mtpt->ier & UART_IER_THRI)) {
-		mtpt->ier |= UART_IER_THRI;
-		serial_out(mtpt, UART_IER, mtpt->ier);
-	}
-}
-
-static void multi_stop_rx(struct sb_uart_port *port)
-{
-	struct mp_port *mtpt = (struct mp_port *)port;
-
-	mtpt->ier &= ~UART_IER_RLSI;
-	mtpt->port.read_status_mask &= ~UART_LSR_DR;
-	serial_out(mtpt, UART_IER, mtpt->ier);
-}
-
-static void multi_enable_ms(struct sb_uart_port *port)
-{
-	struct mp_port *mtpt = (struct mp_port *)port;
-
-	mtpt->ier |= UART_IER_MSI;
-	serial_out(mtpt, UART_IER, mtpt->ier);
-}
-
-
-static _INLINE_ void receive_chars(struct mp_port *mtpt, int *status )
-{
-	struct tty_struct *tty = mtpt->port.info->tty;
-	unsigned char lsr = *status;
-	int max_count = 256;
-	unsigned char ch;
-	char flag;
-
-	//lsr &= mtpt->port.read_status_mask;
-
-	do {
-		if ((lsr & UART_LSR_PE) && (mtpt->port.mdmode & MDMODE_ENABLE))
-		{
-			ch = serial_inp(mtpt, UART_RX);
-		}
-		else if (lsr & UART_LSR_SPECIAL) 
-		{
-			flag = 0;
-			ch = serial_inp(mtpt, UART_RX);
-
-			if (lsr & UART_LSR_BI) 
-			{
-
-				mtpt->port.icount.brk++;
-				flag = TTY_BREAK;
-
-				if (sb_uart_handle_break(&mtpt->port))
-					goto ignore_char;
-			} 
-			if (lsr & UART_LSR_PE)
-			{
-				mtpt->port.icount.parity++;
-				flag = TTY_PARITY;
-			}
-			if (lsr & UART_LSR_FE)
-			{
-				mtpt->port.icount.frame++;
-				flag = TTY_FRAME;
-			}
-			if (lsr & UART_LSR_OE)
-			{
-				mtpt->port.icount.overrun++;
-				flag = TTY_OVERRUN;
-			}
-			tty_insert_flip_char(tty, ch, flag);
-		}
-		else
-		{
-			ch = serial_inp(mtpt, UART_RX);
-			tty_insert_flip_char(tty, ch, 0);
-		}
-ignore_char:
-		lsr = serial_inp(mtpt, UART_LSR);
-	} while ((lsr & UART_LSR_DR) && (max_count-- > 0));
-
-	tty_flip_buffer_push(tty);
-}
-
-
-
-
-static _INLINE_ void transmit_chars(struct mp_port *mtpt)
-{
-	struct circ_buf *xmit = &mtpt->port.info->xmit;
-	int count;
-
-	if (mtpt->port.x_char) {
-		serial_outp(mtpt, UART_TX, mtpt->port.x_char);
-		mtpt->port.icount.tx++;
-		mtpt->port.x_char = 0;
-		return;
-	}
-	if (uart_circ_empty(xmit) || uart_tx_stopped(&mtpt->port)) {
-		multi_stop_tx(&mtpt->port);
-		return;
-	}
-
-	count = uart_circ_chars_pending(xmit);
-
-	if(count > mtpt->port.fifosize)
-	{
-		count = mtpt->port.fifosize;
-	}
-
-	printk("[%d] mdmode: %x\n", mtpt->port.line, mtpt->port.mdmode);
-	do {
-#if 0
-		/* check multi-drop mode */
-		if ((mtpt->port.mdmode & (MDMODE_ENABLE | MDMODE_ADDR)) == (MDMODE_ENABLE | MDMODE_ADDR))
-		{
-			printk("send address\n");
-			/* send multi-drop address */
-			serial_out(mtpt, UART_SCR, xmit->buf[xmit->tail]);
-		}
-		else
-#endif
-		{
-			serial_out(mtpt, UART_TX, xmit->buf[xmit->tail]);
-		}
-		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
-		mtpt->port.icount.tx++;
-	} while (--count > 0);
-}
-
-
-
-static _INLINE_ void check_modem_status(struct mp_port *mtpt)
-{
-	int status;
-
-	status = serial_in(mtpt, UART_MSR);
-
-	if ((status & UART_MSR_ANY_DELTA) == 0)
-		return;
-
-	if (status & UART_MSR_TERI)
-		mtpt->port.icount.rng++;
-	if (status & UART_MSR_DDSR)
-		mtpt->port.icount.dsr++;
-	if (status & UART_MSR_DDCD)
-		sb_uart_handle_dcd_change(&mtpt->port, status & UART_MSR_DCD);
-	if (status & UART_MSR_DCTS)
-		sb_uart_handle_cts_change(&mtpt->port, status & UART_MSR_CTS);
-
-	wake_up_interruptible(&mtpt->port.info->delta_msr_wait);
-}
-
-static inline void multi_handle_port(struct mp_port *mtpt)
-{
-	unsigned int status = serial_inp(mtpt, UART_LSR);
-
-	//printk("lsr: %x\n", status);
-
-	if ((status & UART_LSR_DR) || (status & UART_LSR_SPECIAL))
-		receive_chars(mtpt, &status);
-	check_modem_status(mtpt);
-	if (status & UART_LSR_THRE)
-	{
-		if ((mtpt->port.type == PORT_16C105X)
-			|| (mtpt->port.type == PORT_16C105XA))
-			transmit_chars(mtpt);
-		else
-		{
-			if (mtpt->interface >= RS485NE)
-				uart_set_mctrl(&mtpt->port, TIOCM_RTS);
-			
-			transmit_chars(mtpt);
-
-
-			if (mtpt->interface >= RS485NE)
-			{
-				while((status=serial_in(mtpt,UART_LSR) &0x60)!=0x60);
-				uart_clear_mctrl(&mtpt->port, TIOCM_RTS);
-			}
-		}
-	}
-}
-
-
-
-static irqreturn_t multi_interrupt(int irq, void *dev_id)
-{
-	struct irq_info *iinfo = dev_id;
-	struct list_head *lhead, *end = NULL;
-	int pass_counter = 0;
-
-
-	spin_lock(&iinfo->lock);
-
-	lhead = iinfo->head;
-	do {
-		struct mp_port *mtpt;
-		unsigned int iir;
-
-		mtpt = list_entry(lhead, struct mp_port, list);
-		
-		iir = serial_in(mtpt, UART_IIR);
-		printk("interrupt! port %d, iir 0x%x\n", mtpt->port.line, iir); //wlee
-		if (!(iir & UART_IIR_NO_INT)) 
-		{
-			printk("interrupt handle\n");
-			spin_lock(&mtpt->port.lock);
-			multi_handle_port(mtpt);
-			spin_unlock(&mtpt->port.lock);
-
-			end = NULL;
-		} else if (end == NULL)
-			end = lhead;
-
-		lhead = lhead->next;
-		if (lhead == iinfo->head && pass_counter++ > PASS_LIMIT) 
-		{
-			printk(KERN_ERR "multi: too much work for "
-					"irq%d\n", irq);
-			printk( "multi: too much work for "
-					"irq%d\n", irq);
-			break;
-		}
-	} while (lhead != end);
-
-	spin_unlock(&iinfo->lock);
-
-
-        return IRQ_HANDLED;
-}
-
-static void serial_do_unlink(struct irq_info *i, struct mp_port *mtpt)
-{
-	spin_lock_irq(&i->lock);
-
-	if (!list_empty(i->head)) {
-		if (i->head == &mtpt->list)
-			i->head = i->head->next;
-		list_del(&mtpt->list);
-	} else {
-		i->head = NULL;
-	}
-
-	spin_unlock_irq(&i->lock);
-}
-
-static int serial_link_irq_chain(struct mp_port *mtpt)
-{
-	struct irq_info *i = irq_lists + mtpt->port.irq;
-	int ret, irq_flags = mtpt->port.flags & UPF_SHARE_IRQ ? IRQF_SHARED : 0;
-	spin_lock_irq(&i->lock);
-
-	if (i->head) {
-		list_add(&mtpt->list, i->head);
-		spin_unlock_irq(&i->lock);
-
-		ret = 0;
-	} else {
-		INIT_LIST_HEAD(&mtpt->list);
-		i->head = &mtpt->list;
-		spin_unlock_irq(&i->lock);
-
-		ret = request_irq(mtpt->port.irq, multi_interrupt,
-				irq_flags, "serial", i);
-		if (ret < 0)
-			serial_do_unlink(i, mtpt);
-	}
-
-	return ret;
-}
-
-
-
-
-static void serial_unlink_irq_chain(struct mp_port *mtpt)
-{
-	struct irq_info *i = irq_lists + mtpt->port.irq;
-
-	if (list_empty(i->head))
-	{
-		free_irq(mtpt->port.irq, i);
-	}
-	serial_do_unlink(i, mtpt);
-}
-
-static void multi_timeout(unsigned long data)
-{
-	struct mp_port *mtpt = (struct mp_port *)data;
-
-
-	spin_lock(&mtpt->port.lock);
-	multi_handle_port(mtpt);
-	spin_unlock(&mtpt->port.lock);
-
-	mod_timer(&mtpt->timer, jiffies+1 );
-}
-
-static unsigned int multi_tx_empty(struct sb_uart_port *port)
-{
-	struct mp_port *mtpt = (struct mp_port *)port;
-	unsigned long flags;
-	unsigned int ret;
-
-	spin_lock_irqsave(&mtpt->port.lock, flags);
-	ret = serial_in(mtpt, UART_LSR) & UART_LSR_TEMT ? TIOCSER_TEMT : 0;
-	spin_unlock_irqrestore(&mtpt->port.lock, flags);
-
-	return ret;
-}
-
-
-static unsigned int multi_get_mctrl(struct sb_uart_port *port)
-{
-	struct mp_port *mtpt = (struct mp_port *)port;
-	unsigned char status;
-	unsigned int ret;
-
-	status = serial_in(mtpt, UART_MSR);
-
-	ret = 0;
-	if (status & UART_MSR_DCD)
-		ret |= TIOCM_CAR;
-	if (status & UART_MSR_RI)
-		ret |= TIOCM_RNG;
-	if (status & UART_MSR_DSR)
-		ret |= TIOCM_DSR;
-	if (status & UART_MSR_CTS)
-		ret |= TIOCM_CTS;
-	return ret;
-}
-
-static void multi_set_mctrl(struct sb_uart_port *port, unsigned int mctrl)
-{
-	struct mp_port *mtpt = (struct mp_port *)port;
-	unsigned char mcr = 0;
-
-	mctrl &= 0xff;
-
-	if (mctrl & TIOCM_RTS)
-		mcr |= UART_MCR_RTS;
-	if (mctrl & TIOCM_DTR)
-		mcr |= UART_MCR_DTR;
-	if (mctrl & TIOCM_OUT1)
-		mcr |= UART_MCR_OUT1;
-	if (mctrl & TIOCM_OUT2)
-		mcr |= UART_MCR_OUT2;
-	if (mctrl & TIOCM_LOOP)
-		mcr |= UART_MCR_LOOP;
-
-
-	serial_out(mtpt, UART_MCR, mcr);
-}
-
-
-static void multi_break_ctl(struct sb_uart_port *port, int break_state)
-{
-	struct mp_port *mtpt = (struct mp_port *)port;
-	unsigned long flags;
-
-	spin_lock_irqsave(&mtpt->port.lock, flags);
-	if (break_state == -1)
-		mtpt->lcr |= UART_LCR_SBC;
-	else
-		mtpt->lcr &= ~UART_LCR_SBC;
-	serial_out(mtpt, UART_LCR, mtpt->lcr);
-	spin_unlock_irqrestore(&mtpt->port.lock, flags);
-}
-
-
-
-static int multi_startup(struct sb_uart_port *port)
-{
-	struct mp_port *mtpt = (struct mp_port *)port;
-	unsigned long flags;
-	int retval;
-
-	mtpt->capabilities = uart_config[mtpt->port.type].flags;
-	mtpt->mcr = 0;
-
-	if (mtpt->capabilities & UART_CLEAR_FIFO) {
-		serial_outp(mtpt, UART_FCR, UART_FCR_ENABLE_FIFO);
-		serial_outp(mtpt, UART_FCR, UART_FCR_ENABLE_FIFO |
-				UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
-		serial_outp(mtpt, UART_FCR, 0);
-	}
-
-	(void) serial_inp(mtpt, UART_LSR);
-	(void) serial_inp(mtpt, UART_RX);
-	(void) serial_inp(mtpt, UART_IIR);
-	(void) serial_inp(mtpt, UART_MSR);
-	//test-wlee 9-bit disable
-	serial_outp(mtpt, UART_MSR, 0);
-
-
-	if (!(mtpt->port.flags & UPF_BUGGY_UART) &&
-			(serial_inp(mtpt, UART_LSR) == 0xff)) {
-		printk("ttyS%d: LSR safety check engaged!\n", mtpt->port.line);
-		//return -ENODEV;
-	}
-
-	if ((!is_real_interrupt(mtpt->port.irq)) || (mtpt->poll_type==TYPE_POLL)) {
-		unsigned int timeout = mtpt->port.timeout;
-
-		timeout = timeout > 6 ? (timeout / 2 - 2) : 1;
-
-		mtpt->timer.data = (unsigned long)mtpt;
-		mod_timer(&mtpt->timer, jiffies + timeout);
-	} 
-	else 
-	{
-		retval = serial_link_irq_chain(mtpt);
-		if (retval)
-			return retval;
-	}
-
-	serial_outp(mtpt, UART_LCR, UART_LCR_WLEN8);
-
-	spin_lock_irqsave(&mtpt->port.lock, flags);
-	if ((is_real_interrupt(mtpt->port.irq))||(mtpt->poll_type==TYPE_INTERRUPT))
-		mtpt->port.mctrl |= TIOCM_OUT2;
-
-	multi_set_mctrl(&mtpt->port, mtpt->port.mctrl);
-	spin_unlock_irqrestore(&mtpt->port.lock, flags);
-
-	
-	mtpt->ier = UART_IER_RLSI | UART_IER_RDI;
-	serial_outp(mtpt, UART_IER, mtpt->ier);
-
-	(void) serial_inp(mtpt, UART_LSR);
-	(void) serial_inp(mtpt, UART_RX);
-	(void) serial_inp(mtpt, UART_IIR);
-	(void) serial_inp(mtpt, UART_MSR);
-
-	return 0;
-}
-
-
-
-static void multi_shutdown(struct sb_uart_port *port)
-{
-	struct mp_port *mtpt = (struct mp_port *)port;
-	unsigned long flags;
-
-
-	mtpt->ier = 0;
-	serial_outp(mtpt, UART_IER, 0);
-
-	spin_lock_irqsave(&mtpt->port.lock, flags);
-	mtpt->port.mctrl &= ~TIOCM_OUT2;
-
-	multi_set_mctrl(&mtpt->port, mtpt->port.mctrl);
-	spin_unlock_irqrestore(&mtpt->port.lock, flags);
-
-	serial_out(mtpt, UART_LCR, serial_inp(mtpt, UART_LCR) & ~UART_LCR_SBC);
-	serial_outp(mtpt, UART_FCR, UART_FCR_ENABLE_FIFO |
-			UART_FCR_CLEAR_RCVR |
-			UART_FCR_CLEAR_XMIT);
-	serial_outp(mtpt, UART_FCR, 0);
-
-
-	(void) serial_in(mtpt, UART_RX);
-
-	if ((!is_real_interrupt(mtpt->port.irq))||(mtpt->poll_type==TYPE_POLL))
-	{
-		del_timer_sync(&mtpt->timer);
-	}
-	else
-	{
-		serial_unlink_irq_chain(mtpt);
-	}
-}
-
-
-
-static unsigned int multi_get_divisor(struct sb_uart_port *port, unsigned int baud)
-{
-	unsigned int quot;
-
-	if ((port->flags & UPF_MAGIC_MULTIPLIER) &&
-			baud == (port->uartclk/4))
-		quot = 0x8001;
-	else if ((port->flags & UPF_MAGIC_MULTIPLIER) &&
-			baud == (port->uartclk/8))
-		quot = 0x8002;
-	else
-		quot = sb_uart_get_divisor(port, baud);
-
-	return quot;
-}
-
-
-
-
-static void multi_set_termios(struct sb_uart_port *port, struct MP_TERMIOS *termios, struct MP_TERMIOS *old)
-{
-	struct mp_port *mtpt = (struct mp_port *)port;
-	unsigned char cval, fcr = 0;
-	unsigned long flags;
-	unsigned int baud, quot;
-
-	switch (termios->c_cflag & CSIZE) {
-		case CS5:
-			cval = 0x00;
-			break;
-		case CS6:
-			cval = 0x01;
-			break;
-		case CS7:
-			cval = 0x02;
-			break;
-		default:
-		case CS8:
-			cval = 0x03;
-			break;
-	}
-
-	if (termios->c_cflag & CSTOPB)
-		cval |= 0x04;
-	if (termios->c_cflag & PARENB)
-		cval |= UART_LCR_PARITY;
-	if (!(termios->c_cflag & PARODD))
-		cval |= UART_LCR_EPAR;
-
-#ifdef CMSPAR
-	if (termios->c_cflag & CMSPAR)
-		cval |= UART_LCR_SPAR;
-#endif
-
-	baud = sb_uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
-	quot = multi_get_divisor(port, baud);
-
-	if (mtpt->capabilities & UART_USE_FIFO) {
-		//if (baud < 2400)
-		//	fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_1;
-		//else
-		//	fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_8;
-
-		//	fcr = UART_FCR_ENABLE_FIFO | 0x90;
-			fcr = fcr_arr[mtpt->port.line];
-	}
-
-	spin_lock_irqsave(&mtpt->port.lock, flags);
-
-	sb_uart_update_timeout(port, termios->c_cflag, baud);
-
-	mtpt->port.read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR;
-	if (termios->c_iflag & INPCK)
-		mtpt->port.read_status_mask |= UART_LSR_FE | UART_LSR_PE;
-	if (termios->c_iflag & (BRKINT | PARMRK))
-		mtpt->port.read_status_mask |= UART_LSR_BI;
-
-	mtpt->port.ignore_status_mask = 0;
-	if (termios->c_iflag & IGNPAR)
-		mtpt->port.ignore_status_mask |= UART_LSR_PE | UART_LSR_FE;
-	if (termios->c_iflag & IGNBRK) {
-		mtpt->port.ignore_status_mask |= UART_LSR_BI;
-		if (termios->c_iflag & IGNPAR)
-			mtpt->port.ignore_status_mask |= UART_LSR_OE;
-	}
-
-	if ((termios->c_cflag & CREAD) == 0)
-		mtpt->port.ignore_status_mask |= UART_LSR_DR;
-
-	mtpt->ier &= ~UART_IER_MSI;
-	if (UART_ENABLE_MS(&mtpt->port, termios->c_cflag))
-		mtpt->ier |= UART_IER_MSI;
-
-	serial_out(mtpt, UART_IER, mtpt->ier);
-
-	if (mtpt->capabilities & UART_STARTECH) {
-		serial_outp(mtpt, UART_LCR, 0xBF);
-		serial_outp(mtpt, UART_EFR,
-				termios->c_cflag & CRTSCTS ? UART_EFR_CTS :0);
-	}
-
-	serial_outp(mtpt, UART_LCR, cval | UART_LCR_DLAB);/* set DLAB */
-
-	serial_outp(mtpt, UART_DLL, quot & 0xff);     /* LS of divisor */
-	serial_outp(mtpt, UART_DLM, quot >> 8);       /* MS of divisor */
-
-	serial_outp(mtpt, UART_LCR, cval);        /* reset DLAB */
-	mtpt->lcr = cval;                 /* Save LCR */
-
-	if (fcr & UART_FCR_ENABLE_FIFO) {
-		/* emulated UARTs (Lucent Venus 167x) need two steps */
-		serial_outp(mtpt, UART_FCR, UART_FCR_ENABLE_FIFO);
-	}
-
-	serial_outp(mtpt, UART_FCR, fcr);     /* set fcr */
-
-
-	if ((mtpt->port.type == PORT_16C105X)
-		|| (mtpt->port.type == PORT_16C105XA))
-	{
-		if(deep[mtpt->port.line]!=0)
-			set_deep_fifo(port, ENABLE);
-
-		if (mtpt->interface != RS232)
-			set_auto_rts(port,mtpt->interface);
-
-	}
-	else
-	{
-		if (mtpt->interface >= RS485NE)
-		{
-			uart_clear_mctrl(&mtpt->port, TIOCM_RTS);
-		}
-	}
-
-	if(mtpt->device->device_id == PCI_DEVICE_ID_MP4M)
-	{
-		SendATCommand(mtpt);
-		printk("SendATCommand\n");
-	}	
-	multi_set_mctrl(&mtpt->port, mtpt->port.mctrl);
-	spin_unlock_irqrestore(&mtpt->port.lock, flags);
-}
-
-static void multi_pm(struct sb_uart_port *port, unsigned int state, unsigned int oldstate)
-{
-	struct mp_port *mtpt = (struct mp_port *)port;
-	if (state) {
-		if (mtpt->capabilities & UART_STARTECH) {
-			serial_outp(mtpt, UART_LCR, 0xBF);
-			serial_outp(mtpt, UART_EFR, UART_EFR_ECB);
-			serial_outp(mtpt, UART_LCR, 0);
-			serial_outp(mtpt, UART_IER, UART_IERX_SLEEP);
-			serial_outp(mtpt, UART_LCR, 0xBF);
-			serial_outp(mtpt, UART_EFR, 0);
-			serial_outp(mtpt, UART_LCR, 0);
-		}
-
-		if (mtpt->pm)
-			mtpt->pm(port, state, oldstate);
-	} 
-	else 
-	{
-		if (mtpt->capabilities & UART_STARTECH) {
-			serial_outp(mtpt, UART_LCR, 0xBF);
-			serial_outp(mtpt, UART_EFR, UART_EFR_ECB);
-			serial_outp(mtpt, UART_LCR, 0);
-			serial_outp(mtpt, UART_IER, 0);
-			serial_outp(mtpt, UART_LCR, 0xBF);
-			serial_outp(mtpt, UART_EFR, 0);
-			serial_outp(mtpt, UART_LCR, 0);
-		}
-
-		if (mtpt->pm)
-			mtpt->pm(port, state, oldstate);
-	}
-}
-
-static void multi_release_std_resource(struct mp_port *mtpt)
-{
-	unsigned int size = 8 << mtpt->port.regshift;
-
-	switch (mtpt->port.iotype) {
-		case UPIO_MEM:
-			if (!mtpt->port.mapbase)
-				break;
-
-			if (mtpt->port.flags & UPF_IOREMAP) {
-				iounmap(mtpt->port.membase);
-				mtpt->port.membase = NULL;
-			}
-
-			release_mem_region(mtpt->port.mapbase, size);
-			break;
-
-		case UPIO_HUB6:
-		case UPIO_PORT:
-			release_region(mtpt->port.iobase,size);
-			break;
-	}
-}
-
-static void multi_release_port(struct sb_uart_port *port)
-{
-}
-
-static int multi_request_port(struct sb_uart_port *port)
-{
-	return 0;
-}
-
-static void multi_config_port(struct sb_uart_port *port, int flags)
-{
-	struct mp_port *mtpt = (struct mp_port *)port;
-	int probeflags = PROBE_ANY;
-
-	if (flags & UART_CONFIG_TYPE)
-		autoconfig(mtpt, probeflags);
-	if (mtpt->port.type != PORT_UNKNOWN && flags & UART_CONFIG_IRQ)
-		autoconfig_irq(mtpt);
-
-	if (mtpt->port.type == PORT_UNKNOWN)
-		multi_release_std_resource(mtpt);
-}
-
-static int multi_verify_port(struct sb_uart_port *port, struct serial_struct *ser)
-{
-	if (ser->irq >= NR_IRQS || ser->irq < 0 ||
-			ser->baud_base < 9600 || ser->type < PORT_UNKNOWN ||
-			ser->type == PORT_STARTECH)
-		return -EINVAL;
-	return 0;
-}
-
-static const char *multi_type(struct sb_uart_port *port)
-{
-	int type = port->type;
-
-	if (type >= ARRAY_SIZE(uart_config))
-		type = 0;
-	return uart_config[type].name;
-}
-
-static struct sb_uart_ops multi_pops = {
-	.tx_empty   = multi_tx_empty,
-	.set_mctrl  = multi_set_mctrl,
-	.get_mctrl  = multi_get_mctrl,
-	.stop_tx    = multi_stop_tx,
-	.start_tx   = multi_start_tx,
-	.stop_rx    = multi_stop_rx,
-	.enable_ms  = multi_enable_ms,
-	.break_ctl  = multi_break_ctl,
-	.startup    = multi_startup,
-	.shutdown   = multi_shutdown,
-	.set_termios    = multi_set_termios,
-	.pm     	= multi_pm,
-	.type       	= multi_type,
-	.release_port   = multi_release_port,
-	.request_port   = multi_request_port,
-	.config_port    = multi_config_port,
-	.verify_port    = multi_verify_port,
-};
-
-static struct uart_driver multi_reg = {
-	.owner          = THIS_MODULE,
-	.driver_name    = "goldel_tulip",
-	.dev_name       = "ttyMP",
-	.major          = SB_TTY_MP_MAJOR,
-	.minor          = 0,
-	.nr             = MAX_MP_PORT, 
-	.cons           = NULL,
-};
-
-static void __init multi_init_ports(void)
-{
-	struct mp_port *mtpt;
-	static int first = 1;
-	int i,j,k;
-	unsigned char osc;
-	unsigned char b_ret = 0;
-	static struct mp_device_t *sbdev; 
-
-	if (!first)
-		return;
-	first = 0;
-
-	mtpt = multi_ports; 
-
-	for (k=0;k<NR_BOARD;k++)
-	{
-		sbdev = &mp_devs[k];
-
-		for (i = 0; i < sbdev->nr_ports; i++, mtpt++) 
-		{
-			mtpt->device 		= sbdev;
-			mtpt->port.iobase   = sbdev->uart_access_addr + 8*i;
-			mtpt->port.irq      = sbdev->irq;
-			if ( ((sbdev->device_id == PCI_DEVICE_ID_MP4)&&(sbdev->revision==0x91)))
-				mtpt->interface_config_addr = sbdev->option_reg_addr + 0x08 + i;
-			else if (sbdev->revision == 0xc0)
-				mtpt->interface_config_addr = sbdev->option_reg_addr + 0x08 + (i & 0x1);
-			else
-				mtpt->interface_config_addr = sbdev->option_reg_addr + 0x08 + i/8;
-
-			mtpt->option_base_addr = sbdev->option_reg_addr;
-
-			mtpt->poll_type = sbdev->poll_type;
-
-			mtpt->port.uartclk  = BASE_BAUD * 16;
-
-			/* get input clock information */
-			osc = inb(sbdev->option_reg_addr + MP_OPTR_DIR0 + i/8) & 0x0F;
-			if (osc==0x0f)
-				osc = 0;
-			for(j=0;j<osc;j++)
-				mtpt->port.uartclk *= 2;
-			mtpt->port.flags    |= STD_COM_FLAGS | UPF_SHARE_IRQ ;
-			mtpt->port.iotype   = UPIO_PORT;
-			mtpt->port.ops      = &multi_pops;
-
-			if (sbdev->revision == 0xc0)
-			{
-				/* for SB16C1053APCI */
-				b_ret = sb1053a_get_interface(mtpt, i);
-			}
-			else
-			{
-				b_ret = read_option_register(mtpt,(MP_OPTR_IIR0 + i/8));
-				printk("IIR_RET = %x\n",b_ret);
-			}
-
-			/* default to RS232 */
-			mtpt->interface = RS232;
-			if (IIR_RS422 == (b_ret & IIR_TYPE_MASK))
-				mtpt->interface = RS422PTP;
-			if (IIR_RS485 == (b_ret & IIR_TYPE_MASK))
-				mtpt->interface = RS485NE;
-		}
-	}
-}
-
-static void __init multi_register_ports(struct uart_driver *drv)
-{
-	int i;
-
-	multi_init_ports();
-
-	for (i = 0; i < NR_PORTS; i++) {
-		struct mp_port *mtpt = &multi_ports[i];
-
-		mtpt->port.line = i;
-		mtpt->port.ops = &multi_pops;
-		init_timer(&mtpt->timer);
-		mtpt->timer.function = multi_timeout;
-		mp_add_one_port(drv, &mtpt->port);
-	}
-}
-
-/**
- * pci_remap_base - remap BAR value of pci device
- *
- * PARAMETERS
- *  pcidev  - pci_dev structure address
- *  offset  - BAR offset PCI_BASE_ADDRESS_0 ~ PCI_BASE_ADDRESS_4
- *  address - address to be changed BAR value
- *  size	- size of address space 
- *
- * RETURNS
- *  If this function performs successful, it returns 0. Otherwise, It returns -1.
- */
-static int pci_remap_base(struct pci_dev *pcidev, unsigned int offset, 
-		unsigned int address, unsigned int size) 
-{
-#if 0
-	struct resource *root;
-	unsigned index = (offset - 0x10) >> 2;
-#endif
-
-	pci_write_config_dword(pcidev, offset, address);
-#if 0
-	root = pcidev->resource[index].parent;
-	release_resource(&pcidev->resource[index]);
-	address &= ~0x1;
-	pcidev->resource[index].start = address;
-	pcidev->resource[index].end	  = address + size - 1;
-
-	if (request_resource(root, &pcidev->resource[index]) != NULL)
-	{
-		printk(KERN_ERR "pci remap conflict!! 0x%x\n", address);
-		return (-1);
-	}
-#endif
-
-	return (0);
-}
-
-static int init_mp_dev(struct pci_dev *pcidev, mppcibrd_t brd)
-{
-	static struct mp_device_t *sbdev = mp_devs;
-	unsigned long addr = 0;
-	int j;
-	struct resource *ret = NULL;
-
-	sbdev->device_id = brd.device_id;
-	pci_read_config_byte(pcidev, PCI_CLASS_REVISION, &(sbdev->revision));
-	sbdev->name = brd.name;
-	sbdev->uart_access_addr = pcidev->resource[0].start & PCI_BASE_ADDRESS_IO_MASK;
-
-	/* check revision. The SB16C1053APCI's option i/o address is BAR4 */
-	if (sbdev->revision == 0xc0)
-	{
-		/* SB16C1053APCI */
-		sbdev->option_reg_addr = pcidev->resource[4].start & PCI_BASE_ADDRESS_IO_MASK;
-	}
-	else
-	{
-		sbdev->option_reg_addr = pcidev->resource[1].start & PCI_BASE_ADDRESS_IO_MASK;
-	}
-#if 1	
-	if (sbdev->revision == 0xc0)
-	{
-		outb(0x00, sbdev->option_reg_addr + MP_OPTR_GPOCR);
-		inb(sbdev->option_reg_addr + MP_OPTR_GPOCR);
-		outb(0x83, sbdev->option_reg_addr + MP_OPTR_GPOCR);
-	}
-#endif
-
-	sbdev->irq = pcidev->irq;
-
-	if ((brd.device_id & 0x0800) || !(brd.device_id &0xff00))
-	{
-		sbdev->poll_type = TYPE_INTERRUPT;
-	}
-	else
-	{
-		sbdev->poll_type = TYPE_POLL;
-	}
-
-	/* codes which is specific to each board*/
-	switch(brd.device_id){
-		case PCI_DEVICE_ID_MP1 :
-		case PCIE_DEVICE_ID_MP1 :
-		case PCIE_DEVICE_ID_MP1E :
-		case PCIE_DEVICE_ID_GT_MP1 :
-			sbdev->nr_ports = 1;
-			break;
-		case PCI_DEVICE_ID_MP2 :
-		case PCIE_DEVICE_ID_MP2 :
-		case PCIE_DEVICE_ID_GT_MP2 :
-		case PCIE_DEVICE_ID_MP2B :
-		case PCIE_DEVICE_ID_MP2E :
-			sbdev->nr_ports = 2;
-
-			/* serial base address remap */
-			if (sbdev->revision == 0xc0)
-			{
-				int prev_port_addr = 0;
-
-				pci_read_config_dword(pcidev, PCI_BASE_ADDRESS_0, &prev_port_addr);
-				pci_remap_base(pcidev, PCI_BASE_ADDRESS_1, prev_port_addr + 8, 8);
-			}
-			break;
-		case PCI_DEVICE_ID_MP4 :
-		case PCI_DEVICE_ID_MP4A :
-		case PCIE_DEVICE_ID_MP4 :
-		case PCI_DEVICE_ID_GT_MP4 :
-		case PCI_DEVICE_ID_GT_MP4A :
-		case PCIE_DEVICE_ID_GT_MP4 :
-		case PCI_DEVICE_ID_MP4M :
-		case PCIE_DEVICE_ID_MP4B :
-			sbdev->nr_ports = 4;
-
-			if(sbdev->revision == 0x91){
-				sbdev->reserved_addr[0] = pcidev->resource[0].start & PCI_BASE_ADDRESS_IO_MASK;
-				outb(0x03 , sbdev->reserved_addr[0] + 0x01);
-				outb(0x03 , sbdev->reserved_addr[0] + 0x02);
-				outb(0x01 , sbdev->reserved_addr[0] + 0x20);
-				outb(0x00 , sbdev->reserved_addr[0] + 0x21);
-				request_region(sbdev->reserved_addr[0], 32, sbdev->name);
-				sbdev->uart_access_addr = pcidev->resource[1].start & PCI_BASE_ADDRESS_IO_MASK;
-				sbdev->option_reg_addr = pcidev->resource[2].start & PCI_BASE_ADDRESS_IO_MASK;
-			}
-
-			/* SB16C1053APCI */
-			if (sbdev->revision == 0xc0)
-			{
-				int prev_port_addr = 0;
-
-				pci_read_config_dword(pcidev, PCI_BASE_ADDRESS_0, &prev_port_addr);
-				pci_remap_base(pcidev, PCI_BASE_ADDRESS_1, prev_port_addr + 8, 8);
-				pci_remap_base(pcidev, PCI_BASE_ADDRESS_2, prev_port_addr + 16, 8);
-				pci_remap_base(pcidev, PCI_BASE_ADDRESS_3, prev_port_addr + 24, 8);
-			}
-			break;
-		case PCI_DEVICE_ID_MP6 :
-		case PCI_DEVICE_ID_MP6A :
-		case PCI_DEVICE_ID_GT_MP6 :
-		case PCI_DEVICE_ID_GT_MP6A :
-			sbdev->nr_ports = 6;
-
-			/* SB16C1053APCI */
-			if (sbdev->revision == 0xc0)
-			{
-				int prev_port_addr = 0;
-
-				pci_read_config_dword(pcidev, PCI_BASE_ADDRESS_0, &prev_port_addr);
-				pci_remap_base(pcidev, PCI_BASE_ADDRESS_1, prev_port_addr + 8, 8);
-				pci_remap_base(pcidev, PCI_BASE_ADDRESS_2, prev_port_addr + 16, 16);
-				pci_remap_base(pcidev, PCI_BASE_ADDRESS_3, prev_port_addr + 32, 16);
-			}
-			break;
-		case PCI_DEVICE_ID_MP8 :
-		case PCIE_DEVICE_ID_MP8 :
-		case PCI_DEVICE_ID_GT_MP8 :
-		case PCIE_DEVICE_ID_GT_MP8 :
-		case PCIE_DEVICE_ID_MP8B :
-			sbdev->nr_ports = 8;
-			break;
-		case PCI_DEVICE_ID_MP32 :
-		case PCIE_DEVICE_ID_MP32 :
-		case PCI_DEVICE_ID_GT_MP32 :
-		case PCIE_DEVICE_ID_GT_MP32 :
-			{
-				int portnum_hex=0;
-				portnum_hex = inb(sbdev->option_reg_addr);
-				sbdev->nr_ports = ((portnum_hex/16)*10) + (portnum_hex % 16);
-			}
-			break;
-#ifdef CONFIG_PARPORT_PC
-		case PCI_DEVICE_ID_MP2S1P :
-			sbdev->nr_ports = 2;
-
-			/* SB16C1053APCI */
-			if (sbdev->revision == 0xc0)
-			{
-				int prev_port_addr = 0;
-
-				pci_read_config_dword(pcidev, PCI_BASE_ADDRESS_0, &prev_port_addr);
-				pci_remap_base(pcidev, PCI_BASE_ADDRESS_1, prev_port_addr + 8, 8);
-			}
-
-			/* add PC compatible parallel port */
-			parport_pc_probe_port(pcidev->resource[2].start, pcidev->resource[3].start, PARPORT_IRQ_NONE, PARPORT_DMA_NONE, &pcidev->dev, 0);
-			break;
-		case PCI_DEVICE_ID_MP1P :
-			/* add PC compatible parallel port */
-			parport_pc_probe_port(pcidev->resource[2].start, pcidev->resource[3].start, PARPORT_IRQ_NONE, PARPORT_DMA_NONE, &pcidev->dev, 0);
-			break;
-#endif
-	}
-
-	ret = request_region(sbdev->uart_access_addr, (8*sbdev->nr_ports), sbdev->name);
-
-	if (sbdev->revision == 0xc0)
-	{
-		ret = request_region(sbdev->option_reg_addr, 0x40, sbdev->name);
-	}
-	else
-	{
-		ret = request_region(sbdev->option_reg_addr, 0x20, sbdev->name);
-	}
-
-
-	NR_BOARD++;
-	NR_PORTS += sbdev->nr_ports;
-
-	/* Enable PCI interrupt */
-	addr = sbdev->option_reg_addr + MP_OPTR_IMR0;
-	for(j=0; j < (sbdev->nr_ports/8)+1; j++)
-	{
-		if (sbdev->poll_type == TYPE_INTERRUPT)
-		{
-			outb(0xff,addr +j);
-		}
-	}
-	sbdev++;
-
-	return 0;
-}
-
-static int __init multi_init(void)
-{
-	int ret, i;
-	struct pci_dev  *dev = NULL;
-
-	if(fcr_count==0)
-	{
-		for(i=0;i<256;i++)
-		{
-			fcr_arr[i] = 0x01;
-			
-		}
-	}
-	if(deep_count==0)
-	{
-		for(i=0;i<256;i++)
-		{
-			deep[i] = 1;
-			
-		}
-	}
-	if(rtr_count==0)
-        {
-                for(i=0;i<256;i++)
-                {
-                        rtr[i] = 0x10;
-                }
-        }
-	if(ttr_count==0)
-        {
-                for(i=0;i<256;i++)
-                {
-                        ttr[i] = 0x38;
-                }
-        }
-
-
-printk("MULTI INIT\n");
-	for( i=0; i< mp_nrpcibrds; i++)
-	{
-
-		while( (dev = pci_get_device(mp_pciboards[i].vendor_id, mp_pciboards[i].device_id, dev) ) )
-
-		{
-printk("FOUND~~~\n");
-//	Cent OS bug fix
-//			if (mp_pciboards[i].device_id & 0x0800)
-			{
-				int status;
-	        		pci_disable_device(dev);
-	        		status = pci_enable_device(dev);
-            
-	   		     	if (status != 0)
-        			{ 
-               				printk("Multiport Board Enable Fail !\n\n");
-               				status = -ENXIO;
-                			return status;
-           			}
-			}
-
-			init_mp_dev(dev, mp_pciboards[i]);	
-		}
-	}
-
-	for (i = 0; i < NR_IRQS; i++)
-		spin_lock_init(&irq_lists[i].lock);
-
-	ret = mp_register_driver(&multi_reg);
-
-	if (ret >= 0)
-		multi_register_ports(&multi_reg);
-
-	return ret;
-}
-
-static void __exit multi_exit(void)
-{
-	int i;
-
-	for (i = 0; i < NR_PORTS; i++)
-		mp_remove_one_port(&multi_reg, &multi_ports[i].port);
-
-	mp_unregister_driver(&multi_reg);
-}
-
-module_init(multi_init);
-module_exit(multi_exit);
-
-MODULE_DESCRIPTION("SystemBase Multiport PCI/PCIe CORE");
-MODULE_LICENSE("GPL");
diff --git a/drivers/staging/sb105x/sb_pci_mp.h b/drivers/staging/sb105x/sb_pci_mp.h
deleted file mode 100644
index 80ae4ab..0000000
--- a/drivers/staging/sb105x/sb_pci_mp.h
+++ /dev/null
@@ -1,291 +0,0 @@
-#include <linux/errno.h>
-#include <linux/signal.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/serial.h>
-#include <linux/serial_reg.h>
-#include <linux/ioport.h>
-#include <linux/mm.h>
-#include <linux/sched.h>
-
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/wait.h>
-#include <linux/tty_driver.h>
-#include <linux/pci.h>
-#include <linux/circ_buf.h>
-
-#include <asm/uaccess.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/serial.h>
-#include <linux/interrupt.h>
-
-
-#include <linux/parport.h>
-#include <linux/ctype.h>
-#include <linux/poll.h>
-
-
-#define MP_TERMIOS  ktermios
-
-#include "sb_mp_register.h"
-#include "sb_ser_core.h"
-
-#define DRIVER_VERSION  "1.1"
-#define DRIVER_DATE     "2012/01/05"
-#define DRIVER_AUTHOR  "SYSTEMBASE<tech@sysbas.com>"
-#define DRIVER_DESC  "SystemBase PCI/PCIe Multiport Core"
-
-#define SB_TTY_MP_MAJOR			54
-#define PCI_VENDOR_ID_MULTIPORT		0x14A1
-
-#define PCI_DEVICE_ID_MP1		0x4d01
-#define PCI_DEVICE_ID_MP2		0x4d02
-#define PCI_DEVICE_ID_MP4		0x4d04
-#define PCI_DEVICE_ID_MP4A		0x4d54
-#define PCI_DEVICE_ID_MP6		0x4d06
-#define PCI_DEVICE_ID_MP6A		0x4d56
-#define PCI_DEVICE_ID_MP8		0x4d08
-#define PCI_DEVICE_ID_MP32		0x4d32
-/* Parallel port */
-#define PCI_DEVICE_ID_MP1P		0x4301
-#define PCI_DEVICE_ID_MP2S1P		0x4303
-
-#define PCIE_DEVICE_ID_MP1		0x4501
-#define PCIE_DEVICE_ID_MP2		0x4502
-#define PCIE_DEVICE_ID_MP4		0x4504
-#define PCIE_DEVICE_ID_MP8		0x4508
-#define PCIE_DEVICE_ID_MP32		0x4532
-
-#define PCIE_DEVICE_ID_MP1E		0x4e01
-#define PCIE_DEVICE_ID_MP2E		0x4e02
-#define PCIE_DEVICE_ID_MP2B		0x4b02
-#define PCIE_DEVICE_ID_MP4B		0x4b04
-#define PCIE_DEVICE_ID_MP8B		0x4b08
-
-#define PCI_DEVICE_ID_GT_MP4		0x0004
-#define PCI_DEVICE_ID_GT_MP4A		0x0054
-#define PCI_DEVICE_ID_GT_MP6		0x0006
-#define PCI_DEVICE_ID_GT_MP6A		0x0056
-#define PCI_DEVICE_ID_GT_MP8		0x0008
-#define PCI_DEVICE_ID_GT_MP32		0x0032
-
-#define PCIE_DEVICE_ID_GT_MP1		0x1501
-#define PCIE_DEVICE_ID_GT_MP2		0x1502
-#define PCIE_DEVICE_ID_GT_MP4		0x1504
-#define PCIE_DEVICE_ID_GT_MP8		0x1508
-#define PCIE_DEVICE_ID_GT_MP32		0x1532
-
-#define PCI_DEVICE_ID_MP4M		0x4604  //modem
-
-#define MAX_MP_DEV  8
-#define BD_MAX_PORT 32 	/* Max serial port in one board */
-#define MAX_MP_PORT 256 /* Max serial port in one PC */
-
-#define PORT_16C105XA	3
-#define PORT_16C105X	2
-#define PORT_16C55X		1
-
-#define ENABLE		1
-#define DISABLE		0
-
-/* ioctls */
-#define TIOCGNUMOFPORT		0x545F
-#define TIOCSMULTIECHO		0x5440
-#define TIOCSPTPNOECHO		0x5441
-
-#define TIOCGOPTIONREG		0x5461
-#define TIOCGDISABLEIRQ		0x5462
-#define TIOCGENABLEIRQ		0x5463
-#define TIOCGSOFTRESET		0x5464
-#define TIOCGSOFTRESETR		0x5465
-#define TIOCGREGINFO		0x5466
-#define TIOCGGETLSR		0x5467
-#define TIOCGGETDEVID		0x5468
-#define TIOCGGETBDNO		0x5469
-#define TIOCGGETINTERFACE	0x546A
-#define TIOCGGETREV		0x546B
-#define TIOCGGETNRPORTS		0x546C
-#define TIOCGGETPORTTYPE	0x546D
-#define GETDEEPFIFO		0x54AA
-#define SETDEEPFIFO		0x54AB
-#define SETFCR			0x54BA
-#define SETTTR			0x54B1
-#define SETRTR			0x54B2
-#define GETTTR			0x54B3
-#define GETRTR			0x54B4
-
-/* multi-drop mode related ioctl commands */
-#define TIOCSMULTIDROP		0x5470
-#define TIOCSMDADDR   		0x5471
-#define TIOCGMDADDR   		0x5472
-#define TIOCSENDADDR		0x5473
-
-
-/* serial interface */
-#define RS232		1 
-#define RS422PTP	2
-#define RS422MD		3
-#define RS485NE		4
-#define RS485ECHO	5
-
-#define serial_inp(up, offset)      serial_in(up, offset)
-#define serial_outp(up, offset, value)  serial_out(up, offset, value)
-	
-#define PASS_LIMIT  256
-#define is_real_interrupt(irq)  ((irq) != 0)
-
-#define PROBE_ANY   (~0)
-
-static DEFINE_MUTEX(mp_mutex);
-#define MP_MUTEX_LOCK(x) mutex_lock(&(x)) 
-#define MP_MUTEX_UNLOCK(x) mutex_unlock(&(x)) 
-#define MP_STATE_LOCK(x) mutex_lock(&((x)->mutex)) 
-#define MP_STATE_UNLOCK(x) mutex_unlock(&((x)->mutex)) 
-        
-
-#define UART_LSR_SPECIAL    0x1E
-        
-#define HIGH_BITS_OFFSET        ((sizeof(long)-sizeof(int))*8)
-#define uart_users(state)       ((state)->count + ((state)->info ? (state)->info->blocked_open : 0))
-
-
-//#define MP_DEBUG 1
-#undef MP_DEBUG
-
-#ifdef MP_DEBUG
-#define DPRINTK(x...)   printk(x)
-#else
-#define DPRINTK(x...)   do { } while (0)
-#endif
-
-#ifdef MP_DEBUG
-#define DEBUG_AUTOCONF(fmt...)  printk(fmt)
-#else
-#define DEBUG_AUTOCONF(fmt...)  do { } while (0)
-#endif
-
-#ifdef MP_DEBUG
-#define DEBUG_INTR(fmt...)  printk(fmt)
-#else
-#define DEBUG_INTR(fmt...)  do { } while (0)
-#endif
-
-#if defined(__i386__) && defined(CONFIG_M486)
-#define SERIAL_INLINE
-#endif
-#ifdef SERIAL_INLINE
-#define _INLINE_ inline
-#else
-#define _INLINE_
-#endif
-
-#define TYPE_POLL	1
-#define TYPE_INTERRUPT	2
-
-
-struct mp_device_t {
-        unsigned short  device_id;
-        unsigned char   revision;
-        char            *name;
-        unsigned long   uart_access_addr;
-        unsigned long   option_reg_addr;
-        unsigned long   reserved_addr[4];
-        int             irq;
-        int             nr_ports;
-        int             poll_type;
-};
-
-typedef struct mppcibrd {
-        char            *name;
-        unsigned short  vendor_id;
-        unsigned short  device_id;
-} mppcibrd_t;
-
-static mppcibrd_t mp_pciboards[] = {
-
-        { "Multi-1 PCI", PCI_VENDOR_ID_MULTIPORT , PCI_DEVICE_ID_MP1} ,
-        { "Multi-2 PCI", PCI_VENDOR_ID_MULTIPORT , PCI_DEVICE_ID_MP2} ,
-        { "Multi-4 PCI", PCI_VENDOR_ID_MULTIPORT , PCI_DEVICE_ID_MP4} ,
-        { "Multi-4 PCI", PCI_VENDOR_ID_MULTIPORT , PCI_DEVICE_ID_MP4A} ,
-        { "Multi-6 PCI", PCI_VENDOR_ID_MULTIPORT , PCI_DEVICE_ID_MP6} ,
-        { "Multi-6 PCI", PCI_VENDOR_ID_MULTIPORT , PCI_DEVICE_ID_MP6A} ,
-        { "Multi-8 PCI", PCI_VENDOR_ID_MULTIPORT , PCI_DEVICE_ID_MP8} ,
-        { "Multi-32 PCI", PCI_VENDOR_ID_MULTIPORT , PCI_DEVICE_ID_MP32} ,
-
-        { "Multi-1P PCI", PCI_VENDOR_ID_MULTIPORT , PCI_DEVICE_ID_MP1P} ,
-        { "Multi-2S1P PCI", PCI_VENDOR_ID_MULTIPORT , PCI_DEVICE_ID_MP2S1P} ,
-
-        { "Multi-4(GT) PCI", PCI_VENDOR_ID_MULTIPORT , PCI_DEVICE_ID_GT_MP4} ,
-        { "Multi-4(GT) PCI", PCI_VENDOR_ID_MULTIPORT , PCI_DEVICE_ID_GT_MP4A} ,
-        { "Multi-6(GT) PCI", PCI_VENDOR_ID_MULTIPORT , PCI_DEVICE_ID_GT_MP6} ,
-        { "Multi-6(GT) PCI", PCI_VENDOR_ID_MULTIPORT , PCI_DEVICE_ID_GT_MP6A} ,
-        { "Multi-8(GT) PCI", PCI_VENDOR_ID_MULTIPORT , PCI_DEVICE_ID_GT_MP8} ,
-        { "Multi-32(GT) PCI", PCI_VENDOR_ID_MULTIPORT , PCI_DEVICE_ID_GT_MP32} ,
-
-        { "Multi-1 PCIe", PCI_VENDOR_ID_MULTIPORT , PCIE_DEVICE_ID_MP1} ,
-        { "Multi-2 PCIe", PCI_VENDOR_ID_MULTIPORT , PCIE_DEVICE_ID_MP2} ,
-        { "Multi-4 PCIe", PCI_VENDOR_ID_MULTIPORT , PCIE_DEVICE_ID_MP4} ,
-        { "Multi-8 PCIe", PCI_VENDOR_ID_MULTIPORT , PCIE_DEVICE_ID_MP8} ,
-        { "Multi-32 PCIe", PCI_VENDOR_ID_MULTIPORT , PCIE_DEVICE_ID_MP32} ,
-
-        { "Multi-1 PCIe E", PCI_VENDOR_ID_MULTIPORT , PCIE_DEVICE_ID_MP1E} ,
-        { "Multi-2 PCIe E", PCI_VENDOR_ID_MULTIPORT , PCIE_DEVICE_ID_MP2E} ,
-        { "Multi-2 PCIe B", PCI_VENDOR_ID_MULTIPORT , PCIE_DEVICE_ID_MP2B} ,
-        { "Multi-4 PCIe B", PCI_VENDOR_ID_MULTIPORT , PCIE_DEVICE_ID_MP4B} ,
-        { "Multi-8 PCIe B", PCI_VENDOR_ID_MULTIPORT , PCIE_DEVICE_ID_MP8B} ,
-
-        { "Multi-1(GT) PCIe", PCI_VENDOR_ID_MULTIPORT , PCIE_DEVICE_ID_GT_MP1} ,
-        { "Multi-2(GT) PCIe", PCI_VENDOR_ID_MULTIPORT , PCIE_DEVICE_ID_GT_MP2} ,
-        { "Multi-4(GT) PCIe", PCI_VENDOR_ID_MULTIPORT , PCIE_DEVICE_ID_GT_MP4} ,
-        { "Multi-8(GT) PCIe", PCI_VENDOR_ID_MULTIPORT , PCIE_DEVICE_ID_GT_MP8} ,
-        { "Multi-32(GT) PCIe", PCI_VENDOR_ID_MULTIPORT , PCIE_DEVICE_ID_GT_MP32} ,
-
-        { "Multi-4M PCI", PCI_VENDOR_ID_MULTIPORT , PCI_DEVICE_ID_MP4M} ,
-};
-
-struct mp_port {
-        struct sb_uart_port port;
-
-        struct timer_list   timer;      /* "no irq" timer */
-        struct list_head    list;       /* ports on this IRQ */
-        unsigned int        capabilities;   /* port capabilities */
-        unsigned short      rev;
-        unsigned char       acr;
-        unsigned char       ier;
-        unsigned char       lcr;
-        unsigned char       mcr;
-        unsigned char       mcr_mask;   /* mask of user bits */
-        unsigned char       mcr_force;  /* mask of forced bits */
-        unsigned char       lsr_break_flag;
-
-        void            (*pm)(struct sb_uart_port *port,
-                        unsigned int state, unsigned int old);
-        struct mp_device_t *device;
-        unsigned long   interface_config_addr;
-        unsigned long   option_base_addr;
-        unsigned char   interface;
-        unsigned char   poll_type;
-};
-
-struct irq_info {
-        spinlock_t      lock;
-        struct list_head    *head;
-};
-
-struct sb105x_uart_config {
-	char    *name;
-	int     dfl_xmit_fifo_size;
-	int     flags;
-};
-
-static const struct sb105x_uart_config uart_config[] = {
-        { "unknown",    1,  0 },
-        { "16550A", 16, UART_CLEAR_FIFO | UART_USE_FIFO },
-        { "SB16C1050",    128,    UART_CLEAR_FIFO | UART_USE_FIFO | UART_STARTECH },
-        { "SB16C1050A",    128,    UART_CLEAR_FIFO | UART_USE_FIFO | UART_STARTECH },
-};
-
-
-
diff --git a/drivers/staging/sb105x/sb_ser_core.h b/drivers/staging/sb105x/sb_ser_core.h
deleted file mode 100644
index c8fb991..0000000
--- a/drivers/staging/sb105x/sb_ser_core.h
+++ /dev/null
@@ -1,368 +0,0 @@
-#include <linux/wait.h>
-
-#define UART_CONFIG_TYPE	(1 << 0)
-#define UART_CONFIG_IRQ		(1 << 1)
-#define UPIO_PORT		(0)
-#define UPIO_HUB6		(1)
-#define UPIO_MEM		(2)
-#define UPIO_MEM32		(3)
-#define UPIO_AU			(4)			/* Au1x00 type IO */
-#define UPIO_TSI		(5)			/* Tsi108/109 type IO */
-#define UPF_FOURPORT		(1 << 1)
-#define UPF_SAK			(1 << 2)
-#define UPF_SPD_MASK		(0x1030)
-#define UPF_SPD_HI		(0x0010)
-#define UPF_SPD_VHI		(0x0020)
-#define UPF_SPD_CUST		(0x0030)
-#define UPF_SPD_SHI		(0x1000)
-#define UPF_SPD_WARP		(0x1010)
-#define UPF_SKIP_TEST		(1 << 6)
-#define UPF_AUTO_IRQ		(1 << 7)
-#define UPF_HARDPPS_CD		(1 << 11)
-#define UPF_LOW_LATENCY		(1 << 13)
-#define UPF_BUGGY_UART		(1 << 14)
-#define UPF_MAGIC_MULTIPLIER	(1 << 16)
-#define UPF_CONS_FLOW		(1 << 23)
-#define UPF_SHARE_IRQ		(1 << 24)
-#define UPF_BOOT_AUTOCONF	(1 << 28)
-#define UPF_DEAD		(1 << 30)
-#define UPF_IOREMAP		(1 << 31)
-#define UPF_CHANGE_MASK		(0x17fff)
-#define UPF_USR_MASK		(UPF_SPD_MASK|UPF_LOW_LATENCY)
-#define USF_CLOSING_WAIT_INF	(0)
-#define USF_CLOSING_WAIT_NONE	(~0U)
-
-#define UART_XMIT_SIZE	PAGE_SIZE
-
-#define UIF_CHECK_CD		(1 << 25)
-#define UIF_CTS_FLOW		(1 << 26)
-#define UIF_NORMAL_ACTIVE	(1 << 29)
-#define UIF_INITIALIZED		(1 << 31)
-#define UIF_SUSPENDED		(1 << 30)
-
-#define WAKEUP_CHARS		256
-
-#define uart_circ_empty(circ)		((circ)->head == (circ)->tail)
-#define uart_circ_clear(circ)		((circ)->head = (circ)->tail = 0)
-
-#define uart_circ_chars_pending(circ)	\
-	(CIRC_CNT((circ)->head, (circ)->tail, UART_XMIT_SIZE))
-
-#define uart_circ_chars_free(circ)	\
-	(CIRC_SPACE((circ)->head, (circ)->tail, UART_XMIT_SIZE))
-
-#define uart_tx_stopped(port)		\
-	((port)->info->tty->stopped || (port)->info->tty->hw_stopped)
-
-#define UART_ENABLE_MS(port,cflag)	((port)->flags & UPF_HARDPPS_CD || \
-					 (cflag) & CRTSCTS || \
-					 !((cflag) & CLOCAL))
-
-
-struct sb_uart_port;
-struct sb_uart_info;
-struct serial_struct;
-struct device;
-
-struct sb_uart_ops {
-	unsigned int	(*tx_empty)(struct sb_uart_port *);
-	void		(*set_mctrl)(struct sb_uart_port *, unsigned int mctrl);
-	unsigned int	(*get_mctrl)(struct sb_uart_port *);
-	void		(*stop_tx)(struct sb_uart_port *);
-	void		(*start_tx)(struct sb_uart_port *);
-	void		(*send_xchar)(struct sb_uart_port *, char ch);
-	void		(*stop_rx)(struct sb_uart_port *);
-	void		(*enable_ms)(struct sb_uart_port *);
-	void		(*break_ctl)(struct sb_uart_port *, int ctl);
-	int		(*startup)(struct sb_uart_port *);
-	void		(*shutdown)(struct sb_uart_port *);
-	void		(*set_termios)(struct sb_uart_port *, struct MP_TERMIOS *new,
-				       struct MP_TERMIOS *old);
-	void		(*pm)(struct sb_uart_port *, unsigned int state,
-			      unsigned int oldstate);
-	int		(*set_wake)(struct sb_uart_port *, unsigned int state);
-
-	const char *(*type)(struct sb_uart_port *);
-
-	void		(*release_port)(struct sb_uart_port *);
-
-	int		(*request_port)(struct sb_uart_port *);
-	void		(*config_port)(struct sb_uart_port *, int);
-	int		(*verify_port)(struct sb_uart_port *, struct serial_struct *);
-	int		(*ioctl)(struct sb_uart_port *, unsigned int, unsigned long);
-};
-
-
-struct sb_uart_icount {
-	__u32	cts;
-	__u32	dsr;
-	__u32	rng;
-	__u32	dcd;
-	__u32	rx;
-	__u32	tx;
-	__u32	frame;
-	__u32	overrun;
-	__u32	parity;
-	__u32	brk;
-	__u32	buf_overrun;
-};
-typedef unsigned int  upf_t;
-
-struct sb_uart_port {
-	spinlock_t		lock;			/* port lock */
-	unsigned int		iobase;			/* in/out[bwl] */
-	unsigned char __iomem	*membase;		/* read/write[bwl] */
-	unsigned int		irq;			/* irq number */
-	unsigned int		uartclk;		/* base uart clock */
-	unsigned int		fifosize;		/* tx fifo size */
-	unsigned char		x_char;			/* xon/xoff char */
-	unsigned char		regshift;		/* reg offset shift */
-	unsigned char		iotype;			/* io access style */
-	unsigned char		unused1;
-
-
-	unsigned int		read_status_mask;	/* driver specific */
-	unsigned int		ignore_status_mask;	/* driver specific */
-	struct sb_uart_info	*info;			/* pointer to parent info */
-	struct sb_uart_icount	icount;			/* statistics */
-
-	struct console		*cons;			/* struct console, if any */
-#ifdef CONFIG_SERIAL_CORE_CONSOLE
-	unsigned long		sysrq;			/* sysrq timeout */
-#endif
-
-	upf_t			flags;
-
-	unsigned int		mctrl;			/* current modem ctrl settings */
-	unsigned int		timeout;		/* character-based timeout */
-	unsigned int		type;			/* port type */
-	const struct sb_uart_ops	*ops;
-	unsigned int		custom_divisor;
-	unsigned int		line;			/* port index */
-	unsigned long		mapbase;		/* for ioremap */
-	struct device		*dev;			/* parent device */
-	unsigned char		hub6;			/* this should be in the 8250 driver */
-	unsigned char		unused[3];
-};
-
-#define mdmode			unused[2]
-#define MDMODE_ADDR		0x1
-#define MDMODE_ENABLE	0x2
-#define MDMODE_AUTO		0x4
-#define MDMODE_ADDRSEND	0x8
-
-struct sb_uart_state {
-	unsigned int		close_delay;		/* msec */
-	unsigned int		closing_wait;		/* msec */
-
-
-	int			count;
-	int			pm_state;
-	struct sb_uart_info	*info;
-	struct sb_uart_port	*port;
-
-	struct mutex		mutex;
-};
-
-typedef unsigned int  uif_t;
-
-struct sb_uart_info {
-	struct tty_struct	*tty;
-	struct circ_buf		xmit;
-	uif_t			flags;
-
-	int			blocked_open;
-
-	struct tasklet_struct	tlet;
-
-	wait_queue_head_t	open_wait;
-	wait_queue_head_t	delta_msr_wait;
-};
-
-
-struct module;
-struct tty_driver;
-
-struct uart_driver {
-	struct module		*owner;
-	const char		*driver_name;
-	const char		*dev_name;
-	int			 major;
-	int			 minor;
-	int			 nr;
-	struct console		*cons;
-
-	struct sb_uart_state	*state;
-        struct tty_driver               *tty_driver;
-};
-
-void sb_uart_write_wakeup(struct sb_uart_port *port)
-{
-    struct sb_uart_info *info = port->info;
-    tasklet_schedule(&info->tlet);
-}
-
-void sb_uart_update_timeout(struct sb_uart_port *port, unsigned int cflag,
-			 unsigned int baud)
-{
-    unsigned int bits;
-
-    switch (cflag & CSIZE)
-    {
-        case CS5:
-            bits = 7;
-            break;
-
-        case CS6:
-            bits = 8;
-            break;
-
-        case CS7:
-            bits = 9;
-            break;
-
-        default:
-            bits = 10;
-            break;
-    }
-
-    if (cflag & CSTOPB)
-    {
-        bits++;
-    }
-
-    if (cflag & PARENB)
-    {
-        bits++;
-    }
-
-    bits = bits * port->fifosize;
-
-    port->timeout = (HZ * bits) / baud + HZ/50;
-}
-unsigned int sb_uart_get_baud_rate(struct sb_uart_port *port, struct MP_TERMIOS *termios,
-				struct MP_TERMIOS *old, unsigned int min,
-				unsigned int max)
-{
-        unsigned int try, baud, altbaud = 38400;
-        upf_t flags = port->flags & UPF_SPD_MASK;
-
-        if (flags == UPF_SPD_HI)
-                altbaud = 57600;
-        if (flags == UPF_SPD_VHI)
-                altbaud = 115200;
-        if (flags == UPF_SPD_SHI)
-                altbaud = 230400;
-        if (flags == UPF_SPD_WARP)
-                altbaud = 460800;
-
-        for (try = 0; try < 2; try++) {
-
-                switch (termios->c_cflag & (CBAUD | CBAUDEX))
-                {
-                	case B921600    : baud = 921600;    break;
-                	case B460800    : baud = 460800;    break;
-                	case B230400    : baud = 230400;    break;
-                	case B115200    : baud = 115200;    break;
-                	case B57600     : baud = 57600;     break;
-                	case B38400     : baud = 38400;     break;
-                	case B19200     : baud = 19200;     break;
-                	case B9600      : baud = 9600;      break;
-                	case B4800      : baud = 4800;      break;
-                	case B2400      : baud = 2400;      break;
-                	case B1800      : baud = 1800;      break;
-                	case B1200      : baud = 1200;      break;
-                	case B600       : baud = 600;       break;
-                	case B300       : baud = 300;       break;
-                        case B200       : baud = 200;       break;
-                	case B150       : baud = 150;       break;
-                	case B134       : baud = 134;       break;
-                	case B110       : baud = 110;       break;
-                	case B75        : baud = 75;        break;
-                	case B50        : baud = 50;        break;
-                	default         : baud = 9600;      break;
-                }
-
-                if (baud == 38400)
-                        baud = altbaud;
-
-                if (baud == 0)
-                        baud = 9600;
-
-                if (baud >= min && baud <= max)
-                        return baud;
-
-                termios->c_cflag &= ~CBAUD;
-                if (old) {
-                        termios->c_cflag |= old->c_cflag & CBAUD;
-                        old = NULL;
-                        continue;
-                }
-
-                termios->c_cflag |= B9600;
-        }
-
-        return 0;
-}
-unsigned int sb_uart_get_divisor(struct sb_uart_port *port, unsigned int baud)
-{
-        unsigned int quot;
-
-        if (baud == 38400 && (port->flags & UPF_SPD_MASK) == UPF_SPD_CUST)
-                quot = port->custom_divisor;
-        else
-                quot = (port->uartclk + (8 * baud)) / (16 * baud);
-
-        return quot;
-}
-
-
-
-static inline int sb_uart_handle_break(struct sb_uart_port *port)
-{
-	struct sb_uart_info *info = port->info;
-
-	if (port->flags & UPF_SAK)
-		do_SAK(info->tty);
-	return 0;
-}
-
-static inline void sb_uart_handle_dcd_change(struct sb_uart_port *port, unsigned int status)
-{
-	struct sb_uart_info *info = port->info;
-
-	port->icount.dcd++;
-
-	if (info->flags & UIF_CHECK_CD) {
-		if (status)
-			wake_up_interruptible(&info->open_wait);
-		else if (info->tty)
-			tty_hangup(info->tty);
-	}
-}
-
-static inline void sb_uart_handle_cts_change(struct sb_uart_port *port, unsigned int status)
-{
-	struct sb_uart_info *info = port->info;
-	struct tty_struct *tty = info->tty;
-
-	port->icount.cts++;
-
-	if (info->flags & UIF_CTS_FLOW) {
-		if (tty->hw_stopped) {
-			if (status) {
-				tty->hw_stopped = 0;
-				port->ops->start_tx(port);
-				sb_uart_write_wakeup(port);
-			}
-		} else {
-			if (!status) {
-				tty->hw_stopped = 1;
-				port->ops->stop_tx(port);
-			}
-		}
-	}
-}
-
-
-
diff --git a/drivers/staging/sep/sep_crypto.c b/drivers/staging/sep/sep_crypto.c
index 7fc2675..965485f 100644
--- a/drivers/staging/sep/sep_crypto.c
+++ b/drivers/staging/sep/sep_crypto.c
@@ -112,7 +112,7 @@
  *	on what operation is to be done
  */
 static int sep_submit_work(struct workqueue_struct *work_queue,
-	void(*funct)(void *),
+	void (*funct)(void *),
 	void *data)
 {
 	struct sep_work_struct *sep_work;
diff --git a/drivers/staging/sep/sep_main.c b/drivers/staging/sep/sep_main.c
index 122614c..cbfc0cf 100644
--- a/drivers/staging/sep/sep_main.c
+++ b/drivers/staging/sep/sep_main.c
@@ -1266,9 +1266,8 @@
 	/* Check the number of pages locked - if not all then exit with error */
 	if (result != num_pages) {
 		dev_warn(&sep->pdev->dev,
-			"[PID%d] not all pages locked by get_user_pages, "
-			"result 0x%X, num_pages 0x%X\n",
-				current->pid, result, num_pages);
+			"[PID%d] not all pages locked by get_user_pages, result 0x%X, num_pages 0x%X\n",
+			current->pid, result, num_pages);
 		error = -ENOMEM;
 		goto end_function_with_error3;
 	}
@@ -1293,9 +1292,9 @@
 		lli_array[count].block_size = PAGE_SIZE;
 
 		dev_dbg(&sep->pdev->dev,
-			"[PID%d] lli_array[%x].bus_address is %08lx, "
-			"lli_array[%x].block_size is (hex) %x\n", current->pid,
-			count, (unsigned long)lli_array[count].bus_address,
+			"[PID%d] lli_array[%x].bus_address is %08lx, lli_array[%x].block_size is (hex) %x\n",
+			current->pid, count,
+			(unsigned long)lli_array[count].bus_address,
 			count, lli_array[count].block_size);
 	}
 
@@ -1314,8 +1313,7 @@
 			"[PID%d] After check if page 0 has all data\n",
 			current->pid);
 		dev_dbg(&sep->pdev->dev,
-			"[PID%d] lli_array[0].bus_address is (hex) %08lx, "
-			"lli_array[0].block_size is (hex) %x\n",
+			"[PID%d] lli_array[0].bus_address is (hex) %08lx, lli_array[0].block_size is (hex) %x\n",
 			current->pid,
 			(unsigned long)lli_array[0].bus_address,
 			lli_array[0].block_size);
@@ -1332,8 +1330,7 @@
 			"[PID%d] After last page size adjustment\n",
 			current->pid);
 		dev_dbg(&sep->pdev->dev,
-			"[PID%d] lli_array[%x].bus_address is (hex) %08lx, "
-			"lli_array[%x].block_size is (hex) %x\n",
+			"[PID%d] lli_array[%x].bus_address is (hex) %08lx, lli_array[%x].block_size is (hex) %x\n",
 			current->pid,
 			num_pages - 1,
 			(unsigned long)lli_array[num_pages - 1].bus_address,
@@ -1449,8 +1446,7 @@
 		start_page += PAGE_SIZE;
 
 		dev_dbg(&sep->pdev->dev,
-			"[PID%d] lli_array[%x].bus_address is %08lx, "
-			"lli_array[%x].block_size is (hex) %x\n",
+			"[PID%d] lli_array[%x].bus_address is %08lx, lli_array[%x].block_size is (hex) %x\n",
 			current->pid,
 			count, (unsigned long)lli_array[count].bus_address,
 			count, lli_array[count].block_size);
@@ -1469,8 +1465,7 @@
 
 	dev_dbg(&sep->pdev->dev,
 		"[PID%d] After check if page 0 has all data\n"
-		"lli_array[0].bus_address is (hex) %08lx, "
-		"lli_array[0].block_size is (hex) %x\n",
+		"lli_array[0].bus_address is (hex) %08lx, lli_array[0].block_size is (hex) %x\n",
 		current->pid,
 		(unsigned long)lli_array[0].bus_address,
 		lli_array[0].block_size);
@@ -1484,8 +1479,7 @@
 
 		dev_dbg(&sep->pdev->dev,
 			"[PID%d] After last page size adjustment\n"
-			"lli_array[%x].bus_address is (hex) %08lx, "
-			"lli_array[%x].block_size is (hex) %x\n",
+			"lli_array[%x].bus_address is (hex) %08lx, lli_array[%x].block_size is (hex) %x\n",
 			current->pid, num_pages - 1,
 			(unsigned long)lli_array[num_pages - 1].bus_address,
 			num_pages - 1,
@@ -1745,9 +1739,8 @@
 
 	while ((unsigned long) lli_table_ptr->bus_address != 0xffffffff) {
 		dev_dbg(&sep->pdev->dev,
-			"[PID%d] lli table %08lx, "
-			"table_data_size is (hex) %lx\n",
-				current->pid, table_count, table_data_size);
+			"[PID%d] lli table %08lx, table_data_size is (hex) %lx\n",
+			current->pid, table_count, table_data_size);
 		dev_dbg(&sep->pdev->dev,
 			"[PID%d] num_table_entries is (hex) %lx\n",
 				current->pid, num_table_entries);
@@ -1762,8 +1755,8 @@
 				(unsigned long) lli_table_ptr);
 
 			dev_dbg(&sep->pdev->dev,
-				"[PID%d] phys address is %08lx "
-				"block size is (hex) %x\n", current->pid,
+				"[PID%d] phys address is %08lx block size is (hex) %x\n",
+				current->pid,
 				(unsigned long)lli_table_ptr->bus_address,
 				lli_table_ptr->block_size);
 		}
@@ -1772,14 +1765,12 @@
 		lli_table_ptr--;
 
 		dev_dbg(&sep->pdev->dev,
-			"[PID%d] phys lli_table_ptr->block_size "
-			"is (hex) %x\n",
+			"[PID%d] phys lli_table_ptr->block_size is (hex) %x\n",
 			current->pid,
 			lli_table_ptr->block_size);
 
 		dev_dbg(&sep->pdev->dev,
-			"[PID%d] phys lli_table_ptr->physical_address "
-			"is %08lx\n",
+			"[PID%d] phys lli_table_ptr->physical_address is %08lx\n",
 			current->pid,
 			(unsigned long)lli_table_ptr->bus_address);
 
@@ -1788,13 +1779,11 @@
 		num_table_entries = (lli_table_ptr->block_size >> 24) & 0xff;
 
 		dev_dbg(&sep->pdev->dev,
-			"[PID%d] phys table_data_size is "
-			"(hex) %lx num_table_entries is"
-			" %lx bus_address is%lx\n",
-				current->pid,
-				table_data_size,
-				num_table_entries,
-				(unsigned long)lli_table_ptr->bus_address);
+			"[PID%d] phys table_data_size is (hex) %lx num_table_entries is %lx bus_address is%lx\n",
+			current->pid,
+			table_data_size,
+			num_table_entries,
+			(unsigned long)lli_table_ptr->bus_address);
 
 		if ((unsigned long)lli_table_ptr->bus_address != 0xffffffff)
 			lli_table_ptr = (struct sep_lli_entry *)
@@ -2244,14 +2233,12 @@
 			table_data_size = out_table_data_size;
 
 		dev_dbg(&sep->pdev->dev,
-			"[PID%d] construct tables from lli"
-			" in_table_data_size is (hex) %x\n", current->pid,
-			in_table_data_size);
+			"[PID%d] construct tables from lli in_table_data_size is (hex) %x\n",
+			current->pid, in_table_data_size);
 
 		dev_dbg(&sep->pdev->dev,
-			"[PID%d] construct tables from lli"
-			"out_table_data_size is (hex) %x\n", current->pid,
-			out_table_data_size);
+			"[PID%d] construct tables from lli out_table_data_size is (hex) %x\n",
+			current->pid, out_table_data_size);
 
 		/* Construct input lli table */
 		sep_build_lli_table(sep, &lli_in_array[current_in_entry],
@@ -2316,8 +2303,7 @@
 				info_in_entry_ptr->block_size);
 
 			dev_dbg(&sep->pdev->dev,
-				"[PID%d] output lli_table_out_ptr:"
-				"%08lx  %08x\n",
+				"[PID%d] output lli_table_out_ptr: %08lx  %08x\n",
 				current->pid,
 				(unsigned long)info_out_entry_ptr->bus_address,
 				info_out_entry_ptr->block_size);
@@ -2446,8 +2432,8 @@
 				dma_ctx);
 		if (error) {
 			dev_warn(&sep->pdev->dev,
-				"[PID%d] sep_lock_kernel_pages for input "
-				"virtual buffer failed\n", current->pid);
+				"[PID%d] sep_lock_kernel_pages for input virtual buffer failed\n",
+				current->pid);
 
 			goto end_function;
 		}
@@ -2460,8 +2446,8 @@
 
 		if (error) {
 			dev_warn(&sep->pdev->dev,
-				"[PID%d] sep_lock_kernel_pages for output "
-				"virtual buffer failed\n", current->pid);
+				"[PID%d] sep_lock_kernel_pages for output virtual buffer failed\n",
+				current->pid);
 
 			goto end_function_free_lli_in;
 		}
@@ -2476,8 +2462,8 @@
 				dma_ctx);
 		if (error) {
 			dev_warn(&sep->pdev->dev,
-				"[PID%d] sep_lock_user_pages for input "
-				"virtual buffer failed\n", current->pid);
+				"[PID%d] sep_lock_user_pages for input virtual buffer failed\n",
+				current->pid);
 
 			goto end_function;
 		}
@@ -2491,8 +2477,7 @@
 				SEP_DRIVER_OUT_FLAG, dma_ctx);
 			if (error) {
 				dev_warn(&sep->pdev->dev,
-					"[PID%d] secure dma table setup "
-					" for output virtual buffer failed\n",
+					"[PID%d] secure dma table setup for output virtual buffer failed\n",
 					current->pid);
 
 				goto end_function_free_lli_in;
@@ -2512,8 +2497,7 @@
 
 			if (error) {
 				dev_warn(&sep->pdev->dev,
-					"[PID%d] sep_lock_user_pages"
-					" for output virtual buffer failed\n",
+					"[PID%d] sep_lock_user_pages for output virtual buffer failed\n",
 					current->pid);
 
 				goto end_function_free_lli_in;
@@ -2826,8 +2810,7 @@
 
 	if (error) {
 		dev_warn(&sep->pdev->dev,
-			"prepare DMA table call failed "
-			"from prepare DCB call\n");
+			"prepare DMA table call failed from prepare DCB call\n");
 		goto end_function_error;
 	}
 
@@ -2889,7 +2872,8 @@
 		 * Go over each DCB and see if
 		 * tail pointer must be updated
 		 */
-		for (i = 0; i < (*dma_ctx)->nr_dcb_creat; i++, dcb_table_ptr++) {
+		for (i = 0; i < (*dma_ctx)->nr_dcb_creat;
+		     i++, dcb_table_ptr++) {
 			if (dcb_table_ptr->out_vr_tail_pt) {
 				pt_hold = (unsigned long)dcb_table_ptr->
 					out_vr_tail_pt;
@@ -3762,8 +3746,7 @@
 
 	if (actual_count != count_user) {
 		dev_warn(&sep->pdev->dev,
-			 "[PID%d] inconsistent message "
-			 "sizes 0x%08zX vs 0x%08zX\n",
+			 "[PID%d] inconsistent message sizes 0x%08zX vs 0x%08zX\n",
 			 current->pid, actual_count, count_user);
 		error = -EMSGSIZE;
 		goto end_function;
diff --git a/drivers/staging/slicoss/slic.h b/drivers/staging/slicoss/slic.h
index 4c7822b..702902c 100644
--- a/drivers/staging/slicoss/slic.h
+++ b/drivers/staging/slicoss/slic.h
@@ -464,9 +464,12 @@
 	/*
 	*  SLIC Handles
 	*/
-	struct slic_handle slic_handles[SLIC_CMDQ_MAXCMDS+1]; /* Object handles*/
-	struct slic_handle *pfree_slic_handles;          /* Free object handles*/
-	struct slic_spinlock     handle_lock;           /* Object handle list lock*/
+	/* Object handles*/
+	struct slic_handle slic_handles[SLIC_CMDQ_MAXCMDS+1];
+	/* Free object handles*/
+	struct slic_handle *pfree_slic_handles;
+	/* Object handle list lock*/
+	struct slic_spinlock     handle_lock;
 	ushort              slic_handle_ix;
 
 	u32             xmitq_full;
diff --git a/drivers/staging/slicoss/slicoss.c b/drivers/staging/slicoss/slicoss.c
index e0de497..758c4ef 100644
--- a/drivers/staging/slicoss/slicoss.c
+++ b/drivers/staging/slicoss/slicoss.c
@@ -1830,7 +1830,7 @@
 #endif
 
 	seq_printf(seq, "driver_version           : %s\n", slic_proc_version);
-	seq_puts(seq, "Microcode versions:           \n");
+	seq_puts(seq, "Microcode versions:\n");
 	seq_printf(seq, "    Gigabit (gb)         : %s %s\n",
 		    MOJAVE_UCODE_VERS_STRING, MOJAVE_UCODE_VERS_DATE);
 	seq_printf(seq, "    Gigabit Receiver     : %s %s\n",
@@ -1917,16 +1917,14 @@
 
 			if (config->OEMFruFormat == VENDOR4_FRU_FORMAT) {
 				seq_printf(seq,
-					    "Serial   #               : "
-					    "%c%c%c%c%c%c%c%c%c%c%c%c\n",
+					    "Serial   #               : %c%c%c%c%c%c%c%c%c%c%c%c\n",
 					    fru[8], fru[9], fru[10],
 					    fru[11], fru[12], fru[13],
 					    fru[16], fru[17], fru[18],
 					    fru[19], fru[20], fru[21]);
 			} else {
 				seq_printf(seq,
-					    "Serial   #               : "
-					    "%c%c%c%c%c%c%c%c%c%c%c%c%c%c\n",
+					    "Serial   #               : %c%c%c%c%c%c%c%c%c%c%c%c%c%c\n",
 					    fru[8], fru[9], fru[10],
 					    fru[11], fru[12], fru[13],
 					    fru[14], fru[15], fru[16],
@@ -1974,8 +1972,7 @@
 		{
 			seq_puts(seq, "FRU Information:\n");
 			seq_printf(seq,
-				    "    Part     #           : "
-				    "%c%c%c%c%c%c%c%c\n",
+				    "    Part     #           : %c%c%c%c%c%c%c%c\n",
 				    oemfru[0], oemfru[1], oemfru[2],
 				    oemfru[3], oemfru[4], oemfru[5],
 				    oemfru[6], oemfru[7]);
@@ -2002,20 +1999,17 @@
 		{
 			seq_puts(seq, "FRU Information:\n");
 			seq_printf(seq,
-				    "    FRU Number           : "
-				    "%c%c%c%c%c%c%c%c\n",
+				    "    FRU Number           : %c%c%c%c%c%c%c%c\n",
 				    oemfru[0], oemfru[1], oemfru[2],
 				    oemfru[3], oemfru[4], oemfru[5],
 				    oemfru[6], oemfru[7]);
 			seq_sprintf(seq,
-				    "    Part Number          : "
-				    "%c%c%c%c%c%c%c%c\n",
+				    "    Part Number          : %c%c%c%c%c%c%c%c\n",
 				    oemfru[8], oemfru[9], oemfru[10],
 				    oemfru[11], oemfru[12], oemfru[13],
 				    oemfru[14], oemfru[15]);
 			seq_printf(seq,
-				    "    EC Level             : "
-				    "%c%c%c%c%c%c%c%c\n",
+				    "    EC Level             : %c%c%c%c%c%c%c%c\n",
 				    oemfru[16], oemfru[17], oemfru[18],
 				    oemfru[19], oemfru[20], oemfru[21],
 				    oemfru[22], oemfru[23]);
@@ -2412,8 +2406,7 @@
 		switch (status) {
 		case XMIT_FAIL_LINK_STATE:
 			dev_err(&adapter->netdev->dev,
-				"reject xmit skb[%p: %x] linkstate[%s] "
-				"adapter[%s:%d] card[%s:%d]\n",
+				"reject xmit skb[%p: %x] linkstate[%s] adapter[%s:%d] card[%s:%d]\n",
 				skb, skb->pkt_type,
 				SLIC_LINKSTATE(adapter->linkstate),
 				SLIC_ADAPTER_STATE(adapter->state),
@@ -2428,8 +2421,7 @@
 			break;
 		case XMIT_FAIL_HOSTCMD_FAIL:
 			dev_err(&adapter->netdev->dev,
-				"xmit_start skb[%p] type[%x] No host commands "
-				"available\n", skb, skb->pkt_type);
+				"xmit_start skb[%p] type[%x] No host commands available\n", skb, skb->pkt_type);
 			break;
 		}
 	}
@@ -2642,8 +2634,7 @@
 				}
 			} else if (isr & ISR_XDROP) {
 				dev_err(&dev->dev,
-						"isr & ISR_ERR [%x] "
-						"ISR_XDROP \n", isr);
+						"isr & ISR_ERR [%x] ISR_XDROP\n", isr);
 			} else {
 				dev_err(&dev->dev,
 						"isr & ISR_ERR [%x]\n",
@@ -3269,8 +3260,7 @@
 
 		if (!peeprom) {
 			dev_err(&adapter->pcidev->dev,
-				"eeprom read failed to get memory "
-				"bus %d slot %d\n", adapter->busnumber,
+				"eeprom read failed to get memory bus %d slot %d\n", adapter->busnumber,
 				adapter->slotnumber);
 			return -ENOMEM;
 		} else {
diff --git a/drivers/staging/sm7xxfb/Kconfig b/drivers/staging/sm7xxfb/Kconfig
deleted file mode 100644
index e2922ae..0000000
--- a/drivers/staging/sm7xxfb/Kconfig
+++ /dev/null
@@ -1,13 +0,0 @@
-config FB_SM7XX
-	tristate "Silicon Motion SM7XX framebuffer support"
-	depends on FB && PCI
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	help
-	  Frame buffer driver for the Silicon Motion SM710, SM712, SM721
-	  and SM722 chips.
-
-	  This driver is also available as a module. The module will be
-	  called sm7xxfb. If you want to compile it as a module, say M
-	  here and read <file:Documentation/kbuild/modules.txt>.
diff --git a/drivers/staging/sm7xxfb/Makefile b/drivers/staging/sm7xxfb/Makefile
deleted file mode 100644
index 48f471cf..0000000
--- a/drivers/staging/sm7xxfb/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-obj-$(CONFIG_FB_SM7XX) += sm7xxfb.o
diff --git a/drivers/staging/sm7xxfb/TODO b/drivers/staging/sm7xxfb/TODO
deleted file mode 100644
index 1fcead5..0000000
--- a/drivers/staging/sm7xxfb/TODO
+++ /dev/null
@@ -1,9 +0,0 @@
-TODO:
-- Dual head support
-- 2D acceleration support
-- use kernel coding style
-- refine the code and remove unused code
-- move it to drivers/video/sm7xxfb.c
-
-Please send any patches to Greg Kroah-Hartman <greg@kroah.com> and
-Teddy Wang <teddy.wang@siliconmotion.com.cn>.
diff --git a/drivers/staging/sm7xxfb/sm7xx.h b/drivers/staging/sm7xxfb/sm7xx.h
deleted file mode 100644
index 8599861..0000000
--- a/drivers/staging/sm7xxfb/sm7xx.h
+++ /dev/null
@@ -1,779 +0,0 @@
-/*
- * Silicon Motion SM712 frame buffer device
- *
- * Copyright (C) 2006 Silicon Motion Technology Corp.
- * Authors:	Ge Wang, gewang@siliconmotion.com
- *		Boyod boyod.yang@siliconmotion.com.cn
- *
- * Copyright (C) 2009 Lemote, Inc.
- * Author: Wu Zhangjin, wuzhangjin@gmail.com
- *
- *  This file is subject to the terms and conditions of the GNU General Public
- *  License. See the file COPYING in the main directory of this archive for
- *  more details.
- */
-
-#define NR_PALETTE        256
-
-#define FB_ACCEL_SMI_LYNX 88
-
-#define SCREEN_X_RES      1024
-#define SCREEN_Y_RES      600
-#define SCREEN_BPP        16
-
-/*Assume SM712 graphics chip has 4MB VRAM */
-#define SM712_VIDEOMEMORYSIZE	  0x00400000
-/*Assume SM722 graphics chip has 8MB VRAM */
-#define SM722_VIDEOMEMORYSIZE	  0x00800000
-
-#define dac_reg	(0x3c8)
-#define dac_val	(0x3c9)
-
-extern void __iomem *smtc_RegBaseAddress;
-#define smtc_mmiowb(dat, reg)	writeb(dat, smtc_RegBaseAddress + reg)
-#define smtc_mmioww(dat, reg)	writew(dat, smtc_RegBaseAddress + reg)
-#define smtc_mmiowl(dat, reg)	writel(dat, smtc_RegBaseAddress + reg)
-
-#define smtc_mmiorb(reg)	readb(smtc_RegBaseAddress + reg)
-#define smtc_mmiorw(reg)	readw(smtc_RegBaseAddress + reg)
-#define smtc_mmiorl(reg)	readl(smtc_RegBaseAddress + reg)
-
-#define SIZE_SR00_SR04      (0x04 - 0x00 + 1)
-#define SIZE_SR10_SR24      (0x24 - 0x10 + 1)
-#define SIZE_SR30_SR75      (0x75 - 0x30 + 1)
-#define SIZE_SR80_SR93      (0x93 - 0x80 + 1)
-#define SIZE_SRA0_SRAF      (0xAF - 0xA0 + 1)
-#define SIZE_GR00_GR08      (0x08 - 0x00 + 1)
-#define SIZE_AR00_AR14      (0x14 - 0x00 + 1)
-#define SIZE_CR00_CR18      (0x18 - 0x00 + 1)
-#define SIZE_CR30_CR4D      (0x4D - 0x30 + 1)
-#define SIZE_CR90_CRA7      (0xA7 - 0x90 + 1)
-#define SIZE_VPR		(0x6C + 1)
-#define SIZE_DPR		(0x44 + 1)
-
-static inline void smtc_crtcw(int reg, int val)
-{
-	smtc_mmiowb(reg, 0x3d4);
-	smtc_mmiowb(val, 0x3d5);
-}
-
-static inline unsigned int smtc_crtcr(int reg)
-{
-	smtc_mmiowb(reg, 0x3d4);
-	return smtc_mmiorb(0x3d5);
-}
-
-static inline void smtc_grphw(int reg, int val)
-{
-	smtc_mmiowb(reg, 0x3ce);
-	smtc_mmiowb(val, 0x3cf);
-}
-
-static inline unsigned int smtc_grphr(int reg)
-{
-	smtc_mmiowb(reg, 0x3ce);
-	return smtc_mmiorb(0x3cf);
-}
-
-static inline void smtc_attrw(int reg, int val)
-{
-	smtc_mmiorb(0x3da);
-	smtc_mmiowb(reg, 0x3c0);
-	smtc_mmiorb(0x3c1);
-	smtc_mmiowb(val, 0x3c0);
-}
-
-static inline void smtc_seqw(int reg, int val)
-{
-	smtc_mmiowb(reg, 0x3c4);
-	smtc_mmiowb(val, 0x3c5);
-}
-
-static inline unsigned int smtc_seqr(int reg)
-{
-	smtc_mmiowb(reg, 0x3c4);
-	return smtc_mmiorb(0x3c5);
-}
-
-/* The next structure holds all information relevant for a specific video mode.
- */
-
-struct ModeInit {
-	int mmSizeX;
-	int mmSizeY;
-	int bpp;
-	int hz;
-	unsigned char Init_MISC;
-	unsigned char Init_SR00_SR04[SIZE_SR00_SR04];
-	unsigned char Init_SR10_SR24[SIZE_SR10_SR24];
-	unsigned char Init_SR30_SR75[SIZE_SR30_SR75];
-	unsigned char Init_SR80_SR93[SIZE_SR80_SR93];
-	unsigned char Init_SRA0_SRAF[SIZE_SRA0_SRAF];
-	unsigned char Init_GR00_GR08[SIZE_GR00_GR08];
-	unsigned char Init_AR00_AR14[SIZE_AR00_AR14];
-	unsigned char Init_CR00_CR18[SIZE_CR00_CR18];
-	unsigned char Init_CR30_CR4D[SIZE_CR30_CR4D];
-	unsigned char Init_CR90_CRA7[SIZE_CR90_CRA7];
-};
-
-/**********************************************************************
-			 SM712 Mode table.
- **********************************************************************/
-struct ModeInit VGAMode[] = {
-	{
-	 /*  mode#0: 640 x 480  16Bpp  60Hz */
-	 640, 480, 16, 60,
-	 /*  Init_MISC */
-	 0xE3,
-	 {			/*  Init_SR0_SR4 */
-	  0x03, 0x01, 0x0F, 0x00, 0x0E,
-	  },
-	 {			/*  Init_SR10_SR24 */
-	  0xFF, 0xBE, 0xEF, 0xFF, 0x00, 0x0E, 0x17, 0x2C,
-	  0x99, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	  0xC4, 0x30, 0x02, 0x01, 0x01,
-	  },
-	 {			/*  Init_SR30_SR75 */
-	  0x32, 0x03, 0xA0, 0x09, 0xC0, 0x32, 0x32, 0x32,
-	  0x32, 0x32, 0x32, 0x32, 0x00, 0x00, 0x03, 0xFF,
-	  0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
-	  0x20, 0x0C, 0x44, 0x20, 0x00, 0x32, 0x32, 0x32,
-	  0x04, 0x24, 0x63, 0x4F, 0x52, 0x0B, 0xDF, 0xEA,
-	  0x04, 0x50, 0x19, 0x32, 0x32, 0x00, 0x00, 0x32,
-	  0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00,
-	  0x50, 0x03, 0x74, 0x14, 0x07, 0x82, 0x07, 0x04,
-	  0x00, 0x45, 0x30, 0x30, 0x40, 0x30,
-	  },
-	 {			/*  Init_SR80_SR93 */
-	  0xFF, 0x07, 0x00, 0x6F, 0x7F, 0x7F, 0xFF, 0x32,
-	  0xF7, 0x00, 0x00, 0x00, 0xEF, 0xFF, 0x32, 0x32,
-	  0x00, 0x00, 0x00, 0x00,
-	  },
-	 {			/*  Init_SRA0_SRAF */
-	  0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED,
-	  0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xFF, 0xDF,
-	  },
-	 {			/*  Init_GR00_GR08 */
-	  0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
-	  0xFF,
-	  },
-	 {			/*  Init_AR00_AR14 */
-	  0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-	  0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
-	  0x41, 0x00, 0x0F, 0x00, 0x00,
-	  },
-	 {			/*  Init_CR00_CR18 */
-	  0x5F, 0x4F, 0x4F, 0x00, 0x53, 0x1F, 0x0B, 0x3E,
-	  0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	  0xEA, 0x0C, 0xDF, 0x50, 0x40, 0xDF, 0x00, 0xE3,
-	  0xFF,
-	  },
-	 {			/*  Init_CR30_CR4D */
-	  0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x03, 0x20,
-	  0x00, 0x00, 0x00, 0x40, 0x00, 0xE7, 0xFF, 0xFD,
-	  0x5F, 0x4F, 0x00, 0x54, 0x00, 0x0B, 0xDF, 0x00,
-	  0xEA, 0x0C, 0x2E, 0x00, 0x4F, 0xDF,
-	  },
-	 {			/*  Init_CR90_CRA7 */
-	  0x56, 0xDD, 0x5E, 0xEA, 0x87, 0x44, 0x8F, 0x55,
-	  0x0A, 0x8F, 0x55, 0x0A, 0x00, 0x00, 0x18, 0x00,
-	  0x11, 0x10, 0x0B, 0x0A, 0x0A, 0x0A, 0x0A, 0x00,
-	  },
-	 },
-	{
-	 /*  mode#1: 640 x 480  24Bpp  60Hz */
-	 640, 480, 24, 60,
-	 /*  Init_MISC */
-	 0xE3,
-	 {			/*  Init_SR0_SR4 */
-	  0x03, 0x01, 0x0F, 0x00, 0x0E,
-	  },
-	 {			/*  Init_SR10_SR24 */
-	  0xFF, 0xBE, 0xEF, 0xFF, 0x00, 0x0E, 0x17, 0x2C,
-	  0x99, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	  0xC4, 0x30, 0x02, 0x01, 0x01,
-	  },
-	 {			/*  Init_SR30_SR75 */
-	  0x32, 0x03, 0xA0, 0x09, 0xC0, 0x32, 0x32, 0x32,
-	  0x32, 0x32, 0x32, 0x32, 0x00, 0x00, 0x03, 0xFF,
-	  0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
-	  0x20, 0x0C, 0x44, 0x20, 0x00, 0x32, 0x32, 0x32,
-	  0x04, 0x24, 0x63, 0x4F, 0x52, 0x0B, 0xDF, 0xEA,
-	  0x04, 0x50, 0x19, 0x32, 0x32, 0x00, 0x00, 0x32,
-	  0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00,
-	  0x50, 0x03, 0x74, 0x14, 0x07, 0x82, 0x07, 0x04,
-	  0x00, 0x45, 0x30, 0x30, 0x40, 0x30,
-	  },
-	 {			/*  Init_SR80_SR93 */
-	  0xFF, 0x07, 0x00, 0x6F, 0x7F, 0x7F, 0xFF, 0x32,
-	  0xF7, 0x00, 0x00, 0x00, 0xEF, 0xFF, 0x32, 0x32,
-	  0x00, 0x00, 0x00, 0x00,
-	  },
-	 {			/*  Init_SRA0_SRAF */
-	  0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED,
-	  0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xFF, 0xDF,
-	  },
-	 {			/*  Init_GR00_GR08 */
-	  0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
-	  0xFF,
-	  },
-	 {			/*  Init_AR00_AR14 */
-	  0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-	  0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
-	  0x41, 0x00, 0x0F, 0x00, 0x00,
-	  },
-	 {			/*  Init_CR00_CR18 */
-	  0x5F, 0x4F, 0x4F, 0x00, 0x53, 0x1F, 0x0B, 0x3E,
-	  0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	  0xEA, 0x0C, 0xDF, 0x50, 0x40, 0xDF, 0x00, 0xE3,
-	  0xFF,
-	  },
-	 {			/*  Init_CR30_CR4D */
-	  0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x03, 0x20,
-	  0x00, 0x00, 0x00, 0x40, 0x00, 0xE7, 0xFF, 0xFD,
-	  0x5F, 0x4F, 0x00, 0x54, 0x00, 0x0B, 0xDF, 0x00,
-	  0xEA, 0x0C, 0x2E, 0x00, 0x4F, 0xDF,
-	  },
-	 {			/*  Init_CR90_CRA7 */
-	  0x56, 0xDD, 0x5E, 0xEA, 0x87, 0x44, 0x8F, 0x55,
-	  0x0A, 0x8F, 0x55, 0x0A, 0x00, 0x00, 0x18, 0x00,
-	  0x11, 0x10, 0x0B, 0x0A, 0x0A, 0x0A, 0x0A, 0x00,
-	  },
-	 },
-	{
-	 /*  mode#0: 640 x 480  32Bpp  60Hz */
-	 640, 480, 32, 60,
-	 /*  Init_MISC */
-	 0xE3,
-	 {			/*  Init_SR0_SR4 */
-	  0x03, 0x01, 0x0F, 0x00, 0x0E,
-	  },
-	 {			/*  Init_SR10_SR24 */
-	  0xFF, 0xBE, 0xEF, 0xFF, 0x00, 0x0E, 0x17, 0x2C,
-	  0x99, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	  0xC4, 0x30, 0x02, 0x01, 0x01,
-	  },
-	 {			/*  Init_SR30_SR75 */
-	  0x32, 0x03, 0xA0, 0x09, 0xC0, 0x32, 0x32, 0x32,
-	  0x32, 0x32, 0x32, 0x32, 0x00, 0x00, 0x03, 0xFF,
-	  0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
-	  0x20, 0x0C, 0x44, 0x20, 0x00, 0x32, 0x32, 0x32,
-	  0x04, 0x24, 0x63, 0x4F, 0x52, 0x0B, 0xDF, 0xEA,
-	  0x04, 0x50, 0x19, 0x32, 0x32, 0x00, 0x00, 0x32,
-	  0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00,
-	  0x50, 0x03, 0x74, 0x14, 0x07, 0x82, 0x07, 0x04,
-	  0x00, 0x45, 0x30, 0x30, 0x40, 0x30,
-	  },
-	 {			/*  Init_SR80_SR93 */
-	  0xFF, 0x07, 0x00, 0x6F, 0x7F, 0x7F, 0xFF, 0x32,
-	  0xF7, 0x00, 0x00, 0x00, 0xEF, 0xFF, 0x32, 0x32,
-	  0x00, 0x00, 0x00, 0x00,
-	  },
-	 {			/*  Init_SRA0_SRAF */
-	  0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED,
-	  0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xFF, 0xDF,
-	  },
-	 {			/*  Init_GR00_GR08 */
-	  0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
-	  0xFF,
-	  },
-	 {			/*  Init_AR00_AR14 */
-	  0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-	  0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
-	  0x41, 0x00, 0x0F, 0x00, 0x00,
-	  },
-	 {			/*  Init_CR00_CR18 */
-	  0x5F, 0x4F, 0x4F, 0x00, 0x53, 0x1F, 0x0B, 0x3E,
-	  0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	  0xEA, 0x0C, 0xDF, 0x50, 0x40, 0xDF, 0x00, 0xE3,
-	  0xFF,
-	  },
-	 {			/*  Init_CR30_CR4D */
-	  0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x03, 0x20,
-	  0x00, 0x00, 0x00, 0x40, 0x00, 0xE7, 0xFF, 0xFD,
-	  0x5F, 0x4F, 0x00, 0x54, 0x00, 0x0B, 0xDF, 0x00,
-	  0xEA, 0x0C, 0x2E, 0x00, 0x4F, 0xDF,
-	  },
-	 {			/*  Init_CR90_CRA7 */
-	  0x56, 0xDD, 0x5E, 0xEA, 0x87, 0x44, 0x8F, 0x55,
-	  0x0A, 0x8F, 0x55, 0x0A, 0x00, 0x00, 0x18, 0x00,
-	  0x11, 0x10, 0x0B, 0x0A, 0x0A, 0x0A, 0x0A, 0x00,
-	  },
-	 },
-
-	{			/*  mode#2: 800 x 600  16Bpp  60Hz */
-	 800, 600, 16, 60,
-	 /*  Init_MISC */
-	 0x2B,
-	 {			/*  Init_SR0_SR4 */
-	  0x03, 0x01, 0x0F, 0x03, 0x0E,
-	  },
-	 {			/*  Init_SR10_SR24 */
-	  0xFF, 0xBE, 0xEE, 0xFF, 0x00, 0x0E, 0x17, 0x2C,
-	  0x99, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
-	  0xC4, 0x30, 0x02, 0x01, 0x01,
-	  },
-	 {			/*  Init_SR30_SR75 */
-	  0x34, 0x03, 0x20, 0x09, 0xC0, 0x24, 0x24, 0x24,
-	  0x24, 0x24, 0x24, 0x24, 0x00, 0x00, 0x03, 0xFF,
-	  0x00, 0xFC, 0x00, 0x00, 0x20, 0x38, 0x00, 0xFC,
-	  0x20, 0x0C, 0x44, 0x20, 0x00, 0x24, 0x24, 0x24,
-	  0x04, 0x48, 0x83, 0x63, 0x68, 0x72, 0x57, 0x58,
-	  0x04, 0x55, 0x59, 0x24, 0x24, 0x00, 0x00, 0x24,
-	  0x01, 0x80, 0x7A, 0x1A, 0x1A, 0x00, 0x00, 0x00,
-	  0x50, 0x03, 0x74, 0x14, 0x1C, 0x85, 0x35, 0x13,
-	  0x02, 0x45, 0x30, 0x35, 0x40, 0x20,
-	  },
-	 {			/*  Init_SR80_SR93 */
-	  0x00, 0x00, 0x00, 0x6F, 0x7F, 0x7F, 0xFF, 0x24,
-	  0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x24, 0x24,
-	  0x00, 0x00, 0x00, 0x00,
-	  },
-	 {			/*  Init_SRA0_SRAF */
-	  0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED,
-	  0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xBF, 0xDF,
-	  },
-	 {			/*  Init_GR00_GR08 */
-	  0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
-	  0xFF,
-	  },
-	 {			/*  Init_AR00_AR14 */
-	  0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-	  0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
-	  0x41, 0x00, 0x0F, 0x00, 0x00,
-	  },
-	 {			/*  Init_CR00_CR18 */
-	  0x7F, 0x63, 0x63, 0x00, 0x68, 0x18, 0x72, 0xF0,
-	  0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	  0x58, 0x0C, 0x57, 0x64, 0x40, 0x57, 0x00, 0xE3,
-	  0xFF,
-	  },
-	 {			/*  Init_CR30_CR4D */
-	  0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x03, 0x20,
-	  0x00, 0x00, 0x00, 0x40, 0x00, 0xE7, 0xBF, 0xFD,
-	  0x7F, 0x63, 0x00, 0x69, 0x18, 0x72, 0x57, 0x00,
-	  0x58, 0x0C, 0xE0, 0x20, 0x63, 0x57,
-	  },
-	 {			/*  Init_CR90_CRA7 */
-	  0x56, 0x4B, 0x5E, 0x55, 0x86, 0x9D, 0x8E, 0xAA,
-	  0xDB, 0x2A, 0xDF, 0x33, 0x00, 0x00, 0x18, 0x00,
-	  0x20, 0x1F, 0x1A, 0x19, 0x0F, 0x0F, 0x0F, 0x00,
-	  },
-	 },
-	{			/*  mode#3: 800 x 600  24Bpp  60Hz */
-	 800, 600, 24, 60,
-	 0x2B,
-	 {			/*  Init_SR0_SR4 */
-	  0x03, 0x01, 0x0F, 0x03, 0x0E,
-	  },
-	 {			/*  Init_SR10_SR24 */
-	  0xFF, 0xBE, 0xEE, 0xFF, 0x00, 0x0E, 0x17, 0x2C,
-	  0x99, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	  0xC4, 0x30, 0x02, 0x01, 0x01,
-	  },
-	 {			/*  Init_SR30_SR75 */
-	  0x36, 0x03, 0x20, 0x09, 0xC0, 0x36, 0x36, 0x36,
-	  0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x03, 0xFF,
-	  0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
-	  0x20, 0x0C, 0x44, 0x20, 0x00, 0x36, 0x36, 0x36,
-	  0x04, 0x48, 0x83, 0x63, 0x68, 0x72, 0x57, 0x58,
-	  0x04, 0x55, 0x59, 0x36, 0x36, 0x00, 0x00, 0x36,
-	  0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00,
-	  0x50, 0x03, 0x74, 0x14, 0x1C, 0x85, 0x35, 0x13,
-	  0x02, 0x45, 0x30, 0x30, 0x40, 0x20,
-	  },
-	 {			/*  Init_SR80_SR93 */
-	  0xFF, 0x07, 0x00, 0x6F, 0x7F, 0x7F, 0xFF, 0x36,
-	  0xF7, 0x00, 0x00, 0x00, 0xEF, 0xFF, 0x36, 0x36,
-	  0x00, 0x00, 0x00, 0x00,
-	  },
-	 {			/*  Init_SRA0_SRAF */
-	  0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED,
-	  0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xBF, 0xDF,
-	  },
-	 {			/*  Init_GR00_GR08 */
-	  0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
-	  0xFF,
-	  },
-	 {			/*  Init_AR00_AR14 */
-	  0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-	  0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
-	  0x41, 0x00, 0x0F, 0x00, 0x00,
-	  },
-	 {			/*  Init_CR00_CR18 */
-	  0x7F, 0x63, 0x63, 0x00, 0x68, 0x18, 0x72, 0xF0,
-	  0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	  0x58, 0x0C, 0x57, 0x64, 0x40, 0x57, 0x00, 0xE3,
-	  0xFF,
-	  },
-	 {			/*  Init_CR30_CR4D */
-	  0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x03, 0x20,
-	  0x00, 0x00, 0x00, 0x40, 0x00, 0xE7, 0xBF, 0xFD,
-	  0x7F, 0x63, 0x00, 0x69, 0x18, 0x72, 0x57, 0x00,
-	  0x58, 0x0C, 0xE0, 0x20, 0x63, 0x57,
-	  },
-	 {			/*  Init_CR90_CRA7 */
-	  0x56, 0x4B, 0x5E, 0x55, 0x86, 0x9D, 0x8E, 0xAA,
-	  0xDB, 0x2A, 0xDF, 0x33, 0x00, 0x00, 0x18, 0x00,
-	  0x20, 0x1F, 0x1A, 0x19, 0x0F, 0x0F, 0x0F, 0x00,
-	  },
-	 },
-	{			/*  mode#7: 800 x 600  32Bpp  60Hz */
-	 800, 600, 32, 60,
-	 /*  Init_MISC */
-	 0x2B,
-	 {			/*  Init_SR0_SR4 */
-	  0x03, 0x01, 0x0F, 0x03, 0x0E,
-	  },
-	 {			/*  Init_SR10_SR24 */
-	  0xFF, 0xBE, 0xEE, 0xFF, 0x00, 0x0E, 0x17, 0x2C,
-	  0x99, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
-	  0xC4, 0x30, 0x02, 0x01, 0x01,
-	  },
-	 {			/*  Init_SR30_SR75 */
-	  0x34, 0x03, 0x20, 0x09, 0xC0, 0x24, 0x24, 0x24,
-	  0x24, 0x24, 0x24, 0x24, 0x00, 0x00, 0x03, 0xFF,
-	  0x00, 0xFC, 0x00, 0x00, 0x20, 0x38, 0x00, 0xFC,
-	  0x20, 0x0C, 0x44, 0x20, 0x00, 0x24, 0x24, 0x24,
-	  0x04, 0x48, 0x83, 0x63, 0x68, 0x72, 0x57, 0x58,
-	  0x04, 0x55, 0x59, 0x24, 0x24, 0x00, 0x00, 0x24,
-	  0x01, 0x80, 0x7A, 0x1A, 0x1A, 0x00, 0x00, 0x00,
-	  0x50, 0x03, 0x74, 0x14, 0x1C, 0x85, 0x35, 0x13,
-	  0x02, 0x45, 0x30, 0x35, 0x40, 0x20,
-	  },
-	 {			/*  Init_SR80_SR93 */
-	  0x00, 0x00, 0x00, 0x6F, 0x7F, 0x7F, 0xFF, 0x24,
-	  0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x24, 0x24,
-	  0x00, 0x00, 0x00, 0x00,
-	  },
-	 {			/*  Init_SRA0_SRAF */
-	  0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED,
-	  0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xBF, 0xDF,
-	  },
-	 {			/*  Init_GR00_GR08 */
-	  0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
-	  0xFF,
-	  },
-	 {			/*  Init_AR00_AR14 */
-	  0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-	  0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
-	  0x41, 0x00, 0x0F, 0x00, 0x00,
-	  },
-	 {			/*  Init_CR00_CR18 */
-	  0x7F, 0x63, 0x63, 0x00, 0x68, 0x18, 0x72, 0xF0,
-	  0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	  0x58, 0x0C, 0x57, 0x64, 0x40, 0x57, 0x00, 0xE3,
-	  0xFF,
-	  },
-	 {			/*  Init_CR30_CR4D */
-	  0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x03, 0x20,
-	  0x00, 0x00, 0x00, 0x40, 0x00, 0xE7, 0xBF, 0xFD,
-	  0x7F, 0x63, 0x00, 0x69, 0x18, 0x72, 0x57, 0x00,
-	  0x58, 0x0C, 0xE0, 0x20, 0x63, 0x57,
-	  },
-	 {			/*  Init_CR90_CRA7 */
-	  0x56, 0x4B, 0x5E, 0x55, 0x86, 0x9D, 0x8E, 0xAA,
-	  0xDB, 0x2A, 0xDF, 0x33, 0x00, 0x00, 0x18, 0x00,
-	  0x20, 0x1F, 0x1A, 0x19, 0x0F, 0x0F, 0x0F, 0x00,
-	  },
-	 },
-	/* We use 1024x768 table to light 1024x600 panel for lemote */
-	{			/*  mode#4: 1024 x 600  16Bpp  60Hz  */
-	 1024, 600, 16, 60,
-	 /*  Init_MISC */
-	 0xEB,
-	 {			/*  Init_SR0_SR4 */
-	  0x03, 0x01, 0x0F, 0x00, 0x0E,
-	  },
-	 {			/*  Init_SR10_SR24 */
-	  0xC8, 0x40, 0x14, 0x60, 0x00, 0x0A, 0x17, 0x20,
-	  0x51, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
-	  0xC4, 0x30, 0x02, 0x00, 0x01,
-	  },
-	 {			/*  Init_SR30_SR75 */
-	  0x22, 0x03, 0x24, 0x09, 0xC0, 0x22, 0x22, 0x22,
-	  0x22, 0x22, 0x22, 0x22, 0x00, 0x00, 0x03, 0xFF,
-	  0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
-	  0x20, 0x0C, 0x44, 0x20, 0x00, 0x22, 0x22, 0x22,
-	  0x06, 0x68, 0xA7, 0x7F, 0x83, 0x24, 0xFF, 0x03,
-	  0x00, 0x60, 0x59, 0x22, 0x22, 0x00, 0x00, 0x22,
-	  0x01, 0x80, 0x7A, 0x1A, 0x1A, 0x00, 0x00, 0x00,
-	  0x50, 0x03, 0x16, 0x02, 0x0D, 0x82, 0x09, 0x02,
-	  0x04, 0x45, 0x3F, 0x30, 0x40, 0x20,
-	  },
-	 {			/*  Init_SR80_SR93 */
-	  0xFF, 0x07, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x3A,
-	  0xF7, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x3A, 0x3A,
-	  0x00, 0x00, 0x00, 0x00,
-	  },
-	 {			/*  Init_SRA0_SRAF */
-	  0x00, 0xFB, 0x9F, 0x01, 0x00, 0xED, 0xED, 0xED,
-	  0x7B, 0xFB, 0xFF, 0xFF, 0x97, 0xEF, 0xBF, 0xDF,
-	  },
-	 {			/*  Init_GR00_GR08 */
-	  0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
-	  0xFF,
-	  },
-	 {			/*  Init_AR00_AR14 */
-	  0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-	  0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
-	  0x41, 0x00, 0x0F, 0x00, 0x00,
-	  },
-	 {			/*  Init_CR00_CR18 */
-	  0xA3, 0x7F, 0x7F, 0x00, 0x85, 0x16, 0x24, 0xF5,
-	  0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	  0x03, 0x09, 0xFF, 0x80, 0x40, 0xFF, 0x00, 0xE3,
-	  0xFF,
-	  },
-	 {			/*  Init_CR30_CR4D */
-	  0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x20,
-	  0x00, 0x00, 0x00, 0x40, 0x00, 0xFF, 0xBF, 0xFF,
-	  0xA3, 0x7F, 0x00, 0x82, 0x0b, 0x6f, 0x57, 0x00,
-	  0x5c, 0x0f, 0xE0, 0xe0, 0x7F, 0x57,
-	  },
-	 {			/*  Init_CR90_CRA7 */
-	  0x55, 0xD9, 0x5D, 0xE1, 0x86, 0x1B, 0x8E, 0x26,
-	  0xDA, 0x8D, 0xDE, 0x94, 0x00, 0x00, 0x18, 0x00,
-	  0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x15, 0x03,
-	  },
-	 },
-	{			/*  mode#5: 1024 x 768  24Bpp  60Hz */
-	 1024, 768, 24, 60,
-	 /*  Init_MISC */
-	 0xEB,
-	 {			/*  Init_SR0_SR4 */
-	  0x03, 0x01, 0x0F, 0x03, 0x0E,
-	  },
-	 {			/*  Init_SR10_SR24 */
-	  0xF3, 0xB6, 0xC0, 0xDD, 0x00, 0x0E, 0x17, 0x2C,
-	  0x99, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
-	  0xC4, 0x30, 0x02, 0x01, 0x01,
-	  },
-	 {			/*  Init_SR30_SR75 */
-	  0x38, 0x03, 0x20, 0x09, 0xC0, 0x3A, 0x3A, 0x3A,
-	  0x3A, 0x3A, 0x3A, 0x3A, 0x00, 0x00, 0x03, 0xFF,
-	  0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
-	  0x20, 0x0C, 0x44, 0x20, 0x00, 0x00, 0x00, 0x3A,
-	  0x06, 0x68, 0xA7, 0x7F, 0x83, 0x24, 0xFF, 0x03,
-	  0x00, 0x60, 0x59, 0x3A, 0x3A, 0x00, 0x00, 0x3A,
-	  0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00,
-	  0x50, 0x03, 0x74, 0x14, 0x3B, 0x0D, 0x09, 0x02,
-	  0x04, 0x45, 0x30, 0x30, 0x40, 0x20,
-	  },
-	 {			/*  Init_SR80_SR93 */
-	  0xFF, 0x07, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x3A,
-	  0xF7, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x3A, 0x3A,
-	  0x00, 0x00, 0x00, 0x00,
-	  },
-	 {			/*  Init_SRA0_SRAF */
-	  0x00, 0xFB, 0x9F, 0x01, 0x00, 0xED, 0xED, 0xED,
-	  0x7B, 0xFB, 0xFF, 0xFF, 0x97, 0xEF, 0xBF, 0xDF,
-	  },
-	 {			/*  Init_GR00_GR08 */
-	  0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
-	  0xFF,
-	  },
-	 {			/*  Init_AR00_AR14 */
-	  0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-	  0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
-	  0x41, 0x00, 0x0F, 0x00, 0x00,
-	  },
-	 {			/*  Init_CR00_CR18 */
-	  0xA3, 0x7F, 0x7F, 0x00, 0x85, 0x16, 0x24, 0xF5,
-	  0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	  0x03, 0x09, 0xFF, 0x80, 0x40, 0xFF, 0x00, 0xE3,
-	  0xFF,
-	  },
-	 {			/*  Init_CR30_CR4D */
-	  0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x20,
-	  0x00, 0x00, 0x00, 0x40, 0x00, 0xFF, 0xBF, 0xFF,
-	  0xA3, 0x7F, 0x00, 0x86, 0x15, 0x24, 0xFF, 0x00,
-	  0x01, 0x07, 0xE5, 0x20, 0x7F, 0xFF,
-	  },
-	 {			/*  Init_CR90_CRA7 */
-	  0x55, 0xD9, 0x5D, 0xE1, 0x86, 0x1B, 0x8E, 0x26,
-	  0xDA, 0x8D, 0xDE, 0x94, 0x00, 0x00, 0x18, 0x00,
-	  0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x15, 0x03,
-	  },
-	 },
-	{			/*  mode#4: 1024 x 768  32Bpp  60Hz */
-	 1024, 768, 32, 60,
-	 /*  Init_MISC */
-	 0xEB,
-	 {			/*  Init_SR0_SR4 */
-	  0x03, 0x01, 0x0F, 0x03, 0x0E,
-	  },
-	 {			/*  Init_SR10_SR24 */
-	  0xF3, 0xB6, 0xC0, 0xDD, 0x00, 0x0E, 0x17, 0x2C,
-	  0x99, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
-	  0xC4, 0x32, 0x02, 0x01, 0x01,
-	  },
-	 {			/*  Init_SR30_SR75 */
-	  0x38, 0x03, 0x20, 0x09, 0xC0, 0x3A, 0x3A, 0x3A,
-	  0x3A, 0x3A, 0x3A, 0x3A, 0x00, 0x00, 0x03, 0xFF,
-	  0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
-	  0x20, 0x0C, 0x44, 0x20, 0x00, 0x00, 0x00, 0x3A,
-	  0x06, 0x68, 0xA7, 0x7F, 0x83, 0x24, 0xFF, 0x03,
-	  0x00, 0x60, 0x59, 0x3A, 0x3A, 0x00, 0x00, 0x3A,
-	  0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00,
-	  0x50, 0x03, 0x74, 0x14, 0x3B, 0x0D, 0x09, 0x02,
-	  0x04, 0x45, 0x30, 0x30, 0x40, 0x20,
-	  },
-	 {			/*  Init_SR80_SR93 */
-	  0xFF, 0x07, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x3A,
-	  0xF7, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x3A, 0x3A,
-	  0x00, 0x00, 0x00, 0x00,
-	  },
-	 {			/*  Init_SRA0_SRAF */
-	  0x00, 0xFB, 0x9F, 0x01, 0x00, 0xED, 0xED, 0xED,
-	  0x7B, 0xFB, 0xFF, 0xFF, 0x97, 0xEF, 0xBF, 0xDF,
-	  },
-	 {			/*  Init_GR00_GR08 */
-	  0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
-	  0xFF,
-	  },
-	 {			/*  Init_AR00_AR14 */
-	  0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-	  0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
-	  0x41, 0x00, 0x0F, 0x00, 0x00,
-	  },
-	 {			/*  Init_CR00_CR18 */
-	  0xA3, 0x7F, 0x7F, 0x00, 0x85, 0x16, 0x24, 0xF5,
-	  0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	  0x03, 0x09, 0xFF, 0x80, 0x40, 0xFF, 0x00, 0xE3,
-	  0xFF,
-	  },
-	 {			/*  Init_CR30_CR4D */
-	  0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x20,
-	  0x00, 0x00, 0x00, 0x40, 0x00, 0xFF, 0xBF, 0xFF,
-	  0xA3, 0x7F, 0x00, 0x86, 0x15, 0x24, 0xFF, 0x00,
-	  0x01, 0x07, 0xE5, 0x20, 0x7F, 0xFF,
-	  },
-	 {			/*  Init_CR90_CRA7 */
-	  0x55, 0xD9, 0x5D, 0xE1, 0x86, 0x1B, 0x8E, 0x26,
-	  0xDA, 0x8D, 0xDE, 0x94, 0x00, 0x00, 0x18, 0x00,
-	  0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x15, 0x03,
-	  },
-	 },
-	{			/*  mode#6: 320 x 240  16Bpp  60Hz */
-	 320, 240, 16, 60,
-	 /*  Init_MISC */
-	 0xEB,
-	 {			/*  Init_SR0_SR4 */
-	  0x03, 0x01, 0x0F, 0x03, 0x0E,
-	  },
-	 {			/*  Init_SR10_SR24 */
-	  0xF3, 0xB6, 0xC0, 0xDD, 0x00, 0x0E, 0x17, 0x2C,
-	  0x99, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
-	  0xC4, 0x32, 0x02, 0x01, 0x01,
-	  },
-	 {			/*  Init_SR30_SR75 */
-	  0x38, 0x03, 0x20, 0x09, 0xC0, 0x3A, 0x3A, 0x3A,
-	  0x3A, 0x3A, 0x3A, 0x3A, 0x00, 0x00, 0x03, 0xFF,
-	  0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
-	  0x20, 0x0C, 0x44, 0x20, 0x00, 0x00, 0x00, 0x3A,
-	  0x06, 0x68, 0xA7, 0x7F, 0x83, 0x24, 0xFF, 0x03,
-	  0x00, 0x60, 0x59, 0x3A, 0x3A, 0x00, 0x00, 0x3A,
-	  0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00,
-	  0x50, 0x03, 0x74, 0x14, 0x08, 0x43, 0x08, 0x43,
-	  0x04, 0x45, 0x30, 0x30, 0x40, 0x20,
-	  },
-	 {			/*  Init_SR80_SR93 */
-	  0xFF, 0x07, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x3A,
-	  0xF7, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x3A, 0x3A,
-	  0x00, 0x00, 0x00, 0x00,
-	  },
-	 {			/*  Init_SRA0_SRAF */
-	  0x00, 0xFB, 0x9F, 0x01, 0x00, 0xED, 0xED, 0xED,
-	  0x7B, 0xFB, 0xFF, 0xFF, 0x97, 0xEF, 0xBF, 0xDF,
-	  },
-	 {			/*  Init_GR00_GR08 */
-	  0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
-	  0xFF,
-	  },
-	 {			/*  Init_AR00_AR14 */
-	  0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-	  0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
-	  0x41, 0x00, 0x0F, 0x00, 0x00,
-	  },
-	 {			/*  Init_CR00_CR18 */
-	  0xA3, 0x7F, 0x7F, 0x00, 0x85, 0x16, 0x24, 0xF5,
-	  0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	  0x03, 0x09, 0xFF, 0x80, 0x40, 0xFF, 0x00, 0xE3,
-	  0xFF,
-	  },
-	 {			/*  Init_CR30_CR4D */
-	  0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x20,
-	  0x00, 0x00, 0x30, 0x40, 0x00, 0xFF, 0xBF, 0xFF,
-	  0x2E, 0x27, 0x00, 0x2b, 0x0c, 0x0F, 0xEF, 0x00,
-	  0xFe, 0x0f, 0x01, 0xC0, 0x27, 0xEF,
-	  },
-	 {			/*  Init_CR90_CRA7 */
-	  0x55, 0xD9, 0x5D, 0xE1, 0x86, 0x1B, 0x8E, 0x26,
-	  0xDA, 0x8D, 0xDE, 0x94, 0x00, 0x00, 0x18, 0x00,
-	  0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x15, 0x03,
-	  },
-	 },
-
-	{			/*  mode#8: 320 x 240  32Bpp  60Hz */
-	 320, 240, 32, 60,
-	 /*  Init_MISC */
-	 0xEB,
-	 {			/*  Init_SR0_SR4 */
-	  0x03, 0x01, 0x0F, 0x03, 0x0E,
-	  },
-	 {			/*  Init_SR10_SR24 */
-	  0xF3, 0xB6, 0xC0, 0xDD, 0x00, 0x0E, 0x17, 0x2C,
-	  0x99, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
-	  0xC4, 0x32, 0x02, 0x01, 0x01,
-	  },
-	 {			/*  Init_SR30_SR75 */
-	  0x38, 0x03, 0x20, 0x09, 0xC0, 0x3A, 0x3A, 0x3A,
-	  0x3A, 0x3A, 0x3A, 0x3A, 0x00, 0x00, 0x03, 0xFF,
-	  0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
-	  0x20, 0x0C, 0x44, 0x20, 0x00, 0x00, 0x00, 0x3A,
-	  0x06, 0x68, 0xA7, 0x7F, 0x83, 0x24, 0xFF, 0x03,
-	  0x00, 0x60, 0x59, 0x3A, 0x3A, 0x00, 0x00, 0x3A,
-	  0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00,
-	  0x50, 0x03, 0x74, 0x14, 0x08, 0x43, 0x08, 0x43,
-	  0x04, 0x45, 0x30, 0x30, 0x40, 0x20,
-	  },
-	 {			/*  Init_SR80_SR93 */
-	  0xFF, 0x07, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x3A,
-	  0xF7, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x3A, 0x3A,
-	  0x00, 0x00, 0x00, 0x00,
-	  },
-	 {			/*  Init_SRA0_SRAF */
-	  0x00, 0xFB, 0x9F, 0x01, 0x00, 0xED, 0xED, 0xED,
-	  0x7B, 0xFB, 0xFF, 0xFF, 0x97, 0xEF, 0xBF, 0xDF,
-	  },
-	 {			/*  Init_GR00_GR08 */
-	  0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
-	  0xFF,
-	  },
-	 {			/*  Init_AR00_AR14 */
-	  0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-	  0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
-	  0x41, 0x00, 0x0F, 0x00, 0x00,
-	  },
-	 {			/*  Init_CR00_CR18 */
-	  0xA3, 0x7F, 0x7F, 0x00, 0x85, 0x16, 0x24, 0xF5,
-	  0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	  0x03, 0x09, 0xFF, 0x80, 0x40, 0xFF, 0x00, 0xE3,
-	  0xFF,
-	  },
-	 {			/*  Init_CR30_CR4D */
-	  0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x20,
-	  0x00, 0x00, 0x30, 0x40, 0x00, 0xFF, 0xBF, 0xFF,
-	  0x2E, 0x27, 0x00, 0x2b, 0x0c, 0x0F, 0xEF, 0x00,
-	  0xFe, 0x0f, 0x01, 0xC0, 0x27, 0xEF,
-	  },
-	 {			/*  Init_CR90_CRA7 */
-	  0x55, 0xD9, 0x5D, 0xE1, 0x86, 0x1B, 0x8E, 0x26,
-	  0xDA, 0x8D, 0xDE, 0x94, 0x00, 0x00, 0x18, 0x00,
-	  0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x15, 0x03,
-	  },
-	 },
-};
-
-#define numVGAModes		ARRAY_SIZE(VGAMode)
diff --git a/drivers/staging/sm7xxfb/sm7xxfb.c b/drivers/staging/sm7xxfb/sm7xxfb.c
deleted file mode 100644
index 6176d98..0000000
--- a/drivers/staging/sm7xxfb/sm7xxfb.c
+++ /dev/null
@@ -1,1028 +0,0 @@
-/*
- * Silicon Motion SM7XX frame buffer device
- *
- * Copyright (C) 2006 Silicon Motion Technology Corp.
- * Authors:  Ge Wang, gewang@siliconmotion.com
- *	     Boyod boyod.yang@siliconmotion.com.cn
- *
- * Copyright (C) 2009 Lemote, Inc.
- * Author:   Wu Zhangjin, wuzhangjin@gmail.com
- *
- * Copyright (C) 2011 Igalia, S.L.
- * Author:   Javier M. Mellid <jmunhoz@igalia.com>
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file COPYING in the main directory of this archive for
- * more details.
- *
- * Framebuffer driver for Silicon Motion SM710, SM712, SM721 and SM722 chips
- */
-
-#include <linux/io.h>
-#include <linux/fb.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/uaccess.h>
-#include <linux/module.h>
-#include <linux/console.h>
-#include <linux/screen_info.h>
-
-#ifdef CONFIG_PM
-#include <linux/pm.h>
-#endif
-
-#include "sm7xx.h"
-
-/*
-* Private structure
-*/
-struct smtcfb_info {
-	struct pci_dev *pdev;
-	struct fb_info fb;
-	u16 chip_id;
-	u8  chip_rev_id;
-
-	void __iomem *lfb;	/* linear frame buffer */
-	void __iomem *dp_regs;	/* drawing processor control regs */
-	void __iomem *vp_regs;	/* video processor control regs */
-	void __iomem *cp_regs;	/* capture processor control regs */
-	void __iomem *mmio;	/* memory map IO port */
-
-	u_int width;
-	u_int height;
-	u_int hz;
-
-	u32 colreg[17];
-};
-
-void __iomem *smtc_RegBaseAddress;	/* Memory Map IO starting address */
-
-static struct fb_var_screeninfo smtcfb_var = {
-	.xres           = 1024,
-	.yres           = 600,
-	.xres_virtual   = 1024,
-	.yres_virtual   = 600,
-	.bits_per_pixel = 16,
-	.red            = {16, 8, 0},
-	.green          = {8, 8, 0},
-	.blue           = {0, 8, 0},
-	.activate       = FB_ACTIVATE_NOW,
-	.height         = -1,
-	.width          = -1,
-	.vmode          = FB_VMODE_NONINTERLACED,
-	.nonstd         = 0,
-	.accel_flags    = FB_ACCELF_TEXT,
-};
-
-static struct fb_fix_screeninfo smtcfb_fix = {
-	.id             = "smXXXfb",
-	.type           = FB_TYPE_PACKED_PIXELS,
-	.visual         = FB_VISUAL_TRUECOLOR,
-	.line_length    = 800 * 3,
-	.accel          = FB_ACCEL_SMI_LYNX,
-	.type_aux       = 0,
-	.xpanstep       = 0,
-	.ypanstep       = 0,
-	.ywrapstep      = 0,
-};
-
-struct vesa_mode {
-	char index[6];
-	u16  lfb_width;
-	u16  lfb_height;
-	u16  lfb_depth;
-};
-
-static struct vesa_mode vesa_mode_table[] = {
-	{"0x301", 640,  480,  8},
-	{"0x303", 800,  600,  8},
-	{"0x305", 1024, 768,  8},
-	{"0x307", 1280, 1024, 8},
-
-	{"0x311", 640,  480,  16},
-	{"0x314", 800,  600,  16},
-	{"0x317", 1024, 768,  16},
-	{"0x31A", 1280, 1024, 16},
-
-	{"0x312", 640,  480,  24},
-	{"0x315", 800,  600,  24},
-	{"0x318", 1024, 768,  24},
-	{"0x31B", 1280, 1024, 24},
-};
-
-struct screen_info smtc_scr_info;
-
-/* process command line options, get vga parameter */
-static int __init sm7xx_vga_setup(char *options)
-{
-	int i;
-
-	if (!options || !*options)
-		return -EINVAL;
-
-	smtc_scr_info.lfb_width = 0;
-	smtc_scr_info.lfb_height = 0;
-	smtc_scr_info.lfb_depth = 0;
-
-	pr_debug("sm7xx_vga_setup = %s\n", options);
-
-	for (i = 0; i < ARRAY_SIZE(vesa_mode_table); i++) {
-		if (strstr(options, vesa_mode_table[i].index)) {
-			smtc_scr_info.lfb_width  = vesa_mode_table[i].lfb_width;
-			smtc_scr_info.lfb_height =
-						vesa_mode_table[i].lfb_height;
-			smtc_scr_info.lfb_depth  = vesa_mode_table[i].lfb_depth;
-			return 0;
-		}
-	}
-
-	return -1;
-}
-__setup("vga=", sm7xx_vga_setup);
-
-static void sm712_setpalette(int regno, unsigned red, unsigned green,
-			     unsigned blue, struct fb_info *info)
-{
-	/* set bit 5:4 = 01 (write LCD RAM only) */
-	smtc_seqw(0x66, (smtc_seqr(0x66) & 0xC3) | 0x10);
-
-	smtc_mmiowb(regno, dac_reg);
-	smtc_mmiowb(red >> 10, dac_val);
-	smtc_mmiowb(green >> 10, dac_val);
-	smtc_mmiowb(blue >> 10, dac_val);
-}
-
-/* chan_to_field
- *
- * convert a colour value into a field position
- *
- * from pxafb.c
- */
-
-static inline unsigned int chan_to_field(unsigned int chan,
-					 struct fb_bitfield *bf)
-{
-	chan &= 0xffff;
-	chan >>= 16 - bf->length;
-	return chan << bf->offset;
-}
-
-static int smtc_blank(int blank_mode, struct fb_info *info)
-{
-	/* clear DPMS setting */
-	switch (blank_mode) {
-	case FB_BLANK_UNBLANK:
-		/* Screen On: HSync: On, VSync : On */
-		smtc_seqw(0x01, (smtc_seqr(0x01) & (~0x20)));
-		smtc_seqw(0x6a, 0x16);
-		smtc_seqw(0x6b, 0x02);
-		smtc_seqw(0x21, (smtc_seqr(0x21) & 0x77));
-		smtc_seqw(0x22, (smtc_seqr(0x22) & (~0x30)));
-		smtc_seqw(0x23, (smtc_seqr(0x23) & (~0xc0)));
-		smtc_seqw(0x24, (smtc_seqr(0x24) | 0x01));
-		smtc_seqw(0x31, (smtc_seqr(0x31) | 0x03));
-		break;
-	case FB_BLANK_NORMAL:
-		/* Screen Off: HSync: On, VSync : On   Soft blank */
-		smtc_seqw(0x01, (smtc_seqr(0x01) & (~0x20)));
-		smtc_seqw(0x6a, 0x16);
-		smtc_seqw(0x6b, 0x02);
-		smtc_seqw(0x22, (smtc_seqr(0x22) & (~0x30)));
-		smtc_seqw(0x23, (smtc_seqr(0x23) & (~0xc0)));
-		smtc_seqw(0x24, (smtc_seqr(0x24) | 0x01));
-		smtc_seqw(0x31, ((smtc_seqr(0x31) & (~0x07)) | 0x00));
-		break;
-	case FB_BLANK_VSYNC_SUSPEND:
-		/* Screen On: HSync: On, VSync : Off */
-		smtc_seqw(0x01, (smtc_seqr(0x01) | 0x20));
-		smtc_seqw(0x20, (smtc_seqr(0x20) & (~0xB0)));
-		smtc_seqw(0x6a, 0x0c);
-		smtc_seqw(0x6b, 0x02);
-		smtc_seqw(0x21, (smtc_seqr(0x21) | 0x88));
-		smtc_seqw(0x22, ((smtc_seqr(0x22) & (~0x30)) | 0x20));
-		smtc_seqw(0x23, ((smtc_seqr(0x23) & (~0xc0)) | 0x20));
-		smtc_seqw(0x24, (smtc_seqr(0x24) & (~0x01)));
-		smtc_seqw(0x31, ((smtc_seqr(0x31) & (~0x07)) | 0x00));
-		smtc_seqw(0x34, (smtc_seqr(0x34) | 0x80));
-		break;
-	case FB_BLANK_HSYNC_SUSPEND:
-		/* Screen On: HSync: Off, VSync : On */
-		smtc_seqw(0x01, (smtc_seqr(0x01) | 0x20));
-		smtc_seqw(0x20, (smtc_seqr(0x20) & (~0xB0)));
-		smtc_seqw(0x6a, 0x0c);
-		smtc_seqw(0x6b, 0x02);
-		smtc_seqw(0x21, (smtc_seqr(0x21) | 0x88));
-		smtc_seqw(0x22, ((smtc_seqr(0x22) & (~0x30)) | 0x10));
-		smtc_seqw(0x23, ((smtc_seqr(0x23) & (~0xc0)) | 0xD8));
-		smtc_seqw(0x24, (smtc_seqr(0x24) & (~0x01)));
-		smtc_seqw(0x31, ((smtc_seqr(0x31) & (~0x07)) | 0x00));
-		smtc_seqw(0x34, (smtc_seqr(0x34) | 0x80));
-		break;
-	case FB_BLANK_POWERDOWN:
-		/* Screen On: HSync: Off, VSync : Off */
-		smtc_seqw(0x01, (smtc_seqr(0x01) | 0x20));
-		smtc_seqw(0x20, (smtc_seqr(0x20) & (~0xB0)));
-		smtc_seqw(0x6a, 0x0c);
-		smtc_seqw(0x6b, 0x02);
-		smtc_seqw(0x21, (smtc_seqr(0x21) | 0x88));
-		smtc_seqw(0x22, ((smtc_seqr(0x22) & (~0x30)) | 0x30));
-		smtc_seqw(0x23, ((smtc_seqr(0x23) & (~0xc0)) | 0xD8));
-		smtc_seqw(0x24, (smtc_seqr(0x24) & (~0x01)));
-		smtc_seqw(0x31, ((smtc_seqr(0x31) & (~0x07)) | 0x00));
-		smtc_seqw(0x34, (smtc_seqr(0x34) | 0x80));
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static int smtc_setcolreg(unsigned regno, unsigned red, unsigned green,
-			  unsigned blue, unsigned trans, struct fb_info *info)
-{
-	struct smtcfb_info *sfb;
-	u32 val;
-
-	sfb = info->par;
-
-	if (regno > 255)
-		return 1;
-
-	switch (sfb->fb.fix.visual) {
-	case FB_VISUAL_DIRECTCOLOR:
-	case FB_VISUAL_TRUECOLOR:
-		/*
-		 * 16/32 bit true-colour, use pseudo-palette for 16 base color
-		 */
-		if (regno < 16) {
-			if (sfb->fb.var.bits_per_pixel == 16) {
-				u32 *pal = sfb->fb.pseudo_palette;
-				val = chan_to_field(red, &sfb->fb.var.red);
-				val |= chan_to_field(green, &sfb->fb.var.green);
-				val |= chan_to_field(blue, &sfb->fb.var.blue);
-#ifdef __BIG_ENDIAN
-				pal[regno] =
-				    ((red & 0xf800) >> 8) |
-				    ((green & 0xe000) >> 13) |
-				    ((green & 0x1c00) << 3) |
-				    ((blue & 0xf800) >> 3);
-#else
-				pal[regno] = val;
-#endif
-			} else {
-				u32 *pal = sfb->fb.pseudo_palette;
-				val = chan_to_field(red, &sfb->fb.var.red);
-				val |= chan_to_field(green, &sfb->fb.var.green);
-				val |= chan_to_field(blue, &sfb->fb.var.blue);
-#ifdef __BIG_ENDIAN
-				val =
-				    (val & 0xff00ff00 >> 8) |
-				    (val & 0x00ff00ff << 8);
-#endif
-				pal[regno] = val;
-			}
-		}
-		break;
-
-	case FB_VISUAL_PSEUDOCOLOR:
-		/* color depth 8 bit */
-		sm712_setpalette(regno, red, green, blue, info);
-		break;
-
-	default:
-		return 1;	/* unknown type */
-	}
-
-	return 0;
-
-}
-
-#ifdef __BIG_ENDIAN
-static ssize_t smtcfb_read(struct fb_info *info, char __user *buf, size_t
-				count, loff_t *ppos)
-{
-	unsigned long p = *ppos;
-
-	u32 *buffer, *dst;
-	u32 __iomem *src;
-	int c, i, cnt = 0, err = 0;
-	unsigned long total_size;
-
-	if (!info || !info->screen_base)
-		return -ENODEV;
-
-	if (info->state != FBINFO_STATE_RUNNING)
-		return -EPERM;
-
-	total_size = info->screen_size;
-
-	if (total_size == 0)
-		total_size = info->fix.smem_len;
-
-	if (p >= total_size)
-		return 0;
-
-	if (count >= total_size)
-		count = total_size;
-
-	if (count + p > total_size)
-		count = total_size - p;
-
-	buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count, GFP_KERNEL);
-	if (!buffer)
-		return -ENOMEM;
-
-	src = (u32 __iomem *) (info->screen_base + p);
-
-	if (info->fbops->fb_sync)
-		info->fbops->fb_sync(info);
-
-	while (count) {
-		c = (count > PAGE_SIZE) ? PAGE_SIZE : count;
-		dst = buffer;
-		for (i = c >> 2; i--;) {
-			*dst = fb_readl(src++);
-			*dst =
-			    (*dst & 0xff00ff00 >> 8) |
-			    (*dst & 0x00ff00ff << 8);
-			dst++;
-		}
-		if (c & 3) {
-			u8 *dst8 = (u8 *) dst;
-			u8 __iomem *src8 = (u8 __iomem *) src;
-
-			for (i = c & 3; i--;) {
-				if (i & 1) {
-					*dst8++ = fb_readb(++src8);
-				} else {
-					*dst8++ = fb_readb(--src8);
-					src8 += 2;
-				}
-			}
-			src = (u32 __iomem *) src8;
-		}
-
-		if (copy_to_user(buf, buffer, c)) {
-			err = -EFAULT;
-			break;
-		}
-		*ppos += c;
-		buf += c;
-		cnt += c;
-		count -= c;
-	}
-
-	kfree(buffer);
-
-	return (err) ? err : cnt;
-}
-
-static ssize_t
-smtcfb_write(struct fb_info *info, const char __user *buf, size_t count,
-	     loff_t *ppos)
-{
-	unsigned long p = *ppos;
-
-	u32 *buffer, *src;
-	u32 __iomem *dst;
-	int c, i, cnt = 0, err = 0;
-	unsigned long total_size;
-
-	if (!info || !info->screen_base)
-		return -ENODEV;
-
-	if (info->state != FBINFO_STATE_RUNNING)
-		return -EPERM;
-
-	total_size = info->screen_size;
-
-	if (total_size == 0)
-		total_size = info->fix.smem_len;
-
-	if (p > total_size)
-		return -EFBIG;
-
-	if (count > total_size) {
-		err = -EFBIG;
-		count = total_size;
-	}
-
-	if (count + p > total_size) {
-		if (!err)
-			err = -ENOSPC;
-
-		count = total_size - p;
-	}
-
-	buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count, GFP_KERNEL);
-	if (!buffer)
-		return -ENOMEM;
-
-	dst = (u32 __iomem *) (info->screen_base + p);
-
-	if (info->fbops->fb_sync)
-		info->fbops->fb_sync(info);
-
-	while (count) {
-		c = (count > PAGE_SIZE) ? PAGE_SIZE : count;
-		src = buffer;
-
-		if (copy_from_user(src, buf, c)) {
-			err = -EFAULT;
-			break;
-		}
-
-		for (i = c >> 2; i--;) {
-			fb_writel((*src & 0xff00ff00 >> 8) |
-				  (*src & 0x00ff00ff << 8), dst++);
-			src++;
-		}
-		if (c & 3) {
-			u8 *src8 = (u8 *) src;
-			u8 __iomem *dst8 = (u8 __iomem *) dst;
-
-			for (i = c & 3; i--;) {
-				if (i & 1) {
-					fb_writeb(*src8++, ++dst8);
-				} else {
-					fb_writeb(*src8++, --dst8);
-					dst8 += 2;
-				}
-			}
-			dst = (u32 __iomem *) dst8;
-		}
-
-		*ppos += c;
-		buf += c;
-		cnt += c;
-		count -= c;
-	}
-
-	kfree(buffer);
-
-	return (cnt) ? cnt : err;
-}
-#endif	/* ! __BIG_ENDIAN */
-
-static void sm7xx_set_timing(struct smtcfb_info *sfb)
-{
-	int i = 0, j = 0;
-	u32 m_nScreenStride;
-
-	dev_dbg(&sfb->pdev->dev,
-		"sfb->width=%d sfb->height=%d "
-		"sfb->fb.var.bits_per_pixel=%d sfb->hz=%d\n",
-		sfb->width, sfb->height, sfb->fb.var.bits_per_pixel, sfb->hz);
-
-	for (j = 0; j < numVGAModes; j++) {
-		if (VGAMode[j].mmSizeX == sfb->width &&
-		    VGAMode[j].mmSizeY == sfb->height &&
-		    VGAMode[j].bpp == sfb->fb.var.bits_per_pixel &&
-		    VGAMode[j].hz == sfb->hz) {
-
-			dev_dbg(&sfb->pdev->dev,
-				"VGAMode[j].mmSizeX=%d VGAMode[j].mmSizeY=%d "
-				"VGAMode[j].bpp=%d VGAMode[j].hz=%d\n",
-				VGAMode[j].mmSizeX, VGAMode[j].mmSizeY,
-				VGAMode[j].bpp, VGAMode[j].hz);
-
-			dev_dbg(&sfb->pdev->dev, "VGAMode index=%d\n", j);
-
-			smtc_mmiowb(0x0, 0x3c6);
-
-			smtc_seqw(0, 0x1);
-
-			smtc_mmiowb(VGAMode[j].Init_MISC, 0x3c2);
-
-			/* init SEQ register SR00 - SR04 */
-			for (i = 0; i < SIZE_SR00_SR04; i++)
-				smtc_seqw(i, VGAMode[j].Init_SR00_SR04[i]);
-
-			/* init SEQ register SR10 - SR24 */
-			for (i = 0; i < SIZE_SR10_SR24; i++)
-				smtc_seqw(i + 0x10,
-					  VGAMode[j].Init_SR10_SR24[i]);
-
-			/* init SEQ register SR30 - SR75 */
-			for (i = 0; i < SIZE_SR30_SR75; i++)
-				if ((i + 0x30) != 0x62 &&
-				    (i + 0x30) != 0x6a &&
-				    (i + 0x30) != 0x6b)
-					smtc_seqw(i + 0x30,
-						VGAMode[j].Init_SR30_SR75[i]);
-
-			/* init SEQ register SR80 - SR93 */
-			for (i = 0; i < SIZE_SR80_SR93; i++)
-				smtc_seqw(i + 0x80,
-					  VGAMode[j].Init_SR80_SR93[i]);
-
-			/* init SEQ register SRA0 - SRAF */
-			for (i = 0; i < SIZE_SRA0_SRAF; i++)
-				smtc_seqw(i + 0xa0,
-					  VGAMode[j].Init_SRA0_SRAF[i]);
-
-			/* init Graphic register GR00 - GR08 */
-			for (i = 0; i < SIZE_GR00_GR08; i++)
-				smtc_grphw(i, VGAMode[j].Init_GR00_GR08[i]);
-
-			/* init Attribute register AR00 - AR14 */
-			for (i = 0; i < SIZE_AR00_AR14; i++)
-				smtc_attrw(i, VGAMode[j].Init_AR00_AR14[i]);
-
-			/* init CRTC register CR00 - CR18 */
-			for (i = 0; i < SIZE_CR00_CR18; i++)
-				smtc_crtcw(i, VGAMode[j].Init_CR00_CR18[i]);
-
-			/* init CRTC register CR30 - CR4D */
-			for (i = 0; i < SIZE_CR30_CR4D; i++)
-				smtc_crtcw(i + 0x30,
-					   VGAMode[j].Init_CR30_CR4D[i]);
-
-			/* init CRTC register CR90 - CRA7 */
-			for (i = 0; i < SIZE_CR90_CRA7; i++)
-				smtc_crtcw(i + 0x90,
-					   VGAMode[j].Init_CR90_CRA7[i]);
-		}
-	}
-	smtc_mmiowb(0x67, 0x3c2);
-
-	/* set VPR registers */
-	writel(0x0, sfb->vp_regs + 0x0C);
-	writel(0x0, sfb->vp_regs + 0x40);
-
-	/* set data width */
-	m_nScreenStride =
-		(sfb->width * sfb->fb.var.bits_per_pixel) / 64;
-	switch (sfb->fb.var.bits_per_pixel) {
-	case 8:
-		writel(0x0, sfb->vp_regs + 0x0);
-		break;
-	case 16:
-		writel(0x00020000, sfb->vp_regs + 0x0);
-		break;
-	case 24:
-		writel(0x00040000, sfb->vp_regs + 0x0);
-		break;
-	case 32:
-		writel(0x00030000, sfb->vp_regs + 0x0);
-		break;
-	}
-	writel((u32) (((m_nScreenStride + 2) << 16) | m_nScreenStride),
-	       sfb->vp_regs + 0x10);
-
-}
-
-static void smtc_set_timing(struct smtcfb_info *sfb)
-{
-	switch (sfb->chip_id) {
-	case 0x710:
-	case 0x712:
-	case 0x720:
-		sm7xx_set_timing(sfb);
-		break;
-	}
-}
-
-static void smtcfb_setmode(struct smtcfb_info *sfb)
-{
-	switch (sfb->fb.var.bits_per_pixel) {
-	case 32:
-		sfb->fb.fix.visual       = FB_VISUAL_TRUECOLOR;
-		sfb->fb.fix.line_length  = sfb->fb.var.xres * 4;
-		sfb->fb.var.red.length   = 8;
-		sfb->fb.var.green.length = 8;
-		sfb->fb.var.blue.length  = 8;
-		sfb->fb.var.red.offset   = 16;
-		sfb->fb.var.green.offset = 8;
-		sfb->fb.var.blue.offset  = 0;
-		break;
-	case 24:
-		sfb->fb.fix.visual       = FB_VISUAL_TRUECOLOR;
-		sfb->fb.fix.line_length  = sfb->fb.var.xres * 3;
-		sfb->fb.var.red.length   = 8;
-		sfb->fb.var.green.length = 8;
-		sfb->fb.var.blue.length  = 8;
-		sfb->fb.var.red.offset   = 16;
-		sfb->fb.var.green.offset = 8;
-		sfb->fb.var.blue.offset  = 0;
-		break;
-	case 8:
-		sfb->fb.fix.visual       = FB_VISUAL_PSEUDOCOLOR;
-		sfb->fb.fix.line_length  = sfb->fb.var.xres;
-		sfb->fb.var.red.length   = 3;
-		sfb->fb.var.green.length = 3;
-		sfb->fb.var.blue.length  = 2;
-		sfb->fb.var.red.offset   = 5;
-		sfb->fb.var.green.offset = 2;
-		sfb->fb.var.blue.offset  = 0;
-		break;
-	case 16:
-	default:
-		sfb->fb.fix.visual       = FB_VISUAL_TRUECOLOR;
-		sfb->fb.fix.line_length  = sfb->fb.var.xres * 2;
-		sfb->fb.var.red.length   = 5;
-		sfb->fb.var.green.length = 6;
-		sfb->fb.var.blue.length  = 5;
-		sfb->fb.var.red.offset   = 11;
-		sfb->fb.var.green.offset = 5;
-		sfb->fb.var.blue.offset  = 0;
-		break;
-	}
-
-	sfb->width  = sfb->fb.var.xres;
-	sfb->height = sfb->fb.var.yres;
-	sfb->hz = 60;
-	smtc_set_timing(sfb);
-}
-
-static int smtc_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
-{
-	/* sanity checks */
-	if (var->xres_virtual < var->xres)
-		var->xres_virtual = var->xres;
-
-	if (var->yres_virtual < var->yres)
-		var->yres_virtual = var->yres;
-
-	/* set valid default bpp */
-	if ((var->bits_per_pixel != 8)  && (var->bits_per_pixel != 16) &&
-	    (var->bits_per_pixel != 24) && (var->bits_per_pixel != 32))
-		var->bits_per_pixel = 16;
-
-	return 0;
-}
-
-static int smtc_set_par(struct fb_info *info)
-{
-	smtcfb_setmode(info->par);
-
-	return 0;
-}
-
-static struct fb_ops smtcfb_ops = {
-	.owner        = THIS_MODULE,
-	.fb_check_var = smtc_check_var,
-	.fb_set_par   = smtc_set_par,
-	.fb_setcolreg = smtc_setcolreg,
-	.fb_blank     = smtc_blank,
-	.fb_fillrect  = cfb_fillrect,
-	.fb_imageblit = cfb_imageblit,
-	.fb_copyarea  = cfb_copyarea,
-#ifdef __BIG_ENDIAN
-	.fb_read      = smtcfb_read,
-	.fb_write     = smtcfb_write,
-#endif
-};
-
-/*
- * alloc struct smtcfb_info and assign default values
- */
-static struct smtcfb_info *smtc_alloc_fb_info(struct pci_dev *pdev)
-{
-	struct smtcfb_info *sfb;
-
-	sfb = kzalloc(sizeof(*sfb), GFP_KERNEL);
-
-	if (!sfb)
-		return NULL;
-
-	sfb->pdev = pdev;
-
-	sfb->fb.flags          = FBINFO_FLAG_DEFAULT;
-	sfb->fb.fbops          = &smtcfb_ops;
-	sfb->fb.fix            = smtcfb_fix;
-	sfb->fb.var            = smtcfb_var;
-	sfb->fb.pseudo_palette = sfb->colreg;
-	sfb->fb.par            = sfb;
-
-	return sfb;
-}
-
-/*
- * free struct smtcfb_info
- */
-static void smtc_free_fb_info(struct smtcfb_info *sfb)
-{
-	kfree(sfb);
-}
-
-/*
- * Unmap in the memory mapped IO registers
- */
-
-static void smtc_unmap_mmio(struct smtcfb_info *sfb)
-{
-	if (sfb && smtc_RegBaseAddress)
-		smtc_RegBaseAddress = NULL;
-}
-
-/*
- * Map in the screen memory
- */
-
-static int smtc_map_smem(struct smtcfb_info *sfb,
-		struct pci_dev *pdev, u_long smem_len)
-{
-
-	sfb->fb.fix.smem_start = pci_resource_start(pdev, 0);
-
-#ifdef __BIG_ENDIAN
-	if (sfb->fb.var.bits_per_pixel == 32)
-		sfb->fb.fix.smem_start += 0x800000;
-#endif
-
-	sfb->fb.fix.smem_len = smem_len;
-
-	sfb->fb.screen_base = sfb->lfb;
-
-	if (!sfb->fb.screen_base) {
-		dev_err(&pdev->dev,
-			"%s: unable to map screen memory\n", sfb->fb.fix.id);
-		return -ENOMEM;
-	}
-
-	return 0;
-}
-
-/*
- * Unmap in the screen memory
- *
- */
-static void smtc_unmap_smem(struct smtcfb_info *sfb)
-{
-	if (sfb && sfb->fb.screen_base) {
-		iounmap(sfb->fb.screen_base);
-		sfb->fb.screen_base = NULL;
-	}
-}
-
-/*
- * We need to wake up the device and make sure its in linear memory mode.
- */
-static inline void sm7xx_init_hw(void)
-{
-	outb_p(0x18, 0x3c4);
-	outb_p(0x11, 0x3c5);
-}
-
-static int smtcfb_pci_probe(struct pci_dev *pdev,
-				   const struct pci_device_id *ent)
-{
-	struct smtcfb_info *sfb;
-	u_long smem_size = 0x00800000;	/* default 8MB */
-	int err;
-	unsigned long mmio_base;
-
-	dev_info(&pdev->dev, "Silicon Motion display driver.");
-
-	err = pci_enable_device(pdev);	/* enable SMTC chip */
-	if (err)
-		return err;
-
-	sprintf(smtcfb_fix.id, "sm%Xfb", ent->device);
-
-	sfb = smtc_alloc_fb_info(pdev);
-
-	if (!sfb) {
-		err = -ENOMEM;
-		goto failed_free;
-	}
-
-	sfb->chip_id = ent->device;
-
-	pci_set_drvdata(pdev, sfb);
-
-	sm7xx_init_hw();
-
-	/* get mode parameter from smtc_scr_info */
-	if (smtc_scr_info.lfb_width != 0) {
-		sfb->fb.var.xres = smtc_scr_info.lfb_width;
-		sfb->fb.var.yres = smtc_scr_info.lfb_height;
-		sfb->fb.var.bits_per_pixel = smtc_scr_info.lfb_depth;
-	} else {
-		/* default resolution 1024x600 16bit mode */
-		sfb->fb.var.xres = SCREEN_X_RES;
-		sfb->fb.var.yres = SCREEN_Y_RES;
-		sfb->fb.var.bits_per_pixel = SCREEN_BPP;
-	}
-
-#ifdef __BIG_ENDIAN
-	if (sfb->fb.var.bits_per_pixel == 24)
-		sfb->fb.var.bits_per_pixel = (smtc_scr_info.lfb_depth = 32);
-#endif
-	/* Map address and memory detection */
-	mmio_base = pci_resource_start(pdev, 0);
-	pci_read_config_byte(pdev, PCI_REVISION_ID, &sfb->chip_rev_id);
-
-	switch (sfb->chip_id) {
-	case 0x710:
-	case 0x712:
-		sfb->fb.fix.mmio_start = mmio_base + 0x00400000;
-		sfb->fb.fix.mmio_len = 0x00400000;
-		smem_size = SM712_VIDEOMEMORYSIZE;
-#ifdef __BIG_ENDIAN
-		sfb->lfb = ioremap(mmio_base, 0x00c00000);
-#else
-		sfb->lfb = ioremap(mmio_base, 0x00800000);
-#endif
-		sfb->mmio = (smtc_RegBaseAddress =
-		    sfb->lfb + 0x00700000);
-		sfb->dp_regs = sfb->lfb + 0x00408000;
-		sfb->vp_regs = sfb->lfb + 0x0040c000;
-#ifdef __BIG_ENDIAN
-		if (sfb->fb.var.bits_per_pixel == 32) {
-			sfb->lfb += 0x800000;
-			dev_info(&pdev->dev, "sfb->lfb=%p", sfb->lfb);
-		}
-#endif
-		if (!smtc_RegBaseAddress) {
-			dev_err(&pdev->dev,
-				"%s: unable to map memory mapped IO!",
-				sfb->fb.fix.id);
-			err = -ENOMEM;
-			goto failed_fb;
-		}
-
-		/* set MCLK = 14.31818 * (0x16 / 0x2) */
-		smtc_seqw(0x6a, 0x16);
-		smtc_seqw(0x6b, 0x02);
-		smtc_seqw(0x62, 0x3e);
-		/* enable PCI burst */
-		smtc_seqw(0x17, 0x20);
-		/* enable word swap */
-#ifdef __BIG_ENDIAN
-		if (sfb->fb.var.bits_per_pixel == 32)
-			smtc_seqw(0x17, 0x30);
-#endif
-		break;
-	case 0x720:
-		sfb->fb.fix.mmio_start = mmio_base;
-		sfb->fb.fix.mmio_len = 0x00200000;
-		smem_size = SM722_VIDEOMEMORYSIZE;
-		sfb->dp_regs = ioremap(mmio_base, 0x00a00000);
-		sfb->lfb = sfb->dp_regs + 0x00200000;
-		sfb->mmio = (smtc_RegBaseAddress =
-		    sfb->dp_regs + 0x000c0000);
-		sfb->vp_regs = sfb->dp_regs + 0x800;
-
-		smtc_seqw(0x62, 0xff);
-		smtc_seqw(0x6a, 0x0d);
-		smtc_seqw(0x6b, 0x02);
-		break;
-	default:
-		dev_err(&pdev->dev,
-			"No valid Silicon Motion display chip was detected!");
-
-		goto failed_fb;
-	}
-
-	/* can support 32 bpp */
-	if (15 == sfb->fb.var.bits_per_pixel)
-		sfb->fb.var.bits_per_pixel = 16;
-
-	sfb->fb.var.xres_virtual = sfb->fb.var.xres;
-	sfb->fb.var.yres_virtual = sfb->fb.var.yres;
-	err = smtc_map_smem(sfb, pdev, smem_size);
-	if (err)
-		goto failed;
-
-	smtcfb_setmode(sfb);
-
-	err = register_framebuffer(&sfb->fb);
-	if (err < 0)
-		goto failed;
-
-	dev_info(&pdev->dev,
-		 "Silicon Motion SM%X Rev%X primary display mode %dx%d-%d Init Complete.",
-		 sfb->chip_id, sfb->chip_rev_id, sfb->fb.var.xres,
-		 sfb->fb.var.yres, sfb->fb.var.bits_per_pixel);
-
-	return 0;
-
-failed:
-	dev_err(&pdev->dev, "Silicon Motion, Inc. primary display init fail.");
-
-	smtc_unmap_smem(sfb);
-	smtc_unmap_mmio(sfb);
-failed_fb:
-	smtc_free_fb_info(sfb);
-
-failed_free:
-	pci_disable_device(pdev);
-
-	return err;
-}
-
-/*
- * 0x710 (LynxEM)
- * 0x712 (LynxEM+)
- * 0x720 (Lynx3DM, Lynx3DM+)
- */
-static const struct pci_device_id smtcfb_pci_table[] = {
-	{ PCI_DEVICE(0x126f, 0x710), },
-	{ PCI_DEVICE(0x126f, 0x712), },
-	{ PCI_DEVICE(0x126f, 0x720), },
-	{0,}
-};
-
-static void smtcfb_pci_remove(struct pci_dev *pdev)
-{
-	struct smtcfb_info *sfb;
-
-	sfb = pci_get_drvdata(pdev);
-	smtc_unmap_smem(sfb);
-	smtc_unmap_mmio(sfb);
-	unregister_framebuffer(&sfb->fb);
-	smtc_free_fb_info(sfb);
-}
-
-#ifdef CONFIG_PM
-static int smtcfb_pci_suspend(struct device *device)
-{
-	struct pci_dev *pdev = to_pci_dev(device);
-	struct smtcfb_info *sfb;
-
-	sfb = pci_get_drvdata(pdev);
-
-	/* set the hw in sleep mode use external clock and self memory refresh
-	 * so that we can turn off internal PLLs later on
-	 */
-	smtc_seqw(0x20, (smtc_seqr(0x20) | 0xc0));
-	smtc_seqw(0x69, (smtc_seqr(0x69) & 0xf7));
-
-	console_lock();
-	fb_set_suspend(&sfb->fb, 1);
-	console_unlock();
-
-	/* additionally turn off all function blocks including internal PLLs */
-	smtc_seqw(0x21, 0xff);
-
-	return 0;
-}
-
-static int smtcfb_pci_resume(struct device *device)
-{
-	struct pci_dev *pdev = to_pci_dev(device);
-	struct smtcfb_info *sfb;
-
-	sfb = pci_get_drvdata(pdev);
-
-	/* reinit hardware */
-	sm7xx_init_hw();
-	switch (sfb->chip_id) {
-	case 0x710:
-	case 0x712:
-		/* set MCLK = 14.31818 *  (0x16 / 0x2) */
-		smtc_seqw(0x6a, 0x16);
-		smtc_seqw(0x6b, 0x02);
-		smtc_seqw(0x62, 0x3e);
-		/* enable PCI burst */
-		smtc_seqw(0x17, 0x20);
-#ifdef __BIG_ENDIAN
-		if (sfb->fb.var.bits_per_pixel == 32)
-			smtc_seqw(0x17, 0x30);
-#endif
-		break;
-	case 0x720:
-		smtc_seqw(0x62, 0xff);
-		smtc_seqw(0x6a, 0x0d);
-		smtc_seqw(0x6b, 0x02);
-		break;
-	}
-
-	smtc_seqw(0x34, (smtc_seqr(0x34) | 0xc0));
-	smtc_seqw(0x33, ((smtc_seqr(0x33) | 0x08) & 0xfb));
-
-	smtcfb_setmode(sfb);
-
-	console_lock();
-	fb_set_suspend(&sfb->fb, 0);
-	console_unlock();
-
-	return 0;
-}
-
-static SIMPLE_DEV_PM_OPS(sm7xx_pm_ops, smtcfb_pci_suspend, smtcfb_pci_resume);
-#define SM7XX_PM_OPS (&sm7xx_pm_ops)
-
-#else  /* !CONFIG_PM */
-
-#define SM7XX_PM_OPS NULL
-
-#endif /* !CONFIG_PM */
-
-static struct pci_driver smtcfb_driver = {
-	.name = "smtcfb",
-	.id_table = smtcfb_pci_table,
-	.probe = smtcfb_pci_probe,
-	.remove = smtcfb_pci_remove,
-	.driver.pm  = SM7XX_PM_OPS,
-};
-
-module_pci_driver(smtcfb_driver);
-
-MODULE_AUTHOR("Siliconmotion ");
-MODULE_DESCRIPTION("Framebuffer driver for SMI Graphic Cards");
-MODULE_LICENSE("GPL");
diff --git a/drivers/staging/tidspbridge/core/io_sm.c b/drivers/staging/tidspbridge/core/io_sm.c
index e322fb7..c2829aa 100644
--- a/drivers/staging/tidspbridge/core/io_sm.c
+++ b/drivers/staging/tidspbridge/core/io_sm.c
@@ -2127,7 +2127,7 @@
 	u32 module_size;
 	u32 module_struct_size = 0;
 	u32 sect_ndx;
-	char *sect_str ;
+	char *sect_str;
 	int status = 0;
 
 	status = dev_get_intf_fxns(dev_object, &intf_fxns);
diff --git a/drivers/staging/tidspbridge/core/tiomap3430_pwr.c b/drivers/staging/tidspbridge/core/tiomap3430_pwr.c
index 1862afd..657104f 100644
--- a/drivers/staging/tidspbridge/core/tiomap3430_pwr.c
+++ b/drivers/staging/tidspbridge/core/tiomap3430_pwr.c
@@ -99,7 +99,8 @@
 			return -EPERM;
 		}
 		pwr_state = (*pdata->dsp_prm_read)(OMAP3430_IVA2_MOD,
-					OMAP2_PM_PWSTST) & OMAP_POWERSTATEST_MASK;
+						   OMAP2_PM_PWSTST) &
+						   OMAP_POWERSTATEST_MASK;
 	}
 	if (timeout == 0) {
 		pr_err("%s: Timed out waiting for DSP off mode\n", __func__);
@@ -209,7 +210,8 @@
 			return -EPERM;
 		}
 		pwr_state = (*pdata->dsp_prm_read)(OMAP3430_IVA2_MOD,
-					OMAP2_PM_PWSTST) & OMAP_POWERSTATEST_MASK;
+						   OMAP2_PM_PWSTST) &
+						   OMAP_POWERSTATEST_MASK;
 	}
 
 	if (!timeout) {
@@ -355,7 +357,7 @@
 	    (dev_context->brd_state == BRD_DSP_HIBERNATION)) {
 		dev_dbg(bridge, "OPP: %s IVA in sleep. No message to DSP\n");
 		return 0;
-	} else if ((dev_context->brd_state == BRD_RUNNING)) {
+	} else if (dev_context->brd_state == BRD_RUNNING) {
 		/* Send a prenotification to DSP */
 		dev_dbg(bridge, "OPP: %s sent notification to DSP\n", __func__);
 		sm_interrupt_dsp(dev_context, MBX_PM_SETPOINT_PRENOTIFY);
@@ -396,13 +398,14 @@
 		io_sh_msetting(hio_mgr, SHM_CURROPP, &level);
 		dev_dbg(bridge, "OPP: %s IVA in sleep. Wrote to shm\n",
 			__func__);
-	} else if ((dev_context->brd_state == BRD_RUNNING)) {
+	} else if (dev_context->brd_state == BRD_RUNNING) {
 		/* Update the OPP value in shared memory */
 		io_sh_msetting(hio_mgr, SHM_CURROPP, &level);
 		/* Send a post notification to DSP */
 		sm_interrupt_dsp(dev_context, MBX_PM_SETPOINT_POSTNOTIFY);
-		dev_dbg(bridge, "OPP: %s wrote to shm. Sent post notification "
-			"to DSP\n", __func__);
+		dev_dbg(bridge,
+			"OPP: %s wrote to shm. Sent post notification to DSP\n",
+			 __func__);
 	} else {
 		status = -EPERM;
 	}
diff --git a/drivers/staging/tidspbridge/dynload/tramp.c b/drivers/staging/tidspbridge/dynload/tramp.c
index 404af18..5f04313 100644
--- a/drivers/staging/tidspbridge/dynload/tramp.c
+++ b/drivers/staging/tidspbridge/dynload/tramp.c
@@ -503,7 +503,7 @@
  *	  TRAMPOLINES ARE TREATED AS 2ND PASS even though this is really
  *	  the first (and only) relocation that will be performed on them.
  */
-static int priv_pkt_relo(struct dload_state *dlthis, tgt_au_t * data,
+static int priv_pkt_relo(struct dload_state *dlthis, tgt_au_t *data,
 			 struct reloc_record_t *rp[], u32 relo_count)
 {
 	int ret_val = 1;
diff --git a/drivers/staging/tidspbridge/rmgr/dbdcd.c b/drivers/staging/tidspbridge/rmgr/dbdcd.c
index 190ca3f..2ae48c9 100644
--- a/drivers/staging/tidspbridge/rmgr/dbdcd.c
+++ b/drivers/staging/tidspbridge/rmgr/dbdcd.c
@@ -101,14 +101,14 @@
 	 * if the converted value doesn't fit in u32. So, convert the
 	 * last six bytes to u64 and memcpy what is needed
 	 */
-	if(sscanf(sz_uuid, "%8x%c%4hx%c%4hx%c%2hhx%2hhx%c%llx",
+	if (sscanf(sz_uuid, "%8x%c%4hx%c%4hx%c%2hhx%2hhx%c%llx",
 	       &uuid_tmp.data1, &c, &uuid_tmp.data2, &c,
 	       &uuid_tmp.data3, &c, &uuid_tmp.data4,
 	       &uuid_tmp.data5, &c, &t) != 10)
 		return -EINVAL;
 
 	t = cpu_to_be64(t);
-	memcpy(&uuid_tmp.data6[0], ((char*)&t) + 2, 6);
+	memcpy(&uuid_tmp.data6[0], ((char *)&t) + 2, 6);
 	*uuid_obj = uuid_tmp;
 
 	return 0;
diff --git a/drivers/staging/tidspbridge/rmgr/drv.c b/drivers/staging/tidspbridge/rmgr/drv.c
index be26917..757ae20 100644
--- a/drivers/staging/tidspbridge/rmgr/drv.c
+++ b/drivers/staging/tidspbridge/rmgr/drv.c
@@ -738,7 +738,7 @@
  *     Allocate physically contiguous, uncached memory from external memory pool
  */
 
-static void *mem_ext_phys_mem_alloc(u32 bytes, u32 align, u32 * phys_addr)
+static void *mem_ext_phys_mem_alloc(u32 bytes, u32 align, u32 *phys_addr)
 {
 	u32 new_alloc_ptr;
 	u32 offset;
diff --git a/drivers/staging/tidspbridge/rmgr/nldr.c b/drivers/staging/tidspbridge/rmgr/nldr.c
index ca38050..5ac507c 100644
--- a/drivers/staging/tidspbridge/rmgr/nldr.c
+++ b/drivers/staging/tidspbridge/rmgr/nldr.c
@@ -623,7 +623,7 @@
  *  ======== nldr_get_fxn_addr ========
  */
 int nldr_get_fxn_addr(struct nldr_nodeobject *nldr_node_obj,
-			     char *str_fxn, u32 * addr)
+			     char *str_fxn, u32 *addr)
 {
 	struct dbll_sym_val *dbll_sym;
 	struct nldr_object *nldr_obj;
@@ -1751,9 +1751,8 @@
 	}
 	if (ref_count && (*ref_count > 0)) {
 		*ref_count -= 1;
-		if (other_ref) {
+		if (other_ref)
 			*other_ref -= 1;
-		}
 	}
 
 	if (ref_count && *ref_count == 0) {
diff --git a/drivers/staging/tidspbridge/rmgr/node.c b/drivers/staging/tidspbridge/rmgr/node.c
index 87dfa92..9d3044a 100644
--- a/drivers/staging/tidspbridge/rmgr/node.c
+++ b/drivers/staging/tidspbridge/rmgr/node.c
@@ -246,7 +246,7 @@
 			    struct node_strmdef *pstrm_def,
 			    struct dsp_strmattr *pattrs);
 static void free_stream(struct node_mgr *hnode_mgr, struct stream_chnl stream);
-static int get_fxn_address(struct node_object *hnode, u32 * fxn_addr,
+static int get_fxn_address(struct node_object *hnode, u32 *fxn_addr,
 				  u32 phase);
 static int get_node_props(struct dcd_manager *hdcd_mgr,
 				 struct node_object *hnode,
@@ -406,7 +406,7 @@
 
 	/* check for page aligned Heap size */
 	if (((attr_in->heap_size) & (PG_SIZE4K - 1))) {
-		pr_err("%s: node heap size not aligned to 4K, size = 0x%x \n",
+		pr_err("%s: node heap size not aligned to 4K, size = 0x%x\n",
 		       __func__, attr_in->heap_size);
 		status = -EINVAL;
 	} else {
@@ -703,9 +703,9 @@
 		pattr = &node_dfltbufattrs;	/* set defaults */
 
 	status = proc_get_processor_id(pnode->processor, &proc_id);
-	if (proc_id != DSP_UNIT) {
+	if (proc_id != DSP_UNIT)
 		goto func_end;
-	}
+
 	/*  If segment ID includes MEM_SETVIRTUALSEGID then pbuffer is a
 	 *  virt  address, so set this info in this node's translator
 	 *  object for  future ref. If MEM_GETVIRTUALSEGID then retrieve
@@ -886,11 +886,10 @@
 	if (pattrs && pattrs->strm_mode != STRMMODE_PROCCOPY)
 		return -EPERM;	/* illegal stream mode */
 
-	if (node1_type != NODE_GPP) {
+	if (node1_type != NODE_GPP)
 		hnode_mgr = node1->node_mgr;
-	} else {
+	else
 		hnode_mgr = node2->node_mgr;
-	}
 
 	/* Enter critical section */
 	mutex_lock(&hnode_mgr->node_mgr_lock);
@@ -1576,7 +1575,7 @@
  *  Purpose:
  *      Frees the message buffer.
  */
-int node_free_msg_buf(struct node_object *hnode, u8 * pbuffer,
+int node_free_msg_buf(struct node_object *hnode, u8 *pbuffer,
 			     struct dsp_bufferattr *pattr)
 {
 	struct node_object *pnode = (struct node_object *)hnode;
@@ -2322,7 +2321,8 @@
 			if (!hdeh_mgr)
 				goto func_cont;
 
-			bridge_deh_notify(hdeh_mgr, DSP_SYSERROR, DSP_EXCEPTIONABORT);
+			bridge_deh_notify(hdeh_mgr, DSP_SYSERROR,
+					  DSP_EXCEPTIONABORT);
 		}
 	}
 func_cont:
@@ -2640,7 +2640,7 @@
  *  Purpose:
  *      Retrieves the address for create, execute or delete phase for a node.
  */
-static int get_fxn_address(struct node_object *hnode, u32 * fxn_addr,
+static int get_fxn_address(struct node_object *hnode, u32 *fxn_addr,
 				  u32 phase)
 {
 	char *pstr_fxn_name = NULL;
diff --git a/drivers/staging/unisys/Documentation/overview.txt b/drivers/staging/unisys/Documentation/overview.txt
new file mode 100644
index 0000000..8d078e4
--- /dev/null
+++ b/drivers/staging/unisys/Documentation/overview.txt
@@ -0,0 +1,174 @@
+
+Overview
+
+This document describes the driver set for Unisys Secure Partitioning (s-Par®).
+
+s-Par is firmware that provides hardware partitioning capabilities for
+splitting large-scale Intel x86 servers into multiple isolated
+partitions. s-Par provides a set of para-virtualized device drivers to
+allow guest partitions on the same server to share devices that would
+normally be unsharable; specifically, PCI network interfaces and host
+bus adapters that do not support shared access via SR-IOV. The shared
+device is owned and managed by a small, single-purpose service
+partition, which communicates with each guest partition sharing that
+device through an area of shared memory called a channel. Additional
+drivers provide support interfaces for communicating with s-Par
+services, logging and diagnostics, and accessing the Linux console
+from the s-Par user interface.
+
+The driver stack consists of a set of support modules, a set of bus
+modules, and a set of device driver modules. The support modules
+handle a number of common functions across each of the other
+drivers. The bus modules provide organization for the device driver
+modules, which provide the shared device functionality.
+
+These drivers are for the Unisys virtual PCI hardware model where the
+hypervisor need not intervene (other than normal interrupt handling)
+in the interactions between the client drivers and the virtual adapter
+firmware in the adapter service partition.
+
+Driver Descriptions
+
+Device Modules
+
+The modules in this section handle shared devices and the virtual
+buses required to support them. These modules use functions in and
+depend on the modules described in the support modules section.
+
+visorchipset
+
+The visorchipset module receives device creation and destruction
+events from the Command service partition of s-Par, as well as
+controlling registration of shared device drivers with the s-Par
+driver core. The events received are used to populate other s-Par
+modules with their assigned shared devices. Visorchipset is required
+for shared device drivers to function properly. Visorchipset also
+stores information for handling dump disk device creation during
+kdump.
+
+In operation, the visorchipset module processes device creation and
+destruction messages sent by s-Par's Command service partition through
+a channel. These messages result in creation (or destruction) of each
+virtual bus and virtual device. Each bus and device is also associated
+with a communication channel, which is used to communicate with one or
+more IO service partitions to perform device IO on behalf of the
+guest.
+
+virthba
+
+The virthba module provides access to a shared SCSI host bus adapter
+and one or more disk devices, by proxying SCSI commands between the
+guest and the service partition that owns the shared SCSI adapter,
+using a channel between the guest and the service partition. The disks
+that appear on the shared bus are defined by the s-Par configuration
+and enforced by the service partition, while the guest driver handles
+sending commands and handling responses. Each disk is shared as a
+whole to a guest. Sharing the bus adapter in this way provides
+resiliency; should the device encounter an error, only the service
+partition is rebooted, and the device is reinitialized. This allows
+guests to continue running and to recover from the error.
+
+virtnic
+
+The virtnic module provides a paravirtualized network interface to a
+guest by proxying buffer information between the guest and the service
+partition that owns the shared network interface, using a channel
+between the guest and the service partition. The connectivity of this
+interface with the shared interface and possibly other guest
+partitions is defined by the s-Par configuration and enforced by the
+service partition; the guest driver handles communication and link
+status.
+
+visorserial
+
+The visorserial module allows the console of the linux guest to be
+accessed via the s-Par console serial channel. It creates devices in
+/dev/visorserialclientX which behave like a serial terminal and are
+connected to the diagnostics system in s-Par. By assigning a getty to
+the terminal in the guest, a user could log into and access the guest
+from the s-Par diagnostics SWITCH RUN terminal.
+
+visorbus
+
+The visorbus module handles the bus functions for most functional
+drivers except visorserial, visordiag, virthba, and virtnic. It
+maintains the sysfs subtree /sys/devices/visorbus*/. It is responsible
+for device creation and destruction of the devices on its bus.
+
+visorclientbus
+
+The visorclientbus module forwards the bus functions for virthba, and
+virtnic to the virtpci driver.
+
+virtpci
+
+The virtpci module handles the bus functions for virthba, and virtnic.
+
+s-Par Integration Modules
+
+The modules in this section provide integration with s-Par guest
+partition services like diagnostics and remote desktop. These modules
+depend on functions in the modules described in the support modules
+section.
+
+visorvideoclient
+
+The visorvideoclient module provides functionality for video support
+for the Unisys s-Par Partition Desktop application. The guest OS must
+also have the UEFI GOP protocol enabled for the partition desktop to
+function.  visorconinclient The visorconinclient module provides
+keyboard and mouse support for the Unisys s-Par Partition Desktop
+application.
+
+sparstop
+
+The sparstop module handles requests from the Unisys s-Par platform to
+shutdown the linux guest. It allows a program on the guest to perform
+clean-up functions on the guest before the guest is shut down or
+rebooted using ACPI.
+
+visordiag
+
+This driver provides the ability for the guest to write information
+into the s-Par diagnostics subsystem. It creates a set of devices
+named /dev/visordiag.X which can be written to by the guest to add
+text to the s-Par system log.
+
+Support Modules
+
+The modules described in this section provide functions and
+abstractions to support the modules described in the previous
+sections, to avoid having duplicated functionality.
+
+visornoop
+
+The visornoop module is a placeholder that responds to device
+create/destroy messages that are currently not in use by linux guests.
+
+visoruislib
+
+The visoruislib module is a support library, used to handle requests
+from virtpci.
+
+visorchannelstub
+
+The visorchannelstub module provides support routines for storing and
+retrieving data from a channel.
+
+visorchannel
+
+The visorchannel module is a support library that abstracts reading
+and writing a channel in memory.
+
+visorutil
+
+The visorutil module is a support library required by all other s-Par
+driver modules. Among its features it abstracts reading, writing, and
+manipulating a block of memory.
+
+Minimum Required Driver Set
+
+The drivers required to boot a Linux guest are visorchipset, visorbus,
+visorvideoclient, visorconinclient, visoruislib, visorchannelstub,
+visorchannel, and visorutil. The other drivers are required by the
+product configurations that are currently being marketed.
diff --git a/drivers/staging/unisys/Documentation/proc-entries.txt b/drivers/staging/unisys/Documentation/proc-entries.txt
new file mode 100644
index 0000000..426f92b
--- /dev/null
+++ b/drivers/staging/unisys/Documentation/proc-entries.txt
@@ -0,0 +1,93 @@
+ s-Par Proc Entries
+This document describes the proc entries created by the Unisys s-Par modules.
+
+Support Module Entries
+These entries are provided primarily for debugging.
+
+/proc/uislib/info: This entry contains debugging information for the
+uislib module, including bus information and memory usage.
+
+/proc/visorchipset/controlvm: This directory contains debugging
+entries for the controlvm channel used by visorchipset.
+
+/proc/uislib/platform: This entry is used to display the platform
+number this node is in the system. For some guests, this may be
+invalid.
+
+/proc/visorchipset/chipsetready: This entry is written to by scripts
+to signify that any user level activity has been completed before the
+guest can be considered running and is shown as running in the s-Par
+UI.
+
+Device Entries
+These entries provide status of the devices shared by a service partition.
+
+/proc/uislib/vbus: this is a directory containing entries for each
+virtual bus. Each numbered sub-directory contains an info entry, which
+describes the devices that appear on that bus.
+
+/proc/uislib/cycles_before_wait: This entry is used to tune
+performance, by setting the number of cycles we wait before going idle
+when in polling mode. A longer time will reduce message latency but
+spend more processing time polling.
+
+/proc/uislib/smart_wakeup: This entry is used to tune performance, by
+enabling or disabling smart wakeup.
+
+/proc/virthba/info: This entry contains debugging information for the
+virthba module, including interrupt information and memory usage.
+
+/proc/virthba/enable_ints: This entry controls interrupt use by the
+virthba module. Writing a 0 to this entry will disable interrupts.
+
+/proc/virtnic/info: This entry contains debugging information for the
+virtnic module, including interrupt information, send and receive
+counts, and other device information.
+
+/proc/virtnic/ethX: This is a directory containing entries for each
+virtual NIC. Each named subdirectory contains two entries,
+clientstring and zone.
+
+/proc/virtpci/info: This entry contains debugging information for the
+virtpci module, including virtual PCI bus information and device
+locations.
+
+/proc/virtnic/enable_ints: This entry controls interrupt use by the
+virtnic module. Writing a 0 to this entry will disable interrupts.
+
+Visorconinclient, visordiag, visornoop, visorserialclient, and
+visorvideoclient Entries
+
+The entries in proc for these modules all follow the same
+pattern. Each module has its own proc directory with the same name,
+e.g. visordiag presents a /proc/visordiag directory. Inside of the
+module's directory are a device directory, which contains one numbered
+directory for each device provided by that module. Each device has a
+diag entry that presents the device number and visorbus name for that
+device. The module directory also has a driver/diag entry, which
+reports the corresponding s-Par version number of the driver.
+
+Automated Installation Entries
+
+These entries are used to pass information between the s-Par platform
+and the Linux-based installation and recovery tool. These values are
+read/write, however, the guest can only reset them to 0, or report an
+error status through the installer entry. The values are only set via
+s-Par's firmware interface, to help prevent accidentally booting into
+the tool.
+
+/proc/visorchipset/boottotool: This entry instructs s-Par that the
+next reboot will launch the installation and recovery tool. If set to
+0, the next boot will happen according to the UEFI boot manager
+settings.
+
+/proc/visorchipset/toolaction: This entry indicates the installation
+and recovery tool mode requested for the next boot.
+
+/proc/visorchipset/installer: this entry is used by the installation
+and recovery tool to pass status and result information back to the
+s-Par firmware.
+
+/proc/visorchipset/partition: This directory contains the guest
+partition configuration data for each virtual bus, for use during
+installation and at runtime for s-Par service partitions.
diff --git a/drivers/staging/unisys/Kconfig b/drivers/staging/unisys/Kconfig
new file mode 100644
index 0000000..ac080c9
--- /dev/null
+++ b/drivers/staging/unisys/Kconfig
@@ -0,0 +1,20 @@
+#
+# Unisys SPAR driver configuration
+#
+menuconfig UNISYSSPAR
+	bool "Unisys SPAR driver support"
+	depends on X86_64
+	---help---
+	Support for the Unisys SPAR drivers
+
+if UNISYSSPAR
+
+source "drivers/staging/unisys/visorutil/Kconfig"
+source "drivers/staging/unisys/visorchannel/Kconfig"
+source "drivers/staging/unisys/visorchipset/Kconfig"
+source "drivers/staging/unisys/channels/Kconfig"
+source "drivers/staging/unisys/uislib/Kconfig"
+source "drivers/staging/unisys/virtpci/Kconfig"
+source "drivers/staging/unisys/virthba/Kconfig"
+
+endif # UNISYSSPAR
diff --git a/drivers/staging/unisys/MAINTAINERS b/drivers/staging/unisys/MAINTAINERS
new file mode 100644
index 0000000..c9cef0b
--- /dev/null
+++ b/drivers/staging/unisys/MAINTAINERS
@@ -0,0 +1,6 @@
+Unisys s-Par drivers
+M:	Ben Romer <sparmaintainer@unisys.com>
+S:	Maintained
+F:	Documentation/s-Par/overview.txt
+F:	Documentation/s-Par/proc-entries.txt
+F:	drivers/staging/unisys/
diff --git a/drivers/staging/unisys/Makefile b/drivers/staging/unisys/Makefile
new file mode 100644
index 0000000..b988d69
--- /dev/null
+++ b/drivers/staging/unisys/Makefile
@@ -0,0 +1,10 @@
+#
+# Makefile for Unisys SPAR drivers
+#
+obj-$(CONFIG_UNISYS_VISORUTIL)		+= visorutil/
+obj-$(CONFIG_UNISYS_VISORCHANNEL)	+= visorchannel/
+obj-$(CONFIG_UNISYS_VISORCHIPSET)	+= visorchipset/
+obj-$(CONFIG_UNISYS_CHANNELSTUB)	+= channels/
+obj-$(CONFIG_UNISYS_UISLIB)		+= uislib/
+obj-$(CONFIG_UNISYS_VIRTPCI)		+= virtpci/
+obj-$(CONFIG_UNISYS_VIRTHBA)		+= virthba/
diff --git a/drivers/staging/unisys/TODO b/drivers/staging/unisys/TODO
new file mode 100644
index 0000000..c4265a2
--- /dev/null
+++ b/drivers/staging/unisys/TODO
@@ -0,0 +1,20 @@
+TODO:
+	-checkpatch warnings
+	-move /proc entries to /sys
+	-proper major number(s)
+	-add other drivers needed for full functionality:
+		-visorclientbus
+		-visorbus
+		-visordiag
+		-virtnic
+		-visornoop
+		-visorserial
+		-visorvideoclient
+		-visorconinclient
+		-sparstop
+	-move individual drivers into proper driver subsystems
+		
+
+Patches to:
+	Ken Cox <jkc@redhat.com>
+	Ben Romer <sparmaintainer@unisys.com>
diff --git a/drivers/staging/unisys/channels/Kconfig b/drivers/staging/unisys/channels/Kconfig
new file mode 100644
index 0000000..47a2353
--- /dev/null
+++ b/drivers/staging/unisys/channels/Kconfig
@@ -0,0 +1,10 @@
+#
+# Unisys channels configuration
+#
+
+config UNISYS_CHANNELSTUB
+	tristate "Unisys channelstub driver"
+	depends on UNISYSSPAR
+	---help---
+	If you say Y here, you will enable the Unisys channels driver.
+
diff --git a/drivers/staging/unisys/channels/Makefile b/drivers/staging/unisys/channels/Makefile
new file mode 100644
index 0000000..e60b0ae
--- /dev/null
+++ b/drivers/staging/unisys/channels/Makefile
@@ -0,0 +1,13 @@
+#
+# Makefile for Unisys channelstub
+#
+
+obj-$(CONFIG_UNISYS_CHANNELSTUB)	+= visorchannelstub.o
+
+visorchannelstub-y := channel.o chanstub.o
+
+ccflags-y += -Idrivers/staging/unisys/include
+ccflags-y += -Idrivers/staging/unisys/common-spar/include
+ccflags-y += -Idrivers/staging/unisys/common-spar/include/channels
+ccflags-y += -DCONFIG_SPAR_GUEST -DGUESTDRIVERBUILD -DNOAUTOVERSION
+
diff --git a/drivers/staging/unisys/channels/channel.c b/drivers/staging/unisys/channels/channel.c
new file mode 100644
index 0000000..afe8cea
--- /dev/null
+++ b/drivers/staging/unisys/channels/channel.c
@@ -0,0 +1,307 @@
+/* Copyright © 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+#include <linux/kernel.h>
+#ifdef CONFIG_MODVERSIONS
+#include <config/modversions.h>
+#endif
+#include <linux/module.h>
+#include <linux/init.h>		/* for module_init and module_exit */
+#include <linux/slab.h>		/* for memcpy */
+#include <linux/types.h>
+
+/* Implementation of exported functions for Supervisor channels */
+#include "channel.h"
+
+/*
+ * Routine Description:
+ * Tries to insert the prebuilt signal pointed to by pSignal into the nth
+ * Queue of the Channel pointed to by pChannel
+ *
+ * Parameters:
+ * pChannel: (IN) points to the IO Channel
+ * Queue: (IN) nth Queue of the IO Channel
+ * pSignal: (IN) pointer to the signal
+ *
+ * Assumptions:
+ * - pChannel, Queue and pSignal are valid.
+ * - If insertion fails due to a full queue, the caller will determine the
+ * retry policy (e.g. wait & try again, report an error, etc.).
+ *
+ * Return value:
+ * 1 if the insertion succeeds, 0 if the queue was full.
+ */
+unsigned char
+SignalInsert(pCHANNEL_HEADER pChannel, U32 Queue, void *pSignal)
+{
+	void *psignal;
+	unsigned int head, tail;
+	pSIGNAL_QUEUE_HEADER pqhdr =
+	    (pSIGNAL_QUEUE_HEADER) ((char *) pChannel +
+				    pChannel->oChannelSpace) + Queue;
+
+	/* capture current head and tail */
+	head = pqhdr->Head;
+	tail = pqhdr->Tail;
+
+	/* queue is full if (head + 1) % n equals tail */
+	if (((head + 1) % pqhdr->MaxSignalSlots) == tail) {
+		pqhdr->NumOverflows++;
+		return 0;
+	}
+
+	/* increment the head index */
+	head = (head + 1) % pqhdr->MaxSignalSlots;
+
+	/* copy signal to the head location from the area pointed to
+	 * by pSignal
+	 */
+	psignal =
+	    (char *) pqhdr + pqhdr->oSignalBase + (head * pqhdr->SignalSize);
+	MEMCPY(psignal, pSignal, pqhdr->SignalSize);
+
+	VolatileBarrier();
+	pqhdr->Head = head;
+
+	pqhdr->NumSignalsSent++;
+	return 1;
+}
+EXPORT_SYMBOL_GPL(SignalInsert);
+
+/*
+ * Routine Description:
+ * Removes one signal from Channel pChannel's nth Queue at the
+ * time of the call and copies it into the memory pointed to by
+ * pSignal.
+ *
+ * Parameters:
+ * pChannel: (IN) points to the IO Channel
+ * Queue: (IN) nth Queue of the IO Channel
+ * pSignal: (IN) pointer to where the signals are to be copied
+ *
+ * Assumptions:
+ * - pChannel and Queue are valid.
+ * - pSignal points to a memory area large enough to hold queue's SignalSize
+ *
+ * Return value:
+ * 1 if the removal succeeds, 0 if the queue was empty.
+ */
+unsigned char
+SignalRemove(pCHANNEL_HEADER pChannel, U32 Queue, void *pSignal)
+{
+	void *psource;
+	unsigned int head, tail;
+	pSIGNAL_QUEUE_HEADER pqhdr =
+	    (pSIGNAL_QUEUE_HEADER) ((char *) pChannel +
+				    pChannel->oChannelSpace) + Queue;
+
+	/* capture current head and tail */
+	head = pqhdr->Head;
+	tail = pqhdr->Tail;
+
+	/* queue is empty if the head index equals the tail index */
+	if (head == tail) {
+		pqhdr->NumEmptyCnt++;
+		return 0;
+	}
+
+	/* advance past the 'empty' front slot */
+	tail = (tail + 1) % pqhdr->MaxSignalSlots;
+
+	/* copy signal from tail location to the area pointed to by pSignal */
+	psource =
+	    (char *) pqhdr + pqhdr->oSignalBase + (tail * pqhdr->SignalSize);
+	MEMCPY(pSignal, psource, pqhdr->SignalSize);
+
+	VolatileBarrier();
+	pqhdr->Tail = tail;
+
+	pqhdr->NumSignalsReceived++;
+	return 1;
+}
+EXPORT_SYMBOL_GPL(SignalRemove);
+
+/*
+ * Routine Description:
+ * Removes all signals present in Channel pChannel's nth Queue at the
+ * time of the call and copies them into the memory pointed to by
+ * pSignal.  Returns the # of signals copied as the value of the routine.
+ *
+ * Parameters:
+ * pChannel: (IN) points to the IO Channel
+ * Queue: (IN) nth Queue of the IO Channel
+ * pSignal: (IN) pointer to where the signals are to be copied
+ *
+ * Assumptions:
+ * - pChannel and Queue are valid.
+ * - pSignal points to a memory area large enough to hold Queue's MaxSignals
+ * # of signals, each of which is Queue's SignalSize.
+ *
+ * Return value:
+ * # of signals copied.
+ */
+unsigned int
+SignalRemoveAll(pCHANNEL_HEADER pChannel, U32 Queue, void *pSignal)
+{
+	void *psource;
+	unsigned int head, tail, signalCount = 0;
+	pSIGNAL_QUEUE_HEADER pqhdr =
+	    (pSIGNAL_QUEUE_HEADER) ((char *) pChannel +
+				    pChannel->oChannelSpace) + Queue;
+
+	/* capture current head and tail */
+	head = pqhdr->Head;
+	tail = pqhdr->Tail;
+
+	/* queue is empty if the head index equals the tail index */
+	if (head == tail)
+		return 0;
+
+	while (head != tail) {
+		/* advance past the 'empty' front slot */
+		tail = (tail + 1) % pqhdr->MaxSignalSlots;
+
+		/* copy signal from tail location to the area pointed
+		 * to by pSignal
+		 */
+		psource =
+		    (char *) pqhdr + pqhdr->oSignalBase +
+		    (tail * pqhdr->SignalSize);
+		MEMCPY((char *) pSignal + (pqhdr->SignalSize * signalCount),
+		       psource, pqhdr->SignalSize);
+
+		VolatileBarrier();
+		pqhdr->Tail = tail;
+
+		signalCount++;
+		pqhdr->NumSignalsReceived++;
+	}
+
+	return signalCount;
+}
+
+/*
+ * Routine Description:
+ * Copies one signal from channel pChannel's nth Queue at the given position
+ * at the time of the call into the memory pointed to by pSignal.
+ *
+ * Parameters:
+ * pChannel: (IN) points to the IO Channel
+ * Queue: (IN) nth Queue of the IO Channel
+ * Position: (IN) nth entry in Queue of the IO Channel
+ * pSignal: (IN) pointer to where the signals are to be copied
+ *
+ * Assumptions:
+ * - pChannel and Queue are valid.
+ * - pSignal points to a memory area large enough to hold queue's SignalSize
+ *
+ * Return value:
+ * 1 if the copy succeeds, 0 if the queue was empty or Position was invalid.
+ */
+unsigned char
+SignalPeek(pCHANNEL_HEADER pChannel, U32 Queue, U32 Position, void *pSignal)
+{
+	void *psignal;
+	unsigned int head, tail;
+	pSIGNAL_QUEUE_HEADER pqhdr =
+	    (pSIGNAL_QUEUE_HEADER) ((char *) pChannel +
+				    pChannel->oChannelSpace) + Queue;
+
+	head = pqhdr->Head;
+	tail = pqhdr->Tail;
+
+	/* check if Position is out of range or queue is empty */
+	if (Position >= pqhdr->MaxSignalSlots || Position == tail
+	    || head == tail)
+		return 0;
+
+	/* check if Position is between tail and head */
+	if (head > tail) {
+		if (Position > head || Position < tail)
+			return 0;
+	} else if ((Position > head) && (Position < tail))
+		return 0;
+
+	/* copy signal from Position location to the area pointed to
+	 * by pSignal
+	 */
+	psignal =
+	    (char *) pqhdr + pqhdr->oSignalBase +
+	    (Position * pqhdr->SignalSize);
+	MEMCPY(pSignal, psignal, pqhdr->SignalSize);
+
+	return 1;
+}
+
+/*
+ * Routine Description:
+ * Determine whether a signal queue is empty.
+ *
+ * Parameters:
+ * pChannel: (IN) points to the IO Channel
+ * Queue: (IN) nth Queue of the IO Channel
+ *
+ * Return value:
+ * 1 if the signal queue is empty, 0 otherwise.
+ */
+unsigned char
+SignalQueueIsEmpty(pCHANNEL_HEADER pChannel, U32 Queue)
+{
+	pSIGNAL_QUEUE_HEADER pqhdr =
+	    (pSIGNAL_QUEUE_HEADER) ((char *) pChannel +
+				    pChannel->oChannelSpace) + Queue;
+	return pqhdr->Head == pqhdr->Tail;
+}
+EXPORT_SYMBOL_GPL(SignalQueueIsEmpty);
+
+/*
+ * Routine Description:
+ * Determine whether a signal queue is empty.
+ *
+ * Parameters:
+ * pChannel: (IN) points to the IO Channel
+ * Queue: (IN) nth Queue of the IO Channel
+ *
+ * Return value:
+ * 1 if the signal queue has 1 element, 0 otherwise.
+ */
+unsigned char
+SignalQueueHasOneElement(pCHANNEL_HEADER pChannel, U32 Queue)
+{
+	pSIGNAL_QUEUE_HEADER pqhdr =
+	    (pSIGNAL_QUEUE_HEADER) ((char *) pChannel +
+				    pChannel->oChannelSpace) + Queue;
+	return ((pqhdr->Tail + 1) % pqhdr->MaxSignalSlots) == pqhdr->Head;
+}
+
+/*
+ * Routine Description:
+ * Determine whether a signal queue is full.
+ *
+ * Parameters:
+ * pChannel: (IN) points to the IO Channel
+ * Queue: (IN) nth Queue of the IO Channel
+ *
+ * Return value:
+ * 1 if the signal queue is full, 0 otherwise.
+ */
+unsigned char
+SignalQueueIsFull(pCHANNEL_HEADER pChannel, U32 Queue)
+{
+	pSIGNAL_QUEUE_HEADER pqhdr =
+	    (pSIGNAL_QUEUE_HEADER) ((char *) pChannel +
+				    pChannel->oChannelSpace) + Queue;
+	return ((pqhdr->Head + 1) % pqhdr->MaxSignalSlots) == pqhdr->Tail;
+}
diff --git a/drivers/staging/unisys/channels/chanstub.c b/drivers/staging/unisys/channels/chanstub.c
new file mode 100644
index 0000000..37e207d
--- /dev/null
+++ b/drivers/staging/unisys/channels/chanstub.c
@@ -0,0 +1,70 @@
+/* Copyright © 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+#define EXPORT_SYMTAB
+#include <linux/kernel.h>
+#ifdef CONFIG_MODVERSIONS
+#include <config/modversions.h>
+#endif
+#include <linux/module.h>
+#include <linux/init.h>		/* for module_init and module_exit */
+#include <linux/slab.h>		/* for memcpy */
+#include <linux/types.h>
+
+#include "channel.h"
+#include "chanstub.h"
+#include "version.h"
+
+__init int
+channel_mod_init(void)
+{
+	return 0;
+}
+
+__exit void
+channel_mod_exit(void)
+{
+}
+
+unsigned char
+SignalInsert_withLock(pCHANNEL_HEADER pChannel, U32 Queue,
+		      void *pSignal, spinlock_t *lock)
+{
+	unsigned char result;
+	unsigned long flags;
+	spin_lock_irqsave(lock, flags);
+	result = SignalInsert(pChannel, Queue, pSignal);
+	spin_unlock_irqrestore(lock, flags);
+	return result;
+}
+
+unsigned char
+SignalRemove_withLock(pCHANNEL_HEADER pChannel, U32 Queue,
+		      void *pSignal, spinlock_t *lock)
+{
+	unsigned char result;
+	spin_lock(lock);
+	result = SignalRemove(pChannel, Queue, pSignal);
+	spin_unlock(lock);
+	return result;
+}
+
+module_init(channel_mod_init);
+module_exit(channel_mod_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Bryan Glaudel");
+MODULE_ALIAS("uischan");
+	/* this is extracted during depmod and kept in modules.dep */
diff --git a/drivers/staging/unisys/channels/chanstub.h b/drivers/staging/unisys/channels/chanstub.h
new file mode 100644
index 0000000..dadd7cd
--- /dev/null
+++ b/drivers/staging/unisys/channels/chanstub.h
@@ -0,0 +1,23 @@
+/* Copyright © 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+#ifndef __CHANSTUB_H__
+#define __CHANSTUB_H__
+unsigned char SignalInsert_withLock(pCHANNEL_HEADER pChannel, U32 Queue,
+				     void *pSignal, spinlock_t *lock);
+unsigned char SignalRemove_withLock(pCHANNEL_HEADER pChannel, U32 Queue,
+				     void *pSignal, spinlock_t *lock);
+
+#endif
diff --git a/drivers/staging/unisys/common-spar/include/channels/channel.h b/drivers/staging/unisys/common-spar/include/channels/channel.h
new file mode 100644
index 0000000..83906b4
--- /dev/null
+++ b/drivers/staging/unisys/common-spar/include/channels/channel.h
@@ -0,0 +1,645 @@
+/* Copyright © 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+#ifndef __CHANNEL_H__
+#define __CHANNEL_H__
+
+/*
+* Whenever this file is changed a corresponding change must be made in
+* the Console/ServicePart/visordiag_early/supervisor_channel.h file
+* which is needed for Linux kernel compiles. These two files must be
+* in sync.
+*/
+
+/* define the following to prevent include nesting in kernel header
+ * files of similar abreviated content
+ */
+#define __SUPERVISOR_CHANNEL_H__
+
+#include "commontypes.h"
+
+#define SIGNATURE_16(A, B) ((A) | (B<<8))
+#define SIGNATURE_32(A, B, C, D) \
+	(SIGNATURE_16(A, B) | (SIGNATURE_16(C, D) << 16))
+#define SIGNATURE_64(A, B, C, D, E, F, G, H) \
+	(SIGNATURE_32(A, B, C, D) | ((U64)(SIGNATURE_32(E, F, G, H)) << 32))
+
+#ifndef lengthof
+#define lengthof(TYPE, MEMBER) (sizeof(((TYPE *)0)->MEMBER))
+#endif
+#ifndef COVERQ
+#define COVERQ(v, d)  (((v)+(d)-1) / (d))
+#endif
+#ifndef COVER
+#define COVER(v, d)   ((d)*COVERQ(v, d))
+#endif
+
+#ifndef GUID0
+#define GUID0 {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0} }
+#endif
+
+/*  The C language is inconsistent with respect to where it allows literal
+ *  constants, especially literal constant structs.  Literal constant structs
+ *  are allowed for initialization only, whereas other types of literal
+ *  constants are allowed anywhere.  We get around this inconsistency by
+ *  declaring a "static const" variable for each GUID.  This variable can be
+ *  used in expressions where the literal constant would not be allowed.
+ */
+static const GUID Guid0 = GUID0;
+
+#define ULTRA_CHANNEL_PROTOCOL_SIGNATURE  SIGNATURE_32('E', 'C', 'N', 'L')
+
+typedef enum {
+	CHANNELSRV_UNINITIALIZED = 0,	/* channel is in an undefined state */
+	CHANNELSRV_READY = 1	/* channel has been initialized by server */
+} CHANNEL_SERVERSTATE;
+
+typedef enum {
+	CHANNELCLI_DETACHED = 0,
+	CHANNELCLI_DISABLED = 1,	/* client can see channel but is NOT
+					 * allowed to use it unless given TBD
+					 * explicit request (should actually be
+					 * < DETACHED) */
+	CHANNELCLI_ATTACHING = 2,	/* legacy EFI client request
+					 * for EFI server to attach */
+	CHANNELCLI_ATTACHED = 3,	/* idle, but client may want
+					 * to use channel any time */
+	CHANNELCLI_BUSY = 4,	/* client either wants to use or is
+				 * using channel */
+	CHANNELCLI_OWNED = 5	/* "no worries" state - client can
+				 * access channel anytime */
+} CHANNEL_CLIENTSTATE;
+static inline const U8 *
+ULTRA_CHANNELCLI_STRING(U32 v)
+{
+	switch (v) {
+	case CHANNELCLI_DETACHED:
+		return (const U8 *) ("DETACHED");
+	case CHANNELCLI_DISABLED:
+		return (const U8 *) ("DISABLED");
+	case CHANNELCLI_ATTACHING:
+		return (const U8 *) ("ATTACHING");
+	case CHANNELCLI_ATTACHED:
+		return (const U8 *) ("ATTACHED");
+	case CHANNELCLI_BUSY:
+		return (const U8 *) ("BUSY");
+	case CHANNELCLI_OWNED:
+		return (const U8 *) ("OWNED");
+	default:
+		break;
+	}
+	return (const U8 *) ("?");
+}
+
+#define ULTRA_CHANNELSRV_IS_READY(x)     ((x) == CHANNELSRV_READY)
+#define ULTRA_CHANNEL_SERVER_READY(pChannel) \
+	(ULTRA_CHANNELSRV_IS_READY((pChannel)->SrvState))
+
+#define ULTRA_VALID_CHANNELCLI_TRANSITION(o, n)				\
+	(((((o) == CHANNELCLI_DETACHED) && ((n) == CHANNELCLI_DISABLED)) || \
+	  (((o) == CHANNELCLI_ATTACHING) && ((n) == CHANNELCLI_DISABLED)) || \
+	  (((o) == CHANNELCLI_ATTACHED) && ((n) == CHANNELCLI_DISABLED)) || \
+	  (((o) == CHANNELCLI_ATTACHING) && ((n) == CHANNELCLI_DETACHED)) || \
+	  (((o) == CHANNELCLI_ATTACHED) && ((n) == CHANNELCLI_DETACHED)) || \
+	  (((o) == CHANNELCLI_DETACHED) && ((n) == CHANNELCLI_ATTACHING)) || \
+	  (((o) == CHANNELCLI_ATTACHING) && ((n) == CHANNELCLI_ATTACHED)) || \
+	  (((o) == CHANNELCLI_DETACHED) && ((n) == CHANNELCLI_ATTACHED)) || \
+	  (((o) == CHANNELCLI_BUSY) && ((n) == CHANNELCLI_ATTACHED)) ||	\
+	  (((o) == CHANNELCLI_ATTACHED) && ((n) == CHANNELCLI_BUSY)) ||	\
+	  (((o) == CHANNELCLI_DETACHED) && ((n) == CHANNELCLI_OWNED)) || \
+	  (((o) == CHANNELCLI_DISABLED) && ((n) == CHANNELCLI_OWNED)) || \
+	  (((o) == CHANNELCLI_ATTACHING) && ((n) == CHANNELCLI_OWNED)) || \
+	  (((o) == CHANNELCLI_ATTACHED) && ((n) == CHANNELCLI_OWNED)) || \
+	  (((o) == CHANNELCLI_BUSY) && ((n) == CHANNELCLI_OWNED)) || (0)) \
+	 ? (1) : (0))
+
+#define ULTRA_CHANNEL_CLIENT_CHK_TRANSITION(old, new, chanId, logCtx,	\
+					    file, line)			\
+	do {								\
+		if (!ULTRA_VALID_CHANNELCLI_TRANSITION(old, new))	\
+			UltraLogEvent(logCtx,				\
+				      CHANNELSTATE_DIAG_EVENTID_TRANSITERR, \
+				      CHANNELSTATE_DIAG_SEVERITY, \
+				      CHANNELSTATE_DIAG_SUBSYS,		\
+				      __func__, __LINE__,		\
+				      "%s Channel StateTransition INVALID! (%s) %s(%d)-->%s(%d) @%s:%d\n", \
+				      chanId, "CliState<x>",		\
+				      ULTRA_CHANNELCLI_STRING(old),	\
+				      old,				\
+				      ULTRA_CHANNELCLI_STRING(new),	\
+				      new,				\
+				      PathName_Last_N_Nodes((U8 *)file, 4), \
+				      line);				\
+	} while (0)
+
+#define ULTRA_CHANNEL_CLIENT_TRANSITION(pChan, chanId, field, \
+					newstate, logCtx)		\
+	do {								\
+		ULTRA_CHANNEL_CLIENT_CHK_TRANSITION(			\
+			(((CHANNEL_HEADER *)(pChan))->field), newstate, \
+			chanId, logCtx, __FILE__, __LINE__);		\
+		UltraLogEvent(logCtx, CHANNELSTATE_DIAG_EVENTID_TRANSITOK, \
+			CHANNELSTATE_DIAG_SEVERITY, \
+			      CHANNELSTATE_DIAG_SUBSYS,			\
+			      __func__, __LINE__,			\
+			      "%s Channel StateTransition (%s) %s(%d)-->%s(%d) @%s:%d\n", \
+			      chanId, #field,				\
+			      ULTRA_CHANNELCLI_STRING(((CHANNEL_HEADER *) \
+						       (pChan))->field), \
+			      ((CHANNEL_HEADER *)(pChan))->field,	\
+			      ULTRA_CHANNELCLI_STRING(newstate),	\
+			      newstate,					\
+			      PathName_Last_N_Nodes(__FILE__, 4), __LINE__); \
+		((CHANNEL_HEADER *)(pChan))->field = newstate;		\
+		MEMORYBARRIER;						\
+	} while (0)
+
+#define ULTRA_CHANNEL_CLIENT_ACQUIRE_OS(pChan, chanId, logCtx)	\
+	ULTRA_channel_client_acquire_os(pChan, chanId, logCtx,		\
+					(char *)__FILE__, __LINE__,	\
+					(char *)__func__)
+#define ULTRA_CHANNEL_CLIENT_RELEASE_OS(pChan, chanId, logCtx)	\
+	ULTRA_channel_client_release_os(pChan, chanId, logCtx,	\
+		(char *)__FILE__, __LINE__, (char *)__func__)
+
+/* Values for ULTRA_CHANNEL_PROTOCOL.CliErrorBoot: */
+/* throttling invalid boot channel statetransition error due to client
+ * disabled */
+#define ULTRA_CLIERRORBOOT_THROTTLEMSG_DISABLED    0x01
+
+/* throttling invalid boot channel statetransition error due to client
+ * not attached */
+#define ULTRA_CLIERRORBOOT_THROTTLEMSG_NOTATTACHED 0x02
+
+/* throttling invalid boot channel statetransition error due to busy channel */
+#define ULTRA_CLIERRORBOOT_THROTTLEMSG_BUSY        0x04
+
+/* Values for ULTRA_CHANNEL_PROTOCOL.CliErrorOS: */
+/* throttling invalid guest OS channel statetransition error due to
+ * client disabled */
+#define ULTRA_CLIERROROS_THROTTLEMSG_DISABLED      0x01
+
+/* throttling invalid guest OS channel statetransition error due to
+ * client not attached */
+#define ULTRA_CLIERROROS_THROTTLEMSG_NOTATTACHED   0x02
+
+/* throttling invalid guest OS channel statetransition error due to
+ * busy channel */
+#define ULTRA_CLIERROROS_THROTTLEMSG_BUSY          0x04
+
+/* Values for ULTRA_CHANNEL_PROTOCOL.Features: This define exists so
+* that windows guest can look at the FeatureFlags in the io channel,
+* and configure the windows driver to use interrupts or not based on
+* this setting.  This flag is set in uislib after the
+* ULTRA_VHBA_init_channel is called.  All feature bits for all
+* channels should be defined here.  The io channel feature bits are
+* defined right here */
+#define ULTRA_IO_DRIVER_ENABLES_INTS (0x1ULL << 1)
+#define ULTRA_IO_CHANNEL_IS_POLLING (0x1ULL << 3)
+#define ULTRA_IO_IOVM_IS_OK_WITH_DRIVER_DISABLING_INTS (0x1ULL << 4)
+#define ULTRA_IO_DRIVER_DISABLES_INTS (0x1ULL << 5)
+#define ULTRA_IO_DRIVER_SUPPORTS_ENHANCED_RCVBUF_CHECKING (0x1ULL << 6)
+
+#pragma pack(push, 1)		/* both GCC and VC now allow this pragma */
+/* Common Channel Header */
+typedef struct _CHANNEL_HEADER {
+	U64 Signature;		/* Signature */
+	U32 LegacyState;	/* DEPRECATED - being replaced by */
+	/* /              SrvState, CliStateBoot, and CliStateOS below */
+	U32 HeaderSize;		/* sizeof(CHANNEL_HEADER) */
+	U64 Size;		/* Total size of this channel in bytes */
+	U64 Features;		/* Flags to modify behavior */
+	GUID Type;		/* Channel type: data, bus, control, etc. */
+	U64 PartitionHandle;	/* ID of guest partition */
+	U64 Handle;		/* Device number of this channel in client */
+	U64 oChannelSpace;	/* Offset in bytes to channel specific area */
+	U32 VersionId;		/* CHANNEL_HEADER Version ID */
+	U32 PartitionIndex;	/* Index of guest partition */
+	GUID ZoneGuid;		/* Guid of Channel's zone */
+	U32 oClientString;	/* offset from channel header to
+				 * nul-terminated ClientString (0 if
+				 * ClientString not present) */
+	U32 CliStateBoot;	/* CHANNEL_CLIENTSTATE of pre-boot
+				 * EFI client of this channel */
+	U32 CmdStateCli;	/* CHANNEL_COMMANDSTATE (overloaded in
+				 * Windows drivers, see ServerStateUp,
+				 * ServerStateDown, etc) */
+	U32 CliStateOS;		/* CHANNEL_CLIENTSTATE of Guest OS
+				 * client of this channel */
+	U32 ChannelCharacteristics;	/* CHANNEL_CHARACTERISTIC_<xxx> */
+	U32 CmdStateSrv;	/* CHANNEL_COMMANDSTATE (overloaded in
+				 * Windows drivers, see ServerStateUp,
+				 * ServerStateDown, etc) */
+	U32 SrvState;		/* CHANNEL_SERVERSTATE */
+	U8 CliErrorBoot;	/* bits to indicate err states for
+				 * boot clients, so err messages can
+				 * be throttled */
+	U8 CliErrorOS;		/* bits to indicate err states for OS
+				 * clients, so err messages can be
+				 * throttled */
+	U8 Filler[1];		/* Pad out to 128 byte cacheline */
+	/* Please add all new single-byte values below here */
+	U8 RecoverChannel;
+} CHANNEL_HEADER, *pCHANNEL_HEADER, ULTRA_CHANNEL_PROTOCOL;
+
+#define ULTRA_CHANNEL_ENABLE_INTS (0x1ULL << 0)
+
+/* Subheader for the Signal Type variation of the Common Channel */
+typedef struct _SIGNAL_QUEUE_HEADER {
+	/* 1st cache line */
+	U32 VersionId;		/* SIGNAL_QUEUE_HEADER Version ID */
+	U32 Type;		/* Queue type: storage, network */
+	U64 Size;		/* Total size of this queue in bytes */
+	U64 oSignalBase;	/* Offset to signal queue area */
+	U64 FeatureFlags;	/* Flags to modify behavior */
+	U64 NumSignalsSent;	/* Total # of signals placed in this queue */
+	U64 NumOverflows;	/* Total # of inserts failed due to
+				 * full queue */
+	U32 SignalSize;		/* Total size of a signal for this queue */
+	U32 MaxSignalSlots;	/* Max # of slots in queue, 1 slot is
+				 * always empty */
+	U32 MaxSignals;		/* Max # of signals in queue
+				 * (MaxSignalSlots-1) */
+	U32 Head;		/* Queue head signal # */
+	/* 2nd cache line */
+	U64 NumSignalsReceived;	/* Total # of signals removed from this queue */
+	U32 Tail;		/* Queue tail signal # (on separate
+				 * cache line) */
+	U32 Reserved1;		/* Reserved field */
+	U64 Reserved2;		/* Resrved field */
+	U64 ClientQueue;
+	U64 NumInterruptsReceived;	/* Total # of Interrupts received.  This
+					 * is incremented by the ISR in the
+					 * guest windows driver */
+	U64 NumEmptyCnt;	/* Number of times that SignalRemove
+				 * is called and returned Empty
+				 * Status. */
+	U32 ErrorFlags;		/* Error bits set during SignalReinit
+				 * to denote trouble with client's
+				 * fields */
+	U8 Filler[12];		/* Pad out to 64 byte cacheline */
+} SIGNAL_QUEUE_HEADER, *pSIGNAL_QUEUE_HEADER;
+
+#pragma pack(pop)
+
+#define SignalInit(chan, QHDRFLD, QDATAFLD, QDATATYPE, ver, typ)	\
+	do {								\
+		MEMSET(&chan->QHDRFLD, 0, sizeof(chan->QHDRFLD));	\
+		chan->QHDRFLD.VersionId = ver;				\
+		chan->QHDRFLD.Type = typ;				\
+		chan->QHDRFLD.Size = sizeof(chan->QDATAFLD);		\
+		chan->QHDRFLD.SignalSize = sizeof(QDATATYPE);		\
+		chan->QHDRFLD.oSignalBase = (UINTN)(chan->QDATAFLD)-	\
+			(UINTN)(&chan->QHDRFLD);			\
+		chan->QHDRFLD.MaxSignalSlots =				\
+			sizeof(chan->QDATAFLD)/sizeof(QDATATYPE);	\
+		chan->QHDRFLD.MaxSignals = chan->QHDRFLD.MaxSignalSlots-1; \
+	} while (0)
+
+/* Generic function useful for validating any type of channel when it is
+ * received by the client that will be accessing the channel.
+ * Note that <logCtx> is only needed for callers in the EFI environment, and
+ * is used to pass the EFI_DIAG_CAPTURE_PROTOCOL needed to log messages.
+ */
+static inline int
+ULTRA_check_channel_client(void *pChannel,
+			   GUID expectedTypeGuid,
+			   char *channelName,
+			   U64 expectedMinBytes,
+			   U32 expectedVersionId,
+			   U64 expectedSignature,
+			   char *fileName, int lineNumber, void *logCtx)
+{
+	if (MEMCMP(&expectedTypeGuid, &Guid0, sizeof(GUID)) != 0)
+		/* caller wants us to verify type GUID */
+		if (MEMCMP(&(((CHANNEL_HEADER *) (pChannel))->Type),
+			   &expectedTypeGuid, sizeof(GUID)) != 0) {
+			CHANNEL_GUID_MISMATCH(expectedTypeGuid, channelName,
+					      "type", expectedTypeGuid,
+					      ((CHANNEL_HEADER *)
+					       (pChannel))->Type, fileName,
+					      lineNumber, logCtx);
+			return 0;
+		}
+	if (expectedMinBytes > 0)	/* caller wants us to verify
+					 * channel size */
+		if (((CHANNEL_HEADER *) (pChannel))->Size < expectedMinBytes) {
+			CHANNEL_U64_MISMATCH(expectedTypeGuid, channelName,
+					     "size", expectedMinBytes,
+					     ((CHANNEL_HEADER *)
+					      (pChannel))->Size, fileName,
+					     lineNumber, logCtx);
+			return 0;
+		}
+	if (expectedVersionId > 0)	/* caller wants us to verify
+					 * channel version */
+		if (((CHANNEL_HEADER *) (pChannel))->VersionId !=
+		    expectedVersionId) {
+			CHANNEL_U32_MISMATCH(expectedTypeGuid, channelName,
+					     "version", expectedVersionId,
+					     ((CHANNEL_HEADER *)
+					      (pChannel))->VersionId, fileName,
+					     lineNumber, logCtx);
+			return 0;
+		}
+	if (expectedSignature > 0)	/* caller wants us to verify
+					 * channel signature */
+		if (((CHANNEL_HEADER *) (pChannel))->Signature !=
+		    expectedSignature) {
+			CHANNEL_U64_MISMATCH(expectedTypeGuid, channelName,
+					     "signature", expectedSignature,
+					     ((CHANNEL_HEADER *)
+					      (pChannel))->Signature, fileName,
+					     lineNumber, logCtx);
+			return 0;
+		}
+	return 1;
+}
+
+/* Generic function useful for validating any type of channel when it is about
+ * to be initialized by the server of the channel.
+ * Note that <logCtx> is only needed for callers in the EFI environment, and
+ * is used to pass the EFI_DIAG_CAPTURE_PROTOCOL needed to log messages.
+ */
+static inline int
+ULTRA_check_channel_server(GUID typeGuid,
+			   char *channelName,
+			   U64 expectedMinBytes,
+			   U64 actualBytes,
+			   char *fileName, int lineNumber, void *logCtx)
+{
+	if (expectedMinBytes > 0)	/* caller wants us to verify
+					 * channel size */
+		if (actualBytes < expectedMinBytes) {
+			CHANNEL_U64_MISMATCH(typeGuid, channelName, "size",
+					     expectedMinBytes, actualBytes,
+					     fileName, lineNumber, logCtx);
+			return 0;
+		}
+	return 1;
+}
+
+/* Given a file pathname <s> (with '/' or '\' separating directory nodes),
+ * returns a pointer to the beginning of a node within that pathname such
+ * that the number of nodes from that pointer to the end of the string is
+ * NOT more than <n>.  Note that if the pathname has less than <n> nodes
+ * in it, the return pointer will be to the beginning of the string.
+ */
+static inline U8 *
+PathName_Last_N_Nodes(U8 *s, unsigned int n)
+{
+	U8 *p = s;
+	unsigned int node_count = 0;
+	while (*p != '\0') {
+		if ((*p == '/') || (*p == '\\'))
+			node_count++;
+		p++;
+	}
+	if (node_count <= n)
+		return s;
+	while (n > 0) {
+		p--;
+		if (p == s)
+			break;	/* should never happen, unless someone
+				 * is changing the string while we are
+				 * looking at it!! */
+		if ((*p == '/') || (*p == '\\'))
+			n--;
+	}
+	return p + 1;
+}
+
+static inline int
+ULTRA_channel_client_acquire_os(void *pChannel, U8 *chanId, void *logCtx,
+				char *file, int line, char *func)
+{
+	CHANNEL_HEADER *pChan = (CHANNEL_HEADER *) (pChannel);
+
+	if (pChan->CliStateOS == CHANNELCLI_DISABLED) {
+		if ((pChan->
+		     CliErrorOS & ULTRA_CLIERROROS_THROTTLEMSG_DISABLED) == 0) {
+			/* we are NOT throttling this message */
+			pChan->CliErrorOS |=
+				ULTRA_CLIERROROS_THROTTLEMSG_DISABLED;
+			/* throttle until acquire successful */
+
+			UltraLogEvent(logCtx,
+				      CHANNELSTATE_DIAG_EVENTID_TRANSITERR,
+				      CHANNELSTATE_DIAG_SEVERITY,
+				      CHANNELSTATE_DIAG_SUBSYS, func, line,
+				      "%s Channel StateTransition INVALID! - acquire failed because OS client DISABLED @%s:%d\n",
+				      chanId, PathName_Last_N_Nodes(
+					      (U8 *) file, 4), line);
+		}
+		return 0;
+	}
+	if ((pChan->CliStateOS != CHANNELCLI_OWNED)
+	    && (pChan->CliStateBoot == CHANNELCLI_DISABLED)) {
+		/* Our competitor is DISABLED, so we can transition to OWNED */
+		UltraLogEvent(logCtx, CHANNELSTATE_DIAG_EVENTID_TRANSITOK,
+			      CHANNELSTATE_DIAG_SEVERITY,
+			      CHANNELSTATE_DIAG_SUBSYS, func, line,
+			      "%s Channel StateTransition (%s) %s(%d)-->%s(%d) @%s:%d\n",
+			      chanId, "CliStateOS",
+			      ULTRA_CHANNELCLI_STRING(pChan->CliStateOS),
+			      pChan->CliStateOS,
+			      ULTRA_CHANNELCLI_STRING(CHANNELCLI_OWNED),
+			      CHANNELCLI_OWNED,
+			      PathName_Last_N_Nodes((U8 *) file, 4), line);
+		pChan->CliStateOS = CHANNELCLI_OWNED;
+		MEMORYBARRIER;
+	}
+	if (pChan->CliStateOS == CHANNELCLI_OWNED) {
+		if (pChan->CliErrorOS != 0) {
+			/* we are in an error msg throttling state;
+			 * come out of it */
+			UltraLogEvent(logCtx,
+				      CHANNELSTATE_DIAG_EVENTID_TRANSITOK,
+				      CHANNELSTATE_DIAG_SEVERITY,
+				      CHANNELSTATE_DIAG_SUBSYS, func, line,
+				      "%s Channel OS client acquire now successful @%s:%d\n",
+				      chanId, PathName_Last_N_Nodes((U8 *) file,
+								    4), line);
+			pChan->CliErrorOS = 0;
+		}
+		return 1;
+	}
+
+	/* We have to do it the "hard way".  We transition to BUSY,
+	* and can use the channel iff our competitor has not also
+	* transitioned to BUSY. */
+	if (pChan->CliStateOS != CHANNELCLI_ATTACHED) {
+		if ((pChan->
+		     CliErrorOS & ULTRA_CLIERROROS_THROTTLEMSG_NOTATTACHED) ==
+		    0) {
+			/* we are NOT throttling this message */
+			pChan->CliErrorOS |=
+				ULTRA_CLIERROROS_THROTTLEMSG_NOTATTACHED;
+			/* throttle until acquire successful */
+			UltraLogEvent(logCtx,
+				      CHANNELSTATE_DIAG_EVENTID_TRANSITERR,
+				      CHANNELSTATE_DIAG_SEVERITY,
+				      CHANNELSTATE_DIAG_SUBSYS, func, line,
+				      "%s Channel StateTransition INVALID! - acquire failed because OS client NOT ATTACHED (state=%s(%d)) @%s:%d\n",
+				      chanId,
+				      ULTRA_CHANNELCLI_STRING(pChan->CliStateOS),
+				      pChan->CliStateOS,
+				      PathName_Last_N_Nodes((U8 *) file, 4),
+				      line);
+		}
+		return 0;
+	}
+	pChan->CliStateOS = CHANNELCLI_BUSY;
+	MEMORYBARRIER;
+	if (pChan->CliStateBoot == CHANNELCLI_BUSY) {
+		if ((pChan->CliErrorOS & ULTRA_CLIERROROS_THROTTLEMSG_BUSY) ==
+		    0) {
+			/* we are NOT throttling this message */
+			pChan->CliErrorOS |= ULTRA_CLIERROROS_THROTTLEMSG_BUSY;
+			/* throttle until acquire successful */
+			UltraLogEvent(logCtx,
+				      CHANNELSTATE_DIAG_EVENTID_TRANSITBUSY,
+				      CHANNELSTATE_DIAG_SEVERITY,
+				      CHANNELSTATE_DIAG_SUBSYS, func, line,
+				      "%s Channel StateTransition failed - host OS acquire failed because boot BUSY @%s:%d\n",
+				      chanId, PathName_Last_N_Nodes((U8 *) file,
+								    4), line);
+		}
+		pChan->CliStateOS = CHANNELCLI_ATTACHED;	/* reset busy */
+		MEMORYBARRIER;
+		return 0;
+	}
+	if (pChan->CliErrorOS != 0) {
+		/* we are in an error msg throttling state; come out of it */
+		UltraLogEvent(logCtx, CHANNELSTATE_DIAG_EVENTID_TRANSITOK,
+			      CHANNELSTATE_DIAG_SEVERITY,
+			      CHANNELSTATE_DIAG_SUBSYS, func, line,
+			      "%s Channel OS client acquire now successful @%s:%d\n",
+			      chanId, PathName_Last_N_Nodes((U8 *) file, 4),
+			      line);
+		pChan->CliErrorOS = 0;
+	}
+	return 1;
+}
+
+static inline void
+ULTRA_channel_client_release_os(void *pChannel, U8 *chanId, void *logCtx,
+				char *file, int line, char *func)
+{
+	CHANNEL_HEADER *pChan = (CHANNEL_HEADER *) (pChannel);
+	if (pChan->CliErrorOS != 0) {
+		/* we are in an error msg throttling state; come out of it */
+		UltraLogEvent(logCtx, CHANNELSTATE_DIAG_EVENTID_TRANSITOK,
+			      CHANNELSTATE_DIAG_SEVERITY,
+			      CHANNELSTATE_DIAG_SUBSYS, func, line,
+			      "%s Channel OS client error state cleared @%s:%d\n",
+			      chanId, PathName_Last_N_Nodes((U8 *) file, 4),
+			      line);
+		pChan->CliErrorOS = 0;
+	}
+	if (pChan->CliStateOS == CHANNELCLI_OWNED)
+		return;
+	if (pChan->CliStateOS != CHANNELCLI_BUSY) {
+		UltraLogEvent(logCtx, CHANNELSTATE_DIAG_EVENTID_TRANSITERR,
+			      CHANNELSTATE_DIAG_SEVERITY,
+			      CHANNELSTATE_DIAG_SUBSYS, func, line,
+			      "%s Channel StateTransition INVALID! - release failed because OS client NOT BUSY (state=%s(%d)) @%s:%d\n",
+			      chanId,
+			      ULTRA_CHANNELCLI_STRING(pChan->CliStateOS),
+			      pChan->CliStateOS,
+			      PathName_Last_N_Nodes((U8 *) file, 4), line);
+		/* return; */
+	}
+	pChan->CliStateOS = CHANNELCLI_ATTACHED;	/* release busy */
+}
+
+/*
+* Routine Description:
+* Tries to insert the prebuilt signal pointed to by pSignal into the nth
+* Queue of the Channel pointed to by pChannel
+*
+* Parameters:
+* pChannel: (IN) points to the IO Channel
+* Queue: (IN) nth Queue of the IO Channel
+* pSignal: (IN) pointer to the signal
+*
+* Assumptions:
+* - pChannel, Queue and pSignal are valid.
+* - If insertion fails due to a full queue, the caller will determine the
+* retry policy (e.g. wait & try again, report an error, etc.).
+*
+* Return value: 1 if the insertion succeeds, 0 if the queue was
+* full.
+*/
+
+unsigned char SignalInsert(pCHANNEL_HEADER pChannel, U32 Queue, void *pSignal);
+
+/*
+* Routine Description:
+* Removes one signal from Channel pChannel's nth Queue at the
+* time of the call and copies it into the memory pointed to by
+* pSignal.
+*
+* Parameters:
+* pChannel: (IN) points to the IO Channel
+* Queue: (IN) nth Queue of the IO Channel
+* pSignal: (IN) pointer to where the signals are to be copied
+*
+* Assumptions:
+* - pChannel and Queue are valid.
+* - pSignal points to a memory area large enough to hold queue's SignalSize
+*
+* Return value: 1 if the removal succeeds, 0 if the queue was
+* empty.
+*/
+
+unsigned char SignalRemove(pCHANNEL_HEADER pChannel, U32 Queue, void *pSignal);
+
+/*
+* Routine Description:
+* Removes all signals present in Channel pChannel's nth Queue at the
+* time of the call and copies them into the memory pointed to by
+* pSignal.  Returns the # of signals copied as the value of the routine.
+*
+* Parameters:
+* pChannel: (IN) points to the IO Channel
+* Queue: (IN) nth Queue of the IO Channel
+* pSignal: (IN) pointer to where the signals are to be copied
+*
+* Assumptions:
+* - pChannel and Queue are valid.
+* - pSignal points to a memory area large enough to hold Queue's MaxSignals
+* # of signals, each of which is Queue's SignalSize.
+*
+* Return value:
+* # of signals copied.
+*/
+unsigned int SignalRemoveAll(pCHANNEL_HEADER pChannel, U32 Queue,
+			     void *pSignal);
+
+/*
+* Routine Description:
+* Determine whether a signal queue is empty.
+*
+* Parameters:
+* pChannel: (IN) points to the IO Channel
+* Queue: (IN) nth Queue of the IO Channel
+*
+* Return value:
+* 1 if the signal queue is empty, 0 otherwise.
+*/
+unsigned char SignalQueueIsEmpty(pCHANNEL_HEADER pChannel, U32 Queue);
+
+#endif
diff --git a/drivers/staging/unisys/common-spar/include/channels/channel_guid.h b/drivers/staging/unisys/common-spar/include/channels/channel_guid.h
new file mode 100644
index 0000000..ae0dc2b
--- /dev/null
+++ b/drivers/staging/unisys/common-spar/include/channels/channel_guid.h
@@ -0,0 +1,64 @@
+/* Copyright © 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+/*
+ * CHANNEL Guids
+ */
+
+/* Used in IOChannel
+ * {414815ed-c58c-11da-95a9-00e08161165f}
+ */
+#define ULTRA_VHBA_CHANNEL_PROTOCOL_GUID \
+	{ 0x414815ed, 0xc58c, 0x11da, \
+		{ 0x95, 0xa9, 0x0, 0xe0, 0x81, 0x61, 0x16, 0x5f } }
+static const GUID UltraVhbaChannelProtocolGuid =
+	ULTRA_VHBA_CHANNEL_PROTOCOL_GUID;
+
+/* Used in IOChannel
+ * {8cd5994d-c58e-11da-95a9-00e08161165f}
+ */
+#define ULTRA_VNIC_CHANNEL_PROTOCOL_GUID \
+	{ 0x8cd5994d, 0xc58e, 0x11da, \
+		{ 0x95, 0xa9, 0x0, 0xe0, 0x81, 0x61, 0x16, 0x5f } }
+static const GUID UltraVnicChannelProtocolGuid =
+	ULTRA_VNIC_CHANNEL_PROTOCOL_GUID;
+
+/* Used in IOChannel
+ * {72120008-4AAB-11DC-8530-444553544200}
+ */
+#define ULTRA_SIOVM_GUID \
+	{ 0x72120008, 0x4AAB, 0x11DC,					\
+		{ 0x85, 0x30, 0x44, 0x45, 0x53, 0x54, 0x42, 0x00 } }
+static const GUID UltraSIOVMGuid = ULTRA_SIOVM_GUID;
+
+
+/* Used in visornoop/visornoop_main.c
+ * {5b52c5ac-e5f5-4d42-8dff-429eaecd221f}
+ */
+#define ULTRA_CONTROLDIRECTOR_CHANNEL_PROTOCOL_GUID  \
+	{ 0x5b52c5ac, 0xe5f5, 0x4d42, \
+		{ 0x8d, 0xff, 0x42, 0x9e, 0xae, 0xcd, 0x22, 0x1f } }
+
+static const GUID UltraControlDirectorChannelProtocolGuid =
+	ULTRA_CONTROLDIRECTOR_CHANNEL_PROTOCOL_GUID;
+
+/* Used in visorchipset/visorchipset_main.c
+ * {B4E79625-AEDE-4EAA-9E11-D3EDDCD4504C}
+ */
+#define ULTRA_DIAG_POOL_CHANNEL_PROTOCOL_GUID				\
+	{0xb4e79625, 0xaede, 0x4eaa,					\
+		{ 0x9e, 0x11, 0xd3, 0xed, 0xdc, 0xd4, 0x50, 0x4c } }
+
+
diff --git a/drivers/staging/unisys/common-spar/include/channels/controlframework.h b/drivers/staging/unisys/common-spar/include/channels/controlframework.h
new file mode 100644
index 0000000..5126433
--- /dev/null
+++ b/drivers/staging/unisys/common-spar/include/channels/controlframework.h
@@ -0,0 +1,77 @@
+/* Copyright © 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+/*
+ * Module Name:
+ *  controlframework.h
+ *
+ * Abstract: This file defines common structures in the unmanaged
+ *	     Ultravisor (mostly EFI) space.
+ *
+ */
+
+#ifndef _CONTROL_FRAMEWORK_H_
+#define _CONTROL_FRAMEWORK_H_
+
+#include "commontypes.h"
+#include "channel.h"
+
+#define ULTRA_MEMORY_COUNT_Ki 1024
+
+/* Scale order 0 is one 32-bit (4-byte) word (in 64 or 128-bit
+ * architecture potentially 64 or 128-bit word) */
+#define ULTRA_MEMORY_PAGE_WORD 4
+
+/* Define Ki scale page to be traditional 4KB page */
+#define ULTRA_MEMORY_PAGE_Ki (ULTRA_MEMORY_PAGE_WORD * ULTRA_MEMORY_COUNT_Ki)
+typedef struct _ULTRA_SEGMENT_STATE  {
+	U16 Enabled:1;		/* Bit 0: May enter other states */
+	U16 Active:1;		/* Bit 1: Assigned to active partition */
+	U16 Alive:1;		/* Bit 2: Configure message sent to
+				 * service/server */
+	U16 Revoked:1;		/* Bit 3: similar to partition state
+				 * ShuttingDown */
+	U16 Allocated:1;	/* Bit 4: memory (device/port number)
+				 * has been selected by Command */
+	U16 Known:1;		/* Bit 5: has been introduced to the
+				 * service/guest partition */
+	U16 Ready:1;		/* Bit 6: service/Guest partition has
+				 * responded to introduction */
+	U16 Operating:1;	/* Bit 7: resource is configured and
+				 * operating */
+	/* Note: don't use high bit unless we need to switch to ushort
+	 * which is non-compliant */
+} ULTRA_SEGMENT_STATE;
+static const ULTRA_SEGMENT_STATE SegmentStateRunning = {
+	1, 1, 1, 0, 1, 1, 1, 1
+};
+static const ULTRA_SEGMENT_STATE SegmentStatePaused = {
+	1, 1, 1, 0, 1, 1, 1, 0
+};
+static const ULTRA_SEGMENT_STATE SegmentStateStandby = {
+	1, 1, 0, 0, 1, 1, 1, 0
+};
+typedef union {
+	U64 Full;
+	struct {
+		U8 Major;	/* will be 1 for the first release and
+				 * increment thereafter  */
+		U8 Minor;
+		U16 Maintenance;
+		U32 Revision;	/* Subversion revision */
+	} Part;
+} ULTRA_COMPONENT_VERSION;
+
+#endif				/* _CONTROL_FRAMEWORK_H_ not defined */
diff --git a/drivers/staging/unisys/common-spar/include/channels/controlvmchannel.h b/drivers/staging/unisys/common-spar/include/channels/controlvmchannel.h
new file mode 100644
index 0000000..47f1c4f
--- /dev/null
+++ b/drivers/staging/unisys/common-spar/include/channels/controlvmchannel.h
@@ -0,0 +1,619 @@
+/* Copyright © 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+#ifndef __CONTROLVMCHANNEL_H__
+#define __CONTROLVMCHANNEL_H__
+
+#include "commontypes.h"
+#include "channel.h"
+#include "controlframework.h"
+enum { INVALID_GUEST_FIRMWARE, SAMPLE_GUEST_FIRMWARE,
+	    TIANO32_GUEST_FIRMWARE, TIANO64_GUEST_FIRMWARE
+};
+
+/* {2B3C2D10-7EF5-4ad8-B966-3448B7386B3D} */
+#define ULTRA_CONTROLVM_CHANNEL_PROTOCOL_GUID	\
+	{0x2b3c2d10, 0x7ef5, 0x4ad8, \
+		{0xb9, 0x66, 0x34, 0x48, 0xb7, 0x38, 0x6b, 0x3d} }
+
+static const GUID UltraControlvmChannelProtocolGuid =
+	ULTRA_CONTROLVM_CHANNEL_PROTOCOL_GUID;
+
+#define ULTRA_CONTROLVM_CHANNEL_PROTOCOL_SIGNATURE \
+	ULTRA_CHANNEL_PROTOCOL_SIGNATURE
+#define CONTROLVM_MESSAGE_MAX     64
+
+/* Must increment this whenever you insert or delete fields within
+* this channel struct.  Also increment whenever you change the meaning
+* of fields within this channel struct so as to break pre-existing
+* software.  Note that you can usually add fields to the END of the
+* channel struct withOUT needing to increment this. */
+#define ULTRA_CONTROLVM_CHANNEL_PROTOCOL_VERSIONID  1
+
+#define ULTRA_CONTROLVM_CHANNEL_OK_CLIENT(pChannel, logCtx)           \
+	(ULTRA_check_channel_client(pChannel, \
+		UltraControlvmChannelProtocolGuid, \
+		"controlvm", \
+		sizeof(ULTRA_CONTROLVM_CHANNEL_PROTOCOL), \
+		ULTRA_CONTROLVM_CHANNEL_PROTOCOL_VERSIONID, \
+		ULTRA_CONTROLVM_CHANNEL_PROTOCOL_SIGNATURE, \
+		__FILE__, __LINE__, logCtx))
+#define ULTRA_CONTROLVM_CHANNEL_OK_SERVER(actualBytes, logCtx)        \
+	(ULTRA_check_channel_server(UltraControlvmChannelProtocolGuid,	\
+				    "controlvm",			\
+				    sizeof(ULTRA_CONTROLVM_CHANNEL_PROTOCOL), \
+				    actualBytes, __FILE__, __LINE__, logCtx))
+
+#define MY_DEVICE_INDEX 0
+#define MAX_MACDATA_LEN 8 /* number of bytes for MAC address in config packet */
+#define MAX_SERIAL_NUM	32
+
+#define DISK_ZERO_PUN_NUMBER	1  /* Target ID on the SCSI bus for LUN 0 */
+#define DISK_ZERO_LUN_NUMBER	3  /* Logical Unit Number */
+
+/* Defines for various channel queues... */
+#define CONTROLVM_QUEUE_REQUEST		0
+#define CONTROLVM_QUEUE_RESPONSE	1
+#define	CONTROLVM_QUEUE_EVENT		2
+#define CONTROLVM_QUEUE_ACK		3
+
+/* Max number of messages stored during IOVM creation to be reused
+ * after crash */
+#define CONTROLVM_CRASHMSG_MAX		2
+
+/** Ids for commands that may appear in either queue of a ControlVm channel.
+ *
+ *  Commands that are initiated by the command partition (CP), by an IO or
+ *  console service partition (SP), or by a guest partition (GP)are:
+ *  - issued on the RequestQueue queue (q #0) in the ControlVm channel
+ *  - responded to on the ResponseQueue queue (q #1) in the ControlVm channel
+ *
+ *  Events that are initiated by an IO or console service partition (SP) or
+ *  by a guest partition (GP) are:
+ *  - issued on the EventQueue queue (q #2) in the ControlVm channel
+ *  - responded to on the EventAckQueue queue (q #3) in the ControlVm channel
+ */
+typedef enum  {
+	CONTROLVM_INVALID = 0,
+	/* SWITCH commands required Parameter: SwitchNumber  */
+	/* BUS commands required Parameter: BusNumber  */
+	CONTROLVM_BUS_CREATE = 0x101,	/* CP --> SP, GP */
+	CONTROLVM_BUS_DESTROY = 0x102,	/* CP --> SP, GP */
+	CONTROLVM_BUS_CONFIGURE = 0x104,	/* CP --> SP */
+	CONTROLVM_BUS_CHANGESTATE = 0x105,	/* CP --> SP, GP */
+	CONTROLVM_BUS_CHANGESTATE_EVENT = 0x106, /* SP, GP --> CP */
+/* DEVICE commands required Parameter: BusNumber, DeviceNumber  */
+
+	CONTROLVM_DEVICE_CREATE = 0x201,	/* CP --> SP, GP */
+	CONTROLVM_DEVICE_DESTROY = 0x202,	/* CP --> SP, GP */
+	CONTROLVM_DEVICE_CONFIGURE = 0x203,	/* CP --> SP */
+	CONTROLVM_DEVICE_CHANGESTATE = 0x204,	/* CP --> SP, GP */
+	CONTROLVM_DEVICE_CHANGESTATE_EVENT = 0x205, /* SP, GP --> CP */
+	CONTROLVM_DEVICE_RECONFIGURE = 0x206,	/* CP --> Boot */
+/* DISK commands required Parameter: BusNumber, DeviceNumber  */
+	CONTROLVM_DISK_CREATE = 0x221,	/* CP --> SP */
+	CONTROLVM_DISK_DESTROY = 0x222,	/* CP --> SP */
+	CONTROLVM_DISK_CONFIGURE = 0x223,	/* CP --> SP */
+	CONTROLVM_DISK_CHANGESTATE = 0x224,	/* CP --> SP */
+/* CHIPSET commands */
+	CONTROLVM_CHIPSET_INIT = 0x301,	/* CP --> SP, GP */
+	CONTROLVM_CHIPSET_STOP = 0x302,	/* CP --> SP, GP */
+	CONTROLVM_CHIPSET_SHUTDOWN = 0x303,	/* CP --> SP */
+	CONTROLVM_CHIPSET_READY = 0x304,	/* CP --> SP */
+	CONTROLVM_CHIPSET_SELFTEST = 0x305,	/* CP --> SP */
+
+} CONTROLVM_ID;
+
+struct InterruptInfo {
+	 /**< specifies interrupt info. It is used to send interrupts
+	  *   for this channel. The peer at the end of this channel
+	  *   who has registered an interrupt (using recv fields
+	  *   above) will receive the interrupt. Passed as a parameter
+	  *   to Issue_VMCALL_IO_QUEUE_TRANSITION, which generates the
+	  *   interrupt.  Currently this is used by IOPart-SP to wake
+	  *   up GP when Data Channel transitions from empty to
+	  *   non-empty.*/
+	U64 sendInterruptHandle;
+
+	 /**< specifies interrupt handle. It is used to retrieve the
+	  *   corresponding interrupt pin from Monitor; and the
+	  *   interrupt pin is used to connect to the corresponding
+	  *   intrrupt.  Used by IOPart-GP only. */
+	U64 recvInterruptHandle;
+
+	 /**< specifies interrupt vector. It, interrupt pin, and shared are
+	  *   used to connect to the corresponding interrupt.  Used by
+	  *   IOPart-GP only. */
+	U32 recvInterruptVector;
+
+    /**< specifies if the recvInterrupt is shared.  It, interrupt pin
+     *   and vector are used to connect to 0 = not shared; 1 = shared.
+     *   the corresponding interrupt.  Used by IOPart-GP only. */
+	U8 recvInterruptShared;
+	U8 reserved[3];	/* Natural alignment purposes */
+};
+
+struct PciId {
+	U16 Domain;
+	U8 Bus;
+	U8 Slot;
+	U8 Func;
+	U8 Reserved[3];	/* Natural alignment purposes */
+};
+
+struct PciConfigHdr {
+	U16 VendorId;
+	U16 SubSysVendor;
+	U16 DeviceId;
+	U16 SubSysDevice;
+	U32 ClassCode;
+	U32 Reserved;		/* Natural alignment purposes */
+};
+
+struct ScsiId {
+	U32 Bus;
+	U32 Target;
+	U32 Lun;
+	U32 Host; /* Command should ignore this for *
+		   * DiskArrival/RemovalEvents */
+};
+
+struct WWID {
+	U32 wwid1;
+	U32 wwid2;
+};
+
+struct virtDiskInfo  {
+	U32 switchNo;		/* defined by SWITCH_CREATE */
+	U32 externalPortNo;	/* 0 for SAS RAID provided (external)
+				 * virtual disks, 1 for virtual disk
+				 * images, 2 for gold disk images */
+	U16 VirtualDiskIndex;	/* Index of disk descriptor in the
+				 * VirtualDisk segment associated with
+				 * externalPortNo */
+	U16 Reserved1;
+	U32 Reserved2;
+};
+
+typedef enum {
+	CONTROLVM_ACTION_NONE = 0,
+	CONTROLVM_ACTION_SET_RESTORE = 0x05E7,
+	CONTROLVM_ACTION_CLEAR_RESTORE = 0x0C18,
+	CONTROLVM_ACTION_RESTORING = 0x08E5,
+	CONTROLVM_ACTION_RESTORE_BUSY = 0x0999,
+	CONTROLVM_ACTION_CLEAR_NVRAM = 0xB01
+} CONTROLVM_ACTION;
+
+typedef enum _ULTRA_TOOL_ACTIONS {
+	    /* enumeration that defines intended action  */
+	    ULTRA_TOOL_ACTION_NONE = 0,	/* normal boot of boot disk */
+	ULTRA_TOOL_ACTION_INSTALL = 1,	/* install source disk(s) to boot
+					 * disk */
+	ULTRA_TOOL_ACTION_CAPTURE = 2,	/* capture boot disk to target disk(s)
+					 * as 'gold image' */
+	ULTRA_TOOL_ACTION_REPAIR = 3,	/* use source disk(s) to repair
+					 * installation on boot disk */
+	ULTRA_TOOL_ACTION_CLEAN = 4,	/* 'scrub' virtual disk before
+					 * releasing back to storage pool */
+	ULTRA_TOOL_ACTION_UPGRADE = 5,	/* upgrade to use content of images
+					 * referenced from newer blueprint */
+	ULTRA_TOOL_ACTION_DIAG = 6,	/* use tool to invoke diagnostic script
+					 * provided by blueprint */
+	ULTRA_TOOL_ACTION_FAILED = 7,	/* used when tool fails installation
+					   and cannot continue */
+	ULTRA_TOOL_ACTION_COUNT = 8
+} ULTRA_TOOL_ACTIONS;
+
+typedef struct _ULTRA_EFI_SPAR_INDICATION  {
+	U64 BootToFirmwareUI:1;	/* Bit 0: Stop in uefi ui */
+	U64 ClearNvram:1;	/* Bit 1: Clear NVRAM */
+	U64 ClearCmos:1;	/* Bit 2: Clear CMOS */
+	U64 BootToTool:1;	/* Bit 3: Run install tool */
+	/* remaining bits are available */
+} ULTRA_EFI_SPAR_INDICATION;
+
+typedef enum {
+	ULTRA_CHIPSET_FEATURE_REPLY = 0x00000001,
+	ULTRA_CHIPSET_FEATURE_PARA_HOTPLUG = 0x00000002,
+	ULTRA_CHIPSET_FEATURE_PCIVBUS = 0x00000004
+} ULTRA_CHIPSET_FEATURE;
+
+/** This is the common structure that is at the beginning of every
+ *  ControlVm message (both commands and responses) in any ControlVm
+ *  queue.  Commands are easily distinguished from responses by
+ *  looking at the flags.response field.
+ */
+typedef struct _CONTROLVM_MESSAGE_HEADER  {
+	U32 Id;		/* See CONTROLVM_ID. */
+	/* For requests, indicates the message type. */
+	/* For responses, indicates the type of message we are responding to. */
+
+	U32 MessageSize;	/* Includes size of this struct + size
+				 * of message */
+	U32 SegmentIndex;	/* Index of segment containing Vm
+				 * message/information */
+	U32 CompletionStatus;	/* Error status code or result of
+				 * message completion */
+	struct  {
+		U32 failed:1;		   /**< =1 in a response to * signify
+					    * failure */
+		U32 responseExpected:1;   /**< =1 in all messages that expect a
+					   * response (Control ignores this
+					   * bit) */
+		U32 server:1;		   /**< =1 in all bus & device-related
+					    * messages where the message
+					    * receiver is to act as the bus or
+					    * device server */
+		U32 testMessage:1;	   /**< =1 for testing use only
+					    * (Control and Command ignore this
+					    * bit) */
+		U32 partialCompletion:1;  /**< =1 if there are forthcoming
+					   * responses/acks associated
+					   * with this message */
+		U32 preserve:1;	       /**< =1 this is to let us know to
+					* preserve channel contents
+					* (for running guests)*/
+		U32 writerInDiag:1;	/**< =1 the DiagWriter is active in the
+					 * Diagnostic Partition*/
+
+		    /* remaining bits in this 32-bit word are available */
+	} Flags;
+	U32 Reserved;		/* Natural alignment */
+	U64 MessageHandle;	/* Identifies the particular message instance,
+				 * and is used to match particular */
+	/* request instances with the corresponding response instance. */
+	U64 PayloadVmOffset;	/* Offset of payload area from start of this
+				 * instance of ControlVm segment */
+	U32 PayloadMaxBytes;	/* Maximum bytes allocated in payload
+				 * area of ControlVm segment */
+	U32 PayloadBytes;	/* Actual number of bytes of payload
+				 * area to copy between IO/Command; */
+	/* if non-zero, there is a payload to copy. */
+} CONTROLVM_MESSAGE_HEADER;
+
+typedef struct _CONTROLVM_PACKET_DEVICE_CREATE  {
+	U32 busNo;	   /**< bus # (0..n-1) from the msg receiver's
+			    * perspective */
+
+	    /* Control uses header SegmentIndex field to access bus number... */
+	U32 devNo;	   /**< bus-relative (0..n-1) device number */
+	U64 channelAddr;  /**< Guest physical address of the channel, which
+			*   can be dereferenced by the receiver
+			*   of this ControlVm command */
+	U64 channelBytes; /**< specifies size of the channel in bytes */
+	GUID dataTypeGuid;/**< specifies format of data in channel */
+	GUID devInstGuid; /**< instance guid for the device */
+	struct InterruptInfo intr; /**< specifies interrupt information */
+} CONTROLVM_PACKET_DEVICE_CREATE;	/* for CONTROLVM_DEVICE_CREATE */
+
+typedef struct _CONTROLVM_PACKET_DEVICE_CONFIGURE  {
+	U32 busNo;	      /**< bus # (0..n-1) from the msg
+			       * receiver's perspective */
+
+	    /* Control uses header SegmentIndex field to access bus number... */
+	U32 devNo;	      /**< bus-relative (0..n-1) device number */
+} CONTROLVM_PACKET_DEVICE_CONFIGURE;	/* for CONTROLVM_DEVICE_CONFIGURE */
+
+typedef struct _CONTROLVM_MESSAGE_DEVICE_CREATE  {
+	CONTROLVM_MESSAGE_HEADER Header;
+	CONTROLVM_PACKET_DEVICE_CREATE Packet;
+} CONTROLVM_MESSAGE_DEVICE_CREATE;	/* total 128 bytes */
+
+typedef struct _CONTROLVM_MESSAGE_DEVICE_CONFIGURE  {
+	CONTROLVM_MESSAGE_HEADER Header;
+	CONTROLVM_PACKET_DEVICE_CONFIGURE Packet;
+} CONTROLVM_MESSAGE_DEVICE_CONFIGURE;	/* total 56 bytes */
+
+/* This is the format for a message in any ControlVm queue. */
+typedef struct _CONTROLVM_MESSAGE_PACKET  {
+	union  {
+
+		/* BEGIN Request messages */
+		struct  {
+			U32 busNo;	      /*< bus # (0..n-1) from the msg
+					       * receiver's perspective */
+
+	    /* Control uses header SegmentIndex field to access bus number... */
+			U32 deviceCount;      /*< indicates the max number of
+					       * devices on this bus */
+			U64 channelAddr;     /*< Guest physical address of the
+					      *   channel, which can be
+					      *   dereferenced by the receiver
+					      *   of this ControlVm command */
+			U64 channelBytes;    /*< size of the channel in bytes */
+			GUID busDataTypeGuid;/*< indicates format of data in bus
+					      * channel */
+			GUID busInstGuid;    /*< instance guid for the bus */
+		} createBus;	/* for CONTROLVM_BUS_CREATE */
+		struct  {
+			U32 busNo;	      /*< bus # (0..n-1) from the msg
+					       * receiver's perspective */
+
+	    /* Control uses header SegmentIndex field to access bus number... */
+			U32 reserved;	/* Natural alignment purposes */
+		} destroyBus;	/* for CONTROLVM_BUS_DESTROY */
+		struct  {
+			U32 busNo;		    /*< bus # (0..n-1) from the
+						     * msg receiver's
+						     * perspective */
+
+	    /* Control uses header SegmentIndex field to access bus number... */
+			U32 reserved1;		    /* for alignment purposes */
+			U64 guestHandle;	    /* This is used to convert
+					 *  guest physical address to real
+					 *  physical address for DMA, for ex. */
+			U64 recvBusInterruptHandle;/*< specifies interrupt
+					 *   info. It is used by SP to register
+					 *   to receive interrupts from the CP.
+					 *   This interrupt is used for bus
+					 *   level notifications.  The
+					 *   corresponding
+					 *   sendBusInterruptHandle is kept in
+					 *   CP. */
+		} configureBus;	/* for CONTROLVM_BUS_CONFIGURE */
+
+		/* for CONTROLVM_DEVICE_CREATE */
+		CONTROLVM_PACKET_DEVICE_CREATE createDevice;
+		struct  {
+			U32 busNo;	      /*< bus # (0..n-1) from the msg
+					       * receiver's perspective */
+
+	    /* Control uses header SegmentIndex field to access bus number... */
+			U32 devNo;	      /*< bus-relative (0..n-1) device
+					       * number */
+		} destroyDevice;	/* for CONTROLVM_DEVICE_DESTROY */
+
+		/* for CONTROLVM_DEVICE_CONFIGURE */
+		CONTROLVM_PACKET_DEVICE_CONFIGURE configureDevice;
+		struct  {
+			U32 busNo;	      /*< bus # (0..n-1) from the msg
+					       * receiver's perspective */
+
+	    /* Control uses header SegmentIndex field to access bus number... */
+			U32 devNo;	      /*< bus-relative (0..n-1) device
+					       * number */
+		} reconfigureDevice;	/* for CONTROLVM_DEVICE_RECONFIGURE */
+		struct  {
+			U32 busNo;
+			ULTRA_SEGMENT_STATE state;
+			U8 reserved[2];	/* Natural alignment purposes */
+		} busChangeState;	/* for CONTROLVM_BUS_CHANGESTATE */
+		struct  {
+			U32 busNo;
+			U32 devNo;
+			ULTRA_SEGMENT_STATE state;
+			struct  {
+				U32 physicalDevice:1;	/* =1 if message is for
+							 * a physical device */
+			/* remaining bits in this 32-bit word are available */
+			} flags;
+			U8 reserved[2];	/* Natural alignment purposes */
+		} deviceChangeState;	/* for CONTROLVM_DEVICE_CHANGESTATE */
+		struct  {
+			U32 busNo;
+			U32 devNo;
+			ULTRA_SEGMENT_STATE state;
+			U8 reserved[6];	/* Natural alignment purposes */
+		} deviceChangeStateEvent; /* for CONTROLVM_DEVICE_CHANGESTATE_EVENT */
+		struct  {
+			U32 busCount; /*< indicates the max number of busses */
+			U32 switchCount; /*< indicates the max number of
+					  *   switches (applicable for service
+					  *   partition only) */
+			ULTRA_CHIPSET_FEATURE features;
+			U32 platformNumber;	/* Platform Number */
+		} initChipset;	/* for CONTROLVM_CHIPSET_INIT */
+		struct  {
+			U32 Options; /*< reserved */
+			U32 Test;    /*< bit 0 set to run embedded selftest */
+		} chipsetSelftest;	/* for CONTROLVM_CHIPSET_SELFTEST */
+
+		    /* END Request messages */
+
+		    /* BEGIN Response messages */
+
+		    /* END Response messages */
+
+		    /* BEGIN Event messages */
+
+		    /* END Event messages */
+
+		    /* BEGIN Ack messages */
+
+		    /* END Ack messages */
+		U64 addr;	    /*< a physical address of something, that
+				     *   can be dereferenced by the receiver of
+				     *   this ControlVm command (depends on
+				     *   command id) */
+		U64 handle;	    /*< a handle of something (depends on
+				     * command id) */
+	};
+} CONTROLVM_MESSAGE_PACKET;
+
+/* All messages in any ControlVm queue have this layout. */
+typedef struct _CONTROLVM_MESSAGE  {
+	CONTROLVM_MESSAGE_HEADER hdr;
+	CONTROLVM_MESSAGE_PACKET cmd;
+} CONTROLVM_MESSAGE;
+
+typedef struct _DEVICE_MAP  {
+	GUEST_PHYSICAL_ADDRESS DeviceChannelAddress;
+	U64 DeviceChannelSize;
+	U32 CA_Index;
+	U32 Reserved;		/* natural alignment */
+	U64 Reserved2;		/* Align structure on 32-byte boundary */
+} DEVICE_MAP;
+
+typedef struct _GUEST_DEVICES  {
+	DEVICE_MAP VideoChannel;
+	DEVICE_MAP KeyboardChannel;
+	DEVICE_MAP NetworkChannel;
+	DEVICE_MAP StorageChannel;
+	DEVICE_MAP ConsoleChannel;
+	U32 PartitionIndex;
+	U32 Pad;
+} GUEST_DEVICES;
+
+typedef struct _ULTRA_CONTROLVM_CHANNEL_PROTOCOL  {
+	 CHANNEL_HEADER Header;
+	 GUEST_PHYSICAL_ADDRESS gpControlVm;	/* guest physical address of
+						 * this channel */
+	 GUEST_PHYSICAL_ADDRESS gpPartitionTables; /* guest physical address of
+						    * partition tables */
+	 GUEST_PHYSICAL_ADDRESS gpDiagGuest;	/* guest physical address of
+						 * diagnostic channel */
+	 GUEST_PHYSICAL_ADDRESS gpBootRomDisk;	/* guest phys addr of (read
+						 * only) Boot ROM disk */
+	 GUEST_PHYSICAL_ADDRESS gpBootRamDisk;	/* guest phys addr of writable
+						 * Boot RAM disk */
+	 GUEST_PHYSICAL_ADDRESS gpAcpiTable;	/* guest phys addr of acpi
+						 * table */
+	 GUEST_PHYSICAL_ADDRESS gpControlChannel; /* guest phys addr of control
+						   * channel */
+	 GUEST_PHYSICAL_ADDRESS gpDiagRomDisk;	/* guest phys addr of diagnostic
+						 * ROM disk */
+	 GUEST_PHYSICAL_ADDRESS gpNvram;	/* guest phys addr of NVRAM
+						 * channel */
+	 U64 RequestPayloadOffset;	/* Offset to request payload area */
+	 U64 EventPayloadOffset;	/* Offset to event payload area */
+	 U32 RequestPayloadBytes;	/* Bytes available in request payload
+					 * area */
+	 U32 EventPayloadBytes;	/* Bytes available in event payload area */
+	 U32 ControlChannelBytes;
+	 U32 NvramChannelBytes;	/* Bytes in PartitionNvram segment */
+	 U32 MessageBytes;	/* sizeof(CONTROLVM_MESSAGE) */
+	 U32 MessageCount;	/* CONTROLVM_MESSAGE_MAX */
+	 GUEST_PHYSICAL_ADDRESS gpSmbiosTable;	/* guest phys addr of SMBIOS
+						 * tables */
+	 GUEST_PHYSICAL_ADDRESS gpPhysicalSmbiosTable;	/* guest phys addr of
+							 * SMBIOS table  */
+	 /* ULTRA_MAX_GUESTS_PER_SERVICE */
+	 GUEST_DEVICES gpObsoleteGuestDevices[16];
+
+	 /* guest physical address of EFI firmware image base  */
+	 GUEST_PHYSICAL_ADDRESS VirtualGuestFirmwareImageBase;
+
+	 /* guest physical address of EFI firmware entry point  */
+	 GUEST_PHYSICAL_ADDRESS VirtualGuestFirmwareEntryPoint;
+
+	 /* guest EFI firmware image size  */
+	 U64 VirtualGuestFirmwareImageSize;
+
+	 /* GPA = 1MB where EFI firmware image is copied to  */
+	 GUEST_PHYSICAL_ADDRESS VirtualGuestFirmwareBootBase;
+	 GUEST_PHYSICAL_ADDRESS VirtualGuestImageBase;
+	 GUEST_PHYSICAL_ADDRESS VirtualGuestImageSize;
+	 U64 PrototypeControlChannelOffset;
+	 GUEST_PHYSICAL_ADDRESS VirtualGuestPartitionHandle;
+
+	 U16 RestoreAction;	/* Restore Action field to restore the guest
+				 * partition */
+	U16 DumpAction;		/* For Windows guests it shows if the visordisk
+				 * is running in dump mode */
+	U16 NvramFailCount;
+	U16 SavedCrashMsgCount;	/* = CONTROLVM_CRASHMSG_MAX */
+	U32 SavedCrashMsgOffset;	/* Offset to request payload area needed
+					 * for crash dump */
+	U32 InstallationError;	/* Type of error encountered during
+				 * installation */
+	U32 InstallationTextId;	/* Id of string to display */
+	U16 InstallationRemainingSteps;	/* Number of remaining installation
+					 * steps (for progress bars) */
+	U8 ToolAction;		/* ULTRA_TOOL_ACTIONS Installation Action
+				 * field */
+	U8 Reserved;		/* alignment */
+	ULTRA_EFI_SPAR_INDICATION EfiSparIndication;
+	ULTRA_EFI_SPAR_INDICATION EfiSparIndicationSupported;
+	U32 SPReserved;
+	U8 Reserved2[28];	/* Force signals to begin on 128-byte cache
+				 * line */
+	SIGNAL_QUEUE_HEADER RequestQueue;	/* Service or guest partition
+						 * uses this queue to send
+						 * requests to Control */
+	SIGNAL_QUEUE_HEADER ResponseQueue;	/* Control uses this queue to
+						 * respond to service or guest
+						 * partition requests */
+	SIGNAL_QUEUE_HEADER EventQueue;		/* Control uses this queue to
+						 * send events to service or
+						 * guest partition */
+	SIGNAL_QUEUE_HEADER EventAckQueue;	/* Service or guest partition
+						 * uses this queue to ack
+						 * Control events */
+
+	 /* Request fixed-size message pool - does not include payload */
+	 CONTROLVM_MESSAGE RequestMsg[CONTROLVM_MESSAGE_MAX];
+
+	 /* Response fixed-size message pool - does not include payload */
+	 CONTROLVM_MESSAGE ResponseMsg[CONTROLVM_MESSAGE_MAX];
+
+	 /* Event fixed-size message pool - does not include payload */
+	 CONTROLVM_MESSAGE EventMsg[CONTROLVM_MESSAGE_MAX];
+
+	 /* Ack fixed-size message pool - does not include payload */
+	 CONTROLVM_MESSAGE EventAckMsg[CONTROLVM_MESSAGE_MAX];
+
+	 /* Message stored during IOVM creation to be reused after crash */
+	 CONTROLVM_MESSAGE SavedCrashMsg[CONTROLVM_CRASHMSG_MAX];
+} ULTRA_CONTROLVM_CHANNEL_PROTOCOL;
+
+/* Offsets for VM channel attributes... */
+#define VM_CH_REQ_QUEUE_OFFSET \
+	offsetof(ULTRA_CONTROLVM_CHANNEL_PROTOCOL, RequestQueue)
+#define VM_CH_RESP_QUEUE_OFFSET \
+	offsetof(ULTRA_CONTROLVM_CHANNEL_PROTOCOL, ResponseQueue)
+#define VM_CH_EVENT_QUEUE_OFFSET \
+	offsetof(ULTRA_CONTROLVM_CHANNEL_PROTOCOL, EventQueue)
+#define VM_CH_ACK_QUEUE_OFFSET \
+	offsetof(ULTRA_CONTROLVM_CHANNEL_PROTOCOL, EventAckQueue)
+#define VM_CH_REQ_MSG_OFFSET \
+	offsetof(ULTRA_CONTROLVM_CHANNEL_PROTOCOL, RequestMsg)
+#define VM_CH_RESP_MSG_OFFSET \
+	offsetof(ULTRA_CONTROLVM_CHANNEL_PROTOCOL, ResponseMsg)
+#define VM_CH_EVENT_MSG_OFFSET \
+	offsetof(ULTRA_CONTROLVM_CHANNEL_PROTOCOL, EventMsg)
+#define VM_CH_ACK_MSG_OFFSET \
+	offsetof(ULTRA_CONTROLVM_CHANNEL_PROTOCOL, EventAckMsg)
+#define VM_CH_CRASH_MSG_OFFSET \
+	offsetof(ULTRA_CONTROLVM_CHANNEL_PROTOCOL, SavedCrashMsg)
+
+/* The following header will be located at the beginning of PayloadVmOffset for
+ *  various ControlVm commands. The receiver of a ControlVm command with a
+ *  PayloadVmOffset will dereference this address and then use ConnectionOffset,
+ *  InitiatorOffset, and TargetOffset to get the location of UTF-8 formatted
+ *  strings that can be parsed to obtain command-specific information. The value
+ *  of TotalLength should equal PayloadBytes.  The format of the strings at
+ *  PayloadVmOffset will take different forms depending on the message.  See the
+ *  following Wiki page for more information:
+ *  https://ustr-linux-1.na.uis.unisys.com/spar/index.php/ControlVm_Parameters_Area
+ */
+typedef struct _ULTRA_CONTROLVM_PARAMETERS_HEADER  {
+	U32 TotalLength;
+	U32 HeaderLength;
+	U32 ConnectionOffset;
+	U32 ConnectionLength;
+	U32 InitiatorOffset;
+	U32 InitiatorLength;
+	U32 TargetOffset;
+	U32 TargetLength;
+	U32 ClientOffset;
+	U32 ClientLength;
+	U32 NameOffset;
+	U32 NameLength;
+	GUID Id;
+	U32 Revision;
+	U32 Reserved;		/* Natural alignment */
+} ULTRA_CONTROLVM_PARAMETERS_HEADER;
+
+#endif				/* __CONTROLVMCHANNEL_H__ */
diff --git a/drivers/staging/unisys/common-spar/include/channels/diagchannel.h b/drivers/staging/unisys/common-spar/include/channels/diagchannel.h
new file mode 100644
index 0000000..c93515e
--- /dev/null
+++ b/drivers/staging/unisys/common-spar/include/channels/diagchannel.h
@@ -0,0 +1,427 @@
+/* Copyright © 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+/*++
+ *
+ * Module Name:
+ *
+ * diagchannel.h
+ *
+ * Abstract:
+ *
+ * This file defines the DiagChannel protocol.  This protocol is used to aid in
+ * preserving event data sent by external applications.  This protocol provides
+ * a region for event data to reside in.  This data will eventually be sent to
+ * the Boot Partition where it will be committed to memory and/or disk.  This
+ * file contains platform-independent data that can be built using any
+ * Supervisor build environment (Windows, Linux, EFI).
+ *
+*/
+
+#ifndef _DIAG_CHANNEL_H_
+#define _DIAG_CHANNEL_H_
+
+#include "commontypes.h"
+#include "channel.h"
+
+/* {EEA7A573-DB82-447c-8716-EFBEAAAE4858} */
+#define ULTRA_DIAG_CHANNEL_PROTOCOL_GUID \
+	{0xeea7a573, 0xdb82, 0x447c, \
+		{0x87, 0x16, 0xef, 0xbe, 0xaa, 0xae, 0x48, 0x58} }
+
+static const GUID UltraDiagChannelProtocolGuid =
+	ULTRA_DIAG_CHANNEL_PROTOCOL_GUID;
+
+/* {E850F968-3263-4484-8CA5-2A35D087A5A8} */
+#define ULTRA_DIAG_ROOT_CHANNEL_PROTOCOL_GUID \
+	{0xe850f968, 0x3263, 0x4484, \
+		{0x8c, 0xa5, 0x2a, 0x35, 0xd0, 0x87, 0xa5, 0xa8} }
+
+#define ULTRA_DIAG_CHANNEL_PROTOCOL_SIGNATURE  ULTRA_CHANNEL_PROTOCOL_SIGNATURE
+
+/* Must increment this whenever you insert or delete fields within this channel
+* struct.  Also increment whenever you change the meaning of fields within this
+* channel struct so as to break pre-existing software.  Note that you can
+* usually add fields to the END of the channel struct withOUT needing to
+* increment this. */
+#define ULTRA_DIAG_CHANNEL_PROTOCOL_VERSIONID 2
+
+#define ULTRA_DIAG_CHANNEL_OK_CLIENT(pChannel, logCtx)			\
+	(ULTRA_check_channel_client(pChannel,				\
+				    UltraDiagChannelProtocolGuid,	\
+				    "diag",				\
+				    sizeof(ULTRA_DIAG_CHANNEL_PROTOCOL), \
+				    ULTRA_DIAG_CHANNEL_PROTOCOL_VERSIONID, \
+				    ULTRA_DIAG_CHANNEL_PROTOCOL_SIGNATURE, \
+				    __FILE__, __LINE__, logCtx))
+#define ULTRA_DIAG_CHANNEL_OK_SERVER(actualBytes, logCtx)		\
+	(ULTRA_check_channel_server(UltraDiagChannelProtocolGuid,	\
+				    "diag",				\
+				    sizeof(ULTRA_DIAG_CHANNEL_PROTOCOL), \
+				    actualBytes, __FILE__, __LINE__, logCtx))
+#define MAX_MODULE_NAME_SIZE 128	/* Maximum length of module name... */
+#define MAX_ADDITIONAL_INFO_SIZE 256	/* Maximum length of any additional info
+					 * accompanying event... */
+#define MAX_SUBSYSTEMS 64	/* Maximum number of subsystems allowed in
+				 * DiagChannel... */
+#define LOW_SUBSYSTEMS 32	/* Half of MAX_SUBSYSTEMS to allow 64-bit
+				 * math */
+#define SUBSYSTEM_DEBUG 0	/* Standard subsystem for debug events */
+#define SUBSYSTEM_DEFAULT 1	/* Default subsystem for legacy calls to
+				 * ReportEvent */
+
+/* few useful subsystem mask values */
+#define SUBSYSTEM_MASK_DEBUG	0x01	/* Standard subsystem for debug
+					 * events */
+#define SUBSYSTEM_MASK_DEFAULT  0x02	/* Default subsystem for legacy calls to
+					 * ReportEvents */
+
+/* Event parameter "Severity" is overloaded with Cause in byte 2 and Severity in
+ * byte 0, bytes 1 and 3 are reserved */
+#define SEVERITY_MASK 0x0FF	/* mask out all but the Severity in byte 0 */
+#define CAUSE_MASK 0x0FF0000	/* mask out all but the cause in byte 2 */
+#define CAUSE_SHIFT_AMT 16	/* shift 2 bytes to place it in byte 2 */
+
+/* SubsystemSeverityFilter */
+#define SEVERITY_FILTER_MASK 0x0F /* mask out the Cause half, SeverityFilter is
+				   * in the lower nibble */
+#define CAUSE_FILTER_MASK 0xF0	/* mask out the Severity half, CauseFilter is in
+				 * the upper nibble */
+#define CAUSE_FILTER_SHIFT_AMT	4 /* shift amount to place it in lower or upper
+				   * nibble */
+
+/* Copied from EFI's EFI_TIME struct in efidef.h.  EFI headers are not allowed
+* in some of the Supervisor areas, such as Monitor, so it has been "ported" here
+* for use in diagnostic event timestamps... */
+typedef struct _DIAG_EFI_TIME  {
+	U16 Year;		/* 1998 - 20XX */
+	U8 Month;		/* 1 - 12 */
+	U8 Day;			/* 1 - 31 */
+	U8 Hour;		/* 0 - 23 */
+	U8 Minute;		/* 0 - 59 */
+	U8 Second;		/* 0 - 59 */
+	U8 Pad1;
+	U32 Nanosecond;	/* 0 - 999, 999, 999 */
+	S16 TimeZone;		/* -1440 to 1440 or 2047 */
+	U8 Daylight;
+	U8 Pad2;
+} DIAG_EFI_TIME;
+
+typedef enum  {
+	 ULTRA_COMPONENT_GUEST = 0,
+	 ULTRA_COMPONENT_MONITOR = 0x01,
+	 ULTRA_COMPONENT_CCM = 0x02,	/* Common Control module */
+	 /* RESERVED 0x03 - 0x7 */
+
+	 /* Ultravisor Components */
+	 ULTRA_COMPONENT_BOOT = 0x08,
+	 ULTRA_COMPONENT_IDLE = 0x09,
+	 ULTRA_COMPONENT_CONTROL = 0x0A,
+	 ULTRA_COMPONENT_LOGGER = 0x0B,
+	 ULTRA_COMPONENT_ACPI = 0X0C,
+	 /* RESERVED 0x0D - 0x0F */
+
+	 /* sPAR Components */
+	 ULTRA_COMPONENT_COMMAND = 0x10,
+	 ULTRA_COMPONENT_IODRIVER = 0x11,
+	 ULTRA_COMPONENT_CONSOLE = 0x12,
+	 ULTRA_COMPONENT_OPERATIONS = 0x13,
+	 ULTRA_COMPONENT_MANAGEMENT = 0x14,
+	 ULTRA_COMPONENT_DIAG = 0x15,
+	 ULTRA_COMPONENT_HWDIAG = 0x16,
+	 ULTRA_COMPONENT_PSERVICES = 0x17,
+	 ULTRA_COMPONENT_PDIAG = 0x18
+	 /* RESERVED 0x18 - 0x1F */
+} ULTRA_COMPONENT_TYPES;
+
+/* Structure: DIAG_CHANNEL_EVENT Purpose: Contains attributes that make up an
+ * event to be written to the DIAG_CHANNEL memory.  Attributes: EventId: Id of
+ * the diagnostic event to write to memory.  Severity: Severity of the event
+ * (Error, Info, etc).  ModuleName: Module/file name where event originated.
+ * LineNumber: Line number in module name where event originated.  Timestamp:
+ * Date/time when event was received by ReportEvent, and written to DiagChannel.
+ * Reserved: Padding to align structure on a 64-byte cache line boundary.
+ * AdditionalInfo: Array of characters for additional event info (may be
+ * empty).  */
+typedef struct _DIAG_CHANNEL_EVENT  {
+	U32 EventId;
+	U32 Severity;
+	U8 ModuleName[MAX_MODULE_NAME_SIZE];
+	U32 LineNumber;
+	DIAG_EFI_TIME Timestamp;	/* Size = 16 bytes */
+	U32 PartitionNumber;	/* Filled in by Diag Switch as pool blocks are
+				 * filled */
+	U16 VirtualProcessorNumber;
+	U16 LogicalProcessorNumber;
+	U8 ComponentType;	/* ULTRA_COMPONENT_TYPES */
+	U8 Subsystem;
+	U16 Reserved0;		/* pad to U64 alignment */
+	U32 BlockNumber;	/* filled in by DiagSwitch as pool blocks are
+				 * filled */
+	U32 BlockNumberHigh;
+	U32 EventNumber;	/* filled in by DiagSwitch as pool blocks are
+				 * filled */
+	U32 EventNumberHigh;
+
+	/* The BlockNumber and EventNumber fields are set only by DiagSwitch
+	 * and referenced only by WinDiagDisplay formatting tool as
+	 * additional diagnostic information.  Other tools including
+	 * WinDiagDisplay currently ignore these 'Reserved' bytes. */
+	U8 Reserved[8];
+	U8 AdditionalInfo[MAX_ADDITIONAL_INFO_SIZE];
+
+	/* NOTE: Changesto DIAG_CHANNEL_EVENT generally need to be reflected in
+	 * existing copies *
+	 * - for AppOS at
+	 * GuestLinux/visordiag_early/supervisor_diagchannel.h *
+	 * - for WinDiagDisplay at
+	 * EFI/Ultra/Tools/WinDiagDisplay/WinDiagDisplay/diagstruct.h */
+} DIAG_CHANNEL_EVENT;
+
+/* Levels of severity for diagnostic events, in order from lowest severity to
+* highest (i.e. fatal errors are the most severe, and should always be logged,
+* but info events rarely need to be logged except during debugging).  The values
+* DIAG_SEVERITY_ENUM_BEGIN and DIAG_SEVERITY_ENUM_END are not valid severity
+* values.  They exist merely to dilineate the list, so that future additions
+* won't require changes to the driver (i.e. when checking for out-of-range
+* severities in SetSeverity).  The values DIAG_SEVERITY_OVERRIDE and
+* DIAG_SEVERITY_SHUTOFF are not valid severity values for logging events but
+* they are valid for controlling the amount of event data.  This enum is also
+* defined in DotNet\sParFramework\ControlFramework\ControlFramework.cs.  If a
+* change is made to this enum, they should also be reflected in that file.  */
+typedef enum  { DIAG_SEVERITY_ENUM_BEGIN = 0,
+		DIAG_SEVERITY_OVERRIDE = DIAG_SEVERITY_ENUM_BEGIN,
+		DIAG_SEVERITY_VERBOSE = DIAG_SEVERITY_OVERRIDE,	/* 0 */
+		DIAG_SEVERITY_INFO = DIAG_SEVERITY_VERBOSE + 1,	/* 1 */
+		DIAG_SEVERITY_WARNING = DIAG_SEVERITY_INFO + 1,	/* 2 */
+		DIAG_SEVERITY_ERR = DIAG_SEVERITY_WARNING + 1,	/* 3 */
+		DIAG_SEVERITY_PRINT = DIAG_SEVERITY_ERR + 1,	/* 4 */
+		DIAG_SEVERITY_SHUTOFF = DIAG_SEVERITY_PRINT + 1, /* 5 */
+		DIAG_SEVERITY_ENUM_END = DIAG_SEVERITY_SHUTOFF,	/* 5 */
+		DIAG_SEVERITY_NONFATAL_ERR = DIAG_SEVERITY_ERR,
+		DIAG_SEVERITY_FATAL_ERR = DIAG_SEVERITY_PRINT
+} DIAG_SEVERITY;
+
+/* Event Cause enums
+*
+* Levels of cause for diagnostic events, in order from least to greatest cause
+* Internal errors are most urgent since ideally they should never exist
+* Invalid requests are preventable by avoiding invalid inputs
+* Operations errors depend on environmental factors which may impact which
+* requests are possible
+* Manifest provides intermediate value to capture firmware and configuration
+* version information
+* Trace provides suplimental debug information in release firmware
+* Unknown Log captures unclasified LogEvent calls.
+* Debug is the least urgent since it provides suplimental debug information only
+* in debug firmware
+* Unknown Debug captures unclassified DebugEvent calls.
+* This enum is also defined in
+* DotNet\sParFramework\ControlFramework\ControlFramework.cs.
+* If a change is made to this enum, they should also be reflected in that
+* file.  */
+
+
+
+/* A cause value "DIAG_CAUSE_FILE_XFER" together with a severity value of
+* "DIAG_SEVERITY_PRINT" (=4), is used for transferring text or binary file to
+* the Diag partition. This cause-severity combination will be used by Logger
+* DiagSwitch to segregate events into block types. The files are transferred in
+* 256 byte chunks maximum, in the AdditionalInfo field of the DIAG_CHANNEL_EVENT
+* structure. In the file transfer mode, some event fields will have different
+* meaning: EventId specifies the file offset, severity specifies the block type,
+* ModuleName specifies the filename, LineNumber specifies the number of valid
+* data bytes in an event and AdditionalInfo contains up to 256 bytes of data. */
+
+/* The Diag DiagWriter appends event blocks to events.raw as today, and for data
+ * blocks uses DIAG_CHANNEL_EVENT
+ * PartitionNumber to extract and append 'AdditionalInfo' to filename (specified
+ * by ModuleName). */
+
+/* The Dell PDiag uses this new mechanism to stash DSET .zip onto the
+ * 'diagnostic' virtual disk.  */
+typedef enum  {
+	DIAG_CAUSE_UNKNOWN = 0,
+	DIAG_CAUSE_UNKNOWN_DEBUG = DIAG_CAUSE_UNKNOWN + 1,	/* 1 */
+	DIAG_CAUSE_DEBUG = DIAG_CAUSE_UNKNOWN_DEBUG + 1,	/* 2 */
+	DIAG_CAUSE_UNKNOWN_LOG = DIAG_CAUSE_DEBUG + 1,	/* 3 */
+	DIAG_CAUSE_TRACE = DIAG_CAUSE_UNKNOWN_LOG + 1,	/* 4 */
+	DIAG_CAUSE_MANIFEST = DIAG_CAUSE_TRACE + 1,	/* 5 */
+	DIAG_CAUSE_OPERATIONS_ERROR = DIAG_CAUSE_MANIFEST + 1,	/* 6 */
+	DIAG_CAUSE_INVALID_REQUEST = DIAG_CAUSE_OPERATIONS_ERROR + 1,	/* 7 */
+	DIAG_CAUSE_INTERNAL_ERROR = DIAG_CAUSE_INVALID_REQUEST + 1, /* 8 */
+	DIAG_CAUSE_FILE_XFER = DIAG_CAUSE_INTERNAL_ERROR + 1,	/* 9 */
+	DIAG_CAUSE_ENUM_END = DIAG_CAUSE_FILE_XFER	/* 9 */
+} DIAG_CAUSE;
+
+/* Event Cause category defined into the byte 2 of Severity */
+#define CAUSE_DEBUG (DIAG_CAUSE_DEBUG << CAUSE_SHIFT_AMT)
+#define CAUSE_TRACE (DIAG_CAUSE_TRACE << CAUSE_SHIFT_AMT)
+#define CAUSE_MANIFEST (DIAG_CAUSE_MANIFEST << CAUSE_SHIFT_AMT)
+#define CAUSE_OPERATIONS_ERROR (DIAG_CAUSE_OPERATIONS_ERROR << CAUSE_SHIFT_AMT)
+#define CAUSE_INVALID_REQUEST (DIAG_CAUSE_INVALID_REQUEST << CAUSE_SHIFT_AMT)
+#define CAUSE_INTERNAL_ERROR (DIAG_CAUSE_INTERNAL_ERROR << CAUSE_SHIFT_AMT)
+#define CAUSE_FILE_XFER (DIAG_CAUSE_FILE_XFER << CAUSE_SHIFT_AMT)
+#define CAUSE_ENUM_END CAUSE_FILE_XFER
+
+/* Combine Cause and Severity categories into one */
+#define CAUSE_DEBUG_SEVERITY_VERBOSE \
+	(CAUSE_DEBUG | DIAG_SEVERITY_VERBOSE)
+#define CAUSE_TRACE_SEVERITY_VERBOSE \
+	(CAUSE_TRACE | DIAG_SEVERITY_VERBOSE)
+#define CAUSE_MANIFEST_SEVERITY_VERBOSE\
+	(CAUSE_MANIFEST | DIAG_SEVERITY_VERBOSE)
+#define CAUSE_OPERATIONS_SEVERITY_VERBOSE \
+	(CAUSE_OPERATIONS_ERROR | DIAG_SEVERITY_VERBOSE)
+#define CAUSE_INVALID_SEVERITY_VERBOSE \
+	(CAUSE_INVALID_REQUEST  | DIAG_SEVERITY_VERBOSE)
+#define CAUSE_INTERNAL_SEVERITY_VERBOSE \
+	(CAUSE_INTERNAL_ERROR   | DIAG_SEVERITY_VERBOSE)
+
+#define CAUSE_DEBUG_SEVERITY_INFO \
+	(CAUSE_DEBUG | DIAG_SEVERITY_INFO)
+#define CAUSE_TRACE_SEVERITY_INFO \
+	(CAUSE_TRACE | DIAG_SEVERITY_INFO)
+#define CAUSE_MANIFEST_SEVERITY_INFO \
+	(CAUSE_MANIFEST | DIAG_SEVERITY_INFO)
+#define CAUSE_OPERATIONS_SEVERITY_INFO \
+	(CAUSE_OPERATIONS_ERROR | DIAG_SEVERITY_INFO)
+#define CAUSE_INVALID_SEVERITY_INFO \
+	(CAUSE_INVALID_REQUEST  | DIAG_SEVERITY_INFO)
+#define CAUSE_INTERNAL_SEVERITY_INFO \
+	(CAUSE_INTERNAL_ERROR | DIAG_SEVERITY_INFO)
+
+#define CAUSE_DEBUG_SEVERITY_WARN \
+	(CAUSE_DEBUG | DIAG_SEVERITY_WARNING)
+#define CAUSE_TRACE_SEVERITY_WARN \
+	(CAUSE_TRACE | DIAG_SEVERITY_WARNING)
+#define CAUSE_MANIFEST_SEVERITY_WARN \
+	(CAUSE_MANIFEST | DIAG_SEVERITY_WARNING)
+#define CAUSE_OPERATIONS_SEVERITY_WARN \
+	(CAUSE_OPERATIONS_ERROR | DIAG_SEVERITY_WARNING)
+#define CAUSE_INVALID_SEVERITY_WARN \
+	(CAUSE_INVALID_REQUEST | DIAG_SEVERITY_WARNING)
+#define CAUSE_INTERNAL_SEVERITY_WARN \
+	(CAUSE_INTERNAL_ERROR | DIAG_SEVERITY_WARNING)
+
+#define CAUSE_DEBUG_SEVERITY_ERR \
+	(CAUSE_DEBUG | DIAG_SEVERITY_ERR)
+#define CAUSE_TRACE_SEVERITY_ERR \
+	(CAUSE_TRACE | DIAG_SEVERITY_ERR)
+#define CAUSE_MANIFEST_SEVERITY_ERR \
+	(CAUSE_MANIFEST | DIAG_SEVERITY_ERR)
+#define CAUSE_OPERATIONS_SEVERITY_ERR \
+	(CAUSE_OPERATIONS_ERROR | DIAG_SEVERITY_ERR)
+#define CAUSE_INVALID_SEVERITY_ERR \
+	(CAUSE_INVALID_REQUEST  | DIAG_SEVERITY_ERR)
+#define CAUSE_INTERNAL_SEVERITY_ERR \
+	(CAUSE_INTERNAL_ERROR   | DIAG_SEVERITY_ERR)
+
+#define CAUSE_DEBUG_SEVERITY_PRINT \
+	(CAUSE_DEBUG | DIAG_SEVERITY_PRINT)
+#define CAUSE_TRACE_SEVERITY_PRINT \
+	(CAUSE_TRACE | DIAG_SEVERITY_PRINT)
+#define CAUSE_MANIFEST_SEVERITY_PRINT \
+	(CAUSE_MANIFEST | DIAG_SEVERITY_PRINT)
+#define CAUSE_OPERATIONS_SEVERITY_PRINT \
+	(CAUSE_OPERATIONS_ERROR | DIAG_SEVERITY_PRINT)
+#define CAUSE_INVALID_SEVERITY_PRINT \
+	(CAUSE_INVALID_REQUEST | DIAG_SEVERITY_PRINT)
+#define CAUSE_INTERNAL_SEVERITY_PRINT \
+	(CAUSE_INTERNAL_ERROR | DIAG_SEVERITY_PRINT)
+#define CAUSE_FILE_XFER_SEVERITY_PRINT \
+	(CAUSE_FILE_XFER | DIAG_SEVERITY_PRINT)
+
+/* Structure: DIAG_CHANNEL_PROTOCOL_HEADER
+ *
+ * Purpose: Contains attributes that make up the header specific to the
+ * DIAG_CHANNEL area.
+ *
+ * Attributes:
+ *
+ * DiagLock: Diag Channel spinlock.
+ *
+ *IsChannelInitialized: 1 iff SignalInit was called for this channel; otherwise
+ *			0, and assume the channel is not ready for use yet.
+ *
+ * Reserved: Padding to allign the fields in this structure.
+ *
+ *SubsystemSeverityFilter: Level of severity on a subsystem basis that controls
+ *			whether events are logged.  Any event's severity for a
+ *			particular subsystem below this level will be discarded.
+ */
+typedef struct _DIAG_CHANNEL_PROTOCOL_HEADER  {
+	volatile U32 DiagLock;
+	U8 IsChannelInitialized;
+	U8 Reserved[3];
+	U8 SubsystemSeverityFilter[64];
+} DIAG_CHANNEL_PROTOCOL_HEADER;
+
+/* The Diagram for the Diagnostic Channel: */
+/* ----------------------- */
+/* | Channel Header        |	Defined by ULTRA_CHANNEL_PROTOCOL */
+/* ----------------------- */
+/* | Signal Queue Header   |	Defined by SIGNAL_QUEUE_HEADER */
+/* ----------------------- */
+/* | DiagChannel Header    |	Defined by DIAG_CHANNEL_PROTOCOL_HEADER */
+/* ----------------------- */
+/* | Channel Event Info    |	Defined by (DIAG_CHANNEL_EVENT * MAX_EVENTS) */
+/* ----------------------- */
+/* | Reserved              |	Reserved (pad out to 4MB) */
+/* ----------------------- */
+
+/* Offsets/sizes for diagnostic channel attributes... */
+#define DIAG_CH_QUEUE_HEADER_OFFSET (sizeof(ULTRA_CHANNEL_PROTOCOL))
+#define DIAG_CH_QUEUE_HEADER_SIZE (sizeof(SIGNAL_QUEUE_HEADER))
+#define DIAG_CH_PROTOCOL_HEADER_OFFSET \
+	(DIAG_CH_QUEUE_HEADER_OFFSET + DIAG_CH_QUEUE_HEADER_SIZE)
+#define DIAG_CH_PROTOCOL_HEADER_SIZE (sizeof(DIAG_CHANNEL_PROTOCOL_HEADER))
+#define DIAG_CH_EVENT_OFFSET \
+	(DIAG_CH_PROTOCOL_HEADER_OFFSET + DIAG_CH_PROTOCOL_HEADER_SIZE)
+#define DIAG_CH_SIZE (4096 * 1024)
+
+/* For Control and Idle Partitions with larger (8 MB) diagnostic(root)
+ * channels */
+#define DIAG_CH_LRG_SIZE (2 * DIAG_CH_SIZE)	/* 8 MB */
+
+/*
+ * Structure: ULTRA_DIAG_CHANNEL_PROTOCOL
+ *
+ * Purpose: Contains attributes that make up the DIAG_CHANNEL memory.
+ *
+ * Attributes:
+ *
+ * CommonChannelHeader:	Header info common to all channels.
+ *
+ * QueueHeader: Queue header common to all channels - used to determine where to
+ * store event.
+ *
+ * DiagChannelHeader: Diagnostic channel header info (see
+ * DIAG_CHANNEL_PROTOCOL_HEADER comments).
+ *
+ * Events: Area where diagnostic events (up to MAX_EVENTS) are written.
+ *
+ *Reserved: Reserved area to allow for correct channel size padding.
+*/
+typedef struct _ULTRA_DIAG_CHANNEL_PROTOCOL  {
+	ULTRA_CHANNEL_PROTOCOL CommonChannelHeader;
+	SIGNAL_QUEUE_HEADER QueueHeader;
+	DIAG_CHANNEL_PROTOCOL_HEADER DiagChannelHeader;
+	DIAG_CHANNEL_EVENT Events[(DIAG_CH_SIZE - DIAG_CH_EVENT_OFFSET) /
+				   sizeof(DIAG_CHANNEL_EVENT)];
+}
+ULTRA_DIAG_CHANNEL_PROTOCOL;
+
+#endif
diff --git a/drivers/staging/unisys/common-spar/include/channels/iochannel.h b/drivers/staging/unisys/common-spar/include/channels/iochannel.h
new file mode 100644
index 0000000..94e4b2a
--- /dev/null
+++ b/drivers/staging/unisys/common-spar/include/channels/iochannel.h
@@ -0,0 +1,938 @@
+/* Copyright © 2010 - 2013 UNISYS CORPORATION */
+/* All rights reserved. */
+#ifndef __IOCHANNEL_H__
+#define __IOCHANNEL_H__
+
+/*
+* Everything needed for IOPart-GuestPart communication is define in
+* this file.  Note: Everything is OS-independent because this file is
+* used by Windows, Linux and possible EFI drivers.  */
+
+
+/*
+* Communication flow between the IOPart and GuestPart uses the channel headers
+* channel state.  The following states are currently being used:
+*       UNINIT(All Zeroes), CHANNEL_ATTACHING, CHANNEL_ATTACHED, CHANNEL_OPENED
+*
+* additional states will be used later.  No locking is needed to switch between
+* states due to the following rules:
+*
+*      1.  IOPart is only the only partition allowed to change from UNIT
+*      2.  IOPart is only the only partition allowed to change from
+*		CHANNEL_ATTACHING
+*      3.  GuestPart is only the only partition allowed to change from
+*		CHANNEL_ATTACHED
+*
+* The state changes are the following: IOPart sees the channel is in UNINIT,
+*        UNINIT -> CHANNEL_ATTACHING (performed only by IOPart)
+*        CHANNEL_ATTACHING -> CHANNEL_ATTACHED (performed only by IOPart)
+*        CHANNEL_ATTACHED -> CHANNEL_OPENED (performed only by GuestPart)
+*/
+
+#include "commontypes.h"
+#include "vmcallinterface.h"
+
+#define _ULTRA_CONTROLVM_CHANNEL_INLINE_
+#include "controlvmchannel.h"
+#include "vbuschannel.h"
+#undef _ULTRA_CONTROLVM_CHANNEL_INLINE_
+#include "channel.h"
+
+/*
+ * CHANNEL Guids
+ */
+
+#include "channel_guid.h"
+
+#define ULTRA_VHBA_CHANNEL_PROTOCOL_SIGNATURE ULTRA_CHANNEL_PROTOCOL_SIGNATURE
+#define ULTRA_VNIC_CHANNEL_PROTOCOL_SIGNATURE ULTRA_CHANNEL_PROTOCOL_SIGNATURE
+#define ULTRA_VSWITCH_CHANNEL_PROTOCOL_SIGNATURE \
+	ULTRA_CHANNEL_PROTOCOL_SIGNATURE
+
+/* Must increment these whenever you insert or delete fields within this channel
+* struct.  Also increment whenever you change the meaning of fields within this
+* channel struct so as to break pre-existing software.  Note that you can
+* usually add fields to the END of the channel struct withOUT needing to
+* increment this. */
+#define ULTRA_VHBA_CHANNEL_PROTOCOL_VERSIONID 2
+#define ULTRA_VNIC_CHANNEL_PROTOCOL_VERSIONID 2
+#define ULTRA_VSWITCH_CHANNEL_PROTOCOL_VERSIONID 1
+
+#define ULTRA_VHBA_CHANNEL_OK_CLIENT(pChannel, logCtx)			\
+	(ULTRA_check_channel_client(pChannel, UltraVhbaChannelProtocolGuid, \
+				    "vhba", MIN_IO_CHANNEL_SIZE,	\
+				    ULTRA_VHBA_CHANNEL_PROTOCOL_VERSIONID, \
+				    ULTRA_VHBA_CHANNEL_PROTOCOL_SIGNATURE, \
+				    __FILE__, __LINE__, logCtx))
+#define ULTRA_VHBA_CHANNEL_OK_SERVER(actualBytes, logCtx)		\
+	(ULTRA_check_channel_server(UltraVhbaChannelProtocolGuid,	\
+				    "vhba", MIN_IO_CHANNEL_SIZE, actualBytes, \
+				    __FILE__, __LINE__, logCtx))
+#define ULTRA_VNIC_CHANNEL_OK_CLIENT(pChannel, logCtx)			\
+	(ULTRA_check_channel_client(pChannel, UltraVnicChannelProtocolGuid, \
+				    "vnic", MIN_IO_CHANNEL_SIZE,	\
+				    ULTRA_VNIC_CHANNEL_PROTOCOL_VERSIONID, \
+				    ULTRA_VNIC_CHANNEL_PROTOCOL_SIGNATURE, \
+				    __FILE__, __LINE__, logCtx))
+#define ULTRA_VNIC_CHANNEL_OK_SERVER(actualBytes, logCtx)		\
+	(ULTRA_check_channel_server(UltraVnicChannelProtocolGuid,	\
+				    "vnic", MIN_IO_CHANNEL_SIZE, actualBytes, \
+				    __FILE__, __LINE__, logCtx))
+#define ULTRA_VSWITCH_CHANNEL_OK_CLIENT(pChannel, logCtx)		\
+	(ULTRA_check_channel_client(pChannel, UltraVswitchChannelProtocolGuid, \
+				    "vswitch", MIN_IO_CHANNEL_SIZE,	\
+				    ULTRA_VSWITCH_CHANNEL_PROTOCOL_VERSIONID, \
+				    ULTRA_VSWITCH_CHANNEL_PROTOCOL_SIGNATURE, \
+				    __FILE__, __LINE__, logCtx))
+#define ULTRA_VSWITCH_CHANNEL_OK_SERVER(actualBytes, logCtx)          \
+	(ULTRA_check_channel_server(UltraVswitchChannelProtocolGuid,	\
+				    "vswitch", MIN_IO_CHANNEL_SIZE,	\
+				    actualBytes,		    \
+				    __FILE__, __LINE__, logCtx))
+/*
+* Everything necessary to handle SCSI & NIC traffic between Guest Partition and
+* IO Partition is defined below.  */
+
+
+/*
+* Defines and enums.
+*/
+
+#define MINNUM(a, b) (((a) < (b)) ? (a) : (b))
+#define MAXNUM(a, b) (((a) > (b)) ? (a) : (b))
+
+/* these define the two queues per data channel between iopart and
+ * ioguestparts */
+#define IOCHAN_TO_IOPART 0 /* used by ioguestpart to 'insert' signals to
+			    * iopart */
+#define IOCHAN_FROM_GUESTPART 0 /* used by iopart to 'remove' signals from
+				 * ioguestpart - same queue as previous queue */
+
+#define IOCHAN_TO_GUESTPART 1 /* used by iopart to 'insert' signals to
+			       * ioguestpart */
+#define IOCHAN_FROM_IOPART 1 /* used by ioguestpart to 'remove' signals from
+			      * iopart - same queue as previous queue */
+
+/* these define the two queues per control channel between controlpart and "its"
+ * guests, which includes the iopart  */
+#define CTRLCHAN_TO_CTRLGUESTPART 0 /* used by ctrlguestpart to 'insert' signals
+				     * to ctrlpart */
+#define CTLRCHAN_FROM_CTRLPART 0 /* used by ctrlpart to 'remove' signals from
+				  * ctrlquestpart - same queue as previous
+				  * queue */
+
+#define CTRLCHAN_TO_CTRLPART 1 /* used by ctrlpart to 'insert' signals to
+				* ctrlguestpart */
+#define CTRLCHAN_FROM_CTRLGUESTPART 1 /* used by ctrguestpart to 'remove'
+				       * signals from ctrlpart - same queue as
+				       * previous queue */
+
+/* these define the Event & Ack queues per control channel Events are generated
+* by CTRLGUESTPART and sent to CTRLPART; Acks are generated by CTRLPART and sent
+* to CTRLGUESTPART. */
+#define CTRLCHAN_EVENT_TO_CTRLPART 2 /* used by ctrlguestpart to 'insert' Events
+				      * to ctrlpart */
+#define CTRLCHAN_EVENT_FROM_CTRLGUESTPART 2 /* used by ctrlpart to 'remove'
+					     * Events from ctrlguestpart */
+
+#define CTRLCHAN_ACK_TO_CTRLGUESTPART 3	/* used by ctrlpart to 'insert' Acks to
+					 * ctrlguestpart */
+#define CTRLCHAN_ACK_FROM_CTRLPART 3 /* used by ctrlguestpart to 'remove' Events
+				      * from ctrlpart */
+
+/* size of cdb - i.e., scsi cmnd */
+#define MAX_CMND_SIZE 16
+enum dma_data_dir {
+	DMA_DIR_BIDIR = 0,
+	DMA_DIR_TO_DEV,
+	DMA_DIR_FROM_DEV,
+	DMA_DIR_NONE
+};
+
+#define MAX_SENSE_SIZE 64
+
+#define MAX_PHYS_INFO 64
+
+/* Because GuestToGuestCopy is limited to 4KiB segments, and we have limited the
+* Emulex Driver to 256 scatter list segments via the lpfc_sg_seg_cnt parameter
+* to 256, the maximum I/O size is limited to 256 * 4 KiB = 1 MB */
+#define MAX_IO_SIZE   (1024*1024)	/* 1 MB */
+
+/* NOTE 1: lpfc defines its support for segments in
+* #define LPFC_SG_SEG_CNT 64
+*
+* NOTE 2: In Linux, frags array in skb is currently allocated to be
+* MAX_SKB_FRAGS size, which is 18 which is smaller than MAX_PHYS_INFO for
+* now.  */
+
+#ifndef MAX_SERIAL_NUM
+#define MAX_SERIAL_NUM		32
+#endif				/* MAX_SERIAL_NUM */
+
+#define MAX_SCSI_BUSES		1
+#define MAX_SCSI_TARGETS	8
+#define MAX_SCSI_LUNS		16
+#define MAX_SCSI_FROM_HOST	0xFFFFFFFF	/* Indicator to use Physical HBA
+						 * SCSI Host value */
+
+/* various types of network packets that can be sent in cmdrsp */
+typedef enum { NET_RCV_POST = 0,	/* submit buffer to hold receiving
+					 * incoming packet */
+	/* virtnic -> uisnic */
+	NET_RCV,		/* incoming packet received */
+	/* uisnic -> virtpci */
+	NET_XMIT,		/* for outgoing net packets      */
+	/* virtnic -> uisnic */
+	NET_XMIT_DONE,		/* outgoing packet xmitted */
+	/* uisnic -> virtpci */
+	NET_RCV_ENBDIS,		/* enable/disable packet reception */
+	/* virtnic -> uisnic */
+	NET_RCV_ENBDIS_ACK,	/* acknowledge enable/disable packet
+				 * reception */
+	/* uisnic -> virtnic */
+	NET_RCV_PROMISC,	/* enable/disable promiscuous mode */
+	/* virtnic -> uisnic */
+	NET_CONNECT_STATUS,	/* indicate the loss or restoration of a network
+				 * connection */
+	/* uisnic -> virtnic */
+	NET_MACADDR,		/* indicates the client has requested to update
+				 * its MAC addr */
+	NET_MACADDR_ACK,	/* Mac addres  */
+
+} NET_TYPES;
+
+#define		ETH_HEADER_SIZE 14	/* size of ethernet header */
+
+#define		ETH_MIN_DATA_SIZE 46	/* minimum eth data size */
+#define		ETH_MIN_PACKET_SIZE (ETH_HEADER_SIZE + ETH_MIN_DATA_SIZE)
+
+#define     ETH_DEF_DATA_SIZE 1500	/* default data size */
+#define     ETH_DEF_PACKET_SIZE (ETH_HEADER_SIZE + ETH_DEF_DATA_SIZE)
+
+#define		ETH_MAX_MTU 16384	/* maximum data size */
+
+#ifndef MAX_MACADDR_LEN
+#define MAX_MACADDR_LEN 6	/* number of bytes in MAC address */
+#endif				/* MAX_MACADDR_LEN */
+
+#define ETH_IS_LOCALLY_ADMINISTERED(Address) \
+	(((U8 *) (Address))[0] & ((U8) 0x02))
+#define NIC_VENDOR_ID 0x0008000B
+
+/* various types of scsi task mgmt commands  */
+typedef enum { TASK_MGMT_ABORT_TASK =
+	    1, TASK_MGMT_BUS_RESET, TASK_MGMT_LUN_RESET,
+	    TASK_MGMT_TARGET_RESET,
+} TASK_MGMT_TYPES;
+
+/* various types of vdisk mgmt commands  */
+typedef enum { VDISK_MGMT_ACQUIRE = 1, VDISK_MGMT_RELEASE,
+} VDISK_MGMT_TYPES;
+
+/* this is used in the vdest field  */
+#define VDEST_ALL 0xFFFF
+
+#define MIN_NUMSIGNALS 64
+#define MAX_NUMSIGNALS 4096
+
+/* MAX_NET_RCV_BUF specifies the number of rcv buffers that are created by each
+* guest's virtnic and posted to uisnic.  Uisnic, for each channel, keeps the rcv
+* buffers posted and uses them to receive data on behalf of the guest's virtnic.
+* NOTE: the num_rcv_bufs is configurable for each VNIC. So the following is
+* simply an upperlimit on what each VNIC can provide.  Setting it to half of the
+* NUMSIGNALS to prevent queue full deadlocks */
+#define MAX_NET_RCV_BUFS (MIN_NUMSIGNALS / 2)
+
+/*
+ * structs with pragma pack  */
+
+
+/* ///////////// BEGIN PRAGMA PACK PUSH 1 ///////////////////////// */
+/* ///////////// ONLY STRUCT TYPE SHOULD BE BELOW */
+
+#pragma pack(push, 1)
+
+struct guest_phys_info {
+	U64 address;
+	U64 length;
+};
+
+#define GPI_ENTRIES_PER_PAGE (PAGE_SIZE / sizeof(struct guest_phys_info))
+
+struct uisscsi_dest {
+	U32 channel;		/* channel == bus number */
+	U32 id;			/* id == target number */
+	U32 lun;		/* lun == logical unit number */
+};
+
+struct vhba_wwnn {
+	U32 wwnn1;
+	U32 wwnn2;
+};
+
+/* WARNING: Values stired in this structure must contain maximum counts (not
+ * maximum values). */
+struct vhba_config_max {	/* 20 bytes */
+	U32 max_channel;	/* maximum channel for devices attached to this
+				 * bus */
+	U32 max_id;		/* maximum SCSI ID for devices attached to this
+				 * bus */
+	U32 max_lun;		/* maximum SCSI LUN for devices attached to this
+				 * bus */
+	U32 cmd_per_lun;	/* maximum number of outstanding commands per
+				 * lun that are allowed at one time */
+	U32 max_io_size;	/* maximum io size for devices attached to this
+				 * bus */
+	/* max io size is often determined by the resource of the hba. e.g */
+	/* max scatter gather list length * page size / sector size */
+};
+
+struct uiscmdrsp_scsi {
+	void *scsicmd;		/* the handle to the cmd that was received -
+				 * send it back as is in the rsp packet.  */
+	U8 cmnd[MAX_CMND_SIZE];	/* the cdb for the command */
+	U32 bufflen;		/* length of data to be transferred out or in */
+	U16 guest_phys_entries;	/* Number of entries in scatter-gather (sg)
+				 * list */
+	struct guest_phys_info gpi_list[MAX_PHYS_INFO];	/* physical address
+							 * information for each
+							 * fragment */
+	enum dma_data_dir data_dir;	/* direction of the data, if any */
+	struct uisscsi_dest vdest;	/* identifies the virtual hba, id,
+					 * channel, lun to which cmd was sent */
+
+	    /* the following fields are needed to queue the rsp back to cmd
+	     * originator */
+	int linuxstat;		/* the original Linux status - for use by linux
+				 * vdisk code */
+	U8 scsistat;		/* the scsi status */
+	U8 addlstat;		/* non-scsi status - covers cases like timeout
+				 * needed by windows guests */
+#define ADDL_RESET		1
+#define ADDL_TIMEOUT		2
+#define ADDL_INTERNAL_ERROR	3
+#define ADDL_SEL_TIMEOUT	4
+#define ADDL_CMD_TIMEOUT	5
+#define ADDL_BAD_TARGET		6
+#define ADDL_RETRY		7
+
+	/* the following fields are need to determine the result of command */
+	 U8 sensebuf[MAX_SENSE_SIZE];	/* sense info in case cmd failed; */
+	/* it holds the sense_data struct; */
+	/* see that struct for details. */
+	void *vdisk; /* contains pointer to the vdisk so that we can clean up
+		      * when the IO completes. */
+	int no_disk_result;	/* used to return no disk inquiry result */
+	/* when no_disk_result is set to 1,  */
+	/* scsi.scsistat is SAM_STAT_GOOD */
+	/* scsi.addlstat is 0 */
+	/* scsi.linuxstat is SAM_STAT_GOOD */
+	/* That is, there is NO error. */
+};
+
+/*
+* Defines to support sending correct inquiry result when no disk is
+* configured.  */
+
+/* From SCSI SPC2 -
+ *
+ * If the target is not capable of supporting a device on this logical unit, the
+ * device server shall set this field to 7Fh (PERIPHERAL QUALIFIER set to 011b
+ * and PERIPHERAL DEVICE TYPE set to 1Fh).
+ *
+ *The device server is capable of supporting the specified peripheral device
+ *type on this logical unit. However, the physical device is not currently
+ *connected to this logical unit.
+ */
+
+#define DEV_NOT_PRESENT 0x7f	/* old name - compatibility */
+#define DEV_NOT_CAPABLE 0x7f	/* peripheral qualifier of 0x3  */
+    /* peripheral type of 0x1f */
+    /* specifies no device but target present */
+
+#define DEV_DISK_CAPABLE_NOT_PRESENT 0x20 /* peripheral qualifier of 0x1 */
+    /* peripheral type of 0 - disk */
+    /* specifies device capable, but not present */
+
+#define DEV_PROC_CAPABLE_NOT_PRESENT 0x23 /* peripheral qualifier of 0x1 */
+    /* peripheral type of 3 - processor */
+    /* specifies device capable, but not present */
+
+#define DEV_HISUPPORT 0x10;	/* HiSup = 1; shows support for report luns */
+    /* must be returned for lun 0. */
+
+/* NOTE: Linux code assumes inquiry contains 36 bytes. Without checking length
+* in buf[4] some linux code accesses bytes beyond 5 to retrieve vendor, product
+* & revision.  Yikes! So let us always send back 36 bytes, the minimum for
+* inquiry result. */
+#define NO_DISK_INQUIRY_RESULT_LEN 36
+
+#define MIN_INQUIRY_RESULT_LEN 5 /* we need at least 5 bytes minimum for inquiry
+				  * result */
+
+/* SCSI device version for no disk inquiry result */
+#define SCSI_SPC2_VER 4		/* indicates SCSI SPC2 (SPC3 is 5) */
+
+/* Windows and Linux want different things for a non-existent lun. So, we'll let
+ * caller pass in the peripheral qualifier and type.
+ * NOTE:[4] SCSI returns (n-4); so we return length-1-4 or length-5. */
+
+#define SET_NO_DISK_INQUIRY_RESULT(buf, len, lun, lun0notpresent, notpresent) \
+	do {								\
+		MEMSET(buf, 0,						\
+		       MINNUM(len,					\
+			      (unsigned int) NO_DISK_INQUIRY_RESULT_LEN)); \
+		buf[2] = (U8) SCSI_SPC2_VER;				\
+		if (lun == 0) {						\
+			buf[0] = (U8) lun0notpresent;			\
+			buf[3] = (U8) DEV_HISUPPORT;			\
+		} else							\
+			buf[0] = (U8) notpresent;			\
+		buf[4] = (U8) (						\
+			MINNUM(len,					\
+			       (unsigned int) NO_DISK_INQUIRY_RESULT_LEN) - 5);	\
+		if (len >= NO_DISK_INQUIRY_RESULT_LEN) {		\
+			buf[8] = 'D';					\
+			buf[9] = 'E';					\
+			buf[10] = 'L';					\
+			buf[11] = 'L';					\
+			buf[16] = 'P';					\
+			buf[17] = 'S';					\
+			buf[18] = 'E';					\
+			buf[19] = 'U';					\
+			buf[20] = 'D';					\
+			buf[21] = 'O';					\
+			buf[22] = ' ';					\
+			buf[23] = 'D';					\
+			buf[24] = 'E';					\
+			buf[25] = 'V';					\
+			buf[26] = 'I';					\
+			buf[27] = 'C';					\
+			buf[28] = 'E';					\
+			buf[30] = ' ';					\
+			buf[31] = '.';					\
+		}							\
+	} while (0)
+
+
+/*
+* Struct & Defines to support sense information.
+*/
+
+
+/* The following struct is returned in sensebuf field in uiscmdrsp_scsi.  It is
+* initialized in exactly the manner that is recommended in Windows (hence the
+* odd values).
+* When set, these fields will have the following values:
+* ErrorCode = 0x70		indicates current error
+* Valid = 1			indicates sense info is valid
+* SenseKey			contains sense key as defined by SCSI specs.
+* AdditionalSenseCode		contains sense key as defined by SCSI specs.
+* AdditionalSenseCodeQualifier	contains qualifier to sense code as defined by
+*				scsi docs.
+* AdditionalSenseLength		contains will be sizeof(sense_data)-8=10.
+*/
+struct sense_data {
+	U8 ErrorCode:7;
+	U8 Valid:1;
+	U8 SegmentNumber;
+	U8 SenseKey:4;
+	U8 Reserved:1;
+	U8 IncorrectLength:1;
+	U8 EndOfMedia:1;
+	U8 FileMark:1;
+	U8 Information[4];
+	U8 AdditionalSenseLength;
+	U8 CommandSpecificInformation[4];
+	U8 AdditionalSenseCode;
+	U8 AdditionalSenseCodeQualifier;
+	U8 FieldReplaceableUnitCode;
+	U8 SenseKeySpecific[3];
+};
+
+/* some SCSI ADSENSE codes */
+#ifndef SCSI_ADSENSE_LUN_NOT_READY
+#define SCSI_ADSENSE_LUN_NOT_READY 0x04
+#endif	/*  */
+#ifndef SCSI_ADSENSE_ILLEGAL_COMMAND
+#define SCSI_ADSENSE_ILLEGAL_COMMAND 0x20
+#endif	/*  */
+#ifndef SCSI_ADSENSE_ILLEGAL_BLOCK
+#endif	/*  */
+#ifndef SCSI_ADSENSE_ILLEGAL_BLOCK
+#define SCSI_ADSENSE_ILLEGAL_BLOCK  0x21
+#endif	/*  */
+#ifndef SCSI_ADSENSE_INVALID_CDB
+#define SCSI_ADSENSE_INVALID_CDB    0x24
+#endif	/*  */
+#ifndef SCSI_ADSENSE_INVALID_LUN
+#define SCSI_ADSENSE_INVALID_LUN    0x25
+#endif	/*  */
+#ifndef SCSI_ADWRITE_PROTECT
+#define SCSI_ADWRITE_PROTECT        0x27
+#endif	/*  */
+#ifndef SCSI_ADSENSE_MEDIUM_CHANGED
+#define SCSI_ADSENSE_MEDIUM_CHANGED 0x28
+#endif	/*  */
+#ifndef SCSI_ADSENSE_BUS_RESET
+#define SCSI_ADSENSE_BUS_RESET      0x29
+#endif	/*  */
+#ifndef SCSI_ADSENSE_NO_MEDIA_IN_DEVICE
+#define SCSI_ADSENSE_NO_MEDIA_IN_DEVICE 0x3a
+#endif	/*  */
+
+struct net_pkt_xmt {
+	int len;	/* full length of data in the packet */
+	int num_frags;	/* number of fragments in frags containing data */
+	struct phys_info frags[MAX_PHYS_INFO];	/* physical page information for
+						 * each fragment */
+	char ethhdr[ETH_HEADER_SIZE];	/* the ethernet header  */
+	struct {
+
+		    /* these are needed for csum at uisnic end */
+		U8 valid;	/* 1 = rest of this struct is valid - else
+				 * ignore */
+		U8 hrawoffv;	/* 1 = hwrafoff is valid */
+		U8 nhrawoffv;	/* 1 = nhwrafoff is valid */
+		U16 protocol;	/* specifies packet protocol */
+		U32 csum;	/* value used to set skb->csum at IOPart */
+		U32 hrawoff;	/* value used to set skb->h.raw at IOPart */
+		/* hrawoff points to the start of the TRANSPORT LAYER HEADER */
+		U32 nhrawoff;	/* value used to set skb->nh.raw at IOPart */
+		/* nhrawoff points to the start of the NETWORK LAYER HEADER */
+	} lincsum;
+
+	    /* **** NOTE ****
+	     * The full packet is described in frags but the ethernet header is
+	     * separately kept in ethhdr so that uisnic doesn't have "MAP" the
+	     * guest memory to get to the header. uisnic needs ethhdr to
+	     * determine how to route the packet.
+	     */
+};
+
+struct net_pkt_xmtdone {
+	U32 xmt_done_result;	/* result of NET_XMIT */
+#define XMIT_SUCCESS 0
+#define XMIT_FAILED 1
+};
+
+/* RCVPOST_BUF_SIZe must be at most page_size(4096) - cache_line_size (64) The
+* reason is because dev_skb_alloc which is used to generate RCV_POST skbs in
+* virtnic requires that there is "overhead" in the buffer, and pads 16 bytes.  I
+* prefer to use 1 full cache line size for "overhead" so that transfers are
+* better.  IOVM requires that a buffer be represented by 1 phys_info structure
+* which can only cover page_size. */
+#define RCVPOST_BUF_SIZE 4032
+#define MAX_NET_RCV_CHAIN \
+	((ETH_MAX_MTU+ETH_HEADER_SIZE + RCVPOST_BUF_SIZE-1) / RCVPOST_BUF_SIZE)
+
+struct net_pkt_rcvpost {
+	    /* rcv buf size must be large enough to include ethernet data len +
+	    * ethernet header len - we are choosing 2K because it is guaranteed
+	    * to be describable */
+	    struct phys_info frag;	/* physical page information for the
+					 * single fragment 2K rcv buf */
+	    U64 UniqueNum;		/* This is used to make sure that
+					 * receive posts are returned to  */
+	    /* the Adapter which sent them origonally. */
+};
+
+struct net_pkt_rcv {
+
+	/* the number of receive buffers that can be chained  */
+	/* is based on max mtu and size of each rcv buf */
+	U32 rcv_done_len;	/* length of received data */
+	U8 numrcvbufs;		/* number of receive buffers that contain the */
+	/* incoming data; guest end MUST chain these together. */
+	void *rcvbuf[MAX_NET_RCV_CHAIN];	/* the list of receive buffers
+						 * that must be chained; */
+	/* each entry is a receive buffer provided by NET_RCV_POST. */
+	/* NOTE: first rcvbuf in the chain will also be provided in net.buf. */
+	U64 UniqueNum;
+	U32 RcvsDroppedDelta;
+};
+
+struct net_pkt_enbdis {
+	void *context;
+	U16 enable;		/* 1 = enable, 0 = disable */
+};
+
+struct net_pkt_macaddr {
+	void *context;
+	U8 macaddr[MAX_MACADDR_LEN];	/* 6 bytes */
+};
+
+/* cmd rsp packet used for VNIC network traffic  */
+struct uiscmdrsp_net {
+	NET_TYPES type;
+	void *buf;
+	union {
+		struct net_pkt_xmt xmt;	/* used for NET_XMIT */
+		struct net_pkt_xmtdone xmtdone;	/* used for NET_XMIT_DONE */
+		struct net_pkt_rcvpost rcvpost;	/* used for NET_RCV_POST */
+		struct net_pkt_rcv rcv;	/* used for NET_RCV */
+		struct net_pkt_enbdis enbdis;	/* used for NET_RCV_ENBDIS, */
+		/* NET_RCV_ENBDIS_ACK,  */
+		/* NET_RCV_PROMSIC, */
+		/* and NET_CONNECT_STATUS */
+		struct net_pkt_macaddr macaddr;
+	};
+};
+
+struct uiscmdrsp_scsitaskmgmt {
+	TASK_MGMT_TYPES tasktype;
+
+	    /* the type of task */
+	struct uisscsi_dest vdest;
+
+	    /* the vdisk for which this task mgmt is generated */
+	void *scsicmd;
+
+	    /* This is some handle that the guest has saved off for its own use.
+	    * Its value is preserved by iopart & returned as is in the task mgmt
+	    * rsp. */
+	void *notify;
+
+	    /* For linux guests, this is a pointer to wait_queue_head that a
+	    * thread is waiting on to see if the taskmgmt command has completed.
+	    * For windows guests, this is a pointer to a location that a waiting
+	    * thread is testing to see if the taskmgmt command has completed.
+	    * When the rsp is received by guest, the thread receiving the
+	    * response uses this to notify the the thread waiting for taskmgmt
+	    * command completion.  Its value is preserved by iopart & returned
+	    * as is in the task mgmt rsp. */
+	void *notifyresult;
+
+	    /* this is a handle to location in guest where the result of the
+	    * taskmgmt command (result field) is to saved off when the response
+	    * is handled.  Its value is preserved by iopart & returned as is in
+	    * the task mgmt rsp. */
+	char result;
+
+	    /* result of taskmgmt command - set by IOPart - values are: */
+#define TASK_MGMT_FAILED  0
+#define TASK_MGMT_SUCCESS 1
+};
+
+/* The following is used by uissd to send disk add/remove notifications to
+ * Guest */
+/* Note that the vHba pointer is not used by the Client/Guest side. */
+struct uiscmdrsp_disknotify {
+	U8 add;		/* 0-remove, 1-add */
+	void *vHba;		/* Pointer to vhba_info for channel info to
+				 * route msg */
+	U32 channel, id, lun;	/* SCSI Path of Disk to added or removed */
+};
+
+/* The following is used by virthba/vSCSI to send the Acquire/Release commands
+* to the IOVM.  */
+struct uiscmdrsp_vdiskmgmt {
+	VDISK_MGMT_TYPES vdisktype;
+
+	    /* the type of task */
+	struct uisscsi_dest vdest;
+
+	    /* the vdisk for which this task mgmt is generated */
+	void *scsicmd;
+
+	    /* This is some handle that the guest has saved off for its own use.
+	    * Its value is preserved by iopart & returned as is in the task mgmt
+	    * rsp. */
+	void *notify;
+
+	    /* For linux guests, this is a pointer to wait_queue_head that a
+	    * thread is waiting on to see if the taskmgmt command has completed.
+	    * For windows guests, this is a pointer to a location that a waiting
+	    * thread is testing to see if the taskmgmt command has completed.
+	    * When the rsp is received by guest, the thread receiving the
+	    * response uses this to notify the the thread waiting for taskmgmt
+	    * command completion.  Its value is preserved by iopart & returned
+	    * as is in the task mgmt rsp. */
+	void *notifyresult;
+
+	    /* this is a handle to location in guest where the result of the
+	    * taskmgmt command (result field) is to saved off when the response
+	    * is handled.  Its value is preserved by iopart & returned as is in
+	    * the task mgmt rsp. */
+	char result;
+
+	    /* result of taskmgmt command - set by IOPart - values are: */
+#define VDISK_MGMT_FAILED  0
+#define VDISK_MGMT_SUCCESS 1
+};
+
+/* keeping cmd & rsp info in one structure for now cmd rsp packet for scsi */
+struct uiscmdrsp {
+	char cmdtype;
+
+	    /* describes what type of information is in the struct */
+#define CMD_SCSI_TYPE		1
+#define CMD_NET_TYPE		2
+#define CMD_SCSITASKMGMT_TYPE	3
+#define CMD_NOTIFYGUEST_TYPE	4
+#define CMD_VDISKMGMT_TYPE	5
+	union {
+		struct uiscmdrsp_scsi scsi;
+		struct uiscmdrsp_net net;
+		struct uiscmdrsp_scsitaskmgmt scsitaskmgmt;
+		struct uiscmdrsp_disknotify disknotify;
+		struct uiscmdrsp_vdiskmgmt vdiskmgmt;
+	};
+	void *private_data;	/* used to send the response when the cmd is
+				 * done (scsi & scsittaskmgmt).  */
+	struct uiscmdrsp *next;	/* General Purpose Queue Link */
+	struct uiscmdrsp *activeQ_next;	/* Used to track active commands */
+	struct uiscmdrsp *activeQ_prev;	/* Used to track active commands  */
+};
+
+/* This is just the header of the IO channel.  It is assumed that directly after
+* this header there is a large region of memory which contains the command and
+* response queues as specified in cmdQ and rspQ SIGNAL_QUEUE_HEADERS. */
+typedef struct _ULTRA_IO_CHANNEL_PROTOCOL {
+	CHANNEL_HEADER ChannelHeader;
+	SIGNAL_QUEUE_HEADER cmdQ;
+	SIGNAL_QUEUE_HEADER rspQ;
+	union {
+		struct {
+			struct vhba_wwnn wwnn;	/* 8 bytes */
+			struct vhba_config_max max;	/* 20 bytes */
+		} vhba;		/* 28 */
+		struct {
+			U8 macaddr[MAX_MACADDR_LEN];	/* 6 bytes */
+			U32 num_rcv_bufs;	/* 4 */
+			U32 mtu;	/* 4 */
+			GUID zoneGuid;	/* 16 */
+		} vnic;		/* total     30 */
+	};
+
+#define MAX_CLIENTSTRING_LEN 1024
+	 U8 clientString[MAX_CLIENTSTRING_LEN];	/* NULL terminated - so holds
+						 * max - 1 bytes */
+} ULTRA_IO_CHANNEL_PROTOCOL;
+
+#pragma pack(pop)
+/* ///////////// END PRAGMA PACK PUSH 1 /////////////////////////// */
+
+/* define offsets to members of struct uiscmdrsp */
+#define OFFSET_CMDTYPE OFFSETOF(struct uiscmdrsp, cmdtype)
+#define OFFSET_SCSI OFFSETOF(struct uiscmdrsp, scsi)
+#define OFFSET_NET OFFSETOF(struct uiscmdrsp, net)
+#define OFFSET_SCSITASKMGMT OFFSETOF(struct uiscmdrsp, scsitaskmgmt)
+#define OFFSET_NEXT OFFSETOF(struct uiscmdrsp, next)
+
+/* define offsets to members of struct uiscmdrsp_net */
+#define OFFSET_TYPE OFFSETOF(struct uiscmdrsp_net, type)
+#define OFFSET_BUF OFFSETOF(struct uiscmdrsp_net, buf)
+#define OFFSET_XMT OFFSETOF(struct uiscmdrsp_net, xmt)
+#define OFFSET_XMT_DONE_RESULT OFFSETOF(struct uiscmdrsp_net, xmtdone)
+#define OFFSET_RCVPOST OFFSETOF(struct uiscmdrsp_net, rcvpost)
+#define OFFSET_RCV_DONE_LEN OFFSETOF(struct uiscmdrsp_net, rcv)
+#define OFFSET_ENBDIS OFFSETOF(struct uiscmdrsp_net, enbdis)
+
+/* define offsets to members of struct net_pkt_rcvpost */
+#define OFFSET_TOTALLEN OFFSETOF(struct net_pkt_rcvpost, totallen)
+#define	OFFSET_FRAG OFFSETOF(struct net_pkt_rcvpost, frag)
+
+/*
+* INLINE functions for initializing and accessing I/O data channels
+*/
+
+
+#define NUMSIGNALS(x, q) (((ULTRA_IO_CHANNEL_PROTOCOL *)(x))->q.MaxSignalSlots)
+#define SIZEOF_PROTOCOL (COVER(sizeof(ULTRA_IO_CHANNEL_PROTOCOL), 64))
+#define SIZEOF_CMDRSP (COVER(sizeof(struct uiscmdrsp), 64))
+
+#define IO_CHANNEL_SIZE(x) COVER(SIZEOF_PROTOCOL + \
+				 (NUMSIGNALS(x, cmdQ) + \
+				  NUMSIGNALS(x, rspQ)) * SIZEOF_CMDRSP, 4096)
+#define MIN_IO_CHANNEL_SIZE COVER(SIZEOF_PROTOCOL + \
+				  2 * MIN_NUMSIGNALS * SIZEOF_CMDRSP, 4096)
+#ifdef __GNUC__
+/* These defines should only ever be used in service partitons */
+/* because they rely on the size of uiscmdrsp */
+#define QSLOTSFROMBYTES(bytes) (((bytes-SIZEOF_PROTOCOL)/2)/SIZEOF_CMDRSP)
+#define QSIZEFROMBYTES(bytes) (QSLOTSFROMBYTES(bytes)*SIZEOF_CMDRSP)
+#define SignalQInit(x)						\
+	do {							\
+		x->cmdQ.Size = QSIZEFROMBYTES(x->ChannelHeader.Size);	\
+		x->cmdQ.oSignalBase = SIZEOF_PROTOCOL -			\
+			OFFSETOF(ULTRA_IO_CHANNEL_PROTOCOL, cmdQ);	\
+		x->cmdQ.SignalSize = SIZEOF_CMDRSP;			\
+		x->cmdQ.MaxSignalSlots =				\
+			QSLOTSFROMBYTES(x->ChannelHeader.Size);		\
+		x->cmdQ.MaxSignals = x->cmdQ.MaxSignalSlots - 1;	\
+		x->rspQ.Size = QSIZEFROMBYTES(x->ChannelHeader.Size);	\
+		x->rspQ.oSignalBase =					\
+			(SIZEOF_PROTOCOL + x->cmdQ.Size) -		\
+			OFFSETOF(ULTRA_IO_CHANNEL_PROTOCOL, rspQ);	\
+		x->rspQ.SignalSize = SIZEOF_CMDRSP;			\
+		x->rspQ.MaxSignalSlots =				\
+			QSLOTSFROMBYTES(x->ChannelHeader.Size);		\
+		x->rspQ.MaxSignals = x->rspQ.MaxSignalSlots - 1;	\
+		x->ChannelHeader.oChannelSpace =			\
+			OFFSETOF(ULTRA_IO_CHANNEL_PROTOCOL, cmdQ);	\
+	} while (0)
+
+#define INIT_CLIENTSTRING(chan, type, clientStr, clientStrLen)	\
+	do {								\
+		if (clientStr) {					\
+			chan->ChannelHeader.oClientString =		\
+				OFFSETOF(type, clientString);		\
+			MEMCPY(chan->clientString, clientStr,		\
+			       MINNUM(clientStrLen,			\
+				      (U32) (MAX_CLIENTSTRING_LEN - 1))); \
+			chan->clientString[MINNUM(clientStrLen,		\
+						  (U32) (MAX_CLIENTSTRING_LEN \
+							 - 1))]		\
+				= '\0';					\
+		}							\
+		else							\
+			if (clientStrLen > 0)				\
+				return 0;				\
+	} while (0)
+
+
+#define ULTRA_IO_CHANNEL_SERVER_READY(x, chanId, logCtx) \
+	ULTRA_CHANNEL_SERVER_TRANSITION(x, chanId, SrvState, CHANNELSRV_READY, \
+					logCtx);
+
+#define ULTRA_IO_CHANNEL_SERVER_NOTREADY(x, chanId, logCtx)	\
+	ULTRA_CHANNEL_SERVER_TRANSITION(x, chanId, SrvState, \
+					CHANNELSRV_UNINITIALIZED, logCtx);
+
+static inline int ULTRA_VHBA_init_channel(ULTRA_IO_CHANNEL_PROTOCOL *x,
+					      struct vhba_wwnn *wwnn,
+					      struct vhba_config_max *max,
+					      unsigned char *clientStr,
+					      U32 clientStrLen, U64 bytes)  {
+	MEMSET(x, 0, sizeof(ULTRA_IO_CHANNEL_PROTOCOL));
+	x->ChannelHeader.VersionId = ULTRA_VHBA_CHANNEL_PROTOCOL_VERSIONID;
+	x->ChannelHeader.Signature = ULTRA_VHBA_CHANNEL_PROTOCOL_SIGNATURE;
+	x->ChannelHeader.SrvState = CHANNELSRV_UNINITIALIZED;
+	x->ChannelHeader.HeaderSize = sizeof(x->ChannelHeader);
+	x->ChannelHeader.Size = COVER(bytes, 4096);
+	x->ChannelHeader.Type = UltraVhbaChannelProtocolGuid;
+	x->ChannelHeader.ZoneGuid = Guid0;
+	x->vhba.wwnn = *wwnn;
+	x->vhba.max = *max;
+	INIT_CLIENTSTRING(x, ULTRA_IO_CHANNEL_PROTOCOL, clientStr,
+			  clientStrLen);
+	SignalQInit(x);
+	if ((x->cmdQ.MaxSignalSlots > MAX_NUMSIGNALS) ||
+	     (x->rspQ.MaxSignalSlots > MAX_NUMSIGNALS)) {
+		return 0;
+	}
+	if ((x->cmdQ.MaxSignalSlots < MIN_NUMSIGNALS) ||
+	     (x->rspQ.MaxSignalSlots < MIN_NUMSIGNALS)) {
+		return 0;
+	}
+	return 1;
+}
+
+static inline void ULTRA_VHBA_set_max(ULTRA_IO_CHANNEL_PROTOCOL *x,
+				      struct vhba_config_max *max)  {
+	x->vhba.max = *max;
+}
+
+static inline int ULTRA_VNIC_init_channel(ULTRA_IO_CHANNEL_PROTOCOL *x,
+						 unsigned char *macaddr,
+						 U32 num_rcv_bufs, U32 mtu,
+						 GUID zoneGuid,
+						 unsigned char *clientStr,
+						 U32 clientStrLen,
+						 U64 bytes)  {
+	MEMSET(x, 0, sizeof(ULTRA_IO_CHANNEL_PROTOCOL));
+	x->ChannelHeader.VersionId = ULTRA_VNIC_CHANNEL_PROTOCOL_VERSIONID;
+	x->ChannelHeader.Signature = ULTRA_VNIC_CHANNEL_PROTOCOL_SIGNATURE;
+	x->ChannelHeader.SrvState = CHANNELSRV_UNINITIALIZED;
+	x->ChannelHeader.HeaderSize = sizeof(x->ChannelHeader);
+	x->ChannelHeader.Size = COVER(bytes, 4096);
+	x->ChannelHeader.Type = UltraVnicChannelProtocolGuid;
+	x->ChannelHeader.ZoneGuid = Guid0;
+	MEMCPY(x->vnic.macaddr, macaddr, MAX_MACADDR_LEN);
+	x->vnic.num_rcv_bufs = num_rcv_bufs;
+	x->vnic.mtu = mtu;
+	x->vnic.zoneGuid = zoneGuid;
+	INIT_CLIENTSTRING(x, ULTRA_IO_CHANNEL_PROTOCOL, clientStr,
+			   clientStrLen);
+	SignalQInit(x);
+	if ((x->cmdQ.MaxSignalSlots > MAX_NUMSIGNALS) ||
+	     (x->rspQ.MaxSignalSlots > MAX_NUMSIGNALS)) {
+		return 0;
+	}
+	if ((x->cmdQ.MaxSignalSlots < MIN_NUMSIGNALS) ||
+	     (x->rspQ.MaxSignalSlots < MIN_NUMSIGNALS)) {
+		return 0;
+	}
+	return 1;
+}
+
+#endif	/* __GNUC__ */
+
+/*
+* INLINE function for expanding a guest's pfn-off-size into multiple 4K page
+* pfn-off-size entires.
+*/
+
+
+/* we deal with 4K page sizes when we it comes to passing page information
+ * between */
+/* Guest and IOPartition. */
+#define PI_PAGE_SIZE  0x1000
+#define PI_PAGE_MASK  0x0FFF
+#define PI_PAGE_SHIFT 12
+
+/* returns next non-zero index on success or zero on failure (i.e. out of
+ * room)
+ */
+static INLINE  U16
+add_physinfo_entries(U32 inp_pfn,	/* input - specifies the pfn to be used
+					 * to add entries */
+		     U16 inp_off,	/* input - specifies the off to be used
+					 * to add entries */
+		     U32 inp_len,	/* input - specifies the len to be used
+					 * to add entries */
+		     U16 index,		/* input - index in array at which new
+					 * entries are added */
+		     U16 max_pi_arr_entries,	/* input - specifies the maximum
+						 * entries pi_arr can hold */
+		     struct phys_info pi_arr[]) /* input & output - array to
+						  * which entries are added */
+{
+	U32 len;
+	U16 i, firstlen;
+
+	firstlen = PI_PAGE_SIZE - inp_off;
+	if (inp_len <= firstlen) {
+
+		/* the input entry spans only one page - add as is */
+		if (index >= max_pi_arr_entries)
+			return 0;
+		pi_arr[index].pi_pfn = inp_pfn;
+		pi_arr[index].pi_off = (U16) inp_off;
+		pi_arr[index].pi_len = (U16) inp_len;
+		    return index + 1;
+	}
+
+	    /* this entry spans multiple pages */
+	    for (len = inp_len, i = 0; len;
+		 len -= pi_arr[index + i].pi_len, i++) {
+		if (index + i >= max_pi_arr_entries)
+			return 0;
+		pi_arr[index + i].pi_pfn = inp_pfn + i;
+		if (i == 0) {
+			pi_arr[index].pi_off = inp_off;
+			pi_arr[index].pi_len = firstlen;
+		}
+
+		else {
+			pi_arr[index + i].pi_off = 0;
+			pi_arr[index + i].pi_len =
+			    (U16) MINNUM(len, (U32) PI_PAGE_SIZE);
+		}
+
+	}
+	return index + i;
+}
+
+#endif				/* __IOCHANNEL_H__ */
diff --git a/drivers/staging/unisys/common-spar/include/channels/vbuschannel.h b/drivers/staging/unisys/common-spar/include/channels/vbuschannel.h
new file mode 100644
index 0000000..ec5a8c0
--- /dev/null
+++ b/drivers/staging/unisys/common-spar/include/channels/vbuschannel.h
@@ -0,0 +1,127 @@
+/* Copyright © 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+#ifndef __VBUSCHANNEL_H__
+#define __VBUSCHANNEL_H__
+
+/*  The vbus channel is the channel area provided via the BUS_CREATE controlvm
+ *  message for each virtual bus.  This channel area is provided to both server
+ *  and client ends of the bus.  The channel header area is initialized by
+ *  the server, and the remaining information is filled in by the client.
+ *  We currently use this for the client to provide various information about
+ *  the client devices and client drivers for the server end to see.
+ */
+#include "commontypes.h"
+#include "vbusdeviceinfo.h"
+#include "channel.h"
+
+/* {193b331b-c58f-11da-95a9-00e08161165f} */
+#define ULTRA_VBUS_CHANNEL_PROTOCOL_GUID \
+	{0x193b331b, 0xc58f, 0x11da, \
+		{0x95, 0xa9, 0x0, 0xe0, 0x81, 0x61, 0x16, 0x5f} }
+static const GUID UltraVbusChannelProtocolGuid =
+	ULTRA_VBUS_CHANNEL_PROTOCOL_GUID;
+
+#define ULTRA_VBUS_CHANNEL_PROTOCOL_SIGNATURE ULTRA_CHANNEL_PROTOCOL_SIGNATURE
+
+/* Must increment this whenever you insert or delete fields within this channel
+* struct.  Also increment whenever you change the meaning of fields within this
+* channel struct so as to break pre-existing software.  Note that you can
+* usually add fields to the END of the channel struct withOUT needing to
+* increment this. */
+#define ULTRA_VBUS_CHANNEL_PROTOCOL_VERSIONID 1
+
+#define ULTRA_VBUS_CHANNEL_OK_CLIENT(pChannel, logCtx)       \
+	(ULTRA_check_channel_client(pChannel,				\
+				    UltraVbusChannelProtocolGuid,	\
+				    "vbus",				\
+				    sizeof(ULTRA_VBUS_CHANNEL_PROTOCOL), \
+				    ULTRA_VBUS_CHANNEL_PROTOCOL_VERSIONID, \
+				    ULTRA_VBUS_CHANNEL_PROTOCOL_SIGNATURE, \
+				    __FILE__, __LINE__, logCtx))
+
+#define ULTRA_VBUS_CHANNEL_OK_SERVER(actualBytes, logCtx)    \
+	(ULTRA_check_channel_server(UltraVbusChannelProtocolGuid,	\
+				    "vbus",				\
+				    sizeof(ULTRA_VBUS_CHANNEL_PROTOCOL), \
+				    actualBytes,			\
+				    __FILE__, __LINE__, logCtx))
+
+
+#pragma pack(push, 1)		/* both GCC and VC now allow this pragma */
+typedef struct _ULTRA_VBUS_HEADERINFO {
+	U32 structBytes;	/* size of this struct in bytes */
+	U32 deviceInfoStructBytes;	/* sizeof(ULTRA_VBUS_DEVICEINFO) */
+	U32 devInfoCount;	/* num of items in DevInfo member */
+	/* (this is the allocated size) */
+	U32 chpInfoByteOffset;	/* byte offset from beginning of this struct */
+	/* to the the ChpInfo struct (below) */
+	U32 busInfoByteOffset;	/* byte offset from beginning of this struct */
+	/* to the the BusInfo struct (below) */
+	U32 devInfoByteOffset;	/* byte offset from beginning of this struct */
+	/* to the the DevInfo array (below) */
+	U8 reserved[104];
+} ULTRA_VBUS_HEADERINFO;
+
+typedef struct _ULTRA_VBUS_CHANNEL_PROTOCOL {
+	ULTRA_CHANNEL_PROTOCOL ChannelHeader;	/* initialized by server */
+	ULTRA_VBUS_HEADERINFO HdrInfo;	/* initialized by server */
+	/* the remainder of this channel is filled in by the client */
+	ULTRA_VBUS_DEVICEINFO ChpInfo;	/* describes client chipset device and
+					 * driver */
+	ULTRA_VBUS_DEVICEINFO BusInfo;	/* describes client bus device and
+					 * driver */
+	ULTRA_VBUS_DEVICEINFO DevInfo[0];	/* describes client device and
+						 * driver for */
+	/* each device on the bus */
+} ULTRA_VBUS_CHANNEL_PROTOCOL;
+
+#define VBUS_CH_SIZE_EXACT(MAXDEVICES) \
+	(sizeof(ULTRA_VBUS_CHANNEL_PROTOCOL) + ((MAXDEVICES) * \
+						sizeof(ULTRA_VBUS_DEVICEINFO)))
+#define VBUS_CH_SIZE(MAXDEVICES) COVER(VBUS_CH_SIZE_EXACT(MAXDEVICES), 4096)
+
+static INLINE void
+ULTRA_VBUS_init_channel(ULTRA_VBUS_CHANNEL_PROTOCOL *x, int bytesAllocated)
+{
+	/* Please note that the memory at <x> does NOT necessarily have space
+	* for DevInfo structs allocated at the end, which is why we do NOT use
+	* <bytesAllocated> to clear. */
+	MEMSET(x, 0, sizeof(ULTRA_VBUS_CHANNEL_PROTOCOL));
+	if (bytesAllocated < (int) sizeof(ULTRA_VBUS_CHANNEL_PROTOCOL))
+		return;
+	x->ChannelHeader.VersionId = ULTRA_VBUS_CHANNEL_PROTOCOL_VERSIONID;
+	x->ChannelHeader.Signature = ULTRA_VBUS_CHANNEL_PROTOCOL_SIGNATURE;
+	x->ChannelHeader.SrvState = CHANNELSRV_READY;
+	x->ChannelHeader.HeaderSize = sizeof(x->ChannelHeader);
+	x->ChannelHeader.Size = bytesAllocated;
+	x->ChannelHeader.Type = UltraVbusChannelProtocolGuid;
+	x->ChannelHeader.ZoneGuid = Guid0;
+	x->HdrInfo.structBytes = sizeof(ULTRA_VBUS_HEADERINFO);
+	x->HdrInfo.chpInfoByteOffset = sizeof(ULTRA_VBUS_HEADERINFO);
+	x->HdrInfo.busInfoByteOffset = x->HdrInfo.chpInfoByteOffset
+	    + sizeof(ULTRA_VBUS_DEVICEINFO);
+	x->HdrInfo.devInfoByteOffset = x->HdrInfo.busInfoByteOffset
+	    + sizeof(ULTRA_VBUS_DEVICEINFO);
+	x->HdrInfo.deviceInfoStructBytes = sizeof(ULTRA_VBUS_DEVICEINFO);
+	bytesAllocated -= (sizeof(ULTRA_CHANNEL_PROTOCOL)
+			   + x->HdrInfo.devInfoByteOffset);
+	x->HdrInfo.devInfoCount =
+	    bytesAllocated / x->HdrInfo.deviceInfoStructBytes;
+}
+
+#pragma pack(pop)
+
+#endif
diff --git a/drivers/staging/unisys/common-spar/include/controlvmcompletionstatus.h b/drivers/staging/unisys/common-spar/include/controlvmcompletionstatus.h
new file mode 100644
index 0000000..de30d32
--- /dev/null
+++ b/drivers/staging/unisys/common-spar/include/controlvmcompletionstatus.h
@@ -0,0 +1,92 @@
+/* controlvmcompletionstatus.c
+ *
+ * Copyright © 2010 - 2013 UNISYS CORPORATION
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+/*  Defines for all valid values returned in the response message header
+ *  completionStatus field.  See controlvmchannel.h for description of
+ *  the header: _CONTROLVM_MESSAGE_HEADER.
+ */
+
+#ifndef __CONTROLVMCOMPLETIONSTATUS_H__
+#define __CONTROLVMCOMPLETIONSTATUS_H__
+
+/* General Errors------------------------------------------------------[0-99] */
+#define CONTROLVM_RESP_SUCCESS                                  0
+#define CONTROLVM_RESP_ERROR_ALREADY_DONE                       1
+#define CONTROLVM_RESP_ERROR_IOREMAP_FAILED                     2
+#define CONTROLVM_RESP_ERROR_KMALLOC_FAILED                     3
+#define CONTROLVM_RESP_ERROR_MESSAGE_ID_UNKNOWN                 4
+#define CONTROLVM_RESP_ERROR_MESSAGE_ID_INVALID_FOR_CLIENT      5
+
+/* CONTROLVM_INIT_CHIPSET-------------------------------------------[100-199] */
+#define CONTROLVM_RESP_ERROR_CLIENT_SWITCHCOUNT_NONZERO         100
+#define CONTROLVM_RESP_ERROR_EXPECTED_CHIPSET_INIT              101
+
+/* Maximum Limit----------------------------------------------------[200-299] */
+#define CONTROLVM_RESP_ERROR_MAX_BUSES		201	/* BUS_CREATE */
+#define CONTROLVM_RESP_ERROR_MAX_DEVICES        202	/* DEVICE_CREATE */
+/* Payload and Parameter Related------------------------------------[400-499] */
+#define CONTROLVM_RESP_ERROR_PAYLOAD_INVALID	400	/* SWITCH_ATTACHEXTPORT,
+							 * DEVICE_CONFIGURE */
+#define CONTROLVM_RESP_ERROR_INITIATOR_PARAMETER_INVALID 401	/* Multiple */
+#define CONTROLVM_RESP_ERROR_TARGET_PARAMETER_INVALID 402 /* DEVICE_CONFIGURE */
+#define CONTROLVM_RESP_ERROR_CLIENT_PARAMETER_INVALID 403 /* DEVICE_CONFIGURE */
+/* Specified[Packet Structure] Value-------------------------------[500-599] */
+#define CONTROLVM_RESP_ERROR_BUS_INVALID	500	/* SWITCH_ATTACHINTPORT,
+							 * BUS_CONFIGURE,
+							 * DEVICE_CREATE,
+							 * DEVICE_CONFIG
+							 * DEVICE_DESTROY */
+#define CONTROLVM_RESP_ERROR_DEVICE_INVALID	501 /* SWITCH_ATTACHINTPORT */
+						    /* DEVICE_CREATE,
+						     * DEVICE_CONFIGURE,
+						     * DEVICE_DESTROY */
+#define CONTROLVM_RESP_ERROR_CHANNEL_INVALID	502 /* DEVICE_CREATE,
+						     * DEVICE_CONFIGURE */
+/* Partition Driver Callback Interface----------------------[600-699] */
+#define CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_FAILURE 604	/* BUS_CREATE,
+							 * BUS_DESTROY,
+							 * DEVICE_CREATE,
+							 * DEVICE_DESTROY */
+/* Unable to invoke VIRTPCI callback */
+#define CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_CALLBACK_ERROR 605 /* BUS_CREATE,
+								* BUS_DESTROY,
+								* DEVICE_CREATE,
+								* DEVICE_DESTROY */
+/* VIRTPCI Callback returned error */
+#define CONTROLVM_RESP_ERROR_GENERIC_DRIVER_CALLBACK_ERROR 606 /* SWITCH_ATTACHEXTPORT,
+								* SWITCH_DETACHEXTPORT
+								* DEVICE_CONFIGURE */
+
+/* generic device callback returned error */
+/* Bus Related------------------------------------------------------[700-799] */
+#define CONTROLVM_RESP_ERROR_BUS_DEVICE_ATTACHED 700	/* BUS_DESTROY */
+/* Channel Related--------------------------------------------------[800-899] */
+#define CONTROLVM_RESP_ERROR_CHANNEL_TYPE_UNKNOWN 800	/* GET_CHANNELINFO,
+							 * DEVICE_DESTROY */
+#define CONTROLVM_RESP_ERROR_CHANNEL_SIZE_TOO_SMALL 801	/* DEVICE_CREATE */
+/* Chipset Shutdown Related---------------------------------------[1000-1099] */
+#define CONTROLVM_RESP_ERROR_CHIPSET_SHUTDOWN_FAILED            1000
+#define CONTROLVM_RESP_ERROR_CHIPSET_SHUTDOWN_ALREADY_ACTIVE    1001
+
+/* Chipset Stop Related-------------------------------------------[1100-1199] */
+#define CONTROLVM_RESP_ERROR_CHIPSET_STOP_FAILED_BUS            1100
+#define CONTROLVM_RESP_ERROR_CHIPSET_STOP_FAILED_SWITCH         1101
+
+/* Device Related-------------------------------------------------[1400-1499] */
+#define CONTROLVM_RESP_ERROR_DEVICE_UDEV_TIMEOUT                1400
+
+#endif /* __CONTROLVMCOMPLETIONSTATUS_H__ not defined */
diff --git a/drivers/staging/unisys/common-spar/include/diagnostics/appos_subsystems.h b/drivers/staging/unisys/common-spar/include/diagnostics/appos_subsystems.h
new file mode 100644
index 0000000..4c6294d
--- /dev/null
+++ b/drivers/staging/unisys/common-spar/include/diagnostics/appos_subsystems.h
@@ -0,0 +1,310 @@
+/* Copyright © 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+/* Please note that this file is to be used ONLY for defining diagnostic
+ * subsystem values for the appos (sPAR Linux service partitions) component.
+ */
+#ifndef __APPOS_SUBSYSTEMS_H__
+#define __APPOS_SUBSYSTEMS_H__
+
+#ifdef __KERNEL__
+#include <linux/kernel.h>
+#include <linux/string.h>
+#else
+#include <stdio.h>
+#include <string.h>
+#endif
+
+static inline char *
+subsys_unknown_to_s(int subsys, char *s, int n)
+{
+	snprintf(s, n, "SUBSYS-%-2.2d", subsys);
+	s[n - 1] = '\0';
+	return s;
+}
+
+#define SUBSYS_TO_MASK(subsys)      (1ULL << (subsys))
+
+/* The first SUBSYS_APPOS_MAX subsystems are the same for each AppOS type
+ * (IOVM, SMS, etc.) The rest have unique values for each AppOS type.
+ */
+#define SUBSYS_APPOS_MAX 16
+
+#define	SUBSYS_APPOS_DEFAULT         1	/* or "other" */
+#define SUBSYS_APPOS_CHIPSET         2	/* controlvm and other */
+					/* low-level sPAR activity */
+#define SUBSYS_APPOS_BUS             3	/* sPAR bus */
+/* DAK #define SUBSYS_APPOS_DIAG            4  // diagnostics and dump */
+#define SUBSYS_APPOS_CHANNELACCESS   5	/* generic channel access */
+#define SUBSYS_APPOS_NICCLIENT       6	/* virtual NIC client */
+#define SUBSYS_APPOS_HBACLIENT       7	/* virtual HBA client */
+#define SUBSYS_APPOS_CONSOLESERIAL   8	/* sPAR virtual serial console */
+#define SUBSYS_APPOS_UISLIB          9	/*  */
+#define SUBSYS_APPOS_VRTCUPDD       10	/*  */
+#define SUBSYS_APPOS_WATCHDOG       11	/* watchdog timer and healthcheck */
+#define SUBSYS_APPOS_13             13	/* available */
+#define SUBSYS_APPOS_14             14	/* available */
+#define SUBSYS_APPOS_15             15	/* available */
+#define SUBSYS_APPOS_16             16	/* available */
+static inline char *
+subsys_generic_to_s(int subsys, char *s, int n)
+{
+	switch (subsys) {
+	case SUBSYS_APPOS_DEFAULT:
+		strncpy(s, "APPOS_DEFAULT", n);
+		break;
+	case SUBSYS_APPOS_CHIPSET:
+		strncpy(s, "APPOS_CHIPSET", n);
+		break;
+	case SUBSYS_APPOS_BUS:
+		strncpy(s, "APPOS_BUS", n);
+		break;
+	case SUBSYS_APPOS_CHANNELACCESS:
+		strncpy(s, "APPOS_CHANNELACCESS", n);
+		break;
+	case SUBSYS_APPOS_NICCLIENT:
+		strncpy(s, "APPOS_NICCLIENT", n);
+		break;
+	case SUBSYS_APPOS_HBACLIENT:
+		strncpy(s, "APPOS_HBACLIENT", n);
+		break;
+	case SUBSYS_APPOS_CONSOLESERIAL:
+		strncpy(s, "APPOS_CONSOLESERIAL", n);
+		break;
+	case SUBSYS_APPOS_UISLIB:
+		strncpy(s, "APPOS_UISLIB", n);
+		break;
+	case SUBSYS_APPOS_VRTCUPDD:
+		strncpy(s, "APPOS_VRTCUPDD", n);
+		break;
+	case SUBSYS_APPOS_WATCHDOG:
+		strncpy(s, "APPOS_WATCHDOG", n);
+		break;
+	case SUBSYS_APPOS_13:
+		strncpy(s, "APPOS_13", n);
+		break;
+	case SUBSYS_APPOS_14:
+		strncpy(s, "APPOS_14", n);
+		break;
+	case SUBSYS_APPOS_15:
+		strncpy(s, "APPOS_15", n);
+		break;
+	case SUBSYS_APPOS_16:
+		strncpy(s, "APPOS_16", n);
+		break;
+	default:
+		subsys_unknown_to_s(subsys, s, n);
+		break;
+	}
+	s[n - 1] = '\0';
+	return s;
+}
+
+/* CONSOLE */
+
+#define SUBSYS_CONSOLE_VIDEO        (SUBSYS_APPOS_MAX + 1)	/* 17 */
+#define SUBSYS_CONSOLE_KBDMOU       (SUBSYS_APPOS_MAX + 2)	/* 18 */
+#define SUBSYS_CONSOLE_04           (SUBSYS_APPOS_MAX + 4)
+#define SUBSYS_CONSOLE_05           (SUBSYS_APPOS_MAX + 5)
+#define SUBSYS_CONSOLE_06           (SUBSYS_APPOS_MAX + 6)
+#define SUBSYS_CONSOLE_07           (SUBSYS_APPOS_MAX + 7)
+#define SUBSYS_CONSOLE_08           (SUBSYS_APPOS_MAX + 8)
+#define SUBSYS_CONSOLE_09           (SUBSYS_APPOS_MAX + 9)
+#define SUBSYS_CONSOLE_10           (SUBSYS_APPOS_MAX + 10)
+#define SUBSYS_CONSOLE_11           (SUBSYS_APPOS_MAX + 11)
+#define SUBSYS_CONSOLE_12           (SUBSYS_APPOS_MAX + 12)
+#define SUBSYS_CONSOLE_13           (SUBSYS_APPOS_MAX + 13)
+#define SUBSYS_CONSOLE_14           (SUBSYS_APPOS_MAX + 14)
+#define SUBSYS_CONSOLE_15           (SUBSYS_APPOS_MAX + 15)
+#define SUBSYS_CONSOLE_16           (SUBSYS_APPOS_MAX + 16)
+#define SUBSYS_CONSOLE_17           (SUBSYS_APPOS_MAX + 17)
+#define SUBSYS_CONSOLE_18           (SUBSYS_APPOS_MAX + 18)
+#define SUBSYS_CONSOLE_19           (SUBSYS_APPOS_MAX + 19)
+#define SUBSYS_CONSOLE_20           (SUBSYS_APPOS_MAX + 20)
+#define SUBSYS_CONSOLE_21           (SUBSYS_APPOS_MAX + 21)
+#define SUBSYS_CONSOLE_22           (SUBSYS_APPOS_MAX + 22)
+#define SUBSYS_CONSOLE_23           (SUBSYS_APPOS_MAX + 23)
+#define SUBSYS_CONSOLE_24           (SUBSYS_APPOS_MAX + 24)
+#define SUBSYS_CONSOLE_25           (SUBSYS_APPOS_MAX + 25)
+#define SUBSYS_CONSOLE_26           (SUBSYS_APPOS_MAX + 26)
+#define SUBSYS_CONSOLE_27           (SUBSYS_APPOS_MAX + 27)
+#define SUBSYS_CONSOLE_28           (SUBSYS_APPOS_MAX + 28)
+#define SUBSYS_CONSOLE_29           (SUBSYS_APPOS_MAX + 29)
+#define SUBSYS_CONSOLE_30           (SUBSYS_APPOS_MAX + 30)
+#define SUBSYS_CONSOLE_31           (SUBSYS_APPOS_MAX + 31)
+#define SUBSYS_CONSOLE_32           (SUBSYS_APPOS_MAX + 32)
+#define SUBSYS_CONSOLE_33           (SUBSYS_APPOS_MAX + 33)
+#define SUBSYS_CONSOLE_34           (SUBSYS_APPOS_MAX + 34)
+#define SUBSYS_CONSOLE_35           (SUBSYS_APPOS_MAX + 35)
+#define SUBSYS_CONSOLE_36           (SUBSYS_APPOS_MAX + 36)
+#define SUBSYS_CONSOLE_37           (SUBSYS_APPOS_MAX + 37)
+#define SUBSYS_CONSOLE_38           (SUBSYS_APPOS_MAX + 38)
+#define SUBSYS_CONSOLE_39           (SUBSYS_APPOS_MAX + 39)
+#define SUBSYS_CONSOLE_40           (SUBSYS_APPOS_MAX + 40)
+#define SUBSYS_CONSOLE_41           (SUBSYS_APPOS_MAX + 41)
+#define SUBSYS_CONSOLE_42           (SUBSYS_APPOS_MAX + 42)
+#define SUBSYS_CONSOLE_43           (SUBSYS_APPOS_MAX + 43)
+#define SUBSYS_CONSOLE_44           (SUBSYS_APPOS_MAX + 44)
+#define SUBSYS_CONSOLE_45           (SUBSYS_APPOS_MAX + 45)
+#define SUBSYS_CONSOLE_46           (SUBSYS_APPOS_MAX + 46)
+
+static inline char *
+subsys_console_to_s(int subsys, char *s, int n)
+{
+	switch (subsys) {
+	case SUBSYS_CONSOLE_VIDEO:
+		strncpy(s, "CONSOLE_VIDEO", n);
+		break;
+	case SUBSYS_CONSOLE_KBDMOU:
+		strncpy(s, "CONSOLE_KBDMOU", n);
+		break;
+	case SUBSYS_CONSOLE_04:
+		strncpy(s, "CONSOLE_04", n);
+		break;
+	case SUBSYS_CONSOLE_05:
+		strncpy(s, "CONSOLE_05", n);
+		break;
+	case SUBSYS_CONSOLE_06:
+		strncpy(s, "CONSOLE_06", n);
+		break;
+	case SUBSYS_CONSOLE_07:
+		strncpy(s, "CONSOLE_07", n);
+		break;
+	case SUBSYS_CONSOLE_08:
+		strncpy(s, "CONSOLE_08", n);
+		break;
+	case SUBSYS_CONSOLE_09:
+		strncpy(s, "CONSOLE_09", n);
+		break;
+	case SUBSYS_CONSOLE_10:
+		strncpy(s, "CONSOLE_10", n);
+		break;
+	case SUBSYS_CONSOLE_11:
+		strncpy(s, "CONSOLE_11", n);
+		break;
+	case SUBSYS_CONSOLE_12:
+		strncpy(s, "CONSOLE_12", n);
+		break;
+	case SUBSYS_CONSOLE_13:
+		strncpy(s, "CONSOLE_13", n);
+		break;
+	case SUBSYS_CONSOLE_14:
+		strncpy(s, "CONSOLE_14", n);
+		break;
+	case SUBSYS_CONSOLE_15:
+		strncpy(s, "CONSOLE_15", n);
+		break;
+	case SUBSYS_CONSOLE_16:
+		strncpy(s, "CONSOLE_16", n);
+		break;
+	case SUBSYS_CONSOLE_17:
+		strncpy(s, "CONSOLE_17", n);
+		break;
+	case SUBSYS_CONSOLE_18:
+		strncpy(s, "CONSOLE_18", n);
+		break;
+	case SUBSYS_CONSOLE_19:
+		strncpy(s, "CONSOLE_19", n);
+		break;
+	case SUBSYS_CONSOLE_20:
+		strncpy(s, "CONSOLE_20", n);
+		break;
+	case SUBSYS_CONSOLE_21:
+		strncpy(s, "CONSOLE_21", n);
+		break;
+	case SUBSYS_CONSOLE_22:
+		strncpy(s, "CONSOLE_22", n);
+		break;
+	case SUBSYS_CONSOLE_23:
+		strncpy(s, "CONSOLE_23", n);
+		break;
+	case SUBSYS_CONSOLE_24:
+		strncpy(s, "CONSOLE_24", n);
+		break;
+	case SUBSYS_CONSOLE_25:
+		strncpy(s, "CONSOLE_25", n);
+		break;
+	case SUBSYS_CONSOLE_26:
+		strncpy(s, "CONSOLE_26", n);
+		break;
+	case SUBSYS_CONSOLE_27:
+		strncpy(s, "CONSOLE_27", n);
+		break;
+	case SUBSYS_CONSOLE_28:
+		strncpy(s, "CONSOLE_28", n);
+		break;
+	case SUBSYS_CONSOLE_29:
+		strncpy(s, "CONSOLE_29", n);
+		break;
+	case SUBSYS_CONSOLE_30:
+		strncpy(s, "CONSOLE_30", n);
+		break;
+	case SUBSYS_CONSOLE_31:
+		strncpy(s, "CONSOLE_31", n);
+		break;
+	case SUBSYS_CONSOLE_32:
+		strncpy(s, "CONSOLE_32", n);
+		break;
+	case SUBSYS_CONSOLE_33:
+		strncpy(s, "CONSOLE_33", n);
+		break;
+	case SUBSYS_CONSOLE_34:
+		strncpy(s, "CONSOLE_34", n);
+		break;
+	case SUBSYS_CONSOLE_35:
+		strncpy(s, "CONSOLE_35", n);
+		break;
+	case SUBSYS_CONSOLE_36:
+		strncpy(s, "CONSOLE_36", n);
+		break;
+	case SUBSYS_CONSOLE_37:
+		strncpy(s, "CONSOLE_37", n);
+		break;
+	case SUBSYS_CONSOLE_38:
+		strncpy(s, "CONSOLE_38", n);
+		break;
+	case SUBSYS_CONSOLE_39:
+		strncpy(s, "CONSOLE_39", n);
+		break;
+	case SUBSYS_CONSOLE_40:
+		strncpy(s, "CONSOLE_40", n);
+		break;
+	case SUBSYS_CONSOLE_41:
+		strncpy(s, "CONSOLE_41", n);
+		break;
+	case SUBSYS_CONSOLE_42:
+		strncpy(s, "CONSOLE_42", n);
+		break;
+	case SUBSYS_CONSOLE_43:
+		strncpy(s, "CONSOLE_43", n);
+		break;
+	case SUBSYS_CONSOLE_44:
+		strncpy(s, "CONSOLE_44", n);
+		break;
+	case SUBSYS_CONSOLE_45:
+		strncpy(s, "CONSOLE_45", n);
+		break;
+	case SUBSYS_CONSOLE_46:
+		strncpy(s, "CONSOLE_46", n);
+		break;
+	default:
+		subsys_unknown_to_s(subsys, s, n);
+		break;
+	}
+	s[n - 1] = '\0';
+	return s;
+}
+
+#endif
diff --git a/drivers/staging/unisys/common-spar/include/iovmcall_gnuc.h b/drivers/staging/unisys/common-spar/include/iovmcall_gnuc.h
new file mode 100644
index 0000000..7304e9a0
--- /dev/null
+++ b/drivers/staging/unisys/common-spar/include/iovmcall_gnuc.h
@@ -0,0 +1,53 @@
+/* Copyright © 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+/* Linux GCC Version (32-bit and 64-bit) */
+static inline unsigned long
+__unisys_vmcall_gnuc(unsigned long tuple, unsigned long reg_ebx,
+		     unsigned long reg_ecx)
+{
+	unsigned long result = 0;
+
+	unsigned int cpuid_eax, cpuid_ebx, cpuid_ecx, cpuid_edx;
+	cpuid(0x00000001, &cpuid_eax, &cpuid_ebx, &cpuid_ecx, &cpuid_edx);
+	if (cpuid_ecx & 0x80000000) {
+	      __asm__ __volatile__(".byte 0x00f, 0x001, 0x0c1" : "=a"(result) :
+				   "a"(tuple), "b"(reg_ebx), "c"(reg_ecx)
+				      );
+	} else {
+		result = -1;
+	}
+	return result;
+}
+
+static inline unsigned long
+__unisys_extended_vmcall_gnuc(unsigned long long tuple,
+			      unsigned long long reg_ebx,
+			      unsigned long long reg_ecx,
+			      unsigned long long reg_edx)
+{
+	unsigned long result = 0;
+
+	unsigned int cpuid_eax, cpuid_ebx, cpuid_ecx, cpuid_edx;
+	cpuid(0x00000001, &cpuid_eax, &cpuid_ebx, &cpuid_ecx, &cpuid_edx);
+	if (cpuid_ecx & 0x80000000) {
+	      __asm__ __volatile__(".byte 0x00f, 0x001, 0x0c1" : "=a"(result) :
+				   "a"(tuple), "b"(reg_ebx), "c"(reg_ecx),
+				   "d"(reg_edx));
+	} else {
+		result = -1;
+	}
+	return result;
+	}
diff --git a/drivers/staging/unisys/common-spar/include/vbusdeviceinfo.h b/drivers/staging/unisys/common-spar/include/vbusdeviceinfo.h
new file mode 100644
index 0000000..3736779
--- /dev/null
+++ b/drivers/staging/unisys/common-spar/include/vbusdeviceinfo.h
@@ -0,0 +1,209 @@
+/* Copyright © 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+#ifndef __VBUSDEVICEINFO_H__
+#define __VBUSDEVICEINFO_H__
+
+#include "commontypes.h"
+
+#pragma pack(push, 1)		/* both GCC and VC now allow this pragma */
+
+/* An array of this struct is present in the channel area for each vbus.
+ * (See vbuschannel.h.)
+ * It is filled in by the client side to provide info about the device
+ * and driver from the client's perspective.
+ */
+typedef struct _ULTRA_VBUS_DEVICEINFO {
+	U8 devType[16];		/* short string identifying the device type */
+	U8 drvName[16];		/* driver .sys file name */
+	U8 infoStrings[96];	/* sequence of tab-delimited id strings: */
+	/* <DRIVER_REV> <DRIVER_VERTAG> <DRIVER_COMPILETIME> */
+	U8 reserved[128];	/* pad size to 256 bytes */
+} ULTRA_VBUS_DEVICEINFO;
+
+#pragma pack(pop)
+
+/* Reads chars from the buffer at <src> for <srcmax> bytes, and writes to
+ * the buffer at <p>, which is <remain> bytes long, ensuring never to
+ * overflow the buffer at <p>, using the following rules:
+ * - printable characters are simply copied from the buffer at <src> to the
+ *   buffer at <p>
+ * - intervening streaks of non-printable characters in the buffer at <src>
+ *   are replaced with a single space in the buffer at <p>
+ * Note that we pay no attention to '\0'-termination.
+ * Returns the number of bytes written to <p>.
+ *
+ * Pass <p> == NULL and <remain> == 0 for this special behavior.  In this
+ * case, we simply return the number of bytes that WOULD HAVE been written
+ * to a buffer at <p>, had it been infinitely big.
+ */
+static inline int
+VBUSCHANNEL_sanitize_buffer(char *p, int remain, char *src, int srcmax)
+{
+	int chars = 0;
+	int nonprintable_streak = 0;
+	while (srcmax > 0) {
+		if ((*src >= ' ') && (*src < 0x7f)) {
+			if (nonprintable_streak) {
+				if (remain > 0) {
+					*p = ' ';
+					p++;
+					remain--;
+					chars++;
+				} else if (p == NULL)
+					chars++;
+				nonprintable_streak = 0;
+			}
+			if (remain > 0) {
+				*p = *src;
+				p++;
+				remain--;
+				chars++;
+			} else if (p == NULL)
+				chars++;
+		} else
+			nonprintable_streak = 1;
+		src++;
+		srcmax--;
+	}
+	return chars;
+}
+
+#define VBUSCHANNEL_ADDACHAR(ch, p, remain, chars) \
+	do {					   \
+		if (remain <= 0)		   \
+			break;			   \
+		*p = ch;			   \
+		p++;  chars++;  remain--;	   \
+	} while (0)
+
+/* Converts the non-negative value at <num> to an ascii decimal string
+ * at <p>, writing at most <remain> bytes.  Note there is NO '\0' termination
+ * written to <p>.
+ *
+ * Returns the number of bytes written to <p>.
+ *
+ * Note that we create this function because we need to do this operation in
+ * an environment-independent way (since we are in a common header file).
+ */
+static inline int
+VBUSCHANNEL_itoa(char *p, int remain, int num)
+{
+	int digits = 0;
+	char s[32];
+	int i;
+
+	if (num == 0) {
+		/* '0' is a special case */
+		if (remain <= 0)
+			return 0;
+		*p = '0';
+		return 1;
+	}
+	/* form a backwards decimal ascii string in <s> */
+	while (num > 0) {
+		if (digits >= (int) sizeof(s))
+			return 0;
+		s[digits++] = (num % 10) + '0';
+		num = num / 10;
+	}
+	if (remain < digits) {
+		/* not enough room left at <p> to hold number, so fill with
+		 * '?' */
+		for (i = 0; i < remain; i++, p++)
+			*p = '?';
+		return remain;
+	}
+	/* plug in the decimal ascii string representing the number, by */
+	/* reversing the string we just built in <s> */
+	i = digits;
+	while (i > 0) {
+		i--;
+		*p = s[i];
+		p++;
+	}
+	return digits;
+}
+
+/* Reads <devInfo>, and converts its contents to a printable string at <p>,
+ * writing at most <remain> bytes.  Note there is NO '\0' termination
+ * written to <p>.
+ *
+ * Pass <devix> >= 0 if you want a device index presented.
+ *
+ * Returns the number of bytes written to <p>.
+ */
+static inline int
+VBUSCHANNEL_devInfoToStringBuffer(ULTRA_VBUS_DEVICEINFO devInfo,
+				  char *p, int remain, int devix)
+{
+	char *psrc;
+	int nsrc, x, i, pad;
+	int chars = 0;
+
+	psrc = &(devInfo.devType[0]);
+	nsrc = sizeof(devInfo.devType);
+	if (VBUSCHANNEL_sanitize_buffer(NULL, 0, psrc, nsrc) <= 0)
+		return 0;
+
+	/* emit device index */
+	if (devix >= 0) {
+		VBUSCHANNEL_ADDACHAR('[', p, remain, chars);
+		x = VBUSCHANNEL_itoa(p, remain, devix);
+		p += x;
+		remain -= x;
+		chars += x;
+		VBUSCHANNEL_ADDACHAR(']', p, remain, chars);
+	} else {
+		VBUSCHANNEL_ADDACHAR(' ', p, remain, chars);
+		VBUSCHANNEL_ADDACHAR(' ', p, remain, chars);
+		VBUSCHANNEL_ADDACHAR(' ', p, remain, chars);
+	}
+
+	/* emit device type */
+	x = VBUSCHANNEL_sanitize_buffer(p, remain, psrc, nsrc);
+	p += x;
+	remain -= x;
+	chars += x;
+	pad = 15 - x;		/* pad device type to be exactly 15 chars */
+	for (i = 0; i < pad; i++)
+		VBUSCHANNEL_ADDACHAR(' ', p, remain, chars);
+	VBUSCHANNEL_ADDACHAR(' ', p, remain, chars);
+
+	/* emit driver name */
+	psrc = &(devInfo.drvName[0]);
+	nsrc = sizeof(devInfo.drvName);
+	x = VBUSCHANNEL_sanitize_buffer(p, remain, psrc, nsrc);
+	p += x;
+	remain -= x;
+	chars += x;
+	pad = 15 - x;		/* pad driver name to be exactly 15 chars */
+	for (i = 0; i < pad; i++)
+		VBUSCHANNEL_ADDACHAR(' ', p, remain, chars);
+	VBUSCHANNEL_ADDACHAR(' ', p, remain, chars);
+
+	/* emit strings */
+	psrc = &(devInfo.infoStrings[0]);
+	nsrc = sizeof(devInfo.infoStrings);
+	x = VBUSCHANNEL_sanitize_buffer(p, remain, psrc, nsrc);
+	p += x;
+	remain -= x;
+	chars += x;
+	VBUSCHANNEL_ADDACHAR('\n', p, remain, chars);
+
+	return chars;
+}
+
+#endif
diff --git a/drivers/staging/unisys/common-spar/include/version.h b/drivers/staging/unisys/common-spar/include/version.h
new file mode 100644
index 0000000..00b0ebb
--- /dev/null
+++ b/drivers/staging/unisys/common-spar/include/version.h
@@ -0,0 +1,46 @@
+/* Copyright © 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+/* version.h */
+
+/*  Common version/release info needed by all components goes here.
+ *  (This file must compile cleanly in all environments.)
+ *  Ultimately, this will be combined with defines generated dynamically as
+ *  part of the sysgen, and some of the defines below may in fact end up
+ *  being replaced with dynamically generated ones.
+ */
+#ifndef __VERSION_H__
+#define __VERSION_H__
+
+#define SPARVER1 "1"
+#define SPARVER2 "0"
+#define SPARVER3 "0"
+#define SPARVER4 "0"
+
+#define  VERSION        SPARVER1 "." SPARVER2 "." SPARVER3 "." SPARVER4
+#define  VERSIONDATE    __DATE__
+
+/* Here are various version forms needed in Windows environments.
+ */
+#define VISOR_PRODUCTVERSION      SPARVERCOMMA
+#define VISOR_PRODUCTVERSION_STR  SPARVER1 "." SPARVER2 "." SPARVER3 "." \
+	SPARVER4
+#define VISOR_OBJECTVERSION_STR   SPARVER1 "," SPARVER2 "," SPARVER3 "," \
+	SPARVER4
+
+#define  COPYRIGHT      "Unisys Corporation"
+#define  COPYRIGHTDATE  "2010 - 2013"
+
+#endif
diff --git a/drivers/staging/unisys/common-spar/include/vmcallinterface.h b/drivers/staging/unisys/common-spar/include/vmcallinterface.h
new file mode 100644
index 0000000..bd8944a
--- /dev/null
+++ b/drivers/staging/unisys/common-spar/include/vmcallinterface.h
@@ -0,0 +1,167 @@
+/* Copyright © 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+#ifndef __IOMONINTF_H__
+#define __IOMONINTF_H__
+
+/*
+* This file contains all structures needed to support the VMCALLs for IO
+* Virtualization.  The VMCALLs are provided by Monitor and used by IO code
+* running on IO Partitions.
+*/
+
+#ifdef __GNUC__
+#include "iovmcall_gnuc.h"
+#endif	/*  */
+#include "diagchannel.h"
+
+#ifdef VMCALL_IO_CONTROLVM_ADDR
+#undef VMCALL_IO_CONTROLVM_ADDR
+#endif	/*  */
+
+/* define subsystem number for AppOS, used in uislib driver  */
+#define MDS_APPOS 0x4000000000000000	/* subsystem = 62 - AppOS */
+typedef enum {		/* VMCALL identification tuples  */
+	    /* Note: when a new VMCALL is added:
+	     * - the 1st 2 hex digits correspond to one of the
+	     *   VMCALL_MONITOR_INTERFACE types and
+	     * - the next 2 hex digits are the nth relative instance of within a
+	     *   type
+	     * E.G. for VMCALL_VIRTPART_RECYCLE_PART,
+	     * - the 0x02 identifies it as a VMCALL_VIRTPART type and
+	     * - the 0x01 identifies it as the 1st instance of a VMCALL_VIRTPART
+	     *   type of VMCALL
+	     */
+
+	VMCALL_IO_CONTROLVM_ADDR = 0x0501,	/* used by all Guests, not just
+						 * IO */
+	VMCALL_IO_DIAG_ADDR = 0x0508,
+	VMCALL_IO_VISORSERIAL_ADDR = 0x0509,
+	VMCALL_QUERY_GUEST_VIRTUAL_TIME_OFFSET = 0x0708, /* Allow caller to
+							  * query virtual time
+							  * offset */
+	VMCALL_CHANNEL_VERSION_MISMATCH = 0x0709,
+	VMCALL_POST_CODE_LOGEVENT = 0x070B,	/* LOGEVENT Post Code (RDX) with
+						 * specified subsystem mask (RCX
+						 * - monitor_subsystems.h) and
+						 * severity (RDX) */
+	VMCALL_GENERIC_SURRENDER_QUANTUM_FOREVER = 0x0802, /* Yield the
+							    * remainder & all
+							    * future quantums of
+							    * the caller */
+	VMCALL_MEASUREMENT_DO_NOTHING = 0x0901,
+	VMCALL_UPDATE_PHYSICAL_TIME = 0x0a02	/* Allow
+						 * ULTRA_SERVICE_CAPABILITY_TIME
+						 * capable guest to make
+						 * VMCALL */
+} VMCALL_MONITOR_INTERFACE_METHOD_TUPLE;
+
+#define VMCALL_SUCCESS 0
+#define VMCALL_SUCCESSFUL(result)	(result == 0)
+
+#ifdef __GNUC__
+#define unisys_vmcall(tuple, reg_ebx, reg_ecx) \
+	__unisys_vmcall_gnuc(tuple, reg_ebx, reg_ecx)
+#define unisys_extended_vmcall(tuple, reg_ebx, reg_ecx, reg_edx) \
+	__unisys_extended_vmcall_gnuc(tuple, reg_ebx, reg_ecx, reg_edx)
+#define ISSUE_IO_VMCALL(InterfaceMethod, param, result) \
+	(result = unisys_vmcall(InterfaceMethod, (param) & 0xFFFFFFFF,	\
+				(param) >> 32))
+#define ISSUE_IO_EXTENDED_VMCALL(InterfaceMethod, param1, param2,	\
+				 param3, result)			\
+	(result = unisys_extended_vmcall(InterfaceMethod, param1,	\
+					 param2, param3))
+
+    /* The following uses VMCALL_POST_CODE_LOGEVENT interface but is currently
+     * not used much */
+#define ISSUE_IO_VMCALL_POSTCODE_SEVERITY(postcode, severity)		\
+do {									\
+	U32 _tempresult = VMCALL_SUCCESS;				\
+	ISSUE_IO_EXTENDED_VMCALL(VMCALL_POST_CODE_LOGEVENT, severity,	\
+				 MDS_APPOS, postcode, _tempresult);	\
+} while (0)
+#endif
+
+/* Structures for IO VMCALLs */
+
+/* ///////////// BEGIN PRAGMA PACK PUSH 1 ///////////////////////// */
+/* ///////////// ONLY STRUCT TYPE SHOULD BE BELOW */
+#pragma pack(push, 1)
+struct phys_info {
+	U64 pi_pfn;
+	U16 pi_off;
+	U16 pi_len;
+};
+
+#pragma pack(pop)
+/* ///////////// END PRAGMA PACK PUSH 1 /////////////////////////// */
+typedef struct phys_info IO_DATA_STRUCTURE;
+
+/* ///////////// BEGIN PRAGMA PACK PUSH 1 ///////////////////////// */
+/* ///////////// ONLY STRUCT TYPE SHOULD BE BELOW */
+#pragma pack(push, 1)
+/* Parameters to VMCALL_IO_CONTROLVM_ADDR interface */
+typedef struct _VMCALL_IO_CONTROLVM_ADDR_PARAMS {
+	    /* The Guest-relative physical address of the ControlVm channel.
+	    * This VMCall fills this in with the appropriate address. */
+	U64 ChannelAddress;	/* contents provided by this VMCALL (OUT) */
+	    /* the size of the ControlVm channel in bytes This VMCall fills this
+	    * in with the appropriate address. */
+	U32 ChannelBytes;	/* contents provided by this VMCALL (OUT) */
+	U8 Unused[4];		/* Unused Bytes in the 64-Bit Aligned Struct */
+} VMCALL_IO_CONTROLVM_ADDR_PARAMS;
+
+#pragma pack(pop)
+/* ///////////// END PRAGMA PACK PUSH 1 /////////////////////////// */
+
+/* ///////////// BEGIN PRAGMA PACK PUSH 1 ///////////////////////// */
+/* ///////////// ONLY STRUCT TYPE SHOULD BE BELOW */
+#pragma pack(push, 1)
+/* Parameters to VMCALL_IO_DIAG_ADDR interface */
+typedef struct _VMCALL_IO_DIAG_ADDR_PARAMS {
+	    /* The Guest-relative physical address of the diagnostic channel.
+	    * This VMCall fills this in with the appropriate address. */
+	U64 ChannelAddress;	/* contents provided by this VMCALL (OUT) */
+} VMCALL_IO_DIAG_ADDR_PARAMS;
+
+#pragma pack(pop)
+/* ///////////// END PRAGMA PACK PUSH 1 /////////////////////////// */
+
+/* ///////////// BEGIN PRAGMA PACK PUSH 1 ///////////////////////// */
+/* ///////////// ONLY STRUCT TYPE SHOULD BE BELOW */
+#pragma pack(push, 1)
+/* Parameters to VMCALL_IO_VISORSERIAL_ADDR interface */
+typedef struct _VMCALL_IO_VISORSERIAL_ADDR_PARAMS {
+	    /* The Guest-relative physical address of the serial console
+	    * channel.  This VMCall fills this in with the appropriate
+	    * address. */
+	U64 ChannelAddress;	/* contents provided by this VMCALL (OUT) */
+} VMCALL_IO_VISORSERIAL_ADDR_PARAMS;
+
+#pragma pack(pop)
+/* ///////////// END PRAGMA PACK PUSH 1 /////////////////////////// */
+
+/* Parameters to VMCALL_CHANNEL_MISMATCH interface */
+typedef struct _VMCALL_CHANNEL_VERSION_MISMATCH_PARAMS {
+	U8 ChannelName[32];	/* Null terminated string giving name of channel
+				 * (IN) */
+	U8 ItemName[32];	/* Null terminated string giving name of
+				 * mismatched item (IN) */
+	U32 SourceLineNumber;	/* line# where invoked. (IN) */
+	U8 SourceFileName[36];	/* source code where invoked - Null terminated
+				 * string (IN) */
+} VMCALL_CHANNEL_VERSION_MISMATCH_PARAMS;
+
+#endif /* __IOMONINTF_H__ */
diff --git a/drivers/staging/unisys/include/commontypes.h b/drivers/staging/unisys/include/commontypes.h
new file mode 100644
index 0000000..ae46bed
--- /dev/null
+++ b/drivers/staging/unisys/include/commontypes.h
@@ -0,0 +1,166 @@
+/* Copyright © 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+#ifndef _COMMONTYPES_H_
+#define _COMMONTYPES_H_
+
+/* define the following to prevent include nesting in kernel header files of
+ * similar abreviated content */
+#define _SUPERVISOR_COMMONTYPES_H_
+
+#ifdef __KERNEL__
+#include <linux/types.h>
+#include <linux/version.h>
+#else
+#include <stdint.h>
+#include <syslog.h>
+#endif
+
+#define U8  uint8_t
+#define U16 uint16_t
+#define U32 uint32_t
+#define U64 uint64_t
+#define S8  int8_t
+#define S16 int16_t
+#define S32 int32_t
+#define S64 int64_t
+
+#ifdef __KERNEL__
+
+#ifdef CONFIG_X86_32
+#define UINTN U32
+#else
+#define UINTN U64
+#endif
+
+#else
+
+#include <stdint.h>
+#if __WORDSIZE == 32
+#define UINTN U32
+#elif __WORDSIZE == 64
+#define UINTN U64
+#else
+#error Unsupported __WORDSIZE
+#endif
+
+#endif
+
+typedef struct {
+	U32 data1;
+	U16 data2;
+	U16 data3;
+	U8 data4[8];
+} __attribute__ ((__packed__)) GUID;
+
+#ifndef GUID0
+#define GUID0 {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0} }
+#endif
+typedef U64 GUEST_PHYSICAL_ADDRESS;
+
+#define MEMSET(ptr, val, len) memset(ptr, val, len)
+#define MEMCMP(m1, m2, len) memcmp(m1, m2, len)
+#define STRLEN(s) ((UINTN)strlen((const char *)s))
+#define STRCPY(d, s) (strcpy((char *)d, (const char *)s))
+
+#define INLINE inline
+#define OFFSETOF offsetof
+
+#ifdef __KERNEL__
+#define MEMORYBARRIER mb()
+#define MEMCPY(dest, src, len) memcpy(dest, src, len)
+
+#define CHANNEL_GUID_MISMATCH(chType, chName, field, expected, actual, fil, \
+			      lin, logCtx)				\
+	do {								\
+		char s1[50], s2[50], s3[50];				\
+		pr_err("Channel mismatch on channel=%s(%s) field=%s expected=%s actual=%s @%s:%d\n", \
+		       chName, GUID_format2(&chType, s1), field,	\
+		       GUID_format2(&expected, s2), GUID_format2(&actual, s3), \
+		       fil, lin);					\
+	} while (0)
+#define CHANNEL_U32_MISMATCH(chType, chName, field, expected, actual, fil, \
+			     lin, logCtx)				\
+	do {								\
+		char s1[50];						\
+		pr_err("Channel mismatch on channel=%s(%s) field=%s expected=0x%-8.8lx actual=0x%-8.8lx @%s:%d\n", \
+		       chName, GUID_format2(&chType, s1), field,	\
+		       (unsigned long)expected, (unsigned long)actual,	\
+		       fil, lin);					\
+	} while (0)
+
+#define CHANNEL_U64_MISMATCH(chType, chName, field, expected, actual, fil, \
+			     lin, logCtx)				\
+	do {								\
+		char s1[50];						\
+		pr_err("Channel mismatch on channel=%s(%s) field=%s expected=0x%-8.8Lx actual=0x%-8.8Lx @%s:%d\n", \
+		       chName, GUID_format2(&chType, s1), field,	\
+		       (unsigned long long)expected,			\
+		       (unsigned long long)actual,			\
+		       fil, lin);					\
+	} while (0)
+
+#define UltraLogEvent(logCtx, EventId, Severity, SubsystemMask, pFunctionName, \
+		      LineNumber, Str, args...)				\
+	pr_info(Str, ## args)
+
+#else
+#define MEMCPY(dest, src, len) memcpy(dest, src, len)
+
+#define MEMORYBARRIER mb()
+
+#define CHANNEL_GUID_MISMATCH(chType, chName, field, expected, actual, fil, \
+			      lin, logCtx)				\
+	do {								\
+		char s1[50], s2[50], s3[50];				\
+		syslog(LOG_USER | LOG_ERR,				\
+		       "Channel mismatch on channel=%s(%s) field=%s expected=%s actual=%s @%s:%d", \
+		       chName, GUID_format2(&chType, s1), field,	\
+		       GUID_format2(&expected, s2), GUID_format2(&actual, s3), \
+		       fil, lin);					\
+	} while (0)
+
+#define CHANNEL_U32_MISMATCH(chType, chName, field, expected, actual, fil, \
+			     lin, logCtx)				\
+	do {								\
+		char s1[50];						\
+		syslog(LOG_USER | LOG_ERR,				\
+		       "Channel mismatch on channel=%s(%s) field=%s expected=0x%-8.8lx actual=0x%-8.8lx @%s:%d", \
+		       chName, GUID_format2(&chType, s1), field,	\
+		       (unsigned long)expected, (unsigned long)actual,	\
+		       fil, lin);					\
+	} while (0)
+
+#define CHANNEL_U64_MISMATCH(chType, chName, field, expected, actual, fil, \
+			     lin, logCtx)				\
+	do {								\
+		char s1[50];						\
+		syslog(LOG_USER | LOG_ERR,				\
+		       "Channel mismatch on channel=%s(%s) field=%s expected=0x%-8.8Lx actual=0x%-8.8Lx @%s:%d", \
+		       chName, GUID_format2(&chType, s1), field,	\
+		       (unsigned long long)expected,			\
+		       (unsigned long long)actual,			\
+		       fil, lin);					\
+	} while (0)
+
+#define UltraLogEvent(logCtx, EventId, Severity, SubsystemMask, pFunctionName, \
+		      LineNumber, Str, args...)				\
+	syslog(LOG_USER | LOG_INFO, Str, ## args)
+#endif
+
+#define VolatileBarrier() MEMORYBARRIER
+
+#endif
+#include "guidutils.h"
diff --git a/drivers/staging/unisys/include/guestlinuxdebug.h b/drivers/staging/unisys/include/guestlinuxdebug.h
new file mode 100644
index 0000000..c3de849
--- /dev/null
+++ b/drivers/staging/unisys/include/guestlinuxdebug.h
@@ -0,0 +1,182 @@
+/* Copyright © 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+#ifndef __GUESTLINUXDEBUG_H__
+#define __GUESTLINUXDEBUG_H__
+
+/*
+* This file contains supporting interface for "vmcallinterface.h", particuarly
+* regarding adding additional structure and functionality to linux
+* ISSUE_IO_VMCALL_POSTCODE_SEVERITY */
+
+
+/******* INFO ON ISSUE_POSTCODE_LINUX() BELOW *******/
+#include "vmcallinterface.h"
+typedef enum {		/* POSTCODE driver identifier tuples */
+	/* visorchipset driver files */
+	VISOR_CHIPSET_PC = 0xA0,
+	VISOR_CHIPSET_PC_controlvm_c = 0xA1,
+	VISOR_CHIPSET_PC_controlvm_cm2 = 0xA2,
+	VISOR_CHIPSET_PC_controlvm_direct_c = 0xA3,
+	VISOR_CHIPSET_PC_file_c = 0xA4,
+	VISOR_CHIPSET_PC_parser_c = 0xA5,
+	VISOR_CHIPSET_PC_testing_c = 0xA6,
+	VISOR_CHIPSET_PC_visorchipset_main_c = 0xA7,
+	VISOR_CHIPSET_PC_visorswitchbus_c = 0xA8,
+	/* visorbus driver files */
+	VISOR_BUS_PC = 0xB0,
+	VISOR_BUS_PC_businst_attr_c = 0xB1,
+	VISOR_BUS_PC_channel_attr_c = 0xB2,
+	VISOR_BUS_PC_devmajorminor_attr_c = 0xB3,
+	VISOR_BUS_PC_visorbus_main_c = 0xB4,
+	/* visorclientbus driver files */
+	VISOR_CLIENT_BUS_PC = 0xC0,
+	VISOR_CLIENT_BUS_PC_visorclientbus_main_c = 0xC1,
+	/* virt hba driver files */
+	VIRT_HBA_PC = 0xC2,
+	VIRT_HBA_PC_virthba_c = 0xC3,
+	/* virtpci driver files */
+	VIRT_PCI_PC = 0xC4,
+	VIRT_PCI_PC_virtpci_c = 0xC5,
+	/* virtnic driver files */
+	VIRT_NIC_PC = 0xC6,
+	VIRT_NIC_P_virtnic_c = 0xC7,
+	/* uislib driver files */
+	UISLIB_PC = 0xD0,
+	UISLIB_PC_uislib_c = 0xD1,
+	UISLIB_PC_uisqueue_c = 0xD2,
+	UISLIB_PC_uisthread_c = 0xD3,
+	UISLIB_PC_uisutils_c = 0xD4,
+} DRIVER_PC;
+
+typedef enum {			/* POSTCODE event identifier tuples */
+	ATTACH_PORT_ENTRY_PC = 0x001,
+	ATTACH_PORT_FAILURE_PC = 0x002,
+	ATTACH_PORT_SUCCESS_PC = 0x003,
+	BUS_FAILURE_PC = 0x004,
+	BUS_CREATE_ENTRY_PC = 0x005,
+	BUS_CREATE_FAILURE_PC = 0x006,
+	BUS_CREATE_EXIT_PC = 0x007,
+	BUS_CONFIGURE_ENTRY_PC = 0x008,
+	BUS_CONFIGURE_FAILURE_PC = 0x009,
+	BUS_CONFIGURE_EXIT_PC = 0x00A,
+	CHIPSET_INIT_ENTRY_PC = 0x00B,
+	CHIPSET_INIT_SUCCESS_PC = 0x00C,
+	CHIPSET_INIT_FAILURE_PC = 0x00D,
+	CHIPSET_INIT_EXIT_PC = 0x00E,
+	CREATE_WORKQUEUE_PC = 0x00F,
+	CREATE_WORKQUEUE_FAILED_PC = 0x0A0,
+	CONTROLVM_INIT_FAILURE_PC = 0x0A1,
+	DEVICE_CREATE_ENTRY_PC = 0x0A2,
+	DEVICE_CREATE_FAILURE_PC = 0x0A3,
+	DEVICE_CREATE_SUCCESS_PC = 0x0A4,
+	DEVICE_CREATE_EXIT_PC = 0x0A5,
+	DEVICE_ADD_PC = 0x0A6,
+	DEVICE_REGISTER_FAILURE_PC = 0x0A7,
+	DEVICE_CHANGESTATE_ENTRY_PC = 0x0A8,
+	DEVICE_CHANGESTATE_FAILURE_PC = 0x0A9,
+	DEVICE_CHANGESTATE_EXIT_PC = 0x0AA,
+	DRIVER_ENTRY_PC = 0x0AB,
+	DRIVER_EXIT_PC = 0x0AC,
+	MALLOC_FAILURE_PC = 0x0AD,
+	QUEUE_DELAYED_WORK_PC = 0x0AE,
+	UISLIB_THREAD_FAILURE_PC = 0x0B7,
+	VBUS_CHANNEL_ENTRY_PC = 0x0B8,
+	VBUS_CHANNEL_FAILURE_PC = 0x0B9,
+	VBUS_CHANNEL_EXIT_PC = 0x0BA,
+	VHBA_CREATE_ENTRY_PC = 0x0BB,
+	VHBA_CREATE_FAILURE_PC = 0x0BC,
+	VHBA_CREATE_EXIT_PC = 0x0BD,
+	VHBA_CREATE_SUCCESS_PC = 0x0BE,
+	VHBA_COMMAND_HANDLER_PC = 0x0BF,
+	VHBA_PROBE_ENTRY_PC = 0x0C0,
+	VHBA_PROBE_FAILURE_PC = 0x0C1,
+	VHBA_PROBE_EXIT_PC = 0x0C2,
+	VNIC_CREATE_ENTRY_PC = 0x0C3,
+	VNIC_CREATE_FAILURE_PC = 0x0C4,
+	VNIC_CREATE_SUCCESS_PC = 0x0C5,
+	VNIC_PROBE_ENTRY_PC = 0x0C6,
+	VNIC_PROBE_FAILURE_PC = 0x0C7,
+	VNIC_PROBE_EXIT_PC = 0x0C8,
+	VPCI_CREATE_ENTRY_PC = 0x0C9,
+	VPCI_CREATE_FAILURE_PC = 0x0CA,
+	VPCI_CREATE_EXIT_PC = 0x0CB,
+	VPCI_PROBE_ENTRY_PC = 0x0CC,
+	VPCI_PROBE_FAILURE_PC = 0x0CD,
+	VPCI_PROBE_EXIT_PC = 0x0CE,
+	CRASH_DEV_ENTRY_PC = 0x0CF,
+	CRASH_DEV_EXIT_PC = 0x0D0,
+	CRASH_DEV_HADDR_NULL = 0x0D1,
+	CRASH_DEV_CONTROLVM_NULL = 0x0D2,
+	CRASH_DEV_RD_BUS_FAIULRE_PC = 0x0D3,
+	CRASH_DEV_RD_DEV_FAIULRE_PC = 0x0D4,
+	CRASH_DEV_BUS_NULL_FAILURE_PC = 0x0D5,
+	CRASH_DEV_DEV_NULL_FAILURE_PC = 0x0D6,
+	CRASH_DEV_CTRL_RD_FAILURE_PC = 0x0D7,
+	CRASH_DEV_COUNT_FAILURE_PC = 0x0D8,
+	SAVE_MSG_BUS_FAILURE_PC = 0x0D9,
+	SAVE_MSG_DEV_FAILURE_PC = 0x0DA,
+	CALLHOME_INIT_FAILURE_PC = 0x0DB
+} EVENT_PC;
+
+#ifdef __GNUC__
+
+#define POSTCODE_SEVERITY_ERR DIAG_SEVERITY_ERR
+#define POSTCODE_SEVERITY_WARNING DIAG_SEVERITY_WARNING
+#define POSTCODE_SEVERITY_INFO DIAG_SEVERITY_PRINT	/* TODO-> Info currently
+							 * doesnt show, so we
+							 * set info=warning */
+/* example call of POSTCODE_LINUX_2(VISOR_CHIPSET_PC, POSTCODE_SEVERITY_ERR);
+ * Please also note that the resulting postcode is in hex, so if you are
+ * searching for the __LINE__ number, convert it first to decimal.  The line
+ * number combined with driver and type of call, will allow you to track down
+ * exactly what line an error occured on, or where the last driver
+ * entered/exited from.
+ */
+
+/* BASE FUNCTIONS */
+#define POSTCODE_LINUX_A(DRIVER_PC, EVENT_PC, pc32bit, severity)	\
+do {									\
+	unsigned long long post_code_temp;				\
+	post_code_temp = (((U64)DRIVER_PC) << 56) | (((U64)EVENT_PC) << 44) | \
+		((((U64)__LINE__) & 0xFFF) << 32) |			\
+		(((U64)pc32bit) & 0xFFFFFFFF);				\
+	ISSUE_IO_VMCALL_POSTCODE_SEVERITY(post_code_temp, severity);	\
+} while (0)
+
+#define POSTCODE_LINUX_B(DRIVER_PC, EVENT_PC, pc16bit1, pc16bit2, severity) \
+do {									\
+	unsigned long long post_code_temp;				\
+	post_code_temp = (((U64)DRIVER_PC) << 56) | (((U64)EVENT_PC) << 44) | \
+		((((U64)__LINE__) & 0xFFF) << 32) |			\
+		((((U64)pc16bit1) & 0xFFFF) << 16) |			\
+		(((U64)pc16bit2) & 0xFFFF);				\
+	ISSUE_IO_VMCALL_POSTCODE_SEVERITY(post_code_temp, severity);	\
+} while (0)
+
+/* MOST COMMON */
+#define POSTCODE_LINUX_2(EVENT_PC, severity)				\
+	POSTCODE_LINUX_A(CURRENT_FILE_PC, EVENT_PC, 0x0000, severity);
+
+#define POSTCODE_LINUX_3(EVENT_PC, pc32bit, severity)			\
+	POSTCODE_LINUX_A(CURRENT_FILE_PC, EVENT_PC, pc32bit, severity);
+
+
+#define POSTCODE_LINUX_4(EVENT_PC, pc16bit1, pc16bit2, severity)	\
+	POSTCODE_LINUX_B(CURRENT_FILE_PC, EVENT_PC, pc16bit1,		\
+			 pc16bit2, severity);
+
+#endif
+#endif
diff --git a/drivers/staging/unisys/include/guidutils.h b/drivers/staging/unisys/include/guidutils.h
new file mode 100644
index 0000000..75caf92
--- /dev/null
+++ b/drivers/staging/unisys/include/guidutils.h
@@ -0,0 +1,203 @@
+/* Copyright © 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+/* guidutils.h
+ *
+ * These are GUID manipulation inlines that can be used from either
+ * kernel-mode or user-mode.
+ *
+ */
+#ifndef __GUIDUTILS_H__
+#define __GUIDUTILS_H__
+
+#ifdef __KERNEL__
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/ctype.h>
+#define GUID_STRTOUL kstrtoul
+#else
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+#include <stdlib.h>
+
+#define GUID_STRTOUL strtoul
+#endif
+
+static inline char *
+GUID_format1(const GUID *guid, char *s)
+{
+	sprintf(s, "{%-8.8lx-%-4.4x-%-4.4x-%-2.2x%-2.2x%-2.2x%-2.2x%-2.2x%-2.2x%-2.2x%-2.2x}",
+		(ulong) guid->data1,
+		guid->data2,
+		guid->data3,
+		guid->data4[0],
+		guid->data4[1],
+		guid->data4[2],
+		guid->data4[3],
+		guid->data4[4], guid->data4[5], guid->data4[6], guid->data4[7]);
+	return s;
+}
+
+/** Format a GUID in Microsoft's 'what in the world were they thinking'
+ *  format.
+ */
+static inline char *
+GUID_format2(const GUID *guid, char *s)
+{
+	sprintf(s, "{%-8.8lx-%-4.4x-%-4.4x-%-2.2x%-2.2x-%-2.2x%-2.2x%-2.2x%-2.2x%-2.2x%-2.2x}",
+		(ulong) guid->data1,
+		guid->data2,
+		guid->data3,
+		guid->data4[0],
+		guid->data4[1],
+		guid->data4[2],
+		guid->data4[3],
+		guid->data4[4], guid->data4[5], guid->data4[6], guid->data4[7]);
+	return s;
+}
+
+/**
+ * Like GUID_format2 but without the curly braces and the
+ * hex digits in upper case
+ */
+static inline char *
+GUID_format3(const GUID *guid, char *s)
+{
+	sprintf(s, "%-8.8lX-%-4.4X-%-4.4X-%-2.2X%-2.2X-%-2.2X%-2.2X%-2.2X%-2.2X%-2.2X%-2.2X",
+		(ulong) guid->data1,
+		guid->data2,
+		guid->data3,
+		guid->data4[0],
+		guid->data4[1],
+		guid->data4[2],
+		guid->data4[3],
+		guid->data4[4], guid->data4[5], guid->data4[6], guid->data4[7]);
+	return s;
+}
+
+/** Parse a guid string in any of these forms:
+ *      {11111111-2222-3333-4455-66778899aabb}
+ *      {11111111-2222-3333-445566778899aabb}
+ *      11111111-2222-3333-4455-66778899aabb
+ *      11111111-2222-3333-445566778899aabb
+ */
+static inline GUID
+GUID_scan(U8 *p)
+{
+	GUID guid = GUID0;
+	U8 x[33];
+	int count = 0;
+	int c, i = 0;
+	U8 cdata1[9];
+	U8 cdata2[5];
+	U8 cdata3[5];
+	U8 cdata4[3];
+	int dashcount = 0;
+	int brace = 0;
+	unsigned long uldata;
+
+	if (!p)
+		return guid;
+	if (*p == '{') {
+		p++;
+		brace = 1;
+	}
+	while (count < 32) {
+		if (*p == '}')
+			return guid;
+		if (*p == '\0')
+			return guid;
+		c = toupper(*p);
+		p++;
+		if (c == '-') {
+			switch (dashcount) {
+			case 0:
+				if (i != 8)
+					return guid;
+				break;
+			case 1:
+				if (i != 4)
+					return guid;
+				break;
+			case 2:
+				if (i != 4)
+					return guid;
+				break;
+			case 3:
+				if (i != 4)
+					return guid;
+				break;
+			default:
+				return guid;
+			}
+			dashcount++;
+			i = 0;
+			continue;
+		}
+		if ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F'))
+			i++;
+		else
+			return guid;
+		x[count++] = c;
+	}
+	x[count] = '\0';
+	if (brace) {
+		if (*p == '}')
+			p++;
+		else
+			return guid;
+	}
+	if (dashcount == 3 || dashcount == 4)
+		;
+	else
+		return guid;
+	memset(cdata1, 0, sizeof(cdata1));
+	memset(cdata2, 0, sizeof(cdata2));
+	memset(cdata3, 0, sizeof(cdata3));
+	memset(cdata4, 0, sizeof(cdata4));
+	memcpy(cdata1, x + 0, 8);
+	memcpy(cdata2, x + 8, 4);
+	memcpy(cdata3, x + 12, 4);
+
+	if (GUID_STRTOUL((char *) cdata1, 16, &uldata) == 0)
+		guid.data1 = (U32)uldata;
+	if (GUID_STRTOUL((char *) cdata2, 16, &uldata) == 0)
+		guid.data2 = (U16)uldata;
+	if (GUID_STRTOUL((char *) cdata3, 16, &uldata) == 0)
+		guid.data3 = (U16)uldata;
+
+	for (i = 0; i < 8; i++) {
+		memcpy(cdata4, x + 16 + (i * 2), 2);
+		if (GUID_STRTOUL((char *) cdata4, 16, &uldata) == 0)
+			guid.data4[i] = (U8) uldata;
+	}
+
+	return guid;
+}
+
+static inline char *
+GUID_sanitize(char *inputGuidStr, char *outputGuidStr)
+{
+	GUID g;
+	GUID guid0 = GUID0;
+	*outputGuidStr = '\0';
+	g = GUID_scan((U8 *) inputGuidStr);
+	if (memcmp(&g, &guid0, sizeof(GUID)) == 0)
+		return outputGuidStr;	/* bad GUID format */
+	return GUID_format1(&g, outputGuidStr);
+}
+
+#endif
diff --git a/drivers/staging/unisys/include/periodic_work.h b/drivers/staging/unisys/include/periodic_work.h
new file mode 100644
index 0000000..6e725df
--- /dev/null
+++ b/drivers/staging/unisys/include/periodic_work.h
@@ -0,0 +1,40 @@
+/* periodic_work.h
+ *
+ * Copyright © 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+#ifndef __PERIODIC_WORK_H__
+#define __PERIODIC_WORK_H__
+
+#include "timskmod.h"
+
+
+
+/* PERIODIC_WORK an opaque structure to users.
+ * Fields are declared only in the implementation .c files.
+ */
+typedef struct PERIODIC_WORK_Tag PERIODIC_WORK;
+
+PERIODIC_WORK *periodic_work_create(ulong jiffy_interval,
+				     struct workqueue_struct *workqueue,
+				     void (*workfunc)(void *),
+				     void *workfuncarg,
+				     const char *devnam);
+void            periodic_work_destroy(PERIODIC_WORK *periodic_work);
+BOOL            periodic_work_nextperiod(PERIODIC_WORK *periodic_work);
+BOOL            periodic_work_start(PERIODIC_WORK *periodic_work);
+BOOL            periodic_work_stop(PERIODIC_WORK *periodic_work);
+
+#endif
diff --git a/drivers/staging/unisys/include/procobjecttree.h b/drivers/staging/unisys/include/procobjecttree.h
new file mode 100644
index 0000000..d3b69f4
--- /dev/null
+++ b/drivers/staging/unisys/include/procobjecttree.h
@@ -0,0 +1,48 @@
+/* procobjecttree.h
+ *
+ * Copyright © 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+/** @file *********************************************************************
+ *
+ *  This describes the interfaces necessary for creating a tree of types,
+ *  objects, and properties in /proc.
+ *
+ ******************************************************************************
+ */
+
+#ifndef __PROCOBJECTTREE_H__
+#define __PROCOBJECTTREE_H__
+
+#include "uniklog.h"
+#include "timskmod.h"
+
+/* These are opaque structures to users.
+ * Fields are declared only in the implementation .c files.
+ */
+typedef struct MYPROCOBJECT_Tag MYPROCOBJECT;
+typedef struct MYPROCTYPE_Tag   MYPROCTYPE;
+
+MYPROCOBJECT *proc_CreateObject(MYPROCTYPE *type, const char *name,
+				void *context);
+void          proc_DestroyObject(MYPROCOBJECT *obj);
+MYPROCTYPE   *proc_CreateType(struct proc_dir_entry *procRootDir,
+			      const char **name,
+			      const char **propertyNames,
+			      void (*show_property)(struct seq_file *,
+						    void *, int));
+void          proc_DestroyType(MYPROCTYPE *type);
+
+#endif
diff --git a/drivers/staging/unisys/include/sparstop.h b/drivers/staging/unisys/include/sparstop.h
new file mode 100644
index 0000000..3603ac6
--- /dev/null
+++ b/drivers/staging/unisys/include/sparstop.h
@@ -0,0 +1,30 @@
+/* sparstop.h
+ *
+ * Copyright © 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+#ifndef __SPARSTOP_H__
+#define __SPARSTOP_H__
+
+#include "timskmod.h"
+#include "version.h"
+#include <linux/ctype.h>
+
+typedef void (*SPARSTOP_COMPLETE_FUNC) (void *context, int status);
+
+int sp_stop(void *context, SPARSTOP_COMPLETE_FUNC get_complete_func);
+void test_remove_stop_device(void);
+
+#endif
diff --git a/drivers/staging/unisys/include/timskmod.h b/drivers/staging/unisys/include/timskmod.h
new file mode 100644
index 0000000..0d0b29c
--- /dev/null
+++ b/drivers/staging/unisys/include/timskmod.h
@@ -0,0 +1,558 @@
+/* timskmod.h
+ *
+ * Copyright � 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+#ifndef __TIMSKMOD_H__
+#define __TIMSKMOD_H__
+
+#include <linux/version.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/kobject.h>
+#include <linux/sysfs.h>
+#include <linux/fs.h>
+#include <linux/string.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include <linux/wait.h>
+#include <linux/vmalloc.h>
+#include <linux/proc_fs.h>
+#include <linux/cdev.h>
+#include <linux/types.h>
+#include <asm/irq.h>
+#include <linux/io.h>
+#include <asm/dma.h>
+#include <linux/uaccess.h>
+#include <linux/list.h>
+#include <linux/poll.h>
+/* #define EXPORT_SYMTAB */
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/fcntl.h>
+#include <linux/aio.h>
+#include <linux/workqueue.h>
+#include <linux/kthread.h>
+#include <linux/seq_file.h>
+#include <linux/mm.h>
+
+/* #define DEBUG */
+#ifndef BOOL
+#define BOOL    int
+#endif
+#define FALSE   0
+#define TRUE    1
+#if !defined SUCCESS
+#define SUCCESS 0
+#endif
+#define FAILURE (-1)
+#define DRIVERNAMEMAX 50
+#define MIN(a, b)     (((a) < (b)) ? (a) : (b))
+#define MAX(a, b)     (((a) > (b)) ? (a) : (b))
+#define STRUCTSEQUAL(x, y) (memcmp(&x, &y, sizeof(x)) == 0)
+#ifndef HOSTADDRESS
+#define HOSTADDRESS unsigned long long
+#endif
+
+typedef long VMMIO;  /**< Virtual MMIO address (returned from ioremap), which
+    *   is a virtual address pointer to a memory-mapped region.
+    *   These are declared as "long" instead of u32* to force you to
+    *   use readb()/writeb()/memcpy_fromio()/etc to access them.
+    *   (On x86 we could probably get away with treating them as
+    *   pointers.)
+    */
+typedef long VMMIO8; /**< #VMMIO pointing to  8-bit data */
+typedef long VMMIO16;/**< #VMMIO pointing to 16-bit data */
+typedef long VMMIO32;/**< #VMMIO pointing to 32-bit data */
+
+#define LOCKSEM(sem)                   down_interruptible(sem)
+#define LOCKSEM_UNINTERRUPTIBLE(sem)   down(sem)
+#define UNLOCKSEM(sem)                 up(sem)
+
+/** lock read/write semaphore for reading.
+    Note that all read/write semaphores are of the "uninterruptible" variety.
+    @param sem (rw_semaphore *) points to semaphore to lock
+ */
+#define LOCKREADSEM(sem)               down_read(sem)
+
+/** unlock read/write semaphore for reading.
+    Note that all read/write semaphores are of the "uninterruptible" variety.
+    @param sem (rw_semaphore *) points to semaphore to unlock
+ */
+#define UNLOCKREADSEM(sem)             up_read(sem)
+
+/** lock read/write semaphore for writing.
+    Note that all read/write semaphores are of the "uninterruptible" variety.
+    @param sem (rw_semaphore *) points to semaphore to lock
+ */
+#define LOCKWRITESEM(sem)              down_write(sem)
+
+/** unlock read/write semaphore for writing.
+    Note that all read/write semaphores are of the "uninterruptible" variety.
+    @param sem (rw_semaphore *) points to semaphore to unlock
+ */
+#define UNLOCKWRITESEM(sem)            up_write(sem)
+
+#ifdef ENABLE_RETURN_TRACE
+#define RETTRACE(x)                                            \
+	do {						       \
+		if (1) {				       \
+			INFODRV("RET 0x%lx in %s",	       \
+				(ulong)(x), __func__);     \
+		}					   \
+	} while (0)
+#else
+#define RETTRACE(x)
+#endif
+
+/** return from a void function, using a common exit point "Away" */
+#define RETVOID    do { RETTRACE(0); goto Away; } while (0)
+/** return from an int function, using a common exit point "Away"
+ *  @param x the value to return
+ */
+#define RETINT(x)  do { rc = (x); RETTRACE(x); goto Away; } while (0)
+/** return from a void* function, using a common exit point "Away"
+ *  @param x the value to return
+ */
+#define RETPTR(x)  do { rc = (x); RETTRACE(x); goto Away; } while (0)
+/** return from a BOOL function, using a common exit point "Away"
+ *  @param x the value to return
+ */
+#define RETBOOL(x) do { rc = (x); RETTRACE(x); goto Away; } while (0)
+/** Given a typedef/struct/union and a member field name,
+ *  return the number of bytes occupied by that field.
+ *  @param TYPE     the typedef name, or "struct xx" or "union xx"
+ *  @param MEMBER   the name of the member field whose size is to be determined
+ *  @return         the size of the field in bytes
+ */
+#define FAIL(msg, status) do {          \
+		ERRDRV("'%s'"					      \
+		       ": error (status=%d)\n",			      \
+		       msg, status);				      \
+		RETINT(status);					      \
+	} while (0)
+#define FAIL_WPOSTCODE_1(msg, status, EVENT_PC) do {          \
+		ERRDRV("'%s'"					      \
+		       ": error (status=%d)\n",			      \
+		       msg, status);					\
+		POSTCODE_LINUX_2(EVENT_PC, DIAG_SEVERITY_ERR);		\
+		RETINT(status);						\
+	} while (0)
+#define FAIL_WPOSTCODE_2(msg, status, EVENT_PC, pcval32bit) do {          \
+		ERRDRV("'%s'"						\
+		       ": error (status=%d)\n",				\
+		       msg, status);					\
+		POSTCODE_LINUX_3(EVENT_PC, pcval32bit, DIAG_SEVERITY_ERR); \
+		RETINT(status);						\
+	} while (0)
+#define FAIL_WPOSTCODE_3(msg, status, EVENT_PC, pcval16bit1, pcval16bit2) \
+	do {								\
+		ERRDRV("'%s'"						\
+		       ": error (status=%d)\n",				\
+		       msg, status);					\
+		POSTCODE_LINUX_4(EVENT_PC, pcval16bit1, pcval16bit2,	\
+				 DIAG_SEVERITY_ERR);			\
+		RETINT(status);						\
+	} while (0)
+/** Try to evaulate the provided expression, and do a RETINT(x) iff
+ *  the expression evaluates to < 0.
+ *  @param x the expression to try
+ */
+#define TRY(x) do { int status = (x);                          \
+		if (status < 0)				       \
+			FAIL(__stringify(x), status);	       \
+	} while (0)
+
+#define TRY_WPOSTCODE_1(x, EVENT_PC) do { \
+		int status = (x);	  \
+		if (status < 0)						\
+			FAIL_WPOSTCODE_1(__stringify(x), status, EVENT_PC); \
+	} while (0)
+
+#define TRY_WPOSTCODE_2(x, EVENT_PC, pcval32bit) do { \
+		int status = (x);		      \
+		if (status < 0)						\
+			FAIL_WPOSTCODE_2(__stringify(x), status, EVENT_PC, \
+					 pcval32bit);			\
+	} while (0)
+
+#define TRY_WPOSTCODE_3(x, EVENT_PC, pcval16bit1, pcval16bit2) do { \
+		int status = (x);				    \
+		if (status < 0)						\
+			FAIL_WPOSTCODE_3(__stringify(x), status, EVENT_PC, \
+					 pcval16bit1, pcval16bit2);	\
+	} while (0)
+
+#define ASSERT(cond)                                           \
+	do { if (!(cond))                                      \
+			HUHDRV("ASSERT failed - %s",	       \
+			       __stringify(cond));	       \
+	} while (0)
+
+#define sizeofmember(TYPE, MEMBER) (sizeof(((TYPE *)0)->MEMBER))
+/** "Covered quotient" function */
+#define COVQ(v, d)  (((v) + (d) - 1) / (d))
+#define SWAPPOINTERS(p1, p2)				\
+	do {						\
+		void *SWAPPOINTERS_TEMP = (void *)p1;	\
+		(void *)(p1) = (void *)(p2);            \
+		(void *)(p2) = SWAPPOINTERS_TEMP;	\
+	} while (0)
+
+/**
+ *  @addtogroup driverlogging
+ *  @{
+ */
+
+#define PRINTKDRV(fmt, args...) LOGINF(fmt, ## args)
+#define TBDDRV(fmt, args...)    LOGERR(fmt, ## args)
+#define HUHDRV(fmt, args...)    LOGERR(fmt, ## args)
+#define ERRDRV(fmt, args...)    LOGERR(fmt, ## args)
+#define WARNDRV(fmt, args...)   LOGWRN(fmt, ## args)
+#define SECUREDRV(fmt, args...) LOGWRN(fmt, ## args)
+#define INFODRV(fmt, args...)   LOGINF(fmt, ## args)
+#define DEBUGDRV(fmt, args...)  DBGINF(fmt, ## args)
+
+#define PRINTKDEV(devname, fmt, args...)  LOGINFDEV(devname, fmt, ## args)
+#define TBDDEV(devname, fmt, args...)     LOGERRDEV(devname, fmt, ## args)
+#define HUHDEV(devname, fmt, args...)     LOGERRDEV(devname, fmt, ## args)
+#define ERRDEV(devname, fmt, args...)     LOGERRDEV(devname, fmt, ## args)
+#define ERRDEVX(devno, fmt, args...)	  LOGERRDEVX(devno, fmt, ## args)
+#define WARNDEV(devname, fmt, args...)    LOGWRNDEV(devname, fmt, ## args)
+#define SECUREDEV(devname, fmt, args...)  LOGWRNDEV(devname, fmt, ## args)
+#define INFODEV(devname, fmt, args...)    LOGINFDEV(devname, fmt, ## args)
+#define INFODEVX(devno, fmt, args...)     LOGINFDEVX(devno, fmt, ## args)
+#define DEBUGDEV(devname, fmt, args...)   DBGINFDEV(devname, fmt, ## args)
+
+
+/* @} */
+
+/** Used to add a single line to the /proc filesystem buffer */
+#define ADDPROCLINE(buf, bufsize, line, linelen, totallen) \
+	{						   \
+		if ((totallen) + (linelen) >= bufsize)     \
+			RETINT(totallen);		   \
+		if (linelen > 0) {			   \
+			strcat(buf, line);		   \
+			totallen += linelen;		   \
+		}                                          \
+	}
+
+
+
+/** Verifies the consistency of your PRIVATEDEVICEDATA structure using
+ *  conventional "signature" fields:
+ *  <p>
+ *  - sig1 should contain the size of the structure
+ *  - sig2 should contain a pointer to the beginning of the structure
+ */
+#define DDLOOKSVALID(dd)                                 \
+		((dd != NULL)                             &&	\
+		 ((dd)->sig1 == sizeof(PRIVATEDEVICEDATA)) &&	\
+		 ((dd)->sig2 == dd))
+
+/** Verifies the consistency of your PRIVATEFILEDATA structure using
+ *  conventional "signature" fields:
+ *  <p>
+ *  - sig1 should contain the size of the structure
+ *  - sig2 should contain a pointer to the beginning of the structure
+ */
+#define FDLOOKSVALID(fd)                               \
+	((fd != NULL)                           &&     \
+	 ((fd)->sig1 == sizeof(PRIVATEFILEDATA)) &&    \
+	 ((fd)->sig2 == fd))
+
+/** Verifies the consistency of a PRIVATEDEVICEDATA structure and reacts
+ *  if necessary
+ */
+#define CHKDDX(dd, x) (					   \
+			if (!DDLOOKSVALID((dd))) {	   \
+				PRINTKDRV("bad device structure");	\
+				RETINT(x);				\
+			})
+
+/** Verifies the consistency of a PRIVATEDEVICEDATA structure and reacts
+ *  if necessary
+ */
+#define CHKDD(dd) (							\
+			if (!DDLOOKSVALID(dd)) {			\
+				PRINTKDRV("bad device structure");	\
+				RETVOID;				\
+			})
+
+/** Verifies the consistency of a PRIVATEFILEDATA structure and reacts
+ *  if necessary
+ */
+#define CHKFDX(fd, x) (					   \
+		if (!FDLOOKSVALID(fd)) {		   \
+			PRINTKDRV("bad file structure");   \
+			RETINT(x);			   \
+		})
+
+/** Verifies the consistency of a PRIVATEFILEDATA structure and reacts
+ *  if necessary
+ */
+#define CHKFD(fd) (					  \
+		if (!FDLOOKSVALID(fd)) {		  \
+			PRINTKDRV("bad file structure");  \
+			RETVOID;			  \
+		})
+
+/** Converts a device index #devix into #devData, after checking for validity.
+ *  Can only be called from functions returning void.
+ *  @param devix your device index within the #DevData array.
+ *  @param devData the #PRIVATEDEVICEDATA pointer that will be set on return.
+ *  @param where string identifying the calling function, to be printed in
+ *         debug message
+ *  @param dbg 1 iff debug messages are enabled
+ */
+#define DEVFROMID(devix, devData, where, dbg)				\
+	{								\
+		if (devix >= MAXDEVICES) {				\
+			PRINTKDRV("bad devix passed to %s()", where);	\
+			RETVOID;					\
+		}							\
+		if (dbg)						\
+			DEBUGDEV(devix, "%s", where);			\
+		if (devix >= MAXDEVICES) {				\
+			DEBUGDEV(devix, "%s - bad devix %d",		\
+				 where, devix);				\
+			RETVOID;					\
+		}							\
+		devData = DevData[devix];				\
+		CHKDD(devData);						\
+	}
+
+/** Converts a device index #devix into #devData, after checking for validity.
+ *  Can only be called from functions returning int.
+ *  @param devix your device index within the #DevData array.
+ *  @param devData the #PRIVATEDEVICEDATA pointer that will be set on return.
+ *  @param errcode error code that your function will return on error.
+ *  @param where string identifying the calling function, to be printed in
+ *         debug message
+ *  @param dbg 1 iff debug messages are enabled
+ */
+#define DEVFROMIDX(devix, devData, errcode, where, dbg)			\
+	{								\
+		if (devix >= MAXDEVICES) {				\
+			PRINTKDRV("bad devix passed to %s()", where);	\
+			RETINT(errcode);				\
+		}							\
+		if (dbg)						\
+			DEBUGDEV(devix, "%s", where);			\
+		if (devix >= MAXDEVICES) {				\
+			DEBUGDEV(devix, "%s - bad devix %d",		\
+				 where, devix);				\
+			RETINT(-ENODEV);				\
+		}							\
+		devData = DevData[devix];				\
+		CHKDDX(devData, -EIO);					\
+	}
+
+/** Converts an inode pointer #inode into a #devix and #devData, after
+ *  checking for validity.
+ *  Can only be called from functions returning int.
+ *  @param devix your device index within the #DevData array.
+ *  @param devData the #PRIVATEDEVICEDATA pointer that will be set on return.
+ *  @param inode input inode pointer
+ *  @param errcode error code that your function will return on error.
+ *  @param where string identifying the calling function, to be printed in
+ *         debug message
+ *  @param dbg 1 iff debug messages are enabled
+ */
+#define DEVFROMINODE(devix, devData, inode, errcode, where, dbg)	\
+	{								\
+		if (inode == NULL) {					\
+			PRINTKDRV("bad inode passed to %s()", where);	\
+			RETINT(errcode);				\
+		}							\
+		devix = MINOR(inode->i_rdev);				\
+		if (dbg)						\
+			DEBUGDEV(devix, "%s", where);			\
+		if (devix >= MAXDEVICES) {				\
+			DEBUGDEV(devix, "%s - bad devix %d",		\
+				 where, devix);				\
+			RETINT(-ENODEV);				\
+		}							\
+		devData = DevData[devix];				\
+		CHKDDX(devData, -EIO);					\
+	}
+
+/** Converts a file pointer #file into a #devix and #devData, after checking
+ *  for validity.
+ *  Can only be called from functions returning int.
+ *  @param devix your device index within the #DevData array.
+ *  @param devData the #PRIVATEDEVICEDATA pointer that will be set on return.
+ *  @param file input file pointer
+ *  @param errcode error code that your function will return on error.
+ *  @param where string identifying the calling function, to be printed in
+ *         debug message
+ *  @param dbg 1 iff debug messages are enabled
+ */
+#define DEVFROMFILE(devix, devData, fileData, file, errcode, where, dbg) \
+		{							\
+		if (file == NULL) {					\
+			PRINTKDRV("bad file passed to %s()", where);	\
+			RETINT(errcode);				\
+		}							\
+		CHKFDX((PRIVATEFILEDATA *)(file->private_data), -EIO);	\
+		fileData = file->private_data;				\
+		devix = fileData->devix;				\
+		if (dbg)						\
+			DEBUGDEV(devix, "%s %p", where, file);		\
+		if (devix >= MAXDEVICES) {				\
+			DEBUGDEV(devix, "%s - bad devix %d",		\
+				 where, devix);				\
+			RETINT(-ENODEV);				\
+		}							\
+		devData = DevData[devix];				\
+		CHKDDX(devData, -EIO);					\
+	}
+
+/** Locks dd->lockDev if you havn't already locked it */
+#define LOCKDEV(dd)                                                    \
+	{                                                              \
+		if (!lockedDev) {				       \
+			spin_lock(&dd->lockDev);		       \
+			lockedDev = TRUE;			       \
+		}						       \
+	}
+
+/** Unlocks dd->lockDev if you previously locked it */
+#define UNLOCKDEV(dd)                                                  \
+	{                                                              \
+		if (lockedDev) {				       \
+			spin_unlock(&dd->lockDev);		       \
+			lockedDev = FALSE;			       \
+		}						       \
+	}
+
+/** Locks dd->lockDevISR if you havn't already locked it */
+#define LOCKDEVISR(dd)                                                 \
+	{                                                              \
+		if (!lockedDevISR) {				       \
+			spin_lock_irqsave(&dd->lockDevISR, flags);     \
+			lockedDevISR = TRUE;			       \
+		}						       \
+	}
+
+/** Unlocks dd->lockDevISR if you previously locked it */
+#define UNLOCKDEVISR(dd)						\
+	{								\
+		if (lockedDevISR) {					\
+			spin_unlock_irqrestore(&dd->lockDevISR, flags); \
+			lockedDevISR = FALSE;				\
+		}							\
+	}
+
+/** Locks LockGlobalISR if you havn't already locked it */
+#define LOCKGLOBALISR                                                  \
+	{                                                              \
+		if (!lockedGlobalISR) {				       \
+			spin_lock_irqsave(&LockGlobalISR, flags);      \
+			lockedGlobalISR = TRUE;			       \
+		}						       \
+	}
+
+/** Unlocks LockGlobalISR if you previously locked it */
+#define UNLOCKGLOBALISR                                                \
+	{                                                              \
+		if (lockedGlobalISR) {				       \
+			spin_unlock_irqrestore(&LockGlobalISR, flags); \
+			lockedGlobalISR = FALSE;		       \
+		}						       \
+	}
+
+/** Locks LockGlobal if you havn't already locked it */
+#define LOCKGLOBAL                                                     \
+	{                                                              \
+		if (!lockedGlobal) {				       \
+			spin_lock(&LockGlobal);			       \
+			lockedGlobal = TRUE;			       \
+		}						       \
+	}
+
+/** Unlocks LockGlobal if you previously locked it */
+#define UNLOCKGLOBAL                                                   \
+	{                                                              \
+		if (lockedGlobal) {				       \
+			spin_unlock(&LockGlobal);		       \
+			lockedGlobal = FALSE;			       \
+		}						       \
+	}
+
+/** Use this at the beginning of functions where you intend to
+ *  use #LOCKDEV/#UNLOCKDEV, #LOCKDEVISR/#UNLOCKDEVISR,
+ *  #LOCKGLOBAL/#UNLOCKGLOBAL, #LOCKGLOBALISR/#UNLOCKGLOBALISR.
+ *
+ *  Note that __attribute__((unused)) is how you tell GNU C to suppress
+ *  any warning messages about the variable being unused.
+ */
+#define LOCKPREAMBLE							\
+	ulong flags __attribute__((unused)) = 0;			\
+	BOOL lockedDev __attribute__((unused)) = FALSE;			\
+	BOOL lockedDevISR __attribute__((unused)) = FALSE;		\
+	BOOL lockedGlobal __attribute__((unused)) = FALSE;		\
+	BOOL lockedGlobalISR __attribute__((unused)) = FALSE
+
+
+
+/** Sleep for an indicated number of seconds (for use in kernel mode).
+ *  @param x the number of seconds to sleep.
+ */
+#define SLEEP(x)					     \
+	do { current->state = TASK_INTERRUPTIBLE;	     \
+		schedule_timeout((x)*HZ);		     \
+	} while (0)
+
+/** Sleep for an indicated number of jiffies (for use in kernel mode).
+ *  @param x the number of jiffies to sleep.
+ */
+#define SLEEPJIFFIES(x)						    \
+	do { current->state = TASK_INTERRUPTIBLE;		    \
+		schedule_timeout(x);				    \
+	} while (0)
+
+#ifndef max
+#define max(a, b) (((a) > (b)) ? (a):(b))
+#endif
+
+static inline struct cdev *cdev_alloc_init(struct module *owner,
+					   const struct file_operations *fops)
+{
+	struct cdev *cdev = NULL;
+	cdev = cdev_alloc();
+	if (!cdev)
+		return NULL;
+	cdev->ops = fops;
+	cdev->owner = owner;
+
+	/* Note that the memory allocated for cdev will be deallocated
+	 * when the usage count drops to 0, because it is controlled
+	 * by a kobject of type ktype_cdev_dynamic.  (This
+	 * deallocation could very well happen outside of our kernel
+	 * module, like via the cdev_put in __fput() for example.)
+	 */
+	return cdev;
+}
+
+#include "timskmodutils.h"
+
+#endif
diff --git a/drivers/staging/unisys/include/timskmodutils.h b/drivers/staging/unisys/include/timskmodutils.h
new file mode 100644
index 0000000..ad4175e
--- /dev/null
+++ b/drivers/staging/unisys/include/timskmodutils.h
@@ -0,0 +1,194 @@
+/* timskmodutils.h
+ *
+ * Copyright © 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+#ifndef __TIMSKMODUTILS_H__
+#define __TIMSKMODUTILS_H__
+
+#include "timskmod.h"
+
+void *kmalloc_kernel(size_t siz);
+void *kmalloc_kernel_dma(size_t siz);
+void  kfree_kernel(const void *p, size_t siz);
+void *vmalloc_kernel(size_t siz);
+void  vfree_kernel(const void *p, size_t siz);
+void *pgalloc_kernel(size_t siz);
+void  pgfree_kernel(const void *p, size_t siz);
+void  myprintk(const char *myDrvName, const char *devname,
+		const char *template, ...);
+void  myprintkx(const char *myDrvName, int devno, const char *template, ...);
+
+/** Print the hexadecimal contents of a data buffer to a supplied print buffer.
+ *  @param dest               the print buffer where text characters will be
+ *                            written
+ *  @param destSize           the maximum number of bytes that can be written
+ *                            to #dest
+ *  @param src                the buffer that contains the data that is to be
+ *                            hex-dumped
+ *  @param srcLen             the number of bytes at #src to be hex-dumped
+ *  @param bytesToDumpPerLine output will be formatted such that at most this
+ *                            many of the input data bytes will be represented
+ *                            on each line of output
+ *  @return                   the number of text characters written to #dest
+ *                            (not including the trailing '\0' byte)
+ *  @ingroup internal
+ */
+int   hexDumpToBuffer(char *dest,
+		      int destSize,
+		      char *prefix,
+		      char *src,
+		      int srcLen,
+		      int bytesToDumpPerLine);
+
+/** Print the hexadecimal contents of a data buffer to a supplied print buffer.
+ *  Assume the data buffer contains 32-bit words in little-endian format,
+ *  and dump the words with MSB first and LSB last.
+ *  @param dest               the print buffer where text characters will be
+ *                            written
+ *  @param destSize           the maximum number of bytes that can be written
+ *                            to #dest
+ *  @param src                the buffer that contains the data that is to be
+ *                            hex-dumped
+ *  @param srcWords           the number of 32-bit words at #src to be
+ &                            hex-dumped
+ *  @param wordsToDumpPerLine output will be formatted such that at most this
+ *                            many of the input data words will be represented
+ *                            on each line of output
+ *  @return                   the number of text characters written to #dest
+ *                            (not including the trailing '\0' byte)
+ *  @ingroup internal
+ */
+int   hexDumpWordsToBuffer(char *dest,
+			   int destSize,
+			   char *prefix,
+			   uint32_t *src,
+			   int srcWords,
+			   int wordsToDumpPerLine);
+
+
+/** Use printk to print the hexadecimal contents of a data buffer.
+ *  See #INFOHEXDRV and #INFOHEXDEV for info.
+ *  @ingroup internal
+ */
+int myPrintkHexDump(char *myDrvName,
+		    char *devname,
+		    char *prefix,
+		    char *src,
+		    int srcLen,
+		    int bytesToDumpPerLine);
+
+/** Given as input a number of seconds in #seconds, creates text describing
+ *  the time within #s.  Also breaks down the number of seconds into component
+ *  days, hours, minutes, and seconds, and stores to *#days, *#hours,
+ *  *#minutes, and *#secondsx.
+ *  @param seconds input number of seconds
+ *  @param days    points to a long value where the days component for the
+ *                 days+hours+minutes+seconds representation of #seconds will
+ *                 be stored
+ *  @param hours   points to a long value where the hours component for the
+ *                 days+hours+minutes+seconds representation of #seconds will
+ *                 be stored
+ *  @param minutes points to a long value where the minutes component for the
+ *                 days+hours+minutes+seconds representation of #seconds will
+ *                 be stored
+ *  @param secondsx points to a long value where the seconds component for the
+ *                 days+hours+minutes+seconds representation of #seconds will
+ *                 be stored
+ *  @param s       points to a character buffer where a text representation of
+ *                 the #seconds value will be stored.  This buffer MUST be
+ *                 large enough to hold the resulting string; to be safe it
+ *                 should be at least 100 bytes long.
+ */
+void  expandSeconds(time_t seconds,
+		    long *days, long *hours,
+		    long *minutes,
+		    long *secondsx,
+		    char *s);
+
+/*--------------------------------*
+ *---  GENERAL MESSAGEQ STUFF  ---*
+ *--------------------------------*/
+
+struct MessageQEntry;
+
+/** the data structure used to hold an arbitrary data item that you want
+ *  to place on a #MESSAGEQ.  Declare and initialize as follows:
+ *  @code
+ *      MESSAGEQENTRY myEntry;
+ *      initMessageQEntry (&myEntry, pointerToMyDataItem);
+ *  @endcode
+ *  This structure should be considered opaque; the client using it should
+ *  never access the fields directly.
+ *  Refer to these functions for more info:
+ *  - initMessageQ()
+ *  - initMessageQEntry()
+ *  - enqueueMessage()
+ *  - dequeueMessage()
+ *  - dequeueMessageNoBlock()
+ *  - getQueueCount()
+ *
+ *  @ingroup messageq
+ */
+typedef struct MessageQEntry {
+	void *data;
+	struct MessageQEntry *qNext;
+	struct MessageQEntry *qPrev;
+} MESSAGEQENTRY;
+
+/** the data structure used to hold a FIFO queue of #MESSAGEQENTRY<b></b>s.
+ *  Declare and initialize as follows:
+ *  @code
+ *      MESSAGEQ myQueue;
+ *      initMessageQ (&myQueue);
+ *  @endcode
+ *  This structure should be considered opaque; the client using it should
+ *  never access the fields directly.
+ *  Refer to these functions for more info:
+ *  - initMessageQ()
+ *  - initMessageQEntry()
+ *  - enqueueMessage()
+ *  - dequeueMessage()
+ *  - dequeueMessageNoBlock()
+ *  - getQueueCount()
+ *
+ *  @ingroup messageq
+ */
+typedef struct MessageQ {
+	MESSAGEQENTRY *qHead;
+	MESSAGEQENTRY *qTail;
+	struct semaphore nQEntries;
+	spinlock_t       queueLock;
+} MESSAGEQ;
+
+char *cyclesToSeconds(u64 cycles, u64 cyclesPerSecond,
+		      char *buf, size_t bufsize);
+char *cyclesToIterationSeconds(u64 cycles, u64 cyclesPerSecond,
+			       u64 iterations, char *buf, size_t bufsize);
+char *cyclesToSomethingsPerSecond(u64 cycles, u64 cyclesPerSecond,
+				  u64 somethings, char *buf, size_t bufsize);
+void initMessageQ(MESSAGEQ *q);
+void initMessageQEntry(MESSAGEQENTRY *p, void *data);
+MESSAGEQENTRY *dequeueMessage(MESSAGEQ *q);
+MESSAGEQENTRY *dequeueMessageNoBlock(MESSAGEQ *q);
+void enqueueMessage(MESSAGEQ *q, MESSAGEQENTRY *pEntry);
+size_t getQueueCount(MESSAGEQ *q);
+int waitQueueLen(wait_queue_head_t *q);
+void debugWaitQ(wait_queue_head_t *q);
+struct seq_file *seq_file_new_buffer(void *buf, size_t buf_size);
+void seq_file_done_buffer(struct seq_file *m);
+void seq_hexdump(struct seq_file *seq, u8 *pfx, void *buf, ulong nbytes);
+
+#endif
diff --git a/drivers/staging/unisys/include/uisqueue.h b/drivers/staging/unisys/include/uisqueue.h
new file mode 100644
index 0000000..a9d95d3
--- /dev/null
+++ b/drivers/staging/unisys/include/uisqueue.h
@@ -0,0 +1,472 @@
+/* uisqueue.h
+ *
+ * Copyright © 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+/*
+ * Unisys IO Virtualization header NOTE: This file contains only Linux
+ * specific structs.  All OS-independent structs are in iochannel.h.xx
+ */
+
+#ifndef __UISQUEUE_H__
+#define __UISQUEUE_H__
+
+#include "linux/version.h"
+#include "iochannel.h"
+#include "uniklog.h"
+#include <linux/atomic.h>
+#include <linux/semaphore.h>
+
+#include "controlvmchannel.h"
+#include "controlvmcompletionstatus.h"
+
+struct uisqueue_info {
+
+	pCHANNEL_HEADER chan;
+	/* channel containing queues in which scsi commands &
+	 * responses are queued
+	 */
+	U64 packets_sent;
+	U64 packets_received;
+	U64 interrupts_sent;
+	U64 interrupts_received;
+	U64 max_not_empty_cnt;
+	U64 total_wakeup_cnt;
+	U64 non_empty_wakeup_cnt;
+
+	struct {
+		SIGNAL_QUEUE_HEADER Reserved1;	/*  */
+		SIGNAL_QUEUE_HEADER Reserved2;	/*  */
+	} safe_uis_queue;
+	unsigned int (*send_int_if_needed)(struct uisqueue_info *info,
+					   unsigned int whichcqueue,
+					   unsigned char issueInterruptIfEmpty,
+					   U64 interruptHandle,
+					   unsigned char io_termination);
+};
+
+/* uisqueue_put_cmdrsp_with_lock_client queues a commmand or response
+ * to the specified queue, at the tail if the queue is full but
+ * oktowait == 0, then it return 0 indicating failure.  otherwise it
+ * wait for the queue to become non-full. If command is queued, return
+ * 1 for success.
+ */
+#define DONT_ISSUE_INTERRUPT 0
+#define ISSUE_INTERRUPT		 1
+
+#define DONT_WAIT			 0
+#define OK_TO_WAIT			 1
+#define UISLIB_LOCK_PREFIX \
+		".section .smp_locks,\"a\"\n"   \
+		_ASM_ALIGN "\n"                 \
+		_ASM_PTR "661f\n" /* address */ \
+		".previous\n"                   \
+		"661:\n\tlock; "
+
+unsigned long long uisqueue_InterlockedOr(volatile unsigned long long *Target,
+					  unsigned long long Set);
+unsigned long long uisqueue_InterlockedAnd(volatile unsigned long long *Target,
+					   unsigned long long Set);
+
+unsigned int uisqueue_send_int_if_needed(struct uisqueue_info *pqueueinfo,
+					 unsigned int whichqueue,
+					 unsigned char issueInterruptIfEmpty,
+					 U64 interruptHandle,
+					 unsigned char io_termination);
+
+int uisqueue_put_cmdrsp_with_lock_client(struct uisqueue_info *queueinfo,
+					 struct uiscmdrsp *cmdrsp,
+					 unsigned int queue,
+					 void *insertlock,
+					 unsigned char issueInterruptIfEmpty,
+					 U64 interruptHandle,
+					 char oktowait,
+					 U8 *channelId);
+
+/* uisqueue_get_cmdrsp gets the cmdrsp entry at the head of the queue
+ * and copies it to the area pointed by cmdrsp param.
+ * returns 0 if queue is empty, 1 otherwise
+ */
+int
+
+uisqueue_get_cmdrsp(struct uisqueue_info *queueinfo, void *cmdrsp,
+		    unsigned int queue);
+
+#define MAX_NAME_SIZE_UISQUEUE 64
+
+struct extport_info {
+	U8 valid:1;
+	/* if 1, indicates this extport slot is occupied
+	 * if 0, indicates that extport slot is unoccupied */
+
+	U32 num_devs_using;
+	/* When extport is added, this is set to 0.  For exports
+	* located in NETWORK switches:
+	* Each time a VNIC, i.e., intport, is added to the switch this
+	* is used to assign a pref_pnic for the VNIC and when assigned
+	* to a VNIC this counter is incremented. When a VNIC is
+	* deleted, the extport corresponding to the VNIC's pref_pnic
+	* is located and its num_devs_using is decremented. For VNICs,
+	* num_devs_using is basically used to load-balance transmit
+	* traffic from VNICs.
+	*/
+
+	struct switch_info *swtch;
+	struct PciId pci_id;
+	char name[MAX_NAME_SIZE_UISQUEUE];
+	union {
+		struct vhba_wwnn wwnn;
+		unsigned char macaddr[MAX_MACADDR_LEN];
+	};
+};
+
+struct device_info {
+	void *chanptr;
+	U64 channelAddr;
+	U64 channelBytes;
+	GUID channelTypeGuid;
+	GUID devInstGuid;
+	struct InterruptInfo intr;
+	struct switch_info *swtch;
+	char devid[30];		/* "vbus<busno>:dev<devno>" */
+	U16 polling;
+	struct semaphore interrupt_callback_lock;
+	U32 busNo;
+	U32 devNo;
+	int (*interrupt)(void *);
+	void *interrupt_context;
+	void *private_data;
+	struct list_head list_polling_device_channels;
+	unsigned long long moved_to_tail_cnt;
+	unsigned long long first_busy_cnt;
+	unsigned long long last_on_list_cnt;
+};
+
+typedef enum {
+	RECOVERY_LAN = 1,
+	IB_LAN = 2
+} SWITCH_TYPE;
+
+struct bus_info {
+	U32 busNo, deviceCount;
+	struct device_info **device;
+	U64 guestHandle, recvBusInterruptHandle;
+	GUID busInstGuid;
+	ULTRA_VBUS_CHANNEL_PROTOCOL *pBusChannel;
+	int busChannelBytes;
+	struct proc_dir_entry *proc_dir;	/* proc/uislib/vbus/<x> */
+	struct proc_dir_entry *proc_info;	/* proc/uislib/vbus/<x>/info */
+	char name[25];
+	char partitionName[99];
+	struct bus_info *next;
+	U8 localVnic;		/* 1 if local vnic created internally
+				 * by IOVM; 0 otherwise... */
+};
+
+#define DEDICATED_SWITCH(pSwitch) ((pSwitch->extPortCount == 1) &&	\
+				   (pSwitch->intPortCount == 1))
+
+struct sn_list_entry {
+	struct uisscsi_dest pdest;	/* scsi bus, target, lun for
+					 * phys disk */
+	U8 sernum[MAX_SERIAL_NUM];	/* serial num of physical
+					 * disk.. The length is always
+					 * MAX_SERIAL_NUM, padded with
+					 * spaces */
+	struct sn_list_entry *next;
+};
+
+struct networkPolicy {
+	U32 promiscuous:1;
+	U32 macassign:1;
+	U32 peerforwarding:1;
+	U32 nonotify:1;
+	U32 standby:1;
+	U32 callhome:2;
+	char ip_addr[30];
+};
+
+/*
+ * IO messages sent to UisnicControlChanFunc & UissdControlChanFunc by
+ * code that processes the ControlVm channel messages.
+ */
+
+
+typedef enum {
+	IOPART_ADD_VNIC,
+	IOPART_DEL_VNIC,
+	IOPART_DEL_ALL_VNICS,
+	IOPART_ADD_VHBA,
+	IOPART_ADD_VDISK,
+	IOPART_DEL_VHBA,
+	IOPART_DEL_VDISK,
+	IOPART_DEL_ALL_VDISKS_FOR_VHBA,
+	IOPART_DEL_ALL_VHBAS,
+	IOPART_ATTACH_PHBA,
+	IOPART_DETACH_PHBA,	/* 10 */
+	IOPART_ATTACH_PNIC,
+	IOPART_DETACH_PNIC,
+	IOPART_DETACH_VHBA,
+	IOPART_DETACH_VNIC,
+	IOPART_PAUSE_VDISK,
+	IOPART_RESUME_VDISK,
+	IOPART_ADD_DEVICE,	/* add generic device */
+	IOPART_DEL_DEVICE,	/* del generic device */
+} IOPART_MSG_TYPE;
+
+struct add_virt_iopart {
+	void *chanptr;		/* pointer to data channel */
+	U64 guestHandle;	/* used to convert guest physical
+				 * address to real physical address
+				 * for DMA, for ex. */
+	U64 recvBusInterruptHandle;	/* used to register to receive
+					 * bus level interrupts. */
+	struct InterruptInfo intr;	/* contains recv & send
+					 * interrupt info */
+	/* recvInterruptHandle is used to register to receive
+	* interrupts on the data channel. Used by GuestLinux/Windows
+	* IO drivers to connect to interrupt.  sendInterruptHandle is
+	* used by IOPart drivers as parameter to
+	* Issue_VMCALL_IO_QUEUE_TRANSITION to interrupt thread in
+	* guest linux/windows IO drivers when data channel queue for
+	* vhba/vnic goes from EMPTY to NON-EMPTY. */
+	struct switch_info *swtch;	/* pointer to the virtual
+					 * switch to which the vnic is
+					 * connected */
+
+	U8 useG2GCopy;		/* Used to determine if a virtual HBA
+				 * needs to use G2G copy. */
+	U8 Filler[7];
+
+	U32 busNo;
+	U32 devNo;
+	char *params;
+	ulong params_bytes;
+
+};
+
+struct add_vdisk_iopart {
+	void *chanptr;		      /* pointer to data channel */
+	int implicit;
+	struct uisscsi_dest vdest;    /* scsi bus, target, lun for virt disk */
+	struct uisscsi_dest pdest;    /* scsi bus, target, lun for phys disk */
+	U8 sernum[MAX_SERIAL_NUM];    /* serial num of physical disk */
+	U32 serlen;		      /* length of serial num */
+	U32 busNo;
+	U32 devNo;
+};
+
+struct del_vdisk_iopart {
+	void *chanptr;		     /* pointer to data channel */
+	struct uisscsi_dest vdest;   /* scsi bus, target, lun for virt disk */
+	U32 busNo;
+	U32 devNo;
+};
+
+struct del_virt_iopart {
+	void *chanptr;		     /* pointer to data channel */
+	U32 busNo;
+	U32 devNo;
+};
+
+struct det_virt_iopart {	     /* detach internal port */
+	void *chanptr;		     /* pointer to data channel */
+	struct switch_info *swtch;
+};
+
+struct paures_vdisk_iopart {
+	void *chanptr;		     /* pointer to data channel */
+	struct uisscsi_dest vdest;   /* scsi bus, target, lun for virt disk */
+};
+
+struct add_switch_iopart {	     /* add switch */
+	struct switch_info *swtch;
+	char *params;
+	ulong params_bytes;
+};
+
+struct del_switch_iopart {	     /* destroy switch */
+	struct switch_info *swtch;
+};
+
+struct io_msgs {
+
+	IOPART_MSG_TYPE msgtype;
+
+	/* additional params needed by some messages */
+	union {
+		struct add_virt_iopart add_vhba;
+		struct add_virt_iopart add_vnic;
+		struct add_vdisk_iopart add_vdisk;
+		struct del_virt_iopart del_vhba;
+		struct del_virt_iopart del_vnic;
+		struct det_virt_iopart det_vhba;
+		struct det_virt_iopart det_vnic;
+		struct del_vdisk_iopart del_vdisk;
+		struct del_virt_iopart del_all_vdisks_for_vhba;
+		struct add_virt_iopart add_device;
+		struct del_virt_iopart del_device;
+		struct det_virt_iopart det_intport;
+		struct add_switch_iopart add_switch;
+		struct del_switch_iopart del_switch;
+		struct extport_info *extPort;	/* for attach or detach
+						 * pnic/generic delete all
+						 * vhbas/allvnics need no
+						 * parameters */
+		struct paures_vdisk_iopart paures_vdisk;
+	};
+};
+
+/*
+* Guest messages sent to VirtControlChanFunc by code that processes
+* the ControlVm channel messages.
+*/
+
+typedef enum {
+	GUEST_ADD_VBUS,
+	GUEST_ADD_VHBA,
+	GUEST_ADD_VNIC,
+	GUEST_DEL_VBUS,
+	GUEST_DEL_VHBA,
+	GUEST_DEL_VNIC,
+	GUEST_DEL_ALL_VHBAS,
+	GUEST_DEL_ALL_VNICS,
+	GUEST_DEL_ALL_VBUSES,	/* deletes all vhbas & vnics on all
+				 * buses and deletes all buses */
+	GUEST_PAUSE_VHBA,
+	GUEST_PAUSE_VNIC,
+	GUEST_RESUME_VHBA,
+	GUEST_RESUME_VNIC
+} GUESTPART_MSG_TYPE;
+
+struct add_vbus_guestpart {
+	void *chanptr;		/* pointer to data channel for bus -
+				 * NOT YET USED */
+	U32 busNo;		/* bus number to be created/deleted */
+	U32 deviceCount;	/* max num of devices on bus */
+	GUID busTypeGuid;	/* indicates type of bus */
+	GUID busInstGuid;	/* instance guid for device */
+};
+
+struct del_vbus_guestpart {
+	U32 busNo;		/* bus number to be deleted */
+	/* once we start using the bus's channel, add can dump busNo
+	* into the channel header and then delete will need only one
+	* parameter, chanptr. */
+};
+
+struct add_virt_guestpart {
+	void *chanptr;		/* pointer to data channel */
+	U32 busNo;		/* bus number for the operation */
+	U32 deviceNo;		/* number of device on the bus */
+	GUID devInstGuid;	/* instance guid for device */
+	struct InterruptInfo intr;	/* recv/send interrupt info */
+	/* recvInterruptHandle contains info needed in order to
+	 * register to receive interrupts on the data channel.
+	 * sendInterruptHandle contains handle which is provided to
+	 * monitor VMCALL that will cause an interrupt to be generated
+	 * for the other end.
+	 */
+};
+
+struct pause_virt_guestpart {
+	void *chanptr;		/* pointer to data channel */
+};
+
+struct resume_virt_guestpart {
+	void *chanptr;		/* pointer to data channel */
+};
+
+struct del_virt_guestpart {
+	void *chanptr;		/* pointer to data channel */
+};
+
+struct init_chipset_guestpart {
+	U32 busCount;		/* indicates the max number of busses */
+	U32 switchCount;	/* indicates the max number of switches */
+};
+
+struct guest_msgs {
+
+	GUESTPART_MSG_TYPE msgtype;
+
+	/* additional params needed by messages */
+	union {
+		struct add_vbus_guestpart add_vbus;
+		struct add_virt_guestpart add_vhba;
+		struct add_virt_guestpart add_vnic;
+		struct pause_virt_guestpart pause_vhba;
+		struct pause_virt_guestpart pause_vnic;
+		struct resume_virt_guestpart resume_vhba;
+		struct resume_virt_guestpart resume_vnic;
+		struct del_vbus_guestpart del_vbus;
+		struct del_virt_guestpart del_vhba;
+		struct del_virt_guestpart del_vnic;
+		struct del_vbus_guestpart del_all_vhbas;
+		struct del_vbus_guestpart del_all_vnics;
+		/* del_all_vbuses needs no parameters */
+	};
+	struct init_chipset_guestpart init_chipset;
+
+};
+
+#ifndef __xg
+#define __xg(x) ((volatile long *)(x))
+#endif
+
+/*
+*  Below code is a copy of Linux kernel's cmpxchg function located at
+*  this place
+*  http://tcsxeon:8080/source/xref/00trunk-AppOS-linux/include/asm-x86/cmpxchg_64.h#84
+*  Reason for creating our own version of cmpxchg along with
+*  UISLIB_LOCK_PREFIX is to make the operation atomic even for non SMP
+*  guests.
+*/
+
+static inline unsigned long
+uislibcmpxchg64(volatile void *ptr, unsigned long old, unsigned long new,
+		int size)
+{
+	unsigned long prev;
+	switch (size) {
+	case 1:
+	      __asm__ __volatile__(UISLIB_LOCK_PREFIX "cmpxchgb %b1,%2":"=a"(prev)
+	      :		     "q"(new), "m"(*__xg(ptr)),
+				     "0"(old)
+	      :		     "memory");
+		return prev;
+	case 2:
+	      __asm__ __volatile__(UISLIB_LOCK_PREFIX "cmpxchgw %w1,%2":"=a"(prev)
+	      :		     "r"(new), "m"(*__xg(ptr)),
+				     "0"(old)
+	      :		     "memory");
+		return prev;
+	case 4:
+	      __asm__ __volatile__(UISLIB_LOCK_PREFIX "cmpxchgl %k1,%2":"=a"(prev)
+	      :		     "r"(new), "m"(*__xg(ptr)),
+				     "0"(old)
+	      :		     "memory");
+		return prev;
+	case 8:
+	      __asm__ __volatile__(UISLIB_LOCK_PREFIX "cmpxchgq %1,%2":"=a"(prev)
+	      :		     "r"(new), "m"(*__xg(ptr)),
+				     "0"(old)
+	      :		     "memory");
+		return prev;
+	}
+	return old;
+}
+
+#endif				/* __UISQUEUE_H__ */
diff --git a/drivers/staging/unisys/include/uisthread.h b/drivers/staging/unisys/include/uisthread.h
new file mode 100644
index 0000000..2b1fba7
--- /dev/null
+++ b/drivers/staging/unisys/include/uisthread.h
@@ -0,0 +1,46 @@
+/* uisthread.h
+ *
+ * Copyright © 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+/*****************************************************************************/
+/* Unisys thread utilities header                                            */
+/*****************************************************************************/
+
+
+#ifndef __UISTHREAD_H__
+#define __UISTHREAD_H__
+
+
+#include "linux/completion.h"
+
+struct uisthread_info {
+	struct task_struct *task;
+	int id;
+	int should_stop;
+	struct completion has_stopped;
+};
+
+
+/* returns 0 for failure, 1 for success */
+int uisthread_start(
+	struct uisthread_info *thrinfo,
+	int (*threadfn)(void *),
+	void *thrcontext,
+	char *name);
+
+void uisthread_stop(struct uisthread_info *thrinfo);
+
+#endif /* __UISTHREAD_H__ */
diff --git a/drivers/staging/unisys/include/uisutils.h b/drivers/staging/unisys/include/uisutils.h
new file mode 100644
index 0000000..9fee353
--- /dev/null
+++ b/drivers/staging/unisys/include/uisutils.h
@@ -0,0 +1,359 @@
+/* uisutils.h
+ *
+ * Copyright © 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+/*
+ * Unisys Virtual HBA utilities header
+ */
+
+#ifndef __UISUTILS__H__
+#define __UISUTILS__H__
+#include <linux/string.h>
+#include <linux/io.h>
+#include <linux/sched.h>
+#include <linux/gfp.h>
+
+#include "vmcallinterface.h"
+#include "channel.h"
+#include "uisthread.h"
+#include "uisqueue.h"
+#include "diagnostics/appos_subsystems.h"
+#include "vbusdeviceinfo.h"
+#include <linux/atomic.h>
+
+/* This is the MAGIC number stuffed by virthba in host->this_id. Used to
+ * identify virtual hbas.
+ */
+#define UIS_MAGIC_VHBA 707
+
+/* global function pointers that act as callback functions into
+ * uisnicmod, uissdmod, and virtpcimod
+ */
+extern int (*UisnicControlChanFunc)(struct io_msgs *);
+extern int (*UissdControlChanFunc)(struct io_msgs *);
+extern int (*VirtControlChanFunc)(struct guest_msgs *);
+
+/* Return values of above callback functions: */
+#define CCF_ERROR        0	/* completed and failed */
+#define CCF_OK           1	/* completed successfully */
+#define CCF_PENDING      2	/* operation still pending */
+extern atomic_t UisUtils_Registered_Services;
+
+typedef unsigned int MACARRAY[MAX_MACADDR_LEN];
+typedef struct ReqHandlerInfo_struct {
+	GUID switchTypeGuid;
+	int (*controlfunc)(struct io_msgs *);
+	unsigned long min_channel_bytes;
+	int (*Server_Channel_Ok)(unsigned long channelBytes);
+	int (*Server_Channel_Init)
+	 (void *x, unsigned char *clientStr, U32 clientStrLen, U64 bytes);
+	char switch_type_name[99];
+	struct list_head list_link;	/* links into ReqHandlerInfo_list */
+} ReqHandlerInfo_t;
+
+ReqHandlerInfo_t *ReqHandlerAdd(GUID switchTypeGuid,
+				const char *switch_type_name,
+				int (*controlfunc)(struct io_msgs *),
+				unsigned long min_channel_bytes,
+				int (*Server_Channel_Ok)(unsigned long
+							 channelBytes),
+				int (*Server_Channel_Init)
+				 (void *x, unsigned char *clientStr,
+				  U32 clientStrLen, U64 bytes));
+ReqHandlerInfo_t *ReqHandlerFind(GUID switchTypeGuid);
+int ReqHandlerDel(GUID switchTypeGuid);
+
+#define uislib_ioremap_cache(addr, size) \
+	dbg_ioremap_cache(addr, size, __FILE__, __LINE__)
+
+static inline void *
+dbg_ioremap_cache(U64 addr, unsigned long size, char *file, int line)
+{
+	void *new;
+	new = ioremap_cache(addr, size);
+	return new;
+}
+
+#define uislib_ioremap(addr, size) dbg_ioremap(addr, size, __FILE__, __LINE__)
+
+static inline void *
+dbg_ioremap(U64 addr, unsigned long size, char *file, int line)
+{
+	void *new;
+	new = ioremap(addr, size);
+	return new;
+}
+
+#define uislib_iounmap(addr) dbg_iounmap(addr, __FILE__, __LINE__)
+
+static inline void
+dbg_iounmap(void *addr, char *file, int line)
+{
+	iounmap(addr);
+}
+
+#define PROC_READ_BUFFER_SIZE 131072	/* size of the buffer to allocate to
+					 * hold all of /proc/XXX/info */
+int util_add_proc_line_ex(int *total, char **buffer, int *buffer_remaining,
+			  char *format, ...);
+
+int uisctrl_register_req_handler(int type, void *fptr,
+				 ULTRA_VBUS_DEVICEINFO *chipset_DriverInfo);
+int uisctrl_register_req_handler_ex(GUID switchTypeGuid,
+				    const char *switch_type_name,
+				    int (*fptr)(struct io_msgs *),
+				    unsigned long min_channel_bytes,
+				    int (*Server_Channel_Ok)(unsigned long
+							     channelBytes),
+				    int (*Server_Channel_Init)
+				    (void *x, unsigned char *clientStr,
+				     U32 clientStrLen, U64 bytes),
+				    ULTRA_VBUS_DEVICEINFO *chipset_DriverInfo);
+
+int uisctrl_unregister_req_handler_ex(GUID switchTypeGuid);
+unsigned char *util_map_virt(struct phys_info *sg);
+void util_unmap_virt(struct phys_info *sg);
+unsigned char *util_map_virt_atomic(struct phys_info *sg);
+void util_unmap_virt_atomic(void *buf);
+int uislib_server_inject_add_vnic(U32 switchNo, U32 BusNo, U32 numIntPorts,
+				  U32 numExtPorts, MACARRAY pmac[],
+				  pCHANNEL_HEADER **chan);
+void uislib_server_inject_del_vnic(U32 switchNo, U32 busNo, U32 numIntPorts,
+				   U32 numExtPorts);
+int uislib_client_inject_add_bus(U32 busNo, GUID instGuid,
+				 U64 channelAddr, ulong nChannelBytes);
+int  uislib_client_inject_del_bus(U32 busNo);
+
+int uislib_client_inject_add_vhba(U32 busNo, U32 devNo,
+				  U64 phys_chan_addr, U32 chan_bytes,
+				  int is_test_addr, GUID instGuid,
+				  struct InterruptInfo *intr);
+int  uislib_client_inject_pause_vhba(U32 busNo, U32 devNo);
+int  uislib_client_inject_resume_vhba(U32 busNo, U32 devNo);
+int uislib_client_inject_del_vhba(U32 busNo, U32 devNo);
+int uislib_client_inject_add_vnic(U32 busNo, U32 devNo,
+				  U64 phys_chan_addr, U32 chan_bytes,
+				  int is_test_addr, GUID instGuid,
+				  struct InterruptInfo *intr);
+int uislib_client_inject_pause_vnic(U32 busNo, U32 devNo);
+int uislib_client_inject_resume_vnic(U32 busNo, U32 devNo);
+int uislib_client_inject_del_vnic(U32 busNo, U32 devNo);
+#ifdef STORAGE_CHANNEL
+U64 uislib_storage_channel(int client_id);
+#endif
+int uislib_get_owned_pdest(struct uisscsi_dest *pdest);
+
+int uislib_send_event(CONTROLVM_ID id, CONTROLVM_MESSAGE_PACKET *event);
+
+/* structure used by vhba & vnic to keep track of queue & thread info */
+struct chaninfo {
+	struct uisqueue_info *queueinfo;
+	/* this specifies the queue structures for a channel */
+	/* ALLOCATED BY THE OTHER END - WE JUST GET A POINTER TO THE MEMORY */
+	spinlock_t insertlock;
+	/* currently used only in virtnic when sending data to uisnic */
+	/* to synchronize the inserts into the signal queue */
+	struct uisthread_info threadinfo;
+	/* this specifies the thread structures used by the thread that */
+	/* handles this channel */
+};
+
+/* this is the wait code for all the threads - it is used to get
+* something from a queue choices: wait_for_completion_interruptible,
+* _timeout, interruptible_timeout
+*/
+#define UIS_THREAD_WAIT_MSEC(x) { \
+	set_current_state(TASK_INTERRUPTIBLE); \
+	schedule_timeout(msecs_to_jiffies(x)); \
+}
+#define UIS_THREAD_WAIT_USEC(x) { \
+	set_current_state(TASK_INTERRUPTIBLE); \
+	schedule_timeout(usecs_to_jiffies(x)); \
+}
+#define UIS_THREAD_WAIT UIS_THREAD_WAIT_MSEC(5)
+#define UIS_THREAD_WAIT_SEC(x) { \
+	set_current_state(TASK_INTERRUPTIBLE); \
+	schedule_timeout((x)*HZ); \
+}
+
+#define ALLOC_CMDRSP(cmdrsp) { \
+	cmdrsp = kmalloc(SIZEOF_CMDRSP, GFP_ATOMIC); \
+	if (cmdrsp != NULL) { \
+		memset(cmdrsp, 0, SIZEOF_CMDRSP); \
+	} \
+}
+
+/* This is a hack until we fix IOVM to initialize the channel header
+ * correctly at DEVICE_CREATE time, INSTEAD OF waiting until
+ * DEVICE_CONFIGURE time.
+ */
+#define WAIT_FOR_VALID_GUID(guid) \
+	do {						   \
+		while (memcmp(&guid, &Guid0, sizeof(Guid0)) == 0) {	\
+			LOGERR("Waiting for non-0 GUID (why???)...\n"); \
+			UIS_THREAD_WAIT_SEC(5);				\
+		}							\
+		LOGERR("OK... GUID is non-0 now\n");			\
+	} while (0)
+
+/* CopyFragsInfoFromSkb returns the number of entries added to frags array
+ * Returns -1 on failure.
+ */
+unsigned int util_copy_fragsinfo_from_skb(unsigned char *calling_ctx,
+			      void *skb_in, unsigned int firstfraglen,
+			      unsigned int frags_max, struct phys_info frags[]);
+
+static inline unsigned int
+Issue_VMCALL_IO_CONTROLVM_ADDR(U64 *ControlAddress, U32 *ControlBytes)
+{
+	VMCALL_IO_CONTROLVM_ADDR_PARAMS params;
+	int result = VMCALL_SUCCESS;
+	U64 physaddr;
+
+	physaddr = virt_to_phys(&params);
+	ISSUE_IO_VMCALL(VMCALL_IO_CONTROLVM_ADDR, physaddr, result);
+	if (VMCALL_SUCCESSFUL(result)) {
+		*ControlAddress = params.ChannelAddress;
+		*ControlBytes = params.ChannelBytes;
+	}
+	return result;
+}
+
+static inline unsigned int Issue_VMCALL_IO_DIAG_ADDR(U64 *DiagChannelAddress)
+{
+	VMCALL_IO_DIAG_ADDR_PARAMS params;
+	int result = VMCALL_SUCCESS;
+	U64 physaddr;
+
+	physaddr = virt_to_phys(&params);
+	ISSUE_IO_VMCALL(VMCALL_IO_DIAG_ADDR, physaddr, result);
+	if (VMCALL_SUCCESSFUL(result))
+		*DiagChannelAddress = params.ChannelAddress;
+	return result;
+}
+
+static inline unsigned int
+Issue_VMCALL_IO_VISORSERIAL_ADDR(U64 *DiagChannelAddress)
+{
+	VMCALL_IO_VISORSERIAL_ADDR_PARAMS params;
+	int result = VMCALL_SUCCESS;
+	U64 physaddr;
+
+	physaddr = virt_to_phys(&params);
+	ISSUE_IO_VMCALL(VMCALL_IO_VISORSERIAL_ADDR, physaddr, result);
+	if (VMCALL_SUCCESSFUL(result))
+		*DiagChannelAddress = params.ChannelAddress;
+	return result;
+}
+
+static inline S64 Issue_VMCALL_QUERY_GUEST_VIRTUAL_TIME_OFFSET(void)
+{
+	U64 result = VMCALL_SUCCESS;
+	U64 physaddr = 0;
+
+	ISSUE_IO_VMCALL(VMCALL_QUERY_GUEST_VIRTUAL_TIME_OFFSET, physaddr,
+			result);
+	return result;
+}
+
+static inline S64 Issue_VMCALL_MEASUREMENT_DO_NOTHING(void)
+{
+	U64 result = VMCALL_SUCCESS;
+	U64 physaddr = 0;
+
+	ISSUE_IO_VMCALL(VMCALL_MEASUREMENT_DO_NOTHING, physaddr, result);
+	return result;
+}
+
+struct log_info_t {
+	volatile unsigned long long last_cycles;
+	unsigned long long delta_sum[64];
+	unsigned long long delta_cnt[64];
+	unsigned long long max_delta[64];
+	unsigned long long min_delta[64];
+};
+
+static inline int Issue_VMCALL_UPDATE_PHYSICAL_TIME(U64 adjustment)
+{
+	int result = VMCALL_SUCCESS;
+
+	ISSUE_IO_VMCALL(VMCALL_UPDATE_PHYSICAL_TIME, adjustment, result);
+	return result;
+}
+
+static inline unsigned int
+Issue_VMCALL_CHANNEL_MISMATCH(const char *ChannelName,
+			      const char *ItemName,
+			      U32 SourceLineNumber, const char *path_n_fn)
+{
+	VMCALL_CHANNEL_VERSION_MISMATCH_PARAMS params;
+	int result = VMCALL_SUCCESS;
+	U64 physaddr;
+	char *last_slash = NULL;
+
+	strncpy(params.ChannelName, ChannelName,
+		lengthof(VMCALL_CHANNEL_VERSION_MISMATCH_PARAMS, ChannelName));
+	strncpy(params.ItemName, ItemName,
+		lengthof(VMCALL_CHANNEL_VERSION_MISMATCH_PARAMS, ItemName));
+	params.SourceLineNumber = SourceLineNumber;
+
+	last_slash = strrchr(path_n_fn, '/');
+	if (last_slash != NULL) {
+		last_slash++;
+		strncpy(params.SourceFileName, last_slash,
+			lengthof(VMCALL_CHANNEL_VERSION_MISMATCH_PARAMS,
+				 SourceFileName));
+	} else
+		strncpy(params.SourceFileName,
+			"Cannot determine source filename",
+			lengthof(VMCALL_CHANNEL_VERSION_MISMATCH_PARAMS,
+				 SourceFileName));
+
+	physaddr = virt_to_phys(&params);
+	ISSUE_IO_VMCALL(VMCALL_CHANNEL_VERSION_MISMATCH, physaddr, result);
+	return result;
+}
+
+static inline unsigned int Issue_VMCALL_FATAL_BYE_BYE(void)
+{
+	int result = VMCALL_SUCCESS;
+	U64 physaddr = 0;
+
+	ISSUE_IO_VMCALL(VMCALL_GENERIC_SURRENDER_QUANTUM_FOREVER, physaddr,
+			result);
+	return result;
+}
+
+#define UIS_DAEMONIZE(nam)
+void *uislib_malloc(size_t siz, gfp_t gfp, U8 contiguous, char *fn, int ln);
+#define UISMALLOC(siz, gfp) uislib_malloc(siz, gfp, 1, __FILE__, __LINE__)
+#define UISVMALLOC(siz) uislib_malloc(siz, 0, 0, __FILE__, __LINE__)
+void uislib_free(void *p, size_t siz, U8 contiguous, char *fn, int ln);
+#define UISFREE(p, siz) uislib_free(p, siz, 1, __FILE__, __LINE__)
+#define UISVFREE(p, siz) uislib_free(p, siz, 0, __FILE__, __LINE__)
+void *uislib_cache_alloc(struct kmem_cache *cur_pool, char *fn, int ln);
+#define UISCACHEALLOC(cur_pool) uislib_cache_alloc(cur_pool, __FILE__, __LINE__)
+void uislib_cache_free(struct kmem_cache *cur_pool, void *p, char *fn, int ln);
+#define UISCACHEFREE(cur_pool, p) \
+	uislib_cache_free(cur_pool, p, __FILE__, __LINE__)
+
+void uislib_enable_channel_interrupts(U32 busNo, U32 devNo,
+				      int (*interrupt)(void *),
+				      void *interrupt_context);
+void uislib_disable_channel_interrupts(U32 busNo, U32 devNo);
+void uislib_force_channel_interrupt(U32 busNo, U32 devNo);
+
+#endif /* __UISUTILS__H__ */
diff --git a/drivers/staging/unisys/include/uniklog.h b/drivers/staging/unisys/include/uniklog.h
new file mode 100644
index 0000000..4d7b87c
--- /dev/null
+++ b/drivers/staging/unisys/include/uniklog.h
@@ -0,0 +1,193 @@
+/* uniklog.h
+ *
+ * Copyright © 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+/* This module contains macros to aid developers in logging messages.
+ *
+ * This module is affected by the DEBUG compiletime option.
+ *
+ */
+#ifndef __UNIKLOG_H__
+#define __UNIKLOG_H__
+
+
+#include <linux/printk.h>
+
+/*
+ * # DBGINF
+ *
+ * \brief Log debug informational message - log a LOG_INFO message only
+ *        if DEBUG compiletime option enabled
+ *
+ * \param devname the device name of the device reporting this message, or
+ *                NULL if this message is NOT device-related.
+ * \param fmt printf()-style format string containing the message to log.
+ * \param args Optional arguments to be formatted and inserted into the
+ *             format string.
+ * \return nothing
+ *
+ * Log a message at the LOG_INFO level, but only if DEBUG is enabled.  If
+ * DEBUG is disabled, this expands to a no-op.
+ */
+
+/*
+ * # DBGVER
+ *
+ * \brief Log debug verbose message - log a LOG_DEBUG message only if
+ *        DEBUG compiletime option enabled
+ *
+ * \param devname the device name of the device reporting this message, or
+ *                NULL if this message is NOT device-related.
+ * \param fmt printf()-style format string containing the message to log.
+ * \param args Optional arguments to be formatted and inserted into the
+ *             format string.
+ * \return nothing
+ *
+ * Log a message at the LOG_DEBUG level, but only if DEBUG is enabled.  If
+ * DEBUG is disabled, this expands to a no-op.  Note also that LOG_DEBUG
+ * messages can be enabled/disabled at runtime as well.
+ */
+#define DBGINFDEV(devname, fmt, args...)        do { } while (0)
+#define DBGVERDEV(devname, fmt, args...)        do { } while (0)
+#define DBGINF(fmt, args...)                    do { } while (0)
+#define DBGVER(fmt, args...)                    do { } while (0)
+
+/*
+ * # LOGINF
+ *
+ * \brief Log informational message - logs a message at the LOG_INFO level
+ *
+ * \param devname the device name of the device reporting this message, or
+ *                NULL if this message is NOT device-related.
+ * \param fmt printf()-style format string containing the message to log.
+ * \param args Optional arguments to be formatted and inserted into the
+ *             format string.
+ * \return nothing
+ *
+ * Logs the specified message at the LOG_INFO level.
+ */
+
+#define LOGINF(fmt, args...) pr_info(fmt, ## args)
+#define LOGINFDEV(devname, fmt, args...) \
+	pr_info("%s " fmt, devname, ## args)
+#define LOGINFDEVX(devno, fmt, args...) \
+	pr_info("dev%d " fmt, devno, ## args)
+#define LOGINFNAME(vnic, fmt, args...)				\
+	do {								\
+		if (vnic != NULL) {					\
+			pr_info("%s " fmt, vnic->name, ## args);	\
+		} else {						\
+			pr_info(fmt, ## args);				\
+		}							\
+	} while (0)
+
+/*
+ * # LOGVER
+ *
+ * \brief Log verbose message - logs a message at the LOG_DEBUG level,
+ *        which can be disabled at runtime
+ *
+ * \param devname the device name of the device reporting this message, or
+ *                NULL if this message is NOT device-related.
+ * \param fmt printf()-style format string containing the message to log.
+ * \param args Optional arguments to be formatted and inserted into the format
+ * \param string.
+ * \return nothing
+ *
+ * Logs the specified message at the LOG_DEBUG level.  Note also that
+ * LOG_DEBUG messages can be enabled/disabled at runtime as well.
+ */
+#define LOGVER(fmt, args...) pr_debug(fmt, ## args)
+#define LOGVERDEV(devname, fmt, args...) \
+	pr_debug("%s " fmt, devname, ## args)
+#define LOGVERNAME(vnic, fmt, args...)					\
+	do {								\
+		if (vnic != NULL) {					\
+			pr_debug("%s " fmt, vnic->name, ## args);	\
+		} else {						\
+			pr_debug(fmt, ## args);				\
+		}							\
+	} while (0)
+
+
+/*
+ * # LOGERR
+ *
+ * \brief Log error message - logs a message at the LOG_ERR level,
+ *        including source line number information
+ *
+ * \param devname the device name of the device reporting this message, or
+ *                NULL if this message is NOT device-related.
+ * \param fmt printf()-style format string containing the message to log.
+ * \param args Optional arguments to be formatted and inserted into the format
+ * \param string.
+ * \return nothing
+ *
+ * Logs the specified error message at the LOG_ERR level.  It will also
+ * include the file, line number, and function name of where the error
+ * originated in the log message.
+ */
+#define LOGERR(fmt, args...) pr_err(fmt, ## args)
+#define LOGERRDEV(devname, fmt, args...) \
+	pr_err("%s " fmt, devname, ## args)
+#define LOGERRDEVX(devno, fmt, args...) \
+	pr_err("dev%d " fmt, devno, ## args)
+#define LOGERRNAME(vnic, fmt, args...)				\
+	do {								\
+		if (vnic != NULL) {					\
+			pr_err("%s " fmt, vnic->name, ## args);	\
+		} else {						\
+			pr_err(fmt, ## args);				\
+		}							\
+	} while (0)
+#define LOGORDUMPERR(seqfile, fmt, args...) do {		\
+		if (seqfile) {					\
+			seq_printf(seqfile, fmt, ## args);	\
+		} else {					\
+			LOGERR(fmt, ## args);			\
+		}						\
+	} while (0)
+
+/*
+ * # LOGWRN
+ *
+ * \brief Log warning message - Logs a message at the LOG_WARNING level,
+ *        including source line number information
+ *
+ * \param devname the device name of the device reporting this message, or
+ *                NULL if this message is NOT device-related.
+ * \param fmt printf()-style format string containing the message to log.
+ * \param args Optional arguments to be formatted and inserted into the format
+ * \param string.
+ * \return nothing
+ *
+ * Logs the specified error message at the LOG_WARNING level.  It will also
+ * include the file, line number, and function name of where the error
+ * originated in the log message.
+ */
+#define LOGWRN(fmt, args...) pr_warn(fmt, ## args)
+#define LOGWRNDEV(devname, fmt, args...) \
+	pr_warn("%s " fmt, devname, ## args)
+#define LOGWRNNAME(vnic, fmt, args...) \
+	do {								\
+		if (vnic != NULL) {					\
+			pr_warn("%s " fmt, vnic->name, ## args);	\
+		} else {						\
+			pr_warn(fmt, ## args);				\
+		}							\
+	} while (0)
+
+#endif /* __UNIKLOG_H__ */
diff --git a/drivers/staging/unisys/include/vbushelper.h b/drivers/staging/unisys/include/vbushelper.h
new file mode 100644
index 0000000..93e35f0
--- /dev/null
+++ b/drivers/staging/unisys/include/vbushelper.h
@@ -0,0 +1,47 @@
+/* vbushelper.h
+ *
+ * Copyright © 2011 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+#ifndef __VBUSHELPER_H__
+#define __VBUSHELPER_H__
+
+#include "vbusdeviceinfo.h"
+
+/* TARGET_HOSTNAME specified as -DTARGET_HOSTNAME=\"thename\" on the
+ * command line */
+
+#define TARGET_HOSTNAME "linuxguest"
+
+static inline void
+BusDeviceInfo_Init(ULTRA_VBUS_DEVICEINFO *pBusDeviceInfo,
+		   const char *deviceType, const char *driverName,
+		   const char *ver, const char *verTag,
+		   const char *buildDate, const char *buildTime)
+{
+	memset(pBusDeviceInfo, 0, sizeof(ULTRA_VBUS_DEVICEINFO));
+	snprintf(pBusDeviceInfo->devType, sizeof(pBusDeviceInfo->devType),
+		 "%s", (deviceType) ? deviceType : "unknownType");
+	snprintf(pBusDeviceInfo->drvName, sizeof(pBusDeviceInfo->drvName),
+		 "%s", (driverName) ? driverName : "unknownDriver");
+	snprintf(pBusDeviceInfo->infoStrings,
+		 sizeof(pBusDeviceInfo->infoStrings), "%s\t%s\t%s %s\t%s",
+		 (ver) ? ver : "unknownVer",
+		 (verTag) ? verTag : "unknownVerTag",
+		 (buildDate) ? buildDate : "noBuildDate",
+		 (buildTime) ? buildTime : "nobuildTime", TARGET_HOSTNAME);
+}
+
+#endif
diff --git a/drivers/staging/unisys/uislib/Kconfig b/drivers/staging/unisys/uislib/Kconfig
new file mode 100644
index 0000000..8d87d9c
--- /dev/null
+++ b/drivers/staging/unisys/uislib/Kconfig
@@ -0,0 +1,10 @@
+#
+# Unisys uislib configuration
+#
+
+config UNISYS_UISLIB
+	tristate "Unisys uislib driver"
+	depends on UNISYSSPAR && UNISYS_VISORCHIPSET && UNISYS_CHANNELSTUB
+	---help---
+	If you say Y here, you will enable the Unisys uislib driver.
+
diff --git a/drivers/staging/unisys/uislib/Makefile b/drivers/staging/unisys/uislib/Makefile
new file mode 100644
index 0000000..6e44d49
--- /dev/null
+++ b/drivers/staging/unisys/uislib/Makefile
@@ -0,0 +1,17 @@
+#
+# Makefile for Unisys uislib
+#
+
+obj-$(CONFIG_UNISYS_UISLIB)	+= visoruislib.o
+
+visoruislib-y := uislib.o uisqueue.o  uisthread.o  uisutils.o
+
+ccflags-y += -Idrivers/staging/unisys/include
+ccflags-y += -Idrivers/staging/unisys/channels
+ccflags-y += -Idrivers/staging/unisys/visorchipset
+ccflags-y += -Idrivers/staging/unisys/sparstopdriver
+ccflags-y += -Idrivers/staging/unisys/common-spar/include
+ccflags-y += -Idrivers/staging/unisys/common-spar/include/channels
+
+ccflags-y += -DCONFIG_SPAR_GUEST -DGUESTDRIVERBUILD -DNOAUTOVERSION
+
diff --git a/drivers/staging/unisys/uislib/uislib.c b/drivers/staging/unisys/uislib/uislib.c
new file mode 100644
index 0000000..a004c9d
--- /dev/null
+++ b/drivers/staging/unisys/uislib/uislib.c
@@ -0,0 +1,2536 @@
+/* uislib.c
+ *
+ * Copyright � 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+/* @ALL_INSPECTED */
+#define EXPORT_SYMTAB
+#include <linux/kernel.h>
+#include <linux/highmem.h>
+#ifdef CONFIG_MODVERSIONS
+#include <config/modversions.h>
+#endif
+#include <linux/module.h>
+
+#include "commontypes.h"
+
+#include <linux/version.h>
+#include "uniklog.h"
+#include "diagnostics/appos_subsystems.h"
+#include "uisutils.h"
+#include "vbuschannel.h"
+
+#include <linux/proc_fs.h>
+#include <linux/uaccess.h>	/* for copy_from_user */
+#include <linux/ctype.h>	/* for toupper */
+#include <linux/list.h>
+
+#include "sparstop.h"
+#include "visorchipset.h"
+#include "chanstub.h"
+#include "version.h"
+#include "guestlinuxdebug.h"
+
+#define SET_PROC_OWNER(x, y)
+
+#define UISLIB_TEST_PROC
+#define POLLJIFFIES_NORMAL 1
+/* Choose whether or not you want to wakeup the request-polling thread
+ * after an IO termination:
+ * this is shorter than using __FILE__ (full path name) in
+ * debug/info/error messages
+ */
+#define CURRENT_FILE_PC UISLIB_PC_uislib_c
+#define __MYFILE__ "uislib.c"
+
+/* global function pointers that act as callback functions into virtpcimod */
+int (*VirtControlChanFunc)(struct guest_msgs *);
+
+static int ProcReadBufferValid;
+static char *ProcReadBuffer;	/* Note this MUST be global,
+					 * because the contents must */
+static unsigned int chipset_inited;
+int callback_count = 0;
+#define WAIT_ON_CALLBACK(handle)	\
+	do {			\
+		if (handle)		\
+			break;		\
+		UIS_THREAD_WAIT;	\
+	} while (1)
+
+static struct bus_info *BusListHead;
+static rwlock_t BusListLock;
+static int BusListCount;	/* number of buses in the list */
+static int MaxBusCount;		/* maximum number of buses expected */
+static U64 PhysicalDataChan;
+static int PlatformNumber;
+
+/* This is a list of controlvm messages which could not complete
+ * immediately, but instead must be occasionally retried until they
+ * ultimately succeed/fail.  When this happens,
+ * msg->hdr.Flags.responseExpected determines whether or not we will
+ * send a controlvm response.
+ */
+struct controlvm_retry_entry {
+	CONTROLVM_MESSAGE msg;
+	struct io_msgs cmd;
+	void *obj;
+	int (*controlChanFunc)(struct io_msgs *);
+	struct list_head list_link;
+};
+LIST_HEAD(ControlVmRetryQHead);
+
+static struct uisthread_info Incoming_ThreadInfo;
+static BOOL Incoming_Thread_Started = FALSE;
+LIST_HEAD(List_Polling_Device_Channels);
+unsigned long long tot_moved_to_tail_cnt = 0;
+unsigned long long tot_wait_cnt = 0;
+unsigned long long tot_wakeup_cnt = 0;
+unsigned long long tot_schedule_cnt = 0;
+int en_smart_wakeup = 1;
+static DEFINE_SEMAPHORE(Lock_Polling_Device_Channels);	/* unlocked */
+DECLARE_WAIT_QUEUE_HEAD(Wakeup_Polling_Device_Channels);
+static int Go_Polling_Device_Channels;
+
+static struct proc_dir_entry *uislib_proc_dir;
+static struct proc_dir_entry *uislib_proc_vbus_dir;
+static struct proc_dir_entry *vnic_proc_entry;	/* Used to be "datachan" */
+static struct proc_dir_entry *ctrlchan_proc_entry;
+static struct proc_dir_entry *pmem_proc_entry;
+static struct proc_dir_entry *info_proc_entry;
+static struct proc_dir_entry *switch_proc_entry;
+static struct proc_dir_entry *extport_proc_entry;
+static struct proc_dir_entry *platformnumber_proc_entry;
+static struct proc_dir_entry *bus_proc_entry;
+static struct proc_dir_entry *dev_proc_entry;
+static struct proc_dir_entry *chipset_proc_entry;
+static struct proc_dir_entry *cycles_before_wait_proc_entry;
+static struct proc_dir_entry *reset_counts_proc_entry;
+static struct proc_dir_entry *smart_wakeup_proc_entry;
+static struct proc_dir_entry *disable_proc_entry;
+
+#define DIR_PROC_ENTRY "uislib"
+#define DIR_VBUS_PROC_ENTRY "vbus"
+#define VNIC_PROC_ENTRY_FN "vnic"	/* Used to be "datachan" */
+#define CTRLCHAN_PROC_ENTRY_FN "ctrlchan"
+#define PMEM_PROC_ENTRY_FN "phys_to_virt"
+#define INFO_PROC_ENTRY_FN "info"
+#define SWITCH_PROC_ENTRY_FN "switch"
+#define SWITCH_COUNT_PROC_ENTRY_FN "switch_count"
+#define EXTPORT_PROC_ENTRY_FN "extport"
+#define PLATFORMNUMBER_PROC_ENTRY_FN "platform"
+#define BUS_PROC_ENTRY_FN "bus"
+#define DEV_PROC_ENTRY_FN "device"
+#define CHIPSET_PROC_ENTRY_FN "chipset"
+#define CYCLES_BEFORE_WAIT_PROC_ENTRY_FN "cycles_before_wait"
+#define RESET_COUNTS_PROC_ENTRY_FN "reset_counts"
+#define SMART_WAKEUP_PROC_ENTRY_FN "smart_wakeup"
+#define CALLHOME_PROC_ENTRY_FN "callhome"
+#define CALLHOME_THROTTLED_PROC_ENTRY_FN "callhome_throttled"
+#define DISABLE_PROC_ENTRY_FN "switch_state"
+#ifdef UISLIB_TEST_PROC
+static struct proc_dir_entry *test_proc_entry;
+#define TEST_PROC_ENTRY_FN "test"
+#endif
+unsigned long long cycles_before_wait, wait_cycles;
+
+/*****************************************************/
+/* local functions                                   */
+/*****************************************************/
+
+static int proc_info_vbus_show(struct seq_file *m, void *v);
+static int
+proc_info_vbus_open(struct inode *inode, struct file *filp)
+{
+	/* proc_info_vbus_show will grab this from seq_file.private: */
+	struct bus_info *bus = PDE_DATA(inode);
+	return single_open(filp, proc_info_vbus_show, bus);
+}
+
+static const struct file_operations proc_info_vbus_fops = {
+	.open = proc_info_vbus_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
+
+static ssize_t uislib_proc_read_writeonly(struct file *file,
+					  char __user *buffer,
+					  size_t count, loff_t *ppos);
+
+static ssize_t vnic_proc_write(struct file *file, const char __user *buffer,
+			       size_t count, loff_t *ppos);
+
+static const struct file_operations proc_vnic_fops = {
+	.read = uislib_proc_read_writeonly,
+	.write = vnic_proc_write,
+};
+
+static ssize_t chipset_proc_write(struct file *file, const char __user *buffer,
+				  size_t count, loff_t *ppos);
+
+static const struct file_operations proc_chipset_fops = {
+	.read = uislib_proc_read_writeonly,
+	.write = chipset_proc_write,
+};
+
+static ssize_t info_proc_read(struct file *file, char __user *buf,
+			      size_t len, loff_t *offset);
+static const struct file_operations proc_info_fops = {
+	.read = info_proc_read,
+};
+
+static ssize_t platformnumber_proc_read(struct file *file, char __user *buf,
+					size_t len, loff_t *offset);
+static const struct file_operations proc_platformnumber_fops = {
+	.read = platformnumber_proc_read,
+};
+
+static ssize_t cycles_before_wait_proc_write(struct file *file,
+					     const char __user *buffer,
+					     size_t count, loff_t *ppos);
+static const struct file_operations proc_cycles_before_wait_fops = {
+	.read = uislib_proc_read_writeonly,
+	.write = cycles_before_wait_proc_write,
+};
+
+static ssize_t reset_counts_proc_write(struct file *file,
+				       const char __user *buffer,
+				       size_t count, loff_t *ppos);
+static const struct file_operations proc_reset_counts_fops = {
+	.read = uislib_proc_read_writeonly,
+	.write = reset_counts_proc_write,
+};
+
+static ssize_t smart_wakeup_proc_write(struct file *file,
+				       const char __user *buffer,
+				       size_t count, loff_t *ppos);
+static const struct file_operations proc_smart_wakeup_fops = {
+	.read = uislib_proc_read_writeonly,
+	.write = smart_wakeup_proc_write,
+};
+
+static ssize_t test_proc_write(struct file *file,
+			       const char __user *buffer,
+			       size_t count, loff_t *ppos);
+static const struct file_operations proc_test_fops = {
+	.read = uislib_proc_read_writeonly,
+	.write = test_proc_write,
+};
+
+static ssize_t bus_proc_write(struct file *file,
+			      const char __user *buffer,
+			      size_t count, loff_t *ppos);
+static const struct file_operations proc_bus_fops = {
+	.read = uislib_proc_read_writeonly,
+	.write = bus_proc_write,
+};
+
+static ssize_t dev_proc_write(struct file *file,
+			      const char __user *buffer,
+			      size_t count, loff_t *ppos);
+static const struct file_operations proc_dev_fops = {
+	.read = uislib_proc_read_writeonly,
+	.write = dev_proc_write,
+};
+
+static void
+init_msg_header(CONTROLVM_MESSAGE *msg, U32 id, uint rsp, uint svr)
+{
+	memset(msg, 0, sizeof(CONTROLVM_MESSAGE));
+	msg->hdr.Id = id;
+	msg->hdr.Flags.responseExpected = rsp;
+	msg->hdr.Flags.server = svr;
+}
+
+static void
+create_bus_proc_entries(struct bus_info *bus)
+{
+	bus->proc_dir = proc_mkdir(bus->name, uislib_proc_vbus_dir);
+	if (!bus->proc_dir) {
+		LOGERR("failed to create /proc/uislib/vbus/%s directory",
+		       bus->name);
+		return;
+	}
+	bus->proc_info = proc_create_data("info", 0, bus->proc_dir,
+					  &proc_info_vbus_fops, bus);
+	if (!bus->proc_info) {
+		LOGERR("failed to create /proc/uislib/vbus/%s/info", bus->name);
+		remove_proc_entry(bus->name, uislib_proc_vbus_dir);
+		bus->proc_dir = NULL;
+		return;
+	}
+	SET_PROC_OWNER(bus->proc_info, THIS_MODULE);
+
+}
+
+static void *
+init_vbus_channel(U64 channelAddr, U32 channelBytes, int isServer)
+{
+	void *rc = NULL;
+	void *pChan = uislib_ioremap_cache(channelAddr, channelBytes);
+	if (!pChan) {
+		LOGERR("CONTROLVM_BUS_CREATE error: ioremap_cache of channelAddr:%Lx for channelBytes:%llu failed",
+		     (unsigned long long) channelAddr,
+		     (unsigned long long) channelBytes);
+		RETPTR(NULL);
+	}
+	if (isServer) {
+		memset(pChan, 0, channelBytes);
+		if (!ULTRA_VBUS_CHANNEL_OK_SERVER(channelBytes, NULL)) {
+			ERRDRV("%s channel cannot be used", __func__);
+			uislib_iounmap(pChan);
+			RETPTR(NULL);
+		}
+		ULTRA_VBUS_init_channel(pChan, channelBytes);
+	} else {
+		if (!ULTRA_VBUS_CHANNEL_OK_CLIENT(pChan, NULL)) {
+			ERRDRV("%s channel cannot be used", __func__);
+			uislib_iounmap(pChan);
+			RETPTR(NULL);
+		}
+	}
+	RETPTR(pChan);
+Away:
+	return rc;
+}
+
+static int
+create_bus(CONTROLVM_MESSAGE *msg, char *buf)
+{
+	U32 busNo, deviceCount;
+	struct bus_info *tmp, *bus;
+	size_t size;
+
+	if (MaxBusCount == BusListCount) {
+		LOGERR("CONTROLVM_BUS_CREATE Failed: max buses:%d already created\n",
+		     MaxBusCount);
+		POSTCODE_LINUX_3(BUS_CREATE_FAILURE_PC, MaxBusCount,
+				 POSTCODE_SEVERITY_ERR);
+		return CONTROLVM_RESP_ERROR_MAX_BUSES;
+	}
+
+	busNo = msg->cmd.createBus.busNo;
+	deviceCount = msg->cmd.createBus.deviceCount;
+
+	POSTCODE_LINUX_4(BUS_CREATE_ENTRY_PC, busNo, deviceCount,
+			 POSTCODE_SEVERITY_INFO);
+
+	size =
+	    sizeof(struct bus_info) +
+	    (deviceCount * sizeof(struct device_info *));
+	bus = UISMALLOC(size, GFP_ATOMIC);
+	if (!bus) {
+		LOGERR("CONTROLVM_BUS_CREATE Failed: kmalloc for bus failed.\n");
+		POSTCODE_LINUX_3(BUS_CREATE_FAILURE_PC, busNo,
+				 POSTCODE_SEVERITY_ERR);
+		return CONTROLVM_RESP_ERROR_KMALLOC_FAILED;
+	}
+
+	memset(bus, 0, size);
+
+	/* Currently by default, the bus Number is the GuestHandle.
+	 * Configure Bus message can override this.
+	 */
+	if (msg->hdr.Flags.testMessage) {
+		/* This implies we're the IOVM so set guest handle to 0... */
+		bus->guestHandle = 0;
+		bus->busNo = busNo;
+		bus->localVnic = 1;
+	} else
+		bus->busNo = bus->guestHandle = busNo;
+	sprintf(bus->name, "%d", (int) bus->busNo);
+	bus->deviceCount = deviceCount;
+	bus->device =
+	    (struct device_info **) ((char *) bus + sizeof(struct bus_info));
+	bus->busInstGuid = msg->cmd.createBus.busInstGuid;
+	bus->busChannelBytes = 0;
+	bus->pBusChannel = NULL;
+
+	/* add bus to our bus list - but check for duplicates first */
+	read_lock(&BusListLock);
+	for (tmp = BusListHead; tmp; tmp = tmp->next) {
+		if (tmp->busNo == bus->busNo)
+			break;
+	}
+	read_unlock(&BusListLock);
+	if (tmp) {
+		/* found a bus already in the list with same busNo -
+		 * reject add
+		 */
+		LOGERR("CONTROLVM_BUS_CREATE Failed: bus %d already exists.\n",
+		       bus->busNo);
+		POSTCODE_LINUX_3(BUS_CREATE_FAILURE_PC, bus->busNo,
+				 POSTCODE_SEVERITY_ERR);
+		UISFREE(bus, size);
+		return CONTROLVM_RESP_ERROR_ALREADY_DONE;
+	}
+	if ((msg->cmd.createBus.channelAddr != 0)
+	    && (msg->cmd.createBus.channelBytes != 0)) {
+		bus->busChannelBytes = msg->cmd.createBus.channelBytes;
+		bus->pBusChannel =
+		    init_vbus_channel(msg->cmd.createBus.channelAddr,
+				      msg->cmd.createBus.channelBytes,
+				      msg->hdr.Flags.server);
+	}
+	/* the msg is bound for virtpci; send guest_msgs struct to callback */
+	if (!msg->hdr.Flags.server) {
+		struct guest_msgs cmd;
+		cmd.msgtype = GUEST_ADD_VBUS;
+		cmd.add_vbus.busNo = busNo;
+		cmd.add_vbus.chanptr = bus->pBusChannel;
+		cmd.add_vbus.deviceCount = deviceCount;
+		cmd.add_vbus.busTypeGuid = msg->cmd.createBus.busDataTypeGuid;
+		cmd.add_vbus.busInstGuid = msg->cmd.createBus.busInstGuid;
+		if (!VirtControlChanFunc) {
+			UISFREE(bus, size);
+			LOGERR("CONTROLVM_BUS_CREATE Failed: virtpci callback not registered.");
+			POSTCODE_LINUX_3(BUS_CREATE_FAILURE_PC, bus->busNo,
+					 POSTCODE_SEVERITY_ERR);
+			return CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_FAILURE;
+		}
+		if (!VirtControlChanFunc(&cmd)) {
+			UISFREE(bus, size);
+			LOGERR("CONTROLVM_BUS_CREATE Failed: virtpci GUEST_ADD_VBUS returned error.");
+			POSTCODE_LINUX_3(BUS_CREATE_FAILURE_PC, bus->busNo,
+					 POSTCODE_SEVERITY_ERR);
+			return
+			    CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_CALLBACK_ERROR;
+		}
+	}
+	create_bus_proc_entries(bus);
+
+	/* add bus at the head of our list */
+	write_lock(&BusListLock);
+	if (!BusListHead)
+		BusListHead = bus;
+	else {
+		bus->next = BusListHead;
+		BusListHead = bus;
+	}
+	BusListCount++;
+	write_unlock(&BusListLock);
+
+	POSTCODE_LINUX_3(BUS_CREATE_EXIT_PC, bus->busNo,
+			 POSTCODE_SEVERITY_INFO);
+	return CONTROLVM_RESP_SUCCESS;
+}
+
+static int
+destroy_bus(CONTROLVM_MESSAGE *msg, char *buf)
+{
+	int i;
+	struct bus_info *bus, *prev = NULL;
+	U32 busNo;
+
+	busNo = msg->cmd.destroyBus.busNo;
+
+	/* find and delete the bus */
+	read_lock(&BusListLock);
+	for (bus = BusListHead; bus; prev = bus, bus = bus->next) {
+		if (bus->busNo == busNo) {
+			/* found the bus - ensure that all device
+			 * slots are NULL
+			 */
+			for (i = 0; i < bus->deviceCount; i++) {
+				if (bus->device[i] != NULL) {
+					LOGERR("CONTROLVM_BUS_DESTROY Failed: device %i attached to bus %d.",
+					     i, busNo);
+					read_unlock(&BusListLock);
+					return CONTROLVM_RESP_ERROR_BUS_DEVICE_ATTACHED;
+				}
+			}
+			read_unlock(&BusListLock);
+			/* the msg is bound for virtpci; send
+			 * guest_msgs struct to callback
+			 */
+			if (!msg->hdr.Flags.server) {
+				struct guest_msgs cmd;
+				cmd.msgtype = GUEST_DEL_VBUS;
+				cmd.del_vbus.busNo = busNo;
+				if (!VirtControlChanFunc) {
+					LOGERR("CONTROLVM_BUS_DESTROY Failed: virtpci callback not registered.");
+					return CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_FAILURE;
+				}
+				if (!VirtControlChanFunc(&cmd)) {
+					LOGERR("CONTROLVM_BUS_DESTROY Failed: virtpci GUEST_DEL_VBUS returned error.");
+					return CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_CALLBACK_ERROR;
+				}
+			}
+			/* remove the bus from the list */
+			write_lock(&BusListLock);
+			if (prev)	/* not at head */
+				prev->next = bus->next;
+			else
+				BusListHead = bus->next;
+			BusListCount--;
+			write_unlock(&BusListLock);
+			break;
+		}
+	}
+
+	if (!bus) {
+		LOGERR("CONTROLVM_BUS_DESTROY Failed: failed to find bus %d.\n",
+		       busNo);
+		read_unlock(&BusListLock);
+		return CONTROLVM_RESP_ERROR_ALREADY_DONE;
+	}
+	if (bus->proc_info) {
+		remove_proc_entry("info", bus->proc_dir);
+		bus->proc_info = NULL;
+	}
+	if (bus->proc_dir) {
+		remove_proc_entry(bus->name, uislib_proc_vbus_dir);
+		bus->proc_dir = NULL;
+	}
+	if (bus->pBusChannel) {
+		uislib_iounmap(bus->pBusChannel);
+		bus->pBusChannel = NULL;
+	}
+
+	UISFREE(bus,
+		sizeof(struct bus_info) +
+		(bus->deviceCount * sizeof(struct device_info *)));
+	return CONTROLVM_RESP_SUCCESS;
+}
+
+static int
+create_device(CONTROLVM_MESSAGE *msg, char *buf)
+{
+	struct device_info *dev;
+	struct bus_info *bus;
+	U32 busNo, devNo;
+	int result = CONTROLVM_RESP_SUCCESS;
+	U64 minSize = MIN_IO_CHANNEL_SIZE;
+	ReqHandlerInfo_t *pReqHandler;
+
+	busNo = msg->cmd.createDevice.busNo;
+	devNo = msg->cmd.createDevice.devNo;
+
+	POSTCODE_LINUX_4(DEVICE_CREATE_ENTRY_PC, devNo, busNo,
+			 POSTCODE_SEVERITY_INFO);
+
+	dev = UISMALLOC(sizeof(struct device_info), GFP_ATOMIC);
+	if (!dev) {
+		LOGERR("CONTROLVM_DEVICE_CREATE Failed: kmalloc for dev failed.\n");
+		POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, devNo, busNo,
+				 POSTCODE_SEVERITY_ERR);
+		return CONTROLVM_RESP_ERROR_KMALLOC_FAILED;
+	}
+
+	memset(dev, 0, sizeof(struct device_info));
+	dev->channelTypeGuid = msg->cmd.createDevice.dataTypeGuid;
+	dev->intr = msg->cmd.createDevice.intr;
+	dev->channelAddr = msg->cmd.createDevice.channelAddr;
+	dev->busNo = busNo;
+	dev->devNo = devNo;
+	sema_init(&dev->interrupt_callback_lock, 1);	/* unlocked */
+	sprintf(dev->devid, "vbus%u:dev%u", (unsigned) busNo, (unsigned) devNo);
+	/* map the channel memory for the device. */
+	if (msg->hdr.Flags.testMessage)
+		dev->chanptr = __va(dev->channelAddr);
+	else {
+		pReqHandler = ReqHandlerFind(dev->channelTypeGuid);
+		if (pReqHandler)
+			/* generic service handler registered for this
+			 * channel
+			 */
+			minSize = pReqHandler->min_channel_bytes;
+		if (minSize > msg->cmd.createDevice.channelBytes) {
+			LOGERR("CONTROLVM_DEVICE_CREATE Failed: channel size is too small, channel size:0x%lx, required size:0x%lx",
+			     (ulong) msg->cmd.createDevice.channelBytes,
+			     (ulong) minSize);
+			POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, devNo, busNo,
+					 POSTCODE_SEVERITY_ERR);
+			result = CONTROLVM_RESP_ERROR_CHANNEL_SIZE_TOO_SMALL;
+			goto Away;
+		}
+		dev->chanptr =
+		    uislib_ioremap_cache(dev->channelAddr,
+					 msg->cmd.createDevice.channelBytes);
+		if (!dev->chanptr) {
+			LOGERR("CONTROLVM_DEVICE_CREATE Failed: ioremap_cache of channelAddr:%Lx for channelBytes:%llu failed",
+			     dev->channelAddr,
+			     msg->cmd.createDevice.channelBytes);
+			result = CONTROLVM_RESP_ERROR_IOREMAP_FAILED;
+			POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, devNo, busNo,
+					 POSTCODE_SEVERITY_ERR);
+			goto Away;
+		}
+	}
+	dev->devInstGuid = msg->cmd.createDevice.devInstGuid;
+	dev->channelBytes = msg->cmd.createDevice.channelBytes;
+
+	read_lock(&BusListLock);
+	for (bus = BusListHead; bus; bus = bus->next) {
+		if (bus->busNo == busNo) {
+			/* make sure the device number is valid */
+			if (devNo >= bus->deviceCount) {
+				LOGERR("CONTROLVM_DEVICE_CREATE Failed: device (%d) >= deviceCount (%d).",
+				     devNo, bus->deviceCount);
+				result = CONTROLVM_RESP_ERROR_MAX_DEVICES;
+				POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC,
+						 devNo, busNo,
+						 POSTCODE_SEVERITY_ERR);
+				read_unlock(&BusListLock);
+				goto Away;
+			}
+			/* make sure this device is not already set */
+			if (bus->device[devNo]) {
+				LOGERR("CONTROLVM_DEVICE_CREATE Failed: device %d is already exists.",
+				     devNo);
+				POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC,
+						 devNo, busNo,
+						 POSTCODE_SEVERITY_ERR);
+				result = CONTROLVM_RESP_ERROR_ALREADY_DONE;
+				read_unlock(&BusListLock);
+				goto Away;
+			}
+			read_unlock(&BusListLock);
+			/* the msg is bound for virtpci; send
+			 * guest_msgs struct to callback
+			 */
+			if (!msg->hdr.Flags.server) {
+				struct guest_msgs cmd;
+				if (!memcmp
+				    (&dev->channelTypeGuid,
+				     &UltraVhbaChannelProtocolGuid,
+				     sizeof(GUID))) {
+					WAIT_FOR_VALID_GUID(((CHANNEL_HEADER
+							      *) (dev->
+								  chanptr))->
+							    Type);
+					if (!ULTRA_VHBA_CHANNEL_OK_CLIENT
+					    (dev->chanptr, NULL)) {
+						LOGERR("CONTROLVM_DEVICE_CREATE Failed:[CLIENT]VHBA dev %d chan invalid.",
+						     devNo);
+						POSTCODE_LINUX_4
+						    (DEVICE_CREATE_FAILURE_PC,
+						     devNo, busNo,
+						     POSTCODE_SEVERITY_ERR);
+						result = CONTROLVM_RESP_ERROR_CHANNEL_INVALID;
+						goto Away;
+					}
+					cmd.msgtype = GUEST_ADD_VHBA;
+					cmd.add_vhba.chanptr = dev->chanptr;
+					cmd.add_vhba.busNo = busNo;
+					cmd.add_vhba.deviceNo = devNo;
+					cmd.add_vhba.devInstGuid =
+					    dev->devInstGuid;
+					cmd.add_vhba.intr = dev->intr;
+				} else
+				    if (!memcmp
+					(&dev->channelTypeGuid,
+					 &UltraVnicChannelProtocolGuid,
+					 sizeof(GUID))) {
+					WAIT_FOR_VALID_GUID(((CHANNEL_HEADER
+							      *) (dev->
+								  chanptr))->
+							    Type);
+					if (!ULTRA_VNIC_CHANNEL_OK_CLIENT
+					    (dev->chanptr, NULL)) {
+						LOGERR("CONTROLVM_DEVICE_CREATE Failed: VNIC[CLIENT] dev %d chan invalid.",
+						     devNo);
+						POSTCODE_LINUX_4
+						    (DEVICE_CREATE_FAILURE_PC,
+						     devNo, busNo,
+						     POSTCODE_SEVERITY_ERR);
+						result = CONTROLVM_RESP_ERROR_CHANNEL_INVALID;
+						goto Away;
+					}
+					cmd.msgtype = GUEST_ADD_VNIC;
+					cmd.add_vnic.chanptr = dev->chanptr;
+					cmd.add_vnic.busNo = busNo;
+					cmd.add_vnic.deviceNo = devNo;
+					cmd.add_vnic.devInstGuid =
+					    dev->devInstGuid;
+					cmd.add_vhba.intr = dev->intr;
+				} else {
+					LOGERR("CONTROLVM_DEVICE_CREATE Failed: unknown channelTypeGuid.\n");
+					POSTCODE_LINUX_4
+					    (DEVICE_CREATE_FAILURE_PC, devNo,
+					     busNo, POSTCODE_SEVERITY_ERR);
+					result = CONTROLVM_RESP_ERROR_CHANNEL_TYPE_UNKNOWN;
+					goto Away;
+				}
+
+				if (!VirtControlChanFunc) {
+					LOGERR("CONTROLVM_DEVICE_CREATE Failed: virtpci callback not registered.");
+					POSTCODE_LINUX_4
+					    (DEVICE_CREATE_FAILURE_PC, devNo,
+					     busNo, POSTCODE_SEVERITY_ERR);
+					result = CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_FAILURE;
+					goto Away;
+				}
+
+				if (!VirtControlChanFunc(&cmd)) {
+					LOGERR("CONTROLVM_DEVICE_CREATE Failed: virtpci GUEST_ADD_[VHBA||VNIC] returned error.");
+					POSTCODE_LINUX_4
+					    (DEVICE_CREATE_FAILURE_PC, devNo,
+					     busNo, POSTCODE_SEVERITY_ERR);
+					result = CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_CALLBACK_ERROR;
+					goto Away;
+				}
+			}
+			bus->device[devNo] = dev;
+			POSTCODE_LINUX_4(DEVICE_CREATE_SUCCESS_PC, devNo, busNo,
+					 POSTCODE_SEVERITY_INFO);
+			return CONTROLVM_RESP_SUCCESS;
+		}
+	}
+	read_unlock(&BusListLock);
+
+	LOGERR("CONTROLVM_DEVICE_CREATE Failed: failed to find bus %d.", busNo);
+	POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, devNo, busNo,
+			 POSTCODE_SEVERITY_ERR);
+	result = CONTROLVM_RESP_ERROR_BUS_INVALID;
+
+Away:
+	if (!msg->hdr.Flags.testMessage) {
+		uislib_iounmap(dev->chanptr);
+		dev->chanptr = NULL;
+	}
+
+	UISFREE(dev, sizeof(struct device_info));
+	return result;
+}
+
+static int
+pause_device(CONTROLVM_MESSAGE *msg)
+{
+	U32 busNo, devNo;
+	struct bus_info *bus;
+	struct device_info *dev;
+	struct guest_msgs cmd;
+
+	busNo = msg->cmd.deviceChangeState.busNo;
+	devNo = msg->cmd.deviceChangeState.devNo;
+
+	read_lock(&BusListLock);
+	for (bus = BusListHead; bus; bus = bus->next) {
+		if (bus->busNo == busNo) {
+			/* make sure the device number is valid */
+			if (devNo >= bus->deviceCount) {
+				LOGERR("CONTROLVM_DEVICE_CHANGESTATE:pause Failed: device(%d) >= deviceCount(%d).",
+				     devNo, bus->deviceCount);
+				read_unlock(&BusListLock);
+				return CONTROLVM_RESP_ERROR_DEVICE_INVALID;
+			}
+			/* make sure this device exists */
+			dev = bus->device[devNo];
+			if (!dev) {
+				LOGERR("CONTROLVM_DEVICE_CHANGESTATE:pause Failed: device %d does not exist.",
+				     devNo);
+				read_unlock(&BusListLock);
+				return CONTROLVM_RESP_ERROR_ALREADY_DONE;
+			}
+			read_unlock(&BusListLock);
+			/* the msg is bound for virtpci; send
+			 * guest_msgs struct to callback
+			 */
+			if (!memcmp
+			    (&dev->channelTypeGuid,
+			     &UltraVhbaChannelProtocolGuid, sizeof(GUID))) {
+				cmd.msgtype = GUEST_PAUSE_VHBA;
+				cmd.pause_vhba.chanptr = dev->chanptr;
+			} else
+			    if (!memcmp
+				(&dev->channelTypeGuid,
+				 &UltraVnicChannelProtocolGuid,
+				 sizeof(GUID))) {
+				cmd.msgtype = GUEST_PAUSE_VNIC;
+				cmd.pause_vnic.chanptr = dev->chanptr;
+			} else {
+				LOGERR("CONTROLVM_DEVICE_CHANGESTATE:pause Failed: unknown channelTypeGuid.\n");
+				return
+				    CONTROLVM_RESP_ERROR_CHANNEL_TYPE_UNKNOWN;
+			}
+
+			if (!VirtControlChanFunc) {
+				LOGERR("CONTROLVM_DEVICE_CHANGESTATE Failed: virtpci callback not registered.");
+				return
+				    CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_FAILURE;
+			}
+
+			if (!VirtControlChanFunc(&cmd)) {
+				LOGERR("CONTROLVM_DEVICE_CHANGESTATE:pause Failed: virtpci GUEST_PAUSE_[VHBA||VNIC] returned error.");
+				return CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_CALLBACK_ERROR;
+			}
+			break;
+		}
+	}
+
+	if (!bus) {
+		LOGERR("CONTROLVM_DEVICE_CHANGESTATE:pause Failed: bus %d does not exist",
+		     busNo);
+		read_unlock(&BusListLock);
+		return CONTROLVM_RESP_ERROR_BUS_INVALID;
+	}
+
+	return CONTROLVM_RESP_SUCCESS;
+}
+
+static int
+resume_device(CONTROLVM_MESSAGE *msg)
+{
+	U32 busNo, devNo;
+	struct bus_info *bus;
+	struct device_info *dev;
+	struct guest_msgs cmd;
+
+	busNo = msg->cmd.deviceChangeState.busNo;
+	devNo = msg->cmd.deviceChangeState.devNo;
+
+	read_lock(&BusListLock);
+	for (bus = BusListHead; bus; bus = bus->next) {
+		if (bus->busNo == busNo) {
+			/* make sure the device number is valid */
+			if (devNo >= bus->deviceCount) {
+				LOGERR("CONTROLVM_DEVICE_CHANGESTATE:resume Failed: device(%d) >= deviceCount(%d).",
+				     devNo, bus->deviceCount);
+				read_unlock(&BusListLock);
+				return CONTROLVM_RESP_ERROR_DEVICE_INVALID;
+			}
+			/* make sure this device exists */
+			dev = bus->device[devNo];
+			if (!dev) {
+				LOGERR("CONTROLVM_DEVICE_CHANGESTATE:resume Failed: device %d does not exist.",
+				     devNo);
+				read_unlock(&BusListLock);
+				return CONTROLVM_RESP_ERROR_ALREADY_DONE;
+			}
+			read_unlock(&BusListLock);
+			/* the msg is bound for virtpci; send
+			 * guest_msgs struct to callback
+			 */
+			if (!memcmp(&dev->channelTypeGuid,
+				    &UltraVhbaChannelProtocolGuid,
+				    sizeof(GUID))) {
+				cmd.msgtype = GUEST_RESUME_VHBA;
+				cmd.resume_vhba.chanptr = dev->chanptr;
+			} else
+			    if (!memcmp(&dev->channelTypeGuid,
+					&UltraVnicChannelProtocolGuid,
+					sizeof(GUID))) {
+				cmd.msgtype = GUEST_RESUME_VNIC;
+				cmd.resume_vnic.chanptr = dev->chanptr;
+			} else {
+				LOGERR("CONTROLVM_DEVICE_CHANGESTATE:resume Failed: unknown channelTypeGuid.\n");
+				return
+				    CONTROLVM_RESP_ERROR_CHANNEL_TYPE_UNKNOWN;
+			}
+
+			if (!VirtControlChanFunc) {
+				LOGERR("CONTROLVM_DEVICE_CHANGESTATE Failed: virtpci callback not registered.");
+				return
+				    CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_FAILURE;
+			}
+
+			if (!VirtControlChanFunc(&cmd)) {
+				LOGERR("CONTROLVM_DEVICE_CHANGESTATE:resume Failed: virtpci GUEST_RESUME_[VHBA||VNIC] returned error.");
+				return CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_CALLBACK_ERROR;
+			}
+			break;
+		}
+	}
+
+	if (!bus) {
+		LOGERR("CONTROLVM_DEVICE_CHANGESTATE:resume Failed: bus %d does not exist",
+		     busNo);
+		read_unlock(&BusListLock);
+		return CONTROLVM_RESP_ERROR_BUS_INVALID;
+	}
+
+	return CONTROLVM_RESP_SUCCESS;
+}
+
+static int
+destroy_device(CONTROLVM_MESSAGE *msg, char *buf)
+{
+	U32 busNo, devNo;
+	struct bus_info *bus;
+	struct device_info *dev;
+	struct guest_msgs cmd;
+
+	busNo = msg->cmd.destroyDevice.busNo;
+	devNo = msg->cmd.destroyDevice.devNo;
+
+	read_lock(&BusListLock);
+	LOGINF("destroy_device called for busNo=%u, devNo=%u", busNo, devNo);
+	for (bus = BusListHead; bus; bus = bus->next) {
+		if (bus->busNo == busNo) {
+			/* make sure the device number is valid */
+			if (devNo >= bus->deviceCount) {
+				LOGERR("CONTROLVM_DEVICE_DESTORY Failed: device(%d) >= deviceCount(%d).",
+				     devNo, bus->deviceCount);
+				read_unlock(&BusListLock);
+				return CONTROLVM_RESP_ERROR_DEVICE_INVALID;
+			}
+			/* make sure this device exists */
+			dev = bus->device[devNo];
+			if (!dev) {
+				LOGERR("CONTROLVM_DEVICE_DESTROY Failed: device %d does not exist.",
+				     devNo);
+				read_unlock(&BusListLock);
+				return CONTROLVM_RESP_ERROR_ALREADY_DONE;
+			}
+			read_unlock(&BusListLock);
+			/* the msg is bound for virtpci; send
+			 * guest_msgs struct to callback
+			 */
+			if (!memcmp
+			    (&dev->channelTypeGuid,
+			     &UltraVhbaChannelProtocolGuid, sizeof(GUID))) {
+				cmd.msgtype = GUEST_DEL_VHBA;
+				cmd.del_vhba.chanptr = dev->chanptr;
+			} else
+			    if (!memcmp
+				(&dev->channelTypeGuid,
+				 &UltraVnicChannelProtocolGuid,
+				 sizeof(GUID))) {
+				cmd.msgtype = GUEST_DEL_VNIC;
+				cmd.del_vnic.chanptr = dev->chanptr;
+			} else {
+				LOGERR("CONTROLVM_DEVICE_DESTROY Failed: unknown channelTypeGuid.\n");
+				return
+				    CONTROLVM_RESP_ERROR_CHANNEL_TYPE_UNKNOWN;
+			}
+
+			if (!VirtControlChanFunc) {
+				LOGERR("CONTROLVM_DEVICE_DESTORY Failed: virtpci callback not registered.");
+				return
+				    CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_FAILURE;
+			}
+
+			if (!VirtControlChanFunc(&cmd)) {
+				LOGERR("CONTROLVM_DEVICE_DESTROY Failed: virtpci GUEST_DEL_[VHBA||VNIC] returned error.");
+				return CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_CALLBACK_ERROR;
+			}
+/* you must disable channel interrupts BEFORE you unmap the channel,
+ * because if you unmap first, there may still be some activity going
+ * on which accesses the channel and you will get a "unable to handle
+ * kernel paging request"
+ */
+			if (dev->polling) {
+				LOGINF("calling uislib_disable_channel_interrupts");
+				uislib_disable_channel_interrupts(busNo, devNo);
+			}
+			/* unmap the channel memory for the device. */
+			if (!msg->hdr.Flags.testMessage) {
+				LOGINF("destroy_device, doing iounmap");
+				uislib_iounmap(dev->chanptr);
+			}
+			UISFREE(dev, sizeof(struct device_info));
+			bus->device[devNo] = NULL;
+			break;
+		}
+	}
+
+	if (!bus) {
+		LOGERR("CONTROLVM_DEVICE_DESTROY Failed: bus %d does not exist",
+		       busNo);
+		read_unlock(&BusListLock);
+		return CONTROLVM_RESP_ERROR_BUS_INVALID;
+	}
+
+	return CONTROLVM_RESP_SUCCESS;
+}
+
+void
+ULTRA_disp_channel_header(CHANNEL_HEADER *x)
+{
+	LOGINF("Sig=%llx, HdrSz=%lx, Sz=%llx, Feat=%llx, hPart=%llx, Hndl=%llx, ChSpace=%llx, Ver=%lx, PartIdx=%lx\n",
+	     x->Signature, (long unsigned int) x->HeaderSize, x->Size,
+	     x->Features, x->PartitionHandle, x->Handle, x->oChannelSpace,
+	     (long unsigned int) x->VersionId,
+	     (long unsigned int) x->PartitionIndex);
+
+	LOGINF("ClientStr=%lx, CliStBoot=%lx, CmdStCli=%lx, CliStOS=%lx, ChCharistics=%lx, CmdStSrv=%lx, SrvSt=%lx\n",
+	     (long unsigned int) x->oClientString,
+	     (long unsigned int) x->CliStateBoot,
+	     (long unsigned int) x->CmdStateCli,
+	     (long unsigned int) x->CliStateOS,
+	     (long unsigned int) x->ChannelCharacteristics,
+	     (long unsigned int) x->CmdStateSrv,
+	     (long unsigned int) x->SrvState);
+
+}
+
+void
+ULTRA_disp_channel(ULTRA_IO_CHANNEL_PROTOCOL *x)
+{
+	ULTRA_disp_channel_header(&x->ChannelHeader);
+	LOGINF("cmdQ.Type=%lx\n", (long unsigned int) x->cmdQ.Type);
+	LOGINF("cmdQ.Size=%llx\n", x->cmdQ.Size);
+	LOGINF("cmdQ.oSignalBase=%llx\n", x->cmdQ.oSignalBase);
+	LOGINF("cmdQ.SignalSize=%lx\n", (long unsigned int) x->cmdQ.SignalSize);
+	LOGINF("cmdQ.MaxSignalSlots=%lx\n",
+	       (long unsigned int) x->cmdQ.MaxSignalSlots);
+	LOGINF("cmdQ.MaxSignals=%lx\n", (long unsigned int) x->cmdQ.MaxSignals);
+	LOGINF("rspQ.Type=%lx\n", (long unsigned int) x->rspQ.Type);
+	LOGINF("rspQ.Size=%llx\n", x->rspQ.Size);
+	LOGINF("rspQ.oSignalBase=%llx\n", x->rspQ.oSignalBase);
+	LOGINF("rspQ.SignalSize=%lx\n", (long unsigned int) x->rspQ.SignalSize);
+	LOGINF("rspQ.MaxSignalSlots=%lx\n",
+	       (long unsigned int) x->rspQ.MaxSignalSlots);
+	LOGINF("rspQ.MaxSignals=%lx\n", (long unsigned int) x->rspQ.MaxSignals);
+	LOGINF("SIZEOF_CMDRSP=%lx\n", SIZEOF_CMDRSP);
+	LOGINF("SIZEOF_PROTOCOL=%lx\n", SIZEOF_PROTOCOL);
+}
+
+void
+ULTRA_disp_vnic_channel(ULTRA_IO_CHANNEL_PROTOCOL *x)
+{
+	LOGINF("num_rcv_bufs=%lx\n", (long unsigned int) x->vnic.num_rcv_bufs);
+	LOGINF("mtu=%lx\n", (long unsigned int) x->vnic.mtu);
+}
+
+static int
+init_chipset(CONTROLVM_MESSAGE *msg, char *buf)
+{
+	POSTCODE_LINUX_2(CHIPSET_INIT_ENTRY_PC, POSTCODE_SEVERITY_INFO);
+
+	MaxBusCount = msg->cmd.initChipset.busCount;
+	PlatformNumber = msg->cmd.initChipset.platformNumber;
+	PhysicalDataChan = 0;
+
+	/* We need to make sure we have our functions registered
+	* before processing messages.  If we are a test vehicle the
+	* testMessage for init_chipset will be set.  We can ignore the
+	* waits for the callbacks, since this will be manually entered
+	* from a user.  If no testMessage is set, we will wait for the
+	* functions.
+	*/
+	if (!msg->hdr.Flags.testMessage)
+		WAIT_ON_CALLBACK(VirtControlChanFunc);
+
+	chipset_inited = 1;
+	POSTCODE_LINUX_2(CHIPSET_INIT_EXIT_PC, POSTCODE_SEVERITY_INFO);
+
+	return CONTROLVM_RESP_SUCCESS;
+}
+
+static int
+stop_chipset(CONTROLVM_MESSAGE *msg, char *buf)
+{
+	/* Check that all buses and switches have been torn down and
+	 * destroyed.
+	 */
+	if (BusListHead) {
+		/* Buses still exist. */
+		LOGERR("CONTROLVM_CHIPSET_STOP: BusListHead is not NULL");
+		return CONTROLVM_RESP_ERROR_CHIPSET_STOP_FAILED_BUS;
+	}
+	if (BusListCount) {
+		/* BusListHead is NULL, but BusListCount != 0 */
+		LOGERR("CONTROLVM_CHIPSET_STOP: BusListCount != 0");
+		return CONTROLVM_RESP_ERROR_CHIPSET_STOP_FAILED_BUS;
+	}
+
+	/* Buses are shut down. */
+	return visorchipset_chipset_notready();
+}
+
+static int
+delete_bus_glue(U32 busNo)
+{
+	CONTROLVM_MESSAGE msg;
+
+	init_msg_header(&msg, CONTROLVM_BUS_DESTROY, 0, 0);
+	msg.cmd.destroyBus.busNo = busNo;
+	if (destroy_bus(&msg, NULL) != CONTROLVM_RESP_SUCCESS) {
+		LOGERR("destroy_bus failed. busNo=0x%x\n", busNo);
+		return 0;
+	}
+	return 1;
+}
+
+static int
+delete_device_glue(U32 busNo, U32 devNo)
+{
+	CONTROLVM_MESSAGE msg;
+
+	init_msg_header(&msg, CONTROLVM_DEVICE_DESTROY, 0, 0);
+	msg.cmd.destroyDevice.busNo = busNo;
+	msg.cmd.destroyDevice.devNo = devNo;
+	if (destroy_device(&msg, NULL) != CONTROLVM_RESP_SUCCESS) {
+		LOGERR("destroy_device failed. busNo=0x%x devNo=0x%x\n", busNo,
+		       devNo);
+		return 0;
+	}
+	return 1;
+}
+
+int
+uislib_client_inject_add_bus(U32 busNo, GUID instGuid,
+			     U64 channelAddr, ulong nChannelBytes)
+{
+	CONTROLVM_MESSAGE msg;
+
+	LOGINF("enter busNo=0x%x\n", busNo);
+	/* step 0: init the chipset */
+	POSTCODE_LINUX_3(CHIPSET_INIT_ENTRY_PC, busNo, POSTCODE_SEVERITY_INFO);
+
+	if (!chipset_inited) {
+		/* step: initialize the chipset */
+		init_msg_header(&msg, CONTROLVM_CHIPSET_INIT, 0, 0);
+		/* this change is needed so that console will come up
+		* OK even when the bus 0 create comes in late.  If the
+		* bus 0 create is the first create, then the add_vnic
+		* will work fine, but if the bus 0 create arrives
+		* after number 4, then the add_vnic will fail, and the
+		* ultraboot will fail.
+		*/
+		msg.cmd.initChipset.busCount = 23;
+		msg.cmd.initChipset.switchCount = 0;
+		if (init_chipset(&msg, NULL) != CONTROLVM_RESP_SUCCESS) {
+			LOGERR("init_chipset failed.\n");
+			return 0;
+		}
+		LOGINF("chipset initialized\n");
+		POSTCODE_LINUX_3(CHIPSET_INIT_EXIT_PC, busNo,
+				 POSTCODE_SEVERITY_INFO);
+	}
+
+	/* step 1: create a bus */
+	POSTCODE_LINUX_3(BUS_CREATE_ENTRY_PC, busNo, POSTCODE_SEVERITY_WARNING);
+	init_msg_header(&msg, CONTROLVM_BUS_CREATE, 0, 0);
+	msg.cmd.createBus.busNo = busNo;
+	msg.cmd.createBus.deviceCount = 23;	/* devNo+1; */
+	msg.cmd.createBus.channelAddr = channelAddr;
+	msg.cmd.createBus.channelBytes = nChannelBytes;
+	if (create_bus(&msg, NULL) != CONTROLVM_RESP_SUCCESS) {
+		LOGERR("create_bus failed.\n");
+		POSTCODE_LINUX_3(BUS_CREATE_FAILURE_PC, busNo,
+				 POSTCODE_SEVERITY_ERR);
+		return 0;
+	}
+	POSTCODE_LINUX_3(BUS_CREATE_EXIT_PC, busNo, POSTCODE_SEVERITY_INFO);
+
+	return 1;
+}
+EXPORT_SYMBOL_GPL(uislib_client_inject_add_bus);
+
+
+int
+uislib_client_inject_del_bus(U32 busNo)
+{
+	return delete_bus_glue(busNo);
+}
+EXPORT_SYMBOL_GPL(uislib_client_inject_del_bus);
+
+int
+uislib_client_inject_pause_vhba(U32 busNo, U32 devNo)
+{
+	CONTROLVM_MESSAGE msg;
+	int rc;
+
+	init_msg_header(&msg, CONTROLVM_DEVICE_CHANGESTATE, 0, 0);
+	msg.cmd.deviceChangeState.busNo = busNo;
+	msg.cmd.deviceChangeState.devNo = devNo;
+	msg.cmd.deviceChangeState.state = SegmentStateStandby;
+	rc = pause_device(&msg);
+	if (rc != CONTROLVM_RESP_SUCCESS) {
+		LOGERR("VHBA pause_device failed. busNo=0x%x devNo=0x%x\n",
+		       busNo, devNo);
+		return rc;
+	}
+	return 0;
+}
+EXPORT_SYMBOL_GPL(uislib_client_inject_pause_vhba);
+
+int
+uislib_client_inject_resume_vhba(U32 busNo, U32 devNo)
+{
+	CONTROLVM_MESSAGE msg;
+	int rc;
+
+	init_msg_header(&msg, CONTROLVM_DEVICE_CHANGESTATE, 0, 0);
+	msg.cmd.deviceChangeState.busNo = busNo;
+	msg.cmd.deviceChangeState.devNo = devNo;
+	msg.cmd.deviceChangeState.state = SegmentStateRunning;
+	rc = resume_device(&msg);
+	if (rc != CONTROLVM_RESP_SUCCESS) {
+		LOGERR("VHBA resume_device failed. busNo=0x%x devNo=0x%x\n",
+		       busNo, devNo);
+		return rc;
+	}
+	return 0;
+
+}
+EXPORT_SYMBOL_GPL(uislib_client_inject_resume_vhba);
+
+int
+uislib_client_inject_add_vhba(U32 busNo, U32 devNo,
+			      U64 phys_chan_addr, U32 chan_bytes,
+			      int is_test_addr, GUID instGuid,
+			      struct InterruptInfo *intr)
+{
+	CONTROLVM_MESSAGE msg;
+
+	LOGINF(" enter busNo=0x%x devNo=0x%x\n", busNo, devNo);
+	/* chipset init'ed with bus bus has been previously created -
+	* Verify it still exists step 2: create the VHBA device on the
+	* bus
+	*/
+	POSTCODE_LINUX_4(VHBA_CREATE_ENTRY_PC, devNo, busNo,
+			 POSTCODE_SEVERITY_INFO);
+
+	init_msg_header(&msg, CONTROLVM_DEVICE_CREATE, 0, 0);
+	if (is_test_addr)
+		/* signify that the physical channel address does NOT
+		 * need to be ioremap()ed
+		 */
+		msg.hdr.Flags.testMessage = 1;
+	msg.cmd.createDevice.busNo = busNo;
+	msg.cmd.createDevice.devNo = devNo;
+	msg.cmd.createDevice.devInstGuid = instGuid;
+	if (intr)
+		msg.cmd.createDevice.intr = *intr;
+	else
+		memset(&msg.cmd.createDevice.intr, 0,
+		       sizeof(struct InterruptInfo));
+	msg.cmd.createDevice.channelAddr = phys_chan_addr;
+	if (chan_bytes < MIN_IO_CHANNEL_SIZE) {
+		LOGERR("wrong channel size.chan_bytes = 0x%x IO_CHANNEL_SIZE= 0x%x\n",
+		     chan_bytes, (unsigned int) MIN_IO_CHANNEL_SIZE);
+		POSTCODE_LINUX_4(VHBA_CREATE_FAILURE_PC, chan_bytes,
+				 MIN_IO_CHANNEL_SIZE, POSTCODE_SEVERITY_ERR);
+		return 0;
+	}
+	msg.cmd.createDevice.channelBytes = chan_bytes;
+	msg.cmd.createDevice.dataTypeGuid = UltraVhbaChannelProtocolGuid;
+	if (create_device(&msg, NULL) != CONTROLVM_RESP_SUCCESS) {
+		LOGERR("VHBA create_device failed.\n");
+		POSTCODE_LINUX_4(VHBA_CREATE_FAILURE_PC, devNo, busNo,
+				 POSTCODE_SEVERITY_ERR);
+		return 0;
+	}
+	POSTCODE_LINUX_4(VHBA_CREATE_SUCCESS_PC, devNo, busNo,
+			 POSTCODE_SEVERITY_INFO);
+	return 1;
+}
+EXPORT_SYMBOL_GPL(uislib_client_inject_add_vhba);
+
+int
+uislib_client_inject_del_vhba(U32 busNo, U32 devNo)
+{
+	return delete_device_glue(busNo, devNo);
+}
+EXPORT_SYMBOL_GPL(uislib_client_inject_del_vhba);
+
+int
+uislib_client_inject_add_vnic(U32 busNo, U32 devNo,
+			      U64 phys_chan_addr, U32 chan_bytes,
+			      int is_test_addr, GUID instGuid,
+			      struct InterruptInfo *intr)
+{
+	CONTROLVM_MESSAGE msg;
+
+	LOGINF(" enter busNo=0x%x devNo=0x%x\n", busNo, devNo);
+	/* chipset init'ed with bus bus has been previously created -
+	* Verify it still exists step 2: create the VNIC device on the
+	* bus
+	*/
+	POSTCODE_LINUX_4(VNIC_CREATE_ENTRY_PC, devNo, busNo,
+			 POSTCODE_SEVERITY_INFO);
+
+	init_msg_header(&msg, CONTROLVM_DEVICE_CREATE, 0, 0);
+	if (is_test_addr)
+		/* signify that the physical channel address does NOT
+		 * need to be ioremap()ed
+		 */
+		msg.hdr.Flags.testMessage = 1;
+	msg.cmd.createDevice.busNo = busNo;
+	msg.cmd.createDevice.devNo = devNo;
+	msg.cmd.createDevice.devInstGuid = instGuid;
+	if (intr)
+		msg.cmd.createDevice.intr = *intr;
+	else
+		memset(&msg.cmd.createDevice.intr, 0,
+		       sizeof(struct InterruptInfo));
+	msg.cmd.createDevice.channelAddr = phys_chan_addr;
+	if (chan_bytes < MIN_IO_CHANNEL_SIZE) {
+		LOGERR("wrong channel size.chan_bytes = 0x%x IO_CHANNEL_SIZE= 0x%x\n",
+		     chan_bytes, (unsigned int) MIN_IO_CHANNEL_SIZE);
+		POSTCODE_LINUX_4(VNIC_CREATE_FAILURE_PC, chan_bytes,
+				 MIN_IO_CHANNEL_SIZE, POSTCODE_SEVERITY_ERR);
+		return 0;
+	}
+	msg.cmd.createDevice.channelBytes = chan_bytes;
+	msg.cmd.createDevice.dataTypeGuid = UltraVnicChannelProtocolGuid;
+	if (create_device(&msg, NULL) != CONTROLVM_RESP_SUCCESS) {
+		LOGERR("VNIC create_device failed.\n");
+		POSTCODE_LINUX_4(VNIC_CREATE_FAILURE_PC, devNo, busNo,
+				 POSTCODE_SEVERITY_ERR);
+		return 0;
+	}
+
+	POSTCODE_LINUX_4(VNIC_CREATE_SUCCESS_PC, devNo, busNo,
+			 POSTCODE_SEVERITY_INFO);
+	return 1;
+}
+EXPORT_SYMBOL_GPL(uislib_client_inject_add_vnic);
+
+int
+uislib_client_inject_pause_vnic(U32 busNo, U32 devNo)
+{
+	CONTROLVM_MESSAGE msg;
+	int rc;
+
+	init_msg_header(&msg, CONTROLVM_DEVICE_CHANGESTATE, 0, 0);
+	msg.cmd.deviceChangeState.busNo = busNo;
+	msg.cmd.deviceChangeState.devNo = devNo;
+	msg.cmd.deviceChangeState.state = SegmentStateStandby;
+	rc = pause_device(&msg);
+	if (rc != CONTROLVM_RESP_SUCCESS) {
+		LOGERR("VNIC pause_device failed. busNo=0x%x devNo=0x%x\n",
+		       busNo, devNo);
+		return -1;
+	}
+	return 0;
+}
+EXPORT_SYMBOL_GPL(uislib_client_inject_pause_vnic);
+
+int
+uislib_client_inject_resume_vnic(U32 busNo, U32 devNo)
+{
+	CONTROLVM_MESSAGE msg;
+	int rc;
+
+	init_msg_header(&msg, CONTROLVM_DEVICE_CHANGESTATE, 0, 0);
+	msg.cmd.deviceChangeState.busNo = busNo;
+	msg.cmd.deviceChangeState.devNo = devNo;
+	msg.cmd.deviceChangeState.state = SegmentStateRunning;
+	rc = resume_device(&msg);
+	if (rc != CONTROLVM_RESP_SUCCESS) {
+		LOGERR("VNIC resume_device failed. busNo=0x%x devNo=0x%x\n",
+		       busNo, devNo);
+		return -1;
+	}
+	return 0;
+
+}
+EXPORT_SYMBOL_GPL(uislib_client_inject_resume_vnic);
+
+int
+uislib_client_inject_del_vnic(U32 busNo, U32 devNo)
+{
+	return delete_device_glue(busNo, devNo);
+}
+EXPORT_SYMBOL_GPL(uislib_client_inject_del_vnic);
+
+int
+uislib_client_add_vnic(U32 busNo)
+{
+	BOOL busCreated = FALSE;
+	int devNo = 0;		/* Default to 0, since only one device
+				 * will be created for this bus... */
+	GUID dummyGuid = GUID0;
+	CONTROLVM_MESSAGE msg;
+
+	init_msg_header(&msg, CONTROLVM_BUS_CREATE, 0, 0);
+	msg.hdr.Flags.testMessage = 1;
+	msg.cmd.createBus.busNo = busNo;
+	msg.cmd.createBus.deviceCount = 4;
+	msg.cmd.createBus.channelAddr = 0;
+	msg.cmd.createBus.channelBytes = 0;
+	if (create_bus(&msg, NULL) != CONTROLVM_RESP_SUCCESS) {
+		LOGERR("client create_bus failed");
+		return 0;
+	}
+	busCreated = TRUE;
+
+	init_msg_header(&msg, CONTROLVM_DEVICE_CREATE, 0, 0);
+	msg.hdr.Flags.testMessage = 1;
+	msg.cmd.createDevice.busNo = busNo;
+	msg.cmd.createDevice.devNo = devNo;
+	msg.cmd.createDevice.devInstGuid = dummyGuid;
+	memset(&msg.cmd.createDevice.intr, 0, sizeof(struct InterruptInfo));
+	msg.cmd.createDevice.channelAddr = PhysicalDataChan;
+	msg.cmd.createDevice.channelBytes = MIN_IO_CHANNEL_SIZE;
+	msg.cmd.createDevice.dataTypeGuid = UltraVnicChannelProtocolGuid;
+	if (create_device(&msg, NULL) != CONTROLVM_RESP_SUCCESS) {
+		LOGERR("client create_device failed");
+		goto AwayCleanup;
+	}
+
+	return 1;
+
+AwayCleanup:
+	if (busCreated) {
+		init_msg_header(&msg, CONTROLVM_BUS_DESTROY, 0, 0);
+		msg.hdr.Flags.testMessage = 1;
+		msg.cmd.destroyBus.busNo = busNo;
+		if (destroy_bus(&msg, NULL) != CONTROLVM_RESP_SUCCESS)
+			LOGERR("client destroy_bus failed.\n");
+	}
+
+	return 0;
+}				/* end uislib_client_add_vnic */
+EXPORT_SYMBOL_GPL(uislib_client_add_vnic);
+
+int
+uislib_client_delete_vnic(U32 busNo)
+{
+	int devNo = 0;		/* Default to 0, since only one device
+				 * will be created for this bus... */
+	CONTROLVM_MESSAGE msg;
+
+	init_msg_header(&msg, CONTROLVM_DEVICE_DESTROY, 0, 0);
+	msg.hdr.Flags.testMessage = 1;
+	msg.cmd.destroyDevice.busNo = busNo;
+	msg.cmd.destroyDevice.devNo = devNo;
+	if (destroy_device(&msg, NULL) != CONTROLVM_RESP_SUCCESS) {
+		/* Don't error exit - try to see if bus can be destroyed... */
+		LOGERR("client destroy_device failed.\n");
+	}
+
+	init_msg_header(&msg, CONTROLVM_BUS_DESTROY, 0, 0);
+	msg.hdr.Flags.testMessage = 1;
+	msg.cmd.destroyBus.busNo = busNo;
+	if (destroy_bus(&msg, NULL) != CONTROLVM_RESP_SUCCESS)
+		LOGERR("client destroy_bus failed.\n");
+
+	return 1;
+}
+EXPORT_SYMBOL_GPL(uislib_client_delete_vnic);
+
+				/* end client_delete_vnic */
+
+static atomic_t Malloc_BytesInUse = ATOMIC_INIT(0);
+static atomic_t Malloc_BuffersInUse = ATOMIC_INIT(0);
+static atomic_t Malloc_FailuresAlloc = ATOMIC_INIT(0);
+static atomic_t Malloc_FailuresFree = ATOMIC_INIT(0);
+static atomic_t Malloc_TotalMallocs = ATOMIC_INIT(0);
+static atomic_t Malloc_TotalFrees = ATOMIC_INIT(0);
+
+void *
+uislib_malloc(size_t siz, gfp_t gfp, U8 contiguous, char *fn, int ln)
+{
+	void *p = NULL;
+
+	if (contiguous == 0) {
+		/* Allocate non-contiguous memory, such as in the
+		* add_vnic and add_vhba methods where we are rebooting
+		* the guest, for example.  Otherwise the contiguous
+		* memory allocation attempt results in an
+		* out-of-memory crash in the IOVM...
+		*/
+		p = vmalloc(siz);
+	} else {
+		/* __GFP_NORETRY means "ok to fail", meaning kmalloc()
+		* can return NULL.  If you do NOT specify
+		* __GFP_NORETRY, Linux will go to extreme measures to
+		* get memory for you (like, invoke oom killer), which
+		* will probably cripple the system.
+		*/
+		p = kmalloc(siz, gfp | __GFP_NORETRY);
+	}
+	if (p == NULL) {
+		LOGERR("uislib_malloc failed to alloc %d bytes @%s:%d",
+		       (int) siz, fn, ln);
+		atomic_inc(&Malloc_FailuresAlloc);
+		return NULL;
+	}
+	atomic_add((int) (siz), &Malloc_BytesInUse);
+	atomic_inc(&Malloc_BuffersInUse);
+	atomic_inc(&Malloc_TotalMallocs);	/* will eventually overflow */
+	return p;
+}
+EXPORT_SYMBOL_GPL(uislib_malloc);
+
+void
+uislib_free(void *p, size_t siz, U8 contiguous, char *fn, int ln)
+{
+	if (p == NULL) {
+		LOGERR("uislib_free NULL pointer @%s:%d", fn, ln);
+		atomic_inc(&Malloc_FailuresFree);
+		return;
+	}
+
+	if (contiguous == 0)
+		vfree(p);
+	else
+		kfree(p);
+	atomic_sub((int) (siz), &Malloc_BytesInUse);
+	atomic_dec(&Malloc_BuffersInUse);
+	atomic_inc(&Malloc_TotalFrees);	/* will eventually overflow */
+}
+EXPORT_SYMBOL_GPL(uislib_free);
+
+void *
+uislib_cache_alloc(struct kmem_cache *cur_pool, char *fn, int ln)
+{
+	/* __GFP_NORETRY means "ok to fail", meaning kmalloc() can
+	* return NULL.  If you do NOT specify __GFP_NORETRY, Linux
+	* will go to extreme measures to get memory for you (like,
+	* invoke oom killer), which will probably cripple the system.
+	*/
+	void *p = kmem_cache_alloc(cur_pool, GFP_ATOMIC | __GFP_NORETRY);
+	if (p == NULL) {
+		LOGERR("uislib_malloc failed to alloc uiscmdrsp @%s:%d",
+		       fn, ln);
+		return NULL;
+	}
+	return p;
+}
+EXPORT_SYMBOL_GPL(uislib_cache_alloc);
+
+void
+uislib_cache_free(struct kmem_cache *cur_pool, void *p, char *fn, int ln)
+{
+	if (p == NULL) {
+		LOGERR("uislib_free NULL pointer @%s:%d", fn, ln);
+		return;
+	}
+	kmem_cache_free(cur_pool, p);
+}
+EXPORT_SYMBOL_GPL(uislib_cache_free);
+
+/*****************************************************/
+/* proc filesystem callback functions                */
+/*****************************************************/
+
+static ssize_t
+vnic_proc_write(struct file *file, const char __user *buffer,
+		size_t count, loff_t *ppos)
+{
+	int action = 0xffff, busNo = 0, i, result = 0;
+	char buf[count];
+	char direction;
+/* GUID guid; */
+	if (copy_from_user(buf, buffer, count)) {
+		LOGERR("echo > /proc/uislib/vnic copy_from_user ****FAILED.\n");
+		return -EFAULT;
+	}
+
+	i = sscanf(buf, "%d%c", &action, &direction);
+	if (i != 2) {
+		LOGERR("unable to parse vnic proc parameters.\n");
+		return -EFAULT;
+	}
+
+	if ((direction != '-') && (direction != '+')) {
+		LOGERR("unable to determine whether to add or delete vnic\n");
+		return -EFAULT;
+	}
+
+	/* if (i < 1), i.e., if we didn't even read the action field,
+	* then action will default to 0xffff and the code below will
+	* fall through the switch and print usage.
+	*/
+	switch (action) {
+	case 0:
+		/* call client method... */
+		busNo = 0;	/* All client drivers use bus value of 0... */
+		if (direction == '+')
+			result = uislib_client_add_vnic(busNo);
+		else
+			result = uislib_client_delete_vnic(busNo);
+		if (!result) {
+			LOGERR("echo 0%c > /proc/uislib/vnic failed (client end)",
+			     direction);
+			return -EFAULT;
+		}
+		return count;
+
+	default:
+		break;
+	}
+
+	LOGERR("USAGE: echo <action><direction (up/down)> > /proc/uislib/vnic");
+	LOGERR(" ");
+	LOGERR("Client Syntax");
+	LOGERR("-------------");
+	LOGERR("0+    ==> add vnic");
+	LOGERR("0-    ==> delete vnic");
+	LOGERR(" ");
+	return count;
+}				/* end vnic_proc_write */
+
+static ssize_t
+chipset_proc_write(struct file *file, const char __user *buffer,
+		   size_t count, loff_t *ppos)
+{
+	int i, action = 0xffff;
+	char buf[count];
+	CONTROLVM_MESSAGE msg;
+
+	memset(&msg, 0, sizeof(CONTROLVM_MESSAGE));
+
+	if (copy_from_user(buf, buffer, count)) {
+		LOGERR("copy_from_user ****FAILED.\n");
+		return -EFAULT;
+	}
+
+	if (chipset_inited) {
+		LOGINF("Chipset already initialized\n");
+		return -EFAULT;
+	}
+	i = sscanf(buf, "%x", &action);
+
+	/* if (i < 1), i.e., if we didn't even read the action field,
+	* then action will default to 0xffff and the code below will
+	* fall through the switch and print usage.
+	*/
+	switch (action) {
+	case 1:
+		/* GUEST */
+		/* step: initialize the chipset */
+		init_msg_header(&msg, CONTROLVM_CHIPSET_INIT, 0, 0);
+		msg.hdr.Flags.testMessage = 0;
+		msg.cmd.initChipset.busCount = 23;
+		msg.cmd.initChipset.switchCount = 23;
+
+		if (init_chipset(&msg, NULL) != CONTROLVM_RESP_SUCCESS) {
+			LOGERR("init_chipset failed.\n");
+			return 0;
+		}
+		return 1;
+	case 2:
+		/* BOTH */
+		init_msg_header(&msg, CONTROLVM_CHIPSET_INIT, 0, 0);
+		msg.hdr.Flags.testMessage = 1;
+		msg.cmd.initChipset.busCount = 23;
+		msg.cmd.initChipset.switchCount = 23;
+
+		if (init_chipset(&msg, NULL) != CONTROLVM_RESP_SUCCESS) {
+			LOGERR("init_chipset failed.\n");
+			return 0;
+		}
+		return 1;
+
+	default:
+		break;
+	}
+
+	LOGERR("usage: 1 ==> init_chipset client\n");
+	LOGERR("usage: 2 ==> init_chipset test\n");
+	return -EFAULT;
+}
+
+#define PROCLINE(...)							\
+	do {								\
+		if (util_add_proc_line_ex(&tot, buff,			\
+					  buff_len, __VA_ARGS__) < 0) {	\
+			goto err_done;					\
+		}							\
+	} while (0)
+
+static int
+info_proc_read_helper(char **buff, int *buff_len)
+{
+	int i, tot = 0;
+	struct bus_info *bus;
+
+	PROCLINE("\nBuses:\n");
+
+	read_lock(&BusListLock);
+	for (bus = BusListHead; bus; bus = bus->next) {
+
+		PROCLINE("    bus=0x%p, busNo=%d, deviceCount=%d\n",
+			 bus, bus->busNo, bus->deviceCount);
+
+		PROCLINE("        Devices:\n");
+
+		for (i = 0; i < bus->deviceCount; i++) {
+			if (bus->device[i]) {
+				PROCLINE("            busNo %d, device[%i]: 0x%p, chanptr=0x%p, swtch=0x%p\n",
+				     bus->busNo, i, bus->device[i],
+				     bus->device[i]->chanptr,
+				     bus->device[i]->swtch);
+				PROCLINE("            first_busy_cnt=%llu, moved_to_tail_cnt=%llu, last_on_list_cnt=%llu\n",
+				     bus->device[i]->first_busy_cnt,
+				     bus->device[i]->moved_to_tail_cnt,
+				     bus->device[i]->last_on_list_cnt);
+			}
+		}
+	}
+	read_unlock(&BusListLock);
+
+	PROCLINE("Malloc bytes in use: %d\n", atomic_read(&Malloc_BytesInUse));
+	PROCLINE("Malloc buffers in use: %d\n",
+		 atomic_read(&Malloc_BuffersInUse));
+	PROCLINE("Malloc allocation failures: %d\n",
+		 atomic_read(&Malloc_FailuresAlloc));
+	PROCLINE("Malloc free failures: %d\n",
+		 atomic_read(&Malloc_FailuresFree));
+	PROCLINE("Malloc total mallocs: %u (may overflow)\n",
+		 (unsigned) atomic_read(&Malloc_TotalMallocs));
+	PROCLINE("Malloc total frees: %u (may overflow)\n",
+		 (unsigned) atomic_read(&Malloc_TotalFrees));
+	PROCLINE("UisUtils_Registered_Services: %d\n",
+		 atomic_read(&UisUtils_Registered_Services));
+
+	PROCLINE("cycles_before_wait %llu wait_cycles:%llu\n",
+		 cycles_before_wait, wait_cycles);
+	PROCLINE("tot_wakeup_cnt %llu:tot_wait_cnt %llu:tot_schedule_cnt %llu\n",
+	     tot_wakeup_cnt, tot_wait_cnt, tot_schedule_cnt);
+	PROCLINE("en_smart_wakeup %d\n", en_smart_wakeup);
+	PROCLINE("tot_moved_to_tail_cnt %llu\n", tot_moved_to_tail_cnt);
+
+	return tot;
+err_done:
+
+	return -1;
+}
+
+static ssize_t
+info_proc_read(struct file *file, char __user *buf, size_t len, loff_t *offset)
+{
+	char *temp;
+	int totalBytes = 0;
+	int remaining_bytes = PROC_READ_BUFFER_SIZE;
+
+/* *start = buf; */
+	if (ProcReadBuffer == NULL) {
+		DBGINF("ProcReadBuffer == NULL; allocating buffer.\n.");
+		ProcReadBuffer = UISVMALLOC(PROC_READ_BUFFER_SIZE);
+
+		if (ProcReadBuffer == NULL) {
+			LOGERR("failed to allocate buffer to provide proc data.\n");
+			return -ENOMEM;
+		}
+	}
+
+	temp = ProcReadBuffer;
+
+	if ((*offset == 0) || (!ProcReadBufferValid)) {
+		DBGINF("calling info_proc_read_helper.\n");
+		/* if the read fails, then -1 will be returned */
+		totalBytes = info_proc_read_helper(&temp, &remaining_bytes);
+		ProcReadBufferValid = 1;
+	} else
+		totalBytes = strlen(ProcReadBuffer);
+
+	return simple_read_from_buffer(buf, len, offset,
+				       ProcReadBuffer, totalBytes);
+}
+
+static ssize_t
+platformnumber_proc_read(struct file *file, char __user *buf,
+			 size_t len, loff_t *offset)
+{
+	int length = 0;
+	char *vbuf;
+	loff_t pos = *offset;
+
+	if (pos < 0)
+		return -EINVAL;
+
+	if (pos > 0 || !len)
+		return 0;
+
+	vbuf = kzalloc(len, GFP_KERNEL);
+	if (!vbuf)
+		return -ENOMEM;
+
+	length = sprintf(vbuf, "%d\n", PlatformNumber);
+
+	if (copy_to_user(buf, vbuf, length)) {
+		kfree(vbuf);
+		return -EFAULT;
+	}
+
+	kfree(vbuf);
+	*offset += length;
+	return length;
+}
+
+#ifdef UISLIB_TEST_PROC
+
+/* proc/uislib/vbus/<x>/info */
+static int
+proc_info_vbus_show(struct seq_file *m, void *v)
+{
+	struct bus_info *bus = m->private;
+	int i, devInfoCount, x;
+	char buf[999];
+
+	if (bus == NULL)
+		return 0;
+	seq_printf(m, "Client device / client driver info for %s partition (vbus #%d):\n",
+		   bus->partitionName, bus->busNo);
+	if ((bus->busChannelBytes == 0) || (bus->pBusChannel == NULL))
+		return 0;
+	devInfoCount =
+	    (bus->busChannelBytes -
+	     sizeof(ULTRA_VBUS_CHANNEL_PROTOCOL)) /
+	    sizeof(ULTRA_VBUS_DEVICEINFO);
+	x = VBUSCHANNEL_devInfoToStringBuffer(bus->pBusChannel->ChpInfo, buf,
+					      sizeof(buf) - 1, -1);
+	buf[x] = '\0';
+	seq_printf(m, "%s", buf);
+	x = VBUSCHANNEL_devInfoToStringBuffer(bus->pBusChannel->BusInfo,
+					      buf, sizeof(buf) - 1, -1);
+	buf[x] = '\0';
+	seq_printf(m, "%s", buf);
+	for (i = 0; i < devInfoCount; i++) {
+		x = VBUSCHANNEL_devInfoToStringBuffer(bus->pBusChannel->
+						      DevInfo[i], buf,
+						      sizeof(buf) - 1, i);
+		if (x > 0) {
+			buf[x] = '\0';
+			seq_printf(m, "%s", buf);
+		}
+	}
+	return 0;
+}
+
+static ssize_t
+bus_proc_write(struct file *file, const char __user *buffer,
+	       size_t count, loff_t *ppos)
+{
+	int server_flag = 0;
+	int i, action = 0xffff, result;
+	char buf[count];
+	CONTROLVM_MESSAGE msg;
+	U32 busNo, deviceCount;
+
+	memset(&msg, 0, sizeof(CONTROLVM_MESSAGE));
+
+	if (copy_from_user(buf, buffer, count)) {
+		LOGERR("echo > /proc/uislib/bus: copy_from_user ****FAILED.");
+		return -EFAULT;
+	}
+
+	i = sscanf(buf, "%x-%d-%d", &action, &busNo, &deviceCount);
+
+	/* if (i < 1), i.e., if we didn't even read the action field,
+	* then action will default to 0xffff and the code below will
+	* fall through the switch and print usage.
+	*/
+	switch (action) {
+	case 0:
+		/* destroy a bus */
+		if (i != 2)
+			break;
+		init_msg_header(&msg, CONTROLVM_BUS_DESTROY, 0, server_flag);
+		msg.cmd.destroyBus.busNo = busNo;
+
+		result = destroy_bus(&msg, NULL);
+
+		if (result != CONTROLVM_RESP_SUCCESS) {
+			LOGERR("echo 0-%d > /proc/uislib/bus {CONTROLVM_BUS_DESTROY Failed} Result(%d)",
+			     busNo, result);
+			return -EFAULT;
+		}
+		return count;
+	case 1:
+		/* create a bus */
+		if (i != 3)
+			break;
+		init_msg_header(&msg, CONTROLVM_BUS_CREATE, 0, server_flag);
+		msg.cmd.createBus.busNo = busNo;
+		msg.cmd.createBus.deviceCount = deviceCount;
+
+		result = create_bus(&msg, NULL);
+
+		if (result != CONTROLVM_RESP_SUCCESS) {
+			LOGERR("echo 1-%d-%d > /proc/uislib/bus {CONTROLVM_BUS_CREATE Failed} Result(%d)",
+			     busNo, deviceCount, result);
+			return -EFAULT;
+		}
+
+		return count;
+	default:
+		break;
+	}
+
+	LOGERR("USAGE: echo <action>-<busNo>... > /proc/uislib/bus");
+	LOGERR(" ");
+	LOGERR("Destruct Syntax     ControlVM Message Id");
+	LOGERR("---------------     ---------------------");
+	LOGERR("0-<busNo>       ==> CONTROLVM_BUS_DESTROY");
+	LOGERR(" ");
+	LOGERR("Construct Syntax            ControlVM Message Id");
+	LOGERR("-----------------------     -------------------- ");
+	LOGERR("1-<busNo>-<deviceCount> ==> CONTROLVM_BUS_CREATE");
+
+	return -EFAULT;
+}
+
+static ssize_t
+uislib_proc_read_writeonly(struct file *file, char __user *buffer,
+	       size_t count, loff_t *ppos)
+{
+	return 0;
+}
+
+static ssize_t
+dev_proc_write(struct file *file, const char __user *buffer,
+	       size_t count, loff_t *ppos)
+{
+	int server_flag = 0;
+	CONTROLVM_MESSAGE msg;
+	U32 busNo, devNo;
+	char buf[count];
+	unsigned int chanptr;
+	int type, i, action = 0xffff, result;
+
+	if (copy_from_user(buf, buffer, count)) {
+		LOGERR("echo > /proc/uislib/device: copy_from_user ****FAILED.");
+		return -EFAULT;
+	}
+
+	i = sscanf(buf, "%x-%d-%d-%x-%d",
+		   &action, &busNo, &devNo, &chanptr, &type);
+
+	switch (action) {
+	case 0:
+		if (i != 3)
+			break;
+
+		/* destroy a device */
+		init_msg_header(&msg, CONTROLVM_DEVICE_DESTROY, 0, server_flag);
+		msg.cmd.destroyDevice.busNo = busNo;
+		msg.cmd.destroyDevice.devNo = devNo;
+
+		result = destroy_device(&msg, NULL);
+
+		if (result != CONTROLVM_RESP_SUCCESS) {
+			LOGERR("echo 0-%d-%d > /proc/uislib/device {CONTROLVM_DEVICE_DESTROY Failed} Result(%d)",
+			     busNo, devNo, result);
+			return -EFAULT;
+		}
+
+		return count;
+
+	case 1:
+		if (i != 5)
+			break;
+
+		/* create a device */
+		init_msg_header(&msg, CONTROLVM_DEVICE_CREATE, 0, server_flag);
+		msg.cmd.createDevice.busNo = busNo;
+		msg.cmd.createDevice.devNo = devNo;
+		msg.cmd.createDevice.channelAddr = __pa(chanptr);
+		msg.cmd.createDevice.channelBytes = MIN_IO_CHANNEL_SIZE;
+
+		if (type == 0)
+			msg.cmd.createDevice.dataTypeGuid =
+			    UltraVhbaChannelProtocolGuid;
+		else if (type == 1)
+			msg.cmd.createDevice.dataTypeGuid =
+			    UltraVnicChannelProtocolGuid;
+		else {
+			LOGERR("echo 1-%d-%d-%x-<type> > /proc/uislib/devce failed: invalid device type %d.",
+			     busNo, devNo, chanptr, type);
+			return -EFAULT;
+		}
+
+		result = create_device(&msg, NULL);
+
+		if (result != CONTROLVM_RESP_SUCCESS) {
+			if (type == 0)
+				LOGERR("echo 1-%d-%d-%x-0 > /proc/uislib/device {CONTROLVM_DEVICE_CREATE[vHBA] Failed} Result(%d)",
+				     busNo, devNo, chanptr, result);
+			else
+				LOGERR("echo 1-%d-%d-%x-1 > /proc/uislib/device {CONTROLVM_DEVICE_CREATE[vNIC] Failed} Result(%d)",
+				     busNo, devNo, chanptr, result);
+			return -EFAULT;
+		}
+
+	default:
+		break;
+	}
+
+	LOGERR("USAGE: echo <action>-<busNo>-<devNo>... > /proc/uislib/device");
+	LOGERR(" ");
+	LOGERR("Destruct Syntax       ControlVM Message Id");
+	LOGERR("-----------------     ------------------------");
+	LOGERR("0-<busNo>-<devNo> ==> CONTROLVM_DEVICE_DESTROY");
+	LOGERR(" ");
+	LOGERR("Construct Syntax                       ControlVM Message Id");
+	LOGERR
+	    ("----------------------------------     ----------------------- ");
+	LOGERR
+	    ("1-<busNo>-<devNo>-<chanptr>-<type> ==> CONTROLVM_DEVICE_CREATE");
+	LOGERR("      <type = 0>: vHBA");
+	LOGERR("      <type = 1>: vNIC");
+	LOGERR(" ");
+
+	return -EFAULT;
+}
+
+static ssize_t
+cycles_before_wait_proc_write(struct file *file, const char __user *buffer,
+			      size_t count, loff_t *ppos)
+{
+	char buf[count];
+
+#define CYCLES_BEFORE_WAIT_USE_ERROR  { \
+	LOGERR("Incorrect Call Home Input.\n"); \
+	pr_info("Please pass Call Home Event Parameters in the form:\n"); \
+	pr_info("EventID Category Type[parameter1][parameter2][parameter3][parameter4][parameter5][parameter6]\n"); \
+	return -EFAULT; \
+}
+
+	if (count == 0)
+		CYCLES_BEFORE_WAIT_USE_ERROR;
+
+	if (copy_from_user(buf, buffer, count)) {
+		LOGERR("copy_from_user failed.\n");
+		return -EFAULT;
+	}
+	buf[count - 1] = '\0';	/* Replace the LF at the end of the
+				 * input with a NULL */
+	/* Pull out the cycles_before_wait must be decimal integer */
+	if (sscanf(buf, "%lld", &cycles_before_wait) != 1)
+		CYCLES_BEFORE_WAIT_USE_ERROR;
+
+	return count;
+}
+
+static ssize_t
+reset_counts_proc_write(struct file *file, const char __user *buffer,
+			size_t count, loff_t *ppos)
+{
+	char buf[count];
+	unsigned long long new_value;
+	struct bus_info *bus;
+	int i;
+
+#define RESET_COUNTS_USE_ERROR  { \
+	LOGERR("Incorrect reset_counts Input.\n"); \
+	pr_info("Please pass the new value for the counters:\n"); \
+	pr_info("e.g. echo 0 > reset_counts\n"); \
+	return -EFAULT; \
+	}
+
+	if (count == 0)
+		RESET_COUNTS_USE_ERROR;
+
+	if (copy_from_user(buf, buffer, count)) {
+		LOGERR("copy_from_user failed.\n");
+		return -EFAULT;
+	}
+	buf[count - 1] = '\0';	/* Replace the LF at the end of the
+				 * input with a NULL */
+	/* Pull out the reset_counts must be decimal integer */
+	if (sscanf(buf, "%llu", &new_value) != 1)
+		RESET_COUNTS_USE_ERROR;
+	read_lock(&BusListLock);
+	for (bus = BusListHead; bus; bus = bus->next) {
+
+		for (i = 0; i < bus->deviceCount; i++) {
+			if (bus->device[i]) {
+				bus->device[i]->first_busy_cnt = new_value;
+				bus->device[i]->moved_to_tail_cnt = new_value;
+				bus->device[i]->last_on_list_cnt = new_value;
+			}
+		}
+	}
+	read_unlock(&BusListLock);
+	tot_moved_to_tail_cnt = new_value;
+	tot_wait_cnt = new_value;
+	tot_wakeup_cnt = new_value;
+	tot_schedule_cnt = new_value;
+	return count;
+}
+
+static ssize_t
+smart_wakeup_proc_write(struct file *file, const char __user *buffer,
+			size_t count, loff_t *ppos)
+{
+	char buf[count];
+	int new_value;
+
+#define SMART_WAKEUP_USE_ERROR  { \
+	LOGERR("Incorrect smart_wakeup Input 0 disables smart_wakeup, and 1 enables smart_wakeup.\n"); \
+	pr_info("echo 0 > smart_wakeup\n"); \
+	pr_info("echo 1 > smart_wakeup\n"); \
+	return -EFAULT; \
+	}
+
+	if (count == 0)
+		SMART_WAKEUP_USE_ERROR;
+
+	if (copy_from_user(buf, buffer, count)) {
+		LOGERR("copy_from_user failed.\n");
+		return -EFAULT;
+	}
+	buf[count - 1] = '\0';	/* Replace the LF at the end of the
+				 * input with a NULL */
+	/* Pull out the smart_wakeup must be decimal integer */
+	if (sscanf(buf, "%d", &new_value) != 1)
+		SMART_WAKEUP_USE_ERROR;
+	en_smart_wakeup = new_value;
+	return count;
+}
+
+static ssize_t
+test_proc_write(struct file *file, const char __user *buffer,
+		size_t count, loff_t *ppos)
+{
+	int i, action = 0xffff;
+	char buf[count];
+	CONTROLVM_MESSAGE msg;
+	S64 vrtc_offset;
+
+	memset(&msg, 0, sizeof(CONTROLVM_MESSAGE));
+
+	if (copy_from_user(buf, buffer, count)) {
+		LOGERR("copy_from_user ****FAILED.\n");
+		return -EFAULT;
+	}
+
+	i = sscanf(buf, "%x", &action);
+
+	/* if (i < 1), i.e., if we didn't even read the action field,
+	* then action will default to 0xffff and the code below will
+	* fall through the switch and print usage. */
+	switch (action) {
+	case 6:
+		msg.hdr.Id = CONTROLVM_CHIPSET_STOP;
+		msg.hdr.Flags.responseExpected = 1;
+		stop_chipset(&msg, NULL);
+		break;
+	case 7:
+		vrtc_offset = 0;
+		LOGERR("about to issue QUERY vrtc_offset=%LX", vrtc_offset);
+		vrtc_offset = Issue_VMCALL_QUERY_GUEST_VIRTUAL_TIME_OFFSET();
+		LOGERR("result is vrtc_offset=%LX", vrtc_offset);
+		break;
+	case 8:
+		vrtc_offset = 60;
+		LOGERR("about to increase physical time by 0x%LX seconds",
+		       vrtc_offset);
+		vrtc_offset = Issue_VMCALL_UPDATE_PHYSICAL_TIME(vrtc_offset);
+		break;
+	case 9:
+		vrtc_offset = -60;
+		LOGERR("about to decrease physical time by 0x%LX seconds",
+		       vrtc_offset);
+		vrtc_offset = Issue_VMCALL_UPDATE_PHYSICAL_TIME(vrtc_offset);
+		break;
+	default:
+		LOGERR("usage: 6 for CHIPSET_STOP\n");
+		LOGERR("       7 for VMCALL_QUERY_GUEST_VIRTUAL_TIME_OFFSET()\n");
+		LOGERR("       8 for VMCALL_UPDATE_PHYSICAL_TIME(60)\n");
+		LOGERR("       9 for VMCALL_UPDATE_PHYSICAL_TIME(-60)\n");
+		return -EFAULT;
+		break;
+	}
+	return count;
+}
+
+#endif				/* UISLIB_TEST_PROC */
+static struct device_info *
+find_dev(U32 busNo, U32 devNo)
+{
+	struct bus_info *bus;
+	struct device_info *dev = NULL;
+
+	read_lock(&BusListLock);
+	for (bus = BusListHead; bus; bus = bus->next) {
+		if (bus->busNo == busNo) {
+			/* make sure the device number is valid */
+			if (devNo >= bus->deviceCount) {
+				LOGERR("%s bad busNo, devNo=%d,%d",
+				       __func__,
+				       (int) (busNo), (int) (devNo));
+				goto Away;
+			}
+			dev = bus->device[devNo];
+			if (!dev)
+				LOGERR("%s bad busNo, devNo=%d,%d",
+				       __func__,
+				       (int) (busNo), (int) (devNo));
+			goto Away;
+		}
+	}
+Away:
+	read_unlock(&BusListLock);
+	return dev;
+}
+
+/*  This thread calls the "interrupt" function for each device that has
+ *  enabled such using uislib_enable_channel_interrupts().  The "interrupt"
+ *  function typically reads and processes the devices's channel input
+ *  queue.  This thread repeatedly does this, until the thread is told to stop
+ *  (via uisthread_stop()).  Sleeping rules:
+ *  - If we have called the "interrupt" function for all devices, and all of
+ *    them have reported "nothing processed" (returned 0), then we will go to
+ *    sleep for a maximum of POLLJIFFIES_NORMAL jiffies.
+ *  - If anyone calls uislib_force_channel_interrupt(), the above jiffy
+ *    sleep will be interrupted, and we will resume calling the "interrupt"
+ *    function for all devices.
+ *  - The list of devices is dynamically re-ordered in order to
+ *    attempt to preserve fairness.  Whenever we spin thru the list of
+ *    devices and call the dev->interrupt() function, if we find
+ *    devices which report that there is still more work to do, the
+ *    the first such device we find is moved to the end of the device
+ *    list.  This ensures that extremely busy devices don't starve out
+ *    less-busy ones.
+ *
+ */
+static int
+Process_Incoming(void *v)
+{
+	unsigned long long cur_cycles, old_cycles, idle_cycles, delta_cycles;
+	struct list_head *new_tail = NULL;
+	int i;
+	UIS_DAEMONIZE("dev_incoming");
+	for (i = 0; i < 16; i++) {
+		old_cycles = get_cycles();
+		wait_event_timeout(Wakeup_Polling_Device_Channels,
+				   0, POLLJIFFIES_NORMAL);
+		cur_cycles = get_cycles();
+		if (wait_cycles == 0) {
+			wait_cycles = (cur_cycles - old_cycles);
+		} else {
+			if (wait_cycles < (cur_cycles - old_cycles))
+				wait_cycles = (cur_cycles - old_cycles);
+		}
+	}
+	LOGINF("wait_cycles=%llu", wait_cycles);
+	cycles_before_wait = wait_cycles;
+	idle_cycles = 0;
+	Go_Polling_Device_Channels = 0;
+	while (1) {
+		struct list_head *lelt, *tmp;
+		struct device_info *dev = NULL;
+
+		/* poll each channel for input */
+		LOCKSEM_UNINTERRUPTIBLE(&Lock_Polling_Device_Channels);
+		new_tail = NULL;
+		list_for_each_safe(lelt, tmp, &List_Polling_Device_Channels) {
+			int rc = 0;
+			dev = list_entry(lelt, struct device_info,
+					 list_polling_device_channels);
+			LOCKSEM_UNINTERRUPTIBLE(&dev->interrupt_callback_lock);
+			if (dev->interrupt)
+				rc = dev->interrupt(dev->interrupt_context);
+			else
+				continue;
+			UNLOCKSEM(&dev->interrupt_callback_lock);
+			if (rc) {
+				/* dev->interrupt returned, but there
+				* is still more work to do.
+				* Reschedule work to occur as soon as
+				* possible. */
+				idle_cycles = 0;
+				if (new_tail == NULL) {
+					dev->first_busy_cnt++;
+					if (!
+					    (list_is_last
+					     (lelt,
+					      &List_Polling_Device_Channels))) {
+						new_tail = lelt;
+						dev->moved_to_tail_cnt++;
+					} else
+						dev->last_on_list_cnt++;
+				}
+
+			}
+			if (Incoming_ThreadInfo.should_stop)
+				break;
+		}
+		if (new_tail != NULL) {
+			tot_moved_to_tail_cnt++;
+			list_move_tail(new_tail, &List_Polling_Device_Channels);
+		}
+		UNLOCKSEM(&Lock_Polling_Device_Channels);
+		cur_cycles = get_cycles();
+		delta_cycles = cur_cycles - old_cycles;
+		old_cycles = cur_cycles;
+
+		/* At this point, we have scanned thru all of the
+		* channels, and at least one of the following is true:
+		* - there is no input waiting on any of the channels
+		* - we have received a signal to stop this thread
+		*/
+		if (Incoming_ThreadInfo.should_stop)
+			break;
+		if (en_smart_wakeup == 0xFF) {
+			LOGINF("en_smart_wakeup set to 0xff, to force exiting process_incoming");
+			break;
+		}
+		/* wait for POLLJIFFIES_NORMAL jiffies, or until
+		* someone wakes up Wakeup_Polling_Device_Channels,
+		* whichever comes first only do a wait when we have
+		* been idle for cycles_before_wait cycles.
+		*/
+		if (idle_cycles > cycles_before_wait) {
+			Go_Polling_Device_Channels = 0;
+			tot_wait_cnt++;
+			wait_event_timeout(Wakeup_Polling_Device_Channels,
+					   Go_Polling_Device_Channels,
+					   POLLJIFFIES_NORMAL);
+			Go_Polling_Device_Channels = 1;
+		} else {
+			tot_schedule_cnt++;
+			schedule();
+			idle_cycles = idle_cycles + delta_cycles;
+		}
+	}
+	DBGINF("exiting.\n");
+	complete_and_exit(&Incoming_ThreadInfo.has_stopped, 0);
+}
+
+static BOOL
+Initialize_incoming_thread(void)
+{
+	if (Incoming_Thread_Started)
+		return TRUE;
+	if (!uisthread_start(&Incoming_ThreadInfo,
+			     &Process_Incoming, NULL, "dev_incoming")) {
+		LOGERR("uisthread_start Initialize_incoming_thread ****FAILED");
+		return FALSE;
+	}
+	Incoming_Thread_Started = TRUE;
+	return TRUE;
+}
+
+/*  Add a new device/channel to the list being processed by
+ *  Process_Incoming().
+ *  <interrupt> - indicates the function to call periodically.
+ *  <interrupt_context> - indicates the data to pass to the <interrupt>
+ *                        function.
+ */
+void
+uislib_enable_channel_interrupts(U32 busNo, U32 devNo,
+				 int (*interrupt)(void *),
+				 void *interrupt_context)
+{
+	struct device_info *dev;
+	dev = find_dev(busNo, devNo);
+	if (!dev) {
+		LOGERR("%s busNo=%d, devNo=%d", __func__, (int) (busNo),
+		       (int) (devNo));
+		return;
+	}
+	LOCKSEM_UNINTERRUPTIBLE(&Lock_Polling_Device_Channels);
+	Initialize_incoming_thread();
+	dev->interrupt = interrupt;
+	dev->interrupt_context = interrupt_context;
+	dev->polling = TRUE;
+	list_add_tail(&(dev->list_polling_device_channels),
+		      &List_Polling_Device_Channels);
+	UNLOCKSEM(&Lock_Polling_Device_Channels);
+}
+EXPORT_SYMBOL_GPL(uislib_enable_channel_interrupts);
+
+/*  Remove a device/channel from the list being processed by
+ *  Process_Incoming().
+ */
+void
+uislib_disable_channel_interrupts(U32 busNo, U32 devNo)
+{
+	struct device_info *dev;
+	dev = find_dev(busNo, devNo);
+	if (!dev) {
+		LOGERR("%s busNo=%d, devNo=%d", __func__, (int) (busNo),
+		       (int) (devNo));
+		return;
+	}
+	LOCKSEM_UNINTERRUPTIBLE(&Lock_Polling_Device_Channels);
+	list_del(&dev->list_polling_device_channels);
+	dev->polling = FALSE;
+	dev->interrupt = NULL;
+	UNLOCKSEM(&Lock_Polling_Device_Channels);
+}
+EXPORT_SYMBOL_GPL(uislib_disable_channel_interrupts);
+
+static void
+do_wakeup_polling_device_channels(struct work_struct *dummy)
+{
+	if (!Go_Polling_Device_Channels) {
+		Go_Polling_Device_Channels = 1;
+		wake_up(&Wakeup_Polling_Device_Channels);
+	}
+}
+
+DECLARE_WORK(Work_wakeup_polling_device_channels,
+	     do_wakeup_polling_device_channels);
+
+/*  Call this function when you want to send a hint to Process_Incoming() that
+ *  your device might have more requests.
+ */
+void
+uislib_force_channel_interrupt(U32 busNo, U32 devNo)
+{
+	if (en_smart_wakeup == 0)
+		return;
+	if (Go_Polling_Device_Channels)
+		return;
+	/* The point of using schedule_work() instead of just doing
+	 * the work inline is to force a slight delay before waking up
+	 * the Process_Incoming() thread.
+	 */
+	tot_wakeup_cnt++;
+	schedule_work(&Work_wakeup_polling_device_channels);
+}
+EXPORT_SYMBOL_GPL(uislib_force_channel_interrupt);
+
+/*****************************************************/
+/* Module Init & Exit functions                      */
+/*****************************************************/
+
+static int __init
+uislib_mod_init(void)
+{
+
+	LOGINF("MONITORAPIS");
+
+	LOGINF("sizeof(struct uiscmdrsp):%lu bytes\n",
+	       (ulong) sizeof(struct uiscmdrsp));
+	LOGINF("sizeof(struct phys_info):%lu\n",
+	       (ulong) sizeof(struct phys_info));
+	LOGINF("sizeof(uiscmdrsp_scsi):%lu\n",
+	       (ulong) sizeof(struct uiscmdrsp_scsi));
+	LOGINF("sizeof(uiscmdrsp_net):%lu\n",
+	       (ulong) sizeof(struct uiscmdrsp_net));
+	LOGINF("sizeof(CONTROLVM_MESSAGE):%lu bytes\n",
+	       (ulong) sizeof(CONTROLVM_MESSAGE));
+	LOGINF("sizeof(ULTRA_CONTROLVM_CHANNEL_PROTOCOL):%lu bytes\n",
+	       (ulong) sizeof(ULTRA_CONTROLVM_CHANNEL_PROTOCOL));
+	LOGINF("sizeof(CHANNEL_HEADER):%lu bytes\n",
+	       (ulong) sizeof(CHANNEL_HEADER));
+	LOGINF("sizeof(ULTRA_IO_CHANNEL_PROTOCOL):%lu bytes\n",
+	       (ulong) sizeof(ULTRA_IO_CHANNEL_PROTOCOL));
+	LOGINF("SIZEOF_CMDRSP:%lu bytes\n", SIZEOF_CMDRSP);
+	LOGINF("SIZEOF_PROTOCOL:%lu bytes\n", SIZEOF_PROTOCOL);
+
+	/* initialize global pointers to NULL */
+	BusListHead = NULL;
+	BusListCount = MaxBusCount = 0;
+	rwlock_init(&BusListLock);
+	VirtControlChanFunc = NULL;
+
+	/* Issue VMCALL_GET_CONTROLVM_ADDR to get CtrlChanPhysAddr and
+	 * then map this physical address to a virtual address. */
+	POSTCODE_LINUX_2(DRIVER_ENTRY_PC, POSTCODE_SEVERITY_INFO);
+
+	/* create the proc entries for the channels */
+	uislib_proc_dir = proc_mkdir(DIR_PROC_ENTRY, NULL);
+	/* (e.g., for /proc/uislib/vbus/<x>/info) */
+	uislib_proc_vbus_dir = proc_mkdir(DIR_VBUS_PROC_ENTRY, uislib_proc_dir);
+
+	vnic_proc_entry = proc_create(VNIC_PROC_ENTRY_FN, 0, uislib_proc_dir,
+				      &proc_vnic_fops);
+	SET_PROC_OWNER(vnic_proc_entry, THIS_MODULE);
+
+	/* for testing purposes only, create the proc entries for
+	 * enqueuing Control Channel messages */
+	chipset_proc_entry =
+	    proc_create(CHIPSET_PROC_ENTRY_FN, 0, uislib_proc_dir,
+			&proc_chipset_fops);
+	SET_PROC_OWNER(chipset_proc_entry, THIS_MODULE);
+
+	info_proc_entry = proc_create(INFO_PROC_ENTRY_FN, 0, uislib_proc_dir,
+				      &proc_info_fops);
+	SET_PROC_OWNER(info_proc_entry, THIS_MODULE);
+
+	platformnumber_proc_entry =
+	    proc_create(PLATFORMNUMBER_PROC_ENTRY_FN, 0, uislib_proc_dir,
+			&proc_platformnumber_fops);
+	SET_PROC_OWNER(platformnumberinfo_proc_entry, THIS_MODULE);
+
+	cycles_before_wait_proc_entry =
+	    proc_create(CYCLES_BEFORE_WAIT_PROC_ENTRY_FN, 0, uislib_proc_dir,
+			&proc_cycles_before_wait_fops);
+	SET_PROC_OWNER(cycles_before_wait_proc_entry, THIS_MODULE);
+
+	reset_counts_proc_entry =
+	    proc_create(RESET_COUNTS_PROC_ENTRY_FN, 0, uislib_proc_dir,
+			&proc_reset_counts_fops);
+	SET_PROC_OWNER(reset_counts_proc_entry, THIS_MODULE);
+
+	smart_wakeup_proc_entry =
+	    proc_create(SMART_WAKEUP_PROC_ENTRY_FN, 0, uislib_proc_dir,
+			&proc_smart_wakeup_fops);
+	SET_PROC_OWNER(smart_wakeup_proc_entry, THIS_MODULE);
+
+#ifdef UISLIB_TEST_PROC
+	test_proc_entry = proc_create(TEST_PROC_ENTRY_FN, 0, uislib_proc_dir,
+				      &proc_test_fops);
+	SET_PROC_OWNER(test_proc_entry, THIS_MODULE);
+
+	bus_proc_entry = proc_create(BUS_PROC_ENTRY_FN, 0, uislib_proc_dir,
+				     &proc_bus_fops);
+	SET_PROC_OWNER(bus_proc_entry, THIS_MODULE);
+
+	dev_proc_entry = proc_create(DEV_PROC_ENTRY_FN, 0, uislib_proc_dir,
+				     &proc_dev_fops);
+	SET_PROC_OWNER(dev_proc_entry, THIS_MODULE);
+#endif				/* UISLIB_TEST_PROC */
+	POSTCODE_LINUX_3(DRIVER_EXIT_PC, 0, POSTCODE_SEVERITY_INFO);
+	return 0;
+}
+
+static void __exit
+uislib_mod_exit(void)
+{
+	if (disable_proc_entry)
+		remove_proc_entry(DISABLE_PROC_ENTRY_FN, uislib_proc_dir);
+	if (cycles_before_wait_proc_entry)
+		remove_proc_entry(CYCLES_BEFORE_WAIT_PROC_ENTRY_FN,
+				  uislib_proc_dir);
+	if (reset_counts_proc_entry)
+		remove_proc_entry(RESET_COUNTS_PROC_ENTRY_FN, uislib_proc_dir);
+	if (smart_wakeup_proc_entry)
+		remove_proc_entry(SMART_WAKEUP_PROC_ENTRY_FN, uislib_proc_dir);
+	if (ctrlchan_proc_entry)
+		remove_proc_entry(CTRLCHAN_PROC_ENTRY_FN, uislib_proc_dir);
+	if (pmem_proc_entry)
+		remove_proc_entry(PMEM_PROC_ENTRY_FN, uislib_proc_dir);
+	if (info_proc_entry)
+		remove_proc_entry(INFO_PROC_ENTRY_FN, uislib_proc_dir);
+	if (switch_proc_entry)
+		remove_proc_entry(SWITCH_PROC_ENTRY_FN, uislib_proc_dir);
+	if (extport_proc_entry)
+		remove_proc_entry(EXTPORT_PROC_ENTRY_FN, uislib_proc_dir);
+	if (platformnumber_proc_entry)
+		remove_proc_entry(PLATFORMNUMBER_PROC_ENTRY_FN,
+				  uislib_proc_dir);
+	if (bus_proc_entry)
+		remove_proc_entry(BUS_PROC_ENTRY_FN, uislib_proc_dir);
+	if (dev_proc_entry)
+		remove_proc_entry(DEV_PROC_ENTRY_FN, uislib_proc_dir);
+	if (vnic_proc_entry)
+		remove_proc_entry(VNIC_PROC_ENTRY_FN, uislib_proc_dir);
+	if (chipset_proc_entry)
+		remove_proc_entry(CHIPSET_PROC_ENTRY_FN, uislib_proc_dir);
+	if (uislib_proc_vbus_dir)
+		remove_proc_entry(DIR_VBUS_PROC_ENTRY, uislib_proc_dir);
+	if (uislib_proc_dir)
+		remove_proc_entry(DIR_PROC_ENTRY, NULL);
+
+	if (ProcReadBuffer) {
+		UISVFREE(ProcReadBuffer, PROC_READ_BUFFER_SIZE);
+		ProcReadBuffer = NULL;
+	}
+
+	DBGINF("goodbye.\n");
+	return;
+}
+
+module_init(uislib_mod_init);
+module_exit(uislib_mod_exit);
+
+int uis_mandatory_services = -1;
+
+module_param_named(mandatory_services, uis_mandatory_services,
+		   int, S_IRUGO);
+MODULE_PARM_DESC(uis_mandatory_services,
+		 "number of server drivers we expect to register (default=-1 for legacy behavior)");
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Usha Srinivasan");
+MODULE_ALIAS("uislib");
+  /* this is extracted during depmod and kept in modules.dep */
diff --git a/drivers/staging/unisys/uislib/uisqueue.c b/drivers/staging/unisys/uislib/uisqueue.c
new file mode 100644
index 0000000..67e413f7
--- /dev/null
+++ b/drivers/staging/unisys/uislib/uisqueue.c
@@ -0,0 +1,166 @@
+/* uisqueue.c
+ *
+ * Copyright © 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+/* @ALL_INSPECTED */
+#include <linux/kernel.h>
+#include <linux/module.h>
+
+#include "uisutils.h"
+
+#include "chanstub.h"
+
+/* this is shorter than using __FILE__ (full path name) in
+ * debug/info/error messages */
+#define CURRENT_FILE_PC UISLIB_PC_uisqueue_c
+#define __MYFILE__ "uisqueue.c"
+
+#define RETVOID    do { goto Away; } while (0)
+#define RETINT(x)  do { rc = (x); goto Away; } while (0)
+#define RETPTR(x)  do { rc = (x); goto Away; } while (0)
+#define RETBOOL(x) do { rc = (x); goto Away; } while (0)
+
+#define CHECK_CACHE_ALIGN 0
+
+/*****************************************************/
+/* Exported functions                                */
+/*****************************************************/
+unsigned long long
+uisqueue_InterlockedOr(volatile unsigned long long *Target,
+		       unsigned long long Set)
+{
+	unsigned long long i;
+	unsigned long long j;
+
+	j = *Target;
+	do {
+		i = j;
+		j = uislibcmpxchg64((unsigned long long *) Target,
+				    i, i | Set, sizeof(*(Target)));
+
+	} while (i != j);
+
+	return j;
+}
+EXPORT_SYMBOL_GPL(uisqueue_InterlockedOr);
+
+unsigned long long
+uisqueue_InterlockedAnd(volatile unsigned long long *Target,
+			unsigned long long Set)
+{
+	unsigned long long i;
+	unsigned long long j;
+
+	j = *Target;
+	do {
+		i = j;
+		j = uislibcmpxchg64((unsigned long long *) Target,
+				    i, i & Set, sizeof(*(Target)));
+
+	} while (i != j);
+
+	return j;
+}
+EXPORT_SYMBOL_GPL(uisqueue_InterlockedAnd);
+
+static U8
+do_locked_client_insert(struct uisqueue_info *queueinfo,
+			unsigned int whichqueue,
+			void *pSignal,
+			spinlock_t *lock,
+			unsigned char issueInterruptIfEmpty,
+			U64 interruptHandle, U8 *channelId)
+{
+	unsigned long flags;
+	unsigned char queueWasEmpty;
+	unsigned int locked = 0;
+	unsigned int acquired = 0;
+	U8 rc = 0;
+
+	spin_lock_irqsave(lock, flags);
+	locked = 1;
+
+	if (!ULTRA_CHANNEL_CLIENT_ACQUIRE_OS(queueinfo->chan, channelId, NULL))
+		RETINT(0);
+
+	acquired = 1;
+
+	queueWasEmpty = SignalQueueIsEmpty(queueinfo->chan, whichqueue);
+	if (!SignalInsert(queueinfo->chan, whichqueue, pSignal))
+		RETINT(0);
+	ULTRA_CHANNEL_CLIENT_RELEASE_OS(queueinfo->chan, channelId, NULL);
+	acquired = 0;
+	spin_unlock_irqrestore(lock, flags);
+	locked = 0;
+
+	queueinfo->packets_sent++;
+
+	RETINT(1);
+
+Away:
+	if (acquired) {
+		ULTRA_CHANNEL_CLIENT_RELEASE_OS(queueinfo->chan, channelId,
+						NULL);
+		acquired = 0;
+	}
+	if (locked) {
+		spin_unlock_irqrestore((spinlock_t *) lock, flags);
+		locked = 0;
+	}
+
+	return rc;
+}
+
+int
+uisqueue_put_cmdrsp_with_lock_client(struct uisqueue_info *queueinfo,
+				     struct uiscmdrsp *cmdrsp,
+				     unsigned int whichqueue,
+				     void *insertlock,
+				     unsigned char issueInterruptIfEmpty,
+				     U64 interruptHandle,
+				     char oktowait, U8 *channelId)
+{
+	while (!do_locked_client_insert(queueinfo, whichqueue, cmdrsp,
+					(spinlock_t *) insertlock,
+					issueInterruptIfEmpty,
+					interruptHandle, channelId)) {
+		if (oktowait != OK_TO_WAIT) {
+			LOGERR("****FAILED SignalInsert failed; cannot wait; insert aborted\n");
+			return 0;	/* failed to queue */
+		}
+		/* try again */
+		LOGERR("****FAILED SignalInsert failed; waiting to try again\n");
+		set_current_state(TASK_INTERRUPTIBLE);
+		schedule_timeout(msecs_to_jiffies(10));
+	}
+	return 1;
+}
+EXPORT_SYMBOL_GPL(uisqueue_put_cmdrsp_with_lock_client);
+
+/* uisqueue_get_cmdrsp gets the cmdrsp entry at the head of the queue
+ * returns NULL if queue is empty */
+int
+uisqueue_get_cmdrsp(struct uisqueue_info *queueinfo,
+		    void *cmdrsp, unsigned int whichqueue)
+{
+	if (!SignalRemove(queueinfo->chan, whichqueue, cmdrsp))
+		return 0;
+
+	queueinfo->packets_received++;
+
+	return 1;		/* Success */
+}
+EXPORT_SYMBOL_GPL(uisqueue_get_cmdrsp);
diff --git a/drivers/staging/unisys/uislib/uisthread.c b/drivers/staging/unisys/uislib/uisthread.c
new file mode 100644
index 0000000..ecf4bfc
--- /dev/null
+++ b/drivers/staging/unisys/uislib/uisthread.c
@@ -0,0 +1,85 @@
+/* uisthread.c
+ *
+ * Copyright © 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+/* @ALL_INSPECTED */
+#include <asm/processor.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/kthread.h>
+#include "uniklog.h"
+#include "uisutils.h"
+#include "uisthread.h"
+
+#define KILL(a, b, c) kill_pid(find_vpid(a), b, c)
+
+/* this is shorter than using __FILE__ (full path name) in
+ * debug/info/error messages
+ */
+#define CURRENT_FILE_PC UISLIB_PC_uisthread_c
+#define __MYFILE__ "uisthread.c"
+
+/*****************************************************/
+/* Exported functions                                */
+/*****************************************************/
+
+/* returns 0 for failure, 1 for success */
+int
+uisthread_start(struct uisthread_info *thrinfo,
+		int (*threadfn)(void *), void *thrcontext, char *name)
+{
+	thrinfo->should_stop = 0;
+	/* used to stop the thread */
+	init_completion(&thrinfo->has_stopped);
+	thrinfo->task = kthread_create(threadfn, thrcontext, name, NULL);
+	if (thrinfo->task == NULL) {
+		thrinfo->id = 0;
+		return 0;	/* failure */
+	}
+	thrinfo->id = thrinfo->task->pid;
+	wake_up_process(thrinfo->task);
+	LOGINF("started thread pid:%d\n", thrinfo->id);
+	return 1;
+
+}
+EXPORT_SYMBOL_GPL(uisthread_start);
+
+void
+uisthread_stop(struct uisthread_info *thrinfo)
+{
+	int ret;
+	int stopped = 0;
+	if (thrinfo->id == 0)
+		return;		/* thread not running */
+
+	LOGINF("uisthread_stop stopping id:%d\n", thrinfo->id);
+	thrinfo->should_stop = 1;
+	ret = KILL(thrinfo->id, SIGHUP, 1);
+	if (ret) {
+		LOGERR("unable to signal thread %d\n", ret);
+	} else {
+		/* give up if the thread has NOT died in 1 minute */
+		if (wait_for_completion_timeout(&thrinfo->has_stopped, 60 * HZ))
+			stopped = 1;
+		else
+			LOGERR("timed out trying to signal thread\n");
+	}
+	if (stopped) {
+		LOGINF("uisthread_stop stopped id:%d\n", thrinfo->id);
+		thrinfo->id = 0;
+	}
+}
+EXPORT_SYMBOL_GPL(uisthread_stop);
diff --git a/drivers/staging/unisys/uislib/uisutils.c b/drivers/staging/unisys/uislib/uisutils.c
new file mode 100644
index 0000000..974f8bc
--- /dev/null
+++ b/drivers/staging/unisys/uislib/uisutils.c
@@ -0,0 +1,349 @@
+/* uisutils.c
+ *
+ * Copyright © 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <commontypes.h>
+#include <linux/spinlock.h>
+#include <linux/list.h>
+#include "uniklog.h"
+#include "uisutils.h"
+#include "version.h"
+#include "vbushelper.h"
+#include "guidutils.h"
+#include <linux/skbuff.h>
+#ifdef CONFIG_HIGHMEM
+#include <linux/highmem.h>
+#endif
+
+/* this is shorter than using __FILE__ (full path name) in
+ * debug/info/error messages
+ */
+#define CURRENT_FILE_PC UISLIB_PC_uisutils_c
+#define __MYFILE__ "uisutils.c"
+
+/* exports */
+atomic_t UisUtils_Registered_Services = ATOMIC_INIT(0);
+					/* num registrations via
+					 * uisctrl_register_req_handler() or
+					 * uisctrl_register_req_handler_ex() */
+
+
+/*****************************************************/
+/* Utility functions                                 */
+/*****************************************************/
+
+int
+util_add_proc_line_ex(int *total, char **buffer, int *buffer_remaining,
+		      char *format, ...)
+{
+	va_list args;
+	int len;
+
+	DBGINF("buffer = 0x%p : *buffer = 0x%p.\n", buffer, *buffer);
+	va_start(args, format);
+	len = vsnprintf(*buffer, *buffer_remaining, format, args);
+	if (len >= *buffer_remaining) {
+		*buffer += *buffer_remaining;
+		*total += *buffer_remaining;
+		*buffer_remaining = 0;
+		LOGERR("bytes remaining is too small!\n");
+		return -1;
+	}
+	*buffer_remaining -= len;
+	*buffer += len;
+	*total += len;
+	return len;
+}
+EXPORT_SYMBOL_GPL(util_add_proc_line_ex);
+
+int
+uisctrl_register_req_handler(int type, void *fptr,
+			     ULTRA_VBUS_DEVICEINFO *chipset_DriverInfo)
+{
+	LOGINF("type = %d, fptr = 0x%p.\n", type, fptr);
+
+	switch (type) {
+	case 2:
+		if (fptr) {
+			if (!VirtControlChanFunc)
+				atomic_inc(&UisUtils_Registered_Services);
+			VirtControlChanFunc = fptr;
+		} else {
+			if (VirtControlChanFunc)
+				atomic_dec(&UisUtils_Registered_Services);
+			VirtControlChanFunc = NULL;
+		}
+		break;
+
+	default:
+		LOGERR("invalid type %d.\n", type);
+		return 0;
+	}
+	if (chipset_DriverInfo)
+		BusDeviceInfo_Init(chipset_DriverInfo,
+				   "chipset", "uislib",
+				   VERSION, NULL, __DATE__, __TIME__);
+
+	return 1;
+}
+EXPORT_SYMBOL_GPL(uisctrl_register_req_handler);
+
+int
+uisctrl_register_req_handler_ex(GUID switchTypeGuid,
+				const char *switch_type_name,
+				int (*controlfunc)(struct io_msgs *),
+				unsigned long min_channel_bytes,
+				int (*Server_Channel_Ok)(unsigned long
+							  channelBytes),
+				int (*Server_Channel_Init)
+				 (void *x, unsigned char *clientStr,
+				  U32 clientStrLen, U64 bytes),
+				ULTRA_VBUS_DEVICEINFO *chipset_DriverInfo)
+{
+	char s[99];
+	ReqHandlerInfo_t *pReqHandlerInfo;
+	int rc = 0;		/* assume failure */
+	LOGINF("type=%s, controlfunc=0x%p.\n",
+	       GUID_format1(&switchTypeGuid, s), controlfunc);
+	if (!controlfunc) {
+		LOGERR("%s: controlfunc must be supplied\n",
+		       GUID_format1(&switchTypeGuid, s));
+		goto Away;
+	}
+	if (!Server_Channel_Ok) {
+		LOGERR("%s: Server_Channel_Ok must be supplied\n",
+		       GUID_format1(&switchTypeGuid, s));
+		goto Away;
+	}
+	if (!Server_Channel_Init) {
+		LOGERR("%s: Server_Channel_Init must be supplied\n",
+		       GUID_format1(&switchTypeGuid, s));
+		goto Away;
+	}
+	pReqHandlerInfo = ReqHandlerAdd(switchTypeGuid,
+					switch_type_name,
+					controlfunc,
+					min_channel_bytes,
+					Server_Channel_Ok, Server_Channel_Init);
+	if (!pReqHandlerInfo) {
+		LOGERR("failed to add %s to server list\n",
+		       GUID_format1(&switchTypeGuid, s));
+		goto Away;
+	}
+
+	atomic_inc(&UisUtils_Registered_Services);
+	rc = 1;			/* success */
+Away:
+	if (rc) {
+		if (chipset_DriverInfo)
+			BusDeviceInfo_Init(chipset_DriverInfo,
+					   "chipset", "uislib",
+					   VERSION, NULL,
+					   __DATE__, __TIME__);
+	} else
+		LOGERR("failed to register type %s.\n",
+		       GUID_format1(&switchTypeGuid, s));
+
+	return rc;
+}
+EXPORT_SYMBOL_GPL(uisctrl_register_req_handler_ex);
+
+int
+uisctrl_unregister_req_handler_ex(GUID switchTypeGuid)
+{
+	char s[99];
+	int rc = 0;		/* assume failure */
+	LOGINF("type=%s.\n", GUID_format1(&switchTypeGuid, s));
+	if (ReqHandlerDel(switchTypeGuid) < 0) {
+		LOGERR("failed to remove %s from server list\n",
+		       GUID_format1(&switchTypeGuid, s));
+		goto Away;
+	}
+	atomic_dec(&UisUtils_Registered_Services);
+	rc = 1;			/* success */
+Away:
+	if (!rc)
+		LOGERR("failed to unregister type %s.\n",
+		       GUID_format1(&switchTypeGuid, s));
+	return rc;
+}
+EXPORT_SYMBOL_GPL(uisctrl_unregister_req_handler_ex);
+
+/*
+ * unsigned int util_copy_fragsinfo_from_skb(unsigned char *calling_ctx,
+ *					     void *skb_in,
+ *					     unsigned int firstfraglen,
+ *					     unsigned int frags_max,
+ *					     struct phys_info frags[])
+ *
+ *	calling_ctx - input -   a string that is displayed to show
+ *				who called * this func
+ *	void *skb_in -  skb whose frag info we're copying type is hidden so we
+ *			don't need to include skbbuff in uisutils.h which is
+ *			included in non-networking code.
+ *	unsigned int firstfraglen - input - length of first fragment in skb
+ *	unsigned int frags_max - input - max len of frags array
+ *	struct phys_info frags[] - output - frags array filled in on output
+ *					    return value indicates number of
+ *					    entries filled in frags
+ */
+unsigned int
+util_copy_fragsinfo_from_skb(unsigned char *calling_ctx, void *skb_in,
+			     unsigned int firstfraglen, unsigned int frags_max,
+			     struct phys_info frags[])
+{
+	unsigned int count = 0, ii, size, offset = 0, numfrags;
+	struct sk_buff *skb = skb_in;
+
+	numfrags = skb_shinfo(skb)->nr_frags;
+
+	while (firstfraglen) {
+		if (count == frags_max) {
+			LOGERR("%s frags array too small: max:%d count:%d\n",
+			       calling_ctx, frags_max, count);
+			return -1;	/* failure */
+		}
+		frags[count].pi_pfn =
+		    page_to_pfn(virt_to_page(skb->data + offset));
+		frags[count].pi_off =
+		    (unsigned long) (skb->data + offset) & PI_PAGE_MASK;
+		size =
+		    min(firstfraglen,
+			(unsigned int) (PI_PAGE_SIZE - frags[count].pi_off));
+		/* can take smallest of firstfraglen(what's left) OR
+		* bytes left in the page
+		*/
+		frags[count].pi_len = size;
+		firstfraglen -= size;
+		offset += size;
+		count++;
+	}
+	if (numfrags) {
+		if ((count + numfrags) > frags_max) {
+			LOGERR("**** FAILED %s frags array too small: max:%d count+nr_frags:%d\n",
+			     calling_ctx, frags_max, count + numfrags);
+			return -1;	/* failure */
+		}
+
+		for (ii = 0; ii < numfrags; ii++) {
+			count = add_physinfo_entries(page_to_pfn(skb_frag_page(&skb_shinfo(skb)->frags[ii])),	/* pfn */
+						     skb_shinfo(skb)->frags[ii].
+						     page_offset,
+						     skb_shinfo(skb)->frags[ii].
+						     size, count, frags_max,
+						     frags);
+			if (count == 0) {
+				LOGERR("**** FAILED to add physinfo entries\n");
+				return -1;	/* failure */
+			}
+		}
+	}
+	if (skb_shinfo(skb)->frag_list) {
+		struct sk_buff *skbinlist;
+		int c;
+		for (skbinlist = skb_shinfo(skb)->frag_list; skbinlist;
+		     skbinlist = skbinlist->next) {
+
+			c = util_copy_fragsinfo_from_skb("recursive", skbinlist,
+							 skbinlist->len -
+							 skbinlist->data_len,
+							 frags_max - count,
+							 &frags[count]);
+			if (c == -1) {
+				LOGERR("**** FAILED recursive call failed\n");
+				return -1;
+			}
+			count += c;
+		}
+	}
+	return count;
+}
+EXPORT_SYMBOL_GPL(util_copy_fragsinfo_from_skb);
+
+static LIST_HEAD(ReqHandlerInfo_list);	/* list of ReqHandlerInfo_t */
+static DEFINE_SPINLOCK(ReqHandlerInfo_list_lock);
+
+ReqHandlerInfo_t *
+ReqHandlerAdd(GUID switchTypeGuid,
+	      const char *switch_type_name,
+	      int (*controlfunc)(struct io_msgs *),
+	      unsigned long min_channel_bytes,
+	      int (*Server_Channel_Ok)(unsigned long channelBytes),
+	      int (*Server_Channel_Init)
+	       (void *x, unsigned char *clientStr, U32 clientStrLen, U64 bytes))
+{
+	ReqHandlerInfo_t *rc = NULL;
+
+	rc = UISMALLOC(sizeof(*rc), GFP_ATOMIC);
+	if (!rc)
+		return NULL;
+	memset(rc, 0, sizeof(*rc));
+	rc->switchTypeGuid = switchTypeGuid;
+	rc->controlfunc = controlfunc;
+	rc->min_channel_bytes = min_channel_bytes;
+	rc->Server_Channel_Ok = Server_Channel_Ok;
+	rc->Server_Channel_Init = Server_Channel_Init;
+	if (switch_type_name)
+		strncpy(rc->switch_type_name, switch_type_name,
+			sizeof(rc->switch_type_name) - 1);
+	spin_lock(&ReqHandlerInfo_list_lock);
+	list_add_tail(&(rc->list_link), &ReqHandlerInfo_list);
+	spin_unlock(&ReqHandlerInfo_list_lock);
+
+	return rc;
+}
+
+ReqHandlerInfo_t *
+ReqHandlerFind(GUID switchTypeGuid)
+{
+	struct list_head *lelt, *tmp;
+	ReqHandlerInfo_t *entry = NULL;
+	spin_lock(&ReqHandlerInfo_list_lock);
+	list_for_each_safe(lelt, tmp, &ReqHandlerInfo_list) {
+		entry = list_entry(lelt, ReqHandlerInfo_t, list_link);
+		if (memcmp
+		    (&entry->switchTypeGuid, &switchTypeGuid,
+		     sizeof(GUID)) == 0) {
+			spin_unlock(&ReqHandlerInfo_list_lock);
+			return entry;
+		}
+	}
+	spin_unlock(&ReqHandlerInfo_list_lock);
+	return NULL;
+}
+
+int
+ReqHandlerDel(GUID switchTypeGuid)
+{
+	struct list_head *lelt, *tmp;
+	ReqHandlerInfo_t *entry = NULL;
+	int rc = -1;
+	spin_lock(&ReqHandlerInfo_list_lock);
+	list_for_each_safe(lelt, tmp, &ReqHandlerInfo_list) {
+		entry = list_entry(lelt, ReqHandlerInfo_t, list_link);
+		if (memcmp
+		    (&entry->switchTypeGuid, &switchTypeGuid,
+		     sizeof(GUID)) == 0) {
+			list_del(lelt);
+			UISFREE(entry, sizeof(*entry));
+			rc++;
+		}
+	}
+	spin_unlock(&ReqHandlerInfo_list_lock);
+	return rc;
+}
diff --git a/drivers/staging/unisys/virthba/Kconfig b/drivers/staging/unisys/virthba/Kconfig
new file mode 100644
index 0000000..d2ef0fc
--- /dev/null
+++ b/drivers/staging/unisys/virthba/Kconfig
@@ -0,0 +1,10 @@
+#
+# Unisys virthba configuration
+#
+
+config UNISYS_VIRTHBA
+	tristate "Unisys virthba driver"
+	depends on UNISYSSPAR && UNISYS_VISORCHIPSET && UNISYS_CHANNELSTUB && UNISYS_UISLIB && UNISYS_VIRTPCI
+	---help---
+	If you say Y here, you will enable the Unisys virthba driver.
+
diff --git a/drivers/staging/unisys/virthba/Makefile b/drivers/staging/unisys/virthba/Makefile
new file mode 100644
index 0000000..632b1c0
--- /dev/null
+++ b/drivers/staging/unisys/virthba/Makefile
@@ -0,0 +1,16 @@
+#
+# Makefile for Unisys virthba
+#
+
+obj-$(CONFIG_UNISYS_VIRTHBA)	+= virthba.o
+
+ccflags-y += -Idrivers/staging/unisys/include
+ccflags-y += -Idrivers/staging/unisys/uislib
+ccflags-y += -Idrivers/staging/unisys/timskmod
+ccflags-y += -Idrivers/staging/unisys/visorchipset
+ccflags-y += -Idrivers/staging/unisys/virtpci
+ccflags-y += -Idrivers/staging/unisys/common-spar/include
+ccflags-y += -Idrivers/staging/unisys/common-spar/include/channels
+
+ccflags-y += -DCONFIG_SPAR_GUEST -DGUESTDRIVERBUILD -DNOAUTOVERSION
+
diff --git a/drivers/staging/unisys/virthba/virthba.c b/drivers/staging/unisys/virthba/virthba.c
new file mode 100644
index 0000000..dd5fe75
--- /dev/null
+++ b/drivers/staging/unisys/virthba/virthba.c
@@ -0,0 +1,1813 @@
+/* virthba.c
+ *
+ * Copyright © 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+#define EXPORT_SYMTAB
+
+/* if you want to turn on some debugging of write device data or read
+ * device data, define these two undefs.  You will probably want to
+ * customize the code which is here since it was written assuming
+ * reading and writing a specific data file df.64M.txt which is a
+ * 64Megabyte file created by Art Nilson using a scritp I wrote called
+ * cr_test_data.pl.  The data file consists of 256 byte lines of text
+ * which start with an 8 digit sequence number, a colon, and then
+ * letters after that */
+
+#undef DBGINF
+
+#include <linux/kernel.h>
+#ifdef CONFIG_MODVERSIONS
+#include <config/modversions.h>
+#endif
+
+#include "uniklog.h"
+#include "diagnostics/appos_subsystems.h"
+#include "uisutils.h"
+#include "uisqueue.h"
+#include "uisthread.h"
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/spinlock.h>
+#include <linux/device.h>
+#include <linux/slab.h>
+#include <scsi/scsi.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
+#include <asm/param.h>
+#include <linux/proc_fs.h>
+#include <linux/types.h>
+
+#include "virthba.h"
+#include "virtpci.h"
+#include "visorchipset.h"
+#include "version.h"
+#include "guestlinuxdebug.h"
+/* this is shorter than using __FILE__ (full path name) in
+ * debug/info/error messages
+ */
+#define CURRENT_FILE_PC VIRT_HBA_PC_virthba_c
+#define __MYFILE__ "virthba.c"
+
+/* NOTE:  L1_CACHE_BYTES >=128 */
+#define DEVICE_ATTRIBUTE struct device_attribute
+
+/*****************************************************/
+/* Forward declarations                              */
+/*****************************************************/
+static int virthba_probe(struct virtpci_dev *dev,
+			 const struct pci_device_id *id);
+static void virthba_remove(struct virtpci_dev *dev);
+static int virthba_abort_handler(struct scsi_cmnd *scsicmd);
+static int virthba_bus_reset_handler(struct scsi_cmnd *scsicmd);
+static int virthba_device_reset_handler(struct scsi_cmnd *scsicmd);
+static int virthba_host_reset_handler(struct scsi_cmnd *scsicmd);
+static const char *virthba_get_info(struct Scsi_Host *shp);
+static int virthba_ioctl(struct scsi_device *dev, int cmd, void __user *arg);
+static int virthba_queue_command_lck(struct scsi_cmnd *scsicmd,
+				     void (*virthba_cmnd_done)(struct scsi_cmnd *));
+#ifdef DEF_SCSI_QCMD
+DEF_SCSI_QCMD(virthba_queue_command)
+#else
+#define virthba_queue_command virthba_queue_command_lck
+#endif
+static int virthba_slave_alloc(struct scsi_device *scsidev);
+static int virthba_slave_configure(struct scsi_device *scsidev);
+static void virthba_slave_destroy(struct scsi_device *scsidev);
+static int process_incoming_rsps(void *);
+static int virthba_serverup(struct virtpci_dev *virtpcidev);
+static int virthba_serverdown(struct virtpci_dev *virtpcidev, u32 state);
+static void doDiskAddRemove(struct work_struct *work);
+static void virthba_serverdown_complete(struct work_struct *work);
+
+static ssize_t info_proc_read(struct file *file, char __user *buf,
+			      size_t len, loff_t *offset);
+static ssize_t rqwu_proc_write(struct file *file, const char __user *buffer,
+			       size_t count, loff_t *ppos);
+static ssize_t enable_ints_read(struct file *file, char __user *buffer,
+				size_t count, loff_t *ppos);
+static ssize_t enable_ints_write(struct file *file, const char __user *buffer,
+				 size_t count, loff_t *ppos);
+
+/*****************************************************/
+/* Globals                                           */
+/*****************************************************/
+
+int rsltq_wait_usecs = 4000;	/* Default 4ms */
+static unsigned int MaxBuffLen;
+
+/* Module options */
+char *virthba_options = "NONE";
+
+static const struct pci_device_id virthba_id_table[] = {
+	{PCI_DEVICE(PCI_VENDOR_ID_UNISYS, PCI_DEVICE_ID_VIRTHBA)},
+	{0},
+};
+
+/* export virthba_id_table */
+MODULE_DEVICE_TABLE(pci, virthba_id_table);
+
+static struct workqueue_struct *virthba_serverdown_workqueue;
+
+static struct virtpci_driver virthba_driver = {
+	.name = "uisvirthba",
+	.version = VERSION,
+	.vertag = NULL,
+	.build_date = __DATE__,
+	.build_time = __TIME__,
+	.id_table = virthba_id_table,
+	.probe = virthba_probe,
+	.remove = virthba_remove,
+	.resume = virthba_serverup,
+	.suspend = virthba_serverdown
+};
+
+/* The Send and Recive Buffers of the IO Queue may both be full */
+#define MAX_PENDING_REQUESTS (MIN_NUMSIGNALS*2)
+#define INTERRUPT_VECTOR_MASK 0x3F
+
+struct scsipending {
+	char cmdtype;		/* Type of pointer that is being stored */
+	void *sent;		/* The Data being tracked */
+	/* struct scsi_cmnd *type for virthba_queue_command */
+	/* struct uiscmdrsp *type for management commands */
+};
+
+#define VIRTHBA_ERROR_COUNT 30
+#define IOS_ERROR_THRESHOLD 1000
+struct virtdisk_info {
+	U32 valid;
+	U32 channel, id, lun;	/* Disk Path */
+	atomic_t ios_threshold;
+	atomic_t error_count;
+	struct virtdisk_info *next;
+};
+/* Each Scsi_Host has a host_data area that contains this struct. */
+struct virthba_info {
+	struct Scsi_Host *scsihost;
+	struct virtpci_dev *virtpcidev;
+	struct list_head dev_info_list;
+	struct chaninfo chinfo;
+	struct InterruptInfo intr;	/* use recvInterrupt info to receive
+					   interrupts when IOs complete */
+	int interrupt_vector;
+	struct scsipending pending[MAX_PENDING_REQUESTS]; /* Tracks the requests
+							     that have been */
+	/* forwarded to the IOVM and haven't returned yet */
+	unsigned int nextinsert;	/* Start search for next pending
+					   free slot here */
+	spinlock_t privlock;
+	bool serverdown;
+	bool serverchangingstate;
+	unsigned long long acquire_failed_cnt;
+	unsigned long long interrupts_rcvd;
+	unsigned long long interrupts_notme;
+	unsigned long long interrupts_disabled;
+	struct work_struct serverdown_completion;
+	U64 *flags_addr;
+	atomic_t interrupt_rcvd;
+	wait_queue_head_t rsp_queue;
+	struct virtdisk_info head;
+};
+
+/* Work Data for DARWorkQ */
+struct diskaddremove {
+	U8 add;			/* 0-remove, 1-add */
+	struct Scsi_Host *shost; /* Scsi Host for this virthba instance */
+	U32 channel, id, lun;	/* Disk Path */
+	struct diskaddremove *next;
+};
+
+#define virtpci_dev_to_virthba_virthba_get_info(d) \
+	container_of(d, struct virthba_info, virtpcidev)
+
+static DEVICE_ATTRIBUTE *virthba_shost_attrs[];
+static struct scsi_host_template virthba_driver_template = {
+	.name = "Unisys Virtual HBA",
+	.proc_name = "uisvirthba",
+	.info = virthba_get_info,
+	.ioctl = virthba_ioctl,
+	.queuecommand = virthba_queue_command,
+	.eh_abort_handler = virthba_abort_handler,
+	.eh_device_reset_handler = virthba_device_reset_handler,
+	.eh_bus_reset_handler = virthba_bus_reset_handler,
+	.eh_host_reset_handler = virthba_host_reset_handler,
+	.shost_attrs = virthba_shost_attrs,
+
+#define VIRTHBA_MAX_CMNDS 128
+	.can_queue = VIRTHBA_MAX_CMNDS,
+	.sg_tablesize = 64,	/* largest number of address/length pairs */
+	.this_id = -1,
+	.slave_alloc = virthba_slave_alloc,
+	.slave_configure = virthba_slave_configure,
+	.slave_destroy = virthba_slave_destroy,
+	.use_clustering = ENABLE_CLUSTERING,
+};
+
+struct virthba_devices_open {
+	struct virthba_info *virthbainfo;
+};
+
+static const struct file_operations proc_info_fops = {
+	.read = info_proc_read,
+};
+
+static const struct file_operations proc_rqwu_fops = {
+	.write = rqwu_proc_write,
+};
+
+static const struct file_operations proc_enable_ints_fops = {
+	.read = enable_ints_read,
+	.write = enable_ints_write,
+};
+
+
+#define VIRTHBASOPENMAX 1
+/* array of open devices maintained by open() and close(); */
+static struct virthba_devices_open VirtHbasOpen[VIRTHBASOPENMAX];
+static struct proc_dir_entry *virthba_proc_dir;
+static struct proc_dir_entry *info_proc_entry;
+static struct proc_dir_entry *rqwaitus_proc_entry;
+static struct proc_dir_entry *enable_ints_proc_entry;
+#define INFO_PROC_ENTRY_FN "info"
+#define ENABLE_INTS_ENTRY_FN "enable_ints"
+#define RQWU_PROC_ENTRY_FN "rqwait_usecs"
+#define DIR_PROC_ENTRY "virthba"
+
+/*****************************************************/
+/* Local Functions				     */
+/*****************************************************/
+static int
+add_scsipending_entry(struct virthba_info *vhbainfo, char cmdtype, void *new)
+{
+	unsigned long flags;
+	int insert_location;
+
+	spin_lock_irqsave(&vhbainfo->privlock, flags);
+	insert_location = vhbainfo->nextinsert;
+	while (vhbainfo->pending[insert_location].sent != NULL) {
+		insert_location = (insert_location + 1) % MAX_PENDING_REQUESTS;
+		if (insert_location == (int) vhbainfo->nextinsert) {
+			LOGERR("Queue should be full. insert_location<<%d>>  Unable to find open slot for pending commands.\n",
+			     insert_location);
+			spin_unlock_irqrestore(&vhbainfo->privlock, flags);
+			return -1;
+		}
+	}
+
+	vhbainfo->pending[insert_location].cmdtype = cmdtype;
+	vhbainfo->pending[insert_location].sent = new;
+	vhbainfo->nextinsert = (insert_location + 1) % MAX_PENDING_REQUESTS;
+	spin_unlock_irqrestore(&vhbainfo->privlock, flags);
+
+	return insert_location;
+}
+
+static unsigned int
+add_scsipending_entry_with_wait(struct virthba_info *vhbainfo, char cmdtype,
+				void *new)
+{
+	int insert_location = add_scsipending_entry(vhbainfo, cmdtype, new);
+
+	while (insert_location == -1) {
+		LOGERR("Failed to find empty queue slot.  Waiting to try again\n");
+		set_current_state(TASK_INTERRUPTIBLE);
+		schedule_timeout(msecs_to_jiffies(10));
+		insert_location = add_scsipending_entry(vhbainfo, cmdtype, new);
+	}
+
+	return (unsigned int) insert_location;
+}
+
+static void *
+del_scsipending_entry(struct virthba_info *vhbainfo, uintptr_t del)
+{
+	unsigned long flags;
+	void *sent = NULL;
+
+	if (del >= MAX_PENDING_REQUESTS) {
+		LOGERR("Invalid queue position <<%lu>> given to delete. MAX_PENDING_REQUESTS <<%d>>\n",
+		     (unsigned long) del, MAX_PENDING_REQUESTS);
+	} else {
+		spin_lock_irqsave(&vhbainfo->privlock, flags);
+
+		if (vhbainfo->pending[del].sent == NULL)
+			LOGERR("Deleting already cleared queue entry at <<%lu>>.\n",
+			     (unsigned long) del);
+
+		sent = vhbainfo->pending[del].sent;
+
+		vhbainfo->pending[del].cmdtype = 0;
+		vhbainfo->pending[del].sent = NULL;
+		spin_unlock_irqrestore(&vhbainfo->privlock, flags);
+	}
+
+	return sent;
+}
+
+/* DARWorkQ (Disk Add/Remove) */
+static struct work_struct DARWorkQ;
+struct diskaddremove *DARWorkQHead = NULL;
+spinlock_t DARWorkQLock;
+unsigned short DARWorkQSched = 0;
+#define QUEUE_DISKADDREMOVE(dar) { \
+	spin_lock_irqsave(&DARWorkQLock, flags); \
+	if (!DARWorkQHead) { \
+		DARWorkQHead = dar; \
+		dar->next = NULL; \
+	} \
+	else { \
+		dar->next = DARWorkQHead; \
+		DARWorkQHead = dar; \
+	} \
+	if (!DARWorkQSched) { \
+		schedule_work(&DARWorkQ); \
+		DARWorkQSched = 1; \
+	} \
+	spin_unlock_irqrestore(&DARWorkQLock, flags); \
+}
+
+static inline void
+SendDiskAddRemove(struct diskaddremove *dar)
+{
+	struct scsi_device *sdev;
+	int error;
+
+	sdev = scsi_device_lookup(dar->shost, dar->channel, dar->id, dar->lun);
+	if (sdev) {
+		if (!(dar->add))
+			scsi_remove_device(sdev);
+	} else if (dar->add) {
+		error =
+		    scsi_add_device(dar->shost, dar->channel, dar->id,
+				    dar->lun);
+		if (error)
+			LOGERR("Failed scsi_add_device: host_no=%d[chan=%d:id=%d:lun=%d]\n",
+			     dar->shost->host_no, dar->channel, dar->id,
+			     dar->lun);
+	} else
+		LOGERR("Failed scsi_device_lookup:[chan=%d:id=%d:lun=%d]\n",
+		       dar->channel, dar->id, dar->lun);
+	kfree(dar);
+}
+
+/*****************************************************/
+/* DARWorkQ Handler Thread                           */
+/*****************************************************/
+static void
+doDiskAddRemove(struct work_struct *work)
+{
+	struct diskaddremove *dar;
+	struct diskaddremove *tmphead;
+	int i = 0;
+	unsigned long flags;
+
+	spin_lock_irqsave(&DARWorkQLock, flags);
+	tmphead = DARWorkQHead;
+	DARWorkQHead = NULL;
+	DARWorkQSched = 0;
+	spin_unlock_irqrestore(&DARWorkQLock, flags);
+	while (tmphead) {
+		dar = tmphead;
+		tmphead = dar->next;
+		SendDiskAddRemove(dar);
+		i++;
+	}
+}
+
+/*****************************************************/
+/* Routine to add entry to DARWorkQ                  */
+/*****************************************************/
+static void
+process_disk_notify(struct Scsi_Host *shost, struct uiscmdrsp *cmdrsp)
+{
+	struct diskaddremove *dar;
+	unsigned long flags;
+
+	dar = kmalloc(sizeof(struct diskaddremove), GFP_ATOMIC);
+	if (dar) {
+		memset(dar, 0, sizeof(struct diskaddremove));
+		dar->add = cmdrsp->disknotify.add;
+		dar->shost = shost;
+		dar->channel = cmdrsp->disknotify.channel;
+		dar->id = cmdrsp->disknotify.id;
+		dar->lun = cmdrsp->disknotify.lun;
+		QUEUE_DISKADDREMOVE(dar);
+	} else {
+		LOGERR("kmalloc failed for dar. host_no=%d[chan=%d:id=%d:lun=%d]\n",
+		     shost->host_no, cmdrsp->disknotify.channel,
+		     cmdrsp->disknotify.id, cmdrsp->disknotify.lun);
+	}
+}
+
+/*****************************************************/
+/* Probe Remove Functions                            */
+/*****************************************************/
+irqreturn_t
+virthba_ISR(int irq, void *dev_id)
+{
+	struct virthba_info *virthbainfo = (struct virthba_info *) dev_id;
+	pCHANNEL_HEADER pChannelHeader;
+	pSIGNAL_QUEUE_HEADER pqhdr;
+	U64 mask;
+	unsigned long long rc1;
+
+	if (virthbainfo == NULL)
+		return IRQ_NONE;
+	virthbainfo->interrupts_rcvd++;
+	pChannelHeader = virthbainfo->chinfo.queueinfo->chan;
+	if (((pChannelHeader->Features
+	      & ULTRA_IO_IOVM_IS_OK_WITH_DRIVER_DISABLING_INTS) != 0)
+	    && ((pChannelHeader->Features & ULTRA_IO_DRIVER_DISABLES_INTS) !=
+		0)) {
+		virthbainfo->interrupts_disabled++;
+		mask = ~ULTRA_CHANNEL_ENABLE_INTS;
+		rc1 = uisqueue_InterlockedAnd(virthbainfo->flags_addr, mask);
+	}
+	if (SignalQueueIsEmpty(pChannelHeader, IOCHAN_FROM_IOPART)) {
+		virthbainfo->interrupts_notme++;
+		return IRQ_NONE;
+	}
+	pqhdr = (pSIGNAL_QUEUE_HEADER) ((char *) pChannelHeader +
+					pChannelHeader->oChannelSpace) +
+					IOCHAN_FROM_IOPART;
+	pqhdr->NumInterruptsReceived++;
+	atomic_set(&virthbainfo->interrupt_rcvd, 1);
+	wake_up_interruptible(&virthbainfo->rsp_queue);
+	return IRQ_HANDLED;
+}
+
+static int
+virthba_probe(struct virtpci_dev *virtpcidev, const struct pci_device_id *id)
+{
+	int error;
+	struct Scsi_Host *scsihost;
+	struct virthba_info *virthbainfo;
+	int rsp;
+	int i;
+	irq_handler_t handler = virthba_ISR;
+	pCHANNEL_HEADER pChannelHeader;
+	pSIGNAL_QUEUE_HEADER pqhdr;
+	U64 mask;
+
+	LOGVER("entering virthba_probe...\n");
+	LOGVER("virtpcidev busNo<<%d>>devNo<<%d>>", virtpcidev->busNo,
+	       virtpcidev->deviceNo);
+
+	LOGINF("entering virthba_probe...\n");
+	LOGINF("virtpcidev busNo<<%d>>devNo<<%d>>", virtpcidev->busNo,
+	       virtpcidev->deviceNo);
+	POSTCODE_LINUX_2(VHBA_PROBE_ENTRY_PC, POSTCODE_SEVERITY_INFO);
+	/* call scsi_host_alloc to register a scsi host adapter
+	 * instance - this virthba that has just been created is an
+	 * instance of a scsi host adapter. This scsi_host_alloc
+	 * function allocates a new Scsi_Host struct & performs basic
+	 * initializatoin.  The host is not published to the scsi
+	 * midlayer until scsi_add_host is called.
+	 */
+	DBGINF("calling scsi_host_alloc.\n");
+
+	/* arg 2 passed in length of extra space we want allocated
+	 * with scsi_host struct for our own use scsi_host_alloc
+	 * assign host_no
+	 */
+	scsihost = scsi_host_alloc(&virthba_driver_template,
+				   sizeof(struct virthba_info));
+	if (scsihost == NULL)
+		return -ENODEV;
+
+	DBGINF("scsihost: 0x%p, scsihost->this_id: %d, host_no: %d.\n",
+	       scsihost, scsihost->this_id, scsihost->host_no);
+
+	scsihost->this_id = UIS_MAGIC_VHBA;
+	/* linux treats max-channel differently than max-id & max-lun.
+	 * In the latter cases, those two values result in 0 to max-1
+	 * (inclusive) being scanned. But in the case of channels, the
+	 * scan is 0 to max (inclusive); so we will subtract one from
+	 * the max-channel value.
+	 */
+	LOGINF("virtpcidev->scsi.max.max_channel=%u, max_id=%u, max_lun=%u, cmd_per_lun=%u, max_io_size=%u\n",
+	     (unsigned) virtpcidev->scsi.max.max_channel - 1,
+	     (unsigned) virtpcidev->scsi.max.max_id,
+	     (unsigned) virtpcidev->scsi.max.max_lun,
+	     (unsigned) virtpcidev->scsi.max.cmd_per_lun,
+	     (unsigned) virtpcidev->scsi.max.max_io_size);
+	scsihost->max_channel = (unsigned) virtpcidev->scsi.max.max_channel;
+	scsihost->max_id = (unsigned) virtpcidev->scsi.max.max_id;
+	scsihost->max_lun = (unsigned) virtpcidev->scsi.max.max_lun;
+	scsihost->cmd_per_lun = (unsigned) virtpcidev->scsi.max.cmd_per_lun;
+	scsihost->max_sectors =
+	    (unsigned short) (virtpcidev->scsi.max.max_io_size >> 9);
+	scsihost->sg_tablesize =
+	    (unsigned short) (virtpcidev->scsi.max.max_io_size / PAGE_SIZE);
+	if (scsihost->sg_tablesize > MAX_PHYS_INFO)
+		scsihost->sg_tablesize = MAX_PHYS_INFO;
+	LOGINF("scsihost->max_channel=%u, max_id=%u, max_lun=%u, cmd_per_lun=%u, max_sectors=%hu, sg_tablesize=%hu\n",
+	     scsihost->max_channel, scsihost->max_id, scsihost->max_lun,
+	     scsihost->cmd_per_lun, scsihost->max_sectors,
+	     scsihost->sg_tablesize);
+	LOGINF("scsihost->can_queue=%u, scsihost->cmd_per_lun=%u, max_sectors=%hu, sg_tablesize=%hu\n",
+	     scsihost->can_queue, scsihost->cmd_per_lun, scsihost->max_sectors,
+	     scsihost->sg_tablesize);
+
+	DBGINF("calling scsi_add_host\n");
+
+	/* this creates "host%d" in sysfs.  If 2nd argument is NULL,
+	 * then this generic /sys/devices/platform/host?  device is
+	 * created and /sys/scsi_host/host? ->
+	 * /sys/devices/platform/host?  If 2nd argument is not NULL,
+	 * then this generic /sys/devices/<path>/host? is created and
+	 * host? points to that device instead.
+	 */
+	error = scsi_add_host(scsihost, &virtpcidev->generic_dev);
+	if (error) {
+		LOGERR("scsi_add_host ****FAILED 0x%x  TBD - RECOVER\n", error);
+		POSTCODE_LINUX_2(VHBA_PROBE_FAILURE_PC, POSTCODE_SEVERITY_ERR);
+		/* decr refcount on scsihost which was incremented by
+		 * scsi_add_host so the scsi_host gets deleted
+		 */
+		scsi_host_put(scsihost);
+		return -ENODEV;
+	}
+
+	virthbainfo = (struct virthba_info *) scsihost->hostdata;
+	memset(virthbainfo, 0, sizeof(struct virthba_info));
+	for (i = 0; i < VIRTHBASOPENMAX; i++) {
+		if (VirtHbasOpen[i].virthbainfo == NULL) {
+			VirtHbasOpen[i].virthbainfo = virthbainfo;
+			break;
+		}
+	}
+	virthbainfo->interrupt_vector = -1;
+	virthbainfo->chinfo.queueinfo = &virtpcidev->queueinfo;
+	virthbainfo->virtpcidev = virtpcidev;
+	spin_lock_init(&virthbainfo->chinfo.insertlock);
+
+	DBGINF("generic_dev: 0x%p, queueinfo: 0x%p.\n",
+	       &virtpcidev->generic_dev, &virtpcidev->queueinfo);
+
+	init_waitqueue_head(&virthbainfo->rsp_queue);
+	spin_lock_init(&virthbainfo->privlock);
+	memset(&virthbainfo->pending, 0, sizeof(virthbainfo->pending));
+	virthbainfo->serverdown = false;
+	virthbainfo->serverchangingstate = false;
+
+	virthbainfo->intr = virtpcidev->intr;
+	/* save of host within virthba_info */
+	virthbainfo->scsihost = scsihost;
+
+	/* save of host within virtpci_dev */
+	virtpcidev->scsi.scsihost = scsihost;
+
+	/* Setup workqueue for serverdown messages */
+	INIT_WORK(&virthbainfo->serverdown_completion,
+		  virthba_serverdown_complete);
+
+	virthbainfo->chinfo.queueinfo->chan->Features |=
+	    ULTRA_IO_CHANNEL_IS_POLLING;
+	/* start thread that will receive scsicmnd responses */
+	DBGINF("starting rsp thread -- queueinfo: 0x%p, threadinfo: 0x%p.\n",
+	       virthbainfo->chinfo.queueinfo, &virthbainfo->chinfo.threadinfo);
+
+	pChannelHeader = virthbainfo->chinfo.queueinfo->chan;
+	pqhdr = (pSIGNAL_QUEUE_HEADER) ((char *) pChannelHeader +
+					pChannelHeader->oChannelSpace) +
+					IOCHAN_FROM_IOPART;
+	virthbainfo->flags_addr = &pqhdr->FeatureFlags;
+
+	if (!uisthread_start(&virthbainfo->chinfo.threadinfo,
+			     process_incoming_rsps,
+			     virthbainfo, "vhba_incoming")) {
+		LOGERR("uisthread_start rsp ****FAILED\n");
+		/* decr refcount on scsihost which was incremented by
+		 * scsi_add_host so the scsi_host gets deleted
+		 */
+		POSTCODE_LINUX_2(VHBA_PROBE_FAILURE_PC, POSTCODE_SEVERITY_ERR);
+		scsi_host_put(scsihost);
+		return -ENODEV;
+	}
+	LOGINF("sendInterruptHandle=0x%16llX",
+	       virthbainfo->intr.sendInterruptHandle);
+	LOGINF("recvInterruptHandle=0x%16llX",
+	       virthbainfo->intr.recvInterruptHandle);
+	LOGINF("recvInterruptVector=0x%8X",
+	       virthbainfo->intr.recvInterruptVector);
+	LOGINF("recvInterruptShared=0x%2X",
+	       virthbainfo->intr.recvInterruptShared);
+	LOGINF("scsihost.hostt->name=%s", scsihost->hostt->name);
+	virthbainfo->interrupt_vector =
+	    virthbainfo->intr.recvInterruptHandle & INTERRUPT_VECTOR_MASK;
+	rsp = request_irq(virthbainfo->interrupt_vector, handler, IRQF_SHARED,
+			  scsihost->hostt->name, virthbainfo);
+	if (rsp != 0) {
+		LOGERR("request_irq(%d) uislib_virthba_ISR request failed with rsp=%d\n",
+		       virthbainfo->interrupt_vector, rsp);
+		virthbainfo->interrupt_vector = -1;
+		POSTCODE_LINUX_2(VHBA_PROBE_FAILURE_PC, POSTCODE_SEVERITY_ERR);
+	} else {
+		U64 *Features_addr =
+		    &virthbainfo->chinfo.queueinfo->chan->Features;
+		LOGERR("request_irq(%d) uislib_virthba_ISR request succeeded\n",
+		       virthbainfo->interrupt_vector);
+		mask = ~(ULTRA_IO_CHANNEL_IS_POLLING |
+			 ULTRA_IO_DRIVER_DISABLES_INTS);
+		uisqueue_InterlockedAnd(Features_addr, mask);
+		mask = ULTRA_IO_DRIVER_ENABLES_INTS;
+		uisqueue_InterlockedOr(Features_addr, mask);
+		rsltq_wait_usecs = 4000000;
+	}
+
+	DBGINF("calling scsi_scan_host.\n");
+	scsi_scan_host(scsihost);
+	DBGINF("return from scsi_scan_host.\n");
+
+	LOGINF("virthba added scsihost:0x%p\n", scsihost);
+	POSTCODE_LINUX_2(VHBA_PROBE_EXIT_PC, POSTCODE_SEVERITY_INFO);
+	return 0;
+}
+
+static void
+virthba_remove(struct virtpci_dev *virtpcidev)
+{
+	struct virthba_info *virthbainfo;
+	struct Scsi_Host *scsihost =
+	    (struct Scsi_Host *) virtpcidev->scsi.scsihost;
+
+	LOGINF("virtpcidev busNo<<%d>>devNo<<%d>>", virtpcidev->busNo,
+	       virtpcidev->deviceNo);
+	virthbainfo = (struct virthba_info *) scsihost->hostdata;
+	if (virthbainfo->interrupt_vector != -1)
+		free_irq(virthbainfo->interrupt_vector, virthbainfo);
+	LOGINF("Removing virtpcidev: 0x%p, virthbainfo: 0x%p\n", virtpcidev,
+	       virthbainfo);
+
+	DBGINF("removing scsihost: 0x%p, scsihost->this_id: %d\n", scsihost,
+	       scsihost->this_id);
+	scsi_remove_host(scsihost);
+
+	DBGINF("stopping thread.\n");
+	uisthread_stop(&virthbainfo->chinfo.threadinfo);
+
+	DBGINF("calling scsi_host_put\n");
+
+	/* decr refcount on scsihost which was incremented by
+	 * scsi_add_host so the scsi_host gets deleted
+	 */
+	scsi_host_put(scsihost);
+	LOGINF("virthba removed scsi_host.\n");
+}
+
+static int
+forward_vdiskmgmt_command(VDISK_MGMT_TYPES vdiskcmdtype,
+			  struct Scsi_Host *scsihost,
+			  struct uisscsi_dest *vdest)
+{
+	struct uiscmdrsp *cmdrsp;
+	struct virthba_info *virthbainfo =
+	    (struct virthba_info *) scsihost->hostdata;
+	int notifyresult = 0xffff;
+	wait_queue_head_t notifyevent;
+
+	LOGINF("vDiskMgmt:%d %d:%d:%d\n", vdiskcmdtype,
+	       vdest->channel, vdest->id, vdest->lun);
+
+	if (virthbainfo->serverdown || virthbainfo->serverchangingstate) {
+		DBGINF("Server is down/changing state. Returning Failure.\n");
+		return FAILED;
+	}
+
+	ALLOC_CMDRSP(cmdrsp);
+	if (cmdrsp == NULL) {
+		LOGERR("kmalloc of cmdrsp failed.\n");
+		return FAILED;	/* reject */
+	}
+
+	init_waitqueue_head(&notifyevent);
+
+	/* issue VDISK_MGMT_CMD
+	 * set type to command - as opposed to task mgmt
+	 */
+	cmdrsp->cmdtype = CMD_VDISKMGMT_TYPE;
+	/* specify the event that has to be triggered when this cmd is
+	 * complete
+	 */
+	cmdrsp->vdiskmgmt.notify = (void *) &notifyevent;
+	cmdrsp->vdiskmgmt.notifyresult = (void *) &notifyresult;
+
+	/* save destination */
+	cmdrsp->vdiskmgmt.vdisktype = vdiskcmdtype;
+	cmdrsp->vdiskmgmt.vdest.channel = vdest->channel;
+	cmdrsp->vdiskmgmt.vdest.id = vdest->id;
+	cmdrsp->vdiskmgmt.vdest.lun = vdest->lun;
+	cmdrsp->vdiskmgmt.scsicmd =
+	    (void *) (uintptr_t)
+		add_scsipending_entry_with_wait(virthbainfo, CMD_VDISKMGMT_TYPE,
+						(void *) cmdrsp);
+
+	uisqueue_put_cmdrsp_with_lock_client(virthbainfo->chinfo.queueinfo,
+					     cmdrsp, IOCHAN_TO_IOPART,
+					     &virthbainfo->chinfo.insertlock,
+					     DONT_ISSUE_INTERRUPT, (U64) NULL,
+					     OK_TO_WAIT, "vhba");
+	LOGINF("VdiskMgmt waiting on event notifyevent=0x%p\n",
+	       cmdrsp->scsitaskmgmt.notify);
+	wait_event(notifyevent, notifyresult != 0xffff);
+	LOGINF("VdiskMgmt complete; result:%d\n", cmdrsp->vdiskmgmt.result);
+	kfree(cmdrsp);
+	return SUCCESS;
+}
+
+/*****************************************************/
+/* Scsi Host support functions                       */
+/*****************************************************/
+
+static int
+forward_taskmgmt_command(TASK_MGMT_TYPES tasktype, struct scsi_device *scsidev)
+{
+	struct uiscmdrsp *cmdrsp;
+	struct virthba_info *virthbainfo =
+	    (struct virthba_info *) scsidev->host->hostdata;
+	int notifyresult = 0xffff;
+	wait_queue_head_t notifyevent;
+
+	LOGINF("TaskMgmt:%d %d:%d:%d\n", tasktype,
+	       scsidev->channel, scsidev->id, scsidev->lun);
+
+	if (virthbainfo->serverdown || virthbainfo->serverchangingstate) {
+		DBGINF("Server is down/changing state. Returning Failure.\n");
+		return FAILED;
+	}
+
+	ALLOC_CMDRSP(cmdrsp);
+	if (cmdrsp == NULL) {
+		LOGERR("kmalloc of cmdrsp failed.\n");
+		return FAILED;	/* reject */
+	}
+
+	init_waitqueue_head(&notifyevent);
+
+	/* issue TASK_MGMT_ABORT_TASK */
+	/* set type to command - as opposed to task mgmt */
+	cmdrsp->cmdtype = CMD_SCSITASKMGMT_TYPE;
+	/* specify the event that has to be triggered when this */
+	/* cmd is complete */
+	cmdrsp->scsitaskmgmt.notify = (void *) &notifyevent;
+	cmdrsp->scsitaskmgmt.notifyresult = (void *) &notifyresult;
+
+	/* save destination */
+	cmdrsp->scsitaskmgmt.tasktype = tasktype;
+	cmdrsp->scsitaskmgmt.vdest.channel = scsidev->channel;
+	cmdrsp->scsitaskmgmt.vdest.id = scsidev->id;
+	cmdrsp->scsitaskmgmt.vdest.lun = scsidev->lun;
+	cmdrsp->scsitaskmgmt.scsicmd =
+	    (void *) (uintptr_t)
+		add_scsipending_entry_with_wait(virthbainfo,
+						CMD_SCSITASKMGMT_TYPE,
+						(void *) cmdrsp);
+
+	uisqueue_put_cmdrsp_with_lock_client(virthbainfo->chinfo.queueinfo,
+					     cmdrsp, IOCHAN_TO_IOPART,
+					     &virthbainfo->chinfo.insertlock,
+					     DONT_ISSUE_INTERRUPT, (U64) NULL,
+					     OK_TO_WAIT, "vhba");
+	LOGINF("TaskMgmt waiting on event notifyevent=0x%p\n",
+	       cmdrsp->scsitaskmgmt.notify);
+	wait_event(notifyevent, notifyresult != 0xffff);
+	LOGINF("TaskMgmt complete; result:%d\n", cmdrsp->scsitaskmgmt.result);
+	kfree(cmdrsp);
+	return SUCCESS;
+}
+
+/* The abort handler returns SUCCESS if it has succeeded to make LLDD
+ * and all related hardware forget about the scmd.
+ */
+static int
+virthba_abort_handler(struct scsi_cmnd *scsicmd)
+{
+	/* issue TASK_MGMT_ABORT_TASK */
+	struct scsi_device *scsidev;
+	struct virtdisk_info *vdisk;
+
+	scsidev = scsicmd->device;
+	for (vdisk = &((struct virthba_info *) scsidev->host->hostdata)->head;
+	     vdisk->next; vdisk = vdisk->next) {
+		if ((scsidev->channel == vdisk->channel)
+		    && (scsidev->id == vdisk->id)
+		    && (scsidev->lun == vdisk->lun)) {
+			if (atomic_read(&vdisk->error_count) <
+			    VIRTHBA_ERROR_COUNT) {
+				atomic_inc(&vdisk->error_count);
+				POSTCODE_LINUX_2(VHBA_COMMAND_HANDLER_PC,
+						 POSTCODE_SEVERITY_INFO);
+			} else
+				atomic_set(&vdisk->ios_threshold,
+					   IOS_ERROR_THRESHOLD);
+		}
+	}
+	return forward_taskmgmt_command(TASK_MGMT_ABORT_TASK, scsicmd->device);
+}
+
+static int
+virthba_bus_reset_handler(struct scsi_cmnd *scsicmd)
+{
+	/* issue TASK_MGMT_TARGET_RESET for each target on the bus */
+	struct scsi_device *scsidev;
+	struct virtdisk_info *vdisk;
+
+	scsidev = scsicmd->device;
+	for (vdisk = &((struct virthba_info *) scsidev->host->hostdata)->head;
+	     vdisk->next; vdisk = vdisk->next) {
+		if ((scsidev->channel == vdisk->channel)
+		    && (scsidev->id == vdisk->id)
+		    && (scsidev->lun == vdisk->lun)) {
+			if (atomic_read(&vdisk->error_count) <
+			    VIRTHBA_ERROR_COUNT) {
+				atomic_inc(&vdisk->error_count);
+				POSTCODE_LINUX_2(VHBA_COMMAND_HANDLER_PC,
+						 POSTCODE_SEVERITY_INFO);
+			} else
+				atomic_set(&vdisk->ios_threshold,
+					   IOS_ERROR_THRESHOLD);
+		}
+	}
+	return forward_taskmgmt_command(TASK_MGMT_BUS_RESET, scsicmd->device);
+}
+
+static int
+virthba_device_reset_handler(struct scsi_cmnd *scsicmd)
+{
+	/* issue TASK_MGMT_LUN_RESET */
+	struct scsi_device *scsidev;
+	struct virtdisk_info *vdisk;
+
+	scsidev = scsicmd->device;
+	for (vdisk = &((struct virthba_info *) scsidev->host->hostdata)->head;
+	     vdisk->next; vdisk = vdisk->next) {
+		if ((scsidev->channel == vdisk->channel)
+		    && (scsidev->id == vdisk->id)
+		    && (scsidev->lun == vdisk->lun)) {
+			if (atomic_read(&vdisk->error_count) <
+			    VIRTHBA_ERROR_COUNT) {
+				atomic_inc(&vdisk->error_count);
+				POSTCODE_LINUX_2(VHBA_COMMAND_HANDLER_PC,
+						 POSTCODE_SEVERITY_INFO);
+			} else
+				atomic_set(&vdisk->ios_threshold,
+					   IOS_ERROR_THRESHOLD);
+		}
+	}
+	return forward_taskmgmt_command(TASK_MGMT_LUN_RESET, scsicmd->device);
+}
+
+static int
+virthba_host_reset_handler(struct scsi_cmnd *scsicmd)
+{
+	/* issue TASK_MGMT_TARGET_RESET for each target on each bus for host */
+	LOGERR("virthba_host_reset_handler Not yet implemented\n");
+	return SUCCESS;
+}
+
+static char virthba_get_info_str[256];
+
+static const char *
+virthba_get_info(struct Scsi_Host *shp)
+{
+	/* Return version string */
+	sprintf(virthba_get_info_str, "virthba, version %s\n", VIRTHBA_VERSION);
+	return virthba_get_info_str;
+}
+
+static int
+virthba_ioctl(struct scsi_device *dev, int cmd, void __user *arg)
+{
+	DBGINF("In virthba_ioctl: ioctl: cmd=0x%x\n", cmd);
+	return -EINVAL;
+}
+
+/* This returns SCSI_MLQUEUE_DEVICE_BUSY if the signal queue to IOpart
+ * is full.
+ */
+static int
+virthba_queue_command_lck(struct scsi_cmnd *scsicmd,
+			  void (*virthba_cmnd_done)(struct scsi_cmnd *))
+{
+	struct scsi_device *scsidev = scsicmd->device;
+	int insert_location;
+	unsigned char op;
+	unsigned char *cdb = scsicmd->cmnd;
+	struct Scsi_Host *scsihost = scsidev->host;
+	struct uiscmdrsp *cmdrsp;
+	unsigned int i;
+	struct virthba_info *virthbainfo =
+	    (struct virthba_info *) scsihost->hostdata;
+	struct scatterlist *sg = NULL;
+	struct scatterlist *sgl = NULL;
+	int sg_failed = 0;
+
+	if (virthbainfo->serverdown || virthbainfo->serverchangingstate) {
+		DBGINF("Server is down/changing state. Returning SCSI_MLQUEUE_DEVICE_BUSY.\n");
+		return SCSI_MLQUEUE_DEVICE_BUSY;
+	}
+
+	ALLOC_CMDRSP(cmdrsp);
+	if (cmdrsp == NULL) {
+		LOGERR("kmalloc of cmdrsp failed.\n");
+		return 1;	/* reject the command */
+	}
+
+	/* now saving everything we need from scsi_cmd into cmdrsp
+	 * before we queue cmdrsp set type to command - as opposed to
+	 * task mgmt
+	 */
+	cmdrsp->cmdtype = CMD_SCSI_TYPE;
+	/* save the pending insertion location.  Deletion from pending
+	 * will return the scsicmd pointer for completion
+	 */
+	insert_location =
+	    add_scsipending_entry(virthbainfo, CMD_SCSI_TYPE, (void *) scsicmd);
+	if (insert_location != -1) {
+		cmdrsp->scsi.scsicmd = (void *) (uintptr_t) insert_location;
+	} else {
+		LOGERR("Queue is full. Returning busy.\n");
+		kfree(cmdrsp);
+		return SCSI_MLQUEUE_DEVICE_BUSY;
+	}
+	/* save done function that we have call when cmd is complete */
+	scsicmd->scsi_done = virthba_cmnd_done;
+	/* save destination */
+	cmdrsp->scsi.vdest.channel = scsidev->channel;
+	cmdrsp->scsi.vdest.id = scsidev->id;
+	cmdrsp->scsi.vdest.lun = scsidev->lun;
+	/* save datadir */
+	cmdrsp->scsi.data_dir = scsicmd->sc_data_direction;
+	memcpy(cmdrsp->scsi.cmnd, cdb, MAX_CMND_SIZE);
+
+	cmdrsp->scsi.bufflen = scsi_bufflen(scsicmd);
+
+	/* keep track of the max buffer length so far. */
+	if (cmdrsp->scsi.bufflen > MaxBuffLen)
+		MaxBuffLen = cmdrsp->scsi.bufflen;
+
+	if (scsi_sg_count(scsicmd) > MAX_PHYS_INFO) {
+		LOGERR("scsicmd use_sg:%d greater than MAX:%d\n",
+		       scsi_sg_count(scsicmd), MAX_PHYS_INFO);
+		del_scsipending_entry(virthbainfo, (uintptr_t) insert_location);
+		kfree(cmdrsp);
+		return 1;	/* reject the command */
+	}
+
+	/* This is what we USED to do when we assumed we were running */
+	/* uissd & virthba on the same Linux system. */
+	/* cmdrsp->scsi.buffer = scsicmd->request_buffer; */
+	/* The following code does NOT make that assumption. */
+	/* convert buffer to phys information */
+	if (scsi_sg_count(scsicmd) == 0) {
+		if (scsi_bufflen(scsicmd) > 0) {
+			LOGERR("**** FAILED No scatter list for bufflen > 0\n");
+			BUG_ON(scsi_sg_count(scsicmd) == 0);
+		}
+		DBGINF("No sg; buffer:0x%p bufflen:%d\n",
+		       scsi_sglist(scsicmd), scsi_bufflen(scsicmd));
+	} else {
+		/* buffer is scatterlist - copy it out */
+		sgl = scsi_sglist(scsicmd);
+
+		for_each_sg(sgl, sg, scsi_sg_count(scsicmd), i) {
+
+			cmdrsp->scsi.gpi_list[i].address = sg_phys(sg);
+			cmdrsp->scsi.gpi_list[i].length = sg->length;
+			if ((i != 0) && (sg->offset != 0))
+				LOGINF("Offset on a sg_entry other than zero =<<%d>>.\n",
+				     sg->offset);
+		}
+
+		if (sg_failed) {
+			LOGERR("Start sg_list dump (entries %d, bufflen %d)...\n",
+			     scsi_sg_count(scsicmd), cmdrsp->scsi.bufflen);
+			for_each_sg(sgl, sg, scsi_sg_count(scsicmd), i) {
+				LOGERR("   Entry(%d): page->[0x%p], phys->[0x%Lx], off(%d), len(%d)\n",
+				     i, sg_page(sg),
+				     (unsigned long long) sg_phys(sg),
+				     sg->offset, sg->length);
+			}
+			LOGERR("Done sg_list dump.\n");
+			/* BUG(); ***** For now, let it fail in uissd
+			 * if it is a problem, as it might just
+			 * work
+			 */
+		}
+
+		cmdrsp->scsi.guest_phys_entries = scsi_sg_count(scsicmd);
+	}
+
+	op = cdb[0];
+	i = uisqueue_put_cmdrsp_with_lock_client(virthbainfo->chinfo.queueinfo,
+						 cmdrsp, IOCHAN_TO_IOPART,
+						 &virthbainfo->chinfo.
+						 insertlock,
+						 DONT_ISSUE_INTERRUPT,
+						 (U64) NULL, DONT_WAIT, "vhba");
+	if (i == 0) {
+		/* queue must be full - and we said don't wait - return busy */
+		LOGERR("uisqueue_put_cmdrsp_with_lock ****FAILED\n");
+		kfree(cmdrsp);
+		del_scsipending_entry(virthbainfo, (uintptr_t) insert_location);
+		return SCSI_MLQUEUE_DEVICE_BUSY;
+	}
+
+	/* we're done with cmdrsp space - data from it has been copied
+	 * into channel - free it now.
+	 */
+	kfree(cmdrsp);
+	return 0;		/* non-zero implies host/device is busy */
+}
+
+static int
+virthba_slave_alloc(struct scsi_device *scsidev)
+{
+	/* this called by the midlayer before scan for new devices -
+	 * LLD can alloc any struc & do init if needed.
+	 */
+	struct virtdisk_info *vdisk;
+	struct virtdisk_info *tmpvdisk;
+	struct virthba_info *virthbainfo;
+	struct Scsi_Host *scsihost = (struct Scsi_Host *) scsidev->host;
+
+	virthbainfo = (struct virthba_info *) scsihost->hostdata;
+	if (!virthbainfo) {
+		LOGERR("Could not find virthba_info for scsihost\n");
+		return 0;	/* even though we errored, treat as success */
+	}
+	for (vdisk = &virthbainfo->head; vdisk->next; vdisk = vdisk->next) {
+		if (vdisk->next->valid &&
+		    (vdisk->next->channel == scsidev->channel) &&
+		    (vdisk->next->id == scsidev->id) &&
+		    (vdisk->next->lun == scsidev->lun))
+			return 0;
+	}
+	tmpvdisk = kmalloc(sizeof(struct virtdisk_info), GFP_ATOMIC);
+	if (!tmpvdisk) {	/* error allocating */
+		LOGERR("Could not allocate memory for disk\n");
+		return 0;
+	}
+	memset(tmpvdisk, 0, sizeof(struct virtdisk_info));
+	tmpvdisk->channel = scsidev->channel;
+	tmpvdisk->id = scsidev->id;
+	tmpvdisk->lun = scsidev->lun;
+	tmpvdisk->valid = 1;
+	vdisk->next = tmpvdisk;
+	return 0;		/* success */
+}
+
+static int
+virthba_slave_configure(struct scsi_device *scsidev)
+{
+	return 0;		/* success */
+}
+
+static void
+virthba_slave_destroy(struct scsi_device *scsidev)
+{
+	/* midlevel calls this after device has been quiesced and
+	 * before it is to be deleted.
+	 */
+	struct virtdisk_info *vdisk, *delvdisk;
+	struct virthba_info *virthbainfo;
+	struct Scsi_Host *scsihost = (struct Scsi_Host *) scsidev->host;
+
+	virthbainfo = (struct virthba_info *) scsihost->hostdata;
+	if (!virthbainfo)
+		LOGERR("Could not find virthba_info for scsihost\n");
+	for (vdisk = &virthbainfo->head; vdisk->next; vdisk = vdisk->next) {
+		if (vdisk->next->valid &&
+		    (vdisk->next->channel == scsidev->channel) &&
+		    (vdisk->next->id == scsidev->id) &&
+		    (vdisk->next->lun == scsidev->lun)) {
+			delvdisk = vdisk->next;
+			vdisk->next = vdisk->next->next;
+			kfree(delvdisk);
+			return;
+		}
+	}
+	return;
+}
+
+/*****************************************************/
+/* Scsi Cmnd support thread                          */
+/*****************************************************/
+
+static void
+do_scsi_linuxstat(struct uiscmdrsp *cmdrsp, struct scsi_cmnd *scsicmd)
+{
+	struct virtdisk_info *vdisk;
+	struct scsi_device *scsidev;
+	struct sense_data *sd;
+
+	scsidev = scsicmd->device;
+	memcpy(scsicmd->sense_buffer, cmdrsp->scsi.sensebuf, MAX_SENSE_SIZE);
+	sd = (struct sense_data *) scsicmd->sense_buffer;
+
+	/* Do not log errors for disk-not-present inquiries */
+	if ((cmdrsp->scsi.cmnd[0] == INQUIRY) &&
+	    (host_byte(cmdrsp->scsi.linuxstat) == DID_NO_CONNECT) &&
+	    (cmdrsp->scsi.addlstat == ADDL_SEL_TIMEOUT))
+		return;
+
+	/* Okay see what our error_count is here.... */
+	for (vdisk = &((struct virthba_info *) scsidev->host->hostdata)->head;
+	     vdisk->next; vdisk = vdisk->next) {
+		if ((scsidev->channel != vdisk->channel)
+		    || (scsidev->id != vdisk->id)
+		    || (scsidev->lun != vdisk->lun))
+			continue;
+
+		if (atomic_read(&vdisk->error_count) < VIRTHBA_ERROR_COUNT) {
+			atomic_inc(&vdisk->error_count);
+			LOGERR("SCSICMD ****FAILED scsicmd:0x%p op:0x%x <%d:%d:%d:%d> 0x%x-0x%x-0x%x-0x%x-0x%x.\n",
+			       scsicmd, cmdrsp->scsi.cmnd[0],
+			       scsidev->host->host_no, scsidev->id,
+			       scsidev->channel, scsidev->lun,
+			       cmdrsp->scsi.linuxstat, sd->Valid, sd->SenseKey,
+			       sd->AdditionalSenseCode,
+			       sd->AdditionalSenseCodeQualifier);
+			if (atomic_read(&vdisk->error_count) ==
+			    VIRTHBA_ERROR_COUNT) {
+				LOGERR("Throtling SCSICMD errors disk <%d:%d:%d:%d>\n",
+				     scsidev->host->host_no, scsidev->id,
+				     scsidev->channel, scsidev->lun);
+			}
+			atomic_set(&vdisk->ios_threshold, IOS_ERROR_THRESHOLD);
+		}
+	}
+}
+
+static void
+do_scsi_nolinuxstat(struct uiscmdrsp *cmdrsp, struct scsi_cmnd *scsicmd)
+{
+	struct scsi_device *scsidev;
+	unsigned char buf[36];
+	struct scatterlist *sg;
+	unsigned int i;
+	char *thispage;
+	char *thispage_orig;
+	int bufind = 0;
+	struct virtdisk_info *vdisk;
+
+	scsidev = scsicmd->device;
+	if ((cmdrsp->scsi.cmnd[0] == INQUIRY)
+	    && (cmdrsp->scsi.bufflen >= MIN_INQUIRY_RESULT_LEN)) {
+		if (cmdrsp->scsi.no_disk_result == 0)
+			return;
+
+		/* Linux scsi code is weird; it wants
+		 * a device at Lun 0 to issue report
+		 * luns, but we don't want a disk
+		 * there so we'll present a processor
+		 * there. */
+		SET_NO_DISK_INQUIRY_RESULT(buf, cmdrsp->scsi.bufflen,
+					   scsidev->lun,
+					   DEV_DISK_CAPABLE_NOT_PRESENT,
+					   DEV_NOT_CAPABLE);
+
+		if (scsi_sg_count(scsicmd) == 0) {
+			if (scsi_bufflen(scsicmd) > 0) {
+				LOGERR("**** FAILED No scatter list for bufflen > 0\n");
+				BUG_ON(scsi_sg_count(scsicmd) ==
+				       0);
+			}
+			memcpy(scsi_sglist(scsicmd), buf,
+			       cmdrsp->scsi.bufflen);
+			return;
+		}
+
+		sg = scsi_sglist(scsicmd);
+		for (i = 0; i < scsi_sg_count(scsicmd); i++) {
+			DBGVER("copying OUT OF buf into 0x%p %d\n",
+			     sg_page(sg + i), sg[i].length);
+			thispage_orig = kmap_atomic(sg_page(sg + i));
+			thispage = (void *) ((unsigned long)thispage_orig |
+					     sg[i].offset);
+			memcpy(thispage, buf + bufind, sg[i].length);
+			kunmap_atomic(thispage_orig);
+			bufind += sg[i].length;
+		}
+	} else {
+
+		vdisk = &((struct virthba_info *)scsidev->host->hostdata)->head;
+		for ( ; vdisk->next; vdisk = vdisk->next) {
+			if ((scsidev->channel != vdisk->channel)
+			    || (scsidev->id != vdisk->id)
+			    || (scsidev->lun != vdisk->lun))
+				continue;
+
+			if (atomic_read(&vdisk->ios_threshold) > 0) {
+				atomic_dec(&vdisk->ios_threshold);
+				if (atomic_read(&vdisk->ios_threshold) == 0) {
+					LOGERR("Resetting error count for disk\n");
+					atomic_set(&vdisk->error_count, 0);
+				}
+			}
+		}
+	}
+}
+
+static void
+complete_scsi_command(struct uiscmdrsp *cmdrsp, struct scsi_cmnd *scsicmd)
+{
+	DBGINF("cmdrsp: 0x%p, scsistat:0x%x.\n", cmdrsp, cmdrsp->scsi.scsistat);
+
+	/* take what we need out of cmdrsp and complete the scsicmd */
+	scsicmd->result = cmdrsp->scsi.linuxstat;
+	if (cmdrsp->scsi.linuxstat)
+		do_scsi_linuxstat(cmdrsp, scsicmd);
+	else
+		do_scsi_nolinuxstat(cmdrsp, scsicmd);
+
+	if (scsicmd->scsi_done) {
+		DBGVER("Scsi_DONE\n");
+		scsicmd->scsi_done(scsicmd);
+	}
+}
+
+static inline void
+complete_vdiskmgmt_command(struct uiscmdrsp *cmdrsp)
+{
+	/* copy the result of the taskmgmt and */
+	/* wake up the error handler that is waiting for this */
+	*(int *) cmdrsp->vdiskmgmt.notifyresult = cmdrsp->vdiskmgmt.result;
+	wake_up_all((wait_queue_head_t *) cmdrsp->vdiskmgmt.notify);
+	LOGINF("set notify result to %d\n", cmdrsp->vdiskmgmt.result);
+}
+
+static inline void
+complete_taskmgmt_command(struct uiscmdrsp *cmdrsp)
+{
+	/* copy the result of the taskmgmt and */
+	/* wake up the error handler that is waiting for this */
+	*(int *) cmdrsp->scsitaskmgmt.notifyresult =
+	    cmdrsp->scsitaskmgmt.result;
+	wake_up_all((wait_queue_head_t *) cmdrsp->scsitaskmgmt.notify);
+	LOGINF("set notify result to %d\n", cmdrsp->scsitaskmgmt.result);
+}
+
+static void
+drain_queue(struct virthba_info *virthbainfo, struct chaninfo *dc,
+		struct uiscmdrsp *cmdrsp)
+{
+	unsigned long flags;
+	int qrslt = 0;
+	struct scsi_cmnd *scsicmd;
+	struct Scsi_Host *shost = virthbainfo->scsihost;
+
+	while (1) {
+		spin_lock_irqsave(&virthbainfo->chinfo.insertlock, flags);
+		if (!ULTRA_CHANNEL_CLIENT_ACQUIRE_OS(dc->queueinfo->chan,
+						     "vhba", NULL)) {
+			spin_unlock_irqrestore(&virthbainfo->chinfo.insertlock,
+					       flags);
+			virthbainfo->acquire_failed_cnt++;
+			break;
+		}
+		qrslt = uisqueue_get_cmdrsp(dc->queueinfo, cmdrsp,
+					    IOCHAN_FROM_IOPART);
+		ULTRA_CHANNEL_CLIENT_RELEASE_OS(dc->queueinfo->chan,
+						"vhba", NULL);
+		spin_unlock_irqrestore(&virthbainfo->chinfo.insertlock, flags);
+		if (qrslt == 0)
+			break;
+		if (cmdrsp->cmdtype == CMD_SCSI_TYPE) {
+			/* scsicmd location is returned by the
+			 * deletion
+			 */
+			scsicmd = del_scsipending_entry(virthbainfo,
+					(uintptr_t) cmdrsp->scsi.scsicmd);
+			if (!scsicmd)
+				break;
+			/* complete the orig cmd */
+			complete_scsi_command(cmdrsp, scsicmd);
+		} else if (cmdrsp->cmdtype == CMD_SCSITASKMGMT_TYPE) {
+			if (!del_scsipending_entry(virthbainfo,
+				   (uintptr_t) cmdrsp->scsitaskmgmt.scsicmd))
+				break;
+			complete_taskmgmt_command(cmdrsp);
+		} else if (cmdrsp->cmdtype == CMD_NOTIFYGUEST_TYPE) {
+			/* The vHba pointer has no meaning in
+			 * a Client/Guest Partition. Let's be
+			 * safe and set it to NULL now.  Do
+			 * not use it here! */
+			cmdrsp->disknotify.vHba = NULL;
+			process_disk_notify(shost, cmdrsp);
+		} else if (cmdrsp->cmdtype == CMD_VDISKMGMT_TYPE) {
+			if (!del_scsipending_entry(virthbainfo,
+				   (uintptr_t) cmdrsp->vdiskmgmt.scsicmd))
+				break;
+			complete_vdiskmgmt_command(cmdrsp);
+		} else
+			LOGERR("Invalid cmdtype %d\n", cmdrsp->cmdtype);
+		/* cmdrsp is now available for reuse */
+	}
+}
+
+
+/* main function for the thread that waits for scsi commands to arrive
+ * in a specified queue
+ */
+static int
+process_incoming_rsps(void *v)
+{
+	struct virthba_info *virthbainfo = v;
+	struct chaninfo *dc = &virthbainfo->chinfo;
+	struct uiscmdrsp *cmdrsp = NULL;
+	const int SZ = sizeof(struct uiscmdrsp);
+	U64 mask;
+	unsigned long long rc1;
+
+	UIS_DAEMONIZE("vhba_incoming");
+	/* alloc once and reuse */
+	cmdrsp = kmalloc(SZ, GFP_ATOMIC);
+	if (cmdrsp == NULL) {
+		LOGERR("process_incoming_rsps ****FAILED to malloc - thread exiting\n");
+		complete_and_exit(&dc->threadinfo.has_stopped, 0);
+		return 0;
+	}
+	mask = ULTRA_CHANNEL_ENABLE_INTS;
+	while (1) {
+		wait_event_interruptible_timeout(virthbainfo->rsp_queue,
+			 (atomic_read(&virthbainfo->interrupt_rcvd) == 1),
+					 usecs_to_jiffies(rsltq_wait_usecs));
+		atomic_set(&virthbainfo->interrupt_rcvd, 0);
+		/* drain queue */
+		drain_queue(virthbainfo, dc, cmdrsp);
+		rc1 = uisqueue_InterlockedOr(virthbainfo->flags_addr, mask);
+		if (dc->threadinfo.should_stop)
+			break;
+	}
+
+	kfree(cmdrsp);
+
+	DBGINF("exiting processing incoming rsps.\n");
+	complete_and_exit(&dc->threadinfo.has_stopped, 0);
+}
+
+/*****************************************************/
+/* proc filesystem functions						 */
+/*****************************************************/
+
+static ssize_t
+info_proc_read(struct file *file, char __user *buf, size_t len, loff_t *offset)
+{
+	int length = 0;
+	U64 phys_flags_addr;
+	int i;
+	struct virthba_info *virthbainfo;
+	char *vbuf;
+	loff_t pos = *offset;
+
+	if (pos < 0)
+		return -EINVAL;
+
+	if (pos > 0 || !len)
+		return 0;
+
+	vbuf = kzalloc(len, GFP_KERNEL);
+	if (!vbuf)
+		return -ENOMEM;
+
+	for (i = 0; i < VIRTHBASOPENMAX; i++) {
+		if (VirtHbasOpen[i].virthbainfo == NULL)
+			continue;
+
+		virthbainfo = VirtHbasOpen[i].virthbainfo;
+		length += sprintf(vbuf + length, "CHANSOCK is not defined.\n");
+
+		length += sprintf(vbuf + length, "MaxBuffLen:%d\n", MaxBuffLen);
+
+		length += sprintf(vbuf + length, "\nvirthba result queue poll wait:%d usecs.\n",
+				  rsltq_wait_usecs);
+
+		length += sprintf(vbuf + length,
+				  "\nModule build: Date:%s Time:%s\n",
+				  __DATE__, __TIME__);
+		length += sprintf(vbuf + length, "\ninterrupts_rcvd = %llu, interrupts_disabled = %llu\n",
+				  virthbainfo->interrupts_rcvd,
+				  virthbainfo->interrupts_disabled);
+		length += sprintf(vbuf + length, "\ninterrupts_notme = %llu,\n",
+				  virthbainfo->interrupts_notme);
+		phys_flags_addr = virt_to_phys(virthbainfo->flags_addr);
+
+		length += sprintf(vbuf + length, "flags_addr = %p, phys_flags_addr=0x%016llx, FeatureFlags=%llu\n",
+			  virthbainfo->flags_addr, phys_flags_addr,
+			  *virthbainfo->flags_addr);
+		length += sprintf(vbuf + length, "acquire_failed_cnt:%llu\n",
+				  virthbainfo->acquire_failed_cnt);
+
+		length += sprintf(vbuf + length, "\n");
+	}
+	if (copy_to_user(buf, vbuf, length)) {
+		kfree(vbuf);
+		return -EFAULT;
+	}
+
+	kfree(vbuf);
+	*offset += length;
+	return length;
+}
+
+static ssize_t
+enable_ints_read(struct file *file, char __user *buffer,
+		  size_t count, loff_t *ppos)
+{
+	return 0;
+}
+
+static ssize_t
+enable_ints_write(struct file *file, const char __user *buffer,
+		  size_t count, loff_t *ppos)
+{
+	char buf[count + 1];
+	int i, new_value;
+	struct virthba_info *virthbainfo;
+	U64 *Features_addr;
+	U64 mask;
+
+	buf[count] = '\0';
+	if (copy_from_user(buf, buffer, count)) {
+		LOGERR("copy_from_user failed. buf<<%.*s>> count<<%lu>>\n",
+		       (int) count, buf, count);
+		return -EFAULT;
+	}
+
+	i = sscanf(buf, "%d", &new_value);
+
+	if (i < 1) {
+		LOGERR("Failed to scan value for enable_ints, buf<<%.*s>>",
+		       (int) count, buf);
+		return -EFAULT;
+	}
+
+	/* set all counts to new_value usually 0 */
+	for (i = 0; i < VIRTHBASOPENMAX; i++) {
+		if (VirtHbasOpen[i].virthbainfo != NULL) {
+			virthbainfo = VirtHbasOpen[i].virthbainfo;
+			Features_addr =
+				&virthbainfo->chinfo.queueinfo->chan->Features;
+			if (new_value == 1) {
+				mask = ~(ULTRA_IO_CHANNEL_IS_POLLING |
+					 ULTRA_IO_DRIVER_DISABLES_INTS);
+				uisqueue_InterlockedAnd(Features_addr, mask);
+				mask = ULTRA_IO_DRIVER_ENABLES_INTS;
+				uisqueue_InterlockedOr(Features_addr, mask);
+				rsltq_wait_usecs = 4000000;
+			} else {
+				mask = ~(ULTRA_IO_DRIVER_ENABLES_INTS |
+					 ULTRA_IO_DRIVER_DISABLES_INTS);
+				uisqueue_InterlockedAnd(Features_addr, mask);
+				mask = ULTRA_IO_CHANNEL_IS_POLLING;
+				uisqueue_InterlockedOr(Features_addr, mask);
+				rsltq_wait_usecs = 4000;
+			}
+		}
+	}
+	return count;
+}
+
+static ssize_t
+rqwu_proc_write(struct file *file, const char __user *buffer,
+		size_t count, loff_t *ppos)
+{
+	char buf[count];
+	int i, usecs;
+
+	if (copy_from_user(buf, buffer, count)) {
+		LOGERR("copy_from_user failed. buf<<%.*s>> count<<%lu>>\n",
+		       (int) count, buf, count);
+		return -EFAULT;
+	}
+
+	i = sscanf(buf, "%d", &usecs);
+
+	if (i < 1) {
+		LOGERR("Failed to scan value for rqwait_usecs buf<<%.*s>>",
+		       (int) count, buf);
+		return -EFAULT;
+	}
+
+	/* set global wait time */
+	rsltq_wait_usecs = usecs;
+	return count;
+}
+
+/* As per VirtpciFunc returns 1 for success and 0 for failure */
+static int
+virthba_serverup(struct virtpci_dev *virtpcidev)
+{
+	struct virthba_info *virthbainfo =
+	    (struct virthba_info *) ((struct Scsi_Host *) virtpcidev->scsi.
+				     scsihost)->hostdata;
+
+	DBGINF("virtpcidev busNo<<%d>>devNo<<%d>>", virtpcidev->busNo,
+	       virtpcidev->deviceNo);
+
+	if (!virthbainfo->serverdown) {
+		DBGINF("Server up message recieved while server is already up.\n");
+		return 1;
+	}
+	if (virthbainfo->serverchangingstate) {
+		LOGERR("Server already processing change state message\n");
+		return 0;
+	}
+
+	virthbainfo->serverchangingstate = true;
+	/* Must transition channel to ATTACHED state BEFORE we
+	 * can start using the device again
+	 */
+	ULTRA_CHANNEL_CLIENT_TRANSITION(virthbainfo->chinfo.queueinfo->chan,
+					dev_name(&virtpcidev->generic_dev),
+					CliStateOS,
+					CHANNELCLI_ATTACHED, NULL);
+
+	/* Start Processing the IOVM Response Queue Again */
+	if (!uisthread_start(&virthbainfo->chinfo.threadinfo,
+			     process_incoming_rsps,
+			     virthbainfo, "vhba_incoming")) {
+		LOGERR("uisthread_start rsp ****FAILED\n");
+		return 0;
+	}
+	virthbainfo->serverdown = false;
+	virthbainfo->serverchangingstate = false;
+
+	return 1;
+}
+
+static void
+virthba_serverdown_complete(struct work_struct *work)
+{
+	struct virthba_info *virthbainfo;
+	struct virtpci_dev *virtpcidev;
+	int i;
+	struct scsipending *pendingdel = NULL;
+	struct scsi_cmnd *scsicmd = NULL;
+	struct uiscmdrsp *cmdrsp;
+	unsigned long flags;
+
+	virthbainfo = container_of(work, struct virthba_info,
+				   serverdown_completion);
+
+	/* Stop Using the IOVM Response Queue (queue should be drained
+	 * by the end)
+	 */
+	uisthread_stop(&virthbainfo->chinfo.threadinfo);
+
+	/* Fail Commands that weren't completed */
+	spin_lock_irqsave(&virthbainfo->privlock, flags);
+	for (i = 0; i < MAX_PENDING_REQUESTS; i++) {
+		pendingdel = &(virthbainfo->pending[i]);
+		switch (pendingdel->cmdtype) {
+		case CMD_SCSI_TYPE:
+			scsicmd = (struct scsi_cmnd *) pendingdel->sent;
+			scsicmd->result = (DID_RESET << 16);
+			if (scsicmd->scsi_done)
+				scsicmd->scsi_done(scsicmd);
+			break;
+		case CMD_SCSITASKMGMT_TYPE:
+			cmdrsp = (struct uiscmdrsp *) pendingdel->sent;
+			DBGINF("cmdrsp=0x%x, notify=0x%x\n", cmdrsp,
+			       cmdrsp->scsitaskmgmt.notify);
+			*(int *) cmdrsp->scsitaskmgmt.notifyresult =
+			    TASK_MGMT_FAILED;
+			wake_up_all((wait_queue_head_t *)
+				    cmdrsp->scsitaskmgmt.notify);
+			break;
+		case CMD_VDISKMGMT_TYPE:
+			cmdrsp = (struct uiscmdrsp *) pendingdel->sent;
+			*(int *) cmdrsp->vdiskmgmt.notifyresult =
+			    VDISK_MGMT_FAILED;
+			wake_up_all((wait_queue_head_t *)
+				    cmdrsp->vdiskmgmt.notify);
+			break;
+		default:
+			if (pendingdel->sent != NULL)
+				LOGERR("Unknown command type: 0x%x.  Only freeing list structure.\n",
+				     pendingdel->cmdtype);
+		}
+		pendingdel->cmdtype = 0;
+		pendingdel->sent = NULL;
+	}
+	spin_unlock_irqrestore(&virthbainfo->privlock, flags);
+
+	virtpcidev = virthbainfo->virtpcidev;
+
+	DBGINF("virtpcidev busNo<<%d>>devNo<<%d>>", virtpcidev->busNo,
+	       virtpcidev->deviceNo);
+	virthbainfo->serverdown = true;
+	virthbainfo->serverchangingstate = false;
+	/* Return the ServerDown response to Command */
+	device_pause_response(virtpcidev->busNo, virtpcidev->deviceNo, 0);
+}
+
+/* As per VirtpciFunc returns 1 for success and 0 for failure */
+static int
+virthba_serverdown(struct virtpci_dev *virtpcidev, u32 state)
+{
+	struct virthba_info *virthbainfo =
+	    (struct virthba_info *) ((struct Scsi_Host *) virtpcidev->scsi.
+				     scsihost)->hostdata;
+
+	DBGINF("virthba_serverdown");
+	DBGINF("virtpcidev busNo<<%d>>devNo<<%d>>", virtpcidev->busNo,
+	       virtpcidev->deviceNo);
+
+	if (!virthbainfo->serverdown && !virthbainfo->serverchangingstate) {
+		virthbainfo->serverchangingstate = true;
+		queue_work(virthba_serverdown_workqueue,
+			   &virthbainfo->serverdown_completion);
+	} else if (virthbainfo->serverchangingstate) {
+		LOGERR("Server already processing change state message\n");
+		return 0;
+	} else
+		LOGERR("Server already down, but another server down message received.");
+
+	return 1;
+}
+
+/*****************************************************/
+/* Module Init & Exit functions                      */
+/*****************************************************/
+
+static int __init
+virthba_parse_line(char *str)
+{
+	DBGINF("In virthba_parse_line %s\n", str);
+	return 1;
+}
+
+static void __init
+virthba_parse_options(char *line)
+{
+	char *next = line;
+
+	POSTCODE_LINUX_2(VHBA_CREATE_ENTRY_PC, POSTCODE_SEVERITY_INFO);
+	if (line == NULL || !*line)
+		return;
+	while ((line = next) != NULL) {
+		next = strchr(line, ' ');
+		if (next != NULL)
+			*next++ = 0;
+		if (!virthba_parse_line(line))
+			DBGINF("Unknown option '%s'\n", line);
+	}
+
+	POSTCODE_LINUX_2(VHBA_CREATE_EXIT_PC, POSTCODE_SEVERITY_INFO);
+}
+
+static int __init
+virthba_mod_init(void)
+{
+	int error;
+	int i;
+
+	LOGINF("Entering virthba_mod_init...\n");
+
+	POSTCODE_LINUX_2(VHBA_CREATE_ENTRY_PC, POSTCODE_SEVERITY_INFO);
+	virthba_parse_options(virthba_options);
+
+	error = virtpci_register_driver(&virthba_driver);
+	if (error < 0) {
+		LOGERR("register ****FAILED 0x%x\n", error);
+		POSTCODE_LINUX_3(VHBA_CREATE_FAILURE_PC, error,
+				 POSTCODE_SEVERITY_ERR);
+	} else {
+		/* create the proc directories */
+		virthba_proc_dir = proc_mkdir(DIR_PROC_ENTRY, NULL);
+		info_proc_entry = proc_create(INFO_PROC_ENTRY_FN, 0,
+					      virthba_proc_dir,
+					      &proc_info_fops);
+		rqwaitus_proc_entry = proc_create(RQWU_PROC_ENTRY_FN, 0,
+						  virthba_proc_dir,
+						  &proc_rqwu_fops);
+		enable_ints_proc_entry = proc_create(ENABLE_INTS_ENTRY_FN, 0,
+						     virthba_proc_dir,
+						     &proc_enable_ints_fops);
+
+		/* Initialize DARWorkQ */
+		INIT_WORK(&DARWorkQ, doDiskAddRemove);
+		spin_lock_init(&DARWorkQLock);
+
+		/* clear out array */
+		for (i = 0; i < VIRTHBASOPENMAX; i++)
+			VirtHbasOpen[i].virthbainfo = NULL;
+		/* Initialize the serverdown workqueue */
+		virthba_serverdown_workqueue =
+		    create_singlethread_workqueue("virthba_serverdown");
+		if (virthba_serverdown_workqueue == NULL) {
+			LOGERR("**** FAILED virthba_serverdown_workqueue creation\n");
+			POSTCODE_LINUX_2(VHBA_CREATE_FAILURE_PC,
+					 POSTCODE_SEVERITY_ERR);
+			error = -1;
+		}
+	}
+
+	POSTCODE_LINUX_2(VHBA_CREATE_EXIT_PC, POSTCODE_SEVERITY_INFO);
+	LOGINF("Leaving virthba_mod_init\n");
+	return error;
+}
+
+static ssize_t
+virthba_acquire_lun(struct device *cdev, struct device_attribute *attr,
+		    const char *buf, size_t count)
+{
+	struct uisscsi_dest vdest;
+	struct Scsi_Host *shost = class_to_shost(cdev);
+	int i;
+
+	i = sscanf(buf, "%d-%d-%d", &vdest.channel, &vdest.id, &vdest.lun);
+	if (i != 3)
+		return i;
+
+	return forward_vdiskmgmt_command(VDISK_MGMT_ACQUIRE, shost, &vdest);
+}
+
+static ssize_t
+virthba_release_lun(struct device *cdev, struct device_attribute *attr,
+		    const char *buf, size_t count)
+{
+	struct uisscsi_dest vdest;
+	struct Scsi_Host *shost = class_to_shost(cdev);
+	int i;
+
+	i = sscanf(buf, "%d-%d-%d", &vdest.channel, &vdest.id, &vdest.lun);
+	if (i != 3)
+		return i;
+
+	return forward_vdiskmgmt_command(VDISK_MGMT_RELEASE, shost, &vdest);
+}
+
+#define CLASS_DEVICE_ATTR(_name, _mode, _show, _store)      \
+	struct device_attribute class_device_attr_##_name =   \
+		__ATTR(_name, _mode, _show, _store)
+
+static CLASS_DEVICE_ATTR(acquire_lun, S_IWUSR, NULL, virthba_acquire_lun);
+static CLASS_DEVICE_ATTR(release_lun, S_IWUSR, NULL, virthba_release_lun);
+
+static DEVICE_ATTRIBUTE *virthba_shost_attrs[] = {
+	&class_device_attr_acquire_lun,
+	&class_device_attr_release_lun,
+	NULL
+};
+
+static void __exit
+virthba_mod_exit(void)
+{
+	LOGINF("entering virthba_mod_exit...\n");
+
+	virtpci_unregister_driver(&virthba_driver);
+	/* unregister is going to call virthba_remove */
+	/* destroy serverdown completion workqueue */
+	if (virthba_serverdown_workqueue) {
+		destroy_workqueue(virthba_serverdown_workqueue);
+		virthba_serverdown_workqueue = NULL;
+	}
+
+	if (info_proc_entry)
+		remove_proc_entry(INFO_PROC_ENTRY_FN, virthba_proc_dir);
+
+	if (rqwaitus_proc_entry)
+		remove_proc_entry(RQWU_PROC_ENTRY_FN, NULL);
+
+	if (enable_ints_proc_entry)
+		remove_proc_entry(ENABLE_INTS_ENTRY_FN, NULL);
+
+	if (virthba_proc_dir)
+		remove_proc_entry(DIR_PROC_ENTRY, NULL);
+
+	LOGINF("Leaving virthba_mod_exit\n");
+
+}
+
+/* specify function to be run at module insertion time */
+module_init(virthba_mod_init);
+
+/* specify function to be run when module is removed */
+module_exit(virthba_mod_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Usha Srinivasan");
+MODULE_ALIAS("uisvirthba");
+	/* this is extracted during depmod and kept in modules.dep */
+/* module parameter */
+module_param(virthba_options, charp, S_IRUGO);
diff --git a/drivers/staging/unisys/virthba/virthba.h b/drivers/staging/unisys/virthba/virthba.h
new file mode 100644
index 0000000..88b7974
--- /dev/null
+++ b/drivers/staging/unisys/virthba/virthba.h
@@ -0,0 +1,31 @@
+/* virthba.h
+ *
+ * Copyright © 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+/*
+ * Unisys Virtual HBA driver header
+ */
+
+
+
+#ifndef __VIRTHBA_H__
+#define __VIRTHBA_H__
+
+
+#define VIRTHBA_VERSION "01.00"
+
+
+#endif /* __VIRTHBA_H__ */
diff --git a/drivers/staging/unisys/virtpci/Kconfig b/drivers/staging/unisys/virtpci/Kconfig
new file mode 100644
index 0000000..e59efcb
--- /dev/null
+++ b/drivers/staging/unisys/virtpci/Kconfig
@@ -0,0 +1,10 @@
+#
+# Unisys virtpci configuration
+#
+
+config UNISYS_VIRTPCI
+	tristate "Unisys virtpci driver"
+	depends on UNISYSSPAR && UNISYS_UISLIB
+	---help---
+	If you say Y here, you will enable the Unisys virtpci driver.
+
diff --git a/drivers/staging/unisys/virtpci/Makefile b/drivers/staging/unisys/virtpci/Makefile
new file mode 100644
index 0000000..f9399aa
--- /dev/null
+++ b/drivers/staging/unisys/virtpci/Makefile
@@ -0,0 +1,13 @@
+#
+# Makefile for Unisys virtpci
+#
+
+obj-$(CONFIG_UNISYS_VIRTPCI)	+= virtpci.o
+
+ccflags-y += -Idrivers/staging/unisys/include
+ccflags-y += -Idrivers/staging/unisys/uislib
+ccflags-y += -Idrivers/staging/unisys/common-spar/include
+ccflags-y += -Idrivers/staging/unisys/common-spar/include/channels
+
+ccflags-y += -DCONFIG_SPAR_GUEST -DGUESTDRIVERBUILD -DNOAUTOVERSION
+
diff --git a/drivers/staging/unisys/virtpci/virtpci.c b/drivers/staging/unisys/virtpci/virtpci.c
new file mode 100644
index 0000000..5700e4b
--- /dev/null
+++ b/drivers/staging/unisys/virtpci/virtpci.c
@@ -0,0 +1,1755 @@
+/* virtpci.c
+ *
+ * Copyright © 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+#define EXPORT_SYMTAB
+
+#include <linux/kernel.h>
+#ifdef CONFIG_MODVERSIONS
+#include <config/modversions.h>
+#endif
+#include "uniklog.h"
+#include "diagnostics/appos_subsystems.h"
+#include "uisutils.h"
+#include "commontypes.h"
+#include "vbuschannel.h"
+#include "vbushelper.h"
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/device.h>
+#include <linux/list.h>
+#include <linux/slab.h>
+#include <linux/mod_devicetable.h>
+#include <linux/proc_fs.h>
+#include <linux/if_ether.h>
+#include <linux/version.h>
+#include "version.h"
+#include "guestlinuxdebug.h"
+
+struct driver_private {
+	struct kobject kobj;
+	struct klist klist_devices;
+	struct klist_node knode_bus;
+	struct module_kobject *mkobj;
+	struct device_driver *driver;
+};
+#define to_driver(obj) container_of(obj, struct driver_private, kobj)
+
+/* bus_id went away in 2.6.30 - the size was 20 bytes, so we'll define
+ * it ourselves, and a macro to make getting the field a bit simpler.
+ */
+#ifndef BUS_ID_SIZE
+#define BUS_ID_SIZE 20
+#endif
+
+#define BUS_ID(x) dev_name(x)
+
+#include "virtpci.h"
+
+/* this is shorter than using __FILE__ (full path name) in
+ * debug/info/error messages
+ */
+#define CURRENT_FILE_PC VIRT_PCI_PC_virtpci_c
+#define __MYFILE__ "virtpci.c"
+
+#define VIRTPCI_VERSION "01.00"
+
+/*****************************************************/
+/* Forward declarations                              */
+/*****************************************************/
+
+static int delete_vbus_device(struct device *vbus, void *data);
+static int match_busid(struct device *dev, void *data);
+static void virtpci_bus_release(struct device *dev);
+static void virtpci_device_release(struct device *dev);
+static int virtpci_device_add(struct device *parentbus, int devtype,
+			      struct add_virt_guestpart *addparams,
+			      struct scsi_adap_info *scsi,
+			      struct net_adap_info *net);
+static int virtpci_device_del(struct device *parentbus, int devtype,
+			      struct vhba_wwnn *wwnn, unsigned char macaddr[]);
+static int virtpci_device_serverdown(struct device *parentbus, int devtype,
+				     struct vhba_wwnn *wwnn,
+				     unsigned char macaddr[]);
+static int virtpci_device_serverup(struct device *parentbus, int devtype,
+				   struct vhba_wwnn *wwnn,
+				   unsigned char macaddr[]);
+static ssize_t virtpci_driver_attr_show(struct kobject *kobj,
+					struct attribute *attr, char *buf);
+static ssize_t virtpci_driver_attr_store(struct kobject *kobj,
+					 struct attribute *attr,
+					 const char *buf, size_t count);
+static int virtpci_bus_match(struct device *dev, struct device_driver *drv);
+static int virtpci_uevent(struct device *dev, struct kobj_uevent_env *env);
+static int virtpci_device_suspend(struct device *dev, pm_message_t state);
+static int virtpci_device_resume(struct device *dev);
+static int virtpci_device_probe(struct device *dev);
+static int virtpci_device_remove(struct device *dev);
+static ssize_t virt_proc_write(struct file *file, const char __user *buffer,
+			       size_t count, loff_t *ppos);
+static ssize_t info_proc_read(struct file *file, char __user *buf,
+			      size_t len, loff_t *offset);
+
+static const struct file_operations proc_virt_fops = {
+	.write = virt_proc_write,
+};
+
+static const struct file_operations proc_info_fops = {
+	.read = info_proc_read,
+};
+
+/*****************************************************/
+/* Globals                                           */
+/*****************************************************/
+
+/* methods in bus_type struct allow the bus code to serve as an
+ * intermediary between the device core and individual device core and
+ * individual drivers
+ */
+static struct bus_type virtpci_bus_type = {
+	.name = "uisvirtpci",
+	.match = virtpci_bus_match,
+	.uevent = virtpci_uevent,
+	.suspend = virtpci_device_suspend,
+	.resume = virtpci_device_resume,
+};
+
+static struct device virtpci_rootbus_device = {
+	.init_name = "vbusroot",	/* root bus */
+	.release = virtpci_bus_release
+};
+
+/* filled in with info about parent chipset driver when we register with it */
+static ULTRA_VBUS_DEVICEINFO Chipset_DriverInfo;
+
+static const struct sysfs_ops virtpci_driver_sysfs_ops = {
+	.show = virtpci_driver_attr_show,
+	.store = virtpci_driver_attr_store,
+};
+
+static struct kobj_type virtpci_driver_kobj_type = {
+	.sysfs_ops = &virtpci_driver_sysfs_ops,
+};
+
+static struct virtpci_dev *VpcidevListHead;
+static DEFINE_RWLOCK(VpcidevListLock);
+
+/* filled in with info about this driver, wrt it servicing client busses */
+static ULTRA_VBUS_DEVICEINFO Bus_DriverInfo;
+
+/* virtpci_proc_dir_entry is used to create the proc entry directory
+ * for virtpci
+ */
+static struct proc_dir_entry *virtpci_proc_dir;
+/* virt_proc_entry is used to tell virtpci to add/delete vhbas/vnics/vbuses */
+static struct proc_dir_entry *virt_proc_entry;
+/* info_proc_entry is used to tell virtpci to display current info
+ * kept in the driver
+ */
+static struct proc_dir_entry *info_proc_entry;
+#define VIRT_PROC_ENTRY_FN "virt"
+#define INFO_PROC_ENTRY_FN "info"
+#define DIR_PROC_ENTRY "virtpci"
+
+struct virtpci_busdev {
+	struct device virtpci_bus_device;
+};
+
+/*****************************************************/
+/* Local functions                                   */
+/*****************************************************/
+
+static inline int WAIT_FOR_IO_CHANNEL(ULTRA_IO_CHANNEL_PROTOCOL *chanptr)
+{
+	int count = 120;
+	while (count > 0) {
+
+		if (ULTRA_CHANNEL_SERVER_READY(&chanptr->ChannelHeader))
+			return 1;
+		UIS_THREAD_WAIT_SEC(1);
+		count--;
+	}
+	return 0;
+}
+
+/* Write the contents of <info> to the ULTRA_VBUS_CHANNEL_PROTOCOL.ChpInfo. */
+static int write_vbus_chpInfo(ULTRA_VBUS_CHANNEL_PROTOCOL *chan,
+			      ULTRA_VBUS_DEVICEINFO *info)
+{
+	int off;
+	if (!chan) {
+		LOGERR("vbus channel not present");
+		return -1;
+	}
+	off = sizeof(ULTRA_CHANNEL_PROTOCOL) + chan->HdrInfo.chpInfoByteOffset;
+	if (chan->HdrInfo.chpInfoByteOffset == 0) {
+		LOGERR("vbus channel not used, because chpInfoByteOffset == 0");
+		return -1;
+	}
+	memcpy(((U8 *) (chan)) + off, info, sizeof(*info));
+	return 0;
+}
+
+/* Write the contents of <info> to the ULTRA_VBUS_CHANNEL_PROTOCOL.BusInfo. */
+static int write_vbus_busInfo(ULTRA_VBUS_CHANNEL_PROTOCOL *chan,
+			      ULTRA_VBUS_DEVICEINFO *info)
+{
+	int off;
+	if (!chan) {
+		LOGERR("vbus channel not present");
+		return -1;
+	}
+	off = sizeof(ULTRA_CHANNEL_PROTOCOL) + chan->HdrInfo.busInfoByteOffset;
+	if (chan->HdrInfo.busInfoByteOffset == 0) {
+		LOGERR("vbus channel not used, because busInfoByteOffset == 0");
+		return -1;
+	}
+	memcpy(((U8 *) (chan)) + off, info, sizeof(*info));
+	return 0;
+}
+
+/* Write the contents of <info> to the
+ * ULTRA_VBUS_CHANNEL_PROTOCOL.DevInfo[<devix>].
+ */
+static int
+write_vbus_devInfo(ULTRA_VBUS_CHANNEL_PROTOCOL *chan,
+		   ULTRA_VBUS_DEVICEINFO *info, int devix)
+{
+	int off;
+	if (!chan) {
+		LOGERR("vbus channel not present");
+		return -1;
+	}
+	off =
+	    (sizeof(ULTRA_CHANNEL_PROTOCOL) +
+	     chan->HdrInfo.devInfoByteOffset) +
+	    (chan->HdrInfo.deviceInfoStructBytes * devix);
+	if (chan->HdrInfo.devInfoByteOffset == 0) {
+		LOGERR("vbus channel not used, because devInfoByteOffset == 0");
+		return -1;
+	}
+	memcpy(((U8 *) (chan)) + off, info, sizeof(*info));
+	return 0;
+}
+
+/* adds a vbus
+ * returns 0 failure, 1 success,
+ */
+static int add_vbus(struct add_vbus_guestpart *addparams)
+{
+	int ret;
+	struct device *vbus;
+	vbus = kmalloc(sizeof(struct device), GFP_ATOMIC);
+
+	POSTCODE_LINUX_2(VPCI_CREATE_ENTRY_PC, POSTCODE_SEVERITY_INFO);
+	if (!vbus)
+		return 0;
+
+	memset(vbus, 0, sizeof(struct device));
+	dev_set_name(vbus, "vbus%d", addparams->busNo);
+	vbus->release = virtpci_bus_release;
+	vbus->parent = &virtpci_rootbus_device;	/* root bus is parent */
+	vbus->bus = &virtpci_bus_type;	/* bus type */
+	vbus->platform_data = addparams->chanptr;
+
+	/* register a virt bus device -
+	 * this bus shows up under /sys/devices with .name value
+	 * "virtpci%d" any devices added to this bus then show up under
+	 * /sys/devices/virtpci0
+	 */
+	ret = device_register(vbus);
+	if (ret) {
+		LOGERR("device_register FAILED:%d\n", ret);
+		POSTCODE_LINUX_2(VPCI_CREATE_FAILURE_PC, POSTCODE_SEVERITY_ERR);
+		return 0;
+	}
+	write_vbus_chpInfo(vbus->platform_data /* chanptr */ ,
+			   &Chipset_DriverInfo);
+	write_vbus_busInfo(vbus->platform_data /* chanptr */ , &Bus_DriverInfo);
+	LOGINF("Added vbus %d; device %s created successfully\n",
+	       addparams->busNo, BUS_ID(vbus));
+	POSTCODE_LINUX_2(VPCI_CREATE_EXIT_PC, POSTCODE_SEVERITY_INFO);
+	return 1;
+}
+
+/* for CHANSOCK wwwnn/max are AUTO-GENERATED; for normal channels,
+ * wwnn/max are in the channel header.
+ */
+#define GET_SCSIADAPINFO_FROM_CHANPTR(chanptr) { \
+	scsi.wwnn = ((ULTRA_IO_CHANNEL_PROTOCOL *) chanptr)->vhba.wwnn; \
+	scsi.max = ((ULTRA_IO_CHANNEL_PROTOCOL *) chanptr)->vhba.max; \
+}
+
+/* find bus device with the busid that matches - match_busid matches bus_id */
+#define GET_BUS_DEV(busno) { \
+	sprintf(busid, "vbus%d", busno); \
+	vbus = bus_find_device(&virtpci_bus_type, NULL, \
+			       (void *)busid, match_busid);	\
+	if (!vbus) { \
+		LOGERR("**** FAILED to find vbus %s\n", busid); \
+		return 0; \
+	} \
+}
+
+/* adds a vhba
+ * returns 0 failure, 1 success,
+ */
+static int add_vhba(struct add_virt_guestpart *addparams)
+{
+	int i;
+	struct scsi_adap_info scsi;
+	struct device *vbus;
+	unsigned char busid[BUS_ID_SIZE];
+
+	POSTCODE_LINUX_2(VPCI_CREATE_ENTRY_PC, POSTCODE_SEVERITY_INFO);
+	if (!WAIT_FOR_IO_CHANNEL
+	    ((ULTRA_IO_CHANNEL_PROTOCOL *) addparams->chanptr)) {
+		LOGERR("Timed out.  Channel not ready\n");
+		POSTCODE_LINUX_2(VPCI_CREATE_FAILURE_PC, POSTCODE_SEVERITY_ERR);
+		return 0;
+	}
+
+	GET_SCSIADAPINFO_FROM_CHANPTR(addparams->chanptr);
+
+	GET_BUS_DEV(addparams->busNo);
+
+	LOGINF("Adding vhba wwnn:%x:%x config:%d-%d-%d-%d chanptr:%p\n",
+	       scsi.wwnn.wwnn1, scsi.wwnn.wwnn2,
+	       scsi.max.max_channel, scsi.max.max_id, scsi.max.max_lun,
+	       scsi.max.cmd_per_lun, addparams->chanptr);
+	i = virtpci_device_add(vbus, VIRTHBA_TYPE, addparams, &scsi, NULL);
+	if (i) {
+		LOGINF("Added vhba wwnn:%x:%x chanptr:%p\n", scsi.wwnn.wwnn1,
+		       scsi.wwnn.wwnn2, addparams->chanptr);
+		POSTCODE_LINUX_3(VPCI_CREATE_EXIT_PC, i,
+				 POSTCODE_SEVERITY_INFO);
+	}
+	return i;
+
+}
+
+/* for CHANSOCK macaddr is AUTO-GENERATED; for normal channels,
+ * macaddr is in the channel header.
+ */
+#define GET_NETADAPINFO_FROM_CHANPTR(chanptr) { \
+	memcpy(net.mac_addr, ((ULTRA_IO_CHANNEL_PROTOCOL *) chanptr)->vnic.macaddr, MAX_MACADDR_LEN); \
+	net.num_rcv_bufs = ((ULTRA_IO_CHANNEL_PROTOCOL *) chanptr)->vnic.num_rcv_bufs; \
+	net.mtu = ((ULTRA_IO_CHANNEL_PROTOCOL *) chanptr)->vnic.mtu; \
+	net.zoneGuid = ((ULTRA_IO_CHANNEL_PROTOCOL *) chanptr)->vnic.zoneGuid; \
+}
+
+/* adds a vnic
+ * returns 0 failure, 1 success,
+ */
+static int
+add_vnic(struct add_virt_guestpart *addparams)
+{
+	int i;
+	struct net_adap_info net;
+	struct device *vbus;
+	unsigned char busid[BUS_ID_SIZE];
+
+	POSTCODE_LINUX_2(VPCI_CREATE_ENTRY_PC, POSTCODE_SEVERITY_INFO);
+	if (!WAIT_FOR_IO_CHANNEL
+	    ((ULTRA_IO_CHANNEL_PROTOCOL *) addparams->chanptr)) {
+		LOGERR("Timed out, channel not ready\n");
+		POSTCODE_LINUX_2(VPCI_CREATE_FAILURE_PC, POSTCODE_SEVERITY_ERR);
+		return 0;
+	}
+
+	GET_NETADAPINFO_FROM_CHANPTR(addparams->chanptr);
+
+	GET_BUS_DEV(addparams->busNo);
+
+	LOGINF("Adding vnic macaddr:%02x:%02x:%02x:%02x:%02x:%02x rcvbufs:%d mtu:%d chanptr:%p{%-8.8lx-%-4.4x-%-4.4x-%-2.2x%-2.2x%-2.2x%-2.2x%-2.2x%-2.2x%-2.2x%-2.2x}\n",
+	     net.mac_addr[0], net.mac_addr[1], net.mac_addr[2], net.mac_addr[3],
+	     net.mac_addr[4], net.mac_addr[5], net.num_rcv_bufs, net.mtu,
+	     addparams->chanptr, (ulong) net.zoneGuid.data1, net.zoneGuid.data2,
+	     net.zoneGuid.data3, net.zoneGuid.data4[0], net.zoneGuid.data4[1],
+	     net.zoneGuid.data4[2], net.zoneGuid.data4[3],
+	     net.zoneGuid.data4[4], net.zoneGuid.data4[5],
+	     net.zoneGuid.data4[6], net.zoneGuid.data4[7]);
+	i = virtpci_device_add(vbus, VIRTNIC_TYPE, addparams, NULL, &net);
+	if (i) {
+		LOGINF("Added vnic macaddr:%02x:%02x:%02x:%02x:%02x:%02x\n",
+		       net.mac_addr[0], net.mac_addr[1], net.mac_addr[2],
+		       net.mac_addr[3], net.mac_addr[4], net.mac_addr[5]);
+		POSTCODE_LINUX_3(VPCI_CREATE_EXIT_PC, i,
+				 POSTCODE_SEVERITY_INFO);
+		return 1;
+	}
+	return 0;
+}
+
+/* delete vbus
+ * returns 0 failure, 1 success,
+ */
+static int
+delete_vbus(struct del_vbus_guestpart *delparams)
+{
+	struct device *vbus;
+	unsigned char busid[BUS_ID_SIZE];
+
+	GET_BUS_DEV(delparams->busNo);
+	/* ensure that bus has no devices? -- TBD */
+	LOGINF("Deleting %s\n", BUS_ID(vbus));
+	if (delete_vbus_device(vbus, NULL))
+		return 0;	/* failure */
+	LOGINF("Deleted vbus %d\n", delparams->busNo);
+	return 1;
+}
+
+static int
+delete_vbus_device(struct device *vbus, void *data)
+{
+	int checkforroot = (data != NULL);
+	struct device *pDev = &virtpci_rootbus_device;
+
+	if ((checkforroot) && match_busid(vbus, (void *) BUS_ID(pDev))) {
+		/* skip it - don't delete root bus */
+		LOGINF("skipping root bus\n");
+		return 0;	/* pretend no error */
+	}
+	LOGINF("Calling unregister for %s\n", BUS_ID(vbus));
+	device_unregister(vbus);
+	kfree(vbus);
+	LOGINF("VBus unregister and freed\n");
+	return 0;		/* no error */
+}
+
+/* pause vhba
+* returns 0 failure, 1 success,
+*/
+static int pause_vhba(struct pause_virt_guestpart *pauseparams)
+{
+	int i;
+	struct scsi_adap_info scsi;
+
+	GET_SCSIADAPINFO_FROM_CHANPTR(pauseparams->chanptr);
+
+	LOGINF("Pausing vhba wwnn:%x:%x\n", scsi.wwnn.wwnn1, scsi.wwnn.wwnn2);
+	i = virtpci_device_serverdown(NULL /*no parent bus */ , VIRTHBA_TYPE,
+				      &scsi.wwnn, NULL);
+	if (i)
+		LOGINF("Paused vhba wwnn:%x:%x\n", scsi.wwnn.wwnn1,
+		       scsi.wwnn.wwnn2);
+	return i;
+}
+
+/* pause vnic
+ * returns 0 failure, 1 success,
+ */
+static int pause_vnic(struct pause_virt_guestpart *pauseparams)
+{
+	int i;
+	struct net_adap_info net;
+
+	GET_NETADAPINFO_FROM_CHANPTR(pauseparams->chanptr);
+
+	LOGINF("Pausing vnic macaddr:%02x:%02x:%02x:%02x:%02x:%02x\n",
+	       net.mac_addr[0], net.mac_addr[1], net.mac_addr[2],
+	       net.mac_addr[3], net.mac_addr[4], net.mac_addr[5]);
+	i = virtpci_device_serverdown(NULL /*no parent bus */ , VIRTNIC_TYPE,
+				      NULL, net.mac_addr);
+	if (i) {
+		LOGINF(" Paused vnic macaddr:%02x:%02x:%02x:%02x:%02x:%02x\n",
+		       net.mac_addr[0], net.mac_addr[1], net.mac_addr[2],
+		       net.mac_addr[3], net.mac_addr[4], net.mac_addr[5]);
+	}
+	return i;
+}
+
+/* resume vhba
+ * returns 0 failure, 1 success,
+ */
+static int resume_vhba(struct resume_virt_guestpart *resumeparams)
+{
+	int i;
+	struct scsi_adap_info scsi;
+
+	GET_SCSIADAPINFO_FROM_CHANPTR(resumeparams->chanptr);
+
+	LOGINF("Resuming vhba wwnn:%x:%x\n", scsi.wwnn.wwnn1, scsi.wwnn.wwnn2);
+	i = virtpci_device_serverup(NULL /*no parent bus */ , VIRTHBA_TYPE,
+				    &scsi.wwnn, NULL);
+	if (i)
+		LOGINF("Resumed vhba wwnn:%x:%x\n", scsi.wwnn.wwnn1,
+		       scsi.wwnn.wwnn2);
+	return i;
+}
+
+/* resume vnic
+* returns 0 failure, 1 success,
+*/
+static int
+resume_vnic(struct resume_virt_guestpart *resumeparams)
+{
+	int i;
+	struct net_adap_info net;
+
+	GET_NETADAPINFO_FROM_CHANPTR(resumeparams->chanptr);
+
+	LOGINF("Resuming vnic macaddr:%02x:%02x:%02x:%02x:%02x:%02x\n",
+	       net.mac_addr[0], net.mac_addr[1], net.mac_addr[2],
+	       net.mac_addr[3], net.mac_addr[4], net.mac_addr[5]);
+	i = virtpci_device_serverup(NULL /*no parent bus */ , VIRTNIC_TYPE,
+				    NULL, net.mac_addr);
+	if (i) {
+		LOGINF(" Resumed vnic macaddr:%02x:%02x:%02x:%02x:%02x:%02x\n",
+		       net.mac_addr[0], net.mac_addr[1], net.mac_addr[2],
+		       net.mac_addr[3], net.mac_addr[4], net.mac_addr[5]);
+	}
+	return i;
+}
+
+/* delete vhba
+* returns 0 failure, 1 success,
+*/
+static int delete_vhba(struct del_virt_guestpart *delparams)
+{
+	int i;
+	struct scsi_adap_info scsi;
+
+	GET_SCSIADAPINFO_FROM_CHANPTR(delparams->chanptr);
+
+	LOGINF("Deleting vhba wwnn:%x:%x\n", scsi.wwnn.wwnn1, scsi.wwnn.wwnn2);
+	i = virtpci_device_del(NULL /*no parent bus */ , VIRTHBA_TYPE,
+			       &scsi.wwnn, NULL);
+	if (i) {
+		LOGINF("Deleted vhba wwnn:%x:%x\n", scsi.wwnn.wwnn1,
+		       scsi.wwnn.wwnn2);
+		return 1;
+	}
+	return 0;
+}
+
+/* deletes a vnic
+ * returns 0 failure, 1 success,
+ */
+static int delete_vnic(struct del_virt_guestpart *delparams)
+{
+	int i;
+	struct net_adap_info net;
+
+	GET_NETADAPINFO_FROM_CHANPTR(delparams->chanptr);
+
+	LOGINF("Deleting vnic macaddr:%02x:%02x:%02x:%02x:%02x:%02x\n",
+	       net.mac_addr[0], net.mac_addr[1], net.mac_addr[2],
+	       net.mac_addr[3], net.mac_addr[4], net.mac_addr[5]);
+	i = virtpci_device_del(NULL /*no parent bus */ , VIRTNIC_TYPE, NULL,
+			       net.mac_addr);
+	if (i) {
+		LOGINF("Deleted vnic macaddr:%02x:%02x:%02x:%02x:%02x:%02x\n",
+		       net.mac_addr[0], net.mac_addr[1], net.mac_addr[2],
+		       net.mac_addr[3], net.mac_addr[4], net.mac_addr[5]);
+	}
+	return i;
+}
+
+#define DELETE_ONE_VPCIDEV(vpcidev) { \
+	LOGINF("calling device_unregister:%p\n", &vpcidev->generic_dev); \
+	device_unregister(&vpcidev->generic_dev); \
+	LOGINF("Deleted %p\n", vpcidev); \
+	kfree(vpcidev); \
+}
+
+/* deletes all vhbas and vnics
+ * returns 0 failure, 1 success,
+ */
+static void delete_all(void)
+{
+	int count = 0;
+	unsigned long flags;
+	struct virtpci_dev *tmpvpcidev, *nextvpcidev;
+
+	/* delete the entire vhba/vnic list in one shot */
+	write_lock_irqsave(&VpcidevListLock, flags);
+	tmpvpcidev = VpcidevListHead;
+	VpcidevListHead = NULL;
+	write_unlock_irqrestore(&VpcidevListLock, flags);
+
+	/* delete one vhba/vnic at a time */
+	while (tmpvpcidev) {
+		nextvpcidev = tmpvpcidev->next;
+		/* delete the vhba/vnic at tmpvpcidev */
+		DELETE_ONE_VPCIDEV(tmpvpcidev);
+		tmpvpcidev = nextvpcidev;
+		count++;
+	}
+	LOGINF("Deleted %d vhbas/vnics.\n", count);
+
+	/* now delete each vbus */
+	if (bus_for_each_dev
+	    (&virtpci_bus_type, NULL, (void *) 1, delete_vbus_device))
+		LOGERR("delete of all vbus failed\n");
+}
+
+/* deletes all vnics or vhbas
+ * returns 0 failure, 1 success,
+ */
+static int delete_all_virt(VIRTPCI_DEV_TYPE devtype, struct del_vbus_guestpart *delparams)
+{
+	int i;
+	unsigned char busid[BUS_ID_SIZE];
+	struct device *vbus;
+
+	GET_BUS_DEV(delparams->busNo);
+
+	if ((devtype != VIRTHBA_TYPE) && (devtype != VIRTNIC_TYPE)) {
+		LOGERR("**** FAILED to delete all devices; devtype:%d not vhba:%d or vnic:%d\n",
+		     devtype, VIRTHBA_TYPE, VIRTNIC_TYPE);
+		return 0;
+	}
+
+	LOGINF("Deleting all %s in vbus %s\n",
+	       devtype == VIRTHBA_TYPE ? "vhbas" : "vnics", busid);
+	/* delete all vhbas/vnics */
+	i = virtpci_device_del(vbus, devtype, NULL, NULL);
+	if (i > 0)
+		LOGINF("Deleted %d %s\n", i,
+		       devtype == VIRTHBA_TYPE ? "vhbas" : "vnics");
+	return 1;
+}
+
+static int virtpci_ctrlchan_func(struct guest_msgs *msg)
+{
+	switch (msg->msgtype) {
+	case GUEST_ADD_VBUS:
+		return add_vbus(&msg->add_vbus);
+	case GUEST_ADD_VHBA:
+		return add_vhba(&msg->add_vhba);
+	case GUEST_ADD_VNIC:
+		return add_vnic(&msg->add_vnic);
+	case GUEST_DEL_VBUS:
+		return delete_vbus(&msg->del_vbus);
+	case GUEST_DEL_VHBA:
+		return delete_vhba(&msg->del_vhba);
+	case GUEST_DEL_VNIC:
+		return delete_vnic(&msg->del_vhba);
+	case GUEST_DEL_ALL_VHBAS:
+		return delete_all_virt(VIRTHBA_TYPE, &msg->del_all_vhbas);
+	case GUEST_DEL_ALL_VNICS:
+		return delete_all_virt(VIRTNIC_TYPE, &msg->del_all_vnics);
+	case GUEST_DEL_ALL_VBUSES:
+		delete_all();
+		return 1;
+	case GUEST_PAUSE_VHBA:
+		return pause_vhba(&msg->pause_vhba);
+	case GUEST_PAUSE_VNIC:
+		return pause_vnic(&msg->pause_vnic);
+	case GUEST_RESUME_VHBA:
+		return resume_vhba(&msg->resume_vhba);
+	case GUEST_RESUME_VNIC:
+		return resume_vnic(&msg->resume_vnic);
+	default:
+		LOGERR("invalid message type %d.\n", msg->msgtype);
+		return 0;
+	}
+}
+
+/* same as driver_helper in bus.c linux */
+static int match_busid(struct device *dev, void *data)
+{
+	const char *name = data;
+
+	if (strcmp(name, BUS_ID(dev)) == 0)
+		return 1;
+	return 0;
+}
+
+/*****************************************************/
+/*  Bus functions                                    */
+/*****************************************************/
+
+const struct pci_device_id *
+virtpci_match_device(const struct pci_device_id *ids,
+		     const struct virtpci_dev *dev)
+{
+	while (ids->vendor || ids->subvendor || ids->class_mask) {
+		DBGINF("ids->vendor:%x dev->vendor:%x ids->device:%x dev->device:%x\n",
+		     ids->vendor, dev->vendor, ids->device, dev->device);
+
+		if ((ids->vendor == dev->vendor)
+		    && (ids->device == dev->device))
+			return ids;
+
+		ids++;
+	}
+	return NULL;
+}
+
+/* NOTE: !!!!!!  This function is called when a new device is added
+* for this bus.  Or, it is called for existing devices when a new
+* driver is added for this bus.  It returns nonzero if a given device
+* can be handled by the given driver.
+*/
+static int virtpci_bus_match(struct device *dev, struct device_driver *drv)
+{
+	struct virtpci_dev *virtpcidev = device_to_virtpci_dev(dev);
+	struct virtpci_driver *virtpcidrv = driver_to_virtpci_driver(drv);
+	int match = 0;
+
+	DBGINF("In virtpci_bus_match dev->bus_id:%s drv->name:%s\n",
+	       dev->bus_id, drv->name);
+
+	/* check ids list for a match */
+	if (virtpci_match_device(virtpcidrv->id_table, virtpcidev))
+		match = 1;
+
+	DBGINF("returning match:%d\n", match);
+	return match;		/* 0 - no match; 1 - yes it matches */
+}
+
+static int virtpci_uevent(struct device *dev, struct kobj_uevent_env *env)
+{
+	DBGINF("In virtpci_hotplug\n");
+	/* add variables to the environment prior to the generation of
+	 * hotplug events to user space
+	 */
+	if (add_uevent_var(env, "VIRTPCI_VERSION=%s", VIRTPCI_VERSION))
+		return -ENOMEM;
+	return 0;
+}
+
+static int virtpci_device_suspend(struct device *dev, pm_message_t state)
+{
+	DBGINF("In virtpci_device_suspend -NYI ****\n");
+	return 0;
+}
+
+static int virtpci_device_resume(struct device *dev)
+{
+	DBGINF("In virtpci_device_resume -NYI ****\n");
+	return 0;
+}
+
+/* For a child device just created on a client bus, fill in
+ * information about the driver that is controlling this device into
+ * the the appropriate slot within the vbus channel of the bus
+ * instance.
+ */
+static void fix_vbus_devInfo(struct device *dev, int devNo, int devType,
+			     struct virtpci_driver *virtpcidrv)
+{
+	struct device *vbus;
+	void *pChan;
+	ULTRA_VBUS_DEVICEINFO devInfo;
+	const char *stype;
+
+	if (!dev) {
+		LOGERR("%s dev is NULL", __func__);
+		return;
+	}
+	if (!virtpcidrv) {
+		LOGERR("%s driver is NULL", __func__);
+		return;
+	}
+	vbus = dev->parent;
+	if (!vbus) {
+		LOGERR("%s dev has no parent bus", __func__);
+		return;
+	}
+	pChan = vbus->platform_data;
+	if (!pChan) {
+		LOGERR("%s dev bus has no channel", __func__);
+		return;
+	}
+	switch (devType) {
+	case PCI_DEVICE_ID_VIRTHBA:
+		stype = "vHBA";
+		break;
+	case PCI_DEVICE_ID_VIRTNIC:
+		stype = "vNIC";
+		break;
+	default:
+		stype = "unknown";
+		break;
+	}
+	BusDeviceInfo_Init(&devInfo, stype,
+			   virtpcidrv->name,
+			   virtpcidrv->version,
+			   virtpcidrv->vertag,
+			   virtpcidrv->build_date, virtpcidrv->build_time);
+	write_vbus_devInfo(pChan, &devInfo, devNo);
+
+	/* Re-write bus+chipset info, because it is possible that this
+	* was previously written by our good counterpart, visorbus.
+	*/
+	write_vbus_chpInfo(pChan, &Chipset_DriverInfo);
+	write_vbus_busInfo(pChan, &Bus_DriverInfo);
+}
+
+/* This function is called to query the existence of a specific device
+* and whether this driver can work with it.  It should return -ENODEV
+* in case of failure.
+*/
+static int virtpci_device_probe(struct device *dev)
+{
+	struct virtpci_dev *virtpcidev = device_to_virtpci_dev(dev);
+	struct virtpci_driver *virtpcidrv =
+	    driver_to_virtpci_driver(dev->driver);
+	const struct pci_device_id *id;
+	int error = 0;
+
+	LOGINF("In virtpci_device_probe dev:%p virtpcidev:%p virtpcidrv:%p\n",
+	       dev, virtpcidev, virtpcidrv);	/* VERBOSE/DEBUG ? */
+	POSTCODE_LINUX_2(VPCI_PROBE_ENTRY_PC, POSTCODE_SEVERITY_INFO);
+	/* static match and static probe vs dynamic match & dynamic
+	 * probe - do we care?.
+	 */
+	if (!virtpcidrv->id_table)
+		return -ENODEV;
+
+	id = virtpci_match_device(virtpcidrv->id_table, virtpcidev);
+	if (!id)
+		return -ENODEV;
+
+	/* increment reference count */
+	get_device(dev);
+
+	/* if virtpcidev is not already claimed & probe function is
+	 * valid, probe it
+	 */
+	if (!virtpcidev->mydriver && virtpcidrv->probe) {
+		/* call the probe function - virthba or virtnic probe
+		 * is what it should be
+		 */
+		error = virtpcidrv->probe(virtpcidev, id);
+		if (!error) {
+			fix_vbus_devInfo(dev, virtpcidev->deviceNo,
+					 virtpcidev->device, virtpcidrv);
+			virtpcidev->mydriver = virtpcidrv;
+			POSTCODE_LINUX_2(VPCI_PROBE_EXIT_PC,
+					 POSTCODE_SEVERITY_INFO);
+		} else
+			put_device(dev);
+	}
+	POSTCODE_LINUX_2(VPCI_PROBE_FAILURE_PC, POSTCODE_SEVERITY_ERR);
+	return error;		/* -ENODEV for probe failure */
+}
+
+static int virtpci_device_remove(struct device *dev_)
+{
+	/* dev_ passed in is the HBA device which we called
+	* generic_dev in our virtpcidev struct
+	*/
+	struct virtpci_dev *virtpcidev = device_to_virtpci_dev(dev_);
+	struct virtpci_driver *virtpcidrv = virtpcidev->mydriver;
+	LOGINF("In virtpci_device_remove bus_id:%s dev_:%p virtpcidev:%p dev->driver:%p drivername:%s\n",
+	       BUS_ID(dev_), dev_, virtpcidev, dev_->driver,
+	       dev_->driver->name);	/* VERBOSE/DEBUG */
+	if (virtpcidrv) {
+		/* TEMP: assuming we have only one such driver for now */
+		if (virtpcidrv->remove)
+			virtpcidrv->remove(virtpcidev);
+		virtpcidev->mydriver = NULL;
+	}
+
+	DBGINF("calling putdevice\n");
+	put_device(dev_);
+
+	DBGINF("Leaving\n");
+	return 0;
+}
+
+/*****************************************************/
+/* Bus functions                                     */
+/*****************************************************/
+
+static void virtpci_bus_release(struct device *dev)
+{
+	/* this function is called when the last reference to the
+	 * device is removed
+	 */
+	DBGINF("In virtpci_bus_release\n");
+	/* what else is supposed to happen here? */
+}
+
+/*****************************************************/
+/* Adapter functions                                 */
+/*****************************************************/
+
+static int virtpci_device_add(struct device *parentbus, int devtype,
+			      struct add_virt_guestpart *addparams,
+			      struct scsi_adap_info *scsi, /* NULL for VNIC add */
+			      struct net_adap_info *net	/* NULL for VHBA add */)
+{
+	struct virtpci_dev *virtpcidev = NULL;
+	struct virtpci_dev *tmpvpcidev = NULL, *prev;
+	unsigned long flags;
+	int ret;
+	ULTRA_IO_CHANNEL_PROTOCOL *pIoChan = NULL;
+	struct device *pDev;
+
+	LOGINF("virtpci_device_add parentbus:%p chanptr:%p\n", parentbus,
+	       addparams->chanptr);
+
+	POSTCODE_LINUX_2(VPCI_CREATE_ENTRY_PC, POSTCODE_SEVERITY_INFO);
+
+	if ((devtype != VIRTHBA_TYPE) && (devtype != VIRTNIC_TYPE)) {
+		LOGERR("**** FAILED to add device; devtype:%d not vhba:%d or vnic:%d\n",
+		     devtype, VIRTHBA_TYPE, VIRTNIC_TYPE);
+		POSTCODE_LINUX_3(VPCI_CREATE_FAILURE_PC, devtype,
+				 POSTCODE_SEVERITY_ERR);
+		return 0;
+	}
+
+	/* add a Virtual Device */
+	virtpcidev = kmalloc(sizeof(struct virtpci_dev), GFP_ATOMIC);
+	if (virtpcidev == NULL) {
+		LOGERR("can't add device - malloc FALLED\n");
+		POSTCODE_LINUX_2(MALLOC_FAILURE_PC, POSTCODE_SEVERITY_ERR);
+		return 0;
+	}
+
+	memset(virtpcidev, 0, sizeof(struct virtpci_dev));
+
+	/* initialize stuff unique to virtpci_dev struct */
+	virtpcidev->devtype = devtype;
+	if (devtype == VIRTHBA_TYPE) {
+		virtpcidev->device = PCI_DEVICE_ID_VIRTHBA;
+		virtpcidev->scsi = *scsi;
+	} else {
+		virtpcidev->device = PCI_DEVICE_ID_VIRTNIC;
+		virtpcidev->net = *net;
+	}
+	virtpcidev->vendor = PCI_VENDOR_ID_UNISYS;
+	virtpcidev->busNo = addparams->busNo;
+	virtpcidev->deviceNo = addparams->deviceNo;
+
+	virtpcidev->queueinfo.chan = addparams->chanptr;
+	virtpcidev->queueinfo.send_int_if_needed = NULL;
+
+	/* Set up safe queue... */
+	pIoChan = (ULTRA_IO_CHANNEL_PROTOCOL *) virtpcidev->queueinfo.chan;
+
+	virtpcidev->intr = addparams->intr;
+
+	/* initialize stuff in the device portion of the struct */
+	virtpcidev->generic_dev.bus = &virtpci_bus_type;
+	virtpcidev->generic_dev.parent = parentbus;
+	virtpcidev->generic_dev.release = virtpci_device_release;
+
+	dev_set_name(&virtpcidev->generic_dev, "%x:%x",
+		     addparams->busNo, addparams->deviceNo);
+
+	/* add the vhba/vnic to virtpci device list - but check for
+	 * duplicate wwnn/macaddr first
+	 */
+	write_lock_irqsave(&VpcidevListLock, flags);
+	for (tmpvpcidev = VpcidevListHead; tmpvpcidev;
+	     tmpvpcidev = tmpvpcidev->next) {
+		if (devtype == VIRTHBA_TYPE) {
+			if ((tmpvpcidev->scsi.wwnn.wwnn1 == scsi->wwnn.wwnn1) &&
+			    (tmpvpcidev->scsi.wwnn.wwnn2 == scsi->wwnn.wwnn2)) {
+				/* duplicate - already have vpcidev
+				   with this wwnn */
+				break;
+			}
+		} else
+		    if (memcmp
+			(tmpvpcidev->net.mac_addr, net->mac_addr,
+			 MAX_MACADDR_LEN) == 0) {
+			/* duplicate - already have vnic with this wwnn */
+			break;
+		}
+	}
+	if (tmpvpcidev) {
+		/* found a vhba/vnic already in the list with same
+		 * wwnn or macaddr - reject add
+		 */
+		write_unlock_irqrestore(&VpcidevListLock, flags);
+		kfree(virtpcidev);
+		LOGERR("**** FAILED vhba/vnic already exists in the list\n");
+		POSTCODE_LINUX_2(VPCI_CREATE_FAILURE_PC, POSTCODE_SEVERITY_ERR);
+		return 0;
+	}
+
+	/* add it at the head */
+	if (!VpcidevListHead)
+		VpcidevListHead = virtpcidev;
+	else {
+		/* insert virtpcidev at the head of our linked list of
+		 * vpcidevs
+		 */
+		virtpcidev->next = VpcidevListHead;
+		VpcidevListHead = virtpcidev;
+	}
+
+	write_unlock_irqrestore(&VpcidevListLock, flags);
+
+	/* Must transition channel to ATTACHED state BEFORE
+	 * registering the device, because polling of the channel
+	 * queues can begin at any time after device_register().
+	 */
+	pDev = &virtpcidev->generic_dev;
+	ULTRA_CHANNEL_CLIENT_TRANSITION(addparams->chanptr,
+					BUS_ID(pDev),
+					CliStateOS, CHANNELCLI_ATTACHED, NULL);
+
+	/* don't register until device has been added to
+	* list. Otherwise, a device_unregister from this function can
+	* cause a "scheduling while atomic".
+	*/
+	DBGINF("registering device:%p with bus_id:%s\n",
+	       &virtpcidev->generic_dev, virtpcidev->generic_dev.bus_id);
+	ret = device_register(&virtpcidev->generic_dev);
+	/* NOTE: THIS IS CALLING HOTPLUG virtpci_hotplug!!!
+	 * This call to device_register results in virtpci_bus_match
+	 * being called !!!!!  And, if match returns success, then
+	 * virtpcidev->generic_dev.driver is setup to core_driver,
+	 * i.e., virtpci and the probe function
+	 * virtpcidev->generic_dev.driver->probe is called which
+	 * results in virtpci_device_probe being called. And if
+	 * virtpci_device_probe is successful
+	 */
+	if (ret) {
+		LOGERR("device_register returned %d\n", ret);
+		pDev = &virtpcidev->generic_dev;
+		ULTRA_CHANNEL_CLIENT_TRANSITION(addparams->chanptr,
+						BUS_ID(pDev),
+						CliStateOS,
+						CHANNELCLI_DETACHED, NULL);
+		/* remove virtpcidev, the one we just added, from the list */
+		write_lock_irqsave(&VpcidevListLock, flags);
+		for (tmpvpcidev = VpcidevListHead, prev = NULL;
+		     tmpvpcidev;
+		     prev = tmpvpcidev, tmpvpcidev = tmpvpcidev->next) {
+			if (tmpvpcidev == virtpcidev) {
+				if (prev)
+					prev->next = tmpvpcidev->next;
+				else
+					VpcidevListHead = tmpvpcidev->next;
+				break;
+			}
+		}
+		write_unlock_irqrestore(&VpcidevListLock, flags);
+		kfree(virtpcidev);
+		return 0;
+	}
+
+	LOGINF("Added %s:%d:%d &virtpcidev->generic_dev:%p\n",
+	       (devtype == VIRTHBA_TYPE) ? "virthba" : "virtnic",
+	       addparams->busNo, addparams->deviceNo, &virtpcidev->generic_dev);
+	POSTCODE_LINUX_2(VPCI_CREATE_EXIT_PC, POSTCODE_SEVERITY_INFO);
+	return 1;
+}
+
+static int virtpci_device_serverdown(struct device *parentbus,
+				     int devtype,
+				     struct vhba_wwnn *wwnn,
+				     unsigned char macaddr[])
+{
+	int pausethisone = 0;
+	bool found = false;
+	struct virtpci_dev *tmpvpcidev, *prevvpcidev;
+	struct virtpci_driver *vpcidriver;
+	unsigned long flags;
+	int rc = 0;
+
+	if ((devtype != VIRTHBA_TYPE) && (devtype != VIRTNIC_TYPE)) {
+		LOGERR("**** FAILED to pause device; devtype:%d not vhba:%d or vnic:%d\n",
+		       devtype, VIRTHBA_TYPE, VIRTNIC_TYPE);
+		return 0;
+	}
+
+	/* find the vhba or vnic in virtpci device list */
+	write_lock_irqsave(&VpcidevListLock, flags);
+
+	for (tmpvpcidev = VpcidevListHead, prevvpcidev = NULL;
+	     (tmpvpcidev && !found);
+	     prevvpcidev = tmpvpcidev, tmpvpcidev = tmpvpcidev->next) {
+		if (tmpvpcidev->devtype != devtype)
+			continue;
+
+		if (devtype == VIRTHBA_TYPE) {
+			pausethisone =
+			    ((tmpvpcidev->scsi.wwnn.wwnn1 == wwnn->wwnn1) &&
+			     (tmpvpcidev->scsi.wwnn.wwnn2 == wwnn->wwnn2));
+			/* devtype is vhba, we're pausing vhba whose
+			* wwnn matches the current device's wwnn
+			*/
+		} else {	/* VIRTNIC_TYPE */
+			pausethisone =
+			    memcmp(tmpvpcidev->net.mac_addr, macaddr,
+				   MAX_MACADDR_LEN) == 0;
+			/* devtype is vnic, we're pausing vnic whose
+			* macaddr matches the current device's macaddr */
+		}
+
+		if (!pausethisone)
+			continue;
+
+		found = true;
+		vpcidriver = tmpvpcidev->mydriver;
+		rc = vpcidriver->suspend(tmpvpcidev, 0);
+	}
+	write_unlock_irqrestore(&VpcidevListLock, flags);
+
+	if (!found) {
+		LOGERR("**** FAILED to find vhba/vnic in the list\n");
+		return 0;
+	}
+
+	return rc;
+}
+
+static int virtpci_device_serverup(struct device *parentbus,
+				   int devtype,
+				   struct vhba_wwnn *wwnn,
+				   unsigned char macaddr[])
+{
+	int resumethisone = 0;
+	bool found = false;
+	struct virtpci_dev *tmpvpcidev, *prevvpcidev;
+	struct virtpci_driver *vpcidriver;
+	unsigned long flags;
+	int rc = 0;
+
+	if ((devtype != VIRTHBA_TYPE) && (devtype != VIRTNIC_TYPE)) {
+		LOGERR("**** FAILED to resume device; devtype:%d not vhba:%d or vnic:%d\n",
+		       devtype, VIRTHBA_TYPE, VIRTNIC_TYPE);
+		return 0;
+	}
+
+	/* find the vhba or vnic in virtpci device list */
+	write_lock_irqsave(&VpcidevListLock, flags);
+
+	for (tmpvpcidev = VpcidevListHead, prevvpcidev = NULL;
+	     (tmpvpcidev && !found);
+	     prevvpcidev = tmpvpcidev, tmpvpcidev = tmpvpcidev->next) {
+		if (tmpvpcidev->devtype != devtype)
+			continue;
+
+		if (devtype == VIRTHBA_TYPE) {
+			resumethisone =
+			    ((tmpvpcidev->scsi.wwnn.wwnn1 == wwnn->wwnn1) &&
+			     (tmpvpcidev->scsi.wwnn.wwnn2 == wwnn->wwnn2));
+			/* devtype is vhba, we're resuming vhba whose
+			* wwnn matches the current device's wwnn */
+		} else {	/* VIRTNIC_TYPE */
+			resumethisone =
+			    memcmp(tmpvpcidev->net.mac_addr, macaddr,
+				   MAX_MACADDR_LEN) == 0;
+			/* devtype is vnic, we're resuming vnic whose
+			* macaddr matches the current device's macaddr */
+		}
+
+		if (!resumethisone)
+			continue;
+
+		found = true;
+		vpcidriver = tmpvpcidev->mydriver;
+		/* This should be done at BUS resume time, but an
+		* existing problem prevents us from ever getting a bus
+		* resume...  This hack would fail to work should we
+		* ever have a bus that contains NO devices, since we
+		* would never even get here in that case.
+		*/
+		fix_vbus_devInfo(&tmpvpcidev->generic_dev, tmpvpcidev->deviceNo,
+				 tmpvpcidev->device, vpcidriver);
+		rc = vpcidriver->resume(tmpvpcidev);
+	}
+
+	write_unlock_irqrestore(&VpcidevListLock, flags);
+
+	if (!found) {
+		LOGERR("**** FAILED to find vhba/vnic in the list\n");
+		return 0;
+	}
+
+	return rc;
+}
+
+static int virtpci_device_del(struct device *parentbus,
+			      int devtype, struct vhba_wwnn *wwnn,
+			      unsigned char macaddr[])
+{
+	int count = 0, all = 0, delthisone;
+	struct virtpci_dev *tmpvpcidev, *prevvpcidev, *dellist = NULL;
+	unsigned long flags;
+
+#define DEL_CONTINUE { \
+	prevvpcidev = tmpvpcidev;\
+	tmpvpcidev = tmpvpcidev->next;\
+	continue; \
+}
+
+	if ((devtype != VIRTHBA_TYPE) && (devtype != VIRTNIC_TYPE)) {
+		LOGERR("**** FAILED to delete device; devtype:%d not vhba:%d or vnic:%d\n",
+		       devtype, VIRTHBA_TYPE, VIRTNIC_TYPE);
+		return 0;
+	}
+
+	/* see if we are to delete all - NOTE: all implies we have a
+	 * valid parentbus
+	 */
+	all = ((devtype == VIRTHBA_TYPE) && (wwnn == NULL)) ||
+	    ((devtype == VIRTNIC_TYPE) && (macaddr == NULL));
+
+	/* find all the vhba or vnic or both in virtpci device list
+	* keep list of ones we are deleting so we can call
+	* device_unregister after we release the lock; otherwise we
+	* encounter "schedule while atomic"
+	*/
+	write_lock_irqsave(&VpcidevListLock, flags);
+	for (tmpvpcidev = VpcidevListHead, prevvpcidev = NULL; tmpvpcidev;) {
+		if (tmpvpcidev->devtype != devtype)
+			DEL_CONTINUE;
+
+		if (all) {
+			delthisone =
+			    (tmpvpcidev->generic_dev.parent == parentbus);
+			/* we're deleting all vhbas or vnics on the
+			 * specified parent bus
+			 */
+		} else if (devtype == VIRTHBA_TYPE) {
+			delthisone =
+			    ((tmpvpcidev->scsi.wwnn.wwnn1 == wwnn->wwnn1) &&
+			     (tmpvpcidev->scsi.wwnn.wwnn2 == wwnn->wwnn2));
+			/* devtype is vhba, we're deleting vhba whose
+			 * wwnn matches the current device's wwnn
+			 */
+		} else {	/* VIRTNIC_TYPE */
+			delthisone =
+			    memcmp(tmpvpcidev->net.mac_addr, macaddr,
+				   MAX_MACADDR_LEN) == 0;
+			/* devtype is vnic, we're deleting vnic whose
+			* macaddr matches the current device's macaddr
+			*/
+		}
+
+		if (!delthisone)
+			DEL_CONTINUE;
+
+		/* take vhba/vnic out of the list */
+		if (prevvpcidev)
+			/* not at head */
+			prevvpcidev->next = tmpvpcidev->next;
+		else
+			VpcidevListHead = tmpvpcidev->next;
+
+		/* add it to our deletelist */
+		tmpvpcidev->next = dellist;
+		dellist = tmpvpcidev;
+
+		count++;
+		if (!all)
+			break;	/* done */
+		/* going to top of loop again - set tmpvpcidev to next
+		 * one we're to process
+		 */
+		if (prevvpcidev)
+			tmpvpcidev = prevvpcidev->next;
+		else
+			tmpvpcidev = VpcidevListHead;
+	}
+	write_unlock_irqrestore(&VpcidevListLock, flags);
+
+	if (!all && (count == 0)) {
+		LOGERR("**** FAILED to find vhba/vnic in the list\n");
+		return 0;
+	}
+
+	/* now delete each one from delete list */
+	while (dellist) {
+		/* save next */
+		tmpvpcidev = dellist->next;
+		/* delete the vhba/vnic at dellist */
+		DELETE_ONE_VPCIDEV(dellist);
+		/* do next */
+		dellist = tmpvpcidev;
+	}
+
+	return count;
+}
+
+static void virtpci_device_release(struct device *dev_)
+{
+	/* this function is called when the last reference to the
+	 * device is removed
+	 */
+	LOGINF("In virtpci_device_release:%p - NOT YET IMPLEMENTED\n", dev_);
+}
+
+/*****************************************************/
+/* Driver functions                                  */
+/*****************************************************/
+
+#define kobj_to_device_driver(obj) container_of(obj, struct device_driver, kobj)
+#define attribute_to_driver_attribute(obj) \
+	container_of(obj, struct driver_attribute, attr)
+
+static ssize_t virtpci_driver_attr_show(struct kobject *kobj,
+					struct attribute *attr,
+					char *buf)
+{
+	struct driver_attribute *dattr = attribute_to_driver_attribute(attr);
+	ssize_t ret = 0;
+
+	struct driver_private *dprivate = to_driver(kobj);
+	struct device_driver *driver;
+	if (dprivate != NULL)
+		driver = dprivate->driver;
+	else
+		driver = NULL;
+
+	DBGINF("In virtpci_driver_attr_show driver->name:%s\n", driver->name);
+	if (driver) {
+		if (dattr->show)
+			ret = dattr->show(driver, buf);
+	}
+	return ret;
+}
+
+static ssize_t virtpci_driver_attr_store(struct kobject *kobj,
+					 struct attribute *attr,
+					 const char *buf, size_t count)
+{
+	struct driver_attribute *dattr = attribute_to_driver_attribute(attr);
+	ssize_t ret = 0;
+
+	struct driver_private *dprivate = to_driver(kobj);
+	struct device_driver *driver;
+	if (dprivate != NULL)
+		driver = dprivate->driver;
+	else
+		driver = NULL;
+
+	DBGINF("In virtpci_driver_attr_store driver->name:%s\n", driver->name);
+
+	if (driver) {
+		if (dattr->store)
+			ret = dattr->store(driver, buf, count);
+	}
+	return ret;
+}
+
+/* register a new virtpci driver */
+int virtpci_register_driver(struct virtpci_driver *drv)
+{
+	int result = 0;
+
+	DBGINF("In virtpci_register_driver\n");
+
+	if (drv->id_table == NULL) {
+		LOGERR("id_table missing\n");
+		return 1;
+	}
+	/* initialize core driver fields needed to call driver_register */
+	drv->core_driver.name = drv->name;	/* name of driver in sysfs */
+	drv->core_driver.bus = &virtpci_bus_type;	/* type of bus this
+							 * driver works with */
+	drv->core_driver.probe = virtpci_device_probe;	/* called to query the
+							 * existence of a
+							 * specific device and
+							 * whether this driver
+							 *can work with it */
+	drv->core_driver.remove = virtpci_device_remove; /* called when the
+							  * device is removed
+							  * from the system */
+	/* register with core */
+	result = driver_register(&drv->core_driver);
+	/* calls bus_add_driver which calls driver_attach and
+	 * module_add_driver
+	 */
+	if (result)
+		return result;	/* failed */
+
+	drv->core_driver.p->kobj.ktype = &virtpci_driver_kobj_type;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(virtpci_register_driver);
+
+void virtpci_unregister_driver(struct virtpci_driver *drv)
+{
+	DBGINF("In virtpci_unregister_driver drv:%p\n", drv);
+	driver_unregister(&drv->core_driver);
+	/* driver_unregister calls bus_remove_driver
+	 * bus_remove_driver calls device_detach
+	 * device_detach calls device_release_driver for each of the
+	 * driver's devices
+	 * device_release driver calls drv->remove which is
+	 * virtpci_device_remove
+	 * virtpci_device_remove calls virthba_remove
+	 */
+	DBGINF("Leaving\n");
+}
+EXPORT_SYMBOL_GPL(virtpci_unregister_driver);
+
+/*****************************************************/
+/* proc filesystem functions						 */
+/*****************************************************/
+struct print_vbus_info {
+	int *length;
+	char *buf;
+};
+
+static int print_vbus(struct device *vbus, void *data)
+{
+	struct print_vbus_info *p = (struct print_vbus_info *) data;
+	int l = *(p->length);
+
+	*(p->length) = l + sprintf(p->buf + l, "bus_id:%s\n", dev_name(vbus));
+	return 0;		/* no error */
+}
+
+static ssize_t info_proc_read(struct file *file, char __user *buf,
+			      size_t len, loff_t *offset)
+{
+	int length = 0;
+	struct virtpci_dev *tmpvpcidev;
+	unsigned long flags;
+	struct print_vbus_info printparam;
+	char *vbuf;
+	loff_t pos = *offset;
+
+	if (pos < 0)
+		return -EINVAL;
+
+	if (pos > 0 || !len)
+		return 0;
+
+	vbuf = kzalloc(len, GFP_KERNEL);
+	if (!vbuf)
+		return -ENOMEM;
+
+	length += sprintf(vbuf + length, "CHANSOCK is not defined.\n");
+
+	length += sprintf(vbuf + length, "\n Virtual PCI Bus devices\n");
+	printparam.length = &length;
+	printparam.buf = vbuf;
+	if (bus_for_each_dev(&virtpci_bus_type, NULL,
+			     (void *) &printparam, print_vbus))
+		LOGERR("delete of all vbus failed\n");
+
+	length += sprintf(vbuf + length, "\n Virtual PCI devices\n");
+	read_lock_irqsave(&VpcidevListLock, flags);
+	tmpvpcidev = VpcidevListHead;
+	while (tmpvpcidev) {
+		if (tmpvpcidev->devtype == VIRTHBA_TYPE) {
+			length += sprintf(vbuf + length, "[%d:%d] VHba:%08x:%08x max-config:%d-%d-%d-%d",
+				    tmpvpcidev->busNo, tmpvpcidev->deviceNo,
+				    tmpvpcidev->scsi.wwnn.wwnn1,
+				    tmpvpcidev->scsi.wwnn.wwnn2,
+				    tmpvpcidev->scsi.max.max_channel,
+				    tmpvpcidev->scsi.max.max_id,
+				    tmpvpcidev->scsi.max.max_lun,
+				    tmpvpcidev->scsi.max.cmd_per_lun);
+		} else {
+			length += sprintf(vbuf + length, "[%d:%d] VNic:%02x:%02x:%02x:%02x:%02x:%02x num_rcv_bufs:%d mtu:%d",
+				    tmpvpcidev->busNo, tmpvpcidev->deviceNo,
+				    tmpvpcidev->net.mac_addr[0],
+				    tmpvpcidev->net.mac_addr[1],
+				    tmpvpcidev->net.mac_addr[2],
+				    tmpvpcidev->net.mac_addr[3],
+				    tmpvpcidev->net.mac_addr[4],
+				    tmpvpcidev->net.mac_addr[5],
+				    tmpvpcidev->net.num_rcv_bufs,
+				    tmpvpcidev->net.mtu);
+		}
+		length +=
+		    sprintf(vbuf + length, " chanptr:%p\n",
+			    tmpvpcidev->queueinfo.chan);
+		tmpvpcidev = tmpvpcidev->next;
+	}
+	read_unlock_irqrestore(&VpcidevListLock, flags);
+
+	length +=
+	    sprintf(vbuf + length, "\nModule build: Date:%s Time:%s\n", __DATE__,
+		    __TIME__);
+
+	length += sprintf(vbuf + length, "\n");
+	if (copy_to_user(buf, vbuf, length)) {
+		kfree(vbuf);
+		return -EFAULT;
+	}
+
+	kfree(vbuf);
+	*offset += length;
+	return length;
+}
+
+static ssize_t virt_proc_write(struct file *file, const char __user *buffer,
+			       size_t count, loff_t *ppos)
+{
+	char buf[count];
+	int type, i, action = 0xffff;
+	unsigned int busno, deviceno;
+	void *chanptr;
+	struct add_vbus_guestpart busaddparams;
+	struct add_virt_guestpart addparams;
+	struct del_vbus_guestpart busdelparams;
+	struct del_virt_guestpart delparams;
+	GUID dummyGuid = GUID0;
+#ifdef STORAGE_CHANNEL
+	U64 storagechannel;
+#endif
+
+#define PRINT_USAGE_RETURN {\
+	LOGERR("usage: 0-0-<chanptr>					==> delete vhba\n"); \
+	LOGERR("usage: 0-1-<chanptr>-<busNo>-<deviceNo>	==> add vhba\n"); \
+	LOGERR("usage: 0-f-<busNo>						==> delete all vhbas\n"); \
+	LOGERR("\n"); \
+	LOGERR("usage: 1-0-<chanptr>					==> delete vnic\n"); \
+	LOGERR("usage: 1-1-<chanptr>-<busNo>-<deviceNo>	==> add vnic\n"); \
+	LOGERR("usage: 1-f-<busNo>						==> delete all vnics\n"); \
+	LOGERR("\n"); \
+	LOGERR("usage: 6-0-<busNo>						==> delete vbus\n"); \
+	LOGERR("usage: 6-1-<busNo>						==> add vbus\n"); \
+	LOGERR("usage: 6-f								==> delete all vbuses\n"); \
+	LOGERR("usage: 98-<busNo>-<deviceNo>			==> INJECT Client delete vnic\n"); \
+	LOGERR("usage: 99-<chanptr>-<busNo>-<deviceNo>	==> INJECT Client add vnic\n"); \
+	return -EINVAL; \
+}
+
+	if (copy_from_user(buf, buffer, count)) {
+		LOGERR("copy_from_user failed.\n");
+		return -EFAULT;
+	}
+
+	i = sscanf(buf, "%x-%x", &type, &action);
+	if (i < 2)
+		PRINT_USAGE_RETURN;
+
+	if (type == 0x98) {
+		/* client inject delete vnic */
+		i = sscanf(buf, "%x-%d-%d", &type, &busno, &deviceno);
+		if (i != 3)
+			PRINT_USAGE_RETURN;
+		uislib_client_inject_del_vnic(busno, deviceno);
+		return count;	/* success */
+	} else if (type == 0x99) {
+		/* client inject add vnic */
+		i = sscanf(buf, "%x-%p-%d-%d", &type, &chanptr, &busno,
+			   &deviceno);
+		if (i != 4)
+			PRINT_USAGE_RETURN;
+		if (!uislib_client_inject_add_vnic(busno, deviceno,
+						   __pa(chanptr),
+						   MIN_IO_CHANNEL_SIZE,
+						   1, /* test msg */
+						   dummyGuid, /* inst guid */
+						   NULL)) { /*interrupt info */
+			LOGERR("FAILED to inject add vnic\n");
+			return -EFAULT;
+		}
+		return count;	/* success */
+	}
+
+	if ((type != VIRTHBA_TYPE) && (type != VIRTNIC_TYPE)
+	    && (type != VIRTBUS_TYPE))
+		PRINT_USAGE_RETURN;
+
+	if (type == VIRTBUS_TYPE) {
+		i = sscanf(buf, "%x-%x-%d", &type, &action, &busno);
+		switch (action) {
+		case 0:
+			/* delete vbus */
+			if (i != 3)
+				break;
+			busdelparams.busNo = busno;
+			if (delete_vbus(&busdelparams))
+				return count;	/* success */
+			return -EFAULT;
+
+		case 1:
+			/* add vbus */
+			if (i != 3)
+				break;
+			busaddparams.chanptr = NULL;	/* NOT YET USED */
+			busaddparams.busNo = busno;
+			if (add_vbus(&busaddparams))
+				return count;	/* success */
+			return -EFAULT;
+
+		case 0xf:
+			/* delete all vbuses and all vhbas/vnics on the buses */
+			if (i != 2)
+				break;
+			delete_all();
+			return count;	/* success */
+		default:
+			break;
+		}
+		PRINT_USAGE_RETURN;
+	}
+
+	/* if (type == VIRTNIC_TYPE) or         if (type == VIRTHBA_TYPE) */
+	switch (action) {
+	case 0:
+		/* delete vhba/vnic */
+		i = sscanf(buf, "%x-%x-%p", &type, &action, &chanptr);
+		if (i != 3)
+			break;
+		delparams.chanptr = chanptr;
+		if (type == VIRTHBA_TYPE) {
+			if (delete_vhba(&delparams))
+				return count;	/* success */
+		} else {
+			if (delete_vnic(&delparams))
+				return count;	/* success */
+		}
+		return -EFAULT;
+
+	case 1:
+		/* add vhba/vnic */
+		i = sscanf(buf, "%x-%x-%p-%d-%d", &type, &action, &chanptr,
+			   &busno, &deviceno);
+		if (i != 5)
+			break;
+		addparams.chanptr = chanptr;
+		addparams.busNo = busno;
+		addparams.deviceNo = deviceno;
+		if (type == VIRTHBA_TYPE) {
+			if (add_vhba(&addparams))
+				return count;	/* success */
+		} else {
+			if (add_vnic(&addparams))
+				return count;	/* success */
+		}
+		return -EFAULT;
+
+#ifdef STORAGE_CHANNEL
+	case 2:
+		/* add vhba */
+		i = sscanf(buf, "%x-%x-%d-%d", &type, &action, &busno,
+			   &deviceno);
+		if (i != 4)
+			break;
+		storagechannel = uislib_storage_channel(0);	/* Get my storage channel */
+		/* ioremap_cache it now */
+		addparams.chanptr =
+		    (void *) ioremap_cache(storagechannel, IO_CHANNEL_SIZE);
+		if (addparams.chanptr == NULL) {
+			LOGERR("Failure to get remap storage channel.\n");
+			return -EFAULT;
+		}
+		addparams.busNo = busno;
+		addparams.deviceNo = deviceno;
+		if (type == VIRTHBA_TYPE) {
+			if (add_vhba(&addparams))
+				return count;	/* success */
+		}
+		return -EFAULT;
+#endif
+	case 0xf:
+		/* delete all vhbas/vnics */
+		i = sscanf(buf, "%x-%x-%d", &type, &action, &busno);
+		if (i != 3)
+			break;
+		busdelparams.busNo = busno;
+		delete_all_virt(type, &busdelparams);
+		return count;	/* success */
+	default:
+		break;
+	}
+	PRINT_USAGE_RETURN;
+}
+
+/*****************************************************/
+/* Module Init & Exit functions                      */
+/*****************************************************/
+
+static int __init virtpci_mod_init(void)
+{
+	int ret;
+
+
+	LOGINF("Module build: Date:%s Time:%s...\n", __DATE__, __TIME__);
+
+	POSTCODE_LINUX_2(VPCI_CREATE_ENTRY_PC, POSTCODE_SEVERITY_INFO);
+
+	ret = bus_register(&virtpci_bus_type);
+	/* creates /sys/bus/uisvirtpci which contains devices &
+	 * drivers directory
+	 */
+	if (ret) {
+		LOGERR("bus_register ****FAILED:%d\n", ret);
+		POSTCODE_LINUX_3(VPCI_CREATE_FAILURE_PC, ret,
+				 POSTCODE_SEVERITY_ERR);
+		return ret;
+	}
+	DBGINF("bus_register successful\n");
+	BusDeviceInfo_Init(&Bus_DriverInfo,
+			   "clientbus", "virtpci",
+			   VERSION, NULL, __DATE__, __TIME__);
+
+	/* create a root bus used to parent all the virtpci buses. */
+	ret = device_register(&virtpci_rootbus_device);
+	if (ret) {
+		LOGERR("device_register FAILED:%d\n", ret);
+		bus_unregister(&virtpci_bus_type);
+		POSTCODE_LINUX_3(VPCI_CREATE_FAILURE_PC, ret,
+				 POSTCODE_SEVERITY_ERR);
+		return ret;
+	}
+	DBGINF("device_register successful ret:%x\n", ret);
+
+	if (!uisctrl_register_req_handler(2, (void *) &virtpci_ctrlchan_func,
+					  &Chipset_DriverInfo)) {
+		LOGERR("uisctrl_register_req_handler ****FAILED.\n");
+		POSTCODE_LINUX_2(VPCI_CREATE_FAILURE_PC, POSTCODE_SEVERITY_ERR);
+		device_unregister(&virtpci_rootbus_device);
+		bus_unregister(&virtpci_bus_type);
+		return -1;
+	}
+
+	LOGINF("successfully registered virtpci_ctrlchan_func (0x%p) as callback.\n",
+	     (void *) &virtpci_ctrlchan_func);
+	/* create the proc directories */
+	virtpci_proc_dir = proc_mkdir(DIR_PROC_ENTRY, NULL);
+	virt_proc_entry = proc_create(VIRT_PROC_ENTRY_FN, 0, virtpci_proc_dir,
+				      &proc_virt_fops);
+	info_proc_entry = proc_create(INFO_PROC_ENTRY_FN, 0, virtpci_proc_dir,
+				      &proc_info_fops);
+	LOGINF("Leaving\n");
+	POSTCODE_LINUX_2(VPCI_CREATE_EXIT_PC, POSTCODE_SEVERITY_INFO);
+	return 0;
+}
+
+static void __exit virtpci_mod_exit(void)
+{
+	LOGINF("virtpci_mod_exit...\n");
+
+	/* unregister the callback function */
+	if (!uisctrl_register_req_handler(2, NULL, NULL))
+		LOGERR("uisctrl_register_req_handler ****FAILED.\n");
+
+	device_unregister(&virtpci_rootbus_device);
+	bus_unregister(&virtpci_bus_type);
+
+	if (virt_proc_entry)
+		remove_proc_entry(VIRT_PROC_ENTRY_FN, virtpci_proc_dir);
+
+	if (info_proc_entry)
+		remove_proc_entry(INFO_PROC_ENTRY_FN, virtpci_proc_dir);
+
+	if (virtpci_proc_dir)
+		remove_proc_entry(DIR_PROC_ENTRY, NULL);
+
+	LOGINF("Leaving\n");
+
+}
+
+module_init(virtpci_mod_init);
+module_exit(virtpci_mod_exit);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Usha Srinivasan");
+MODULE_ALIAS("uisvirtpci");
+
diff --git a/drivers/staging/unisys/virtpci/virtpci.h b/drivers/staging/unisys/virtpci/virtpci.h
new file mode 100644
index 0000000..b8fd07b
--- /dev/null
+++ b/drivers/staging/unisys/virtpci/virtpci.h
@@ -0,0 +1,104 @@
+/* virtpci.h
+ *
+ * Copyright © 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+/*
+ * Unisys Virtual PCI driver header
+ */
+
+#ifndef __VIRTPCI_H__
+#define __VIRTPCI_H__
+
+#include "uisqueue.h"
+#include <linux/version.h>
+
+#define PCI_DEVICE_ID_VIRTHBA 0xAA00
+#define PCI_DEVICE_ID_VIRTNIC 0xAB00
+
+struct scsi_adap_info {
+	void *scsihost;		/* scsi host if this device is a scsi hba */
+	struct vhba_wwnn wwnn;	/* the world wide node name of vhba */
+	struct vhba_config_max max;	/* various max specifications used
+					 * to config vhba */
+};
+
+struct net_adap_info {
+	struct net_device *netdev;	/* network device if this
+					 * device is a NIC */
+	u8 mac_addr[MAX_MACADDR_LEN];
+	int num_rcv_bufs;
+	unsigned mtu;
+	GUID zoneGuid;
+};
+
+typedef enum {
+	VIRTHBA_TYPE = 0,
+	VIRTNIC_TYPE = 1,
+	VIRTBUS_TYPE = 6,
+} VIRTPCI_DEV_TYPE;
+
+struct virtpci_dev {
+	VIRTPCI_DEV_TYPE devtype;	/* indicates type of the
+					 * virtual pci device */
+	struct virtpci_driver *mydriver;	/* which driver has allocated
+						 * this device */
+	unsigned short vendor;	/* vendor id for device */
+	unsigned short device;	/* device id for device */
+	U32 busNo;		/* number of bus on which device exists */
+	U32 deviceNo;		/* device's number on the bus */
+	struct InterruptInfo intr;	/* interrupt info */
+	struct device generic_dev;	/* generic device */
+	union {
+		struct scsi_adap_info scsi;
+		struct net_adap_info net;
+	};
+
+	struct uisqueue_info queueinfo;	/* holds ptr to channel where cmds &
+					 * rsps are queued & retrieved */
+	struct virtpci_dev *next;	/* points to next virtpci device */
+};
+
+struct virtpci_driver {
+	struct list_head node;
+	const char *name;	/* the name of the driver in sysfs */
+	const char *version;
+	const char *vertag;
+	const char *build_date;
+	const char *build_time;
+	const struct pci_device_id *id_table;	/* must be non-NULL for probe
+						 * to be called */
+	int (*probe)(struct virtpci_dev *dev,
+		      const struct pci_device_id *id); /* device inserted */
+	void (*remove)(struct virtpci_dev *dev); /* Device removed (NULL if
+						    * not a hot-plug capable
+						    * driver) */
+	int (*suspend)(struct virtpci_dev *dev,
+			u32 state);		   /* Device suspended */
+	int (*resume)(struct virtpci_dev *dev);	/* Device woken up */
+	int (*enable_wake)(struct virtpci_dev *dev,
+			    u32 state, int enable);	/* Enable wake event */
+	struct device_driver core_driver;	/* VIRTPCI core fills this in */
+};
+
+#define	driver_to_virtpci_driver(in_drv) \
+	container_of(in_drv, struct virtpci_driver, core_driver)
+#define device_to_virtpci_dev(in_dev) \
+	container_of(in_dev, struct virtpci_dev, generic_dev)
+
+int virtpci_register_driver(struct virtpci_driver *);
+void virtpci_unregister_driver(struct virtpci_driver *);
+
+#endif /* __VIRTPCI_H__ */
diff --git a/drivers/staging/unisys/visorchannel/Kconfig b/drivers/staging/unisys/visorchannel/Kconfig
new file mode 100644
index 0000000..41c3b4b
--- /dev/null
+++ b/drivers/staging/unisys/visorchannel/Kconfig
@@ -0,0 +1,10 @@
+#
+# Unisys visorchannel configuration
+#
+
+config UNISYS_VISORCHANNEL
+	tristate "Unisys visorchannel driver"
+	depends on UNISYSSPAR && UNISYS_VISORUTIL
+	---help---
+	If you say Y here, you will enable the Unisys visorchannel driver.
+
diff --git a/drivers/staging/unisys/visorchannel/Makefile b/drivers/staging/unisys/visorchannel/Makefile
new file mode 100644
index 0000000..f0060be
--- /dev/null
+++ b/drivers/staging/unisys/visorchannel/Makefile
@@ -0,0 +1,14 @@
+#
+# Makefile for Unisys visorchannel
+#
+
+obj-$(CONFIG_UNISYS_VISORCHANNEL)	+= visorchannel.o
+
+visorchannel-y := visorchannel_main.o visorchannel_funcs.o
+
+ccflags-y += -Idrivers/staging/unisys/include
+ccflags-y += -Idrivers/staging/unisys/common-spar/include
+ccflags-y += -Idrivers/staging/unisys/common-spar/include/channels
+ccflags-y += -Idrivers/staging/unisys/visorutil
+ccflags-y += -DCONFIG_SPAR_GUEST -DGUESTDRIVERBUILD -DNOAUTOVERSION
+
diff --git a/drivers/staging/unisys/visorchannel/globals.h b/drivers/staging/unisys/visorchannel/globals.h
new file mode 100644
index 0000000..668f832
--- /dev/null
+++ b/drivers/staging/unisys/visorchannel/globals.h
@@ -0,0 +1,29 @@
+/* globals.h
+ *
+ * Copyright © 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+#ifndef __VISORCHANNEL_GLOBALS_H__
+#define __VISORCHANNEL_GLOBALS_H__
+
+#include "uniklog.h"
+#include "timskmod.h"
+#include "memregion.h"
+#include "version.h"
+
+#define MYDRVNAME "visorchannel"
+
+
+#endif
diff --git a/drivers/staging/unisys/visorchannel/visorchannel.h b/drivers/staging/unisys/visorchannel/visorchannel.h
new file mode 100644
index 0000000..4546686
--- /dev/null
+++ b/drivers/staging/unisys/visorchannel/visorchannel.h
@@ -0,0 +1,106 @@
+/* visorchannel.h
+ *
+ * Copyright © 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+#ifndef __VISORCHANNEL_H__
+#define __VISORCHANNEL_H__
+
+#include "commontypes.h"
+#include "memregion.h"
+#include "channel.h"
+#ifndef HOSTADDRESS
+#define HOSTADDRESS U64
+#endif
+#ifndef BOOL
+#define BOOL int
+#endif
+
+/* VISORCHANNEL is an opaque structure to users.
+ * Fields are declared only in the implementation .c files.
+ */
+typedef struct VISORCHANNEL_Tag VISORCHANNEL;
+
+/* Note that for visorchannel_create() and visorchannel_create_overlapped(),
+ * <channelBytes> and <guid> arguments may be 0 if we are a channel CLIENT.
+ * In this case, the values can simply be read from the channel header.
+ */
+VISORCHANNEL *visorchannel_create(HOSTADDRESS physaddr,
+				  ulong channelBytes, GUID guid);
+VISORCHANNEL *visorchannel_create_overlapped(ulong channelBytes,
+					     VISORCHANNEL *parent, ulong off,
+					     GUID guid);
+VISORCHANNEL *visorchannel_create_with_lock(HOSTADDRESS physaddr,
+					    ulong channelBytes, GUID guid);
+VISORCHANNEL *visorchannel_create_overlapped_with_lock(ulong channelBytes,
+						       VISORCHANNEL *parent,
+						       ulong off, GUID guid);
+void visorchannel_destroy(VISORCHANNEL *channel);
+int visorchannel_read(VISORCHANNEL *channel, ulong offset,
+		      void *local, ulong nbytes);
+int visorchannel_write(VISORCHANNEL *channel, ulong offset,
+		       void *local, ulong nbytes);
+int visorchannel_clear(VISORCHANNEL *channel, ulong offset,
+		       U8 ch, ulong nbytes);
+BOOL visorchannel_signalremove(VISORCHANNEL *channel, U32 queue, void *msg);
+BOOL visorchannel_signalinsert(VISORCHANNEL *channel, U32 queue, void *msg);
+int visorchannel_signalqueue_slots_avail(VISORCHANNEL *channel, U32 queue);
+int visorchannel_signalqueue_max_slots(VISORCHANNEL *channel, U32 queue);
+
+HOSTADDRESS visorchannel_get_physaddr(VISORCHANNEL *channel);
+ulong visorchannel_get_nbytes(VISORCHANNEL *channel);
+char *visorchannel_id(VISORCHANNEL *channel, char *s);
+char *visorchannel_zoneid(VISORCHANNEL *channel, char *s);
+U64 visorchannel_get_clientpartition(VISORCHANNEL *channel);
+GUID visorchannel_get_GUID(VISORCHANNEL *channel);
+MEMREGION *visorchannel_get_memregion(VISORCHANNEL *channel);
+char *visorchannel_GUID_id(GUID *guid, char *s);
+void visorchannel_debug(VISORCHANNEL *channel, int nQueues,
+			struct seq_file *seq, U32 off);
+void visorchannel_dump_section(VISORCHANNEL *chan, char *s,
+			       int off, int len, struct seq_file *seq);
+void *visorchannel_get_header(VISORCHANNEL *channel);
+
+#define	VISORCHANNEL_CHANGE_SERVER_STATE(chan, chanId, newstate)	\
+	do {								\
+		U8 *p = (U8 *)visorchannel_get_header(chan);		\
+		if (p) {						\
+			ULTRA_CHANNEL_SERVER_TRANSITION(p, chanId, SrvState, \
+							newstate, logCtx); \
+			visorchannel_write				\
+				(chan,					\
+				 offsetof(ULTRA_CHANNEL_PROTOCOL, SrvState), \
+				 p +					\
+				 offsetof(ULTRA_CHANNEL_PROTOCOL, SrvState), \
+				 sizeof(U32));				\
+		}							\
+	} while (0)
+
+#define	VISORCHANNEL_CHANGE_CLIENT_STATE(chan, chanId, newstate)	\
+	do {								\
+		U8 *p = (U8 *)visorchannel_get_header(chan);		\
+		if (p) {						\
+			ULTRA_CHANNEL_CLIENT_TRANSITION(p, chanId, CliStateOS, \
+							newstate, logCtx); \
+			visorchannel_write				\
+				(chan,					\
+				 offsetof(ULTRA_CHANNEL_PROTOCOL, CliStateOS), \
+				 p +					\
+				 offsetof(ULTRA_CHANNEL_PROTOCOL, CliStateOS), \
+				 sizeof(U32));				\
+		}							\
+	} while (0)
+
+#endif
diff --git a/drivers/staging/unisys/visorchannel/visorchannel_funcs.c b/drivers/staging/unisys/visorchannel/visorchannel_funcs.c
new file mode 100644
index 0000000..509c77b
--- /dev/null
+++ b/drivers/staging/unisys/visorchannel/visorchannel_funcs.c
@@ -0,0 +1,765 @@
+/* visorchannel_funcs.c
+ *
+ * Copyright © 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+/*
+ *  This provides Supervisor channel communication primitives, which are
+ *  independent of the mechanism used to access the channel data.  All channel
+ *  data is accessed using the memregion abstraction.  (memregion has both
+ *  a CM2 implementation and a direct memory implementation.)
+ */
+
+#include "globals.h"
+#include "visorchannel.h"
+#include "guidutils.h"
+
+#define MYDRVNAME "visorchannel"
+
+struct VISORCHANNEL_Tag {
+	MEMREGION *memregion;	/* from memregion_create() */
+	CHANNEL_HEADER chan_hdr;
+	GUID guid;
+	ulong size;
+	BOOL needs_lock;
+	spinlock_t insert_lock;
+	spinlock_t remove_lock;
+
+	struct {
+		SIGNAL_QUEUE_HEADER req_queue;
+		SIGNAL_QUEUE_HEADER rsp_queue;
+		SIGNAL_QUEUE_HEADER event_queue;
+		SIGNAL_QUEUE_HEADER ack_queue;
+	} safe_uis_queue;
+};
+
+/* Creates the VISORCHANNEL abstraction for a data area in memory, but does
+ * NOT modify this data area.
+ */
+static VISORCHANNEL *
+visorchannel_create_guts(HOSTADDRESS physaddr, ulong channelBytes,
+			 VISORCHANNEL *parent, ulong off, GUID guid,
+			 BOOL needs_lock)
+{
+	VISORCHANNEL *p = NULL;
+	void *rc = NULL;
+
+	p = kmalloc(sizeof(VISORCHANNEL), GFP_KERNEL|__GFP_NORETRY);
+	if (p == NULL)
+		FAIL("allocation failed", 0);
+	p->memregion = NULL;
+	p->needs_lock = needs_lock;
+	spin_lock_init(&p->insert_lock);
+	spin_lock_init(&p->remove_lock);
+
+	/* prepare chan_hdr (abstraction to read/write channel memory) */
+	if (parent == NULL)
+		p->memregion =
+		    memregion_create(physaddr, sizeof(CHANNEL_HEADER));
+	else
+		p->memregion =
+		    memregion_create_overlapped
+		    (parent->memregion, off, sizeof(CHANNEL_HEADER));
+	if (p->memregion == NULL)
+		FAIL("memregion_create failed", 0);
+	if (memregion_read(p->memregion, 0, &p->chan_hdr,
+			   sizeof(CHANNEL_HEADER)) < 0)
+		FAIL("memregion_read failed", 0);
+	if (channelBytes == 0)
+		/* we had better be a CLIENT of this channel */
+		channelBytes = (ulong) p->chan_hdr.Size;
+	if (STRUCTSEQUAL(guid, Guid0))
+		/* we had better be a CLIENT of this channel */
+		guid = p->chan_hdr.Type;
+	if (memregion_resize(p->memregion, channelBytes) < 0)
+		FAIL("memregion_resize failed", 0);
+	p->size = channelBytes;
+	p->guid = guid;
+
+	RETPTR(p);
+
+Away:
+
+	if (rc == NULL) {
+		if (p != NULL) {
+			visorchannel_destroy(p);
+			p = NULL;
+		}
+	}
+	return rc;
+}
+
+VISORCHANNEL *
+visorchannel_create(HOSTADDRESS physaddr, ulong channelBytes, GUID guid)
+{
+	return visorchannel_create_guts(physaddr, channelBytes, NULL, 0, guid,
+					FALSE);
+}
+EXPORT_SYMBOL_GPL(visorchannel_create);
+
+VISORCHANNEL *
+visorchannel_create_with_lock(HOSTADDRESS physaddr, ulong channelBytes,
+			      GUID guid)
+{
+	return visorchannel_create_guts(physaddr, channelBytes, NULL, 0, guid,
+					TRUE);
+}
+EXPORT_SYMBOL_GPL(visorchannel_create_with_lock);
+
+VISORCHANNEL *
+visorchannel_create_overlapped(ulong channelBytes,
+			       VISORCHANNEL *parent, ulong off, GUID guid)
+{
+	return visorchannel_create_guts(0, channelBytes, parent, off, guid,
+					FALSE);
+}
+EXPORT_SYMBOL_GPL(visorchannel_create_overlapped);
+
+VISORCHANNEL *
+visorchannel_create_overlapped_with_lock(ulong channelBytes,
+					 VISORCHANNEL *parent, ulong off,
+					 GUID guid)
+{
+	return visorchannel_create_guts(0, channelBytes, parent, off, guid,
+					TRUE);
+}
+EXPORT_SYMBOL_GPL(visorchannel_create_overlapped_with_lock);
+
+void
+visorchannel_destroy(VISORCHANNEL *channel)
+{
+	if (channel == NULL)
+		return;
+	if (channel->memregion != NULL) {
+		memregion_destroy(channel->memregion);
+		channel->memregion = NULL;
+	}
+	kfree(channel);
+}
+EXPORT_SYMBOL_GPL(visorchannel_destroy);
+
+HOSTADDRESS
+visorchannel_get_physaddr(VISORCHANNEL *channel)
+{
+	return memregion_get_physaddr(channel->memregion);
+}
+EXPORT_SYMBOL_GPL(visorchannel_get_physaddr);
+
+ulong
+visorchannel_get_nbytes(VISORCHANNEL *channel)
+{
+	return channel->size;
+}
+EXPORT_SYMBOL_GPL(visorchannel_get_nbytes);
+
+char *
+visorchannel_GUID_id(GUID *guid, char *s)
+{
+	return GUID_format1(guid, s);
+}
+EXPORT_SYMBOL_GPL(visorchannel_GUID_id);
+
+char *
+visorchannel_id(VISORCHANNEL *channel, char *s)
+{
+	return visorchannel_GUID_id(&channel->guid, s);
+}
+EXPORT_SYMBOL_GPL(visorchannel_id);
+
+char *
+visorchannel_zoneid(VISORCHANNEL *channel, char *s)
+{
+	return visorchannel_GUID_id(&channel->chan_hdr.ZoneGuid, s);
+}
+EXPORT_SYMBOL_GPL(visorchannel_zoneid);
+
+HOSTADDRESS
+visorchannel_get_clientpartition(VISORCHANNEL *channel)
+{
+	return channel->chan_hdr.PartitionHandle;
+}
+EXPORT_SYMBOL_GPL(visorchannel_get_clientpartition);
+
+GUID
+visorchannel_get_GUID(VISORCHANNEL *channel)
+{
+	return channel->guid;
+}
+EXPORT_SYMBOL_GPL(visorchannel_get_GUID);
+
+MEMREGION *
+visorchannel_get_memregion(VISORCHANNEL *channel)
+{
+	return channel->memregion;
+}
+EXPORT_SYMBOL_GPL(visorchannel_get_memregion);
+
+pSIGNAL_QUEUE_HEADER
+visorchannel_get_safe_queue(VISORCHANNEL *pchannel, U32 queue)
+{
+	switch (queue) {
+	case 0:
+		return &pchannel->safe_uis_queue.req_queue;
+	case 1:
+		return &pchannel->safe_uis_queue.rsp_queue;
+	case 2:
+		return &pchannel->safe_uis_queue.event_queue;
+	case 3:
+		return &pchannel->safe_uis_queue.ack_queue;
+	default:
+		ERRDRV("Invalid queue value %d\n", queue);
+		return NULL;
+	}
+}				/* end visorchannel_get_safe_queue */
+
+int
+visorchannel_read(VISORCHANNEL *channel, ulong offset,
+		  void *local, ulong nbytes)
+{
+	int rc = memregion_read(channel->memregion, offset, local, nbytes);
+	if ((rc >= 0) && (offset == 0) && (nbytes >= sizeof(CHANNEL_HEADER)))
+		memcpy(&channel->chan_hdr, local, sizeof(CHANNEL_HEADER));
+	return rc;
+}
+EXPORT_SYMBOL_GPL(visorchannel_read);
+
+int
+visorchannel_write(VISORCHANNEL *channel, ulong offset,
+		   void *local, ulong nbytes)
+{
+	if (offset == 0 && nbytes >= sizeof(CHANNEL_HEADER))
+		memcpy(&channel->chan_hdr, local, sizeof(CHANNEL_HEADER));
+	return memregion_write(channel->memregion, offset, local, nbytes);
+}
+EXPORT_SYMBOL_GPL(visorchannel_write);
+
+int
+visorchannel_clear(VISORCHANNEL *channel, ulong offset, U8 ch, ulong nbytes)
+{
+	int rc = -1;
+	int bufsize = 65536;
+	int written = 0;
+	U8 *buf = vmalloc(bufsize);
+
+	if (buf == NULL) {
+		ERRDRV("%s failed memory allocation", __func__);
+		RETINT(-1);
+	}
+	memset(buf, ch, bufsize);
+	while (nbytes > 0) {
+		ulong thisbytes = bufsize;
+		int x = -1;
+		if (nbytes < thisbytes)
+			thisbytes = nbytes;
+		x = memregion_write(channel->memregion, offset + written,
+				    buf, thisbytes);
+		if (x < 0)
+			RETINT(x);
+		written += thisbytes;
+		nbytes -= thisbytes;
+	}
+	RETINT(0);
+
+Away:
+	if (buf != NULL) {
+		vfree(buf);
+		buf = NULL;
+	}
+	return rc;
+}
+EXPORT_SYMBOL_GPL(visorchannel_clear);
+
+void *
+visorchannel_get_header(VISORCHANNEL *channel)
+{
+	return (void *) &(channel->chan_hdr);
+}
+EXPORT_SYMBOL_GPL(visorchannel_get_header);
+
+/** Return offset of a specific SIGNAL_QUEUE_HEADER from the beginning of a
+ *  channel header
+ */
+#define SIG_QUEUE_OFFSET(chan_hdr, q) \
+	((chan_hdr)->oChannelSpace + ((q) * sizeof(SIGNAL_QUEUE_HEADER)))
+
+/** Return offset of a specific queue entry (data) from the beginning of a
+ *  channel header
+ */
+#define SIG_DATA_OFFSET(chan_hdr, q, sig_hdr, slot) \
+	(SIG_QUEUE_OFFSET(chan_hdr, q) + (sig_hdr)->oSignalBase + \
+	    ((slot) * (sig_hdr)->SignalSize))
+
+/** Write the contents of a specific field within a SIGNAL_QUEUE_HEADER back
+ *  into host memory
+ */
+#define SIG_WRITE_FIELD(channel, queue, sig_hdr, FIELD)                \
+	(memregion_write(channel->memregion,                        \
+			 SIG_QUEUE_OFFSET(&channel->chan_hdr, queue)+\
+			   offsetof(SIGNAL_QUEUE_HEADER, FIELD),     \
+			 &((sig_hdr)->FIELD),                       \
+			 sizeof((sig_hdr)->FIELD)) >= 0)
+
+static BOOL
+sig_read_header(VISORCHANNEL *channel, U32 queue,
+		SIGNAL_QUEUE_HEADER *sig_hdr)
+{
+	BOOL rc = FALSE;
+
+	if (channel->chan_hdr.oChannelSpace < sizeof(CHANNEL_HEADER))
+		FAIL("oChannelSpace too small", FALSE);
+
+	/* Read the appropriate SIGNAL_QUEUE_HEADER into local memory. */
+
+	if (memregion_read(channel->memregion,
+			   SIG_QUEUE_OFFSET(&channel->chan_hdr, queue),
+			   sig_hdr, sizeof(SIGNAL_QUEUE_HEADER)) < 0) {
+		ERRDRV("queue=%d SIG_QUEUE_OFFSET=%d",
+		       queue, (int)SIG_QUEUE_OFFSET(&channel->chan_hdr, queue));
+		FAIL("memregion_read of signal queue failed", FALSE);
+	}
+	RETBOOL(TRUE);
+Away:
+	return rc;
+}
+
+static BOOL
+sig_do_data(VISORCHANNEL *channel, U32 queue,
+	    SIGNAL_QUEUE_HEADER *sig_hdr, U32 slot, void *data, BOOL is_write)
+{
+	BOOL rc = FALSE;
+	int signal_data_offset = SIG_DATA_OFFSET(&channel->chan_hdr, queue,
+						 sig_hdr, slot);
+	if (is_write) {
+		if (memregion_write(channel->memregion, signal_data_offset,
+				    data, sig_hdr->SignalSize) < 0)
+			FAIL("memregion_write of signal data failed", FALSE);
+	} else {
+		if (memregion_read(channel->memregion, signal_data_offset,
+				   data, sig_hdr->SignalSize) < 0)
+			FAIL("memregion_read of signal data failed", FALSE);
+	}
+	RETBOOL(TRUE);
+Away:
+	return rc;
+}
+
+static inline BOOL
+sig_read_data(VISORCHANNEL *channel, U32 queue,
+	      SIGNAL_QUEUE_HEADER *sig_hdr, U32 slot, void *data)
+{
+	return sig_do_data(channel, queue, sig_hdr, slot, data, FALSE);
+}
+
+static inline BOOL
+sig_write_data(VISORCHANNEL *channel, U32 queue,
+	       SIGNAL_QUEUE_HEADER *sig_hdr, U32 slot, void *data)
+{
+	return sig_do_data(channel, queue, sig_hdr, slot, data, TRUE);
+}
+
+static inline unsigned char
+safe_sig_queue_validate(pSIGNAL_QUEUE_HEADER psafe_sqh,
+			pSIGNAL_QUEUE_HEADER punsafe_sqh,
+			U32 *phead, U32 *ptail)
+{
+	if ((*phead >= psafe_sqh->MaxSignalSlots)
+	    || (*ptail >= psafe_sqh->MaxSignalSlots)) {
+		/* Choose 0 or max, maybe based on current tail value */
+		*phead = 0;
+		*ptail = 0;
+
+		/* Sync with client as necessary */
+		punsafe_sqh->Head = *phead;
+		punsafe_sqh->Tail = *ptail;
+
+		ERRDRV("safe_sig_queue_validate: head = 0x%x, tail = 0x%x, MaxSlots = 0x%x",
+		     *phead, *ptail, psafe_sqh->MaxSignalSlots);
+		return 0;
+	}
+	return 1;
+}				/* end safe_sig_queue_validate */
+
+BOOL
+visorchannel_signalremove(VISORCHANNEL *channel, U32 queue, void *msg)
+{
+	BOOL rc = FALSE;
+	SIGNAL_QUEUE_HEADER sig_hdr;
+
+	if (channel->needs_lock)
+		spin_lock(&channel->remove_lock);
+
+	if (!sig_read_header(channel, queue, &sig_hdr))
+		RETBOOL(FALSE);
+	if (sig_hdr.Head == sig_hdr.Tail)
+		RETBOOL(FALSE);	/* no signals to remove */
+	sig_hdr.Tail = (sig_hdr.Tail + 1) % sig_hdr.MaxSignalSlots;
+	if (!sig_read_data(channel, queue, &sig_hdr, sig_hdr.Tail, msg))
+		FAIL("sig_read_data failed", FALSE);
+	sig_hdr.NumSignalsReceived++;
+
+	/* For each data field in SIGNAL_QUEUE_HEADER that was modified,
+	 * update host memory.
+	 */
+	MEMORYBARRIER;
+	if (!SIG_WRITE_FIELD(channel, queue, &sig_hdr, Tail))
+		FAIL("memregion_write of Tail failed", FALSE);
+	if (!SIG_WRITE_FIELD(channel, queue, &sig_hdr, NumSignalsReceived))
+		FAIL("memregion_write of NumSignalsReceived failed", FALSE);
+
+	RETBOOL(TRUE);
+
+Away:
+	if (channel->needs_lock)
+		spin_unlock(&channel->remove_lock);
+
+	return rc;
+}
+EXPORT_SYMBOL_GPL(visorchannel_signalremove);
+
+BOOL
+visorchannel_safesignalremove(VISORCHANNEL *channel, U32 queue, void *msg)
+{
+	BOOL rc = FALSE;
+	SIGNAL_QUEUE_HEADER *psafe_sqh, unsafe_sqh;
+	int stat;
+
+	if (channel->needs_lock)
+		spin_lock(&channel->remove_lock);
+
+	if (!sig_read_header(channel, queue, &unsafe_sqh))
+		RETBOOL(FALSE);
+
+	psafe_sqh = visorchannel_get_safe_queue(channel, queue);
+	if (psafe_sqh == NULL) {
+		ERRDRV("safesignalremove: get_safe_queue failed\n");
+		RETBOOL(FALSE);
+	}
+
+	stat =
+	    safe_sig_queue_validate(psafe_sqh, &unsafe_sqh, &unsafe_sqh.Head,
+				    &unsafe_sqh.Tail);
+	if (stat == 0) {
+		ERRDRV("safe_signal_remove: safe_sig_queue_validate failed, queue = %d",
+		     queue);
+		RETBOOL(FALSE);
+	}
+
+	if (unsafe_sqh.Head == unsafe_sqh.Tail)
+		RETBOOL(FALSE);	/* no signals to remove */
+	unsafe_sqh.Tail = (unsafe_sqh.Tail + 1) % psafe_sqh->MaxSignalSlots;
+	if (!sig_read_data(channel, queue, psafe_sqh, unsafe_sqh.Tail, msg))
+		FAIL("sig_read_data failed", FALSE);
+	unsafe_sqh.NumSignalsReceived++;
+
+	/* For each data field in SIGNAL_QUEUE_HEADER that was modified,
+	 * update host memory.
+	 */
+	MEMORYBARRIER;
+	if (!SIG_WRITE_FIELD(channel, queue, &unsafe_sqh, Tail))
+		FAIL("memregion_write of Tail failed", FALSE);
+	if (!SIG_WRITE_FIELD(channel, queue, &unsafe_sqh, NumSignalsReceived))
+		FAIL("memregion_write of NumSignalsReceived failed", FALSE);
+
+	RETBOOL(TRUE);
+
+Away:
+	if (channel->needs_lock)
+		spin_unlock(&channel->remove_lock);
+
+	return rc;
+}				/* end visorchannel_safesignalremove */
+
+BOOL
+visorchannel_signalinsert(VISORCHANNEL *channel, U32 queue, void *msg)
+{
+	BOOL rc = FALSE;
+	SIGNAL_QUEUE_HEADER sig_hdr;
+
+	if (channel->needs_lock)
+		spin_lock(&channel->insert_lock);
+
+	if (!sig_read_header(channel, queue, &sig_hdr))
+		RETBOOL(FALSE);
+
+	sig_hdr.Head = ((sig_hdr.Head + 1) % sig_hdr.MaxSignalSlots);
+	if (sig_hdr.Head == sig_hdr.Tail) {
+#if 0
+		ERRDRV("visorchannel queue #%d overflow (max slots=%d)",
+		       queue, sig_hdr.MaxSignalSlots);
+#endif
+		sig_hdr.NumOverflows++;
+		if (!SIG_WRITE_FIELD(channel, queue, &sig_hdr, NumOverflows))
+			FAIL("memregion_write of NumOverflows failed", FALSE);
+		RETBOOL(FALSE);
+	}
+
+	if (!sig_write_data(channel, queue, &sig_hdr, sig_hdr.Head, msg))
+		FAIL("sig_write_data failed", FALSE);
+	sig_hdr.NumSignalsSent++;
+
+	/* For each data field in SIGNAL_QUEUE_HEADER that was modified,
+	 * update host memory.
+	 */
+	MEMORYBARRIER;
+	if (!SIG_WRITE_FIELD(channel, queue, &sig_hdr, Head))
+		FAIL("memregion_write of Head failed", FALSE);
+	if (!SIG_WRITE_FIELD(channel, queue, &sig_hdr, NumSignalsSent))
+		FAIL("memregion_write of NumSignalsSent failed", FALSE);
+
+	RETBOOL(TRUE);
+
+Away:
+	if (channel->needs_lock)
+		spin_unlock(&channel->insert_lock);
+
+	return rc;
+}
+EXPORT_SYMBOL_GPL(visorchannel_signalinsert);
+
+
+int
+visorchannel_signalqueue_slots_avail(VISORCHANNEL *channel, U32 queue)
+{
+	SIGNAL_QUEUE_HEADER sig_hdr;
+	U32 slots_avail, slots_used;
+	U32 head, tail;
+
+	if (!sig_read_header(channel, queue, &sig_hdr))
+		return 0;
+	head = sig_hdr.Head;
+	tail = sig_hdr.Tail;
+	if (head < tail)
+		head = head + sig_hdr.MaxSignalSlots;
+	slots_used = (head - tail);
+	slots_avail = sig_hdr.MaxSignals - slots_used;
+	return (int) slots_avail;
+}
+EXPORT_SYMBOL_GPL(visorchannel_signalqueue_slots_avail);
+
+int
+visorchannel_signalqueue_max_slots(VISORCHANNEL *channel, U32 queue)
+{
+	SIGNAL_QUEUE_HEADER sig_hdr;
+	if (!sig_read_header(channel, queue, &sig_hdr))
+		return 0;
+	return (int) sig_hdr.MaxSignals;
+}
+EXPORT_SYMBOL_GPL(visorchannel_signalqueue_max_slots);
+
+BOOL
+visorchannel_safesignalinsert(VISORCHANNEL *channel, U32 queue, void *msg)
+{
+	BOOL rc = FALSE;
+	SIGNAL_QUEUE_HEADER *psafe_sqh, unsafe_sqh;
+	int stat;
+
+	if (channel->needs_lock)
+		spin_lock(&channel->insert_lock);
+
+	if (!sig_read_header(channel, queue, &unsafe_sqh))
+		RETBOOL(FALSE);
+
+	psafe_sqh = visorchannel_get_safe_queue(channel, queue);
+	if (psafe_sqh == NULL) {
+		ERRDRV("safesignalinsert: get_safe_queue failed\n");
+		RETBOOL(FALSE);
+	}
+
+	unsafe_sqh.Head = ((unsafe_sqh.Head + 1) % psafe_sqh->MaxSignalSlots);
+
+	stat =
+	    safe_sig_queue_validate(psafe_sqh, &unsafe_sqh, &unsafe_sqh.Head,
+				    &unsafe_sqh.Tail);
+	if (stat == 0) {
+		ERRDRV("safe_signal_insert: safe_sig_queue_validate failed, queue = %d",
+		     queue);
+		RETBOOL(FALSE);
+	}
+
+	if (unsafe_sqh.Head == unsafe_sqh.Tail) {
+#if 0
+		ERRDRV("visorchannel queue #%d overflow (max slots=%d)",
+		       queue, psafe_sqh->MaxSignalSlots);
+#endif
+		unsafe_sqh.NumOverflows++;
+		if (!SIG_WRITE_FIELD(channel, queue, &unsafe_sqh, NumOverflows))
+			FAIL("memregion_write of NumOverflows failed", FALSE);
+		RETBOOL(FALSE);
+	}
+
+	if (!sig_write_data(channel, queue, psafe_sqh, unsafe_sqh.Head, msg))
+		FAIL("sig_write_data failed", FALSE);
+	unsafe_sqh.NumSignalsSent++;
+
+	/* For each data field in SIGNAL_QUEUE_HEADER that was modified,
+	 * update host memory.
+	 */
+	MEMORYBARRIER;
+	if (!SIG_WRITE_FIELD(channel, queue, &unsafe_sqh, Head))
+		FAIL("memregion_write of Head failed", FALSE);
+	if (!SIG_WRITE_FIELD(channel, queue, &unsafe_sqh, NumSignalsSent))
+		FAIL("memregion_write of NumSignalsSent failed", FALSE);
+
+	RETBOOL(TRUE);
+
+Away:
+	if (channel->needs_lock)
+		spin_unlock(&channel->insert_lock);
+
+	return rc;
+}				/* end visorchannel_safesignalinsert */
+
+static void
+sigqueue_debug(SIGNAL_QUEUE_HEADER *q, int which, struct seq_file *seq)
+{
+	seq_printf(seq, "Signal Queue #%d\n", which);
+	seq_printf(seq, "   VersionId          = %lu\n", (ulong) q->VersionId);
+	seq_printf(seq, "   Type               = %lu\n", (ulong) q->Type);
+	seq_printf(seq, "   oSignalBase        = %llu\n",
+		   (long long) q->oSignalBase);
+	seq_printf(seq, "   SignalSize         = %lu\n", (ulong) q->SignalSize);
+	seq_printf(seq, "   MaxSignalSlots     = %lu\n",
+		   (ulong) q->MaxSignalSlots);
+	seq_printf(seq, "   MaxSignals         = %lu\n", (ulong) q->MaxSignals);
+	seq_printf(seq, "   FeatureFlags       = %-16.16Lx\n",
+		   (long long) q->FeatureFlags);
+	seq_printf(seq, "   NumSignalsSent     = %llu\n",
+		   (long long) q->NumSignalsSent);
+	seq_printf(seq, "   NumSignalsReceived = %llu\n",
+		   (long long) q->NumSignalsReceived);
+	seq_printf(seq, "   NumOverflows       = %llu\n",
+		   (long long) q->NumOverflows);
+	seq_printf(seq, "   Head               = %lu\n", (ulong) q->Head);
+	seq_printf(seq, "   Tail               = %lu\n", (ulong) q->Tail);
+}
+
+void
+visorchannel_debug(VISORCHANNEL *channel, int nQueues,
+		   struct seq_file *seq, U32 off)
+{
+	HOSTADDRESS addr = 0;
+	ulong nbytes = 0, nbytes_region = 0;
+	MEMREGION *memregion = NULL;
+	CHANNEL_HEADER hdr;
+	CHANNEL_HEADER *phdr = &hdr;
+	char s[99];
+	int i = 0;
+	int errcode = 0;
+
+	if (channel == NULL) {
+		ERRDRV("%s no channel", __func__);
+		return;
+	}
+	memregion = channel->memregion;
+	if (memregion == NULL) {
+		ERRDRV("%s no memregion", __func__);
+		return;
+	}
+	addr = memregion_get_physaddr(memregion);
+	nbytes_region = memregion_get_nbytes(memregion);
+	errcode = visorchannel_read(channel, off,
+				    phdr, sizeof(CHANNEL_HEADER));
+	if (errcode < 0) {
+		seq_printf(seq,
+			   "Read of channel header failed with errcode=%d)\n",
+			   errcode);
+		if (off == 0) {
+			phdr = &channel->chan_hdr;
+			seq_puts(seq, "(following data may be stale)\n");
+		} else
+			return;
+	}
+	nbytes = (ulong) (phdr->Size);
+	seq_printf(seq, "--- Begin channel @0x%-16.16Lx for 0x%lx bytes (region=0x%lx bytes) ---\n",
+		   addr + off, nbytes, nbytes_region);
+	seq_printf(seq, "Type            = %s\n", GUID_format2(&phdr->Type, s));
+	seq_printf(seq, "ZoneGuid        = %s\n",
+		   GUID_format2(&phdr->ZoneGuid, s));
+	seq_printf(seq, "Signature       = 0x%-16.16Lx\n",
+		   (long long) phdr->Signature);
+	seq_printf(seq, "LegacyState     = %lu\n", (ulong) phdr->LegacyState);
+	seq_printf(seq, "SrvState        = %lu\n", (ulong) phdr->SrvState);
+	seq_printf(seq, "CliStateBoot    = %lu\n", (ulong) phdr->CliStateBoot);
+	seq_printf(seq, "CliStateOS      = %lu\n", (ulong) phdr->CliStateOS);
+	seq_printf(seq, "HeaderSize      = %lu\n", (ulong) phdr->HeaderSize);
+	seq_printf(seq, "Size            = %llu\n", (long long) phdr->Size);
+	seq_printf(seq, "Features        = 0x%-16.16llx\n",
+		   (long long) phdr->Features);
+	seq_printf(seq, "PartitionHandle = 0x%-16.16llx\n",
+		   (long long) phdr->PartitionHandle);
+	seq_printf(seq, "Handle          = 0x%-16.16llx\n",
+		   (long long) phdr->Handle);
+	seq_printf(seq, "VersionId       = %lu\n", (ulong) phdr->VersionId);
+	seq_printf(seq, "oChannelSpace   = %llu\n",
+		   (long long) phdr->oChannelSpace);
+	if ((phdr->oChannelSpace == 0) || (errcode < 0))
+		;
+	else
+		for (i = 0; i < nQueues; i++) {
+			SIGNAL_QUEUE_HEADER q;
+			errcode = visorchannel_read(channel,
+						    off + phdr->oChannelSpace +
+						    (i * sizeof(q)),
+						    &q, sizeof(q));
+			if (errcode < 0) {
+				seq_printf(seq,
+					   "failed to read signal queue #%d from channel @0x%-16.16Lx errcode=%d\n",
+					   i, addr, errcode);
+				continue;
+			}
+			sigqueue_debug(&q, i, seq);
+		}
+	seq_printf(seq, "--- End   channel @0x%-16.16Lx for 0x%lx bytes ---\n",
+		   addr + off, nbytes);
+}
+EXPORT_SYMBOL_GPL(visorchannel_debug);
+
+void
+visorchannel_dump_section(VISORCHANNEL *chan, char *s,
+			  int off, int len, struct seq_file *seq)
+{
+	char *buf = NULL, *fmtbuf = NULL;
+	int fmtbufsize = 0;
+	int i = 0;
+	int errcode = 0;
+
+	fmtbufsize = 100 * COVQ(len, 16);
+	buf = kmalloc(len, GFP_KERNEL|__GFP_NORETRY);
+	fmtbuf = kmalloc(fmtbufsize, GFP_KERNEL|__GFP_NORETRY);
+	if (buf == NULL || fmtbuf == NULL)
+		goto Away;
+
+	errcode = visorchannel_read(chan, off, buf, len);
+	if (errcode < 0) {
+		ERRDRV("%s failed to read %s from channel errcode=%d",
+		       s, __func__, errcode);
+		goto Away;
+	}
+	seq_printf(seq, "channel %s:\n", s);
+	hexDumpToBuffer(fmtbuf, fmtbufsize, "  ", buf, len, 16);
+	for (i = 0; fmtbuf[i] != '\0'; i++)
+		seq_printf(seq, "%c", fmtbuf[i]);
+
+Away:
+	if (buf != NULL) {
+		kfree(buf);
+		buf = NULL;
+	}
+	if (fmtbuf != NULL) {
+		kfree(fmtbuf);
+		fmtbuf = NULL;
+	}
+}
+EXPORT_SYMBOL_GPL(visorchannel_dump_section);
diff --git a/drivers/staging/unisys/visorchannel/visorchannel_main.c b/drivers/staging/unisys/visorchannel/visorchannel_main.c
new file mode 100644
index 0000000..482ee0a
--- /dev/null
+++ b/drivers/staging/unisys/visorchannel/visorchannel_main.c
@@ -0,0 +1,49 @@
+/* visorchannel_main.c
+ *
+ * Copyright © 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+/*
+ *  This is a module "wrapper" around visorchannel_funcs.
+ */
+
+#include "globals.h"
+#include "channel.h"
+#include "visorchannel.h"
+#include "guidutils.h"
+
+#define MYDRVNAME "visorchannel"
+
+static int __init
+visorchannel_init(void)
+{
+	INFODRV("driver version %s loaded", VERSION);
+	return 0;
+}
+
+static void
+visorchannel_exit(void)
+{
+	INFODRV("driver unloaded");
+}
+
+module_init(visorchannel_init);
+module_exit(visorchannel_exit);
+
+MODULE_AUTHOR("Unisys");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Supervisor channel driver for service partition: ver "
+		   VERSION);
+MODULE_VERSION(VERSION);
diff --git a/drivers/staging/unisys/visorchipset/Kconfig b/drivers/staging/unisys/visorchipset/Kconfig
new file mode 100644
index 0000000..7ca2fbc
--- /dev/null
+++ b/drivers/staging/unisys/visorchipset/Kconfig
@@ -0,0 +1,10 @@
+#
+# Unisys visorchipset configuration
+#
+
+config UNISYS_VISORCHIPSET
+	tristate "Unisys visorchipset driver"
+	depends on UNISYSSPAR && UNISYS_VISORUTIL && UNISYS_VISORCHANNEL
+	---help---
+	If you say Y here, you will enable the Unisys visorchipset driver.
+
diff --git a/drivers/staging/unisys/visorchipset/Makefile b/drivers/staging/unisys/visorchipset/Makefile
new file mode 100644
index 0000000..f5e8650
--- /dev/null
+++ b/drivers/staging/unisys/visorchipset/Makefile
@@ -0,0 +1,18 @@
+#
+# Makefile for Unisys visorchipset
+#
+
+obj-$(CONFIG_UNISYS_VISORCHIPSET)	+= visorchipset.o
+
+visorchipset-y := visorchipset_main.o controlvm_direct.o file.o filexfer.o \
+			parser.o
+
+ccflags-y += -Idrivers/staging/unisys/include
+ccflags-y += -Idrivers/staging/unisys/uislib
+ccflags-y += -Idrivers/staging/unisys/visorchannel
+ccflags-y += -Idrivers/staging/unisys/common-spar/include
+ccflags-y += -Idrivers/staging/unisys/common-spar/include/channels
+ccflags-y += -Idrivers/staging/unisys/visorutil
+ccflags-y += -Iinclude/generated
+ccflags-y += -DCONFIG_SPAR_GUEST -DGUESTDRIVERBUILD -DNOAUTOVERSION
+
diff --git a/drivers/staging/unisys/visorchipset/controlvm.h b/drivers/staging/unisys/visorchipset/controlvm.h
new file mode 100644
index 0000000..873fa12
--- /dev/null
+++ b/drivers/staging/unisys/visorchipset/controlvm.h
@@ -0,0 +1,27 @@
+/* controlvm.h
+ *
+ * Copyright © 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+#ifndef __CONTROLVM_H__
+#define __CONTROLVM_H__
+
+#include "timskmod.h"
+
+int         controlvm_init(void);
+void        controlvm_deinit(void);
+HOSTADDRESS controlvm_get_channel_address(void);
+
+#endif
diff --git a/drivers/staging/unisys/visorchipset/controlvm_direct.c b/drivers/staging/unisys/visorchipset/controlvm_direct.c
new file mode 100644
index 0000000..7fbc589
--- /dev/null
+++ b/drivers/staging/unisys/visorchipset/controlvm_direct.c
@@ -0,0 +1,61 @@
+/* controlvm_direct.c
+ *
+ * Copyright © 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+/* This is a controlvm-related code that is dependent upon firmware running
+ * on a virtual partition.
+ */
+
+#include "globals.h"
+#include "uisutils.h"
+#define CURRENT_FILE_PC VISOR_CHIPSET_PC_controlvm_direct_c
+
+
+/* We can fill in this code when we learn how to make vmcalls... */
+
+
+
+int controlvm_init(void)
+{
+	return 0;
+}
+
+
+
+void controlvm_deinit(void)
+{
+}
+
+
+
+HOSTADDRESS controlvm_get_channel_address(void)
+{
+	static BOOL warned = FALSE;
+	U64 addr = 0;
+
+	U32 size = 0;
+
+	if (!VMCALL_SUCCESSFUL(Issue_VMCALL_IO_CONTROLVM_ADDR(&addr, &size))) {
+		if (!warned) {
+			ERRDRV("%s - vmcall to determine controlvm channel addr failed",
+			       __func__);
+			warned = TRUE;
+		}
+		return 0;
+	}
+	INFODRV("controlvm addr=%Lx", addr);
+	return addr;
+}
diff --git a/drivers/staging/unisys/visorchipset/file.c b/drivers/staging/unisys/visorchipset/file.c
new file mode 100644
index 0000000..b0d28a2
--- /dev/null
+++ b/drivers/staging/unisys/visorchipset/file.c
@@ -0,0 +1,223 @@
+/* file.c
+ *
+ * Copyright © 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+/* This contains the implementation that allows a usermode program to
+ * communicate with the visorchipset driver using a device/file interface.
+ */
+
+#include "globals.h"
+#include "visorchannel.h"
+#include <linux/mm.h>
+#include <linux/fs.h>
+#include "uisutils.h"
+
+#define CURRENT_FILE_PC VISOR_CHIPSET_PC_file_c
+
+static struct cdev Cdev;
+static VISORCHANNEL **PControlVm_channel;
+static dev_t MajorDev = -1; /**< indicates major num for device */
+static BOOL Registered = FALSE;
+
+static int visorchipset_open(struct inode *inode, struct file *file);
+static int visorchipset_release(struct inode *inode, struct file *file);
+static int visorchipset_mmap(struct file *file, struct vm_area_struct *vma);
+#ifdef HAVE_UNLOCKED_IOCTL
+long visorchipset_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
+#else
+int visorchipset_ioctl(struct inode *inode, struct file *file,
+		       unsigned int cmd, unsigned long arg);
+#endif
+
+static const struct file_operations visorchipset_fops = {
+	.owner = THIS_MODULE,
+	.open = visorchipset_open,
+	.read = NULL,
+	.write = NULL,
+#ifdef HAVE_UNLOCKED_IOCTL
+	.unlocked_ioctl = visorchipset_ioctl,
+#else
+	.ioctl = visorchipset_ioctl,
+#endif
+	.release = visorchipset_release,
+	.mmap = visorchipset_mmap,
+};
+
+int
+visorchipset_file_init(dev_t majorDev, VISORCHANNEL **pControlVm_channel)
+{
+	int rc = -1;
+
+	PControlVm_channel = pControlVm_channel;
+	MajorDev = majorDev;
+	cdev_init(&Cdev, &visorchipset_fops);
+	Cdev.owner = THIS_MODULE;
+	if (MAJOR(MajorDev) == 0) {
+		/* dynamic major device number registration required */
+		if (alloc_chrdev_region(&MajorDev, 0, 1, MYDRVNAME) < 0) {
+			ERRDRV("Unable to allocate+register char device %s",
+			       MYDRVNAME);
+			RETINT(-1);
+		}
+		Registered = TRUE;
+		INFODRV("New major number %d registered\n", MAJOR(MajorDev));
+	} else {
+		/* static major device number registration required */
+		if (register_chrdev_region(MajorDev, 1, MYDRVNAME) < 0) {
+			ERRDRV("Unable to register char device %s", MYDRVNAME);
+			RETINT(-1);
+		}
+		Registered = TRUE;
+		INFODRV("Static major number %d registered\n", MAJOR(MajorDev));
+	}
+	if (cdev_add(&Cdev, MKDEV(MAJOR(MajorDev), 0), 1) < 0)
+		FAIL("failed to create char device", -1);
+	INFODRV("Registered char device for %s (major=%d)",
+		MYDRVNAME, MAJOR(MajorDev));
+	RETINT(0);
+Away:
+	return rc;
+}
+
+void
+visorchipset_file_cleanup(void)
+{
+	if (Cdev.ops != NULL)
+		cdev_del(&Cdev);
+	Cdev.ops = NULL;
+	if (Registered) {
+		if (MAJOR(MajorDev) >= 0) {
+			unregister_chrdev_region(MajorDev, 1);
+			MajorDev = MKDEV(0, 0);
+		}
+		Registered = FALSE;
+	}
+}
+
+static int
+visorchipset_open(struct inode *inode, struct file *file)
+{
+	unsigned minor_number = iminor(inode);
+	int rc = -ENODEV;
+
+	DEBUGDRV("%s", __func__);
+	if (minor_number != 0)
+		RETINT(-ENODEV);
+	file->private_data = NULL;
+	RETINT(0);
+Away:
+	if (rc < 0)
+		ERRDRV("%s minor=%d failed", __func__, minor_number);
+	return rc;
+}
+
+static int
+visorchipset_release(struct inode *inode, struct file *file)
+{
+	int rc = -1;
+	DEBUGDRV("%s", __func__);
+	RETINT(0);
+Away:
+	return rc;
+}
+
+static int
+visorchipset_mmap(struct file *file, struct vm_area_struct *vma)
+{
+	ulong physAddr = 0;
+	ulong offset = vma->vm_pgoff << PAGE_SHIFT;
+	GUEST_PHYSICAL_ADDRESS addr = 0;
+
+	/* sv_enable_dfp(); */
+	DEBUGDRV("%s", __func__);
+	if (offset & (PAGE_SIZE - 1)) {
+		ERRDRV("%s virtual address NOT page-aligned!", __func__);
+		return -ENXIO;	/* need aligned offsets */
+	}
+	switch (offset) {
+	case VISORCHIPSET_MMAP_CONTROLCHANOFFSET:
+		vma->vm_flags |= VM_IO;
+		if (*PControlVm_channel == NULL) {
+			ERRDRV("%s no controlvm channel yet", __func__);
+			return -ENXIO;
+		}
+		visorchannel_read(*PControlVm_channel,
+				  offsetof(ULTRA_CONTROLVM_CHANNEL_PROTOCOL,
+					   gpControlChannel), &addr,
+				  sizeof(addr));
+		if (addr == 0) {
+			ERRDRV("%s control channel address is 0", __func__);
+			return -ENXIO;
+		}
+		physAddr = (ulong) (addr);
+		DEBUGDRV("mapping physical address = 0x%lx", physAddr);
+		if (remap_pfn_range(vma, vma->vm_start,
+				    physAddr >> PAGE_SHIFT,
+				    vma->vm_end - vma->vm_start,
+				    /*pgprot_noncached */
+				    (vma->vm_page_prot))) {
+			ERRDRV("%s remap_pfn_range failed", __func__);
+			return -EAGAIN;
+		}
+		break;
+	default:
+		return -ENOSYS;
+	}
+	DEBUGDRV("%s success!", __func__);
+	return 0;
+}
+
+#ifdef HAVE_UNLOCKED_IOCTL
+long
+visorchipset_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+#else
+int
+visorchipset_ioctl(struct inode *inode, struct file *file,
+		   unsigned int cmd, unsigned long arg)
+#endif
+{
+	int rc = SUCCESS;
+	S64 adjustment;
+	S64 vrtc_offset;
+	DBGINF("entered visorchipset_ioctl, cmd=%d", cmd);
+	switch (cmd) {
+	case VMCALL_QUERY_GUEST_VIRTUAL_TIME_OFFSET:
+		/* get the physical rtc offset */
+		vrtc_offset = Issue_VMCALL_QUERY_GUEST_VIRTUAL_TIME_OFFSET();
+		if (copy_to_user
+		    ((void __user *)arg, &vrtc_offset, sizeof(vrtc_offset)))
+			RETINT(-EFAULT);
+		DBGINF("insde visorchipset_ioctl, cmd=%d, vrtc_offset=%lld",
+		       cmd, vrtc_offset);
+		break;
+	case VMCALL_UPDATE_PHYSICAL_TIME:
+		if (copy_from_user
+		    (&adjustment, (void __user *)arg, sizeof(adjustment)))
+			RETINT(-EFAULT);
+		DBGINF("insde visorchipset_ioctl, cmd=%d, adjustment=%lld", cmd,
+		       adjustment);
+		rc = Issue_VMCALL_UPDATE_PHYSICAL_TIME(adjustment);
+		break;
+	default:
+		LOGERR("visorchipset_ioctl received invalid command");
+		RETINT(-EFAULT);
+		break;
+	}
+	RETINT(rc);
+Away:
+	DBGINF("exiting %d!", rc);
+	return rc;
+}
diff --git a/drivers/staging/unisys/visorchipset/file.h b/drivers/staging/unisys/visorchipset/file.h
new file mode 100644
index 0000000..597282a
--- /dev/null
+++ b/drivers/staging/unisys/visorchipset/file.h
@@ -0,0 +1,26 @@
+/* file.h
+ *
+ * Copyright © 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+#ifndef __FILE_H__
+#define __FILE_H__
+
+#include "globals.h"
+
+int visorchipset_file_init(dev_t majorDev, VISORCHANNEL **pControlVm_channel);
+void visorchipset_file_cleanup(void);
+
+#endif
diff --git a/drivers/staging/unisys/visorchipset/filexfer.c b/drivers/staging/unisys/visorchipset/filexfer.c
new file mode 100644
index 0000000..431cff8
--- /dev/null
+++ b/drivers/staging/unisys/visorchipset/filexfer.c
@@ -0,0 +1,506 @@
+/* filexfer.c
+ *
+ * Copyright © 2013 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+/* Code here-in is the "glue" that connects controlvm messages with the
+ * sparfilexfer driver, which is used to transfer file contents as payload
+ * across the controlvm channel.
+ */
+
+#include "globals.h"
+#include "controlvm.h"
+#include "visorchipset.h"
+#include "filexfer.h"
+
+#ifdef ENABLE_SPARFILEXFER /* sparfilexfer kernel module enabled in build */
+#include "sparfilexfer.h"
+
+/* Driver-global memory */
+static LIST_HEAD(Request_list);	/* list of struct any_request *, via
+				 * req_list memb */
+
+/* lock for above pool for allocation of any_request structs, and pool
+* name; note that kmem_cache_create requires that we keep the storage
+* for the pool name for the life of the pool
+ */
+static DEFINE_SPINLOCK(Request_list_lock);
+
+static struct kmem_cache *Request_memory_pool;
+static const char Request_memory_pool_name[] = "filexfer_request_pool";
+size_t Caller_req_context_bytes = 0;	/* passed to filexfer_constructor() */
+
+/* This structure defines a single controlvm GETFILE conversation, which
+ * consists of a single controlvm request message and 1 or more controlvm
+ * response messages.
+ */
+struct getfile_request {
+	CONTROLVM_MESSAGE_HEADER controlvm_header;
+	atomic_t buffers_in_use;
+	GET_CONTIGUOUS_CONTROLVM_PAYLOAD_FUNC get_contiguous_controlvm_payload;
+	CONTROLVM_RESPOND_WITH_PAYLOAD_FUNC controlvm_respond_with_payload;
+};
+
+/* This structure defines a single controlvm PUTFILE conversation, which
+ * consists of a single controlvm request with a filename, and additional
+ * controlvm messages with file data.
+ */
+struct putfile_request {
+	GET_CONTROLVM_FILEDATA_FUNC get_controlvm_filedata;
+	CONTROLVM_RESPOND_FUNC controlvm_end_putFile;
+};
+
+/* This structure defines a single file transfer operation, which can either
+ * be a GETFILE or PUTFILE.
+ */
+struct any_request {
+	struct list_head req_list;
+	ulong2 file_request_number;
+	ulong2 data_sequence_number;
+	TRANSMITFILE_DUMP_FUNC dump_func;
+	BOOL is_get;
+	union {
+		struct getfile_request get;
+		struct putfile_request put;
+	};
+	/* Size of caller_context_data will be
+	 * <Caller_req_context_bytes> bytes.  I aligned this because I
+	 * am paranoid about what happens when an arbitrary data
+	 * structure with unknown alignment requirements gets copied
+	 * here.  I want caller_context_data to be aligned to the
+	 * coarsest possible alignment boundary that could be required
+	 * for any user data structure.
+	 */
+	u8 caller_context_data[1] __aligned(sizeof(ulong2);
+};
+
+/*
+ * Links the any_request into the global list of allocated requests
+ * (<Request_list>).
+ */
+static void
+unit_tracking_create(struct list_head *dev_list_link)
+{
+	unsigned long flags;
+	spin_lock_irqsave(&Request_list_lock, flags);
+	list_add(dev_list_link, &Request_list);
+	spin_unlock_irqrestore(&Request_list_lock, flags);
+}
+
+/* Unlinks a any_request from the global list (<Request_list>).
+ */
+static void
+unit_tracking_destroy(struct list_head *dev_list_link)
+{
+	unsigned long flags;
+	spin_lock_irqsave(&Request_list_lock, flags);
+	list_del(dev_list_link);
+	spin_unlock_irqrestore(&Request_list_lock, flags);
+}
+
+/* Allocate memory for and return a new any_request struct, and
+ * link it to the global list of outstanding requests.
+ */
+static struct any_request *
+alloc_request(char *fn, int ln)
+{
+	struct any_request *req = (struct any_request *)
+	    (visorchipset_cache_alloc(Request_memory_pool,
+				      FALSE,
+				      fn, ln));
+	if (!req)
+		return NULL;
+	memset(req, 0, sizeof(struct any_request) + Caller_req_context_bytes);
+	unit_tracking_create(&req->req_list);
+	return req;
+}
+
+/* Book-end for alloc_request().
+ */
+static void
+free_request(struct any_request *req, char *fn, int ln)
+{
+	unit_tracking_destroy(&req->req_list);
+	visorchipset_cache_free(Request_memory_pool, req, fn, ln);
+}
+
+/* Constructor for filexfer.o.
+ */
+int
+filexfer_constructor(size_t req_context_bytes)
+{
+	int rc = -1;
+
+	Caller_req_context_bytes = req_context_bytes;
+	Request_memory_pool =
+	    kmem_cache_create(Request_memory_pool_name,
+			      sizeof(struct any_request) +
+			      Caller_req_context_bytes,
+			      0, SLAB_HWCACHE_ALIGN, NULL);
+	if (!Request_memory_pool) {
+		LOGERR("failed to alloc Request_memory_pool");
+		rc = -ENOMEM;
+		goto Away;
+	}
+	rc = 0;
+Away:
+	if (rc < 0) {
+		if (Request_memory_pool) {
+			kmem_cache_destroy(Request_memory_pool);
+			Request_memory_pool = NULL;
+		}
+	}
+	return rc;
+}
+
+/* Destructor for filexfer.o.
+ */
+void
+filexfer_destructor(void)
+{
+	if (Request_memory_pool) {
+		kmem_cache_destroy(Request_memory_pool);
+		Request_memory_pool = NULL;
+	}
+}
+
+/* This function will obtain an available chunk from the controlvm payload area,
+ * store the size in bytes of the chunk in <actual_size>, and return a pointer
+ * to the chunk.  The function is passed to the sparfilexfer driver, which calls
+ * it whenever payload space is required to copy file data into.
+ */
+static void *
+get_empty_bucket_for_getfile_data(void *context,
+				  ulong min_size, ulong max_size,
+				  ulong *actual_size)
+{
+	void *bucket;
+	struct any_request *req = (struct any_request *) context;
+
+	if (!req->is_get) {
+		LOGERR("%s - unexpected call", __func__);
+		return NULL;
+	}
+	bucket = (*req->get.get_contiguous_controlvm_payload)
+	    (min_size, max_size, actual_size);
+	if (bucket != NULL) {
+		atomic_inc(&req->get.buffers_in_use);
+		DBGINF("%s - sent %lu-byte buffer", __func__, *actual_size);
+	}
+	return bucket;
+}
+
+/* This function will send a controlvm response with data in the payload
+ * (whose space was obtained with get_empty_bucket_for_getfile_data).  The
+ * function is passed to the sparfilexfer driver, which calls it whenever it
+ * wants to send file data back across the controlvm channel.
+ */
+static int
+send_full_getfile_data_bucket(void *context, void *bucket,
+			      ulong bucket_actual_size, ulong bucket_used_size)
+{
+	struct any_request *req = (struct any_request *) context;
+
+	if (!req->is_get) {
+		LOGERR("%s - unexpected call", __func__);
+		return 0;
+	}
+	DBGINF("sending buffer for %lu/%lu",
+	       bucket_used_size, bucket_actual_size);
+	if (!(*req->get.controlvm_respond_with_payload)
+	    (&req->get.controlvm_header,
+	     req->file_request_number,
+	     req->data_sequence_number++,
+	     0, bucket, bucket_actual_size, bucket_used_size, TRUE))
+		atomic_dec(&req->get.buffers_in_use);
+	return 0;
+}
+
+/* This function will send a controlvm response indicating the end of a
+ * GETFILE transfer.  The function is passed to the sparfilexfer driver.
+ */
+static void
+send_end_of_getfile_data(void *context, int status)
+{
+	struct any_request *req = (struct any_request *) context;
+	if (!req->is_get) {
+		LOGERR("%s - unexpected call", __func__);
+		return;
+	}
+	LOGINF("status=%d", status);
+	(*req->get.controlvm_respond_with_payload)
+	    (&req->get.controlvm_header,
+	     req->file_request_number,
+	     req->data_sequence_number++, status, NULL, 0, 0, FALSE);
+	free_request(req, __FILE__, __LINE__);
+	module_put(THIS_MODULE);
+}
+
+/* This function supplies data for a PUTFILE transfer.
+ * The function is passed to the sparfilexfer driver.
+ */
+static int
+get_putfile_data(void *context, void *pbuf, size_t bufsize,
+		 BOOL buf_is_userspace, size_t *bytes_transferred)
+{
+	struct any_request *req = (struct any_request *) context;
+	if (req->is_get) {
+		LOGERR("%s - unexpected call", __func__);
+		return -1;
+	}
+	return (*req->put.get_controlvm_filedata) (&req->caller_context_data[0],
+						   pbuf, bufsize,
+						   buf_is_userspace,
+						   bytes_transferred);
+}
+
+/* This function is called to indicate the end of a PUTFILE transfer.
+ * The function is passed to the sparfilexfer driver.
+ */
+static void
+end_putfile(void *context, int status)
+{
+	struct any_request *req = (struct any_request *) context;
+	if (req->is_get) {
+		LOGERR("%s - unexpected call", __func__);
+		return;
+	}
+	(*req->put.controlvm_end_putFile) (&req->caller_context_data[0],
+					   status);
+	free_request(req, __FILE__, __LINE__);
+	module_put(THIS_MODULE);
+}
+
+/* Refer to filexfer.h for description. */
+BOOL
+filexfer_getFile(CONTROLVM_MESSAGE_HEADER *msgHdr,
+		 ulong2 file_request_number,
+		 uint uplink_index,
+		 uint disk_index,
+		 char *file_name,
+		 GET_CONTIGUOUS_CONTROLVM_PAYLOAD_FUNC
+		 get_contiguous_controlvm_payload,
+		 CONTROLVM_RESPOND_WITH_PAYLOAD_FUNC
+		 controlvm_respond_with_payload,
+		 TRANSMITFILE_DUMP_FUNC dump_func)
+{
+	BOOL use_count_up = FALSE;
+	BOOL failed = TRUE;
+	struct any_request *req = alloc_request(__FILE__, __LINE__);
+
+	if (!req) {
+		LOGERR("allocation of any_request failed");
+		goto Away;
+	}
+	/* We need to increment this module's use count because we're handing
+	 * off pointers to functions within this module to be used by
+	 * another module.
+	 */
+	__module_get(THIS_MODULE);
+	use_count_up = TRUE;
+	req->is_get = TRUE;
+	req->file_request_number = file_request_number;
+	req->data_sequence_number = 0;
+	req->dump_func = dump_func;
+	req->get.controlvm_header = *msgHdr;
+	atomic_set(&req->get.buffers_in_use, 0);
+	req->get.get_contiguous_controlvm_payload =
+	    get_contiguous_controlvm_payload;
+	req->get.controlvm_respond_with_payload =
+	    controlvm_respond_with_payload;
+	if (sparfilexfer_local2remote(req,	/* context, passed to
+						 * callback funcs */
+				      file_name,
+				      file_request_number,
+				      uplink_index,
+				      disk_index,
+				      get_empty_bucket_for_getfile_data,
+				      send_full_getfile_data_bucket,
+				      send_end_of_getfile_data) < 0) {
+		LOGERR("sparfilexfer_local2remote failed");
+		goto Away;
+	}
+	failed = FALSE;
+Away:
+	if (failed) {
+		if (use_count_up) {
+			module_put(THIS_MODULE);
+			use_count_up = FALSE;
+		}
+		if (req) {
+			free_request(req, __FILE__, __LINE__);
+			req = NULL;
+		}
+		return FALSE;
+	} else {
+		return TRUE;
+		/* success; send callbacks will be called for responses */
+	}
+}
+
+/* Refer to filexfer.h for description. */
+void *
+filexfer_putFile(CONTROLVM_MESSAGE_HEADER *msgHdr,
+		 ulong2 file_request_number,
+		 uint uplink_index,
+		 uint disk_index,
+		 char *file_name,
+		 TRANSMITFILE_INIT_CONTEXT_FUNC init_context,
+		 GET_CONTROLVM_FILEDATA_FUNC get_controlvm_filedata,
+		 CONTROLVM_RESPOND_FUNC controlvm_end_putFile,
+		 TRANSMITFILE_DUMP_FUNC dump_func)
+{
+	BOOL use_count_up = FALSE;
+	BOOL failed = TRUE;
+	struct any_request *req = alloc_request(__FILE__, __LINE__);
+	void *caller_ctx = NULL;
+
+	if (!req) {
+		LOGERR("allocation of any_request failed");
+		goto Away;
+	}
+	caller_ctx = (void *) (&(req->caller_context_data[0]));
+	/* We need to increment this module's use count because we're handing
+	 * off pointers to functions within this module to be used by
+	 * another module.
+	 */
+	__module_get(THIS_MODULE);
+	use_count_up = TRUE;
+	req->is_get = FALSE;
+	req->file_request_number = file_request_number;
+	req->data_sequence_number = 0;
+	req->dump_func = dump_func;
+	req->put.get_controlvm_filedata = get_controlvm_filedata;
+	req->put.controlvm_end_putFile = controlvm_end_putFile;
+	(*init_context) (caller_ctx, msgHdr, file_request_number);
+	if (sparfilexfer_remote2local(req,	/* context, passed to
+						 * callback funcs */
+				      file_name,
+				      file_request_number,
+				      uplink_index,
+				      disk_index,
+				      get_putfile_data, end_putfile) < 0) {
+		LOGERR("sparfilexfer_remote2local failed");
+		goto Away;
+	}
+	failed = FALSE;
+Away:
+	if (failed) {
+		if (use_count_up) {
+			module_put(THIS_MODULE);
+			use_count_up = FALSE;
+		}
+		if (req) {
+			free_request(req, __FILE__, __LINE__);
+			req = NULL;
+		}
+		return NULL;
+	} else {
+		return caller_ctx;
+		/* success; callbacks will be called for responses */
+	}
+}
+
+static void
+dump_get_request(struct seq_file *f, struct getfile_request *getreq)
+{
+	seq_printf(f, "  buffers_in_use=%d\n",
+		   atomic_read(&getreq->buffers_in_use));
+}
+
+static void
+dump_put_request(struct seq_file *f, struct putfile_request *putreq)
+{
+}
+
+static void
+dump_request(struct seq_file *f, struct any_request *req)
+{
+	seq_printf(f, "* %s id=%llu seq=%llu\n",
+		   ((req->is_get) ? "Get" : "Put"),
+		   req->file_request_number, req->data_sequence_number);
+	if (req->is_get)
+		dump_get_request(f, &req->get);
+	else
+		dump_put_request(f, &req->put);
+	if (req->dump_func)
+		(*req->dump_func) (f, &(req->caller_context_data[0]), "  ");
+}
+
+void
+filexfer_dump(struct seq_file *f)
+{
+	ulong flags;
+	struct list_head *entry;
+
+	seq_puts(f, "Outstanding TRANSMIT_FILE requests:\n");
+	spin_lock_irqsave(&Request_list_lock, flags);
+	list_for_each(entry, &Request_list) {
+		struct any_request *req;
+		req = list_entry(entry, struct any_request, req_list);
+		dump_request(f, req);
+	}
+	spin_unlock_irqrestore(&Request_list_lock, flags);
+}
+
+#else				/* ifdef ENABLE_SPARFILEXFER */
+int
+filexfer_constructor(size_t req_context_bytes)
+{
+	return 0;		/* success */
+}
+
+void
+filexfer_destructor(void)
+{
+}
+
+BOOL
+filexfer_getFile(CONTROLVM_MESSAGE_HEADER *msgHdr,
+		 u64 file_request_number,
+		 uint uplink_index,
+		 uint disk_index,
+		 char *file_name,
+		 GET_CONTIGUOUS_CONTROLVM_PAYLOAD_FUNC
+		 get_contiguous_controlvm_payload,
+		 CONTROLVM_RESPOND_WITH_PAYLOAD_FUNC
+		 controlvm_respond_with_payload,
+		 TRANSMITFILE_DUMP_FUNC dump_func)
+{
+	/* since no sparfilexfer module exists to call, we just fail */
+	return FALSE;
+}
+
+void *
+filexfer_putFile(CONTROLVM_MESSAGE_HEADER *msgHdr,
+		 u64 file_request_number,
+		 uint uplink_index,
+		 uint disk_index,
+		 char *file_name,
+		 TRANSMITFILE_INIT_CONTEXT_FUNC init_context,
+		 GET_CONTROLVM_FILEDATA_FUNC get_controlvm_filedata,
+		 CONTROLVM_RESPOND_FUNC controlvm_end_putFile,
+		 TRANSMITFILE_DUMP_FUNC dump_func)
+{
+	/* since no sparfilexfer module exists to call, we just fail */
+	return NULL;
+}
+
+void
+filexfer_dump(struct seq_file *f)
+{
+}
+
+#endif				/* ifdef ENABLE_SPARFILEXFER */
diff --git a/drivers/staging/unisys/visorchipset/filexfer.h b/drivers/staging/unisys/visorchipset/filexfer.h
new file mode 100644
index 0000000..a1bfca6
--- /dev/null
+++ b/drivers/staging/unisys/visorchipset/filexfer.h
@@ -0,0 +1,147 @@
+/* filexfer.h
+ *
+ * Copyright © 2013 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+/* This header file defines the interface that filexfer.c provides to other
+ * code in the visorchipset driver.
+ */
+
+#ifndef __FILEXFER_H__
+#define __FILEXFER_H__
+
+#include "globals.h"
+#include "controlvmchannel.h"
+#include <linux/seq_file.h>
+
+typedef void *(*GET_CONTIGUOUS_CONTROLVM_PAYLOAD_FUNC) (ulong min_size,
+							ulong max_size,
+							ulong *actual_size);
+
+typedef BOOL
+(*CONTROLVM_RESPOND_WITH_PAYLOAD_FUNC) (CONTROLVM_MESSAGE_HEADER *msgHdr,
+					u64 fileRequestNumber,
+					u64 dataSequenceNumber,
+					int response,
+					void *bucket, ulong payloadChunkSize,
+					ulong payloadUsedBytes, BOOL partial);
+
+typedef void
+(*TRANSMITFILE_INIT_CONTEXT_FUNC)(void *ctx,
+				  const CONTROLVM_MESSAGE_HEADER *hdr,
+				  u64 file_request_number);
+typedef void (*TRANSMITFILE_DUMP_FUNC) (struct seq_file *f, void *ctx,
+					const char *pfx);
+typedef int (*GET_CONTROLVM_FILEDATA_FUNC) (void *ctx,
+					    void *buf, size_t bufsize,
+					    BOOL buf_is_userspace,
+					    size_t *bytes_transferred);
+typedef void (*CONTROLVM_RESPOND_FUNC) (void *ctx, int response);
+
+/* Call once to initialize filexfer.o.
+ * req_context_bytes number of bytes the caller needs to keep track of each file
+ * transfer conversation.  The <ctx_init_value> passed to filexfer_putFile() is
+ * assumed to be this many bytes in size.  Code within filexfer.o will copy this
+ * into a dynamically-allocated area, and pass back a pointer to that area in
+ * callback functions.
+ */
+int filexfer_constructor(size_t req_context_bytes);
+
+/* Call once to clean up filexfer.o */
+void filexfer_destructor(void);
+
+/* Call this to dump diagnostic info about all outstanding getFiles/putFiles */
+void filexfer_dump(struct seq_file *f);
+
+/* Call to transfer a file from the local filesystem (i.e., from the environment
+ * where this driver is running) across the controlvm channel to a remote
+ * environment.  1 or more controlvm responses will be sent as a result, each
+ * of which whose payload contains file data.  Only the last controlvm message
+ * will have Flags.partialCompletion==0.
+ *
+ *   msgHdr      the controlvm message header of the GETFILE request which
+ *               we just received
+ *   file_request_number  this is all data from the GETFILE request that
+ *   uplink_index         define which file is to be transferred
+ *   disk_index
+ *   file_name
+ *   get_contiguous_controlvm_payload  function to call when space is needed
+ *                                     in the payload area
+ *   controlvm_respond_with_payload    function to call to send each controlvm
+ *                                     response containing file data as the
+ *                                     payload; returns FALSE only if the
+ *				       payload buffer was freed inline
+ *   dump_func                         function to dump context data in
+ *                                     human-readable format
+ *
+ *  Returns TRUE iff the file transfer request has been successfully initiated,
+ *  or FALSE to indicate failure.
+ */
+BOOL
+filexfer_getFile(CONTROLVM_MESSAGE_HEADER *msgHdr,
+		 u64 file_request_number,
+		 uint uplink_index,
+		 uint disk_index,
+		 char *file_name,
+		 GET_CONTIGUOUS_CONTROLVM_PAYLOAD_FUNC
+		 get_contiguous_controlvm_payload,
+		 CONTROLVM_RESPOND_WITH_PAYLOAD_FUNC
+		 controlvm_respond_with_payload,
+		 TRANSMITFILE_DUMP_FUNC dump_func);
+
+/* Call to create a file in the local filesystem (i.e., in the environment
+ * where this driver is running) from data received as payload in
+ * controlvm channel messages from a remote environment.  1 or more controlvm
+ * messages will be received for this transfer, and only the last will have
+ * Flags.partialCompletion==0.
+ *
+ *   msgHdr      the controlvm message header of the PUTFILE request which
+ *               we just received
+ *   file_request_number  this is all data from the PUTFILE request that
+ *   uplink_index         define which file is to be created in the local
+ *   disk_index           filesystem
+ *   file_name
+ *   init_context         function to call to initialize the
+ *                        <req_context_bytes>-sized storage area returned by
+ *                        this func; note that it would NOT be sufficient to
+ *                        allow the caller to initialize this upon return, as
+ *                        the the other user-supplied callbacks might have
+ *                        already been called by then
+ *   get_controlvm_filedata   function to call to obtain more data for the file
+ *                            being written; refer to get_controlvm_filedata()
+ *                            in visorchipset_main.c for a complete description
+ *                            of parameters
+ *   controlvm_end_putFile    function to call to indicate that creation of the
+ *                            local file has completed;  set <response> to a
+ *                            negative value to indicate an error
+ *   dump_func                function to dump context data in human-readable
+ *                            format
+ *
+ *  Returns a pointer to a dynamically-allocated storage area of size
+ *  <req_context_bytes> which the caller can use, or NULL for error.  The
+ *  caller should NEVER free the returned pointer, but should expect to receive
+ *  it as the <ctx> argument when callback functions are called.
+ */
+void *filexfer_putFile(CONTROLVM_MESSAGE_HEADER *msgHdr,
+		       u64 file_request_number,
+		       uint uplink_index,
+		       uint disk_index,
+		       char *file_name,
+		       TRANSMITFILE_INIT_CONTEXT_FUNC init_context,
+		       GET_CONTROLVM_FILEDATA_FUNC get_controlvm_filedata,
+		       CONTROLVM_RESPOND_FUNC controlvm_end_putFile,
+		       TRANSMITFILE_DUMP_FUNC dump_func);
+
+#endif
diff --git a/drivers/staging/unisys/visorchipset/globals.h b/drivers/staging/unisys/visorchipset/globals.h
new file mode 100644
index 0000000..a0e6d4f
--- /dev/null
+++ b/drivers/staging/unisys/visorchipset/globals.h
@@ -0,0 +1,45 @@
+/* globals.h
+ *
+ * Copyright © 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+
+#ifndef __VISORCHIPSET_GLOBALS_H__
+#define __VISORCHIPSET_GLOBALS_H__
+
+#include "uniklog.h"
+#include "diagnostics/appos_subsystems.h"
+#include "timskmod.h"
+#include "visorchipset.h"
+#include "visorchipset_umode.h"
+#include "version.h"
+
+#define MYDRVNAME "visorchipset"
+
+
+/* module parameters */
+
+extern int visorchipset_testvnic;
+extern int visorchipset_testvnicclient;
+extern int visorchipset_testmsg;
+extern int visorchipset_major;
+extern int visorchipset_serverregwait;
+extern int visorchipset_clientregwait;
+extern int visorchipset_testteardown;
+extern int visorchipset_disable_controlvm;
+extern int visorchipset_crash_kernel;
+extern int visorchipset_holdchipsetready;
+
+#endif
diff --git a/drivers/staging/unisys/visorchipset/parser.c b/drivers/staging/unisys/visorchipset/parser.c
new file mode 100644
index 0000000..09b3a84
--- /dev/null
+++ b/drivers/staging/unisys/visorchipset/parser.c
@@ -0,0 +1,466 @@
+/* parser.c
+ *
+ * Copyright © 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+#include "parser.h"
+#include "memregion.h"
+#include "controlvmchannel.h"
+#include <linux/ctype.h>
+#include <linux/mm.h>
+
+#define MYDRVNAME "visorchipset_parser"
+#define CURRENT_FILE_PC VISOR_CHIPSET_PC_parser_c
+
+/* We will refuse to allocate more than this many bytes to copy data from
+ * incoming payloads.  This serves as a throttling mechanism.
+ */
+#define MAX_CONTROLVM_PAYLOAD_BYTES (1024*128)
+static ulong Controlvm_Payload_Bytes_Buffered;
+
+struct PARSER_CONTEXT_Tag {
+	ulong allocbytes;
+	ulong param_bytes;
+	u8 *curr;
+	ulong bytes_remaining;
+	BOOL byte_stream;
+	char data[0];
+};
+
+static PARSER_CONTEXT *
+parser_init_guts(U64 addr, U32 bytes, BOOL isLocal,
+		 BOOL hasStandardPayloadHeader, BOOL *tryAgain)
+{
+	int allocbytes = sizeof(PARSER_CONTEXT) + bytes;
+	PARSER_CONTEXT *rc = NULL;
+	PARSER_CONTEXT *ctx = NULL;
+	MEMREGION *rgn = NULL;
+	ULTRA_CONTROLVM_PARAMETERS_HEADER *phdr = NULL;
+
+	if (tryAgain)
+		*tryAgain = FALSE;
+	if (!hasStandardPayloadHeader)
+		/* alloc and 0 extra byte to ensure payload is
+		 * '\0'-terminated
+		 */
+		allocbytes++;
+	if ((Controlvm_Payload_Bytes_Buffered + bytes)
+	    > MAX_CONTROLVM_PAYLOAD_BYTES) {
+		ERRDRV("%s (%s:%d) - prevented allocation of %d bytes to prevent exceeding throttling max (%d)",
+		       __func__, __FILE__, __LINE__, allocbytes,
+		       MAX_CONTROLVM_PAYLOAD_BYTES);
+		if (tryAgain)
+			*tryAgain = TRUE;
+		RETPTR(NULL);
+	}
+	ctx = kmalloc(allocbytes, GFP_KERNEL|__GFP_NORETRY);
+	if (ctx == NULL) {
+		ERRDRV("%s (%s:%d) - failed to allocate %d bytes",
+		       __func__, __FILE__, __LINE__, allocbytes);
+		if (tryAgain)
+			*tryAgain = TRUE;
+		RETPTR(NULL);
+	}
+	memset(ctx, 0, allocbytes);
+	ctx->allocbytes = allocbytes;
+	ctx->param_bytes = bytes;
+	ctx->curr = NULL;
+	ctx->bytes_remaining = 0;
+	ctx->byte_stream = FALSE;
+	if (isLocal) {
+		void *p;
+		if (addr > virt_to_phys(high_memory - 1)) {
+			ERRDRV("%s - bad local address (0x%-16.16Lx for %lu)",
+			       __func__,
+			       (unsigned long long) addr, (ulong) bytes);
+			RETPTR(NULL);
+		}
+		p = __va((ulong) (addr));
+		memcpy(ctx->data, p, bytes);
+	} else {
+		rgn = memregion_create(addr, bytes);
+		if (!rgn)
+			RETPTR(NULL);
+		if (memregion_read(rgn, 0, ctx->data, bytes) < 0)
+			RETPTR(NULL);
+	}
+	if (!hasStandardPayloadHeader) {
+		ctx->byte_stream = TRUE;
+		RETPTR(ctx);
+	}
+	phdr = (ULTRA_CONTROLVM_PARAMETERS_HEADER *) (ctx->data);
+	if (phdr->TotalLength != bytes) {
+		ERRDRV("%s - bad total length %lu (should be %lu)",
+		       __func__,
+		       (ulong) (phdr->TotalLength), (ulong) (bytes));
+		RETPTR(NULL);
+	}
+	if (phdr->TotalLength < phdr->HeaderLength) {
+		ERRDRV("%s - total length < header length (%lu < %lu)",
+		       __func__,
+		       (ulong) (phdr->TotalLength),
+		       (ulong) (phdr->HeaderLength));
+		RETPTR(NULL);
+	}
+	if (phdr->HeaderLength < sizeof(ULTRA_CONTROLVM_PARAMETERS_HEADER)) {
+		ERRDRV("%s - header is too small (%lu < %lu)",
+		       __func__,
+		       (ulong) (phdr->HeaderLength),
+		       (ulong) (sizeof(ULTRA_CONTROLVM_PARAMETERS_HEADER)));
+		RETPTR(NULL);
+	}
+
+	RETPTR(ctx);
+
+Away:
+	if (rgn) {
+		memregion_destroy(rgn);
+		rgn = NULL;
+	}
+	if (rc)
+		Controlvm_Payload_Bytes_Buffered += ctx->param_bytes;
+	else {
+		if (ctx) {
+			parser_done(ctx);
+			ctx = NULL;
+		}
+	}
+	return rc;
+}
+
+PARSER_CONTEXT *
+parser_init(U64 addr, U32 bytes, BOOL isLocal, BOOL *tryAgain)
+{
+	return parser_init_guts(addr, bytes, isLocal, TRUE, tryAgain);
+}
+
+/* Call this instead of parser_init() if the payload area consists of just
+ * a sequence of bytes, rather than a ULTRA_CONTROLVM_PARAMETERS_HEADER
+ * structures.  Afterwards, you can call parser_simpleString_get() or
+ * parser_byteStream_get() to obtain the data.
+ */
+PARSER_CONTEXT *
+parser_init_byteStream(U64 addr, U32 bytes, BOOL isLocal, BOOL *tryAgain)
+{
+	return parser_init_guts(addr, bytes, isLocal, FALSE, tryAgain);
+}
+
+/* Obtain '\0'-terminated copy of string in payload area.
+ */
+char *
+parser_simpleString_get(PARSER_CONTEXT *ctx)
+{
+	if (!ctx->byte_stream)
+		return NULL;
+	return ctx->data;	/* note this IS '\0'-terminated, because of
+				 * the num of bytes we alloc+clear in
+				 * parser_init_byteStream() */
+}
+
+/* Obtain a copy of the buffer in the payload area.
+ */
+void *
+parser_byteStream_get(PARSER_CONTEXT *ctx, ulong *nbytes)
+{
+	if (!ctx->byte_stream)
+		return NULL;
+	if (nbytes)
+		*nbytes = ctx->param_bytes;
+	return (void *) ctx->data;
+}
+
+GUID
+parser_id_get(PARSER_CONTEXT *ctx)
+{
+	ULTRA_CONTROLVM_PARAMETERS_HEADER *phdr = NULL;
+
+	if (ctx == NULL) {
+		ERRDRV("%s (%s:%d) - no context",
+		       __func__, __FILE__, __LINE__);
+		return Guid0;
+	}
+	phdr = (ULTRA_CONTROLVM_PARAMETERS_HEADER *) (ctx->data);
+	return phdr->Id;
+}
+
+void
+parser_param_start(PARSER_CONTEXT *ctx, PARSER_WHICH_STRING which_string)
+{
+	ULTRA_CONTROLVM_PARAMETERS_HEADER *phdr = NULL;
+
+	if (ctx == NULL) {
+		ERRDRV("%s (%s:%d) - no context",
+		       __func__, __FILE__, __LINE__);
+		RETVOID;
+	}
+	phdr = (ULTRA_CONTROLVM_PARAMETERS_HEADER *) (ctx->data);
+	switch (which_string) {
+	case PARSERSTRING_INITIATOR:
+		ctx->curr = ctx->data + phdr->InitiatorOffset;
+		ctx->bytes_remaining = phdr->InitiatorLength;
+		break;
+	case PARSERSTRING_TARGET:
+		ctx->curr = ctx->data + phdr->TargetOffset;
+		ctx->bytes_remaining = phdr->TargetLength;
+		break;
+	case PARSERSTRING_CONNECTION:
+		ctx->curr = ctx->data + phdr->ConnectionOffset;
+		ctx->bytes_remaining = phdr->ConnectionLength;
+		break;
+	case PARSERSTRING_NAME:
+		ctx->curr = ctx->data + phdr->NameOffset;
+		ctx->bytes_remaining = phdr->NameLength;
+		break;
+	default:
+		ERRDRV("%s - bad which_string %d", __func__, which_string);
+		RETVOID;
+		break;
+	}
+	RETVOID;
+
+Away:
+	return;
+}
+
+void
+parser_done(PARSER_CONTEXT *ctx)
+{
+	if (!ctx)
+		return;
+	Controlvm_Payload_Bytes_Buffered -= ctx->param_bytes;
+	kfree(ctx);
+}
+
+/** Return length of string not counting trailing spaces. */
+static int
+string_length_no_trail(char *s, int len)
+{
+	int i = len - 1;
+	while (i >= 0) {
+		if (!isspace(s[i]))
+			return i + 1;
+		i--;
+	}
+	return 0;
+}
+
+/** Grab the next name and value out of the parameter buffer.
+ *  The entire parameter buffer looks like this:
+ *      <name>=<value>\0
+ *      <name>=<value>\0
+ *      ...
+ *      \0
+ *  If successful, the next <name> value is returned within the supplied
+ *  <nam> buffer (the value is always upper-cased), and the corresponding
+ *  <value> is returned within a kmalloc()ed buffer, whose pointer is
+ *  provided as the return value of this function.
+ *  (The total number of bytes allocated is strlen(<value>)+1.)
+ *
+ *  NULL is returned to indicate failure, which can occur for several reasons:
+ *  - all <name>=<value> pairs have already been processed
+ *  - bad parameter
+ *  - parameter buffer ends prematurely (couldn't find an '=' or '\0' within
+ *    the confines of the parameter buffer)
+ *  - the <nam> buffer is not large enough to hold the <name> of the next
+ *    parameter
+ */
+void *
+parser_param_get(PARSER_CONTEXT *ctx, char *nam, int namesize)
+{
+	u8 *pscan, *pnam = nam;
+	ulong nscan;
+	int value_length = -1, orig_value_length = -1;
+	void *value = NULL;
+	int i;
+	int closing_quote = 0;
+
+	if (!ctx)
+		return NULL;
+	pscan = ctx->curr;
+	nscan = ctx->bytes_remaining;
+	if (nscan == 0)
+		return NULL;
+	if (*pscan == '\0')
+		/*  This is the normal return point after you have processed
+		 *  all of the <name>=<value> pairs in a syntactically-valid
+		 *  parameter buffer.
+		 */
+		return NULL;
+
+	/* skip whitespace */
+	while (isspace(*pscan)) {
+		pscan++;
+		nscan--;
+		if (nscan == 0)
+			return NULL;
+	}
+
+	while (*pscan != ':') {
+		if (namesize <= 0) {
+			ERRDRV("%s - name too big", __func__);
+			return NULL;
+		}
+		*pnam = toupper(*pscan);
+		pnam++;
+		namesize--;
+		pscan++;
+		nscan--;
+		if (nscan == 0) {
+			ERRDRV("%s - unexpected end of input parsing name",
+			       __func__);
+			return NULL;
+		}
+	}
+	if (namesize <= 0) {
+		ERRDRV("%s - name too big", __func__);
+		return NULL;
+	}
+	*pnam = '\0';
+	nam[string_length_no_trail(nam, strlen(nam))] = '\0';
+
+	/* point to char immediately after ":" in "<name>:<value>" */
+	pscan++;
+	nscan--;
+	/* skip whitespace */
+	while (isspace(*pscan)) {
+		pscan++;
+		nscan--;
+		if (nscan == 0) {
+			ERRDRV("%s - unexpected end of input looking for value",
+			       __func__);
+			return NULL;
+		}
+	}
+	if (nscan == 0) {
+		ERRDRV("%s - unexpected end of input looking for value",
+		       __func__);
+		return NULL;
+	}
+	if (*pscan == '\'' || *pscan == '"') {
+		closing_quote = *pscan;
+		pscan++;
+		nscan--;
+		if (nscan == 0) {
+			ERRDRV("%s - unexpected end of input after %c",
+			       __func__, closing_quote);
+			return NULL;
+		}
+	}
+
+	/* look for a separator character, terminator character, or
+	 * end of data
+	 */
+	for (i = 0, value_length = -1; i < nscan; i++) {
+		if (closing_quote) {
+			if (pscan[i] == '\0') {
+				ERRDRV("%s - unexpected end of input parsing quoted value", __func__);
+				return NULL;
+			}
+			if (pscan[i] == closing_quote) {
+				value_length = i;
+				break;
+			}
+		} else
+		    if (pscan[i] == ',' || pscan[i] == ';'
+			|| pscan[i] == '\0') {
+			value_length = i;
+			break;
+		}
+	}
+	if (value_length < 0) {
+		if (closing_quote) {
+			ERRDRV("%s - unexpected end of input parsing quoted value", __func__);
+			return NULL;
+		}
+		value_length = nscan;
+	}
+	orig_value_length = value_length;
+	if (closing_quote == 0)
+		value_length = string_length_no_trail(pscan, orig_value_length);
+	value = kmalloc(value_length + 1, GFP_KERNEL|__GFP_NORETRY);
+	if (value == NULL)
+		return NULL;
+	memcpy(value, pscan, value_length);
+	((u8 *) (value))[value_length] = '\0';
+
+	pscan += orig_value_length;
+	nscan -= orig_value_length;
+
+	/* skip past separator or closing quote */
+	if (nscan > 0) {
+		if (*pscan != '\0') {
+			pscan++;
+			nscan--;
+		}
+	}
+
+	if (closing_quote && (nscan > 0)) {
+		/* we still need to skip around the real separator if present */
+		/* first, skip whitespace */
+		while (isspace(*pscan)) {
+			pscan++;
+			nscan--;
+			if (nscan == 0)
+				break;
+		}
+		if (nscan > 0) {
+			if (*pscan == ',' || *pscan == ';') {
+				pscan++;
+				nscan--;
+			} else if (*pscan != '\0') {
+				ERRDRV("%s - missing separator after quoted string", __func__);
+				kfree(value);
+				value = NULL;
+				return NULL;
+			}
+		}
+	}
+	ctx->curr = pscan;
+	ctx->bytes_remaining = nscan;
+	return value;
+}
+
+void *
+parser_string_get(PARSER_CONTEXT *ctx)
+{
+	u8 *pscan;
+	ulong nscan;
+	int value_length = -1;
+	void *value = NULL;
+	int i;
+
+	if (!ctx)
+		return NULL;
+	pscan = ctx->curr;
+	nscan = ctx->bytes_remaining;
+	if (nscan == 0)
+		return NULL;
+	if (!pscan)
+		return NULL;
+	for (i = 0, value_length = -1; i < nscan; i++)
+		if (pscan[i] == '\0') {
+			value_length = i;
+			break;
+		}
+	if (value_length < 0)	/* '\0' was not included in the length */
+		value_length = nscan;
+	value = kmalloc(value_length + 1, GFP_KERNEL|__GFP_NORETRY);
+	if (value == NULL)
+		return NULL;
+	if (value_length > 0)
+		memcpy(value, pscan, value_length);
+	((u8 *) (value))[value_length] = '\0';
+	return value;
+}
diff --git a/drivers/staging/unisys/visorchipset/parser.h b/drivers/staging/unisys/visorchipset/parser.h
new file mode 100644
index 0000000..a0cc50a
--- /dev/null
+++ b/drivers/staging/unisys/visorchipset/parser.h
@@ -0,0 +1,45 @@
+/* parser.h
+ *
+ * Copyright © 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+#ifndef __PARSER_H__
+#define __PARSER_H__
+
+#include "uniklog.h"
+#include "timskmod.h"
+#include "channel.h"
+
+typedef enum {
+	PARSERSTRING_INITIATOR,
+	PARSERSTRING_TARGET,
+	PARSERSTRING_CONNECTION,
+	PARSERSTRING_NAME,
+} PARSER_WHICH_STRING;
+
+typedef struct PARSER_CONTEXT_Tag PARSER_CONTEXT;
+
+PARSER_CONTEXT *parser_init(U64 addr, U32 bytes, BOOL isLocal, BOOL *tryAgain);
+PARSER_CONTEXT *parser_init_byteStream(U64 addr, U32 bytes, BOOL isLocal,
+				       BOOL *tryAgain);
+void parser_param_start(PARSER_CONTEXT *ctx, PARSER_WHICH_STRING which_string);
+void *parser_param_get(PARSER_CONTEXT *ctx, char *nam, int namesize);
+void *parser_string_get(PARSER_CONTEXT *ctx);
+GUID parser_id_get(PARSER_CONTEXT *ctx);
+char *parser_simpleString_get(PARSER_CONTEXT *ctx);
+void *parser_byteStream_get(PARSER_CONTEXT *ctx, ulong *nbytes);
+void parser_done(PARSER_CONTEXT *ctx);
+
+#endif
diff --git a/drivers/staging/unisys/visorchipset/testing.h b/drivers/staging/unisys/visorchipset/testing.h
new file mode 100644
index 0000000..a44f555
--- /dev/null
+++ b/drivers/staging/unisys/visorchipset/testing.h
@@ -0,0 +1,41 @@
+/* testing.h
+ *
+ * Copyright © 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+#ifndef __VISORCHIPSET_TESTING_H__
+#define __VISORCHIPSET_TESTING_H__
+
+#define VISORCHIPSET_TEST_PROC
+#include "globals.h"
+#include "controlvmchannel.h"
+
+void test_produce_test_message(CONTROLVM_MESSAGE *msg, int isLocalTestAddr);
+BOOL test_consume_test_message(CONTROLVM_MESSAGE *msg);
+void test_manufacture_vnic_client_add(void *p);
+void test_manufacture_vnic_client_add_phys(HOSTADDRESS addr);
+void test_manufacture_preamble_messages(void);
+void test_manufacture_device_attach(ulong busNo, ulong devNo);
+void test_manufacture_device_add(ulong busNo, ulong devNo, GUID dataTypeGuid,
+				 void *pChannel);
+void test_manufacture_add_bus(ulong busNo, ulong maxDevices,
+			      GUID id, u8 *name, BOOL isServer);
+void test_manufacture_device_destroy(ulong busNo, ulong devNo);
+void test_manufacture_bus_destroy(ulong busNo);
+void test_manufacture_detach_externalPort(ulong switchNo, ulong externalPortNo);
+void test_manufacture_detach_internalPort(ulong switchNo, ulong internalPortNo);
+void test_cleanup(void);
+
+#endif
diff --git a/drivers/staging/unisys/visorchipset/visorchipset.h b/drivers/staging/unisys/visorchipset/visorchipset.h
new file mode 100644
index 0000000..8e62a89
--- /dev/null
+++ b/drivers/staging/unisys/visorchipset/visorchipset.h
@@ -0,0 +1,307 @@
+/* visorchipset.h
+ *
+ * Copyright © 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+#ifndef __VISORCHIPSET_H__
+#define __VISORCHIPSET_H__
+
+#include "timskmod.h"
+#include "channel.h"
+#include "controlvmchannel.h"
+#include "parser.h"
+#include "procobjecttree.h"
+#include "vbusdeviceinfo.h"
+#include "vbushelper.h"
+
+/** Describes the state from the perspective of which controlvm messages have
+ *  been received for a bus or device.
+ */
+typedef struct {
+	U32 created:1;
+	U32 attached:1;
+	U32 configured:1;
+	U32 running:1;
+	/* Add new fields above. */
+	/* Remaining bits in this 32-bit word are unused. */
+} VISORCHIPSET_STATE;
+
+typedef enum {
+	/** address is guest physical, but outside of the physical memory
+	 *  region that is controlled by the running OS (this is the normal
+	 *  address type for Supervisor channels)
+	 */
+	ADDRTYPE_localPhysical,
+
+	/** address is guest physical, and withIN the confines of the
+	 *  physical memory controlled by the running OS.
+	 */
+	ADDRTYPE_localTest,
+} VISORCHIPSET_ADDRESSTYPE;
+
+typedef enum {
+	CRASH_dev,
+	CRASH_bus,
+} CRASH_OBJ_TYPE;
+
+/** Attributes for a particular Supervisor channel.
+ */
+typedef struct {
+	VISORCHIPSET_ADDRESSTYPE addrType;
+	HOSTADDRESS channelAddr;
+	struct InterruptInfo intr;
+	U64 nChannelBytes;
+	GUID channelTypeGuid;
+	GUID channelInstGuid;
+
+} VISORCHIPSET_CHANNEL_INFO;
+
+/** Attributes for a particular Supervisor device.
+ *  Any visorchipset client can query these attributes using
+ *  visorchipset_get_client_device_info() or
+ *  visorchipset_get_server_device_info().
+ */
+typedef struct {
+	struct list_head entry;
+	U32 busNo;
+	U32 devNo;
+	GUID devInstGuid;
+	VISORCHIPSET_STATE state;
+	VISORCHIPSET_CHANNEL_INFO chanInfo;
+	U32 Reserved1;		/* CONTROLVM_ID */
+	U64 Reserved2;
+	U32 switchNo;		/* when devState.attached==1 */
+	U32 internalPortNo;	/* when devState.attached==1 */
+	CONTROLVM_MESSAGE_HEADER pendingMsgHdr;	/* CONTROLVM_MESSAGE */
+	/** For private use by the bus driver */
+	void *bus_driver_context;
+
+} VISORCHIPSET_DEVICE_INFO;
+
+static inline VISORCHIPSET_DEVICE_INFO *
+finddevice(struct list_head *list, U32 busNo, U32 devNo)
+{
+	VISORCHIPSET_DEVICE_INFO *p;
+
+	list_for_each_entry(p, list, entry) {
+		if (p->busNo == busNo && p->devNo == devNo)
+			return p;
+	}
+	return NULL;
+}
+
+static inline void delbusdevices(struct list_head *list, U32 busNo)
+{
+	VISORCHIPSET_DEVICE_INFO *p;
+
+	list_for_each_entry(p, list, entry) {
+		if (p->busNo == busNo) {
+			list_del(&p->entry);
+			kfree(p);
+		}
+	}
+}
+
+/** Attributes for a particular Supervisor bus.
+ *  (For a service partition acting as the server for buses/devices, there
+ *  is a 1-to-1 relationship between busses and guest partitions.)
+ *  Any visorchipset client can query these attributes using
+ *  visorchipset_get_client_bus_info() or visorchipset_get_bus_info().
+ */
+typedef struct {
+	struct list_head entry;
+	U32 busNo;
+	VISORCHIPSET_STATE state;
+	VISORCHIPSET_CHANNEL_INFO chanInfo;
+	GUID partitionGuid;
+	U64 partitionHandle;
+	U8 *name;		/* UTF8 */
+	U8 *description;	/* UTF8 */
+	U64 Reserved1;
+	U32 Reserved2;
+	MYPROCOBJECT *procObject;
+	struct {
+		U32 server:1;
+		/* Add new fields above. */
+		/* Remaining bits in this 32-bit word are unused. */
+	} flags;
+	CONTROLVM_MESSAGE_HEADER pendingMsgHdr;	/* CONTROLVM MsgHdr */
+	/** For private use by the bus driver */
+	void *bus_driver_context;
+	U64 devNo;
+
+} VISORCHIPSET_BUS_INFO;
+
+static inline VISORCHIPSET_BUS_INFO *
+findbus(struct list_head *list, U32 busNo)
+{
+	VISORCHIPSET_BUS_INFO *p;
+
+	list_for_each_entry(p, list, entry) {
+		if (p->busNo == busNo)
+			return p;
+	}
+	return NULL;
+}
+
+/** Attributes for a particular Supervisor switch.
+ */
+typedef struct {
+	U32 switchNo;
+	VISORCHIPSET_STATE state;
+	GUID switchTypeGuid;
+	U8 *authService1;
+	U8 *authService2;
+	U8 *authService3;
+	U8 *securityContext;
+	U64 Reserved;
+	U32 Reserved2;		/* CONTROLVM_ID */
+	struct device dev;
+	BOOL dev_exists;
+	CONTROLVM_MESSAGE_HEADER pendingMsgHdr;
+
+} VISORCHIPSET_SWITCH_INFO;
+
+/** Attributes for a particular Supervisor external port, which is connected
+ *  to a specific switch.
+ */
+typedef struct {
+	U32 switchNo;
+	U32 externalPortNo;
+	VISORCHIPSET_STATE state;
+	GUID networkZoneGuid;
+	int pdPort;
+	U8 *ip;
+	U8 *ipNetmask;
+	U8 *ipBroadcast;
+	U8 *ipNetwork;
+	U8 *ipGateway;
+	U8 *ipDNS;
+	U64 Reserved1;
+	U32 Reserved2;		/* CONTROLVM_ID */
+	struct device dev;
+	BOOL dev_exists;
+	CONTROLVM_MESSAGE_HEADER pendingMsgHdr;
+
+} VISORCHIPSET_EXTERNALPORT_INFO;
+
+/** Attributes for a particular Supervisor internal port, which is how a
+ *  device connects to a particular switch.
+ */
+typedef struct {
+	U32 switchNo;
+	U32 internalPortNo;
+	VISORCHIPSET_STATE state;
+	U32 busNo;		/* valid only when state.attached == 1 */
+	U32 devNo;		/* valid only when state.attached == 1 */
+	U64 Reserved1;
+	U32 Reserved2;		/* CONTROLVM_ID */
+	CONTROLVM_MESSAGE_HEADER pendingMsgHdr;
+	MYPROCOBJECT *procObject;
+
+} VISORCHIPSET_INTERNALPORT_INFO;
+
+/*  These functions will be called from within visorchipset when certain
+ *  events happen.  (The implementation of these functions is outside of
+ *  visorchipset.)
+ */
+typedef struct {
+	void (*bus_create)(ulong busNo);
+	void (*bus_destroy)(ulong busNo);
+	void (*device_create)(ulong busNo, ulong devNo);
+	void (*device_destroy)(ulong busNo, ulong devNo);
+	void (*device_pause)(ulong busNo, ulong devNo);
+	void (*device_resume)(ulong busNo, ulong devNo);
+	int (*get_channel_info)(GUID typeGuid, ulong *minSize,
+				 ulong *maxSize);
+} VISORCHIPSET_BUSDEV_NOTIFIERS;
+
+/*  These functions live inside visorchipset, and will be called to indicate
+ *  responses to specific events (by code outside of visorchipset).
+ *  For now, the value for each response is simply either:
+ *       0 = it worked
+ *      -1 = it failed
+ */
+typedef struct {
+	void (*bus_create)(ulong busNo, int response);
+	void (*bus_destroy)(ulong busNo, int response);
+	void (*device_create)(ulong busNo, ulong devNo, int response);
+	void (*device_destroy)(ulong busNo, ulong devNo, int response);
+	void (*device_pause)(ulong busNo, ulong devNo, int response);
+	void (*device_resume)(ulong busNo, ulong devNo, int response);
+} VISORCHIPSET_BUSDEV_RESPONDERS;
+
+/** Register functions (in the bus driver) to get called by visorchipset
+ *  whenever a bus or device appears for which this service partition is
+ *  to be the server for.  visorchipset will fill in <responders>, to
+ *  indicate functions the bus driver should call to indicate message
+ *  responses.
+ */
+void
+visorchipset_register_busdev_client(VISORCHIPSET_BUSDEV_NOTIFIERS *notifiers,
+				    VISORCHIPSET_BUSDEV_RESPONDERS *responders,
+				    ULTRA_VBUS_DEVICEINFO *driverInfo);
+
+/** Register functions (in the bus driver) to get called by visorchipset
+ *  whenever a bus or device appears for which this service partition is
+ *  to be the client for.  visorchipset will fill in <responders>, to
+ *  indicate functions the bus driver should call to indicate message
+ *  responses.
+ */
+void
+visorchipset_register_busdev_server(VISORCHIPSET_BUSDEV_NOTIFIERS *notifiers,
+				    VISORCHIPSET_BUSDEV_RESPONDERS *responders,
+				    ULTRA_VBUS_DEVICEINFO *driverInfo);
+
+typedef void (*SPARREPORTEVENT_COMPLETE_FUNC) (CONTROLVM_MESSAGE *msg,
+					       int status);
+
+void device_pause_response(ulong busNo, ulong devNo, int response);
+
+BOOL visorchipset_get_bus_info(ulong busNo, VISORCHIPSET_BUS_INFO *busInfo);
+BOOL visorchipset_get_device_info(ulong busNo, ulong devNo,
+				  VISORCHIPSET_DEVICE_INFO *devInfo);
+BOOL visorchipset_get_switch_info(ulong switchNo,
+				  VISORCHIPSET_SWITCH_INFO *switchInfo);
+BOOL visorchipset_get_externalport_info(ulong switchNo, ulong externalPortNo,
+					VISORCHIPSET_EXTERNALPORT_INFO
+					*externalPortInfo);
+BOOL visorchipset_set_bus_context(ulong busNo, void *context);
+BOOL visorchipset_set_device_context(ulong busNo, ulong devNo, void *context);
+int visorchipset_chipset_ready(void);
+int visorchipset_chipset_selftest(void);
+int visorchipset_chipset_notready(void);
+void visorchipset_controlvm_respond_reportEvent(CONTROLVM_MESSAGE *msg,
+						void *payload);
+void visorchipset_save_message(CONTROLVM_MESSAGE *msg, CRASH_OBJ_TYPE type);
+void *visorchipset_cache_alloc(struct kmem_cache *pool,
+			       BOOL ok_to_block, char *fn, int ln);
+void visorchipset_cache_free(struct kmem_cache *pool, void *p,
+			     char *fn, int ln);
+
+#if defined(TRANSMITFILE_DEBUG) || defined(DEBUG)
+#define DBG_GETFILE_PAYLOAD(msg, controlvm_header)      \
+	LOGINF(msg,                                     \
+	       (ulong)controlvm_header.PayloadVmOffset, \
+	       (ulong)controlvm_header.PayloadMaxBytes)
+#define DBG_GETFILE(fmt, ...)  LOGINF(fmt, ##__VA_ARGS__)
+#define DBG_PUTFILE(fmt, ...)  LOGINF(fmt, ##__VA_ARGS__)
+#else
+#define DBG_GETFILE_PAYLOAD(msg, controlvm_header)
+#define DBG_GETFILE(fmt, ...)
+#define DBG_PUTFILE(fmt, ...)
+#endif
+
+#endif
diff --git a/drivers/staging/unisys/visorchipset/visorchipset_main.c b/drivers/staging/unisys/visorchipset/visorchipset_main.c
new file mode 100644
index 0000000..e0ec3a4
--- /dev/null
+++ b/drivers/staging/unisys/visorchipset/visorchipset_main.c
@@ -0,0 +1,2912 @@
+/* visorchipset_main.c
+ *
+ * Copyright � 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+#include "globals.h"
+#include "controlvm.h"
+#include "visorchipset.h"
+#include "procobjecttree.h"
+#include "visorchannel.h"
+#include "periodic_work.h"
+#include "testing.h"
+#include "file.h"
+#include "parser.h"
+#include "uniklog.h"
+#include "uisutils.h"
+#include "guidutils.h"
+#include "controlvmcompletionstatus.h"
+#include "guestlinuxdebug.h"
+#include "filexfer.h"
+
+#include <linux/nls.h>
+#include <linux/netdevice.h>
+#include <linux/platform_device.h>
+
+#define CURRENT_FILE_PC VISOR_CHIPSET_PC_visorchipset_main_c
+#define TEST_VNIC_PHYSITF "eth0"	/* physical network itf for
+					 * vnic loopback test */
+#define TEST_VNIC_SWITCHNO 1
+#define TEST_VNIC_BUSNO 9
+
+#define MAX_NAME_SIZE 128
+#define MAX_IP_SIZE   50
+#define MAXOUTSTANDINGCHANNELCOMMAND 256
+#define POLLJIFFIES_CONTROLVMCHANNEL_FAST   1
+#define POLLJIFFIES_CONTROLVMCHANNEL_SLOW 100
+
+/* When the controlvm channel is idle for at least MIN_IDLE_SECONDS,
+* we switch to slow polling mode.  As soon as we get a controlvm
+* message, we switch back to fast polling mode.
+*/
+#define MIN_IDLE_SECONDS 10
+ulong Poll_jiffies = POLLJIFFIES_CONTROLVMCHANNEL_FAST;
+ulong Most_recent_message_jiffies;	/* when we got our last
+					 * controlvm message */
+static inline char *
+NONULLSTR(char *s)
+{
+	if (s)
+		return s;
+	else
+		return "";
+}
+
+static int serverregistered;
+static int clientregistered;
+
+#define MAX_CHIPSET_EVENTS 2
+static U8 chipset_events[MAX_CHIPSET_EVENTS] = { 0, 0 };
+
+static struct delayed_work Periodic_controlvm_work;
+static struct workqueue_struct *Periodic_controlvm_workqueue;
+DEFINE_SEMAPHORE(NotifierLock);
+
+typedef struct {
+	CONTROLVM_MESSAGE message;
+	unsigned int crc;
+} MESSAGE_ENVELOPE;
+
+static CONTROLVM_MESSAGE_HEADER g_DiagMsgHdr;
+static CONTROLVM_MESSAGE_HEADER g_ChipSetMsgHdr;
+static CONTROLVM_MESSAGE_HEADER g_DelDumpMsgHdr;
+static const GUID UltraDiagPoolChannelProtocolGuid =
+	ULTRA_DIAG_POOL_CHANNEL_PROTOCOL_GUID;
+/* 0xffffff is an invalid Bus/Device number */
+static ulong g_diagpoolBusNo = 0xffffff;
+static ulong g_diagpoolDevNo = 0xffffff;
+static CONTROLVM_MESSAGE_PACKET g_DeviceChangeStatePacket;
+
+/* Only VNIC and VHBA channels are sent to visorclientbus (aka
+ * "visorhackbus")
+ */
+#define FOR_VISORHACKBUS(channel_type_guid) \
+	((memcmp(&channel_type_guid, &UltraVnicChannelProtocolGuid, \
+		 sizeof(GUID)) == 0) ||				    \
+	 (memcmp(&channel_type_guid, &UltraVhbaChannelProtocolGuid, \
+		 sizeof(GUID)) == 0))
+#define FOR_VISORBUS(channel_type_guid) (!(FOR_VISORHACKBUS(channel_type_guid)))
+
+#define is_diagpool_channel(channel_type_guid) \
+	 (memcmp(&channel_type_guid, \
+		 &UltraDiagPoolChannelProtocolGuid, sizeof(GUID)) == 0)
+
+typedef enum {
+	PARTPROP_invalid,
+	PARTPROP_name,
+	PARTPROP_description,
+	PARTPROP_handle,
+	PARTPROP_busNumber,
+	/* add new properties above, but don't forget to change
+	 * InitPartitionProperties() and show_partition_property() also...
+	 */
+	PARTPROP_last
+} PARTITION_property;
+static const char *PartitionTypeNames[] = { "partition", NULL };
+
+static char *PartitionPropertyNames[PARTPROP_last + 1];
+static void
+InitPartitionProperties(void)
+{
+	char **p = PartitionPropertyNames;
+	p[PARTPROP_invalid] = "";
+	p[PARTPROP_name] = "name";
+	p[PARTPROP_description] = "description";
+	p[PARTPROP_handle] = "handle";
+	p[PARTPROP_busNumber] = "busNumber";
+	p[PARTPROP_last] = NULL;
+}
+
+typedef enum {
+	CTLVMPROP_invalid,
+	CTLVMPROP_physAddr,
+	CTLVMPROP_controlChannelAddr,
+	CTLVMPROP_controlChannelBytes,
+	CTLVMPROP_sparBootPart,
+	CTLVMPROP_sparStoragePart,
+	CTLVMPROP_livedumpLength,
+	CTLVMPROP_livedumpCrc32,
+	/* add new properties above, but don't forget to change
+	 * InitControlVmProperties() show_controlvm_property() also...
+	 */
+	CTLVMPROP_last
+} CONTROLVM_property;
+
+static const char *ControlVmTypeNames[] = { "controlvm", NULL };
+
+static char *ControlVmPropertyNames[CTLVMPROP_last + 1];
+static void
+InitControlVmProperties(void)
+{
+	char **p = ControlVmPropertyNames;
+	p[CTLVMPROP_invalid] = "";
+	p[CTLVMPROP_physAddr] = "physAddr";
+	p[CTLVMPROP_controlChannelAddr] = "controlChannelAddr";
+	p[CTLVMPROP_controlChannelBytes] = "controlChannelBytes";
+	p[CTLVMPROP_sparBootPart] = "spar_boot_part";
+	p[CTLVMPROP_sparStoragePart] = "spar_storage_part";
+	p[CTLVMPROP_livedumpLength] = "livedumpLength";
+	p[CTLVMPROP_livedumpCrc32] = "livedumpCrc32";
+	p[CTLVMPROP_last] = NULL;
+}
+
+static MYPROCOBJECT *ControlVmObject;
+static MYPROCTYPE *PartitionType;
+static MYPROCTYPE *ControlVmType;
+
+#define VISORCHIPSET_DIAG_PROC_ENTRY_FN "diagdump"
+static struct proc_dir_entry *diag_proc_dir;
+
+#define VISORCHIPSET_CHIPSET_PROC_ENTRY_FN "chipsetready"
+static struct proc_dir_entry *chipset_proc_dir;
+
+#define VISORCHIPSET_PARAHOTPLUG_PROC_ENTRY_FN "parahotplug"
+static struct proc_dir_entry *parahotplug_proc_dir;
+
+static LIST_HEAD(BusInfoList);
+static LIST_HEAD(DevInfoList);
+
+static struct proc_dir_entry *ProcDir;
+static VISORCHANNEL *ControlVm_channel;
+
+static ssize_t visorchipset_proc_read_writeonly(struct file *file,
+						char __user *buf,
+						size_t len, loff_t *offset);
+static ssize_t proc_read_installer(struct file *file, char __user *buf,
+				   size_t len, loff_t *offset);
+static ssize_t proc_write_installer(struct file *file,
+				    const char __user *buffer,
+				    size_t count, loff_t *ppos);
+static ssize_t proc_read_toolaction(struct file *file, char __user *buf,
+				    size_t len, loff_t *offset);
+static ssize_t proc_write_toolaction(struct file *file,
+				     const char __user *buffer,
+				     size_t count, loff_t *ppos);
+static ssize_t proc_read_bootToTool(struct file *file, char __user *buf,
+				    size_t len, loff_t *offset);
+static ssize_t proc_write_bootToTool(struct file *file,
+				     const char __user *buffer,
+				     size_t count, loff_t *ppos);
+static const struct file_operations proc_installer_fops = {
+	.read = proc_read_installer,
+	.write = proc_write_installer,
+};
+
+static const struct file_operations proc_toolaction_fops = {
+	.read = proc_read_toolaction,
+	.write = proc_write_toolaction,
+};
+
+static const struct file_operations proc_bootToTool_fops = {
+	.read = proc_read_bootToTool,
+	.write = proc_write_bootToTool,
+};
+
+typedef struct {
+	U8 *ptr;		/* pointer to base address of payload pool */
+	U64 offset;		/* offset from beginning of controlvm
+				 * channel to beginning of payload * pool */
+	U32 bytes;		/* number of bytes in payload pool */
+} CONTROLVM_PAYLOAD_INFO;
+
+/* Manages the request payload in the controlvm channel */
+static CONTROLVM_PAYLOAD_INFO ControlVm_payload_info;
+
+static pCHANNEL_HEADER Test_Vnic_channel;
+
+typedef struct {
+	CONTROLVM_MESSAGE_HEADER Dumpcapture_header;
+	CONTROLVM_MESSAGE_HEADER Gettextdump_header;
+	CONTROLVM_MESSAGE_HEADER Dumpcomplete_header;
+	BOOL Gettextdump_outstanding;
+	u32 crc32;
+	ulong length;
+	atomic_t buffers_in_use;
+	ulong destination;
+} LIVEDUMP_INFO;
+/* Manages the info for a CONTROLVM_DUMP_CAPTURESTATE /
+ * CONTROLVM_DUMP_GETTEXTDUMP / CONTROLVM_DUMP_COMPLETE conversation.
+ */
+static LIVEDUMP_INFO LiveDump_info;
+
+/* The following globals are used to handle the scenario where we are unable to
+ * offload the payload from a controlvm message due to memory requirements.  In
+ * this scenario, we simply stash the controlvm message, then attempt to
+ * process it again the next time controlvm_periodic_work() runs.
+ */
+static CONTROLVM_MESSAGE ControlVm_Pending_Msg;
+static BOOL ControlVm_Pending_Msg_Valid = FALSE;
+
+/* Pool of struct putfile_buffer_entry, for keeping track of pending (incoming)
+ * TRANSMIT_FILE PutFile payloads.
+ */
+static struct kmem_cache *Putfile_buffer_list_pool;
+static const char Putfile_buffer_list_pool_name[] =
+	"controlvm_putfile_buffer_list_pool";
+
+/* This identifies a data buffer that has been received via a controlvm messages
+ * in a remote --> local CONTROLVM_TRANSMIT_FILE conversation.
+ */
+struct putfile_buffer_entry {
+	struct list_head next;	/* putfile_buffer_entry list */
+	PARSER_CONTEXT *parser_ctx; /* points to buffer containing input data */
+};
+
+/* List of struct putfile_request *, via next_putfile_request member.
+ * Each entry in this list identifies an outstanding TRANSMIT_FILE
+ * conversation.
+ */
+static LIST_HEAD(Putfile_request_list);
+
+/* This describes a buffer and its current state of transfer (e.g., how many
+ * bytes have already been supplied as putfile data, and how many bytes are
+ * remaining) for a putfile_request.
+ */
+struct putfile_active_buffer {
+	/* a payload from a controlvm message, containing a file data buffer */
+	PARSER_CONTEXT *parser_ctx;
+	/* points within data area of parser_ctx to next byte of data */
+	u8 *pnext;
+	/* # bytes left from <pnext> to the end of this data buffer */
+	size_t bytes_remaining;
+};
+
+#define PUTFILE_REQUEST_SIG 0x0906101302281211
+/* This identifies a single remote --> local CONTROLVM_TRANSMIT_FILE
+ * conversation.  Structs of this type are dynamically linked into
+ * <Putfile_request_list>.
+ */
+struct putfile_request {
+	u64 sig;		/* PUTFILE_REQUEST_SIG */
+
+	/* header from original TransmitFile request */
+	CONTROLVM_MESSAGE_HEADER controlvm_header;
+	u64 file_request_number;	/* from original TransmitFile request */
+
+	/* link to next struct putfile_request */
+	struct list_head next_putfile_request;
+
+	/* most-recent sequence number supplied via a controlvm message */
+	u64 data_sequence_number;
+
+	/* head of putfile_buffer_entry list, which describes the data to be
+	 * supplied as putfile data;
+	 * - this list is added to when controlvm messages come in that supply
+	 * file data
+	 * - this list is removed from via the hotplug program that is actually
+	 * consuming these buffers to write as file data */
+	struct list_head input_buffer_list;
+	spinlock_t req_list_lock;	/* lock for input_buffer_list */
+
+	/* waiters for input_buffer_list to go non-empty */
+	wait_queue_head_t input_buffer_wq;
+
+	/* data not yet read within current putfile_buffer_entry */
+	struct putfile_active_buffer active_buf;
+
+	/* <0 = failed, 0 = in-progress, >0 = successful; */
+	/* note that this must be set with req_list_lock, and if you set <0, */
+	/* it is your responsibility to also free up all of the other objects */
+	/* in this struct (like input_buffer_list, active_buf.parser_ctx) */
+	/* before releasing the lock */
+	int completion_status;
+};
+
+atomic_t Visorchipset_cache_buffers_in_use = ATOMIC_INIT(0);
+
+struct parahotplug_request {
+	struct list_head list;
+	int id;
+	unsigned long expiration;
+	CONTROLVM_MESSAGE msg;
+};
+
+static LIST_HEAD(Parahotplug_request_list);
+static DEFINE_SPINLOCK(Parahotplug_request_list_lock);	/* lock for above */
+static void parahotplug_process_list(void);
+
+/* Manages the info for a CONTROLVM_DUMP_CAPTURESTATE /
+ * CONTROLVM_REPORTEVENT.
+ */
+static VISORCHIPSET_BUSDEV_NOTIFIERS BusDev_Server_Notifiers;
+static VISORCHIPSET_BUSDEV_NOTIFIERS BusDev_Client_Notifiers;
+
+static void bus_create_response(ulong busNo, int response);
+static void bus_destroy_response(ulong busNo, int response);
+static void device_create_response(ulong busNo, ulong devNo, int response);
+static void device_destroy_response(ulong busNo, ulong devNo, int response);
+static void device_resume_response(ulong busNo, ulong devNo, int response);
+
+static VISORCHIPSET_BUSDEV_RESPONDERS BusDev_Responders = {
+	.bus_create = bus_create_response,
+	.bus_destroy = bus_destroy_response,
+	.device_create = device_create_response,
+	.device_destroy = device_destroy_response,
+	.device_pause = device_pause_response,
+	.device_resume = device_resume_response,
+};
+
+/* info for /dev/visorchipset */
+static dev_t MajorDev = -1; /**< indicates major num for device */
+
+/* /sys/devices/platform/visorchipset */
+static struct platform_device Visorchipset_platform_device = {
+	.name = "visorchipset",
+	.id = -1,
+};
+
+/* Function prototypes */
+static void controlvm_respond(CONTROLVM_MESSAGE_HEADER *msgHdr, int response);
+static void controlvm_respond_chipset_init(CONTROLVM_MESSAGE_HEADER *msgHdr,
+					   int response,
+					   ULTRA_CHIPSET_FEATURE features);
+static void controlvm_respond_physdev_changestate(CONTROLVM_MESSAGE_HEADER *
+						  msgHdr, int response,
+						  ULTRA_SEGMENT_STATE state);
+
+static void
+show_partition_property(struct seq_file *f, void *ctx, int property)
+{
+	VISORCHIPSET_BUS_INFO *info = (VISORCHIPSET_BUS_INFO *) (ctx);
+
+	switch (property) {
+	case PARTPROP_name:
+		seq_printf(f, "%s\n", NONULLSTR(info->name));
+		break;
+	case PARTPROP_description:
+		seq_printf(f, "%s\n", NONULLSTR(info->description));
+		break;
+	case PARTPROP_handle:
+		seq_printf(f, "0x%-16.16Lx\n", info->partitionHandle);
+		break;
+	case PARTPROP_busNumber:
+		seq_printf(f, "%d\n", info->busNo);
+		break;
+	default:
+		seq_printf(f, "(%d??)\n", property);
+		break;
+	}
+}
+
+static void
+show_controlvm_property(struct seq_file *f, void *ctx, int property)
+{
+	/* Note: ctx is not needed since we only have 1 controlvm channel */
+	switch (property) {
+	case CTLVMPROP_physAddr:
+		if (ControlVm_channel == NULL)
+			seq_puts(f, "0x0\n");
+		else
+			seq_printf(f, "0x%-16.16Lx\n",
+				   visorchannel_get_physaddr
+				   (ControlVm_channel));
+		break;
+	case CTLVMPROP_controlChannelAddr:
+		if (ControlVm_channel == NULL)
+			seq_puts(f, "0x0\n");
+		else {
+			GUEST_PHYSICAL_ADDRESS addr = 0;
+			visorchannel_read(ControlVm_channel,
+					  offsetof
+					  (ULTRA_CONTROLVM_CHANNEL_PROTOCOL,
+					   gpControlChannel), &addr,
+					  sizeof(addr));
+			seq_printf(f, "0x%-16.16Lx\n", (u64) (addr));
+		}
+		break;
+	case CTLVMPROP_controlChannelBytes:
+		if (ControlVm_channel == NULL)
+			seq_puts(f, "0x0\n");
+		else {
+			U32 bytes = 0;
+			visorchannel_read(ControlVm_channel,
+					  offsetof
+					  (ULTRA_CONTROLVM_CHANNEL_PROTOCOL,
+					   ControlChannelBytes), &bytes,
+					  sizeof(bytes));
+			seq_printf(f, "%lu\n", (ulong) (bytes));
+		}
+		break;
+	case CTLVMPROP_sparBootPart:
+		seq_puts(f, "0:0:0:0/1\n");
+		break;
+	case CTLVMPROP_sparStoragePart:
+		seq_puts(f, "0:0:0:0/2\n");
+		break;
+	case CTLVMPROP_livedumpLength:
+		seq_printf(f, "%lu\n", LiveDump_info.length);
+		break;
+	case CTLVMPROP_livedumpCrc32:
+		seq_printf(f, "%lu\n", (ulong) LiveDump_info.crc32);
+		break;
+	default:
+		seq_printf(f, "(%d??)\n", property);
+		break;
+	}
+}
+
+static void
+proc_Init(void)
+{
+	if (ProcDir == NULL) {
+		ProcDir = proc_mkdir(MYDRVNAME, NULL);
+		if (ProcDir == NULL) {
+			LOGERR("failed to create /proc directory %s",
+			       MYDRVNAME);
+			POSTCODE_LINUX_2(CHIPSET_INIT_FAILURE_PC,
+					 POSTCODE_SEVERITY_ERR);
+		}
+	}
+}
+
+static void
+proc_DeInit(void)
+{
+	if (ProcDir != NULL)
+		remove_proc_entry(MYDRVNAME, NULL);
+	ProcDir = NULL;
+}
+
+#if 0
+static void
+testUnicode(void)
+{
+	wchar_t unicodeString[] = { 'a', 'b', 'c', 0 };
+	char s[sizeof(unicodeString) * NLS_MAX_CHARSET_SIZE];
+	wchar_t unicode2[99];
+
+	/* NOTE: Either due to a bug, or feature I don't understand, the
+	 *       kernel utf8_mbstowcs() and utf_wcstombs() do NOT copy the
+	 *       trailed NUL byte!!   REALLY!!!!!    Arrrrgggghhhhh
+	 */
+
+	LOGINF("sizeof(wchar_t) = %d", sizeof(wchar_t));
+	LOGINF("utf8_wcstombs=%d",
+	       chrs = utf8_wcstombs(s, unicodeString, sizeof(s)));
+	if (chrs >= 0)
+		s[chrs] = '\0';	/* GRRRRRRRR */
+	LOGINF("s='%s'", s);
+	LOGINF("utf8_mbstowcs=%d", chrs = utf8_mbstowcs(unicode2, s, 100));
+	if (chrs >= 0)
+		unicode2[chrs] = 0;	/* GRRRRRRRR */
+	if (memcmp(unicodeString, unicode2, sizeof(unicodeString)) == 0)
+		LOGINF("strings match... good");
+	else
+		LOGINF("strings did not match!!");
+}
+#endif
+
+static void
+busInfo_clear(void *v)
+{
+	VISORCHIPSET_BUS_INFO *p = (VISORCHIPSET_BUS_INFO *) (v);
+
+	if (p->procObject) {
+		proc_DestroyObject(p->procObject);
+		p->procObject = NULL;
+	}
+	kfree(p->name);
+	p->name = NULL;
+
+	kfree(p->description);
+	p->description = NULL;
+
+	p->state.created = 0;
+	memset(p, 0, sizeof(VISORCHIPSET_BUS_INFO));
+}
+
+static void
+devInfo_clear(void *v)
+{
+	VISORCHIPSET_DEVICE_INFO *p = (VISORCHIPSET_DEVICE_INFO *) (v);
+	p->state.created = 0;
+	memset(p, 0, sizeof(VISORCHIPSET_DEVICE_INFO));
+}
+
+static U8
+check_chipset_events(void)
+{
+	int i;
+	U8 send_msg = 1;
+	/* Check events to determine if response should be sent */
+	for (i = 0; i < MAX_CHIPSET_EVENTS; i++)
+		send_msg &= chipset_events[i];
+	return send_msg;
+}
+
+static void
+clear_chipset_events(void)
+{
+	int i;
+	/* Clear chipset_events */
+	for (i = 0; i < MAX_CHIPSET_EVENTS; i++)
+		chipset_events[i] = 0;
+}
+
+void
+visorchipset_register_busdev_server(VISORCHIPSET_BUSDEV_NOTIFIERS *notifiers,
+				    VISORCHIPSET_BUSDEV_RESPONDERS *responders,
+				    ULTRA_VBUS_DEVICEINFO *driverInfo)
+{
+	LOCKSEM_UNINTERRUPTIBLE(&NotifierLock);
+	if (notifiers == NULL) {
+		memset(&BusDev_Server_Notifiers, 0,
+		       sizeof(BusDev_Server_Notifiers));
+		serverregistered = 0;	/* clear flag */
+	} else {
+		BusDev_Server_Notifiers = *notifiers;
+		serverregistered = 1;	/* set flag */
+	}
+	if (responders)
+		*responders = BusDev_Responders;
+	if (driverInfo)
+		BusDeviceInfo_Init(driverInfo, "chipset", "visorchipset",
+				   VERSION, NULL, __DATE__, __TIME__);
+
+	UNLOCKSEM(&NotifierLock);
+}
+EXPORT_SYMBOL_GPL(visorchipset_register_busdev_server);
+
+void
+visorchipset_register_busdev_client(VISORCHIPSET_BUSDEV_NOTIFIERS *notifiers,
+				    VISORCHIPSET_BUSDEV_RESPONDERS *responders,
+				    ULTRA_VBUS_DEVICEINFO *driverInfo)
+{
+	LOCKSEM_UNINTERRUPTIBLE(&NotifierLock);
+	if (notifiers == NULL) {
+		memset(&BusDev_Client_Notifiers, 0,
+		       sizeof(BusDev_Client_Notifiers));
+		clientregistered = 0;	/* clear flag */
+	} else {
+		BusDev_Client_Notifiers = *notifiers;
+		clientregistered = 1;	/* set flag */
+	}
+	if (responders)
+		*responders = BusDev_Responders;
+	if (driverInfo)
+		BusDeviceInfo_Init(driverInfo, "chipset(bolts)", "visorchipset",
+				   VERSION, NULL, __DATE__, __TIME__);
+	UNLOCKSEM(&NotifierLock);
+}
+EXPORT_SYMBOL_GPL(visorchipset_register_busdev_client);
+
+static void
+cleanup_controlvm_structures(void)
+{
+	VISORCHIPSET_BUS_INFO *bi;
+	VISORCHIPSET_DEVICE_INFO *di;
+
+	list_for_each_entry(bi, &BusInfoList, entry) {
+		busInfo_clear(bi);
+		list_del(&bi->entry);
+		kfree(bi);
+	}
+
+	list_for_each_entry(di, &DevInfoList, entry) {
+		devInfo_clear(di);
+		list_del(&di->entry);
+		kfree(di);
+	}
+}
+
+static void
+chipset_init(CONTROLVM_MESSAGE *inmsg)
+{
+	static int chipset_inited;
+	ULTRA_CHIPSET_FEATURE features = 0;
+	int rc = CONTROLVM_RESP_SUCCESS;
+
+	POSTCODE_LINUX_2(CHIPSET_INIT_ENTRY_PC, POSTCODE_SEVERITY_INFO);
+	if (chipset_inited) {
+		LOGERR("CONTROLVM_CHIPSET_INIT Failed: Already Done.");
+		RETINT(-CONTROLVM_RESP_ERROR_ALREADY_DONE);
+	}
+	chipset_inited = 1;
+	POSTCODE_LINUX_2(CHIPSET_INIT_EXIT_PC, POSTCODE_SEVERITY_INFO);
+
+	/* Set features to indicate we support parahotplug (if Command
+	 * also supports it). */
+	features =
+	    inmsg->cmd.initChipset.
+	    features & ULTRA_CHIPSET_FEATURE_PARA_HOTPLUG;
+
+	/* Set the "reply" bit so Command knows this is a
+	 * features-aware driver. */
+	features |= ULTRA_CHIPSET_FEATURE_REPLY;
+
+Away:
+	if (rc < 0)
+		cleanup_controlvm_structures();
+	if (inmsg->hdr.Flags.responseExpected)
+		controlvm_respond_chipset_init(&inmsg->hdr, rc, features);
+}
+
+static void
+controlvm_init_response(CONTROLVM_MESSAGE *msg,
+			CONTROLVM_MESSAGE_HEADER *msgHdr, int response)
+{
+	memset(msg, 0, sizeof(CONTROLVM_MESSAGE));
+	memcpy(&msg->hdr, msgHdr, sizeof(CONTROLVM_MESSAGE_HEADER));
+	msg->hdr.PayloadBytes = 0;
+	msg->hdr.PayloadVmOffset = 0;
+	msg->hdr.PayloadMaxBytes = 0;
+	if (response < 0) {
+		msg->hdr.Flags.failed = 1;
+		msg->hdr.CompletionStatus = (U32) (-response);
+	}
+}
+
+static void
+controlvm_respond(CONTROLVM_MESSAGE_HEADER *msgHdr, int response)
+{
+	CONTROLVM_MESSAGE outmsg;
+	if (!ControlVm_channel)
+		return;
+	controlvm_init_response(&outmsg, msgHdr, response);
+	/* For DiagPool channel DEVICE_CHANGESTATE, we need to send
+	* back the deviceChangeState structure in the packet. */
+	if (msgHdr->Id == CONTROLVM_DEVICE_CHANGESTATE
+	    && g_DeviceChangeStatePacket.deviceChangeState.busNo ==
+	    g_diagpoolBusNo
+	    && g_DeviceChangeStatePacket.deviceChangeState.devNo ==
+	    g_diagpoolDevNo)
+		outmsg.cmd = g_DeviceChangeStatePacket;
+	if (outmsg.hdr.Flags.testMessage == 1) {
+		LOGINF("%s controlvm_msg=0x%x response=%d for test message",
+		       __func__, outmsg.hdr.Id, response);
+		return;
+	}
+	if (!visorchannel_signalinsert(ControlVm_channel,
+				       CONTROLVM_QUEUE_REQUEST, &outmsg)) {
+		LOGERR("signalinsert failed!");
+		return;
+	}
+}
+
+static void
+controlvm_respond_chipset_init(CONTROLVM_MESSAGE_HEADER *msgHdr, int response,
+			       ULTRA_CHIPSET_FEATURE features)
+{
+	CONTROLVM_MESSAGE outmsg;
+	if (!ControlVm_channel)
+		return;
+	controlvm_init_response(&outmsg, msgHdr, response);
+	outmsg.cmd.initChipset.features = features;
+	if (!visorchannel_signalinsert(ControlVm_channel,
+				       CONTROLVM_QUEUE_REQUEST, &outmsg)) {
+		LOGERR("signalinsert failed!");
+		return;
+	}
+}
+
+static void
+controlvm_respond_physdev_changestate(CONTROLVM_MESSAGE_HEADER *msgHdr,
+				      int response, ULTRA_SEGMENT_STATE state)
+{
+	CONTROLVM_MESSAGE outmsg;
+	if (!ControlVm_channel)
+		return;
+	controlvm_init_response(&outmsg, msgHdr, response);
+	outmsg.cmd.deviceChangeState.state = state;
+	outmsg.cmd.deviceChangeState.flags.physicalDevice = 1;
+	if (!visorchannel_signalinsert(ControlVm_channel,
+				       CONTROLVM_QUEUE_REQUEST, &outmsg)) {
+		LOGERR("signalinsert failed!");
+		return;
+	}
+}
+
+void
+visorchipset_save_message(CONTROLVM_MESSAGE *msg, CRASH_OBJ_TYPE type)
+{
+	U32 localSavedCrashMsgOffset;
+	U16 localSavedCrashMsgCount;
+
+	/* get saved message count */
+	if (visorchannel_read(ControlVm_channel,
+			      offsetof(ULTRA_CONTROLVM_CHANNEL_PROTOCOL,
+				       SavedCrashMsgCount),
+			      &localSavedCrashMsgCount, sizeof(U16)) < 0) {
+		LOGERR("failed to get Saved Message Count");
+		POSTCODE_LINUX_2(CRASH_DEV_CTRL_RD_FAILURE_PC,
+				 POSTCODE_SEVERITY_ERR);
+		return;
+	}
+
+	if (localSavedCrashMsgCount != CONTROLVM_CRASHMSG_MAX) {
+		LOGERR("Saved Message Count incorrect %d",
+		       localSavedCrashMsgCount);
+		POSTCODE_LINUX_3(CRASH_DEV_COUNT_FAILURE_PC,
+				 localSavedCrashMsgCount,
+				 POSTCODE_SEVERITY_ERR);
+		return;
+	}
+
+	/* get saved crash message offset */
+	if (visorchannel_read(ControlVm_channel,
+			      offsetof(ULTRA_CONTROLVM_CHANNEL_PROTOCOL,
+				       SavedCrashMsgOffset),
+			      &localSavedCrashMsgOffset, sizeof(U32)) < 0) {
+		LOGERR("failed to get Saved Message Offset");
+		POSTCODE_LINUX_2(CRASH_DEV_CTRL_RD_FAILURE_PC,
+				 POSTCODE_SEVERITY_ERR);
+		return;
+	}
+
+	if (type == CRASH_bus) {
+		if (visorchannel_write(ControlVm_channel,
+				       localSavedCrashMsgOffset,
+				       msg, sizeof(CONTROLVM_MESSAGE)) < 0) {
+			LOGERR("SAVE_MSG_BUS_FAILURE: Failed to write CrashCreateBusMsg!");
+			POSTCODE_LINUX_2(SAVE_MSG_BUS_FAILURE_PC,
+					 POSTCODE_SEVERITY_ERR);
+			return;
+		}
+	} else {
+		if (visorchannel_write(ControlVm_channel,
+				       localSavedCrashMsgOffset +
+				       sizeof(CONTROLVM_MESSAGE), msg,
+				       sizeof(CONTROLVM_MESSAGE)) < 0) {
+			LOGERR("SAVE_MSG_DEV_FAILURE: Failed to write CrashCreateDevMsg!");
+			POSTCODE_LINUX_2(SAVE_MSG_DEV_FAILURE_PC,
+					 POSTCODE_SEVERITY_ERR);
+			return;
+		}
+	}
+}
+EXPORT_SYMBOL_GPL(visorchipset_save_message);
+
+static void
+bus_responder(CONTROLVM_ID cmdId, ulong busNo, int response)
+{
+	VISORCHIPSET_BUS_INFO *p = NULL;
+	BOOL need_clear = FALSE;
+
+	p = findbus(&BusInfoList, busNo);
+	if (!p) {
+		LOGERR("internal error busNo=%lu", busNo);
+		return;
+	}
+	if (response < 0) {
+		if ((cmdId == CONTROLVM_BUS_CREATE) &&
+		    (response != (-CONTROLVM_RESP_ERROR_ALREADY_DONE)))
+			/* undo the row we just created... */
+			delbusdevices(&DevInfoList, busNo);
+	} else {
+		if (cmdId == CONTROLVM_BUS_CREATE)
+			p->state.created = 1;
+		if (cmdId == CONTROLVM_BUS_DESTROY)
+			need_clear = TRUE;
+	}
+
+	if (p->pendingMsgHdr.Id == CONTROLVM_INVALID) {
+		LOGERR("bus_responder no pending msg");
+		return;		/* no controlvm response needed */
+	}
+	if (p->pendingMsgHdr.Id != (U32) cmdId) {
+		LOGERR("expected=%d, found=%d", cmdId, p->pendingMsgHdr.Id);
+		return;
+	}
+	controlvm_respond(&p->pendingMsgHdr, response);
+	p->pendingMsgHdr.Id = CONTROLVM_INVALID;
+	if (need_clear) {
+		busInfo_clear(p);
+		delbusdevices(&DevInfoList, busNo);
+	}
+}
+
+static void
+device_changestate_responder(CONTROLVM_ID cmdId,
+			     ulong busNo, ulong devNo, int response,
+			     ULTRA_SEGMENT_STATE responseState)
+{
+	VISORCHIPSET_DEVICE_INFO *p = NULL;
+	CONTROLVM_MESSAGE outmsg;
+
+	if (!ControlVm_channel)
+		return;
+
+	p = finddevice(&DevInfoList, busNo, devNo);
+	if (!p) {
+		LOGERR("internal error; busNo=%lu, devNo=%lu", busNo, devNo);
+		return;
+	}
+	if (p->pendingMsgHdr.Id == CONTROLVM_INVALID) {
+		LOGERR("device_responder no pending msg");
+		return;		/* no controlvm response needed */
+	}
+	if (p->pendingMsgHdr.Id != cmdId) {
+		LOGERR("expected=%d, found=%d", cmdId, p->pendingMsgHdr.Id);
+		return;
+	}
+
+	controlvm_init_response(&outmsg, &p->pendingMsgHdr, response);
+
+	outmsg.cmd.deviceChangeState.busNo = busNo;
+	outmsg.cmd.deviceChangeState.devNo = devNo;
+	outmsg.cmd.deviceChangeState.state = responseState;
+
+	if (!visorchannel_signalinsert(ControlVm_channel,
+				       CONTROLVM_QUEUE_REQUEST, &outmsg)) {
+		LOGERR("signalinsert failed!");
+		return;
+	}
+
+	p->pendingMsgHdr.Id = CONTROLVM_INVALID;
+}
+
+static void
+device_responder(CONTROLVM_ID cmdId, ulong busNo, ulong devNo, int response)
+{
+	VISORCHIPSET_DEVICE_INFO *p = NULL;
+	BOOL need_clear = FALSE;
+
+	p = finddevice(&DevInfoList, busNo, devNo);
+	if (!p) {
+		LOGERR("internal error; busNo=%lu, devNo=%lu", busNo, devNo);
+		return;
+	}
+	if (response >= 0) {
+		if (cmdId == CONTROLVM_DEVICE_CREATE)
+			p->state.created = 1;
+		if (cmdId == CONTROLVM_DEVICE_DESTROY)
+			need_clear = TRUE;
+	}
+
+	if (p->pendingMsgHdr.Id == CONTROLVM_INVALID) {
+		LOGERR("device_responder no pending msg");
+		return;		/* no controlvm response needed */
+	}
+	if (p->pendingMsgHdr.Id != (U32) cmdId) {
+		LOGERR("expected=%d, found=%d", cmdId, p->pendingMsgHdr.Id);
+		return;
+	}
+	controlvm_respond(&p->pendingMsgHdr, response);
+	p->pendingMsgHdr.Id = CONTROLVM_INVALID;
+	if (need_clear)
+		devInfo_clear(p);
+}
+
+static void
+bus_epilog(U32 busNo,
+	   U32 cmd, CONTROLVM_MESSAGE_HEADER *msgHdr,
+	   int response, BOOL needResponse)
+{
+	BOOL notified = FALSE;
+
+	VISORCHIPSET_BUS_INFO *pBusInfo = findbus(&BusInfoList, busNo);
+
+	if (!pBusInfo) {
+		LOGERR("HUH? bad busNo=%d", busNo);
+		return;
+	}
+	if (needResponse) {
+		memcpy(&pBusInfo->pendingMsgHdr, msgHdr,
+		       sizeof(CONTROLVM_MESSAGE_HEADER));
+	} else
+		pBusInfo->pendingMsgHdr.Id = CONTROLVM_INVALID;
+
+	LOCKSEM_UNINTERRUPTIBLE(&NotifierLock);
+	if (response == CONTROLVM_RESP_SUCCESS) {
+		switch (cmd) {
+		case CONTROLVM_BUS_CREATE:
+			/* We can't tell from the bus_create
+			* information which of our 2 bus flavors the
+			* devices on this bus will ultimately end up.
+			* FORTUNATELY, it turns out it is harmless to
+			* send the bus_create to both of them.  We can
+			* narrow things down a little bit, though,
+			* because we know: - BusDev_Server can handle
+			* either server or client devices
+			* - BusDev_Client can handle ONLY client
+			* devices */
+			if (BusDev_Server_Notifiers.bus_create) {
+				(*BusDev_Server_Notifiers.bus_create) (busNo);
+				notified = TRUE;
+			}
+			if ((!pBusInfo->flags.server) /*client */ &&
+			    BusDev_Client_Notifiers.bus_create) {
+				(*BusDev_Client_Notifiers.bus_create) (busNo);
+				notified = TRUE;
+			}
+			break;
+		case CONTROLVM_BUS_DESTROY:
+			if (BusDev_Server_Notifiers.bus_destroy) {
+				(*BusDev_Server_Notifiers.bus_destroy) (busNo);
+				notified = TRUE;
+			}
+			if ((!pBusInfo->flags.server) /*client */ &&
+			    BusDev_Client_Notifiers.bus_destroy) {
+				(*BusDev_Client_Notifiers.bus_destroy) (busNo);
+				notified = TRUE;
+			}
+			break;
+		}
+	}
+	if (notified)
+		/* The callback function just called above is responsible
+		 * for calling the appropriate VISORCHIPSET_BUSDEV_RESPONDERS
+		 * function, which will call bus_responder()
+		 */
+		;
+	else
+		bus_responder(cmd, busNo, response);
+	UNLOCKSEM(&NotifierLock);
+}
+
+static void
+device_epilog(U32 busNo, U32 devNo, ULTRA_SEGMENT_STATE state, U32 cmd,
+	      CONTROLVM_MESSAGE_HEADER *msgHdr, int response,
+	      BOOL needResponse, BOOL for_visorbus)
+{
+	VISORCHIPSET_BUSDEV_NOTIFIERS *notifiers = NULL;
+	BOOL notified = FALSE;
+
+	VISORCHIPSET_DEVICE_INFO *pDevInfo =
+		finddevice(&DevInfoList, busNo, devNo);
+	char *envp[] = {
+		"SPARSP_DIAGPOOL_PAUSED_STATE = 1",
+		NULL
+	};
+
+	if (!pDevInfo) {
+		LOGERR("HUH? bad busNo=%d, devNo=%d", busNo, devNo);
+		return;
+	}
+	if (for_visorbus)
+		notifiers = &BusDev_Server_Notifiers;
+	else
+		notifiers = &BusDev_Client_Notifiers;
+	if (needResponse) {
+		memcpy(&pDevInfo->pendingMsgHdr, msgHdr,
+		       sizeof(CONTROLVM_MESSAGE_HEADER));
+	} else
+		pDevInfo->pendingMsgHdr.Id = CONTROLVM_INVALID;
+
+	LOCKSEM_UNINTERRUPTIBLE(&NotifierLock);
+	if (response >= 0) {
+		switch (cmd) {
+		case CONTROLVM_DEVICE_CREATE:
+			if (notifiers->device_create) {
+				(*notifiers->device_create) (busNo, devNo);
+				notified = TRUE;
+			}
+			break;
+		case CONTROLVM_DEVICE_CHANGESTATE:
+			/* ServerReady / ServerRunning / SegmentStateRunning */
+			if (state.Alive == SegmentStateRunning.Alive &&
+			    state.Operating == SegmentStateRunning.Operating) {
+				if (notifiers->device_resume) {
+					(*notifiers->device_resume) (busNo,
+								     devNo);
+					notified = TRUE;
+				}
+			}
+			/* ServerNotReady / ServerLost / SegmentStateStandby */
+			else if (state.Alive == SegmentStateStandby.Alive &&
+				 state.Operating ==
+				 SegmentStateStandby.Operating) {
+				/* technically this is standby case
+				 * where server is lost
+				 */
+				if (notifiers->device_pause) {
+					(*notifiers->device_pause) (busNo,
+								    devNo);
+					notified = TRUE;
+				}
+			} else if (state.Alive == SegmentStatePaused.Alive &&
+				   state.Operating ==
+				   SegmentStatePaused.Operating) {
+				/* this is lite pause where channel is
+				 * still valid just 'pause' of it
+				 */
+				if (busNo == g_diagpoolBusNo
+				    && devNo == g_diagpoolDevNo) {
+					LOGINF("DEVICE_CHANGESTATE(DiagpoolChannel busNo=%d devNo=%d is pausing...)",
+					     busNo, devNo);
+					/* this will trigger the
+					 * diag_shutdown.sh script in
+					 * the visorchipset hotplug */
+					kobject_uevent_env
+					    (&Visorchipset_platform_device.dev.
+					     kobj, KOBJ_ONLINE, envp);
+				}
+			}
+			break;
+		case CONTROLVM_DEVICE_DESTROY:
+			if (notifiers->device_destroy) {
+				(*notifiers->device_destroy) (busNo, devNo);
+				notified = TRUE;
+			}
+			break;
+		}
+	}
+	if (notified)
+		/* The callback function just called above is responsible
+		 * for calling the appropriate VISORCHIPSET_BUSDEV_RESPONDERS
+		 * function, which will call device_responder()
+		 */
+		;
+	else
+		device_responder(cmd, busNo, devNo, response);
+	UNLOCKSEM(&NotifierLock);
+}
+
+static void
+bus_create(CONTROLVM_MESSAGE *inmsg)
+{
+	CONTROLVM_MESSAGE_PACKET *cmd = &inmsg->cmd;
+	ulong busNo = cmd->createBus.busNo;
+	int rc = CONTROLVM_RESP_SUCCESS;
+	VISORCHIPSET_BUS_INFO *pBusInfo = NULL;
+
+
+	pBusInfo = findbus(&BusInfoList, busNo);
+	if (pBusInfo && (pBusInfo->state.created == 1)) {
+		LOGERR("CONTROLVM_BUS_CREATE Failed: bus %lu already exists",
+		       busNo);
+		POSTCODE_LINUX_3(BUS_CREATE_FAILURE_PC, busNo,
+				 POSTCODE_SEVERITY_ERR);
+		RETINT(-CONTROLVM_RESP_ERROR_ALREADY_DONE);
+	}
+	pBusInfo = kmalloc(sizeof(VISORCHIPSET_BUS_INFO), GFP_KERNEL);
+	if (pBusInfo == NULL) {
+		LOGERR("CONTROLVM_BUS_CREATE Failed: bus %lu kmalloc failed",
+		       busNo);
+		POSTCODE_LINUX_3(BUS_CREATE_FAILURE_PC, busNo,
+				 POSTCODE_SEVERITY_ERR);
+		RETINT(-CONTROLVM_RESP_ERROR_KMALLOC_FAILED);
+	}
+
+	memset(pBusInfo, 0, sizeof(VISORCHIPSET_BUS_INFO));
+	INIT_LIST_HEAD(&pBusInfo->entry);
+	pBusInfo->busNo = busNo;
+	pBusInfo->devNo = cmd->createBus.deviceCount;
+
+	POSTCODE_LINUX_3(BUS_CREATE_ENTRY_PC, busNo, POSTCODE_SEVERITY_INFO);
+
+	if (inmsg->hdr.Flags.testMessage == 1)
+		pBusInfo->chanInfo.addrType = ADDRTYPE_localTest;
+	else
+		pBusInfo->chanInfo.addrType = ADDRTYPE_localPhysical;
+
+	pBusInfo->flags.server = inmsg->hdr.Flags.server;
+	pBusInfo->chanInfo.channelAddr = cmd->createBus.channelAddr;
+	pBusInfo->chanInfo.nChannelBytes = cmd->createBus.channelBytes;
+	pBusInfo->chanInfo.channelTypeGuid = cmd->createBus.busDataTypeGuid;
+	pBusInfo->chanInfo.channelInstGuid = cmd->createBus.busInstGuid;
+
+	list_add(&pBusInfo->entry, &BusInfoList);
+
+	POSTCODE_LINUX_3(BUS_CREATE_EXIT_PC, busNo, POSTCODE_SEVERITY_INFO);
+
+Away:
+	bus_epilog(busNo, CONTROLVM_BUS_CREATE, &inmsg->hdr,
+		   rc, inmsg->hdr.Flags.responseExpected == 1);
+}
+
+static void
+bus_destroy(CONTROLVM_MESSAGE *inmsg)
+{
+	CONTROLVM_MESSAGE_PACKET *cmd = &inmsg->cmd;
+	ulong busNo = cmd->destroyBus.busNo;
+	VISORCHIPSET_BUS_INFO *pBusInfo;
+	int rc = CONTROLVM_RESP_SUCCESS;
+
+	pBusInfo = findbus(&BusInfoList, busNo);
+	if (!pBusInfo) {
+		LOGERR("CONTROLVM_BUS_DESTROY Failed: bus %lu invalid", busNo);
+		RETINT(-CONTROLVM_RESP_ERROR_BUS_INVALID);
+	}
+	if (pBusInfo->state.created == 0) {
+		LOGERR("CONTROLVM_BUS_DESTROY Failed: bus %lu already destroyed",
+		     busNo);
+		RETINT(-CONTROLVM_RESP_ERROR_ALREADY_DONE);
+	}
+
+Away:
+	bus_epilog(busNo, CONTROLVM_BUS_DESTROY, &inmsg->hdr,
+		   rc, inmsg->hdr.Flags.responseExpected == 1);
+}
+
+static void
+bus_configure(CONTROLVM_MESSAGE *inmsg, PARSER_CONTEXT *parser_ctx)
+{
+	CONTROLVM_MESSAGE_PACKET *cmd = &inmsg->cmd;
+	ulong busNo = cmd->configureBus.busNo;
+	VISORCHIPSET_BUS_INFO *pBusInfo = NULL;
+	int rc = CONTROLVM_RESP_SUCCESS;
+	char s[99];
+
+	busNo = cmd->configureBus.busNo;
+	POSTCODE_LINUX_3(BUS_CONFIGURE_ENTRY_PC, busNo, POSTCODE_SEVERITY_INFO);
+
+	pBusInfo = findbus(&BusInfoList, busNo);
+	if (!pBusInfo) {
+		LOGERR("CONTROLVM_BUS_CONFIGURE Failed: bus %lu invalid",
+		       busNo);
+		POSTCODE_LINUX_3(BUS_CONFIGURE_FAILURE_PC, busNo,
+				 POSTCODE_SEVERITY_ERR);
+		RETINT(-CONTROLVM_RESP_ERROR_BUS_INVALID);
+	}
+	if (pBusInfo->state.created == 0) {
+		LOGERR("CONTROLVM_BUS_CONFIGURE Failed: Invalid bus %lu - not created yet",
+		     busNo);
+		POSTCODE_LINUX_3(BUS_CONFIGURE_FAILURE_PC, busNo,
+				 POSTCODE_SEVERITY_ERR);
+		RETINT(-CONTROLVM_RESP_ERROR_BUS_INVALID);
+	}
+	/* TBD - add this check to other commands also... */
+	if (pBusInfo->pendingMsgHdr.Id != CONTROLVM_INVALID) {
+		LOGERR("CONTROLVM_BUS_CONFIGURE Failed: bus %lu MsgId=%u outstanding",
+		     busNo, (uint) pBusInfo->pendingMsgHdr.Id);
+		POSTCODE_LINUX_3(BUS_CONFIGURE_FAILURE_PC, busNo,
+				 POSTCODE_SEVERITY_ERR);
+		RETINT(-CONTROLVM_RESP_ERROR_MESSAGE_ID_INVALID_FOR_CLIENT);
+	}
+
+	pBusInfo->partitionHandle = cmd->configureBus.guestHandle;
+	pBusInfo->partitionGuid = parser_id_get(parser_ctx);
+	parser_param_start(parser_ctx, PARSERSTRING_NAME);
+	pBusInfo->name = parser_string_get(parser_ctx);
+
+	visorchannel_GUID_id(&pBusInfo->partitionGuid, s);
+	pBusInfo->procObject =
+	    proc_CreateObject(PartitionType, s, (void *) (pBusInfo));
+	if (pBusInfo->procObject == NULL) {
+		LOGERR("CONTROLVM_BUS_CONFIGURE Failed: busNo=%lu failed to create /proc entry",
+		     busNo);
+		POSTCODE_LINUX_3(BUS_CONFIGURE_FAILURE_PC, busNo,
+				 POSTCODE_SEVERITY_ERR);
+		RETINT(-CONTROLVM_RESP_ERROR_KMALLOC_FAILED);
+	}
+	POSTCODE_LINUX_3(BUS_CONFIGURE_EXIT_PC, busNo, POSTCODE_SEVERITY_INFO);
+Away:
+	bus_epilog(busNo, CONTROLVM_BUS_CONFIGURE, &inmsg->hdr,
+		   rc, inmsg->hdr.Flags.responseExpected == 1);
+}
+
+static void
+my_device_create(CONTROLVM_MESSAGE *inmsg)
+{
+	CONTROLVM_MESSAGE_PACKET *cmd = &inmsg->cmd;
+	ulong busNo = cmd->createDevice.busNo;
+	ulong devNo = cmd->createDevice.devNo;
+	VISORCHIPSET_DEVICE_INFO *pDevInfo = NULL;
+	VISORCHIPSET_BUS_INFO *pBusInfo = NULL;
+	int rc = CONTROLVM_RESP_SUCCESS;
+
+	pDevInfo = finddevice(&DevInfoList, busNo, devNo);
+	if (pDevInfo && (pDevInfo->state.created == 1)) {
+		LOGERR("CONTROLVM_DEVICE_CREATE Failed: busNo=%lu, devNo=%lu already exists",
+		     busNo, devNo);
+		POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, devNo, busNo,
+				 POSTCODE_SEVERITY_ERR);
+		RETINT(-CONTROLVM_RESP_ERROR_ALREADY_DONE);
+	}
+	pBusInfo = findbus(&BusInfoList, busNo);
+	if (!pBusInfo) {
+		LOGERR("CONTROLVM_DEVICE_CREATE Failed: Invalid bus %lu - out of range",
+		     busNo);
+		POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, devNo, busNo,
+				 POSTCODE_SEVERITY_ERR);
+		RETINT(-CONTROLVM_RESP_ERROR_BUS_INVALID);
+	}
+	if (pBusInfo->state.created == 0) {
+		LOGERR("CONTROLVM_DEVICE_CREATE Failed: Invalid bus %lu - not created yet",
+		     busNo);
+		POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, devNo, busNo,
+				 POSTCODE_SEVERITY_ERR);
+		RETINT(-CONTROLVM_RESP_ERROR_BUS_INVALID);
+	}
+	pDevInfo = kmalloc(sizeof(VISORCHIPSET_DEVICE_INFO), GFP_KERNEL);
+	if (pDevInfo == NULL) {
+		LOGERR("CONTROLVM_DEVICE_CREATE Failed: busNo=%lu, devNo=%lu kmaloc failed",
+		     busNo, devNo);
+		POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, devNo, busNo,
+				 POSTCODE_SEVERITY_ERR);
+		RETINT(-CONTROLVM_RESP_ERROR_KMALLOC_FAILED);
+	}
+	memset(pDevInfo, 0, sizeof(VISORCHIPSET_DEVICE_INFO));
+	INIT_LIST_HEAD(&pDevInfo->entry);
+	pDevInfo->busNo = busNo;
+	pDevInfo->devNo = devNo;
+	pDevInfo->devInstGuid = cmd->createDevice.devInstGuid;
+	POSTCODE_LINUX_4(DEVICE_CREATE_ENTRY_PC, devNo, busNo,
+			 POSTCODE_SEVERITY_INFO);
+
+	if (inmsg->hdr.Flags.testMessage == 1)
+		pDevInfo->chanInfo.addrType = ADDRTYPE_localTest;
+	else
+		pDevInfo->chanInfo.addrType = ADDRTYPE_localPhysical;
+	pDevInfo->chanInfo.channelAddr = cmd->createDevice.channelAddr;
+	pDevInfo->chanInfo.nChannelBytes = cmd->createDevice.channelBytes;
+	pDevInfo->chanInfo.channelTypeGuid = cmd->createDevice.dataTypeGuid;
+	pDevInfo->chanInfo.intr = cmd->createDevice.intr;
+	list_add(&pDevInfo->entry, &DevInfoList);
+	POSTCODE_LINUX_4(DEVICE_CREATE_EXIT_PC, devNo, busNo,
+			 POSTCODE_SEVERITY_INFO);
+Away:
+	/* get the bus and devNo for DiagPool channel */
+	if (is_diagpool_channel(pDevInfo->chanInfo.channelTypeGuid)) {
+		g_diagpoolBusNo = busNo;
+		g_diagpoolDevNo = devNo;
+		LOGINF("CONTROLVM_DEVICE_CREATE for DiagPool channel: busNo=%lu, devNo=%lu",
+		     g_diagpoolBusNo, g_diagpoolDevNo);
+	}
+	device_epilog(busNo, devNo, SegmentStateRunning,
+		      CONTROLVM_DEVICE_CREATE, &inmsg->hdr, rc,
+		      inmsg->hdr.Flags.responseExpected == 1,
+		      FOR_VISORBUS(pDevInfo->chanInfo.channelTypeGuid));
+}
+
+static void
+my_device_changestate(CONTROLVM_MESSAGE *inmsg)
+{
+	CONTROLVM_MESSAGE_PACKET *cmd = &inmsg->cmd;
+	ulong busNo = cmd->deviceChangeState.busNo;
+	ulong devNo = cmd->deviceChangeState.devNo;
+	ULTRA_SEGMENT_STATE state = cmd->deviceChangeState.state;
+	VISORCHIPSET_DEVICE_INFO *pDevInfo = NULL;
+	int rc = CONTROLVM_RESP_SUCCESS;
+
+	pDevInfo = finddevice(&DevInfoList, busNo, devNo);
+	if (!pDevInfo) {
+		LOGERR("CONTROLVM_DEVICE_CHANGESTATE Failed: busNo=%lu, devNo=%lu invalid (doesn't exist)",
+		     busNo, devNo);
+		POSTCODE_LINUX_4(DEVICE_CHANGESTATE_FAILURE_PC, devNo, busNo,
+				 POSTCODE_SEVERITY_ERR);
+		RETINT(-CONTROLVM_RESP_ERROR_DEVICE_INVALID);
+	}
+	if (pDevInfo->state.created == 0) {
+		LOGERR("CONTROLVM_DEVICE_CHANGESTATE Failed: busNo=%lu, devNo=%lu invalid (not created)",
+		     busNo, devNo);
+		POSTCODE_LINUX_4(DEVICE_CHANGESTATE_FAILURE_PC, devNo, busNo,
+				 POSTCODE_SEVERITY_ERR);
+		RETINT(-CONTROLVM_RESP_ERROR_DEVICE_INVALID);
+	}
+Away:
+	if ((rc >= CONTROLVM_RESP_SUCCESS) && pDevInfo)
+		device_epilog(busNo, devNo, state, CONTROLVM_DEVICE_CHANGESTATE,
+			      &inmsg->hdr, rc,
+			      inmsg->hdr.Flags.responseExpected == 1,
+			      FOR_VISORBUS(pDevInfo->chanInfo.channelTypeGuid));
+}
+
+static void
+my_device_destroy(CONTROLVM_MESSAGE *inmsg)
+{
+	CONTROLVM_MESSAGE_PACKET *cmd = &inmsg->cmd;
+	ulong busNo = cmd->destroyDevice.busNo;
+	ulong devNo = cmd->destroyDevice.devNo;
+	VISORCHIPSET_DEVICE_INFO *pDevInfo = NULL;
+	int rc = CONTROLVM_RESP_SUCCESS;
+
+	pDevInfo = finddevice(&DevInfoList, busNo, devNo);
+	if (!pDevInfo) {
+		LOGERR("CONTROLVM_DEVICE_DESTROY Failed: busNo=%lu, devNo=%lu invalid",
+		     busNo, devNo);
+		RETINT(-CONTROLVM_RESP_ERROR_DEVICE_INVALID);
+	}
+	if (pDevInfo->state.created == 0) {
+		LOGERR("CONTROLVM_DEVICE_DESTROY Failed: busNo=%lu, devNo=%lu already destroyed",
+		     busNo, devNo);
+		RETINT(-CONTROLVM_RESP_ERROR_ALREADY_DONE);
+	}
+
+Away:
+	if ((rc >= CONTROLVM_RESP_SUCCESS) && pDevInfo)
+		device_epilog(busNo, devNo, SegmentStateRunning,
+			      CONTROLVM_DEVICE_DESTROY, &inmsg->hdr, rc,
+			      inmsg->hdr.Flags.responseExpected == 1,
+			      FOR_VISORBUS(pDevInfo->chanInfo.channelTypeGuid));
+}
+
+/* When provided with the physical address of the controlvm channel
+ * (phys_addr), the offset to the payload area we need to manage
+ * (offset), and the size of this payload area (bytes), fills in the
+ * CONTROLVM_PAYLOAD_INFO struct.  Returns TRUE for success or FALSE
+ * for failure.
+ */
+static int
+initialize_controlvm_payload_info(HOSTADDRESS phys_addr, U64 offset, U32 bytes,
+				  CONTROLVM_PAYLOAD_INFO *info)
+{
+	U8 *payload = NULL;
+	int rc = CONTROLVM_RESP_SUCCESS;
+
+	if (info == NULL) {
+		LOGERR("HUH ? CONTROLVM_PAYLOAD_INIT Failed : Programmer check at %s:%d",
+		     __FILE__, __LINE__);
+		RETINT(-CONTROLVM_RESP_ERROR_PAYLOAD_INVALID);
+	}
+	memset(info, 0, sizeof(CONTROLVM_PAYLOAD_INFO));
+	if ((offset == 0) || (bytes == 0)) {
+		LOGERR("CONTROLVM_PAYLOAD_INIT Failed: RequestPayloadOffset=%llu RequestPayloadBytes=%llu!",
+		     (u64) offset, (u64) bytes);
+		RETINT(-CONTROLVM_RESP_ERROR_PAYLOAD_INVALID);
+	}
+	payload = ioremap_cache(phys_addr + offset, bytes);
+	if (payload == NULL) {
+		LOGERR("CONTROLVM_PAYLOAD_INIT Failed: ioremap_cache %llu for %llu bytes failed",
+		     (u64) offset, (u64) bytes);
+		RETINT(-CONTROLVM_RESP_ERROR_IOREMAP_FAILED);
+	}
+
+	info->offset = offset;
+	info->bytes = bytes;
+	info->ptr = payload;
+	LOGINF("offset=%llu, bytes=%lu, ptr=%p",
+	       (u64) (info->offset), (ulong) (info->bytes), info->ptr);
+
+Away:
+	if (rc < 0) {
+		if (payload != NULL) {
+			iounmap(payload);
+			payload = NULL;
+		}
+	}
+	return rc;
+}
+
+static void
+destroy_controlvm_payload_info(CONTROLVM_PAYLOAD_INFO *info)
+{
+	if (info->ptr != NULL) {
+		iounmap(info->ptr);
+		info->ptr = NULL;
+	}
+	memset(info, 0, sizeof(CONTROLVM_PAYLOAD_INFO));
+}
+
+static void
+initialize_controlvm_payload(void)
+{
+	HOSTADDRESS phys_addr = visorchannel_get_physaddr(ControlVm_channel);
+	U64 payloadOffset = 0;
+	U32 payloadBytes = 0;
+	if (visorchannel_read(ControlVm_channel,
+			      offsetof(ULTRA_CONTROLVM_CHANNEL_PROTOCOL,
+				       RequestPayloadOffset),
+			      &payloadOffset, sizeof(payloadOffset)) < 0) {
+		LOGERR("CONTROLVM_PAYLOAD_INIT Failed to read controlvm channel!");
+		POSTCODE_LINUX_2(CONTROLVM_INIT_FAILURE_PC,
+				 POSTCODE_SEVERITY_ERR);
+		return;
+	}
+	if (visorchannel_read(ControlVm_channel,
+			      offsetof(ULTRA_CONTROLVM_CHANNEL_PROTOCOL,
+				       RequestPayloadBytes),
+			      &payloadBytes, sizeof(payloadBytes)) < 0) {
+		LOGERR("CONTROLVM_PAYLOAD_INIT Failed to read controlvm channel!");
+		POSTCODE_LINUX_2(CONTROLVM_INIT_FAILURE_PC,
+				 POSTCODE_SEVERITY_ERR);
+		return;
+	}
+	initialize_controlvm_payload_info(phys_addr,
+					  payloadOffset, payloadBytes,
+					  &ControlVm_payload_info);
+}
+
+/*  Send ACTION=online for DEVPATH=/sys/devices/platform/visorchipset.
+ *  Returns CONTROLVM_RESP_xxx code.
+ */
+int
+visorchipset_chipset_ready(void)
+{
+	kobject_uevent(&Visorchipset_platform_device.dev.kobj, KOBJ_ONLINE);
+	return CONTROLVM_RESP_SUCCESS;
+}
+EXPORT_SYMBOL_GPL(visorchipset_chipset_ready);
+
+int
+visorchipset_chipset_selftest(void)
+{
+	char env_selftest[20];
+	char *envp[] = { env_selftest, NULL };
+	sprintf(env_selftest, "SPARSP_SELFTEST=%d", 1);
+	kobject_uevent_env(&Visorchipset_platform_device.dev.kobj, KOBJ_CHANGE,
+			   envp);
+	return CONTROLVM_RESP_SUCCESS;
+}
+EXPORT_SYMBOL_GPL(visorchipset_chipset_selftest);
+
+/*  Send ACTION=offline for DEVPATH=/sys/devices/platform/visorchipset.
+ *  Returns CONTROLVM_RESP_xxx code.
+ */
+int
+visorchipset_chipset_notready(void)
+{
+	kobject_uevent(&Visorchipset_platform_device.dev.kobj, KOBJ_OFFLINE);
+	return CONTROLVM_RESP_SUCCESS;
+}
+EXPORT_SYMBOL_GPL(visorchipset_chipset_notready);
+
+static void
+chipset_ready(CONTROLVM_MESSAGE_HEADER *msgHdr)
+{
+	int rc = visorchipset_chipset_ready();
+	if (rc != CONTROLVM_RESP_SUCCESS)
+		rc = -rc;
+	if (msgHdr->Flags.responseExpected && !visorchipset_holdchipsetready)
+		controlvm_respond(msgHdr, rc);
+	if (msgHdr->Flags.responseExpected && visorchipset_holdchipsetready) {
+		/* Send CHIPSET_READY response when all modules have been loaded
+		 * and disks mounted for the partition
+		 */
+		g_ChipSetMsgHdr = *msgHdr;
+		LOGINF("Holding CHIPSET_READY response");
+	}
+}
+
+static void
+chipset_selftest(CONTROLVM_MESSAGE_HEADER *msgHdr)
+{
+	int rc = visorchipset_chipset_selftest();
+	if (rc != CONTROLVM_RESP_SUCCESS)
+		rc = -rc;
+	if (msgHdr->Flags.responseExpected)
+		controlvm_respond(msgHdr, rc);
+}
+
+static void
+chipset_notready(CONTROLVM_MESSAGE_HEADER *msgHdr)
+{
+	int rc = visorchipset_chipset_notready();
+	if (rc != CONTROLVM_RESP_SUCCESS)
+		rc = -rc;
+	if (msgHdr->Flags.responseExpected)
+		controlvm_respond(msgHdr, rc);
+}
+
+/* This is your "one-stop" shop for grabbing the next message from the
+ * CONTROLVM_QUEUE_EVENT queue in the controlvm channel.
+ */
+static BOOL
+read_controlvm_event(CONTROLVM_MESSAGE *msg)
+{
+	if (visorchannel_signalremove(ControlVm_channel,
+				      CONTROLVM_QUEUE_EVENT, msg)) {
+		/* got a message */
+		if (msg->hdr.Flags.testMessage == 1) {
+			LOGERR("ignoring bad CONTROLVM_QUEUE_EVENT msg with controlvm_msg_id=0x%x because Flags.testMessage is nonsensical (=1)", msg->hdr.Id);
+			return FALSE;
+		} else
+			return TRUE;
+	}
+	return FALSE;
+}
+
+/*
+ * The general parahotplug flow works as follows.  The visorchipset
+ * driver receives a DEVICE_CHANGESTATE message from Command
+ * specifying a physical device to enable or disable.  The CONTROLVM
+ * message handler calls parahotplug_process_message, which then adds
+ * the message to a global list and kicks off a udev event which
+ * causes a user level script to enable or disable the specified
+ * device.  The udev script then writes to
+ * /proc/visorchipset/parahotplug, which causes parahotplug_proc_write
+ * to get called, at which point the appropriate CONTROLVM message is
+ * retrieved from the list and responded to.
+ */
+
+#define PARAHOTPLUG_TIMEOUT_MS 2000
+
+/*
+ * Generate unique int to match an outstanding CONTROLVM message with a
+ * udev script /proc response
+ */
+static int
+parahotplug_next_id(void)
+{
+	static atomic_t id = ATOMIC_INIT(0);
+	return atomic_inc_return(&id);
+}
+
+/*
+ * Returns the time (in jiffies) when a CONTROLVM message on the list
+ * should expire -- PARAHOTPLUG_TIMEOUT_MS in the future
+ */
+static unsigned long
+parahotplug_next_expiration(void)
+{
+	return jiffies + PARAHOTPLUG_TIMEOUT_MS * HZ / 1000;
+}
+
+/*
+ * Create a parahotplug_request, which is basically a wrapper for a
+ * CONTROLVM_MESSAGE that we can stick on a list
+ */
+static struct parahotplug_request *
+parahotplug_request_create(CONTROLVM_MESSAGE *msg)
+{
+	struct parahotplug_request *req =
+	    kmalloc(sizeof(struct parahotplug_request),
+		    GFP_KERNEL|__GFP_NORETRY);
+	if (req == NULL)
+		return NULL;
+
+	req->id = parahotplug_next_id();
+	req->expiration = parahotplug_next_expiration();
+	req->msg = *msg;
+
+	return req;
+}
+
+/*
+ * Free a parahotplug_request.
+ */
+static void
+parahotplug_request_destroy(struct parahotplug_request *req)
+{
+	kfree(req);
+}
+
+/*
+ * Cause uevent to run the user level script to do the disable/enable
+ * specified in (the CONTROLVM message in) the specified
+ * parahotplug_request
+ */
+static void
+parahotplug_request_kickoff(struct parahotplug_request *req)
+{
+	CONTROLVM_MESSAGE_PACKET *cmd = &req->msg.cmd;
+	char env_cmd[40], env_id[40], env_state[40], env_bus[40], env_dev[40],
+	    env_func[40];
+	char *envp[] = {
+		env_cmd, env_id, env_state, env_bus, env_dev, env_func, NULL
+	};
+
+	sprintf(env_cmd, "SPAR_PARAHOTPLUG=1");
+	sprintf(env_id, "SPAR_PARAHOTPLUG_ID=%d", req->id);
+	sprintf(env_state, "SPAR_PARAHOTPLUG_STATE=%d",
+		cmd->deviceChangeState.state.Active);
+	sprintf(env_bus, "SPAR_PARAHOTPLUG_BUS=%d",
+		cmd->deviceChangeState.busNo);
+	sprintf(env_dev, "SPAR_PARAHOTPLUG_DEVICE=%d",
+		cmd->deviceChangeState.devNo >> 3);
+	sprintf(env_func, "SPAR_PARAHOTPLUG_FUNCTION=%d",
+		cmd->deviceChangeState.devNo & 0x7);
+
+	LOGINF("parahotplug_request_kickoff: state=%d, bdf=%d/%d/%d, id=%u\n",
+	       cmd->deviceChangeState.state.Active,
+	       cmd->deviceChangeState.busNo, cmd->deviceChangeState.devNo >> 3,
+	       cmd->deviceChangeState.devNo & 7, req->id);
+
+	kobject_uevent_env(&Visorchipset_platform_device.dev.kobj, KOBJ_CHANGE,
+			   envp);
+}
+
+/*
+ * Remove any request from the list that's been on there too long and
+ * respond with an error.
+ */
+static void
+parahotplug_process_list(void)
+{
+	struct list_head *pos = NULL;
+	struct list_head *tmp = NULL;
+
+	spin_lock(&Parahotplug_request_list_lock);
+
+	list_for_each_safe(pos, tmp, &Parahotplug_request_list) {
+		struct parahotplug_request *req =
+		    list_entry(pos, struct parahotplug_request, list);
+		if (time_after_eq(jiffies, req->expiration)) {
+			list_del(pos);
+			if (req->msg.hdr.Flags.responseExpected)
+				controlvm_respond_physdev_changestate(
+					&req->msg.hdr,
+					CONTROLVM_RESP_ERROR_DEVICE_UDEV_TIMEOUT,
+					req->msg.cmd.deviceChangeState.state);
+			parahotplug_request_destroy(req);
+		}
+	}
+
+	spin_unlock(&Parahotplug_request_list_lock);
+}
+
+/*
+ * Called from the /proc handler, which means the user script has
+ * finished the enable/disable.  Find the matching identifier, and
+ * respond to the CONTROLVM message with success.
+ */
+static int
+parahotplug_request_complete(int id, U16 active)
+{
+	struct list_head *pos = NULL;
+	struct list_head *tmp = NULL;
+
+	spin_lock(&Parahotplug_request_list_lock);
+
+	/* Look for a request matching "id". */
+	list_for_each_safe(pos, tmp, &Parahotplug_request_list) {
+		struct parahotplug_request *req =
+		    list_entry(pos, struct parahotplug_request, list);
+		if (req->id == id) {
+			/* Found a match.  Remove it from the list and
+			 * respond.
+			 */
+			list_del(pos);
+			spin_unlock(&Parahotplug_request_list_lock);
+			req->msg.cmd.deviceChangeState.state.Active = active;
+			if (req->msg.hdr.Flags.responseExpected)
+				controlvm_respond_physdev_changestate(
+					&req->msg.hdr, CONTROLVM_RESP_SUCCESS,
+					req->msg.cmd.deviceChangeState.state);
+			parahotplug_request_destroy(req);
+			return 0;
+		}
+	}
+
+	spin_unlock(&Parahotplug_request_list_lock);
+	return -1;
+}
+
+/*
+ * Enables or disables a PCI device by kicking off a udev script
+ */
+void
+parahotplug_process_message(CONTROLVM_MESSAGE *inmsg)
+{
+	struct parahotplug_request *req;
+
+	req = parahotplug_request_create(inmsg);
+
+	if (req == NULL) {
+		LOGERR("parahotplug_process_message: couldn't allocate request");
+		return;
+	}
+
+	if (inmsg->cmd.deviceChangeState.state.Active) {
+		/* For enable messages, just respond with success
+		* right away.  This is a bit of a hack, but there are
+		* issues with the early enable messages we get (with
+		* either the udev script not detecting that the device
+		* is up, or not getting called at all).  Fortunately
+		* the messages that get lost don't matter anyway, as
+		* devices are automatically enabled at
+		* initialization.
+		*/
+		parahotplug_request_kickoff(req);
+		controlvm_respond_physdev_changestate(&inmsg->hdr,
+						      CONTROLVM_RESP_SUCCESS,
+						      inmsg->cmd.
+						      deviceChangeState.state);
+		parahotplug_request_destroy(req);
+	} else {
+		/* For disable messages, add the request to the
+		* request list before kicking off the udev script.  It
+		* won't get responded to until the script has
+		* indicated it's done.
+		*/
+		spin_lock(&Parahotplug_request_list_lock);
+		list_add_tail(&(req->list), &Parahotplug_request_list);
+		spin_unlock(&Parahotplug_request_list_lock);
+
+		parahotplug_request_kickoff(req);
+	}
+}
+
+/*
+ * Gets called when the udev script writes to
+ * /proc/visorchipset/parahotplug.  Expects input in the form of "<id>
+ * <active>" where <id> is the identifier passed to the script that
+ * matches a request on the request list, and <active> is 0 or 1
+ * indicating whether the device is now enabled or not.
+ */
+static ssize_t
+parahotplug_proc_write(struct file *file, const char __user *buffer,
+		       size_t count, loff_t *ppos)
+{
+	char buf[64];
+	uint id;
+	ushort active;
+
+	if (count > sizeof(buf) - 1) {
+		LOGERR("parahotplug_proc_write: count (%d) exceeds size of buffer (%d)",
+		     (int) count, (int) sizeof(buf));
+		return -EINVAL;
+	}
+	if (copy_from_user(buf, buffer, count)) {
+		LOGERR("parahotplug_proc_write: copy_from_user failed");
+		return -EFAULT;
+	}
+	buf[count] = '\0';
+
+	if (sscanf(buf, "%u %hu", &id, &active) != 2) {
+		id = 0;
+		active = 0;
+	}
+
+	if (active != 1 && active != 0) {
+		LOGERR("parahotplug_proc_write: invalid active field");
+		return -EINVAL;
+	}
+
+	parahotplug_request_complete((int) id, (U16) active);
+
+	return count;
+}
+
+static const struct file_operations parahotplug_proc_fops = {
+	.owner = THIS_MODULE,
+	.read = visorchipset_proc_read_writeonly,
+	.write = parahotplug_proc_write,
+};
+
+/* Process a controlvm message.
+ * Return result:
+ *    FALSE - this function will return FALSE only in the case where the
+ *            controlvm message was NOT processed, but processing must be
+ *            retried before reading the next controlvm message; a
+ *            scenario where this can occur is when we need to throttle
+ *            the allocation of memory in which to copy out controlvm
+ *            payload data
+ *    TRUE  - processing of the controlvm message completed,
+ *            either successfully or with an error.
+ */
+static BOOL
+handle_command(CONTROLVM_MESSAGE inmsg, HOSTADDRESS channel_addr)
+{
+	CONTROLVM_MESSAGE_PACKET *cmd = &inmsg.cmd;
+	U64 parametersAddr = 0;
+	U32 parametersBytes = 0;
+	PARSER_CONTEXT *parser_ctx = NULL;
+	BOOL isLocalAddr = FALSE;
+	CONTROLVM_MESSAGE ackmsg;
+
+	/* create parsing context if necessary */
+	isLocalAddr = (inmsg.hdr.Flags.testMessage == 1);
+	if (channel_addr == 0) {
+		LOGERR("HUH? channel_addr is 0!");
+		return TRUE;
+	}
+	parametersAddr = channel_addr + inmsg.hdr.PayloadVmOffset;
+	parametersBytes = inmsg.hdr.PayloadBytes;
+
+	/* Parameter and channel addresses within test messages actually lie
+	 * within our OS-controlled memory.  We need to know that, because it
+	 * makes a difference in how we compute the virtual address.
+	 */
+	if (parametersAddr != 0 && parametersBytes != 0) {
+		BOOL retry = FALSE;
+		parser_ctx =
+		    parser_init_byteStream(parametersAddr, parametersBytes,
+					   isLocalAddr, &retry);
+		if (!parser_ctx) {
+			if (retry) {
+				LOGWRN("throttling to copy payload");
+				return FALSE;
+			}
+			LOGWRN("parsing failed");
+			LOGWRN("inmsg.hdr.Id=0x%lx", (ulong) inmsg.hdr.Id);
+			LOGWRN("parametersAddr=0x%llx", (u64) parametersAddr);
+			LOGWRN("parametersBytes=%lu", (ulong) parametersBytes);
+			LOGWRN("isLocalAddr=%d", isLocalAddr);
+		}
+	}
+
+	if (!isLocalAddr) {
+		controlvm_init_response(&ackmsg, &inmsg.hdr,
+					CONTROLVM_RESP_SUCCESS);
+		if ((ControlVm_channel)
+		    &&
+		    (!visorchannel_signalinsert
+		     (ControlVm_channel, CONTROLVM_QUEUE_ACK, &ackmsg)))
+			LOGWRN("failed to send ACK failed");
+	}
+	switch (inmsg.hdr.Id) {
+	case CONTROLVM_CHIPSET_INIT:
+		LOGINF("CHIPSET_INIT(#busses=%lu,#switches=%lu)",
+		       (ulong) inmsg.cmd.initChipset.busCount,
+		       (ulong) inmsg.cmd.initChipset.switchCount);
+		chipset_init(&inmsg);
+		break;
+	case CONTROLVM_BUS_CREATE:
+		LOGINF("BUS_CREATE(%lu,#devs=%lu)",
+		       (ulong) cmd->createBus.busNo,
+		       (ulong) cmd->createBus.deviceCount);
+		bus_create(&inmsg);
+		break;
+	case CONTROLVM_BUS_DESTROY:
+		LOGINF("BUS_DESTROY(%lu)", (ulong) cmd->destroyBus.busNo);
+		bus_destroy(&inmsg);
+		break;
+	case CONTROLVM_BUS_CONFIGURE:
+		LOGINF("BUS_CONFIGURE(%lu)", (ulong) cmd->configureBus.busNo);
+		bus_configure(&inmsg, parser_ctx);
+		break;
+	case CONTROLVM_DEVICE_CREATE:
+		LOGINF("DEVICE_CREATE(%lu,%lu)",
+		       (ulong) cmd->createDevice.busNo,
+		       (ulong) cmd->createDevice.devNo);
+		my_device_create(&inmsg);
+		break;
+	case CONTROLVM_DEVICE_CHANGESTATE:
+		if (cmd->deviceChangeState.flags.physicalDevice) {
+			LOGINF("DEVICE_CHANGESTATE for physical device (%lu,%lu, active=%lu)",
+			     (ulong) cmd->deviceChangeState.busNo,
+			     (ulong) cmd->deviceChangeState.devNo,
+			     (ulong) cmd->deviceChangeState.state.Active);
+			parahotplug_process_message(&inmsg);
+		} else {
+			LOGINF("DEVICE_CHANGESTATE for virtual device (%lu,%lu, state.Alive=0x%lx)",
+			     (ulong) cmd->deviceChangeState.busNo,
+			     (ulong) cmd->deviceChangeState.devNo,
+			     (ulong) cmd->deviceChangeState.state.Alive);
+			/* save the hdr and cmd structures for later use */
+			/* when sending back the response to Command */
+			my_device_changestate(&inmsg);
+			g_DiagMsgHdr = inmsg.hdr;
+			g_DeviceChangeStatePacket = inmsg.cmd;
+			break;
+		}
+		break;
+	case CONTROLVM_DEVICE_DESTROY:
+		LOGINF("DEVICE_DESTROY(%lu,%lu)",
+		       (ulong) cmd->destroyDevice.busNo,
+		       (ulong) cmd->destroyDevice.devNo);
+		my_device_destroy(&inmsg);
+		break;
+	case CONTROLVM_DEVICE_CONFIGURE:
+		LOGINF("DEVICE_CONFIGURE(%lu,%lu)",
+		       (ulong) cmd->configureDevice.busNo,
+		       (ulong) cmd->configureDevice.devNo);
+		/* no op for now, just send a respond that we passed */
+		if (inmsg.hdr.Flags.responseExpected)
+			controlvm_respond(&inmsg.hdr, CONTROLVM_RESP_SUCCESS);
+		break;
+	case CONTROLVM_CHIPSET_READY:
+		LOGINF("CHIPSET_READY");
+		chipset_ready(&inmsg.hdr);
+		break;
+	case CONTROLVM_CHIPSET_SELFTEST:
+		LOGINF("CHIPSET_SELFTEST");
+		chipset_selftest(&inmsg.hdr);
+		break;
+	case CONTROLVM_CHIPSET_STOP:
+		LOGINF("CHIPSET_STOP");
+		chipset_notready(&inmsg.hdr);
+		break;
+	default:
+		LOGERR("unrecognized controlvm cmd=%d", (int) inmsg.hdr.Id);
+		if (inmsg.hdr.Flags.responseExpected)
+			controlvm_respond(&inmsg.hdr,
+					  -CONTROLVM_RESP_ERROR_MESSAGE_ID_UNKNOWN);
+		break;
+	}
+
+	if (parser_ctx != NULL) {
+		parser_done(parser_ctx);
+		parser_ctx = NULL;
+	}
+	return TRUE;
+}
+
+static void
+controlvm_periodic_work(struct work_struct *work)
+{
+	VISORCHIPSET_CHANNEL_INFO chanInfo;
+	CONTROLVM_MESSAGE inmsg;
+	char s[99];
+	BOOL gotACommand = FALSE;
+	BOOL handle_command_failed = FALSE;
+	static U64 Poll_Count;
+
+	/* make sure visorbus server is registered for controlvm callbacks */
+	if (visorchipset_serverregwait && !serverregistered)
+		RETVOID;
+	/* make sure visorclientbus server is regsitered for controlvm
+	 * callbacks
+	 */
+	if (visorchipset_clientregwait && !clientregistered)
+		RETVOID;
+
+	memset(&chanInfo, 0, sizeof(VISORCHIPSET_CHANNEL_INFO));
+	if (!ControlVm_channel) {
+		HOSTADDRESS addr = controlvm_get_channel_address();
+		if (addr != 0) {
+			ControlVm_channel =
+			    visorchannel_create_with_lock
+			    (addr,
+			     sizeof(ULTRA_CONTROLVM_CHANNEL_PROTOCOL),
+			     UltraControlvmChannelProtocolGuid);
+			if (ControlVm_channel == NULL)
+				LOGERR("failed to create controlvm channel");
+			else if (ULTRA_CONTROLVM_CHANNEL_OK_CLIENT
+				 (visorchannel_get_header(ControlVm_channel),
+				  NULL)) {
+				LOGINF("Channel %s (ControlVm) discovered",
+				       visorchannel_id(ControlVm_channel, s));
+				initialize_controlvm_payload();
+			} else {
+				LOGERR("controlvm channel is invalid");
+				visorchannel_destroy(ControlVm_channel);
+				ControlVm_channel = NULL;
+			}
+		}
+	}
+
+	Poll_Count++;
+	if ((ControlVm_channel != NULL) || (Poll_Count >= 250))
+		;	/* keep going */
+	else
+		RETVOID;
+
+	/* Check events to determine if response to CHIPSET_READY
+	 * should be sent
+	 */
+	if (visorchipset_holdchipsetready
+	    && (g_ChipSetMsgHdr.Id != CONTROLVM_INVALID)) {
+		if (check_chipset_events() == 1) {
+			LOGINF("Sending CHIPSET_READY response");
+			controlvm_respond(&g_ChipSetMsgHdr, 0);
+			clear_chipset_events();
+			memset(&g_ChipSetMsgHdr, 0,
+			       sizeof(CONTROLVM_MESSAGE_HEADER));
+		}
+	}
+
+	if (ControlVm_channel) {
+		while (visorchannel_signalremove(ControlVm_channel,
+						 CONTROLVM_QUEUE_RESPONSE,
+						 &inmsg)) {
+			if (inmsg.hdr.PayloadMaxBytes != 0) {
+				LOGERR("Payload of size %lu returned @%lu with unexpected message id %d.",
+				     (ulong) inmsg.hdr.PayloadMaxBytes,
+				     (ulong) inmsg.hdr.PayloadVmOffset,
+				     inmsg.hdr.Id);
+			}
+		}
+		if (!gotACommand) {
+			if (ControlVm_Pending_Msg_Valid) {
+				/* we throttled processing of a prior
+				* msg, so try to process it again
+				* rather than reading a new one
+				*/
+				inmsg = ControlVm_Pending_Msg;
+				ControlVm_Pending_Msg_Valid = FALSE;
+				gotACommand = TRUE;
+			} else
+				gotACommand = read_controlvm_event(&inmsg);
+		}
+	}
+
+	handle_command_failed = FALSE;
+	while (gotACommand && (!handle_command_failed)) {
+		Most_recent_message_jiffies = jiffies;
+		if (ControlVm_channel) {
+			if (handle_command(inmsg,
+					   visorchannel_get_physaddr
+					   (ControlVm_channel)))
+				gotACommand = read_controlvm_event(&inmsg);
+			else {
+				/* this is a scenario where throttling
+				* is required, but probably NOT an
+				* error...; we stash the current
+				* controlvm msg so we will attempt to
+				* reprocess it on our next loop
+				*/
+				handle_command_failed = TRUE;
+				ControlVm_Pending_Msg = inmsg;
+				ControlVm_Pending_Msg_Valid = TRUE;
+			}
+
+		} else {
+			handle_command(inmsg, 0);
+			gotACommand = FALSE;
+		}
+	}
+
+	/* parahotplug_worker */
+	parahotplug_process_list();
+
+	RETVOID;
+
+Away:
+
+	if (time_after(jiffies,
+		       Most_recent_message_jiffies + (HZ * MIN_IDLE_SECONDS))) {
+		/* it's been longer than MIN_IDLE_SECONDS since we
+		* processed our last controlvm message; slow down the
+		* polling
+		*/
+		if (Poll_jiffies != POLLJIFFIES_CONTROLVMCHANNEL_SLOW) {
+			LOGINF("switched to slow controlvm polling");
+			Poll_jiffies = POLLJIFFIES_CONTROLVMCHANNEL_SLOW;
+		}
+	} else {
+		if (Poll_jiffies != POLLJIFFIES_CONTROLVMCHANNEL_FAST) {
+			Poll_jiffies = POLLJIFFIES_CONTROLVMCHANNEL_FAST;
+			LOGINF("switched to fast controlvm polling");
+		}
+	}
+
+	if (queue_delayed_work(Periodic_controlvm_workqueue,
+			       &Periodic_controlvm_work, Poll_jiffies) < 0) {
+		LOGERR("queue_delayed_work failed!");
+		POSTCODE_LINUX_2(QUEUE_DELAYED_WORK_PC, POSTCODE_SEVERITY_ERR);
+	}
+}
+
+static void
+setup_crash_devices_work_queue(struct work_struct *work)
+{
+
+	CONTROLVM_MESSAGE localCrashCreateBusMsg;
+	CONTROLVM_MESSAGE localCrashCreateDevMsg;
+	CONTROLVM_MESSAGE msg;
+	HOSTADDRESS host_addr;
+	U32 localSavedCrashMsgOffset;
+	U16 localSavedCrashMsgCount;
+
+	/* make sure visorbus server is registered for controlvm callbacks */
+	if (visorchipset_serverregwait && !serverregistered)
+		RETVOID;
+
+	/* make sure visorclientbus server is regsitered for controlvm
+	 * callbacks
+	 */
+	if (visorchipset_clientregwait && !clientregistered)
+		RETVOID;
+
+	POSTCODE_LINUX_2(CRASH_DEV_ENTRY_PC, POSTCODE_SEVERITY_INFO);
+
+	/* send init chipset msg */
+	msg.hdr.Id = CONTROLVM_CHIPSET_INIT;
+	msg.cmd.initChipset.busCount = 23;
+	msg.cmd.initChipset.switchCount = 0;
+
+	chipset_init(&msg);
+
+	host_addr = controlvm_get_channel_address();
+	if (!host_addr) {
+		LOGERR("Huh?  Host address is NULL");
+		POSTCODE_LINUX_2(CRASH_DEV_HADDR_NULL, POSTCODE_SEVERITY_ERR);
+		return;
+	}
+
+	ControlVm_channel =
+	    visorchannel_create_with_lock
+	    (host_addr,
+	     sizeof(ULTRA_CONTROLVM_CHANNEL_PROTOCOL),
+	     UltraControlvmChannelProtocolGuid);
+
+	if (ControlVm_channel == NULL) {
+		LOGERR("failed to create controlvm channel");
+		POSTCODE_LINUX_2(CRASH_DEV_CONTROLVM_NULL,
+				 POSTCODE_SEVERITY_ERR);
+		return;
+	}
+
+	/* get saved message count */
+	if (visorchannel_read(ControlVm_channel,
+			      offsetof(ULTRA_CONTROLVM_CHANNEL_PROTOCOL,
+				       SavedCrashMsgCount),
+			      &localSavedCrashMsgCount, sizeof(U16)) < 0) {
+		LOGERR("failed to get Saved Message Count");
+		POSTCODE_LINUX_2(CRASH_DEV_CTRL_RD_FAILURE_PC,
+				 POSTCODE_SEVERITY_ERR);
+		return;
+	}
+
+	if (localSavedCrashMsgCount != CONTROLVM_CRASHMSG_MAX) {
+		LOGERR("Saved Message Count incorrect %d",
+		       localSavedCrashMsgCount);
+		POSTCODE_LINUX_3(CRASH_DEV_COUNT_FAILURE_PC,
+				 localSavedCrashMsgCount,
+				 POSTCODE_SEVERITY_ERR);
+		return;
+	}
+
+	/* get saved crash message offset */
+	if (visorchannel_read(ControlVm_channel,
+			      offsetof(ULTRA_CONTROLVM_CHANNEL_PROTOCOL,
+				       SavedCrashMsgOffset),
+			      &localSavedCrashMsgOffset, sizeof(U32)) < 0) {
+		LOGERR("failed to get Saved Message Offset");
+		POSTCODE_LINUX_2(CRASH_DEV_CTRL_RD_FAILURE_PC,
+				 POSTCODE_SEVERITY_ERR);
+		return;
+	}
+
+	/* read create device message for storage bus offset */
+	if (visorchannel_read(ControlVm_channel,
+			      localSavedCrashMsgOffset,
+			      &localCrashCreateBusMsg,
+			      sizeof(CONTROLVM_MESSAGE)) < 0) {
+		LOGERR("CRASH_DEV_RD_BUS_FAIULRE: Failed to read CrashCreateBusMsg!");
+		POSTCODE_LINUX_2(CRASH_DEV_RD_BUS_FAIULRE_PC,
+				 POSTCODE_SEVERITY_ERR);
+		return;
+	}
+
+	/* read create device message for storage device */
+	if (visorchannel_read(ControlVm_channel,
+			      localSavedCrashMsgOffset +
+			      sizeof(CONTROLVM_MESSAGE),
+			      &localCrashCreateDevMsg,
+			      sizeof(CONTROLVM_MESSAGE)) < 0) {
+		LOGERR("CRASH_DEV_RD_DEV_FAIULRE: Failed to read CrashCreateDevMsg!");
+		POSTCODE_LINUX_2(CRASH_DEV_RD_DEV_FAIULRE_PC,
+				 POSTCODE_SEVERITY_ERR);
+		return;
+	}
+
+	/* reuse IOVM create bus message */
+	if (localCrashCreateBusMsg.cmd.createBus.channelAddr != 0)
+		bus_create(&localCrashCreateBusMsg);
+	else {
+		LOGERR("CrashCreateBusMsg is null, no dump will be taken");
+		POSTCODE_LINUX_2(CRASH_DEV_BUS_NULL_FAILURE_PC,
+				 POSTCODE_SEVERITY_ERR);
+		return;
+	}
+
+	/* reuse create device message for storage device */
+	if (localCrashCreateDevMsg.cmd.createDevice.channelAddr != 0)
+		my_device_create(&localCrashCreateDevMsg);
+	else {
+		LOGERR("CrashCreateDevMsg is null, no dump will be taken");
+		POSTCODE_LINUX_2(CRASH_DEV_DEV_NULL_FAILURE_PC,
+				 POSTCODE_SEVERITY_ERR);
+		return;
+	}
+	LOGINF("Bus and device ready for dumping");
+	POSTCODE_LINUX_2(CRASH_DEV_EXIT_PC, POSTCODE_SEVERITY_INFO);
+	return;
+
+Away:
+
+	Poll_jiffies = POLLJIFFIES_CONTROLVMCHANNEL_SLOW;
+
+	if (queue_delayed_work(Periodic_controlvm_workqueue,
+			       &Periodic_controlvm_work, Poll_jiffies) < 0) {
+		LOGERR("queue_delayed_work failed!");
+		POSTCODE_LINUX_2(QUEUE_DELAYED_WORK_PC, POSTCODE_SEVERITY_ERR);
+	}
+}
+
+static void
+bus_create_response(ulong busNo, int response)
+{
+	bus_responder(CONTROLVM_BUS_CREATE, busNo, response);
+}
+
+static void
+bus_destroy_response(ulong busNo, int response)
+{
+	bus_responder(CONTROLVM_BUS_DESTROY, busNo, response);
+}
+
+static void
+device_create_response(ulong busNo, ulong devNo, int response)
+{
+	device_responder(CONTROLVM_DEVICE_CREATE, busNo, devNo, response);
+}
+
+static void
+device_destroy_response(ulong busNo, ulong devNo, int response)
+{
+	device_responder(CONTROLVM_DEVICE_DESTROY, busNo, devNo, response);
+}
+
+void
+device_pause_response(ulong busNo, ulong devNo, int response)
+{
+
+	device_changestate_responder(CONTROLVM_DEVICE_CHANGESTATE,
+				     busNo, devNo, response,
+				     SegmentStateStandby);
+}
+EXPORT_SYMBOL_GPL(device_pause_response);
+
+static void
+device_resume_response(ulong busNo, ulong devNo, int response)
+{
+	device_changestate_responder(CONTROLVM_DEVICE_CHANGESTATE,
+				     busNo, devNo, response,
+				     SegmentStateRunning);
+}
+
+BOOL
+visorchipset_get_bus_info(ulong busNo, VISORCHIPSET_BUS_INFO *busInfo)
+{
+	void *p = findbus(&BusInfoList, busNo);
+	if (!p) {
+		LOGERR("(%lu) failed", busNo);
+		return FALSE;
+	}
+	memcpy(busInfo, p, sizeof(VISORCHIPSET_BUS_INFO));
+	return TRUE;
+}
+EXPORT_SYMBOL_GPL(visorchipset_get_bus_info);
+
+BOOL
+visorchipset_set_bus_context(ulong busNo, void *context)
+{
+	VISORCHIPSET_BUS_INFO *p = findbus(&BusInfoList, busNo);
+	if (!p) {
+		LOGERR("(%lu) failed", busNo);
+		return FALSE;
+	}
+	p->bus_driver_context = context;
+	return TRUE;
+}
+EXPORT_SYMBOL_GPL(visorchipset_set_bus_context);
+
+BOOL
+visorchipset_get_device_info(ulong busNo, ulong devNo,
+			     VISORCHIPSET_DEVICE_INFO *devInfo)
+{
+	void *p = finddevice(&DevInfoList, busNo, devNo);
+	if (!p) {
+		LOGERR("(%lu,%lu) failed", busNo, devNo);
+		return FALSE;
+	}
+	memcpy(devInfo, p, sizeof(VISORCHIPSET_DEVICE_INFO));
+	return TRUE;
+}
+EXPORT_SYMBOL_GPL(visorchipset_get_device_info);
+
+BOOL
+visorchipset_set_device_context(ulong busNo, ulong devNo, void *context)
+{
+	VISORCHIPSET_DEVICE_INFO *p = finddevice(&DevInfoList, busNo, devNo);
+	if (!p) {
+		LOGERR("(%lu,%lu) failed", busNo, devNo);
+		return FALSE;
+	}
+	p->bus_driver_context = context;
+	return TRUE;
+}
+EXPORT_SYMBOL_GPL(visorchipset_set_device_context);
+
+/* Generic wrapper function for allocating memory from a kmem_cache pool.
+ */
+void *
+visorchipset_cache_alloc(struct kmem_cache *pool, BOOL ok_to_block,
+			 char *fn, int ln)
+{
+	gfp_t gfp;
+	void *p;
+
+	if (ok_to_block)
+		gfp = GFP_KERNEL;
+	else
+		gfp = GFP_ATOMIC;
+	/* __GFP_NORETRY means "ok to fail", meaning
+	 * kmem_cache_alloc() can return NULL, implying the caller CAN
+	 * cope with failure.  If you do NOT specify __GFP_NORETRY,
+	 * Linux will go to extreme measures to get memory for you
+	 * (like, invoke oom killer), which will probably cripple the
+	 * system.
+	 */
+	gfp |= __GFP_NORETRY;
+	p = kmem_cache_alloc(pool, gfp);
+	if (!p) {
+		LOGERR("kmem_cache_alloc failed early @%s:%d\n", fn, ln);
+		return NULL;
+	}
+	atomic_inc(&Visorchipset_cache_buffers_in_use);
+	return p;
+}
+
+/* Generic wrapper function for freeing memory from a kmem_cache pool.
+ */
+void
+visorchipset_cache_free(struct kmem_cache *pool, void *p, char *fn, int ln)
+{
+	if (!p) {
+		LOGERR("NULL pointer @%s:%d\n", fn, ln);
+		return;
+	}
+	atomic_dec(&Visorchipset_cache_buffers_in_use);
+	kmem_cache_free(pool, p);
+}
+
+#define gettoken(bufp) strsep(bufp, " -\t\n")
+
+static ssize_t
+chipset_proc_write(struct file *file, const char __user *buffer,
+		   size_t count, loff_t *ppos)
+{
+	char buf[512];
+	char *token, *p;
+
+	if (count > sizeof(buf) - 1) {
+		LOGERR("chipset_proc_write: count (%d) exceeds size of buffer (%d)",
+		     (int) count, (int) sizeof(buffer));
+		return -EINVAL;
+	}
+	if (copy_from_user(buf, buffer, count)) {
+		LOGERR("chipset_proc_write: copy_from_user failed");
+		return -EFAULT;
+	}
+	buf[count] = '\0';
+
+	p = buf;
+	token = gettoken(&p);
+
+	if (strcmp(token, "CALLHOMEDISK_MOUNTED") == 0) {
+		token = gettoken(&p);
+		/* The Call Home Disk has been mounted */
+		if (strcmp(token, "0") == 0)
+			chipset_events[0] = 1;
+	} else if (strcmp(token, "MODULES_LOADED") == 0) {
+		token = gettoken(&p);
+		/* All modules for the partition have been loaded */
+		if (strcmp(token, "0") == 0)
+			chipset_events[1] = 1;
+	} else if (token == NULL) {
+		/* No event specified */
+		LOGERR("No event was specified to send CHIPSET_READY response");
+		return -1;
+	} else {
+		/* Unsupported event specified */
+		LOGERR("%s is an invalid event for sending CHIPSET_READY response",		     token);
+		return -1;
+	}
+
+	return count;
+}
+
+static ssize_t
+visorchipset_proc_read_writeonly(struct file *file, char __user *buf,
+				 size_t len, loff_t *offset)
+{
+	return 0;
+}
+
+/**
+ * Reads the InstallationError, InstallationTextId,
+ * InstallationRemainingSteps fields of ControlVMChannel.
+ */
+static ssize_t
+proc_read_installer(struct file *file, char __user *buf,
+		    size_t len, loff_t *offset)
+{
+	int length = 0;
+	U16 remainingSteps;
+	U32 error, textId;
+	char *vbuf;
+	loff_t pos = *offset;
+
+	if (pos < 0)
+		return -EINVAL;
+
+	if (pos > 0 || !len)
+		return 0;
+
+	vbuf = kzalloc(len, GFP_KERNEL);
+	if (!vbuf)
+		return -ENOMEM;
+
+	visorchannel_read(ControlVm_channel,
+			  offsetof(ULTRA_CONTROLVM_CHANNEL_PROTOCOL,
+				   InstallationRemainingSteps), &remainingSteps,
+			  sizeof(U16));
+	visorchannel_read(ControlVm_channel,
+			  offsetof(ULTRA_CONTROLVM_CHANNEL_PROTOCOL,
+				   InstallationError), &error, sizeof(U32));
+	visorchannel_read(ControlVm_channel,
+			  offsetof(ULTRA_CONTROLVM_CHANNEL_PROTOCOL,
+				   InstallationTextId), &textId, sizeof(U32));
+
+	length = sprintf(vbuf, "%u %u %u\n", remainingSteps, error, textId);
+	if (copy_to_user(buf, vbuf, length)) {
+		kfree(vbuf);
+		return -EFAULT;
+	}
+
+	kfree(vbuf);
+	*offset += length;
+	return length;
+}
+
+/**
+ * Writes to the InstallationError, InstallationTextId,
+ * InstallationRemainingSteps fields of
+ * ControlVMChannel.
+ * Input: RemainingSteps Error TextId
+ * Limit 32 characters input
+ */
+#define UINT16_MAX		(65535U)
+#define UINT32_MAX		(4294967295U)
+static ssize_t
+proc_write_installer(struct file *file,
+		     const char __user *buffer, size_t count, loff_t *ppos)
+{
+	char buf[32];
+	U16 remainingSteps;
+	U32 error, textId;
+
+	/* Check to make sure there is no buffer overflow */
+	if (count > (sizeof(buf) - 1))
+		return -EINVAL;
+
+	if (copy_from_user(buf, buffer, count)) {
+		WARN(1, "Error copying from user space\n");
+		return -EFAULT;
+	}
+
+	if (sscanf(buf, "%hu %i %i", &remainingSteps, &error, &textId) != 3) {
+		remainingSteps = UINT16_MAX;
+		error = UINT32_MAX;
+		textId = UINT32_MAX;
+	}
+
+	if (remainingSteps != UINT16_MAX) {
+		if (visorchannel_write
+		    (ControlVm_channel,
+		     offsetof(ULTRA_CONTROLVM_CHANNEL_PROTOCOL,
+			      InstallationRemainingSteps), &remainingSteps,
+		     sizeof(U16)) < 0)
+			WARN(1, "Installation Status Write Failed - Write function error - RemainingSteps = %d\n",
+			     remainingSteps);
+	}
+
+	if (error != UINT32_MAX) {
+		if (visorchannel_write
+		    (ControlVm_channel,
+		     offsetof(ULTRA_CONTROLVM_CHANNEL_PROTOCOL,
+			      InstallationError), &error, sizeof(U32)) < 0)
+			WARN(1, "Installation Status Write Failed - Write function error - Error = %d\n",
+			     error);
+	}
+
+	if (textId != UINT32_MAX) {
+		if (visorchannel_write
+		    (ControlVm_channel,
+		     offsetof(ULTRA_CONTROLVM_CHANNEL_PROTOCOL,
+			      InstallationTextId), &textId, sizeof(U32)) < 0)
+			WARN(1, "Installation Status Write Failed - Write function error - TextId = %d\n",
+			     textId);
+	}
+
+	/* So this function isn't called multiple times, must return
+	 * size of buffer
+	 */
+	return count;
+}
+
+/**
+ * Reads the ToolAction field of ControlVMChannel.
+ */
+static ssize_t
+proc_read_toolaction(struct file *file, char __user *buf,
+		     size_t len, loff_t *offset)
+{
+	int length = 0;
+	U8 toolAction;
+	char *vbuf;
+	loff_t pos = *offset;
+
+	if (pos < 0)
+		return -EINVAL;
+
+	if (pos > 0 || !len)
+		return 0;
+
+	vbuf = kzalloc(len, GFP_KERNEL);
+	if (!vbuf)
+		return -ENOMEM;
+
+	visorchannel_read(ControlVm_channel,
+			  offsetof(ULTRA_CONTROLVM_CHANNEL_PROTOCOL,
+				   ToolAction), &toolAction, sizeof(U8));
+
+	length = sprintf(vbuf, "%u\n", toolAction);
+	if (copy_to_user(buf, vbuf, length)) {
+		kfree(vbuf);
+		return -EFAULT;
+	}
+
+	kfree(vbuf);
+	*offset += length;
+	return length;
+}
+
+/**
+ * Writes to the ToolAction field of ControlVMChannel.
+ * Input: ToolAction
+ * Limit 3 characters input
+ */
+#define UINT8_MAX (255U)
+static ssize_t
+proc_write_toolaction(struct file *file,
+		      const char __user *buffer, size_t count, loff_t *ppos)
+{
+	char buf[3];
+	U8 toolAction;
+
+	/* Check to make sure there is no buffer overflow */
+	if (count > (sizeof(buf) - 1))
+		return -EINVAL;
+
+	if (copy_from_user(buf, buffer, count)) {
+		WARN(1, "Error copying from user space\n");
+		return -EFAULT;
+	}
+
+	if (sscanf(buf, "%hhd", &toolAction) != 1)
+		toolAction = UINT8_MAX;
+
+	if (toolAction != UINT8_MAX) {
+		if (visorchannel_write
+		    (ControlVm_channel,
+		     offsetof(ULTRA_CONTROLVM_CHANNEL_PROTOCOL, ToolAction),
+		     &toolAction, sizeof(U8)) < 0)
+			WARN(1, "Installation ToolAction Write Failed - ToolAction = %d\n",
+			     toolAction);
+	}
+
+	/* So this function isn't called multiple times, must return
+	 * size of buffer
+	 */
+	return count;
+}
+
+/**
+ * Reads the EfiSparIndication.BootToTool field of ControlVMChannel.
+ */
+static ssize_t
+proc_read_bootToTool(struct file *file, char __user *buf,
+		     size_t len, loff_t *offset)
+{
+	int length = 0;
+	ULTRA_EFI_SPAR_INDICATION efiSparIndication;
+	char *vbuf;
+	loff_t pos = *offset;
+
+	if (pos < 0)
+		return -EINVAL;
+
+	if (pos > 0 || !len)
+		return 0;
+
+	vbuf = kzalloc(len, GFP_KERNEL);
+	if (!vbuf)
+		return -ENOMEM;
+
+	visorchannel_read(ControlVm_channel,
+			  offsetof(ULTRA_CONTROLVM_CHANNEL_PROTOCOL,
+				   EfiSparIndication), &efiSparIndication,
+			  sizeof(ULTRA_EFI_SPAR_INDICATION));
+
+	length = sprintf(vbuf, "%d\n", (int) efiSparIndication.BootToTool);
+	if (copy_to_user(buf, vbuf, length)) {
+		kfree(vbuf);
+		return -EFAULT;
+	}
+
+	kfree(vbuf);
+	*offset += length;
+	return length;
+}
+
+/**
+ * Writes to the EfiSparIndication.BootToTool field of ControlVMChannel.
+ * Input: 1 or 0 (1 being on, 0 being off)
+ */
+static ssize_t
+proc_write_bootToTool(struct file *file,
+		      const char __user *buffer, size_t count, loff_t *ppos)
+{
+	char buf[3];
+	int inputVal;
+	ULTRA_EFI_SPAR_INDICATION efiSparIndication;
+
+	/* Check to make sure there is no buffer overflow */
+	if (count > (sizeof(buf) - 1))
+		return -EINVAL;
+
+	if (copy_from_user(buf, buffer, count)) {
+		WARN(1, "Error copying from user space\n");
+		return -EFAULT;
+	}
+
+	if (sscanf(buf, "%i", &inputVal) != 1)
+		inputVal = 0;
+
+	efiSparIndication.BootToTool = (inputVal == 1 ? 1 : 0);
+
+	if (visorchannel_write
+	    (ControlVm_channel,
+	     offsetof(ULTRA_CONTROLVM_CHANNEL_PROTOCOL, EfiSparIndication),
+	     &efiSparIndication, sizeof(ULTRA_EFI_SPAR_INDICATION)) < 0)
+		printk
+		    ("Installation BootToTool Write Failed - BootToTool = %d\n",
+		     (int) efiSparIndication.BootToTool);
+
+	/* So this function isn't called multiple times, must return
+	 * size of buffer
+	 */
+	return count;
+}
+
+static const struct file_operations chipset_proc_fops = {
+	.owner = THIS_MODULE,
+	.read = visorchipset_proc_read_writeonly,
+	.write = chipset_proc_write,
+};
+
+static int __init
+visorchipset_init(void)
+{
+	int rc = 0, x = 0;
+	struct proc_dir_entry *installer_file;
+	struct proc_dir_entry *toolaction_file;
+	struct proc_dir_entry *bootToTool_file;
+
+	LOGINF("chipset driver version %s loaded", VERSION);
+	/* process module options */
+	POSTCODE_LINUX_2(DRIVER_ENTRY_PC, POSTCODE_SEVERITY_INFO);
+
+	LOGINF("option - testvnic=%d", visorchipset_testvnic);
+	LOGINF("option - testvnicclient=%d", visorchipset_testvnicclient);
+	LOGINF("option - testmsg=%d", visorchipset_testmsg);
+	LOGINF("option - testteardown=%d", visorchipset_testteardown);
+	LOGINF("option - major=%d", visorchipset_major);
+	LOGINF("option - serverregwait=%d", visorchipset_serverregwait);
+	LOGINF("option - clientregwait=%d", visorchipset_clientregwait);
+	LOGINF("option - holdchipsetready=%d", visorchipset_holdchipsetready);
+
+	memset(&BusDev_Server_Notifiers, 0, sizeof(BusDev_Server_Notifiers));
+	memset(&BusDev_Client_Notifiers, 0, sizeof(BusDev_Client_Notifiers));
+	memset(&ControlVm_payload_info, 0, sizeof(ControlVm_payload_info));
+	memset(&LiveDump_info, 0, sizeof(LiveDump_info));
+	atomic_set(&LiveDump_info.buffers_in_use, 0);
+
+	if (visorchipset_testvnic)
+		FAIL_WPOSTCODE_2("testvnic option no longer supported", x,
+				 CHIPSET_INIT_FAILURE_PC, x);
+
+	controlvm_init();
+	MajorDev = MKDEV(visorchipset_major, 0);
+	TRY_WPOSTCODE_1(visorchipset_file_init(MajorDev, &ControlVm_channel),
+			CHIPSET_INIT_FAILURE_PC);
+	proc_Init();
+	memset(PartitionPropertyNames, 0, sizeof(PartitionPropertyNames));
+	memset(ControlVmPropertyNames, 0, sizeof(ControlVmPropertyNames));
+	InitPartitionProperties();
+	InitControlVmProperties();
+
+	PartitionType = proc_CreateType(ProcDir, PartitionTypeNames,
+					(const char **) PartitionPropertyNames,
+					&show_partition_property);
+	ControlVmType =
+	    proc_CreateType(ProcDir, ControlVmTypeNames,
+			    (const char **) ControlVmPropertyNames,
+			    &show_controlvm_property);
+
+	ControlVmObject = proc_CreateObject(ControlVmType, NULL, NULL);
+
+	/* Setup Installation fields */
+	installer_file = proc_create("installer", 0644, ProcDir,
+				     &proc_installer_fops);
+	/* Setup the ToolAction field */
+	toolaction_file = proc_create("toolaction", 0644, ProcDir,
+				      &proc_toolaction_fops);
+	/* Setup the BootToTool field */
+	bootToTool_file = proc_create("boottotool", 0644, ProcDir,
+				      &proc_bootToTool_fops);
+
+	memset(&g_DiagMsgHdr, 0, sizeof(CONTROLVM_MESSAGE_HEADER));
+
+	chipset_proc_dir = proc_create(VISORCHIPSET_CHIPSET_PROC_ENTRY_FN,
+				       0644, ProcDir, &chipset_proc_fops);
+	memset(&g_ChipSetMsgHdr, 0, sizeof(CONTROLVM_MESSAGE_HEADER));
+
+	parahotplug_proc_dir =
+	    proc_create(VISORCHIPSET_PARAHOTPLUG_PROC_ENTRY_FN, 0200,
+			ProcDir, &parahotplug_proc_fops);
+	memset(&g_DelDumpMsgHdr, 0, sizeof(CONTROLVM_MESSAGE_HEADER));
+
+	if (filexfer_constructor(sizeof(struct putfile_request)) < 0) {
+		FAIL_WPOSTCODE_1("filexfer_constructor failed", -1,
+				 CHIPSET_INIT_FAILURE_PC);
+	}
+	Putfile_buffer_list_pool =
+	    kmem_cache_create(Putfile_buffer_list_pool_name,
+			      sizeof(struct putfile_buffer_entry),
+			      0, SLAB_HWCACHE_ALIGN, NULL);
+	if (!Putfile_buffer_list_pool) {
+		FAIL_WPOSTCODE_1("failed to alloc Putfile_buffer_list_pool", -1,
+				 CHIPSET_INIT_FAILURE_PC);
+	}
+	if (visorchipset_disable_controlvm) {
+		LOGINF("visorchipset_init:controlvm disabled");
+	} else {
+		/* if booting in a crash kernel */
+		if (visorchipset_crash_kernel)
+			INIT_DELAYED_WORK(&Periodic_controlvm_work,
+					  setup_crash_devices_work_queue);
+		else
+			INIT_DELAYED_WORK(&Periodic_controlvm_work,
+					  controlvm_periodic_work);
+		Periodic_controlvm_workqueue =
+		    create_singlethread_workqueue("visorchipset_controlvm");
+
+		if (Periodic_controlvm_workqueue == NULL)
+			FAIL_WPOSTCODE_1("cannot create controlvm workqueue",
+					 -ENOMEM, CREATE_WORKQUEUE_FAILED_PC);
+		Most_recent_message_jiffies = jiffies;
+		Poll_jiffies = POLLJIFFIES_CONTROLVMCHANNEL_FAST;
+		TRY_WPOSTCODE_1(queue_delayed_work
+				(Periodic_controlvm_workqueue,
+				 &Periodic_controlvm_work, Poll_jiffies),
+				QUEUE_DELAYED_WORK_PC);
+	}
+
+	Visorchipset_platform_device.dev.devt = MajorDev;
+	if (platform_device_register(&Visorchipset_platform_device) < 0)
+		FAIL_WPOSTCODE_1
+		    ("platform_device_register(visorchipset) failed", -1,
+		     DEVICE_REGISTER_FAILURE_PC);
+	LOGINF("visorchipset device created");
+	POSTCODE_LINUX_2(CHIPSET_INIT_SUCCESS_PC, POSTCODE_SEVERITY_INFO);
+	RETINT(0);
+
+Away:
+
+	if (rc) {
+		LOGERR("visorchipset_init failed");
+		POSTCODE_LINUX_3(CHIPSET_INIT_FAILURE_PC, rc,
+				 POSTCODE_SEVERITY_ERR);
+	}
+	return rc;
+}
+
+static void
+visorchipset_exit(void)
+{
+	char s[99];
+	POSTCODE_LINUX_2(DRIVER_EXIT_PC, POSTCODE_SEVERITY_INFO);
+
+	if (visorchipset_disable_controlvm) {
+		;
+	} else {
+		cancel_delayed_work(&Periodic_controlvm_work);
+		flush_workqueue(Periodic_controlvm_workqueue);
+		destroy_workqueue(Periodic_controlvm_workqueue);
+		Periodic_controlvm_workqueue = NULL;
+		destroy_controlvm_payload_info(&ControlVm_payload_info);
+	}
+	Test_Vnic_channel = NULL;
+	if (Putfile_buffer_list_pool) {
+		kmem_cache_destroy(Putfile_buffer_list_pool);
+		Putfile_buffer_list_pool = NULL;
+	}
+	filexfer_destructor();
+	if (ControlVmObject) {
+		proc_DestroyObject(ControlVmObject);
+		ControlVmObject = NULL;
+	}
+	cleanup_controlvm_structures();
+
+	if (ControlVmType) {
+		proc_DestroyType(ControlVmType);
+		ControlVmType = NULL;
+	}
+	if (PartitionType) {
+		proc_DestroyType(PartitionType);
+		PartitionType = NULL;
+	}
+	if (diag_proc_dir) {
+		remove_proc_entry(VISORCHIPSET_DIAG_PROC_ENTRY_FN, ProcDir);
+		diag_proc_dir = NULL;
+	}
+	memset(&g_DiagMsgHdr, 0, sizeof(CONTROLVM_MESSAGE_HEADER));
+
+	if (chipset_proc_dir) {
+		remove_proc_entry(VISORCHIPSET_CHIPSET_PROC_ENTRY_FN, ProcDir);
+		chipset_proc_dir = NULL;
+	}
+	memset(&g_ChipSetMsgHdr, 0, sizeof(CONTROLVM_MESSAGE_HEADER));
+
+	if (parahotplug_proc_dir) {
+		remove_proc_entry(VISORCHIPSET_PARAHOTPLUG_PROC_ENTRY_FN,
+				  ProcDir);
+		parahotplug_proc_dir = NULL;
+	}
+
+	memset(&g_DelDumpMsgHdr, 0, sizeof(CONTROLVM_MESSAGE_HEADER));
+
+	proc_DeInit();
+	if (ControlVm_channel != NULL) {
+		LOGINF("Channel %s (ControlVm) disconnected",
+		       visorchannel_id(ControlVm_channel, s));
+		visorchannel_destroy(ControlVm_channel);
+		ControlVm_channel = NULL;
+	}
+	controlvm_deinit();
+	visorchipset_file_cleanup();
+	POSTCODE_LINUX_2(DRIVER_EXIT_PC, POSTCODE_SEVERITY_INFO);
+	LOGINF("chipset driver unloaded");
+}
+
+module_param_named(testvnic, visorchipset_testvnic, int, S_IRUGO);
+MODULE_PARM_DESC(visorchipset_testvnic, "1 to test vnic, using dummy VNIC connected via a loopback to a physical ethernet");
+int visorchipset_testvnic = 0;
+
+module_param_named(testvnicclient, visorchipset_testvnicclient, int, S_IRUGO);
+MODULE_PARM_DESC(visorchipset_testvnicclient, "1 to test vnic, using real VNIC channel attached to a separate IOVM guest");
+int visorchipset_testvnicclient = 0;
+
+module_param_named(testmsg, visorchipset_testmsg, int, S_IRUGO);
+MODULE_PARM_DESC(visorchipset_testmsg,
+		 "1 to manufacture the chipset, bus, and switch messages");
+int visorchipset_testmsg = 0;
+
+module_param_named(major, visorchipset_major, int, S_IRUGO);
+MODULE_PARM_DESC(visorchipset_major, "major device number to use for the device node");
+int visorchipset_major = 0;
+
+module_param_named(serverregwait, visorchipset_serverregwait, int, S_IRUGO);
+MODULE_PARM_DESC(visorchipset_serverreqwait,
+		 "1 to have the module wait for the visor bus to register");
+int visorchipset_serverregwait = 0;	/* default is off */
+module_param_named(clientregwait, visorchipset_clientregwait, int, S_IRUGO);
+MODULE_PARM_DESC(visorchipset_clientregwait, "1 to have the module wait for the visorclientbus to register");
+int visorchipset_clientregwait = 1;	/* default is on */
+module_param_named(testteardown, visorchipset_testteardown, int, S_IRUGO);
+MODULE_PARM_DESC(visorchipset_testteardown,
+		 "1 to test teardown of the chipset, bus, and switch");
+int visorchipset_testteardown = 0;	/* default is off */
+module_param_named(disable_controlvm, visorchipset_disable_controlvm, int,
+		   S_IRUGO);
+MODULE_PARM_DESC(visorchipset_disable_controlvm,
+		 "1 to disable polling of controlVm channel");
+int visorchipset_disable_controlvm = 0;	/* default is off */
+module_param_named(crash_kernel, visorchipset_crash_kernel, int, S_IRUGO);
+MODULE_PARM_DESC(visorchipset_crash_kernel,
+		 "1 means we are running in crash kernel");
+int visorchipset_crash_kernel = 0; /* default is running in non-crash kernel */
+module_param_named(holdchipsetready, visorchipset_holdchipsetready,
+		   int, S_IRUGO);
+MODULE_PARM_DESC(visorchipset_holdchipsetready,
+		 "1 to hold response to CHIPSET_READY");
+int visorchipset_holdchipsetready = 0; /* default is to send CHIPSET_READY
+				      * response immediately */
+module_init(visorchipset_init);
+module_exit(visorchipset_exit);
+
+MODULE_AUTHOR("Unisys");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Supervisor chipset driver for service partition: ver "
+		   VERSION);
+MODULE_VERSION(VERSION);
diff --git a/drivers/staging/unisys/visorchipset/visorchipset_umode.h b/drivers/staging/unisys/visorchipset/visorchipset_umode.h
new file mode 100644
index 0000000..259e840
--- /dev/null
+++ b/drivers/staging/unisys/visorchipset/visorchipset_umode.h
@@ -0,0 +1,37 @@
+/* visorchipset_umode.h
+ *
+ * Copyright © 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+/** @file *********************************************************************
+ *
+ *  This describes structures needed for the interface between the
+ *  visorchipset driver and a user-mode component that opens the device.
+ *
+ ******************************************************************************
+ */
+
+#ifndef __VISORCHIPSET_UMODE_H
+#define __VISORCHIPSET_UMODE_H
+
+
+
+/** The user-mode program can access the control channel buffer directly
+ *  via this memory map.
+ */
+#define VISORCHIPSET_MMAP_CONTROLCHANOFFSET    (0x00000000)
+#define VISORCHIPSET_MMAP_CONTROLCHANSIZE      (0x00400000)  /* 4MB */
+
+#endif /* __VISORCHIPSET_UMODE_H */
diff --git a/drivers/staging/unisys/visorutil/Kconfig b/drivers/staging/unisys/visorutil/Kconfig
new file mode 100644
index 0000000..4ff61a7
--- /dev/null
+++ b/drivers/staging/unisys/visorutil/Kconfig
@@ -0,0 +1,10 @@
+#
+# Unisys timskmod configuration
+#
+
+config UNISYS_VISORUTIL
+	tristate "Unisys visorutil driver"
+	depends on UNISYSSPAR
+	---help---
+	If you say Y here, you will enable the Unisys visorutil driver.
+
diff --git a/drivers/staging/unisys/visorutil/Makefile b/drivers/staging/unisys/visorutil/Makefile
new file mode 100644
index 0000000..3f46388
--- /dev/null
+++ b/drivers/staging/unisys/visorutil/Makefile
@@ -0,0 +1,11 @@
+#
+# Makefile for Unisys timskmod
+#
+
+obj-$(CONFIG_UNISYS_VISORUTIL)	+= visorutil.o
+
+visorutil-y := charqueue.o  easyproc.o  periodic_work.o  procobjecttree.o  \
+		memregion_direct.o visorkmodutils.o
+
+ccflags-y += -Idrivers/staging/unisys/include
+ccflags-y += -DCONFIG_SPAR_GUEST -DGUESTDRIVERBUILD -DNOAUTOVERSION
diff --git a/drivers/staging/unisys/visorutil/charqueue.c b/drivers/staging/unisys/visorutil/charqueue.c
new file mode 100644
index 0000000..2bce94e
--- /dev/null
+++ b/drivers/staging/unisys/visorutil/charqueue.c
@@ -0,0 +1,144 @@
+/* charqueue.c
+ *
+ * Copyright © 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+/*
+ *  Simple character queue implementation for Linux kernel mode.
+ */
+
+#include "charqueue.h"
+
+#define MYDRVNAME "charqueue"
+
+#define IS_EMPTY(charqueue) (charqueue->head == charqueue->tail)
+
+
+
+struct CHARQUEUE_Tag {
+	int alloc_size;
+	int nslots;
+	spinlock_t lock;
+	int head, tail;
+	unsigned char buf[0];
+};
+
+
+
+CHARQUEUE *charqueue_create(ulong nslots)
+{
+	int alloc_size = sizeof(CHARQUEUE) + nslots + 1;
+	CHARQUEUE *cq = kmalloc(alloc_size, GFP_KERNEL|__GFP_NORETRY);
+	if (cq == NULL) {
+		ERRDRV("charqueue_create allocation failed (alloc_size=%d)",
+		       alloc_size);
+		return NULL;
+	}
+	cq->alloc_size = alloc_size;
+	cq->nslots = nslots;
+	cq->head = cq->tail = 0;
+	spin_lock_init(&cq->lock);
+	return cq;
+}
+EXPORT_SYMBOL_GPL(charqueue_create);
+
+
+
+void charqueue_enqueue(CHARQUEUE *charqueue, unsigned char c)
+{
+	int alloc_slots = charqueue->nslots+1;  /* 1 slot is always empty */
+
+	spin_lock(&charqueue->lock);
+	charqueue->head = (charqueue->head+1) % alloc_slots;
+	if (charqueue->head == charqueue->tail)
+		/* overflow; overwrite the oldest entry */
+		charqueue->tail = (charqueue->tail+1) % alloc_slots;
+	charqueue->buf[charqueue->head] = c;
+	spin_unlock(&charqueue->lock);
+}
+EXPORT_SYMBOL_GPL(charqueue_enqueue);
+
+
+
+BOOL charqueue_is_empty(CHARQUEUE *charqueue)
+{
+	BOOL b;
+	spin_lock(&charqueue->lock);
+	b = IS_EMPTY(charqueue);
+	spin_unlock(&charqueue->lock);
+	return b;
+}
+EXPORT_SYMBOL_GPL(charqueue_is_empty);
+
+
+
+static int charqueue_dequeue_1(CHARQUEUE *charqueue)
+{
+	int alloc_slots = charqueue->nslots + 1;  /* 1 slot is always empty */
+
+	if (IS_EMPTY(charqueue))
+		return -1;
+	charqueue->tail = (charqueue->tail+1) % alloc_slots;
+	return charqueue->buf[charqueue->tail];
+}
+
+
+
+int charqueue_dequeue(CHARQUEUE *charqueue)
+{
+	int rc = -1;
+
+	spin_lock(&charqueue->lock);
+	RETINT(charqueue_dequeue_1(charqueue));
+Away:
+	spin_unlock(&charqueue->lock);
+	return rc;
+}
+
+
+
+int charqueue_dequeue_n(CHARQUEUE *charqueue, unsigned char *buf, int n)
+{
+	int rc = -1, counter = 0, c;
+
+	spin_lock(&charqueue->lock);
+	for (;;) {
+		if (n <= 0)
+			break;  /* no more buffer space */
+		c = charqueue_dequeue_1(charqueue);
+		if (c < 0)
+			break;  /* no more input */
+		*buf = (unsigned char)(c);
+		buf++;
+		n--;
+		counter++;
+	}
+	RETINT(counter);
+
+Away:
+	spin_unlock(&charqueue->lock);
+	return rc;
+}
+EXPORT_SYMBOL_GPL(charqueue_dequeue_n);
+
+
+
+void charqueue_destroy(CHARQUEUE *charqueue)
+{
+	if (charqueue == NULL)
+		return;
+	kfree(charqueue);
+}
+EXPORT_SYMBOL_GPL(charqueue_destroy);
diff --git a/drivers/staging/unisys/visorutil/charqueue.h b/drivers/staging/unisys/visorutil/charqueue.h
new file mode 100644
index 0000000..e9ce0a9
--- /dev/null
+++ b/drivers/staging/unisys/visorutil/charqueue.h
@@ -0,0 +1,37 @@
+/* charqueue.h
+ *
+ * Copyright © 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+#ifndef __CHARQUEUE_H__
+#define __CHARQUEUE_H__
+
+#include "uniklog.h"
+#include "timskmod.h"
+
+/* CHARQUEUE is an opaque structure to users.
+ * Fields are declared only in the implementation .c files.
+ */
+typedef struct CHARQUEUE_Tag CHARQUEUE;
+
+CHARQUEUE *charqueue_create(ulong nslots);
+void charqueue_enqueue(CHARQUEUE *charqueue, unsigned char c);
+int charqueue_dequeue(CHARQUEUE *charqueue);
+int charqueue_dequeue_n(CHARQUEUE *charqueue, unsigned char *buf, int n);
+BOOL charqueue_is_empty(CHARQUEUE *charqueue);
+void charqueue_destroy(CHARQUEUE *charqueue);
+
+#endif
+
diff --git a/drivers/staging/unisys/visorutil/easyproc.c b/drivers/staging/unisys/visorutil/easyproc.c
new file mode 100644
index 0000000..2b750ee
--- /dev/null
+++ b/drivers/staging/unisys/visorutil/easyproc.c
@@ -0,0 +1,365 @@
+/* Copyright © 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+/** @file *********************************************************************
+ *
+ *  Handle procfs-specific tasks.
+ *  Note that this file does not know about any module-specific things, nor
+ *  does it know anything about what information to reveal as part of the proc
+ *  entries.  The 2 functions that take care of displaying device and
+ *  driver specific information are passed as parameters to
+ *  easyproc_InitDriver().
+ *
+ *      void show_device_info(struct seq_file *seq, void *p);
+ *      void show_driver_info(struct seq_file *seq);
+ *
+ *  The second parameter to show_device_info is actually a pointer to the
+ *  device-specific info to show.  It is the context that was originally
+ *  passed to easyproc_InitDevice().
+ *
+ ******************************************************************************
+ */
+
+#include <linux/proc_fs.h>
+
+#include "uniklog.h"
+#include "timskmod.h"
+#include "easyproc.h"
+
+#define MYDRVNAME "easyproc"
+
+
+
+/*
+ *   /proc/<ProcId>                              ProcDir
+ *   /proc/<ProcId>/driver                       ProcDriverDir
+ *   /proc/<ProcId>/driver/diag                  ProcDriverDiagFile
+ *   /proc/<ProcId>/device                       ProcDeviceDir
+ *   /proc/<ProcId>/device/0                     procDevicexDir
+ *   /proc/<ProcId>/device/0/diag                procDevicexDiagFile
+ */
+
+
+static ssize_t proc_write_device(struct file *file, const char __user *buffer,
+				 size_t count, loff_t *ppos);
+static ssize_t proc_write_driver(struct file *file, const char __user *buffer,
+				 size_t count, loff_t *ppos);
+
+static struct proc_dir_entry *
+	createProcDir(char *name, struct proc_dir_entry *parent)
+{
+	struct proc_dir_entry *p = proc_mkdir_mode(name, S_IFDIR, parent);
+	if (p == NULL)
+		ERRDRV("failed to create /proc directory %s", name);
+	return p;
+}
+
+static int seq_show_driver(struct seq_file *seq, void *offset);
+static int proc_open_driver(struct inode *inode, struct file *file)
+{
+	return single_open(file, seq_show_driver, PDE_DATA(inode));
+}
+static const struct file_operations proc_fops_driver = {
+	.open = proc_open_driver,
+	.read = seq_read,
+	.write = proc_write_driver,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
+
+static int seq_show_device(struct seq_file *seq, void *offset);
+static int seq_show_device_property(struct seq_file *seq, void *offset);
+static int proc_open_device(struct inode *inode, struct file *file)
+{
+	return single_open(file, seq_show_device, PDE_DATA(inode));
+}
+static const struct file_operations proc_fops_device = {
+	.open = proc_open_device,
+	.read = seq_read,
+	.write = proc_write_device,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
+static int proc_open_device_property(struct inode *inode, struct file *file)
+{
+	return single_open(file, seq_show_device_property, PDE_DATA(inode));
+}
+static const struct file_operations proc_fops_device_property = {
+	.open = proc_open_device_property,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
+
+
+
+void easyproc_InitDriver(struct easyproc_driver_info *pdriver,
+			 char *procId,
+			 void (*show_driver_info)(struct seq_file *),
+			 void (*show_device_info)(struct seq_file *, void *))
+{
+	memset(pdriver, 0, sizeof(struct easyproc_driver_info));
+	pdriver->ProcId = procId;
+	if (pdriver->ProcId == NULL)
+		ERRDRV("ProcId cannot be NULL (trouble ahead)!");
+	pdriver->Show_driver_info = show_driver_info;
+	pdriver->Show_device_info = show_device_info;
+	if (pdriver->ProcDir == NULL)
+		pdriver->ProcDir = createProcDir(pdriver->ProcId, NULL);
+	if ((pdriver->ProcDir != NULL) && (pdriver->ProcDriverDir == NULL))
+		pdriver->ProcDriverDir = createProcDir("driver",
+						       pdriver->ProcDir);
+	if ((pdriver->ProcDir != NULL) && (pdriver->ProcDeviceDir == NULL))
+		pdriver->ProcDeviceDir = createProcDir("device",
+						       pdriver->ProcDir);
+	if ((pdriver->ProcDriverDir != NULL) &&
+	    (pdriver->ProcDriverDiagFile == NULL)) {
+		pdriver->ProcDriverDiagFile =
+			proc_create_data("diag", 0,
+					 pdriver->ProcDriverDir,
+					 &proc_fops_driver, pdriver);
+		if (pdriver->ProcDriverDiagFile == NULL)
+			ERRDRV("failed to register /proc/%s/driver/diag entry",
+			       pdriver->ProcId);
+	}
+}
+EXPORT_SYMBOL_GPL(easyproc_InitDriver);
+
+
+
+void easyproc_InitDriverEx(struct easyproc_driver_info *pdriver,
+			   char *procId,
+			   void (*show_driver_info)(struct seq_file *),
+			   void (*show_device_info)(struct seq_file *, void *),
+			   void (*write_driver_info)(char *buf, size_t count,
+						     loff_t *ppos),
+			   void (*write_device_info)(char *buf, size_t count,
+						     loff_t *ppos, void *p))
+{
+	easyproc_InitDriver(pdriver, procId,
+			    show_driver_info, show_device_info);
+	pdriver->Write_driver_info = write_driver_info;
+	pdriver->Write_device_info = write_device_info;
+}
+EXPORT_SYMBOL_GPL(easyproc_InitDriverEx);
+
+
+
+void easyproc_DeInitDriver(struct easyproc_driver_info *pdriver)
+{
+	if (pdriver->ProcDriverDiagFile != NULL) {
+		remove_proc_entry("diag", pdriver->ProcDriverDir);
+		pdriver->ProcDriverDiagFile = NULL;
+	}
+	if (pdriver->ProcDriverDir != NULL) {
+		remove_proc_entry("driver", pdriver->ProcDir);
+		pdriver->ProcDriverDir = NULL;
+	}
+	if (pdriver->ProcDeviceDir != NULL) {
+		remove_proc_entry("device", pdriver->ProcDir);
+		pdriver->ProcDeviceDir = NULL;
+	}
+	if (pdriver->ProcDir != NULL) {
+		remove_proc_entry(pdriver->ProcId, NULL);
+		pdriver->ProcDir = NULL;
+	}
+	pdriver->ProcId = NULL;
+	pdriver->Show_driver_info = NULL;
+	pdriver->Show_device_info = NULL;
+	pdriver->Write_driver_info = NULL;
+	pdriver->Write_device_info = NULL;
+}
+EXPORT_SYMBOL_GPL(easyproc_DeInitDriver);
+
+
+
+void easyproc_InitDevice(struct easyproc_driver_info *pdriver,
+			 struct easyproc_device_info *p, int devno,
+			 void *devdata)
+{
+	if ((pdriver->ProcDeviceDir != NULL) && (p->procDevicexDir == NULL)) {
+		char s[29];
+		sprintf(s, "%d", devno);
+		p->procDevicexDir = createProcDir(s, pdriver->ProcDeviceDir);
+		p->devno = devno;
+	}
+	p->devdata = devdata;
+	p->pdriver = pdriver;
+	p->devno = devno;
+	if ((p->procDevicexDir != NULL) && (p->procDevicexDiagFile == NULL)) {
+		p->procDevicexDiagFile =
+			proc_create_data("diag", 0, p->procDevicexDir,
+					 &proc_fops_device, p);
+		if (p->procDevicexDiagFile == NULL)
+			ERRDEVX(devno, "failed to register /proc/%s/device/%d/diag entry",
+				pdriver->ProcId, devno
+			       );
+	}
+	memset(&(p->device_property_info[0]), 0,
+	       sizeof(p->device_property_info));
+}
+EXPORT_SYMBOL_GPL(easyproc_InitDevice);
+
+
+
+void easyproc_CreateDeviceProperty(struct easyproc_device_info *p,
+				   void (*show_property_info)(struct seq_file *, void *),
+				   char *property_name)
+{
+	size_t i;
+	struct easyproc_device_property_info *px = NULL;
+
+	if (p->procDevicexDir == NULL) {
+		ERRDRV("state error");
+		return;
+	}
+	for (i = 0; i < ARRAY_SIZE(p->device_property_info); i++) {
+		if (p->device_property_info[i].procEntry == NULL) {
+			px = &(p->device_property_info[i]);
+			break;
+		}
+	}
+	if (!px) {
+		ERRDEVX(p->devno, "too many device properties");
+		return;
+	}
+	px->devdata = p->devdata;
+	px->pdriver = p->pdriver;
+	px->procEntry = proc_create_data(property_name, 0, p->procDevicexDir,
+					 &proc_fops_device_property, px);
+	if (strlen(property_name)+1 > sizeof(px->property_name)) {
+		ERRDEVX(p->devno, "device property name %s too long",
+			property_name);
+		return;
+	}
+	strcpy(px->property_name, property_name);
+	if (px->procEntry == NULL) {
+		ERRDEVX(p->devno, "failed to register /proc/%s/device/%d/%s entry",
+			p->pdriver->ProcId, p->devno, property_name
+		       );
+		return;
+	}
+	px->show_device_property_info = show_property_info;
+}
+EXPORT_SYMBOL_GPL(easyproc_CreateDeviceProperty);
+
+
+
+void easyproc_DeInitDevice(struct easyproc_driver_info *pdriver,
+			   struct easyproc_device_info *p, int devno)
+{
+	size_t i;
+	for (i = 0; i < ARRAY_SIZE(p->device_property_info); i++) {
+		if (p->device_property_info[i].procEntry != NULL) {
+			struct easyproc_device_property_info *px =
+				&(p->device_property_info[i]);
+			remove_proc_entry(px->property_name, p->procDevicexDir);
+			px->procEntry = NULL;
+		}
+	}
+	if (p->procDevicexDiagFile != NULL) {
+		remove_proc_entry("diag", p->procDevicexDir);
+		p->procDevicexDiagFile = NULL;
+	}
+	if (p->procDevicexDir != NULL) {
+		char s[29];
+		sprintf(s, "%d", devno);
+		remove_proc_entry(s, pdriver->ProcDeviceDir);
+		p->procDevicexDir = NULL;
+	}
+	p->devdata = NULL;
+	p->pdriver = NULL;
+}
+EXPORT_SYMBOL_GPL(easyproc_DeInitDevice);
+
+
+
+static int seq_show_driver(struct seq_file *seq, void *offset)
+{
+	struct easyproc_driver_info *p =
+		(struct easyproc_driver_info *)(seq->private);
+	if (!p)
+		return 0;
+	(*(p->Show_driver_info))(seq);
+	return 0;
+}
+
+
+
+static int seq_show_device(struct seq_file *seq, void *offset)
+{
+	struct easyproc_device_info *p =
+		(struct easyproc_device_info *)(seq->private);
+	if ((!p) || (!(p->pdriver)))
+		return 0;
+	(*(p->pdriver->Show_device_info))(seq, p->devdata);
+	return 0;
+}
+
+
+
+static int seq_show_device_property(struct seq_file *seq, void *offset)
+{
+	struct easyproc_device_property_info *p =
+		(struct easyproc_device_property_info *)(seq->private);
+	if ((!p) || (!(p->show_device_property_info)))
+		return 0;
+	(*(p->show_device_property_info))(seq, p->devdata);
+	return 0;
+}
+
+
+
+static ssize_t proc_write_driver(struct file *file, const char __user *buffer,
+				 size_t count, loff_t *ppos)
+{
+	struct seq_file *seq = (struct seq_file *)file->private_data;
+	struct easyproc_driver_info *p = NULL;
+	char local_buf[256];
+	if (seq == NULL)
+		return 0;
+	p = (struct easyproc_driver_info *)(seq->private);
+	if ((!p) || (!(p->Write_driver_info)))
+		return 0;
+	if (count >= sizeof(local_buf))
+		return -ENOMEM;
+	if (copy_from_user(local_buf, buffer, count))
+		return -EFAULT;
+	local_buf[count] = '\0';  /* be friendly */
+	(*(p->Write_driver_info))(local_buf, count, ppos);
+	return count;
+}
+
+
+
+static ssize_t proc_write_device(struct file *file, const char __user *buffer,
+				 size_t count, loff_t *ppos)
+{
+	struct seq_file *seq = (struct seq_file *)file->private_data;
+	struct easyproc_device_info *p = NULL;
+	char local_buf[256];
+	if (seq == NULL)
+		return 0;
+	p = (struct easyproc_device_info *)(seq->private);
+	if ((!p) || (!(p->pdriver)) || (!(p->pdriver->Write_device_info)))
+		return 0;
+	if (count >= sizeof(local_buf))
+		return -ENOMEM;
+	if (copy_from_user(local_buf, buffer, count))
+		return -EFAULT;
+	local_buf[count] = '\0';  /* be friendly */
+	(*(p->pdriver->Write_device_info))(local_buf, count, ppos, p->devdata);
+	return count;
+}
diff --git a/drivers/staging/unisys/visorutil/easyproc.h b/drivers/staging/unisys/visorutil/easyproc.h
new file mode 100644
index 0000000..a1b4df7
--- /dev/null
+++ b/drivers/staging/unisys/visorutil/easyproc.h
@@ -0,0 +1,86 @@
+/* easyproc.h
+ *
+ * Copyright © 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+/** @file *********************************************************************
+ *
+ *  This describes the interfaces necessary for a simple /proc file
+ *  implementation for a driver.
+ *
+ ******************************************************************************
+ */
+
+#ifndef __EASYPROC_H__
+#define __EASYPROC_H__
+
+#include "timskmod.h"
+
+
+struct easyproc_driver_info {
+	struct proc_dir_entry *ProcDir;
+	struct proc_dir_entry *ProcDriverDir;
+	struct proc_dir_entry *ProcDriverDiagFile;
+	struct proc_dir_entry *ProcDeviceDir;
+	char *ProcId;
+	void (*Show_device_info)(struct seq_file *seq, void *p);
+	void (*Show_driver_info)(struct seq_file *seq);
+	void (*Write_device_info)(char *buf, size_t count,
+				  loff_t *ppos, void *p);
+	void (*Write_driver_info)(char *buf, size_t count, loff_t *ppos);
+};
+
+/* property is a file under /proc/<x>/device/<x>/<property_name> */
+struct easyproc_device_property_info {
+	char property_name[25];
+	struct proc_dir_entry *procEntry;
+	struct easyproc_driver_info *pdriver;
+	void *devdata;
+	void (*show_device_property_info)(struct seq_file *seq, void *p);
+};
+
+struct easyproc_device_info {
+	struct proc_dir_entry *procDevicexDir;
+	struct proc_dir_entry *procDevicexDiagFile;
+	struct easyproc_driver_info *pdriver;
+	void *devdata;
+	int devno;
+	/*  allow for a number of custom properties for each device: */
+	struct easyproc_device_property_info device_property_info[10];
+};
+
+void easyproc_InitDevice(struct easyproc_driver_info *pdriver,
+			 struct easyproc_device_info *p, int devno,
+			 void *devdata);
+void easyproc_DeInitDevice(struct easyproc_driver_info *pdriver,
+			   struct easyproc_device_info *p, int devno);
+void easyproc_InitDriver(struct easyproc_driver_info *pdriver,
+			 char *procId,
+			 void (*show_driver_info)(struct seq_file *),
+			 void (*show_device_info)(struct seq_file *, void *));
+void easyproc_InitDriverEx(struct easyproc_driver_info *pdriver,
+			   char *procId,
+			   void (*show_driver_info)(struct seq_file *),
+			   void (*show_device_info)(struct seq_file *, void *),
+			   void (*Write_driver_info)(char *buf, size_t count,
+						     loff_t *ppos),
+			   void (*Write_device_info)(char *buf, size_t count,
+						     loff_t *ppos, void *p));
+void easyproc_DeInitDriver(struct easyproc_driver_info *pdriver);
+void easyproc_CreateDeviceProperty(struct easyproc_device_info *p,
+				   void (*show_property_info)(struct seq_file *, void *),
+				   char *property_name);
+
+#endif
diff --git a/drivers/staging/unisys/visorutil/memregion.h b/drivers/staging/unisys/visorutil/memregion.h
new file mode 100644
index 0000000..a1fce7b
--- /dev/null
+++ b/drivers/staging/unisys/visorutil/memregion.h
@@ -0,0 +1,43 @@
+/* memregion.h
+ *
+ * Copyright © 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+#ifndef __MEMREGION_H__
+#define __MEMREGION_H__
+
+#include "timskmod.h"
+
+/* MEMREGION is an opaque structure to users.
+ * Fields are declared only in the implementation .c files.
+ */
+typedef struct MEMREGION_Tag MEMREGION;
+
+MEMREGION *memregion_create(HOSTADDRESS physaddr, ulong nbytes);
+MEMREGION *memregion_create_overlapped(MEMREGION *parent,
+				       ulong offset, ulong nbytes);
+int memregion_resize(MEMREGION *memregion, ulong newsize);
+int memregion_read(MEMREGION *memregion,
+		   ulong offset, void *dest, ulong nbytes);
+int memregion_write(MEMREGION *memregion,
+		    ulong offset, void *src, ulong nbytes);
+void memregion_destroy(MEMREGION *memregion);
+HOSTADDRESS memregion_get_physaddr(MEMREGION *memregion);
+ulong memregion_get_nbytes(MEMREGION *memregion);
+void memregion_dump(MEMREGION *memregion, char *s,
+		    ulong off, ulong len, struct seq_file *seq);
+void *memregion_get_pointer(MEMREGION *memregion);
+
+#endif
diff --git a/drivers/staging/unisys/visorutil/memregion_direct.c b/drivers/staging/unisys/visorutil/memregion_direct.c
new file mode 100644
index 0000000..fbb460f
--- /dev/null
+++ b/drivers/staging/unisys/visorutil/memregion_direct.c
@@ -0,0 +1,221 @@
+/* memregion_direct.c
+ *
+ * Copyright © 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+/*
+ *  This is an implementation of memory regions that can be used to read/write
+ *  channel memory (in main memory of the host system) from code running in
+ *  a virtual partition.
+ */
+#include "uniklog.h"
+#include "timskmod.h"
+#include "memregion.h"
+
+#define MYDRVNAME "memregion"
+
+struct MEMREGION_Tag {
+	HOSTADDRESS physaddr;
+	ulong nbytes;
+	void *mapped;
+	BOOL requested;
+	BOOL overlapped;
+};
+
+static BOOL mapit(MEMREGION *memregion);
+static void unmapit(MEMREGION *memregion);
+
+MEMREGION *
+memregion_create(HOSTADDRESS physaddr, ulong nbytes)
+{
+	MEMREGION *rc = NULL;
+	MEMREGION *memregion = kmalloc(sizeof(MEMREGION),
+				       GFP_KERNEL|__GFP_NORETRY);
+	if (memregion == NULL) {
+		ERRDRV("memregion_create allocation failed");
+		return NULL;
+	}
+	memset(memregion, 0, sizeof(MEMREGION));
+	memregion->physaddr = physaddr;
+	memregion->nbytes = nbytes;
+	memregion->overlapped = FALSE;
+	if (!mapit(memregion))
+		RETPTR(NULL);
+	RETPTR(memregion);
+
+Away:
+	if (rc == NULL) {
+		if (memregion != NULL) {
+			memregion_destroy(memregion);
+			memregion = NULL;
+		}
+	}
+	return rc;
+}
+EXPORT_SYMBOL_GPL(memregion_create);
+
+MEMREGION *
+memregion_create_overlapped(MEMREGION *parent, ulong offset, ulong nbytes)
+{
+	MEMREGION *memregion = NULL;
+
+	if (parent == NULL) {
+		ERRDRV("%s parent is NULL", __func__);
+		return NULL;
+	}
+	if (parent->mapped == NULL) {
+		ERRDRV("%s parent is not mapped!", __func__);
+		return NULL;
+	}
+	if ((offset >= parent->nbytes) ||
+	    ((offset + nbytes) >= parent->nbytes)) {
+		ERRDRV("%s range (%lu,%lu) out of parent range",
+		       __func__, offset, nbytes);
+		return NULL;
+	}
+	memregion = kmalloc(sizeof(MEMREGION), GFP_KERNEL|__GFP_NORETRY);
+	if (memregion == NULL) {
+		ERRDRV("%s allocation failed", __func__);
+		return NULL;
+	}
+	memset(memregion, 0, sizeof(MEMREGION));
+	memregion->physaddr = parent->physaddr + offset;
+	memregion->nbytes = nbytes;
+	memregion->mapped = ((u8 *) (parent->mapped)) + offset;
+	memregion->requested = FALSE;
+	memregion->overlapped = TRUE;
+	return memregion;
+}
+EXPORT_SYMBOL_GPL(memregion_create_overlapped);
+
+
+static BOOL
+mapit(MEMREGION *memregion)
+{
+	ulong physaddr = (ulong) (memregion->physaddr);
+	ulong nbytes = memregion->nbytes;
+
+	memregion->requested = FALSE;
+	if (!request_mem_region(physaddr, nbytes, MYDRVNAME))
+		ERRDRV("cannot reserve channel memory @0x%lx for 0x%lx-- no big deal", physaddr, nbytes);
+	else
+		memregion->requested = TRUE;
+	memregion->mapped = ioremap_cache(physaddr, nbytes);
+	if (memregion->mapped == NULL) {
+		ERRDRV("cannot ioremap_cache channel memory @0x%lx for 0x%lx",
+		       physaddr, nbytes);
+		return FALSE;
+	}
+	return TRUE;
+}
+
+static void
+unmapit(MEMREGION *memregion)
+{
+	if (memregion->mapped != NULL) {
+		iounmap(memregion->mapped);
+		memregion->mapped = NULL;
+	}
+	if (memregion->requested) {
+		release_mem_region((ulong) (memregion->physaddr),
+				   memregion->nbytes);
+		memregion->requested = FALSE;
+	}
+}
+
+HOSTADDRESS
+memregion_get_physaddr(MEMREGION *memregion)
+{
+	return memregion->physaddr;
+}
+EXPORT_SYMBOL_GPL(memregion_get_physaddr);
+
+ulong
+memregion_get_nbytes(MEMREGION *memregion)
+{
+	return memregion->nbytes;
+}
+EXPORT_SYMBOL_GPL(memregion_get_nbytes);
+
+void *
+memregion_get_pointer(MEMREGION *memregion)
+{
+	return memregion->mapped;
+}
+EXPORT_SYMBOL_GPL(memregion_get_pointer);
+
+int
+memregion_resize(MEMREGION *memregion, ulong newsize)
+{
+	if (newsize == memregion->nbytes)
+		return 0;
+	if (memregion->overlapped)
+		/* no error check here - we no longer know the
+		 * parent's range!
+		 */
+		memregion->nbytes = newsize;
+	else {
+		unmapit(memregion);
+		memregion->nbytes = newsize;
+		if (!mapit(memregion))
+			return -1;
+	}
+	return 0;
+}
+EXPORT_SYMBOL_GPL(memregion_resize);
+
+
+static int
+memregion_readwrite(BOOL is_write,
+		    MEMREGION *memregion, ulong offset,
+		    void *local, ulong nbytes)
+{
+	if (offset + nbytes > memregion->nbytes) {
+		ERRDRV("memregion_readwrite offset out of range!!");
+		return -EFAULT;
+	}
+	if (is_write)
+		memcpy_toio(memregion->mapped + offset, local, nbytes);
+	else
+		memcpy_fromio(local, memregion->mapped + offset, nbytes);
+
+	return 0;
+}
+
+int
+memregion_read(MEMREGION *memregion, ulong offset, void *dest, ulong nbytes)
+{
+	return memregion_readwrite(FALSE, memregion, offset, dest, nbytes);
+}
+EXPORT_SYMBOL_GPL(memregion_read);
+
+int
+memregion_write(MEMREGION *memregion, ulong offset, void *src, ulong nbytes)
+{
+	return memregion_readwrite(TRUE, memregion, offset, src, nbytes);
+}
+EXPORT_SYMBOL_GPL(memregion_write);
+
+void
+memregion_destroy(MEMREGION *memregion)
+{
+	if (memregion == NULL)
+		return;
+	if (!memregion->overlapped)
+		unmapit(memregion);
+	kfree(memregion);
+}
+EXPORT_SYMBOL_GPL(memregion_destroy);
+
diff --git a/drivers/staging/unisys/visorutil/periodic_work.c b/drivers/staging/unisys/visorutil/periodic_work.c
new file mode 100644
index 0000000..1350b8e
--- /dev/null
+++ b/drivers/staging/unisys/visorutil/periodic_work.c
@@ -0,0 +1,230 @@
+/* periodic_work.c
+ *
+ * Copyright © 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+/*
+ *  Helper functions to schedule periodic work in Linux kernel mode.
+ */
+
+#include "uniklog.h"
+#include "timskmod.h"
+#include "periodic_work.h"
+
+#define MYDRVNAME "periodic_work"
+
+
+
+struct PERIODIC_WORK_Tag {
+	rwlock_t lock;
+	struct delayed_work work;
+	void (*workfunc)(void *);
+	void *workfuncarg;
+	BOOL is_scheduled;
+	BOOL want_to_stop;
+	ulong jiffy_interval;
+	struct workqueue_struct *workqueue;
+	const char *devnam;
+};
+
+
+
+static void periodic_work_func(struct work_struct *work)
+{
+	PERIODIC_WORK *periodic_work =
+		container_of(work, struct PERIODIC_WORK_Tag, work.work);
+	(*periodic_work->workfunc)(periodic_work->workfuncarg);
+}
+
+
+
+PERIODIC_WORK *periodic_work_create(ulong jiffy_interval,
+				      struct workqueue_struct *workqueue,
+				      void (*workfunc)(void *),
+				      void *workfuncarg,
+				      const char *devnam)
+{
+	PERIODIC_WORK *periodic_work = kmalloc(sizeof(PERIODIC_WORK),
+					       GFP_KERNEL|__GFP_NORETRY);
+	if (periodic_work == NULL) {
+		ERRDRV("periodic_work allocation failed ");
+		return NULL;
+	}
+	memset(periodic_work, '\0', sizeof(PERIODIC_WORK));
+	rwlock_init(&periodic_work->lock);
+	periodic_work->jiffy_interval = jiffy_interval;
+	periodic_work->workqueue = workqueue;
+	periodic_work->workfunc = workfunc;
+	periodic_work->workfuncarg = workfuncarg;
+	periodic_work->devnam = devnam;
+	return periodic_work;
+}
+EXPORT_SYMBOL_GPL(periodic_work_create);
+
+
+
+void periodic_work_destroy(PERIODIC_WORK *periodic_work)
+{
+	if (periodic_work == NULL)
+		return;
+	kfree(periodic_work);
+}
+EXPORT_SYMBOL_GPL(periodic_work_destroy);
+
+
+
+/** Call this from your periodic work worker function to schedule the next
+ *  call.
+ *  If this function returns FALSE, there was a failure and the
+ *  periodic work is no longer scheduled
+ */
+BOOL periodic_work_nextperiod(PERIODIC_WORK *periodic_work)
+{
+	BOOL rc = FALSE;
+	write_lock(&periodic_work->lock);
+	if (periodic_work->want_to_stop) {
+		periodic_work->is_scheduled = FALSE;
+		periodic_work->want_to_stop = FALSE;
+		RETBOOL(TRUE);  /* yes, TRUE; see periodic_work_stop() */
+	} else if (queue_delayed_work(periodic_work->workqueue,
+				      &periodic_work->work,
+				      periodic_work->jiffy_interval) < 0) {
+		ERRDEV(periodic_work->devnam, "queue_delayed_work failed!");
+		periodic_work->is_scheduled = FALSE;
+		RETBOOL(FALSE);
+	}
+	RETBOOL(TRUE);
+Away:
+	write_unlock(&periodic_work->lock);
+	return rc;
+}
+EXPORT_SYMBOL_GPL(periodic_work_nextperiod);
+
+
+
+/** This function returns TRUE iff new periodic work was actually started.
+ *  If this function returns FALSE, then no work was started
+ *  (either because it was already started, or because of a failure).
+ */
+BOOL periodic_work_start(PERIODIC_WORK *periodic_work)
+{
+	BOOL rc = FALSE;
+
+	write_lock(&periodic_work->lock);
+	if (periodic_work->is_scheduled)
+		RETBOOL(FALSE);
+	if (periodic_work->want_to_stop) {
+		ERRDEV(periodic_work->devnam,
+		       "dev_start_periodic_work failed!");
+		RETBOOL(FALSE);
+	}
+	INIT_DELAYED_WORK(&periodic_work->work, &periodic_work_func);
+	if (queue_delayed_work(periodic_work->workqueue,
+			       &periodic_work->work,
+			       periodic_work->jiffy_interval) < 0) {
+		ERRDEV(periodic_work->devnam,
+		       "%s queue_delayed_work failed!", __func__);
+		RETBOOL(FALSE);
+	}
+	periodic_work->is_scheduled = TRUE;
+	RETBOOL(TRUE);
+Away:
+	write_unlock(&periodic_work->lock);
+	return rc;
+
+}
+EXPORT_SYMBOL_GPL(periodic_work_start);
+
+
+
+
+/** This function returns TRUE iff your call actually stopped the periodic
+ *  work.
+ *
+ *  -- PAY ATTENTION... this is important --
+ *
+ *  NO NO #1
+ *
+ *     Do NOT call this function from some function that is running on the
+ *     same workqueue as the work you are trying to stop might be running
+ *     on!  If you violate this rule, periodic_work_stop() MIGHT work, but it
+ *     also MIGHT get hung up in an infinite loop saying
+ *     "waiting for delayed work...".  This will happen if the delayed work
+ *     you are trying to cancel has been put in the workqueue list, but can't
+ *     run yet because we are running that same workqueue thread right now.
+ *
+ *     Bottom line: If you need to call periodic_work_stop() from a workitem,
+ *     be sure the workitem is on a DIFFERENT workqueue than the workitem that
+ *     you are trying to cancel.
+ *
+ *     If I could figure out some way to check for this "no no" condition in
+ *     the code, I would.  It would have saved me the trouble of writing this
+ *     long comment.  And also, don't think this is some "theoretical" race
+ *     condition.  It is REAL, as I have spent the day chasing it.
+ *
+ *  NO NO #2
+ *
+ *     Take close note of the locks that you own when you call this function.
+ *     You must NOT own any locks that are needed by the periodic work
+ *     function that is currently installed.  If you DO, a deadlock may result,
+ *     because stopping the periodic work often involves waiting for the last
+ *     iteration of the periodic work function to complete.  Again, if you hit
+ *     this deadlock, you will get hung up in an infinite loop saying
+ *     "waiting for delayed work...".
+ */
+BOOL periodic_work_stop(PERIODIC_WORK *periodic_work)
+{
+	BOOL stopped_something = FALSE;
+
+	write_lock(&periodic_work->lock);
+	stopped_something = periodic_work->is_scheduled &&
+		(!periodic_work->want_to_stop);
+	while (periodic_work->is_scheduled) {
+		periodic_work->want_to_stop = TRUE;
+		if (cancel_delayed_work(&periodic_work->work)) {
+			/* We get here if the delayed work was pending as
+			 * delayed work, but was NOT run.
+			 */
+			ASSERT(periodic_work->is_scheduled);
+			periodic_work->is_scheduled = FALSE;
+		} else {
+			/* If we get here, either the delayed work:
+			 * - was run, OR,
+			 * - is running RIGHT NOW on another processor, OR,
+			 * - wasn't even scheduled (there is a miniscule
+			 *   timing window where this could be the case)
+			 * flush_workqueue() would make sure it is finished
+			 * executing, but that still isn't very useful, which
+			 * explains the loop...
+			 */
+		}
+		if (periodic_work->is_scheduled) {
+			write_unlock(&periodic_work->lock);
+			WARNDEV(periodic_work->devnam,
+				"waiting for delayed work...");
+			/* We rely on the delayed work function running here,
+			 * and eventually calling periodic_work_nextperiod(),
+			 * which will see that want_to_stop is set, and
+			 * subsequently clear is_scheduled.
+			 */
+			SLEEPJIFFIES(10);
+			write_lock(&periodic_work->lock);
+		} else
+			periodic_work->want_to_stop = FALSE;
+	}
+	write_unlock(&periodic_work->lock);
+	return stopped_something;
+}
+EXPORT_SYMBOL_GPL(periodic_work_stop);
diff --git a/drivers/staging/unisys/visorutil/procobjecttree.c b/drivers/staging/unisys/visorutil/procobjecttree.c
new file mode 100644
index 0000000..f59b37e
--- /dev/null
+++ b/drivers/staging/unisys/visorutil/procobjecttree.c
@@ -0,0 +1,334 @@
+/* procobjecttree.c
+ *
+ * Copyright © 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+#include "procobjecttree.h"
+
+#define MYDRVNAME "procobjecttree"
+
+
+
+/** This is context info that we stash in each /proc file entry, which we
+ *  need in order to call the callback function that supplies the /proc read
+ *  info for that file.
+ */
+typedef struct {
+	void (*show_property)(struct seq_file *, void *, int);
+	MYPROCOBJECT *procObject;
+	int propertyIndex;
+
+} PROCDIRENTRYCONTEXT;
+
+/** This describes the attributes of a tree rooted at
+ *  <procDirRoot>/<name[0]>/<name[1]>/...
+ *  Properties for each object of this type will be located under
+ *  <procDirRoot>/<name[0]>/<name[1]>/.../<objectName>/<propertyName>.
+ */
+struct MYPROCTYPE_Tag {
+	const char **name;  /**< node names for this type, ending with NULL */
+	int nNames;         /**< num of node names in <name> */
+
+	/** root dir for this type tree in /proc */
+	struct proc_dir_entry *procDirRoot;
+
+	struct proc_dir_entry **procDirs;  /**< for each node in <name> */
+
+	/** bottom dir where objects will be rooted; i.e., this is
+	 *  <procDirRoot>/<name[0]>/<name[1]>/.../, which is the same as the
+	 *  last entry in the <procDirs> array. */
+	struct proc_dir_entry *procDir;
+
+	/** name for each property that objects of this type can have */
+	const char **propertyNames;
+
+	int nProperties;       /**< num of names in <propertyNames> */
+
+	/** Call this, passing MYPROCOBJECT.context and the property index
+	 *  whenever someone reads the proc entry */
+	void (*show_property)(struct seq_file *, void *, int);
+};
+
+
+
+struct MYPROCOBJECT_Tag {
+	MYPROCTYPE *type;
+
+	/** This is the name of the dir node in /proc under which the
+	 *  properties of this object will appear as files. */
+	char *name;
+
+	int namesize;   /**< number of bytes allocated for name */
+	void *context;  /**< passed to MYPROCTYPE.show_property */
+
+	/** <type.procDirRoot>/<type.name[0]>/<type.name[1]>/.../<name> */
+	struct proc_dir_entry *procDir;
+
+	/** a proc dir entry for each of the properties of the object;
+	 *  properties are identified in MYPROCTYPE.propertyNames, so each of
+	 *  the <procDirProperties> describes a single file like
+	 *  <type.procDirRoot>/<type.name[0]>/<type.name[1]>/...
+	 *           /<name>/<propertyName>
+	 */
+	struct proc_dir_entry **procDirProperties;
+
+	/** this is a holding area for the context information that is needed
+	 *  to run the /proc callback function */
+	PROCDIRENTRYCONTEXT *procDirPropertyContexts;
+};
+
+
+
+static struct proc_dir_entry *
+createProcDir(const char *name, struct proc_dir_entry *parent)
+{
+	struct proc_dir_entry *p = proc_mkdir_mode(name, S_IFDIR, parent);
+	if (p == NULL)
+		ERRDRV("failed to create /proc directory %s", name);
+	return p;
+}
+
+static struct proc_dir_entry *
+createProcFile(const char *name, struct proc_dir_entry *parent,
+	       const struct file_operations *fops, void *data)
+{
+	struct proc_dir_entry *p = proc_create_data(name, 0, parent,
+						    fops, data);
+	if (p == NULL)
+		ERRDRV("failed to create /proc file %s", name);
+	return p;
+}
+
+static int seq_show(struct seq_file *seq, void *offset);
+static int proc_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, seq_show, PDE_DATA(inode));
+}
+
+static const struct file_operations proc_fops = {
+	.open = proc_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
+
+
+
+MYPROCTYPE *proc_CreateType(struct proc_dir_entry *procDirRoot,
+			    const char **name,
+			    const char **propertyNames,
+			    void (*show_property)(struct seq_file *,
+						  void *, int))
+{
+	int i = 0;
+	MYPROCTYPE *rc = NULL, *type = NULL;
+	struct proc_dir_entry *parent = NULL;
+
+	if (procDirRoot == NULL)
+		FAIL("procDirRoot cannot be NULL!", 0);
+	if (name == NULL || name[0] == NULL)
+		FAIL("name must contain at least 1 node name!", 0);
+	type = kmalloc(sizeof(MYPROCTYPE), GFP_KERNEL|__GFP_NORETRY);
+	if (type == NULL)
+		FAIL("out of memory", 0);
+	memset(type, 0, sizeof(MYPROCTYPE));
+	type->name = name;
+	type->propertyNames = propertyNames;
+	type->nProperties = 0;
+	type->nNames = 0;
+	type->show_property = show_property;
+	type->procDirRoot = procDirRoot;
+	if (type->propertyNames != 0)
+		while (type->propertyNames[type->nProperties] != NULL)
+			type->nProperties++;
+	while (type->name[type->nNames] != NULL)
+		type->nNames++;
+	type->procDirs = kmalloc((type->nNames+1)*
+				 sizeof(struct proc_dir_entry *),
+				 GFP_KERNEL|__GFP_NORETRY);
+	if (type->procDirs == NULL)
+		FAIL("out of memory", 0);
+	memset(type->procDirs, 0, (type->nNames + 1) *
+	       sizeof(struct proc_dir_entry *));
+	parent = procDirRoot;
+	for (i = 0; i < type->nNames; i++) {
+		type->procDirs[i] = createProcDir(type->name[i], parent);
+		if (type->procDirs[i] == NULL)
+			RETPTR(NULL);
+		parent = type->procDirs[i];
+	}
+	type->procDir = type->procDirs[type->nNames-1];
+	RETPTR(type);
+Away:
+	if (rc == NULL) {
+		if (type != NULL) {
+			proc_DestroyType(type);
+			type = NULL;
+		}
+	}
+	return rc;
+}
+EXPORT_SYMBOL_GPL(proc_CreateType);
+
+
+
+void proc_DestroyType(MYPROCTYPE *type)
+{
+	if (type == NULL)
+		return;
+	if (type->procDirs != NULL) {
+		int i = type->nNames-1;
+		while (i >= 0) {
+			if (type->procDirs[i] != NULL) {
+				struct proc_dir_entry *parent = NULL;
+				if (i == 0)
+					parent = type->procDirRoot;
+				else
+					parent = type->procDirs[i-1];
+				remove_proc_entry(type->name[i], parent);
+			}
+			i--;
+		}
+		kfree(type->procDirs);
+		type->procDirs = NULL;
+	}
+	kfree(type);
+}
+EXPORT_SYMBOL_GPL(proc_DestroyType);
+
+
+
+MYPROCOBJECT *proc_CreateObject(MYPROCTYPE *type,
+				const char *name, void *context)
+{
+	MYPROCOBJECT *obj = NULL, *rc = NULL;
+	int i = 0;
+
+	if (type == NULL)
+		FAIL("type cannot be NULL", 0);
+	obj = kmalloc(sizeof(MYPROCOBJECT), GFP_KERNEL | __GFP_NORETRY);
+	if (obj == NULL)
+		FAIL("out of memory", 0);
+	memset(obj, 0, sizeof(MYPROCOBJECT));
+	obj->type = type;
+	obj->context = context;
+	if (name == NULL) {
+		obj->name = NULL;
+		obj->procDir = type->procDir;
+	} else {
+		obj->namesize = strlen(name)+1;
+		obj->name = kmalloc(obj->namesize, GFP_KERNEL | __GFP_NORETRY);
+		if (obj->name == NULL) {
+			obj->namesize = 0;
+			FAIL("out of memory", 0);
+		}
+		strcpy(obj->name, name);
+		obj->procDir = createProcDir(obj->name, type->procDir);
+		if (obj->procDir == NULL)
+			RETPTR(NULL);
+	}
+	obj->procDirPropertyContexts =
+		kmalloc((type->nProperties+1)*sizeof(PROCDIRENTRYCONTEXT),
+			GFP_KERNEL|__GFP_NORETRY);
+	if (obj->procDirPropertyContexts == NULL)
+		FAIL("out of memory", 0);
+	memset(obj->procDirPropertyContexts, 0,
+	       (type->nProperties+1)*sizeof(PROCDIRENTRYCONTEXT));
+	obj->procDirProperties =
+		kmalloc((type->nProperties+1) * sizeof(struct proc_dir_entry *),
+			GFP_KERNEL|__GFP_NORETRY);
+	if (obj->procDirProperties == NULL)
+		FAIL("out of memory", 0);
+	memset(obj->procDirProperties, 0,
+	       (type->nProperties+1) * sizeof(struct proc_dir_entry *));
+	for (i = 0; i < type->nProperties; i++) {
+		obj->procDirPropertyContexts[i].procObject = obj;
+		obj->procDirPropertyContexts[i].propertyIndex = i;
+		obj->procDirPropertyContexts[i].show_property =
+			type->show_property;
+		if (type->propertyNames[i][0] != '\0') {
+			/* only create properties that have names */
+			obj->procDirProperties[i] =
+				createProcFile(type->propertyNames[i],
+					       obj->procDir, &proc_fops,
+					       &obj->procDirPropertyContexts[i]);
+			if (obj->procDirProperties[i] == NULL)
+				RETPTR(NULL);
+		}
+	}
+	RETPTR(obj);
+Away:
+	if (rc == NULL) {
+		if (obj != NULL) {
+			proc_DestroyObject(obj);
+			obj = NULL;
+		}
+	}
+	return rc;
+}
+EXPORT_SYMBOL_GPL(proc_CreateObject);
+
+
+
+void proc_DestroyObject(MYPROCOBJECT *obj)
+{
+	MYPROCTYPE *type = NULL;
+	if (obj == NULL)
+		return;
+	type = obj->type;
+	if (type == NULL)
+		return;
+	if (obj->procDirProperties != NULL) {
+		int i = 0;
+		for (i = 0; i < type->nProperties; i++) {
+			if (obj->procDirProperties[i] != NULL) {
+				remove_proc_entry(type->propertyNames[i],
+						  obj->procDir);
+				obj->procDirProperties[i] = NULL;
+			}
+		}
+		kfree(obj->procDirProperties);
+		obj->procDirProperties = NULL;
+	}
+	if (obj->procDirPropertyContexts != NULL) {
+		kfree(obj->procDirPropertyContexts);
+		obj->procDirPropertyContexts = NULL;
+	}
+	if (obj->procDir != NULL) {
+		if (obj->name != NULL)
+			remove_proc_entry(obj->name, type->procDir);
+		obj->procDir = NULL;
+	}
+	if (obj->name != NULL) {
+		kfree(obj->name);
+		obj->name = NULL;
+	}
+	kfree(obj);
+}
+EXPORT_SYMBOL_GPL(proc_DestroyObject);
+
+
+
+static int seq_show(struct seq_file *seq, void *offset)
+{
+	PROCDIRENTRYCONTEXT *ctx = (PROCDIRENTRYCONTEXT *)(seq->private);
+	if (ctx == NULL) {
+		ERRDRV("I don't have a freakin' clue...");
+		return 0;
+	}
+	(*ctx->show_property)(seq, ctx->procObject->context,
+			      ctx->propertyIndex);
+	return 0;
+}
diff --git a/drivers/staging/unisys/visorutil/visorkmodutils.c b/drivers/staging/unisys/visorutil/visorkmodutils.c
new file mode 100644
index 0000000..13e7326
--- /dev/null
+++ b/drivers/staging/unisys/visorutil/visorkmodutils.c
@@ -0,0 +1,721 @@
+/* timskmodutils.c
+ *
+ * Copyright © 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+#include "uniklog.h"
+#include "timskmod.h"
+
+#define MYDRVNAME "timskmodutils"
+
+BOOL Debug_Malloc_Enabled = FALSE;
+
+
+
+void myprintk(const char *myDrvName, const char *devname,
+	       const char *template, ...)
+{
+	va_list ap;
+	char temp[999];
+	char *ptemp = temp;
+	char pfx[20];
+	char msg[sizeof(pfx) + strlen(myDrvName) + 50];
+
+	if (myDrvName == NULL)
+		return;
+	temp[sizeof(temp)-1] = '\0';
+	pfx[0]               = '\0';
+	msg[0]               = '\0';
+	va_start(ap, template);
+	vsprintf(temp, template, ap);
+	va_end(ap);
+	if (temp[0] == '<') {
+		size_t i = 0;
+		for (i = 0; i < sizeof(pfx) - 1; i++) {
+			pfx[i] = temp[i];
+			if (pfx[i] == '>' || pfx[i] == '\0') {
+				if (pfx[i] == '>')
+					ptemp = temp+i+1;
+				i++;
+				break;
+			}
+		}
+		pfx[i] = '\0';
+	}
+	if (devname == NULL)
+		sprintf(msg, "%s%s: ", pfx, myDrvName);
+	else
+		sprintf(msg, "%s%s[%s]: ", pfx, myDrvName, devname);
+	printk(KERN_INFO "%s", msg);
+
+	/* The <prefix> applies up until the \n, so we should not include
+	 * it in these printks.  That's why we use <ptemp> to point to the
+	 * first char after the ">" in the prefix.
+	 */
+	printk(KERN_INFO "%s", ptemp);
+	printk("\n");
+
+}
+
+
+
+void myprintkx(const char *myDrvName, int devno, const char *template, ...)
+{
+	va_list ap;
+	char temp[999];
+	char *ptemp = temp;
+	char pfx[20];
+	char msg[sizeof(pfx) + strlen(myDrvName) + 50];
+
+	if (myDrvName == NULL)
+		return;
+	temp[sizeof(temp)-1] = '\0';
+	pfx[0]               = '\0';
+	msg[0]               = '\0';
+	va_start(ap, template);
+	vsprintf(temp, template, ap);
+	va_end(ap);
+	if (temp[0] == '<') {
+		size_t i = 0;
+		for (i = 0; i < sizeof(pfx) - 1; i++) {
+			pfx[i] = temp[i];
+			if (pfx[i] == '>' || pfx[i] == '\0') {
+				if (pfx[i] == '>')
+					ptemp = temp+i+1;
+				i++;
+				break;
+			}
+		}
+		pfx[i] = '\0';
+	}
+	if (devno < 0)
+		sprintf(msg, "%s%s: ", pfx, myDrvName);
+	else
+		sprintf(msg, "%s%s[%d]: ", pfx, myDrvName, devno);
+	printk(KERN_INFO "%s", msg);
+
+	/* The <prefix> applies up until the \n, so we should not include
+	 * it in these printks.  That's why we use <ptemp> to point to the
+	 * first char after the ">" in the prefix.
+	 */
+	printk(KERN_INFO "%s", ptemp);
+	printk("\n");
+}
+
+
+
+int hexDumpWordsToBuffer(char *dest,
+			 int destSize,
+			 char *prefix,
+			 uint32_t *src,
+			 int srcWords,
+			 int wordsToDumpPerLine)
+{
+	int i = 0;
+	int pos = 0;
+	char hex[(wordsToDumpPerLine * 9) + 1];
+	char *line = NULL;
+	int linesize = 1000;
+	int linelen = 0;
+	int currentlen = 0;
+	char emptystring[] = "";
+	char *pfx = prefix;
+	int baseaddr = 0;
+	int rc = 0;
+	uint8_t b1, b2, b3, b4;
+
+	line = vmalloc(linesize);
+	if (line == NULL)
+		RETINT(currentlen);
+
+	if (pfx == NULL || (strlen(pfx) > 50))
+		pfx = emptystring;
+	memset(hex, ' ', wordsToDumpPerLine * 9);
+	hex[wordsToDumpPerLine * 9] = '\0';
+	if (destSize > 0)
+		dest[0] = '\0';
+
+	for (i = 0; i < srcWords; i++) {
+		pos = i % wordsToDumpPerLine;
+		if ((pos == 0) && (i > 0)) {
+			hex[wordsToDumpPerLine * 9] = '\0';
+			linelen = sprintf(line, "%s%-6.6x %s\n", pfx,
+					  baseaddr, hex);
+			if ((currentlen) + (linelen) >= destSize)
+				RETINT(currentlen);
+			strcat(dest, line);
+			currentlen += linelen;
+			memset(hex, ' ', wordsToDumpPerLine * 9);
+			baseaddr = i * 4;
+		}
+		b1 = (uint8_t)((src[i] >> 24) & 0xff);
+		b2 = (uint8_t)((src[i] >> 16) & 0xff);
+		b3 = (uint8_t)((src[i] >>  8) & 0xff);
+		b4 = (uint8_t)((src[i]) & 0xff);
+		sprintf(hex + (pos * 9), "%-2.2x%-2.2x%-2.2x%-2.2x ",
+			b1, b2, b3, b4);
+		*(hex + (pos * 9) + 9) = ' ';  /* get rid of null */
+	}
+	pos = i%wordsToDumpPerLine;
+	if (i > 0) {
+		hex[wordsToDumpPerLine * 9] = '\0';
+		linelen = sprintf(line, "%s%-6.6x %s\n", pfx, baseaddr, hex);
+		if ((currentlen) + (linelen) >= destSize)
+			RETINT(currentlen);
+		strcat(dest, line);
+		currentlen += linelen;
+	}
+	RETINT(currentlen);
+
+Away:
+	if (line)
+		vfree(line);
+	return rc;
+}
+EXPORT_SYMBOL_GPL(hexDumpWordsToBuffer);
+
+
+
+int myPrintkHexDump(char *myDrvName,
+		    char *devname,
+		    char *prefix,
+		    char *src,
+		    int srcLen,
+		    int bytesToDumpPerLine)
+{
+	int i = 0;
+	int pos = 0;
+	char printable[bytesToDumpPerLine + 1];
+	char hex[(bytesToDumpPerLine*3) + 1];
+	char *line = NULL;
+	int linesize = 1000;
+	int linelen = 0;
+	int currentlen = 0;
+	char emptystring[] = "";
+	char *pfx = prefix;
+	int baseaddr = 0;
+	int rc = 0;
+	int linecount = 0;
+
+	line = vmalloc(linesize);
+	if (line == NULL)
+		RETINT(currentlen);
+
+	if (pfx == NULL || (strlen(pfx) > 50))
+		pfx = emptystring;
+	memset(hex, ' ', bytesToDumpPerLine * 3);
+	hex[bytesToDumpPerLine * 3] = '\0';
+	memset(printable, ' ', bytesToDumpPerLine);
+	printable[bytesToDumpPerLine] = '\0';
+
+	for (i = 0; i < srcLen; i++) {
+		pos = i % bytesToDumpPerLine;
+		if ((pos == 0) && (i > 0)) {
+			hex[bytesToDumpPerLine*3] = '\0';
+			linelen = sprintf(line, "%s%-6.6x %s %s",
+					  pfx, baseaddr, hex, printable);
+			myprintk(myDrvName, devname, KERN_INFO "%s", line);
+			currentlen += linelen;
+			linecount++;
+			if ((linecount % 50) == 0)
+				SLEEPJIFFIES(10);
+			memset(hex, ' ', bytesToDumpPerLine*3);
+			memset(printable, ' ', bytesToDumpPerLine);
+			baseaddr = i;
+		}
+		sprintf(hex + (pos * 3), "%-2.2x ", (uint8_t)(src[i]));
+		*(hex + (pos * 3) + 3) = ' ';  /* get rid of null */
+		if (((uint8_t)(src[i]) >= ' ') && (uint8_t)(src[i]) < 127)
+			printable[pos] = src[i];
+		else
+			printable[pos] = '.';
+	}
+	pos = i%bytesToDumpPerLine;
+	if (i > 0) {
+		hex[bytesToDumpPerLine*3] = '\0';
+		linelen = sprintf(line, "%s%-6.6x %s %s",
+				  pfx, baseaddr, hex, printable);
+		myprintk(myDrvName, devname, KERN_INFO "%s", line);
+		currentlen += linelen;
+	}
+	RETINT(currentlen);
+
+Away:
+	if (line)
+		vfree(line);
+	return rc;
+}
+
+
+
+/** Given as input a number of seconds in #seconds, creates text describing
+    the time within #s.  Also breaks down the number of seconds into component
+    days, hours, minutes, and seconds, and stores to *#days, *#hours,
+    *#minutes, and *#secondsx.
+ *  @param seconds input number of seconds
+ *  @param days    points to a long value where the days component for the
+ *                 days+hours+minutes+seconds representation of #seconds will
+ *                 be stored
+ *  @param hours   points to a long value where the hours component for the
+ *                 days+hours+minutes+seconds representation of #seconds will
+ *                 be stored
+ *  @param minutes points to a long value where the minutes component for the
+ *                 days+hours+minutes+seconds representation of #seconds will
+ *                 be stored
+ *  @param secondsx points to a long value where the seconds component for the
+ *                 days+hours+minutes+seconds representation of #seconds will
+ *                 be stored
+ *  @param s       points to a character buffer where a text representation of
+ *		   the #seconds value will be stored.  This buffer MUST be
+ *		   large enough to hold the resulting string; to be safe it
+ *		   should be at least 100 bytes long.
+ */
+void expandSeconds(time_t seconds, long *days, long *hours, long *minutes,
+		   long *secondsx, char *s)
+{
+	BOOL started = FALSE;
+	char buf[99];
+
+	*days = seconds / (60*60*24);
+	seconds -= ((*days)*(60*60*24));
+	*hours = seconds / (60*60);
+	seconds -= ((*hours)*(60*60));
+	*minutes = seconds/60;
+	seconds -= ((*minutes)*60);
+	*secondsx = (long)seconds;
+	if (s == NULL)
+		RETVOID;
+	s[0] = '\0';
+	if (*days > 0) {
+		sprintf(buf, "%lu day", *days);
+		strcat(s, buf);
+		if (*days != 1)
+			strcat(s, "s");
+		started = TRUE;
+	}
+	if ((*hours > 0) || started) {
+		if (started)
+			strcat(s, ", ");
+		sprintf(buf, "%lu hour", *hours);
+		strcat(s, buf);
+		if (*hours != 1)
+			strcat(s, "s");
+		started = TRUE;
+	}
+	if ((*minutes > 0) || started) {
+		if (started)
+			strcat(s, ", ");
+		sprintf(buf, "%lu minute", *minutes);
+		strcat(s, buf);
+		if (*minutes != 1)
+			strcat(s, "s");
+		started = TRUE;
+	}
+	if (started)
+		strcat(s, ", ");
+	sprintf(buf, "%lu second", *secondsx);
+	strcat(s, buf);
+	if (*secondsx != 1)
+		strcat(s, "s");
+
+Away:
+	return;
+}
+
+
+
+/** Initialize a #MESSAGEQ for use (initially it will be empty, of course).
+ *  @param q               the #MESSAGEQ to initialize
+ *  @ingroup messageq
+ */
+void initMessageQ(MESSAGEQ *q)
+{
+	q->qHead = NULL;
+	q->qTail = NULL;
+	sema_init(&q->nQEntries, 0);   /* will block initially */
+	spin_lock_init(&q->queueLock);
+}
+
+
+
+/** Initialize #p with your data structure in #data,
+ *  so you can later place #p onto a #MESSAGEQ.
+ *  @param p               the queue entry that will house your data structure
+ *  @param data            a pointer to your data structure that you want
+ *                         to queue
+ *  @ingroup messageq
+ */
+void initMessageQEntry(MESSAGEQENTRY *p, void *data)
+{
+	p->data = data;
+	p->qNext = NULL;
+	p->qPrev = NULL;
+}
+
+
+
+MESSAGEQENTRY *dequeueMessageGuts(MESSAGEQ *q, BOOL canBlock)
+{
+	MESSAGEQENTRY *pEntry = NULL;
+	MESSAGEQENTRY *rc = NULL;
+	BOOL locked = FALSE;
+	ulong flags = 0;
+	int res = 0;
+
+	if (canBlock) {
+		/* wait for non-empty q */
+		res = down_interruptible(&q->nQEntries);
+		if (signal_pending(current)) {
+			DEBUGDRV("got signal in dequeueMessage");
+			RETPTR(NULL);
+		}
+	} else if (down_trylock(&q->nQEntries))
+		RETPTR(NULL);
+	spin_lock_irqsave(&q->queueLock, flags);
+	locked = TRUE;
+#ifdef PARANOID
+	if (q->qHead == NULL) {
+		HUHDRV("unexpected empty queue in getQueue");
+		RETPTR(NULL);
+	}
+#endif
+	pEntry = q->qHead;
+	if (pEntry == q->qTail) {
+		/* only 1 item in the queue */
+		q->qHead = NULL;
+		q->qTail = NULL;
+	} else {
+		q->qHead = pEntry->qNext;
+		q->qHead->qPrev = NULL;
+	}
+	RETPTR(pEntry);
+Away:
+	if (locked) {
+		spin_unlock_irqrestore(&q->queueLock, flags);
+		locked = FALSE;
+	}
+	return rc;
+}
+
+
+
+/** Remove the next message at the head of the FIFO queue, and return it.
+ *  Wait for the queue to become non-empty if it is empty when this
+ *  function is called.
+ *  @param q               the queue where the message is to be obtained from
+ *  @return                the queue entry obtained from the head of the
+ *                         FIFO queue, or NULL iff a signal was received
+ *                         while waiting for the queue to become non-empty
+ *  @ingroup messageq
+ */
+MESSAGEQENTRY *dequeueMessage(MESSAGEQ *q)
+{
+	return dequeueMessageGuts(q, TRUE);
+}
+
+
+
+/** Remove the next message at the head of the FIFO queue, and return it.
+ *  This function will never block (it returns NULL instead).
+ *  @param q               the queue where the message is to be obtained from
+ *  @return                the queue entry obtained from the head of the
+ *                         FIFO queue, or NULL iff the queue is empty.
+ *  @ingroup messageq
+ */
+MESSAGEQENTRY *dequeueMessageNoBlock(MESSAGEQ *q)
+{
+	return dequeueMessageGuts(q, FALSE);
+}
+
+
+
+/** Add an entry to a FIFO queue.
+ *  @param q               the queue where the entry is to be added
+ *  @param pEntry          the entry you want to add to the queue
+ *  @ingroup messageq
+ */
+void enqueueMessage(MESSAGEQ *q, MESSAGEQENTRY *pEntry)
+{
+	BOOL locked = FALSE;
+	ulong flags = 0;
+
+	spin_lock_irqsave(&q->queueLock, flags);
+	locked = TRUE;
+	if (q->qHead == NULL) {
+#ifdef PARANOID
+		if (q->qTail != NULL) {
+			HUHDRV("qHead/qTail not consistent");
+			RETVOID;
+		}
+#endif
+		q->qHead = pEntry;
+		q->qTail = pEntry;
+		pEntry->qNext = NULL;
+		pEntry->qPrev = NULL;
+	} else {
+#ifdef PARANOID
+		if (q->qTail == NULL) {
+			HUHDRV("qTail should not be NULL here");
+			RETVOID;
+		}
+#endif
+		q->qTail->qNext = pEntry;
+		pEntry->qPrev = q->qTail;
+		pEntry->qNext = NULL;
+		q->qTail = pEntry;
+	}
+	spin_unlock_irqrestore(&q->queueLock, flags);
+	locked = FALSE;
+	up(&q->nQEntries);
+	RETVOID;
+Away:
+	if (locked) {
+		spin_unlock_irqrestore(&q->queueLock, flags);
+		locked = FALSE;
+	}
+	return;
+}
+
+
+
+/** Return the number of entries in the queue.
+ *  @param q               the queue to be examined
+ *  @return                the number of entries on #q
+ *  @ingroup messageq
+ */
+size_t getQueueCount(MESSAGEQ *q)
+{
+	return (size_t)__sync_fetch_and_add(&(q->nQEntries.count), 0);
+}
+
+
+
+/** Return the number of processes waiting in a standard wait queue.
+ *  @param q               the pointer to the wait queue to be
+ *                         examined
+ *  @return                the number of waiters
+ *  @ingroup internal
+ */
+int waitQueueLen(wait_queue_head_t *q)
+{
+	struct list_head *x;
+	int count = 0;
+	list_for_each(x, &(q->task_list))
+		count++;
+	return count;
+}
+
+
+
+/** Display information about the processes on a standard wait queue.
+ *  @param q               the pointer to the wait queue to be
+ *                         examined
+ *  @ingroup internal
+ */
+void debugWaitQ(wait_queue_head_t *q)
+{
+	DEBUGDRV("task_list.next= %-8.8x",
+		 ((struct __wait_queue_head *)(q))->task_list.next);
+	DEBUGDRV("task_list.prev= %-8.8x",
+		 ((struct __wait_queue_head *)(q))->task_list.prev);
+}
+
+
+
+/** Print the hexadecimal contents of a data buffer to a supplied print buffer.
+ *  @param dest               the print buffer where text characters will
+ *			      be written
+ *  @param destSize           the maximum number of bytes that can be written
+ *			      to #dest
+ *  @param src                the buffer that contains the data that is to be
+ *			      hex-dumped
+ *  @param srcLen             the number of bytes at #src to be hex-dumped
+ *  @param bytesToDumpPerLine output will be formatted such that at most
+ *			      this many of the input data bytes will be
+ *			      represented on each line of output
+ *  @return                   the number of text characters written to #dest
+ *                            (not including the trailing '\0' byte)
+ *  @ingroup internal
+ */
+int hexDumpToBuffer(char *dest, int destSize, char *prefix, char *src,
+		    int srcLen, int bytesToDumpPerLine)
+{
+	int i = 0;
+	int pos = 0;
+	char printable[bytesToDumpPerLine + 1];
+	char hex[(bytesToDumpPerLine * 3) + 1];
+	char *line = NULL;
+	int linesize = 1000;
+	int linelen = 0;
+	int currentlen = 0;
+	char emptystring[] = "";
+	char *pfx = prefix;
+	int baseaddr = 0;
+	int rc = 0;
+
+	line = vmalloc(linesize);
+	if (line == NULL)
+		RETINT(currentlen);
+
+	if (pfx == NULL || (strlen(pfx) > 50))
+		pfx = emptystring;
+	memset(hex, ' ', bytesToDumpPerLine * 3);
+	hex[bytesToDumpPerLine * 3] = '\0';
+	memset(printable, ' ', bytesToDumpPerLine);
+	printable[bytesToDumpPerLine] = '\0';
+	if (destSize > 0)
+		dest[0] = '\0';
+
+	for (i = 0; i < srcLen; i++) {
+		pos = i % bytesToDumpPerLine;
+		if ((pos == 0) && (i > 0)) {
+			hex[bytesToDumpPerLine*3] = '\0';
+			linelen = sprintf(line, "%s%-6.6x %s %s\n", pfx,
+					  baseaddr, hex, printable);
+			if ((currentlen) + (linelen) >= destSize)
+				RETINT(currentlen);
+			strcat(dest, line);
+			currentlen += linelen;
+			memset(hex, ' ', bytesToDumpPerLine * 3);
+			memset(printable, ' ', bytesToDumpPerLine);
+			baseaddr = i;
+		}
+		sprintf(hex + (pos * 3), "%-2.2x ", (uint8_t)(src[i]));
+		*(hex + (pos * 3) + 3) = ' ';  /* get rid of null */
+		if (((uint8_t)(src[i]) >= ' ') && (uint8_t)(src[i]) < 127)
+			printable[pos] = src[i];
+		else
+			printable[pos] = '.';
+	}
+	pos = i%bytesToDumpPerLine;
+	if (i > 0) {
+		hex[bytesToDumpPerLine * 3] = '\0';
+		linelen = sprintf(line, "%s%-6.6x %s %s\n",
+				  pfx, baseaddr, hex, printable);
+		if ((currentlen) + (linelen) >= destSize)
+			RETINT(currentlen);
+		strcat(dest, line);
+		currentlen += linelen;
+	}
+	RETINT(currentlen);
+
+Away:
+	if (line)
+		vfree(line);
+	return rc;
+}
+EXPORT_SYMBOL_GPL(hexDumpToBuffer);
+
+
+/** Callers to interfaces that set __GFP_NORETRY flag below
+ *  must check for a NULL (error) result as we are telling the
+ *  kernel interface that it is okay to fail.
+ */
+
+void *kmalloc_kernel(size_t siz)
+{
+	return kmalloc(siz, GFP_KERNEL | __GFP_NORETRY);
+}
+
+void *kmalloc_kernel_dma(size_t siz)
+{
+	return kmalloc(siz, GFP_KERNEL | __GFP_NORETRY|GFP_DMA);
+}
+
+void kfree_kernel(const void *p, size_t siz)
+{
+	kfree(p);
+}
+
+void *vmalloc_kernel(size_t siz)
+{
+	return vmalloc((unsigned long)(siz));
+}
+
+void vfree_kernel(const void *p, size_t siz)
+{
+	vfree((void *)(p));
+}
+
+void *pgalloc_kernel(size_t siz)
+{
+	return (void *)__get_free_pages(GFP_KERNEL|__GFP_NORETRY,
+				       get_order(siz));
+}
+
+void pgfree_kernel(const void *p, size_t siz)
+{
+	free_pages((ulong)(p), get_order(siz));
+}
+
+
+
+/*  Use these handy-dandy seq_file_xxx functions if you want to call some
+ *  functions that write stuff into a seq_file, but you actually just want
+ *  to dump that output into a buffer.  Use them as follows:
+ *  - call seq_file_new_buffer to create the seq_file (you supply the buf)
+ *  - call whatever functions you want that take a seq_file as an argument
+ *    (the buf you supplied will get the output data)
+ *  - call seq_file_done_buffer to dispose of your seq_file
+ */
+struct seq_file *seq_file_new_buffer(void *buf, size_t buf_size)
+{
+	struct seq_file *rc = NULL;
+	struct seq_file *m = kmalloc_kernel(sizeof(struct seq_file));
+
+	if (m == NULL)
+		RETPTR(NULL);
+	memset(m, 0, sizeof(struct seq_file));
+	m->buf = buf;
+	m->size = buf_size;
+	RETPTR(m);
+Away:
+	if (rc == NULL) {
+		seq_file_done_buffer(m);
+		m = NULL;
+	}
+	return rc;
+}
+EXPORT_SYMBOL_GPL(seq_file_new_buffer);
+
+
+
+void seq_file_done_buffer(struct seq_file *m)
+{
+	if (!m)
+		return;
+	kfree(m);
+}
+EXPORT_SYMBOL_GPL(seq_file_done_buffer);
+
+
+
+void seq_hexdump(struct seq_file *seq, u8 *pfx, void *buf, ulong nbytes)
+{
+	int fmtbufsize = 100 * COVQ(nbytes, 16);
+	char *fmtbuf = NULL;
+	int i = 0;
+	if (buf == NULL) {
+		seq_printf(seq, "%s<NULL>\n", pfx);
+		return;
+	}
+	fmtbuf = kmalloc_kernel(fmtbufsize);
+	if (fmtbuf == NULL)
+		return;
+	hexDumpToBuffer(fmtbuf, fmtbufsize, pfx, (char *)(buf), nbytes, 16);
+	for (i = 0; fmtbuf[i] != '\0'; i++)
+		seq_printf(seq, "%c", fmtbuf[i]);
+	kfree(fmtbuf);
+}
diff --git a/drivers/staging/usbip/stub_dev.c b/drivers/staging/usbip/stub_dev.c
index b0bfd34..60a3e3f 100644
--- a/drivers/staging/usbip/stub_dev.c
+++ b/drivers/staging/usbip/stub_dev.c
@@ -87,13 +87,16 @@
 	int sockfd = 0;
 	struct socket *socket;
 	ssize_t err = -EINVAL;
+	int rv;
 
 	if (!sdev) {
 		dev_err(dev, "sdev is null\n");
 		return -ENODEV;
 	}
 
-	sscanf(buf, "%d", &sockfd);
+	rv = sscanf(buf, "%d", &sockfd);
+	if (rv != 1)
+		return -EINVAL;
 
 	if (sockfd != -1) {
 		dev_info(dev, "stub up\n");
diff --git a/drivers/staging/usbip/uapi/usbip.h b/drivers/staging/usbip/uapi/usbip.h
new file mode 100644
index 0000000..fa5db30
--- /dev/null
+++ b/drivers/staging/usbip/uapi/usbip.h
@@ -0,0 +1,26 @@
+/*
+ *	usbip.h
+ *
+ *	USBIP uapi defines and function prototypes etc.
+*/
+
+#ifndef _UAPI_LINUX_USBIP_H
+#define _UAPI_LINUX_USBIP_H
+
+/* usbip device status - exported in usbip device sysfs status */
+enum usbip_device_status {
+	/* sdev is available. */
+	SDEV_ST_AVAILABLE = 0x01,
+	/* sdev is now used. */
+	SDEV_ST_USED,
+	/* sdev is unusable because of a fatal error. */
+	SDEV_ST_ERROR,
+
+	/* vdev does not connect a remote device. */
+	VDEV_ST_NULL,
+	/* vdev is used, but the USB address is not assigned yet */
+	VDEV_ST_NOTASSIGNED,
+	VDEV_ST_USED,
+	VDEV_ST_ERROR
+};
+#endif /* _UAPI_LINUX_USBIP_H */
diff --git a/drivers/staging/usbip/usbip_common.h b/drivers/staging/usbip/usbip_common.h
index 7e6c543..732fb63 100644
--- a/drivers/staging/usbip/usbip_common.h
+++ b/drivers/staging/usbip/usbip_common.h
@@ -29,6 +29,7 @@
 #include <linux/types.h>
 #include <linux/usb.h>
 #include <linux/wait.h>
+#include "uapi/usbip.h"
 
 #define USBIP_VERSION "1.0.0"
 
@@ -235,22 +236,6 @@
 	USBIP_STUB,
 };
 
-enum usbip_status {
-	/* sdev is available. */
-	SDEV_ST_AVAILABLE = 0x01,
-	/* sdev is now used. */
-	SDEV_ST_USED,
-	/* sdev is unusable because of a fatal error. */
-	SDEV_ST_ERROR,
-
-	/* vdev does not connect a remote device. */
-	VDEV_ST_NULL,
-	/* vdev is used, but the USB address is not assigned yet */
-	VDEV_ST_NOTASSIGNED,
-	VDEV_ST_USED,
-	VDEV_ST_ERROR
-};
-
 /* event handler */
 #define USBIP_EH_SHUTDOWN	(1 << 0)
 #define USBIP_EH_BYE		(1 << 1)
@@ -271,7 +256,7 @@
 /* a common structure for stub_device and vhci_device */
 struct usbip_device {
 	enum usbip_side side;
-	enum usbip_status status;
+	enum usbip_device_status status;
 
 	/* lock for status */
 	spinlock_t lock;
diff --git a/drivers/staging/usbip/userspace/libsrc/usbip_common.h b/drivers/staging/usbip/userspace/libsrc/usbip_common.h
index 2cb81b3..5af59d4 100644
--- a/drivers/staging/usbip/userspace/libsrc/usbip_common.h
+++ b/drivers/staging/usbip/userspace/libsrc/usbip_common.h
@@ -15,6 +15,7 @@
 #include <syslog.h>
 #include <unistd.h>
 #include <linux/usb/ch9.h>
+#include "../../uapi/usbip.h"
 
 #ifndef USBIDS_FILE
 #define USBIDS_FILE "/usr/share/hwdata/usb.ids"
@@ -77,23 +78,6 @@
 		abort();				\
 	} while (0)
 
-/* FIXME: how to sync with drivers/usbip_common.h ? */
-enum usbip_device_status {
-	/* sdev is available. */
-	SDEV_ST_AVAILABLE = 0x01,
-	/* sdev is now used. */
-	SDEV_ST_USED,
-	/* sdev is unusable because of a fatal error. */
-	SDEV_ST_ERROR,
-
-	/* vdev does not connect a remote device. */
-	VDEV_ST_NULL,
-	/* vdev is used, but the USB address is not assigned yet */
-	VDEV_ST_NOTASSIGNED,
-	VDEV_ST_USED,
-	VDEV_ST_ERROR
-};
-
 struct usbip_usb_interface {
 	uint8_t bInterfaceClass;
 	uint8_t bInterfaceSubClass;
diff --git a/drivers/staging/usbip/userspace/libsrc/usbip_host_driver.c b/drivers/staging/usbip/userspace/libsrc/usbip_host_driver.c
index 86a8675..35b2f5b 100644
--- a/drivers/staging/usbip/userspace/libsrc/usbip_host_driver.c
+++ b/drivers/staging/usbip/userspace/libsrc/usbip_host_driver.c
@@ -101,6 +101,7 @@
 static struct usbip_exported_device *usbip_exported_device_new(char *sdevpath)
 {
 	struct usbip_exported_device *edev = NULL;
+	struct usbip_exported_device *edev_old;
 	size_t size;
 	int i;
 
@@ -126,8 +127,10 @@
 	size = sizeof(*edev) + edev->udev.bNumInterfaces *
 		sizeof(struct usbip_usb_interface);
 
+	edev_old = edev;
 	edev = realloc(edev, size);
 	if (!edev) {
+		edev = edev_old;
 		dbg("realloc failed");
 		goto err;
 	}
diff --git a/drivers/staging/usbip/userspace/libsrc/vhci_driver.c b/drivers/staging/usbip/userspace/libsrc/vhci_driver.c
index f4bfefe..d80d37c 100644
--- a/drivers/staging/usbip/userspace/libsrc/vhci_driver.c
+++ b/drivers/staging/usbip/userspace/libsrc/vhci_driver.c
@@ -545,7 +545,7 @@
 		return -1;
 	}
 
-	snprintf(buff, sizeof(buff), "%u %u %u %u",
+	snprintf(buff, sizeof(buff), "%u %d %u %u",
 			port, sockfd, devid, speed);
 	dbg("writing: %s", buff);
 
diff --git a/drivers/staging/vt6656/device.h b/drivers/staging/vt6656/device.h
index e5f0be3..e2abe3d 100644
--- a/drivers/staging/vt6656/device.h
+++ b/drivers/staging/vt6656/device.h
@@ -158,10 +158,10 @@
 /*
  * Enum of context types for SendPacket
  */
-typedef enum _CONTEXT_TYPE {
-    CONTEXT_DATA_PACKET = 1,
-    CONTEXT_MGMT_PACKET
-} CONTEXT_TYPE;
+enum {
+	CONTEXT_DATA_PACKET = 1,
+	CONTEXT_MGMT_PACKET
+};
 
 /* RCB (Receive Control Block) */
 struct vnt_rcb {
@@ -180,9 +180,7 @@
 	struct sk_buff *pPacket;
 	struct urb *pUrb;
 	unsigned int uBufLen;
-	CONTEXT_TYPE Type;
-	struct ethhdr sEthHeader;
-	void *Next;
+	u8 type;
 	bool bBoolInUse;
 	unsigned char Data[MAX_TOTAL_SIZE_WITH_ALL_HEADERS];
 };
@@ -206,12 +204,10 @@
 /*
  * Structure to keep track of USB interrupt packets
  */
-typedef struct {
-    unsigned int            uDataLen;
-    u8 *           pDataBuf;
-  /* struct urb *pUrb; */
-    bool            bInUse;
-} INT_BUFFER, *PINT_BUFFER;
+struct vnt_interrupt_buffer {
+	u8 *data_buf;
+	bool in_use;
+};
 
 /*++ NDIS related */
 
@@ -280,16 +276,6 @@
     PMKID_CANDIDATE CandidateList[MAX_PMKIDLIST];
 } SPMKIDCandidateEvent, *PSPMKIDCandidateEvent;
 
-/*++ 802.11h related */
-#define MAX_QUIET_COUNT     8
-
-typedef struct tagSQuietControl {
-    bool        bEnable;
-    u32       dwStartTime;
-    u8        byPeriod;
-    u16        wDuration;
-} SQuietControl, *PSQuietControl;
-
 /* The receive duplicate detection cache entry */
 typedef struct tagSCacheEntry{
     u16        wFmSequence;
@@ -369,8 +355,6 @@
 
 	OPTIONS sOpts;
 
-	struct tasklet_struct CmdWorkItem;
-	struct tasklet_struct EventWorkItem;
 	struct work_struct read_work_item;
 	struct work_struct rx_mng_work_item;
 
@@ -420,28 +404,11 @@
 	struct vnt_tx_pkt_info pkt_info[16];
 
 	/* Variables to track resources for the Interrupt In Pipe */
-	INT_BUFFER intBuf;
-	int bEventAvailable;
+	struct vnt_interrupt_buffer int_buf;
 
 	/* default config from file by user setting */
 	DEFAULT_CONFIG config_file;
 
-	/* Statistic for USB */
-	unsigned long ulBulkInPosted;
-	unsigned long ulBulkInError;
-	unsigned long ulBulkInContCRCError;
-	unsigned long ulBulkInBytesRead;
-
-	unsigned long ulBulkOutPosted;
-	unsigned long ulBulkOutError;
-	unsigned long ulBulkOutContCRCError;
-	unsigned long ulBulkOutBytesWrite;
-
-	unsigned long ulIntInPosted;
-	unsigned long ulIntInError;
-	unsigned long ulIntInContCRCError;
-	unsigned long ulIntInBytesRead;
-
 	/* Version control */
 	u16 wFirmwareVersion;
 	u8 byLocalID;
@@ -462,11 +429,6 @@
 	int bExistSWNetAddr;
 
 	/* Maintain statistical debug info. */
-	unsigned long packetsReceived;
-	unsigned long packetsReceivedDropped;
-	unsigned long packetsReceivedOverflow;
-	unsigned long packetsSent;
-	unsigned long packetsSentDropped;
 	unsigned long SendContextsInUse;
 	unsigned long RcvBuffersInUse;
 
@@ -791,5 +753,6 @@
                                  (fMP_DISCONNECTED | fMP_RESET_IN_PROGRESS | fMP_HALT_IN_PROGRESS | fMP_INIT_IN_PROGRESS | fMP_SURPRISE_REMOVED)) == 0)
 
 int device_alloc_frag_buf(struct vnt_private *, PSDeFragControlBlock pDeF);
+void vnt_configure_filter(struct vnt_private *);
 
 #endif
diff --git a/drivers/staging/vt6656/dpc.c b/drivers/staging/vt6656/dpc.c
index 03351e7..4ccaa7e 100644
--- a/drivers/staging/vt6656/dpc.c
+++ b/drivers/staging/vt6656/dpc.c
@@ -1227,14 +1227,13 @@
     if (is_multicast_ether_addr((u8 *)(skb->data+cbHeaderOffset))) {
        if (pMgmt->sNodeDBTable[0].bPSEnable) {
 
-           skbcpy = dev_alloc_skb((int)pDevice->rx_buf_sz);
+	    skbcpy = netdev_alloc_skb(pDevice->dev, pDevice->rx_buf_sz);
 
         // if any node in PS mode, buffer packet until DTIM.
            if (skbcpy == NULL) {
                DBG_PRT(MSG_LEVEL_NOTICE, KERN_INFO "relay multicast no skb available \n");
            }
            else {
-               skbcpy->dev = pDevice->dev;
                skbcpy->len = FrameSize;
                memcpy(skbcpy->data, skb->data+cbHeaderOffset, FrameSize);
                skb_queue_tail(&(pMgmt->sNodeDBTable[0].sTxPSQueue), skbcpy);
@@ -1295,63 +1294,66 @@
 
 void RXvWorkItem(struct work_struct *work)
 {
-	struct vnt_private *pDevice =
+	struct vnt_private *priv =
 		container_of(work, struct vnt_private, read_work_item);
-	int ntStatus;
-	struct vnt_rcb *pRCB = NULL;
+	int status;
+	struct vnt_rcb *rcb = NULL;
 
-	if (pDevice->Flags & fMP_DISCONNECTED)
+	if (priv->Flags & fMP_DISCONNECTED)
 		return;
 
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->Rx Polling Thread\n");
-    spin_lock_irq(&pDevice->lock);
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->Rx Polling Thread\n");
 
-    while ((pDevice->Flags & fMP_POST_READS) &&
-            MP_IS_READY(pDevice) &&
-            (pDevice->NumRecvFreeList != 0) ) {
-        pRCB = pDevice->FirstRecvFreeList;
-        pDevice->NumRecvFreeList--;
-        DequeueRCB(pDevice->FirstRecvFreeList, pDevice->LastRecvFreeList);
-        ntStatus = PIPEnsBulkInUsbRead(pDevice, pRCB);
-    }
-    pDevice->bIsRxWorkItemQueued = false;
-    spin_unlock_irq(&pDevice->lock);
+	spin_lock_irq(&priv->lock);
 
-}
+	while ((priv->Flags & fMP_POST_READS) && MP_IS_READY(priv) &&
+			(priv->NumRecvFreeList != 0)) {
+		rcb = priv->FirstRecvFreeList;
 
-void RXvFreeRCB(struct vnt_rcb *pRCB, int bReAllocSkb)
-{
-	struct vnt_private *pDevice = pRCB->pDevice;
+		priv->NumRecvFreeList--;
 
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->RXvFreeRCB\n");
+		DequeueRCB(priv->FirstRecvFreeList, priv->LastRecvFreeList);
 
-	if (bReAllocSkb == false) {
-		kfree_skb(pRCB->skb);
-		bReAllocSkb = true;
+		status = PIPEnsBulkInUsbRead(priv, rcb);
 	}
 
-    if (bReAllocSkb == true) {
-        pRCB->skb = dev_alloc_skb((int)pDevice->rx_buf_sz);
-        // todo error handling
-        if (pRCB->skb == NULL) {
-            DBG_PRT(MSG_LEVEL_ERR,KERN_ERR" Failed to re-alloc rx skb\n");
-        }else {
-            pRCB->skb->dev = pDevice->dev;
-        }
-    }
-    //
-    // Insert the RCB back in the Recv free list
-    //
-    EnqueueRCB(pDevice->FirstRecvFreeList, pDevice->LastRecvFreeList, pRCB);
-    pDevice->NumRecvFreeList++;
+	priv->bIsRxWorkItemQueued = false;
 
-    if ((pDevice->Flags & fMP_POST_READS) && MP_IS_READY(pDevice) &&
-        (pDevice->bIsRxWorkItemQueued == false) ) {
+	spin_unlock_irq(&priv->lock);
+}
 
-        pDevice->bIsRxWorkItemQueued = true;
-	schedule_work(&pDevice->read_work_item);
-    }
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"<----RXFreeRCB %d %d\n",pDevice->NumRecvFreeList, pDevice->NumRecvMngList);
+void RXvFreeRCB(struct vnt_rcb *rcb, int re_alloc_skb)
+{
+	struct vnt_private *priv = rcb->pDevice;
+
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->RXvFreeRCB\n");
+
+	if (re_alloc_skb == false) {
+		kfree_skb(rcb->skb);
+		re_alloc_skb = true;
+	}
+
+	if (re_alloc_skb == true) {
+		rcb->skb = netdev_alloc_skb(priv->dev, priv->rx_buf_sz);
+		/* TODO error handling */
+		if (!rcb->skb) {
+			DBG_PRT(MSG_LEVEL_ERR, KERN_ERR
+				" Failed to re-alloc rx skb\n");
+		}
+	}
+
+	/* Insert the RCB back in the Recv free list */
+	EnqueueRCB(priv->FirstRecvFreeList, priv->LastRecvFreeList, rcb);
+	priv->NumRecvFreeList++;
+
+	if ((priv->Flags & fMP_POST_READS) && MP_IS_READY(priv) &&
+			(priv->bIsRxWorkItemQueued == false)) {
+		priv->bIsRxWorkItemQueued = true;
+		schedule_work(&priv->read_work_item);
+	}
+
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"<----RXFreeRCB %d %d\n",
+			priv->NumRecvFreeList, priv->NumRecvMngList);
 }
 
 void RXvMngWorkItem(struct work_struct *work)
diff --git a/drivers/staging/vt6656/int.c b/drivers/staging/vt6656/int.c
index 34c4528..cca56b2 100644
--- a/drivers/staging/vt6656/int.c
+++ b/drivers/staging/vt6656/int.c
@@ -84,7 +84,7 @@
 
 	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->s_nsInterruptProcessData\n");
 
-	int_data = (struct vnt_interrupt_data *)priv->intBuf.pDataBuf;
+	int_data = (struct vnt_interrupt_data *)priv->int_buf.data_buf;
 
 	if (int_data->tsr0 & TSR_VALID) {
 		if (int_data->tsr0 & (TSR_TMO | TSR_RETRYTMO))
@@ -178,8 +178,8 @@
 			bScheduleCommand((void *) priv,
 					WLAN_CMD_RADIO,
 					NULL);
-	priv->intBuf.uDataLen = 0;
-	priv->intBuf.bInUse = false;
+
+	priv->int_buf.in_use = false;
 
 	stats->tx_errors = priv->wstats.discard.retries;
 	stats->tx_dropped = priv->wstats.discard.retries;
diff --git a/drivers/staging/vt6656/main_usb.c b/drivers/staging/vt6656/main_usb.c
index bea1ad9..7dd885f 100644
--- a/drivers/staging/vt6656/main_usb.c
+++ b/drivers/staging/vt6656/main_usb.c
@@ -749,44 +749,47 @@
 	return rc;
 }
 
-static void device_free_tx_bufs(struct vnt_private *pDevice)
+static void device_free_tx_bufs(struct vnt_private *priv)
 {
-	struct vnt_usb_send_context *pTxContext;
-    int ii;
-
-    for (ii = 0; ii < pDevice->cbTD; ii++) {
-
-        pTxContext = pDevice->apTD[ii];
-	/* deallocate URBs */
-        if (pTxContext->pUrb) {
-            usb_kill_urb(pTxContext->pUrb);
-            usb_free_urb(pTxContext->pUrb);
-        }
-        kfree(pTxContext);
-    }
-    return;
-}
-
-static void device_free_rx_bufs(struct vnt_private *pDevice)
-{
-	struct vnt_rcb *pRCB;
+	struct vnt_usb_send_context *tx_context;
 	int ii;
 
-    for (ii = 0; ii < pDevice->cbRD; ii++) {
+	for (ii = 0; ii < priv->cbTD; ii++) {
+		tx_context = priv->apTD[ii];
+		/* deallocate URBs */
+		if (tx_context->pUrb) {
+			usb_kill_urb(tx_context->pUrb);
+			usb_free_urb(tx_context->pUrb);
+		}
 
-        pRCB = pDevice->apRCB[ii];
-	/* deallocate URBs */
-        if (pRCB->pUrb) {
-            usb_kill_urb(pRCB->pUrb);
-            usb_free_urb(pRCB->pUrb);
-        }
-	/* deallocate skb */
-        if (pRCB->skb)
-            dev_kfree_skb(pRCB->skb);
-    }
-    kfree(pDevice->pRCBMem);
+		kfree(tx_context);
+	}
 
-    return;
+	return;
+}
+
+static void device_free_rx_bufs(struct vnt_private *priv)
+{
+	struct vnt_rcb *rcb;
+	int ii;
+
+	for (ii = 0; ii < priv->cbRD; ii++) {
+		rcb = priv->apRCB[ii];
+
+		/* deallocate URBs */
+		if (rcb->pUrb) {
+			usb_kill_urb(rcb->pUrb);
+			usb_free_urb(rcb->pUrb);
+		}
+
+		/* deallocate skb */
+		if (rcb->skb)
+			dev_kfree_skb(rcb->skb);
+	}
+
+	kfree(priv->pRCBMem);
+
+	return;
 }
 
 static void usb_device_reset(struct vnt_private *pDevice)
@@ -798,95 +801,109 @@
 	return ;
 }
 
-static void device_free_int_bufs(struct vnt_private *pDevice)
+static void device_free_int_bufs(struct vnt_private *priv)
 {
-    kfree(pDevice->intBuf.pDataBuf);
-    return;
+	kfree(priv->int_buf.data_buf);
+
+	return;
 }
 
-static bool device_alloc_bufs(struct vnt_private *pDevice)
+static bool device_alloc_bufs(struct vnt_private *priv)
 {
-	struct vnt_usb_send_context *pTxContext;
-	struct vnt_rcb *pRCB;
+	struct vnt_usb_send_context *tx_context;
+	struct vnt_rcb *rcb;
 	int ii;
 
-    for (ii = 0; ii < pDevice->cbTD; ii++) {
-
-	pTxContext = kmalloc(sizeof(struct vnt_usb_send_context), GFP_KERNEL);
-        if (pTxContext == NULL) {
-            DBG_PRT(MSG_LEVEL_ERR,KERN_ERR "%s : allocate tx usb context failed\n", pDevice->dev->name);
-            goto free_tx;
-        }
-        pDevice->apTD[ii] = pTxContext;
-	pTxContext->pDevice = (void *) pDevice;
-	/* allocate URBs */
-        pTxContext->pUrb = usb_alloc_urb(0, GFP_ATOMIC);
-        if (pTxContext->pUrb == NULL) {
-            DBG_PRT(MSG_LEVEL_ERR,KERN_ERR "alloc tx urb failed\n");
-            goto free_tx;
-        }
-        pTxContext->bBoolInUse = false;
-    }
-
-    /* allocate RCB mem */
-	pDevice->pRCBMem = kzalloc((sizeof(struct vnt_rcb) * pDevice->cbRD),
+	for (ii = 0; ii < priv->cbTD; ii++) {
+		tx_context = kmalloc(sizeof(struct vnt_usb_send_context),
 								GFP_KERNEL);
-    if (pDevice->pRCBMem == NULL) {
-        DBG_PRT(MSG_LEVEL_ERR,KERN_ERR "%s : alloc rx usb context failed\n", pDevice->dev->name);
-        goto free_tx;
-    }
+		if (tx_context == NULL) {
+			DBG_PRT(MSG_LEVEL_ERR, KERN_ERR
+				"%s : allocate tx usb context failed\n",
+					priv->dev->name);
+			goto free_tx;
+		}
 
-    pDevice->FirstRecvFreeList = NULL;
-    pDevice->LastRecvFreeList = NULL;
-    pDevice->FirstRecvMngList = NULL;
-    pDevice->LastRecvMngList = NULL;
-    pDevice->NumRecvFreeList = 0;
+		priv->apTD[ii] = tx_context;
+		tx_context->pDevice = priv;
 
-	pRCB = (struct vnt_rcb *)pDevice->pRCBMem;
+		/* allocate URBs */
+		tx_context->pUrb = usb_alloc_urb(0, GFP_ATOMIC);
+		if (tx_context->pUrb == NULL) {
+			DBG_PRT(MSG_LEVEL_ERR,
+				KERN_ERR "alloc tx urb failed\n");
+			goto free_tx;
+		}
 
-    for (ii = 0; ii < pDevice->cbRD; ii++) {
-
-        pDevice->apRCB[ii] = pRCB;
-	pRCB->pDevice = (void *) pDevice;
-	/* allocate URBs */
-        pRCB->pUrb = usb_alloc_urb(0, GFP_ATOMIC);
-
-        if (pRCB->pUrb == NULL) {
-            DBG_PRT(MSG_LEVEL_ERR,KERN_ERR" Failed to alloc rx urb\n");
-            goto free_rx_tx;
-        }
-        pRCB->skb = dev_alloc_skb((int)pDevice->rx_buf_sz);
-        if (pRCB->skb == NULL) {
-            DBG_PRT(MSG_LEVEL_ERR,KERN_ERR" Failed to alloc rx skb\n");
-            goto free_rx_tx;
-        }
-        pRCB->skb->dev = pDevice->dev;
-        pRCB->bBoolInUse = false;
-        EnqueueRCB(pDevice->FirstRecvFreeList, pDevice->LastRecvFreeList, pRCB);
-        pDevice->NumRecvFreeList++;
-        pRCB++;
-    }
-
-	pDevice->pInterruptURB = usb_alloc_urb(0, GFP_ATOMIC);
-	if (pDevice->pInterruptURB == NULL) {
-	    DBG_PRT(MSG_LEVEL_ERR,KERN_ERR"Failed to alloc int urb\n");
-	    goto free_rx_tx;
+		tx_context->bBoolInUse = false;
 	}
 
-    pDevice->intBuf.pDataBuf = kmalloc(MAX_INTERRUPT_SIZE, GFP_KERNEL);
-	if (pDevice->intBuf.pDataBuf == NULL) {
-	    DBG_PRT(MSG_LEVEL_ERR,KERN_ERR"Failed to alloc int buf\n");
-	    usb_free_urb(pDevice->pInterruptURB);
-	    goto free_rx_tx;
+	/* allocate RCB mem */
+	priv->pRCBMem = kzalloc((sizeof(struct vnt_rcb) * priv->cbRD),
+								GFP_KERNEL);
+	if (priv->pRCBMem == NULL) {
+		DBG_PRT(MSG_LEVEL_ERR, KERN_ERR
+			"%s : alloc rx usb context failed\n",
+				priv->dev->name);
+		goto free_tx;
 	}
 
-    return true;
+	priv->FirstRecvFreeList = NULL;
+	priv->LastRecvFreeList = NULL;
+	priv->FirstRecvMngList = NULL;
+	priv->LastRecvMngList = NULL;
+	priv->NumRecvFreeList = 0;
+
+	rcb = (struct vnt_rcb *)priv->pRCBMem;
+
+	for (ii = 0; ii < priv->cbRD; ii++) {
+		priv->apRCB[ii] = rcb;
+		rcb->pDevice = priv;
+
+		/* allocate URBs */
+		rcb->pUrb = usb_alloc_urb(0, GFP_ATOMIC);
+		if (rcb->pUrb == NULL) {
+			DBG_PRT(MSG_LEVEL_ERR, KERN_ERR
+				" Failed to alloc rx urb\n");
+			goto free_rx_tx;
+		}
+
+		rcb->skb = netdev_alloc_skb(priv->dev, priv->rx_buf_sz);
+		if (rcb->skb == NULL) {
+			DBG_PRT(MSG_LEVEL_ERR, KERN_ERR
+						" Failed to alloc rx skb\n");
+			goto free_rx_tx;
+		}
+
+		rcb->bBoolInUse = false;
+
+		EnqueueRCB(priv->FirstRecvFreeList,
+						priv->LastRecvFreeList, rcb);
+
+		priv->NumRecvFreeList++;
+		rcb++;
+	}
+
+	priv->pInterruptURB = usb_alloc_urb(0, GFP_ATOMIC);
+	if (priv->pInterruptURB == NULL) {
+		DBG_PRT(MSG_LEVEL_ERR, KERN_ERR"Failed to alloc int urb\n");
+		goto free_rx_tx;
+	}
+
+	priv->int_buf.data_buf = kmalloc(MAX_INTERRUPT_SIZE, GFP_KERNEL);
+	if (priv->int_buf.data_buf == NULL) {
+		DBG_PRT(MSG_LEVEL_ERR, KERN_ERR"Failed to alloc int buf\n");
+		usb_free_urb(priv->pInterruptURB);
+		goto free_rx_tx;
+	}
+
+	return true;
 
 free_rx_tx:
-    device_free_rx_bufs(pDevice);
+	device_free_rx_bufs(priv);
 
 free_tx:
-    device_free_tx_bufs(pDevice);
+	device_free_tx_bufs(priv);
 
 	return false;
 }
@@ -931,13 +948,11 @@
 int device_alloc_frag_buf(struct vnt_private *pDevice,
 		PSDeFragControlBlock pDeF)
 {
+	pDeF->skb = netdev_alloc_skb(pDevice->dev, pDevice->rx_buf_sz);
+	if (!pDeF->skb)
+		return false;
 
-    pDeF->skb = dev_alloc_skb((int)pDevice->rx_buf_sz);
-    if (pDeF->skb == NULL)
-        return false;
-    pDeF->skb->dev = pDevice->dev;
-
-    return true;
+	return true;
 }
 
 static int  device_open(struct net_device *dev)
@@ -974,8 +989,6 @@
 		goto free_all;
 	}
 
-    device_set_multi(pDevice->dev);
-
     /* init for key management */
     KeyvInitTable(pDevice,&pDevice->sKey);
 	memcpy(pDevice->vnt_mgmt.abyMACAddr,
@@ -992,15 +1005,12 @@
 
     vMgrObjectInit(pDevice);
 
-    tasklet_init(&pDevice->EventWorkItem, (void *)INTvWorkItem, (unsigned long)pDevice);
-
 	schedule_delayed_work(&pDevice->second_callback_work, HZ);
 
 	pDevice->int_interval = 100;  /* max 100 microframes */
     pDevice->eEncryptionStatus = Ndis802_11EncryptionDisabled;
 
     pDevice->bIsRxWorkItemQueued = true;
-    pDevice->bEventAvailable = false;
 
    pDevice->bWPADEVUp = false;
      pDevice->bwextstep0 = false;
@@ -1096,8 +1106,6 @@
 	cancel_work_sync(&pDevice->rx_mng_work_item);
 	cancel_work_sync(&pDevice->read_work_item);
 
-    tasklet_kill(&pDevice->EventWorkItem);
-
    pDevice->bRoaming = false;
    pDevice->bIsRoaming = false;
    pDevice->bEnableRoaming = false;
@@ -1349,14 +1357,26 @@
 static void device_set_multi(struct net_device *dev)
 {
 	struct vnt_private *priv = netdev_priv(dev);
+	unsigned long flags;
+
+	if (priv->flags & DEVICE_FLAGS_OPENED) {
+		spin_lock_irqsave(&priv->lock, flags);
+
+		bScheduleCommand(priv, WLAN_CMD_CONFIGURE_FILTER, NULL);
+
+		spin_unlock_irqrestore(&priv->lock, flags);
+	}
+}
+
+void vnt_configure_filter(struct vnt_private *priv)
+{
+	struct net_device *dev = priv->dev;
 	struct vnt_manager *mgmt = &priv->vnt_mgmt;
 	struct netdev_hw_addr *ha;
 	u64 mc_filter = 0;
 	u8 tmp = 0;
 	int rc;
 
-	spin_lock_irq(&priv->lock);
-
 	rc = CONTROLnsRequestIn(priv, MESSAGE_TYPE_READ,
 		MAC_REG_RCR, MESSAGE_REQUEST_MACREG, 1, &tmp);
 	if (rc == 0)
@@ -1403,8 +1423,6 @@
 
 	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO
 				"priv->byRxMode out= %x\n", priv->byRxMode);
-
-	spin_unlock_irq(&priv->lock);
 }
 
 static struct net_device_stats *device_get_stats(struct net_device *dev)
diff --git a/drivers/staging/vt6656/rxtx.c b/drivers/staging/vt6656/rxtx.c
index 92146e5..7083af3 100644
--- a/drivers/staging/vt6656/rxtx.c
+++ b/drivers/staging/vt6656/rxtx.c
@@ -1610,7 +1610,7 @@
     pTX_Buffer->byType = 0x00;
 
     pContext->pPacket = NULL;
-    pContext->Type = CONTEXT_MGMT_PACKET;
+    pContext->type = CONTEXT_MGMT_PACKET;
     pContext->uBufLen = (u16)cbReqCount + 4;  //USB header
 
     if (WLAN_GET_FC_TODS(pMACHeader->frame_control) == 0) {
@@ -1702,7 +1702,7 @@
     pTX_Buffer->byType = 0x01;
 
     pContext->pPacket = NULL;
-    pContext->Type = CONTEXT_MGMT_PACKET;
+    pContext->type = CONTEXT_MGMT_PACKET;
     pContext->uBufLen = (u16)cbReqCount + 4;  //USB header
 
     PIPEnsSendBulkOut(pDevice,pContext);
@@ -2050,7 +2050,7 @@
     pTX_Buffer->byType = 0x00;
 
     pContext->pPacket = skb;
-    pContext->Type = CONTEXT_MGMT_PACKET;
+    pContext->type = CONTEXT_MGMT_PACKET;
     pContext->uBufLen = (u16)cbReqCount + 4;  //USB header
 
     if (WLAN_GET_FC_TODS(pMACHeader->frame_control) == 0) {
@@ -2440,11 +2440,11 @@
     pTX_Buffer->wTxByteCount = (u16)BytesToWrite;
 
     pContext->pPacket = skb;
-    pContext->Type = CONTEXT_DATA_PACKET;
+    pContext->type = CONTEXT_DATA_PACKET;
     pContext->uBufLen = (u16)BytesToWrite + 4 ; //USB header
 
     s_vSaveTxPktInfo(pDevice, (u8)(pTX_Buffer->byPKTNO & 0x0F),
-			&pContext->sEthHeader.h_dest[0],
+			&pDevice->sTxEthHeader.h_dest[0],
 			(u16)(BytesToWrite-uHeaderLen),
 			pTX_Buffer->fifo_head.wFIFOCtl);
 
@@ -2594,11 +2594,11 @@
     pTX_Buffer->wTxByteCount = (u16)BytesToWrite;
 
     pContext->pPacket = NULL;
-    pContext->Type = CONTEXT_DATA_PACKET;
+    pContext->type = CONTEXT_DATA_PACKET;
     pContext->uBufLen = (u16)BytesToWrite + 4 ; //USB header
 
     s_vSaveTxPktInfo(pDevice, (u8)(pTX_Buffer->byPKTNO & 0x0F),
-		&pContext->sEthHeader.h_dest[0],
+		&pDevice->sTxEthHeader.h_dest[0],
 		(u16)(BytesToWrite - uHeaderLen),
 		pTX_Buffer->fifo_head.wFIFOCtl);
 
diff --git a/drivers/staging/vt6656/usbpipe.c b/drivers/staging/vt6656/usbpipe.c
index 119f656..a4a4bf2 100644
--- a/drivers/staging/vt6656/usbpipe.c
+++ b/drivers/staging/vt6656/usbpipe.c
@@ -295,40 +295,38 @@
  *
  */
 
-int PIPEnsInterruptRead(struct vnt_private *pDevice)
+int PIPEnsInterruptRead(struct vnt_private *priv)
 {
-	int ntStatus = STATUS_FAILURE;
+	int status = STATUS_FAILURE;
 
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->s_nsStartInterruptUsbRead()\n");
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO
+			"---->s_nsStartInterruptUsbRead()\n");
 
-    if(pDevice->intBuf.bInUse == true){
-        return (STATUS_FAILURE);
-    }
-    pDevice->intBuf.bInUse = true;
-//    pDevice->bEventAvailable = false;
-    pDevice->ulIntInPosted++;
+	if (priv->int_buf.in_use == true)
+		return STATUS_FAILURE;
 
-    //
-    // Now that we have created the urb, we will send a
-    // request to the USB device object.
-    //
-    pDevice->pInterruptURB->interval = pDevice->int_interval;
+	priv->int_buf.in_use = true;
 
-usb_fill_bulk_urb(pDevice->pInterruptURB,
-		pDevice->usb,
-		usb_rcvbulkpipe(pDevice->usb, 1),
-		(void *) pDevice->intBuf.pDataBuf,
+	usb_fill_int_urb(priv->pInterruptURB,
+		priv->usb,
+		usb_rcvbulkpipe(priv->usb, 1),
+		priv->int_buf.data_buf,
 		MAX_INTERRUPT_SIZE,
 		s_nsInterruptUsbIoCompleteRead,
-		pDevice);
+		priv,
+		priv->int_interval);
 
-	ntStatus = usb_submit_urb(pDevice->pInterruptURB, GFP_ATOMIC);
-	if (ntStatus != 0) {
-	    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Submit int URB failed %d\n", ntStatus);
-    }
+	status = usb_submit_urb(priv->pInterruptURB, GFP_ATOMIC);
+	if (status) {
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO
+			"Submit int URB failed %d\n", status);
+		priv->int_buf.in_use = false;
+	}
 
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"<----s_nsStartInterruptUsbRead Return(%x)\n",ntStatus);
-    return ntStatus;
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO
+		"<----s_nsStartInterruptUsbRead Return(%x)\n", status);
+
+	return status;
 }
 
 /*
@@ -348,7 +346,7 @@
 
 static void s_nsInterruptUsbIoCompleteRead(struct urb *urb)
 {
-	struct vnt_private *priv = (struct vnt_private *)urb->context;
+	struct vnt_private *priv = urb->context;
 	int status;
 
 	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO
@@ -361,7 +359,7 @@
 	case -ECONNRESET:
 	case -ENOENT:
 	case -ESHUTDOWN:
-		priv->intBuf.bInUse = false;
+		priv->int_buf.in_use = false;
 		return;
 	default:
 		break;
@@ -373,15 +371,11 @@
 		"s_nsInterruptUsbIoCompleteRead Status %d\n", status);
 
 	if (status != STATUS_SUCCESS) {
-		priv->ulBulkInError++;
-		priv->intBuf.bInUse = false;
+		priv->int_buf.in_use = false;
 
 		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO
 			"IntUSBIoCompleteControl STATUS = %d\n", status);
 	} else {
-		priv->ulIntInBytesRead += (unsigned long)urb->actual_length;
-		priv->ulIntInContCRCError = 0;
-		priv->bEventAvailable = true;
 		INTnsProcessData(priv);
 	}
 
@@ -390,7 +384,7 @@
 		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO
 			"Submit int URB failed %d\n", status);
 	} else {
-		priv->intBuf.bInUse = true;
+		priv->int_buf.in_use = true;
 	}
 
 	return;
@@ -410,45 +404,41 @@
  *
  */
 
-int PIPEnsBulkInUsbRead(struct vnt_private *pDevice, struct vnt_rcb *pRCB)
+int PIPEnsBulkInUsbRead(struct vnt_private *priv, struct vnt_rcb *rcb)
 {
-	int ntStatus = 0;
-	struct urb *pUrb;
+	int status = 0;
+	struct urb *urb;
 
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->s_nsStartBulkInUsbRead\n");
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->s_nsStartBulkInUsbRead\n");
 
-    if (pDevice->Flags & fMP_DISCONNECTED)
-        return STATUS_FAILURE;
+	if (priv->Flags & fMP_DISCONNECTED)
+		return STATUS_FAILURE;
 
-    pDevice->ulBulkInPosted++;
+	urb = rcb->pUrb;
+	if (rcb->skb == NULL) {
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"rcb->skb is null\n");
+		return status;
+	}
 
-	pUrb = pRCB->pUrb;
-    //
-    // Now that we have created the urb, we will send a
-    // request to the USB device object.
-    //
-    if (pRCB->skb == NULL) {
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pRCB->skb is null \n");
-        return ntStatus;
-    }
-
-	usb_fill_bulk_urb(pUrb,
-		pDevice->usb,
-		usb_rcvbulkpipe(pDevice->usb, 2),
-		(void *) (pRCB->skb->data),
+	usb_fill_bulk_urb(urb,
+		priv->usb,
+		usb_rcvbulkpipe(priv->usb, 2),
+		(void *) (rcb->skb->data),
 		MAX_TOTAL_SIZE_WITH_ALL_HEADERS,
 		s_nsBulkInUsbIoCompleteRead,
-		pRCB);
+		rcb);
 
-	ntStatus = usb_submit_urb(pUrb, GFP_ATOMIC);
-	if (ntStatus != 0) {
-		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Submit Rx URB failed %d\n", ntStatus);
+	status = usb_submit_urb(urb, GFP_ATOMIC);
+	if (status != 0) {
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO
+				"Submit Rx URB failed %d\n", status);
 		return STATUS_FAILURE ;
 	}
-    pRCB->Ref = 1;
-    pRCB->bBoolInUse= true;
 
-    return ntStatus;
+	rcb->Ref = 1;
+	rcb->bBoolInUse = true;
+
+	return status;
 }
 
 /*
@@ -468,51 +458,47 @@
 
 static void s_nsBulkInUsbIoCompleteRead(struct urb *urb)
 {
-	struct vnt_rcb *pRCB = (struct vnt_rcb *)urb->context;
-	struct vnt_private *pDevice = pRCB->pDevice;
-	unsigned long   bytesRead;
-	int bIndicateReceive = false;
-	int bReAllocSkb = false;
-	int status;
+	struct vnt_rcb *rcb = urb->context;
+	struct vnt_private *priv = rcb->pDevice;
+	int re_alloc_skb = false;
 
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->s_nsBulkInUsbIoCompleteRead\n");
-    status = urb->status;
-    bytesRead = urb->actual_length;
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->s_nsBulkInUsbIoCompleteRead\n");
 
-    if (status) {
-        pDevice->ulBulkInError++;
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"BULK In failed %d\n", status);
-//todo...xxxxxx
-//        if (status == USBD_STATUS_CRC) {
-//            pDevice->ulBulkInContCRCError++;
-//        }
-//        if (status == STATUS_DEVICE_NOT_CONNECTED )
-//        {
-//            MP_SET_FLAG(pDevice, fMP_DISCONNECTED);
-//        }
-    } else {
-	if (bytesRead)
-		bIndicateReceive = true;
-        pDevice->ulBulkInContCRCError = 0;
-        pDevice->ulBulkInBytesRead += bytesRead;
-    }
+	switch (urb->status) {
+	case 0:
+		break;
+	case -ECONNRESET:
+	case -ENOENT:
+	case -ESHUTDOWN:
+		return;
+	case -ETIMEDOUT:
+	default:
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO
+				"BULK In failed %d\n", urb->status);
+		break;
+	}
 
-    if (bIndicateReceive) {
-        spin_lock(&pDevice->lock);
-        if (RXbBulkInProcessData(pDevice, pRCB, bytesRead) == true)
-            bReAllocSkb = true;
-        spin_unlock(&pDevice->lock);
-    }
-    pRCB->Ref--;
-    if (pRCB->Ref == 0)
-    {
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"RxvFreeNormal %d \n",pDevice->NumRecvFreeList);
-        spin_lock(&pDevice->lock);
-        RXvFreeRCB(pRCB, bReAllocSkb);
-        spin_unlock(&pDevice->lock);
-    }
+	if (urb->actual_length) {
+		spin_lock(&priv->lock);
 
-    return;
+		if (RXbBulkInProcessData(priv, rcb, urb->actual_length) == true)
+			re_alloc_skb = true;
+
+		spin_unlock(&priv->lock);
+	}
+
+	rcb->Ref--;
+	if (rcb->Ref == 0) {
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"RxvFreeNormal %d\n",
+							priv->NumRecvFreeList);
+		spin_lock(&priv->lock);
+
+		RXvFreeRCB(rcb, re_alloc_skb);
+
+		spin_unlock(&priv->lock);
+	}
+
+	return;
 }
 
 /*
@@ -529,53 +515,40 @@
  *
  */
 
-int PIPEnsSendBulkOut(struct vnt_private *pDevice,
-				struct vnt_usb_send_context *pContext)
+int PIPEnsSendBulkOut(struct vnt_private *priv,
+				struct vnt_usb_send_context *context)
 {
 	int status;
-	struct urb          *pUrb;
+	struct urb *urb;
 
-    pDevice->bPWBitOn = false;
+	priv->bPWBitOn = false;
 
-/*
-    if (pDevice->pPendingBulkOutContext != NULL) {
-        pDevice->NumContextsQueued++;
-        EnqueueContext(pDevice->FirstTxContextQueue, pDevice->LastTxContextQueue, pContext);
-        status = STATUS_PENDING;
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Send pending!\n");
-        return status;
-    }
-*/
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"s_nsSendBulkOut\n");
 
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"s_nsSendBulkOut\n");
+	if (!(MP_IS_READY(priv) && priv->Flags & fMP_POST_WRITES)) {
+		context->bBoolInUse = false;
+		return STATUS_RESOURCES;
+	}
 
-    if (MP_IS_READY(pDevice) && (pDevice->Flags & fMP_POST_WRITES)) {
+	urb = context->pUrb;
 
-        pUrb = pContext->pUrb;
-        pDevice->ulBulkOutPosted++;
-//        pDevice->pPendingBulkOutContext = pContext;
-        usb_fill_bulk_urb(
-        	    pUrb,
-        		pDevice->usb,
-		    usb_sndbulkpipe(pDevice->usb, 3),
-		    (void *) &(pContext->Data[0]),
-        		pContext->uBufLen,
-        		s_nsBulkOutIoCompleteWrite,
-        		pContext);
+	usb_fill_bulk_urb(urb,
+			priv->usb,
+			usb_sndbulkpipe(priv->usb, 3),
+			context->Data,
+			context->uBufLen,
+			s_nsBulkOutIoCompleteWrite,
+			context);
 
-    	status = usb_submit_urb(pUrb, GFP_ATOMIC);
-    	if (status != 0)
-    	{
-    		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Submit Tx URB failed %d\n", status);
-		pContext->bBoolInUse = false;
-    		return STATUS_FAILURE;
-    	}
-        return STATUS_PENDING;
-    }
-    else {
-        pContext->bBoolInUse = false;
-        return STATUS_RESOURCES;
-    }
+	status = usb_submit_urb(urb, GFP_ATOMIC);
+	if (status != 0) {
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO
+				"Submit Tx URB failed %d\n", status);
+		context->bBoolInUse = false;
+		return STATUS_FAILURE;
+	}
+
+	return STATUS_PENDING;
 }
 
 /*
@@ -608,68 +581,49 @@
 
 static void s_nsBulkOutIoCompleteWrite(struct urb *urb)
 {
-	struct vnt_private *pDevice;
-	int status;
-	CONTEXT_TYPE ContextType;
-	unsigned long ulBufLen;
-	struct vnt_usb_send_context *pContext;
+	struct vnt_usb_send_context *context = urb->context;
+	struct vnt_private *priv = context->pDevice;
+	u8 context_type = context->type;
 
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->s_nsBulkOutIoCompleteWrite\n");
-    //
-    // The context given to IoSetCompletionRoutine is an USB_CONTEXT struct
-    //
-	pContext = (struct vnt_usb_send_context *)urb->context;
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->s_nsBulkOutIoCompleteWrite\n");
 
-    pDevice = pContext->pDevice;
-    ContextType = pContext->Type;
-    ulBufLen = pContext->uBufLen;
+	switch (urb->status) {
+	case 0:
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO
+			"Write %d bytes\n", context->uBufLen);
+		break;
+	case -ECONNRESET:
+	case -ENOENT:
+	case -ESHUTDOWN:
+		context->bBoolInUse = false;
+		return;
+	case -ETIMEDOUT:
+	default:
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO
+				"BULK Out failed %d\n", urb->status);
+		break;
+	}
 
-    if (!netif_device_present(pDevice->dev))
-	    return;
+	if (!netif_device_present(priv->dev))
+		return;
 
-   //
-    // Perform various IRP, URB, and buffer 'sanity checks'
-    //
+	if (CONTEXT_DATA_PACKET == context_type) {
+		if (context->pPacket != NULL) {
+			dev_kfree_skb_irq(context->pPacket);
+			context->pPacket = NULL;
+			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO
+				"tx  %d bytes\n", context->uBufLen);
+		}
 
-    status = urb->status;
+		priv->dev->trans_start = jiffies;
+	}
 
-    if(status == STATUS_SUCCESS) {
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Write %d bytes\n",(int)ulBufLen);
-        pDevice->ulBulkOutBytesWrite += ulBufLen;
-        pDevice->ulBulkOutContCRCError = 0;
-    } else {
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"BULK Out failed %d\n", status);
-        pDevice->ulBulkOutError++;
-    }
+	if (priv->bLinkPass == true) {
+		if (netif_queue_stopped(priv->dev))
+			netif_wake_queue(priv->dev);
+	}
 
-//    pDevice->ulCheckForHangCount = 0;
-//    pDevice->pPendingBulkOutContext = NULL;
+	context->bBoolInUse = false;
 
-    if ( CONTEXT_DATA_PACKET == ContextType ) {
-        // Indicate to the protocol the status of the sent packet and return
-        // ownership of the packet.
-	    if (pContext->pPacket != NULL) {
-	        dev_kfree_skb_irq(pContext->pPacket);
-	        pContext->pPacket = NULL;
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"tx  %d bytes\n",(int)ulBufLen);
-	    }
-
-        pDevice->dev->trans_start = jiffies;
-
-        if (status == STATUS_SUCCESS) {
-            pDevice->packetsSent++;
-        }
-        else {
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Send USB error! [%08xh]\n", status);
-            pDevice->packetsSentDropped++;
-        }
-
-    }
-    if (pDevice->bLinkPass == true) {
-        if (netif_queue_stopped(pDevice->dev))
-            netif_wake_queue(pDevice->dev);
-    }
-    pContext->bBoolInUse = false;
-
-    return;
+	return;
 }
diff --git a/drivers/staging/vt6656/wcmd.c b/drivers/staging/vt6656/wcmd.c
index 6b95229..3cf3f24 100644
--- a/drivers/staging/vt6656/wcmd.c
+++ b/drivers/staging/vt6656/wcmd.c
@@ -293,17 +293,11 @@
 	case WLAN_CMD_SCAN_START:
 
 		pDevice->byReAssocCount = 0;
-		if (pDevice->bRadioOff == true) {
-			s_bCommandComplete(pDevice);
-			spin_unlock_irq(&pDevice->lock);
-			return;
-		}
+		if (pDevice->bRadioOff == true)
+			break;
 
-		if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP) {
-			s_bCommandComplete(pDevice);
-			spin_unlock_irq(&pDevice->lock);
-			return;
-		}
+		if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP)
+			break;
 
 		pItemSSID = (PWLAN_IE_SSID)pMgmt->abyScanSSID;
 
@@ -311,16 +305,12 @@
 			pMgmt->uScanChannel = pDevice->byMinChannel;
 		if (pMgmt->uScanChannel > pDevice->byMaxChannel) {
 			pDevice->eCommandState = WLAN_CMD_SCAN_END;
-			s_bCommandComplete(pDevice);
-			spin_unlock_irq(&pDevice->lock);
-			return;
+			break;
 		} else {
 			if (!ChannelValid(pDevice->byZoneType, pMgmt->uScanChannel)) {
 				DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Invalid channel pMgmt->uScanChannel = %d\n", pMgmt->uScanChannel);
 				pMgmt->uScanChannel++;
-				s_bCommandComplete(pDevice);
-				spin_unlock_irq(&pDevice->lock);
-				return;
+				break;
 			}
 			if (pMgmt->uScanChannel == pDevice->byMinChannel) {
 				// pMgmt->eScanType = WMAC_SCAN_ACTIVE;          //mike mark
@@ -420,16 +410,13 @@
 		memset(&wrqu, 0, sizeof(wrqu));
 		wireless_send_event(pDevice->dev, SIOCGIWSCAN, &wrqu, NULL);
 
-		s_bCommandComplete(pDevice);
 		break;
 
 	case WLAN_CMD_DISASSOCIATE_START:
 		pDevice->byReAssocCount = 0;
 		if ((pMgmt->eCurrMode == WMAC_MODE_ESS_STA) &&
 		    (pMgmt->eCurrState != WMAC_STATE_ASSOC)) {
-			s_bCommandComplete(pDevice);
-			spin_unlock_irq(&pDevice->lock);
-			return;
+			break;
 		} else {
 			pDevice->bwextstep0 = false;
 			pDevice->bwextstep1 = false;
@@ -458,17 +445,14 @@
 		netif_stop_queue(pDevice->dev);
 		if (pDevice->bNeedRadioOFF == true)
 			CARDbRadioPowerOff(pDevice);
-		s_bCommandComplete(pDevice);
+
 		break;
 
 	case WLAN_CMD_SSID_START:
 
 		pDevice->byReAssocCount = 0;
-		if (pDevice->bRadioOff == true) {
-			s_bCommandComplete(pDevice);
-			spin_unlock_irq(&pDevice->lock);
-			return;
-		}
+		if (pDevice->bRadioOff == true)
+			break;
 
 		memcpy(pMgmt->abyAdHocSSID, pMgmt->abyDesireSSID,
 		       ((PWLAN_IE_SSID)pMgmt->abyDesireSSID)->len + WLAN_IEHDR_LEN);
@@ -489,11 +473,9 @@
 		if ((pMgmt->eCurrState == WMAC_STATE_ASSOC) ||
 		    ((pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) && (pMgmt->eCurrState == WMAC_STATE_JOINTED))) {
 			if (pItemSSID->len == pItemSSIDCurr->len) {
-				if (memcmp(pItemSSID->abySSID, pItemSSIDCurr->abySSID, pItemSSID->len) == 0) {
-					s_bCommandComplete(pDevice);
-					spin_unlock_irq(&pDevice->lock);
-					return;
-				}
+				if (!memcmp(pItemSSID->abySSID,
+					pItemSSIDCurr->abySSID, pItemSSID->len))
+					break;
 			}
 			netif_stop_queue(pDevice->dev);
 			pDevice->bLinkPass = false;
@@ -582,7 +564,6 @@
 				}
 			}
 		}
-		s_bCommandComplete(pDevice);
 		break;
 
 	case WLAN_AUTHENTICATE_WAIT:
@@ -612,7 +593,6 @@
 		}
 		pDevice->byLinkWaitCount = 0;
 
-		s_bCommandComplete(pDevice);
 		break;
 
 	case WLAN_ASSOCIATE_WAIT:
@@ -647,7 +627,6 @@
 			return;
 		}
 
-		s_bCommandComplete(pDevice);
 		break;
 
 	case WLAN_CMD_AP_MODE_START:
@@ -683,7 +662,6 @@
 			ControlvMaskByte(pDevice, MESSAGE_REQUEST_MACREG, MAC_REG_PAPEDELAY, LEDSTS_STS, LEDSTS_INTER);
 			schedule_delayed_work(&pDevice->second_callback_work, HZ);
 		}
-		s_bCommandComplete(pDevice);
 		break;
 
 	case WLAN_CMD_TX_PSPACKET_START:
@@ -738,8 +716,6 @@
 				pMgmt->sNodeDBTable[ii].bRxPSPoll = false;
 			}
 		}
-
-		s_bCommandComplete(pDevice);
 		break;
 
 	case WLAN_CMD_RADIO_START:
@@ -760,11 +736,8 @@
 					1,
 					&byTmp);
 
-			if (ntStatus != STATUS_SUCCESS) {
-				s_bCommandComplete(pDevice);
-				spin_unlock_irq(&pDevice->lock);
-				return;
-			}
+			if (ntStatus != STATUS_SUCCESS)
+				break;
 			if ((byTmp & GPIO3_DATA) == 0) {
 				DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" WLAN_CMD_RADIO_START_OFF........................\n");
 				// Old commands are useless.
@@ -833,7 +806,6 @@
 			}
 		}
 
-		s_bCommandComplete(pDevice);
 		break;
 
 	case WLAN_CMD_CHANGE_BBSENSITIVITY_START:
@@ -843,24 +815,20 @@
 		BBvSetVGAGainOffset(pDevice, pDevice->byBBVGACurrent);
 		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Change sensitivity pDevice->byBBVGACurrent = %x\n", pDevice->byBBVGACurrent);
 		pDevice->bStopDataPkt = false;
-		s_bCommandComplete(pDevice);
 		break;
 
 	case WLAN_CMD_TBTT_WAKEUP_START:
 		PSbIsNextTBTTWakeUp(pDevice);
-		s_bCommandComplete(pDevice);
 		break;
 
 	case WLAN_CMD_BECON_SEND_START:
 		bMgrPrepareBeaconToSend(pDevice, pMgmt);
-		s_bCommandComplete(pDevice);
 		break;
 
 	case WLAN_CMD_SETPOWER_START:
 
 		RFbSetPower(pDevice, pDevice->wCurrentRate, pMgmt->uCurrChannel);
 
-		s_bCommandComplete(pDevice);
 		break;
 
 	case WLAN_CMD_CHANGE_ANTENNA_START:
@@ -878,12 +846,10 @@
 			else
 				BBvSetAntennaMode(pDevice, ANT_RXA);
 		}
-		s_bCommandComplete(pDevice);
 		break;
 
 	case WLAN_CMD_REMOVE_ALLKEY_START:
 		KeybRemoveAllKey(pDevice, &(pDevice->sKey), pDevice->abyBSSID);
-		s_bCommandComplete(pDevice);
 		break;
 
 	case WLAN_CMD_MAC_DISPOWERSAVING_START:
@@ -898,7 +864,6 @@
 					NULL
 					);
 		}
-		s_bCommandComplete(pDevice);
 		break;
 
 	case WLAN_CMD_11H_CHSW_START:
@@ -906,14 +871,17 @@
 		pDevice->bChannelSwitch = false;
 		pMgmt->uCurrChannel = pDevice->byNewChannel;
 		pDevice->bStopDataPkt = false;
-		s_bCommandComplete(pDevice);
 		break;
 
+	case WLAN_CMD_CONFIGURE_FILTER_START:
+		vnt_configure_filter(pDevice);
+		break;
 	default:
-		s_bCommandComplete(pDevice);
 		break;
 	} //switch
 
+	s_bCommandComplete(pDevice);
+
 	spin_unlock_irq(&pDevice->lock);
 	return;
 }
@@ -1009,6 +977,11 @@
 			pDevice->eCommandState = WLAN_CMD_11H_CHSW_START;
 			break;
 
+		case WLAN_CMD_CONFIGURE_FILTER:
+			pDevice->eCommandState =
+						WLAN_CMD_CONFIGURE_FILTER_START;
+			break;
+
 		default:
 			break;
 		}
diff --git a/drivers/staging/vt6656/wcmd.h b/drivers/staging/vt6656/wcmd.h
index caf2684..7365721 100644
--- a/drivers/staging/vt6656/wcmd.h
+++ b/drivers/staging/vt6656/wcmd.h
@@ -51,7 +51,8 @@
     WLAN_CMD_REMOVE_ALLKEY,
     WLAN_CMD_MAC_DISPOWERSAVING,
     WLAN_CMD_11H_CHSW,
-    WLAN_CMD_RUN_AP
+    WLAN_CMD_RUN_AP,
+    WLAN_CMD_CONFIGURE_FILTER
 } CMD_CODE, *PCMD_CODE;
 
 #define CMD_Q_SIZE              32
@@ -96,6 +97,7 @@
     WLAN_CMD_REMOVE_ALLKEY_START,
     WLAN_CMD_MAC_DISPOWERSAVING_START,
     WLAN_CMD_11H_CHSW_START,
+    WLAN_CMD_CONFIGURE_FILTER_START,
     WLAN_CMD_IDLE
 } CMD_STATE, *PCMD_STATE;
 
diff --git a/drivers/staging/xgifb/XGI_main_26.c b/drivers/staging/xgifb/XGI_main_26.c
index b3ff603..46680468 100644
--- a/drivers/staging/xgifb/XGI_main_26.c
+++ b/drivers/staging/xgifb/XGI_main_26.c
@@ -1754,8 +1754,7 @@
 		dev_err(&pdev->dev, "Unable request memory size %x\n",
 		       xgifb_info->video_size);
 		dev_err(&pdev->dev,
-			"Fatal error: Unable to reserve frame buffer memory. "
-			"Is there another framebuffer driver active?\n");
+			"Fatal error: Unable to reserve frame buffer memory. Is there another framebuffer driver active?\n");
 		ret = -ENODEV;
 		goto error_disable;
 	}
@@ -2087,23 +2086,19 @@
 
 module_param(mode, charp, 0);
 MODULE_PARM_DESC(mode,
-	"Selects the desired default display mode in the format XxYxDepth "
-	"(eg. 1024x768x16).");
+	"Selects the desired default display mode in the format XxYxDepth (eg. 1024x768x16).");
 
 module_param(forcecrt2type, charp, 0);
 MODULE_PARM_DESC(forcecrt2type,
-	"Force the second display output type. Possible values are NONE, "
-	"LCD, TV, VGA, SVIDEO or COMPOSITE.");
+	"Force the second display output type. Possible values are NONE, LCD, TV, VGA, SVIDEO or COMPOSITE.");
 
 module_param(vesa, int, 0);
 MODULE_PARM_DESC(vesa,
-	"Selects the desired default display mode by VESA mode number "
-	"(eg. 0x117).");
+	"Selects the desired default display mode by VESA mode number (eg. 0x117).");
 
 module_param(filter, int, 0);
 MODULE_PARM_DESC(filter,
-	"Selects TV flicker filter type (only for systems with a SiS301 video bridge). "
-	"Possible values 0-7. Default: [no filter]).");
+	"Selects TV flicker filter type (only for systems with a SiS301 video bridge). Possible values 0-7. Default: [no filter]).");
 
 static int __init xgifb_init(void)
 {
diff --git a/drivers/target/target_core_sbc.c b/drivers/target/target_core_sbc.c
index a448944..42f18fc 100644
--- a/drivers/target/target_core_sbc.c
+++ b/drivers/target/target_core_sbc.c
@@ -1074,7 +1074,7 @@
 	struct scatterlist *psg;
 	void *paddr, *addr;
 	unsigned int i, len, left;
-	unsigned int offset = 0;
+	unsigned int offset = sg_off;
 
 	left = sectors * dev->prot_length;
 
@@ -1084,11 +1084,10 @@
 		if (offset >= sg->length) {
 			sg = sg_next(sg);
 			offset = 0;
-			sg_off = sg->offset;
 		}
 
 		paddr = kmap_atomic(sg_page(psg)) + psg->offset;
-		addr = kmap_atomic(sg_page(sg)) + sg_off;
+		addr = kmap_atomic(sg_page(sg)) + sg->offset + offset;
 
 		if (read)
 			memcpy(paddr, addr, len);
@@ -1163,7 +1162,7 @@
 {
 	struct se_device *dev = cmd->se_dev;
 	struct se_dif_v1_tuple *sdt;
-	struct scatterlist *dsg;
+	struct scatterlist *dsg, *psg = sg;
 	sector_t sector = start;
 	void *daddr, *paddr;
 	int i, j, offset = sg_off;
@@ -1171,14 +1170,14 @@
 
 	for_each_sg(cmd->t_data_sg, dsg, cmd->t_data_nents, i) {
 		daddr = kmap_atomic(sg_page(dsg)) + dsg->offset;
-		paddr = kmap_atomic(sg_page(sg)) + sg->offset;
+		paddr = kmap_atomic(sg_page(psg)) + sg->offset;
 
 		for (j = 0; j < dsg->length; j += dev->dev_attrib.block_size) {
 
-			if (offset >= sg->length) {
+			if (offset >= psg->length) {
 				kunmap_atomic(paddr);
-				sg = sg_next(sg);
-				paddr = kmap_atomic(sg_page(sg)) + sg->offset;
+				psg = sg_next(psg);
+				paddr = kmap_atomic(sg_page(psg)) + psg->offset;
 				offset = 0;
 			}
 
diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c
index 24b4f65d..2956250 100644
--- a/drivers/target/target_core_transport.c
+++ b/drivers/target/target_core_transport.c
@@ -1601,6 +1601,9 @@
 	case TCM_CHECK_CONDITION_ABORT_CMD:
 	case TCM_CHECK_CONDITION_UNIT_ATTENTION:
 	case TCM_CHECK_CONDITION_NOT_READY:
+	case TCM_LOGICAL_BLOCK_GUARD_CHECK_FAILED:
+	case TCM_LOGICAL_BLOCK_APP_TAG_CHECK_FAILED:
+	case TCM_LOGICAL_BLOCK_REF_TAG_CHECK_FAILED:
 		break;
 	case TCM_OUT_OF_RESOURCES:
 		sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c
index bd2715a..c74a00a 100644
--- a/drivers/tty/tty_io.c
+++ b/drivers/tty/tty_io.c
@@ -1267,17 +1267,16 @@
  *	@p: output buffer of at least 7 bytes
  *
  *	Generate a name from a driver reference and write it to the output
- *	buffer. Return the number of bytes written.
+ *	buffer.
  *
  *	Locking: None
  */
-static ssize_t tty_line_name(struct tty_driver *driver, int index, char *p)
+static void tty_line_name(struct tty_driver *driver, int index, char *p)
 {
 	if (driver->flags & TTY_DRIVER_UNNUMBERED_NODE)
-		return sprintf(p, "%s", driver->name);
+		strcpy(p, driver->name);
 	else
-		return sprintf(p, "%s%d", driver->name,
-			       index + driver->name_base);
+		sprintf(p, "%s%d", driver->name, index + driver->name_base);
 }
 
 /**
@@ -3546,19 +3545,9 @@
 		if (i >= ARRAY_SIZE(cs))
 			break;
 	}
-	while (i--) {
-		struct tty_driver *driver;
-		const char *name = cs[i]->name;
-		int index = cs[i]->index;
-
-		driver = cs[i]->device(cs[i], &index);
-		if (driver) {
-			count += tty_line_name(driver, index, buf + count);
-			count += sprintf(buf + count, "%c", i ? ' ':'\n');
-		} else
-			count += sprintf(buf + count, "%s%d%c",
-					 name, index, i ? ' ':'\n');
-	}
+	while (i--)
+		count += sprintf(buf + count, "%s%d%c",
+				 cs[i]->name, cs[i]->index, i ? ' ':'\n');
 	console_unlock();
 
 	return count;
diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c
index 80de2f8..4ab2cb6 100644
--- a/drivers/usb/chipidea/udc.c
+++ b/drivers/usb/chipidea/udc.c
@@ -105,7 +105,7 @@
 
 	do {
 		/* flush any pending transfer */
-		hw_write(ci, OP_ENDPTFLUSH, BIT(n), BIT(n));
+		hw_write(ci, OP_ENDPTFLUSH, ~0, BIT(n));
 		while (hw_read(ci, OP_ENDPTFLUSH, BIT(n)))
 			cpu_relax();
 	} while (hw_read(ci, OP_ENDPTSTAT, BIT(n)));
@@ -205,7 +205,7 @@
 	if (is_ctrl && dir == RX && hw_read(ci, OP_ENDPTSETUPSTAT, BIT(num)))
 		return -EAGAIN;
 
-	hw_write(ci, OP_ENDPTPRIME, BIT(n), BIT(n));
+	hw_write(ci, OP_ENDPTPRIME, ~0, BIT(n));
 
 	while (hw_read(ci, OP_ENDPTPRIME, BIT(n)))
 		cpu_relax();
diff --git a/drivers/usb/gadget/bcm63xx_udc.c b/drivers/usb/gadget/bcm63xx_udc.c
index 888fbb4..e969eb8 100644
--- a/drivers/usb/gadget/bcm63xx_udc.c
+++ b/drivers/usb/gadget/bcm63xx_udc.c
@@ -360,24 +360,30 @@
 	bcm_writel(val, udc->iudma_regs + off);
 }
 
-static inline u32 usb_dmac_readl(struct bcm63xx_udc *udc, u32 off)
+static inline u32 usb_dmac_readl(struct bcm63xx_udc *udc, u32 off, int chan)
 {
-	return bcm_readl(udc->iudma_regs + IUDMA_DMAC_OFFSET + off);
+	return bcm_readl(udc->iudma_regs + IUDMA_DMAC_OFFSET + off +
+			(ENETDMA_CHAN_WIDTH * chan));
 }
 
-static inline void usb_dmac_writel(struct bcm63xx_udc *udc, u32 val, u32 off)
+static inline void usb_dmac_writel(struct bcm63xx_udc *udc, u32 val, u32 off,
+					int chan)
 {
-	bcm_writel(val, udc->iudma_regs + IUDMA_DMAC_OFFSET + off);
+	bcm_writel(val, udc->iudma_regs + IUDMA_DMAC_OFFSET + off +
+			(ENETDMA_CHAN_WIDTH * chan));
 }
 
-static inline u32 usb_dmas_readl(struct bcm63xx_udc *udc, u32 off)
+static inline u32 usb_dmas_readl(struct bcm63xx_udc *udc, u32 off, int chan)
 {
-	return bcm_readl(udc->iudma_regs + IUDMA_DMAS_OFFSET + off);
+	return bcm_readl(udc->iudma_regs + IUDMA_DMAS_OFFSET + off +
+			(ENETDMA_CHAN_WIDTH * chan));
 }
 
-static inline void usb_dmas_writel(struct bcm63xx_udc *udc, u32 val, u32 off)
+static inline void usb_dmas_writel(struct bcm63xx_udc *udc, u32 val, u32 off,
+					int chan)
 {
-	bcm_writel(val, udc->iudma_regs + IUDMA_DMAS_OFFSET + off);
+	bcm_writel(val, udc->iudma_regs + IUDMA_DMAS_OFFSET + off +
+			(ENETDMA_CHAN_WIDTH * chan));
 }
 
 static inline void set_clocks(struct bcm63xx_udc *udc, bool is_enabled)
@@ -638,7 +644,7 @@
 	} while (!last_bd);
 
 	usb_dmac_writel(udc, ENETDMAC_CHANCFG_EN_MASK,
-			ENETDMAC_CHANCFG_REG(iudma->ch_idx));
+			ENETDMAC_CHANCFG_REG, iudma->ch_idx);
 }
 
 /**
@@ -694,9 +700,9 @@
 		bcm63xx_fifo_reset_ep(udc, max(0, iudma->ep_num));
 
 	/* stop DMA, then wait for the hardware to wrap up */
-	usb_dmac_writel(udc, 0, ENETDMAC_CHANCFG_REG(ch_idx));
+	usb_dmac_writel(udc, 0, ENETDMAC_CHANCFG_REG, ch_idx);
 
-	while (usb_dmac_readl(udc, ENETDMAC_CHANCFG_REG(ch_idx)) &
+	while (usb_dmac_readl(udc, ENETDMAC_CHANCFG_REG, ch_idx) &
 				   ENETDMAC_CHANCFG_EN_MASK) {
 		udelay(1);
 
@@ -713,10 +719,10 @@
 			dev_warn(udc->dev, "forcibly halting IUDMA channel %d\n",
 				 ch_idx);
 			usb_dmac_writel(udc, ENETDMAC_CHANCFG_BUFHALT_MASK,
-					ENETDMAC_CHANCFG_REG(ch_idx));
+					ENETDMAC_CHANCFG_REG, ch_idx);
 		}
 	}
-	usb_dmac_writel(udc, ~0, ENETDMAC_IR_REG(ch_idx));
+	usb_dmac_writel(udc, ~0, ENETDMAC_IR_REG, ch_idx);
 
 	/* don't leave "live" HW-owned entries for the next guy to step on */
 	for (d = iudma->bd_ring; d <= iudma->end_bd; d++)
@@ -728,11 +734,11 @@
 
 	/* set up IRQs, UBUS burst size, and BD base for this channel */
 	usb_dmac_writel(udc, ENETDMAC_IR_BUFDONE_MASK,
-			ENETDMAC_IRMASK_REG(ch_idx));
-	usb_dmac_writel(udc, 8, ENETDMAC_MAXBURST_REG(ch_idx));
+			ENETDMAC_IRMASK_REG, ch_idx);
+	usb_dmac_writel(udc, 8, ENETDMAC_MAXBURST_REG, ch_idx);
 
-	usb_dmas_writel(udc, iudma->bd_ring_dma, ENETDMAS_RSTART_REG(ch_idx));
-	usb_dmas_writel(udc, 0, ENETDMAS_SRAM2_REG(ch_idx));
+	usb_dmas_writel(udc, iudma->bd_ring_dma, ENETDMAS_RSTART_REG, ch_idx);
+	usb_dmas_writel(udc, 0, ENETDMAS_SRAM2_REG, ch_idx);
 }
 
 /**
@@ -2035,7 +2041,7 @@
 	spin_lock(&udc->lock);
 
 	usb_dmac_writel(udc, ENETDMAC_IR_BUFDONE_MASK,
-			ENETDMAC_IR_REG(iudma->ch_idx));
+			ENETDMAC_IR_REG, iudma->ch_idx);
 	bep = iudma->bep;
 	rc = iudma_read(udc, iudma);
 
@@ -2175,18 +2181,18 @@
 		seq_printf(s, " [ep%d]:\n",
 			   max_t(int, iudma_defaults[ch_idx].ep_num, 0));
 		seq_printf(s, "  cfg: %08x; irqstat: %08x; irqmask: %08x; maxburst: %08x\n",
-			   usb_dmac_readl(udc, ENETDMAC_CHANCFG_REG(ch_idx)),
-			   usb_dmac_readl(udc, ENETDMAC_IR_REG(ch_idx)),
-			   usb_dmac_readl(udc, ENETDMAC_IRMASK_REG(ch_idx)),
-			   usb_dmac_readl(udc, ENETDMAC_MAXBURST_REG(ch_idx)));
+			   usb_dmac_readl(udc, ENETDMAC_CHANCFG_REG, ch_idx),
+			   usb_dmac_readl(udc, ENETDMAC_IR_REG, ch_idx),
+			   usb_dmac_readl(udc, ENETDMAC_IRMASK_REG, ch_idx),
+			   usb_dmac_readl(udc, ENETDMAC_MAXBURST_REG, ch_idx));
 
-		sram2 = usb_dmas_readl(udc, ENETDMAS_SRAM2_REG(ch_idx));
-		sram3 = usb_dmas_readl(udc, ENETDMAS_SRAM3_REG(ch_idx));
+		sram2 = usb_dmas_readl(udc, ENETDMAS_SRAM2_REG, ch_idx);
+		sram3 = usb_dmas_readl(udc, ENETDMAS_SRAM3_REG, ch_idx);
 		seq_printf(s, "  base: %08x; index: %04x_%04x; desc: %04x_%04x %08x\n",
-			   usb_dmas_readl(udc, ENETDMAS_RSTART_REG(ch_idx)),
+			   usb_dmas_readl(udc, ENETDMAS_RSTART_REG, ch_idx),
 			   sram2 >> 16, sram2 & 0xffff,
 			   sram3 >> 16, sram3 & 0xffff,
-			   usb_dmas_readl(udc, ENETDMAS_SRAM4_REG(ch_idx)));
+			   usb_dmas_readl(udc, ENETDMAS_SRAM4_REG, ch_idx));
 		seq_printf(s, "  desc: %d/%d used", iudma->n_bds_used,
 			   iudma->n_bds);
 
diff --git a/drivers/usb/gadget/f_fs.c b/drivers/usb/gadget/f_fs.c
index 306a2b5..2b43343 100644
--- a/drivers/usb/gadget/f_fs.c
+++ b/drivers/usb/gadget/f_fs.c
@@ -585,7 +585,6 @@
 			     char __user *buf, size_t len, int read)
 {
 	struct ffs_epfile *epfile = file->private_data;
-	struct usb_gadget *gadget = epfile->ffs->gadget;
 	struct ffs_ep *ep;
 	char *data = NULL;
 	ssize_t ret, data_len;
@@ -622,6 +621,12 @@
 	/* Allocate & copy */
 	if (!halt) {
 		/*
+		 * if we _do_ wait above, the epfile->ffs->gadget might be NULL
+		 * before the waiting completes, so do not assign to 'gadget' earlier
+		 */
+		struct usb_gadget *gadget = epfile->ffs->gadget;
+
+		/*
 		 * Controller may require buffer size to be aligned to
 		 * maxpacketsize of an out endpoint.
 		 */
diff --git a/drivers/usb/gadget/printer.c b/drivers/usb/gadget/printer.c
index bf7a56b..69b76ef 100644
--- a/drivers/usb/gadget/printer.c
+++ b/drivers/usb/gadget/printer.c
@@ -1157,7 +1157,7 @@
 
 	usb_gadget_set_selfpowered(gadget);
 
-	if (gadget->is_otg) {
+	if (gadget_is_otg(gadget)) {
 		otg_descriptor.bmAttributes |= USB_OTG_HNP;
 		printer_cfg_driver.descriptors = otg_desc;
 		printer_cfg_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
diff --git a/drivers/usb/gadget/s3c2410_udc.c b/drivers/usb/gadget/s3c2410_udc.c
index f04b2c3..dd9678f 100644
--- a/drivers/usb/gadget/s3c2410_udc.c
+++ b/drivers/usb/gadget/s3c2410_udc.c
@@ -1629,7 +1629,7 @@
 		ep->ep.desc = NULL;
 		ep->halted = 0;
 		INIT_LIST_HEAD(&ep->queue);
-		usb_ep_set_maxpacket_limit(&ep->ep, &ep->ep.maxpacket);
+		usb_ep_set_maxpacket_limit(&ep->ep, ep->ep.maxpacket);
 	}
 }
 
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 4711427..81cda09 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -685,8 +685,15 @@
 	struct ehci_hcd		*ehci = hcd_to_ehci (hcd);
 	u32			status, masked_status, pcd_status = 0, cmd;
 	int			bh;
+	unsigned long		flags;
 
-	spin_lock (&ehci->lock);
+	/*
+	 * For threadirqs option we use spin_lock_irqsave() variant to prevent
+	 * deadlock with ehci hrtimer callback, because hrtimer callbacks run
+	 * in interrupt context even when threadirqs is specified. We can go
+	 * back to spin_lock() variant when hrtimer callbacks become threaded.
+	 */
+	spin_lock_irqsave(&ehci->lock, flags);
 
 	status = ehci_readl(ehci, &ehci->regs->status);
 
@@ -704,7 +711,7 @@
 
 	/* Shared IRQ? */
 	if (!masked_status || unlikely(ehci->rh_state == EHCI_RH_HALTED)) {
-		spin_unlock(&ehci->lock);
+		spin_unlock_irqrestore(&ehci->lock, flags);
 		return IRQ_NONE;
 	}
 
@@ -815,7 +822,7 @@
 
 	if (bh)
 		ehci_work (ehci);
-	spin_unlock (&ehci->lock);
+	spin_unlock_irqrestore(&ehci->lock, flags);
 	if (pcd_status)
 		usb_hcd_poll_rh_status(hcd);
 	return IRQ_HANDLED;
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
index 47b858f..7ae0c4d 100644
--- a/drivers/usb/host/ehci-hub.c
+++ b/drivers/usb/host/ehci-hub.c
@@ -238,6 +238,7 @@
 	int			port;
 	int			mask;
 	int			changed;
+	bool			fs_idle_delay;
 
 	ehci_dbg(ehci, "suspend root hub\n");
 
@@ -272,6 +273,7 @@
 	ehci->bus_suspended = 0;
 	ehci->owned_ports = 0;
 	changed = 0;
+	fs_idle_delay = false;
 	port = HCS_N_PORTS(ehci->hcs_params);
 	while (port--) {
 		u32 __iomem	*reg = &ehci->regs->port_status [port];
@@ -300,16 +302,32 @@
 		}
 
 		if (t1 != t2) {
+			/*
+			 * On some controllers, Wake-On-Disconnect will
+			 * generate false wakeup signals until the bus
+			 * switches over to full-speed idle.  For their
+			 * sake, add a delay if we need one.
+			 */
+			if ((t2 & PORT_WKDISC_E) &&
+					ehci_port_speed(ehci, t2) ==
+						USB_PORT_STAT_HIGH_SPEED)
+				fs_idle_delay = true;
 			ehci_writel(ehci, t2, reg);
 			changed = 1;
 		}
 	}
+	spin_unlock_irq(&ehci->lock);
+
+	if ((changed && ehci->has_tdi_phy_lpm) || fs_idle_delay) {
+		/*
+		 * Wait for HCD to enter low-power mode or for the bus
+		 * to switch to full-speed idle.
+		 */
+		usleep_range(5000, 5500);
+	}
 
 	if (changed && ehci->has_tdi_phy_lpm) {
-		spin_unlock_irq(&ehci->lock);
-		msleep(5);	/* 5 ms for HCD to enter low-power mode */
 		spin_lock_irq(&ehci->lock);
-
 		port = HCS_N_PORTS(ehci->hcs_params);
 		while (port--) {
 			u32 __iomem	*hostpc_reg = &ehci->regs->hostpc[port];
@@ -322,8 +340,8 @@
 					port, (t3 & HOSTPC_PHCD) ?
 					"succeeded" : "failed");
 		}
+		spin_unlock_irq(&ehci->lock);
 	}
-	spin_unlock_irq(&ehci->lock);
 
 	/* Apparently some devices need a >= 1-uframe delay here */
 	if (ehci->bus_suspended)
diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
index fc192ad..239ad0b 100644
--- a/drivers/usb/musb/musb_core.c
+++ b/drivers/usb/musb/musb_core.c
@@ -477,8 +477,11 @@
 				musb->port1_status |=
 						(USB_PORT_STAT_C_SUSPEND << 16)
 						| MUSB_PORT_STAT_RESUME;
+				musb->rh_timer = jiffies
+						 + msecs_to_jiffies(20);
 				schedule_delayed_work(
-					&musb->finish_resume_work, 20);
+					&musb->finish_resume_work,
+					msecs_to_jiffies(20));
 
 				musb->xceiv->state = OTG_STATE_A_HOST;
 				musb->is_active = 1;
@@ -2157,11 +2160,19 @@
 	void __iomem *musb_base = musb->mregs;
 	void __iomem *ep_target_regs;
 	void __iomem *epio;
+	u8 power;
 
 	musb_writew(musb_base, MUSB_FRAME, musb->context.frame);
 	musb_writeb(musb_base, MUSB_TESTMODE, musb->context.testmode);
 	musb_write_ulpi_buscontrol(musb->mregs, musb->context.busctl);
-	musb_writeb(musb_base, MUSB_POWER, musb->context.power);
+
+	/* Don't affect SUSPENDM/RESUME bits in POWER reg */
+	power = musb_readb(musb_base, MUSB_POWER);
+	power &= MUSB_POWER_SUSPENDM | MUSB_POWER_RESUME;
+	musb->context.power &= ~(MUSB_POWER_SUSPENDM | MUSB_POWER_RESUME);
+	power |= musb->context.power;
+	musb_writeb(musb_base, MUSB_POWER, power);
+
 	musb_writew(musb_base, MUSB_INTRTXE, musb->intrtxe);
 	musb_writew(musb_base, MUSB_INTRRXE, musb->intrrxe);
 	musb_writeb(musb_base, MUSB_INTRUSBE, musb->context.intrusbe);
diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c
index ed45572..abb38c3 100644
--- a/drivers/usb/musb/musb_host.c
+++ b/drivers/usb/musb/musb_host.c
@@ -1183,6 +1183,9 @@
 				csr = MUSB_CSR0_H_STATUSPKT
 					| MUSB_CSR0_TXPKTRDY;
 
+			/* disable ping token in status phase */
+			csr |= MUSB_CSR0_H_DIS_PING;
+
 			/* flag status stage */
 			musb->ep0_stage = MUSB_EP0_STATUS;
 
diff --git a/drivers/usb/musb/musb_virthub.c b/drivers/usb/musb/musb_virthub.c
index eb63443..e2d2d8c 100644
--- a/drivers/usb/musb/musb_virthub.c
+++ b/drivers/usb/musb/musb_virthub.c
@@ -135,7 +135,8 @@
 
 		/* later, GetPortStatus will stop RESUME signaling */
 		musb->port1_status |= MUSB_PORT_STAT_RESUME;
-		schedule_delayed_work(&musb->finish_resume_work, 20);
+		schedule_delayed_work(&musb->finish_resume_work,
+				      msecs_to_jiffies(20));
 	}
 }
 
@@ -158,7 +159,6 @@
 	 */
 	power = musb_readb(mbase, MUSB_POWER);
 	if (do_reset) {
-
 		/*
 		 * If RESUME is set, we must make sure it stays minimum 20 ms.
 		 * Then we must clear RESUME and wait a bit to let musb start
@@ -167,11 +167,22 @@
 		 * detected".
 		 */
 		if (power &  MUSB_POWER_RESUME) {
-			while (time_before(jiffies, musb->rh_timer))
-				msleep(1);
+			long remain = (unsigned long) musb->rh_timer - jiffies;
+
+			if (musb->rh_timer > 0 && remain > 0) {
+				/* take into account the minimum delay after resume */
+				schedule_delayed_work(
+					&musb->deassert_reset_work, remain);
+				return;
+			}
+
 			musb_writeb(mbase, MUSB_POWER,
-				power & ~MUSB_POWER_RESUME);
-			msleep(1);
+				    power & ~MUSB_POWER_RESUME);
+
+			/* Give the core 1 ms to clear MUSB_POWER_RESUME */
+			schedule_delayed_work(&musb->deassert_reset_work,
+					      msecs_to_jiffies(1));
+			return;
 		}
 
 		power &= 0xf0;
@@ -180,7 +191,8 @@
 
 		musb->port1_status |= USB_PORT_STAT_RESET;
 		musb->port1_status &= ~USB_PORT_STAT_ENABLE;
-		schedule_delayed_work(&musb->deassert_reset_work, 50);
+		schedule_delayed_work(&musb->deassert_reset_work,
+				      msecs_to_jiffies(50));
 	} else {
 		dev_dbg(musb->controller, "root port reset stopped\n");
 		musb_writeb(mbase, MUSB_POWER,
diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c
index 2a408cd..8aa59a2 100644
--- a/drivers/usb/musb/omap2430.c
+++ b/drivers/usb/musb/omap2430.c
@@ -659,7 +659,6 @@
 				OTG_INTERFSEL);
 
 		omap2430_low_level_exit(musb);
-		phy_power_off(musb->phy);
 	}
 
 	return 0;
@@ -674,7 +673,6 @@
 		omap2430_low_level_init(musb);
 		musb_writel(musb->mregs, OTG_INTERFSEL,
 				musb->context.otg_interfsel);
-		phy_power_on(musb->phy);
 	}
 
 	return 0;
diff --git a/drivers/usb/phy/phy-msm-usb.c b/drivers/usb/phy/phy-msm-usb.c
index 8546c8d..d204f74 100644
--- a/drivers/usb/phy/phy-msm-usb.c
+++ b/drivers/usb/phy/phy-msm-usb.c
@@ -159,32 +159,6 @@
 	return rc;
 }
 
-#ifdef CONFIG_PM_SLEEP
-#define USB_PHY_SUSP_DIG_VOL  500000
-static int msm_hsusb_config_vddcx(int high)
-{
-	int max_vol = USB_PHY_VDD_DIG_VOL_MAX;
-	int min_vol;
-	int ret;
-
-	if (high)
-		min_vol = USB_PHY_VDD_DIG_VOL_MIN;
-	else
-		min_vol = USB_PHY_SUSP_DIG_VOL;
-
-	ret = regulator_set_voltage(hsusb_vddcx, min_vol, max_vol);
-	if (ret) {
-		pr_err("%s: unable to set the voltage for regulator "
-			"HSUSB_VDDCX\n", __func__);
-		return ret;
-	}
-
-	pr_debug("%s: min_vol:%d max_vol:%d\n", __func__, min_vol, max_vol);
-
-	return ret;
-}
-#endif
-
 static int msm_hsusb_ldo_set_mode(int on)
 {
 	int ret = 0;
@@ -440,7 +414,32 @@
 #define PHY_SUSPEND_TIMEOUT_USEC	(500 * 1000)
 #define PHY_RESUME_TIMEOUT_USEC	(100 * 1000)
 
-#ifdef CONFIG_PM_SLEEP
+#ifdef CONFIG_PM
+
+#define USB_PHY_SUSP_DIG_VOL  500000
+static int msm_hsusb_config_vddcx(int high)
+{
+	int max_vol = USB_PHY_VDD_DIG_VOL_MAX;
+	int min_vol;
+	int ret;
+
+	if (high)
+		min_vol = USB_PHY_VDD_DIG_VOL_MIN;
+	else
+		min_vol = USB_PHY_SUSP_DIG_VOL;
+
+	ret = regulator_set_voltage(hsusb_vddcx, min_vol, max_vol);
+	if (ret) {
+		pr_err("%s: unable to set the voltage for regulator "
+			"HSUSB_VDDCX\n", __func__);
+		return ret;
+	}
+
+	pr_debug("%s: min_vol:%d max_vol:%d\n", __func__, min_vol, max_vol);
+
+	return ret;
+}
+
 static int msm_otg_suspend(struct msm_otg *motg)
 {
 	struct usb_phy *phy = &motg->phy;
@@ -1733,22 +1732,18 @@
 }
 #endif
 
-#ifdef CONFIG_PM
 static const struct dev_pm_ops msm_otg_dev_pm_ops = {
 	SET_SYSTEM_SLEEP_PM_OPS(msm_otg_pm_suspend, msm_otg_pm_resume)
 	SET_RUNTIME_PM_OPS(msm_otg_runtime_suspend, msm_otg_runtime_resume,
 				msm_otg_runtime_idle)
 };
-#endif
 
 static struct platform_driver msm_otg_driver = {
 	.remove = msm_otg_remove,
 	.driver = {
 		.name = DRIVER_NAME,
 		.owner = THIS_MODULE,
-#ifdef CONFIG_PM
 		.pm = &msm_otg_dev_pm_ops,
-#endif
 	},
 };
 
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index ee1f00f..44ab129 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -907,6 +907,8 @@
 	/* Crucible Devices */
 	{ USB_DEVICE(FTDI_VID, FTDI_CT_COMET_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_Z3X_PID) },
+	/* Cressi Devices */
+	{ USB_DEVICE(FTDI_VID, FTDI_CRESSI_PID) },
 	{ }					/* Terminating entry */
 };
 
diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h
index 1e2d369..e599fbf 100644
--- a/drivers/usb/serial/ftdi_sio_ids.h
+++ b/drivers/usb/serial/ftdi_sio_ids.h
@@ -1320,3 +1320,9 @@
  * Manufacturer: Smart GSM Team
  */
 #define FTDI_Z3X_PID		0x0011
+
+/*
+ * Product: Cressi PC Interface
+ * Manufacturer: Cressi
+ */
+#define FTDI_CRESSI_PID		0x87d0
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index 216d20a..68fc9fe 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -1526,7 +1526,8 @@
 	/* Cinterion */
 	{ USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_EU3_E) },
 	{ USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_EU3_P) },
-	{ USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_PH8) },
+	{ USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_PH8),
+		.driver_info = (kernel_ulong_t)&net_intf4_blacklist },
 	{ USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_AHXX) },
 	{ USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_PLXX),
 		.driver_info = (kernel_ulong_t)&net_intf4_blacklist },
diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c
index 9a68409..a0fa5de 100644
--- a/drivers/vhost/net.c
+++ b/drivers/vhost/net.c
@@ -70,7 +70,12 @@
 };
 
 struct vhost_net_ubuf_ref {
-	struct kref kref;
+	/* refcount follows semantics similar to kref:
+	 *  0: object is released
+	 *  1: no outstanding ubufs
+	 * >1: outstanding ubufs
+	 */
+	atomic_t refcount;
 	wait_queue_head_t wait;
 	struct vhost_virtqueue *vq;
 };
@@ -116,14 +121,6 @@
 	vhost_net_zcopy_mask |= 0x1 << vq;
 }
 
-static void vhost_net_zerocopy_done_signal(struct kref *kref)
-{
-	struct vhost_net_ubuf_ref *ubufs;
-
-	ubufs = container_of(kref, struct vhost_net_ubuf_ref, kref);
-	wake_up(&ubufs->wait);
-}
-
 static struct vhost_net_ubuf_ref *
 vhost_net_ubuf_alloc(struct vhost_virtqueue *vq, bool zcopy)
 {
@@ -134,21 +131,24 @@
 	ubufs = kmalloc(sizeof(*ubufs), GFP_KERNEL);
 	if (!ubufs)
 		return ERR_PTR(-ENOMEM);
-	kref_init(&ubufs->kref);
+	atomic_set(&ubufs->refcount, 1);
 	init_waitqueue_head(&ubufs->wait);
 	ubufs->vq = vq;
 	return ubufs;
 }
 
-static void vhost_net_ubuf_put(struct vhost_net_ubuf_ref *ubufs)
+static int vhost_net_ubuf_put(struct vhost_net_ubuf_ref *ubufs)
 {
-	kref_put(&ubufs->kref, vhost_net_zerocopy_done_signal);
+	int r = atomic_sub_return(1, &ubufs->refcount);
+	if (unlikely(!r))
+		wake_up(&ubufs->wait);
+	return r;
 }
 
 static void vhost_net_ubuf_put_and_wait(struct vhost_net_ubuf_ref *ubufs)
 {
-	kref_put(&ubufs->kref, vhost_net_zerocopy_done_signal);
-	wait_event(ubufs->wait, !atomic_read(&ubufs->kref.refcount));
+	vhost_net_ubuf_put(ubufs);
+	wait_event(ubufs->wait, !atomic_read(&ubufs->refcount));
 }
 
 static void vhost_net_ubuf_put_wait_and_free(struct vhost_net_ubuf_ref *ubufs)
@@ -306,23 +306,26 @@
 {
 	struct vhost_net_ubuf_ref *ubufs = ubuf->ctx;
 	struct vhost_virtqueue *vq = ubufs->vq;
-	int cnt = atomic_read(&ubufs->kref.refcount);
+	int cnt;
+
+	rcu_read_lock_bh();
 
 	/* set len to mark this desc buffers done DMA */
 	vq->heads[ubuf->desc].len = success ?
 		VHOST_DMA_DONE_LEN : VHOST_DMA_FAILED_LEN;
-	vhost_net_ubuf_put(ubufs);
+	cnt = vhost_net_ubuf_put(ubufs);
 
 	/*
 	 * Trigger polling thread if guest stopped submitting new buffers:
-	 * in this case, the refcount after decrement will eventually reach 1
-	 * so here it is 2.
+	 * in this case, the refcount after decrement will eventually reach 1.
 	 * We also trigger polling periodically after each 16 packets
 	 * (the value 16 here is more or less arbitrary, it's tuned to trigger
 	 * less than 10% of times).
 	 */
-	if (cnt <= 2 || !(cnt % 16))
+	if (cnt <= 1 || !(cnt % 16))
 		vhost_poll_queue(&vq->poll);
+
+	rcu_read_unlock_bh();
 }
 
 /* Expects to be always run from workqueue - which acts as
@@ -420,7 +423,7 @@
 			msg.msg_control = ubuf;
 			msg.msg_controllen = sizeof(ubuf);
 			ubufs = nvq->ubufs;
-			kref_get(&ubufs->kref);
+			atomic_inc(&ubufs->refcount);
 			nvq->upend_idx = (nvq->upend_idx + 1) % UIO_MAXIOV;
 		} else {
 			msg.msg_control = NULL;
@@ -780,7 +783,7 @@
 		vhost_net_ubuf_put_and_wait(n->vqs[VHOST_NET_VQ_TX].ubufs);
 		mutex_lock(&n->vqs[VHOST_NET_VQ_TX].vq.mutex);
 		n->tx_flush = false;
-		kref_init(&n->vqs[VHOST_NET_VQ_TX].ubufs->kref);
+		atomic_set(&n->vqs[VHOST_NET_VQ_TX].ubufs->refcount, 1);
 		mutex_unlock(&n->vqs[VHOST_NET_VQ_TX].vq.mutex);
 	}
 }
@@ -800,6 +803,8 @@
 		fput(tx_sock->file);
 	if (rx_sock)
 		fput(rx_sock->file);
+	/* Make sure no callbacks are outstanding */
+	synchronize_rcu_bh();
 	/* We do an extra flush before freeing memory,
 	 * since jobs can re-queue themselves. */
 	vhost_net_flush(n);
diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c
index 0a025b8..e48d4a6 100644
--- a/drivers/vhost/scsi.c
+++ b/drivers/vhost/scsi.c
@@ -1001,6 +1001,12 @@
 			break;
 		}
 
+		/* virtio-scsi spec requires byte 0 of the lun to be 1 */
+		if (unlikely(v_req.lun[0] != 1)) {
+			vhost_scsi_send_bad_target(vs, vq, head, out);
+			continue;
+		}
+
 		/* Extract the tpgt */
 		target = v_req.lun[1];
 		tpg = ACCESS_ONCE(vs_tpg[target]);
diff --git a/drivers/watchdog/w83697hf_wdt.c b/drivers/watchdog/w83697hf_wdt.c
index aaf2995..68b45fc 100644
--- a/drivers/watchdog/w83697hf_wdt.c
+++ b/drivers/watchdog/w83697hf_wdt.c
@@ -402,7 +402,7 @@
 
 	if (!found) {
 		pr_err("No W83697HF/HG could be found\n");
-		ret = -EIO;
+		ret = -ENODEV;
 		goto out;
 	}
 
diff --git a/fs/ceph/acl.c b/fs/ceph/acl.c
index 4c2d452..21887d6 100644
--- a/fs/ceph/acl.c
+++ b/fs/ceph/acl.c
@@ -54,11 +54,6 @@
 	return acl;
 }
 
-void ceph_forget_all_cached_acls(struct inode *inode)
-{
-	forget_all_cached_acls(inode);
-}
-
 struct posix_acl *ceph_get_acl(struct inode *inode, int type)
 {
 	int size;
@@ -160,11 +155,7 @@
 			goto out_dput;
 	}
 
-	if (value)
-		ret = __ceph_setxattr(dentry, name, value, size, 0);
-	else
-		ret = __ceph_removexattr(dentry, name);
-
+	ret = __ceph_setxattr(dentry, name, value, size, 0);
 	if (ret) {
 		if (new_mode != old_mode) {
 			newattrs.ia_mode = old_mode;
diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c
index 6da4df8..45eda6d 100644
--- a/fs/ceph/dir.c
+++ b/fs/ceph/dir.c
@@ -100,6 +100,14 @@
 	return p & 0xffffffff;
 }
 
+static int fpos_cmp(loff_t l, loff_t r)
+{
+	int v = ceph_frag_compare(fpos_frag(l), fpos_frag(r));
+	if (v)
+		return v;
+	return (int)(fpos_off(l) - fpos_off(r));
+}
+
 /*
  * When possible, we try to satisfy a readdir by peeking at the
  * dcache.  We make this work by carefully ordering dentries on
@@ -156,7 +164,7 @@
 		if (!d_unhashed(dentry) && dentry->d_inode &&
 		    ceph_snap(dentry->d_inode) != CEPH_SNAPDIR &&
 		    ceph_ino(dentry->d_inode) != CEPH_INO_CEPH &&
-		    ctx->pos <= di->offset)
+		    fpos_cmp(ctx->pos, di->offset) <= 0)
 			break;
 		dout(" skipping %p %.*s at %llu (%llu)%s%s\n", dentry,
 		     dentry->d_name.len, dentry->d_name.name, di->offset,
@@ -695,9 +703,8 @@
 	ceph_mdsc_put_request(req);
 
 	if (!err)
-		err = ceph_init_acl(dentry, dentry->d_inode, dir);
-
-	if (err)
+		ceph_init_acl(dentry, dentry->d_inode, dir);
+	else
 		d_drop(dentry);
 	return err;
 }
@@ -735,7 +742,9 @@
 	if (!err && !req->r_reply_info.head->is_dentry)
 		err = ceph_handle_notrace_create(dir, dentry);
 	ceph_mdsc_put_request(req);
-	if (err)
+	if (!err)
+		ceph_init_acl(dentry, dentry->d_inode, dir);
+	else
 		d_drop(dentry);
 	return err;
 }
@@ -776,7 +785,9 @@
 		err = ceph_handle_notrace_create(dir, dentry);
 	ceph_mdsc_put_request(req);
 out:
-	if (err < 0)
+	if (!err)
+		ceph_init_acl(dentry, dentry->d_inode, dir);
+	else
 		d_drop(dentry);
 	return err;
 }
diff --git a/fs/ceph/file.c b/fs/ceph/file.c
index dfd2ce3..09c7afe 100644
--- a/fs/ceph/file.c
+++ b/fs/ceph/file.c
@@ -286,6 +286,7 @@
 	} else {
 		dout("atomic_open finish_open on dn %p\n", dn);
 		if (req->r_op == CEPH_MDS_OP_CREATE && req->r_reply_info.has_create_ino) {
+			ceph_init_acl(dentry, dentry->d_inode, dir);
 			*opened |= FILE_CREATED;
 		}
 		err = finish_open(file, dentry, ceph_open, opened);
diff --git a/fs/ceph/super.c b/fs/ceph/super.c
index 2df963f..10a4ccb 100644
--- a/fs/ceph/super.c
+++ b/fs/ceph/super.c
@@ -144,7 +144,11 @@
 	Opt_ino32,
 	Opt_noino32,
 	Opt_fscache,
-	Opt_nofscache
+	Opt_nofscache,
+#ifdef CONFIG_CEPH_FS_POSIX_ACL
+	Opt_acl,
+#endif
+	Opt_noacl
 };
 
 static match_table_t fsopt_tokens = {
@@ -172,6 +176,10 @@
 	{Opt_noino32, "noino32"},
 	{Opt_fscache, "fsc"},
 	{Opt_nofscache, "nofsc"},
+#ifdef CONFIG_CEPH_FS_POSIX_ACL
+	{Opt_acl, "acl"},
+#endif
+	{Opt_noacl, "noacl"},
 	{-1, NULL}
 };
 
@@ -271,6 +279,14 @@
 	case Opt_nofscache:
 		fsopt->flags &= ~CEPH_MOUNT_OPT_FSCACHE;
 		break;
+#ifdef CONFIG_CEPH_FS_POSIX_ACL
+	case Opt_acl:
+		fsopt->sb_flags |= MS_POSIXACL;
+		break;
+#endif
+	case Opt_noacl:
+		fsopt->sb_flags &= ~MS_POSIXACL;
+		break;
 	default:
 		BUG_ON(token);
 	}
@@ -438,6 +454,13 @@
 	else
 		seq_puts(m, ",nofsc");
 
+#ifdef CONFIG_CEPH_FS_POSIX_ACL
+	if (fsopt->sb_flags & MS_POSIXACL)
+		seq_puts(m, ",acl");
+	else
+		seq_puts(m, ",noacl");
+#endif
+
 	if (fsopt->wsize)
 		seq_printf(m, ",wsize=%d", fsopt->wsize);
 	if (fsopt->rsize != CEPH_RSIZE_DEFAULT)
@@ -819,9 +842,6 @@
 
 	s->s_flags = fsc->mount_options->sb_flags;
 	s->s_maxbytes = 1ULL << 40;  /* temp value until we get mdsmap */
-#ifdef CONFIG_CEPH_FS_POSIX_ACL
-	s->s_flags |= MS_POSIXACL;
-#endif
 
 	s->s_xattr = ceph_xattr_handlers;
 	s->s_fs_info = fsc;
@@ -911,6 +931,10 @@
 	struct ceph_options *opt = NULL;
 
 	dout("ceph_mount\n");
+
+#ifdef CONFIG_CEPH_FS_POSIX_ACL
+	flags |= MS_POSIXACL;
+#endif
 	err = parse_mount_options(&fsopt, &opt, flags, data, dev_name, &path);
 	if (err < 0) {
 		res = ERR_PTR(err);
diff --git a/fs/ceph/super.h b/fs/ceph/super.h
index 19793b5..d8801a9 100644
--- a/fs/ceph/super.h
+++ b/fs/ceph/super.h
@@ -13,6 +13,7 @@
 #include <linux/wait.h>
 #include <linux/writeback.h>
 #include <linux/slab.h>
+#include <linux/posix_acl.h>
 
 #include <linux/ceph/libceph.h>
 
@@ -743,7 +744,11 @@
 struct posix_acl *ceph_get_acl(struct inode *, int);
 int ceph_set_acl(struct inode *inode, struct posix_acl *acl, int type);
 int ceph_init_acl(struct dentry *, struct inode *, struct inode *);
-void ceph_forget_all_cached_acls(struct inode *inode);
+
+static inline void ceph_forget_all_cached_acls(struct inode *inode)
+{
+       forget_all_cached_acls(inode);
+}
 
 #else
 
diff --git a/fs/ceph/xattr.c b/fs/ceph/xattr.c
index 898b656..a55ec37 100644
--- a/fs/ceph/xattr.c
+++ b/fs/ceph/xattr.c
@@ -12,6 +12,9 @@
 #define XATTR_CEPH_PREFIX "ceph."
 #define XATTR_CEPH_PREFIX_LEN (sizeof (XATTR_CEPH_PREFIX) - 1)
 
+static int __remove_xattr(struct ceph_inode_info *ci,
+			  struct ceph_inode_xattr *xattr);
+
 /*
  * List of handlers for synthetic system.* attributes. Other
  * attributes are handled directly.
@@ -319,8 +322,7 @@
 static int __set_xattr(struct ceph_inode_info *ci,
 			   const char *name, int name_len,
 			   const char *val, int val_len,
-			   int dirty,
-			   int should_free_name, int should_free_val,
+			   int flags, int update_xattr,
 			   struct ceph_inode_xattr **newxattr)
 {
 	struct rb_node **p;
@@ -349,12 +351,31 @@
 		xattr = NULL;
 	}
 
+	if (update_xattr) {
+		int err = 0;
+		if (xattr && (flags & XATTR_CREATE))
+			err = -EEXIST;
+		else if (!xattr && (flags & XATTR_REPLACE))
+			err = -ENODATA;
+		if (err) {
+			kfree(name);
+			kfree(val);
+			return err;
+		}
+		if (update_xattr < 0) {
+			if (xattr)
+				__remove_xattr(ci, xattr);
+			kfree(name);
+			return 0;
+		}
+	}
+
 	if (!xattr) {
 		new = 1;
 		xattr = *newxattr;
 		xattr->name = name;
 		xattr->name_len = name_len;
-		xattr->should_free_name = should_free_name;
+		xattr->should_free_name = update_xattr;
 
 		ci->i_xattrs.count++;
 		dout("__set_xattr count=%d\n", ci->i_xattrs.count);
@@ -364,7 +385,7 @@
 		if (xattr->should_free_val)
 			kfree((void *)xattr->val);
 
-		if (should_free_name) {
+		if (update_xattr) {
 			kfree((void *)name);
 			name = xattr->name;
 		}
@@ -379,8 +400,8 @@
 		xattr->val = "";
 
 	xattr->val_len = val_len;
-	xattr->dirty = dirty;
-	xattr->should_free_val = (val && should_free_val);
+	xattr->dirty = update_xattr;
+	xattr->should_free_val = (val && update_xattr);
 
 	if (new) {
 		rb_link_node(&xattr->node, parent, p);
@@ -442,7 +463,7 @@
 			  struct ceph_inode_xattr *xattr)
 {
 	if (!xattr)
-		return -EOPNOTSUPP;
+		return -ENODATA;
 
 	rb_erase(&xattr->node, &ci->i_xattrs.index);
 
@@ -588,7 +609,7 @@
 			p += len;
 
 			err = __set_xattr(ci, name, namelen, val, len,
-					  0, 0, 0, &xattrs[numattr]);
+					  0, 0, &xattrs[numattr]);
 
 			if (err < 0)
 				goto bad;
@@ -850,6 +871,9 @@
 
 	dout("setxattr value=%.*s\n", (int)size, value);
 
+	if (!value)
+		flags |= CEPH_XATTR_REMOVE;
+
 	/* do request */
 	req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_SETXATTR,
 				       USE_AUTH_MDS);
@@ -892,7 +916,7 @@
 	struct ceph_inode_info *ci = ceph_inode(inode);
 	int issued;
 	int err;
-	int dirty;
+	int dirty = 0;
 	int name_len = strlen(name);
 	int val_len = size;
 	char *newname = NULL;
@@ -953,12 +977,14 @@
 		goto retry;
 	}
 
-	err = __set_xattr(ci, newname, name_len, newval,
-			  val_len, 1, 1, 1, &xattr);
+	err = __set_xattr(ci, newname, name_len, newval, val_len,
+			  flags, value ? 1 : -1, &xattr);
 
-	dirty = __ceph_mark_dirty_caps(ci, CEPH_CAP_XATTR_EXCL);
-	ci->i_xattrs.dirty = true;
-	inode->i_ctime = CURRENT_TIME;
+	if (!err) {
+		dirty = __ceph_mark_dirty_caps(ci, CEPH_CAP_XATTR_EXCL);
+		ci->i_xattrs.dirty = true;
+		inode->i_ctime = CURRENT_TIME;
+	}
 
 	spin_unlock(&ci->i_ceph_lock);
 	if (dirty)
diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c
index c819b0b..7ff866d 100644
--- a/fs/cifs/cifsacl.c
+++ b/fs/cifs/cifsacl.c
@@ -865,8 +865,8 @@
 	return rc;
 }
 
-static struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb,
-		__u16 fid, u32 *pacllen)
+struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb,
+		const struct cifs_fid *cifsfid, u32 *pacllen)
 {
 	struct cifs_ntsd *pntsd = NULL;
 	unsigned int xid;
@@ -877,7 +877,8 @@
 		return ERR_CAST(tlink);
 
 	xid = get_xid();
-	rc = CIFSSMBGetCIFSACL(xid, tlink_tcon(tlink), fid, &pntsd, pacllen);
+	rc = CIFSSMBGetCIFSACL(xid, tlink_tcon(tlink), cifsfid->netfid, &pntsd,
+				pacllen);
 	free_xid(xid);
 
 	cifs_put_tlink(tlink);
@@ -946,7 +947,7 @@
 	if (!open_file)
 		return get_cifs_acl_by_path(cifs_sb, path, pacllen);
 
-	pntsd = get_cifs_acl_by_fid(cifs_sb, open_file->fid.netfid, pacllen);
+	pntsd = get_cifs_acl_by_fid(cifs_sb, &open_file->fid, pacllen);
 	cifsFileInfo_put(open_file);
 	return pntsd;
 }
@@ -1006,19 +1007,31 @@
 /* Translate the CIFS ACL (simlar to NTFS ACL) for a file into mode bits */
 int
 cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr,
-		  struct inode *inode, const char *path, const __u16 *pfid)
+		  struct inode *inode, const char *path,
+		  const struct cifs_fid *pfid)
 {
 	struct cifs_ntsd *pntsd = NULL;
 	u32 acllen = 0;
 	int rc = 0;
+	struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
+	struct cifs_tcon *tcon;
 
 	cifs_dbg(NOISY, "converting ACL to mode for %s\n", path);
 
-	if (pfid)
-		pntsd = get_cifs_acl_by_fid(cifs_sb, *pfid, &acllen);
-	else
-		pntsd = get_cifs_acl(cifs_sb, inode, path, &acllen);
+	if (IS_ERR(tlink))
+		return PTR_ERR(tlink);
+	tcon = tlink_tcon(tlink);
 
+	if (pfid && (tcon->ses->server->ops->get_acl_by_fid))
+		pntsd = tcon->ses->server->ops->get_acl_by_fid(cifs_sb, pfid,
+							  &acllen);
+	else if (tcon->ses->server->ops->get_acl)
+		pntsd = tcon->ses->server->ops->get_acl(cifs_sb, inode, path,
+							&acllen);
+	else {
+		cifs_put_tlink(tlink);
+		return -EOPNOTSUPP;
+	}
 	/* if we can retrieve the ACL, now parse Access Control Entries, ACEs */
 	if (IS_ERR(pntsd)) {
 		rc = PTR_ERR(pntsd);
@@ -1030,6 +1043,8 @@
 			cifs_dbg(VFS, "parse sec desc failed rc = %d\n", rc);
 	}
 
+	cifs_put_tlink(tlink);
+
 	return rc;
 }
 
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 86dc28c..cf32f03 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -398,6 +398,8 @@
 			const struct nls_table *, int);
 	struct cifs_ntsd * (*get_acl)(struct cifs_sb_info *, struct inode *,
 			const char *, u32 *);
+	struct cifs_ntsd * (*get_acl_by_fid)(struct cifs_sb_info *,
+			const struct cifs_fid *, u32 *);
 	int (*set_acl)(struct cifs_ntsd *, __u32, struct inode *, const char *,
 			int);
 };
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index d00e09d..acc4ee8 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -151,7 +151,7 @@
 
 extern int cifs_get_inode_info(struct inode **inode, const char *full_path,
 			       FILE_ALL_INFO *data, struct super_block *sb,
-			       int xid, const __u16 *fid);
+			       int xid, const struct cifs_fid *fid);
 extern int cifs_get_inode_info_unix(struct inode **pinode,
 			const unsigned char *search_path,
 			struct super_block *sb, unsigned int xid);
@@ -162,11 +162,13 @@
 				      const unsigned int xid);
 extern int cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb,
 			      struct cifs_fattr *fattr, struct inode *inode,
-			      const char *path, const __u16 *pfid);
+			      const char *path, const struct cifs_fid *pfid);
 extern int id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64,
 					kuid_t, kgid_t);
 extern struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *, struct inode *,
 					const char *, u32 *);
+extern struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *,
+						const struct cifs_fid *, u32 *);
 extern int set_cifs_acl(struct cifs_ntsd *, __u32, struct inode *,
 				const char *, int);
 
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index d3a6796..3db0c5f 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -378,7 +378,7 @@
 					      xid);
 	else {
 		rc = cifs_get_inode_info(&newinode, full_path, buf, inode->i_sb,
-					 xid, &fid->netfid);
+					 xid, fid);
 		if (newinode) {
 			if (server->ops->set_lease_key)
 				server->ops->set_lease_key(newinode, fid);
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 7555846..53c1507 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -244,7 +244,7 @@
 					      xid);
 	else
 		rc = cifs_get_inode_info(&inode, full_path, buf, inode->i_sb,
-					 xid, &fid->netfid);
+					 xid, fid);
 
 out:
 	kfree(buf);
@@ -2389,7 +2389,7 @@
 		 unsigned long nr_segs, loff_t *poffset)
 {
 	unsigned long nr_pages, i;
-	size_t copied, len, cur_len;
+	size_t bytes, copied, len, cur_len;
 	ssize_t total_written = 0;
 	loff_t offset;
 	struct iov_iter it;
@@ -2444,14 +2444,45 @@
 
 		save_len = cur_len;
 		for (i = 0; i < nr_pages; i++) {
-			copied = min_t(const size_t, cur_len, PAGE_SIZE);
+			bytes = min_t(const size_t, cur_len, PAGE_SIZE);
 			copied = iov_iter_copy_from_user(wdata->pages[i], &it,
-							 0, copied);
+							 0, bytes);
 			cur_len -= copied;
 			iov_iter_advance(&it, copied);
+			/*
+			 * If we didn't copy as much as we expected, then that
+			 * may mean we trod into an unmapped area. Stop copying
+			 * at that point. On the next pass through the big
+			 * loop, we'll likely end up getting a zero-length
+			 * write and bailing out of it.
+			 */
+			if (copied < bytes)
+				break;
 		}
 		cur_len = save_len - cur_len;
 
+		/*
+		 * If we have no data to send, then that probably means that
+		 * the copy above failed altogether. That's most likely because
+		 * the address in the iovec was bogus. Set the rc to -EFAULT,
+		 * free anything we allocated and bail out.
+		 */
+		if (!cur_len) {
+			for (i = 0; i < nr_pages; i++)
+				put_page(wdata->pages[i]);
+			kfree(wdata);
+			rc = -EFAULT;
+			break;
+		}
+
+		/*
+		 * i + 1 now represents the number of pages we actually used in
+		 * the copy phase above. Bring nr_pages down to that, and free
+		 * any pages that we didn't use.
+		 */
+		for ( ; nr_pages > i + 1; nr_pages--)
+			put_page(wdata->pages[nr_pages - 1]);
+
 		wdata->sync_mode = WB_SYNC_ALL;
 		wdata->nr_pages = nr_pages;
 		wdata->offset = (__u64)offset;
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index be58b8f..aadc2b6 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -677,7 +677,7 @@
 int
 cifs_get_inode_info(struct inode **inode, const char *full_path,
 		    FILE_ALL_INFO *data, struct super_block *sb, int xid,
-		    const __u16 *fid)
+		    const struct cifs_fid *fid)
 {
 	bool validinum = false;
 	__u16 srchflgs;
diff --git a/fs/cifs/smb1ops.c b/fs/cifs/smb1ops.c
index bfd66d8..526fb89 100644
--- a/fs/cifs/smb1ops.c
+++ b/fs/cifs/smb1ops.c
@@ -1073,6 +1073,7 @@
 #endif /* CIFS_XATTR */
 #ifdef CONFIG_CIFS_ACL
 	.get_acl = get_cifs_acl,
+	.get_acl_by_fid = get_cifs_acl_by_fid,
 	.set_acl = set_cifs_acl,
 #endif /* CIFS_ACL */
 };
diff --git a/fs/cifs/smb2glob.h b/fs/cifs/smb2glob.h
index c383508..bc0bb9c 100644
--- a/fs/cifs/smb2glob.h
+++ b/fs/cifs/smb2glob.h
@@ -57,4 +57,7 @@
 #define SMB2_CMACAES_SIZE (16)
 #define SMB3_SIGNKEY_SIZE (16)
 
+/* Maximum buffer size value we can send with 1 credit */
+#define SMB2_MAX_BUFFER_SIZE 65536
+
 #endif	/* _SMB2_GLOB_H */
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
index 757da3e..192f51a 100644
--- a/fs/cifs/smb2ops.c
+++ b/fs/cifs/smb2ops.c
@@ -182,11 +182,8 @@
 	/* start with specified wsize, or default */
 	wsize = volume_info->wsize ? volume_info->wsize : CIFS_DEFAULT_IOSIZE;
 	wsize = min_t(unsigned int, wsize, server->max_write);
-	/*
-	 * limit write size to 2 ** 16, because we don't support multicredit
-	 * requests now.
-	 */
-	wsize = min_t(unsigned int, wsize, 2 << 15);
+	/* set it to the maximum buffer size value we can send with 1 credit */
+	wsize = min_t(unsigned int, wsize, SMB2_MAX_BUFFER_SIZE);
 
 	return wsize;
 }
@@ -200,11 +197,8 @@
 	/* start with specified rsize, or default */
 	rsize = volume_info->rsize ? volume_info->rsize : CIFS_DEFAULT_IOSIZE;
 	rsize = min_t(unsigned int, rsize, server->max_read);
-	/*
-	 * limit write size to 2 ** 16, because we don't support multicredit
-	 * requests now.
-	 */
-	rsize = min_t(unsigned int, rsize, 2 << 15);
+	/* set it to the maximum buffer size value we can send with 1 credit */
+	rsize = min_t(unsigned int, rsize, SMB2_MAX_BUFFER_SIZE);
 
 	return rsize;
 }
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c
index a3f7a9c..8603447 100644
--- a/fs/cifs/smb2pdu.c
+++ b/fs/cifs/smb2pdu.c
@@ -413,7 +413,9 @@
 
 	/* SMB2 only has an extended negflavor */
 	server->negflavor = CIFS_NEGFLAVOR_EXTENDED;
-	server->maxBuf = le32_to_cpu(rsp->MaxTransactSize);
+	/* set it to the maximum buffer size value we can send with 1 credit */
+	server->maxBuf = min_t(unsigned int, le32_to_cpu(rsp->MaxTransactSize),
+			       SMB2_MAX_BUFFER_SIZE);
 	server->max_read = le32_to_cpu(rsp->MaxReadSize);
 	server->max_write = le32_to_cpu(rsp->MaxWriteSize);
 	/* BB Do we need to validate the SecurityMode? */
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index ece5556..d3a534f 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -771,6 +771,8 @@
 	if (EXT4_FITS_IN_INODE(raw_inode, einode, xtime))		       \
 		(einode)->xtime.tv_sec = 				       \
 			(signed)le32_to_cpu((raw_inode)->xtime);	       \
+	else								       \
+		(einode)->xtime.tv_sec = 0;				       \
 	if (EXT4_FITS_IN_INODE(raw_inode, einode, xtime ## _extra))	       \
 		ext4_decode_extra_time(&(einode)->xtime,		       \
 				       raw_inode->xtime ## _extra);	       \
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index 10cff47..74bc2d5 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -3906,6 +3906,7 @@
 		} else
 			err = ret;
 		map->m_flags |= EXT4_MAP_MAPPED;
+		map->m_pblk = newblock;
 		if (allocated > map->m_len)
 			allocated = map->m_len;
 		map->m_len = allocated;
diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c
index 6bea806..a2a837f 100644
--- a/fs/ext4/ioctl.c
+++ b/fs/ext4/ioctl.c
@@ -140,7 +140,7 @@
 	handle = ext4_journal_start(inode_bl, EXT4_HT_MOVE_EXTENTS, 2);
 	if (IS_ERR(handle)) {
 		err = -EINVAL;
-		goto swap_boot_out;
+		goto journal_err_out;
 	}
 
 	/* Protect extent tree against block allocations via delalloc */
@@ -198,6 +198,7 @@
 
 	ext4_double_up_write_data_sem(inode, inode_bl);
 
+journal_err_out:
 	ext4_inode_resume_unlocked_dio(inode);
 	ext4_inode_resume_unlocked_dio(inode_bl);
 
diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c
index c5adbb3..f3b84cd 100644
--- a/fs/ext4/resize.c
+++ b/fs/ext4/resize.c
@@ -243,6 +243,7 @@
 	ext4_group_t group;
 	ext4_group_t last_group;
 	unsigned overhead;
+	__u16 uninit_mask = (flexbg_size > 1) ? ~EXT4_BG_BLOCK_UNINIT : ~0;
 
 	BUG_ON(flex_gd->count == 0 || group_data == NULL);
 
@@ -266,7 +267,7 @@
 	src_group++;
 	for (; src_group <= last_group; src_group++) {
 		overhead = ext4_group_overhead_blocks(sb, src_group);
-		if (overhead != 0)
+		if (overhead == 0)
 			last_blk += group_data[src_group - group].blocks_count;
 		else
 			break;
@@ -280,8 +281,7 @@
 		group = ext4_get_group_number(sb, start_blk - 1);
 		group -= group_data[0].group;
 		group_data[group].free_blocks_count--;
-		if (flexbg_size > 1)
-			flex_gd->bg_flags[group] &= ~EXT4_BG_BLOCK_UNINIT;
+		flex_gd->bg_flags[group] &= uninit_mask;
 	}
 
 	/* Allocate inode bitmaps */
@@ -292,22 +292,30 @@
 		group = ext4_get_group_number(sb, start_blk - 1);
 		group -= group_data[0].group;
 		group_data[group].free_blocks_count--;
-		if (flexbg_size > 1)
-			flex_gd->bg_flags[group] &= ~EXT4_BG_BLOCK_UNINIT;
+		flex_gd->bg_flags[group] &= uninit_mask;
 	}
 
 	/* Allocate inode tables */
 	for (; it_index < flex_gd->count; it_index++) {
-		if (start_blk + EXT4_SB(sb)->s_itb_per_group > last_blk)
+		unsigned int itb = EXT4_SB(sb)->s_itb_per_group;
+		ext4_fsblk_t next_group_start;
+
+		if (start_blk + itb > last_blk)
 			goto next_group;
 		group_data[it_index].inode_table = start_blk;
-		group = ext4_get_group_number(sb, start_blk - 1);
+		group = ext4_get_group_number(sb, start_blk);
+		next_group_start = ext4_group_first_block_no(sb, group + 1);
 		group -= group_data[0].group;
-		group_data[group].free_blocks_count -=
-					EXT4_SB(sb)->s_itb_per_group;
-		if (flexbg_size > 1)
-			flex_gd->bg_flags[group] &= ~EXT4_BG_BLOCK_UNINIT;
 
+		if (start_blk + itb > next_group_start) {
+			flex_gd->bg_flags[group + 1] &= uninit_mask;
+			overhead = start_blk + itb - next_group_start;
+			group_data[group + 1].free_blocks_count -= overhead;
+			itb -= overhead;
+		}
+
+		group_data[group].free_blocks_count -= itb;
+		flex_gd->bg_flags[group] &= uninit_mask;
 		start_blk += EXT4_SB(sb)->s_itb_per_group;
 	}
 
@@ -401,7 +409,7 @@
 		start = ext4_group_first_block_no(sb, group);
 		group -= flex_gd->groups[0].group;
 
-		count2 = sb->s_blocksize * 8 - (block - start);
+		count2 = EXT4_BLOCKS_PER_GROUP(sb) - (block - start);
 		if (count2 > count)
 			count2 = count;
 
@@ -620,7 +628,7 @@
 			if (err)
 				goto out;
 			count = group_table_count[j];
-			start = group_data[i].block_bitmap;
+			start = (&group_data[i].block_bitmap)[j];
 			block = start;
 		}
 
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 1f7784d..710fed2 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -3695,16 +3695,22 @@
 	for (i = 0; i < 4; i++)
 		sbi->s_hash_seed[i] = le32_to_cpu(es->s_hash_seed[i]);
 	sbi->s_def_hash_version = es->s_def_hash_version;
-	i = le32_to_cpu(es->s_flags);
-	if (i & EXT2_FLAGS_UNSIGNED_HASH)
-		sbi->s_hash_unsigned = 3;
-	else if ((i & EXT2_FLAGS_SIGNED_HASH) == 0) {
+	if (EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_DIR_INDEX)) {
+		i = le32_to_cpu(es->s_flags);
+		if (i & EXT2_FLAGS_UNSIGNED_HASH)
+			sbi->s_hash_unsigned = 3;
+		else if ((i & EXT2_FLAGS_SIGNED_HASH) == 0) {
 #ifdef __CHAR_UNSIGNED__
-		es->s_flags |= cpu_to_le32(EXT2_FLAGS_UNSIGNED_HASH);
-		sbi->s_hash_unsigned = 3;
+			if (!(sb->s_flags & MS_RDONLY))
+				es->s_flags |=
+					cpu_to_le32(EXT2_FLAGS_UNSIGNED_HASH);
+			sbi->s_hash_unsigned = 3;
 #else
-		es->s_flags |= cpu_to_le32(EXT2_FLAGS_SIGNED_HASH);
+			if (!(sb->s_flags & MS_RDONLY))
+				es->s_flags |=
+					cpu_to_le32(EXT2_FLAGS_SIGNED_HASH);
 #endif
+		}
 	}
 
 	/* Handle clustersize */
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c
index e0259a1..d754e3c 100644
--- a/fs/fs-writeback.c
+++ b/fs/fs-writeback.c
@@ -40,18 +40,13 @@
 struct wb_writeback_work {
 	long nr_pages;
 	struct super_block *sb;
-	/*
-	 * Write only inodes dirtied before this time. Don't forget to set
-	 * older_than_this_is_set when you set this.
-	 */
-	unsigned long older_than_this;
+	unsigned long *older_than_this;
 	enum writeback_sync_modes sync_mode;
 	unsigned int tagged_writepages:1;
 	unsigned int for_kupdate:1;
 	unsigned int range_cyclic:1;
 	unsigned int for_background:1;
 	unsigned int for_sync:1;	/* sync(2) WB_SYNC_ALL writeback */
-	unsigned int older_than_this_is_set:1;
 	enum wb_reason reason;		/* why was writeback initiated? */
 
 	struct list_head list;		/* pending work list */
@@ -252,10 +247,10 @@
 	int do_sb_sort = 0;
 	int moved = 0;
 
-	WARN_ON_ONCE(!work->older_than_this_is_set);
 	while (!list_empty(delaying_queue)) {
 		inode = wb_inode(delaying_queue->prev);
-		if (inode_dirtied_after(inode, work->older_than_this))
+		if (work->older_than_this &&
+		    inode_dirtied_after(inode, *work->older_than_this))
 			break;
 		list_move(&inode->i_wb_list, &tmp);
 		moved++;
@@ -742,8 +737,6 @@
 		.sync_mode	= WB_SYNC_NONE,
 		.range_cyclic	= 1,
 		.reason		= reason,
-		.older_than_this = jiffies,
-		.older_than_this_is_set = 1,
 	};
 
 	spin_lock(&wb->list_lock);
@@ -802,13 +795,12 @@
 {
 	unsigned long wb_start = jiffies;
 	long nr_pages = work->nr_pages;
+	unsigned long oldest_jif;
 	struct inode *inode;
 	long progress;
 
-	if (!work->older_than_this_is_set) {
-		work->older_than_this = jiffies;
-		work->older_than_this_is_set = 1;
-	}
+	oldest_jif = jiffies;
+	work->older_than_this = &oldest_jif;
 
 	spin_lock(&wb->list_lock);
 	for (;;) {
@@ -842,10 +834,10 @@
 		 * safe.
 		 */
 		if (work->for_kupdate) {
-			work->older_than_this = jiffies -
+			oldest_jif = jiffies -
 				msecs_to_jiffies(dirty_expire_interval * 10);
 		} else if (work->for_background)
-			work->older_than_this = jiffies;
+			oldest_jif = jiffies;
 
 		trace_writeback_start(wb->bdi, work);
 		if (list_empty(&wb->b_io))
@@ -1357,21 +1349,18 @@
 
 /**
  * sync_inodes_sb	-	sync sb inode pages
- * @sb:			the superblock
- * @older_than_this:	timestamp
+ * @sb: the superblock
  *
  * This function writes and waits on any dirty inode belonging to this
- * superblock that has been dirtied before given timestamp.
+ * super_block.
  */
-void sync_inodes_sb(struct super_block *sb, unsigned long older_than_this)
+void sync_inodes_sb(struct super_block *sb)
 {
 	DECLARE_COMPLETION_ONSTACK(done);
 	struct wb_writeback_work work = {
 		.sb		= sb,
 		.sync_mode	= WB_SYNC_ALL,
 		.nr_pages	= LONG_MAX,
-		.older_than_this = older_than_this,
-		.older_than_this_is_set = 1,
 		.range_cyclic	= 0,
 		.done		= &done,
 		.reason		= WB_REASON_SYNC,
diff --git a/fs/fscache/object-list.c b/fs/fscache/object-list.c
index e1959ef..b5ebc2d 100644
--- a/fs/fscache/object-list.c
+++ b/fs/fscache/object-list.c
@@ -50,6 +50,8 @@
 	struct fscache_object *xobj;
 	struct rb_node **p = &fscache_object_list.rb_node, *parent = NULL;
 
+	ASSERT(RB_EMPTY_NODE(&obj->objlist_link));
+
 	write_lock(&fscache_object_list_lock);
 
 	while (*p) {
@@ -75,6 +77,9 @@
  */
 void fscache_objlist_remove(struct fscache_object *obj)
 {
+	if (RB_EMPTY_NODE(&obj->objlist_link))
+		return;
+
 	write_lock(&fscache_object_list_lock);
 
 	BUG_ON(RB_EMPTY_ROOT(&fscache_object_list));
diff --git a/fs/fscache/object.c b/fs/fscache/object.c
index 53d35c5..d3b4539 100644
--- a/fs/fscache/object.c
+++ b/fs/fscache/object.c
@@ -314,6 +314,9 @@
 	object->cache = cache;
 	object->cookie = cookie;
 	object->parent = NULL;
+#ifdef CONFIG_FSCACHE_OBJECT_LIST
+	RB_CLEAR_NODE(&object->objlist_link);
+#endif
 
 	object->oob_event_mask = 0;
 	for (t = object->oob_table; t->events; t++)
diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c
index 8360674..60bb365 100644
--- a/fs/jbd2/transaction.c
+++ b/fs/jbd2/transaction.c
@@ -514,11 +514,13 @@
 	 * similarly constrained call sites
 	 */
 	ret = start_this_handle(journal, handle, GFP_NOFS);
-	if (ret < 0)
+	if (ret < 0) {
 		jbd2_journal_free_reserved(handle);
+		return ret;
+	}
 	handle->h_type = type;
 	handle->h_line_no = line_no;
-	return ret;
+	return 0;
 }
 EXPORT_SYMBOL(jbd2_journal_start_reserved);
 
diff --git a/fs/jfs/acl.c b/fs/jfs/acl.c
index e973b85..5a8ea16 100644
--- a/fs/jfs/acl.c
+++ b/fs/jfs/acl.c
@@ -86,6 +86,8 @@
 		rc = posix_acl_equiv_mode(acl, &inode->i_mode);
 		if (rc < 0)
 			return rc;
+		inode->i_ctime = CURRENT_TIME;
+		mark_inode_dirty(inode);
 		if (rc == 0)
 			acl = NULL;
 		break;
diff --git a/fs/kernfs/mount.c b/fs/kernfs/mount.c
index 0d6ce89..0f4152d 100644
--- a/fs/kernfs/mount.c
+++ b/fs/kernfs/mount.c
@@ -94,6 +94,7 @@
  * @fs_type: file_system_type of the fs being mounted
  * @flags: mount flags specified for the mount
  * @root: kernfs_root of the hierarchy being mounted
+ * @new_sb_created: tell the caller if we allocated a new superblock
  * @ns: optional namespace tag of the mount
  *
  * This is to be called from each kernfs user's file_system_type->mount()
@@ -104,7 +105,8 @@
  * The return value can be passed to the vfs layer verbatim.
  */
 struct dentry *kernfs_mount_ns(struct file_system_type *fs_type, int flags,
-			       struct kernfs_root *root, const void *ns)
+			       struct kernfs_root *root, bool *new_sb_created,
+			       const void *ns)
 {
 	struct super_block *sb;
 	struct kernfs_super_info *info;
@@ -122,6 +124,10 @@
 		kfree(info);
 	if (IS_ERR(sb))
 		return ERR_CAST(sb);
+
+	if (new_sb_created)
+		*new_sb_created = !sb->s_root;
+
 	if (!sb->s_root) {
 		error = kernfs_fill_super(sb);
 		if (error) {
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 28a0a3c..360114a 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -164,17 +164,16 @@
 	if (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)) {
 		nfs_fscache_invalidate(inode);
 		nfsi->cache_validity |= NFS_INO_INVALID_ATTR
-					| NFS_INO_INVALID_LABEL
 					| NFS_INO_INVALID_DATA
 					| NFS_INO_INVALID_ACCESS
 					| NFS_INO_INVALID_ACL
 					| NFS_INO_REVAL_PAGECACHE;
 	} else
 		nfsi->cache_validity |= NFS_INO_INVALID_ATTR
-					| NFS_INO_INVALID_LABEL
 					| NFS_INO_INVALID_ACCESS
 					| NFS_INO_INVALID_ACL
 					| NFS_INO_REVAL_PAGECACHE;
+	nfs_zap_label_cache_locked(nfsi);
 }
 
 void nfs_zap_caches(struct inode *inode)
@@ -266,6 +265,13 @@
 }
 
 #ifdef CONFIG_NFS_V4_SECURITY_LABEL
+static void nfs_clear_label_invalid(struct inode *inode)
+{
+	spin_lock(&inode->i_lock);
+	NFS_I(inode)->cache_validity &= ~NFS_INO_INVALID_LABEL;
+	spin_unlock(&inode->i_lock);
+}
+
 void nfs_setsecurity(struct inode *inode, struct nfs_fattr *fattr,
 					struct nfs4_label *label)
 {
@@ -283,6 +289,7 @@
 					__func__,
 					(char *)label->label,
 					label->len, error);
+		nfs_clear_label_invalid(inode);
 	}
 }
 
@@ -1648,7 +1655,7 @@
 		inode->i_blocks = fattr->du.nfs2.blocks;
 
 	/* Update attrtimeo value if we're out of the unstable period */
-	if (invalid & (NFS_INO_INVALID_ATTR|NFS_INO_INVALID_LABEL)) {
+	if (invalid & NFS_INO_INVALID_ATTR) {
 		nfs_inc_stats(inode, NFSIOS_ATTRINVALIDATE);
 		nfsi->attrtimeo = NFS_MINATTRTIMEO(inode);
 		nfsi->attrtimeo_timestamp = now;
@@ -1661,7 +1668,6 @@
 		}
 	}
 	invalid &= ~NFS_INO_INVALID_ATTR;
-	invalid &= ~NFS_INO_INVALID_LABEL;
 	/* Don't invalidate the data if we were to blame */
 	if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode)
 				|| S_ISLNK(inode->i_mode)))
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index 8b5cc04..b46cf5a 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -176,7 +176,8 @@
 extern struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *,
 						      struct nfs_fh *);
 extern int nfs4_update_server(struct nfs_server *server, const char *hostname,
-					struct sockaddr *sap, size_t salen);
+					struct sockaddr *sap, size_t salen,
+					struct net *net);
 extern void nfs_free_server(struct nfs_server *server);
 extern struct nfs_server *nfs_clone_server(struct nfs_server *,
 					   struct nfs_fh *,
@@ -279,9 +280,18 @@
 	}
 	return;
 }
+
+static inline void nfs_zap_label_cache_locked(struct nfs_inode *nfsi)
+{
+	if (nfs_server_capable(&nfsi->vfs_inode, NFS_CAP_SECURITY_LABEL))
+		nfsi->cache_validity |= NFS_INO_INVALID_LABEL;
+}
 #else
 static inline struct nfs4_label *nfs4_label_alloc(struct nfs_server *server, gfp_t flags) { return NULL; }
 static inline void nfs4_label_free(void *label) {}
+static inline void nfs_zap_label_cache_locked(struct nfs_inode *nfsi)
+{
+}
 #endif /* CONFIG_NFS_V4_SECURITY_LABEL */
 
 /* proc.c */
diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c
index aa9bc973..a462ef0 100644
--- a/fs/nfs/nfs3proc.c
+++ b/fs/nfs/nfs3proc.c
@@ -18,6 +18,7 @@
 #include <linux/lockd/bind.h>
 #include <linux/nfs_mount.h>
 #include <linux/freezer.h>
+#include <linux/xattr.h>
 
 #include "iostat.h"
 #include "internal.h"
diff --git a/fs/nfs/nfs4client.c b/fs/nfs/nfs4client.c
index 860ad26..0e46d3d 100644
--- a/fs/nfs/nfs4client.c
+++ b/fs/nfs/nfs4client.c
@@ -1135,6 +1135,7 @@
  * @hostname: new end-point's hostname
  * @sap: new end-point's socket address
  * @salen: size of "sap"
+ * @net: net namespace
  *
  * The nfs_server must be quiescent before this function is invoked.
  * Either its session is drained (NFSv4.1+), or its transport is
@@ -1143,13 +1144,13 @@
  * Returns zero on success, or a negative errno value.
  */
 int nfs4_update_server(struct nfs_server *server, const char *hostname,
-		       struct sockaddr *sap, size_t salen)
+		       struct sockaddr *sap, size_t salen, struct net *net)
 {
 	struct nfs_client *clp = server->nfs_client;
 	struct rpc_clnt *clnt = server->client;
 	struct xprt_create xargs = {
 		.ident		= clp->cl_proto,
-		.net		= &init_net,
+		.net		= net,
 		.dstaddr	= sap,
 		.addrlen	= salen,
 		.servername	= hostname,
@@ -1189,7 +1190,7 @@
 	error = nfs4_set_client(server, hostname, sap, salen, buf,
 				clp->cl_rpcclient->cl_auth->au_flavor,
 				clp->cl_proto, clnt->cl_timeout,
-				clp->cl_minorversion, clp->cl_net);
+				clp->cl_minorversion, net);
 	nfs_put_client(clp);
 	if (error != 0) {
 		nfs_server_insert_lists(server);
diff --git a/fs/nfs/nfs4namespace.c b/fs/nfs/nfs4namespace.c
index 4e7f05d..3d5dbf8 100644
--- a/fs/nfs/nfs4namespace.c
+++ b/fs/nfs/nfs4namespace.c
@@ -121,9 +121,8 @@
 }
 
 static size_t nfs_parse_server_name(char *string, size_t len,
-		struct sockaddr *sa, size_t salen, struct nfs_server *server)
+		struct sockaddr *sa, size_t salen, struct net *net)
 {
-	struct net *net = rpc_net_ns(server->client);
 	ssize_t ret;
 
 	ret = rpc_pton(net, string, len, sa, salen);
@@ -223,6 +222,7 @@
 				     const struct nfs4_fs_location *location)
 {
 	const size_t addr_bufsize = sizeof(struct sockaddr_storage);
+	struct net *net = rpc_net_ns(NFS_SB(mountdata->sb)->client);
 	struct vfsmount *mnt = ERR_PTR(-ENOENT);
 	char *mnt_path;
 	unsigned int maxbuflen;
@@ -248,8 +248,7 @@
 			continue;
 
 		mountdata->addrlen = nfs_parse_server_name(buf->data, buf->len,
-				mountdata->addr, addr_bufsize,
-				NFS_SB(mountdata->sb));
+				mountdata->addr, addr_bufsize, net);
 		if (mountdata->addrlen == 0)
 			continue;
 
@@ -419,6 +418,7 @@
 		const struct nfs4_fs_location *location)
 {
 	const size_t addr_bufsize = sizeof(struct sockaddr_storage);
+	struct net *net = rpc_net_ns(server->client);
 	struct sockaddr *sap;
 	unsigned int s;
 	size_t salen;
@@ -440,7 +440,7 @@
 			continue;
 
 		salen = nfs_parse_server_name(buf->data, buf->len,
-						sap, addr_bufsize, server);
+						sap, addr_bufsize, net);
 		if (salen == 0)
 			continue;
 		rpc_set_port(sap, NFS_PORT);
@@ -450,7 +450,7 @@
 		if (hostname == NULL)
 			break;
 
-		error = nfs4_update_server(server, hostname, sap, salen);
+		error = nfs4_update_server(server, hostname, sap, salen, net);
 		kfree(hostname);
 		if (error == 0)
 			break;
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index e5be725..e1a4721 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -1015,8 +1015,11 @@
 	if (ret == -EIO)
 		/* A lost lock - don't even consider delegations */
 		goto out;
-	if (nfs4_copy_delegation_stateid(dst, state->inode, fmode))
+	/* returns true if delegation stateid found and copied */
+	if (nfs4_copy_delegation_stateid(dst, state->inode, fmode)) {
+		ret = 0;
 		goto out;
+	}
 	if (ret != -ENOENT)
 		/* nfs4_copy_delegation_stateid() didn't over-write
 		 * dst, so it still has the lock stateid which we now
diff --git a/fs/notify/dnotify/dnotify.c b/fs/notify/dnotify/dnotify.c
index 0b9ff43..abc8cbc 100644
--- a/fs/notify/dnotify/dnotify.c
+++ b/fs/notify/dnotify/dnotify.c
@@ -86,7 +86,7 @@
 				struct fsnotify_mark *inode_mark,
 				struct fsnotify_mark *vfsmount_mark,
 				u32 mask, void *data, int data_type,
-				const unsigned char *file_name)
+				const unsigned char *file_name, u32 cookie)
 {
 	struct dnotify_mark *dn_mark;
 	struct dnotify_struct *dn;
diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c
index 0e792f5..dc638f7 100644
--- a/fs/notify/fanotify/fanotify.c
+++ b/fs/notify/fanotify/fanotify.c
@@ -147,7 +147,7 @@
 				 struct fsnotify_mark *inode_mark,
 				 struct fsnotify_mark *fanotify_mark,
 				 u32 mask, void *data, int data_type,
-				 const unsigned char *file_name)
+				 const unsigned char *file_name, u32 cookie)
 {
 	int ret = 0;
 	struct fanotify_event_info *event;
@@ -192,10 +192,12 @@
 
 	ret = fsnotify_add_notify_event(group, fsn_event, fanotify_merge);
 	if (ret) {
-		BUG_ON(mask & FAN_ALL_PERM_EVENTS);
+		/* Permission events shouldn't be merged */
+		BUG_ON(ret == 1 && mask & FAN_ALL_PERM_EVENTS);
 		/* Our event wasn't used in the end. Free it. */
 		fsnotify_destroy_event(group, fsn_event);
-		ret = 0;
+
+		return 0;
 	}
 
 #ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS
diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c
index b6175fa..287a22c 100644
--- a/fs/notify/fanotify/fanotify_user.c
+++ b/fs/notify/fanotify/fanotify_user.c
@@ -698,6 +698,7 @@
 	struct fsnotify_group *group;
 	int f_flags, fd;
 	struct user_struct *user;
+	struct fanotify_event_info *oevent;
 
 	pr_debug("%s: flags=%d event_f_flags=%d\n",
 		__func__, flags, event_f_flags);
@@ -730,8 +731,20 @@
 	group->fanotify_data.user = user;
 	atomic_inc(&user->fanotify_listeners);
 
+	oevent = kmem_cache_alloc(fanotify_event_cachep, GFP_KERNEL);
+	if (unlikely(!oevent)) {
+		fd = -ENOMEM;
+		goto out_destroy_group;
+	}
+	group->overflow_event = &oevent->fse;
+	fsnotify_init_event(group->overflow_event, NULL, FS_Q_OVERFLOW);
+	oevent->tgid = get_pid(task_tgid(current));
+	oevent->path.mnt = NULL;
+	oevent->path.dentry = NULL;
+
 	group->fanotify_data.f_flags = event_f_flags;
 #ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS
+	oevent->response = 0;
 	mutex_init(&group->fanotify_data.access_mutex);
 	init_waitqueue_head(&group->fanotify_data.access_waitq);
 	INIT_LIST_HEAD(&group->fanotify_data.access_list);
diff --git a/fs/notify/fsnotify.c b/fs/notify/fsnotify.c
index 1d4e1ea..9d3e9c5 100644
--- a/fs/notify/fsnotify.c
+++ b/fs/notify/fsnotify.c
@@ -179,7 +179,7 @@
 
 	return group->ops->handle_event(group, to_tell, inode_mark,
 					vfsmount_mark, mask, data, data_is,
-					file_name);
+					file_name, cookie);
 }
 
 /*
diff --git a/fs/notify/group.c b/fs/notify/group.c
index ee674fe..ad19959 100644
--- a/fs/notify/group.c
+++ b/fs/notify/group.c
@@ -55,6 +55,13 @@
 	/* clear the notification queue of all events */
 	fsnotify_flush_notify(group);
 
+	/*
+	 * Destroy overflow event (we cannot use fsnotify_destroy_event() as
+	 * that deliberately ignores overflow events.
+	 */
+	if (group->overflow_event)
+		group->ops->free_event(group->overflow_event);
+
 	fsnotify_put_group(group);
 }
 
@@ -99,7 +106,6 @@
 	INIT_LIST_HEAD(&group->marks_list);
 
 	group->ops = ops;
-	fsnotify_init_event(&group->overflow_event, NULL, FS_Q_OVERFLOW);
 
 	return group;
 }
diff --git a/fs/notify/inotify/inotify.h b/fs/notify/inotify/inotify.h
index 485eef3..ed855ef 100644
--- a/fs/notify/inotify/inotify.h
+++ b/fs/notify/inotify/inotify.h
@@ -27,6 +27,6 @@
 				struct fsnotify_mark *inode_mark,
 				struct fsnotify_mark *vfsmount_mark,
 				u32 mask, void *data, int data_type,
-				const unsigned char *file_name);
+				const unsigned char *file_name, u32 cookie);
 
 extern const struct fsnotify_ops inotify_fsnotify_ops;
diff --git a/fs/notify/inotify/inotify_fsnotify.c b/fs/notify/inotify/inotify_fsnotify.c
index d5ee563..43ab1e1 100644
--- a/fs/notify/inotify/inotify_fsnotify.c
+++ b/fs/notify/inotify/inotify_fsnotify.c
@@ -67,7 +67,7 @@
 			 struct fsnotify_mark *inode_mark,
 			 struct fsnotify_mark *vfsmount_mark,
 			 u32 mask, void *data, int data_type,
-			 const unsigned char *file_name)
+			 const unsigned char *file_name, u32 cookie)
 {
 	struct inotify_inode_mark *i_mark;
 	struct inotify_event_info *event;
@@ -103,6 +103,7 @@
 	fsn_event = &event->fse;
 	fsnotify_init_event(fsn_event, inode, mask);
 	event->wd = i_mark->wd;
+	event->sync_cookie = cookie;
 	event->name_len = len;
 	if (len)
 		strcpy(event->name, file_name);
diff --git a/fs/notify/inotify/inotify_user.c b/fs/notify/inotify/inotify_user.c
index 497395c..78a2ca3 100644
--- a/fs/notify/inotify/inotify_user.c
+++ b/fs/notify/inotify/inotify_user.c
@@ -495,7 +495,7 @@
 
 	/* Queue ignore event for the watch */
 	inotify_handle_event(group, NULL, fsn_mark, NULL, FS_IN_IGNORED,
-			     NULL, FSNOTIFY_EVENT_NONE, NULL);
+			     NULL, FSNOTIFY_EVENT_NONE, NULL, 0);
 
 	i_mark = container_of(fsn_mark, struct inotify_inode_mark, fsn_mark);
 	/* remove this mark from the idr */
@@ -633,11 +633,23 @@
 static struct fsnotify_group *inotify_new_group(unsigned int max_events)
 {
 	struct fsnotify_group *group;
+	struct inotify_event_info *oevent;
 
 	group = fsnotify_alloc_group(&inotify_fsnotify_ops);
 	if (IS_ERR(group))
 		return group;
 
+	oevent = kmalloc(sizeof(struct inotify_event_info), GFP_KERNEL);
+	if (unlikely(!oevent)) {
+		fsnotify_destroy_group(group);
+		return ERR_PTR(-ENOMEM);
+	}
+	group->overflow_event = &oevent->fse;
+	fsnotify_init_event(group->overflow_event, NULL, FS_Q_OVERFLOW);
+	oevent->wd = -1;
+	oevent->sync_cookie = 0;
+	oevent->name_len = 0;
+
 	group->max_events = max_events;
 
 	spin_lock_init(&group->inotify_data.idr_lock);
diff --git a/fs/notify/notification.c b/fs/notify/notification.c
index 18b3c44..1e58402 100644
--- a/fs/notify/notification.c
+++ b/fs/notify/notification.c
@@ -80,7 +80,8 @@
 /*
  * Add an event to the group notification queue.  The group can later pull this
  * event off the queue to deal with.  The function returns 0 if the event was
- * added to the queue, 1 if the event was merged with some other queued event.
+ * added to the queue, 1 if the event was merged with some other queued event,
+ * 2 if the queue of events has overflown.
  */
 int fsnotify_add_notify_event(struct fsnotify_group *group,
 			      struct fsnotify_event *event,
@@ -95,10 +96,14 @@
 	mutex_lock(&group->notification_mutex);
 
 	if (group->q_len >= group->max_events) {
+		ret = 2;
 		/* Queue overflow event only if it isn't already queued */
-		if (list_empty(&group->overflow_event.list))
-			event = &group->overflow_event;
-		ret = 1;
+		if (!list_empty(&group->overflow_event->list)) {
+			mutex_unlock(&group->notification_mutex);
+			return ret;
+		}
+		event = group->overflow_event;
+		goto queue;
 	}
 
 	if (!list_empty(list) && merge) {
@@ -109,6 +114,7 @@
 		}
 	}
 
+queue:
 	group->q_len++;
 	list_add_tail(&event->list, list);
 	mutex_unlock(&group->notification_mutex);
@@ -132,7 +138,11 @@
 
 	event = list_first_entry(&group->notification_list,
 				 struct fsnotify_event, list);
-	list_del(&event->list);
+	/*
+	 * We need to init list head for the case of overflow event so that
+	 * check in fsnotify_add_notify_events() works
+	 */
+	list_del_init(&event->list);
 	group->q_len--;
 
 	return event;
diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c
index 831d49a..cfc8dcc 100644
--- a/fs/quota/dquot.c
+++ b/fs/quota/dquot.c
@@ -581,9 +581,17 @@
 		dqstats_inc(DQST_LOOKUPS);
 		dqput(old_dquot);
 		old_dquot = dquot;
-		ret = fn(dquot, priv);
-		if (ret < 0)
-			goto out;
+		/*
+		 * ->release_dquot() can be racing with us. Our reference
+		 * protects us from new calls to it so just wait for any
+		 * outstanding call and recheck the DQ_ACTIVE_B after that.
+		 */
+		wait_on_dquot(dquot);
+		if (test_bit(DQ_ACTIVE_B, &dquot->dq_flags)) {
+			ret = fn(dquot, priv);
+			if (ret < 0)
+				goto out;
+		}
 		spin_lock(&dq_list_lock);
 		/* We are safe to continue now because our dquot could not
 		 * be moved out of the inuse list while we hold the reference */
diff --git a/fs/reiserfs/do_balan.c b/fs/reiserfs/do_balan.c
index 2b7882b..9a3c68c 100644
--- a/fs/reiserfs/do_balan.c
+++ b/fs/reiserfs/do_balan.c
@@ -324,23 +324,17 @@
 			switch (flag) {
 			case M_INSERT:	/* insert item into L[0] */
 
-				if (item_pos == tb->lnum[0] - 1
-				    && tb->lbytes != -1) {
+				if (item_pos == tb->lnum[0] - 1 && tb->lbytes != -1) {
 					/* part of new item falls into L[0] */
 					int new_item_len;
 					int version;
 
-					ret_val =
-					    leaf_shift_left(tb, tb->lnum[0] - 1,
-							    -1);
+					ret_val = leaf_shift_left(tb, tb->lnum[0] - 1, -1);
 
 					/* Calculate item length to insert to S[0] */
-					new_item_len =
-					    ih_item_len(ih) - tb->lbytes;
+					new_item_len = ih_item_len(ih) - tb->lbytes;
 					/* Calculate and check item length to insert to L[0] */
-					put_ih_item_len(ih,
-							ih_item_len(ih) -
-							new_item_len);
+					put_ih_item_len(ih, ih_item_len(ih) - new_item_len);
 
 					RFALSE(ih_item_len(ih) <= 0,
 					       "PAP-12080: there is nothing to insert into L[0]: ih_item_len=%d",
@@ -349,30 +343,18 @@
 					/* Insert new item into L[0] */
 					buffer_info_init_left(tb, &bi);
 					leaf_insert_into_buf(&bi,
-							     n + item_pos -
-							     ret_val, ih, body,
-							     zeros_num >
-							     ih_item_len(ih) ?
-							     ih_item_len(ih) :
-							     zeros_num);
+							n + item_pos - ret_val, ih, body,
+							zeros_num > ih_item_len(ih) ? ih_item_len(ih) : zeros_num);
 
 					version = ih_version(ih);
 
 					/* Calculate key component, item length and body to insert into S[0] */
-					set_le_ih_k_offset(ih,
-							   le_ih_k_offset(ih) +
-							   (tb->
-							    lbytes <<
-							    (is_indirect_le_ih
-							     (ih) ? tb->tb_sb->
-							     s_blocksize_bits -
-							     UNFM_P_SHIFT :
-							     0)));
+					set_le_ih_k_offset(ih, le_ih_k_offset(ih) +
+							(tb-> lbytes << (is_indirect_le_ih(ih) ? tb->tb_sb-> s_blocksize_bits - UNFM_P_SHIFT : 0)));
 
 					put_ih_item_len(ih, new_item_len);
 					if (tb->lbytes > zeros_num) {
-						body +=
-						    (tb->lbytes - zeros_num);
+						body += (tb->lbytes - zeros_num);
 						zeros_num = 0;
 					} else
 						zeros_num -= tb->lbytes;
@@ -383,15 +365,10 @@
 				} else {
 					/* new item in whole falls into L[0] */
 					/* Shift lnum[0]-1 items to L[0] */
-					ret_val =
-					    leaf_shift_left(tb, tb->lnum[0] - 1,
-							    tb->lbytes);
+					ret_val = leaf_shift_left(tb, tb->lnum[0] - 1, tb->lbytes);
 					/* Insert new item into L[0] */
 					buffer_info_init_left(tb, &bi);
-					leaf_insert_into_buf(&bi,
-							     n + item_pos -
-							     ret_val, ih, body,
-							     zeros_num);
+					leaf_insert_into_buf(&bi, n + item_pos - ret_val, ih, body, zeros_num);
 					tb->insert_size[0] = 0;
 					zeros_num = 0;
 				}
@@ -399,264 +376,117 @@
 
 			case M_PASTE:	/* append item in L[0] */
 
-				if (item_pos == tb->lnum[0] - 1
-				    && tb->lbytes != -1) {
+				if (item_pos == tb->lnum[0] - 1 && tb->lbytes != -1) {
 					/* we must shift the part of the appended item */
-					if (is_direntry_le_ih
-					    (B_N_PITEM_HEAD(tbS0, item_pos))) {
+					if (is_direntry_le_ih(B_N_PITEM_HEAD(tbS0, item_pos))) {
 
 						RFALSE(zeros_num,
 						       "PAP-12090: invalid parameter in case of a directory");
 						/* directory item */
 						if (tb->lbytes > pos_in_item) {
 							/* new directory entry falls into L[0] */
-							struct item_head
-							    *pasted;
-							int l_pos_in_item =
-							    pos_in_item;
+							struct item_head *pasted;
+							int l_pos_in_item = pos_in_item;
 
 							/* Shift lnum[0] - 1 items in whole. Shift lbytes - 1 entries from given directory item */
-							ret_val =
-							    leaf_shift_left(tb,
-									    tb->
-									    lnum
-									    [0],
-									    tb->
-									    lbytes
-									    -
-									    1);
-							if (ret_val
-							    && !item_pos) {
-								pasted =
-								    B_N_PITEM_HEAD
-								    (tb->L[0],
-								     B_NR_ITEMS
-								     (tb->
-								      L[0]) -
-								     1);
-								l_pos_in_item +=
-								    I_ENTRY_COUNT
-								    (pasted) -
-								    (tb->
-								     lbytes -
-								     1);
+							ret_val = leaf_shift_left(tb, tb->lnum[0], tb->lbytes-1);
+							if (ret_val && !item_pos) {
+								pasted = B_N_PITEM_HEAD(tb->L[0], B_NR_ITEMS(tb->L[0]) - 1);
+								l_pos_in_item += I_ENTRY_COUNT(pasted) - (tb->lbytes -1);
 							}
 
 							/* Append given directory entry to directory item */
 							buffer_info_init_left(tb, &bi);
-							leaf_paste_in_buffer
-							    (&bi,
-							     n + item_pos -
-							     ret_val,
-							     l_pos_in_item,
-							     tb->insert_size[0],
-							     body, zeros_num);
+							leaf_paste_in_buffer(&bi, n + item_pos - ret_val, l_pos_in_item, tb->insert_size[0], body, zeros_num);
 
 							/* previous string prepared space for pasting new entry, following string pastes this entry */
 
 							/* when we have merge directory item, pos_in_item has been changed too */
 
 							/* paste new directory entry. 1 is entry number */
-							leaf_paste_entries(&bi,
-									   n +
-									   item_pos
-									   -
-									   ret_val,
-									   l_pos_in_item,
-									   1,
-									   (struct
-									    reiserfs_de_head
-									    *)
-									   body,
-									   body
-									   +
-									   DEH_SIZE,
-									   tb->
-									   insert_size
-									   [0]
-							    );
+							leaf_paste_entries(&bi, n + item_pos - ret_val, l_pos_in_item,
+									   1, (struct reiserfs_de_head *) body,
+									   body + DEH_SIZE, tb->insert_size[0]);
 							tb->insert_size[0] = 0;
 						} else {
 							/* new directory item doesn't fall into L[0] */
 							/* Shift lnum[0]-1 items in whole. Shift lbytes directory entries from directory item number lnum[0] */
-							leaf_shift_left(tb,
-									tb->
-									lnum[0],
-									tb->
-									lbytes);
+							leaf_shift_left(tb, tb->lnum[0], tb->lbytes);
 						}
 						/* Calculate new position to append in item body */
 						pos_in_item -= tb->lbytes;
 					} else {
 						/* regular object */
-						RFALSE(tb->lbytes <= 0,
-						       "PAP-12095: there is nothing to shift to L[0]. lbytes=%d",
-						       tb->lbytes);
-						RFALSE(pos_in_item !=
-						       ih_item_len
-						       (B_N_PITEM_HEAD
-							(tbS0, item_pos)),
+						RFALSE(tb->lbytes <= 0, "PAP-12095: there is nothing to shift to L[0]. lbytes=%d", tb->lbytes);
+						RFALSE(pos_in_item != ih_item_len(B_N_PITEM_HEAD(tbS0, item_pos)),
 						       "PAP-12100: incorrect position to paste: item_len=%d, pos_in_item=%d",
-						       ih_item_len
-						       (B_N_PITEM_HEAD
-							(tbS0, item_pos)),
-						       pos_in_item);
+						       ih_item_len(B_N_PITEM_HEAD(tbS0, item_pos)),pos_in_item);
 
 						if (tb->lbytes >= pos_in_item) {
 							/* appended item will be in L[0] in whole */
 							int l_n;
 
 							/* this bytes number must be appended to the last item of L[h] */
-							l_n =
-							    tb->lbytes -
-							    pos_in_item;
+							l_n = tb->lbytes - pos_in_item;
 
 							/* Calculate new insert_size[0] */
-							tb->insert_size[0] -=
-							    l_n;
+							tb->insert_size[0] -= l_n;
 
-							RFALSE(tb->
-							       insert_size[0] <=
-							       0,
+							RFALSE(tb->insert_size[0] <= 0,
 							       "PAP-12105: there is nothing to paste into L[0]. insert_size=%d",
-							       tb->
-							       insert_size[0]);
-							ret_val =
-							    leaf_shift_left(tb,
-									    tb->
-									    lnum
-									    [0],
-									    ih_item_len
-									    (B_N_PITEM_HEAD
-									     (tbS0,
-									      item_pos)));
+							       tb->insert_size[0]);
+							ret_val = leaf_shift_left(tb, tb->lnum[0], ih_item_len
+									    (B_N_PITEM_HEAD(tbS0, item_pos)));
 							/* Append to body of item in L[0] */
 							buffer_info_init_left(tb, &bi);
 							leaf_paste_in_buffer
-							    (&bi,
-							     n + item_pos -
-							     ret_val,
-							     ih_item_len
-							     (B_N_PITEM_HEAD
-							      (tb->L[0],
-							       n + item_pos -
-							       ret_val)), l_n,
-							     body,
-							     zeros_num >
-							     l_n ? l_n :
-							     zeros_num);
+							    (&bi, n + item_pos - ret_val, ih_item_len
+							     (B_N_PITEM_HEAD(tb->L[0], n + item_pos - ret_val)),
+							     l_n, body,
+							     zeros_num > l_n ? l_n : zeros_num);
 							/* 0-th item in S0 can be only of DIRECT type when l_n != 0 */
 							{
 								int version;
-								int temp_l =
-								    l_n;
+								int temp_l = l_n;
 
-								RFALSE
-								    (ih_item_len
-								     (B_N_PITEM_HEAD
-								      (tbS0,
-								       0)),
+								RFALSE(ih_item_len(B_N_PITEM_HEAD(tbS0, 0)),
 								     "PAP-12106: item length must be 0");
-								RFALSE
-								    (comp_short_le_keys
-								     (B_N_PKEY
-								      (tbS0, 0),
-								      B_N_PKEY
-								      (tb->L[0],
-								       n +
-								       item_pos
-								       -
-								       ret_val)),
+								RFALSE(comp_short_le_keys(B_N_PKEY(tbS0, 0), B_N_PKEY
+								      (tb->L[0], n + item_pos - ret_val)),
 								     "PAP-12107: items must be of the same file");
 								if (is_indirect_le_ih(B_N_PITEM_HEAD(tb->L[0], n + item_pos - ret_val))) {
-									temp_l =
-									    l_n
-									    <<
-									    (tb->
-									     tb_sb->
-									     s_blocksize_bits
-									     -
-									     UNFM_P_SHIFT);
+									temp_l = l_n << (tb->tb_sb-> s_blocksize_bits - UNFM_P_SHIFT);
 								}
 								/* update key of first item in S0 */
-								version =
-								    ih_version
-								    (B_N_PITEM_HEAD
-								     (tbS0, 0));
-								set_le_key_k_offset
-								    (version,
-								     B_N_PKEY
-								     (tbS0, 0),
-								     le_key_k_offset
-								     (version,
-								      B_N_PKEY
-								      (tbS0,
-								       0)) +
-								     temp_l);
+								version = ih_version(B_N_PITEM_HEAD(tbS0, 0));
+								set_le_key_k_offset(version, B_N_PKEY(tbS0, 0),
+								     le_key_k_offset(version,B_N_PKEY(tbS0, 0)) + temp_l);
 								/* update left delimiting key */
-								set_le_key_k_offset
-								    (version,
-								     B_N_PDELIM_KEY
-								     (tb->
-								      CFL[0],
-								      tb->
-								      lkey[0]),
-								     le_key_k_offset
-								     (version,
-								      B_N_PDELIM_KEY
-								      (tb->
-								       CFL[0],
-								       tb->
-								       lkey[0]))
-								     + temp_l);
+								set_le_key_k_offset(version, B_N_PDELIM_KEY(tb->CFL[0], tb->lkey[0]),
+								     le_key_k_offset(version, B_N_PDELIM_KEY(tb->CFL[0], tb->lkey[0])) + temp_l);
 							}
 
 							/* Calculate new body, position in item and insert_size[0] */
 							if (l_n > zeros_num) {
-								body +=
-								    (l_n -
-								     zeros_num);
+								body += (l_n - zeros_num);
 								zeros_num = 0;
 							} else
-								zeros_num -=
-								    l_n;
+								zeros_num -= l_n;
 							pos_in_item = 0;
 
-							RFALSE
-							    (comp_short_le_keys
-							     (B_N_PKEY(tbS0, 0),
-							      B_N_PKEY(tb->L[0],
-								       B_NR_ITEMS
-								       (tb->
-									L[0]) -
-								       1))
-							     ||
-							     !op_is_left_mergeable
-							     (B_N_PKEY(tbS0, 0),
-							      tbS0->b_size)
-							     ||
-							     !op_is_left_mergeable
-							     (B_N_PDELIM_KEY
-							      (tb->CFL[0],
-							       tb->lkey[0]),
-							      tbS0->b_size),
+							RFALSE(comp_short_le_keys(B_N_PKEY(tbS0, 0), B_N_PKEY(tb->L[0], B_NR_ITEMS(tb->L[0]) - 1))
+							     || !op_is_left_mergeable(B_N_PKEY(tbS0, 0), tbS0->b_size)
+							     || !op_is_left_mergeable(B_N_PDELIM_KEY(tb->CFL[0], tb->lkey[0]), tbS0->b_size),
 							     "PAP-12120: item must be merge-able with left neighboring item");
 						} else {	/* only part of the appended item will be in L[0] */
 
 							/* Calculate position in item for append in S[0] */
-							pos_in_item -=
-							    tb->lbytes;
+							pos_in_item -= tb->lbytes;
 
-							RFALSE(pos_in_item <= 0,
-							       "PAP-12125: no place for paste. pos_in_item=%d",
-							       pos_in_item);
+							RFALSE(pos_in_item <= 0, "PAP-12125: no place for paste. pos_in_item=%d", pos_in_item);
 
 							/* Shift lnum[0] - 1 items in whole. Shift lbytes - 1 byte from item number lnum[0] */
-							leaf_shift_left(tb,
-									tb->
-									lnum[0],
-									tb->
-									lbytes);
+							leaf_shift_left(tb, tb->lnum[0], tb->lbytes);
 						}
 					}
 				} else {	/* appended item will be in L[0] in whole */
@@ -665,52 +495,30 @@
 
 					if (!item_pos && op_is_left_mergeable(B_N_PKEY(tbS0, 0), tbS0->b_size)) {	/* if we paste into first item of S[0] and it is left mergable */
 						/* then increment pos_in_item by the size of the last item in L[0] */
-						pasted =
-						    B_N_PITEM_HEAD(tb->L[0],
-								   n - 1);
+						pasted = B_N_PITEM_HEAD(tb->L[0], n - 1);
 						if (is_direntry_le_ih(pasted))
-							pos_in_item +=
-							    ih_entry_count
-							    (pasted);
+							pos_in_item += ih_entry_count(pasted);
 						else
-							pos_in_item +=
-							    ih_item_len(pasted);
+							pos_in_item += ih_item_len(pasted);
 					}
 
 					/* Shift lnum[0] - 1 items in whole. Shift lbytes - 1 byte from item number lnum[0] */
-					ret_val =
-					    leaf_shift_left(tb, tb->lnum[0],
-							    tb->lbytes);
+					ret_val = leaf_shift_left(tb, tb->lnum[0], tb->lbytes);
 					/* Append to body of item in L[0] */
 					buffer_info_init_left(tb, &bi);
-					leaf_paste_in_buffer(&bi,
-							     n + item_pos -
-							     ret_val,
+					leaf_paste_in_buffer(&bi, n + item_pos - ret_val,
 							     pos_in_item,
 							     tb->insert_size[0],
 							     body, zeros_num);
 
 					/* if appended item is directory, paste entry */
-					pasted =
-					    B_N_PITEM_HEAD(tb->L[0],
-							   n + item_pos -
-							   ret_val);
+					pasted = B_N_PITEM_HEAD(tb->L[0], n + item_pos - ret_val);
 					if (is_direntry_le_ih(pasted))
-						leaf_paste_entries(&bi,
-								   n +
-								   item_pos -
-								   ret_val,
-								   pos_in_item,
-								   1,
-								   (struct
-								    reiserfs_de_head
-								    *)body,
-								   body +
-								   DEH_SIZE,
-								   tb->
-								   insert_size
-								   [0]
-						    );
+						leaf_paste_entries(&bi, n + item_pos - ret_val,
+								   pos_in_item, 1,
+								   (struct reiserfs_de_head *) body,
+								   body + DEH_SIZE,
+								   tb->insert_size[0]);
 					/* if appended item is indirect item, put unformatted node into un list */
 					if (is_indirect_le_ih(pasted))
 						set_ih_free_space(pasted, 0);
@@ -722,13 +530,7 @@
 				reiserfs_panic(tb->tb_sb, "PAP-12130",
 					       "lnum > 0: unexpected mode: "
 					       " %s(%d)",
-					       (flag ==
-						M_DELETE) ? "DELETE" : ((flag ==
-									 M_CUT)
-									? "CUT"
-									:
-									"UNKNOWN"),
-					       flag);
+					       (flag == M_DELETE) ? "DELETE" : ((flag == M_CUT) ? "CUT" : "UNKNOWN"), flag);
 			}
 		} else {
 			/* new item doesn't fall into L[0] */
@@ -748,14 +550,12 @@
 		case M_INSERT:	/* insert item */
 			if (n - tb->rnum[0] < item_pos) {	/* new item or its part falls to R[0] */
 				if (item_pos == n - tb->rnum[0] + 1 && tb->rbytes != -1) {	/* part of new item falls into R[0] */
-					loff_t old_key_comp, old_len,
-					    r_zeros_number;
+					loff_t old_key_comp, old_len, r_zeros_number;
 					const char *r_body;
 					int version;
 					loff_t offset;
 
-					leaf_shift_right(tb, tb->rnum[0] - 1,
-							 -1);
+					leaf_shift_right(tb, tb->rnum[0] - 1, -1);
 
 					version = ih_version(ih);
 					/* Remember key component and item length */
@@ -763,29 +563,17 @@
 					old_len = ih_item_len(ih);
 
 					/* Calculate key component and item length to insert into R[0] */
-					offset =
-					    le_ih_k_offset(ih) +
-					    ((old_len -
-					      tb->
-					      rbytes) << (is_indirect_le_ih(ih)
-							  ? tb->tb_sb->
-							  s_blocksize_bits -
-							  UNFM_P_SHIFT : 0));
+					offset = le_ih_k_offset(ih) + ((old_len - tb->rbytes) << (is_indirect_le_ih(ih) ? tb->tb_sb->s_blocksize_bits - UNFM_P_SHIFT : 0));
 					set_le_ih_k_offset(ih, offset);
 					put_ih_item_len(ih, tb->rbytes);
 					/* Insert part of the item into R[0] */
 					buffer_info_init_right(tb, &bi);
 					if ((old_len - tb->rbytes) > zeros_num) {
 						r_zeros_number = 0;
-						r_body =
-						    body + (old_len -
-							    tb->rbytes) -
-						    zeros_num;
+						r_body = body + (old_len - tb->rbytes) - zeros_num;
 					} else {
 						r_body = body;
-						r_zeros_number =
-						    zeros_num - (old_len -
-								 tb->rbytes);
+						r_zeros_number = zeros_num - (old_len - tb->rbytes);
 						zeros_num -= r_zeros_number;
 					}
 
@@ -798,25 +586,18 @@
 
 					/* Calculate key component and item length to insert into S[0] */
 					set_le_ih_k_offset(ih, old_key_comp);
-					put_ih_item_len(ih,
-							old_len - tb->rbytes);
+					put_ih_item_len(ih, old_len - tb->rbytes);
 
 					tb->insert_size[0] -= tb->rbytes;
 
 				} else {	/* whole new item falls into R[0] */
 
 					/* Shift rnum[0]-1 items to R[0] */
-					ret_val =
-					    leaf_shift_right(tb,
-							     tb->rnum[0] - 1,
-							     tb->rbytes);
+					ret_val = leaf_shift_right(tb, tb->rnum[0] - 1, tb->rbytes);
 					/* Insert new item into R[0] */
 					buffer_info_init_right(tb, &bi);
-					leaf_insert_into_buf(&bi,
-							     item_pos - n +
-							     tb->rnum[0] - 1,
-							     ih, body,
-							     zeros_num);
+					leaf_insert_into_buf(&bi, item_pos - n + tb->rnum[0] - 1,
+							     ih, body, zeros_num);
 
 					if (item_pos - n + tb->rnum[0] - 1 == 0) {
 						replace_key(tb, tb->CFR[0],
@@ -841,200 +622,97 @@
 
 						RFALSE(zeros_num,
 						       "PAP-12145: invalid parameter in case of a directory");
-						entry_count =
-						    I_ENTRY_COUNT(B_N_PITEM_HEAD
-								  (tbS0,
-								   item_pos));
+						entry_count = I_ENTRY_COUNT(B_N_PITEM_HEAD
+								  (tbS0, item_pos));
 						if (entry_count - tb->rbytes <
 						    pos_in_item)
 							/* new directory entry falls into R[0] */
 						{
 							int paste_entry_position;
 
-							RFALSE(tb->rbytes - 1 >=
-							       entry_count
-							       || !tb->
-							       insert_size[0],
+							RFALSE(tb->rbytes - 1 >= entry_count || !tb-> insert_size[0],
 							       "PAP-12150: no enough of entries to shift to R[0]: rbytes=%d, entry_count=%d",
-							       tb->rbytes,
-							       entry_count);
+							       tb->rbytes, entry_count);
 							/* Shift rnum[0]-1 items in whole. Shift rbytes-1 directory entries from directory item number rnum[0] */
-							leaf_shift_right(tb,
-									 tb->
-									 rnum
-									 [0],
-									 tb->
-									 rbytes
-									 - 1);
+							leaf_shift_right(tb, tb->rnum[0], tb->rbytes - 1);
 							/* Paste given directory entry to directory item */
-							paste_entry_position =
-							    pos_in_item -
-							    entry_count +
-							    tb->rbytes - 1;
+							paste_entry_position = pos_in_item - entry_count + tb->rbytes - 1;
 							buffer_info_init_right(tb, &bi);
-							leaf_paste_in_buffer
-							    (&bi, 0,
-							     paste_entry_position,
-							     tb->insert_size[0],
-							     body, zeros_num);
+							leaf_paste_in_buffer(&bi, 0, paste_entry_position, tb->insert_size[0], body, zeros_num);
 							/* paste entry */
-							leaf_paste_entries(&bi,
-									   0,
-									   paste_entry_position,
-									   1,
-									   (struct
-									    reiserfs_de_head
-									    *)
-									   body,
-									   body
-									   +
-									   DEH_SIZE,
-									   tb->
-									   insert_size
-									   [0]
-							    );
+							leaf_paste_entries(&bi, 0, paste_entry_position, 1,
+									   (struct reiserfs_de_head *) body,
+									   body + DEH_SIZE, tb->insert_size[0]);
 
-							if (paste_entry_position
-							    == 0) {
+							if (paste_entry_position == 0) {
 								/* change delimiting keys */
-								replace_key(tb,
-									    tb->
-									    CFR
-									    [0],
-									    tb->
-									    rkey
-									    [0],
-									    tb->
-									    R
-									    [0],
-									    0);
+								replace_key(tb, tb->CFR[0], tb->rkey[0], tb->R[0],0);
 							}
 
 							tb->insert_size[0] = 0;
 							pos_in_item++;
 						} else {	/* new directory entry doesn't fall into R[0] */
 
-							leaf_shift_right(tb,
-									 tb->
-									 rnum
-									 [0],
-									 tb->
-									 rbytes);
+							leaf_shift_right(tb, tb->rnum[0], tb->rbytes);
 						}
 					} else {	/* regular object */
 
-						int n_shift, n_rem,
-						    r_zeros_number;
+						int n_shift, n_rem, r_zeros_number;
 						const char *r_body;
 
 						/* Calculate number of bytes which must be shifted from appended item */
-						if ((n_shift =
-						     tb->rbytes -
-						     tb->insert_size[0]) < 0)
+						if ((n_shift = tb->rbytes - tb->insert_size[0]) < 0)
 							n_shift = 0;
 
-						RFALSE(pos_in_item !=
-						       ih_item_len
-						       (B_N_PITEM_HEAD
-							(tbS0, item_pos)),
+						RFALSE(pos_in_item != ih_item_len
+						       (B_N_PITEM_HEAD(tbS0, item_pos)),
 						       "PAP-12155: invalid position to paste. ih_item_len=%d, pos_in_item=%d",
-						       pos_in_item,
-						       ih_item_len
-						       (B_N_PITEM_HEAD
-							(tbS0, item_pos)));
+						       pos_in_item, ih_item_len
+						       (B_N_PITEM_HEAD(tbS0, item_pos)));
 
-						leaf_shift_right(tb,
-								 tb->rnum[0],
-								 n_shift);
+						leaf_shift_right(tb, tb->rnum[0], n_shift);
 						/* Calculate number of bytes which must remain in body after appending to R[0] */
-						if ((n_rem =
-						     tb->insert_size[0] -
-						     tb->rbytes) < 0)
+						if ((n_rem = tb->insert_size[0] - tb->rbytes) < 0)
 							n_rem = 0;
 
 						{
 							int version;
-							unsigned long temp_rem =
-							    n_rem;
+							unsigned long temp_rem = n_rem;
 
-							version =
-							    ih_version
-							    (B_N_PITEM_HEAD
-							     (tb->R[0], 0));
-							if (is_indirect_le_key
-							    (version,
-							     B_N_PKEY(tb->R[0],
-								      0))) {
-								temp_rem =
-								    n_rem <<
-								    (tb->tb_sb->
-								     s_blocksize_bits
-								     -
-								     UNFM_P_SHIFT);
+							version = ih_version(B_N_PITEM_HEAD(tb->R[0], 0));
+							if (is_indirect_le_key(version, B_N_PKEY(tb->R[0], 0))) {
+								temp_rem = n_rem << (tb->tb_sb->s_blocksize_bits - UNFM_P_SHIFT);
 							}
-							set_le_key_k_offset
-							    (version,
-							     B_N_PKEY(tb->R[0],
-								      0),
-							     le_key_k_offset
-							     (version,
-							      B_N_PKEY(tb->R[0],
-								       0)) +
-							     temp_rem);
-							set_le_key_k_offset
-							    (version,
-							     B_N_PDELIM_KEY(tb->
-									    CFR
-									    [0],
-									    tb->
-									    rkey
-									    [0]),
-							     le_key_k_offset
-							     (version,
-							      B_N_PDELIM_KEY
-							      (tb->CFR[0],
-							       tb->rkey[0])) +
-							     temp_rem);
+							set_le_key_k_offset(version, B_N_PKEY(tb->R[0], 0),
+							     le_key_k_offset(version, B_N_PKEY(tb->R[0], 0)) + temp_rem);
+							set_le_key_k_offset(version, B_N_PDELIM_KEY(tb->CFR[0], tb->rkey[0]),
+							     le_key_k_offset(version, B_N_PDELIM_KEY(tb->CFR[0], tb->rkey[0])) + temp_rem);
 						}
 /*		  k_offset (B_N_PKEY(tb->R[0],0)) += n_rem;
 		  k_offset (B_N_PDELIM_KEY(tb->CFR[0],tb->rkey[0])) += n_rem;*/
-						do_balance_mark_internal_dirty
-						    (tb, tb->CFR[0], 0);
+						do_balance_mark_internal_dirty(tb, tb->CFR[0], 0);
 
 						/* Append part of body into R[0] */
 						buffer_info_init_right(tb, &bi);
 						if (n_rem > zeros_num) {
 							r_zeros_number = 0;
-							r_body =
-							    body + n_rem -
-							    zeros_num;
+							r_body = body + n_rem - zeros_num;
 						} else {
 							r_body = body;
-							r_zeros_number =
-							    zeros_num - n_rem;
-							zeros_num -=
-							    r_zeros_number;
+							r_zeros_number = zeros_num - n_rem;
+							zeros_num -= r_zeros_number;
 						}
 
-						leaf_paste_in_buffer(&bi, 0,
-								     n_shift,
-								     tb->
-								     insert_size
-								     [0] -
-								     n_rem,
-								     r_body,
-								     r_zeros_number);
+						leaf_paste_in_buffer(&bi, 0, n_shift,
+								     tb->insert_size[0] - n_rem,
+								     r_body, r_zeros_number);
 
-						if (is_indirect_le_ih
-						    (B_N_PITEM_HEAD
-						     (tb->R[0], 0))) {
+						if (is_indirect_le_ih(B_N_PITEM_HEAD(tb->R[0], 0))) {
 #if 0
 							RFALSE(n_rem,
 							       "PAP-12160: paste more than one unformatted node pointer");
 #endif
-							set_ih_free_space
-							    (B_N_PITEM_HEAD
-							     (tb->R[0], 0), 0);
+							set_ih_free_space(B_N_PITEM_HEAD(tb->R[0], 0), 0);
 						}
 						tb->insert_size[0] = n_rem;
 						if (!n_rem)
@@ -1044,58 +722,28 @@
 
 					struct item_head *pasted;
 
-					ret_val =
-					    leaf_shift_right(tb, tb->rnum[0],
-							     tb->rbytes);
+					ret_val = leaf_shift_right(tb, tb->rnum[0], tb->rbytes);
 					/* append item in R[0] */
 					if (pos_in_item >= 0) {
 						buffer_info_init_right(tb, &bi);
-						leaf_paste_in_buffer(&bi,
-								     item_pos -
-								     n +
-								     tb->
-								     rnum[0],
-								     pos_in_item,
-								     tb->
-								     insert_size
-								     [0], body,
-								     zeros_num);
+						leaf_paste_in_buffer(&bi, item_pos - n + tb->rnum[0], pos_in_item,
+								     tb->insert_size[0], body, zeros_num);
 					}
 
 					/* paste new entry, if item is directory item */
-					pasted =
-					    B_N_PITEM_HEAD(tb->R[0],
-							   item_pos - n +
-							   tb->rnum[0]);
-					if (is_direntry_le_ih(pasted)
-					    && pos_in_item >= 0) {
-						leaf_paste_entries(&bi,
-								   item_pos -
-								   n +
-								   tb->rnum[0],
-								   pos_in_item,
-								   1,
-								   (struct
-								    reiserfs_de_head
-								    *)body,
-								   body +
-								   DEH_SIZE,
-								   tb->
-								   insert_size
-								   [0]
-						    );
+					pasted = B_N_PITEM_HEAD(tb->R[0], item_pos - n + tb->rnum[0]);
+					if (is_direntry_le_ih(pasted) && pos_in_item >= 0) {
+						leaf_paste_entries(&bi, item_pos - n + tb->rnum[0],
+								   pos_in_item, 1,
+								   (struct reiserfs_de_head *) body,
+								   body + DEH_SIZE, tb->insert_size[0]);
 						if (!pos_in_item) {
 
-							RFALSE(item_pos - n +
-							       tb->rnum[0],
+							RFALSE(item_pos - n + tb->rnum[0],
 							       "PAP-12165: directory item must be first item of node when pasting is in 0th position");
 
 							/* update delimiting keys */
-							replace_key(tb,
-								    tb->CFR[0],
-								    tb->rkey[0],
-								    tb->R[0],
-								    0);
+							replace_key(tb, tb->CFR[0], tb->rkey[0], tb->R[0], 0);
 						}
 					}
 
@@ -1111,22 +759,16 @@
 		default:	/* cases d and t */
 			reiserfs_panic(tb->tb_sb, "PAP-12175",
 				       "rnum > 0: unexpected mode: %s(%d)",
-				       (flag ==
-					M_DELETE) ? "DELETE" : ((flag ==
-								 M_CUT) ? "CUT"
-								: "UNKNOWN"),
-				       flag);
+				       (flag == M_DELETE) ? "DELETE" : ((flag == M_CUT) ? "CUT" : "UNKNOWN"), flag);
 		}
 
 	}
 
 	/* tb->rnum[0] > 0 */
 	RFALSE(tb->blknum[0] > 3,
-	       "PAP-12180: blknum can not be %d. It must be <= 3",
-	       tb->blknum[0]);
+	       "PAP-12180: blknum can not be %d. It must be <= 3", tb->blknum[0]);
 	RFALSE(tb->blknum[0] < 0,
-	       "PAP-12185: blknum can not be %d. It must be >= 0",
-	       tb->blknum[0]);
+	       "PAP-12185: blknum can not be %d. It must be >= 0", tb->blknum[0]);
 
 	/* if while adding to a node we discover that it is possible to split
 	   it in two, and merge the left part into the left neighbor and the
@@ -1177,8 +819,7 @@
 
 			if (n - snum[i] < item_pos) {	/* new item or it's part falls to first new node S_new[i] */
 				if (item_pos == n - snum[i] + 1 && sbytes[i] != -1) {	/* part of new item falls into S_new[i] */
-					int old_key_comp, old_len,
-					    r_zeros_number;
+					int old_key_comp, old_len, r_zeros_number;
 					const char *r_body;
 					int version;
 
@@ -1192,15 +833,8 @@
 					old_len = ih_item_len(ih);
 
 					/* Calculate key component and item length to insert into S_new[i] */
-					set_le_ih_k_offset(ih,
-							   le_ih_k_offset(ih) +
-							   ((old_len -
-							     sbytes[i]) <<
-							    (is_indirect_le_ih
-							     (ih) ? tb->tb_sb->
-							     s_blocksize_bits -
-							     UNFM_P_SHIFT :
-							     0)));
+					set_le_ih_k_offset(ih, le_ih_k_offset(ih) +
+							   ((old_len - sbytes[i]) << (is_indirect_le_ih(ih) ? tb->tb_sb-> s_blocksize_bits - UNFM_P_SHIFT : 0)));
 
 					put_ih_item_len(ih, sbytes[i]);
 
@@ -1209,39 +843,29 @@
 
 					if ((old_len - sbytes[i]) > zeros_num) {
 						r_zeros_number = 0;
-						r_body =
-						    body + (old_len -
-							    sbytes[i]) -
-						    zeros_num;
+						r_body = body + (old_len - sbytes[i]) - zeros_num;
 					} else {
 						r_body = body;
-						r_zeros_number =
-						    zeros_num - (old_len -
-								 sbytes[i]);
+						r_zeros_number = zeros_num - (old_len - sbytes[i]);
 						zeros_num -= r_zeros_number;
 					}
 
-					leaf_insert_into_buf(&bi, 0, ih, r_body,
-							     r_zeros_number);
+					leaf_insert_into_buf(&bi, 0, ih, r_body, r_zeros_number);
 
 					/* Calculate key component and item length to insert into S[i] */
 					set_le_ih_k_offset(ih, old_key_comp);
-					put_ih_item_len(ih,
-							old_len - sbytes[i]);
+					put_ih_item_len(ih, old_len - sbytes[i]);
 					tb->insert_size[0] -= sbytes[i];
 				} else {	/* whole new item falls into S_new[i] */
 
 					/* Shift snum[0] - 1 items to S_new[i] (sbytes[i] of split item) */
 					leaf_move_items(LEAF_FROM_S_TO_SNEW, tb,
-							snum[i] - 1, sbytes[i],
-							S_new[i]);
+							snum[i] - 1, sbytes[i], S_new[i]);
 
 					/* Insert new item into S_new[i] */
 					buffer_info_init_bh(tb, &bi, S_new[i]);
-					leaf_insert_into_buf(&bi,
-							     item_pos - n +
-							     snum[i] - 1, ih,
-							     body, zeros_num);
+					leaf_insert_into_buf(&bi, item_pos - n + snum[i] - 1,
+							     ih, body, zeros_num);
 
 					zeros_num = tb->insert_size[0] = 0;
 				}
@@ -1268,150 +892,73 @@
 
 						int entry_count;
 
-						entry_count =
-						    ih_entry_count(aux_ih);
+						entry_count = ih_entry_count(aux_ih);
 
-						if (entry_count - sbytes[i] <
-						    pos_in_item
-						    && pos_in_item <=
-						    entry_count) {
+						if (entry_count - sbytes[i] < pos_in_item && pos_in_item <= entry_count) {
 							/* new directory entry falls into S_new[i] */
 
-							RFALSE(!tb->
-							       insert_size[0],
-							       "PAP-12215: insert_size is already 0");
-							RFALSE(sbytes[i] - 1 >=
-							       entry_count,
+							RFALSE(!tb->insert_size[0], "PAP-12215: insert_size is already 0");
+							RFALSE(sbytes[i] - 1 >= entry_count,
 							       "PAP-12220: there are no so much entries (%d), only %d",
-							       sbytes[i] - 1,
-							       entry_count);
+							       sbytes[i] - 1, entry_count);
 
 							/* Shift snum[i]-1 items in whole. Shift sbytes[i] directory entries from directory item number snum[i] */
-							leaf_move_items
-							    (LEAF_FROM_S_TO_SNEW,
-							     tb, snum[i],
-							     sbytes[i] - 1,
-							     S_new[i]);
+							leaf_move_items(LEAF_FROM_S_TO_SNEW, tb, snum[i], sbytes[i] - 1, S_new[i]);
 							/* Paste given directory entry to directory item */
 							buffer_info_init_bh(tb, &bi, S_new[i]);
-							leaf_paste_in_buffer
-							    (&bi, 0,
-							     pos_in_item -
-							     entry_count +
-							     sbytes[i] - 1,
-							     tb->insert_size[0],
-							     body, zeros_num);
+							leaf_paste_in_buffer(&bi, 0, pos_in_item - entry_count + sbytes[i] - 1,
+							     tb->insert_size[0], body, zeros_num);
 							/* paste new directory entry */
-							leaf_paste_entries(&bi,
-									   0,
-									   pos_in_item
-									   -
-									   entry_count
-									   +
-									   sbytes
-									   [i] -
-									   1, 1,
-									   (struct
-									    reiserfs_de_head
-									    *)
-									   body,
-									   body
-									   +
-									   DEH_SIZE,
-									   tb->
-									   insert_size
-									   [0]
-							    );
+							leaf_paste_entries(&bi, 0, pos_in_item - entry_count + sbytes[i] - 1, 1,
+									   (struct reiserfs_de_head *) body,
+									   body + DEH_SIZE, tb->insert_size[0]);
 							tb->insert_size[0] = 0;
 							pos_in_item++;
 						} else {	/* new directory entry doesn't fall into S_new[i] */
-							leaf_move_items
-							    (LEAF_FROM_S_TO_SNEW,
-							     tb, snum[i],
-							     sbytes[i],
-							     S_new[i]);
+							leaf_move_items(LEAF_FROM_S_TO_SNEW,tb, snum[i], sbytes[i], S_new[i]);
 						}
 					} else {	/* regular object */
 
-						int n_shift, n_rem,
-						    r_zeros_number;
+						int n_shift, n_rem, r_zeros_number;
 						const char *r_body;
 
-						RFALSE(pos_in_item !=
-						       ih_item_len
-						       (B_N_PITEM_HEAD
-							(tbS0, item_pos))
-						       || tb->insert_size[0] <=
-						       0,
+						RFALSE(pos_in_item != ih_item_len(B_N_PITEM_HEAD(tbS0, item_pos)) || tb->insert_size[0] <= 0,
 						       "PAP-12225: item too short or insert_size <= 0");
 
 						/* Calculate number of bytes which must be shifted from appended item */
-						n_shift =
-						    sbytes[i] -
-						    tb->insert_size[0];
+						n_shift = sbytes[i] - tb->insert_size[0];
 						if (n_shift < 0)
 							n_shift = 0;
-						leaf_move_items
-						    (LEAF_FROM_S_TO_SNEW, tb,
-						     snum[i], n_shift,
-						     S_new[i]);
+						leaf_move_items(LEAF_FROM_S_TO_SNEW, tb, snum[i], n_shift, S_new[i]);
 
 						/* Calculate number of bytes which must remain in body after append to S_new[i] */
-						n_rem =
-						    tb->insert_size[0] -
-						    sbytes[i];
+						n_rem = tb->insert_size[0] - sbytes[i];
 						if (n_rem < 0)
 							n_rem = 0;
 						/* Append part of body into S_new[0] */
 						buffer_info_init_bh(tb, &bi, S_new[i]);
 						if (n_rem > zeros_num) {
 							r_zeros_number = 0;
-							r_body =
-							    body + n_rem -
-							    zeros_num;
+							r_body = body + n_rem - zeros_num;
 						} else {
 							r_body = body;
-							r_zeros_number =
-							    zeros_num - n_rem;
-							zeros_num -=
-							    r_zeros_number;
+							r_zeros_number = zeros_num - n_rem;
+							zeros_num -= r_zeros_number;
 						}
 
-						leaf_paste_in_buffer(&bi, 0,
-								     n_shift,
-								     tb->
-								     insert_size
-								     [0] -
-								     n_rem,
-								     r_body,
-								     r_zeros_number);
+						leaf_paste_in_buffer(&bi, 0, n_shift,
+								     tb->insert_size[0] - n_rem,
+								     r_body, r_zeros_number);
 						{
 							struct item_head *tmp;
 
-							tmp =
-							    B_N_PITEM_HEAD(S_new
-									   [i],
-									   0);
+							tmp = B_N_PITEM_HEAD(S_new[i], 0);
 							if (is_indirect_le_ih
 							    (tmp)) {
-								set_ih_free_space
-								    (tmp, 0);
-								set_le_ih_k_offset
-								    (tmp,
-								     le_ih_k_offset
-								     (tmp) +
-								     (n_rem <<
-								      (tb->
-								       tb_sb->
-								       s_blocksize_bits
-								       -
-								       UNFM_P_SHIFT)));
+								set_ih_free_space(tmp, 0);
+								set_le_ih_k_offset(tmp, le_ih_k_offset(tmp) + (n_rem << (tb->tb_sb->s_blocksize_bits - UNFM_P_SHIFT)));
 							} else {
-								set_le_ih_k_offset
-								    (tmp,
-								     le_ih_k_offset
-								     (tmp) +
-								     n_rem);
+								set_le_ih_k_offset(tmp, le_ih_k_offset(tmp) + n_rem);
 							}
 						}
 
@@ -1426,8 +973,7 @@
 					struct item_head *pasted;
 
 #ifdef CONFIG_REISERFS_CHECK
-					struct item_head *ih_check =
-					    B_N_PITEM_HEAD(tbS0, item_pos);
+					struct item_head *ih_check = B_N_PITEM_HEAD(tbS0, item_pos);
 
 					if (!is_direntry_le_ih(ih_check)
 					    && (pos_in_item != ih_item_len(ih_check)
@@ -1439,8 +985,7 @@
 							     "to ih_item_len");
 #endif				/* CONFIG_REISERFS_CHECK */
 
-					leaf_mi =
-					    leaf_move_items(LEAF_FROM_S_TO_SNEW,
+					leaf_mi = leaf_move_items(LEAF_FROM_S_TO_SNEW,
 							    tb, snum[i],
 							    sbytes[i],
 							    S_new[i]);
@@ -1452,30 +997,19 @@
 					/* paste into item */
 					buffer_info_init_bh(tb, &bi, S_new[i]);
 					leaf_paste_in_buffer(&bi,
-							     item_pos - n +
-							     snum[i],
+							     item_pos - n + snum[i],
 							     pos_in_item,
 							     tb->insert_size[0],
 							     body, zeros_num);
 
-					pasted =
-					    B_N_PITEM_HEAD(S_new[i],
-							   item_pos - n +
-							   snum[i]);
+					pasted = B_N_PITEM_HEAD(S_new[i], item_pos - n + snum[i]);
 					if (is_direntry_le_ih(pasted)) {
 						leaf_paste_entries(&bi,
-								   item_pos -
-								   n + snum[i],
-								   pos_in_item,
-								   1,
-								   (struct
-								    reiserfs_de_head
-								    *)body,
-								   body +
-								   DEH_SIZE,
-								   tb->
-								   insert_size
-								   [0]
+								   item_pos - n + snum[i],
+								   pos_in_item, 1,
+								   (struct reiserfs_de_head *)body,
+								   body + DEH_SIZE,
+								   tb->insert_size[0]
 						    );
 					}
 
@@ -1495,11 +1029,7 @@
 		default:	/* cases d and t */
 			reiserfs_panic(tb->tb_sb, "PAP-12245",
 				       "blknum > 2: unexpected mode: %s(%d)",
-				       (flag ==
-					M_DELETE) ? "DELETE" : ((flag ==
-								 M_CUT) ? "CUT"
-								: "UNKNOWN"),
-				       flag);
+				       (flag == M_DELETE) ? "DELETE" : ((flag == M_CUT) ? "CUT" : "UNKNOWN"), flag);
 		}
 
 		memcpy(insert_key + i, B_N_PKEY(S_new[i], 0), KEY_SIZE);
@@ -1524,9 +1054,7 @@
 			/* If we insert the first key change the delimiting key */
 			if (item_pos == 0) {
 				if (tb->CFL[0])	/* can be 0 in reiserfsck */
-					replace_key(tb, tb->CFL[0], tb->lkey[0],
-						    tbS0, 0);
-
+					replace_key(tb, tb->CFL[0], tb->lkey[0], tbS0, 0);
 			}
 			break;
 
@@ -1536,53 +1064,27 @@
 				pasted = B_N_PITEM_HEAD(tbS0, item_pos);
 				/* when directory, may be new entry already pasted */
 				if (is_direntry_le_ih(pasted)) {
-					if (pos_in_item >= 0 &&
-					    pos_in_item <=
-					    ih_entry_count(pasted)) {
+					if (pos_in_item >= 0 && pos_in_item <= ih_entry_count(pasted)) {
 
 						RFALSE(!tb->insert_size[0],
 						       "PAP-12260: insert_size is 0 already");
 
 						/* prepare space */
 						buffer_info_init_tbS0(tb, &bi);
-						leaf_paste_in_buffer(&bi,
-								     item_pos,
-								     pos_in_item,
-								     tb->
-								     insert_size
-								     [0], body,
+						leaf_paste_in_buffer(&bi, item_pos, pos_in_item,
+								     tb->insert_size[0], body,
 								     zeros_num);
 
 						/* paste entry */
-						leaf_paste_entries(&bi,
-								   item_pos,
-								   pos_in_item,
-								   1,
-								   (struct
-								    reiserfs_de_head
-								    *)body,
-								   body +
-								   DEH_SIZE,
-								   tb->
-								   insert_size
-								   [0]
-						    );
+						leaf_paste_entries(&bi, item_pos, pos_in_item, 1,
+								   (struct reiserfs_de_head *)body,
+								   body + DEH_SIZE,
+								   tb->insert_size[0]);
 						if (!item_pos && !pos_in_item) {
-							RFALSE(!tb->CFL[0]
-							       || !tb->L[0],
+							RFALSE(!tb->CFL[0] || !tb->L[0],
 							       "PAP-12270: CFL[0]/L[0] must be specified");
-							if (tb->CFL[0]) {
-								replace_key(tb,
-									    tb->
-									    CFL
-									    [0],
-									    tb->
-									    lkey
-									    [0],
-									    tbS0,
-									    0);
-
-							}
+							if (tb->CFL[0])
+								replace_key(tb, tb->CFL[0], tb->lkey[0], tbS0, 0);
 						}
 						tb->insert_size[0] = 0;
 					}
@@ -1593,13 +1095,8 @@
 						       "PAP-12275: insert size must not be %d",
 						       tb->insert_size[0]);
 						buffer_info_init_tbS0(tb, &bi);
-						leaf_paste_in_buffer(&bi,
-								     item_pos,
-								     pos_in_item,
-								     tb->
-								     insert_size
-								     [0], body,
-								     zeros_num);
+						leaf_paste_in_buffer(&bi, item_pos, pos_in_item,
+								     tb->insert_size[0], body, zeros_num);
 
 						if (is_indirect_le_ih(pasted)) {
 #if 0
@@ -1611,8 +1108,7 @@
 							       tb->
 							       insert_size[0]);
 #endif
-							set_ih_free_space
-							    (pasted, 0);
+							set_ih_free_space(pasted, 0);
 						}
 						tb->insert_size[0] = 0;
 					}
@@ -1620,8 +1116,7 @@
 					else {
 						if (tb->insert_size[0]) {
 							print_cur_tb("12285");
-							reiserfs_panic(tb->
-								       tb_sb,
+							reiserfs_panic(tb->tb_sb,
 							    "PAP-12285",
 							    "insert_size "
 							    "must be 0 "
diff --git a/fs/sync.c b/fs/sync.c
index e8ba024..b28d1dd 100644
--- a/fs/sync.c
+++ b/fs/sync.c
@@ -27,11 +27,10 @@
  * wait == 1 case since in that case write_inode() functions do
  * sync_dirty_buffer() and thus effectively write one block at a time.
  */
-static int __sync_filesystem(struct super_block *sb, int wait,
-			     unsigned long start)
+static int __sync_filesystem(struct super_block *sb, int wait)
 {
 	if (wait)
-		sync_inodes_sb(sb, start);
+		sync_inodes_sb(sb);
 	else
 		writeback_inodes_sb(sb, WB_REASON_SYNC);
 
@@ -48,7 +47,6 @@
 int sync_filesystem(struct super_block *sb)
 {
 	int ret;
-	unsigned long start = jiffies;
 
 	/*
 	 * We need to be protected against the filesystem going from
@@ -62,17 +60,17 @@
 	if (sb->s_flags & MS_RDONLY)
 		return 0;
 
-	ret = __sync_filesystem(sb, 0, start);
+	ret = __sync_filesystem(sb, 0);
 	if (ret < 0)
 		return ret;
-	return __sync_filesystem(sb, 1, start);
+	return __sync_filesystem(sb, 1);
 }
 EXPORT_SYMBOL_GPL(sync_filesystem);
 
 static void sync_inodes_one_sb(struct super_block *sb, void *arg)
 {
 	if (!(sb->s_flags & MS_RDONLY))
-		sync_inodes_sb(sb, *((unsigned long *)arg));
+		sync_inodes_sb(sb);
 }
 
 static void sync_fs_one_sb(struct super_block *sb, void *arg)
@@ -104,10 +102,9 @@
 SYSCALL_DEFINE0(sync)
 {
 	int nowait = 0, wait = 1;
-	unsigned long start = jiffies;
 
 	wakeup_flusher_threads(0, WB_REASON_SYNC);
-	iterate_supers(sync_inodes_one_sb, &start);
+	iterate_supers(sync_inodes_one_sb, NULL);
 	iterate_supers(sync_fs_one_sb, &nowait);
 	iterate_supers(sync_fs_one_sb, &wait);
 	iterate_bdevs(fdatawrite_one_bdev, NULL);
diff --git a/fs/sysfs/mount.c b/fs/sysfs/mount.c
index 6211230..3eaf5c6 100644
--- a/fs/sysfs/mount.c
+++ b/fs/sysfs/mount.c
@@ -27,6 +27,7 @@
 {
 	struct dentry *root;
 	void *ns;
+	bool new_sb;
 
 	if (!(flags & MS_KERNMOUNT)) {
 		if (!capable(CAP_SYS_ADMIN) && !fs_fully_visible(fs_type))
@@ -37,8 +38,8 @@
 	}
 
 	ns = kobj_ns_grab_current(KOBJ_NS_TYPE_NET);
-	root = kernfs_mount_ns(fs_type, flags, sysfs_root, ns);
-	if (IS_ERR(root))
+	root = kernfs_mount_ns(fs_type, flags, sysfs_root, &new_sb, ns);
+	if (IS_ERR(root) || !new_sb)
 		kobj_ns_drop(KOBJ_NS_TYPE_NET, ns);
 	return root;
 }
diff --git a/fs/udf/file.c b/fs/udf/file.c
index c02a27a..1037637 100644
--- a/fs/udf/file.c
+++ b/fs/udf/file.c
@@ -144,6 +144,7 @@
 	size_t count = iocb->ki_nbytes;
 	struct udf_inode_info *iinfo = UDF_I(inode);
 
+	mutex_lock(&inode->i_mutex);
 	down_write(&iinfo->i_data_sem);
 	if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) {
 		if (file->f_flags & O_APPEND)
@@ -156,6 +157,7 @@
 						pos + count)) {
 			err = udf_expand_file_adinicb(inode);
 			if (err) {
+				mutex_unlock(&inode->i_mutex);
 				udf_debug("udf_expand_adinicb: err=%d\n", err);
 				return err;
 			}
@@ -169,9 +171,17 @@
 	} else
 		up_write(&iinfo->i_data_sem);
 
-	retval = generic_file_aio_write(iocb, iov, nr_segs, ppos);
-	if (retval > 0)
+	retval = __generic_file_aio_write(iocb, iov, nr_segs, &iocb->ki_pos);
+	mutex_unlock(&inode->i_mutex);
+
+	if (retval > 0) {
+		ssize_t err;
+
 		mark_inode_dirty(inode);
+		err = generic_write_sync(file, iocb->ki_pos - retval, retval);
+		if (err < 0)
+			retval = err;
+	}
 
 	return retval;
 }
diff --git a/fs/udf/inode.c b/fs/udf/inode.c
index 062b792..982ce05 100644
--- a/fs/udf/inode.c
+++ b/fs/udf/inode.c
@@ -265,6 +265,7 @@
 		.nr_to_write = 1,
 	};
 
+	WARN_ON_ONCE(!mutex_is_locked(&inode->i_mutex));
 	if (!iinfo->i_lenAlloc) {
 		if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_SHORT_AD))
 			iinfo->i_alloc_type = ICBTAG_FLAG_AD_SHORT;
diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c
index f35d5c9..9ddfb81 100644
--- a/fs/xfs/xfs_iops.c
+++ b/fs/xfs/xfs_iops.c
@@ -705,7 +705,6 @@
 {
 	struct xfs_mount	*mp = ip->i_mount;
 	struct inode		*inode = VFS_I(ip);
-	int			mask = iattr->ia_valid;
 	xfs_off_t		oldsize, newsize;
 	struct xfs_trans	*tp;
 	int			error;
@@ -726,8 +725,8 @@
 
 	ASSERT(xfs_isilocked(ip, XFS_IOLOCK_EXCL));
 	ASSERT(S_ISREG(ip->i_d.di_mode));
-	ASSERT((mask & (ATTR_UID|ATTR_GID|ATTR_ATIME|ATTR_ATIME_SET|
-			ATTR_MTIME_SET|ATTR_KILL_PRIV|ATTR_TIMES_SET)) == 0);
+	ASSERT((iattr->ia_valid & (ATTR_UID|ATTR_GID|ATTR_ATIME|ATTR_ATIME_SET|
+		ATTR_MTIME_SET|ATTR_KILL_PRIV|ATTR_TIMES_SET)) == 0);
 
 	oldsize = inode->i_size;
 	newsize = iattr->ia_size;
@@ -736,7 +735,7 @@
 	 * Short circuit the truncate case for zero length files.
 	 */
 	if (newsize == 0 && oldsize == 0 && ip->i_d.di_nextents == 0) {
-		if (!(mask & (ATTR_CTIME|ATTR_MTIME)))
+		if (!(iattr->ia_valid & (ATTR_CTIME|ATTR_MTIME)))
 			return 0;
 
 		/*
@@ -824,10 +823,11 @@
 	 * these flags set.  For all other operations the VFS set these flags
 	 * explicitly if it wants a timestamp update.
 	 */
-	if (newsize != oldsize && (!(mask & (ATTR_CTIME | ATTR_MTIME)))) {
+	if (newsize != oldsize &&
+	    !(iattr->ia_valid & (ATTR_CTIME | ATTR_MTIME))) {
 		iattr->ia_ctime = iattr->ia_mtime =
 			current_fs_time(inode->i_sb);
-		mask |= ATTR_CTIME | ATTR_MTIME;
+		iattr->ia_valid |= ATTR_CTIME | ATTR_MTIME;
 	}
 
 	/*
@@ -863,9 +863,9 @@
 		xfs_inode_clear_eofblocks_tag(ip);
 	}
 
-	if (mask & ATTR_MODE)
+	if (iattr->ia_valid & ATTR_MODE)
 		xfs_setattr_mode(ip, iattr);
-	if (mask & (ATTR_ATIME|ATTR_CTIME|ATTR_MTIME))
+	if (iattr->ia_valid & (ATTR_ATIME|ATTR_CTIME|ATTR_MTIME))
 		xfs_setattr_time(ip, iattr);
 
 	xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
diff --git a/fs/xfs/xfs_log_cil.c b/fs/xfs/xfs_log_cil.c
index cdebd83..4ef6fdb 100644
--- a/fs/xfs/xfs_log_cil.c
+++ b/fs/xfs/xfs_log_cil.c
@@ -205,16 +205,25 @@
 		/*
 		 * We 64-bit align the length of each iovec so that the start
 		 * of the next one is naturally aligned.  We'll need to
-		 * account for that slack space here.
+		 * account for that slack space here. Then round nbytes up
+		 * to 64-bit alignment so that the initial buffer alignment is
+		 * easy to calculate and verify.
 		 */
 		nbytes += niovecs * sizeof(uint64_t);
+		nbytes = round_up(nbytes, sizeof(uint64_t));
 
 		/* grab the old item if it exists for reservation accounting */
 		old_lv = lip->li_lv;
 
-		/* calc buffer size */
-		buf_size = sizeof(struct xfs_log_vec) + nbytes +
-				niovecs * sizeof(struct xfs_log_iovec);
+		/*
+		 * The data buffer needs to start 64-bit aligned, so round up
+		 * that space to ensure we can align it appropriately and not
+		 * overrun the buffer.
+		 */
+		buf_size = nbytes +
+			   round_up((sizeof(struct xfs_log_vec) +
+				     niovecs * sizeof(struct xfs_log_iovec)),
+				    sizeof(uint64_t));
 
 		/* compare to existing item size */
 		if (lip->li_lv && buf_size <= lip->li_lv->lv_size) {
@@ -251,6 +260,8 @@
 		/* The allocated data region lies beyond the iovec region */
 		lv->lv_buf_len = 0;
 		lv->lv_buf = (char *)lv + buf_size - nbytes;
+		ASSERT(IS_ALIGNED((unsigned long)lv->lv_buf, sizeof(uint64_t)));
+
 		lip->li_ops->iop_format(lip, lv);
 insert:
 		ASSERT(lv->lv_buf_len <= nbytes);
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
index 02df7b4..f96c056 100644
--- a/fs/xfs/xfs_mount.c
+++ b/fs/xfs/xfs_mount.c
@@ -282,22 +282,29 @@
 	struct xfs_sb	*sbp = &mp->m_sb;
 	int		error;
 	int		loud = !(flags & XFS_MFSI_QUIET);
+	const struct xfs_buf_ops *buf_ops;
 
 	ASSERT(mp->m_sb_bp == NULL);
 	ASSERT(mp->m_ddev_targp != NULL);
 
 	/*
+	 * For the initial read, we must guess at the sector
+	 * size based on the block device.  It's enough to
+	 * get the sb_sectsize out of the superblock and
+	 * then reread with the proper length.
+	 * We don't verify it yet, because it may not be complete.
+	 */
+	sector_size = xfs_getsize_buftarg(mp->m_ddev_targp);
+	buf_ops = NULL;
+
+	/*
 	 * Allocate a (locked) buffer to hold the superblock.
 	 * This will be kept around at all times to optimize
 	 * access to the superblock.
 	 */
-	sector_size = xfs_getsize_buftarg(mp->m_ddev_targp);
-
 reread:
 	bp = xfs_buf_read_uncached(mp->m_ddev_targp, XFS_SB_DADDR,
-				   BTOBB(sector_size), 0,
-				   loud ? &xfs_sb_buf_ops
-				        : &xfs_sb_quiet_buf_ops);
+				   BTOBB(sector_size), 0, buf_ops);
 	if (!bp) {
 		if (loud)
 			xfs_warn(mp, "SB buffer read failed");
@@ -328,12 +335,13 @@
 	}
 
 	/*
-	 * If device sector size is smaller than the superblock size,
-	 * re-read the superblock so the buffer is correctly sized.
+	 * Re-read the superblock so the buffer is correctly sized,
+	 * and properly verified.
 	 */
-	if (sector_size < sbp->sb_sectsize) {
+	if (buf_ops == NULL) {
 		xfs_buf_relse(bp);
 		sector_size = sbp->sb_sectsize;
+		buf_ops = loud ? &xfs_sb_buf_ops : &xfs_sb_quiet_buf_ops;
 		goto reread;
 	}
 
diff --git a/fs/xfs/xfs_sb.c b/fs/xfs/xfs_sb.c
index b7c9aea..1e11679 100644
--- a/fs/xfs/xfs_sb.c
+++ b/fs/xfs/xfs_sb.c
@@ -295,8 +295,7 @@
 	    sbp->sb_dblocks == 0					||
 	    sbp->sb_dblocks > XFS_MAX_DBLOCKS(sbp)			||
 	    sbp->sb_dblocks < XFS_MIN_DBLOCKS(sbp))) {
-		XFS_CORRUPTION_ERROR("SB sanity check failed",
-				XFS_ERRLEVEL_LOW, mp, sbp);
+		xfs_notice(mp, "SB sanity check failed");
 		return XFS_ERROR(EFSCORRUPTED);
 	}
 
@@ -611,10 +610,10 @@
 						XFS_SB_VERSION_5) ||
 	     dsb->sb_crc != 0)) {
 
-		if (!xfs_verify_cksum(bp->b_addr, be16_to_cpu(dsb->sb_sectsize),
+		if (!xfs_verify_cksum(bp->b_addr, BBTOB(bp->b_length),
 				      offsetof(struct xfs_sb, sb_crc))) {
 			/* Only fail bad secondaries on a known V5 filesystem */
-			if (bp->b_bn != XFS_SB_DADDR &&
+			if (bp->b_bn == XFS_SB_DADDR ||
 			    xfs_sb_version_hascrc(&mp->m_sb)) {
 				error = EFSCORRUPTED;
 				goto out_error;
@@ -625,7 +624,7 @@
 
 out_error:
 	if (error) {
-		if (error != EWRONGFS)
+		if (error == EFSCORRUPTED)
 			XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW,
 					     mp, bp->b_addr);
 		xfs_buf_ioerror(bp, error);
@@ -644,7 +643,6 @@
 {
 	struct xfs_dsb	*dsb = XFS_BUF_TO_SBP(bp);
 
-
 	if (dsb->sb_magicnum == cpu_to_be32(XFS_SB_MAGIC)) {
 		/* XFS filesystem, verify noisily! */
 		xfs_sb_read_verify(bp);
diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c
index f317488..d971f49 100644
--- a/fs/xfs/xfs_super.c
+++ b/fs/xfs/xfs_super.c
@@ -913,7 +913,7 @@
 	struct super_block	*sb = mp->m_super;
 
 	if (down_read_trylock(&sb->s_umount)) {
-		sync_inodes_sb(sb, jiffies);
+		sync_inodes_sb(sb);
 		up_read(&sb->s_umount);
 	}
 }
diff --git a/include/asm-generic/pgtable.h b/include/asm-generic/pgtable.h
index 8e4f41d..34c7bdc 100644
--- a/include/asm-generic/pgtable.h
+++ b/include/asm-generic/pgtable.h
@@ -701,6 +701,18 @@
 }
 #endif
 
+#ifndef ptep_set_numa
+static inline void ptep_set_numa(struct mm_struct *mm, unsigned long addr,
+				 pte_t *ptep)
+{
+	pte_t ptent = *ptep;
+
+	ptent = pte_mknuma(ptent);
+	set_pte_at(mm, addr, ptep, ptent);
+	return;
+}
+#endif
+
 #ifndef pmd_mknuma
 static inline pmd_t pmd_mknuma(pmd_t pmd)
 {
@@ -708,6 +720,18 @@
 	return pmd_clear_flags(pmd, _PAGE_PRESENT);
 }
 #endif
+
+#ifndef pmdp_set_numa
+static inline void pmdp_set_numa(struct mm_struct *mm, unsigned long addr,
+				 pmd_t *pmdp)
+{
+	pmd_t pmd = *pmdp;
+
+	pmd = pmd_mknuma(pmd);
+	set_pmd_at(mm, addr, pmdp, pmd);
+	return;
+}
+#endif
 #else
 extern int pte_numa(pte_t pte);
 extern int pmd_numa(pmd_t pmd);
@@ -715,6 +739,8 @@
 extern pmd_t pmd_mknonnuma(pmd_t pmd);
 extern pte_t pte_mknuma(pte_t pte);
 extern pmd_t pmd_mknuma(pmd_t pmd);
+extern void ptep_set_numa(struct mm_struct *mm, unsigned long addr, pte_t *ptep);
+extern void pmdp_set_numa(struct mm_struct *mm, unsigned long addr, pmd_t *pmdp);
 #endif /* CONFIG_ARCH_USES_NUMA_PROT_NONE */
 #else
 static inline int pmd_numa(pmd_t pmd)
@@ -742,10 +768,23 @@
 	return pte;
 }
 
+static inline void ptep_set_numa(struct mm_struct *mm, unsigned long addr,
+				 pte_t *ptep)
+{
+	return;
+}
+
+
 static inline pmd_t pmd_mknuma(pmd_t pmd)
 {
 	return pmd;
 }
+
+static inline void pmdp_set_numa(struct mm_struct *mm, unsigned long addr,
+				 pmd_t *pmdp)
+{
+	return ;
+}
 #endif /* CONFIG_NUMA_BALANCING */
 
 #endif /* CONFIG_MMU */
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 71727b6..8f3dee0 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -907,6 +907,9 @@
 
 	/* whether async page flip is supported or not */
 	bool async_page_flip;
+
+	/* cursor size */
+	uint32_t cursor_width, cursor_height;
 };
 
 #define obj_to_crtc(x) container_of(x, struct drm_crtc, base)
diff --git a/include/drm/ttm/ttm_page_alloc.h b/include/drm/ttm/ttm_page_alloc.h
index d1f61bf..49a8284 100644
--- a/include/drm/ttm/ttm_page_alloc.h
+++ b/include/drm/ttm/ttm_page_alloc.h
@@ -29,6 +29,8 @@
 #include <drm/ttm/ttm_bo_driver.h>
 #include <drm/ttm/ttm_memory.h>
 
+struct device;
+
 /**
  * Initialize pool allocator.
  */
diff --git a/include/linux/ceph/ceph_fs.h b/include/linux/ceph/ceph_fs.h
index 2623cff..25bfb0e 100644
--- a/include/linux/ceph/ceph_fs.h
+++ b/include/linux/ceph/ceph_fs.h
@@ -373,8 +373,9 @@
 /*
  * Ceph setxattr request flags.
  */
-#define CEPH_XATTR_CREATE  1
-#define CEPH_XATTR_REPLACE 2
+#define CEPH_XATTR_CREATE  (1 << 0)
+#define CEPH_XATTR_REPLACE (1 << 1)
+#define CEPH_XATTR_REMOVE  (1 << 31)
 
 union ceph_mds_request_args {
 	struct {
diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h
index 5c09759..9450f02 100644
--- a/include/linux/cgroup.h
+++ b/include/linux/cgroup.h
@@ -166,6 +166,8 @@
 	 *
 	 * The ID of the root cgroup is always 0, and a new cgroup
 	 * will be assigned with a smallest available ID.
+	 *
+	 * Allocating/Removing ID must be protected by cgroup_mutex.
 	 */
 	int id;
 
diff --git a/include/linux/dma-buf.h b/include/linux/dma-buf.h
index dfac5ed..f886985 100644
--- a/include/linux/dma-buf.h
+++ b/include/linux/dma-buf.h
@@ -171,7 +171,7 @@
 			       size_t size, int flags, const char *);
 
 #define dma_buf_export(priv, ops, size, flags)	\
-	dma_buf_export_named(priv, ops, size, flags, __FILE__)
+	dma_buf_export_named(priv, ops, size, flags, KBUILD_MODNAME)
 
 int dma_buf_fd(struct dma_buf *dmabuf, int flags);
 struct dma_buf *dma_buf_get(int fd);
diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h
index 3d286ff..64cf3ef 100644
--- a/include/linux/fsnotify_backend.h
+++ b/include/linux/fsnotify_backend.h
@@ -99,7 +99,7 @@
 			    struct fsnotify_mark *inode_mark,
 			    struct fsnotify_mark *vfsmount_mark,
 			    u32 mask, void *data, int data_type,
-			    const unsigned char *file_name);
+			    const unsigned char *file_name, u32 cookie);
 	void (*free_group_priv)(struct fsnotify_group *group);
 	void (*freeing_mark)(struct fsnotify_mark *mark, struct fsnotify_group *group);
 	void (*free_event)(struct fsnotify_event *event);
@@ -160,7 +160,7 @@
 
 	struct fasync_struct *fsn_fa;    /* async notification */
 
-	struct fsnotify_event overflow_event;	/* Event we queue when the
+	struct fsnotify_event *overflow_event;	/* Event we queue when the
 						 * notification list is too
 						 * full */
 
diff --git a/include/linux/ipc_namespace.h b/include/linux/ipc_namespace.h
index e7831d2..35e7eca 100644
--- a/include/linux/ipc_namespace.h
+++ b/include/linux/ipc_namespace.h
@@ -118,9 +118,7 @@
  *     the new maximum will handle anyone else.  I may have to revisit this
  *     in the future.
  */
-#define MIN_QUEUESMAX			1
 #define DFLT_QUEUESMAX		      256
-#define HARD_QUEUESMAX		     1024
 #define MIN_MSGMAX			1
 #define DFLT_MSG		       10U
 #define DFLT_MSGMAX		       10
diff --git a/include/linux/kernfs.h b/include/linux/kernfs.h
index 5be9f02..d267623 100644
--- a/include/linux/kernfs.h
+++ b/include/linux/kernfs.h
@@ -249,7 +249,8 @@
 
 const void *kernfs_super_ns(struct super_block *sb);
 struct dentry *kernfs_mount_ns(struct file_system_type *fs_type, int flags,
-			       struct kernfs_root *root, const void *ns);
+			       struct kernfs_root *root, bool *new_sb_created,
+			       const void *ns);
 void kernfs_kill_sb(struct super_block *sb);
 
 void kernfs_init(void);
@@ -317,7 +318,7 @@
 
 static inline struct dentry *
 kernfs_mount_ns(struct file_system_type *fs_type, int flags,
-		struct kernfs_root *root, const void *ns)
+		struct kernfs_root *root, bool *new_sb_created, const void *ns)
 { return ERR_PTR(-ENOSYS); }
 
 static inline void kernfs_kill_sb(struct super_block *sb) { }
@@ -368,9 +369,9 @@
 
 static inline struct dentry *
 kernfs_mount(struct file_system_type *fs_type, int flags,
-	     struct kernfs_root *root)
+	     struct kernfs_root *root, bool *new_sb_created)
 {
-	return kernfs_mount_ns(fs_type, flags, root, NULL);
+	return kernfs_mount_ns(fs_type, flags, root, new_sb_created, NULL);
 }
 
 #endif	/* __LINUX_KERNFS_H */
diff --git a/include/linux/mfd/max8997-private.h b/include/linux/mfd/max8997-private.h
index ad1ae7f..78c76cd 100644
--- a/include/linux/mfd/max8997-private.h
+++ b/include/linux/mfd/max8997-private.h
@@ -387,7 +387,7 @@
 	struct i2c_client *muic; /* slave addr 0x4a */
 	struct mutex iolock;
 
-	int type;
+	unsigned long type;
 	struct platform_device *battery; /* battery control (not fuel gauge) */
 
 	int irq;
diff --git a/include/linux/mfd/max8998-private.h b/include/linux/mfd/max8998-private.h
index 4ecb24b..d68ada5 100644
--- a/include/linux/mfd/max8998-private.h
+++ b/include/linux/mfd/max8998-private.h
@@ -163,7 +163,7 @@
 	int ono;
 	u8 irq_masks_cur[MAX8998_NUM_IRQ_REGS];
 	u8 irq_masks_cache[MAX8998_NUM_IRQ_REGS];
-	int type;
+	unsigned long type;
 	bool wakeup;
 };
 
diff --git a/include/linux/mfd/tps65217.h b/include/linux/mfd/tps65217.h
index a5a7f01..54b5458 100644
--- a/include/linux/mfd/tps65217.h
+++ b/include/linux/mfd/tps65217.h
@@ -252,7 +252,7 @@
 struct tps65217 {
 	struct device *dev;
 	struct tps65217_board *pdata;
-	unsigned int id;
+	unsigned long id;
 	struct regulator_desc desc[TPS65217_NUM_REGULATOR];
 	struct regulator_dev *rdev[TPS65217_NUM_REGULATOR];
 	struct regmap *regmap;
@@ -263,7 +263,7 @@
 	return dev_get_drvdata(dev);
 }
 
-static inline int tps65217_chip_id(struct tps65217 *tps65217)
+static inline unsigned long tps65217_chip_id(struct tps65217 *tps65217)
 {
 	return tps65217->id;
 }
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 440a02e..e8eeebd 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -752,6 +752,9 @@
 	unsigned char id_len;
 };
 
+typedef u16 (*select_queue_fallback_t)(struct net_device *dev,
+				       struct sk_buff *skb);
+
 /*
  * This structure defines the management hooks for network devices.
  * The following hooks can be defined; unless noted otherwise, they are
@@ -783,7 +786,7 @@
  *	Required can not be NULL.
  *
  * u16 (*ndo_select_queue)(struct net_device *dev, struct sk_buff *skb,
- *                         void *accel_priv);
+ *                         void *accel_priv, select_queue_fallback_t fallback);
  *	Called to decide which queue to when device supports multiple
  *	transmit queues.
  *
@@ -1005,7 +1008,8 @@
 						   struct net_device *dev);
 	u16			(*ndo_select_queue)(struct net_device *dev,
 						    struct sk_buff *skb,
-						    void *accel_priv);
+						    void *accel_priv,
+						    select_queue_fallback_t fallback);
 	void			(*ndo_change_rx_flags)(struct net_device *dev,
 						       int flags);
 	void			(*ndo_set_rx_mode)(struct net_device *dev);
@@ -1551,7 +1555,6 @@
 struct netdev_queue *netdev_pick_tx(struct net_device *dev,
 				    struct sk_buff *skb,
 				    void *accel_priv);
-u16 __netdev_pick_tx(struct net_device *dev, struct sk_buff *skb);
 
 /*
  * Net namespace inlines
@@ -2276,6 +2279,26 @@
 }
 
 /**
+ * 	netdev_cap_txqueue - check if selected tx queue exceeds device queues
+ * 	@dev: network device
+ * 	@queue_index: given tx queue index
+ *
+ * 	Returns 0 if given tx queue index >= number of device tx queues,
+ * 	otherwise returns the originally passed tx queue index.
+ */
+static inline u16 netdev_cap_txqueue(struct net_device *dev, u16 queue_index)
+{
+	if (unlikely(queue_index >= dev->real_num_tx_queues)) {
+		net_warn_ratelimited("%s selects TX queue %d, but real number of TX queues is %d\n",
+				     dev->name, queue_index,
+				     dev->real_num_tx_queues);
+		return 0;
+	}
+
+	return queue_index;
+}
+
+/**
  *	netif_running - test if up
  *	@dev: network device
  *
@@ -3068,7 +3091,12 @@
 void netif_stacked_transfer_operstate(const struct net_device *rootdev,
 					struct net_device *dev);
 
-netdev_features_t netif_skb_features(struct sk_buff *skb);
+netdev_features_t netif_skb_dev_features(struct sk_buff *skb,
+					 const struct net_device *dev);
+static inline netdev_features_t netif_skb_features(struct sk_buff *skb)
+{
+	return netif_skb_dev_features(skb, skb->dev);
+}
 
 static inline bool net_gso_ok(netdev_features_t features, int gso_type)
 {
diff --git a/include/linux/pci.h b/include/linux/pci.h
index fb57c89..33aa2ca 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -1169,8 +1169,23 @@
 void pci_restore_msi_state(struct pci_dev *dev);
 int pci_msi_enabled(void);
 int pci_enable_msi_range(struct pci_dev *dev, int minvec, int maxvec);
+static inline int pci_enable_msi_exact(struct pci_dev *dev, int nvec)
+{
+	int rc = pci_enable_msi_range(dev, nvec, nvec);
+	if (rc < 0)
+		return rc;
+	return 0;
+}
 int pci_enable_msix_range(struct pci_dev *dev, struct msix_entry *entries,
 			  int minvec, int maxvec);
+static inline int pci_enable_msix_exact(struct pci_dev *dev,
+					struct msix_entry *entries, int nvec)
+{
+	int rc = pci_enable_msix_range(dev, entries, nvec, nvec);
+	if (rc < 0)
+		return rc;
+	return 0;
+}
 #else
 static inline int pci_msi_vec_count(struct pci_dev *dev) { return -ENOSYS; }
 static inline int pci_enable_msi_block(struct pci_dev *dev, int nvec)
@@ -1189,9 +1204,14 @@
 static inline int pci_enable_msi_range(struct pci_dev *dev, int minvec,
 				       int maxvec)
 { return -ENOSYS; }
+static inline int pci_enable_msi_exact(struct pci_dev *dev, int nvec)
+{ return -ENOSYS; }
 static inline int pci_enable_msix_range(struct pci_dev *dev,
 		      struct msix_entry *entries, int minvec, int maxvec)
 { return -ENOSYS; }
+static inline int pci_enable_msix_exact(struct pci_dev *dev,
+		      struct msix_entry *entries, int nvec)
+{ return -ENOSYS; }
 #endif
 
 #ifdef CONFIG_PCIEPORTBUS
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index f589c9af..3ebbbe7 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -2916,5 +2916,22 @@
 {
 	return !skb->head_frag || skb_cloned(skb);
 }
+
+/**
+ * skb_gso_network_seglen - Return length of individual segments of a gso packet
+ *
+ * @skb: GSO skb
+ *
+ * skb_gso_network_seglen is used to determine the real size of the
+ * individual segments, including Layer3 (IP, IPv6) and L4 headers (TCP/UDP).
+ *
+ * The MAC/L2 header is not accounted for.
+ */
+static inline unsigned int skb_gso_network_seglen(const struct sk_buff *skb)
+{
+	unsigned int hdr_len = skb_transport_header(skb) -
+			       skb_network_header(skb);
+	return hdr_len + skb_gso_transport_seglen(skb);
+}
 #endif	/* __KERNEL__ */
 #endif	/* _LINUX_SKBUFF_H */
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index 40ed9e9..a747a77 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -281,13 +281,15 @@
 asmlinkage long sys_sched_setparam(pid_t pid,
 					struct sched_param __user *param);
 asmlinkage long sys_sched_setattr(pid_t pid,
-					struct sched_attr __user *attr);
+					struct sched_attr __user *attr,
+					unsigned int flags);
 asmlinkage long sys_sched_getscheduler(pid_t pid);
 asmlinkage long sys_sched_getparam(pid_t pid,
 					struct sched_param __user *param);
 asmlinkage long sys_sched_getattr(pid_t pid,
 					struct sched_attr __user *attr,
-					unsigned int size);
+					unsigned int size,
+					unsigned int flags);
 asmlinkage long sys_sched_setaffinity(pid_t pid, unsigned int len,
 					unsigned long __user *user_mask_ptr);
 asmlinkage long sys_sched_getaffinity(pid_t pid, unsigned int len,
diff --git a/include/linux/workqueue.h b/include/linux/workqueue.h
index 594521b..704f4f6 100644
--- a/include/linux/workqueue.h
+++ b/include/linux/workqueue.h
@@ -419,10 +419,7 @@
 	static struct lock_class_key __key;				\
 	const char *__lock_name;					\
 									\
-	if (__builtin_constant_p(fmt))					\
-		__lock_name = (fmt);					\
-	else								\
-		__lock_name = #fmt;					\
+	__lock_name = #fmt#args;					\
 									\
 	__alloc_workqueue_key((fmt), (flags), (max_active),		\
 			      &__key, __lock_name, ##args);		\
diff --git a/include/linux/writeback.h b/include/linux/writeback.h
index fc0e432..021b8a3 100644
--- a/include/linux/writeback.h
+++ b/include/linux/writeback.h
@@ -97,7 +97,7 @@
 int try_to_writeback_inodes_sb(struct super_block *, enum wb_reason reason);
 int try_to_writeback_inodes_sb_nr(struct super_block *, unsigned long nr,
 				  enum wb_reason reason);
-void sync_inodes_sb(struct super_block *sb, unsigned long older_than_this);
+void sync_inodes_sb(struct super_block *);
 void wakeup_flusher_threads(long nr_pages, enum wb_reason reason);
 void inode_wait_for_writeback(struct inode *inode);
 
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index d992ca3..6ee76c8 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -1653,17 +1653,6 @@
 	/* This is the last advertised value of rwnd over a SACK chunk. */
 	__u32 a_rwnd;
 
-	/* Number of bytes by which the rwnd has slopped.  The rwnd is allowed
-	 * to slop over a maximum of the association's frag_point.
-	 */
-	__u32 rwnd_over;
-
-	/* Keeps treack of rwnd pressure.  This happens when we have
-	 * a window, but not recevie buffer (i.e small packets).  This one
-	 * is releases slowly (1 PMTU at a time ).
-	 */
-	__u32 rwnd_press;
-
 	/* This is the sndbuf size in use for the association.
 	 * This corresponds to the sndbuf size for the association,
 	 * as specified in the sk->sndbuf.
@@ -1892,8 +1881,7 @@
 __u32 sctp_association_get_next_tsn(struct sctp_association *);
 
 void sctp_assoc_sync_pmtu(struct sock *, struct sctp_association *);
-void sctp_assoc_rwnd_increase(struct sctp_association *, unsigned int);
-void sctp_assoc_rwnd_decrease(struct sctp_association *, unsigned int);
+void sctp_assoc_rwnd_update(struct sctp_association *, bool);
 void sctp_assoc_set_primary(struct sctp_association *,
 			    struct sctp_transport *);
 void sctp_assoc_del_nonprimary_peers(struct sctp_association *,
diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h
index 68d92e3..6e89ef6 100644
--- a/include/sound/soc-dapm.h
+++ b/include/sound/soc-dapm.h
@@ -449,14 +449,22 @@
 /* dapm audio pin control and status */
 int snd_soc_dapm_enable_pin(struct snd_soc_dapm_context *dapm,
 			    const char *pin);
+int snd_soc_dapm_enable_pin_unlocked(struct snd_soc_dapm_context *dapm,
+				     const char *pin);
 int snd_soc_dapm_disable_pin(struct snd_soc_dapm_context *dapm,
 			     const char *pin);
+int snd_soc_dapm_disable_pin_unlocked(struct snd_soc_dapm_context *dapm,
+				      const char *pin);
 int snd_soc_dapm_nc_pin(struct snd_soc_dapm_context *dapm, const char *pin);
+int snd_soc_dapm_nc_pin_unlocked(struct snd_soc_dapm_context *dapm,
+				 const char *pin);
 int snd_soc_dapm_get_pin_status(struct snd_soc_dapm_context *dapm,
 				const char *pin);
 int snd_soc_dapm_sync(struct snd_soc_dapm_context *dapm);
 int snd_soc_dapm_force_enable_pin(struct snd_soc_dapm_context *dapm,
 				  const char *pin);
+int snd_soc_dapm_force_enable_pin_unlocked(struct snd_soc_dapm_context *dapm,
+					   const char *pin);
 int snd_soc_dapm_ignore_suspend(struct snd_soc_dapm_context *dapm,
 				const char *pin);
 void snd_soc_dapm_auto_nc_codec_pins(struct snd_soc_codec *codec);
diff --git a/include/trace/events/writeback.h b/include/trace/events/writeback.h
index c7bbbe7..464ea82 100644
--- a/include/trace/events/writeback.h
+++ b/include/trace/events/writeback.h
@@ -287,11 +287,11 @@
 		__field(int,		reason)
 	),
 	TP_fast_assign(
-		unsigned long older_than_this = work->older_than_this;
+		unsigned long *older_than_this = work->older_than_this;
 		strncpy(__entry->name, dev_name(wb->bdi->dev), 32);
-		__entry->older	= older_than_this;
+		__entry->older	= older_than_this ?  *older_than_this : 0;
 		__entry->age	= older_than_this ?
-				  (jiffies - older_than_this) * 1000 / HZ : -1;
+				  (jiffies - *older_than_this) * 1000 / HZ : -1;
 		__entry->moved	= moved;
 		__entry->reason	= work->reason;
 	),
diff --git a/include/uapi/asm-generic/unistd.h b/include/uapi/asm-generic/unistd.h
index a20a9b4..dde8041 100644
--- a/include/uapi/asm-generic/unistd.h
+++ b/include/uapi/asm-generic/unistd.h
@@ -692,9 +692,13 @@
 __SYSCALL(__NR_kcmp, sys_kcmp)
 #define __NR_finit_module 273
 __SYSCALL(__NR_finit_module, sys_finit_module)
+#define __NR_sched_setattr 274
+__SYSCALL(__NR_sched_setattr, sys_sched_setattr)
+#define __NR_sched_getattr 275
+__SYSCALL(__NR_sched_getattr, sys_sched_getattr)
 
 #undef __NR_syscalls
-#define __NR_syscalls 274
+#define __NR_syscalls 276
 
 /*
  * All syscalls below here should go away really,
diff --git a/include/uapi/drm/drm.h b/include/uapi/drm/drm.h
index 3c9a833..b06c8ed 100644
--- a/include/uapi/drm/drm.h
+++ b/include/uapi/drm/drm.h
@@ -619,6 +619,8 @@
 #define  DRM_PRIME_CAP_EXPORT		0x2
 #define DRM_CAP_TIMESTAMP_MONOTONIC	0x6
 #define DRM_CAP_ASYNC_PAGE_FLIP		0x7
+#define DRM_CAP_CURSOR_WIDTH		0x8
+#define DRM_CAP_CURSOR_HEIGHT		0x9
 
 /** DRM_IOCTL_GET_CAP ioctl argument type */
 struct drm_get_cap {
diff --git a/include/uapi/drm/vmwgfx_drm.h b/include/uapi/drm/vmwgfx_drm.h
index 9971c56..87792a5 100644
--- a/include/uapi/drm/vmwgfx_drm.h
+++ b/include/uapi/drm/vmwgfx_drm.h
@@ -87,6 +87,7 @@
 #define DRM_VMW_PARAM_MAX_SURF_MEMORY  7
 #define DRM_VMW_PARAM_3D_CAPS_SIZE     8
 #define DRM_VMW_PARAM_MAX_MOB_MEMORY   9
+#define DRM_VMW_PARAM_MAX_MOB_SIZE     10
 
 /**
  * struct drm_vmw_getparam_arg
diff --git a/ipc/mq_sysctl.c b/ipc/mq_sysctl.c
index 383d638..5bb8bfe 100644
--- a/ipc/mq_sysctl.c
+++ b/ipc/mq_sysctl.c
@@ -22,6 +22,16 @@
 	return which;
 }
 
+static int proc_mq_dointvec(ctl_table *table, int write,
+			    void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+	struct ctl_table mq_table;
+	memcpy(&mq_table, table, sizeof(mq_table));
+	mq_table.data = get_mq(table);
+
+	return proc_dointvec(&mq_table, write, buffer, lenp, ppos);
+}
+
 static int proc_mq_dointvec_minmax(ctl_table *table, int write,
 	void __user *buffer, size_t *lenp, loff_t *ppos)
 {
@@ -33,12 +43,10 @@
 					lenp, ppos);
 }
 #else
+#define proc_mq_dointvec NULL
 #define proc_mq_dointvec_minmax NULL
 #endif
 
-static int msg_queues_limit_min = MIN_QUEUESMAX;
-static int msg_queues_limit_max = HARD_QUEUESMAX;
-
 static int msg_max_limit_min = MIN_MSGMAX;
 static int msg_max_limit_max = HARD_MSGMAX;
 
@@ -51,9 +59,7 @@
 		.data		= &init_ipc_ns.mq_queues_max,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= proc_mq_dointvec_minmax,
-		.extra1		= &msg_queues_limit_min,
-		.extra2		= &msg_queues_limit_max,
+		.proc_handler	= proc_mq_dointvec,
 	},
 	{
 		.procname	= "msg_max",
diff --git a/ipc/mqueue.c b/ipc/mqueue.c
index ccf1f9f..c3b3117 100644
--- a/ipc/mqueue.c
+++ b/ipc/mqueue.c
@@ -433,9 +433,9 @@
 		error = -EACCES;
 		goto out_unlock;
 	}
-	if (ipc_ns->mq_queues_count >= HARD_QUEUESMAX ||
-	    (ipc_ns->mq_queues_count >= ipc_ns->mq_queues_max &&
-	     !capable(CAP_SYS_RESOURCE))) {
+
+	if (ipc_ns->mq_queues_count >= ipc_ns->mq_queues_max &&
+	    !capable(CAP_SYS_RESOURCE)) {
 		error = -ENOSPC;
 		goto out_unlock;
 	}
diff --git a/kernel/audit_tree.c b/kernel/audit_tree.c
index 67ccf0e..135944a 100644
--- a/kernel/audit_tree.c
+++ b/kernel/audit_tree.c
@@ -916,7 +916,7 @@
 				   struct fsnotify_mark *inode_mark,
 				   struct fsnotify_mark *vfsmount_mark,
 				   u32 mask, void *data, int data_type,
-				   const unsigned char *file_name)
+				   const unsigned char *file_name, u32 cookie)
 {
 	return 0;
 }
diff --git a/kernel/audit_watch.c b/kernel/audit_watch.c
index 2596fac..70b4554 100644
--- a/kernel/audit_watch.c
+++ b/kernel/audit_watch.c
@@ -471,7 +471,7 @@
 				    struct fsnotify_mark *inode_mark,
 				    struct fsnotify_mark *vfsmount_mark,
 				    u32 mask, void *data, int data_type,
-				    const unsigned char *dname)
+				    const unsigned char *dname, u32 cookie)
 {
 	struct inode *inode;
 	struct audit_parent *parent;
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index e2f46ba..105f273 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -886,7 +886,9 @@
 		 * per-subsystem and moved to css->id so that lookups are
 		 * successful until the target css is released.
 		 */
+		mutex_lock(&cgroup_mutex);
 		idr_remove(&cgrp->root->cgroup_idr, cgrp->id);
+		mutex_unlock(&cgroup_mutex);
 		cgrp->id = -1;
 
 		call_rcu(&cgrp->rcu_head, cgroup_free_rcu);
@@ -1566,10 +1568,10 @@
 		mutex_lock(&cgroup_mutex);
 		mutex_lock(&cgroup_root_mutex);
 
-		root_cgrp->id = idr_alloc(&root->cgroup_idr, root_cgrp,
-					   0, 1, GFP_KERNEL);
-		if (root_cgrp->id < 0)
+		ret = idr_alloc(&root->cgroup_idr, root_cgrp, 0, 1, GFP_KERNEL);
+		if (ret < 0)
 			goto unlock_drop;
+		root_cgrp->id = ret;
 
 		/* Check for name clashes with existing mounts */
 		ret = -EBUSY;
@@ -2763,10 +2765,7 @@
 	 */
 	update_before = cgroup_serial_nr_next;
 
-	mutex_unlock(&cgroup_mutex);
-
 	/* add/rm files for all cgroups created before */
-	rcu_read_lock();
 	css_for_each_descendant_pre(css, cgroup_css(root, ss)) {
 		struct cgroup *cgrp = css->cgroup;
 
@@ -2775,23 +2774,19 @@
 
 		inode = cgrp->dentry->d_inode;
 		dget(cgrp->dentry);
-		rcu_read_unlock();
-
 		dput(prev);
 		prev = cgrp->dentry;
 
+		mutex_unlock(&cgroup_mutex);
 		mutex_lock(&inode->i_mutex);
 		mutex_lock(&cgroup_mutex);
 		if (cgrp->serial_nr < update_before && !cgroup_is_dead(cgrp))
 			ret = cgroup_addrm_files(cgrp, cfts, is_add);
-		mutex_unlock(&cgroup_mutex);
 		mutex_unlock(&inode->i_mutex);
-
-		rcu_read_lock();
 		if (ret)
 			break;
 	}
-	rcu_read_unlock();
+	mutex_unlock(&cgroup_mutex);
 	dput(prev);
 	deactivate_super(sb);
 	return ret;
@@ -2910,9 +2905,14 @@
 		 * We should check if the process is exiting, otherwise
 		 * it will race with cgroup_exit() in that the list
 		 * entry won't be deleted though the process has exited.
+		 * Do it while holding siglock so that we don't end up
+		 * racing against cgroup_exit().
 		 */
+		spin_lock_irq(&p->sighand->siglock);
 		if (!(p->flags & PF_EXITING) && list_empty(&p->cg_list))
 			list_add(&p->cg_list, &task_css_set(p)->tasks);
+		spin_unlock_irq(&p->sighand->siglock);
+
 		task_unlock(p);
 	} while_each_thread(g, p);
 	read_unlock(&tasklist_lock);
@@ -4158,7 +4158,7 @@
 	struct cgroup *cgrp;
 	struct cgroup_name *name;
 	struct cgroupfs_root *root = parent->root;
-	int ssid, err = 0;
+	int ssid, err;
 	struct cgroup_subsys *ss;
 	struct super_block *sb = root->sb;
 
@@ -4168,19 +4168,13 @@
 		return -ENOMEM;
 
 	name = cgroup_alloc_name(dentry);
-	if (!name)
+	if (!name) {
+		err = -ENOMEM;
 		goto err_free_cgrp;
+	}
 	rcu_assign_pointer(cgrp->name, name);
 
 	/*
-	 * Temporarily set the pointer to NULL, so idr_find() won't return
-	 * a half-baked cgroup.
-	 */
-	cgrp->id = idr_alloc(&root->cgroup_idr, NULL, 1, 0, GFP_KERNEL);
-	if (cgrp->id < 0)
-		goto err_free_name;
-
-	/*
 	 * Only live parents can have children.  Note that the liveliness
 	 * check isn't strictly necessary because cgroup_mkdir() and
 	 * cgroup_rmdir() are fully synchronized by i_mutex; however, do it
@@ -4189,7 +4183,17 @@
 	 */
 	if (!cgroup_lock_live_group(parent)) {
 		err = -ENODEV;
-		goto err_free_id;
+		goto err_free_name;
+	}
+
+	/*
+	 * Temporarily set the pointer to NULL, so idr_find() won't return
+	 * a half-baked cgroup.
+	 */
+	cgrp->id = idr_alloc(&root->cgroup_idr, NULL, 1, 0, GFP_KERNEL);
+	if (cgrp->id < 0) {
+		err = -ENOMEM;
+		goto err_unlock;
 	}
 
 	/* Grab a reference on the superblock so the hierarchy doesn't
@@ -4221,7 +4225,7 @@
 	 */
 	err = cgroup_create_file(dentry, S_IFDIR | mode, sb);
 	if (err < 0)
-		goto err_unlock;
+		goto err_free_id;
 	lockdep_assert_held(&dentry->d_inode->i_mutex);
 
 	cgrp->serial_nr = cgroup_serial_nr_next++;
@@ -4257,12 +4261,12 @@
 
 	return 0;
 
-err_unlock:
-	mutex_unlock(&cgroup_mutex);
-	/* Release the reference count that we took on the superblock */
-	deactivate_super(sb);
 err_free_id:
 	idr_remove(&root->cgroup_idr, cgrp->id);
+	/* Release the reference count that we took on the superblock */
+	deactivate_super(sb);
+err_unlock:
+	mutex_unlock(&cgroup_mutex);
 err_free_name:
 	kfree(rcu_dereference_raw(cgrp->name));
 err_free_cgrp:
diff --git a/kernel/events/core.c b/kernel/events/core.c
index 56003c6..fa0b2d4 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -7856,14 +7856,14 @@
 static void __perf_event_exit_context(void *__info)
 {
 	struct perf_event_context *ctx = __info;
-	struct perf_event *event, *tmp;
+	struct perf_event *event;
 
 	perf_pmu_rotate_stop(ctx->pmu);
 
-	list_for_each_entry_safe(event, tmp, &ctx->pinned_groups, group_entry)
+	rcu_read_lock();
+	list_for_each_entry_rcu(event, &ctx->event_list, event_entry)
 		__perf_remove_from_context(event);
-	list_for_each_entry_safe(event, tmp, &ctx->flexible_groups, group_entry)
-		__perf_remove_from_context(event);
+	rcu_read_unlock();
 }
 
 static void perf_event_exit_cpu_context(int cpu)
@@ -7887,11 +7887,11 @@
 {
 	struct swevent_htable *swhash = &per_cpu(swevent_htable, cpu);
 
+	perf_event_exit_cpu_context(cpu);
+
 	mutex_lock(&swhash->hlist_mutex);
 	swevent_hlist_release(swhash);
 	mutex_unlock(&swhash->hlist_mutex);
-
-	perf_event_exit_cpu_context(cpu);
 }
 #else
 static inline void perf_event_exit_cpu(int cpu) { }
diff --git a/kernel/power/console.c b/kernel/power/console.c
index eacb8bd..aba9c54 100644
--- a/kernel/power/console.c
+++ b/kernel/power/console.c
@@ -9,6 +9,7 @@
 #include <linux/kbd_kern.h>
 #include <linux/vt.h>
 #include <linux/module.h>
+#include <linux/slab.h>
 #include "power.h"
 
 #define SUSPEND_CONSOLE	(MAX_NR_CONSOLES-1)
diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
index b1d255f..4dae9cb 100644
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
@@ -1076,7 +1076,6 @@
 		next_seq = log_next_seq;
 
 		len = 0;
-		prev = 0;
 		while (len >= 0 && seq < next_seq) {
 			struct printk_log *msg = log_from_idx(idx);
 			int textlen;
@@ -2788,7 +2787,6 @@
 	next_idx = idx;
 
 	l = 0;
-	prev = 0;
 	while (seq < dumper->next_seq) {
 		struct printk_log *msg = log_from_idx(idx);
 
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index b46131e..6edbef2 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -1952,7 +1952,7 @@
 {
 
 	struct dl_bw *dl_b = dl_bw_of(task_cpu(p));
-	u64 period = attr->sched_period;
+	u64 period = attr->sched_period ?: attr->sched_deadline;
 	u64 runtime = attr->sched_runtime;
 	u64 new_bw = dl_policy(policy) ? to_ratio(period, runtime) : 0;
 	int cpus, err = -1;
@@ -3661,13 +3661,14 @@
  * @pid: the pid in question.
  * @uattr: structure containing the extended parameters.
  */
-SYSCALL_DEFINE2(sched_setattr, pid_t, pid, struct sched_attr __user *, uattr)
+SYSCALL_DEFINE3(sched_setattr, pid_t, pid, struct sched_attr __user *, uattr,
+			       unsigned int, flags)
 {
 	struct sched_attr attr;
 	struct task_struct *p;
 	int retval;
 
-	if (!uattr || pid < 0)
+	if (!uattr || pid < 0 || flags)
 		return -EINVAL;
 
 	if (sched_copy_attr(uattr, &attr))
@@ -3786,7 +3787,7 @@
 		attr->size = usize;
 	}
 
-	ret = copy_to_user(uattr, attr, usize);
+	ret = copy_to_user(uattr, attr, attr->size);
 	if (ret)
 		return -EFAULT;
 
@@ -3804,8 +3805,8 @@
  * @uattr: structure containing the extended parameters.
  * @size: sizeof(attr) for fwd/bwd comp.
  */
-SYSCALL_DEFINE3(sched_getattr, pid_t, pid, struct sched_attr __user *, uattr,
-		unsigned int, size)
+SYSCALL_DEFINE4(sched_getattr, pid_t, pid, struct sched_attr __user *, uattr,
+		unsigned int, size, unsigned int, flags)
 {
 	struct sched_attr attr = {
 		.size = sizeof(struct sched_attr),
@@ -3814,7 +3815,7 @@
 	int retval;
 
 	if (!uattr || pid < 0 || size > PAGE_SIZE ||
-	    size < SCHED_ATTR_SIZE_VER0)
+	    size < SCHED_ATTR_SIZE_VER0 || flags)
 		return -EINVAL;
 
 	rcu_read_lock();
@@ -7422,6 +7423,7 @@
 	u64 period = global_rt_period();
 	u64 new_bw = to_ratio(period, runtime);
 	int cpu, ret = 0;
+	unsigned long flags;
 
 	/*
 	 * Here we want to check the bandwidth not being set to some
@@ -7435,10 +7437,10 @@
 	for_each_possible_cpu(cpu) {
 		struct dl_bw *dl_b = dl_bw_of(cpu);
 
-		raw_spin_lock(&dl_b->lock);
+		raw_spin_lock_irqsave(&dl_b->lock, flags);
 		if (new_bw < dl_b->total_bw)
 			ret = -EBUSY;
-		raw_spin_unlock(&dl_b->lock);
+		raw_spin_unlock_irqrestore(&dl_b->lock, flags);
 
 		if (ret)
 			break;
@@ -7451,6 +7453,7 @@
 {
 	u64 new_bw = -1;
 	int cpu;
+	unsigned long flags;
 
 	def_dl_bandwidth.dl_period = global_rt_period();
 	def_dl_bandwidth.dl_runtime = global_rt_runtime();
@@ -7464,9 +7467,9 @@
 	for_each_possible_cpu(cpu) {
 		struct dl_bw *dl_b = dl_bw_of(cpu);
 
-		raw_spin_lock(&dl_b->lock);
+		raw_spin_lock_irqsave(&dl_b->lock, flags);
 		dl_b->bw = new_bw;
-		raw_spin_unlock(&dl_b->lock);
+		raw_spin_unlock_irqrestore(&dl_b->lock, flags);
 	}
 }
 
@@ -7475,7 +7478,8 @@
 	if (sysctl_sched_rt_period <= 0)
 		return -EINVAL;
 
-	if (sysctl_sched_rt_runtime > sysctl_sched_rt_period)
+	if ((sysctl_sched_rt_runtime != RUNTIME_INF) &&
+		(sysctl_sched_rt_runtime > sysctl_sched_rt_period))
 		return -EINVAL;
 
 	return 0;
diff --git a/kernel/sched/cpudeadline.c b/kernel/sched/cpudeadline.c
index 045fc74..5b8838b 100644
--- a/kernel/sched/cpudeadline.c
+++ b/kernel/sched/cpudeadline.c
@@ -70,7 +70,7 @@
 
 static void cpudl_change_key(struct cpudl *cp, int idx, u64 new_dl)
 {
-	WARN_ON(idx > num_present_cpus() || idx == IDX_INVALID);
+	WARN_ON(!cpu_present(idx) || idx == IDX_INVALID);
 
 	if (dl_time_before(new_dl, cp->elements[idx].dl)) {
 		cp->elements[idx].dl = new_dl;
@@ -117,7 +117,7 @@
 	}
 
 out:
-	WARN_ON(best_cpu > num_present_cpus() && best_cpu != -1);
+	WARN_ON(!cpu_present(best_cpu) && best_cpu != -1);
 
 	return best_cpu;
 }
@@ -137,7 +137,7 @@
 	int old_idx, new_cpu;
 	unsigned long flags;
 
-	WARN_ON(cpu > num_present_cpus());
+	WARN_ON(!cpu_present(cpu));
 
 	raw_spin_lock_irqsave(&cp->lock, flags);
 	old_idx = cp->cpu_to_idx[cpu];
diff --git a/kernel/sched/deadline.c b/kernel/sched/deadline.c
index 0dd5e09..15cbc17 100644
--- a/kernel/sched/deadline.c
+++ b/kernel/sched/deadline.c
@@ -121,7 +121,7 @@
 
 static void update_dl_migration(struct dl_rq *dl_rq)
 {
-	if (dl_rq->dl_nr_migratory && dl_rq->dl_nr_total > 1) {
+	if (dl_rq->dl_nr_migratory && dl_rq->dl_nr_running > 1) {
 		if (!dl_rq->overloaded) {
 			dl_set_overload(rq_of_dl_rq(dl_rq));
 			dl_rq->overloaded = 1;
@@ -137,7 +137,6 @@
 	struct task_struct *p = dl_task_of(dl_se);
 	dl_rq = &rq_of_dl_rq(dl_rq)->dl;
 
-	dl_rq->dl_nr_total++;
 	if (p->nr_cpus_allowed > 1)
 		dl_rq->dl_nr_migratory++;
 
@@ -149,7 +148,6 @@
 	struct task_struct *p = dl_task_of(dl_se);
 	dl_rq = &rq_of_dl_rq(dl_rq)->dl;
 
-	dl_rq->dl_nr_total--;
 	if (p->nr_cpus_allowed > 1)
 		dl_rq->dl_nr_migratory--;
 
@@ -717,6 +715,7 @@
 
 	WARN_ON(!dl_prio(prio));
 	dl_rq->dl_nr_running++;
+	inc_nr_running(rq_of_dl_rq(dl_rq));
 
 	inc_dl_deadline(dl_rq, deadline);
 	inc_dl_migration(dl_se, dl_rq);
@@ -730,6 +729,7 @@
 	WARN_ON(!dl_prio(prio));
 	WARN_ON(!dl_rq->dl_nr_running);
 	dl_rq->dl_nr_running--;
+	dec_nr_running(rq_of_dl_rq(dl_rq));
 
 	dec_dl_deadline(dl_rq, dl_se->deadline);
 	dec_dl_migration(dl_se, dl_rq);
@@ -836,8 +836,6 @@
 
 	if (!task_current(rq, p) && p->nr_cpus_allowed > 1)
 		enqueue_pushable_dl_task(rq, p);
-
-	inc_nr_running(rq);
 }
 
 static void __dequeue_task_dl(struct rq *rq, struct task_struct *p, int flags)
@@ -850,8 +848,6 @@
 {
 	update_curr_dl(rq);
 	__dequeue_task_dl(rq, p, flags);
-
-	dec_nr_running(rq);
 }
 
 /*
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index 966cc2b..7815709 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -1757,6 +1757,8 @@
 			start = end;
 			if (pages <= 0)
 				goto out;
+
+			cond_resched();
 		} while (end != vma->vm_end);
 	}
 
diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h
index c2119fd..f964add 100644
--- a/kernel/sched/sched.h
+++ b/kernel/sched/sched.h
@@ -462,7 +462,6 @@
 	} earliest_dl;
 
 	unsigned long dl_nr_migratory;
-	unsigned long dl_nr_total;
 	int overloaded;
 
 	/*
diff --git a/kernel/time/sched_clock.c b/kernel/time/sched_clock.c
index 0abb364..4d23dc4 100644
--- a/kernel/time/sched_clock.c
+++ b/kernel/time/sched_clock.c
@@ -116,20 +116,42 @@
 void __init sched_clock_register(u64 (*read)(void), int bits,
 				 unsigned long rate)
 {
+	u64 res, wrap, new_mask, new_epoch, cyc, ns;
+	u32 new_mult, new_shift;
+	ktime_t new_wrap_kt;
 	unsigned long r;
-	u64 res, wrap;
 	char r_unit;
 
 	if (cd.rate > rate)
 		return;
 
 	WARN_ON(!irqs_disabled());
-	read_sched_clock = read;
-	sched_clock_mask = CLOCKSOURCE_MASK(bits);
-	cd.rate = rate;
 
 	/* calculate the mult/shift to convert counter ticks to ns. */
-	clocks_calc_mult_shift(&cd.mult, &cd.shift, rate, NSEC_PER_SEC, 3600);
+	clocks_calc_mult_shift(&new_mult, &new_shift, rate, NSEC_PER_SEC, 3600);
+
+	new_mask = CLOCKSOURCE_MASK(bits);
+
+	/* calculate how many ns until we wrap */
+	wrap = clocks_calc_max_nsecs(new_mult, new_shift, 0, new_mask);
+	new_wrap_kt = ns_to_ktime(wrap - (wrap >> 3));
+
+	/* update epoch for new counter and update epoch_ns from old counter*/
+	new_epoch = read();
+	cyc = read_sched_clock();
+	ns = cd.epoch_ns + cyc_to_ns((cyc - cd.epoch_cyc) & sched_clock_mask,
+			  cd.mult, cd.shift);
+
+	raw_write_seqcount_begin(&cd.seq);
+	read_sched_clock = read;
+	sched_clock_mask = new_mask;
+	cd.rate = rate;
+	cd.wrap_kt = new_wrap_kt;
+	cd.mult = new_mult;
+	cd.shift = new_shift;
+	cd.epoch_cyc = new_epoch;
+	cd.epoch_ns = ns;
+	raw_write_seqcount_end(&cd.seq);
 
 	r = rate;
 	if (r >= 4000000) {
@@ -141,22 +163,12 @@
 	} else
 		r_unit = ' ';
 
-	/* calculate how many ns until we wrap */
-	wrap = clocks_calc_max_nsecs(cd.mult, cd.shift, 0, sched_clock_mask);
-	cd.wrap_kt = ns_to_ktime(wrap - (wrap >> 3));
-
 	/* calculate the ns resolution of this counter */
-	res = cyc_to_ns(1ULL, cd.mult, cd.shift);
+	res = cyc_to_ns(1ULL, new_mult, new_shift);
+
 	pr_info("sched_clock: %u bits at %lu%cHz, resolution %lluns, wraps every %lluns\n",
 		bits, r, r_unit, res, wrap);
 
-	update_sched_clock();
-
-	/*
-	 * Ensure that sched_clock() starts off at 0ns
-	 */
-	cd.epoch_ns = 0;
-
 	/* Enable IRQ time accounting if we have a fast enough sched_clock */
 	if (irqtime > 0 || (irqtime == -1 && rate >= 1000000))
 		enable_sched_clock_irqtime();
diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c
index 240fb62..dd06439 100644
--- a/kernel/user_namespace.c
+++ b/kernel/user_namespace.c
@@ -225,7 +225,7 @@
  *
  *	When there is no mapping defined for the user-namespace uid
  *	pair INVALID_UID is returned.  Callers are expected to test
- *	for and handle handle INVALID_UID being returned.  INVALID_UID
+ *	for and handle INVALID_UID being returned.  INVALID_UID
  *	may be tested for using uid_valid().
  */
 kuid_t make_kuid(struct user_namespace *ns, uid_t uid)
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index 82ef9f3..193e977 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -1851,6 +1851,12 @@
 	if (worker->flags & WORKER_IDLE)
 		pool->nr_idle--;
 
+	/*
+	 * Once WORKER_DIE is set, the kworker may destroy itself at any
+	 * point.  Pin to ensure the task stays until we're done with it.
+	 */
+	get_task_struct(worker->task);
+
 	list_del_init(&worker->entry);
 	worker->flags |= WORKER_DIE;
 
@@ -1859,6 +1865,7 @@
 	spin_unlock_irq(&pool->lock);
 
 	kthread_stop(worker->task);
+	put_task_struct(worker->task);
 	kfree(worker);
 
 	spin_lock_irq(&pool->lock);
diff --git a/mm/huge_memory.c b/mm/huge_memory.c
index 82166bf..4df39b1 100644
--- a/mm/huge_memory.c
+++ b/mm/huge_memory.c
@@ -1166,8 +1166,10 @@
 		} else {
 			ret = do_huge_pmd_wp_page_fallback(mm, vma, address,
 					pmd, orig_pmd, page, haddr);
-			if (ret & VM_FAULT_OOM)
+			if (ret & VM_FAULT_OOM) {
 				split_huge_page(page);
+				ret |= VM_FAULT_FALLBACK;
+			}
 			put_page(page);
 		}
 		count_vm_event(THP_FAULT_FALLBACK);
@@ -1179,9 +1181,10 @@
 		if (page) {
 			split_huge_page(page);
 			put_page(page);
-		}
+		} else
+			split_huge_page_pmd(vma, address, pmd);
+		ret |= VM_FAULT_FALLBACK;
 		count_vm_event(THP_FAULT_FALLBACK);
-		ret |= VM_FAULT_OOM;
 		goto out;
 	}
 
@@ -1545,6 +1548,7 @@
 				entry = pmd_mknonnuma(entry);
 			entry = pmd_modify(entry, newprot);
 			ret = HPAGE_PMD_NR;
+			set_pmd_at(mm, addr, pmd, entry);
 			BUG_ON(pmd_write(entry));
 		} else {
 			struct page *page = pmd_page(*pmd);
@@ -1557,16 +1561,10 @@
 			 */
 			if (!is_huge_zero_page(page) &&
 			    !pmd_numa(*pmd)) {
-				entry = *pmd;
-				entry = pmd_mknuma(entry);
+				pmdp_set_numa(mm, addr, pmd);
 				ret = HPAGE_PMD_NR;
 			}
 		}
-
-		/* Set PMD if cleared earlier */
-		if (ret == HPAGE_PMD_NR)
-			set_pmd_at(mm, addr, pmd, entry);
-
 		spin_unlock(ptl);
 	}
 
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index 53385cd..ce7a8cc 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -1687,7 +1687,7 @@
 	 * protects memcg_name and makes sure that parallel ooms do not
 	 * interleave
 	 */
-	static DEFINE_SPINLOCK(oom_info_lock);
+	static DEFINE_MUTEX(oom_info_lock);
 	struct cgroup *task_cgrp;
 	struct cgroup *mem_cgrp;
 	static char memcg_name[PATH_MAX];
@@ -1698,7 +1698,7 @@
 	if (!p)
 		return;
 
-	spin_lock(&oom_info_lock);
+	mutex_lock(&oom_info_lock);
 	rcu_read_lock();
 
 	mem_cgrp = memcg->css.cgroup;
@@ -1767,7 +1767,7 @@
 
 		pr_cont("\n");
 	}
-	spin_unlock(&oom_info_lock);
+	mutex_unlock(&oom_info_lock);
 }
 
 /*
diff --git a/mm/memory.c b/mm/memory.c
index be6a0c0..22dfa61 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -3348,6 +3348,7 @@
 		if (ret & VM_FAULT_LOCKED)
 			unlock_page(vmf.page);
 		ret = VM_FAULT_HWPOISON;
+		page_cache_release(vmf.page);
 		goto uncharge_out;
 	}
 
@@ -3703,7 +3704,6 @@
 	if (unlikely(is_vm_hugetlb_page(vma)))
 		return hugetlb_fault(mm, vma, address, flags);
 
-retry:
 	pgd = pgd_offset(mm, address);
 	pud = pud_alloc(mm, pgd, address);
 	if (!pud)
@@ -3741,20 +3741,13 @@
 			if (dirty && !pmd_write(orig_pmd)) {
 				ret = do_huge_pmd_wp_page(mm, vma, address, pmd,
 							  orig_pmd);
-				/*
-				 * If COW results in an oom, the huge pmd will
-				 * have been split, so retry the fault on the
-				 * pte for a smaller charge.
-				 */
-				if (unlikely(ret & VM_FAULT_OOM))
-					goto retry;
-				return ret;
+				if (!(ret & VM_FAULT_FALLBACK))
+					return ret;
 			} else {
 				huge_pmd_set_accessed(mm, vma, address, pmd,
 						      orig_pmd, dirty);
+				return 0;
 			}
-
-			return 0;
 		}
 	}
 
diff --git a/mm/mprotect.c b/mm/mprotect.c
index 7332c17..769a67a 100644
--- a/mm/mprotect.c
+++ b/mm/mprotect.c
@@ -58,36 +58,27 @@
 				if (pte_numa(ptent))
 					ptent = pte_mknonnuma(ptent);
 				ptent = pte_modify(ptent, newprot);
+				/*
+				 * Avoid taking write faults for pages we
+				 * know to be dirty.
+				 */
+				if (dirty_accountable && pte_dirty(ptent))
+					ptent = pte_mkwrite(ptent);
+				ptep_modify_prot_commit(mm, addr, pte, ptent);
 				updated = true;
 			} else {
 				struct page *page;
 
-				ptent = *pte;
 				page = vm_normal_page(vma, addr, oldpte);
 				if (page && !PageKsm(page)) {
 					if (!pte_numa(oldpte)) {
-						ptent = pte_mknuma(ptent);
-						set_pte_at(mm, addr, pte, ptent);
+						ptep_set_numa(mm, addr, pte);
 						updated = true;
 					}
 				}
 			}
-
-			/*
-			 * Avoid taking write faults for pages we know to be
-			 * dirty.
-			 */
-			if (dirty_accountable && pte_dirty(ptent)) {
-				ptent = pte_mkwrite(ptent);
-				updated = true;
-			}
-
 			if (updated)
 				pages++;
-
-			/* Only !prot_numa always clears the pte */
-			if (!prot_numa)
-				ptep_modify_prot_commit(mm, addr, pte, ptent);
 		} else if (IS_ENABLED(CONFIG_MIGRATION) && !pte_file(oldpte)) {
 			swp_entry_t entry = pte_to_swp_entry(oldpte);
 
diff --git a/mm/vmpressure.c b/mm/vmpressure.c
index 196970a..d4042e7 100644
--- a/mm/vmpressure.c
+++ b/mm/vmpressure.c
@@ -19,6 +19,7 @@
 #include <linux/mm.h>
 #include <linux/vmstat.h>
 #include <linux/eventfd.h>
+#include <linux/slab.h>
 #include <linux/swap.h>
 #include <linux/printk.h>
 #include <linux/vmpressure.h>
diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c
index 512159b..8323bce 100644
--- a/net/batman-adv/bat_iv_ogm.c
+++ b/net/batman-adv/bat_iv_ogm.c
@@ -241,19 +241,19 @@
 	size = bat_priv->num_ifaces * sizeof(uint8_t);
 	orig_node->bat_iv.bcast_own_sum = kzalloc(size, GFP_ATOMIC);
 	if (!orig_node->bat_iv.bcast_own_sum)
-		goto free_bcast_own;
+		goto free_orig_node;
 
 	hash_added = batadv_hash_add(bat_priv->orig_hash, batadv_compare_orig,
 				     batadv_choose_orig, orig_node,
 				     &orig_node->hash_entry);
 	if (hash_added != 0)
-		goto free_bcast_own;
+		goto free_orig_node;
 
 	return orig_node;
 
-free_bcast_own:
-	kfree(orig_node->bat_iv.bcast_own);
 free_orig_node:
+	/* free twice, as batadv_orig_node_new sets refcount to 2 */
+	batadv_orig_node_free_ref(orig_node);
 	batadv_orig_node_free_ref(orig_node);
 
 	return NULL;
@@ -266,7 +266,7 @@
 			struct batadv_orig_node *orig_neigh)
 {
 	struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface);
-	struct batadv_neigh_node *neigh_node;
+	struct batadv_neigh_node *neigh_node, *tmp_neigh_node;
 
 	neigh_node = batadv_neigh_node_new(hard_iface, neigh_addr, orig_node);
 	if (!neigh_node)
@@ -281,14 +281,24 @@
 	neigh_node->orig_node = orig_neigh;
 	neigh_node->if_incoming = hard_iface;
 
-	batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
-		   "Creating new neighbor %pM for orig_node %pM on interface %s\n",
-		   neigh_addr, orig_node->orig, hard_iface->net_dev->name);
-
 	spin_lock_bh(&orig_node->neigh_list_lock);
-	hlist_add_head_rcu(&neigh_node->list, &orig_node->neigh_list);
+	tmp_neigh_node = batadv_neigh_node_get(orig_node, hard_iface,
+					       neigh_addr);
+	if (!tmp_neigh_node) {
+		hlist_add_head_rcu(&neigh_node->list, &orig_node->neigh_list);
+	} else {
+		kfree(neigh_node);
+		batadv_hardif_free_ref(hard_iface);
+		neigh_node = tmp_neigh_node;
+	}
 	spin_unlock_bh(&orig_node->neigh_list_lock);
 
+	if (!tmp_neigh_node)
+		batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
+			   "Creating new neighbor %pM for orig_node %pM on interface %s\n",
+			   neigh_addr, orig_node->orig,
+			   hard_iface->net_dev->name);
+
 out:
 	return neigh_node;
 }
diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c
index 3d417d3..b851cc5 100644
--- a/net/batman-adv/hard-interface.c
+++ b/net/batman-adv/hard-interface.c
@@ -241,7 +241,7 @@
 {
 	struct batadv_priv *bat_priv = netdev_priv(soft_iface);
 	const struct batadv_hard_iface *hard_iface;
-	int min_mtu = ETH_DATA_LEN;
+	int min_mtu = INT_MAX;
 
 	rcu_read_lock();
 	list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) {
@@ -256,8 +256,6 @@
 	}
 	rcu_read_unlock();
 
-	atomic_set(&bat_priv->packet_size_max, min_mtu);
-
 	if (atomic_read(&bat_priv->fragmentation) == 0)
 		goto out;
 
@@ -268,13 +266,21 @@
 	min_mtu = min_t(int, min_mtu, BATADV_FRAG_MAX_FRAG_SIZE);
 	min_mtu -= sizeof(struct batadv_frag_packet);
 	min_mtu *= BATADV_FRAG_MAX_FRAGMENTS;
-	atomic_set(&bat_priv->packet_size_max, min_mtu);
-
-	/* with fragmentation enabled we can fragment external packets easily */
-	min_mtu = min_t(int, min_mtu, ETH_DATA_LEN);
 
 out:
-	return min_mtu - batadv_max_header_len();
+	/* report to the other components the maximum amount of bytes that
+	 * batman-adv can send over the wire (without considering the payload
+	 * overhead). For example, this value is used by TT to compute the
+	 * maximum local table table size
+	 */
+	atomic_set(&bat_priv->packet_size_max, min_mtu);
+
+	/* the real soft-interface MTU is computed by removing the payload
+	 * overhead from the maximum amount of bytes that was just computed.
+	 *
+	 * However batman-adv does not support MTUs bigger than ETH_DATA_LEN
+	 */
+	return min_t(int, min_mtu - batadv_max_header_len(), ETH_DATA_LEN);
 }
 
 /* adjusts the MTU if a new interface with a smaller MTU appeared. */
diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c
index 6df12a2..8539416 100644
--- a/net/batman-adv/originator.c
+++ b/net/batman-adv/originator.c
@@ -458,6 +458,42 @@
 }
 
 /**
+ * batadv_neigh_node_get - retrieve a neighbour from the list
+ * @orig_node: originator which the neighbour belongs to
+ * @hard_iface: the interface where this neighbour is connected to
+ * @addr: the address of the neighbour
+ *
+ * Looks for and possibly returns a neighbour belonging to this originator list
+ * which is connected through the provided hard interface.
+ * Returns NULL if the neighbour is not found.
+ */
+struct batadv_neigh_node *
+batadv_neigh_node_get(const struct batadv_orig_node *orig_node,
+		      const struct batadv_hard_iface *hard_iface,
+		      const uint8_t *addr)
+{
+	struct batadv_neigh_node *tmp_neigh_node, *res = NULL;
+
+	rcu_read_lock();
+	hlist_for_each_entry_rcu(tmp_neigh_node, &orig_node->neigh_list, list) {
+		if (!batadv_compare_eth(tmp_neigh_node->addr, addr))
+			continue;
+
+		if (tmp_neigh_node->if_incoming != hard_iface)
+			continue;
+
+		if (!atomic_inc_not_zero(&tmp_neigh_node->refcount))
+			continue;
+
+		res = tmp_neigh_node;
+		break;
+	}
+	rcu_read_unlock();
+
+	return res;
+}
+
+/**
  * batadv_orig_ifinfo_free_rcu - free the orig_ifinfo object
  * @rcu: rcu pointer of the orig_ifinfo object
  */
diff --git a/net/batman-adv/originator.h b/net/batman-adv/originator.h
index 37be290..db3a9ed 100644
--- a/net/batman-adv/originator.h
+++ b/net/batman-adv/originator.h
@@ -29,6 +29,10 @@
 struct batadv_orig_node *batadv_orig_node_new(struct batadv_priv *bat_priv,
 					      const uint8_t *addr);
 struct batadv_neigh_node *
+batadv_neigh_node_get(const struct batadv_orig_node *orig_node,
+		      const struct batadv_hard_iface *hard_iface,
+		      const uint8_t *addr);
+struct batadv_neigh_node *
 batadv_neigh_node_new(struct batadv_hard_iface *hard_iface,
 		      const uint8_t *neigh_addr,
 		      struct batadv_orig_node *orig_node);
diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c
index 1ed9f7c..a953d5b 100644
--- a/net/batman-adv/routing.c
+++ b/net/batman-adv/routing.c
@@ -688,7 +688,7 @@
 	int is_old_ttvn;
 
 	/* check if there is enough data before accessing it */
-	if (pskb_may_pull(skb, hdr_len + ETH_HLEN) < 0)
+	if (!pskb_may_pull(skb, hdr_len + ETH_HLEN))
 		return 0;
 
 	/* create a copy of the skb (in case of for re-routing) to modify it. */
@@ -918,6 +918,8 @@
 
 	if (ret != NET_RX_SUCCESS)
 		ret = batadv_route_unicast_packet(skb, recv_if);
+	else
+		consume_skb(skb);
 
 	return ret;
 }
diff --git a/net/batman-adv/send.c b/net/batman-adv/send.c
index 579f5f0..843febd 100644
--- a/net/batman-adv/send.c
+++ b/net/batman-adv/send.c
@@ -254,9 +254,9 @@
 				   struct batadv_orig_node *orig_node,
 				   unsigned short vid)
 {
-	struct ethhdr *ethhdr = (struct ethhdr *)skb->data;
+	struct ethhdr *ethhdr;
 	struct batadv_unicast_packet *unicast_packet;
-	int ret = NET_XMIT_DROP;
+	int ret = NET_XMIT_DROP, hdr_size;
 
 	if (!orig_node)
 		goto out;
@@ -265,12 +265,16 @@
 	case BATADV_UNICAST:
 		if (!batadv_send_skb_prepare_unicast(skb, orig_node))
 			goto out;
+
+		hdr_size = sizeof(*unicast_packet);
 		break;
 	case BATADV_UNICAST_4ADDR:
 		if (!batadv_send_skb_prepare_unicast_4addr(bat_priv, skb,
 							   orig_node,
 							   packet_subtype))
 			goto out;
+
+		hdr_size = sizeof(struct batadv_unicast_4addr_packet);
 		break;
 	default:
 		/* this function supports UNICAST and UNICAST_4ADDR only. It
@@ -279,6 +283,7 @@
 		goto out;
 	}
 
+	ethhdr = (struct ethhdr *)(skb->data + hdr_size);
 	unicast_packet = (struct batadv_unicast_packet *)skb->data;
 
 	/* inform the destination node that we are still missing a correct route
diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c
index b6071f6..959dde7 100644
--- a/net/batman-adv/translation-table.c
+++ b/net/batman-adv/translation-table.c
@@ -1975,6 +1975,7 @@
 	struct hlist_head *head;
 	uint32_t i, crc_tmp, crc = 0;
 	uint8_t flags;
+	__be16 tmp_vid;
 
 	for (i = 0; i < hash->size; i++) {
 		head = &hash->table[i];
@@ -2011,8 +2012,11 @@
 							     orig_node))
 				continue;
 
-			crc_tmp = crc32c(0, &tt_common->vid,
-					 sizeof(tt_common->vid));
+			/* use network order to read the VID: this ensures that
+			 * every node reads the bytes in the same order.
+			 */
+			tmp_vid = htons(tt_common->vid);
+			crc_tmp = crc32c(0, &tmp_vid, sizeof(tmp_vid));
 
 			/* compute the CRC on flags that have to be kept in sync
 			 * among nodes
@@ -2046,6 +2050,7 @@
 	struct hlist_head *head;
 	uint32_t i, crc_tmp, crc = 0;
 	uint8_t flags;
+	__be16 tmp_vid;
 
 	for (i = 0; i < hash->size; i++) {
 		head = &hash->table[i];
@@ -2064,8 +2069,11 @@
 			if (tt_common->flags & BATADV_TT_CLIENT_NEW)
 				continue;
 
-			crc_tmp = crc32c(0, &tt_common->vid,
-					 sizeof(tt_common->vid));
+			/* use network order to read the VID: this ensures that
+			 * every node reads the bytes in the same order.
+			 */
+			tmp_vid = htons(tt_common->vid);
+			crc_tmp = crc32c(0, &tmp_vid, sizeof(tmp_vid));
 
 			/* compute the CRC on flags that have to be kept in sync
 			 * among nodes
@@ -2262,6 +2270,7 @@
 {
 	struct batadv_tvlv_tt_vlan_data *tt_vlan_tmp;
 	struct batadv_orig_node_vlan *vlan;
+	uint32_t crc;
 	int i;
 
 	/* check if each received CRC matches the locally stored one */
@@ -2281,7 +2290,10 @@
 		if (!vlan)
 			return false;
 
-		if (vlan->tt.crc != ntohl(tt_vlan_tmp->crc))
+		crc = vlan->tt.crc;
+		batadv_orig_node_vlan_free_ref(vlan);
+
+		if (crc != ntohl(tt_vlan_tmp->crc))
 			return false;
 	}
 
@@ -3218,7 +3230,6 @@
 
 		spin_lock_bh(&orig_node->tt_lock);
 
-		tt_change = (struct batadv_tvlv_tt_change *)tt_buff;
 		batadv_tt_update_changes(bat_priv, orig_node, tt_num_changes,
 					 ttvn, tt_change);
 
diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c
index 292e619..d9fb934 100644
--- a/net/bluetooth/hidp/core.c
+++ b/net/bluetooth/hidp/core.c
@@ -430,6 +430,16 @@
 		del_timer(&session->timer);
 }
 
+static void hidp_process_report(struct hidp_session *session,
+				int type, const u8 *data, int len, int intr)
+{
+	if (len > HID_MAX_BUFFER_SIZE)
+		len = HID_MAX_BUFFER_SIZE;
+
+	memcpy(session->input_buf, data, len);
+	hid_input_report(session->hid, type, session->input_buf, len, intr);
+}
+
 static void hidp_process_handshake(struct hidp_session *session,
 					unsigned char param)
 {
@@ -502,7 +512,8 @@
 			hidp_input_report(session, skb);
 
 		if (session->hid)
-			hid_input_report(session->hid, HID_INPUT_REPORT, skb->data, skb->len, 0);
+			hidp_process_report(session, HID_INPUT_REPORT,
+					    skb->data, skb->len, 0);
 		break;
 
 	case HIDP_DATA_RTYPE_OTHER:
@@ -584,7 +595,8 @@
 			hidp_input_report(session, skb);
 
 		if (session->hid) {
-			hid_input_report(session->hid, HID_INPUT_REPORT, skb->data, skb->len, 1);
+			hidp_process_report(session, HID_INPUT_REPORT,
+					    skb->data, skb->len, 1);
 			BT_DBG("report len %d", skb->len);
 		}
 	} else {
diff --git a/net/bluetooth/hidp/hidp.h b/net/bluetooth/hidp/hidp.h
index ab52414..8798492 100644
--- a/net/bluetooth/hidp/hidp.h
+++ b/net/bluetooth/hidp/hidp.h
@@ -24,6 +24,7 @@
 #define __HIDP_H
 
 #include <linux/types.h>
+#include <linux/hid.h>
 #include <linux/kref.h>
 #include <net/bluetooth/bluetooth.h>
 #include <net/bluetooth/l2cap.h>
@@ -179,6 +180,9 @@
 
 	/* Used in hidp_output_raw_report() */
 	int output_report_success; /* boolean */
+
+	/* temporary input buffer */
+	u8 input_buf[HID_MAX_BUFFER_SIZE];
 };
 
 /* HIDP init defines */
diff --git a/net/core/dev.c b/net/core/dev.c
index 4ad1b78..b1b0c8d 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -2420,7 +2420,7 @@
  * 2. No high memory really exists on this machine.
  */
 
-static int illegal_highdma(struct net_device *dev, struct sk_buff *skb)
+static int illegal_highdma(const struct net_device *dev, struct sk_buff *skb)
 {
 #ifdef CONFIG_HIGHMEM
 	int i;
@@ -2495,34 +2495,36 @@
 }
 
 static netdev_features_t harmonize_features(struct sk_buff *skb,
-	netdev_features_t features)
+					    const struct net_device *dev,
+					    netdev_features_t features)
 {
 	if (skb->ip_summed != CHECKSUM_NONE &&
 	    !can_checksum_protocol(features, skb_network_protocol(skb))) {
 		features &= ~NETIF_F_ALL_CSUM;
-	} else if (illegal_highdma(skb->dev, skb)) {
+	} else if (illegal_highdma(dev, skb)) {
 		features &= ~NETIF_F_SG;
 	}
 
 	return features;
 }
 
-netdev_features_t netif_skb_features(struct sk_buff *skb)
+netdev_features_t netif_skb_dev_features(struct sk_buff *skb,
+					 const struct net_device *dev)
 {
 	__be16 protocol = skb->protocol;
-	netdev_features_t features = skb->dev->features;
+	netdev_features_t features = dev->features;
 
-	if (skb_shinfo(skb)->gso_segs > skb->dev->gso_max_segs)
+	if (skb_shinfo(skb)->gso_segs > dev->gso_max_segs)
 		features &= ~NETIF_F_GSO_MASK;
 
 	if (protocol == htons(ETH_P_8021Q) || protocol == htons(ETH_P_8021AD)) {
 		struct vlan_ethhdr *veh = (struct vlan_ethhdr *)skb->data;
 		protocol = veh->h_vlan_encapsulated_proto;
 	} else if (!vlan_tx_tag_present(skb)) {
-		return harmonize_features(skb, features);
+		return harmonize_features(skb, dev, features);
 	}
 
-	features &= (skb->dev->vlan_features | NETIF_F_HW_VLAN_CTAG_TX |
+	features &= (dev->vlan_features | NETIF_F_HW_VLAN_CTAG_TX |
 					       NETIF_F_HW_VLAN_STAG_TX);
 
 	if (protocol == htons(ETH_P_8021Q) || protocol == htons(ETH_P_8021AD))
@@ -2530,9 +2532,9 @@
 				NETIF_F_GEN_CSUM | NETIF_F_HW_VLAN_CTAG_TX |
 				NETIF_F_HW_VLAN_STAG_TX;
 
-	return harmonize_features(skb, features);
+	return harmonize_features(skb, dev, features);
 }
-EXPORT_SYMBOL(netif_skb_features);
+EXPORT_SYMBOL(netif_skb_dev_features);
 
 int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
 			struct netdev_queue *txq)
diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c
index 87577d4..e29e810 100644
--- a/net/core/flow_dissector.c
+++ b/net/core/flow_dissector.c
@@ -323,17 +323,6 @@
 	return poff;
 }
 
-static inline u16 dev_cap_txqueue(struct net_device *dev, u16 queue_index)
-{
-	if (unlikely(queue_index >= dev->real_num_tx_queues)) {
-		net_warn_ratelimited("%s selects TX queue %d, but real number of TX queues is %d\n",
-				     dev->name, queue_index,
-				     dev->real_num_tx_queues);
-		return 0;
-	}
-	return queue_index;
-}
-
 static inline int get_xps_queue(struct net_device *dev, struct sk_buff *skb)
 {
 #ifdef CONFIG_XPS
@@ -372,7 +361,7 @@
 #endif
 }
 
-u16 __netdev_pick_tx(struct net_device *dev, struct sk_buff *skb)
+static u16 __netdev_pick_tx(struct net_device *dev, struct sk_buff *skb)
 {
 	struct sock *sk = skb->sk;
 	int queue_index = sk_tx_queue_get(sk);
@@ -392,7 +381,6 @@
 
 	return queue_index;
 }
-EXPORT_SYMBOL(__netdev_pick_tx);
 
 struct netdev_queue *netdev_pick_tx(struct net_device *dev,
 				    struct sk_buff *skb,
@@ -403,13 +391,13 @@
 	if (dev->real_num_tx_queues != 1) {
 		const struct net_device_ops *ops = dev->netdev_ops;
 		if (ops->ndo_select_queue)
-			queue_index = ops->ndo_select_queue(dev, skb,
-							    accel_priv);
+			queue_index = ops->ndo_select_queue(dev, skb, accel_priv,
+							    __netdev_pick_tx);
 		else
 			queue_index = __netdev_pick_tx(dev, skb);
 
 		if (!accel_priv)
-			queue_index = dev_cap_txqueue(dev, queue_index);
+			queue_index = netdev_cap_txqueue(dev, queue_index);
 	}
 
 	skb_set_queue_mapping(skb, queue_index);
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 048dc8d..1a0dac2 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -1963,16 +1963,21 @@
 
 		dev->ifindex = ifm->ifi_index;
 
-		if (ops->newlink)
+		if (ops->newlink) {
 			err = ops->newlink(net, dev, tb, data);
-		else
+			/* Drivers should call free_netdev() in ->destructor
+			 * and unregister it on failure so that device could be
+			 * finally freed in rtnl_unlock.
+			 */
+			if (err < 0)
+				goto out;
+		} else {
 			err = register_netdevice(dev);
-
-		if (err < 0) {
-			free_netdev(dev);
-			goto out;
+			if (err < 0) {
+				free_netdev(dev);
+				goto out;
+			}
 		}
-
 		err = rtnl_configure_link(dev, ifm);
 		if (err < 0)
 			unregister_netdevice(dev);
diff --git a/net/dccp/ccids/lib/tfrc.c b/net/dccp/ccids/lib/tfrc.c
index c073b81..62b5828 100644
--- a/net/dccp/ccids/lib/tfrc.c
+++ b/net/dccp/ccids/lib/tfrc.c
@@ -8,7 +8,7 @@
 #include "tfrc.h"
 
 #ifdef CONFIG_IP_DCCP_TFRC_DEBUG
-static bool tfrc_debug;
+bool tfrc_debug;
 module_param(tfrc_debug, bool, 0644);
 MODULE_PARM_DESC(tfrc_debug, "Enable TFRC debug messages");
 #endif
diff --git a/net/dccp/ccids/lib/tfrc.h b/net/dccp/ccids/lib/tfrc.h
index a3d8f7c..40ee7d6 100644
--- a/net/dccp/ccids/lib/tfrc.h
+++ b/net/dccp/ccids/lib/tfrc.h
@@ -21,6 +21,7 @@
 #include "packet_history.h"
 
 #ifdef CONFIG_IP_DCCP_TFRC_DEBUG
+extern bool tfrc_debug;
 #define tfrc_pr_debug(format, a...)	DCCP_PR_DEBUG(tfrc_debug, format, ##a)
 #else
 #define tfrc_pr_debug(format, a...)
diff --git a/net/ipv4/ip_forward.c b/net/ipv4/ip_forward.c
index e9f1217..f3869c1 100644
--- a/net/ipv4/ip_forward.c
+++ b/net/ipv4/ip_forward.c
@@ -39,6 +39,71 @@
 #include <net/route.h>
 #include <net/xfrm.h>
 
+static bool ip_may_fragment(const struct sk_buff *skb)
+{
+	return unlikely((ip_hdr(skb)->frag_off & htons(IP_DF)) == 0) ||
+	       !skb->local_df;
+}
+
+static bool ip_exceeds_mtu(const struct sk_buff *skb, unsigned int mtu)
+{
+	if (skb->len <= mtu || skb->local_df)
+		return false;
+
+	if (skb_is_gso(skb) && skb_gso_network_seglen(skb) <= mtu)
+		return false;
+
+	return true;
+}
+
+static bool ip_gso_exceeds_dst_mtu(const struct sk_buff *skb)
+{
+	unsigned int mtu;
+
+	if (skb->local_df || !skb_is_gso(skb))
+		return false;
+
+	mtu = ip_dst_mtu_maybe_forward(skb_dst(skb), true);
+
+	/* if seglen > mtu, do software segmentation for IP fragmentation on
+	 * output.  DF bit cannot be set since ip_forward would have sent
+	 * icmp error.
+	 */
+	return skb_gso_network_seglen(skb) > mtu;
+}
+
+/* called if GSO skb needs to be fragmented on forward */
+static int ip_forward_finish_gso(struct sk_buff *skb)
+{
+	struct dst_entry *dst = skb_dst(skb);
+	netdev_features_t features;
+	struct sk_buff *segs;
+	int ret = 0;
+
+	features = netif_skb_dev_features(skb, dst->dev);
+	segs = skb_gso_segment(skb, features & ~NETIF_F_GSO_MASK);
+	if (IS_ERR(segs)) {
+		kfree_skb(skb);
+		return -ENOMEM;
+	}
+
+	consume_skb(skb);
+
+	do {
+		struct sk_buff *nskb = segs->next;
+		int err;
+
+		segs->next = NULL;
+		err = dst_output(segs);
+
+		if (err && ret == 0)
+			ret = err;
+		segs = nskb;
+	} while (segs);
+
+	return ret;
+}
+
 static int ip_forward_finish(struct sk_buff *skb)
 {
 	struct ip_options *opt	= &(IPCB(skb)->opt);
@@ -49,6 +114,9 @@
 	if (unlikely(opt->optlen))
 		ip_forward_options(skb);
 
+	if (ip_gso_exceeds_dst_mtu(skb))
+		return ip_forward_finish_gso(skb);
+
 	return dst_output(skb);
 }
 
@@ -91,8 +159,7 @@
 
 	IPCB(skb)->flags |= IPSKB_FORWARDED;
 	mtu = ip_dst_mtu_maybe_forward(&rt->dst, true);
-	if (unlikely(skb->len > mtu && !skb_is_gso(skb) &&
-		     (ip_hdr(skb)->frag_off & htons(IP_DF))) && !skb->local_df) {
+	if (!ip_may_fragment(skb) && ip_exceeds_mtu(skb, mtu)) {
 		IP_INC_STATS(dev_net(rt->dst.dev), IPSTATS_MIB_FRAGFAILS);
 		icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED,
 			  htonl(mtu));
diff --git a/net/ipv4/ipconfig.c b/net/ipv4/ipconfig.c
index efa1138..b3e86ea 100644
--- a/net/ipv4/ipconfig.c
+++ b/net/ipv4/ipconfig.c
@@ -273,7 +273,7 @@
 
 		msleep(1);
 
-		if time_before(jiffies, next_msg)
+		if (time_before(jiffies, next_msg))
 			continue;
 
 		elapsed = jiffies_to_msecs(jiffies - start);
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 25071b4..4c011ec 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -1597,6 +1597,7 @@
 	rth->rt_gateway	= 0;
 	rth->rt_uses_gateway = 0;
 	INIT_LIST_HEAD(&rth->rt_uncached);
+	RT_CACHE_STAT_INC(in_slow_tot);
 
 	rth->dst.input = ip_forward;
 	rth->dst.output = ip_output;
@@ -1695,10 +1696,11 @@
 	fl4.daddr = daddr;
 	fl4.saddr = saddr;
 	err = fib_lookup(net, &fl4, &res);
-	if (err != 0)
+	if (err != 0) {
+		if (!IN_DEV_FORWARD(in_dev))
+			err = -EHOSTUNREACH;
 		goto no_route;
-
-	RT_CACHE_STAT_INC(in_slow_tot);
+	}
 
 	if (res.type == RTN_BROADCAST)
 		goto brd_input;
@@ -1712,8 +1714,10 @@
 		goto local_input;
 	}
 
-	if (!IN_DEV_FORWARD(in_dev))
+	if (!IN_DEV_FORWARD(in_dev)) {
+		err = -EHOSTUNREACH;
 		goto no_route;
+	}
 	if (res.type != RTN_UNICAST)
 		goto martian_destination;
 
@@ -1768,6 +1772,7 @@
 	rth->rt_gateway	= 0;
 	rth->rt_uses_gateway = 0;
 	INIT_LIST_HEAD(&rth->rt_uncached);
+	RT_CACHE_STAT_INC(in_slow_tot);
 	if (res.type == RTN_UNREACHABLE) {
 		rth->dst.input= ip_error;
 		rth->dst.error= -err;
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index ad23569..fdbfeca 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -2783,6 +2783,8 @@
 	ipv6_addr_set(&addr,  htonl(0xFE800000), 0, 0, 0);
 	if (!ipv6_generate_eui64(addr.s6_addr + 8, dev))
 		addrconf_add_linklocal(idev, &addr);
+	else
+		addrconf_prefix_route(&addr, 64, dev, 0, 0);
 }
 #endif
 
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index ef02b26..070a2fa 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -342,6 +342,20 @@
 	return mtu;
 }
 
+static bool ip6_pkt_too_big(const struct sk_buff *skb, unsigned int mtu)
+{
+	if (skb->len <= mtu || skb->local_df)
+		return false;
+
+	if (IP6CB(skb)->frag_max_size && IP6CB(skb)->frag_max_size > mtu)
+		return true;
+
+	if (skb_is_gso(skb) && skb_gso_network_seglen(skb) <= mtu)
+		return false;
+
+	return true;
+}
+
 int ip6_forward(struct sk_buff *skb)
 {
 	struct dst_entry *dst = skb_dst(skb);
@@ -466,8 +480,7 @@
 	if (mtu < IPV6_MIN_MTU)
 		mtu = IPV6_MIN_MTU;
 
-	if ((!skb->local_df && skb->len > mtu && !skb_is_gso(skb)) ||
-	    (IP6CB(skb)->frag_max_size && IP6CB(skb)->frag_max_size > mtu)) {
+	if (ip6_pkt_too_big(skb, mtu)) {
 		/* Again, force OUTPUT device used as source address */
 		skb->dev = dst->dev;
 		icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index d6d1f1d..ce1c443 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -1057,7 +1057,8 @@
 
 static u16 ieee80211_netdev_select_queue(struct net_device *dev,
 					 struct sk_buff *skb,
-					 void *accel_priv)
+					 void *accel_priv,
+					 select_queue_fallback_t fallback)
 {
 	return ieee80211_select_queue(IEEE80211_DEV_TO_SUB_IF(dev), skb);
 }
@@ -1075,7 +1076,8 @@
 
 static u16 ieee80211_monitor_select_queue(struct net_device *dev,
 					  struct sk_buff *skb,
-					  void *accel_priv)
+					  void *accel_priv,
+					  select_queue_fallback_t fallback)
 {
 	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 	struct ieee80211_local *local = sdata->local;
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index 6a2bb37..48a6a93 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -308,11 +308,27 @@
 	return po->xmit == packet_direct_xmit;
 }
 
-static u16 packet_pick_tx_queue(struct net_device *dev)
+static u16 __packet_pick_tx_queue(struct net_device *dev, struct sk_buff *skb)
 {
 	return (u16) raw_smp_processor_id() % dev->real_num_tx_queues;
 }
 
+static void packet_pick_tx_queue(struct net_device *dev, struct sk_buff *skb)
+{
+	const struct net_device_ops *ops = dev->netdev_ops;
+	u16 queue_index;
+
+	if (ops->ndo_select_queue) {
+		queue_index = ops->ndo_select_queue(dev, skb, NULL,
+						    __packet_pick_tx_queue);
+		queue_index = netdev_cap_txqueue(dev, queue_index);
+	} else {
+		queue_index = __packet_pick_tx_queue(dev, skb);
+	}
+
+	skb_set_queue_mapping(skb, queue_index);
+}
+
 /* register_prot_hook must be invoked with the po->bind_lock held,
  * or from a context in which asynchronous accesses to the packet
  * socket is not possible (packet_create()).
@@ -2285,7 +2301,8 @@
 			}
 		}
 
-		skb_set_queue_mapping(skb, packet_pick_tx_queue(dev));
+		packet_pick_tx_queue(dev, skb);
+
 		skb->destructor = tpacket_destruct_skb;
 		__packet_set_status(po, ph, TP_STATUS_SENDING);
 		packet_inc_pending(&po->tx_ring);
@@ -2499,7 +2516,8 @@
 	skb->dev = dev;
 	skb->priority = sk->sk_priority;
 	skb->mark = sk->sk_mark;
-	skb_set_queue_mapping(skb, packet_pick_tx_queue(dev));
+
+	packet_pick_tx_queue(dev, skb);
 
 	if (po->has_vnet_hdr) {
 		if (vnet_hdr.flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) {
@@ -3786,7 +3804,7 @@
 		 */
 			if (!tx_ring)
 				init_prb_bdqc(po, rb, pg_vec, req_u, tx_ring);
-				break;
+			break;
 		default:
 			break;
 		}
diff --git a/net/sched/sch_pie.c b/net/sched/sch_pie.c
index a255d02..fefeeb7 100644
--- a/net/sched/sch_pie.c
+++ b/net/sched/sch_pie.c
@@ -15,6 +15,11 @@
  *
  * ECN support is added by Naeem Khademi <naeemk@ifi.uio.no>
  * University of Oslo, Norway.
+ *
+ * References:
+ * IETF draft submission: http://tools.ietf.org/html/draft-pan-aqm-pie-00
+ * IEEE  Conference on High Performance Switching and Routing 2013 :
+ * "PIE: A * Lightweight Control Scheme to Address the Bufferbloat Problem"
  */
 
 #include <linux/module.h>
@@ -36,7 +41,7 @@
 	psched_time_t target;	/* user specified target delay in pschedtime */
 	u32 tupdate;		/* timer frequency (in jiffies) */
 	u32 limit;		/* number of packets that can be enqueued */
-	u32 alpha;		/* alpha and beta are between -4 and 4 */
+	u32 alpha;		/* alpha and beta are between 0 and 32 */
 	u32 beta;		/* and are used for shift relative to 1 */
 	bool ecn;		/* true if ecn is enabled */
 	bool bytemode;		/* to scale drop early prob based on pkt size */
@@ -326,10 +331,16 @@
 	if (qdelay == 0 && qlen != 0)
 		update_prob = false;
 
-	/* Add ranges for alpha and beta, more aggressive for high dropping
-	 * mode and gentle steps for light dropping mode
-	 * In light dropping mode, take gentle steps; in medium dropping mode,
-	 * take medium steps; in high dropping mode, take big steps.
+	/* In the algorithm, alpha and beta are between 0 and 2 with typical
+	 * value for alpha as 0.125. In this implementation, we use values 0-32
+	 * passed from user space to represent this. Also, alpha and beta have
+	 * unit of HZ and need to be scaled before they can used to update
+	 * probability. alpha/beta are updated locally below by 1) scaling them
+	 * appropriately 2) scaling down by 16 to come to 0-2 range.
+	 * Please see paper for details.
+	 *
+	 * We scale alpha and beta differently depending on whether we are in
+	 * light, medium or high dropping mode.
 	 */
 	if (q->vars.prob < MAX_PROB / 100) {
 		alpha =
diff --git a/net/sctp/associola.c b/net/sctp/associola.c
index 5ae6092..f558433 100644
--- a/net/sctp/associola.c
+++ b/net/sctp/associola.c
@@ -1367,44 +1367,35 @@
 	return false;
 }
 
-/* Increase asoc's rwnd by len and send any window update SACK if needed. */
-void sctp_assoc_rwnd_increase(struct sctp_association *asoc, unsigned int len)
+/* Update asoc's rwnd for the approximated state in the buffer,
+ * and check whether SACK needs to be sent.
+ */
+void sctp_assoc_rwnd_update(struct sctp_association *asoc, bool update_peer)
 {
+	int rx_count;
 	struct sctp_chunk *sack;
 	struct timer_list *timer;
 
-	if (asoc->rwnd_over) {
-		if (asoc->rwnd_over >= len) {
-			asoc->rwnd_over -= len;
-		} else {
-			asoc->rwnd += (len - asoc->rwnd_over);
-			asoc->rwnd_over = 0;
-		}
-	} else {
-		asoc->rwnd += len;
-	}
+	if (asoc->ep->rcvbuf_policy)
+		rx_count = atomic_read(&asoc->rmem_alloc);
+	else
+		rx_count = atomic_read(&asoc->base.sk->sk_rmem_alloc);
 
-	/* If we had window pressure, start recovering it
-	 * once our rwnd had reached the accumulated pressure
-	 * threshold.  The idea is to recover slowly, but up
-	 * to the initial advertised window.
-	 */
-	if (asoc->rwnd_press && asoc->rwnd >= asoc->rwnd_press) {
-		int change = min(asoc->pathmtu, asoc->rwnd_press);
-		asoc->rwnd += change;
-		asoc->rwnd_press -= change;
-	}
+	if ((asoc->base.sk->sk_rcvbuf - rx_count) > 0)
+		asoc->rwnd = (asoc->base.sk->sk_rcvbuf - rx_count) >> 1;
+	else
+		asoc->rwnd = 0;
 
-	pr_debug("%s: asoc:%p rwnd increased by %d to (%u, %u) - %u\n",
-		 __func__, asoc, len, asoc->rwnd, asoc->rwnd_over,
-		 asoc->a_rwnd);
+	pr_debug("%s: asoc:%p rwnd=%u, rx_count=%d, sk_rcvbuf=%d\n",
+		 __func__, asoc, asoc->rwnd, rx_count,
+		 asoc->base.sk->sk_rcvbuf);
 
 	/* Send a window update SACK if the rwnd has increased by at least the
 	 * minimum of the association's PMTU and half of the receive buffer.
 	 * The algorithm used is similar to the one described in
 	 * Section 4.2.3.3 of RFC 1122.
 	 */
-	if (sctp_peer_needs_update(asoc)) {
+	if (update_peer && sctp_peer_needs_update(asoc)) {
 		asoc->a_rwnd = asoc->rwnd;
 
 		pr_debug("%s: sending window update SACK- asoc:%p rwnd:%u "
@@ -1426,45 +1417,6 @@
 	}
 }
 
-/* Decrease asoc's rwnd by len. */
-void sctp_assoc_rwnd_decrease(struct sctp_association *asoc, unsigned int len)
-{
-	int rx_count;
-	int over = 0;
-
-	if (unlikely(!asoc->rwnd || asoc->rwnd_over))
-		pr_debug("%s: association:%p has asoc->rwnd:%u, "
-			 "asoc->rwnd_over:%u!\n", __func__, asoc,
-			 asoc->rwnd, asoc->rwnd_over);
-
-	if (asoc->ep->rcvbuf_policy)
-		rx_count = atomic_read(&asoc->rmem_alloc);
-	else
-		rx_count = atomic_read(&asoc->base.sk->sk_rmem_alloc);
-
-	/* If we've reached or overflowed our receive buffer, announce
-	 * a 0 rwnd if rwnd would still be positive.  Store the
-	 * the potential pressure overflow so that the window can be restored
-	 * back to original value.
-	 */
-	if (rx_count >= asoc->base.sk->sk_rcvbuf)
-		over = 1;
-
-	if (asoc->rwnd >= len) {
-		asoc->rwnd -= len;
-		if (over) {
-			asoc->rwnd_press += asoc->rwnd;
-			asoc->rwnd = 0;
-		}
-	} else {
-		asoc->rwnd_over = len - asoc->rwnd;
-		asoc->rwnd = 0;
-	}
-
-	pr_debug("%s: asoc:%p rwnd decreased by %d to (%u, %u, %u)\n",
-		 __func__, asoc, len, asoc->rwnd, asoc->rwnd_over,
-		 asoc->rwnd_press);
-}
 
 /* Build the bind address list for the association based on info from the
  * local endpoint and the remote peer.
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
index 483dcd7..591b44d 100644
--- a/net/sctp/sm_statefuns.c
+++ b/net/sctp/sm_statefuns.c
@@ -6176,7 +6176,7 @@
 	 * PMTU.  In cases, such as loopback, this might be a rather
 	 * large spill over.
 	 */
-	if ((!chunk->data_accepted) && (!asoc->rwnd || asoc->rwnd_over ||
+	if ((!chunk->data_accepted) && (!asoc->rwnd ||
 	    (datalen > asoc->rwnd + asoc->frag_point))) {
 
 		/* If this is the next TSN, consider reneging to make
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 9e91d6e..981aaf8 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -64,6 +64,7 @@
 #include <linux/crypto.h>
 #include <linux/slab.h>
 #include <linux/file.h>
+#include <linux/compat.h>
 
 #include <net/ip.h>
 #include <net/icmp.h>
@@ -1368,11 +1369,19 @@
 /*
  * New (hopefully final) interface for the API.
  * We use the sctp_getaddrs_old structure so that use-space library
- * can avoid any unnecessary allocations.   The only defferent part
+ * can avoid any unnecessary allocations. The only different part
  * is that we store the actual length of the address buffer into the
- * addrs_num structure member.  That way we can re-use the existing
+ * addrs_num structure member. That way we can re-use the existing
  * code.
  */
+#ifdef CONFIG_COMPAT
+struct compat_sctp_getaddrs_old {
+	sctp_assoc_t	assoc_id;
+	s32		addr_num;
+	compat_uptr_t	addrs;		/* struct sockaddr * */
+};
+#endif
+
 static int sctp_getsockopt_connectx3(struct sock *sk, int len,
 				     char __user *optval,
 				     int __user *optlen)
@@ -1381,16 +1390,30 @@
 	sctp_assoc_t assoc_id = 0;
 	int err = 0;
 
-	if (len < sizeof(param))
-		return -EINVAL;
+#ifdef CONFIG_COMPAT
+	if (is_compat_task()) {
+		struct compat_sctp_getaddrs_old param32;
 
-	if (copy_from_user(&param, optval, sizeof(param)))
-		return -EFAULT;
+		if (len < sizeof(param32))
+			return -EINVAL;
+		if (copy_from_user(&param32, optval, sizeof(param32)))
+			return -EFAULT;
 
-	err = __sctp_setsockopt_connectx(sk,
-			(struct sockaddr __user *)param.addrs,
-			param.addr_num, &assoc_id);
+		param.assoc_id = param32.assoc_id;
+		param.addr_num = param32.addr_num;
+		param.addrs = compat_ptr(param32.addrs);
+	} else
+#endif
+	{
+		if (len < sizeof(param))
+			return -EINVAL;
+		if (copy_from_user(&param, optval, sizeof(param)))
+			return -EFAULT;
+	}
 
+	err = __sctp_setsockopt_connectx(sk, (struct sockaddr __user *)
+					 param.addrs, param.addr_num,
+					 &assoc_id);
 	if (err == 0 || err == -EINPROGRESS) {
 		if (copy_to_user(optval, &assoc_id, sizeof(assoc_id)))
 			return -EFAULT;
@@ -2092,12 +2115,6 @@
 		sctp_skb_pull(skb, copied);
 		skb_queue_head(&sk->sk_receive_queue, skb);
 
-		/* When only partial message is copied to the user, increase
-		 * rwnd by that amount. If all the data in the skb is read,
-		 * rwnd is updated when the event is freed.
-		 */
-		if (!sctp_ulpevent_is_notification(event))
-			sctp_assoc_rwnd_increase(event->asoc, copied);
 		goto out;
 	} else if ((event->msg_flags & MSG_NOTIFICATION) ||
 		   (event->msg_flags & MSG_EOR))
diff --git a/net/sctp/sysctl.c b/net/sctp/sysctl.c
index 7135e61..35c8923 100644
--- a/net/sctp/sysctl.c
+++ b/net/sctp/sysctl.c
@@ -151,6 +151,7 @@
 	},
 	{
 		.procname	= "cookie_hmac_alg",
+		.data		= &init_net.sctp.sctp_hmac_alg,
 		.maxlen		= 8,
 		.mode		= 0644,
 		.proc_handler	= proc_sctp_do_hmac_alg,
@@ -401,15 +402,18 @@
 
 int sctp_sysctl_net_register(struct net *net)
 {
-	struct ctl_table *table;
-	int i;
+	struct ctl_table *table = sctp_net_table;
 
-	table = kmemdup(sctp_net_table, sizeof(sctp_net_table), GFP_KERNEL);
-	if (!table)
-		return -ENOMEM;
+	if (!net_eq(net, &init_net)) {
+		int i;
 
-	for (i = 0; table[i].data; i++)
-		table[i].data += (char *)(&net->sctp) - (char *)&init_net.sctp;
+		table = kmemdup(sctp_net_table, sizeof(sctp_net_table), GFP_KERNEL);
+		if (!table)
+			return -ENOMEM;
+
+		for (i = 0; table[i].data; i++)
+			table[i].data += (char *)(&net->sctp) - (char *)&init_net.sctp;
+	}
 
 	net->sctp.sysctl_header = register_net_sysctl(net, "net/sctp", table);
 	return 0;
diff --git a/net/sctp/ulpevent.c b/net/sctp/ulpevent.c
index 85c6465..8d198ae 100644
--- a/net/sctp/ulpevent.c
+++ b/net/sctp/ulpevent.c
@@ -989,7 +989,7 @@
 	skb = sctp_event2skb(event);
 	/* Set the owner and charge rwnd for bytes received.  */
 	sctp_ulpevent_set_owner(event, asoc);
-	sctp_assoc_rwnd_decrease(asoc, skb_headlen(skb));
+	sctp_assoc_rwnd_update(asoc, false);
 
 	if (!skb->data_len)
 		return;
@@ -1011,6 +1011,7 @@
 {
 	struct sk_buff *skb, *frag;
 	unsigned int	len;
+	struct sctp_association *asoc;
 
 	/* Current stack structures assume that the rcv buffer is
 	 * per socket.   For UDP style sockets this is not true as
@@ -1035,8 +1036,11 @@
 	}
 
 done:
-	sctp_assoc_rwnd_increase(event->asoc, len);
+	asoc = event->asoc;
+	sctp_association_hold(asoc);
 	sctp_ulpevent_release_owner(event);
+	sctp_assoc_rwnd_update(asoc, true);
+	sctp_association_put(asoc);
 }
 
 static void sctp_ulpevent_release_frag_data(struct sctp_ulpevent *event)
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
index 6c0513a..36e431e 100644
--- a/net/sunrpc/auth_gss/auth_gss.c
+++ b/net/sunrpc/auth_gss/auth_gss.c
@@ -108,6 +108,7 @@
 static DEFINE_SPINLOCK(pipe_version_lock);
 static struct rpc_wait_queue pipe_version_rpc_waitqueue;
 static DECLARE_WAIT_QUEUE_HEAD(pipe_version_waitqueue);
+static void gss_put_auth(struct gss_auth *gss_auth);
 
 static void gss_free_ctx(struct gss_cl_ctx *);
 static const struct rpc_pipe_ops gss_upcall_ops_v0;
@@ -320,6 +321,7 @@
 	if (gss_msg->ctx != NULL)
 		gss_put_ctx(gss_msg->ctx);
 	rpc_destroy_wait_queue(&gss_msg->rpc_waitqueue);
+	gss_put_auth(gss_msg->auth);
 	kfree(gss_msg);
 }
 
@@ -498,9 +500,12 @@
 	default:
 		err = gss_encode_v1_msg(gss_msg, service_name, gss_auth->target_name);
 		if (err)
-			goto err_free_msg;
+			goto err_put_pipe_version;
 	};
+	kref_get(&gss_auth->kref);
 	return gss_msg;
+err_put_pipe_version:
+	put_pipe_version(gss_auth->net);
 err_free_msg:
 	kfree(gss_msg);
 err:
@@ -991,6 +996,8 @@
 	gss_auth->service = gss_pseudoflavor_to_service(gss_auth->mech, flavor);
 	if (gss_auth->service == 0)
 		goto err_put_mech;
+	if (!gssd_running(gss_auth->net))
+		goto err_put_mech;
 	auth = &gss_auth->rpc_auth;
 	auth->au_cslack = GSS_CRED_SLACK >> 2;
 	auth->au_rslack = GSS_VERF_SLACK >> 2;
@@ -1062,6 +1069,12 @@
 }
 
 static void
+gss_put_auth(struct gss_auth *gss_auth)
+{
+	kref_put(&gss_auth->kref, gss_free_callback);
+}
+
+static void
 gss_destroy(struct rpc_auth *auth)
 {
 	struct gss_auth *gss_auth = container_of(auth,
@@ -1082,7 +1095,7 @@
 	gss_auth->gss_pipe[1] = NULL;
 	rpcauth_destroy_credcache(auth);
 
-	kref_put(&gss_auth->kref, gss_free_callback);
+	gss_put_auth(gss_auth);
 }
 
 /*
@@ -1253,7 +1266,7 @@
 	call_rcu(&cred->cr_rcu, gss_free_cred_callback);
 	if (ctx)
 		gss_put_ctx(ctx);
-	kref_put(&gss_auth->kref, gss_free_callback);
+	gss_put_auth(gss_auth);
 }
 
 static void
diff --git a/net/sunrpc/backchannel_rqst.c b/net/sunrpc/backchannel_rqst.c
index 890a299..e860d4f 100644
--- a/net/sunrpc/backchannel_rqst.c
+++ b/net/sunrpc/backchannel_rqst.c
@@ -64,7 +64,6 @@
 	free_page((unsigned long)xbufp->head[0].iov_base);
 	xbufp = &req->rq_snd_buf;
 	free_page((unsigned long)xbufp->head[0].iov_base);
-	list_del(&req->rq_bc_pa_list);
 	kfree(req);
 }
 
@@ -168,8 +167,10 @@
 	/*
 	 * Memory allocation failed, free the temporary list
 	 */
-	list_for_each_entry_safe(req, tmp, &tmp_list, rq_bc_pa_list)
+	list_for_each_entry_safe(req, tmp, &tmp_list, rq_bc_pa_list) {
+		list_del(&req->rq_bc_pa_list);
 		xprt_free_allocation(req);
+	}
 
 	dprintk("RPC:       setup backchannel transport failed\n");
 	return -ENOMEM;
@@ -198,6 +199,7 @@
 	xprt_dec_alloc_count(xprt, max_reqs);
 	list_for_each_entry_safe(req, tmp, &xprt->bc_pa_list, rq_bc_pa_list) {
 		dprintk("RPC:        req=%p\n", req);
+		list_del(&req->rq_bc_pa_list);
 		xprt_free_allocation(req);
 		if (--max_reqs == 0)
 			break;
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index 817a1e5..0addefc 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -510,6 +510,7 @@
 	struct rpc_rqst *req = task->tk_rqstp;
 	struct rpc_xprt *xprt = req->rq_xprt;
 	struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt);
+	struct sock *sk = transport->inet;
 	int ret = -EAGAIN;
 
 	dprintk("RPC: %5u xmit incomplete (%u left of %u)\n",
@@ -527,7 +528,7 @@
 			 * window size
 			 */
 			set_bit(SOCK_NOSPACE, &transport->sock->flags);
-			transport->inet->sk_write_pending++;
+			sk->sk_write_pending++;
 			/* ...and wait for more buffer space */
 			xprt_wait_for_buffer_space(task, xs_nospace_callback);
 		}
@@ -537,6 +538,9 @@
 	}
 
 	spin_unlock_bh(&xprt->transport_lock);
+
+	/* Race breaker in case memory is freed before above code is called */
+	sk->sk_write_space(sk);
 	return ret;
 }
 
diff --git a/net/tipc/core.h b/net/tipc/core.h
index 1ff477b..5569d96 100644
--- a/net/tipc/core.h
+++ b/net/tipc/core.h
@@ -192,6 +192,7 @@
 
 struct tipc_skb_cb {
 	void *handle;
+	bool deferred;
 };
 
 #define TIPC_SKB_CB(__skb) ((struct tipc_skb_cb *)&((__skb)->cb[0]))
diff --git a/net/tipc/link.c b/net/tipc/link.c
index d4b5de4..da6018b 100644
--- a/net/tipc/link.c
+++ b/net/tipc/link.c
@@ -1391,6 +1391,12 @@
 	u32 hdr_size;
 	u32 min_hdr_size;
 
+	/* If this packet comes from the defer queue, the skb has already
+	 * been validated
+	 */
+	if (unlikely(TIPC_SKB_CB(buf)->deferred))
+		return 1;
+
 	if (unlikely(buf->len < MIN_H_SIZE))
 		return 0;
 
@@ -1703,6 +1709,7 @@
 				&l_ptr->newest_deferred_in, buf)) {
 		l_ptr->deferred_inqueue_sz++;
 		l_ptr->stats.deferred_recv++;
+		TIPC_SKB_CB(buf)->deferred = true;
 		if ((l_ptr->deferred_inqueue_sz % 16) == 1)
 			tipc_link_send_proto_msg(l_ptr, STATE_MSG, 0, 0, 0, 0, 0);
 	} else
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index 49392ec..79c059e 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -152,6 +152,7 @@
 dtc_cpp_flags  = -Wp,-MD,$(depfile).pre.tmp -nostdinc                    \
 		 -I$(srctree)/arch/$(SRCARCH)/boot/dts                   \
 		 -I$(srctree)/arch/$(SRCARCH)/boot/dts/include           \
+		 -I$(srctree)/drivers/of/testcase-data                   \
 		 -undef -D__DTS__
 
 # Finds the multi-part object the current object will be linked into
diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c
index c0f4988..9c5cdc2ca 100644
--- a/security/selinux/ss/policydb.c
+++ b/security/selinux/ss/policydb.c
@@ -3338,10 +3338,10 @@
 	if (rc)
 		return rc;
 
-	buf[0] = ft->stype;
-	buf[1] = ft->ttype;
-	buf[2] = ft->tclass;
-	buf[3] = otype->otype;
+	buf[0] = cpu_to_le32(ft->stype);
+	buf[1] = cpu_to_le32(ft->ttype);
+	buf[2] = cpu_to_le32(ft->tclass);
+	buf[3] = cpu_to_le32(otype->otype);
 
 	rc = put_entry(buf, sizeof(u32), 4, fp);
 	if (rc)
diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c
index 54d1479..46ecdbb 100644
--- a/sound/pci/hda/patch_ca0132.c
+++ b/sound/pci/hda/patch_ca0132.c
@@ -2662,60 +2662,6 @@
 }
 
 /*
- * PCM stuffs
- */
-static void ca0132_setup_stream(struct hda_codec *codec, hda_nid_t nid,
-				 u32 stream_tag,
-				 int channel_id, int format)
-{
-	unsigned int oldval, newval;
-
-	if (!nid)
-		return;
-
-	snd_printdd(
-		   "ca0132_setup_stream: NID=0x%x, stream=0x%x, "
-		   "channel=%d, format=0x%x\n",
-		   nid, stream_tag, channel_id, format);
-
-	/* update the format-id if changed */
-	oldval = snd_hda_codec_read(codec, nid, 0,
-				    AC_VERB_GET_STREAM_FORMAT,
-				    0);
-	if (oldval != format) {
-		msleep(20);
-		snd_hda_codec_write(codec, nid, 0,
-				    AC_VERB_SET_STREAM_FORMAT,
-				    format);
-	}
-
-	oldval = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONV, 0);
-	newval = (stream_tag << 4) | channel_id;
-	if (oldval != newval) {
-		snd_hda_codec_write(codec, nid, 0,
-				    AC_VERB_SET_CHANNEL_STREAMID,
-				    newval);
-	}
-}
-
-static void ca0132_cleanup_stream(struct hda_codec *codec, hda_nid_t nid)
-{
-	unsigned int val;
-
-	if (!nid)
-		return;
-
-	snd_printdd(KERN_INFO "ca0132_cleanup_stream: NID=0x%x\n", nid);
-
-	val = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONV, 0);
-	if (!val)
-		return;
-
-	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_STREAM_FORMAT, 0);
-	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CHANNEL_STREAMID, 0);
-}
-
-/*
  * PCM callbacks
  */
 static int ca0132_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
@@ -2726,7 +2672,7 @@
 {
 	struct ca0132_spec *spec = codec->spec;
 
-	ca0132_setup_stream(codec, spec->dacs[0], stream_tag, 0, format);
+	snd_hda_codec_setup_stream(codec, spec->dacs[0], stream_tag, 0, format);
 
 	return 0;
 }
@@ -2745,7 +2691,7 @@
 	if (spec->effects_switch[PLAY_ENHANCEMENT - EFFECT_START_NID])
 		msleep(50);
 
-	ca0132_cleanup_stream(codec, spec->dacs[0]);
+	snd_hda_codec_cleanup_stream(codec, spec->dacs[0]);
 
 	return 0;
 }
@@ -2822,10 +2768,8 @@
 					unsigned int format,
 					struct snd_pcm_substream *substream)
 {
-	struct ca0132_spec *spec = codec->spec;
-
-	ca0132_setup_stream(codec, spec->adcs[substream->number],
-			    stream_tag, 0, format);
+	snd_hda_codec_setup_stream(codec, hinfo->nid,
+				   stream_tag, 0, format);
 
 	return 0;
 }
@@ -2839,7 +2783,7 @@
 	if (spec->dsp_state == DSP_DOWNLOADING)
 		return 0;
 
-	ca0132_cleanup_stream(codec, hinfo->nid);
+	snd_hda_codec_cleanup_stream(codec, hinfo->nid);
 	return 0;
 }
 
@@ -4742,6 +4686,8 @@
 		return err;
 
 	codec->patch_ops = ca0132_patch_ops;
+	codec->pcm_format_first = 1;
+	codec->no_sticky_stream = 1;
 
 	return 0;
 }
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index a9a83b8..ec304f3 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -4308,7 +4308,9 @@
 	SND_PCI_QUIRK(0x1028, 0x0651, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE),
 	SND_PCI_QUIRK(0x1028, 0x0652, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE),
 	SND_PCI_QUIRK(0x1028, 0x0653, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE),
+	SND_PCI_QUIRK(0x1028, 0x0657, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE),
 	SND_PCI_QUIRK(0x1028, 0x0658, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
+	SND_PCI_QUIRK(0x1028, 0x065f, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE),
 	SND_PCI_QUIRK(0x1028, 0x0662, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE),
 	SND_PCI_QUIRK(0x1028, 0x15cc, "Dell X5 Precision", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
 	SND_PCI_QUIRK(0x1028, 0x15cd, "Dell X5 Precision", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
@@ -4317,6 +4319,54 @@
 	SND_PCI_QUIRK(0x103c, 0x1973, "HP Pavilion", ALC269_FIXUP_HP_MUTE_LED_MIC1),
 	SND_PCI_QUIRK(0x103c, 0x1983, "HP Pavilion", ALC269_FIXUP_HP_MUTE_LED_MIC1),
 	SND_PCI_QUIRK(0x103c, 0x218b, "HP", ALC269_FIXUP_LIMIT_INT_MIC_BOOST_MUTE_LED),
+	/* ALC282 */
+	SND_PCI_QUIRK(0x103c, 0x220f, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+	SND_PCI_QUIRK(0x103c, 0x2213, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+	SND_PCI_QUIRK(0x103c, 0x2266, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+	SND_PCI_QUIRK(0x103c, 0x2267, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+	SND_PCI_QUIRK(0x103c, 0x2268, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+	SND_PCI_QUIRK(0x103c, 0x2269, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+	SND_PCI_QUIRK(0x103c, 0x226a, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+	SND_PCI_QUIRK(0x103c, 0x226b, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+	SND_PCI_QUIRK(0x103c, 0x227a, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+	SND_PCI_QUIRK(0x103c, 0x227b, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+	SND_PCI_QUIRK(0x103c, 0x229e, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+	SND_PCI_QUIRK(0x103c, 0x22a0, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+	SND_PCI_QUIRK(0x103c, 0x22b2, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+	SND_PCI_QUIRK(0x103c, 0x22b7, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+	SND_PCI_QUIRK(0x103c, 0x22bf, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+	SND_PCI_QUIRK(0x103c, 0x22c0, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+	SND_PCI_QUIRK(0x103c, 0x22c1, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+	SND_PCI_QUIRK(0x103c, 0x22c2, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+	SND_PCI_QUIRK(0x103c, 0x22cd, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+	SND_PCI_QUIRK(0x103c, 0x22ce, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+	SND_PCI_QUIRK(0x103c, 0x22cf, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+	SND_PCI_QUIRK(0x103c, 0x22d0, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+	/* ALC290 */
+	SND_PCI_QUIRK(0x103c, 0x2260, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+	SND_PCI_QUIRK(0x103c, 0x2261, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+	SND_PCI_QUIRK(0x103c, 0x2262, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+	SND_PCI_QUIRK(0x103c, 0x2263, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+	SND_PCI_QUIRK(0x103c, 0x2264, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+	SND_PCI_QUIRK(0x103c, 0x2265, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+	SND_PCI_QUIRK(0x103c, 0x227d, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+	SND_PCI_QUIRK(0x103c, 0x227e, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+	SND_PCI_QUIRK(0x103c, 0x227f, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+	SND_PCI_QUIRK(0x103c, 0x2280, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+	SND_PCI_QUIRK(0x103c, 0x2281, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+	SND_PCI_QUIRK(0x103c, 0x2282, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+	SND_PCI_QUIRK(0x103c, 0x2289, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+	SND_PCI_QUIRK(0x103c, 0x228a, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+	SND_PCI_QUIRK(0x103c, 0x228b, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+	SND_PCI_QUIRK(0x103c, 0x228c, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+	SND_PCI_QUIRK(0x103c, 0x228d, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+	SND_PCI_QUIRK(0x103c, 0x228e, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+	SND_PCI_QUIRK(0x103c, 0x22c5, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+	SND_PCI_QUIRK(0x103c, 0x22c6, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+	SND_PCI_QUIRK(0x103c, 0x22c7, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+	SND_PCI_QUIRK(0x103c, 0x22c8, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+	SND_PCI_QUIRK(0x103c, 0x22c3, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+	SND_PCI_QUIRK(0x103c, 0x22c4, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
 	SND_PCI_QUIRK_VENDOR(0x103c, "HP", ALC269_FIXUP_HP_MUTE_LED),
 	SND_PCI_QUIRK(0x1043, 0x103f, "ASUS TX300", ALC282_FIXUP_ASUS_TX300),
 	SND_PCI_QUIRK(0x1043, 0x106d, "Asus K53BE", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index 7311bad..3bc29c9 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -83,6 +83,7 @@
 	STAC_DELL_M6_BOTH,
 	STAC_DELL_EQ,
 	STAC_ALIENWARE_M17X,
+	STAC_92HD89XX_HP_FRONT_JACK,
 	STAC_92HD73XX_MODELS
 };
 
@@ -97,6 +98,7 @@
 	STAC_92HD83XXX_HP_LED,
 	STAC_92HD83XXX_HP_INV_LED,
 	STAC_92HD83XXX_HP_MIC_LED,
+	STAC_HP_LED_GPIO10,
 	STAC_92HD83XXX_HEADSET_JACK,
 	STAC_92HD83XXX_HP,
 	STAC_HP_ENVY_BASS,
@@ -1795,6 +1797,12 @@
 	{}
 };
 
+static const struct hda_pintbl stac92hd89xx_hp_front_jack_pin_configs[] = {
+	{ 0x0a, 0x02214030 },
+	{ 0x0b, 0x02A19010 },
+	{}
+};
+
 static void stac92hd73xx_fixup_ref(struct hda_codec *codec,
 				   const struct hda_fixup *fix, int action)
 {
@@ -1913,6 +1921,10 @@
 	[STAC_92HD73XX_NO_JD] = {
 		.type = HDA_FIXUP_FUNC,
 		.v.func = stac92hd73xx_fixup_no_jd,
+	},
+	[STAC_92HD89XX_HP_FRONT_JACK] = {
+		.type = HDA_FIXUP_PINS,
+		.v.pins = stac92hd89xx_hp_front_jack_pin_configs,
 	}
 };
 
@@ -1973,6 +1985,8 @@
 		      "Alienware M17x", STAC_ALIENWARE_M17X),
 	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0490,
 		      "Alienware M17x R3", STAC_DELL_EQ),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x2b17,
+				"unknown HP", STAC_92HD89XX_HP_FRONT_JACK),
 	{} /* terminator */
 };
 
@@ -2117,6 +2131,17 @@
 	}
 }
 
+static void stac92hd83xxx_fixup_hp_led_gpio10(struct hda_codec *codec,
+				   const struct hda_fixup *fix, int action)
+{
+	struct sigmatel_spec *spec = codec->spec;
+
+	if (action == HDA_FIXUP_ACT_PRE_PROBE) {
+		spec->gpio_led = 0x10; /* GPIO4 */
+		spec->default_polarity = 0;
+	}
+}
+
 static void stac92hd83xxx_fixup_headset_jack(struct hda_codec *codec,
 				   const struct hda_fixup *fix, int action)
 {
@@ -2611,6 +2636,12 @@
 		.chained = true,
 		.chain_id = STAC_92HD83XXX_HP,
 	},
+	[STAC_HP_LED_GPIO10] = {
+		.type = HDA_FIXUP_FUNC,
+		.v.func = stac92hd83xxx_fixup_hp_led_gpio10,
+		.chained = true,
+		.chain_id = STAC_92HD83XXX_HP,
+	},
 	[STAC_92HD83XXX_HEADSET_JACK] = {
 		.type = HDA_FIXUP_FUNC,
 		.v.func = stac92hd83xxx_fixup_headset_jack,
@@ -2689,6 +2720,8 @@
 			  "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD),
 	SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1888,
 			  "HP Envy Spectre", STAC_HP_ENVY_BASS),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1899,
+			  "HP Folio 13", STAC_HP_LED_GPIO10),
 	SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x18df,
 			  "HP Folio", STAC_HP_BNB13_EQ),
 	SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x18F8,
diff --git a/sound/soc/blackfin/Kconfig b/sound/soc/blackfin/Kconfig
index 54f74f8..4544d8e 100644
--- a/sound/soc/blackfin/Kconfig
+++ b/sound/soc/blackfin/Kconfig
@@ -11,7 +11,7 @@
 
 config SND_BF5XX_SOC_SSM2602
 	tristate "SoC SSM2602 Audio Codec Add-On Card support"
-	depends on SND_BF5XX_I2S && (SPI_MASTER || I2C)
+	depends on SND_BF5XX_I2S && SND_SOC_I2C_AND_SPI
 	select SND_BF5XX_SOC_I2S if !BF60x
 	select SND_BF6XX_SOC_I2S if BF60x
 	select SND_SOC_SSM2602
@@ -21,10 +21,9 @@
 
 config SND_SOC_BFIN_EVAL_ADAU1701
 	tristate "Support for the EVAL-ADAU1701MINIZ board on Blackfin eval boards"
-	depends on SND_BF5XX_I2S
+	depends on SND_BF5XX_I2S && I2C
 	select SND_BF5XX_SOC_I2S
 	select SND_SOC_ADAU1701
-	select I2C
 	help
 	  Say Y if you want to add support for the Analog Devices EVAL-ADAU1701MINIZ
 	  board connected to one of the Blackfin evaluation boards like the
@@ -45,7 +44,7 @@
 
 config SND_SOC_BFIN_EVAL_ADAV80X
 	tristate "Support for the EVAL-ADAV80X boards on Blackfin eval boards"
-	depends on SND_BF5XX_I2S && (SPI_MASTER || I2C)
+	depends on SND_BF5XX_I2S && SND_SOC_I2C_AND_SPI
 	select SND_BF5XX_SOC_I2S
 	select SND_SOC_ADAV80X
 	help
@@ -58,7 +57,7 @@
 
 config SND_BF5XX_SOC_AD1836
 	tristate "SoC AD1836 Audio support for BF5xx"
-	depends on SND_BF5XX_I2S
+	depends on SND_BF5XX_I2S && SPI_MASTER
 	select SND_BF5XX_SOC_I2S
 	select SND_SOC_AD1836
 	help
@@ -66,7 +65,7 @@
 
 config SND_BF5XX_SOC_AD193X
 	tristate "SoC AD193X Audio support for Blackfin"
-	depends on SND_BF5XX_I2S
+	depends on SND_BF5XX_I2S && SND_SOC_I2C_AND_SPI
 	select SND_BF5XX_SOC_I2S
 	select SND_SOC_AD193X
 	help
diff --git a/sound/soc/codecs/ad1980.c b/sound/soc/codecs/ad1980.c
index 7257a88..34d965a 100644
--- a/sound/soc/codecs/ad1980.c
+++ b/sound/soc/codecs/ad1980.c
@@ -57,8 +57,8 @@
 static const char *ad1980_rec_sel[] = {"Mic", "CD", "NC", "AUX", "Line",
 		"Stereo Mix", "Mono Mix", "Phone"};
 
-static const struct soc_enum ad1980_cap_src =
-	SOC_ENUM_DOUBLE(AC97_REC_SEL, 8, 0, 7, ad1980_rec_sel);
+static SOC_ENUM_DOUBLE_DECL(ad1980_cap_src,
+			    AC97_REC_SEL, 8, 0, ad1980_rec_sel);
 
 static const struct snd_kcontrol_new ad1980_snd_ac97_controls[] = {
 SOC_DOUBLE("Master Playback Volume", AC97_MASTER, 8, 0, 31, 1),
diff --git a/sound/soc/codecs/da732x.c b/sound/soc/codecs/da732x.c
index f295b65..f4d965ebc 100644
--- a/sound/soc/codecs/da732x.c
+++ b/sound/soc/codecs/da732x.c
@@ -1268,11 +1268,23 @@
 	},
 };
 
+static bool da732x_volatile(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case DA732X_REG_HPL_DAC_OFF_CNTL:
+	case DA732X_REG_HPR_DAC_OFF_CNTL:
+		return true;
+	default:
+		return false;
+	}
+}
+
 static const struct regmap_config da732x_regmap = {
 	.reg_bits		= 8,
 	.val_bits		= 8,
 
 	.max_register		= DA732X_MAX_REG,
+	.volatile_reg		= da732x_volatile,
 	.reg_defaults		= da732x_reg_cache,
 	.num_reg_defaults	= ARRAY_SIZE(da732x_reg_cache),
 	.cache_type		= REGCACHE_RBTREE,
diff --git a/sound/soc/codecs/da9055.c b/sound/soc/codecs/da9055.c
index 52b79a4..4228126 100644
--- a/sound/soc/codecs/da9055.c
+++ b/sound/soc/codecs/da9055.c
@@ -1523,8 +1523,15 @@
 	return 0;
 }
 
+/*
+ * DO NOT change the device Ids. The naming is intentionally specific as both
+ * the CODEC and PMIC parts of this chip are instantiated separately as I2C
+ * devices (both have configurable I2C addresses, and are to all intents and
+ * purposes separate). As a result there are specific DA9055 Ids for CODEC
+ * and PMIC, which must be different to operate together.
+ */
 static const struct i2c_device_id da9055_i2c_id[] = {
-	{ "da9055", 0 },
+	{ "da9055-codec", 0 },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, da9055_i2c_id);
@@ -1532,7 +1539,7 @@
 /* I2C codec control layer */
 static struct i2c_driver da9055_i2c_driver = {
 	.driver = {
-		.name = "da9055",
+		.name = "da9055-codec",
 		.owner = THIS_MODULE,
 	},
 	.probe		= da9055_i2c_probe,
diff --git a/sound/soc/codecs/isabelle.c b/sound/soc/codecs/isabelle.c
index 5839048..cb736dd 100644
--- a/sound/soc/codecs/isabelle.c
+++ b/sound/soc/codecs/isabelle.c
@@ -140,13 +140,17 @@
 static const char *isabelle_rx2_texts[] = {"VRX2", "ARX2"};
 
 static const struct soc_enum isabelle_rx1_enum[] = {
-	SOC_ENUM_SINGLE(ISABELLE_VOICE_HPF_CFG_REG, 3, 1, isabelle_rx1_texts),
-	SOC_ENUM_SINGLE(ISABELLE_AUDIO_HPF_CFG_REG, 5, 1, isabelle_rx1_texts),
+	SOC_ENUM_SINGLE(ISABELLE_VOICE_HPF_CFG_REG, 3,
+			ARRAY_SIZE(isabelle_rx1_texts), isabelle_rx1_texts),
+	SOC_ENUM_SINGLE(ISABELLE_AUDIO_HPF_CFG_REG, 5,
+			ARRAY_SIZE(isabelle_rx1_texts), isabelle_rx1_texts),
 };
 
 static const struct soc_enum isabelle_rx2_enum[] = {
-	SOC_ENUM_SINGLE(ISABELLE_VOICE_HPF_CFG_REG, 2, 1, isabelle_rx2_texts),
-	SOC_ENUM_SINGLE(ISABELLE_AUDIO_HPF_CFG_REG, 4, 1, isabelle_rx2_texts),
+	SOC_ENUM_SINGLE(ISABELLE_VOICE_HPF_CFG_REG, 2,
+			ARRAY_SIZE(isabelle_rx2_texts), isabelle_rx2_texts),
+	SOC_ENUM_SINGLE(ISABELLE_AUDIO_HPF_CFG_REG, 4,
+			ARRAY_SIZE(isabelle_rx2_texts), isabelle_rx2_texts),
 };
 
 /* Headset DAC playback switches */
@@ -161,13 +165,17 @@
 static const char *isabelle_vtx_texts[] = {"AMIC2", "DMIC"};
 
 static const struct soc_enum isabelle_atx_enum[] = {
-	SOC_ENUM_SINGLE(ISABELLE_AMIC_CFG_REG, 7, 1, isabelle_atx_texts),
-	SOC_ENUM_SINGLE(ISABELLE_DMIC_CFG_REG, 0, 1, isabelle_atx_texts),
+	SOC_ENUM_SINGLE(ISABELLE_AMIC_CFG_REG, 7,
+			ARRAY_SIZE(isabelle_atx_texts), isabelle_atx_texts),
+	SOC_ENUM_SINGLE(ISABELLE_DMIC_CFG_REG, 0,
+			ARRAY_SIZE(isabelle_atx_texts), isabelle_atx_texts),
 };
 
 static const struct soc_enum isabelle_vtx_enum[] = {
-	SOC_ENUM_SINGLE(ISABELLE_AMIC_CFG_REG, 6, 1, isabelle_vtx_texts),
-	SOC_ENUM_SINGLE(ISABELLE_DMIC_CFG_REG, 0, 1, isabelle_vtx_texts),
+	SOC_ENUM_SINGLE(ISABELLE_AMIC_CFG_REG, 6,
+			ARRAY_SIZE(isabelle_vtx_texts), isabelle_vtx_texts),
+	SOC_ENUM_SINGLE(ISABELLE_DMIC_CFG_REG, 0,
+			ARRAY_SIZE(isabelle_vtx_texts), isabelle_vtx_texts),
 };
 
 static const struct snd_kcontrol_new atx_mux_controls =
@@ -183,17 +191,13 @@
 /* Left analog microphone selection */
 static const char *isabelle_amic2_texts[] = {"Sub Mic", "Aux/FM Right"};
 
-static const struct soc_enum isabelle_amic1_enum[] = {
-	SOC_ENUM_SINGLE(ISABELLE_AMIC_CFG_REG, 5,
-			ARRAY_SIZE(isabelle_amic1_texts),
-			isabelle_amic1_texts),
-};
+static SOC_ENUM_SINGLE_DECL(isabelle_amic1_enum,
+			    ISABELLE_AMIC_CFG_REG, 5,
+			    isabelle_amic1_texts);
 
-static const struct soc_enum isabelle_amic2_enum[] = {
-	SOC_ENUM_SINGLE(ISABELLE_AMIC_CFG_REG, 4,
-			ARRAY_SIZE(isabelle_amic2_texts),
-			isabelle_amic2_texts),
-};
+static SOC_ENUM_SINGLE_DECL(isabelle_amic2_enum,
+			    ISABELLE_AMIC_CFG_REG, 4,
+			    isabelle_amic2_texts);
 
 static const struct snd_kcontrol_new amic1_control =
 	SOC_DAPM_ENUM("Route", isabelle_amic1_enum);
@@ -206,16 +210,20 @@
 static const char *isabelle_st_voice_texts[] = {"VTX1", "VTX2"};
 
 static const struct soc_enum isabelle_st_audio_enum[] = {
-	SOC_ENUM_SINGLE(ISABELLE_ATX_STPGA1_CFG_REG, 7, 1,
+	SOC_ENUM_SINGLE(ISABELLE_ATX_STPGA1_CFG_REG, 7,
+			ARRAY_SIZE(isabelle_st_audio_texts),
 			isabelle_st_audio_texts),
-	SOC_ENUM_SINGLE(ISABELLE_ATX_STPGA2_CFG_REG, 7, 1,
+	SOC_ENUM_SINGLE(ISABELLE_ATX_STPGA2_CFG_REG, 7,
+			ARRAY_SIZE(isabelle_st_audio_texts),
 			isabelle_st_audio_texts),
 };
 
 static const struct soc_enum isabelle_st_voice_enum[] = {
-	SOC_ENUM_SINGLE(ISABELLE_VTX_STPGA1_CFG_REG, 7, 1,
+	SOC_ENUM_SINGLE(ISABELLE_VTX_STPGA1_CFG_REG, 7,
+			ARRAY_SIZE(isabelle_st_voice_texts),
 			isabelle_st_voice_texts),
-	SOC_ENUM_SINGLE(ISABELLE_VTX2_STPGA2_CFG_REG, 7, 1,
+	SOC_ENUM_SINGLE(ISABELLE_VTX2_STPGA2_CFG_REG, 7,
+			ARRAY_SIZE(isabelle_st_voice_texts),
 			isabelle_st_voice_texts),
 };
 
diff --git a/sound/soc/codecs/max98090.c b/sound/soc/codecs/max98090.c
index 51f9b3d..9f714ea 100644
--- a/sound/soc/codecs/max98090.c
+++ b/sound/soc/codecs/max98090.c
@@ -336,6 +336,7 @@
 	case M98090_REG_RECORD_TDM_SLOT:
 	case M98090_REG_SAMPLE_RATE:
 	case M98090_REG_DMIC34_BIQUAD_BASE ... M98090_REG_DMIC34_BIQUAD_BASE + 0x0E:
+	case M98090_REG_REVISION_ID:
 		return true;
 	default:
 		return false;
@@ -1769,16 +1770,6 @@
 
 	switch (level) {
 	case SND_SOC_BIAS_ON:
-		if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
-			ret = regcache_sync(max98090->regmap);
-
-			if (ret != 0) {
-				dev_err(codec->dev,
-					"Failed to sync cache: %d\n", ret);
-				return ret;
-			}
-		}
-
 		if (max98090->jack_state == M98090_JACK_STATE_HEADSET) {
 			/*
 			 * Set to normal bias level.
@@ -1792,6 +1783,16 @@
 		break;
 
 	case SND_SOC_BIAS_STANDBY:
+		if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
+			ret = regcache_sync(max98090->regmap);
+			if (ret != 0) {
+				dev_err(codec->dev,
+					"Failed to sync cache: %d\n", ret);
+				return ret;
+			}
+		}
+		break;
+
 	case SND_SOC_BIAS_OFF:
 		/* Set internal pull-up to lowest power mode */
 		snd_soc_update_bits(codec, M98090_REG_JACK_DETECT,
diff --git a/sound/soc/codecs/rt5640.c b/sound/soc/codecs/rt5640.c
index a3fb411..8869249 100644
--- a/sound/soc/codecs/rt5640.c
+++ b/sound/soc/codecs/rt5640.c
@@ -2093,6 +2093,7 @@
 #ifdef CONFIG_ACPI
 static struct acpi_device_id rt5640_acpi_match[] = {
 	{ "INT33CA", 0 },
+	{ "10EC5640", 0 },
 	{ },
 };
 MODULE_DEVICE_TABLE(acpi, rt5640_acpi_match);
diff --git a/sound/soc/codecs/sta32x.c b/sound/soc/codecs/sta32x.c
index 06edb39..2735361 100644
--- a/sound/soc/codecs/sta32x.c
+++ b/sound/soc/codecs/sta32x.c
@@ -187,42 +187,42 @@
 	13, 16, TLV_DB_SCALE_ITEM(-1500, 300, 0),
 };
 
-static const struct soc_enum sta32x_drc_ac_enum =
-	SOC_ENUM_SINGLE(STA32X_CONFD, STA32X_CONFD_DRC_SHIFT,
-			2, sta32x_drc_ac);
-static const struct soc_enum sta32x_auto_eq_enum =
-	SOC_ENUM_SINGLE(STA32X_AUTO1, STA32X_AUTO1_AMEQ_SHIFT,
-			3, sta32x_auto_eq_mode);
-static const struct soc_enum sta32x_auto_gc_enum =
-	SOC_ENUM_SINGLE(STA32X_AUTO1, STA32X_AUTO1_AMGC_SHIFT,
-			4, sta32x_auto_gc_mode);
-static const struct soc_enum sta32x_auto_xo_enum =
-	SOC_ENUM_SINGLE(STA32X_AUTO2, STA32X_AUTO2_XO_SHIFT,
-			16, sta32x_auto_xo_mode);
-static const struct soc_enum sta32x_preset_eq_enum =
-	SOC_ENUM_SINGLE(STA32X_AUTO3, STA32X_AUTO3_PEQ_SHIFT,
-			32, sta32x_preset_eq_mode);
-static const struct soc_enum sta32x_limiter_ch1_enum =
-	SOC_ENUM_SINGLE(STA32X_C1CFG, STA32X_CxCFG_LS_SHIFT,
-			3, sta32x_limiter_select);
-static const struct soc_enum sta32x_limiter_ch2_enum =
-	SOC_ENUM_SINGLE(STA32X_C2CFG, STA32X_CxCFG_LS_SHIFT,
-			3, sta32x_limiter_select);
-static const struct soc_enum sta32x_limiter_ch3_enum =
-	SOC_ENUM_SINGLE(STA32X_C3CFG, STA32X_CxCFG_LS_SHIFT,
-			3, sta32x_limiter_select);
-static const struct soc_enum sta32x_limiter1_attack_rate_enum =
-	SOC_ENUM_SINGLE(STA32X_L1AR, STA32X_LxA_SHIFT,
-			16, sta32x_limiter_attack_rate);
-static const struct soc_enum sta32x_limiter2_attack_rate_enum =
-	SOC_ENUM_SINGLE(STA32X_L2AR, STA32X_LxA_SHIFT,
-			16, sta32x_limiter_attack_rate);
-static const struct soc_enum sta32x_limiter1_release_rate_enum =
-	SOC_ENUM_SINGLE(STA32X_L1AR, STA32X_LxR_SHIFT,
-			16, sta32x_limiter_release_rate);
-static const struct soc_enum sta32x_limiter2_release_rate_enum =
-	SOC_ENUM_SINGLE(STA32X_L2AR, STA32X_LxR_SHIFT,
-			16, sta32x_limiter_release_rate);
+static SOC_ENUM_SINGLE_DECL(sta32x_drc_ac_enum,
+			    STA32X_CONFD, STA32X_CONFD_DRC_SHIFT,
+			    sta32x_drc_ac);
+static SOC_ENUM_SINGLE_DECL(sta32x_auto_eq_enum,
+			    STA32X_AUTO1, STA32X_AUTO1_AMEQ_SHIFT,
+			    sta32x_auto_eq_mode);
+static SOC_ENUM_SINGLE_DECL(sta32x_auto_gc_enum,
+			    STA32X_AUTO1, STA32X_AUTO1_AMGC_SHIFT,
+			    sta32x_auto_gc_mode);
+static SOC_ENUM_SINGLE_DECL(sta32x_auto_xo_enum,
+			    STA32X_AUTO2, STA32X_AUTO2_XO_SHIFT,
+			    sta32x_auto_xo_mode);
+static SOC_ENUM_SINGLE_DECL(sta32x_preset_eq_enum,
+			    STA32X_AUTO3, STA32X_AUTO3_PEQ_SHIFT,
+			    sta32x_preset_eq_mode);
+static SOC_ENUM_SINGLE_DECL(sta32x_limiter_ch1_enum,
+			    STA32X_C1CFG, STA32X_CxCFG_LS_SHIFT,
+			    sta32x_limiter_select);
+static SOC_ENUM_SINGLE_DECL(sta32x_limiter_ch2_enum,
+			    STA32X_C2CFG, STA32X_CxCFG_LS_SHIFT,
+			    sta32x_limiter_select);
+static SOC_ENUM_SINGLE_DECL(sta32x_limiter_ch3_enum,
+			    STA32X_C3CFG, STA32X_CxCFG_LS_SHIFT,
+			    sta32x_limiter_select);
+static SOC_ENUM_SINGLE_DECL(sta32x_limiter1_attack_rate_enum,
+			    STA32X_L1AR, STA32X_LxA_SHIFT,
+			    sta32x_limiter_attack_rate);
+static SOC_ENUM_SINGLE_DECL(sta32x_limiter2_attack_rate_enum,
+			    STA32X_L2AR, STA32X_LxA_SHIFT,
+			    sta32x_limiter_attack_rate);
+static SOC_ENUM_SINGLE_DECL(sta32x_limiter1_release_rate_enum,
+			    STA32X_L1AR, STA32X_LxR_SHIFT,
+			    sta32x_limiter_release_rate);
+static SOC_ENUM_SINGLE_DECL(sta32x_limiter2_release_rate_enum,
+			    STA32X_L2AR, STA32X_LxR_SHIFT,
+			    sta32x_limiter_release_rate);
 
 /* byte array controls for setting biquad, mixer, scaling coefficients;
  * for biquads all five coefficients need to be set in one go,
@@ -331,7 +331,7 @@
 
 static int sta32x_cache_sync(struct snd_soc_codec *codec)
 {
-	struct sta32x_priv *sta32x = codec->control_data;
+	struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec);
 	unsigned int mute;
 	int rc;
 
@@ -434,7 +434,7 @@
 SOC_ENUM("Limiter1 Attack Rate (dB/ms)", sta32x_limiter1_attack_rate_enum),
 SOC_ENUM("Limiter2 Attack Rate (dB/ms)", sta32x_limiter2_attack_rate_enum),
 SOC_ENUM("Limiter1 Release Rate (dB/ms)", sta32x_limiter1_release_rate_enum),
-SOC_ENUM("Limiter2 Release Rate (dB/ms)", sta32x_limiter1_release_rate_enum),
+SOC_ENUM("Limiter2 Release Rate (dB/ms)", sta32x_limiter2_release_rate_enum),
 
 /* depending on mode, the attack/release thresholds have
  * two different enum definitions; provide both
diff --git a/sound/soc/codecs/wm8400.c b/sound/soc/codecs/wm8400.c
index 48dc7d2..6d684d9 100644
--- a/sound/soc/codecs/wm8400.c
+++ b/sound/soc/codecs/wm8400.c
@@ -117,19 +117,23 @@
 static const char *wm8400_digital_sidetone[] =
 	{"None", "Left ADC", "Right ADC", "Reserved"};
 
-static const struct soc_enum wm8400_left_digital_sidetone_enum =
-SOC_ENUM_SINGLE(WM8400_DIGITAL_SIDE_TONE,
-		WM8400_ADC_TO_DACL_SHIFT, 2, wm8400_digital_sidetone);
+static SOC_ENUM_SINGLE_DECL(wm8400_left_digital_sidetone_enum,
+			    WM8400_DIGITAL_SIDE_TONE,
+			    WM8400_ADC_TO_DACL_SHIFT,
+			    wm8400_digital_sidetone);
 
-static const struct soc_enum wm8400_right_digital_sidetone_enum =
-SOC_ENUM_SINGLE(WM8400_DIGITAL_SIDE_TONE,
-		WM8400_ADC_TO_DACR_SHIFT, 2, wm8400_digital_sidetone);
+static SOC_ENUM_SINGLE_DECL(wm8400_right_digital_sidetone_enum,
+			    WM8400_DIGITAL_SIDE_TONE,
+			    WM8400_ADC_TO_DACR_SHIFT,
+			    wm8400_digital_sidetone);
 
 static const char *wm8400_adcmode[] =
 	{"Hi-fi mode", "Voice mode 1", "Voice mode 2", "Voice mode 3"};
 
-static const struct soc_enum wm8400_right_adcmode_enum =
-SOC_ENUM_SINGLE(WM8400_ADC_CTRL, WM8400_ADC_HPF_CUT_SHIFT, 3, wm8400_adcmode);
+static SOC_ENUM_SINGLE_DECL(wm8400_right_adcmode_enum,
+			    WM8400_ADC_CTRL,
+			    WM8400_ADC_HPF_CUT_SHIFT,
+			    wm8400_adcmode);
 
 static const struct snd_kcontrol_new wm8400_snd_controls[] = {
 /* INMIXL */
@@ -422,9 +426,10 @@
 static const char *wm8400_ainlmux[] =
 	{"INMIXL Mix", "RXVOICE Mix", "DIFFINL Mix"};
 
-static const struct soc_enum wm8400_ainlmux_enum =
-SOC_ENUM_SINGLE( WM8400_INPUT_MIXER1, WM8400_AINLMODE_SHIFT,
-	ARRAY_SIZE(wm8400_ainlmux), wm8400_ainlmux);
+static SOC_ENUM_SINGLE_DECL(wm8400_ainlmux_enum,
+			    WM8400_INPUT_MIXER1,
+			    WM8400_AINLMODE_SHIFT,
+			    wm8400_ainlmux);
 
 static const struct snd_kcontrol_new wm8400_dapm_ainlmux_controls =
 SOC_DAPM_ENUM("Route", wm8400_ainlmux_enum);
@@ -435,9 +440,10 @@
 static const char *wm8400_ainrmux[] =
 	{"INMIXR Mix", "RXVOICE Mix", "DIFFINR Mix"};
 
-static const struct soc_enum wm8400_ainrmux_enum =
-SOC_ENUM_SINGLE( WM8400_INPUT_MIXER1, WM8400_AINRMODE_SHIFT,
-	ARRAY_SIZE(wm8400_ainrmux), wm8400_ainrmux);
+static SOC_ENUM_SINGLE_DECL(wm8400_ainrmux_enum,
+			    WM8400_INPUT_MIXER1,
+			    WM8400_AINRMODE_SHIFT,
+			    wm8400_ainrmux);
 
 static const struct snd_kcontrol_new wm8400_dapm_ainrmux_controls =
 SOC_DAPM_ENUM("Route", wm8400_ainrmux_enum);
diff --git a/sound/soc/codecs/wm8770.c b/sound/soc/codecs/wm8770.c
index 89a18d8..5bce210 100644
--- a/sound/soc/codecs/wm8770.c
+++ b/sound/soc/codecs/wm8770.c
@@ -196,8 +196,8 @@
 	"AIN5", "AIN6", "AIN7", "AIN8"
 };
 
-static const struct soc_enum ain_enum =
-	SOC_ENUM_DOUBLE(WM8770_ADCMUX, 0, 4, 8, ain_text);
+static SOC_ENUM_DOUBLE_DECL(ain_enum,
+			    WM8770_ADCMUX, 0, 4, ain_text);
 
 static const struct snd_kcontrol_new ain_mux =
 	SOC_DAPM_ENUM("Capture Mux", ain_enum);
diff --git a/sound/soc/codecs/wm8900.c b/sound/soc/codecs/wm8900.c
index e98bc70..43c2201 100644
--- a/sound/soc/codecs/wm8900.c
+++ b/sound/soc/codecs/wm8900.c
@@ -304,53 +304,53 @@
 
 static const char *mic_bias_level_txt[] = { "0.9*AVDD", "0.65*AVDD" };
 
-static const struct soc_enum mic_bias_level =
-SOC_ENUM_SINGLE(WM8900_REG_INCTL, 8, 2, mic_bias_level_txt);
+static SOC_ENUM_SINGLE_DECL(mic_bias_level,
+			    WM8900_REG_INCTL, 8, mic_bias_level_txt);
 
 static const char *dac_mute_rate_txt[] = { "Fast", "Slow" };
 
-static const struct soc_enum dac_mute_rate =
-SOC_ENUM_SINGLE(WM8900_REG_DACCTRL, 7, 2, dac_mute_rate_txt);
+static SOC_ENUM_SINGLE_DECL(dac_mute_rate,
+			    WM8900_REG_DACCTRL, 7, dac_mute_rate_txt);
 
 static const char *dac_deemphasis_txt[] = {
 	"Disabled", "32kHz", "44.1kHz", "48kHz"
 };
 
-static const struct soc_enum dac_deemphasis =
-SOC_ENUM_SINGLE(WM8900_REG_DACCTRL, 4, 4, dac_deemphasis_txt);
+static SOC_ENUM_SINGLE_DECL(dac_deemphasis,
+			    WM8900_REG_DACCTRL, 4, dac_deemphasis_txt);
 
 static const char *adc_hpf_cut_txt[] = {
 	"Hi-fi mode", "Voice mode 1", "Voice mode 2", "Voice mode 3"
 };
 
-static const struct soc_enum adc_hpf_cut =
-SOC_ENUM_SINGLE(WM8900_REG_ADCCTRL, 5, 4, adc_hpf_cut_txt);
+static SOC_ENUM_SINGLE_DECL(adc_hpf_cut,
+			    WM8900_REG_ADCCTRL, 5, adc_hpf_cut_txt);
 
 static const char *lr_txt[] = {
 	"Left", "Right"
 };
 
-static const struct soc_enum aifl_src =
-SOC_ENUM_SINGLE(WM8900_REG_AUDIO1, 15, 2, lr_txt);
+static SOC_ENUM_SINGLE_DECL(aifl_src,
+			    WM8900_REG_AUDIO1, 15, lr_txt);
 
-static const struct soc_enum aifr_src =
-SOC_ENUM_SINGLE(WM8900_REG_AUDIO1, 14, 2, lr_txt);
+static SOC_ENUM_SINGLE_DECL(aifr_src,
+			    WM8900_REG_AUDIO1, 14, lr_txt);
 
-static const struct soc_enum dacl_src =
-SOC_ENUM_SINGLE(WM8900_REG_AUDIO2, 15, 2, lr_txt);
+static SOC_ENUM_SINGLE_DECL(dacl_src,
+			    WM8900_REG_AUDIO2, 15, lr_txt);
 
-static const struct soc_enum dacr_src =
-SOC_ENUM_SINGLE(WM8900_REG_AUDIO2, 14, 2, lr_txt);
+static SOC_ENUM_SINGLE_DECL(dacr_src,
+			    WM8900_REG_AUDIO2, 14, lr_txt);
 
 static const char *sidetone_txt[] = {
 	"Disabled", "Left ADC", "Right ADC"
 };
 
-static const struct soc_enum dacl_sidetone =
-SOC_ENUM_SINGLE(WM8900_REG_SIDETONE, 2, 3, sidetone_txt);
+static SOC_ENUM_SINGLE_DECL(dacl_sidetone,
+			    WM8900_REG_SIDETONE, 2, sidetone_txt);
 
-static const struct soc_enum dacr_sidetone =
-SOC_ENUM_SINGLE(WM8900_REG_SIDETONE, 0, 3, sidetone_txt);
+static SOC_ENUM_SINGLE_DECL(dacr_sidetone,
+			    WM8900_REG_SIDETONE, 0, sidetone_txt);
 
 static const struct snd_kcontrol_new wm8900_snd_controls[] = {
 SOC_ENUM("Mic Bias Level", mic_bias_level),
@@ -496,8 +496,8 @@
 
 static const char *wm8900_lp_mux[] = { "Disabled", "Enabled" };
 
-static const struct soc_enum wm8900_lineout2_lp_mux =
-SOC_ENUM_SINGLE(WM8900_REG_LOUTMIXCTL1, 1, 2, wm8900_lp_mux);
+static SOC_ENUM_SINGLE_DECL(wm8900_lineout2_lp_mux,
+			    WM8900_REG_LOUTMIXCTL1, 1, wm8900_lp_mux);
 
 static const struct snd_kcontrol_new wm8900_lineout2_lp =
 SOC_DAPM_ENUM("Route", wm8900_lineout2_lp_mux);
diff --git a/sound/soc/codecs/wm8958-dsp2.c b/sound/soc/codecs/wm8958-dsp2.c
index b7488f1..d4248e0 100644
--- a/sound/soc/codecs/wm8958-dsp2.c
+++ b/sound/soc/codecs/wm8958-dsp2.c
@@ -153,7 +153,7 @@
 
 			data32 &= 0xffffff;
 
-			wm8994_bulk_write(codec->control_data,
+			wm8994_bulk_write(wm8994->wm8994,
 					  data32 & 0xffffff,
 					  block_len / 2,
 					  (void *)(data + 8));
diff --git a/sound/soc/codecs/wm8993.c b/sound/soc/codecs/wm8993.c
index 433d59a..2ee23a3 100644
--- a/sound/soc/codecs/wm8993.c
+++ b/sound/soc/codecs/wm8993.c
@@ -1562,7 +1562,6 @@
 	struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec);
 
 	wm8993_set_bias_level(codec, SND_SOC_BIAS_OFF);
-	regulator_bulk_free(ARRAY_SIZE(wm8993->supplies), wm8993->supplies);
 	return 0;
 }
 
diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c
index b9be9cb..adb7206 100644
--- a/sound/soc/codecs/wm8994.c
+++ b/sound/soc/codecs/wm8994.c
@@ -265,21 +265,21 @@
 	"2.7kHz", "1.35kHz", "675Hz", "370Hz", "180Hz", "90Hz", "45Hz"
 };
 
-static const struct soc_enum sidetone_hpf =
-	SOC_ENUM_SINGLE(WM8994_SIDETONE, 7, 7, sidetone_hpf_text);
+static SOC_ENUM_SINGLE_DECL(sidetone_hpf,
+			    WM8994_SIDETONE, 7, sidetone_hpf_text);
 
 static const char *adc_hpf_text[] = {
 	"HiFi", "Voice 1", "Voice 2", "Voice 3"
 };
 
-static const struct soc_enum aif1adc1_hpf =
-	SOC_ENUM_SINGLE(WM8994_AIF1_ADC1_FILTERS, 13, 4, adc_hpf_text);
+static SOC_ENUM_SINGLE_DECL(aif1adc1_hpf,
+			    WM8994_AIF1_ADC1_FILTERS, 13, adc_hpf_text);
 
-static const struct soc_enum aif1adc2_hpf =
-	SOC_ENUM_SINGLE(WM8994_AIF1_ADC2_FILTERS, 13, 4, adc_hpf_text);
+static SOC_ENUM_SINGLE_DECL(aif1adc2_hpf,
+			    WM8994_AIF1_ADC2_FILTERS, 13, adc_hpf_text);
 
-static const struct soc_enum aif2adc_hpf =
-	SOC_ENUM_SINGLE(WM8994_AIF2_ADC_FILTERS, 13, 4, adc_hpf_text);
+static SOC_ENUM_SINGLE_DECL(aif2adc_hpf,
+			    WM8994_AIF2_ADC_FILTERS, 13, adc_hpf_text);
 
 static const DECLARE_TLV_DB_SCALE(aif_tlv, 0, 600, 0);
 static const DECLARE_TLV_DB_SCALE(digital_tlv, -7200, 75, 1);
@@ -501,39 +501,39 @@
 	"Left", "Right"
 };
 
-static const struct soc_enum aif1adcl_src =
-	SOC_ENUM_SINGLE(WM8994_AIF1_CONTROL_1, 15, 2, aif_chan_src_text);
+static SOC_ENUM_SINGLE_DECL(aif1adcl_src,
+			    WM8994_AIF1_CONTROL_1, 15, aif_chan_src_text);
 
-static const struct soc_enum aif1adcr_src =
-	SOC_ENUM_SINGLE(WM8994_AIF1_CONTROL_1, 14, 2, aif_chan_src_text);
+static SOC_ENUM_SINGLE_DECL(aif1adcr_src,
+			    WM8994_AIF1_CONTROL_1, 14, aif_chan_src_text);
 
-static const struct soc_enum aif2adcl_src =
-	SOC_ENUM_SINGLE(WM8994_AIF2_CONTROL_1, 15, 2, aif_chan_src_text);
+static SOC_ENUM_SINGLE_DECL(aif2adcl_src,
+			    WM8994_AIF2_CONTROL_1, 15, aif_chan_src_text);
 
-static const struct soc_enum aif2adcr_src =
-	SOC_ENUM_SINGLE(WM8994_AIF2_CONTROL_1, 14, 2, aif_chan_src_text);
+static SOC_ENUM_SINGLE_DECL(aif2adcr_src,
+			    WM8994_AIF2_CONTROL_1, 14, aif_chan_src_text);
 
-static const struct soc_enum aif1dacl_src =
-	SOC_ENUM_SINGLE(WM8994_AIF1_CONTROL_2, 15, 2, aif_chan_src_text);
+static SOC_ENUM_SINGLE_DECL(aif1dacl_src,
+			    WM8994_AIF1_CONTROL_2, 15, aif_chan_src_text);
 
-static const struct soc_enum aif1dacr_src =
-	SOC_ENUM_SINGLE(WM8994_AIF1_CONTROL_2, 14, 2, aif_chan_src_text);
+static SOC_ENUM_SINGLE_DECL(aif1dacr_src,
+			    WM8994_AIF1_CONTROL_2, 14, aif_chan_src_text);
 
-static const struct soc_enum aif2dacl_src =
-	SOC_ENUM_SINGLE(WM8994_AIF2_CONTROL_2, 15, 2, aif_chan_src_text);
+static SOC_ENUM_SINGLE_DECL(aif2dacl_src,
+			    WM8994_AIF2_CONTROL_2, 15, aif_chan_src_text);
 
-static const struct soc_enum aif2dacr_src =
-	SOC_ENUM_SINGLE(WM8994_AIF2_CONTROL_2, 14, 2, aif_chan_src_text);
+static SOC_ENUM_SINGLE_DECL(aif2dacr_src,
+			    WM8994_AIF2_CONTROL_2, 14, aif_chan_src_text);
 
 static const char *osr_text[] = {
 	"Low Power", "High Performance",
 };
 
-static const struct soc_enum dac_osr =
-	SOC_ENUM_SINGLE(WM8994_OVERSAMPLING, 0, 2, osr_text);
+static SOC_ENUM_SINGLE_DECL(dac_osr,
+			    WM8994_OVERSAMPLING, 0, osr_text);
 
-static const struct soc_enum adc_osr =
-	SOC_ENUM_SINGLE(WM8994_OVERSAMPLING, 1, 2, osr_text);
+static SOC_ENUM_SINGLE_DECL(adc_osr,
+			    WM8994_OVERSAMPLING, 1, osr_text);
 
 static const struct snd_kcontrol_new wm8994_snd_controls[] = {
 SOC_DOUBLE_R_TLV("AIF1ADC1 Volume", WM8994_AIF1_ADC1_LEFT_VOLUME,
@@ -690,17 +690,20 @@
 	"30ms", "125ms", "250ms", "500ms",
 };
 
-static const struct soc_enum wm8958_aif1dac1_ng_hold =
-	SOC_ENUM_SINGLE(WM8958_AIF1_DAC1_NOISE_GATE,
-			WM8958_AIF1DAC1_NG_THR_SHIFT, 4, wm8958_ng_text);
+static SOC_ENUM_SINGLE_DECL(wm8958_aif1dac1_ng_hold,
+			    WM8958_AIF1_DAC1_NOISE_GATE,
+			    WM8958_AIF1DAC1_NG_THR_SHIFT,
+			    wm8958_ng_text);
 
-static const struct soc_enum wm8958_aif1dac2_ng_hold =
-	SOC_ENUM_SINGLE(WM8958_AIF1_DAC2_NOISE_GATE,
-			WM8958_AIF1DAC2_NG_THR_SHIFT, 4, wm8958_ng_text);
+static SOC_ENUM_SINGLE_DECL(wm8958_aif1dac2_ng_hold,
+			    WM8958_AIF1_DAC2_NOISE_GATE,
+			    WM8958_AIF1DAC2_NG_THR_SHIFT,
+			    wm8958_ng_text);
 
-static const struct soc_enum wm8958_aif2dac_ng_hold =
-	SOC_ENUM_SINGLE(WM8958_AIF2_DAC_NOISE_GATE,
-			WM8958_AIF2DAC_NG_THR_SHIFT, 4, wm8958_ng_text);
+static SOC_ENUM_SINGLE_DECL(wm8958_aif2dac_ng_hold,
+			    WM8958_AIF2_DAC_NOISE_GATE,
+			    WM8958_AIF2DAC_NG_THR_SHIFT,
+			    wm8958_ng_text);
 
 static const struct snd_kcontrol_new wm8958_snd_controls[] = {
 SOC_SINGLE_TLV("AIF3 Boost Volume", WM8958_AIF3_CONTROL_2, 10, 3, 0, aif_tlv),
@@ -1341,8 +1344,8 @@
 	"DMIC",
 };
 
-static const struct soc_enum adc_enum =
-	SOC_ENUM_SINGLE(0, 0, 2, adc_mux_text);
+static SOC_ENUM_SINGLE_DECL(adc_enum,
+			    0, 0, adc_mux_text);
 
 static const struct snd_kcontrol_new adcl_mux =
 	SOC_DAPM_ENUM_VIRT("ADCL Mux", adc_enum);
@@ -1478,14 +1481,14 @@
 	"ADC/DMIC1", "DMIC2",
 };
 
-static const struct soc_enum sidetone1_enum =
-	SOC_ENUM_SINGLE(WM8994_SIDETONE, 0, 2, sidetone_text);
+static SOC_ENUM_SINGLE_DECL(sidetone1_enum,
+			    WM8994_SIDETONE, 0, sidetone_text);
 
 static const struct snd_kcontrol_new sidetone1_mux =
 	SOC_DAPM_ENUM("Left Sidetone Mux", sidetone1_enum);
 
-static const struct soc_enum sidetone2_enum =
-	SOC_ENUM_SINGLE(WM8994_SIDETONE, 1, 2, sidetone_text);
+static SOC_ENUM_SINGLE_DECL(sidetone2_enum,
+			    WM8994_SIDETONE, 1, sidetone_text);
 
 static const struct snd_kcontrol_new sidetone2_mux =
 	SOC_DAPM_ENUM("Right Sidetone Mux", sidetone2_enum);
@@ -1498,22 +1501,24 @@
 	"None", "ADCDAT",
 };
 
-static const struct soc_enum aif1_loopback_enum =
-	SOC_ENUM_SINGLE(WM8994_AIF1_CONTROL_2, WM8994_AIF1_LOOPBACK_SHIFT, 2,
-			loopback_text);
+static SOC_ENUM_SINGLE_DECL(aif1_loopback_enum,
+			    WM8994_AIF1_CONTROL_2,
+			    WM8994_AIF1_LOOPBACK_SHIFT,
+			    loopback_text);
 
 static const struct snd_kcontrol_new aif1_loopback =
 	SOC_DAPM_ENUM("AIF1 Loopback", aif1_loopback_enum);
 
-static const struct soc_enum aif2_loopback_enum =
-	SOC_ENUM_SINGLE(WM8994_AIF2_CONTROL_2, WM8994_AIF2_LOOPBACK_SHIFT, 2,
-			loopback_text);
+static SOC_ENUM_SINGLE_DECL(aif2_loopback_enum,
+			    WM8994_AIF2_CONTROL_2,
+			    WM8994_AIF2_LOOPBACK_SHIFT,
+			    loopback_text);
 
 static const struct snd_kcontrol_new aif2_loopback =
 	SOC_DAPM_ENUM("AIF2 Loopback", aif2_loopback_enum);
 
-static const struct soc_enum aif1dac_enum =
-	SOC_ENUM_SINGLE(WM8994_POWER_MANAGEMENT_6, 0, 2, aif1dac_text);
+static SOC_ENUM_SINGLE_DECL(aif1dac_enum,
+			    WM8994_POWER_MANAGEMENT_6, 0, aif1dac_text);
 
 static const struct snd_kcontrol_new aif1dac_mux =
 	SOC_DAPM_ENUM("AIF1DAC Mux", aif1dac_enum);
@@ -1522,8 +1527,8 @@
 	"AIF2DACDAT", "AIF3DACDAT",
 };
 
-static const struct soc_enum aif2dac_enum =
-	SOC_ENUM_SINGLE(WM8994_POWER_MANAGEMENT_6, 1, 2, aif2dac_text);
+static SOC_ENUM_SINGLE_DECL(aif2dac_enum,
+			    WM8994_POWER_MANAGEMENT_6, 1, aif2dac_text);
 
 static const struct snd_kcontrol_new aif2dac_mux =
 	SOC_DAPM_ENUM("AIF2DAC Mux", aif2dac_enum);
@@ -1532,8 +1537,8 @@
 	"AIF2ADCDAT", "AIF3DACDAT",
 };
 
-static const struct soc_enum aif2adc_enum =
-	SOC_ENUM_SINGLE(WM8994_POWER_MANAGEMENT_6, 2, 2, aif2adc_text);
+static SOC_ENUM_SINGLE_DECL(aif2adc_enum,
+			    WM8994_POWER_MANAGEMENT_6, 2, aif2adc_text);
 
 static const struct snd_kcontrol_new aif2adc_mux =
 	SOC_DAPM_ENUM("AIF2ADC Mux", aif2adc_enum);
@@ -1542,14 +1547,14 @@
 	"AIF1ADCDAT", "AIF2ADCDAT", "AIF2DACDAT", "Mono PCM",
 };
 
-static const struct soc_enum wm8994_aif3adc_enum =
-	SOC_ENUM_SINGLE(WM8994_POWER_MANAGEMENT_6, 3, 3, aif3adc_text);
+static SOC_ENUM_SINGLE_DECL(wm8994_aif3adc_enum,
+			    WM8994_POWER_MANAGEMENT_6, 3, aif3adc_text);
 
 static const struct snd_kcontrol_new wm8994_aif3adc_mux =
 	SOC_DAPM_ENUM("AIF3ADC Mux", wm8994_aif3adc_enum);
 
-static const struct soc_enum wm8958_aif3adc_enum =
-	SOC_ENUM_SINGLE(WM8994_POWER_MANAGEMENT_6, 3, 4, aif3adc_text);
+static SOC_ENUM_SINGLE_DECL(wm8958_aif3adc_enum,
+			    WM8994_POWER_MANAGEMENT_6, 3, aif3adc_text);
 
 static const struct snd_kcontrol_new wm8958_aif3adc_mux =
 	SOC_DAPM_ENUM("AIF3ADC Mux", wm8958_aif3adc_enum);
@@ -1558,8 +1563,8 @@
 	"None", "AIF2ADCL", "AIF2ADCR",
 };
 
-static const struct soc_enum mono_pcm_out_enum =
-	SOC_ENUM_SINGLE(WM8994_POWER_MANAGEMENT_6, 9, 3, mono_pcm_out_text);
+static SOC_ENUM_SINGLE_DECL(mono_pcm_out_enum,
+			    WM8994_POWER_MANAGEMENT_6, 9, mono_pcm_out_text);
 
 static const struct snd_kcontrol_new mono_pcm_out_mux =
 	SOC_DAPM_ENUM("Mono PCM Out Mux", mono_pcm_out_enum);
@@ -1569,14 +1574,14 @@
 };
 
 /* Note that these two control shouldn't be simultaneously switched to AIF3 */
-static const struct soc_enum aif2dacl_src_enum =
-	SOC_ENUM_SINGLE(WM8994_POWER_MANAGEMENT_6, 7, 2, aif2dac_src_text);
+static SOC_ENUM_SINGLE_DECL(aif2dacl_src_enum,
+			    WM8994_POWER_MANAGEMENT_6, 7, aif2dac_src_text);
 
 static const struct snd_kcontrol_new aif2dacl_src_mux =
 	SOC_DAPM_ENUM("AIF2DACL Mux", aif2dacl_src_enum);
 
-static const struct soc_enum aif2dacr_src_enum =
-	SOC_ENUM_SINGLE(WM8994_POWER_MANAGEMENT_6, 8, 2, aif2dac_src_text);
+static SOC_ENUM_SINGLE_DECL(aif2dacr_src_enum,
+			    WM8994_POWER_MANAGEMENT_6, 8, aif2dac_src_text);
 
 static const struct snd_kcontrol_new aif2dacr_src_mux =
 	SOC_DAPM_ENUM("AIF2DACR Mux", aif2dacr_src_enum);
diff --git a/sound/soc/davinci/davinci-evm.c b/sound/soc/davinci/davinci-evm.c
index 70ff377..5e3bc3c 100644
--- a/sound/soc/davinci/davinci-evm.c
+++ b/sound/soc/davinci/davinci-evm.c
@@ -399,6 +399,7 @@
 	.driver		= {
 		.name	= "davinci_evm",
 		.owner	= THIS_MODULE,
+		.pm	= &snd_soc_pm_ops,
 		.of_match_table = of_match_ptr(davinci_evm_dt_ids),
 	},
 };
diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c
index b7858bf..670afa2 100644
--- a/sound/soc/davinci/davinci-mcasp.c
+++ b/sound/soc/davinci/davinci-mcasp.c
@@ -263,7 +263,9 @@
 					 unsigned int fmt)
 {
 	struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(cpu_dai);
+	int ret = 0;
 
+	pm_runtime_get_sync(mcasp->dev);
 	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
 	case SND_SOC_DAIFMT_DSP_B:
 	case SND_SOC_DAIFMT_AC97:
@@ -317,7 +319,8 @@
 		break;
 
 	default:
-		return -EINVAL;
+		ret = -EINVAL;
+		goto out;
 	}
 
 	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
@@ -354,10 +357,12 @@
 		break;
 
 	default:
-		return -EINVAL;
+		ret = -EINVAL;
+		break;
 	}
-
-	return 0;
+out:
+	pm_runtime_put_sync(mcasp->dev);
+	return ret;
 }
 
 static int davinci_mcasp_set_clkdiv(struct snd_soc_dai *dai, int div_id, int div)
@@ -448,7 +453,7 @@
 	return 0;
 }
 
-static int davinci_hw_common_param(struct davinci_mcasp *mcasp, int stream,
+static int mcasp_common_hw_param(struct davinci_mcasp *mcasp, int stream,
 				    int channels)
 {
 	int i;
@@ -524,12 +529,18 @@
 	return 0;
 }
 
-static void davinci_hw_param(struct davinci_mcasp *mcasp, int stream)
+static int mcasp_i2s_hw_param(struct davinci_mcasp *mcasp, int stream)
 {
 	int i, active_slots;
 	u32 mask = 0;
 	u32 busel = 0;
 
+	if ((mcasp->tdm_slots < 2) || (mcasp->tdm_slots > 32)) {
+		dev_err(mcasp->dev, "tdm slot %d not supported\n",
+			mcasp->tdm_slots);
+		return -EINVAL;
+	}
+
 	active_slots = (mcasp->tdm_slots > 31) ? 32 : mcasp->tdm_slots;
 	for (i = 0; i < active_slots; i++)
 		mask |= (1 << i);
@@ -539,35 +550,21 @@
 	if (!mcasp->dat_port)
 		busel = TXSEL;
 
-	if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
-		/* bit stream is MSB first  with no delay */
-		/* DSP_B mode */
-		mcasp_set_reg(mcasp, DAVINCI_MCASP_TXTDM_REG, mask);
-		mcasp_set_bits(mcasp, DAVINCI_MCASP_TXFMT_REG, busel | TXORD);
+	mcasp_set_reg(mcasp, DAVINCI_MCASP_TXTDM_REG, mask);
+	mcasp_set_bits(mcasp, DAVINCI_MCASP_TXFMT_REG, busel | TXORD);
+	mcasp_mod_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG,
+		       FSXMOD(mcasp->tdm_slots), FSXMOD(0x1FF));
 
-		if ((mcasp->tdm_slots >= 2) && (mcasp->tdm_slots <= 32))
-			mcasp_mod_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG,
-				       FSXMOD(mcasp->tdm_slots), FSXMOD(0x1FF));
-		else
-			printk(KERN_ERR "playback tdm slot %d not supported\n",
-				mcasp->tdm_slots);
-	} else {
-		/* bit stream is MSB first with no delay */
-		/* DSP_B mode */
-		mcasp_set_bits(mcasp, DAVINCI_MCASP_RXFMT_REG, busel | RXORD);
-		mcasp_set_reg(mcasp, DAVINCI_MCASP_RXTDM_REG, mask);
+	mcasp_set_reg(mcasp, DAVINCI_MCASP_RXTDM_REG, mask);
+	mcasp_set_bits(mcasp, DAVINCI_MCASP_RXFMT_REG, busel | RXORD);
+	mcasp_mod_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG,
+		       FSRMOD(mcasp->tdm_slots), FSRMOD(0x1FF));
 
-		if ((mcasp->tdm_slots >= 2) && (mcasp->tdm_slots <= 32))
-			mcasp_mod_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG,
-				       FSRMOD(mcasp->tdm_slots), FSRMOD(0x1FF));
-		else
-			printk(KERN_ERR "capture tdm slot %d not supported\n",
-				mcasp->tdm_slots);
-	}
+	return 0;
 }
 
 /* S/PDIF */
-static void davinci_hw_dit_param(struct davinci_mcasp *mcasp)
+static int mcasp_dit_hw_param(struct davinci_mcasp *mcasp)
 {
 	/* Set the TX format : 24 bit right rotation, 32 bit slot, Pad 0
 	   and LSB first */
@@ -589,6 +586,8 @@
 
 	/* Enable the DIT */
 	mcasp_set_bits(mcasp, DAVINCI_MCASP_TXDITCTL_REG, DITEN);
+
+	return 0;
 }
 
 static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream,
@@ -605,13 +604,14 @@
 	u8 slots = mcasp->tdm_slots;
 	u8 active_serializers;
 	int channels;
+	int ret;
 	struct snd_interval *pcm_channels = hw_param_interval(params,
 					SNDRV_PCM_HW_PARAM_CHANNELS);
 	channels = pcm_channels->min;
 
 	active_serializers = (channels + slots - 1) / slots;
 
-	if (davinci_hw_common_param(mcasp, substream->stream, channels) == -EINVAL)
+	if (mcasp_common_hw_param(mcasp, substream->stream, channels) == -EINVAL)
 		return -EINVAL;
 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
 		fifo_level = mcasp->txnumevt * active_serializers;
@@ -619,9 +619,12 @@
 		fifo_level = mcasp->rxnumevt * active_serializers;
 
 	if (mcasp->op_mode == DAVINCI_MCASP_DIT_MODE)
-		davinci_hw_dit_param(mcasp);
+		ret = mcasp_dit_hw_param(mcasp);
 	else
-		davinci_hw_param(mcasp, substream->stream);
+		ret = mcasp_i2s_hw_param(mcasp, substream->stream);
+
+	if (ret)
+		return ret;
 
 	switch (params_format(params)) {
 	case SNDRV_PCM_FORMAT_U8:
@@ -678,19 +681,9 @@
 	case SNDRV_PCM_TRIGGER_RESUME:
 	case SNDRV_PCM_TRIGGER_START:
 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-		ret = pm_runtime_get_sync(mcasp->dev);
-		if (IS_ERR_VALUE(ret))
-			dev_err(mcasp->dev, "pm_runtime_get_sync() failed\n");
 		davinci_mcasp_start(mcasp, substream->stream);
 		break;
-
 	case SNDRV_PCM_TRIGGER_SUSPEND:
-		davinci_mcasp_stop(mcasp, substream->stream);
-		ret = pm_runtime_put_sync(mcasp->dev);
-		if (IS_ERR_VALUE(ret))
-			dev_err(mcasp->dev, "pm_runtime_put_sync() failed\n");
-		break;
-
 	case SNDRV_PCM_TRIGGER_STOP:
 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
 		davinci_mcasp_stop(mcasp, substream->stream);
diff --git a/sound/soc/fsl/fsl_esai.c b/sound/soc/fsl/fsl_esai.c
index d0c72ed..c84026c 100644
--- a/sound/soc/fsl/fsl_esai.c
+++ b/sound/soc/fsl/fsl_esai.c
@@ -326,7 +326,7 @@
 	regmap_update_bits(esai_priv->regmap, REG_ESAI_TSMA,
 			   ESAI_xSMA_xS_MASK, ESAI_xSMA_xS(tx_mask));
 	regmap_update_bits(esai_priv->regmap, REG_ESAI_TSMB,
-			   ESAI_xSMA_xS_MASK, ESAI_xSMB_xS(tx_mask));
+			   ESAI_xSMB_xS_MASK, ESAI_xSMB_xS(tx_mask));
 
 	regmap_update_bits(esai_priv->regmap, REG_ESAI_RCCR,
 			   ESAI_xCCR_xDC_MASK, ESAI_xCCR_xDC(slots));
@@ -334,7 +334,7 @@
 	regmap_update_bits(esai_priv->regmap, REG_ESAI_RSMA,
 			   ESAI_xSMA_xS_MASK, ESAI_xSMA_xS(rx_mask));
 	regmap_update_bits(esai_priv->regmap, REG_ESAI_RSMB,
-			   ESAI_xSMA_xS_MASK, ESAI_xSMB_xS(rx_mask));
+			   ESAI_xSMB_xS_MASK, ESAI_xSMB_xS(rx_mask));
 
 	esai_priv->slot_width = slot_width;
 
diff --git a/sound/soc/fsl/fsl_esai.h b/sound/soc/fsl/fsl_esai.h
index 9c9f957..75e1403 100644
--- a/sound/soc/fsl/fsl_esai.h
+++ b/sound/soc/fsl/fsl_esai.h
@@ -322,7 +322,7 @@
 #define ESAI_xSMB_xS_SHIFT	0
 #define ESAI_xSMB_xS_WIDTH	16
 #define ESAI_xSMB_xS_MASK	(((1 << ESAI_xSMB_xS_WIDTH) - 1) << ESAI_xSMB_xS_SHIFT)
-#define ESAI_xSMB_xS(v)		(((v) >> ESAI_xSMA_xS_WIDTH) & ESAI_xSMA_xS_MASK)
+#define ESAI_xSMB_xS(v)		(((v) >> ESAI_xSMA_xS_WIDTH) & ESAI_xSMB_xS_MASK)
 
 /* Port C Direction Register -- REG_ESAI_PRRC 0xF8 */
 #define ESAI_PRRC_PDC_SHIFT	0
diff --git a/sound/soc/fsl/imx-mc13783.c b/sound/soc/fsl/imx-mc13783.c
index 79cee78..a2fd732 100644
--- a/sound/soc/fsl/imx-mc13783.c
+++ b/sound/soc/fsl/imx-mc13783.c
@@ -160,7 +160,6 @@
 	.driver = {
 		.name = "imx_mc13783",
 		.owner = THIS_MODULE,
-		.pm = &snd_soc_pm_ops,
 	},
 	.probe = imx_mc13783_probe,
 	.remove = imx_mc13783_remove
diff --git a/sound/soc/fsl/imx-sgtl5000.c b/sound/soc/fsl/imx-sgtl5000.c
index f2beae7..1cb22dd 100644
--- a/sound/soc/fsl/imx-sgtl5000.c
+++ b/sound/soc/fsl/imx-sgtl5000.c
@@ -33,8 +33,7 @@
 
 static int imx_sgtl5000_dai_init(struct snd_soc_pcm_runtime *rtd)
 {
-	struct imx_sgtl5000_data *data = container_of(rtd->card,
-					struct imx_sgtl5000_data, card);
+	struct imx_sgtl5000_data *data = snd_soc_card_get_drvdata(rtd->card);
 	struct device *dev = rtd->card->dev;
 	int ret;
 
@@ -159,13 +158,15 @@
 	data->card.dapm_widgets = imx_sgtl5000_dapm_widgets;
 	data->card.num_dapm_widgets = ARRAY_SIZE(imx_sgtl5000_dapm_widgets);
 
+	platform_set_drvdata(pdev, &data->card);
+	snd_soc_card_set_drvdata(&data->card, data);
+
 	ret = devm_snd_soc_register_card(&pdev->dev, &data->card);
 	if (ret) {
 		dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret);
 		goto fail;
 	}
 
-	platform_set_drvdata(pdev, data);
 	of_node_put(ssi_np);
 	of_node_put(codec_np);
 
@@ -184,7 +185,8 @@
 
 static int imx_sgtl5000_remove(struct platform_device *pdev)
 {
-	struct imx_sgtl5000_data *data = platform_get_drvdata(pdev);
+	struct snd_soc_card *card = platform_get_drvdata(pdev);
+	struct imx_sgtl5000_data *data = snd_soc_card_get_drvdata(card);
 
 	clk_put(data->codec_clk);
 
diff --git a/sound/soc/fsl/imx-wm8962.c b/sound/soc/fsl/imx-wm8962.c
index 3fd76bc..3a3d17c 100644
--- a/sound/soc/fsl/imx-wm8962.c
+++ b/sound/soc/fsl/imx-wm8962.c
@@ -71,7 +71,7 @@
 {
 	struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai;
 	struct imx_priv *priv = &card_priv;
-	struct imx_wm8962_data *data = platform_get_drvdata(priv->pdev);
+	struct imx_wm8962_data *data = snd_soc_card_get_drvdata(card);
 	struct device *dev = &priv->pdev->dev;
 	unsigned int pll_out;
 	int ret;
@@ -137,7 +137,7 @@
 {
 	struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai;
 	struct imx_priv *priv = &card_priv;
-	struct imx_wm8962_data *data = platform_get_drvdata(priv->pdev);
+	struct imx_wm8962_data *data = snd_soc_card_get_drvdata(card);
 	struct device *dev = &priv->pdev->dev;
 	int ret;
 
@@ -264,13 +264,15 @@
 	data->card.late_probe = imx_wm8962_late_probe;
 	data->card.set_bias_level = imx_wm8962_set_bias_level;
 
+	platform_set_drvdata(pdev, &data->card);
+	snd_soc_card_set_drvdata(&data->card, data);
+
 	ret = devm_snd_soc_register_card(&pdev->dev, &data->card);
 	if (ret) {
 		dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret);
 		goto clk_fail;
 	}
 
-	platform_set_drvdata(pdev, data);
 	of_node_put(ssi_np);
 	of_node_put(codec_np);
 
@@ -289,7 +291,8 @@
 
 static int imx_wm8962_remove(struct platform_device *pdev)
 {
-	struct imx_wm8962_data *data = platform_get_drvdata(pdev);
+	struct snd_soc_card *card = platform_get_drvdata(pdev);
+	struct imx_wm8962_data *data = snd_soc_card_get_drvdata(card);
 
 	if (!IS_ERR(data->codec_clk))
 		clk_disable_unprepare(data->codec_clk);
diff --git a/sound/soc/samsung/Kconfig b/sound/soc/samsung/Kconfig
index 454f41c..3507574 100644
--- a/sound/soc/samsung/Kconfig
+++ b/sound/soc/samsung/Kconfig
@@ -59,7 +59,7 @@
 	select SND_SOC_WM8750
 	select SND_S3C2412_SOC_I2S
 	help
-	  Sat Y if you want to add support for SoC audio on the Jive.
+	  Say Y if you want to add support for SoC audio on the Jive.
 
 config SND_SOC_SAMSUNG_SMDK_WM8580
 	tristate "SoC I2S Audio support for WM8580 on SMDK"
@@ -145,11 +145,11 @@
 
 config SND_SOC_SAMSUNG_SMDK_WM9713
 	tristate "SoC AC97 Audio support for SMDK with WM9713"
-	depends on SND_SOC_SAMSUNG && (MACH_SMDK6410 || MACH_SMDKC100 || MACH_SMDKV210 || MACH_SMDKC110 || MACH_SMDKV310 || MACH_SMDKC210)
+	depends on SND_SOC_SAMSUNG && (MACH_SMDK6410 || MACH_SMDKC100 || MACH_SMDKV210 || MACH_SMDKC110)
 	select SND_SOC_WM9713
 	select SND_SAMSUNG_AC97
 	help
-	  Sat Y if you want to add support for SoC audio on the SMDK.
+	  Say Y if you want to add support for SoC audio on the SMDK.
 
 config SND_SOC_SMARTQ
 	tristate "SoC I2S Audio support for SmartQ board"
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index dc8ff13..b9dc6ac 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -1218,7 +1218,7 @@
 			ret = regulator_allow_bypass(w->regulator, false);
 			if (ret != 0)
 				dev_warn(w->dapm->dev,
-					 "ASoC: Failed to bypass %s: %d\n",
+					 "ASoC: Failed to unbypass %s: %d\n",
 					 w->name, ret);
 		}
 
@@ -1228,7 +1228,7 @@
 			ret = regulator_allow_bypass(w->regulator, true);
 			if (ret != 0)
 				dev_warn(w->dapm->dev,
-					 "ASoC: Failed to unbypass %s: %d\n",
+					 "ASoC: Failed to bypass %s: %d\n",
 					 w->name, ret);
 		}
 
@@ -3210,15 +3210,11 @@
 	struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
 	const char *pin = (const char *)kcontrol->private_value;
 
-	mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
-
 	if (ucontrol->value.integer.value[0])
 		snd_soc_dapm_enable_pin(&card->dapm, pin);
 	else
 		snd_soc_dapm_disable_pin(&card->dapm, pin);
 
-	mutex_unlock(&card->dapm_mutex);
-
 	snd_soc_dapm_sync(&card->dapm);
 	return 0;
 }
@@ -3248,7 +3244,7 @@
 			ret = regulator_allow_bypass(w->regulator, true);
 			if (ret != 0)
 				dev_warn(w->dapm->dev,
-					 "ASoC: Failed to unbypass %s: %d\n",
+					 "ASoC: Failed to bypass %s: %d\n",
 					 w->name, ret);
 		}
 		break;
@@ -3767,22 +3763,84 @@
 }
 
 /**
+ * snd_soc_dapm_enable_pin_unlocked - enable pin.
+ * @dapm: DAPM context
+ * @pin: pin name
+ *
+ * Enables input/output pin and its parents or children widgets iff there is
+ * a valid audio route and active audio stream.
+ *
+ * Requires external locking.
+ *
+ * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
+ * do any widget power switching.
+ */
+int snd_soc_dapm_enable_pin_unlocked(struct snd_soc_dapm_context *dapm,
+				   const char *pin)
+{
+	return snd_soc_dapm_set_pin(dapm, pin, 1);
+}
+EXPORT_SYMBOL_GPL(snd_soc_dapm_enable_pin_unlocked);
+
+/**
  * snd_soc_dapm_enable_pin - enable pin.
  * @dapm: DAPM context
  * @pin: pin name
  *
  * Enables input/output pin and its parents or children widgets iff there is
  * a valid audio route and active audio stream.
+ *
  * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
  * do any widget power switching.
  */
 int snd_soc_dapm_enable_pin(struct snd_soc_dapm_context *dapm, const char *pin)
 {
-	return snd_soc_dapm_set_pin(dapm, pin, 1);
+	int ret;
+
+	mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
+
+	ret = snd_soc_dapm_set_pin(dapm, pin, 1);
+
+	mutex_unlock(&dapm->card->dapm_mutex);
+
+	return ret;
 }
 EXPORT_SYMBOL_GPL(snd_soc_dapm_enable_pin);
 
 /**
+ * snd_soc_dapm_force_enable_pin_unlocked - force a pin to be enabled
+ * @dapm: DAPM context
+ * @pin: pin name
+ *
+ * Enables input/output pin regardless of any other state.  This is
+ * intended for use with microphone bias supplies used in microphone
+ * jack detection.
+ *
+ * Requires external locking.
+ *
+ * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
+ * do any widget power switching.
+ */
+int snd_soc_dapm_force_enable_pin_unlocked(struct snd_soc_dapm_context *dapm,
+					 const char *pin)
+{
+	struct snd_soc_dapm_widget *w = dapm_find_widget(dapm, pin, true);
+
+	if (!w) {
+		dev_err(dapm->dev, "ASoC: unknown pin %s\n", pin);
+		return -EINVAL;
+	}
+
+	dev_dbg(w->dapm->dev, "ASoC: force enable pin %s\n", pin);
+	w->connected = 1;
+	w->force = 1;
+	dapm_mark_dirty(w, "force enable");
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(snd_soc_dapm_force_enable_pin_unlocked);
+
+/**
  * snd_soc_dapm_force_enable_pin - force a pin to be enabled
  * @dapm: DAPM context
  * @pin: pin name
@@ -3797,39 +3855,86 @@
 int snd_soc_dapm_force_enable_pin(struct snd_soc_dapm_context *dapm,
 				  const char *pin)
 {
-	struct snd_soc_dapm_widget *w = dapm_find_widget(dapm, pin, true);
+	int ret;
 
-	if (!w) {
-		dev_err(dapm->dev, "ASoC: unknown pin %s\n", pin);
-		return -EINVAL;
-	}
+	mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
 
-	dev_dbg(w->dapm->dev, "ASoC: force enable pin %s\n", pin);
-	w->connected = 1;
-	w->force = 1;
-	dapm_mark_dirty(w, "force enable");
+	ret = snd_soc_dapm_force_enable_pin_unlocked(dapm, pin);
 
-	return 0;
+	mutex_unlock(&dapm->card->dapm_mutex);
+
+	return ret;
 }
 EXPORT_SYMBOL_GPL(snd_soc_dapm_force_enable_pin);
 
 /**
+ * snd_soc_dapm_disable_pin_unlocked - disable pin.
+ * @dapm: DAPM context
+ * @pin: pin name
+ *
+ * Disables input/output pin and its parents or children widgets.
+ *
+ * Requires external locking.
+ *
+ * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
+ * do any widget power switching.
+ */
+int snd_soc_dapm_disable_pin_unlocked(struct snd_soc_dapm_context *dapm,
+				    const char *pin)
+{
+	return snd_soc_dapm_set_pin(dapm, pin, 0);
+}
+EXPORT_SYMBOL_GPL(snd_soc_dapm_disable_pin_unlocked);
+
+/**
  * snd_soc_dapm_disable_pin - disable pin.
  * @dapm: DAPM context
  * @pin: pin name
  *
  * Disables input/output pin and its parents or children widgets.
+ *
  * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
  * do any widget power switching.
  */
 int snd_soc_dapm_disable_pin(struct snd_soc_dapm_context *dapm,
 			     const char *pin)
 {
-	return snd_soc_dapm_set_pin(dapm, pin, 0);
+	int ret;
+
+	mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
+
+	ret = snd_soc_dapm_set_pin(dapm, pin, 0);
+
+	mutex_unlock(&dapm->card->dapm_mutex);
+
+	return ret;
 }
 EXPORT_SYMBOL_GPL(snd_soc_dapm_disable_pin);
 
 /**
+ * snd_soc_dapm_nc_pin_unlocked - permanently disable pin.
+ * @dapm: DAPM context
+ * @pin: pin name
+ *
+ * Marks the specified pin as being not connected, disabling it along
+ * any parent or child widgets.  At present this is identical to
+ * snd_soc_dapm_disable_pin() but in future it will be extended to do
+ * additional things such as disabling controls which only affect
+ * paths through the pin.
+ *
+ * Requires external locking.
+ *
+ * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
+ * do any widget power switching.
+ */
+int snd_soc_dapm_nc_pin_unlocked(struct snd_soc_dapm_context *dapm,
+			       const char *pin)
+{
+	return snd_soc_dapm_set_pin(dapm, pin, 0);
+}
+EXPORT_SYMBOL_GPL(snd_soc_dapm_nc_pin_unlocked);
+
+/**
  * snd_soc_dapm_nc_pin - permanently disable pin.
  * @dapm: DAPM context
  * @pin: pin name
@@ -3845,7 +3950,15 @@
  */
 int snd_soc_dapm_nc_pin(struct snd_soc_dapm_context *dapm, const char *pin)
 {
-	return snd_soc_dapm_set_pin(dapm, pin, 0);
+	int ret;
+
+	mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
+
+	ret = snd_soc_dapm_set_pin(dapm, pin, 0);
+
+	mutex_unlock(&dapm->card->dapm_mutex);
+
+	return ret;
 }
 EXPORT_SYMBOL_GPL(snd_soc_dapm_nc_pin);
 
diff --git a/sound/soc/txx9/txx9aclc-ac97.c b/sound/soc/txx9/txx9aclc-ac97.c
index e0305a1..9edd68d 100644
--- a/sound/soc/txx9/txx9aclc-ac97.c
+++ b/sound/soc/txx9/txx9aclc-ac97.c
@@ -183,14 +183,16 @@
 	irq = platform_get_irq(pdev, 0);
 	if (irq < 0)
 		return irq;
+
+	drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata), GFP_KERNEL);
+	if (!drvdata)
+		return -ENOMEM;
+
 	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	drvdata->base = devm_ioremap_resource(&pdev->dev, r);
 	if (IS_ERR(drvdata->base))
 		return PTR_ERR(drvdata->base);
 
-	drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata), GFP_KERNEL);
-	if (!drvdata)
-		return -ENOMEM;
 	platform_set_drvdata(pdev, drvdata);
 	drvdata->physbase = r->start;
 	if (sizeof(drvdata->physbase) > sizeof(r->start) &&
diff --git a/sound/usb/mixer_maps.c b/sound/usb/mixer_maps.c
index 32af6b7..d1d72ff 100644
--- a/sound/usb/mixer_maps.c
+++ b/sound/usb/mixer_maps.c
@@ -328,6 +328,11 @@
 	{}
 };
 
+static const struct usbmix_name_map kef_x300a_map[] = {
+	{ 10, NULL }, /* firmware locks up (?) when we try to access this FU */
+	{ 0 }
+};
+
 /*
  * Control map entries
  */
@@ -419,6 +424,10 @@
 		.id = USB_ID(0x200c, 0x1018),
 		.map = ebox44_map,
 	},
+	{
+		.id = USB_ID(0x27ac, 0x1000),
+		.map = kef_x300a_map,
+	},
 	{ 0 } /* terminator */
 };
 
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 3c53ec2..02f985f 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -113,14 +113,16 @@
 	if (!he)
 		return -ENOMEM;
 
-	err = hist_entry__inc_addr_samples(he, evsel->idx, al->addr);
-	if (err)
-		goto out;
+	if (ui__has_annotation()) {
+		err = hist_entry__inc_addr_samples(he, evsel->idx, al->addr);
+		if (err)
+			goto out;
 
-	mx = he->mem_info;
-	err = addr_map_symbol__inc_samples(&mx->daddr, evsel->idx);
-	if (err)
-		goto out;
+		mx = he->mem_info;
+		err = addr_map_symbol__inc_samples(&mx->daddr, evsel->idx);
+		if (err)
+			goto out;
+	}
 
 	evsel->hists.stats.total_period += cost;
 	hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE);
@@ -164,14 +166,18 @@
 		he = __hists__add_entry(&evsel->hists, al, parent, &bi[i], NULL,
 					1, 1, 0);
 		if (he) {
-			bx = he->branch_info;
-			err = addr_map_symbol__inc_samples(&bx->from, evsel->idx);
-			if (err)
-				goto out;
+			if (ui__has_annotation()) {
+				bx = he->branch_info;
+				err = addr_map_symbol__inc_samples(&bx->from,
+								   evsel->idx);
+				if (err)
+					goto out;
 
-			err = addr_map_symbol__inc_samples(&bx->to, evsel->idx);
-			if (err)
-				goto out;
+				err = addr_map_symbol__inc_samples(&bx->to,
+								   evsel->idx);
+				if (err)
+					goto out;
+			}
 
 			evsel->hists.stats.total_period += 1;
 			hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE);
@@ -205,7 +211,9 @@
 	if (err)
 		goto out;
 
-	err = hist_entry__inc_addr_samples(he, evsel->idx, al->addr);
+	if (ui__has_annotation())
+		err = hist_entry__inc_addr_samples(he, evsel->idx, al->addr);
+
 	evsel->hists.stats.total_period += sample->period;
 	hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE);
 out:
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 76cd510..5f989a7 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -176,7 +176,7 @@
 {
 	struct annotation *notes;
 	struct symbol *sym;
-	int err;
+	int err = 0;
 
 	if (he == NULL || he->ms.sym == NULL ||
 	    ((top->sym_filter_entry == NULL ||
@@ -190,7 +190,9 @@
 		return;
 
 	ip = he->ms.map->map_ip(he->ms.map, ip);
-	err = hist_entry__inc_addr_samples(he, counter, ip);
+
+	if (ui__has_annotation())
+		err = hist_entry__inc_addr_samples(he, counter, ip);
 
 	pthread_mutex_unlock(&notes->lock);
 
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 896f270..6aa6fb6 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -37,6 +37,10 @@
 # define MADV_UNMERGEABLE	13
 #endif
 
+#ifndef EFD_SEMAPHORE
+# define EFD_SEMAPHORE		1
+#endif
+
 struct tp_field {
 	int offset;
 	union {
@@ -279,6 +283,11 @@
 
 #define SCA_STRARRAY syscall_arg__scnprintf_strarray
 
+#if defined(__i386__) || defined(__x86_64__)
+/*
+ * FIXME: Make this available to all arches as soon as the ioctl beautifier
+ * 	  gets rewritten to support all arches.
+ */
 static size_t syscall_arg__scnprintf_strhexarray(char *bf, size_t size,
 						 struct syscall_arg *arg)
 {
@@ -286,6 +295,7 @@
 }
 
 #define SCA_STRHEXARRAY syscall_arg__scnprintf_strhexarray
+#endif /* defined(__i386__) || defined(__x86_64__) */
 
 static size_t syscall_arg__scnprintf_fd(char *bf, size_t size,
 					struct syscall_arg *arg);
@@ -839,6 +849,10 @@
 
 #define SCA_SIGNUM syscall_arg__scnprintf_signum
 
+#if defined(__i386__) || defined(__x86_64__)
+/*
+ * FIXME: Make this available to all arches.
+ */
 #define TCGETS		0x5401
 
 static const char *tioctls[] = {
@@ -860,6 +874,7 @@
 };
 
 static DEFINE_STRARRAY_OFFSET(tioctls, 0x5401);
+#endif /* defined(__i386__) || defined(__x86_64__) */
 
 #define STRARRAY(arg, name, array) \
 	  .arg_scnprintf = { [arg] = SCA_STRARRAY, }, \
@@ -941,9 +956,16 @@
 	{ .name	    = "getrlimit",  .errmsg = true, STRARRAY(0, resource, rlimit_resources), },
 	{ .name	    = "ioctl",	    .errmsg = true,
 	  .arg_scnprintf = { [0] = SCA_FD, /* fd */ 
+#if defined(__i386__) || defined(__x86_64__)
+/*
+ * FIXME: Make this available to all arches.
+ */
 			     [1] = SCA_STRHEXARRAY, /* cmd */
 			     [2] = SCA_HEX, /* arg */ },
 	  .arg_parm	 = { [1] = &strarray__tioctls, /* cmd */ }, },
+#else
+			     [2] = SCA_HEX, /* arg */ }, },
+#endif
 	{ .name	    = "kill",	    .errmsg = true,
 	  .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
 	{ .name	    = "linkat",	    .errmsg = true,
diff --git a/tools/perf/config/Makefile b/tools/perf/config/Makefile
index c48d449..0331ea2 100644
--- a/tools/perf/config/Makefile
+++ b/tools/perf/config/Makefile
@@ -478,7 +478,7 @@
 endif
 
 ifeq ($(feature-libbfd), 1)
-  EXTLIBS += -lbfd
+  EXTLIBS += -lbfd -lz -liberty
 endif
 
 ifdef NO_DEMANGLE
diff --git a/tools/perf/config/feature-checks/Makefile b/tools/perf/config/feature-checks/Makefile
index 12e5513..523b7bc 100644
--- a/tools/perf/config/feature-checks/Makefile
+++ b/tools/perf/config/feature-checks/Makefile
@@ -121,7 +121,7 @@
 	$(BUILD) $(FLAGS_PYTHON_EMBED)
 
 test-libbfd.bin:
-	$(BUILD) -DPACKAGE='"perf"' -lbfd -ldl
+	$(BUILD) -DPACKAGE='"perf"' -lbfd -lz -liberty -ldl
 
 test-liberty.bin:
 	$(CC) -o $(OUTPUT)$@ test-libbfd.c -DPACKAGE='"perf"' -lbfd -ldl -liberty
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index 469eb67..3aa555f 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -8,6 +8,8 @@
  */
 
 #include "util.h"
+#include "ui/ui.h"
+#include "sort.h"
 #include "build-id.h"
 #include "color.h"
 #include "cache.h"
@@ -489,7 +491,7 @@
 {
 	struct annotation *notes;
 
-	if (sym == NULL || use_browser != 1 || !sort__has_sym)
+	if (sym == NULL)
 		return 0;
 
 	notes = symbol__annotation(sym);
@@ -1399,3 +1401,8 @@
 {
 	return symbol__annotate(he->ms.sym, he->ms.map, privsize);
 }
+
+bool ui__has_annotation(void)
+{
+	return use_browser == 1 && sort__has_sym;
+}
diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h
index b2aef59..56ad4f5 100644
--- a/tools/perf/util/annotate.h
+++ b/tools/perf/util/annotate.h
@@ -151,6 +151,8 @@
 void symbol__annotate_decay_histogram(struct symbol *sym, int evidx);
 void disasm__purge(struct list_head *head);
 
+bool ui__has_annotation(void);
+
 int symbol__tty_annotate(struct symbol *sym, struct map *map,
 			 struct perf_evsel *evsel, bool print_lines,
 			 bool full_paths, int min_pcnt, int max_lines);
diff --git a/tools/perf/util/include/linux/bitops.h b/tools/perf/util/include/linux/bitops.h
index 45cf10a..dadfa7e 100644
--- a/tools/perf/util/include/linux/bitops.h
+++ b/tools/perf/util/include/linux/bitops.h
@@ -87,13 +87,15 @@
 	return num;
 }
 
+typedef const unsigned long __attribute__((__may_alias__)) long_alias_t;
+
 /*
  * Find the first set bit in a memory region.
  */
 static inline unsigned long
 find_first_bit(const unsigned long *addr, unsigned long size)
 {
-	const unsigned long *p = addr;
+	long_alias_t *p = (long_alias_t *) addr;
 	unsigned long result = 0;
 	unsigned long tmp;
 
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index d248fca..1e15df1 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -1091,12 +1091,12 @@
 static bool is_event_supported(u8 type, unsigned config)
 {
 	bool ret = true;
+	int open_return;
 	struct perf_evsel *evsel;
 	struct perf_event_attr attr = {
 		.type = type,
 		.config = config,
 		.disabled = 1,
-		.exclude_kernel = 1,
 	};
 	struct {
 		struct thread_map map;
@@ -1108,7 +1108,20 @@
 
 	evsel = perf_evsel__new(&attr);
 	if (evsel) {
-		ret = perf_evsel__open(evsel, NULL, &tmap.map) >= 0;
+		open_return = perf_evsel__open(evsel, NULL, &tmap.map);
+		ret = open_return >= 0;
+
+		if (open_return == -EACCES) {
+			/*
+			 * This happens if the paranoid value
+			 * /proc/sys/kernel/perf_event_paranoid is set to 2
+			 * Re-run with exclude_kernel set; we don't do that
+			 * by default as some ARM machines do not support it.
+			 *
+			 */
+			evsel->attr.exclude_kernel = 1;
+			ret = perf_evsel__open(evsel, NULL, &tmap.map) >= 0;
+		}
 		perf_evsel__delete(evsel);
 	}
 
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index a8a9b6c..d8b048c 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -336,8 +336,8 @@
 		return ret;
 
 	for (i = 0; i < ntevs && ret >= 0; i++) {
+		/* point.address is the addres of point.symbol + point.offset */
 		offset = tevs[i].point.address - stext;
-		offset += tevs[i].point.offset;
 		tevs[i].point.offset = 0;
 		zfree(&tevs[i].point.symbol);
 		ret = e_snprintf(buf, 32, "0x%lx", offset);
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 0b39a48..5da6ce7 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -1008,6 +1008,12 @@
 		if (err == 0)
 			perf_session__set_id_hdr_size(session);
 		return err;
+	case PERF_RECORD_HEADER_EVENT_TYPE:
+		/*
+		 * Depreceated, but we need to handle it for sake
+		 * of old data files create in pipe mode.
+		 */
+		return 0;
 	case PERF_RECORD_HEADER_TRACING_DATA:
 		/* setup for reading amidst mmap */
 		lseek(fd, file_offset, SEEK_SET);
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index a9d758a..e89afc0 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -1336,6 +1336,8 @@
 
 			if (syms_ss && runtime_ss)
 				break;
+		} else {
+			symsrc__destroy(ss);
 		}
 
 	}