lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:	Tue, 17 May 2016 03:28:01 -0400
From:	David Kershner <david.kershner@...sys.com>
To:	<corbet@....net>, <tglx@...utronix.de>, <mingo@...hat.com>,
	<hpa@...or.com>, <david.kershner@...sys.com>,
	<gregkh@...uxfoundation.org>, <erik.arfvidson@...sys.com>,
	<timothy.sell@...sys.com>, <hofrat@...dl.org>,
	<dzickus@...hat.com>, <jes.sorensen@...hat.com>,
	<alexander.curtin@...sys.com>, <janani.rvchndrn@...il.com>,
	<sudipm.mukherjee@...il.com>, <prarit@...hat.com>,
	<david.binder@...sys.com>, <nhorman@...hat.com>,
	<dan.j.williams@...el.com>, <linux-kernel@...r.kernel.org>,
	<linux-doc@...r.kernel.org>,
	<driverdev-devel@...uxdriverproject.org>,
	<sparmaintainer@...sys.com>
Subject: [PATCH 5/5] arch: x86: add visorbus directory to arch/x86

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@...sys.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

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ