summaryrefslogtreecommitdiff
path: root/drivers/staging/hv
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/hv')
-rw-r--r--drivers/staging/hv/blkvsc_drv.c42
-rw-r--r--drivers/staging/hv/channel.c113
-rw-r--r--drivers/staging/hv/channel_mgmt.c8
-rw-r--r--drivers/staging/hv/connection.c52
-rw-r--r--drivers/staging/hv/hv.c4
-rw-r--r--drivers/staging/hv/hv_mouse.c2
-rw-r--r--drivers/staging/hv/hv_timesource.c1
-rw-r--r--drivers/staging/hv/hyperv.h86
-rw-r--r--drivers/staging/hv/hyperv_net.h14
-rw-r--r--drivers/staging/hv/hyperv_vmbus.h2
-rw-r--r--drivers/staging/hv/netvsc.c173
-rw-r--r--drivers/staging/hv/netvsc_drv.c60
-rw-r--r--drivers/staging/hv/ring_buffer.c6
-rw-r--r--drivers/staging/hv/rndis_filter.c59
-rw-r--r--drivers/staging/hv/storvsc.c8
-rw-r--r--drivers/staging/hv/storvsc_drv.c88
-rw-r--r--drivers/staging/hv/tools/hv_kvp_daemon.c1
-rw-r--r--drivers/staging/hv/vmbus_drv.c136
18 files changed, 234 insertions, 621 deletions
diff --git a/drivers/staging/hv/blkvsc_drv.c b/drivers/staging/hv/blkvsc_drv.c
index 46daade7a9e2..3612574ca520 100644
--- a/drivers/staging/hv/blkvsc_drv.c
+++ b/drivers/staging/hv/blkvsc_drv.c
@@ -518,22 +518,18 @@ static int blkvsc_remove(struct hv_device *dev)
blkvsc_do_operation(blkdev, DO_FLUSH);
- blk_cleanup_queue(blkdev->gd->queue);
+ if (blkdev->users == 0) {
+ del_gendisk(blkdev->gd);
+ put_disk(blkdev->gd);
+ blk_cleanup_queue(blkdev->gd->queue);
- /*
- * Call to the vsc driver to let it know that the device is being
- * removed
- */
- storvsc_dev_remove(dev);
-
- del_gendisk(blkdev->gd);
+ storvsc_dev_remove(blkdev->device_ctx);
- kmem_cache_destroy(blkdev->request_pool);
-
- kfree(blkdev);
+ kmem_cache_destroy(blkdev->request_pool);
+ kfree(blkdev);
+ }
return 0;
-
}
static void blkvsc_shutdown(struct hv_device *dev)
@@ -568,13 +564,23 @@ static int blkvsc_release(struct gendisk *disk, fmode_t mode)
struct block_device_context *blkdev = disk->private_data;
unsigned long flags;
- if (blkdev->users == 1) {
+ spin_lock_irqsave(&blkdev->lock, flags);
+
+ if ((--blkdev->users == 0) && (blkdev->shutting_down)) {
+ blk_stop_queue(blkdev->gd->queue);
+ spin_unlock_irqrestore(&blkdev->lock, flags);
+
blkvsc_do_operation(blkdev, DO_FLUSH);
- }
+ del_gendisk(blkdev->gd);
+ put_disk(blkdev->gd);
+ blk_cleanup_queue(blkdev->gd->queue);
- spin_lock_irqsave(&blkdev->lock, flags);
- blkdev->users--;
- spin_unlock_irqrestore(&blkdev->lock, flags);
+ storvsc_dev_remove(blkdev->device_ctx);
+
+ kmem_cache_destroy(blkdev->request_pool);
+ kfree(blkdev);
+ } else
+ spin_unlock_irqrestore(&blkdev->lock, flags);
return 0;
}
@@ -824,7 +830,6 @@ static int blkvsc_drv_init(void)
BUILD_BUG_ON(sizeof(sector_t) != 8);
memcpy(&drv->dev_type, &dev_type, sizeof(struct hv_guid));
- drv->name = drv_name;
drv->driver.name = drv_name;
/* The driver belongs to vmbus */
@@ -921,7 +926,6 @@ static int blkvsc_probe(struct hv_device *dev)
else
blkdev->gd->first_minor = 0;
blkdev->gd->fops = &block_ops;
- blkdev->gd->events = DISK_EVENT_MEDIA_CHANGE;
blkdev->gd->private_data = blkdev;
blkdev->gd->driverfs_dev = &(blkdev->device_ctx->device);
sprintf(blkdev->gd->disk_name, "hd%c", 'a' + major_info.index);
diff --git a/drivers/staging/hv/channel.c b/drivers/staging/hv/channel.c
index f655e59a9a8f..455f47a891f1 100644
--- a/drivers/staging/hv/channel.c
+++ b/drivers/staging/hv/channel.c
@@ -39,7 +39,6 @@ static int create_gpadl_header(
u32 size, /* page-size multiple */
struct vmbus_channel_msginfo **msginfo,
u32 *messagecount);
-static void dump_vmbus_channel(struct vmbus_channel *channel);
static void vmbus_setevent(struct vmbus_channel *channel);
/*
@@ -186,12 +185,12 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size,
openMsg = (struct vmbus_channel_open_channel *)openInfo->msg;
openMsg->header.msgtype = CHANNELMSG_OPENCHANNEL;
- openMsg->openid = newchannel->offermsg.child_relid; /* FIXME */
+ 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; /* TODO */
+ openMsg->server_contextarea_gpadlhandle = 0;
if (userdatalen > MAX_USER_DEFINED_BYTES) {
err = -EINVAL;
@@ -210,9 +209,9 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size,
sizeof(struct vmbus_channel_open_channel));
if (ret != 0)
- goto Cleanup;
+ goto cleanup;
- t = wait_for_completion_timeout(&openInfo->waitevent, HZ);
+ t = wait_for_completion_timeout(&openInfo->waitevent, 5*HZ);
if (t == 0) {
err = -ETIMEDOUT;
goto errorout;
@@ -222,7 +221,7 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size,
if (openInfo->response.open_result.status)
err = openInfo->response.open_result.status;
-Cleanup:
+cleanup:
spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
list_del(&openInfo->msglistentry);
spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
@@ -356,20 +355,35 @@ static int create_gpadl_header(void *kbuffer, u32 size,
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)
+
+ 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;
/*
- * FIXME:
* 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.
*/
- /* gpadl_body->Gpadl = kbuffer; */
for (i = 0; i < pfncurr; i++)
gpadl_body->pfn[i] = pfn + pfnsum + i;
@@ -458,12 +472,11 @@ int vmbus_establish_gpadl(struct vmbus_channel *channel, void *kbuffer,
ret = vmbus_post_msg(gpadlmsg, msginfo->msgsize -
sizeof(*msginfo));
if (ret != 0)
- goto Cleanup;
+ goto cleanup;
if (msgcount > 1) {
list_for_each(curr, &msginfo->submsglist) {
- /* FIXME: should this use list_entry() instead ? */
submsginfo = (struct vmbus_channel_msginfo *)curr;
gpadl_body =
(struct vmbus_channel_gpadl_body *)submsginfo->msg;
@@ -478,18 +491,18 @@ int vmbus_establish_gpadl(struct vmbus_channel *channel, void *kbuffer,
submsginfo->msgsize -
sizeof(*submsginfo));
if (ret != 0)
- goto Cleanup;
+ goto cleanup;
}
}
- t = wait_for_completion_timeout(&msginfo->waitevent, HZ);
+ 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:
+cleanup:
spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
list_del(&msginfo->msglistentry);
spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
@@ -532,7 +545,7 @@ int vmbus_teardown_gpadl(struct vmbus_channel *channel, u32 gpadl_handle)
sizeof(struct vmbus_channel_gpadl_teardown));
BUG_ON(ret != 0);
- t = wait_for_completion_timeout(&info->waitevent, HZ);
+ t = wait_for_completion_timeout(&info->waitevent, 5*HZ);
BUG_ON(t == 0);
/* Received a torndown response */
@@ -551,24 +564,15 @@ EXPORT_SYMBOL_GPL(vmbus_teardown_gpadl);
void vmbus_close(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->onchannel_callback = 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;
+ msg = &channel->close_msg.msg;
- msg = (struct vmbus_channel_close_channel *)info->msg;
msg->header.msgtype = CHANNELMSG_CLOSECHANNEL;
msg->child_relid = channel->offermsg.child_relid;
@@ -580,8 +584,6 @@ void vmbus_close(struct vmbus_channel *channel)
vmbus_teardown_gpadl(channel,
channel->ringbuffer_gpadlhandle);
- /* TODO: Send a msg to release the childRelId */
-
/* Cleanup the ring buffers for this channel */
hv_ringbuffer_cleanup(&channel->outbound);
hv_ringbuffer_cleanup(&channel->inbound);
@@ -589,21 +591,7 @@ void vmbus_close(struct vmbus_channel *channel)
free_pages((unsigned long)channel->ringbuffer_pages,
get_order(channel->ringbuffer_pagecount * PAGE_SIZE));
- 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(&vmbus_connection.channel_lock, flags);
- list_del(&channel->listentry);
- spin_unlock_irqrestore(&vmbus_connection.channel_lock, flags);
-
- free_channel(channel);
- }
}
EXPORT_SYMBOL_GPL(vmbus_close);
@@ -632,7 +620,6 @@ int vmbus_sendpacket(struct vmbus_channel *channel, const void *buffer,
u64 aligned_data = 0;
int ret;
- dump_vmbus_channel(channel);
/* Setup the descriptor */
desc.type = type; /* VmbusPacketTypeDataInBand; */
@@ -650,7 +637,6 @@ int vmbus_sendpacket(struct vmbus_channel *channel, const void *buffer,
ret = hv_ringbuffer_write(&channel->outbound, bufferlist, 3);
- /* TODO: We should determine if this is optional */
if (ret == 0 && !hv_get_ringbuffer_interrupt_mask(&channel->outbound))
vmbus_setevent(channel);
@@ -679,7 +665,6 @@ int vmbus_sendpacket_pagebuffer(struct vmbus_channel *channel,
if (pagecount > MAX_PAGE_BUFFER_COUNT)
return -EINVAL;
- dump_vmbus_channel(channel);
/*
* Adjust the size down since vmbus_channel_packet_page_buffer is the
@@ -713,7 +698,6 @@ int vmbus_sendpacket_pagebuffer(struct vmbus_channel *channel,
ret = hv_ringbuffer_write(&channel->outbound, bufferlist, 3);
- /* TODO: We should determine if this is optional */
if (ret == 0 && !hv_get_ringbuffer_interrupt_mask(&channel->outbound))
vmbus_setevent(channel);
@@ -739,7 +723,6 @@ int vmbus_sendpacket_multipagebuffer(struct vmbus_channel *channel,
u32 pfncount = NUM_PAGES_SPANNED(multi_pagebuffer->offset,
multi_pagebuffer->len);
- dump_vmbus_channel(channel);
if ((pfncount < 0) || (pfncount > MAX_MULTIPAGE_BUFFER_COUNT))
return -EINVAL;
@@ -777,7 +760,6 @@ int vmbus_sendpacket_multipagebuffer(struct vmbus_channel *channel,
ret = hv_ringbuffer_write(&channel->outbound, bufferlist, 3);
- /* TODO: We should determine if this is optional */
if (ret == 0 && !hv_get_ringbuffer_interrupt_mask(&channel->outbound))
vmbus_setevent(channel);
@@ -829,7 +811,7 @@ int vmbus_recvpacket(struct vmbus_channel *channel, void *buffer,
pr_err("Buffer too small - got %d needs %d\n",
bufferlen, userlen);
- return -1;
+ return -ETOOSMALL;
}
*requestid = desc.trans_id;
@@ -893,36 +875,3 @@ int vmbus_recvpacket_raw(struct vmbus_channel *channel, void *buffer,
return 0;
}
EXPORT_SYMBOL_GPL(vmbus_recvpacket_raw);
-
-/*
- * vmbus_onchannel_event - Channel event callback
- */
-void vmbus_onchannel_event(struct vmbus_channel *channel)
-{
- dump_vmbus_channel(channel);
-
- channel->onchannel_callback(channel->channel_callback_context);
-
- mod_timer(&channel->poll_timer, jiffies + usecs_to_jiffies(100));
-}
-
-/*
- * vmbus_ontimer - Timer event callback
- */
-void vmbus_ontimer(unsigned long data)
-{
- struct vmbus_channel *channel = (struct vmbus_channel *)data;
-
- if (channel->onchannel_callback)
- channel->onchannel_callback(channel->channel_callback_context);
-}
-
-/*
- * dump_vmbus_channel- Dump vmbus channel info to the console
- */
-static void dump_vmbus_channel(struct vmbus_channel *channel)
-{
- DPRINT_DBG(VMBUS, "Channel (%d)", channel->offermsg.child_relid);
- hv_dump_ring_info(&channel->outbound, "Outbound ");
- hv_dump_ring_info(&channel->inbound, "Inbound ");
-}
diff --git a/drivers/staging/hv/channel_mgmt.c b/drivers/staging/hv/channel_mgmt.c
index 957d61ee4ceb..bf011f3fb851 100644
--- a/drivers/staging/hv/channel_mgmt.c
+++ b/drivers/staging/hv/channel_mgmt.c
@@ -283,10 +283,6 @@ static struct vmbus_channel *alloc_channel(void)
spin_lock_init(&channel->inbound_lock);
- init_timer(&channel->poll_timer);
- channel->poll_timer.data = (unsigned long)channel;
- channel->poll_timer.function = vmbus_ontimer;
-
channel->controlwq = create_workqueue("hv_vmbus_ctl");
if (!channel->controlwq) {
kfree(channel);
@@ -315,7 +311,6 @@ static void release_channel(struct work_struct *work)
*/
void free_channel(struct vmbus_channel *channel)
{
- del_timer_sync(&channel->poll_timer);
/*
* We have to release the channel's workqueue/thread in the vmbus's
@@ -482,7 +477,6 @@ static void vmbus_onoffer(struct vmbus_channel_message_header *hdr)
newchannel->monitor_grp = (u8)offer->monitorid / 32;
newchannel->monitor_bit = (u8)offer->monitorid % 32;
- /* TODO: Make sure the offer comes from our parent partition */
INIT_WORK(&newchannel->work, vmbus_process_offer);
queue_work(newchannel->controlwq, &newchannel->work);
}
@@ -773,7 +767,7 @@ int vmbus_request_offers(void)
goto cleanup;
}
- t = wait_for_completion_timeout(&msginfo->waitevent, HZ);
+ t = wait_for_completion_timeout(&msginfo->waitevent, 5*HZ);
if (t == 0) {
ret = -ETIMEDOUT;
goto cleanup;
diff --git a/drivers/staging/hv/connection.c b/drivers/staging/hv/connection.c
index 37bbf770ef11..e6b40392e08d 100644
--- a/drivers/staging/hv/connection.c
+++ b/drivers/staging/hv/connection.c
@@ -51,13 +51,13 @@ int vmbus_connect(void)
/* Make sure we are not connecting or connected */
if (vmbus_connection.conn_state != DISCONNECTED)
- return -1;
+ 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 = -1;
+ ret = -ENOMEM;
goto cleanup;
}
@@ -74,7 +74,7 @@ int vmbus_connect(void)
vmbus_connection.int_page =
(void *)__get_free_pages(GFP_KERNEL|__GFP_ZERO, 0);
if (vmbus_connection.int_page == NULL) {
- ret = -1;
+ ret = -ENOMEM;
goto cleanup;
}
@@ -90,7 +90,7 @@ int vmbus_connect(void)
vmbus_connection.monitor_pages =
(void *)__get_free_pages((GFP_KERNEL|__GFP_ZERO), 1);
if (vmbus_connection.monitor_pages == NULL) {
- ret = -1;
+ ret = -ENOMEM;
goto cleanup;
}
@@ -135,7 +135,7 @@ int vmbus_connect(void)
}
/* Wait for the connection response */
- t = wait_for_completion_timeout(&msginfo->waitevent, HZ);
+ t = wait_for_completion_timeout(&msginfo->waitevent, 5*HZ);
if (t == 0) {
spin_lock_irqsave(&vmbus_connection.channelmsg_lock,
flags);
@@ -157,7 +157,7 @@ int vmbus_connect(void)
pr_err("Unable to connect, "
"Version %d not supported by Hyper-V\n",
VMBUS_REVISION_NUMBER);
- ret = -1;
+ ret = -ECONNREFUSED;
goto cleanup;
}
@@ -185,44 +185,6 @@ cleanup:
return ret;
}
-/*
- * vmbus_disconnect -
- * Sends a disconnect request on the partition service connection
- */
-int vmbus_disconnect(void)
-{
- int ret = 0;
- struct vmbus_channel_message_header *msg;
-
- /* Make sure we are connected */
- if (vmbus_connection.conn_state != CONNECTED)
- return -1;
-
- msg = kzalloc(sizeof(struct vmbus_channel_message_header), GFP_KERNEL);
- if (!msg)
- return -ENOMEM;
-
- msg->msgtype = CHANNELMSG_UNLOAD;
-
- ret = vmbus_post_msg(msg,
- sizeof(struct vmbus_channel_message_header));
- if (ret != 0)
- goto cleanup;
-
- free_pages((unsigned long)vmbus_connection.int_page, 0);
- free_pages((unsigned long)vmbus_connection.monitor_pages, 1);
-
- /* TODO: iterate thru the msg list and free up */
- destroy_workqueue(vmbus_connection.work_queue);
-
- vmbus_connection.conn_state = DISCONNECTED;
-
- pr_info("hv_vmbus disconnected\n");
-
-cleanup:
- kfree(msg);
- return ret;
-}
/*
* relid2channel - Get the channel object given its
@@ -262,7 +224,7 @@ static void process_chn_event(u32 relid)
channel = relid2channel(relid);
if (channel) {
- vmbus_onchannel_event(channel);
+ channel->onchannel_callback(channel->channel_callback_context);
} else {
pr_err("channel not found for relid - %u\n", relid);
}
diff --git a/drivers/staging/hv/hv.c b/drivers/staging/hv/hv.c
index a2cc0911de58..824f81679ae8 100644
--- a/drivers/staging/hv/hv.c
+++ b/drivers/staging/hv/hv.c
@@ -277,11 +277,11 @@ u16 hv_post_message(union hv_connection_id connection_id,
unsigned long addr;
if (payload_size > HV_MESSAGE_PAYLOAD_BYTE_COUNT)
- return -1;
+ return -EMSGSIZE;
addr = (unsigned long)kmalloc(sizeof(struct aligned_input), GFP_ATOMIC);
if (!addr)
- return -1;
+ return -ENOMEM;
aligned_msg = (struct hv_input_post_message *)
(ALIGN(addr, HV_HYPERCALL_PARAM_ALIGN));
diff --git a/drivers/staging/hv/hv_mouse.c b/drivers/staging/hv/hv_mouse.c
index 359e73741c48..d957fc228019 100644
--- a/drivers/staging/hv/hv_mouse.c
+++ b/drivers/staging/hv/hv_mouse.c
@@ -24,7 +24,6 @@
#include <linux/hiddev.h>
#include <linux/pci.h>
#include <linux/dmi.h>
-#include <linux/delay.h>
#include "hyperv.h"
@@ -936,7 +935,6 @@ static int __init mousevsc_init(void)
sizeof(struct hv_guid));
drv->driver.name = driver_name;
- drv->name = driver_name;
/* The driver belongs to vmbus */
vmbus_child_driver_register(&drv->driver);
diff --git a/drivers/staging/hv/hv_timesource.c b/drivers/staging/hv/hv_timesource.c
index 0efb04915255..2b0f9aaf9122 100644
--- a/drivers/staging/hv/hv_timesource.c
+++ b/drivers/staging/hv/hv_timesource.c
@@ -22,7 +22,6 @@
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-#include <linux/version.h>
#include <linux/clocksource.h>
#include <linux/init.h>
#include <linux/module.h>
diff --git a/drivers/staging/hv/hyperv.h b/drivers/staging/hv/hyperv.h
index 3310e9bdf562..1747a2404f6c 100644
--- a/drivers/staging/hv/hyperv.h
+++ b/drivers/staging/hv/hyperv.h
@@ -523,46 +523,6 @@ enum vmbus_channel_state {
CHANNEL_OPEN_STATE,
};
-struct vmbus_channel {
- struct list_head listentry;
-
- struct hv_device *device_obj;
-
- struct timer_list poll_timer; /* SA-111 workaround */
- 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;
-
- /* Channel callback are invoked in this workqueue context */
- /* HANDLE dataWorkQueue; */
-
- void (*onchannel_callback)(void *context);
- void *channel_callback_context;
-};
-
struct vmbus_channel_debug_info {
u32 relid;
enum vmbus_channel_state state;
@@ -609,6 +569,51 @@ struct vmbus_channel_msginfo {
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);
@@ -691,7 +696,6 @@ extern int vmbus_recvpacket_raw(struct vmbus_channel *channel,
u32 *buffer_actual_len,
u64 *requestid);
-extern void vmbus_onchannel_event(struct vmbus_channel *channel);
extern void vmbus_get_debug_info(struct vmbus_channel *channel,
struct vmbus_channel_debug_info *debug);
diff --git a/drivers/staging/hv/hyperv_net.h b/drivers/staging/hv/hyperv_net.h
index 315097df799a..27f987b48dfe 100644
--- a/drivers/staging/hv/hyperv_net.h
+++ b/drivers/staging/hv/hyperv_net.h
@@ -99,9 +99,9 @@ int netvsc_recv_callback(struct hv_device *device_obj,
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_filte_device_add(struct hv_device *dev,
+int rndis_filter_device_add(struct hv_device *dev,
void *additional_info);
-int rndis_filter_device_remove(struct hv_device *dev);
+void rndis_filter_device_remove(struct hv_device *dev);
int rndis_filter_receive(struct hv_device *dev,
struct hv_netvsc_packet *pkt);
@@ -355,10 +355,6 @@ struct nvsp_message {
/* #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
@@ -383,12 +379,6 @@ struct netvsc_device {
struct list_head recv_pkt_list;
spinlock_t recv_pkt_list_lock;
- /* Send buffer allocated by us but manages by NetVSP */
- void *send_buf;
- u32 send_buf_size;
- u32 send_buf_gpadl_handle;
- u32 send_section_size;
-
/* Receive buffer allocated by us but manages by NetVSP */
void *recv_buf;
u32 recv_buf_size;
diff --git a/drivers/staging/hv/hyperv_vmbus.h b/drivers/staging/hv/hyperv_vmbus.h
index bf30a425b643..349ad80ce328 100644
--- a/drivers/staging/hv/hyperv_vmbus.h
+++ b/drivers/staging/hv/hyperv_vmbus.h
@@ -619,8 +619,6 @@ struct vmbus_channel *relid2channel(u32 relid);
int vmbus_connect(void);
-int vmbus_disconnect(void);
-
int vmbus_post_msg(void *buffer, size_t buflen);
int vmbus_set_event(u32 child_relid);
diff --git a/drivers/staging/hv/netvsc.c b/drivers/staging/hv/netvsc.c
index 41cbb26eccbf..dc5e5c488e3b 100644
--- a/drivers/staging/hv/netvsc.c
+++ b/drivers/staging/hv/netvsc.c
@@ -270,7 +270,7 @@ static int netvsc_init_recv_buf(struct hv_device *device)
goto cleanup;
}
- t = wait_for_completion_timeout(&net_device->channel_init_wait, HZ);
+ t = wait_for_completion_timeout(&net_device->channel_init_wait, 5*HZ);
BUG_ON(t == 0);
@@ -323,162 +323,6 @@ exit:
return ret;
}
-static int netvsc_destroy_send_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->send_section_size) {
- /* Send the revoke send buffer */
- revoke_packet = &net_device->revoke_packet;
- memset(revoke_packet, 0, sizeof(struct nvsp_message));
-
- revoke_packet->hdr.msg_type =
- NVSP_MSG1_TYPE_REVOKE_SEND_BUF;
- revoke_packet->msg.v1_msg.
- revoke_send_buf.id = NETVSC_SEND_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 send buffer to netvsp");
- return -1;
- }
- }
-
- /* Teardown the gpadl on the vsp end */
- if (net_device->send_buf_gpadl_handle) {
- ret = vmbus_teardown_gpadl(net_device->dev->channel,
- net_device->send_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 send buffer's gpadl");
- return -1;
- }
- net_device->send_buf_gpadl_handle = 0;
- }
-
- if (net_device->send_buf) {
- /* Free up the receive buffer */
- free_pages((unsigned long)net_device->send_buf,
- get_order(net_device->send_buf_size));
- net_device->send_buf = NULL;
- }
-
- return ret;
-}
-
-static int netvsc_init_send_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;
- }
- if (net_device->send_buf_size <= 0) {
- ret = -EINVAL;
- goto cleanup;
- }
-
- net_device->send_buf =
- (void *)__get_free_pages(GFP_KERNEL|__GFP_ZERO,
- get_order(net_device->send_buf_size));
- if (!net_device->send_buf) {
- dev_err(&device->device, "unable to allocate send "
- "buffer of size %d", net_device->send_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->send_buf,
- net_device->send_buf_size,
- &net_device->send_buf_gpadl_handle);
- if (ret != 0) {
- dev_err(&device->device, "unable to establish send 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_SEND_BUF;
- init_packet->msg.v1_msg.send_recv_buf.
- gpadl_handle = net_device->send_buf_gpadl_handle;
- init_packet->msg.v1_msg.send_recv_buf.id =
- NETVSC_SEND_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, HZ);
-
- BUG_ON(t == 0);
-
- /* Check the response */
- if (init_packet->msg.v1_msg.
- send_send_buf_complete.status != NVSP_STAT_SUCCESS) {
- dev_err(&device->device, "Unable to complete send buffer "
- "initialzation with NetVsp - status %d",
- init_packet->msg.v1_msg.
- send_send_buf_complete.status);
- ret = -1;
- goto cleanup;
- }
-
- net_device->send_section_size = init_packet->
- msg.v1_msg.send_send_buf_complete.section_size;
-
- goto exit;
-
-cleanup:
- netvsc_destroy_send_buf(net_device);
-
-exit:
- put_net_device(device);
- return ret;
-}
-
static int netvsc_connect_vsp(struct hv_device *device)
{
@@ -513,7 +357,7 @@ static int netvsc_connect_vsp(struct hv_device *device)
if (ret != 0)
goto cleanup;
- t = wait_for_completion_timeout(&net_device->channel_init_wait, HZ);
+ t = wait_for_completion_timeout(&net_device->channel_init_wait, 5*HZ);
if (t == 0) {
ret = -ETIMEDOUT;
@@ -556,8 +400,6 @@ static int netvsc_connect_vsp(struct hv_device *device)
/* Post the big receive buffer to NetVSP */
ret = netvsc_init_recv_buf(device);
- if (ret == 0)
- ret = netvsc_init_send_buf(device);
cleanup:
put_net_device(device);
@@ -567,7 +409,6 @@ cleanup:
static void netvsc_disconnect_vsp(struct netvsc_device *net_device)
{
netvsc_destroy_recv_buf(net_device);
- netvsc_destroy_send_buf(net_device);
}
/*
@@ -698,10 +539,10 @@ int netvsc_send(struct hv_device *device,
(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);
+ sizeof(struct nvsp_message),
+ (unsigned long)packet,
+ VM_PKT_DATA_INBAND,
+ VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
}
@@ -1099,8 +940,6 @@ int netvsc_device_add(struct hv_device *device, void *additional_info)
net_device->recv_buf_size = NETVSC_RECEIVE_BUFFER_SIZE;
spin_lock_init(&net_device->recv_pkt_list_lock);
- net_device->send_buf_size = NETVSC_SEND_BUFFER_SIZE;
-
INIT_LIST_HEAD(&net_device->recv_pkt_list);
for (i = 0; i < NETVSC_RECEIVE_PACKETLIST_COUNT; i++) {
diff --git a/drivers/staging/hv/netvsc_drv.c b/drivers/staging/hv/netvsc_drv.c
index 7b9c229f7295..61989f0d9f0d 100644
--- a/drivers/staging/hv/netvsc_drv.c
+++ b/drivers/staging/hv/netvsc_drv.c
@@ -21,6 +21,7 @@
#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>
@@ -45,8 +46,8 @@
struct net_device_context {
/* point back to our device context */
struct hv_device *device_ctx;
- unsigned long avail;
- struct work_struct work;
+ atomic_t avail;
+ struct delayed_work dwork;
};
@@ -118,9 +119,10 @@ static void netvsc_xmit_completion(void *context)
dev_kfree_skb_any(skb);
- net_device_ctx->avail += num_pages;
- if (net_device_ctx->avail >= PACKET_PAGES_HIWATER)
- netif_wake_queue(net);
+ atomic_add(num_pages, &net_device_ctx->avail);
+ if (atomic_read(&net_device_ctx->avail) >=
+ PACKET_PAGES_HIWATER)
+ netif_wake_queue(net);
}
}
@@ -133,7 +135,7 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
/* 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. */
@@ -156,9 +158,6 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
/* Setup the rndis header */
packet->page_buf_cnt = num_pages;
- /* TODO: Flush all write buffers/ memory fence ??? */
- /* wmb(); */
-
/* Initialize it from the skb */
packet->total_data_buflen = skb->len;
@@ -188,8 +187,8 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
net->stats.tx_bytes += skb->len;
net->stats.tx_packets++;
- net_device_ctx->avail -= num_pages;
- if (net_device_ctx->avail < 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 */
@@ -220,7 +219,7 @@ void netvsc_linkstatus_callback(struct hv_device *device_obj,
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);
@@ -318,7 +317,7 @@ static const struct net_device_ops device_ops = {
* 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)
@@ -326,8 +325,7 @@ static void netvsc_send_garp(struct work_struct *w)
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);
}
@@ -349,13 +347,13 @@ static int netvsc_probe(struct hv_device *dev)
net_device_ctx = netdev_priv(net);
net_device_ctx->device_ctx = dev;
- net_device_ctx->avail = ring_size;
+ atomic_set(&net_device_ctx->avail, ring_size);
dev_set_drvdata(&dev->device, net);
- INIT_WORK(&net_device_ctx->work, netvsc_send_garp);
+ INIT_DELAYED_WORK(&net_device_ctx->dwork, netvsc_send_garp);
/* Notify the netvsc driver of the new device */
device_info.ring_size = ring_size;
- ret = rndis_filte_device_add(dev, &device_info);
+ ret = rndis_filter_device_add(dev, &device_info);
if (ret != 0) {
free_netdev(net);
dev_set_drvdata(&dev->device, NULL);
@@ -364,17 +362,7 @@ static int netvsc_probe(struct hv_device *dev)
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.link_state)
- netif_carrier_on(net);
+ netif_carrier_on(net);
memcpy(net->dev_addr, device_info.mac_adr, ETH_ALEN);
@@ -400,16 +388,18 @@ static int netvsc_probe(struct hv_device *dev)
static int netvsc_remove(struct hv_device *dev)
{
struct net_device *net = dev_get_drvdata(&dev->device);
- int ret;
+ struct net_device_context *ndev_ctx;
if (net == NULL) {
dev_err(&dev->device, "No net device to remove\n");
return 0;
}
+ 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);
@@ -417,14 +407,10 @@ static int netvsc_remove(struct hv_device *dev)
* Call to the vsc driver to let it know that the device is being
* removed
*/
- ret = rndis_filter_device_remove(dev);
- if (ret != 0) {
- /* TODO: */
- netdev_err(net, "unable to remove vsc device (ret %d)\n", ret);
- }
+ rndis_filter_device_remove(dev);
free_netdev(net);
- return ret;
+ return 0;
}
/* The one and only one */
diff --git a/drivers/staging/hv/ring_buffer.c b/drivers/staging/hv/ring_buffer.c
index 3da333018b5a..42f76728429a 100644
--- a/drivers/staging/hv/ring_buffer.c
+++ b/drivers/staging/hv/ring_buffer.c
@@ -50,6 +50,8 @@ hv_get_ringbuffer_availbytes(struct hv_ring_buffer_info *rbi,
{
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;
@@ -411,7 +413,7 @@ int hv_ringbuffer_write(struct hv_ring_buffer_info *outring_info,
sizeof(u64));
/* Make sure we flush all writes before updating the writeIndex */
- mb();
+ smp_wmb();
/* Now, update the write location */
hv_set_next_write_location(outring_info, next_write_location);
@@ -513,7 +515,7 @@ int hv_ringbuffer_read(struct hv_ring_buffer_info *inring_info, void *buffer,
/* 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();
+ smp_mb();
/* Update the read index */
hv_set_next_read_location(inring_info, next_read_location);
diff --git a/drivers/staging/hv/rndis_filter.c b/drivers/staging/hv/rndis_filter.c
index 60ebdb1b6082..dbb520199756 100644
--- a/drivers/staging/hv/rndis_filter.c
+++ b/drivers/staging/hv/rndis_filter.c
@@ -139,14 +139,17 @@ static void put_rndis_request(struct rndis_device *dev,
kfree(req);
}
-static void dump_rndis_message(struct rndis_message *rndis_msg)
+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:
- DPRINT_DBG(NETVSC, "REMOTE_NDIS_PACKET_MSG (len %u, "
+ 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",
+ "pkt len %u\n",
rndis_msg->msg_len,
rndis_msg->msg.pkt.data_offset,
rndis_msg->msg.pkt.data_len,
@@ -158,10 +161,10 @@ static void dump_rndis_message(struct rndis_message *rndis_msg)
break;
case REMOTE_NDIS_INITIALIZE_CMPLT:
- DPRINT_DBG(NETVSC, "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)",
+ "pkt aligned %u)\n",
rndis_msg->msg_len,
rndis_msg->msg.init_complete.req_id,
rndis_msg->msg.init_complete.status,
@@ -176,9 +179,9 @@ static void dump_rndis_message(struct rndis_message *rndis_msg)
break;
case REMOTE_NDIS_QUERY_CMPLT:
- DPRINT_DBG(NETVSC, "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)",
+ "buf offset %u)\n",
rndis_msg->msg_len,
rndis_msg->msg.query_complete.req_id,
rndis_msg->msg.query_complete.status,
@@ -189,16 +192,16 @@ static void dump_rndis_message(struct rndis_message *rndis_msg)
break;
case REMOTE_NDIS_SET_CMPLT:
- DPRINT_DBG(NETVSC,
- "REMOTE_NDIS_SET_CMPLT (len %u, id 0x%x, status 0x%x)",
+ 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:
- DPRINT_DBG(NETVSC, "REMOTE_NDIS_INDICATE_STATUS_MSG "
- "(len %u, status 0x%x, buf len %u, buf offset %u)",
+ 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,
@@ -206,7 +209,7 @@ static void dump_rndis_message(struct rndis_message *rndis_msg)
break;
default:
- DPRINT_DBG(NETVSC, "0x%x (len %u)",
+ netdev_dbg(netdev, "0x%x (len %u)\n",
rndis_msg->ndis_msg_type,
rndis_msg->msg_len);
break;
@@ -372,24 +375,6 @@ int rndis_filter_receive(struct hv_device *dev,
pkt->page_buf[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 (pkt->total_data_buflen != rndis_hdr->msg_len) {
- kunmap_atomic(rndis_hdr - pkt->page_buf[0].offset,
- KM_IRQ0);
-
- dev_err(&dev->device, "invalid rndis message? (expected %u "
- "bytes got %u)...dropping this message!\n",
- rndis_hdr->msg_len,
- pkt->total_data_buflen);
- return -1;
- }
-#endif
-
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 "
@@ -405,7 +390,7 @@ int rndis_filter_receive(struct hv_device *dev,
kunmap_atomic(rndis_hdr - pkt->page_buf[0].offset, KM_IRQ0);
- dump_rndis_message(&rndis_msg);
+ dump_rndis_message(dev, &rndis_msg);
switch (rndis_msg.ndis_msg_type) {
case REMOTE_NDIS_PACKET_MSG:
@@ -467,7 +452,7 @@ static int rndis_filter_query_device(struct rndis_device *dev, u32 oid,
if (ret != 0)
goto Cleanup;
- t = wait_for_completion_timeout(&request->wait_event, HZ);
+ t = wait_for_completion_timeout(&request->wait_event, 5*HZ);
if (t == 0) {
ret = -ETIMEDOUT;
goto Cleanup;
@@ -543,7 +528,7 @@ static int rndis_filter_set_packet_filter(struct rndis_device *dev,
if (ret != 0)
goto Cleanup;
- t = wait_for_completion_timeout(&request->wait_event, HZ);
+ t = wait_for_completion_timeout(&request->wait_event, 5*HZ);
if (t == 0) {
ret = -1;
@@ -600,7 +585,7 @@ static int rndis_filter_init_device(struct rndis_device *dev)
}
- t = wait_for_completion_timeout(&request->wait_event, HZ);
+ t = wait_for_completion_timeout(&request->wait_event, 5*HZ);
if (t == 0) {
ret = -ETIMEDOUT;
@@ -681,7 +666,7 @@ static int rndis_filter_close_device(struct rndis_device *dev)
return ret;
}
-int rndis_filte_device_add(struct hv_device *dev,
+int rndis_filter_device_add(struct hv_device *dev,
void *additional_info)
{
int ret;
@@ -741,7 +726,7 @@ int rndis_filte_device_add(struct hv_device *dev,
return ret;
}
-int rndis_filter_device_remove(struct hv_device *dev)
+void rndis_filter_device_remove(struct hv_device *dev)
{
struct netvsc_device *net_dev = dev->ext;
struct rndis_device *rndis_dev = net_dev->extension;
@@ -753,8 +738,6 @@ int rndis_filter_device_remove(struct hv_device *dev)
net_dev->extension = NULL;
netvsc_device_remove(dev);
-
- return 0;
}
diff --git a/drivers/staging/hv/storvsc.c b/drivers/staging/hv/storvsc.c
index 06cd3276813c..302978611943 100644
--- a/drivers/staging/hv/storvsc.c
+++ b/drivers/staging/hv/storvsc.c
@@ -135,7 +135,7 @@ static int storvsc_channel_init(struct hv_device *device)
if (ret != 0)
goto cleanup;
- t = wait_for_completion_timeout(&request->wait_event, HZ);
+ t = wait_for_completion_timeout(&request->wait_event, 5*HZ);
if (t == 0) {
ret = -ETIMEDOUT;
goto cleanup;
@@ -163,7 +163,7 @@ static int storvsc_channel_init(struct hv_device *device)
if (ret != 0)
goto cleanup;
- t = wait_for_completion_timeout(&request->wait_event, HZ);
+ t = wait_for_completion_timeout(&request->wait_event, 5*HZ);
if (t == 0) {
ret = -ETIMEDOUT;
goto cleanup;
@@ -192,7 +192,7 @@ static int storvsc_channel_init(struct hv_device *device)
if (ret != 0)
goto cleanup;
- t = wait_for_completion_timeout(&request->wait_event, HZ);
+ t = wait_for_completion_timeout(&request->wait_event, 5*HZ);
if (t == 0) {
ret = -ETIMEDOUT;
goto cleanup;
@@ -222,7 +222,7 @@ static int storvsc_channel_init(struct hv_device *device)
if (ret != 0)
goto cleanup;
- t = wait_for_completion_timeout(&request->wait_event, HZ);
+ t = wait_for_completion_timeout(&request->wait_event, 5*HZ);
if (t == 0) {
ret = -ETIMEDOUT;
goto cleanup;
diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c
index 942cc5f98db1..7effaf32e25f 100644
--- a/drivers/staging/hv/storvsc_drv.c
+++ b/drivers/staging/hv/storvsc_drv.c
@@ -24,6 +24,7 @@
#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>
@@ -44,7 +45,7 @@ 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 gStorVscDeviceType = {
+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
@@ -92,12 +93,8 @@ static int storvsc_device_configure(struct scsi_device *sdevice)
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);
@@ -308,31 +305,21 @@ static unsigned int copy_to_bounce_buffer(struct scatterlist *orig_sgl,
}
-/*
- * storvsc_remove - Callback when our device is removed
- */
static int storvsc_remove(struct hv_device *dev)
{
struct Scsi_Host *host = dev_get_drvdata(&dev->device);
struct hv_host_device *host_dev =
(struct hv_host_device *)host->hostdata;
- /*
- * Call to the vsc driver to let it know that the device is being
- * removed
- */
- storvsc_dev_remove(dev);
+ scsi_remove_host(host);
+
+ scsi_host_put(host);
+ storvsc_dev_remove(dev);
if (host_dev->request_pool) {
kmem_cache_destroy(host_dev->request_pool);
host_dev->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 0;
}
@@ -357,9 +344,6 @@ static int storvsc_get_chs(struct scsi_device *sdev, struct block_device * bdev,
info[1] = sectors_pt;
info[2] = (int)cylinders;
- DPRINT_INFO(STORVSC_DRV, "CHS (%d, %d, %d)", (int)cylinders, heads,
- sectors_pt);
-
return 0;
}
@@ -370,7 +354,6 @@ static int storvsc_host_reset(struct hv_device *device)
struct vstor_packet *vstor_packet;
int ret, t;
- DPRINT_INFO(STORVSC, "resetting host adapter...");
stor_device = get_stor_device(device);
if (!stor_device)
@@ -393,13 +376,12 @@ static int storvsc_host_reset(struct hv_device *device)
if (ret != 0)
goto cleanup;
- t = wait_for_completion_timeout(&request->wait_event, HZ);
+ t = wait_for_completion_timeout(&request->wait_event, 5*HZ);
if (t == 0) {
ret = -ETIMEDOUT;
goto cleanup;
}
- DPRINT_INFO(STORVSC, "host adapter reset completed");
/*
* At this point, all outstanding requests in the adapter
@@ -422,17 +404,10 @@ static int storvsc_host_reset_handler(struct scsi_cmnd *scmnd)
(struct hv_host_device *)scmnd->device->host->hostdata;
struct hv_device *dev = host_dev->dev;
- DPRINT_INFO(STORVSC_DRV, "sdev (%p) dev obj (%p) - host resetting...",
- scmnd->device, dev);
-
- /* Invokes the vsc to reset the host/bus */
ret = storvsc_host_reset(dev);
if (ret != 0)
return ret;
- DPRINT_INFO(STORVSC_DRV, "sdev (%p) dev obj (%p) - host reseted",
- scmnd->device, dev);
-
return ret;
}
@@ -479,7 +454,6 @@ static void storvsc_commmand_completion(struct hv_storvsc_request *request)
scmnd->host_scribble = NULL;
scmnd->scsi_done = NULL;
- /* !!DO NOT MODIFY the scmnd after this call */
scsi_done_fn(scmnd);
kmem_cache_free(host_dev->request_pool, cmd_request);
@@ -510,8 +484,6 @@ static int storvsc_queuecommand_lck(struct scsi_cmnd *scmnd,
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;
}
@@ -752,11 +724,28 @@ static struct hv_driver storvsc_drv = {
.remove = storvsc_remove,
};
-
/*
- * storvsc_drv_init - StorVsc driver initialization.
+ * 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 int storvsc_drv_init(void)
+
+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)
{
int ret;
struct hv_driver *drv = &storvsc_drv;
@@ -775,14 +764,13 @@ static int storvsc_drv_init(void)
sizeof(struct vstor_packet) + sizeof(u64),
sizeof(u64)));
- memcpy(&drv->dev_type, &gStorVscDeviceType,
+ 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->name = driver_name;
drv->driver.name = driver_name;
@@ -792,27 +780,13 @@ static int storvsc_drv_init(void)
return ret;
}
-static void storvsc_drv_exit(void)
+static void __exit storvsc_drv_exit(void)
{
vmbus_child_driver_unregister(&storvsc_drv.driver);
}
-static int __init storvsc_init(void)
-{
- int ret;
-
- DPRINT_INFO(STORVSC_DRV, "Storvsc initializing....");
- ret = storvsc_drv_init();
- return ret;
-}
-
-static void __exit storvsc_exit(void)
-{
- storvsc_drv_exit();
-}
-
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
index 33f0f1c8ad73..a4a407f7052a 100644
--- a/drivers/staging/hv/tools/hv_kvp_daemon.c
+++ b/drivers/staging/hv/tools/hv_kvp_daemon.c
@@ -35,7 +35,6 @@
#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>
diff --git a/drivers/staging/hv/vmbus_drv.c b/drivers/staging/hv/vmbus_drv.c
index ec1d38cd481c..1c949f5fb716 100644
--- a/drivers/staging/hv/vmbus_drv.c
+++ b/drivers/staging/hv/vmbus_drv.c
@@ -39,7 +39,7 @@
#include "hyperv_vmbus.h"
-static struct pci_dev *hv_pci_dev;
+static struct acpi_device *hv_acpi_dev;
static struct tasklet_struct msg_dpc;
static struct tasklet_struct event_dpc;
@@ -49,7 +49,6 @@ EXPORT_SYMBOL(vmbus_loglevel);
/* (ALL_MODULES << 16 | DEBUG_LVL_ENTEREXIT); */
/* (((VMBUS | VMBUS_DRV)<<16) | DEBUG_LVL_ENTEREXIT); */
-static int pci_probe_error;
static struct completion probe_event;
static int irq;
@@ -108,12 +107,12 @@ static ssize_t vmbus_show_device_attr(struct device *dev,
struct device_attribute *dev_attr,
char *buf)
{
- struct hv_device *device_ctx = device_to_hv_device(dev);
+ 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(device_ctx, &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-"
@@ -301,10 +300,10 @@ static int vmbus_match(struct device *device, struct device_driver *driver)
{
int match = 0;
struct hv_driver *drv = drv_to_hv_drv(driver);
- struct hv_device *device_ctx = device_to_hv_device(device);
+ struct hv_device *hv_dev = device_to_hv_device(device);
/* We found our driver ? */
- if (memcmp(&device_ctx->dev_type, &drv->dev_type,
+ if (memcmp(&hv_dev->dev_type, &drv->dev_type,
sizeof(struct hv_guid)) == 0)
match = 1;
@@ -330,7 +329,7 @@ static int vmbus_probe(struct device *child_device)
} else {
pr_err("probe not set for driver %s\n",
dev_name(child_device));
- ret = -1;
+ ret = -ENODEV;
}
return ret;
}
@@ -353,7 +352,7 @@ static int vmbus_remove(struct device *child_device)
} else {
pr_err("remove not set for driver %s\n",
dev_name(child_device));
- ret = -1;
+ ret = -ENODEV;
}
}
@@ -388,9 +387,9 @@ static void vmbus_shutdown(struct device *child_device)
*/
static void vmbus_device_release(struct device *device)
{
- struct hv_device *device_ctx = device_to_hv_device(device);
+ struct hv_device *hv_dev = device_to_hv_device(device);
- kfree(device_ctx);
+ kfree(hv_dev);
}
@@ -456,7 +455,7 @@ static void vmbus_on_msg_dpc(unsigned long data)
* will not deliver any more messages since there is
* no empty slot
*/
- mb();
+ smp_mb();
if (msg->header.message_flags.msg_pending) {
/*
@@ -487,7 +486,6 @@ static int vmbus_on_isr(void)
if (msg->header.message_type != HVMSG_NONE)
ret |= 0x1;
- /* TODO: Check if there are events to be process */
page_addr = hv_context.synic_event_page[cpu];
event = (union hv_synic_event_flags *)page_addr + VMBUS_MESSAGE_SINT;
@@ -528,7 +526,7 @@ static irqreturn_t vmbus_isr(int irq, void *dev_id)
* - get the irq resource
* - retrieve the channel offers
*/
-static int vmbus_bus_init(struct pci_dev *pdev)
+static int vmbus_bus_init(int irq)
{
int ret;
unsigned int vector;
@@ -537,7 +535,7 @@ static int vmbus_bus_init(struct pci_dev *pdev)
ret = hv_init();
if (ret != 0) {
pr_err("Unable to initialize the hypervisor - 0x%x\n", ret);
- goto cleanup;
+ return ret;
}
/* Initialize the bus context */
@@ -546,27 +544,23 @@ static int vmbus_bus_init(struct pci_dev *pdev)
/* Now, register the bus with LDM */
ret = bus_register(&hv_bus);
- if (ret) {
- ret = -1;
- goto cleanup;
- }
+ if (ret)
+ return ret;
/* Get the interrupt resource */
- ret = request_irq(pdev->irq, vmbus_isr,
- IRQF_SHARED | IRQF_SAMPLE_RANDOM,
- driver_name, pdev);
+ 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",
- pdev->irq);
+ irq);
bus_unregister(&hv_bus);
- ret = -1;
- goto cleanup;
+ return ret;
}
- vector = IRQ0_VECTOR + pdev->irq;
+ vector = IRQ0_VECTOR + irq;
/*
* Notify the hypervisor of our irq and
@@ -575,16 +569,15 @@ static int vmbus_bus_init(struct pci_dev *pdev)
on_each_cpu(hv_synic_init, (void *)&vector, 1);
ret = vmbus_connect();
if (ret) {
- free_irq(pdev->irq, pdev);
+ free_irq(irq, hv_acpi_dev);
bus_unregister(&hv_bus);
- goto cleanup;
+ return ret;
}
vmbus_request_offers();
-cleanup:
- return ret;
+ return 0;
}
/**
@@ -631,7 +624,6 @@ void vmbus_child_driver_unregister(struct device_driver *drv)
driver_unregister(drv);
- drv->bus = NULL;
}
EXPORT_SYMBOL(vmbus_child_driver_unregister);
@@ -676,7 +668,7 @@ int vmbus_child_device_register(struct hv_device *child_device_obj)
/* The new device belongs to this bus */
child_device_obj->device.bus = &hv_bus; /* device->dev.bus; */
- child_device_obj->device.parent = &hv_pci_dev->dev;
+ child_device_obj->device.parent = &hv_acpi_dev->dev;
child_device_obj->device.release = vmbus_device_release;
/*
@@ -733,6 +725,8 @@ 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);
@@ -747,6 +741,7 @@ static int vmbus_acpi_add(struct acpi_device *device)
static const struct acpi_device_id vmbus_acpi_device_ids[] = {
{"VMBUS", 0},
+ {"VMBus", 0},
{"", 0},
};
MODULE_DEVICE_TABLE(acpi, vmbus_acpi_device_ids);
@@ -759,53 +754,6 @@ static struct acpi_driver vmbus_acpi_driver = {
},
};
-static int vmbus_acpi_init(void)
-{
- int result;
-
-
- result = acpi_bus_register_driver(&vmbus_acpi_driver);
- if (result < 0)
- return result;
-
- return 0;
-}
-
-static void vmbus_acpi_exit(void)
-{
- acpi_bus_unregister_driver(&vmbus_acpi_driver);
-
- return;
-}
-
-
-static int __devinit hv_pci_probe(struct pci_dev *pdev,
- const struct pci_device_id *ent)
-{
- hv_pci_dev = pdev;
-
- pci_probe_error = pci_enable_device(pdev);
- if (pci_probe_error)
- goto probe_cleanup;
-
- /*
- * If the PCI sub-sytem did not assign us an
- * irq, use the bios provided one.
- */
-
- if (pdev->irq == 0)
- pdev->irq = irq;
-
- pci_probe_error = vmbus_bus_init(pdev);
-
- if (pci_probe_error)
- pci_disable_device(pdev);
-
-probe_cleanup:
- complete(&probe_event);
- return pci_probe_error;
-}
-
/*
* 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
@@ -818,13 +766,7 @@ static const struct pci_device_id microsoft_hv_pci_table[] = {
};
MODULE_DEVICE_TABLE(pci, microsoft_hv_pci_table);
-static struct pci_driver hv_bus_driver = {
- .name = "hv_bus",
- .probe = hv_pci_probe,
- .id_table = microsoft_hv_pci_table,
-};
-
-static int __init hv_pci_init(void)
+static int __init hv_acpi_init(void)
{
int ret;
@@ -834,32 +776,22 @@ static int __init hv_pci_init(void)
* Get irq resources first.
*/
- ret = vmbus_acpi_init();
+ ret = acpi_bus_register_driver(&vmbus_acpi_driver);
+
if (ret)
return ret;
wait_for_completion(&probe_event);
if (irq <= 0) {
- vmbus_acpi_exit();
+ acpi_bus_unregister_driver(&vmbus_acpi_driver);
return -ENODEV;
}
- vmbus_acpi_exit();
- init_completion(&probe_event);
- ret = pci_register_driver(&hv_bus_driver);
+ ret = vmbus_bus_init(irq);
if (ret)
- return ret;
- /*
- * All the vmbus initialization occurs within the
- * hv_pci_probe() function. Wait for hv_pci_probe()
- * to complete.
- */
- wait_for_completion(&probe_event);
-
- if (pci_probe_error)
- pci_unregister_driver(&hv_bus_driver);
- return pci_probe_error;
+ acpi_bus_unregister_driver(&vmbus_acpi_driver);
+ return ret;
}
@@ -867,4 +799,4 @@ MODULE_LICENSE("GPL");
MODULE_VERSION(HV_DRV_VERSION);
module_param(vmbus_loglevel, int, S_IRUGO|S_IWUSR);
-module_init(hv_pci_init);
+module_init(hv_acpi_init);