aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hv
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/hv')
-rw-r--r--drivers/hv/connection.c26
-rw-r--r--drivers/hv/vmbus_drv.c27
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)
321void vmbus_on_event(unsigned long data) 321void 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