linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/5] add bus driver for Unisys s-Par paravirtualized devices to arch/x86
@ 2016-05-17  7:27 David Kershner
  2016-05-17  7:27 ` [PATCH 1/5] staging: unisys: Move vbushelper.h to visorbus directory David Kershner
                   ` (5 more replies)
  0 siblings, 6 replies; 15+ messages in thread
From: David Kershner @ 2016-05-17  7:27 UTC (permalink / raw)
  To: corbet, tglx, mingo, hpa, david.kershner, gregkh, erik.arfvidson,
	timothy.sell, hofrat, dzickus, jes.sorensen, alexander.curtin,
	janani.rvchndrn, sudipm.mukherjee, prarit, david.binder, nhorman,
	dan.j.williams, linux-kernel, linux-doc, driverdev-devel,
	sparmaintainer

This patchset moves the visorbus driver (fromdrivers/staging/unisys/visorbus)
and its dependent headers files (from drivers/staging/unisys/include)
out of staging into the main kernel tree.

The visorbus driver is a bus driver for various paravirtualized devices
presented within a Unisys s-Par guest environment.  Drivers for these
devices are also currently present under drivers/staging/unisys/, which we
intend to also move out of staging immediately after visorbus.  All of
these other drivers are dependent upon visorbus and the include directory,
which is why we would like to move these first.

Our initial consultations with various members of the community have led us
to the conclusion that the most appropriate locations for these is:
    arch/x86/visorbus/       (driver)
    include/linux/visorbus/  (header files)

The rationale is that visorbus is dependent on x86-64 architecture.

David Kershner (5):
  staging: unisys: Move vbushelper.h to visorbus directory
  include: linux: visorbus: Add visorbus to include/linux directory
  Documentation: Move visorbus documentation from staging to
    Documentation/
  staging: unisys: visorbus: Have visorbus use include/linux/visorbus
  arch: x86: add visorbus directory to arch/x86

 Documentation/ABI/stable/sysfs-bus-visorbus        |   89 +
 Documentation/visorbus.txt                         |  337 +++
 arch/x86/Kbuild                                    |    3 +
 arch/x86/Kconfig                                   |    2 +
 arch/x86/visorbus/Kconfig                          |   14 +
 arch/x86/visorbus/Makefile                         |    8 +
 arch/x86/visorbus/controlvmchannel.h               |  485 ++++
 arch/x86/visorbus/controlvmcompletionstatus.h      |  101 +
 arch/x86/visorbus/iovmcall_gnuc.h                  |   48 +
 arch/x86/visorbus/periodic_work.c                  |  203 ++
 arch/x86/visorbus/vbuschannel.h                    |   95 +
 arch/x86/visorbus/vbusdeviceinfo.h                 |  213 ++
 arch/x86/visorbus/vbushelper.h                     |   46 +
 arch/x86/visorbus/visorbus_main.c                  | 1344 +++++++++++
 arch/x86/visorbus/visorbus_private.h               |   68 +
 arch/x86/visorbus/visorchannel.c                   |  635 ++++++
 arch/x86/visorbus/visorchipset.c                   | 2355 ++++++++++++++++++++
 arch/x86/visorbus/vmcallinterface.h                |   91 +
 .../Documentation/ABI/sysfs-platform-visorchipset  |   89 -
 drivers/staging/unisys/Documentation/overview.txt  |  337 ---
 drivers/staging/unisys/Kconfig                     |    1 -
 drivers/staging/unisys/Makefile                    |    1 -
 drivers/staging/unisys/include/vbushelper.h        |   46 -
 drivers/staging/unisys/visorbus/Kconfig            |   14 -
 drivers/staging/unisys/visorbus/Makefile           |   12 -
 drivers/staging/unisys/visorbus/controlvmchannel.h |  485 ----
 .../unisys/visorbus/controlvmcompletionstatus.h    |  101 -
 drivers/staging/unisys/visorbus/iovmcall_gnuc.h    |   48 -
 drivers/staging/unisys/visorbus/periodic_work.c    |  204 --
 drivers/staging/unisys/visorbus/vbuschannel.h      |   94 -
 drivers/staging/unisys/visorbus/vbusdeviceinfo.h   |  213 --
 drivers/staging/unisys/visorbus/visorbus_main.c    | 1344 -----------
 drivers/staging/unisys/visorbus/visorbus_private.h |   68 -
 drivers/staging/unisys/visorbus/visorchannel.c     |  635 ------
 drivers/staging/unisys/visorbus/visorchipset.c     | 2355 --------------------
 drivers/staging/unisys/visorbus/vmcallinterface.h  |   92 -
 include/linux/visorbus/channel.h                   |  572 +++++
 include/linux/visorbus/channel_guid.h              |   55 +
 include/linux/visorbus/diagchannel.h               |   38 +
 include/linux/visorbus/guestlinuxdebug.h           |  180 ++
 include/linux/visorbus/iochannel.h                 |  571 +++++
 include/linux/visorbus/periodic_work.h             |   40 +
 include/linux/visorbus/vbushelper.h                |   46 +
 include/linux/visorbus/version.h                   |   45 +
 include/linux/visorbus/visorbus.h                  |  234 ++
 45 files changed, 7918 insertions(+), 6139 deletions(-)
 create mode 100644 Documentation/ABI/stable/sysfs-bus-visorbus
 create mode 100644 Documentation/visorbus.txt
 create mode 100644 arch/x86/visorbus/Kconfig
 create mode 100644 arch/x86/visorbus/Makefile
 create mode 100644 arch/x86/visorbus/controlvmchannel.h
 create mode 100644 arch/x86/visorbus/controlvmcompletionstatus.h
 create mode 100644 arch/x86/visorbus/iovmcall_gnuc.h
 create mode 100644 arch/x86/visorbus/periodic_work.c
 create mode 100644 arch/x86/visorbus/vbuschannel.h
 create mode 100644 arch/x86/visorbus/vbusdeviceinfo.h
 create mode 100644 arch/x86/visorbus/vbushelper.h
 create mode 100644 arch/x86/visorbus/visorbus_main.c
 create mode 100644 arch/x86/visorbus/visorbus_private.h
 create mode 100644 arch/x86/visorbus/visorchannel.c
 create mode 100644 arch/x86/visorbus/visorchipset.c
 create mode 100644 arch/x86/visorbus/vmcallinterface.h
 delete mode 100644 drivers/staging/unisys/Documentation/ABI/sysfs-platform-visorchipset
 delete mode 100644 drivers/staging/unisys/Documentation/overview.txt
 delete mode 100644 drivers/staging/unisys/include/vbushelper.h
 delete mode 100644 drivers/staging/unisys/visorbus/Kconfig
 delete mode 100644 drivers/staging/unisys/visorbus/Makefile
 delete mode 100644 drivers/staging/unisys/visorbus/controlvmchannel.h
 delete mode 100644 drivers/staging/unisys/visorbus/controlvmcompletionstatus.h
 delete mode 100644 drivers/staging/unisys/visorbus/iovmcall_gnuc.h
 delete mode 100644 drivers/staging/unisys/visorbus/periodic_work.c
 delete mode 100644 drivers/staging/unisys/visorbus/vbuschannel.h
 delete mode 100644 drivers/staging/unisys/visorbus/vbusdeviceinfo.h
 delete mode 100644 drivers/staging/unisys/visorbus/visorbus_main.c
 delete mode 100644 drivers/staging/unisys/visorbus/visorbus_private.h
 delete mode 100644 drivers/staging/unisys/visorbus/visorchannel.c
 delete mode 100644 drivers/staging/unisys/visorbus/visorchipset.c
 delete mode 100644 drivers/staging/unisys/visorbus/vmcallinterface.h
 create mode 100644 include/linux/visorbus/channel.h
 create mode 100644 include/linux/visorbus/channel_guid.h
 create mode 100644 include/linux/visorbus/diagchannel.h
 create mode 100644 include/linux/visorbus/guestlinuxdebug.h
 create mode 100644 include/linux/visorbus/iochannel.h
 create mode 100644 include/linux/visorbus/periodic_work.h
 create mode 100644 include/linux/visorbus/vbushelper.h
 create mode 100644 include/linux/visorbus/version.h
 create mode 100644 include/linux/visorbus/visorbus.h

-- 
1.9.1

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH 1/5] staging: unisys: Move vbushelper.h to visorbus directory
  2016-05-17  7:27 [PATCH 0/5] add bus driver for Unisys s-Par paravirtualized devices to arch/x86 David Kershner
@ 2016-05-17  7:27 ` David Kershner
  2016-05-17  7:27 ` [PATCH 2/5] include: linux: visorbus: Add visorbus to include/linux directory David Kershner
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 15+ messages in thread
From: David Kershner @ 2016-05-17  7:27 UTC (permalink / raw)
  To: corbet, tglx, mingo, hpa, david.kershner, gregkh, erik.arfvidson,
	timothy.sell, hofrat, dzickus, jes.sorensen, alexander.curtin,
	janani.rvchndrn, sudipm.mukherjee, prarit, david.binder, nhorman,
	dan.j.williams, linux-kernel, linux-doc, driverdev-devel,
	sparmaintainer

Only visorbus needs this header file so move it to visorbus
directory.

Signed-off-by: David Kershner <david.kershner@unisys.com>
---
 drivers/staging/unisys/include/vbushelper.h  | 46 ----------------------------
 drivers/staging/unisys/visorbus/vbushelper.h | 46 ++++++++++++++++++++++++++++
 2 files changed, 46 insertions(+), 46 deletions(-)
 delete mode 100644 drivers/staging/unisys/include/vbushelper.h
 create mode 100644 drivers/staging/unisys/visorbus/vbushelper.h

diff --git a/drivers/staging/unisys/include/vbushelper.h b/drivers/staging/unisys/include/vbushelper.h
deleted file mode 100644
index f1b6aac..0000000
--- a/drivers/staging/unisys/include/vbushelper.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/* vbushelper.h
- *
- * Copyright (C) 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__
-
-/* TARGET_HOSTNAME specified as -DTARGET_HOSTNAME=\"thename\" on the
- * command line
- */
-
-#define TARGET_HOSTNAME "linuxguest"
-
-static inline void bus_device_info_init(
-		struct ultra_vbus_deviceinfo *bus_device_info_ptr,
-		const char *dev_type, const char *drv_name,
-		const char *ver, const char *ver_tag)
-{
-	memset(bus_device_info_ptr, 0, sizeof(struct ultra_vbus_deviceinfo));
-	snprintf(bus_device_info_ptr->devtype,
-		 sizeof(bus_device_info_ptr->devtype),
-		 "%s", (dev_type) ? dev_type : "unknownType");
-	snprintf(bus_device_info_ptr->drvname,
-		 sizeof(bus_device_info_ptr->drvname),
-		 "%s", (drv_name) ? drv_name : "unknownDriver");
-	snprintf(bus_device_info_ptr->infostrs,
-		 sizeof(bus_device_info_ptr->infostrs), "%s\t%s\t%s",
-		 (ver) ? ver : "unknownVer",
-		 (ver_tag) ? ver_tag : "unknownVerTag",
-		 TARGET_HOSTNAME);
-}
-
-#endif
diff --git a/drivers/staging/unisys/visorbus/vbushelper.h b/drivers/staging/unisys/visorbus/vbushelper.h
new file mode 100644
index 0000000..f1b6aac
--- /dev/null
+++ b/drivers/staging/unisys/visorbus/vbushelper.h
@@ -0,0 +1,46 @@
+/* vbushelper.h
+ *
+ * Copyright (C) 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__
+
+/* TARGET_HOSTNAME specified as -DTARGET_HOSTNAME=\"thename\" on the
+ * command line
+ */
+
+#define TARGET_HOSTNAME "linuxguest"
+
+static inline void bus_device_info_init(
+		struct ultra_vbus_deviceinfo *bus_device_info_ptr,
+		const char *dev_type, const char *drv_name,
+		const char *ver, const char *ver_tag)
+{
+	memset(bus_device_info_ptr, 0, sizeof(struct ultra_vbus_deviceinfo));
+	snprintf(bus_device_info_ptr->devtype,
+		 sizeof(bus_device_info_ptr->devtype),
+		 "%s", (dev_type) ? dev_type : "unknownType");
+	snprintf(bus_device_info_ptr->drvname,
+		 sizeof(bus_device_info_ptr->drvname),
+		 "%s", (drv_name) ? drv_name : "unknownDriver");
+	snprintf(bus_device_info_ptr->infostrs,
+		 sizeof(bus_device_info_ptr->infostrs), "%s\t%s\t%s",
+		 (ver) ? ver : "unknownVer",
+		 (ver_tag) ? ver_tag : "unknownVerTag",
+		 TARGET_HOSTNAME);
+}
+
+#endif
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 2/5] include: linux: visorbus: Add visorbus to include/linux directory
  2016-05-17  7:27 [PATCH 0/5] add bus driver for Unisys s-Par paravirtualized devices to arch/x86 David Kershner
  2016-05-17  7:27 ` [PATCH 1/5] staging: unisys: Move vbushelper.h to visorbus directory David Kershner
@ 2016-05-17  7:27 ` David Kershner
  2016-05-17  7:27 ` [PATCH 3/5] Documentation: Move visorbus documentation from staging to Documentation/ David Kershner
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 15+ messages in thread
From: David Kershner @ 2016-05-17  7:27 UTC (permalink / raw)
  To: corbet, tglx, mingo, hpa, david.kershner, gregkh, erik.arfvidson,
	timothy.sell, hofrat, dzickus, jes.sorensen, alexander.curtin,
	janani.rvchndrn, sudipm.mukherjee, prarit, david.binder, nhorman,
	dan.j.williams, linux-kernel, linux-doc, driverdev-devel,
	sparmaintainer

Update include/linux to include the s-Par associated common include
header files needed for the s-Par visorbus.

Signed-off-by: David Kershner <david.kershner@unisys.com>
---
 include/linux/visorbus/channel.h         | 572 +++++++++++++++++++++++++++++++
 include/linux/visorbus/channel_guid.h    |  55 +++
 include/linux/visorbus/diagchannel.h     |  38 ++
 include/linux/visorbus/guestlinuxdebug.h | 180 ++++++++++
 include/linux/visorbus/iochannel.h       | 571 ++++++++++++++++++++++++++++++
 include/linux/visorbus/periodic_work.h   |  40 +++
 include/linux/visorbus/vbushelper.h      |  46 +++
 include/linux/visorbus/version.h         |  45 +++
 include/linux/visorbus/visorbus.h        | 234 +++++++++++++
 9 files changed, 1781 insertions(+)
 create mode 100644 include/linux/visorbus/channel.h
 create mode 100644 include/linux/visorbus/channel_guid.h
 create mode 100644 include/linux/visorbus/diagchannel.h
 create mode 100644 include/linux/visorbus/guestlinuxdebug.h
 create mode 100644 include/linux/visorbus/iochannel.h
 create mode 100644 include/linux/visorbus/periodic_work.h
 create mode 100644 include/linux/visorbus/vbushelper.h
 create mode 100644 include/linux/visorbus/version.h
 create mode 100644 include/linux/visorbus/visorbus.h

diff --git a/include/linux/visorbus/channel.h b/include/linux/visorbus/channel.h
new file mode 100644
index 0000000..db4e6b2
--- /dev/null
+++ b/include/linux/visorbus/channel.h
@@ -0,0 +1,572 @@
+/* Copyright (C) 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__
+
+#include <linux/types.h>
+#include <linux/io.h>
+#include <linux/uuid.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 abbreviated content
+ */
+#define __SUPERVISOR_CHANNEL_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
+
+#define ULTRA_CHANNEL_PROTOCOL_SIGNATURE  SIGNATURE_32('E', 'C', 'N', 'L')
+
+enum channel_serverstate {
+	CHANNELSRV_UNINITIALIZED = 0,	/* channel is in an undefined state */
+	CHANNELSRV_READY = 1	/* channel has been initialized by server */
+};
+
+enum channel_clientstate {
+	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 */
+};
+
+static inline const u8 *
+ULTRA_CHANNELCLI_STRING(u32 state)
+{
+	switch (state) {
+	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 SPAR_CHANNEL_SERVER_READY(ch) \
+	(readl(&(ch)->srv_state) == CHANNELSRV_READY)
+
+#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))
+
+/* 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)
+
+/* Common Channel Header */
+struct channel_header {
+	u64 signature;		/* Signature */
+	u32 legacy_state;	/* DEPRECATED - being replaced by */
+			/* SrvState, CliStateBoot, and CliStateOS below */
+	u32 header_size;	/* sizeof(struct channel_header) */
+	u64 size;		/* Total size of this channel in bytes */
+	u64 features;		/* Flags to modify behavior */
+	uuid_le chtype;		/* Channel type: data, bus, control, etc. */
+	u64 partition_handle;	/* ID of guest partition */
+	u64 handle;		/* Device number of this channel in client */
+	u64 ch_space_offset;	/* Offset in bytes to channel specific area */
+	u32 version_id;		/* struct channel_header Version ID */
+	u32 partition_index;	/* Index of guest partition */
+	uuid_le zone_uuid;	/* Guid of Channel's zone */
+	u32 cli_str_offset;	/* offset from channel header to
+				 * nul-terminated ClientString (0 if
+				 * ClientString not present)
+				 */
+	u32 cli_state_boot;	/* CHANNEL_CLIENTSTATE of pre-boot
+				 * EFI client of this channel
+				 */
+	u32 cmd_state_cli;	/* CHANNEL_COMMANDSTATE (overloaded in
+				 * Windows drivers, see ServerStateUp,
+				 * ServerStateDown, etc)
+				 */
+	u32 cli_state_os;	/* CHANNEL_CLIENTSTATE of Guest OS
+				 * client of this channel
+				 */
+	u32 ch_characteristic;	/* CHANNEL_CHARACTERISTIC_<xxx> */
+	u32 cmd_state_srv;	/* CHANNEL_COMMANDSTATE (overloaded in
+				 * Windows drivers, see ServerStateUp,
+				 * ServerStateDown, etc)
+				 */
+	u32 srv_state;		/* CHANNEL_SERVERSTATE */
+	u8 cli_error_boot;	/* bits to indicate err states for
+				 * boot clients, so err messages can
+				 * be throttled
+				 */
+	u8 cli_error_os;	/* 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 recover_channel;
+} __packed;
+
+#define ULTRA_CHANNEL_ENABLE_INTS (0x1ULL << 0)
+
+/* Subheader for the Signal Type variation of the Common Channel */
+struct signal_queue_header {
+	/* 1st cache line */
+	u32 version;		/* SIGNAL_QUEUE_HEADER Version ID */
+	u32 chtype;		/* Queue type: storage, network */
+	u64 size;		/* Total size of this queue in bytes */
+	u64 sig_base_offset;	/* Offset to signal queue area */
+	u64 features;		/* Flags to modify behavior */
+	u64 num_sent;		/* Total # of signals placed in this queue */
+	u64 num_overflows;	/* Total # of inserts failed due to
+				 * full queue
+				 */
+	u32 signal_size;	/* Total size of a signal for this queue */
+	u32 max_slots;		/* Max # of slots in queue, 1 slot is
+				 * always empty
+				 */
+	u32 max_signals;	/* Max # of signals in queue
+				 * (MaxSignalSlots-1)
+				 */
+	u32 head;		/* Queue head signal # */
+	/* 2nd cache line */
+	u64 num_received;	/* Total # of signals removed from this queue */
+	u32 tail;		/* Queue tail signal */
+	u32 reserved1;		/* Reserved field */
+	u64 reserved2;		/* Reserved field */
+	u64 client_queue;
+	u64 num_irq_received;	/* Total # of Interrupts received.  This
+				 * is incremented by the ISR in the
+				 * guest windows driver
+				 */
+	u64 num_empty;		/* Number of times that visor_signal_remove
+				 * 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 */
+} __packed;
+
+#define spar_signal_init(chan, QHDRFLD, QDATAFLD, QDATATYPE, ver, typ)	\
+	do {								\
+		memset(&chan->QHDRFLD, 0, sizeof(chan->QHDRFLD));	\
+		chan->QHDRFLD.version = ver;				\
+		chan->QHDRFLD.chtype = typ;				\
+		chan->QHDRFLD.size = sizeof(chan->QDATAFLD);		\
+		chan->QHDRFLD.signal_size = sizeof(QDATATYPE);		\
+		chan->QHDRFLD.sig_base_offset = (u64)(chan->QDATAFLD) -	\
+			(u64)(&chan->QHDRFLD);				\
+		chan->QHDRFLD.max_slots =				\
+			sizeof(chan->QDATAFLD) / sizeof(QDATATYPE);	\
+		chan->QHDRFLD.max_signals = chan->QHDRFLD.max_slots - 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
+spar_check_channel_client(void __iomem *ch,
+			  uuid_le expected_uuid,
+			  char *chname,
+			  u64 expected_min_bytes,
+			  u32 expected_version,
+			  u64 expected_signature)
+{
+	if (uuid_le_cmp(expected_uuid, NULL_UUID_LE) != 0) {
+		uuid_le guid;
+
+		memcpy_fromio(&guid,
+			      &((struct channel_header __iomem *)(ch))->chtype,
+			      sizeof(guid));
+		/* caller wants us to verify type GUID */
+		if (uuid_le_cmp(guid, expected_uuid) != 0) {
+			pr_err("Channel mismatch on channel=%s(%pUL) field=type expected=%pUL actual=%pUL\n",
+			       chname, &expected_uuid,
+			       &expected_uuid, &guid);
+			return 0;
+		}
+	}
+	if (expected_min_bytes > 0) {	/* verify channel size */
+		unsigned long long bytes =
+				readq(&((struct channel_header __iomem *)
+					(ch))->size);
+		if (bytes < expected_min_bytes) {
+			pr_err("Channel mismatch on channel=%s(%pUL) field=size expected=0x%-8.8Lx actual=0x%-8.8Lx\n",
+			       chname, &expected_uuid,
+			       (unsigned long long)expected_min_bytes, bytes);
+			return 0;
+		}
+	}
+	if (expected_version > 0) {	/* verify channel version */
+		unsigned long ver = readl(&((struct channel_header __iomem *)
+				    (ch))->version_id);
+		if (ver != expected_version) {
+			pr_err("Channel mismatch on channel=%s(%pUL) field=version expected=0x%-8.8lx actual=0x%-8.8lx\n",
+			       chname, &expected_uuid,
+			       (unsigned long)expected_version, ver);
+			return 0;
+		}
+	}
+	if (expected_signature > 0) {	/* verify channel signature */
+		unsigned long long sig =
+				readq(&((struct channel_header __iomem *)
+					(ch))->signature);
+		if (sig != expected_signature) {
+			pr_err("Channel mismatch on channel=%s(%pUL) field=signature expected=0x%-8.8llx actual=0x%-8.8llx\n",
+			       chname, &expected_uuid,
+			       expected_signature, sig);
+			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 spar_check_channel_server(uuid_le typeuuid, char *name,
+					    u64 expected_min_bytes,
+					    u64 actual_bytes)
+{
+	if (expected_min_bytes > 0)	/* verify channel size */
+		if (actual_bytes < expected_min_bytes) {
+			pr_err("Channel mismatch on channel=%s(%pUL) field=size expected=0x%-8.8llx actual=0x%-8.8llx\n",
+			       name, &typeuuid, expected_min_bytes,
+			       actual_bytes);
+			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
+spar_channel_client_acquire_os(void __iomem *ch, u8 *id)
+{
+	struct channel_header __iomem *hdr = ch;
+
+	if (readl(&hdr->cli_state_os) == CHANNELCLI_DISABLED) {
+		if ((readb(&hdr->cli_error_os)
+		     & ULTRA_CLIERROROS_THROTTLEMSG_DISABLED) == 0) {
+			/* we are NOT throttling this message */
+			writeb(readb(&hdr->cli_error_os) |
+			       ULTRA_CLIERROROS_THROTTLEMSG_DISABLED,
+			       &hdr->cli_error_os);
+			/* throttle until acquire successful */
+
+			pr_info("%s Channel StateTransition INVALID! - acquire failed because OS client DISABLED\n",
+				id);
+		}
+		return 0;
+	}
+	if ((readl(&hdr->cli_state_os) != CHANNELCLI_OWNED) &&
+	    (readl(&hdr->cli_state_boot) == CHANNELCLI_DISABLED)) {
+		/* Our competitor is DISABLED, so we can transition to OWNED */
+		pr_info("%s Channel StateTransition (%s) %s(%d)-->%s(%d)\n",
+			id, "cli_state_os",
+			ULTRA_CHANNELCLI_STRING(readl(&hdr->cli_state_os)),
+			readl(&hdr->cli_state_os),
+			ULTRA_CHANNELCLI_STRING(CHANNELCLI_OWNED),
+			CHANNELCLI_OWNED);
+		writel(CHANNELCLI_OWNED, &hdr->cli_state_os);
+		mb(); /* required for channel synch */
+	}
+	if (readl(&hdr->cli_state_os) == CHANNELCLI_OWNED) {
+		if (readb(&hdr->cli_error_os)) {
+			/* we are in an error msg throttling state;
+			 * come out of it
+			 */
+			pr_info("%s Channel OS client acquire now successful\n",
+				id);
+			writeb(0, &hdr->cli_error_os);
+		}
+		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 (readl(&hdr->cli_state_os) != CHANNELCLI_ATTACHED) {
+		if ((readb(&hdr->cli_error_os)
+		     & ULTRA_CLIERROROS_THROTTLEMSG_NOTATTACHED) == 0) {
+			/* we are NOT throttling this message */
+			writeb(readb(&hdr->cli_error_os) |
+			       ULTRA_CLIERROROS_THROTTLEMSG_NOTATTACHED,
+			       &hdr->cli_error_os);
+			/* throttle until acquire successful */
+			pr_info("%s Channel StateTransition INVALID! - acquire failed because OS client NOT ATTACHED (state=%s(%d))\n",
+				id, ULTRA_CHANNELCLI_STRING(
+						readl(&hdr->cli_state_os)),
+				readl(&hdr->cli_state_os));
+		}
+		return 0;
+	}
+	writel(CHANNELCLI_BUSY, &hdr->cli_state_os);
+	mb(); /* required for channel synch */
+	if (readl(&hdr->cli_state_boot) == CHANNELCLI_BUSY) {
+		if ((readb(&hdr->cli_error_os)
+		     & ULTRA_CLIERROROS_THROTTLEMSG_BUSY) == 0) {
+			/* we are NOT throttling this message */
+			writeb(readb(&hdr->cli_error_os) |
+			       ULTRA_CLIERROROS_THROTTLEMSG_BUSY,
+			       &hdr->cli_error_os);
+			/* throttle until acquire successful */
+			pr_info("%s Channel StateTransition failed - host OS acquire failed because boot BUSY\n",
+				id);
+		}
+		/* reset busy */
+		writel(CHANNELCLI_ATTACHED, &hdr->cli_state_os);
+		mb(); /* required for channel synch */
+		return 0;
+	}
+	if (readb(&hdr->cli_error_os)) {
+		/* we are in an error msg throttling state; come out of it */
+		pr_info("%s Channel OS client acquire now successful\n", id);
+		writeb(0, &hdr->cli_error_os);
+	}
+	return 1;
+}
+
+static inline void
+spar_channel_client_release_os(void __iomem *ch, u8 *id)
+{
+	struct channel_header __iomem *hdr = ch;
+
+	if (readb(&hdr->cli_error_os)) {
+		/* we are in an error msg throttling state; come out of it */
+		pr_info("%s Channel OS client error state cleared\n", id);
+		writeb(0, &hdr->cli_error_os);
+	}
+	if (readl(&hdr->cli_state_os) == CHANNELCLI_OWNED)
+		return;
+	if (readl(&hdr->cli_state_os) != CHANNELCLI_BUSY) {
+		pr_info("%s Channel StateTransition INVALID! - release failed because OS client NOT BUSY (state=%s(%d))\n",
+			id, ULTRA_CHANNELCLI_STRING(
+					readl(&hdr->cli_state_os)),
+			readl(&hdr->cli_state_os));
+		/* return; */
+	}
+	writel(CHANNELCLI_ATTACHED, &hdr->cli_state_os); /* 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 spar_signal_insert(struct channel_header __iomem *ch, u32 queue,
+				 void *sig);
+
+/*
+* 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 spar_signal_remove(struct channel_header __iomem *ch, u32 queue,
+				 void *sig);
+
+/*
+* 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 spar_signal_remove_all(struct channel_header *ch, u32 queue,
+				    void *sig);
+
+/*
+* 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 spar_signalqueue_empty(struct channel_header __iomem *ch,
+				     u32 queue);
+
+#endif
diff --git a/include/linux/visorbus/channel_guid.h b/include/linux/visorbus/channel_guid.h
new file mode 100644
index 0000000..17cb499
--- /dev/null
+++ b/include/linux/visorbus/channel_guid.h
@@ -0,0 +1,55 @@
+/* Copyright (C) 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
+ */
+
+/* {414815ed-c58c-11da-95a9-00e08161165f} */
+#define SPAR_VHBA_CHANNEL_PROTOCOL_UUID \
+		UUID_LE(0x414815ed, 0xc58c, 0x11da, \
+				0x95, 0xa9, 0x0, 0xe0, 0x81, 0x61, 0x16, 0x5f)
+static const uuid_le spar_vhba_channel_protocol_uuid =
+	SPAR_VHBA_CHANNEL_PROTOCOL_UUID;
+#define SPAR_VHBA_CHANNEL_PROTOCOL_UUID_STR \
+	"414815ed-c58c-11da-95a9-00e08161165f"
+
+/* {8cd5994d-c58e-11da-95a9-00e08161165f} */
+#define SPAR_VNIC_CHANNEL_PROTOCOL_UUID \
+		UUID_LE(0x8cd5994d, 0xc58e, 0x11da, \
+				0x95, 0xa9, 0x0, 0xe0, 0x81, 0x61, 0x16, 0x5f)
+static const uuid_le spar_vnic_channel_protocol_uuid =
+	SPAR_VNIC_CHANNEL_PROTOCOL_UUID;
+#define SPAR_VNIC_CHANNEL_PROTOCOL_UUID_STR \
+	"8cd5994d-c58e-11da-95a9-00e08161165f"
+
+/* {72120008-4AAB-11DC-8530-444553544200} */
+#define SPAR_SIOVM_UUID \
+		UUID_LE(0x72120008, 0x4AAB, 0x11DC, \
+				0x85, 0x30, 0x44, 0x45, 0x53, 0x54, 0x42, 0x00)
+static const uuid_le spar_siovm_uuid = SPAR_SIOVM_UUID;
+
+/* {5b52c5ac-e5f5-4d42-8dff-429eaecd221f} */
+#define SPAR_CONTROLDIRECTOR_CHANNEL_PROTOCOL_UUID  \
+		UUID_LE(0x5b52c5ac, 0xe5f5, 0x4d42, \
+				0x8d, 0xff, 0x42, 0x9e, 0xae, 0xcd, 0x22, 0x1f)
+
+static const uuid_le spar_controldirector_channel_protocol_uuid =
+	SPAR_CONTROLDIRECTOR_CHANNEL_PROTOCOL_UUID;
+
+/* {b4e79625-aede-4eAA-9e11-D3eddcd4504c} */
+#define SPAR_DIAG_POOL_CHANNEL_PROTOCOL_UUID				\
+		UUID_LE(0xb4e79625, 0xaede, 0x4eaa, \
+				0x9e, 0x11, 0xd3, 0xed, 0xdc, 0xd4, 0x50, 0x4c)
diff --git a/include/linux/visorbus/diagchannel.h b/include/linux/visorbus/diagchannel.h
new file mode 100644
index 0000000..6e813c7
--- /dev/null
+++ b/include/linux/visorbus/diagchannel.h
@@ -0,0 +1,38 @@
+/* Copyright (C) 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 _DIAG_CHANNEL_H_
+#define _DIAG_CHANNEL_H_
+
+/* 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. Changes made
+ * to the enum, need to be reflected in s-Par.
+ */
+enum diag_severity {
+		DIAG_SEVERITY_VERBOSE = 0,
+		DIAG_SEVERITY_INFO = 1,
+		DIAG_SEVERITY_WARNING = 2,
+		DIAG_SEVERITY_ERR = 3,
+		DIAG_SEVERITY_PRINT = 4,
+};
+
+#endif
diff --git a/include/linux/visorbus/guestlinuxdebug.h b/include/linux/visorbus/guestlinuxdebug.h
new file mode 100644
index 0000000..b81287f
--- /dev/null
+++ b/include/linux/visorbus/guestlinuxdebug.h
@@ -0,0 +1,180 @@
+/* Copyright (C) 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", particularly
+ * regarding adding additional structure and functionality to linux
+ * ISSUE_IO_VMCALL_POSTCODE_SEVERITY
+ */
+
+/******* INFO ON ISSUE_POSTCODE_LINUX() BELOW *******/
+enum driver_pc {		/* 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,
+};
+
+enum event_pc {			/* 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
+};
+
+#ifdef __GNUC__
+
+#define POSTCODE_SEVERITY_ERR DIAG_SEVERITY_ERR
+#define POSTCODE_SEVERITY_WARNING DIAG_SEVERITY_WARNING
+/* TODO-> Info currently doesn't show, so we set info=warning */
+#define POSTCODE_SEVERITY_INFO DIAG_SEVERITY_PRINT
+
+/* 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 occurred 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/include/linux/visorbus/iochannel.h b/include/linux/visorbus/iochannel.h
new file mode 100644
index 0000000..5ccf814
--- /dev/null
+++ b/include/linux/visorbus/iochannel.h
@@ -0,0 +1,571 @@
+/* Copyright (C) 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 <linux/uuid.h>
+
+#include <linux/dma-direction.h>
+#include "channel.h"
+#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 SPAR_VHBA_CHANNEL_OK_CLIENT(ch)			\
+	(spar_check_channel_client(ch, spar_vhba_channel_protocol_uuid, \
+				   "vhba", MIN_IO_CHANNEL_SIZE,	\
+				   ULTRA_VHBA_CHANNEL_PROTOCOL_VERSIONID, \
+				   ULTRA_VHBA_CHANNEL_PROTOCOL_SIGNATURE))
+
+#define SPAR_VNIC_CHANNEL_OK_CLIENT(ch)			\
+	(spar_check_channel_client(ch, spar_vnic_channel_protocol_uuid, \
+				   "vnic", MIN_IO_CHANNEL_SIZE,	\
+				   ULTRA_VNIC_CHANNEL_PROTOCOL_VERSIONID, \
+				   ULTRA_VNIC_CHANNEL_PROTOCOL_SIGNATURE))
+
+/*
+ * 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))
+
+/* define the two queues per data channel between iopart and ioguestparts */
+/* used by ioguestpart to 'insert' signals to iopart */
+#define IOCHAN_TO_IOPART 0
+/* used by ioguestpart to 'remove' signals from iopart, same previous queue */
+#define IOCHAN_FROM_IOPART 1
+
+/* size of cdb - i.e., scsi cmnd */
+#define MAX_CMND_SIZE 16
+
+#define MAX_SENSE_SIZE 64
+
+#define MAX_PHYS_INFO 64
+
+/* various types of network packets that can be sent in cmdrsp */
+enum net_types {
+	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 address */
+
+};
+
+#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_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 */
+
+/* various types of scsi task mgmt commands  */
+enum task_mgmt_types {
+	TASK_MGMT_ABORT_TASK = 1,
+	TASK_MGMT_BUS_RESET,
+	TASK_MGMT_LUN_RESET,
+	TASK_MGMT_TARGET_RESET,
+};
+
+/* various types of vdisk mgmt commands  */
+enum vdisk_mgmt_types {
+	VDISK_MGMT_ACQUIRE = 1,
+	VDISK_MGMT_RELEASE,
+};
+
+struct phys_info {
+	u64 pi_pfn;
+	u16 pi_off;
+	u16 pi_len;
+} __packed;
+
+#define MIN_NUMSIGNALS 64
+
+/* structs with pragma pack  */
+
+struct guest_phys_info {
+	u64 address;
+	u64 length;
+} __packed;
+
+#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 */
+} __packed;
+
+struct vhba_wwnn {
+	u32 wwnn1;
+	u32 wwnn2;
+} __packed;
+
+/* 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 bus */
+	u32 max_lun;	/* maximum SCSI LUN for devices attached to bus */
+	u32 cmd_per_lun;/* maximum number of outstanding commands per LUN */
+	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 */
+} __packed;
+
+struct uiscmdrsp_scsi {
+	u64 handle;		/* 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 list */
+	struct guest_phys_info gpi_list[MAX_PHYS_INFO];	/* physical address
+							 * information for each
+							 * fragment
+							 */
+	enum dma_data_direction  data_dir; /* direction of the data, if any */
+	struct uisscsi_dest vdest;	/* identifies the virtual hba, id, */
+					/* channel, lun to which cmd was sent */
+
+	/* Needed to queue the rsp back to cmd originator */
+	int linuxstat;		/* original Linux status used by linux vdisk */
+	u8 scsistat;		/* the scsi status */
+	u8 addlstat;		/* non-scsi status */
+#define ADDL_SEL_TIMEOUT	4
+
+	/* 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; /* pointer to the vdisk to clean up when 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.
+	 */
+} __packed;
+
+/* 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_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_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 /* 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) */
+
+/* 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 segment_number;
+	u8 sense_key:4;
+	u8 reserved:1;
+	u8 incorrect_length:1;
+	u8 end_of_media:1;
+	u8 file_mark:1;
+	u8 information[4];
+	u8 additional_sense_length;
+	u8 command_specific_information[4];
+	u8 additional_sense_code;
+	u8 additional_sense_code_qualifier;
+	u8 fru_code;
+	u8 sense_key_specific[3];
+} __packed;
+
+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 */
+	char ethhdr[ETH_HEADER_SIZE];	/* the ethernet header  */
+	struct {
+		/* these are needed for csum at uisnic end */
+		u8 valid;	/* 1 = 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.
+	     */
+} __packed;
+
+struct net_pkt_xmtdone {
+	u32 xmt_done_result;	/* result of NET_XMIT */
+} __packed;
+
+/* 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 unique_num;
+	    /* unique_num ensure that receive posts are returned to */
+	    /* the Adapter which we sent them originally. */
+} __packed;
+
+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];	/* list of chained rcvbufs */
+	/* 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 unique_num;
+	u32 rcvs_dropped_delta;
+} __packed;
+
+struct net_pkt_enbdis {
+	void *context;
+	u16 enable;		/* 1 = enable, 0 = disable */
+} __packed;
+
+struct net_pkt_macaddr {
+	void *context;
+	u8 macaddr[MAX_MACADDR_LEN];	/* 6 bytes */
+} __packed;
+
+/* cmd rsp packet used for VNIC network traffic  */
+struct uiscmdrsp_net {
+	enum 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;
+	};
+} __packed;
+
+struct uiscmdrsp_scsitaskmgmt {
+	enum task_mgmt_types tasktype;
+
+	    /* the type of task */
+	struct uisscsi_dest vdest;
+
+	    /* the vdisk for which this task mgmt is generated */
+	u64 handle;
+
+	    /* This is a 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.
+	     */
+	u64 notify_handle;
+
+	   /* 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.
+	    * When the rsp is received by guest, the thread receiving the
+	    * response uses this to notify the thread waiting for taskmgmt
+	    * command completion.  Its value is preserved by iopart & returned
+	    * as is in the task mgmt rsp.
+	    */
+	u64 notifyresult_handle;
+
+	    /* 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
+} __packed;
+
+/* 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 *v_hba;		/* channel info to route msg */
+	u32 channel, id, lun;	/* SCSI Path of Disk to added or removed */
+} __packed;
+
+/* The following is used by virthba/vSCSI to send the Acquire/Release commands
+ * to the IOVM.
+ */
+struct uiscmdrsp_vdiskmgmt {
+	enum vdisk_mgmt_types vdisktype;
+
+	    /* the type of task */
+	struct uisscsi_dest vdest;
+
+	    /* the vdisk for which this task mgmt is generated */
+	u64 handle;
+
+	    /* This is a 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.
+	     */
+	u64 notify_handle;
+
+	    /* For linux guests, this is a pointer to wait_queue_head that a
+	     * thread is waiting on to see if the tskmgmt command has completed.
+	     * When the rsp is received by guest, the thread receiving the
+	     * response uses this to notify the thread waiting for taskmgmt
+	     * command completion.  Its value is preserved by iopart & returned
+	     * as is in the task mgmt rsp.
+	     */
+	u64 notifyresult_handle;
+
+	    /* 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
+} __packed;
+
+/* 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;	/* 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 */
+} __packed;
+
+struct iochannel_vhba {
+	struct vhba_wwnn wwnn;		/* 8 bytes */
+	struct vhba_config_max max;	/* 20 bytes */
+} __packed;				/* total = 28 bytes */
+struct iochannel_vnic {
+	u8 macaddr[6];			/* 6 bytes */
+	u32 num_rcv_bufs;		/* 4 bytes */
+	u32 mtu;			/* 4 bytes */
+	uuid_le zone_uuid;		/* 16 bytes */
+} __packed;
+/* 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 cmd_q and rsp_q SIGNAL_QUEUE_HEADERS.
+ */
+struct spar_io_channel_protocol {
+	struct channel_header channel_header;
+	struct signal_queue_header cmd_q;
+	struct signal_queue_header rsp_q;
+	union {
+		struct iochannel_vhba vhba;
+		struct iochannel_vnic vnic;
+	} __packed;
+
+#define MAX_CLIENTSTRING_LEN 1024
+	/* client_string is NULL termimated so holds max -1 bytes */
+	 u8 client_string[MAX_CLIENTSTRING_LEN];
+} __packed;
+
+/* INLINE functions for initializing and accessing I/O data channels */
+#define SIZEOF_PROTOCOL (COVER(sizeof(struct spar_io_channel_protocol), 64))
+#define SIZEOF_CMDRSP (COVER(sizeof(struct uiscmdrsp), 64))
+
+#define MIN_IO_CHANNEL_SIZE COVER(SIZEOF_PROTOCOL + \
+				  2 * MIN_NUMSIGNALS * SIZEOF_CMDRSP, 4096)
+
+/*
+ * INLINE function for expanding a guest's pfn-off-size into multiple 4K page
+ * pfn-off-size entires.
+ */
+
+/* use 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
+
+/* returns next non-zero index on success or zero on failure (i.e. out of
+ * room)
+ */
+static inline  u16
+add_physinfo_entries(u64 inp_pfn, u16 inp_off, u32 inp_len, u16 index,
+		     u16 max_pi_arr_entries, struct phys_info pi_arr[])
+{
+	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/include/linux/visorbus/periodic_work.h b/include/linux/visorbus/periodic_work.h
new file mode 100644
index 0000000..0b3335a
--- /dev/null
+++ b/include/linux/visorbus/periodic_work.h
@@ -0,0 +1,40 @@
+/* periodic_work.h
+ *
+ * Copyright (C) 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 <linux/seq_file.h>
+#include <linux/slab.h>
+
+/* PERIODIC_WORK an opaque structure to users.
+ * Fields are declared only in the implementation .c files.
+ */
+struct periodic_work;
+
+struct periodic_work *
+visor_periodic_work_create(ulong jiffy_interval,
+			   struct workqueue_struct *workqueue,
+			   void (*workfunc)(void *),
+			   void *workfuncarg,
+			   const char *devnam);
+void visor_periodic_work_destroy(struct periodic_work *pw);
+bool visor_periodic_work_nextperiod(struct periodic_work *pw);
+bool visor_periodic_work_start(struct periodic_work *pw);
+bool visor_periodic_work_stop(struct periodic_work *pw);
+
+#endif
diff --git a/include/linux/visorbus/vbushelper.h b/include/linux/visorbus/vbushelper.h
new file mode 100644
index 0000000..f1b6aac
--- /dev/null
+++ b/include/linux/visorbus/vbushelper.h
@@ -0,0 +1,46 @@
+/* vbushelper.h
+ *
+ * Copyright (C) 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__
+
+/* TARGET_HOSTNAME specified as -DTARGET_HOSTNAME=\"thename\" on the
+ * command line
+ */
+
+#define TARGET_HOSTNAME "linuxguest"
+
+static inline void bus_device_info_init(
+		struct ultra_vbus_deviceinfo *bus_device_info_ptr,
+		const char *dev_type, const char *drv_name,
+		const char *ver, const char *ver_tag)
+{
+	memset(bus_device_info_ptr, 0, sizeof(struct ultra_vbus_deviceinfo));
+	snprintf(bus_device_info_ptr->devtype,
+		 sizeof(bus_device_info_ptr->devtype),
+		 "%s", (dev_type) ? dev_type : "unknownType");
+	snprintf(bus_device_info_ptr->drvname,
+		 sizeof(bus_device_info_ptr->drvname),
+		 "%s", (drv_name) ? drv_name : "unknownDriver");
+	snprintf(bus_device_info_ptr->infostrs,
+		 sizeof(bus_device_info_ptr->infostrs), "%s\t%s\t%s",
+		 (ver) ? ver : "unknownVer",
+		 (ver_tag) ? ver_tag : "unknownVerTag",
+		 TARGET_HOSTNAME);
+}
+
+#endif
diff --git a/include/linux/visorbus/version.h b/include/linux/visorbus/version.h
new file mode 100644
index 0000000..83d1da7
--- /dev/null
+++ b/include/linux/visorbus/version.h
@@ -0,0 +1,45 @@
+/* Copyright (C) 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
+
+/* 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/include/linux/visorbus/visorbus.h b/include/linux/visorbus/visorbus.h
new file mode 100644
index 0000000..9baf1ec
--- /dev/null
+++ b/include/linux/visorbus/visorbus.h
@@ -0,0 +1,234 @@
+/* visorbus.h
+ *
+ * Copyright (C) 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 header file is to be included by other kernel mode components that
+ *  implement a particular kind of visor_device.  Each of these other kernel
+ *  mode components is called a visor device driver.  Refer to visortemplate
+ *  for a minimal sample visor device driver.
+ *
+ *  There should be nothing in this file that is private to the visorbus
+ *  bus implementation itself.
+ *
+ */
+
+#ifndef __VISORBUS_H__
+#define __VISORBUS_H__
+
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/poll.h>
+#include <linux/kernel.h>
+#include <linux/uuid.h>
+
+#include "periodic_work.h"
+#include "channel.h"
+
+struct visor_driver;
+struct visor_device;
+extern struct bus_type visorbus_type;
+
+typedef void (*visorbus_state_complete_func) (struct visor_device *dev,
+					      int status);
+struct visorchipset_state {
+	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. */
+};
+
+/** This struct describes a specific Supervisor channel, by providing its
+ *  GUID, name, and sizes.
+ */
+struct visor_channeltype_descriptor {
+	const uuid_le guid;
+	const char *name;
+};
+
+/**
+ * struct visor_driver - Information provided by each visor driver when it
+ * registers with the visorbus driver.
+ * @name:		Name of the visor driver.
+ * @version:		The numbered version of the driver (x.x.xxx).
+ * @vertag:		A human readable version string.
+ * @owner:		The module owner.
+ * @channel_types:	Types of channels handled by this driver, ending with
+ *			a zero GUID. Our specialized BUS.match() method knows
+ *			about this list, and uses it to determine whether this
+ *			driver will in fact handle a new device that it has
+ *			detected.
+ * @probe:		Called when a new device comes online, by our probe()
+ *			function specified by driver.probe() (triggered
+ *			ultimately by some call to driver_register(),
+ *			bus_add_driver(), or driver_attach()).
+ * @remove:		Called when a new device is removed, by our remove()
+ *			function specified by driver.remove() (triggered
+ *			ultimately by some call to device_release_driver()).
+ * @channel_interrupt:	Called periodically, whenever there is a possiblity
+ *			that "something interesting" may have happened to the
+ *			channel.
+ * @pause:		Called to initiate a change of the device's state.  If
+ *			the return valu`e is < 0, there was an error and the
+ *			state transition will NOT occur.  If the return value
+ *			is >= 0, then the state transition was INITIATED
+ *			successfully, and complete_func() will be called (or
+ *			was just called) with the final status when either the
+ *			state transition fails or completes successfully.
+ * @resume:		Behaves similar to pause.
+ * @driver:		Private reference to the device driver. For use by bus
+ *			driver only.
+ * @version_attr:	Private version field. For use by bus driver only.
+ */
+struct visor_driver {
+	const char *name;
+	const char *version;
+	const char *vertag;
+	struct module *owner;
+	struct visor_channeltype_descriptor *channel_types;
+	int (*probe)(struct visor_device *dev);
+	void (*remove)(struct visor_device *dev);
+	void (*channel_interrupt)(struct visor_device *dev);
+	int (*pause)(struct visor_device *dev,
+		     visorbus_state_complete_func complete_func);
+	int (*resume)(struct visor_device *dev,
+		      visorbus_state_complete_func complete_func);
+
+	/* These fields are for private use by the bus driver only. */
+	struct device_driver driver;
+	struct driver_attribute version_attr;
+};
+
+#define to_visor_driver(x) ((x) ? \
+	(container_of(x, struct visor_driver, driver)) : (NULL))
+
+/**
+ * struct visor_device - A device type for things "plugged" into the visorbus
+ * bus
+ * visorchannel:		Points to the channel that the device is
+ *				associated with.
+ * channel_type_guid:		Identifies the channel type to the bus driver.
+ * device:			Device struct meant for use by the bus driver
+ *				only.
+ * list_all:			Used by the bus driver to enumerate devices.
+ * periodic_work:		Device work queue. Private use by bus driver
+ *				only.
+ * being_removed:		Indicates that the device is being removed from
+ *				the bus. Private bus driver use only.
+ * visordriver_callback_lock:	Used by the bus driver to lock when handling
+ *				channel events.
+ * pausing:			Indicates that a change towards a paused state.
+ *				is in progress. Only modified by the bus driver.
+ * resuming:			Indicates that a change towards a running state
+ *				is in progress. Only modified by the bus driver.
+ * chipset_bus_no:		Private field used by the bus driver.
+ * chipset_dev_no:		Private field used the bus driver.
+ * state:			Used to indicate the current state of the
+ *				device.
+ * inst:			Unique GUID for this instance of the device.
+ * name:			Name of the device.
+ * pending_msg_hdr:		For private use by bus driver to respond to
+ *				hypervisor requests.
+ * vbus_hdr_info:		A pointer to header info. Private use by bus
+ *				driver.
+ * partition_uuid:		Indicates client partion id. This should be the
+ *				same across all visor_devices in the current
+ *				guest. Private use by bus driver only.
+ */
+
+struct visor_device {
+	struct visorchannel *visorchannel;
+	uuid_le channel_type_guid;
+	/* These fields are for private use by the bus driver only. */
+	struct device device;
+	struct list_head list_all;
+	struct periodic_work *periodic_work;
+	bool being_removed;
+	struct semaphore visordriver_callback_lock;
+	bool pausing;
+	bool resuming;
+	u32 chipset_bus_no;
+	u32 chipset_dev_no;
+	struct visorchipset_state state;
+	uuid_le inst;
+	u8 *name;
+	struct controlvm_message_header *pending_msg_hdr;
+	void *vbus_hdr_info;
+	uuid_le partition_uuid;
+};
+
+#define to_visor_device(x) container_of(x, struct visor_device, device)
+
+#ifndef STANDALONE_CLIENT
+int visorbus_register_visor_driver(struct visor_driver *);
+void visorbus_unregister_visor_driver(struct visor_driver *);
+int visorbus_read_channel(struct visor_device *dev,
+			  unsigned long offset, void *dest,
+			  unsigned long nbytes);
+int visorbus_write_channel(struct visor_device *dev,
+			   unsigned long offset, void *src,
+			   unsigned long nbytes);
+int visorbus_clear_channel(struct visor_device *dev,
+			   unsigned long offset, u8 ch, unsigned long nbytes);
+void visorbus_enable_channel_interrupts(struct visor_device *dev);
+void visorbus_disable_channel_interrupts(struct visor_device *dev);
+#endif
+
+/* Note that for visorchannel_create()
+ * <channel_bytes> 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.
+ */
+struct visorchannel *visorchannel_create(u64 physaddr,
+					 unsigned long channel_bytes,
+					 gfp_t gfp, uuid_le guid);
+struct visorchannel *visorchannel_create_with_lock(u64 physaddr,
+						   unsigned long channel_bytes,
+						   gfp_t gfp, uuid_le guid);
+void visorchannel_destroy(struct visorchannel *channel);
+int visorchannel_read(struct visorchannel *channel, ulong offset,
+		      void *local, ulong nbytes);
+int visorchannel_write(struct visorchannel *channel, ulong offset,
+		       void *local, ulong nbytes);
+int visorchannel_clear(struct visorchannel *channel, ulong offset,
+		       u8 ch, ulong nbytes);
+bool visorchannel_signalremove(struct visorchannel *channel, u32 queue,
+			       void *msg);
+bool visorchannel_signalinsert(struct visorchannel *channel, u32 queue,
+			       void *msg);
+bool visorchannel_signalempty(struct visorchannel *channel, u32 queue);
+
+int visorchannel_signalqueue_slots_avail(struct visorchannel *channel,
+					 u32 queue);
+int visorchannel_signalqueue_max_slots(struct visorchannel *channel, u32 queue);
+u64 visorchannel_get_physaddr(struct visorchannel *channel);
+ulong visorchannel_get_nbytes(struct visorchannel *channel);
+char *visorchannel_id(struct visorchannel *channel, char *s);
+char *visorchannel_zoneid(struct visorchannel *channel, char *s);
+u64 visorchannel_get_clientpartition(struct visorchannel *channel);
+int visorchannel_set_clientpartition(struct visorchannel *channel,
+				     u64 partition_handle);
+uuid_le visorchannel_get_uuid(struct visorchannel *channel);
+char *visorchannel_uuid_id(uuid_le *guid, char *s);
+void visorchannel_debug(struct visorchannel *channel, int num_queues,
+			struct seq_file *seq, u32 off);
+void __iomem *visorchannel_get_header(struct visorchannel *channel);
+
+#define BUS_ROOT_DEVICE		UINT_MAX
+struct visor_device *visorbus_get_device_by_id(u32 bus_no, u32 dev_no,
+					       struct visor_device *from);
+#endif
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 3/5] Documentation: Move visorbus documentation from staging to Documentation/
  2016-05-17  7:27 [PATCH 0/5] add bus driver for Unisys s-Par paravirtualized devices to arch/x86 David Kershner
  2016-05-17  7:27 ` [PATCH 1/5] staging: unisys: Move vbushelper.h to visorbus directory David Kershner
  2016-05-17  7:27 ` [PATCH 2/5] include: linux: visorbus: Add visorbus to include/linux directory David Kershner
@ 2016-05-17  7:27 ` David Kershner
  2016-05-17 13:50   ` Greg KH
  2016-05-17  7:28 ` [PATCH 4/5] staging: unisys: visorbus: Have visorbus use include/linux/visorbus David Kershner
                   ` (2 subsequent siblings)
  5 siblings, 1 reply; 15+ messages in thread
From: David Kershner @ 2016-05-17  7:27 UTC (permalink / raw)
  To: corbet, tglx, mingo, hpa, david.kershner, gregkh, erik.arfvidson,
	timothy.sell, hofrat, dzickus, jes.sorensen, alexander.curtin,
	janani.rvchndrn, sudipm.mukherjee, prarit, david.binder, nhorman,
	dan.j.williams, linux-kernel, linux-doc, driverdev-devel,
	sparmaintainer

This patch simple does a git mv of the
drivers/staging/unisys/Documentation directory to Documentation. Renames
overview.txt to visorbus.txt and renames sysfs-platform-visorchipset to
the correct name sysfs-bus-visorbus.

Signed-off-by: David Kershner <david.kershner@unisys.com>
---
 Documentation/ABI/stable/sysfs-bus-visorbus        |  89 ++++++
 Documentation/visorbus.txt                         | 337 +++++++++++++++++++++
 .../Documentation/ABI/sysfs-platform-visorchipset  |  89 ------
 drivers/staging/unisys/Documentation/overview.txt  | 337 ---------------------
 4 files changed, 426 insertions(+), 426 deletions(-)
 create mode 100644 Documentation/ABI/stable/sysfs-bus-visorbus
 create mode 100644 Documentation/visorbus.txt
 delete mode 100644 drivers/staging/unisys/Documentation/ABI/sysfs-platform-visorchipset
 delete mode 100644 drivers/staging/unisys/Documentation/overview.txt

diff --git a/Documentation/ABI/stable/sysfs-bus-visorbus b/Documentation/ABI/stable/sysfs-bus-visorbus
new file mode 100644
index 0000000..c2359de
--- /dev/null
+++ b/Documentation/ABI/stable/sysfs-bus-visorbus
@@ -0,0 +1,89 @@
+This file describes sysfs entries beneath /devices/platform/visorchipset.
+
+What:		install/error
+Date:		7/18/2014
+KernelVersion: 	TBD
+Contact:	sparmaintainer@unisys.com
+Description:	used to send the ID of a string that should be displayed on
+		s-Par's automatic installation progress screen when an error
+		is encountered during installation. This field has no effect
+		if not in installation mode.
+Users:		sparmaintainer@unisys.com
+
+What:		install/remainingsteps
+Date:		7/18/2014
+KernelVersion: 	TBD
+Contact:	sparmaintainer@unisys.com
+Description:	used to set the value of the progress bar on the s-Par automatic
+		installation progress screen. This field has no effect if not in
+		installation mode.
+Users:		sparmaintainer@unisys.com
+
+What:		install/textid
+Date:		7/18/2014
+KernelVersion: 	TBD
+Contact:	sparmaintainer@unisys.com
+Description:	used to send the ID of a string that should be displayed on
+		s-Par's automatic installation progress screen. Setting this
+		field when not in installation mode (boottotool was set on
+		the previous guest boot) has no effect.
+Users:		sparmaintainer@unisys.com
+
+What:		install/boottotool
+Date:		7/18/2014
+KernelVersion: 	TBD
+Contact:	sparmaintainer@unisys.com
+Description:	The boottotool flag controls s-Par behavior on the next boot of
+		this guest. Setting the flag will cause the guest to boot from
+		the utility and installation image, which will use the value in
+		the toolaction field to determine what operation is being
+		requested.
+Users:		sparmaintainer@unisys.com
+
+What:		install/toolaction
+Date:		7/18/2014
+KernelVersion: 	TBD
+Contact:	sparmaintainer@unisys.com
+Description:	This field is used to tell s-Par which type of recovery tool
+		action to perform on the next guest boot-up. The meaning of the
+		value is dependent on the type of installation software used to
+		commission the guest.
+Users:		sparmaintainer@unisys.com
+
+What:		parahotplug/deviceenabled
+Date:		7/18/2014
+KernelVersion: 	TBD
+Contact:	sparmaintainer@unisys.com
+Description:	This entry is used by a Unisys support script installed on the
+		guest, and triggered by a udev event. The support script is
+		responsible for enabling and disabling SR-IOV devices when the
+		PF device is being recovered in another guest.
+
+		Some SR-IOV devices have problems when the PF is reset without
+		first disabling all VFs attached to that PF. s-Par handles this
+		situation by sending a message to guests using these VFs, and
+		the script will disable the device. When the PF is recovered,
+		another message is sent to the guests to re-enable the VFs.
+
+		The parahotplug/deviceenabled interface is used to acknowledge
+		the recovery message.
+Users:		sparmaintainer@unisys.com
+
+What:		parahotplug/devicedisabled
+Date:		7/18/2014
+KernelVersion: 	TBD
+Contact:	sparmaintainer@unisys.com
+Description:	This entry is used by a Unisys support script installed on the
+		guest, and triggered by a udev event. The support script is
+		responsible for enabling and disabling SR-IOV devices when the
+		PF device is being recovered in another guest.
+
+		Some SR-IOV devices have problems when the PF is reset without
+		first disabling all VFs attached to that PF. s-Par handles this
+		situation by sending a message to guests using these VFs, and
+		the script will disable the device. When the PF is recovered,
+		another message is sent to the guests to re-enable the VFs.
+
+		The parahotplug/devicedisaabled interface is used to acknowledge
+		the initial recovery message.
+Users:		sparmaintainer@unisys.com
diff --git a/Documentation/visorbus.txt b/Documentation/visorbus.txt
new file mode 100644
index 0000000..1146c1c
--- /dev/null
+++ b/Documentation/visorbus.txt
@@ -0,0 +1,337 @@
+1. Overview
+-----------
+
+This document describes the driver set for Unisys Secure Partitioning
+(s-Par(R)).
+
+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:
+
+* visornic - network interface
+* visorhba - scsi disk adapter
+* visorinput - keyboard and mouse
+
+These drivers conform to the standard Linux bus/device model described
+within Documentation/driver-model/, and utilize a driver named visorbus to
+present the virtual busses involved. Drivers in the 'visor*' driver set are
+commonly referred to as "guest drivers" or "client drivers".  All drivers
+except visorbus expose a device of a specific usable class to the Linux guest
+environment (e.g., block, network, or input), and are collectively referred
+to as "function drivers".
+
+The back-end for each device is owned and managed by a small,
+single-purpose service partition in the s-Par firmware, which communicates
+with each guest partition sharing that device through an area of shared memory
+called a "channel". In s-Par nomenclature, the back-end is often referred to
+as the "service partition", "IO partition" (for virtual network and scsi disk
+devices), or "console partition" (for virtual keyboard and mouse devices).
+
+Each virtual device requires exactly 1 dedicated channel, which the guest
+driver and back-end use to communicate.  The hypervisor need not intervene
+(other than normal interrupt handling) in the interactions that occur across
+this channel.
+
+NOT covered in this document:
+
+* s-Par also supports sharing physical PCI adapters via SR-IOV, but
+  because this requires no specific support in the guest partitions, it will
+  not be discussed in this document.  Shared SR-IOV devices should be used
+  wherever possible for highest performance.
+
+* Because the s-Par back-end provides a standard EFI framebuffer to each
+  guest, the already-existing efifb Linux driver is used to provide guest
+  video access. Thus, the only s-Par-unique support that is necessary to
+  provide a guest graphics console are for keyboard and mouse (via visorinput).
+
+
+2. Driver Descriptions
+----------------------
+
+2.1. visorbus
+-------------
+
+2.1.1. Overview
+---------------
+
+The visorbus driver handles the virtual busses on which all of the virtual
+devices reside. It provides a registration function named
+visorbus_register_visor_driver() that is called by each of the function
+drivers at initialization time, which the function driver uses to tell
+visorbus about the device classes (via specifying a list of device type
+GUIDs) it wants to handle. For use by function drivers, visorbus provides
+implementation for struct visor_driver and struct visor_device, as well
+as utility functions for communicating with the back-end.
+
+visorbus is associated with ACPI id "PNP0A07" in modules.alias, so if built
+as a module it will typically be loaded automatically via standard udev or
+systemd (God help us) configurations.
+
+visorbus can similarly force auto-loading of function drivers for virtual
+devices it discovers, as it includes a MODALIAS environment variable of this
+form in the hotplug uevent environment when each virtual device is
+discovered:
+
+    visorbus:<device type GUID>
+
+visorbus notifies each function driver when a device of its registered class
+arrives and departs, by calling the function driver's probe() and remove()
+methods.
+
+The actual struct device objects that correspond to each virtual bus and
+each virtual device are created and owned by visorbus.  These device objects
+are created in response to messages from the s-Par back-end received on a
+special control channel called the "controlvm channel" (each guest partition
+has access to exactly 1 controlvm channel), and have a lifetime that is
+independent of the function drivers that control them.
+
+2.1.2. "struct visor device" Function Driver Interfaces
+-------------------------------------------------------
+
+The interface between visorbus and its function drivers is defined in
+visorbus.h, and described below.
+
+When a visor function driver loads, it calls visorbus_register_visor_driver()
+to register itself with visorbus. The significant information passed in this
+exchange is as follows:
+
+* the GUID(s) of the channel type(s) that are handled by this driver, as
+  well as a "friendly name" identifying each (this will be published under
+  /sys/devices/visorbus<x>/dev<y>)
+
+* the addresses of callback functions to be called whenever a virtual
+  device/channel with the appropriate channel-type GUID(s) appears or
+  disappears
+
+* the address of a "channel_interrupt" function, which will be automatically
+  called at specific intervals to enable the driver to poll the device
+  channel for activity
+
+The following functions implemented within each function driver will be
+called automatically by the visorbus driver at appropriate times:
+
+* The probe() function notifies about the creation of each new virtual
+  device/channel instance.
+
+* The remove() function notifies about the destruction of a virtual
+  device/channel instance.
+
+* The channel_interrupt() function is called at frequent intervals to
+  give the function driver an opportunity to poll the virtual device channel
+  for requests.  Information is passed to this function to enable the
+  function driver to use the visorchannel_signalinsert() and
+  visorchannel_signalremove() functions to respond to and initiate activity
+  over the channel.  (Note that since it is the visorbus driver that
+  determines when this is called, it is very easy to switch to
+  interrupt-driven mechanisms when available for particular virtual device
+  types.)
+
+* The pause() function is called should it ever be necessary to direct the
+  function driver to temporarily stop accessing the device channel.  An
+  example of when this is needed is when the service partition implementing
+  the back-end of the virtual device needs to be recovered.  After a
+  successful return of pause(), the function driver must not access the
+  device channel until a subsequent resume() occurs.
+
+* The resume() function is the "book-end" to pause(), and is described above.
+
+2.1.3. sysfs Advertised Information
+-----------------------------------
+
+Because visorbus is a standard Linux bus driver in the model described in
+Documentation/driver-model/, the hierarchy of s-Par virtual devices is
+published in the sysfs tree beneath /bus/visorbus/, e.g.,
+/sys/bus/visorbus/devices/ might look like:
+
+    vbus1:dev1 -> ../../../devices/visorbus1/vbus1:dev1
+    vbus1:dev2 -> ../../../devices/visorbus1/vbus1:dev2
+    vbus1:dev3 -> ../../../devices/visorbus1/vbus1:dev3
+    vbus2:dev0 -> ../../../devices/visorbus2/vbus2:dev0
+    vbus2:dev1 -> ../../../devices/visorbus2/vbus2:dev1
+    vbus2:dev2 -> ../../../devices/visorbus2/vbus2:dev2
+    visorbus1 -> ../../../devices/visorbus1
+    visorbus2 -> ../../../devices/visorbus2
+
+visor_device notes:
+
+* Each visorbus<n> entry denotes the existence of a struct visor_device
+  denoting virtual bus #<n>.  A unique s-Par channel exists for each such
+  virtual bus.
+
+* Virtual bus numbers uniquely identify s-Par back-end service partitions.
+  In this example, bus 1 corresponds to the s-Par console partition
+  (controls keyboard, video, and mouse), whereas bus 2 corresponds to the
+  s-Par IO partition (controls network and disk).
+
+* Each vbus<x>:dev<y> entry denotes the existence of a struct visor_device
+  denoting virtual device #<y> outboard of virtual bus #<x>.  A unique s-Par
+  channel exists for each such virtual device.
+
+* If a function driver has loaded and claimed a particular device, the
+  bus/visorbus/devices/vbus<x>:dev<y>/driver symlink will indicate that
+  function driver.
+
+Every active visorbus device will have a sysfs subtree under:
+
+    /sys/devices/visorbus<x>/vbus<x>:dev<y>/
+
+The following files exist under /sys/devices/visorbus<x>/vbus<x>:dev<y>:
+
+    subsystem                 link to sysfs tree that describes the
+                              visorbus bus type; e.g.:
+                                  ../../../bus/visorbus
+
+    driver                    link to sysfs tree that describes the
+                              function driver controlling this device;
+                              e.g.:
+                                  ../../../bus/visorbus/drivers/visorhba
+                              Note that this "driver" link will not exist
+                              if the appropriate function driver has not
+                              been loaded yet.
+
+    channel                   properties of the device channel (all in
+                              ascii text format)
+
+        clientpartition       handle identifying the guest (client) side
+                              of this channel, e.g. 0x10000000.
+
+        nbytes                total size of this channel in bytes
+
+        physaddr              the guest physical address for the base of
+                              the channel
+
+        typeguid              a GUID identifying the channel type, in
+                              xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx notation
+
+        typename              a "friendly name" for this channel type, e.g.,
+                              "keyboard".  Note that this name is provided by
+                              a particular function driver, so "typename"
+                              will return an empty string until AFTER the
+                              appropriate function driver controlling this
+                              channel type is loaded
+
+        zoneguid              a GUID identifying the channel zone, in
+                              xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx notation
+
+
+2.2. visorhba
+-------------
+
+The visorhba driver registers with visorbus as the function driver to
+handle virtual scsi disk devices, specified using the
+SPAR_VHBA_CHANNEL_PROTOCOL_UUID type in the visorbus_register_visor_driver()
+call. visorhba uses scsi_add_host() to expose a Linux block device
+(e.g., /sys/block/) in the guest environment for each s-Par virtual device.
+
+visorhba 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.
+
+When compiled as a module, visorhba can be autoloaded by visorbus in
+standard udev/systemd environments, as it includes the modules.alias
+definition:
+
+    "visorbus:"+SPAR_VHBA_CHANNEL_PROTOCOL_UUID_STR
+
+i.e.:
+
+    alias visorbus:414815ed-c58c-11da-95a9-00e08161165f visorhba
+
+
+2.3. visornic
+-------------
+
+The visornic driver registers with visorbus as the function driver to
+handle virtual network devices, specified using the
+SPAR_VNIC_CHANNEL_PROTOCOL_UUID type in the visorbus_register_visor_driver()
+call. visornic uses register_netdev() to expose a Linux device of class net
+(e.g., /sys/class/net/) in the guest environment for each s-Par virtual
+device.
+
+visornic 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.
+
+When compiled as a module, visornic can be autoloaded by visorbus in
+standard udev/systemd environments, as it includes the modules.alias
+definition:
+
+    "visorbus:"+SPAR_VNIC_CHANNEL_PROTOCOL_UUID_STR
+
+i.e.:
+
+    alias visorbus:8cd5994d-c58e-11da-95a9-00e08161165f visornic
+
+
+2.4. visorinput
+---------------
+
+The visorinput driver registers with visorbus as the function driver to
+handle human input devices, specified using the
+SPAR_KEYBOARD_CHANNEL_PROTOCOL_UUID and SPAR_MOUSE_CHANNEL_PROTOCOL_UUID
+types in the visorbus_register_visor_driver() call. visorinput uses
+input_register_device() to expose devices of class input
+(e.g., /sys/class/input/) for virtual keyboard and virtual mouse devices.
+A s-Par virtual keyboard device maps 1-to-1 with a Linux input device
+named "visor Keyboard", while a s-Par virtual mouse device has 2 Linux input
+devices created for it: 1 named "visor Wheel", and 1 named "visor Mouse".
+
+By registering as input class devices, modern versions of X will
+automatically find and properly use s-Par virtual keyboard and mouse devices.
+As the s-Par back-end reports keyboard and mouse activity via events on the
+virtual device channel, the visorinput driver delivers the activity to the
+Linux environment by calling input_report_key() and input_report_abs().
+
+You can interact with the guest console using the usyscon Partition Desktop
+(a.k.a., "pd") application, provided as part of s-Par.  After installing the
+usyscon Partition Desktop into a Linux environment via the
+usyscon_partitiondesktop-*.rpm, or into a Windows environment via
+PartitionDesktop.msi, you will be able to launch a console for your guest
+Linux environment by clicking the console icon in the s-Par web UI.
+
+When compiled as a module, visorinput can be autoloaded by visorbus in
+standard udev/systemd environments, as it includes the modules.alias
+definition:
+
+    "visorbus:"+SPAR_MOUSE_CHANNEL_PROTOCOL_UUID_STR
+    "visorbus:"+SPAR_KEYBOARD_CHANNEL_PROTOCOL_UUID_STR
+
+i.e.:
+
+    alias visorbus:c73416d0-b0b8-44af-b304-9d2ae99f1b3d visorinput
+    alias visorbus:addf07d4-94a9-46e2-81c3-61abcdbdbd87 visorinput
+
+
+3. Minimum Required Driver Set
+------------------------------
+
+visorbus is required for every Linux guest running under s-Par.
+
+visorhba is typically required for a Linux guest running under s-Par, as it
+is required if your guest boot disk is a virtual device provided by the s-Par
+back-end, which is the default configuration.  However, for advanced
+configurations where the Linux guest boots via an SR-IOV-provided HBA or
+SAN disk for example, visorhba is not technically required.
+
+visornic is typically required for a Linux guest running under s-Par, as it
+is required if your guest network interface is a virtual device provided by
+the s-Par back-end, which is the default configuration.  However, for
+configurations where the Linux guest is provided with an SR-IOV NIC
+for example, visornic is not technically required.
+
+visorinput is only required for a Linux guest running under s-Par if you
+require graphics-mode access to your guest console.
diff --git a/drivers/staging/unisys/Documentation/ABI/sysfs-platform-visorchipset b/drivers/staging/unisys/Documentation/ABI/sysfs-platform-visorchipset
deleted file mode 100644
index c2359de..0000000
--- a/drivers/staging/unisys/Documentation/ABI/sysfs-platform-visorchipset
+++ /dev/null
@@ -1,89 +0,0 @@
-This file describes sysfs entries beneath /devices/platform/visorchipset.
-
-What:		install/error
-Date:		7/18/2014
-KernelVersion: 	TBD
-Contact:	sparmaintainer@unisys.com
-Description:	used to send the ID of a string that should be displayed on
-		s-Par's automatic installation progress screen when an error
-		is encountered during installation. This field has no effect
-		if not in installation mode.
-Users:		sparmaintainer@unisys.com
-
-What:		install/remainingsteps
-Date:		7/18/2014
-KernelVersion: 	TBD
-Contact:	sparmaintainer@unisys.com
-Description:	used to set the value of the progress bar on the s-Par automatic
-		installation progress screen. This field has no effect if not in
-		installation mode.
-Users:		sparmaintainer@unisys.com
-
-What:		install/textid
-Date:		7/18/2014
-KernelVersion: 	TBD
-Contact:	sparmaintainer@unisys.com
-Description:	used to send the ID of a string that should be displayed on
-		s-Par's automatic installation progress screen. Setting this
-		field when not in installation mode (boottotool was set on
-		the previous guest boot) has no effect.
-Users:		sparmaintainer@unisys.com
-
-What:		install/boottotool
-Date:		7/18/2014
-KernelVersion: 	TBD
-Contact:	sparmaintainer@unisys.com
-Description:	The boottotool flag controls s-Par behavior on the next boot of
-		this guest. Setting the flag will cause the guest to boot from
-		the utility and installation image, which will use the value in
-		the toolaction field to determine what operation is being
-		requested.
-Users:		sparmaintainer@unisys.com
-
-What:		install/toolaction
-Date:		7/18/2014
-KernelVersion: 	TBD
-Contact:	sparmaintainer@unisys.com
-Description:	This field is used to tell s-Par which type of recovery tool
-		action to perform on the next guest boot-up. The meaning of the
-		value is dependent on the type of installation software used to
-		commission the guest.
-Users:		sparmaintainer@unisys.com
-
-What:		parahotplug/deviceenabled
-Date:		7/18/2014
-KernelVersion: 	TBD
-Contact:	sparmaintainer@unisys.com
-Description:	This entry is used by a Unisys support script installed on the
-		guest, and triggered by a udev event. The support script is
-		responsible for enabling and disabling SR-IOV devices when the
-		PF device is being recovered in another guest.
-
-		Some SR-IOV devices have problems when the PF is reset without
-		first disabling all VFs attached to that PF. s-Par handles this
-		situation by sending a message to guests using these VFs, and
-		the script will disable the device. When the PF is recovered,
-		another message is sent to the guests to re-enable the VFs.
-
-		The parahotplug/deviceenabled interface is used to acknowledge
-		the recovery message.
-Users:		sparmaintainer@unisys.com
-
-What:		parahotplug/devicedisabled
-Date:		7/18/2014
-KernelVersion: 	TBD
-Contact:	sparmaintainer@unisys.com
-Description:	This entry is used by a Unisys support script installed on the
-		guest, and triggered by a udev event. The support script is
-		responsible for enabling and disabling SR-IOV devices when the
-		PF device is being recovered in another guest.
-
-		Some SR-IOV devices have problems when the PF is reset without
-		first disabling all VFs attached to that PF. s-Par handles this
-		situation by sending a message to guests using these VFs, and
-		the script will disable the device. When the PF is recovered,
-		another message is sent to the guests to re-enable the VFs.
-
-		The parahotplug/devicedisaabled interface is used to acknowledge
-		the initial recovery message.
-Users:		sparmaintainer@unisys.com
diff --git a/drivers/staging/unisys/Documentation/overview.txt b/drivers/staging/unisys/Documentation/overview.txt
deleted file mode 100644
index 1146c1c..0000000
--- a/drivers/staging/unisys/Documentation/overview.txt
+++ /dev/null
@@ -1,337 +0,0 @@
-1. Overview
------------
-
-This document describes the driver set for Unisys Secure Partitioning
-(s-Par(R)).
-
-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:
-
-* visornic - network interface
-* visorhba - scsi disk adapter
-* visorinput - keyboard and mouse
-
-These drivers conform to the standard Linux bus/device model described
-within Documentation/driver-model/, and utilize a driver named visorbus to
-present the virtual busses involved. Drivers in the 'visor*' driver set are
-commonly referred to as "guest drivers" or "client drivers".  All drivers
-except visorbus expose a device of a specific usable class to the Linux guest
-environment (e.g., block, network, or input), and are collectively referred
-to as "function drivers".
-
-The back-end for each device is owned and managed by a small,
-single-purpose service partition in the s-Par firmware, which communicates
-with each guest partition sharing that device through an area of shared memory
-called a "channel". In s-Par nomenclature, the back-end is often referred to
-as the "service partition", "IO partition" (for virtual network and scsi disk
-devices), or "console partition" (for virtual keyboard and mouse devices).
-
-Each virtual device requires exactly 1 dedicated channel, which the guest
-driver and back-end use to communicate.  The hypervisor need not intervene
-(other than normal interrupt handling) in the interactions that occur across
-this channel.
-
-NOT covered in this document:
-
-* s-Par also supports sharing physical PCI adapters via SR-IOV, but
-  because this requires no specific support in the guest partitions, it will
-  not be discussed in this document.  Shared SR-IOV devices should be used
-  wherever possible for highest performance.
-
-* Because the s-Par back-end provides a standard EFI framebuffer to each
-  guest, the already-existing efifb Linux driver is used to provide guest
-  video access. Thus, the only s-Par-unique support that is necessary to
-  provide a guest graphics console are for keyboard and mouse (via visorinput).
-
-
-2. Driver Descriptions
-----------------------
-
-2.1. visorbus
--------------
-
-2.1.1. Overview
----------------
-
-The visorbus driver handles the virtual busses on which all of the virtual
-devices reside. It provides a registration function named
-visorbus_register_visor_driver() that is called by each of the function
-drivers at initialization time, which the function driver uses to tell
-visorbus about the device classes (via specifying a list of device type
-GUIDs) it wants to handle. For use by function drivers, visorbus provides
-implementation for struct visor_driver and struct visor_device, as well
-as utility functions for communicating with the back-end.
-
-visorbus is associated with ACPI id "PNP0A07" in modules.alias, so if built
-as a module it will typically be loaded automatically via standard udev or
-systemd (God help us) configurations.
-
-visorbus can similarly force auto-loading of function drivers for virtual
-devices it discovers, as it includes a MODALIAS environment variable of this
-form in the hotplug uevent environment when each virtual device is
-discovered:
-
-    visorbus:<device type GUID>
-
-visorbus notifies each function driver when a device of its registered class
-arrives and departs, by calling the function driver's probe() and remove()
-methods.
-
-The actual struct device objects that correspond to each virtual bus and
-each virtual device are created and owned by visorbus.  These device objects
-are created in response to messages from the s-Par back-end received on a
-special control channel called the "controlvm channel" (each guest partition
-has access to exactly 1 controlvm channel), and have a lifetime that is
-independent of the function drivers that control them.
-
-2.1.2. "struct visor device" Function Driver Interfaces
--------------------------------------------------------
-
-The interface between visorbus and its function drivers is defined in
-visorbus.h, and described below.
-
-When a visor function driver loads, it calls visorbus_register_visor_driver()
-to register itself with visorbus. The significant information passed in this
-exchange is as follows:
-
-* the GUID(s) of the channel type(s) that are handled by this driver, as
-  well as a "friendly name" identifying each (this will be published under
-  /sys/devices/visorbus<x>/dev<y>)
-
-* the addresses of callback functions to be called whenever a virtual
-  device/channel with the appropriate channel-type GUID(s) appears or
-  disappears
-
-* the address of a "channel_interrupt" function, which will be automatically
-  called at specific intervals to enable the driver to poll the device
-  channel for activity
-
-The following functions implemented within each function driver will be
-called automatically by the visorbus driver at appropriate times:
-
-* The probe() function notifies about the creation of each new virtual
-  device/channel instance.
-
-* The remove() function notifies about the destruction of a virtual
-  device/channel instance.
-
-* The channel_interrupt() function is called at frequent intervals to
-  give the function driver an opportunity to poll the virtual device channel
-  for requests.  Information is passed to this function to enable the
-  function driver to use the visorchannel_signalinsert() and
-  visorchannel_signalremove() functions to respond to and initiate activity
-  over the channel.  (Note that since it is the visorbus driver that
-  determines when this is called, it is very easy to switch to
-  interrupt-driven mechanisms when available for particular virtual device
-  types.)
-
-* The pause() function is called should it ever be necessary to direct the
-  function driver to temporarily stop accessing the device channel.  An
-  example of when this is needed is when the service partition implementing
-  the back-end of the virtual device needs to be recovered.  After a
-  successful return of pause(), the function driver must not access the
-  device channel until a subsequent resume() occurs.
-
-* The resume() function is the "book-end" to pause(), and is described above.
-
-2.1.3. sysfs Advertised Information
------------------------------------
-
-Because visorbus is a standard Linux bus driver in the model described in
-Documentation/driver-model/, the hierarchy of s-Par virtual devices is
-published in the sysfs tree beneath /bus/visorbus/, e.g.,
-/sys/bus/visorbus/devices/ might look like:
-
-    vbus1:dev1 -> ../../../devices/visorbus1/vbus1:dev1
-    vbus1:dev2 -> ../../../devices/visorbus1/vbus1:dev2
-    vbus1:dev3 -> ../../../devices/visorbus1/vbus1:dev3
-    vbus2:dev0 -> ../../../devices/visorbus2/vbus2:dev0
-    vbus2:dev1 -> ../../../devices/visorbus2/vbus2:dev1
-    vbus2:dev2 -> ../../../devices/visorbus2/vbus2:dev2
-    visorbus1 -> ../../../devices/visorbus1
-    visorbus2 -> ../../../devices/visorbus2
-
-visor_device notes:
-
-* Each visorbus<n> entry denotes the existence of a struct visor_device
-  denoting virtual bus #<n>.  A unique s-Par channel exists for each such
-  virtual bus.
-
-* Virtual bus numbers uniquely identify s-Par back-end service partitions.
-  In this example, bus 1 corresponds to the s-Par console partition
-  (controls keyboard, video, and mouse), whereas bus 2 corresponds to the
-  s-Par IO partition (controls network and disk).
-
-* Each vbus<x>:dev<y> entry denotes the existence of a struct visor_device
-  denoting virtual device #<y> outboard of virtual bus #<x>.  A unique s-Par
-  channel exists for each such virtual device.
-
-* If a function driver has loaded and claimed a particular device, the
-  bus/visorbus/devices/vbus<x>:dev<y>/driver symlink will indicate that
-  function driver.
-
-Every active visorbus device will have a sysfs subtree under:
-
-    /sys/devices/visorbus<x>/vbus<x>:dev<y>/
-
-The following files exist under /sys/devices/visorbus<x>/vbus<x>:dev<y>:
-
-    subsystem                 link to sysfs tree that describes the
-                              visorbus bus type; e.g.:
-                                  ../../../bus/visorbus
-
-    driver                    link to sysfs tree that describes the
-                              function driver controlling this device;
-                              e.g.:
-                                  ../../../bus/visorbus/drivers/visorhba
-                              Note that this "driver" link will not exist
-                              if the appropriate function driver has not
-                              been loaded yet.
-
-    channel                   properties of the device channel (all in
-                              ascii text format)
-
-        clientpartition       handle identifying the guest (client) side
-                              of this channel, e.g. 0x10000000.
-
-        nbytes                total size of this channel in bytes
-
-        physaddr              the guest physical address for the base of
-                              the channel
-
-        typeguid              a GUID identifying the channel type, in
-                              xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx notation
-
-        typename              a "friendly name" for this channel type, e.g.,
-                              "keyboard".  Note that this name is provided by
-                              a particular function driver, so "typename"
-                              will return an empty string until AFTER the
-                              appropriate function driver controlling this
-                              channel type is loaded
-
-        zoneguid              a GUID identifying the channel zone, in
-                              xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx notation
-
-
-2.2. visorhba
--------------
-
-The visorhba driver registers with visorbus as the function driver to
-handle virtual scsi disk devices, specified using the
-SPAR_VHBA_CHANNEL_PROTOCOL_UUID type in the visorbus_register_visor_driver()
-call. visorhba uses scsi_add_host() to expose a Linux block device
-(e.g., /sys/block/) in the guest environment for each s-Par virtual device.
-
-visorhba 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.
-
-When compiled as a module, visorhba can be autoloaded by visorbus in
-standard udev/systemd environments, as it includes the modules.alias
-definition:
-
-    "visorbus:"+SPAR_VHBA_CHANNEL_PROTOCOL_UUID_STR
-
-i.e.:
-
-    alias visorbus:414815ed-c58c-11da-95a9-00e08161165f visorhba
-
-
-2.3. visornic
--------------
-
-The visornic driver registers with visorbus as the function driver to
-handle virtual network devices, specified using the
-SPAR_VNIC_CHANNEL_PROTOCOL_UUID type in the visorbus_register_visor_driver()
-call. visornic uses register_netdev() to expose a Linux device of class net
-(e.g., /sys/class/net/) in the guest environment for each s-Par virtual
-device.
-
-visornic 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.
-
-When compiled as a module, visornic can be autoloaded by visorbus in
-standard udev/systemd environments, as it includes the modules.alias
-definition:
-
-    "visorbus:"+SPAR_VNIC_CHANNEL_PROTOCOL_UUID_STR
-
-i.e.:
-
-    alias visorbus:8cd5994d-c58e-11da-95a9-00e08161165f visornic
-
-
-2.4. visorinput
----------------
-
-The visorinput driver registers with visorbus as the function driver to
-handle human input devices, specified using the
-SPAR_KEYBOARD_CHANNEL_PROTOCOL_UUID and SPAR_MOUSE_CHANNEL_PROTOCOL_UUID
-types in the visorbus_register_visor_driver() call. visorinput uses
-input_register_device() to expose devices of class input
-(e.g., /sys/class/input/) for virtual keyboard and virtual mouse devices.
-A s-Par virtual keyboard device maps 1-to-1 with a Linux input device
-named "visor Keyboard", while a s-Par virtual mouse device has 2 Linux input
-devices created for it: 1 named "visor Wheel", and 1 named "visor Mouse".
-
-By registering as input class devices, modern versions of X will
-automatically find and properly use s-Par virtual keyboard and mouse devices.
-As the s-Par back-end reports keyboard and mouse activity via events on the
-virtual device channel, the visorinput driver delivers the activity to the
-Linux environment by calling input_report_key() and input_report_abs().
-
-You can interact with the guest console using the usyscon Partition Desktop
-(a.k.a., "pd") application, provided as part of s-Par.  After installing the
-usyscon Partition Desktop into a Linux environment via the
-usyscon_partitiondesktop-*.rpm, or into a Windows environment via
-PartitionDesktop.msi, you will be able to launch a console for your guest
-Linux environment by clicking the console icon in the s-Par web UI.
-
-When compiled as a module, visorinput can be autoloaded by visorbus in
-standard udev/systemd environments, as it includes the modules.alias
-definition:
-
-    "visorbus:"+SPAR_MOUSE_CHANNEL_PROTOCOL_UUID_STR
-    "visorbus:"+SPAR_KEYBOARD_CHANNEL_PROTOCOL_UUID_STR
-
-i.e.:
-
-    alias visorbus:c73416d0-b0b8-44af-b304-9d2ae99f1b3d visorinput
-    alias visorbus:addf07d4-94a9-46e2-81c3-61abcdbdbd87 visorinput
-
-
-3. Minimum Required Driver Set
-------------------------------
-
-visorbus is required for every Linux guest running under s-Par.
-
-visorhba is typically required for a Linux guest running under s-Par, as it
-is required if your guest boot disk is a virtual device provided by the s-Par
-back-end, which is the default configuration.  However, for advanced
-configurations where the Linux guest boots via an SR-IOV-provided HBA or
-SAN disk for example, visorhba is not technically required.
-
-visornic is typically required for a Linux guest running under s-Par, as it
-is required if your guest network interface is a virtual device provided by
-the s-Par back-end, which is the default configuration.  However, for
-configurations where the Linux guest is provided with an SR-IOV NIC
-for example, visornic is not technically required.
-
-visorinput is only required for a Linux guest running under s-Par if you
-require graphics-mode access to your guest console.
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 4/5] staging: unisys: visorbus: Have visorbus use include/linux/visorbus
  2016-05-17  7:27 [PATCH 0/5] add bus driver for Unisys s-Par paravirtualized devices to arch/x86 David Kershner
                   ` (2 preceding siblings ...)
  2016-05-17  7:27 ` [PATCH 3/5] Documentation: Move visorbus documentation from staging to Documentation/ David Kershner
@ 2016-05-17  7:28 ` David Kershner
  2016-05-17 13:52   ` Greg KH
  2016-05-17  7:28 ` [PATCH 5/5] arch: x86: add visorbus directory to arch/x86 David Kershner
  2016-05-17 13:51 ` [PATCH 0/5] add bus driver for Unisys s-Par paravirtualized devices " Greg KH
  5 siblings, 1 reply; 15+ messages in thread
From: David Kershner @ 2016-05-17  7:28 UTC (permalink / raw)
  To: corbet, tglx, mingo, hpa, david.kershner, gregkh, erik.arfvidson,
	timothy.sell, hofrat, dzickus, jes.sorensen, alexander.curtin,
	janani.rvchndrn, sudipm.mukherjee, prarit, david.binder, nhorman,
	dan.j.williams, linux-kernel, linux-doc, driverdev-devel,
	sparmaintainer

Since we have now moved the include directories over to
include/linux/visorbus this patch makes all of visorbus
use the new include folders.

Signed-off-by: David Kershner <david.kershner@unisys.com>
---
 drivers/staging/unisys/visorbus/controlvmchannel.h |  2 +-
 drivers/staging/unisys/visorbus/periodic_work.c    |  3 +--
 drivers/staging/unisys/visorbus/vbuschannel.h      |  3 ++-
 drivers/staging/unisys/visorbus/visorbus_main.c    |  8 ++++----
 drivers/staging/unisys/visorbus/visorchannel.c     |  4 ++--
 drivers/staging/unisys/visorbus/visorchipset.c     | 10 +++++-----
 drivers/staging/unisys/visorbus/vmcallinterface.h  |  5 ++---
 7 files changed, 17 insertions(+), 18 deletions(-)

diff --git a/drivers/staging/unisys/visorbus/controlvmchannel.h b/drivers/staging/unisys/visorbus/controlvmchannel.h
index 03e36fb..0a0e221 100644
--- a/drivers/staging/unisys/visorbus/controlvmchannel.h
+++ b/drivers/staging/unisys/visorbus/controlvmchannel.h
@@ -16,7 +16,7 @@
 #define __CONTROLVMCHANNEL_H__
 
 #include <linux/uuid.h>
-#include "channel.h"
+#include <linux/visorbus/channel.h>
 
 /* {2B3C2D10-7EF5-4ad8-B966-3448B7386B3D} */
 #define SPAR_CONTROLVM_CHANNEL_PROTOCOL_UUID	\
diff --git a/drivers/staging/unisys/visorbus/periodic_work.c b/drivers/staging/unisys/visorbus/periodic_work.c
index 00b1527..9b3b150 100644
--- a/drivers/staging/unisys/visorbus/periodic_work.c
+++ b/drivers/staging/unisys/visorbus/periodic_work.c
@@ -18,8 +18,7 @@
  *  Helper functions to schedule periodic work in Linux kernel mode.
  */
 #include <linux/sched.h>
-
-#include "periodic_work.h"
+#include <linux/visorbus/periodic_work.h>
 
 #define MYDRVNAME "periodic_work"
 
diff --git a/drivers/staging/unisys/visorbus/vbuschannel.h b/drivers/staging/unisys/visorbus/vbuschannel.h
index 90fa12e..3e0388d 100644
--- a/drivers/staging/unisys/visorbus/vbuschannel.h
+++ b/drivers/staging/unisys/visorbus/vbuschannel.h
@@ -23,8 +23,9 @@
  *  the client devices and client drivers for the server end to see.
  */
 #include <linux/uuid.h>
+#include <linux/visorbus/channel.h>
+
 #include "vbusdeviceinfo.h"
-#include "channel.h"
 
 /* {193b331b-c58f-11da-95a9-00e08161165f} */
 #define SPAR_VBUS_CHANNEL_PROTOCOL_UUID \
diff --git a/drivers/staging/unisys/visorbus/visorbus_main.c b/drivers/staging/unisys/visorbus/visorbus_main.c
index d32b898..efd87c6 100644
--- a/drivers/staging/unisys/visorbus/visorbus_main.c
+++ b/drivers/staging/unisys/visorbus/visorbus_main.c
@@ -16,12 +16,12 @@
 
 #include <linux/uuid.h>
 
-#include "visorbus.h"
+#include <linux/visorbus/visorbus.h>
+#include <linux/visorbus/version.h>
+#include <linux/visorbus/periodic_work.h>
+#include <linux/visorbus/guestlinuxdebug.h>
 #include "visorbus_private.h"
-#include "version.h"
-#include "periodic_work.h"
 #include "vbuschannel.h"
-#include "guestlinuxdebug.h"
 #include "vmcallinterface.h"
 
 #define MYDRVNAME "visorbus"
diff --git a/drivers/staging/unisys/visorbus/visorchannel.c b/drivers/staging/unisys/visorbus/visorchannel.c
index 4337358..4e8b0ef 100644
--- a/drivers/staging/unisys/visorbus/visorchannel.c
+++ b/drivers/staging/unisys/visorbus/visorchannel.c
@@ -22,8 +22,8 @@
 #include <linux/uuid.h>
 #include <linux/io.h>
 
-#include "version.h"
-#include "visorbus.h"
+#include <linux/visorbus/version.h>
+#include <linux/visorbus/visorbus.h>
 #include "controlvmchannel.h"
 
 #define MYDRVNAME "visorchannel"
diff --git a/drivers/staging/unisys/visorbus/visorchipset.c b/drivers/staging/unisys/visorbus/visorchipset.c
index 1a06baf..630137a 100644
--- a/drivers/staging/unisys/visorbus/visorchipset.c
+++ b/drivers/staging/unisys/visorbus/visorchipset.c
@@ -24,14 +24,14 @@
 #include <linux/platform_device.h>
 #include <linux/uuid.h>
 #include <linux/crash_dump.h>
+#include <linux/visorbus/channel_guid.h>
+#include <linux/visorbus/guestlinuxdebug.h>
+#include <linux/visorbus/periodic_work.h>
+#include <linux/visorbus/version.h>
+#include <linux/visorbus/visorbus.h>
 
-#include "channel_guid.h"
 #include "controlvmchannel.h"
 #include "controlvmcompletionstatus.h"
-#include "guestlinuxdebug.h"
-#include "periodic_work.h"
-#include "version.h"
-#include "visorbus.h"
 #include "visorbus_private.h"
 #include "vmcallinterface.h"
 
diff --git a/drivers/staging/unisys/visorbus/vmcallinterface.h b/drivers/staging/unisys/visorbus/vmcallinterface.h
index c043fa4..aac7000 100644
--- a/drivers/staging/unisys/visorbus/vmcallinterface.h
+++ b/drivers/staging/unisys/visorbus/vmcallinterface.h
@@ -21,10 +21,9 @@
 * running on IO Partitions.
 */
 
-#ifdef __GNUC__
+#include <linux/visorbus/diagchannel.h>
+
 #include "iovmcall_gnuc.h"
-#endif	/*  */
-#include "diagchannel.h"
 
 #ifdef VMCALL_IO_CONTROLVM_ADDR
 #undef VMCALL_IO_CONTROLVM_ADDR
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 5/5] arch: x86: add visorbus directory to arch/x86
  2016-05-17  7:27 [PATCH 0/5] add bus driver for Unisys s-Par paravirtualized devices to arch/x86 David Kershner
                   ` (3 preceding siblings ...)
  2016-05-17  7:28 ` [PATCH 4/5] staging: unisys: visorbus: Have visorbus use include/linux/visorbus David Kershner
@ 2016-05-17  7:28 ` David Kershner
  2016-05-17 13:51 ` [PATCH 0/5] add bus driver for Unisys s-Par paravirtualized devices " Greg KH
  5 siblings, 0 replies; 15+ messages in thread
From: David Kershner @ 2016-05-17  7:28 UTC (permalink / raw)
  To: corbet, tglx, mingo, hpa, david.kershner, gregkh, erik.arfvidson,
	timothy.sell, hofrat, dzickus, jes.sorensen, alexander.curtin,
	janani.rvchndrn, sudipm.mukherjee, prarit, david.binder, nhorman,
	dan.j.williams, linux-kernel, linux-doc, driverdev-devel,
	sparmaintainer

This patch adds the s-Par bus driver to the arch/x86 directory.
This location was chosen since the s-Par bus driver is dependent
on the x86 architecture.

Updates the KBuild and Kconfig files to include being able to
build it.

Signed-off-by: David Kershner <david.kershner@unisys.com>
---
 arch/x86/Kbuild                                    |    3 +
 arch/x86/Kconfig                                   |    2 +
 arch/x86/visorbus/Kconfig                          |   14 +
 arch/x86/visorbus/Makefile                         |    8 +
 arch/x86/visorbus/controlvmchannel.h               |  485 ++++
 arch/x86/visorbus/controlvmcompletionstatus.h      |  101 +
 arch/x86/visorbus/iovmcall_gnuc.h                  |   48 +
 arch/x86/visorbus/periodic_work.c                  |  203 ++
 arch/x86/visorbus/vbuschannel.h                    |   95 +
 arch/x86/visorbus/vbusdeviceinfo.h                 |  213 ++
 arch/x86/visorbus/vbushelper.h                     |   46 +
 arch/x86/visorbus/visorbus_main.c                  | 1344 +++++++++++
 arch/x86/visorbus/visorbus_private.h               |   68 +
 arch/x86/visorbus/visorchannel.c                   |  635 ++++++
 arch/x86/visorbus/visorchipset.c                   | 2355 ++++++++++++++++++++
 arch/x86/visorbus/vmcallinterface.h                |   91 +
 drivers/staging/unisys/Kconfig                     |    1 -
 drivers/staging/unisys/Makefile                    |    1 -
 drivers/staging/unisys/visorbus/Kconfig            |   14 -
 drivers/staging/unisys/visorbus/Makefile           |   12 -
 drivers/staging/unisys/visorbus/controlvmchannel.h |  485 ----
 .../unisys/visorbus/controlvmcompletionstatus.h    |  101 -
 drivers/staging/unisys/visorbus/iovmcall_gnuc.h    |   48 -
 drivers/staging/unisys/visorbus/periodic_work.c    |  203 --
 drivers/staging/unisys/visorbus/vbuschannel.h      |   95 -
 drivers/staging/unisys/visorbus/vbusdeviceinfo.h   |  213 --
 drivers/staging/unisys/visorbus/vbushelper.h       |   46 -
 drivers/staging/unisys/visorbus/visorbus_main.c    | 1344 -----------
 drivers/staging/unisys/visorbus/visorbus_private.h |   68 -
 drivers/staging/unisys/visorbus/visorchannel.c     |  635 ------
 drivers/staging/unisys/visorbus/visorchipset.c     | 2355 --------------------
 drivers/staging/unisys/visorbus/vmcallinterface.h  |   91 -
 32 files changed, 5711 insertions(+), 5712 deletions(-)
 create mode 100644 arch/x86/visorbus/Kconfig
 create mode 100644 arch/x86/visorbus/Makefile
 create mode 100644 arch/x86/visorbus/controlvmchannel.h
 create mode 100644 arch/x86/visorbus/controlvmcompletionstatus.h
 create mode 100644 arch/x86/visorbus/iovmcall_gnuc.h
 create mode 100644 arch/x86/visorbus/periodic_work.c
 create mode 100644 arch/x86/visorbus/vbuschannel.h
 create mode 100644 arch/x86/visorbus/vbusdeviceinfo.h
 create mode 100644 arch/x86/visorbus/vbushelper.h
 create mode 100644 arch/x86/visorbus/visorbus_main.c
 create mode 100644 arch/x86/visorbus/visorbus_private.h
 create mode 100644 arch/x86/visorbus/visorchannel.c
 create mode 100644 arch/x86/visorbus/visorchipset.c
 create mode 100644 arch/x86/visorbus/vmcallinterface.h
 delete mode 100644 drivers/staging/unisys/visorbus/Kconfig
 delete mode 100644 drivers/staging/unisys/visorbus/Makefile
 delete mode 100644 drivers/staging/unisys/visorbus/controlvmchannel.h
 delete mode 100644 drivers/staging/unisys/visorbus/controlvmcompletionstatus.h
 delete mode 100644 drivers/staging/unisys/visorbus/iovmcall_gnuc.h
 delete mode 100644 drivers/staging/unisys/visorbus/periodic_work.c
 delete mode 100644 drivers/staging/unisys/visorbus/vbuschannel.h
 delete mode 100644 drivers/staging/unisys/visorbus/vbusdeviceinfo.h
 delete mode 100644 drivers/staging/unisys/visorbus/vbushelper.h
 delete mode 100644 drivers/staging/unisys/visorbus/visorbus_main.c
 delete mode 100644 drivers/staging/unisys/visorbus/visorbus_private.h
 delete mode 100644 drivers/staging/unisys/visorbus/visorchannel.c
 delete mode 100644 drivers/staging/unisys/visorbus/visorchipset.c
 delete mode 100644 drivers/staging/unisys/visorbus/vmcallinterface.h

diff --git a/arch/x86/Kbuild b/arch/x86/Kbuild
index eb3abf8..6d08662 100644
--- a/arch/x86/Kbuild
+++ b/arch/x86/Kbuild
@@ -10,6 +10,9 @@ obj-$(CONFIG_XEN) += xen/
 # lguest paravirtualization support
 obj-$(CONFIG_LGUEST_GUEST) += lguest/
 
+# s-Par paravirtualization support
+obj-$(CONFIG_UNISYS_VISORBUS) += visorbus/
+
 obj-y += realmode/
 obj-y += kernel/
 obj-y += mm/
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 2dc18605..cd46482 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -770,6 +770,8 @@ config PARAVIRT_CLOCK
 
 endif #HYPERVISOR_GUEST
 
+source "arch/x86/visorbus/Kconfig"
+
 config NO_BOOTMEM
 	def_bool y
 
diff --git a/arch/x86/visorbus/Kconfig b/arch/x86/visorbus/Kconfig
new file mode 100644
index 0000000..5113880
--- /dev/null
+++ b/arch/x86/visorbus/Kconfig
@@ -0,0 +1,14 @@
+#
+# Unisys visorbus configuration
+#
+
+config UNISYS_VISORBUS
+	tristate "Unisys visorbus driver"
+	depends on UNISYSSPAR
+	---help---
+	The visorbus driver is a virtualized bus for the Unisys s-Par firmware.
+	Virtualized devices allow Linux guests on a system to share disks and
+	network cards that do not have SR-IOV support, and to be accessed using
+	the partition desktop application. The visorbus driver is required to
+	discover devices on an s-Par guest, and must be present for any other
+	s-Par guest driver to function correctly.
diff --git a/arch/x86/visorbus/Makefile b/arch/x86/visorbus/Makefile
new file mode 100644
index 0000000..206cd68
--- /dev/null
+++ b/arch/x86/visorbus/Makefile
@@ -0,0 +1,8 @@
+#
+# Makefile for Unisys visorbus
+#
+
+obj-$(CONFIG_UNISYS_VISORBUS)	+= visorbus.o
+
+visorbus-objs := visorbus_main.o visorchannel.o visorchipset.o periodic_work.o
+
diff --git a/arch/x86/visorbus/controlvmchannel.h b/arch/x86/visorbus/controlvmchannel.h
new file mode 100644
index 0000000..0a0e221
--- /dev/null
+++ b/arch/x86/visorbus/controlvmchannel.h
@@ -0,0 +1,485 @@
+/* Copyright (C) 2010 - 2015 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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 <linux/uuid.h>
+#include <linux/visorbus/channel.h>
+
+/* {2B3C2D10-7EF5-4ad8-B966-3448B7386B3D} */
+#define SPAR_CONTROLVM_CHANNEL_PROTOCOL_UUID	\
+		UUID_LE(0x2b3c2d10, 0x7ef5, 0x4ad8, \
+			0xb9, 0x66, 0x34, 0x48, 0xb7, 0x38, 0x6b, 0x3d)
+
+#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 SPAR_CONTROLVM_CHANNEL_OK_CLIENT(ch)           \
+	spar_check_channel_client(ch, \
+		SPAR_CONTROLVM_CHANNEL_PROTOCOL_UUID, \
+		"controlvm", \
+		sizeof(struct spar_controlvm_channel_protocol), \
+		ULTRA_CONTROLVM_CHANNEL_PROTOCOL_VERSIONID, \
+		ULTRA_CONTROLVM_CHANNEL_PROTOCOL_SIGNATURE)
+
+#define MAX_SERIAL_NUM	32
+
+/* 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 num of messages stored during IOVM creation to be reused after crash */
+#define CONTROLVM_CRASHMSG_MAX		2
+
+struct spar_segment_state  {
+	/* Bit 0: May enter other states */
+	u16 enabled:1;
+	/* Bit 1: Assigned to active partition */
+	u16 active:1;
+	/* Bit 2: Configure message sent to service/server */
+	u16 alive:1;
+	/* Bit 3: similar to partition state ShuttingDown */
+	u16 revoked:1;
+	/* Bit 4: memory (device/port number) has been selected by Command */
+	u16 allocated:1;
+	/* Bit 5: has been introduced to the service/guest partition */
+	u16 known:1;
+	/* Bit 6: service/Guest partition has responded to introduction */
+	u16 ready:1;
+	/* Bit 7: resource is configured and operating */
+	u16 operating:1;
+/* Note: don't use high bit unless we need to switch to ushort
+ * which is non-compliant
+ */
+};
+
+static const struct spar_segment_state segment_state_running = {
+	1, 1, 1, 0, 1, 1, 1, 1
+};
+
+static const struct spar_segment_state segment_state_paused = {
+	1, 1, 1, 0, 1, 1, 1, 0
+};
+
+static const struct spar_segment_state segment_state_standby = {
+	1, 1, 0, 0, 1, 1, 1, 0
+};
+
+/* 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
+ */
+enum controlvm_id {
+	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 */
+/* CHIPSET commands */
+	CONTROLVM_CHIPSET_INIT = 0x301,			/* CP --> SP, GP */
+	CONTROLVM_CHIPSET_STOP = 0x302,			/* CP --> SP, GP */
+	CONTROLVM_CHIPSET_READY = 0x304,		/* CP --> SP */
+	CONTROLVM_CHIPSET_SELFTEST = 0x305,		/* CP --> SP */
+
+};
+
+struct irq_info {
+	u64 reserved1;
+
+	 /* 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
+	  *   interrupt.  Used by IOPart-GP only.
+	  */
+	u64 recv_irq_handle;
+
+	 /* specifies interrupt vector. It, interrupt pin, and shared are
+	  *   used to connect to the corresponding interrupt.  Used by
+	  *   IOPart-GP only.
+	  */
+	u32 recv_irq_vector;
+
+    /* 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 recv_irq_shared;
+	u8 reserved[3];	/* Natural alignment purposes */
+};
+
+struct pci_id {
+	u16 domain;
+	u8 bus;
+	u8 slot;
+	u8 func;
+	u8 reserved[3];	/* Natural alignment purposes */
+};
+
+struct efi_spar_indication  {
+	u64 boot_to_fw_ui:1;		/* Bit 0: Stop in uefi ui */
+	u64 clear_nvram:1;		/* Bit 1: Clear NVRAM */
+	u64 clear_cmos:1;		/* Bit 2: Clear CMOS */
+	u64 boot_to_tool:1;		/* Bit 3: Run install tool */
+	/* remaining bits are available */
+};
+
+enum ultra_chipset_feature {
+	ULTRA_CHIPSET_FEATURE_REPLY = 0x00000001,
+	ULTRA_CHIPSET_FEATURE_PARA_HOTPLUG = 0x00000002,
+};
+
+/* 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.
+ */
+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. */
+
+	/* Includes size of this struct + size of message */
+	u32 message_size;
+	/* Index of segment containing Vm message/information */
+	u32 segment_index;
+	/* Error status code or result of  message completion */
+	u32 completion_status;
+	struct  {
+		/* =1 in a response to signify failure */
+		u32 failed:1;
+		/* =1 in all messages that expect a response */
+		u32 response_expected:1;
+		/* =1 in all bus & device-related messages where the message
+		 * receiver is to act as the bus or device server
+		 */
+		u32 server:1;
+		/* =1 for testing use only (Control and Command ignore this */
+		u32 test_message:1;
+		/* =1 if there are forthcoming responses/acks associated
+		 * with this message
+		 */
+		u32 partial_completion:1;
+		/* =1 this is to let us know to preserve channel contents */
+		u32 preserve:1;
+		/* =1 the DiagWriter is active in the Diagnostic Partition */
+		u32 writer_in_diag:1;
+	} flags;
+	/* Natural alignment */
+	u32 reserved;
+	/* Identifies the particular message instance */
+	u64 message_handle;
+	/* request instances with the corresponding response instance. */
+	/* Offset of payload area from start of this instance */
+	u64 payload_vm_offset;
+	/* Maximum bytes allocated in payload area of ControlVm segment */
+	u32 payload_max_bytes;
+	/* Actual number of bytes of payload area to copy between IO/Command */
+	u32 payload_bytes;
+	/* if non-zero, there is a payload to copy. */
+};
+
+struct controlvm_packet_device_create  {
+	u32 bus_no;		/* bus # (0..n-1) from the msg receiver's end */
+	u32 dev_no;		/* bus-relative (0..n-1) device number */
+	/* Guest physical address of the channel, which can be dereferenced by
+	 * the receiver of this ControlVm command
+	 */
+	u64 channel_addr;
+	u64 channel_bytes;	/* specifies size of the channel in bytes */
+	uuid_le data_type_uuid;	/* specifies format of data in channel */
+	uuid_le dev_inst_uuid;	/* instance guid for the device */
+	struct irq_info intr;	/* specifies interrupt information */
+};	/* for CONTROLVM_DEVICE_CREATE */
+
+struct controlvm_packet_device_configure  {
+	/* bus # (0..n-1) from the msg receiver's perspective */
+	u32 bus_no;
+	/* Control uses header SegmentIndex field to access bus number... */
+	u32 dev_no;	      /* bus-relative (0..n-1) device number */
+} ;	/* for CONTROLVM_DEVICE_CONFIGURE */
+
+struct controlvm_message_device_create {
+	struct controlvm_message_header header;
+	struct controlvm_packet_device_create packet;
+};	/* total 128 bytes */
+
+struct controlvm_message_device_configure  {
+	struct controlvm_message_header header;
+	struct controlvm_packet_device_configure packet;
+};	/* total 56 bytes */
+
+/* This is the format for a message in any ControlVm queue. */
+struct controlvm_message_packet  {
+	union  {
+		struct  {
+	/* bus # (0..n-1) from the msg receiver's perspective */
+			u32 bus_no;
+	/* indicates the max number of devices on this bus */
+			u32 dev_count;
+	/* Guest physical address of the channel, which can be
+	 * dereferenced by the receiver of this ControlVm command
+	 */
+			u64 channel_addr;
+			u64 channel_bytes;	/* size of the channel */
+	/* indicates format of data in bus channel*/
+			uuid_le bus_data_type_uuid;
+			uuid_le bus_inst_uuid;	/* instance uuid for the bus */
+		} create_bus;	/* for CONTROLVM_BUS_CREATE */
+		struct  {
+	/* bus # (0..n-1) from the msg receiver's perspective */
+			u32 bus_no;
+			u32 reserved;	/* Natural alignment purposes */
+		} destroy_bus;	/* for CONTROLVM_BUS_DESTROY */
+		struct  {
+	/* bus # (0..n-1) from the receiver's perspective */
+			u32 bus_no;
+			u32 reserved1;	/* for alignment purposes */
+	/* This is used to convert guest physical address to physical address */
+			u64 guest_handle;
+			u64 recv_bus_irq_handle;
+				/* 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.
+				 */
+		} configure_bus;	/* for CONTROLVM_BUS_CONFIGURE */
+		/* for CONTROLVM_DEVICE_CREATE */
+		struct controlvm_packet_device_create create_device;
+		struct  {
+		/* bus # (0..n-1) from the msg receiver's perspective */
+			u32 bus_no;
+			u32 dev_no;	/* bus-relative (0..n-1) device # */
+		} destroy_device;	/* for CONTROLVM_DEVICE_DESTROY */
+		/* for CONTROLVM_DEVICE_CONFIGURE */
+		struct controlvm_packet_device_configure configure_device;
+		struct  {
+		/* bus # (0..n-1) from the msg receiver's perspective */
+			u32 bus_no;
+			u32 dev_no;	/* bus-relative (0..n-1) device # */
+		} reconfigure_device;	/* for CONTROLVM_DEVICE_RECONFIGURE */
+		struct  {
+			u32 bus_no;
+			struct spar_segment_state state;
+			u8 reserved[2];	/* Natural alignment purposes */
+		} bus_change_state;	/* for CONTROLVM_BUS_CHANGESTATE */
+		struct  {
+			u32 bus_no;
+			u32 dev_no;
+			struct spar_segment_state state;
+			struct  {
+				/* =1 if message is for a physical device */
+				u32 phys_device:1;
+			} flags;
+			u8 reserved[2];	/* Natural alignment purposes */
+		} device_change_state;	/* for CONTROLVM_DEVICE_CHANGESTATE */
+		struct  {
+			u32 bus_no;
+			u32 dev_no;
+			struct spar_segment_state state;
+			u8 reserved[6];	/* Natural alignment purposes */
+		} device_change_state_event;
+			/* for CONTROLVM_DEVICE_CHANGESTATE_EVENT */
+		struct  {
+			/* indicates the max number of busses */
+			u32 bus_count;
+			/* indicates the max number of switches */
+			u32 switch_count;
+			enum ultra_chipset_feature features;
+			u32 platform_number;	/* Platform Number */
+		} init_chipset;	/* for CONTROLVM_CHIPSET_INIT */
+		struct  {
+			u32 options;	/* reserved */
+			u32 test;	/* bit 0 set to run embedded selftest */
+		} chipset_selftest;	/* for CONTROLVM_CHIPSET_SELFTEST */
+		/* a physical address of something, that can be dereferenced
+		 * by the receiver of this ControlVm command
+		 */
+		u64 addr;
+		/* a handle of something (depends on command id) */
+		u64 handle;
+	};
+};
+
+/* All messages in any ControlVm queue have this layout. */
+struct controlvm_message {
+	struct controlvm_message_header hdr;
+	struct controlvm_message_packet cmd;
+};
+
+struct spar_controlvm_channel_protocol {
+	struct channel_header header;
+	u64 gp_controlvm;	/* guest phys addr of this channel */
+	u64 gp_partition_tables;/* guest phys addr of partition tables */
+	u64 gp_diag_guest;	/* guest phys addr of diagnostic channel */
+	u64 gp_boot_romdisk;/* guest phys addr of (read* only) Boot ROM disk */
+	u64 gp_boot_ramdisk;/* guest phys addr of writable Boot RAM disk */
+	u64 gp_acpi_table;	/* guest phys addr of acpi table */
+	u64 gp_control_channel;/* guest phys addr of control channel */
+	u64 gp_diag_romdisk;/* guest phys addr of diagnostic ROM disk */
+	u64 gp_nvram;	/* guest phys addr of NVRAM channel */
+	u64 request_payload_offset;	/* Offset to request payload area */
+	u64 event_payload_offset;	/* Offset to event payload area */
+	/* Bytes available in request payload area */
+	u32 request_payload_bytes;
+	u32 event_payload_bytes;/* Bytes available in event payload area */
+	u32 control_channel_bytes;
+	u32 nvram_channel_bytes;	/* Bytes in PartitionNvram segment */
+	u32 message_bytes;		/* sizeof(CONTROLVM_MESSAGE) */
+	u32 message_count;		/* CONTROLVM_MESSAGE_MAX */
+	u64 gp_smbios_table;		/* guest phys addr of SMBIOS tables */
+	u64 gp_physical_smbios_table;	/* guest phys addr of SMBIOS table  */
+	/* ULTRA_MAX_GUESTS_PER_SERVICE */
+	char gp_reserved[2688];
+
+	/* guest physical address of EFI firmware image base  */
+	u64 virtual_guest_firmware_image_base;
+
+	/* guest physical address of EFI firmware entry point  */
+	u64 virtual_guest_firmware_entry_point;
+
+	/* guest EFI firmware image size  */
+	u64 virtual_guest_firmware_image_size;
+
+	/* GPA = 1MB where EFI firmware image is copied to  */
+	u64 virtual_guest_firmware_boot_base;
+	u64 virtual_guest_image_base;
+	u64 virtual_guest_image_size;
+	u64 prototype_control_channel_offset;
+	u64 virtual_guest_partition_handle;
+	/* Restore Action field to restore the guest partition */
+	u16 restore_action;
+	/* For Windows guests it shows if the visordisk is in dump mode */
+	u16 dump_action;
+	u16 nvram_fail_count;
+	u16 saved_crash_message_count;	/* = CONTROLVM_CRASHMSG_MAX */
+	/* Offset to request payload area needed for crash dump */
+	u32 saved_crash_message_offset;
+	/* Type of error encountered during installation */
+	u32 installation_error;
+	u32 installation_text_id;	/* Id of string to display */
+	/* Number of remaining installation  steps (for progress bars) */
+	u16 installation_remaining_steps;
+	/* ULTRA_TOOL_ACTIONS Installation Action field */
+	u8 tool_action;
+	u8 reserved;		/* alignment */
+	struct efi_spar_indication efi_spar_ind;
+	struct efi_spar_indication efi_spar_ind_supported;
+	u32 sp_reserved;
+	/* Force signals to begin on 128-byte cache line */
+	u8 reserved2[28];
+	/* guest partition uses this queue to send requests to Control */
+	struct signal_queue_header request_queue;
+	/* Control uses this queue to respond to service or guest
+	 * partition requests
+	 */
+	struct signal_queue_header response_queue;
+	/* Control uses this queue to send events to guest partition */
+	struct signal_queue_header event_queue;
+	/* Service or guest partition  uses this queue to ack Control events */
+	struct signal_queue_header event_ack_queue;
+	 /* Request fixed-size message pool - does not include payload */
+	 struct controlvm_message request_msg[CONTROLVM_MESSAGE_MAX];
+
+	 /* Response fixed-size message pool - does not include payload */
+	 struct controlvm_message response_msg[CONTROLVM_MESSAGE_MAX];
+
+	 /* Event fixed-size message pool - does not include payload */
+	 struct controlvm_message event_msg[CONTROLVM_MESSAGE_MAX];
+
+	 /* Ack fixed-size message pool - does not include payload */
+	 struct controlvm_message event_ack_msg[CONTROLVM_MESSAGE_MAX];
+
+	 /* Message stored during IOVM creation to be reused after crash */
+	 struct controlvm_message saved_crash_msg[CONTROLVM_CRASHMSG_MAX];
+};
+
+/* Offsets for VM channel attributes */
+#define VM_CH_REQ_QUEUE_OFFSET \
+	offsetof(struct spar_controlvm_channel_protocol, request_queue)
+#define VM_CH_RESP_QUEUE_OFFSET \
+	offsetof(struct spar_controlvm_channel_protocol, response_queue)
+#define VM_CH_EVENT_QUEUE_OFFSET \
+	offsetof(struct spar_controlvm_channel_protocol, event_queue)
+#define VM_CH_ACK_QUEUE_OFFSET \
+	offsetof(struct spar_controlvm_channel_protocol, event_ack_queue)
+#define VM_CH_REQ_MSG_OFFSET \
+	offsetof(struct spar_controlvm_channel_protocol, request_msg)
+#define VM_CH_RESP_MSG_OFFSET \
+	offsetof(struct spar_controlvm_channel_protocol, response_msg)
+#define VM_CH_EVENT_MSG_OFFSET \
+	offsetof(struct spar_controlvm_channel_protocol, event_msg)
+#define VM_CH_ACK_MSG_OFFSET \
+	offsetof(struct spar_controlvm_channel_protocol, event_ack_msg)
+#define VM_CH_CRASH_MSG_OFFSET \
+	offsetof(struct spar_controlvm_channel_protocol, saved_crash_msg)
+
+/* 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 connection_offset,
+ * initiator_offset, and target_offset to get the location of UTF-8 formatted
+ * strings that can be parsed to obtain command-specific information. The value
+ * of total_length should equal PayloadBytes. The format of the strings at
+ * PayloadVmOffset will take different forms depending on the message.
+ */
+struct spar_controlvm_parameters_header {
+	u32 total_length;
+	u32 header_length;
+	u32 connection_offset;
+	u32 connection_length;
+	u32 initiator_offset;
+	u32 initiator_length;
+	u32 target_offset;
+	u32 target_length;
+	u32 client_offset;
+	u32 client_length;
+	u32 name_offset;
+	u32 name_length;
+	uuid_le id;
+	u32 revision;
+	u32 reserved;		/* Natural alignment */
+};
+
+#endif				/* __CONTROLVMCHANNEL_H__ */
diff --git a/arch/x86/visorbus/controlvmcompletionstatus.h b/arch/x86/visorbus/controlvmcompletionstatus.h
new file mode 100644
index 0000000..23ad0ea
--- /dev/null
+++ b/arch/x86/visorbus/controlvmcompletionstatus.h
@@ -0,0 +1,101 @@
+/* controlvmcompletionstatus.c
+ *
+ * Copyright (C) 2010 - 2015 UNISYS CORPORATION
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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/arch/x86/visorbus/iovmcall_gnuc.h b/arch/x86/visorbus/iovmcall_gnuc.h
new file mode 100644
index 0000000..98ea7f3
--- /dev/null
+++ b/arch/x86/visorbus/iovmcall_gnuc.h
@@ -0,0 +1,48 @@
+/* Copyright (C) 2010 - 2015 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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))
+		return -EPERM;
+
+	__asm__ __volatile__(".byte 0x00f, 0x001, 0x0c1" : "=a"(result) :
+		"a"(tuple), "b"(reg_ebx), "c"(reg_ecx));
+	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))
+		return -EPERM;
+
+	__asm__ __volatile__(".byte 0x00f, 0x001, 0x0c1" : "=a"(result) :
+		"a"(tuple), "b"(reg_ebx), "c"(reg_ecx), "d"(reg_edx));
+	return result;
+}
diff --git a/arch/x86/visorbus/periodic_work.c b/arch/x86/visorbus/periodic_work.c
new file mode 100644
index 0000000..9b3b150
--- /dev/null
+++ b/arch/x86/visorbus/periodic_work.c
@@ -0,0 +1,203 @@
+/* periodic_work.c
+ *
+ * Copyright (C) 2010 - 2015 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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 <linux/sched.h>
+#include <linux/visorbus/periodic_work.h>
+
+#define MYDRVNAME "periodic_work"
+
+struct periodic_work {
+	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)
+{
+	struct periodic_work *pw;
+
+	pw = container_of(work, struct periodic_work, work.work);
+	(*pw->workfunc)(pw->workfuncarg);
+}
+
+struct periodic_work
+*visor_periodic_work_create(ulong jiffy_interval,
+			    struct workqueue_struct *workqueue,
+			    void (*workfunc)(void *),
+			    void *workfuncarg,
+			    const char *devnam)
+{
+	struct periodic_work *pw;
+
+	pw = kzalloc(sizeof(*pw), GFP_KERNEL | __GFP_NORETRY);
+	if (!pw)
+		return NULL;
+
+	rwlock_init(&pw->lock);
+	pw->jiffy_interval = jiffy_interval;
+	pw->workqueue = workqueue;
+	pw->workfunc = workfunc;
+	pw->workfuncarg = workfuncarg;
+	pw->devnam = devnam;
+	return pw;
+}
+EXPORT_SYMBOL_GPL(visor_periodic_work_create);
+
+void visor_periodic_work_destroy(struct periodic_work *pw)
+{
+	kfree(pw);
+}
+EXPORT_SYMBOL_GPL(visor_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 visor_periodic_work_nextperiod(struct periodic_work *pw)
+{
+	bool rc = false;
+
+	write_lock(&pw->lock);
+	if (pw->want_to_stop) {
+		pw->is_scheduled = false;
+		pw->want_to_stop = false;
+		rc = true;  /* yes, true; see visor_periodic_work_stop() */
+		goto unlock;
+	} else if (!queue_delayed_work(pw->workqueue, &pw->work,
+				       pw->jiffy_interval)) {
+		pw->is_scheduled = false;
+		rc = false;
+		goto unlock;
+	}
+	rc = true;
+unlock:
+	write_unlock(&pw->lock);
+	return rc;
+}
+EXPORT_SYMBOL_GPL(visor_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 visor_periodic_work_start(struct periodic_work *pw)
+{
+	bool rc = false;
+
+	write_lock(&pw->lock);
+	if (pw->is_scheduled) {
+		rc = false;
+		goto unlock;
+	}
+	if (pw->want_to_stop) {
+		rc = false;
+		goto unlock;
+	}
+	INIT_DELAYED_WORK(&pw->work, &periodic_work_func);
+	if (!queue_delayed_work(pw->workqueue, &pw->work,
+				pw->jiffy_interval)) {
+		rc = false;
+		goto unlock;
+	}
+	pw->is_scheduled = true;
+	rc = true;
+unlock:
+	write_unlock(&pw->lock);
+	return rc;
+}
+EXPORT_SYMBOL_GPL(visor_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, visor_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 visor_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 visor_periodic_work_stop(struct periodic_work *pw)
+{
+	bool stopped_something = false;
+
+	write_lock(&pw->lock);
+	stopped_something = pw->is_scheduled && (!pw->want_to_stop);
+	while (pw->is_scheduled) {
+		pw->want_to_stop = true;
+		if (cancel_delayed_work(&pw->work)) {
+			/* We get here if the delayed work was pending as
+			 * delayed work, but was NOT run.
+			 */
+			WARN_ON(!pw->is_scheduled);
+			pw->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 (pw->is_scheduled) {
+			write_unlock(&pw->lock);
+			schedule_timeout_interruptible(msecs_to_jiffies(10));
+			write_lock(&pw->lock);
+		} else {
+			pw->want_to_stop = false;
+		}
+	}
+	write_unlock(&pw->lock);
+	return stopped_something;
+}
+EXPORT_SYMBOL_GPL(visor_periodic_work_stop);
diff --git a/arch/x86/visorbus/vbuschannel.h b/arch/x86/visorbus/vbuschannel.h
new file mode 100644
index 0000000..3e0388d
--- /dev/null
+++ b/arch/x86/visorbus/vbuschannel.h
@@ -0,0 +1,95 @@
+/* Copyright (C) 2010 - 2015 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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 <linux/uuid.h>
+#include <linux/visorbus/channel.h>
+
+#include "vbusdeviceinfo.h"
+
+/* {193b331b-c58f-11da-95a9-00e08161165f} */
+#define SPAR_VBUS_CHANNEL_PROTOCOL_UUID \
+		UUID_LE(0x193b331b, 0xc58f, 0x11da, \
+				0x95, 0xa9, 0x0, 0xe0, 0x81, 0x61, 0x16, 0x5f)
+static const uuid_le spar_vbus_channel_protocol_uuid =
+	SPAR_VBUS_CHANNEL_PROTOCOL_UUID;
+
+#define SPAR_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 SPAR_VBUS_CHANNEL_PROTOCOL_VERSIONID 1
+
+#define SPAR_VBUS_CHANNEL_OK_CLIENT(ch)       \
+	spar_check_channel_client(ch,				\
+				   spar_vbus_channel_protocol_uuid,	\
+				   "vbus",				\
+				   sizeof(struct spar_vbus_channel_protocol),\
+				   SPAR_VBUS_CHANNEL_PROTOCOL_VERSIONID, \
+				   SPAR_VBUS_CHANNEL_PROTOCOL_SIGNATURE)
+
+#define SPAR_VBUS_CHANNEL_OK_SERVER(actual_bytes)    \
+	(spar_check_channel_server(spar_vbus_channel_protocol_uuid,	\
+				   "vbus",				\
+				   sizeof(struct spar_vbus_channel_protocol),\
+				   actual_bytes))
+
+#pragma pack(push, 1)		/* both GCC and VC now allow this pragma */
+struct spar_vbus_headerinfo {
+	u32 struct_bytes;	/* size of this struct in bytes */
+	u32 device_info_struct_bytes;	/* sizeof(ULTRA_VBUS_DEVICEINFO) */
+	u32 dev_info_count;	/* num of items in DevInfo member */
+	/* (this is the allocated size) */
+	u32 chp_info_offset;	/* byte offset from beginning of this struct */
+	/* to the ChpInfo struct (below) */
+	u32 bus_info_offset;	/* byte offset from beginning of this struct */
+	/* to the BusInfo struct (below) */
+	u32 dev_info_offset;	/* byte offset from beginning of this struct */
+	/* to the DevInfo array (below) */
+	u8 reserved[104];
+};
+
+struct spar_vbus_channel_protocol {
+	struct channel_header channel_header;	/* initialized by server */
+	struct spar_vbus_headerinfo hdr_info;	/* initialized by server */
+	/* the remainder of this channel is filled in by the client */
+	struct ultra_vbus_deviceinfo chp_info;
+	/* describes client chipset device and driver */
+	struct ultra_vbus_deviceinfo bus_info;
+	/* describes client bus device and driver */
+	struct ultra_vbus_deviceinfo dev_info[0];
+	/* describes client device and driver for each device on the bus */
+};
+
+#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)
+
+#pragma pack(pop)
+
+#endif
diff --git a/arch/x86/visorbus/vbusdeviceinfo.h b/arch/x86/visorbus/vbusdeviceinfo.h
new file mode 100644
index 0000000..abdab4a
--- /dev/null
+++ b/arch/x86/visorbus/vbusdeviceinfo.h
@@ -0,0 +1,213 @@
+/* Copyright (C) 2010 - 2015 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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 <linux/types.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.
+ */
+struct ultra_vbus_deviceinfo {
+	u8 devtype[16];		/* short string identifying the device type */
+	u8 drvname[16];		/* driver .sys file name */
+	u8 infostrs[96];	/* sequence of tab-delimited id strings: */
+	/* <DRIVER_REV> <DRIVER_VERTAG> <DRIVER_COMPILETIME> */
+	u8 reserved[128];	/* pad size to 256 bytes */
+};
+
+#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) {
+					chars++;
+				}
+				nonprintable_streak = 0;
+			}
+			if (remain > 0) {
+				*p = *src;
+				p++;
+				remain--;
+				chars++;
+			} else if (!p) {
+				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_devinfo_to_string(struct 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->infostrs[0];
+	nsrc = sizeof(devinfo->infostrs);
+	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/arch/x86/visorbus/vbushelper.h b/arch/x86/visorbus/vbushelper.h
new file mode 100644
index 0000000..f1b6aac
--- /dev/null
+++ b/arch/x86/visorbus/vbushelper.h
@@ -0,0 +1,46 @@
+/* vbushelper.h
+ *
+ * Copyright (C) 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__
+
+/* TARGET_HOSTNAME specified as -DTARGET_HOSTNAME=\"thename\" on the
+ * command line
+ */
+
+#define TARGET_HOSTNAME "linuxguest"
+
+static inline void bus_device_info_init(
+		struct ultra_vbus_deviceinfo *bus_device_info_ptr,
+		const char *dev_type, const char *drv_name,
+		const char *ver, const char *ver_tag)
+{
+	memset(bus_device_info_ptr, 0, sizeof(struct ultra_vbus_deviceinfo));
+	snprintf(bus_device_info_ptr->devtype,
+		 sizeof(bus_device_info_ptr->devtype),
+		 "%s", (dev_type) ? dev_type : "unknownType");
+	snprintf(bus_device_info_ptr->drvname,
+		 sizeof(bus_device_info_ptr->drvname),
+		 "%s", (drv_name) ? drv_name : "unknownDriver");
+	snprintf(bus_device_info_ptr->infostrs,
+		 sizeof(bus_device_info_ptr->infostrs), "%s\t%s\t%s",
+		 (ver) ? ver : "unknownVer",
+		 (ver_tag) ? ver_tag : "unknownVerTag",
+		 TARGET_HOSTNAME);
+}
+
+#endif
diff --git a/arch/x86/visorbus/visorbus_main.c b/arch/x86/visorbus/visorbus_main.c
new file mode 100644
index 0000000..efd87c6
--- /dev/null
+++ b/arch/x86/visorbus/visorbus_main.c
@@ -0,0 +1,1344 @@
+/* visorbus_main.c
+ *
+ * Copyright � 2010 - 2015 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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/uuid.h>
+
+#include <linux/visorbus/visorbus.h>
+#include <linux/visorbus/version.h>
+#include <linux/visorbus/periodic_work.h>
+#include <linux/visorbus/guestlinuxdebug.h>
+#include "visorbus_private.h"
+#include "vbuschannel.h"
+#include "vmcallinterface.h"
+
+#define MYDRVNAME "visorbus"
+
+/* module parameters */
+static int visorbus_debug;
+static int visorbus_forcematch;
+static int visorbus_forcenomatch;
+static int visorbus_debugref;
+#define SERIALLOOPBACKCHANADDR (100 * 1024 * 1024)
+
+/* Display string that is guaranteed to be no longer the 99 characters*/
+#define LINESIZE 99
+
+#define CURRENT_FILE_PC VISOR_BUS_PC_visorbus_main_c
+#define POLLJIFFIES_TESTWORK         100
+#define POLLJIFFIES_NORMALCHANNEL     10
+
+static int busreg_rc = -ENODEV; /* stores the result from bus registration */
+
+static int visorbus_uevent(struct device *xdev, struct kobj_uevent_env *env);
+static int visorbus_match(struct device *xdev, struct device_driver *xdrv);
+static void fix_vbus_dev_info(struct visor_device *visordev);
+
+/*  BUS type attributes
+ *
+ *  define & implement display of bus attributes under
+ *  /sys/bus/visorbus.
+ *
+ */
+
+static ssize_t version_show(struct bus_type *bus, char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%s\n", VERSION);
+}
+
+static BUS_ATTR_RO(version);
+
+static struct attribute *visorbus_bus_attrs[] = {
+	&bus_attr_version.attr,
+	NULL,
+};
+
+static const struct attribute_group visorbus_bus_group = {
+	.attrs = visorbus_bus_attrs,
+};
+
+static const struct attribute_group *visorbus_bus_groups[] = {
+	&visorbus_bus_group,
+	NULL,
+};
+
+/*
+ * DEVICE type attributes
+ *
+ * The modalias file will contain the guid of the device.
+ */
+static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
+			     char *buf)
+{
+	struct visor_device *vdev;
+	uuid_le guid;
+
+	vdev = to_visor_device(dev);
+	guid = visorchannel_get_uuid(vdev->visorchannel);
+	return snprintf(buf, PAGE_SIZE, "visorbus:%pUl\n", &guid);
+}
+static DEVICE_ATTR_RO(modalias);
+
+static struct attribute *visorbus_dev_attrs[] = {
+	&dev_attr_modalias.attr,
+	NULL,
+};
+
+/* sysfs example for bridge-only sysfs files using device_type's */
+static const struct attribute_group visorbus_dev_group = {
+	.attrs = visorbus_dev_attrs,
+};
+
+static const struct attribute_group *visorbus_dev_groups[] = {
+	&visorbus_dev_group,
+	NULL,
+};
+
+/** This describes the TYPE of bus.
+ *  (Don't confuse this with an INSTANCE of the bus.)
+ */
+struct bus_type visorbus_type = {
+	.name = "visorbus",
+	.match = visorbus_match,
+	.uevent = visorbus_uevent,
+	.dev_groups = visorbus_dev_groups,
+	.bus_groups = visorbus_bus_groups,
+};
+
+static struct delayed_work periodic_work;
+
+/* YES, we need 2 workqueues.
+ * The reason is, workitems on the test queue may need to cancel
+ * workitems on the other queue.  You will be in for trouble if you try to
+ * do this with workitems queued on the same workqueue.
+ */
+static struct workqueue_struct *periodic_test_workqueue;
+static struct workqueue_struct *periodic_dev_workqueue;
+static long long bus_count;	/** number of bus instances */
+					/** ever-increasing */
+
+static void chipset_bus_create(struct visor_device *bus_info);
+static void chipset_bus_destroy(struct visor_device *bus_info);
+static void chipset_device_create(struct visor_device *dev_info);
+static void chipset_device_destroy(struct visor_device *dev_info);
+static void chipset_device_pause(struct visor_device *dev_info);
+static void chipset_device_resume(struct visor_device *dev_info);
+
+/** These functions are implemented herein, and are called by the chipset
+ *  driver to notify us about specific events.
+ */
+static struct visorchipset_busdev_notifiers chipset_notifiers = {
+	.bus_create = chipset_bus_create,
+	.bus_destroy = chipset_bus_destroy,
+	.device_create = chipset_device_create,
+	.device_destroy = chipset_device_destroy,
+	.device_pause = chipset_device_pause,
+	.device_resume = chipset_device_resume,
+};
+
+/** These functions are implemented in the chipset driver, and we call them
+ *  herein when we want to acknowledge a specific event.
+ */
+static struct visorchipset_busdev_responders chipset_responders;
+
+/* filled in with info about parent chipset driver when we register with it */
+static struct ultra_vbus_deviceinfo chipset_driverinfo;
+/* filled in with info about this driver, wrt it servicing client busses */
+static struct ultra_vbus_deviceinfo clientbus_driverinfo;
+
+/** list of visor_device structs, linked via .list_all */
+static LIST_HEAD(list_all_bus_instances);
+/** list of visor_device structs, linked via .list_all */
+static LIST_HEAD(list_all_device_instances);
+
+static int
+visorbus_uevent(struct device *xdev, struct kobj_uevent_env *env)
+{
+	struct visor_device *dev;
+	uuid_le guid;
+
+	dev = to_visor_device(xdev);
+	guid = visorchannel_get_uuid(dev->visorchannel);
+
+	if (add_uevent_var(env, "MODALIAS=visorbus:%pUl", &guid))
+		return -ENOMEM;
+	return 0;
+}
+
+/* This is called automatically upon adding a visor_device (device_add), or
+ * adding a visor_driver (visorbus_register_visor_driver), and returns 1 iff the
+ * provided driver can control the specified device.
+ */
+static int
+visorbus_match(struct device *xdev, struct device_driver *xdrv)
+{
+	uuid_le channel_type;
+	int i;
+	struct visor_device *dev;
+	struct visor_driver *drv;
+
+	dev = to_visor_device(xdev);
+	drv = to_visor_driver(xdrv);
+	channel_type = visorchannel_get_uuid(dev->visorchannel);
+
+	if (visorbus_forcematch)
+		return 1;
+	if (visorbus_forcenomatch)
+		return 0;
+	if (!drv->channel_types)
+		return 0;
+
+	for (i = 0;
+	     (uuid_le_cmp(drv->channel_types[i].guid, NULL_UUID_LE) != 0) ||
+	     (drv->channel_types[i].name);
+	     i++)
+		if (uuid_le_cmp(drv->channel_types[i].guid,
+				channel_type) == 0)
+			return i + 1;
+
+	return 0;
+}
+
+/** This is called when device_unregister() is called for the bus device
+ *  instance, after all other tasks involved with destroying the device
+ *  are complete.
+ */
+static void
+visorbus_release_busdevice(struct device *xdev)
+{
+	struct visor_device *dev = dev_get_drvdata(xdev);
+
+	kfree(dev);
+}
+
+/** This is called when device_unregister() is called for each child
+ *  device instance.
+ */
+static void
+visorbus_release_device(struct device *xdev)
+{
+	struct visor_device *dev = to_visor_device(xdev);
+
+	if (dev->periodic_work) {
+		visor_periodic_work_destroy(dev->periodic_work);
+		dev->periodic_work = NULL;
+	}
+	if (dev->visorchannel) {
+		visorchannel_destroy(dev->visorchannel);
+		dev->visorchannel = NULL;
+	}
+	kfree(dev);
+}
+
+/* begin implementation of specific channel attributes to appear under
+* /sys/bus/visorbus<x>/dev<y>/channel
+*/
+static ssize_t physaddr_show(struct device *dev, struct device_attribute *attr,
+			     char *buf)
+{
+	struct visor_device *vdev = to_visor_device(dev);
+
+	if (!vdev->visorchannel)
+		return 0;
+	return snprintf(buf, PAGE_SIZE, "0x%llx\n",
+			visorchannel_get_physaddr(vdev->visorchannel));
+}
+
+static ssize_t nbytes_show(struct device *dev, struct device_attribute *attr,
+			   char *buf)
+{
+	struct visor_device *vdev = to_visor_device(dev);
+
+	if (!vdev->visorchannel)
+		return 0;
+	return snprintf(buf, PAGE_SIZE, "0x%lx\n",
+			visorchannel_get_nbytes(vdev->visorchannel));
+}
+
+static ssize_t clientpartition_show(struct device *dev,
+				    struct device_attribute *attr, char *buf)
+{
+	struct visor_device *vdev = to_visor_device(dev);
+
+	if (!vdev->visorchannel)
+		return 0;
+	return snprintf(buf, PAGE_SIZE, "0x%llx\n",
+			visorchannel_get_clientpartition(vdev->visorchannel));
+}
+
+static ssize_t typeguid_show(struct device *dev, struct device_attribute *attr,
+			     char *buf)
+{
+	struct visor_device *vdev = to_visor_device(dev);
+	char typeid[LINESIZE];
+
+	if (!vdev->visorchannel)
+		return 0;
+	return snprintf(buf, PAGE_SIZE, "%s\n",
+			visorchannel_id(vdev->visorchannel, typeid));
+}
+
+static ssize_t zoneguid_show(struct device *dev, struct device_attribute *attr,
+			     char *buf)
+{
+	struct visor_device *vdev = to_visor_device(dev);
+	char zoneid[LINESIZE];
+
+	if (!vdev->visorchannel)
+		return 0;
+	return snprintf(buf, PAGE_SIZE, "%s\n",
+			visorchannel_zoneid(vdev->visorchannel, zoneid));
+}
+
+static ssize_t typename_show(struct device *dev, struct device_attribute *attr,
+			     char *buf)
+{
+	struct visor_device *vdev = to_visor_device(dev);
+	int i = 0;
+	struct bus_type *xbus = dev->bus;
+	struct device_driver *xdrv = dev->driver;
+	struct visor_driver *drv = NULL;
+
+	if (!vdev->visorchannel || !xbus || !xdrv)
+		return 0;
+	i = xbus->match(dev, xdrv);
+	if (!i)
+		return 0;
+	drv = to_visor_driver(xdrv);
+	return snprintf(buf, PAGE_SIZE, "%s\n", drv->channel_types[i - 1].name);
+}
+
+static DEVICE_ATTR_RO(physaddr);
+static DEVICE_ATTR_RO(nbytes);
+static DEVICE_ATTR_RO(clientpartition);
+static DEVICE_ATTR_RO(typeguid);
+static DEVICE_ATTR_RO(zoneguid);
+static DEVICE_ATTR_RO(typename);
+
+static struct attribute *channel_attrs[] = {
+		&dev_attr_physaddr.attr,
+		&dev_attr_nbytes.attr,
+		&dev_attr_clientpartition.attr,
+		&dev_attr_typeguid.attr,
+		&dev_attr_zoneguid.attr,
+		&dev_attr_typename.attr,
+		NULL
+};
+
+static struct attribute_group channel_attr_grp = {
+		.name = "channel",
+		.attrs = channel_attrs,
+};
+
+static const struct attribute_group *visorbus_channel_groups[] = {
+		&channel_attr_grp,
+		NULL
+};
+
+/* end implementation of specific channel attributes */
+
+/*  BUS instance attributes
+ *
+ *  define & implement display of bus attributes under
+ *  /sys/bus/visorbus/busses/visorbus<n>.
+ *
+ *  This is a bit hoaky because the kernel does not yet have the infrastructure
+ *  to separate bus INSTANCE attributes from bus TYPE attributes...
+ *  so we roll our own.  See businst.c / businst.h.
+ *
+ */
+
+static ssize_t partition_handle_show(struct device *dev,
+				     struct device_attribute *attr,
+				     char *buf) {
+	struct visor_device *vdev = to_visor_device(dev);
+	u64 handle = visorchannel_get_clientpartition(vdev->visorchannel);
+
+	return snprintf(buf, PAGE_SIZE, "0x%llx\n", handle);
+}
+
+static ssize_t partition_guid_show(struct device *dev,
+				   struct device_attribute *attr,
+				   char *buf) {
+	struct visor_device *vdev = to_visor_device(dev);
+
+	return snprintf(buf, PAGE_SIZE, "{%pUb}\n", &vdev->partition_uuid);
+}
+
+static ssize_t partition_name_show(struct device *dev,
+				   struct device_attribute *attr,
+				   char *buf) {
+	struct visor_device *vdev = to_visor_device(dev);
+
+	return snprintf(buf, PAGE_SIZE, "%s\n", vdev->name);
+}
+
+static ssize_t channel_addr_show(struct device *dev,
+				 struct device_attribute *attr,
+				 char *buf) {
+	struct visor_device *vdev = to_visor_device(dev);
+	u64 addr = visorchannel_get_physaddr(vdev->visorchannel);
+
+	return snprintf(buf, PAGE_SIZE, "0x%llx\n", addr);
+}
+
+static ssize_t channel_bytes_show(struct device *dev,
+				  struct device_attribute *attr,
+				  char *buf) {
+	struct visor_device *vdev = to_visor_device(dev);
+	u64 nbytes = visorchannel_get_nbytes(vdev->visorchannel);
+
+	return snprintf(buf, PAGE_SIZE, "0x%llx\n", nbytes);
+}
+
+static ssize_t channel_id_show(struct device *dev,
+			       struct device_attribute *attr,
+			       char *buf) {
+	struct visor_device *vdev = to_visor_device(dev);
+	int len = 0;
+
+	if (vdev->visorchannel) {
+		visorchannel_id(vdev->visorchannel, buf);
+		len = strlen(buf);
+		buf[len++] = '\n';
+	}
+	return len;
+}
+
+static ssize_t client_bus_info_show(struct device *dev,
+				    struct device_attribute *attr,
+				    char *buf) {
+	struct visor_device *vdev = to_visor_device(dev);
+	struct visorchannel *channel = vdev->visorchannel;
+
+	int i, shift, remain = PAGE_SIZE;
+	unsigned long off;
+	char *pos = buf;
+	u8 *partition_name;
+	struct ultra_vbus_deviceinfo dev_info;
+
+	partition_name = "";
+	if (channel) {
+		if (vdev->name)
+			partition_name = vdev->name;
+		shift = snprintf(pos, remain,
+				 "Client device / client driver info for %s eartition (vbus #%d):\n",
+				 partition_name, vdev->chipset_dev_no);
+		pos += shift;
+		remain -= shift;
+		shift = visorchannel_read(channel,
+					  offsetof(struct
+						   spar_vbus_channel_protocol,
+						   chp_info),
+					  &dev_info, sizeof(dev_info));
+		if (shift >= 0) {
+			shift = vbuschannel_devinfo_to_string(&dev_info, pos,
+							      remain, -1);
+			pos += shift;
+			remain -= shift;
+		}
+		shift = visorchannel_read(channel,
+					  offsetof(struct
+						   spar_vbus_channel_protocol,
+						   bus_info),
+					  &dev_info, sizeof(dev_info));
+		if (shift >= 0) {
+			shift = vbuschannel_devinfo_to_string(&dev_info, pos,
+							      remain, -1);
+			pos += shift;
+			remain -= shift;
+		}
+		off = offsetof(struct spar_vbus_channel_protocol, dev_info);
+		i = 0;
+		while (off + sizeof(dev_info) <=
+		       visorchannel_get_nbytes(channel)) {
+			shift = visorchannel_read(channel,
+						  off, &dev_info,
+						  sizeof(dev_info));
+			if (shift >= 0) {
+				shift = vbuschannel_devinfo_to_string
+				    (&dev_info, pos, remain, i);
+				pos += shift;
+				remain -= shift;
+			}
+			off += sizeof(dev_info);
+			i++;
+		}
+	}
+	return PAGE_SIZE - remain;
+}
+
+static DEVICE_ATTR_RO(partition_handle);
+static DEVICE_ATTR_RO(partition_guid);
+static DEVICE_ATTR_RO(partition_name);
+static DEVICE_ATTR_RO(channel_addr);
+static DEVICE_ATTR_RO(channel_bytes);
+static DEVICE_ATTR_RO(channel_id);
+static DEVICE_ATTR_RO(client_bus_info);
+
+static struct attribute *dev_attrs[] = {
+		&dev_attr_partition_handle.attr,
+		&dev_attr_partition_guid.attr,
+		&dev_attr_partition_name.attr,
+		&dev_attr_channel_addr.attr,
+		&dev_attr_channel_bytes.attr,
+		&dev_attr_channel_id.attr,
+		&dev_attr_client_bus_info.attr,
+		NULL
+};
+
+static struct attribute_group dev_attr_grp = {
+		.attrs = dev_attrs,
+};
+
+static const struct attribute_group *visorbus_groups[] = {
+		&dev_attr_grp,
+		NULL
+};
+
+/*  DRIVER attributes
+ *
+ *  define & implement display of driver attributes under
+ *  /sys/bus/visorbus/drivers/<drivername>.
+ *
+ */
+
+static ssize_t
+DRIVER_ATTR_version(struct device_driver *xdrv, char *buf)
+{
+	struct visor_driver *drv = to_visor_driver(xdrv);
+
+	return snprintf(buf, PAGE_SIZE, "%s\n", drv->version);
+}
+
+static int
+register_driver_attributes(struct visor_driver *drv)
+{
+	struct driver_attribute version =
+	    __ATTR(version, S_IRUGO, DRIVER_ATTR_version, NULL);
+	drv->version_attr = version;
+	return driver_create_file(&drv->driver, &drv->version_attr);
+}
+
+static void
+unregister_driver_attributes(struct visor_driver *drv)
+{
+	driver_remove_file(&drv->driver, &drv->version_attr);
+}
+
+static void
+dev_periodic_work(void *xdev)
+{
+	struct visor_device *dev = xdev;
+	struct visor_driver *drv = to_visor_driver(dev->device.driver);
+
+	down(&dev->visordriver_callback_lock);
+	if (drv->channel_interrupt)
+		drv->channel_interrupt(dev);
+	up(&dev->visordriver_callback_lock);
+	if (!visor_periodic_work_nextperiod(dev->periodic_work))
+		put_device(&dev->device);
+}
+
+static void
+dev_start_periodic_work(struct visor_device *dev)
+{
+	if (dev->being_removed)
+		return;
+	/* now up by at least 2 */
+	get_device(&dev->device);
+	if (!visor_periodic_work_start(dev->periodic_work))
+		put_device(&dev->device);
+}
+
+static void
+dev_stop_periodic_work(struct visor_device *dev)
+{
+	if (visor_periodic_work_stop(dev->periodic_work))
+		put_device(&dev->device);
+}
+
+/** This is called automatically upon adding a visor_device (device_add), or
+ *  adding a visor_driver (visorbus_register_visor_driver), but only after
+ *  visorbus_match has returned 1 to indicate a successful match between
+ *  driver and device.
+ */
+static int
+visordriver_probe_device(struct device *xdev)
+{
+	int res;
+	struct visor_driver *drv;
+	struct visor_device *dev;
+
+	drv = to_visor_driver(xdev->driver);
+	dev = to_visor_device(xdev);
+
+	if (!drv->probe)
+		return -ENODEV;
+
+	down(&dev->visordriver_callback_lock);
+	dev->being_removed = false;
+
+	res = drv->probe(dev);
+	if (res >= 0) {
+		/* success: reference kept via unmatched get_device() */
+		get_device(&dev->device);
+		fix_vbus_dev_info(dev);
+	}
+
+	up(&dev->visordriver_callback_lock);
+	return res;
+}
+
+/** This is called when device_unregister() is called for each child device
+ *  instance, to notify the appropriate visorbus_driver that the device is
+ *  going away, and to decrease the reference count of the device.
+ */
+static int
+visordriver_remove_device(struct device *xdev)
+{
+	struct visor_device *dev;
+	struct visor_driver *drv;
+
+	dev = to_visor_device(xdev);
+	drv = to_visor_driver(xdev->driver);
+	down(&dev->visordriver_callback_lock);
+	dev->being_removed = true;
+	if (drv->remove)
+		drv->remove(dev);
+	up(&dev->visordriver_callback_lock);
+	dev_stop_periodic_work(dev);
+
+	put_device(&dev->device);
+	return 0;
+}
+
+/** A particular type of visor driver calls this function to register
+ *  the driver.  The caller MUST fill in the following fields within the
+ *  #drv structure:
+ *      name, version, owner, channel_types, probe, remove
+ *
+ *  Here's how the whole Linux bus / driver / device model works.
+ *
+ *  At system start-up, the visorbus kernel module is loaded, which registers
+ *  visorbus_type as a bus type, using bus_register().
+ *
+ *  All kernel modules that support particular device types on a
+ *  visorbus bus are loaded.  Each of these kernel modules calls
+ *  visorbus_register_visor_driver() in their init functions, passing a
+ *  visor_driver struct.  visorbus_register_visor_driver() in turn calls
+ *  register_driver(&visor_driver.driver).  This .driver member is
+ *  initialized with generic methods (like probe), whose sole responsibility
+ *  is to act as a broker for the real methods, which are within the
+ *  visor_driver struct.  (This is the way the subclass behavior is
+ *  implemented, since visor_driver is essentially a subclass of the
+ *  generic driver.)  Whenever a driver_register() happens, core bus code in
+ *  the kernel does (see device_attach() in drivers/base/dd.c):
+ *
+ *      for each dev associated with the bus (the bus that driver is on) that
+ *      does not yet have a driver
+ *          if bus.match(dev,newdriver) == yes_matched  ** .match specified
+ *                                                 ** during bus_register().
+ *              newdriver.probe(dev)  ** for visor drivers, this will call
+ *                    ** the generic driver.probe implemented in visorbus.c,
+ *                    ** which in turn calls the probe specified within the
+ *                    ** struct visor_driver (which was specified by the
+ *                    ** actual device driver as part of
+ *                    ** visorbus_register_visor_driver()).
+ *
+ *  The above dance also happens when a new device appears.
+ *  So the question is, how are devices created within the system?
+ *  Basically, just call device_add(dev).  See pci_bus_add_devices().
+ *  pci_scan_device() shows an example of how to build a device struct.  It
+ *  returns the newly-created struct to pci_scan_single_device(), who adds it
+ *  to the list of devices at PCIBUS.devices.  That list of devices is what
+ *  is traversed by pci_bus_add_devices().
+ *
+ */
+int visorbus_register_visor_driver(struct visor_driver *drv)
+{
+	int rc = 0;
+
+	if (busreg_rc < 0)
+		return -ENODEV; /*can't register on a nonexistent bus*/
+
+	drv->driver.name = drv->name;
+	drv->driver.bus = &visorbus_type;
+	drv->driver.probe = visordriver_probe_device;
+	drv->driver.remove = visordriver_remove_device;
+	drv->driver.owner = drv->owner;
+
+	/* driver_register does this:
+	 *   bus_add_driver(drv)
+	 *   ->if (drv.bus)  ** (bus_type) **
+	 *       driver_attach(drv)
+	 *         for each dev with bus type of drv.bus
+	 *           if (!dev.drv)  ** no driver assigned yet **
+	 *             if (bus.match(dev,drv))  [visorbus_match]
+	 *               dev.drv = drv
+	 *               if (!drv.probe(dev))   [visordriver_probe_device]
+	 *                 dev.drv = NULL
+	 */
+
+	rc = driver_register(&drv->driver);
+	if (rc < 0)
+		return rc;
+	rc = register_driver_attributes(drv);
+	if (rc < 0)
+		driver_unregister(&drv->driver);
+	return rc;
+}
+EXPORT_SYMBOL_GPL(visorbus_register_visor_driver);
+
+/** A particular type of visor driver calls this function to unregister
+ *  the driver, i.e., within its module_exit function.
+ */
+void
+visorbus_unregister_visor_driver(struct visor_driver *drv)
+{
+	unregister_driver_attributes(drv);
+	driver_unregister(&drv->driver);
+}
+EXPORT_SYMBOL_GPL(visorbus_unregister_visor_driver);
+
+int
+visorbus_read_channel(struct visor_device *dev, unsigned long offset,
+		      void *dest, unsigned long nbytes)
+{
+	return visorchannel_read(dev->visorchannel, offset, dest, nbytes);
+}
+EXPORT_SYMBOL_GPL(visorbus_read_channel);
+
+int
+visorbus_write_channel(struct visor_device *dev, unsigned long offset,
+		       void *src, unsigned long nbytes)
+{
+	return visorchannel_write(dev->visorchannel, offset, src, nbytes);
+}
+EXPORT_SYMBOL_GPL(visorbus_write_channel);
+
+int
+visorbus_clear_channel(struct visor_device *dev, unsigned long offset, u8 ch,
+		       unsigned long nbytes)
+{
+	return visorchannel_clear(dev->visorchannel, offset, ch, nbytes);
+}
+EXPORT_SYMBOL_GPL(visorbus_clear_channel);
+
+/** We don't really have a real interrupt, so for now we just call the
+ *  interrupt function periodically...
+ */
+void
+visorbus_enable_channel_interrupts(struct visor_device *dev)
+{
+	dev_start_periodic_work(dev);
+}
+EXPORT_SYMBOL_GPL(visorbus_enable_channel_interrupts);
+
+void
+visorbus_disable_channel_interrupts(struct visor_device *dev)
+{
+	dev_stop_periodic_work(dev);
+}
+EXPORT_SYMBOL_GPL(visorbus_disable_channel_interrupts);
+
+/** This is how everything starts from the device end.
+ *  This function is called when a channel first appears via a ControlVM
+ *  message.  In response, this function allocates a visor_device to
+ *  correspond to the new channel, and attempts to connect it the appropriate
+ *  driver.  If the appropriate driver is found, the visor_driver.probe()
+ *  function for that driver will be called, and will be passed the new
+ *  visor_device that we just created.
+ *
+ *  It's ok if the appropriate driver is not yet loaded, because in that case
+ *  the new device struct will just stick around in the bus' list of devices.
+ *  When the appropriate driver calls visorbus_register_visor_driver(), the
+ *  visor_driver.probe() for the new driver will be called with the new
+ *  device.
+ */
+static int
+create_visor_device(struct visor_device *dev)
+{
+	int err;
+	u32 chipset_bus_no = dev->chipset_bus_no;
+	u32 chipset_dev_no = dev->chipset_dev_no;
+
+	POSTCODE_LINUX_4(DEVICE_CREATE_ENTRY_PC, chipset_dev_no, chipset_bus_no,
+			 POSTCODE_SEVERITY_INFO);
+
+	sema_init(&dev->visordriver_callback_lock, 1);	/* unlocked */
+	dev->device.bus = &visorbus_type;
+	dev->device.groups = visorbus_channel_groups;
+	device_initialize(&dev->device);
+	dev->device.release = visorbus_release_device;
+	/* keep a reference just for us (now 2) */
+	get_device(&dev->device);
+	dev->periodic_work =
+		visor_periodic_work_create(POLLJIFFIES_NORMALCHANNEL,
+					   periodic_dev_workqueue,
+					   dev_periodic_work,
+					   dev, dev_name(&dev->device));
+	if (!dev->periodic_work) {
+		POSTCODE_LINUX_3(DEVICE_CREATE_FAILURE_PC, chipset_dev_no,
+				 DIAG_SEVERITY_ERR);
+		err = -EINVAL;
+		goto err_put;
+	}
+
+	/* bus_id must be a unique name with respect to this bus TYPE
+	 * (NOT bus instance).  That's why we need to include the bus
+	 * number within the name.
+	 */
+	dev_set_name(&dev->device, "vbus%u:dev%u",
+		     chipset_bus_no, chipset_dev_no);
+
+	/*  device_add does this:
+	 *    bus_add_device(dev)
+	 *    ->device_attach(dev)
+	 *      ->for each driver drv registered on the bus that dev is on
+	 *          if (dev.drv)  **  device already has a driver **
+	 *            ** not sure we could ever get here... **
+	 *          else
+	 *            if (bus.match(dev,drv)) [visorbus_match]
+	 *              dev.drv = drv
+	 *              if (!drv.probe(dev))  [visordriver_probe_device]
+	 *                dev.drv = NULL
+	 *
+	 *  Note that device_add does NOT fail if no driver failed to
+	 *  claim the device.  The device will be linked onto
+	 *  bus_type.klist_devices regardless (use bus_for_each_dev).
+	 */
+	err = device_add(&dev->device);
+	if (err < 0) {
+		POSTCODE_LINUX_3(DEVICE_ADD_PC, chipset_bus_no,
+				 DIAG_SEVERITY_ERR);
+		goto err_put;
+	}
+
+	list_add_tail(&dev->list_all, &list_all_device_instances);
+	return 0; /* success: reference kept via unmatched get_device() */
+
+err_put:
+	put_device(&dev->device);
+	return err;
+}
+
+static void
+remove_visor_device(struct visor_device *dev)
+{
+	list_del(&dev->list_all);
+	put_device(&dev->device);
+	device_unregister(&dev->device);
+}
+
+static int
+get_vbus_header_info(struct visorchannel *chan,
+		     struct spar_vbus_headerinfo *hdr_info)
+{
+	if (!SPAR_VBUS_CHANNEL_OK_CLIENT(visorchannel_get_header(chan)))
+		return -EINVAL;
+
+	if (visorchannel_read(chan, sizeof(struct channel_header), hdr_info,
+			      sizeof(*hdr_info)) < 0) {
+		return -EIO;
+	}
+	if (hdr_info->struct_bytes < sizeof(struct spar_vbus_headerinfo))
+		return -EINVAL;
+
+	if (hdr_info->device_info_struct_bytes <
+	    sizeof(struct ultra_vbus_deviceinfo)) {
+		return -EINVAL;
+	}
+	return 0;
+}
+
+/* Write the contents of <info> to the struct
+ * spar_vbus_channel_protocol.chp_info.
+ */
+
+static int
+write_vbus_chp_info(struct visorchannel *chan,
+		    struct spar_vbus_headerinfo *hdr_info,
+		    struct ultra_vbus_deviceinfo *info)
+{
+	int off = sizeof(struct channel_header) + hdr_info->chp_info_offset;
+
+	if (hdr_info->chp_info_offset == 0)
+		return -EFAULT;
+
+	if (visorchannel_write(chan, off, info, sizeof(*info)) < 0)
+		return -EFAULT;
+	return 0;
+}
+
+/* Write the contents of <info> to the struct
+ * spar_vbus_channel_protocol.bus_info.
+ */
+
+static int
+write_vbus_bus_info(struct visorchannel *chan,
+		    struct spar_vbus_headerinfo *hdr_info,
+		    struct ultra_vbus_deviceinfo *info)
+{
+	int off = sizeof(struct channel_header) + hdr_info->bus_info_offset;
+
+	if (hdr_info->bus_info_offset == 0)
+		return -EFAULT;
+
+	if (visorchannel_write(chan, off, info, sizeof(*info)) < 0)
+		return -EFAULT;
+	return 0;
+}
+
+/* Write the contents of <info> to the
+ * struct spar_vbus_channel_protocol.dev_info[<devix>].
+ */
+static int
+write_vbus_dev_info(struct visorchannel *chan,
+		    struct spar_vbus_headerinfo *hdr_info,
+		    struct ultra_vbus_deviceinfo *info, int devix)
+{
+	int off =
+	    (sizeof(struct channel_header) + hdr_info->dev_info_offset) +
+	    (hdr_info->device_info_struct_bytes * devix);
+
+	if (hdr_info->dev_info_offset == 0)
+		return -EFAULT;
+
+	if (visorchannel_write(chan, off, info, sizeof(*info)) < 0)
+		return -EFAULT;
+	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_dev_info(struct visor_device *visordev)
+{
+	int i;
+	struct visor_device *bdev;
+	struct visor_driver *visordrv;
+	int bus_no = visordev->chipset_bus_no;
+	int dev_no = visordev->chipset_dev_no;
+	struct ultra_vbus_deviceinfo dev_info;
+	const char *chan_type_name = NULL;
+	struct spar_vbus_headerinfo *hdr_info;
+
+	if (!visordev->device.driver)
+		return;
+
+	hdr_info = (struct spar_vbus_headerinfo *)visordev->vbus_hdr_info;
+	if (!hdr_info)
+		return;
+
+	bdev = visorbus_get_device_by_id(bus_no, BUS_ROOT_DEVICE, NULL);
+	if (!bdev)
+		return;
+
+	visordrv = to_visor_driver(visordev->device.driver);
+
+	/* Within the list of device types (by GUID) that the driver
+	 * says it supports, find out which one of those types matches
+	 * the type of this device, so that we can include the device
+	 * type name
+	 */
+	for (i = 0; visordrv->channel_types[i].name; i++) {
+		if (memcmp(&visordrv->channel_types[i].guid,
+			   &visordev->channel_type_guid,
+			   sizeof(visordrv->channel_types[i].guid)) == 0) {
+			chan_type_name = visordrv->channel_types[i].name;
+			break;
+		}
+	}
+
+	bus_device_info_init(&dev_info, chan_type_name,
+			     visordrv->name, visordrv->version,
+			     visordrv->vertag);
+	write_vbus_dev_info(bdev->visorchannel, hdr_info, &dev_info, dev_no);
+
+	/* Re-write bus+chipset info, because it is possible that this
+	* was previously written by our evil counterpart, virtpci.
+	*/
+	write_vbus_chp_info(bdev->visorchannel, hdr_info, &chipset_driverinfo);
+	write_vbus_bus_info(bdev->visorchannel, hdr_info,
+			    &clientbus_driverinfo);
+}
+
+/** Create a device instance for the visor bus itself.
+ */
+static int
+create_bus_instance(struct visor_device *dev)
+{
+	int id = dev->chipset_bus_no;
+	struct spar_vbus_headerinfo *hdr_info;
+
+	POSTCODE_LINUX_2(BUS_CREATE_ENTRY_PC, POSTCODE_SEVERITY_INFO);
+
+	hdr_info = kzalloc(sizeof(*hdr_info), GFP_KERNEL);
+	if (!hdr_info)
+		return -ENOMEM;
+
+	dev_set_name(&dev->device, "visorbus%d", id);
+	dev->device.bus = &visorbus_type;
+	dev->device.groups = visorbus_groups;
+	dev->device.release = visorbus_release_busdevice;
+
+	if (device_register(&dev->device) < 0) {
+		POSTCODE_LINUX_3(DEVICE_CREATE_FAILURE_PC, id,
+				 POSTCODE_SEVERITY_ERR);
+		kfree(hdr_info);
+		return -ENODEV;
+	}
+
+	if (get_vbus_header_info(dev->visorchannel, hdr_info) >= 0) {
+		dev->vbus_hdr_info = (void *)hdr_info;
+		write_vbus_chp_info(dev->visorchannel, hdr_info,
+				    &chipset_driverinfo);
+		write_vbus_bus_info(dev->visorchannel, hdr_info,
+				    &clientbus_driverinfo);
+	} else {
+		kfree(hdr_info);
+	}
+	bus_count++;
+	list_add_tail(&dev->list_all, &list_all_bus_instances);
+	dev_set_drvdata(&dev->device, dev);
+	return 0;
+}
+
+/** Remove a device instance for the visor bus itself.
+ */
+static void
+remove_bus_instance(struct visor_device *dev)
+{
+	/* Note that this will result in the release method for
+	 * dev->dev being called, which will call
+	 * visorbus_release_busdevice().  This has something to do with
+	 * the put_device() done in device_unregister(), but I have never
+	 * successfully been able to trace thru the code to see where/how
+	 * release() gets called.  But I know it does.
+	 */
+	bus_count--;
+	if (dev->visorchannel) {
+		visorchannel_destroy(dev->visorchannel);
+		dev->visorchannel = NULL;
+	}
+	kfree(dev->vbus_hdr_info);
+	list_del(&dev->list_all);
+	device_unregister(&dev->device);
+}
+
+/** Create and register the one-and-only one instance of
+ *  the visor bus type (visorbus_type).
+ */
+static int
+create_bus_type(void)
+{
+	busreg_rc = bus_register(&visorbus_type);
+	return busreg_rc;
+}
+
+/** Remove the one-and-only one instance of the visor bus type (visorbus_type).
+ */
+static void
+remove_bus_type(void)
+{
+	bus_unregister(&visorbus_type);
+}
+
+/** Remove all child visor bus device instances.
+ */
+static void
+remove_all_visor_devices(void)
+{
+	struct list_head *listentry, *listtmp;
+
+	list_for_each_safe(listentry, listtmp, &list_all_device_instances) {
+		struct visor_device *dev = list_entry(listentry,
+						      struct visor_device,
+						      list_all);
+		remove_visor_device(dev);
+	}
+}
+
+static void
+chipset_bus_create(struct visor_device *dev)
+{
+	int rc;
+	u32 bus_no = dev->chipset_bus_no;
+
+	POSTCODE_LINUX_3(BUS_CREATE_ENTRY_PC, bus_no, POSTCODE_SEVERITY_INFO);
+	rc = create_bus_instance(dev);
+	POSTCODE_LINUX_3(BUS_CREATE_EXIT_PC, bus_no, POSTCODE_SEVERITY_INFO);
+
+	if (rc < 0)
+		POSTCODE_LINUX_3(BUS_CREATE_FAILURE_PC, bus_no,
+				 POSTCODE_SEVERITY_ERR);
+	else
+		POSTCODE_LINUX_3(CHIPSET_INIT_SUCCESS_PC, bus_no,
+				 POSTCODE_SEVERITY_INFO);
+
+	if (chipset_responders.bus_create)
+		(*chipset_responders.bus_create) (dev, rc);
+}
+
+static void
+chipset_bus_destroy(struct visor_device *dev)
+{
+	remove_bus_instance(dev);
+	if (chipset_responders.bus_destroy)
+		(*chipset_responders.bus_destroy)(dev, 0);
+}
+
+static void
+chipset_device_create(struct visor_device *dev_info)
+{
+	int rc;
+	u32 bus_no = dev_info->chipset_bus_no;
+	u32 dev_no = dev_info->chipset_dev_no;
+
+	POSTCODE_LINUX_4(DEVICE_CREATE_ENTRY_PC, dev_no, bus_no,
+			 POSTCODE_SEVERITY_INFO);
+
+	rc = create_visor_device(dev_info);
+	if (chipset_responders.device_create)
+		chipset_responders.device_create(dev_info, rc);
+
+	if (rc < 0)
+		POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, dev_no, bus_no,
+				 POSTCODE_SEVERITY_ERR);
+	else
+		POSTCODE_LINUX_4(DEVICE_CREATE_SUCCESS_PC, dev_no, bus_no,
+				 POSTCODE_SEVERITY_INFO);
+}
+
+static void
+chipset_device_destroy(struct visor_device *dev_info)
+{
+	remove_visor_device(dev_info);
+
+	if (chipset_responders.device_destroy)
+		(*chipset_responders.device_destroy) (dev_info, 0);
+}
+
+/* This is the callback function specified for a function driver, to
+ * be called when a pending "pause device" operation has been
+ * completed.
+ */
+static void
+pause_state_change_complete(struct visor_device *dev, int status)
+{
+	if (!dev->pausing)
+		return;
+
+	dev->pausing = false;
+	if (!chipset_responders.device_pause) /* this can never happen! */
+		return;
+
+	/* Notify the chipset driver that the pause is complete, which
+	 * will presumably want to send some sort of response to the
+	 * initiator.
+	 */
+	(*chipset_responders.device_pause) (dev, status);
+}
+
+/* This is the callback function specified for a function driver, to
+ * be called when a pending "resume device" operation has been
+ * completed.
+ */
+static void
+resume_state_change_complete(struct visor_device *dev, int status)
+{
+	if (!dev->resuming)
+		return;
+
+	dev->resuming = false;
+	if (!chipset_responders.device_resume) /* this can never happen! */
+		return;
+
+	/* Notify the chipset driver that the resume is complete,
+	 * which will presumably want to send some sort of response to
+	 * the initiator.
+	 */
+	(*chipset_responders.device_resume) (dev, status);
+}
+
+/* Tell the subordinate function driver for a specific device to pause
+ * or resume that device.  Result is returned asynchronously via a
+ * callback function.
+ */
+static void
+initiate_chipset_device_pause_resume(struct visor_device *dev, bool is_pause)
+{
+	int rc;
+	struct visor_driver *drv = NULL;
+	void (*notify_func)(struct visor_device *dev, int response) = NULL;
+
+	if (is_pause)
+		notify_func = chipset_responders.device_pause;
+	else
+		notify_func = chipset_responders.device_resume;
+	if (!notify_func)
+		return;
+
+	drv = to_visor_driver(dev->device.driver);
+	if (!drv) {
+		(*notify_func)(dev, -ENODEV);
+		return;
+	}
+
+	if (dev->pausing || dev->resuming) {
+		(*notify_func)(dev, -EBUSY);
+		return;
+	}
+
+	/* Note that even though both drv->pause() and drv->resume
+	 * specify a callback function, it is NOT necessary for us to
+	 * increment our local module usage count.  Reason is, there
+	 * is already a linkage dependency between child function
+	 * drivers and visorbus, so it is already IMPOSSIBLE to unload
+	 * visorbus while child function drivers are still running.
+	 */
+	if (is_pause) {
+		if (!drv->pause) {
+			(*notify_func)(dev, -EINVAL);
+			return;
+		}
+
+		dev->pausing = true;
+		rc = drv->pause(dev, pause_state_change_complete);
+	} else {
+		/* 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_dev_info(dev);
+		if (!drv->resume) {
+			(*notify_func)(dev, -EINVAL);
+			return;
+		}
+
+		dev->resuming = true;
+		rc = drv->resume(dev, resume_state_change_complete);
+	}
+	if (rc < 0) {
+		if (is_pause)
+			dev->pausing = false;
+		else
+			dev->resuming = false;
+		(*notify_func)(dev, -EINVAL);
+	}
+}
+
+static void
+chipset_device_pause(struct visor_device *dev_info)
+{
+	initiate_chipset_device_pause_resume(dev_info, true);
+}
+
+static void
+chipset_device_resume(struct visor_device *dev_info)
+{
+	initiate_chipset_device_pause_resume(dev_info, false);
+}
+
+struct channel_size_info {
+	uuid_le guid;
+	unsigned long min_size;
+	unsigned long max_size;
+};
+
+int
+visorbus_init(void)
+{
+	int err;
+
+	POSTCODE_LINUX_3(DRIVER_ENTRY_PC, 0, POSTCODE_SEVERITY_INFO);
+	bus_device_info_init(&clientbus_driverinfo,
+			     "clientbus", "visorbus",
+			     VERSION, NULL);
+
+	err = create_bus_type();
+	if (err < 0) {
+		POSTCODE_LINUX_2(BUS_CREATE_ENTRY_PC, DIAG_SEVERITY_ERR);
+		goto error;
+	}
+
+	periodic_dev_workqueue = create_singlethread_workqueue("visorbus_dev");
+	if (!periodic_dev_workqueue) {
+		POSTCODE_LINUX_2(CREATE_WORKQUEUE_PC, DIAG_SEVERITY_ERR);
+		err = -ENOMEM;
+		goto error;
+	}
+
+	/* This enables us to receive notifications when devices appear for
+	 * which this service partition is to be a server for.
+	 */
+	visorchipset_register_busdev(&chipset_notifiers,
+				     &chipset_responders,
+				     &chipset_driverinfo);
+
+	return 0;
+
+error:
+	POSTCODE_LINUX_3(CHIPSET_INIT_FAILURE_PC, err, POSTCODE_SEVERITY_ERR);
+	return err;
+}
+
+void
+visorbus_exit(void)
+{
+	struct list_head *listentry, *listtmp;
+
+	visorchipset_register_busdev(NULL, NULL, NULL);
+	remove_all_visor_devices();
+
+	flush_workqueue(periodic_dev_workqueue); /* better not be any work! */
+	destroy_workqueue(periodic_dev_workqueue);
+	periodic_dev_workqueue = NULL;
+
+	if (periodic_test_workqueue) {
+		cancel_delayed_work(&periodic_work);
+		flush_workqueue(periodic_test_workqueue);
+		destroy_workqueue(periodic_test_workqueue);
+		periodic_test_workqueue = NULL;
+	}
+
+	list_for_each_safe(listentry, listtmp, &list_all_bus_instances) {
+		struct visor_device *dev = list_entry(listentry,
+						      struct visor_device,
+						      list_all);
+		remove_bus_instance(dev);
+	}
+	remove_bus_type();
+}
+
+module_param_named(debug, visorbus_debug, int, S_IRUGO);
+MODULE_PARM_DESC(visorbus_debug, "1 to debug");
+
+module_param_named(forcematch, visorbus_forcematch, int, S_IRUGO);
+MODULE_PARM_DESC(visorbus_forcematch,
+		 "1 to force a successful dev <--> drv match");
+
+module_param_named(forcenomatch, visorbus_forcenomatch, int, S_IRUGO);
+MODULE_PARM_DESC(visorbus_forcenomatch,
+		 "1 to force an UNsuccessful dev <--> drv match");
+
+module_param_named(debugref, visorbus_debugref, int, S_IRUGO);
+MODULE_PARM_DESC(visorbus_debugref, "1 to debug reference counting");
diff --git a/arch/x86/visorbus/visorbus_private.h b/arch/x86/visorbus/visorbus_private.h
new file mode 100644
index 0000000..39edd20
--- /dev/null
+++ b/arch/x86/visorbus/visorbus_private.h
@@ -0,0 +1,68 @@
+/* visorchipset.h
+ *
+ * Copyright (C) 2010 - 2015 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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 <linux/uuid.h>
+
+#include "controlvmchannel.h"
+#include "vbusdeviceinfo.h"
+#include "vbushelper.h"
+
+/*  These functions will be called from within visorchipset when certain
+ *  events happen.  (The implementation of these functions is outside of
+ *  visorchipset.)
+ */
+struct visorchipset_busdev_notifiers {
+	void (*bus_create)(struct visor_device *bus_info);
+	void (*bus_destroy)(struct visor_device *bus_info);
+	void (*device_create)(struct visor_device *bus_info);
+	void (*device_destroy)(struct visor_device *bus_info);
+	void (*device_pause)(struct visor_device *bus_info);
+	void (*device_resume)(struct visor_device *bus_info);
+};
+
+/*  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
+ */
+struct visorchipset_busdev_responders {
+	void (*bus_create)(struct visor_device *p, int response);
+	void (*bus_destroy)(struct visor_device *p, int response);
+	void (*device_create)(struct visor_device *p, int response);
+	void (*device_destroy)(struct visor_device *p, int response);
+	void (*device_pause)(struct visor_device *p, int response);
+	void (*device_resume)(struct visor_device *p, int response);
+};
+
+/** Register functions (in the bus driver) to get called by visorchipset
+ *  whenever a bus or device appears for which this guest 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(
+			struct visorchipset_busdev_notifiers *notifiers,
+			struct visorchipset_busdev_responders *responders,
+			struct ultra_vbus_deviceinfo *driver_info);
+
+/* visorbus init and exit functions */
+int visorbus_init(void);
+void visorbus_exit(void);
+#endif
diff --git a/arch/x86/visorbus/visorchannel.c b/arch/x86/visorbus/visorchannel.c
new file mode 100644
index 0000000..4e8b0ef
--- /dev/null
+++ b/arch/x86/visorbus/visorchannel.c
@@ -0,0 +1,635 @@
+/* visorchannel_funcs.c
+ *
+ * Copyright (C) 2010 - 2015 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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.
+ */
+
+#include <linux/uuid.h>
+#include <linux/io.h>
+
+#include <linux/visorbus/version.h>
+#include <linux/visorbus/visorbus.h>
+#include "controlvmchannel.h"
+
+#define MYDRVNAME "visorchannel"
+
+#define SPAR_CONSOLEVIDEO_CHANNEL_PROTOCOL_GUID \
+	UUID_LE(0x3cd6e705, 0xd6a2, 0x4aa5,           \
+		0xad, 0x5c, 0x7b, 0x8, 0x88, 0x9d, 0xff, 0xe2)
+static const uuid_le spar_video_guid = SPAR_CONSOLEVIDEO_CHANNEL_PROTOCOL_GUID;
+
+struct visorchannel {
+	u64 physaddr;
+	ulong nbytes;
+	void *mapped;
+	bool requested;
+	struct channel_header chan_hdr;
+	uuid_le guid;
+	bool needs_lock;	/* channel creator knows if more than one */
+				/* thread will be inserting or removing */
+	spinlock_t insert_lock; /* protect head writes in chan_hdr */
+	spinlock_t remove_lock;	/* protect tail writes in chan_hdr */
+
+	struct {
+		struct signal_queue_header req_queue;
+		struct signal_queue_header rsp_queue;
+		struct signal_queue_header event_queue;
+		struct signal_queue_header ack_queue;
+	} safe_uis_queue;
+	uuid_le type;
+	uuid_le inst;
+};
+
+/* Creates the struct visorchannel abstraction for a data area in memory,
+ * but does NOT modify this data area.
+ */
+static struct visorchannel *
+visorchannel_create_guts(u64 physaddr, unsigned long channel_bytes,
+			 gfp_t gfp, unsigned long off,
+			 uuid_le guid, bool needs_lock)
+{
+	struct visorchannel *channel;
+	int err;
+	size_t size = sizeof(struct channel_header);
+
+	if (physaddr == 0)
+		return NULL;
+
+	channel = kzalloc(sizeof(*channel), gfp);
+	if (!channel)
+		return NULL;
+
+	channel->needs_lock = needs_lock;
+	spin_lock_init(&channel->insert_lock);
+	spin_lock_init(&channel->remove_lock);
+
+	/* Video driver constains the efi framebuffer so it will get a
+	 * conflict resource when requesting its full mem region. Since
+	 * we are only using the efi framebuffer for video we can ignore
+	 * this. Remember that we haven't requested it so we don't try to
+	 * release later on.
+	 */
+	channel->requested = request_mem_region(physaddr, size, MYDRVNAME);
+	if (!channel->requested) {
+		if (uuid_le_cmp(guid, spar_video_guid)) {
+			/* Not the video channel we care about this */
+			goto err_destroy_channel;
+		}
+	}
+
+	channel->mapped = memremap(physaddr, size, MEMREMAP_WB);
+	if (!channel->mapped) {
+		release_mem_region(physaddr, size);
+		goto err_destroy_channel;
+	}
+
+	channel->physaddr = physaddr;
+	channel->nbytes = size;
+
+	err = visorchannel_read(channel, 0, &channel->chan_hdr,
+				sizeof(struct channel_header));
+	if (err)
+		goto err_destroy_channel;
+
+	/* we had better be a CLIENT of this channel */
+	if (channel_bytes == 0)
+		channel_bytes = (ulong)channel->chan_hdr.size;
+	if (uuid_le_cmp(guid, NULL_UUID_LE) == 0)
+		guid = channel->chan_hdr.chtype;
+
+	memunmap(channel->mapped);
+	if (channel->requested)
+		release_mem_region(channel->physaddr, channel->nbytes);
+	channel->mapped = NULL;
+	channel->requested = request_mem_region(channel->physaddr,
+						channel_bytes, MYDRVNAME);
+	if (!channel->requested) {
+		if (uuid_le_cmp(guid, spar_video_guid)) {
+			/* Different we care about this */
+			goto err_destroy_channel;
+		}
+	}
+
+	channel->mapped = memremap(channel->physaddr, channel_bytes,
+			MEMREMAP_WB);
+	if (!channel->mapped) {
+		release_mem_region(channel->physaddr, channel_bytes);
+		goto err_destroy_channel;
+	}
+
+	channel->nbytes = channel_bytes;
+	channel->guid = guid;
+	return channel;
+
+err_destroy_channel:
+	visorchannel_destroy(channel);
+	return NULL;
+}
+
+struct visorchannel *
+visorchannel_create(u64 physaddr, unsigned long channel_bytes,
+		    gfp_t gfp, uuid_le guid)
+{
+	return visorchannel_create_guts(physaddr, channel_bytes, gfp, 0, guid,
+					false);
+}
+EXPORT_SYMBOL_GPL(visorchannel_create);
+
+struct visorchannel *
+visorchannel_create_with_lock(u64 physaddr, unsigned long channel_bytes,
+			      gfp_t gfp, uuid_le guid)
+{
+	return visorchannel_create_guts(physaddr, channel_bytes, gfp, 0, guid,
+					true);
+}
+EXPORT_SYMBOL_GPL(visorchannel_create_with_lock);
+
+void
+visorchannel_destroy(struct visorchannel *channel)
+{
+	if (!channel)
+		return;
+	if (channel->mapped) {
+		memunmap(channel->mapped);
+		if (channel->requested)
+			release_mem_region(channel->physaddr, channel->nbytes);
+	}
+	kfree(channel);
+}
+EXPORT_SYMBOL_GPL(visorchannel_destroy);
+
+u64
+visorchannel_get_physaddr(struct visorchannel *channel)
+{
+	return channel->physaddr;
+}
+EXPORT_SYMBOL_GPL(visorchannel_get_physaddr);
+
+ulong
+visorchannel_get_nbytes(struct visorchannel *channel)
+{
+	return channel->nbytes;
+}
+EXPORT_SYMBOL_GPL(visorchannel_get_nbytes);
+
+char *
+visorchannel_uuid_id(uuid_le *guid, char *s)
+{
+	sprintf(s, "%pUL", guid);
+	return s;
+}
+EXPORT_SYMBOL_GPL(visorchannel_uuid_id);
+
+char *
+visorchannel_id(struct visorchannel *channel, char *s)
+{
+	return visorchannel_uuid_id(&channel->guid, s);
+}
+EXPORT_SYMBOL_GPL(visorchannel_id);
+
+char *
+visorchannel_zoneid(struct visorchannel *channel, char *s)
+{
+	return visorchannel_uuid_id(&channel->chan_hdr.zone_uuid, s);
+}
+EXPORT_SYMBOL_GPL(visorchannel_zoneid);
+
+u64
+visorchannel_get_clientpartition(struct visorchannel *channel)
+{
+	return channel->chan_hdr.partition_handle;
+}
+EXPORT_SYMBOL_GPL(visorchannel_get_clientpartition);
+
+int
+visorchannel_set_clientpartition(struct visorchannel *channel,
+				 u64 partition_handle)
+{
+	channel->chan_hdr.partition_handle = partition_handle;
+	return 0;
+}
+EXPORT_SYMBOL_GPL(visorchannel_set_clientpartition);
+
+uuid_le
+visorchannel_get_uuid(struct visorchannel *channel)
+{
+	return channel->guid;
+}
+EXPORT_SYMBOL_GPL(visorchannel_get_uuid);
+
+int
+visorchannel_read(struct visorchannel *channel, ulong offset,
+		  void *local, ulong nbytes)
+{
+	if (offset + nbytes > channel->nbytes)
+		return -EIO;
+
+	memcpy(local, channel->mapped + offset, nbytes);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(visorchannel_read);
+
+int
+visorchannel_write(struct visorchannel *channel, ulong offset,
+		   void *local, ulong nbytes)
+{
+	size_t chdr_size = sizeof(struct channel_header);
+	size_t copy_size;
+
+	if (offset + nbytes > channel->nbytes)
+		return -EIO;
+
+	if (offset < chdr_size) {
+		copy_size = min(chdr_size - offset, nbytes);
+		memcpy(((char *)(&channel->chan_hdr)) + offset,
+		       local, copy_size);
+	}
+
+	memcpy(channel->mapped + offset, local, nbytes);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(visorchannel_write);
+
+int
+visorchannel_clear(struct visorchannel *channel, ulong offset, u8 ch,
+		   ulong nbytes)
+{
+	int err;
+	int bufsize = PAGE_SIZE;
+	int written = 0;
+	u8 *buf;
+
+	buf = (u8 *)__get_free_page(GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	memset(buf, ch, bufsize);
+
+	while (nbytes > 0) {
+		int thisbytes = bufsize;
+
+		if (nbytes < thisbytes)
+			thisbytes = nbytes;
+		err = visorchannel_write(channel, offset + written,
+					 buf, thisbytes);
+		if (err)
+			goto out_free_page;
+
+		written += thisbytes;
+		nbytes -= thisbytes;
+	}
+	err = 0;
+
+out_free_page:
+	free_page((unsigned long)buf);
+	return err;
+}
+EXPORT_SYMBOL_GPL(visorchannel_clear);
+
+void __iomem  *
+visorchannel_get_header(struct visorchannel *channel)
+{
+	return (void __iomem *)&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)->ch_space_offset + \
+	 ((q) * sizeof(struct 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)->sig_base_offset + \
+	    ((slot) * (sig_hdr)->signal_size))
+
+/** 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)			 \
+	(visorchannel_write(channel,					 \
+			    SIG_QUEUE_OFFSET(&channel->chan_hdr, queue) +\
+			    offsetof(struct signal_queue_header, FIELD), \
+			    &((sig_hdr)->FIELD),			 \
+			    sizeof((sig_hdr)->FIELD)) >= 0)
+
+static bool
+sig_read_header(struct visorchannel *channel, u32 queue,
+		struct signal_queue_header *sig_hdr)
+{
+	int err;
+
+	if (channel->chan_hdr.ch_space_offset < sizeof(struct channel_header))
+		return false;
+
+	/* Read the appropriate SIGNAL_QUEUE_HEADER into local memory. */
+	err = visorchannel_read(channel,
+				SIG_QUEUE_OFFSET(&channel->chan_hdr, queue),
+				sig_hdr, sizeof(struct signal_queue_header));
+	if (err)
+		return false;
+
+	return true;
+}
+
+static inline bool
+sig_read_data(struct visorchannel *channel, u32 queue,
+	      struct signal_queue_header *sig_hdr, u32 slot, void *data)
+{
+	int err;
+	int signal_data_offset = SIG_DATA_OFFSET(&channel->chan_hdr, queue,
+						 sig_hdr, slot);
+
+	err = visorchannel_read(channel, signal_data_offset,
+				data, sig_hdr->signal_size);
+	if (err)
+		return false;
+
+	return true;
+}
+
+static inline bool
+sig_write_data(struct visorchannel *channel, u32 queue,
+	       struct signal_queue_header *sig_hdr, u32 slot, void *data)
+{
+	int err;
+	int signal_data_offset = SIG_DATA_OFFSET(&channel->chan_hdr, queue,
+						 sig_hdr, slot);
+
+	err = visorchannel_write(channel, signal_data_offset,
+				 data, sig_hdr->signal_size);
+	if (err)
+		return false;
+
+	return true;
+}
+
+static bool
+signalremove_inner(struct visorchannel *channel, u32 queue, void *msg)
+{
+	struct signal_queue_header sig_hdr;
+
+	if (!sig_read_header(channel, queue, &sig_hdr))
+		return false;
+	if (sig_hdr.head == sig_hdr.tail)
+		return false;	/* no signals to remove */
+
+	sig_hdr.tail = (sig_hdr.tail + 1) % sig_hdr.max_slots;
+	if (!sig_read_data(channel, queue, &sig_hdr, sig_hdr.tail, msg))
+		return false;
+	sig_hdr.num_received++;
+
+	/* For each data field in SIGNAL_QUEUE_HEADER that was modified,
+	 * update host memory.
+	 */
+	mb(); /* required for channel synch */
+	if (!SIG_WRITE_FIELD(channel, queue, &sig_hdr, tail))
+		return false;
+	if (!SIG_WRITE_FIELD(channel, queue, &sig_hdr, num_received))
+		return false;
+	return true;
+}
+
+bool
+visorchannel_signalremove(struct visorchannel *channel, u32 queue, void *msg)
+{
+	bool rc;
+	unsigned long flags;
+
+	if (channel->needs_lock) {
+		spin_lock_irqsave(&channel->remove_lock, flags);
+		rc = signalremove_inner(channel, queue, msg);
+		spin_unlock_irqrestore(&channel->remove_lock, flags);
+	} else {
+		rc = signalremove_inner(channel, queue, msg);
+	}
+
+	return rc;
+}
+EXPORT_SYMBOL_GPL(visorchannel_signalremove);
+
+bool
+visorchannel_signalempty(struct visorchannel *channel, u32 queue)
+{
+	unsigned long flags = 0;
+	struct signal_queue_header sig_hdr;
+	bool rc = false;
+
+	if (channel->needs_lock)
+		spin_lock_irqsave(&channel->remove_lock, flags);
+
+	if (!sig_read_header(channel, queue, &sig_hdr))
+		rc = true;
+	if (sig_hdr.head == sig_hdr.tail)
+		rc = true;
+	if (channel->needs_lock)
+		spin_unlock_irqrestore(&channel->remove_lock, flags);
+
+	return rc;
+}
+EXPORT_SYMBOL_GPL(visorchannel_signalempty);
+
+static bool
+signalinsert_inner(struct visorchannel *channel, u32 queue, void *msg)
+{
+	struct signal_queue_header sig_hdr;
+
+	if (!sig_read_header(channel, queue, &sig_hdr))
+		return false;
+
+	sig_hdr.head = (sig_hdr.head + 1) % sig_hdr.max_slots;
+	if (sig_hdr.head == sig_hdr.tail) {
+		sig_hdr.num_overflows++;
+		visorchannel_write(channel,
+				   SIG_QUEUE_OFFSET(&channel->chan_hdr, queue) +
+				   offsetof(struct signal_queue_header,
+					    num_overflows),
+				   &sig_hdr.num_overflows,
+				   sizeof(sig_hdr.num_overflows));
+		return false;
+	}
+
+	if (!sig_write_data(channel, queue, &sig_hdr, sig_hdr.head, msg))
+		return false;
+
+	sig_hdr.num_sent++;
+
+	/* For each data field in SIGNAL_QUEUE_HEADER that was modified,
+	 * update host memory.
+	 */
+	mb(); /* required for channel synch */
+	if (!SIG_WRITE_FIELD(channel, queue, &sig_hdr, head))
+		return false;
+	if (!SIG_WRITE_FIELD(channel, queue, &sig_hdr, num_sent))
+		return false;
+
+	return true;
+}
+
+bool
+visorchannel_signalinsert(struct visorchannel *channel, u32 queue, void *msg)
+{
+	bool rc;
+	unsigned long flags;
+
+	if (channel->needs_lock) {
+		spin_lock_irqsave(&channel->insert_lock, flags);
+		rc = signalinsert_inner(channel, queue, msg);
+		spin_unlock_irqrestore(&channel->insert_lock, flags);
+	} else {
+		rc = signalinsert_inner(channel, queue, msg);
+	}
+
+	return rc;
+}
+EXPORT_SYMBOL_GPL(visorchannel_signalinsert);
+
+int
+visorchannel_signalqueue_slots_avail(struct visorchannel *channel, u32 queue)
+{
+	struct 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.max_slots;
+	slots_used = head - tail;
+	slots_avail = sig_hdr.max_signals - slots_used;
+	return (int)slots_avail;
+}
+EXPORT_SYMBOL_GPL(visorchannel_signalqueue_slots_avail);
+
+int
+visorchannel_signalqueue_max_slots(struct visorchannel *channel, u32 queue)
+{
+	struct signal_queue_header sig_hdr;
+
+	if (!sig_read_header(channel, queue, &sig_hdr))
+		return 0;
+	return (int)sig_hdr.max_signals;
+}
+EXPORT_SYMBOL_GPL(visorchannel_signalqueue_max_slots);
+
+static void
+sigqueue_debug(struct 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->version);
+	seq_printf(seq, "   Type               = %lu\n", (ulong)q->chtype);
+	seq_printf(seq, "   oSignalBase        = %llu\n",
+		   (long long)q->sig_base_offset);
+	seq_printf(seq, "   SignalSize         = %lu\n", (ulong)q->signal_size);
+	seq_printf(seq, "   MaxSignalSlots     = %lu\n",
+		   (ulong)q->max_slots);
+	seq_printf(seq, "   MaxSignals         = %lu\n", (ulong)q->max_signals);
+	seq_printf(seq, "   FeatureFlags       = %-16.16Lx\n",
+		   (long long)q->features);
+	seq_printf(seq, "   NumSignalsSent     = %llu\n",
+		   (long long)q->num_sent);
+	seq_printf(seq, "   NumSignalsReceived = %llu\n",
+		   (long long)q->num_received);
+	seq_printf(seq, "   NumOverflows       = %llu\n",
+		   (long long)q->num_overflows);
+	seq_printf(seq, "   Head               = %lu\n", (ulong)q->head);
+	seq_printf(seq, "   Tail               = %lu\n", (ulong)q->tail);
+}
+
+void
+visorchannel_debug(struct visorchannel *channel, int num_queues,
+		   struct seq_file *seq, u32 off)
+{
+	u64 addr = 0;
+	ulong nbytes = 0, nbytes_region = 0;
+	struct channel_header hdr;
+	struct channel_header *phdr = &hdr;
+	int i = 0;
+	int errcode = 0;
+
+	if (!channel)
+		return;
+
+	addr = visorchannel_get_physaddr(channel);
+	nbytes_region = visorchannel_get_nbytes(channel);
+	errcode = visorchannel_read(channel, off,
+				    phdr, sizeof(struct 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            = %pUL\n", &phdr->chtype);
+	seq_printf(seq, "ZoneGuid        = %pUL\n", &phdr->zone_uuid);
+	seq_printf(seq, "Signature       = 0x%-16.16Lx\n",
+		   (long long)phdr->signature);
+	seq_printf(seq, "LegacyState     = %lu\n", (ulong)phdr->legacy_state);
+	seq_printf(seq, "SrvState        = %lu\n", (ulong)phdr->srv_state);
+	seq_printf(seq, "CliStateBoot    = %lu\n", (ulong)phdr->cli_state_boot);
+	seq_printf(seq, "CliStateOS      = %lu\n", (ulong)phdr->cli_state_os);
+	seq_printf(seq, "HeaderSize      = %lu\n", (ulong)phdr->header_size);
+	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->partition_handle);
+	seq_printf(seq, "Handle          = 0x%-16.16llx\n",
+		   (long long)phdr->handle);
+	seq_printf(seq, "VersionId       = %lu\n", (ulong)phdr->version_id);
+	seq_printf(seq, "oChannelSpace   = %llu\n",
+		   (long long)phdr->ch_space_offset);
+	if ((phdr->ch_space_offset == 0) || (errcode < 0))
+		;
+	else
+		for (i = 0; i < num_queues; i++) {
+			struct signal_queue_header q;
+
+			errcode = visorchannel_read(channel,
+						    off +
+						    phdr->ch_space_offset +
+						    (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);
diff --git a/arch/x86/visorbus/visorchipset.c b/arch/x86/visorbus/visorchipset.c
new file mode 100644
index 0000000..630137a
--- /dev/null
+++ b/arch/x86/visorbus/visorchipset.c
@@ -0,0 +1,2355 @@
+/* visorchipset_main.c
+ *
+ * Copyright (C) 2010 - 2015 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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/acpi.h>
+#include <linux/cdev.h>
+#include <linux/ctype.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/nls.h>
+#include <linux/netdevice.h>
+#include <linux/platform_device.h>
+#include <linux/uuid.h>
+#include <linux/crash_dump.h>
+#include <linux/visorbus/channel_guid.h>
+#include <linux/visorbus/guestlinuxdebug.h>
+#include <linux/visorbus/periodic_work.h>
+#include <linux/visorbus/version.h>
+#include <linux/visorbus/visorbus.h>
+
+#include "controlvmchannel.h"
+#include "controlvmcompletionstatus.h"
+#include "visorbus_private.h"
+#include "vmcallinterface.h"
+
+#define CURRENT_FILE_PC VISOR_CHIPSET_PC_visorchipset_main_c
+
+#define MAX_NAME_SIZE 128
+#define MAX_IP_SIZE   50
+#define MAXOUTSTANDINGCHANNELCOMMAND 256
+#define POLLJIFFIES_CONTROLVMCHANNEL_FAST   1
+#define POLLJIFFIES_CONTROLVMCHANNEL_SLOW 100
+
+#define MAX_CONTROLVM_PAYLOAD_BYTES (1024 * 128)
+
+#define VISORCHIPSET_MMAP_CONTROLCHANOFFSET	0x00000000
+
+#define UNISYS_SPAR_LEAF_ID 0x40000000
+
+/* The s-Par leaf ID returns "UnisysSpar64" encoded across ebx, ecx, edx */
+#define UNISYS_SPAR_ID_EBX 0x73696e55
+#define UNISYS_SPAR_ID_ECX 0x70537379
+#define UNISYS_SPAR_ID_EDX 0x34367261
+
+/*
+ * Module parameters
+ */
+static int visorchipset_major;
+static int visorchipset_visorbusregwait = 1;	/* default is on */
+static unsigned long controlvm_payload_bytes_buffered;
+static u32 dump_vhba_bus;
+
+static int
+visorchipset_open(struct inode *inode, struct file *file)
+{
+	unsigned int minor_number = iminor(inode);
+
+	if (minor_number)
+		return -ENODEV;
+	file->private_data = NULL;
+	return 0;
+}
+
+static int
+visorchipset_release(struct inode *inode, struct file *file)
+{
+	return 0;
+}
+
+/* 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
+static unsigned long poll_jiffies = POLLJIFFIES_CONTROLVMCHANNEL_FAST;
+/* when we got our last controlvm message */
+static unsigned long most_recent_message_jiffies;
+static int visorbusregistered;
+
+struct parser_context {
+	unsigned long allocbytes;
+	unsigned long param_bytes;
+	u8 *curr;
+	unsigned long bytes_remaining;
+	bool byte_stream;
+	char data[0];
+};
+
+static struct delayed_work periodic_controlvm_work;
+static DEFINE_SEMAPHORE(notifier_lock);
+
+static struct cdev file_cdev;
+static struct visorchannel **file_controlvm_channel;
+static struct controlvm_message_packet g_devicechangestate_packet;
+
+static LIST_HEAD(bus_info_list);
+static LIST_HEAD(dev_info_list);
+
+static struct visorchannel *controlvm_channel;
+
+/* Manages the request payload in the controlvm channel */
+struct visor_controlvm_payload_info {
+	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 */
+};
+
+static struct visor_controlvm_payload_info controlvm_payload_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 struct controlvm_message controlvm_pending_msg;
+static bool controlvm_pending_msg_valid;
+
+/* 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 */
+	struct parser_context *parser_ctx; /* points to input data buffer */
+};
+
+/* 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 */
+	struct parser_context *parser_ctx;
+	/* points within data area of parser_ctx to next byte of data */
+	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 */
+	struct controlvm_message_header controlvm_header;
+
+	/* link to next struct putfile_request */
+	struct list_head next_putfile_request;
+
+	/* 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;
+};
+
+struct parahotplug_request {
+	struct list_head list;
+	int id;
+	unsigned long expiration;
+	struct 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 struct visorchipset_busdev_notifiers busdev_notifiers;
+
+static void bus_create_response(struct visor_device *p, int response);
+static void bus_destroy_response(struct visor_device *p, int response);
+static void device_create_response(struct visor_device *p, int response);
+static void device_destroy_response(struct visor_device *p, int response);
+static void device_resume_response(struct visor_device *p, int response);
+
+static void visorchipset_device_pause_response(struct visor_device *p,
+					       int response);
+
+static struct 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 = visorchipset_device_pause_response,
+	.device_resume = device_resume_response,
+};
+
+/* info for /dev/visorchipset */
+static dev_t major_dev = -1; /**< indicates major num for device */
+
+/* prototypes for attributes */
+static ssize_t toolaction_show(struct device *dev,
+			       struct device_attribute *attr, char *buf);
+static ssize_t toolaction_store(struct device *dev,
+				struct device_attribute *attr,
+				const char *buf, size_t count);
+static DEVICE_ATTR_RW(toolaction);
+
+static ssize_t boottotool_show(struct device *dev,
+			       struct device_attribute *attr, char *buf);
+static ssize_t boottotool_store(struct device *dev,
+				struct device_attribute *attr, const char *buf,
+				size_t count);
+static DEVICE_ATTR_RW(boottotool);
+
+static ssize_t error_show(struct device *dev, struct device_attribute *attr,
+			  char *buf);
+static ssize_t error_store(struct device *dev, struct device_attribute *attr,
+			   const char *buf, size_t count);
+static DEVICE_ATTR_RW(error);
+
+static ssize_t textid_show(struct device *dev, struct device_attribute *attr,
+			   char *buf);
+static ssize_t textid_store(struct device *dev, struct device_attribute *attr,
+			    const char *buf, size_t count);
+static DEVICE_ATTR_RW(textid);
+
+static ssize_t remaining_steps_show(struct device *dev,
+				    struct device_attribute *attr, char *buf);
+static ssize_t remaining_steps_store(struct device *dev,
+				     struct device_attribute *attr,
+				     const char *buf, size_t count);
+static DEVICE_ATTR_RW(remaining_steps);
+
+static ssize_t devicedisabled_store(struct device *dev,
+				    struct device_attribute *attr,
+				    const char *buf, size_t count);
+static DEVICE_ATTR_WO(devicedisabled);
+
+static ssize_t deviceenabled_store(struct device *dev,
+				   struct device_attribute *attr,
+				   const char *buf, size_t count);
+static DEVICE_ATTR_WO(deviceenabled);
+
+static struct attribute *visorchipset_install_attrs[] = {
+	&dev_attr_toolaction.attr,
+	&dev_attr_boottotool.attr,
+	&dev_attr_error.attr,
+	&dev_attr_textid.attr,
+	&dev_attr_remaining_steps.attr,
+	NULL
+};
+
+static struct attribute_group visorchipset_install_group = {
+	.name = "install",
+	.attrs = visorchipset_install_attrs
+};
+
+static struct attribute *visorchipset_parahotplug_attrs[] = {
+	&dev_attr_devicedisabled.attr,
+	&dev_attr_deviceenabled.attr,
+	NULL
+};
+
+static struct attribute_group visorchipset_parahotplug_group = {
+	.name = "parahotplug",
+	.attrs = visorchipset_parahotplug_attrs
+};
+
+static const struct attribute_group *visorchipset_dev_groups[] = {
+	&visorchipset_install_group,
+	&visorchipset_parahotplug_group,
+	NULL
+};
+
+static void visorchipset_dev_release(struct device *dev)
+{
+}
+
+/* /sys/devices/platform/visorchipset */
+static struct platform_device visorchipset_platform_device = {
+	.name = "visorchipset",
+	.id = -1,
+	.dev.groups = visorchipset_dev_groups,
+	.dev.release = visorchipset_dev_release,
+};
+
+/* Function prototypes */
+static void controlvm_respond(struct controlvm_message_header *msg_hdr,
+			      int response);
+static void controlvm_respond_chipset_init(
+		struct controlvm_message_header *msg_hdr, int response,
+		enum ultra_chipset_feature features);
+static void controlvm_respond_physdev_changestate(
+		struct controlvm_message_header *msg_hdr, int response,
+		struct spar_segment_state state);
+
+static void parser_done(struct parser_context *ctx);
+
+static struct parser_context *
+parser_init_byte_stream(u64 addr, u32 bytes, bool local, bool *retry)
+{
+	int allocbytes = sizeof(struct parser_context) + bytes;
+	struct parser_context *ctx;
+
+	if (retry)
+		*retry = false;
+
+	/*
+	 * alloc an 0 extra byte to ensure payload is
+	 * '\0'-terminated
+	 */
+	allocbytes++;
+	if ((controlvm_payload_bytes_buffered + bytes)
+	    > MAX_CONTROLVM_PAYLOAD_BYTES) {
+		if (retry)
+			*retry = true;
+		return NULL;
+	}
+	ctx = kzalloc(allocbytes, GFP_KERNEL | __GFP_NORETRY);
+	if (!ctx) {
+		if (retry)
+			*retry = true;
+		return NULL;
+	}
+
+	ctx->allocbytes = allocbytes;
+	ctx->param_bytes = bytes;
+	ctx->curr = NULL;
+	ctx->bytes_remaining = 0;
+	ctx->byte_stream = false;
+	if (local) {
+		void *p;
+
+		if (addr > virt_to_phys(high_memory - 1))
+			goto err_finish_ctx;
+		p = __va((unsigned long)(addr));
+		memcpy(ctx->data, p, bytes);
+	} else {
+		void *mapping = memremap(addr, bytes, MEMREMAP_WB);
+
+		if (!mapping)
+			goto err_finish_ctx;
+		memcpy(ctx->data, mapping, bytes);
+		memunmap(mapping);
+	}
+
+	ctx->byte_stream = true;
+	controlvm_payload_bytes_buffered += ctx->param_bytes;
+
+	return ctx;
+
+err_finish_ctx:
+	parser_done(ctx);
+	return NULL;
+}
+
+static uuid_le
+parser_id_get(struct parser_context *ctx)
+{
+	struct spar_controlvm_parameters_header *phdr = NULL;
+
+	if (!ctx)
+		return NULL_UUID_LE;
+	phdr = (struct spar_controlvm_parameters_header *)(ctx->data);
+	return phdr->id;
+}
+
+/** Describes the state from the perspective of which controlvm messages have
+ *  been received for a bus or device.
+ */
+
+enum PARSER_WHICH_STRING {
+	PARSERSTRING_INITIATOR,
+	PARSERSTRING_TARGET,
+	PARSERSTRING_CONNECTION,
+	PARSERSTRING_NAME, /* TODO: only PARSERSTRING_NAME is used ? */
+};
+
+static void
+parser_param_start(struct parser_context *ctx,
+		   enum PARSER_WHICH_STRING which_string)
+{
+	struct spar_controlvm_parameters_header *phdr = NULL;
+
+	if (!ctx)
+		return;
+
+	phdr = (struct spar_controlvm_parameters_header *)(ctx->data);
+	switch (which_string) {
+	case PARSERSTRING_INITIATOR:
+		ctx->curr = ctx->data + phdr->initiator_offset;
+		ctx->bytes_remaining = phdr->initiator_length;
+		break;
+	case PARSERSTRING_TARGET:
+		ctx->curr = ctx->data + phdr->target_offset;
+		ctx->bytes_remaining = phdr->target_length;
+		break;
+	case PARSERSTRING_CONNECTION:
+		ctx->curr = ctx->data + phdr->connection_offset;
+		ctx->bytes_remaining = phdr->connection_length;
+		break;
+	case PARSERSTRING_NAME:
+		ctx->curr = ctx->data + phdr->name_offset;
+		ctx->bytes_remaining = phdr->name_length;
+		break;
+	default:
+		break;
+	}
+}
+
+static void parser_done(struct parser_context *ctx)
+{
+	if (!ctx)
+		return;
+	controlvm_payload_bytes_buffered -= ctx->param_bytes;
+	kfree(ctx);
+}
+
+static void *
+parser_string_get(struct parser_context *ctx)
+{
+	u8 *pscan;
+	unsigned long 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)
+		return NULL;
+	if (value_length > 0)
+		memcpy(value, pscan, value_length);
+	((u8 *)(value))[value_length] = '\0';
+	return value;
+}
+
+static ssize_t toolaction_show(struct device *dev,
+			       struct device_attribute *attr,
+			       char *buf)
+{
+	u8 tool_action = 0;
+
+	visorchannel_read(controlvm_channel,
+			  offsetof(struct spar_controlvm_channel_protocol,
+				   tool_action), &tool_action, sizeof(u8));
+	return scnprintf(buf, PAGE_SIZE, "%u\n", tool_action);
+}
+
+static ssize_t toolaction_store(struct device *dev,
+				struct device_attribute *attr,
+				const char *buf, size_t count)
+{
+	u8 tool_action;
+	int ret;
+
+	if (kstrtou8(buf, 10, &tool_action))
+		return -EINVAL;
+
+	ret = visorchannel_write
+		(controlvm_channel,
+		 offsetof(struct spar_controlvm_channel_protocol,
+			  tool_action),
+		 &tool_action, sizeof(u8));
+
+	if (ret)
+		return ret;
+	return count;
+}
+
+static ssize_t boottotool_show(struct device *dev,
+			       struct device_attribute *attr,
+			       char *buf)
+{
+	struct efi_spar_indication efi_spar_indication;
+
+	visorchannel_read(controlvm_channel,
+			  offsetof(struct spar_controlvm_channel_protocol,
+				   efi_spar_ind), &efi_spar_indication,
+			  sizeof(struct efi_spar_indication));
+	return scnprintf(buf, PAGE_SIZE, "%u\n",
+			 efi_spar_indication.boot_to_tool);
+}
+
+static ssize_t boottotool_store(struct device *dev,
+				struct device_attribute *attr,
+				const char *buf, size_t count)
+{
+	int val, ret;
+	struct efi_spar_indication efi_spar_indication;
+
+	if (kstrtoint(buf, 10, &val))
+		return -EINVAL;
+
+	efi_spar_indication.boot_to_tool = val;
+	ret = visorchannel_write
+		(controlvm_channel,
+		 offsetof(struct spar_controlvm_channel_protocol,
+			  efi_spar_ind), &(efi_spar_indication),
+		 sizeof(struct efi_spar_indication));
+
+	if (ret)
+		return ret;
+	return count;
+}
+
+static ssize_t error_show(struct device *dev, struct device_attribute *attr,
+			  char *buf)
+{
+	u32 error = 0;
+
+	visorchannel_read(controlvm_channel,
+			  offsetof(struct spar_controlvm_channel_protocol,
+				   installation_error),
+			  &error, sizeof(u32));
+	return scnprintf(buf, PAGE_SIZE, "%i\n", error);
+}
+
+static ssize_t error_store(struct device *dev, struct device_attribute *attr,
+			   const char *buf, size_t count)
+{
+	u32 error;
+	int ret;
+
+	if (kstrtou32(buf, 10, &error))
+		return -EINVAL;
+
+	ret = visorchannel_write
+		(controlvm_channel,
+		 offsetof(struct spar_controlvm_channel_protocol,
+			  installation_error),
+		 &error, sizeof(u32));
+	if (ret)
+		return ret;
+	return count;
+}
+
+static ssize_t textid_show(struct device *dev, struct device_attribute *attr,
+			   char *buf)
+{
+	u32 text_id = 0;
+
+	visorchannel_read
+		(controlvm_channel,
+		 offsetof(struct spar_controlvm_channel_protocol,
+			  installation_text_id),
+		 &text_id, sizeof(u32));
+	return scnprintf(buf, PAGE_SIZE, "%i\n", text_id);
+}
+
+static ssize_t textid_store(struct device *dev, struct device_attribute *attr,
+			    const char *buf, size_t count)
+{
+	u32 text_id;
+	int ret;
+
+	if (kstrtou32(buf, 10, &text_id))
+		return -EINVAL;
+
+	ret = visorchannel_write
+		(controlvm_channel,
+		 offsetof(struct spar_controlvm_channel_protocol,
+			  installation_text_id),
+		 &text_id, sizeof(u32));
+	if (ret)
+		return ret;
+	return count;
+}
+
+static ssize_t remaining_steps_show(struct device *dev,
+				    struct device_attribute *attr, char *buf)
+{
+	u16 remaining_steps = 0;
+
+	visorchannel_read(controlvm_channel,
+			  offsetof(struct spar_controlvm_channel_protocol,
+				   installation_remaining_steps),
+			  &remaining_steps, sizeof(u16));
+	return scnprintf(buf, PAGE_SIZE, "%hu\n", remaining_steps);
+}
+
+static ssize_t remaining_steps_store(struct device *dev,
+				     struct device_attribute *attr,
+				     const char *buf, size_t count)
+{
+	u16 remaining_steps;
+	int ret;
+
+	if (kstrtou16(buf, 10, &remaining_steps))
+		return -EINVAL;
+
+	ret = visorchannel_write
+		(controlvm_channel,
+		 offsetof(struct spar_controlvm_channel_protocol,
+			  installation_remaining_steps),
+		 &remaining_steps, sizeof(u16));
+	if (ret)
+		return ret;
+	return count;
+}
+
+struct visor_busdev {
+	u32 bus_no;
+	u32 dev_no;
+};
+
+static int match_visorbus_dev_by_id(struct device *dev, void *data)
+{
+	struct visor_device *vdev = to_visor_device(dev);
+	struct visor_busdev *id = data;
+	u32 bus_no = id->bus_no;
+	u32 dev_no = id->dev_no;
+
+	if ((vdev->chipset_bus_no == bus_no) &&
+	    (vdev->chipset_dev_no == dev_no))
+		return 1;
+
+	return 0;
+}
+
+struct visor_device *visorbus_get_device_by_id(u32 bus_no, u32 dev_no,
+					       struct visor_device *from)
+{
+	struct device *dev;
+	struct device *dev_start = NULL;
+	struct visor_device *vdev = NULL;
+	struct visor_busdev id = {
+			.bus_no = bus_no,
+			.dev_no = dev_no
+		};
+
+	if (from)
+		dev_start = &from->device;
+	dev = bus_find_device(&visorbus_type, dev_start, (void *)&id,
+			      match_visorbus_dev_by_id);
+	if (dev)
+		vdev = to_visor_device(dev);
+	return vdev;
+}
+EXPORT_SYMBOL(visorbus_get_device_by_id);
+
+void
+visorchipset_register_busdev(
+			struct visorchipset_busdev_notifiers *notifiers,
+			struct visorchipset_busdev_responders *responders,
+			struct ultra_vbus_deviceinfo *driver_info)
+{
+	down(&notifier_lock);
+	if (!notifiers) {
+		memset(&busdev_notifiers, 0,
+		       sizeof(busdev_notifiers));
+		visorbusregistered = 0;	/* clear flag */
+	} else {
+		busdev_notifiers = *notifiers;
+		visorbusregistered = 1;	/* set flag */
+	}
+	if (responders)
+		*responders = busdev_responders;
+	if (driver_info)
+		bus_device_info_init(driver_info, "chipset", "visorchipset",
+				     VERSION, NULL);
+
+	up(&notifier_lock);
+}
+EXPORT_SYMBOL_GPL(visorchipset_register_busdev);
+
+static void
+chipset_init(struct controlvm_message *inmsg)
+{
+	static int chipset_inited;
+	enum ultra_chipset_feature features = 0;
+	int rc = CONTROLVM_RESP_SUCCESS;
+
+	POSTCODE_LINUX_2(CHIPSET_INIT_ENTRY_PC, POSTCODE_SEVERITY_INFO);
+	if (chipset_inited) {
+		rc = -CONTROLVM_RESP_ERROR_ALREADY_DONE;
+		goto out_respond;
+	}
+	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.init_chipset.
+	    features & ULTRA_CHIPSET_FEATURE_PARA_HOTPLUG;
+
+	/* Set the "reply" bit so Command knows this is a
+	 * features-aware driver.
+	 */
+	features |= ULTRA_CHIPSET_FEATURE_REPLY;
+
+out_respond:
+	if (inmsg->hdr.flags.response_expected)
+		controlvm_respond_chipset_init(&inmsg->hdr, rc, features);
+}
+
+static void
+controlvm_init_response(struct controlvm_message *msg,
+			struct controlvm_message_header *msg_hdr, int response)
+{
+	memset(msg, 0, sizeof(struct controlvm_message));
+	memcpy(&msg->hdr, msg_hdr, sizeof(struct controlvm_message_header));
+	msg->hdr.payload_bytes = 0;
+	msg->hdr.payload_vm_offset = 0;
+	msg->hdr.payload_max_bytes = 0;
+	if (response < 0) {
+		msg->hdr.flags.failed = 1;
+		msg->hdr.completion_status = (u32)(-response);
+	}
+}
+
+static void
+controlvm_respond(struct controlvm_message_header *msg_hdr, int response)
+{
+	struct controlvm_message outmsg;
+
+	controlvm_init_response(&outmsg, msg_hdr, response);
+	if (outmsg.hdr.flags.test_message == 1)
+		return;
+
+	if (!visorchannel_signalinsert(controlvm_channel,
+				       CONTROLVM_QUEUE_REQUEST, &outmsg)) {
+		return;
+	}
+}
+
+static void
+controlvm_respond_chipset_init(struct controlvm_message_header *msg_hdr,
+			       int response,
+			       enum ultra_chipset_feature features)
+{
+	struct controlvm_message outmsg;
+
+	controlvm_init_response(&outmsg, msg_hdr, response);
+	outmsg.cmd.init_chipset.features = features;
+	if (!visorchannel_signalinsert(controlvm_channel,
+				       CONTROLVM_QUEUE_REQUEST, &outmsg)) {
+		return;
+	}
+}
+
+static void controlvm_respond_physdev_changestate(
+		struct controlvm_message_header *msg_hdr, int response,
+		struct spar_segment_state state)
+{
+	struct controlvm_message outmsg;
+
+	controlvm_init_response(&outmsg, msg_hdr, response);
+	outmsg.cmd.device_change_state.state = state;
+	outmsg.cmd.device_change_state.flags.phys_device = 1;
+	if (!visorchannel_signalinsert(controlvm_channel,
+				       CONTROLVM_QUEUE_REQUEST, &outmsg)) {
+		return;
+	}
+}
+
+enum crash_obj_type {
+	CRASH_DEV,
+	CRASH_BUS,
+};
+
+static void
+save_crash_message(struct controlvm_message *msg, enum crash_obj_type typ)
+{
+	u32 local_crash_msg_offset;
+	u16 local_crash_msg_count;
+
+	if (visorchannel_read(controlvm_channel,
+			      offsetof(struct spar_controlvm_channel_protocol,
+				       saved_crash_message_count),
+			      &local_crash_msg_count, sizeof(u16)) < 0) {
+		POSTCODE_LINUX_2(CRASH_DEV_CTRL_RD_FAILURE_PC,
+				 POSTCODE_SEVERITY_ERR);
+		return;
+	}
+
+	if (local_crash_msg_count != CONTROLVM_CRASHMSG_MAX) {
+		POSTCODE_LINUX_3(CRASH_DEV_COUNT_FAILURE_PC,
+				 local_crash_msg_count,
+				 POSTCODE_SEVERITY_ERR);
+		return;
+	}
+
+	if (visorchannel_read(controlvm_channel,
+			      offsetof(struct spar_controlvm_channel_protocol,
+				       saved_crash_message_offset),
+			      &local_crash_msg_offset, sizeof(u32)) < 0) {
+		POSTCODE_LINUX_2(CRASH_DEV_CTRL_RD_FAILURE_PC,
+				 POSTCODE_SEVERITY_ERR);
+		return;
+	}
+
+	if (typ == CRASH_BUS) {
+		if (visorchannel_write(controlvm_channel,
+				       local_crash_msg_offset,
+				       msg,
+				       sizeof(struct controlvm_message)) < 0) {
+			POSTCODE_LINUX_2(SAVE_MSG_BUS_FAILURE_PC,
+					 POSTCODE_SEVERITY_ERR);
+			return;
+		}
+	} else {
+		local_crash_msg_offset += sizeof(struct controlvm_message);
+		if (visorchannel_write(controlvm_channel,
+				       local_crash_msg_offset,
+				       msg,
+				       sizeof(struct controlvm_message)) < 0) {
+			POSTCODE_LINUX_2(SAVE_MSG_DEV_FAILURE_PC,
+					 POSTCODE_SEVERITY_ERR);
+			return;
+		}
+	}
+}
+
+static void
+bus_responder(enum controlvm_id cmd_id,
+	      struct controlvm_message_header *pending_msg_hdr,
+	      int response)
+{
+	if (!pending_msg_hdr)
+		return;		/* no controlvm response needed */
+
+	if (pending_msg_hdr->id != (u32)cmd_id)
+		return;
+
+	controlvm_respond(pending_msg_hdr, response);
+}
+
+static void
+device_changestate_responder(enum controlvm_id cmd_id,
+			     struct visor_device *p, int response,
+			     struct spar_segment_state response_state)
+{
+	struct controlvm_message outmsg;
+	u32 bus_no = p->chipset_bus_no;
+	u32 dev_no = p->chipset_dev_no;
+
+	if (!p->pending_msg_hdr)
+		return;		/* no controlvm response needed */
+	if (p->pending_msg_hdr->id != cmd_id)
+		return;
+
+	controlvm_init_response(&outmsg, p->pending_msg_hdr, response);
+
+	outmsg.cmd.device_change_state.bus_no = bus_no;
+	outmsg.cmd.device_change_state.dev_no = dev_no;
+	outmsg.cmd.device_change_state.state = response_state;
+
+	if (!visorchannel_signalinsert(controlvm_channel,
+				       CONTROLVM_QUEUE_REQUEST, &outmsg))
+		return;
+}
+
+static void
+device_responder(enum controlvm_id cmd_id,
+		 struct controlvm_message_header *pending_msg_hdr,
+		 int response)
+{
+	if (!pending_msg_hdr)
+		return;		/* no controlvm response needed */
+
+	if (pending_msg_hdr->id != (u32)cmd_id)
+		return;
+
+	controlvm_respond(pending_msg_hdr, response);
+}
+
+static void
+bus_epilog(struct visor_device *bus_info,
+	   u32 cmd, struct controlvm_message_header *msg_hdr,
+	   int response, bool need_response)
+{
+	struct controlvm_message_header *pmsg_hdr = NULL;
+
+	down(&notifier_lock);
+
+	if (!bus_info) {
+		/* relying on a valid passed in response code */
+		/* be lazy and re-use msg_hdr for this failure, is this ok?? */
+		pmsg_hdr = msg_hdr;
+		goto out_respond_and_unlock;
+	}
+
+	if (bus_info->pending_msg_hdr) {
+		/* only non-NULL if dev is still waiting on a response */
+		response = -CONTROLVM_RESP_ERROR_MESSAGE_ID_INVALID_FOR_CLIENT;
+		pmsg_hdr = bus_info->pending_msg_hdr;
+		goto out_respond_and_unlock;
+	}
+
+	if (need_response) {
+		pmsg_hdr = kzalloc(sizeof(*pmsg_hdr), GFP_KERNEL);
+		if (!pmsg_hdr) {
+			POSTCODE_LINUX_4(MALLOC_FAILURE_PC, cmd,
+					 bus_info->chipset_bus_no,
+					 POSTCODE_SEVERITY_ERR);
+			goto out_unlock;
+		}
+
+		memcpy(pmsg_hdr, msg_hdr,
+		       sizeof(struct controlvm_message_header));
+		bus_info->pending_msg_hdr = pmsg_hdr;
+	}
+
+	if (response == CONTROLVM_RESP_SUCCESS) {
+		switch (cmd) {
+		case CONTROLVM_BUS_CREATE:
+			if (busdev_notifiers.bus_create) {
+				(*busdev_notifiers.bus_create) (bus_info);
+				goto out_unlock;
+			}
+			break;
+		case CONTROLVM_BUS_DESTROY:
+			if (busdev_notifiers.bus_destroy) {
+				(*busdev_notifiers.bus_destroy) (bus_info);
+				goto out_unlock;
+			}
+			break;
+		}
+	}
+
+out_respond_and_unlock:
+	bus_responder(cmd, pmsg_hdr, response);
+
+out_unlock:
+	up(&notifier_lock);
+}
+
+static void
+device_epilog(struct visor_device *dev_info,
+	      struct spar_segment_state state, u32 cmd,
+	      struct controlvm_message_header *msg_hdr, int response,
+	      bool need_response, bool for_visorbus)
+{
+	struct visorchipset_busdev_notifiers *notifiers;
+	struct controlvm_message_header *pmsg_hdr = NULL;
+
+	notifiers = &busdev_notifiers;
+
+	down(&notifier_lock);
+	if (!dev_info) {
+		/* relying on a valid passed in response code */
+		/* be lazy and re-use msg_hdr for this failure, is this ok?? */
+		pmsg_hdr = msg_hdr;
+		goto out_respond_and_unlock;
+	}
+
+	if (dev_info->pending_msg_hdr) {
+		/* only non-NULL if dev is still waiting on a response */
+		response = -CONTROLVM_RESP_ERROR_MESSAGE_ID_INVALID_FOR_CLIENT;
+		pmsg_hdr = dev_info->pending_msg_hdr;
+		goto out_respond_and_unlock;
+	}
+
+	if (need_response) {
+		pmsg_hdr = kzalloc(sizeof(*pmsg_hdr), GFP_KERNEL);
+		if (!pmsg_hdr) {
+			response = -CONTROLVM_RESP_ERROR_KMALLOC_FAILED;
+			goto out_respond_and_unlock;
+		}
+
+		memcpy(pmsg_hdr, msg_hdr,
+		       sizeof(struct controlvm_message_header));
+		dev_info->pending_msg_hdr = pmsg_hdr;
+	}
+
+	if (response >= 0) {
+		switch (cmd) {
+		case CONTROLVM_DEVICE_CREATE:
+			if (notifiers->device_create) {
+				(*notifiers->device_create) (dev_info);
+				goto out_unlock;
+			}
+			break;
+		case CONTROLVM_DEVICE_CHANGESTATE:
+			/* ServerReady / ServerRunning / SegmentStateRunning */
+			if (state.alive == segment_state_running.alive &&
+			    state.operating ==
+				segment_state_running.operating) {
+				if (notifiers->device_resume) {
+					(*notifiers->device_resume) (dev_info);
+					goto out_unlock;
+				}
+			}
+			/* ServerNotReady / ServerLost / SegmentStateStandby */
+			else if (state.alive == segment_state_standby.alive &&
+				 state.operating ==
+				 segment_state_standby.operating) {
+				/* technically this is standby case
+				 * where server is lost
+				 */
+				if (notifiers->device_pause) {
+					(*notifiers->device_pause) (dev_info);
+					goto out_unlock;
+				}
+			}
+			break;
+		case CONTROLVM_DEVICE_DESTROY:
+			if (notifiers->device_destroy) {
+				(*notifiers->device_destroy) (dev_info);
+				goto out_unlock;
+			}
+			break;
+		}
+	}
+
+out_respond_and_unlock:
+	device_responder(cmd, pmsg_hdr, response);
+
+out_unlock:
+	up(&notifier_lock);
+}
+
+static void
+bus_create(struct controlvm_message *inmsg)
+{
+	struct controlvm_message_packet *cmd = &inmsg->cmd;
+	u32 bus_no = cmd->create_bus.bus_no;
+	int rc = CONTROLVM_RESP_SUCCESS;
+	struct visor_device *bus_info;
+	struct visorchannel *visorchannel;
+
+	bus_info = visorbus_get_device_by_id(bus_no, BUS_ROOT_DEVICE, NULL);
+	if (bus_info && (bus_info->state.created == 1)) {
+		POSTCODE_LINUX_3(BUS_CREATE_FAILURE_PC, bus_no,
+				 POSTCODE_SEVERITY_ERR);
+		rc = -CONTROLVM_RESP_ERROR_ALREADY_DONE;
+		goto out_bus_epilog;
+	}
+	bus_info = kzalloc(sizeof(*bus_info), GFP_KERNEL);
+	if (!bus_info) {
+		POSTCODE_LINUX_3(BUS_CREATE_FAILURE_PC, bus_no,
+				 POSTCODE_SEVERITY_ERR);
+		rc = -CONTROLVM_RESP_ERROR_KMALLOC_FAILED;
+		goto out_bus_epilog;
+	}
+
+	INIT_LIST_HEAD(&bus_info->list_all);
+	bus_info->chipset_bus_no = bus_no;
+	bus_info->chipset_dev_no = BUS_ROOT_DEVICE;
+
+	POSTCODE_LINUX_3(BUS_CREATE_ENTRY_PC, bus_no, POSTCODE_SEVERITY_INFO);
+
+	visorchannel = visorchannel_create(cmd->create_bus.channel_addr,
+					   cmd->create_bus.channel_bytes,
+					   GFP_KERNEL,
+					   cmd->create_bus.bus_data_type_uuid);
+
+	if (!visorchannel) {
+		POSTCODE_LINUX_3(BUS_CREATE_FAILURE_PC, bus_no,
+				 POSTCODE_SEVERITY_ERR);
+		rc = -CONTROLVM_RESP_ERROR_KMALLOC_FAILED;
+		kfree(bus_info);
+		bus_info = NULL;
+		goto out_bus_epilog;
+	}
+	bus_info->visorchannel = visorchannel;
+	if (uuid_le_cmp(cmd->create_bus.bus_inst_uuid, spar_siovm_uuid) == 0) {
+		dump_vhba_bus = bus_no;
+		save_crash_message(inmsg, CRASH_BUS);
+	}
+
+	POSTCODE_LINUX_3(BUS_CREATE_EXIT_PC, bus_no, POSTCODE_SEVERITY_INFO);
+
+out_bus_epilog:
+	bus_epilog(bus_info, CONTROLVM_BUS_CREATE, &inmsg->hdr,
+		   rc, inmsg->hdr.flags.response_expected == 1);
+}
+
+static void
+bus_destroy(struct controlvm_message *inmsg)
+{
+	struct controlvm_message_packet *cmd = &inmsg->cmd;
+	u32 bus_no = cmd->destroy_bus.bus_no;
+	struct visor_device *bus_info;
+	int rc = CONTROLVM_RESP_SUCCESS;
+
+	bus_info = visorbus_get_device_by_id(bus_no, BUS_ROOT_DEVICE, NULL);
+	if (!bus_info)
+		rc = -CONTROLVM_RESP_ERROR_BUS_INVALID;
+	else if (bus_info->state.created == 0)
+		rc = -CONTROLVM_RESP_ERROR_ALREADY_DONE;
+
+	bus_epilog(bus_info, CONTROLVM_BUS_DESTROY, &inmsg->hdr,
+		   rc, inmsg->hdr.flags.response_expected == 1);
+
+	/* bus_info is freed as part of the busdevice_release function */
+}
+
+static void
+bus_configure(struct controlvm_message *inmsg,
+	      struct parser_context *parser_ctx)
+{
+	struct controlvm_message_packet *cmd = &inmsg->cmd;
+	u32 bus_no;
+	struct visor_device *bus_info;
+	int rc = CONTROLVM_RESP_SUCCESS;
+
+	bus_no = cmd->configure_bus.bus_no;
+	POSTCODE_LINUX_3(BUS_CONFIGURE_ENTRY_PC, bus_no,
+			 POSTCODE_SEVERITY_INFO);
+
+	bus_info = visorbus_get_device_by_id(bus_no, BUS_ROOT_DEVICE, NULL);
+	if (!bus_info) {
+		POSTCODE_LINUX_3(BUS_CONFIGURE_FAILURE_PC, bus_no,
+				 POSTCODE_SEVERITY_ERR);
+		rc = -CONTROLVM_RESP_ERROR_BUS_INVALID;
+	} else if (bus_info->state.created == 0) {
+		POSTCODE_LINUX_3(BUS_CONFIGURE_FAILURE_PC, bus_no,
+				 POSTCODE_SEVERITY_ERR);
+		rc = -CONTROLVM_RESP_ERROR_BUS_INVALID;
+	} else if (bus_info->pending_msg_hdr) {
+		POSTCODE_LINUX_3(BUS_CONFIGURE_FAILURE_PC, bus_no,
+				 POSTCODE_SEVERITY_ERR);
+		rc = -CONTROLVM_RESP_ERROR_MESSAGE_ID_INVALID_FOR_CLIENT;
+	} else {
+		visorchannel_set_clientpartition
+			(bus_info->visorchannel,
+			 cmd->configure_bus.guest_handle);
+		bus_info->partition_uuid = parser_id_get(parser_ctx);
+		parser_param_start(parser_ctx, PARSERSTRING_NAME);
+		bus_info->name = parser_string_get(parser_ctx);
+
+		POSTCODE_LINUX_3(BUS_CONFIGURE_EXIT_PC, bus_no,
+				 POSTCODE_SEVERITY_INFO);
+	}
+	bus_epilog(bus_info, CONTROLVM_BUS_CONFIGURE, &inmsg->hdr,
+		   rc, inmsg->hdr.flags.response_expected == 1);
+}
+
+static void
+my_device_create(struct controlvm_message *inmsg)
+{
+	struct controlvm_message_packet *cmd = &inmsg->cmd;
+	u32 bus_no = cmd->create_device.bus_no;
+	u32 dev_no = cmd->create_device.dev_no;
+	struct visor_device *dev_info = NULL;
+	struct visor_device *bus_info;
+	struct visorchannel *visorchannel;
+	int rc = CONTROLVM_RESP_SUCCESS;
+
+	bus_info = visorbus_get_device_by_id(bus_no, BUS_ROOT_DEVICE, NULL);
+	if (!bus_info) {
+		POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, dev_no, bus_no,
+				 POSTCODE_SEVERITY_ERR);
+		rc = -CONTROLVM_RESP_ERROR_BUS_INVALID;
+		goto out_respond;
+	}
+
+	if (bus_info->state.created == 0) {
+		POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, dev_no, bus_no,
+				 POSTCODE_SEVERITY_ERR);
+		rc = -CONTROLVM_RESP_ERROR_BUS_INVALID;
+		goto out_respond;
+	}
+
+	dev_info = visorbus_get_device_by_id(bus_no, dev_no, NULL);
+	if (dev_info && (dev_info->state.created == 1)) {
+		POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, dev_no, bus_no,
+				 POSTCODE_SEVERITY_ERR);
+		rc = -CONTROLVM_RESP_ERROR_ALREADY_DONE;
+		goto out_respond;
+	}
+
+	dev_info = kzalloc(sizeof(*dev_info), GFP_KERNEL);
+	if (!dev_info) {
+		POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, dev_no, bus_no,
+				 POSTCODE_SEVERITY_ERR);
+		rc = -CONTROLVM_RESP_ERROR_KMALLOC_FAILED;
+		goto out_respond;
+	}
+
+	dev_info->chipset_bus_no = bus_no;
+	dev_info->chipset_dev_no = dev_no;
+	dev_info->inst = cmd->create_device.dev_inst_uuid;
+
+	/* not sure where the best place to set the 'parent' */
+	dev_info->device.parent = &bus_info->device;
+
+	POSTCODE_LINUX_4(DEVICE_CREATE_ENTRY_PC, dev_no, bus_no,
+			 POSTCODE_SEVERITY_INFO);
+
+	visorchannel =
+	       visorchannel_create_with_lock(cmd->create_device.channel_addr,
+					     cmd->create_device.channel_bytes,
+					     GFP_KERNEL,
+					     cmd->create_device.data_type_uuid);
+
+	if (!visorchannel) {
+		POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, dev_no, bus_no,
+				 POSTCODE_SEVERITY_ERR);
+		rc = -CONTROLVM_RESP_ERROR_KMALLOC_FAILED;
+		kfree(dev_info);
+		dev_info = NULL;
+		goto out_respond;
+	}
+	dev_info->visorchannel = visorchannel;
+	dev_info->channel_type_guid = cmd->create_device.data_type_uuid;
+	if (uuid_le_cmp(cmd->create_device.data_type_uuid,
+			spar_vhba_channel_protocol_uuid) == 0)
+		save_crash_message(inmsg, CRASH_DEV);
+
+	POSTCODE_LINUX_4(DEVICE_CREATE_EXIT_PC, dev_no, bus_no,
+			 POSTCODE_SEVERITY_INFO);
+out_respond:
+	device_epilog(dev_info, segment_state_running,
+		      CONTROLVM_DEVICE_CREATE, &inmsg->hdr, rc,
+		      inmsg->hdr.flags.response_expected == 1, 1);
+}
+
+static void
+my_device_changestate(struct controlvm_message *inmsg)
+{
+	struct controlvm_message_packet *cmd = &inmsg->cmd;
+	u32 bus_no = cmd->device_change_state.bus_no;
+	u32 dev_no = cmd->device_change_state.dev_no;
+	struct spar_segment_state state = cmd->device_change_state.state;
+	struct visor_device *dev_info;
+	int rc = CONTROLVM_RESP_SUCCESS;
+
+	dev_info = visorbus_get_device_by_id(bus_no, dev_no, NULL);
+	if (!dev_info) {
+		POSTCODE_LINUX_4(DEVICE_CHANGESTATE_FAILURE_PC, dev_no, bus_no,
+				 POSTCODE_SEVERITY_ERR);
+		rc = -CONTROLVM_RESP_ERROR_DEVICE_INVALID;
+	} else if (dev_info->state.created == 0) {
+		POSTCODE_LINUX_4(DEVICE_CHANGESTATE_FAILURE_PC, dev_no, bus_no,
+				 POSTCODE_SEVERITY_ERR);
+		rc = -CONTROLVM_RESP_ERROR_DEVICE_INVALID;
+	}
+	if ((rc >= CONTROLVM_RESP_SUCCESS) && dev_info)
+		device_epilog(dev_info, state,
+			      CONTROLVM_DEVICE_CHANGESTATE, &inmsg->hdr, rc,
+			      inmsg->hdr.flags.response_expected == 1, 1);
+}
+
+static void
+my_device_destroy(struct controlvm_message *inmsg)
+{
+	struct controlvm_message_packet *cmd = &inmsg->cmd;
+	u32 bus_no = cmd->destroy_device.bus_no;
+	u32 dev_no = cmd->destroy_device.dev_no;
+	struct visor_device *dev_info;
+	int rc = CONTROLVM_RESP_SUCCESS;
+
+	dev_info = visorbus_get_device_by_id(bus_no, dev_no, NULL);
+	if (!dev_info)
+		rc = -CONTROLVM_RESP_ERROR_DEVICE_INVALID;
+	else if (dev_info->state.created == 0)
+		rc = -CONTROLVM_RESP_ERROR_ALREADY_DONE;
+
+	if ((rc >= CONTROLVM_RESP_SUCCESS) && dev_info)
+		device_epilog(dev_info, segment_state_running,
+			      CONTROLVM_DEVICE_DESTROY, &inmsg->hdr, rc,
+			      inmsg->hdr.flags.response_expected == 1, 1);
+}
+
+/* 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(u64 phys_addr, u64 offset, u32 bytes,
+				  struct visor_controlvm_payload_info *info)
+{
+	u8 *payload = NULL;
+
+	if (!info)
+		return -CONTROLVM_RESP_ERROR_PAYLOAD_INVALID;
+
+	memset(info, 0, sizeof(struct visor_controlvm_payload_info));
+	if ((offset == 0) || (bytes == 0))
+		return -CONTROLVM_RESP_ERROR_PAYLOAD_INVALID;
+
+	payload = memremap(phys_addr + offset, bytes, MEMREMAP_WB);
+	if (!payload)
+		return -CONTROLVM_RESP_ERROR_IOREMAP_FAILED;
+
+	info->offset = offset;
+	info->bytes = bytes;
+	info->ptr = payload;
+
+	return CONTROLVM_RESP_SUCCESS;
+}
+
+static void
+destroy_controlvm_payload_info(struct visor_controlvm_payload_info *info)
+{
+	if (info->ptr) {
+		memunmap(info->ptr);
+		info->ptr = NULL;
+	}
+	memset(info, 0, sizeof(struct visor_controlvm_payload_info));
+}
+
+static void
+initialize_controlvm_payload(void)
+{
+	u64 phys_addr = visorchannel_get_physaddr(controlvm_channel);
+	u64 payload_offset = 0;
+	u32 payload_bytes = 0;
+
+	if (visorchannel_read(controlvm_channel,
+			      offsetof(struct spar_controlvm_channel_protocol,
+				       request_payload_offset),
+			      &payload_offset, sizeof(payload_offset)) < 0) {
+		POSTCODE_LINUX_2(CONTROLVM_INIT_FAILURE_PC,
+				 POSTCODE_SEVERITY_ERR);
+		return;
+	}
+	if (visorchannel_read(controlvm_channel,
+			      offsetof(struct spar_controlvm_channel_protocol,
+				       request_payload_bytes),
+			      &payload_bytes, sizeof(payload_bytes)) < 0) {
+		POSTCODE_LINUX_2(CONTROLVM_INIT_FAILURE_PC,
+				 POSTCODE_SEVERITY_ERR);
+		return;
+	}
+	initialize_controlvm_payload_info(phys_addr,
+					  payload_offset, payload_bytes,
+					  &controlvm_payload_info);
+}
+
+/*  Send ACTION=online for DEVPATH=/sys/devices/platform/visorchipset.
+ *  Returns CONTROLVM_RESP_xxx code.
+ */
+static int
+visorchipset_chipset_ready(void)
+{
+	kobject_uevent(&visorchipset_platform_device.dev.kobj, KOBJ_ONLINE);
+	return CONTROLVM_RESP_SUCCESS;
+}
+
+static 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;
+}
+
+/*  Send ACTION=offline for DEVPATH=/sys/devices/platform/visorchipset.
+ *  Returns CONTROLVM_RESP_xxx code.
+ */
+static int
+visorchipset_chipset_notready(void)
+{
+	kobject_uevent(&visorchipset_platform_device.dev.kobj, KOBJ_OFFLINE);
+	return CONTROLVM_RESP_SUCCESS;
+}
+
+static void
+chipset_ready(struct controlvm_message_header *msg_hdr)
+{
+	int rc = visorchipset_chipset_ready();
+
+	if (rc != CONTROLVM_RESP_SUCCESS)
+		rc = -rc;
+	if (msg_hdr->flags.response_expected)
+		controlvm_respond(msg_hdr, rc);
+}
+
+static void
+chipset_selftest(struct controlvm_message_header *msg_hdr)
+{
+	int rc = visorchipset_chipset_selftest();
+
+	if (rc != CONTROLVM_RESP_SUCCESS)
+		rc = -rc;
+	if (msg_hdr->flags.response_expected)
+		controlvm_respond(msg_hdr, rc);
+}
+
+static void
+chipset_notready(struct controlvm_message_header *msg_hdr)
+{
+	int rc = visorchipset_chipset_notready();
+
+	if (rc != CONTROLVM_RESP_SUCCESS)
+		rc = -rc;
+	if (msg_hdr->flags.response_expected)
+		controlvm_respond(msg_hdr, 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(struct controlvm_message *msg)
+{
+	if (visorchannel_signalremove(controlvm_channel,
+				      CONTROLVM_QUEUE_EVENT, msg)) {
+		/* got a message */
+		if (msg->hdr.flags.test_message == 1)
+			return false;
+		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 + msecs_to_jiffies(PARAHOTPLUG_TIMEOUT_MS);
+}
+
+/*
+ * 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(struct controlvm_message *msg)
+{
+	struct parahotplug_request *req;
+
+	req = kmalloc(sizeof(*req), GFP_KERNEL | __GFP_NORETRY);
+	if (!req)
+		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)
+{
+	struct 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->device_change_state.state.active);
+	sprintf(env_bus, "SPAR_PARAHOTPLUG_BUS=%d",
+		cmd->device_change_state.bus_no);
+	sprintf(env_dev, "SPAR_PARAHOTPLUG_DEVICE=%d",
+		cmd->device_change_state.dev_no >> 3);
+	sprintf(env_func, "SPAR_PARAHOTPLUG_FUNCTION=%d",
+		cmd->device_change_state.dev_no & 0x7);
+
+	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;
+	struct list_head *tmp;
+
+	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))
+			continue;
+
+		list_del(pos);
+		if (req->msg.hdr.flags.response_expected)
+			controlvm_respond_physdev_changestate(
+				&req->msg.hdr,
+				CONTROLVM_RESP_ERROR_DEVICE_UDEV_TIMEOUT,
+				req->msg.cmd.device_change_state.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;
+	struct list_head *tmp;
+
+	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.device_change_state.state.active = active;
+			if (req->msg.hdr.flags.response_expected)
+				controlvm_respond_physdev_changestate(
+					&req->msg.hdr, CONTROLVM_RESP_SUCCESS,
+					req->msg.cmd.device_change_state.state);
+			parahotplug_request_destroy(req);
+			return 0;
+		}
+	}
+
+	spin_unlock(&parahotplug_request_list_lock);
+	return -EINVAL;
+}
+
+/*
+ * Enables or disables a PCI device by kicking off a udev script
+ */
+static void
+parahotplug_process_message(struct controlvm_message *inmsg)
+{
+	struct parahotplug_request *req;
+
+	req = parahotplug_request_create(inmsg);
+
+	if (!req)
+		return;
+
+	if (inmsg->cmd.device_change_state.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.device_change_state.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);
+	}
+}
+
+/* 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(struct controlvm_message inmsg, u64 channel_addr)
+{
+	struct controlvm_message_packet *cmd = &inmsg.cmd;
+	u64 parm_addr;
+	u32 parm_bytes;
+	struct parser_context *parser_ctx = NULL;
+	bool local_addr;
+	struct controlvm_message ackmsg;
+
+	/* create parsing context if necessary */
+	local_addr = (inmsg.hdr.flags.test_message == 1);
+	if (channel_addr == 0)
+		return true;
+	parm_addr = channel_addr + inmsg.hdr.payload_vm_offset;
+	parm_bytes = inmsg.hdr.payload_bytes;
+
+	/* 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 (parm_addr && parm_bytes) {
+		bool retry = false;
+
+		parser_ctx =
+		    parser_init_byte_stream(parm_addr, parm_bytes,
+					    local_addr, &retry);
+		if (!parser_ctx && retry)
+			return false;
+	}
+
+	if (!local_addr) {
+		controlvm_init_response(&ackmsg, &inmsg.hdr,
+					CONTROLVM_RESP_SUCCESS);
+		if (controlvm_channel)
+			visorchannel_signalinsert(controlvm_channel,
+						  CONTROLVM_QUEUE_ACK,
+						  &ackmsg);
+	}
+	switch (inmsg.hdr.id) {
+	case CONTROLVM_CHIPSET_INIT:
+		chipset_init(&inmsg);
+		break;
+	case CONTROLVM_BUS_CREATE:
+		bus_create(&inmsg);
+		break;
+	case CONTROLVM_BUS_DESTROY:
+		bus_destroy(&inmsg);
+		break;
+	case CONTROLVM_BUS_CONFIGURE:
+		bus_configure(&inmsg, parser_ctx);
+		break;
+	case CONTROLVM_DEVICE_CREATE:
+		my_device_create(&inmsg);
+		break;
+	case CONTROLVM_DEVICE_CHANGESTATE:
+		if (cmd->device_change_state.flags.phys_device) {
+			parahotplug_process_message(&inmsg);
+		} else {
+			/* save the hdr and cmd structures for later use */
+			/* when sending back the response to Command */
+			my_device_changestate(&inmsg);
+			g_devicechangestate_packet = inmsg.cmd;
+			break;
+		}
+		break;
+	case CONTROLVM_DEVICE_DESTROY:
+		my_device_destroy(&inmsg);
+		break;
+	case CONTROLVM_DEVICE_CONFIGURE:
+		/* no op for now, just send a respond that we passed */
+		if (inmsg.hdr.flags.response_expected)
+			controlvm_respond(&inmsg.hdr, CONTROLVM_RESP_SUCCESS);
+		break;
+	case CONTROLVM_CHIPSET_READY:
+		chipset_ready(&inmsg.hdr);
+		break;
+	case CONTROLVM_CHIPSET_SELFTEST:
+		chipset_selftest(&inmsg.hdr);
+		break;
+	case CONTROLVM_CHIPSET_STOP:
+		chipset_notready(&inmsg.hdr);
+		break;
+	default:
+		if (inmsg.hdr.flags.response_expected)
+			controlvm_respond
+				(&inmsg.hdr,
+				 -CONTROLVM_RESP_ERROR_MESSAGE_ID_UNKNOWN);
+		break;
+	}
+
+	if (parser_ctx) {
+		parser_done(parser_ctx);
+		parser_ctx = NULL;
+	}
+	return true;
+}
+
+static inline unsigned int
+issue_vmcall_io_controlvm_addr(u64 *control_addr, u32 *control_bytes)
+{
+	struct 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)) {
+		*control_addr = params.address;
+		*control_bytes = params.channel_bytes;
+	}
+	return result;
+}
+
+static u64 controlvm_get_channel_address(void)
+{
+	u64 addr = 0;
+	u32 size = 0;
+
+	if (!VMCALL_SUCCESSFUL(issue_vmcall_io_controlvm_addr(&addr, &size)))
+		return 0;
+
+	return addr;
+}
+
+static void
+controlvm_periodic_work(struct work_struct *work)
+{
+	struct controlvm_message inmsg;
+	bool got_command = false;
+	bool handle_command_failed = false;
+
+	/* make sure visorbus server is registered for controlvm callbacks */
+	if (visorchipset_visorbusregwait && !visorbusregistered)
+		goto cleanup;
+
+	while (visorchannel_signalremove(controlvm_channel,
+					 CONTROLVM_QUEUE_RESPONSE,
+					 &inmsg))
+		;
+	if (!got_command) {
+		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;
+			got_command = true;
+		} else {
+			got_command = read_controlvm_event(&inmsg);
+		}
+	}
+
+	handle_command_failed = false;
+	while (got_command && (!handle_command_failed)) {
+		most_recent_message_jiffies = jiffies;
+		if (handle_command(inmsg,
+				   visorchannel_get_physaddr
+				   (controlvm_channel)))
+			got_command = 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;
+		}
+	}
+
+	/* parahotplug_worker */
+	parahotplug_process_list();
+
+cleanup:
+
+	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)
+			poll_jiffies = POLLJIFFIES_CONTROLVMCHANNEL_SLOW;
+	} else {
+		if (poll_jiffies != POLLJIFFIES_CONTROLVMCHANNEL_FAST)
+			poll_jiffies = POLLJIFFIES_CONTROLVMCHANNEL_FAST;
+	}
+
+	schedule_delayed_work(&periodic_controlvm_work, poll_jiffies);
+}
+
+static void
+setup_crash_devices_work_queue(struct work_struct *work)
+{
+	struct controlvm_message local_crash_bus_msg;
+	struct controlvm_message local_crash_dev_msg;
+	struct controlvm_message msg;
+	u32 local_crash_msg_offset;
+	u16 local_crash_msg_count;
+
+	/* make sure visorbus is registered for controlvm callbacks */
+	if (visorchipset_visorbusregwait && !visorbusregistered) {
+		poll_jiffies = POLLJIFFIES_CONTROLVMCHANNEL_SLOW;
+		schedule_delayed_work(&periodic_controlvm_work, poll_jiffies);
+		return;
+	}
+
+	POSTCODE_LINUX_2(CRASH_DEV_ENTRY_PC, POSTCODE_SEVERITY_INFO);
+
+	/* send init chipset msg */
+	msg.hdr.id = CONTROLVM_CHIPSET_INIT;
+	msg.cmd.init_chipset.bus_count = 23;
+	msg.cmd.init_chipset.switch_count = 0;
+
+	chipset_init(&msg);
+
+	/* get saved message count */
+	if (visorchannel_read(controlvm_channel,
+			      offsetof(struct spar_controlvm_channel_protocol,
+				       saved_crash_message_count),
+			      &local_crash_msg_count, sizeof(u16)) < 0) {
+		POSTCODE_LINUX_2(CRASH_DEV_CTRL_RD_FAILURE_PC,
+				 POSTCODE_SEVERITY_ERR);
+		return;
+	}
+
+	if (local_crash_msg_count != CONTROLVM_CRASHMSG_MAX) {
+		POSTCODE_LINUX_3(CRASH_DEV_COUNT_FAILURE_PC,
+				 local_crash_msg_count,
+				 POSTCODE_SEVERITY_ERR);
+		return;
+	}
+
+	/* get saved crash message offset */
+	if (visorchannel_read(controlvm_channel,
+			      offsetof(struct spar_controlvm_channel_protocol,
+				       saved_crash_message_offset),
+			      &local_crash_msg_offset, sizeof(u32)) < 0) {
+		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,
+			      local_crash_msg_offset,
+			      &local_crash_bus_msg,
+			      sizeof(struct controlvm_message)) < 0) {
+		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,
+			      local_crash_msg_offset +
+			      sizeof(struct controlvm_message),
+			      &local_crash_dev_msg,
+			      sizeof(struct controlvm_message)) < 0) {
+		POSTCODE_LINUX_2(CRASH_DEV_RD_DEV_FAIULRE_PC,
+				 POSTCODE_SEVERITY_ERR);
+		return;
+	}
+
+	/* reuse IOVM create bus message */
+	if (local_crash_bus_msg.cmd.create_bus.channel_addr) {
+		bus_create(&local_crash_bus_msg);
+	} else {
+		POSTCODE_LINUX_2(CRASH_DEV_BUS_NULL_FAILURE_PC,
+				 POSTCODE_SEVERITY_ERR);
+		return;
+	}
+
+	/* reuse create device message for storage device */
+	if (local_crash_dev_msg.cmd.create_device.channel_addr) {
+		my_device_create(&local_crash_dev_msg);
+	} else {
+		POSTCODE_LINUX_2(CRASH_DEV_DEV_NULL_FAILURE_PC,
+				 POSTCODE_SEVERITY_ERR);
+		return;
+	}
+	POSTCODE_LINUX_2(CRASH_DEV_EXIT_PC, POSTCODE_SEVERITY_INFO);
+}
+
+static void
+bus_create_response(struct visor_device *bus_info, int response)
+{
+	if (response >= 0)
+		bus_info->state.created = 1;
+
+	bus_responder(CONTROLVM_BUS_CREATE, bus_info->pending_msg_hdr,
+		      response);
+
+	kfree(bus_info->pending_msg_hdr);
+	bus_info->pending_msg_hdr = NULL;
+}
+
+static void
+bus_destroy_response(struct visor_device *bus_info, int response)
+{
+	bus_responder(CONTROLVM_BUS_DESTROY, bus_info->pending_msg_hdr,
+		      response);
+
+	kfree(bus_info->pending_msg_hdr);
+	bus_info->pending_msg_hdr = NULL;
+}
+
+static void
+device_create_response(struct visor_device *dev_info, int response)
+{
+	if (response >= 0)
+		dev_info->state.created = 1;
+
+	device_responder(CONTROLVM_DEVICE_CREATE, dev_info->pending_msg_hdr,
+			 response);
+
+	kfree(dev_info->pending_msg_hdr);
+	dev_info->pending_msg_hdr = NULL;
+}
+
+static void
+device_destroy_response(struct visor_device *dev_info, int response)
+{
+	device_responder(CONTROLVM_DEVICE_DESTROY, dev_info->pending_msg_hdr,
+			 response);
+
+	kfree(dev_info->pending_msg_hdr);
+	dev_info->pending_msg_hdr = NULL;
+}
+
+static void
+visorchipset_device_pause_response(struct visor_device *dev_info,
+				   int response)
+{
+	device_changestate_responder(CONTROLVM_DEVICE_CHANGESTATE,
+				     dev_info, response,
+				     segment_state_standby);
+
+	kfree(dev_info->pending_msg_hdr);
+	dev_info->pending_msg_hdr = NULL;
+}
+
+static void
+device_resume_response(struct visor_device *dev_info, int response)
+{
+	device_changestate_responder(CONTROLVM_DEVICE_CHANGESTATE,
+				     dev_info, response,
+				     segment_state_running);
+
+	kfree(dev_info->pending_msg_hdr);
+	dev_info->pending_msg_hdr = NULL;
+}
+
+/* The parahotplug/devicedisabled interface gets called by our support script
+ * when an SR-IOV device has been shut down. The ID is passed to the script
+ * and then passed back when the device has been removed.
+ */
+static ssize_t devicedisabled_store(struct device *dev,
+				    struct device_attribute *attr,
+				    const char *buf, size_t count)
+{
+	unsigned int id;
+
+	if (kstrtouint(buf, 10, &id))
+		return -EINVAL;
+
+	parahotplug_request_complete(id, 0);
+	return count;
+}
+
+/* The parahotplug/deviceenabled interface gets called by our support script
+ * when an SR-IOV device has been recovered. The ID is passed to the script
+ * and then passed back when the device has been brought back up.
+ */
+static ssize_t deviceenabled_store(struct device *dev,
+				   struct device_attribute *attr,
+				   const char *buf, size_t count)
+{
+	unsigned int id;
+
+	if (kstrtouint(buf, 10, &id))
+		return -EINVAL;
+
+	parahotplug_request_complete(id, 1);
+	return count;
+}
+
+static int
+visorchipset_mmap(struct file *file, struct vm_area_struct *vma)
+{
+	unsigned long physaddr = 0;
+	unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
+	u64 addr = 0;
+
+	/* sv_enable_dfp(); */
+	if (offset & (PAGE_SIZE - 1))
+		return -ENXIO;	/* need aligned offsets */
+
+	switch (offset) {
+	case VISORCHIPSET_MMAP_CONTROLCHANOFFSET:
+		vma->vm_flags |= VM_IO;
+		if (!*file_controlvm_channel)
+			return -ENXIO;
+
+		visorchannel_read
+			(*file_controlvm_channel,
+			 offsetof(struct spar_controlvm_channel_protocol,
+				  gp_control_channel),
+			 &addr, sizeof(addr));
+		if (!addr)
+			return -ENXIO;
+
+		physaddr = (unsigned long)addr;
+		if (remap_pfn_range(vma, vma->vm_start,
+				    physaddr >> PAGE_SHIFT,
+				    vma->vm_end - vma->vm_start,
+				    /*pgprot_noncached */
+				    (vma->vm_page_prot))) {
+			return -EAGAIN;
+		}
+		break;
+	default:
+		return -ENXIO;
+	}
+	return 0;
+}
+
+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 int issue_vmcall_update_physical_time(u64 adjustment)
+{
+	int result = VMCALL_SUCCESS;
+
+	ISSUE_IO_VMCALL(VMCALL_UPDATE_PHYSICAL_TIME, adjustment, result);
+	return result;
+}
+
+static long visorchipset_ioctl(struct file *file, unsigned int cmd,
+			       unsigned long arg)
+{
+	u64 adjustment;
+	s64 vrtc_offset;
+
+	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))) {
+			return -EFAULT;
+		}
+		return 0;
+	case VMCALL_UPDATE_PHYSICAL_TIME:
+		if (copy_from_user(&adjustment, (void __user *)arg,
+				   sizeof(adjustment))) {
+			return -EFAULT;
+		}
+		return issue_vmcall_update_physical_time(adjustment);
+	default:
+		return -EFAULT;
+	}
+}
+
+static const struct file_operations visorchipset_fops = {
+	.owner = THIS_MODULE,
+	.open = visorchipset_open,
+	.read = NULL,
+	.write = NULL,
+	.unlocked_ioctl = visorchipset_ioctl,
+	.release = visorchipset_release,
+	.mmap = visorchipset_mmap,
+};
+
+static int
+visorchipset_file_init(dev_t major_dev, struct visorchannel **controlvm_channel)
+{
+	int rc = 0;
+
+	file_controlvm_channel = controlvm_channel;
+	cdev_init(&file_cdev, &visorchipset_fops);
+	file_cdev.owner = THIS_MODULE;
+	if (MAJOR(major_dev) == 0) {
+		rc = alloc_chrdev_region(&major_dev, 0, 1, "visorchipset");
+		/* dynamic major device number registration required */
+		if (rc < 0)
+			return rc;
+	} else {
+		/* static major device number registration required */
+		rc = register_chrdev_region(major_dev, 1, "visorchipset");
+		if (rc < 0)
+			return rc;
+	}
+	rc = cdev_add(&file_cdev, MKDEV(MAJOR(major_dev), 0), 1);
+	if (rc < 0) {
+		unregister_chrdev_region(major_dev, 1);
+		return rc;
+	}
+	return 0;
+}
+
+static void
+visorchipset_file_cleanup(dev_t major_dev)
+{
+	if (file_cdev.ops)
+		cdev_del(&file_cdev);
+	file_cdev.ops = NULL;
+	unregister_chrdev_region(major_dev, 1);
+}
+
+static int
+visorchipset_init(struct acpi_device *acpi_device)
+{
+	int err = -ENODEV;
+	u64 addr;
+	uuid_le uuid = SPAR_CONTROLVM_CHANNEL_PROTOCOL_UUID;
+
+	addr = controlvm_get_channel_address();
+	if (!addr)
+		goto error;
+
+	memset(&busdev_notifiers, 0, sizeof(busdev_notifiers));
+	memset(&controlvm_payload_info, 0, sizeof(controlvm_payload_info));
+
+	controlvm_channel = visorchannel_create_with_lock(addr, 0,
+							  GFP_KERNEL, uuid);
+	if (!controlvm_channel)
+		goto error;
+
+	if (SPAR_CONTROLVM_CHANNEL_OK_CLIENT(
+		    visorchannel_get_header(controlvm_channel))) {
+		initialize_controlvm_payload();
+	} else {
+		goto error_destroy_channel;
+	}
+
+	major_dev = MKDEV(visorchipset_major, 0);
+	err = visorchipset_file_init(major_dev, &controlvm_channel);
+	if (err < 0)
+		goto error_destroy_payload;
+
+	/* if booting in a crash kernel */
+	if (is_kdump_kernel())
+		INIT_DELAYED_WORK(&periodic_controlvm_work,
+				  setup_crash_devices_work_queue);
+	else
+		INIT_DELAYED_WORK(&periodic_controlvm_work,
+				  controlvm_periodic_work);
+
+	most_recent_message_jiffies = jiffies;
+	poll_jiffies = POLLJIFFIES_CONTROLVMCHANNEL_FAST;
+	schedule_delayed_work(&periodic_controlvm_work, poll_jiffies);
+
+	visorchipset_platform_device.dev.devt = major_dev;
+	if (platform_device_register(&visorchipset_platform_device) < 0) {
+		POSTCODE_LINUX_2(DEVICE_REGISTER_FAILURE_PC, DIAG_SEVERITY_ERR);
+		err = -ENODEV;
+		goto error_cancel_work;
+	}
+	POSTCODE_LINUX_2(CHIPSET_INIT_SUCCESS_PC, POSTCODE_SEVERITY_INFO);
+
+	err = visorbus_init();
+	if (err < 0)
+		goto error_unregister;
+
+	return 0;
+
+error_unregister:
+	platform_device_unregister(&visorchipset_platform_device);
+
+error_cancel_work:
+	cancel_delayed_work_sync(&periodic_controlvm_work);
+	visorchipset_file_cleanup(major_dev);
+
+error_destroy_payload:
+	destroy_controlvm_payload_info(&controlvm_payload_info);
+
+error_destroy_channel:
+	visorchannel_destroy(controlvm_channel);
+
+error:
+	POSTCODE_LINUX_3(CHIPSET_INIT_FAILURE_PC, err, POSTCODE_SEVERITY_ERR);
+	return err;
+}
+
+static int
+visorchipset_exit(struct acpi_device *acpi_device)
+{
+	POSTCODE_LINUX_2(DRIVER_EXIT_PC, POSTCODE_SEVERITY_INFO);
+
+	visorbus_exit();
+
+	cancel_delayed_work_sync(&periodic_controlvm_work);
+	destroy_controlvm_payload_info(&controlvm_payload_info);
+
+	visorchannel_destroy(controlvm_channel);
+
+	visorchipset_file_cleanup(visorchipset_platform_device.dev.devt);
+	platform_device_unregister(&visorchipset_platform_device);
+	POSTCODE_LINUX_2(DRIVER_EXIT_PC, POSTCODE_SEVERITY_INFO);
+
+	return 0;
+}
+
+static const struct acpi_device_id unisys_device_ids[] = {
+	{"PNP0A07", 0},
+	{"", 0},
+};
+
+static struct acpi_driver unisys_acpi_driver = {
+	.name = "unisys_acpi",
+	.class = "unisys_acpi_class",
+	.owner = THIS_MODULE,
+	.ids = unisys_device_ids,
+	.ops = {
+		.add = visorchipset_init,
+		.remove = visorchipset_exit,
+		},
+};
+
+MODULE_DEVICE_TABLE(acpi, unisys_device_ids);
+
+static __init uint32_t visorutil_spar_detect(void)
+{
+	unsigned int eax, ebx, ecx, edx;
+
+	if (cpu_has_hypervisor) {
+		/* check the ID */
+		cpuid(UNISYS_SPAR_LEAF_ID, &eax, &ebx, &ecx, &edx);
+		return  (ebx == UNISYS_SPAR_ID_EBX) &&
+			(ecx == UNISYS_SPAR_ID_ECX) &&
+			(edx == UNISYS_SPAR_ID_EDX);
+	} else {
+		return 0;
+	}
+}
+
+static int init_unisys(void)
+{
+	int result;
+
+	if (!visorutil_spar_detect())
+		return -ENODEV;
+
+	result = acpi_bus_register_driver(&unisys_acpi_driver);
+	if (result)
+		return -ENODEV;
+
+	pr_info("Unisys Visorchipset Driver Loaded.\n");
+	return 0;
+};
+
+static void exit_unisys(void)
+{
+	acpi_bus_unregister_driver(&unisys_acpi_driver);
+}
+
+module_param_named(major, visorchipset_major, int, S_IRUGO);
+MODULE_PARM_DESC(visorchipset_major,
+		 "major device number to use for the device node");
+module_param_named(visorbusregwait, visorchipset_visorbusregwait, int, S_IRUGO);
+MODULE_PARM_DESC(visorchipset_visorbusregwait,
+		 "1 to have the module wait for the visor bus to register");
+
+module_init(init_unisys);
+module_exit(exit_unisys);
+
+MODULE_AUTHOR("Unisys");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Supervisor chipset driver for service partition: ver "
+		   VERSION);
+MODULE_VERSION(VERSION);
diff --git a/arch/x86/visorbus/vmcallinterface.h b/arch/x86/visorbus/vmcallinterface.h
new file mode 100644
index 0000000..aac7000
--- /dev/null
+++ b/arch/x86/visorbus/vmcallinterface.h
@@ -0,0 +1,91 @@
+/* Copyright (C) 2010 - 2015 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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.
+*/
+
+#include <linux/visorbus/diagchannel.h>
+
+#include "iovmcall_gnuc.h"
+
+#ifdef VMCALL_IO_CONTROLVM_ADDR
+#undef VMCALL_IO_CONTROLVM_ADDR
+#endif	/*  */
+
+/* define subsystem number for AppOS, used in uislib driver  */
+#define MDS_APPOS 0x4000000000000000L	/* subsystem = 62 - AppOS */
+enum vmcall_monitor_interface_method_tuple { /* 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
+	     */
+	/* used by all Guests, not just IO */
+	VMCALL_IO_CONTROLVM_ADDR = 0x0501,
+	/* Allow caller to query virtual time offset */
+	VMCALL_QUERY_GUEST_VIRTUAL_TIME_OFFSET = 0x0708,
+	/* LOGEVENT Post Code (RDX) with specified subsystem mask */
+	/* (RCX - monitor_subsystems.h) and severity (RDX) */
+	VMCALL_POST_CODE_LOGEVENT = 0x070B,
+	/* Allow ULTRA_SERVICE_CAPABILITY_TIME capable guest to make VMCALL */
+	VMCALL_UPDATE_PHYSICAL_TIME = 0x0a02
+};
+
+#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(method, param, result) \
+	(result = unisys_vmcall(method, (param) & 0xFFFFFFFF,	\
+				(param) >> 32))
+#define ISSUE_IO_EXTENDED_VMCALL(method, param1, param2, param3) \
+	unisys_extended_vmcall(method, 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)		\
+	ISSUE_IO_EXTENDED_VMCALL(VMCALL_POST_CODE_LOGEVENT, severity,	\
+				 MDS_APPOS, postcode)
+#endif
+
+/* Structures for IO VMCALLs */
+
+/* Parameters to VMCALL_IO_CONTROLVM_ADDR interface */
+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 address;	/* contents provided by this VMCALL (OUT) */
+	/* the size of the ControlVm channel in bytes This VMCall fills this */
+	/* in with the appropriate address. */
+	u32 channel_bytes;	/* contents provided by this VMCALL (OUT) */
+	u8 unused[4];		/* Unused Bytes in the 64-Bit Aligned Struct */
+} __packed;
+
+#endif /* __IOMONINTF_H__ */
diff --git a/drivers/staging/unisys/Kconfig b/drivers/staging/unisys/Kconfig
index 4f1f5e6..688b5e3 100644
--- a/drivers/staging/unisys/Kconfig
+++ b/drivers/staging/unisys/Kconfig
@@ -11,7 +11,6 @@ menuconfig UNISYSSPAR
 
 if UNISYSSPAR
 
-source "drivers/staging/unisys/visorbus/Kconfig"
 source "drivers/staging/unisys/visornic/Kconfig"
 source "drivers/staging/unisys/visorinput/Kconfig"
 source "drivers/staging/unisys/visorhba/Kconfig"
diff --git a/drivers/staging/unisys/Makefile b/drivers/staging/unisys/Makefile
index 20eb098..e45f44b 100644
--- a/drivers/staging/unisys/Makefile
+++ b/drivers/staging/unisys/Makefile
@@ -1,7 +1,6 @@
 #
 # Makefile for Unisys SPAR drivers
 #
-obj-$(CONFIG_UNISYS_VISORBUS)		+= visorbus/
 obj-$(CONFIG_UNISYS_VISORNIC)		+= visornic/
 obj-$(CONFIG_UNISYS_VISORINPUT)		+= visorinput/
 obj-$(CONFIG_UNISYS_VISORHBA)		+= visorhba/
diff --git a/drivers/staging/unisys/visorbus/Kconfig b/drivers/staging/unisys/visorbus/Kconfig
deleted file mode 100644
index 5113880..0000000
--- a/drivers/staging/unisys/visorbus/Kconfig
+++ /dev/null
@@ -1,14 +0,0 @@
-#
-# Unisys visorbus configuration
-#
-
-config UNISYS_VISORBUS
-	tristate "Unisys visorbus driver"
-	depends on UNISYSSPAR
-	---help---
-	The visorbus driver is a virtualized bus for the Unisys s-Par firmware.
-	Virtualized devices allow Linux guests on a system to share disks and
-	network cards that do not have SR-IOV support, and to be accessed using
-	the partition desktop application. The visorbus driver is required to
-	discover devices on an s-Par guest, and must be present for any other
-	s-Par guest driver to function correctly.
diff --git a/drivers/staging/unisys/visorbus/Makefile b/drivers/staging/unisys/visorbus/Makefile
deleted file mode 100644
index fc790e7..0000000
--- a/drivers/staging/unisys/visorbus/Makefile
+++ /dev/null
@@ -1,12 +0,0 @@
-#
-# Makefile for Unisys visorbus
-#
-
-obj-$(CONFIG_UNISYS_VISORBUS)	+= visorbus.o
-
-visorbus-y := visorbus_main.o
-visorbus-y += visorchannel.o
-visorbus-y += visorchipset.o
-visorbus-y += periodic_work.o
-
-ccflags-y += -Idrivers/staging/unisys/include
diff --git a/drivers/staging/unisys/visorbus/controlvmchannel.h b/drivers/staging/unisys/visorbus/controlvmchannel.h
deleted file mode 100644
index 0a0e221..0000000
--- a/drivers/staging/unisys/visorbus/controlvmchannel.h
+++ /dev/null
@@ -1,485 +0,0 @@
-/* Copyright (C) 2010 - 2015 UNISYS CORPORATION
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope 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 <linux/uuid.h>
-#include <linux/visorbus/channel.h>
-
-/* {2B3C2D10-7EF5-4ad8-B966-3448B7386B3D} */
-#define SPAR_CONTROLVM_CHANNEL_PROTOCOL_UUID	\
-		UUID_LE(0x2b3c2d10, 0x7ef5, 0x4ad8, \
-			0xb9, 0x66, 0x34, 0x48, 0xb7, 0x38, 0x6b, 0x3d)
-
-#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 SPAR_CONTROLVM_CHANNEL_OK_CLIENT(ch)           \
-	spar_check_channel_client(ch, \
-		SPAR_CONTROLVM_CHANNEL_PROTOCOL_UUID, \
-		"controlvm", \
-		sizeof(struct spar_controlvm_channel_protocol), \
-		ULTRA_CONTROLVM_CHANNEL_PROTOCOL_VERSIONID, \
-		ULTRA_CONTROLVM_CHANNEL_PROTOCOL_SIGNATURE)
-
-#define MAX_SERIAL_NUM	32
-
-/* 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 num of messages stored during IOVM creation to be reused after crash */
-#define CONTROLVM_CRASHMSG_MAX		2
-
-struct spar_segment_state  {
-	/* Bit 0: May enter other states */
-	u16 enabled:1;
-	/* Bit 1: Assigned to active partition */
-	u16 active:1;
-	/* Bit 2: Configure message sent to service/server */
-	u16 alive:1;
-	/* Bit 3: similar to partition state ShuttingDown */
-	u16 revoked:1;
-	/* Bit 4: memory (device/port number) has been selected by Command */
-	u16 allocated:1;
-	/* Bit 5: has been introduced to the service/guest partition */
-	u16 known:1;
-	/* Bit 6: service/Guest partition has responded to introduction */
-	u16 ready:1;
-	/* Bit 7: resource is configured and operating */
-	u16 operating:1;
-/* Note: don't use high bit unless we need to switch to ushort
- * which is non-compliant
- */
-};
-
-static const struct spar_segment_state segment_state_running = {
-	1, 1, 1, 0, 1, 1, 1, 1
-};
-
-static const struct spar_segment_state segment_state_paused = {
-	1, 1, 1, 0, 1, 1, 1, 0
-};
-
-static const struct spar_segment_state segment_state_standby = {
-	1, 1, 0, 0, 1, 1, 1, 0
-};
-
-/* 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
- */
-enum controlvm_id {
-	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 */
-/* CHIPSET commands */
-	CONTROLVM_CHIPSET_INIT = 0x301,			/* CP --> SP, GP */
-	CONTROLVM_CHIPSET_STOP = 0x302,			/* CP --> SP, GP */
-	CONTROLVM_CHIPSET_READY = 0x304,		/* CP --> SP */
-	CONTROLVM_CHIPSET_SELFTEST = 0x305,		/* CP --> SP */
-
-};
-
-struct irq_info {
-	u64 reserved1;
-
-	 /* 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
-	  *   interrupt.  Used by IOPart-GP only.
-	  */
-	u64 recv_irq_handle;
-
-	 /* specifies interrupt vector. It, interrupt pin, and shared are
-	  *   used to connect to the corresponding interrupt.  Used by
-	  *   IOPart-GP only.
-	  */
-	u32 recv_irq_vector;
-
-    /* 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 recv_irq_shared;
-	u8 reserved[3];	/* Natural alignment purposes */
-};
-
-struct pci_id {
-	u16 domain;
-	u8 bus;
-	u8 slot;
-	u8 func;
-	u8 reserved[3];	/* Natural alignment purposes */
-};
-
-struct efi_spar_indication  {
-	u64 boot_to_fw_ui:1;		/* Bit 0: Stop in uefi ui */
-	u64 clear_nvram:1;		/* Bit 1: Clear NVRAM */
-	u64 clear_cmos:1;		/* Bit 2: Clear CMOS */
-	u64 boot_to_tool:1;		/* Bit 3: Run install tool */
-	/* remaining bits are available */
-};
-
-enum ultra_chipset_feature {
-	ULTRA_CHIPSET_FEATURE_REPLY = 0x00000001,
-	ULTRA_CHIPSET_FEATURE_PARA_HOTPLUG = 0x00000002,
-};
-
-/* 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.
- */
-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. */
-
-	/* Includes size of this struct + size of message */
-	u32 message_size;
-	/* Index of segment containing Vm message/information */
-	u32 segment_index;
-	/* Error status code or result of  message completion */
-	u32 completion_status;
-	struct  {
-		/* =1 in a response to signify failure */
-		u32 failed:1;
-		/* =1 in all messages that expect a response */
-		u32 response_expected:1;
-		/* =1 in all bus & device-related messages where the message
-		 * receiver is to act as the bus or device server
-		 */
-		u32 server:1;
-		/* =1 for testing use only (Control and Command ignore this */
-		u32 test_message:1;
-		/* =1 if there are forthcoming responses/acks associated
-		 * with this message
-		 */
-		u32 partial_completion:1;
-		/* =1 this is to let us know to preserve channel contents */
-		u32 preserve:1;
-		/* =1 the DiagWriter is active in the Diagnostic Partition */
-		u32 writer_in_diag:1;
-	} flags;
-	/* Natural alignment */
-	u32 reserved;
-	/* Identifies the particular message instance */
-	u64 message_handle;
-	/* request instances with the corresponding response instance. */
-	/* Offset of payload area from start of this instance */
-	u64 payload_vm_offset;
-	/* Maximum bytes allocated in payload area of ControlVm segment */
-	u32 payload_max_bytes;
-	/* Actual number of bytes of payload area to copy between IO/Command */
-	u32 payload_bytes;
-	/* if non-zero, there is a payload to copy. */
-};
-
-struct controlvm_packet_device_create  {
-	u32 bus_no;		/* bus # (0..n-1) from the msg receiver's end */
-	u32 dev_no;		/* bus-relative (0..n-1) device number */
-	/* Guest physical address of the channel, which can be dereferenced by
-	 * the receiver of this ControlVm command
-	 */
-	u64 channel_addr;
-	u64 channel_bytes;	/* specifies size of the channel in bytes */
-	uuid_le data_type_uuid;	/* specifies format of data in channel */
-	uuid_le dev_inst_uuid;	/* instance guid for the device */
-	struct irq_info intr;	/* specifies interrupt information */
-};	/* for CONTROLVM_DEVICE_CREATE */
-
-struct controlvm_packet_device_configure  {
-	/* bus # (0..n-1) from the msg receiver's perspective */
-	u32 bus_no;
-	/* Control uses header SegmentIndex field to access bus number... */
-	u32 dev_no;	      /* bus-relative (0..n-1) device number */
-} ;	/* for CONTROLVM_DEVICE_CONFIGURE */
-
-struct controlvm_message_device_create {
-	struct controlvm_message_header header;
-	struct controlvm_packet_device_create packet;
-};	/* total 128 bytes */
-
-struct controlvm_message_device_configure  {
-	struct controlvm_message_header header;
-	struct controlvm_packet_device_configure packet;
-};	/* total 56 bytes */
-
-/* This is the format for a message in any ControlVm queue. */
-struct controlvm_message_packet  {
-	union  {
-		struct  {
-	/* bus # (0..n-1) from the msg receiver's perspective */
-			u32 bus_no;
-	/* indicates the max number of devices on this bus */
-			u32 dev_count;
-	/* Guest physical address of the channel, which can be
-	 * dereferenced by the receiver of this ControlVm command
-	 */
-			u64 channel_addr;
-			u64 channel_bytes;	/* size of the channel */
-	/* indicates format of data in bus channel*/
-			uuid_le bus_data_type_uuid;
-			uuid_le bus_inst_uuid;	/* instance uuid for the bus */
-		} create_bus;	/* for CONTROLVM_BUS_CREATE */
-		struct  {
-	/* bus # (0..n-1) from the msg receiver's perspective */
-			u32 bus_no;
-			u32 reserved;	/* Natural alignment purposes */
-		} destroy_bus;	/* for CONTROLVM_BUS_DESTROY */
-		struct  {
-	/* bus # (0..n-1) from the receiver's perspective */
-			u32 bus_no;
-			u32 reserved1;	/* for alignment purposes */
-	/* This is used to convert guest physical address to physical address */
-			u64 guest_handle;
-			u64 recv_bus_irq_handle;
-				/* 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.
-				 */
-		} configure_bus;	/* for CONTROLVM_BUS_CONFIGURE */
-		/* for CONTROLVM_DEVICE_CREATE */
-		struct controlvm_packet_device_create create_device;
-		struct  {
-		/* bus # (0..n-1) from the msg receiver's perspective */
-			u32 bus_no;
-			u32 dev_no;	/* bus-relative (0..n-1) device # */
-		} destroy_device;	/* for CONTROLVM_DEVICE_DESTROY */
-		/* for CONTROLVM_DEVICE_CONFIGURE */
-		struct controlvm_packet_device_configure configure_device;
-		struct  {
-		/* bus # (0..n-1) from the msg receiver's perspective */
-			u32 bus_no;
-			u32 dev_no;	/* bus-relative (0..n-1) device # */
-		} reconfigure_device;	/* for CONTROLVM_DEVICE_RECONFIGURE */
-		struct  {
-			u32 bus_no;
-			struct spar_segment_state state;
-			u8 reserved[2];	/* Natural alignment purposes */
-		} bus_change_state;	/* for CONTROLVM_BUS_CHANGESTATE */
-		struct  {
-			u32 bus_no;
-			u32 dev_no;
-			struct spar_segment_state state;
-			struct  {
-				/* =1 if message is for a physical device */
-				u32 phys_device:1;
-			} flags;
-			u8 reserved[2];	/* Natural alignment purposes */
-		} device_change_state;	/* for CONTROLVM_DEVICE_CHANGESTATE */
-		struct  {
-			u32 bus_no;
-			u32 dev_no;
-			struct spar_segment_state state;
-			u8 reserved[6];	/* Natural alignment purposes */
-		} device_change_state_event;
-			/* for CONTROLVM_DEVICE_CHANGESTATE_EVENT */
-		struct  {
-			/* indicates the max number of busses */
-			u32 bus_count;
-			/* indicates the max number of switches */
-			u32 switch_count;
-			enum ultra_chipset_feature features;
-			u32 platform_number;	/* Platform Number */
-		} init_chipset;	/* for CONTROLVM_CHIPSET_INIT */
-		struct  {
-			u32 options;	/* reserved */
-			u32 test;	/* bit 0 set to run embedded selftest */
-		} chipset_selftest;	/* for CONTROLVM_CHIPSET_SELFTEST */
-		/* a physical address of something, that can be dereferenced
-		 * by the receiver of this ControlVm command
-		 */
-		u64 addr;
-		/* a handle of something (depends on command id) */
-		u64 handle;
-	};
-};
-
-/* All messages in any ControlVm queue have this layout. */
-struct controlvm_message {
-	struct controlvm_message_header hdr;
-	struct controlvm_message_packet cmd;
-};
-
-struct spar_controlvm_channel_protocol {
-	struct channel_header header;
-	u64 gp_controlvm;	/* guest phys addr of this channel */
-	u64 gp_partition_tables;/* guest phys addr of partition tables */
-	u64 gp_diag_guest;	/* guest phys addr of diagnostic channel */
-	u64 gp_boot_romdisk;/* guest phys addr of (read* only) Boot ROM disk */
-	u64 gp_boot_ramdisk;/* guest phys addr of writable Boot RAM disk */
-	u64 gp_acpi_table;	/* guest phys addr of acpi table */
-	u64 gp_control_channel;/* guest phys addr of control channel */
-	u64 gp_diag_romdisk;/* guest phys addr of diagnostic ROM disk */
-	u64 gp_nvram;	/* guest phys addr of NVRAM channel */
-	u64 request_payload_offset;	/* Offset to request payload area */
-	u64 event_payload_offset;	/* Offset to event payload area */
-	/* Bytes available in request payload area */
-	u32 request_payload_bytes;
-	u32 event_payload_bytes;/* Bytes available in event payload area */
-	u32 control_channel_bytes;
-	u32 nvram_channel_bytes;	/* Bytes in PartitionNvram segment */
-	u32 message_bytes;		/* sizeof(CONTROLVM_MESSAGE) */
-	u32 message_count;		/* CONTROLVM_MESSAGE_MAX */
-	u64 gp_smbios_table;		/* guest phys addr of SMBIOS tables */
-	u64 gp_physical_smbios_table;	/* guest phys addr of SMBIOS table  */
-	/* ULTRA_MAX_GUESTS_PER_SERVICE */
-	char gp_reserved[2688];
-
-	/* guest physical address of EFI firmware image base  */
-	u64 virtual_guest_firmware_image_base;
-
-	/* guest physical address of EFI firmware entry point  */
-	u64 virtual_guest_firmware_entry_point;
-
-	/* guest EFI firmware image size  */
-	u64 virtual_guest_firmware_image_size;
-
-	/* GPA = 1MB where EFI firmware image is copied to  */
-	u64 virtual_guest_firmware_boot_base;
-	u64 virtual_guest_image_base;
-	u64 virtual_guest_image_size;
-	u64 prototype_control_channel_offset;
-	u64 virtual_guest_partition_handle;
-	/* Restore Action field to restore the guest partition */
-	u16 restore_action;
-	/* For Windows guests it shows if the visordisk is in dump mode */
-	u16 dump_action;
-	u16 nvram_fail_count;
-	u16 saved_crash_message_count;	/* = CONTROLVM_CRASHMSG_MAX */
-	/* Offset to request payload area needed for crash dump */
-	u32 saved_crash_message_offset;
-	/* Type of error encountered during installation */
-	u32 installation_error;
-	u32 installation_text_id;	/* Id of string to display */
-	/* Number of remaining installation  steps (for progress bars) */
-	u16 installation_remaining_steps;
-	/* ULTRA_TOOL_ACTIONS Installation Action field */
-	u8 tool_action;
-	u8 reserved;		/* alignment */
-	struct efi_spar_indication efi_spar_ind;
-	struct efi_spar_indication efi_spar_ind_supported;
-	u32 sp_reserved;
-	/* Force signals to begin on 128-byte cache line */
-	u8 reserved2[28];
-	/* guest partition uses this queue to send requests to Control */
-	struct signal_queue_header request_queue;
-	/* Control uses this queue to respond to service or guest
-	 * partition requests
-	 */
-	struct signal_queue_header response_queue;
-	/* Control uses this queue to send events to guest partition */
-	struct signal_queue_header event_queue;
-	/* Service or guest partition  uses this queue to ack Control events */
-	struct signal_queue_header event_ack_queue;
-	 /* Request fixed-size message pool - does not include payload */
-	 struct controlvm_message request_msg[CONTROLVM_MESSAGE_MAX];
-
-	 /* Response fixed-size message pool - does not include payload */
-	 struct controlvm_message response_msg[CONTROLVM_MESSAGE_MAX];
-
-	 /* Event fixed-size message pool - does not include payload */
-	 struct controlvm_message event_msg[CONTROLVM_MESSAGE_MAX];
-
-	 /* Ack fixed-size message pool - does not include payload */
-	 struct controlvm_message event_ack_msg[CONTROLVM_MESSAGE_MAX];
-
-	 /* Message stored during IOVM creation to be reused after crash */
-	 struct controlvm_message saved_crash_msg[CONTROLVM_CRASHMSG_MAX];
-};
-
-/* Offsets for VM channel attributes */
-#define VM_CH_REQ_QUEUE_OFFSET \
-	offsetof(struct spar_controlvm_channel_protocol, request_queue)
-#define VM_CH_RESP_QUEUE_OFFSET \
-	offsetof(struct spar_controlvm_channel_protocol, response_queue)
-#define VM_CH_EVENT_QUEUE_OFFSET \
-	offsetof(struct spar_controlvm_channel_protocol, event_queue)
-#define VM_CH_ACK_QUEUE_OFFSET \
-	offsetof(struct spar_controlvm_channel_protocol, event_ack_queue)
-#define VM_CH_REQ_MSG_OFFSET \
-	offsetof(struct spar_controlvm_channel_protocol, request_msg)
-#define VM_CH_RESP_MSG_OFFSET \
-	offsetof(struct spar_controlvm_channel_protocol, response_msg)
-#define VM_CH_EVENT_MSG_OFFSET \
-	offsetof(struct spar_controlvm_channel_protocol, event_msg)
-#define VM_CH_ACK_MSG_OFFSET \
-	offsetof(struct spar_controlvm_channel_protocol, event_ack_msg)
-#define VM_CH_CRASH_MSG_OFFSET \
-	offsetof(struct spar_controlvm_channel_protocol, saved_crash_msg)
-
-/* 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 connection_offset,
- * initiator_offset, and target_offset to get the location of UTF-8 formatted
- * strings that can be parsed to obtain command-specific information. The value
- * of total_length should equal PayloadBytes. The format of the strings at
- * PayloadVmOffset will take different forms depending on the message.
- */
-struct spar_controlvm_parameters_header {
-	u32 total_length;
-	u32 header_length;
-	u32 connection_offset;
-	u32 connection_length;
-	u32 initiator_offset;
-	u32 initiator_length;
-	u32 target_offset;
-	u32 target_length;
-	u32 client_offset;
-	u32 client_length;
-	u32 name_offset;
-	u32 name_length;
-	uuid_le id;
-	u32 revision;
-	u32 reserved;		/* Natural alignment */
-};
-
-#endif				/* __CONTROLVMCHANNEL_H__ */
diff --git a/drivers/staging/unisys/visorbus/controlvmcompletionstatus.h b/drivers/staging/unisys/visorbus/controlvmcompletionstatus.h
deleted file mode 100644
index 23ad0ea..0000000
--- a/drivers/staging/unisys/visorbus/controlvmcompletionstatus.h
+++ /dev/null
@@ -1,101 +0,0 @@
-/* controlvmcompletionstatus.c
- *
- * Copyright (C) 2010 - 2015 UNISYS CORPORATION
- * All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope 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/visorbus/iovmcall_gnuc.h b/drivers/staging/unisys/visorbus/iovmcall_gnuc.h
deleted file mode 100644
index 98ea7f3..0000000
--- a/drivers/staging/unisys/visorbus/iovmcall_gnuc.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/* Copyright (C) 2010 - 2015 UNISYS CORPORATION
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope 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))
-		return -EPERM;
-
-	__asm__ __volatile__(".byte 0x00f, 0x001, 0x0c1" : "=a"(result) :
-		"a"(tuple), "b"(reg_ebx), "c"(reg_ecx));
-	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))
-		return -EPERM;
-
-	__asm__ __volatile__(".byte 0x00f, 0x001, 0x0c1" : "=a"(result) :
-		"a"(tuple), "b"(reg_ebx), "c"(reg_ecx), "d"(reg_edx));
-	return result;
-}
diff --git a/drivers/staging/unisys/visorbus/periodic_work.c b/drivers/staging/unisys/visorbus/periodic_work.c
deleted file mode 100644
index 9b3b150..0000000
--- a/drivers/staging/unisys/visorbus/periodic_work.c
+++ /dev/null
@@ -1,203 +0,0 @@
-/* periodic_work.c
- *
- * Copyright (C) 2010 - 2015 UNISYS CORPORATION
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope 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 <linux/sched.h>
-#include <linux/visorbus/periodic_work.h>
-
-#define MYDRVNAME "periodic_work"
-
-struct periodic_work {
-	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)
-{
-	struct periodic_work *pw;
-
-	pw = container_of(work, struct periodic_work, work.work);
-	(*pw->workfunc)(pw->workfuncarg);
-}
-
-struct periodic_work
-*visor_periodic_work_create(ulong jiffy_interval,
-			    struct workqueue_struct *workqueue,
-			    void (*workfunc)(void *),
-			    void *workfuncarg,
-			    const char *devnam)
-{
-	struct periodic_work *pw;
-
-	pw = kzalloc(sizeof(*pw), GFP_KERNEL | __GFP_NORETRY);
-	if (!pw)
-		return NULL;
-
-	rwlock_init(&pw->lock);
-	pw->jiffy_interval = jiffy_interval;
-	pw->workqueue = workqueue;
-	pw->workfunc = workfunc;
-	pw->workfuncarg = workfuncarg;
-	pw->devnam = devnam;
-	return pw;
-}
-EXPORT_SYMBOL_GPL(visor_periodic_work_create);
-
-void visor_periodic_work_destroy(struct periodic_work *pw)
-{
-	kfree(pw);
-}
-EXPORT_SYMBOL_GPL(visor_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 visor_periodic_work_nextperiod(struct periodic_work *pw)
-{
-	bool rc = false;
-
-	write_lock(&pw->lock);
-	if (pw->want_to_stop) {
-		pw->is_scheduled = false;
-		pw->want_to_stop = false;
-		rc = true;  /* yes, true; see visor_periodic_work_stop() */
-		goto unlock;
-	} else if (!queue_delayed_work(pw->workqueue, &pw->work,
-				       pw->jiffy_interval)) {
-		pw->is_scheduled = false;
-		rc = false;
-		goto unlock;
-	}
-	rc = true;
-unlock:
-	write_unlock(&pw->lock);
-	return rc;
-}
-EXPORT_SYMBOL_GPL(visor_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 visor_periodic_work_start(struct periodic_work *pw)
-{
-	bool rc = false;
-
-	write_lock(&pw->lock);
-	if (pw->is_scheduled) {
-		rc = false;
-		goto unlock;
-	}
-	if (pw->want_to_stop) {
-		rc = false;
-		goto unlock;
-	}
-	INIT_DELAYED_WORK(&pw->work, &periodic_work_func);
-	if (!queue_delayed_work(pw->workqueue, &pw->work,
-				pw->jiffy_interval)) {
-		rc = false;
-		goto unlock;
-	}
-	pw->is_scheduled = true;
-	rc = true;
-unlock:
-	write_unlock(&pw->lock);
-	return rc;
-}
-EXPORT_SYMBOL_GPL(visor_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, visor_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 visor_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 visor_periodic_work_stop(struct periodic_work *pw)
-{
-	bool stopped_something = false;
-
-	write_lock(&pw->lock);
-	stopped_something = pw->is_scheduled && (!pw->want_to_stop);
-	while (pw->is_scheduled) {
-		pw->want_to_stop = true;
-		if (cancel_delayed_work(&pw->work)) {
-			/* We get here if the delayed work was pending as
-			 * delayed work, but was NOT run.
-			 */
-			WARN_ON(!pw->is_scheduled);
-			pw->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 (pw->is_scheduled) {
-			write_unlock(&pw->lock);
-			schedule_timeout_interruptible(msecs_to_jiffies(10));
-			write_lock(&pw->lock);
-		} else {
-			pw->want_to_stop = false;
-		}
-	}
-	write_unlock(&pw->lock);
-	return stopped_something;
-}
-EXPORT_SYMBOL_GPL(visor_periodic_work_stop);
diff --git a/drivers/staging/unisys/visorbus/vbuschannel.h b/drivers/staging/unisys/visorbus/vbuschannel.h
deleted file mode 100644
index 3e0388d..0000000
--- a/drivers/staging/unisys/visorbus/vbuschannel.h
+++ /dev/null
@@ -1,95 +0,0 @@
-/* Copyright (C) 2010 - 2015 UNISYS CORPORATION
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope 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 <linux/uuid.h>
-#include <linux/visorbus/channel.h>
-
-#include "vbusdeviceinfo.h"
-
-/* {193b331b-c58f-11da-95a9-00e08161165f} */
-#define SPAR_VBUS_CHANNEL_PROTOCOL_UUID \
-		UUID_LE(0x193b331b, 0xc58f, 0x11da, \
-				0x95, 0xa9, 0x0, 0xe0, 0x81, 0x61, 0x16, 0x5f)
-static const uuid_le spar_vbus_channel_protocol_uuid =
-	SPAR_VBUS_CHANNEL_PROTOCOL_UUID;
-
-#define SPAR_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 SPAR_VBUS_CHANNEL_PROTOCOL_VERSIONID 1
-
-#define SPAR_VBUS_CHANNEL_OK_CLIENT(ch)       \
-	spar_check_channel_client(ch,				\
-				   spar_vbus_channel_protocol_uuid,	\
-				   "vbus",				\
-				   sizeof(struct spar_vbus_channel_protocol),\
-				   SPAR_VBUS_CHANNEL_PROTOCOL_VERSIONID, \
-				   SPAR_VBUS_CHANNEL_PROTOCOL_SIGNATURE)
-
-#define SPAR_VBUS_CHANNEL_OK_SERVER(actual_bytes)    \
-	(spar_check_channel_server(spar_vbus_channel_protocol_uuid,	\
-				   "vbus",				\
-				   sizeof(struct spar_vbus_channel_protocol),\
-				   actual_bytes))
-
-#pragma pack(push, 1)		/* both GCC and VC now allow this pragma */
-struct spar_vbus_headerinfo {
-	u32 struct_bytes;	/* size of this struct in bytes */
-	u32 device_info_struct_bytes;	/* sizeof(ULTRA_VBUS_DEVICEINFO) */
-	u32 dev_info_count;	/* num of items in DevInfo member */
-	/* (this is the allocated size) */
-	u32 chp_info_offset;	/* byte offset from beginning of this struct */
-	/* to the ChpInfo struct (below) */
-	u32 bus_info_offset;	/* byte offset from beginning of this struct */
-	/* to the BusInfo struct (below) */
-	u32 dev_info_offset;	/* byte offset from beginning of this struct */
-	/* to the DevInfo array (below) */
-	u8 reserved[104];
-};
-
-struct spar_vbus_channel_protocol {
-	struct channel_header channel_header;	/* initialized by server */
-	struct spar_vbus_headerinfo hdr_info;	/* initialized by server */
-	/* the remainder of this channel is filled in by the client */
-	struct ultra_vbus_deviceinfo chp_info;
-	/* describes client chipset device and driver */
-	struct ultra_vbus_deviceinfo bus_info;
-	/* describes client bus device and driver */
-	struct ultra_vbus_deviceinfo dev_info[0];
-	/* describes client device and driver for each device on the bus */
-};
-
-#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)
-
-#pragma pack(pop)
-
-#endif
diff --git a/drivers/staging/unisys/visorbus/vbusdeviceinfo.h b/drivers/staging/unisys/visorbus/vbusdeviceinfo.h
deleted file mode 100644
index abdab4a..0000000
--- a/drivers/staging/unisys/visorbus/vbusdeviceinfo.h
+++ /dev/null
@@ -1,213 +0,0 @@
-/* Copyright (C) 2010 - 2015 UNISYS CORPORATION
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope 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 <linux/types.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.
- */
-struct ultra_vbus_deviceinfo {
-	u8 devtype[16];		/* short string identifying the device type */
-	u8 drvname[16];		/* driver .sys file name */
-	u8 infostrs[96];	/* sequence of tab-delimited id strings: */
-	/* <DRIVER_REV> <DRIVER_VERTAG> <DRIVER_COMPILETIME> */
-	u8 reserved[128];	/* pad size to 256 bytes */
-};
-
-#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) {
-					chars++;
-				}
-				nonprintable_streak = 0;
-			}
-			if (remain > 0) {
-				*p = *src;
-				p++;
-				remain--;
-				chars++;
-			} else if (!p) {
-				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_devinfo_to_string(struct 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->infostrs[0];
-	nsrc = sizeof(devinfo->infostrs);
-	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/visorbus/vbushelper.h b/drivers/staging/unisys/visorbus/vbushelper.h
deleted file mode 100644
index f1b6aac..0000000
--- a/drivers/staging/unisys/visorbus/vbushelper.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/* vbushelper.h
- *
- * Copyright (C) 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__
-
-/* TARGET_HOSTNAME specified as -DTARGET_HOSTNAME=\"thename\" on the
- * command line
- */
-
-#define TARGET_HOSTNAME "linuxguest"
-
-static inline void bus_device_info_init(
-		struct ultra_vbus_deviceinfo *bus_device_info_ptr,
-		const char *dev_type, const char *drv_name,
-		const char *ver, const char *ver_tag)
-{
-	memset(bus_device_info_ptr, 0, sizeof(struct ultra_vbus_deviceinfo));
-	snprintf(bus_device_info_ptr->devtype,
-		 sizeof(bus_device_info_ptr->devtype),
-		 "%s", (dev_type) ? dev_type : "unknownType");
-	snprintf(bus_device_info_ptr->drvname,
-		 sizeof(bus_device_info_ptr->drvname),
-		 "%s", (drv_name) ? drv_name : "unknownDriver");
-	snprintf(bus_device_info_ptr->infostrs,
-		 sizeof(bus_device_info_ptr->infostrs), "%s\t%s\t%s",
-		 (ver) ? ver : "unknownVer",
-		 (ver_tag) ? ver_tag : "unknownVerTag",
-		 TARGET_HOSTNAME);
-}
-
-#endif
diff --git a/drivers/staging/unisys/visorbus/visorbus_main.c b/drivers/staging/unisys/visorbus/visorbus_main.c
deleted file mode 100644
index efd87c6..0000000
--- a/drivers/staging/unisys/visorbus/visorbus_main.c
+++ /dev/null
@@ -1,1344 +0,0 @@
-/* visorbus_main.c
- *
- * Copyright � 2010 - 2015 UNISYS CORPORATION
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope 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/uuid.h>
-
-#include <linux/visorbus/visorbus.h>
-#include <linux/visorbus/version.h>
-#include <linux/visorbus/periodic_work.h>
-#include <linux/visorbus/guestlinuxdebug.h>
-#include "visorbus_private.h"
-#include "vbuschannel.h"
-#include "vmcallinterface.h"
-
-#define MYDRVNAME "visorbus"
-
-/* module parameters */
-static int visorbus_debug;
-static int visorbus_forcematch;
-static int visorbus_forcenomatch;
-static int visorbus_debugref;
-#define SERIALLOOPBACKCHANADDR (100 * 1024 * 1024)
-
-/* Display string that is guaranteed to be no longer the 99 characters*/
-#define LINESIZE 99
-
-#define CURRENT_FILE_PC VISOR_BUS_PC_visorbus_main_c
-#define POLLJIFFIES_TESTWORK         100
-#define POLLJIFFIES_NORMALCHANNEL     10
-
-static int busreg_rc = -ENODEV; /* stores the result from bus registration */
-
-static int visorbus_uevent(struct device *xdev, struct kobj_uevent_env *env);
-static int visorbus_match(struct device *xdev, struct device_driver *xdrv);
-static void fix_vbus_dev_info(struct visor_device *visordev);
-
-/*  BUS type attributes
- *
- *  define & implement display of bus attributes under
- *  /sys/bus/visorbus.
- *
- */
-
-static ssize_t version_show(struct bus_type *bus, char *buf)
-{
-	return snprintf(buf, PAGE_SIZE, "%s\n", VERSION);
-}
-
-static BUS_ATTR_RO(version);
-
-static struct attribute *visorbus_bus_attrs[] = {
-	&bus_attr_version.attr,
-	NULL,
-};
-
-static const struct attribute_group visorbus_bus_group = {
-	.attrs = visorbus_bus_attrs,
-};
-
-static const struct attribute_group *visorbus_bus_groups[] = {
-	&visorbus_bus_group,
-	NULL,
-};
-
-/*
- * DEVICE type attributes
- *
- * The modalias file will contain the guid of the device.
- */
-static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
-			     char *buf)
-{
-	struct visor_device *vdev;
-	uuid_le guid;
-
-	vdev = to_visor_device(dev);
-	guid = visorchannel_get_uuid(vdev->visorchannel);
-	return snprintf(buf, PAGE_SIZE, "visorbus:%pUl\n", &guid);
-}
-static DEVICE_ATTR_RO(modalias);
-
-static struct attribute *visorbus_dev_attrs[] = {
-	&dev_attr_modalias.attr,
-	NULL,
-};
-
-/* sysfs example for bridge-only sysfs files using device_type's */
-static const struct attribute_group visorbus_dev_group = {
-	.attrs = visorbus_dev_attrs,
-};
-
-static const struct attribute_group *visorbus_dev_groups[] = {
-	&visorbus_dev_group,
-	NULL,
-};
-
-/** This describes the TYPE of bus.
- *  (Don't confuse this with an INSTANCE of the bus.)
- */
-struct bus_type visorbus_type = {
-	.name = "visorbus",
-	.match = visorbus_match,
-	.uevent = visorbus_uevent,
-	.dev_groups = visorbus_dev_groups,
-	.bus_groups = visorbus_bus_groups,
-};
-
-static struct delayed_work periodic_work;
-
-/* YES, we need 2 workqueues.
- * The reason is, workitems on the test queue may need to cancel
- * workitems on the other queue.  You will be in for trouble if you try to
- * do this with workitems queued on the same workqueue.
- */
-static struct workqueue_struct *periodic_test_workqueue;
-static struct workqueue_struct *periodic_dev_workqueue;
-static long long bus_count;	/** number of bus instances */
-					/** ever-increasing */
-
-static void chipset_bus_create(struct visor_device *bus_info);
-static void chipset_bus_destroy(struct visor_device *bus_info);
-static void chipset_device_create(struct visor_device *dev_info);
-static void chipset_device_destroy(struct visor_device *dev_info);
-static void chipset_device_pause(struct visor_device *dev_info);
-static void chipset_device_resume(struct visor_device *dev_info);
-
-/** These functions are implemented herein, and are called by the chipset
- *  driver to notify us about specific events.
- */
-static struct visorchipset_busdev_notifiers chipset_notifiers = {
-	.bus_create = chipset_bus_create,
-	.bus_destroy = chipset_bus_destroy,
-	.device_create = chipset_device_create,
-	.device_destroy = chipset_device_destroy,
-	.device_pause = chipset_device_pause,
-	.device_resume = chipset_device_resume,
-};
-
-/** These functions are implemented in the chipset driver, and we call them
- *  herein when we want to acknowledge a specific event.
- */
-static struct visorchipset_busdev_responders chipset_responders;
-
-/* filled in with info about parent chipset driver when we register with it */
-static struct ultra_vbus_deviceinfo chipset_driverinfo;
-/* filled in with info about this driver, wrt it servicing client busses */
-static struct ultra_vbus_deviceinfo clientbus_driverinfo;
-
-/** list of visor_device structs, linked via .list_all */
-static LIST_HEAD(list_all_bus_instances);
-/** list of visor_device structs, linked via .list_all */
-static LIST_HEAD(list_all_device_instances);
-
-static int
-visorbus_uevent(struct device *xdev, struct kobj_uevent_env *env)
-{
-	struct visor_device *dev;
-	uuid_le guid;
-
-	dev = to_visor_device(xdev);
-	guid = visorchannel_get_uuid(dev->visorchannel);
-
-	if (add_uevent_var(env, "MODALIAS=visorbus:%pUl", &guid))
-		return -ENOMEM;
-	return 0;
-}
-
-/* This is called automatically upon adding a visor_device (device_add), or
- * adding a visor_driver (visorbus_register_visor_driver), and returns 1 iff the
- * provided driver can control the specified device.
- */
-static int
-visorbus_match(struct device *xdev, struct device_driver *xdrv)
-{
-	uuid_le channel_type;
-	int i;
-	struct visor_device *dev;
-	struct visor_driver *drv;
-
-	dev = to_visor_device(xdev);
-	drv = to_visor_driver(xdrv);
-	channel_type = visorchannel_get_uuid(dev->visorchannel);
-
-	if (visorbus_forcematch)
-		return 1;
-	if (visorbus_forcenomatch)
-		return 0;
-	if (!drv->channel_types)
-		return 0;
-
-	for (i = 0;
-	     (uuid_le_cmp(drv->channel_types[i].guid, NULL_UUID_LE) != 0) ||
-	     (drv->channel_types[i].name);
-	     i++)
-		if (uuid_le_cmp(drv->channel_types[i].guid,
-				channel_type) == 0)
-			return i + 1;
-
-	return 0;
-}
-
-/** This is called when device_unregister() is called for the bus device
- *  instance, after all other tasks involved with destroying the device
- *  are complete.
- */
-static void
-visorbus_release_busdevice(struct device *xdev)
-{
-	struct visor_device *dev = dev_get_drvdata(xdev);
-
-	kfree(dev);
-}
-
-/** This is called when device_unregister() is called for each child
- *  device instance.
- */
-static void
-visorbus_release_device(struct device *xdev)
-{
-	struct visor_device *dev = to_visor_device(xdev);
-
-	if (dev->periodic_work) {
-		visor_periodic_work_destroy(dev->periodic_work);
-		dev->periodic_work = NULL;
-	}
-	if (dev->visorchannel) {
-		visorchannel_destroy(dev->visorchannel);
-		dev->visorchannel = NULL;
-	}
-	kfree(dev);
-}
-
-/* begin implementation of specific channel attributes to appear under
-* /sys/bus/visorbus<x>/dev<y>/channel
-*/
-static ssize_t physaddr_show(struct device *dev, struct device_attribute *attr,
-			     char *buf)
-{
-	struct visor_device *vdev = to_visor_device(dev);
-
-	if (!vdev->visorchannel)
-		return 0;
-	return snprintf(buf, PAGE_SIZE, "0x%llx\n",
-			visorchannel_get_physaddr(vdev->visorchannel));
-}
-
-static ssize_t nbytes_show(struct device *dev, struct device_attribute *attr,
-			   char *buf)
-{
-	struct visor_device *vdev = to_visor_device(dev);
-
-	if (!vdev->visorchannel)
-		return 0;
-	return snprintf(buf, PAGE_SIZE, "0x%lx\n",
-			visorchannel_get_nbytes(vdev->visorchannel));
-}
-
-static ssize_t clientpartition_show(struct device *dev,
-				    struct device_attribute *attr, char *buf)
-{
-	struct visor_device *vdev = to_visor_device(dev);
-
-	if (!vdev->visorchannel)
-		return 0;
-	return snprintf(buf, PAGE_SIZE, "0x%llx\n",
-			visorchannel_get_clientpartition(vdev->visorchannel));
-}
-
-static ssize_t typeguid_show(struct device *dev, struct device_attribute *attr,
-			     char *buf)
-{
-	struct visor_device *vdev = to_visor_device(dev);
-	char typeid[LINESIZE];
-
-	if (!vdev->visorchannel)
-		return 0;
-	return snprintf(buf, PAGE_SIZE, "%s\n",
-			visorchannel_id(vdev->visorchannel, typeid));
-}
-
-static ssize_t zoneguid_show(struct device *dev, struct device_attribute *attr,
-			     char *buf)
-{
-	struct visor_device *vdev = to_visor_device(dev);
-	char zoneid[LINESIZE];
-
-	if (!vdev->visorchannel)
-		return 0;
-	return snprintf(buf, PAGE_SIZE, "%s\n",
-			visorchannel_zoneid(vdev->visorchannel, zoneid));
-}
-
-static ssize_t typename_show(struct device *dev, struct device_attribute *attr,
-			     char *buf)
-{
-	struct visor_device *vdev = to_visor_device(dev);
-	int i = 0;
-	struct bus_type *xbus = dev->bus;
-	struct device_driver *xdrv = dev->driver;
-	struct visor_driver *drv = NULL;
-
-	if (!vdev->visorchannel || !xbus || !xdrv)
-		return 0;
-	i = xbus->match(dev, xdrv);
-	if (!i)
-		return 0;
-	drv = to_visor_driver(xdrv);
-	return snprintf(buf, PAGE_SIZE, "%s\n", drv->channel_types[i - 1].name);
-}
-
-static DEVICE_ATTR_RO(physaddr);
-static DEVICE_ATTR_RO(nbytes);
-static DEVICE_ATTR_RO(clientpartition);
-static DEVICE_ATTR_RO(typeguid);
-static DEVICE_ATTR_RO(zoneguid);
-static DEVICE_ATTR_RO(typename);
-
-static struct attribute *channel_attrs[] = {
-		&dev_attr_physaddr.attr,
-		&dev_attr_nbytes.attr,
-		&dev_attr_clientpartition.attr,
-		&dev_attr_typeguid.attr,
-		&dev_attr_zoneguid.attr,
-		&dev_attr_typename.attr,
-		NULL
-};
-
-static struct attribute_group channel_attr_grp = {
-		.name = "channel",
-		.attrs = channel_attrs,
-};
-
-static const struct attribute_group *visorbus_channel_groups[] = {
-		&channel_attr_grp,
-		NULL
-};
-
-/* end implementation of specific channel attributes */
-
-/*  BUS instance attributes
- *
- *  define & implement display of bus attributes under
- *  /sys/bus/visorbus/busses/visorbus<n>.
- *
- *  This is a bit hoaky because the kernel does not yet have the infrastructure
- *  to separate bus INSTANCE attributes from bus TYPE attributes...
- *  so we roll our own.  See businst.c / businst.h.
- *
- */
-
-static ssize_t partition_handle_show(struct device *dev,
-				     struct device_attribute *attr,
-				     char *buf) {
-	struct visor_device *vdev = to_visor_device(dev);
-	u64 handle = visorchannel_get_clientpartition(vdev->visorchannel);
-
-	return snprintf(buf, PAGE_SIZE, "0x%llx\n", handle);
-}
-
-static ssize_t partition_guid_show(struct device *dev,
-				   struct device_attribute *attr,
-				   char *buf) {
-	struct visor_device *vdev = to_visor_device(dev);
-
-	return snprintf(buf, PAGE_SIZE, "{%pUb}\n", &vdev->partition_uuid);
-}
-
-static ssize_t partition_name_show(struct device *dev,
-				   struct device_attribute *attr,
-				   char *buf) {
-	struct visor_device *vdev = to_visor_device(dev);
-
-	return snprintf(buf, PAGE_SIZE, "%s\n", vdev->name);
-}
-
-static ssize_t channel_addr_show(struct device *dev,
-				 struct device_attribute *attr,
-				 char *buf) {
-	struct visor_device *vdev = to_visor_device(dev);
-	u64 addr = visorchannel_get_physaddr(vdev->visorchannel);
-
-	return snprintf(buf, PAGE_SIZE, "0x%llx\n", addr);
-}
-
-static ssize_t channel_bytes_show(struct device *dev,
-				  struct device_attribute *attr,
-				  char *buf) {
-	struct visor_device *vdev = to_visor_device(dev);
-	u64 nbytes = visorchannel_get_nbytes(vdev->visorchannel);
-
-	return snprintf(buf, PAGE_SIZE, "0x%llx\n", nbytes);
-}
-
-static ssize_t channel_id_show(struct device *dev,
-			       struct device_attribute *attr,
-			       char *buf) {
-	struct visor_device *vdev = to_visor_device(dev);
-	int len = 0;
-
-	if (vdev->visorchannel) {
-		visorchannel_id(vdev->visorchannel, buf);
-		len = strlen(buf);
-		buf[len++] = '\n';
-	}
-	return len;
-}
-
-static ssize_t client_bus_info_show(struct device *dev,
-				    struct device_attribute *attr,
-				    char *buf) {
-	struct visor_device *vdev = to_visor_device(dev);
-	struct visorchannel *channel = vdev->visorchannel;
-
-	int i, shift, remain = PAGE_SIZE;
-	unsigned long off;
-	char *pos = buf;
-	u8 *partition_name;
-	struct ultra_vbus_deviceinfo dev_info;
-
-	partition_name = "";
-	if (channel) {
-		if (vdev->name)
-			partition_name = vdev->name;
-		shift = snprintf(pos, remain,
-				 "Client device / client driver info for %s eartition (vbus #%d):\n",
-				 partition_name, vdev->chipset_dev_no);
-		pos += shift;
-		remain -= shift;
-		shift = visorchannel_read(channel,
-					  offsetof(struct
-						   spar_vbus_channel_protocol,
-						   chp_info),
-					  &dev_info, sizeof(dev_info));
-		if (shift >= 0) {
-			shift = vbuschannel_devinfo_to_string(&dev_info, pos,
-							      remain, -1);
-			pos += shift;
-			remain -= shift;
-		}
-		shift = visorchannel_read(channel,
-					  offsetof(struct
-						   spar_vbus_channel_protocol,
-						   bus_info),
-					  &dev_info, sizeof(dev_info));
-		if (shift >= 0) {
-			shift = vbuschannel_devinfo_to_string(&dev_info, pos,
-							      remain, -1);
-			pos += shift;
-			remain -= shift;
-		}
-		off = offsetof(struct spar_vbus_channel_protocol, dev_info);
-		i = 0;
-		while (off + sizeof(dev_info) <=
-		       visorchannel_get_nbytes(channel)) {
-			shift = visorchannel_read(channel,
-						  off, &dev_info,
-						  sizeof(dev_info));
-			if (shift >= 0) {
-				shift = vbuschannel_devinfo_to_string
-				    (&dev_info, pos, remain, i);
-				pos += shift;
-				remain -= shift;
-			}
-			off += sizeof(dev_info);
-			i++;
-		}
-	}
-	return PAGE_SIZE - remain;
-}
-
-static DEVICE_ATTR_RO(partition_handle);
-static DEVICE_ATTR_RO(partition_guid);
-static DEVICE_ATTR_RO(partition_name);
-static DEVICE_ATTR_RO(channel_addr);
-static DEVICE_ATTR_RO(channel_bytes);
-static DEVICE_ATTR_RO(channel_id);
-static DEVICE_ATTR_RO(client_bus_info);
-
-static struct attribute *dev_attrs[] = {
-		&dev_attr_partition_handle.attr,
-		&dev_attr_partition_guid.attr,
-		&dev_attr_partition_name.attr,
-		&dev_attr_channel_addr.attr,
-		&dev_attr_channel_bytes.attr,
-		&dev_attr_channel_id.attr,
-		&dev_attr_client_bus_info.attr,
-		NULL
-};
-
-static struct attribute_group dev_attr_grp = {
-		.attrs = dev_attrs,
-};
-
-static const struct attribute_group *visorbus_groups[] = {
-		&dev_attr_grp,
-		NULL
-};
-
-/*  DRIVER attributes
- *
- *  define & implement display of driver attributes under
- *  /sys/bus/visorbus/drivers/<drivername>.
- *
- */
-
-static ssize_t
-DRIVER_ATTR_version(struct device_driver *xdrv, char *buf)
-{
-	struct visor_driver *drv = to_visor_driver(xdrv);
-
-	return snprintf(buf, PAGE_SIZE, "%s\n", drv->version);
-}
-
-static int
-register_driver_attributes(struct visor_driver *drv)
-{
-	struct driver_attribute version =
-	    __ATTR(version, S_IRUGO, DRIVER_ATTR_version, NULL);
-	drv->version_attr = version;
-	return driver_create_file(&drv->driver, &drv->version_attr);
-}
-
-static void
-unregister_driver_attributes(struct visor_driver *drv)
-{
-	driver_remove_file(&drv->driver, &drv->version_attr);
-}
-
-static void
-dev_periodic_work(void *xdev)
-{
-	struct visor_device *dev = xdev;
-	struct visor_driver *drv = to_visor_driver(dev->device.driver);
-
-	down(&dev->visordriver_callback_lock);
-	if (drv->channel_interrupt)
-		drv->channel_interrupt(dev);
-	up(&dev->visordriver_callback_lock);
-	if (!visor_periodic_work_nextperiod(dev->periodic_work))
-		put_device(&dev->device);
-}
-
-static void
-dev_start_periodic_work(struct visor_device *dev)
-{
-	if (dev->being_removed)
-		return;
-	/* now up by at least 2 */
-	get_device(&dev->device);
-	if (!visor_periodic_work_start(dev->periodic_work))
-		put_device(&dev->device);
-}
-
-static void
-dev_stop_periodic_work(struct visor_device *dev)
-{
-	if (visor_periodic_work_stop(dev->periodic_work))
-		put_device(&dev->device);
-}
-
-/** This is called automatically upon adding a visor_device (device_add), or
- *  adding a visor_driver (visorbus_register_visor_driver), but only after
- *  visorbus_match has returned 1 to indicate a successful match between
- *  driver and device.
- */
-static int
-visordriver_probe_device(struct device *xdev)
-{
-	int res;
-	struct visor_driver *drv;
-	struct visor_device *dev;
-
-	drv = to_visor_driver(xdev->driver);
-	dev = to_visor_device(xdev);
-
-	if (!drv->probe)
-		return -ENODEV;
-
-	down(&dev->visordriver_callback_lock);
-	dev->being_removed = false;
-
-	res = drv->probe(dev);
-	if (res >= 0) {
-		/* success: reference kept via unmatched get_device() */
-		get_device(&dev->device);
-		fix_vbus_dev_info(dev);
-	}
-
-	up(&dev->visordriver_callback_lock);
-	return res;
-}
-
-/** This is called when device_unregister() is called for each child device
- *  instance, to notify the appropriate visorbus_driver that the device is
- *  going away, and to decrease the reference count of the device.
- */
-static int
-visordriver_remove_device(struct device *xdev)
-{
-	struct visor_device *dev;
-	struct visor_driver *drv;
-
-	dev = to_visor_device(xdev);
-	drv = to_visor_driver(xdev->driver);
-	down(&dev->visordriver_callback_lock);
-	dev->being_removed = true;
-	if (drv->remove)
-		drv->remove(dev);
-	up(&dev->visordriver_callback_lock);
-	dev_stop_periodic_work(dev);
-
-	put_device(&dev->device);
-	return 0;
-}
-
-/** A particular type of visor driver calls this function to register
- *  the driver.  The caller MUST fill in the following fields within the
- *  #drv structure:
- *      name, version, owner, channel_types, probe, remove
- *
- *  Here's how the whole Linux bus / driver / device model works.
- *
- *  At system start-up, the visorbus kernel module is loaded, which registers
- *  visorbus_type as a bus type, using bus_register().
- *
- *  All kernel modules that support particular device types on a
- *  visorbus bus are loaded.  Each of these kernel modules calls
- *  visorbus_register_visor_driver() in their init functions, passing a
- *  visor_driver struct.  visorbus_register_visor_driver() in turn calls
- *  register_driver(&visor_driver.driver).  This .driver member is
- *  initialized with generic methods (like probe), whose sole responsibility
- *  is to act as a broker for the real methods, which are within the
- *  visor_driver struct.  (This is the way the subclass behavior is
- *  implemented, since visor_driver is essentially a subclass of the
- *  generic driver.)  Whenever a driver_register() happens, core bus code in
- *  the kernel does (see device_attach() in drivers/base/dd.c):
- *
- *      for each dev associated with the bus (the bus that driver is on) that
- *      does not yet have a driver
- *          if bus.match(dev,newdriver) == yes_matched  ** .match specified
- *                                                 ** during bus_register().
- *              newdriver.probe(dev)  ** for visor drivers, this will call
- *                    ** the generic driver.probe implemented in visorbus.c,
- *                    ** which in turn calls the probe specified within the
- *                    ** struct visor_driver (which was specified by the
- *                    ** actual device driver as part of
- *                    ** visorbus_register_visor_driver()).
- *
- *  The above dance also happens when a new device appears.
- *  So the question is, how are devices created within the system?
- *  Basically, just call device_add(dev).  See pci_bus_add_devices().
- *  pci_scan_device() shows an example of how to build a device struct.  It
- *  returns the newly-created struct to pci_scan_single_device(), who adds it
- *  to the list of devices at PCIBUS.devices.  That list of devices is what
- *  is traversed by pci_bus_add_devices().
- *
- */
-int visorbus_register_visor_driver(struct visor_driver *drv)
-{
-	int rc = 0;
-
-	if (busreg_rc < 0)
-		return -ENODEV; /*can't register on a nonexistent bus*/
-
-	drv->driver.name = drv->name;
-	drv->driver.bus = &visorbus_type;
-	drv->driver.probe = visordriver_probe_device;
-	drv->driver.remove = visordriver_remove_device;
-	drv->driver.owner = drv->owner;
-
-	/* driver_register does this:
-	 *   bus_add_driver(drv)
-	 *   ->if (drv.bus)  ** (bus_type) **
-	 *       driver_attach(drv)
-	 *         for each dev with bus type of drv.bus
-	 *           if (!dev.drv)  ** no driver assigned yet **
-	 *             if (bus.match(dev,drv))  [visorbus_match]
-	 *               dev.drv = drv
-	 *               if (!drv.probe(dev))   [visordriver_probe_device]
-	 *                 dev.drv = NULL
-	 */
-
-	rc = driver_register(&drv->driver);
-	if (rc < 0)
-		return rc;
-	rc = register_driver_attributes(drv);
-	if (rc < 0)
-		driver_unregister(&drv->driver);
-	return rc;
-}
-EXPORT_SYMBOL_GPL(visorbus_register_visor_driver);
-
-/** A particular type of visor driver calls this function to unregister
- *  the driver, i.e., within its module_exit function.
- */
-void
-visorbus_unregister_visor_driver(struct visor_driver *drv)
-{
-	unregister_driver_attributes(drv);
-	driver_unregister(&drv->driver);
-}
-EXPORT_SYMBOL_GPL(visorbus_unregister_visor_driver);
-
-int
-visorbus_read_channel(struct visor_device *dev, unsigned long offset,
-		      void *dest, unsigned long nbytes)
-{
-	return visorchannel_read(dev->visorchannel, offset, dest, nbytes);
-}
-EXPORT_SYMBOL_GPL(visorbus_read_channel);
-
-int
-visorbus_write_channel(struct visor_device *dev, unsigned long offset,
-		       void *src, unsigned long nbytes)
-{
-	return visorchannel_write(dev->visorchannel, offset, src, nbytes);
-}
-EXPORT_SYMBOL_GPL(visorbus_write_channel);
-
-int
-visorbus_clear_channel(struct visor_device *dev, unsigned long offset, u8 ch,
-		       unsigned long nbytes)
-{
-	return visorchannel_clear(dev->visorchannel, offset, ch, nbytes);
-}
-EXPORT_SYMBOL_GPL(visorbus_clear_channel);
-
-/** We don't really have a real interrupt, so for now we just call the
- *  interrupt function periodically...
- */
-void
-visorbus_enable_channel_interrupts(struct visor_device *dev)
-{
-	dev_start_periodic_work(dev);
-}
-EXPORT_SYMBOL_GPL(visorbus_enable_channel_interrupts);
-
-void
-visorbus_disable_channel_interrupts(struct visor_device *dev)
-{
-	dev_stop_periodic_work(dev);
-}
-EXPORT_SYMBOL_GPL(visorbus_disable_channel_interrupts);
-
-/** This is how everything starts from the device end.
- *  This function is called when a channel first appears via a ControlVM
- *  message.  In response, this function allocates a visor_device to
- *  correspond to the new channel, and attempts to connect it the appropriate
- *  driver.  If the appropriate driver is found, the visor_driver.probe()
- *  function for that driver will be called, and will be passed the new
- *  visor_device that we just created.
- *
- *  It's ok if the appropriate driver is not yet loaded, because in that case
- *  the new device struct will just stick around in the bus' list of devices.
- *  When the appropriate driver calls visorbus_register_visor_driver(), the
- *  visor_driver.probe() for the new driver will be called with the new
- *  device.
- */
-static int
-create_visor_device(struct visor_device *dev)
-{
-	int err;
-	u32 chipset_bus_no = dev->chipset_bus_no;
-	u32 chipset_dev_no = dev->chipset_dev_no;
-
-	POSTCODE_LINUX_4(DEVICE_CREATE_ENTRY_PC, chipset_dev_no, chipset_bus_no,
-			 POSTCODE_SEVERITY_INFO);
-
-	sema_init(&dev->visordriver_callback_lock, 1);	/* unlocked */
-	dev->device.bus = &visorbus_type;
-	dev->device.groups = visorbus_channel_groups;
-	device_initialize(&dev->device);
-	dev->device.release = visorbus_release_device;
-	/* keep a reference just for us (now 2) */
-	get_device(&dev->device);
-	dev->periodic_work =
-		visor_periodic_work_create(POLLJIFFIES_NORMALCHANNEL,
-					   periodic_dev_workqueue,
-					   dev_periodic_work,
-					   dev, dev_name(&dev->device));
-	if (!dev->periodic_work) {
-		POSTCODE_LINUX_3(DEVICE_CREATE_FAILURE_PC, chipset_dev_no,
-				 DIAG_SEVERITY_ERR);
-		err = -EINVAL;
-		goto err_put;
-	}
-
-	/* bus_id must be a unique name with respect to this bus TYPE
-	 * (NOT bus instance).  That's why we need to include the bus
-	 * number within the name.
-	 */
-	dev_set_name(&dev->device, "vbus%u:dev%u",
-		     chipset_bus_no, chipset_dev_no);
-
-	/*  device_add does this:
-	 *    bus_add_device(dev)
-	 *    ->device_attach(dev)
-	 *      ->for each driver drv registered on the bus that dev is on
-	 *          if (dev.drv)  **  device already has a driver **
-	 *            ** not sure we could ever get here... **
-	 *          else
-	 *            if (bus.match(dev,drv)) [visorbus_match]
-	 *              dev.drv = drv
-	 *              if (!drv.probe(dev))  [visordriver_probe_device]
-	 *                dev.drv = NULL
-	 *
-	 *  Note that device_add does NOT fail if no driver failed to
-	 *  claim the device.  The device will be linked onto
-	 *  bus_type.klist_devices regardless (use bus_for_each_dev).
-	 */
-	err = device_add(&dev->device);
-	if (err < 0) {
-		POSTCODE_LINUX_3(DEVICE_ADD_PC, chipset_bus_no,
-				 DIAG_SEVERITY_ERR);
-		goto err_put;
-	}
-
-	list_add_tail(&dev->list_all, &list_all_device_instances);
-	return 0; /* success: reference kept via unmatched get_device() */
-
-err_put:
-	put_device(&dev->device);
-	return err;
-}
-
-static void
-remove_visor_device(struct visor_device *dev)
-{
-	list_del(&dev->list_all);
-	put_device(&dev->device);
-	device_unregister(&dev->device);
-}
-
-static int
-get_vbus_header_info(struct visorchannel *chan,
-		     struct spar_vbus_headerinfo *hdr_info)
-{
-	if (!SPAR_VBUS_CHANNEL_OK_CLIENT(visorchannel_get_header(chan)))
-		return -EINVAL;
-
-	if (visorchannel_read(chan, sizeof(struct channel_header), hdr_info,
-			      sizeof(*hdr_info)) < 0) {
-		return -EIO;
-	}
-	if (hdr_info->struct_bytes < sizeof(struct spar_vbus_headerinfo))
-		return -EINVAL;
-
-	if (hdr_info->device_info_struct_bytes <
-	    sizeof(struct ultra_vbus_deviceinfo)) {
-		return -EINVAL;
-	}
-	return 0;
-}
-
-/* Write the contents of <info> to the struct
- * spar_vbus_channel_protocol.chp_info.
- */
-
-static int
-write_vbus_chp_info(struct visorchannel *chan,
-		    struct spar_vbus_headerinfo *hdr_info,
-		    struct ultra_vbus_deviceinfo *info)
-{
-	int off = sizeof(struct channel_header) + hdr_info->chp_info_offset;
-
-	if (hdr_info->chp_info_offset == 0)
-		return -EFAULT;
-
-	if (visorchannel_write(chan, off, info, sizeof(*info)) < 0)
-		return -EFAULT;
-	return 0;
-}
-
-/* Write the contents of <info> to the struct
- * spar_vbus_channel_protocol.bus_info.
- */
-
-static int
-write_vbus_bus_info(struct visorchannel *chan,
-		    struct spar_vbus_headerinfo *hdr_info,
-		    struct ultra_vbus_deviceinfo *info)
-{
-	int off = sizeof(struct channel_header) + hdr_info->bus_info_offset;
-
-	if (hdr_info->bus_info_offset == 0)
-		return -EFAULT;
-
-	if (visorchannel_write(chan, off, info, sizeof(*info)) < 0)
-		return -EFAULT;
-	return 0;
-}
-
-/* Write the contents of <info> to the
- * struct spar_vbus_channel_protocol.dev_info[<devix>].
- */
-static int
-write_vbus_dev_info(struct visorchannel *chan,
-		    struct spar_vbus_headerinfo *hdr_info,
-		    struct ultra_vbus_deviceinfo *info, int devix)
-{
-	int off =
-	    (sizeof(struct channel_header) + hdr_info->dev_info_offset) +
-	    (hdr_info->device_info_struct_bytes * devix);
-
-	if (hdr_info->dev_info_offset == 0)
-		return -EFAULT;
-
-	if (visorchannel_write(chan, off, info, sizeof(*info)) < 0)
-		return -EFAULT;
-	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_dev_info(struct visor_device *visordev)
-{
-	int i;
-	struct visor_device *bdev;
-	struct visor_driver *visordrv;
-	int bus_no = visordev->chipset_bus_no;
-	int dev_no = visordev->chipset_dev_no;
-	struct ultra_vbus_deviceinfo dev_info;
-	const char *chan_type_name = NULL;
-	struct spar_vbus_headerinfo *hdr_info;
-
-	if (!visordev->device.driver)
-		return;
-
-	hdr_info = (struct spar_vbus_headerinfo *)visordev->vbus_hdr_info;
-	if (!hdr_info)
-		return;
-
-	bdev = visorbus_get_device_by_id(bus_no, BUS_ROOT_DEVICE, NULL);
-	if (!bdev)
-		return;
-
-	visordrv = to_visor_driver(visordev->device.driver);
-
-	/* Within the list of device types (by GUID) that the driver
-	 * says it supports, find out which one of those types matches
-	 * the type of this device, so that we can include the device
-	 * type name
-	 */
-	for (i = 0; visordrv->channel_types[i].name; i++) {
-		if (memcmp(&visordrv->channel_types[i].guid,
-			   &visordev->channel_type_guid,
-			   sizeof(visordrv->channel_types[i].guid)) == 0) {
-			chan_type_name = visordrv->channel_types[i].name;
-			break;
-		}
-	}
-
-	bus_device_info_init(&dev_info, chan_type_name,
-			     visordrv->name, visordrv->version,
-			     visordrv->vertag);
-	write_vbus_dev_info(bdev->visorchannel, hdr_info, &dev_info, dev_no);
-
-	/* Re-write bus+chipset info, because it is possible that this
-	* was previously written by our evil counterpart, virtpci.
-	*/
-	write_vbus_chp_info(bdev->visorchannel, hdr_info, &chipset_driverinfo);
-	write_vbus_bus_info(bdev->visorchannel, hdr_info,
-			    &clientbus_driverinfo);
-}
-
-/** Create a device instance for the visor bus itself.
- */
-static int
-create_bus_instance(struct visor_device *dev)
-{
-	int id = dev->chipset_bus_no;
-	struct spar_vbus_headerinfo *hdr_info;
-
-	POSTCODE_LINUX_2(BUS_CREATE_ENTRY_PC, POSTCODE_SEVERITY_INFO);
-
-	hdr_info = kzalloc(sizeof(*hdr_info), GFP_KERNEL);
-	if (!hdr_info)
-		return -ENOMEM;
-
-	dev_set_name(&dev->device, "visorbus%d", id);
-	dev->device.bus = &visorbus_type;
-	dev->device.groups = visorbus_groups;
-	dev->device.release = visorbus_release_busdevice;
-
-	if (device_register(&dev->device) < 0) {
-		POSTCODE_LINUX_3(DEVICE_CREATE_FAILURE_PC, id,
-				 POSTCODE_SEVERITY_ERR);
-		kfree(hdr_info);
-		return -ENODEV;
-	}
-
-	if (get_vbus_header_info(dev->visorchannel, hdr_info) >= 0) {
-		dev->vbus_hdr_info = (void *)hdr_info;
-		write_vbus_chp_info(dev->visorchannel, hdr_info,
-				    &chipset_driverinfo);
-		write_vbus_bus_info(dev->visorchannel, hdr_info,
-				    &clientbus_driverinfo);
-	} else {
-		kfree(hdr_info);
-	}
-	bus_count++;
-	list_add_tail(&dev->list_all, &list_all_bus_instances);
-	dev_set_drvdata(&dev->device, dev);
-	return 0;
-}
-
-/** Remove a device instance for the visor bus itself.
- */
-static void
-remove_bus_instance(struct visor_device *dev)
-{
-	/* Note that this will result in the release method for
-	 * dev->dev being called, which will call
-	 * visorbus_release_busdevice().  This has something to do with
-	 * the put_device() done in device_unregister(), but I have never
-	 * successfully been able to trace thru the code to see where/how
-	 * release() gets called.  But I know it does.
-	 */
-	bus_count--;
-	if (dev->visorchannel) {
-		visorchannel_destroy(dev->visorchannel);
-		dev->visorchannel = NULL;
-	}
-	kfree(dev->vbus_hdr_info);
-	list_del(&dev->list_all);
-	device_unregister(&dev->device);
-}
-
-/** Create and register the one-and-only one instance of
- *  the visor bus type (visorbus_type).
- */
-static int
-create_bus_type(void)
-{
-	busreg_rc = bus_register(&visorbus_type);
-	return busreg_rc;
-}
-
-/** Remove the one-and-only one instance of the visor bus type (visorbus_type).
- */
-static void
-remove_bus_type(void)
-{
-	bus_unregister(&visorbus_type);
-}
-
-/** Remove all child visor bus device instances.
- */
-static void
-remove_all_visor_devices(void)
-{
-	struct list_head *listentry, *listtmp;
-
-	list_for_each_safe(listentry, listtmp, &list_all_device_instances) {
-		struct visor_device *dev = list_entry(listentry,
-						      struct visor_device,
-						      list_all);
-		remove_visor_device(dev);
-	}
-}
-
-static void
-chipset_bus_create(struct visor_device *dev)
-{
-	int rc;
-	u32 bus_no = dev->chipset_bus_no;
-
-	POSTCODE_LINUX_3(BUS_CREATE_ENTRY_PC, bus_no, POSTCODE_SEVERITY_INFO);
-	rc = create_bus_instance(dev);
-	POSTCODE_LINUX_3(BUS_CREATE_EXIT_PC, bus_no, POSTCODE_SEVERITY_INFO);
-
-	if (rc < 0)
-		POSTCODE_LINUX_3(BUS_CREATE_FAILURE_PC, bus_no,
-				 POSTCODE_SEVERITY_ERR);
-	else
-		POSTCODE_LINUX_3(CHIPSET_INIT_SUCCESS_PC, bus_no,
-				 POSTCODE_SEVERITY_INFO);
-
-	if (chipset_responders.bus_create)
-		(*chipset_responders.bus_create) (dev, rc);
-}
-
-static void
-chipset_bus_destroy(struct visor_device *dev)
-{
-	remove_bus_instance(dev);
-	if (chipset_responders.bus_destroy)
-		(*chipset_responders.bus_destroy)(dev, 0);
-}
-
-static void
-chipset_device_create(struct visor_device *dev_info)
-{
-	int rc;
-	u32 bus_no = dev_info->chipset_bus_no;
-	u32 dev_no = dev_info->chipset_dev_no;
-
-	POSTCODE_LINUX_4(DEVICE_CREATE_ENTRY_PC, dev_no, bus_no,
-			 POSTCODE_SEVERITY_INFO);
-
-	rc = create_visor_device(dev_info);
-	if (chipset_responders.device_create)
-		chipset_responders.device_create(dev_info, rc);
-
-	if (rc < 0)
-		POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, dev_no, bus_no,
-				 POSTCODE_SEVERITY_ERR);
-	else
-		POSTCODE_LINUX_4(DEVICE_CREATE_SUCCESS_PC, dev_no, bus_no,
-				 POSTCODE_SEVERITY_INFO);
-}
-
-static void
-chipset_device_destroy(struct visor_device *dev_info)
-{
-	remove_visor_device(dev_info);
-
-	if (chipset_responders.device_destroy)
-		(*chipset_responders.device_destroy) (dev_info, 0);
-}
-
-/* This is the callback function specified for a function driver, to
- * be called when a pending "pause device" operation has been
- * completed.
- */
-static void
-pause_state_change_complete(struct visor_device *dev, int status)
-{
-	if (!dev->pausing)
-		return;
-
-	dev->pausing = false;
-	if (!chipset_responders.device_pause) /* this can never happen! */
-		return;
-
-	/* Notify the chipset driver that the pause is complete, which
-	 * will presumably want to send some sort of response to the
-	 * initiator.
-	 */
-	(*chipset_responders.device_pause) (dev, status);
-}
-
-/* This is the callback function specified for a function driver, to
- * be called when a pending "resume device" operation has been
- * completed.
- */
-static void
-resume_state_change_complete(struct visor_device *dev, int status)
-{
-	if (!dev->resuming)
-		return;
-
-	dev->resuming = false;
-	if (!chipset_responders.device_resume) /* this can never happen! */
-		return;
-
-	/* Notify the chipset driver that the resume is complete,
-	 * which will presumably want to send some sort of response to
-	 * the initiator.
-	 */
-	(*chipset_responders.device_resume) (dev, status);
-}
-
-/* Tell the subordinate function driver for a specific device to pause
- * or resume that device.  Result is returned asynchronously via a
- * callback function.
- */
-static void
-initiate_chipset_device_pause_resume(struct visor_device *dev, bool is_pause)
-{
-	int rc;
-	struct visor_driver *drv = NULL;
-	void (*notify_func)(struct visor_device *dev, int response) = NULL;
-
-	if (is_pause)
-		notify_func = chipset_responders.device_pause;
-	else
-		notify_func = chipset_responders.device_resume;
-	if (!notify_func)
-		return;
-
-	drv = to_visor_driver(dev->device.driver);
-	if (!drv) {
-		(*notify_func)(dev, -ENODEV);
-		return;
-	}
-
-	if (dev->pausing || dev->resuming) {
-		(*notify_func)(dev, -EBUSY);
-		return;
-	}
-
-	/* Note that even though both drv->pause() and drv->resume
-	 * specify a callback function, it is NOT necessary for us to
-	 * increment our local module usage count.  Reason is, there
-	 * is already a linkage dependency between child function
-	 * drivers and visorbus, so it is already IMPOSSIBLE to unload
-	 * visorbus while child function drivers are still running.
-	 */
-	if (is_pause) {
-		if (!drv->pause) {
-			(*notify_func)(dev, -EINVAL);
-			return;
-		}
-
-		dev->pausing = true;
-		rc = drv->pause(dev, pause_state_change_complete);
-	} else {
-		/* 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_dev_info(dev);
-		if (!drv->resume) {
-			(*notify_func)(dev, -EINVAL);
-			return;
-		}
-
-		dev->resuming = true;
-		rc = drv->resume(dev, resume_state_change_complete);
-	}
-	if (rc < 0) {
-		if (is_pause)
-			dev->pausing = false;
-		else
-			dev->resuming = false;
-		(*notify_func)(dev, -EINVAL);
-	}
-}
-
-static void
-chipset_device_pause(struct visor_device *dev_info)
-{
-	initiate_chipset_device_pause_resume(dev_info, true);
-}
-
-static void
-chipset_device_resume(struct visor_device *dev_info)
-{
-	initiate_chipset_device_pause_resume(dev_info, false);
-}
-
-struct channel_size_info {
-	uuid_le guid;
-	unsigned long min_size;
-	unsigned long max_size;
-};
-
-int
-visorbus_init(void)
-{
-	int err;
-
-	POSTCODE_LINUX_3(DRIVER_ENTRY_PC, 0, POSTCODE_SEVERITY_INFO);
-	bus_device_info_init(&clientbus_driverinfo,
-			     "clientbus", "visorbus",
-			     VERSION, NULL);
-
-	err = create_bus_type();
-	if (err < 0) {
-		POSTCODE_LINUX_2(BUS_CREATE_ENTRY_PC, DIAG_SEVERITY_ERR);
-		goto error;
-	}
-
-	periodic_dev_workqueue = create_singlethread_workqueue("visorbus_dev");
-	if (!periodic_dev_workqueue) {
-		POSTCODE_LINUX_2(CREATE_WORKQUEUE_PC, DIAG_SEVERITY_ERR);
-		err = -ENOMEM;
-		goto error;
-	}
-
-	/* This enables us to receive notifications when devices appear for
-	 * which this service partition is to be a server for.
-	 */
-	visorchipset_register_busdev(&chipset_notifiers,
-				     &chipset_responders,
-				     &chipset_driverinfo);
-
-	return 0;
-
-error:
-	POSTCODE_LINUX_3(CHIPSET_INIT_FAILURE_PC, err, POSTCODE_SEVERITY_ERR);
-	return err;
-}
-
-void
-visorbus_exit(void)
-{
-	struct list_head *listentry, *listtmp;
-
-	visorchipset_register_busdev(NULL, NULL, NULL);
-	remove_all_visor_devices();
-
-	flush_workqueue(periodic_dev_workqueue); /* better not be any work! */
-	destroy_workqueue(periodic_dev_workqueue);
-	periodic_dev_workqueue = NULL;
-
-	if (periodic_test_workqueue) {
-		cancel_delayed_work(&periodic_work);
-		flush_workqueue(periodic_test_workqueue);
-		destroy_workqueue(periodic_test_workqueue);
-		periodic_test_workqueue = NULL;
-	}
-
-	list_for_each_safe(listentry, listtmp, &list_all_bus_instances) {
-		struct visor_device *dev = list_entry(listentry,
-						      struct visor_device,
-						      list_all);
-		remove_bus_instance(dev);
-	}
-	remove_bus_type();
-}
-
-module_param_named(debug, visorbus_debug, int, S_IRUGO);
-MODULE_PARM_DESC(visorbus_debug, "1 to debug");
-
-module_param_named(forcematch, visorbus_forcematch, int, S_IRUGO);
-MODULE_PARM_DESC(visorbus_forcematch,
-		 "1 to force a successful dev <--> drv match");
-
-module_param_named(forcenomatch, visorbus_forcenomatch, int, S_IRUGO);
-MODULE_PARM_DESC(visorbus_forcenomatch,
-		 "1 to force an UNsuccessful dev <--> drv match");
-
-module_param_named(debugref, visorbus_debugref, int, S_IRUGO);
-MODULE_PARM_DESC(visorbus_debugref, "1 to debug reference counting");
diff --git a/drivers/staging/unisys/visorbus/visorbus_private.h b/drivers/staging/unisys/visorbus/visorbus_private.h
deleted file mode 100644
index 39edd20..0000000
--- a/drivers/staging/unisys/visorbus/visorbus_private.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/* visorchipset.h
- *
- * Copyright (C) 2010 - 2015 UNISYS CORPORATION
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope 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 <linux/uuid.h>
-
-#include "controlvmchannel.h"
-#include "vbusdeviceinfo.h"
-#include "vbushelper.h"
-
-/*  These functions will be called from within visorchipset when certain
- *  events happen.  (The implementation of these functions is outside of
- *  visorchipset.)
- */
-struct visorchipset_busdev_notifiers {
-	void (*bus_create)(struct visor_device *bus_info);
-	void (*bus_destroy)(struct visor_device *bus_info);
-	void (*device_create)(struct visor_device *bus_info);
-	void (*device_destroy)(struct visor_device *bus_info);
-	void (*device_pause)(struct visor_device *bus_info);
-	void (*device_resume)(struct visor_device *bus_info);
-};
-
-/*  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
- */
-struct visorchipset_busdev_responders {
-	void (*bus_create)(struct visor_device *p, int response);
-	void (*bus_destroy)(struct visor_device *p, int response);
-	void (*device_create)(struct visor_device *p, int response);
-	void (*device_destroy)(struct visor_device *p, int response);
-	void (*device_pause)(struct visor_device *p, int response);
-	void (*device_resume)(struct visor_device *p, int response);
-};
-
-/** Register functions (in the bus driver) to get called by visorchipset
- *  whenever a bus or device appears for which this guest 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(
-			struct visorchipset_busdev_notifiers *notifiers,
-			struct visorchipset_busdev_responders *responders,
-			struct ultra_vbus_deviceinfo *driver_info);
-
-/* visorbus init and exit functions */
-int visorbus_init(void);
-void visorbus_exit(void);
-#endif
diff --git a/drivers/staging/unisys/visorbus/visorchannel.c b/drivers/staging/unisys/visorbus/visorchannel.c
deleted file mode 100644
index 4e8b0ef..0000000
--- a/drivers/staging/unisys/visorbus/visorchannel.c
+++ /dev/null
@@ -1,635 +0,0 @@
-/* visorchannel_funcs.c
- *
- * Copyright (C) 2010 - 2015 UNISYS CORPORATION
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope 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.
- */
-
-#include <linux/uuid.h>
-#include <linux/io.h>
-
-#include <linux/visorbus/version.h>
-#include <linux/visorbus/visorbus.h>
-#include "controlvmchannel.h"
-
-#define MYDRVNAME "visorchannel"
-
-#define SPAR_CONSOLEVIDEO_CHANNEL_PROTOCOL_GUID \
-	UUID_LE(0x3cd6e705, 0xd6a2, 0x4aa5,           \
-		0xad, 0x5c, 0x7b, 0x8, 0x88, 0x9d, 0xff, 0xe2)
-static const uuid_le spar_video_guid = SPAR_CONSOLEVIDEO_CHANNEL_PROTOCOL_GUID;
-
-struct visorchannel {
-	u64 physaddr;
-	ulong nbytes;
-	void *mapped;
-	bool requested;
-	struct channel_header chan_hdr;
-	uuid_le guid;
-	bool needs_lock;	/* channel creator knows if more than one */
-				/* thread will be inserting or removing */
-	spinlock_t insert_lock; /* protect head writes in chan_hdr */
-	spinlock_t remove_lock;	/* protect tail writes in chan_hdr */
-
-	struct {
-		struct signal_queue_header req_queue;
-		struct signal_queue_header rsp_queue;
-		struct signal_queue_header event_queue;
-		struct signal_queue_header ack_queue;
-	} safe_uis_queue;
-	uuid_le type;
-	uuid_le inst;
-};
-
-/* Creates the struct visorchannel abstraction for a data area in memory,
- * but does NOT modify this data area.
- */
-static struct visorchannel *
-visorchannel_create_guts(u64 physaddr, unsigned long channel_bytes,
-			 gfp_t gfp, unsigned long off,
-			 uuid_le guid, bool needs_lock)
-{
-	struct visorchannel *channel;
-	int err;
-	size_t size = sizeof(struct channel_header);
-
-	if (physaddr == 0)
-		return NULL;
-
-	channel = kzalloc(sizeof(*channel), gfp);
-	if (!channel)
-		return NULL;
-
-	channel->needs_lock = needs_lock;
-	spin_lock_init(&channel->insert_lock);
-	spin_lock_init(&channel->remove_lock);
-
-	/* Video driver constains the efi framebuffer so it will get a
-	 * conflict resource when requesting its full mem region. Since
-	 * we are only using the efi framebuffer for video we can ignore
-	 * this. Remember that we haven't requested it so we don't try to
-	 * release later on.
-	 */
-	channel->requested = request_mem_region(physaddr, size, MYDRVNAME);
-	if (!channel->requested) {
-		if (uuid_le_cmp(guid, spar_video_guid)) {
-			/* Not the video channel we care about this */
-			goto err_destroy_channel;
-		}
-	}
-
-	channel->mapped = memremap(physaddr, size, MEMREMAP_WB);
-	if (!channel->mapped) {
-		release_mem_region(physaddr, size);
-		goto err_destroy_channel;
-	}
-
-	channel->physaddr = physaddr;
-	channel->nbytes = size;
-
-	err = visorchannel_read(channel, 0, &channel->chan_hdr,
-				sizeof(struct channel_header));
-	if (err)
-		goto err_destroy_channel;
-
-	/* we had better be a CLIENT of this channel */
-	if (channel_bytes == 0)
-		channel_bytes = (ulong)channel->chan_hdr.size;
-	if (uuid_le_cmp(guid, NULL_UUID_LE) == 0)
-		guid = channel->chan_hdr.chtype;
-
-	memunmap(channel->mapped);
-	if (channel->requested)
-		release_mem_region(channel->physaddr, channel->nbytes);
-	channel->mapped = NULL;
-	channel->requested = request_mem_region(channel->physaddr,
-						channel_bytes, MYDRVNAME);
-	if (!channel->requested) {
-		if (uuid_le_cmp(guid, spar_video_guid)) {
-			/* Different we care about this */
-			goto err_destroy_channel;
-		}
-	}
-
-	channel->mapped = memremap(channel->physaddr, channel_bytes,
-			MEMREMAP_WB);
-	if (!channel->mapped) {
-		release_mem_region(channel->physaddr, channel_bytes);
-		goto err_destroy_channel;
-	}
-
-	channel->nbytes = channel_bytes;
-	channel->guid = guid;
-	return channel;
-
-err_destroy_channel:
-	visorchannel_destroy(channel);
-	return NULL;
-}
-
-struct visorchannel *
-visorchannel_create(u64 physaddr, unsigned long channel_bytes,
-		    gfp_t gfp, uuid_le guid)
-{
-	return visorchannel_create_guts(physaddr, channel_bytes, gfp, 0, guid,
-					false);
-}
-EXPORT_SYMBOL_GPL(visorchannel_create);
-
-struct visorchannel *
-visorchannel_create_with_lock(u64 physaddr, unsigned long channel_bytes,
-			      gfp_t gfp, uuid_le guid)
-{
-	return visorchannel_create_guts(physaddr, channel_bytes, gfp, 0, guid,
-					true);
-}
-EXPORT_SYMBOL_GPL(visorchannel_create_with_lock);
-
-void
-visorchannel_destroy(struct visorchannel *channel)
-{
-	if (!channel)
-		return;
-	if (channel->mapped) {
-		memunmap(channel->mapped);
-		if (channel->requested)
-			release_mem_region(channel->physaddr, channel->nbytes);
-	}
-	kfree(channel);
-}
-EXPORT_SYMBOL_GPL(visorchannel_destroy);
-
-u64
-visorchannel_get_physaddr(struct visorchannel *channel)
-{
-	return channel->physaddr;
-}
-EXPORT_SYMBOL_GPL(visorchannel_get_physaddr);
-
-ulong
-visorchannel_get_nbytes(struct visorchannel *channel)
-{
-	return channel->nbytes;
-}
-EXPORT_SYMBOL_GPL(visorchannel_get_nbytes);
-
-char *
-visorchannel_uuid_id(uuid_le *guid, char *s)
-{
-	sprintf(s, "%pUL", guid);
-	return s;
-}
-EXPORT_SYMBOL_GPL(visorchannel_uuid_id);
-
-char *
-visorchannel_id(struct visorchannel *channel, char *s)
-{
-	return visorchannel_uuid_id(&channel->guid, s);
-}
-EXPORT_SYMBOL_GPL(visorchannel_id);
-
-char *
-visorchannel_zoneid(struct visorchannel *channel, char *s)
-{
-	return visorchannel_uuid_id(&channel->chan_hdr.zone_uuid, s);
-}
-EXPORT_SYMBOL_GPL(visorchannel_zoneid);
-
-u64
-visorchannel_get_clientpartition(struct visorchannel *channel)
-{
-	return channel->chan_hdr.partition_handle;
-}
-EXPORT_SYMBOL_GPL(visorchannel_get_clientpartition);
-
-int
-visorchannel_set_clientpartition(struct visorchannel *channel,
-				 u64 partition_handle)
-{
-	channel->chan_hdr.partition_handle = partition_handle;
-	return 0;
-}
-EXPORT_SYMBOL_GPL(visorchannel_set_clientpartition);
-
-uuid_le
-visorchannel_get_uuid(struct visorchannel *channel)
-{
-	return channel->guid;
-}
-EXPORT_SYMBOL_GPL(visorchannel_get_uuid);
-
-int
-visorchannel_read(struct visorchannel *channel, ulong offset,
-		  void *local, ulong nbytes)
-{
-	if (offset + nbytes > channel->nbytes)
-		return -EIO;
-
-	memcpy(local, channel->mapped + offset, nbytes);
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(visorchannel_read);
-
-int
-visorchannel_write(struct visorchannel *channel, ulong offset,
-		   void *local, ulong nbytes)
-{
-	size_t chdr_size = sizeof(struct channel_header);
-	size_t copy_size;
-
-	if (offset + nbytes > channel->nbytes)
-		return -EIO;
-
-	if (offset < chdr_size) {
-		copy_size = min(chdr_size - offset, nbytes);
-		memcpy(((char *)(&channel->chan_hdr)) + offset,
-		       local, copy_size);
-	}
-
-	memcpy(channel->mapped + offset, local, nbytes);
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(visorchannel_write);
-
-int
-visorchannel_clear(struct visorchannel *channel, ulong offset, u8 ch,
-		   ulong nbytes)
-{
-	int err;
-	int bufsize = PAGE_SIZE;
-	int written = 0;
-	u8 *buf;
-
-	buf = (u8 *)__get_free_page(GFP_KERNEL);
-	if (!buf)
-		return -ENOMEM;
-
-	memset(buf, ch, bufsize);
-
-	while (nbytes > 0) {
-		int thisbytes = bufsize;
-
-		if (nbytes < thisbytes)
-			thisbytes = nbytes;
-		err = visorchannel_write(channel, offset + written,
-					 buf, thisbytes);
-		if (err)
-			goto out_free_page;
-
-		written += thisbytes;
-		nbytes -= thisbytes;
-	}
-	err = 0;
-
-out_free_page:
-	free_page((unsigned long)buf);
-	return err;
-}
-EXPORT_SYMBOL_GPL(visorchannel_clear);
-
-void __iomem  *
-visorchannel_get_header(struct visorchannel *channel)
-{
-	return (void __iomem *)&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)->ch_space_offset + \
-	 ((q) * sizeof(struct 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)->sig_base_offset + \
-	    ((slot) * (sig_hdr)->signal_size))
-
-/** 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)			 \
-	(visorchannel_write(channel,					 \
-			    SIG_QUEUE_OFFSET(&channel->chan_hdr, queue) +\
-			    offsetof(struct signal_queue_header, FIELD), \
-			    &((sig_hdr)->FIELD),			 \
-			    sizeof((sig_hdr)->FIELD)) >= 0)
-
-static bool
-sig_read_header(struct visorchannel *channel, u32 queue,
-		struct signal_queue_header *sig_hdr)
-{
-	int err;
-
-	if (channel->chan_hdr.ch_space_offset < sizeof(struct channel_header))
-		return false;
-
-	/* Read the appropriate SIGNAL_QUEUE_HEADER into local memory. */
-	err = visorchannel_read(channel,
-				SIG_QUEUE_OFFSET(&channel->chan_hdr, queue),
-				sig_hdr, sizeof(struct signal_queue_header));
-	if (err)
-		return false;
-
-	return true;
-}
-
-static inline bool
-sig_read_data(struct visorchannel *channel, u32 queue,
-	      struct signal_queue_header *sig_hdr, u32 slot, void *data)
-{
-	int err;
-	int signal_data_offset = SIG_DATA_OFFSET(&channel->chan_hdr, queue,
-						 sig_hdr, slot);
-
-	err = visorchannel_read(channel, signal_data_offset,
-				data, sig_hdr->signal_size);
-	if (err)
-		return false;
-
-	return true;
-}
-
-static inline bool
-sig_write_data(struct visorchannel *channel, u32 queue,
-	       struct signal_queue_header *sig_hdr, u32 slot, void *data)
-{
-	int err;
-	int signal_data_offset = SIG_DATA_OFFSET(&channel->chan_hdr, queue,
-						 sig_hdr, slot);
-
-	err = visorchannel_write(channel, signal_data_offset,
-				 data, sig_hdr->signal_size);
-	if (err)
-		return false;
-
-	return true;
-}
-
-static bool
-signalremove_inner(struct visorchannel *channel, u32 queue, void *msg)
-{
-	struct signal_queue_header sig_hdr;
-
-	if (!sig_read_header(channel, queue, &sig_hdr))
-		return false;
-	if (sig_hdr.head == sig_hdr.tail)
-		return false;	/* no signals to remove */
-
-	sig_hdr.tail = (sig_hdr.tail + 1) % sig_hdr.max_slots;
-	if (!sig_read_data(channel, queue, &sig_hdr, sig_hdr.tail, msg))
-		return false;
-	sig_hdr.num_received++;
-
-	/* For each data field in SIGNAL_QUEUE_HEADER that was modified,
-	 * update host memory.
-	 */
-	mb(); /* required for channel synch */
-	if (!SIG_WRITE_FIELD(channel, queue, &sig_hdr, tail))
-		return false;
-	if (!SIG_WRITE_FIELD(channel, queue, &sig_hdr, num_received))
-		return false;
-	return true;
-}
-
-bool
-visorchannel_signalremove(struct visorchannel *channel, u32 queue, void *msg)
-{
-	bool rc;
-	unsigned long flags;
-
-	if (channel->needs_lock) {
-		spin_lock_irqsave(&channel->remove_lock, flags);
-		rc = signalremove_inner(channel, queue, msg);
-		spin_unlock_irqrestore(&channel->remove_lock, flags);
-	} else {
-		rc = signalremove_inner(channel, queue, msg);
-	}
-
-	return rc;
-}
-EXPORT_SYMBOL_GPL(visorchannel_signalremove);
-
-bool
-visorchannel_signalempty(struct visorchannel *channel, u32 queue)
-{
-	unsigned long flags = 0;
-	struct signal_queue_header sig_hdr;
-	bool rc = false;
-
-	if (channel->needs_lock)
-		spin_lock_irqsave(&channel->remove_lock, flags);
-
-	if (!sig_read_header(channel, queue, &sig_hdr))
-		rc = true;
-	if (sig_hdr.head == sig_hdr.tail)
-		rc = true;
-	if (channel->needs_lock)
-		spin_unlock_irqrestore(&channel->remove_lock, flags);
-
-	return rc;
-}
-EXPORT_SYMBOL_GPL(visorchannel_signalempty);
-
-static bool
-signalinsert_inner(struct visorchannel *channel, u32 queue, void *msg)
-{
-	struct signal_queue_header sig_hdr;
-
-	if (!sig_read_header(channel, queue, &sig_hdr))
-		return false;
-
-	sig_hdr.head = (sig_hdr.head + 1) % sig_hdr.max_slots;
-	if (sig_hdr.head == sig_hdr.tail) {
-		sig_hdr.num_overflows++;
-		visorchannel_write(channel,
-				   SIG_QUEUE_OFFSET(&channel->chan_hdr, queue) +
-				   offsetof(struct signal_queue_header,
-					    num_overflows),
-				   &sig_hdr.num_overflows,
-				   sizeof(sig_hdr.num_overflows));
-		return false;
-	}
-
-	if (!sig_write_data(channel, queue, &sig_hdr, sig_hdr.head, msg))
-		return false;
-
-	sig_hdr.num_sent++;
-
-	/* For each data field in SIGNAL_QUEUE_HEADER that was modified,
-	 * update host memory.
-	 */
-	mb(); /* required for channel synch */
-	if (!SIG_WRITE_FIELD(channel, queue, &sig_hdr, head))
-		return false;
-	if (!SIG_WRITE_FIELD(channel, queue, &sig_hdr, num_sent))
-		return false;
-
-	return true;
-}
-
-bool
-visorchannel_signalinsert(struct visorchannel *channel, u32 queue, void *msg)
-{
-	bool rc;
-	unsigned long flags;
-
-	if (channel->needs_lock) {
-		spin_lock_irqsave(&channel->insert_lock, flags);
-		rc = signalinsert_inner(channel, queue, msg);
-		spin_unlock_irqrestore(&channel->insert_lock, flags);
-	} else {
-		rc = signalinsert_inner(channel, queue, msg);
-	}
-
-	return rc;
-}
-EXPORT_SYMBOL_GPL(visorchannel_signalinsert);
-
-int
-visorchannel_signalqueue_slots_avail(struct visorchannel *channel, u32 queue)
-{
-	struct 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.max_slots;
-	slots_used = head - tail;
-	slots_avail = sig_hdr.max_signals - slots_used;
-	return (int)slots_avail;
-}
-EXPORT_SYMBOL_GPL(visorchannel_signalqueue_slots_avail);
-
-int
-visorchannel_signalqueue_max_slots(struct visorchannel *channel, u32 queue)
-{
-	struct signal_queue_header sig_hdr;
-
-	if (!sig_read_header(channel, queue, &sig_hdr))
-		return 0;
-	return (int)sig_hdr.max_signals;
-}
-EXPORT_SYMBOL_GPL(visorchannel_signalqueue_max_slots);
-
-static void
-sigqueue_debug(struct 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->version);
-	seq_printf(seq, "   Type               = %lu\n", (ulong)q->chtype);
-	seq_printf(seq, "   oSignalBase        = %llu\n",
-		   (long long)q->sig_base_offset);
-	seq_printf(seq, "   SignalSize         = %lu\n", (ulong)q->signal_size);
-	seq_printf(seq, "   MaxSignalSlots     = %lu\n",
-		   (ulong)q->max_slots);
-	seq_printf(seq, "   MaxSignals         = %lu\n", (ulong)q->max_signals);
-	seq_printf(seq, "   FeatureFlags       = %-16.16Lx\n",
-		   (long long)q->features);
-	seq_printf(seq, "   NumSignalsSent     = %llu\n",
-		   (long long)q->num_sent);
-	seq_printf(seq, "   NumSignalsReceived = %llu\n",
-		   (long long)q->num_received);
-	seq_printf(seq, "   NumOverflows       = %llu\n",
-		   (long long)q->num_overflows);
-	seq_printf(seq, "   Head               = %lu\n", (ulong)q->head);
-	seq_printf(seq, "   Tail               = %lu\n", (ulong)q->tail);
-}
-
-void
-visorchannel_debug(struct visorchannel *channel, int num_queues,
-		   struct seq_file *seq, u32 off)
-{
-	u64 addr = 0;
-	ulong nbytes = 0, nbytes_region = 0;
-	struct channel_header hdr;
-	struct channel_header *phdr = &hdr;
-	int i = 0;
-	int errcode = 0;
-
-	if (!channel)
-		return;
-
-	addr = visorchannel_get_physaddr(channel);
-	nbytes_region = visorchannel_get_nbytes(channel);
-	errcode = visorchannel_read(channel, off,
-				    phdr, sizeof(struct 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            = %pUL\n", &phdr->chtype);
-	seq_printf(seq, "ZoneGuid        = %pUL\n", &phdr->zone_uuid);
-	seq_printf(seq, "Signature       = 0x%-16.16Lx\n",
-		   (long long)phdr->signature);
-	seq_printf(seq, "LegacyState     = %lu\n", (ulong)phdr->legacy_state);
-	seq_printf(seq, "SrvState        = %lu\n", (ulong)phdr->srv_state);
-	seq_printf(seq, "CliStateBoot    = %lu\n", (ulong)phdr->cli_state_boot);
-	seq_printf(seq, "CliStateOS      = %lu\n", (ulong)phdr->cli_state_os);
-	seq_printf(seq, "HeaderSize      = %lu\n", (ulong)phdr->header_size);
-	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->partition_handle);
-	seq_printf(seq, "Handle          = 0x%-16.16llx\n",
-		   (long long)phdr->handle);
-	seq_printf(seq, "VersionId       = %lu\n", (ulong)phdr->version_id);
-	seq_printf(seq, "oChannelSpace   = %llu\n",
-		   (long long)phdr->ch_space_offset);
-	if ((phdr->ch_space_offset == 0) || (errcode < 0))
-		;
-	else
-		for (i = 0; i < num_queues; i++) {
-			struct signal_queue_header q;
-
-			errcode = visorchannel_read(channel,
-						    off +
-						    phdr->ch_space_offset +
-						    (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);
diff --git a/drivers/staging/unisys/visorbus/visorchipset.c b/drivers/staging/unisys/visorbus/visorchipset.c
deleted file mode 100644
index 630137a..0000000
--- a/drivers/staging/unisys/visorbus/visorchipset.c
+++ /dev/null
@@ -1,2355 +0,0 @@
-/* visorchipset_main.c
- *
- * Copyright (C) 2010 - 2015 UNISYS CORPORATION
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope 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/acpi.h>
-#include <linux/cdev.h>
-#include <linux/ctype.h>
-#include <linux/fs.h>
-#include <linux/mm.h>
-#include <linux/nls.h>
-#include <linux/netdevice.h>
-#include <linux/platform_device.h>
-#include <linux/uuid.h>
-#include <linux/crash_dump.h>
-#include <linux/visorbus/channel_guid.h>
-#include <linux/visorbus/guestlinuxdebug.h>
-#include <linux/visorbus/periodic_work.h>
-#include <linux/visorbus/version.h>
-#include <linux/visorbus/visorbus.h>
-
-#include "controlvmchannel.h"
-#include "controlvmcompletionstatus.h"
-#include "visorbus_private.h"
-#include "vmcallinterface.h"
-
-#define CURRENT_FILE_PC VISOR_CHIPSET_PC_visorchipset_main_c
-
-#define MAX_NAME_SIZE 128
-#define MAX_IP_SIZE   50
-#define MAXOUTSTANDINGCHANNELCOMMAND 256
-#define POLLJIFFIES_CONTROLVMCHANNEL_FAST   1
-#define POLLJIFFIES_CONTROLVMCHANNEL_SLOW 100
-
-#define MAX_CONTROLVM_PAYLOAD_BYTES (1024 * 128)
-
-#define VISORCHIPSET_MMAP_CONTROLCHANOFFSET	0x00000000
-
-#define UNISYS_SPAR_LEAF_ID 0x40000000
-
-/* The s-Par leaf ID returns "UnisysSpar64" encoded across ebx, ecx, edx */
-#define UNISYS_SPAR_ID_EBX 0x73696e55
-#define UNISYS_SPAR_ID_ECX 0x70537379
-#define UNISYS_SPAR_ID_EDX 0x34367261
-
-/*
- * Module parameters
- */
-static int visorchipset_major;
-static int visorchipset_visorbusregwait = 1;	/* default is on */
-static unsigned long controlvm_payload_bytes_buffered;
-static u32 dump_vhba_bus;
-
-static int
-visorchipset_open(struct inode *inode, struct file *file)
-{
-	unsigned int minor_number = iminor(inode);
-
-	if (minor_number)
-		return -ENODEV;
-	file->private_data = NULL;
-	return 0;
-}
-
-static int
-visorchipset_release(struct inode *inode, struct file *file)
-{
-	return 0;
-}
-
-/* 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
-static unsigned long poll_jiffies = POLLJIFFIES_CONTROLVMCHANNEL_FAST;
-/* when we got our last controlvm message */
-static unsigned long most_recent_message_jiffies;
-static int visorbusregistered;
-
-struct parser_context {
-	unsigned long allocbytes;
-	unsigned long param_bytes;
-	u8 *curr;
-	unsigned long bytes_remaining;
-	bool byte_stream;
-	char data[0];
-};
-
-static struct delayed_work periodic_controlvm_work;
-static DEFINE_SEMAPHORE(notifier_lock);
-
-static struct cdev file_cdev;
-static struct visorchannel **file_controlvm_channel;
-static struct controlvm_message_packet g_devicechangestate_packet;
-
-static LIST_HEAD(bus_info_list);
-static LIST_HEAD(dev_info_list);
-
-static struct visorchannel *controlvm_channel;
-
-/* Manages the request payload in the controlvm channel */
-struct visor_controlvm_payload_info {
-	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 */
-};
-
-static struct visor_controlvm_payload_info controlvm_payload_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 struct controlvm_message controlvm_pending_msg;
-static bool controlvm_pending_msg_valid;
-
-/* 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 */
-	struct parser_context *parser_ctx; /* points to input data buffer */
-};
-
-/* 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 */
-	struct parser_context *parser_ctx;
-	/* points within data area of parser_ctx to next byte of data */
-	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 */
-	struct controlvm_message_header controlvm_header;
-
-	/* link to next struct putfile_request */
-	struct list_head next_putfile_request;
-
-	/* 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;
-};
-
-struct parahotplug_request {
-	struct list_head list;
-	int id;
-	unsigned long expiration;
-	struct 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 struct visorchipset_busdev_notifiers busdev_notifiers;
-
-static void bus_create_response(struct visor_device *p, int response);
-static void bus_destroy_response(struct visor_device *p, int response);
-static void device_create_response(struct visor_device *p, int response);
-static void device_destroy_response(struct visor_device *p, int response);
-static void device_resume_response(struct visor_device *p, int response);
-
-static void visorchipset_device_pause_response(struct visor_device *p,
-					       int response);
-
-static struct 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 = visorchipset_device_pause_response,
-	.device_resume = device_resume_response,
-};
-
-/* info for /dev/visorchipset */
-static dev_t major_dev = -1; /**< indicates major num for device */
-
-/* prototypes for attributes */
-static ssize_t toolaction_show(struct device *dev,
-			       struct device_attribute *attr, char *buf);
-static ssize_t toolaction_store(struct device *dev,
-				struct device_attribute *attr,
-				const char *buf, size_t count);
-static DEVICE_ATTR_RW(toolaction);
-
-static ssize_t boottotool_show(struct device *dev,
-			       struct device_attribute *attr, char *buf);
-static ssize_t boottotool_store(struct device *dev,
-				struct device_attribute *attr, const char *buf,
-				size_t count);
-static DEVICE_ATTR_RW(boottotool);
-
-static ssize_t error_show(struct device *dev, struct device_attribute *attr,
-			  char *buf);
-static ssize_t error_store(struct device *dev, struct device_attribute *attr,
-			   const char *buf, size_t count);
-static DEVICE_ATTR_RW(error);
-
-static ssize_t textid_show(struct device *dev, struct device_attribute *attr,
-			   char *buf);
-static ssize_t textid_store(struct device *dev, struct device_attribute *attr,
-			    const char *buf, size_t count);
-static DEVICE_ATTR_RW(textid);
-
-static ssize_t remaining_steps_show(struct device *dev,
-				    struct device_attribute *attr, char *buf);
-static ssize_t remaining_steps_store(struct device *dev,
-				     struct device_attribute *attr,
-				     const char *buf, size_t count);
-static DEVICE_ATTR_RW(remaining_steps);
-
-static ssize_t devicedisabled_store(struct device *dev,
-				    struct device_attribute *attr,
-				    const char *buf, size_t count);
-static DEVICE_ATTR_WO(devicedisabled);
-
-static ssize_t deviceenabled_store(struct device *dev,
-				   struct device_attribute *attr,
-				   const char *buf, size_t count);
-static DEVICE_ATTR_WO(deviceenabled);
-
-static struct attribute *visorchipset_install_attrs[] = {
-	&dev_attr_toolaction.attr,
-	&dev_attr_boottotool.attr,
-	&dev_attr_error.attr,
-	&dev_attr_textid.attr,
-	&dev_attr_remaining_steps.attr,
-	NULL
-};
-
-static struct attribute_group visorchipset_install_group = {
-	.name = "install",
-	.attrs = visorchipset_install_attrs
-};
-
-static struct attribute *visorchipset_parahotplug_attrs[] = {
-	&dev_attr_devicedisabled.attr,
-	&dev_attr_deviceenabled.attr,
-	NULL
-};
-
-static struct attribute_group visorchipset_parahotplug_group = {
-	.name = "parahotplug",
-	.attrs = visorchipset_parahotplug_attrs
-};
-
-static const struct attribute_group *visorchipset_dev_groups[] = {
-	&visorchipset_install_group,
-	&visorchipset_parahotplug_group,
-	NULL
-};
-
-static void visorchipset_dev_release(struct device *dev)
-{
-}
-
-/* /sys/devices/platform/visorchipset */
-static struct platform_device visorchipset_platform_device = {
-	.name = "visorchipset",
-	.id = -1,
-	.dev.groups = visorchipset_dev_groups,
-	.dev.release = visorchipset_dev_release,
-};
-
-/* Function prototypes */
-static void controlvm_respond(struct controlvm_message_header *msg_hdr,
-			      int response);
-static void controlvm_respond_chipset_init(
-		struct controlvm_message_header *msg_hdr, int response,
-		enum ultra_chipset_feature features);
-static void controlvm_respond_physdev_changestate(
-		struct controlvm_message_header *msg_hdr, int response,
-		struct spar_segment_state state);
-
-static void parser_done(struct parser_context *ctx);
-
-static struct parser_context *
-parser_init_byte_stream(u64 addr, u32 bytes, bool local, bool *retry)
-{
-	int allocbytes = sizeof(struct parser_context) + bytes;
-	struct parser_context *ctx;
-
-	if (retry)
-		*retry = false;
-
-	/*
-	 * alloc an 0 extra byte to ensure payload is
-	 * '\0'-terminated
-	 */
-	allocbytes++;
-	if ((controlvm_payload_bytes_buffered + bytes)
-	    > MAX_CONTROLVM_PAYLOAD_BYTES) {
-		if (retry)
-			*retry = true;
-		return NULL;
-	}
-	ctx = kzalloc(allocbytes, GFP_KERNEL | __GFP_NORETRY);
-	if (!ctx) {
-		if (retry)
-			*retry = true;
-		return NULL;
-	}
-
-	ctx->allocbytes = allocbytes;
-	ctx->param_bytes = bytes;
-	ctx->curr = NULL;
-	ctx->bytes_remaining = 0;
-	ctx->byte_stream = false;
-	if (local) {
-		void *p;
-
-		if (addr > virt_to_phys(high_memory - 1))
-			goto err_finish_ctx;
-		p = __va((unsigned long)(addr));
-		memcpy(ctx->data, p, bytes);
-	} else {
-		void *mapping = memremap(addr, bytes, MEMREMAP_WB);
-
-		if (!mapping)
-			goto err_finish_ctx;
-		memcpy(ctx->data, mapping, bytes);
-		memunmap(mapping);
-	}
-
-	ctx->byte_stream = true;
-	controlvm_payload_bytes_buffered += ctx->param_bytes;
-
-	return ctx;
-
-err_finish_ctx:
-	parser_done(ctx);
-	return NULL;
-}
-
-static uuid_le
-parser_id_get(struct parser_context *ctx)
-{
-	struct spar_controlvm_parameters_header *phdr = NULL;
-
-	if (!ctx)
-		return NULL_UUID_LE;
-	phdr = (struct spar_controlvm_parameters_header *)(ctx->data);
-	return phdr->id;
-}
-
-/** Describes the state from the perspective of which controlvm messages have
- *  been received for a bus or device.
- */
-
-enum PARSER_WHICH_STRING {
-	PARSERSTRING_INITIATOR,
-	PARSERSTRING_TARGET,
-	PARSERSTRING_CONNECTION,
-	PARSERSTRING_NAME, /* TODO: only PARSERSTRING_NAME is used ? */
-};
-
-static void
-parser_param_start(struct parser_context *ctx,
-		   enum PARSER_WHICH_STRING which_string)
-{
-	struct spar_controlvm_parameters_header *phdr = NULL;
-
-	if (!ctx)
-		return;
-
-	phdr = (struct spar_controlvm_parameters_header *)(ctx->data);
-	switch (which_string) {
-	case PARSERSTRING_INITIATOR:
-		ctx->curr = ctx->data + phdr->initiator_offset;
-		ctx->bytes_remaining = phdr->initiator_length;
-		break;
-	case PARSERSTRING_TARGET:
-		ctx->curr = ctx->data + phdr->target_offset;
-		ctx->bytes_remaining = phdr->target_length;
-		break;
-	case PARSERSTRING_CONNECTION:
-		ctx->curr = ctx->data + phdr->connection_offset;
-		ctx->bytes_remaining = phdr->connection_length;
-		break;
-	case PARSERSTRING_NAME:
-		ctx->curr = ctx->data + phdr->name_offset;
-		ctx->bytes_remaining = phdr->name_length;
-		break;
-	default:
-		break;
-	}
-}
-
-static void parser_done(struct parser_context *ctx)
-{
-	if (!ctx)
-		return;
-	controlvm_payload_bytes_buffered -= ctx->param_bytes;
-	kfree(ctx);
-}
-
-static void *
-parser_string_get(struct parser_context *ctx)
-{
-	u8 *pscan;
-	unsigned long 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)
-		return NULL;
-	if (value_length > 0)
-		memcpy(value, pscan, value_length);
-	((u8 *)(value))[value_length] = '\0';
-	return value;
-}
-
-static ssize_t toolaction_show(struct device *dev,
-			       struct device_attribute *attr,
-			       char *buf)
-{
-	u8 tool_action = 0;
-
-	visorchannel_read(controlvm_channel,
-			  offsetof(struct spar_controlvm_channel_protocol,
-				   tool_action), &tool_action, sizeof(u8));
-	return scnprintf(buf, PAGE_SIZE, "%u\n", tool_action);
-}
-
-static ssize_t toolaction_store(struct device *dev,
-				struct device_attribute *attr,
-				const char *buf, size_t count)
-{
-	u8 tool_action;
-	int ret;
-
-	if (kstrtou8(buf, 10, &tool_action))
-		return -EINVAL;
-
-	ret = visorchannel_write
-		(controlvm_channel,
-		 offsetof(struct spar_controlvm_channel_protocol,
-			  tool_action),
-		 &tool_action, sizeof(u8));
-
-	if (ret)
-		return ret;
-	return count;
-}
-
-static ssize_t boottotool_show(struct device *dev,
-			       struct device_attribute *attr,
-			       char *buf)
-{
-	struct efi_spar_indication efi_spar_indication;
-
-	visorchannel_read(controlvm_channel,
-			  offsetof(struct spar_controlvm_channel_protocol,
-				   efi_spar_ind), &efi_spar_indication,
-			  sizeof(struct efi_spar_indication));
-	return scnprintf(buf, PAGE_SIZE, "%u\n",
-			 efi_spar_indication.boot_to_tool);
-}
-
-static ssize_t boottotool_store(struct device *dev,
-				struct device_attribute *attr,
-				const char *buf, size_t count)
-{
-	int val, ret;
-	struct efi_spar_indication efi_spar_indication;
-
-	if (kstrtoint(buf, 10, &val))
-		return -EINVAL;
-
-	efi_spar_indication.boot_to_tool = val;
-	ret = visorchannel_write
-		(controlvm_channel,
-		 offsetof(struct spar_controlvm_channel_protocol,
-			  efi_spar_ind), &(efi_spar_indication),
-		 sizeof(struct efi_spar_indication));
-
-	if (ret)
-		return ret;
-	return count;
-}
-
-static ssize_t error_show(struct device *dev, struct device_attribute *attr,
-			  char *buf)
-{
-	u32 error = 0;
-
-	visorchannel_read(controlvm_channel,
-			  offsetof(struct spar_controlvm_channel_protocol,
-				   installation_error),
-			  &error, sizeof(u32));
-	return scnprintf(buf, PAGE_SIZE, "%i\n", error);
-}
-
-static ssize_t error_store(struct device *dev, struct device_attribute *attr,
-			   const char *buf, size_t count)
-{
-	u32 error;
-	int ret;
-
-	if (kstrtou32(buf, 10, &error))
-		return -EINVAL;
-
-	ret = visorchannel_write
-		(controlvm_channel,
-		 offsetof(struct spar_controlvm_channel_protocol,
-			  installation_error),
-		 &error, sizeof(u32));
-	if (ret)
-		return ret;
-	return count;
-}
-
-static ssize_t textid_show(struct device *dev, struct device_attribute *attr,
-			   char *buf)
-{
-	u32 text_id = 0;
-
-	visorchannel_read
-		(controlvm_channel,
-		 offsetof(struct spar_controlvm_channel_protocol,
-			  installation_text_id),
-		 &text_id, sizeof(u32));
-	return scnprintf(buf, PAGE_SIZE, "%i\n", text_id);
-}
-
-static ssize_t textid_store(struct device *dev, struct device_attribute *attr,
-			    const char *buf, size_t count)
-{
-	u32 text_id;
-	int ret;
-
-	if (kstrtou32(buf, 10, &text_id))
-		return -EINVAL;
-
-	ret = visorchannel_write
-		(controlvm_channel,
-		 offsetof(struct spar_controlvm_channel_protocol,
-			  installation_text_id),
-		 &text_id, sizeof(u32));
-	if (ret)
-		return ret;
-	return count;
-}
-
-static ssize_t remaining_steps_show(struct device *dev,
-				    struct device_attribute *attr, char *buf)
-{
-	u16 remaining_steps = 0;
-
-	visorchannel_read(controlvm_channel,
-			  offsetof(struct spar_controlvm_channel_protocol,
-				   installation_remaining_steps),
-			  &remaining_steps, sizeof(u16));
-	return scnprintf(buf, PAGE_SIZE, "%hu\n", remaining_steps);
-}
-
-static ssize_t remaining_steps_store(struct device *dev,
-				     struct device_attribute *attr,
-				     const char *buf, size_t count)
-{
-	u16 remaining_steps;
-	int ret;
-
-	if (kstrtou16(buf, 10, &remaining_steps))
-		return -EINVAL;
-
-	ret = visorchannel_write
-		(controlvm_channel,
-		 offsetof(struct spar_controlvm_channel_protocol,
-			  installation_remaining_steps),
-		 &remaining_steps, sizeof(u16));
-	if (ret)
-		return ret;
-	return count;
-}
-
-struct visor_busdev {
-	u32 bus_no;
-	u32 dev_no;
-};
-
-static int match_visorbus_dev_by_id(struct device *dev, void *data)
-{
-	struct visor_device *vdev = to_visor_device(dev);
-	struct visor_busdev *id = data;
-	u32 bus_no = id->bus_no;
-	u32 dev_no = id->dev_no;
-
-	if ((vdev->chipset_bus_no == bus_no) &&
-	    (vdev->chipset_dev_no == dev_no))
-		return 1;
-
-	return 0;
-}
-
-struct visor_device *visorbus_get_device_by_id(u32 bus_no, u32 dev_no,
-					       struct visor_device *from)
-{
-	struct device *dev;
-	struct device *dev_start = NULL;
-	struct visor_device *vdev = NULL;
-	struct visor_busdev id = {
-			.bus_no = bus_no,
-			.dev_no = dev_no
-		};
-
-	if (from)
-		dev_start = &from->device;
-	dev = bus_find_device(&visorbus_type, dev_start, (void *)&id,
-			      match_visorbus_dev_by_id);
-	if (dev)
-		vdev = to_visor_device(dev);
-	return vdev;
-}
-EXPORT_SYMBOL(visorbus_get_device_by_id);
-
-void
-visorchipset_register_busdev(
-			struct visorchipset_busdev_notifiers *notifiers,
-			struct visorchipset_busdev_responders *responders,
-			struct ultra_vbus_deviceinfo *driver_info)
-{
-	down(&notifier_lock);
-	if (!notifiers) {
-		memset(&busdev_notifiers, 0,
-		       sizeof(busdev_notifiers));
-		visorbusregistered = 0;	/* clear flag */
-	} else {
-		busdev_notifiers = *notifiers;
-		visorbusregistered = 1;	/* set flag */
-	}
-	if (responders)
-		*responders = busdev_responders;
-	if (driver_info)
-		bus_device_info_init(driver_info, "chipset", "visorchipset",
-				     VERSION, NULL);
-
-	up(&notifier_lock);
-}
-EXPORT_SYMBOL_GPL(visorchipset_register_busdev);
-
-static void
-chipset_init(struct controlvm_message *inmsg)
-{
-	static int chipset_inited;
-	enum ultra_chipset_feature features = 0;
-	int rc = CONTROLVM_RESP_SUCCESS;
-
-	POSTCODE_LINUX_2(CHIPSET_INIT_ENTRY_PC, POSTCODE_SEVERITY_INFO);
-	if (chipset_inited) {
-		rc = -CONTROLVM_RESP_ERROR_ALREADY_DONE;
-		goto out_respond;
-	}
-	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.init_chipset.
-	    features & ULTRA_CHIPSET_FEATURE_PARA_HOTPLUG;
-
-	/* Set the "reply" bit so Command knows this is a
-	 * features-aware driver.
-	 */
-	features |= ULTRA_CHIPSET_FEATURE_REPLY;
-
-out_respond:
-	if (inmsg->hdr.flags.response_expected)
-		controlvm_respond_chipset_init(&inmsg->hdr, rc, features);
-}
-
-static void
-controlvm_init_response(struct controlvm_message *msg,
-			struct controlvm_message_header *msg_hdr, int response)
-{
-	memset(msg, 0, sizeof(struct controlvm_message));
-	memcpy(&msg->hdr, msg_hdr, sizeof(struct controlvm_message_header));
-	msg->hdr.payload_bytes = 0;
-	msg->hdr.payload_vm_offset = 0;
-	msg->hdr.payload_max_bytes = 0;
-	if (response < 0) {
-		msg->hdr.flags.failed = 1;
-		msg->hdr.completion_status = (u32)(-response);
-	}
-}
-
-static void
-controlvm_respond(struct controlvm_message_header *msg_hdr, int response)
-{
-	struct controlvm_message outmsg;
-
-	controlvm_init_response(&outmsg, msg_hdr, response);
-	if (outmsg.hdr.flags.test_message == 1)
-		return;
-
-	if (!visorchannel_signalinsert(controlvm_channel,
-				       CONTROLVM_QUEUE_REQUEST, &outmsg)) {
-		return;
-	}
-}
-
-static void
-controlvm_respond_chipset_init(struct controlvm_message_header *msg_hdr,
-			       int response,
-			       enum ultra_chipset_feature features)
-{
-	struct controlvm_message outmsg;
-
-	controlvm_init_response(&outmsg, msg_hdr, response);
-	outmsg.cmd.init_chipset.features = features;
-	if (!visorchannel_signalinsert(controlvm_channel,
-				       CONTROLVM_QUEUE_REQUEST, &outmsg)) {
-		return;
-	}
-}
-
-static void controlvm_respond_physdev_changestate(
-		struct controlvm_message_header *msg_hdr, int response,
-		struct spar_segment_state state)
-{
-	struct controlvm_message outmsg;
-
-	controlvm_init_response(&outmsg, msg_hdr, response);
-	outmsg.cmd.device_change_state.state = state;
-	outmsg.cmd.device_change_state.flags.phys_device = 1;
-	if (!visorchannel_signalinsert(controlvm_channel,
-				       CONTROLVM_QUEUE_REQUEST, &outmsg)) {
-		return;
-	}
-}
-
-enum crash_obj_type {
-	CRASH_DEV,
-	CRASH_BUS,
-};
-
-static void
-save_crash_message(struct controlvm_message *msg, enum crash_obj_type typ)
-{
-	u32 local_crash_msg_offset;
-	u16 local_crash_msg_count;
-
-	if (visorchannel_read(controlvm_channel,
-			      offsetof(struct spar_controlvm_channel_protocol,
-				       saved_crash_message_count),
-			      &local_crash_msg_count, sizeof(u16)) < 0) {
-		POSTCODE_LINUX_2(CRASH_DEV_CTRL_RD_FAILURE_PC,
-				 POSTCODE_SEVERITY_ERR);
-		return;
-	}
-
-	if (local_crash_msg_count != CONTROLVM_CRASHMSG_MAX) {
-		POSTCODE_LINUX_3(CRASH_DEV_COUNT_FAILURE_PC,
-				 local_crash_msg_count,
-				 POSTCODE_SEVERITY_ERR);
-		return;
-	}
-
-	if (visorchannel_read(controlvm_channel,
-			      offsetof(struct spar_controlvm_channel_protocol,
-				       saved_crash_message_offset),
-			      &local_crash_msg_offset, sizeof(u32)) < 0) {
-		POSTCODE_LINUX_2(CRASH_DEV_CTRL_RD_FAILURE_PC,
-				 POSTCODE_SEVERITY_ERR);
-		return;
-	}
-
-	if (typ == CRASH_BUS) {
-		if (visorchannel_write(controlvm_channel,
-				       local_crash_msg_offset,
-				       msg,
-				       sizeof(struct controlvm_message)) < 0) {
-			POSTCODE_LINUX_2(SAVE_MSG_BUS_FAILURE_PC,
-					 POSTCODE_SEVERITY_ERR);
-			return;
-		}
-	} else {
-		local_crash_msg_offset += sizeof(struct controlvm_message);
-		if (visorchannel_write(controlvm_channel,
-				       local_crash_msg_offset,
-				       msg,
-				       sizeof(struct controlvm_message)) < 0) {
-			POSTCODE_LINUX_2(SAVE_MSG_DEV_FAILURE_PC,
-					 POSTCODE_SEVERITY_ERR);
-			return;
-		}
-	}
-}
-
-static void
-bus_responder(enum controlvm_id cmd_id,
-	      struct controlvm_message_header *pending_msg_hdr,
-	      int response)
-{
-	if (!pending_msg_hdr)
-		return;		/* no controlvm response needed */
-
-	if (pending_msg_hdr->id != (u32)cmd_id)
-		return;
-
-	controlvm_respond(pending_msg_hdr, response);
-}
-
-static void
-device_changestate_responder(enum controlvm_id cmd_id,
-			     struct visor_device *p, int response,
-			     struct spar_segment_state response_state)
-{
-	struct controlvm_message outmsg;
-	u32 bus_no = p->chipset_bus_no;
-	u32 dev_no = p->chipset_dev_no;
-
-	if (!p->pending_msg_hdr)
-		return;		/* no controlvm response needed */
-	if (p->pending_msg_hdr->id != cmd_id)
-		return;
-
-	controlvm_init_response(&outmsg, p->pending_msg_hdr, response);
-
-	outmsg.cmd.device_change_state.bus_no = bus_no;
-	outmsg.cmd.device_change_state.dev_no = dev_no;
-	outmsg.cmd.device_change_state.state = response_state;
-
-	if (!visorchannel_signalinsert(controlvm_channel,
-				       CONTROLVM_QUEUE_REQUEST, &outmsg))
-		return;
-}
-
-static void
-device_responder(enum controlvm_id cmd_id,
-		 struct controlvm_message_header *pending_msg_hdr,
-		 int response)
-{
-	if (!pending_msg_hdr)
-		return;		/* no controlvm response needed */
-
-	if (pending_msg_hdr->id != (u32)cmd_id)
-		return;
-
-	controlvm_respond(pending_msg_hdr, response);
-}
-
-static void
-bus_epilog(struct visor_device *bus_info,
-	   u32 cmd, struct controlvm_message_header *msg_hdr,
-	   int response, bool need_response)
-{
-	struct controlvm_message_header *pmsg_hdr = NULL;
-
-	down(&notifier_lock);
-
-	if (!bus_info) {
-		/* relying on a valid passed in response code */
-		/* be lazy and re-use msg_hdr for this failure, is this ok?? */
-		pmsg_hdr = msg_hdr;
-		goto out_respond_and_unlock;
-	}
-
-	if (bus_info->pending_msg_hdr) {
-		/* only non-NULL if dev is still waiting on a response */
-		response = -CONTROLVM_RESP_ERROR_MESSAGE_ID_INVALID_FOR_CLIENT;
-		pmsg_hdr = bus_info->pending_msg_hdr;
-		goto out_respond_and_unlock;
-	}
-
-	if (need_response) {
-		pmsg_hdr = kzalloc(sizeof(*pmsg_hdr), GFP_KERNEL);
-		if (!pmsg_hdr) {
-			POSTCODE_LINUX_4(MALLOC_FAILURE_PC, cmd,
-					 bus_info->chipset_bus_no,
-					 POSTCODE_SEVERITY_ERR);
-			goto out_unlock;
-		}
-
-		memcpy(pmsg_hdr, msg_hdr,
-		       sizeof(struct controlvm_message_header));
-		bus_info->pending_msg_hdr = pmsg_hdr;
-	}
-
-	if (response == CONTROLVM_RESP_SUCCESS) {
-		switch (cmd) {
-		case CONTROLVM_BUS_CREATE:
-			if (busdev_notifiers.bus_create) {
-				(*busdev_notifiers.bus_create) (bus_info);
-				goto out_unlock;
-			}
-			break;
-		case CONTROLVM_BUS_DESTROY:
-			if (busdev_notifiers.bus_destroy) {
-				(*busdev_notifiers.bus_destroy) (bus_info);
-				goto out_unlock;
-			}
-			break;
-		}
-	}
-
-out_respond_and_unlock:
-	bus_responder(cmd, pmsg_hdr, response);
-
-out_unlock:
-	up(&notifier_lock);
-}
-
-static void
-device_epilog(struct visor_device *dev_info,
-	      struct spar_segment_state state, u32 cmd,
-	      struct controlvm_message_header *msg_hdr, int response,
-	      bool need_response, bool for_visorbus)
-{
-	struct visorchipset_busdev_notifiers *notifiers;
-	struct controlvm_message_header *pmsg_hdr = NULL;
-
-	notifiers = &busdev_notifiers;
-
-	down(&notifier_lock);
-	if (!dev_info) {
-		/* relying on a valid passed in response code */
-		/* be lazy and re-use msg_hdr for this failure, is this ok?? */
-		pmsg_hdr = msg_hdr;
-		goto out_respond_and_unlock;
-	}
-
-	if (dev_info->pending_msg_hdr) {
-		/* only non-NULL if dev is still waiting on a response */
-		response = -CONTROLVM_RESP_ERROR_MESSAGE_ID_INVALID_FOR_CLIENT;
-		pmsg_hdr = dev_info->pending_msg_hdr;
-		goto out_respond_and_unlock;
-	}
-
-	if (need_response) {
-		pmsg_hdr = kzalloc(sizeof(*pmsg_hdr), GFP_KERNEL);
-		if (!pmsg_hdr) {
-			response = -CONTROLVM_RESP_ERROR_KMALLOC_FAILED;
-			goto out_respond_and_unlock;
-		}
-
-		memcpy(pmsg_hdr, msg_hdr,
-		       sizeof(struct controlvm_message_header));
-		dev_info->pending_msg_hdr = pmsg_hdr;
-	}
-
-	if (response >= 0) {
-		switch (cmd) {
-		case CONTROLVM_DEVICE_CREATE:
-			if (notifiers->device_create) {
-				(*notifiers->device_create) (dev_info);
-				goto out_unlock;
-			}
-			break;
-		case CONTROLVM_DEVICE_CHANGESTATE:
-			/* ServerReady / ServerRunning / SegmentStateRunning */
-			if (state.alive == segment_state_running.alive &&
-			    state.operating ==
-				segment_state_running.operating) {
-				if (notifiers->device_resume) {
-					(*notifiers->device_resume) (dev_info);
-					goto out_unlock;
-				}
-			}
-			/* ServerNotReady / ServerLost / SegmentStateStandby */
-			else if (state.alive == segment_state_standby.alive &&
-				 state.operating ==
-				 segment_state_standby.operating) {
-				/* technically this is standby case
-				 * where server is lost
-				 */
-				if (notifiers->device_pause) {
-					(*notifiers->device_pause) (dev_info);
-					goto out_unlock;
-				}
-			}
-			break;
-		case CONTROLVM_DEVICE_DESTROY:
-			if (notifiers->device_destroy) {
-				(*notifiers->device_destroy) (dev_info);
-				goto out_unlock;
-			}
-			break;
-		}
-	}
-
-out_respond_and_unlock:
-	device_responder(cmd, pmsg_hdr, response);
-
-out_unlock:
-	up(&notifier_lock);
-}
-
-static void
-bus_create(struct controlvm_message *inmsg)
-{
-	struct controlvm_message_packet *cmd = &inmsg->cmd;
-	u32 bus_no = cmd->create_bus.bus_no;
-	int rc = CONTROLVM_RESP_SUCCESS;
-	struct visor_device *bus_info;
-	struct visorchannel *visorchannel;
-
-	bus_info = visorbus_get_device_by_id(bus_no, BUS_ROOT_DEVICE, NULL);
-	if (bus_info && (bus_info->state.created == 1)) {
-		POSTCODE_LINUX_3(BUS_CREATE_FAILURE_PC, bus_no,
-				 POSTCODE_SEVERITY_ERR);
-		rc = -CONTROLVM_RESP_ERROR_ALREADY_DONE;
-		goto out_bus_epilog;
-	}
-	bus_info = kzalloc(sizeof(*bus_info), GFP_KERNEL);
-	if (!bus_info) {
-		POSTCODE_LINUX_3(BUS_CREATE_FAILURE_PC, bus_no,
-				 POSTCODE_SEVERITY_ERR);
-		rc = -CONTROLVM_RESP_ERROR_KMALLOC_FAILED;
-		goto out_bus_epilog;
-	}
-
-	INIT_LIST_HEAD(&bus_info->list_all);
-	bus_info->chipset_bus_no = bus_no;
-	bus_info->chipset_dev_no = BUS_ROOT_DEVICE;
-
-	POSTCODE_LINUX_3(BUS_CREATE_ENTRY_PC, bus_no, POSTCODE_SEVERITY_INFO);
-
-	visorchannel = visorchannel_create(cmd->create_bus.channel_addr,
-					   cmd->create_bus.channel_bytes,
-					   GFP_KERNEL,
-					   cmd->create_bus.bus_data_type_uuid);
-
-	if (!visorchannel) {
-		POSTCODE_LINUX_3(BUS_CREATE_FAILURE_PC, bus_no,
-				 POSTCODE_SEVERITY_ERR);
-		rc = -CONTROLVM_RESP_ERROR_KMALLOC_FAILED;
-		kfree(bus_info);
-		bus_info = NULL;
-		goto out_bus_epilog;
-	}
-	bus_info->visorchannel = visorchannel;
-	if (uuid_le_cmp(cmd->create_bus.bus_inst_uuid, spar_siovm_uuid) == 0) {
-		dump_vhba_bus = bus_no;
-		save_crash_message(inmsg, CRASH_BUS);
-	}
-
-	POSTCODE_LINUX_3(BUS_CREATE_EXIT_PC, bus_no, POSTCODE_SEVERITY_INFO);
-
-out_bus_epilog:
-	bus_epilog(bus_info, CONTROLVM_BUS_CREATE, &inmsg->hdr,
-		   rc, inmsg->hdr.flags.response_expected == 1);
-}
-
-static void
-bus_destroy(struct controlvm_message *inmsg)
-{
-	struct controlvm_message_packet *cmd = &inmsg->cmd;
-	u32 bus_no = cmd->destroy_bus.bus_no;
-	struct visor_device *bus_info;
-	int rc = CONTROLVM_RESP_SUCCESS;
-
-	bus_info = visorbus_get_device_by_id(bus_no, BUS_ROOT_DEVICE, NULL);
-	if (!bus_info)
-		rc = -CONTROLVM_RESP_ERROR_BUS_INVALID;
-	else if (bus_info->state.created == 0)
-		rc = -CONTROLVM_RESP_ERROR_ALREADY_DONE;
-
-	bus_epilog(bus_info, CONTROLVM_BUS_DESTROY, &inmsg->hdr,
-		   rc, inmsg->hdr.flags.response_expected == 1);
-
-	/* bus_info is freed as part of the busdevice_release function */
-}
-
-static void
-bus_configure(struct controlvm_message *inmsg,
-	      struct parser_context *parser_ctx)
-{
-	struct controlvm_message_packet *cmd = &inmsg->cmd;
-	u32 bus_no;
-	struct visor_device *bus_info;
-	int rc = CONTROLVM_RESP_SUCCESS;
-
-	bus_no = cmd->configure_bus.bus_no;
-	POSTCODE_LINUX_3(BUS_CONFIGURE_ENTRY_PC, bus_no,
-			 POSTCODE_SEVERITY_INFO);
-
-	bus_info = visorbus_get_device_by_id(bus_no, BUS_ROOT_DEVICE, NULL);
-	if (!bus_info) {
-		POSTCODE_LINUX_3(BUS_CONFIGURE_FAILURE_PC, bus_no,
-				 POSTCODE_SEVERITY_ERR);
-		rc = -CONTROLVM_RESP_ERROR_BUS_INVALID;
-	} else if (bus_info->state.created == 0) {
-		POSTCODE_LINUX_3(BUS_CONFIGURE_FAILURE_PC, bus_no,
-				 POSTCODE_SEVERITY_ERR);
-		rc = -CONTROLVM_RESP_ERROR_BUS_INVALID;
-	} else if (bus_info->pending_msg_hdr) {
-		POSTCODE_LINUX_3(BUS_CONFIGURE_FAILURE_PC, bus_no,
-				 POSTCODE_SEVERITY_ERR);
-		rc = -CONTROLVM_RESP_ERROR_MESSAGE_ID_INVALID_FOR_CLIENT;
-	} else {
-		visorchannel_set_clientpartition
-			(bus_info->visorchannel,
-			 cmd->configure_bus.guest_handle);
-		bus_info->partition_uuid = parser_id_get(parser_ctx);
-		parser_param_start(parser_ctx, PARSERSTRING_NAME);
-		bus_info->name = parser_string_get(parser_ctx);
-
-		POSTCODE_LINUX_3(BUS_CONFIGURE_EXIT_PC, bus_no,
-				 POSTCODE_SEVERITY_INFO);
-	}
-	bus_epilog(bus_info, CONTROLVM_BUS_CONFIGURE, &inmsg->hdr,
-		   rc, inmsg->hdr.flags.response_expected == 1);
-}
-
-static void
-my_device_create(struct controlvm_message *inmsg)
-{
-	struct controlvm_message_packet *cmd = &inmsg->cmd;
-	u32 bus_no = cmd->create_device.bus_no;
-	u32 dev_no = cmd->create_device.dev_no;
-	struct visor_device *dev_info = NULL;
-	struct visor_device *bus_info;
-	struct visorchannel *visorchannel;
-	int rc = CONTROLVM_RESP_SUCCESS;
-
-	bus_info = visorbus_get_device_by_id(bus_no, BUS_ROOT_DEVICE, NULL);
-	if (!bus_info) {
-		POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, dev_no, bus_no,
-				 POSTCODE_SEVERITY_ERR);
-		rc = -CONTROLVM_RESP_ERROR_BUS_INVALID;
-		goto out_respond;
-	}
-
-	if (bus_info->state.created == 0) {
-		POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, dev_no, bus_no,
-				 POSTCODE_SEVERITY_ERR);
-		rc = -CONTROLVM_RESP_ERROR_BUS_INVALID;
-		goto out_respond;
-	}
-
-	dev_info = visorbus_get_device_by_id(bus_no, dev_no, NULL);
-	if (dev_info && (dev_info->state.created == 1)) {
-		POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, dev_no, bus_no,
-				 POSTCODE_SEVERITY_ERR);
-		rc = -CONTROLVM_RESP_ERROR_ALREADY_DONE;
-		goto out_respond;
-	}
-
-	dev_info = kzalloc(sizeof(*dev_info), GFP_KERNEL);
-	if (!dev_info) {
-		POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, dev_no, bus_no,
-				 POSTCODE_SEVERITY_ERR);
-		rc = -CONTROLVM_RESP_ERROR_KMALLOC_FAILED;
-		goto out_respond;
-	}
-
-	dev_info->chipset_bus_no = bus_no;
-	dev_info->chipset_dev_no = dev_no;
-	dev_info->inst = cmd->create_device.dev_inst_uuid;
-
-	/* not sure where the best place to set the 'parent' */
-	dev_info->device.parent = &bus_info->device;
-
-	POSTCODE_LINUX_4(DEVICE_CREATE_ENTRY_PC, dev_no, bus_no,
-			 POSTCODE_SEVERITY_INFO);
-
-	visorchannel =
-	       visorchannel_create_with_lock(cmd->create_device.channel_addr,
-					     cmd->create_device.channel_bytes,
-					     GFP_KERNEL,
-					     cmd->create_device.data_type_uuid);
-
-	if (!visorchannel) {
-		POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, dev_no, bus_no,
-				 POSTCODE_SEVERITY_ERR);
-		rc = -CONTROLVM_RESP_ERROR_KMALLOC_FAILED;
-		kfree(dev_info);
-		dev_info = NULL;
-		goto out_respond;
-	}
-	dev_info->visorchannel = visorchannel;
-	dev_info->channel_type_guid = cmd->create_device.data_type_uuid;
-	if (uuid_le_cmp(cmd->create_device.data_type_uuid,
-			spar_vhba_channel_protocol_uuid) == 0)
-		save_crash_message(inmsg, CRASH_DEV);
-
-	POSTCODE_LINUX_4(DEVICE_CREATE_EXIT_PC, dev_no, bus_no,
-			 POSTCODE_SEVERITY_INFO);
-out_respond:
-	device_epilog(dev_info, segment_state_running,
-		      CONTROLVM_DEVICE_CREATE, &inmsg->hdr, rc,
-		      inmsg->hdr.flags.response_expected == 1, 1);
-}
-
-static void
-my_device_changestate(struct controlvm_message *inmsg)
-{
-	struct controlvm_message_packet *cmd = &inmsg->cmd;
-	u32 bus_no = cmd->device_change_state.bus_no;
-	u32 dev_no = cmd->device_change_state.dev_no;
-	struct spar_segment_state state = cmd->device_change_state.state;
-	struct visor_device *dev_info;
-	int rc = CONTROLVM_RESP_SUCCESS;
-
-	dev_info = visorbus_get_device_by_id(bus_no, dev_no, NULL);
-	if (!dev_info) {
-		POSTCODE_LINUX_4(DEVICE_CHANGESTATE_FAILURE_PC, dev_no, bus_no,
-				 POSTCODE_SEVERITY_ERR);
-		rc = -CONTROLVM_RESP_ERROR_DEVICE_INVALID;
-	} else if (dev_info->state.created == 0) {
-		POSTCODE_LINUX_4(DEVICE_CHANGESTATE_FAILURE_PC, dev_no, bus_no,
-				 POSTCODE_SEVERITY_ERR);
-		rc = -CONTROLVM_RESP_ERROR_DEVICE_INVALID;
-	}
-	if ((rc >= CONTROLVM_RESP_SUCCESS) && dev_info)
-		device_epilog(dev_info, state,
-			      CONTROLVM_DEVICE_CHANGESTATE, &inmsg->hdr, rc,
-			      inmsg->hdr.flags.response_expected == 1, 1);
-}
-
-static void
-my_device_destroy(struct controlvm_message *inmsg)
-{
-	struct controlvm_message_packet *cmd = &inmsg->cmd;
-	u32 bus_no = cmd->destroy_device.bus_no;
-	u32 dev_no = cmd->destroy_device.dev_no;
-	struct visor_device *dev_info;
-	int rc = CONTROLVM_RESP_SUCCESS;
-
-	dev_info = visorbus_get_device_by_id(bus_no, dev_no, NULL);
-	if (!dev_info)
-		rc = -CONTROLVM_RESP_ERROR_DEVICE_INVALID;
-	else if (dev_info->state.created == 0)
-		rc = -CONTROLVM_RESP_ERROR_ALREADY_DONE;
-
-	if ((rc >= CONTROLVM_RESP_SUCCESS) && dev_info)
-		device_epilog(dev_info, segment_state_running,
-			      CONTROLVM_DEVICE_DESTROY, &inmsg->hdr, rc,
-			      inmsg->hdr.flags.response_expected == 1, 1);
-}
-
-/* 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(u64 phys_addr, u64 offset, u32 bytes,
-				  struct visor_controlvm_payload_info *info)
-{
-	u8 *payload = NULL;
-
-	if (!info)
-		return -CONTROLVM_RESP_ERROR_PAYLOAD_INVALID;
-
-	memset(info, 0, sizeof(struct visor_controlvm_payload_info));
-	if ((offset == 0) || (bytes == 0))
-		return -CONTROLVM_RESP_ERROR_PAYLOAD_INVALID;
-
-	payload = memremap(phys_addr + offset, bytes, MEMREMAP_WB);
-	if (!payload)
-		return -CONTROLVM_RESP_ERROR_IOREMAP_FAILED;
-
-	info->offset = offset;
-	info->bytes = bytes;
-	info->ptr = payload;
-
-	return CONTROLVM_RESP_SUCCESS;
-}
-
-static void
-destroy_controlvm_payload_info(struct visor_controlvm_payload_info *info)
-{
-	if (info->ptr) {
-		memunmap(info->ptr);
-		info->ptr = NULL;
-	}
-	memset(info, 0, sizeof(struct visor_controlvm_payload_info));
-}
-
-static void
-initialize_controlvm_payload(void)
-{
-	u64 phys_addr = visorchannel_get_physaddr(controlvm_channel);
-	u64 payload_offset = 0;
-	u32 payload_bytes = 0;
-
-	if (visorchannel_read(controlvm_channel,
-			      offsetof(struct spar_controlvm_channel_protocol,
-				       request_payload_offset),
-			      &payload_offset, sizeof(payload_offset)) < 0) {
-		POSTCODE_LINUX_2(CONTROLVM_INIT_FAILURE_PC,
-				 POSTCODE_SEVERITY_ERR);
-		return;
-	}
-	if (visorchannel_read(controlvm_channel,
-			      offsetof(struct spar_controlvm_channel_protocol,
-				       request_payload_bytes),
-			      &payload_bytes, sizeof(payload_bytes)) < 0) {
-		POSTCODE_LINUX_2(CONTROLVM_INIT_FAILURE_PC,
-				 POSTCODE_SEVERITY_ERR);
-		return;
-	}
-	initialize_controlvm_payload_info(phys_addr,
-					  payload_offset, payload_bytes,
-					  &controlvm_payload_info);
-}
-
-/*  Send ACTION=online for DEVPATH=/sys/devices/platform/visorchipset.
- *  Returns CONTROLVM_RESP_xxx code.
- */
-static int
-visorchipset_chipset_ready(void)
-{
-	kobject_uevent(&visorchipset_platform_device.dev.kobj, KOBJ_ONLINE);
-	return CONTROLVM_RESP_SUCCESS;
-}
-
-static 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;
-}
-
-/*  Send ACTION=offline for DEVPATH=/sys/devices/platform/visorchipset.
- *  Returns CONTROLVM_RESP_xxx code.
- */
-static int
-visorchipset_chipset_notready(void)
-{
-	kobject_uevent(&visorchipset_platform_device.dev.kobj, KOBJ_OFFLINE);
-	return CONTROLVM_RESP_SUCCESS;
-}
-
-static void
-chipset_ready(struct controlvm_message_header *msg_hdr)
-{
-	int rc = visorchipset_chipset_ready();
-
-	if (rc != CONTROLVM_RESP_SUCCESS)
-		rc = -rc;
-	if (msg_hdr->flags.response_expected)
-		controlvm_respond(msg_hdr, rc);
-}
-
-static void
-chipset_selftest(struct controlvm_message_header *msg_hdr)
-{
-	int rc = visorchipset_chipset_selftest();
-
-	if (rc != CONTROLVM_RESP_SUCCESS)
-		rc = -rc;
-	if (msg_hdr->flags.response_expected)
-		controlvm_respond(msg_hdr, rc);
-}
-
-static void
-chipset_notready(struct controlvm_message_header *msg_hdr)
-{
-	int rc = visorchipset_chipset_notready();
-
-	if (rc != CONTROLVM_RESP_SUCCESS)
-		rc = -rc;
-	if (msg_hdr->flags.response_expected)
-		controlvm_respond(msg_hdr, 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(struct controlvm_message *msg)
-{
-	if (visorchannel_signalremove(controlvm_channel,
-				      CONTROLVM_QUEUE_EVENT, msg)) {
-		/* got a message */
-		if (msg->hdr.flags.test_message == 1)
-			return false;
-		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 + msecs_to_jiffies(PARAHOTPLUG_TIMEOUT_MS);
-}
-
-/*
- * 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(struct controlvm_message *msg)
-{
-	struct parahotplug_request *req;
-
-	req = kmalloc(sizeof(*req), GFP_KERNEL | __GFP_NORETRY);
-	if (!req)
-		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)
-{
-	struct 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->device_change_state.state.active);
-	sprintf(env_bus, "SPAR_PARAHOTPLUG_BUS=%d",
-		cmd->device_change_state.bus_no);
-	sprintf(env_dev, "SPAR_PARAHOTPLUG_DEVICE=%d",
-		cmd->device_change_state.dev_no >> 3);
-	sprintf(env_func, "SPAR_PARAHOTPLUG_FUNCTION=%d",
-		cmd->device_change_state.dev_no & 0x7);
-
-	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;
-	struct list_head *tmp;
-
-	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))
-			continue;
-
-		list_del(pos);
-		if (req->msg.hdr.flags.response_expected)
-			controlvm_respond_physdev_changestate(
-				&req->msg.hdr,
-				CONTROLVM_RESP_ERROR_DEVICE_UDEV_TIMEOUT,
-				req->msg.cmd.device_change_state.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;
-	struct list_head *tmp;
-
-	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.device_change_state.state.active = active;
-			if (req->msg.hdr.flags.response_expected)
-				controlvm_respond_physdev_changestate(
-					&req->msg.hdr, CONTROLVM_RESP_SUCCESS,
-					req->msg.cmd.device_change_state.state);
-			parahotplug_request_destroy(req);
-			return 0;
-		}
-	}
-
-	spin_unlock(&parahotplug_request_list_lock);
-	return -EINVAL;
-}
-
-/*
- * Enables or disables a PCI device by kicking off a udev script
- */
-static void
-parahotplug_process_message(struct controlvm_message *inmsg)
-{
-	struct parahotplug_request *req;
-
-	req = parahotplug_request_create(inmsg);
-
-	if (!req)
-		return;
-
-	if (inmsg->cmd.device_change_state.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.device_change_state.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);
-	}
-}
-
-/* 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(struct controlvm_message inmsg, u64 channel_addr)
-{
-	struct controlvm_message_packet *cmd = &inmsg.cmd;
-	u64 parm_addr;
-	u32 parm_bytes;
-	struct parser_context *parser_ctx = NULL;
-	bool local_addr;
-	struct controlvm_message ackmsg;
-
-	/* create parsing context if necessary */
-	local_addr = (inmsg.hdr.flags.test_message == 1);
-	if (channel_addr == 0)
-		return true;
-	parm_addr = channel_addr + inmsg.hdr.payload_vm_offset;
-	parm_bytes = inmsg.hdr.payload_bytes;
-
-	/* 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 (parm_addr && parm_bytes) {
-		bool retry = false;
-
-		parser_ctx =
-		    parser_init_byte_stream(parm_addr, parm_bytes,
-					    local_addr, &retry);
-		if (!parser_ctx && retry)
-			return false;
-	}
-
-	if (!local_addr) {
-		controlvm_init_response(&ackmsg, &inmsg.hdr,
-					CONTROLVM_RESP_SUCCESS);
-		if (controlvm_channel)
-			visorchannel_signalinsert(controlvm_channel,
-						  CONTROLVM_QUEUE_ACK,
-						  &ackmsg);
-	}
-	switch (inmsg.hdr.id) {
-	case CONTROLVM_CHIPSET_INIT:
-		chipset_init(&inmsg);
-		break;
-	case CONTROLVM_BUS_CREATE:
-		bus_create(&inmsg);
-		break;
-	case CONTROLVM_BUS_DESTROY:
-		bus_destroy(&inmsg);
-		break;
-	case CONTROLVM_BUS_CONFIGURE:
-		bus_configure(&inmsg, parser_ctx);
-		break;
-	case CONTROLVM_DEVICE_CREATE:
-		my_device_create(&inmsg);
-		break;
-	case CONTROLVM_DEVICE_CHANGESTATE:
-		if (cmd->device_change_state.flags.phys_device) {
-			parahotplug_process_message(&inmsg);
-		} else {
-			/* save the hdr and cmd structures for later use */
-			/* when sending back the response to Command */
-			my_device_changestate(&inmsg);
-			g_devicechangestate_packet = inmsg.cmd;
-			break;
-		}
-		break;
-	case CONTROLVM_DEVICE_DESTROY:
-		my_device_destroy(&inmsg);
-		break;
-	case CONTROLVM_DEVICE_CONFIGURE:
-		/* no op for now, just send a respond that we passed */
-		if (inmsg.hdr.flags.response_expected)
-			controlvm_respond(&inmsg.hdr, CONTROLVM_RESP_SUCCESS);
-		break;
-	case CONTROLVM_CHIPSET_READY:
-		chipset_ready(&inmsg.hdr);
-		break;
-	case CONTROLVM_CHIPSET_SELFTEST:
-		chipset_selftest(&inmsg.hdr);
-		break;
-	case CONTROLVM_CHIPSET_STOP:
-		chipset_notready(&inmsg.hdr);
-		break;
-	default:
-		if (inmsg.hdr.flags.response_expected)
-			controlvm_respond
-				(&inmsg.hdr,
-				 -CONTROLVM_RESP_ERROR_MESSAGE_ID_UNKNOWN);
-		break;
-	}
-
-	if (parser_ctx) {
-		parser_done(parser_ctx);
-		parser_ctx = NULL;
-	}
-	return true;
-}
-
-static inline unsigned int
-issue_vmcall_io_controlvm_addr(u64 *control_addr, u32 *control_bytes)
-{
-	struct 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)) {
-		*control_addr = params.address;
-		*control_bytes = params.channel_bytes;
-	}
-	return result;
-}
-
-static u64 controlvm_get_channel_address(void)
-{
-	u64 addr = 0;
-	u32 size = 0;
-
-	if (!VMCALL_SUCCESSFUL(issue_vmcall_io_controlvm_addr(&addr, &size)))
-		return 0;
-
-	return addr;
-}
-
-static void
-controlvm_periodic_work(struct work_struct *work)
-{
-	struct controlvm_message inmsg;
-	bool got_command = false;
-	bool handle_command_failed = false;
-
-	/* make sure visorbus server is registered for controlvm callbacks */
-	if (visorchipset_visorbusregwait && !visorbusregistered)
-		goto cleanup;
-
-	while (visorchannel_signalremove(controlvm_channel,
-					 CONTROLVM_QUEUE_RESPONSE,
-					 &inmsg))
-		;
-	if (!got_command) {
-		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;
-			got_command = true;
-		} else {
-			got_command = read_controlvm_event(&inmsg);
-		}
-	}
-
-	handle_command_failed = false;
-	while (got_command && (!handle_command_failed)) {
-		most_recent_message_jiffies = jiffies;
-		if (handle_command(inmsg,
-				   visorchannel_get_physaddr
-				   (controlvm_channel)))
-			got_command = 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;
-		}
-	}
-
-	/* parahotplug_worker */
-	parahotplug_process_list();
-
-cleanup:
-
-	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)
-			poll_jiffies = POLLJIFFIES_CONTROLVMCHANNEL_SLOW;
-	} else {
-		if (poll_jiffies != POLLJIFFIES_CONTROLVMCHANNEL_FAST)
-			poll_jiffies = POLLJIFFIES_CONTROLVMCHANNEL_FAST;
-	}
-
-	schedule_delayed_work(&periodic_controlvm_work, poll_jiffies);
-}
-
-static void
-setup_crash_devices_work_queue(struct work_struct *work)
-{
-	struct controlvm_message local_crash_bus_msg;
-	struct controlvm_message local_crash_dev_msg;
-	struct controlvm_message msg;
-	u32 local_crash_msg_offset;
-	u16 local_crash_msg_count;
-
-	/* make sure visorbus is registered for controlvm callbacks */
-	if (visorchipset_visorbusregwait && !visorbusregistered) {
-		poll_jiffies = POLLJIFFIES_CONTROLVMCHANNEL_SLOW;
-		schedule_delayed_work(&periodic_controlvm_work, poll_jiffies);
-		return;
-	}
-
-	POSTCODE_LINUX_2(CRASH_DEV_ENTRY_PC, POSTCODE_SEVERITY_INFO);
-
-	/* send init chipset msg */
-	msg.hdr.id = CONTROLVM_CHIPSET_INIT;
-	msg.cmd.init_chipset.bus_count = 23;
-	msg.cmd.init_chipset.switch_count = 0;
-
-	chipset_init(&msg);
-
-	/* get saved message count */
-	if (visorchannel_read(controlvm_channel,
-			      offsetof(struct spar_controlvm_channel_protocol,
-				       saved_crash_message_count),
-			      &local_crash_msg_count, sizeof(u16)) < 0) {
-		POSTCODE_LINUX_2(CRASH_DEV_CTRL_RD_FAILURE_PC,
-				 POSTCODE_SEVERITY_ERR);
-		return;
-	}
-
-	if (local_crash_msg_count != CONTROLVM_CRASHMSG_MAX) {
-		POSTCODE_LINUX_3(CRASH_DEV_COUNT_FAILURE_PC,
-				 local_crash_msg_count,
-				 POSTCODE_SEVERITY_ERR);
-		return;
-	}
-
-	/* get saved crash message offset */
-	if (visorchannel_read(controlvm_channel,
-			      offsetof(struct spar_controlvm_channel_protocol,
-				       saved_crash_message_offset),
-			      &local_crash_msg_offset, sizeof(u32)) < 0) {
-		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,
-			      local_crash_msg_offset,
-			      &local_crash_bus_msg,
-			      sizeof(struct controlvm_message)) < 0) {
-		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,
-			      local_crash_msg_offset +
-			      sizeof(struct controlvm_message),
-			      &local_crash_dev_msg,
-			      sizeof(struct controlvm_message)) < 0) {
-		POSTCODE_LINUX_2(CRASH_DEV_RD_DEV_FAIULRE_PC,
-				 POSTCODE_SEVERITY_ERR);
-		return;
-	}
-
-	/* reuse IOVM create bus message */
-	if (local_crash_bus_msg.cmd.create_bus.channel_addr) {
-		bus_create(&local_crash_bus_msg);
-	} else {
-		POSTCODE_LINUX_2(CRASH_DEV_BUS_NULL_FAILURE_PC,
-				 POSTCODE_SEVERITY_ERR);
-		return;
-	}
-
-	/* reuse create device message for storage device */
-	if (local_crash_dev_msg.cmd.create_device.channel_addr) {
-		my_device_create(&local_crash_dev_msg);
-	} else {
-		POSTCODE_LINUX_2(CRASH_DEV_DEV_NULL_FAILURE_PC,
-				 POSTCODE_SEVERITY_ERR);
-		return;
-	}
-	POSTCODE_LINUX_2(CRASH_DEV_EXIT_PC, POSTCODE_SEVERITY_INFO);
-}
-
-static void
-bus_create_response(struct visor_device *bus_info, int response)
-{
-	if (response >= 0)
-		bus_info->state.created = 1;
-
-	bus_responder(CONTROLVM_BUS_CREATE, bus_info->pending_msg_hdr,
-		      response);
-
-	kfree(bus_info->pending_msg_hdr);
-	bus_info->pending_msg_hdr = NULL;
-}
-
-static void
-bus_destroy_response(struct visor_device *bus_info, int response)
-{
-	bus_responder(CONTROLVM_BUS_DESTROY, bus_info->pending_msg_hdr,
-		      response);
-
-	kfree(bus_info->pending_msg_hdr);
-	bus_info->pending_msg_hdr = NULL;
-}
-
-static void
-device_create_response(struct visor_device *dev_info, int response)
-{
-	if (response >= 0)
-		dev_info->state.created = 1;
-
-	device_responder(CONTROLVM_DEVICE_CREATE, dev_info->pending_msg_hdr,
-			 response);
-
-	kfree(dev_info->pending_msg_hdr);
-	dev_info->pending_msg_hdr = NULL;
-}
-
-static void
-device_destroy_response(struct visor_device *dev_info, int response)
-{
-	device_responder(CONTROLVM_DEVICE_DESTROY, dev_info->pending_msg_hdr,
-			 response);
-
-	kfree(dev_info->pending_msg_hdr);
-	dev_info->pending_msg_hdr = NULL;
-}
-
-static void
-visorchipset_device_pause_response(struct visor_device *dev_info,
-				   int response)
-{
-	device_changestate_responder(CONTROLVM_DEVICE_CHANGESTATE,
-				     dev_info, response,
-				     segment_state_standby);
-
-	kfree(dev_info->pending_msg_hdr);
-	dev_info->pending_msg_hdr = NULL;
-}
-
-static void
-device_resume_response(struct visor_device *dev_info, int response)
-{
-	device_changestate_responder(CONTROLVM_DEVICE_CHANGESTATE,
-				     dev_info, response,
-				     segment_state_running);
-
-	kfree(dev_info->pending_msg_hdr);
-	dev_info->pending_msg_hdr = NULL;
-}
-
-/* The parahotplug/devicedisabled interface gets called by our support script
- * when an SR-IOV device has been shut down. The ID is passed to the script
- * and then passed back when the device has been removed.
- */
-static ssize_t devicedisabled_store(struct device *dev,
-				    struct device_attribute *attr,
-				    const char *buf, size_t count)
-{
-	unsigned int id;
-
-	if (kstrtouint(buf, 10, &id))
-		return -EINVAL;
-
-	parahotplug_request_complete(id, 0);
-	return count;
-}
-
-/* The parahotplug/deviceenabled interface gets called by our support script
- * when an SR-IOV device has been recovered. The ID is passed to the script
- * and then passed back when the device has been brought back up.
- */
-static ssize_t deviceenabled_store(struct device *dev,
-				   struct device_attribute *attr,
-				   const char *buf, size_t count)
-{
-	unsigned int id;
-
-	if (kstrtouint(buf, 10, &id))
-		return -EINVAL;
-
-	parahotplug_request_complete(id, 1);
-	return count;
-}
-
-static int
-visorchipset_mmap(struct file *file, struct vm_area_struct *vma)
-{
-	unsigned long physaddr = 0;
-	unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
-	u64 addr = 0;
-
-	/* sv_enable_dfp(); */
-	if (offset & (PAGE_SIZE - 1))
-		return -ENXIO;	/* need aligned offsets */
-
-	switch (offset) {
-	case VISORCHIPSET_MMAP_CONTROLCHANOFFSET:
-		vma->vm_flags |= VM_IO;
-		if (!*file_controlvm_channel)
-			return -ENXIO;
-
-		visorchannel_read
-			(*file_controlvm_channel,
-			 offsetof(struct spar_controlvm_channel_protocol,
-				  gp_control_channel),
-			 &addr, sizeof(addr));
-		if (!addr)
-			return -ENXIO;
-
-		physaddr = (unsigned long)addr;
-		if (remap_pfn_range(vma, vma->vm_start,
-				    physaddr >> PAGE_SHIFT,
-				    vma->vm_end - vma->vm_start,
-				    /*pgprot_noncached */
-				    (vma->vm_page_prot))) {
-			return -EAGAIN;
-		}
-		break;
-	default:
-		return -ENXIO;
-	}
-	return 0;
-}
-
-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 int issue_vmcall_update_physical_time(u64 adjustment)
-{
-	int result = VMCALL_SUCCESS;
-
-	ISSUE_IO_VMCALL(VMCALL_UPDATE_PHYSICAL_TIME, adjustment, result);
-	return result;
-}
-
-static long visorchipset_ioctl(struct file *file, unsigned int cmd,
-			       unsigned long arg)
-{
-	u64 adjustment;
-	s64 vrtc_offset;
-
-	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))) {
-			return -EFAULT;
-		}
-		return 0;
-	case VMCALL_UPDATE_PHYSICAL_TIME:
-		if (copy_from_user(&adjustment, (void __user *)arg,
-				   sizeof(adjustment))) {
-			return -EFAULT;
-		}
-		return issue_vmcall_update_physical_time(adjustment);
-	default:
-		return -EFAULT;
-	}
-}
-
-static const struct file_operations visorchipset_fops = {
-	.owner = THIS_MODULE,
-	.open = visorchipset_open,
-	.read = NULL,
-	.write = NULL,
-	.unlocked_ioctl = visorchipset_ioctl,
-	.release = visorchipset_release,
-	.mmap = visorchipset_mmap,
-};
-
-static int
-visorchipset_file_init(dev_t major_dev, struct visorchannel **controlvm_channel)
-{
-	int rc = 0;
-
-	file_controlvm_channel = controlvm_channel;
-	cdev_init(&file_cdev, &visorchipset_fops);
-	file_cdev.owner = THIS_MODULE;
-	if (MAJOR(major_dev) == 0) {
-		rc = alloc_chrdev_region(&major_dev, 0, 1, "visorchipset");
-		/* dynamic major device number registration required */
-		if (rc < 0)
-			return rc;
-	} else {
-		/* static major device number registration required */
-		rc = register_chrdev_region(major_dev, 1, "visorchipset");
-		if (rc < 0)
-			return rc;
-	}
-	rc = cdev_add(&file_cdev, MKDEV(MAJOR(major_dev), 0), 1);
-	if (rc < 0) {
-		unregister_chrdev_region(major_dev, 1);
-		return rc;
-	}
-	return 0;
-}
-
-static void
-visorchipset_file_cleanup(dev_t major_dev)
-{
-	if (file_cdev.ops)
-		cdev_del(&file_cdev);
-	file_cdev.ops = NULL;
-	unregister_chrdev_region(major_dev, 1);
-}
-
-static int
-visorchipset_init(struct acpi_device *acpi_device)
-{
-	int err = -ENODEV;
-	u64 addr;
-	uuid_le uuid = SPAR_CONTROLVM_CHANNEL_PROTOCOL_UUID;
-
-	addr = controlvm_get_channel_address();
-	if (!addr)
-		goto error;
-
-	memset(&busdev_notifiers, 0, sizeof(busdev_notifiers));
-	memset(&controlvm_payload_info, 0, sizeof(controlvm_payload_info));
-
-	controlvm_channel = visorchannel_create_with_lock(addr, 0,
-							  GFP_KERNEL, uuid);
-	if (!controlvm_channel)
-		goto error;
-
-	if (SPAR_CONTROLVM_CHANNEL_OK_CLIENT(
-		    visorchannel_get_header(controlvm_channel))) {
-		initialize_controlvm_payload();
-	} else {
-		goto error_destroy_channel;
-	}
-
-	major_dev = MKDEV(visorchipset_major, 0);
-	err = visorchipset_file_init(major_dev, &controlvm_channel);
-	if (err < 0)
-		goto error_destroy_payload;
-
-	/* if booting in a crash kernel */
-	if (is_kdump_kernel())
-		INIT_DELAYED_WORK(&periodic_controlvm_work,
-				  setup_crash_devices_work_queue);
-	else
-		INIT_DELAYED_WORK(&periodic_controlvm_work,
-				  controlvm_periodic_work);
-
-	most_recent_message_jiffies = jiffies;
-	poll_jiffies = POLLJIFFIES_CONTROLVMCHANNEL_FAST;
-	schedule_delayed_work(&periodic_controlvm_work, poll_jiffies);
-
-	visorchipset_platform_device.dev.devt = major_dev;
-	if (platform_device_register(&visorchipset_platform_device) < 0) {
-		POSTCODE_LINUX_2(DEVICE_REGISTER_FAILURE_PC, DIAG_SEVERITY_ERR);
-		err = -ENODEV;
-		goto error_cancel_work;
-	}
-	POSTCODE_LINUX_2(CHIPSET_INIT_SUCCESS_PC, POSTCODE_SEVERITY_INFO);
-
-	err = visorbus_init();
-	if (err < 0)
-		goto error_unregister;
-
-	return 0;
-
-error_unregister:
-	platform_device_unregister(&visorchipset_platform_device);
-
-error_cancel_work:
-	cancel_delayed_work_sync(&periodic_controlvm_work);
-	visorchipset_file_cleanup(major_dev);
-
-error_destroy_payload:
-	destroy_controlvm_payload_info(&controlvm_payload_info);
-
-error_destroy_channel:
-	visorchannel_destroy(controlvm_channel);
-
-error:
-	POSTCODE_LINUX_3(CHIPSET_INIT_FAILURE_PC, err, POSTCODE_SEVERITY_ERR);
-	return err;
-}
-
-static int
-visorchipset_exit(struct acpi_device *acpi_device)
-{
-	POSTCODE_LINUX_2(DRIVER_EXIT_PC, POSTCODE_SEVERITY_INFO);
-
-	visorbus_exit();
-
-	cancel_delayed_work_sync(&periodic_controlvm_work);
-	destroy_controlvm_payload_info(&controlvm_payload_info);
-
-	visorchannel_destroy(controlvm_channel);
-
-	visorchipset_file_cleanup(visorchipset_platform_device.dev.devt);
-	platform_device_unregister(&visorchipset_platform_device);
-	POSTCODE_LINUX_2(DRIVER_EXIT_PC, POSTCODE_SEVERITY_INFO);
-
-	return 0;
-}
-
-static const struct acpi_device_id unisys_device_ids[] = {
-	{"PNP0A07", 0},
-	{"", 0},
-};
-
-static struct acpi_driver unisys_acpi_driver = {
-	.name = "unisys_acpi",
-	.class = "unisys_acpi_class",
-	.owner = THIS_MODULE,
-	.ids = unisys_device_ids,
-	.ops = {
-		.add = visorchipset_init,
-		.remove = visorchipset_exit,
-		},
-};
-
-MODULE_DEVICE_TABLE(acpi, unisys_device_ids);
-
-static __init uint32_t visorutil_spar_detect(void)
-{
-	unsigned int eax, ebx, ecx, edx;
-
-	if (cpu_has_hypervisor) {
-		/* check the ID */
-		cpuid(UNISYS_SPAR_LEAF_ID, &eax, &ebx, &ecx, &edx);
-		return  (ebx == UNISYS_SPAR_ID_EBX) &&
-			(ecx == UNISYS_SPAR_ID_ECX) &&
-			(edx == UNISYS_SPAR_ID_EDX);
-	} else {
-		return 0;
-	}
-}
-
-static int init_unisys(void)
-{
-	int result;
-
-	if (!visorutil_spar_detect())
-		return -ENODEV;
-
-	result = acpi_bus_register_driver(&unisys_acpi_driver);
-	if (result)
-		return -ENODEV;
-
-	pr_info("Unisys Visorchipset Driver Loaded.\n");
-	return 0;
-};
-
-static void exit_unisys(void)
-{
-	acpi_bus_unregister_driver(&unisys_acpi_driver);
-}
-
-module_param_named(major, visorchipset_major, int, S_IRUGO);
-MODULE_PARM_DESC(visorchipset_major,
-		 "major device number to use for the device node");
-module_param_named(visorbusregwait, visorchipset_visorbusregwait, int, S_IRUGO);
-MODULE_PARM_DESC(visorchipset_visorbusregwait,
-		 "1 to have the module wait for the visor bus to register");
-
-module_init(init_unisys);
-module_exit(exit_unisys);
-
-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/visorbus/vmcallinterface.h b/drivers/staging/unisys/visorbus/vmcallinterface.h
deleted file mode 100644
index aac7000..0000000
--- a/drivers/staging/unisys/visorbus/vmcallinterface.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/* Copyright (C) 2010 - 2015 UNISYS CORPORATION
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope 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.
-*/
-
-#include <linux/visorbus/diagchannel.h>
-
-#include "iovmcall_gnuc.h"
-
-#ifdef VMCALL_IO_CONTROLVM_ADDR
-#undef VMCALL_IO_CONTROLVM_ADDR
-#endif	/*  */
-
-/* define subsystem number for AppOS, used in uislib driver  */
-#define MDS_APPOS 0x4000000000000000L	/* subsystem = 62 - AppOS */
-enum vmcall_monitor_interface_method_tuple { /* 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
-	     */
-	/* used by all Guests, not just IO */
-	VMCALL_IO_CONTROLVM_ADDR = 0x0501,
-	/* Allow caller to query virtual time offset */
-	VMCALL_QUERY_GUEST_VIRTUAL_TIME_OFFSET = 0x0708,
-	/* LOGEVENT Post Code (RDX) with specified subsystem mask */
-	/* (RCX - monitor_subsystems.h) and severity (RDX) */
-	VMCALL_POST_CODE_LOGEVENT = 0x070B,
-	/* Allow ULTRA_SERVICE_CAPABILITY_TIME capable guest to make VMCALL */
-	VMCALL_UPDATE_PHYSICAL_TIME = 0x0a02
-};
-
-#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(method, param, result) \
-	(result = unisys_vmcall(method, (param) & 0xFFFFFFFF,	\
-				(param) >> 32))
-#define ISSUE_IO_EXTENDED_VMCALL(method, param1, param2, param3) \
-	unisys_extended_vmcall(method, 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)		\
-	ISSUE_IO_EXTENDED_VMCALL(VMCALL_POST_CODE_LOGEVENT, severity,	\
-				 MDS_APPOS, postcode)
-#endif
-
-/* Structures for IO VMCALLs */
-
-/* Parameters to VMCALL_IO_CONTROLVM_ADDR interface */
-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 address;	/* contents provided by this VMCALL (OUT) */
-	/* the size of the ControlVm channel in bytes This VMCall fills this */
-	/* in with the appropriate address. */
-	u32 channel_bytes;	/* contents provided by this VMCALL (OUT) */
-	u8 unused[4];		/* Unused Bytes in the 64-Bit Aligned Struct */
-} __packed;
-
-#endif /* __IOMONINTF_H__ */
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* Re: [PATCH 3/5] Documentation: Move visorbus documentation from staging to Documentation/
  2016-05-17  7:27 ` [PATCH 3/5] Documentation: Move visorbus documentation from staging to Documentation/ David Kershner
@ 2016-05-17 13:50   ` Greg KH
  0 siblings, 0 replies; 15+ messages in thread
From: Greg KH @ 2016-05-17 13:50 UTC (permalink / raw)
  To: David Kershner
  Cc: corbet, tglx, mingo, hpa, erik.arfvidson, timothy.sell, hofrat,
	dzickus, jes.sorensen, alexander.curtin, janani.rvchndrn,
	sudipm.mukherjee, prarit, david.binder, nhorman, dan.j.williams,
	linux-kernel, linux-doc, driverdev-devel, sparmaintainer

On Tue, May 17, 2016 at 03:27:59AM -0400, David Kershner wrote:
> This patch simple does a git mv of the
> drivers/staging/unisys/Documentation directory to Documentation. Renames
> overview.txt to visorbus.txt and renames sysfs-platform-visorchipset to
> the correct name sysfs-bus-visorbus.
> 
> Signed-off-by: David Kershner <david.kershner@unisys.com>
> ---
>  Documentation/ABI/stable/sysfs-bus-visorbus        |  89 ++++++
>  Documentation/visorbus.txt                         | 337 +++++++++++++++++++++
>  .../Documentation/ABI/sysfs-platform-visorchipset  |  89 ------
>  drivers/staging/unisys/Documentation/overview.txt  | 337 ---------------------
>  4 files changed, 426 insertions(+), 426 deletions(-)
>  create mode 100644 Documentation/ABI/stable/sysfs-bus-visorbus
>  create mode 100644 Documentation/visorbus.txt
>  delete mode 100644 drivers/staging/unisys/Documentation/ABI/sysfs-platform-visorchipset
>  delete mode 100644 drivers/staging/unisys/Documentation/overview.txt

Always create patches with -M so that they are tiny and we can see you
are moving files around, not deleting and adding them.

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 0/5] add bus driver for Unisys s-Par paravirtualized devices to arch/x86
  2016-05-17  7:27 [PATCH 0/5] add bus driver for Unisys s-Par paravirtualized devices to arch/x86 David Kershner
                   ` (4 preceding siblings ...)
  2016-05-17  7:28 ` [PATCH 5/5] arch: x86: add visorbus directory to arch/x86 David Kershner
@ 2016-05-17 13:51 ` Greg KH
  2016-05-17 14:01   ` Jes Sorensen
  5 siblings, 1 reply; 15+ messages in thread
From: Greg KH @ 2016-05-17 13:51 UTC (permalink / raw)
  To: David Kershner
  Cc: corbet, tglx, mingo, hpa, erik.arfvidson, timothy.sell, hofrat,
	dzickus, jes.sorensen, alexander.curtin, janani.rvchndrn,
	sudipm.mukherjee, prarit, david.binder, nhorman, dan.j.williams,
	linux-kernel, linux-doc, driverdev-devel, sparmaintainer

On Tue, May 17, 2016 at 03:27:56AM -0400, David Kershner wrote:
> This patchset moves the visorbus driver (fromdrivers/staging/unisys/visorbus)
> and its dependent headers files (from drivers/staging/unisys/include)
> out of staging into the main kernel tree.
> 
> The visorbus driver is a bus driver for various paravirtualized devices
> presented within a Unisys s-Par guest environment.  Drivers for these
> devices are also currently present under drivers/staging/unisys/, which we
> intend to also move out of staging immediately after visorbus.  All of
> these other drivers are dependent upon visorbus and the include directory,
> which is why we would like to move these first.
> 
> Our initial consultations with various members of the community have led us
> to the conclusion that the most appropriate locations for these is:
>     arch/x86/visorbus/       (driver)
>     include/linux/visorbus/  (header files)
> 
> The rationale is that visorbus is dependent on x86-64 architecture.

What makes it dependent on x86?  What prevents it from running on some
other architecture (not the fact that no one has made such hardware,
just the code reasons please.)

And given that this is the middle of the merge window, no maintainer is
going to have any time to do anything with these, can you please resend
them after 4.7-rc1 is out?

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 4/5] staging: unisys: visorbus: Have visorbus use include/linux/visorbus
  2016-05-17  7:28 ` [PATCH 4/5] staging: unisys: visorbus: Have visorbus use include/linux/visorbus David Kershner
@ 2016-05-17 13:52   ` Greg KH
  0 siblings, 0 replies; 15+ messages in thread
From: Greg KH @ 2016-05-17 13:52 UTC (permalink / raw)
  To: David Kershner
  Cc: corbet, tglx, mingo, hpa, erik.arfvidson, timothy.sell, hofrat,
	dzickus, jes.sorensen, alexander.curtin, janani.rvchndrn,
	sudipm.mukherjee, prarit, david.binder, nhorman, dan.j.williams,
	linux-kernel, linux-doc, driverdev-devel, sparmaintainer

On Tue, May 17, 2016 at 03:28:00AM -0400, David Kershner wrote:
> Since we have now moved the include directories over to
> include/linux/visorbus this patch makes all of visorbus
> use the new include folders.
> 
> Signed-off-by: David Kershner <david.kershner@unisys.com>
> ---
>  drivers/staging/unisys/visorbus/controlvmchannel.h |  2 +-
>  drivers/staging/unisys/visorbus/periodic_work.c    |  3 +--
>  drivers/staging/unisys/visorbus/vbuschannel.h      |  3 ++-
>  drivers/staging/unisys/visorbus/visorbus_main.c    |  8 ++++----
>  drivers/staging/unisys/visorbus/visorchannel.c     |  4 ++--
>  drivers/staging/unisys/visorbus/visorchipset.c     | 10 +++++-----
>  drivers/staging/unisys/visorbus/vmcallinterface.h  |  5 ++---
>  7 files changed, 17 insertions(+), 18 deletions(-)

Does that mean the build was broken before you made this patch?  Not
allowed, sorry :(

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 0/5] add bus driver for Unisys s-Par paravirtualized devices to arch/x86
  2016-05-17 13:51 ` [PATCH 0/5] add bus driver for Unisys s-Par paravirtualized devices " Greg KH
@ 2016-05-17 14:01   ` Jes Sorensen
  2016-05-17 14:27     ` Greg KH
  0 siblings, 1 reply; 15+ messages in thread
From: Jes Sorensen @ 2016-05-17 14:01 UTC (permalink / raw)
  To: Greg KH
  Cc: David Kershner, corbet, tglx, mingo, hpa, erik.arfvidson,
	timothy.sell, hofrat, dzickus, alexander.curtin, janani.rvchndrn,
	sudipm.mukherjee, prarit, david.binder, nhorman, dan.j.williams,
	linux-kernel, linux-doc, driverdev-devel, sparmaintainer

Greg KH <gregkh@linuxfoundation.org> writes:
> On Tue, May 17, 2016 at 03:27:56AM -0400, David Kershner wrote:
>> This patchset moves the visorbus driver (fromdrivers/staging/unisys/visorbus)
>> and its dependent headers files (from drivers/staging/unisys/include)
>> out of staging into the main kernel tree.
>> 
>> The visorbus driver is a bus driver for various paravirtualized devices
>> presented within a Unisys s-Par guest environment.  Drivers for these
>> devices are also currently present under drivers/staging/unisys/, which we
>> intend to also move out of staging immediately after visorbus.  All of
>> these other drivers are dependent upon visorbus and the include directory,
>> which is why we would like to move these first.
>> 
>> Our initial consultations with various members of the community have led us
>> to the conclusion that the most appropriate locations for these is:
>>     arch/x86/visorbus/       (driver)
>>     include/linux/visorbus/  (header files)
>> 
>> The rationale is that visorbus is dependent on x86-64 architecture.
>
> What makes it dependent on x86?  What prevents it from running on some
> other architecture (not the fact that no one has made such hardware,
> just the code reasons please.)

It's dependent on system firmware which is only available on the S-Par
platform which is x86_64 only. The closest similarity is probably what
you find on the PPC and Sparc platforms.

Jes

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 0/5] add bus driver for Unisys s-Par paravirtualized devices to arch/x86
  2016-05-17 14:01   ` Jes Sorensen
@ 2016-05-17 14:27     ` Greg KH
  2016-05-17 23:49       ` Jes Sorensen
  0 siblings, 1 reply; 15+ messages in thread
From: Greg KH @ 2016-05-17 14:27 UTC (permalink / raw)
  To: Jes Sorensen
  Cc: David Kershner, corbet, tglx, mingo, hpa, erik.arfvidson,
	timothy.sell, hofrat, dzickus, alexander.curtin, janani.rvchndrn,
	sudipm.mukherjee, prarit, david.binder, nhorman, dan.j.williams,
	linux-kernel, linux-doc, driverdev-devel, sparmaintainer

On Tue, May 17, 2016 at 10:01:55AM -0400, Jes Sorensen wrote:
> Greg KH <gregkh@linuxfoundation.org> writes:
> > On Tue, May 17, 2016 at 03:27:56AM -0400, David Kershner wrote:
> >> This patchset moves the visorbus driver (fromdrivers/staging/unisys/visorbus)
> >> and its dependent headers files (from drivers/staging/unisys/include)
> >> out of staging into the main kernel tree.
> >> 
> >> The visorbus driver is a bus driver for various paravirtualized devices
> >> presented within a Unisys s-Par guest environment.  Drivers for these
> >> devices are also currently present under drivers/staging/unisys/, which we
> >> intend to also move out of staging immediately after visorbus.  All of
> >> these other drivers are dependent upon visorbus and the include directory,
> >> which is why we would like to move these first.
> >> 
> >> Our initial consultations with various members of the community have led us
> >> to the conclusion that the most appropriate locations for these is:
> >>     arch/x86/visorbus/       (driver)
> >>     include/linux/visorbus/  (header files)
> >> 
> >> The rationale is that visorbus is dependent on x86-64 architecture.
> >
> > What makes it dependent on x86?  What prevents it from running on some
> > other architecture (not the fact that no one has made such hardware,
> > just the code reasons please.)
> 
> It's dependent on system firmware which is only available on the S-Par
> platform which is x86_64 only. The closest similarity is probably what
> you find on the PPC and Sparc platforms.

Ok, but still no need to put it under arch/ anything, it should go in
drivers/ like all other drivers and busses are, no matter what the arch
it happens to run on is.

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 0/5] add bus driver for Unisys s-Par paravirtualized devices to arch/x86
  2016-05-17 14:27     ` Greg KH
@ 2016-05-17 23:49       ` Jes Sorensen
  2016-05-18  0:03         ` Greg KH
  0 siblings, 1 reply; 15+ messages in thread
From: Jes Sorensen @ 2016-05-17 23:49 UTC (permalink / raw)
  To: Greg KH
  Cc: David Kershner, corbet, tglx, mingo, hpa, erik.arfvidson,
	timothy.sell, hofrat, dzickus, alexander.curtin, janani.rvchndrn,
	sudipm.mukherjee, prarit, david.binder, nhorman, dan.j.williams,
	linux-kernel, linux-doc, driverdev-devel, sparmaintainer

Greg KH <gregkh@linuxfoundation.org> writes:
> On Tue, May 17, 2016 at 10:01:55AM -0400, Jes Sorensen wrote:
>> Greg KH <gregkh@linuxfoundation.org> writes:
>> > On Tue, May 17, 2016 at 03:27:56AM -0400, David Kershner wrote:
>> >> This patchset moves the visorbus driver
>> >> (fromdrivers/staging/unisys/visorbus)
>> >> and its dependent headers files (from drivers/staging/unisys/include)
>> >> out of staging into the main kernel tree.
>> >> 
>> >> The visorbus driver is a bus driver for various paravirtualized devices
>> >> presented within a Unisys s-Par guest environment.  Drivers for these
>> >> devices are also currently present under drivers/staging/unisys/, which we
>> >> intend to also move out of staging immediately after visorbus.  All of
>> >> these other drivers are dependent upon visorbus and the include directory,
>> >> which is why we would like to move these first.
>> >> 
>> >> Our initial consultations with various members of the community have led us
>> >> to the conclusion that the most appropriate locations for these is:
>> >>     arch/x86/visorbus/       (driver)
>> >>     include/linux/visorbus/  (header files)
>> >> 
>> >> The rationale is that visorbus is dependent on x86-64 architecture.
>> >
>> > What makes it dependent on x86?  What prevents it from running on some
>> > other architecture (not the fact that no one has made such hardware,
>> > just the code reasons please.)
>> 
>> It's dependent on system firmware which is only available on the S-Par
>> platform which is x86_64 only. The closest similarity is probably what
>> you find on the PPC and Sparc platforms.
>
> Ok, but still no need to put it under arch/ anything, it should go in
> drivers/ like all other drivers and busses are, no matter what the arch
> it happens to run on is.

I don't think thats obvious. arch/x86/kvm is an example of this, Sparc
and PPC also have their stuff under arch/.

I am open, if people prefer to have drivers/visorbus I can support that.
I find right now it's really messy with things being put all over the
place, and it's not obvious what the real placement is for all of this.

Jes

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 0/5] add bus driver for Unisys s-Par paravirtualized devices to arch/x86
  2016-05-17 23:49       ` Jes Sorensen
@ 2016-05-18  0:03         ` Greg KH
  2016-05-18 16:03           ` Jes Sorensen
  0 siblings, 1 reply; 15+ messages in thread
From: Greg KH @ 2016-05-18  0:03 UTC (permalink / raw)
  To: Jes Sorensen
  Cc: David Kershner, corbet, tglx, mingo, hpa, erik.arfvidson,
	timothy.sell, hofrat, dzickus, alexander.curtin, janani.rvchndrn,
	sudipm.mukherjee, prarit, david.binder, nhorman, dan.j.williams,
	linux-kernel, linux-doc, driverdev-devel, sparmaintainer

On Tue, May 17, 2016 at 07:49:53PM -0400, Jes Sorensen wrote:
> Greg KH <gregkh@linuxfoundation.org> writes:
> > On Tue, May 17, 2016 at 10:01:55AM -0400, Jes Sorensen wrote:
> >> Greg KH <gregkh@linuxfoundation.org> writes:
> >> > On Tue, May 17, 2016 at 03:27:56AM -0400, David Kershner wrote:
> >> >> This patchset moves the visorbus driver
> >> >> (fromdrivers/staging/unisys/visorbus)
> >> >> and its dependent headers files (from drivers/staging/unisys/include)
> >> >> out of staging into the main kernel tree.
> >> >> 
> >> >> The visorbus driver is a bus driver for various paravirtualized devices
> >> >> presented within a Unisys s-Par guest environment.  Drivers for these
> >> >> devices are also currently present under drivers/staging/unisys/, which we
> >> >> intend to also move out of staging immediately after visorbus.  All of
> >> >> these other drivers are dependent upon visorbus and the include directory,
> >> >> which is why we would like to move these first.
> >> >> 
> >> >> Our initial consultations with various members of the community have led us
> >> >> to the conclusion that the most appropriate locations for these is:
> >> >>     arch/x86/visorbus/       (driver)
> >> >>     include/linux/visorbus/  (header files)
> >> >> 
> >> >> The rationale is that visorbus is dependent on x86-64 architecture.
> >> >
> >> > What makes it dependent on x86?  What prevents it from running on some
> >> > other architecture (not the fact that no one has made such hardware,
> >> > just the code reasons please.)
> >> 
> >> It's dependent on system firmware which is only available on the S-Par
> >> platform which is x86_64 only. The closest similarity is probably what
> >> you find on the PPC and Sparc platforms.
> >
> > Ok, but still no need to put it under arch/ anything, it should go in
> > drivers/ like all other drivers and busses are, no matter what the arch
> > it happens to run on is.
> 
> I don't think thats obvious. arch/x86/kvm is an example of this, Sparc
> and PPC also have their stuff under arch/.

For some things, yes, but let's not make the same mistakes as others :)

Look at drivers/hv/ for an example of a very x86-only bus and driver
subsystem living in drivers/  Please don't burry driver stuff in arch/
the ARM developers are trying to fix their mistakes of the past and move
all of their cruft out of arch/ for that reason.

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 0/5] add bus driver for Unisys s-Par paravirtualized devices to arch/x86
  2016-05-18  0:03         ` Greg KH
@ 2016-05-18 16:03           ` Jes Sorensen
  2016-05-18 17:26             ` Greg KH
  0 siblings, 1 reply; 15+ messages in thread
From: Jes Sorensen @ 2016-05-18 16:03 UTC (permalink / raw)
  To: Greg KH
  Cc: David Kershner, corbet, tglx, mingo, hpa, erik.arfvidson,
	timothy.sell, hofrat, dzickus, alexander.curtin, janani.rvchndrn,
	sudipm.mukherjee, prarit, david.binder, nhorman, dan.j.williams,
	linux-kernel, linux-doc, driverdev-devel, sparmaintainer

Greg KH <gregkh@linuxfoundation.org> writes:
> On Tue, May 17, 2016 at 07:49:53PM -0400, Jes Sorensen wrote:
>> > Ok, but still no need to put it under arch/ anything, it should go in
>> > drivers/ like all other drivers and busses are, no matter what the arch
>> > it happens to run on is.
>> 
>> I don't think thats obvious. arch/x86/kvm is an example of this, Sparc
>> and PPC also have their stuff under arch/.
>
> For some things, yes, but let's not make the same mistakes as others :)
>
> Look at drivers/hv/ for an example of a very x86-only bus and driver
> subsystem living in drivers/  Please don't burry driver stuff in arch/
> the ARM developers are trying to fix their mistakes of the past and move
> all of their cruft out of arch/ for that reason.

Works for me.

So should they put it in drivers/visorbus or drivers/bus/visorbus?  What
about drivers/virt? Would you suggest hv and xen gets moved in there?

Cheers,
Jes

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 0/5] add bus driver for Unisys s-Par paravirtualized devices to arch/x86
  2016-05-18 16:03           ` Jes Sorensen
@ 2016-05-18 17:26             ` Greg KH
  0 siblings, 0 replies; 15+ messages in thread
From: Greg KH @ 2016-05-18 17:26 UTC (permalink / raw)
  To: Jes Sorensen
  Cc: David Kershner, corbet, tglx, mingo, hpa, erik.arfvidson,
	timothy.sell, hofrat, dzickus, alexander.curtin, janani.rvchndrn,
	sudipm.mukherjee, prarit, david.binder, nhorman, dan.j.williams,
	linux-kernel, linux-doc, driverdev-devel, sparmaintainer

On Wed, May 18, 2016 at 12:03:58PM -0400, Jes Sorensen wrote:
> Greg KH <gregkh@linuxfoundation.org> writes:
> > On Tue, May 17, 2016 at 07:49:53PM -0400, Jes Sorensen wrote:
> >> > Ok, but still no need to put it under arch/ anything, it should go in
> >> > drivers/ like all other drivers and busses are, no matter what the arch
> >> > it happens to run on is.
> >> 
> >> I don't think thats obvious. arch/x86/kvm is an example of this, Sparc
> >> and PPC also have their stuff under arch/.
> >
> > For some things, yes, but let's not make the same mistakes as others :)
> >
> > Look at drivers/hv/ for an example of a very x86-only bus and driver
> > subsystem living in drivers/  Please don't burry driver stuff in arch/
> > the ARM developers are trying to fix their mistakes of the past and move
> > all of their cruft out of arch/ for that reason.
> 
> Works for me.
> 
> So should they put it in drivers/visorbus or drivers/bus/visorbus?

drivers/visorbus please.  drivers/bus/ is an "odd" thing :(

> What about drivers/virt? Would you suggest hv and xen gets moved in
> there?

Ah, yeah, that would be great, never noticed it before, despite being
there since 2011...

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2016-05-18 17:26 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-05-17  7:27 [PATCH 0/5] add bus driver for Unisys s-Par paravirtualized devices to arch/x86 David Kershner
2016-05-17  7:27 ` [PATCH 1/5] staging: unisys: Move vbushelper.h to visorbus directory David Kershner
2016-05-17  7:27 ` [PATCH 2/5] include: linux: visorbus: Add visorbus to include/linux directory David Kershner
2016-05-17  7:27 ` [PATCH 3/5] Documentation: Move visorbus documentation from staging to Documentation/ David Kershner
2016-05-17 13:50   ` Greg KH
2016-05-17  7:28 ` [PATCH 4/5] staging: unisys: visorbus: Have visorbus use include/linux/visorbus David Kershner
2016-05-17 13:52   ` Greg KH
2016-05-17  7:28 ` [PATCH 5/5] arch: x86: add visorbus directory to arch/x86 David Kershner
2016-05-17 13:51 ` [PATCH 0/5] add bus driver for Unisys s-Par paravirtualized devices " Greg KH
2016-05-17 14:01   ` Jes Sorensen
2016-05-17 14:27     ` Greg KH
2016-05-17 23:49       ` Jes Sorensen
2016-05-18  0:03         ` Greg KH
2016-05-18 16:03           ` Jes Sorensen
2016-05-18 17:26             ` Greg KH

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).