Commit 6552ecd7 authored by K. Y. Srinivasan's avatar K. Y. Srinivasan Committed by Greg Kroah-Hartman

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: default avatarK. Y. Srinivasan <kys@microsoft.com>
Reviewed-by: default avatarHaiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent abbf3b2a
...@@ -321,10 +321,32 @@ static void process_chn_event(u32 relid) ...@@ -321,10 +321,32 @@ static void process_chn_event(u32 relid)
void vmbus_on_event(unsigned long data) void vmbus_on_event(unsigned long data)
{ {
u32 dword; u32 dword;
u32 maxdword = MAX_NUM_CHANNELS_SUPPORTED >> 5; u32 maxdword;
int bit; int bit;
u32 relid; u32 relid;
u32 *recv_int_page = vmbus_connection.recv_int_page; u32 *recv_int_page = NULL;
void *page_addr;
int cpu = smp_processor_id();
union hv_synic_event_flags *event;
if ((vmbus_proto_version == VERSION_WS2008) ||
(vmbus_proto_version == VERSION_WIN7)) {
maxdword = MAX_NUM_CHANNELS_SUPPORTED >> 5;
recv_int_page = vmbus_connection.recv_int_page;
} else {
/*
* When the host is win8 and beyond, the event page
* 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 +
VMBUS_MESSAGE_SINT;
recv_int_page = event->flags32;
}
/* Check events */ /* Check events */
if (!recv_int_page) if (!recv_int_page)
......
...@@ -460,15 +460,32 @@ static irqreturn_t vmbus_isr(int irq, void *dev_id) ...@@ -460,15 +460,32 @@ static irqreturn_t vmbus_isr(int irq, void *dev_id)
* Hyper-V, and the Windows team suggested we do the same. * Hyper-V, and the Windows team suggested we do the same.
*/ */
page_addr = hv_context.synic_event_page[cpu]; if ((vmbus_proto_version == VERSION_WS2008) ||
event = (union hv_synic_event_flags *)page_addr + VMBUS_MESSAGE_SINT; (vmbus_proto_version == VERSION_WIN7)) {
/* Since we are a child, we only need to check bit 0 */ page_addr = hv_context.synic_event_page[cpu];
if (sync_test_and_clear_bit(0, (unsigned long *) &event->flags32[0])) { event = (union hv_synic_event_flags *)page_addr +
VMBUS_MESSAGE_SINT;
/* Since we are a child, we only need to check bit 0 */
if (sync_test_and_clear_bit(0,
(unsigned long *) &event->flags32[0])) {
handled = true;
}
} else {
/*
* Our host is win8 or above. The signaling mechanism
* has changed and we can directly look at the event page.
* If bit n is set then we have an interrup on the channel
* whose id is n.
*/
handled = true; handled = true;
tasklet_schedule(&event_dpc);
} }
if (handled)
tasklet_schedule(&event_dpc);
page_addr = hv_context.synic_message_page[cpu]; page_addr = hv_context.synic_message_page[cpu];
msg = (struct hv_message *)page_addr + VMBUS_MESSAGE_SINT; msg = (struct hv_message *)page_addr + VMBUS_MESSAGE_SINT;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment