diff options
author | Timo Teräs <timo.teras@iki.fi> | 2010-12-15 20:48:08 +0200 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-12-16 12:35:14 -0800 |
commit | bf6506f60c46c8a709df534408cc6d470df657ff (patch) | |
tree | b870adf16c465d746796cda01def14d7a8d97046 /drivers/staging/hv | |
parent | f4528696d803749892eac27422a6fd7748cffee1 (diff) |
staging: hv: convert vmbus_on_msg_dpc to not call osd_schedule_callback
The additional abstraction is unneeded. This also fixes a sleeping
while atomic issue as osd_schedule_callback can sleep which is
not allowed for vmbus_on_msg_dpc running in a tasklet.
Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=16701
Reviewed-By: Hank Janssen <hjanssen@microsoft.com>
Cc: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Timo Teräs <timo.teras@iki.fi>
Cc: stable <stable@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/staging/hv')
-rw-r--r-- | drivers/staging/hv/channel_mgmt.c | 4 | ||||
-rw-r--r-- | drivers/staging/hv/vmbus_drv.c | 28 |
2 files changed, 21 insertions, 11 deletions
diff --git a/drivers/staging/hv/channel_mgmt.c b/drivers/staging/hv/channel_mgmt.c index 0f4d6093f674..6f393e7d8e25 100644 --- a/drivers/staging/hv/channel_mgmt.c +++ b/drivers/staging/hv/channel_mgmt.c @@ -753,7 +753,6 @@ void vmbus_onmessage(void *context) hdr->msgtype, size); print_hex_dump_bytes("", DUMP_PREFIX_NONE, (unsigned char *)msg->u.payload, size); - kfree(msg); return; } @@ -762,9 +761,6 @@ void vmbus_onmessage(void *context) else DPRINT_ERR(VMBUS, "Unhandled channel message type %d", hdr->msgtype); - - /* Free the msg that was allocated in VmbusOnMsgDPC() */ - kfree(msg); } /* diff --git a/drivers/staging/hv/vmbus_drv.c b/drivers/staging/hv/vmbus_drv.c index d794b603bf17..84fdb64d3ceb 100644 --- a/drivers/staging/hv/vmbus_drv.c +++ b/drivers/staging/hv/vmbus_drv.c @@ -203,6 +203,21 @@ static void VmbusOnCleanup(struct hv_driver *drv) hv_cleanup(); } +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_on_msg_dpc - DPC routine to handle messages from the hypervisior */ @@ -212,20 +227,19 @@ static void vmbus_on_msg_dpc(struct hv_driver *drv) void *page_addr = hv_context.synic_message_page[cpu]; struct hv_message *msg = (struct hv_message *)page_addr + VMBUS_MESSAGE_SINT; - struct hv_message *copied; + struct onmessage_work_context *ctx; while (1) { if (msg->header.message_type == HVMSG_NONE) { /* no msg */ break; } else { - copied = kmemdup(msg, sizeof(*copied), GFP_ATOMIC); - if (copied == NULL) + ctx = kmalloc(sizeof(*ctx), GFP_ATOMIC); + if (ctx == NULL) continue; - - osd_schedule_callback(gVmbusConnection.WorkQueue, - vmbus_onmessage, - (void *)copied); + INIT_WORK(&ctx->work, vmbus_onmessage_work); + memcpy(&ctx->msg, msg, sizeof(*msg)); + queue_work(gVmbusConnection.WorkQueue, &ctx->work); } msg->header.message_type = HVMSG_NONE; |