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 | |
| 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>
| -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; | 
