Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Timo Teräs and committed by
Greg Kroah-Hartman
bf6506f6 f4528696

+21 -11
-4
drivers/staging/hv/channel_mgmt.c
··· 753 753 hdr->msgtype, size); 754 754 print_hex_dump_bytes("", DUMP_PREFIX_NONE, 755 755 (unsigned char *)msg->u.payload, size); 756 - kfree(msg); 757 756 return; 758 757 } 759 758 ··· 761 762 else 762 763 DPRINT_ERR(VMBUS, "Unhandled channel message type %d", 763 764 hdr->msgtype); 764 - 765 - /* Free the msg that was allocated in VmbusOnMsgDPC() */ 766 - kfree(msg); 767 765 } 768 766 769 767 /*
+21 -7
drivers/staging/hv/vmbus_drv.c
··· 203 203 hv_cleanup(); 204 204 } 205 205 206 + struct onmessage_work_context { 207 + struct work_struct work; 208 + struct hv_message msg; 209 + }; 210 + 211 + static void vmbus_onmessage_work(struct work_struct *work) 212 + { 213 + struct onmessage_work_context *ctx; 214 + 215 + ctx = container_of(work, struct onmessage_work_context, 216 + work); 217 + vmbus_onmessage(&ctx->msg); 218 + kfree(ctx); 219 + } 220 + 206 221 /* 207 222 * vmbus_on_msg_dpc - DPC routine to handle messages from the hypervisior 208 223 */ ··· 227 212 void *page_addr = hv_context.synic_message_page[cpu]; 228 213 struct hv_message *msg = (struct hv_message *)page_addr + 229 214 VMBUS_MESSAGE_SINT; 230 - struct hv_message *copied; 215 + struct onmessage_work_context *ctx; 231 216 232 217 while (1) { 233 218 if (msg->header.message_type == HVMSG_NONE) { 234 219 /* no msg */ 235 220 break; 236 221 } else { 237 - copied = kmemdup(msg, sizeof(*copied), GFP_ATOMIC); 238 - if (copied == NULL) 222 + ctx = kmalloc(sizeof(*ctx), GFP_ATOMIC); 223 + if (ctx == NULL) 239 224 continue; 240 - 241 - osd_schedule_callback(gVmbusConnection.WorkQueue, 242 - vmbus_onmessage, 243 - (void *)copied); 225 + INIT_WORK(&ctx->work, vmbus_onmessage_work); 226 + memcpy(&ctx->msg, msg, sizeof(*msg)); 227 + queue_work(gVmbusConnection.WorkQueue, &ctx->work); 244 228 } 245 229 246 230 msg->header.message_type = HVMSG_NONE;