Skip to content

Commit

Permalink
Drivers: hv: Modify the interrupt handling code to support win8 and b…
Browse files Browse the repository at this point in the history
…eyond

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>
  • Loading branch information
K. Y. Srinivasan authored and Greg Kroah-Hartman committed Jan 17, 2013
1 parent abbf3b2 commit 6552ecd
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 7 deletions.
26 changes: 24 additions & 2 deletions drivers/hv/connection.c
Original file line number Diff line number Diff line change
Expand Up @@ -321,10 +321,32 @@ static void process_chn_event(u32 relid)
void vmbus_on_event(unsigned long data)
{
u32 dword;
u32 maxdword = MAX_NUM_CHANNELS_SUPPORTED >> 5;
u32 maxdword;
int bit;
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 */
if (!recv_int_page)
Expand Down
27 changes: 22 additions & 5 deletions drivers/hv/vmbus_drv.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*/

page_addr = hv_context.synic_event_page[cpu];
event = (union hv_synic_event_flags *)page_addr + VMBUS_MESSAGE_SINT;
if ((vmbus_proto_version == VERSION_WS2008) ||
(vmbus_proto_version == VERSION_WIN7)) {

/* Since we are a child, we only need to check bit 0 */
if (sync_test_and_clear_bit(0, (unsigned long *) &event->flags32[0])) {
page_addr = hv_context.synic_event_page[cpu];
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;
tasklet_schedule(&event_dpc);
}

if (handled)
tasklet_schedule(&event_dpc);


page_addr = hv_context.synic_message_page[cpu];
msg = (struct hv_message *)page_addr + VMBUS_MESSAGE_SINT;

Expand Down

0 comments on commit 6552ecd

Please sign in to comment.