diff options
Diffstat (limited to 'drivers/hv')
-rw-r--r-- | drivers/hv/connection.c | 26 | ||||
-rw-r--r-- | drivers/hv/vmbus_drv.c | 27 |
2 files changed, 46 insertions, 7 deletions
diff --git a/drivers/hv/connection.c b/drivers/hv/connection.c index 114050dc8e28..ac71653abb77 100644 --- a/drivers/hv/connection.c +++ b/drivers/hv/connection.c | |||
@@ -321,10 +321,32 @@ static void process_chn_event(u32 relid) | |||
321 | void vmbus_on_event(unsigned long data) | 321 | void vmbus_on_event(unsigned long data) |
322 | { | 322 | { |
323 | u32 dword; | 323 | u32 dword; |
324 | u32 maxdword = MAX_NUM_CHANNELS_SUPPORTED >> 5; | 324 | u32 maxdword; |
325 | int bit; | 325 | int bit; |
326 | u32 relid; | 326 | u32 relid; |
327 | u32 *recv_int_page = vmbus_connection.recv_int_page; | 327 | u32 *recv_int_page = NULL; |
328 | void *page_addr; | ||
329 | int cpu = smp_processor_id(); | ||
330 | union hv_synic_event_flags *event; | ||
331 | |||
332 | if ((vmbus_proto_version == VERSION_WS2008) || | ||
333 | (vmbus_proto_version == VERSION_WIN7)) { | ||
334 | maxdword = MAX_NUM_CHANNELS_SUPPORTED >> 5; | ||
335 | recv_int_page = vmbus_connection.recv_int_page; | ||
336 | } else { | ||
337 | /* | ||
338 | * When the host is win8 and beyond, the event page | ||
339 | * can be directly checked to get the id of the channel | ||
340 | * that has the interrupt pending. | ||
341 | */ | ||
342 | maxdword = HV_EVENT_FLAGS_DWORD_COUNT; | ||
343 | page_addr = hv_context.synic_event_page[cpu]; | ||
344 | event = (union hv_synic_event_flags *)page_addr + | ||
345 | VMBUS_MESSAGE_SINT; | ||
346 | recv_int_page = event->flags32; | ||
347 | } | ||
348 | |||
349 | |||
328 | 350 | ||
329 | /* Check events */ | 351 | /* Check events */ |
330 | if (!recv_int_page) | 352 | if (!recv_int_page) |
diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c index 8e1a9ec53003..c583a0403c53 100644 --- a/drivers/hv/vmbus_drv.c +++ b/drivers/hv/vmbus_drv.c | |||
@@ -460,15 +460,32 @@ static irqreturn_t vmbus_isr(int irq, void *dev_id) | |||
460 | * Hyper-V, and the Windows team suggested we do the same. | 460 | * Hyper-V, and the Windows team suggested we do the same. |
461 | */ | 461 | */ |
462 | 462 | ||
463 | page_addr = hv_context.synic_event_page[cpu]; | 463 | if ((vmbus_proto_version == VERSION_WS2008) || |
464 | event = (union hv_synic_event_flags *)page_addr + VMBUS_MESSAGE_SINT; | 464 | (vmbus_proto_version == VERSION_WIN7)) { |
465 | 465 | ||
466 | /* Since we are a child, we only need to check bit 0 */ | 466 | page_addr = hv_context.synic_event_page[cpu]; |
467 | if (sync_test_and_clear_bit(0, (unsigned long *) &event->flags32[0])) { | 467 | event = (union hv_synic_event_flags *)page_addr + |
468 | VMBUS_MESSAGE_SINT; | ||
469 | |||
470 | /* Since we are a child, we only need to check bit 0 */ | ||
471 | if (sync_test_and_clear_bit(0, | ||
472 | (unsigned long *) &event->flags32[0])) { | ||
473 | handled = true; | ||
474 | } | ||
475 | } else { | ||
476 | /* | ||
477 | * Our host is win8 or above. The signaling mechanism | ||
478 | * has changed and we can directly look at the event page. | ||
479 | * If bit n is set then we have an interrup on the channel | ||
480 | * whose id is n. | ||
481 | */ | ||
468 | handled = true; | 482 | handled = true; |
469 | tasklet_schedule(&event_dpc); | ||
470 | } | 483 | } |
471 | 484 | ||
485 | if (handled) | ||
486 | tasklet_schedule(&event_dpc); | ||
487 | |||
488 | |||
472 | page_addr = hv_context.synic_message_page[cpu]; | 489 | page_addr = hv_context.synic_message_page[cpu]; |
473 | msg = (struct hv_message *)page_addr + VMBUS_MESSAGE_SINT; | 490 | msg = (struct hv_message *)page_addr + VMBUS_MESSAGE_SINT; |
474 | 491 | ||