- patches.suse/staging-hv-update-to-3.0.patch
  Update hyperv drivers to current mainline state (bnc#662432).
- patches.xen/xen3-patch-2.6.32: Refresh.

suse-commit: 131ee6958a09a04cdde272d9c67a1089b77638c1
diff --git a/drivers/staging/hv/BlkVsc.c b/drivers/staging/hv/BlkVsc.c
deleted file mode 100644
index ee7c298..0000000
--- a/drivers/staging/hv/BlkVsc.c
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- *
- * Copyright (c) 2009, Microsoft Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place - Suite 330, Boston, MA 02111-1307 USA.
- *
- * Authors:
- *   Haiyang Zhang <haiyangz@microsoft.com>
- *   Hank Janssen  <hjanssen@microsoft.com>
- *
- */
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include "osd.h"
-#include "StorVsc.c"
-
-static const char *gBlkDriverName = "blkvsc";
-
-/* {32412632-86cb-44a2-9b5c-50d1417354f5} */
-static const struct hv_guid gBlkVscDeviceType = {
-	.data = {
-		0x32, 0x26, 0x41, 0x32, 0xcb, 0x86, 0xa2, 0x44,
-		0x9b, 0x5c, 0x50, 0xd1, 0x41, 0x73, 0x54, 0xf5
-	}
-};
-
-static int BlkVscOnDeviceAdd(struct hv_device *Device, void *AdditionalInfo)
-{
-	struct storvsc_device_info *deviceInfo;
-	int ret = 0;
-
-	deviceInfo = (struct storvsc_device_info *)AdditionalInfo;
-
-	ret = StorVscOnDeviceAdd(Device, AdditionalInfo);
-	if (ret != 0)
-		return ret;
-
-	/*
-	 * We need to use the device instance guid to set the path and target
-	 * id. For IDE devices, the device instance id is formatted as
-	 * <bus id> * - <device id> - 8899 - 000000000000.
-	 */
-	deviceInfo->PathId = Device->deviceInstance.data[3] << 24 |
-			     Device->deviceInstance.data[2] << 16 |
-			     Device->deviceInstance.data[1] << 8  |
-			     Device->deviceInstance.data[0];
-
-	deviceInfo->TargetId = Device->deviceInstance.data[5] << 8 |
-			       Device->deviceInstance.data[4];
-
-	return ret;
-}
-
-int BlkVscInitialize(struct hv_driver *Driver)
-{
-	struct storvsc_driver_object *storDriver;
-	int ret = 0;
-
-	storDriver = (struct storvsc_driver_object *)Driver;
-
-	/* Make sure we are at least 2 pages since 1 page is used for control */
-	/* ASSERT(storDriver->RingBufferSize >= (PAGE_SIZE << 1)); */
-
-	Driver->name = gBlkDriverName;
-	memcpy(&Driver->deviceType, &gBlkVscDeviceType, sizeof(struct hv_guid));
-
-	storDriver->RequestExtSize = sizeof(struct storvsc_request_extension);
-
-	/*
-	 * Divide the ring buffer data size (which is 1 page less than the ring
-	 * buffer size since that page is reserved for the ring buffer indices)
-	 * by the max request size (which is
-	 * VMBUS_CHANNEL_PACKET_MULITPAGE_BUFFER + struct vstor_packet + u64)
-	 */
-	storDriver->MaxOutstandingRequestsPerChannel =
-		((storDriver->RingBufferSize - PAGE_SIZE) /
-		  ALIGN_UP(MAX_MULTIPAGE_BUFFER_PACKET +
-			   sizeof(struct vstor_packet) + sizeof(u64),
-			   sizeof(u64)));
-
-	DPRINT_INFO(BLKVSC, "max io outstd %u",
-		    storDriver->MaxOutstandingRequestsPerChannel);
-
-	/* Setup the dispatch table */
-	storDriver->Base.OnDeviceAdd = BlkVscOnDeviceAdd;
-	storDriver->Base.OnDeviceRemove = StorVscOnDeviceRemove;
-	storDriver->Base.OnCleanup = StorVscOnCleanup;
-	storDriver->OnIORequest	= StorVscOnIORequest;
-
-	return ret;
-}
diff --git a/drivers/staging/hv/Channel.c b/drivers/staging/hv/Channel.c
deleted file mode 100644
index d712ba8..0000000
--- a/drivers/staging/hv/Channel.c
+++ /dev/null
@@ -1,1044 +0,0 @@
-/*
- * Copyright (c) 2009, Microsoft Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place - Suite 330, Boston, MA 02111-1307 USA.
- *
- * Authors:
- *   Haiyang Zhang <haiyangz@microsoft.com>
- *   Hank Janssen  <hjanssen@microsoft.com>
- */
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include "osd.h"
-#include "logging.h"
-#include "VmbusPrivate.h"
-
-/* Internal routines */
-static int VmbusChannelCreateGpadlHeader(
-	void *Kbuffer,	/* must be phys and virt contiguous */
-	u32 Size,	/* page-size multiple */
-	struct vmbus_channel_msginfo **msgInfo,
-	u32 *MessageCount);
-static void DumpVmbusChannel(struct vmbus_channel *channel);
-static void VmbusChannelSetEvent(struct vmbus_channel *channel);
-
-
-#if 0
-static void DumpMonitorPage(struct hv_monitor_page *MonitorPage)
-{
-	int i = 0;
-	int j = 0;
-
-	DPRINT_DBG(VMBUS, "monitorPage - %p, trigger state - %d",
-		   MonitorPage, MonitorPage->TriggerState);
-
-	for (i = 0; i < 4; i++)
-		DPRINT_DBG(VMBUS, "trigger group (%d) - %llx", i,
-			   MonitorPage->TriggerGroup[i].AsUINT64);
-
-	for (i = 0; i < 4; i++) {
-		for (j = 0; j < 32; j++) {
-			DPRINT_DBG(VMBUS, "latency (%d)(%d) - %llx", i, j,
-				   MonitorPage->Latency[i][j]);
-		}
-	}
-	for (i = 0; i < 4; i++) {
-		for (j = 0; j < 32; j++) {
-			DPRINT_DBG(VMBUS, "param-conn id (%d)(%d) - %d", i, j,
-			       MonitorPage->Parameter[i][j].ConnectionId.Asu32);
-			DPRINT_DBG(VMBUS, "param-flag (%d)(%d) - %d", i, j,
-				MonitorPage->Parameter[i][j].FlagNumber);
-		}
-	}
-}
-#endif
-
-/*
- * VmbusChannelSetEvent - Trigger an event notification on the specified
- * channel.
- */
-static void VmbusChannelSetEvent(struct vmbus_channel *Channel)
-{
-	struct hv_monitor_page *monitorPage;
-
-	if (Channel->OfferMsg.MonitorAllocated) {
-		/* Each u32 represents 32 channels */
-		sync_set_bit(Channel->OfferMsg.ChildRelId & 31,
-			(unsigned long *) gVmbusConnection.SendInterruptPage +
-			(Channel->OfferMsg.ChildRelId >> 5));
-
-		monitorPage = gVmbusConnection.MonitorPages;
-		monitorPage++; /* Get the child to parent monitor page */
-
-		sync_set_bit(Channel->MonitorBit,
-			(unsigned long *)&monitorPage->TriggerGroup
-					[Channel->MonitorGroup].Pending);
-
-	} else {
-		VmbusSetEvent(Channel->OfferMsg.ChildRelId);
-	}
-}
-
-#if 0
-static void VmbusChannelClearEvent(struct vmbus_channel *channel)
-{
-	struct hv_monitor_page *monitorPage;
-
-	if (Channel->OfferMsg.MonitorAllocated) {
-		/* Each u32 represents 32 channels */
-		sync_clear_bit(Channel->OfferMsg.ChildRelId & 31,
-			  (unsigned long *)gVmbusConnection.SendInterruptPage +
-			  (Channel->OfferMsg.ChildRelId >> 5));
-
-		monitorPage =
-			(struct hv_monitor_page *)gVmbusConnection.MonitorPages;
-		monitorPage++; /* Get the child to parent monitor page */
-
-		sync_clear_bit(Channel->MonitorBit,
-			  (unsigned long *)&monitorPage->TriggerGroup
-					[Channel->MonitorGroup].Pending);
-	}
-}
-
-#endif
-/*
- * VmbusChannelGetDebugInfo -Retrieve various channel debug info
- */
-void VmbusChannelGetDebugInfo(struct vmbus_channel *Channel,
-			      struct vmbus_channel_debug_info *DebugInfo)
-{
-	struct hv_monitor_page *monitorPage;
-	u8 monitorGroup = (u8)Channel->OfferMsg.MonitorId / 32;
-	u8 monitorOffset = (u8)Channel->OfferMsg.MonitorId % 32;
-	/* u32 monitorBit	= 1 << monitorOffset; */
-
-	DebugInfo->RelId = Channel->OfferMsg.ChildRelId;
-	DebugInfo->State = Channel->State;
-	memcpy(&DebugInfo->InterfaceType,
-	       &Channel->OfferMsg.Offer.InterfaceType, sizeof(struct hv_guid));
-	memcpy(&DebugInfo->InterfaceInstance,
-	       &Channel->OfferMsg.Offer.InterfaceInstance,
-	       sizeof(struct hv_guid));
-
-	monitorPage = (struct hv_monitor_page *)gVmbusConnection.MonitorPages;
-
-	DebugInfo->MonitorId = Channel->OfferMsg.MonitorId;
-
-	DebugInfo->ServerMonitorPending =
-			monitorPage->TriggerGroup[monitorGroup].Pending;
-	DebugInfo->ServerMonitorLatency =
-			monitorPage->Latency[monitorGroup][monitorOffset];
-	DebugInfo->ServerMonitorConnectionId =
-			monitorPage->Parameter[monitorGroup]
-					      [monitorOffset].ConnectionId.u.Id;
-
-	monitorPage++;
-
-	DebugInfo->ClientMonitorPending =
-			monitorPage->TriggerGroup[monitorGroup].Pending;
-	DebugInfo->ClientMonitorLatency =
-			monitorPage->Latency[monitorGroup][monitorOffset];
-	DebugInfo->ClientMonitorConnectionId =
-			monitorPage->Parameter[monitorGroup]
-					      [monitorOffset].ConnectionId.u.Id;
-
-	RingBufferGetDebugInfo(&Channel->Inbound, &DebugInfo->Inbound);
-	RingBufferGetDebugInfo(&Channel->Outbound, &DebugInfo->Outbound);
-}
-
-/*
- * VmbusChannelOpen - Open the specified channel.
- */
-int VmbusChannelOpen(struct vmbus_channel *NewChannel, u32 SendRingBufferSize,
-		     u32 RecvRingBufferSize, void *UserData, u32 UserDataLen,
-		     void (*OnChannelCallback)(void *context), void *Context)
-{
-	struct vmbus_channel_open_channel *openMsg;
-	struct vmbus_channel_msginfo *openInfo = NULL;
-	void *in, *out;
-	unsigned long flags;
-	int ret, err = 0;
-
-	/* Aligned to page size */
-	/* ASSERT(!(SendRingBufferSize & (PAGE_SIZE - 1))); */
-	/* ASSERT(!(RecvRingBufferSize & (PAGE_SIZE - 1))); */
-
-	NewChannel->OnChannelCallback = OnChannelCallback;
-	NewChannel->ChannelCallbackContext = Context;
-
-	/* Allocate the ring buffer */
-	out = osd_PageAlloc((SendRingBufferSize + RecvRingBufferSize)
-			     >> PAGE_SHIFT);
-	if (!out)
-		return -ENOMEM;
-
-	/* ASSERT(((unsigned long)out & (PAGE_SIZE-1)) == 0); */
-
-	in = (void *)((unsigned long)out + SendRingBufferSize);
-
-	NewChannel->RingBufferPages = out;
-	NewChannel->RingBufferPageCount = (SendRingBufferSize +
-					   RecvRingBufferSize) >> PAGE_SHIFT;
-
-	ret = RingBufferInit(&NewChannel->Outbound, out, SendRingBufferSize);
-	if (ret != 0) {
-		err = ret;
-		goto errorout;
-	}
-
-	ret = RingBufferInit(&NewChannel->Inbound, in, RecvRingBufferSize);
-	if (ret != 0) {
-		err = ret;
-		goto errorout;
-	}
-
-
-	/* Establish the gpadl for the ring buffer */
-	DPRINT_DBG(VMBUS, "Establishing ring buffer's gpadl for channel %p...",
-		   NewChannel);
-
-	NewChannel->RingBufferGpadlHandle = 0;
-
-	ret = VmbusChannelEstablishGpadl(NewChannel,
-					 NewChannel->Outbound.RingBuffer,
-					 SendRingBufferSize +
-					 RecvRingBufferSize,
-					 &NewChannel->RingBufferGpadlHandle);
-
-	if (ret != 0) {
-		err = ret;
-		goto errorout;
-	}
-
-	DPRINT_DBG(VMBUS, "channel %p <relid %d gpadl 0x%x send ring %p "
-		   "size %d recv ring %p size %d, downstreamoffset %d>",
-		   NewChannel, NewChannel->OfferMsg.ChildRelId,
-		   NewChannel->RingBufferGpadlHandle,
-		   NewChannel->Outbound.RingBuffer,
-		   NewChannel->Outbound.RingSize,
-		   NewChannel->Inbound.RingBuffer,
-		   NewChannel->Inbound.RingSize,
-		   SendRingBufferSize);
-
-	/* Create and init the channel open message */
-	openInfo = kmalloc(sizeof(*openInfo) +
-			   sizeof(struct vmbus_channel_open_channel),
-			   GFP_KERNEL);
-	if (!openInfo) {
-		err = -ENOMEM;
-		goto errorout;
-	}
-
-	openInfo->WaitEvent = osd_WaitEventCreate();
-	if (!openInfo->WaitEvent) {
-		err = -ENOMEM;
-		goto errorout;
-	}
-
-	openMsg = (struct vmbus_channel_open_channel *)openInfo->Msg;
-	openMsg->Header.MessageType = ChannelMessageOpenChannel;
-	openMsg->OpenId = NewChannel->OfferMsg.ChildRelId; /* FIXME */
-	openMsg->ChildRelId = NewChannel->OfferMsg.ChildRelId;
-	openMsg->RingBufferGpadlHandle = NewChannel->RingBufferGpadlHandle;
-	openMsg->DownstreamRingBufferPageOffset = SendRingBufferSize >>
-						  PAGE_SHIFT;
-	openMsg->ServerContextAreaGpadlHandle = 0; /* TODO */
-
-	if (UserDataLen > MAX_USER_DEFINED_BYTES) {
-		err = -EINVAL;
-		goto errorout;
-	}
-
-	if (UserDataLen)
-		memcpy(openMsg->UserData, UserData, UserDataLen);
-
-	spin_lock_irqsave(&gVmbusConnection.channelmsg_lock, flags);
-	list_add_tail(&openInfo->MsgListEntry,
-		      &gVmbusConnection.ChannelMsgList);
-	spin_unlock_irqrestore(&gVmbusConnection.channelmsg_lock, flags);
-
-	DPRINT_DBG(VMBUS, "Sending channel open msg...");
-
-	ret = VmbusPostMessage(openMsg,
-			       sizeof(struct vmbus_channel_open_channel));
-	if (ret != 0) {
-		DPRINT_ERR(VMBUS, "unable to open channel - %d", ret);
-		goto Cleanup;
-	}
-
-	/* FIXME: Need to time-out here */
-	osd_WaitEventWait(openInfo->WaitEvent);
-
-	if (openInfo->Response.OpenResult.Status == 0)
-		DPRINT_INFO(VMBUS, "channel <%p> open success!!", NewChannel);
-	else
-		DPRINT_INFO(VMBUS, "channel <%p> open failed - %d!!",
-			    NewChannel, openInfo->Response.OpenResult.Status);
-
-Cleanup:
-	spin_lock_irqsave(&gVmbusConnection.channelmsg_lock, flags);
-	list_del(&openInfo->MsgListEntry);
-	spin_unlock_irqrestore(&gVmbusConnection.channelmsg_lock, flags);
-
-	kfree(openInfo->WaitEvent);
-	kfree(openInfo);
-	return 0;
-
-errorout:
-	RingBufferCleanup(&NewChannel->Outbound);
-	RingBufferCleanup(&NewChannel->Inbound);
-	osd_PageFree(out, (SendRingBufferSize + RecvRingBufferSize)
-		     >> PAGE_SHIFT);
-	kfree(openInfo);
-	return err;
-}
-
-/*
- * DumpGpadlBody - Dump the gpadl body message to the console for
- * debugging purposes.
- */
-static void DumpGpadlBody(struct vmbus_channel_gpadl_body *Gpadl, u32 Len)
-{
-	int i;
-	int pfnCount;
-
-	pfnCount = (Len - sizeof(struct vmbus_channel_gpadl_body)) /
-		   sizeof(u64);
-	DPRINT_DBG(VMBUS, "gpadl body - len %d pfn count %d", Len, pfnCount);
-
-	for (i = 0; i < pfnCount; i++)
-		DPRINT_DBG(VMBUS, "gpadl body  - %d) pfn %llu",
-			   i, Gpadl->Pfn[i]);
-}
-
-/*
- * DumpGpadlHeader - Dump the gpadl header message to the console for
- * debugging purposes.
- */
-static void DumpGpadlHeader(struct vmbus_channel_gpadl_header *Gpadl)
-{
-	int i, j;
-	int pageCount;
-
-	DPRINT_DBG(VMBUS,
-		   "gpadl header - relid %d, range count %d, range buflen %d",
-		   Gpadl->ChildRelId, Gpadl->RangeCount, Gpadl->RangeBufLen);
-	for (i = 0; i < Gpadl->RangeCount; i++) {
-		pageCount = Gpadl->Range[i].ByteCount >> PAGE_SHIFT;
-		pageCount = (pageCount > 26) ? 26 : pageCount;
-
-		DPRINT_DBG(VMBUS, "gpadl range %d - len %d offset %d "
-			   "page count %d", i, Gpadl->Range[i].ByteCount,
-			   Gpadl->Range[i].ByteOffset, pageCount);
-
-		for (j = 0; j < pageCount; j++)
-			DPRINT_DBG(VMBUS, "%d) pfn %llu", j,
-				   Gpadl->Range[i].PfnArray[j]);
-	}
-}
-
-/*
- * VmbusChannelCreateGpadlHeader - Creates a gpadl for the specified buffer
- */
-static int VmbusChannelCreateGpadlHeader(void *Kbuffer, u32 Size,
-					 struct vmbus_channel_msginfo **MsgInfo,
-					 u32 *MessageCount)
-{
-	int i;
-	int pageCount;
-	unsigned long long pfn;
-	struct vmbus_channel_gpadl_header *gpaHeader;
-	struct vmbus_channel_gpadl_body *gpadlBody;
-	struct vmbus_channel_msginfo *msgHeader;
-	struct vmbus_channel_msginfo *msgBody = NULL;
-	u32 msgSize;
-
-	int pfnSum, pfnCount, pfnLeft, pfnCurr, pfnSize;
-
-	/* ASSERT((kbuffer & (PAGE_SIZE-1)) == 0); */
-	/* ASSERT((Size & (PAGE_SIZE-1)) == 0); */
-
-	pageCount = Size >> PAGE_SHIFT;
-	pfn = virt_to_phys(Kbuffer) >> PAGE_SHIFT;
-
-	/* do we need a gpadl body msg */
-	pfnSize = MAX_SIZE_CHANNEL_MESSAGE -
-		  sizeof(struct vmbus_channel_gpadl_header) -
-		  sizeof(struct gpa_range);
-	pfnCount = pfnSize / sizeof(u64);
-
-	if (pageCount > pfnCount) {
-		/* we need a gpadl body */
-		/* fill in the header */
-		msgSize = sizeof(struct vmbus_channel_msginfo) +
-			  sizeof(struct vmbus_channel_gpadl_header) +
-			  sizeof(struct gpa_range) + pfnCount * sizeof(u64);
-		msgHeader =  kzalloc(msgSize, GFP_KERNEL);
-		if (!msgHeader)
-			goto nomem;
-
-		INIT_LIST_HEAD(&msgHeader->SubMsgList);
-		msgHeader->MessageSize = msgSize;
-
-		gpaHeader = (struct vmbus_channel_gpadl_header *)msgHeader->Msg;
-		gpaHeader->RangeCount = 1;
-		gpaHeader->RangeBufLen = sizeof(struct gpa_range) +
-					 pageCount * sizeof(u64);
-		gpaHeader->Range[0].ByteOffset = 0;
-		gpaHeader->Range[0].ByteCount = Size;
-		for (i = 0; i < pfnCount; i++)
-			gpaHeader->Range[0].PfnArray[i] = pfn+i;
-		*MsgInfo = msgHeader;
-		*MessageCount = 1;
-
-		pfnSum = pfnCount;
-		pfnLeft = pageCount - pfnCount;
-
-		/* how many pfns can we fit */
-		pfnSize = MAX_SIZE_CHANNEL_MESSAGE -
-			  sizeof(struct vmbus_channel_gpadl_body);
-		pfnCount = pfnSize / sizeof(u64);
-
-		/* fill in the body */
-		while (pfnLeft) {
-			if (pfnLeft > pfnCount)
-				pfnCurr = pfnCount;
-			else
-				pfnCurr = pfnLeft;
-
-			msgSize = sizeof(struct vmbus_channel_msginfo) +
-				  sizeof(struct vmbus_channel_gpadl_body) +
-				  pfnCurr * sizeof(u64);
-			msgBody = kzalloc(msgSize, GFP_KERNEL);
-			/* FIXME: we probably need to more if this fails */
-			if (!msgBody)
-				goto nomem;
-			msgBody->MessageSize = msgSize;
-			(*MessageCount)++;
-			gpadlBody =
-				(struct vmbus_channel_gpadl_body *)msgBody->Msg;
-
-			/*
-			 * FIXME:
-			 * Gpadl is u32 and we are using a pointer which could
-			 * be 64-bit
-			 */
-			/* gpadlBody->Gpadl = kbuffer; */
-			for (i = 0; i < pfnCurr; i++)
-				gpadlBody->Pfn[i] = pfn + pfnSum + i;
-
-			/* add to msg header */
-			list_add_tail(&msgBody->MsgListEntry,
-				      &msgHeader->SubMsgList);
-			pfnSum += pfnCurr;
-			pfnLeft -= pfnCurr;
-		}
-	} else {
-		/* everything fits in a header */
-		msgSize = sizeof(struct vmbus_channel_msginfo) +
-			  sizeof(struct vmbus_channel_gpadl_header) +
-			  sizeof(struct gpa_range) + pageCount * sizeof(u64);
-		msgHeader = kzalloc(msgSize, GFP_KERNEL);
-		if (msgHeader == NULL)
-			goto nomem;
-		msgHeader->MessageSize = msgSize;
-
-		gpaHeader = (struct vmbus_channel_gpadl_header *)msgHeader->Msg;
-		gpaHeader->RangeCount = 1;
-		gpaHeader->RangeBufLen = sizeof(struct gpa_range) +
-					 pageCount * sizeof(u64);
-		gpaHeader->Range[0].ByteOffset = 0;
-		gpaHeader->Range[0].ByteCount = Size;
-		for (i = 0; i < pageCount; i++)
-			gpaHeader->Range[0].PfnArray[i] = pfn+i;
-
-		*MsgInfo = msgHeader;
-		*MessageCount = 1;
-	}
-
-	return 0;
-nomem:
-	kfree(msgHeader);
-	kfree(msgBody);
-	return -ENOMEM;
-}
-
-/*
- * VmbusChannelEstablishGpadl - Estabish a GPADL for the specified buffer
- *
- * @Channel: a channel
- * @Kbuffer: from kmalloc
- * @Size: page-size multiple
- * @GpadlHandle: some funky thing
- */
-int VmbusChannelEstablishGpadl(struct vmbus_channel *Channel, void *Kbuffer,
-			       u32 Size, u32 *GpadlHandle)
-{
-	struct vmbus_channel_gpadl_header *gpadlMsg;
-	struct vmbus_channel_gpadl_body *gpadlBody;
-	/* struct vmbus_channel_gpadl_created *gpadlCreated; */
-	struct vmbus_channel_msginfo *msgInfo = NULL;
-	struct vmbus_channel_msginfo *subMsgInfo;
-	u32 msgCount;
-	struct list_head *curr;
-	u32 nextGpadlHandle;
-	unsigned long flags;
-	int ret = 0;
-
-	nextGpadlHandle = atomic_read(&gVmbusConnection.NextGpadlHandle);
-	atomic_inc(&gVmbusConnection.NextGpadlHandle);
-
-	ret = VmbusChannelCreateGpadlHeader(Kbuffer, Size, &msgInfo, &msgCount);
-	if (ret)
-		return ret;
-
-	msgInfo->WaitEvent = osd_WaitEventCreate();
-	if (!msgInfo->WaitEvent) {
-		ret = -ENOMEM;
-		goto Cleanup;
-	}
-
-	gpadlMsg = (struct vmbus_channel_gpadl_header *)msgInfo->Msg;
-	gpadlMsg->Header.MessageType = ChannelMessageGpadlHeader;
-	gpadlMsg->ChildRelId = Channel->OfferMsg.ChildRelId;
-	gpadlMsg->Gpadl = nextGpadlHandle;
-
-	DumpGpadlHeader(gpadlMsg);
-
-	spin_lock_irqsave(&gVmbusConnection.channelmsg_lock, flags);
-	list_add_tail(&msgInfo->MsgListEntry,
-		      &gVmbusConnection.ChannelMsgList);
-
-	spin_unlock_irqrestore(&gVmbusConnection.channelmsg_lock, flags);
-	DPRINT_DBG(VMBUS, "buffer %p, size %d msg cnt %d",
-		   Kbuffer, Size, msgCount);
-
-	DPRINT_DBG(VMBUS, "Sending GPADL Header - len %zd",
-		   msgInfo->MessageSize - sizeof(*msgInfo));
-
-	ret = VmbusPostMessage(gpadlMsg, msgInfo->MessageSize -
-			       sizeof(*msgInfo));
-	if (ret != 0) {
-		DPRINT_ERR(VMBUS, "Unable to open channel - %d", ret);
-		goto Cleanup;
-	}
-
-	if (msgCount > 1) {
-		list_for_each(curr, &msgInfo->SubMsgList) {
-
-			/* FIXME: should this use list_entry() instead ? */
-			subMsgInfo = (struct vmbus_channel_msginfo *)curr;
-			gpadlBody =
-			     (struct vmbus_channel_gpadl_body *)subMsgInfo->Msg;
-
-			gpadlBody->Header.MessageType = ChannelMessageGpadlBody;
-			gpadlBody->Gpadl = nextGpadlHandle;
-
-			DPRINT_DBG(VMBUS, "Sending GPADL Body - len %zd",
-				   subMsgInfo->MessageSize -
-				   sizeof(*subMsgInfo));
-
-			DumpGpadlBody(gpadlBody, subMsgInfo->MessageSize -
-				      sizeof(*subMsgInfo));
-			ret = VmbusPostMessage(gpadlBody,
-					       subMsgInfo->MessageSize -
-					       sizeof(*subMsgInfo));
-			if (ret != 0)
-				goto Cleanup;
-
-		}
-	}
-	osd_WaitEventWait(msgInfo->WaitEvent);
-
-	/* At this point, we received the gpadl created msg */
-	DPRINT_DBG(VMBUS, "Received GPADL created "
-		   "(relid %d, status %d handle %x)",
-		   Channel->OfferMsg.ChildRelId,
-		   msgInfo->Response.GpadlCreated.CreationStatus,
-		   gpadlMsg->Gpadl);
-
-	*GpadlHandle = gpadlMsg->Gpadl;
-
-Cleanup:
-	spin_lock_irqsave(&gVmbusConnection.channelmsg_lock, flags);
-	list_del(&msgInfo->MsgListEntry);
-	spin_unlock_irqrestore(&gVmbusConnection.channelmsg_lock, flags);
-
-	kfree(msgInfo->WaitEvent);
-	kfree(msgInfo);
-	return ret;
-}
-
-/*
- * VmbusChannelTeardownGpadl -Teardown the specified GPADL handle
- */
-int VmbusChannelTeardownGpadl(struct vmbus_channel *Channel, u32 GpadlHandle)
-{
-	struct vmbus_channel_gpadl_teardown *msg;
-	struct vmbus_channel_msginfo *info;
-	unsigned long flags;
-	int ret;
-
-	/* ASSERT(GpadlHandle != 0); */
-
-	info = kmalloc(sizeof(*info) +
-		       sizeof(struct vmbus_channel_gpadl_teardown), GFP_KERNEL);
-	if (!info)
-		return -ENOMEM;
-
-	info->WaitEvent = osd_WaitEventCreate();
-	if (!info->WaitEvent) {
-		kfree(info);
-		return -ENOMEM;
-	}
-
-	msg = (struct vmbus_channel_gpadl_teardown *)info->Msg;
-
-	msg->Header.MessageType = ChannelMessageGpadlTeardown;
-	msg->ChildRelId = Channel->OfferMsg.ChildRelId;
-	msg->Gpadl = GpadlHandle;
-
-	spin_lock_irqsave(&gVmbusConnection.channelmsg_lock, flags);
-	list_add_tail(&info->MsgListEntry,
-		      &gVmbusConnection.ChannelMsgList);
-	spin_unlock_irqrestore(&gVmbusConnection.channelmsg_lock, flags);
-
-	ret = VmbusPostMessage(msg,
-			       sizeof(struct vmbus_channel_gpadl_teardown));
-	if (ret != 0) {
-		/* TODO: */
-		/* something... */
-	}
-
-	osd_WaitEventWait(info->WaitEvent);
-
-	/* Received a torndown response */
-	spin_lock_irqsave(&gVmbusConnection.channelmsg_lock, flags);
-	list_del(&info->MsgListEntry);
-	spin_unlock_irqrestore(&gVmbusConnection.channelmsg_lock, flags);
-
-	kfree(info->WaitEvent);
-	kfree(info);
-	return ret;
-}
-
-/*
- * VmbusChannelClose - Close the specified channel
- */
-void VmbusChannelClose(struct vmbus_channel *Channel)
-{
-	struct vmbus_channel_close_channel *msg;
-	struct vmbus_channel_msginfo *info;
-	unsigned long flags;
-	int ret;
-
-	/* Stop callback and cancel the timer asap */
-	Channel->OnChannelCallback = NULL;
-	del_timer_sync(&Channel->poll_timer);
-
-	/* Send a closing message */
-	info = kmalloc(sizeof(*info) +
-		       sizeof(struct vmbus_channel_close_channel), GFP_KERNEL);
-        /* FIXME: can't do anything other than return here because the
-	 *        function is void */
-	if (!info)
-		return;
-
-	/* info->waitEvent = osd_WaitEventCreate(); */
-
-	msg = (struct vmbus_channel_close_channel *)info->Msg;
-	msg->Header.MessageType = ChannelMessageCloseChannel;
-	msg->ChildRelId = Channel->OfferMsg.ChildRelId;
-
-	ret = VmbusPostMessage(msg, sizeof(struct vmbus_channel_close_channel));
-	if (ret != 0) {
-		/* TODO: */
-		/* something... */
-	}
-
-	/* Tear down the gpadl for the channel's ring buffer */
-	if (Channel->RingBufferGpadlHandle)
-		VmbusChannelTeardownGpadl(Channel,
-					  Channel->RingBufferGpadlHandle);
-
-	/* TODO: Send a msg to release the childRelId */
-
-	/* Cleanup the ring buffers for this channel */
-	RingBufferCleanup(&Channel->Outbound);
-	RingBufferCleanup(&Channel->Inbound);
-
-	osd_PageFree(Channel->RingBufferPages, Channel->RingBufferPageCount);
-
-	kfree(info);
-
-	/*
-	 * If we are closing the channel during an error path in
-	 * opening the channel, don't free the channel since the
-	 * caller will free the channel
-	 */
-
-	if (Channel->State == CHANNEL_OPEN_STATE) {
-		spin_lock_irqsave(&gVmbusConnection.channel_lock, flags);
-		list_del(&Channel->ListEntry);
-		spin_unlock_irqrestore(&gVmbusConnection.channel_lock, flags);
-
-		FreeVmbusChannel(Channel);
-	}
-}
-
-/**
- * VmbusChannelSendPacket() - Send the specified buffer on the given channel
- * @Channel: Pointer to vmbus_channel structure.
- * @Buffer: Pointer to the buffer you want to receive the data into.
- * @BufferLen: Maximum size of what the the buffer will hold
- * @RequestId: Identifier of the request
- * @vmbus_packet_type: Type of packet that is being send e.g. negotiate, time
- * packet etc.
- *
- * Sends data in @Buffer directly to hyper-v via the vmbus
- * This will send the data unparsed to hyper-v.
- *
- * Mainly used by Hyper-V drivers.
- */
-int VmbusChannelSendPacket(struct vmbus_channel *Channel, const void *Buffer,
-			   u32 BufferLen, u64 RequestId,
-			   enum vmbus_packet_type Type, u32 Flags)
-{
-	struct vmpacket_descriptor desc;
-	u32 packetLen = sizeof(struct vmpacket_descriptor) + BufferLen;
-	u32 packetLenAligned = ALIGN_UP(packetLen, sizeof(u64));
-	struct scatterlist bufferList[3];
-	u64 alignedData = 0;
-	int ret;
-
-	DPRINT_DBG(VMBUS, "channel %p buffer %p len %d",
-		   Channel, Buffer, BufferLen);
-
-	DumpVmbusChannel(Channel);
-
-	/* ASSERT((packetLenAligned - packetLen) < sizeof(u64)); */
-
-	/* Setup the descriptor */
-	desc.Type = Type; /* VmbusPacketTypeDataInBand; */
-	desc.Flags = Flags; /* VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED; */
-	/* in 8-bytes granularity */
-	desc.DataOffset8 = sizeof(struct vmpacket_descriptor) >> 3;
-	desc.Length8 = (u16)(packetLenAligned >> 3);
-	desc.TransactionId = RequestId;
-
-	sg_init_table(bufferList, 3);
-	sg_set_buf(&bufferList[0], &desc, sizeof(struct vmpacket_descriptor));
-	sg_set_buf(&bufferList[1], Buffer, BufferLen);
-	sg_set_buf(&bufferList[2], &alignedData, packetLenAligned - packetLen);
-
-	ret = RingBufferWrite(&Channel->Outbound, bufferList, 3);
-
-	/* TODO: We should determine if this is optional */
-	if (ret == 0 && !GetRingBufferInterruptMask(&Channel->Outbound))
-		VmbusChannelSetEvent(Channel);
-
-	return ret;
-}
-EXPORT_SYMBOL(VmbusChannelSendPacket);
-
-/*
- * VmbusChannelSendPacketPageBuffer - Send a range of single-page buffer
- * packets using a GPADL Direct packet type.
- */
-int VmbusChannelSendPacketPageBuffer(struct vmbus_channel *Channel,
-				     struct hv_page_buffer PageBuffers[],
-				     u32 PageCount, void *Buffer, u32 BufferLen,
-				     u64 RequestId)
-{
-	int ret;
-	int i;
-	struct VMBUS_CHANNEL_PACKET_PAGE_BUFFER desc;
-	u32 descSize;
-	u32 packetLen;
-	u32 packetLenAligned;
-	struct scatterlist bufferList[3];
-	u64 alignedData = 0;
-
-	if (PageCount > MAX_PAGE_BUFFER_COUNT)
-		return -EINVAL;
-
-	DumpVmbusChannel(Channel);
-
-	/*
-	 * Adjust the size down since VMBUS_CHANNEL_PACKET_PAGE_BUFFER is the
-	 * largest size we support
-	 */
-	descSize = sizeof(struct VMBUS_CHANNEL_PACKET_PAGE_BUFFER) -
-			  ((MAX_PAGE_BUFFER_COUNT - PageCount) *
-			  sizeof(struct hv_page_buffer));
-	packetLen = descSize + BufferLen;
-	packetLenAligned = ALIGN_UP(packetLen, sizeof(u64));
-
-	/* ASSERT((packetLenAligned - packetLen) < sizeof(u64)); */
-
-	/* Setup the descriptor */
-	desc.Type = VmbusPacketTypeDataUsingGpaDirect;
-	desc.Flags = VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED;
-	desc.DataOffset8 = descSize >> 3; /* in 8-bytes grandularity */
-	desc.Length8 = (u16)(packetLenAligned >> 3);
-	desc.TransactionId = RequestId;
-	desc.RangeCount = PageCount;
-
-	for (i = 0; i < PageCount; i++) {
-		desc.Range[i].Length = PageBuffers[i].Length;
-		desc.Range[i].Offset = PageBuffers[i].Offset;
-		desc.Range[i].Pfn	 = PageBuffers[i].Pfn;
-	}
-
-	sg_init_table(bufferList, 3);
-	sg_set_buf(&bufferList[0], &desc, descSize);
-	sg_set_buf(&bufferList[1], Buffer, BufferLen);
-	sg_set_buf(&bufferList[2], &alignedData, packetLenAligned - packetLen);
-
-	ret = RingBufferWrite(&Channel->Outbound, bufferList, 3);
-
-	/* TODO: We should determine if this is optional */
-	if (ret == 0 && !GetRingBufferInterruptMask(&Channel->Outbound))
-		VmbusChannelSetEvent(Channel);
-
-	return ret;
-}
-
-/*
- * VmbusChannelSendPacketMultiPageBuffer - Send a multi-page buffer packet
- * using a GPADL Direct packet type.
- */
-int VmbusChannelSendPacketMultiPageBuffer(struct vmbus_channel *Channel,
-				struct hv_multipage_buffer *MultiPageBuffer,
-				void *Buffer, u32 BufferLen, u64 RequestId)
-{
-	int ret;
-	struct VMBUS_CHANNEL_PACKET_MULITPAGE_BUFFER desc;
-	u32 descSize;
-	u32 packetLen;
-	u32 packetLenAligned;
-	struct scatterlist bufferList[3];
-	u64 alignedData = 0;
-	u32 PfnCount = NUM_PAGES_SPANNED(MultiPageBuffer->Offset,
-					 MultiPageBuffer->Length);
-
-	DumpVmbusChannel(Channel);
-
-	DPRINT_DBG(VMBUS, "data buffer - offset %u len %u pfn count %u",
-		   MultiPageBuffer->Offset, MultiPageBuffer->Length, PfnCount);
-
-	if ((PfnCount < 0) || (PfnCount > MAX_MULTIPAGE_BUFFER_COUNT))
-		return -EINVAL;
-
-	/*
-	 * Adjust the size down since VMBUS_CHANNEL_PACKET_MULITPAGE_BUFFER is
-	 * the largest size we support
-	 */
-	descSize = sizeof(struct VMBUS_CHANNEL_PACKET_MULITPAGE_BUFFER) -
-			  ((MAX_MULTIPAGE_BUFFER_COUNT - PfnCount) *
-			  sizeof(u64));
-	packetLen = descSize + BufferLen;
-	packetLenAligned = ALIGN_UP(packetLen, sizeof(u64));
-
-	/* ASSERT((packetLenAligned - packetLen) < sizeof(u64)); */
-
-	/* Setup the descriptor */
-	desc.Type = VmbusPacketTypeDataUsingGpaDirect;
-	desc.Flags = VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED;
-	desc.DataOffset8 = descSize >> 3; /* in 8-bytes grandularity */
-	desc.Length8 = (u16)(packetLenAligned >> 3);
-	desc.TransactionId = RequestId;
-	desc.RangeCount = 1;
-
-	desc.Range.Length = MultiPageBuffer->Length;
-	desc.Range.Offset = MultiPageBuffer->Offset;
-
-	memcpy(desc.Range.PfnArray, MultiPageBuffer->PfnArray,
-	       PfnCount * sizeof(u64));
-
-	sg_init_table(bufferList, 3);
-	sg_set_buf(&bufferList[0], &desc, descSize);
-	sg_set_buf(&bufferList[1], Buffer, BufferLen);
-	sg_set_buf(&bufferList[2], &alignedData, packetLenAligned - packetLen);
-
-	ret = RingBufferWrite(&Channel->Outbound, bufferList, 3);
-
-	/* TODO: We should determine if this is optional */
-	if (ret == 0 && !GetRingBufferInterruptMask(&Channel->Outbound))
-		VmbusChannelSetEvent(Channel);
-
-	return ret;
-}
-
-
-/**
- * VmbusChannelRecvPacket() - Retrieve the user packet on the specified channel
- * @Channel: Pointer to vmbus_channel structure.
- * @Buffer: Pointer to the buffer you want to receive the data into.
- * @BufferLen: Maximum size of what the the buffer will hold
- * @BufferActualLen: The actual size of the data after it was received
- * @RequestId: Identifier of the request
- *
- * Receives directly from the hyper-v vmbus and puts the data it received
- * into Buffer. This will receive the data unparsed from hyper-v.
- *
- * Mainly used by Hyper-V drivers.
- */
-int VmbusChannelRecvPacket(struct vmbus_channel *Channel, void *Buffer,
-			   u32 BufferLen, u32 *BufferActualLen, u64 *RequestId)
-{
-	struct vmpacket_descriptor desc;
-	u32 packetLen;
-	u32 userLen;
-	int ret;
-	unsigned long flags;
-
-	*BufferActualLen = 0;
-	*RequestId = 0;
-
-	spin_lock_irqsave(&Channel->inbound_lock, flags);
-
-	ret = RingBufferPeek(&Channel->Inbound, &desc,
-			     sizeof(struct vmpacket_descriptor));
-	if (ret != 0) {
-		spin_unlock_irqrestore(&Channel->inbound_lock, flags);
-
-		/* DPRINT_DBG(VMBUS, "nothing to read!!"); */
-		return 0;
-	}
-
-	/* VmbusChannelClearEvent(Channel); */
-
-	packetLen = desc.Length8 << 3;
-	userLen = packetLen - (desc.DataOffset8 << 3);
-	/* ASSERT(userLen > 0); */
-
-	DPRINT_DBG(VMBUS, "packet received on channel %p relid %d <type %d "
-		   "flag %d tid %llx pktlen %d datalen %d> ",
-		   Channel, Channel->OfferMsg.ChildRelId, desc.Type,
-		   desc.Flags, desc.TransactionId, packetLen, userLen);
-
-	*BufferActualLen = userLen;
-
-	if (userLen > BufferLen) {
-		spin_unlock_irqrestore(&Channel->inbound_lock, flags);
-
-		DPRINT_ERR(VMBUS, "buffer too small - got %d needs %d",
-			   BufferLen, userLen);
-		return -1;
-	}
-
-	*RequestId = desc.TransactionId;
-
-	/* Copy over the packet to the user buffer */
-	ret = RingBufferRead(&Channel->Inbound, Buffer, userLen,
-			     (desc.DataOffset8 << 3));
-
-	spin_unlock_irqrestore(&Channel->inbound_lock, flags);
-
-	return 0;
-}
-EXPORT_SYMBOL(VmbusChannelRecvPacket);
-
-/*
- * VmbusChannelRecvPacketRaw - Retrieve the raw packet on the specified channel
- */
-int VmbusChannelRecvPacketRaw(struct vmbus_channel *Channel, void *Buffer,
-			      u32 BufferLen, u32 *BufferActualLen,
-			      u64 *RequestId)
-{
-	struct vmpacket_descriptor desc;
-	u32 packetLen;
-	u32 userLen;
-	int ret;
-	unsigned long flags;
-
-	*BufferActualLen = 0;
-	*RequestId = 0;
-
-	spin_lock_irqsave(&Channel->inbound_lock, flags);
-
-	ret = RingBufferPeek(&Channel->Inbound, &desc,
-			     sizeof(struct vmpacket_descriptor));
-	if (ret != 0) {
-		spin_unlock_irqrestore(&Channel->inbound_lock, flags);
-
-		/* DPRINT_DBG(VMBUS, "nothing to read!!"); */
-		return 0;
-	}
-
-	/* VmbusChannelClearEvent(Channel); */
-
-	packetLen = desc.Length8 << 3;
-	userLen = packetLen - (desc.DataOffset8 << 3);
-
-	DPRINT_DBG(VMBUS, "packet received on channel %p relid %d <type %d "
-		   "flag %d tid %llx pktlen %d datalen %d> ",
-		   Channel, Channel->OfferMsg.ChildRelId, desc.Type,
-		   desc.Flags, desc.TransactionId, packetLen, userLen);
-
-	*BufferActualLen = packetLen;
-
-	if (packetLen > BufferLen) {
-		spin_unlock_irqrestore(&Channel->inbound_lock, flags);
-
-		DPRINT_ERR(VMBUS, "buffer too small - needed %d bytes but "
-			   "got space for only %d bytes", packetLen, BufferLen);
-		return -2;
-	}
-
-	*RequestId = desc.TransactionId;
-
-	/* Copy over the entire packet to the user buffer */
-	ret = RingBufferRead(&Channel->Inbound, Buffer, packetLen, 0);
-
-	spin_unlock_irqrestore(&Channel->inbound_lock, flags);
-	return 0;
-}
-
-/*
- * VmbusChannelOnChannelEvent - Channel event callback
- */
-void VmbusChannelOnChannelEvent(struct vmbus_channel *Channel)
-{
-	DumpVmbusChannel(Channel);
-	/* ASSERT(Channel->OnChannelCallback); */
-
-	Channel->OnChannelCallback(Channel->ChannelCallbackContext);
-
-	mod_timer(&Channel->poll_timer, jiffies + usecs_to_jiffies(100));
-}
-
-/*
- * VmbusChannelOnTimer - Timer event callback
- */
-void VmbusChannelOnTimer(unsigned long data)
-{
-	struct vmbus_channel *channel = (struct vmbus_channel *)data;
-
-	if (channel->OnChannelCallback)
-		channel->OnChannelCallback(channel->ChannelCallbackContext);
-}
-
-/*
- * DumpVmbusChannel - Dump vmbus channel info to the console
- */
-static void DumpVmbusChannel(struct vmbus_channel *Channel)
-{
-	DPRINT_DBG(VMBUS, "Channel (%d)", Channel->OfferMsg.ChildRelId);
-	DumpRingInfo(&Channel->Outbound, "Outbound ");
-	DumpRingInfo(&Channel->Inbound, "Inbound ");
-}
diff --git a/drivers/staging/hv/Channel.h b/drivers/staging/hv/Channel.h
deleted file mode 100644
index 6b283ed..0000000
--- a/drivers/staging/hv/Channel.h
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- *
- * Copyright (c) 2009, Microsoft Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place - Suite 330, Boston, MA 02111-1307 USA.
- *
- * Authors:
- *   Haiyang Zhang <haiyangz@microsoft.com>
- *   Hank Janssen  <hjanssen@microsoft.com>
- *
- */
-
-
-#ifndef _CHANNEL_H_
-#define _CHANNEL_H_
-
-#include "ChannelMgmt.h"
-
-/* The format must be the same as struct vmdata_gpa_direct */
-struct VMBUS_CHANNEL_PACKET_PAGE_BUFFER {
-	u16 Type;
-	u16 DataOffset8;
-	u16 Length8;
-	u16 Flags;
-	u64 TransactionId;
-	u32 Reserved;
-	u32 RangeCount;
-	struct hv_page_buffer Range[MAX_PAGE_BUFFER_COUNT];
-} __attribute__((packed));
-
-/* The format must be the same as struct vmdata_gpa_direct */
-struct VMBUS_CHANNEL_PACKET_MULITPAGE_BUFFER {
-	u16 Type;
-	u16 DataOffset8;
-	u16 Length8;
-	u16 Flags;
-	u64 TransactionId;
-	u32 Reserved;
-	u32 RangeCount;		/* Always 1 in this case */
-	struct hv_multipage_buffer Range;
-} __attribute__((packed));
-
-
-extern int VmbusChannelOpen(struct vmbus_channel *channel,
-			    u32 SendRingBufferSize,
-			    u32 RecvRingBufferSize,
-			    void *UserData,
-			    u32 UserDataLen,
-			    void(*OnChannelCallback)(void *context),
-			    void *Context);
-
-extern void VmbusChannelClose(struct vmbus_channel *channel);
-
-extern int VmbusChannelSendPacket(struct vmbus_channel *channel,
-				  const void *Buffer,
-				  u32 BufferLen,
-				  u64 RequestId,
-				  enum vmbus_packet_type Type,
-				  u32 Flags);
-
-extern int VmbusChannelSendPacketPageBuffer(struct vmbus_channel *channel,
-					    struct hv_page_buffer PageBuffers[],
-					    u32 PageCount,
-					    void *Buffer,
-					    u32 BufferLen,
-					    u64 RequestId);
-
-extern int VmbusChannelSendPacketMultiPageBuffer(struct vmbus_channel *channel,
-					struct hv_multipage_buffer *mpb,
-					void *Buffer,
-					u32 BufferLen,
-					u64 RequestId);
-
-extern int VmbusChannelEstablishGpadl(struct vmbus_channel *channel,
-				      void *Kbuffer,
-				      u32 Size,
-				      u32 *GpadlHandle);
-
-extern int VmbusChannelTeardownGpadl(struct vmbus_channel *channel,
-				     u32 GpadlHandle);
-
-extern int VmbusChannelRecvPacket(struct vmbus_channel *channel,
-				  void *Buffer,
-				  u32 BufferLen,
-				  u32 *BufferActualLen,
-				  u64 *RequestId);
-
-extern int VmbusChannelRecvPacketRaw(struct vmbus_channel *channel,
-				     void *Buffer,
-				     u32 BufferLen,
-				     u32 *BufferActualLen,
-				     u64 *RequestId);
-
-extern void VmbusChannelOnChannelEvent(struct vmbus_channel *channel);
-
-extern void VmbusChannelGetDebugInfo(struct vmbus_channel *channel,
-				     struct vmbus_channel_debug_info *debug);
-
-extern void VmbusChannelOnTimer(unsigned long data);
-
-#endif /* _CHANNEL_H_ */
diff --git a/drivers/staging/hv/ChannelInterface.c b/drivers/staging/hv/ChannelInterface.c
deleted file mode 100644
index 019b064..0000000
--- a/drivers/staging/hv/ChannelInterface.c
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
- *
- * Copyright (c) 2009, Microsoft Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place - Suite 330, Boston, MA 02111-1307 USA.
- *
- * Authors:
- *   Haiyang Zhang <haiyangz@microsoft.com>
- *   Hank Janssen  <hjanssen@microsoft.com>
- *
- */
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include "osd.h"
-#include "VmbusPrivate.h"
-
-static int IVmbusChannelOpen(struct hv_device *device, u32 SendBufferSize,
-			     u32 RecvRingBufferSize, void *UserData,
-			     u32 UserDataLen,
-			     void (*ChannelCallback)(void *context),
-			     void *Context)
-{
-	return VmbusChannelOpen(device->context, SendBufferSize,
-				RecvRingBufferSize, UserData, UserDataLen,
-				ChannelCallback, Context);
-}
-
-static void IVmbusChannelClose(struct hv_device *device)
-{
-	VmbusChannelClose(device->context);
-}
-
-static int IVmbusChannelSendPacket(struct hv_device *device, const void *Buffer,
-				   u32 BufferLen, u64 RequestId, u32 Type,
-				   u32 Flags)
-{
-	return VmbusChannelSendPacket(device->context, Buffer, BufferLen,
-				      RequestId, Type, Flags);
-}
-
-static int IVmbusChannelSendPacketPageBuffer(struct hv_device *device,
-				struct hv_page_buffer PageBuffers[],
-				u32 PageCount, void *Buffer,
-				u32 BufferLen, u64 RequestId)
-{
-	return VmbusChannelSendPacketPageBuffer(device->context, PageBuffers,
-						PageCount, Buffer, BufferLen,
-						RequestId);
-}
-
-static int IVmbusChannelSendPacketMultiPageBuffer(struct hv_device *device,
-				struct hv_multipage_buffer *MultiPageBuffer,
-				void *Buffer, u32 BufferLen, u64 RequestId)
-{
-	return VmbusChannelSendPacketMultiPageBuffer(device->context,
-						     MultiPageBuffer, Buffer,
-						     BufferLen, RequestId);
-}
-
-static int IVmbusChannelRecvPacket(struct hv_device *device, void *Buffer,
-				   u32 BufferLen, u32 *BufferActualLen,
-				   u64 *RequestId)
-{
-	return VmbusChannelRecvPacket(device->context, Buffer, BufferLen,
-				      BufferActualLen, RequestId);
-}
-
-static int IVmbusChannelRecvPacketRaw(struct hv_device *device, void *Buffer,
-				      u32 BufferLen, u32 *BufferActualLen,
-				      u64 *RequestId)
-{
-	return VmbusChannelRecvPacketRaw(device->context, Buffer, BufferLen,
-					 BufferActualLen, RequestId);
-}
-
-static int IVmbusChannelEstablishGpadl(struct hv_device *device, void *Buffer,
-				       u32 BufferLen, u32 *GpadlHandle)
-{
-	return VmbusChannelEstablishGpadl(device->context, Buffer, BufferLen,
-					  GpadlHandle);
-}
-
-static int IVmbusChannelTeardownGpadl(struct hv_device *device, u32 GpadlHandle)
-{
-	return VmbusChannelTeardownGpadl(device->context, GpadlHandle);
-
-}
-
-void GetChannelInterface(struct vmbus_channel_interface *iface)
-{
-	iface->Open = IVmbusChannelOpen;
-	iface->Close	= IVmbusChannelClose;
-	iface->SendPacket = IVmbusChannelSendPacket;
-	iface->SendPacketPageBuffer = IVmbusChannelSendPacketPageBuffer;
-	iface->SendPacketMultiPageBuffer =
-					IVmbusChannelSendPacketMultiPageBuffer;
-	iface->RecvPacket = IVmbusChannelRecvPacket;
-	iface->RecvPacketRaw	= IVmbusChannelRecvPacketRaw;
-	iface->EstablishGpadl = IVmbusChannelEstablishGpadl;
-	iface->TeardownGpadl = IVmbusChannelTeardownGpadl;
-	iface->GetInfo = GetChannelInfo;
-}
-
-void GetChannelInfo(struct hv_device *device, struct hv_device_info *info)
-{
-	struct vmbus_channel_debug_info debugInfo;
-
-	if (!device->context)
-		return;
-
-	VmbusChannelGetDebugInfo(device->context, &debugInfo);
-
-	info->ChannelId = debugInfo.RelId;
-	info->ChannelState = debugInfo.State;
-	memcpy(&info->ChannelType, &debugInfo.InterfaceType,
-	       sizeof(struct hv_guid));
-	memcpy(&info->ChannelInstance, &debugInfo.InterfaceInstance,
-	       sizeof(struct hv_guid));
-
-	info->MonitorId = debugInfo.MonitorId;
-
-	info->ServerMonitorPending = debugInfo.ServerMonitorPending;
-	info->ServerMonitorLatency = debugInfo.ServerMonitorLatency;
-	info->ServerMonitorConnectionId = debugInfo.ServerMonitorConnectionId;
-
-	info->ClientMonitorPending = debugInfo.ClientMonitorPending;
-	info->ClientMonitorLatency = debugInfo.ClientMonitorLatency;
-	info->ClientMonitorConnectionId = debugInfo.ClientMonitorConnectionId;
-
-	info->Inbound.InterruptMask = debugInfo.Inbound.CurrentInterruptMask;
-	info->Inbound.ReadIndex = debugInfo.Inbound.CurrentReadIndex;
-	info->Inbound.WriteIndex = debugInfo.Inbound.CurrentWriteIndex;
-	info->Inbound.BytesAvailToRead = debugInfo.Inbound.BytesAvailToRead;
-	info->Inbound.BytesAvailToWrite = debugInfo.Inbound.BytesAvailToWrite;
-
-	info->Outbound.InterruptMask = debugInfo.Outbound.CurrentInterruptMask;
-	info->Outbound.ReadIndex = debugInfo.Outbound.CurrentReadIndex;
-	info->Outbound.WriteIndex = debugInfo.Outbound.CurrentWriteIndex;
-	info->Outbound.BytesAvailToRead = debugInfo.Outbound.BytesAvailToRead;
-	info->Outbound.BytesAvailToWrite = debugInfo.Outbound.BytesAvailToWrite;
-}
diff --git a/drivers/staging/hv/ChannelInterface.h b/drivers/staging/hv/ChannelInterface.h
deleted file mode 100644
index 27b7a25..0000000
--- a/drivers/staging/hv/ChannelInterface.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- *
- * Copyright (c) 2009, Microsoft Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place - Suite 330, Boston, MA 02111-1307 USA.
- *
- * Authors:
- *   Haiyang Zhang <haiyangz@microsoft.com>
- *   Hank Janssen  <hjanssen@microsoft.com>
- *
- */
-
-
-#ifndef _CHANNEL_INTERFACE_H_
-#define _CHANNEL_INTERFACE_H_
-
-#include "VmbusApi.h"
-
-void GetChannelInterface(struct vmbus_channel_interface *ChannelInterface);
-
-void GetChannelInfo(struct hv_device *Device,
-		    struct hv_device_info *DeviceInfo);
-
-#endif /* _CHANNEL_INTERFACE_H_ */
diff --git a/drivers/staging/hv/ChannelMgmt.c b/drivers/staging/hv/ChannelMgmt.c
deleted file mode 100644
index 8d27f70..0000000
--- a/drivers/staging/hv/ChannelMgmt.c
+++ /dev/null
@@ -1,851 +0,0 @@
-/*
- * Copyright (c) 2009, Microsoft Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place - Suite 330, Boston, MA 02111-1307 USA.
- *
- * Authors:
- *   Haiyang Zhang <haiyangz@microsoft.com>
- *   Hank Janssen  <hjanssen@microsoft.com>
- */
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/list.h>
-#include <linux/module.h>
-#include <linux/completion.h>
-#include "osd.h"
-#include "logging.h"
-#include "VmbusPrivate.h"
-#include "utils.h"
-
-struct vmbus_channel_message_table_entry {
-	enum vmbus_channel_message_type messageType;
-	void (*messageHandler)(struct vmbus_channel_message_header *msg);
-};
-
-#define MAX_MSG_TYPES                    3
-#define MAX_NUM_DEVICE_CLASSES_SUPPORTED 7
-
-static const struct hv_guid
-	gSupportedDeviceClasses[MAX_NUM_DEVICE_CLASSES_SUPPORTED] = {
-	/* {ba6163d9-04a1-4d29-b605-72e2ffb1dc7f} */
-	/* Storage - SCSI */
-	{
-		.data  = {
-			0xd9, 0x63, 0x61, 0xba, 0xa1, 0x04, 0x29, 0x4d,
-			0xb6, 0x05, 0x72, 0xe2, 0xff, 0xb1, 0xdc, 0x7f
-		}
-	},
-
-	/* {F8615163-DF3E-46c5-913F-F2D2F965ED0E} */
-	/* Network */
-	{
-		.data = {
-			0x63, 0x51, 0x61, 0xF8, 0x3E, 0xDF, 0xc5, 0x46,
-			0x91, 0x3F, 0xF2, 0xD2, 0xF9, 0x65, 0xED, 0x0E
-		}
-	},
-
-	/* {CFA8B69E-5B4A-4cc0-B98B-8BA1A1F3F95A} */
-	/* Input */
-	{
-		.data = {
-			0x9E, 0xB6, 0xA8, 0xCF, 0x4A, 0x5B, 0xc0, 0x4c,
-			0xB9, 0x8B, 0x8B, 0xA1, 0xA1, 0xF3, 0xF9, 0x5A
-		}
-	},
-
-	/* {32412632-86cb-44a2-9b5c-50d1417354f5} */
-	/* IDE */
-	{
-		.data = {
-			0x32, 0x26, 0x41, 0x32, 0xcb, 0x86, 0xa2, 0x44,
-			0x9b, 0x5c, 0x50, 0xd1, 0x41, 0x73, 0x54, 0xf5
-		}
-	},
-	/* 0E0B6031-5213-4934-818B-38D90CED39DB */
-	/* Shutdown */
-	{
-		.data = {
-			0x31, 0x60, 0x0B, 0X0E, 0x13, 0x52, 0x34, 0x49,
-			0x81, 0x8B, 0x38, 0XD9, 0x0C, 0xED, 0x39, 0xDB
-		}
-	},
-	/* {9527E630-D0AE-497b-ADCE-E80AB0175CAF} */
-	/* TimeSync */
-	{
-		.data = {
-			0x30, 0xe6, 0x27, 0x95, 0xae, 0xd0, 0x7b, 0x49,
-			0xad, 0xce, 0xe8, 0x0a, 0xb0, 0x17, 0x5c, 0xaf
-		}
-	},
-	/* {57164f39-9115-4e78-ab55-382f3bd5422d} */
-	/* Heartbeat */
-	{
-		.data = {
-			0x39, 0x4f, 0x16, 0x57, 0x15, 0x91, 0x78, 0x4e,
-			0xab, 0x55, 0x38, 0x2f, 0x3b, 0xd5, 0x42, 0x2d
-		}
-	},
-};
-
-
-/**
- * prep_negotiate_resp() - Create default response for Hyper-V Negotiate message
- * @icmsghdrp: Pointer to msg header structure
- * @icmsg_negotiate: Pointer to negotiate message structure
- * @buf: Raw buffer channel data
- *
- * @icmsghdrp is of type &struct icmsg_hdr.
- * @negop is of type &struct icmsg_negotiate.
- * Set up and fill in default negotiate response message. This response can
- * come from both the vmbus driver and the hv_utils driver. The current api
- * will respond properly to both Windows 2008 and Windows 2008-R2 operating
- * systems.
- *
- * Mainly used by Hyper-V drivers.
- */
-void prep_negotiate_resp(struct icmsg_hdr *icmsghdrp,
-			     struct icmsg_negotiate *negop,
-			     u8 *buf)
-{
-	if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
-		icmsghdrp->icmsgsize = 0x10;
-
-		negop = (struct icmsg_negotiate *)&buf[
-			sizeof(struct vmbuspipe_hdr) +
-			sizeof(struct icmsg_hdr)];
-
-		if (negop->icframe_vercnt == 2 &&
-		   negop->icversion_data[1].major == 3) {
-			negop->icversion_data[0].major = 3;
-			negop->icversion_data[0].minor = 0;
-			negop->icversion_data[1].major = 3;
-			negop->icversion_data[1].minor = 0;
-		} else {
-			negop->icversion_data[0].major = 1;
-			negop->icversion_data[0].minor = 0;
-			negop->icversion_data[1].major = 1;
-			negop->icversion_data[1].minor = 0;
-		}
-
-		negop->icframe_vercnt = 1;
-		negop->icmsg_vercnt = 1;
-	}
-}
-EXPORT_SYMBOL(prep_negotiate_resp);
-
-/**
- * chn_cb_negotiate() - Default handler for non IDE/SCSI/NETWORK
- * Hyper-V requests
- * @context: Pointer to argument structure.
- *
- * Set up the default handler for non device driver specific requests
- * from Hyper-V. This stub responds to the default negotiate messages
- * that come in for every non IDE/SCSI/Network request.
- * This behavior is normally overwritten in the hv_utils driver. That
- * driver handles requests like gracefull shutdown, heartbeats etc.
- *
- * Mainly used by Hyper-V drivers.
- */
-void chn_cb_negotiate(void *context)
-{
-	struct vmbus_channel *channel = context;
-	u8 *buf;
-	u32 buflen, recvlen;
-	u64 requestid;
-
-	struct icmsg_hdr *icmsghdrp;
-	struct icmsg_negotiate *negop = NULL;
-
-	buflen = PAGE_SIZE;
-	buf = kmalloc(buflen, GFP_ATOMIC);
-
-	VmbusChannelRecvPacket(channel, buf, buflen, &recvlen, &requestid);
-
-	if (recvlen > 0) {
-		icmsghdrp = (struct icmsg_hdr *)&buf[
-			sizeof(struct vmbuspipe_hdr)];
-
-		prep_negotiate_resp(icmsghdrp, negop, buf);
-
-		icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION
-			| ICMSGHDRFLAG_RESPONSE;
-
-		VmbusChannelSendPacket(channel, buf,
-				       recvlen, requestid,
-				       VmbusPacketTypeDataInBand, 0);
-	}
-
-	kfree(buf);
-}
-EXPORT_SYMBOL(chn_cb_negotiate);
-
-/*
- * Function table used for message responses for non IDE/SCSI/Network type
- * messages. (Such as KVP/Shutdown etc)
- */
-struct hyperv_service_callback hv_cb_utils[MAX_MSG_TYPES] = {
-	/* 0E0B6031-5213-4934-818B-38D90CED39DB */
-	/* Shutdown */
-	{
-		.msg_type = HV_SHUTDOWN_MSG,
-		.data = {
-			0x31, 0x60, 0x0B, 0X0E, 0x13, 0x52, 0x34, 0x49,
-			0x81, 0x8B, 0x38, 0XD9, 0x0C, 0xED, 0x39, 0xDB
-		},
-		.callback = chn_cb_negotiate,
-		.log_msg = "Shutdown channel functionality initialized"
-	},
-
-	/* {9527E630-D0AE-497b-ADCE-E80AB0175CAF} */
-	/* TimeSync */
-	{
-		.msg_type = HV_TIMESYNC_MSG,
-		.data = {
-			0x30, 0xe6, 0x27, 0x95, 0xae, 0xd0, 0x7b, 0x49,
-			0xad, 0xce, 0xe8, 0x0a, 0xb0, 0x17, 0x5c, 0xaf
-		},
-		.callback = chn_cb_negotiate,
-		.log_msg = "Timesync channel functionality initialized"
-	},
-	/* {57164f39-9115-4e78-ab55-382f3bd5422d} */
-	/* Heartbeat */
-	{
-		.msg_type = HV_HEARTBEAT_MSG,
-		.data = {
-			0x39, 0x4f, 0x16, 0x57, 0x15, 0x91, 0x78, 0x4e,
-			0xab, 0x55, 0x38, 0x2f, 0x3b, 0xd5, 0x42, 0x2d
-		},
-		.callback = chn_cb_negotiate,
-		.log_msg = "Heartbeat channel functionality initialized"
-	},
-};
-EXPORT_SYMBOL(hv_cb_utils);
-
-/*
- * AllocVmbusChannel - Allocate and initialize a vmbus channel object
- */
-struct vmbus_channel *AllocVmbusChannel(void)
-{
-	struct vmbus_channel *channel;
-
-	channel = kzalloc(sizeof(*channel), GFP_ATOMIC);
-	if (!channel)
-		return NULL;
-
-	spin_lock_init(&channel->inbound_lock);
-
-	init_timer(&channel->poll_timer);
-	channel->poll_timer.data = (unsigned long)channel;
-	channel->poll_timer.function = VmbusChannelOnTimer;
-
-	channel->ControlWQ = create_workqueue("hv_vmbus_ctl");
-	if (!channel->ControlWQ) {
-		kfree(channel);
-		return NULL;
-	}
-
-	return channel;
-}
-
-/*
- * ReleaseVmbusChannel - Release the vmbus channel object itself
- */
-static inline void ReleaseVmbusChannel(void *context)
-{
-	struct vmbus_channel *channel = context;
-
-	DPRINT_DBG(VMBUS, "releasing channel (%p)", channel);
-	destroy_workqueue(channel->ControlWQ);
-	DPRINT_DBG(VMBUS, "channel released (%p)", channel);
-
-	kfree(channel);
-}
-
-/*
- * FreeVmbusChannel - Release the resources used by the vmbus channel object
- */
-void FreeVmbusChannel(struct vmbus_channel *Channel)
-{
-	del_timer_sync(&Channel->poll_timer);
-
-	/*
-	 * We have to release the channel's workqueue/thread in the vmbus's
-	 * workqueue/thread context
-	 * ie we can't destroy ourselves.
-	 */
-	osd_schedule_callback(gVmbusConnection.WorkQueue, ReleaseVmbusChannel,
-			      Channel);
-}
-
-
-DECLARE_COMPLETION(hv_channel_ready);
-
-/*
- * Count initialized channels, and ensure all channels are ready when hv_vmbus
- * module loading completes.
- */
-static void count_hv_channel(void)
-{
-	static int counter;
-	unsigned long flags;
-
-	spin_lock_irqsave(&gVmbusConnection.channel_lock, flags);
-	if (++counter == MAX_MSG_TYPES)
-		complete(&hv_channel_ready);
-	spin_unlock_irqrestore(&gVmbusConnection.channel_lock, flags);
-}
-
-
-/*
- * VmbusChannelProcessOffer - Process the offer by creating a channel/device
- * associated with this offer
- */
-static void VmbusChannelProcessOffer(void *context)
-{
-	struct vmbus_channel *newChannel = context;
-	struct vmbus_channel *channel;
-	bool fNew = true;
-	int ret;
-	int cnt;
-	unsigned long flags;
-
-	/* Make sure this is a new offer */
-	spin_lock_irqsave(&gVmbusConnection.channel_lock, flags);
-
-	list_for_each_entry(channel, &gVmbusConnection.ChannelList, ListEntry) {
-		if (!memcmp(&channel->OfferMsg.Offer.InterfaceType,
-			    &newChannel->OfferMsg.Offer.InterfaceType,
-			    sizeof(struct hv_guid)) &&
-		    !memcmp(&channel->OfferMsg.Offer.InterfaceInstance,
-			    &newChannel->OfferMsg.Offer.InterfaceInstance,
-			    sizeof(struct hv_guid))) {
-			fNew = false;
-			break;
-		}
-	}
-
-	if (fNew)
-		list_add_tail(&newChannel->ListEntry,
-			      &gVmbusConnection.ChannelList);
-
-	spin_unlock_irqrestore(&gVmbusConnection.channel_lock, flags);
-
-	if (!fNew) {
-		DPRINT_DBG(VMBUS, "Ignoring duplicate offer for relid (%d)",
-			   newChannel->OfferMsg.ChildRelId);
-		FreeVmbusChannel(newChannel);
-		return;
-	}
-
-	/*
-	 * Start the process of binding this offer to the driver
-	 * We need to set the DeviceObject field before calling
-	 * VmbusChildDeviceAdd()
-	 */
-	newChannel->DeviceObject = VmbusChildDeviceCreate(
-		&newChannel->OfferMsg.Offer.InterfaceType,
-		&newChannel->OfferMsg.Offer.InterfaceInstance,
-		newChannel);
-
-	DPRINT_DBG(VMBUS, "child device object allocated - %p",
-		   newChannel->DeviceObject);
-
-	/*
-	 * Add the new device to the bus. This will kick off device-driver
-	 * binding which eventually invokes the device driver's AddDevice()
-	 * method.
-	 */
-	ret = VmbusChildDeviceAdd(newChannel->DeviceObject);
-	if (ret != 0) {
-		DPRINT_ERR(VMBUS,
-			   "unable to add child device object (relid %d)",
-			   newChannel->OfferMsg.ChildRelId);
-
-		spin_lock_irqsave(&gVmbusConnection.channel_lock, flags);
-		list_del(&newChannel->ListEntry);
-		spin_unlock_irqrestore(&gVmbusConnection.channel_lock, flags);
-
-		FreeVmbusChannel(newChannel);
-	} else {
-		/*
-		 * This state is used to indicate a successful open
-		 * so that when we do close the channel normally, we
-		 * can cleanup properly
-		 */
-		newChannel->State = CHANNEL_OPEN_STATE;
-
-		/* Open IC channels */
-		for (cnt = 0; cnt < MAX_MSG_TYPES; cnt++) {
-			if (memcmp(&newChannel->OfferMsg.Offer.InterfaceType,
-				   &hv_cb_utils[cnt].data,
-				   sizeof(struct hv_guid)) == 0 &&
-				VmbusChannelOpen(newChannel, 2 * PAGE_SIZE,
-						 2 * PAGE_SIZE, NULL, 0,
-						 hv_cb_utils[cnt].callback,
-						 newChannel) == 0) {
-				hv_cb_utils[cnt].channel = newChannel;
-				DPRINT_INFO(VMBUS, "%s",
-						hv_cb_utils[cnt].log_msg);
-				count_hv_channel();
-			}
-		}
-	}
-}
-
-/*
- * VmbusChannelProcessRescindOffer - Rescind the offer by initiating a device removal
- */
-static void VmbusChannelProcessRescindOffer(void *context)
-{
-	struct vmbus_channel *channel = context;
-
-	VmbusChildDeviceRemove(channel->DeviceObject);
-}
-
-/*
- * VmbusChannelOnOffer - Handler for channel offers from vmbus in parent partition.
- *
- * We ignore all offers except network and storage offers. For each network and
- * storage offers, we create a channel object and queue a work item to the
- * channel object to process the offer synchronously
- */
-static void VmbusChannelOnOffer(struct vmbus_channel_message_header *hdr)
-{
-	struct vmbus_channel_offer_channel *offer;
-	struct vmbus_channel *newChannel;
-	struct hv_guid *guidType;
-	struct hv_guid *guidInstance;
-	int i;
-	int fSupported = 0;
-
-	offer = (struct vmbus_channel_offer_channel *)hdr;
-	for (i = 0; i < MAX_NUM_DEVICE_CLASSES_SUPPORTED; i++) {
-		if (memcmp(&offer->Offer.InterfaceType,
-		    &gSupportedDeviceClasses[i], sizeof(struct hv_guid)) == 0) {
-			fSupported = 1;
-			break;
-		}
-	}
-
-	if (!fSupported) {
-		DPRINT_DBG(VMBUS, "Ignoring channel offer notification for "
-			   "child relid %d", offer->ChildRelId);
-		return;
-	}
-
-	guidType = &offer->Offer.InterfaceType;
-	guidInstance = &offer->Offer.InterfaceInstance;
-
-	DPRINT_INFO(VMBUS, "Channel offer notification - "
-		    "child relid %d monitor id %d allocated %d, "
-		    "type {%02x%02x%02x%02x-%02x%02x-%02x%02x-"
-		    "%02x%02x%02x%02x%02x%02x%02x%02x} "
-		    "instance {%02x%02x%02x%02x-%02x%02x-%02x%02x-"
-		    "%02x%02x%02x%02x%02x%02x%02x%02x}",
-		    offer->ChildRelId, offer->MonitorId,
-		    offer->MonitorAllocated,
-		    guidType->data[3], guidType->data[2],
-		    guidType->data[1], guidType->data[0],
-		    guidType->data[5], guidType->data[4],
-		    guidType->data[7], guidType->data[6],
-		    guidType->data[8], guidType->data[9],
-		    guidType->data[10], guidType->data[11],
-		    guidType->data[12], guidType->data[13],
-		    guidType->data[14], guidType->data[15],
-		    guidInstance->data[3], guidInstance->data[2],
-		    guidInstance->data[1], guidInstance->data[0],
-		    guidInstance->data[5], guidInstance->data[4],
-		    guidInstance->data[7], guidInstance->data[6],
-		    guidInstance->data[8], guidInstance->data[9],
-		    guidInstance->data[10], guidInstance->data[11],
-		    guidInstance->data[12], guidInstance->data[13],
-		    guidInstance->data[14], guidInstance->data[15]);
-
-	/* Allocate the channel object and save this offer. */
-	newChannel = AllocVmbusChannel();
-	if (!newChannel) {
-		DPRINT_ERR(VMBUS, "unable to allocate channel object");
-		return;
-	}
-
-	DPRINT_DBG(VMBUS, "channel object allocated - %p", newChannel);
-
-	memcpy(&newChannel->OfferMsg, offer,
-	       sizeof(struct vmbus_channel_offer_channel));
-	newChannel->MonitorGroup = (u8)offer->MonitorId / 32;
-	newChannel->MonitorBit = (u8)offer->MonitorId % 32;
-
-	/* TODO: Make sure the offer comes from our parent partition */
-	osd_schedule_callback(newChannel->ControlWQ, VmbusChannelProcessOffer,
-			      newChannel);
-}
-
-/*
- * VmbusChannelOnOfferRescind - Rescind offer handler.
- *
- * We queue a work item to process this offer synchronously
- */
-static void VmbusChannelOnOfferRescind(struct vmbus_channel_message_header *hdr)
-{
-	struct vmbus_channel_rescind_offer *rescind;
-	struct vmbus_channel *channel;
-
-	rescind = (struct vmbus_channel_rescind_offer *)hdr;
-	channel = GetChannelFromRelId(rescind->ChildRelId);
-	if (channel == NULL) {
-		DPRINT_DBG(VMBUS, "channel not found for relId %d",
-			   rescind->ChildRelId);
-		return;
-	}
-
-	osd_schedule_callback(channel->ControlWQ,
-			      VmbusChannelProcessRescindOffer,
-			      channel);
-}
-
-/*
- * VmbusChannelOnOffersDelivered - This is invoked when all offers have been delivered.
- *
- * Nothing to do here.
- */
-static void VmbusChannelOnOffersDelivered(
-			struct vmbus_channel_message_header *hdr)
-{
-}
-
-/*
- * VmbusChannelOnOpenResult - Open result handler.
- *
- * This is invoked when we received a response to our channel open request.
- * Find the matching request, copy the response and signal the requesting
- * thread.
- */
-static void VmbusChannelOnOpenResult(struct vmbus_channel_message_header *hdr)
-{
-	struct vmbus_channel_open_result *result;
-	struct list_head *curr;
-	struct vmbus_channel_msginfo *msgInfo;
-	struct vmbus_channel_message_header *requestHeader;
-	struct vmbus_channel_open_channel *openMsg;
-	unsigned long flags;
-
-	result = (struct vmbus_channel_open_result *)hdr;
-	DPRINT_DBG(VMBUS, "vmbus open result - %d", result->Status);
-
-	/*
-	 * Find the open msg, copy the result and signal/unblock the wait event
-	 */
-	spin_lock_irqsave(&gVmbusConnection.channelmsg_lock, flags);
-
-	list_for_each(curr, &gVmbusConnection.ChannelMsgList) {
-/* FIXME: this should probably use list_entry() instead */
-		msgInfo = (struct vmbus_channel_msginfo *)curr;
-		requestHeader = (struct vmbus_channel_message_header *)msgInfo->Msg;
-
-		if (requestHeader->MessageType == ChannelMessageOpenChannel) {
-			openMsg = (struct vmbus_channel_open_channel *)msgInfo->Msg;
-			if (openMsg->ChildRelId == result->ChildRelId &&
-			    openMsg->OpenId == result->OpenId) {
-				memcpy(&msgInfo->Response.OpenResult,
-				       result,
-				       sizeof(struct vmbus_channel_open_result));
-				osd_WaitEventSet(msgInfo->WaitEvent);
-				break;
-			}
-		}
-	}
-	spin_unlock_irqrestore(&gVmbusConnection.channelmsg_lock, flags);
-}
-
-/*
- * VmbusChannelOnGpadlCreated - GPADL created handler.
- *
- * This is invoked when we received a response to our gpadl create request.
- * Find the matching request, copy the response and signal the requesting
- * thread.
- */
-static void VmbusChannelOnGpadlCreated(struct vmbus_channel_message_header *hdr)
-{
-	struct vmbus_channel_gpadl_created *gpadlCreated;
-	struct list_head *curr;
-	struct vmbus_channel_msginfo *msgInfo;
-	struct vmbus_channel_message_header *requestHeader;
-	struct vmbus_channel_gpadl_header *gpadlHeader;
-	unsigned long flags;
-
-	gpadlCreated = (struct vmbus_channel_gpadl_created *)hdr;
-	DPRINT_DBG(VMBUS, "vmbus gpadl created result - %d",
-		   gpadlCreated->CreationStatus);
-
-	/*
-	 * Find the establish msg, copy the result and signal/unblock the wait
-	 * event
-	 */
-	spin_lock_irqsave(&gVmbusConnection.channelmsg_lock, flags);
-
-	list_for_each(curr, &gVmbusConnection.ChannelMsgList) {
-/* FIXME: this should probably use list_entry() instead */
-		msgInfo = (struct vmbus_channel_msginfo *)curr;
-		requestHeader = (struct vmbus_channel_message_header *)msgInfo->Msg;
-
-		if (requestHeader->MessageType == ChannelMessageGpadlHeader) {
-			gpadlHeader = (struct vmbus_channel_gpadl_header *)requestHeader;
-
-			if ((gpadlCreated->ChildRelId ==
-			     gpadlHeader->ChildRelId) &&
-			    (gpadlCreated->Gpadl == gpadlHeader->Gpadl)) {
-				memcpy(&msgInfo->Response.GpadlCreated,
-				       gpadlCreated,
-				       sizeof(struct vmbus_channel_gpadl_created));
-				osd_WaitEventSet(msgInfo->WaitEvent);
-				break;
-			}
-		}
-	}
-	spin_unlock_irqrestore(&gVmbusConnection.channelmsg_lock, flags);
-}
-
-/*
- * VmbusChannelOnGpadlTorndown - GPADL torndown handler.
- *
- * This is invoked when we received a response to our gpadl teardown request.
- * Find the matching request, copy the response and signal the requesting
- * thread.
- */
-static void VmbusChannelOnGpadlTorndown(
-			struct vmbus_channel_message_header *hdr)
-{
-	struct vmbus_channel_gpadl_torndown *gpadlTorndown;
-	struct list_head *curr;
-	struct vmbus_channel_msginfo *msgInfo;
-	struct vmbus_channel_message_header *requestHeader;
-	struct vmbus_channel_gpadl_teardown *gpadlTeardown;
-	unsigned long flags;
-
-	gpadlTorndown = (struct vmbus_channel_gpadl_torndown *)hdr;
-
-	/*
-	 * Find the open msg, copy the result and signal/unblock the wait event
-	 */
-	spin_lock_irqsave(&gVmbusConnection.channelmsg_lock, flags);
-
-	list_for_each(curr, &gVmbusConnection.ChannelMsgList) {
-/* FIXME: this should probably use list_entry() instead */
-		msgInfo = (struct vmbus_channel_msginfo *)curr;
-		requestHeader = (struct vmbus_channel_message_header *)msgInfo->Msg;
-
-		if (requestHeader->MessageType == ChannelMessageGpadlTeardown) {
-			gpadlTeardown = (struct vmbus_channel_gpadl_teardown *)requestHeader;
-
-			if (gpadlTorndown->Gpadl == gpadlTeardown->Gpadl) {
-				memcpy(&msgInfo->Response.GpadlTorndown,
-				       gpadlTorndown,
-				       sizeof(struct vmbus_channel_gpadl_torndown));
-				osd_WaitEventSet(msgInfo->WaitEvent);
-				break;
-			}
-		}
-	}
-	spin_unlock_irqrestore(&gVmbusConnection.channelmsg_lock, flags);
-}
-
-/*
- * VmbusChannelOnVersionResponse - Version response handler
- *
- * This is invoked when we received a response to our initiate contact request.
- * Find the matching request, copy the response and signal the requesting
- * thread.
- */
-static void VmbusChannelOnVersionResponse(
-		struct vmbus_channel_message_header *hdr)
-{
-	struct list_head *curr;
-	struct vmbus_channel_msginfo *msgInfo;
-	struct vmbus_channel_message_header *requestHeader;
-	struct vmbus_channel_initiate_contact *initiate;
-	struct vmbus_channel_version_response *versionResponse;
-	unsigned long flags;
-
-	versionResponse = (struct vmbus_channel_version_response *)hdr;
-	spin_lock_irqsave(&gVmbusConnection.channelmsg_lock, flags);
-
-	list_for_each(curr, &gVmbusConnection.ChannelMsgList) {
-/* FIXME: this should probably use list_entry() instead */
-		msgInfo = (struct vmbus_channel_msginfo *)curr;
-		requestHeader = (struct vmbus_channel_message_header *)msgInfo->Msg;
-
-		if (requestHeader->MessageType ==
-		    ChannelMessageInitiateContact) {
-			initiate = (struct vmbus_channel_initiate_contact *)requestHeader;
-			memcpy(&msgInfo->Response.VersionResponse,
-			      versionResponse,
-			      sizeof(struct vmbus_channel_version_response));
-			osd_WaitEventSet(msgInfo->WaitEvent);
-		}
-	}
-	spin_unlock_irqrestore(&gVmbusConnection.channelmsg_lock, flags);
-}
-
-/* Channel message dispatch table */
-static struct vmbus_channel_message_table_entry
-	gChannelMessageTable[ChannelMessageCount] = {
-	{ChannelMessageInvalid,			NULL},
-	{ChannelMessageOfferChannel,		VmbusChannelOnOffer},
-	{ChannelMessageRescindChannelOffer,	VmbusChannelOnOfferRescind},
-	{ChannelMessageRequestOffers,		NULL},
-	{ChannelMessageAllOffersDelivered,	VmbusChannelOnOffersDelivered},
-	{ChannelMessageOpenChannel,		NULL},
-	{ChannelMessageOpenChannelResult,	VmbusChannelOnOpenResult},
-	{ChannelMessageCloseChannel,		NULL},
-	{ChannelMessageGpadlHeader,		NULL},
-	{ChannelMessageGpadlBody,		NULL},
-	{ChannelMessageGpadlCreated,		VmbusChannelOnGpadlCreated},
-	{ChannelMessageGpadlTeardown,		NULL},
-	{ChannelMessageGpadlTorndown,		VmbusChannelOnGpadlTorndown},
-	{ChannelMessageRelIdReleased,		NULL},
-	{ChannelMessageInitiateContact,		NULL},
-	{ChannelMessageVersionResponse,		VmbusChannelOnVersionResponse},
-	{ChannelMessageUnload,			NULL},
-};
-
-/*
- * VmbusOnChannelMessage - Handler for channel protocol messages.
- *
- * This is invoked in the vmbus worker thread context.
- */
-void VmbusOnChannelMessage(void *Context)
-{
-	struct hv_message *msg = Context;
-	struct vmbus_channel_message_header *hdr;
-	int size;
-
-	hdr = (struct vmbus_channel_message_header *)msg->u.Payload;
-	size = msg->Header.PayloadSize;
-
-	DPRINT_DBG(VMBUS, "message type %d size %d", hdr->MessageType, size);
-
-	if (hdr->MessageType >= ChannelMessageCount) {
-		DPRINT_ERR(VMBUS,
-			   "Received invalid channel message type %d size %d",
-			   hdr->MessageType, size);
-		print_hex_dump_bytes("", DUMP_PREFIX_NONE,
-				     (unsigned char *)msg->u.Payload, size);
-		kfree(msg);
-		return;
-	}
-
-	if (gChannelMessageTable[hdr->MessageType].messageHandler)
-		gChannelMessageTable[hdr->MessageType].messageHandler(hdr);
-	else
-		DPRINT_ERR(VMBUS, "Unhandled channel message type %d",
-			   hdr->MessageType);
-
-	/* Free the msg that was allocated in VmbusOnMsgDPC() */
-	kfree(msg);
-}
-
-/*
- * VmbusChannelRequestOffers - Send a request to get all our pending offers.
- */
-int VmbusChannelRequestOffers(void)
-{
-	struct vmbus_channel_message_header *msg;
-	struct vmbus_channel_msginfo *msgInfo;
-	int ret;
-
-	msgInfo = kmalloc(sizeof(*msgInfo) +
-			  sizeof(struct vmbus_channel_message_header),
-			  GFP_KERNEL);
-	if (!msgInfo)
-		return -ENOMEM;
-
-	msgInfo->WaitEvent = osd_WaitEventCreate();
-	if (!msgInfo->WaitEvent) {
-		kfree(msgInfo);
-		return -ENOMEM;
-	}
-
-	msg = (struct vmbus_channel_message_header *)msgInfo->Msg;
-
-	msg->MessageType = ChannelMessageRequestOffers;
-
-	/*SpinlockAcquire(gVmbusConnection.channelMsgLock);
-	INSERT_TAIL_LIST(&gVmbusConnection.channelMsgList,
-			 &msgInfo->msgListEntry);
-	SpinlockRelease(gVmbusConnection.channelMsgLock);*/
-
-	ret = VmbusPostMessage(msg,
-			       sizeof(struct vmbus_channel_message_header));
-	if (ret != 0) {
-		DPRINT_ERR(VMBUS, "Unable to request offers - %d", ret);
-
-		/*SpinlockAcquire(gVmbusConnection.channelMsgLock);
-		REMOVE_ENTRY_LIST(&msgInfo->msgListEntry);
-		SpinlockRelease(gVmbusConnection.channelMsgLock);*/
-
-		goto Cleanup;
-	}
-	/* osd_WaitEventWait(msgInfo->waitEvent); */
-
-	/*SpinlockAcquire(gVmbusConnection.channelMsgLock);
-	REMOVE_ENTRY_LIST(&msgInfo->msgListEntry);
-	SpinlockRelease(gVmbusConnection.channelMsgLock);*/
-
-
-Cleanup:
-	if (msgInfo) {
-		kfree(msgInfo->WaitEvent);
-		kfree(msgInfo);
-	}
-
-	return ret;
-}
-
-/*
- * VmbusChannelReleaseUnattachedChannels - Release channels that are
- * unattached/unconnected ie (no drivers associated)
- */
-void VmbusChannelReleaseUnattachedChannels(void)
-{
-	struct vmbus_channel *channel, *pos;
-	struct vmbus_channel *start = NULL;
-	unsigned long flags;
-
-	spin_lock_irqsave(&gVmbusConnection.channel_lock, flags);
-
-	list_for_each_entry_safe(channel, pos, &gVmbusConnection.ChannelList,
-				 ListEntry) {
-		if (channel == start)
-			break;
-
-		if (!channel->DeviceObject->Driver) {
-			list_del(&channel->ListEntry);
-			DPRINT_INFO(VMBUS,
-				    "Releasing unattached device object %p",
-				    channel->DeviceObject);
-
-			VmbusChildDeviceRemove(channel->DeviceObject);
-			FreeVmbusChannel(channel);
-		} else {
-			if (!start)
-				start = channel;
-		}
-	}
-
-	spin_unlock_irqrestore(&gVmbusConnection.channel_lock, flags);
-}
-
-/* eof */
diff --git a/drivers/staging/hv/ChannelMgmt.h b/drivers/staging/hv/ChannelMgmt.h
deleted file mode 100644
index 6e2f84d..0000000
--- a/drivers/staging/hv/ChannelMgmt.h
+++ /dev/null
@@ -1,320 +0,0 @@
-/*
- *
- * Copyright (c) 2009, Microsoft Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place - Suite 330, Boston, MA 02111-1307 USA.
- *
- * Authors:
- *   Haiyang Zhang <haiyangz@microsoft.com>
- *   Hank Janssen  <hjanssen@microsoft.com>
- *
- */
-
-
-#ifndef _CHANNEL_MGMT_H_
-#define _CHANNEL_MGMT_H_
-
-#include <linux/list.h>
-#include <linux/timer.h>
-#include "RingBuffer.h"
-#include "VmbusChannelInterface.h"
-#include "VmbusPacketFormat.h"
-
-/* Version 1 messages */
-enum vmbus_channel_message_type {
-	ChannelMessageInvalid			=  0,
-	ChannelMessageOfferChannel		=  1,
-	ChannelMessageRescindChannelOffer	=  2,
-	ChannelMessageRequestOffers		=  3,
-	ChannelMessageAllOffersDelivered	=  4,
-	ChannelMessageOpenChannel		=  5,
-	ChannelMessageOpenChannelResult		=  6,
-	ChannelMessageCloseChannel		=  7,
-	ChannelMessageGpadlHeader		=  8,
-	ChannelMessageGpadlBody			=  9,
-	ChannelMessageGpadlCreated		= 10,
-	ChannelMessageGpadlTeardown		= 11,
-	ChannelMessageGpadlTorndown		= 12,
-	ChannelMessageRelIdReleased		= 13,
-	ChannelMessageInitiateContact		= 14,
-	ChannelMessageVersionResponse		= 15,
-	ChannelMessageUnload			= 16,
-#ifdef VMBUS_FEATURE_PARENT_OR_PEER_MEMORY_MAPPED_INTO_A_CHILD
-	ChannelMessageViewRangeAdd		= 17,
-	ChannelMessageViewRangeRemove		= 18,
-#endif
-	ChannelMessageCount
-};
-
-struct vmbus_channel_message_header {
-	enum vmbus_channel_message_type MessageType;
-	u32 Padding;
-} __attribute__((packed));
-
-/* Query VMBus Version parameters */
-struct vmbus_channel_query_vmbus_version {
-	struct vmbus_channel_message_header Header;
-	u32 Version;
-} __attribute__((packed));
-
-/* VMBus Version Supported parameters */
-struct vmbus_channel_version_supported {
-	struct vmbus_channel_message_header Header;
-	bool VersionSupported;
-} __attribute__((packed));
-
-/* Offer Channel parameters */
-struct vmbus_channel_offer_channel {
-	struct vmbus_channel_message_header Header;
-	struct vmbus_channel_offer Offer;
-	u32 ChildRelId;
-	u8 MonitorId;
-	bool MonitorAllocated;
-} __attribute__((packed));
-
-/* Rescind Offer parameters */
-struct vmbus_channel_rescind_offer {
-	struct vmbus_channel_message_header Header;
-	u32 ChildRelId;
-} __attribute__((packed));
-
-/*
- * Request Offer -- no parameters, SynIC message contains the partition ID
- * Set Snoop -- no parameters, SynIC message contains the partition ID
- * Clear Snoop -- no parameters, SynIC message contains the partition ID
- * All Offers Delivered -- no parameters, SynIC message contains the partition
- *		           ID
- * Flush Client -- no parameters, SynIC message contains the partition ID
- */
-
-/* Open Channel parameters */
-struct vmbus_channel_open_channel {
-	struct vmbus_channel_message_header Header;
-
-	/* Identifies the specific VMBus channel that is being opened. */
-	u32 ChildRelId;
-
-	/* ID making a particular open request at a channel offer unique. */
-	u32 OpenId;
-
-	/* GPADL for the channel's ring buffer. */
-	u32 RingBufferGpadlHandle;
-
-	/* GPADL for the channel's server context save area. */
-	u32 ServerContextAreaGpadlHandle;
-
-	/*
-	* The upstream ring buffer begins at offset zero in the memory
-	* described by RingBufferGpadlHandle. The downstream ring buffer
-	* follows it at this offset (in pages).
-	*/
-	u32 DownstreamRingBufferPageOffset;
-
-	/* User-specific data to be passed along to the server endpoint. */
-	unsigned char UserData[MAX_USER_DEFINED_BYTES];
-} __attribute__((packed));
-
-/* Open Channel Result parameters */
-struct vmbus_channel_open_result {
-	struct vmbus_channel_message_header Header;
-	u32 ChildRelId;
-	u32 OpenId;
-	u32 Status;
-} __attribute__((packed));
-
-/* Close channel parameters; */
-struct vmbus_channel_close_channel {
-	struct vmbus_channel_message_header Header;
-	u32 ChildRelId;
-} __attribute__((packed));
-
-/* Channel Message GPADL */
-#define GPADL_TYPE_RING_BUFFER		1
-#define GPADL_TYPE_SERVER_SAVE_AREA	2
-#define GPADL_TYPE_TRANSACTION		8
-
-/*
- * The number of PFNs in a GPADL message is defined by the number of
- * pages that would be spanned by ByteCount and ByteOffset.  If the
- * implied number of PFNs won't fit in this packet, there will be a
- * follow-up packet that contains more.
- */
-struct vmbus_channel_gpadl_header {
-	struct vmbus_channel_message_header Header;
-	u32 ChildRelId;
-	u32 Gpadl;
-	u16 RangeBufLen;
-	u16 RangeCount;
-	struct gpa_range Range[0];
-} __attribute__((packed));
-
-/* This is the followup packet that contains more PFNs. */
-struct vmbus_channel_gpadl_body {
-	struct vmbus_channel_message_header Header;
-	u32 MessageNumber;
-	u32 Gpadl;
-	u64 Pfn[0];
-} __attribute__((packed));
-
-struct vmbus_channel_gpadl_created {
-	struct vmbus_channel_message_header Header;
-	u32 ChildRelId;
-	u32 Gpadl;
-	u32 CreationStatus;
-} __attribute__((packed));
-
-struct vmbus_channel_gpadl_teardown {
-	struct vmbus_channel_message_header Header;
-	u32 ChildRelId;
-	u32 Gpadl;
-} __attribute__((packed));
-
-struct vmbus_channel_gpadl_torndown {
-	struct vmbus_channel_message_header Header;
-	u32 Gpadl;
-} __attribute__((packed));
-
-#ifdef VMBUS_FEATURE_PARENT_OR_PEER_MEMORY_MAPPED_INTO_A_CHILD
-struct vmbus_channel_view_range_add {
-	struct vmbus_channel_message_header Header;
-	PHYSICAL_ADDRESS ViewRangeBase;
-	u64 ViewRangeLength;
-	u32 ChildRelId;
-} __attribute__((packed));
-
-struct vmbus_channel_view_range_remove {
-	struct vmbus_channel_message_header Header;
-	PHYSICAL_ADDRESS ViewRangeBase;
-	u32 ChildRelId;
-} __attribute__((packed));
-#endif
-
-struct vmbus_channel_relid_released {
-	struct vmbus_channel_message_header Header;
-	u32 ChildRelId;
-} __attribute__((packed));
-
-struct vmbus_channel_initiate_contact {
-	struct vmbus_channel_message_header Header;
-	u32 VMBusVersionRequested;
-	u32 Padding2;
-	u64 InterruptPage;
-	u64 MonitorPage1;
-	u64 MonitorPage2;
-} __attribute__((packed));
-
-struct vmbus_channel_version_response {
-	struct vmbus_channel_message_header Header;
-	bool VersionSupported;
-} __attribute__((packed));
-
-enum vmbus_channel_state {
-	CHANNEL_OFFER_STATE,
-	CHANNEL_OPENING_STATE,
-	CHANNEL_OPEN_STATE,
-};
-
-struct vmbus_channel {
-	struct list_head ListEntry;
-
-	struct hv_device *DeviceObject;
-
-	struct timer_list poll_timer; /* SA-111 workaround */
-
-	enum vmbus_channel_state State;
-
-	struct vmbus_channel_offer_channel OfferMsg;
-	/*
-	 * These are based on the OfferMsg.MonitorId.
-	 * Save it here for easy access.
-	 */
-	u8 MonitorGroup;
-	u8 MonitorBit;
-
-	u32 RingBufferGpadlHandle;
-
-	/* Allocated memory for ring buffer */
-	void *RingBufferPages;
-	u32 RingBufferPageCount;
-	struct hv_ring_buffer_info Outbound;	/* send to parent */
-	struct hv_ring_buffer_info Inbound;	/* receive from parent */
-	spinlock_t inbound_lock;
-	struct workqueue_struct *ControlWQ;
-
-	/* Channel callback are invoked in this workqueue context */
-	/* HANDLE dataWorkQueue; */
-
-	void (*OnChannelCallback)(void *context);
-	void *ChannelCallbackContext;
-};
-
-struct vmbus_channel_debug_info {
-	u32 RelId;
-	enum vmbus_channel_state State;
-	struct hv_guid InterfaceType;
-	struct hv_guid InterfaceInstance;
-	u32 MonitorId;
-	u32 ServerMonitorPending;
-	u32 ServerMonitorLatency;
-	u32 ServerMonitorConnectionId;
-	u32 ClientMonitorPending;
-	u32 ClientMonitorLatency;
-	u32 ClientMonitorConnectionId;
-
-	struct hv_ring_buffer_debug_info Inbound;
-	struct hv_ring_buffer_debug_info Outbound;
-};
-
-/*
- * Represents each channel msg on the vmbus connection This is a
- * variable-size data structure depending on the msg type itself
- */
-struct vmbus_channel_msginfo {
-	/* Bookkeeping stuff */
-	struct list_head MsgListEntry;
-
-	/* So far, this is only used to handle gpadl body message */
-	struct list_head SubMsgList;
-
-	/* Synchronize the request/response if needed */
-	struct osd_waitevent *WaitEvent;
-
-	union {
-		struct vmbus_channel_version_supported VersionSupported;
-		struct vmbus_channel_open_result OpenResult;
-		struct vmbus_channel_gpadl_torndown GpadlTorndown;
-		struct vmbus_channel_gpadl_created GpadlCreated;
-		struct vmbus_channel_version_response VersionResponse;
-	} Response;
-
-	u32 MessageSize;
-	/*
-	 * The channel message that goes out on the "wire".
-	 * It will contain at minimum the VMBUS_CHANNEL_MESSAGE_HEADER header
-	 */
-	unsigned char Msg[0];
-};
-
-
-struct vmbus_channel *AllocVmbusChannel(void);
-
-void FreeVmbusChannel(struct vmbus_channel *Channel);
-
-void VmbusOnChannelMessage(void *Context);
-
-int VmbusChannelRequestOffers(void);
-
-void VmbusChannelReleaseUnattachedChannels(void);
-
-#endif /* _CHANNEL_MGMT_H_ */
diff --git a/drivers/staging/hv/Connection.c b/drivers/staging/hv/Connection.c
deleted file mode 100644
index b60b0c6..0000000
--- a/drivers/staging/hv/Connection.c
+++ /dev/null
@@ -1,330 +0,0 @@
-/*
- *
- * Copyright (c) 2009, Microsoft Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place - Suite 330, Boston, MA 02111-1307 USA.
- *
- * Authors:
- *   Haiyang Zhang <haiyangz@microsoft.com>
- *   Hank Janssen  <hjanssen@microsoft.com>
- *
- */
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/vmalloc.h>
-#include "osd.h"
-#include "logging.h"
-#include "VmbusPrivate.h"
-
-
-struct VMBUS_CONNECTION gVmbusConnection = {
-	.ConnectState		= Disconnected,
-	.NextGpadlHandle	= ATOMIC_INIT(0xE1E10),
-};
-
-/*
- * VmbusConnect - Sends a connect request on the partition service connection
- */
-int VmbusConnect(void)
-{
-	int ret = 0;
-	struct vmbus_channel_msginfo *msgInfo = NULL;
-	struct vmbus_channel_initiate_contact *msg;
-	unsigned long flags;
-
-	/* Make sure we are not connecting or connected */
-	if (gVmbusConnection.ConnectState != Disconnected)
-		return -1;
-
-	/* Initialize the vmbus connection */
-	gVmbusConnection.ConnectState = Connecting;
-	gVmbusConnection.WorkQueue = create_workqueue("hv_vmbus_con");
-	if (!gVmbusConnection.WorkQueue) {
-		ret = -1;
-		goto Cleanup;
-	}
-
-	INIT_LIST_HEAD(&gVmbusConnection.ChannelMsgList);
-	spin_lock_init(&gVmbusConnection.channelmsg_lock);
-
-	INIT_LIST_HEAD(&gVmbusConnection.ChannelList);
-	spin_lock_init(&gVmbusConnection.channel_lock);
-
-	/*
-	 * Setup the vmbus event connection for channel interrupt
-	 * abstraction stuff
-	 */
-	gVmbusConnection.InterruptPage = osd_PageAlloc(1);
-	if (gVmbusConnection.InterruptPage == NULL) {
-		ret = -1;
-		goto Cleanup;
-	}
-
-	gVmbusConnection.RecvInterruptPage = gVmbusConnection.InterruptPage;
-	gVmbusConnection.SendInterruptPage =
-		(void *)((unsigned long)gVmbusConnection.InterruptPage +
-			(PAGE_SIZE >> 1));
-
-	/*
-	 * Setup the monitor notification facility. The 1st page for
-	 * parent->child and the 2nd page for child->parent
-	 */
-	gVmbusConnection.MonitorPages = osd_PageAlloc(2);
-	if (gVmbusConnection.MonitorPages == NULL) {
-		ret = -1;
-		goto Cleanup;
-	}
-
-	msgInfo = kzalloc(sizeof(*msgInfo) +
-			  sizeof(struct vmbus_channel_initiate_contact),
-			  GFP_KERNEL);
-	if (msgInfo == NULL) {
-		ret = -ENOMEM;
-		goto Cleanup;
-	}
-
-	msgInfo->WaitEvent = osd_WaitEventCreate();
-	if (!msgInfo->WaitEvent) {
-		ret = -ENOMEM;
-		goto Cleanup;
-	}
-
-	msg = (struct vmbus_channel_initiate_contact *)msgInfo->Msg;
-
-	msg->Header.MessageType = ChannelMessageInitiateContact;
-	msg->VMBusVersionRequested = VMBUS_REVISION_NUMBER;
-	msg->InterruptPage = virt_to_phys(gVmbusConnection.InterruptPage);
-	msg->MonitorPage1 = virt_to_phys(gVmbusConnection.MonitorPages);
-	msg->MonitorPage2 = virt_to_phys(
-			(void *)((unsigned long)gVmbusConnection.MonitorPages +
-				 PAGE_SIZE));
-
-	/*
-	 * Add to list before we send the request since we may
-	 * receive the response before returning from this routine
-	 */
-	spin_lock_irqsave(&gVmbusConnection.channelmsg_lock, flags);
-	list_add_tail(&msgInfo->MsgListEntry,
-		      &gVmbusConnection.ChannelMsgList);
-
-	spin_unlock_irqrestore(&gVmbusConnection.channelmsg_lock, flags);
-
-	DPRINT_DBG(VMBUS, "Vmbus connection - interrupt pfn %llx, "
-		   "monitor1 pfn %llx,, monitor2 pfn %llx",
-		   msg->InterruptPage, msg->MonitorPage1, msg->MonitorPage2);
-
-	DPRINT_DBG(VMBUS, "Sending channel initiate msg...");
-	ret = VmbusPostMessage(msg,
-			       sizeof(struct vmbus_channel_initiate_contact));
-	if (ret != 0) {
-		list_del(&msgInfo->MsgListEntry);
-		goto Cleanup;
-	}
-
-	/* Wait for the connection response */
-	osd_WaitEventWait(msgInfo->WaitEvent);
-
-	list_del(&msgInfo->MsgListEntry);
-
-	/* Check if successful */
-	if (msgInfo->Response.VersionResponse.VersionSupported) {
-		DPRINT_INFO(VMBUS, "Vmbus connected!!");
-		gVmbusConnection.ConnectState = Connected;
-
-	} else {
-		DPRINT_ERR(VMBUS, "Vmbus connection failed!!..."
-			   "current version (%d) not supported",
-			   VMBUS_REVISION_NUMBER);
-		ret = -1;
-		goto Cleanup;
-	}
-
-	kfree(msgInfo->WaitEvent);
-	kfree(msgInfo);
-	return 0;
-
-Cleanup:
-	gVmbusConnection.ConnectState = Disconnected;
-
-	if (gVmbusConnection.WorkQueue)
-		destroy_workqueue(gVmbusConnection.WorkQueue);
-
-	if (gVmbusConnection.InterruptPage) {
-		osd_PageFree(gVmbusConnection.InterruptPage, 1);
-		gVmbusConnection.InterruptPage = NULL;
-	}
-
-	if (gVmbusConnection.MonitorPages) {
-		osd_PageFree(gVmbusConnection.MonitorPages, 2);
-		gVmbusConnection.MonitorPages = NULL;
-	}
-
-	if (msgInfo) {
-		kfree(msgInfo->WaitEvent);
-		kfree(msgInfo);
-	}
-
-	return ret;
-}
-
-/*
- * VmbusDisconnect - Sends a disconnect request on the partition service connection
- */
-int VmbusDisconnect(void)
-{
-	int ret = 0;
-	struct vmbus_channel_message_header *msg;
-
-	/* Make sure we are connected */
-	if (gVmbusConnection.ConnectState != Connected)
-		return -1;
-
-	msg = kzalloc(sizeof(struct vmbus_channel_message_header), GFP_KERNEL);
-	if (!msg)
-		return -ENOMEM;
-
-	msg->MessageType = ChannelMessageUnload;
-
-	ret = VmbusPostMessage(msg,
-			       sizeof(struct vmbus_channel_message_header));
-	if (ret != 0)
-		goto Cleanup;
-
-	osd_PageFree(gVmbusConnection.InterruptPage, 1);
-
-	/* TODO: iterate thru the msg list and free up */
-	destroy_workqueue(gVmbusConnection.WorkQueue);
-
-	gVmbusConnection.ConnectState = Disconnected;
-
-	DPRINT_INFO(VMBUS, "Vmbus disconnected!!");
-
-Cleanup:
-	kfree(msg);
-	return ret;
-}
-
-/*
- * GetChannelFromRelId - Get the channel object given its child relative id (ie channel id)
- */
-struct vmbus_channel *GetChannelFromRelId(u32 relId)
-{
-	struct vmbus_channel *channel;
-	struct vmbus_channel *foundChannel  = NULL;
-	unsigned long flags;
-
-	spin_lock_irqsave(&gVmbusConnection.channel_lock, flags);
-	list_for_each_entry(channel, &gVmbusConnection.ChannelList, ListEntry) {
-		if (channel->OfferMsg.ChildRelId == relId) {
-			foundChannel = channel;
-			break;
-		}
-	}
-	spin_unlock_irqrestore(&gVmbusConnection.channel_lock, flags);
-
-	return foundChannel;
-}
-
-/*
- * VmbusProcessChannelEvent - Process a channel event notification
- */
-static void VmbusProcessChannelEvent(void *context)
-{
-	struct vmbus_channel *channel;
-	u32 relId = (u32)(unsigned long)context;
-
-	/* ASSERT(relId > 0); */
-
-	/*
-	 * Find the channel based on this relid and invokes the
-	 * channel callback to process the event
-	 */
-	channel = GetChannelFromRelId(relId);
-
-	if (channel) {
-		VmbusChannelOnChannelEvent(channel);
-		/*
-		 * WorkQueueQueueWorkItem(channel->dataWorkQueue,
-		 *			  VmbusChannelOnChannelEvent,
-		 *			  (void*)channel);
-		 */
-	} else {
-		DPRINT_ERR(VMBUS, "channel not found for relid - %d.", relId);
-	}
-}
-
-/*
- * VmbusOnEvents - Handler for events
- */
-void VmbusOnEvents(void)
-{
-	int dword;
-	int maxdword = MAX_NUM_CHANNELS_SUPPORTED >> 5;
-	int bit;
-	int relid;
-	u32 *recvInterruptPage = gVmbusConnection.RecvInterruptPage;
-
-	/* Check events */
-	if (recvInterruptPage) {
-		for (dword = 0; dword < maxdword; dword++) {
-			if (recvInterruptPage[dword]) {
-				for (bit = 0; bit < 32; bit++) {
-					if (sync_test_and_clear_bit(bit,
-						(unsigned long *)
-						&recvInterruptPage[dword])) {
-						relid = (dword << 5) + bit;
-						DPRINT_DBG(VMBUS, "event detected for relid - %d", relid);
-
-						if (relid == 0) {
-							/* special case - vmbus channel protocol msg */
-							DPRINT_DBG(VMBUS, "invalid relid - %d", relid);
-							continue;
-						} else {
-							/* QueueWorkItem(VmbusProcessEvent, (void*)relid); */
-							/* ret = WorkQueueQueueWorkItem(gVmbusConnection.workQueue, VmbusProcessChannelEvent, (void*)relid); */
-							VmbusProcessChannelEvent((void *)(unsigned long)relid);
-						}
-					}
-				}
-			}
-		 }
-	}
-	return;
-}
-
-/*
- * VmbusPostMessage - Send a msg on the vmbus's message connection
- */
-int VmbusPostMessage(void *buffer, size_t bufferLen)
-{
-	union hv_connection_id connId;
-
-	connId.Asu32 = 0;
-	connId.u.Id = VMBUS_MESSAGE_CONNECTION_ID;
-	return HvPostMessage(connId, 1, buffer, bufferLen);
-}
-
-/*
- * VmbusSetEvent - Send an event notification to the parent
- */
-int VmbusSetEvent(u32 childRelId)
-{
-	/* Each u32 represents 32 channels */
-	sync_set_bit(childRelId & 31,
-		(unsigned long *)gVmbusConnection.SendInterruptPage +
-		(childRelId >> 5));
-
-	return HvSignalEvent();
-}
diff --git a/drivers/staging/hv/Hv.c b/drivers/staging/hv/Hv.c
deleted file mode 100644
index d580270..0000000
--- a/drivers/staging/hv/Hv.c
+++ /dev/null
@@ -1,499 +0,0 @@
-/*
- * Copyright (c) 2009, Microsoft Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place - Suite 330, Boston, MA 02111-1307 USA.
- *
- * Authors:
- *   Haiyang Zhang <haiyangz@microsoft.com>
- *   Hank Janssen  <hjanssen@microsoft.com>
- *
- */
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/vmalloc.h>
-#include "osd.h"
-#include "logging.h"
-#include "VmbusPrivate.h"
-
-/* The one and only */
-struct hv_context gHvContext = {
-	.SynICInitialized	= false,
-	.HypercallPage		= NULL,
-	.SignalEventParam	= NULL,
-	.SignalEventBuffer	= NULL,
-};
-
-/*
- * HvQueryHypervisorPresence - Query the cpuid for presense of windows hypervisor
- */
-static int HvQueryHypervisorPresence(void)
-{
-	unsigned int eax;
-	unsigned int ebx;
-	unsigned int ecx;
-	unsigned int edx;
-	unsigned int op;
-
-	eax = 0;
-	ebx = 0;
-	ecx = 0;
-	edx = 0;
-	op = HvCpuIdFunctionVersionAndFeatures;
-	cpuid(op, &eax, &ebx, &ecx, &edx);
-
-	return ecx & HV_PRESENT_BIT;
-}
-
-/*
- * HvQueryHypervisorInfo - Get version info of the windows hypervisor
- */
-static int HvQueryHypervisorInfo(void)
-{
-	unsigned int eax;
-	unsigned int ebx;
-	unsigned int ecx;
-	unsigned int edx;
-	unsigned int maxLeaf;
-	unsigned int op;
-
-	/*
-	* Its assumed that this is called after confirming that Viridian
-	* is present. Query id and revision.
-	*/
-	eax = 0;
-	ebx = 0;
-	ecx = 0;
-	edx = 0;
-	op = HvCpuIdFunctionHvVendorAndMaxFunction;
-	cpuid(op, &eax, &ebx, &ecx, &edx);
-
-	DPRINT_INFO(VMBUS, "Vendor ID: %c%c%c%c%c%c%c%c%c%c%c%c",
-		    (ebx & 0xFF),
-		    ((ebx >> 8) & 0xFF),
-		    ((ebx >> 16) & 0xFF),
-		    ((ebx >> 24) & 0xFF),
-		    (ecx & 0xFF),
-		    ((ecx >> 8) & 0xFF),
-		    ((ecx >> 16) & 0xFF),
-		    ((ecx >> 24) & 0xFF),
-		    (edx & 0xFF),
-		    ((edx >> 8) & 0xFF),
-		    ((edx >> 16) & 0xFF),
-		    ((edx >> 24) & 0xFF));
-
-	maxLeaf = eax;
-	eax = 0;
-	ebx = 0;
-	ecx = 0;
-	edx = 0;
-	op = HvCpuIdFunctionHvInterface;
-	cpuid(op, &eax, &ebx, &ecx, &edx);
-
-	DPRINT_INFO(VMBUS, "Interface ID: %c%c%c%c",
-		    (eax & 0xFF),
-		    ((eax >> 8) & 0xFF),
-		    ((eax >> 16) & 0xFF),
-		    ((eax >> 24) & 0xFF));
-
-	if (maxLeaf >= HvCpuIdFunctionMsHvVersion) {
-		eax = 0;
-		ebx = 0;
-		ecx = 0;
-		edx = 0;
-		op = HvCpuIdFunctionMsHvVersion;
-		cpuid(op, &eax, &ebx, &ecx, &edx);
-		DPRINT_INFO(VMBUS, "OS Build:%d-%d.%d-%d-%d.%d",\
-			    eax,
-			    ebx >> 16,
-			    ebx & 0xFFFF,
-			    ecx,
-			    edx >> 24,
-			    edx & 0xFFFFFF);
-	}
-	return maxLeaf;
-}
-
-/*
- * HvDoHypercall - Invoke the specified hypercall
- */
-static u64 HvDoHypercall(u64 Control, void *Input, void *Output)
-{
-#ifdef CONFIG_X86_64
-	u64 hvStatus = 0;
-	u64 inputAddress = (Input) ? virt_to_phys(Input) : 0;
-	u64 outputAddress = (Output) ? virt_to_phys(Output) : 0;
-	volatile void *hypercallPage = gHvContext.HypercallPage;
-
-	DPRINT_DBG(VMBUS, "Hypercall <control %llx input phys %llx virt %p "
-		   "output phys %llx virt %p hypercall %p>",
-		   Control, inputAddress, Input,
-		   outputAddress, Output, hypercallPage);
-
-	__asm__ __volatile__("mov %0, %%r8" : : "r" (outputAddress) : "r8");
-	__asm__ __volatile__("call *%3" : "=a" (hvStatus) :
-			     "c" (Control), "d" (inputAddress),
-			     "m" (hypercallPage));
-
-	DPRINT_DBG(VMBUS, "Hypercall <return %llx>",  hvStatus);
-
-	return hvStatus;
-
-#else
-
-	u32 controlHi = Control >> 32;
-	u32 controlLo = Control & 0xFFFFFFFF;
-	u32 hvStatusHi = 1;
-	u32 hvStatusLo = 1;
-	u64 inputAddress = (Input) ? virt_to_phys(Input) : 0;
-	u32 inputAddressHi = inputAddress >> 32;
-	u32 inputAddressLo = inputAddress & 0xFFFFFFFF;
-	u64 outputAddress = (Output) ? virt_to_phys(Output) : 0;
-	u32 outputAddressHi = outputAddress >> 32;
-	u32 outputAddressLo = outputAddress & 0xFFFFFFFF;
-	volatile void *hypercallPage = gHvContext.HypercallPage;
-
-	DPRINT_DBG(VMBUS, "Hypercall <control %llx input %p output %p>",
-		   Control, Input, Output);
-
-	__asm__ __volatile__ ("call *%8" : "=d"(hvStatusHi),
-			      "=a"(hvStatusLo) : "d" (controlHi),
-			      "a" (controlLo), "b" (inputAddressHi),
-			      "c" (inputAddressLo), "D"(outputAddressHi),
-			      "S"(outputAddressLo), "m" (hypercallPage));
-
-	DPRINT_DBG(VMBUS, "Hypercall <return %llx>",
-		   hvStatusLo | ((u64)hvStatusHi << 32));
-
-	return hvStatusLo | ((u64)hvStatusHi << 32);
-#endif /* !x86_64 */
-}
-
-/*
- * HvInit - Main initialization routine.
- *
- * This routine must be called before any other routines in here are called
- */
-int HvInit(void)
-{
-	int ret = 0;
-	int maxLeaf;
-	union hv_x64_msr_hypercall_contents hypercallMsr;
-	void *virtAddr = NULL;
-
-	memset(gHvContext.synICEventPage, 0, sizeof(void *) * MAX_NUM_CPUS);
-	memset(gHvContext.synICMessagePage, 0, sizeof(void *) * MAX_NUM_CPUS);
-
-	if (!HvQueryHypervisorPresence()) {
-		DPRINT_ERR(VMBUS, "No Windows hypervisor detected!!");
-		goto Cleanup;
-	}
-
-	DPRINT_INFO(VMBUS,
-		    "Windows hypervisor detected! Retrieving more info...");
-
-	maxLeaf = HvQueryHypervisorInfo();
-	/* HvQueryHypervisorFeatures(maxLeaf); */
-
-	/*
-	 * We only support running on top of Hyper-V
-	 */
-	rdmsrl(HV_X64_MSR_GUEST_OS_ID, gHvContext.GuestId);
-
-	if (gHvContext.GuestId != 0) {
-		DPRINT_ERR(VMBUS, "Unknown guest id (0x%llx)!!",
-				gHvContext.GuestId);
-		goto Cleanup;
-	}
-
-	/* Write our OS info */
-	wrmsrl(HV_X64_MSR_GUEST_OS_ID, HV_LINUX_GUEST_ID);
-	gHvContext.GuestId = HV_LINUX_GUEST_ID;
-
-	/* See if the hypercall page is already set */
-	rdmsrl(HV_X64_MSR_HYPERCALL, hypercallMsr.AsUINT64);
-
-	/*
-	* Allocate the hypercall page memory
-	* virtAddr = osd_PageAlloc(1);
-	*/
-	virtAddr = osd_VirtualAllocExec(PAGE_SIZE);
-
-	if (!virtAddr) {
-		DPRINT_ERR(VMBUS,
-			   "unable to allocate hypercall page!!");
-		goto Cleanup;
-	}
-
-	hypercallMsr.Enable = 1;
-
-	hypercallMsr.GuestPhysicalAddress = vmalloc_to_pfn(virtAddr);
-	wrmsrl(HV_X64_MSR_HYPERCALL, hypercallMsr.AsUINT64);
-
-	/* Confirm that hypercall page did get setup. */
-	hypercallMsr.AsUINT64 = 0;
-	rdmsrl(HV_X64_MSR_HYPERCALL, hypercallMsr.AsUINT64);
-
-	if (!hypercallMsr.Enable) {
-		DPRINT_ERR(VMBUS, "unable to set hypercall page!!");
-		goto Cleanup;
-	}
-
-	gHvContext.HypercallPage = virtAddr;
-
-	DPRINT_INFO(VMBUS, "Hypercall page VA=%p, PA=0x%0llx",
-		    gHvContext.HypercallPage,
-		    (u64)hypercallMsr.GuestPhysicalAddress << PAGE_SHIFT);
-
-	/* Setup the global signal event param for the signal event hypercall */
-	gHvContext.SignalEventBuffer =
-			kmalloc(sizeof(struct hv_input_signal_event_buffer),
-				GFP_KERNEL);
-	if (!gHvContext.SignalEventBuffer)
-		goto Cleanup;
-
-	gHvContext.SignalEventParam =
-		(struct hv_input_signal_event *)
-			(ALIGN_UP((unsigned long)gHvContext.SignalEventBuffer,
-				  HV_HYPERCALL_PARAM_ALIGN));
-	gHvContext.SignalEventParam->ConnectionId.Asu32 = 0;
-	gHvContext.SignalEventParam->ConnectionId.u.Id =
-						VMBUS_EVENT_CONNECTION_ID;
-	gHvContext.SignalEventParam->FlagNumber = 0;
-	gHvContext.SignalEventParam->RsvdZ = 0;
-
-	return ret;
-
-Cleanup:
-	if (virtAddr) {
-		if (hypercallMsr.Enable) {
-			hypercallMsr.AsUINT64 = 0;
-			wrmsrl(HV_X64_MSR_HYPERCALL, hypercallMsr.AsUINT64);
-		}
-
-		vfree(virtAddr);
-	}
-	ret = -1;
-	return ret;
-}
-
-/*
- * HvCleanup - Cleanup routine.
- *
- * This routine is called normally during driver unloading or exiting.
- */
-void HvCleanup(void)
-{
-	union hv_x64_msr_hypercall_contents hypercallMsr;
-
-	kfree(gHvContext.SignalEventBuffer);
-	gHvContext.SignalEventBuffer = NULL;
-	gHvContext.SignalEventParam = NULL;
-
-	if (gHvContext.HypercallPage) {
-		hypercallMsr.AsUINT64 = 0;
-		wrmsrl(HV_X64_MSR_HYPERCALL, hypercallMsr.AsUINT64);
-		vfree(gHvContext.HypercallPage);
-		gHvContext.HypercallPage = NULL;
-	}
-}
-
-/*
- * HvPostMessage - Post a message using the hypervisor message IPC.
- *
- * This involves a hypercall.
- */
-u16 HvPostMessage(union hv_connection_id connectionId,
-		  enum hv_message_type messageType,
-		  void *payload, size_t payloadSize)
-{
-	struct alignedInput {
-		u64 alignment8;
-		struct hv_input_post_message msg;
-	};
-
-	struct hv_input_post_message *alignedMsg;
-	u16 status;
-	unsigned long addr;
-
-	if (payloadSize > HV_MESSAGE_PAYLOAD_BYTE_COUNT)
-		return -1;
-
-	addr = (unsigned long)kmalloc(sizeof(struct alignedInput), GFP_ATOMIC);
-	if (!addr)
-		return -1;
-
-	alignedMsg = (struct hv_input_post_message *)
-			(ALIGN_UP(addr, HV_HYPERCALL_PARAM_ALIGN));
-
-	alignedMsg->ConnectionId = connectionId;
-	alignedMsg->MessageType = messageType;
-	alignedMsg->PayloadSize = payloadSize;
-	memcpy((void *)alignedMsg->Payload, payload, payloadSize);
-
-	status = HvDoHypercall(HvCallPostMessage, alignedMsg, NULL) & 0xFFFF;
-
-	kfree((void *)addr);
-
-	return status;
-}
-
-
-/*
- * HvSignalEvent - Signal an event on the specified connection using the hypervisor event IPC.
- *
- * This involves a hypercall.
- */
-u16 HvSignalEvent(void)
-{
-	u16 status;
-
-	status = HvDoHypercall(HvCallSignalEvent, gHvContext.SignalEventParam,
-			       NULL) & 0xFFFF;
-	return status;
-}
-
-/*
- * HvSynicInit - Initialize the Synthethic Interrupt Controller.
- *
- * If it is already initialized by another entity (ie x2v shim), we need to
- * retrieve the initialized message and event pages.  Otherwise, we create and
- * initialize the message and event pages.
- */
-void HvSynicInit(void *irqarg)
-{
-	u64 version;
-	union hv_synic_simp simp;
-	union hv_synic_siefp siefp;
-	union hv_synic_sint sharedSint;
-	union hv_synic_scontrol sctrl;
-
-	u32 irqVector = *((u32 *)(irqarg));
-	int cpu = smp_processor_id();
-
-	if (!gHvContext.HypercallPage)
-		return;
-
-	/* Check the version */
-	rdmsrl(HV_X64_MSR_SVERSION, version);
-
-	DPRINT_INFO(VMBUS, "SynIC version: %llx", version);
-
-	gHvContext.synICMessagePage[cpu] = (void *)get_zeroed_page(GFP_ATOMIC);
-
-	if (gHvContext.synICMessagePage[cpu] == NULL) {
-		DPRINT_ERR(VMBUS,
-			   "unable to allocate SYNIC message page!!");
-		goto Cleanup;
-	}
-
-	gHvContext.synICEventPage[cpu] = (void *)get_zeroed_page(GFP_ATOMIC);
-
-	if (gHvContext.synICEventPage[cpu] == NULL) {
-		DPRINT_ERR(VMBUS,
-			   "unable to allocate SYNIC event page!!");
-		goto Cleanup;
-	}
-
-	/* Setup the Synic's message page */
-	rdmsrl(HV_X64_MSR_SIMP, simp.AsUINT64);
-	simp.SimpEnabled = 1;
-	simp.BaseSimpGpa = virt_to_phys(gHvContext.synICMessagePage[cpu])
-		>> PAGE_SHIFT;
-
-	DPRINT_DBG(VMBUS, "HV_X64_MSR_SIMP msr set to: %llx", simp.AsUINT64);
-
-	wrmsrl(HV_X64_MSR_SIMP, simp.AsUINT64);
-
-	/* Setup the Synic's event page */
-	rdmsrl(HV_X64_MSR_SIEFP, siefp.AsUINT64);
-	siefp.SiefpEnabled = 1;
-	siefp.BaseSiefpGpa = virt_to_phys(gHvContext.synICEventPage[cpu])
-		>> PAGE_SHIFT;
-
-	DPRINT_DBG(VMBUS, "HV_X64_MSR_SIEFP msr set to: %llx", siefp.AsUINT64);
-
-	wrmsrl(HV_X64_MSR_SIEFP, siefp.AsUINT64);
-
-	/* Setup the interception SINT. */
-	/* wrmsrl((HV_X64_MSR_SINT0 + HV_SYNIC_INTERCEPTION_SINT_INDEX), */
-	/*	  interceptionSint.AsUINT64); */
-
-	/* Setup the shared SINT. */
-	rdmsrl(HV_X64_MSR_SINT0 + VMBUS_MESSAGE_SINT, sharedSint.AsUINT64);
-
-	sharedSint.AsUINT64 = 0;
-	sharedSint.Vector = irqVector; /* HV_SHARED_SINT_IDT_VECTOR + 0x20; */
-	sharedSint.Masked = false;
-	sharedSint.AutoEoi = true;
-
-	DPRINT_DBG(VMBUS, "HV_X64_MSR_SINT1 msr set to: %llx",
-		   sharedSint.AsUINT64);
-
-	wrmsrl(HV_X64_MSR_SINT0 + VMBUS_MESSAGE_SINT, sharedSint.AsUINT64);
-
-	/* Enable the global synic bit */
-	rdmsrl(HV_X64_MSR_SCONTROL, sctrl.AsUINT64);
-	sctrl.Enable = 1;
-
-	wrmsrl(HV_X64_MSR_SCONTROL, sctrl.AsUINT64);
-
-	gHvContext.SynICInitialized = true;
-	return;
-
-Cleanup:
-	if (gHvContext.synICEventPage[cpu])
-		osd_PageFree(gHvContext.synICEventPage[cpu], 1);
-
-	if (gHvContext.synICMessagePage[cpu])
-		osd_PageFree(gHvContext.synICMessagePage[cpu], 1);
-	return;
-}
-
-/*
- * HvSynicCleanup - Cleanup routine for HvSynicInit().
- */
-void HvSynicCleanup(void *arg)
-{
-	union hv_synic_sint sharedSint;
-	union hv_synic_simp simp;
-	union hv_synic_siefp siefp;
-	int cpu = smp_processor_id();
-
-	if (!gHvContext.SynICInitialized)
-		return;
-
-	rdmsrl(HV_X64_MSR_SINT0 + VMBUS_MESSAGE_SINT, sharedSint.AsUINT64);
-
-	sharedSint.Masked = 1;
-
-	/* Need to correctly cleanup in the case of SMP!!! */
-	/* Disable the interrupt */
-	wrmsrl(HV_X64_MSR_SINT0 + VMBUS_MESSAGE_SINT, sharedSint.AsUINT64);
-
-	rdmsrl(HV_X64_MSR_SIMP, simp.AsUINT64);
-	simp.SimpEnabled = 0;
-	simp.BaseSimpGpa = 0;
-
-	wrmsrl(HV_X64_MSR_SIMP, simp.AsUINT64);
-
-	rdmsrl(HV_X64_MSR_SIEFP, siefp.AsUINT64);
-	siefp.SiefpEnabled = 0;
-	siefp.BaseSiefpGpa = 0;
-
-	wrmsrl(HV_X64_MSR_SIEFP, siefp.AsUINT64);
-
-	osd_PageFree(gHvContext.synICMessagePage[cpu], 1);
-	osd_PageFree(gHvContext.synICEventPage[cpu], 1);
-}
diff --git a/drivers/staging/hv/Hv.h b/drivers/staging/hv/Hv.h
deleted file mode 100644
index 41f5ebb..0000000
--- a/drivers/staging/hv/Hv.h
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- *
- * Copyright (c) 2009, Microsoft Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place - Suite 330, Boston, MA 02111-1307 USA.
- *
- * Authors:
- *   Haiyang Zhang <haiyangz@microsoft.com>
- *   Hank Janssen  <hjanssen@microsoft.com>
- *
- */
-
-
-#ifndef __HV_H__
-#define __HV_H__
-
-#include "hv_api.h"
-
-enum {
-	VMBUS_MESSAGE_CONNECTION_ID	= 1,
-	VMBUS_MESSAGE_PORT_ID		= 1,
-	VMBUS_EVENT_CONNECTION_ID	= 2,
-	VMBUS_EVENT_PORT_ID		= 2,
-	VMBUS_MONITOR_CONNECTION_ID	= 3,
-	VMBUS_MONITOR_PORT_ID		= 3,
-	VMBUS_MESSAGE_SINT		= 2,
-};
-
-/* #defines */
-
-#define HV_PRESENT_BIT			0x80000000
-
-#define HV_LINUX_GUEST_ID_LO		0x00000000
-#define HV_LINUX_GUEST_ID_HI		0xB16B00B5
-#define HV_LINUX_GUEST_ID		(((u64)HV_LINUX_GUEST_ID_HI << 32) | \
-					   HV_LINUX_GUEST_ID_LO)
-
-#define HV_CPU_POWER_MANAGEMENT		(1 << 0)
-#define HV_RECOMMENDATIONS_MAX		4
-
-#define HV_X64_MAX			5
-#define HV_CAPS_MAX			8
-
-
-#define HV_HYPERCALL_PARAM_ALIGN	sizeof(u64)
-
-
-/* Service definitions */
-
-#define HV_SERVICE_PARENT_PORT				(0)
-#define HV_SERVICE_PARENT_CONNECTION			(0)
-
-#define HV_SERVICE_CONNECT_RESPONSE_SUCCESS		(0)
-#define HV_SERVICE_CONNECT_RESPONSE_INVALID_PARAMETER	(1)
-#define HV_SERVICE_CONNECT_RESPONSE_UNKNOWN_SERVICE	(2)
-#define HV_SERVICE_CONNECT_RESPONSE_CONNECTION_REJECTED	(3)
-
-#define HV_SERVICE_CONNECT_REQUEST_MESSAGE_ID		(1)
-#define HV_SERVICE_CONNECT_RESPONSE_MESSAGE_ID		(2)
-#define HV_SERVICE_DISCONNECT_REQUEST_MESSAGE_ID	(3)
-#define HV_SERVICE_DISCONNECT_RESPONSE_MESSAGE_ID	(4)
-#define HV_SERVICE_MAX_MESSAGE_ID				(4)
-
-#define HV_SERVICE_PROTOCOL_VERSION (0x0010)
-#define HV_CONNECT_PAYLOAD_BYTE_COUNT 64
-
-/* #define VMBUS_REVISION_NUMBER	6 */
-
-/* Our local vmbus's port and connection id. Anything >0 is fine */
-/* #define VMBUS_PORT_ID		11 */
-
-/* 628180B8-308D-4c5e-B7DB-1BEB62E62EF4 */
-static const struct hv_guid VMBUS_SERVICE_ID = {
-	.data = {
-		0xb8, 0x80, 0x81, 0x62, 0x8d, 0x30, 0x5e, 0x4c,
-		0xb7, 0xdb, 0x1b, 0xeb, 0x62, 0xe6, 0x2e, 0xf4
-	},
-};
-
-#define MAX_NUM_CPUS	32
-
-
-struct hv_input_signal_event_buffer {
-	u64 Align8;
-	struct hv_input_signal_event Event;
-};
-
-struct hv_context {
-	/* We only support running on top of Hyper-V
-	* So at this point this really can only contain the Hyper-V ID
-	*/
-	u64 GuestId;
-
-	void *HypercallPage;
-
-	bool SynICInitialized;
-
-	/*
-	 * This is used as an input param to HvCallSignalEvent hypercall. The
-	 * input param is immutable in our usage and must be dynamic mem (vs
-	 * stack or global). */
-	struct hv_input_signal_event_buffer *SignalEventBuffer;
-	/* 8-bytes aligned of the buffer above */
-	struct hv_input_signal_event *SignalEventParam;
-
-	void *synICMessagePage[MAX_NUM_CPUS];
-	void *synICEventPage[MAX_NUM_CPUS];
-};
-
-extern struct hv_context gHvContext;
-
-
-/* Hv Interface */
-
-extern int HvInit(void);
-
-extern void HvCleanup(void);
-
-extern u16 HvPostMessage(union hv_connection_id connectionId,
-			 enum hv_message_type messageType,
-			 void *payload, size_t payloadSize);
-
-extern u16 HvSignalEvent(void);
-
-extern void HvSynicInit(void *irqarg);
-
-extern void HvSynicCleanup(void *arg);
-
-#endif /* __HV_H__ */
diff --git a/drivers/staging/hv/Kconfig b/drivers/staging/hv/Kconfig
index 022e621..1a67b19 100644
--- a/drivers/staging/hv/Kconfig
+++ b/drivers/staging/hv/Kconfig
@@ -1,6 +1,6 @@
 config HYPERV
 	tristate "Microsoft Hyper-V client drivers"
-	depends on X86 && !XEN && m
+	depends on X86 && !XEN && ACPI && PCI && m
 	default n
 	help
 	  Select this option to run Linux as a Hyper-V client operating
@@ -17,7 +17,7 @@
 
 config HYPERV_BLOCK
 	tristate "Microsoft Hyper-V virtual block driver"
-	depends on BLOCK && SCSI
+	depends on BLOCK && SCSI && (LBDAF || 64BIT)
 	default HYPERV
 	help
 	  Select this option to enable the Hyper-V virtual block driver.
@@ -31,8 +31,16 @@
 
 config HYPERV_UTILS
 	tristate "Microsoft Hyper-V Utilities driver"
+	depends on CONNECTOR && NLS
 	default HYPERV
 	help
 	  Select this option to enable the Hyper-V Utilities.
 
+config HYPERV_MOUSE
+	tristate "Microsoft Hyper-V mouse driver"
+	depends on HID
+	default HYPERV
+	help
+	  Select this option to enable the Hyper-V mouse driver.
+
 endif
diff --git a/drivers/staging/hv/Makefile b/drivers/staging/hv/Makefile
index 3ded0bc..fb94c40 100644
--- a/drivers/staging/hv/Makefile
+++ b/drivers/staging/hv/Makefile
@@ -3,11 +3,14 @@
 obj-$(CONFIG_HYPERV_BLOCK)	+= hv_blkvsc.o
 obj-$(CONFIG_HYPERV_NET)	+= hv_netvsc.o
 obj-$(CONFIG_HYPERV_UTILS)	+= hv_utils.o
+obj-$(CONFIG_HYPERV_MOUSE)	+= hv_mouse.o
 
-hv_vmbus-objs := vmbus_drv.o osd.o \
-		 Vmbus.o Hv.o Connection.o Channel.o \
-		 ChannelMgmt.o ChannelInterface.o RingBuffer.o
-hv_storvsc-objs := storvsc_drv.o StorVsc.o
-hv_blkvsc-objs := blkvsc_drv.o BlkVsc.o
-hv_netvsc-objs := netvsc_drv.o NetVsc.o RndisFilter.o
-hv_utils-objs := hyperv_utils.o ext_utils.o
+EXTRA_CFLAGS += -I$(src)/include
+
+hv_vmbus-y := vmbus_drv.o \
+		 hv.o connection.o channel.o \
+		 channel_mgmt.o ring_buffer.o
+hv_storvsc-y := storvsc_drv.o storvsc.o
+hv_blkvsc-y := blkvsc_drv.o  storvsc.o
+hv_netvsc-y := netvsc_drv.o netvsc.o rndis_filter.o
+hv_utils-y := hv_util.o hv_kvp.o
diff --git a/drivers/staging/hv/NetVsc.c b/drivers/staging/hv/NetVsc.c
deleted file mode 100644
index b3e3181..0000000
--- a/drivers/staging/hv/NetVsc.c
+++ /dev/null
@@ -1,1328 +0,0 @@
-/*
- * Copyright (c) 2009, Microsoft Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place - Suite 330, Boston, MA 02111-1307 USA.
- *
- * Authors:
- *   Haiyang Zhang <haiyangz@microsoft.com>
- *   Hank Janssen  <hjanssen@microsoft.com>
- */
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/delay.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-#include "osd.h"
-#include "logging.h"
-#include "NetVsc.h"
-#include "RndisFilter.h"
-
-
-/* Globals */
-static const char *gDriverName = "netvsc";
-
-/* {F8615163-DF3E-46c5-913F-F2D2F965ED0E} */
-static const struct hv_guid gNetVscDeviceType = {
-	.data = {
-		0x63, 0x51, 0x61, 0xF8, 0x3E, 0xDF, 0xc5, 0x46,
-		0x91, 0x3F, 0xF2, 0xD2, 0xF9, 0x65, 0xED, 0x0E
-	}
-};
-
-static int NetVscOnDeviceAdd(struct hv_device *Device, void *AdditionalInfo);
-
-static int NetVscOnDeviceRemove(struct hv_device *Device);
-
-static void NetVscOnCleanup(struct hv_driver *Driver);
-
-static void NetVscOnChannelCallback(void *context);
-
-static int NetVscInitializeSendBufferWithNetVsp(struct hv_device *Device);
-
-static int NetVscInitializeReceiveBufferWithNetVsp(struct hv_device *Device);
-
-static int NetVscDestroySendBuffer(struct netvsc_device *NetDevice);
-
-static int NetVscDestroyReceiveBuffer(struct netvsc_device *NetDevice);
-
-static int NetVscConnectToVsp(struct hv_device *Device);
-
-static void NetVscOnSendCompletion(struct hv_device *Device,
-				   struct vmpacket_descriptor *Packet);
-
-static int NetVscOnSend(struct hv_device *Device,
-			struct hv_netvsc_packet *Packet);
-
-static void NetVscOnReceive(struct hv_device *Device,
-			    struct vmpacket_descriptor *Packet);
-
-static void NetVscOnReceiveCompletion(void *Context);
-
-static void NetVscSendReceiveCompletion(struct hv_device *Device,
-					u64 TransactionId);
-
-
-static struct netvsc_device *AllocNetDevice(struct hv_device *Device)
-{
-	struct netvsc_device *netDevice;
-
-	netDevice = kzalloc(sizeof(struct netvsc_device), GFP_KERNEL);
-	if (!netDevice)
-		return NULL;
-
-	/* Set to 2 to allow both inbound and outbound traffic */
-	atomic_cmpxchg(&netDevice->RefCount, 0, 2);
-
-	netDevice->Device = Device;
-	Device->Extension = netDevice;
-
-	return netDevice;
-}
-
-static void FreeNetDevice(struct netvsc_device *Device)
-{
-	WARN_ON(atomic_read(&Device->RefCount) == 0);
-	Device->Device->Extension = NULL;
-	kfree(Device);
-}
-
-
-/* Get the net device object iff exists and its refcount > 1 */
-static struct netvsc_device *GetOutboundNetDevice(struct hv_device *Device)
-{
-	struct netvsc_device *netDevice;
-
-	netDevice = Device->Extension;
-	if (netDevice && atomic_read(&netDevice->RefCount) > 1)
-		atomic_inc(&netDevice->RefCount);
-	else
-		netDevice = NULL;
-
-	return netDevice;
-}
-
-/* Get the net device object iff exists and its refcount > 0 */
-static struct netvsc_device *GetInboundNetDevice(struct hv_device *Device)
-{
-	struct netvsc_device *netDevice;
-
-	netDevice = Device->Extension;
-	if (netDevice && atomic_read(&netDevice->RefCount))
-		atomic_inc(&netDevice->RefCount);
-	else
-		netDevice = NULL;
-
-	return netDevice;
-}
-
-static void PutNetDevice(struct hv_device *Device)
-{
-	struct netvsc_device *netDevice;
-
-	netDevice = Device->Extension;
-	/* ASSERT(netDevice); */
-
-	atomic_dec(&netDevice->RefCount);
-}
-
-static struct netvsc_device *ReleaseOutboundNetDevice(struct hv_device *Device)
-{
-	struct netvsc_device *netDevice;
-
-	netDevice = Device->Extension;
-	if (netDevice == NULL)
-		return NULL;
-
-	/* Busy wait until the ref drop to 2, then set it to 1 */
-	while (atomic_cmpxchg(&netDevice->RefCount, 2, 1) != 2)
-		udelay(100);
-
-	return netDevice;
-}
-
-static struct netvsc_device *ReleaseInboundNetDevice(struct hv_device *Device)
-{
-	struct netvsc_device *netDevice;
-
-	netDevice = Device->Extension;
-	if (netDevice == NULL)
-		return NULL;
-
-	/* Busy wait until the ref drop to 1, then set it to 0 */
-	while (atomic_cmpxchg(&netDevice->RefCount, 1, 0) != 1)
-		udelay(100);
-
-	Device->Extension = NULL;
-	return netDevice;
-}
-
-/*
- * NetVscInitialize - Main entry point
- */
-int NetVscInitialize(struct hv_driver *drv)
-{
-	struct netvsc_driver *driver = (struct netvsc_driver *)drv;
-
-	DPRINT_DBG(NETVSC, "sizeof(struct hv_netvsc_packet)=%zd, "
-		   "sizeof(struct nvsp_message)=%zd, "
-		   "sizeof(struct vmtransfer_page_packet_header)=%zd",
-		   sizeof(struct hv_netvsc_packet),
-		   sizeof(struct nvsp_message),
-		   sizeof(struct vmtransfer_page_packet_header));
-
-	/* Make sure we are at least 2 pages since 1 page is used for control */
-	/* ASSERT(driver->RingBufferSize >= (PAGE_SIZE << 1)); */
-
-	drv->name = gDriverName;
-	memcpy(&drv->deviceType, &gNetVscDeviceType, sizeof(struct hv_guid));
-
-	/* Make sure it is set by the caller */
-	/* FIXME: These probably should still be tested in some way */
-	/* ASSERT(driver->OnReceiveCallback); */
-	/* ASSERT(driver->OnLinkStatusChanged); */
-
-	/* Setup the dispatch table */
-	driver->Base.OnDeviceAdd	= NetVscOnDeviceAdd;
-	driver->Base.OnDeviceRemove	= NetVscOnDeviceRemove;
-	driver->Base.OnCleanup		= NetVscOnCleanup;
-
-	driver->OnSend			= NetVscOnSend;
-
-	RndisFilterInit(driver);
-	return 0;
-}
-
-static int NetVscInitializeReceiveBufferWithNetVsp(struct hv_device *Device)
-{
-	int ret = 0;
-	struct netvsc_device *netDevice;
-	struct nvsp_message *initPacket;
-
-	netDevice = GetOutboundNetDevice(Device);
-	if (!netDevice) {
-		DPRINT_ERR(NETVSC, "unable to get net device..."
-			   "device being destroyed?");
-		return -1;
-	}
-	/* ASSERT(netDevice->ReceiveBufferSize > 0); */
-	/* page-size grandularity */
-	/* ASSERT((netDevice->ReceiveBufferSize & (PAGE_SIZE - 1)) == 0); */
-
-	netDevice->ReceiveBuffer =
-		osd_PageAlloc(netDevice->ReceiveBufferSize >> PAGE_SHIFT);
-	if (!netDevice->ReceiveBuffer) {
-		DPRINT_ERR(NETVSC,
-			   "unable to allocate receive buffer of size %d",
-			   netDevice->ReceiveBufferSize);
-		ret = -1;
-		goto Cleanup;
-	}
-	/* page-aligned buffer */
-	/* ASSERT(((unsigned long)netDevice->ReceiveBuffer & (PAGE_SIZE - 1)) == */
-	/* 	0); */
-
-	DPRINT_INFO(NETVSC, "Establishing receive buffer's GPADL...");
-
-	/*
-	 * Establish the gpadl handle for this buffer on this
-	 * channel.  Note: This call uses the vmbus connection rather
-	 * than the channel to establish the gpadl handle.
-	 */
-	ret = Device->Driver->VmbusChannelInterface.EstablishGpadl(Device,
-					netDevice->ReceiveBuffer,
-					netDevice->ReceiveBufferSize,
-					&netDevice->ReceiveBufferGpadlHandle);
-	if (ret != 0) {
-		DPRINT_ERR(NETVSC,
-			   "unable to establish receive buffer's gpadl");
-		goto Cleanup;
-	}
-
-	/* osd_WaitEventWait(ext->ChannelInitEvent); */
-
-	/* Notify the NetVsp of the gpadl handle */
-	DPRINT_INFO(NETVSC, "Sending NvspMessage1TypeSendReceiveBuffer...");
-
-	initPacket = &netDevice->ChannelInitPacket;
-
-	memset(initPacket, 0, sizeof(struct nvsp_message));
-
-	initPacket->Header.MessageType = NvspMessage1TypeSendReceiveBuffer;
-	initPacket->Messages.Version1Messages.SendReceiveBuffer.GpadlHandle = netDevice->ReceiveBufferGpadlHandle;
-	initPacket->Messages.Version1Messages.SendReceiveBuffer.Id = NETVSC_RECEIVE_BUFFER_ID;
-
-	/* Send the gpadl notification request */
-	ret = Device->Driver->VmbusChannelInterface.SendPacket(Device,
-				initPacket,
-				sizeof(struct nvsp_message),
-				(unsigned long)initPacket,
-				VmbusPacketTypeDataInBand,
-				VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
-	if (ret != 0) {
-		DPRINT_ERR(NETVSC,
-			   "unable to send receive buffer's gpadl to netvsp");
-		goto Cleanup;
-	}
-
-	osd_WaitEventWait(netDevice->ChannelInitEvent);
-
-	/* Check the response */
-	if (initPacket->Messages.Version1Messages.SendReceiveBufferComplete.Status != NvspStatusSuccess) {
-		DPRINT_ERR(NETVSC, "Unable to complete receive buffer "
-			   "initialzation with NetVsp - status %d",
-			   initPacket->Messages.Version1Messages.SendReceiveBufferComplete.Status);
-		ret = -1;
-		goto Cleanup;
-	}
-
-	/* Parse the response */
-	/* ASSERT(netDevice->ReceiveSectionCount == 0); */
-	/* ASSERT(netDevice->ReceiveSections == NULL); */
-
-	netDevice->ReceiveSectionCount = initPacket->Messages.Version1Messages.SendReceiveBufferComplete.NumSections;
-
-	netDevice->ReceiveSections = kmalloc(netDevice->ReceiveSectionCount * sizeof(struct nvsp_1_receive_buffer_section), GFP_KERNEL);
-	if (netDevice->ReceiveSections == NULL) {
-		ret = -1;
-		goto Cleanup;
-	}
-
-	memcpy(netDevice->ReceiveSections,
-		initPacket->Messages.Version1Messages.SendReceiveBufferComplete.Sections,
-		netDevice->ReceiveSectionCount * sizeof(struct nvsp_1_receive_buffer_section));
-
-	DPRINT_INFO(NETVSC, "Receive sections info (count %d, offset %d, "
-		    "endoffset %d, suballoc size %d, num suballocs %d)",
-		    netDevice->ReceiveSectionCount,
-		    netDevice->ReceiveSections[0].Offset,
-		    netDevice->ReceiveSections[0].EndOffset,
-		    netDevice->ReceiveSections[0].SubAllocationSize,
-		    netDevice->ReceiveSections[0].NumSubAllocations);
-
-	/*
-	 * For 1st release, there should only be 1 section that represents the
-	 * entire receive buffer
-	 */
-	if (netDevice->ReceiveSectionCount != 1 ||
-	    netDevice->ReceiveSections->Offset != 0) {
-		ret = -1;
-		goto Cleanup;
-	}
-
-	goto Exit;
-
-Cleanup:
-	NetVscDestroyReceiveBuffer(netDevice);
-
-Exit:
-	PutNetDevice(Device);
-	return ret;
-}
-
-static int NetVscInitializeSendBufferWithNetVsp(struct hv_device *Device)
-{
-	int ret = 0;
-	struct netvsc_device *netDevice;
-	struct nvsp_message *initPacket;
-
-	netDevice = GetOutboundNetDevice(Device);
-	if (!netDevice) {
-		DPRINT_ERR(NETVSC, "unable to get net device..."
-			   "device being destroyed?");
-		return -1;
-	}
-	if (netDevice->SendBufferSize <= 0) {
-		ret = -EINVAL;
-		goto Cleanup;
-	}
-
-	/* page-size grandularity */
-	/* ASSERT((netDevice->SendBufferSize & (PAGE_SIZE - 1)) == 0); */
-
-	netDevice->SendBuffer =
-		osd_PageAlloc(netDevice->SendBufferSize >> PAGE_SHIFT);
-	if (!netDevice->SendBuffer) {
-		DPRINT_ERR(NETVSC, "unable to allocate send buffer of size %d",
-			   netDevice->SendBufferSize);
-		ret = -1;
-		goto Cleanup;
-	}
-	/* page-aligned buffer */
-	/* ASSERT(((unsigned long)netDevice->SendBuffer & (PAGE_SIZE - 1)) == 0); */
-
-	DPRINT_INFO(NETVSC, "Establishing send buffer's GPADL...");
-
-	/*
-	 * Establish the gpadl handle for this buffer on this
-	 * channel.  Note: This call uses the vmbus connection rather
-	 * than the channel to establish the gpadl handle.
-	 */
-	ret = Device->Driver->VmbusChannelInterface.EstablishGpadl(Device,
-					netDevice->SendBuffer,
-					netDevice->SendBufferSize,
-					&netDevice->SendBufferGpadlHandle);
-	if (ret != 0) {
-		DPRINT_ERR(NETVSC, "unable to establish send buffer's gpadl");
-		goto Cleanup;
-	}
-
-	/* osd_WaitEventWait(ext->ChannelInitEvent); */
-
-	/* Notify the NetVsp of the gpadl handle */
-	DPRINT_INFO(NETVSC, "Sending NvspMessage1TypeSendSendBuffer...");
-
-	initPacket = &netDevice->ChannelInitPacket;
-
-	memset(initPacket, 0, sizeof(struct nvsp_message));
-
-	initPacket->Header.MessageType = NvspMessage1TypeSendSendBuffer;
-	initPacket->Messages.Version1Messages.SendReceiveBuffer.GpadlHandle = netDevice->SendBufferGpadlHandle;
-	initPacket->Messages.Version1Messages.SendReceiveBuffer.Id = NETVSC_SEND_BUFFER_ID;
-
-	/* Send the gpadl notification request */
-	ret = Device->Driver->VmbusChannelInterface.SendPacket(Device,
-				initPacket, sizeof(struct nvsp_message),
-				(unsigned long)initPacket,
-				VmbusPacketTypeDataInBand,
-				VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
-	if (ret != 0) {
-		DPRINT_ERR(NETVSC,
-			   "unable to send receive buffer's gpadl to netvsp");
-		goto Cleanup;
-	}
-
-	osd_WaitEventWait(netDevice->ChannelInitEvent);
-
-	/* Check the response */
-	if (initPacket->Messages.Version1Messages.SendSendBufferComplete.Status != NvspStatusSuccess) {
-		DPRINT_ERR(NETVSC, "Unable to complete send buffer "
-			   "initialzation with NetVsp - status %d",
-			   initPacket->Messages.Version1Messages.SendSendBufferComplete.Status);
-		ret = -1;
-		goto Cleanup;
-	}
-
-	netDevice->SendSectionSize = initPacket->Messages.Version1Messages.SendSendBufferComplete.SectionSize;
-
-	goto Exit;
-
-Cleanup:
-	NetVscDestroySendBuffer(netDevice);
-
-Exit:
-	PutNetDevice(Device);
-	return ret;
-}
-
-static int NetVscDestroyReceiveBuffer(struct netvsc_device *NetDevice)
-{
-	struct nvsp_message *revokePacket;
-	int ret = 0;
-
-	/*
-	 * If we got a section count, it means we received a
-	 * SendReceiveBufferComplete msg (ie sent
-	 * NvspMessage1TypeSendReceiveBuffer msg) therefore, we need
-	 * to send a revoke msg here
-	 */
-	if (NetDevice->ReceiveSectionCount) {
-		DPRINT_INFO(NETVSC,
-			    "Sending NvspMessage1TypeRevokeReceiveBuffer...");
-
-		/* Send the revoke receive buffer */
-		revokePacket = &NetDevice->RevokePacket;
-		memset(revokePacket, 0, sizeof(struct nvsp_message));
-
-		revokePacket->Header.MessageType = NvspMessage1TypeRevokeReceiveBuffer;
-		revokePacket->Messages.Version1Messages.RevokeReceiveBuffer.Id = NETVSC_RECEIVE_BUFFER_ID;
-
-		ret = NetDevice->Device->Driver->VmbusChannelInterface.SendPacket(
-						NetDevice->Device,
-						revokePacket,
-						sizeof(struct nvsp_message),
-						(unsigned long)revokePacket,
-						VmbusPacketTypeDataInBand, 0);
-		/*
-		 * If we failed here, we might as well return and
-		 * have a leak rather than continue and a bugchk
-		 */
-		if (ret != 0) {
-			DPRINT_ERR(NETVSC, "unable to send revoke receive "
-				   "buffer to netvsp");
-			return -1;
-		}
-	}
-
-	/* Teardown the gpadl on the vsp end */
-	if (NetDevice->ReceiveBufferGpadlHandle) {
-		DPRINT_INFO(NETVSC, "Tearing down receive buffer's GPADL...");
-
-		ret = NetDevice->Device->Driver->VmbusChannelInterface.TeardownGpadl(
-					NetDevice->Device,
-					NetDevice->ReceiveBufferGpadlHandle);
-
-		/* If we failed here, we might as well return and have a leak rather than continue and a bugchk */
-		if (ret != 0) {
-			DPRINT_ERR(NETVSC,
-				   "unable to teardown receive buffer's gpadl");
-			return -1;
-		}
-		NetDevice->ReceiveBufferGpadlHandle = 0;
-	}
-
-	if (NetDevice->ReceiveBuffer) {
-		DPRINT_INFO(NETVSC, "Freeing up receive buffer...");
-
-		/* Free up the receive buffer */
-		osd_PageFree(NetDevice->ReceiveBuffer,
-			     NetDevice->ReceiveBufferSize >> PAGE_SHIFT);
-		NetDevice->ReceiveBuffer = NULL;
-	}
-
-	if (NetDevice->ReceiveSections) {
-		NetDevice->ReceiveSectionCount = 0;
-		kfree(NetDevice->ReceiveSections);
-		NetDevice->ReceiveSections = NULL;
-	}
-
-	return ret;
-}
-
-static int NetVscDestroySendBuffer(struct netvsc_device *NetDevice)
-{
-	struct nvsp_message *revokePacket;
-	int ret = 0;
-
-	/*
-	 * If we got a section count, it means we received a
-	 *  SendReceiveBufferComplete msg (ie sent
-	 *  NvspMessage1TypeSendReceiveBuffer msg) therefore, we need
-	 *  to send a revoke msg here
-	 */
-	if (NetDevice->SendSectionSize) {
-		DPRINT_INFO(NETVSC,
-			    "Sending NvspMessage1TypeRevokeSendBuffer...");
-
-		/* Send the revoke send buffer */
-		revokePacket = &NetDevice->RevokePacket;
-		memset(revokePacket, 0, sizeof(struct nvsp_message));
-
-		revokePacket->Header.MessageType = NvspMessage1TypeRevokeSendBuffer;
-		revokePacket->Messages.Version1Messages.RevokeSendBuffer.Id = NETVSC_SEND_BUFFER_ID;
-
-		ret = NetDevice->Device->Driver->VmbusChannelInterface.SendPacket(NetDevice->Device,
-					revokePacket,
-					sizeof(struct nvsp_message),
-					(unsigned long)revokePacket,
-					VmbusPacketTypeDataInBand, 0);
-		/*
-		 * If we failed here, we might as well return and have a leak
-		 * rather than continue and a bugchk
-		 */
-		if (ret != 0) {
-			DPRINT_ERR(NETVSC, "unable to send revoke send buffer "
-				   "to netvsp");
-			return -1;
-		}
-	}
-
-	/* Teardown the gpadl on the vsp end */
-	if (NetDevice->SendBufferGpadlHandle) {
-		DPRINT_INFO(NETVSC, "Tearing down send buffer's GPADL...");
-
-		ret = NetDevice->Device->Driver->VmbusChannelInterface.TeardownGpadl(NetDevice->Device, NetDevice->SendBufferGpadlHandle);
-
-		/*
-		 * If we failed here, we might as well return and have a leak
-		 * rather than continue and a bugchk
-		 */
-		if (ret != 0) {
-			DPRINT_ERR(NETVSC, "unable to teardown send buffer's "
-				   "gpadl");
-			return -1;
-		}
-		NetDevice->SendBufferGpadlHandle = 0;
-	}
-
-	if (NetDevice->SendBuffer) {
-		DPRINT_INFO(NETVSC, "Freeing up send buffer...");
-
-		/* Free up the receive buffer */
-		osd_PageFree(NetDevice->SendBuffer,
-			     NetDevice->SendBufferSize >> PAGE_SHIFT);
-		NetDevice->SendBuffer = NULL;
-	}
-
-	return ret;
-}
-
-
-static int NetVscConnectToVsp(struct hv_device *Device)
-{
-	int ret;
-	struct netvsc_device *netDevice;
-	struct nvsp_message *initPacket;
-	int ndisVersion;
-
-	netDevice = GetOutboundNetDevice(Device);
-	if (!netDevice) {
-		DPRINT_ERR(NETVSC, "unable to get net device..."
-			   "device being destroyed?");
-		return -1;
-	}
-
-	initPacket = &netDevice->ChannelInitPacket;
-
-	memset(initPacket, 0, sizeof(struct nvsp_message));
-	initPacket->Header.MessageType = NvspMessageTypeInit;
-	initPacket->Messages.InitMessages.Init.MinProtocolVersion = NVSP_MIN_PROTOCOL_VERSION;
-	initPacket->Messages.InitMessages.Init.MaxProtocolVersion = NVSP_MAX_PROTOCOL_VERSION;
-
-	DPRINT_INFO(NETVSC, "Sending NvspMessageTypeInit...");
-
-	/* Send the init request */
-	ret = Device->Driver->VmbusChannelInterface.SendPacket(Device,
-				initPacket,
-				sizeof(struct nvsp_message),
-				(unsigned long)initPacket,
-				VmbusPacketTypeDataInBand,
-				VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
-
-	if (ret != 0) {
-		DPRINT_ERR(NETVSC, "unable to send NvspMessageTypeInit");
-		goto Cleanup;
-	}
-
-	osd_WaitEventWait(netDevice->ChannelInitEvent);
-
-	/* Now, check the response */
-	/* ASSERT(initPacket->Messages.InitMessages.InitComplete.MaximumMdlChainLength <= MAX_MULTIPAGE_BUFFER_COUNT); */
-	DPRINT_INFO(NETVSC, "NvspMessageTypeInit status(%d) max mdl chain (%d)",
-		initPacket->Messages.InitMessages.InitComplete.Status,
-		initPacket->Messages.InitMessages.InitComplete.MaximumMdlChainLength);
-
-	if (initPacket->Messages.InitMessages.InitComplete.Status !=
-	    NvspStatusSuccess) {
-		DPRINT_ERR(NETVSC,
-			"unable to initialize with netvsp (status 0x%x)",
-			initPacket->Messages.InitMessages.InitComplete.Status);
-		ret = -1;
-		goto Cleanup;
-	}
-
-	if (initPacket->Messages.InitMessages.InitComplete.NegotiatedProtocolVersion != NVSP_PROTOCOL_VERSION_1) {
-		DPRINT_ERR(NETVSC, "unable to initialize with netvsp "
-			   "(version expected 1 got %d)",
-			   initPacket->Messages.InitMessages.InitComplete.NegotiatedProtocolVersion);
-		ret = -1;
-		goto Cleanup;
-	}
-	DPRINT_INFO(NETVSC, "Sending NvspMessage1TypeSendNdisVersion...");
-
-	/* Send the ndis version */
-	memset(initPacket, 0, sizeof(struct nvsp_message));
-
-	ndisVersion = 0x00050000;
-
-	initPacket->Header.MessageType = NvspMessage1TypeSendNdisVersion;
-	initPacket->Messages.Version1Messages.SendNdisVersion.NdisMajorVersion =
-				(ndisVersion & 0xFFFF0000) >> 16;
-	initPacket->Messages.Version1Messages.SendNdisVersion.NdisMinorVersion =
-				ndisVersion & 0xFFFF;
-
-	/* Send the init request */
-	ret = Device->Driver->VmbusChannelInterface.SendPacket(Device,
-					initPacket,
-					sizeof(struct nvsp_message),
-					(unsigned long)initPacket,
-					VmbusPacketTypeDataInBand, 0);
-	if (ret != 0) {
-		DPRINT_ERR(NETVSC,
-			   "unable to send NvspMessage1TypeSendNdisVersion");
-		ret = -1;
-		goto Cleanup;
-	}
-	/*
-	 * BUGBUG - We have to wait for the above msg since the
-	 * netvsp uses KMCL which acknowledges packet (completion
-	 * packet) since our Vmbus always set the
-	 * VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED flag
-	 */
-	 /* osd_WaitEventWait(NetVscChannel->ChannelInitEvent); */
-
-	/* Post the big receive buffer to NetVSP */
-	ret = NetVscInitializeReceiveBufferWithNetVsp(Device);
-	if (ret == 0)
-		ret = NetVscInitializeSendBufferWithNetVsp(Device);
-
-Cleanup:
-	PutNetDevice(Device);
-	return ret;
-}
-
-static void NetVscDisconnectFromVsp(struct netvsc_device *NetDevice)
-{
-	NetVscDestroyReceiveBuffer(NetDevice);
-	NetVscDestroySendBuffer(NetDevice);
-}
-
-/*
- * NetVscOnDeviceAdd - Callback when the device belonging to this driver is added
- */
-static int NetVscOnDeviceAdd(struct hv_device *Device, void *AdditionalInfo)
-{
-	int ret = 0;
-	int i;
-	struct netvsc_device *netDevice;
-	struct hv_netvsc_packet *packet, *pos;
-	struct netvsc_driver *netDriver =
-				(struct netvsc_driver *)Device->Driver;
-
-	netDevice = AllocNetDevice(Device);
-	if (!netDevice) {
-		ret = -1;
-		goto Cleanup;
-	}
-
-	DPRINT_DBG(NETVSC, "netvsc channel object allocated - %p", netDevice);
-
-	/* Initialize the NetVSC channel extension */
-	netDevice->ReceiveBufferSize = NETVSC_RECEIVE_BUFFER_SIZE;
-	spin_lock_init(&netDevice->receive_packet_list_lock);
-
-	netDevice->SendBufferSize = NETVSC_SEND_BUFFER_SIZE;
-
-	INIT_LIST_HEAD(&netDevice->ReceivePacketList);
-
-	for (i = 0; i < NETVSC_RECEIVE_PACKETLIST_COUNT; i++) {
-		packet = kzalloc(sizeof(struct hv_netvsc_packet) +
-				 (NETVSC_RECEIVE_SG_COUNT *
-				  sizeof(struct hv_page_buffer)), GFP_KERNEL);
-		if (!packet) {
-			DPRINT_DBG(NETVSC, "unable to allocate netvsc pkts "
-				   "for receive pool (wanted %d got %d)",
-				   NETVSC_RECEIVE_PACKETLIST_COUNT, i);
-			break;
-		}
-		list_add_tail(&packet->ListEntry,
-			      &netDevice->ReceivePacketList);
-	}
-	netDevice->ChannelInitEvent = osd_WaitEventCreate();
-	if (!netDevice->ChannelInitEvent) {
-		ret = -ENOMEM;
-		goto Cleanup;
-	}
-
-	/* Open the channel */
-	ret = Device->Driver->VmbusChannelInterface.Open(Device,
-						netDriver->RingBufferSize,
-						netDriver->RingBufferSize,
-						NULL, 0,
-						NetVscOnChannelCallback,
-						Device);
-
-	if (ret != 0) {
-		DPRINT_ERR(NETVSC, "unable to open channel: %d", ret);
-		ret = -1;
-		goto Cleanup;
-	}
-
-	/* Channel is opened */
-	DPRINT_INFO(NETVSC, "*** NetVSC channel opened successfully! ***");
-
-	/* Connect with the NetVsp */
-	ret = NetVscConnectToVsp(Device);
-	if (ret != 0) {
-		DPRINT_ERR(NETVSC, "unable to connect to NetVSP - %d", ret);
-		ret = -1;
-		goto Close;
-	}
-
-	DPRINT_INFO(NETVSC, "*** NetVSC channel handshake result - %d ***",
-		    ret);
-
-	return ret;
-
-Close:
-	/* Now, we can close the channel safely */
-	Device->Driver->VmbusChannelInterface.Close(Device);
-
-Cleanup:
-
-	if (netDevice) {
-		kfree(netDevice->ChannelInitEvent);
-
-		list_for_each_entry_safe(packet, pos,
-					 &netDevice->ReceivePacketList,
-					 ListEntry) {
-			list_del(&packet->ListEntry);
-			kfree(packet);
-		}
-
-		ReleaseOutboundNetDevice(Device);
-		ReleaseInboundNetDevice(Device);
-
-		FreeNetDevice(netDevice);
-	}
-
-	return ret;
-}
-
-/*
- * NetVscOnDeviceRemove - Callback when the root bus device is removed
- */
-static int NetVscOnDeviceRemove(struct hv_device *Device)
-{
-	struct netvsc_device *netDevice;
-	struct hv_netvsc_packet *netvscPacket, *pos;
-
-	DPRINT_INFO(NETVSC, "Disabling outbound traffic on net device (%p)...",
-		    Device->Extension);
-
-	/* Stop outbound traffic ie sends and receives completions */
-	netDevice = ReleaseOutboundNetDevice(Device);
-	if (!netDevice) {
-		DPRINT_ERR(NETVSC, "No net device present!!");
-		return -1;
-	}
-
-	/* Wait for all send completions */
-	while (atomic_read(&netDevice->NumOutstandingSends)) {
-		DPRINT_INFO(NETVSC, "waiting for %d requests to complete...",
-			    atomic_read(&netDevice->NumOutstandingSends));
-		udelay(100);
-	}
-
-	DPRINT_INFO(NETVSC, "Disconnecting from netvsp...");
-
-	NetVscDisconnectFromVsp(netDevice);
-
-	DPRINT_INFO(NETVSC, "Disabling inbound traffic on net device (%p)...",
-		    Device->Extension);
-
-	/* Stop inbound traffic ie receives and sends completions */
-	netDevice = ReleaseInboundNetDevice(Device);
-
-	/* At this point, no one should be accessing netDevice except in here */
-	DPRINT_INFO(NETVSC, "net device (%p) safe to remove", netDevice);
-
-	/* Now, we can close the channel safely */
-	Device->Driver->VmbusChannelInterface.Close(Device);
-
-	/* Release all resources */
-	list_for_each_entry_safe(netvscPacket, pos,
-				 &netDevice->ReceivePacketList, ListEntry) {
-		list_del(&netvscPacket->ListEntry);
-		kfree(netvscPacket);
-	}
-
-	kfree(netDevice->ChannelInitEvent);
-	FreeNetDevice(netDevice);
-	return 0;
-}
-
-/*
- * NetVscOnCleanup - Perform any cleanup when the driver is removed
- */
-static void NetVscOnCleanup(struct hv_driver *drv)
-{
-}
-
-static void NetVscOnSendCompletion(struct hv_device *Device,
-				   struct vmpacket_descriptor *Packet)
-{
-	struct netvsc_device *netDevice;
-	struct nvsp_message *nvspPacket;
-	struct hv_netvsc_packet *nvscPacket;
-
-	netDevice = GetInboundNetDevice(Device);
-	if (!netDevice) {
-		DPRINT_ERR(NETVSC, "unable to get net device..."
-			   "device being destroyed?");
-		return;
-	}
-
-	nvspPacket = (struct nvsp_message *)((unsigned long)Packet + (Packet->DataOffset8 << 3));
-
-	DPRINT_DBG(NETVSC, "send completion packet - type %d",
-		   nvspPacket->Header.MessageType);
-
-	if ((nvspPacket->Header.MessageType == NvspMessageTypeInitComplete) ||
-	    (nvspPacket->Header.MessageType ==
-	     NvspMessage1TypeSendReceiveBufferComplete) ||
-	    (nvspPacket->Header.MessageType ==
-	     NvspMessage1TypeSendSendBufferComplete)) {
-		/* Copy the response back */
-		memcpy(&netDevice->ChannelInitPacket, nvspPacket,
-		       sizeof(struct nvsp_message));
-		osd_WaitEventSet(netDevice->ChannelInitEvent);
-	} else if (nvspPacket->Header.MessageType ==
-		   NvspMessage1TypeSendRNDISPacketComplete) {
-		/* Get the send context */
-		nvscPacket = (struct hv_netvsc_packet *)(unsigned long)Packet->TransactionId;
-		/* ASSERT(nvscPacket); */
-
-		/* Notify the layer above us */
-		nvscPacket->Completion.Send.OnSendCompletion(nvscPacket->Completion.Send.SendCompletionContext);
-
-		atomic_dec(&netDevice->NumOutstandingSends);
-	} else {
-		DPRINT_ERR(NETVSC, "Unknown send completion packet type - "
-			   "%d received!!", nvspPacket->Header.MessageType);
-	}
-
-	PutNetDevice(Device);
-}
-
-static int NetVscOnSend(struct hv_device *Device,
-			struct hv_netvsc_packet *Packet)
-{
-	struct netvsc_device *netDevice;
-	int ret = 0;
-
-	struct nvsp_message sendMessage;
-
-	netDevice = GetOutboundNetDevice(Device);
-	if (!netDevice) {
-		DPRINT_ERR(NETVSC, "net device (%p) shutting down..."
-			   "ignoring outbound packets", netDevice);
-		return -2;
-	}
-
-	sendMessage.Header.MessageType = NvspMessage1TypeSendRNDISPacket;
-	if (Packet->IsDataPacket) {
-		/* 0 is RMC_DATA; */
-		sendMessage.Messages.Version1Messages.SendRNDISPacket.ChannelType = 0;
-	} else {
-		/* 1 is RMC_CONTROL; */
-		sendMessage.Messages.Version1Messages.SendRNDISPacket.ChannelType = 1;
-	}
-
-	/* Not using send buffer section */
-	sendMessage.Messages.Version1Messages.SendRNDISPacket.SendBufferSectionIndex = 0xFFFFFFFF;
-	sendMessage.Messages.Version1Messages.SendRNDISPacket.SendBufferSectionSize = 0;
-
-	if (Packet->PageBufferCount) {
-		ret = Device->Driver->VmbusChannelInterface.SendPacketPageBuffer(
-					Device, Packet->PageBuffers,
-					Packet->PageBufferCount,
-					&sendMessage,
-					sizeof(struct nvsp_message),
-					(unsigned long)Packet);
-	} else {
-		ret = Device->Driver->VmbusChannelInterface.SendPacket(Device,
-				&sendMessage,
-				sizeof(struct nvsp_message),
-				(unsigned long)Packet,
-				VmbusPacketTypeDataInBand,
-				VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
-
-	}
-
-	if (ret != 0)
-		DPRINT_ERR(NETVSC, "Unable to send packet %p ret %d",
-			   Packet, ret);
-
-	atomic_inc(&netDevice->NumOutstandingSends);
-	PutNetDevice(Device);
-	return ret;
-}
-
-static void NetVscOnReceive(struct hv_device *Device,
-			    struct vmpacket_descriptor *Packet)
-{
-	struct netvsc_device *netDevice;
-	struct vmtransfer_page_packet_header *vmxferpagePacket;
-	struct nvsp_message *nvspPacket;
-	struct hv_netvsc_packet *netvscPacket = NULL;
-	unsigned long start;
-	unsigned long end, endVirtual;
-	/* struct netvsc_driver *netvscDriver; */
-	struct xferpage_packet *xferpagePacket = NULL;
-	int i, j;
-	int count = 0, bytesRemain = 0;
-	unsigned long flags;
-	LIST_HEAD(listHead);
-
-	netDevice = GetInboundNetDevice(Device);
-	if (!netDevice) {
-		DPRINT_ERR(NETVSC, "unable to get net device..."
-			   "device being destroyed?");
-		return;
-	}
-
-	/*
-	 * All inbound packets other than send completion should be xfer page
-	 * packet
-	 */
-	if (Packet->Type != VmbusPacketTypeDataUsingTransferPages) {
-		DPRINT_ERR(NETVSC, "Unknown packet type received - %d",
-			   Packet->Type);
-		PutNetDevice(Device);
-		return;
-	}
-
-	nvspPacket = (struct nvsp_message *)((unsigned long)Packet +
-			(Packet->DataOffset8 << 3));
-
-	/* Make sure this is a valid nvsp packet */
-	if (nvspPacket->Header.MessageType != NvspMessage1TypeSendRNDISPacket) {
-		DPRINT_ERR(NETVSC, "Unknown nvsp packet type received - %d",
-			   nvspPacket->Header.MessageType);
-		PutNetDevice(Device);
-		return;
-	}
-
-	DPRINT_DBG(NETVSC, "NVSP packet received - type %d",
-		   nvspPacket->Header.MessageType);
-
-	vmxferpagePacket = (struct vmtransfer_page_packet_header *)Packet;
-
-	if (vmxferpagePacket->TransferPageSetId != NETVSC_RECEIVE_BUFFER_ID) {
-		DPRINT_ERR(NETVSC, "Invalid xfer page set id - "
-			   "expecting %x got %x", NETVSC_RECEIVE_BUFFER_ID,
-			   vmxferpagePacket->TransferPageSetId);
-		PutNetDevice(Device);
-		return;
-	}
-
-	DPRINT_DBG(NETVSC, "xfer page - range count %d",
-		   vmxferpagePacket->RangeCount);
-
-	/*
-	 * Grab free packets (range count + 1) to represent this xfer
-	 * page packet. +1 to represent the xfer page packet itself.
-	 * We grab it here so that we know exactly how many we can
-	 * fulfil
-	 */
-	spin_lock_irqsave(&netDevice->receive_packet_list_lock, flags);
-	while (!list_empty(&netDevice->ReceivePacketList)) {
-		list_move_tail(netDevice->ReceivePacketList.next, &listHead);
-		if (++count == vmxferpagePacket->RangeCount + 1)
-			break;
-	}
-	spin_unlock_irqrestore(&netDevice->receive_packet_list_lock, flags);
-
-	/*
-	 * We need at least 2 netvsc pkts (1 to represent the xfer
-	 * page and at least 1 for the range) i.e. we can handled
-	 * some of the xfer page packet ranges...
-	 */
-	if (count < 2) {
-		DPRINT_ERR(NETVSC, "Got only %d netvsc pkt...needed %d pkts. "
-			   "Dropping this xfer page packet completely!",
-			   count, vmxferpagePacket->RangeCount + 1);
-
-		/* Return it to the freelist */
-		spin_lock_irqsave(&netDevice->receive_packet_list_lock, flags);
-		for (i = count; i != 0; i--) {
-			list_move_tail(listHead.next,
-				       &netDevice->ReceivePacketList);
-		}
-		spin_unlock_irqrestore(&netDevice->receive_packet_list_lock,
-				       flags);
-
-		NetVscSendReceiveCompletion(Device,
-					    vmxferpagePacket->d.TransactionId);
-
-		PutNetDevice(Device);
-		return;
-	}
-
-	/* Remove the 1st packet to represent the xfer page packet itself */
-	xferpagePacket = (struct xferpage_packet *)listHead.next;
-	list_del(&xferpagePacket->ListEntry);
-
-	/* This is how much we can satisfy */
-	xferpagePacket->Count = count - 1;
-	/* ASSERT(xferpagePacket->Count > 0 && xferpagePacket->Count <= */
-	/* 	vmxferpagePacket->RangeCount); */
-
-	if (xferpagePacket->Count != vmxferpagePacket->RangeCount) {
-		DPRINT_INFO(NETVSC, "Needed %d netvsc pkts to satisy this xfer "
-			    "page...got %d", vmxferpagePacket->RangeCount,
-			    xferpagePacket->Count);
-	}
-
-	/* Each range represents 1 RNDIS pkt that contains 1 ethernet frame */
-	for (i = 0; i < (count - 1); i++) {
-		netvscPacket = (struct hv_netvsc_packet *)listHead.next;
-		list_del(&netvscPacket->ListEntry);
-
-		/* Initialize the netvsc packet */
-		netvscPacket->XferPagePacket = xferpagePacket;
-		netvscPacket->Completion.Recv.OnReceiveCompletion =
-					NetVscOnReceiveCompletion;
-		netvscPacket->Completion.Recv.ReceiveCompletionContext =
-					netvscPacket;
-		netvscPacket->Device = Device;
-		/* Save this so that we can send it back */
-		netvscPacket->Completion.Recv.ReceiveCompletionTid =
-					vmxferpagePacket->d.TransactionId;
-
-		netvscPacket->TotalDataBufferLength =
-					vmxferpagePacket->Ranges[i].ByteCount;
-		netvscPacket->PageBufferCount = 1;
-
-		/* ASSERT(vmxferpagePacket->Ranges[i].ByteOffset + */
-		/* 	vmxferpagePacket->Ranges[i].ByteCount < */
-		/* 	netDevice->ReceiveBufferSize); */
-
-		netvscPacket->PageBuffers[0].Length =
-					vmxferpagePacket->Ranges[i].ByteCount;
-
-		start = virt_to_phys((void *)((unsigned long)netDevice->ReceiveBuffer + vmxferpagePacket->Ranges[i].ByteOffset));
-
-		netvscPacket->PageBuffers[0].Pfn = start >> PAGE_SHIFT;
-		endVirtual = (unsigned long)netDevice->ReceiveBuffer
-		    + vmxferpagePacket->Ranges[i].ByteOffset
-		    + vmxferpagePacket->Ranges[i].ByteCount - 1;
-		end = virt_to_phys((void *)endVirtual);
-
-		/* Calculate the page relative offset */
-		netvscPacket->PageBuffers[0].Offset =
-			vmxferpagePacket->Ranges[i].ByteOffset & (PAGE_SIZE - 1);
-		if ((end >> PAGE_SHIFT) != (start >> PAGE_SHIFT)) {
-			/* Handle frame across multiple pages: */
-			netvscPacket->PageBuffers[0].Length =
-				(netvscPacket->PageBuffers[0].Pfn << PAGE_SHIFT)
-				+ PAGE_SIZE - start;
-			bytesRemain = netvscPacket->TotalDataBufferLength -
-					netvscPacket->PageBuffers[0].Length;
-			for (j = 1; j < NETVSC_PACKET_MAXPAGE; j++) {
-				netvscPacket->PageBuffers[j].Offset = 0;
-				if (bytesRemain <= PAGE_SIZE) {
-					netvscPacket->PageBuffers[j].Length = bytesRemain;
-					bytesRemain = 0;
-				} else {
-					netvscPacket->PageBuffers[j].Length = PAGE_SIZE;
-					bytesRemain -= PAGE_SIZE;
-				}
-				netvscPacket->PageBuffers[j].Pfn =
-				    virt_to_phys((void *)(endVirtual - bytesRemain)) >> PAGE_SHIFT;
-				netvscPacket->PageBufferCount++;
-				if (bytesRemain == 0)
-					break;
-			}
-			/* ASSERT(bytesRemain == 0); */
-		}
-		DPRINT_DBG(NETVSC, "[%d] - (abs offset %u len %u) => "
-			   "(pfn %llx, offset %u, len %u)", i,
-			   vmxferpagePacket->Ranges[i].ByteOffset,
-			   vmxferpagePacket->Ranges[i].ByteCount,
-			   netvscPacket->PageBuffers[0].Pfn,
-			   netvscPacket->PageBuffers[0].Offset,
-			   netvscPacket->PageBuffers[0].Length);
-
-		/* Pass it to the upper layer */
-		((struct netvsc_driver *)Device->Driver)->OnReceiveCallback(Device, netvscPacket);
-
-		NetVscOnReceiveCompletion(netvscPacket->Completion.Recv.ReceiveCompletionContext);
-	}
-
-	/* ASSERT(list_empty(&listHead)); */
-
-	PutNetDevice(Device);
-}
-
-static void NetVscSendReceiveCompletion(struct hv_device *Device,
-					u64 TransactionId)
-{
-	struct nvsp_message recvcompMessage;
-	int retries = 0;
-	int ret;
-
-	DPRINT_DBG(NETVSC, "Sending receive completion pkt - %llx",
-		   TransactionId);
-
-	recvcompMessage.Header.MessageType =
-				NvspMessage1TypeSendRNDISPacketComplete;
-
-	/* FIXME: Pass in the status */
-	recvcompMessage.Messages.Version1Messages.SendRNDISPacketComplete.Status = NvspStatusSuccess;
-
-retry_send_cmplt:
-	/* Send the completion */
-	ret = Device->Driver->VmbusChannelInterface.SendPacket(Device,
-					&recvcompMessage,
-					sizeof(struct nvsp_message),
-					TransactionId,
-					VmbusPacketTypeCompletion, 0);
-	if (ret == 0) {
-		/* success */
-		/* no-op */
-	} else if (ret == -1) {
-		/* no more room...wait a bit and attempt to retry 3 times */
-		retries++;
-		DPRINT_ERR(NETVSC, "unable to send receive completion pkt "
-			   "(tid %llx)...retrying %d", TransactionId, retries);
-
-		if (retries < 4) {
-			udelay(100);
-			goto retry_send_cmplt;
-		} else {
-			DPRINT_ERR(NETVSC, "unable to send receive completion "
-				  "pkt (tid %llx)...give up retrying",
-				  TransactionId);
-		}
-	} else {
-		DPRINT_ERR(NETVSC, "unable to send receive completion pkt - "
-			   "%llx", TransactionId);
-	}
-}
-
-/* Send a receive completion packet to RNDIS device (ie NetVsp) */
-static void NetVscOnReceiveCompletion(void *Context)
-{
-	struct hv_netvsc_packet *packet = Context;
-	struct hv_device *device = (struct hv_device *)packet->Device;
-	struct netvsc_device *netDevice;
-	u64 transactionId = 0;
-	bool fSendReceiveComp = false;
-	unsigned long flags;
-
-	/* ASSERT(packet->XferPagePacket); */
-
-	/*
-	 * Even though it seems logical to do a GetOutboundNetDevice() here to
-	 * send out receive completion, we are using GetInboundNetDevice()
-	 * since we may have disable outbound traffic already.
-	 */
-	netDevice = GetInboundNetDevice(device);
-	if (!netDevice) {
-		DPRINT_ERR(NETVSC, "unable to get net device..."
-			   "device being destroyed?");
-		return;
-	}
-
-	/* Overloading use of the lock. */
-	spin_lock_irqsave(&netDevice->receive_packet_list_lock, flags);
-
-	/* ASSERT(packet->XferPagePacket->Count > 0); */
-	packet->XferPagePacket->Count--;
-
-	/*
-	 * Last one in the line that represent 1 xfer page packet.
-	 * Return the xfer page packet itself to the freelist
-	 */
-	if (packet->XferPagePacket->Count == 0) {
-		fSendReceiveComp = true;
-		transactionId = packet->Completion.Recv.ReceiveCompletionTid;
-		list_add_tail(&packet->XferPagePacket->ListEntry,
-			      &netDevice->ReceivePacketList);
-
-	}
-
-	/* Put the packet back */
-	list_add_tail(&packet->ListEntry, &netDevice->ReceivePacketList);
-	spin_unlock_irqrestore(&netDevice->receive_packet_list_lock, flags);
-
-	/* Send a receive completion for the xfer page packet */
-	if (fSendReceiveComp)
-		NetVscSendReceiveCompletion(device, transactionId);
-
-	PutNetDevice(device);
-}
-
-static void NetVscOnChannelCallback(void *Context)
-{
-	int ret;
-	struct hv_device *device = Context;
-	struct netvsc_device *netDevice;
-	u32 bytesRecvd;
-	u64 requestId;
-	unsigned char *packet;
-	struct vmpacket_descriptor *desc;
-	unsigned char *buffer;
-	int bufferlen = NETVSC_PACKET_SIZE;
-
-	/* ASSERT(device); */
-
-	packet = kzalloc(NETVSC_PACKET_SIZE * sizeof(unsigned char),
-			 GFP_KERNEL);
-	if (!packet)
-		return;
-	buffer = packet;
-
-	netDevice = GetInboundNetDevice(device);
-	if (!netDevice) {
-		DPRINT_ERR(NETVSC, "net device (%p) shutting down..."
-			   "ignoring inbound packets", netDevice);
-		goto out;
-	}
-
-	do {
-		ret = device->Driver->VmbusChannelInterface.RecvPacketRaw(
-						device, buffer, bufferlen,
-						&bytesRecvd, &requestId);
-		if (ret == 0) {
-			if (bytesRecvd > 0) {
-				DPRINT_DBG(NETVSC, "receive %d bytes, tid %llx",
-					   bytesRecvd, requestId);
-
-				desc = (struct vmpacket_descriptor *)buffer;
-				switch (desc->Type) {
-				case VmbusPacketTypeCompletion:
-					NetVscOnSendCompletion(device, desc);
-					break;
-
-				case VmbusPacketTypeDataUsingTransferPages:
-					NetVscOnReceive(device, desc);
-					break;
-
-				default:
-					DPRINT_ERR(NETVSC,
-						   "unhandled packet type %d, "
-						   "tid %llx len %d\n",
-						   desc->Type, requestId,
-						   bytesRecvd);
-					break;
-				}
-
-				/* reset */
-				if (bufferlen > NETVSC_PACKET_SIZE) {
-					kfree(buffer);
-					buffer = packet;
-					bufferlen = NETVSC_PACKET_SIZE;
-				}
-			} else {
-				/* reset */
-				if (bufferlen > NETVSC_PACKET_SIZE) {
-					kfree(buffer);
-					buffer = packet;
-					bufferlen = NETVSC_PACKET_SIZE;
-				}
-
-				break;
-			}
-		} else if (ret == -2) {
-			/* Handle large packet */
-			buffer = kmalloc(bytesRecvd, GFP_ATOMIC);
-			if (buffer == NULL) {
-				/* Try again next time around */
-				DPRINT_ERR(NETVSC,
-					   "unable to allocate buffer of size "
-					   "(%d)!!", bytesRecvd);
-				break;
-			}
-
-			bufferlen = bytesRecvd;
-		}
-	} while (1);
-
-	PutNetDevice(device);
-out:
-	kfree(buffer);
-	return;
-}
diff --git a/drivers/staging/hv/NetVsc.h b/drivers/staging/hv/NetVsc.h
deleted file mode 100644
index a6264db..0000000
--- a/drivers/staging/hv/NetVsc.h
+++ /dev/null
@@ -1,331 +0,0 @@
-/*
- *
- * Copyright (c) 2009, Microsoft Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place - Suite 330, Boston, MA 02111-1307 USA.
- *
- * Authors:
- *   Haiyang Zhang <haiyangz@microsoft.com>
- *   Hank Janssen  <hjanssen@microsoft.com>
- *
- */
-
-
-#ifndef _NETVSC_H_
-#define _NETVSC_H_
-
-#include <linux/list.h>
-#include "VmbusPacketFormat.h"
-#include "VmbusChannelInterface.h"
-#include "NetVscApi.h"
-
-
-#define NVSP_INVALID_PROTOCOL_VERSION	((u32)0xFFFFFFFF)
-
-#define NVSP_PROTOCOL_VERSION_1		2
-#define NVSP_MIN_PROTOCOL_VERSION	NVSP_PROTOCOL_VERSION_1
-#define NVSP_MAX_PROTOCOL_VERSION	NVSP_PROTOCOL_VERSION_1
-
-enum {
-	NvspMessageTypeNone = 0,
-
-	/* Init Messages */
-	NvspMessageTypeInit			= 1,
-	NvspMessageTypeInitComplete		= 2,
-
-	NvspVersionMessageStart			= 100,
-
-	/* Version 1 Messages */
-	NvspMessage1TypeSendNdisVersion		= NvspVersionMessageStart,
-
-	NvspMessage1TypeSendReceiveBuffer,
-	NvspMessage1TypeSendReceiveBufferComplete,
-	NvspMessage1TypeRevokeReceiveBuffer,
-
-	NvspMessage1TypeSendSendBuffer,
-	NvspMessage1TypeSendSendBufferComplete,
-	NvspMessage1TypeRevokeSendBuffer,
-
-	NvspMessage1TypeSendRNDISPacket,
-	NvspMessage1TypeSendRNDISPacketComplete,
-
-	/*
-	 * This should be set to the number of messages for the version with
-	 * the maximum number of messages.
-	 */
-	NvspNumMessagePerVersion		= 9,
-};
-
-enum {
-	NvspStatusNone = 0,
-	NvspStatusSuccess,
-	NvspStatusFailure,
-	NvspStatusProtocolVersionRangeTooNew,
-	NvspStatusProtocolVersionRangeTooOld,
-	NvspStatusInvalidRndisPacket,
-	NvspStatusBusy,
-	NvspStatusMax,
-};
-
-struct nvsp_message_header {
-	u32 MessageType;
-};
-
-/* Init Messages */
-
-/*
- * This message is used by the VSC to initialize the channel after the channels
- * has been opened. This message should never include anything other then
- * versioning (i.e. this message will be the same for ever).
- */
-struct nvsp_message_init {
-	u32 MinProtocolVersion;
-	u32 MaxProtocolVersion;
-} __attribute__((packed));
-
-/*
- * This message is used by the VSP to complete the initialization of the
- * channel. This message should never include anything other then versioning
- * (i.e. this message will be the same for ever).
- */
-struct nvsp_message_init_complete {
-	u32 NegotiatedProtocolVersion;
-	u32 MaximumMdlChainLength;
-	u32 Status;
-} __attribute__((packed));
-
-union nvsp_message_init_uber {
-	struct nvsp_message_init Init;
-	struct nvsp_message_init_complete InitComplete;
-} __attribute__((packed));
-
-/* Version 1 Messages */
-
-/*
- * This message is used by the VSC to send the NDIS version to the VSP. The VSP
- * can use this information when handling OIDs sent by the VSC.
- */
-struct nvsp_1_message_send_ndis_version {
-	u32 NdisMajorVersion;
-	u32 NdisMinorVersion;
-} __attribute__((packed));
-
-/*
- * This message is used by the VSC to send a receive buffer to the VSP. The VSP
- * can then use the receive buffer to send data to the VSC.
- */
-struct nvsp_1_message_send_receive_buffer {
-	u32 GpadlHandle;
-	u16 Id;
-} __attribute__((packed));
-
-struct nvsp_1_receive_buffer_section {
-	u32 Offset;
-	u32 SubAllocationSize;
-	u32 NumSubAllocations;
-	u32 EndOffset;
-} __attribute__((packed));
-
-/*
- * This message is used by the VSP to acknowledge a receive buffer send by the
- * VSC. This message must be sent by the VSP before the VSP uses the receive
- * buffer.
- */
-struct nvsp_1_message_send_receive_buffer_complete {
-	u32 Status;
-	u32 NumSections;
-
-	/*
-	 * The receive buffer is split into two parts, a large suballocation
-	 * section and a small suballocation section. These sections are then
-	 * suballocated by a certain size.
-	 */
-
-	/*
-	 * For example, the following break up of the receive buffer has 6
-	 * large suballocations and 10 small suballocations.
-	 */
-
-	/*
-	 * |            Large Section          |  |   Small Section   |
-	 * ------------------------------------------------------------
-	 * |     |     |     |     |     |     |  | | | | | | | | | | |
-	 * |                                      |
-	 *  LargeOffset                            SmallOffset
-	 */
-
-	struct nvsp_1_receive_buffer_section Sections[1];
-} __attribute__((packed));
-
-/*
- * This message is sent by the VSC to revoke the receive buffer.  After the VSP
- * completes this transaction, the vsp should never use the receive buffer
- * again.
- */
-struct nvsp_1_message_revoke_receive_buffer {
-	u16 Id;
-};
-
-/*
- * This message is used by the VSC to send a send buffer to the VSP. The VSC
- * can then use the send buffer to send data to the VSP.
- */
-struct nvsp_1_message_send_send_buffer {
-	u32 GpadlHandle;
-	u16 Id;
-} __attribute__((packed));
-
-/*
- * This message is used by the VSP to acknowledge a send buffer sent by the
- * VSC. This message must be sent by the VSP before the VSP uses the sent
- * buffer.
- */
-struct nvsp_1_message_send_send_buffer_complete {
-	u32 Status;
-
-	/*
-	 * The VSC gets to choose the size of the send buffer and the VSP gets
-	 * to choose the sections size of the buffer.  This was done to enable
-	 * dynamic reconfigurations when the cost of GPA-direct buffers
-	 * decreases.
-	 */
-	u32 SectionSize;
-} __attribute__((packed));
-
-/*
- * This message is sent by the VSC to revoke the send buffer.  After the VSP
- * completes this transaction, the vsp should never use the send buffer again.
- */
-struct nvsp_1_message_revoke_send_buffer {
-	u16 Id;
-};
-
-/*
- * This message is used by both the VSP and the VSC to send a RNDIS message to
- * the opposite channel endpoint.
- */
-struct nvsp_1_message_send_rndis_packet {
-	/*
-	 * This field is specified by RNIDS. They assume there's two different
-	 * channels of communication. However, the Network VSP only has one.
-	 * Therefore, the channel travels with the RNDIS packet.
-	 */
-	u32 ChannelType;
-
-	/*
-	 * This field is used to send part or all of the data through a send
-	 * buffer. This values specifies an index into the send buffer. If the
-	 * index is 0xFFFFFFFF, then the send buffer is not being used and all
-	 * of the data was sent through other VMBus mechanisms.
-	 */
-	u32 SendBufferSectionIndex;
-	u32 SendBufferSectionSize;
-} __attribute__((packed));
-
-/*
- * This message is used by both the VSP and the VSC to complete a RNDIS message
- * to the opposite channel endpoint. At this point, the initiator of this
- * message cannot use any resources associated with the original RNDIS packet.
- */
-struct nvsp_1_message_send_rndis_packet_complete {
-	u32 Status;
-};
-
-union nvsp_1_message_uber {
-	struct nvsp_1_message_send_ndis_version SendNdisVersion;
-
-	struct nvsp_1_message_send_receive_buffer SendReceiveBuffer;
-	struct nvsp_1_message_send_receive_buffer_complete
-						SendReceiveBufferComplete;
-	struct nvsp_1_message_revoke_receive_buffer RevokeReceiveBuffer;
-
-	struct nvsp_1_message_send_send_buffer SendSendBuffer;
-	struct nvsp_1_message_send_send_buffer_complete SendSendBufferComplete;
-	struct nvsp_1_message_revoke_send_buffer RevokeSendBuffer;
-
-	struct nvsp_1_message_send_rndis_packet SendRNDISPacket;
-	struct nvsp_1_message_send_rndis_packet_complete
-						SendRNDISPacketComplete;
-} __attribute__((packed));
-
-union nvsp_all_messages {
-	union nvsp_message_init_uber InitMessages;
-	union nvsp_1_message_uber Version1Messages;
-} __attribute__((packed));
-
-/* ALL Messages */
-struct nvsp_message {
-	struct nvsp_message_header Header;
-	union nvsp_all_messages Messages;
-} __attribute__((packed));
-
-
-
-
-/* #define NVSC_MIN_PROTOCOL_VERSION		1 */
-/* #define NVSC_MAX_PROTOCOL_VERSION		1 */
-
-#define NETVSC_SEND_BUFFER_SIZE			(64*1024)	/* 64K */
-#define NETVSC_SEND_BUFFER_ID			0xface
-
-
-#define NETVSC_RECEIVE_BUFFER_SIZE		(1024*1024)	/* 1MB */
-
-#define NETVSC_RECEIVE_BUFFER_ID		0xcafe
-
-#define NETVSC_RECEIVE_SG_COUNT			1
-
-/* Preallocated receive packets */
-#define NETVSC_RECEIVE_PACKETLIST_COUNT		256
-
-#define NETVSC_PACKET_SIZE                      2048
-
-/* Per netvsc channel-specific */
-struct netvsc_device {
-	struct hv_device *Device;
-
-	atomic_t RefCount;
-	atomic_t NumOutstandingSends;
-	/*
-	 * List of free preallocated hv_netvsc_packet to represent receive
-	 * packet
-	 */
-	struct list_head ReceivePacketList;
-	spinlock_t receive_packet_list_lock;
-
-	/* Send buffer allocated by us but manages by NetVSP */
-	void *SendBuffer;
-	u32 SendBufferSize;
-	u32 SendBufferGpadlHandle;
-	u32 SendSectionSize;
-
-	/* Receive buffer allocated by us but manages by NetVSP */
-	void *ReceiveBuffer;
-	u32 ReceiveBufferSize;
-	u32 ReceiveBufferGpadlHandle;
-	u32 ReceiveSectionCount;
-	struct nvsp_1_receive_buffer_section *ReceiveSections;
-
-	/* Used for NetVSP initialization protocol */
-	struct osd_waitevent *ChannelInitEvent;
-	struct nvsp_message ChannelInitPacket;
-
-	struct nvsp_message RevokePacket;
-	/* unsigned char HwMacAddr[HW_MACADDR_LEN]; */
-
-	/* Holds rndis device info */
-	void *Extension;
-};
-
-#endif /* _NETVSC_H_ */
diff --git a/drivers/staging/hv/NetVscApi.h b/drivers/staging/hv/NetVscApi.h
deleted file mode 100644
index 91a4cd9..0000000
--- a/drivers/staging/hv/NetVscApi.h
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- *
- * Copyright (c) 2009, Microsoft Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place - Suite 330, Boston, MA 02111-1307 USA.
- *
- * Authors:
- *   Haiyang Zhang <haiyangz@microsoft.com>
- *   Hank Janssen  <hjanssen@microsoft.com>
- *
- */
-
-
-#ifndef _NETVSC_API_H_
-#define _NETVSC_API_H_
-
-#include "VmbusApi.h"
-
-/* Fwd declaration */
-struct hv_netvsc_packet;
-
-/* Represent the xfer page packet which contains 1 or more netvsc packet */
-struct xferpage_packet {
-	struct list_head ListEntry;
-
-	/* # of netvsc packets this xfer packet contains */
-	u32 Count;
-};
-
-/* The number of pages which are enough to cover jumbo frame buffer. */
-#define NETVSC_PACKET_MAXPAGE		4
-
-/*
- * Represent netvsc packet which contains 1 RNDIS and 1 ethernet frame
- * within the RNDIS
- */
-struct hv_netvsc_packet {
-	/* Bookkeeping stuff */
-	struct list_head ListEntry;
-
-	struct hv_device *Device;
-	bool IsDataPacket;
-
-	/*
-	 * Valid only for receives when we break a xfer page packet
-	 * into multiple netvsc packets
-	 */
-	struct xferpage_packet *XferPagePacket;
-
-	union {
-		struct{
-			u64 ReceiveCompletionTid;
-			void *ReceiveCompletionContext;
-			void (*OnReceiveCompletion)(void *context);
-		} Recv;
-		struct{
-			u64 SendCompletionTid;
-			void *SendCompletionContext;
-			void (*OnSendCompletion)(void *context);
-		} Send;
-	} Completion;
-
-	/* This points to the memory after PageBuffers */
-	void *Extension;
-
-	u32 TotalDataBufferLength;
-	/* Points to the send/receive buffer where the ethernet frame is */
-	u32 PageBufferCount;
-	struct hv_page_buffer PageBuffers[NETVSC_PACKET_MAXPAGE];
-};
-
-/* Represents the net vsc driver */
-struct netvsc_driver {
-	/* Must be the first field */
-	/* Which is a bug FIXME! */
-	struct hv_driver Base;
-
-	u32 RingBufferSize;
-	u32 RequestExtSize;
-
-	/*
-	 * This is set by the caller to allow us to callback when we
-	 * receive a packet from the "wire"
-	 */
-	int (*OnReceiveCallback)(struct hv_device *dev,
-				 struct hv_netvsc_packet *packet);
-	void (*OnLinkStatusChanged)(struct hv_device *dev, u32 Status);
-
-	/* Specific to this driver */
-	int (*OnSend)(struct hv_device *dev, struct hv_netvsc_packet *packet);
-
-	void *Context;
-};
-
-struct netvsc_device_info {
-    unsigned char MacAddr[6];
-    bool LinkState;	/* 0 - link up, 1 - link down */
-};
-
-/* Interface */
-int NetVscInitialize(struct hv_driver *drv);
-int RndisFilterOnOpen(struct hv_device *Device);
-int RndisFilterOnClose(struct hv_device *Device);
-
-#endif /* _NETVSC_API_H_ */
diff --git a/drivers/staging/hv/RingBuffer.c b/drivers/staging/hv/RingBuffer.c
deleted file mode 100644
index c4e02a5..0000000
--- a/drivers/staging/hv/RingBuffer.c
+++ /dev/null
@@ -1,619 +0,0 @@
-/*
- *
- * Copyright (c) 2009, Microsoft Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place - Suite 330, Boston, MA 02111-1307 USA.
- *
- * Authors:
- *   Haiyang Zhang <haiyangz@microsoft.com>
- *   Hank Janssen  <hjanssen@microsoft.com>
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include "osd.h"
-#include "logging.h"
-#include "RingBuffer.h"
-
-
-/* #defines */
-
-
-/* Amount of space to write to */
-#define BYTES_AVAIL_TO_WRITE(r, w, z) ((w) >= (r)) ? ((z) - ((w) - (r))) : ((r) - (w))
-
-
-/*++
-
-Name:
-	GetRingBufferAvailBytes()
-
-Description:
-	Get number of bytes available to read and to write to
-	for the specified ring buffer
-
---*/
-static inline void
-GetRingBufferAvailBytes(struct hv_ring_buffer_info *rbi, u32 *read, u32 *write)
-{
-	u32 read_loc, write_loc;
-
-	/* Capture the read/write indices before they changed */
-	read_loc = rbi->RingBuffer->ReadIndex;
-	write_loc = rbi->RingBuffer->WriteIndex;
-
-	*write = BYTES_AVAIL_TO_WRITE(read_loc, write_loc, rbi->RingDataSize);
-	*read = rbi->RingDataSize - *write;
-}
-
-/*++
-
-Name:
-	GetNextWriteLocation()
-
-Description:
-	Get the next write location for the specified ring buffer
-
---*/
-static inline u32
-GetNextWriteLocation(struct hv_ring_buffer_info *RingInfo)
-{
-	u32 next = RingInfo->RingBuffer->WriteIndex;
-
-	/* ASSERT(next < RingInfo->RingDataSize); */
-
-	return next;
-}
-
-/*++
-
-Name:
-	SetNextWriteLocation()
-
-Description:
-	Set the next write location for the specified ring buffer
-
---*/
-static inline void
-SetNextWriteLocation(struct hv_ring_buffer_info *RingInfo,
-		     u32 NextWriteLocation)
-{
-	RingInfo->RingBuffer->WriteIndex = NextWriteLocation;
-}
-
-/*++
-
-Name:
-	GetNextReadLocation()
-
-Description:
-	Get the next read location for the specified ring buffer
-
---*/
-static inline u32
-GetNextReadLocation(struct hv_ring_buffer_info *RingInfo)
-{
-	u32 next = RingInfo->RingBuffer->ReadIndex;
-
-	/* ASSERT(next < RingInfo->RingDataSize); */
-
-	return next;
-}
-
-/*++
-
-Name:
-	GetNextReadLocationWithOffset()
-
-Description:
-	Get the next read location + offset for the specified ring buffer.
-	This allows the caller to skip
-
---*/
-static inline u32
-GetNextReadLocationWithOffset(struct hv_ring_buffer_info *RingInfo, u32 Offset)
-{
-	u32 next = RingInfo->RingBuffer->ReadIndex;
-
-	/* ASSERT(next < RingInfo->RingDataSize); */
-	next += Offset;
-	next %= RingInfo->RingDataSize;
-
-	return next;
-}
-
-/*++
-
-Name:
-	SetNextReadLocation()
-
-Description:
-	Set the next read location for the specified ring buffer
-
---*/
-static inline void
-SetNextReadLocation(struct hv_ring_buffer_info *RingInfo, u32 NextReadLocation)
-{
-	RingInfo->RingBuffer->ReadIndex = NextReadLocation;
-}
-
-
-/*++
-
-Name:
-	GetRingBuffer()
-
-Description:
-	Get the start of the ring buffer
-
---*/
-static inline void *
-GetRingBuffer(struct hv_ring_buffer_info *RingInfo)
-{
-	return (void *)RingInfo->RingBuffer->Buffer;
-}
-
-
-/*++
-
-Name:
-	GetRingBufferSize()
-
-Description:
-	Get the size of the ring buffer
-
---*/
-static inline u32
-GetRingBufferSize(struct hv_ring_buffer_info *RingInfo)
-{
-	return RingInfo->RingDataSize;
-}
-
-/*++
-
-Name:
-	GetRingBufferIndices()
-
-Description:
-	Get the read and write indices as u64 of the specified ring buffer
-
---*/
-static inline u64
-GetRingBufferIndices(struct hv_ring_buffer_info *RingInfo)
-{
-	return (u64)RingInfo->RingBuffer->WriteIndex << 32;
-}
-
-
-/*++
-
-Name:
-	DumpRingInfo()
-
-Description:
-	Dump out to console the ring buffer info
-
---*/
-void DumpRingInfo(struct hv_ring_buffer_info *RingInfo, char *Prefix)
-{
-	u32 bytesAvailToWrite;
-	u32 bytesAvailToRead;
-
-	GetRingBufferAvailBytes(RingInfo,
-	&bytesAvailToRead,
-	&bytesAvailToWrite);
-
-	DPRINT(VMBUS,
-		DEBUG_RING_LVL,
-		"%s <<ringinfo %p buffer %p avail write %u "
-		"avail read %u read idx %u write idx %u>>",
-		Prefix,
-		RingInfo,
-		RingInfo->RingBuffer->Buffer,
-		bytesAvailToWrite,
-		bytesAvailToRead,
-		RingInfo->RingBuffer->ReadIndex,
-		RingInfo->RingBuffer->WriteIndex);
-}
-
-
-/* Internal routines */
-
-static u32
-CopyToRingBuffer(
-	struct hv_ring_buffer_info	*RingInfo,
-	u32				StartWriteOffset,
-	void				*Src,
-	u32				SrcLen);
-
-static u32
-CopyFromRingBuffer(
-	struct hv_ring_buffer_info	*RingInfo,
-	void				*Dest,
-	u32				DestLen,
-	u32				StartReadOffset);
-
-
-
-/*++
-
-Name:
-	RingBufferGetDebugInfo()
-
-Description:
-	Get various debug metrics for the specified ring buffer
-
---*/
-void RingBufferGetDebugInfo(struct hv_ring_buffer_info *RingInfo,
-			    struct hv_ring_buffer_debug_info *debug_info)
-{
-	u32 bytesAvailToWrite;
-	u32 bytesAvailToRead;
-
-	if (RingInfo->RingBuffer) {
-		GetRingBufferAvailBytes(RingInfo,
-					&bytesAvailToRead,
-					&bytesAvailToWrite);
-
-		debug_info->BytesAvailToRead = bytesAvailToRead;
-		debug_info->BytesAvailToWrite = bytesAvailToWrite;
-		debug_info->CurrentReadIndex = RingInfo->RingBuffer->ReadIndex;
-		debug_info->CurrentWriteIndex = RingInfo->RingBuffer->WriteIndex;
-		debug_info->CurrentInterruptMask = RingInfo->RingBuffer->InterruptMask;
-	}
-}
-
-
-/*++
-
-Name:
-	GetRingBufferInterruptMask()
-
-Description:
-	Get the interrupt mask for the specified ring buffer
-
---*/
-u32 GetRingBufferInterruptMask(struct hv_ring_buffer_info *rbi)
-{
-	return rbi->RingBuffer->InterruptMask;
-}
-
-/*++
-
-Name:
-	RingBufferInit()
-
-Description:
-	Initialize the ring buffer
-
---*/
-int RingBufferInit(struct hv_ring_buffer_info *RingInfo, void *Buffer, u32 BufferLen)
-{
-	if (sizeof(struct hv_ring_buffer) != PAGE_SIZE)
-		return -EINVAL;
-
-	memset(RingInfo, 0, sizeof(struct hv_ring_buffer_info));
-
-	RingInfo->RingBuffer = (struct hv_ring_buffer *)Buffer;
-	RingInfo->RingBuffer->ReadIndex = RingInfo->RingBuffer->WriteIndex = 0;
-
-	RingInfo->RingSize = BufferLen;
-	RingInfo->RingDataSize = BufferLen - sizeof(struct hv_ring_buffer);
-
-	spin_lock_init(&RingInfo->ring_lock);
-
-	return 0;
-}
-
-/*++
-
-Name:
-	RingBufferCleanup()
-
-Description:
-	Cleanup the ring buffer
-
---*/
-void RingBufferCleanup(struct hv_ring_buffer_info *RingInfo)
-{
-}
-
-/*++
-
-Name:
-	RingBufferWrite()
-
-Description:
-	Write to the ring buffer
-
---*/
-int RingBufferWrite(struct hv_ring_buffer_info *OutRingInfo,
-		    struct scatterlist *sglist, u32 sgcount)
-{
-	int i = 0;
-	u32 byteAvailToWrite;
-	u32 byteAvailToRead;
-	u32 totalBytesToWrite = 0;
-
-	struct scatterlist *sg;
-	volatile u32 nextWriteLocation;
-	u64 prevIndices = 0;
-	unsigned long flags;
-
-	for_each_sg(sglist, sg, sgcount, i)
-	{
-		totalBytesToWrite += sg->length;
-	}
-
-	totalBytesToWrite += sizeof(u64);
-
-	spin_lock_irqsave(&OutRingInfo->ring_lock, flags);
-
-	GetRingBufferAvailBytes(OutRingInfo,
-				&byteAvailToRead,
-				&byteAvailToWrite);
-
-	DPRINT_DBG(VMBUS, "Writing %u bytes...", totalBytesToWrite);
-
-	/* DumpRingInfo(OutRingInfo, "BEFORE "); */
-
-	/* If there is only room for the packet, assume it is full. */
-	/* Otherwise, the next time around, we think the ring buffer */
-	/* is empty since the read index == write index */
-	if (byteAvailToWrite <= totalBytesToWrite) {
-		DPRINT_DBG(VMBUS,
-			"No more space left on outbound ring buffer "
-			"(needed %u, avail %u)",
-			totalBytesToWrite,
-			byteAvailToWrite);
-
-		spin_unlock_irqrestore(&OutRingInfo->ring_lock, flags);
-		return -1;
-	}
-
-	/* Write to the ring buffer */
-	nextWriteLocation = GetNextWriteLocation(OutRingInfo);
-
-	for_each_sg(sglist, sg, sgcount, i)
-	{
-		nextWriteLocation = CopyToRingBuffer(OutRingInfo,
-						     nextWriteLocation,
-						     sg_virt(sg),
-						     sg->length);
-	}
-
-	/* Set previous packet start */
-	prevIndices = GetRingBufferIndices(OutRingInfo);
-
-	nextWriteLocation = CopyToRingBuffer(OutRingInfo,
-					     nextWriteLocation,
-					     &prevIndices,
-					     sizeof(u64));
-
-	/* Make sure we flush all writes before updating the writeIndex */
-	mb();
-
-	/* Now, update the write location */
-	SetNextWriteLocation(OutRingInfo, nextWriteLocation);
-
-	/* DumpRingInfo(OutRingInfo, "AFTER "); */
-
-	spin_unlock_irqrestore(&OutRingInfo->ring_lock, flags);
-	return 0;
-}
-
-
-/*++
-
-Name:
-	RingBufferPeek()
-
-Description:
-	Read without advancing the read index
-
---*/
-int RingBufferPeek(struct hv_ring_buffer_info *InRingInfo, void *Buffer, u32 BufferLen)
-{
-	u32 bytesAvailToWrite;
-	u32 bytesAvailToRead;
-	u32 nextReadLocation = 0;
-	unsigned long flags;
-
-	spin_lock_irqsave(&InRingInfo->ring_lock, flags);
-
-	GetRingBufferAvailBytes(InRingInfo,
-				&bytesAvailToRead,
-				&bytesAvailToWrite);
-
-	/* Make sure there is something to read */
-	if (bytesAvailToRead < BufferLen) {
-		/* DPRINT_DBG(VMBUS,
-			"got callback but not enough to read "
-			"<avail to read %d read size %d>!!",
-			bytesAvailToRead,
-			BufferLen); */
-
-		spin_unlock_irqrestore(&InRingInfo->ring_lock, flags);
-
-		return -1;
-	}
-
-	/* Convert to byte offset */
-	nextReadLocation = GetNextReadLocation(InRingInfo);
-
-	nextReadLocation = CopyFromRingBuffer(InRingInfo,
-						Buffer,
-						BufferLen,
-						nextReadLocation);
-
-	spin_unlock_irqrestore(&InRingInfo->ring_lock, flags);
-
-	return 0;
-}
-
-
-/*++
-
-Name:
-	RingBufferRead()
-
-Description:
-	Read and advance the read index
-
---*/
-int RingBufferRead(struct hv_ring_buffer_info *InRingInfo, void *Buffer,
-		   u32 BufferLen, u32 Offset)
-{
-	u32 bytesAvailToWrite;
-	u32 bytesAvailToRead;
-	u32 nextReadLocation = 0;
-	u64 prevIndices = 0;
-	unsigned long flags;
-
-	if (BufferLen <= 0)
-		return -EINVAL;
-
-	spin_lock_irqsave(&InRingInfo->ring_lock, flags);
-
-	GetRingBufferAvailBytes(InRingInfo,
-				&bytesAvailToRead,
-				&bytesAvailToWrite);
-
-	DPRINT_DBG(VMBUS, "Reading %u bytes...", BufferLen);
-
-	/* DumpRingInfo(InRingInfo, "BEFORE "); */
-
-	/* Make sure there is something to read */
-	if (bytesAvailToRead < BufferLen) {
-		DPRINT_DBG(VMBUS,
-			"got callback but not enough to read "
-			"<avail to read %d read size %d>!!",
-			bytesAvailToRead,
-			BufferLen);
-
-		spin_unlock_irqrestore(&InRingInfo->ring_lock, flags);
-
-		return -1;
-	}
-
-	nextReadLocation = GetNextReadLocationWithOffset(InRingInfo, Offset);
-
-	nextReadLocation = CopyFromRingBuffer(InRingInfo,
-						Buffer,
-						BufferLen,
-						nextReadLocation);
-
-	nextReadLocation = CopyFromRingBuffer(InRingInfo,
-						&prevIndices,
-						sizeof(u64),
-						nextReadLocation);
-
-	/* Make sure all reads are done before we update the read index since */
-	/* the writer may start writing to the read area once the read index */
-	/*is updated */
-	mb();
-
-	/* Update the read index */
-	SetNextReadLocation(InRingInfo, nextReadLocation);
-
-	/* DumpRingInfo(InRingInfo, "AFTER "); */
-
-	spin_unlock_irqrestore(&InRingInfo->ring_lock, flags);
-
-	return 0;
-}
-
-
-/*++
-
-Name:
-	CopyToRingBuffer()
-
-Description:
-	Helper routine to copy from source to ring buffer.
-	Assume there is enough room. Handles wrap-around in dest case only!!
-
---*/
-static u32
-CopyToRingBuffer(
-	struct hv_ring_buffer_info	*RingInfo,
-	u32				StartWriteOffset,
-	void				*Src,
-	u32				SrcLen)
-{
-	void *ringBuffer = GetRingBuffer(RingInfo);
-	u32 ringBufferSize = GetRingBufferSize(RingInfo);
-	u32 fragLen;
-
-	/* wrap-around detected! */
-	if (SrcLen > ringBufferSize - StartWriteOffset) {
-		DPRINT_DBG(VMBUS, "wrap-around detected!");
-
-		fragLen = ringBufferSize - StartWriteOffset;
-		memcpy(ringBuffer + StartWriteOffset, Src, fragLen);
-		memcpy(ringBuffer, Src + fragLen, SrcLen - fragLen);
-	} else
-		memcpy(ringBuffer + StartWriteOffset, Src, SrcLen);
-
-	StartWriteOffset += SrcLen;
-	StartWriteOffset %= ringBufferSize;
-
-	return StartWriteOffset;
-}
-
-
-/*++
-
-Name:
-	CopyFromRingBuffer()
-
-Description:
-	Helper routine to copy to source from ring buffer.
-	Assume there is enough room. Handles wrap-around in src case only!!
-
---*/
-static u32
-CopyFromRingBuffer(
-	struct hv_ring_buffer_info	*RingInfo,
-	void				*Dest,
-	u32				DestLen,
-	u32				StartReadOffset)
-{
-	void *ringBuffer = GetRingBuffer(RingInfo);
-	u32 ringBufferSize = GetRingBufferSize(RingInfo);
-
-	u32 fragLen;
-
-	/* wrap-around detected at the src */
-	if (DestLen > ringBufferSize - StartReadOffset) {
-		DPRINT_DBG(VMBUS, "src wrap-around detected!");
-
-		fragLen = ringBufferSize - StartReadOffset;
-
-		memcpy(Dest, ringBuffer + StartReadOffset, fragLen);
-		memcpy(Dest + fragLen, ringBuffer, DestLen - fragLen);
-	} else
-
-		memcpy(Dest, ringBuffer + StartReadOffset, DestLen);
-
-
-	StartReadOffset += DestLen;
-	StartReadOffset %= ringBufferSize;
-
-	return StartReadOffset;
-}
-
-
-/* eof */
diff --git a/drivers/staging/hv/RingBuffer.h b/drivers/staging/hv/RingBuffer.h
deleted file mode 100644
index a7f1717..0000000
--- a/drivers/staging/hv/RingBuffer.h
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- *
- * Copyright (c) 2009, Microsoft Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place - Suite 330, Boston, MA 02111-1307 USA.
- *
- * Authors:
- *   Haiyang Zhang <haiyangz@microsoft.com>
- *   Hank Janssen  <hjanssen@microsoft.com>
- *
- */
-
-
-#ifndef _RING_BUFFER_H_
-#define _RING_BUFFER_H_
-
-#include <linux/scatterlist.h>
-
-struct hv_ring_buffer {
-	/* Offset in bytes from the start of ring data below */
-	volatile u32 WriteIndex;
-
-	/* Offset in bytes from the start of ring data below */
-	volatile u32 ReadIndex;
-
-	volatile u32 InterruptMask;
-
-	/* Pad it to PAGE_SIZE so that data starts on page boundary */
-	u8	Reserved[4084];
-
-	/* NOTE:
-	 * The InterruptMask field is used only for channels but since our
-	 * vmbus connection also uses this data structure and its data starts
-	 * here, we commented out this field.
-	 */
-	/* volatile u32 InterruptMask; */
-
-	/*
-	 * Ring data starts here + RingDataStartOffset
-	 * !!! DO NOT place any fields below this !!!
-	 */
-	u8 Buffer[0];
-} __attribute__((packed));
-
-struct hv_ring_buffer_info {
-	struct hv_ring_buffer *RingBuffer;
-	u32 RingSize;			/* Include the shared header */
-	spinlock_t ring_lock;
-
-	u32 RingDataSize;		/* < ringSize */
-	u32 RingDataStartOffset;
-};
-
-struct hv_ring_buffer_debug_info {
-	u32 CurrentInterruptMask;
-	u32 CurrentReadIndex;
-	u32 CurrentWriteIndex;
-	u32 BytesAvailToRead;
-	u32 BytesAvailToWrite;
-};
-
-
-
-/* Interface */
-
-
-int RingBufferInit(struct hv_ring_buffer_info *RingInfo, void *Buffer,
-		   u32 BufferLen);
-
-void RingBufferCleanup(struct hv_ring_buffer_info *RingInfo);
-
-int RingBufferWrite(struct hv_ring_buffer_info *RingInfo,
-		    struct scatterlist *sglist,
-		    u32 sgcount);
-
-int RingBufferPeek(struct hv_ring_buffer_info *RingInfo, void *Buffer,
-		   u32 BufferLen);
-
-int RingBufferRead(struct hv_ring_buffer_info *RingInfo,
-		   void *Buffer,
-		   u32 BufferLen,
-		   u32 Offset);
-
-u32 GetRingBufferInterruptMask(struct hv_ring_buffer_info *RingInfo);
-
-void DumpRingInfo(struct hv_ring_buffer_info *RingInfo, char *Prefix);
-
-void RingBufferGetDebugInfo(struct hv_ring_buffer_info *RingInfo,
-			    struct hv_ring_buffer_debug_info *debug_info);
-
-#endif /* _RING_BUFFER_H_ */
diff --git a/drivers/staging/hv/RndisFilter.c b/drivers/staging/hv/RndisFilter.c
deleted file mode 100644
index 159b230..0000000
--- a/drivers/staging/hv/RndisFilter.c
+++ /dev/null
@@ -1,918 +0,0 @@
-/*
- * Copyright (c) 2009, Microsoft Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place - Suite 330, Boston, MA 02111-1307 USA.
- *
- * Authors:
- *   Haiyang Zhang <haiyangz@microsoft.com>
- *   Hank Janssen  <hjanssen@microsoft.com>
- */
-#include <linux/kernel.h>
-#include <linux/highmem.h>
-#include <linux/slab.h>
-#include <linux/io.h>
-#include <linux/if_ether.h>
-
-#include "osd.h"
-#include "logging.h"
-#include "NetVscApi.h"
-#include "RndisFilter.h"
-
-/* Data types */
-struct rndis_filter_driver_object {
-	/* The original driver */
-	struct netvsc_driver InnerDriver;
-};
-
-enum rndis_device_state {
-	RNDIS_DEV_UNINITIALIZED = 0,
-	RNDIS_DEV_INITIALIZING,
-	RNDIS_DEV_INITIALIZED,
-	RNDIS_DEV_DATAINITIALIZED,
-};
-
-struct rndis_device {
-	struct netvsc_device *NetDevice;
-
-	enum rndis_device_state State;
-	u32 LinkStatus;
-	atomic_t NewRequestId;
-
-	spinlock_t request_lock;
-	struct list_head RequestList;
-
-	unsigned char HwMacAddr[ETH_ALEN];
-};
-
-struct rndis_request {
-	struct list_head ListEntry;
-	struct osd_waitevent *WaitEvent;
-
-	/*
-	 * FIXME: We assumed a fixed size response here. If we do ever need to
-	 * handle a bigger response, we can either define a max response
-	 * message or add a response buffer variable above this field
-	 */
-	struct rndis_message ResponseMessage;
-
-	/* Simplify allocation by having a netvsc packet inline */
-	struct hv_netvsc_packet	Packet;
-	struct hv_page_buffer Buffer;
-	/* FIXME: We assumed a fixed size request here. */
-	struct rndis_message RequestMessage;
-};
-
-
-struct rndis_filter_packet {
-	void *CompletionContext;
-	void (*OnCompletion)(void *context);
-	struct rndis_message Message;
-};
-
-
-static int RndisFilterOnDeviceAdd(struct hv_device *Device,
-				  void *AdditionalInfo);
-
-static int RndisFilterOnDeviceRemove(struct hv_device *Device);
-
-static void RndisFilterOnCleanup(struct hv_driver *Driver);
-
-static int RndisFilterOnSend(struct hv_device *Device,
-			     struct hv_netvsc_packet *Packet);
-
-static void RndisFilterOnSendCompletion(void *Context);
-
-static void RndisFilterOnSendRequestCompletion(void *Context);
-
-
-/* The one and only */
-static struct rndis_filter_driver_object gRndisFilter;
-
-static struct rndis_device *GetRndisDevice(void)
-{
-	struct rndis_device *device;
-
-	device = kzalloc(sizeof(struct rndis_device), GFP_KERNEL);
-	if (!device)
-		return NULL;
-
-	spin_lock_init(&device->request_lock);
-
-	INIT_LIST_HEAD(&device->RequestList);
-
-	device->State = RNDIS_DEV_UNINITIALIZED;
-
-	return device;
-}
-
-static struct rndis_request *GetRndisRequest(struct rndis_device *Device,
-					     u32 MessageType,
-					     u32 MessageLength)
-{
-	struct rndis_request *request;
-	struct rndis_message *rndisMessage;
-	struct rndis_set_request *set;
-	unsigned long flags;
-
-	request = kzalloc(sizeof(struct rndis_request), GFP_KERNEL);
-	if (!request)
-		return NULL;
-
-	request->WaitEvent = osd_WaitEventCreate();
-	if (!request->WaitEvent) {
-		kfree(request);
-		return NULL;
-	}
-
-	rndisMessage = &request->RequestMessage;
-	rndisMessage->NdisMessageType = MessageType;
-	rndisMessage->MessageLength = MessageLength;
-
-	/*
-	 * Set the request id. This field is always after the rndis header for
-	 * request/response packet types so we just used the SetRequest as a
-	 * template
-	 */
-	set = &rndisMessage->Message.SetRequest;
-	set->RequestId = atomic_inc_return(&Device->NewRequestId);
-
-	/* Add to the request list */
-	spin_lock_irqsave(&Device->request_lock, flags);
-	list_add_tail(&request->ListEntry, &Device->RequestList);
-	spin_unlock_irqrestore(&Device->request_lock, flags);
-
-	return request;
-}
-
-static void PutRndisRequest(struct rndis_device *Device,
-			    struct rndis_request *Request)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&Device->request_lock, flags);
-	list_del(&Request->ListEntry);
-	spin_unlock_irqrestore(&Device->request_lock, flags);
-
-	kfree(Request->WaitEvent);
-	kfree(Request);
-}
-
-static void DumpRndisMessage(struct rndis_message *RndisMessage)
-{
-	switch (RndisMessage->NdisMessageType) {
-	case REMOTE_NDIS_PACKET_MSG:
-		DPRINT_DBG(NETVSC, "REMOTE_NDIS_PACKET_MSG (len %u, "
-			   "data offset %u data len %u, # oob %u, "
-			   "oob offset %u, oob len %u, pkt offset %u, "
-			   "pkt len %u",
-			   RndisMessage->MessageLength,
-			   RndisMessage->Message.Packet.DataOffset,
-			   RndisMessage->Message.Packet.DataLength,
-			   RndisMessage->Message.Packet.NumOOBDataElements,
-			   RndisMessage->Message.Packet.OOBDataOffset,
-			   RndisMessage->Message.Packet.OOBDataLength,
-			   RndisMessage->Message.Packet.PerPacketInfoOffset,
-			   RndisMessage->Message.Packet.PerPacketInfoLength);
-		break;
-
-	case REMOTE_NDIS_INITIALIZE_CMPLT:
-		DPRINT_DBG(NETVSC, "REMOTE_NDIS_INITIALIZE_CMPLT "
-			"(len %u, id 0x%x, status 0x%x, major %d, minor %d, "
-			"device flags %d, max xfer size 0x%x, max pkts %u, "
-			"pkt aligned %u)",
-			RndisMessage->MessageLength,
-			RndisMessage->Message.InitializeComplete.RequestId,
-			RndisMessage->Message.InitializeComplete.Status,
-			RndisMessage->Message.InitializeComplete.MajorVersion,
-			RndisMessage->Message.InitializeComplete.MinorVersion,
-			RndisMessage->Message.InitializeComplete.DeviceFlags,
-			RndisMessage->Message.InitializeComplete.MaxTransferSize,
-			RndisMessage->Message.InitializeComplete.MaxPacketsPerMessage,
-			RndisMessage->Message.InitializeComplete.PacketAlignmentFactor);
-		break;
-
-	case REMOTE_NDIS_QUERY_CMPLT:
-		DPRINT_DBG(NETVSC, "REMOTE_NDIS_QUERY_CMPLT "
-			"(len %u, id 0x%x, status 0x%x, buf len %u, "
-			"buf offset %u)",
-			RndisMessage->MessageLength,
-			RndisMessage->Message.QueryComplete.RequestId,
-			RndisMessage->Message.QueryComplete.Status,
-			RndisMessage->Message.QueryComplete.InformationBufferLength,
-			RndisMessage->Message.QueryComplete.InformationBufferOffset);
-		break;
-
-	case REMOTE_NDIS_SET_CMPLT:
-		DPRINT_DBG(NETVSC,
-			"REMOTE_NDIS_SET_CMPLT (len %u, id 0x%x, status 0x%x)",
-			RndisMessage->MessageLength,
-			RndisMessage->Message.SetComplete.RequestId,
-			RndisMessage->Message.SetComplete.Status);
-		break;
-
-	case REMOTE_NDIS_INDICATE_STATUS_MSG:
-		DPRINT_DBG(NETVSC, "REMOTE_NDIS_INDICATE_STATUS_MSG "
-			"(len %u, status 0x%x, buf len %u, buf offset %u)",
-			RndisMessage->MessageLength,
-			RndisMessage->Message.IndicateStatus.Status,
-			RndisMessage->Message.IndicateStatus.StatusBufferLength,
-			RndisMessage->Message.IndicateStatus.StatusBufferOffset);
-		break;
-
-	default:
-		DPRINT_DBG(NETVSC, "0x%x (len %u)",
-			RndisMessage->NdisMessageType,
-			RndisMessage->MessageLength);
-		break;
-	}
-}
-
-static int RndisFilterSendRequest(struct rndis_device *Device,
-				  struct rndis_request *Request)
-{
-	int ret;
-	struct hv_netvsc_packet *packet;
-
-	/* Setup the packet to send it */
-	packet = &Request->Packet;
-
-	packet->IsDataPacket = false;
-	packet->TotalDataBufferLength = Request->RequestMessage.MessageLength;
-	packet->PageBufferCount = 1;
-
-	packet->PageBuffers[0].Pfn = virt_to_phys(&Request->RequestMessage) >>
-					PAGE_SHIFT;
-	packet->PageBuffers[0].Length = Request->RequestMessage.MessageLength;
-	packet->PageBuffers[0].Offset =
-		(unsigned long)&Request->RequestMessage & (PAGE_SIZE - 1);
-
-	packet->Completion.Send.SendCompletionContext = Request;/* packet; */
-	packet->Completion.Send.OnSendCompletion =
-		RndisFilterOnSendRequestCompletion;
-	packet->Completion.Send.SendCompletionTid = (unsigned long)Device;
-
-	ret = gRndisFilter.InnerDriver.OnSend(Device->NetDevice->Device, packet);
-	return ret;
-}
-
-static void RndisFilterReceiveResponse(struct rndis_device *Device,
-				       struct rndis_message *Response)
-{
-	struct rndis_request *request = NULL;
-	bool found = false;
-	unsigned long flags;
-
-	spin_lock_irqsave(&Device->request_lock, flags);
-	list_for_each_entry(request, &Device->RequestList, ListEntry) {
-		/*
-		 * All request/response message contains RequestId as the 1st
-		 * field
-		 */
-		if (request->RequestMessage.Message.InitializeRequest.RequestId
-		    == Response->Message.InitializeComplete.RequestId) {
-			DPRINT_DBG(NETVSC, "found rndis request for "
-				"this response (id 0x%x req type 0x%x res "
-				"type 0x%x)",
-				request->RequestMessage.Message.InitializeRequest.RequestId,
-				request->RequestMessage.NdisMessageType,
-				Response->NdisMessageType);
-
-			found = true;
-			break;
-		}
-	}
-	spin_unlock_irqrestore(&Device->request_lock, flags);
-
-	if (found) {
-		if (Response->MessageLength <= sizeof(struct rndis_message)) {
-			memcpy(&request->ResponseMessage, Response,
-			       Response->MessageLength);
-		} else {
-			DPRINT_ERR(NETVSC, "rndis response buffer overflow "
-				  "detected (size %u max %zu)",
-				  Response->MessageLength,
-				  sizeof(struct rndis_filter_packet));
-
-			if (Response->NdisMessageType ==
-			    REMOTE_NDIS_RESET_CMPLT) {
-				/* does not have a request id field */
-				request->ResponseMessage.Message.ResetComplete.Status = STATUS_BUFFER_OVERFLOW;
-			} else {
-				request->ResponseMessage.Message.InitializeComplete.Status = STATUS_BUFFER_OVERFLOW;
-			}
-		}
-
-		osd_WaitEventSet(request->WaitEvent);
-	} else {
-		DPRINT_ERR(NETVSC, "no rndis request found for this response "
-			   "(id 0x%x res type 0x%x)",
-			   Response->Message.InitializeComplete.RequestId,
-			   Response->NdisMessageType);
-	}
-}
-
-static void RndisFilterReceiveIndicateStatus(struct rndis_device *Device,
-					     struct rndis_message *Response)
-{
-	struct rndis_indicate_status *indicate =
-			&Response->Message.IndicateStatus;
-
-	if (indicate->Status == RNDIS_STATUS_MEDIA_CONNECT) {
-		gRndisFilter.InnerDriver.OnLinkStatusChanged(Device->NetDevice->Device, 1);
-	} else if (indicate->Status == RNDIS_STATUS_MEDIA_DISCONNECT) {
-		gRndisFilter.InnerDriver.OnLinkStatusChanged(Device->NetDevice->Device, 0);
-	} else {
-		/*
-		 * TODO:
-		 */
-	}
-}
-
-static void RndisFilterReceiveData(struct rndis_device *Device,
-				   struct rndis_message *Message,
-				   struct hv_netvsc_packet *Packet)
-{
-	struct rndis_packet *rndisPacket;
-	u32 dataOffset;
-
-	/* empty ethernet frame ?? */
-	/* ASSERT(Packet->PageBuffers[0].Length > */
-	/* 	RNDIS_MESSAGE_SIZE(struct rndis_packet)); */
-
-	rndisPacket = &Message->Message.Packet;
-
-	/*
-	 * FIXME: Handle multiple rndis pkt msgs that maybe enclosed in this
-	 * netvsc packet (ie TotalDataBufferLength != MessageLength)
-	 */
-
-	/* Remove the rndis header and pass it back up the stack */
-	dataOffset = RNDIS_HEADER_SIZE + rndisPacket->DataOffset;
-
-	Packet->TotalDataBufferLength -= dataOffset;
-	Packet->PageBuffers[0].Offset += dataOffset;
-	Packet->PageBuffers[0].Length -= dataOffset;
-
-	Packet->IsDataPacket = true;
-
-	gRndisFilter.InnerDriver.OnReceiveCallback(Device->NetDevice->Device,
-						   Packet);
-}
-
-static int RndisFilterOnReceive(struct hv_device *Device,
-				struct hv_netvsc_packet	*Packet)
-{
-	struct netvsc_device *netDevice = Device->Extension;
-	struct rndis_device *rndisDevice;
-	struct rndis_message rndisMessage;
-	struct rndis_message *rndisHeader;
-
-	if (!netDevice)
-		return -EINVAL;
-
-	/* Make sure the rndis device state is initialized */
-	if (!netDevice->Extension) {
-		DPRINT_ERR(NETVSC, "got rndis message but no rndis device..."
-			  "dropping this message!");
-		return -1;
-	}
-
-	rndisDevice = (struct rndis_device *)netDevice->Extension;
-	if (rndisDevice->State == RNDIS_DEV_UNINITIALIZED) {
-		DPRINT_ERR(NETVSC, "got rndis message but rndis device "
-			   "uninitialized...dropping this message!");
-		return -1;
-	}
-
-	rndisHeader = (struct rndis_message *)kmap_atomic(
-			pfn_to_page(Packet->PageBuffers[0].Pfn), KM_IRQ0);
-
-	rndisHeader = (void *)((unsigned long)rndisHeader +
-			Packet->PageBuffers[0].Offset);
-
-	/* Make sure we got a valid rndis message */
-	/*
-	 * FIXME: There seems to be a bug in set completion msg where its
-	 * MessageLength is 16 bytes but the ByteCount field in the xfer page
-	 * range shows 52 bytes
-	 * */
-#if 0
-	if (Packet->TotalDataBufferLength != rndisHeader->MessageLength) {
-		kunmap_atomic(rndisHeader - Packet->PageBuffers[0].Offset,
-			      KM_IRQ0);
-
-		DPRINT_ERR(NETVSC, "invalid rndis message? (expected %u "
-			   "bytes got %u)...dropping this message!",
-			   rndisHeader->MessageLength,
-			   Packet->TotalDataBufferLength);
-		return -1;
-	}
-#endif
-
-	if ((rndisHeader->NdisMessageType != REMOTE_NDIS_PACKET_MSG) &&
-	    (rndisHeader->MessageLength > sizeof(struct rndis_message))) {
-		DPRINT_ERR(NETVSC, "incoming rndis message buffer overflow "
-			   "detected (got %u, max %zu)...marking it an error!",
-			   rndisHeader->MessageLength,
-			   sizeof(struct rndis_message));
-	}
-
-	memcpy(&rndisMessage, rndisHeader,
-		(rndisHeader->MessageLength > sizeof(struct rndis_message)) ?
-			sizeof(struct rndis_message) :
-			rndisHeader->MessageLength);
-
-	kunmap_atomic(rndisHeader - Packet->PageBuffers[0].Offset, KM_IRQ0);
-
-	DumpRndisMessage(&rndisMessage);
-
-	switch (rndisMessage.NdisMessageType) {
-	case REMOTE_NDIS_PACKET_MSG:
-		/* data msg */
-		RndisFilterReceiveData(rndisDevice, &rndisMessage, Packet);
-		break;
-
-	case REMOTE_NDIS_INITIALIZE_CMPLT:
-	case REMOTE_NDIS_QUERY_CMPLT:
-	case REMOTE_NDIS_SET_CMPLT:
-	/* case REMOTE_NDIS_RESET_CMPLT: */
-	/* case REMOTE_NDIS_KEEPALIVE_CMPLT: */
-		/* completion msgs */
-		RndisFilterReceiveResponse(rndisDevice, &rndisMessage);
-		break;
-
-	case REMOTE_NDIS_INDICATE_STATUS_MSG:
-		/* notification msgs */
-		RndisFilterReceiveIndicateStatus(rndisDevice, &rndisMessage);
-		break;
-	default:
-		DPRINT_ERR(NETVSC, "unhandled rndis message (type %u len %u)",
-			   rndisMessage.NdisMessageType,
-			   rndisMessage.MessageLength);
-		break;
-	}
-
-	return 0;
-}
-
-static int RndisFilterQueryDevice(struct rndis_device *Device, u32 Oid,
-				  void *Result, u32 *ResultSize)
-{
-	struct rndis_request *request;
-	u32 inresultSize = *ResultSize;
-	struct rndis_query_request *query;
-	struct rndis_query_complete *queryComplete;
-	int ret = 0;
-
-	if (!Result)
-		return -EINVAL;
-
-	*ResultSize = 0;
-	request = GetRndisRequest(Device, REMOTE_NDIS_QUERY_MSG,
-			RNDIS_MESSAGE_SIZE(struct rndis_query_request));
-	if (!request) {
-		ret = -1;
-		goto Cleanup;
-	}
-
-	/* Setup the rndis query */
-	query = &request->RequestMessage.Message.QueryRequest;
-	query->Oid = Oid;
-	query->InformationBufferOffset = sizeof(struct rndis_query_request);
-	query->InformationBufferLength = 0;
-	query->DeviceVcHandle = 0;
-
-	ret = RndisFilterSendRequest(Device, request);
-	if (ret != 0)
-		goto Cleanup;
-
-	osd_WaitEventWait(request->WaitEvent);
-
-	/* Copy the response back */
-	queryComplete = &request->ResponseMessage.Message.QueryComplete;
-
-	if (queryComplete->InformationBufferLength > inresultSize) {
-		ret = -1;
-		goto Cleanup;
-	}
-
-	memcpy(Result,
-	       (void *)((unsigned long)queryComplete +
-			 queryComplete->InformationBufferOffset),
-	       queryComplete->InformationBufferLength);
-
-	*ResultSize = queryComplete->InformationBufferLength;
-
-Cleanup:
-	if (request)
-		PutRndisRequest(Device, request);
-
-	return ret;
-}
-
-static int RndisFilterQueryDeviceMac(struct rndis_device *Device)
-{
-	u32 size = ETH_ALEN;
-
-	return RndisFilterQueryDevice(Device,
-				      RNDIS_OID_802_3_PERMANENT_ADDRESS,
-				      Device->HwMacAddr, &size);
-}
-
-static int RndisFilterQueryDeviceLinkStatus(struct rndis_device *Device)
-{
-	u32 size = sizeof(u32);
-
-	return RndisFilterQueryDevice(Device,
-				      RNDIS_OID_GEN_MEDIA_CONNECT_STATUS,
-				      &Device->LinkStatus, &size);
-}
-
-static int RndisFilterSetPacketFilter(struct rndis_device *Device,
-				      u32 NewFilter)
-{
-	struct rndis_request *request;
-	struct rndis_set_request *set;
-	struct rndis_set_complete *setComplete;
-	u32 status;
-	int ret;
-
-	/* ASSERT(RNDIS_MESSAGE_SIZE(struct rndis_set_request) + sizeof(u32) <= */
-	/* 	sizeof(struct rndis_message)); */
-
-	request = GetRndisRequest(Device, REMOTE_NDIS_SET_MSG,
-			RNDIS_MESSAGE_SIZE(struct rndis_set_request) +
-			sizeof(u32));
-	if (!request) {
-		ret = -1;
-		goto Cleanup;
-	}
-
-	/* Setup the rndis set */
-	set = &request->RequestMessage.Message.SetRequest;
-	set->Oid = RNDIS_OID_GEN_CURRENT_PACKET_FILTER;
-	set->InformationBufferLength = sizeof(u32);
-	set->InformationBufferOffset = sizeof(struct rndis_set_request);
-
-	memcpy((void *)(unsigned long)set + sizeof(struct rndis_set_request),
-	       &NewFilter, sizeof(u32));
-
-	ret = RndisFilterSendRequest(Device, request);
-	if (ret != 0)
-		goto Cleanup;
-
-	ret = osd_WaitEventWaitEx(request->WaitEvent, 2000/*2sec*/);
-	if (!ret) {
-		ret = -1;
-		DPRINT_ERR(NETVSC, "timeout before we got a set response...");
-		/*
-		 * We cant deallocate the request since we may still receive a
-		 * send completion for it.
-		 */
-		goto Exit;
-	} else {
-		if (ret > 0)
-			ret = 0;
-		setComplete = &request->ResponseMessage.Message.SetComplete;
-		status = setComplete->Status;
-	}
-
-Cleanup:
-	if (request)
-		PutRndisRequest(Device, request);
-Exit:
-	return ret;
-}
-
-int RndisFilterInit(struct netvsc_driver *Driver)
-{
-	DPRINT_DBG(NETVSC, "sizeof(struct rndis_filter_packet) == %zd",
-		   sizeof(struct rndis_filter_packet));
-
-	Driver->RequestExtSize = sizeof(struct rndis_filter_packet);
-
-	/* Driver->Context = rndisDriver; */
-
-	memset(&gRndisFilter, 0, sizeof(struct rndis_filter_driver_object));
-
-	/*rndisDriver->Driver = Driver;
-
-	ASSERT(Driver->OnLinkStatusChanged);
-	rndisDriver->OnLinkStatusChanged = Driver->OnLinkStatusChanged;*/
-
-	/* Save the original dispatch handlers before we override it */
-	gRndisFilter.InnerDriver.Base.OnDeviceAdd = Driver->Base.OnDeviceAdd;
-	gRndisFilter.InnerDriver.Base.OnDeviceRemove =
-					Driver->Base.OnDeviceRemove;
-	gRndisFilter.InnerDriver.Base.OnCleanup = Driver->Base.OnCleanup;
-
-	/* ASSERT(Driver->OnSend); */
-	/* ASSERT(Driver->OnReceiveCallback); */
-	gRndisFilter.InnerDriver.OnSend = Driver->OnSend;
-	gRndisFilter.InnerDriver.OnReceiveCallback = Driver->OnReceiveCallback;
-	gRndisFilter.InnerDriver.OnLinkStatusChanged =
-					Driver->OnLinkStatusChanged;
-
-	/* Override */
-	Driver->Base.OnDeviceAdd = RndisFilterOnDeviceAdd;
-	Driver->Base.OnDeviceRemove = RndisFilterOnDeviceRemove;
-	Driver->Base.OnCleanup = RndisFilterOnCleanup;
-	Driver->OnSend = RndisFilterOnSend;
-	/* Driver->QueryLinkStatus = RndisFilterQueryDeviceLinkStatus; */
-	Driver->OnReceiveCallback = RndisFilterOnReceive;
-
-	return 0;
-}
-
-static int RndisFilterInitDevice(struct rndis_device *Device)
-{
-	struct rndis_request *request;
-	struct rndis_initialize_request *init;
-	struct rndis_initialize_complete *initComplete;
-	u32 status;
-	int ret;
-
-	request = GetRndisRequest(Device, REMOTE_NDIS_INITIALIZE_MSG,
-			RNDIS_MESSAGE_SIZE(struct rndis_initialize_request));
-	if (!request) {
-		ret = -1;
-		goto Cleanup;
-	}
-
-	/* Setup the rndis set */
-	init = &request->RequestMessage.Message.InitializeRequest;
-	init->MajorVersion = RNDIS_MAJOR_VERSION;
-	init->MinorVersion = RNDIS_MINOR_VERSION;
-	/* FIXME: Use 1536 - rounded ethernet frame size */
-	init->MaxTransferSize = 2048;
-
-	Device->State = RNDIS_DEV_INITIALIZING;
-
-	ret = RndisFilterSendRequest(Device, request);
-	if (ret != 0) {
-		Device->State = RNDIS_DEV_UNINITIALIZED;
-		goto Cleanup;
-	}
-
-	osd_WaitEventWait(request->WaitEvent);
-
-	initComplete = &request->ResponseMessage.Message.InitializeComplete;
-	status = initComplete->Status;
-	if (status == RNDIS_STATUS_SUCCESS) {
-		Device->State = RNDIS_DEV_INITIALIZED;
-		ret = 0;
-	} else {
-		Device->State = RNDIS_DEV_UNINITIALIZED;
-		ret = -1;
-	}
-
-Cleanup:
-	if (request)
-		PutRndisRequest(Device, request);
-
-	return ret;
-}
-
-static void RndisFilterHaltDevice(struct rndis_device *Device)
-{
-	struct rndis_request *request;
-	struct rndis_halt_request *halt;
-
-	/* Attempt to do a rndis device halt */
-	request = GetRndisRequest(Device, REMOTE_NDIS_HALT_MSG,
-				RNDIS_MESSAGE_SIZE(struct rndis_halt_request));
-	if (!request)
-		goto Cleanup;
-
-	/* Setup the rndis set */
-	halt = &request->RequestMessage.Message.HaltRequest;
-	halt->RequestId = atomic_inc_return(&Device->NewRequestId);
-
-	/* Ignore return since this msg is optional. */
-	RndisFilterSendRequest(Device, request);
-
-	Device->State = RNDIS_DEV_UNINITIALIZED;
-
-Cleanup:
-	if (request)
-		PutRndisRequest(Device, request);
-	return;
-}
-
-static int RndisFilterOpenDevice(struct rndis_device *Device)
-{
-	int ret;
-
-	if (Device->State != RNDIS_DEV_INITIALIZED)
-		return 0;
-
-	ret = RndisFilterSetPacketFilter(Device,
-					 NDIS_PACKET_TYPE_BROADCAST |
-					 NDIS_PACKET_TYPE_ALL_MULTICAST |
-					 NDIS_PACKET_TYPE_DIRECTED);
-	if (ret == 0)
-		Device->State = RNDIS_DEV_DATAINITIALIZED;
-
-	return ret;
-}
-
-static int RndisFilterCloseDevice(struct rndis_device *Device)
-{
-	int ret;
-
-	if (Device->State != RNDIS_DEV_DATAINITIALIZED)
-		return 0;
-
-	ret = RndisFilterSetPacketFilter(Device, 0);
-	if (ret == 0)
-		Device->State = RNDIS_DEV_INITIALIZED;
-
-	return ret;
-}
-
-static int RndisFilterOnDeviceAdd(struct hv_device *Device,
-				  void *AdditionalInfo)
-{
-	int ret;
-	struct netvsc_device *netDevice;
-	struct rndis_device *rndisDevice;
-	struct netvsc_device_info *deviceInfo = AdditionalInfo;
-
-	rndisDevice = GetRndisDevice();
-	if (!rndisDevice)
-		return -1;
-
-	DPRINT_DBG(NETVSC, "rndis device object allocated - %p", rndisDevice);
-
-	/*
-	 * Let the inner driver handle this first to create the netvsc channel
-	 * NOTE! Once the channel is created, we may get a receive callback
-	 * (RndisFilterOnReceive()) before this call is completed
-	 */
-	ret = gRndisFilter.InnerDriver.Base.OnDeviceAdd(Device, AdditionalInfo);
-	if (ret != 0) {
-		kfree(rndisDevice);
-		return ret;
-	}
-
-
-	/* Initialize the rndis device */
-	netDevice = Device->Extension;
-	/* ASSERT(netDevice); */
-	/* ASSERT(netDevice->Device); */
-
-	netDevice->Extension = rndisDevice;
-	rndisDevice->NetDevice = netDevice;
-
-	/* Send the rndis initialization message */
-	ret = RndisFilterInitDevice(rndisDevice);
-	if (ret != 0) {
-		/*
-		 * TODO: If rndis init failed, we will need to shut down the
-		 * channel
-		 */
-	}
-
-	/* Get the mac address */
-	ret = RndisFilterQueryDeviceMac(rndisDevice);
-	if (ret != 0) {
-		/*
-		 * TODO: shutdown rndis device and the channel
-		 */
-	}
-
-	DPRINT_INFO(NETVSC, "Device 0x%p mac addr %pM",
-		    rndisDevice, rndisDevice->HwMacAddr);
-
-	memcpy(deviceInfo->MacAddr, rndisDevice->HwMacAddr, ETH_ALEN);
-
-	RndisFilterQueryDeviceLinkStatus(rndisDevice);
-
-	deviceInfo->LinkState = rndisDevice->LinkStatus;
-	DPRINT_INFO(NETVSC, "Device 0x%p link state %s", rndisDevice,
-		    ((deviceInfo->LinkState) ? ("down") : ("up")));
-
-	return ret;
-}
-
-static int RndisFilterOnDeviceRemove(struct hv_device *Device)
-{
-	struct netvsc_device *netDevice = Device->Extension;
-	struct rndis_device *rndisDevice = netDevice->Extension;
-
-	/* Halt and release the rndis device */
-	RndisFilterHaltDevice(rndisDevice);
-
-	kfree(rndisDevice);
-	netDevice->Extension = NULL;
-
-	/* Pass control to inner driver to remove the device */
-	gRndisFilter.InnerDriver.Base.OnDeviceRemove(Device);
-
-	return 0;
-}
-
-static void RndisFilterOnCleanup(struct hv_driver *Driver)
-{
-}
-
-int RndisFilterOnOpen(struct hv_device *Device)
-{
-	struct netvsc_device *netDevice = Device->Extension;
-
-	if (!netDevice)
-		return -EINVAL;
-
-	return RndisFilterOpenDevice(netDevice->Extension);
-}
-
-int RndisFilterOnClose(struct hv_device *Device)
-{
-	struct netvsc_device *netDevice = Device->Extension;
-
-	if (!netDevice)
-		return -EINVAL;
-
-	return RndisFilterCloseDevice(netDevice->Extension);
-}
-
-static int RndisFilterOnSend(struct hv_device *Device,
-			     struct hv_netvsc_packet *Packet)
-{
-	int ret;
-	struct rndis_filter_packet *filterPacket;
-	struct rndis_message *rndisMessage;
-	struct rndis_packet *rndisPacket;
-	u32 rndisMessageSize;
-
-	/* Add the rndis header */
-	filterPacket = (struct rndis_filter_packet *)Packet->Extension;
-	/* ASSERT(filterPacket); */
-
-	memset(filterPacket, 0, sizeof(struct rndis_filter_packet));
-
-	rndisMessage = &filterPacket->Message;
-	rndisMessageSize = RNDIS_MESSAGE_SIZE(struct rndis_packet);
-
-	rndisMessage->NdisMessageType = REMOTE_NDIS_PACKET_MSG;
-	rndisMessage->MessageLength = Packet->TotalDataBufferLength +
-				      rndisMessageSize;
-
-	rndisPacket = &rndisMessage->Message.Packet;
-	rndisPacket->DataOffset = sizeof(struct rndis_packet);
-	rndisPacket->DataLength = Packet->TotalDataBufferLength;
-
-	Packet->IsDataPacket = true;
-	Packet->PageBuffers[0].Pfn = virt_to_phys(rndisMessage) >> PAGE_SHIFT;
-	Packet->PageBuffers[0].Offset =
-			(unsigned long)rndisMessage & (PAGE_SIZE-1);
-	Packet->PageBuffers[0].Length = rndisMessageSize;
-
-	/* Save the packet send completion and context */
-	filterPacket->OnCompletion = Packet->Completion.Send.OnSendCompletion;
-	filterPacket->CompletionContext =
-				Packet->Completion.Send.SendCompletionContext;
-
-	/* Use ours */
-	Packet->Completion.Send.OnSendCompletion = RndisFilterOnSendCompletion;
-	Packet->Completion.Send.SendCompletionContext = filterPacket;
-
-	ret = gRndisFilter.InnerDriver.OnSend(Device, Packet);
-	if (ret != 0) {
-		/*
-		 * Reset the completion to originals to allow retries from
-		 * above
-		 */
-		Packet->Completion.Send.OnSendCompletion =
-				filterPacket->OnCompletion;
-		Packet->Completion.Send.SendCompletionContext =
-				filterPacket->CompletionContext;
-	}
-
-	return ret;
-}
-
-static void RndisFilterOnSendCompletion(void *Context)
-{
-	struct rndis_filter_packet *filterPacket = Context;
-
-	/* Pass it back to the original handler */
-	filterPacket->OnCompletion(filterPacket->CompletionContext);
-}
-
-
-static void RndisFilterOnSendRequestCompletion(void *Context)
-{
-	/* Noop */
-}
diff --git a/drivers/staging/hv/RndisFilter.h b/drivers/staging/hv/RndisFilter.h
deleted file mode 100644
index fa7dd79..0000000
--- a/drivers/staging/hv/RndisFilter.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- *
- * Copyright (c) 2009, Microsoft Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place - Suite 330, Boston, MA 02111-1307 USA.
- *
- * Authors:
- *   Haiyang Zhang <haiyangz@microsoft.com>
- *   Hank Janssen  <hjanssen@microsoft.com>
- *
- */
-
-
-#ifndef _RNDISFILTER_H_
-#define _RNDISFILTER_H_
-
-#define __struct_bcount(x)
-
-#include "NetVsc.h"
-
-#include "rndis.h"
-
-#define RNDIS_HEADER_SIZE	(sizeof(struct rndis_message) - \
-				 sizeof(union rndis_message_container))
-
-#define NDIS_PACKET_TYPE_DIRECTED	0x00000001
-#define NDIS_PACKET_TYPE_MULTICAST	0x00000002
-#define NDIS_PACKET_TYPE_ALL_MULTICAST	0x00000004
-#define NDIS_PACKET_TYPE_BROADCAST	0x00000008
-#define NDIS_PACKET_TYPE_SOURCE_ROUTING	0x00000010
-#define NDIS_PACKET_TYPE_PROMISCUOUS	0x00000020
-#define NDIS_PACKET_TYPE_SMT		0x00000040
-#define NDIS_PACKET_TYPE_ALL_LOCAL	0x00000080
-#define NDIS_PACKET_TYPE_GROUP		0x00000100
-#define NDIS_PACKET_TYPE_ALL_FUNCTIONAL	0x00000200
-#define NDIS_PACKET_TYPE_FUNCTIONAL	0x00000400
-#define NDIS_PACKET_TYPE_MAC_FRAME	0x00000800
-
-
-/* Interface */
-
-extern int RndisFilterInit(struct netvsc_driver *driver);
-
-#endif /* _RNDISFILTER_H_ */
diff --git a/drivers/staging/hv/StorVsc.c b/drivers/staging/hv/StorVsc.c
deleted file mode 100644
index 57bd315..0000000
--- a/drivers/staging/hv/StorVsc.c
+++ /dev/null
@@ -1,856 +0,0 @@
-/*
- * Copyright (c) 2009, Microsoft Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place - Suite 330, Boston, MA 02111-1307 USA.
- *
- * Authors:
- *   Haiyang Zhang <haiyangz@microsoft.com>
- *   Hank Janssen  <hjanssen@microsoft.com>
- */
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <linux/mm.h>
-#include <linux/delay.h>
-#include "osd.h"
-#include "logging.h"
-#include "StorVscApi.h"
-#include "VmbusPacketFormat.h"
-#include "vstorage.h"
-
-
-struct storvsc_request_extension {
-	/* LIST_ENTRY ListEntry; */
-
-	struct hv_storvsc_request *Request;
-	struct hv_device *Device;
-
-	/* Synchronize the request/response if needed */
-	struct osd_waitevent *WaitEvent;
-
-	struct vstor_packet VStorPacket;
-};
-
-/* A storvsc device is a device object that contains a vmbus channel */
-struct storvsc_device {
-	struct hv_device *Device;
-
-	/* 0 indicates the device is being destroyed */
-	atomic_t RefCount;
-
-	int reset;
-	spinlock_t lock;
-	atomic_t NumOutstandingRequests;
-
-	/*
-	 * Each unique Port/Path/Target represents 1 channel ie scsi
-	 * controller. In reality, the pathid, targetid is always 0
-	 * and the port is set by us
-	 */
-	unsigned int PortNumber;
-	unsigned char PathId;
-	unsigned char TargetId;
-
-	/* LIST_ENTRY OutstandingRequestList; */
-	/* HANDLE OutstandingRequestLock; */
-
-	/* Used for vsc/vsp channel reset process */
-	struct storvsc_request_extension InitRequest;
-	struct storvsc_request_extension ResetRequest;
-};
-
-
-static const char *gDriverName = "storvsc";
-
-/* {ba6163d9-04a1-4d29-b605-72e2ffb1dc7f} */
-static const struct hv_guid gStorVscDeviceType = {
-	.data = {
-		0xd9, 0x63, 0x61, 0xba, 0xa1, 0x04, 0x29, 0x4d,
-		0xb6, 0x05, 0x72, 0xe2, 0xff, 0xb1, 0xdc, 0x7f
-	}
-};
-
-
-static inline struct storvsc_device *AllocStorDevice(struct hv_device *Device)
-{
-	struct storvsc_device *storDevice;
-
-	storDevice = kzalloc(sizeof(struct storvsc_device), GFP_KERNEL);
-	if (!storDevice)
-		return NULL;
-
-	/* Set to 2 to allow both inbound and outbound traffics */
-	/* (ie GetStorDevice() and MustGetStorDevice()) to proceed. */
-	atomic_cmpxchg(&storDevice->RefCount, 0, 2);
-
-	storDevice->Device = Device;
-	storDevice->reset  = 0;
-	spin_lock_init(&storDevice->lock);
-
-	Device->Extension = storDevice;
-
-	return storDevice;
-}
-
-static inline void FreeStorDevice(struct storvsc_device *Device)
-{
-	/* ASSERT(atomic_read(&Device->RefCount) == 0); */
-	/*kfree(Device->lock);*/
-	kfree(Device);
-}
-
-/* Get the stordevice object iff exists and its refcount > 1 */
-static inline struct storvsc_device *GetStorDevice(struct hv_device *Device)
-{
-	struct storvsc_device *storDevice;
-	unsigned long flags;
-
-	storDevice = (struct storvsc_device *)Device->Extension;
-
-	spin_lock_irqsave(&storDevice->lock, flags);
-
-	if (storDevice->reset == 1) {
-		spin_unlock_irqrestore(&storDevice->lock, flags);
-		return NULL;
-	}
-
-	if (storDevice && atomic_read(&storDevice->RefCount) > 1)
-		atomic_inc(&storDevice->RefCount);
-	else
-		storDevice = NULL;
-
-	spin_unlock_irqrestore(&storDevice->lock, flags);
-
-	return storDevice;
-}
-
-/* Get the stordevice object iff exists and its refcount > 0 */
-static inline struct storvsc_device *MustGetStorDevice(struct hv_device *Device)
-{
-	struct storvsc_device *storDevice;
-	unsigned long flags;
-
-	storDevice = (struct storvsc_device *)Device->Extension;
-
-	spin_lock_irqsave(&storDevice->lock, flags);
-
-	if (storDevice && atomic_read(&storDevice->RefCount))
-		atomic_inc(&storDevice->RefCount);
-	else
-		storDevice = NULL;
-
-	spin_unlock_irqrestore(&storDevice->lock, flags);
-
-	return storDevice;
-}
-
-static inline void PutStorDevice(struct hv_device *Device)
-{
-	struct storvsc_device *storDevice;
-
-	storDevice = (struct storvsc_device *)Device->Extension;
-	/* ASSERT(storDevice); */
-
-	atomic_dec(&storDevice->RefCount);
-	/* ASSERT(atomic_read(&storDevice->RefCount)); */
-}
-
-/* Drop ref count to 1 to effectively disable GetStorDevice() */
-static inline struct storvsc_device *ReleaseStorDevice(struct hv_device *Device)
-{
-	struct storvsc_device *storDevice;
-
-	storDevice = (struct storvsc_device *)Device->Extension;
-	/* ASSERT(storDevice); */
-
-	/* Busy wait until the ref drop to 2, then set it to 1 */
-	while (atomic_cmpxchg(&storDevice->RefCount, 2, 1) != 2)
-		udelay(100);
-
-	return storDevice;
-}
-
-/* Drop ref count to 0. No one can use StorDevice object. */
-static inline struct storvsc_device *FinalReleaseStorDevice(
-			struct hv_device *Device)
-{
-	struct storvsc_device *storDevice;
-
-	storDevice = (struct storvsc_device *)Device->Extension;
-	/* ASSERT(storDevice); */
-
-	/* Busy wait until the ref drop to 1, then set it to 0 */
-	while (atomic_cmpxchg(&storDevice->RefCount, 1, 0) != 1)
-		udelay(100);
-
-	Device->Extension = NULL;
-	return storDevice;
-}
-
-static int StorVscChannelInit(struct hv_device *Device)
-{
-	struct storvsc_device *storDevice;
-	struct storvsc_request_extension *request;
-	struct vstor_packet *vstorPacket;
-	int ret;
-
-	storDevice = GetStorDevice(Device);
-	if (!storDevice) {
-		DPRINT_ERR(STORVSC, "unable to get stor device..."
-			   "device being destroyed?");
-		return -1;
-	}
-
-	request = &storDevice->InitRequest;
-	vstorPacket = &request->VStorPacket;
-
-	/*
-	 * Now, initiate the vsc/vsp initialization protocol on the open
-	 * channel
-	 */
-	memset(request, 0, sizeof(struct storvsc_request_extension));
-	request->WaitEvent = osd_WaitEventCreate();
-	if (!request->WaitEvent) {
-		ret = -ENOMEM;
-		goto nomem;
-	}
-
-	vstorPacket->Operation = VStorOperationBeginInitialization;
-	vstorPacket->Flags = REQUEST_COMPLETION_FLAG;
-
-	/*SpinlockAcquire(gDriverExt.packetListLock);
-	INSERT_TAIL_LIST(&gDriverExt.packetList, &packet->listEntry.entry);
-	SpinlockRelease(gDriverExt.packetListLock);*/
-
-	DPRINT_INFO(STORVSC, "BEGIN_INITIALIZATION_OPERATION...");
-
-	ret = Device->Driver->VmbusChannelInterface.SendPacket(Device,
-				vstorPacket,
-				sizeof(struct vstor_packet),
-				(unsigned long)request,
-				VmbusPacketTypeDataInBand,
-				VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
-	if (ret != 0) {
-		DPRINT_ERR(STORVSC,
-			   "unable to send BEGIN_INITIALIZATION_OPERATION");
-		goto Cleanup;
-	}
-
-	osd_WaitEventWait(request->WaitEvent);
-
-	if (vstorPacket->Operation != VStorOperationCompleteIo ||
-	    vstorPacket->Status != 0) {
-		DPRINT_ERR(STORVSC, "BEGIN_INITIALIZATION_OPERATION failed "
-			   "(op %d status 0x%x)",
-			   vstorPacket->Operation, vstorPacket->Status);
-		goto Cleanup;
-	}
-
-	DPRINT_INFO(STORVSC, "QUERY_PROTOCOL_VERSION_OPERATION...");
-
-	/* reuse the packet for version range supported */
-	memset(vstorPacket, 0, sizeof(struct vstor_packet));
-	vstorPacket->Operation = VStorOperationQueryProtocolVersion;
-	vstorPacket->Flags = REQUEST_COMPLETION_FLAG;
-
-	vstorPacket->Version.MajorMinor = VMSTOR_PROTOCOL_VERSION_CURRENT;
-	FILL_VMSTOR_REVISION(vstorPacket->Version.Revision);
-
-	ret = Device->Driver->VmbusChannelInterface.SendPacket(Device,
-				vstorPacket,
-				sizeof(struct vstor_packet),
-				(unsigned long)request,
-				VmbusPacketTypeDataInBand,
-				VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
-	if (ret != 0) {
-		DPRINT_ERR(STORVSC,
-			   "unable to send BEGIN_INITIALIZATION_OPERATION");
-		goto Cleanup;
-	}
-
-	osd_WaitEventWait(request->WaitEvent);
-
-	/* TODO: Check returned version */
-	if (vstorPacket->Operation != VStorOperationCompleteIo ||
-	    vstorPacket->Status != 0) {
-		DPRINT_ERR(STORVSC, "QUERY_PROTOCOL_VERSION_OPERATION failed "
-			   "(op %d status 0x%x)",
-			   vstorPacket->Operation, vstorPacket->Status);
-		goto Cleanup;
-	}
-
-	/* Query channel properties */
-	DPRINT_INFO(STORVSC, "QUERY_PROPERTIES_OPERATION...");
-
-	memset(vstorPacket, 0, sizeof(struct vstor_packet));
-	vstorPacket->Operation = VStorOperationQueryProperties;
-	vstorPacket->Flags = REQUEST_COMPLETION_FLAG;
-	vstorPacket->StorageChannelProperties.PortNumber =
-					storDevice->PortNumber;
-
-	ret = Device->Driver->VmbusChannelInterface.SendPacket(Device,
-				vstorPacket,
-				sizeof(struct vstor_packet),
-				(unsigned long)request,
-				VmbusPacketTypeDataInBand,
-				VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
-
-	if (ret != 0) {
-		DPRINT_ERR(STORVSC,
-			   "unable to send QUERY_PROPERTIES_OPERATION");
-		goto Cleanup;
-	}
-
-	osd_WaitEventWait(request->WaitEvent);
-
-	/* TODO: Check returned version */
-	if (vstorPacket->Operation != VStorOperationCompleteIo ||
-	    vstorPacket->Status != 0) {
-		DPRINT_ERR(STORVSC, "QUERY_PROPERTIES_OPERATION failed "
-			   "(op %d status 0x%x)",
-			   vstorPacket->Operation, vstorPacket->Status);
-		goto Cleanup;
-	}
-
-	storDevice->PathId = vstorPacket->StorageChannelProperties.PathId;
-	storDevice->TargetId = vstorPacket->StorageChannelProperties.TargetId;
-
-	DPRINT_DBG(STORVSC, "channel flag 0x%x, max xfer len 0x%x",
-		   vstorPacket->StorageChannelProperties.Flags,
-		   vstorPacket->StorageChannelProperties.MaxTransferBytes);
-
-	DPRINT_INFO(STORVSC, "END_INITIALIZATION_OPERATION...");
-
-	memset(vstorPacket, 0, sizeof(struct vstor_packet));
-	vstorPacket->Operation = VStorOperationEndInitialization;
-	vstorPacket->Flags = REQUEST_COMPLETION_FLAG;
-
-	ret = Device->Driver->VmbusChannelInterface.SendPacket(Device,
-				vstorPacket,
-				sizeof(struct vstor_packet),
-				(unsigned long)request,
-				VmbusPacketTypeDataInBand,
-				VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
-
-	if (ret != 0) {
-		DPRINT_ERR(STORVSC,
-			   "unable to send END_INITIALIZATION_OPERATION");
-		goto Cleanup;
-	}
-
-	osd_WaitEventWait(request->WaitEvent);
-
-	if (vstorPacket->Operation != VStorOperationCompleteIo ||
-	    vstorPacket->Status != 0) {
-		DPRINT_ERR(STORVSC, "END_INITIALIZATION_OPERATION failed "
-			   "(op %d status 0x%x)",
-			   vstorPacket->Operation, vstorPacket->Status);
-		goto Cleanup;
-	}
-
-	DPRINT_INFO(STORVSC, "**** storage channel up and running!! ****");
-
-Cleanup:
-	kfree(request->WaitEvent);
-	request->WaitEvent = NULL;
-nomem:
-	PutStorDevice(Device);
-	return ret;
-}
-
-static void StorVscOnIOCompletion(struct hv_device *Device,
-				  struct vstor_packet *VStorPacket,
-				  struct storvsc_request_extension *RequestExt)
-{
-	struct hv_storvsc_request *request;
-	struct storvsc_device *storDevice;
-
-	storDevice = MustGetStorDevice(Device);
-	if (!storDevice) {
-		DPRINT_ERR(STORVSC, "unable to get stor device..."
-			   "device being destroyed?");
-		return;
-	}
-
-	DPRINT_DBG(STORVSC, "IO_COMPLETE_OPERATION - request extension %p "
-		   "completed bytes xfer %u", RequestExt,
-		   VStorPacket->VmSrb.DataTransferLength);
-
-	/* ASSERT(RequestExt != NULL); */
-	/* ASSERT(RequestExt->Request != NULL); */
-
-	request = RequestExt->Request;
-
-	/* ASSERT(request->OnIOCompletion != NULL); */
-
-	/* Copy over the status...etc */
-	request->Status = VStorPacket->VmSrb.ScsiStatus;
-
-	if (request->Status != 0 || VStorPacket->VmSrb.SrbStatus != 1) {
-		DPRINT_WARN(STORVSC,
-			    "cmd 0x%x scsi status 0x%x srb status 0x%x\n",
-			    request->Cdb[0], VStorPacket->VmSrb.ScsiStatus,
-			    VStorPacket->VmSrb.SrbStatus);
-	}
-
-	if ((request->Status & 0xFF) == 0x02) {
-		/* CHECK_CONDITION */
-		if (VStorPacket->VmSrb.SrbStatus & 0x80) {
-			/* autosense data available */
-			DPRINT_WARN(STORVSC, "storvsc pkt %p autosense data "
-				    "valid - len %d\n", RequestExt,
-				    VStorPacket->VmSrb.SenseInfoLength);
-
-			/* ASSERT(VStorPacket->VmSrb.SenseInfoLength <= */
-			/* 	request->SenseBufferSize); */
-			memcpy(request->SenseBuffer,
-			       VStorPacket->VmSrb.SenseData,
-			       VStorPacket->VmSrb.SenseInfoLength);
-
-			request->SenseBufferSize =
-					VStorPacket->VmSrb.SenseInfoLength;
-		}
-	}
-
-	/* TODO: */
-	request->BytesXfer = VStorPacket->VmSrb.DataTransferLength;
-
-	request->OnIOCompletion(request);
-
-	atomic_dec(&storDevice->NumOutstandingRequests);
-
-	PutStorDevice(Device);
-}
-
-static void StorVscOnReceive(struct hv_device *Device,
-			     struct vstor_packet *VStorPacket,
-			     struct storvsc_request_extension *RequestExt)
-{
-	switch (VStorPacket->Operation) {
-	case VStorOperationCompleteIo:
-		DPRINT_DBG(STORVSC, "IO_COMPLETE_OPERATION");
-		StorVscOnIOCompletion(Device, VStorPacket, RequestExt);
-		break;
-	case VStorOperationRemoveDevice:
-		DPRINT_INFO(STORVSC, "REMOVE_DEVICE_OPERATION");
-		/* TODO: */
-		break;
-
-	default:
-		DPRINT_INFO(STORVSC, "Unknown operation received - %d",
-			    VStorPacket->Operation);
-		break;
-	}
-}
-
-static void StorVscOnChannelCallback(void *context)
-{
-	struct hv_device *device = (struct hv_device *)context;
-	struct storvsc_device *storDevice;
-	u32 bytesRecvd;
-	u64 requestId;
-	unsigned char packet[ALIGN_UP(sizeof(struct vstor_packet), 8)];
-	struct storvsc_request_extension *request;
-	int ret;
-
-	/* ASSERT(device); */
-
-	storDevice = MustGetStorDevice(device);
-	if (!storDevice) {
-		DPRINT_ERR(STORVSC, "unable to get stor device..."
-			   "device being destroyed?");
-		return;
-	}
-
-	do {
-		ret = device->Driver->VmbusChannelInterface.RecvPacket(device,
-				packet,
-				ALIGN_UP(sizeof(struct vstor_packet), 8),
-				&bytesRecvd, &requestId);
-		if (ret == 0 && bytesRecvd > 0) {
-			DPRINT_DBG(STORVSC, "receive %d bytes - tid %llx",
-				   bytesRecvd, requestId);
-
-			/* ASSERT(bytesRecvd == sizeof(struct vstor_packet)); */
-
-			request = (struct storvsc_request_extension *)
-					(unsigned long)requestId;
-			/* ASSERT(request);c */
-
-			/* if (vstorPacket.Flags & SYNTHETIC_FLAG) */
-			if ((request == &storDevice->InitRequest) ||
-			    (request == &storDevice->ResetRequest)) {
-				/* DPRINT_INFO(STORVSC,
-				 *             "reset completion - operation "
-				 *             "%u status %u",
-				 *             vstorPacket.Operation,
-				 *             vstorPacket.Status); */
-
-				memcpy(&request->VStorPacket, packet,
-				       sizeof(struct vstor_packet));
-
-				osd_WaitEventSet(request->WaitEvent);
-			} else {
-				StorVscOnReceive(device,
-						(struct vstor_packet *)packet,
-						request);
-			}
-		} else {
-			/* DPRINT_DBG(STORVSC, "nothing else to read..."); */
-			break;
-		}
-	} while (1);
-
-	PutStorDevice(device);
-	return;
-}
-
-static int StorVscConnectToVsp(struct hv_device *Device)
-{
-	struct vmstorage_channel_properties props;
-	struct storvsc_driver_object *storDriver;
-	int ret;
-
-	storDriver = (struct storvsc_driver_object *)Device->Driver;
-	memset(&props, 0, sizeof(struct vmstorage_channel_properties));
-
-	/* Open the channel */
-	ret = Device->Driver->VmbusChannelInterface.Open(Device,
-			storDriver->RingBufferSize,
-			storDriver->RingBufferSize,
-			(void *)&props,
-			sizeof(struct vmstorage_channel_properties),
-			StorVscOnChannelCallback,
-			Device);
-
-	DPRINT_DBG(STORVSC, "storage props: path id %d, tgt id %d, max xfer %d",
-		   props.PathId, props.TargetId, props.MaxTransferBytes);
-
-	if (ret != 0) {
-		DPRINT_ERR(STORVSC, "unable to open channel: %d", ret);
-		return -1;
-	}
-
-	ret = StorVscChannelInit(Device);
-
-	return ret;
-}
-
-/*
- * StorVscOnDeviceAdd - Callback when the device belonging to this driver is added
- */
-static int StorVscOnDeviceAdd(struct hv_device *Device, void *AdditionalInfo)
-{
-	struct storvsc_device *storDevice;
-	/* struct vmstorage_channel_properties *props; */
-	struct storvsc_device_info *deviceInfo;
-	int ret = 0;
-
-	deviceInfo = (struct storvsc_device_info *)AdditionalInfo;
-	storDevice = AllocStorDevice(Device);
-	if (!storDevice) {
-		ret = -1;
-		goto Cleanup;
-	}
-
-	/* Save the channel properties to our storvsc channel */
-	/* props = (struct vmstorage_channel_properties *)
-	 *		channel->offerMsg.Offer.u.Standard.UserDefined; */
-
-	/* FIXME: */
-	/*
-	 * If we support more than 1 scsi channel, we need to set the
-	 * port number here to the scsi channel but how do we get the
-	 * scsi channel prior to the bus scan
-	 */
-
-	/* storChannel->PortNumber = 0;
-	storChannel->PathId = props->PathId;
-	storChannel->TargetId = props->TargetId; */
-
-	storDevice->PortNumber = deviceInfo->PortNumber;
-	/* Send it back up */
-	ret = StorVscConnectToVsp(Device);
-
-	/* deviceInfo->PortNumber = storDevice->PortNumber; */
-	deviceInfo->PathId = storDevice->PathId;
-	deviceInfo->TargetId = storDevice->TargetId;
-
-	DPRINT_DBG(STORVSC, "assigned port %u, path %u target %u\n",
-		   storDevice->PortNumber, storDevice->PathId,
-		   storDevice->TargetId);
-
-Cleanup:
-	return ret;
-}
-
-/*
- * StorVscOnDeviceRemove - Callback when the our device is being removed
- */
-static int StorVscOnDeviceRemove(struct hv_device *Device)
-{
-	struct storvsc_device *storDevice;
-
-	DPRINT_INFO(STORVSC, "disabling storage device (%p)...",
-		    Device->Extension);
-
-	storDevice = ReleaseStorDevice(Device);
-
-	/*
-	 * At this point, all outbound traffic should be disable. We
-	 * only allow inbound traffic (responses) to proceed so that
-	 * outstanding requests can be completed.
-	 */
-	while (atomic_read(&storDevice->NumOutstandingRequests)) {
-		DPRINT_INFO(STORVSC, "waiting for %d requests to complete...",
-			    atomic_read(&storDevice->NumOutstandingRequests));
-		udelay(100);
-	}
-
-	DPRINT_INFO(STORVSC, "removing storage device (%p)...",
-		    Device->Extension);
-
-	storDevice = FinalReleaseStorDevice(Device);
-
-	DPRINT_INFO(STORVSC, "storage device (%p) safe to remove", storDevice);
-
-	/* Close the channel */
-	Device->Driver->VmbusChannelInterface.Close(Device);
-
-	FreeStorDevice(storDevice);
-	return 0;
-}
-
-int StorVscOnHostReset(struct hv_device *Device)
-{
-	struct storvsc_device *storDevice;
-	struct storvsc_request_extension *request;
-	struct vstor_packet *vstorPacket;
-	unsigned long flags;
-	int ret;
-
-	DPRINT_INFO(STORVSC, "resetting host adapter...");
-
-	storDevice = GetStorDevice(Device);
-	if (!storDevice) {
-		DPRINT_ERR(STORVSC, "unable to get stor device..."
-			   "device being destroyed?");
-		return -1;
-	}
-
-	spin_lock_irqsave(&storDevice->lock, flags);
-	storDevice->reset = 1;
-	spin_unlock_irqrestore(&storDevice->lock, flags);
-
-	/*
-	 * Wait for traffic in transit to complete
-	 */
-	while (atomic_read(&storDevice->NumOutstandingRequests))
-		udelay(1000);
-
-	request = &storDevice->ResetRequest;
-	vstorPacket = &request->VStorPacket;
-
-	request->WaitEvent = osd_WaitEventCreate();
-	if (!request->WaitEvent) {
-		ret = -ENOMEM;
-		goto Cleanup;
-	}
-
-	vstorPacket->Operation = VStorOperationResetBus;
-	vstorPacket->Flags = REQUEST_COMPLETION_FLAG;
-	vstorPacket->VmSrb.PathId = storDevice->PathId;
-
-	ret = Device->Driver->VmbusChannelInterface.SendPacket(Device,
-				vstorPacket,
-				sizeof(struct vstor_packet),
-				(unsigned long)&storDevice->ResetRequest,
-				VmbusPacketTypeDataInBand,
-				VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
-	if (ret != 0) {
-		DPRINT_ERR(STORVSC, "Unable to send reset packet %p ret %d",
-			   vstorPacket, ret);
-		goto Cleanup;
-	}
-
-	/* FIXME: Add a timeout */
-	osd_WaitEventWait(request->WaitEvent);
-
-	kfree(request->WaitEvent);
-	DPRINT_INFO(STORVSC, "host adapter reset completed");
-
-	/*
-	 * At this point, all outstanding requests in the adapter
-	 * should have been flushed out and return to us
-	 */
-
-Cleanup:
-	PutStorDevice(Device);
-	return ret;
-}
-
-/*
- * StorVscOnIORequest - Callback to initiate an I/O request
- */
-static int StorVscOnIORequest(struct hv_device *Device,
-			      struct hv_storvsc_request *Request)
-{
-	struct storvsc_device *storDevice;
-	struct storvsc_request_extension *requestExtension;
-	struct vstor_packet *vstorPacket;
-	int ret = 0;
-
-	requestExtension =
-		(struct storvsc_request_extension *)Request->Extension;
-	vstorPacket = &requestExtension->VStorPacket;
-	storDevice = GetStorDevice(Device);
-
-	DPRINT_DBG(STORVSC, "enter - Device %p, DeviceExt %p, Request %p, "
-		   "Extension %p", Device, storDevice, Request,
-		   requestExtension);
-
-	DPRINT_DBG(STORVSC, "req %p len %d bus %d, target %d, lun %d cdblen %d",
-		   Request, Request->DataBuffer.Length, Request->Bus,
-		   Request->TargetId, Request->LunId, Request->CdbLen);
-
-	if (!storDevice) {
-		DPRINT_ERR(STORVSC, "unable to get stor device..."
-			   "device being destroyed?");
-		return -2;
-	}
-
-	/* print_hex_dump_bytes("", DUMP_PREFIX_NONE, Request->Cdb,
-	 *			Request->CdbLen); */
-
-	requestExtension->Request = Request;
-	requestExtension->Device  = Device;
-
-	memset(vstorPacket, 0 , sizeof(struct vstor_packet));
-
-	vstorPacket->Flags |= REQUEST_COMPLETION_FLAG;
-
-	vstorPacket->VmSrb.Length = sizeof(struct vmscsi_request);
-
-	vstorPacket->VmSrb.PortNumber = Request->Host;
-	vstorPacket->VmSrb.PathId = Request->Bus;
-	vstorPacket->VmSrb.TargetId = Request->TargetId;
-	vstorPacket->VmSrb.Lun = Request->LunId;
-
-	vstorPacket->VmSrb.SenseInfoLength = SENSE_BUFFER_SIZE;
-
-	/* Copy over the scsi command descriptor block */
-	vstorPacket->VmSrb.CdbLength = Request->CdbLen;
-	memcpy(&vstorPacket->VmSrb.Cdb, Request->Cdb, Request->CdbLen);
-
-	vstorPacket->VmSrb.DataIn = Request->Type;
-	vstorPacket->VmSrb.DataTransferLength = Request->DataBuffer.Length;
-
-	vstorPacket->Operation = VStorOperationExecuteSRB;
-
-	DPRINT_DBG(STORVSC, "srb - len %d port %d, path %d, target %d, "
-		   "lun %d senselen %d cdblen %d",
-		   vstorPacket->VmSrb.Length,
-		   vstorPacket->VmSrb.PortNumber,
-		   vstorPacket->VmSrb.PathId,
-		   vstorPacket->VmSrb.TargetId,
-		   vstorPacket->VmSrb.Lun,
-		   vstorPacket->VmSrb.SenseInfoLength,
-		   vstorPacket->VmSrb.CdbLength);
-
-	if (requestExtension->Request->DataBuffer.Length) {
-		ret = Device->Driver->VmbusChannelInterface.
-			SendPacketMultiPageBuffer(Device,
-				&requestExtension->Request->DataBuffer,
-				vstorPacket,
-				sizeof(struct vstor_packet),
-				(unsigned long)requestExtension);
-	} else {
-		ret = Device->Driver->VmbusChannelInterface.SendPacket(Device,
-				vstorPacket,
-				sizeof(struct vstor_packet),
-				(unsigned long)requestExtension,
-				VmbusPacketTypeDataInBand,
-				VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
-	}
-
-	if (ret != 0) {
-		DPRINT_DBG(STORVSC, "Unable to send packet %p ret %d",
-			   vstorPacket, ret);
-	}
-
-	atomic_inc(&storDevice->NumOutstandingRequests);
-
-	PutStorDevice(Device);
-	return ret;
-}
-
-/*
- * StorVscOnCleanup - Perform any cleanup when the driver is removed
- */
-static void StorVscOnCleanup(struct hv_driver *Driver)
-{
-}
-
-/*
- * StorVscInitialize - Main entry point
- */
-int StorVscInitialize(struct hv_driver *Driver)
-{
-	struct storvsc_driver_object *storDriver;
-
-	storDriver = (struct storvsc_driver_object *)Driver;
-
-	DPRINT_DBG(STORVSC, "sizeof(STORVSC_REQUEST)=%zd "
-		   "sizeof(struct storvsc_request_extension)=%zd "
-		   "sizeof(struct vstor_packet)=%zd, "
-		   "sizeof(struct vmscsi_request)=%zd",
-		   sizeof(struct hv_storvsc_request),
-		   sizeof(struct storvsc_request_extension),
-		   sizeof(struct vstor_packet),
-		   sizeof(struct vmscsi_request));
-
-	/* Make sure we are at least 2 pages since 1 page is used for control */
-	/* ASSERT(storDriver->RingBufferSize >= (PAGE_SIZE << 1)); */
-
-	Driver->name = gDriverName;
-	memcpy(&Driver->deviceType, &gStorVscDeviceType,
-	       sizeof(struct hv_guid));
-
-	storDriver->RequestExtSize = sizeof(struct storvsc_request_extension);
-
-	/*
-	 * Divide the ring buffer data size (which is 1 page less
-	 * than the ring buffer size since that page is reserved for
-	 * the ring buffer indices) by the max request size (which is
-	 * VMBUS_CHANNEL_PACKET_MULITPAGE_BUFFER + struct vstor_packet + u64)
-	 */
-	storDriver->MaxOutstandingRequestsPerChannel =
-		((storDriver->RingBufferSize - PAGE_SIZE) /
-		  ALIGN_UP(MAX_MULTIPAGE_BUFFER_PACKET +
-			   sizeof(struct vstor_packet) + sizeof(u64),
-			   sizeof(u64)));
-
-	DPRINT_INFO(STORVSC, "max io %u, currently %u\n",
-		    storDriver->MaxOutstandingRequestsPerChannel,
-		    STORVSC_MAX_IO_REQUESTS);
-
-	/* Setup the dispatch table */
-	storDriver->Base.OnDeviceAdd	= StorVscOnDeviceAdd;
-	storDriver->Base.OnDeviceRemove	= StorVscOnDeviceRemove;
-	storDriver->Base.OnCleanup	= StorVscOnCleanup;
-
-	storDriver->OnIORequest		= StorVscOnIORequest;
-
-	return 0;
-}
diff --git a/drivers/staging/hv/StorVscApi.h b/drivers/staging/hv/StorVscApi.h
deleted file mode 100644
index aad90bd..0000000
--- a/drivers/staging/hv/StorVscApi.h
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- *
- * Copyright (c) 2009, Microsoft Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place - Suite 330, Boston, MA 02111-1307 USA.
- *
- * Authors:
- *   Haiyang Zhang <haiyangz@microsoft.com>
- *   Hank Janssen  <hjanssen@microsoft.com>
- *
- */
-
-
-#ifndef _STORVSC_API_H_
-#define _STORVSC_API_H_
-
-#include "VmbusApi.h"
-
-/* Defines */
-#define STORVSC_RING_BUFFER_SIZE			(20*PAGE_SIZE)
-#define BLKVSC_RING_BUFFER_SIZE				(20*PAGE_SIZE)
-
-#define STORVSC_MAX_IO_REQUESTS				128
-
-/*
- * In Hyper-V, each port/path/target maps to 1 scsi host adapter.  In
- * reality, the path/target is not used (ie always set to 0) so our
- * scsi host adapter essentially has 1 bus with 1 target that contains
- * up to 256 luns.
- */
-#define STORVSC_MAX_LUNS_PER_TARGET			64
-#define STORVSC_MAX_TARGETS				1
-#define STORVSC_MAX_CHANNELS				1
-
-struct hv_storvsc_request;
-
-/* Matches Windows-end */
-enum storvsc_request_type{
-	WRITE_TYPE,
-	READ_TYPE,
-	UNKNOWN_TYPE,
-};
-
-struct hv_storvsc_request {
-	enum storvsc_request_type Type;
-	u32 Host;
-	u32 Bus;
-	u32 TargetId;
-	u32 LunId;
-	u8 *Cdb;
-	u32 CdbLen;
-	u32 Status;
-	u32 BytesXfer;
-
-	unsigned char *SenseBuffer;
-	u32 SenseBufferSize;
-
-	void *Context;
-
-	void (*OnIOCompletion)(struct hv_storvsc_request *Request);
-
-	/* This points to the memory after DataBuffer */
-	void *Extension;
-
-	struct hv_multipage_buffer DataBuffer;
-};
-
-/* Represents the block vsc driver */
-struct storvsc_driver_object {
-	/* Must be the first field */
-	/* Which is a bug FIXME! */
-	struct hv_driver Base;
-
-	/* Set by caller (in bytes) */
-	u32 RingBufferSize;
-
-	/* Allocate this much private extension for each I/O request */
-	u32 RequestExtSize;
-
-	/* Maximum # of requests in flight per channel/device */
-	u32 MaxOutstandingRequestsPerChannel;
-
-	/* Specific to this driver */
-	int (*OnIORequest)(struct hv_device *Device,
-			   struct hv_storvsc_request *Request);
-};
-
-struct storvsc_device_info {
-	unsigned int PortNumber;
-	unsigned char PathId;
-	unsigned char TargetId;
-};
-
-/* Interface */
-int StorVscInitialize(struct hv_driver *driver);
-int StorVscOnHostReset(struct hv_device *Device);
-int BlkVscInitialize(struct hv_driver *driver);
-
-#endif /* _STORVSC_API_H_ */
diff --git a/drivers/staging/hv/TODO b/drivers/staging/hv/TODO
index dbfbde9..582fd4a 100644
--- a/drivers/staging/hv/TODO
+++ b/drivers/staging/hv/TODO
@@ -1,15 +1,10 @@
 TODO:
 	- fix remaining checkpatch warnings and errors
-	- use of /** when it is not a kerneldoc header
-	- remove RingBuffer.c to us in-kernel ringbuffer functions instead.
 	- audit the vmbus to verify it is working properly with the
 	  driver model
-	- convert vmbus driver interface function pointer tables
-          to constant, a.k.a vmbus_ops
 	- see if the vmbus can be merged with the other virtual busses
 	  in the kernel
 	- audit the network driver
-	  - use existing net_device_stats struct in network device
 	  - checking for carrier inside open is wrong, network device API
             confusion??
 	- audit the block driver
diff --git a/drivers/staging/hv/VersionInfo.h b/drivers/staging/hv/VersionInfo.h
deleted file mode 100644
index 35178f2c7..0000000
--- a/drivers/staging/hv/VersionInfo.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- *
- * Copyright (c) 2009, Microsoft Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place - Suite 330, Boston, MA 02111-1307 USA.
- *
- * Authors:
- *   Haiyang Zhang <haiyangz@microsoft.com>
- *   Hank Janssen  <hjanssen@microsoft.com>
- *
- */
-
-#ifndef __HV_VERSION_INFO
-#define __HV_VERSION_INFO
-
-/*
- * We use the same version numbering for all Hyper-V modules.
- *
- * Definition of versioning is as follows;
- *
- *	Major Number	Changes for these scenarios;
- *			1.	When a new version of Windows Hyper-V
- *				is released.
- *			2.	A Major change has occurred in the
- *				Linux IC's.
- *			(For example the merge for the first time
- *			into the kernel) Every time the Major Number
- *			changes, the Revision number is reset to 0.
- *	Minor Number	Changes when new functionality is added
- *			to the Linux IC's that is not a bug fix.
- *
- * 3.1 - Added completed hv_utils driver. Shutdown/Heartbeat/Timesync
- */
-#define HV_DRV_VERSION           "3.1"
-
-
-#endif
diff --git a/drivers/staging/hv/Vmbus.c b/drivers/staging/hv/Vmbus.c
deleted file mode 100644
index a9b031c4..0000000
--- a/drivers/staging/hv/Vmbus.c
+++ /dev/null
@@ -1,293 +0,0 @@
-/*
- * Copyright (c) 2009, Microsoft Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place - Suite 330, Boston, MA 02111-1307 USA.
- *
- * Authors:
- *   Haiyang Zhang <haiyangz@microsoft.com>
- *   Hank Janssen  <hjanssen@microsoft.com>
- *
- */
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include "osd.h"
-#include "logging.h"
-#include "VersionInfo.h"
-#include "VmbusPrivate.h"
-
-static const char *gDriverName = "vmbus";
-
-/*
- * Windows vmbus does not defined this.
- * We defined this to be consistent with other devices
- */
-/* {c5295816-f63a-4d5f-8d1a-4daf999ca185} */
-static const struct hv_guid gVmbusDeviceType = {
-	.data = {
-		0x16, 0x58, 0x29, 0xc5, 0x3a, 0xf6, 0x5f, 0x4d,
-		0x8d, 0x1a, 0x4d, 0xaf, 0x99, 0x9c, 0xa1, 0x85
-	}
-};
-
-/* {ac3760fc-9adf-40aa-9427-a70ed6de95c5} */
-static const struct hv_guid gVmbusDeviceId = {
-	.data = {
-		0xfc, 0x60, 0x37, 0xac, 0xdf, 0x9a, 0xaa, 0x40,
-		0x94, 0x27, 0xa7, 0x0e, 0xd6, 0xde, 0x95, 0xc5
-	}
-};
-
-static struct hv_driver *gDriver; /* vmbus driver object */
-static struct hv_device *gDevice; /* vmbus root device */
-
-/*
- * VmbusGetChannelOffers - Retrieve the channel offers from the parent partition
- */
-static void VmbusGetChannelOffers(void)
-{
-	VmbusChannelRequestOffers();
-}
-
-/*
- * VmbusGetChannelInterface - Get the channel interface
- */
-static void VmbusGetChannelInterface(struct vmbus_channel_interface *Interface)
-{
-	GetChannelInterface(Interface);
-}
-
-/*
- * VmbusGetChannelInfo - Get the device info for the specified device object
- */
-static void VmbusGetChannelInfo(struct hv_device *DeviceObject,
-				struct hv_device_info *DeviceInfo)
-{
-	GetChannelInfo(DeviceObject, DeviceInfo);
-}
-
-/*
- * VmbusCreateChildDevice - Creates the child device on the bus that represents the channel offer
- */
-struct hv_device *VmbusChildDeviceCreate(struct hv_guid *DeviceType,
-					 struct hv_guid *DeviceInstance,
-					 void *Context)
-{
-	struct vmbus_driver *vmbusDriver = (struct vmbus_driver *)gDriver;
-
-	return vmbusDriver->OnChildDeviceCreate(DeviceType, DeviceInstance,
-						Context);
-}
-
-/*
- * VmbusChildDeviceAdd - Registers the child device with the vmbus
- */
-int VmbusChildDeviceAdd(struct hv_device *ChildDevice)
-{
-	struct vmbus_driver *vmbusDriver = (struct vmbus_driver *)gDriver;
-
-	return vmbusDriver->OnChildDeviceAdd(gDevice, ChildDevice);
-}
-
-/*
- * VmbusChildDeviceRemove Unregisters the child device from the vmbus
- */
-void VmbusChildDeviceRemove(struct hv_device *ChildDevice)
-{
-	struct vmbus_driver *vmbusDriver = (struct vmbus_driver *)gDriver;
-
-	vmbusDriver->OnChildDeviceRemove(ChildDevice);
-}
-
-/*
- * VmbusOnDeviceAdd - Callback when the root bus device is added
- */
-static int VmbusOnDeviceAdd(struct hv_device *dev, void *AdditionalInfo)
-{
-	u32 *irqvector = AdditionalInfo;
-	int ret;
-
-	gDevice = dev;
-
-	memcpy(&gDevice->deviceType, &gVmbusDeviceType, sizeof(struct hv_guid));
-	memcpy(&gDevice->deviceInstance, &gVmbusDeviceId,
-	       sizeof(struct hv_guid));
-
-	/* strcpy(dev->name, "vmbus"); */
-	/* SynIC setup... */
-	on_each_cpu(HvSynicInit, (void *)irqvector, 1);
-
-	/* Connect to VMBus in the root partition */
-	ret = VmbusConnect();
-
-	/* VmbusSendEvent(device->localPortId+1); */
-	return ret;
-}
-
-/*
- * VmbusOnDeviceRemove - Callback when the root bus device is removed
- */
-static int VmbusOnDeviceRemove(struct hv_device *dev)
-{
-	int ret = 0;
-
-	VmbusChannelReleaseUnattachedChannels();
-	VmbusDisconnect();
-	on_each_cpu(HvSynicCleanup, NULL, 1);
-	return ret;
-}
-
-/*
- * VmbusOnCleanup - Perform any cleanup when the driver is removed
- */
-static void VmbusOnCleanup(struct hv_driver *drv)
-{
-	/* struct vmbus_driver *driver = (struct vmbus_driver *)drv; */
-
-	HvCleanup();
-}
-
-/*
- * VmbusOnMsgDPC - DPC routine to handle messages from the hypervisior
- */
-static void VmbusOnMsgDPC(struct hv_driver *drv)
-{
-	int cpu = smp_processor_id();
-	void *page_addr = gHvContext.synICMessagePage[cpu];
-	struct hv_message *msg = (struct hv_message *)page_addr +
-				  VMBUS_MESSAGE_SINT;
-	struct hv_message *copied;
-
-	while (1) {
-		if (msg->Header.MessageType == HvMessageTypeNone) {
-			/* no msg */
-			break;
-		} else {
-			copied = kmemdup(msg, sizeof(*copied), GFP_ATOMIC);
-			if (copied == NULL)
-				continue;
-
-			osd_schedule_callback(gVmbusConnection.WorkQueue,
-					      VmbusOnChannelMessage,
-					      (void *)copied);
-		}
-
-		msg->Header.MessageType = HvMessageTypeNone;
-
-		/*
-		 * Make sure the write to MessageType (ie set to
-		 * HvMessageTypeNone) happens before we read the
-		 * MessagePending and EOMing. Otherwise, the EOMing
-		 * will not deliver any more messages since there is
-		 * no empty slot
-		 */
-		mb();
-
-		if (msg->Header.MessageFlags.MessagePending) {
-			/*
-			 * This will cause message queue rescan to
-			 * possibly deliver another msg from the
-			 * hypervisor
-			 */
-			wrmsrl(HV_X64_MSR_EOM, 0);
-		}
-	}
-}
-
-/*
- * VmbusOnEventDPC - DPC routine to handle events from the hypervisior
- */
-static void VmbusOnEventDPC(struct hv_driver *drv)
-{
-	/* TODO: Process any events */
-	VmbusOnEvents();
-}
-
-/*
- * VmbusOnISR - ISR routine
- */
-static int VmbusOnISR(struct hv_driver *drv)
-{
-	int ret = 0;
-	int cpu = smp_processor_id();
-	void *page_addr;
-	struct hv_message *msg;
-	union hv_synic_event_flags *event;
-
-	page_addr = gHvContext.synICMessagePage[cpu];
-	msg = (struct hv_message *)page_addr + VMBUS_MESSAGE_SINT;
-
-	/* Check if there are actual msgs to be process */
-	if (msg->Header.MessageType != HvMessageTypeNone) {
-		DPRINT_DBG(VMBUS, "received msg type %d size %d",
-				msg->Header.MessageType,
-				msg->Header.PayloadSize);
-		ret |= 0x1;
-	}
-
-	/* TODO: Check if there are events to be process */
-	page_addr = gHvContext.synICEventPage[cpu];
-	event = (union hv_synic_event_flags *)page_addr + VMBUS_MESSAGE_SINT;
-
-	/* Since we are a child, we only need to check bit 0 */
-	if (sync_test_and_clear_bit(0, (unsigned long *) &event->Flags32[0])) {
-		DPRINT_DBG(VMBUS, "received event %d", event->Flags32[0]);
-		ret |= 0x2;
-	}
-
-	return ret;
-}
-
-/*
- * VmbusInitialize - Main entry point
- */
-int VmbusInitialize(struct hv_driver *drv)
-{
-	struct vmbus_driver *driver = (struct vmbus_driver *)drv;
-	int ret;
-
-	DPRINT_INFO(VMBUS, "+++++++ HV Driver version = %s +++++++",
-		    HV_DRV_VERSION);
-	DPRINT_INFO(VMBUS, "+++++++ Vmbus supported version = %d +++++++",
-			VMBUS_REVISION_NUMBER);
-	DPRINT_INFO(VMBUS, "+++++++ Vmbus using SINT %d +++++++",
-			VMBUS_MESSAGE_SINT);
-	DPRINT_DBG(VMBUS, "sizeof(VMBUS_CHANNEL_PACKET_PAGE_BUFFER)=%zd, "
-			"sizeof(VMBUS_CHANNEL_PACKET_MULITPAGE_BUFFER)=%zd",
-			sizeof(struct VMBUS_CHANNEL_PACKET_PAGE_BUFFER),
-			sizeof(struct VMBUS_CHANNEL_PACKET_MULITPAGE_BUFFER));
-
-	drv->name = gDriverName;
-	memcpy(&drv->deviceType, &gVmbusDeviceType, sizeof(struct hv_guid));
-
-	/* Setup dispatch table */
-	driver->Base.OnDeviceAdd	= VmbusOnDeviceAdd;
-	driver->Base.OnDeviceRemove	= VmbusOnDeviceRemove;
-	driver->Base.OnCleanup		= VmbusOnCleanup;
-	driver->OnIsr			= VmbusOnISR;
-	driver->OnMsgDpc		= VmbusOnMsgDPC;
-	driver->OnEventDpc		= VmbusOnEventDPC;
-	driver->GetChannelOffers	= VmbusGetChannelOffers;
-	driver->GetChannelInterface	= VmbusGetChannelInterface;
-	driver->GetChannelInfo		= VmbusGetChannelInfo;
-
-	/* Hypervisor initialization...setup hypercall page..etc */
-	ret = HvInit();
-	if (ret != 0)
-		DPRINT_ERR(VMBUS, "Unable to initialize the hypervisor - 0x%x",
-				ret);
-	gDriver = drv;
-
-	return ret;
-}
diff --git a/drivers/staging/hv/VmbusApi.h b/drivers/staging/hv/VmbusApi.h
deleted file mode 100644
index 4275be3..0000000
--- a/drivers/staging/hv/VmbusApi.h
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
- *
- * Copyright (c) 2009, Microsoft Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place - Suite 330, Boston, MA 02111-1307 USA.
- *
- * Authors:
- *   Haiyang Zhang <haiyangz@microsoft.com>
- *   Hank Janssen  <hjanssen@microsoft.com>
- *
- */
-
-
-#ifndef _VMBUS_API_H_
-#define _VMBUS_API_H_
-
-#define MAX_PAGE_BUFFER_COUNT				16
-#define MAX_MULTIPAGE_BUFFER_COUNT			32 /* 128K */
-
-#pragma pack(push, 1)
-
-/* Single-page buffer */
-struct hv_page_buffer {
-	u32 Length;
-	u32 Offset;
-	u64 Pfn;
-};
-
-/* Multiple-page buffer */
-struct hv_multipage_buffer {
-	/* Length and Offset determines the # of pfns in the array */
-	u32 Length;
-	u32 Offset;
-	u64 PfnArray[MAX_MULTIPAGE_BUFFER_COUNT];
-};
-
-/* 0x18 includes the proprietary packet header */
-#define MAX_PAGE_BUFFER_PACKET		(0x18 +			\
-					(sizeof(struct hv_page_buffer) * \
-					 MAX_PAGE_BUFFER_COUNT))
-#define MAX_MULTIPAGE_BUFFER_PACKET	(0x18 +			\
-					 sizeof(struct hv_multipage_buffer))
-
-
-#pragma pack(pop)
-
-struct hv_driver;
-struct hv_device;
-
-struct hv_dev_port_info {
-	u32 InterruptMask;
-	u32 ReadIndex;
-	u32 WriteIndex;
-	u32 BytesAvailToRead;
-	u32 BytesAvailToWrite;
-};
-
-struct hv_device_info {
-	u32 ChannelId;
-	u32 ChannelState;
-	struct hv_guid ChannelType;
-	struct hv_guid ChannelInstance;
-
-	u32 MonitorId;
-	u32 ServerMonitorPending;
-	u32 ServerMonitorLatency;
-	u32 ServerMonitorConnectionId;
-	u32 ClientMonitorPending;
-	u32 ClientMonitorLatency;
-	u32 ClientMonitorConnectionId;
-
-	struct hv_dev_port_info Inbound;
-	struct hv_dev_port_info Outbound;
-};
-
-/**
- * struct vmbus_channel_interface - Contains member functions for vmbus channel
- * @Open:      Open the channel
- * @Close:     Close the channel
- * @SendPacket:        Send a packet over the channel
- * @SendPacketPageBuffer:      Send a single page buffer over the channel
- * @SendPacketMultiPageBuffer: Send a multiple page buffers
- * @RecvPacket:        Receive packet
- * @RecvPacketRaw:     Receive Raw packet
- * @EstablishGpadl:    Set up GPADL for ringbuffer
- * @TeardownGpadl:     Teardown GPADL for ringbuffer
- * @GetInfo:   Get info about the channel
- *
- * This structure contains function pointer to control vmbus channel
- * behavior. None of these functions is externally callable, but they
- * are used for normal vmbus channel internal behavior.
- * Only used by Hyper-V drivers.
- */
-struct vmbus_channel_interface {
-	int (*Open)(struct hv_device *Device, u32 SendBufferSize,
-		    u32 RecvRingBufferSize, void *UserData, u32 UserDataLen,
-		    void (*ChannelCallback)(void *context),
-		    void *Context);
-	void (*Close)(struct hv_device *device);
-	int (*SendPacket)(struct hv_device *Device, const void *Buffer,
-			  u32 BufferLen, u64 RequestId, u32 Type, u32 Flags);
-	int (*SendPacketPageBuffer)(struct hv_device *dev,
-				    struct hv_page_buffer PageBuffers[],
-				    u32 PageCount, void *Buffer, u32 BufferLen,
-				    u64 RequestId);
-	int (*SendPacketMultiPageBuffer)(struct hv_device *device,
-					 struct hv_multipage_buffer *mpb,
-					 void *Buffer,
-					 u32 BufferLen,
-					 u64 RequestId);
-	int (*RecvPacket)(struct hv_device *dev, void *buf, u32 buflen,
-			  u32 *BufferActualLen, u64 *RequestId);
-	int (*RecvPacketRaw)(struct hv_device *dev, void *buf, u32 buflen,
-			     u32 *BufferActualLen, u64 *RequestId);
-	int (*EstablishGpadl)(struct hv_device *dev, void *buf, u32 buflen,
-			      u32 *GpadlHandle);
-	int (*TeardownGpadl)(struct hv_device *device, u32 GpadlHandle);
-	void (*GetInfo)(struct hv_device *dev, struct hv_device_info *devinfo);
-};
-
-/* Base driver object */
-struct hv_driver {
-	const char *name;
-
-	/* the device type supported by this driver */
-	struct hv_guid deviceType;
-
-	int (*OnDeviceAdd)(struct hv_device *device, void *data);
-	int (*OnDeviceRemove)(struct hv_device *device);
-	void (*OnCleanup)(struct hv_driver *driver);
-
-	struct vmbus_channel_interface VmbusChannelInterface;
-};
-
-/* Base device object */
-struct hv_device {
-	/* the driver for this device */
-	struct hv_driver *Driver;
-
-	char name[64];
-
-	/* the device type id of this device */
-	struct hv_guid deviceType;
-
-	/* the device instance id of this device */
-	struct hv_guid deviceInstance;
-
-	void *context;
-
-	/* Device extension; */
-	void *Extension;
-};
-
-/* Vmbus driver object */
-struct vmbus_driver {
-	/* !! Must be the 1st field !! */
-	/* FIXME if ^, then someone is doing somthing stupid */
-	struct hv_driver Base;
-
-	/* Set by the caller */
-	struct hv_device * (*OnChildDeviceCreate)(struct hv_guid *DeviceType,
-						struct hv_guid *DeviceInstance,
-						void *Context);
-	void (*OnChildDeviceDestroy)(struct hv_device *device);
-	int (*OnChildDeviceAdd)(struct hv_device *RootDevice,
-				struct hv_device *ChildDevice);
-	void (*OnChildDeviceRemove)(struct hv_device *device);
-
-	/* Set by the callee */
-	int (*OnIsr)(struct hv_driver *driver);
-	void (*OnMsgDpc)(struct hv_driver *driver);
-	void (*OnEventDpc)(struct hv_driver *driver);
-	void (*GetChannelOffers)(void);
-
-	void (*GetChannelInterface)(struct vmbus_channel_interface *i);
-	void (*GetChannelInfo)(struct hv_device *dev,
-			       struct hv_device_info *devinfo);
-};
-
-int VmbusInitialize(struct hv_driver *drv);
-
-#endif /* _VMBUS_API_H_ */
diff --git a/drivers/staging/hv/VmbusChannelInterface.h b/drivers/staging/hv/VmbusChannelInterface.h
deleted file mode 100644
index 2674282..0000000
--- a/drivers/staging/hv/VmbusChannelInterface.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- *
- * Copyright (c) 2009, Microsoft Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place - Suite 330, Boston, MA 02111-1307 USA.
- *
- * Authors:
- *   Haiyang Zhang <haiyangz@microsoft.com>
- *   Hank Janssen  <hjanssen@microsoft.com>
- *
- */
-
-#ifndef __VMBUSCHANNELINTERFACE_H
-#define __VMBUSCHANNELINTERFACE_H
-
-/*
- * A revision number of vmbus that is used for ensuring both ends on a
- * partition are using compatible versions.
- */
-#define VMBUS_REVISION_NUMBER		13
-
-/* Make maximum size of pipe payload of 16K */
-#define MAX_PIPE_DATA_PAYLOAD		(sizeof(u8) * 16384)
-
-/* Define PipeMode values. */
-#define VMBUS_PIPE_TYPE_BYTE		0x00000000
-#define VMBUS_PIPE_TYPE_MESSAGE		0x00000004
-
-/* The size of the user defined data buffer for non-pipe offers. */
-#define MAX_USER_DEFINED_BYTES		120
-
-/* The size of the user defined data buffer for pipe offers. */
-#define MAX_PIPE_USER_DEFINED_BYTES	116
-
-/*
- * At the center of the Channel Management library is the Channel Offer. This
- * struct contains the fundamental information about an offer.
- */
-struct vmbus_channel_offer {
-	struct hv_guid InterfaceType;
-	struct hv_guid InterfaceInstance;
-	u64 InterruptLatencyIn100nsUnits;
-	u32 InterfaceRevision;
-	u32 ServerContextAreaSize;	/* in bytes */
-	u16 ChannelFlags;
-	u16 MmioMegabytes;		/* in bytes * 1024 * 1024 */
-
-	union {
-		/* Non-pipes: The user has MAX_USER_DEFINED_BYTES bytes. */
-		struct {
-			unsigned char UserDefined[MAX_USER_DEFINED_BYTES];
-		} Standard;
-
-		/*
-		 * Pipes:
-		 * The following sructure is an integrated pipe protocol, which
-		 * is implemented on top of standard user-defined data. Pipe
-		 * clients have MAX_PIPE_USER_DEFINED_BYTES left for their own
-		 * use.
-		 */
-		struct {
-			u32  PipeMode;
-			unsigned char UserDefined[MAX_PIPE_USER_DEFINED_BYTES];
-		} Pipe;
-	} u;
-	u32 Padding;
-} __attribute__((packed));
-
-/* Server Flags */
-#define VMBUS_CHANNEL_ENUMERATE_DEVICE_INTERFACE	1
-#define VMBUS_CHANNEL_SERVER_SUPPORTS_TRANSFER_PAGES	2
-#define VMBUS_CHANNEL_SERVER_SUPPORTS_GPADLS		4
-#define VMBUS_CHANNEL_NAMED_PIPE_MODE			0x10
-#define VMBUS_CHANNEL_LOOPBACK_OFFER			0x100
-#define VMBUS_CHANNEL_PARENT_OFFER			0x200
-#define VMBUS_CHANNEL_REQUEST_MONITORED_NOTIFICATION	0x400
-
-#endif
diff --git a/drivers/staging/hv/VmbusPacketFormat.h b/drivers/staging/hv/VmbusPacketFormat.h
deleted file mode 100644
index f9f6b4b..0000000
--- a/drivers/staging/hv/VmbusPacketFormat.h
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- *
- * Copyright (c) 2009, Microsoft Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place - Suite 330, Boston, MA 02111-1307 USA.
- *
- * Authors:
- *   Haiyang Zhang <haiyangz@microsoft.com>
- *   Hank Janssen  <hjanssen@microsoft.com>
- *
- */
-
-#ifndef _VMBUSPACKETFORMAT_H_
-#define _VMBUSPACKETFORMAT_H_
-
-struct vmpacket_descriptor {
-	u16 Type;
-	u16 DataOffset8;
-	u16 Length8;
-	u16 Flags;
-	u64 TransactionId;
-} __attribute__((packed));
-
-struct vmpacket_header {
-	u32 PreviousPacketStartOffset;
-	struct vmpacket_descriptor Descriptor;
-} __attribute__((packed));
-
-struct vmtransfer_page_range {
-	u32 ByteCount;
-	u32 ByteOffset;
-} __attribute__((packed));
-
-struct vmtransfer_page_packet_header {
-	struct vmpacket_descriptor d;
-	u16 TransferPageSetId;
-	bool SenderOwnsSet;
-	u8 Reserved;
-	u32 RangeCount;
-	struct vmtransfer_page_range Ranges[1];
-} __attribute__((packed));
-
-struct vmgpadl_packet_header {
-	struct vmpacket_descriptor d;
-	u32 Gpadl;
-	u32 Reserved;
-} __attribute__((packed));
-
-struct vmadd_remove_transfer_page_set {
-	struct vmpacket_descriptor d;
-	u32 Gpadl;
-	u16 TransferPageSetId;
-	u16 Reserved;
-} __attribute__((packed));
-
-/*
- * This structure defines a range in guest physical space that can be made to
- * look virtually contiguous.
- */
-struct gpa_range {
-	u32 ByteCount;
-	u32 ByteOffset;
-	u64 PfnArray[0];
-};
-
-/*
- * This is the format for an Establish Gpadl packet, which contains a handle by
- * which this GPADL will be known and a set of GPA ranges associated with it.
- * This can be converted to a MDL by the guest OS.  If there are multiple GPA
- * ranges, then the resulting MDL will be "chained," representing multiple VA
- * ranges.
- */
-struct vmestablish_gpadl {
-	struct vmpacket_descriptor d;
-	u32 Gpadl;
-	u32 RangeCount;
-	struct gpa_range Range[1];
-} __attribute__((packed));
-
-/*
- * This is the format for a Teardown Gpadl packet, which indicates that the
- * GPADL handle in the Establish Gpadl packet will never be referenced again.
- */
-struct vmteardown_gpadl {
-	struct vmpacket_descriptor d;
-	u32 Gpadl;
-	u32 Reserved;	/* for alignment to a 8-byte boundary */
-} __attribute__((packed));
-
-/*
- * This is the format for a GPA-Direct packet, which contains a set of GPA
- * ranges, in addition to commands and/or data.
- */
-struct vmdata_gpa_direct {
-	struct vmpacket_descriptor d;
-	u32 Reserved;
-	u32 RangeCount;
-	struct gpa_range Range[1];
-} __attribute__((packed));
-
-/* This is the format for a Additional Data Packet. */
-struct vmadditional_data {
-	struct vmpacket_descriptor d;
-	u64 TotalBytes;
-	u32 ByteOffset;
-	u32 ByteCount;
-	unsigned char Data[1];
-} __attribute__((packed));
-
-union vmpacket_largest_possible_header {
-	struct vmpacket_descriptor SimpleHeader;
-	struct vmtransfer_page_packet_header TransferPageHeader;
-	struct vmgpadl_packet_header GpadlHeader;
-	struct vmadd_remove_transfer_page_set AddRemoveTransferPageHeader;
-	struct vmestablish_gpadl EstablishGpadlHeader;
-	struct vmteardown_gpadl TeardownGpadlHeader;
-	struct vmdata_gpa_direct DataGpaDirectHeader;
-};
-
-#define VMPACKET_DATA_START_ADDRESS(__packet)	\
-	(void *)(((unsigned char *)__packet) +	\
-	 ((struct vmpacket_descriptor)__packet)->DataOffset8 * 8)
-
-#define VMPACKET_DATA_LENGTH(__packet)		\
-	((((struct vmpacket_descriptor)__packet)->Length8 -	\
-	  ((struct vmpacket_descriptor)__packet)->DataOffset8) * 8)
-
-#define VMPACKET_TRANSFER_MODE(__packet)	\
-	(((struct IMPACT)__packet)->Type)
-
-enum vmbus_packet_type {
-	VmbusPacketTypeInvalid				= 0x0,
-	VmbusPacketTypeSynch				= 0x1,
-	VmbusPacketTypeAddTransferPageSet		= 0x2,
-	VmbusPacketTypeRemoveTransferPageSet		= 0x3,
-	VmbusPacketTypeEstablishGpadl			= 0x4,
-	VmbusPacketTypeTearDownGpadl			= 0x5,
-	VmbusPacketTypeDataInBand			= 0x6,
-	VmbusPacketTypeDataUsingTransferPages		= 0x7,
-	VmbusPacketTypeDataUsingGpadl			= 0x8,
-	VmbusPacketTypeDataUsingGpaDirect		= 0x9,
-	VmbusPacketTypeCancelRequest			= 0xa,
-	VmbusPacketTypeCompletion			= 0xb,
-	VmbusPacketTypeDataUsingAdditionalPackets	= 0xc,
-	VmbusPacketTypeAdditionalData			= 0xd
-};
-
-#define VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED	1
-
-#endif
diff --git a/drivers/staging/hv/VmbusPrivate.h b/drivers/staging/hv/VmbusPrivate.h
deleted file mode 100644
index 5a37cce..0000000
--- a/drivers/staging/hv/VmbusPrivate.h
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- *
- * Copyright (c) 2009, Microsoft Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place - Suite 330, Boston, MA 02111-1307 USA.
- *
- * Authors:
- *   Haiyang Zhang <haiyangz@microsoft.com>
- *   Hank Janssen  <hjanssen@microsoft.com>
- *
- */
-
-
-#ifndef _VMBUS_PRIVATE_H_
-#define _VMBUS_PRIVATE_H_
-
-#include "Hv.h"
-#include "VmbusApi.h"
-#include "Channel.h"
-#include "ChannelMgmt.h"
-#include "ChannelInterface.h"
-#include "RingBuffer.h"
-#include <linux/list.h>
-#include <asm/sync_bitops.h>
-
-
-/*
- * Maximum channels is determined by the size of the interrupt page
- * which is PAGE_SIZE. 1/2 of PAGE_SIZE is for send endpoint interrupt
- * and the other is receive endpoint interrupt
- */
-#define MAX_NUM_CHANNELS	((PAGE_SIZE >> 1) << 3)	/* 16348 channels */
-
-/* The value here must be in multiple of 32 */
-/* TODO: Need to make this configurable */
-#define MAX_NUM_CHANNELS_SUPPORTED	256
-
-
-enum VMBUS_CONNECT_STATE {
-	Disconnected,
-	Connecting,
-	Connected,
-	Disconnecting
-};
-
-#define MAX_SIZE_CHANNEL_MESSAGE	HV_MESSAGE_PAYLOAD_BYTE_COUNT
-
-struct VMBUS_CONNECTION {
-	enum VMBUS_CONNECT_STATE ConnectState;
-
-	atomic_t NextGpadlHandle;
-
-	/*
-	 * Represents channel interrupts. Each bit position represents a
-	 * channel.  When a channel sends an interrupt via VMBUS, it finds its
-	 * bit in the sendInterruptPage, set it and calls Hv to generate a port
-	 * event. The other end receives the port event and parse the
-	 * recvInterruptPage to see which bit is set
-	 */
-	void *InterruptPage;
-	void *SendInterruptPage;
-	void *RecvInterruptPage;
-
-	/*
-	 * 2 pages - 1st page for parent->child notification and 2nd
-	 * is child->parent notification
-	 */
-	void *MonitorPages;
-	struct list_head ChannelMsgList;
-	spinlock_t channelmsg_lock;
-
-	/* List of channels */
-	struct list_head ChannelList;
-	spinlock_t channel_lock;
-
-	struct workqueue_struct *WorkQueue;
-};
-
-
-struct VMBUS_MSGINFO {
-	/* Bookkeeping stuff */
-	struct list_head MsgListEntry;
-
-	/* Synchronize the request/response if needed */
-	struct osd_waitevent *WaitEvent;
-
-	/* The message itself */
-	unsigned char Msg[0];
-};
-
-
-extern struct VMBUS_CONNECTION gVmbusConnection;
-
-/* General vmbus interface */
-
-struct hv_device *VmbusChildDeviceCreate(struct hv_guid *deviceType,
-					 struct hv_guid *deviceInstance,
-					 void *context);
-
-int VmbusChildDeviceAdd(struct hv_device *Device);
-
-void VmbusChildDeviceRemove(struct hv_device *Device);
-
-/* static void */
-/* VmbusChildDeviceDestroy( */
-/* struct hv_device *); */
-
-struct vmbus_channel *GetChannelFromRelId(u32 relId);
-
-
-/* Connection interface */
-
-int VmbusConnect(void);
-
-int VmbusDisconnect(void);
-
-int VmbusPostMessage(void *buffer, size_t bufSize);
-
-int VmbusSetEvent(u32 childRelId);
-
-void VmbusOnEvents(void);
-
-
-#endif /* _VMBUS_PRIVATE_H_ */
diff --git a/drivers/staging/hv/blkvsc_drv.c b/drivers/staging/hv/blkvsc_drv.c
index ddc553c..3612574 100644
--- a/drivers/staging/hv/blkvsc_drv.c
+++ b/drivers/staging/hv/blkvsc_drv.c
@@ -17,6 +17,7 @@
  * Authors:
  *   Haiyang Zhang <haiyangz@microsoft.com>
  *   Hank Janssen  <hjanssen@microsoft.com>
+ *   K. Y. Srinivasan <kys@microsoft.com>
  */
 #include <linux/init.h>
 #include <linux/module.h>
@@ -30,11 +31,9 @@
 #include <scsi/scsi_cmnd.h>
 #include <scsi/scsi_eh.h>
 #include <scsi/scsi_dbg.h>
-#include "osd.h"
-#include "logging.h"
-#include "VersionInfo.h"
-#include "vmbus.h"
-#include "StorVscApi.h"
+
+#include "hyperv.h"
+#include "hyperv_storage.h"
 
 
 #define BLKVSC_MINORS	64
@@ -45,6 +44,12 @@
 	DVD_TYPE,
 };
 
+enum blkvsc_op_type {
+	DO_INQUIRY,
+	DO_CAPACITY,
+	DO_FLUSH,
+};
+
 /*
  * This request ties the struct request and struct
  * blkvsc_request/hv_storvsc_request together A struct request may be
@@ -71,9 +76,6 @@
 	/* The group this request is part of. Maybe null */
 	struct blkvsc_request_group *group;
 
-	wait_queue_head_t wevent;
-	int cond;
-
 	int write;
 	sector_t sector_start;
 	unsigned long sector_count;
@@ -83,18 +85,12 @@
 	unsigned char cmnd[MAX_COMMAND_SIZE];
 
 	struct hv_storvsc_request request;
-	/*
-	 * !!!DO NOT ADD ANYTHING BELOW HERE!!! Otherwise, memory can overlap,
-	 * because - The extension buffer falls right here and is pointed to by
-	 * request.Extension;
-	 * Which sounds like a horrible idea, who designed this?
-	 */
 };
 
 /* Per device structure */
 struct block_device_context {
 	/* point back to our device context */
-	struct vm_device *device_ctx;
+	struct hv_device *device_ctx;
 	struct kmem_cache *request_pool;
 	spinlock_t lock;
 	struct gendisk *gd;
@@ -105,7 +101,6 @@
 	unsigned int device_id_len;
 	int num_outstanding_reqs;
 	int shutting_down;
-	int media_not_present;
 	unsigned int sector_size;
 	sector_t capacity;
 	unsigned int port;
@@ -114,524 +109,314 @@
 	int users;
 };
 
-/* Per driver */
-struct blkvsc_driver_context {
-	/* !! These must be the first 2 fields !! */
-	/* FIXME this is a bug! */
-	struct driver_context drv_ctx;
-	struct storvsc_driver_object drv_obj;
+static const char *drv_name = "blkvsc";
+
+/* {32412632-86cb-44a2-9b5c-50d1417354f5} */
+static const struct hv_guid dev_type = {
+	.data = {
+		0x32, 0x26, 0x41, 0x32, 0xcb, 0x86, 0xa2, 0x44,
+		0x9b, 0x5c, 0x50, 0xd1, 0x41, 0x73, 0x54, 0xf5
+	}
 };
 
-/* Static decl */
-static int blkvsc_probe(struct device *dev);
-static int blkvsc_remove(struct device *device);
-static void blkvsc_shutdown(struct device *device);
-
-static int blkvsc_open(struct block_device *bdev,  fmode_t mode);
-static int blkvsc_release(struct gendisk *disk, fmode_t mode);
-static int blkvsc_media_changed(struct gendisk *gd);
-static int blkvsc_revalidate_disk(struct gendisk *gd);
-static int blkvsc_getgeo(struct block_device *bd, struct hd_geometry *hg);
-static int blkvsc_ioctl(struct block_device *bd, fmode_t mode,
-			unsigned cmd, unsigned long argument);
-static void blkvsc_request(struct request_queue *queue);
+/*
+ * There is a circular dependency involving blkvsc_request_completion()
+ * and blkvsc_do_request().
+ */
 static void blkvsc_request_completion(struct hv_storvsc_request *request);
-static int blkvsc_do_request(struct block_device_context *blkdev,
-			     struct request *req);
-static int blkvsc_submit_request(struct blkvsc_request *blkvsc_req,
-		void (*request_completion)(struct hv_storvsc_request *));
-static void blkvsc_init_rw(struct blkvsc_request *blkvsc_req);
-static void blkvsc_cmd_completion(struct hv_storvsc_request *request);
-static int blkvsc_do_inquiry(struct block_device_context *blkdev);
-static int blkvsc_do_read_capacity(struct block_device_context *blkdev);
-static int blkvsc_do_read_capacity16(struct block_device_context *blkdev);
-static int blkvsc_do_flush(struct block_device_context *blkdev);
-static int blkvsc_cancel_pending_reqs(struct block_device_context *blkdev);
-static int blkvsc_do_pending_reqs(struct block_device_context *blkdev);
 
 static int blkvsc_ringbuffer_size = BLKVSC_RING_BUFFER_SIZE;
+
 module_param(blkvsc_ringbuffer_size, int, S_IRUGO);
 MODULE_PARM_DESC(ring_size, "Ring buffer size (in bytes)");
 
-/* The one and only one */
-static struct blkvsc_driver_context g_blkvsc_drv;
-
-static const struct block_device_operations block_ops = {
-	.owner = THIS_MODULE,
-	.open = blkvsc_open,
-	.release = blkvsc_release,
-	.media_changed = blkvsc_media_changed,
-	.revalidate_disk = blkvsc_revalidate_disk,
-	.getgeo = blkvsc_getgeo,
-	.ioctl  = blkvsc_ioctl,
-};
-
 /*
- * blkvsc_drv_init -  BlkVsc driver initialization.
+ * There is a circular dependency involving blkvsc_probe()
+ * and block_ops.
  */
-static int blkvsc_drv_init(int (*drv_init)(struct hv_driver *drv))
+static int blkvsc_probe(struct hv_device *dev);
+
+static int blkvsc_device_add(struct hv_device *device,
+				void *additional_info)
 {
-	struct storvsc_driver_object *storvsc_drv_obj = &g_blkvsc_drv.drv_obj;
-	struct driver_context *drv_ctx = &g_blkvsc_drv.drv_ctx;
-	int ret;
-
-	vmbus_get_interface(&storvsc_drv_obj->Base.VmbusChannelInterface);
-
-	storvsc_drv_obj->RingBufferSize = blkvsc_ringbuffer_size;
-
-	/* Callback to client driver to complete the initialization */
-	drv_init(&storvsc_drv_obj->Base);
-
-	drv_ctx->driver.name = storvsc_drv_obj->Base.name;
-	memcpy(&drv_ctx->class_id, &storvsc_drv_obj->Base.deviceType,
-	       sizeof(struct hv_guid));
-
-	drv_ctx->probe = blkvsc_probe;
-	drv_ctx->remove = blkvsc_remove;
-	drv_ctx->shutdown = blkvsc_shutdown;
-
-	/* The driver belongs to vmbus */
-	ret = vmbus_child_driver_register(drv_ctx);
-
-	return ret;
-}
-
-static int blkvsc_drv_exit_cb(struct device *dev, void *data)
-{
-	struct device **curr = (struct device **)data;
-	*curr = dev;
-	return 1; /* stop iterating */
-}
-
-static void blkvsc_drv_exit(void)
-{
-	struct storvsc_driver_object *storvsc_drv_obj = &g_blkvsc_drv.drv_obj;
-	struct driver_context *drv_ctx = &g_blkvsc_drv.drv_ctx;
-	struct device *current_dev;
-	int ret;
-
-	while (1) {
-		current_dev = NULL;
-
-		/* Get the device */
-		ret = driver_for_each_device(&drv_ctx->driver, NULL,
-					     (void *) &current_dev,
-					     blkvsc_drv_exit_cb);
-
-		if (ret)
-			DPRINT_WARN(BLKVSC_DRV,
-				    "driver_for_each_device returned %d", ret);
-
-
-		if (current_dev == NULL)
-			break;
-
-		/* Initiate removal from the top-down */
-		device_unregister(current_dev);
-	}
-
-	if (storvsc_drv_obj->Base.OnCleanup)
-		storvsc_drv_obj->Base.OnCleanup(&storvsc_drv_obj->Base);
-
-	vmbus_child_driver_unregister(drv_ctx);
-
-	return;
-}
-
-/*
- * blkvsc_probe - Add a new device for this driver
- */
-static int blkvsc_probe(struct device *device)
-{
-	struct driver_context *driver_ctx =
-				driver_to_driver_context(device->driver);
-	struct blkvsc_driver_context *blkvsc_drv_ctx =
-				(struct blkvsc_driver_context *)driver_ctx;
-	struct storvsc_driver_object *storvsc_drv_obj =
-				&blkvsc_drv_ctx->drv_obj;
-	struct vm_device *device_ctx = device_to_vm_device(device);
-	struct hv_device *device_obj = &device_ctx->device_obj;
-
-	struct block_device_context *blkdev = NULL;
-	struct storvsc_device_info device_info;
-	int major = 0;
-	int devnum = 0;
+	struct storvsc_device_info *device_info;
 	int ret = 0;
-	static int ide0_registered;
-	static int ide1_registered;
 
-	DPRINT_DBG(BLKVSC_DRV, "blkvsc_probe - enter");
+	device_info = (struct storvsc_device_info *)additional_info;
 
-	if (!storvsc_drv_obj->Base.OnDeviceAdd) {
-		DPRINT_ERR(BLKVSC_DRV, "OnDeviceAdd() not set");
-		ret = -1;
-		goto Cleanup;
-	}
+	device_info->ring_buffer_size = blkvsc_ringbuffer_size;
 
-	blkdev = kzalloc(sizeof(struct block_device_context), GFP_KERNEL);
-	if (!blkdev) {
-		ret = -ENOMEM;
-		goto Cleanup;
-	}
-
-	INIT_LIST_HEAD(&blkdev->pending_list);
-
-	/* Initialize what we can here */
-	spin_lock_init(&blkdev->lock);
-
-	/* ASSERT(sizeof(struct blkvsc_request_group) <= */
-	/* 	sizeof(struct blkvsc_request)); */
-
-	blkdev->request_pool = kmem_cache_create(dev_name(&device_ctx->device),
-					sizeof(struct blkvsc_request) +
-					storvsc_drv_obj->RequestExtSize, 0,
-					SLAB_HWCACHE_ALIGN, NULL);
-	if (!blkdev->request_pool) {
-		ret = -ENOMEM;
-		goto Cleanup;
-	}
-
-
-	/* Call to the vsc driver to add the device */
-	ret = storvsc_drv_obj->Base.OnDeviceAdd(device_obj, &device_info);
-	if (ret != 0) {
-		DPRINT_ERR(BLKVSC_DRV, "unable to add blkvsc device");
-		goto Cleanup;
-	}
-
-	blkdev->device_ctx = device_ctx;
-	/* this identified the device 0 or 1 */
-	blkdev->target = device_info.TargetId;
-	/* this identified the ide ctrl 0 or 1 */
-	blkdev->path = device_info.PathId;
-
-	dev_set_drvdata(device, blkdev);
-
-	/* Calculate the major and device num */
-	if (blkdev->path == 0) {
-		major = IDE0_MAJOR;
-		devnum = blkdev->path + blkdev->target;		/* 0 or 1 */
-
-		if (!ide0_registered) {
-			ret = register_blkdev(major, "ide");
-			if (ret != 0) {
-				DPRINT_ERR(BLKVSC_DRV,
-					   "register_blkdev() failed! ret %d",
-					   ret);
-				goto Remove;
-			}
-
-			ide0_registered = 1;
-		}
-	} else if (blkdev->path == 1) {
-		major = IDE1_MAJOR;
-		devnum = blkdev->path + blkdev->target + 1; /* 2 or 3 */
-
-		if (!ide1_registered) {
-			ret = register_blkdev(major, "ide");
-			if (ret != 0) {
-				DPRINT_ERR(BLKVSC_DRV,
-					   "register_blkdev() failed! ret %d",
-					   ret);
-				goto Remove;
-			}
-
-			ide1_registered = 1;
-		}
-	} else {
-		DPRINT_ERR(BLKVSC_DRV, "invalid pathid");
-		ret = -1;
-		goto Cleanup;
-	}
-
-	DPRINT_INFO(BLKVSC_DRV, "blkvsc registered for major %d!!", major);
-
-	blkdev->gd = alloc_disk(BLKVSC_MINORS);
-	if (!blkdev->gd) {
-		DPRINT_ERR(BLKVSC_DRV, "register_blkdev() failed! ret %d", ret);
-		ret = -1;
-		goto Cleanup;
-	}
-
-	blkdev->gd->queue = blk_init_queue(blkvsc_request, &blkdev->lock);
-
-	blk_queue_max_segment_size(blkdev->gd->queue, PAGE_SIZE);
-	blk_queue_max_segments(blkdev->gd->queue, MAX_MULTIPAGE_BUFFER_COUNT);
-	blk_queue_segment_boundary(blkdev->gd->queue, PAGE_SIZE-1);
-	blk_queue_bounce_limit(blkdev->gd->queue, BLK_BOUNCE_ANY);
-	blk_queue_dma_alignment(blkdev->gd->queue, 511);
-
-	blkdev->gd->major = major;
-	if (devnum == 1 || devnum == 3)
-		blkdev->gd->first_minor = BLKVSC_MINORS;
-	else
-		blkdev->gd->first_minor = 0;
-	blkdev->gd->fops = &block_ops;
-	blkdev->gd->private_data = blkdev;
-	blkdev->gd->driverfs_dev = &(blkdev->device_ctx->device);
-	sprintf(blkdev->gd->disk_name, "hd%c", 'a' + devnum);
-
-	blkvsc_do_inquiry(blkdev);
-	if (blkdev->device_type == DVD_TYPE) {
-		set_disk_ro(blkdev->gd, 1);
-		blkdev->gd->flags |= GENHD_FL_REMOVABLE;
-		blkvsc_do_read_capacity(blkdev);
-	} else {
-		blkvsc_do_read_capacity16(blkdev);
-	}
-
-	set_capacity(blkdev->gd, blkdev->capacity * (blkdev->sector_size/512));
-	blk_queue_logical_block_size(blkdev->gd->queue, blkdev->sector_size);
-	/* go! */
-	add_disk(blkdev->gd);
-
-	DPRINT_INFO(BLKVSC_DRV, "%s added!! capacity %lu sector_size %d",
-		    blkdev->gd->disk_name, (unsigned long)blkdev->capacity,
-		    blkdev->sector_size);
-
-	return ret;
-
-Remove:
-	storvsc_drv_obj->Base.OnDeviceRemove(device_obj);
-
-Cleanup:
-	if (blkdev) {
-		if (blkdev->request_pool) {
-			kmem_cache_destroy(blkdev->request_pool);
-			blkdev->request_pool = NULL;
-		}
-		kfree(blkdev);
-		blkdev = NULL;
-	}
-
-	return ret;
-}
-
-static void blkvsc_shutdown(struct device *device)
-{
-	struct block_device_context *blkdev = dev_get_drvdata(device);
-	unsigned long flags;
-
-	if (!blkdev)
-		return;
-
-	DPRINT_DBG(BLKVSC_DRV, "blkvsc_shutdown - users %d disk %s\n",
-		   blkdev->users, blkdev->gd->disk_name);
-
-	spin_lock_irqsave(&blkdev->lock, flags);
-
-	blkdev->shutting_down = 1;
-
-	blk_stop_queue(blkdev->gd->queue);
-
-	spin_unlock_irqrestore(&blkdev->lock, flags);
-
-	while (blkdev->num_outstanding_reqs) {
-		DPRINT_INFO(STORVSC, "waiting for %d requests to complete...",
-			    blkdev->num_outstanding_reqs);
-		udelay(100);
-	}
-
-	blkvsc_do_flush(blkdev);
-
-	spin_lock_irqsave(&blkdev->lock, flags);
-
-	blkvsc_cancel_pending_reqs(blkdev);
-
-	spin_unlock_irqrestore(&blkdev->lock, flags);
-}
-
-static int blkvsc_do_flush(struct block_device_context *blkdev)
-{
-	struct blkvsc_request *blkvsc_req;
-
-	DPRINT_DBG(BLKVSC_DRV, "blkvsc_do_flush()\n");
-
-	if (blkdev->device_type != HARDDISK_TYPE)
-		return 0;
-
-	blkvsc_req = kmem_cache_alloc(blkdev->request_pool, GFP_KERNEL);
-	if (!blkvsc_req)
-		return -ENOMEM;
-
-	memset(blkvsc_req, 0, sizeof(struct blkvsc_request));
-	init_waitqueue_head(&blkvsc_req->wevent);
-	blkvsc_req->dev = blkdev;
-	blkvsc_req->req = NULL;
-	blkvsc_req->write = 0;
-
-	blkvsc_req->request.DataBuffer.PfnArray[0] = 0;
-	blkvsc_req->request.DataBuffer.Offset = 0;
-	blkvsc_req->request.DataBuffer.Length = 0;
-
-	blkvsc_req->cmnd[0] = SYNCHRONIZE_CACHE;
-	blkvsc_req->cmd_len = 10;
+	ret = storvsc_dev_add(device, additional_info);
+	if (ret != 0)
+		return ret;
 
 	/*
-	 * Set this here since the completion routine may be invoked and
-	 * completed before we return
+	 * We need to use the device instance guid to set the path and target
+	 * id. For IDE devices, the device instance id is formatted as
+	 * <bus id> * - <device id> - 8899 - 000000000000.
 	 */
-	blkvsc_req->cond = 0;
-	blkvsc_submit_request(blkvsc_req, blkvsc_cmd_completion);
+	device_info->path_id = device->dev_instance.data[3] << 24 |
+			     device->dev_instance.data[2] << 16 |
+			     device->dev_instance.data[1] << 8  |
+			     device->dev_instance.data[0];
 
-	wait_event_interruptible(blkvsc_req->wevent, blkvsc_req->cond);
+	device_info->target_id = device->dev_instance.data[5] << 8 |
+			       device->dev_instance.data[4];
 
-	kmem_cache_free(blkvsc_req->dev->request_pool, blkvsc_req);
+	return ret;
+}
+
+static int blkvsc_submit_request(struct blkvsc_request *blkvsc_req,
+			void (*request_completion)(struct hv_storvsc_request *))
+{
+	struct block_device_context *blkdev = blkvsc_req->dev;
+	struct hv_storvsc_request *storvsc_req;
+	struct vmscsi_request *vm_srb;
+	int ret;
+
+
+	storvsc_req = &blkvsc_req->request;
+	vm_srb = &storvsc_req->vstor_packet.vm_srb;
+
+	vm_srb->data_in = blkvsc_req->write ? WRITE_TYPE : READ_TYPE;
+
+	storvsc_req->on_io_completion = request_completion;
+	storvsc_req->context = blkvsc_req;
+
+	vm_srb->port_number = blkdev->port;
+	vm_srb->path_id = blkdev->path;
+	vm_srb->target_id = blkdev->target;
+	vm_srb->lun = 0;	 /* this is not really used at all */
+
+	vm_srb->cdb_length = blkvsc_req->cmd_len;
+
+	memcpy(vm_srb->cdb, blkvsc_req->cmnd, vm_srb->cdb_length);
+
+	storvsc_req->sense_buffer = blkvsc_req->sense_buffer;
+
+	ret =  storvsc_do_io(blkdev->device_ctx,
+					   &blkvsc_req->request);
+	if (ret == 0)
+		blkdev->num_outstanding_reqs++;
+
+	return ret;
+}
+
+
+static int blkvsc_open(struct block_device *bdev, fmode_t mode)
+{
+	struct block_device_context *blkdev = bdev->bd_disk->private_data;
+	unsigned long flags;
+
+	spin_lock_irqsave(&blkdev->lock, flags);
+
+	blkdev->users++;
+
+	spin_unlock_irqrestore(&blkdev->lock, flags);
 
 	return 0;
 }
 
-/* Do a scsi INQUIRY cmd here to get the device type (ie disk or dvd) */
-static int blkvsc_do_inquiry(struct block_device_context *blkdev)
+
+static int blkvsc_getgeo(struct block_device *bd, struct hd_geometry *hg)
+{
+	sector_t nsect = get_capacity(bd->bd_disk);
+	sector_t cylinders = nsect;
+
+	/*
+	 * We are making up these values; let us keep it simple.
+	 */
+	hg->heads = 0xff;
+	hg->sectors = 0x3f;
+	sector_div(cylinders, hg->heads * hg->sectors);
+	hg->cylinders = cylinders;
+	if ((sector_t)(hg->cylinders + 1) * hg->heads * hg->sectors < nsect)
+		hg->cylinders = 0xffff;
+	return 0;
+
+}
+
+
+static void blkvsc_init_rw(struct blkvsc_request *blkvsc_req)
+{
+
+	blkvsc_req->cmd_len = 16;
+
+	if (rq_data_dir(blkvsc_req->req)) {
+		blkvsc_req->write = 1;
+		blkvsc_req->cmnd[0] = WRITE_16;
+	} else {
+		blkvsc_req->write = 0;
+		blkvsc_req->cmnd[0] = READ_16;
+	}
+
+	blkvsc_req->cmnd[1] |=
+	(blkvsc_req->req->cmd_flags & REQ_FUA) ? 0x8 : 0;
+
+	*(unsigned long long *)&blkvsc_req->cmnd[2] =
+	cpu_to_be64(blkvsc_req->sector_start);
+	*(unsigned int *)&blkvsc_req->cmnd[10] =
+	cpu_to_be32(blkvsc_req->sector_count);
+}
+
+
+static int blkvsc_ioctl(struct block_device *bd, fmode_t mode,
+			unsigned cmd, unsigned long arg)
+{
+	struct block_device_context *blkdev = bd->bd_disk->private_data;
+	int ret = 0;
+
+	switch (cmd) {
+	case HDIO_GET_IDENTITY:
+		if (copy_to_user((void __user *)arg, blkdev->device_id,
+				 blkdev->device_id_len))
+			ret = -EFAULT;
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+static void blkvsc_cmd_completion(struct hv_storvsc_request *request)
+{
+	struct blkvsc_request *blkvsc_req =
+			(struct blkvsc_request *)request->context;
+	struct block_device_context *blkdev =
+			(struct block_device_context *)blkvsc_req->dev;
+	struct scsi_sense_hdr sense_hdr;
+	struct vmscsi_request *vm_srb;
+	unsigned long flags;
+
+
+	vm_srb = &blkvsc_req->request.vstor_packet.vm_srb;
+
+	spin_lock_irqsave(&blkdev->lock, flags);
+	blkdev->num_outstanding_reqs--;
+	spin_unlock_irqrestore(&blkdev->lock, flags);
+
+	if (vm_srb->scsi_status)
+		if (scsi_normalize_sense(blkvsc_req->sense_buffer,
+					 SCSI_SENSE_BUFFERSIZE, &sense_hdr))
+			scsi_print_sense_hdr("blkvsc", &sense_hdr);
+
+	complete(&blkvsc_req->request.wait_event);
+}
+
+
+static int blkvsc_do_operation(struct block_device_context *blkdev,
+				enum blkvsc_op_type op)
 {
 	struct blkvsc_request *blkvsc_req;
 	struct page *page_buf;
 	unsigned char *buf;
 	unsigned char device_type;
-
-	DPRINT_DBG(BLKVSC_DRV, "blkvsc_do_inquiry()\n");
-
-	blkvsc_req = kmem_cache_alloc(blkdev->request_pool, GFP_KERNEL);
-	if (!blkvsc_req)
-		return -ENOMEM;
-
-	memset(blkvsc_req, 0, sizeof(struct blkvsc_request));
-	page_buf = alloc_page(GFP_KERNEL);
-	if (!page_buf) {
-		kmem_cache_free(blkvsc_req->dev->request_pool, blkvsc_req);
-		return -ENOMEM;
-	}
-
-	init_waitqueue_head(&blkvsc_req->wevent);
-	blkvsc_req->dev = blkdev;
-	blkvsc_req->req = NULL;
-	blkvsc_req->write = 0;
-
-	blkvsc_req->request.DataBuffer.PfnArray[0] = page_to_pfn(page_buf);
-	blkvsc_req->request.DataBuffer.Offset = 0;
-	blkvsc_req->request.DataBuffer.Length = 64;
-
-	blkvsc_req->cmnd[0] = INQUIRY;
-	blkvsc_req->cmnd[1] = 0x1;		/* Get product data */
-	blkvsc_req->cmnd[2] = 0x83;		/* mode page 83 */
-	blkvsc_req->cmnd[4] = 64;
-	blkvsc_req->cmd_len = 6;
-
-	/*
-	 * Set this here since the completion routine may be invoked and
-	 * completed before we return
-	 */
-	blkvsc_req->cond = 0;
-
-	blkvsc_submit_request(blkvsc_req, blkvsc_cmd_completion);
-
-	DPRINT_DBG(BLKVSC_DRV, "waiting %p to complete - cond %d\n",
-		   blkvsc_req, blkvsc_req->cond);
-
-	wait_event_interruptible(blkvsc_req->wevent, blkvsc_req->cond);
-
-	buf = kmap(page_buf);
-
-	/* print_hex_dump_bytes("", DUMP_PREFIX_NONE, buf, 64); */
-	/* be to le */
-	device_type = buf[0] & 0x1F;
-
-	if (device_type == 0x0) {
-		blkdev->device_type = HARDDISK_TYPE;
-	} else if (device_type == 0x5) {
-		blkdev->device_type = DVD_TYPE;
-	} else {
-		/* TODO: this is currently unsupported device type */
-		blkdev->device_type = UNKNOWN_DEV_TYPE;
-	}
-
-	DPRINT_DBG(BLKVSC_DRV, "device type %d\n", device_type);
-
-	blkdev->device_id_len = buf[7];
-	if (blkdev->device_id_len > 64)
-		blkdev->device_id_len = 64;
-
-	memcpy(blkdev->device_id, &buf[8], blkdev->device_id_len);
-	/* printk_hex_dump_bytes("", DUMP_PREFIX_NONE, blkdev->device_id,
-	 * blkdev->device_id_len); */
-
-	kunmap(page_buf);
-
-	__free_page(page_buf);
-
-	kmem_cache_free(blkvsc_req->dev->request_pool, blkvsc_req);
-
-	return 0;
-}
-
-/* Do a scsi READ_CAPACITY cmd here to get the size of the disk */
-static int blkvsc_do_read_capacity(struct block_device_context *blkdev)
-{
-	struct blkvsc_request *blkvsc_req;
-	struct page *page_buf;
-	unsigned char *buf;
 	struct scsi_sense_hdr sense_hdr;
+	struct vmscsi_request *vm_srb;
+	unsigned long flags;
 
-	DPRINT_DBG(BLKVSC_DRV, "blkvsc_do_read_capacity()\n");
+	int ret = 0;
 
-	blkdev->sector_size = 0;
-	blkdev->capacity = 0;
-	blkdev->media_not_present = 0; /* assume a disk is present */
-
-	blkvsc_req = kmem_cache_alloc(blkdev->request_pool, GFP_KERNEL);
+	blkvsc_req = kmem_cache_zalloc(blkdev->request_pool, GFP_KERNEL);
 	if (!blkvsc_req)
 		return -ENOMEM;
 
-	memset(blkvsc_req, 0, sizeof(struct blkvsc_request));
 	page_buf = alloc_page(GFP_KERNEL);
 	if (!page_buf) {
 		kmem_cache_free(blkvsc_req->dev->request_pool, blkvsc_req);
 		return -ENOMEM;
 	}
 
-	init_waitqueue_head(&blkvsc_req->wevent);
+	vm_srb = &blkvsc_req->request.vstor_packet.vm_srb;
+	init_completion(&blkvsc_req->request.wait_event);
 	blkvsc_req->dev = blkdev;
 	blkvsc_req->req = NULL;
 	blkvsc_req->write = 0;
 
-	blkvsc_req->request.DataBuffer.PfnArray[0] = page_to_pfn(page_buf);
-	blkvsc_req->request.DataBuffer.Offset = 0;
-	blkvsc_req->request.DataBuffer.Length = 8;
+	blkvsc_req->request.data_buffer.pfn_array[0] =
+	page_to_pfn(page_buf);
+	blkvsc_req->request.data_buffer.offset = 0;
 
-	blkvsc_req->cmnd[0] = READ_CAPACITY;
-	blkvsc_req->cmd_len = 16;
+	switch (op) {
+	case DO_INQUIRY:
+		blkvsc_req->cmnd[0] = INQUIRY;
+		blkvsc_req->cmnd[1] = 0x1;		/* Get product data */
+		blkvsc_req->cmnd[2] = 0x83;		/* mode page 83 */
+		blkvsc_req->cmnd[4] = 64;
+		blkvsc_req->cmd_len = 6;
+		blkvsc_req->request.data_buffer.len = 64;
+		break;
 
-	/*
-	 * Set this here since the completion routine may be invoked
-	 * and completed before we return
-	 */
-	blkvsc_req->cond = 0;
+	case DO_CAPACITY:
+		blkdev->sector_size = 0;
+		blkdev->capacity = 0;
 
+		blkvsc_req->cmnd[0] = READ_CAPACITY;
+		blkvsc_req->cmd_len = 16;
+		blkvsc_req->request.data_buffer.len = 8;
+		break;
+
+	case DO_FLUSH:
+		blkvsc_req->cmnd[0] = SYNCHRONIZE_CACHE;
+		blkvsc_req->cmd_len = 10;
+		blkvsc_req->request.data_buffer.pfn_array[0] = 0;
+		blkvsc_req->request.data_buffer.len = 0;
+		break;
+	default:
+		ret = -EINVAL;
+		goto cleanup;
+	}
+
+	spin_lock_irqsave(&blkdev->lock, flags);
 	blkvsc_submit_request(blkvsc_req, blkvsc_cmd_completion);
+	spin_unlock_irqrestore(&blkdev->lock, flags);
 
-	DPRINT_DBG(BLKVSC_DRV, "waiting %p to complete - cond %d\n",
-		   blkvsc_req, blkvsc_req->cond);
-
-	wait_event_interruptible(blkvsc_req->wevent, blkvsc_req->cond);
+	wait_for_completion_interruptible(&blkvsc_req->request.wait_event);
 
 	/* check error */
-	if (blkvsc_req->request.Status) {
+	if (vm_srb->scsi_status) {
 		scsi_normalize_sense(blkvsc_req->sense_buffer,
 				     SCSI_SENSE_BUFFERSIZE, &sense_hdr);
 
-		if (sense_hdr.asc == 0x3A) {
-			/* Medium not present */
-			blkdev->media_not_present = 1;
-		}
 		return 0;
 	}
+
 	buf = kmap(page_buf);
 
-	/* be to le */
-	blkdev->capacity = ((buf[0] << 24) | (buf[1] << 16) |
-			    (buf[2] << 8) | buf[3]) + 1;
-	blkdev->sector_size = (buf[4] << 24) | (buf[5] << 16) |
-			      (buf[6] << 8) | buf[7];
+	switch (op) {
+	case DO_INQUIRY:
+		device_type = buf[0] & 0x1F;
+
+		if (device_type == 0x0)
+			blkdev->device_type = HARDDISK_TYPE;
+		 else
+			blkdev->device_type = UNKNOWN_DEV_TYPE;
+
+		blkdev->device_id_len = buf[7];
+		if (blkdev->device_id_len > 64)
+			blkdev->device_id_len = 64;
+
+		memcpy(blkdev->device_id, &buf[8], blkdev->device_id_len);
+		break;
+
+	case DO_CAPACITY:
+		/* be to le */
+		blkdev->capacity =
+		((buf[0] << 24) | (buf[1] << 16) |
+		(buf[2] << 8) | buf[3]) + 1;
+
+		blkdev->sector_size =
+		(buf[4] << 24) | (buf[5] << 16) |
+		(buf[6] << 8) | buf[7];
+		break;
+	default:
+		break;
+
+	}
+
+cleanup:
 
 	kunmap(page_buf);
 
@@ -639,122 +424,86 @@
 
 	kmem_cache_free(blkvsc_req->dev->request_pool, blkvsc_req);
 
-	return 0;
+	return ret;
 }
 
-static int blkvsc_do_read_capacity16(struct block_device_context *blkdev)
+
+static int blkvsc_cancel_pending_reqs(struct block_device_context *blkdev)
 {
-	struct blkvsc_request *blkvsc_req;
-	struct page *page_buf;
-	unsigned char *buf;
-	struct scsi_sense_hdr sense_hdr;
+	struct blkvsc_request *pend_req, *tmp;
+	struct blkvsc_request *comp_req, *tmp2;
+	struct vmscsi_request *vm_srb;
 
-	DPRINT_DBG(BLKVSC_DRV, "blkvsc_do_read_capacity16()\n");
+	int ret = 0;
 
-	blkdev->sector_size = 0;
-	blkdev->capacity = 0;
-	blkdev->media_not_present = 0; /* assume a disk is present */
 
-	blkvsc_req = kmem_cache_alloc(blkdev->request_pool, GFP_KERNEL);
-	if (!blkvsc_req)
-		return -ENOMEM;
+	/* Flush the pending list first */
+	list_for_each_entry_safe(pend_req, tmp, &blkdev->pending_list,
+				 pend_entry) {
+		/*
+		 * The pend_req could be part of a partially completed
+		 * request. If so, complete those req first until we
+		 * hit the pend_req
+		 */
+		list_for_each_entry_safe(comp_req, tmp2,
+					 &pend_req->group->blkvsc_req_list,
+					 req_entry) {
 
-	memset(blkvsc_req, 0, sizeof(struct blkvsc_request));
-	page_buf = alloc_page(GFP_KERNEL);
-	if (!page_buf) {
-		kmem_cache_free(blkvsc_req->dev->request_pool, blkvsc_req);
-		return -ENOMEM;
-	}
+			if (comp_req == pend_req)
+				break;
 
-	init_waitqueue_head(&blkvsc_req->wevent);
-	blkvsc_req->dev = blkdev;
-	blkvsc_req->req = NULL;
-	blkvsc_req->write = 0;
+			list_del(&comp_req->req_entry);
 
-	blkvsc_req->request.DataBuffer.PfnArray[0] = page_to_pfn(page_buf);
-	blkvsc_req->request.DataBuffer.Offset = 0;
-	blkvsc_req->request.DataBuffer.Length = 12;
+			if (comp_req->req) {
+				vm_srb =
+				&comp_req->request.vstor_packet.
+				vm_srb;
+				ret = __blk_end_request(comp_req->req,
+					(!vm_srb->scsi_status ? 0 : -EIO),
+					comp_req->sector_count *
+					blkdev->sector_size);
 
-	blkvsc_req->cmnd[0] = 0x9E; /* READ_CAPACITY16; */
-	blkvsc_req->cmd_len = 16;
+				/* FIXME: shouldn't this do more than return? */
+				if (ret)
+					goto out;
+			}
 
-	/*
-	 * Set this here since the completion routine may be invoked
-	 * and completed before we return
-	 */
-	blkvsc_req->cond = 0;
-
-	blkvsc_submit_request(blkvsc_req, blkvsc_cmd_completion);
-
-	DPRINT_DBG(BLKVSC_DRV, "waiting %p to complete - cond %d\n",
-		   blkvsc_req, blkvsc_req->cond);
-
-	wait_event_interruptible(blkvsc_req->wevent, blkvsc_req->cond);
-
-	/* check error */
-	if (blkvsc_req->request.Status) {
-		scsi_normalize_sense(blkvsc_req->sense_buffer,
-				     SCSI_SENSE_BUFFERSIZE, &sense_hdr);
-		if (sense_hdr.asc == 0x3A) {
-			/* Medium not present */
-			blkdev->media_not_present = 1;
+			kmem_cache_free(blkdev->request_pool, comp_req);
 		}
-		return 0;
+
+		list_del(&pend_req->pend_entry);
+
+		list_del(&pend_req->req_entry);
+
+		if (comp_req->req) {
+			if (!__blk_end_request(pend_req->req, -EIO,
+					       pend_req->sector_count *
+					       blkdev->sector_size)) {
+				/*
+				 * All the sectors have been xferred ie the
+				 * request is done
+				 */
+				kmem_cache_free(blkdev->request_pool,
+						pend_req->group);
+			}
+		}
+
+		kmem_cache_free(blkdev->request_pool, pend_req);
 	}
-	buf = kmap(page_buf);
 
-	/* be to le */
-	blkdev->capacity = be64_to_cpu(*(unsigned long long *) &buf[0]) + 1;
-	blkdev->sector_size = be32_to_cpu(*(unsigned int *)&buf[8]);
-
-#if 0
-	blkdev->capacity = ((buf[0] << 24) | (buf[1] << 16) |
-			    (buf[2] << 8) | buf[3]) + 1;
-	blkdev->sector_size = (buf[4] << 24) | (buf[5] << 16) |
-			      (buf[6] << 8) | buf[7];
-#endif
-
-	kunmap(page_buf);
-
-	__free_page(page_buf);
-
-	kmem_cache_free(blkvsc_req->dev->request_pool, blkvsc_req);
-
-	return 0;
+out:
+	return ret;
 }
 
+
 /*
  * blkvsc_remove() - Callback when our device is removed
  */
-static int blkvsc_remove(struct device *device)
+static int blkvsc_remove(struct hv_device *dev)
 {
-	struct driver_context *driver_ctx =
-				driver_to_driver_context(device->driver);
-	struct blkvsc_driver_context *blkvsc_drv_ctx =
-				(struct blkvsc_driver_context *)driver_ctx;
-	struct storvsc_driver_object *storvsc_drv_obj =
-				&blkvsc_drv_ctx->drv_obj;
-	struct vm_device *device_ctx = device_to_vm_device(device);
-	struct hv_device *device_obj = &device_ctx->device_obj;
-	struct block_device_context *blkdev = dev_get_drvdata(device);
+	struct block_device_context *blkdev = dev_get_drvdata(&dev->device);
 	unsigned long flags;
-	int ret;
 
-	DPRINT_DBG(BLKVSC_DRV, "blkvsc_remove()\n");
-
-	if (!storvsc_drv_obj->Base.OnDeviceRemove)
-		return -1;
-
-	/*
-	 * Call to the vsc driver to let it know that the device is being
-	 * removed
-	 */
-	ret = storvsc_drv_obj->Base.OnDeviceRemove(device_obj);
-	if (ret != 0) {
-		/* TODO: */
-		DPRINT_ERR(BLKVSC_DRV,
-			   "unable to remove blkvsc device (ret %d)", ret);
-	}
 
 	/* Get to a known state */
 	spin_lock_irqsave(&blkdev->lock, flags);
@@ -763,147 +512,79 @@
 
 	blk_stop_queue(blkdev->gd->queue);
 
+	blkvsc_cancel_pending_reqs(blkdev);
+
 	spin_unlock_irqrestore(&blkdev->lock, flags);
 
-	while (blkdev->num_outstanding_reqs) {
-		DPRINT_INFO(STORVSC, "waiting for %d requests to complete...",
-			    blkdev->num_outstanding_reqs);
-		udelay(100);
+	blkvsc_do_operation(blkdev, DO_FLUSH);
+
+	if (blkdev->users == 0) {
+		del_gendisk(blkdev->gd);
+		put_disk(blkdev->gd);
+		blk_cleanup_queue(blkdev->gd->queue);
+
+		storvsc_dev_remove(blkdev->device_ctx);
+
+		kmem_cache_destroy(blkdev->request_pool);
+		kfree(blkdev);
 	}
 
-	blkvsc_do_flush(blkdev);
+	return 0;
+}
+
+static void blkvsc_shutdown(struct hv_device *dev)
+{
+	struct block_device_context *blkdev = dev_get_drvdata(&dev->device);
+	unsigned long flags;
+
+	if (!blkdev)
+		return;
 
 	spin_lock_irqsave(&blkdev->lock, flags);
 
+	blkdev->shutting_down = 1;
+
+	blk_stop_queue(blkdev->gd->queue);
+
 	blkvsc_cancel_pending_reqs(blkdev);
 
 	spin_unlock_irqrestore(&blkdev->lock, flags);
 
-	blk_cleanup_queue(blkdev->gd->queue);
+	blkvsc_do_operation(blkdev, DO_FLUSH);
 
-	del_gendisk(blkdev->gd);
+	/*
+	 * Now wait for all outgoing I/O to be drained.
+	 */
+	storvsc_wait_to_drain((struct storvsc_device *)dev->ext);
 
-	kmem_cache_destroy(blkdev->request_pool);
-
-	kfree(blkdev);
-
-	return ret;
 }
 
-static void blkvsc_init_rw(struct blkvsc_request *blkvsc_req)
+static int blkvsc_release(struct gendisk *disk, fmode_t mode)
 {
-	/* ASSERT(blkvsc_req->req); */
-	/* ASSERT(blkvsc_req->sector_count <= (MAX_MULTIPAGE_BUFFER_COUNT*8)); */
+	struct block_device_context *blkdev = disk->private_data;
+	unsigned long flags;
 
-	blkvsc_req->cmd_len = 16;
+	spin_lock_irqsave(&blkdev->lock, flags);
 
-	if (blkvsc_req->sector_start > 0xffffffff) {
-		if (rq_data_dir(blkvsc_req->req)) {
-			blkvsc_req->write = 1;
-			blkvsc_req->cmnd[0] = WRITE_16;
-		} else {
-			blkvsc_req->write = 0;
-			blkvsc_req->cmnd[0] = READ_16;
-		}
+	if ((--blkdev->users == 0) && (blkdev->shutting_down)) {
+		blk_stop_queue(blkdev->gd->queue);
+		spin_unlock_irqrestore(&blkdev->lock, flags);
 
-		blkvsc_req->cmnd[1] |=
-			(blkvsc_req->req->cmd_flags & REQ_FUA) ? 0x8 : 0;
+		blkvsc_do_operation(blkdev, DO_FLUSH);
+		del_gendisk(blkdev->gd);
+		put_disk(blkdev->gd);
+		blk_cleanup_queue(blkdev->gd->queue);
 
-		*(unsigned long long *)&blkvsc_req->cmnd[2] =
-				cpu_to_be64(blkvsc_req->sector_start);
-		*(unsigned int *)&blkvsc_req->cmnd[10] =
-				cpu_to_be32(blkvsc_req->sector_count);
-	} else if ((blkvsc_req->sector_count > 0xff) ||
-		   (blkvsc_req->sector_start > 0x1fffff)) {
-		if (rq_data_dir(blkvsc_req->req)) {
-			blkvsc_req->write = 1;
-			blkvsc_req->cmnd[0] = WRITE_10;
-		} else {
-			blkvsc_req->write = 0;
-			blkvsc_req->cmnd[0] = READ_10;
-		}
+		storvsc_dev_remove(blkdev->device_ctx);
 
-		blkvsc_req->cmnd[1] |=
-			(blkvsc_req->req->cmd_flags & REQ_FUA) ? 0x8 : 0;
+		kmem_cache_destroy(blkdev->request_pool);
+		kfree(blkdev);
+	} else
+		spin_unlock_irqrestore(&blkdev->lock, flags);
 
-		*(unsigned int *)&blkvsc_req->cmnd[2] =
-				cpu_to_be32(blkvsc_req->sector_start);
-		*(unsigned short *)&blkvsc_req->cmnd[7] =
-				cpu_to_be16(blkvsc_req->sector_count);
-	} else {
-		if (rq_data_dir(blkvsc_req->req)) {
-			blkvsc_req->write = 1;
-			blkvsc_req->cmnd[0] = WRITE_6;
-		} else {
-			blkvsc_req->write = 0;
-			blkvsc_req->cmnd[0] = READ_6;
-		}
-
-		*(unsigned int *)&blkvsc_req->cmnd[1] =
-				cpu_to_be32(blkvsc_req->sector_start) >> 8;
-		blkvsc_req->cmnd[1] &= 0x1f;
-		blkvsc_req->cmnd[4] = (unsigned char)blkvsc_req->sector_count;
-	}
+	return 0;
 }
 
-static int blkvsc_submit_request(struct blkvsc_request *blkvsc_req,
-			void (*request_completion)(struct hv_storvsc_request *))
-{
-	struct block_device_context *blkdev = blkvsc_req->dev;
-	struct vm_device *device_ctx = blkdev->device_ctx;
-	struct driver_context *driver_ctx =
-			driver_to_driver_context(device_ctx->device.driver);
-	struct blkvsc_driver_context *blkvsc_drv_ctx =
-			(struct blkvsc_driver_context *)driver_ctx;
-	struct storvsc_driver_object *storvsc_drv_obj =
-			&blkvsc_drv_ctx->drv_obj;
-	struct hv_storvsc_request *storvsc_req;
-	int ret;
-
-	DPRINT_DBG(BLKVSC_DRV, "blkvsc_submit_request() - "
-		   "req %p type %s start_sector %lu count %ld offset %d "
-		   "len %d\n", blkvsc_req,
-		   (blkvsc_req->write) ? "WRITE" : "READ",
-		   (unsigned long) blkvsc_req->sector_start,
-		   blkvsc_req->sector_count,
-		   blkvsc_req->request.DataBuffer.Offset,
-		   blkvsc_req->request.DataBuffer.Length);
-#if 0
-	for (i = 0; i < (blkvsc_req->request.DataBuffer.Length >> 12); i++) {
-		DPRINT_DBG(BLKVSC_DRV, "blkvsc_submit_request() - "
-			   "req %p pfn[%d] %llx\n",
-			   blkvsc_req, i,
-			   blkvsc_req->request.DataBuffer.PfnArray[i]);
-	}
-#endif
-
-	storvsc_req = &blkvsc_req->request;
-	storvsc_req->Extension = (void *)((unsigned long)blkvsc_req +
-					  sizeof(struct blkvsc_request));
-
-	storvsc_req->Type = blkvsc_req->write ? WRITE_TYPE : READ_TYPE;
-
-	storvsc_req->OnIOCompletion = request_completion;
-	storvsc_req->Context = blkvsc_req;
-
-	storvsc_req->Host = blkdev->port;
-	storvsc_req->Bus = blkdev->path;
-	storvsc_req->TargetId = blkdev->target;
-	storvsc_req->LunId = 0;	 /* this is not really used at all */
-
-	storvsc_req->CdbLen = blkvsc_req->cmd_len;
-	storvsc_req->Cdb = blkvsc_req->cmnd;
-
-	storvsc_req->SenseBuffer = blkvsc_req->sense_buffer;
-	storvsc_req->SenseBufferSize = SCSI_SENSE_BUFFERSIZE;
-
-	ret = storvsc_drv_obj->OnIORequest(&blkdev->device_ctx->device_obj,
-					   &blkvsc_req->request);
-	if (ret == 0)
-		blkdev->num_outstanding_reqs++;
-
-	return ret;
-}
 
 /*
  * We break the request into 1 or more blkvsc_requests and submit
@@ -926,11 +607,8 @@
 	int pending = 0;
 	struct blkvsc_request_group *group = NULL;
 
-	DPRINT_DBG(BLKVSC_DRV, "blkdev %p req %p sect %lu\n", blkdev, req,
-		  (unsigned long)blk_rq_pos(req));
-
 	/* Create a group to tie req to list of blkvsc_reqs */
-	group = kmem_cache_alloc(blkdev->request_pool, GFP_ATOMIC);
+	group = kmem_cache_zalloc(blkdev->request_pool, GFP_ATOMIC);
 	if (!group)
 		return -ENOMEM;
 
@@ -946,11 +624,6 @@
 			 * Map this bio into an existing or new storvsc request
 			 */
 			bio_for_each_segment(bvec, bio, seg_idx) {
-				DPRINT_DBG(BLKVSC_DRV, "bio_for_each_segment() "
-					   "- req %p bio %p bvec %p seg_idx %d "
-					   "databuf_idx %d\n", req, bio, bvec,
-					   seg_idx, databuf_idx);
-
 				/* Get a new storvsc request */
 				/* 1st-time */
 				if ((!blkvsc_req) ||
@@ -962,10 +635,15 @@
 				     (prev_bvec->bv_len != PAGE_SIZE))) {
 					/* submit the prev one */
 					if (blkvsc_req) {
-						blkvsc_req->sector_start = start_sector;
-						sector_div(blkvsc_req->sector_start, (blkdev->sector_size >> 9));
+						blkvsc_req->sector_start =
+						start_sector;
+						sector_div(
+						blkvsc_req->sector_start,
+						(blkdev->sector_size >> 9));
 
-						blkvsc_req->sector_count = num_sectors / (blkdev->sector_size >> 9);
+						blkvsc_req->sector_count =
+						num_sectors /
+						(blkdev->sector_size >> 9);
 						blkvsc_init_rw(blkvsc_req);
 					}
 
@@ -973,18 +651,24 @@
 					 * Create new blkvsc_req to represent
 					 * the current bvec
 					 */
-					blkvsc_req = kmem_cache_alloc(blkdev->request_pool, GFP_ATOMIC);
+					blkvsc_req =
+					kmem_cache_zalloc(
+					blkdev->request_pool, GFP_ATOMIC);
 					if (!blkvsc_req) {
 						/* free up everything */
 						list_for_each_entry_safe(
 							blkvsc_req, tmp,
 							&group->blkvsc_req_list,
 							req_entry) {
-							list_del(&blkvsc_req->req_entry);
-							kmem_cache_free(blkdev->request_pool, blkvsc_req);
+							list_del(
+							&blkvsc_req->req_entry);
+							kmem_cache_free(
+							blkdev->request_pool,
+							blkvsc_req);
 						}
 
-						kmem_cache_free(blkdev->request_pool, group);
+						kmem_cache_free(
+						blkdev->request_pool, group);
 						return -ENOMEM;
 					}
 
@@ -993,23 +677,32 @@
 
 					blkvsc_req->dev = blkdev;
 					blkvsc_req->req = req;
-					blkvsc_req->request.DataBuffer.Offset = bvec->bv_offset;
-					blkvsc_req->request.DataBuffer.Length = 0;
+					blkvsc_req->request.
+					data_buffer.offset
+					= bvec->bv_offset;
+					blkvsc_req->request.
+					data_buffer.len = 0;
 
 					/* Add to the group */
 					blkvsc_req->group = group;
 					blkvsc_req->group->outstanding++;
 					list_add_tail(&blkvsc_req->req_entry,
-						&blkvsc_req->group->blkvsc_req_list);
+					&blkvsc_req->group->blkvsc_req_list);
 
 					start_sector += num_sectors;
 					num_sectors = 0;
 					databuf_idx = 0;
 				}
 
-				/* Add the curr bvec/segment to the curr blkvsc_req */
-				blkvsc_req->request.DataBuffer.PfnArray[databuf_idx] = page_to_pfn(bvec->bv_page);
-				blkvsc_req->request.DataBuffer.Length += bvec->bv_len;
+				/*
+				 * Add the curr bvec/segment to the curr
+				 * blkvsc_req
+				 */
+				blkvsc_req->request.data_buffer.
+					pfn_array[databuf_idx]
+						= page_to_pfn(bvec->bv_page);
+				blkvsc_req->request.data_buffer.len
+					+= bvec->bv_len;
 
 				prev_bvec = bvec;
 
@@ -1023,10 +716,6 @@
 
 	/* Handle the last one */
 	if (blkvsc_req) {
-		DPRINT_DBG(BLKVSC_DRV, "blkdev %p req %p group %p count %d\n",
-			   blkdev, req, blkvsc_req->group,
-			   blkvsc_req->group->outstanding);
-
 		blkvsc_req->sector_start = start_sector;
 		sector_div(blkvsc_req->sector_start,
 			   (blkdev->sector_size >> 9));
@@ -1039,13 +728,6 @@
 
 	list_for_each_entry(blkvsc_req, &group->blkvsc_req_list, req_entry) {
 		if (pending) {
-			DPRINT_DBG(BLKVSC_DRV, "adding blkvsc_req to "
-				   "pending_list - blkvsc_req %p start_sect %lu"
-				   " sect_count %ld (%lu %ld)\n", blkvsc_req,
-				   (unsigned long)blkvsc_req->sector_start,
-				   blkvsc_req->sector_count,
-				   (unsigned long)start_sector,
-				   (unsigned long)num_sectors);
 
 			list_add_tail(&blkvsc_req->pend_entry,
 				      &blkdev->pending_list);
@@ -1058,62 +740,236 @@
 					      &blkdev->pending_list);
 			}
 
-			DPRINT_DBG(BLKVSC_DRV, "submitted blkvsc_req %p "
-				   "start_sect %lu sect_count %ld (%lu %ld) "
-				   "ret %d\n", blkvsc_req,
-				   (unsigned long)blkvsc_req->sector_start,
-				   blkvsc_req->sector_count,
-				   (unsigned long)start_sector,
-				   num_sectors, ret);
 		}
 	}
 
 	return pending;
 }
 
-static void blkvsc_cmd_completion(struct hv_storvsc_request *request)
+static int blkvsc_do_pending_reqs(struct block_device_context *blkdev)
 {
-	struct blkvsc_request *blkvsc_req =
-			(struct blkvsc_request *)request->Context;
-	struct block_device_context *blkdev =
-			(struct block_device_context *)blkvsc_req->dev;
-	struct scsi_sense_hdr sense_hdr;
+	struct blkvsc_request *pend_req, *tmp;
+	int ret = 0;
 
-	DPRINT_DBG(BLKVSC_DRV, "blkvsc_cmd_completion() - req %p\n",
-		   blkvsc_req);
+	/* Flush the pending list first */
+	list_for_each_entry_safe(pend_req, tmp, &blkdev->pending_list,
+				 pend_entry) {
 
-	blkdev->num_outstanding_reqs--;
+		ret = blkvsc_submit_request(pend_req,
+					    blkvsc_request_completion);
+		if (ret != 0)
+			break;
+		else
+			list_del(&pend_req->pend_entry);
+	}
 
-	if (blkvsc_req->request.Status)
-		if (scsi_normalize_sense(blkvsc_req->sense_buffer,
-					 SCSI_SENSE_BUFFERSIZE, &sense_hdr))
-			scsi_print_sense_hdr("blkvsc", &sense_hdr);
+	return ret;
+}
 
-	blkvsc_req->cond = 1;
-	wake_up_interruptible(&blkvsc_req->wevent);
+
+static void blkvsc_request(struct request_queue *queue)
+{
+	struct block_device_context *blkdev = NULL;
+	struct request *req;
+	int ret = 0;
+
+	while ((req = blk_peek_request(queue)) != NULL) {
+
+		blkdev = req->rq_disk->private_data;
+		if (blkdev->shutting_down || req->cmd_type != REQ_TYPE_FS) {
+			__blk_end_request_cur(req, 0);
+			continue;
+		}
+
+		ret = blkvsc_do_pending_reqs(blkdev);
+
+		if (ret != 0) {
+			blk_stop_queue(queue);
+			break;
+		}
+
+		blk_start_request(req);
+
+		ret = blkvsc_do_request(blkdev, req);
+		if (ret > 0) {
+			blk_stop_queue(queue);
+			break;
+		} else if (ret < 0) {
+			blk_requeue_request(queue, req);
+			blk_stop_queue(queue);
+			break;
+		}
+	}
+}
+
+
+
+/* The one and only one */
+static  struct hv_driver blkvsc_drv = {
+	.probe =  blkvsc_probe,
+	.remove =  blkvsc_remove,
+	.shutdown = blkvsc_shutdown,
+};
+
+static const struct block_device_operations block_ops = {
+	.owner = THIS_MODULE,
+	.open = blkvsc_open,
+	.release = blkvsc_release,
+	.getgeo = blkvsc_getgeo,
+	.ioctl  = blkvsc_ioctl,
+};
+
+/*
+ * blkvsc_drv_init -  BlkVsc driver initialization.
+ */
+static int blkvsc_drv_init(void)
+{
+	struct hv_driver *drv = &blkvsc_drv;
+	int ret;
+
+	BUILD_BUG_ON(sizeof(sector_t) != 8);
+
+	memcpy(&drv->dev_type, &dev_type, sizeof(struct hv_guid));
+	drv->driver.name = drv_name;
+
+	/* The driver belongs to vmbus */
+	ret = vmbus_child_driver_register(&drv->driver);
+
+	return ret;
+}
+
+
+static void blkvsc_drv_exit(void)
+{
+
+	vmbus_child_driver_unregister(&blkvsc_drv.driver);
+}
+
+/*
+ * blkvsc_probe - Add a new device for this driver
+ */
+static int blkvsc_probe(struct hv_device *dev)
+{
+	struct block_device_context *blkdev = NULL;
+	struct storvsc_device_info device_info;
+	struct storvsc_major_info major_info;
+	int ret = 0;
+
+	blkdev = kzalloc(sizeof(struct block_device_context), GFP_KERNEL);
+	if (!blkdev) {
+		ret = -ENOMEM;
+		goto cleanup;
+	}
+
+	INIT_LIST_HEAD(&blkdev->pending_list);
+
+	/* Initialize what we can here */
+	spin_lock_init(&blkdev->lock);
+
+
+	blkdev->request_pool = kmem_cache_create(dev_name(&dev->device),
+					sizeof(struct blkvsc_request), 0,
+					SLAB_HWCACHE_ALIGN, NULL);
+	if (!blkdev->request_pool) {
+		ret = -ENOMEM;
+		goto cleanup;
+	}
+
+
+	ret = blkvsc_device_add(dev, &device_info);
+	if (ret != 0)
+		goto cleanup;
+
+	blkdev->device_ctx = dev;
+	/* this identified the device 0 or 1 */
+	blkdev->target = device_info.target_id;
+	/* this identified the ide ctrl 0 or 1 */
+	blkdev->path = device_info.path_id;
+
+	dev_set_drvdata(&dev->device, blkdev);
+
+	ret = storvsc_get_major_info(&device_info, &major_info);
+
+	if (ret)
+		goto cleanup;
+
+	if (major_info.do_register) {
+		ret = register_blkdev(major_info.major, major_info.devname);
+
+		if (ret != 0) {
+			DPRINT_ERR(BLKVSC_DRV,
+				   "register_blkdev() failed! ret %d", ret);
+			goto remove;
+		}
+	}
+
+	DPRINT_INFO(BLKVSC_DRV, "blkvsc registered for major %d!!",
+			major_info.major);
+
+	blkdev->gd = alloc_disk(BLKVSC_MINORS);
+	if (!blkdev->gd) {
+		ret = -1;
+		goto cleanup;
+	}
+
+	blkdev->gd->queue = blk_init_queue(blkvsc_request, &blkdev->lock);
+
+	blk_queue_max_segment_size(blkdev->gd->queue, PAGE_SIZE);
+	blk_queue_max_segments(blkdev->gd->queue, MAX_MULTIPAGE_BUFFER_COUNT);
+	blk_queue_segment_boundary(blkdev->gd->queue, PAGE_SIZE-1);
+	blk_queue_bounce_limit(blkdev->gd->queue, BLK_BOUNCE_ANY);
+	blk_queue_dma_alignment(blkdev->gd->queue, 511);
+
+	blkdev->gd->major = major_info.major;
+	if (major_info.index == 1 || major_info.index == 3)
+		blkdev->gd->first_minor = BLKVSC_MINORS;
+	else
+		blkdev->gd->first_minor = 0;
+	blkdev->gd->fops = &block_ops;
+	blkdev->gd->private_data = blkdev;
+	blkdev->gd->driverfs_dev = &(blkdev->device_ctx->device);
+	sprintf(blkdev->gd->disk_name, "hd%c", 'a' + major_info.index);
+
+	blkvsc_do_operation(blkdev, DO_INQUIRY);
+	blkvsc_do_operation(blkdev, DO_CAPACITY);
+
+	set_capacity(blkdev->gd, blkdev->capacity * (blkdev->sector_size/512));
+	blk_queue_logical_block_size(blkdev->gd->queue, blkdev->sector_size);
+	/* go! */
+	add_disk(blkdev->gd);
+
+	DPRINT_INFO(BLKVSC_DRV, "%s added!! capacity %lu sector_size %d",
+		    blkdev->gd->disk_name, (unsigned long)blkdev->capacity,
+		    blkdev->sector_size);
+
+	return ret;
+
+remove:
+	storvsc_dev_remove(dev);
+
+cleanup:
+	if (blkdev) {
+		if (blkdev->request_pool) {
+			kmem_cache_destroy(blkdev->request_pool);
+			blkdev->request_pool = NULL;
+		}
+		kfree(blkdev);
+		blkdev = NULL;
+	}
+
+	return ret;
 }
 
 static void blkvsc_request_completion(struct hv_storvsc_request *request)
 {
 	struct blkvsc_request *blkvsc_req =
-			(struct blkvsc_request *)request->Context;
+			(struct blkvsc_request *)request->context;
 	struct block_device_context *blkdev =
 			(struct block_device_context *)blkvsc_req->dev;
 	unsigned long flags;
 	struct blkvsc_request *comp_req, *tmp;
+	struct vmscsi_request *vm_srb;
 
-	/* ASSERT(blkvsc_req->group); */
-
-	DPRINT_DBG(BLKVSC_DRV, "blkdev %p blkvsc_req %p group %p type %s "
-		   "sect_start %lu sect_count %ld len %d group outstd %d "
-		   "total outstd %d\n",
-		   blkdev, blkvsc_req, blkvsc_req->group,
-		   (blkvsc_req->write) ? "WRITE" : "READ",
-		   (unsigned long)blkvsc_req->sector_start,
-		   blkvsc_req->sector_count,
-		   blkvsc_req->request.DataBuffer.Length,
-		   blkvsc_req->group->outstanding,
-		   blkdev->num_outstanding_reqs);
 
 	spin_lock_irqsave(&blkdev->lock, flags);
 
@@ -1129,23 +985,18 @@
 		list_for_each_entry_safe(comp_req, tmp,
 					 &blkvsc_req->group->blkvsc_req_list,
 					 req_entry) {
-			DPRINT_DBG(BLKVSC_DRV, "completing blkvsc_req %p "
-				   "sect_start %lu sect_count %ld\n",
-				   comp_req,
-				   (unsigned long)comp_req->sector_start,
-				   comp_req->sector_count);
 
 			list_del(&comp_req->req_entry);
 
+			vm_srb =
+			&comp_req->request.vstor_packet.vm_srb;
 			if (!__blk_end_request(comp_req->req,
-				(!comp_req->request.Status ? 0 : -EIO),
+				(!vm_srb->scsi_status ? 0 : -EIO),
 				comp_req->sector_count * blkdev->sector_size)) {
 				/*
 				 * All the sectors have been xferred ie the
 				 * request is done
 				 */
-				DPRINT_DBG(BLKVSC_DRV, "req %p COMPLETED\n",
-					   comp_req->req);
 				kmem_cache_free(blkdev->request_pool,
 						comp_req->group);
 			}
@@ -1163,327 +1014,6 @@
 	spin_unlock_irqrestore(&blkdev->lock, flags);
 }
 
-static int blkvsc_cancel_pending_reqs(struct block_device_context *blkdev)
-{
-	struct blkvsc_request *pend_req, *tmp;
-	struct blkvsc_request *comp_req, *tmp2;
-
-	int ret = 0;
-
-	DPRINT_DBG(BLKVSC_DRV, "blkvsc_cancel_pending_reqs()");
-
-	/* Flush the pending list first */
-	list_for_each_entry_safe(pend_req, tmp, &blkdev->pending_list,
-				 pend_entry) {
-		/*
-		 * The pend_req could be part of a partially completed
-		 * request. If so, complete those req first until we
-		 * hit the pend_req
-		 */
-		list_for_each_entry_safe(comp_req, tmp2,
-					 &pend_req->group->blkvsc_req_list,
-					 req_entry) {
-			DPRINT_DBG(BLKVSC_DRV, "completing blkvsc_req %p "
-				   "sect_start %lu sect_count %ld\n",
-				   comp_req,
-				   (unsigned long) comp_req->sector_start,
-				   comp_req->sector_count);
-
-			if (comp_req == pend_req)
-				break;
-
-			list_del(&comp_req->req_entry);
-
-			if (comp_req->req) {
-				ret = __blk_end_request(comp_req->req,
-					(!comp_req->request.Status ? 0 : -EIO),
-					comp_req->sector_count *
-					blkdev->sector_size);
-
-				/* FIXME: shouldn't this do more than return? */
-				if (ret)
-					goto out;
-			}
-
-			kmem_cache_free(blkdev->request_pool, comp_req);
-		}
-
-		DPRINT_DBG(BLKVSC_DRV, "cancelling pending request - %p\n",
-			   pend_req);
-
-		list_del(&pend_req->pend_entry);
-
-		list_del(&pend_req->req_entry);
-
-		if (comp_req->req) {
-			if (!__blk_end_request(pend_req->req, -EIO,
-					       pend_req->sector_count *
-					       blkdev->sector_size)) {
-				/*
-				 * All the sectors have been xferred ie the
-				 * request is done
-				 */
-				DPRINT_DBG(BLKVSC_DRV,
-					   "blkvsc_cancel_pending_reqs() - "
-					   "req %p COMPLETED\n", pend_req->req);
-				kmem_cache_free(blkdev->request_pool,
-						pend_req->group);
-			}
-		}
-
-		kmem_cache_free(blkdev->request_pool, pend_req);
-	}
-
-out:
-	return ret;
-}
-
-static int blkvsc_do_pending_reqs(struct block_device_context *blkdev)
-{
-	struct blkvsc_request *pend_req, *tmp;
-	int ret = 0;
-
-	/* Flush the pending list first */
-	list_for_each_entry_safe(pend_req, tmp, &blkdev->pending_list,
-				 pend_entry) {
-		DPRINT_DBG(BLKVSC_DRV, "working off pending_list - %p\n",
-			   pend_req);
-
-		ret = blkvsc_submit_request(pend_req,
-					    blkvsc_request_completion);
-		if (ret != 0)
-			break;
-		else
-			list_del(&pend_req->pend_entry);
-	}
-
-	return ret;
-}
-
-static void blkvsc_request(struct request_queue *queue)
-{
-	struct block_device_context *blkdev = NULL;
-	struct request *req;
-	int ret = 0;
-
-	DPRINT_DBG(BLKVSC_DRV, "- enter\n");
-	while ((req = blk_peek_request(queue)) != NULL) {
-		DPRINT_DBG(BLKVSC_DRV, "- req %p\n", req);
-
-		blkdev = req->rq_disk->private_data;
-		if (blkdev->shutting_down || req->cmd_type != REQ_TYPE_FS ||
-		    blkdev->media_not_present) {
-			__blk_end_request_cur(req, 0);
-			continue;
-		}
-
-		ret = blkvsc_do_pending_reqs(blkdev);
-
-		if (ret != 0) {
-			DPRINT_DBG(BLKVSC_DRV,
-				   "- stop queue - pending_list not empty\n");
-			blk_stop_queue(queue);
-			break;
-		}
-
-		blk_start_request(req);
-
-		ret = blkvsc_do_request(blkdev, req);
-		if (ret > 0) {
-			DPRINT_DBG(BLKVSC_DRV, "- stop queue - no room\n");
-			blk_stop_queue(queue);
-			break;
-		} else if (ret < 0) {
-			DPRINT_DBG(BLKVSC_DRV, "- stop queue - no mem\n");
-			blk_requeue_request(queue, req);
-			blk_stop_queue(queue);
-			break;
-		}
-	}
-}
-
-static int blkvsc_open(struct block_device *bdev, fmode_t mode)
-{
-	struct block_device_context *blkdev = bdev->bd_disk->private_data;
-
-	DPRINT_DBG(BLKVSC_DRV, "- users %d disk %s\n", blkdev->users,
-		   blkdev->gd->disk_name);
-
-	spin_lock(&blkdev->lock);
-
-	if (!blkdev->users && blkdev->device_type == DVD_TYPE) {
-		spin_unlock(&blkdev->lock);
-		check_disk_change(bdev);
-		spin_lock(&blkdev->lock);
-	}
-
-	blkdev->users++;
-
-	spin_unlock(&blkdev->lock);
-	return 0;
-}
-
-static int blkvsc_release(struct gendisk *disk, fmode_t mode)
-{
-	struct block_device_context *blkdev = disk->private_data;
-
-	DPRINT_DBG(BLKVSC_DRV, "- users %d disk %s\n", blkdev->users,
-		   blkdev->gd->disk_name);
-
-	spin_lock(&blkdev->lock);
-	if (blkdev->users == 1) {
-		spin_unlock(&blkdev->lock);
-		blkvsc_do_flush(blkdev);
-		spin_lock(&blkdev->lock);
-	}
-
-	blkdev->users--;
-
-	spin_unlock(&blkdev->lock);
-	return 0;
-}
-
-static int blkvsc_media_changed(struct gendisk *gd)
-{
-	DPRINT_DBG(BLKVSC_DRV, "- enter\n");
-	return 1;
-}
-
-static int blkvsc_revalidate_disk(struct gendisk *gd)
-{
-	struct block_device_context *blkdev = gd->private_data;
-
-	DPRINT_DBG(BLKVSC_DRV, "- enter\n");
-
-	if (blkdev->device_type == DVD_TYPE) {
-		blkvsc_do_read_capacity(blkdev);
-		set_capacity(blkdev->gd, blkdev->capacity *
-			    (blkdev->sector_size/512));
-		blk_queue_logical_block_size(gd->queue, blkdev->sector_size);
-	}
-	return 0;
-}
-
-static int blkvsc_getgeo(struct block_device *bd, struct hd_geometry *hg)
-{
-	sector_t total_sectors = get_capacity(bd->bd_disk);
-	sector_t cylinder_times_heads = 0;
-	sector_t temp = 0;
-
-	int sectors_per_track = 0;
-	int heads = 0;
-	int cylinders = 0;
-	int rem = 0;
-
-	if (total_sectors > (65535 * 16 * 255))
-		total_sectors = (65535 * 16 * 255);
-
-	if (total_sectors >= (65535 * 16 * 63)) {
-		sectors_per_track = 255;
-		heads = 16;
-
-		cylinder_times_heads = total_sectors;
-		/* sector_div stores the quotient in cylinder_times_heads */
-		rem = sector_div(cylinder_times_heads, sectors_per_track);
-	} else {
-		sectors_per_track = 17;
-
-		cylinder_times_heads = total_sectors;
-		/* sector_div stores the quotient in cylinder_times_heads */
-		rem = sector_div(cylinder_times_heads, sectors_per_track);
-
-		temp = cylinder_times_heads + 1023;
-		/* sector_div stores the quotient in temp */
-		rem = sector_div(temp, 1024);
-
-		heads = temp;
-
-		if (heads < 4)
-			heads = 4;
-
-
-		if (cylinder_times_heads >= (heads * 1024) || (heads > 16)) {
-			sectors_per_track = 31;
-			heads = 16;
-
-			cylinder_times_heads = total_sectors;
-			/*
-			 * sector_div stores the quotient in
-			 * cylinder_times_heads
-			 */
-			rem = sector_div(cylinder_times_heads,
-					 sectors_per_track);
-		}
-
-		if (cylinder_times_heads >= (heads * 1024)) {
-			sectors_per_track = 63;
-			heads = 16;
-
-			cylinder_times_heads = total_sectors;
-			/*
-			 * sector_div stores the quotient in
-			 * cylinder_times_heads
-			 */
-			rem = sector_div(cylinder_times_heads,
-					 sectors_per_track);
-		}
-	}
-
-	temp = cylinder_times_heads;
-	/* sector_div stores the quotient in temp */
-	rem = sector_div(temp, heads);
-	cylinders = temp;
-
-	hg->heads = heads;
-	hg->sectors = sectors_per_track;
-	hg->cylinders = cylinders;
-
-	DPRINT_INFO(BLKVSC_DRV, "CHS (%d, %d, %d)", cylinders, heads,
-		    sectors_per_track);
-
-    return 0;
-}
-
-static int blkvsc_ioctl(struct block_device *bd, fmode_t mode,
-			unsigned cmd, unsigned long argument)
-{
-/*	struct block_device_context *blkdev = bd->bd_disk->private_data; */
-	int ret;
-
-	switch (cmd) {
-	/*
-	 * TODO: I think there is certain format for HDIO_GET_IDENTITY rather
-	 * than just a GUID. Commented it out for now.
-	 */
-#if 0
-	case HDIO_GET_IDENTITY:
-		DPRINT_INFO(BLKVSC_DRV, "HDIO_GET_IDENTITY\n");
-		if (copy_to_user((void __user *)arg, blkdev->device_id,
-				 blkdev->device_id_len))
-			ret = -EFAULT;
-		break;
-#endif
-	default:
-		ret = -EINVAL;
-		break;
-	}
-
-	return ret;
-}
-
-static int __init blkvsc_init(void)
-{
-	int ret;
-
-	BUILD_BUG_ON(sizeof(sector_t) != 8);
-
-	DPRINT_INFO(BLKVSC_DRV, "Blkvsc initializing....");
-
-	ret = blkvsc_drv_init(BlkVscInitialize);
-
-	return ret;
-}
-
 static void __exit blkvsc_exit(void)
 {
 	blkvsc_drv_exit();
@@ -1492,5 +1022,5 @@
 MODULE_LICENSE("GPL");
 MODULE_VERSION(HV_DRV_VERSION);
 MODULE_DESCRIPTION("Microsoft Hyper-V virtual block driver");
-module_init(blkvsc_init);
+module_init(blkvsc_drv_init);
 module_exit(blkvsc_exit);
diff --git a/drivers/staging/hv/channel.c b/drivers/staging/hv/channel.c
new file mode 100644
index 0000000..cffca7c
--- /dev/null
+++ b/drivers/staging/hv/channel.c
@@ -0,0 +1,877 @@
+/*
+ * Copyright (c) 2009, Microsoft Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * Authors:
+ *   Haiyang Zhang <haiyangz@microsoft.com>
+ *   Hank Janssen  <hjanssen@microsoft.com>
+ */
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/wait.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+
+#include "hyperv.h"
+#include "hyperv_vmbus.h"
+
+#define NUM_PAGES_SPANNED(addr, len) \
+((PAGE_ALIGN(addr + len) >> PAGE_SHIFT) - (addr >> PAGE_SHIFT))
+
+/* Internal routines */
+static int create_gpadl_header(
+	void *kbuffer,	/* must be phys and virt contiguous */
+	u32 size,	/* page-size multiple */
+	struct vmbus_channel_msginfo **msginfo,
+	u32 *messagecount);
+static void vmbus_setevent(struct vmbus_channel *channel);
+
+/*
+ * vmbus_setevent- Trigger an event notification on the specified
+ * channel.
+ */
+static void vmbus_setevent(struct vmbus_channel *channel)
+{
+	struct hv_monitor_page *monitorpage;
+
+	if (channel->offermsg.monitor_allocated) {
+		/* Each u32 represents 32 channels */
+		sync_set_bit(channel->offermsg.child_relid & 31,
+			(unsigned long *) vmbus_connection.send_int_page +
+			(channel->offermsg.child_relid >> 5));
+
+		monitorpage = vmbus_connection.monitor_pages;
+		monitorpage++; /* Get the child to parent monitor page */
+
+		sync_set_bit(channel->monitor_bit,
+			(unsigned long *)&monitorpage->trigger_group
+					[channel->monitor_grp].pending);
+
+	} else {
+		vmbus_set_event(channel->offermsg.child_relid);
+	}
+}
+
+/*
+ * vmbus_get_debug_info -Retrieve various channel debug info
+ */
+void vmbus_get_debug_info(struct vmbus_channel *channel,
+			      struct vmbus_channel_debug_info *debuginfo)
+{
+	struct hv_monitor_page *monitorpage;
+	u8 monitor_group = (u8)channel->offermsg.monitorid / 32;
+	u8 monitor_offset = (u8)channel->offermsg.monitorid % 32;
+	/* u32 monitorBit	= 1 << monitorOffset; */
+
+	debuginfo->relid = channel->offermsg.child_relid;
+	debuginfo->state = channel->state;
+	memcpy(&debuginfo->interfacetype,
+	       &channel->offermsg.offer.if_type, sizeof(struct hv_guid));
+	memcpy(&debuginfo->interface_instance,
+	       &channel->offermsg.offer.if_instance,
+	       sizeof(struct hv_guid));
+
+	monitorpage = (struct hv_monitor_page *)vmbus_connection.monitor_pages;
+
+	debuginfo->monitorid = channel->offermsg.monitorid;
+
+	debuginfo->servermonitor_pending =
+			monitorpage->trigger_group[monitor_group].pending;
+	debuginfo->servermonitor_latency =
+			monitorpage->latency[monitor_group][monitor_offset];
+	debuginfo->servermonitor_connectionid =
+			monitorpage->parameter[monitor_group]
+					[monitor_offset].connectionid.u.id;
+
+	monitorpage++;
+
+	debuginfo->clientmonitor_pending =
+			monitorpage->trigger_group[monitor_group].pending;
+	debuginfo->clientmonitor_latency =
+			monitorpage->latency[monitor_group][monitor_offset];
+	debuginfo->clientmonitor_connectionid =
+			monitorpage->parameter[monitor_group]
+					[monitor_offset].connectionid.u.id;
+
+	hv_ringbuffer_get_debuginfo(&channel->inbound, &debuginfo->inbound);
+	hv_ringbuffer_get_debuginfo(&channel->outbound, &debuginfo->outbound);
+}
+
+/*
+ * vmbus_open - Open the specified channel.
+ */
+int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size,
+		     u32 recv_ringbuffer_size, void *userdata, u32 userdatalen,
+		     void (*onchannelcallback)(void *context), void *context)
+{
+	struct vmbus_channel_open_channel *openMsg;
+	struct vmbus_channel_msginfo *openInfo = NULL;
+	void *in, *out;
+	unsigned long flags;
+	int ret, t, err = 0;
+
+	newchannel->onchannel_callback = onchannelcallback;
+	newchannel->channel_callback_context = context;
+
+	/* Allocate the ring buffer */
+	out = (void *)__get_free_pages(GFP_KERNEL|__GFP_ZERO,
+		get_order(send_ringbuffer_size + recv_ringbuffer_size));
+
+	if (!out)
+		return -ENOMEM;
+
+
+	in = (void *)((unsigned long)out + send_ringbuffer_size);
+
+	newchannel->ringbuffer_pages = out;
+	newchannel->ringbuffer_pagecount = (send_ringbuffer_size +
+					   recv_ringbuffer_size) >> PAGE_SHIFT;
+
+	ret = hv_ringbuffer_init(
+		&newchannel->outbound, out, send_ringbuffer_size);
+
+	if (ret != 0) {
+		err = ret;
+		goto errorout;
+	}
+
+	ret = hv_ringbuffer_init(
+		&newchannel->inbound, in, recv_ringbuffer_size);
+	if (ret != 0) {
+		err = ret;
+		goto errorout;
+	}
+
+
+	/* Establish the gpadl for the ring buffer */
+	newchannel->ringbuffer_gpadlhandle = 0;
+
+	ret = vmbus_establish_gpadl(newchannel,
+					 newchannel->outbound.ring_buffer,
+					 send_ringbuffer_size +
+					 recv_ringbuffer_size,
+					 &newchannel->ringbuffer_gpadlhandle);
+
+	if (ret != 0) {
+		err = ret;
+		goto errorout;
+	}
+
+	/* Create and init the channel open message */
+	openInfo = kmalloc(sizeof(*openInfo) +
+			   sizeof(struct vmbus_channel_open_channel),
+			   GFP_KERNEL);
+	if (!openInfo) {
+		err = -ENOMEM;
+		goto errorout;
+	}
+
+	init_completion(&openInfo->waitevent);
+
+	openMsg = (struct vmbus_channel_open_channel *)openInfo->msg;
+	openMsg->header.msgtype = CHANNELMSG_OPENCHANNEL;
+	openMsg->openid = newchannel->offermsg.child_relid;
+	openMsg->child_relid = newchannel->offermsg.child_relid;
+	openMsg->ringbuffer_gpadlhandle = newchannel->ringbuffer_gpadlhandle;
+	openMsg->downstream_ringbuffer_pageoffset = send_ringbuffer_size >>
+						  PAGE_SHIFT;
+	openMsg->server_contextarea_gpadlhandle = 0;
+
+	if (userdatalen > MAX_USER_DEFINED_BYTES) {
+		err = -EINVAL;
+		goto errorout;
+	}
+
+	if (userdatalen)
+		memcpy(openMsg->userdata, userdata, userdatalen);
+
+	spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
+	list_add_tail(&openInfo->msglistentry,
+		      &vmbus_connection.chn_msg_list);
+	spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
+
+	ret = vmbus_post_msg(openMsg,
+			       sizeof(struct vmbus_channel_open_channel));
+
+	if (ret != 0)
+		goto cleanup;
+
+	t = wait_for_completion_timeout(&openInfo->waitevent, HZ);
+	if (t == 0) {
+		err = -ETIMEDOUT;
+		goto errorout;
+	}
+
+
+	if (openInfo->response.open_result.status)
+		err = openInfo->response.open_result.status;
+
+cleanup:
+	spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
+	list_del(&openInfo->msglistentry);
+	spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
+
+	kfree(openInfo);
+	return err;
+
+errorout:
+	hv_ringbuffer_cleanup(&newchannel->outbound);
+	hv_ringbuffer_cleanup(&newchannel->inbound);
+	free_pages((unsigned long)out,
+		get_order(send_ringbuffer_size + recv_ringbuffer_size));
+	kfree(openInfo);
+	return err;
+}
+EXPORT_SYMBOL_GPL(vmbus_open);
+
+/*
+ * dump_gpadl_body - Dump the gpadl body message to the console for
+ * debugging purposes.
+ */
+static void dump_gpadl_body(struct vmbus_channel_gpadl_body *gpadl, u32 len)
+{
+	int i;
+	int pfncount;
+
+	pfncount = (len - sizeof(struct vmbus_channel_gpadl_body)) /
+		   sizeof(u64);
+
+	DPRINT_DBG(VMBUS, "gpadl body - len %d pfn count %d", len, pfncount);
+
+	for (i = 0; i < pfncount; i++)
+		DPRINT_DBG(VMBUS, "gpadl body  - %d) pfn %llu",
+			   i, gpadl->pfn[i]);
+}
+
+/*
+ * dump_gpadl_header - Dump the gpadl header message to the console for
+ * debugging purposes.
+ */
+static void dump_gpadl_header(struct vmbus_channel_gpadl_header *gpadl)
+{
+	int i, j;
+	int pagecount;
+
+	DPRINT_DBG(VMBUS,
+		   "gpadl header - relid %d, range count %d, range buflen %d",
+		   gpadl->child_relid, gpadl->rangecount, gpadl->range_buflen);
+	for (i = 0; i < gpadl->rangecount; i++) {
+		pagecount = gpadl->range[i].byte_count >> PAGE_SHIFT;
+		pagecount = (pagecount > 26) ? 26 : pagecount;
+
+		DPRINT_DBG(VMBUS, "gpadl range %d - len %d offset %d "
+			   "page count %d", i, gpadl->range[i].byte_count,
+			   gpadl->range[i].byte_offset, pagecount);
+
+		for (j = 0; j < pagecount; j++)
+			DPRINT_DBG(VMBUS, "%d) pfn %llu", j,
+				   gpadl->range[i].pfn_array[j]);
+	}
+}
+
+/*
+ * create_gpadl_header - Creates a gpadl for the specified buffer
+ */
+static int create_gpadl_header(void *kbuffer, u32 size,
+					 struct vmbus_channel_msginfo **msginfo,
+					 u32 *messagecount)
+{
+	int i;
+	int pagecount;
+	unsigned long long pfn;
+	struct vmbus_channel_gpadl_header *gpadl_header;
+	struct vmbus_channel_gpadl_body *gpadl_body;
+	struct vmbus_channel_msginfo *msgheader;
+	struct vmbus_channel_msginfo *msgbody = NULL;
+	u32 msgsize;
+
+	int pfnsum, pfncount, pfnleft, pfncurr, pfnsize;
+
+	pagecount = size >> PAGE_SHIFT;
+	pfn = virt_to_phys(kbuffer) >> PAGE_SHIFT;
+
+	/* do we need a gpadl body msg */
+	pfnsize = MAX_SIZE_CHANNEL_MESSAGE -
+		  sizeof(struct vmbus_channel_gpadl_header) -
+		  sizeof(struct gpa_range);
+	pfncount = pfnsize / sizeof(u64);
+
+	if (pagecount > pfncount) {
+		/* we need a gpadl body */
+		/* fill in the header */
+		msgsize = sizeof(struct vmbus_channel_msginfo) +
+			  sizeof(struct vmbus_channel_gpadl_header) +
+			  sizeof(struct gpa_range) + pfncount * sizeof(u64);
+		msgheader =  kzalloc(msgsize, GFP_KERNEL);
+		if (!msgheader)
+			goto nomem;
+
+		INIT_LIST_HEAD(&msgheader->submsglist);
+		msgheader->msgsize = msgsize;
+
+		gpadl_header = (struct vmbus_channel_gpadl_header *)
+			msgheader->msg;
+		gpadl_header->rangecount = 1;
+		gpadl_header->range_buflen = sizeof(struct gpa_range) +
+					 pagecount * sizeof(u64);
+		gpadl_header->range[0].byte_offset = 0;
+		gpadl_header->range[0].byte_count = size;
+		for (i = 0; i < pfncount; i++)
+			gpadl_header->range[0].pfn_array[i] = pfn+i;
+		*msginfo = msgheader;
+		*messagecount = 1;
+
+		pfnsum = pfncount;
+		pfnleft = pagecount - pfncount;
+
+		/* how many pfns can we fit */
+		pfnsize = MAX_SIZE_CHANNEL_MESSAGE -
+			  sizeof(struct vmbus_channel_gpadl_body);
+		pfncount = pfnsize / sizeof(u64);
+
+		/* fill in the body */
+		while (pfnleft) {
+			if (pfnleft > pfncount)
+				pfncurr = pfncount;
+			else
+				pfncurr = pfnleft;
+
+			msgsize = sizeof(struct vmbus_channel_msginfo) +
+				  sizeof(struct vmbus_channel_gpadl_body) +
+				  pfncurr * sizeof(u64);
+			msgbody = kzalloc(msgsize, GFP_KERNEL);
+
+			if (!msgbody) {
+				struct vmbus_channel_msginfo *pos = NULL;
+				struct vmbus_channel_msginfo *tmp = NULL;
+				/*
+				 * Free up all the allocated messages.
+				 */
+				list_for_each_entry_safe(pos, tmp,
+					&msgheader->submsglist,
+					msglistentry) {
+
+					list_del(&pos->msglistentry);
+					kfree(pos);
+				}
+
+				goto nomem;
+			}
+
+			msgbody->msgsize = msgsize;
+			(*messagecount)++;
+			gpadl_body =
+				(struct vmbus_channel_gpadl_body *)msgbody->msg;
+
+			/*
+			 * Gpadl is u32 and we are using a pointer which could
+			 * be 64-bit
+			 * This is governed by the guest/host protocol and
+			 * so the hypervisor gurantees that this is ok.
+			 */
+			for (i = 0; i < pfncurr; i++)
+				gpadl_body->pfn[i] = pfn + pfnsum + i;
+
+			/* add to msg header */
+			list_add_tail(&msgbody->msglistentry,
+				      &msgheader->submsglist);
+			pfnsum += pfncurr;
+			pfnleft -= pfncurr;
+		}
+	} else {
+		/* everything fits in a header */
+		msgsize = sizeof(struct vmbus_channel_msginfo) +
+			  sizeof(struct vmbus_channel_gpadl_header) +
+			  sizeof(struct gpa_range) + pagecount * sizeof(u64);
+		msgheader = kzalloc(msgsize, GFP_KERNEL);
+		if (msgheader == NULL)
+			goto nomem;
+		msgheader->msgsize = msgsize;
+
+		gpadl_header = (struct vmbus_channel_gpadl_header *)
+			msgheader->msg;
+		gpadl_header->rangecount = 1;
+		gpadl_header->range_buflen = sizeof(struct gpa_range) +
+					 pagecount * sizeof(u64);
+		gpadl_header->range[0].byte_offset = 0;
+		gpadl_header->range[0].byte_count = size;
+		for (i = 0; i < pagecount; i++)
+			gpadl_header->range[0].pfn_array[i] = pfn+i;
+
+		*msginfo = msgheader;
+		*messagecount = 1;
+	}
+
+	return 0;
+nomem:
+	kfree(msgheader);
+	kfree(msgbody);
+	return -ENOMEM;
+}
+
+/*
+ * vmbus_establish_gpadl - Estabish a GPADL for the specified buffer
+ *
+ * @channel: a channel
+ * @kbuffer: from kmalloc
+ * @size: page-size multiple
+ * @gpadl_handle: some funky thing
+ */
+int vmbus_establish_gpadl(struct vmbus_channel *channel, void *kbuffer,
+			       u32 size, u32 *gpadl_handle)
+{
+	struct vmbus_channel_gpadl_header *gpadlmsg;
+	struct vmbus_channel_gpadl_body *gpadl_body;
+	/* struct vmbus_channel_gpadl_created *gpadlCreated; */
+	struct vmbus_channel_msginfo *msginfo = NULL;
+	struct vmbus_channel_msginfo *submsginfo;
+	u32 msgcount;
+	struct list_head *curr;
+	u32 next_gpadl_handle;
+	unsigned long flags;
+	int ret = 0;
+	int t;
+
+	next_gpadl_handle = atomic_read(&vmbus_connection.next_gpadl_handle);
+	atomic_inc(&vmbus_connection.next_gpadl_handle);
+
+	ret = create_gpadl_header(kbuffer, size, &msginfo, &msgcount);
+	if (ret)
+		return ret;
+
+	init_completion(&msginfo->waitevent);
+
+	gpadlmsg = (struct vmbus_channel_gpadl_header *)msginfo->msg;
+	gpadlmsg->header.msgtype = CHANNELMSG_GPADL_HEADER;
+	gpadlmsg->child_relid = channel->offermsg.child_relid;
+	gpadlmsg->gpadl = next_gpadl_handle;
+
+	dump_gpadl_header(gpadlmsg);
+
+	spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
+	list_add_tail(&msginfo->msglistentry,
+		      &vmbus_connection.chn_msg_list);
+
+	spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
+
+	ret = vmbus_post_msg(gpadlmsg, msginfo->msgsize -
+			       sizeof(*msginfo));
+	if (ret != 0)
+		goto cleanup;
+
+	if (msgcount > 1) {
+		list_for_each(curr, &msginfo->submsglist) {
+
+			submsginfo = (struct vmbus_channel_msginfo *)curr;
+			gpadl_body =
+			     (struct vmbus_channel_gpadl_body *)submsginfo->msg;
+
+			gpadl_body->header.msgtype =
+				CHANNELMSG_GPADL_BODY;
+			gpadl_body->gpadl = next_gpadl_handle;
+
+			dump_gpadl_body(gpadl_body, submsginfo->msgsize -
+				      sizeof(*submsginfo));
+			ret = vmbus_post_msg(gpadl_body,
+					       submsginfo->msgsize -
+					       sizeof(*submsginfo));
+			if (ret != 0)
+				goto cleanup;
+
+		}
+	}
+	t = wait_for_completion_timeout(&msginfo->waitevent, 5*HZ);
+	BUG_ON(t == 0);
+
+
+	/* At this point, we received the gpadl created msg */
+	*gpadl_handle = gpadlmsg->gpadl;
+
+cleanup:
+	spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
+	list_del(&msginfo->msglistentry);
+	spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
+
+	kfree(msginfo);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(vmbus_establish_gpadl);
+
+/*
+ * vmbus_teardown_gpadl -Teardown the specified GPADL handle
+ */
+int vmbus_teardown_gpadl(struct vmbus_channel *channel, u32 gpadl_handle)
+{
+	struct vmbus_channel_gpadl_teardown *msg;
+	struct vmbus_channel_msginfo *info;
+	unsigned long flags;
+	int ret, t;
+
+	/* ASSERT(gpadl_handle != 0); */
+
+	info = kmalloc(sizeof(*info) +
+		       sizeof(struct vmbus_channel_gpadl_teardown), GFP_KERNEL);
+	if (!info)
+		return -ENOMEM;
+
+	init_completion(&info->waitevent);
+
+	msg = (struct vmbus_channel_gpadl_teardown *)info->msg;
+
+	msg->header.msgtype = CHANNELMSG_GPADL_TEARDOWN;
+	msg->child_relid = channel->offermsg.child_relid;
+	msg->gpadl = gpadl_handle;
+
+	spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
+	list_add_tail(&info->msglistentry,
+		      &vmbus_connection.chn_msg_list);
+	spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
+	ret = vmbus_post_msg(msg,
+			       sizeof(struct vmbus_channel_gpadl_teardown));
+
+	BUG_ON(ret != 0);
+	t = wait_for_completion_timeout(&info->waitevent, 5*HZ);
+	BUG_ON(t == 0);
+
+	/* Received a torndown response */
+	spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
+	list_del(&info->msglistentry);
+	spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
+
+	kfree(info);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(vmbus_teardown_gpadl);
+
+/*
+ * vmbus_close - Close the specified channel
+ */
+void vmbus_close(struct vmbus_channel *channel)
+{
+	struct vmbus_channel_close_channel *msg;
+	int ret;
+
+	/* Stop callback and cancel the timer asap */
+	channel->onchannel_callback = NULL;
+
+	/* Send a closing message */
+
+	msg = &channel->close_msg.msg;
+
+	msg->header.msgtype = CHANNELMSG_CLOSECHANNEL;
+	msg->child_relid = channel->offermsg.child_relid;
+
+	ret = vmbus_post_msg(msg, sizeof(struct vmbus_channel_close_channel));
+
+	BUG_ON(ret != 0);
+	/* Tear down the gpadl for the channel's ring buffer */
+	if (channel->ringbuffer_gpadlhandle)
+		vmbus_teardown_gpadl(channel,
+					  channel->ringbuffer_gpadlhandle);
+
+	/* Cleanup the ring buffers for this channel */
+	hv_ringbuffer_cleanup(&channel->outbound);
+	hv_ringbuffer_cleanup(&channel->inbound);
+
+	free_pages((unsigned long)channel->ringbuffer_pages,
+		get_order(channel->ringbuffer_pagecount * PAGE_SIZE));
+
+
+}
+EXPORT_SYMBOL_GPL(vmbus_close);
+
+/**
+ * vmbus_sendpacket() - Send the specified buffer on the given channel
+ * @channel: Pointer to vmbus_channel structure.
+ * @buffer: Pointer to the buffer you want to receive the data into.
+ * @bufferlen: Maximum size of what the the buffer will hold
+ * @requestid: Identifier of the request
+ * @type: Type of packet that is being send e.g. negotiate, time
+ * packet etc.
+ *
+ * Sends data in @buffer directly to hyper-v via the vmbus
+ * This will send the data unparsed to hyper-v.
+ *
+ * Mainly used by Hyper-V drivers.
+ */
+int vmbus_sendpacket(struct vmbus_channel *channel, const void *buffer,
+			   u32 bufferlen, u64 requestid,
+			   enum vmbus_packet_type type, u32 flags)
+{
+	struct vmpacket_descriptor desc;
+	u32 packetlen = sizeof(struct vmpacket_descriptor) + bufferlen;
+	u32 packetlen_aligned = ALIGN(packetlen, sizeof(u64));
+	struct scatterlist bufferlist[3];
+	u64 aligned_data = 0;
+	int ret;
+
+
+	/* Setup the descriptor */
+	desc.type = type; /* VmbusPacketTypeDataInBand; */
+	desc.flags = flags; /* VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED; */
+	/* in 8-bytes granularity */
+	desc.offset8 = sizeof(struct vmpacket_descriptor) >> 3;
+	desc.len8 = (u16)(packetlen_aligned >> 3);
+	desc.trans_id = requestid;
+
+	sg_init_table(bufferlist, 3);
+	sg_set_buf(&bufferlist[0], &desc, sizeof(struct vmpacket_descriptor));
+	sg_set_buf(&bufferlist[1], buffer, bufferlen);
+	sg_set_buf(&bufferlist[2], &aligned_data,
+		   packetlen_aligned - packetlen);
+
+	ret = hv_ringbuffer_write(&channel->outbound, bufferlist, 3);
+
+	if (ret == 0 && !hv_get_ringbuffer_interrupt_mask(&channel->outbound))
+		vmbus_setevent(channel);
+
+	return ret;
+}
+EXPORT_SYMBOL(vmbus_sendpacket);
+
+/*
+ * vmbus_sendpacket_pagebuffer - Send a range of single-page buffer
+ * packets using a GPADL Direct packet type.
+ */
+int vmbus_sendpacket_pagebuffer(struct vmbus_channel *channel,
+				     struct hv_page_buffer pagebuffers[],
+				     u32 pagecount, void *buffer, u32 bufferlen,
+				     u64 requestid)
+{
+	int ret;
+	int i;
+	struct vmbus_channel_packet_page_buffer desc;
+	u32 descsize;
+	u32 packetlen;
+	u32 packetlen_aligned;
+	struct scatterlist bufferlist[3];
+	u64 aligned_data = 0;
+
+	if (pagecount > MAX_PAGE_BUFFER_COUNT)
+		return -EINVAL;
+
+
+	/*
+	 * Adjust the size down since vmbus_channel_packet_page_buffer is the
+	 * largest size we support
+	 */
+	descsize = sizeof(struct vmbus_channel_packet_page_buffer) -
+			  ((MAX_PAGE_BUFFER_COUNT - pagecount) *
+			  sizeof(struct hv_page_buffer));
+	packetlen = descsize + bufferlen;
+	packetlen_aligned = ALIGN(packetlen, sizeof(u64));
+
+	/* Setup the descriptor */
+	desc.type = VM_PKT_DATA_USING_GPA_DIRECT;
+	desc.flags = VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED;
+	desc.dataoffset8 = descsize >> 3; /* in 8-bytes grandularity */
+	desc.length8 = (u16)(packetlen_aligned >> 3);
+	desc.transactionid = requestid;
+	desc.rangecount = pagecount;
+
+	for (i = 0; i < pagecount; i++) {
+		desc.range[i].len = pagebuffers[i].len;
+		desc.range[i].offset = pagebuffers[i].offset;
+		desc.range[i].pfn	 = pagebuffers[i].pfn;
+	}
+
+	sg_init_table(bufferlist, 3);
+	sg_set_buf(&bufferlist[0], &desc, descsize);
+	sg_set_buf(&bufferlist[1], buffer, bufferlen);
+	sg_set_buf(&bufferlist[2], &aligned_data,
+		packetlen_aligned - packetlen);
+
+	ret = hv_ringbuffer_write(&channel->outbound, bufferlist, 3);
+
+	if (ret == 0 && !hv_get_ringbuffer_interrupt_mask(&channel->outbound))
+		vmbus_setevent(channel);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(vmbus_sendpacket_pagebuffer);
+
+/*
+ * vmbus_sendpacket_multipagebuffer - Send a multi-page buffer packet
+ * using a GPADL Direct packet type.
+ */
+int vmbus_sendpacket_multipagebuffer(struct vmbus_channel *channel,
+				struct hv_multipage_buffer *multi_pagebuffer,
+				void *buffer, u32 bufferlen, u64 requestid)
+{
+	int ret;
+	struct vmbus_channel_packet_multipage_buffer desc;
+	u32 descsize;
+	u32 packetlen;
+	u32 packetlen_aligned;
+	struct scatterlist bufferlist[3];
+	u64 aligned_data = 0;
+	u32 pfncount = NUM_PAGES_SPANNED(multi_pagebuffer->offset,
+					 multi_pagebuffer->len);
+
+
+	if ((pfncount < 0) || (pfncount > MAX_MULTIPAGE_BUFFER_COUNT))
+		return -EINVAL;
+
+	/*
+	 * Adjust the size down since vmbus_channel_packet_multipage_buffer is
+	 * the largest size we support
+	 */
+	descsize = sizeof(struct vmbus_channel_packet_multipage_buffer) -
+			  ((MAX_MULTIPAGE_BUFFER_COUNT - pfncount) *
+			  sizeof(u64));
+	packetlen = descsize + bufferlen;
+	packetlen_aligned = ALIGN(packetlen, sizeof(u64));
+
+
+	/* Setup the descriptor */
+	desc.type = VM_PKT_DATA_USING_GPA_DIRECT;
+	desc.flags = VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED;
+	desc.dataoffset8 = descsize >> 3; /* in 8-bytes grandularity */
+	desc.length8 = (u16)(packetlen_aligned >> 3);
+	desc.transactionid = requestid;
+	desc.rangecount = 1;
+
+	desc.range.len = multi_pagebuffer->len;
+	desc.range.offset = multi_pagebuffer->offset;
+
+	memcpy(desc.range.pfn_array, multi_pagebuffer->pfn_array,
+	       pfncount * sizeof(u64));
+
+	sg_init_table(bufferlist, 3);
+	sg_set_buf(&bufferlist[0], &desc, descsize);
+	sg_set_buf(&bufferlist[1], buffer, bufferlen);
+	sg_set_buf(&bufferlist[2], &aligned_data,
+		packetlen_aligned - packetlen);
+
+	ret = hv_ringbuffer_write(&channel->outbound, bufferlist, 3);
+
+	if (ret == 0 && !hv_get_ringbuffer_interrupt_mask(&channel->outbound))
+		vmbus_setevent(channel);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(vmbus_sendpacket_multipagebuffer);
+
+/**
+ * vmbus_recvpacket() - Retrieve the user packet on the specified channel
+ * @channel: Pointer to vmbus_channel structure.
+ * @buffer: Pointer to the buffer you want to receive the data into.
+ * @bufferlen: Maximum size of what the the buffer will hold
+ * @buffer_actual_len: The actual size of the data after it was received
+ * @requestid: Identifier of the request
+ *
+ * Receives directly from the hyper-v vmbus and puts the data it received
+ * into Buffer. This will receive the data unparsed from hyper-v.
+ *
+ * Mainly used by Hyper-V drivers.
+ */
+int vmbus_recvpacket(struct vmbus_channel *channel, void *buffer,
+			u32 bufferlen, u32 *buffer_actual_len, u64 *requestid)
+{
+	struct vmpacket_descriptor desc;
+	u32 packetlen;
+	u32 userlen;
+	int ret;
+	unsigned long flags;
+
+	*buffer_actual_len = 0;
+	*requestid = 0;
+
+	spin_lock_irqsave(&channel->inbound_lock, flags);
+
+	ret = hv_ringbuffer_peek(&channel->inbound, &desc,
+			     sizeof(struct vmpacket_descriptor));
+	if (ret != 0) {
+		spin_unlock_irqrestore(&channel->inbound_lock, flags);
+		return 0;
+	}
+
+	packetlen = desc.len8 << 3;
+	userlen = packetlen - (desc.offset8 << 3);
+
+	*buffer_actual_len = userlen;
+
+	if (userlen > bufferlen) {
+		spin_unlock_irqrestore(&channel->inbound_lock, flags);
+
+		pr_err("Buffer too small - got %d needs %d\n",
+			   bufferlen, userlen);
+		return -ETOOSMALL;
+	}
+
+	*requestid = desc.trans_id;
+
+	/* Copy over the packet to the user buffer */
+	ret = hv_ringbuffer_read(&channel->inbound, buffer, userlen,
+			     (desc.offset8 << 3));
+
+	spin_unlock_irqrestore(&channel->inbound_lock, flags);
+
+	return 0;
+}
+EXPORT_SYMBOL(vmbus_recvpacket);
+
+/*
+ * vmbus_recvpacket_raw - Retrieve the raw packet on the specified channel
+ */
+int vmbus_recvpacket_raw(struct vmbus_channel *channel, void *buffer,
+			      u32 bufferlen, u32 *buffer_actual_len,
+			      u64 *requestid)
+{
+	struct vmpacket_descriptor desc;
+	u32 packetlen;
+	u32 userlen;
+	int ret;
+	unsigned long flags;
+
+	*buffer_actual_len = 0;
+	*requestid = 0;
+
+	spin_lock_irqsave(&channel->inbound_lock, flags);
+
+	ret = hv_ringbuffer_peek(&channel->inbound, &desc,
+			     sizeof(struct vmpacket_descriptor));
+	if (ret != 0) {
+		spin_unlock_irqrestore(&channel->inbound_lock, flags);
+		return 0;
+	}
+
+
+	packetlen = desc.len8 << 3;
+	userlen = packetlen - (desc.offset8 << 3);
+
+	*buffer_actual_len = packetlen;
+
+	if (packetlen > bufferlen) {
+		spin_unlock_irqrestore(&channel->inbound_lock, flags);
+
+		pr_err("Buffer too small - needed %d bytes but "
+			"got space for only %d bytes\n",
+			packetlen, bufferlen);
+		return -2;
+	}
+
+	*requestid = desc.trans_id;
+
+	/* Copy over the entire packet to the user buffer */
+	ret = hv_ringbuffer_read(&channel->inbound, buffer, packetlen, 0);
+
+	spin_unlock_irqrestore(&channel->inbound_lock, flags);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(vmbus_recvpacket_raw);
diff --git a/drivers/staging/hv/channel_mgmt.c b/drivers/staging/hv/channel_mgmt.c
new file mode 100644
index 0000000..bf011f3
--- /dev/null
+++ b/drivers/staging/hv/channel_mgmt.c
@@ -0,0 +1,784 @@
+/*
+ * Copyright (c) 2009, Microsoft Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * Authors:
+ *   Haiyang Zhang <haiyangz@microsoft.com>
+ *   Hank Janssen  <hjanssen@microsoft.com>
+ */
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/wait.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/completion.h>
+
+#include "hyperv.h"
+#include "hyperv_vmbus.h"
+
+struct vmbus_channel_message_table_entry {
+	enum vmbus_channel_message_type message_type;
+	void (*message_handler)(struct vmbus_channel_message_header *msg);
+};
+
+#define MAX_MSG_TYPES                    4
+#define MAX_NUM_DEVICE_CLASSES_SUPPORTED 8
+
+static const struct hv_guid
+	supported_device_classes[MAX_NUM_DEVICE_CLASSES_SUPPORTED] = {
+	/* {ba6163d9-04a1-4d29-b605-72e2ffb1dc7f} */
+	/* Storage - SCSI */
+	{
+		.data  = {
+			0xd9, 0x63, 0x61, 0xba, 0xa1, 0x04, 0x29, 0x4d,
+			0xb6, 0x05, 0x72, 0xe2, 0xff, 0xb1, 0xdc, 0x7f
+		}
+	},
+
+	/* {F8615163-DF3E-46c5-913F-F2D2F965ED0E} */
+	/* Network */
+	{
+		.data = {
+			0x63, 0x51, 0x61, 0xF8, 0x3E, 0xDF, 0xc5, 0x46,
+			0x91, 0x3F, 0xF2, 0xD2, 0xF9, 0x65, 0xED, 0x0E
+		}
+	},
+
+	/* {CFA8B69E-5B4A-4cc0-B98B-8BA1A1F3F95A} */
+	/* Input */
+	{
+		.data = {
+			0x9E, 0xB6, 0xA8, 0xCF, 0x4A, 0x5B, 0xc0, 0x4c,
+			0xB9, 0x8B, 0x8B, 0xA1, 0xA1, 0xF3, 0xF9, 0x5A
+		}
+	},
+
+	/* {32412632-86cb-44a2-9b5c-50d1417354f5} */
+	/* IDE */
+	{
+		.data = {
+			0x32, 0x26, 0x41, 0x32, 0xcb, 0x86, 0xa2, 0x44,
+			0x9b, 0x5c, 0x50, 0xd1, 0x41, 0x73, 0x54, 0xf5
+		}
+	},
+	/* 0E0B6031-5213-4934-818B-38D90CED39DB */
+	/* Shutdown */
+	{
+		.data = {
+			0x31, 0x60, 0x0B, 0X0E, 0x13, 0x52, 0x34, 0x49,
+			0x81, 0x8B, 0x38, 0XD9, 0x0C, 0xED, 0x39, 0xDB
+		}
+	},
+	/* {9527E630-D0AE-497b-ADCE-E80AB0175CAF} */
+	/* TimeSync */
+	{
+		.data = {
+			0x30, 0xe6, 0x27, 0x95, 0xae, 0xd0, 0x7b, 0x49,
+			0xad, 0xce, 0xe8, 0x0a, 0xb0, 0x17, 0x5c, 0xaf
+		}
+	},
+	/* {57164f39-9115-4e78-ab55-382f3bd5422d} */
+	/* Heartbeat */
+	{
+		.data = {
+			0x39, 0x4f, 0x16, 0x57, 0x15, 0x91, 0x78, 0x4e,
+			0xab, 0x55, 0x38, 0x2f, 0x3b, 0xd5, 0x42, 0x2d
+		}
+	},
+	/* {A9A0F4E7-5A45-4d96-B827-8A841E8C03E6} */
+	/* KVP */
+	{
+		.data = {
+			0xe7, 0xf4, 0xa0, 0xa9, 0x45, 0x5a, 0x96, 0x4d,
+			0xb8, 0x27, 0x8a, 0x84, 0x1e, 0x8c, 0x3,  0xe6
+	}
+	},
+
+};
+
+
+/**
+ * prep_negotiate_resp() - Create default response for Hyper-V Negotiate message
+ * @icmsghdrp: Pointer to msg header structure
+ * @icmsg_negotiate: Pointer to negotiate message structure
+ * @buf: Raw buffer channel data
+ *
+ * @icmsghdrp is of type &struct icmsg_hdr.
+ * @negop is of type &struct icmsg_negotiate.
+ * Set up and fill in default negotiate response message. This response can
+ * come from both the vmbus driver and the hv_utils driver. The current api
+ * will respond properly to both Windows 2008 and Windows 2008-R2 operating
+ * systems.
+ *
+ * Mainly used by Hyper-V drivers.
+ */
+void prep_negotiate_resp(struct icmsg_hdr *icmsghdrp,
+			     struct icmsg_negotiate *negop,
+			     u8 *buf)
+{
+	if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
+		icmsghdrp->icmsgsize = 0x10;
+
+		negop = (struct icmsg_negotiate *)&buf[
+			sizeof(struct vmbuspipe_hdr) +
+			sizeof(struct icmsg_hdr)];
+
+		if (negop->icframe_vercnt == 2 &&
+		   negop->icversion_data[1].major == 3) {
+			negop->icversion_data[0].major = 3;
+			negop->icversion_data[0].minor = 0;
+			negop->icversion_data[1].major = 3;
+			negop->icversion_data[1].minor = 0;
+		} else {
+			negop->icversion_data[0].major = 1;
+			negop->icversion_data[0].minor = 0;
+			negop->icversion_data[1].major = 1;
+			negop->icversion_data[1].minor = 0;
+		}
+
+		negop->icframe_vercnt = 1;
+		negop->icmsg_vercnt = 1;
+	}
+}
+EXPORT_SYMBOL(prep_negotiate_resp);
+
+/**
+ * chn_cb_negotiate() - Default handler for non IDE/SCSI/NETWORK
+ * Hyper-V requests
+ * @context: Pointer to argument structure.
+ *
+ * Set up the default handler for non device driver specific requests
+ * from Hyper-V. This stub responds to the default negotiate messages
+ * that come in for every non IDE/SCSI/Network request.
+ * This behavior is normally overwritten in the hv_utils driver. That
+ * driver handles requests like graceful shutdown, heartbeats etc.
+ *
+ * Mainly used by Hyper-V drivers.
+ */
+void chn_cb_negotiate(void *context)
+{
+	struct vmbus_channel *channel = context;
+	u8 *buf;
+	u32 buflen, recvlen;
+	u64 requestid;
+
+	struct icmsg_hdr *icmsghdrp;
+	struct icmsg_negotiate *negop = NULL;
+
+	if (channel->util_index >= 0) {
+		/*
+		 * This is a properly initialized util channel.
+		 * Route this callback appropriately and setup state
+		 * so that we don't need to reroute again.
+		 */
+		if (hv_cb_utils[channel->util_index].callback != NULL) {
+			/*
+			 * The util driver has established a handler for
+			 * this service; do the magic.
+			 */
+			channel->onchannel_callback =
+			hv_cb_utils[channel->util_index].callback;
+			(hv_cb_utils[channel->util_index].callback)(channel);
+			return;
+		}
+	}
+
+	buflen = PAGE_SIZE;
+	buf = kmalloc(buflen, GFP_ATOMIC);
+
+	vmbus_recvpacket(channel, buf, buflen, &recvlen, &requestid);
+
+	if (recvlen > 0) {
+		icmsghdrp = (struct icmsg_hdr *)&buf[
+			sizeof(struct vmbuspipe_hdr)];
+
+		prep_negotiate_resp(icmsghdrp, negop, buf);
+
+		icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION
+			| ICMSGHDRFLAG_RESPONSE;
+
+		vmbus_sendpacket(channel, buf,
+				       recvlen, requestid,
+				       VM_PKT_DATA_INBAND, 0);
+	}
+
+	kfree(buf);
+}
+EXPORT_SYMBOL(chn_cb_negotiate);
+
+/*
+ * Function table used for message responses for non IDE/SCSI/Network type
+ * messages. (Such as KVP/Shutdown etc)
+ */
+struct hyperv_service_callback hv_cb_utils[MAX_MSG_TYPES] = {
+	/* 0E0B6031-5213-4934-818B-38D90CED39DB */
+	/* Shutdown */
+	{
+		.msg_type = HV_SHUTDOWN_MSG,
+		.data = {
+			0x31, 0x60, 0x0B, 0X0E, 0x13, 0x52, 0x34, 0x49,
+			0x81, 0x8B, 0x38, 0XD9, 0x0C, 0xED, 0x39, 0xDB
+		},
+		.log_msg = "Shutdown channel functionality initialized"
+	},
+
+	/* {9527E630-D0AE-497b-ADCE-E80AB0175CAF} */
+	/* TimeSync */
+	{
+		.msg_type = HV_TIMESYNC_MSG,
+		.data = {
+			0x30, 0xe6, 0x27, 0x95, 0xae, 0xd0, 0x7b, 0x49,
+			0xad, 0xce, 0xe8, 0x0a, 0xb0, 0x17, 0x5c, 0xaf
+		},
+		.log_msg = "Timesync channel functionality initialized"
+	},
+	/* {57164f39-9115-4e78-ab55-382f3bd5422d} */
+	/* Heartbeat */
+	{
+		.msg_type = HV_HEARTBEAT_MSG,
+		.data = {
+			0x39, 0x4f, 0x16, 0x57, 0x15, 0x91, 0x78, 0x4e,
+			0xab, 0x55, 0x38, 0x2f, 0x3b, 0xd5, 0x42, 0x2d
+		},
+		.log_msg = "Heartbeat channel functionality initialized"
+	},
+	/* {A9A0F4E7-5A45-4d96-B827-8A841E8C03E6} */
+	/* KVP */
+	{
+		.data = {
+			0xe7, 0xf4, 0xa0, 0xa9, 0x45, 0x5a, 0x96, 0x4d,
+			0xb8, 0x27, 0x8a, 0x84, 0x1e, 0x8c, 0x3,  0xe6
+		},
+		.log_msg = "KVP channel functionality initialized"
+	},
+};
+EXPORT_SYMBOL(hv_cb_utils);
+
+/*
+ * alloc_channel - Allocate and initialize a vmbus channel object
+ */
+static struct vmbus_channel *alloc_channel(void)
+{
+	struct vmbus_channel *channel;
+
+	channel = kzalloc(sizeof(*channel), GFP_ATOMIC);
+	if (!channel)
+		return NULL;
+
+	spin_lock_init(&channel->inbound_lock);
+
+	channel->controlwq = create_workqueue("hv_vmbus_ctl");
+	if (!channel->controlwq) {
+		kfree(channel);
+		return NULL;
+	}
+
+	return channel;
+}
+
+/*
+ * release_hannel - Release the vmbus channel object itself
+ */
+static void release_channel(struct work_struct *work)
+{
+	struct vmbus_channel *channel = container_of(work,
+						     struct vmbus_channel,
+						     work);
+
+	destroy_workqueue(channel->controlwq);
+
+	kfree(channel);
+}
+
+/*
+ * free_channel - Release the resources used by the vmbus channel object
+ */
+void free_channel(struct vmbus_channel *channel)
+{
+
+	/*
+	 * We have to release the channel's workqueue/thread in the vmbus's
+	 * workqueue/thread context
+	 * ie we can't destroy ourselves.
+	 */
+	INIT_WORK(&channel->work, release_channel);
+	queue_work(vmbus_connection.work_queue, &channel->work);
+}
+
+
+
+/*
+ * vmbus_process_rescind_offer -
+ * Rescind the offer by initiating a device removal
+ */
+static void vmbus_process_rescind_offer(struct work_struct *work)
+{
+	struct vmbus_channel *channel = container_of(work,
+						     struct vmbus_channel,
+						     work);
+
+	vmbus_child_device_unregister(channel->device_obj);
+}
+
+/*
+ * vmbus_process_offer - Process the offer by creating a channel/device
+ * associated with this offer
+ */
+static void vmbus_process_offer(struct work_struct *work)
+{
+	struct vmbus_channel *newchannel = container_of(work,
+							struct vmbus_channel,
+							work);
+	struct vmbus_channel *channel;
+	bool fnew = true;
+	int ret;
+	int cnt;
+	unsigned long flags;
+
+	/* The next possible work is rescind handling */
+	INIT_WORK(&newchannel->work, vmbus_process_rescind_offer);
+
+	/* Make sure this is a new offer */
+	spin_lock_irqsave(&vmbus_connection.channel_lock, flags);
+
+	list_for_each_entry(channel, &vmbus_connection.chn_list, listentry) {
+		if (!memcmp(&channel->offermsg.offer.if_type,
+			    &newchannel->offermsg.offer.if_type,
+			    sizeof(struct hv_guid)) &&
+		    !memcmp(&channel->offermsg.offer.if_instance,
+			    &newchannel->offermsg.offer.if_instance,
+			    sizeof(struct hv_guid))) {
+			fnew = false;
+			break;
+		}
+	}
+
+	if (fnew)
+		list_add_tail(&newchannel->listentry,
+			      &vmbus_connection.chn_list);
+
+	spin_unlock_irqrestore(&vmbus_connection.channel_lock, flags);
+
+	if (!fnew) {
+		free_channel(newchannel);
+		return;
+	}
+
+	/*
+	 * Start the process of binding this offer to the driver
+	 * We need to set the DeviceObject field before calling
+	 * vmbus_child_dev_add()
+	 */
+	newchannel->device_obj = vmbus_child_device_create(
+		&newchannel->offermsg.offer.if_type,
+		&newchannel->offermsg.offer.if_instance,
+		newchannel);
+
+	/*
+	 * Add the new device to the bus. This will kick off device-driver
+	 * binding which eventually invokes the device driver's AddDevice()
+	 * method.
+	 */
+	ret = vmbus_child_device_register(newchannel->device_obj);
+	if (ret != 0) {
+		pr_err("unable to add child device object (relid %d)\n",
+			   newchannel->offermsg.child_relid);
+
+		spin_lock_irqsave(&vmbus_connection.channel_lock, flags);
+		list_del(&newchannel->listentry);
+		spin_unlock_irqrestore(&vmbus_connection.channel_lock, flags);
+
+		free_channel(newchannel);
+	} else {
+		/*
+		 * This state is used to indicate a successful open
+		 * so that when we do close the channel normally, we
+		 * can cleanup properly
+		 */
+		newchannel->state = CHANNEL_OPEN_STATE;
+		newchannel->util_index = -1; /* Invalid index */
+
+		/* Open IC channels */
+		for (cnt = 0; cnt < MAX_MSG_TYPES; cnt++) {
+			if (memcmp(&newchannel->offermsg.offer.if_type,
+				   &hv_cb_utils[cnt].data,
+				   sizeof(struct hv_guid)) == 0 &&
+				vmbus_open(newchannel, 2 * PAGE_SIZE,
+						 2 * PAGE_SIZE, NULL, 0,
+						 chn_cb_negotiate,
+						 newchannel) == 0) {
+				hv_cb_utils[cnt].channel = newchannel;
+				newchannel->util_index = cnt;
+
+				pr_info("%s\n", hv_cb_utils[cnt].log_msg);
+
+			}
+		}
+	}
+}
+
+/*
+ * vmbus_onoffer - Handler for channel offers from vmbus in parent partition.
+ *
+ * We ignore all offers except network and storage offers. For each network and
+ * storage offers, we create a channel object and queue a work item to the
+ * channel object to process the offer synchronously
+ */
+static void vmbus_onoffer(struct vmbus_channel_message_header *hdr)
+{
+	struct vmbus_channel_offer_channel *offer;
+	struct vmbus_channel *newchannel;
+	struct hv_guid *guidtype;
+	struct hv_guid *guidinstance;
+	int i;
+	int fsupported = 0;
+
+	offer = (struct vmbus_channel_offer_channel *)hdr;
+	for (i = 0; i < MAX_NUM_DEVICE_CLASSES_SUPPORTED; i++) {
+		if (memcmp(&offer->offer.if_type,
+			&supported_device_classes[i],
+			sizeof(struct hv_guid)) == 0) {
+			fsupported = 1;
+			break;
+		}
+	}
+
+	if (!fsupported)
+		return;
+
+	guidtype = &offer->offer.if_type;
+	guidinstance = &offer->offer.if_instance;
+
+	/* Allocate the channel object and save this offer. */
+	newchannel = alloc_channel();
+	if (!newchannel) {
+		pr_err("Unable to allocate channel object\n");
+		return;
+	}
+
+	memcpy(&newchannel->offermsg, offer,
+	       sizeof(struct vmbus_channel_offer_channel));
+	newchannel->monitor_grp = (u8)offer->monitorid / 32;
+	newchannel->monitor_bit = (u8)offer->monitorid % 32;
+
+	INIT_WORK(&newchannel->work, vmbus_process_offer);
+	queue_work(newchannel->controlwq, &newchannel->work);
+}
+
+/*
+ * vmbus_onoffer_rescind - Rescind offer handler.
+ *
+ * We queue a work item to process this offer synchronously
+ */
+static void vmbus_onoffer_rescind(struct vmbus_channel_message_header *hdr)
+{
+	struct vmbus_channel_rescind_offer *rescind;
+	struct vmbus_channel *channel;
+
+	rescind = (struct vmbus_channel_rescind_offer *)hdr;
+	channel = relid2channel(rescind->child_relid);
+
+	if (channel == NULL)
+		/* Just return here, no channel found */
+		return;
+
+	/* work is initialized for vmbus_process_rescind_offer() from
+	 * vmbus_process_offer() where the channel got created */
+	queue_work(channel->controlwq, &channel->work);
+}
+
+/*
+ * vmbus_onoffers_delivered -
+ * This is invoked when all offers have been delivered.
+ *
+ * Nothing to do here.
+ */
+static void vmbus_onoffers_delivered(
+			struct vmbus_channel_message_header *hdr)
+{
+}
+
+/*
+ * vmbus_onopen_result - Open result handler.
+ *
+ * This is invoked when we received a response to our channel open request.
+ * Find the matching request, copy the response and signal the requesting
+ * thread.
+ */
+static void vmbus_onopen_result(struct vmbus_channel_message_header *hdr)
+{
+	struct vmbus_channel_open_result *result;
+	struct vmbus_channel_msginfo *msginfo;
+	struct vmbus_channel_message_header *requestheader;
+	struct vmbus_channel_open_channel *openmsg;
+	unsigned long flags;
+
+	result = (struct vmbus_channel_open_result *)hdr;
+
+	/*
+	 * Find the open msg, copy the result and signal/unblock the wait event
+	 */
+	spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
+
+	list_for_each_entry(msginfo, &vmbus_connection.chn_msg_list,
+				msglistentry) {
+		requestheader =
+			(struct vmbus_channel_message_header *)msginfo->msg;
+
+		if (requestheader->msgtype == CHANNELMSG_OPENCHANNEL) {
+			openmsg =
+			(struct vmbus_channel_open_channel *)msginfo->msg;
+			if (openmsg->child_relid == result->child_relid &&
+			    openmsg->openid == result->openid) {
+				memcpy(&msginfo->response.open_result,
+				       result,
+				       sizeof(
+					struct vmbus_channel_open_result));
+				complete(&msginfo->waitevent);
+				break;
+			}
+		}
+	}
+	spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
+}
+
+/*
+ * vmbus_ongpadl_created - GPADL created handler.
+ *
+ * This is invoked when we received a response to our gpadl create request.
+ * Find the matching request, copy the response and signal the requesting
+ * thread.
+ */
+static void vmbus_ongpadl_created(struct vmbus_channel_message_header *hdr)
+{
+	struct vmbus_channel_gpadl_created *gpadlcreated;
+	struct vmbus_channel_msginfo *msginfo;
+	struct vmbus_channel_message_header *requestheader;
+	struct vmbus_channel_gpadl_header *gpadlheader;
+	unsigned long flags;
+
+	gpadlcreated = (struct vmbus_channel_gpadl_created *)hdr;
+
+	/*
+	 * Find the establish msg, copy the result and signal/unblock the wait
+	 * event
+	 */
+	spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
+
+	list_for_each_entry(msginfo, &vmbus_connection.chn_msg_list,
+				msglistentry) {
+		requestheader =
+			(struct vmbus_channel_message_header *)msginfo->msg;
+
+		if (requestheader->msgtype == CHANNELMSG_GPADL_HEADER) {
+			gpadlheader =
+			(struct vmbus_channel_gpadl_header *)requestheader;
+
+			if ((gpadlcreated->child_relid ==
+			     gpadlheader->child_relid) &&
+			    (gpadlcreated->gpadl == gpadlheader->gpadl)) {
+				memcpy(&msginfo->response.gpadl_created,
+				       gpadlcreated,
+				       sizeof(
+					struct vmbus_channel_gpadl_created));
+				complete(&msginfo->waitevent);
+				break;
+			}
+		}
+	}
+	spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
+}
+
+/*
+ * vmbus_ongpadl_torndown - GPADL torndown handler.
+ *
+ * This is invoked when we received a response to our gpadl teardown request.
+ * Find the matching request, copy the response and signal the requesting
+ * thread.
+ */
+static void vmbus_ongpadl_torndown(
+			struct vmbus_channel_message_header *hdr)
+{
+	struct vmbus_channel_gpadl_torndown *gpadl_torndown;
+	struct vmbus_channel_msginfo *msginfo;
+	struct vmbus_channel_message_header *requestheader;
+	struct vmbus_channel_gpadl_teardown *gpadl_teardown;
+	unsigned long flags;
+
+	gpadl_torndown = (struct vmbus_channel_gpadl_torndown *)hdr;
+
+	/*
+	 * Find the open msg, copy the result and signal/unblock the wait event
+	 */
+	spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
+
+	list_for_each_entry(msginfo, &vmbus_connection.chn_msg_list,
+				msglistentry) {
+		requestheader =
+			(struct vmbus_channel_message_header *)msginfo->msg;
+
+		if (requestheader->msgtype == CHANNELMSG_GPADL_TEARDOWN) {
+			gpadl_teardown =
+			(struct vmbus_channel_gpadl_teardown *)requestheader;
+
+			if (gpadl_torndown->gpadl == gpadl_teardown->gpadl) {
+				memcpy(&msginfo->response.gpadl_torndown,
+				       gpadl_torndown,
+				       sizeof(
+					struct vmbus_channel_gpadl_torndown));
+				complete(&msginfo->waitevent);
+				break;
+			}
+		}
+	}
+	spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
+}
+
+/*
+ * vmbus_onversion_response - Version response handler
+ *
+ * This is invoked when we received a response to our initiate contact request.
+ * Find the matching request, copy the response and signal the requesting
+ * thread.
+ */
+static void vmbus_onversion_response(
+		struct vmbus_channel_message_header *hdr)
+{
+	struct vmbus_channel_msginfo *msginfo;
+	struct vmbus_channel_message_header *requestheader;
+	struct vmbus_channel_initiate_contact *initiate;
+	struct vmbus_channel_version_response *version_response;
+	unsigned long flags;
+
+	version_response = (struct vmbus_channel_version_response *)hdr;
+	spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
+
+	list_for_each_entry(msginfo, &vmbus_connection.chn_msg_list,
+				msglistentry) {
+		requestheader =
+			(struct vmbus_channel_message_header *)msginfo->msg;
+
+		if (requestheader->msgtype ==
+		    CHANNELMSG_INITIATE_CONTACT) {
+			initiate =
+			(struct vmbus_channel_initiate_contact *)requestheader;
+			memcpy(&msginfo->response.version_response,
+			      version_response,
+			      sizeof(struct vmbus_channel_version_response));
+			complete(&msginfo->waitevent);
+		}
+	}
+	spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
+}
+
+/* Channel message dispatch table */
+static struct vmbus_channel_message_table_entry
+	channel_message_table[CHANNELMSG_COUNT] = {
+	{CHANNELMSG_INVALID,			NULL},
+	{CHANNELMSG_OFFERCHANNEL,		vmbus_onoffer},
+	{CHANNELMSG_RESCIND_CHANNELOFFER,	vmbus_onoffer_rescind},
+	{CHANNELMSG_REQUESTOFFERS,		NULL},
+	{CHANNELMSG_ALLOFFERS_DELIVERED,	vmbus_onoffers_delivered},
+	{CHANNELMSG_OPENCHANNEL,		NULL},
+	{CHANNELMSG_OPENCHANNEL_RESULT,	vmbus_onopen_result},
+	{CHANNELMSG_CLOSECHANNEL,		NULL},
+	{CHANNELMSG_GPADL_HEADER,		NULL},
+	{CHANNELMSG_GPADL_BODY,		NULL},
+	{CHANNELMSG_GPADL_CREATED,		vmbus_ongpadl_created},
+	{CHANNELMSG_GPADL_TEARDOWN,		NULL},
+	{CHANNELMSG_GPADL_TORNDOWN,		vmbus_ongpadl_torndown},
+	{CHANNELMSG_RELID_RELEASED,		NULL},
+	{CHANNELMSG_INITIATE_CONTACT,		NULL},
+	{CHANNELMSG_VERSION_RESPONSE,		vmbus_onversion_response},
+	{CHANNELMSG_UNLOAD,			NULL},
+};
+
+/*
+ * vmbus_onmessage - Handler for channel protocol messages.
+ *
+ * This is invoked in the vmbus worker thread context.
+ */
+void vmbus_onmessage(void *context)
+{
+	struct hv_message *msg = context;
+	struct vmbus_channel_message_header *hdr;
+	int size;
+
+	hdr = (struct vmbus_channel_message_header *)msg->u.payload;
+	size = msg->header.payload_size;
+
+	if (hdr->msgtype >= CHANNELMSG_COUNT) {
+		pr_err("Received invalid channel message type %d size %d\n",
+			   hdr->msgtype, size);
+		print_hex_dump_bytes("", DUMP_PREFIX_NONE,
+				     (unsigned char *)msg->u.payload, size);
+		return;
+	}
+
+	if (channel_message_table[hdr->msgtype].message_handler)
+		channel_message_table[hdr->msgtype].message_handler(hdr);
+	else
+		pr_err("Unhandled channel message type %d\n", hdr->msgtype);
+}
+
+/*
+ * vmbus_request_offers - Send a request to get all our pending offers.
+ */
+int vmbus_request_offers(void)
+{
+	struct vmbus_channel_message_header *msg;
+	struct vmbus_channel_msginfo *msginfo;
+	int ret, t;
+
+	msginfo = kmalloc(sizeof(*msginfo) +
+			  sizeof(struct vmbus_channel_message_header),
+			  GFP_KERNEL);
+	if (!msginfo)
+		return -ENOMEM;
+
+	init_completion(&msginfo->waitevent);
+
+	msg = (struct vmbus_channel_message_header *)msginfo->msg;
+
+	msg->msgtype = CHANNELMSG_REQUESTOFFERS;
+
+
+	ret = vmbus_post_msg(msg,
+			       sizeof(struct vmbus_channel_message_header));
+	if (ret != 0) {
+		pr_err("Unable to request offers - %d\n", ret);
+
+		goto cleanup;
+	}
+
+	t = wait_for_completion_timeout(&msginfo->waitevent, 5*HZ);
+	if (t == 0) {
+		ret = -ETIMEDOUT;
+		goto cleanup;
+	}
+
+
+
+cleanup:
+	kfree(msginfo);
+
+	return ret;
+}
+
+/* eof */
diff --git a/drivers/staging/hv/connection.c b/drivers/staging/hv/connection.c
new file mode 100644
index 0000000..7e15392
--- /dev/null
+++ b/drivers/staging/hv/connection.c
@@ -0,0 +1,290 @@
+/*
+ *
+ * Copyright (c) 2009, Microsoft Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * Authors:
+ *   Haiyang Zhang <haiyangz@microsoft.com>
+ *   Hank Janssen  <hjanssen@microsoft.com>
+ *
+ */
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/wait.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+
+#include "hyperv.h"
+#include "hyperv_vmbus.h"
+
+
+struct vmbus_connection vmbus_connection = {
+	.conn_state		= DISCONNECTED,
+	.next_gpadl_handle	= ATOMIC_INIT(0xE1E10),
+};
+
+/*
+ * vmbus_connect - Sends a connect request on the partition service connection
+ */
+int vmbus_connect(void)
+{
+	int ret = 0;
+	int t;
+	struct vmbus_channel_msginfo *msginfo = NULL;
+	struct vmbus_channel_initiate_contact *msg;
+	unsigned long flags;
+
+	/* Make sure we are not connecting or connected */
+	if (vmbus_connection.conn_state != DISCONNECTED)
+		return -EISCONN;
+
+	/* Initialize the vmbus connection */
+	vmbus_connection.conn_state = CONNECTING;
+	vmbus_connection.work_queue = create_workqueue("hv_vmbus_con");
+	if (!vmbus_connection.work_queue) {
+		ret = -ENOMEM;
+		goto cleanup;
+	}
+
+	INIT_LIST_HEAD(&vmbus_connection.chn_msg_list);
+	spin_lock_init(&vmbus_connection.channelmsg_lock);
+
+	INIT_LIST_HEAD(&vmbus_connection.chn_list);
+	spin_lock_init(&vmbus_connection.channel_lock);
+
+	/*
+	 * Setup the vmbus event connection for channel interrupt
+	 * abstraction stuff
+	 */
+	vmbus_connection.int_page =
+	(void *)__get_free_pages(GFP_KERNEL|__GFP_ZERO, 0);
+	if (vmbus_connection.int_page == NULL) {
+		ret = -ENOMEM;
+		goto cleanup;
+	}
+
+	vmbus_connection.recv_int_page = vmbus_connection.int_page;
+	vmbus_connection.send_int_page =
+		(void *)((unsigned long)vmbus_connection.int_page +
+			(PAGE_SIZE >> 1));
+
+	/*
+	 * Setup the monitor notification facility. The 1st page for
+	 * parent->child and the 2nd page for child->parent
+	 */
+	vmbus_connection.monitor_pages =
+	(void *)__get_free_pages((GFP_KERNEL|__GFP_ZERO), 1);
+	if (vmbus_connection.monitor_pages == NULL) {
+		ret = -ENOMEM;
+		goto cleanup;
+	}
+
+	msginfo = kzalloc(sizeof(*msginfo) +
+			  sizeof(struct vmbus_channel_initiate_contact),
+			  GFP_KERNEL);
+	if (msginfo == NULL) {
+		ret = -ENOMEM;
+		goto cleanup;
+	}
+
+	init_completion(&msginfo->waitevent);
+
+	msg = (struct vmbus_channel_initiate_contact *)msginfo->msg;
+
+	msg->header.msgtype = CHANNELMSG_INITIATE_CONTACT;
+	msg->vmbus_version_requested = VMBUS_REVISION_NUMBER;
+	msg->interrupt_page = virt_to_phys(vmbus_connection.int_page);
+	msg->monitor_page1 = virt_to_phys(vmbus_connection.monitor_pages);
+	msg->monitor_page2 = virt_to_phys(
+			(void *)((unsigned long)vmbus_connection.monitor_pages +
+				 PAGE_SIZE));
+
+	/*
+	 * Add to list before we send the request since we may
+	 * receive the response before returning from this routine
+	 */
+	spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
+	list_add_tail(&msginfo->msglistentry,
+		      &vmbus_connection.chn_msg_list);
+
+	spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
+
+	ret = vmbus_post_msg(msg,
+			       sizeof(struct vmbus_channel_initiate_contact));
+	if (ret != 0) {
+		spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
+		list_del(&msginfo->msglistentry);
+		spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock,
+					flags);
+		goto cleanup;
+	}
+
+	/* Wait for the connection response */
+	t =  wait_for_completion_timeout(&msginfo->waitevent, HZ);
+	if (t == 0) {
+		spin_lock_irqsave(&vmbus_connection.channelmsg_lock,
+				flags);
+		list_del(&msginfo->msglistentry);
+		spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock,
+					flags);
+		ret = -ETIMEDOUT;
+		goto cleanup;
+	}
+
+	spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
+	list_del(&msginfo->msglistentry);
+	spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
+
+	/* Check if successful */
+	if (msginfo->response.version_response.version_supported) {
+		vmbus_connection.conn_state = CONNECTED;
+	} else {
+		pr_err("Unable to connect, "
+			"Version %d not supported by Hyper-V\n",
+			VMBUS_REVISION_NUMBER);
+		ret = -ECONNREFUSED;
+		goto cleanup;
+	}
+
+	kfree(msginfo);
+	return 0;
+
+cleanup:
+	vmbus_connection.conn_state = DISCONNECTED;
+
+	if (vmbus_connection.work_queue)
+		destroy_workqueue(vmbus_connection.work_queue);
+
+	if (vmbus_connection.int_page) {
+		free_pages((unsigned long)vmbus_connection.int_page, 0);
+		vmbus_connection.int_page = NULL;
+	}
+
+	if (vmbus_connection.monitor_pages) {
+		free_pages((unsigned long)vmbus_connection.monitor_pages, 1);
+		vmbus_connection.monitor_pages = NULL;
+	}
+
+	kfree(msginfo);
+
+	return ret;
+}
+
+
+/*
+ * relid2channel - Get the channel object given its
+ * child relative id (ie channel id)
+ */
+struct vmbus_channel *relid2channel(u32 relid)
+{
+	struct vmbus_channel *channel;
+	struct vmbus_channel *found_channel  = NULL;
+	unsigned long flags;
+
+	spin_lock_irqsave(&vmbus_connection.channel_lock, flags);
+	list_for_each_entry(channel, &vmbus_connection.chn_list, listentry) {
+		if (channel->offermsg.child_relid == relid) {
+			found_channel = channel;
+			break;
+		}
+	}
+	spin_unlock_irqrestore(&vmbus_connection.channel_lock, flags);
+
+	return found_channel;
+}
+
+/*
+ * process_chn_event - Process a channel event notification
+ */
+static void process_chn_event(u32 relid)
+{
+	struct vmbus_channel *channel;
+
+	/* ASSERT(relId > 0); */
+
+	/*
+	 * Find the channel based on this relid and invokes the
+	 * channel callback to process the event
+	 */
+	channel = relid2channel(relid);
+
+	if (channel) {
+		channel->onchannel_callback(channel->channel_callback_context);
+	} else {
+		pr_err("channel not found for relid - %u\n", relid);
+	}
+}
+
+/*
+ * vmbus_on_event - Handler for events
+ */
+void vmbus_on_event(unsigned long data)
+{
+	u32 dword;
+	u32 maxdword = MAX_NUM_CHANNELS_SUPPORTED >> 5;
+	int bit;
+	u32 relid;
+	u32 *recv_int_page = vmbus_connection.recv_int_page;
+
+	/* Check events */
+	if (!recv_int_page)
+		return;
+	for (dword = 0; dword < maxdword; dword++) {
+		if (!recv_int_page[dword])
+			continue;
+		for (bit = 0; bit < 32; bit++) {
+			if (sync_test_and_clear_bit(bit, (unsigned long *)&recv_int_page[dword])) {
+				relid = (dword << 5) + bit;
+
+				if (relid == 0) {
+					/*
+					 * Special case - vmbus
+					 * channel protocol msg
+					 */
+					continue;
+				}
+				process_chn_event(relid);
+			}
+		}
+	}
+}
+
+/*
+ * vmbus_post_msg - Send a msg on the vmbus's message connection
+ */
+int vmbus_post_msg(void *buffer, size_t buflen)
+{
+	union hv_connection_id conn_id;
+
+	conn_id.asu32 = 0;
+	conn_id.u.id = VMBUS_MESSAGE_CONNECTION_ID;
+	return hv_post_message(conn_id, 1, buffer, buflen);
+}
+
+/*
+ * vmbus_set_event - Send an event notification to the parent
+ */
+int vmbus_set_event(u32 child_relid)
+{
+	/* Each u32 represents 32 channels */
+	sync_set_bit(child_relid & 31,
+		(unsigned long *)vmbus_connection.send_int_page +
+		(child_relid >> 5));
+
+	return hv_signal_event();
+}
diff --git a/drivers/staging/hv/ext_utils.c b/drivers/staging/hv/ext_utils.c
deleted file mode 100644
index a44cd1b..0000000
--- a/drivers/staging/hv/ext_utils.c
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (c) 2010, Microsoft Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place - Suite 330, Boston, MA 02111-1307 USA.
- *
- * Authors:
- *   Haiyang Zhang <haiyangz@microsoft.com>
- *   Hank Janssen  <hjanssen@microsoft.com>
- */
-#include <linux/reboot.h>
-#include "utils.h"
-
-void shutdown_linux_system()
-{
-	orderly_poweroff(false);
-}
diff --git a/drivers/staging/hv/hv.c b/drivers/staging/hv/hv.c
new file mode 100644
index 0000000..824f816
--- /dev/null
+++ b/drivers/staging/hv/hv.c
@@ -0,0 +1,438 @@
+/*
+ * Copyright (c) 2009, Microsoft Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * Authors:
+ *   Haiyang Zhang <haiyangz@microsoft.com>
+ *   Hank Janssen  <hjanssen@microsoft.com>
+ *
+ */
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+
+#include "hyperv.h"
+#include "hyperv_vmbus.h"
+
+/* The one and only */
+struct hv_context hv_context = {
+	.synic_initialized	= false,
+	.hypercall_page		= NULL,
+	.signal_event_param	= NULL,
+	.signal_event_buffer	= NULL,
+};
+
+/*
+ * query_hypervisor_presence
+ * - Query the cpuid for presence of windows hypervisor
+ */
+static int query_hypervisor_presence(void)
+{
+	unsigned int eax;
+	unsigned int ebx;
+	unsigned int ecx;
+	unsigned int edx;
+	unsigned int op;
+
+	eax = 0;
+	ebx = 0;
+	ecx = 0;
+	edx = 0;
+	op = HVCPUID_VERSION_FEATURES;
+	cpuid(op, &eax, &ebx, &ecx, &edx);
+
+	return ecx & HV_PRESENT_BIT;
+}
+
+/*
+ * query_hypervisor_info - Get version info of the windows hypervisor
+ */
+static int query_hypervisor_info(void)
+{
+	unsigned int eax;
+	unsigned int ebx;
+	unsigned int ecx;
+	unsigned int edx;
+	unsigned int max_leaf;
+	unsigned int op;
+
+	/*
+	* Its assumed that this is called after confirming that Viridian
+	* is present. Query id and revision.
+	*/
+	eax = 0;
+	ebx = 0;
+	ecx = 0;
+	edx = 0;
+	op = HVCPUID_VENDOR_MAXFUNCTION;
+	cpuid(op, &eax, &ebx, &ecx, &edx);
+
+	max_leaf = eax;
+
+	if (max_leaf >= HVCPUID_VERSION) {
+		eax = 0;
+		ebx = 0;
+		ecx = 0;
+		edx = 0;
+		op = HVCPUID_VERSION;
+		cpuid(op, &eax, &ebx, &ecx, &edx);
+		pr_info("Hyper-V Host OS Build:%d-%d.%d-%d-%d.%d\n",
+			    eax,
+			    ebx >> 16,
+			    ebx & 0xFFFF,
+			    ecx,
+			    edx >> 24,
+			    edx & 0xFFFFFF);
+	}
+	return max_leaf;
+}
+
+/*
+ * do_hypercall- Invoke the specified hypercall
+ */
+static u64 do_hypercall(u64 control, void *input, void *output)
+{
+#ifdef CONFIG_X86_64
+	u64 hv_status = 0;
+	u64 input_address = (input) ? virt_to_phys(input) : 0;
+	u64 output_address = (output) ? virt_to_phys(output) : 0;
+	volatile void *hypercall_page = hv_context.hypercall_page;
+
+	__asm__ __volatile__("mov %0, %%r8" : : "r" (output_address) : "r8");
+	__asm__ __volatile__("call *%3" : "=a" (hv_status) :
+			     "c" (control), "d" (input_address),
+			     "m" (hypercall_page));
+
+	return hv_status;
+
+#else
+
+	u32 control_hi = control >> 32;
+	u32 control_lo = control & 0xFFFFFFFF;
+	u32 hv_status_hi = 1;
+	u32 hv_status_lo = 1;
+	u64 input_address = (input) ? virt_to_phys(input) : 0;
+	u32 input_address_hi = input_address >> 32;
+	u32 input_address_lo = input_address & 0xFFFFFFFF;
+	u64 output_address = (output) ? virt_to_phys(output) : 0;
+	u32 output_address_hi = output_address >> 32;
+	u32 output_address_lo = output_address & 0xFFFFFFFF;
+	volatile void *hypercall_page = hv_context.hypercall_page;
+
+	__asm__ __volatile__ ("call *%8" : "=d"(hv_status_hi),
+			      "=a"(hv_status_lo) : "d" (control_hi),
+			      "a" (control_lo), "b" (input_address_hi),
+			      "c" (input_address_lo), "D"(output_address_hi),
+			      "S"(output_address_lo), "m" (hypercall_page));
+
+	return hv_status_lo | ((u64)hv_status_hi << 32);
+#endif /* !x86_64 */
+}
+
+/*
+ * hv_init - Main initialization routine.
+ *
+ * This routine must be called before any other routines in here are called
+ */
+int hv_init(void)
+{
+	int ret = 0;
+	int max_leaf;
+	union hv_x64_msr_hypercall_contents hypercall_msr;
+	void *virtaddr = NULL;
+
+	memset(hv_context.synic_event_page, 0, sizeof(void *) * MAX_NUM_CPUS);
+	memset(hv_context.synic_message_page, 0,
+	       sizeof(void *) * MAX_NUM_CPUS);
+
+	if (!query_hypervisor_presence())
+		goto cleanup;
+
+	max_leaf = query_hypervisor_info();
+	/* HvQueryHypervisorFeatures(maxLeaf); */
+
+	/*
+	 * We only support running on top of Hyper-V
+	 */
+	rdmsrl(HV_X64_MSR_GUEST_OS_ID, hv_context.guestid);
+
+	if (hv_context.guestid != 0)
+		goto cleanup;
+
+	/* Write our OS info */
+	wrmsrl(HV_X64_MSR_GUEST_OS_ID, HV_LINUX_GUEST_ID);
+	hv_context.guestid = HV_LINUX_GUEST_ID;
+
+	/* See if the hypercall page is already set */
+	rdmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64);
+
+	/*
+	* Allocate the hypercall page memory
+	* virtaddr = osd_page_alloc(1);
+	*/
+	virtaddr = __vmalloc(PAGE_SIZE, GFP_KERNEL, PAGE_KERNEL_EXEC);
+
+	if (!virtaddr)
+		goto cleanup;
+
+	hypercall_msr.enable = 1;
+
+	hypercall_msr.guest_physical_address = vmalloc_to_pfn(virtaddr);
+	wrmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64);
+
+	/* Confirm that hypercall page did get setup. */
+	hypercall_msr.as_uint64 = 0;
+	rdmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64);
+
+	if (!hypercall_msr.enable)
+		goto cleanup;
+
+	hv_context.hypercall_page = virtaddr;
+
+	/* Setup the global signal event param for the signal event hypercall */
+	hv_context.signal_event_buffer =
+			kmalloc(sizeof(struct hv_input_signal_event_buffer),
+				GFP_KERNEL);
+	if (!hv_context.signal_event_buffer)
+		goto cleanup;
+
+	hv_context.signal_event_param =
+		(struct hv_input_signal_event *)
+			(ALIGN((unsigned long)
+				  hv_context.signal_event_buffer,
+				  HV_HYPERCALL_PARAM_ALIGN));
+	hv_context.signal_event_param->connectionid.asu32 = 0;
+	hv_context.signal_event_param->connectionid.u.id =
+						VMBUS_EVENT_CONNECTION_ID;
+	hv_context.signal_event_param->flag_number = 0;
+	hv_context.signal_event_param->rsvdz = 0;
+
+	return ret;
+
+cleanup:
+	if (virtaddr) {
+		if (hypercall_msr.enable) {
+			hypercall_msr.as_uint64 = 0;
+			wrmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64);
+		}
+
+		vfree(virtaddr);
+	}
+	ret = -1;
+	return ret;
+}
+
+/*
+ * hv_cleanup - Cleanup routine.
+ *
+ * This routine is called normally during driver unloading or exiting.
+ */
+void hv_cleanup(void)
+{
+	union hv_x64_msr_hypercall_contents hypercall_msr;
+
+	kfree(hv_context.signal_event_buffer);
+	hv_context.signal_event_buffer = NULL;
+	hv_context.signal_event_param = NULL;
+
+	if (hv_context.hypercall_page) {
+		hypercall_msr.as_uint64 = 0;
+		wrmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64);
+		vfree(hv_context.hypercall_page);
+		hv_context.hypercall_page = NULL;
+	}
+}
+
+/*
+ * hv_post_message - Post a message using the hypervisor message IPC.
+ *
+ * This involves a hypercall.
+ */
+u16 hv_post_message(union hv_connection_id connection_id,
+		  enum hv_message_type message_type,
+		  void *payload, size_t payload_size)
+{
+	struct aligned_input {
+		u64 alignment8;
+		struct hv_input_post_message msg;
+	};
+
+	struct hv_input_post_message *aligned_msg;
+	u16 status;
+	unsigned long addr;
+
+	if (payload_size > HV_MESSAGE_PAYLOAD_BYTE_COUNT)
+		return -EMSGSIZE;
+
+	addr = (unsigned long)kmalloc(sizeof(struct aligned_input), GFP_ATOMIC);
+	if (!addr)
+		return -ENOMEM;
+
+	aligned_msg = (struct hv_input_post_message *)
+			(ALIGN(addr, HV_HYPERCALL_PARAM_ALIGN));
+
+	aligned_msg->connectionid = connection_id;
+	aligned_msg->message_type = message_type;
+	aligned_msg->payload_size = payload_size;
+	memcpy((void *)aligned_msg->payload, payload, payload_size);
+
+	status = do_hypercall(HVCALL_POST_MESSAGE, aligned_msg, NULL)
+		& 0xFFFF;
+
+	kfree((void *)addr);
+
+	return status;
+}
+
+
+/*
+ * hv_signal_event -
+ * Signal an event on the specified connection using the hypervisor event IPC.
+ *
+ * This involves a hypercall.
+ */
+u16 hv_signal_event(void)
+{
+	u16 status;
+
+	status = do_hypercall(HVCALL_SIGNAL_EVENT,
+			       hv_context.signal_event_param,
+			       NULL) & 0xFFFF;
+	return status;
+}
+
+/*
+ * hv_synic_init - Initialize the Synthethic Interrupt Controller.
+ *
+ * If it is already initialized by another entity (ie x2v shim), we need to
+ * retrieve the initialized message and event pages.  Otherwise, we create and
+ * initialize the message and event pages.
+ */
+void hv_synic_init(void *irqarg)
+{
+	u64 version;
+	union hv_synic_simp simp;
+	union hv_synic_siefp siefp;
+	union hv_synic_sint shared_sint;
+	union hv_synic_scontrol sctrl;
+
+	u32 irq_vector = *((u32 *)(irqarg));
+	int cpu = smp_processor_id();
+
+	if (!hv_context.hypercall_page)
+		return;
+
+	/* Check the version */
+	rdmsrl(HV_X64_MSR_SVERSION, version);
+
+	hv_context.synic_message_page[cpu] =
+		(void *)get_zeroed_page(GFP_ATOMIC);
+
+	if (hv_context.synic_message_page[cpu] == NULL) {
+		pr_err("Unable to allocate SYNIC message page\n");
+		goto cleanup;
+	}
+
+	hv_context.synic_event_page[cpu] =
+		(void *)get_zeroed_page(GFP_ATOMIC);
+
+	if (hv_context.synic_event_page[cpu] == NULL) {
+		pr_err("Unable to allocate SYNIC event page\n");
+		goto cleanup;
+	}
+
+	/* Setup the Synic's message page */
+	rdmsrl(HV_X64_MSR_SIMP, simp.as_uint64);
+	simp.simp_enabled = 1;
+	simp.base_simp_gpa = virt_to_phys(hv_context.synic_message_page[cpu])
+		>> PAGE_SHIFT;
+
+	wrmsrl(HV_X64_MSR_SIMP, simp.as_uint64);
+
+	/* Setup the Synic's event page */
+	rdmsrl(HV_X64_MSR_SIEFP, siefp.as_uint64);
+	siefp.siefp_enabled = 1;
+	siefp.base_siefp_gpa = virt_to_phys(hv_context.synic_event_page[cpu])
+		>> PAGE_SHIFT;
+
+	wrmsrl(HV_X64_MSR_SIEFP, siefp.as_uint64);
+
+	/* Setup the shared SINT. */
+	rdmsrl(HV_X64_MSR_SINT0 + VMBUS_MESSAGE_SINT, shared_sint.as_uint64);
+
+	shared_sint.as_uint64 = 0;
+	shared_sint.vector = irq_vector; /* HV_SHARED_SINT_IDT_VECTOR + 0x20; */
+	shared_sint.masked = false;
+	shared_sint.auto_eoi = true;
+
+	wrmsrl(HV_X64_MSR_SINT0 + VMBUS_MESSAGE_SINT, shared_sint.as_uint64);
+
+	/* Enable the global synic bit */
+	rdmsrl(HV_X64_MSR_SCONTROL, sctrl.as_uint64);
+	sctrl.enable = 1;
+
+	wrmsrl(HV_X64_MSR_SCONTROL, sctrl.as_uint64);
+
+	hv_context.synic_initialized = true;
+	return;
+
+cleanup:
+	if (hv_context.synic_event_page[cpu])
+		free_page((unsigned long)hv_context.synic_event_page[cpu]);
+
+	if (hv_context.synic_message_page[cpu])
+		free_page((unsigned long)hv_context.synic_message_page[cpu]);
+	return;
+}
+
+/*
+ * hv_synic_cleanup - Cleanup routine for hv_synic_init().
+ */
+void hv_synic_cleanup(void *arg)
+{
+	union hv_synic_sint shared_sint;
+	union hv_synic_simp simp;
+	union hv_synic_siefp siefp;
+	int cpu = smp_processor_id();
+
+	if (!hv_context.synic_initialized)
+		return;
+
+	rdmsrl(HV_X64_MSR_SINT0 + VMBUS_MESSAGE_SINT, shared_sint.as_uint64);
+
+	shared_sint.masked = 1;
+
+	/* Need to correctly cleanup in the case of SMP!!! */
+	/* Disable the interrupt */
+	wrmsrl(HV_X64_MSR_SINT0 + VMBUS_MESSAGE_SINT, shared_sint.as_uint64);
+
+	rdmsrl(HV_X64_MSR_SIMP, simp.as_uint64);
+	simp.simp_enabled = 0;
+	simp.base_simp_gpa = 0;
+
+	wrmsrl(HV_X64_MSR_SIMP, simp.as_uint64);
+
+	rdmsrl(HV_X64_MSR_SIEFP, siefp.as_uint64);
+	siefp.siefp_enabled = 0;
+	siefp.base_siefp_gpa = 0;
+
+	wrmsrl(HV_X64_MSR_SIEFP, siefp.as_uint64);
+
+	free_page((unsigned long)hv_context.synic_message_page[cpu]);
+	free_page((unsigned long)hv_context.synic_event_page[cpu]);
+}
diff --git a/drivers/staging/hv/hv_api.h b/drivers/staging/hv/hv_api.h
deleted file mode 100644
index 9eb818e..0000000
--- a/drivers/staging/hv/hv_api.h
+++ /dev/null
@@ -1,905 +0,0 @@
-/*
- *
- * Copyright (c) 2009, Microsoft Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place - Suite 330, Boston, MA 02111-1307 USA.
- *
- * Authors:
- *   Haiyang Zhang <haiyangz@microsoft.com>
- *   Hank Janssen  <hjanssen@microsoft.com>
- *
- */
-#ifndef __HV_API_H
-#define __HV_API_H
-
-
-/* Status codes for hypervisor operations. */
-
-/*
- * HV_STATUS_SUCCESS
- * The specified hypercall succeeded
- */
-#define HV_STATUS_SUCCESS				((u16)0x0000)
-
-/*
- * HV_STATUS_INVALID_HYPERCALL_CODE
- * The hypervisor does not support the operation because the specified
- * hypercall code is not supported.
- */
-#define HV_STATUS_INVALID_HYPERCALL_CODE		((u16)0x0002)
-
-/*
- * HV_STATUS_INVALID_HYPERCALL_INPUT
- * The hypervisor does not support the operation because the encoding for the
- * hypercall input register is not supported.
- */
-#define HV_STATUS_INVALID_HYPERCALL_INPUT		((u16)0x0003)
-
-/*
- * HV_STATUS_INVALID_ALIGNMENT
- * The hypervisor could not perform the operation beacuse a parameter has an
- * invalid alignment.
- */
-#define HV_STATUS_INVALID_ALIGNMENT			((u16)0x0004)
-
-/*
- * HV_STATUS_INVALID_PARAMETER
- * The hypervisor could not perform the operation beacuse an invalid parameter
- * was specified.
- */
-#define HV_STATUS_INVALID_PARAMETER			((u16)0x0005)
-
-/*
- * HV_STATUS_ACCESS_DENIED
- * Access to the specified object was denied.
- */
-#define HV_STATUS_ACCESS_DENIED				((u16)0x0006)
-
-/*
- * HV_STATUS_INVALID_PARTITION_STATE
- * The hypervisor could not perform the operation because the partition is
- * entering or in an invalid state.
- */
-#define HV_STATUS_INVALID_PARTITION_STATE		((u16)0x0007)
-
-/*
- * HV_STATUS_OPERATION_DENIED
- * The operation is not allowed in the current state.
- */
-#define HV_STATUS_OPERATION_DENIED			((u16)0x0008)
-
-/*
- * HV_STATUS_UNKNOWN_PROPERTY
- * The hypervisor does not recognize the specified partition property.
- */
-#define HV_STATUS_UNKNOWN_PROPERTY			((u16)0x0009)
-
-/*
- * HV_STATUS_PROPERTY_VALUE_OUT_OF_RANGE
- * The specified value of a partition property is out of range or violates an
- * invariant.
- */
-#define HV_STATUS_PROPERTY_VALUE_OUT_OF_RANGE		((u16)0x000A)
-
-/*
- * HV_STATUS_INSUFFICIENT_MEMORY
- * There is not enough memory in the hypervisor pool to complete the operation.
- */
-#define HV_STATUS_INSUFFICIENT_MEMORY			((u16)0x000B)
-
-/*
- * HV_STATUS_PARTITION_TOO_DEEP
- * The maximum partition depth has been exceeded for the partition hierarchy.
- */
-#define HV_STATUS_PARTITION_TOO_DEEP			((u16)0x000C)
-
-/*
- * HV_STATUS_INVALID_PARTITION_ID
- * A partition with the specified partition Id does not exist.
- */
-#define HV_STATUS_INVALID_PARTITION_ID			((u16)0x000D)
-
-/*
- * HV_STATUS_INVALID_VP_INDEX
- * The hypervisor could not perform the operation because the specified VP
- * index is invalid.
- */
-#define HV_STATUS_INVALID_VP_INDEX			((u16)0x000E)
-
-/*
- * HV_STATUS_NOT_FOUND
- * The iteration is complete; no addition items in the iteration could be
- * found.
- */
-#define HV_STATUS_NOT_FOUND				((u16)0x0010)
-
-/*
- * HV_STATUS_INVALID_PORT_ID
- * The hypervisor could not perform the operation because the specified port
- * identifier is invalid.
- */
-#define HV_STATUS_INVALID_PORT_ID			((u16)0x0011)
-
-/*
- * HV_STATUS_INVALID_CONNECTION_ID
- * The hypervisor could not perform the operation because the specified
- * connection identifier is invalid.
- */
-#define HV_STATUS_INVALID_CONNECTION_ID			((u16)0x0012)
-
-/*
- * HV_STATUS_INSUFFICIENT_BUFFERS
- * You did not supply enough message buffers to send a message.
- */
-#define HV_STATUS_INSUFFICIENT_BUFFERS			((u16)0x0013)
-
-/*
- * HV_STATUS_NOT_ACKNOWLEDGED
- * The previous virtual interrupt has not been acknowledged.
- */
-#define HV_STATUS_NOT_ACKNOWLEDGED			((u16)0x0014)
-
-/*
- * HV_STATUS_INVALID_VP_STATE
- * A virtual processor is not in the correct state for the performance of the
- * indicated operation.
- */
-#define HV_STATUS_INVALID_VP_STATE			((u16)0x0015)
-
-/*
- * HV_STATUS_ACKNOWLEDGED
- * The previous virtual interrupt has already been acknowledged.
- */
-#define HV_STATUS_ACKNOWLEDGED				((u16)0x0016)
-
-/*
- * HV_STATUS_INVALID_SAVE_RESTORE_STATE
- * The indicated partition is not in a valid state for saving or restoring.
- */
-#define HV_STATUS_INVALID_SAVE_RESTORE_STATE		((u16)0x0017)
-
-/*
- * HV_STATUS_INVALID_SYNIC_STATE
- * The hypervisor could not complete the operation because a required feature
- * of the synthetic interrupt controller (SynIC) was disabled.
- */
-#define HV_STATUS_INVALID_SYNIC_STATE			((u16)0x0018)
-
-/*
- * HV_STATUS_OBJECT_IN_USE
- * The hypervisor could not perform the operation because the object or value
- * was either already in use or being used for a purpose that would not permit
- * completing the operation.
- */
-#define HV_STATUS_OBJECT_IN_USE				((u16)0x0019)
-
-/*
- * HV_STATUS_INVALID_PROXIMITY_DOMAIN_INFO
- * The proximity domain information is invalid.
- */
-#define HV_STATUS_INVALID_PROXIMITY_DOMAIN_INFO		((u16)0x001A)
-
-/*
- * HV_STATUS_NO_DATA
- * An attempt to retrieve debugging data failed because none was available.
- */
-#define HV_STATUS_NO_DATA				((u16)0x001B)
-
-/*
- * HV_STATUS_INACTIVE
- * The physical connection being used for debuggging has not recorded any
- * receive activity since the last operation.
- */
-#define HV_STATUS_INACTIVE				((u16)0x001C)
-
-/*
- * HV_STATUS_NO_RESOURCES
- * There are not enough resources to complete the operation.
- */
-#define HV_STATUS_NO_RESOURCES				((u16)0x001D)
-
-/*
- * HV_STATUS_FEATURE_UNAVAILABLE
- * A hypervisor feature is not available to the user.
- */
-#define HV_STATUS_FEATURE_UNAVAILABLE			((u16)0x001E)
-
-/*
- * HV_STATUS_UNSUCCESSFUL
- * {Operation Failed} The requested operation was unsuccessful.
- */
-#define HV_STATUS_UNSUCCESSFUL				((u16)0x1001)
-
-/*
- * HV_STATUS_INSUFFICIENT_BUFFER
- * The specified buffer was too small to contain all of the requested data.
- */
-#define HV_STATUS_INSUFFICIENT_BUFFER			((u16)0x1002)
-
-/*
- * HV_STATUS_GPA_NOT_PRESENT
- * The guest physical address is not currently associated with a system
- * physical address.
- */
-#define HV_STATUS_GPA_NOT_PRESENT			((u16)0x1003)
-
-/*
- * HV_STATUS_GUEST_PAGE_FAULT
- * The operation would have resulted in a page fault in the guest.
- */
-#define HV_STATUS_GUEST_PAGE_FAULT			((u16)0x1004)
-
-/*
- * HV_STATUS_RUNDOWN_DISABLED
- * The operation cannot proceed as the rundown object was marked disabled.
- */
-#define HV_STATUS_RUNDOWN_DISABLED			((u16)0x1005)
-
-/*
- * HV_STATUS_KEY_ALREADY_EXISTS
- * The entry cannot be added as another entry with the same key already exists.
- */
-#define HV_STATUS_KEY_ALREADY_EXISTS			((u16)0x1006)
-
-/*
- * HV_STATUS_GPA_INTERCEPT
- * The operation resulted an intercept on a region of guest physical memory.
- */
-#define HV_STATUS_GPA_INTERCEPT				((u16)0x1007)
-
-/*
- * HV_STATUS_GUEST_GENERAL_PROTECTION_FAULT
- * The operation would have resulted in a general protection fault in the
- * guest.
- */
-#define HV_STATUS_GUEST_GENERAL_PROTECTION_FAULT	((u16)0x1008)
-
-/*
- * HV_STATUS_GUEST_STACK_FAULT
- * The operation would have resulted in a stack fault in the guest.
- */
-#define HV_STATUS_GUEST_STACK_FAULT			((u16)0x1009)
-
-/*
- * HV_STATUS_GUEST_INVALID_OPCODE_FAULT
- * The operation would have resulted in an invalid opcode fault in the guest.
- */
-#define HV_STATUS_GUEST_INVALID_OPCODE_FAULT		((u16)0x100A)
-
-/*
- * HV_STATUS_FINALIZE_INCOMPLETE
- * The partition is not completely finalized.
- */
-#define HV_STATUS_FINALIZE_INCOMPLETE			((u16)0x100B)
-
-/*
- * HV_STATUS_GUEST_MACHINE_CHECK_ABORT
- * The operation would have resulted in an machine check abort in the guest.
- */
-#define HV_STATUS_GUEST_MACHINE_CHECK_ABORT		((u16)0x100C)
-
-/*
- * HV_STATUS_ILLEGAL_OVERLAY_ACCESS
- * An illegal access was attempted to an overlay page.
- */
-#define HV_STATUS_ILLEGAL_OVERLAY_ACCESS		((u16)0x100D)
-
-/*
- * HV_STATUS_INSUFFICIENT_SYSTEM_VA
- * There is not enough system VA space available to satisfy the request,
- */
-#define HV_STATUS_INSUFFICIENT_SYSTEM_VA		((u16)0x100E)
-
-/*
- * HV_STATUS_VIRTUAL_ADDRESS_NOT_MAPPED
- * The passed virtual address was not mapped in the hypervisor address space.
- */
-#define HV_STATUS_VIRTUAL_ADDRESS_NOT_MAPPED		((u16)0x100F)
-
-/*
- * HV_STATUS_NOT_IMPLEMENTED
- * The requested operation is not implemented in this version of the
- * hypervisor.
- */
-#define HV_STATUS_NOT_IMPLEMENTED			((u16)0x1010)
-
-/*
- * HV_STATUS_VMX_INSTRUCTION_FAILED
- * The requested VMX instruction failed to complete successfully.
- */
-#define HV_STATUS_VMX_INSTRUCTION_FAILED		((u16)0x1011)
-
-/*
- * HV_STATUS_VMX_INSTRUCTION_FAILED_WITH_STATUS
- * The requested VMX instruction failed to complete successfully indicating
- * status.
- */
-#define HV_STATUS_VMX_INSTRUCTION_FAILED_WITH_STATUS	((u16)0x1012)
-
-/*
- * HV_STATUS_MSR_ACCESS_FAILED
- * The requested access to the model specific register failed.
- */
-#define HV_STATUS_MSR_ACCESS_FAILED		((u16)0x1013)
-
-/*
- * HV_STATUS_CR_ACCESS_FAILED
- * The requested access to the control register failed.
- */
-#define HV_STATUS_CR_ACCESS_FAILED		((u16)0x1014)
-
-/*
- * HV_STATUS_TIMEOUT
- * The specified timeout expired before the operation completed.
- */
-#define HV_STATUS_TIMEOUT			((u16)0x1016)
-
-/*
- * HV_STATUS_MSR_INTERCEPT
- * The requested access to the model specific register generated an intercept.
- */
-#define HV_STATUS_MSR_INTERCEPT			((u16)0x1017)
-
-/*
- * HV_STATUS_CPUID_INTERCEPT
- * The CPUID instruction generated an intercept.
- */
-#define HV_STATUS_CPUID_INTERCEPT		((u16)0x1018)
-
-/*
- * HV_STATUS_REPEAT_INSTRUCTION
- * The current instruction should be repeated and the instruction pointer not
- * advanced.
- */
-#define HV_STATUS_REPEAT_INSTRUCTION		((u16)0x1019)
-
-/*
- * HV_STATUS_PAGE_PROTECTION_VIOLATION
- * The current instruction should be repeated and the instruction pointer not
- * advanced.
- */
-#define HV_STATUS_PAGE_PROTECTION_VIOLATION	((u16)0x101A)
-
-/*
- * HV_STATUS_PAGE_TABLE_INVALID
- * The current instruction should be repeated and the instruction pointer not
- * advanced.
- */
-#define HV_STATUS_PAGE_TABLE_INVALID		((u16)0x101B)
-
-/*
- * HV_STATUS_PAGE_NOT_PRESENT
- * The current instruction should be repeated and the instruction pointer not
- * advanced.
- */
-#define HV_STATUS_PAGE_NOT_PRESENT		((u16)0x101C)
-
-/*
- * HV_STATUS_IO_INTERCEPT
- * The requested access to the I/O port generated an intercept.
- */
-#define HV_STATUS_IO_INTERCEPT				((u16)0x101D)
-
-/*
- * HV_STATUS_NOTHING_TO_DO
- * There is nothing to do.
- */
-#define HV_STATUS_NOTHING_TO_DO				((u16)0x101E)
-
-/*
- * HV_STATUS_THREAD_TERMINATING
- * The requested thread is terminating.
- */
-#define HV_STATUS_THREAD_TERMINATING			((u16)0x101F)
-
-/*
- * HV_STATUS_SECTION_ALREADY_CONSTRUCTED
- * The specified section was already constructed.
- */
-#define HV_STATUS_SECTION_ALREADY_CONSTRUCTED		((u16)0x1020)
-
-/* HV_STATUS_SECTION_NOT_ALREADY_CONSTRUCTED
- * The specified section was not already constructed.
- */
-#define HV_STATUS_SECTION_NOT_ALREADY_CONSTRUCTED	((u16)0x1021)
-
-/*
- * HV_STATUS_PAGE_ALREADY_COMMITTED
- * The specified virtual address was already backed by physical memory.
- */
-#define HV_STATUS_PAGE_ALREADY_COMMITTED		((u16)0x1022)
-
-/*
- * HV_STATUS_PAGE_NOT_ALREADY_COMMITTED
- * The specified virtual address was not already backed by physical memory.
- */
-#define HV_STATUS_PAGE_NOT_ALREADY_COMMITTED		((u16)0x1023)
-
-/*
- * HV_STATUS_COMMITTED_PAGES_REMAIN
- * Committed pages remain in the section.
- */
-#define HV_STATUS_COMMITTED_PAGES_REMAIN		((u16)0x1024)
-
-/*
- * HV_STATUS_NO_REMAINING_COMMITTED_PAGES
- * No additional committed pages beyond the specified page exist in the
- * section.
- */
-#define HV_STATUS_NO_REMAINING_COMMITTED_PAGES		((u16)0x1025)
-
-/*
- * HV_STATUS_INSUFFICIENT_COMPARTMENT_VA
- * The VA space of the compartment is exhausted.
- */
-#define HV_STATUS_INSUFFICIENT_COMPARTMENT_VA		((u16)0x1026)
-
-/*
- * HV_STATUS_DEREF_SPA_LIST_FULL
- * The SPA dereference list is full, and there are additional entries to be
- * added to it.
- */
-#define HV_STATUS_DEREF_SPA_LIST_FULL			((u16)0x1027)
-
-/*
- * HV_STATUS_GPA_OUT_OF_RANGE
- * The supplied GPA is out of range.
- */
-#define HV_STATUS_GPA_OUT_OF_RANGE			((u16)0x1027)
-
-/*
- * HV_STATUS_NONVOLATILE_XMM_STALE
- * The XMM register that was being accessed is stale.
- */
-#define HV_STATUS_NONVOLATILE_XMM_STALE			((u16)0x1028)
-
-/* HV_STATUS_UNSUPPORTED_PROCESSOR
- * The hypervisor does not support the processors in this system.
- */
-#define HV_STATUS_UNSUPPORTED_PROCESSOR			((u16)0x1029)
-
-/*
- * HV_STATUS_INSUFFICIENT_CROM_SPACE
- * Insufficient space existed for copying over the CROM contents.
- */
-#define HV_STATUS_INSUFFICIENT_CROM_SPACE		((u16)0x2000)
-
-/*
- * HV_STATUS_BAD_CROM_FORMAT
- * The contents of the CROM failed validation attempts.
- */
-#define HV_STATUS_BAD_CROM_FORMAT			((u16)0x2001)
-
-/*
- * HV_STATUS_UNSUPPORTED_CROM_FORMAT
- * The contents of the CROM contain contents the parser doesn't support.
- */
-#define HV_STATUS_UNSUPPORTED_CROM_FORMAT		((u16)0x2002)
-
-/*
- * HV_STATUS_UNSUPPORTED_CONTROLLER
- * The register format of the OHCI controller specified for debugging is not
- * supported.
- */
-#define HV_STATUS_UNSUPPORTED_CONTROLLER		((u16)0x2003)
-
-/*
- * HV_STATUS_CROM_TOO_LARGE
- * The CROM contents were to large to copy over.
- */
-#define HV_STATUS_CROM_TOO_LARGE			((u16)0x2004)
-
-/*
- * HV_STATUS_CONTROLLER_IN_USE
- * The OHCI controller specified for debugging cannot be used as it is already
- * in use.
- */
-#define HV_STATUS_CONTROLLER_IN_USE			((u16)0x2005)
-
-
-/*
- * The below CPUID leaves are present if VersionAndFeatures.HypervisorPresent
- * is set by CPUID(HvCpuIdFunctionVersionAndFeatures).
- */
-enum hv_cpuid_function {
-	HvCpuIdFunctionVersionAndFeatures		= 0x00000001,
-	HvCpuIdFunctionHvVendorAndMaxFunction		= 0x40000000,
-	HvCpuIdFunctionHvInterface			= 0x40000001,
-
-	/*
-	 * The remaining functions depend on the value of
-	 * HvCpuIdFunctionInterface
-	 */
-	HvCpuIdFunctionMsHvVersion			= 0x40000002,
-	HvCpuIdFunctionMsHvFeatures			= 0x40000003,
-	HvCpuIdFunctionMsHvEnlightenmentInformation	= 0x40000004,
-	HvCpuIdFunctionMsHvImplementationLimits		= 0x40000005,
-};
-
-/* Define the virtual APIC registers */
-#define HV_X64_MSR_EOI			(0x40000070)
-#define HV_X64_MSR_ICR			(0x40000071)
-#define HV_X64_MSR_TPR			(0x40000072)
-#define HV_X64_MSR_APIC_ASSIST_PAGE	(0x40000073)
-
-/* Define version of the synthetic interrupt controller. */
-#define HV_SYNIC_VERSION		(1)
-
-/* Define synthetic interrupt controller model specific registers. */
-#define HV_X64_MSR_SCONTROL		(0x40000080)
-#define HV_X64_MSR_SVERSION		(0x40000081)
-#define HV_X64_MSR_SIEFP		(0x40000082)
-#define HV_X64_MSR_SIMP			(0x40000083)
-#define HV_X64_MSR_EOM			(0x40000084)
-#define HV_X64_MSR_SINT0		(0x40000090)
-#define HV_X64_MSR_SINT1		(0x40000091)
-#define HV_X64_MSR_SINT2		(0x40000092)
-#define HV_X64_MSR_SINT3		(0x40000093)
-#define HV_X64_MSR_SINT4		(0x40000094)
-#define HV_X64_MSR_SINT5		(0x40000095)
-#define HV_X64_MSR_SINT6		(0x40000096)
-#define HV_X64_MSR_SINT7		(0x40000097)
-#define HV_X64_MSR_SINT8		(0x40000098)
-#define HV_X64_MSR_SINT9		(0x40000099)
-#define HV_X64_MSR_SINT10		(0x4000009A)
-#define HV_X64_MSR_SINT11		(0x4000009B)
-#define HV_X64_MSR_SINT12		(0x4000009C)
-#define HV_X64_MSR_SINT13		(0x4000009D)
-#define HV_X64_MSR_SINT14		(0x4000009E)
-#define HV_X64_MSR_SINT15		(0x4000009F)
-
-/* Define the expected SynIC version. */
-#define HV_SYNIC_VERSION_1		(0x1)
-
-/* Define synthetic interrupt controller message constants. */
-#define HV_MESSAGE_SIZE			(256)
-#define HV_MESSAGE_PAYLOAD_BYTE_COUNT	(240)
-#define HV_MESSAGE_PAYLOAD_QWORD_COUNT	(30)
-#define HV_ANY_VP			(0xFFFFFFFF)
-
-/* Define synthetic interrupt controller flag constants. */
-#define HV_EVENT_FLAGS_COUNT		(256 * 8)
-#define HV_EVENT_FLAGS_BYTE_COUNT	(256)
-#define HV_EVENT_FLAGS_DWORD_COUNT	(256 / sizeof(u32))
-
-/* Define hypervisor message types. */
-enum hv_message_type {
-	HvMessageTypeNone			= 0x00000000,
-
-	/* Memory access messages. */
-	HvMessageTypeUnmappedGpa		= 0x80000000,
-	HvMessageTypeGpaIntercept		= 0x80000001,
-
-	/* Timer notification messages. */
-	HvMessageTimerExpired			= 0x80000010,
-
-	/* Error messages. */
-	HvMessageTypeInvalidVpRegisterValue	= 0x80000020,
-	HvMessageTypeUnrecoverableException	= 0x80000021,
-	HvMessageTypeUnsupportedFeature		= 0x80000022,
-
-	/* Trace buffer complete messages. */
-	HvMessageTypeEventLogBufferComplete	= 0x80000040,
-
-	/* Platform-specific processor intercept messages. */
-	HvMessageTypeX64IoPortIntercept		= 0x80010000,
-	HvMessageTypeX64MsrIntercept		= 0x80010001,
-	HvMessageTypeX64CpuidIntercept		= 0x80010002,
-	HvMessageTypeX64ExceptionIntercept	= 0x80010003,
-	HvMessageTypeX64ApicEoi			= 0x80010004,
-	HvMessageTypeX64LegacyFpError		= 0x80010005
-};
-
-/* Define the number of synthetic interrupt sources. */
-#define HV_SYNIC_SINT_COUNT		(16)
-#define HV_SYNIC_STIMER_COUNT		(4)
-
-/* Define invalid partition identifier. */
-#define HV_PARTITION_ID_INVALID		((u64)0x0)
-
-/* Define connection identifier type. */
-union hv_connection_id {
-	u32 Asu32;
-	struct {
-		u32 Id:24;
-		u32 Reserved:8;
-	} u;
-};
-
-/* Define port identifier type. */
-union hv_port_id {
-	u32 Asu32;
-	struct {
-		u32 Id:24;
-		u32 Reserved:8;
-	} u ;
-};
-
-/* Define port type. */
-enum hv_port_type {
-	HvPortTypeMessage	= 1,
-	HvPortTypeEvent		= 2,
-	HvPortTypeMonitor	= 3
-};
-
-/* Define port information structure. */
-struct hv_port_info {
-	enum hv_port_type PortType;
-	u32 Padding;
-	union {
-		struct {
-			u32 TargetSint;
-			u32 TargetVp;
-			u64 RsvdZ;
-		} MessagePortInfo;
-		struct {
-			u32 TargetSint;
-			u32 TargetVp;
-			u16 BaseFlagNumber;
-			u16 FlagCount;
-			u32 RsvdZ;
-		} EventPortInfo;
-		struct {
-			u64 MonitorAddress;
-			u64 RsvdZ;
-		} MonitorPortInfo;
-	};
-};
-
-struct hv_connection_info {
-	enum hv_port_type PortType;
-	u32 Padding;
-	union {
-		struct {
-			u64 RsvdZ;
-		} MessageConnectionInfo;
-		struct {
-			u64 RsvdZ;
-		} EventConnectionInfo;
-		struct {
-			u64 MonitorAddress;
-		} MonitorConnectionInfo;
-	};
-};
-
-/* Define synthetic interrupt controller message flags. */
-union hv_message_flags {
-	u8 Asu8;
-	struct {
-		u8 MessagePending:1;
-		u8 Reserved:7;
-	};
-};
-
-/* Define synthetic interrupt controller message header. */
-struct hv_message_header {
-	enum hv_message_type MessageType;
-	u8 PayloadSize;
-	union hv_message_flags MessageFlags;
-	u8 Reserved[2];
-	union {
-		u64 Sender;
-		union hv_port_id Port;
-	};
-};
-
-/* Define timer message payload structure. */
-struct hv_timer_message_payload {
-	u32 TimerIndex;
-	u32 Reserved;
-	u64 ExpirationTime;	/* When the timer expired */
-	u64 DeliveryTime;	/* When the message was delivered */
-};
-
-/* Define synthetic interrupt controller message format. */
-struct hv_message {
-	struct hv_message_header Header;
-	union {
-		u64 Payload[HV_MESSAGE_PAYLOAD_QWORD_COUNT];
-	} u ;
-};
-
-/* Define the number of message buffers associated with each port. */
-#define HV_PORT_MESSAGE_BUFFER_COUNT	(16)
-
-/* Define the synthetic interrupt message page layout. */
-struct hv_message_page {
-	struct hv_message SintMessage[HV_SYNIC_SINT_COUNT];
-};
-
-/* Define the synthetic interrupt controller event flags format. */
-union hv_synic_event_flags {
-	u8 Flags8[HV_EVENT_FLAGS_BYTE_COUNT];
-	u32 Flags32[HV_EVENT_FLAGS_DWORD_COUNT];
-};
-
-/* Define the synthetic interrupt flags page layout. */
-struct hv_synic_event_flags_page {
-	union hv_synic_event_flags SintEventFlags[HV_SYNIC_SINT_COUNT];
-};
-
-/* Define SynIC control register. */
-union hv_synic_scontrol {
-	u64 AsUINT64;
-	struct {
-		u64 Enable:1;
-		u64 Reserved:63;
-	};
-};
-
-/* Define synthetic interrupt source. */
-union hv_synic_sint {
-	u64 AsUINT64;
-	struct {
-		u64 Vector:8;
-		u64 Reserved1:8;
-		u64 Masked:1;
-		u64 AutoEoi:1;
-		u64 Reserved2:46;
-	};
-};
-
-/* Define the format of the SIMP register */
-union hv_synic_simp {
-	u64 AsUINT64;
-	struct {
-		u64 SimpEnabled:1;
-		u64 Preserved:11;
-		u64 BaseSimpGpa:52;
-	};
-};
-
-/* Define the format of the SIEFP register */
-union hv_synic_siefp {
-	u64 AsUINT64;
-	struct {
-		u64 SiefpEnabled:1;
-		u64 Preserved:11;
-		u64 BaseSiefpGpa:52;
-	};
-};
-
-/* Definitions for the monitored notification facility */
-union hv_monitor_trigger_group {
-	u64 AsUINT64;
-	struct {
-		u32 Pending;
-		u32 Armed;
-	};
-};
-
-struct hv_monitor_parameter {
-	union hv_connection_id ConnectionId;
-	u16 FlagNumber;
-	u16 RsvdZ;
-};
-
-union hv_monitor_trigger_state {
-	u32 Asu32;
-
-	struct {
-		u32 GroupEnable:4;
-		u32 RsvdZ:28;
-	};
-};
-
-/* struct hv_monitor_page Layout */
-/* ------------------------------------------------------ */
-/* | 0   | TriggerState (4 bytes) | Rsvd1 (4 bytes)     | */
-/* | 8   | TriggerGroup[0]                              | */
-/* | 10  | TriggerGroup[1]                              | */
-/* | 18  | TriggerGroup[2]                              | */
-/* | 20  | TriggerGroup[3]                              | */
-/* | 28  | Rsvd2[0]                                     | */
-/* | 30  | Rsvd2[1]                                     | */
-/* | 38  | Rsvd2[2]                                     | */
-/* | 40  | NextCheckTime[0][0]    | NextCheckTime[0][1] | */
-/* | ...                                                | */
-/* | 240 | Latency[0][0..3]                             | */
-/* | 340 | Rsvz3[0]                                     | */
-/* | 440 | Parameter[0][0]                              | */
-/* | 448 | Parameter[0][1]                              | */
-/* | ...                                                | */
-/* | 840 | Rsvd4[0]                                     | */
-/* ------------------------------------------------------ */
-struct hv_monitor_page {
-	union hv_monitor_trigger_state TriggerState;
-	u32 RsvdZ1;
-
-	union hv_monitor_trigger_group TriggerGroup[4];
-	u64 RsvdZ2[3];
-
-	s32 NextCheckTime[4][32];
-
-	u16 Latency[4][32];
-	u64 RsvdZ3[32];
-
-	struct hv_monitor_parameter Parameter[4][32];
-
-	u8 RsvdZ4[1984];
-};
-
-/* Declare the various hypercall operations. */
-enum hv_call_code {
-	HvCallPostMessage	= 0x005c,
-	HvCallSignalEvent	= 0x005d,
-};
-
-/* Definition of the HvPostMessage hypercall input structure. */
-struct hv_input_post_message {
-	union hv_connection_id ConnectionId;
-	u32 Reserved;
-	enum hv_message_type MessageType;
-	u32 PayloadSize;
-	u64 Payload[HV_MESSAGE_PAYLOAD_QWORD_COUNT];
-};
-
-/* Definition of the HvSignalEvent hypercall input structure. */
-struct hv_input_signal_event {
-	union hv_connection_id ConnectionId;
-	u16 FlagNumber;
-	u16 RsvdZ;
-};
-
-/*
- * Versioning definitions used for guests reporting themselves to the
- * hypervisor, and visa versa.
- */
-
-/* Version info reported by guest OS's */
-enum hv_guest_os_vendor {
-	HvGuestOsVendorMicrosoft	= 0x0001
-};
-
-enum hv_guest_os_microsoft_ids {
-	HvGuestOsMicrosoftUndefined	= 0x00,
-	HvGuestOsMicrosoftMSDOS		= 0x01,
-	HvGuestOsMicrosoftWindows3x	= 0x02,
-	HvGuestOsMicrosoftWindows9x	= 0x03,
-	HvGuestOsMicrosoftWindowsNT	= 0x04,
-	HvGuestOsMicrosoftWindowsCE	= 0x05
-};
-
-/*
- * Declare the MSR used to identify the guest OS.
- */
-#define HV_X64_MSR_GUEST_OS_ID	0x40000000
-
-union hv_x64_msr_guest_os_id_contents {
-	u64 AsUINT64;
-	struct {
-		u64 BuildNumber:16;
-		u64 ServiceVersion:8; /* Service Pack, etc. */
-		u64 MinorVersion:8;
-		u64 MajorVersion:8;
-		u64 OsId:8; /* enum hv_guest_os_microsoft_ids (if Vendor=MS) */
-		u64 VendorId:16; /* enum hv_guest_os_vendor */
-	};
-};
-
-/*
- * Declare the MSR used to setup pages used to communicate with the hypervisor.
- */
-#define HV_X64_MSR_HYPERCALL	0x40000001
-
-union hv_x64_msr_hypercall_contents {
-	u64 AsUINT64;
-	struct {
-		u64 Enable:1;
-		u64 Reserved:11;
-		u64 GuestPhysicalAddress:52;
-	};
-};
-
-#endif
diff --git a/drivers/staging/hv/hv_compat.h b/drivers/staging/hv/hv_compat.h
new file mode 100644
index 0000000..16724ba
--- /dev/null
+++ b/drivers/staging/hv/hv_compat.h
@@ -0,0 +1,81 @@
+
+#ifndef _HV_COMPAT_H
+#define _HV_COMPAT_H
+
+#include <linux/rcupdate.h>
+#include <linux/version.h>
+#include <linux/netdevice.h>
+#include <linux/inetdevice.h>
+#include <net/arp.h>
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_dbg.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_driver.h>
+#include <scsi/scsi_eh.h>
+#include <scsi/scsi_host.h>
+
+#define CN_KVP_IDX	0x9
+
+#ifndef pr_warn
+#define pr_warn(fmt, arg...) printk(KERN_WARNING fmt, ##arg)
+#endif
+
+
+#define DEF_SCSI_QCMD(func_name) \
+	int func_name(struct scsi_cmnd *cmd, \
+			void (*done)(struct scsi_cmnd *))   \
+	{								\
+		int rc;							\
+		rc = func_name##_lck(cmd, done);			\
+		return rc;						\
+	}
+
+#define blk_queue_max_segments(a, b)
+
+#ifndef netdev_err
+static inline void netdev_err(struct net_device *net, const char *fmt, ...)
+{
+	va_list args;
+
+	va_start(args, fmt);
+	vprintk(fmt, args);
+	va_end(args);
+}
+
+#endif
+
+#ifndef netdev_dbg
+#if defined(DEBUG)
+#define netdev_dbg(dev, fmt, ...)  netdev_err(dev, fmt, ...)
+#else
+#define netdev_dbg(__dev, format, args...)                      \
+({                                                              \
+	if (0)                                                  \
+		netdev_err(__dev, format, ##args); \
+	0;                                                      \
+})
+
+#endif
+#endif
+
+
+#if defined(RHEL_RELEASE_VERSION) && (RHEL_RELEASE_CODE == 1536) && \
+LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 32)
+static inline void  netif_notify_peers(struct net_device *net)
+{
+	struct in_device *idev;
+
+	rcu_read_lock();
+	if (((idev = __in_dev_get_rcu(net)) != NULL) &&
+		idev->ifa_list != NULL) {
+		arp_send(ARPOP_REQUEST, ETH_P_ARP,
+		idev->ifa_list->ifa_address, net,
+		idev->ifa_list->ifa_address, NULL,
+		net->dev_addr, NULL);
+	}
+	rcu_read_unlock();
+}
+
+#endif
+#endif
diff --git a/drivers/staging/hv/hv_kvp.c b/drivers/staging/hv/hv_kvp.c
new file mode 100644
index 0000000..13b0ecf
--- /dev/null
+++ b/drivers/staging/hv/hv_kvp.c
@@ -0,0 +1,334 @@
+/*
+ * An implementation of key value pair (KVP) functionality for Linux.
+ *
+ *
+ * Copyright (C) 2010, Novell, Inc.
+ * Author : K. Y. Srinivasan <ksrinivasan@novell.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/net.h>
+#include <linux/nls.h>
+#include <linux/connector.h>
+#include <linux/workqueue.h>
+
+#include "hyperv.h"
+#include "hv_kvp.h"
+
+
+
+/*
+ * Global state maintained for transaction that is being processed.
+ * Note that only one transaction can be active at any point in time.
+ *
+ * This state is set when we receive a request from the host; we
+ * cleanup this state when the transaction is completed - when we respond
+ * to the host with the key value.
+ */
+
+static struct {
+	bool active; /* transaction status - active or not */
+	int recv_len; /* number of bytes received. */
+	struct vmbus_channel *recv_channel; /* chn we got the request */
+	u64 recv_req_id; /* request ID. */
+} kvp_transaction;
+
+static int kvp_send_key(int index);
+
+static void kvp_respond_to_host(char *key, char *value, int error);
+static void kvp_work_func(struct work_struct *dummy);
+static void kvp_register(void);
+
+static DECLARE_DELAYED_WORK(kvp_work, kvp_work_func);
+
+static struct cb_id kvp_id = { CN_KVP_IDX, CN_KVP_VAL };
+static const char kvp_name[] = "kvp_kernel_module";
+static int timeout_fired;
+static u8 *recv_buffer;
+/*
+ * Register the kernel component with the user-level daemon.
+ * As part of this registration, pass the LIC version number.
+ */
+
+static void
+kvp_register(void)
+{
+
+	struct cn_msg *msg;
+
+	msg = kzalloc(sizeof(*msg) + strlen(HV_DRV_VERSION) + 1 , GFP_ATOMIC);
+
+	if (msg) {
+		msg->id.idx =  CN_KVP_IDX;
+		msg->id.val = CN_KVP_VAL;
+		msg->seq = KVP_REGISTER;
+		strcpy(msg->data, HV_DRV_VERSION);
+		msg->len = strlen(HV_DRV_VERSION) + 1;
+		cn_netlink_send(msg, 0, GFP_ATOMIC);
+		kfree(msg);
+	}
+}
+static void
+kvp_work_func(struct work_struct *dummy)
+{
+	/*
+	 * If the timer fires, the user-mode component has not responded;
+	 * process the pending transaction.
+	 */
+	kvp_respond_to_host("Unknown key", "Guest timed out", timeout_fired);
+	timeout_fired = 1;
+}
+
+/*
+ * Callback when data is received from user mode.
+ */
+
+static void
+kvp_cn_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp)
+{
+	struct hv_ku_msg *message;
+
+	message = (struct hv_ku_msg *)msg->data;
+	if (msg->seq == KVP_REGISTER) {
+		pr_info("KVP: user-mode registering done.\n");
+		kvp_register();
+	}
+
+	if (msg->seq == KVP_USER_SET) {
+		/*
+		 * Complete the transaction by forwarding the key value
+		 * to the host. But first, cancel the timeout.
+		 */
+		if (cancel_delayed_work_sync(&kvp_work))
+			kvp_respond_to_host(message->kvp_key,
+						message->kvp_value,
+						!strlen(message->kvp_key));
+	}
+}
+
+static int
+kvp_send_key(int index)
+{
+	struct cn_msg *msg;
+
+	msg = kzalloc(sizeof(*msg) + sizeof(struct hv_kvp_msg) , GFP_ATOMIC);
+
+	if (msg) {
+		msg->id.idx =  CN_KVP_IDX;
+		msg->id.val = CN_KVP_VAL;
+		msg->seq = KVP_KERNEL_GET;
+		((struct hv_ku_msg *)msg->data)->kvp_index = index;
+		msg->len = sizeof(struct hv_ku_msg);
+		cn_netlink_send(msg, 0, GFP_ATOMIC);
+		kfree(msg);
+		return 0;
+	}
+	return 1;
+}
+
+/*
+ * Send a response back to the host.
+ */
+
+static void
+kvp_respond_to_host(char *key, char *value, int error)
+{
+	struct hv_kvp_msg  *kvp_msg;
+	struct hv_kvp_msg_enumerate  *kvp_data;
+	char	*key_name;
+	struct icmsg_hdr *icmsghdrp;
+	int	keylen, valuelen;
+	u32	buf_len;
+	struct vmbus_channel *channel;
+	u64	req_id;
+
+	/*
+	 * If a transaction is not active; log and return.
+	 */
+
+	if (!kvp_transaction.active) {
+		/*
+		 * This is a spurious call!
+		 */
+		pr_warn("KVP: Transaction not active\n");
+		return;
+	}
+	/*
+	 * Copy the global state for completing the transaction. Note that
+	 * only one transaction can be active at a time.
+	 */
+
+	buf_len = kvp_transaction.recv_len;
+	channel = kvp_transaction.recv_channel;
+	req_id = kvp_transaction.recv_req_id;
+
+	icmsghdrp = (struct icmsg_hdr *)
+			&recv_buffer[sizeof(struct vmbuspipe_hdr)];
+	kvp_msg = (struct hv_kvp_msg *)
+			&recv_buffer[sizeof(struct vmbuspipe_hdr) +
+			sizeof(struct icmsg_hdr)];
+	kvp_data = &kvp_msg->kvp_data;
+	key_name = key;
+
+	/*
+	 * If the error parameter is set, terminate the host's enumeration.
+	 */
+	if (error) {
+		/*
+		 * We don't support this index or the we have timedout;
+		 * terminate the host-side iteration by returning an error.
+		 */
+		icmsghdrp->status = HV_E_FAIL;
+		goto response_done;
+	}
+
+	/*
+	 * The windows host expects the key/value pair to be encoded
+	 * in utf16.
+	 */
+	keylen = utf8s_to_utf16s(key_name, strlen(key_name),
+				(wchar_t *)kvp_data->data.key);
+	kvp_data->data.key_size = 2*(keylen + 1); /* utf16 encoding */
+	valuelen = utf8s_to_utf16s(value, strlen(value),
+				(wchar_t *)kvp_data->data.value);
+	kvp_data->data.value_size = 2*(valuelen + 1); /* utf16 encoding */
+
+	kvp_data->data.value_type = REG_SZ; /* all our values are strings */
+	icmsghdrp->status = HV_S_OK;
+
+response_done:
+	icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION | ICMSGHDRFLAG_RESPONSE;
+
+	vmbus_sendpacket(channel, recv_buffer, buf_len, req_id,
+				VM_PKT_DATA_INBAND, 0);
+
+	kvp_transaction.active = false;
+}
+
+/*
+ * This callback is invoked when we get a KVP message from the host.
+ * The host ensures that only one KVP transaction can be active at a time.
+ * KVP implementation in Linux needs to forward the key to a user-mde
+ * component to retrive the corresponding value. Consequently, we cannot
+ * respond to the host in the conext of this callback. Since the host
+ * guarantees that at most only one transaction can be active at a time,
+ * we stash away the transaction state in a set of global variables.
+ */
+
+void hv_kvp_onchannelcallback(void *context)
+{
+	struct vmbus_channel *channel = context;
+	u32 recvlen;
+	u64 requestid;
+
+	struct hv_kvp_msg *kvp_msg;
+	struct hv_kvp_msg_enumerate *kvp_data;
+
+	struct icmsg_hdr *icmsghdrp;
+	struct icmsg_negotiate *negop = NULL;
+
+
+	if (kvp_transaction.active)
+		return;
+
+
+	vmbus_recvpacket(channel, recv_buffer, PAGE_SIZE, &recvlen, &requestid);
+
+	if (recvlen > 0) {
+		icmsghdrp = (struct icmsg_hdr *)&recv_buffer[
+			sizeof(struct vmbuspipe_hdr)];
+
+		if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
+			prep_negotiate_resp(icmsghdrp, negop, recv_buffer);
+		} else {
+			kvp_msg = (struct hv_kvp_msg *)&recv_buffer[
+				sizeof(struct vmbuspipe_hdr) +
+				sizeof(struct icmsg_hdr)];
+
+			kvp_data = &kvp_msg->kvp_data;
+
+			/*
+			 * We only support the "get" operation on
+			 * "KVP_POOL_AUTO" pool.
+			 */
+
+			if ((kvp_msg->kvp_hdr.pool != KVP_POOL_AUTO) ||
+				(kvp_msg->kvp_hdr.operation !=
+				KVP_OP_ENUMERATE)) {
+				icmsghdrp->status = HV_E_FAIL;
+				goto callback_done;
+			}
+
+			/*
+			 * Stash away this global state for completing the
+			 * transaction; note transactions are serialized.
+			 */
+			kvp_transaction.recv_len = recvlen;
+			kvp_transaction.recv_channel = channel;
+			kvp_transaction.recv_req_id = requestid;
+			kvp_transaction.active = true;
+
+			/*
+			 * Get the information from the
+			 * user-mode component.
+			 * component. This transaction will be
+			 * completed when we get the value from
+			 * the user-mode component.
+			 * Set a timeout to deal with
+			 * user-mode not responding.
+			 */
+			kvp_send_key(kvp_data->index);
+			schedule_delayed_work(&kvp_work, 100);
+
+			return;
+
+		}
+
+callback_done:
+
+		icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION
+			| ICMSGHDRFLAG_RESPONSE;
+
+		vmbus_sendpacket(channel, recv_buffer,
+				       recvlen, requestid,
+				       VM_PKT_DATA_INBAND, 0);
+	}
+
+}
+
+int
+hv_kvp_init(void)
+{
+	int err;
+
+	err = cn_add_callback(&kvp_id, kvp_name, kvp_cn_callback);
+	if (err)
+		return err;
+	recv_buffer = kmalloc(PAGE_SIZE, GFP_KERNEL);
+	if (!recv_buffer)
+		return -ENOMEM;
+
+	return 0;
+}
+
+void hv_kvp_deinit(void)
+{
+	cn_del_callback(&kvp_id);
+	cancel_delayed_work_sync(&kvp_work);
+	kfree(recv_buffer);
+}
diff --git a/drivers/staging/hv/hv_kvp.h b/drivers/staging/hv/hv_kvp.h
new file mode 100644
index 0000000..8c402f3
--- /dev/null
+++ b/drivers/staging/hv/hv_kvp.h
@@ -0,0 +1,184 @@
+/*
+ * An implementation of HyperV key value pair (KVP) functionality for Linux.
+ *
+ *
+ * Copyright (C) 2010, Novell, Inc.
+ * Author : K. Y. Srinivasan <ksrinivasan@novell.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+#ifndef	_KVP_H
+#define	_KVP_H_
+
+/*
+ * Maximum value size - used for both key names and value data, and includes
+ * any applicable NULL terminators.
+ *
+ * Note:  This limit is somewhat arbitrary, but falls easily within what is
+ * supported for all native guests (back to Win 2000) and what is reasonable
+ * for the IC KVP exchange functionality.  Note that Windows Me/98/95 are
+ * limited to 255 character key names.
+ *
+ * MSDN recommends not storing data values larger than 2048 bytes in the
+ * registry.
+ *
+ * Note:  This value is used in defining the KVP exchange message - this value
+ * cannot be modified without affecting the message size and compatibility.
+ */
+
+/*
+ * bytes, including any null terminators
+ */
+#define HV_KVP_EXCHANGE_MAX_VALUE_SIZE          (2048)
+
+
+/*
+ * Maximum key size - the registry limit for the length of an entry name
+ * is 256 characters, including the null terminator
+ */
+
+#define HV_KVP_EXCHANGE_MAX_KEY_SIZE            (512)
+
+/*
+ * In Linux, we implement the KVP functionality in two components:
+ * 1) The kernel component which is packaged as part of the hv_utils driver
+ * is responsible for communicating with the host and responsible for
+ * implementing the host/guest protocol. 2) A user level daemon that is
+ * responsible for data gathering.
+ *
+ * Host/Guest Protocol: The host iterates over an index and expects the guest
+ * to assign a key name to the index and also return the value corresponding to
+ * the key. The host will have atmost one KVP transaction outstanding at any
+ * given point in time. The host side iteration stops when the guest returns
+ * an error. Microsoft has specified the following mapping of key names to
+ * host specified index:
+ *
+ *	Index		Key Name
+ *	0		FullyQualifiedDomainName
+ *	1		IntegrationServicesVersion
+ *	2		NetworkAddressIPv4
+ *	3		NetworkAddressIPv6
+ *	4		OSBuildNumber
+ *	5		OSName
+ *	6		OSMajorVersion
+ *	7		OSMinorVersion
+ *	8		OSVersion
+ *	9		ProcessorArchitecture
+ *
+ * The Windows host expects the Key Name and Key Value to be encoded in utf16.
+ *
+ * Guest Kernel/KVP Daemon Protocol: As noted earlier, we implement all of the
+ * data gathering functionality in a user mode daemon. The user level daemon
+ * is also responsible for binding the key name to the index as well. The
+ * kernel and user-level daemon communicate using a connector channel.
+ *
+ * The user mode component first registers with the
+ * the kernel component. Subsequently, the kernel component requests, data
+ * for the specified keys. In response to this message the user mode component
+ * fills in the value corresponding to the specified key. We overload the
+ * sequence field in the cn_msg header to define our KVP message types.
+ *
+ *
+ * The kernel component simply acts as a conduit for communication between the
+ * Windows host and the user-level daemon. The kernel component passes up the
+ * index received from the Host to the user-level daemon. If the index is
+ * valid (supported), the corresponding key as well as its
+ * value (both are strings) is returned. If the index is invalid
+ * (not supported), a NULL key string is returned.
+ */
+
+/*
+ *
+ * The following definitions are shared with the user-mode component; do not
+ * change any of this without making the corresponding changes in
+ * the KVP user-mode component.
+ */
+
+#define CN_KVP_VAL             0x1 /* This supports queries from the kernel */
+#define CN_KVP_USER_VAL       0x2 /* This supports queries from the user */
+
+enum hv_ku_op {
+	KVP_REGISTER = 0, /* Register the user mode component */
+	KVP_KERNEL_GET, /* Kernel is requesting the value */
+	KVP_KERNEL_SET, /* Kernel is providing the value */
+	KVP_USER_GET,  /* User is requesting the value */
+	KVP_USER_SET  /* User is providing the value */
+};
+
+struct hv_ku_msg {
+	__u32 kvp_index; /* Key index */
+	__u8  kvp_key[HV_KVP_EXCHANGE_MAX_KEY_SIZE]; /* Key name */
+	__u8  kvp_value[HV_KVP_EXCHANGE_MAX_VALUE_SIZE]; /* Key  value */
+};
+
+
+
+
+#ifdef __KERNEL__
+
+/*
+ * Registry value types.
+ */
+
+#define REG_SZ 1
+
+enum hv_kvp_exchg_op {
+	KVP_OP_GET = 0,
+	KVP_OP_SET,
+	KVP_OP_DELETE,
+	KVP_OP_ENUMERATE,
+	KVP_OP_COUNT /* Number of operations, must be last. */
+};
+
+enum hv_kvp_exchg_pool {
+	KVP_POOL_EXTERNAL = 0,
+	KVP_POOL_GUEST,
+	KVP_POOL_AUTO,
+	KVP_POOL_AUTO_EXTERNAL,
+	KVP_POOL_AUTO_INTERNAL,
+	KVP_POOL_COUNT /* Number of pools, must be last. */
+};
+
+struct hv_kvp_hdr {
+	u8 operation;
+	u8 pool;
+};
+
+struct hv_kvp_exchg_msg_value {
+	u32 value_type;
+	u32 key_size;
+	u32 value_size;
+	u8 key[HV_KVP_EXCHANGE_MAX_KEY_SIZE];
+	u8 value[HV_KVP_EXCHANGE_MAX_VALUE_SIZE];
+};
+
+struct hv_kvp_msg_enumerate {
+	u32 index;
+	struct hv_kvp_exchg_msg_value data;
+};
+
+struct hv_kvp_msg {
+	struct hv_kvp_hdr	kvp_hdr;
+	struct hv_kvp_msg_enumerate	kvp_data;
+};
+
+int hv_kvp_init(void);
+void hv_kvp_deinit(void);
+void hv_kvp_onchannelcallback(void *);
+
+#endif /* __KERNEL__ */
+#endif	/* _KVP_H */
+
diff --git a/drivers/staging/hv/hv_mouse.c b/drivers/staging/hv/hv_mouse.c
new file mode 100644
index 0000000..b191810
--- /dev/null
+++ b/drivers/staging/hv/hv_mouse.c
@@ -0,0 +1,975 @@
+/*
+ *  Copyright (c) 2009, Citrix Systems, Inc.
+ *  Copyright (c) 2010, Microsoft Corporation.
+ *  Copyright (c) 2011, Novell Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms and conditions of the GNU General Public License,
+ *  version 2, as published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ *  more details.
+ */
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/workqueue.h>
+#include <linux/sched.h>
+#include <linux/wait.h>
+#include <linux/input.h>
+#include <linux/hid.h>
+#include <linux/hiddev.h>
+#include <linux/pci.h>
+#include <linux/dmi.h>
+#include <linux/delay.h>
+
+#include "hyperv.h"
+
+
+/*
+ * Data types
+ */
+struct hv_input_dev_info {
+	unsigned short vendor;
+	unsigned short product;
+	unsigned short version;
+	char name[128];
+};
+
+/* The maximum size of a synthetic input message. */
+#define SYNTHHID_MAX_INPUT_REPORT_SIZE 16
+
+/*
+ * Current version
+ *
+ * History:
+ * Beta, RC < 2008/1/22        1,0
+ * RC > 2008/1/22              2,0
+ */
+#define SYNTHHID_INPUT_VERSION_MAJOR	2
+#define SYNTHHID_INPUT_VERSION_MINOR	0
+#define SYNTHHID_INPUT_VERSION		(SYNTHHID_INPUT_VERSION_MINOR | \
+					 (SYNTHHID_INPUT_VERSION_MAJOR << 16))
+
+
+#pragma pack(push,1)
+/*
+ * Message types in the synthetic input protocol
+ */
+enum synthhid_msg_type {
+	SynthHidProtocolRequest,
+	SynthHidProtocolResponse,
+	SynthHidInitialDeviceInfo,
+	SynthHidInitialDeviceInfoAck,
+	SynthHidInputReport,
+	SynthHidMax
+};
+
+/*
+ * Basic message structures.
+ */
+struct synthhid_msg_hdr {
+	enum synthhid_msg_type type;
+	u32 size;
+};
+
+struct synthhid_msg {
+	struct synthhid_msg_hdr header;
+	char data[1]; /* Enclosed message */
+};
+
+union synthhid_version {
+	struct {
+		u16 minor_version;
+		u16 major_version;
+	};
+	u32 version;
+};
+
+/*
+ * Protocol messages
+ */
+struct synthhid_protocol_request {
+	struct synthhid_msg_hdr header;
+	union synthhid_version version_requested;
+};
+
+struct synthhid_protocol_response {
+	struct synthhid_msg_hdr header;
+	union synthhid_version version_requested;
+	unsigned char approved;
+};
+
+struct synthhid_device_info {
+	struct synthhid_msg_hdr header;
+	struct hv_input_dev_info hid_dev_info;
+	struct hid_descriptor hid_descriptor;
+};
+
+struct synthhid_device_info_ack {
+	struct synthhid_msg_hdr header;
+	unsigned char reserved;
+};
+
+struct synthhid_input_report {
+	struct synthhid_msg_hdr header;
+	char buffer[1];
+};
+
+#pragma pack(pop)
+
+#define INPUTVSC_SEND_RING_BUFFER_SIZE		10*PAGE_SIZE
+#define INPUTVSC_RECV_RING_BUFFER_SIZE		10*PAGE_SIZE
+
+#define NBITS(x) (((x)/BITS_PER_LONG)+1)
+
+enum pipe_prot_msg_type {
+	PipeMessageInvalid = 0,
+	PipeMessageData,
+	PipeMessageMaximum
+};
+
+
+struct pipe_prt_msg {
+	enum pipe_prot_msg_type type;
+	u32 size;
+	char data[1];
+};
+
+/*
+ * Data types
+ */
+struct  mousevsc_prt_msg {
+	enum pipe_prot_msg_type type;
+	u32 size;
+	union {
+		struct synthhid_protocol_request request;
+		struct synthhid_protocol_response response;
+		struct synthhid_device_info_ack ack;
+	};
+};
+
+/*
+ * Represents an mousevsc device
+ */
+struct mousevsc_dev {
+	struct hv_device	*device;
+	/* 0 indicates the device is being destroyed */
+	atomic_t		ref_count;
+	int			num_outstanding_req;
+	unsigned char		init_complete;
+	struct mousevsc_prt_msg	protocol_req;
+	struct mousevsc_prt_msg	protocol_resp;
+	/* Synchronize the request/response if needed */
+	wait_queue_head_t	protocol_wait_event;
+	wait_queue_head_t	dev_info_wait_event;
+	int			protocol_wait_condition;
+	int			device_wait_condition;
+	int			dev_info_status;
+
+	struct hid_descriptor	*hid_desc;
+	unsigned char		*report_desc;
+	u32			report_desc_size;
+	struct hv_input_dev_info hid_dev_info;
+};
+
+
+static const char *driver_name = "mousevsc";
+
+/* {CFA8B69E-5B4A-4cc0-B98B-8BA1A1F3F95A} */
+static const struct hv_guid mouse_guid = {
+	.data = {0x9E, 0xB6, 0xA8, 0xCF, 0x4A, 0x5B, 0xc0, 0x4c,
+		 0xB9, 0x8B, 0x8B, 0xA1, 0xA1, 0xF3, 0xF9, 0x5A}
+};
+
+static void deviceinfo_callback(struct hv_device *dev, struct hv_input_dev_info *info);
+static void inputreport_callback(struct hv_device *dev, void *packet, u32 len);
+static void reportdesc_callback(struct hv_device *dev, void *packet, u32 len);
+
+static struct mousevsc_dev *alloc_input_device(struct hv_device *device)
+{
+	struct mousevsc_dev *input_dev;
+
+	input_dev = kzalloc(sizeof(struct mousevsc_dev), GFP_KERNEL);
+
+	if (!input_dev)
+		return NULL;
+
+	/*
+	 * Set to 2 to allow both inbound and outbound traffics
+	 * (ie get_input_device() and must_get_input_device()) to proceed.
+	 */
+	atomic_cmpxchg(&input_dev->ref_count, 0, 2);
+
+	input_dev->device = device;
+	device->ext = input_dev;
+
+	return input_dev;
+}
+
+static void free_input_device(struct mousevsc_dev *device)
+{
+	WARN_ON(atomic_read(&device->ref_count) == 0);
+	kfree(device);
+}
+
+/*
+ * Get the inputdevice object if exists and its refcount > 1
+ */
+static struct mousevsc_dev *get_input_device(struct hv_device *device)
+{
+	struct mousevsc_dev *input_dev;
+
+	input_dev = (struct mousevsc_dev *)device->ext;
+
+/*
+ *	FIXME
+ *	This sure isn't a valid thing to print for debugging, no matter
+ *	what the intention is...
+ *
+ *	printk(KERN_ERR "-------------------------> REFCOUNT = %d",
+ *	       input_dev->ref_count);
+ */
+
+	if (input_dev && atomic_read(&input_dev->ref_count) > 1)
+		atomic_inc(&input_dev->ref_count);
+	else
+		input_dev = NULL;
+
+	return input_dev;
+}
+
+/*
+ * Get the inputdevice object iff exists and its refcount > 0
+ */
+static struct mousevsc_dev *must_get_input_device(struct hv_device *device)
+{
+	struct mousevsc_dev *input_dev;
+
+	input_dev = (struct mousevsc_dev *)device->ext;
+
+	if (input_dev && atomic_read(&input_dev->ref_count))
+		atomic_inc(&input_dev->ref_count);
+	else
+		input_dev = NULL;
+
+	return input_dev;
+}
+
+static void put_input_device(struct hv_device *device)
+{
+	struct mousevsc_dev *input_dev;
+
+	input_dev = (struct mousevsc_dev *)device->ext;
+
+	atomic_dec(&input_dev->ref_count);
+}
+
+/*
+ * Drop ref count to 1 to effectively disable get_input_device()
+ */
+static struct mousevsc_dev *release_input_device(struct hv_device *device)
+{
+	struct mousevsc_dev *input_dev;
+
+	input_dev = (struct mousevsc_dev *)device->ext;
+
+	/* Busy wait until the ref drop to 2, then set it to 1  */
+	while (atomic_cmpxchg(&input_dev->ref_count, 2, 1) != 2)
+		udelay(100);
+
+	return input_dev;
+}
+
+/*
+ * Drop ref count to 0. No one can use input_device object.
+ */
+static struct mousevsc_dev *final_release_input_device(struct hv_device *device)
+{
+	struct mousevsc_dev *input_dev;
+
+	input_dev = (struct mousevsc_dev *)device->ext;
+
+	/* Busy wait until the ref drop to 1, then set it to 0  */
+	while (atomic_cmpxchg(&input_dev->ref_count, 1, 0) != 1)
+		udelay(100);
+
+	device->ext = NULL;
+	return input_dev;
+}
+
+static void mousevsc_on_send_completion(struct hv_device *device,
+					struct vmpacket_descriptor *packet)
+{
+	struct mousevsc_dev *input_dev;
+	void *request;
+
+	input_dev = must_get_input_device(device);
+	if (!input_dev) {
+		pr_err("unable to get input device...device being destroyed?");
+		return;
+	}
+
+	request = (void *)(unsigned long)packet->trans_id;
+
+	if (request == &input_dev->protocol_req) {
+		/* FIXME */
+		/* Shouldn't we be doing something here? */
+	}
+
+	put_input_device(device);
+}
+
+static void mousevsc_on_receive_device_info(struct mousevsc_dev *input_device,
+				struct synthhid_device_info *device_info)
+{
+	int ret = 0;
+	struct hid_descriptor *desc;
+	struct mousevsc_prt_msg ack;
+
+	/* Assume success for now */
+	input_device->dev_info_status = 0;
+
+	/* Save the device attr */
+	memcpy(&input_device->hid_dev_info, &device_info->hid_dev_info,
+		sizeof(struct hv_input_dev_info));
+
+	/* Save the hid desc */
+	desc = &device_info->hid_descriptor;
+	WARN_ON(desc->bLength > 0);
+
+	input_device->hid_desc = kzalloc(desc->bLength, GFP_KERNEL);
+
+	if (!input_device->hid_desc) {
+		pr_err("unable to allocate hid descriptor - size %d", desc->bLength);
+		goto Cleanup;
+	}
+
+	memcpy(input_device->hid_desc, desc, desc->bLength);
+
+	/* Save the report desc */
+	input_device->report_desc_size = desc->desc[0].wDescriptorLength;
+	input_device->report_desc = kzalloc(input_device->report_desc_size,
+					  GFP_KERNEL);
+
+	if (!input_device->report_desc) {
+		pr_err("unable to allocate report descriptor - size %d",
+			   input_device->report_desc_size);
+		goto Cleanup;
+	}
+
+	memcpy(input_device->report_desc,
+	       ((unsigned char *)desc) + desc->bLength,
+	       desc->desc[0].wDescriptorLength);
+
+	/* Send the ack */
+	memset(&ack, 0, sizeof(struct mousevsc_prt_msg));
+
+	ack.type = PipeMessageData;
+	ack.size = sizeof(struct synthhid_device_info_ack);
+
+	ack.ack.header.type = SynthHidInitialDeviceInfoAck;
+	ack.ack.header.size = 1;
+	ack.ack.reserved = 0;
+
+	ret = vmbus_sendpacket(input_device->device->channel,
+			&ack,
+			sizeof(struct pipe_prt_msg) - sizeof(unsigned char) +
+			sizeof(struct synthhid_device_info_ack),
+			(unsigned long)&ack,
+			VM_PKT_DATA_INBAND,
+			VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
+	if (ret != 0) {
+		pr_err("unable to send synthhid device info ack - ret %d",
+			   ret);
+		goto Cleanup;
+	}
+
+	input_device->device_wait_condition = 1;
+	wake_up(&input_device->dev_info_wait_event);
+
+	return;
+
+Cleanup:
+	kfree(input_device->hid_desc);
+	input_device->hid_desc = NULL;
+
+	kfree(input_device->report_desc);
+	input_device->report_desc = NULL;
+
+	input_device->dev_info_status = -1;
+	input_device->device_wait_condition = 1;
+	wake_up(&input_device->dev_info_wait_event);
+}
+
+static void mousevsc_on_receive_input_report(struct mousevsc_dev *input_device,
+				struct synthhid_input_report *input_report)
+{
+	struct hv_driver *input_drv;
+
+	if (!input_device->init_complete) {
+		pr_info("Initialization incomplete...ignoring input_report msg");
+		return;
+	}
+
+	input_drv = drv_to_hv_drv(input_device->device->device.driver);
+
+	inputreport_callback(input_device->device,
+			     input_report->buffer,
+			     input_report->header.size);
+}
+
+static void mousevsc_on_receive(struct hv_device *device,
+				struct vmpacket_descriptor *packet)
+{
+	struct pipe_prt_msg *pipe_msg;
+	struct synthhid_msg *hid_msg;
+	struct mousevsc_dev *input_dev;
+
+	input_dev = must_get_input_device(device);
+	if (!input_dev) {
+		pr_err("unable to get input device...device being destroyed?");
+		return;
+	}
+
+	pipe_msg = (struct pipe_prt_msg *)((unsigned long)packet +
+						(packet->offset8 << 3));
+
+	if (pipe_msg->type != PipeMessageData) {
+		pr_err("unknown pipe msg type - type %d len %d",
+			   pipe_msg->type, pipe_msg->size);
+		put_input_device(device);
+		return ;
+	}
+
+	hid_msg = (struct synthhid_msg *)&pipe_msg->data[0];
+
+	switch (hid_msg->header.type) {
+	case SynthHidProtocolResponse:
+		memcpy(&input_dev->protocol_resp, pipe_msg,
+		       pipe_msg->size + sizeof(struct pipe_prt_msg) -
+		       sizeof(unsigned char));
+		input_dev->protocol_wait_condition = 1;
+		wake_up(&input_dev->protocol_wait_event);
+		break;
+
+	case SynthHidInitialDeviceInfo:
+		WARN_ON(pipe_msg->size >= sizeof(struct hv_input_dev_info));
+
+		/*
+		 * Parse out the device info into device attr,
+		 * hid desc and report desc
+		 */
+		mousevsc_on_receive_device_info(input_dev,
+			(struct synthhid_device_info *)&pipe_msg->data[0]);
+		break;
+	case SynthHidInputReport:
+		mousevsc_on_receive_input_report(input_dev,
+			(struct synthhid_input_report *)&pipe_msg->data[0]);
+
+		break;
+	default:
+		pr_err("unsupported hid msg type - type %d len %d",
+		       hid_msg->header.type, hid_msg->header.size);
+		break;
+	}
+
+	put_input_device(device);
+}
+
+static void mousevsc_on_channel_callback(void *context)
+{
+	const int packetSize = 0x100;
+	int ret = 0;
+	struct hv_device *device = (struct hv_device *)context;
+	struct mousevsc_dev *input_dev;
+
+	u32 bytes_recvd;
+	u64 req_id;
+	unsigned char packet[0x100];
+	struct vmpacket_descriptor *desc;
+	unsigned char	*buffer = packet;
+	int	bufferlen = packetSize;
+
+	input_dev = must_get_input_device(device);
+
+	if (!input_dev) {
+		pr_err("unable to get input device...device being destroyed?");
+		return;
+	}
+
+	do {
+		ret = vmbus_recvpacket_raw(device->channel, buffer,
+					bufferlen, &bytes_recvd, &req_id);
+
+		if (ret == 0) {
+			if (bytes_recvd > 0) {
+				desc = (struct vmpacket_descriptor *)buffer;
+
+				switch (desc->type) {
+					case VM_PKT_COMP:
+						mousevsc_on_send_completion(
+							device, desc);
+						break;
+
+					case VM_PKT_DATA_INBAND:
+						mousevsc_on_receive(
+							device, desc);
+						break;
+
+					default:
+						pr_err("unhandled packet type %d, tid %llx len %d\n",
+							   desc->type,
+							   req_id,
+							   bytes_recvd);
+						break;
+				}
+
+				/* reset */
+				if (bufferlen > packetSize) {
+					kfree(buffer);
+
+					buffer = packet;
+					bufferlen = packetSize;
+				}
+			} else {
+				/*
+				 * pr_debug("nothing else to read...");
+				 * reset
+				 */
+				if (bufferlen > packetSize) {
+					kfree(buffer);
+
+					buffer = packet;
+					bufferlen = packetSize;
+				}
+				break;
+			}
+		} else if (ret == -2) {
+			/* Handle large packet */
+			bufferlen = bytes_recvd;
+			buffer = kzalloc(bytes_recvd, GFP_KERNEL);
+
+			if (buffer == NULL) {
+				buffer = packet;
+				bufferlen = packetSize;
+
+				/* Try again next time around */
+				pr_err("unable to allocate buffer of size %d!",
+				       bytes_recvd);
+				break;
+			}
+		}
+	} while (1);
+
+	put_input_device(device);
+
+	return;
+}
+
+static int mousevsc_connect_to_vsp(struct hv_device *device)
+{
+	int ret = 0;
+	struct mousevsc_dev *input_dev;
+	struct mousevsc_prt_msg *request;
+	struct mousevsc_prt_msg *response;
+
+	input_dev = get_input_device(device);
+
+	if (!input_dev) {
+		pr_err("unable to get input device...device being destroyed?");
+		return -1;
+	}
+
+	init_waitqueue_head(&input_dev->protocol_wait_event);
+	init_waitqueue_head(&input_dev->dev_info_wait_event);
+
+	request = &input_dev->protocol_req;
+
+	/*
+	 * Now, initiate the vsc/vsp initialization protocol on the open channel
+	 */
+	memset(request, 0, sizeof(struct mousevsc_prt_msg));
+
+	request->type = PipeMessageData;
+	request->size = sizeof(struct synthhid_protocol_request);
+
+	request->request.header.type = SynthHidProtocolRequest;
+	request->request.header.size = sizeof(unsigned long);
+	request->request.version_requested.version = SYNTHHID_INPUT_VERSION;
+
+	pr_info("synthhid protocol request...");
+
+	ret = vmbus_sendpacket(device->channel, request,
+					sizeof(struct pipe_prt_msg) -
+					sizeof(unsigned char) +
+					sizeof(struct synthhid_protocol_request),
+					(unsigned long)request,
+					VM_PKT_DATA_INBAND,
+					VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
+	if (ret != 0) {
+		pr_err("unable to send synthhid protocol request.");
+		goto Cleanup;
+	}
+
+	input_dev->protocol_wait_condition = 0;
+	wait_event_timeout(input_dev->protocol_wait_event,
+		input_dev->protocol_wait_condition, msecs_to_jiffies(1000));
+	if (input_dev->protocol_wait_condition == 0) {
+		ret = -ETIMEDOUT;
+		goto Cleanup;
+	}
+
+	response = &input_dev->protocol_resp;
+
+	if (!response->response.approved) {
+		pr_err("synthhid protocol request failed (version %d)",
+		       SYNTHHID_INPUT_VERSION);
+		ret = -1;
+		goto Cleanup;
+	}
+
+	input_dev->device_wait_condition = 0;
+	wait_event_timeout(input_dev->dev_info_wait_event,
+		input_dev->device_wait_condition, msecs_to_jiffies(1000));
+	if (input_dev->device_wait_condition == 0) {
+		ret = -ETIMEDOUT;
+		goto Cleanup;
+	}
+
+	/*
+	 * We should have gotten the device attr, hid desc and report
+	 * desc at this point
+	 */
+	if (!input_dev->dev_info_status)
+		pr_info("**** input channel up and running!! ****");
+	else
+		ret = -1;
+
+Cleanup:
+	put_input_device(device);
+
+	return ret;
+}
+
+static int mousevsc_on_device_add(struct hv_device *device,
+					void *additional_info)
+{
+	int ret = 0;
+	struct mousevsc_dev *input_dev;
+	struct hv_driver *input_drv;
+	struct hv_input_dev_info dev_info;
+
+	input_dev = alloc_input_device(device);
+
+	if (!input_dev) {
+		ret = -1;
+		goto Cleanup;
+	}
+
+	input_dev->init_complete = false;
+
+	/* Open the channel */
+	ret = vmbus_open(device->channel,
+		INPUTVSC_SEND_RING_BUFFER_SIZE,
+		INPUTVSC_RECV_RING_BUFFER_SIZE,
+		NULL,
+		0,
+		mousevsc_on_channel_callback,
+		device
+		);
+
+	if (ret != 0) {
+		pr_err("unable to open channel: %d", ret);
+		free_input_device(input_dev);
+		return -1;
+	}
+
+	pr_info("InputVsc channel open: %d", ret);
+
+	ret = mousevsc_connect_to_vsp(device);
+
+	if (ret != 0) {
+		pr_err("unable to connect channel: %d", ret);
+
+		vmbus_close(device->channel);
+		free_input_device(input_dev);
+		return ret;
+	}
+
+	input_drv = drv_to_hv_drv(input_dev->device->device.driver);
+
+	dev_info.vendor = input_dev->hid_dev_info.vendor;
+	dev_info.product = input_dev->hid_dev_info.product;
+	dev_info.version = input_dev->hid_dev_info.version;
+	strcpy(dev_info.name, "Microsoft Vmbus HID-compliant Mouse");
+
+	/* Send the device info back up */
+	deviceinfo_callback(device, &dev_info);
+
+	/* Send the report desc back up */
+	/* workaround SA-167 */
+	if (input_dev->report_desc[14] == 0x25)
+		input_dev->report_desc[14] = 0x29;
+
+	reportdesc_callback(device, input_dev->report_desc,
+			    input_dev->report_desc_size);
+
+	input_dev->init_complete = true;
+
+Cleanup:
+	return ret;
+}
+
+static int mousevsc_on_device_remove(struct hv_device *device)
+{
+	struct mousevsc_dev *input_dev;
+	int ret = 0;
+
+	pr_info("disabling input device (%p)...",
+		    device->ext);
+
+	input_dev = release_input_device(device);
+
+
+	/*
+	 * At this point, all outbound traffic should be disable. We only
+	 * allow inbound traffic (responses) to proceed
+	 *
+	 * so that outstanding requests can be completed.
+	 */
+	while (input_dev->num_outstanding_req) {
+		pr_info("waiting for %d requests to complete...",
+			input_dev->num_outstanding_req);
+
+		udelay(100);
+	}
+
+	pr_info("removing input device (%p)...", device->ext);
+
+	input_dev = final_release_input_device(device);
+
+	pr_info("input device (%p) safe to remove", input_dev);
+
+	/* Close the channel */
+	vmbus_close(device->channel);
+
+	free_input_device(input_dev);
+
+	return ret;
+}
+
+
+/*
+ * Data types
+ */
+struct input_device_context {
+	struct hv_device	*device_ctx;
+	struct hid_device	*hid_device;
+	struct hv_input_dev_info device_info;
+	int			connected;
+};
+
+
+static void deviceinfo_callback(struct hv_device *dev, struct hv_input_dev_info *info)
+{
+	struct input_device_context *input_device_ctx =
+		dev_get_drvdata(&dev->device);
+
+	memcpy(&input_device_ctx->device_info, info,
+	       sizeof(struct hv_input_dev_info));
+
+	DPRINT_INFO(INPUTVSC_DRV, "%s", __func__);
+}
+
+static void inputreport_callback(struct hv_device *dev, void *packet, u32 len)
+{
+	int ret = 0;
+
+	struct input_device_context *input_dev_ctx =
+		dev_get_drvdata(&dev->device);
+
+	ret = hid_input_report(input_dev_ctx->hid_device,
+			      HID_INPUT_REPORT, packet, len, 1);
+
+	DPRINT_DBG(INPUTVSC_DRV, "hid_input_report (ret %d)", ret);
+}
+
+static int mousevsc_hid_open(struct hid_device *hid)
+{
+	return 0;
+}
+
+static void mousevsc_hid_close(struct hid_device *hid)
+{
+}
+
+static int mousevsc_probe(struct hv_device *dev)
+{
+	int ret = 0;
+
+	struct input_device_context *input_dev_ctx;
+
+	input_dev_ctx = kmalloc(sizeof(struct input_device_context),
+				GFP_KERNEL);
+
+	dev_set_drvdata(&dev->device, input_dev_ctx);
+
+	/* Call to the vsc driver to add the device */
+	ret = mousevsc_on_device_add(dev, NULL);
+
+	if (ret != 0) {
+		DPRINT_ERR(INPUTVSC_DRV, "unable to add input vsc device");
+
+		return -1;
+	}
+
+	return 0;
+}
+
+static int mousevsc_remove(struct hv_device *dev)
+{
+	int ret = 0;
+
+	struct input_device_context *input_dev_ctx;
+
+	input_dev_ctx = kmalloc(sizeof(struct input_device_context),
+				GFP_KERNEL);
+
+	dev_set_drvdata(&dev->device, input_dev_ctx);
+
+	if (input_dev_ctx->connected) {
+		hidinput_disconnect(input_dev_ctx->hid_device);
+		input_dev_ctx->connected = 0;
+	}
+
+	/*
+	 * Call to the vsc driver to let it know that the device
+	 * is being removed
+	 */
+	ret = mousevsc_on_device_remove(dev);
+
+	if (ret != 0) {
+		DPRINT_ERR(INPUTVSC_DRV,
+			   "unable to remove vsc device (ret %d)", ret);
+	}
+
+	kfree(input_dev_ctx);
+
+	return ret;
+}
+
+static void reportdesc_callback(struct hv_device *dev, void *packet, u32 len)
+{
+	struct input_device_context *input_device_ctx =
+		dev_get_drvdata(&dev->device);
+	struct hid_device *hid_dev;
+
+	/* hid_debug = -1; */
+	hid_dev = kmalloc(sizeof(struct hid_device), GFP_KERNEL);
+
+	if (hid_parse_report(hid_dev, packet, len)) {
+		DPRINT_INFO(INPUTVSC_DRV, "Unable to call hd_parse_report");
+		return;
+	}
+
+	if (hid_dev) {
+		DPRINT_INFO(INPUTVSC_DRV, "hid_device created");
+
+		hid_dev->ll_driver->open  = mousevsc_hid_open;
+		hid_dev->ll_driver->close = mousevsc_hid_close;
+
+		hid_dev->bus = BUS_VIRTUAL;
+		hid_dev->vendor = input_device_ctx->device_info.vendor;
+		hid_dev->product = input_device_ctx->device_info.product;
+		hid_dev->version = input_device_ctx->device_info.version;
+		hid_dev->dev = dev->device;
+
+		sprintf(hid_dev->name, "%s",
+			input_device_ctx->device_info.name);
+
+		/*
+		 * HJ Do we want to call it with a 0
+		 */
+		if (!hidinput_connect(hid_dev, 0)) {
+			hid_dev->claimed |= HID_CLAIMED_INPUT;
+
+			input_device_ctx->connected = 1;
+
+			DPRINT_INFO(INPUTVSC_DRV,
+				     "HID device claimed by input\n");
+		}
+
+		if (!hid_dev->claimed) {
+			DPRINT_ERR(INPUTVSC_DRV,
+				    "HID device not claimed by "
+				    "input or hiddev\n");
+		}
+
+		input_device_ctx->hid_device = hid_dev;
+	}
+
+	kfree(hid_dev);
+}
+
+
+static struct  hv_driver mousevsc_drv = {
+	.probe = mousevsc_probe,
+	.remove = mousevsc_remove,
+};
+
+static void mousevsc_drv_exit(void)
+{
+	vmbus_child_driver_unregister(&mousevsc_drv.driver);
+}
+
+static int __init mousevsc_init(void)
+{
+	struct hv_driver *drv = &mousevsc_drv;
+
+	DPRINT_INFO(INPUTVSC_DRV, "Hyper-V Mouse driver initializing.");
+
+	memcpy(&drv->dev_type, &mouse_guid,
+	       sizeof(struct hv_guid));
+
+	drv->driver.name = driver_name;
+
+	/* The driver belongs to vmbus */
+	vmbus_child_driver_register(&drv->driver);
+
+	return 0;
+}
+
+static void __exit mousevsc_exit(void)
+{
+	mousevsc_drv_exit();
+}
+
+/*
+ * We don't want to automatically load this driver just yet, it's quite
+ * broken.  It's safe if you want to load it yourself manually, but
+ * don't inflict it on unsuspecting users, that's just mean.
+ */
+#if 0
+
+/*
+ * We use a PCI table to determine if we should autoload this driver  This is
+ * needed by distro tools to determine if the hyperv drivers should be
+ * installed and/or configured.  We don't do anything else with the table, but
+ * it needs to be present.
+ */
+const static struct pci_device_id microsoft_hv_pci_table[] = {
+	{ PCI_DEVICE(0x1414, 0x5353) },	/* VGA compatible controller */
+	{ 0 }
+};
+MODULE_DEVICE_TABLE(pci, microsoft_hv_pci_table);
+#endif
+
+MODULE_LICENSE("GPL");
+MODULE_VERSION(HV_DRV_VERSION);
+module_init(mousevsc_init);
+module_exit(mousevsc_exit);
+
diff --git a/drivers/staging/hv/hv_timesource.c b/drivers/staging/hv/hv_timesource.c
index d3be8af..0efb049 100644
--- a/drivers/staging/hv/hv_timesource.c
+++ b/drivers/staging/hv/hv_timesource.c
@@ -5,9 +5,9 @@
  * Copyright (C) 2010, Novell, Inc.
  * Author : K. Y. Srinivasan <ksrinivasan@novell.com>
  *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published
- * by the Free Software Foundation.
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
  *
  * This program is distributed in the hope that it will be useful, but
  * WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -20,6 +20,7 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  *
  */
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
 #include <linux/version.h>
 #include <linux/clocksource.h>
@@ -27,23 +28,11 @@
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/dmi.h>
+#include <asm/hyperv.h>
+#include <asm/mshyperv.h>
+#include <asm/hypervisor.h>
 
 #define HV_CLOCK_SHIFT	22
-/*
- * HyperV defined synthetic CPUID leaves:
- */
-#define HV_CPUID_SIGNATURE	0x40000000
-#define HV_CPUID_MIN		0x40000005
-#define HV_HYPERVISOR_PRESENT_BIT	0x80000000
-#define HV_CPUID_FEATURES	0x40000003
-#define HV_CPUID_RECOMMENDATIONS	0x40000004
-
-/*
- * HyperV defined synthetic MSRs
- */
-
-#define HV_X64_MSR_TIME_REF_COUNT	0x40000020
-
 
 static cycle_t read_hv_clock(struct clocksource *arg)
 {
@@ -94,49 +83,16 @@
 MODULE_DEVICE_TABLE(pci, hv_timesource_pci_table);
 
 
-static int __init hv_detect_hyperv(void)
-{
-	u32 eax, ebx, ecx, edx;
-	char hyp_signature[13];
-
-	cpuid(1, &eax, &ebx, &ecx, &edx);
-
-	if (!(ecx & HV_HYPERVISOR_PRESENT_BIT))
-		return 1;
-
-	cpuid(HV_CPUID_SIGNATURE, &eax, &ebx, &ecx, &edx);
-	*(u32 *)(hyp_signature + 0) = ebx;
-	*(u32 *)(hyp_signature + 4) = ecx;
-	*(u32 *)(hyp_signature + 8) = edx;
-
-	if ((eax < HV_CPUID_MIN) || (memcmp("Microsoft Hv", hyp_signature, 12)))
-		return 1;
-
-	/*
-	 * Extract the features, recommendations etc.
-	 */
-	cpuid(HV_CPUID_FEATURES, &eax, &ebx, &ecx, &edx);
-	if (!(eax & 0x10)) {
-		printk(KERN_WARNING "HyperV Time Ref Counter not available!\n");
-		return 1;
-	}
-
-	cpuid(HV_CPUID_RECOMMENDATIONS, &eax, &ebx, &ecx, &edx);
-	printk(KERN_INFO "HyperV recommendations: %x\n", eax);
-	printk(KERN_INFO "HyperV spin count: %x\n", ebx);
-	return 0;
-}
-
-
 static int __init init_hv_clocksource(void)
 {
-	if (hv_detect_hyperv())
+	if ((x86_hyper != &x86_hyper_ms_hyperv) ||
+		!(ms_hyperv.features & HV_X64_MSR_TIME_REF_COUNT_AVAILABLE))
 		return -ENODEV;
 
 	if (!dmi_check_system(hv_timesource_dmi_table))
 		return -ENODEV;
 
-	printk(KERN_INFO "Registering HyperV clock source\n");
+	pr_info("Registering HyperV clock source\n");
 	return clocksource_register(&hyperv_cs);
 }
 
diff --git a/drivers/staging/hv/hyperv_utils.c b/drivers/staging/hv/hv_util.c
similarity index 63%
rename from drivers/staging/hv/hyperv_utils.c
rename to drivers/staging/hv/hv_util.c
index fa78ba0..c164b54 100644
--- a/drivers/staging/hv/hyperv_utils.c
+++ b/drivers/staging/hv/hv_util.c
@@ -18,6 +18,8 @@
  *   Haiyang Zhang <haiyangz@microsoft.com>
  *   Hank Janssen  <hjanssen@microsoft.com>
  */
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/module.h>
@@ -27,23 +29,17 @@
 #include <linux/dmi.h>
 #include <linux/pci.h>
 
-#include "logging.h"
-#include "osd.h"
-#include "vmbus.h"
-#include "VmbusPacketFormat.h"
-#include "VmbusChannelInterface.h"
-#include "VersionInfo.h"
-#include "Channel.h"
-#include "VmbusPrivate.h"
-#include "VmbusApi.h"
-#include "utils.h"
+#include "hyperv.h"
+#include "hv_kvp.h"
 
+static u8 *shut_txf_buf;
+static u8 *time_txf_buf;
+static u8 *hbeat_txf_buf;
 
 static void shutdown_onchannelcallback(void *context)
 {
 	struct vmbus_channel *channel = context;
-	u8 *buf;
-	u32 buflen, recvlen;
+	u32 recvlen;
 	u64 requestid;
 	u8  execute_shutdown = false;
 
@@ -52,24 +48,20 @@
 	struct icmsg_hdr *icmsghdrp;
 	struct icmsg_negotiate *negop = NULL;
 
-	buflen = PAGE_SIZE;
-	buf = kmalloc(buflen, GFP_ATOMIC);
-
-	VmbusChannelRecvPacket(channel, buf, buflen, &recvlen, &requestid);
+	vmbus_recvpacket(channel, shut_txf_buf,
+			 PAGE_SIZE, &recvlen, &requestid);
 
 	if (recvlen > 0) {
-		DPRINT_DBG(VMBUS, "shutdown packet: len=%d, requestid=%lld",
-			   recvlen, requestid);
-
-		icmsghdrp = (struct icmsg_hdr *)&buf[
+		icmsghdrp = (struct icmsg_hdr *)&shut_txf_buf[
 			sizeof(struct vmbuspipe_hdr)];
 
 		if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
-			prep_negotiate_resp(icmsghdrp, negop, buf);
+			prep_negotiate_resp(icmsghdrp, negop, shut_txf_buf);
 		} else {
-			shutdown_msg = (struct shutdown_msg_data *)&buf[
-				sizeof(struct vmbuspipe_hdr) +
-				sizeof(struct icmsg_hdr)];
+			shutdown_msg =
+				(struct shutdown_msg_data *)&shut_txf_buf[
+					sizeof(struct vmbuspipe_hdr) +
+					sizeof(struct icmsg_hdr)];
 
 			switch (shutdown_msg->flags) {
 			case 0:
@@ -77,29 +69,27 @@
 				icmsghdrp->status = HV_S_OK;
 				execute_shutdown = true;
 
-				DPRINT_INFO(VMBUS, "Shutdown request received -"
-					    " gracefull shutdown initiated");
+				pr_info("Shutdown request received -"
+					    " graceful shutdown initiated\n");
 				break;
 			default:
 				icmsghdrp->status = HV_E_FAIL;
 				execute_shutdown = false;
 
-				DPRINT_INFO(VMBUS, "Shutdown request received -"
-					    " Invalid request");
+				pr_info("Shutdown request received -"
+					    " Invalid request\n");
 				break;
-			};
+			}
 		}
 
 		icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION
 			| ICMSGHDRFLAG_RESPONSE;
 
-		VmbusChannelSendPacket(channel, buf,
+		vmbus_sendpacket(channel, shut_txf_buf,
 				       recvlen, requestid,
-				       VmbusPacketTypeDataInBand, 0);
+				       VM_PKT_DATA_INBAND, 0);
 	}
 
-	kfree(buf);
-
 	if (execute_shutdown == true)
 		orderly_poweroff(false);
 }
@@ -150,28 +140,22 @@
 static void timesync_onchannelcallback(void *context)
 {
 	struct vmbus_channel *channel = context;
-	u8 *buf;
-	u32 buflen, recvlen;
+	u32 recvlen;
 	u64 requestid;
 	struct icmsg_hdr *icmsghdrp;
 	struct ictimesync_data *timedatap;
 
-	buflen = PAGE_SIZE;
-	buf = kmalloc(buflen, GFP_ATOMIC);
-
-	VmbusChannelRecvPacket(channel, buf, buflen, &recvlen, &requestid);
+	vmbus_recvpacket(channel, time_txf_buf,
+			 PAGE_SIZE, &recvlen, &requestid);
 
 	if (recvlen > 0) {
-		DPRINT_DBG(VMBUS, "timesync packet: recvlen=%d, requestid=%lld",
-			recvlen, requestid);
-
-		icmsghdrp = (struct icmsg_hdr *)&buf[
+		icmsghdrp = (struct icmsg_hdr *)&time_txf_buf[
 				sizeof(struct vmbuspipe_hdr)];
 
 		if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
-			prep_negotiate_resp(icmsghdrp, NULL, buf);
+			prep_negotiate_resp(icmsghdrp, NULL, time_txf_buf);
 		} else {
-			timedatap = (struct ictimesync_data *)&buf[
+			timedatap = (struct ictimesync_data *)&time_txf_buf[
 				sizeof(struct vmbuspipe_hdr) +
 				sizeof(struct icmsg_hdr)];
 			adj_guesttime(timedatap->parenttime, timedatap->flags);
@@ -180,12 +164,10 @@
 		icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION
 			| ICMSGHDRFLAG_RESPONSE;
 
-		VmbusChannelSendPacket(channel, buf,
+		vmbus_sendpacket(channel, time_txf_buf,
 				recvlen, requestid,
-				VmbusPacketTypeDataInBand, 0);
+				VM_PKT_DATA_INBAND, 0);
 	}
-
-	kfree(buf);
 }
 
 /*
@@ -196,36 +178,25 @@
 static void heartbeat_onchannelcallback(void *context)
 {
 	struct vmbus_channel *channel = context;
-	u8 *buf;
-	u32 buflen, recvlen;
+	u32 recvlen;
 	u64 requestid;
 	struct icmsg_hdr *icmsghdrp;
 	struct heartbeat_msg_data *heartbeat_msg;
 
-	buflen = PAGE_SIZE;
-	buf = kmalloc(buflen, GFP_ATOMIC);
-
-	VmbusChannelRecvPacket(channel, buf, buflen, &recvlen, &requestid);
+	vmbus_recvpacket(channel, hbeat_txf_buf,
+			 PAGE_SIZE, &recvlen, &requestid);
 
 	if (recvlen > 0) {
-		DPRINT_DBG(VMBUS, "heartbeat packet: len=%d, requestid=%lld",
-			   recvlen, requestid);
-
-		icmsghdrp = (struct icmsg_hdr *)&buf[
-			sizeof(struct vmbuspipe_hdr)];
-
-		icmsghdrp = (struct icmsg_hdr *)&buf[
+		icmsghdrp = (struct icmsg_hdr *)&hbeat_txf_buf[
 				sizeof(struct vmbuspipe_hdr)];
 
 		if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
-			prep_negotiate_resp(icmsghdrp, NULL, buf);
+			prep_negotiate_resp(icmsghdrp, NULL, hbeat_txf_buf);
 		} else {
-			heartbeat_msg = (struct heartbeat_msg_data *)&buf[
-				sizeof(struct vmbuspipe_hdr) +
-				sizeof(struct icmsg_hdr)];
-
-			DPRINT_DBG(VMBUS, "heartbeat seq = %lld",
-				   heartbeat_msg->seq_num);
+			heartbeat_msg =
+				(struct heartbeat_msg_data *)&hbeat_txf_buf[
+					sizeof(struct vmbuspipe_hdr) +
+					sizeof(struct icmsg_hdr)];
 
 			heartbeat_msg->seq_num += 1;
 		}
@@ -233,12 +204,10 @@
 		icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION
 			| ICMSGHDRFLAG_RESPONSE;
 
-		VmbusChannelSendPacket(channel, buf,
+		vmbus_sendpacket(channel, hbeat_txf_buf,
 				       recvlen, requestid,
-				       VmbusPacketTypeDataInBand, 0);
+				       VM_PKT_DATA_INBAND, 0);
 	}
-
-	kfree(buf);
 }
 
 static const struct pci_device_id __initconst
@@ -248,6 +217,7 @@
 };
 MODULE_DEVICE_TABLE(pci, hv_utils_pci_table);
 
+
 static const struct dmi_system_id __initconst
 hv_utils_dmi_table[] __maybe_unused  = {
 	{
@@ -265,38 +235,67 @@
 
 static int __init init_hyperv_utils(void)
 {
-	printk(KERN_INFO "Registering HyperV Utility Driver\n");
+	pr_info("Registering HyperV Utility Driver\n");
 
-	hv_cb_utils[HV_SHUTDOWN_MSG].channel->OnChannelCallback =
-		&shutdown_onchannelcallback;
+	if (hv_kvp_init())
+		return -ENODEV;
+
+
+	if (!dmi_check_system(hv_utils_dmi_table))
+		return -ENODEV;
+
+	shut_txf_buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
+	time_txf_buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
+	hbeat_txf_buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
+
+	if (!shut_txf_buf || !time_txf_buf || !hbeat_txf_buf) {
+		pr_info("Unable to allocate memory for receive buffer\n");
+		kfree(shut_txf_buf);
+		kfree(time_txf_buf);
+		kfree(hbeat_txf_buf);
+		return -ENOMEM;
+	}
+
 	hv_cb_utils[HV_SHUTDOWN_MSG].callback = &shutdown_onchannelcallback;
 
-	hv_cb_utils[HV_TIMESYNC_MSG].channel->OnChannelCallback =
-		&timesync_onchannelcallback;
 	hv_cb_utils[HV_TIMESYNC_MSG].callback = &timesync_onchannelcallback;
 
-	hv_cb_utils[HV_HEARTBEAT_MSG].channel->OnChannelCallback =
-		&heartbeat_onchannelcallback;
 	hv_cb_utils[HV_HEARTBEAT_MSG].callback = &heartbeat_onchannelcallback;
 
+	hv_cb_utils[HV_KVP_MSG].callback = &hv_kvp_onchannelcallback;
+
 	return 0;
 }
 
 static void exit_hyperv_utils(void)
 {
-	printk(KERN_INFO "De-Registered HyperV Utility Driver\n");
+	pr_info("De-Registered HyperV Utility Driver\n");
 
-	hv_cb_utils[HV_SHUTDOWN_MSG].channel->OnChannelCallback =
-		&chn_cb_negotiate;
-	hv_cb_utils[HV_SHUTDOWN_MSG].callback = &chn_cb_negotiate;
+	if (hv_cb_utils[HV_SHUTDOWN_MSG].channel != NULL)
+		hv_cb_utils[HV_SHUTDOWN_MSG].channel->onchannel_callback =
+			&chn_cb_negotiate;
+	hv_cb_utils[HV_SHUTDOWN_MSG].callback = NULL;
 
-	hv_cb_utils[HV_TIMESYNC_MSG].channel->OnChannelCallback =
-		&chn_cb_negotiate;
-	hv_cb_utils[HV_TIMESYNC_MSG].callback = &chn_cb_negotiate;
+	if (hv_cb_utils[HV_TIMESYNC_MSG].channel != NULL)
+		hv_cb_utils[HV_TIMESYNC_MSG].channel->onchannel_callback =
+			&chn_cb_negotiate;
+	hv_cb_utils[HV_TIMESYNC_MSG].callback = NULL;
 
-	hv_cb_utils[HV_HEARTBEAT_MSG].channel->OnChannelCallback =
-		&chn_cb_negotiate;
-	hv_cb_utils[HV_HEARTBEAT_MSG].callback = &chn_cb_negotiate;
+	if (hv_cb_utils[HV_HEARTBEAT_MSG].channel != NULL)
+		hv_cb_utils[HV_HEARTBEAT_MSG].channel->onchannel_callback =
+			&chn_cb_negotiate;
+	hv_cb_utils[HV_HEARTBEAT_MSG].callback = NULL;
+
+	if (hv_cb_utils[HV_KVP_MSG].channel != NULL)
+		hv_cb_utils[HV_KVP_MSG].channel->onchannel_callback =
+			&chn_cb_negotiate;
+	hv_cb_utils[HV_KVP_MSG].callback = NULL;
+
+	hv_kvp_deinit();
+
+	kfree(shut_txf_buf);
+	kfree(time_txf_buf);
+	kfree(hbeat_txf_buf);
 }
 
 module_init(init_hyperv_utils);
diff --git a/drivers/staging/hv/hyperv.h b/drivers/staging/hv/hyperv.h
new file mode 100644
index 0000000..8175b25
--- /dev/null
+++ b/drivers/staging/hv/hyperv.h
@@ -0,0 +1,953 @@
+/*
+ *
+ * Copyright (c) 2011, Microsoft Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * Authors:
+ *   Haiyang Zhang <haiyangz@microsoft.com>
+ *   Hank Janssen  <hjanssen@microsoft.com>
+ *   K. Y. Srinivasan <kys@microsoft.com>
+ *
+ */
+
+#ifndef _HYPERV_H
+#define _HYPERV_H
+
+#include <linux/scatterlist.h>
+#include <linux/list.h>
+#include <linux/timer.h>
+#include <linux/workqueue.h>
+#include <linux/completion.h>
+#include <linux/device.h>
+#include <linux/version.h>
+
+
+#include <asm/hyperv.h>
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 33)
+#include "hv_compat.h"
+#endif
+
+struct hv_guid {
+	unsigned char data[16];
+};
+
+#define MAX_PAGE_BUFFER_COUNT				16
+#define MAX_MULTIPAGE_BUFFER_COUNT			32 /* 128K */
+
+#pragma pack(push, 1)
+
+/* Single-page buffer */
+struct hv_page_buffer {
+	u32 len;
+	u32 offset;
+	u64 pfn;
+};
+
+/* Multiple-page buffer */
+struct hv_multipage_buffer {
+	/* Length and Offset determines the # of pfns in the array */
+	u32 len;
+	u32 offset;
+	u64 pfn_array[MAX_MULTIPAGE_BUFFER_COUNT];
+};
+
+/* 0x18 includes the proprietary packet header */
+#define MAX_PAGE_BUFFER_PACKET		(0x18 +			\
+					(sizeof(struct hv_page_buffer) * \
+					 MAX_PAGE_BUFFER_COUNT))
+#define MAX_MULTIPAGE_BUFFER_PACKET	(0x18 +			\
+					 sizeof(struct hv_multipage_buffer))
+
+
+#pragma pack(pop)
+
+struct hv_ring_buffer {
+	/* Offset in bytes from the start of ring data below */
+	u32 write_index;
+
+	/* Offset in bytes from the start of ring data below */
+	u32 read_index;
+
+	u32 interrupt_mask;
+
+	/* Pad it to PAGE_SIZE so that data starts on page boundary */
+	u8	reserved[4084];
+
+	/* NOTE:
+	 * The interrupt_mask field is used only for channels but since our
+	 * vmbus connection also uses this data structure and its data starts
+	 * here, we commented out this field.
+	 */
+
+	/*
+	 * Ring data starts here + RingDataStartOffset
+	 * !!! DO NOT place any fields below this !!!
+	 */
+	u8 buffer[0];
+} __packed;
+
+struct hv_ring_buffer_info {
+	struct hv_ring_buffer *ring_buffer;
+	u32 ring_size;			/* Include the shared header */
+	spinlock_t ring_lock;
+
+	u32 ring_datasize;		/* < ring_size */
+	u32 ring_data_startoffset;
+};
+
+struct hv_ring_buffer_debug_info {
+	u32 current_interrupt_mask;
+	u32 current_read_index;
+	u32 current_write_index;
+	u32 bytes_avail_toread;
+	u32 bytes_avail_towrite;
+};
+
+/*
+ * We use the same version numbering for all Hyper-V modules.
+ *
+ * Definition of versioning is as follows;
+ *
+ *	Major Number	Changes for these scenarios;
+ *			1.	When a new version of Windows Hyper-V
+ *				is released.
+ *			2.	A Major change has occurred in the
+ *				Linux IC's.
+ *			(For example the merge for the first time
+ *			into the kernel) Every time the Major Number
+ *			changes, the Revision number is reset to 0.
+ *	Minor Number	Changes when new functionality is added
+ *			to the Linux IC's that is not a bug fix.
+ *
+ * 3.1 - Added completed hv_utils driver. Shutdown/Heartbeat/Timesync
+ */
+#define HV_DRV_VERSION           "3.1"
+
+
+/*
+ * A revision number of vmbus that is used for ensuring both ends on a
+ * partition are using compatible versions.
+ */
+#define VMBUS_REVISION_NUMBER		13
+
+/* Make maximum size of pipe payload of 16K */
+#define MAX_PIPE_DATA_PAYLOAD		(sizeof(u8) * 16384)
+
+/* Define PipeMode values. */
+#define VMBUS_PIPE_TYPE_BYTE		0x00000000
+#define VMBUS_PIPE_TYPE_MESSAGE		0x00000004
+
+/* The size of the user defined data buffer for non-pipe offers. */
+#define MAX_USER_DEFINED_BYTES		120
+
+/* The size of the user defined data buffer for pipe offers. */
+#define MAX_PIPE_USER_DEFINED_BYTES	116
+
+/*
+ * At the center of the Channel Management library is the Channel Offer. This
+ * struct contains the fundamental information about an offer.
+ */
+struct vmbus_channel_offer {
+	struct hv_guid if_type;
+	struct hv_guid if_instance;
+	u64 int_latency; /* in 100ns units */
+	u32 if_revision;
+	u32 server_ctx_size;	/* in bytes */
+	u16 chn_flags;
+	u16 mmio_megabytes;		/* in bytes * 1024 * 1024 */
+
+	union {
+		/* Non-pipes: The user has MAX_USER_DEFINED_BYTES bytes. */
+		struct {
+			unsigned char user_def[MAX_USER_DEFINED_BYTES];
+		} std;
+
+		/*
+		 * Pipes:
+		 * The following sructure is an integrated pipe protocol, which
+		 * is implemented on top of standard user-defined data. Pipe
+		 * clients have MAX_PIPE_USER_DEFINED_BYTES left for their own
+		 * use.
+		 */
+		struct {
+			u32  pipe_mode;
+			unsigned char user_def[MAX_PIPE_USER_DEFINED_BYTES];
+		} pipe;
+	} u;
+	u32 padding;
+} __packed;
+
+/* Server Flags */
+#define VMBUS_CHANNEL_ENUMERATE_DEVICE_INTERFACE	1
+#define VMBUS_CHANNEL_SERVER_SUPPORTS_TRANSFER_PAGES	2
+#define VMBUS_CHANNEL_SERVER_SUPPORTS_GPADLS		4
+#define VMBUS_CHANNEL_NAMED_PIPE_MODE			0x10
+#define VMBUS_CHANNEL_LOOPBACK_OFFER			0x100
+#define VMBUS_CHANNEL_PARENT_OFFER			0x200
+#define VMBUS_CHANNEL_REQUEST_MONITORED_NOTIFICATION	0x400
+
+struct vmpacket_descriptor {
+	u16 type;
+	u16 offset8;
+	u16 len8;
+	u16 flags;
+	u64 trans_id;
+} __packed;
+
+struct vmpacket_header {
+	u32 prev_pkt_start_offset;
+	struct vmpacket_descriptor descriptor;
+} __packed;
+
+struct vmtransfer_page_range {
+	u32 byte_count;
+	u32 byte_offset;
+} __packed;
+
+struct vmtransfer_page_packet_header {
+	struct vmpacket_descriptor d;
+	u16 xfer_pageset_id;
+	bool sender_owns_set;
+	u8 reserved;
+	u32 range_cnt;
+	struct vmtransfer_page_range ranges[1];
+} __packed;
+
+struct vmgpadl_packet_header {
+	struct vmpacket_descriptor d;
+	u32 gpadl;
+	u32 reserved;
+} __packed;
+
+struct vmadd_remove_transfer_page_set {
+	struct vmpacket_descriptor d;
+	u32 gpadl;
+	u16 xfer_pageset_id;
+	u16 reserved;
+} __packed;
+
+/*
+ * This structure defines a range in guest physical space that can be made to
+ * look virtually contiguous.
+ */
+struct gpa_range {
+	u32 byte_count;
+	u32 byte_offset;
+	u64 pfn_array[0];
+};
+
+/*
+ * This is the format for an Establish Gpadl packet, which contains a handle by
+ * which this GPADL will be known and a set of GPA ranges associated with it.
+ * This can be converted to a MDL by the guest OS.  If there are multiple GPA
+ * ranges, then the resulting MDL will be "chained," representing multiple VA
+ * ranges.
+ */
+struct vmestablish_gpadl {
+	struct vmpacket_descriptor d;
+	u32 gpadl;
+	u32 range_cnt;
+	struct gpa_range range[1];
+} __packed;
+
+/*
+ * This is the format for a Teardown Gpadl packet, which indicates that the
+ * GPADL handle in the Establish Gpadl packet will never be referenced again.
+ */
+struct vmteardown_gpadl {
+	struct vmpacket_descriptor d;
+	u32 gpadl;
+	u32 reserved;	/* for alignment to a 8-byte boundary */
+} __packed;
+
+/*
+ * This is the format for a GPA-Direct packet, which contains a set of GPA
+ * ranges, in addition to commands and/or data.
+ */
+struct vmdata_gpa_direct {
+	struct vmpacket_descriptor d;
+	u32 reserved;
+	u32 range_cnt;
+	struct gpa_range range[1];
+} __packed;
+
+/* This is the format for a Additional Data Packet. */
+struct vmadditional_data {
+	struct vmpacket_descriptor d;
+	u64 total_bytes;
+	u32 offset;
+	u32 byte_cnt;
+	unsigned char data[1];
+} __packed;
+
+union vmpacket_largest_possible_header {
+	struct vmpacket_descriptor simple_hdr;
+	struct vmtransfer_page_packet_header xfer_page_hdr;
+	struct vmgpadl_packet_header gpadl_hdr;
+	struct vmadd_remove_transfer_page_set add_rm_xfer_page_hdr;
+	struct vmestablish_gpadl establish_gpadl_hdr;
+	struct vmteardown_gpadl teardown_gpadl_hdr;
+	struct vmdata_gpa_direct data_gpa_direct_hdr;
+};
+
+#define VMPACKET_DATA_START_ADDRESS(__packet)	\
+	(void *)(((unsigned char *)__packet) +	\
+	 ((struct vmpacket_descriptor)__packet)->offset8 * 8)
+
+#define VMPACKET_DATA_LENGTH(__packet)		\
+	((((struct vmpacket_descriptor)__packet)->len8 -	\
+	  ((struct vmpacket_descriptor)__packet)->offset8) * 8)
+
+#define VMPACKET_TRANSFER_MODE(__packet)	\
+	(((struct IMPACT)__packet)->type)
+
+enum vmbus_packet_type {
+	VM_PKT_INVALID				= 0x0,
+	VM_PKT_SYNCH				= 0x1,
+	VM_PKT_ADD_XFER_PAGESET			= 0x2,
+	VM_PKT_RM_XFER_PAGESET			= 0x3,
+	VM_PKT_ESTABLISH_GPADL			= 0x4,
+	VM_PKT_TEARDOWN_GPADL			= 0x5,
+	VM_PKT_DATA_INBAND			= 0x6,
+	VM_PKT_DATA_USING_XFER_PAGES		= 0x7,
+	VM_PKT_DATA_USING_GPADL			= 0x8,
+	VM_PKT_DATA_USING_GPA_DIRECT		= 0x9,
+	VM_PKT_CANCEL_REQUEST			= 0xa,
+	VM_PKT_COMP				= 0xb,
+	VM_PKT_DATA_USING_ADDITIONAL_PKT	= 0xc,
+	VM_PKT_ADDITIONAL_DATA			= 0xd
+};
+
+#define VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED	1
+
+
+/* Version 1 messages */
+enum vmbus_channel_message_type {
+	CHANNELMSG_INVALID			=  0,
+	CHANNELMSG_OFFERCHANNEL		=  1,
+	CHANNELMSG_RESCIND_CHANNELOFFER	=  2,
+	CHANNELMSG_REQUESTOFFERS		=  3,
+	CHANNELMSG_ALLOFFERS_DELIVERED	=  4,
+	CHANNELMSG_OPENCHANNEL		=  5,
+	CHANNELMSG_OPENCHANNEL_RESULT		=  6,
+	CHANNELMSG_CLOSECHANNEL		=  7,
+	CHANNELMSG_GPADL_HEADER		=  8,
+	CHANNELMSG_GPADL_BODY			=  9,
+	CHANNELMSG_GPADL_CREATED		= 10,
+	CHANNELMSG_GPADL_TEARDOWN		= 11,
+	CHANNELMSG_GPADL_TORNDOWN		= 12,
+	CHANNELMSG_RELID_RELEASED		= 13,
+	CHANNELMSG_INITIATE_CONTACT		= 14,
+	CHANNELMSG_VERSION_RESPONSE		= 15,
+	CHANNELMSG_UNLOAD			= 16,
+#ifdef VMBUS_FEATURE_PARENT_OR_PEER_MEMORY_MAPPED_INTO_A_CHILD
+	CHANNELMSG_VIEWRANGE_ADD		= 17,
+	CHANNELMSG_VIEWRANGE_REMOVE		= 18,
+#endif
+	CHANNELMSG_COUNT
+};
+
+struct vmbus_channel_message_header {
+	enum vmbus_channel_message_type msgtype;
+	u32 padding;
+} __packed;
+
+/* Query VMBus Version parameters */
+struct vmbus_channel_query_vmbus_version {
+	struct vmbus_channel_message_header header;
+	u32 version;
+} __packed;
+
+/* VMBus Version Supported parameters */
+struct vmbus_channel_version_supported {
+	struct vmbus_channel_message_header header;
+	bool version_supported;
+} __packed;
+
+/* Offer Channel parameters */
+struct vmbus_channel_offer_channel {
+	struct vmbus_channel_message_header header;
+	struct vmbus_channel_offer offer;
+	u32 child_relid;
+	u8 monitorid;
+	bool monitor_allocated;
+} __packed;
+
+/* Rescind Offer parameters */
+struct vmbus_channel_rescind_offer {
+	struct vmbus_channel_message_header header;
+	u32 child_relid;
+} __packed;
+
+/*
+ * Request Offer -- no parameters, SynIC message contains the partition ID
+ * Set Snoop -- no parameters, SynIC message contains the partition ID
+ * Clear Snoop -- no parameters, SynIC message contains the partition ID
+ * All Offers Delivered -- no parameters, SynIC message contains the partition
+ *		           ID
+ * Flush Client -- no parameters, SynIC message contains the partition ID
+ */
+
+/* Open Channel parameters */
+struct vmbus_channel_open_channel {
+	struct vmbus_channel_message_header header;
+
+	/* Identifies the specific VMBus channel that is being opened. */
+	u32 child_relid;
+
+	/* ID making a particular open request at a channel offer unique. */
+	u32 openid;
+
+	/* GPADL for the channel's ring buffer. */
+	u32 ringbuffer_gpadlhandle;
+
+	/* GPADL for the channel's server context save area. */
+	u32 server_contextarea_gpadlhandle;
+
+	/*
+	* The upstream ring buffer begins at offset zero in the memory
+	* described by RingBufferGpadlHandle. The downstream ring buffer
+	* follows it at this offset (in pages).
+	*/
+	u32 downstream_ringbuffer_pageoffset;
+
+	/* User-specific data to be passed along to the server endpoint. */
+	unsigned char userdata[MAX_USER_DEFINED_BYTES];
+} __packed;
+
+/* Open Channel Result parameters */
+struct vmbus_channel_open_result {
+	struct vmbus_channel_message_header header;
+	u32 child_relid;
+	u32 openid;
+	u32 status;
+} __packed;
+
+/* Close channel parameters; */
+struct vmbus_channel_close_channel {
+	struct vmbus_channel_message_header header;
+	u32 child_relid;
+} __packed;
+
+/* Channel Message GPADL */
+#define GPADL_TYPE_RING_BUFFER		1
+#define GPADL_TYPE_SERVER_SAVE_AREA	2
+#define GPADL_TYPE_TRANSACTION		8
+
+/*
+ * The number of PFNs in a GPADL message is defined by the number of
+ * pages that would be spanned by ByteCount and ByteOffset.  If the
+ * implied number of PFNs won't fit in this packet, there will be a
+ * follow-up packet that contains more.
+ */
+struct vmbus_channel_gpadl_header {
+	struct vmbus_channel_message_header header;
+	u32 child_relid;
+	u32 gpadl;
+	u16 range_buflen;
+	u16 rangecount;
+	struct gpa_range range[0];
+} __packed;
+
+/* This is the followup packet that contains more PFNs. */
+struct vmbus_channel_gpadl_body {
+	struct vmbus_channel_message_header header;
+	u32 msgnumber;
+	u32 gpadl;
+	u64 pfn[0];
+} __packed;
+
+struct vmbus_channel_gpadl_created {
+	struct vmbus_channel_message_header header;
+	u32 child_relid;
+	u32 gpadl;
+	u32 creation_status;
+} __packed;
+
+struct vmbus_channel_gpadl_teardown {
+	struct vmbus_channel_message_header header;
+	u32 child_relid;
+	u32 gpadl;
+} __packed;
+
+struct vmbus_channel_gpadl_torndown {
+	struct vmbus_channel_message_header header;
+	u32 gpadl;
+} __packed;
+
+#ifdef VMBUS_FEATURE_PARENT_OR_PEER_MEMORY_MAPPED_INTO_A_CHILD
+struct vmbus_channel_view_range_add {
+	struct vmbus_channel_message_header header;
+	PHYSICAL_ADDRESS viewrange_base;
+	u64 viewrange_length;
+	u32 child_relid;
+} __packed;
+
+struct vmbus_channel_view_range_remove {
+	struct vmbus_channel_message_header header;
+	PHYSICAL_ADDRESS viewrange_base;
+	u32 child_relid;
+} __packed;
+#endif
+
+struct vmbus_channel_relid_released {
+	struct vmbus_channel_message_header header;
+	u32 child_relid;
+} __packed;
+
+struct vmbus_channel_initiate_contact {
+	struct vmbus_channel_message_header header;
+	u32 vmbus_version_requested;
+	u32 padding2;
+	u64 interrupt_page;
+	u64 monitor_page1;
+	u64 monitor_page2;
+} __packed;
+
+struct vmbus_channel_version_response {
+	struct vmbus_channel_message_header header;
+	bool version_supported;
+} __packed;
+
+enum vmbus_channel_state {
+	CHANNEL_OFFER_STATE,
+	CHANNEL_OPENING_STATE,
+	CHANNEL_OPEN_STATE,
+};
+
+struct vmbus_channel_debug_info {
+	u32 relid;
+	enum vmbus_channel_state state;
+	struct hv_guid interfacetype;
+	struct hv_guid interface_instance;
+	u32 monitorid;
+	u32 servermonitor_pending;
+	u32 servermonitor_latency;
+	u32 servermonitor_connectionid;
+	u32 clientmonitor_pending;
+	u32 clientmonitor_latency;
+	u32 clientmonitor_connectionid;
+
+	struct hv_ring_buffer_debug_info inbound;
+	struct hv_ring_buffer_debug_info outbound;
+};
+
+/*
+ * Represents each channel msg on the vmbus connection This is a
+ * variable-size data structure depending on the msg type itself
+ */
+struct vmbus_channel_msginfo {
+	/* Bookkeeping stuff */
+	struct list_head msglistentry;
+
+	/* So far, this is only used to handle gpadl body message */
+	struct list_head submsglist;
+
+	/* Synchronize the request/response if needed */
+	struct completion  waitevent;
+	union {
+		struct vmbus_channel_version_supported version_supported;
+		struct vmbus_channel_open_result open_result;
+		struct vmbus_channel_gpadl_torndown gpadl_torndown;
+		struct vmbus_channel_gpadl_created gpadl_created;
+		struct vmbus_channel_version_response version_response;
+	} response;
+
+	u32 msgsize;
+	/*
+	 * The channel message that goes out on the "wire".
+	 * It will contain at minimum the VMBUS_CHANNEL_MESSAGE_HEADER header
+	 */
+	unsigned char msg[0];
+};
+
+struct vmbus_close_msg {
+	struct vmbus_channel_msginfo info;
+	struct vmbus_channel_close_channel msg;
+};
+
+struct vmbus_channel {
+	struct list_head listentry;
+
+	struct hv_device *device_obj;
+
+	struct work_struct work;
+
+	enum vmbus_channel_state state;
+	/*
+	 * For util channels, stash the
+	 * the service index for easy access.
+	 */
+	s8 util_index;
+
+	struct vmbus_channel_offer_channel offermsg;
+	/*
+	 * These are based on the OfferMsg.MonitorId.
+	 * Save it here for easy access.
+	 */
+	u8 monitor_grp;
+	u8 monitor_bit;
+
+	u32 ringbuffer_gpadlhandle;
+
+	/* Allocated memory for ring buffer */
+	void *ringbuffer_pages;
+	u32 ringbuffer_pagecount;
+	struct hv_ring_buffer_info outbound;	/* send to parent */
+	struct hv_ring_buffer_info inbound;	/* receive from parent */
+	spinlock_t inbound_lock;
+	struct workqueue_struct *controlwq;
+
+	struct vmbus_close_msg close_msg;
+
+	/* Channel callback are invoked in this workqueue context */
+	/* HANDLE dataWorkQueue; */
+
+	void (*onchannel_callback)(void *context);
+	void *channel_callback_context;
+};
+
+void free_channel(struct vmbus_channel *channel);
+
+void vmbus_onmessage(void *context);
+
+int vmbus_request_offers(void);
+
+/* The format must be the same as struct vmdata_gpa_direct */
+struct vmbus_channel_packet_page_buffer {
+	u16 type;
+	u16 dataoffset8;
+	u16 length8;
+	u16 flags;
+	u64 transactionid;
+	u32 reserved;
+	u32 rangecount;
+	struct hv_page_buffer range[MAX_PAGE_BUFFER_COUNT];
+} __packed;
+
+/* The format must be the same as struct vmdata_gpa_direct */
+struct vmbus_channel_packet_multipage_buffer {
+	u16 type;
+	u16 dataoffset8;
+	u16 length8;
+	u16 flags;
+	u64 transactionid;
+	u32 reserved;
+	u32 rangecount;		/* Always 1 in this case */
+	struct hv_multipage_buffer range;
+} __packed;
+
+
+extern int vmbus_open(struct vmbus_channel *channel,
+			    u32 send_ringbuffersize,
+			    u32 recv_ringbuffersize,
+			    void *userdata,
+			    u32 userdatalen,
+			    void(*onchannel_callback)(void *context),
+			    void *context);
+
+extern void vmbus_close(struct vmbus_channel *channel);
+
+extern int vmbus_sendpacket(struct vmbus_channel *channel,
+				  const void *buffer,
+				  u32 bufferLen,
+				  u64 requestid,
+				  enum vmbus_packet_type type,
+				  u32 flags);
+
+extern int vmbus_sendpacket_pagebuffer(struct vmbus_channel *channel,
+					    struct hv_page_buffer pagebuffers[],
+					    u32 pagecount,
+					    void *buffer,
+					    u32 bufferlen,
+					    u64 requestid);
+
+extern int vmbus_sendpacket_multipagebuffer(struct vmbus_channel *channel,
+					struct hv_multipage_buffer *mpb,
+					void *buffer,
+					u32 bufferlen,
+					u64 requestid);
+
+extern int vmbus_establish_gpadl(struct vmbus_channel *channel,
+				      void *kbuffer,
+				      u32 size,
+				      u32 *gpadl_handle);
+
+extern int vmbus_teardown_gpadl(struct vmbus_channel *channel,
+				     u32 gpadl_handle);
+
+extern int vmbus_recvpacket(struct vmbus_channel *channel,
+				  void *buffer,
+				  u32 bufferlen,
+				  u32 *buffer_actual_len,
+				  u64 *requestid);
+
+extern int vmbus_recvpacket_raw(struct vmbus_channel *channel,
+				     void *buffer,
+				     u32 bufferlen,
+				     u32 *buffer_actual_len,
+				     u64 *requestid);
+
+
+extern void vmbus_get_debug_info(struct vmbus_channel *channel,
+				     struct vmbus_channel_debug_info *debug);
+
+extern void vmbus_ontimer(unsigned long data);
+
+
+#define LOWORD(dw) ((unsigned short)(dw))
+#define HIWORD(dw) ((unsigned short)(((unsigned int) (dw) >> 16) & 0xFFFF))
+
+
+#define VMBUS				0x0001
+#define STORVSC				0x0002
+#define NETVSC				0x0004
+#define INPUTVSC			0x0008
+#define BLKVSC				0x0010
+#define VMBUS_DRV			0x0100
+#define STORVSC_DRV			0x0200
+#define NETVSC_DRV			0x0400
+#define INPUTVSC_DRV		0x0800
+#define BLKVSC_DRV			0x1000
+
+#define ALL_MODULES			(VMBUS		|\
+							STORVSC		|\
+							NETVSC		|\
+							INPUTVSC	|\
+							BLKVSC		|\
+							VMBUS_DRV	|\
+							STORVSC_DRV	|\
+							NETVSC_DRV	|\
+							INPUTVSC_DRV|\
+							BLKVSC_DRV)
+
+/* Logging Level */
+#define ERROR_LVL				3
+#define WARNING_LVL				4
+#define INFO_LVL				6
+#define DEBUG_LVL				7
+#define DEBUG_LVL_ENTEREXIT			8
+#define DEBUG_RING_LVL				9
+
+extern unsigned int vmbus_loglevel;
+
+#define DPRINT(mod, lvl, fmt, args...) do {\
+	if ((mod & (HIWORD(vmbus_loglevel))) &&	\
+	    (lvl <= LOWORD(vmbus_loglevel)))	\
+		printk(KERN_DEBUG #mod": %s() " fmt "\n", __func__, ## args);\
+	} while (0)
+
+#define DPRINT_DBG(mod, fmt, args...) do {\
+	if ((mod & (HIWORD(vmbus_loglevel))) &&		\
+	    (DEBUG_LVL <= LOWORD(vmbus_loglevel)))	\
+		printk(KERN_DEBUG #mod": %s() " fmt "\n", __func__, ## args);\
+	} while (0)
+
+#define DPRINT_INFO(mod, fmt, args...) do {\
+	if ((mod & (HIWORD(vmbus_loglevel))) &&		\
+	    (INFO_LVL <= LOWORD(vmbus_loglevel)))	\
+		printk(KERN_INFO #mod": " fmt "\n", ## args);\
+	} while (0)
+
+#define DPRINT_WARN(mod, fmt, args...) do {\
+	if ((mod & (HIWORD(vmbus_loglevel))) &&		\
+	    (WARNING_LVL <= LOWORD(vmbus_loglevel)))	\
+		printk(KERN_WARNING #mod": WARNING! " fmt "\n", ## args);\
+	} while (0)
+
+#define DPRINT_ERR(mod, fmt, args...) do {\
+	if ((mod & (HIWORD(vmbus_loglevel))) &&		\
+	    (ERROR_LVL <= LOWORD(vmbus_loglevel)))	\
+		printk(KERN_ERR #mod": %s() ERROR!! " fmt "\n",	\
+		       __func__, ## args);\
+	} while (0)
+
+
+
+struct hv_driver;
+struct hv_device;
+
+struct hv_dev_port_info {
+	u32 int_mask;
+	u32 read_idx;
+	u32 write_idx;
+	u32 bytes_avail_toread;
+	u32 bytes_avail_towrite;
+};
+
+struct hv_device_info {
+	u32 chn_id;
+	u32 chn_state;
+	struct hv_guid chn_type;
+	struct hv_guid chn_instance;
+
+	u32 monitor_id;
+	u32 server_monitor_pending;
+	u32 server_monitor_latency;
+	u32 server_monitor_conn_id;
+	u32 client_monitor_pending;
+	u32 client_monitor_latency;
+	u32 client_monitor_conn_id;
+
+	struct hv_dev_port_info inbound;
+	struct hv_dev_port_info outbound;
+};
+
+/* Base driver object */
+struct hv_driver {
+	const char *name;
+
+	/* the device type supported by this driver */
+	struct hv_guid dev_type;
+
+	struct device_driver driver;
+
+	int (*probe)(struct hv_device *);
+	int (*remove)(struct hv_device *);
+	void (*shutdown)(struct hv_device *);
+
+};
+
+/* Base device object */
+struct hv_device {
+	/* the device type id of this device */
+	struct hv_guid dev_type;
+
+	/* the device instance id of this device */
+	struct hv_guid dev_instance;
+
+	struct device device;
+
+	struct vmbus_channel *channel;
+
+	/* Device extension; */
+	void *ext;
+};
+
+
+static inline struct hv_device *device_to_hv_device(struct device *d)
+{
+	return container_of(d, struct hv_device, device);
+}
+
+static inline struct hv_driver *drv_to_hv_drv(struct device_driver *d)
+{
+	return container_of(d, struct hv_driver, driver);
+}
+
+
+/* Vmbus interface */
+int vmbus_child_driver_register(struct device_driver *drv);
+void vmbus_child_driver_unregister(struct device_driver *drv);
+
+/*
+ * Common header for Hyper-V ICs
+ */
+
+#define ICMSGTYPE_NEGOTIATE		0
+#define ICMSGTYPE_HEARTBEAT		1
+#define ICMSGTYPE_KVPEXCHANGE		2
+#define ICMSGTYPE_SHUTDOWN		3
+#define ICMSGTYPE_TIMESYNC		4
+#define ICMSGTYPE_VSS			5
+
+#define ICMSGHDRFLAG_TRANSACTION	1
+#define ICMSGHDRFLAG_REQUEST		2
+#define ICMSGHDRFLAG_RESPONSE		4
+
+#define HV_S_OK				0x00000000
+#define HV_E_FAIL			0x80004005
+#define HV_ERROR_NOT_SUPPORTED		0x80070032
+#define HV_ERROR_MACHINE_LOCKED		0x800704F7
+
+struct vmbuspipe_hdr {
+	u32 flags;
+	u32 msgsize;
+} __packed;
+
+struct ic_version {
+	u16 major;
+	u16 minor;
+} __packed;
+
+struct icmsg_hdr {
+	struct ic_version icverframe;
+	u16 icmsgtype;
+	struct ic_version icvermsg;
+	u16 icmsgsize;
+	u32 status;
+	u8 ictransaction_id;
+	u8 icflags;
+	u8 reserved[2];
+} __packed;
+
+struct icmsg_negotiate {
+	u16 icframe_vercnt;
+	u16 icmsg_vercnt;
+	u32 reserved;
+	struct ic_version icversion_data[1]; /* any size array */
+} __packed;
+
+struct shutdown_msg_data {
+	u32 reason_code;
+	u32 timeout_seconds;
+	u32 flags;
+	u8  display_message[2048];
+} __packed;
+
+struct heartbeat_msg_data {
+	u64 seq_num;
+	u32 reserved[8];
+} __packed;
+
+/* Time Sync IC defs */
+#define ICTIMESYNCFLAG_PROBE	0
+#define ICTIMESYNCFLAG_SYNC	1
+#define ICTIMESYNCFLAG_SAMPLE	2
+
+#ifdef __x86_64__
+#define WLTIMEDELTA	116444736000000000L	/* in 100ns unit */
+#else
+#define WLTIMEDELTA	116444736000000000LL
+#endif
+
+struct ictimesync_data {
+	u64 parenttime;
+	u64 childtime;
+	u64 roundtriptime;
+	u8 flags;
+} __packed;
+
+/* Index for each IC struct in array hv_cb_utils[] */
+#define HV_SHUTDOWN_MSG		0
+#define HV_TIMESYNC_MSG		1
+#define HV_HEARTBEAT_MSG	2
+#define HV_KVP_MSG		3
+
+struct hyperv_service_callback {
+	u8 msg_type;
+	char *log_msg;
+	unsigned char data[16];
+	struct vmbus_channel *channel;
+	void (*callback) (void *context);
+};
+
+extern void prep_negotiate_resp(struct icmsg_hdr *,
+				struct icmsg_negotiate *, u8 *);
+extern void chn_cb_negotiate(void *);
+extern struct hyperv_service_callback hv_cb_utils[];
+
+#endif /* _HYPERV_H */
diff --git a/drivers/staging/hv/hyperv_net.h b/drivers/staging/hv/hyperv_net.h
new file mode 100644
index 0000000..27f987b
--- /dev/null
+++ b/drivers/staging/hv/hyperv_net.h
@@ -0,0 +1,1057 @@
+/*
+ *
+ * Copyright (c) 2011, Microsoft Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * Authors:
+ *   Haiyang Zhang <haiyangz@microsoft.com>
+ *   Hank Janssen  <hjanssen@microsoft.com>
+ *   K. Y. Srinivasan <kys@microsoft.com>
+ *
+ */
+
+#ifndef _HYPERV_NET_H
+#define _HYPERV_NET_H
+
+#include <linux/list.h>
+#include "hyperv.h"
+
+/* Fwd declaration */
+struct hv_netvsc_packet;
+
+/* Represent the xfer page packet which contains 1 or more netvsc packet */
+struct xferpage_packet {
+	struct list_head list_ent;
+
+	/* # of netvsc packets this xfer packet contains */
+	u32 count;
+};
+
+/* The number of pages which are enough to cover jumbo frame buffer. */
+#define NETVSC_PACKET_MAXPAGE		4
+
+/*
+ * Represent netvsc packet which contains 1 RNDIS and 1 ethernet frame
+ * within the RNDIS
+ */
+struct hv_netvsc_packet {
+	/* Bookkeeping stuff */
+	struct list_head list_ent;
+
+	struct hv_device *device;
+	bool is_data_pkt;
+
+	/*
+	 * Valid only for receives when we break a xfer page packet
+	 * into multiple netvsc packets
+	 */
+	struct xferpage_packet *xfer_page_pkt;
+
+	union {
+		struct {
+			u64 recv_completion_tid;
+			void *recv_completion_ctx;
+			void (*recv_completion)(void *context);
+		} recv;
+		struct {
+			u64 send_completion_tid;
+			void *send_completion_ctx;
+			void (*send_completion)(void *context);
+		} send;
+	} completion;
+
+	/* This points to the memory after page_buf */
+	void *extension;
+
+	u32 total_data_buflen;
+	/* Points to the send/receive buffer where the ethernet frame is */
+	u32 page_buf_cnt;
+	struct hv_page_buffer page_buf[NETVSC_PACKET_MAXPAGE];
+};
+
+struct netvsc_device_info {
+	unsigned char mac_adr[6];
+	bool link_state;	/* 0 - link up, 1 - link down */
+	int  ring_size;
+};
+
+/* Interface */
+int netvsc_device_add(struct hv_device *device, void *additional_info);
+int netvsc_device_remove(struct hv_device *device);
+int netvsc_send(struct hv_device *device,
+		struct hv_netvsc_packet *packet);
+void netvsc_linkstatus_callback(struct hv_device *device_obj,
+				unsigned int status);
+int netvsc_recv_callback(struct hv_device *device_obj,
+			struct hv_netvsc_packet *packet);
+int netvsc_initialize(struct hv_driver *drv);
+int rndis_filter_open(struct hv_device *dev);
+int rndis_filter_close(struct hv_device *dev);
+int rndis_filter_device_add(struct hv_device *dev,
+			void *additional_info);
+void rndis_filter_device_remove(struct hv_device *dev);
+int rndis_filter_receive(struct hv_device *dev,
+			struct hv_netvsc_packet *pkt);
+
+
+
+int rndis_filter_send(struct hv_device *dev,
+			struct hv_netvsc_packet *pkt);
+
+#define NVSP_INVALID_PROTOCOL_VERSION	((u32)0xFFFFFFFF)
+
+#define NVSP_PROTOCOL_VERSION_1		2
+#define NVSP_MIN_PROTOCOL_VERSION	NVSP_PROTOCOL_VERSION_1
+#define NVSP_MAX_PROTOCOL_VERSION	NVSP_PROTOCOL_VERSION_1
+
+enum {
+	NVSP_MSG_TYPE_NONE = 0,
+
+	/* Init Messages */
+	NVSP_MSG_TYPE_INIT			= 1,
+	NVSP_MSG_TYPE_INIT_COMPLETE		= 2,
+
+	NVSP_VERSION_MSG_START			= 100,
+
+	/* Version 1 Messages */
+	NVSP_MSG1_TYPE_SEND_NDIS_VER		= NVSP_VERSION_MSG_START,
+
+	NVSP_MSG1_TYPE_SEND_RECV_BUF,
+	NVSP_MSG1_TYPE_SEND_RECV_BUF_COMPLETE,
+	NVSP_MSG1_TYPE_REVOKE_RECV_BUF,
+
+	NVSP_MSG1_TYPE_SEND_SEND_BUF,
+	NVSP_MSG1_TYPE_SEND_SEND_BUF_COMPLETE,
+	NVSP_MSG1_TYPE_REVOKE_SEND_BUF,
+
+	NVSP_MSG1_TYPE_SEND_RNDIS_PKT,
+	NVSP_MSG1_TYPE_SEND_RNDIS_PKT_COMPLETE,
+
+	/*
+	 * This should be set to the number of messages for the version with
+	 * the maximum number of messages.
+	 */
+	NVSP_NUM_MSG_PER_VERSION		= 9,
+};
+
+enum {
+	NVSP_STAT_NONE = 0,
+	NVSP_STAT_SUCCESS,
+	NVSP_STAT_FAIL,
+	NVSP_STAT_PROTOCOL_TOO_NEW,
+	NVSP_STAT_PROTOCOL_TOO_OLD,
+	NVSP_STAT_INVALID_RNDIS_PKT,
+	NVSP_STAT_BUSY,
+	NVSP_STAT_MAX,
+};
+
+struct nvsp_message_header {
+	u32 msg_type;
+};
+
+/* Init Messages */
+
+/*
+ * This message is used by the VSC to initialize the channel after the channels
+ * has been opened. This message should never include anything other then
+ * versioning (i.e. this message will be the same for ever).
+ */
+struct nvsp_message_init {
+	u32 min_protocol_ver;
+	u32 max_protocol_ver;
+} __packed;
+
+/*
+ * This message is used by the VSP to complete the initialization of the
+ * channel. This message should never include anything other then versioning
+ * (i.e. this message will be the same for ever).
+ */
+struct nvsp_message_init_complete {
+	u32 negotiated_protocol_ver;
+	u32 max_mdl_chain_len;
+	u32 status;
+} __packed;
+
+union nvsp_message_init_uber {
+	struct nvsp_message_init init;
+	struct nvsp_message_init_complete init_complete;
+} __packed;
+
+/* Version 1 Messages */
+
+/*
+ * This message is used by the VSC to send the NDIS version to the VSP. The VSP
+ * can use this information when handling OIDs sent by the VSC.
+ */
+struct nvsp_1_message_send_ndis_version {
+	u32 ndis_major_ver;
+	u32 ndis_minor_ver;
+} __packed;
+
+/*
+ * This message is used by the VSC to send a receive buffer to the VSP. The VSP
+ * can then use the receive buffer to send data to the VSC.
+ */
+struct nvsp_1_message_send_receive_buffer {
+	u32 gpadl_handle;
+	u16 id;
+} __packed;
+
+struct nvsp_1_receive_buffer_section {
+	u32 offset;
+	u32 sub_alloc_size;
+	u32 num_sub_allocs;
+	u32 end_offset;
+} __packed;
+
+/*
+ * This message is used by the VSP to acknowledge a receive buffer send by the
+ * VSC. This message must be sent by the VSP before the VSP uses the receive
+ * buffer.
+ */
+struct nvsp_1_message_send_receive_buffer_complete {
+	u32 status;
+	u32 num_sections;
+
+	/*
+	 * The receive buffer is split into two parts, a large suballocation
+	 * section and a small suballocation section. These sections are then
+	 * suballocated by a certain size.
+	 */
+
+	/*
+	 * For example, the following break up of the receive buffer has 6
+	 * large suballocations and 10 small suballocations.
+	 */
+
+	/*
+	 * |            Large Section          |  |   Small Section   |
+	 * ------------------------------------------------------------
+	 * |     |     |     |     |     |     |  | | | | | | | | | | |
+	 * |                                      |
+	 *  LargeOffset                            SmallOffset
+	 */
+
+	struct nvsp_1_receive_buffer_section sections[1];
+} __packed;
+
+/*
+ * This message is sent by the VSC to revoke the receive buffer.  After the VSP
+ * completes this transaction, the vsp should never use the receive buffer
+ * again.
+ */
+struct nvsp_1_message_revoke_receive_buffer {
+	u16 id;
+};
+
+/*
+ * This message is used by the VSC to send a send buffer to the VSP. The VSC
+ * can then use the send buffer to send data to the VSP.
+ */
+struct nvsp_1_message_send_send_buffer {
+	u32 gpadl_handle;
+	u16 id;
+} __packed;
+
+/*
+ * This message is used by the VSP to acknowledge a send buffer sent by the
+ * VSC. This message must be sent by the VSP before the VSP uses the sent
+ * buffer.
+ */
+struct nvsp_1_message_send_send_buffer_complete {
+	u32 status;
+
+	/*
+	 * The VSC gets to choose the size of the send buffer and the VSP gets
+	 * to choose the sections size of the buffer.  This was done to enable
+	 * dynamic reconfigurations when the cost of GPA-direct buffers
+	 * decreases.
+	 */
+	u32 section_size;
+} __packed;
+
+/*
+ * This message is sent by the VSC to revoke the send buffer.  After the VSP
+ * completes this transaction, the vsp should never use the send buffer again.
+ */
+struct nvsp_1_message_revoke_send_buffer {
+	u16 id;
+};
+
+/*
+ * This message is used by both the VSP and the VSC to send a RNDIS message to
+ * the opposite channel endpoint.
+ */
+struct nvsp_1_message_send_rndis_packet {
+	/*
+	 * This field is specified by RNIDS. They assume there's two different
+	 * channels of communication. However, the Network VSP only has one.
+	 * Therefore, the channel travels with the RNDIS packet.
+	 */
+	u32 channel_type;
+
+	/*
+	 * This field is used to send part or all of the data through a send
+	 * buffer. This values specifies an index into the send buffer. If the
+	 * index is 0xFFFFFFFF, then the send buffer is not being used and all
+	 * of the data was sent through other VMBus mechanisms.
+	 */
+	u32 send_buf_section_index;
+	u32 send_buf_section_size;
+} __packed;
+
+/*
+ * This message is used by both the VSP and the VSC to complete a RNDIS message
+ * to the opposite channel endpoint. At this point, the initiator of this
+ * message cannot use any resources associated with the original RNDIS packet.
+ */
+struct nvsp_1_message_send_rndis_packet_complete {
+	u32 status;
+};
+
+union nvsp_1_message_uber {
+	struct nvsp_1_message_send_ndis_version send_ndis_ver;
+
+	struct nvsp_1_message_send_receive_buffer send_recv_buf;
+	struct nvsp_1_message_send_receive_buffer_complete
+						send_recv_buf_complete;
+	struct nvsp_1_message_revoke_receive_buffer revoke_recv_buf;
+
+	struct nvsp_1_message_send_send_buffer send_send_buf;
+	struct nvsp_1_message_send_send_buffer_complete send_send_buf_complete;
+	struct nvsp_1_message_revoke_send_buffer revoke_send_buf;
+
+	struct nvsp_1_message_send_rndis_packet send_rndis_pkt;
+	struct nvsp_1_message_send_rndis_packet_complete
+						send_rndis_pkt_complete;
+} __packed;
+
+union nvsp_all_messages {
+	union nvsp_message_init_uber init_msg;
+	union nvsp_1_message_uber v1_msg;
+} __packed;
+
+/* ALL Messages */
+struct nvsp_message {
+	struct nvsp_message_header hdr;
+	union nvsp_all_messages msg;
+} __packed;
+
+
+
+
+/* #define NVSC_MIN_PROTOCOL_VERSION		1 */
+/* #define NVSC_MAX_PROTOCOL_VERSION		1 */
+
+#define NETVSC_RECEIVE_BUFFER_SIZE		(1024*1024)	/* 1MB */
+
+#define NETVSC_RECEIVE_BUFFER_ID		0xcafe
+
+#define NETVSC_RECEIVE_SG_COUNT			1
+
+/* Preallocated receive packets */
+#define NETVSC_RECEIVE_PACKETLIST_COUNT		256
+
+#define NETVSC_PACKET_SIZE                      2048
+
+/* Per netvsc channel-specific */
+struct netvsc_device {
+	struct hv_device *dev;
+
+	atomic_t refcnt;
+	atomic_t num_outstanding_sends;
+	/*
+	 * List of free preallocated hv_netvsc_packet to represent receive
+	 * packet
+	 */
+	struct list_head recv_pkt_list;
+	spinlock_t recv_pkt_list_lock;
+
+	/* Receive buffer allocated by us but manages by NetVSP */
+	void *recv_buf;
+	u32 recv_buf_size;
+	u32 recv_buf_gpadl_handle;
+	u32 recv_section_cnt;
+	struct nvsp_1_receive_buffer_section *recv_section;
+
+	/* Used for NetVSP initialization protocol */
+	struct completion channel_init_wait;
+	struct nvsp_message channel_init_pkt;
+
+	struct nvsp_message revoke_packet;
+	/* unsigned char HwMacAddr[HW_MACADDR_LEN]; */
+
+	/* Holds rndis device info */
+	void *extension;
+};
+
+
+/*  Status codes */
+
+
+#ifndef STATUS_SUCCESS
+#define STATUS_SUCCESS				(0x00000000L)
+#endif
+
+#ifndef STATUS_UNSUCCESSFUL
+#define STATUS_UNSUCCESSFUL			(0xC0000001L)
+#endif
+
+#ifndef STATUS_PENDING
+#define STATUS_PENDING				(0x00000103L)
+#endif
+
+#ifndef STATUS_INSUFFICIENT_RESOURCES
+#define STATUS_INSUFFICIENT_RESOURCES		(0xC000009AL)
+#endif
+
+#ifndef STATUS_BUFFER_OVERFLOW
+#define STATUS_BUFFER_OVERFLOW			(0x80000005L)
+#endif
+
+#ifndef STATUS_NOT_SUPPORTED
+#define STATUS_NOT_SUPPORTED			(0xC00000BBL)
+#endif
+
+#define RNDIS_STATUS_SUCCESS			(STATUS_SUCCESS)
+#define RNDIS_STATUS_PENDING			(STATUS_PENDING)
+#define RNDIS_STATUS_NOT_RECOGNIZED		(0x00010001L)
+#define RNDIS_STATUS_NOT_COPIED			(0x00010002L)
+#define RNDIS_STATUS_NOT_ACCEPTED		(0x00010003L)
+#define RNDIS_STATUS_CALL_ACTIVE		(0x00010007L)
+
+#define RNDIS_STATUS_ONLINE			(0x40010003L)
+#define RNDIS_STATUS_RESET_START		(0x40010004L)
+#define RNDIS_STATUS_RESET_END			(0x40010005L)
+#define RNDIS_STATUS_RING_STATUS		(0x40010006L)
+#define RNDIS_STATUS_CLOSED			(0x40010007L)
+#define RNDIS_STATUS_WAN_LINE_UP		(0x40010008L)
+#define RNDIS_STATUS_WAN_LINE_DOWN		(0x40010009L)
+#define RNDIS_STATUS_WAN_FRAGMENT		(0x4001000AL)
+#define RNDIS_STATUS_MEDIA_CONNECT		(0x4001000BL)
+#define RNDIS_STATUS_MEDIA_DISCONNECT		(0x4001000CL)
+#define RNDIS_STATUS_HARDWARE_LINE_UP		(0x4001000DL)
+#define RNDIS_STATUS_HARDWARE_LINE_DOWN		(0x4001000EL)
+#define RNDIS_STATUS_INTERFACE_UP		(0x4001000FL)
+#define RNDIS_STATUS_INTERFACE_DOWN		(0x40010010L)
+#define RNDIS_STATUS_MEDIA_BUSY			(0x40010011L)
+#define RNDIS_STATUS_MEDIA_SPECIFIC_INDICATION	(0x40010012L)
+#define RNDIS_STATUS_WW_INDICATION		RDIA_SPECIFIC_INDICATION
+#define RNDIS_STATUS_LINK_SPEED_CHANGE		(0x40010013L)
+
+#define RNDIS_STATUS_NOT_RESETTABLE		(0x80010001L)
+#define RNDIS_STATUS_SOFT_ERRORS		(0x80010003L)
+#define RNDIS_STATUS_HARD_ERRORS		(0x80010004L)
+#define RNDIS_STATUS_BUFFER_OVERFLOW		(STATUS_BUFFER_OVERFLOW)
+
+#define RNDIS_STATUS_FAILURE			(STATUS_UNSUCCESSFUL)
+#define RNDIS_STATUS_RESOURCES			(STATUS_INSUFFICIENT_RESOURCES)
+#define RNDIS_STATUS_CLOSING			(0xC0010002L)
+#define RNDIS_STATUS_BAD_VERSION		(0xC0010004L)
+#define RNDIS_STATUS_BAD_CHARACTERISTICS	(0xC0010005L)
+#define RNDIS_STATUS_ADAPTER_NOT_FOUND		(0xC0010006L)
+#define RNDIS_STATUS_OPEN_FAILED		(0xC0010007L)
+#define RNDIS_STATUS_DEVICE_FAILED		(0xC0010008L)
+#define RNDIS_STATUS_MULTICAST_FULL		(0xC0010009L)
+#define RNDIS_STATUS_MULTICAST_EXISTS		(0xC001000AL)
+#define RNDIS_STATUS_MULTICAST_NOT_FOUND	(0xC001000BL)
+#define RNDIS_STATUS_REQUEST_ABORTED		(0xC001000CL)
+#define RNDIS_STATUS_RESET_IN_PROGRESS		(0xC001000DL)
+#define RNDIS_STATUS_CLOSING_INDICATING		(0xC001000EL)
+#define RNDIS_STATUS_NOT_SUPPORTED		(STATUS_NOT_SUPPORTED)
+#define RNDIS_STATUS_INVALID_PACKET		(0xC001000FL)
+#define RNDIS_STATUS_OPEN_LIST_FULL		(0xC0010010L)
+#define RNDIS_STATUS_ADAPTER_NOT_READY		(0xC0010011L)
+#define RNDIS_STATUS_ADAPTER_NOT_OPEN		(0xC0010012L)
+#define RNDIS_STATUS_NOT_INDICATING		(0xC0010013L)
+#define RNDIS_STATUS_INVALID_LENGTH		(0xC0010014L)
+#define RNDIS_STATUS_INVALID_DATA		(0xC0010015L)
+#define RNDIS_STATUS_BUFFER_TOO_SHORT		(0xC0010016L)
+#define RNDIS_STATUS_INVALID_OID		(0xC0010017L)
+#define RNDIS_STATUS_ADAPTER_REMOVED		(0xC0010018L)
+#define RNDIS_STATUS_UNSUPPORTED_MEDIA		(0xC0010019L)
+#define RNDIS_STATUS_GROUP_ADDRESS_IN_USE	(0xC001001AL)
+#define RNDIS_STATUS_FILE_NOT_FOUND		(0xC001001BL)
+#define RNDIS_STATUS_ERROR_READING_FILE		(0xC001001CL)
+#define RNDIS_STATUS_ALREADY_MAPPED		(0xC001001DL)
+#define RNDIS_STATUS_RESOURCE_CONFLICT		(0xC001001EL)
+#define RNDIS_STATUS_NO_CABLE			(0xC001001FL)
+
+#define RNDIS_STATUS_INVALID_SAP		(0xC0010020L)
+#define RNDIS_STATUS_SAP_IN_USE			(0xC0010021L)
+#define RNDIS_STATUS_INVALID_ADDRESS		(0xC0010022L)
+#define RNDIS_STATUS_VC_NOT_ACTIVATED		(0xC0010023L)
+#define RNDIS_STATUS_DEST_OUT_OF_ORDER		(0xC0010024L)
+#define RNDIS_STATUS_VC_NOT_AVAILABLE		(0xC0010025L)
+#define RNDIS_STATUS_CELLRATE_NOT_AVAILABLE	(0xC0010026L)
+#define RNDIS_STATUS_INCOMPATABLE_QOS		(0xC0010027L)
+#define RNDIS_STATUS_AAL_PARAMS_UNSUPPORTED	(0xC0010028L)
+#define RNDIS_STATUS_NO_ROUTE_TO_DESTINATION	(0xC0010029L)
+
+#define RNDIS_STATUS_TOKEN_RING_OPEN_ERROR	(0xC0011000L)
+
+/* Object Identifiers used by NdisRequest Query/Set Information */
+/* General Objects */
+#define RNDIS_OID_GEN_SUPPORTED_LIST		0x00010101
+#define RNDIS_OID_GEN_HARDWARE_STATUS		0x00010102
+#define RNDIS_OID_GEN_MEDIA_SUPPORTED		0x00010103
+#define RNDIS_OID_GEN_MEDIA_IN_USE		0x00010104
+#define RNDIS_OID_GEN_MAXIMUM_LOOKAHEAD		0x00010105
+#define RNDIS_OID_GEN_MAXIMUM_FRAME_SIZE	0x00010106
+#define RNDIS_OID_GEN_LINK_SPEED		0x00010107
+#define RNDIS_OID_GEN_TRANSMIT_BUFFER_SPACE	0x00010108
+#define RNDIS_OID_GEN_RECEIVE_BUFFER_SPACE	0x00010109
+#define RNDIS_OID_GEN_TRANSMIT_BLOCK_SIZE	0x0001010A
+#define RNDIS_OID_GEN_RECEIVE_BLOCK_SIZE	0x0001010B
+#define RNDIS_OID_GEN_VENDOR_ID			0x0001010C
+#define RNDIS_OID_GEN_VENDOR_DESCRIPTION	0x0001010D
+#define RNDIS_OID_GEN_CURRENT_PACKET_FILTER	0x0001010E
+#define RNDIS_OID_GEN_CURRENT_LOOKAHEAD		0x0001010F
+#define RNDIS_OID_GEN_DRIVER_VERSION		0x00010110
+#define RNDIS_OID_GEN_MAXIMUM_TOTAL_SIZE	0x00010111
+#define RNDIS_OID_GEN_PROTOCOL_OPTIONS		0x00010112
+#define RNDIS_OID_GEN_MAC_OPTIONS		0x00010113
+#define RNDIS_OID_GEN_MEDIA_CONNECT_STATUS	0x00010114
+#define RNDIS_OID_GEN_MAXIMUM_SEND_PACKETS	0x00010115
+#define RNDIS_OID_GEN_VENDOR_DRIVER_VERSION	0x00010116
+#define RNDIS_OID_GEN_NETWORK_LAYER_ADDRESSES	0x00010118
+#define RNDIS_OID_GEN_TRANSPORT_HEADER_OFFSET	0x00010119
+#define RNDIS_OID_GEN_MACHINE_NAME		0x0001021A
+#define RNDIS_OID_GEN_RNDIS_CONFIG_PARAMETER	0x0001021B
+
+#define RNDIS_OID_GEN_XMIT_OK			0x00020101
+#define RNDIS_OID_GEN_RCV_OK			0x00020102
+#define RNDIS_OID_GEN_XMIT_ERROR		0x00020103
+#define RNDIS_OID_GEN_RCV_ERROR			0x00020104
+#define RNDIS_OID_GEN_RCV_NO_BUFFER		0x00020105
+
+#define RNDIS_OID_GEN_DIRECTED_BYTES_XMIT	0x00020201
+#define RNDIS_OID_GEN_DIRECTED_FRAMES_XMIT	0x00020202
+#define RNDIS_OID_GEN_MULTICAST_BYTES_XMIT	0x00020203
+#define RNDIS_OID_GEN_MULTICAST_FRAMES_XMIT	0x00020204
+#define RNDIS_OID_GEN_BROADCAST_BYTES_XMIT	0x00020205
+#define RNDIS_OID_GEN_BROADCAST_FRAMES_XMIT	0x00020206
+#define RNDIS_OID_GEN_DIRECTED_BYTES_RCV	0x00020207
+#define RNDIS_OID_GEN_DIRECTED_FRAMES_RCV	0x00020208
+#define RNDIS_OID_GEN_MULTICAST_BYTES_RCV	0x00020209
+#define RNDIS_OID_GEN_MULTICAST_FRAMES_RCV	0x0002020A
+#define RNDIS_OID_GEN_BROADCAST_BYTES_RCV	0x0002020B
+#define RNDIS_OID_GEN_BROADCAST_FRAMES_RCV	0x0002020C
+
+#define RNDIS_OID_GEN_RCV_CRC_ERROR		0x0002020D
+#define RNDIS_OID_GEN_TRANSMIT_QUEUE_LENGTH	0x0002020E
+
+#define RNDIS_OID_GEN_GET_TIME_CAPS		0x0002020F
+#define RNDIS_OID_GEN_GET_NETCARD_TIME		0x00020210
+
+/* These are connection-oriented general OIDs. */
+/* These replace the above OIDs for connection-oriented media. */
+#define RNDIS_OID_GEN_CO_SUPPORTED_LIST		0x00010101
+#define RNDIS_OID_GEN_CO_HARDWARE_STATUS	0x00010102
+#define RNDIS_OID_GEN_CO_MEDIA_SUPPORTED	0x00010103
+#define RNDIS_OID_GEN_CO_MEDIA_IN_USE		0x00010104
+#define RNDIS_OID_GEN_CO_LINK_SPEED		0x00010105
+#define RNDIS_OID_GEN_CO_VENDOR_ID		0x00010106
+#define RNDIS_OID_GEN_CO_VENDOR_DESCRIPTION	0x00010107
+#define RNDIS_OID_GEN_CO_DRIVER_VERSION		0x00010108
+#define RNDIS_OID_GEN_CO_PROTOCOL_OPTIONS	0x00010109
+#define RNDIS_OID_GEN_CO_MAC_OPTIONS		0x0001010A
+#define RNDIS_OID_GEN_CO_MEDIA_CONNECT_STATUS	0x0001010B
+#define RNDIS_OID_GEN_CO_VENDOR_DRIVER_VERSION	0x0001010C
+#define RNDIS_OID_GEN_CO_MINIMUM_LINK_SPEED	0x0001010D
+
+#define RNDIS_OID_GEN_CO_GET_TIME_CAPS		0x00010201
+#define RNDIS_OID_GEN_CO_GET_NETCARD_TIME	0x00010202
+
+/* These are connection-oriented statistics OIDs. */
+#define RNDIS_OID_GEN_CO_XMIT_PDUS_OK		0x00020101
+#define RNDIS_OID_GEN_CO_RCV_PDUS_OK		0x00020102
+#define RNDIS_OID_GEN_CO_XMIT_PDUS_ERROR	0x00020103
+#define RNDIS_OID_GEN_CO_RCV_PDUS_ERROR		0x00020104
+#define RNDIS_OID_GEN_CO_RCV_PDUS_NO_BUFFER	0x00020105
+
+
+#define RNDIS_OID_GEN_CO_RCV_CRC_ERROR		0x00020201
+#define RNDIS_OID_GEN_CO_TRANSMIT_QUEUE_LENGTH	0x00020202
+#define RNDIS_OID_GEN_CO_BYTES_XMIT		0x00020203
+#define RNDIS_OID_GEN_CO_BYTES_RCV		0x00020204
+#define RNDIS_OID_GEN_CO_BYTES_XMIT_OUTSTANDING	0x00020205
+#define RNDIS_OID_GEN_CO_NETCARD_LOAD		0x00020206
+
+/* These are objects for Connection-oriented media call-managers. */
+#define RNDIS_OID_CO_ADD_PVC			0xFF000001
+#define RNDIS_OID_CO_DELETE_PVC			0xFF000002
+#define RNDIS_OID_CO_GET_CALL_INFORMATION	0xFF000003
+#define RNDIS_OID_CO_ADD_ADDRESS		0xFF000004
+#define RNDIS_OID_CO_DELETE_ADDRESS		0xFF000005
+#define RNDIS_OID_CO_GET_ADDRESSES		0xFF000006
+#define RNDIS_OID_CO_ADDRESS_CHANGE		0xFF000007
+#define RNDIS_OID_CO_SIGNALING_ENABLED		0xFF000008
+#define RNDIS_OID_CO_SIGNALING_DISABLED		0xFF000009
+
+/* 802.3 Objects (Ethernet) */
+#define RNDIS_OID_802_3_PERMANENT_ADDRESS	0x01010101
+#define RNDIS_OID_802_3_CURRENT_ADDRESS		0x01010102
+#define RNDIS_OID_802_3_MULTICAST_LIST		0x01010103
+#define RNDIS_OID_802_3_MAXIMUM_LIST_SIZE	0x01010104
+#define RNDIS_OID_802_3_MAC_OPTIONS		0x01010105
+
+#define NDIS_802_3_MAC_OPTION_PRIORITY		0x00000001
+
+#define RNDIS_OID_802_3_RCV_ERROR_ALIGNMENT	0x01020101
+#define RNDIS_OID_802_3_XMIT_ONE_COLLISION	0x01020102
+#define RNDIS_OID_802_3_XMIT_MORE_COLLISIONS	0x01020103
+
+#define RNDIS_OID_802_3_XMIT_DEFERRED		0x01020201
+#define RNDIS_OID_802_3_XMIT_MAX_COLLISIONS	0x01020202
+#define RNDIS_OID_802_3_RCV_OVERRUN		0x01020203
+#define RNDIS_OID_802_3_XMIT_UNDERRUN		0x01020204
+#define RNDIS_OID_802_3_XMIT_HEARTBEAT_FAILURE	0x01020205
+#define RNDIS_OID_802_3_XMIT_TIMES_CRS_LOST	0x01020206
+#define RNDIS_OID_802_3_XMIT_LATE_COLLISIONS	0x01020207
+
+/* Remote NDIS message types */
+#define REMOTE_NDIS_PACKET_MSG			0x00000001
+#define REMOTE_NDIS_INITIALIZE_MSG		0x00000002
+#define REMOTE_NDIS_HALT_MSG			0x00000003
+#define REMOTE_NDIS_QUERY_MSG			0x00000004
+#define REMOTE_NDIS_SET_MSG			0x00000005
+#define REMOTE_NDIS_RESET_MSG			0x00000006
+#define REMOTE_NDIS_INDICATE_STATUS_MSG		0x00000007
+#define REMOTE_NDIS_KEEPALIVE_MSG		0x00000008
+
+#define REMOTE_CONDIS_MP_CREATE_VC_MSG		0x00008001
+#define REMOTE_CONDIS_MP_DELETE_VC_MSG		0x00008002
+#define REMOTE_CONDIS_MP_ACTIVATE_VC_MSG	0x00008005
+#define REMOTE_CONDIS_MP_DEACTIVATE_VC_MSG	0x00008006
+#define REMOTE_CONDIS_INDICATE_STATUS_MSG	0x00008007
+
+/* Remote NDIS message completion types */
+#define REMOTE_NDIS_INITIALIZE_CMPLT		0x80000002
+#define REMOTE_NDIS_QUERY_CMPLT			0x80000004
+#define REMOTE_NDIS_SET_CMPLT			0x80000005
+#define REMOTE_NDIS_RESET_CMPLT			0x80000006
+#define REMOTE_NDIS_KEEPALIVE_CMPLT		0x80000008
+
+#define REMOTE_CONDIS_MP_CREATE_VC_CMPLT	0x80008001
+#define REMOTE_CONDIS_MP_DELETE_VC_CMPLT	0x80008002
+#define REMOTE_CONDIS_MP_ACTIVATE_VC_CMPLT	0x80008005
+#define REMOTE_CONDIS_MP_DEACTIVATE_VC_CMPLT	0x80008006
+
+/*
+ * Reserved message type for private communication between lower-layer host
+ * driver and remote device, if necessary.
+ */
+#define REMOTE_NDIS_BUS_MSG			0xff000001
+
+/*  Defines for DeviceFlags in struct rndis_initialize_complete */
+#define RNDIS_DF_CONNECTIONLESS			0x00000001
+#define RNDIS_DF_CONNECTION_ORIENTED		0x00000002
+#define RNDIS_DF_RAW_DATA			0x00000004
+
+/*  Remote NDIS medium types. */
+#define RNDIS_MEDIUM_802_3			0x00000000
+#define RNDIS_MEDIUM_802_5			0x00000001
+#define RNDIS_MEDIUM_FDDI				0x00000002
+#define RNDIS_MEDIUM_WAN				0x00000003
+#define RNDIS_MEDIUM_LOCAL_TALK			0x00000004
+#define RNDIS_MEDIUM_ARCNET_RAW			0x00000006
+#define RNDIS_MEDIUM_ARCNET_878_2			0x00000007
+#define RNDIS_MEDIUM_ATM				0x00000008
+#define RNDIS_MEDIUM_WIRELESS_WAN			0x00000009
+#define RNDIS_MEDIUM_IRDA				0x0000000a
+#define RNDIS_MEDIUM_CO_WAN			0x0000000b
+/* Not a real medium, defined as an upper-bound */
+#define RNDIS_MEDIUM_MAX				0x0000000d
+
+
+/* Remote NDIS medium connection states. */
+#define RNDIS_MEDIA_STATE_CONNECTED		0x00000000
+#define RNDIS_MEDIA_STATE_DISCONNECTED		0x00000001
+
+/*  Remote NDIS version numbers */
+#define RNDIS_MAJOR_VERSION			0x00000001
+#define RNDIS_MINOR_VERSION			0x00000000
+
+
+/* NdisInitialize message */
+struct rndis_initialize_request {
+	u32 req_id;
+	u32 major_ver;
+	u32 minor_ver;
+	u32 max_xfer_size;
+};
+
+/* Response to NdisInitialize */
+struct rndis_initialize_complete {
+	u32 req_id;
+	u32 status;
+	u32 major_ver;
+	u32 minor_ver;
+	u32 dev_flags;
+	u32 medium;
+	u32 max_pkt_per_msg;
+	u32 max_xfer_size;
+	u32 pkt_alignment_factor;
+	u32 af_list_offset;
+	u32 af_list_size;
+};
+
+/* Call manager devices only: Information about an address family */
+/* supported by the device is appended to the response to NdisInitialize. */
+struct rndis_co_address_family {
+	u32 address_family;
+	u32 major_ver;
+	u32 minor_ver;
+};
+
+/* NdisHalt message */
+struct rndis_halt_request {
+	u32 req_id;
+};
+
+/* NdisQueryRequest message */
+struct rndis_query_request {
+	u32 req_id;
+	u32 oid;
+	u32 info_buflen;
+	u32 info_buf_offset;
+	u32 dev_vc_handle;
+};
+
+/* Response to NdisQueryRequest */
+struct rndis_query_complete {
+	u32 req_id;
+	u32 status;
+	u32 info_buflen;
+	u32 info_buf_offset;
+};
+
+/* NdisSetRequest message */
+struct rndis_set_request {
+	u32 req_id;
+	u32 oid;
+	u32 info_buflen;
+	u32 info_buf_offset;
+	u32 dev_vc_handle;
+};
+
+/* Response to NdisSetRequest */
+struct rndis_set_complete {
+	u32 req_id;
+	u32 status;
+};
+
+/* NdisReset message */
+struct rndis_reset_request {
+	u32 reserved;
+};
+
+/* Response to NdisReset */
+struct rndis_reset_complete {
+	u32 status;
+	u32 addressing_reset;
+};
+
+/* NdisMIndicateStatus message */
+struct rndis_indicate_status {
+	u32 status;
+	u32 status_buflen;
+	u32 status_buf_offset;
+};
+
+/* Diagnostic information passed as the status buffer in */
+/* struct rndis_indicate_status messages signifying error conditions. */
+struct rndis_diagnostic_info {
+	u32 diag_status;
+	u32 error_offset;
+};
+
+/* NdisKeepAlive message */
+struct rndis_keepalive_request {
+	u32 req_id;
+};
+
+/* Response to NdisKeepAlive */
+struct rndis_keepalive_complete {
+	u32 req_id;
+	u32 status;
+};
+
+/*
+ * Data message. All Offset fields contain byte offsets from the beginning of
+ * struct rndis_packet. All Length fields are in bytes.  VcHandle is set
+ * to 0 for connectionless data, otherwise it contains the VC handle.
+ */
+struct rndis_packet {
+	u32 data_offset;
+	u32 data_len;
+	u32 oob_data_offset;
+	u32 oob_data_len;
+	u32 num_oob_data_elements;
+	u32 per_pkt_info_offset;
+	u32 per_pkt_info_len;
+	u32 vc_handle;
+	u32 reserved;
+};
+
+/* Optional Out of Band data associated with a Data message. */
+struct rndis_oobd {
+	u32 size;
+	u32 type;
+	u32 class_info_offset;
+};
+
+/* Packet extension field contents associated with a Data message. */
+struct rndis_per_packet_info {
+	u32 size;
+	u32 type;
+	u32 per_pkt_info_offset;
+};
+
+/* Format of Information buffer passed in a SetRequest for the OID */
+/* OID_GEN_RNDIS_CONFIG_PARAMETER. */
+struct rndis_config_parameter_info {
+	u32 parameter_name_offset;
+	u32 parameter_name_length;
+	u32 parameter_type;
+	u32 parameter_value_offset;
+	u32 parameter_value_length;
+};
+
+/* Values for ParameterType in struct rndis_config_parameter_info */
+#define RNDIS_CONFIG_PARAM_TYPE_INTEGER     0
+#define RNDIS_CONFIG_PARAM_TYPE_STRING      2
+
+/* CONDIS Miniport messages for connection oriented devices */
+/* that do not implement a call manager. */
+
+/* CoNdisMiniportCreateVc message */
+struct rcondis_mp_create_vc {
+	u32 req_id;
+	u32 ndis_vc_handle;
+};
+
+/* Response to CoNdisMiniportCreateVc */
+struct rcondis_mp_create_vc_complete {
+	u32 req_id;
+	u32 dev_vc_handle;
+	u32 status;
+};
+
+/* CoNdisMiniportDeleteVc message */
+struct rcondis_mp_delete_vc {
+	u32 req_id;
+	u32 dev_vc_handle;
+};
+
+/* Response to CoNdisMiniportDeleteVc */
+struct rcondis_mp_delete_vc_complete {
+	u32 req_id;
+	u32 status;
+};
+
+/* CoNdisMiniportQueryRequest message */
+struct rcondis_mp_query_request {
+	u32 req_id;
+	u32 request_type;
+	u32 oid;
+	u32 dev_vc_handle;
+	u32 info_buflen;
+	u32 info_buf_offset;
+};
+
+/* CoNdisMiniportSetRequest message */
+struct rcondis_mp_set_request {
+	u32 req_id;
+	u32 request_type;
+	u32 oid;
+	u32 dev_vc_handle;
+	u32 info_buflen;
+	u32 info_buf_offset;
+};
+
+/* CoNdisIndicateStatus message */
+struct rcondis_indicate_status {
+	u32 ndis_vc_handle;
+	u32 status;
+	u32 status_buflen;
+	u32 status_buf_offset;
+};
+
+/* CONDIS Call/VC parameters */
+struct rcondis_specific_parameters {
+	u32 parameter_type;
+	u32 parameter_length;
+	u32 parameter_lffset;
+};
+
+struct rcondis_media_parameters {
+	u32 flags;
+	u32 reserved1;
+	u32 reserved2;
+	struct rcondis_specific_parameters media_specific;
+};
+
+struct rndis_flowspec {
+	u32 token_rate;
+	u32 token_bucket_size;
+	u32 peak_bandwidth;
+	u32 latency;
+	u32 delay_variation;
+	u32 service_type;
+	u32 max_sdu_size;
+	u32 minimum_policed_size;
+};
+
+struct rcondis_call_manager_parameters {
+	struct rndis_flowspec transmit;
+	struct rndis_flowspec receive;
+	struct rcondis_specific_parameters call_mgr_specific;
+};
+
+/* CoNdisMiniportActivateVc message */
+struct rcondis_mp_activate_vc_request {
+	u32 req_id;
+	u32 flags;
+	u32 dev_vc_handle;
+	u32 media_params_offset;
+	u32 media_params_length;
+	u32 call_mgr_params_offset;
+	u32 call_mgr_params_length;
+};
+
+/* Response to CoNdisMiniportActivateVc */
+struct rcondis_mp_activate_vc_complete {
+	u32 req_id;
+	u32 status;
+};
+
+/* CoNdisMiniportDeactivateVc message */
+struct rcondis_mp_deactivate_vc_request {
+	u32 req_id;
+	u32 flags;
+	u32 dev_vc_handle;
+};
+
+/* Response to CoNdisMiniportDeactivateVc */
+struct rcondis_mp_deactivate_vc_complete {
+	u32 req_id;
+	u32 status;
+};
+
+
+/* union with all of the RNDIS messages */
+union rndis_message_container {
+	struct rndis_packet pkt;
+	struct rndis_initialize_request init_req;
+	struct rndis_halt_request halt_req;
+	struct rndis_query_request query_req;
+	struct rndis_set_request set_req;
+	struct rndis_reset_request reset_req;
+	struct rndis_keepalive_request keep_alive_req;
+	struct rndis_indicate_status indicate_status;
+	struct rndis_initialize_complete init_complete;
+	struct rndis_query_complete query_complete;
+	struct rndis_set_complete set_complete;
+	struct rndis_reset_complete reset_complete;
+	struct rndis_keepalive_complete keep_alive_complete;
+	struct rcondis_mp_create_vc co_miniport_create_vc;
+	struct rcondis_mp_delete_vc co_miniport_delete_vc;
+	struct rcondis_indicate_status co_indicate_status;
+	struct rcondis_mp_activate_vc_request co_miniport_activate_vc;
+	struct rcondis_mp_deactivate_vc_request co_miniport_deactivate_vc;
+	struct rcondis_mp_create_vc_complete co_miniport_create_vc_complete;
+	struct rcondis_mp_delete_vc_complete co_miniport_delete_vc_complete;
+	struct rcondis_mp_activate_vc_complete co_miniport_activate_vc_complete;
+	struct rcondis_mp_deactivate_vc_complete
+		co_miniport_deactivate_vc_complete;
+};
+
+/* Remote NDIS message format */
+struct rndis_message {
+	u32 ndis_msg_type;
+
+	/* Total length of this message, from the beginning */
+	/* of the sruct rndis_message, in bytes. */
+	u32 msg_len;
+
+	/* Actual message */
+	union rndis_message_container msg;
+};
+
+
+struct rndis_filter_packet {
+	void *completion_ctx;
+	void (*completion)(void *context);
+	struct rndis_message msg;
+};
+
+/* Handy macros */
+
+/* get the size of an RNDIS message. Pass in the message type, */
+/* struct rndis_set_request, struct rndis_packet for example */
+#define RNDIS_MESSAGE_SIZE(msg)				\
+	(sizeof(msg) + (sizeof(struct rndis_message) -	\
+	 sizeof(union rndis_message_container)))
+
+/* get pointer to info buffer with message pointer */
+#define MESSAGE_TO_INFO_BUFFER(msg)				\
+	(((unsigned char *)(msg)) + msg->info_buf_offset)
+
+/* get pointer to status buffer with message pointer */
+#define MESSAGE_TO_STATUS_BUFFER(msg)			\
+	(((unsigned char *)(msg)) + msg->status_buf_offset)
+
+/* get pointer to OOBD buffer with message pointer */
+#define MESSAGE_TO_OOBD_BUFFER(msg)				\
+	(((unsigned char *)(msg)) + msg->oob_data_offset)
+
+/* get pointer to data buffer with message pointer */
+#define MESSAGE_TO_DATA_BUFFER(msg)				\
+	(((unsigned char *)(msg)) + msg->per_pkt_info_offset)
+
+/* get pointer to contained message from NDIS_MESSAGE pointer */
+#define RNDIS_MESSAGE_PTR_TO_MESSAGE_PTR(rndis_msg)		\
+	((void *) &rndis_msg->msg)
+
+/* get pointer to contained message from NDIS_MESSAGE pointer */
+#define RNDIS_MESSAGE_RAW_PTR_TO_MESSAGE_PTR(rndis_msg)	\
+	((void *) rndis_msg)
+
+
+#define __struct_bcount(x)
+
+
+
+#define RNDIS_HEADER_SIZE	(sizeof(struct rndis_message) - \
+				 sizeof(union rndis_message_container))
+
+#define NDIS_PACKET_TYPE_DIRECTED	0x00000001
+#define NDIS_PACKET_TYPE_MULTICAST	0x00000002
+#define NDIS_PACKET_TYPE_ALL_MULTICAST	0x00000004
+#define NDIS_PACKET_TYPE_BROADCAST	0x00000008
+#define NDIS_PACKET_TYPE_SOURCE_ROUTING	0x00000010
+#define NDIS_PACKET_TYPE_PROMISCUOUS	0x00000020
+#define NDIS_PACKET_TYPE_SMT		0x00000040
+#define NDIS_PACKET_TYPE_ALL_LOCAL	0x00000080
+#define NDIS_PACKET_TYPE_GROUP		0x00000100
+#define NDIS_PACKET_TYPE_ALL_FUNCTIONAL	0x00000200
+#define NDIS_PACKET_TYPE_FUNCTIONAL	0x00000400
+#define NDIS_PACKET_TYPE_MAC_FRAME	0x00000800
+
+
+
+#endif /* _HYPERV_NET_H */
diff --git a/drivers/staging/hv/hyperv_storage.h b/drivers/staging/hv/hyperv_storage.h
new file mode 100644
index 0000000..a01f9a0
--- /dev/null
+++ b/drivers/staging/hv/hyperv_storage.h
@@ -0,0 +1,334 @@
+/*
+ *
+ * Copyright (c) 2011, Microsoft Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * Authors:
+ *   Haiyang Zhang <haiyangz@microsoft.com>
+ *   Hank Janssen  <hjanssen@microsoft.com>
+ *   K. Y. Srinivasan <kys@microsoft.com>
+ *
+ */
+
+#ifndef _HYPERV_STORAGE_H
+#define _HYPERV_STORAGE_H
+
+
+/* vstorage.w revision number.  This is used in the case of a version match, */
+/* to alert the user that structure sizes may be mismatched even though the */
+/* protocol versions match. */
+
+
+#define REVISION_STRING(REVISION_) #REVISION_
+#define FILL_VMSTOR_REVISION(RESULT_LVALUE_)				\
+	do {								\
+		char *revision_string					\
+			= REVISION_STRING($Rev : 6 $) + 6;		\
+		RESULT_LVALUE_ = 0;					\
+		while (*revision_string >= '0'				\
+			&& *revision_string <= '9') {			\
+			RESULT_LVALUE_ *= 10;				\
+			RESULT_LVALUE_ += *revision_string - '0';	\
+			revision_string++;				\
+		}							\
+	} while (0)
+
+/* Major/minor macros.  Minor version is in LSB, meaning that earlier flat */
+/* version numbers will be interpreted as "0.x" (i.e., 1 becomes 0.1). */
+#define VMSTOR_PROTOCOL_MAJOR(VERSION_)		(((VERSION_) >> 8) & 0xff)
+#define VMSTOR_PROTOCOL_MINOR(VERSION_)		(((VERSION_))      & 0xff)
+#define VMSTOR_PROTOCOL_VERSION(MAJOR_, MINOR_)	((((MAJOR_) & 0xff) << 8) | \
+						 (((MINOR_) & 0xff)))
+#define VMSTOR_INVALID_PROTOCOL_VERSION		(-1)
+
+/* Version history: */
+/* V1 Beta                    0.1 */
+/* V1 RC < 2008/1/31          1.0 */
+/* V1 RC > 2008/1/31          2.0 */
+#define VMSTOR_PROTOCOL_VERSION_CURRENT VMSTOR_PROTOCOL_VERSION(2, 0)
+
+
+
+
+/*  This will get replaced with the max transfer length that is possible on */
+/*  the host adapter. */
+/*  The max transfer length will be published when we offer a vmbus channel. */
+#define MAX_TRANSFER_LENGTH	0x40000
+#define DEFAULT_PACKET_SIZE (sizeof(struct vmdata_gpa_direct) +	\
+			sizeof(struct vstor_packet) +		\
+			sizesizeof(u64) * (MAX_TRANSFER_LENGTH / PAGE_SIZE)))
+
+
+/*  Packet structure describing virtual storage requests. */
+enum vstor_packet_operation {
+	VSTOR_OPERATION_COMPLETE_IO		= 1,
+	VSTOR_OPERATION_REMOVE_DEVICE		= 2,
+	VSTOR_OPERATION_EXECUTE_SRB		= 3,
+	VSTOR_OPERATION_RESET_LUN		= 4,
+	VSTOR_OPERATION_RESET_ADAPTER		= 5,
+	VSTOR_OPERATION_RESET_BUS		= 6,
+	VSTOR_OPERATION_BEGIN_INITIALIZATION	= 7,
+	VSTOR_OPERATION_END_INITIALIZATION	= 8,
+	VSTOR_OPERATION_QUERY_PROTOCOL_VERSION	= 9,
+	VSTOR_OPERATION_QUERY_PROPERTIES	= 10,
+	VSTOR_OPERATION_MAXIMUM			= 10
+};
+
+/*
+ * Platform neutral description of a scsi request -
+ * this remains the same across the write regardless of 32/64 bit
+ * note: it's patterned off the SCSI_PASS_THROUGH structure
+ */
+#define CDB16GENERIC_LENGTH			0x10
+
+#ifndef SENSE_BUFFER_SIZE
+#define SENSE_BUFFER_SIZE			0x12
+#endif
+
+#define MAX_DATA_BUF_LEN_WITH_PADDING		0x14
+
+struct vmscsi_request {
+	unsigned short length;
+	unsigned char srb_status;
+	unsigned char scsi_status;
+
+	unsigned char port_number;
+	unsigned char path_id;
+	unsigned char target_id;
+	unsigned char lun;
+
+	unsigned char cdb_length;
+	unsigned char sense_info_length;
+	unsigned char data_in;
+	unsigned char reserved;
+
+	unsigned int data_transfer_length;
+
+	union {
+		unsigned char cdb[CDB16GENERIC_LENGTH];
+		unsigned char sense_data[SENSE_BUFFER_SIZE];
+		unsigned char reserved_array[MAX_DATA_BUF_LEN_WITH_PADDING];
+	};
+} __attribute((packed));
+
+
+/*
+ * This structure is sent during the intialization phase to get the different
+ * properties of the channel.
+ */
+struct vmstorage_channel_properties {
+	unsigned short protocol_version;
+	unsigned char path_id;
+	unsigned char target_id;
+
+	/* Note: port number is only really known on the client side */
+	unsigned int port_number;
+	unsigned int flags;
+	unsigned int max_transfer_bytes;
+
+	/*  This id is unique for each channel and will correspond with */
+	/*  vendor specific data in the inquirydata */
+	unsigned long long unique_id;
+} __packed;
+
+/*  This structure is sent during the storage protocol negotiations. */
+struct vmstorage_protocol_version {
+	/* Major (MSW) and minor (LSW) version numbers. */
+	unsigned short major_minor;
+
+	/*
+	 * Revision number is auto-incremented whenever this file is changed
+	 * (See FILL_VMSTOR_REVISION macro above).  Mismatch does not
+	 * definitely indicate incompatibility--but it does indicate mismatched
+	 * builds.
+	 */
+	unsigned short revision;
+} __packed;
+
+/* Channel Property Flags */
+#define STORAGE_CHANNEL_REMOVABLE_FLAG		0x1
+#define STORAGE_CHANNEL_EMULATED_IDE_FLAG	0x2
+
+struct vstor_packet {
+	/* Requested operation type */
+	enum vstor_packet_operation operation;
+
+	/*  Flags - see below for values */
+	unsigned int flags;
+
+	/* Status of the request returned from the server side. */
+	unsigned int status;
+
+	/* Data payload area */
+	union {
+		/*
+		 * Structure used to forward SCSI commands from the
+		 * client to the server.
+		 */
+		struct vmscsi_request vm_srb;
+
+		/* Structure used to query channel properties. */
+		struct vmstorage_channel_properties storage_channel_properties;
+
+		/* Used during version negotiations. */
+		struct vmstorage_protocol_version version;
+	};
+} __packed;
+
+/* Packet flags */
+/*
+ * This flag indicates that the server should send back a completion for this
+ * packet.
+ */
+#define REQUEST_COMPLETION_FLAG	0x1
+
+/*  This is the set of flags that the vsc can set in any packets it sends */
+#define VSC_LEGAL_FLAGS		(REQUEST_COMPLETION_FLAG)
+
+
+#include <linux/kernel.h>
+#include <linux/wait.h>
+#include "hyperv_storage.h"
+#include "hyperv.h"
+
+/* Defines */
+#define STORVSC_RING_BUFFER_SIZE			(20*PAGE_SIZE)
+#define BLKVSC_RING_BUFFER_SIZE				(20*PAGE_SIZE)
+
+#define STORVSC_MAX_IO_REQUESTS				128
+
+/*
+ * In Hyper-V, each port/path/target maps to 1 scsi host adapter.  In
+ * reality, the path/target is not used (ie always set to 0) so our
+ * scsi host adapter essentially has 1 bus with 1 target that contains
+ * up to 256 luns.
+ */
+#define STORVSC_MAX_LUNS_PER_TARGET			64
+#define STORVSC_MAX_TARGETS				1
+#define STORVSC_MAX_CHANNELS				1
+
+struct hv_storvsc_request;
+
+/* Matches Windows-end */
+enum storvsc_request_type {
+	WRITE_TYPE,
+	READ_TYPE,
+	UNKNOWN_TYPE,
+};
+
+
+struct hv_storvsc_request {
+	struct hv_storvsc_request *request;
+	struct hv_device *device;
+
+	/* Synchronize the request/response if needed */
+	struct completion wait_event;
+
+	unsigned char *sense_buffer;
+	void *context;
+	void (*on_io_completion)(struct hv_storvsc_request *request);
+	struct hv_multipage_buffer data_buffer;
+
+	struct vstor_packet vstor_packet;
+};
+
+
+struct storvsc_device_info {
+	u32 ring_buffer_size;
+	unsigned int port_number;
+	unsigned char path_id;
+	unsigned char target_id;
+};
+
+struct storvsc_major_info {
+	int major;
+	int index;
+	bool do_register;
+	char *devname;
+	char *diskname;
+};
+
+/* A storvsc device is a device object that contains a vmbus channel */
+struct storvsc_device {
+	struct hv_device *device;
+
+	/* 0 indicates the device is being destroyed */
+	atomic_t ref_count;
+
+	bool	 drain_notify;
+	atomic_t num_outstanding_req;
+
+	wait_queue_head_t waiting_to_drain;
+
+	/*
+	 * Each unique Port/Path/Target represents 1 channel ie scsi
+	 * controller. In reality, the pathid, targetid is always 0
+	 * and the port is set by us
+	 */
+	unsigned int port_number;
+	unsigned char path_id;
+	unsigned char target_id;
+
+	/* Used for vsc/vsp channel reset process */
+	struct hv_storvsc_request init_request;
+	struct hv_storvsc_request reset_request;
+};
+
+
+/* Get the stordevice object iff exists and its refcount > 1 */
+static inline struct storvsc_device *get_stor_device(struct hv_device *device)
+{
+	struct storvsc_device *stor_device;
+
+	stor_device = (struct storvsc_device *)device->ext;
+	if (stor_device && atomic_read(&stor_device->ref_count) > 1)
+		atomic_inc(&stor_device->ref_count);
+	else
+		stor_device = NULL;
+
+	return stor_device;
+}
+
+
+static inline void put_stor_device(struct hv_device *device)
+{
+	struct storvsc_device *stor_device;
+
+	stor_device = (struct storvsc_device *)device->ext;
+
+	atomic_dec(&stor_device->ref_count);
+}
+
+static inline void storvsc_wait_to_drain(struct storvsc_device *dev)
+{
+	dev->drain_notify = true;
+	wait_event(dev->waiting_to_drain,
+		   atomic_read(&dev->num_outstanding_req) == 0);
+	dev->drain_notify = false;
+}
+
+/* Interface */
+
+int storvsc_dev_add(struct hv_device *device,
+				void *additional_info);
+int storvsc_dev_remove(struct hv_device *device);
+
+int storvsc_do_io(struct hv_device *device,
+				struct hv_storvsc_request *request);
+
+int storvsc_get_major_info(struct storvsc_device_info *device_info,
+				struct storvsc_major_info *major_info);
+
+#endif /* _HYPERV_STORAGE_H */
diff --git a/drivers/staging/hv/hyperv_vmbus.h b/drivers/staging/hv/hyperv_vmbus.h
new file mode 100644
index 0000000..349ad80
--- /dev/null
+++ b/drivers/staging/hv/hyperv_vmbus.h
@@ -0,0 +1,629 @@
+/*
+ *
+ * Copyright (c) 2011, Microsoft Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * Authors:
+ *   Haiyang Zhang <haiyangz@microsoft.com>
+ *   Hank Janssen  <hjanssen@microsoft.com>
+ *   K. Y. Srinivasan <kys@microsoft.com>
+ *
+ */
+
+#ifndef _HYPERV_VMBUS_H
+#define _HYPERV_VMBUS_H
+
+#include <linux/list.h>
+#include <asm/sync_bitops.h>
+#include <linux/atomic.h>
+
+#include "hyperv.h"
+
+/*
+ * The below CPUID leaves are present if VersionAndFeatures.HypervisorPresent
+ * is set by CPUID(HVCPUID_VERSION_FEATURES).
+ */
+enum hv_cpuid_function {
+	HVCPUID_VERSION_FEATURES		= 0x00000001,
+	HVCPUID_VENDOR_MAXFUNCTION		= 0x40000000,
+	HVCPUID_INTERFACE			= 0x40000001,
+
+	/*
+	 * The remaining functions depend on the value of
+	 * HVCPUID_INTERFACE
+	 */
+	HVCPUID_VERSION			= 0x40000002,
+	HVCPUID_FEATURES			= 0x40000003,
+	HVCPUID_ENLIGHTENMENT_INFO	= 0x40000004,
+	HVCPUID_IMPLEMENTATION_LIMITS		= 0x40000005,
+};
+
+/* Define version of the synthetic interrupt controller. */
+#define HV_SYNIC_VERSION		(1)
+
+/* Define the expected SynIC version. */
+#define HV_SYNIC_VERSION_1		(0x1)
+
+/* Define synthetic interrupt controller message constants. */
+#define HV_MESSAGE_SIZE			(256)
+#define HV_MESSAGE_PAYLOAD_BYTE_COUNT	(240)
+#define HV_MESSAGE_PAYLOAD_QWORD_COUNT	(30)
+#define HV_ANY_VP			(0xFFFFFFFF)
+
+/* Define synthetic interrupt controller flag constants. */
+#define HV_EVENT_FLAGS_COUNT		(256 * 8)
+#define HV_EVENT_FLAGS_BYTE_COUNT	(256)
+#define HV_EVENT_FLAGS_DWORD_COUNT	(256 / sizeof(u32))
+
+/* Define hypervisor message types. */
+enum hv_message_type {
+	HVMSG_NONE			= 0x00000000,
+
+	/* Memory access messages. */
+	HVMSG_UNMAPPED_GPA		= 0x80000000,
+	HVMSG_GPA_INTERCEPT		= 0x80000001,
+
+	/* Timer notification messages. */
+	HVMSG_TIMER_EXPIRED			= 0x80000010,
+
+	/* Error messages. */
+	HVMSG_INVALID_VP_REGISTER_VALUE	= 0x80000020,
+	HVMSG_UNRECOVERABLE_EXCEPTION	= 0x80000021,
+	HVMSG_UNSUPPORTED_FEATURE		= 0x80000022,
+
+	/* Trace buffer complete messages. */
+	HVMSG_EVENTLOG_BUFFERCOMPLETE	= 0x80000040,
+
+	/* Platform-specific processor intercept messages. */
+	HVMSG_X64_IOPORT_INTERCEPT		= 0x80010000,
+	HVMSG_X64_MSR_INTERCEPT		= 0x80010001,
+	HVMSG_X64_CPUID_INTERCEPT		= 0x80010002,
+	HVMSG_X64_EXCEPTION_INTERCEPT	= 0x80010003,
+	HVMSG_X64_APIC_EOI			= 0x80010004,
+	HVMSG_X64_LEGACY_FP_ERROR		= 0x80010005
+};
+
+/* Define the number of synthetic interrupt sources. */
+#define HV_SYNIC_SINT_COUNT		(16)
+#define HV_SYNIC_STIMER_COUNT		(4)
+
+/* Define invalid partition identifier. */
+#define HV_PARTITION_ID_INVALID		((u64)0x0)
+
+/* Define connection identifier type. */
+union hv_connection_id {
+	u32 asu32;
+	struct {
+		u32 id:24;
+		u32 reserved:8;
+	} u;
+};
+
+/* Define port identifier type. */
+union hv_port_id {
+	u32 asu32;
+	struct {
+		u32 id:24;
+		u32 reserved:8;
+	} u ;
+};
+
+/* Define port type. */
+enum hv_port_type {
+	HVPORT_MSG	= 1,
+	HVPORT_EVENT		= 2,
+	HVPORT_MONITOR	= 3
+};
+
+/* Define port information structure. */
+struct hv_port_info {
+	enum hv_port_type port_type;
+	u32 padding;
+	union {
+		struct {
+			u32 target_sint;
+			u32 target_vp;
+			u64 rsvdz;
+		} message_port_info;
+		struct {
+			u32 target_sint;
+			u32 target_vp;
+			u16 base_flag_bumber;
+			u16 flag_count;
+			u32 rsvdz;
+		} event_port_info;
+		struct {
+			u64 monitor_address;
+			u64 rsvdz;
+		} monitor_port_info;
+	};
+};
+
+struct hv_connection_info {
+	enum hv_port_type port_type;
+	u32 padding;
+	union {
+		struct {
+			u64 rsvdz;
+		} message_connection_info;
+		struct {
+			u64 rsvdz;
+		} event_connection_info;
+		struct {
+			u64 monitor_address;
+		} monitor_connection_info;
+	};
+};
+
+/* Define synthetic interrupt controller message flags. */
+union hv_message_flags {
+	u8 asu8;
+	struct {
+		u8 msg_pending:1;
+		u8 reserved:7;
+	};
+};
+
+/* Define synthetic interrupt controller message header. */
+struct hv_message_header {
+	enum hv_message_type message_type;
+	u8 payload_size;
+	union hv_message_flags message_flags;
+	u8 reserved[2];
+	union {
+		u64 sender;
+		union hv_port_id port;
+	};
+};
+
+/* Define timer message payload structure. */
+struct hv_timer_message_payload {
+	u32 timer_index;
+	u32 reserved;
+	u64 expiration_time;	/* When the timer expired */
+	u64 delivery_time;	/* When the message was delivered */
+};
+
+/* Define synthetic interrupt controller message format. */
+struct hv_message {
+	struct hv_message_header header;
+	union {
+		u64 payload[HV_MESSAGE_PAYLOAD_QWORD_COUNT];
+	} u ;
+};
+
+/* Define the number of message buffers associated with each port. */
+#define HV_PORT_MESSAGE_BUFFER_COUNT	(16)
+
+/* Define the synthetic interrupt message page layout. */
+struct hv_message_page {
+	struct hv_message sint_message[HV_SYNIC_SINT_COUNT];
+};
+
+/* Define the synthetic interrupt controller event flags format. */
+union hv_synic_event_flags {
+	u8 flags8[HV_EVENT_FLAGS_BYTE_COUNT];
+	u32 flags32[HV_EVENT_FLAGS_DWORD_COUNT];
+};
+
+/* Define the synthetic interrupt flags page layout. */
+struct hv_synic_event_flags_page {
+	union hv_synic_event_flags sintevent_flags[HV_SYNIC_SINT_COUNT];
+};
+
+/* Define SynIC control register. */
+union hv_synic_scontrol {
+	u64 as_uint64;
+	struct {
+		u64 enable:1;
+		u64 reserved:63;
+	};
+};
+
+/* Define synthetic interrupt source. */
+union hv_synic_sint {
+	u64 as_uint64;
+	struct {
+		u64 vector:8;
+		u64 reserved1:8;
+		u64 masked:1;
+		u64 auto_eoi:1;
+		u64 reserved2:46;
+	};
+};
+
+/* Define the format of the SIMP register */
+union hv_synic_simp {
+	u64 as_uint64;
+	struct {
+		u64 simp_enabled:1;
+		u64 preserved:11;
+		u64 base_simp_gpa:52;
+	};
+};
+
+/* Define the format of the SIEFP register */
+union hv_synic_siefp {
+	u64 as_uint64;
+	struct {
+		u64 siefp_enabled:1;
+		u64 preserved:11;
+		u64 base_siefp_gpa:52;
+	};
+};
+
+/* Definitions for the monitored notification facility */
+union hv_monitor_trigger_group {
+	u64 as_uint64;
+	struct {
+		u32 pending;
+		u32 armed;
+	};
+};
+
+struct hv_monitor_parameter {
+	union hv_connection_id connectionid;
+	u16 flagnumber;
+	u16 rsvdz;
+};
+
+union hv_monitor_trigger_state {
+	u32 asu32;
+
+	struct {
+		u32 group_enable:4;
+		u32 rsvdz:28;
+	};
+};
+
+/* struct hv_monitor_page Layout */
+/* ------------------------------------------------------ */
+/* | 0   | TriggerState (4 bytes) | Rsvd1 (4 bytes)     | */
+/* | 8   | TriggerGroup[0]                              | */
+/* | 10  | TriggerGroup[1]                              | */
+/* | 18  | TriggerGroup[2]                              | */
+/* | 20  | TriggerGroup[3]                              | */
+/* | 28  | Rsvd2[0]                                     | */
+/* | 30  | Rsvd2[1]                                     | */
+/* | 38  | Rsvd2[2]                                     | */
+/* | 40  | NextCheckTime[0][0]    | NextCheckTime[0][1] | */
+/* | ...                                                | */
+/* | 240 | Latency[0][0..3]                             | */
+/* | 340 | Rsvz3[0]                                     | */
+/* | 440 | Parameter[0][0]                              | */
+/* | 448 | Parameter[0][1]                              | */
+/* | ...                                                | */
+/* | 840 | Rsvd4[0]                                     | */
+/* ------------------------------------------------------ */
+struct hv_monitor_page {
+	union hv_monitor_trigger_state trigger_state;
+	u32 rsvdz1;
+
+	union hv_monitor_trigger_group trigger_group[4];
+	u64 rsvdz2[3];
+
+	s32 next_checktime[4][32];
+
+	u16 latency[4][32];
+	u64 rsvdz3[32];
+
+	struct hv_monitor_parameter parameter[4][32];
+
+	u8 rsvdz4[1984];
+};
+
+/* Declare the various hypercall operations. */
+enum hv_call_code {
+	HVCALL_POST_MESSAGE	= 0x005c,
+	HVCALL_SIGNAL_EVENT	= 0x005d,
+};
+
+/* Definition of the hv_post_message hypercall input structure. */
+struct hv_input_post_message {
+	union hv_connection_id connectionid;
+	u32 reserved;
+	enum hv_message_type message_type;
+	u32 payload_size;
+	u64 payload[HV_MESSAGE_PAYLOAD_QWORD_COUNT];
+};
+
+/* Definition of the hv_signal_event hypercall input structure. */
+struct hv_input_signal_event {
+	union hv_connection_id connectionid;
+	u16 flag_number;
+	u16 rsvdz;
+};
+
+/*
+ * Versioning definitions used for guests reporting themselves to the
+ * hypervisor, and visa versa.
+ */
+
+/* Version info reported by guest OS's */
+enum hv_guest_os_vendor {
+	HVGUESTOS_VENDOR_MICROSOFT	= 0x0001
+};
+
+enum hv_guest_os_microsoft_ids {
+	HVGUESTOS_MICROSOFT_UNDEFINED	= 0x00,
+	HVGUESTOS_MICROSOFT_MSDOS		= 0x01,
+	HVGUESTOS_MICROSOFT_WINDOWS3X	= 0x02,
+	HVGUESTOS_MICROSOFT_WINDOWS9X	= 0x03,
+	HVGUESTOS_MICROSOFT_WINDOWSNT	= 0x04,
+	HVGUESTOS_MICROSOFT_WINDOWSCE	= 0x05
+};
+
+/*
+ * Declare the MSR used to identify the guest OS.
+ */
+#define HV_X64_MSR_GUEST_OS_ID	0x40000000
+
+union hv_x64_msr_guest_os_id_contents {
+	u64 as_uint64;
+	struct {
+		u64 build_number:16;
+		u64 service_version:8; /* Service Pack, etc. */
+		u64 minor_version:8;
+		u64 major_version:8;
+		u64 os_id:8; /* enum hv_guest_os_microsoft_ids (if Vendor=MS) */
+		u64 vendor_id:16; /* enum hv_guest_os_vendor */
+	};
+};
+
+/*
+ * Declare the MSR used to setup pages used to communicate with the hypervisor.
+ */
+#define HV_X64_MSR_HYPERCALL	0x40000001
+
+union hv_x64_msr_hypercall_contents {
+	u64 as_uint64;
+	struct {
+		u64 enable:1;
+		u64 reserved:11;
+		u64 guest_physical_address:52;
+	};
+};
+
+
+enum {
+	VMBUS_MESSAGE_CONNECTION_ID	= 1,
+	VMBUS_MESSAGE_PORT_ID		= 1,
+	VMBUS_EVENT_CONNECTION_ID	= 2,
+	VMBUS_EVENT_PORT_ID		= 2,
+	VMBUS_MONITOR_CONNECTION_ID	= 3,
+	VMBUS_MONITOR_PORT_ID		= 3,
+	VMBUS_MESSAGE_SINT		= 2,
+};
+
+/* #defines */
+
+#define HV_PRESENT_BIT			0x80000000
+
+#define HV_LINUX_GUEST_ID_LO		0x00000000
+#define HV_LINUX_GUEST_ID_HI		0xB16B00B5
+#define HV_LINUX_GUEST_ID		(((u64)HV_LINUX_GUEST_ID_HI << 32) | \
+					   HV_LINUX_GUEST_ID_LO)
+
+#define HV_CPU_POWER_MANAGEMENT		(1 << 0)
+#define HV_RECOMMENDATIONS_MAX		4
+
+#define HV_X64_MAX			5
+#define HV_CAPS_MAX			8
+
+
+#define HV_HYPERCALL_PARAM_ALIGN	sizeof(u64)
+
+
+/* Service definitions */
+
+#define HV_SERVICE_PARENT_PORT				(0)
+#define HV_SERVICE_PARENT_CONNECTION			(0)
+
+#define HV_SERVICE_CONNECT_RESPONSE_SUCCESS		(0)
+#define HV_SERVICE_CONNECT_RESPONSE_INVALID_PARAMETER	(1)
+#define HV_SERVICE_CONNECT_RESPONSE_UNKNOWN_SERVICE	(2)
+#define HV_SERVICE_CONNECT_RESPONSE_CONNECTION_REJECTED	(3)
+
+#define HV_SERVICE_CONNECT_REQUEST_MESSAGE_ID		(1)
+#define HV_SERVICE_CONNECT_RESPONSE_MESSAGE_ID		(2)
+#define HV_SERVICE_DISCONNECT_REQUEST_MESSAGE_ID	(3)
+#define HV_SERVICE_DISCONNECT_RESPONSE_MESSAGE_ID	(4)
+#define HV_SERVICE_MAX_MESSAGE_ID				(4)
+
+#define HV_SERVICE_PROTOCOL_VERSION (0x0010)
+#define HV_CONNECT_PAYLOAD_BYTE_COUNT 64
+
+/* #define VMBUS_REVISION_NUMBER	6 */
+
+/* Our local vmbus's port and connection id. Anything >0 is fine */
+/* #define VMBUS_PORT_ID		11 */
+
+/* 628180B8-308D-4c5e-B7DB-1BEB62E62EF4 */
+static const struct hv_guid VMBUS_SERVICE_ID = {
+	.data = {
+		0xb8, 0x80, 0x81, 0x62, 0x8d, 0x30, 0x5e, 0x4c,
+		0xb7, 0xdb, 0x1b, 0xeb, 0x62, 0xe6, 0x2e, 0xf4
+	},
+};
+
+#define MAX_NUM_CPUS	32
+
+
+struct hv_input_signal_event_buffer {
+	u64 align8;
+	struct hv_input_signal_event event;
+};
+
+struct hv_context {
+	/* We only support running on top of Hyper-V
+	* So at this point this really can only contain the Hyper-V ID
+	*/
+	u64 guestid;
+
+	void *hypercall_page;
+
+	bool synic_initialized;
+
+	/*
+	 * This is used as an input param to HvCallSignalEvent hypercall. The
+	 * input param is immutable in our usage and must be dynamic mem (vs
+	 * stack or global). */
+	struct hv_input_signal_event_buffer *signal_event_buffer;
+	/* 8-bytes aligned of the buffer above */
+	struct hv_input_signal_event *signal_event_param;
+
+	void *synic_message_page[MAX_NUM_CPUS];
+	void *synic_event_page[MAX_NUM_CPUS];
+};
+
+extern struct hv_context hv_context;
+
+
+/* Hv Interface */
+
+extern int hv_init(void);
+
+extern void hv_cleanup(void);
+
+extern u16 hv_post_message(union hv_connection_id connection_id,
+			 enum hv_message_type message_type,
+			 void *payload, size_t payload_size);
+
+extern u16 hv_signal_event(void);
+
+extern void hv_synic_init(void *irqarg);
+
+extern void hv_synic_cleanup(void *arg);
+
+
+/* Interface */
+
+
+int hv_ringbuffer_init(struct hv_ring_buffer_info *ring_info, void *buffer,
+		   u32 buflen);
+
+void hv_ringbuffer_cleanup(struct hv_ring_buffer_info *ring_info);
+
+int hv_ringbuffer_write(struct hv_ring_buffer_info *ring_info,
+		    struct scatterlist *sglist,
+		    u32 sgcount);
+
+int hv_ringbuffer_peek(struct hv_ring_buffer_info *ring_info, void *buffer,
+		   u32 buflen);
+
+int hv_ringbuffer_read(struct hv_ring_buffer_info *ring_info,
+		   void *buffer,
+		   u32 buflen,
+		   u32 offset);
+
+u32 hv_get_ringbuffer_interrupt_mask(struct hv_ring_buffer_info *ring_info);
+
+void hv_dump_ring_info(struct hv_ring_buffer_info *ring_info, char *prefix);
+
+void hv_ringbuffer_get_debuginfo(struct hv_ring_buffer_info *ring_info,
+			    struct hv_ring_buffer_debug_info *debug_info);
+
+/*
+ * Maximum channels is determined by the size of the interrupt page
+ * which is PAGE_SIZE. 1/2 of PAGE_SIZE is for send endpoint interrupt
+ * and the other is receive endpoint interrupt
+ */
+#define MAX_NUM_CHANNELS	((PAGE_SIZE >> 1) << 3)	/* 16348 channels */
+
+/* The value here must be in multiple of 32 */
+/* TODO: Need to make this configurable */
+#define MAX_NUM_CHANNELS_SUPPORTED	256
+
+
+enum vmbus_connect_state {
+	DISCONNECTED,
+	CONNECTING,
+	CONNECTED,
+	DISCONNECTING
+};
+
+#define MAX_SIZE_CHANNEL_MESSAGE	HV_MESSAGE_PAYLOAD_BYTE_COUNT
+
+struct vmbus_connection {
+	enum vmbus_connect_state conn_state;
+
+	atomic_t next_gpadl_handle;
+
+	/*
+	 * Represents channel interrupts. Each bit position represents a
+	 * channel.  When a channel sends an interrupt via VMBUS, it finds its
+	 * bit in the sendInterruptPage, set it and calls Hv to generate a port
+	 * event. The other end receives the port event and parse the
+	 * recvInterruptPage to see which bit is set
+	 */
+	void *int_page;
+	void *send_int_page;
+	void *recv_int_page;
+
+	/*
+	 * 2 pages - 1st page for parent->child notification and 2nd
+	 * is child->parent notification
+	 */
+	void *monitor_pages;
+	struct list_head chn_msg_list;
+	spinlock_t channelmsg_lock;
+
+	/* List of channels */
+	struct list_head chn_list;
+	spinlock_t channel_lock;
+
+	struct workqueue_struct *work_queue;
+};
+
+
+struct vmbus_msginfo {
+	/* Bookkeeping stuff */
+	struct list_head msglist_entry;
+
+	/* The message itself */
+	unsigned char msg[0];
+};
+
+
+extern struct vmbus_connection vmbus_connection;
+
+/* General vmbus interface */
+
+struct hv_device *vmbus_child_device_create(struct hv_guid *type,
+					 struct hv_guid *instance,
+					 struct vmbus_channel *channel);
+
+int vmbus_child_device_register(struct hv_device *child_device_obj);
+void vmbus_child_device_unregister(struct hv_device *device_obj);
+
+/* static void */
+/* VmbusChildDeviceDestroy( */
+/* struct hv_device *); */
+
+struct vmbus_channel *relid2channel(u32 relid);
+
+
+/* Connection interface */
+
+int vmbus_connect(void);
+
+int vmbus_post_msg(void *buffer, size_t buflen);
+
+int vmbus_set_event(u32 child_relid);
+
+void vmbus_on_event(unsigned long data);
+
+
+#endif /* _HYPERV_VMBUS_H */
diff --git a/drivers/staging/hv/include/asm/hyperv.h b/drivers/staging/hv/include/asm/hyperv.h
new file mode 100644
index 0000000..5df477a
--- /dev/null
+++ b/drivers/staging/hv/include/asm/hyperv.h
@@ -0,0 +1,193 @@
+#ifndef _ASM_X86_HYPERV_H
+#define _ASM_X86_HYPERV_H
+
+#include <linux/types.h>
+
+/*
+ * The below CPUID leaves are present if VersionAndFeatures.HypervisorPresent
+ * is set by CPUID(HvCpuIdFunctionVersionAndFeatures).
+ */
+#define HYPERV_CPUID_VENDOR_AND_MAX_FUNCTIONS	0x40000000
+#define HYPERV_CPUID_INTERFACE			0x40000001
+#define HYPERV_CPUID_VERSION			0x40000002
+#define HYPERV_CPUID_FEATURES			0x40000003
+#define HYPERV_CPUID_ENLIGHTMENT_INFO		0x40000004
+#define HYPERV_CPUID_IMPLEMENT_LIMITS		0x40000005
+
+#define HYPERV_HYPERVISOR_PRESENT_BIT		0x80000000
+#define HYPERV_CPUID_MIN			0x40000005
+#define HYPERV_CPUID_MAX			0x4000ffff
+
+/*
+ * Feature identification. EAX indicates which features are available
+ * to the partition based upon the current partition privileges.
+ */
+
+/* VP Runtime (HV_X64_MSR_VP_RUNTIME) available */
+#define HV_X64_MSR_VP_RUNTIME_AVAILABLE		(1 << 0)
+/* Partition Reference Counter (HV_X64_MSR_TIME_REF_COUNT) available*/
+#define HV_X64_MSR_TIME_REF_COUNT_AVAILABLE	(1 << 1)
+/*
+ * Basic SynIC MSRs (HV_X64_MSR_SCONTROL through HV_X64_MSR_EOM
+ * and HV_X64_MSR_SINT0 through HV_X64_MSR_SINT15) available
+ */
+#define HV_X64_MSR_SYNIC_AVAILABLE		(1 << 2)
+/*
+ * Synthetic Timer MSRs (HV_X64_MSR_STIMER0_CONFIG through
+ * HV_X64_MSR_STIMER3_COUNT) available
+ */
+#define HV_X64_MSR_SYNTIMER_AVAILABLE		(1 << 3)
+/*
+ * APIC access MSRs (HV_X64_MSR_EOI, HV_X64_MSR_ICR and HV_X64_MSR_TPR)
+ * are available
+ */
+#define HV_X64_MSR_APIC_ACCESS_AVAILABLE	(1 << 4)
+/* Hypercall MSRs (HV_X64_MSR_GUEST_OS_ID and HV_X64_MSR_HYPERCALL) available*/
+#define HV_X64_MSR_HYPERCALL_AVAILABLE		(1 << 5)
+/* Access virtual processor index MSR (HV_X64_MSR_VP_INDEX) available*/
+#define HV_X64_MSR_VP_INDEX_AVAILABLE		(1 << 6)
+/* Virtual system reset MSR (HV_X64_MSR_RESET) is available*/
+#define HV_X64_MSR_RESET_AVAILABLE		(1 << 7)
+ /*
+  * Access statistics pages MSRs (HV_X64_MSR_STATS_PARTITION_RETAIL_PAGE,
+  * HV_X64_MSR_STATS_PARTITION_INTERNAL_PAGE, HV_X64_MSR_STATS_VP_RETAIL_PAGE,
+  * HV_X64_MSR_STATS_VP_INTERNAL_PAGE) available
+  */
+#define HV_X64_MSR_STAT_PAGES_AVAILABLE		(1 << 8)
+
+/*
+ * Feature identification: EBX indicates which flags were specified at
+ * partition creation. The format is the same as the partition creation
+ * flag structure defined in section Partition Creation Flags.
+ */
+#define HV_X64_CREATE_PARTITIONS		(1 << 0)
+#define HV_X64_ACCESS_PARTITION_ID		(1 << 1)
+#define HV_X64_ACCESS_MEMORY_POOL		(1 << 2)
+#define HV_X64_ADJUST_MESSAGE_BUFFERS		(1 << 3)
+#define HV_X64_POST_MESSAGES			(1 << 4)
+#define HV_X64_SIGNAL_EVENTS			(1 << 5)
+#define HV_X64_CREATE_PORT			(1 << 6)
+#define HV_X64_CONNECT_PORT			(1 << 7)
+#define HV_X64_ACCESS_STATS			(1 << 8)
+#define HV_X64_DEBUGGING			(1 << 11)
+#define HV_X64_CPU_POWER_MANAGEMENT		(1 << 12)
+#define HV_X64_CONFIGURE_PROFILER		(1 << 13)
+
+/*
+ * Feature identification. EDX indicates which miscellaneous features
+ * are available to the partition.
+ */
+/* The MWAIT instruction is available (per section MONITOR / MWAIT) */
+#define HV_X64_MWAIT_AVAILABLE				(1 << 0)
+/* Guest debugging support is available */
+#define HV_X64_GUEST_DEBUGGING_AVAILABLE		(1 << 1)
+/* Performance Monitor support is available*/
+#define HV_X64_PERF_MONITOR_AVAILABLE			(1 << 2)
+/* Support for physical CPU dynamic partitioning events is available*/
+#define HV_X64_CPU_DYNAMIC_PARTITIONING_AVAILABLE	(1 << 3)
+/*
+ * Support for passing hypercall input parameter block via XMM
+ * registers is available
+ */
+#define HV_X64_HYPERCALL_PARAMS_XMM_AVAILABLE		(1 << 4)
+/* Support for a virtual guest idle state is available */
+#define HV_X64_GUEST_IDLE_STATE_AVAILABLE		(1 << 5)
+
+/*
+ * Implementation recommendations. Indicates which behaviors the hypervisor
+ * recommends the OS implement for optimal performance.
+ */
+ /*
+  * Recommend using hypercall for address space switches rather
+  * than MOV to CR3 instruction
+  */
+#define HV_X64_MWAIT_RECOMMENDED		(1 << 0)
+/* Recommend using hypercall for local TLB flushes rather
+ * than INVLPG or MOV to CR3 instructions */
+#define HV_X64_LOCAL_TLB_FLUSH_RECOMMENDED	(1 << 1)
+/*
+ * Recommend using hypercall for remote TLB flushes rather
+ * than inter-processor interrupts
+ */
+#define HV_X64_REMOTE_TLB_FLUSH_RECOMMENDED	(1 << 2)
+/*
+ * Recommend using MSRs for accessing APIC registers
+ * EOI, ICR and TPR rather than their memory-mapped counterparts
+ */
+#define HV_X64_APIC_ACCESS_RECOMMENDED		(1 << 3)
+/* Recommend using the hypervisor-provided MSR to initiate a system RESET */
+#define HV_X64_SYSTEM_RESET_RECOMMENDED		(1 << 4)
+/*
+ * Recommend using relaxed timing for this partition. If used,
+ * the VM should disable any watchdog timeouts that rely on the
+ * timely delivery of external interrupts
+ */
+#define HV_X64_RELAXED_TIMING_RECOMMENDED	(1 << 5)
+
+/* MSR used to identify the guest OS. */
+#define HV_X64_MSR_GUEST_OS_ID			0x40000000
+
+/* MSR used to setup pages used to communicate with the hypervisor. */
+#define HV_X64_MSR_HYPERCALL			0x40000001
+
+/* MSR used to provide vcpu index */
+#define HV_X64_MSR_VP_INDEX			0x40000002
+
+/* MSR used to read the per-partition time reference counter */
+#define HV_X64_MSR_TIME_REF_COUNT		0x40000020
+
+/* Define the virtual APIC registers */
+#define HV_X64_MSR_EOI				0x40000070
+#define HV_X64_MSR_ICR				0x40000071
+#define HV_X64_MSR_TPR				0x40000072
+#define HV_X64_MSR_APIC_ASSIST_PAGE		0x40000073
+
+/* Define synthetic interrupt controller model specific registers. */
+#define HV_X64_MSR_SCONTROL			0x40000080
+#define HV_X64_MSR_SVERSION			0x40000081
+#define HV_X64_MSR_SIEFP			0x40000082
+#define HV_X64_MSR_SIMP				0x40000083
+#define HV_X64_MSR_EOM				0x40000084
+#define HV_X64_MSR_SINT0			0x40000090
+#define HV_X64_MSR_SINT1			0x40000091
+#define HV_X64_MSR_SINT2			0x40000092
+#define HV_X64_MSR_SINT3			0x40000093
+#define HV_X64_MSR_SINT4			0x40000094
+#define HV_X64_MSR_SINT5			0x40000095
+#define HV_X64_MSR_SINT6			0x40000096
+#define HV_X64_MSR_SINT7			0x40000097
+#define HV_X64_MSR_SINT8			0x40000098
+#define HV_X64_MSR_SINT9			0x40000099
+#define HV_X64_MSR_SINT10			0x4000009A
+#define HV_X64_MSR_SINT11			0x4000009B
+#define HV_X64_MSR_SINT12			0x4000009C
+#define HV_X64_MSR_SINT13			0x4000009D
+#define HV_X64_MSR_SINT14			0x4000009E
+#define HV_X64_MSR_SINT15			0x4000009F
+
+
+#define HV_X64_MSR_HYPERCALL_ENABLE		0x00000001
+#define HV_X64_MSR_HYPERCALL_PAGE_ADDRESS_SHIFT	12
+#define HV_X64_MSR_HYPERCALL_PAGE_ADDRESS_MASK	\
+		(~((1ull << HV_X64_MSR_HYPERCALL_PAGE_ADDRESS_SHIFT) - 1))
+
+/* Declare the various hypercall operations. */
+#define HV_X64_HV_NOTIFY_LONG_SPIN_WAIT		0x0008
+
+#define HV_X64_MSR_APIC_ASSIST_PAGE_ENABLE		0x00000001
+#define HV_X64_MSR_APIC_ASSIST_PAGE_ADDRESS_SHIFT	12
+#define HV_X64_MSR_APIC_ASSIST_PAGE_ADDRESS_MASK	\
+		(~((1ull << HV_X64_MSR_APIC_ASSIST_PAGE_ADDRESS_SHIFT) - 1))
+
+#define HV_PROCESSOR_POWER_STATE_C0		0
+#define HV_PROCESSOR_POWER_STATE_C1		1
+#define HV_PROCESSOR_POWER_STATE_C2		2
+#define HV_PROCESSOR_POWER_STATE_C3		3
+
+/* hypercall status code */
+#define HV_STATUS_SUCCESS			0
+#define HV_STATUS_INVALID_HYPERCALL_CODE	2
+#define HV_STATUS_INVALID_HYPERCALL_INPUT	3
+#define HV_STATUS_INVALID_ALIGNMENT		4
+
+#endif
diff --git a/drivers/staging/hv/include/asm/mshyperv.h b/drivers/staging/hv/include/asm/mshyperv.h
new file mode 100644
index 0000000..87b5199
--- /dev/null
+++ b/drivers/staging/hv/include/asm/mshyperv.h
@@ -0,0 +1,16 @@
+#ifndef _ASM_X86_MSHYPER_H
+#define _ASM_X86_MSHYPER_H
+
+#include <linux/types.h>
+#include <asm/hyperv.h>
+
+struct ms_hyperv_info {
+	u32 features;
+	u32 hints;
+};
+
+extern struct ms_hyperv_info ms_hyperv;
+extern  void  *x86_hyper;
+extern  int x86_hyper_ms_hyperv;
+
+#endif
diff --git a/drivers/staging/hv/include/linux/atomic.h b/drivers/staging/hv/include/linux/atomic.h
new file mode 100644
index 0000000..2e5735a
--- /dev/null
+++ b/drivers/staging/hv/include/linux/atomic.h
@@ -0,0 +1,5 @@
+#ifndef _LINUX_ATOMIC_H
+#define _LINUX_ATOMIC_H
+#include <asm/atomic.h>
+
+#endif
diff --git a/drivers/staging/hv/logging.h b/drivers/staging/hv/logging.h
deleted file mode 100644
index 20d4d12..0000000
--- a/drivers/staging/hv/logging.h
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- *
- * Copyright (c) 2009, Microsoft Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place - Suite 330, Boston, MA 02111-1307 USA.
- *
- * Authors:
- *   Haiyang Zhang <haiyangz@microsoft.com>
- *   Hank Janssen  <hjanssen@microsoft.com>
- *
- */
-
-
-#ifndef _LOGGING_H_
-#define _LOGGING_H_
-
-/* #include <linux/init.h> */
-/* #include <linux/module.h> */
-
-
-#define VMBUS				0x0001
-#define STORVSC				0x0002
-#define NETVSC				0x0004
-#define INPUTVSC			0x0008
-#define BLKVSC				0x0010
-#define VMBUS_DRV			0x0100
-#define STORVSC_DRV			0x0200
-#define NETVSC_DRV			0x0400
-#define INPUTVSC_DRV		0x0800
-#define BLKVSC_DRV			0x1000
-
-#define ALL_MODULES			(VMBUS		|\
-							STORVSC		|\
-							NETVSC		|\
-							INPUTVSC	|\
-							BLKVSC		|\
-							VMBUS_DRV	|\
-							STORVSC_DRV	|\
-							NETVSC_DRV	|\
-							INPUTVSC_DRV|\
-							BLKVSC_DRV)
-
-/* Logging Level */
-#define ERROR_LVL				3
-#define WARNING_LVL				4
-#define INFO_LVL				6
-#define DEBUG_LVL				7
-#define DEBUG_LVL_ENTEREXIT			8
-#define DEBUG_RING_LVL				9
-
-extern unsigned int vmbus_loglevel;
-
-#define DPRINT(mod, lvl, fmt, args...) do {\
-	if ((mod & (HIWORD(vmbus_loglevel))) &&	\
-	    (lvl <= LOWORD(vmbus_loglevel)))	\
-		printk(KERN_DEBUG #mod": %s() " fmt "\n", __func__, ## args);\
-	} while (0)
-
-#define DPRINT_DBG(mod, fmt, args...) do {\
-	if ((mod & (HIWORD(vmbus_loglevel))) &&		\
-	    (DEBUG_LVL <= LOWORD(vmbus_loglevel)))	\
-		printk(KERN_DEBUG #mod": %s() " fmt "\n", __func__, ## args);\
-	} while (0)
-
-#define DPRINT_INFO(mod, fmt, args...) do {\
-	if ((mod & (HIWORD(vmbus_loglevel))) &&		\
-	    (INFO_LVL <= LOWORD(vmbus_loglevel)))	\
-		printk(KERN_INFO #mod": " fmt "\n", ## args);\
-	} while (0)
-
-#define DPRINT_WARN(mod, fmt, args...) do {\
-	if ((mod & (HIWORD(vmbus_loglevel))) &&		\
-	    (WARNING_LVL <= LOWORD(vmbus_loglevel)))	\
-		printk(KERN_WARNING #mod": WARNING! " fmt "\n", ## args);\
-	} while (0)
-
-#define DPRINT_ERR(mod, fmt, args...) do {\
-	if ((mod & (HIWORD(vmbus_loglevel))) &&		\
-	    (ERROR_LVL <= LOWORD(vmbus_loglevel)))	\
-		printk(KERN_ERR #mod": %s() ERROR!! " fmt "\n",	\
-		       __func__, ## args);\
-	} while (0)
-
-#endif /* _LOGGING_H_ */
diff --git a/drivers/staging/hv/netvsc.c b/drivers/staging/hv/netvsc.c
new file mode 100644
index 0000000..267df74
--- /dev/null
+++ b/drivers/staging/hv/netvsc.c
@@ -0,0 +1,1015 @@
+/*
+ * Copyright (c) 2009, Microsoft Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * Authors:
+ *   Haiyang Zhang <haiyangz@microsoft.com>
+ *   Hank Janssen  <hjanssen@microsoft.com>
+ */
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/wait.h>
+#include <linux/mm.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+
+#include "hyperv.h"
+#include "hyperv_net.h"
+
+
+/* Globals */
+static const char *driver_name = "netvsc";
+
+/* {F8615163-DF3E-46c5-913F-F2D2F965ED0E} */
+static const struct hv_guid netvsc_device_type = {
+	.data = {
+		0x63, 0x51, 0x61, 0xF8, 0x3E, 0xDF, 0xc5, 0x46,
+		0x91, 0x3F, 0xF2, 0xD2, 0xF9, 0x65, 0xED, 0x0E
+	}
+};
+
+
+static struct netvsc_device *alloc_net_device(struct hv_device *device)
+{
+	struct netvsc_device *net_device;
+
+	net_device = kzalloc(sizeof(struct netvsc_device), GFP_KERNEL);
+	if (!net_device)
+		return NULL;
+
+	/* Set to 2 to allow both inbound and outbound traffic */
+	atomic_cmpxchg(&net_device->refcnt, 0, 2);
+
+	net_device->dev = device;
+	device->ext = net_device;
+
+	return net_device;
+}
+
+static void free_net_device(struct netvsc_device *device)
+{
+	WARN_ON(atomic_read(&device->refcnt) != 0);
+	device->dev->ext = NULL;
+	kfree(device);
+}
+
+
+/* Get the net device object iff exists and its refcount > 1 */
+static struct netvsc_device *get_outbound_net_device(struct hv_device *device)
+{
+	struct netvsc_device *net_device;
+
+	net_device = device->ext;
+	if (net_device && atomic_read(&net_device->refcnt) > 1)
+		atomic_inc(&net_device->refcnt);
+	else
+		net_device = NULL;
+
+	return net_device;
+}
+
+/* Get the net device object iff exists and its refcount > 0 */
+static struct netvsc_device *get_inbound_net_device(struct hv_device *device)
+{
+	struct netvsc_device *net_device;
+
+	net_device = device->ext;
+	if (net_device && atomic_read(&net_device->refcnt))
+		atomic_inc(&net_device->refcnt);
+	else
+		net_device = NULL;
+
+	return net_device;
+}
+
+static void put_net_device(struct hv_device *device)
+{
+	struct netvsc_device *net_device;
+
+	net_device = device->ext;
+
+	atomic_dec(&net_device->refcnt);
+}
+
+static struct netvsc_device *release_outbound_net_device(
+		struct hv_device *device)
+{
+	struct netvsc_device *net_device;
+
+	net_device = device->ext;
+	if (net_device == NULL)
+		return NULL;
+
+	/* Busy wait until the ref drop to 2, then set it to 1 */
+	while (atomic_cmpxchg(&net_device->refcnt, 2, 1) != 2)
+		udelay(100);
+
+	return net_device;
+}
+
+static struct netvsc_device *release_inbound_net_device(
+		struct hv_device *device)
+{
+	struct netvsc_device *net_device;
+
+	net_device = device->ext;
+	if (net_device == NULL)
+		return NULL;
+
+	/* Busy wait until the ref drop to 1, then set it to 0 */
+	while (atomic_cmpxchg(&net_device->refcnt, 1, 0) != 1)
+		udelay(100);
+
+	device->ext = NULL;
+	return net_device;
+}
+
+static int netvsc_destroy_recv_buf(struct netvsc_device *net_device)
+{
+	struct nvsp_message *revoke_packet;
+	int ret = 0;
+
+	/*
+	 * If we got a section count, it means we received a
+	 * SendReceiveBufferComplete msg (ie sent
+	 * NvspMessage1TypeSendReceiveBuffer msg) therefore, we need
+	 * to send a revoke msg here
+	 */
+	if (net_device->recv_section_cnt) {
+		/* Send the revoke receive buffer */
+		revoke_packet = &net_device->revoke_packet;
+		memset(revoke_packet, 0, sizeof(struct nvsp_message));
+
+		revoke_packet->hdr.msg_type =
+			NVSP_MSG1_TYPE_REVOKE_RECV_BUF;
+		revoke_packet->msg.v1_msg.
+		revoke_recv_buf.id = NETVSC_RECEIVE_BUFFER_ID;
+
+		ret = vmbus_sendpacket(net_device->dev->channel,
+				       revoke_packet,
+				       sizeof(struct nvsp_message),
+				       (unsigned long)revoke_packet,
+				       VM_PKT_DATA_INBAND, 0);
+		/*
+		 * If we failed here, we might as well return and
+		 * have a leak rather than continue and a bugchk
+		 */
+		if (ret != 0) {
+			dev_err(&net_device->dev->device, "unable to send "
+				"revoke receive buffer to netvsp");
+			return -1;
+		}
+	}
+
+	/* Teardown the gpadl on the vsp end */
+	if (net_device->recv_buf_gpadl_handle) {
+		ret = vmbus_teardown_gpadl(net_device->dev->channel,
+			   net_device->recv_buf_gpadl_handle);
+
+		/* If we failed here, we might as well return and have a leak
+		 * rather than continue and a bugchk
+		 */
+		if (ret != 0) {
+			dev_err(&net_device->dev->device,
+				   "unable to teardown receive buffer's gpadl");
+			return -1;
+		}
+		net_device->recv_buf_gpadl_handle = 0;
+	}
+
+	if (net_device->recv_buf) {
+		/* Free up the receive buffer */
+		free_pages((unsigned long)net_device->recv_buf,
+			get_order(net_device->recv_buf_size));
+		net_device->recv_buf = NULL;
+	}
+
+	if (net_device->recv_section) {
+		net_device->recv_section_cnt = 0;
+		kfree(net_device->recv_section);
+		net_device->recv_section = NULL;
+	}
+
+	return ret;
+}
+
+static int netvsc_init_recv_buf(struct hv_device *device)
+{
+	int ret = 0;
+	int t;
+	struct netvsc_device *net_device;
+	struct nvsp_message *init_packet;
+
+	net_device = get_outbound_net_device(device);
+	if (!net_device) {
+		dev_err(&device->device, "unable to get net device..."
+			   "device being destroyed?");
+		return -1;
+	}
+
+	net_device->recv_buf =
+		(void *)__get_free_pages(GFP_KERNEL|__GFP_ZERO,
+				get_order(net_device->recv_buf_size));
+	if (!net_device->recv_buf) {
+		dev_err(&device->device, "unable to allocate receive "
+			"buffer of size %d", net_device->recv_buf_size);
+		ret = -1;
+		goto cleanup;
+	}
+
+	/*
+	 * Establish the gpadl handle for this buffer on this
+	 * channel.  Note: This call uses the vmbus connection rather
+	 * than the channel to establish the gpadl handle.
+	 */
+	ret = vmbus_establish_gpadl(device->channel, net_device->recv_buf,
+				    net_device->recv_buf_size,
+				    &net_device->recv_buf_gpadl_handle);
+	if (ret != 0) {
+		dev_err(&device->device,
+			"unable to establish receive buffer's gpadl");
+		goto cleanup;
+	}
+
+
+	/* Notify the NetVsp of the gpadl handle */
+	init_packet = &net_device->channel_init_pkt;
+
+	memset(init_packet, 0, sizeof(struct nvsp_message));
+
+	init_packet->hdr.msg_type = NVSP_MSG1_TYPE_SEND_RECV_BUF;
+	init_packet->msg.v1_msg.send_recv_buf.
+		gpadl_handle = net_device->recv_buf_gpadl_handle;
+	init_packet->msg.v1_msg.
+		send_recv_buf.id = NETVSC_RECEIVE_BUFFER_ID;
+
+	/* Send the gpadl notification request */
+	ret = vmbus_sendpacket(device->channel, init_packet,
+			       sizeof(struct nvsp_message),
+			       (unsigned long)init_packet,
+			       VM_PKT_DATA_INBAND,
+			       VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
+	if (ret != 0) {
+		dev_err(&device->device,
+			"unable to send receive buffer's gpadl to netvsp");
+		goto cleanup;
+	}
+
+	t = wait_for_completion_timeout(&net_device->channel_init_wait, 5*HZ);
+	BUG_ON(t == 0);
+
+
+	/* Check the response */
+	if (init_packet->msg.v1_msg.
+	    send_recv_buf_complete.status != NVSP_STAT_SUCCESS) {
+		dev_err(&device->device, "Unable to complete receive buffer "
+			   "initialzation with NetVsp - status %d",
+			   init_packet->msg.v1_msg.
+			   send_recv_buf_complete.status);
+		ret = -1;
+		goto cleanup;
+	}
+
+	/* Parse the response */
+
+	net_device->recv_section_cnt = init_packet->msg.
+		v1_msg.send_recv_buf_complete.num_sections;
+
+	net_device->recv_section = kmalloc(net_device->recv_section_cnt
+		* sizeof(struct nvsp_1_receive_buffer_section), GFP_KERNEL);
+	if (net_device->recv_section == NULL) {
+		ret = -1;
+		goto cleanup;
+	}
+
+	memcpy(net_device->recv_section,
+		init_packet->msg.v1_msg.
+	       send_recv_buf_complete.sections,
+		net_device->recv_section_cnt *
+	       sizeof(struct nvsp_1_receive_buffer_section));
+
+	/*
+	 * For 1st release, there should only be 1 section that represents the
+	 * entire receive buffer
+	 */
+	if (net_device->recv_section_cnt != 1 ||
+	    net_device->recv_section->offset != 0) {
+		ret = -1;
+		goto cleanup;
+	}
+
+	goto exit;
+
+cleanup:
+	netvsc_destroy_recv_buf(net_device);
+
+exit:
+	put_net_device(device);
+	return ret;
+}
+
+
+static int netvsc_connect_vsp(struct hv_device *device)
+{
+	int ret, t;
+	struct netvsc_device *net_device;
+	struct nvsp_message *init_packet;
+	int ndis_version;
+
+	net_device = get_outbound_net_device(device);
+	if (!net_device) {
+		dev_err(&device->device, "unable to get net device..."
+			   "device being destroyed?");
+		return -1;
+	}
+
+	init_packet = &net_device->channel_init_pkt;
+
+	memset(init_packet, 0, sizeof(struct nvsp_message));
+	init_packet->hdr.msg_type = NVSP_MSG_TYPE_INIT;
+	init_packet->msg.init_msg.init.min_protocol_ver =
+		NVSP_MIN_PROTOCOL_VERSION;
+	init_packet->msg.init_msg.init.max_protocol_ver =
+		NVSP_MAX_PROTOCOL_VERSION;
+
+	/* Send the init request */
+	ret = vmbus_sendpacket(device->channel, init_packet,
+			       sizeof(struct nvsp_message),
+			       (unsigned long)init_packet,
+			       VM_PKT_DATA_INBAND,
+			       VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
+
+	if (ret != 0)
+		goto cleanup;
+
+	t = wait_for_completion_timeout(&net_device->channel_init_wait, HZ);
+
+	if (t == 0) {
+		ret = -ETIMEDOUT;
+		goto cleanup;
+	}
+
+	if (init_packet->msg.init_msg.init_complete.status !=
+	    NVSP_STAT_SUCCESS) {
+		ret = -1;
+		goto cleanup;
+	}
+
+	if (init_packet->msg.init_msg.init_complete.
+	    negotiated_protocol_ver != NVSP_PROTOCOL_VERSION_1) {
+		ret = -1;
+		goto cleanup;
+	}
+	/* Send the ndis version */
+	memset(init_packet, 0, sizeof(struct nvsp_message));
+
+	ndis_version = 0x00050000;
+
+	init_packet->hdr.msg_type = NVSP_MSG1_TYPE_SEND_NDIS_VER;
+	init_packet->msg.v1_msg.
+		send_ndis_ver.ndis_major_ver =
+				(ndis_version & 0xFFFF0000) >> 16;
+	init_packet->msg.v1_msg.
+		send_ndis_ver.ndis_minor_ver =
+				ndis_version & 0xFFFF;
+
+	/* Send the init request */
+	ret = vmbus_sendpacket(device->channel, init_packet,
+				sizeof(struct nvsp_message),
+				(unsigned long)init_packet,
+				VM_PKT_DATA_INBAND, 0);
+	if (ret != 0) {
+		ret = -1;
+		goto cleanup;
+	}
+
+	/* Post the big receive buffer to NetVSP */
+	ret = netvsc_init_recv_buf(device);
+
+cleanup:
+	put_net_device(device);
+	return ret;
+}
+
+static void netvsc_disconnect_vsp(struct netvsc_device *net_device)
+{
+	netvsc_destroy_recv_buf(net_device);
+}
+
+/*
+ * netvsc_device_remove - Callback when the root bus device is removed
+ */
+int netvsc_device_remove(struct hv_device *device)
+{
+	struct netvsc_device *net_device;
+	struct hv_netvsc_packet *netvsc_packet, *pos;
+
+	/* Stop outbound traffic ie sends and receives completions */
+	net_device = release_outbound_net_device(device);
+	if (!net_device) {
+		dev_err(&device->device, "No net device present!!");
+		return -1;
+	}
+
+	/* Wait for all send completions */
+	while (atomic_read(&net_device->num_outstanding_sends)) {
+		dev_err(&device->device,
+			"waiting for %d requests to complete...",
+			atomic_read(&net_device->num_outstanding_sends));
+		udelay(100);
+	}
+
+	netvsc_disconnect_vsp(net_device);
+
+	/* Stop inbound traffic ie receives and sends completions */
+	net_device = release_inbound_net_device(device);
+
+	/* At this point, no one should be accessing netDevice except in here */
+	dev_notice(&device->device, "net device safe to remove");
+
+	/* Now, we can close the channel safely */
+	vmbus_close(device->channel);
+
+	/* Release all resources */
+	list_for_each_entry_safe(netvsc_packet, pos,
+				 &net_device->recv_pkt_list, list_ent) {
+		list_del(&netvsc_packet->list_ent);
+		kfree(netvsc_packet);
+	}
+
+	free_net_device(net_device);
+	return 0;
+}
+
+static void netvsc_send_completion(struct hv_device *device,
+				   struct vmpacket_descriptor *packet)
+{
+	struct netvsc_device *net_device;
+	struct nvsp_message *nvsp_packet;
+	struct hv_netvsc_packet *nvsc_packet;
+
+	net_device = get_inbound_net_device(device);
+	if (!net_device) {
+		dev_err(&device->device, "unable to get net device..."
+			   "device being destroyed?");
+		return;
+	}
+
+	nvsp_packet = (struct nvsp_message *)((unsigned long)packet +
+			(packet->offset8 << 3));
+
+	if ((nvsp_packet->hdr.msg_type == NVSP_MSG_TYPE_INIT_COMPLETE) ||
+	    (nvsp_packet->hdr.msg_type ==
+	     NVSP_MSG1_TYPE_SEND_RECV_BUF_COMPLETE) ||
+	    (nvsp_packet->hdr.msg_type ==
+	     NVSP_MSG1_TYPE_SEND_SEND_BUF_COMPLETE)) {
+		/* Copy the response back */
+		memcpy(&net_device->channel_init_pkt, nvsp_packet,
+		       sizeof(struct nvsp_message));
+		complete(&net_device->channel_init_wait);
+	} else if (nvsp_packet->hdr.msg_type ==
+		   NVSP_MSG1_TYPE_SEND_RNDIS_PKT_COMPLETE) {
+		/* Get the send context */
+		nvsc_packet = (struct hv_netvsc_packet *)(unsigned long)
+			packet->trans_id;
+
+		/* Notify the layer above us */
+		nvsc_packet->completion.send.send_completion(
+			nvsc_packet->completion.send.send_completion_ctx);
+
+		atomic_dec(&net_device->num_outstanding_sends);
+	} else {
+		dev_err(&device->device, "Unknown send completion packet type- "
+			   "%d received!!", nvsp_packet->hdr.msg_type);
+	}
+
+	put_net_device(device);
+}
+
+int netvsc_send(struct hv_device *device,
+			struct hv_netvsc_packet *packet)
+{
+	struct netvsc_device *net_device;
+	int ret = 0;
+
+	struct nvsp_message sendMessage;
+
+	net_device = get_outbound_net_device(device);
+	if (!net_device) {
+		dev_err(&device->device, "net device (%p) shutting down..."
+			   "ignoring outbound packets", net_device);
+		return -2;
+	}
+
+	sendMessage.hdr.msg_type = NVSP_MSG1_TYPE_SEND_RNDIS_PKT;
+	if (packet->is_data_pkt) {
+		/* 0 is RMC_DATA; */
+		sendMessage.msg.v1_msg.send_rndis_pkt.channel_type = 0;
+	} else {
+		/* 1 is RMC_CONTROL; */
+		sendMessage.msg.v1_msg.send_rndis_pkt.channel_type = 1;
+	}
+
+	/* Not using send buffer section */
+	sendMessage.msg.v1_msg.send_rndis_pkt.send_buf_section_index =
+		0xFFFFFFFF;
+	sendMessage.msg.v1_msg.send_rndis_pkt.send_buf_section_size = 0;
+
+	if (packet->page_buf_cnt) {
+		ret = vmbus_sendpacket_pagebuffer(device->channel,
+						  packet->page_buf,
+						  packet->page_buf_cnt,
+						  &sendMessage,
+						  sizeof(struct nvsp_message),
+						  (unsigned long)packet);
+	} else {
+		ret = vmbus_sendpacket(device->channel, &sendMessage,
+				       sizeof(struct nvsp_message),
+				       (unsigned long)packet,
+				       VM_PKT_DATA_INBAND,
+				       VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
+
+	}
+
+	if (ret != 0)
+		dev_err(&device->device, "Unable to send packet %p ret %d",
+			   packet, ret);
+
+	atomic_inc(&net_device->num_outstanding_sends);
+	put_net_device(device);
+	return ret;
+}
+
+static void netvsc_send_recv_completion(struct hv_device *device,
+					u64 transaction_id)
+{
+	struct nvsp_message recvcompMessage;
+	int retries = 0;
+	int ret;
+
+	recvcompMessage.hdr.msg_type =
+				NVSP_MSG1_TYPE_SEND_RNDIS_PKT_COMPLETE;
+
+	/* FIXME: Pass in the status */
+	recvcompMessage.msg.v1_msg.send_rndis_pkt_complete.status =
+		NVSP_STAT_SUCCESS;
+
+retry_send_cmplt:
+	/* Send the completion */
+	ret = vmbus_sendpacket(device->channel, &recvcompMessage,
+			       sizeof(struct nvsp_message), transaction_id,
+			       VM_PKT_COMP, 0);
+	if (ret == 0) {
+		/* success */
+		/* no-op */
+	} else if (ret == -1) {
+		/* no more room...wait a bit and attempt to retry 3 times */
+		retries++;
+		dev_err(&device->device, "unable to send receive completion pkt"
+			" (tid %llx)...retrying %d", transaction_id, retries);
+
+		if (retries < 4) {
+			udelay(100);
+			goto retry_send_cmplt;
+		} else {
+			dev_err(&device->device, "unable to send receive "
+				"completion pkt (tid %llx)...give up retrying",
+				transaction_id);
+		}
+	} else {
+		dev_err(&device->device, "unable to send receive "
+			"completion pkt - %llx", transaction_id);
+	}
+}
+
+/* Send a receive completion packet to RNDIS device (ie NetVsp) */
+static void netvsc_receive_completion(void *context)
+{
+	struct hv_netvsc_packet *packet = context;
+	struct hv_device *device = (struct hv_device *)packet->device;
+	struct netvsc_device *net_device;
+	u64 transaction_id = 0;
+	bool fsend_receive_comp = false;
+	unsigned long flags;
+
+	/*
+	 * Even though it seems logical to do a GetOutboundNetDevice() here to
+	 * send out receive completion, we are using GetInboundNetDevice()
+	 * since we may have disable outbound traffic already.
+	 */
+	net_device = get_inbound_net_device(device);
+	if (!net_device) {
+		dev_err(&device->device, "unable to get net device..."
+			   "device being destroyed?");
+		return;
+	}
+
+	/* Overloading use of the lock. */
+	spin_lock_irqsave(&net_device->recv_pkt_list_lock, flags);
+
+	packet->xfer_page_pkt->count--;
+
+	/*
+	 * Last one in the line that represent 1 xfer page packet.
+	 * Return the xfer page packet itself to the freelist
+	 */
+	if (packet->xfer_page_pkt->count == 0) {
+		fsend_receive_comp = true;
+		transaction_id = packet->completion.recv.recv_completion_tid;
+		list_add_tail(&packet->xfer_page_pkt->list_ent,
+			      &net_device->recv_pkt_list);
+
+	}
+
+	/* Put the packet back */
+	list_add_tail(&packet->list_ent, &net_device->recv_pkt_list);
+	spin_unlock_irqrestore(&net_device->recv_pkt_list_lock, flags);
+
+	/* Send a receive completion for the xfer page packet */
+	if (fsend_receive_comp)
+		netvsc_send_recv_completion(device, transaction_id);
+
+	put_net_device(device);
+}
+
+static void netvsc_receive(struct hv_device *device,
+			    struct vmpacket_descriptor *packet)
+{
+	struct netvsc_device *net_device;
+	struct vmtransfer_page_packet_header *vmxferpage_packet;
+	struct nvsp_message *nvsp_packet;
+	struct hv_netvsc_packet *netvsc_packet = NULL;
+	unsigned long start;
+	unsigned long end, end_virtual;
+	/* struct netvsc_driver *netvscDriver; */
+	struct xferpage_packet *xferpage_packet = NULL;
+	int i, j;
+	int count = 0, bytes_remain = 0;
+	unsigned long flags;
+
+	LIST_HEAD(listHead);
+
+	net_device = get_inbound_net_device(device);
+	if (!net_device) {
+		dev_err(&device->device, "unable to get net device..."
+			   "device being destroyed?");
+		return;
+	}
+
+	/*
+	 * All inbound packets other than send completion should be xfer page
+	 * packet
+	 */
+	if (packet->type != VM_PKT_DATA_USING_XFER_PAGES) {
+		dev_err(&device->device, "Unknown packet type received - %d",
+			   packet->type);
+		put_net_device(device);
+		return;
+	}
+
+	nvsp_packet = (struct nvsp_message *)((unsigned long)packet +
+			(packet->offset8 << 3));
+
+	/* Make sure this is a valid nvsp packet */
+	if (nvsp_packet->hdr.msg_type !=
+	    NVSP_MSG1_TYPE_SEND_RNDIS_PKT) {
+		dev_err(&device->device, "Unknown nvsp packet type received-"
+			" %d", nvsp_packet->hdr.msg_type);
+		put_net_device(device);
+		return;
+	}
+
+	vmxferpage_packet = (struct vmtransfer_page_packet_header *)packet;
+
+	if (vmxferpage_packet->xfer_pageset_id != NETVSC_RECEIVE_BUFFER_ID) {
+		dev_err(&device->device, "Invalid xfer page set id - "
+			   "expecting %x got %x", NETVSC_RECEIVE_BUFFER_ID,
+			   vmxferpage_packet->xfer_pageset_id);
+		put_net_device(device);
+		return;
+	}
+
+	/*
+	 * Grab free packets (range count + 1) to represent this xfer
+	 * page packet. +1 to represent the xfer page packet itself.
+	 * We grab it here so that we know exactly how many we can
+	 * fulfil
+	 */
+	spin_lock_irqsave(&net_device->recv_pkt_list_lock, flags);
+	while (!list_empty(&net_device->recv_pkt_list)) {
+		list_move_tail(net_device->recv_pkt_list.next, &listHead);
+		if (++count == vmxferpage_packet->range_cnt + 1)
+			break;
+	}
+	spin_unlock_irqrestore(&net_device->recv_pkt_list_lock, flags);
+
+	/*
+	 * We need at least 2 netvsc pkts (1 to represent the xfer
+	 * page and at least 1 for the range) i.e. we can handled
+	 * some of the xfer page packet ranges...
+	 */
+	if (count < 2) {
+		dev_err(&device->device, "Got only %d netvsc pkt...needed "
+			"%d pkts. Dropping this xfer page packet completely!",
+			count, vmxferpage_packet->range_cnt + 1);
+
+		/* Return it to the freelist */
+		spin_lock_irqsave(&net_device->recv_pkt_list_lock, flags);
+		for (i = count; i != 0; i--) {
+			list_move_tail(listHead.next,
+				       &net_device->recv_pkt_list);
+		}
+		spin_unlock_irqrestore(&net_device->recv_pkt_list_lock,
+				       flags);
+
+		netvsc_send_recv_completion(device,
+					    vmxferpage_packet->d.trans_id);
+
+		put_net_device(device);
+		return;
+	}
+
+	/* Remove the 1st packet to represent the xfer page packet itself */
+	xferpage_packet = (struct xferpage_packet *)listHead.next;
+	list_del(&xferpage_packet->list_ent);
+
+	/* This is how much we can satisfy */
+	xferpage_packet->count = count - 1;
+
+	if (xferpage_packet->count != vmxferpage_packet->range_cnt) {
+		dev_err(&device->device, "Needed %d netvsc pkts to satisy "
+			"this xfer page...got %d",
+			vmxferpage_packet->range_cnt, xferpage_packet->count);
+	}
+
+	/* Each range represents 1 RNDIS pkt that contains 1 ethernet frame */
+	for (i = 0; i < (count - 1); i++) {
+		netvsc_packet = (struct hv_netvsc_packet *)listHead.next;
+		list_del(&netvsc_packet->list_ent);
+
+		/* Initialize the netvsc packet */
+		netvsc_packet->xfer_page_pkt = xferpage_packet;
+		netvsc_packet->completion.recv.recv_completion =
+					netvsc_receive_completion;
+		netvsc_packet->completion.recv.recv_completion_ctx =
+					netvsc_packet;
+		netvsc_packet->device = device;
+		/* Save this so that we can send it back */
+		netvsc_packet->completion.recv.recv_completion_tid =
+					vmxferpage_packet->d.trans_id;
+
+		netvsc_packet->total_data_buflen =
+					vmxferpage_packet->ranges[i].byte_count;
+		netvsc_packet->page_buf_cnt = 1;
+
+		netvsc_packet->page_buf[0].len =
+					vmxferpage_packet->ranges[i].byte_count;
+
+		start = virt_to_phys((void *)((unsigned long)net_device->
+		recv_buf + vmxferpage_packet->ranges[i].byte_offset));
+
+		netvsc_packet->page_buf[0].pfn = start >> PAGE_SHIFT;
+		end_virtual = (unsigned long)net_device->recv_buf
+		    + vmxferpage_packet->ranges[i].byte_offset
+		    + vmxferpage_packet->ranges[i].byte_count - 1;
+		end = virt_to_phys((void *)end_virtual);
+
+		/* Calculate the page relative offset */
+		netvsc_packet->page_buf[0].offset =
+			vmxferpage_packet->ranges[i].byte_offset &
+			(PAGE_SIZE - 1);
+		if ((end >> PAGE_SHIFT) != (start >> PAGE_SHIFT)) {
+			/* Handle frame across multiple pages: */
+			netvsc_packet->page_buf[0].len =
+				(netvsc_packet->page_buf[0].pfn <<
+				 PAGE_SHIFT)
+				+ PAGE_SIZE - start;
+			bytes_remain = netvsc_packet->total_data_buflen -
+					netvsc_packet->page_buf[0].len;
+			for (j = 1; j < NETVSC_PACKET_MAXPAGE; j++) {
+				netvsc_packet->page_buf[j].offset = 0;
+				if (bytes_remain <= PAGE_SIZE) {
+					netvsc_packet->page_buf[j].len =
+						bytes_remain;
+					bytes_remain = 0;
+				} else {
+					netvsc_packet->page_buf[j].len =
+						PAGE_SIZE;
+					bytes_remain -= PAGE_SIZE;
+				}
+				netvsc_packet->page_buf[j].pfn =
+				    virt_to_phys((void *)(end_virtual -
+						bytes_remain)) >> PAGE_SHIFT;
+				netvsc_packet->page_buf_cnt++;
+				if (bytes_remain == 0)
+					break;
+			}
+		}
+
+		/* Pass it to the upper layer */
+		rndis_filter_receive(device, netvsc_packet);
+
+		netvsc_receive_completion(netvsc_packet->
+				completion.recv.recv_completion_ctx);
+	}
+
+	put_net_device(device);
+}
+
+static void netvsc_channel_cb(void *context)
+{
+	int ret;
+	struct hv_device *device = context;
+	struct netvsc_device *net_device;
+	u32 bytes_recvd;
+	u64 request_id;
+	unsigned char *packet;
+	struct vmpacket_descriptor *desc;
+	unsigned char *buffer;
+	int bufferlen = NETVSC_PACKET_SIZE;
+
+	packet = kzalloc(NETVSC_PACKET_SIZE * sizeof(unsigned char),
+			 GFP_ATOMIC);
+	if (!packet)
+		return;
+	buffer = packet;
+
+	net_device = get_inbound_net_device(device);
+	if (!net_device) {
+		dev_err(&device->device, "net device (%p) shutting down..."
+			   "ignoring inbound packets", net_device);
+		goto out;
+	}
+
+	do {
+		ret = vmbus_recvpacket_raw(device->channel, buffer, bufferlen,
+					   &bytes_recvd, &request_id);
+		if (ret == 0) {
+			if (bytes_recvd > 0) {
+				desc = (struct vmpacket_descriptor *)buffer;
+				switch (desc->type) {
+				case VM_PKT_COMP:
+					netvsc_send_completion(device, desc);
+					break;
+
+				case VM_PKT_DATA_USING_XFER_PAGES:
+					netvsc_receive(device, desc);
+					break;
+
+				default:
+					dev_err(&device->device,
+						   "unhandled packet type %d, "
+						   "tid %llx len %d\n",
+						   desc->type, request_id,
+						   bytes_recvd);
+					break;
+				}
+
+				/* reset */
+				if (bufferlen > NETVSC_PACKET_SIZE) {
+					kfree(buffer);
+					buffer = packet;
+					bufferlen = NETVSC_PACKET_SIZE;
+				}
+			} else {
+				/* reset */
+				if (bufferlen > NETVSC_PACKET_SIZE) {
+					kfree(buffer);
+					buffer = packet;
+					bufferlen = NETVSC_PACKET_SIZE;
+				}
+
+				break;
+			}
+		} else if (ret == -2) {
+			/* Handle large packet */
+			buffer = kmalloc(bytes_recvd, GFP_ATOMIC);
+			if (buffer == NULL) {
+				/* Try again next time around */
+				dev_err(&device->device,
+					   "unable to allocate buffer of size "
+					   "(%d)!!", bytes_recvd);
+				break;
+			}
+
+			bufferlen = bytes_recvd;
+		}
+	} while (1);
+
+	put_net_device(device);
+out:
+	kfree(buffer);
+	return;
+}
+
+/*
+ * netvsc_device_add - Callback when the device belonging to this
+ * driver is added
+ */
+int netvsc_device_add(struct hv_device *device, void *additional_info)
+{
+	int ret = 0;
+	int i;
+	int ring_size =
+	((struct netvsc_device_info *)additional_info)->ring_size;
+	struct netvsc_device *net_device;
+	struct hv_netvsc_packet *packet, *pos;
+
+	net_device = alloc_net_device(device);
+	if (!net_device) {
+		ret = -1;
+		goto cleanup;
+	}
+
+	/* Initialize the NetVSC channel extension */
+	net_device->recv_buf_size = NETVSC_RECEIVE_BUFFER_SIZE;
+	spin_lock_init(&net_device->recv_pkt_list_lock);
+
+	INIT_LIST_HEAD(&net_device->recv_pkt_list);
+
+	for (i = 0; i < NETVSC_RECEIVE_PACKETLIST_COUNT; i++) {
+		packet = kzalloc(sizeof(struct hv_netvsc_packet) +
+				 (NETVSC_RECEIVE_SG_COUNT *
+				  sizeof(struct hv_page_buffer)), GFP_KERNEL);
+		if (!packet)
+			break;
+
+		list_add_tail(&packet->list_ent,
+			      &net_device->recv_pkt_list);
+	}
+	init_completion(&net_device->channel_init_wait);
+
+	/* Open the channel */
+	ret = vmbus_open(device->channel, ring_size * PAGE_SIZE,
+			 ring_size * PAGE_SIZE, NULL, 0,
+			 netvsc_channel_cb, device);
+
+	if (ret != 0) {
+		dev_err(&device->device, "unable to open channel: %d", ret);
+		ret = -1;
+		goto cleanup;
+	}
+
+	/* Channel is opened */
+	pr_info("hv_netvsc channel opened successfully");
+
+	/* Connect with the NetVsp */
+	ret = netvsc_connect_vsp(device);
+	if (ret != 0) {
+		dev_err(&device->device,
+			"unable to connect to NetVSP - %d", ret);
+		ret = -1;
+		goto close;
+	}
+
+	return ret;
+
+close:
+	/* Now, we can close the channel safely */
+	vmbus_close(device->channel);
+
+cleanup:
+
+	if (net_device) {
+		list_for_each_entry_safe(packet, pos,
+					 &net_device->recv_pkt_list,
+					 list_ent) {
+			list_del(&packet->list_ent);
+			kfree(packet);
+		}
+
+		release_outbound_net_device(device);
+		release_inbound_net_device(device);
+
+		free_net_device(net_device);
+	}
+
+	return ret;
+}
+
+/*
+ * netvsc_initialize - Main entry point
+ */
+int netvsc_initialize(struct hv_driver *drv)
+{
+
+	drv->name = driver_name;
+	memcpy(&drv->dev_type, &netvsc_device_type, sizeof(struct hv_guid));
+
+	return 0;
+}
diff --git a/drivers/staging/hv/netvsc_drv.c b/drivers/staging/hv/netvsc_drv.c
index 0d4bacf..8504520 100644
--- a/drivers/staging/hv/netvsc_drv.c
+++ b/drivers/staging/hv/netvsc_drv.c
@@ -18,7 +18,10 @@
  *   Haiyang Zhang <haiyangz@microsoft.com>
  *   Hank Janssen  <hjanssen@microsoft.com>
  */
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/init.h>
+#include <linux/atomic.h>
 #include <linux/module.h>
 #include <linux/highmem.h>
 #include <linux/device.h>
@@ -36,37 +39,29 @@
 #include <net/route.h>
 #include <net/sock.h>
 #include <net/pkt_sched.h>
-#include "osd.h"
-#include "logging.h"
-#include "VersionInfo.h"
-#include "vmbus.h"
-#include "NetVscApi.h"
+
+#include "hyperv.h"
+#include "hyperv_net.h"
 
 struct net_device_context {
 	/* point back to our device context */
-	struct vm_device *device_ctx;
-	unsigned long avail;
-	struct work_struct work;
+	struct hv_device *device_ctx;
+	atomic_t avail;
+	struct delayed_work dwork;
 };
 
-struct netvsc_driver_context {
-	/* !! These must be the first 2 fields !! */
-	/* Which is a bug FIXME! */
-	struct driver_context drv_ctx;
-	struct netvsc_driver drv_obj;
-};
 
 #define PACKET_PAGES_LOWATER  8
 /* Need this many pages to handle worst case fragmented packet */
 #define PACKET_PAGES_HIWATER  (MAX_SKB_FRAGS + 2)
 
-static int ring_size = roundup_pow_of_two(2*MAX_SKB_FRAGS+1);
+static int ring_size = 128;
 module_param(ring_size, int, S_IRUGO);
 MODULE_PARM_DESC(ring_size, "Ring buffer size (# of pages)");
 
-/* The one and only one */
-static struct netvsc_driver_context g_netvsc_drv;
-
+/* no-op so the netdev core doesn't return -EINVAL when modifying the the
+ * multicast address list in SIOCADDMULTI. hv is setup to get all multicast
+ * when it calls RndisFilterOnOpen() */
 static void netvsc_set_multicast_list(struct net_device *net)
 {
 }
@@ -74,21 +69,21 @@
 static int netvsc_open(struct net_device *net)
 {
 	struct net_device_context *net_device_ctx = netdev_priv(net);
-	struct hv_device *device_obj = &net_device_ctx->device_ctx->device_obj;
+	struct hv_device *device_obj = net_device_ctx->device_ctx;
 	int ret = 0;
 
 	if (netif_carrier_ok(net)) {
 		/* Open up the device */
-		ret = RndisFilterOnOpen(device_obj);
+		ret = rndis_filter_open(device_obj);
 		if (ret != 0) {
-			DPRINT_ERR(NETVSC_DRV,
-				   "unable to open device (ret %d).", ret);
+			netdev_err(net, "unable to open device (ret %d).\n",
+				   ret);
 			return ret;
 		}
 
 		netif_start_queue(net);
 	} else {
-		DPRINT_ERR(NETVSC_DRV, "unable to open device...link is down.");
+		netdev_err(net, "unable to open device...link is down.\n");
 	}
 
 	return ret;
@@ -97,15 +92,14 @@
 static int netvsc_close(struct net_device *net)
 {
 	struct net_device_context *net_device_ctx = netdev_priv(net);
-	struct hv_device *device_obj = &net_device_ctx->device_ctx->device_obj;
+	struct hv_device *device_obj = net_device_ctx->device_ctx;
 	int ret;
 
 	netif_stop_queue(net);
 
-	ret = RndisFilterOnClose(device_obj);
+	ret = rndis_filter_close(device_obj);
 	if (ret != 0)
-		DPRINT_ERR(NETVSC_DRV, "unable to close device (ret %d).", ret);
-
+		netdev_err(net, "unable to close device (ret %d).\n", ret);
 	return ret;
 }
 
@@ -113,7 +107,7 @@
 {
 	struct hv_netvsc_packet *packet = (struct hv_netvsc_packet *)context;
 	struct sk_buff *skb = (struct sk_buff *)
-		(unsigned long)packet->Completion.Send.SendCompletionTid;
+		(unsigned long)packet->completion.send.send_completion_tid;
 
 	kfree(packet);
 
@@ -124,7 +118,9 @@
 
 		dev_kfree_skb_any(skb);
 
-		if ((net_device_ctx->avail += num_pages) >= PACKET_PAGES_HIWATER)
+		atomic_add(num_pages, &net_device_ctx->avail);
+		if (atomic_read(&net_device_ctx->avail) >=
+				PACKET_PAGES_HIWATER)
  			netif_wake_queue(net);
 	}
 }
@@ -132,80 +128,66 @@
 static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
 {
 	struct net_device_context *net_device_ctx = netdev_priv(net);
-	struct driver_context *driver_ctx =
-	    driver_to_driver_context(net_device_ctx->device_ctx->device.driver);
-	struct netvsc_driver_context *net_drv_ctx =
-		(struct netvsc_driver_context *)driver_ctx;
-	struct netvsc_driver *net_drv_obj = &net_drv_ctx->drv_obj;
 	struct hv_netvsc_packet *packet;
 	int ret;
 	unsigned int i, num_pages;
 
-	DPRINT_DBG(NETVSC_DRV, "xmit packet - len %d data_len %d",
-		   skb->len, skb->data_len);
-
 	/* Add 1 for skb->data and additional one for RNDIS */
 	num_pages = skb_shinfo(skb)->nr_frags + 1 + 1;
-	if (num_pages > net_device_ctx->avail)
+	if (num_pages > atomic_read(&net_device_ctx->avail))
 		return NETDEV_TX_BUSY;
 
 	/* Allocate a netvsc packet based on # of frags. */
 	packet = kzalloc(sizeof(struct hv_netvsc_packet) +
 			 (num_pages * sizeof(struct hv_page_buffer)) +
-			 net_drv_obj->RequestExtSize, GFP_ATOMIC);
+			 sizeof(struct rndis_filter_packet), GFP_ATOMIC);
 	if (!packet) {
 		/* out of memory, silently drop packet */
-		DPRINT_ERR(NETVSC_DRV, "unable to allocate hv_netvsc_packet");
+		netdev_err(net, "unable to allocate hv_netvsc_packet\n");
 
 		dev_kfree_skb(skb);
 		net->stats.tx_dropped++;
 		return NETDEV_TX_OK;
 	}
 
-	packet->Extension = (void *)(unsigned long)packet +
+	packet->extension = (void *)(unsigned long)packet +
 				sizeof(struct hv_netvsc_packet) +
 				    (num_pages * sizeof(struct hv_page_buffer));
 
 	/* Setup the rndis header */
-	packet->PageBufferCount = num_pages;
-
-	/* TODO: Flush all write buffers/ memory fence ??? */
-	/* wmb(); */
+	packet->page_buf_cnt = num_pages;
 
 	/* Initialize it from the skb */
-	packet->TotalDataBufferLength	= skb->len;
+	packet->total_data_buflen	= skb->len;
 
 	/* Start filling in the page buffers starting after RNDIS buffer. */
-	packet->PageBuffers[1].Pfn = virt_to_phys(skb->data) >> PAGE_SHIFT;
-	packet->PageBuffers[1].Offset
+	packet->page_buf[1].pfn = virt_to_phys(skb->data) >> PAGE_SHIFT;
+	packet->page_buf[1].offset
 		= (unsigned long)skb->data & (PAGE_SIZE - 1);
-	packet->PageBuffers[1].Length = skb_headlen(skb);
+	packet->page_buf[1].len = skb_headlen(skb);
 
 	/* Additional fragments are after SKB data */
 	for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
 		skb_frag_t *f = &skb_shinfo(skb)->frags[i];
 
-		packet->PageBuffers[i+2].Pfn = page_to_pfn(f->page);
-		packet->PageBuffers[i+2].Offset = f->page_offset;
-		packet->PageBuffers[i+2].Length = f->size;
+		packet->page_buf[i+2].pfn = page_to_pfn(f->page);
+		packet->page_buf[i+2].offset = f->page_offset;
+		packet->page_buf[i+2].len = f->size;
 	}
 
 	/* Set the completion routine */
-	packet->Completion.Send.OnSendCompletion = netvsc_xmit_completion;
-	packet->Completion.Send.SendCompletionContext = packet;
-	packet->Completion.Send.SendCompletionTid = (unsigned long)skb;
+	packet->completion.send.send_completion = netvsc_xmit_completion;
+	packet->completion.send.send_completion_ctx = packet;
+	packet->completion.send.send_completion_tid = (unsigned long)skb;
 
-	ret = net_drv_obj->OnSend(&net_device_ctx->device_ctx->device_obj,
+	ret = rndis_filter_send(net_device_ctx->device_ctx,
 				  packet);
 	if (ret == 0) {
 		net->stats.tx_bytes += skb->len;
 		net->stats.tx_packets++;
 
-		DPRINT_DBG(NETVSC_DRV, "# of xmits %lu total size %lu",
-			   net->stats.tx_packets,
-			   net->stats.tx_bytes);
-
-		if ((net_device_ctx->avail -= num_pages) < PACKET_PAGES_LOWATER)
+		atomic_sub(num_pages, &net_device_ctx->avail);
+		if (atomic_read(&net_device_ctx->avail) < PACKET_PAGES_LOWATER)
 			netif_stop_queue(net);
 	} else {
 		/* we are shutting down or bus overloaded, just drop packet */
@@ -219,16 +201,15 @@
 /*
  * netvsc_linkstatus_callback - Link up/down notification
  */
-static void netvsc_linkstatus_callback(struct hv_device *device_obj,
+void netvsc_linkstatus_callback(struct hv_device *device_obj,
 				       unsigned int status)
 {
-	struct vm_device *device_ctx = to_vm_device(device_obj);
-	struct net_device *net = dev_get_drvdata(&device_ctx->device);
+	struct net_device *net = dev_get_drvdata(&device_obj->device);
 	struct net_device_context *ndev_ctx;
 
 	if (!net) {
-		DPRINT_ERR(NETVSC_DRV, "got link status but net device "
-				"not initialized yet");
+		netdev_err(net, "got link status but net device "
+				"not initialized yet\n");
 		return;
 	}
 
@@ -237,7 +218,7 @@
 		netif_wake_queue(net);
 		netif_notify_peers(net);
 		ndev_ctx = netdev_priv(net);
-		schedule_work(&ndev_ctx->work);
+		schedule_delayed_work(&ndev_ctx->dwork, msecs_to_jiffies(20));
 	} else {
 		netif_carrier_off(net);
 		netif_stop_queue(net);
@@ -248,24 +229,23 @@
  * netvsc_recv_callback -  Callback when we receive a packet from the
  * "wire" on the specified device.
  */
-static int netvsc_recv_callback(struct hv_device *device_obj,
+int netvsc_recv_callback(struct hv_device *device_obj,
 				struct hv_netvsc_packet *packet)
 {
-	struct vm_device *device_ctx = to_vm_device(device_obj);
-	struct net_device *net = dev_get_drvdata(&device_ctx->device);
+	struct net_device *net = dev_get_drvdata(&device_obj->device);
 	struct sk_buff *skb;
 	void *data;
 	int i;
 	unsigned long flags;
 
 	if (!net) {
-		DPRINT_ERR(NETVSC_DRV, "got receive callback but net device "
-				"not initialized yet");
+		netdev_err(net, "got receive callback but net device"
+			" not initialized yet\n");
 		return 0;
 	}
 
 	/* Allocate a skb - TODO direct I/O to pages? */
-	skb = netdev_alloc_skb_ip_align(net, packet->TotalDataBufferLength);
+	skb = netdev_alloc_skb_ip_align(net, packet->total_data_buflen);
 	if (unlikely(!skb)) {
 		++net->stats.rx_dropped;
 		return 0;
@@ -278,17 +258,17 @@
 	 * Copy to skb. This copy is needed here since the memory pointed by
 	 * hv_netvsc_packet cannot be deallocated
 	 */
-	for (i = 0; i < packet->PageBufferCount; i++) {
-		data = kmap_atomic(pfn_to_page(packet->PageBuffers[i].Pfn),
+	for (i = 0; i < packet->page_buf_cnt; i++) {
+		data = kmap_atomic(pfn_to_page(packet->page_buf[i].pfn),
 					       KM_IRQ1);
 		data = (void *)(unsigned long)data +
-				packet->PageBuffers[i].Offset;
+				packet->page_buf[i].offset;
 
-		memcpy(skb_put(skb, packet->PageBuffers[i].Length), data,
-		       packet->PageBuffers[i].Length);
+		memcpy(skb_put(skb, packet->page_buf[i].len), data,
+		       packet->page_buf[i].len);
 
 		kunmap_atomic((void *)((unsigned long)data -
-				       packet->PageBuffers[i].Offset), KM_IRQ1);
+				       packet->page_buf[i].offset), KM_IRQ1);
 	}
 
 	local_irq_restore(flags);
@@ -306,9 +286,6 @@
 	 */
 	netif_rx(skb);
 
-	DPRINT_DBG(NETVSC_DRV, "# of recvs %lu total size %lu",
-		   net->stats.rx_packets, net->stats.rx_bytes);
-
 	return 0;
 }
 
@@ -322,8 +299,6 @@
 
 static const struct ethtool_ops ethtool_ops = {
 	.get_drvinfo	= netvsc_get_drvinfo,
-	.get_sg		= ethtool_op_get_sg,
-	.set_sg		= ethtool_op_set_sg,
 	.get_link	= ethtool_op_get_link,
 };
 
@@ -341,7 +316,7 @@
  * Send GARP packet to network peers after migrations.
  * After Quick Migration, the network is not immediately operational in the
  * current context when receiving RNDIS_STATUS_MEDIA_CONNECT event. So, add
- * another netif_notify_peers() into a scheduled work, otherwise GARP packet
+ * another netif_notify_peers() into a delayed work, otherwise GARP packet
  * will not be sent after quick migration, and cause network disconnection.
  */
 static void netvsc_send_garp(struct work_struct *w)
@@ -349,68 +324,46 @@
 	struct net_device_context *ndev_ctx;
 	struct net_device *net;
 
-	msleep(20);
-	ndev_ctx = container_of(w, struct net_device_context, work);
+	ndev_ctx = container_of(w, struct net_device_context, dwork.work);
 	net = dev_get_drvdata(&ndev_ctx->device_ctx->device);
 	netif_notify_peers(net);
 }
 
 
-static int netvsc_probe(struct device *device)
+static int netvsc_probe(struct hv_device *dev)
 {
-	struct driver_context *driver_ctx =
-		driver_to_driver_context(device->driver);
-	struct netvsc_driver_context *net_drv_ctx =
-		(struct netvsc_driver_context *)driver_ctx;
-	struct netvsc_driver *net_drv_obj = &net_drv_ctx->drv_obj;
-	struct vm_device *device_ctx = device_to_vm_device(device);
-	struct hv_device *device_obj = &device_ctx->device_obj;
 	struct net_device *net = NULL;
 	struct net_device_context *net_device_ctx;
 	struct netvsc_device_info device_info;
 	int ret;
 
-	if (!net_drv_obj->Base.OnDeviceAdd)
-		return -1;
-
 	net = alloc_etherdev(sizeof(struct net_device_context));
 	if (!net)
 		return -1;
 
 	/* Set initial state */
 	netif_carrier_off(net);
-	netif_stop_queue(net);
 
 	net_device_ctx = netdev_priv(net);
-	net_device_ctx->device_ctx = device_ctx;
-	net_device_ctx->avail = ring_size;
-	dev_set_drvdata(device, net);
-	INIT_WORK(&net_device_ctx->work, netvsc_send_garp);
+	net_device_ctx->device_ctx = dev;
+	atomic_set(&net_device_ctx->avail, ring_size);
+	dev_set_drvdata(&dev->device, net);
+	INIT_DELAYED_WORK(&net_device_ctx->dwork, netvsc_send_garp);
 
 	/* Notify the netvsc driver of the new device */
-	ret = net_drv_obj->Base.OnDeviceAdd(device_obj, &device_info);
+	device_info.ring_size = ring_size;
+	ret = rndis_filter_device_add(dev, &device_info);
 	if (ret != 0) {
 		free_netdev(net);
-		dev_set_drvdata(device, NULL);
+		dev_set_drvdata(&dev->device, NULL);
 
-		DPRINT_ERR(NETVSC_DRV, "unable to add netvsc device (ret %d)",
-			   ret);
+		netdev_err(net, "unable to add netvsc device (ret %d)\n", ret);
 		return ret;
 	}
 
-	/*
-	 * If carrier is still off ie we did not get a link status callback,
-	 * update it if necessary
-	 */
-	/*
-	 * FIXME: We should use a atomic or test/set instead to avoid getting
-	 * out of sync with the device's link status
-	 */
-	if (!netif_carrier_ok(net))
-		if (!device_info.LinkState)
-			netif_carrier_on(net);
+	netif_carrier_on(net);
 
-	memcpy(net->dev_addr, device_info.MacAddr, ETH_ALEN);
+	memcpy(net->dev_addr, device_info.mac_adr, ETH_ALEN);
 
 	net->netdev_ops = &device_ops;
 
@@ -418,41 +371,33 @@
 	net->features = NETIF_F_SG;
 
 	SET_ETHTOOL_OPS(net, &ethtool_ops);
-	SET_NETDEV_DEV(net, device);
+	SET_NETDEV_DEV(net, &dev->device);
 
 	ret = register_netdev(net);
 	if (ret != 0) {
 		/* Remove the device and release the resource */
-		net_drv_obj->Base.OnDeviceRemove(device_obj);
+		rndis_filter_device_remove(dev);
 		free_netdev(net);
 	}
 
 	return ret;
 }
 
-static int netvsc_remove(struct device *device)
+static int netvsc_remove(struct hv_device *dev)
 {
-	struct driver_context *driver_ctx =
-		driver_to_driver_context(device->driver);
-	struct netvsc_driver_context *net_drv_ctx =
-		(struct netvsc_driver_context *)driver_ctx;
-	struct netvsc_driver *net_drv_obj = &net_drv_ctx->drv_obj;
-	struct vm_device *device_ctx = device_to_vm_device(device);
-	struct net_device *net = dev_get_drvdata(&device_ctx->device);
-	struct hv_device *device_obj = &device_ctx->device_obj;
-	int ret;
+	struct net_device *net = dev_get_drvdata(&dev->device);
+	struct net_device_context *ndev_ctx;
 
 	if (net == NULL) {
-		DPRINT_INFO(NETVSC, "no net device to remove");
+		dev_err(&dev->device, "No net device to remove\n");
 		return 0;
 	}
 
-	if (!net_drv_obj->Base.OnDeviceRemove)
-		return -1;
+	ndev_ctx = netdev_priv(net);
+	cancel_delayed_work_sync(&ndev_ctx->dwork);
 
 	/* Stop outbound asap */
 	netif_stop_queue(net);
-	/* netif_carrier_off(net); */
 
 	unregister_netdev(net);
 
@@ -460,87 +405,23 @@
 	 * Call to the vsc driver to let it know that the device is being
 	 * removed
 	 */
-	ret = net_drv_obj->Base.OnDeviceRemove(device_obj);
-	if (ret != 0) {
-		/* TODO: */
-		DPRINT_ERR(NETVSC, "unable to remove vsc device (ret %d)", ret);
-	}
+	rndis_filter_device_remove(dev);
 
 	free_netdev(net);
-	return ret;
+	return 0;
 }
 
-static int netvsc_drv_exit_cb(struct device *dev, void *data)
+/* The one and only one */
+static struct  hv_driver netvsc_drv = {
+	.probe = netvsc_probe,
+	.remove = netvsc_remove,
+};
+
+static void __exit netvsc_drv_exit(void)
 {
-	struct device **curr = (struct device **)data;
-
-	*curr = dev;
-	/* stop iterating */
-	return 1;
+	vmbus_child_driver_unregister(&netvsc_drv.driver);
 }
 
-static void netvsc_drv_exit(void)
-{
-	struct netvsc_driver *netvsc_drv_obj = &g_netvsc_drv.drv_obj;
-	struct driver_context *drv_ctx = &g_netvsc_drv.drv_ctx;
-	struct device *current_dev;
-	int ret;
-
-	while (1) {
-		current_dev = NULL;
-
-		/* Get the device */
-		ret = driver_for_each_device(&drv_ctx->driver, NULL,
-					     &current_dev, netvsc_drv_exit_cb);
-		if (ret)
-			DPRINT_WARN(NETVSC_DRV,
-				    "driver_for_each_device returned %d", ret);
-
-		if (current_dev == NULL)
-			break;
-
-		/* Initiate removal from the top-down */
-		DPRINT_INFO(NETVSC_DRV, "unregistering device (%p)...",
-			    current_dev);
-
-		device_unregister(current_dev);
-	}
-
-	if (netvsc_drv_obj->Base.OnCleanup)
-		netvsc_drv_obj->Base.OnCleanup(&netvsc_drv_obj->Base);
-
-	vmbus_child_driver_unregister(drv_ctx);
-
-	return;
-}
-
-static int netvsc_drv_init(int (*drv_init)(struct hv_driver *drv))
-{
-	struct netvsc_driver *net_drv_obj = &g_netvsc_drv.drv_obj;
-	struct driver_context *drv_ctx = &g_netvsc_drv.drv_ctx;
-	int ret;
-
-	vmbus_get_interface(&net_drv_obj->Base.VmbusChannelInterface);
-
-	net_drv_obj->RingBufferSize = ring_size * PAGE_SIZE;
-	net_drv_obj->OnReceiveCallback = netvsc_recv_callback;
-	net_drv_obj->OnLinkStatusChanged = netvsc_linkstatus_callback;
-
-	/* Callback to client driver to complete the initialization */
-	drv_init(&net_drv_obj->Base);
-
-	drv_ctx->driver.name = net_drv_obj->Base.name;
-	memcpy(&drv_ctx->class_id, &net_drv_obj->Base.deviceType,
-	       sizeof(struct hv_guid));
-
-	drv_ctx->probe = netvsc_probe;
-	drv_ctx->remove = netvsc_remove;
-
-	/* The driver belongs to vmbus */
-	ret = vmbus_child_driver_register(drv_ctx);
-
-	return ret;
-}
 
 static const struct dmi_system_id __initconst
 hv_netvsc_dmi_table[] __maybe_unused  = {
@@ -556,19 +437,26 @@
 };
 MODULE_DEVICE_TABLE(dmi, hv_netvsc_dmi_table);
 
-static int __init netvsc_init(void)
+static int __init netvsc_drv_init(void)
 {
-	DPRINT_INFO(NETVSC_DRV, "Netvsc initializing....");
+	struct hv_driver *drv = &netvsc_drv;
+	int ret;
+
+	pr_info("initializing....");
 
 	if (!dmi_check_system(hv_netvsc_dmi_table))
 		return -ENODEV;
 
-	return netvsc_drv_init(NetVscInitialize);
-}
 
-static void __exit netvsc_exit(void)
-{
-	netvsc_drv_exit();
+	/* Callback to client driver to complete the initialization */
+	netvsc_initialize(drv);
+
+	drv->driver.name = drv->name;
+
+	/* The driver belongs to vmbus */
+	ret = vmbus_child_driver_register(&drv->driver);
+
+	return ret;
 }
 
 static const struct pci_device_id __initconst
@@ -582,5 +470,5 @@
 MODULE_VERSION(HV_DRV_VERSION);
 MODULE_DESCRIPTION("Microsoft Hyper-V network driver");
 
-module_init(netvsc_init);
-module_exit(netvsc_exit);
+module_init(netvsc_drv_init);
+module_exit(netvsc_drv_exit);
diff --git a/drivers/staging/hv/osd.c b/drivers/staging/hv/osd.c
deleted file mode 100644
index 8c3eb27..0000000
--- a/drivers/staging/hv/osd.c
+++ /dev/null
@@ -1,228 +0,0 @@
-/*
- *
- * Copyright (c) 2009, Microsoft Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place - Suite 330, Boston, MA 02111-1307 USA.
- *
- * Authors:
- *   Haiyang Zhang <haiyangz@microsoft.com>
- *   Hank Janssen  <hjanssen@microsoft.com>
- *
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/mm.h>
-#include <linux/highmem.h>
-#include <linux/vmalloc.h>
-#include <linux/ioport.h>
-#include <linux/irq.h>
-#include <linux/interrupt.h>
-#include <linux/sched.h>
-#include <linux/wait.h>
-#include <linux/spinlock.h>
-#include <linux/workqueue.h>
-#include <linux/kernel.h>
-#include <linux/jiffies.h>
-#include <linux/delay.h>
-#include <linux/time.h>
-#include <linux/io.h>
-#include <linux/bitops.h>
-#include <linux/slab.h>
-#include "osd.h"
-
-struct osd_callback_struct {
-	struct work_struct work;
-	void (*callback)(void *);
-	void *data;
-};
-
-void *osd_VirtualAllocExec(unsigned int size)
-{
-#ifdef __x86_64__
-	return __vmalloc(size, GFP_KERNEL, PAGE_KERNEL_EXEC);
-#else
-	return __vmalloc(size, GFP_KERNEL,
-			 __pgprot(__PAGE_KERNEL & (~_PAGE_NX)));
-#endif
-}
-
-/**
- * osd_PageAlloc() - Allocate pages
- * @count:      Total number of Kernel pages you want to allocate
- *
- * Tries to allocate @count number of consecutive free kernel pages.
- * And if successful, it will set the pages to 0 before returning.
- * If successfull it will return pointer to the @count pages.
- * Mainly used by Hyper-V drivers.
- */
-void *osd_PageAlloc(unsigned int count)
-{
-	void *p;
-
-	p = (void *)__get_free_pages(GFP_KERNEL, get_order(count * PAGE_SIZE));
-	if (p)
-		memset(p, 0, count * PAGE_SIZE);
-	return p;
-
-	/* struct page* page = alloc_page(GFP_KERNEL|__GFP_ZERO); */
-	/* void *p; */
-
-	/* BUGBUG: We need to use kmap in case we are in HIMEM region */
-	/* p = page_address(page); */
-	/* if (p) memset(p, 0, PAGE_SIZE); */
-	/* return p; */
-}
-EXPORT_SYMBOL_GPL(osd_PageAlloc);
-
-/**
- * osd_PageFree() - Free pages
- * @page:       Pointer to the first page to be freed
- * @count:      Total number of Kernel pages you free
- *
- * Frees the pages allocated by osd_PageAlloc()
- * Mainly used by Hyper-V drivers.
- */
-void osd_PageFree(void *page, unsigned int count)
-{
-	free_pages((unsigned long)page, get_order(count * PAGE_SIZE));
-	/*struct page* p = virt_to_page(page);
-	__free_page(p);*/
-}
-EXPORT_SYMBOL_GPL(osd_PageFree);
-
-/**
- * osd_WaitEventCreate() - Create the event queue
- *
- * Allocates memory for a &struct osd_waitevent. And then calls
- * init_waitqueue_head to set up the wait queue for the event.
- * This structure is usually part of a another structure that contains
- * the actual Hyper-V device driver structure.
- *
- * Returns pointer to &struct osd_waitevent
- * Mainly used by Hyper-V drivers.
- */
-struct osd_waitevent *osd_WaitEventCreate(void)
-{
-	struct osd_waitevent *wait = kmalloc(sizeof(struct osd_waitevent),
-					     GFP_KERNEL);
-	if (!wait)
-		return NULL;
-
-	wait->condition = 0;
-	init_waitqueue_head(&wait->event);
-	return wait;
-}
-EXPORT_SYMBOL_GPL(osd_WaitEventCreate);
-
-
-/**
- * osd_WaitEventSet() - Wake up the process
- * @waitEvent: Structure to event to be woken up
- *
- * @waitevent is of type &struct osd_waitevent
- *
- * Wake up the sleeping process so it can do some work.
- * And set condition indicator in &struct osd_waitevent to indicate
- * the process is in a woken state.
- *
- * Only used by Network and Storage Hyper-V drivers.
- */
-void osd_WaitEventSet(struct osd_waitevent *waitEvent)
-{
-	waitEvent->condition = 1;
-	wake_up_interruptible(&waitEvent->event);
-}
-EXPORT_SYMBOL_GPL(osd_WaitEventSet);
-
-/**
- * osd_WaitEventWait() - Wait for event till condition is true
- * @waitEvent: Structure to event to be put to sleep
- *
- * @waitevent is of type &struct osd_waitevent
- *
- * Set up the process to sleep until waitEvent->condition get true.
- * And set condition indicator in &struct osd_waitevent to indicate
- * the process is in a sleeping state.
- *
- * Returns the status of 'wait_event_interruptible()' system call
- *
- * Mainly used by Hyper-V drivers.
- */
-int osd_WaitEventWait(struct osd_waitevent *waitEvent)
-{
-	int ret = 0;
-
-	ret = wait_event_interruptible(waitEvent->event,
-				       waitEvent->condition);
-	waitEvent->condition = 0;
-	return ret;
-}
-EXPORT_SYMBOL_GPL(osd_WaitEventWait);
-
-/**
- * osd_WaitEventWaitEx() - Wait for event or timeout for process wakeup
- * @waitEvent: Structure to event to be put to sleep
- * @TimeoutInMs:       Total number of Milliseconds to wait before waking up
- *
- * @waitevent is of type &struct osd_waitevent
- * Set up the process to sleep until @waitEvent->condition get true or
- * @TimeoutInMs (Time out in Milliseconds) has been reached.
- * And set condition indicator in &struct osd_waitevent to indicate
- * the process is in a sleeping state.
- *
- * Returns the status of 'wait_event_interruptible_timeout()' system call
- *
- * Mainly used by Hyper-V drivers.
- */
-int osd_WaitEventWaitEx(struct osd_waitevent *waitEvent, u32 TimeoutInMs)
-{
-	int ret = 0;
-
-	ret = wait_event_interruptible_timeout(waitEvent->event,
-					       waitEvent->condition,
-					       msecs_to_jiffies(TimeoutInMs));
-	waitEvent->condition = 0;
-	return ret;
-}
-EXPORT_SYMBOL_GPL(osd_WaitEventWaitEx);
-
-static void osd_callback_work(struct work_struct *work)
-{
-	struct osd_callback_struct *cb = container_of(work,
-						struct osd_callback_struct,
-						work);
-	(cb->callback)(cb->data);
-	kfree(cb);
-}
-
-int osd_schedule_callback(struct workqueue_struct *wq,
-			  void (*func)(void *),
-			  void *data)
-{
-	struct osd_callback_struct *cb;
-
-	cb = kmalloc(sizeof(*cb), GFP_KERNEL);
-	if (!cb) {
-		printk(KERN_ERR "unable to allocate memory in osd_schedule_callback\n");
-		return -1;
-	}
-
-	cb->callback = func;
-	cb->data = data;
-	INIT_WORK(&cb->work, osd_callback_work);
-	return queue_work(wq, &cb->work);
-}
-
diff --git a/drivers/staging/hv/osd.h b/drivers/staging/hv/osd.h
deleted file mode 100644
index ce064e8..0000000
--- a/drivers/staging/hv/osd.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- *
- * Copyright (c) 2009, Microsoft Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place - Suite 330, Boston, MA 02111-1307 USA.
- *
- * Authors:
- *   Haiyang Zhang <haiyangz@microsoft.com>
- *   Hank Janssen  <hjanssen@microsoft.com>
- *
- */
-
-
-#ifndef _OSD_H_
-#define _OSD_H_
-
-#include <linux/workqueue.h>
-
-/* Defines */
-#define ALIGN_UP(value, align)	(((value) & (align-1)) ?		\
-				 (((value) + (align-1)) & ~(align-1)) :	\
-				 (value))
-#define ALIGN_DOWN(value, align)	((value) & ~(align-1))
-#define NUM_PAGES_SPANNED(addr, len)	((ALIGN_UP(addr+len, PAGE_SIZE) - \
-					 ALIGN_DOWN(addr, PAGE_SIZE)) >>  \
-					 PAGE_SHIFT)
-
-#define LOWORD(dw)	((unsigned short)(dw))
-#define HIWORD(dw)	((unsigned short)(((unsigned int) (dw) >> 16) & 0xFFFF))
-
-struct hv_guid {
-	unsigned char data[16];
-};
-
-struct osd_waitevent {
-	int condition;
-	wait_queue_head_t event;
-};
-
-/* Osd routines */
-
-extern void *osd_VirtualAllocExec(unsigned int size);
-
-extern void *osd_PageAlloc(unsigned int count);
-extern void osd_PageFree(void *page, unsigned int count);
-
-extern struct osd_waitevent *osd_WaitEventCreate(void);
-extern void osd_WaitEventSet(struct osd_waitevent *waitEvent);
-extern int osd_WaitEventWait(struct osd_waitevent *waitEvent);
-
-/* If >0, waitEvent got signaled. If ==0, timeout. If < 0, error */
-extern int osd_WaitEventWaitEx(struct osd_waitevent *waitEvent,
-			       u32 TimeoutInMs);
-
-int osd_schedule_callback(struct workqueue_struct *wq,
-			  void (*func)(void *),
-			  void *data);
-
-#endif /* _OSD_H_ */
diff --git a/drivers/staging/hv/overrides.mk b/drivers/staging/hv/overrides.mk
new file mode 100644
index 0000000..1e370cf
--- /dev/null
+++ b/drivers/staging/hv/overrides.mk
@@ -0,0 +1,4 @@
+_HV_CPPFLAGS += -I$(M)/include
+
+EXTRA_CFLAGS += $(_HV_CPPFLAGS)
+CPPFLAGS := -I$(M)/include $(CPPFLAGS)
diff --git a/drivers/staging/hv/ring_buffer.c b/drivers/staging/hv/ring_buffer.c
new file mode 100644
index 0000000..42f7672
--- /dev/null
+++ b/drivers/staging/hv/ring_buffer.c
@@ -0,0 +1,526 @@
+/*
+ *
+ * Copyright (c) 2009, Microsoft Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * Authors:
+ *   Haiyang Zhang <haiyangz@microsoft.com>
+ *   Hank Janssen  <hjanssen@microsoft.com>
+ *   K. Y. Srinivasan <kys@microsoft.com>
+ *
+ */
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/mm.h>
+
+#include "hyperv.h"
+#include "hyperv_vmbus.h"
+
+
+/* #defines */
+
+
+/* Amount of space to write to */
+#define BYTES_AVAIL_TO_WRITE(r, w, z) ((w) >= (r)) ? ((z) - ((w) - (r))) : ((r) - (w))
+
+
+/*
+ *
+ * hv_get_ringbuffer_availbytes()
+ *
+ * Get number of bytes available to read and to write to
+ * for the specified ring buffer
+ */
+static inline void
+hv_get_ringbuffer_availbytes(struct hv_ring_buffer_info *rbi,
+			  u32 *read, u32 *write)
+{
+	u32 read_loc, write_loc;
+
+	smp_read_barrier_depends();
+
+	/* Capture the read/write indices before they changed */
+	read_loc = rbi->ring_buffer->read_index;
+	write_loc = rbi->ring_buffer->write_index;
+
+	*write = BYTES_AVAIL_TO_WRITE(read_loc, write_loc, rbi->ring_datasize);
+	*read = rbi->ring_datasize - *write;
+}
+
+/*
+ * hv_get_next_write_location()
+ *
+ * Get the next write location for the specified ring buffer
+ *
+ */
+static inline u32
+hv_get_next_write_location(struct hv_ring_buffer_info *ring_info)
+{
+	u32 next = ring_info->ring_buffer->write_index;
+
+	return next;
+}
+
+/*
+ * hv_set_next_write_location()
+ *
+ * Set the next write location for the specified ring buffer
+ *
+ */
+static inline void
+hv_set_next_write_location(struct hv_ring_buffer_info *ring_info,
+		     u32 next_write_location)
+{
+	ring_info->ring_buffer->write_index = next_write_location;
+}
+
+/*
+ * hv_get_next_read_location()
+ *
+ * Get the next read location for the specified ring buffer
+ */
+static inline u32
+hv_get_next_read_location(struct hv_ring_buffer_info *ring_info)
+{
+	u32 next = ring_info->ring_buffer->read_index;
+
+	return next;
+}
+
+/*
+ * hv_get_next_readlocation_withoffset()
+ *
+ * Get the next read location + offset for the specified ring buffer.
+ * This allows the caller to skip
+ */
+static inline u32
+hv_get_next_readlocation_withoffset(struct hv_ring_buffer_info *ring_info,
+				 u32 offset)
+{
+	u32 next = ring_info->ring_buffer->read_index;
+
+	next += offset;
+	next %= ring_info->ring_datasize;
+
+	return next;
+}
+
+/*
+ *
+ * hv_set_next_read_location()
+ *
+ * Set the next read location for the specified ring buffer
+ *
+ */
+static inline void
+hv_set_next_read_location(struct hv_ring_buffer_info *ring_info,
+		    u32 next_read_location)
+{
+	ring_info->ring_buffer->read_index = next_read_location;
+}
+
+
+/*
+ *
+ * hv_get_ring_buffer()
+ *
+ * Get the start of the ring buffer
+ */
+static inline void *
+hv_get_ring_buffer(struct hv_ring_buffer_info *ring_info)
+{
+	return (void *)ring_info->ring_buffer->buffer;
+}
+
+
+/*
+ *
+ * hv_get_ring_buffersize()
+ *
+ * Get the size of the ring buffer
+ */
+static inline u32
+hv_get_ring_buffersize(struct hv_ring_buffer_info *ring_info)
+{
+	return ring_info->ring_datasize;
+}
+
+/*
+ *
+ * hv_get_ring_bufferindices()
+ *
+ * Get the read and write indices as u64 of the specified ring buffer
+ *
+ */
+static inline u64
+hv_get_ring_bufferindices(struct hv_ring_buffer_info *ring_info)
+{
+	return (u64)ring_info->ring_buffer->write_index << 32;
+}
+
+
+/*
+ *
+ * hv_dump_ring_info()
+ *
+ * Dump out to console the ring buffer info
+ *
+ */
+void hv_dump_ring_info(struct hv_ring_buffer_info *ring_info, char *prefix)
+{
+	u32 bytes_avail_towrite;
+	u32 bytes_avail_toread;
+
+	hv_get_ringbuffer_availbytes(ring_info,
+	&bytes_avail_toread,
+	&bytes_avail_towrite);
+
+	DPRINT(VMBUS,
+		DEBUG_RING_LVL,
+		"%s <<ringinfo %p buffer %p avail write %u "
+		"avail read %u read idx %u write idx %u>>",
+		prefix,
+		ring_info,
+		ring_info->ring_buffer->buffer,
+		bytes_avail_towrite,
+		bytes_avail_toread,
+		ring_info->ring_buffer->read_index,
+		ring_info->ring_buffer->write_index);
+}
+
+
+/*
+ *
+ * hv_copyfrom_ringbuffer()
+ *
+ * Helper routine to copy to source from ring buffer.
+ * Assume there is enough room. Handles wrap-around in src case only!!
+ *
+ */
+static u32 hv_copyfrom_ringbuffer(
+	struct hv_ring_buffer_info	*ring_info,
+	void				*dest,
+	u32				destlen,
+	u32				start_read_offset)
+{
+	void *ring_buffer = hv_get_ring_buffer(ring_info);
+	u32 ring_buffer_size = hv_get_ring_buffersize(ring_info);
+
+	u32 frag_len;
+
+	/* wrap-around detected at the src */
+	if (destlen > ring_buffer_size - start_read_offset) {
+		frag_len = ring_buffer_size - start_read_offset;
+
+		memcpy(dest, ring_buffer + start_read_offset, frag_len);
+		memcpy(dest + frag_len, ring_buffer, destlen - frag_len);
+	} else
+
+		memcpy(dest, ring_buffer + start_read_offset, destlen);
+
+
+	start_read_offset += destlen;
+	start_read_offset %= ring_buffer_size;
+
+	return start_read_offset;
+}
+
+
+/*
+ *
+ * hv_copyto_ringbuffer()
+ *
+ * Helper routine to copy from source to ring buffer.
+ * Assume there is enough room. Handles wrap-around in dest case only!!
+ *
+ */
+static u32 hv_copyto_ringbuffer(
+	struct hv_ring_buffer_info	*ring_info,
+	u32				start_write_offset,
+	void				*src,
+	u32				srclen)
+{
+	void *ring_buffer = hv_get_ring_buffer(ring_info);
+	u32 ring_buffer_size = hv_get_ring_buffersize(ring_info);
+	u32 frag_len;
+
+	/* wrap-around detected! */
+	if (srclen > ring_buffer_size - start_write_offset) {
+		frag_len = ring_buffer_size - start_write_offset;
+		memcpy(ring_buffer + start_write_offset, src, frag_len);
+		memcpy(ring_buffer, src + frag_len, srclen - frag_len);
+	} else
+		memcpy(ring_buffer + start_write_offset, src, srclen);
+
+	start_write_offset += srclen;
+	start_write_offset %= ring_buffer_size;
+
+	return start_write_offset;
+}
+
+/*
+ *
+ * hv_ringbuffer_get_debuginfo()
+ *
+ * Get various debug metrics for the specified ring buffer
+ *
+ */
+void hv_ringbuffer_get_debuginfo(struct hv_ring_buffer_info *ring_info,
+			    struct hv_ring_buffer_debug_info *debug_info)
+{
+	u32 bytes_avail_towrite;
+	u32 bytes_avail_toread;
+
+	if (ring_info->ring_buffer) {
+		hv_get_ringbuffer_availbytes(ring_info,
+					&bytes_avail_toread,
+					&bytes_avail_towrite);
+
+		debug_info->bytes_avail_toread = bytes_avail_toread;
+		debug_info->bytes_avail_towrite = bytes_avail_towrite;
+		debug_info->current_read_index =
+			ring_info->ring_buffer->read_index;
+		debug_info->current_write_index =
+			ring_info->ring_buffer->write_index;
+		debug_info->current_interrupt_mask =
+			ring_info->ring_buffer->interrupt_mask;
+	}
+}
+
+
+/*
+ *
+ * hv_get_ringbuffer_interrupt_mask()
+ *
+ * Get the interrupt mask for the specified ring buffer
+ *
+ */
+u32 hv_get_ringbuffer_interrupt_mask(struct hv_ring_buffer_info *rbi)
+{
+	return rbi->ring_buffer->interrupt_mask;
+}
+
+/*
+ *
+ * hv_ringbuffer_init()
+ *
+ *Initialize the ring buffer
+ *
+ */
+int hv_ringbuffer_init(struct hv_ring_buffer_info *ring_info,
+		   void *buffer, u32 buflen)
+{
+	if (sizeof(struct hv_ring_buffer) != PAGE_SIZE)
+		return -EINVAL;
+
+	memset(ring_info, 0, sizeof(struct hv_ring_buffer_info));
+
+	ring_info->ring_buffer = (struct hv_ring_buffer *)buffer;
+	ring_info->ring_buffer->read_index =
+		ring_info->ring_buffer->write_index = 0;
+
+	ring_info->ring_size = buflen;
+	ring_info->ring_datasize = buflen - sizeof(struct hv_ring_buffer);
+
+	spin_lock_init(&ring_info->ring_lock);
+
+	return 0;
+}
+
+/*
+ *
+ * hv_ringbuffer_cleanup()
+ *
+ * Cleanup the ring buffer
+ *
+ */
+void hv_ringbuffer_cleanup(struct hv_ring_buffer_info *ring_info)
+{
+}
+
+/*
+ *
+ * hv_ringbuffer_write()
+ *
+ * Write to the ring buffer
+ *
+ */
+int hv_ringbuffer_write(struct hv_ring_buffer_info *outring_info,
+		    struct scatterlist *sglist, u32 sgcount)
+{
+	int i = 0;
+	u32 bytes_avail_towrite;
+	u32 bytes_avail_toread;
+	u32 totalbytes_towrite = 0;
+
+	struct scatterlist *sg;
+	u32 next_write_location;
+	u64 prev_indices = 0;
+	unsigned long flags;
+
+	for_each_sg(sglist, sg, sgcount, i)
+	{
+		totalbytes_towrite += sg->length;
+	}
+
+	totalbytes_towrite += sizeof(u64);
+
+	spin_lock_irqsave(&outring_info->ring_lock, flags);
+
+	hv_get_ringbuffer_availbytes(outring_info,
+				&bytes_avail_toread,
+				&bytes_avail_towrite);
+
+
+	/* If there is only room for the packet, assume it is full. */
+	/* Otherwise, the next time around, we think the ring buffer */
+	/* is empty since the read index == write index */
+	if (bytes_avail_towrite <= totalbytes_towrite) {
+		spin_unlock_irqrestore(&outring_info->ring_lock, flags);
+		return -1;
+	}
+
+	/* Write to the ring buffer */
+	next_write_location = hv_get_next_write_location(outring_info);
+
+	for_each_sg(sglist, sg, sgcount, i)
+	{
+		next_write_location = hv_copyto_ringbuffer(outring_info,
+						     next_write_location,
+						     sg_virt(sg),
+						     sg->length);
+	}
+
+	/* Set previous packet start */
+	prev_indices = hv_get_ring_bufferindices(outring_info);
+
+	next_write_location = hv_copyto_ringbuffer(outring_info,
+					     next_write_location,
+					     &prev_indices,
+					     sizeof(u64));
+
+	/* Make sure we flush all writes before updating the writeIndex */
+	smp_wmb();
+
+	/* Now, update the write location */
+	hv_set_next_write_location(outring_info, next_write_location);
+
+
+	spin_unlock_irqrestore(&outring_info->ring_lock, flags);
+	return 0;
+}
+
+
+/*
+ *
+ * hv_ringbuffer_peek()
+ *
+ * Read without advancing the read index
+ *
+ */
+int hv_ringbuffer_peek(struct hv_ring_buffer_info *Inring_info,
+		   void *Buffer, u32 buflen)
+{
+	u32 bytes_avail_towrite;
+	u32 bytes_avail_toread;
+	u32 next_read_location = 0;
+	unsigned long flags;
+
+	spin_lock_irqsave(&Inring_info->ring_lock, flags);
+
+	hv_get_ringbuffer_availbytes(Inring_info,
+				&bytes_avail_toread,
+				&bytes_avail_towrite);
+
+	/* Make sure there is something to read */
+	if (bytes_avail_toread < buflen) {
+
+		spin_unlock_irqrestore(&Inring_info->ring_lock, flags);
+
+		return -1;
+	}
+
+	/* Convert to byte offset */
+	next_read_location = hv_get_next_read_location(Inring_info);
+
+	next_read_location = hv_copyfrom_ringbuffer(Inring_info,
+						Buffer,
+						buflen,
+						next_read_location);
+
+	spin_unlock_irqrestore(&Inring_info->ring_lock, flags);
+
+	return 0;
+}
+
+
+/*
+ *
+ * hv_ringbuffer_read()
+ *
+ * Read and advance the read index
+ *
+ */
+int hv_ringbuffer_read(struct hv_ring_buffer_info *inring_info, void *buffer,
+		   u32 buflen, u32 offset)
+{
+	u32 bytes_avail_towrite;
+	u32 bytes_avail_toread;
+	u32 next_read_location = 0;
+	u64 prev_indices = 0;
+	unsigned long flags;
+
+	if (buflen <= 0)
+		return -EINVAL;
+
+	spin_lock_irqsave(&inring_info->ring_lock, flags);
+
+	hv_get_ringbuffer_availbytes(inring_info,
+				&bytes_avail_toread,
+				&bytes_avail_towrite);
+
+	/* Make sure there is something to read */
+	if (bytes_avail_toread < buflen) {
+		spin_unlock_irqrestore(&inring_info->ring_lock, flags);
+
+		return -1;
+	}
+
+	next_read_location =
+		hv_get_next_readlocation_withoffset(inring_info, offset);
+
+	next_read_location = hv_copyfrom_ringbuffer(inring_info,
+						buffer,
+						buflen,
+						next_read_location);
+
+	next_read_location = hv_copyfrom_ringbuffer(inring_info,
+						&prev_indices,
+						sizeof(u64),
+						next_read_location);
+
+	/* Make sure all reads are done before we update the read index since */
+	/* the writer may start writing to the read area once the read index */
+	/*is updated */
+	smp_mb();
+
+	/* Update the read index */
+	hv_set_next_read_location(inring_info, next_read_location);
+
+	spin_unlock_irqrestore(&inring_info->ring_lock, flags);
+
+	return 0;
+}
diff --git a/drivers/staging/hv/rndis.h b/drivers/staging/hv/rndis.h
deleted file mode 100644
index 723e1f1..0000000
--- a/drivers/staging/hv/rndis.h
+++ /dev/null
@@ -1,652 +0,0 @@
-/*
- *
- * Copyright (c) 2009, Microsoft Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place - Suite 330, Boston, MA 02111-1307 USA.
- *
- * Authors:
- *   Haiyang Zhang <haiyangz@microsoft.com>
- *   Hank Janssen  <hjanssen@microsoft.com>
- *
- */
-
-#ifndef _RNDIS_H_
-#define _RNDIS_H_
-
-/*  Status codes */
-
-
-#ifndef STATUS_SUCCESS
-#define STATUS_SUCCESS				(0x00000000L)
-#endif
-
-#ifndef STATUS_UNSUCCESSFUL
-#define STATUS_UNSUCCESSFUL			(0xC0000001L)
-#endif
-
-#ifndef STATUS_PENDING
-#define STATUS_PENDING				(0x00000103L)
-#endif
-
-#ifndef STATUS_INSUFFICIENT_RESOURCES
-#define STATUS_INSUFFICIENT_RESOURCES		(0xC000009AL)
-#endif
-
-#ifndef STATUS_BUFFER_OVERFLOW
-#define STATUS_BUFFER_OVERFLOW			(0x80000005L)
-#endif
-
-#ifndef STATUS_NOT_SUPPORTED
-#define STATUS_NOT_SUPPORTED			(0xC00000BBL)
-#endif
-
-#define RNDIS_STATUS_SUCCESS			(STATUS_SUCCESS)
-#define RNDIS_STATUS_PENDING			(STATUS_PENDING)
-#define RNDIS_STATUS_NOT_RECOGNIZED		(0x00010001L)
-#define RNDIS_STATUS_NOT_COPIED			(0x00010002L)
-#define RNDIS_STATUS_NOT_ACCEPTED		(0x00010003L)
-#define RNDIS_STATUS_CALL_ACTIVE		(0x00010007L)
-
-#define RNDIS_STATUS_ONLINE			(0x40010003L)
-#define RNDIS_STATUS_RESET_START		(0x40010004L)
-#define RNDIS_STATUS_RESET_END			(0x40010005L)
-#define RNDIS_STATUS_RING_STATUS		(0x40010006L)
-#define RNDIS_STATUS_CLOSED			(0x40010007L)
-#define RNDIS_STATUS_WAN_LINE_UP		(0x40010008L)
-#define RNDIS_STATUS_WAN_LINE_DOWN		(0x40010009L)
-#define RNDIS_STATUS_WAN_FRAGMENT		(0x4001000AL)
-#define RNDIS_STATUS_MEDIA_CONNECT		(0x4001000BL)
-#define RNDIS_STATUS_MEDIA_DISCONNECT		(0x4001000CL)
-#define RNDIS_STATUS_HARDWARE_LINE_UP		(0x4001000DL)
-#define RNDIS_STATUS_HARDWARE_LINE_DOWN		(0x4001000EL)
-#define RNDIS_STATUS_INTERFACE_UP		(0x4001000FL)
-#define RNDIS_STATUS_INTERFACE_DOWN		(0x40010010L)
-#define RNDIS_STATUS_MEDIA_BUSY			(0x40010011L)
-#define RNDIS_STATUS_MEDIA_SPECIFIC_INDICATION	(0x40010012L)
-#define RNDIS_STATUS_WW_INDICATION		RDIA_SPECIFIC_INDICATION
-#define RNDIS_STATUS_LINK_SPEED_CHANGE		(0x40010013L)
-
-#define RNDIS_STATUS_NOT_RESETTABLE		(0x80010001L)
-#define RNDIS_STATUS_SOFT_ERRORS		(0x80010003L)
-#define RNDIS_STATUS_HARD_ERRORS		(0x80010004L)
-#define RNDIS_STATUS_BUFFER_OVERFLOW		(STATUS_BUFFER_OVERFLOW)
-
-#define RNDIS_STATUS_FAILURE			(STATUS_UNSUCCESSFUL)
-#define RNDIS_STATUS_RESOURCES			(STATUS_INSUFFICIENT_RESOURCES)
-#define RNDIS_STATUS_CLOSING			(0xC0010002L)
-#define RNDIS_STATUS_BAD_VERSION		(0xC0010004L)
-#define RNDIS_STATUS_BAD_CHARACTERISTICS	(0xC0010005L)
-#define RNDIS_STATUS_ADAPTER_NOT_FOUND		(0xC0010006L)
-#define RNDIS_STATUS_OPEN_FAILED		(0xC0010007L)
-#define RNDIS_STATUS_DEVICE_FAILED		(0xC0010008L)
-#define RNDIS_STATUS_MULTICAST_FULL		(0xC0010009L)
-#define RNDIS_STATUS_MULTICAST_EXISTS		(0xC001000AL)
-#define RNDIS_STATUS_MULTICAST_NOT_FOUND	(0xC001000BL)
-#define RNDIS_STATUS_REQUEST_ABORTED		(0xC001000CL)
-#define RNDIS_STATUS_RESET_IN_PROGRESS		(0xC001000DL)
-#define RNDIS_STATUS_CLOSING_INDICATING		(0xC001000EL)
-#define RNDIS_STATUS_NOT_SUPPORTED		(STATUS_NOT_SUPPORTED)
-#define RNDIS_STATUS_INVALID_PACKET		(0xC001000FL)
-#define RNDIS_STATUS_OPEN_LIST_FULL		(0xC0010010L)
-#define RNDIS_STATUS_ADAPTER_NOT_READY		(0xC0010011L)
-#define RNDIS_STATUS_ADAPTER_NOT_OPEN		(0xC0010012L)
-#define RNDIS_STATUS_NOT_INDICATING		(0xC0010013L)
-#define RNDIS_STATUS_INVALID_LENGTH		(0xC0010014L)
-#define RNDIS_STATUS_INVALID_DATA		(0xC0010015L)
-#define RNDIS_STATUS_BUFFER_TOO_SHORT		(0xC0010016L)
-#define RNDIS_STATUS_INVALID_OID		(0xC0010017L)
-#define RNDIS_STATUS_ADAPTER_REMOVED		(0xC0010018L)
-#define RNDIS_STATUS_UNSUPPORTED_MEDIA		(0xC0010019L)
-#define RNDIS_STATUS_GROUP_ADDRESS_IN_USE	(0xC001001AL)
-#define RNDIS_STATUS_FILE_NOT_FOUND		(0xC001001BL)
-#define RNDIS_STATUS_ERROR_READING_FILE		(0xC001001CL)
-#define RNDIS_STATUS_ALREADY_MAPPED		(0xC001001DL)
-#define RNDIS_STATUS_RESOURCE_CONFLICT		(0xC001001EL)
-#define RNDIS_STATUS_NO_CABLE			(0xC001001FL)
-
-#define RNDIS_STATUS_INVALID_SAP		(0xC0010020L)
-#define RNDIS_STATUS_SAP_IN_USE			(0xC0010021L)
-#define RNDIS_STATUS_INVALID_ADDRESS		(0xC0010022L)
-#define RNDIS_STATUS_VC_NOT_ACTIVATED		(0xC0010023L)
-#define RNDIS_STATUS_DEST_OUT_OF_ORDER		(0xC0010024L)
-#define RNDIS_STATUS_VC_NOT_AVAILABLE		(0xC0010025L)
-#define RNDIS_STATUS_CELLRATE_NOT_AVAILABLE	(0xC0010026L)
-#define RNDIS_STATUS_INCOMPATABLE_QOS		(0xC0010027L)
-#define RNDIS_STATUS_AAL_PARAMS_UNSUPPORTED	(0xC0010028L)
-#define RNDIS_STATUS_NO_ROUTE_TO_DESTINATION	(0xC0010029L)
-
-#define RNDIS_STATUS_TOKEN_RING_OPEN_ERROR	(0xC0011000L)
-
-/* Object Identifiers used by NdisRequest Query/Set Information */
-/* General Objects */
-#define RNDIS_OID_GEN_SUPPORTED_LIST		0x00010101
-#define RNDIS_OID_GEN_HARDWARE_STATUS		0x00010102
-#define RNDIS_OID_GEN_MEDIA_SUPPORTED		0x00010103
-#define RNDIS_OID_GEN_MEDIA_IN_USE		0x00010104
-#define RNDIS_OID_GEN_MAXIMUM_LOOKAHEAD		0x00010105
-#define RNDIS_OID_GEN_MAXIMUM_FRAME_SIZE	0x00010106
-#define RNDIS_OID_GEN_LINK_SPEED		0x00010107
-#define RNDIS_OID_GEN_TRANSMIT_BUFFER_SPACE	0x00010108
-#define RNDIS_OID_GEN_RECEIVE_BUFFER_SPACE	0x00010109
-#define RNDIS_OID_GEN_TRANSMIT_BLOCK_SIZE	0x0001010A
-#define RNDIS_OID_GEN_RECEIVE_BLOCK_SIZE	0x0001010B
-#define RNDIS_OID_GEN_VENDOR_ID			0x0001010C
-#define RNDIS_OID_GEN_VENDOR_DESCRIPTION	0x0001010D
-#define RNDIS_OID_GEN_CURRENT_PACKET_FILTER	0x0001010E
-#define RNDIS_OID_GEN_CURRENT_LOOKAHEAD		0x0001010F
-#define RNDIS_OID_GEN_DRIVER_VERSION		0x00010110
-#define RNDIS_OID_GEN_MAXIMUM_TOTAL_SIZE	0x00010111
-#define RNDIS_OID_GEN_PROTOCOL_OPTIONS		0x00010112
-#define RNDIS_OID_GEN_MAC_OPTIONS		0x00010113
-#define RNDIS_OID_GEN_MEDIA_CONNECT_STATUS	0x00010114
-#define RNDIS_OID_GEN_MAXIMUM_SEND_PACKETS	0x00010115
-#define RNDIS_OID_GEN_VENDOR_DRIVER_VERSION	0x00010116
-#define RNDIS_OID_GEN_NETWORK_LAYER_ADDRESSES	0x00010118
-#define RNDIS_OID_GEN_TRANSPORT_HEADER_OFFSET	0x00010119
-#define RNDIS_OID_GEN_MACHINE_NAME		0x0001021A
-#define RNDIS_OID_GEN_RNDIS_CONFIG_PARAMETER	0x0001021B
-
-#define RNDIS_OID_GEN_XMIT_OK			0x00020101
-#define RNDIS_OID_GEN_RCV_OK			0x00020102
-#define RNDIS_OID_GEN_XMIT_ERROR		0x00020103
-#define RNDIS_OID_GEN_RCV_ERROR			0x00020104
-#define RNDIS_OID_GEN_RCV_NO_BUFFER		0x00020105
-
-#define RNDIS_OID_GEN_DIRECTED_BYTES_XMIT	0x00020201
-#define RNDIS_OID_GEN_DIRECTED_FRAMES_XMIT	0x00020202
-#define RNDIS_OID_GEN_MULTICAST_BYTES_XMIT	0x00020203
-#define RNDIS_OID_GEN_MULTICAST_FRAMES_XMIT	0x00020204
-#define RNDIS_OID_GEN_BROADCAST_BYTES_XMIT	0x00020205
-#define RNDIS_OID_GEN_BROADCAST_FRAMES_XMIT	0x00020206
-#define RNDIS_OID_GEN_DIRECTED_BYTES_RCV	0x00020207
-#define RNDIS_OID_GEN_DIRECTED_FRAMES_RCV	0x00020208
-#define RNDIS_OID_GEN_MULTICAST_BYTES_RCV	0x00020209
-#define RNDIS_OID_GEN_MULTICAST_FRAMES_RCV	0x0002020A
-#define RNDIS_OID_GEN_BROADCAST_BYTES_RCV	0x0002020B
-#define RNDIS_OID_GEN_BROADCAST_FRAMES_RCV	0x0002020C
-
-#define RNDIS_OID_GEN_RCV_CRC_ERROR		0x0002020D
-#define RNDIS_OID_GEN_TRANSMIT_QUEUE_LENGTH	0x0002020E
-
-#define RNDIS_OID_GEN_GET_TIME_CAPS		0x0002020F
-#define RNDIS_OID_GEN_GET_NETCARD_TIME		0x00020210
-
-/* These are connection-oriented general OIDs. */
-/* These replace the above OIDs for connection-oriented media. */
-#define RNDIS_OID_GEN_CO_SUPPORTED_LIST		0x00010101
-#define RNDIS_OID_GEN_CO_HARDWARE_STATUS	0x00010102
-#define RNDIS_OID_GEN_CO_MEDIA_SUPPORTED	0x00010103
-#define RNDIS_OID_GEN_CO_MEDIA_IN_USE		0x00010104
-#define RNDIS_OID_GEN_CO_LINK_SPEED		0x00010105
-#define RNDIS_OID_GEN_CO_VENDOR_ID		0x00010106
-#define RNDIS_OID_GEN_CO_VENDOR_DESCRIPTION	0x00010107
-#define RNDIS_OID_GEN_CO_DRIVER_VERSION		0x00010108
-#define RNDIS_OID_GEN_CO_PROTOCOL_OPTIONS	0x00010109
-#define RNDIS_OID_GEN_CO_MAC_OPTIONS		0x0001010A
-#define RNDIS_OID_GEN_CO_MEDIA_CONNECT_STATUS	0x0001010B
-#define RNDIS_OID_GEN_CO_VENDOR_DRIVER_VERSION	0x0001010C
-#define RNDIS_OID_GEN_CO_MINIMUM_LINK_SPEED	0x0001010D
-
-#define RNDIS_OID_GEN_CO_GET_TIME_CAPS		0x00010201
-#define RNDIS_OID_GEN_CO_GET_NETCARD_TIME	0x00010202
-
-/* These are connection-oriented statistics OIDs. */
-#define RNDIS_OID_GEN_CO_XMIT_PDUS_OK		0x00020101
-#define RNDIS_OID_GEN_CO_RCV_PDUS_OK		0x00020102
-#define RNDIS_OID_GEN_CO_XMIT_PDUS_ERROR	0x00020103
-#define RNDIS_OID_GEN_CO_RCV_PDUS_ERROR		0x00020104
-#define RNDIS_OID_GEN_CO_RCV_PDUS_NO_BUFFER	0x00020105
-
-
-#define RNDIS_OID_GEN_CO_RCV_CRC_ERROR		0x00020201
-#define RNDIS_OID_GEN_CO_TRANSMIT_QUEUE_LENGTH	0x00020202
-#define RNDIS_OID_GEN_CO_BYTES_XMIT		0x00020203
-#define RNDIS_OID_GEN_CO_BYTES_RCV		0x00020204
-#define RNDIS_OID_GEN_CO_BYTES_XMIT_OUTSTANDING	0x00020205
-#define RNDIS_OID_GEN_CO_NETCARD_LOAD		0x00020206
-
-/* These are objects for Connection-oriented media call-managers. */
-#define RNDIS_OID_CO_ADD_PVC			0xFF000001
-#define RNDIS_OID_CO_DELETE_PVC			0xFF000002
-#define RNDIS_OID_CO_GET_CALL_INFORMATION	0xFF000003
-#define RNDIS_OID_CO_ADD_ADDRESS		0xFF000004
-#define RNDIS_OID_CO_DELETE_ADDRESS		0xFF000005
-#define RNDIS_OID_CO_GET_ADDRESSES		0xFF000006
-#define RNDIS_OID_CO_ADDRESS_CHANGE		0xFF000007
-#define RNDIS_OID_CO_SIGNALING_ENABLED		0xFF000008
-#define RNDIS_OID_CO_SIGNALING_DISABLED		0xFF000009
-
-/* 802.3 Objects (Ethernet) */
-#define RNDIS_OID_802_3_PERMANENT_ADDRESS	0x01010101
-#define RNDIS_OID_802_3_CURRENT_ADDRESS		0x01010102
-#define RNDIS_OID_802_3_MULTICAST_LIST		0x01010103
-#define RNDIS_OID_802_3_MAXIMUM_LIST_SIZE	0x01010104
-#define RNDIS_OID_802_3_MAC_OPTIONS		0x01010105
-
-#define NDIS_802_3_MAC_OPTION_PRIORITY		0x00000001
-
-#define RNDIS_OID_802_3_RCV_ERROR_ALIGNMENT	0x01020101
-#define RNDIS_OID_802_3_XMIT_ONE_COLLISION	0x01020102
-#define RNDIS_OID_802_3_XMIT_MORE_COLLISIONS	0x01020103
-
-#define RNDIS_OID_802_3_XMIT_DEFERRED		0x01020201
-#define RNDIS_OID_802_3_XMIT_MAX_COLLISIONS	0x01020202
-#define RNDIS_OID_802_3_RCV_OVERRUN		0x01020203
-#define RNDIS_OID_802_3_XMIT_UNDERRUN		0x01020204
-#define RNDIS_OID_802_3_XMIT_HEARTBEAT_FAILURE	0x01020205
-#define RNDIS_OID_802_3_XMIT_TIMES_CRS_LOST	0x01020206
-#define RNDIS_OID_802_3_XMIT_LATE_COLLISIONS	0x01020207
-
-/* Remote NDIS message types */
-#define REMOTE_NDIS_PACKET_MSG			0x00000001
-#define REMOTE_NDIS_INITIALIZE_MSG		0x00000002
-#define REMOTE_NDIS_HALT_MSG			0x00000003
-#define REMOTE_NDIS_QUERY_MSG			0x00000004
-#define REMOTE_NDIS_SET_MSG			0x00000005
-#define REMOTE_NDIS_RESET_MSG			0x00000006
-#define REMOTE_NDIS_INDICATE_STATUS_MSG		0x00000007
-#define REMOTE_NDIS_KEEPALIVE_MSG		0x00000008
-
-#define REMOTE_CONDIS_MP_CREATE_VC_MSG		0x00008001
-#define REMOTE_CONDIS_MP_DELETE_VC_MSG		0x00008002
-#define REMOTE_CONDIS_MP_ACTIVATE_VC_MSG	0x00008005
-#define REMOTE_CONDIS_MP_DEACTIVATE_VC_MSG	0x00008006
-#define REMOTE_CONDIS_INDICATE_STATUS_MSG	0x00008007
-
-/* Remote NDIS message completion types */
-#define REMOTE_NDIS_INITIALIZE_CMPLT		0x80000002
-#define REMOTE_NDIS_QUERY_CMPLT			0x80000004
-#define REMOTE_NDIS_SET_CMPLT			0x80000005
-#define REMOTE_NDIS_RESET_CMPLT			0x80000006
-#define REMOTE_NDIS_KEEPALIVE_CMPLT		0x80000008
-
-#define REMOTE_CONDIS_MP_CREATE_VC_CMPLT	0x80008001
-#define REMOTE_CONDIS_MP_DELETE_VC_CMPLT	0x80008002
-#define REMOTE_CONDIS_MP_ACTIVATE_VC_CMPLT	0x80008005
-#define REMOTE_CONDIS_MP_DEACTIVATE_VC_CMPLT	0x80008006
-
-/*
- * Reserved message type for private communication between lower-layer host
- * driver and remote device, if necessary.
- */
-#define REMOTE_NDIS_BUS_MSG			0xff000001
-
-/*  Defines for DeviceFlags in struct rndis_initialize_complete */
-#define RNDIS_DF_CONNECTIONLESS			0x00000001
-#define RNDIS_DF_CONNECTION_ORIENTED		0x00000002
-#define RNDIS_DF_RAW_DATA			0x00000004
-
-/*  Remote NDIS medium types. */
-#define RNdisMedium802_3			0x00000000
-#define RNdisMedium802_5			0x00000001
-#define RNdisMediumFddi				0x00000002
-#define RNdisMediumWan				0x00000003
-#define RNdisMediumLocalTalk			0x00000004
-#define RNdisMediumArcnetRaw			0x00000006
-#define RNdisMediumArcnet878_2			0x00000007
-#define RNdisMediumAtm				0x00000008
-#define RNdisMediumWirelessWan			0x00000009
-#define RNdisMediumIrda				0x0000000a
-#define RNdisMediumCoWan			0x0000000b
-/* Not a real medium, defined as an upper-bound */
-#define RNdisMediumMax				0x0000000d
-
-
-/* Remote NDIS medium connection states. */
-#define RNdisMediaStateConnected		0x00000000
-#define RNdisMediaStateDisconnected		0x00000001
-
-/*  Remote NDIS version numbers */
-#define RNDIS_MAJOR_VERSION			0x00000001
-#define RNDIS_MINOR_VERSION			0x00000000
-
-
-/* NdisInitialize message */
-struct rndis_initialize_request {
-	u32 RequestId;
-	u32 MajorVersion;
-	u32 MinorVersion;
-	u32 MaxTransferSize;
-};
-
-/* Response to NdisInitialize */
-struct rndis_initialize_complete {
-	u32 RequestId;
-	u32 Status;
-	u32 MajorVersion;
-	u32 MinorVersion;
-	u32 DeviceFlags;
-	u32 Medium;
-	u32 MaxPacketsPerMessage;
-	u32 MaxTransferSize;
-	u32 PacketAlignmentFactor;
-	u32 AFListOffset;
-	u32 AFListSize;
-};
-
-/* Call manager devices only: Information about an address family */
-/* supported by the device is appended to the response to NdisInitialize. */
-struct rndis_co_address_family {
-	u32 AddressFamily;
-	u32 MajorVersion;
-	u32 MinorVersion;
-};
-
-/* NdisHalt message */
-struct rndis_halt_request {
-	u32 RequestId;
-};
-
-/* NdisQueryRequest message */
-struct rndis_query_request {
-	u32 RequestId;
-	u32 Oid;
-	u32 InformationBufferLength;
-	u32 InformationBufferOffset;
-	u32 DeviceVcHandle;
-};
-
-/* Response to NdisQueryRequest */
-struct rndis_query_complete {
-	u32 RequestId;
-	u32 Status;
-	u32 InformationBufferLength;
-	u32 InformationBufferOffset;
-};
-
-/* NdisSetRequest message */
-struct rndis_set_request {
-	u32 RequestId;
-	u32 Oid;
-	u32 InformationBufferLength;
-	u32 InformationBufferOffset;
-	u32 DeviceVcHandle;
-};
-
-/* Response to NdisSetRequest */
-struct rndis_set_complete {
-	u32 RequestId;
-	u32 Status;
-};
-
-/* NdisReset message */
-struct rndis_reset_request {
-	u32 Reserved;
-};
-
-/* Response to NdisReset */
-struct rndis_reset_complete {
-	u32 Status;
-	u32 AddressingReset;
-};
-
-/* NdisMIndicateStatus message */
-struct rndis_indicate_status {
-	u32 Status;
-	u32 StatusBufferLength;
-	u32 StatusBufferOffset;
-};
-
-/* Diagnostic information passed as the status buffer in */
-/* struct rndis_indicate_status messages signifying error conditions. */
-struct rndis_diagnostic_info {
-	u32 DiagStatus;
-	u32 ErrorOffset;
-};
-
-/* NdisKeepAlive message */
-struct rndis_keepalive_request {
-	u32 RequestId;
-};
-
-/* Response to NdisKeepAlive */
-struct rndis_keepalive_complete {
-	u32 RequestId;
-	u32 Status;
-};
-
-/*
- * Data message. All Offset fields contain byte offsets from the beginning of
- * struct rndis_packet. All Length fields are in bytes.  VcHandle is set
- * to 0 for connectionless data, otherwise it contains the VC handle.
- */
-struct rndis_packet {
-	u32 DataOffset;
-	u32 DataLength;
-	u32 OOBDataOffset;
-	u32 OOBDataLength;
-	u32 NumOOBDataElements;
-	u32 PerPacketInfoOffset;
-	u32 PerPacketInfoLength;
-	u32 VcHandle;
-	u32 Reserved;
-};
-
-/* Optional Out of Band data associated with a Data message. */
-struct rndis_oobd {
-	u32 Size;
-	u32 Type;
-	u32 ClassInformationOffset;
-};
-
-/* Packet extension field contents associated with a Data message. */
-struct rndis_per_packet_info {
-	u32 Size;
-	u32 Type;
-	u32 PerPacketInformationOffset;
-};
-
-/* Format of Information buffer passed in a SetRequest for the OID */
-/* OID_GEN_RNDIS_CONFIG_PARAMETER. */
-struct rndis_config_parameter_info {
-	u32 ParameterNameOffset;
-	u32 ParameterNameLength;
-	u32 ParameterType;
-	u32 ParameterValueOffset;
-	u32 ParameterValueLength;
-};
-
-/* Values for ParameterType in struct rndis_config_parameter_info */
-#define RNDIS_CONFIG_PARAM_TYPE_INTEGER     0
-#define RNDIS_CONFIG_PARAM_TYPE_STRING      2
-
-/* CONDIS Miniport messages for connection oriented devices */
-/* that do not implement a call manager. */
-
-/* CoNdisMiniportCreateVc message */
-struct rcondis_mp_create_vc {
-	u32 RequestId;
-	u32 NdisVcHandle;
-};
-
-/* Response to CoNdisMiniportCreateVc */
-struct rcondis_mp_create_vc_complete {
-	u32 RequestId;
-	u32 DeviceVcHandle;
-	u32 Status;
-};
-
-/* CoNdisMiniportDeleteVc message */
-struct rcondis_mp_delete_vc {
-	u32 RequestId;
-	u32 DeviceVcHandle;
-};
-
-/* Response to CoNdisMiniportDeleteVc */
-struct rcondis_mp_delete_vc_complete {
-	u32 RequestId;
-	u32 Status;
-};
-
-/* CoNdisMiniportQueryRequest message */
-struct rcondis_mp_query_request {
-	u32 RequestId;
-	u32 RequestType;
-	u32 Oid;
-	u32 DeviceVcHandle;
-	u32 InformationBufferLength;
-	u32 InformationBufferOffset;
-};
-
-/* CoNdisMiniportSetRequest message */
-struct rcondis_mp_set_request {
-	u32 RequestId;
-	u32 RequestType;
-	u32 Oid;
-	u32 DeviceVcHandle;
-	u32 InformationBufferLength;
-	u32 InformationBufferOffset;
-};
-
-/* CoNdisIndicateStatus message */
-struct rcondis_indicate_status {
-	u32 NdisVcHandle;
-	u32 Status;
-	u32 StatusBufferLength;
-	u32 StatusBufferOffset;
-};
-
-/* CONDIS Call/VC parameters */
-struct rcondis_specific_parameters {
-	u32 ParameterType;
-	u32 ParameterLength;
-	u32 ParameterOffset;
-};
-
-struct rcondis_media_parameters {
-	u32 Flags;
-	u32 Reserved1;
-	u32 Reserved2;
-	struct rcondis_specific_parameters MediaSpecific;
-};
-
-struct rndis_flowspec {
-	u32 TokenRate;
-	u32 TokenBucketSize;
-	u32 PeakBandwidth;
-	u32 Latency;
-	u32 DelayVariation;
-	u32 ServiceType;
-	u32 MaxSduSize;
-	u32 MinimumPolicedSize;
-};
-
-struct rcondis_call_manager_parameters {
-	struct rndis_flowspec Transmit;
-	struct rndis_flowspec Receive;
-	struct rcondis_specific_parameters CallMgrSpecific;
-};
-
-/* CoNdisMiniportActivateVc message */
-struct rcondis_mp_activate_vc_request {
-	u32 RequestId;
-	u32 Flags;
-	u32 DeviceVcHandle;
-	u32 MediaParamsOffset;
-	u32 MediaParamsLength;
-	u32 CallMgrParamsOffset;
-	u32 CallMgrParamsLength;
-};
-
-/* Response to CoNdisMiniportActivateVc */
-struct rcondis_mp_activate_vc_complete {
-	u32 RequestId;
-	u32 Status;
-};
-
-/* CoNdisMiniportDeactivateVc message */
-struct rcondis_mp_deactivate_vc_request {
-	u32 RequestId;
-	u32 Flags;
-	u32 DeviceVcHandle;
-};
-
-/* Response to CoNdisMiniportDeactivateVc */
-struct rcondis_mp_deactivate_vc_complete {
-	u32 RequestId;
-	u32 Status;
-};
-
-
-/* union with all of the RNDIS messages */
-union rndis_message_container {
-	struct rndis_packet Packet;
-	struct rndis_initialize_request InitializeRequest;
-	struct rndis_halt_request HaltRequest;
-	struct rndis_query_request QueryRequest;
-	struct rndis_set_request SetRequest;
-	struct rndis_reset_request ResetRequest;
-	struct rndis_keepalive_request KeepaliveRequest;
-	struct rndis_indicate_status IndicateStatus;
-	struct rndis_initialize_complete InitializeComplete;
-	struct rndis_query_complete QueryComplete;
-	struct rndis_set_complete SetComplete;
-	struct rndis_reset_complete ResetComplete;
-	struct rndis_keepalive_complete KeepaliveComplete;
-	struct rcondis_mp_create_vc CoMiniportCreateVc;
-	struct rcondis_mp_delete_vc CoMiniportDeleteVc;
-	struct rcondis_indicate_status CoIndicateStatus;
-	struct rcondis_mp_activate_vc_request CoMiniportActivateVc;
-	struct rcondis_mp_deactivate_vc_request CoMiniportDeactivateVc;
-	struct rcondis_mp_create_vc_complete CoMiniportCreateVcComplete;
-	struct rcondis_mp_delete_vc_complete CoMiniportDeleteVcComplete;
-	struct rcondis_mp_activate_vc_complete CoMiniportActivateVcComplete;
-	struct rcondis_mp_deactivate_vc_complete CoMiniportDeactivateVcComplete;
-};
-
-/* Remote NDIS message format */
-struct rndis_message {
-	u32 NdisMessageType;
-
-	/* Total length of this message, from the beginning */
-	/* of the sruct rndis_message, in bytes. */
-	u32 MessageLength;
-
-	/* Actual message */
-	union rndis_message_container Message;
-};
-
-/* Handy macros */
-
-/* get the size of an RNDIS message. Pass in the message type, */
-/* struct rndis_set_request, struct rndis_packet for example */
-#define RNDIS_MESSAGE_SIZE(Message)				\
-	(sizeof(Message) + (sizeof(struct rndis_message) -	\
-	 sizeof(union rndis_message_container)))
-
-/* get pointer to info buffer with message pointer */
-#define MESSAGE_TO_INFO_BUFFER(Message)				\
-	(((unsigned char *)(Message)) + Message->InformationBufferOffset)
-
-/* get pointer to status buffer with message pointer */
-#define MESSAGE_TO_STATUS_BUFFER(Message)			\
-	(((unsigned char *)(Message)) + Message->StatusBufferOffset)
-
-/* get pointer to OOBD buffer with message pointer */
-#define MESSAGE_TO_OOBD_BUFFER(Message)				\
-	(((unsigned char *)(Message)) + Message->OOBDataOffset)
-
-/* get pointer to data buffer with message pointer */
-#define MESSAGE_TO_DATA_BUFFER(Message)				\
-	(((unsigned char *)(Message)) + Message->PerPacketInfoOffset)
-
-/* get pointer to contained message from NDIS_MESSAGE pointer */
-#define RNDIS_MESSAGE_PTR_TO_MESSAGE_PTR(RndisMessage)		\
-	((void *) &RndisMessage->Message)
-
-/* get pointer to contained message from NDIS_MESSAGE pointer */
-#define RNDIS_MESSAGE_RAW_PTR_TO_MESSAGE_PTR(RndisMessage)	\
-	((void *) RndisMessage)
-
-#endif /* _RNDIS_H_ */
diff --git a/drivers/staging/hv/rndis_filter.c b/drivers/staging/hv/rndis_filter.c
new file mode 100644
index 0000000..5674a13
--- /dev/null
+++ b/drivers/staging/hv/rndis_filter.c
@@ -0,0 +1,831 @@
+/*
+ * Copyright (c) 2009, Microsoft Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * Authors:
+ *   Haiyang Zhang <haiyangz@microsoft.com>
+ *   Hank Janssen  <hjanssen@microsoft.com>
+ */
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/wait.h>
+#include <linux/highmem.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/if_ether.h>
+#include <linux/netdevice.h>
+
+#include "hyperv.h"
+#include "hyperv_net.h"
+
+
+enum rndis_device_state {
+	RNDIS_DEV_UNINITIALIZED = 0,
+	RNDIS_DEV_INITIALIZING,
+	RNDIS_DEV_INITIALIZED,
+	RNDIS_DEV_DATAINITIALIZED,
+};
+
+struct rndis_device {
+	struct netvsc_device *net_dev;
+
+	enum rndis_device_state state;
+	u32 link_stat;
+	atomic_t new_req_id;
+
+	spinlock_t request_lock;
+	struct list_head req_list;
+
+	unsigned char hw_mac_adr[ETH_ALEN];
+};
+
+struct rndis_request {
+	struct list_head list_ent;
+	struct completion  wait_event;
+
+	/*
+	 * FIXME: We assumed a fixed size response here. If we do ever need to
+	 * handle a bigger response, we can either define a max response
+	 * message or add a response buffer variable above this field
+	 */
+	struct rndis_message response_msg;
+
+	/* Simplify allocation by having a netvsc packet inline */
+	struct hv_netvsc_packet	pkt;
+	struct hv_page_buffer buf;
+	/* FIXME: We assumed a fixed size request here. */
+	struct rndis_message request_msg;
+};
+
+static void rndis_filter_send_completion(void *ctx);
+
+static void rndis_filter_send_request_completion(void *ctx);
+
+
+
+static struct rndis_device *get_rndis_device(void)
+{
+	struct rndis_device *device;
+
+	device = kzalloc(sizeof(struct rndis_device), GFP_KERNEL);
+	if (!device)
+		return NULL;
+
+	spin_lock_init(&device->request_lock);
+
+	INIT_LIST_HEAD(&device->req_list);
+
+	device->state = RNDIS_DEV_UNINITIALIZED;
+
+	return device;
+}
+
+static struct rndis_request *get_rndis_request(struct rndis_device *dev,
+					     u32 msg_type,
+					     u32 msg_len)
+{
+	struct rndis_request *request;
+	struct rndis_message *rndis_msg;
+	struct rndis_set_request *set;
+	unsigned long flags;
+
+	request = kzalloc(sizeof(struct rndis_request), GFP_KERNEL);
+	if (!request)
+		return NULL;
+
+	init_completion(&request->wait_event);
+
+	rndis_msg = &request->request_msg;
+	rndis_msg->ndis_msg_type = msg_type;
+	rndis_msg->msg_len = msg_len;
+
+	/*
+	 * Set the request id. This field is always after the rndis header for
+	 * request/response packet types so we just used the SetRequest as a
+	 * template
+	 */
+	set = &rndis_msg->msg.set_req;
+	set->req_id = atomic_inc_return(&dev->new_req_id);
+
+	/* Add to the request list */
+	spin_lock_irqsave(&dev->request_lock, flags);
+	list_add_tail(&request->list_ent, &dev->req_list);
+	spin_unlock_irqrestore(&dev->request_lock, flags);
+
+	return request;
+}
+
+static void put_rndis_request(struct rndis_device *dev,
+			    struct rndis_request *req)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&dev->request_lock, flags);
+	list_del(&req->list_ent);
+	spin_unlock_irqrestore(&dev->request_lock, flags);
+
+	kfree(req);
+}
+
+static void dump_rndis_message(struct hv_device *hv_dev,
+			struct rndis_message *rndis_msg)
+{
+	struct net_device *netdev = dev_get_drvdata(&hv_dev->device);
+
+	switch (rndis_msg->ndis_msg_type) {
+	case REMOTE_NDIS_PACKET_MSG:
+		netdev_dbg(netdev, "REMOTE_NDIS_PACKET_MSG (len %u, "
+			   "data offset %u data len %u, # oob %u, "
+			   "oob offset %u, oob len %u, pkt offset %u, "
+			   "pkt len %u\n",
+			   rndis_msg->msg_len,
+			   rndis_msg->msg.pkt.data_offset,
+			   rndis_msg->msg.pkt.data_len,
+			   rndis_msg->msg.pkt.num_oob_data_elements,
+			   rndis_msg->msg.pkt.oob_data_offset,
+			   rndis_msg->msg.pkt.oob_data_len,
+			   rndis_msg->msg.pkt.per_pkt_info_offset,
+			   rndis_msg->msg.pkt.per_pkt_info_len);
+		break;
+
+	case REMOTE_NDIS_INITIALIZE_CMPLT:
+		netdev_dbg(netdev, "REMOTE_NDIS_INITIALIZE_CMPLT "
+			"(len %u, id 0x%x, status 0x%x, major %d, minor %d, "
+			"device flags %d, max xfer size 0x%x, max pkts %u, "
+			"pkt aligned %u)\n",
+			rndis_msg->msg_len,
+			rndis_msg->msg.init_complete.req_id,
+			rndis_msg->msg.init_complete.status,
+			rndis_msg->msg.init_complete.major_ver,
+			rndis_msg->msg.init_complete.minor_ver,
+			rndis_msg->msg.init_complete.dev_flags,
+			rndis_msg->msg.init_complete.max_xfer_size,
+			rndis_msg->msg.init_complete.
+			   max_pkt_per_msg,
+			rndis_msg->msg.init_complete.
+			   pkt_alignment_factor);
+		break;
+
+	case REMOTE_NDIS_QUERY_CMPLT:
+		netdev_dbg(netdev, "REMOTE_NDIS_QUERY_CMPLT "
+			"(len %u, id 0x%x, status 0x%x, buf len %u, "
+			"buf offset %u)\n",
+			rndis_msg->msg_len,
+			rndis_msg->msg.query_complete.req_id,
+			rndis_msg->msg.query_complete.status,
+			rndis_msg->msg.query_complete.
+			   info_buflen,
+			rndis_msg->msg.query_complete.
+			   info_buf_offset);
+		break;
+
+	case REMOTE_NDIS_SET_CMPLT:
+		netdev_dbg(netdev,
+			"REMOTE_NDIS_SET_CMPLT (len %u, id 0x%x, status 0x%x)\n",
+			rndis_msg->msg_len,
+			rndis_msg->msg.set_complete.req_id,
+			rndis_msg->msg.set_complete.status);
+		break;
+
+	case REMOTE_NDIS_INDICATE_STATUS_MSG:
+		netdev_dbg(netdev, "REMOTE_NDIS_INDICATE_STATUS_MSG "
+			"(len %u, status 0x%x, buf len %u, buf offset %u)\n",
+			rndis_msg->msg_len,
+			rndis_msg->msg.indicate_status.status,
+			rndis_msg->msg.indicate_status.status_buflen,
+			rndis_msg->msg.indicate_status.status_buf_offset);
+		break;
+
+	default:
+		netdev_dbg(netdev, "0x%x (len %u)\n",
+			rndis_msg->ndis_msg_type,
+			rndis_msg->msg_len);
+		break;
+	}
+}
+
+static int rndis_filter_send_request(struct rndis_device *dev,
+				  struct rndis_request *req)
+{
+	int ret;
+	struct hv_netvsc_packet *packet;
+
+	/* Setup the packet to send it */
+	packet = &req->pkt;
+
+	packet->is_data_pkt = false;
+	packet->total_data_buflen = req->request_msg.msg_len;
+	packet->page_buf_cnt = 1;
+
+	packet->page_buf[0].pfn = virt_to_phys(&req->request_msg) >>
+					PAGE_SHIFT;
+	packet->page_buf[0].len = req->request_msg.msg_len;
+	packet->page_buf[0].offset =
+		(unsigned long)&req->request_msg & (PAGE_SIZE - 1);
+
+	packet->completion.send.send_completion_ctx = req;/* packet; */
+	packet->completion.send.send_completion =
+		rndis_filter_send_request_completion;
+	packet->completion.send.send_completion_tid = (unsigned long)dev;
+
+	ret = netvsc_send(dev->net_dev->dev, packet);
+	return ret;
+}
+
+static void rndis_filter_receive_response(struct rndis_device *dev,
+				       struct rndis_message *resp)
+{
+	struct rndis_request *request = NULL;
+	bool found = false;
+	unsigned long flags;
+
+	spin_lock_irqsave(&dev->request_lock, flags);
+	list_for_each_entry(request, &dev->req_list, list_ent) {
+		/*
+		 * All request/response message contains RequestId as the 1st
+		 * field
+		 */
+		if (request->request_msg.msg.init_req.req_id
+		    == resp->msg.init_complete.req_id) {
+			found = true;
+			break;
+		}
+	}
+	spin_unlock_irqrestore(&dev->request_lock, flags);
+
+	if (found) {
+		if (resp->msg_len <= sizeof(struct rndis_message)) {
+			memcpy(&request->response_msg, resp,
+			       resp->msg_len);
+		} else {
+			dev_err(&dev->net_dev->dev->device,
+				"rndis response buffer overflow "
+				"detected (size %u max %zu)\n",
+				resp->msg_len,
+				sizeof(struct rndis_filter_packet));
+
+			if (resp->ndis_msg_type ==
+			    REMOTE_NDIS_RESET_CMPLT) {
+				/* does not have a request id field */
+				request->response_msg.msg.reset_complete.
+					status = STATUS_BUFFER_OVERFLOW;
+			} else {
+				request->response_msg.msg.
+				init_complete.status =
+					STATUS_BUFFER_OVERFLOW;
+			}
+		}
+
+		complete(&request->wait_event);
+	} else {
+		dev_err(&dev->net_dev->dev->device,
+			"no rndis request found for this response "
+			"(id 0x%x res type 0x%x)\n",
+			resp->msg.init_complete.req_id,
+			resp->ndis_msg_type);
+	}
+}
+
+static void rndis_filter_receive_indicate_status(struct rndis_device *dev,
+					     struct rndis_message *resp)
+{
+	struct rndis_indicate_status *indicate =
+			&resp->msg.indicate_status;
+
+	if (indicate->status == RNDIS_STATUS_MEDIA_CONNECT) {
+		netvsc_linkstatus_callback(
+			dev->net_dev->dev, 1);
+	} else if (indicate->status == RNDIS_STATUS_MEDIA_DISCONNECT) {
+		netvsc_linkstatus_callback(
+			dev->net_dev->dev, 0);
+	} else {
+		/*
+		 * TODO:
+		 */
+	}
+}
+
+static void rndis_filter_receive_data(struct rndis_device *dev,
+				   struct rndis_message *msg,
+				   struct hv_netvsc_packet *pkt)
+{
+	struct rndis_packet *rndis_pkt;
+	u32 data_offset;
+
+	rndis_pkt = &msg->msg.pkt;
+
+	/*
+	 * FIXME: Handle multiple rndis pkt msgs that maybe enclosed in this
+	 * netvsc packet (ie TotalDataBufferLength != MessageLength)
+	 */
+
+	/* Remove the rndis header and pass it back up the stack */
+	data_offset = RNDIS_HEADER_SIZE + rndis_pkt->data_offset;
+
+	pkt->total_data_buflen -= data_offset;
+	pkt->page_buf[0].offset += data_offset;
+	pkt->page_buf[0].len -= data_offset;
+
+	pkt->is_data_pkt = true;
+
+	netvsc_recv_callback(dev->net_dev->dev, pkt);
+}
+
+int rndis_filter_receive(struct hv_device *dev,
+				struct hv_netvsc_packet	*pkt)
+{
+	struct netvsc_device *net_dev = dev->ext;
+	struct rndis_device *rndis_dev;
+	struct rndis_message rndis_msg;
+	struct rndis_message *rndis_hdr;
+
+	if (!net_dev)
+		return -EINVAL;
+
+	/* Make sure the rndis device state is initialized */
+	if (!net_dev->extension) {
+		dev_err(&dev->device, "got rndis message but no rndis device - "
+			  "dropping this message!\n");
+		return -1;
+	}
+
+	rndis_dev = (struct rndis_device *)net_dev->extension;
+	if (rndis_dev->state == RNDIS_DEV_UNINITIALIZED) {
+		dev_err(&dev->device, "got rndis message but rndis device "
+			   "uninitialized...dropping this message!\n");
+		return -1;
+	}
+
+	rndis_hdr = (struct rndis_message *)kmap_atomic(
+			pfn_to_page(pkt->page_buf[0].pfn), KM_IRQ0);
+
+	rndis_hdr = (void *)((unsigned long)rndis_hdr +
+			pkt->page_buf[0].offset);
+
+	/* Make sure we got a valid rndis message */
+	if ((rndis_hdr->ndis_msg_type != REMOTE_NDIS_PACKET_MSG) &&
+	    (rndis_hdr->msg_len > sizeof(struct rndis_message))) {
+		dev_err(&dev->device, "incoming rndis message buffer overflow "
+			   "detected (got %u, max %zu)..marking it an error!\n",
+			   rndis_hdr->msg_len,
+			   sizeof(struct rndis_message));
+	}
+
+	memcpy(&rndis_msg, rndis_hdr,
+		(rndis_hdr->msg_len > sizeof(struct rndis_message)) ?
+			sizeof(struct rndis_message) :
+			rndis_hdr->msg_len);
+
+	kunmap_atomic(rndis_hdr - pkt->page_buf[0].offset, KM_IRQ0);
+
+	dump_rndis_message(dev, &rndis_msg);
+
+	switch (rndis_msg.ndis_msg_type) {
+	case REMOTE_NDIS_PACKET_MSG:
+		/* data msg */
+		rndis_filter_receive_data(rndis_dev, &rndis_msg, pkt);
+		break;
+
+	case REMOTE_NDIS_INITIALIZE_CMPLT:
+	case REMOTE_NDIS_QUERY_CMPLT:
+	case REMOTE_NDIS_SET_CMPLT:
+		/* completion msgs */
+		rndis_filter_receive_response(rndis_dev, &rndis_msg);
+		break;
+
+	case REMOTE_NDIS_INDICATE_STATUS_MSG:
+		/* notification msgs */
+		rndis_filter_receive_indicate_status(rndis_dev, &rndis_msg);
+		break;
+	default:
+		dev_err(&dev->device,
+			"unhandled rndis message (type %u len %u)\n",
+			   rndis_msg.ndis_msg_type,
+			   rndis_msg.msg_len);
+		break;
+	}
+
+	return 0;
+}
+
+static int rndis_filter_query_device(struct rndis_device *dev, u32 oid,
+				  void *result, u32 *result_size)
+{
+	struct rndis_request *request;
+	u32 inresult_size = *result_size;
+	struct rndis_query_request *query;
+	struct rndis_query_complete *query_complete;
+	int ret = 0;
+	int t;
+
+	if (!result)
+		return -EINVAL;
+
+	*result_size = 0;
+	request = get_rndis_request(dev, REMOTE_NDIS_QUERY_MSG,
+			RNDIS_MESSAGE_SIZE(struct rndis_query_request));
+	if (!request) {
+		ret = -1;
+		goto Cleanup;
+	}
+
+	/* Setup the rndis query */
+	query = &request->request_msg.msg.query_req;
+	query->oid = oid;
+	query->info_buf_offset = sizeof(struct rndis_query_request);
+	query->info_buflen = 0;
+	query->dev_vc_handle = 0;
+
+	ret = rndis_filter_send_request(dev, request);
+	if (ret != 0)
+		goto Cleanup;
+
+	t = wait_for_completion_timeout(&request->wait_event, HZ);
+	if (t == 0) {
+		ret = -ETIMEDOUT;
+		goto Cleanup;
+	}
+
+	/* Copy the response back */
+	query_complete = &request->response_msg.msg.query_complete;
+
+	if (query_complete->info_buflen > inresult_size) {
+		ret = -1;
+		goto Cleanup;
+	}
+
+	memcpy(result,
+	       (void *)((unsigned long)query_complete +
+			 query_complete->info_buf_offset),
+	       query_complete->info_buflen);
+
+	*result_size = query_complete->info_buflen;
+
+Cleanup:
+	if (request)
+		put_rndis_request(dev, request);
+
+	return ret;
+}
+
+static int rndis_filter_query_device_mac(struct rndis_device *dev)
+{
+	u32 size = ETH_ALEN;
+
+	return rndis_filter_query_device(dev,
+				      RNDIS_OID_802_3_PERMANENT_ADDRESS,
+				      dev->hw_mac_adr, &size);
+}
+
+static int rndis_filter_query_device_link_status(struct rndis_device *dev)
+{
+	u32 size = sizeof(u32);
+
+	return rndis_filter_query_device(dev,
+				      RNDIS_OID_GEN_MEDIA_CONNECT_STATUS,
+				      &dev->link_stat, &size);
+}
+
+static int rndis_filter_set_packet_filter(struct rndis_device *dev,
+				      u32 new_filter)
+{
+	struct rndis_request *request;
+	struct rndis_set_request *set;
+	struct rndis_set_complete *set_complete;
+	u32 status;
+	int ret, t;
+
+	request = get_rndis_request(dev, REMOTE_NDIS_SET_MSG,
+			RNDIS_MESSAGE_SIZE(struct rndis_set_request) +
+			sizeof(u32));
+	if (!request) {
+		ret = -1;
+		goto Cleanup;
+	}
+
+	/* Setup the rndis set */
+	set = &request->request_msg.msg.set_req;
+	set->oid = RNDIS_OID_GEN_CURRENT_PACKET_FILTER;
+	set->info_buflen = sizeof(u32);
+	set->info_buf_offset = sizeof(struct rndis_set_request);
+
+	memcpy((void *)(unsigned long)set + sizeof(struct rndis_set_request),
+	       &new_filter, sizeof(u32));
+
+	ret = rndis_filter_send_request(dev, request);
+	if (ret != 0)
+		goto Cleanup;
+
+	t = wait_for_completion_timeout(&request->wait_event, HZ);
+
+	if (t == 0) {
+		ret = -1;
+		dev_err(&dev->net_dev->dev->device,
+			"timeout before we got a set response...\n");
+		/*
+		 * We can't deallocate the request since we may still receive a
+		 * send completion for it.
+		 */
+		goto Exit;
+	} else {
+		if (ret > 0)
+			ret = 0;
+		set_complete = &request->response_msg.msg.set_complete;
+		status = set_complete->status;
+	}
+
+Cleanup:
+	if (request)
+		put_rndis_request(dev, request);
+Exit:
+	return ret;
+}
+
+
+static int rndis_filter_init_device(struct rndis_device *dev)
+{
+	struct rndis_request *request;
+	struct rndis_initialize_request *init;
+	struct rndis_initialize_complete *init_complete;
+	u32 status;
+	int ret, t;
+
+	request = get_rndis_request(dev, REMOTE_NDIS_INITIALIZE_MSG,
+			RNDIS_MESSAGE_SIZE(struct rndis_initialize_request));
+	if (!request) {
+		ret = -1;
+		goto Cleanup;
+	}
+
+	/* Setup the rndis set */
+	init = &request->request_msg.msg.init_req;
+	init->major_ver = RNDIS_MAJOR_VERSION;
+	init->minor_ver = RNDIS_MINOR_VERSION;
+	/* FIXME: Use 1536 - rounded ethernet frame size */
+	init->max_xfer_size = 2048;
+
+	dev->state = RNDIS_DEV_INITIALIZING;
+
+	ret = rndis_filter_send_request(dev, request);
+	if (ret != 0) {
+		dev->state = RNDIS_DEV_UNINITIALIZED;
+		goto Cleanup;
+	}
+
+
+	t = wait_for_completion_timeout(&request->wait_event, HZ);
+
+	if (t == 0) {
+		ret = -ETIMEDOUT;
+		goto Cleanup;
+	}
+
+	init_complete = &request->response_msg.msg.init_complete;
+	status = init_complete->status;
+	if (status == RNDIS_STATUS_SUCCESS) {
+		dev->state = RNDIS_DEV_INITIALIZED;
+		ret = 0;
+	} else {
+		dev->state = RNDIS_DEV_UNINITIALIZED;
+		ret = -1;
+	}
+
+Cleanup:
+	if (request)
+		put_rndis_request(dev, request);
+
+	return ret;
+}
+
+static void rndis_filter_halt_device(struct rndis_device *dev)
+{
+	struct rndis_request *request;
+	struct rndis_halt_request *halt;
+
+	/* Attempt to do a rndis device halt */
+	request = get_rndis_request(dev, REMOTE_NDIS_HALT_MSG,
+				RNDIS_MESSAGE_SIZE(struct rndis_halt_request));
+	if (!request)
+		goto Cleanup;
+
+	/* Setup the rndis set */
+	halt = &request->request_msg.msg.halt_req;
+	halt->req_id = atomic_inc_return(&dev->new_req_id);
+
+	/* Ignore return since this msg is optional. */
+	rndis_filter_send_request(dev, request);
+
+	dev->state = RNDIS_DEV_UNINITIALIZED;
+
+Cleanup:
+	if (request)
+		put_rndis_request(dev, request);
+	return;
+}
+
+static int rndis_filter_open_device(struct rndis_device *dev)
+{
+	int ret;
+
+	if (dev->state != RNDIS_DEV_INITIALIZED)
+		return 0;
+
+	ret = rndis_filter_set_packet_filter(dev,
+					 NDIS_PACKET_TYPE_BROADCAST |
+					 NDIS_PACKET_TYPE_ALL_MULTICAST |
+					 NDIS_PACKET_TYPE_DIRECTED);
+	if (ret == 0)
+		dev->state = RNDIS_DEV_DATAINITIALIZED;
+
+	return ret;
+}
+
+static int rndis_filter_close_device(struct rndis_device *dev)
+{
+	int ret;
+
+	if (dev->state != RNDIS_DEV_DATAINITIALIZED)
+		return 0;
+
+	ret = rndis_filter_set_packet_filter(dev, 0);
+	if (ret == 0)
+		dev->state = RNDIS_DEV_INITIALIZED;
+
+	return ret;
+}
+
+int rndis_filter_device_add(struct hv_device *dev,
+				  void *additional_info)
+{
+	int ret;
+	struct netvsc_device *netDevice;
+	struct rndis_device *rndisDevice;
+	struct netvsc_device_info *deviceInfo = additional_info;
+
+	rndisDevice = get_rndis_device();
+	if (!rndisDevice)
+		return -1;
+
+	/*
+	 * Let the inner driver handle this first to create the netvsc channel
+	 * NOTE! Once the channel is created, we may get a receive callback
+	 * (RndisFilterOnReceive()) before this call is completed
+	 */
+	ret = netvsc_device_add(dev, additional_info);
+	if (ret != 0) {
+		kfree(rndisDevice);
+		return ret;
+	}
+
+
+	/* Initialize the rndis device */
+	netDevice = dev->ext;
+
+	netDevice->extension = rndisDevice;
+	rndisDevice->net_dev = netDevice;
+
+	/* Send the rndis initialization message */
+	ret = rndis_filter_init_device(rndisDevice);
+	if (ret != 0) {
+		/*
+		 * TODO: If rndis init failed, we will need to shut down the
+		 * channel
+		 */
+	}
+
+	/* Get the mac address */
+	ret = rndis_filter_query_device_mac(rndisDevice);
+	if (ret != 0) {
+		/*
+		 * TODO: shutdown rndis device and the channel
+		 */
+	}
+
+	memcpy(deviceInfo->mac_adr, rndisDevice->hw_mac_adr, ETH_ALEN);
+
+	rndis_filter_query_device_link_status(rndisDevice);
+
+	deviceInfo->link_state = rndisDevice->link_stat;
+
+	dev_info(&dev->device, "Device MAC %pM link state %s",
+		 rndisDevice->hw_mac_adr,
+		 ((deviceInfo->link_state) ? ("down\n") : ("up\n")));
+
+	return ret;
+}
+
+void rndis_filter_device_remove(struct hv_device *dev)
+{
+	struct netvsc_device *net_dev = dev->ext;
+	struct rndis_device *rndis_dev = net_dev->extension;
+
+	/* Halt and release the rndis device */
+	rndis_filter_halt_device(rndis_dev);
+
+	kfree(rndis_dev);
+	net_dev->extension = NULL;
+
+	netvsc_device_remove(dev);
+}
+
+
+int rndis_filter_open(struct hv_device *dev)
+{
+	struct netvsc_device *netDevice = dev->ext;
+
+	if (!netDevice)
+		return -EINVAL;
+
+	return rndis_filter_open_device(netDevice->extension);
+}
+
+int rndis_filter_close(struct hv_device *dev)
+{
+	struct netvsc_device *netDevice = dev->ext;
+
+	if (!netDevice)
+		return -EINVAL;
+
+	return rndis_filter_close_device(netDevice->extension);
+}
+
+int rndis_filter_send(struct hv_device *dev,
+			     struct hv_netvsc_packet *pkt)
+{
+	int ret;
+	struct rndis_filter_packet *filterPacket;
+	struct rndis_message *rndisMessage;
+	struct rndis_packet *rndisPacket;
+	u32 rndisMessageSize;
+
+	/* Add the rndis header */
+	filterPacket = (struct rndis_filter_packet *)pkt->extension;
+
+	memset(filterPacket, 0, sizeof(struct rndis_filter_packet));
+
+	rndisMessage = &filterPacket->msg;
+	rndisMessageSize = RNDIS_MESSAGE_SIZE(struct rndis_packet);
+
+	rndisMessage->ndis_msg_type = REMOTE_NDIS_PACKET_MSG;
+	rndisMessage->msg_len = pkt->total_data_buflen +
+				      rndisMessageSize;
+
+	rndisPacket = &rndisMessage->msg.pkt;
+	rndisPacket->data_offset = sizeof(struct rndis_packet);
+	rndisPacket->data_len = pkt->total_data_buflen;
+
+	pkt->is_data_pkt = true;
+	pkt->page_buf[0].pfn = virt_to_phys(rndisMessage) >> PAGE_SHIFT;
+	pkt->page_buf[0].offset =
+			(unsigned long)rndisMessage & (PAGE_SIZE-1);
+	pkt->page_buf[0].len = rndisMessageSize;
+
+	/* Save the packet send completion and context */
+	filterPacket->completion = pkt->completion.send.send_completion;
+	filterPacket->completion_ctx =
+				pkt->completion.send.send_completion_ctx;
+
+	/* Use ours */
+	pkt->completion.send.send_completion = rndis_filter_send_completion;
+	pkt->completion.send.send_completion_ctx = filterPacket;
+
+	ret = netvsc_send(dev, pkt);
+	if (ret != 0) {
+		/*
+		 * Reset the completion to originals to allow retries from
+		 * above
+		 */
+		pkt->completion.send.send_completion =
+				filterPacket->completion;
+		pkt->completion.send.send_completion_ctx =
+				filterPacket->completion_ctx;
+	}
+
+	return ret;
+}
+
+static void rndis_filter_send_completion(void *ctx)
+{
+	struct rndis_filter_packet *filterPacket = ctx;
+
+	/* Pass it back to the original handler */
+	filterPacket->completion(filterPacket->completion_ctx);
+}
+
+
+static void rndis_filter_send_request_completion(void *ctx)
+{
+	/* Noop */
+}
diff --git a/drivers/staging/hv/storvsc.c b/drivers/staging/hv/storvsc.c
new file mode 100644
index 0000000..06cd327
--- /dev/null
+++ b/drivers/staging/hv/storvsc.c
@@ -0,0 +1,564 @@
+/*
+ * Copyright (c) 2009, Microsoft Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * Authors:
+ *   Haiyang Zhang <haiyangz@microsoft.com>
+ *   Hank Janssen  <hjanssen@microsoft.com>
+ *   K. Y. Srinivasan <kys@microsoft.com>
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/completion.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/delay.h>
+
+#include "hyperv.h"
+#include "hyperv_storage.h"
+
+
+static inline struct storvsc_device *alloc_stor_device(struct hv_device *device)
+{
+	struct storvsc_device *stor_device;
+
+	stor_device = kzalloc(sizeof(struct storvsc_device), GFP_KERNEL);
+	if (!stor_device)
+		return NULL;
+
+	/* Set to 2 to allow both inbound and outbound traffics */
+	/* (ie get_stor_device() and must_get_stor_device()) to proceed. */
+	atomic_cmpxchg(&stor_device->ref_count, 0, 2);
+
+	init_waitqueue_head(&stor_device->waiting_to_drain);
+	stor_device->device = device;
+	device->ext = stor_device;
+
+	return stor_device;
+}
+
+static inline void free_stor_device(struct storvsc_device *device)
+{
+	kfree(device);
+}
+
+/* Get the stordevice object iff exists and its refcount > 0 */
+static inline struct storvsc_device *must_get_stor_device(
+					struct hv_device *device)
+{
+	struct storvsc_device *stor_device;
+
+	stor_device = (struct storvsc_device *)device->ext;
+	if (stor_device && atomic_read(&stor_device->ref_count))
+		atomic_inc(&stor_device->ref_count);
+	else
+		stor_device = NULL;
+
+	return stor_device;
+}
+
+/* Drop ref count to 1 to effectively disable get_stor_device() */
+static inline struct storvsc_device *release_stor_device(
+					struct hv_device *device)
+{
+	struct storvsc_device *stor_device;
+
+	stor_device = (struct storvsc_device *)device->ext;
+
+	/* Busy wait until the ref drop to 2, then set it to 1 */
+	while (atomic_cmpxchg(&stor_device->ref_count, 2, 1) != 2)
+		udelay(100);
+
+	return stor_device;
+}
+
+/* Drop ref count to 0. No one can use stor_device object. */
+static inline struct storvsc_device *final_release_stor_device(
+			struct hv_device *device)
+{
+	struct storvsc_device *stor_device;
+
+	stor_device = (struct storvsc_device *)device->ext;
+
+	/* Busy wait until the ref drop to 1, then set it to 0 */
+	while (atomic_cmpxchg(&stor_device->ref_count, 1, 0) != 1)
+		udelay(100);
+
+	device->ext = NULL;
+	return stor_device;
+}
+
+static int storvsc_channel_init(struct hv_device *device)
+{
+	struct storvsc_device *stor_device;
+	struct hv_storvsc_request *request;
+	struct vstor_packet *vstor_packet;
+	int ret, t;
+
+	stor_device = get_stor_device(device);
+	if (!stor_device)
+		return -1;
+
+	request = &stor_device->init_request;
+	vstor_packet = &request->vstor_packet;
+
+	/*
+	 * Now, initiate the vsc/vsp initialization protocol on the open
+	 * channel
+	 */
+	memset(request, 0, sizeof(struct hv_storvsc_request));
+	init_completion(&request->wait_event);
+	vstor_packet->operation = VSTOR_OPERATION_BEGIN_INITIALIZATION;
+	vstor_packet->flags = REQUEST_COMPLETION_FLAG;
+
+	DPRINT_INFO(STORVSC, "BEGIN_INITIALIZATION_OPERATION...");
+
+	ret = vmbus_sendpacket(device->channel, vstor_packet,
+			       sizeof(struct vstor_packet),
+			       (unsigned long)request,
+			       VM_PKT_DATA_INBAND,
+			       VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
+	if (ret != 0)
+		goto cleanup;
+
+	t = wait_for_completion_timeout(&request->wait_event, HZ);
+	if (t == 0) {
+		ret = -ETIMEDOUT;
+		goto cleanup;
+	}
+
+	if (vstor_packet->operation != VSTOR_OPERATION_COMPLETE_IO ||
+	    vstor_packet->status != 0)
+		goto cleanup;
+
+	DPRINT_INFO(STORVSC, "QUERY_PROTOCOL_VERSION_OPERATION...");
+
+	/* reuse the packet for version range supported */
+	memset(vstor_packet, 0, sizeof(struct vstor_packet));
+	vstor_packet->operation = VSTOR_OPERATION_QUERY_PROTOCOL_VERSION;
+	vstor_packet->flags = REQUEST_COMPLETION_FLAG;
+
+	vstor_packet->version.major_minor = VMSTOR_PROTOCOL_VERSION_CURRENT;
+	FILL_VMSTOR_REVISION(vstor_packet->version.revision);
+
+	ret = vmbus_sendpacket(device->channel, vstor_packet,
+			       sizeof(struct vstor_packet),
+			       (unsigned long)request,
+			       VM_PKT_DATA_INBAND,
+			       VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
+	if (ret != 0)
+		goto cleanup;
+
+	t = wait_for_completion_timeout(&request->wait_event, HZ);
+	if (t == 0) {
+		ret = -ETIMEDOUT;
+		goto cleanup;
+	}
+
+	/* TODO: Check returned version */
+	if (vstor_packet->operation != VSTOR_OPERATION_COMPLETE_IO ||
+	    vstor_packet->status != 0)
+		goto cleanup;
+
+	/* Query channel properties */
+	DPRINT_INFO(STORVSC, "QUERY_PROPERTIES_OPERATION...");
+
+	memset(vstor_packet, 0, sizeof(struct vstor_packet));
+	vstor_packet->operation = VSTOR_OPERATION_QUERY_PROPERTIES;
+	vstor_packet->flags = REQUEST_COMPLETION_FLAG;
+	vstor_packet->storage_channel_properties.port_number =
+					stor_device->port_number;
+
+	ret = vmbus_sendpacket(device->channel, vstor_packet,
+			       sizeof(struct vstor_packet),
+			       (unsigned long)request,
+			       VM_PKT_DATA_INBAND,
+			       VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
+
+	if (ret != 0)
+		goto cleanup;
+
+	t = wait_for_completion_timeout(&request->wait_event, HZ);
+	if (t == 0) {
+		ret = -ETIMEDOUT;
+		goto cleanup;
+	}
+
+	/* TODO: Check returned version */
+	if (vstor_packet->operation != VSTOR_OPERATION_COMPLETE_IO ||
+	    vstor_packet->status != 0)
+		goto cleanup;
+
+	stor_device->path_id = vstor_packet->storage_channel_properties.path_id;
+	stor_device->target_id
+		= vstor_packet->storage_channel_properties.target_id;
+
+	DPRINT_INFO(STORVSC, "END_INITIALIZATION_OPERATION...");
+
+	memset(vstor_packet, 0, sizeof(struct vstor_packet));
+	vstor_packet->operation = VSTOR_OPERATION_END_INITIALIZATION;
+	vstor_packet->flags = REQUEST_COMPLETION_FLAG;
+
+	ret = vmbus_sendpacket(device->channel, vstor_packet,
+			       sizeof(struct vstor_packet),
+			       (unsigned long)request,
+			       VM_PKT_DATA_INBAND,
+			       VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
+
+	if (ret != 0)
+		goto cleanup;
+
+	t = wait_for_completion_timeout(&request->wait_event, HZ);
+	if (t == 0) {
+		ret = -ETIMEDOUT;
+		goto cleanup;
+	}
+
+	if (vstor_packet->operation != VSTOR_OPERATION_COMPLETE_IO ||
+	    vstor_packet->status != 0)
+		goto cleanup;
+
+	DPRINT_INFO(STORVSC, "**** storage channel up and running!! ****");
+
+cleanup:
+	put_stor_device(device);
+	return ret;
+}
+
+static void storvsc_on_io_completion(struct hv_device *device,
+				  struct vstor_packet *vstor_packet,
+				  struct hv_storvsc_request *request)
+{
+	struct storvsc_device *stor_device;
+	struct vstor_packet *stor_pkt;
+
+	stor_device = must_get_stor_device(device);
+	if (!stor_device)
+		return;
+
+	stor_pkt = &request->vstor_packet;
+
+
+	/* Copy over the status...etc */
+	stor_pkt->vm_srb.scsi_status = vstor_packet->vm_srb.scsi_status;
+	stor_pkt->vm_srb.srb_status = vstor_packet->vm_srb.srb_status;
+	stor_pkt->vm_srb.sense_info_length =
+	vstor_packet->vm_srb.sense_info_length;
+
+	if (vstor_packet->vm_srb.scsi_status != 0 ||
+		vstor_packet->vm_srb.srb_status != 1){
+		DPRINT_WARN(STORVSC,
+			    "cmd 0x%x scsi status 0x%x srb status 0x%x\n",
+			    stor_pkt->vm_srb.cdb[0],
+			    vstor_packet->vm_srb.scsi_status,
+			    vstor_packet->vm_srb.srb_status);
+	}
+
+	if ((vstor_packet->vm_srb.scsi_status & 0xFF) == 0x02) {
+		/* CHECK_CONDITION */
+		if (vstor_packet->vm_srb.srb_status & 0x80) {
+			/* autosense data available */
+			DPRINT_WARN(STORVSC, "storvsc pkt %p autosense data "
+				    "valid - len %d\n", request,
+				    vstor_packet->vm_srb.sense_info_length);
+
+			memcpy(request->sense_buffer,
+			       vstor_packet->vm_srb.sense_data,
+			       vstor_packet->vm_srb.sense_info_length);
+
+		}
+	}
+
+	stor_pkt->vm_srb.data_transfer_length =
+	vstor_packet->vm_srb.data_transfer_length;
+
+	request->on_io_completion(request);
+
+	if (atomic_dec_and_test(&stor_device->num_outstanding_req) &&
+		stor_device->drain_notify)
+		wake_up(&stor_device->waiting_to_drain);
+
+
+	put_stor_device(device);
+}
+
+static void storvsc_on_receive(struct hv_device *device,
+			     struct vstor_packet *vstor_packet,
+			     struct hv_storvsc_request *request)
+{
+	switch (vstor_packet->operation) {
+	case VSTOR_OPERATION_COMPLETE_IO:
+		storvsc_on_io_completion(device, vstor_packet, request);
+		break;
+	case VSTOR_OPERATION_REMOVE_DEVICE:
+		DPRINT_INFO(STORVSC, "REMOVE_DEVICE_OPERATION");
+		/* TODO: */
+		break;
+
+	default:
+		DPRINT_INFO(STORVSC, "Unknown operation received - %d",
+			    vstor_packet->operation);
+		break;
+	}
+}
+
+static void storvsc_on_channel_callback(void *context)
+{
+	struct hv_device *device = (struct hv_device *)context;
+	struct storvsc_device *stor_device;
+	u32 bytes_recvd;
+	u64 request_id;
+	unsigned char packet[ALIGN(sizeof(struct vstor_packet), 8)];
+	struct hv_storvsc_request *request;
+	int ret;
+
+
+	stor_device = must_get_stor_device(device);
+	if (!stor_device)
+		return;
+
+	do {
+		ret = vmbus_recvpacket(device->channel, packet,
+				       ALIGN(sizeof(struct vstor_packet), 8),
+				       &bytes_recvd, &request_id);
+		if (ret == 0 && bytes_recvd > 0) {
+
+			request = (struct hv_storvsc_request *)
+					(unsigned long)request_id;
+
+			if ((request == &stor_device->init_request) ||
+			    (request == &stor_device->reset_request)) {
+
+				memcpy(&request->vstor_packet, packet,
+				       sizeof(struct vstor_packet));
+				complete(&request->wait_event);
+			} else {
+				storvsc_on_receive(device,
+						(struct vstor_packet *)packet,
+						request);
+			}
+		} else {
+			break;
+		}
+	} while (1);
+
+	put_stor_device(device);
+	return;
+}
+
+static int storvsc_connect_to_vsp(struct hv_device *device, u32 ring_size)
+{
+	struct vmstorage_channel_properties props;
+	int ret;
+
+	memset(&props, 0, sizeof(struct vmstorage_channel_properties));
+
+	/* Open the channel */
+	ret = vmbus_open(device->channel,
+			 ring_size,
+			 ring_size,
+			 (void *)&props,
+			 sizeof(struct vmstorage_channel_properties),
+			 storvsc_on_channel_callback, device);
+
+	if (ret != 0)
+		return -1;
+
+	ret = storvsc_channel_init(device);
+
+	return ret;
+}
+
+int storvsc_dev_add(struct hv_device *device,
+					void *additional_info)
+{
+	struct storvsc_device *stor_device;
+	struct storvsc_device_info *device_info;
+	int ret = 0;
+
+	device_info = (struct storvsc_device_info *)additional_info;
+	stor_device = alloc_stor_device(device);
+	if (!stor_device) {
+		ret = -1;
+		goto cleanup;
+	}
+
+	/* Save the channel properties to our storvsc channel */
+
+	/* FIXME: */
+	/*
+	 * If we support more than 1 scsi channel, we need to set the
+	 * port number here to the scsi channel but how do we get the
+	 * scsi channel prior to the bus scan
+	 */
+
+	stor_device->port_number = device_info->port_number;
+	/* Send it back up */
+	ret = storvsc_connect_to_vsp(device, device_info->ring_buffer_size);
+
+	device_info->path_id = stor_device->path_id;
+	device_info->target_id = stor_device->target_id;
+
+cleanup:
+	return ret;
+}
+
+int storvsc_dev_remove(struct hv_device *device)
+{
+	struct storvsc_device *stor_device;
+
+	DPRINT_INFO(STORVSC, "disabling storage device (%p)...",
+		    device->ext);
+
+	stor_device = release_stor_device(device);
+
+	/*
+	 * At this point, all outbound traffic should be disable. We
+	 * only allow inbound traffic (responses) to proceed so that
+	 * outstanding requests can be completed.
+	 */
+
+	storvsc_wait_to_drain(stor_device);
+
+	stor_device = final_release_stor_device(device);
+
+	/* Close the channel */
+	vmbus_close(device->channel);
+
+	free_stor_device(stor_device);
+	return 0;
+}
+
+int storvsc_do_io(struct hv_device *device,
+			      struct hv_storvsc_request *request)
+{
+	struct storvsc_device *stor_device;
+	struct vstor_packet *vstor_packet;
+	int ret = 0;
+
+	vstor_packet = &request->vstor_packet;
+	stor_device = get_stor_device(device);
+
+	if (!stor_device)
+		return -2;
+
+
+	request->device  = device;
+
+
+	vstor_packet->flags |= REQUEST_COMPLETION_FLAG;
+
+	vstor_packet->vm_srb.length = sizeof(struct vmscsi_request);
+
+
+	vstor_packet->vm_srb.sense_info_length = SENSE_BUFFER_SIZE;
+
+
+	vstor_packet->vm_srb.data_transfer_length =
+	request->data_buffer.len;
+
+	vstor_packet->operation = VSTOR_OPERATION_EXECUTE_SRB;
+
+	if (request->data_buffer.len) {
+		ret = vmbus_sendpacket_multipagebuffer(device->channel,
+				&request->data_buffer,
+				vstor_packet,
+				sizeof(struct vstor_packet),
+				(unsigned long)request);
+	} else {
+		ret = vmbus_sendpacket(device->channel, vstor_packet,
+				       sizeof(struct vstor_packet),
+				       (unsigned long)request,
+				       VM_PKT_DATA_INBAND,
+				       VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
+	}
+
+	if (ret != 0)
+		return ret;
+
+	atomic_inc(&stor_device->num_outstanding_req);
+
+	put_stor_device(device);
+	return ret;
+}
+
+/*
+ * The channel properties uniquely specify how the device is to be
+ * presented to the guest. Map this information for use by the block
+ * driver. For Linux guests on Hyper-V, we emulate a scsi HBA in the guest
+ * (storvsc_drv) and so scsi devices in the guest  are handled by
+ * native upper level Linux drivers. Consequently, Hyper-V
+ * block driver, while being a generic block driver, presently does not
+ * deal with anything other than devices that would need to be presented
+ * to the guest as an IDE disk.
+ *
+ * This function maps the channel properties as embedded in the input
+ * parameter device_info onto information necessary to register the
+ * corresponding block device.
+ *
+ * Currently, there is no way to stop the emulation of the block device
+ * on the host side. And so, to prevent the native IDE drivers in Linux
+ * from taking over these devices (to be managedby Hyper-V block
+ * driver), we will take over if need be the major of the IDE controllers.
+ *
+ */
+
+int storvsc_get_major_info(struct storvsc_device_info *device_info,
+			    struct storvsc_major_info *major_info)
+{
+	static bool ide0_registered;
+	static bool ide1_registered;
+
+	/*
+	 * For now we only support IDE disks.
+	 */
+	major_info->devname = "ide";
+	major_info->diskname = "hd";
+
+	if (device_info->path_id) {
+		major_info->major = 22;
+		if (!ide1_registered) {
+			major_info->do_register = true;
+			ide1_registered = true;
+		} else
+			major_info->do_register = false;
+
+		if (device_info->target_id)
+			major_info->index = 3;
+		else
+			major_info->index = 2;
+
+		return 0;
+	} else {
+		major_info->major = 3;
+		if (!ide0_registered) {
+			major_info->do_register = true;
+			ide0_registered = true;
+		} else
+			major_info->do_register = false;
+
+		if (device_info->target_id)
+			major_info->index = 1;
+		else
+			major_info->index = 0;
+
+		return 0;
+	}
+
+	return -ENODEV;
+}
+
diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c
index f35da51..2c6d2f2 100644
--- a/drivers/staging/hv/storvsc_drv.c
+++ b/drivers/staging/hv/storvsc_drv.c
@@ -17,12 +17,14 @@
  * Authors:
  *   Haiyang Zhang <haiyangz@microsoft.com>
  *   Hank Janssen  <hjanssen@microsoft.com>
+ *   K. Y. Srinivasan <kys@microsoft.com>
  */
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/device.h>
 #include <linux/blkdev.h>
+#include <linux/dmi.h>
 #include <scsi/scsi.h>
 #include <scsi/scsi_cmnd.h>
 #include <scsi/scsi_host.h>
@@ -31,18 +33,27 @@
 #include <scsi/scsi_eh.h>
 #include <scsi/scsi_devinfo.h>
 #include <scsi/scsi_dbg.h>
-#include "osd.h"
-#include "logging.h"
-#include "VersionInfo.h"
-#include "vmbus.h"
-#include "StorVscApi.h"
 
+#include "hyperv.h"
+#include "hyperv_storage.h"
 
-struct host_device_context {
-	/* must be 1st field
-	 * FIXME this is a bug */
-	/* point back to our device context */
-	struct vm_device *device_ctx;
+static int storvsc_ringbuffer_size = STORVSC_RING_BUFFER_SIZE;
+
+module_param(storvsc_ringbuffer_size, int, S_IRUGO);
+MODULE_PARM_DESC(storvsc_ringbuffer_size, "Ring buffer size (bytes)");
+
+static const char *driver_name = "storvsc";
+
+/* {ba6163d9-04a1-4d29-b605-72e2ffb1dc7f} */
+static const struct hv_guid stor_vsci_device_type = {
+	.data = {
+		0xd9, 0x63, 0x61, 0xba, 0xa1, 0x04, 0x29, 0x4d,
+		0xb6, 0x05, 0x72, 0xe2, 0xff, 0xb1, 0xdc, 0x7f
+	}
+};
+
+struct hv_host_device {
+	struct hv_device *dev;
 	struct kmem_cache *request_pool;
 	unsigned int port;
 	unsigned char path;
@@ -57,347 +68,53 @@
 	struct scatterlist *bounce_sgl;
 
 	struct hv_storvsc_request request;
-	/* !!!DO NOT ADD ANYTHING BELOW HERE!!! */
-	/* The extension buffer falls right here and is pointed to by
-	 * request.Extension;
-	 * Which sounds like a very bad design... */
 };
 
-struct storvsc_driver_context {
-	/* !! These must be the first 2 fields !! */
-	/* FIXME this is a bug... */
-	struct driver_context drv_ctx;
-	struct storvsc_driver_object drv_obj;
-};
 
-/* Static decl */
-static int storvsc_probe(struct device *dev);
-static int storvsc_queuecommand(struct scsi_cmnd *scmnd,
-				void (*done)(struct scsi_cmnd *));
-static int storvsc_device_alloc(struct scsi_device *);
-static int storvsc_device_configure(struct scsi_device *);
-static int storvsc_host_reset_handler(struct scsi_cmnd *scmnd);
-static int storvsc_remove(struct device *dev);
+static int storvsc_device_alloc(struct scsi_device *sdevice)
+{
+	/*
+	 * This enables luns to be located sparsely. Otherwise, we may not
+	 * discovered them.
+	 */
+	sdevice->sdev_bflags |= BLIST_SPARSELUN | BLIST_LARGELUN;
+	return 0;
+}
 
-static struct scatterlist *create_bounce_buffer(struct scatterlist *sgl,
-						unsigned int sg_count,
-						unsigned int len);
+static int storvsc_merge_bvec(struct request_queue *q,
+			      struct bvec_merge_data *bmd, struct bio_vec *bvec)
+{
+	/* checking done by caller. */
+	return bvec->bv_len;
+}
+
+static int storvsc_device_configure(struct scsi_device *sdevice)
+{
+	scsi_adjust_queue_depth(sdevice, MSG_SIMPLE_TAG,
+				STORVSC_MAX_IO_REQUESTS);
+
+	blk_queue_max_segment_size(sdevice->request_queue, PAGE_SIZE);
+
+	blk_queue_merge_bvec(sdevice->request_queue, storvsc_merge_bvec);
+
+	blk_queue_bounce_limit(sdevice->request_queue, BLK_BOUNCE_ANY);
+
+	return 0;
+}
+
 static void destroy_bounce_buffer(struct scatterlist *sgl,
-				  unsigned int sg_count);
-static int do_bounce_buffer(struct scatterlist *sgl, unsigned int sg_count);
-static unsigned int copy_from_bounce_buffer(struct scatterlist *orig_sgl,
-					    struct scatterlist *bounce_sgl,
-					    unsigned int orig_sgl_count);
-static unsigned int copy_to_bounce_buffer(struct scatterlist *orig_sgl,
-					  struct scatterlist *bounce_sgl,
-					  unsigned int orig_sgl_count);
-
-static int storvsc_get_chs(struct scsi_device *sdev, struct block_device *bdev,
-			   sector_t capacity, int *info);
-
-
-static int storvsc_ringbuffer_size = STORVSC_RING_BUFFER_SIZE;
-module_param(storvsc_ringbuffer_size, int, S_IRUGO);
-MODULE_PARM_DESC(storvsc_ringbuffer_size, "Ring buffer size (bytes)");
-
-/* The one and only one */
-static struct storvsc_driver_context g_storvsc_drv;
-
-/* Scsi driver */
-static struct scsi_host_template scsi_driver = {
-	.module	=		THIS_MODULE,
-	.name =			"storvsc_host_t",
-	.bios_param =		storvsc_get_chs,
-	.queuecommand =		storvsc_queuecommand,
-	.eh_host_reset_handler =	storvsc_host_reset_handler,
-	.slave_alloc =		storvsc_device_alloc,
-	.slave_configure =	storvsc_device_configure,
-	.cmd_per_lun =		1,
-	/* 64 max_queue * 1 target */
-	.can_queue =		STORVSC_MAX_IO_REQUESTS*STORVSC_MAX_TARGETS,
-	.this_id =		-1,
-	/* no use setting to 0 since ll_blk_rw reset it to 1 */
-	/* currently 32 */
-	.sg_tablesize =		MAX_MULTIPAGE_BUFFER_COUNT,
-	/*
-	 * ENABLE_CLUSTERING allows mutiple physically contig bio_vecs to merge
-	 * into 1 sg element. If set, we must limit the max_segment_size to
-	 * PAGE_SIZE, otherwise we may get 1 sg element that represents
-	 * multiple
-	 */
-	/* physically contig pfns (ie sg[x].length > PAGE_SIZE). */
-	.use_clustering =	ENABLE_CLUSTERING,
-	/* Make sure we dont get a sg segment crosses a page boundary */
-	.dma_boundary =		PAGE_SIZE-1,
-};
-
-
-/*
- * storvsc_drv_init - StorVsc driver initialization.
- */
-static int storvsc_drv_init(int (*drv_init)(struct hv_driver *drv))
+				  unsigned int sg_count)
 {
-	int ret;
-	struct storvsc_driver_object *storvsc_drv_obj = &g_storvsc_drv.drv_obj;
-	struct driver_context *drv_ctx = &g_storvsc_drv.drv_ctx;
+	int i;
+	struct page *page_buf;
 
-	vmbus_get_interface(&storvsc_drv_obj->Base.VmbusChannelInterface);
-
-	storvsc_drv_obj->RingBufferSize = storvsc_ringbuffer_size;
-
-	/* Callback to client driver to complete the initialization */
-	drv_init(&storvsc_drv_obj->Base);
-
-	DPRINT_INFO(STORVSC_DRV,
-		    "request extension size %u, max outstanding reqs %u",
-		    storvsc_drv_obj->RequestExtSize,
-		    storvsc_drv_obj->MaxOutstandingRequestsPerChannel);
-
-	if (storvsc_drv_obj->MaxOutstandingRequestsPerChannel <
-	    STORVSC_MAX_IO_REQUESTS) {
-		DPRINT_ERR(STORVSC_DRV,
-			   "The number of outstanding io requests (%d) "
-			   "is larger than that supported (%d) internally.",
-			   STORVSC_MAX_IO_REQUESTS,
-			   storvsc_drv_obj->MaxOutstandingRequestsPerChannel);
-		return -1;
+	for (i = 0; i < sg_count; i++) {
+		page_buf = sg_page((&sgl[i]));
+		if (page_buf != NULL)
+			__free_page(page_buf);
 	}
 
-	drv_ctx->driver.name = storvsc_drv_obj->Base.name;
-	memcpy(&drv_ctx->class_id, &storvsc_drv_obj->Base.deviceType,
-	       sizeof(struct hv_guid));
-
-	drv_ctx->probe = storvsc_probe;
-	drv_ctx->remove = storvsc_remove;
-
-	/* The driver belongs to vmbus */
-	ret = vmbus_child_driver_register(drv_ctx);
-
-	return ret;
-}
-
-static int storvsc_drv_exit_cb(struct device *dev, void *data)
-{
-	struct device **curr = (struct device **)data;
-	*curr = dev;
-	return 1; /* stop iterating */
-}
-
-static void storvsc_drv_exit(void)
-{
-	struct storvsc_driver_object *storvsc_drv_obj = &g_storvsc_drv.drv_obj;
-	struct driver_context *drv_ctx = &g_storvsc_drv.drv_ctx;
-	struct device *current_dev = NULL;
-	int ret;
-
-	while (1) {
-		current_dev = NULL;
-
-		/* Get the device */
-		ret = driver_for_each_device(&drv_ctx->driver, NULL,
-					     (void *) &current_dev,
-					     storvsc_drv_exit_cb);
-
-		if (ret)
-			DPRINT_WARN(STORVSC_DRV,
-				    "driver_for_each_device returned %d", ret);
-
-		if (current_dev == NULL)
-			break;
-
-		/* Initiate removal from the top-down */
-		device_unregister(current_dev);
-	}
-
-	if (storvsc_drv_obj->Base.OnCleanup)
-		storvsc_drv_obj->Base.OnCleanup(&storvsc_drv_obj->Base);
-
-	vmbus_child_driver_unregister(drv_ctx);
-	return;
-}
-
-/*
- * storvsc_probe - Add a new device for this driver
- */
-static int storvsc_probe(struct device *device)
-{
-	int ret;
-	struct driver_context *driver_ctx =
-				driver_to_driver_context(device->driver);
-	struct storvsc_driver_context *storvsc_drv_ctx =
-				(struct storvsc_driver_context *)driver_ctx;
-	struct storvsc_driver_object *storvsc_drv_obj =
-				&storvsc_drv_ctx->drv_obj;
-	struct vm_device *device_ctx = device_to_vm_device(device);
-	struct hv_device *device_obj = &device_ctx->device_obj;
-	struct Scsi_Host *host;
-	struct host_device_context *host_device_ctx;
-	struct storvsc_device_info device_info;
-
-	if (!storvsc_drv_obj->Base.OnDeviceAdd)
-		return -1;
-
-	host = scsi_host_alloc(&scsi_driver,
-			       sizeof(struct host_device_context));
-	if (!host) {
-		DPRINT_ERR(STORVSC_DRV, "unable to allocate scsi host object");
-		return -ENOMEM;
-	}
-
-	dev_set_drvdata(device, host);
-
-	host_device_ctx = (struct host_device_context *)host->hostdata;
-	memset(host_device_ctx, 0, sizeof(struct host_device_context));
-
-	host_device_ctx->port = host->host_no;
-	host_device_ctx->device_ctx = device_ctx;
-
-	host_device_ctx->request_pool =
-				kmem_cache_create(dev_name(&device_ctx->device),
-					sizeof(struct storvsc_cmd_request) +
-					storvsc_drv_obj->RequestExtSize, 0,
-					SLAB_HWCACHE_ALIGN, NULL);
-
-	if (!host_device_ctx->request_pool) {
-		scsi_host_put(host);
-		return -ENOMEM;
-	}
-
-	device_info.PortNumber = host->host_no;
-	/* Call to the vsc driver to add the device */
-	ret = storvsc_drv_obj->Base.OnDeviceAdd(device_obj,
-						(void *)&device_info);
-	if (ret != 0) {
-		DPRINT_ERR(STORVSC_DRV, "unable to add scsi vsc device");
-		kmem_cache_destroy(host_device_ctx->request_pool);
-		scsi_host_put(host);
-		return -1;
-	}
-
-	/* host_device_ctx->port = device_info.PortNumber; */
-	host_device_ctx->path = device_info.PathId;
-	host_device_ctx->target = device_info.TargetId;
-
-	/* max # of devices per target */
-	host->max_lun = STORVSC_MAX_LUNS_PER_TARGET;
-	/* max # of targets per channel */
-	host->max_id = STORVSC_MAX_TARGETS;
-	/* max # of channels */
-	host->max_channel = STORVSC_MAX_CHANNELS - 1;
-
-	/* Register the HBA and start the scsi bus scan */
-	ret = scsi_add_host(host, device);
-	if (ret != 0) {
-		DPRINT_ERR(STORVSC_DRV, "unable to add scsi host device");
-
-		storvsc_drv_obj->Base.OnDeviceRemove(device_obj);
-
-		kmem_cache_destroy(host_device_ctx->request_pool);
-		scsi_host_put(host);
-		return -1;
-	}
-
-	scsi_scan_host(host);
-	return ret;
-}
-
-/*
- * storvsc_remove - Callback when our device is removed
- */
-static int storvsc_remove(struct device *device)
-{
-	int ret;
-	struct driver_context *driver_ctx =
-			driver_to_driver_context(device->driver);
-	struct storvsc_driver_context *storvsc_drv_ctx =
-			(struct storvsc_driver_context *)driver_ctx;
-	struct storvsc_driver_object *storvsc_drv_obj =
-			&storvsc_drv_ctx->drv_obj;
-	struct vm_device *device_ctx = device_to_vm_device(device);
-	struct hv_device *device_obj = &device_ctx->device_obj;
-	struct Scsi_Host *host = dev_get_drvdata(device);
-	struct host_device_context *host_device_ctx =
-			(struct host_device_context *)host->hostdata;
-
-
-	if (!storvsc_drv_obj->Base.OnDeviceRemove)
-		return -1;
-
-	/*
-	 * Call to the vsc driver to let it know that the device is being
-	 * removed
-	 */
-	ret = storvsc_drv_obj->Base.OnDeviceRemove(device_obj);
-	if (ret != 0) {
-		/* TODO: */
-		DPRINT_ERR(STORVSC, "unable to remove vsc device (ret %d)",
-			   ret);
-	}
-
-	if (host_device_ctx->request_pool) {
-		kmem_cache_destroy(host_device_ctx->request_pool);
-		host_device_ctx->request_pool = NULL;
-	}
-
-	DPRINT_INFO(STORVSC, "removing host adapter (%p)...", host);
-	scsi_remove_host(host);
-
-	DPRINT_INFO(STORVSC, "releasing host adapter (%p)...", host);
-	scsi_host_put(host);
-	return ret;
-}
-
-/*
- * storvsc_commmand_completion - Command completion processing
- */
-static void storvsc_commmand_completion(struct hv_storvsc_request *request)
-{
-	struct storvsc_cmd_request *cmd_request =
-		(struct storvsc_cmd_request *)request->Context;
-	struct scsi_cmnd *scmnd = cmd_request->cmd;
-	struct host_device_context *host_device_ctx =
-		(struct host_device_context *)scmnd->device->host->hostdata;
-	void (*scsi_done_fn)(struct scsi_cmnd *);
-	struct scsi_sense_hdr sense_hdr;
-
-	/* ASSERT(request == &cmd_request->request); */
-	/* ASSERT(scmnd); */
-	/* ASSERT((unsigned long)scmnd->host_scribble == */
-	/*        (unsigned long)cmd_request); */
-	/* ASSERT(scmnd->scsi_done); */
-
-	if (cmd_request->bounce_sgl_count) {
-		/* using bounce buffer */
-		/* printk("copy_from_bounce_buffer\n"); */
-
-		/* FIXME: We can optimize on writes by just skipping this */
-		copy_from_bounce_buffer(scsi_sglist(scmnd),
-					cmd_request->bounce_sgl,
-					scsi_sg_count(scmnd));
-		destroy_bounce_buffer(cmd_request->bounce_sgl,
-				      cmd_request->bounce_sgl_count);
-	}
-
-	scmnd->result = request->Status;
-
-	if (scmnd->result) {
-		if (scsi_normalize_sense(scmnd->sense_buffer,
-					 request->SenseBufferSize, &sense_hdr))
-			scsi_print_sense_hdr("storvsc", &sense_hdr);
-	}
-
-	/* ASSERT(request->BytesXfer <= request->DataBuffer.Length); */
-	scsi_set_resid(scmnd, request->DataBuffer.Length - request->BytesXfer);
-
-	scsi_done_fn = scmnd->scsi_done;
-
-	scmnd->host_scribble = NULL;
-	scmnd->scsi_done = NULL;
-
-	/* !!DO NOT MODIFY the scmnd after this call */
-	scsi_done_fn(scmnd);
-
-	kmem_cache_free(host_device_ctx->request_pool, cmd_request);
+	kfree(sgl);
 }
 
 static int do_bounce_buffer(struct scatterlist *sgl, unsigned int sg_count)
@@ -436,7 +153,7 @@
 	struct scatterlist *bounce_sgl;
 	struct page *page_buf;
 
-	num_pages = ALIGN_UP(len, PAGE_SIZE) >> PAGE_SHIFT;
+	num_pages = ALIGN(len, PAGE_SIZE) >> PAGE_SHIFT;
 
 	bounce_sgl = kcalloc(num_pages, sizeof(struct scatterlist), GFP_ATOMIC);
 	if (!bounce_sgl)
@@ -456,21 +173,72 @@
 	return NULL;
 }
 
-static void destroy_bounce_buffer(struct scatterlist *sgl,
-				  unsigned int sg_count)
+
+/* Assume the original sgl has enough room */
+static unsigned int copy_from_bounce_buffer(struct scatterlist *orig_sgl,
+					    struct scatterlist *bounce_sgl,
+					    unsigned int orig_sgl_count)
 {
 	int i;
-	struct page *page_buf;
+	int j = 0;
+	unsigned long src, dest;
+	unsigned int srclen, destlen, copylen;
+	unsigned int total_copied = 0;
+	unsigned long bounce_addr = 0;
+	unsigned long dest_addr = 0;
+	unsigned long flags;
 
-	for (i = 0; i < sg_count; i++) {
-		page_buf = sg_page((&sgl[i]));
-		if (page_buf != NULL)
-			__free_page(page_buf);
+	local_irq_save(flags);
+
+	for (i = 0; i < orig_sgl_count; i++) {
+		dest_addr = (unsigned long)kmap_atomic(sg_page((&orig_sgl[i])),
+					KM_IRQ0) + orig_sgl[i].offset;
+		dest = dest_addr;
+		destlen = orig_sgl[i].length;
+
+		if (bounce_addr == 0)
+			bounce_addr =
+			(unsigned long)kmap_atomic(sg_page((&bounce_sgl[j])),
+							KM_IRQ0);
+
+		while (destlen) {
+			src = bounce_addr + bounce_sgl[j].offset;
+			srclen = bounce_sgl[j].length - bounce_sgl[j].offset;
+
+			copylen = min(srclen, destlen);
+			memcpy((void *)dest, (void *)src, copylen);
+
+			total_copied += copylen;
+			bounce_sgl[j].offset += copylen;
+			destlen -= copylen;
+			dest += copylen;
+
+			if (bounce_sgl[j].offset == bounce_sgl[j].length) {
+				/* full */
+				kunmap_atomic((void *)bounce_addr, KM_IRQ0);
+				j++;
+
+				/* if we need to use another bounce buffer */
+				if (destlen || i != orig_sgl_count - 1)
+					bounce_addr =
+					(unsigned long)kmap_atomic(
+					sg_page((&bounce_sgl[j])), KM_IRQ0);
+			} else if (destlen == 0 && i == orig_sgl_count - 1) {
+				/* unmap the last bounce that is < PAGE_SIZE */
+				kunmap_atomic((void *)bounce_addr, KM_IRQ0);
+			}
+		}
+
+		kunmap_atomic((void *)(dest_addr - orig_sgl[i].offset),
+			      KM_IRQ0);
 	}
 
-	kfree(sgl);
+	local_irq_restore(flags);
+
+	return total_copied;
 }
 
+
 /* Assume the bounce_sgl has enough room ie using the create_bounce_buffer() */
 static unsigned int copy_to_bounce_buffer(struct scatterlist *orig_sgl,
 					  struct scatterlist *bounce_sgl,
@@ -493,10 +261,10 @@
 		src = src_addr;
 		srclen = orig_sgl[i].length;
 
-		/* ASSERT(orig_sgl[i].offset + orig_sgl[i].length <= PAGE_SIZE); */
-
 		if (bounce_addr == 0)
-			bounce_addr = (unsigned long)kmap_atomic(sg_page((&bounce_sgl[j])), KM_IRQ0);
+			bounce_addr =
+			(unsigned long)kmap_atomic(sg_page((&bounce_sgl[j])),
+						KM_IRQ0);
 
 		while (srclen) {
 			/* assume bounce offset always == 0 */
@@ -518,7 +286,10 @@
 
 				/* if we need to use another bounce buffer */
 				if (srclen || i != orig_sgl_count - 1)
-					bounce_addr = (unsigned long)kmap_atomic(sg_page((&bounce_sgl[j])), KM_IRQ0);
+					bounce_addr =
+					(unsigned long)kmap_atomic(
+					sg_page((&bounce_sgl[j])), KM_IRQ0);
+
 			} else if (srclen == 0 && i == orig_sgl_count - 1) {
 				/* unmap the last bounce that is < PAGE_SIZE */
 				kunmap_atomic((void *)bounce_addr, KM_IRQ0);
@@ -533,120 +304,197 @@
 	return total_copied;
 }
 
-/* Assume the original sgl has enough room */
-static unsigned int copy_from_bounce_buffer(struct scatterlist *orig_sgl,
-					    struct scatterlist *bounce_sgl,
-					    unsigned int orig_sgl_count)
+
+static int storvsc_remove(struct hv_device *dev)
 {
-	int i;
-	int j = 0;
-	unsigned long src, dest;
-	unsigned int srclen, destlen, copylen;
-	unsigned int total_copied = 0;
-	unsigned long bounce_addr = 0;
-	unsigned long dest_addr = 0;
-	unsigned long flags;
+	struct Scsi_Host *host = dev_get_drvdata(&dev->device);
+	struct hv_host_device *host_dev =
+			(struct hv_host_device *)host->hostdata;
 
-	local_irq_save(flags);
+	scsi_remove_host(host);
 
-	for (i = 0; i < orig_sgl_count; i++) {
-		dest_addr = (unsigned long)kmap_atomic(sg_page((&orig_sgl[i])),
-					KM_IRQ0) + orig_sgl[i].offset;
-		dest = dest_addr;
-		destlen = orig_sgl[i].length;
-		/* ASSERT(orig_sgl[i].offset + orig_sgl[i].length <= PAGE_SIZE); */
+	scsi_host_put(host);
 
-		if (bounce_addr == 0)
-			bounce_addr = (unsigned long)kmap_atomic(sg_page((&bounce_sgl[j])), KM_IRQ0);
+	storvsc_dev_remove(dev);
+	if (host_dev->request_pool) {
+		kmem_cache_destroy(host_dev->request_pool);
+		host_dev->request_pool = NULL;
+	}
+	return 0;
+}
 
-		while (destlen) {
-			src = bounce_addr + bounce_sgl[j].offset;
-			srclen = bounce_sgl[j].length - bounce_sgl[j].offset;
 
-			copylen = min(srclen, destlen);
-			memcpy((void *)dest, (void *)src, copylen);
+static int storvsc_get_chs(struct scsi_device *sdev, struct block_device * bdev,
+			   sector_t capacity, int *info)
+{
+	sector_t nsect = capacity;
+	sector_t cylinders = nsect;
+	int heads, sectors_pt;
 
-			total_copied += copylen;
-			bounce_sgl[j].offset += copylen;
-			destlen -= copylen;
-			dest += copylen;
+	/*
+	 * We are making up these values; let us keep it simple.
+	 */
+	heads = 0xff;
+	sectors_pt = 0x3f;      /* Sectors per track */
+	sector_div(cylinders, heads * sectors_pt);
+	if ((sector_t)(cylinders + 1) * heads * sectors_pt < nsect)
+		cylinders = 0xffff;
 
-			if (bounce_sgl[j].offset == bounce_sgl[j].length) {
-				/* full */
-				kunmap_atomic((void *)bounce_addr, KM_IRQ0);
-				j++;
+	info[0] = heads;
+	info[1] = sectors_pt;
+	info[2] = (int)cylinders;
 
-				/* if we need to use another bounce buffer */
-				if (destlen || i != orig_sgl_count - 1)
-					bounce_addr = (unsigned long)kmap_atomic(sg_page((&bounce_sgl[j])), KM_IRQ0);
-			} else if (destlen == 0 && i == orig_sgl_count - 1) {
-				/* unmap the last bounce that is < PAGE_SIZE */
-				kunmap_atomic((void *)bounce_addr, KM_IRQ0);
-			}
-		}
+	return 0;
+}
 
-		kunmap_atomic((void *)(dest_addr - orig_sgl[i].offset),
-			      KM_IRQ0);
+static int storvsc_host_reset(struct hv_device *device)
+{
+	struct storvsc_device *stor_device;
+	struct hv_storvsc_request *request;
+	struct vstor_packet *vstor_packet;
+	int ret, t;
+
+
+	stor_device = get_stor_device(device);
+	if (!stor_device)
+		return -1;
+
+	request = &stor_device->reset_request;
+	vstor_packet = &request->vstor_packet;
+
+	init_completion(&request->wait_event);
+
+	vstor_packet->operation = VSTOR_OPERATION_RESET_BUS;
+	vstor_packet->flags = REQUEST_COMPLETION_FLAG;
+	vstor_packet->vm_srb.path_id = stor_device->path_id;
+
+	ret = vmbus_sendpacket(device->channel, vstor_packet,
+			       sizeof(struct vstor_packet),
+			       (unsigned long)&stor_device->reset_request,
+			       VM_PKT_DATA_INBAND,
+			       VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
+	if (ret != 0)
+		goto cleanup;
+
+	t = wait_for_completion_timeout(&request->wait_event, HZ);
+	if (t == 0) {
+		ret = -ETIMEDOUT;
+		goto cleanup;
 	}
 
-	local_irq_restore(flags);
 
-	return total_copied;
+	/*
+	 * At this point, all outstanding requests in the adapter
+	 * should have been flushed out and return to us
+	 */
+
+cleanup:
+	put_stor_device(device);
+	return ret;
 }
 
+
+/*
+ * storvsc_host_reset_handler - Reset the scsi HBA
+ */
+static int storvsc_host_reset_handler(struct scsi_cmnd *scmnd)
+{
+	int ret;
+	struct hv_host_device *host_dev =
+		(struct hv_host_device *)scmnd->device->host->hostdata;
+	struct hv_device *dev = host_dev->dev;
+
+	ret = storvsc_host_reset(dev);
+	if (ret != 0)
+		return ret;
+
+	return ret;
+}
+
+
+/*
+ * storvsc_commmand_completion - Command completion processing
+ */
+static void storvsc_commmand_completion(struct hv_storvsc_request *request)
+{
+	struct storvsc_cmd_request *cmd_request =
+		(struct storvsc_cmd_request *)request->context;
+	struct scsi_cmnd *scmnd = cmd_request->cmd;
+	struct hv_host_device *host_dev =
+		(struct hv_host_device *)scmnd->device->host->hostdata;
+	void (*scsi_done_fn)(struct scsi_cmnd *);
+	struct scsi_sense_hdr sense_hdr;
+	struct vmscsi_request *vm_srb;
+
+	if (cmd_request->bounce_sgl_count) {
+
+		/* FIXME: We can optimize on writes by just skipping this */
+		copy_from_bounce_buffer(scsi_sglist(scmnd),
+					cmd_request->bounce_sgl,
+					scsi_sg_count(scmnd));
+		destroy_bounce_buffer(cmd_request->bounce_sgl,
+				      cmd_request->bounce_sgl_count);
+	}
+
+	vm_srb = &request->vstor_packet.vm_srb;
+	scmnd->result = vm_srb->scsi_status;
+
+	if (scmnd->result) {
+		if (scsi_normalize_sense(scmnd->sense_buffer,
+				SCSI_SENSE_BUFFERSIZE, &sense_hdr))
+			scsi_print_sense_hdr("storvsc", &sense_hdr);
+	}
+
+	scsi_set_resid(scmnd,
+		request->data_buffer.len -
+		vm_srb->data_transfer_length);
+
+	scsi_done_fn = scmnd->scsi_done;
+
+	scmnd->host_scribble = NULL;
+	scmnd->scsi_done = NULL;
+
+	scsi_done_fn(scmnd);
+
+	kmem_cache_free(host_dev->request_pool, cmd_request);
+}
+
+
 /*
  * storvsc_queuecommand - Initiate command processing
  */
-static int storvsc_queuecommand(struct scsi_cmnd *scmnd,
+static int storvsc_queuecommand_lck(struct scsi_cmnd *scmnd,
 				void (*done)(struct scsi_cmnd *))
 {
 	int ret;
-	struct host_device_context *host_device_ctx =
-		(struct host_device_context *)scmnd->device->host->hostdata;
-	struct vm_device *device_ctx = host_device_ctx->device_ctx;
-	struct driver_context *driver_ctx =
-		driver_to_driver_context(device_ctx->device.driver);
-	struct storvsc_driver_context *storvsc_drv_ctx =
-		(struct storvsc_driver_context *)driver_ctx;
-	struct storvsc_driver_object *storvsc_drv_obj =
-		&storvsc_drv_ctx->drv_obj;
+	struct hv_host_device *host_dev =
+		(struct hv_host_device *)scmnd->device->host->hostdata;
+	struct hv_device *dev = host_dev->dev;
 	struct hv_storvsc_request *request;
 	struct storvsc_cmd_request *cmd_request;
 	unsigned int request_size = 0;
 	int i;
 	struct scatterlist *sgl;
 	unsigned int sg_count = 0;
+	struct vmscsi_request *vm_srb;
 
-	DPRINT_DBG(STORVSC_DRV, "scmnd %p dir %d, use_sg %d buf %p len %d "
-		   "queue depth %d tagged %d", scmnd, scmnd->sc_data_direction,
-		   scsi_sg_count(scmnd), scsi_sglist(scmnd),
-		   scsi_bufflen(scmnd), scmnd->device->queue_depth,
-		   scmnd->device->tagged_supported);
 
 	/* If retrying, no need to prep the cmd */
 	if (scmnd->host_scribble) {
-		/* ASSERT(scmnd->scsi_done != NULL); */
 
 		cmd_request =
 			(struct storvsc_cmd_request *)scmnd->host_scribble;
-		DPRINT_INFO(STORVSC_DRV, "retrying scmnd %p cmd_request %p",
-			    scmnd, cmd_request);
 
 		goto retry_request;
 	}
 
-	/* ASSERT(scmnd->scsi_done == NULL); */
-	/* ASSERT(scmnd->host_scribble == NULL); */
-
 	scmnd->scsi_done = done;
 
 	request_size = sizeof(struct storvsc_cmd_request);
 
-	cmd_request = kmem_cache_alloc(host_device_ctx->request_pool,
+	cmd_request = kmem_cache_zalloc(host_dev->request_pool,
 				       GFP_ATOMIC);
 	if (!cmd_request) {
-		DPRINT_ERR(STORVSC_DRV, "scmnd (%p) - unable to allocate "
-			   "storvsc_cmd_request...marking queue busy", scmnd);
 		scmnd->scsi_done = NULL;
 		return SCSI_MLQUEUE_DEVICE_BUSY;
 	}
@@ -659,70 +507,58 @@
 	scmnd->host_scribble = (unsigned char *)cmd_request;
 
 	request = &cmd_request->request;
+	vm_srb = &request->vstor_packet.vm_srb;
 
-	request->Extension =
-		(void *)((unsigned long)cmd_request + request_size);
-	DPRINT_DBG(STORVSC_DRV, "req %p size %d ext %d", request, request_size,
-		   storvsc_drv_obj->RequestExtSize);
 
 	/* Build the SRB */
 	switch (scmnd->sc_data_direction) {
 	case DMA_TO_DEVICE:
-		request->Type = WRITE_TYPE;
+		vm_srb->data_in = WRITE_TYPE;
 		break;
 	case DMA_FROM_DEVICE:
-		request->Type = READ_TYPE;
+		vm_srb->data_in = READ_TYPE;
 		break;
 	default:
-		request->Type = UNKNOWN_TYPE;
+		vm_srb->data_in = UNKNOWN_TYPE;
 		break;
 	}
 
-	request->OnIOCompletion = storvsc_commmand_completion;
-	request->Context = cmd_request;/* scmnd; */
+	request->on_io_completion = storvsc_commmand_completion;
+	request->context = cmd_request;/* scmnd; */
 
-	/* request->PortId = scmnd->device->channel; */
-	request->Host = host_device_ctx->port;
-	request->Bus = scmnd->device->channel;
-	request->TargetId = scmnd->device->id;
-	request->LunId = scmnd->device->lun;
+	vm_srb->port_number = host_dev->port;
+	vm_srb->path_id = scmnd->device->channel;
+	vm_srb->target_id = scmnd->device->id;
+	vm_srb->lun = scmnd->device->lun;
 
-	/* ASSERT(scmnd->cmd_len <= 16); */
-	request->CdbLen = scmnd->cmd_len;
-	request->Cdb = scmnd->cmnd;
+	vm_srb->cdb_length = scmnd->cmd_len;
 
-	request->SenseBuffer = scmnd->sense_buffer;
-	request->SenseBufferSize = SCSI_SENSE_BUFFERSIZE;
+	memcpy(vm_srb->cdb, scmnd->cmnd, vm_srb->cdb_length);
+
+	request->sense_buffer = scmnd->sense_buffer;
 
 
-	request->DataBuffer.Length = scsi_bufflen(scmnd);
+	request->data_buffer.len = scsi_bufflen(scmnd);
 	if (scsi_sg_count(scmnd)) {
 		sgl = (struct scatterlist *)scsi_sglist(scmnd);
 		sg_count = scsi_sg_count(scmnd);
 
 		/* check if we need to bounce the sgl */
 		if (do_bounce_buffer(sgl, scsi_sg_count(scmnd)) != -1) {
-			DPRINT_INFO(STORVSC_DRV,
-				    "need to bounce buffer for this scmnd %p",
-				    scmnd);
 			cmd_request->bounce_sgl =
 				create_bounce_buffer(sgl, scsi_sg_count(scmnd),
 						     scsi_bufflen(scmnd));
 			if (!cmd_request->bounce_sgl) {
-				DPRINT_ERR(STORVSC_DRV,
-					   "unable to create bounce buffer for "
-					   "this scmnd %p", scmnd);
-
 				scmnd->scsi_done = NULL;
 				scmnd->host_scribble = NULL;
-				kmem_cache_free(host_device_ctx->request_pool,
+				kmem_cache_free(host_dev->request_pool,
 						cmd_request);
 
 				return SCSI_MLQUEUE_HOST_BUSY;
 			}
 
 			cmd_request->bounce_sgl_count =
-				ALIGN_UP(scsi_bufflen(scmnd), PAGE_SIZE) >>
+				ALIGN(scsi_bufflen(scmnd), PAGE_SIZE) >>
 					PAGE_SHIFT;
 
 			/*
@@ -736,31 +572,25 @@
 			sg_count = cmd_request->bounce_sgl_count;
 		}
 
-		request->DataBuffer.Offset = sgl[0].offset;
+		request->data_buffer.offset = sgl[0].offset;
 
-		for (i = 0; i < sg_count; i++) {
-			DPRINT_DBG(STORVSC_DRV, "sgl[%d] len %d offset %d\n",
-				   i, sgl[i].length, sgl[i].offset);
-			request->DataBuffer.PfnArray[i] =
+		for (i = 0; i < sg_count; i++)
+			request->data_buffer.pfn_array[i] =
 				page_to_pfn(sg_page((&sgl[i])));
-		}
+
 	} else if (scsi_sglist(scmnd)) {
-		/* ASSERT(scsi_bufflen(scmnd) <= PAGE_SIZE); */
-		request->DataBuffer.Offset =
+		request->data_buffer.offset =
 			virt_to_phys(scsi_sglist(scmnd)) & (PAGE_SIZE-1);
-		request->DataBuffer.PfnArray[0] =
+		request->data_buffer.pfn_array[0] =
 			virt_to_phys(scsi_sglist(scmnd)) >> PAGE_SHIFT;
 	}
 
 retry_request:
 	/* Invokes the vsc to start an IO */
-	ret = storvsc_drv_obj->OnIORequest(&device_ctx->device_obj,
-					   &cmd_request->request);
+	ret = storvsc_do_io(dev, &cmd_request->request);
+
 	if (ret == -1) {
 		/* no more space */
-		DPRINT_ERR(STORVSC_DRV,
-			   "scmnd (%p) - queue FULL...marking queue busy",
-			   scmnd);
 
 		if (cmd_request->bounce_sgl_count) {
 			/*
@@ -774,7 +604,7 @@
 					      cmd_request->bounce_sgl_count);
 		}
 
-		kmem_cache_free(host_device_ctx->request_pool, cmd_request);
+		kmem_cache_free(host_dev->request_pool, cmd_request);
 
 		scmnd->scsi_done = NULL;
 		scmnd->host_scribble = NULL;
@@ -785,172 +615,178 @@
 	return ret;
 }
 
-static int storvsc_merge_bvec(struct request_queue *q,
-			      struct bvec_merge_data *bmd, struct bio_vec *bvec)
-{
-	/* checking done by caller. */
-	return bvec->bv_len;
-}
+static DEF_SCSI_QCMD(storvsc_queuecommand)
 
-/*
- * storvsc_device_configure - Configure the specified scsi device
- */
-static int storvsc_device_alloc(struct scsi_device *sdevice)
-{
-	DPRINT_DBG(STORVSC_DRV, "sdev (%p) - setting device flag to %d",
-		   sdevice, BLIST_SPARSELUN);
+
+/* Scsi driver */
+static struct scsi_host_template scsi_driver = {
+	.module	=		THIS_MODULE,
+	.name =			"storvsc_host_t",
+	.bios_param =		storvsc_get_chs,
+	.queuecommand =		storvsc_queuecommand,
+	.eh_host_reset_handler =	storvsc_host_reset_handler,
+	.slave_alloc =		storvsc_device_alloc,
+	.slave_configure =	storvsc_device_configure,
+	.cmd_per_lun =		1,
+	/* 64 max_queue * 1 target */
+	.can_queue =		STORVSC_MAX_IO_REQUESTS*STORVSC_MAX_TARGETS,
+	.this_id =		-1,
+	/* no use setting to 0 since ll_blk_rw reset it to 1 */
+	/* currently 32 */
+	.sg_tablesize =		MAX_MULTIPAGE_BUFFER_COUNT,
 	/*
-	 * This enables luns to be located sparsely. Otherwise, we may not
-	 * discovered them.
+	 * ENABLE_CLUSTERING allows mutiple physically contig bio_vecs to merge
+	 * into 1 sg element. If set, we must limit the max_segment_size to
+	 * PAGE_SIZE, otherwise we may get 1 sg element that represents
+	 * multiple
 	 */
-	sdevice->sdev_bflags |= BLIST_SPARSELUN | BLIST_LARGELUN;
-	return 0;
-}
+	/* physically contig pfns (ie sg[x].length > PAGE_SIZE). */
+	.use_clustering =	ENABLE_CLUSTERING,
+	/* Make sure we dont get a sg segment crosses a page boundary */
+	.dma_boundary =		PAGE_SIZE-1,
+};
 
-static int storvsc_device_configure(struct scsi_device *sdevice)
-{
-	DPRINT_INFO(STORVSC_DRV, "sdev (%p) - curr queue depth %d", sdevice,
-		    sdevice->queue_depth);
-
-	DPRINT_INFO(STORVSC_DRV, "sdev (%p) - setting queue depth to %d",
-		    sdevice, STORVSC_MAX_IO_REQUESTS);
-	scsi_adjust_queue_depth(sdevice, MSG_SIMPLE_TAG,
-				STORVSC_MAX_IO_REQUESTS);
-
-	DPRINT_INFO(STORVSC_DRV, "sdev (%p) - setting max segment size to %ld",
-		    sdevice, PAGE_SIZE);
-	blk_queue_max_segment_size(sdevice->request_queue, PAGE_SIZE);
-
-	DPRINT_INFO(STORVSC_DRV, "sdev (%p) - adding merge bio vec routine",
-		    sdevice);
-	blk_queue_merge_bvec(sdevice->request_queue, storvsc_merge_bvec);
-
-	blk_queue_bounce_limit(sdevice->request_queue, BLK_BOUNCE_ANY);
-	/* sdevice->timeout = (2000 * HZ);//(75 * HZ); */
-
-	return 0;
-}
 
 /*
- * storvsc_host_reset_handler - Reset the scsi HBA
+ * storvsc_probe - Add a new device for this driver
  */
-static int storvsc_host_reset_handler(struct scsi_cmnd *scmnd)
+
+static int storvsc_probe(struct hv_device *device)
 {
 	int ret;
-	struct host_device_context *host_device_ctx =
-		(struct host_device_context *)scmnd->device->host->hostdata;
-	struct vm_device *device_ctx = host_device_ctx->device_ctx;
+	struct Scsi_Host *host;
+	struct hv_host_device *host_dev;
+	struct storvsc_device_info device_info;
 
-	DPRINT_INFO(STORVSC_DRV, "sdev (%p) dev obj (%p) - host resetting...",
-		    scmnd->device, &device_ctx->device_obj);
+	host = scsi_host_alloc(&scsi_driver,
+			       sizeof(struct hv_host_device));
+	if (!host)
+		return -ENOMEM;
 
-	/* Invokes the vsc to reset the host/bus */
-	ret = StorVscOnHostReset(&device_ctx->device_obj);
-	if (ret != 0)
-		return ret;
+	dev_set_drvdata(&device->device, host);
 
-	DPRINT_INFO(STORVSC_DRV, "sdev (%p) dev obj (%p) - host reseted",
-		    scmnd->device, &device_ctx->device_obj);
+	host_dev = (struct hv_host_device *)host->hostdata;
+	memset(host_dev, 0, sizeof(struct hv_host_device));
 
-	return ret;
-}
+	host_dev->port = host->host_no;
+	host_dev->dev = device;
 
-static int storvsc_get_chs(struct scsi_device *sdev, struct block_device * bdev,
-			   sector_t capacity, int *info)
-{
-	sector_t total_sectors = capacity;
-	sector_t cylinder_times_heads = 0;
-	sector_t temp = 0;
+	host_dev->request_pool =
+				kmem_cache_create(dev_name(&device->device),
+					sizeof(struct storvsc_cmd_request), 0,
+					SLAB_HWCACHE_ALIGN, NULL);
 
-	int sectors_per_track = 0;
-	int heads = 0;
-	int cylinders = 0;
-	int rem = 0;
-
-	if (total_sectors > (65535 * 16 * 255))
-		total_sectors = (65535 * 16 * 255);
-
-	if (total_sectors >= (65535 * 16 * 63)) {
-		sectors_per_track = 255;
-		heads = 16;
-
-		cylinder_times_heads = total_sectors;
-		/* sector_div stores the quotient in cylinder_times_heads */
-		rem = sector_div(cylinder_times_heads, sectors_per_track);
-	} else {
-		sectors_per_track = 17;
-
-		cylinder_times_heads = total_sectors;
-		/* sector_div stores the quotient in cylinder_times_heads */
-		rem = sector_div(cylinder_times_heads, sectors_per_track);
-
-		temp = cylinder_times_heads + 1023;
-		/* sector_div stores the quotient in temp */
-		rem = sector_div(temp, 1024);
-
-		heads = temp;
-
-		if (heads < 4)
-			heads = 4;
-
-		if (cylinder_times_heads >= (heads * 1024) || (heads > 16)) {
-			sectors_per_track = 31;
-			heads = 16;
-
-			cylinder_times_heads = total_sectors;
-			/*
-			 * sector_div stores the quotient in
-			 * cylinder_times_heads
-			 */
-			rem = sector_div(cylinder_times_heads,
-					 sectors_per_track);
-		}
-
-		if (cylinder_times_heads >= (heads * 1024)) {
-			sectors_per_track = 63;
-			heads = 16;
-
-			cylinder_times_heads = total_sectors;
-			/*
-			 * sector_div stores the quotient in
-			 * cylinder_times_heads
-			 */
-			rem = sector_div(cylinder_times_heads,
-					 sectors_per_track);
-		}
+	if (!host_dev->request_pool) {
+		scsi_host_put(host);
+		return -ENOMEM;
 	}
 
-	temp = cylinder_times_heads;
-	/* sector_div stores the quotient in temp */
-	rem = sector_div(temp, heads);
-	cylinders = temp;
+	device_info.port_number = host->host_no;
+	device_info.ring_buffer_size  = storvsc_ringbuffer_size;
+	/* Call to the vsc driver to add the device */
+	ret = storvsc_dev_add(device, (void *)&device_info);
 
-	info[0] = heads;
-	info[1] = sectors_per_track;
-	info[2] = cylinders;
+	if (ret != 0) {
+		kmem_cache_destroy(host_dev->request_pool);
+		scsi_host_put(host);
+		return -1;
+	}
 
-	DPRINT_INFO(STORVSC_DRV, "CHS (%d, %d, %d)", cylinders, heads,
-		    sectors_per_track);
+	host_dev->path = device_info.path_id;
+	host_dev->target = device_info.target_id;
 
-    return 0;
-}
+	/* max # of devices per target */
+	host->max_lun = STORVSC_MAX_LUNS_PER_TARGET;
+	/* max # of targets per channel */
+	host->max_id = STORVSC_MAX_TARGETS;
+	/* max # of channels */
+	host->max_channel = STORVSC_MAX_CHANNELS - 1;
 
-static int __init storvsc_init(void)
-{
-	int ret;
+	/* Register the HBA and start the scsi bus scan */
+	ret = scsi_add_host(host, &device->device);
+	if (ret != 0) {
 
-	DPRINT_INFO(STORVSC_DRV, "Storvsc initializing....");
-	ret = storvsc_drv_init(StorVscInitialize);
+		storvsc_dev_remove(device);
+
+		kmem_cache_destroy(host_dev->request_pool);
+		scsi_host_put(host);
+		return -1;
+	}
+
+	scsi_scan_host(host);
 	return ret;
 }
 
-static void __exit storvsc_exit(void)
+/* The one and only one */
+
+static struct hv_driver storvsc_drv = {
+	.probe = storvsc_probe,
+	.remove = storvsc_remove,
+};
+
+/*
+ * We use a DMI table to determine if we should autoload this driver  This is
+ * needed by distro tools to determine if the hyperv drivers should be
+ * installed and/or configured.  We don't do anything else with the table, but
+ * it needs to be present.
+ */
+
+static const struct dmi_system_id __initconst
+hv_stor_dmi_table[] __maybe_unused  = {
+	{
+		.ident = "Hyper-V",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Virtual Machine"),
+			DMI_MATCH(DMI_BOARD_NAME, "Virtual Machine"),
+		},
+	},
+	{ },
+};
+MODULE_DEVICE_TABLE(dmi, hv_stor_dmi_table);
+
+static int __init storvsc_drv_init(void)
 {
-	storvsc_drv_exit();
+	int ret;
+	struct hv_driver *drv = &storvsc_drv;
+	u32 max_outstanding_req_per_channel;
+
+	/*
+	 * Divide the ring buffer data size (which is 1 page less
+	 * than the ring buffer size since that page is reserved for
+	 * the ring buffer indices) by the max request size (which is
+	 * vmbus_channel_packet_multipage_buffer + struct vstor_packet + u64)
+	 */
+
+	max_outstanding_req_per_channel =
+	((storvsc_ringbuffer_size - PAGE_SIZE) /
+	ALIGN(MAX_MULTIPAGE_BUFFER_PACKET +
+	sizeof(struct vstor_packet) + sizeof(u64),
+	sizeof(u64)));
+
+	memcpy(&drv->dev_type, &stor_vsci_device_type,
+	       sizeof(struct hv_guid));
+
+	if (max_outstanding_req_per_channel <
+	    STORVSC_MAX_IO_REQUESTS)
+		return -1;
+
+	drv->driver.name = driver_name;
+
+
+	/* The driver belongs to vmbus */
+	ret = vmbus_child_driver_register(&drv->driver);
+
+	return ret;
+}
+
+static void __exit storvsc_drv_exit(void)
+{
+	vmbus_child_driver_unregister(&storvsc_drv.driver);
 }
 
 MODULE_LICENSE("GPL");
 MODULE_VERSION(HV_DRV_VERSION);
 MODULE_DESCRIPTION("Microsoft Hyper-V virtual storage driver");
-module_init(storvsc_init);
-module_exit(storvsc_exit);
+module_init(storvsc_drv_init);
+module_exit(storvsc_drv_exit);
diff --git a/drivers/staging/hv/tools/hv_kvp_daemon.c b/drivers/staging/hv/tools/hv_kvp_daemon.c
new file mode 100644
index 0000000..33f0f1c
--- /dev/null
+++ b/drivers/staging/hv/tools/hv_kvp_daemon.c
@@ -0,0 +1,494 @@
+/*
+ * An implementation of key value pair (KVP) functionality for Linux.
+ *
+ *
+ * Copyright (C) 2010, Novell, Inc.
+ * Author : K. Y. Srinivasan <ksrinivasan@novell.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/poll.h>
+#include <sys/utsname.h>
+#include <linux/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <arpa/inet.h>
+#include <linux/connector.h>
+#include <linux/netlink.h>
+#include <sys/socket.h>
+#include <ifaddrs.h>
+#include <netdb.h>
+#include <syslog.h>
+
+/*
+ * KYS: TODO. Need to register these in the kernel.
+ *
+ * The following definitions are shared with the in-kernel component; do not
+ * change any of this without making the corresponding changes in
+ * the KVP kernel component.
+ */
+#define CN_KVP_IDX		0x9     /* MSFT KVP functionality */
+#define CN_KVP_VAL		0x1 /* This supports queries from the kernel */
+#define CN_KVP_USER_VAL		0x2 /* This supports queries from the user  */
+
+/*
+ * KVP protocol: The user mode component first registers with the
+ * the kernel component. Subsequently, the kernel component requests, data
+ * for the specified keys. In response to this message the user mode component
+ * fills in the value corresponding to the specified key. We overload the
+ * sequence field in the cn_msg header to define our KVP message types.
+ *
+ * We use this infrastructure for also supporting queries from user mode
+ * application for state that may be maintained in the KVP kernel component.
+ *
+ * XXXKYS: Have a shared header file between the user and kernel (TODO)
+ */
+
+enum kvp_op {
+	KVP_REGISTER = 0, /* Register the user mode component*/
+	KVP_KERNEL_GET, /*Kernel is requesting the value for the specified key*/
+	KVP_KERNEL_SET, /*Kernel is providing the value for the specified key*/
+	KVP_USER_GET, /*User is requesting the value for the specified key*/
+	KVP_USER_SET /*User is providing the value for the specified key*/
+};
+
+#define HV_KVP_EXCHANGE_MAX_KEY_SIZE	512
+#define HV_KVP_EXCHANGE_MAX_VALUE_SIZE	2048
+
+struct hv_ku_msg {
+	__u32	kvp_index;
+	__u8  kvp_key[HV_KVP_EXCHANGE_MAX_KEY_SIZE]; /* Key name */
+	__u8  kvp_value[HV_KVP_EXCHANGE_MAX_VALUE_SIZE]; /* Key  value */
+};
+
+enum key_index {
+	FullyQualifiedDomainName = 0,
+	IntegrationServicesVersion, /*This key is serviced in the kernel*/
+	NetworkAddressIPv4,
+	NetworkAddressIPv6,
+	OSBuildNumber,
+	OSName,
+	OSMajorVersion,
+	OSMinorVersion,
+	OSVersion,
+	ProcessorArchitecture
+};
+
+/*
+ * End of shared definitions.
+ */
+
+static char kvp_send_buffer[4096];
+static char kvp_recv_buffer[4096];
+static struct sockaddr_nl addr;
+
+static char *os_name = "";
+static char *os_major = "";
+static char *os_minor = "";
+static char *processor_arch;
+static char *os_build;
+static char *lic_version;
+static struct utsname uts_buf;
+
+void kvp_get_os_info(void)
+{
+	FILE	*file;
+	char	*p, buf[512];
+
+	uname(&uts_buf);
+	os_build = uts_buf.release;
+	processor_arch= uts_buf.machine;
+
+	file = fopen("/etc/SuSE-release", "r");
+	if (file != NULL)
+		goto kvp_osinfo_found;
+	file  = fopen("/etc/redhat-release", "r");
+	if (file != NULL)
+		goto kvp_osinfo_found;
+	/*
+	 * Add code for other supported platforms.
+	 */
+
+	/*
+	 * We don't have information about the os.
+	 */
+	os_name = uts_buf.sysname;
+	return;
+
+kvp_osinfo_found:
+	/* up to three lines */
+	p = fgets(buf, sizeof(buf), file);
+	if (p) {
+		p = strchr(buf, '\n');
+		if (p)
+			*p = '\0';
+		p = strdup(buf);
+		if (!p)
+			goto done;
+		os_name = p;
+
+		/* second line */
+		p = fgets(buf, sizeof(buf), file);
+		if (p) {
+			p = strchr(buf, '\n');
+			if (p)
+				*p = '\0';
+			p = strdup(buf);
+			if (!p)
+				goto done;
+			os_major = p;
+
+			/* third line */
+			p = fgets(buf, sizeof(buf), file);
+			if (p)  {
+				p = strchr(buf, '\n');
+				if (p)
+					*p = '\0';
+				p = strdup(buf);
+				if (p)
+					os_minor = p;
+			}
+		}
+	}
+
+done:
+	fclose(file);
+	return;
+}
+
+static int
+kvp_get_ip_address(int family, char *buffer, int length)
+{
+	struct ifaddrs *ifap;
+	struct ifaddrs *curp;
+	int ipv4_len = strlen("255.255.255.255") + 1;
+	int ipv6_len = strlen("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff")+1;
+	int offset = 0;
+	const char *str;
+	char tmp[50];
+	int error = 0;
+
+	/*
+	 * On entry into this function, the buffer is capable of holding the
+	 * maximum key value (2048 bytes).
+	 */
+
+	if (getifaddrs(&ifap)) {
+		strcpy(buffer, "getifaddrs failed\n");
+		return 1;
+	}
+
+	curp = ifap;
+	while (curp != NULL) {
+		if ((curp->ifa_addr != NULL) &&
+		   (curp->ifa_addr->sa_family == family)) {
+			if (family == AF_INET) {
+				struct sockaddr_in *addr =
+				(struct sockaddr_in *) curp->ifa_addr;
+
+				str = inet_ntop(family, &addr->sin_addr,
+						tmp, 50);
+				if (str == NULL) {
+					strcpy(buffer, "inet_ntop failed\n");
+					error = 1;
+					goto getaddr_done;
+				}
+				if (offset == 0)
+					strcpy(buffer, tmp);
+				else
+					strcat(buffer, tmp);
+				strcat(buffer, ";");
+
+				offset += strlen(str) + 1;
+				if ((length - offset) < (ipv4_len + 1))
+					goto getaddr_done;
+
+			} else {
+
+			/*
+			 * We only support AF_INET and AF_INET6
+			 * and the list of addresses is separated by a ";".
+			 */
+				struct sockaddr_in6 *addr =
+				(struct sockaddr_in6 *) curp->ifa_addr;
+
+				str = inet_ntop(family,
+					&addr->sin6_addr.s6_addr,
+					tmp, 50);
+				if (str == NULL) {
+					strcpy(buffer, "inet_ntop failed\n");
+					error = 1;
+					goto getaddr_done;
+				}
+				if (offset == 0)
+					strcpy(buffer, tmp);
+				else
+					strcat(buffer, tmp);
+				strcat(buffer, ";");
+				offset += strlen(str) + 1;
+				if ((length - offset) < (ipv6_len + 1))
+					goto getaddr_done;
+
+			}
+
+		}
+		curp = curp->ifa_next;
+	}
+
+getaddr_done:
+	freeifaddrs(ifap);
+	return error;
+}
+
+
+static int
+kvp_get_domain_name(char *buffer, int length)
+{
+	struct addrinfo	hints, *info ;
+	gethostname(buffer, length);
+	int error = 0;
+
+	memset(&hints, 0, sizeof(hints));
+	hints.ai_family = AF_INET; /*Get only ipv4 addrinfo. */
+	hints.ai_socktype = SOCK_STREAM;
+	hints.ai_flags = AI_CANONNAME;
+
+	error = getaddrinfo(buffer, "http", &hints, &info);
+	if (error != 0) {
+		strcpy(buffer, "getaddrinfo failed\n");
+		error = 1;
+		goto get_domain_done;
+	}
+	strcpy(buffer, info->ai_canonname);
+get_domain_done:
+	freeaddrinfo(info);
+	return error;
+}
+
+static int
+netlink_send(int fd, struct cn_msg *msg)
+{
+	struct nlmsghdr *nlh;
+	unsigned int size;
+	struct msghdr message;
+	char buffer[64];
+	struct iovec iov[2];
+
+	size = NLMSG_SPACE(sizeof(struct cn_msg) + msg->len);
+
+	nlh = (struct nlmsghdr *)buffer;
+	nlh->nlmsg_seq = 0;
+	nlh->nlmsg_pid = getpid();
+	nlh->nlmsg_type = NLMSG_DONE;
+	nlh->nlmsg_len = NLMSG_LENGTH(size - sizeof(*nlh));
+	nlh->nlmsg_flags = 0;
+
+	iov[0].iov_base = nlh;
+	iov[0].iov_len = sizeof(*nlh);
+
+	iov[1].iov_base = msg;
+	iov[1].iov_len = size;
+
+	memset(&message, 0, sizeof(message));
+	message.msg_name = &addr;
+	message.msg_namelen = sizeof(addr);
+	message.msg_iov = iov;
+	message.msg_iovlen = 2;
+
+	return sendmsg(fd, &message, 0);
+}
+
+int main(void)
+{
+	int fd, len, sock_opt;
+	int error;
+	struct cn_msg *message;
+	struct pollfd pfd;
+	struct nlmsghdr *incoming_msg;
+	struct cn_msg	*incoming_cn_msg;
+	struct hv_ku_msg *hv_msg;
+	char	*p;
+	char	*key_value;
+	char	*key_name;
+
+	daemon(1, 0);
+	openlog("KVP", 0, LOG_USER);
+	syslog(LOG_INFO, "KVP starting; pid is:%d", getpid());
+	/*
+	 * Retrieve OS release information.
+	 */
+	kvp_get_os_info();
+
+	fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR);
+	if (fd < 0) {
+		syslog(LOG_ERR, "netlink socket creation failed; error:%d", fd);
+		exit(-1);
+	}
+	addr.nl_family = AF_NETLINK;
+	addr.nl_pad = 0;
+	addr.nl_pid = 0;
+	addr.nl_groups = CN_KVP_IDX;
+
+
+	error = bind(fd, (struct sockaddr *)&addr, sizeof(addr));
+	if (error < 0) {
+		syslog(LOG_ERR, "bind failed; error:%d", error);
+		close(fd);
+		exit(-1);
+	}
+	sock_opt = addr.nl_groups;
+	setsockopt(fd, 270, 1, &sock_opt, sizeof(sock_opt));
+	/*
+	 * Register ourselves with the kernel.
+	 */
+	message = (struct cn_msg *)kvp_send_buffer;
+	message->id.idx = CN_KVP_IDX;
+	message->id.val = CN_KVP_VAL;
+	message->seq = KVP_REGISTER;
+	message->ack = 0;
+	message->len = 0;
+
+	len = netlink_send(fd, message);
+	if (len < 0) {
+		syslog(LOG_ERR, "netlink_send failed; error:%d", len);
+		close(fd);
+		exit(-1);
+	}
+
+	pfd.fd = fd;
+
+	while (1) {
+		pfd.events = POLLIN;
+		pfd.revents = 0;
+		poll(&pfd, 1, -1);
+
+		len = recv(fd, kvp_recv_buffer, sizeof(kvp_recv_buffer), 0);
+
+		if (len < 0) {
+			syslog(LOG_ERR, "recv failed; error:%d", len);
+			close(fd);
+			return -1;
+		}
+
+		incoming_msg = (struct nlmsghdr *)kvp_recv_buffer;
+		incoming_cn_msg = (struct cn_msg *)NLMSG_DATA(incoming_msg);
+
+		switch (incoming_cn_msg->seq) {
+		case KVP_REGISTER:
+			/*
+			 * Driver is registering with us; stash away the version
+			 * information.
+			 */
+			p = (char *)incoming_cn_msg->data;
+			lic_version = malloc(strlen(p) + 1);
+			if (lic_version) {
+				strcpy(lic_version, p);
+				syslog(LOG_INFO, "KVP LIC Version: %s",
+					lic_version);
+			} else {
+				syslog(LOG_ERR, "malloc failed");
+			}
+			continue;
+
+		case KVP_KERNEL_GET:
+			break;
+		default:
+			continue;
+		}
+
+		hv_msg = (struct hv_ku_msg *)incoming_cn_msg->data;
+		key_name = (char *)hv_msg->kvp_key;
+		key_value = (char *)hv_msg->kvp_value;
+
+		switch (hv_msg->kvp_index) {
+		case FullyQualifiedDomainName:
+			kvp_get_domain_name(key_value,
+					HV_KVP_EXCHANGE_MAX_VALUE_SIZE);
+			strcpy(key_name, "FullyQualifiedDomainName");
+			break;
+		case IntegrationServicesVersion:
+			strcpy(key_name, "IntegrationServicesVersion");
+			strcpy(key_value, lic_version);
+			break;
+		case NetworkAddressIPv4:
+			kvp_get_ip_address(AF_INET, key_value,
+					HV_KVP_EXCHANGE_MAX_VALUE_SIZE);
+			strcpy(key_name, "NetworkAddressIPv4");
+			break;
+		case NetworkAddressIPv6:
+			kvp_get_ip_address(AF_INET6, key_value,
+					HV_KVP_EXCHANGE_MAX_VALUE_SIZE);
+			strcpy(key_name, "NetworkAddressIPv6");
+			break;
+		case OSBuildNumber:
+			strcpy(key_value, os_build);
+			strcpy(key_name, "OSBuildNumber");
+			break;
+		case OSName:
+			strcpy(key_value, os_name);
+			strcpy(key_name, "OSName");
+			break;
+		case OSMajorVersion:
+			strcpy(key_value, os_major);
+			strcpy(key_name, "OSMajorVersion");
+			break;
+		case OSMinorVersion:
+			strcpy(key_value, os_minor);
+			strcpy(key_name, "OSMinorVersion");
+			break;
+		case OSVersion:
+			strcpy(key_value, os_build);
+			strcpy(key_name, "OSVersion");
+			break;
+		case ProcessorArchitecture:
+			strcpy(key_value, processor_arch);
+			strcpy(key_name, "ProcessorArchitecture");
+			break;
+		default:
+			strcpy(key_value, "Unknown Key");
+			/*
+			 * We use a null key name to terminate enumeration.
+			 */
+			strcpy(key_name, "");
+			break;
+		}
+		/*
+		 * Send the value back to the kernel. The response is
+		 * already in the receive buffer. Update the cn_msg header to
+		 * reflect the key value that has been added to the message
+		 */
+
+		incoming_cn_msg->id.idx = CN_KVP_IDX;
+		incoming_cn_msg->id.val = CN_KVP_VAL;
+		incoming_cn_msg->seq = KVP_USER_SET;
+		incoming_cn_msg->ack = 0;
+		incoming_cn_msg->len = sizeof(struct hv_ku_msg);
+
+		len = netlink_send(fd, incoming_cn_msg);
+		if (len < 0) {
+			syslog(LOG_ERR, "net_link send failed; error:%d", len);
+			exit(-1);
+		}
+	}
+
+}
diff --git a/drivers/staging/hv/utils.h b/drivers/staging/hv/utils.h
deleted file mode 100644
index 7c07499..0000000
--- a/drivers/staging/hv/utils.h
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * Copyright (c) 2009, Microsoft Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place - Suite 330, Boston, MA 02111-1307 USA.
- *
- * Authors:
- *   Haiyang Zhang <haiyangz@microsoft.com>
- *   Hank Janssen  <hjanssen@microsoft.com>
- */
-#ifndef __HV_UTILS_H_
-#define __HV_UTILS_H_
-
-/*
- * Common header for Hyper-V ICs
- */
-#define ICMSGTYPE_NEGOTIATE		0
-#define ICMSGTYPE_HEARTBEAT		1
-#define ICMSGTYPE_KVPEXCHANGE		2
-#define ICMSGTYPE_SHUTDOWN		3
-#define ICMSGTYPE_TIMESYNC		4
-#define ICMSGTYPE_VSS			5
-
-#define ICMSGHDRFLAG_TRANSACTION	1
-#define ICMSGHDRFLAG_REQUEST		2
-#define ICMSGHDRFLAG_RESPONSE		4
-
-#define HV_S_OK				0x00000000
-#define HV_E_FAIL			0x80004005
-#define HV_ERROR_NOT_SUPPORTED		0x80070032
-#define HV_ERROR_MACHINE_LOCKED		0x800704F7
-
-struct vmbuspipe_hdr {
-	u32 flags;
-	u32 msgsize;
-} __attribute__((packed));
-
-struct ic_version {
-	u16 major;
-	u16 minor;
-} __attribute__((packed));
-
-struct icmsg_hdr {
-	struct ic_version icverframe;
-	u16 icmsgtype;
-	struct ic_version icvermsg;
-	u16 icmsgsize;
-	u32 status;
-	u8 ictransaction_id;
-	u8 icflags;
-	u8 reserved[2];
-} __attribute__((packed));
-
-struct icmsg_negotiate {
-	u16 icframe_vercnt;
-	u16 icmsg_vercnt;
-	u32 reserved;
-	struct ic_version icversion_data[1]; /* any size array */
-} __attribute__((packed));
-
-struct shutdown_msg_data {
-	u32 reason_code;
-	u32 timeout_seconds;
-	u32 flags;
-	u8  display_message[2048];
-} __attribute__((packed));
-
-struct heartbeat_msg_data {
-	u64 seq_num;
-	u32 reserved[8];
-} __attribute__((packed));
-
-/* Time Sync IC defs */
-#define ICTIMESYNCFLAG_PROBE	0
-#define ICTIMESYNCFLAG_SYNC	1
-#define ICTIMESYNCFLAG_SAMPLE	2
-
-#ifdef __x86_64__
-#define WLTIMEDELTA	116444736000000000L	/* in 100ns unit */
-#else
-#define WLTIMEDELTA	116444736000000000LL
-#endif
-
-struct ictimesync_data{
-	u64 parenttime;
-	u64 childtime;
-	u64 roundtriptime;
-	u8 flags;
-} __attribute__((packed));
-
-/* Index for each IC struct in array hv_cb_utils[] */
-#define HV_SHUTDOWN_MSG		0
-#define HV_TIMESYNC_MSG		1
-#define HV_HEARTBEAT_MSG	2
-
-struct hyperv_service_callback {
-	u8 msg_type;
-	char *log_msg;
-	unsigned char data[16];
-	struct vmbus_channel *channel;
-	void (*callback) (void *context);
-};
-
-extern void prep_negotiate_resp(struct icmsg_hdr *,
-				struct icmsg_negotiate *, u8 *);
-extern void chn_cb_negotiate(void *);
-extern struct hyperv_service_callback hv_cb_utils[];
-
-#endif /* __HV_UTILS_H_ */
diff --git a/drivers/staging/hv/vmbus.h b/drivers/staging/hv/vmbus.h
deleted file mode 100644
index f037871..0000000
--- a/drivers/staging/hv/vmbus.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- *
- * Copyright (c) 2009, Microsoft Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place - Suite 330, Boston, MA 02111-1307 USA.
- *
- * Authors:
- *   Haiyang Zhang <haiyangz@microsoft.com>
- *   Hank Janssen  <hjanssen@microsoft.com>
- *
- */
-
-
-#ifndef _VMBUS_H_
-#define _VMBUS_H_
-
-#include <linux/device.h>
-#include "VmbusApi.h"
-
-struct driver_context {
-	struct hv_guid class_id;
-
-	struct device_driver driver;
-
-	/*
-	 * Use these methods instead of the struct device_driver so 2.6 kernel
-	 * stops complaining
-	 * TODO - fix this!
-	 */
-	int (*probe)(struct device *);
-	int (*remove)(struct device *);
-	void (*shutdown)(struct device *);
-};
-
-struct vm_device {
-	struct work_struct probe_failed_work_item;
-	struct hv_guid class_id;
-	struct hv_guid device_id;
-	int probe_error;
-	struct hv_device device_obj;
-	struct device device;
-};
-
-static inline struct vm_device *to_vm_device(struct hv_device *d)
-{
-	return container_of(d, struct vm_device, device_obj);
-}
-
-static inline struct vm_device *device_to_vm_device(struct device *d)
-{
-	return container_of(d, struct vm_device, device);
-}
-
-static inline struct driver_context *driver_to_driver_context(struct device_driver *d)
-{
-	return container_of(d, struct driver_context, driver);
-}
-
-
-/* Vmbus interface */
-
-int vmbus_child_driver_register(struct driver_context *driver_ctx);
-void vmbus_child_driver_unregister(struct driver_context *driver_ctx);
-void vmbus_get_interface(struct vmbus_channel_interface *interface);
-
-extern struct completion hv_channel_ready;
-
-#endif /* _VMBUS_H_ */
diff --git a/drivers/staging/hv/vmbus_drv.c b/drivers/staging/hv/vmbus_drv.c
index 481f3af..4f915b5 100644
--- a/drivers/staging/hv/vmbus_drv.c
+++ b/drivers/staging/hv/vmbus_drv.c
@@ -17,7 +17,11 @@
  * Authors:
  *   Haiyang Zhang <haiyangz@microsoft.com>
  *   Hank Janssen  <hjanssen@microsoft.com>
+ *   K. Y. Srinivasan <kys@microsoft.com>
+ *
  */
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/device.h>
@@ -27,67 +31,190 @@
 #include <linux/pci.h>
 #include <linux/dmi.h>
 #include <linux/slab.h>
+#include <linux/acpi.h>
+#include <acpi/acpi_bus.h>
 #include <linux/completion.h>
-#include "VersionInfo.h"
-#include "osd.h"
-#include "logging.h"
-#include "vmbus.h"
 
+#include "hyperv.h"
+#include "hyperv_vmbus.h"
 
-/* FIXME! We need to do this dynamically for PIC and APIC system */
-#define VMBUS_IRQ		0x5
-#define VMBUS_IRQ_VECTOR	IRQ5_VECTOR
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35)
+#include <asm/mshyperv.h>
 
-/* Main vmbus driver data structure */
-struct vmbus_driver_context {
-	/* !! These must be the first 2 fields !! */
-	/* FIXME, this is a bug */
-	/* The driver field is not used in here. Instead, the bus field is */
-	/* used to represent the driver */
-	struct driver_context drv_ctx;
-	struct vmbus_driver drv_obj;
+int x86_hyper_ms_hyperv;
+EXPORT_SYMBOL(x86_hyper_ms_hyperv);
 
-	struct bus_type bus;
-	struct tasklet_struct msg_dpc;
-	struct tasklet_struct event_dpc;
+void *x86_hyper = &x86_hyper_ms_hyperv;
+EXPORT_SYMBOL(x86_hyper);
 
-	/* The bus root device */
-	struct vm_device device_ctx;
+struct ms_hyperv_info ms_hyperv = {
+		.features = HV_X64_MSR_TIME_REF_COUNT_AVAILABLE,
 };
+EXPORT_SYMBOL(ms_hyperv);
 
-static int vmbus_match(struct device *device, struct device_driver *driver);
-static int vmbus_probe(struct device *device);
-static int vmbus_remove(struct device *device);
-static void vmbus_shutdown(struct device *device);
-static int vmbus_uevent(struct device *device, struct kobj_uevent_env *env);
-static void vmbus_msg_dpc(unsigned long data);
-static void vmbus_event_dpc(unsigned long data);
+#endif
 
-static irqreturn_t vmbus_isr(int irq, void *dev_id);
+static struct acpi_device  *hv_acpi_dev;
 
-static void vmbus_device_release(struct device *device);
-static void vmbus_bus_release(struct device *device);
-
-static struct hv_device *vmbus_child_device_create(struct hv_guid *type,
-						   struct hv_guid *instance,
-						   void *context);
-static void vmbus_child_device_destroy(struct hv_device *device_obj);
-static int vmbus_child_device_register(struct hv_device *root_device_obj,
-				       struct hv_device *child_device_obj);
-static void vmbus_child_device_unregister(struct hv_device *child_device_obj);
-static void vmbus_child_device_get_info(struct hv_device *device_obj,
-					struct hv_device_info *device_info);
-static ssize_t vmbus_show_device_attr(struct device *dev,
-				      struct device_attribute *dev_attr,
-				      char *buf);
-
+static struct tasklet_struct msg_dpc;
+static struct tasklet_struct event_dpc;
 
 unsigned int vmbus_loglevel = (ALL_MODULES << 16 | INFO_LVL);
 EXPORT_SYMBOL(vmbus_loglevel);
 	/* (ALL_MODULES << 16 | DEBUG_LVL_ENTEREXIT); */
 	/* (((VMBUS | VMBUS_DRV)<<16) | DEBUG_LVL_ENTEREXIT); */
 
-static int vmbus_irq = VMBUS_IRQ;
+static struct completion probe_event;
+static int irq;
+
+static void get_channel_info(struct hv_device *device,
+			     struct hv_device_info *info)
+{
+	struct vmbus_channel_debug_info debug_info;
+
+	if (!device->channel)
+		return;
+
+	vmbus_get_debug_info(device->channel, &debug_info);
+
+	info->chn_id = debug_info.relid;
+	info->chn_state = debug_info.state;
+	memcpy(&info->chn_type, &debug_info.interfacetype,
+	       sizeof(struct hv_guid));
+	memcpy(&info->chn_instance, &debug_info.interface_instance,
+	       sizeof(struct hv_guid));
+
+	info->monitor_id = debug_info.monitorid;
+
+	info->server_monitor_pending = debug_info.servermonitor_pending;
+	info->server_monitor_latency = debug_info.servermonitor_latency;
+	info->server_monitor_conn_id = debug_info.servermonitor_connectionid;
+
+	info->client_monitor_pending = debug_info.clientmonitor_pending;
+	info->client_monitor_latency = debug_info.clientmonitor_latency;
+	info->client_monitor_conn_id = debug_info.clientmonitor_connectionid;
+
+	info->inbound.int_mask = debug_info.inbound.current_interrupt_mask;
+	info->inbound.read_idx = debug_info.inbound.current_read_index;
+	info->inbound.write_idx = debug_info.inbound.current_write_index;
+	info->inbound.bytes_avail_toread =
+		debug_info.inbound.bytes_avail_toread;
+	info->inbound.bytes_avail_towrite =
+		debug_info.inbound.bytes_avail_towrite;
+
+	info->outbound.int_mask =
+		debug_info.outbound.current_interrupt_mask;
+	info->outbound.read_idx = debug_info.outbound.current_read_index;
+	info->outbound.write_idx = debug_info.outbound.current_write_index;
+	info->outbound.bytes_avail_toread =
+		debug_info.outbound.bytes_avail_toread;
+	info->outbound.bytes_avail_towrite =
+		debug_info.outbound.bytes_avail_towrite;
+}
+
+/*
+ * vmbus_show_device_attr - Show the device attribute in sysfs.
+ *
+ * This is invoked when user does a
+ * "cat /sys/bus/vmbus/devices/<busdevice>/<attr name>"
+ */
+static ssize_t vmbus_show_device_attr(struct device *dev,
+				      struct device_attribute *dev_attr,
+				      char *buf)
+{
+	struct hv_device *hv_dev = device_to_hv_device(dev);
+	struct hv_device_info device_info;
+
+	memset(&device_info, 0, sizeof(struct hv_device_info));
+
+	get_channel_info(hv_dev, &device_info);
+
+	if (!strcmp(dev_attr->attr.name, "class_id")) {
+		return sprintf(buf, "{%02x%02x%02x%02x-%02x%02x-%02x%02x-"
+			       "%02x%02x%02x%02x%02x%02x%02x%02x}\n",
+			       device_info.chn_type.data[3],
+			       device_info.chn_type.data[2],
+			       device_info.chn_type.data[1],
+			       device_info.chn_type.data[0],
+			       device_info.chn_type.data[5],
+			       device_info.chn_type.data[4],
+			       device_info.chn_type.data[7],
+			       device_info.chn_type.data[6],
+			       device_info.chn_type.data[8],
+			       device_info.chn_type.data[9],
+			       device_info.chn_type.data[10],
+			       device_info.chn_type.data[11],
+			       device_info.chn_type.data[12],
+			       device_info.chn_type.data[13],
+			       device_info.chn_type.data[14],
+			       device_info.chn_type.data[15]);
+	} else if (!strcmp(dev_attr->attr.name, "device_id")) {
+		return sprintf(buf, "{%02x%02x%02x%02x-%02x%02x-%02x%02x-"
+			       "%02x%02x%02x%02x%02x%02x%02x%02x}\n",
+			       device_info.chn_instance.data[3],
+			       device_info.chn_instance.data[2],
+			       device_info.chn_instance.data[1],
+			       device_info.chn_instance.data[0],
+			       device_info.chn_instance.data[5],
+			       device_info.chn_instance.data[4],
+			       device_info.chn_instance.data[7],
+			       device_info.chn_instance.data[6],
+			       device_info.chn_instance.data[8],
+			       device_info.chn_instance.data[9],
+			       device_info.chn_instance.data[10],
+			       device_info.chn_instance.data[11],
+			       device_info.chn_instance.data[12],
+			       device_info.chn_instance.data[13],
+			       device_info.chn_instance.data[14],
+			       device_info.chn_instance.data[15]);
+	} else if (!strcmp(dev_attr->attr.name, "state")) {
+		return sprintf(buf, "%d\n", device_info.chn_state);
+	} else if (!strcmp(dev_attr->attr.name, "id")) {
+		return sprintf(buf, "%d\n", device_info.chn_id);
+	} else if (!strcmp(dev_attr->attr.name, "out_intr_mask")) {
+		return sprintf(buf, "%d\n", device_info.outbound.int_mask);
+	} else if (!strcmp(dev_attr->attr.name, "out_read_index")) {
+		return sprintf(buf, "%d\n", device_info.outbound.read_idx);
+	} else if (!strcmp(dev_attr->attr.name, "out_write_index")) {
+		return sprintf(buf, "%d\n", device_info.outbound.write_idx);
+	} else if (!strcmp(dev_attr->attr.name, "out_read_bytes_avail")) {
+		return sprintf(buf, "%d\n",
+			       device_info.outbound.bytes_avail_toread);
+	} else if (!strcmp(dev_attr->attr.name, "out_write_bytes_avail")) {
+		return sprintf(buf, "%d\n",
+			       device_info.outbound.bytes_avail_towrite);
+	} else if (!strcmp(dev_attr->attr.name, "in_intr_mask")) {
+		return sprintf(buf, "%d\n", device_info.inbound.int_mask);
+	} else if (!strcmp(dev_attr->attr.name, "in_read_index")) {
+		return sprintf(buf, "%d\n", device_info.inbound.read_idx);
+	} else if (!strcmp(dev_attr->attr.name, "in_write_index")) {
+		return sprintf(buf, "%d\n", device_info.inbound.write_idx);
+	} else if (!strcmp(dev_attr->attr.name, "in_read_bytes_avail")) {
+		return sprintf(buf, "%d\n",
+			       device_info.inbound.bytes_avail_toread);
+	} else if (!strcmp(dev_attr->attr.name, "in_write_bytes_avail")) {
+		return sprintf(buf, "%d\n",
+			       device_info.inbound.bytes_avail_towrite);
+	} else if (!strcmp(dev_attr->attr.name, "monitor_id")) {
+		return sprintf(buf, "%d\n", device_info.monitor_id);
+	} else if (!strcmp(dev_attr->attr.name, "server_monitor_pending")) {
+		return sprintf(buf, "%d\n", device_info.server_monitor_pending);
+	} else if (!strcmp(dev_attr->attr.name, "server_monitor_latency")) {
+		return sprintf(buf, "%d\n", device_info.server_monitor_latency);
+	} else if (!strcmp(dev_attr->attr.name, "server_monitor_conn_id")) {
+		return sprintf(buf, "%d\n",
+			       device_info.server_monitor_conn_id);
+	} else if (!strcmp(dev_attr->attr.name, "client_monitor_pending")) {
+		return sprintf(buf, "%d\n", device_info.client_monitor_pending);
+	} else if (!strcmp(dev_attr->attr.name, "client_monitor_latency")) {
+		return sprintf(buf, "%d\n", device_info.client_monitor_latency);
+	} else if (!strcmp(dev_attr->attr.name, "client_monitor_conn_id")) {
+		return sprintf(buf, "%d\n",
+			       device_info.client_monitor_conn_id);
+	} else {
+		return 0;
+	}
+}
 
 /* Set up per device attributes in /sys/bus/vmbus/devices/<bus device> */
 static struct device_attribute vmbus_device_attrs[] = {
@@ -119,485 +246,6 @@
 	__ATTR_NULL
 };
 
-/* The one and only one */
-static struct vmbus_driver_context g_vmbus_drv = {
-	.bus.name =		"vmbus",
-	.bus.match =		vmbus_match,
-	.bus.shutdown =		vmbus_shutdown,
-	.bus.remove =		vmbus_remove,
-	.bus.probe =		vmbus_probe,
-	.bus.uevent =		vmbus_uevent,
-	.bus.dev_attrs =	vmbus_device_attrs,
-};
-
-/*
- * vmbus_show_device_attr - Show the device attribute in sysfs.
- *
- * This is invoked when user does a
- * "cat /sys/bus/vmbus/devices/<busdevice>/<attr name>"
- */
-static ssize_t vmbus_show_device_attr(struct device *dev,
-				      struct device_attribute *dev_attr,
-				      char *buf)
-{
-	struct vm_device *device_ctx = device_to_vm_device(dev);
-	struct hv_device_info device_info;
-
-	memset(&device_info, 0, sizeof(struct hv_device_info));
-
-	vmbus_child_device_get_info(&device_ctx->device_obj, &device_info);
-
-	if (!strcmp(dev_attr->attr.name, "class_id")) {
-		return sprintf(buf, "{%02x%02x%02x%02x-%02x%02x-%02x%02x-"
-			       "%02x%02x%02x%02x%02x%02x%02x%02x}\n",
-			       device_info.ChannelType.data[3],
-			       device_info.ChannelType.data[2],
-			       device_info.ChannelType.data[1],
-			       device_info.ChannelType.data[0],
-			       device_info.ChannelType.data[5],
-			       device_info.ChannelType.data[4],
-			       device_info.ChannelType.data[7],
-			       device_info.ChannelType.data[6],
-			       device_info.ChannelType.data[8],
-			       device_info.ChannelType.data[9],
-			       device_info.ChannelType.data[10],
-			       device_info.ChannelType.data[11],
-			       device_info.ChannelType.data[12],
-			       device_info.ChannelType.data[13],
-			       device_info.ChannelType.data[14],
-			       device_info.ChannelType.data[15]);
-	} else if (!strcmp(dev_attr->attr.name, "device_id")) {
-		return sprintf(buf, "{%02x%02x%02x%02x-%02x%02x-%02x%02x-"
-			       "%02x%02x%02x%02x%02x%02x%02x%02x}\n",
-			       device_info.ChannelInstance.data[3],
-			       device_info.ChannelInstance.data[2],
-			       device_info.ChannelInstance.data[1],
-			       device_info.ChannelInstance.data[0],
-			       device_info.ChannelInstance.data[5],
-			       device_info.ChannelInstance.data[4],
-			       device_info.ChannelInstance.data[7],
-			       device_info.ChannelInstance.data[6],
-			       device_info.ChannelInstance.data[8],
-			       device_info.ChannelInstance.data[9],
-			       device_info.ChannelInstance.data[10],
-			       device_info.ChannelInstance.data[11],
-			       device_info.ChannelInstance.data[12],
-			       device_info.ChannelInstance.data[13],
-			       device_info.ChannelInstance.data[14],
-			       device_info.ChannelInstance.data[15]);
-	} else if (!strcmp(dev_attr->attr.name, "state")) {
-		return sprintf(buf, "%d\n", device_info.ChannelState);
-	} else if (!strcmp(dev_attr->attr.name, "id")) {
-		return sprintf(buf, "%d\n", device_info.ChannelId);
-	} else if (!strcmp(dev_attr->attr.name, "out_intr_mask")) {
-		return sprintf(buf, "%d\n", device_info.Outbound.InterruptMask);
-	} else if (!strcmp(dev_attr->attr.name, "out_read_index")) {
-		return sprintf(buf, "%d\n", device_info.Outbound.ReadIndex);
-	} else if (!strcmp(dev_attr->attr.name, "out_write_index")) {
-		return sprintf(buf, "%d\n", device_info.Outbound.WriteIndex);
-	} else if (!strcmp(dev_attr->attr.name, "out_read_bytes_avail")) {
-		return sprintf(buf, "%d\n",
-			       device_info.Outbound.BytesAvailToRead);
-	} else if (!strcmp(dev_attr->attr.name, "out_write_bytes_avail")) {
-		return sprintf(buf, "%d\n",
-			       device_info.Outbound.BytesAvailToWrite);
-	} else if (!strcmp(dev_attr->attr.name, "in_intr_mask")) {
-		return sprintf(buf, "%d\n", device_info.Inbound.InterruptMask);
-	} else if (!strcmp(dev_attr->attr.name, "in_read_index")) {
-		return sprintf(buf, "%d\n", device_info.Inbound.ReadIndex);
-	} else if (!strcmp(dev_attr->attr.name, "in_write_index")) {
-		return sprintf(buf, "%d\n", device_info.Inbound.WriteIndex);
-	} else if (!strcmp(dev_attr->attr.name, "in_read_bytes_avail")) {
-		return sprintf(buf, "%d\n",
-			       device_info.Inbound.BytesAvailToRead);
-	} else if (!strcmp(dev_attr->attr.name, "in_write_bytes_avail")) {
-		return sprintf(buf, "%d\n",
-			       device_info.Inbound.BytesAvailToWrite);
-	} else if (!strcmp(dev_attr->attr.name, "monitor_id")) {
-		return sprintf(buf, "%d\n", device_info.MonitorId);
-	} else if (!strcmp(dev_attr->attr.name, "server_monitor_pending")) {
-		return sprintf(buf, "%d\n", device_info.ServerMonitorPending);
-	} else if (!strcmp(dev_attr->attr.name, "server_monitor_latency")) {
-		return sprintf(buf, "%d\n", device_info.ServerMonitorLatency);
-	} else if (!strcmp(dev_attr->attr.name, "server_monitor_conn_id")) {
-		return sprintf(buf, "%d\n",
-			       device_info.ServerMonitorConnectionId);
-	} else if (!strcmp(dev_attr->attr.name, "client_monitor_pending")) {
-		return sprintf(buf, "%d\n", device_info.ClientMonitorPending);
-	} else if (!strcmp(dev_attr->attr.name, "client_monitor_latency")) {
-		return sprintf(buf, "%d\n", device_info.ClientMonitorLatency);
-	} else if (!strcmp(dev_attr->attr.name, "client_monitor_conn_id")) {
-		return sprintf(buf, "%d\n",
-			       device_info.ClientMonitorConnectionId);
-	} else {
-		return 0;
-	}
-}
-
-/*
- * vmbus_bus_init -Main vmbus driver initialization routine.
- *
- * Here, we
- *	- initialize the vmbus driver context
- *	- setup various driver entry points
- *	- invoke the vmbus hv main init routine
- *	- get the irq resource
- *	- invoke the vmbus to add the vmbus root device
- *	- setup the vmbus root device
- *	- retrieve the channel offers
- */
-static int vmbus_bus_init(int (*drv_init)(struct hv_driver *drv))
-{
-	struct vmbus_driver_context *vmbus_drv_ctx = &g_vmbus_drv;
-	struct vmbus_driver *vmbus_drv_obj = &g_vmbus_drv.drv_obj;
-	struct vm_device *dev_ctx = &g_vmbus_drv.device_ctx;
-	int ret;
-	unsigned int vector;
-
-	/*
-	 * Set this up to allow lower layer to callback to add/remove child
-	 * devices on the bus
-	 */
-	vmbus_drv_obj->OnChildDeviceCreate = vmbus_child_device_create;
-	vmbus_drv_obj->OnChildDeviceDestroy = vmbus_child_device_destroy;
-	vmbus_drv_obj->OnChildDeviceAdd = vmbus_child_device_register;
-	vmbus_drv_obj->OnChildDeviceRemove = vmbus_child_device_unregister;
-
-	/* Call to bus driver to initialize */
-	ret = drv_init(&vmbus_drv_obj->Base);
-	if (ret != 0) {
-		DPRINT_ERR(VMBUS_DRV, "Unable to initialize vmbus (%d)", ret);
-		goto cleanup;
-	}
-
-	/* Sanity checks */
-	if (!vmbus_drv_obj->Base.OnDeviceAdd) {
-		DPRINT_ERR(VMBUS_DRV, "OnDeviceAdd() routine not set");
-		ret = -1;
-		goto cleanup;
-	}
-
-	vmbus_drv_ctx->bus.name = vmbus_drv_obj->Base.name;
-
-	/* Initialize the bus context */
-	tasklet_init(&vmbus_drv_ctx->msg_dpc, vmbus_msg_dpc,
-		     (unsigned long)vmbus_drv_obj);
-	tasklet_init(&vmbus_drv_ctx->event_dpc, vmbus_event_dpc,
-		     (unsigned long)vmbus_drv_obj);
-
-	/* Now, register the bus driver with LDM */
-	ret = bus_register(&vmbus_drv_ctx->bus);
-	if (ret) {
-		ret = -1;
-		goto cleanup;
-	}
-
-	/* Get the interrupt resource */
-	ret = request_irq(vmbus_irq, vmbus_isr, IRQF_SAMPLE_RANDOM,
-			  vmbus_drv_obj->Base.name, NULL);
-
-	if (ret != 0) {
-		DPRINT_ERR(VMBUS_DRV, "ERROR - Unable to request IRQ %d",
-			   vmbus_irq);
-
-		bus_unregister(&vmbus_drv_ctx->bus);
-
-		ret = -1;
-		goto cleanup;
-	}
-	vector = VMBUS_IRQ_VECTOR;
-
-	DPRINT_INFO(VMBUS_DRV, "irq 0x%x vector 0x%x", vmbus_irq, vector);
-
-	/* Call to bus driver to add the root device */
-	memset(dev_ctx, 0, sizeof(struct vm_device));
-
-	ret = vmbus_drv_obj->Base.OnDeviceAdd(&dev_ctx->device_obj, &vector);
-	if (ret != 0) {
-		DPRINT_ERR(VMBUS_DRV,
-			   "ERROR - Unable to add vmbus root device");
-
-		free_irq(vmbus_irq, NULL);
-
-		bus_unregister(&vmbus_drv_ctx->bus);
-
-		ret = -1;
-		goto cleanup;
-	}
-	/* strcpy(dev_ctx->device.bus_id, dev_ctx->device_obj.name); */
-	dev_set_name(&dev_ctx->device, "vmbus_0_0");
-	memcpy(&dev_ctx->class_id, &dev_ctx->device_obj.deviceType,
-		sizeof(struct hv_guid));
-	memcpy(&dev_ctx->device_id, &dev_ctx->device_obj.deviceInstance,
-		sizeof(struct hv_guid));
-
-	/* No need to bind a driver to the root device. */
-	dev_ctx->device.parent = NULL;
-	/* NULL; vmbus_remove() does not get invoked */
-	dev_ctx->device.bus = &vmbus_drv_ctx->bus;
-
-	/* Setup the device dispatch table */
-	dev_ctx->device.release = vmbus_bus_release;
-
-	/* Setup the bus as root device */
-	ret = device_register(&dev_ctx->device);
-	if (ret) {
-		DPRINT_ERR(VMBUS_DRV,
-			   "ERROR - Unable to register vmbus root device");
-
-		free_irq(vmbus_irq, NULL);
-		bus_unregister(&vmbus_drv_ctx->bus);
-
-		ret = -1;
-		goto cleanup;
-	}
-
-
-	vmbus_drv_obj->GetChannelOffers();
-
-	wait_for_completion(&hv_channel_ready);
-
-cleanup:
-	return ret;
-}
-
-/*
- * vmbus_bus_exit - Terminate the vmbus driver.
- *
- * This routine is opposite of vmbus_bus_init()
- */
-static void vmbus_bus_exit(void)
-{
-	struct vmbus_driver *vmbus_drv_obj = &g_vmbus_drv.drv_obj;
-	struct vmbus_driver_context *vmbus_drv_ctx = &g_vmbus_drv;
-
-	struct vm_device *dev_ctx = &g_vmbus_drv.device_ctx;
-
-	/* Remove the root device */
-	if (vmbus_drv_obj->Base.OnDeviceRemove)
-		vmbus_drv_obj->Base.OnDeviceRemove(&dev_ctx->device_obj);
-
-	if (vmbus_drv_obj->Base.OnCleanup)
-		vmbus_drv_obj->Base.OnCleanup(&vmbus_drv_obj->Base);
-
-	/* Unregister the root bus device */
-	device_unregister(&dev_ctx->device);
-
-	bus_unregister(&vmbus_drv_ctx->bus);
-
-	free_irq(vmbus_irq, NULL);
-
-	tasklet_kill(&vmbus_drv_ctx->msg_dpc);
-	tasklet_kill(&vmbus_drv_ctx->event_dpc);
-}
-
-
-/**
- * vmbus_child_driver_register() - Register a vmbus's child driver
- * @driver_ctx:        Pointer to driver structure you want to register
- *
- * @driver_ctx is of type &struct driver_context
- *
- * Registers the given driver with Linux through the 'driver_register()' call
- * And sets up the hyper-v vmbus handling for this driver.
- * It will return the state of the 'driver_register()' call.
- *
- * Mainly used by Hyper-V drivers.
- */
-int vmbus_child_driver_register(struct driver_context *driver_ctx)
-{
-	struct vmbus_driver *vmbus_drv_obj = &g_vmbus_drv.drv_obj;
-	int ret;
-
-	DPRINT_INFO(VMBUS_DRV, "child driver (%p) registering - name %s",
-		    driver_ctx, driver_ctx->driver.name);
-
-	/* The child driver on this vmbus */
-	driver_ctx->driver.bus = &g_vmbus_drv.bus;
-
-	ret = driver_register(&driver_ctx->driver);
-
-	vmbus_drv_obj->GetChannelOffers();
-
-	return ret;
-}
-EXPORT_SYMBOL(vmbus_child_driver_register);
-
-/**
- * vmbus_child_driver_unregister() - Unregister a vmbus's child driver
- * @driver_ctx:        Pointer to driver structure you want to un-register
- *
- * @driver_ctx is of type &struct driver_context
- *
- * Un-register the given driver with Linux through the 'driver_unregister()'
- * call. And ungegisters the driver from the Hyper-V vmbus handler.
- *
- * Mainly used by Hyper-V drivers.
- */
-void vmbus_child_driver_unregister(struct driver_context *driver_ctx)
-{
-	DPRINT_INFO(VMBUS_DRV, "child driver (%p) unregistering - name %s",
-		    driver_ctx, driver_ctx->driver.name);
-
-	driver_unregister(&driver_ctx->driver);
-
-	driver_ctx->driver.bus = NULL;
-}
-EXPORT_SYMBOL(vmbus_child_driver_unregister);
-
-/**
- * vmbus_get_interface() - Get the vmbus channel interface.
- * @interface: Pointer to channel interface structure
- *
- * Get the Hyper-V channel used for the driver.
- *
- * @interface is of type &struct vmbus_channel_interface
- * This is invoked by child/client driver that sits above vmbus.
- *
- * Mainly used by Hyper-V drivers.
- */
-void vmbus_get_interface(struct vmbus_channel_interface *interface)
-{
-	struct vmbus_driver *vmbus_drv_obj = &g_vmbus_drv.drv_obj;
-
-	vmbus_drv_obj->GetChannelInterface(interface);
-}
-EXPORT_SYMBOL(vmbus_get_interface);
-
-/*
- * vmbus_child_device_get_info - Get the vmbus child device info.
- *
- * This is invoked to display various device attributes in sysfs.
- */
-static void vmbus_child_device_get_info(struct hv_device *device_obj,
-					struct hv_device_info *device_info)
-{
-	struct vmbus_driver *vmbus_drv_obj = &g_vmbus_drv.drv_obj;
-
-	vmbus_drv_obj->GetChannelInfo(device_obj, device_info);
-}
-
-/*
- * vmbus_child_device_create - Creates and registers a new child device
- * on the vmbus.
- */
-static struct hv_device *vmbus_child_device_create(struct hv_guid *type,
-						   struct hv_guid *instance,
-						   void *context)
-{
-	struct vm_device *child_device_ctx;
-	struct hv_device *child_device_obj;
-
-	/* Allocate the new child device */
-	child_device_ctx = kzalloc(sizeof(struct vm_device), GFP_KERNEL);
-	if (!child_device_ctx) {
-		DPRINT_ERR(VMBUS_DRV,
-			"unable to allocate device_context for child device");
-		return NULL;
-	}
-
-	DPRINT_DBG(VMBUS_DRV, "child device (%p) allocated - "
-		"type {%02x%02x%02x%02x-%02x%02x-%02x%02x-"
-		"%02x%02x%02x%02x%02x%02x%02x%02x},"
-		"id {%02x%02x%02x%02x-%02x%02x-%02x%02x-"
-		"%02x%02x%02x%02x%02x%02x%02x%02x}",
-		&child_device_ctx->device,
-		type->data[3], type->data[2], type->data[1], type->data[0],
-		type->data[5], type->data[4], type->data[7], type->data[6],
-		type->data[8], type->data[9], type->data[10], type->data[11],
-		type->data[12], type->data[13], type->data[14], type->data[15],
-		instance->data[3], instance->data[2],
-		instance->data[1], instance->data[0],
-		instance->data[5], instance->data[4],
-		instance->data[7], instance->data[6],
-		instance->data[8], instance->data[9],
-		instance->data[10], instance->data[11],
-		instance->data[12], instance->data[13],
-		instance->data[14], instance->data[15]);
-
-	child_device_obj = &child_device_ctx->device_obj;
-	child_device_obj->context = context;
-	memcpy(&child_device_obj->deviceType, type, sizeof(struct hv_guid));
-	memcpy(&child_device_obj->deviceInstance, instance,
-	       sizeof(struct hv_guid));
-
-	memcpy(&child_device_ctx->class_id, type, sizeof(struct hv_guid));
-	memcpy(&child_device_ctx->device_id, instance, sizeof(struct hv_guid));
-
-	return child_device_obj;
-}
-
-/*
- * vmbus_child_device_register - Register the child device on the specified bus
- */
-static int vmbus_child_device_register(struct hv_device *root_device_obj,
-				       struct hv_device *child_device_obj)
-{
-	int ret = 0;
-	struct vm_device *root_device_ctx =
-				to_vm_device(root_device_obj);
-	struct vm_device *child_device_ctx =
-				to_vm_device(child_device_obj);
-	static atomic_t device_num = ATOMIC_INIT(0);
-
-	DPRINT_DBG(VMBUS_DRV, "child device (%p) registering",
-		   child_device_ctx);
-
-	/* Set the device name. Otherwise, device_register() will fail. */
-	dev_set_name(&child_device_ctx->device, "vmbus_0_%d",
-		     atomic_inc_return(&device_num));
-
-	/* The new device belongs to this bus */
-	child_device_ctx->device.bus = &g_vmbus_drv.bus; /* device->dev.bus; */
-	child_device_ctx->device.parent = &root_device_ctx->device;
-	child_device_ctx->device.release = vmbus_device_release;
-
-	/*
-	 * Register with the LDM. This will kick off the driver/device
-	 * binding...which will eventually call vmbus_match() and vmbus_probe()
-	 */
-	ret = device_register(&child_device_ctx->device);
-
-	/* vmbus_probe() error does not get propergate to device_register(). */
-	ret = child_device_ctx->probe_error;
-
-	if (ret)
-		DPRINT_ERR(VMBUS_DRV, "unable to register child device (%p)",
-			   &child_device_ctx->device);
-	else
-		DPRINT_INFO(VMBUS_DRV, "child device (%p) registered",
-			    &child_device_ctx->device);
-
-	return ret;
-}
-
-/*
- * vmbus_child_device_unregister - Remove the specified child device
- * from the vmbus.
- */
-static void vmbus_child_device_unregister(struct hv_device *device_obj)
-{
-	struct vm_device *device_ctx = to_vm_device(device_obj);
-
-	DPRINT_INFO(VMBUS_DRV, "unregistering child device (%p)",
-		    &device_ctx->device);
-
-	/*
-	 * Kick off the process of unregistering the device.
-	 * This will call vmbus_remove() and eventually vmbus_device_release()
-	 */
-	device_unregister(&device_ctx->device);
-
-	DPRINT_INFO(VMBUS_DRV, "child device (%p) unregistered",
-		    &device_ctx->device);
-}
-
-/*
- * vmbus_child_device_destroy - Destroy the specified child device on the vmbus.
- */
-static void vmbus_child_device_destroy(struct hv_device *device_obj)
-{
-}
 
 /*
  * vmbus_uevent - add uevent for our device
@@ -608,43 +256,28 @@
  */
 static int vmbus_uevent(struct device *device, struct kobj_uevent_env *env)
 {
-	struct vm_device *device_ctx = device_to_vm_device(device);
+	struct hv_device *dev = device_to_hv_device(device);
 	int ret;
 
-	DPRINT_INFO(VMBUS_DRV, "generating uevent - VMBUS_DEVICE_CLASS_GUID={"
-		    "%02x%02x%02x%02x-%02x%02x-%02x%02x-"
-		    "%02x%02x%02x%02x%02x%02x%02x%02x}",
-		    device_ctx->class_id.data[3], device_ctx->class_id.data[2],
-		    device_ctx->class_id.data[1], device_ctx->class_id.data[0],
-		    device_ctx->class_id.data[5], device_ctx->class_id.data[4],
-		    device_ctx->class_id.data[7], device_ctx->class_id.data[6],
-		    device_ctx->class_id.data[8], device_ctx->class_id.data[9],
-		    device_ctx->class_id.data[10],
-		    device_ctx->class_id.data[11],
-		    device_ctx->class_id.data[12],
-		    device_ctx->class_id.data[13],
-		    device_ctx->class_id.data[14],
-		    device_ctx->class_id.data[15]);
-
 	ret = add_uevent_var(env, "VMBUS_DEVICE_CLASS_GUID={"
 			     "%02x%02x%02x%02x-%02x%02x-%02x%02x-"
 			     "%02x%02x%02x%02x%02x%02x%02x%02x}",
-			     device_ctx->class_id.data[3],
-			     device_ctx->class_id.data[2],
-			     device_ctx->class_id.data[1],
-			     device_ctx->class_id.data[0],
-			     device_ctx->class_id.data[5],
-			     device_ctx->class_id.data[4],
-			     device_ctx->class_id.data[7],
-			     device_ctx->class_id.data[6],
-			     device_ctx->class_id.data[8],
-			     device_ctx->class_id.data[9],
-			     device_ctx->class_id.data[10],
-			     device_ctx->class_id.data[11],
-			     device_ctx->class_id.data[12],
-			     device_ctx->class_id.data[13],
-			     device_ctx->class_id.data[14],
-			     device_ctx->class_id.data[15]);
+			     dev->dev_type.data[3],
+			     dev->dev_type.data[2],
+			     dev->dev_type.data[1],
+			     dev->dev_type.data[0],
+			     dev->dev_type.data[5],
+			     dev->dev_type.data[4],
+			     dev->dev_type.data[7],
+			     dev->dev_type.data[6],
+			     dev->dev_type.data[8],
+			     dev->dev_type.data[9],
+			     dev->dev_type.data[10],
+			     dev->dev_type.data[11],
+			     dev->dev_type.data[12],
+			     dev->dev_type.data[13],
+			     dev->dev_type.data[14],
+			     dev->dev_type.data[15]);
 
 	if (ret)
 		return ret;
@@ -652,106 +285,66 @@
 	ret = add_uevent_var(env, "VMBUS_DEVICE_DEVICE_GUID={"
 			     "%02x%02x%02x%02x-%02x%02x-%02x%02x-"
 			     "%02x%02x%02x%02x%02x%02x%02x%02x}",
-			     device_ctx->device_id.data[3],
-			     device_ctx->device_id.data[2],
-			     device_ctx->device_id.data[1],
-			     device_ctx->device_id.data[0],
-			     device_ctx->device_id.data[5],
-			     device_ctx->device_id.data[4],
-			     device_ctx->device_id.data[7],
-			     device_ctx->device_id.data[6],
-			     device_ctx->device_id.data[8],
-			     device_ctx->device_id.data[9],
-			     device_ctx->device_id.data[10],
-			     device_ctx->device_id.data[11],
-			     device_ctx->device_id.data[12],
-			     device_ctx->device_id.data[13],
-			     device_ctx->device_id.data[14],
-			     device_ctx->device_id.data[15]);
+			     dev->dev_instance.data[3],
+			     dev->dev_instance.data[2],
+			     dev->dev_instance.data[1],
+			     dev->dev_instance.data[0],
+			     dev->dev_instance.data[5],
+			     dev->dev_instance.data[4],
+			     dev->dev_instance.data[7],
+			     dev->dev_instance.data[6],
+			     dev->dev_instance.data[8],
+			     dev->dev_instance.data[9],
+			     dev->dev_instance.data[10],
+			     dev->dev_instance.data[11],
+			     dev->dev_instance.data[12],
+			     dev->dev_instance.data[13],
+			     dev->dev_instance.data[14],
+			     dev->dev_instance.data[15]);
 	if (ret)
 		return ret;
 
 	return 0;
 }
 
+
 /*
  * vmbus_match - Attempt to match the specified device to the specified driver
  */
 static int vmbus_match(struct device *device, struct device_driver *driver)
 {
 	int match = 0;
-	struct driver_context *driver_ctx = driver_to_driver_context(driver);
-	struct vm_device *device_ctx = device_to_vm_device(device);
+	struct hv_driver *drv = drv_to_hv_drv(driver);
+	struct hv_device *hv_dev = device_to_hv_device(device);
 
 	/* We found our driver ? */
-	if (memcmp(&device_ctx->class_id, &driver_ctx->class_id,
-		   sizeof(struct hv_guid)) == 0) {
-		/*
-		 * !! NOTE: The driver_ctx is not a vmbus_drv_ctx. We typecast
-		 * it here to access the struct hv_driver field
-		 */
-		struct vmbus_driver_context *vmbus_drv_ctx =
-			(struct vmbus_driver_context *)driver_ctx;
-
-		device_ctx->device_obj.Driver = &vmbus_drv_ctx->drv_obj.Base;
-		DPRINT_INFO(VMBUS_DRV,
-			    "device object (%p) set to driver object (%p)",
-			    &device_ctx->device_obj,
-			    device_ctx->device_obj.Driver);
-
+	if (memcmp(&hv_dev->dev_type, &drv->dev_type,
+		   sizeof(struct hv_guid)) == 0)
 		match = 1;
-	}
+
 	return match;
 }
 
 /*
- * vmbus_probe_failed_cb - Callback when a driver probe failed in vmbus_probe()
- *
- * We need a callback because we cannot invoked device_unregister() inside
- * vmbus_probe() since vmbus_probe() may be invoked inside device_register()
- * i.e. we cannot call device_unregister() inside device_register()
- */
-static void vmbus_probe_failed_cb(struct work_struct *context)
-{
-	struct vm_device *device_ctx = (struct vm_device *)context;
-
-	/*
-	 * Kick off the process of unregistering the device.
-	 * This will call vmbus_remove() and eventually vmbus_device_release()
-	 */
-	device_unregister(&device_ctx->device);
-
-	/* put_device(&device_ctx->device); */
-}
-
-/*
  * vmbus_probe - Add the new vmbus's child device
  */
 static int vmbus_probe(struct device *child_device)
 {
 	int ret = 0;
-	struct driver_context *driver_ctx =
-			driver_to_driver_context(child_device->driver);
-	struct vm_device *device_ctx =
-			device_to_vm_device(child_device);
+	struct hv_driver *drv =
+			drv_to_hv_drv(child_device->driver);
+	struct hv_device *dev = device_to_hv_device(child_device);
 
-	/* Let the specific open-source driver handles the probe if it can */
-	if (driver_ctx->probe) {
-		ret = device_ctx->probe_error = driver_ctx->probe(child_device);
-		if (ret != 0) {
-			DPRINT_ERR(VMBUS_DRV, "probe() failed for device %s "
-				   "(%p) on driver %s (%d)...",
-				   dev_name(child_device), child_device,
-				   child_device->driver->name, ret);
+	if (drv->probe) {
+		ret = drv->probe(dev);
+		if (ret != 0)
+			pr_err("probe failed for device %s (%d)\n",
+			       dev_name(child_device), ret);
 
-			INIT_WORK(&device_ctx->probe_failed_work_item,
-				  vmbus_probe_failed_cb);
-			schedule_work(&device_ctx->probe_failed_work_item);
-		}
 	} else {
-		DPRINT_ERR(VMBUS_DRV, "probe() method not set for driver - %s",
-			   child_device->driver->name);
-		ret = -1;
+		pr_err("probe not set for driver %s\n",
+		       dev_name(child_device));
+		ret = -ENODEV;
 	}
 	return ret;
 }
@@ -762,134 +355,176 @@
 static int vmbus_remove(struct device *child_device)
 {
 	int ret;
-	struct driver_context *driver_ctx;
+	struct hv_driver *drv;
 
-	/* Special case root bus device */
-	if (child_device->parent == NULL) {
-		/*
-		 * No-op since it is statically defined and handle in
-		 * vmbus_bus_exit()
-		 */
-		return 0;
-	}
+	struct hv_device *dev = device_to_hv_device(child_device);
 
 	if (child_device->driver) {
-		driver_ctx = driver_to_driver_context(child_device->driver);
+		drv = drv_to_hv_drv(child_device->driver);
 
-		/*
-		 * Let the specific open-source driver handles the removal if
-		 * it can
-		 */
-		if (driver_ctx->remove) {
-			ret = driver_ctx->remove(child_device);
+		if (drv->remove) {
+			ret = drv->remove(dev);
 		} else {
-			DPRINT_ERR(VMBUS_DRV,
-				   "remove() method not set for driver - %s",
-				   child_device->driver->name);
-			ret = -1;
+			pr_err("remove not set for driver %s\n",
+				dev_name(child_device));
+			ret = -ENODEV;
 		}
 	}
 
 	return 0;
 }
 
+
 /*
  * vmbus_shutdown - Shutdown a vmbus device
  */
 static void vmbus_shutdown(struct device *child_device)
 {
-	struct driver_context *driver_ctx;
+	struct hv_driver *drv;
+	struct hv_device *dev = device_to_hv_device(child_device);
 
-	/* Special case root bus device */
-	if (child_device->parent == NULL) {
-		/*
-		 * No-op since it is statically defined and handle in
-		 * vmbus_bus_exit()
-		 */
-		return;
-	}
 
 	/* The device may not be attached yet */
 	if (!child_device->driver)
 		return;
 
-	driver_ctx = driver_to_driver_context(child_device->driver);
+	drv = drv_to_hv_drv(child_device->driver);
 
-	/* Let the specific open-source driver handles the removal if it can */
-	if (driver_ctx->shutdown)
-		driver_ctx->shutdown(child_device);
+	if (drv->shutdown)
+		drv->shutdown(dev);
 
 	return;
 }
 
-/*
- * vmbus_bus_release - Final callback release of the vmbus root device
- */
-static void vmbus_bus_release(struct device *device)
-{
-	/* FIXME */
-	/* Empty release functions are a bug, or a major sign
-	 * of a problem design, this MUST BE FIXED! */
-	dev_err(device, "%s needs to be fixed!\n", __func__);
-	WARN_ON(1);
-}
 
 /*
  * vmbus_device_release - Final callback release of the vmbus child device
  */
 static void vmbus_device_release(struct device *device)
 {
-	struct vm_device *device_ctx = device_to_vm_device(device);
+	struct hv_device *hv_dev = device_to_hv_device(device);
 
-	/* vmbus_child_device_destroy(&device_ctx->device_obj); */
-	kfree(device_ctx);
+	kfree(hv_dev);
 
-	/* !!DO NOT REFERENCE device_ctx anymore at this point!! */
+}
+
+/* The one and only one */
+static struct bus_type  hv_bus = {
+	.name =		"vmbus",
+	.match =		vmbus_match,
+	.shutdown =		vmbus_shutdown,
+	.remove =		vmbus_remove,
+	.probe =		vmbus_probe,
+	.uevent =		vmbus_uevent,
+	.dev_attrs =	vmbus_device_attrs,
+};
+
+static const char *driver_name = "hyperv";
+
+
+struct onmessage_work_context {
+	struct work_struct work;
+	struct hv_message msg;
+};
+
+static void vmbus_onmessage_work(struct work_struct *work)
+{
+	struct onmessage_work_context *ctx;
+
+	ctx = container_of(work, struct onmessage_work_context,
+			   work);
+	vmbus_onmessage(&ctx->msg);
+	kfree(ctx);
 }
 
 /*
- * vmbus_msg_dpc - Tasklet routine to handle hypervisor messages
+ * vmbus_on_msg_dpc - DPC routine to handle messages from the hypervisior
  */
-static void vmbus_msg_dpc(unsigned long data)
+static void vmbus_on_msg_dpc(unsigned long data)
 {
-	struct vmbus_driver *vmbus_drv_obj = (struct vmbus_driver *)data;
+	int cpu = smp_processor_id();
+	void *page_addr = hv_context.synic_message_page[cpu];
+	struct hv_message *msg = (struct hv_message *)page_addr +
+				  VMBUS_MESSAGE_SINT;
+	struct onmessage_work_context *ctx;
 
-	/* ASSERT(vmbus_drv_obj->OnMsgDpc != NULL); */
+	while (1) {
+		if (msg->header.message_type == HVMSG_NONE) {
+			/* no msg */
+			break;
+		} else {
+			ctx = kmalloc(sizeof(*ctx), GFP_ATOMIC);
+			if (ctx == NULL)
+				continue;
+			INIT_WORK(&ctx->work, vmbus_onmessage_work);
+			memcpy(&ctx->msg, msg, sizeof(*msg));
+			queue_work(vmbus_connection.work_queue, &ctx->work);
+		}
 
-	/* Call to bus driver to handle interrupt */
-	vmbus_drv_obj->OnMsgDpc(&vmbus_drv_obj->Base);
+		msg->header.message_type = HVMSG_NONE;
+
+		/*
+		 * Make sure the write to MessageType (ie set to
+		 * HVMSG_NONE) happens before we read the
+		 * MessagePending and EOMing. Otherwise, the EOMing
+		 * will not deliver any more messages since there is
+		 * no empty slot
+		 */
+		smp_mb();
+
+		if (msg->header.message_flags.msg_pending) {
+			/*
+			 * This will cause message queue rescan to
+			 * possibly deliver another msg from the
+			 * hypervisor
+			 */
+			wrmsrl(HV_X64_MSR_EOM, 0);
+		}
+	}
 }
 
 /*
- * vmbus_msg_dpc - Tasklet routine to handle hypervisor events
+ * vmbus_on_isr - ISR routine
  */
-static void vmbus_event_dpc(unsigned long data)
+static int vmbus_on_isr(void)
 {
-	struct vmbus_driver *vmbus_drv_obj = (struct vmbus_driver *)data;
+	int ret = 0;
+	int cpu = smp_processor_id();
+	void *page_addr;
+	struct hv_message *msg;
+	union hv_synic_event_flags *event;
 
-	/* ASSERT(vmbus_drv_obj->OnEventDpc != NULL); */
+	page_addr = hv_context.synic_message_page[cpu];
+	msg = (struct hv_message *)page_addr + VMBUS_MESSAGE_SINT;
 
-	/* Call to bus driver to handle interrupt */
-	vmbus_drv_obj->OnEventDpc(&vmbus_drv_obj->Base);
+	/* Check if there are actual msgs to be process */
+	if (msg->header.message_type != HVMSG_NONE)
+		ret |= 0x1;
+
+	page_addr = hv_context.synic_event_page[cpu];
+	event = (union hv_synic_event_flags *)page_addr + VMBUS_MESSAGE_SINT;
+
+	/* Since we are a child, we only need to check bit 0 */
+	if (sync_test_and_clear_bit(0, (unsigned long *) &event->flags32[0]))
+		ret |= 0x2;
+
+	return ret;
 }
 
+
 static irqreturn_t vmbus_isr(int irq, void *dev_id)
 {
-	struct vmbus_driver *vmbus_driver_obj = &g_vmbus_drv.drv_obj;
 	int ret;
 
-	/* ASSERT(vmbus_driver_obj->OnIsr != NULL); */
-
-	/* Call to bus driver to handle interrupt */
-	ret = vmbus_driver_obj->OnIsr(&vmbus_driver_obj->Base);
+	ret = vmbus_on_isr();
 
 	/* Schedules a dpc if necessary */
 	if (ret > 0) {
 		if (test_bit(0, (unsigned long *)&ret))
-			tasklet_schedule(&g_vmbus_drv.msg_dpc);
+			tasklet_schedule(&msg_dpc);
 
 		if (test_bit(1, (unsigned long *)&ret))
-			tasklet_schedule(&g_vmbus_drv.event_dpc);
+			tasklet_schedule(&event_dpc);
 
 		return IRQ_HANDLED;
 	} else {
@@ -897,37 +532,242 @@
 	}
 }
 
-static struct dmi_system_id __initdata microsoft_hv_dmi_table[] = {
-	{
-		.ident = "Hyper-V",
-		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "Virtual Machine"),
-			DMI_MATCH(DMI_BOARD_NAME, "Virtual Machine"),
-		},
-	},
-	{ },
-};
-MODULE_DEVICE_TABLE(dmi, microsoft_hv_dmi_table);
-
-static int __init vmbus_init(void)
+/*
+ * vmbus_bus_init -Main vmbus driver initialization routine.
+ *
+ * Here, we
+ *	- initialize the vmbus driver context
+ *	- invoke the vmbus hv main init routine
+ *	- get the irq resource
+ *	- retrieve the channel offers
+ */
+static int vmbus_bus_init(int irq)
 {
-	DPRINT_INFO(VMBUS_DRV,
-		"Vmbus initializing.... current log level 0x%x (%x,%x)",
-		vmbus_loglevel, HIWORD(vmbus_loglevel), LOWORD(vmbus_loglevel));
-	/* Todo: it is used for loglevel, to be ported to new kernel. */
+	int ret;
+	unsigned int vector;
 
-	if (!dmi_check_system(microsoft_hv_dmi_table))
+	/* Hypervisor initialization...setup hypercall page..etc */
+	ret = hv_init();
+	if (ret != 0) {
+		pr_err("Unable to initialize the hypervisor - 0x%x\n", ret);
+		return ret;
+	}
+
+	/* Initialize the bus context */
+	tasklet_init(&msg_dpc, vmbus_on_msg_dpc, 0);
+	tasklet_init(&event_dpc, vmbus_on_event, 0);
+
+	/* Now, register the bus  with LDM */
+	ret = bus_register(&hv_bus);
+	if (ret)
+		return ret;
+
+	/* Get the interrupt resource */
+	ret = request_irq(irq, vmbus_isr, IRQF_SAMPLE_RANDOM,
+			driver_name, hv_acpi_dev);
+
+	if (ret != 0) {
+		pr_err("Unable to request IRQ %d\n",
+			   irq);
+
+		bus_unregister(&hv_bus);
+
+		return ret;
+	}
+
+	vector = IRQ0_VECTOR + irq;
+
+	/*
+	 * Notify the hypervisor of our irq and
+	 * connect to the host.
+	 */
+	on_each_cpu(hv_synic_init, (void *)&vector, 1);
+	ret = vmbus_connect();
+	if (ret) {
+		free_irq(irq, hv_acpi_dev);
+		bus_unregister(&hv_bus);
+		return ret;
+	}
+
+
+	vmbus_request_offers();
+
+	return 0;
+}
+
+/**
+ * vmbus_child_driver_register() - Register a vmbus's child driver
+ * @drv:        Pointer to driver structure you want to register
+ *
+ *
+ * Registers the given driver with Linux through the 'driver_register()' call
+ * And sets up the hyper-v vmbus handling for this driver.
+ * It will return the state of the 'driver_register()' call.
+ *
+ * Mainly used by Hyper-V drivers.
+ */
+int vmbus_child_driver_register(struct device_driver *drv)
+{
+	int ret;
+
+	pr_info("child driver registering - name %s\n", drv->name);
+
+	/* The child driver on this vmbus */
+	drv->bus = &hv_bus;
+
+	ret = driver_register(drv);
+
+	vmbus_request_offers();
+
+	return ret;
+}
+EXPORT_SYMBOL(vmbus_child_driver_register);
+
+/**
+ * vmbus_child_driver_unregister() - Unregister a vmbus's child driver
+ * @drv:        Pointer to driver structure you want to un-register
+ *
+ *
+ * Un-register the given driver with Linux through the 'driver_unregister()'
+ * call. And ungegisters the driver from the Hyper-V vmbus handler.
+ *
+ * Mainly used by Hyper-V drivers.
+ */
+void vmbus_child_driver_unregister(struct device_driver *drv)
+{
+	pr_info("child driver unregistering - name %s\n", drv->name);
+
+	driver_unregister(drv);
+
+}
+EXPORT_SYMBOL(vmbus_child_driver_unregister);
+
+/*
+ * vmbus_child_device_create - Creates and registers a new child device
+ * on the vmbus.
+ */
+struct hv_device *vmbus_child_device_create(struct hv_guid *type,
+					    struct hv_guid *instance,
+					    struct vmbus_channel *channel)
+{
+	struct hv_device *child_device_obj;
+
+	/* Allocate the new child device */
+	child_device_obj = kzalloc(sizeof(struct hv_device), GFP_KERNEL);
+	if (!child_device_obj) {
+		pr_err("Unable to allocate device object for child device\n");
+		return NULL;
+	}
+
+	child_device_obj->channel = channel;
+	memcpy(&child_device_obj->dev_type, type, sizeof(struct hv_guid));
+	memcpy(&child_device_obj->dev_instance, instance,
+	       sizeof(struct hv_guid));
+
+
+	return child_device_obj;
+}
+
+/*
+ * vmbus_child_device_register - Register the child device
+ */
+int vmbus_child_device_register(struct hv_device *child_device_obj)
+{
+	int ret = 0;
+
+	static atomic_t device_num = ATOMIC_INIT(0);
+
+	/* Set the device name. Otherwise, device_register() will fail. */
+	dev_set_name(&child_device_obj->device, "vmbus_0_%d",
+		     atomic_inc_return(&device_num));
+
+	/* The new device belongs to this bus */
+	child_device_obj->device.bus = &hv_bus; /* device->dev.bus; */
+	child_device_obj->device.parent = &hv_acpi_dev->dev;
+	child_device_obj->device.release = vmbus_device_release;
+
+	/*
+	 * Register with the LDM. This will kick off the driver/device
+	 * binding...which will eventually call vmbus_match() and vmbus_probe()
+	 */
+	ret = device_register(&child_device_obj->device);
+
+	if (ret)
+		pr_err("Unable to register child device\n");
+	else
+		pr_info("child device %s registered\n",
+			dev_name(&child_device_obj->device));
+
+	return ret;
+}
+
+/*
+ * vmbus_child_device_unregister - Remove the specified child device
+ * from the vmbus.
+ */
+void vmbus_child_device_unregister(struct hv_device *device_obj)
+{
+	/*
+	 * Kick off the process of unregistering the device.
+	 * This will call vmbus_remove() and eventually vmbus_device_release()
+	 */
+	device_unregister(&device_obj->device);
+
+	pr_info("child device %s unregistered\n",
+		dev_name(&device_obj->device));
+}
+
+
+/*
+ * VMBUS is an acpi enumerated device. Get the the IRQ information
+ * from DSDT.
+ */
+
+static acpi_status vmbus_walk_resources(struct acpi_resource *res, void *irq)
+{
+
+	if (res->type == ACPI_RESOURCE_TYPE_IRQ) {
+		struct acpi_resource_irq *irqp;
+		irqp = &res->data.irq;
+
+		*((unsigned int *)irq) = irqp->interrupts[0];
+	}
+
+	return AE_OK;
+}
+
+static int vmbus_acpi_add(struct acpi_device *device)
+{
+	acpi_status result;
+
+	hv_acpi_dev = device;
+
+	result =
+	acpi_walk_resources(device->handle, METHOD_NAME__CRS,
+			vmbus_walk_resources, &irq);
+
+	if (ACPI_FAILURE(result)) {
+		complete(&probe_event);
 		return -ENODEV;
-
-	return vmbus_bus_init(VmbusInitialize);
+	}
+	complete(&probe_event);
+	return 0;
 }
 
-static void __exit vmbus_exit(void)
-{
-	vmbus_bus_exit();
-	/* Todo: it is used for loglevel, to be ported to new kernel. */
-}
+static const struct acpi_device_id vmbus_acpi_device_ids[] = {
+	{"VMBUS", 0},
+	{"VMBus", 0},
+	{"", 0},
+};
+MODULE_DEVICE_TABLE(acpi, vmbus_acpi_device_ids);
+
+static struct acpi_driver vmbus_acpi_driver = {
+	.name = "vmbus",
+	.ids = vmbus_acpi_device_ids,
+	.ops = {
+		.add = vmbus_acpi_add,
+	},
+};
 
 /*
  * We use a PCI table to determine if we should autoload this driver  This is
@@ -941,10 +781,34 @@
 };
 MODULE_DEVICE_TABLE(pci, microsoft_hv_pci_table);
 
+static int __init hv_acpi_init(void)
+{
+	int ret;
+
+	init_completion(&probe_event);
+
+	/*
+	 * Get irq resources first.
+	 */
+
+	ret = acpi_bus_register_driver(&vmbus_acpi_driver);
+
+	if (ret)
+		return ret;
+
+	wait_for_completion(&probe_event);
+
+	if (irq <= 0) {
+		acpi_bus_unregister_driver(&vmbus_acpi_driver);
+		return -ENODEV;
+	}
+
+	return vmbus_bus_init(irq);
+}
+
+
 MODULE_LICENSE("GPL");
 MODULE_VERSION(HV_DRV_VERSION);
-module_param(vmbus_irq, int, S_IRUGO);
-module_param(vmbus_loglevel, int, S_IRUGO);
+module_param(vmbus_loglevel, int, S_IRUGO|S_IWUSR);
 
-module_init(vmbus_init);
-module_exit(vmbus_exit);
+module_init(hv_acpi_init);
diff --git a/drivers/staging/hv/vstorage.h b/drivers/staging/hv/vstorage.h
deleted file mode 100644
index 4ea597d..0000000
--- a/drivers/staging/hv/vstorage.h
+++ /dev/null
@@ -1,192 +0,0 @@
-/*
- *
- * Copyright (c) 2009, Microsoft Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place - Suite 330, Boston, MA 02111-1307 USA.
- *
- * Authors:
- *   Haiyang Zhang <haiyangz@microsoft.com>
- *   Hank Janssen  <hjanssen@microsoft.com>
- *
- */
-
-/* vstorage.w revision number.  This is used in the case of a version match, */
-/* to alert the user that structure sizes may be mismatched even though the */
-/* protocol versions match. */
-
-#define REVISION_STRING(REVISION_) #REVISION_
-#define FILL_VMSTOR_REVISION(RESULT_LVALUE_)				\
-{									\
-	char *revisionString = REVISION_STRING($Revision : 6 $) + 11;	\
-	RESULT_LVALUE_ = 0;						\
-	while (*revisionString >= '0' && *revisionString <= '9') {	\
-		RESULT_LVALUE_ *= 10;					\
-		RESULT_LVALUE_ += *revisionString - '0';		\
-		revisionString++;					\
-	}								\
-}
-
-/* Major/minor macros.  Minor version is in LSB, meaning that earlier flat */
-/* version numbers will be interpreted as "0.x" (i.e., 1 becomes 0.1). */
-#define VMSTOR_PROTOCOL_MAJOR(VERSION_)		(((VERSION_) >> 8) & 0xff)
-#define VMSTOR_PROTOCOL_MINOR(VERSION_)		(((VERSION_))      & 0xff)
-#define VMSTOR_PROTOCOL_VERSION(MAJOR_, MINOR_)	((((MAJOR_) & 0xff) << 8) | \
-						 (((MINOR_) & 0xff)))
-#define VMSTOR_INVALID_PROTOCOL_VERSION		(-1)
-
-/* Version history: */
-/* V1 Beta                    0.1 */
-/* V1 RC < 2008/1/31          1.0 */
-/* V1 RC > 2008/1/31          2.0 */
-#define VMSTOR_PROTOCOL_VERSION_CURRENT VMSTOR_PROTOCOL_VERSION(2, 0)
-
-
-
-
-/*  This will get replaced with the max transfer length that is possible on */
-/*  the host adapter. */
-/*  The max transfer length will be published when we offer a vmbus channel. */
-#define MAX_TRANSFER_LENGTH	0x40000
-#define DEFAULT_PACKET_SIZE (sizeof(struct vmdata_gpa_direct) +	\
-			sizeof(struct vstor_packet) +		\
-			sizesizeof(u64) * (MAX_TRANSFER_LENGTH / PAGE_SIZE)))
-
-
-/*  Packet structure describing virtual storage requests. */
-enum vstor_packet_operation {
-	VStorOperationCompleteIo            = 1,
-	VStorOperationRemoveDevice          = 2,
-	VStorOperationExecuteSRB            = 3,
-	VStorOperationResetLun              = 4,
-	VStorOperationResetAdapter          = 5,
-	VStorOperationResetBus              = 6,
-	VStorOperationBeginInitialization   = 7,
-	VStorOperationEndInitialization     = 8,
-	VStorOperationQueryProtocolVersion  = 9,
-	VStorOperationQueryProperties       = 10,
-	VStorOperationMaximum               = 10
-};
-
-/*
- * Platform neutral description of a scsi request -
- * this remains the same across the write regardless of 32/64 bit
- * note: it's patterned off the SCSI_PASS_THROUGH structure
- */
-#define CDB16GENERIC_LENGTH			0x10
-
-#ifndef SENSE_BUFFER_SIZE
-#define SENSE_BUFFER_SIZE			0x12
-#endif
-
-#define MAX_DATA_BUFFER_LENGTH_WITH_PADDING	0x14
-
-struct vmscsi_request {
-	unsigned short Length;
-	unsigned char SrbStatus;
-	unsigned char ScsiStatus;
-
-	unsigned char PortNumber;
-	unsigned char PathId;
-	unsigned char TargetId;
-	unsigned char Lun;
-
-	unsigned char CdbLength;
-	unsigned char SenseInfoLength;
-	unsigned char DataIn;
-	unsigned char Reserved;
-
-	unsigned int DataTransferLength;
-
-	union {
-	unsigned char Cdb[CDB16GENERIC_LENGTH];
-
-	unsigned char SenseData[SENSE_BUFFER_SIZE];
-
-	unsigned char ReservedArray[MAX_DATA_BUFFER_LENGTH_WITH_PADDING];
-	};
-} __attribute((packed));
-
-
-/*
- * This structure is sent during the intialization phase to get the different
- * properties of the channel.
- */
-struct vmstorage_channel_properties {
-	unsigned short ProtocolVersion;
-	unsigned char  PathId;
-	unsigned char  TargetId;
-
-	/* Note: port number is only really known on the client side */
-	unsigned int  PortNumber;
-	unsigned int  Flags;
-	unsigned int  MaxTransferBytes;
-
-	/*  This id is unique for each channel and will correspond with */
-	/*  vendor specific data in the inquirydata */
-	unsigned long long UniqueId;
-} __attribute__((packed));
-
-/*  This structure is sent during the storage protocol negotiations. */
-struct vmstorage_protocol_version {
-	/* Major (MSW) and minor (LSW) version numbers. */
-	unsigned short MajorMinor;
-
-	/*
-	 * Revision number is auto-incremented whenever this file is changed
-	 * (See FILL_VMSTOR_REVISION macro above).  Mismatch does not
-	 * definitely indicate incompatibility--but it does indicate mismatched
-	 * builds.
-	 */
-	unsigned short Revision;
-} __attribute__((packed));
-
-/* Channel Property Flags */
-#define STORAGE_CHANNEL_REMOVABLE_FLAG		0x1
-#define STORAGE_CHANNEL_EMULATED_IDE_FLAG	0x2
-
-struct vstor_packet {
-	/* Requested operation type */
-	enum vstor_packet_operation Operation;
-
-	/*  Flags - see below for values */
-	unsigned int     Flags;
-
-	/* Status of the request returned from the server side. */
-	unsigned int     Status;
-
-	/* Data payload area */
-	union {
-		/*
-		 * Structure used to forward SCSI commands from the
-		 * client to the server.
-		 */
-		struct vmscsi_request VmSrb;
-
-		/* Structure used to query channel properties. */
-		struct vmstorage_channel_properties StorageChannelProperties;
-
-		/* Used during version negotiations. */
-		struct vmstorage_protocol_version Version;
-	};
-} __attribute__((packed));
-
-/* Packet flags */
-/*
- * This flag indicates that the server should send back a completion for this
- * packet.
- */
-#define REQUEST_COMPLETION_FLAG	0x1
-
-/*  This is the set of flags that the vsc can set in any packets it sends */
-#define VSC_LEGAL_FLAGS		(REQUEST_COMPLETION_FLAG)