aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorK. Y. Srinivasan <kys@microsoft.com>2011-10-09 22:42:28 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2011-10-11 00:50:00 -0400
commite2bb65378385a10e21612845e33cd5936e0cbadb (patch)
treeefd641a6591d29e5a05da80ce6eb707b0c1c3cde
parent76e5f8135d63eb784ef44438e46e82cf0329e179 (diff)
Staging: hv: util: Invoke cn_netlink_send() in a work context
Invoke cn_netlink_send() in a work context as opposed being called in the context of channel callback. On entry into the channel callback code the channel inbound spin lock is held and deferring to a work context avoids having to invoke cn_netlink_send() while holding the inbound lock. As part of this adjustment, also increase the timeout value for waiting for the user level component of KVP. Signed-off-by: K. Y. Srinivasan <kys@microsoft.com> Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r--drivers/staging/hv/hv_kvp.c18
1 files changed, 11 insertions, 7 deletions
diff --git a/drivers/staging/hv/hv_kvp.c b/drivers/staging/hv/hv_kvp.c
index 307aedc08a3..1e9515cc609 100644
--- a/drivers/staging/hv/hv_kvp.c
+++ b/drivers/staging/hv/hv_kvp.c
@@ -44,11 +44,12 @@
44static struct { 44static struct {
45 bool active; /* transaction status - active or not */ 45 bool active; /* transaction status - active or not */
46 int recv_len; /* number of bytes received. */ 46 int recv_len; /* number of bytes received. */
47 int index; /* current index */
47 struct vmbus_channel *recv_channel; /* chn we got the request */ 48 struct vmbus_channel *recv_channel; /* chn we got the request */
48 u64 recv_req_id; /* request ID. */ 49 u64 recv_req_id; /* request ID. */
49} kvp_transaction; 50} kvp_transaction;
50 51
51static int kvp_send_key(int index); 52static void kvp_send_key(struct work_struct *dummy);
52 53
53#define TIMEOUT_FIRED 1 54#define TIMEOUT_FIRED 1
54 55
@@ -57,6 +58,7 @@ static void kvp_work_func(struct work_struct *dummy);
57static void kvp_register(void); 58static void kvp_register(void);
58 59
59static DECLARE_DELAYED_WORK(kvp_work, kvp_work_func); 60static DECLARE_DELAYED_WORK(kvp_work, kvp_work_func);
61static DECLARE_WORK(kvp_sendkey_work, kvp_send_key);
60 62
61static struct cb_id kvp_id = { CN_KVP_IDX, CN_KVP_VAL }; 63static struct cb_id kvp_id = { CN_KVP_IDX, CN_KVP_VAL };
62static const char kvp_name[] = "kvp_kernel_module"; 64static const char kvp_name[] = "kvp_kernel_module";
@@ -121,10 +123,11 @@ kvp_cn_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp)
121 } 123 }
122} 124}
123 125
124static int 126static void
125kvp_send_key(int index) 127kvp_send_key(struct work_struct *dummy)
126{ 128{
127 struct cn_msg *msg; 129 struct cn_msg *msg;
130 int index = kvp_transaction.index;
128 131
129 msg = kzalloc(sizeof(*msg) + sizeof(struct hv_kvp_msg) , GFP_ATOMIC); 132 msg = kzalloc(sizeof(*msg) + sizeof(struct hv_kvp_msg) , GFP_ATOMIC);
130 133
@@ -136,9 +139,8 @@ kvp_send_key(int index)
136 msg->len = sizeof(struct hv_ku_msg); 139 msg->len = sizeof(struct hv_ku_msg);
137 cn_netlink_send(msg, 0, GFP_ATOMIC); 140 cn_netlink_send(msg, 0, GFP_ATOMIC);
138 kfree(msg); 141 kfree(msg);
139 return 0;
140 } 142 }
141 return 1; 143 return;
142} 144}
143 145
144/* 146/*
@@ -286,6 +288,7 @@ void hv_kvp_onchannelcallback(void *context)
286 kvp_transaction.recv_channel = channel; 288 kvp_transaction.recv_channel = channel;
287 kvp_transaction.recv_req_id = requestid; 289 kvp_transaction.recv_req_id = requestid;
288 kvp_transaction.active = true; 290 kvp_transaction.active = true;
291 kvp_transaction.index = kvp_data->index;
289 292
290 /* 293 /*
291 * Get the information from the 294 * Get the information from the
@@ -296,8 +299,8 @@ void hv_kvp_onchannelcallback(void *context)
296 * Set a timeout to deal with 299 * Set a timeout to deal with
297 * user-mode not responding. 300 * user-mode not responding.
298 */ 301 */
299 kvp_send_key(kvp_data->index); 302 schedule_work(&kvp_sendkey_work);
300 schedule_delayed_work(&kvp_work, 100); 303 schedule_delayed_work(&kvp_work, 5*HZ);
301 304
302 return; 305 return;
303 306
@@ -332,4 +335,5 @@ void hv_kvp_deinit(void)
332{ 335{
333 cn_del_callback(&kvp_id); 336 cn_del_callback(&kvp_id);
334 cancel_delayed_work_sync(&kvp_work); 337 cancel_delayed_work_sync(&kvp_work);
338 cancel_work_sync(&kvp_sendkey_work);
335} 339}