From 4b2f9abea52af3782d349080fca5e189b0693792 Mon Sep 17 00:00:00 2001
From: =?utf8?q?Timo=20Ter=C3=A4s?= <timo.teras@iki.fi>
Date: Wed, 15 Dec 2010 20:48:09 +0200
Subject: [PATCH] staging: hv: convert channel_mgmt.c to not call
 osd_schedule_callback
MIME-Version: 1.0
Content-Type: text/plain; charset=utf8
Content-Transfer-Encoding: 8bit

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 <hjanssen@microsoft.com>
Cc: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Timo Teräs <timo.teras@iki.fi>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
---
 drivers/staging/hv/channel_mgmt.c | 52 ++++++++++++++++++-------------
 drivers/staging/hv/channel_mgmt.h |  1 +
 2 files changed, 31 insertions(+), 22 deletions(-)

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