mirror of https://gitee.com/openkylin/linux.git
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>
This commit is contained in:
parent
abbf3b2aa0
commit
6552ecd70c
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
Loading…
Reference in New Issue