aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorOlaf Hering <olaf@aepfle.de>2011-03-21 09:41:37 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2011-04-05 00:33:25 -0400
commit22356585712d1ff08fbfed152edd8b386873b238 (patch)
treeaeb0a6192077d4865d06f6b35cdbf789b390ca99 /drivers
parent75e4fb221babbe329c1aba8c34092d29034f1545 (diff)
staging: hv: use sync_bitops when interacting with the hypervisor
Locking is required when tweaking bits located in a shared page, use the sync_ version of bitops. Without this change vmbus_on_event() will miss events and as a result, vmbus_isr() will not schedule the receive tasklet. Signed-off-by: Olaf Hering <olaf@aepfle.de> Cc: stable <stable@kernel.org> Acked-by: Haiyang Zhang <haiyangz@microsoft.com> Acked-by: Hank Janssen <hjanssen@microsoft.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/staging/hv/channel.c8
-rw-r--r--drivers/staging/hv/connection.c4
-rw-r--r--drivers/staging/hv/vmbus_drv.c2
-rw-r--r--drivers/staging/hv/vmbus_private.h1
4 files changed, 8 insertions, 7 deletions
diff --git a/drivers/staging/hv/channel.c b/drivers/staging/hv/channel.c
index 775a52a91222..f7ce7d2494b3 100644
--- a/drivers/staging/hv/channel.c
+++ b/drivers/staging/hv/channel.c
@@ -81,14 +81,14 @@ static void vmbus_setevent(struct vmbus_channel *channel)
81 81
82 if (channel->offermsg.monitor_allocated) { 82 if (channel->offermsg.monitor_allocated) {
83 /* Each u32 represents 32 channels */ 83 /* Each u32 represents 32 channels */
84 set_bit(channel->offermsg.child_relid & 31, 84 sync_set_bit(channel->offermsg.child_relid & 31,
85 (unsigned long *) vmbus_connection.send_int_page + 85 (unsigned long *) vmbus_connection.send_int_page +
86 (channel->offermsg.child_relid >> 5)); 86 (channel->offermsg.child_relid >> 5));
87 87
88 monitorpage = vmbus_connection.monitor_pages; 88 monitorpage = vmbus_connection.monitor_pages;
89 monitorpage++; /* Get the child to parent monitor page */ 89 monitorpage++; /* Get the child to parent monitor page */
90 90
91 set_bit(channel->monitor_bit, 91 sync_set_bit(channel->monitor_bit,
92 (unsigned long *)&monitorpage->trigger_group 92 (unsigned long *)&monitorpage->trigger_group
93 [channel->monitor_grp].pending); 93 [channel->monitor_grp].pending);
94 94
@@ -104,7 +104,7 @@ static void VmbusChannelClearEvent(struct vmbus_channel *channel)
104 104
105 if (Channel->offermsg.monitor_allocated) { 105 if (Channel->offermsg.monitor_allocated) {
106 /* Each u32 represents 32 channels */ 106 /* Each u32 represents 32 channels */
107 clear_bit(Channel->offermsg.child_relid & 31, 107 sync_clear_bit(Channel->offermsg.child_relid & 31,
108 (unsigned long *)vmbus_connection.send_int_page + 108 (unsigned long *)vmbus_connection.send_int_page +
109 (Channel->offermsg.child_relid >> 5)); 109 (Channel->offermsg.child_relid >> 5));
110 110
@@ -112,7 +112,7 @@ static void VmbusChannelClearEvent(struct vmbus_channel *channel)
112 vmbus_connection.monitor_pages; 112 vmbus_connection.monitor_pages;
113 monitorPage++; /* Get the child to parent monitor page */ 113 monitorPage++; /* Get the child to parent monitor page */
114 114
115 clear_bit(Channel->monitor_bit, 115 sync_clear_bit(Channel->monitor_bit,
116 (unsigned long *)&monitorPage->trigger_group 116 (unsigned long *)&monitorPage->trigger_group
117 [Channel->monitor_grp].Pending); 117 [Channel->monitor_grp].Pending);
118 } 118 }
diff --git a/drivers/staging/hv/connection.c b/drivers/staging/hv/connection.c
index 44b203b95a22..afc8116e7aa4 100644
--- a/drivers/staging/hv/connection.c
+++ b/drivers/staging/hv/connection.c
@@ -296,7 +296,7 @@ void vmbus_on_event(unsigned long data)
296 for (dword = 0; dword < maxdword; dword++) { 296 for (dword = 0; dword < maxdword; dword++) {
297 if (recv_int_page[dword]) { 297 if (recv_int_page[dword]) {
298 for (bit = 0; bit < 32; bit++) { 298 for (bit = 0; bit < 32; bit++) {
299 if (test_and_clear_bit(bit, 299 if (sync_test_and_clear_bit(bit,
300 (unsigned long *) 300 (unsigned long *)
301 &recv_int_page[dword])) { 301 &recv_int_page[dword])) {
302 relid = (dword << 5) + bit; 302 relid = (dword << 5) + bit;
@@ -338,7 +338,7 @@ int vmbus_post_msg(void *buffer, size_t buflen)
338int vmbus_set_event(u32 child_relid) 338int vmbus_set_event(u32 child_relid)
339{ 339{
340 /* Each u32 represents 32 channels */ 340 /* Each u32 represents 32 channels */
341 set_bit(child_relid & 31, 341 sync_set_bit(child_relid & 31,
342 (unsigned long *)vmbus_connection.send_int_page + 342 (unsigned long *)vmbus_connection.send_int_page +
343 (child_relid >> 5)); 343 (child_relid >> 5));
344 344
diff --git a/drivers/staging/hv/vmbus_drv.c b/drivers/staging/hv/vmbus_drv.c
index b473f468dd83..79089f85d903 100644
--- a/drivers/staging/hv/vmbus_drv.c
+++ b/drivers/staging/hv/vmbus_drv.c
@@ -254,7 +254,7 @@ static int vmbus_on_isr(void)
254 event = (union hv_synic_event_flags *)page_addr + VMBUS_MESSAGE_SINT; 254 event = (union hv_synic_event_flags *)page_addr + VMBUS_MESSAGE_SINT;
255 255
256 /* Since we are a child, we only need to check bit 0 */ 256 /* Since we are a child, we only need to check bit 0 */
257 if (test_and_clear_bit(0, (unsigned long *) &event->flags32[0])) { 257 if (sync_test_and_clear_bit(0, (unsigned long *) &event->flags32[0])) {
258 DPRINT_DBG(VMBUS, "received event %d", event->flags32[0]); 258 DPRINT_DBG(VMBUS, "received event %d", event->flags32[0]);
259 ret |= 0x2; 259 ret |= 0x2;
260 } 260 }
diff --git a/drivers/staging/hv/vmbus_private.h b/drivers/staging/hv/vmbus_private.h
index ca050a499b99..6f0d8df5e178 100644
--- a/drivers/staging/hv/vmbus_private.h
+++ b/drivers/staging/hv/vmbus_private.h
@@ -31,6 +31,7 @@
31#include "channel_mgmt.h" 31#include "channel_mgmt.h"
32#include "ring_buffer.h" 32#include "ring_buffer.h"
33#include <linux/list.h> 33#include <linux/list.h>
34#include <asm/sync_bitops.h>
34 35
35 36
36/* 37/*