diff options
author | Olaf Hering <olaf@aepfle.de> | 2011-03-21 09:41:37 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2011-04-05 00:33:25 -0400 |
commit | 22356585712d1ff08fbfed152edd8b386873b238 (patch) | |
tree | aeb0a6192077d4865d06f6b35cdbf789b390ca99 /drivers | |
parent | 75e4fb221babbe329c1aba8c34092d29034f1545 (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.c | 8 | ||||
-rw-r--r-- | drivers/staging/hv/connection.c | 4 | ||||
-rw-r--r-- | drivers/staging/hv/vmbus_drv.c | 2 | ||||
-rw-r--r-- | drivers/staging/hv/vmbus_private.h | 1 |
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) | |||
338 | int vmbus_set_event(u32 child_relid) | 338 | int 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 | /* |