diff options
| -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 | ||
