aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorK. Y. Srinivasan <kys@microsoft.com>2012-12-01 09:46:49 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-01-17 14:39:15 -0500
commit6552ecd70cc6f31f4bb9d63f36a7dd023db3e519 (patch)
treec049853ac72d2720afcac4f896752657499a7aac /drivers
parentabbf3b2aa090b4a6bf22c935924b6467990266da (diff)
Drivers: hv: Modify the interrupt handling code to support win8 and beyond
Starting with Win8 (WS2012), the event page can be used to directly get the channel ID that needs servicing. Modify the channel event handling code to take advantage of this feature. Signed-off-by: K. Y. Srinivasan <kys@microsoft.com> Reviewed-by: Haiyang Zhang <haiyangz@microsoft.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers')
-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