summaryrefslogtreecommitdiff
path: root/drivers/hv/connection.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/hv/connection.c')
-rw-r--r--drivers/hv/connection.c55
1 files changed, 17 insertions, 38 deletions
diff --git a/drivers/hv/connection.c b/drivers/hv/connection.c
index 307a5a8937f6..1766ef03e78d 100644
--- a/drivers/hv/connection.c
+++ b/drivers/hv/connection.c
@@ -379,17 +379,11 @@ static void process_chn_event(u32 relid)
*/
void vmbus_on_event(unsigned long data)
{
- u32 dword;
- u32 maxdword;
- int bit;
- u32 relid;
- u32 *recv_int_page = NULL;
- void *page_addr;
- int cpu = smp_processor_id();
- union hv_synic_event_flags *event;
+ unsigned long *recv_int_page;
+ u32 maxbits, relid;
if (vmbus_proto_version < VERSION_WIN8) {
- maxdword = MAX_NUM_CHANNELS_SUPPORTED >> 5;
+ maxbits = MAX_NUM_CHANNELS_SUPPORTED;
recv_int_page = vmbus_connection.recv_int_page;
} else {
/*
@@ -397,35 +391,24 @@ void vmbus_on_event(unsigned long data)
* can be directly checked to get the id of the channel
* that has the interrupt pending.
*/
- maxdword = HV_EVENT_FLAGS_DWORD_COUNT;
- page_addr = hv_context.synic_event_page[cpu];
- event = (union hv_synic_event_flags *)page_addr +
+ int cpu = smp_processor_id();
+ void *page_addr = hv_context.synic_event_page[cpu];
+ union hv_synic_event_flags *event
+ = (union hv_synic_event_flags *)page_addr +
VMBUS_MESSAGE_SINT;
- recv_int_page = event->flags32;
- }
-
+ maxbits = HV_EVENT_FLAGS_COUNT;
+ recv_int_page = event->flags;
+ }
- /* Check events */
- if (!recv_int_page)
+ if (unlikely(!recv_int_page))
return;
- for (dword = 0; dword < maxdword; dword++) {
- if (!recv_int_page[dword])
- continue;
- for (bit = 0; bit < 32; bit++) {
- if (sync_test_and_clear_bit(bit,
- (unsigned long *)&recv_int_page[dword])) {
- relid = (dword << 5) + bit;
-
- if (relid == 0)
- /*
- * Special case - vmbus
- * channel protocol msg
- */
- continue;
+ for_each_set_bit(relid, recv_int_page, maxbits) {
+ if (sync_test_and_clear_bit(relid, recv_int_page)) {
+ /* Special case - vmbus channel protocol msg */
+ if (relid != 0)
process_chn_event(relid);
- }
}
}
}
@@ -491,12 +474,8 @@ void vmbus_set_event(struct vmbus_channel *channel)
{
u32 child_relid = channel->offermsg.child_relid;
- if (!channel->is_dedicated_interrupt) {
- /* Each u32 represents 32 channels */
- sync_set_bit(child_relid & 31,
- (unsigned long *)vmbus_connection.send_int_page +
- (child_relid >> 5));
- }
+ if (!channel->is_dedicated_interrupt)
+ vmbus_send_interrupt(child_relid);
hv_do_hypercall(HVCALL_SIGNAL_EVENT, channel->sig_event, NULL);
}