From: Timo Teräs Date: Wed, 15 Dec 2010 18:48:09 +0000 (+0200) Subject: staging: hv: convert channel_mgmt.c to not call osd_schedule_callback X-Git-Tag: v2.6.38-rc1~423^2~5 X-Git-Url: https://git.openpandora.org/cgi-bin/gitweb.cgi?p=pandora-kernel.git;a=commitdiff_plain;h=4b2f9abea52af3782d349080fca5e189b0693792 staging: hv: convert channel_mgmt.c to not call osd_schedule_callback The additional abstraction is unneeded. The three calls are assumed to not be pending simultaneously: - vmbus_onoffer queues work exactly once when a new channel is created, the channel is not attached to lists until the work is executed - vmbus_onoffer_rescind is received only when the channel is active it is enough to process the work once - free_channel is called exactly once when the channel is getting destroyed; I assumed that vmbus_process_rescind_offer cannot be pending while free_channel is called Reviewed-By: Hank Janssen Cc: Haiyang Zhang Signed-off-by: Timo Teräs Signed-off-by: Greg Kroah-Hartman --- diff --git a/drivers/staging/hv/channel_mgmt.c b/drivers/staging/hv/channel_mgmt.c index 6f393e7d8e25..d44d5c39f68b 100644 --- a/drivers/staging/hv/channel_mgmt.c +++ b/drivers/staging/hv/channel_mgmt.c @@ -263,9 +263,11 @@ static struct vmbus_channel *alloc_channel(void) /* * release_hannel - Release the vmbus channel object itself */ -static inline void release_channel(void *context) +static void release_channel(struct work_struct *work) { - struct vmbus_channel *channel = context; + struct vmbus_channel *channel = container_of(work, + struct vmbus_channel, + work); DPRINT_DBG(VMBUS, "releasing channel (%p)", channel); destroy_workqueue(channel->controlwq); @@ -286,8 +288,8 @@ void free_channel(struct vmbus_channel *channel) * workqueue/thread context * ie we can't destroy ourselves. */ - osd_schedule_callback(gVmbusConnection.WorkQueue, release_channel, - channel); + INIT_WORK(&channel->work, release_channel); + queue_work(gVmbusConnection.WorkQueue, &channel->work); } @@ -308,20 +310,37 @@ static void count_hv_channel(void) spin_unlock_irqrestore(&gVmbusConnection.channel_lock, flags); } +/* + * 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(void *context) +static void vmbus_process_offer(struct work_struct *work) { - struct vmbus_channel *newchannel = context; + 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(&gVmbusConnection.channel_lock, flags); @@ -405,17 +424,6 @@ static void vmbus_process_offer(void *context) } } -/* - * vmbus_process_rescind_offer - - * Rescind the offer by initiating a device removal - */ -static void vmbus_process_rescind_offer(void *context) -{ - struct vmbus_channel *channel = context; - - vmbus_child_device_unregister(channel->device_obj); -} - /* * vmbus_onoffer - Handler for channel offers from vmbus in parent partition. * @@ -490,8 +498,8 @@ static void vmbus_onoffer(struct vmbus_channel_message_header *hdr) newchannel->monitor_bit = (u8)offer->monitorid % 32; /* TODO: Make sure the offer comes from our parent partition */ - osd_schedule_callback(newchannel->controlwq, vmbus_process_offer, - newchannel); + INIT_WORK(&newchannel->work, vmbus_process_offer); + queue_work(newchannel->controlwq, &newchannel->work); } /* @@ -512,9 +520,9 @@ static void vmbus_onoffer_rescind(struct vmbus_channel_message_header *hdr) return; } - osd_schedule_callback(channel->controlwq, - vmbus_process_rescind_offer, - channel); + /* work is initialized for vmbus_process_rescind_offer() from + * vmbus_process_offer() where the channel got created */ + queue_work(channel->controlwq, &channel->work); } /* diff --git a/drivers/staging/hv/channel_mgmt.h b/drivers/staging/hv/channel_mgmt.h index 12f30aff152d..de6b2a0ebf70 100644 --- a/drivers/staging/hv/channel_mgmt.h +++ b/drivers/staging/hv/channel_mgmt.h @@ -231,6 +231,7 @@ struct vmbus_channel { struct hv_device *device_obj; struct timer_list poll_timer; /* SA-111 workaround */ + struct work_struct work; enum vmbus_channel_state state;