diff options
author | K. Y. Srinivasan <kys@microsoft.com> | 2011-10-09 22:42:28 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2011-10-11 00:50:00 -0400 |
commit | e2bb65378385a10e21612845e33cd5936e0cbadb (patch) | |
tree | efd641a6591d29e5a05da80ce6eb707b0c1c3cde /drivers | |
parent | 76e5f8135d63eb784ef44438e46e82cf0329e179 (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>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/staging/hv/hv_kvp.c | 18 |
1 files changed, 11 insertions, 7 deletions
diff --git a/drivers/staging/hv/hv_kvp.c b/drivers/staging/hv/hv_kvp.c index 307aedc08a36..1e9515cc6094 100644 --- a/drivers/staging/hv/hv_kvp.c +++ b/drivers/staging/hv/hv_kvp.c | |||
@@ -44,11 +44,12 @@ | |||
44 | static struct { | 44 | static 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 | ||
51 | static int kvp_send_key(int index); | 52 | static 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); | |||
57 | static void kvp_register(void); | 58 | static void kvp_register(void); |
58 | 59 | ||
59 | static DECLARE_DELAYED_WORK(kvp_work, kvp_work_func); | 60 | static DECLARE_DELAYED_WORK(kvp_work, kvp_work_func); |
61 | static DECLARE_WORK(kvp_sendkey_work, kvp_send_key); | ||
60 | 62 | ||
61 | static struct cb_id kvp_id = { CN_KVP_IDX, CN_KVP_VAL }; | 63 | static struct cb_id kvp_id = { CN_KVP_IDX, CN_KVP_VAL }; |
62 | static const char kvp_name[] = "kvp_kernel_module"; | 64 | static 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 | ||
124 | static int | 126 | static void |
125 | kvp_send_key(int index) | 127 | kvp_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 | } |