fate#314663 hyper-v memory ballooning support
[opensuse:kernel-source.git] / patches.suse / suse-hv-fate314665-0018-Drivers-hv-Modify-the-interrupt-handling-code-to-sup.patch
1 Patch-mainline: submitted
2 From: <ohering@suse.de>
3 Date: Sat, 1 Dec 2012 06:46:49 -0800
4 Subject: [PATCH 18/28] Drivers: hv: Modify the interrupt handling code to
5  support win8 and beyond
6
7 Starting with Win8 (WS2012), the event page can be used to directly get the
8 channel ID that needs servicing. Modify the channel event handling code
9 to take advantage of this feature.
10
11 Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
12 Reviewed-by: Haiyang Zhang <haiyangz@microsoft.com>
13 ---
14  drivers/hv/connection.c | 26 ++++++++++++++++++++++++--
15  drivers/hv/vmbus_drv.c  | 27 ++++++++++++++++++++++-----
16  2 files changed, 46 insertions(+), 7 deletions(-)
17
18 diff --git a/drivers/hv/connection.c b/drivers/hv/connection.c
19 index 114050d..ac71653 100644
20 --- a/drivers/hv/connection.c
21 +++ b/drivers/hv/connection.c
22 @@ -321,10 +321,32 @@ static void process_chn_event(u32 relid)
23  void vmbus_on_event(unsigned long data)
24  {
25         u32 dword;
26 -       u32 maxdword = MAX_NUM_CHANNELS_SUPPORTED >> 5;
27 +       u32 maxdword;
28         int bit;
29         u32 relid;
30 -       u32 *recv_int_page = vmbus_connection.recv_int_page;
31 +       u32 *recv_int_page = NULL;
32 +       void *page_addr;
33 +       int cpu = smp_processor_id();
34 +       union hv_synic_event_flags *event;
35 +
36 +       if ((vmbus_proto_version == VERSION_WS2008) ||
37 +               (vmbus_proto_version == VERSION_WIN7)) {
38 +               maxdword = MAX_NUM_CHANNELS_SUPPORTED >> 5;
39 +               recv_int_page = vmbus_connection.recv_int_page;
40 +       } else {
41 +               /*
42 +                * When the host is win8 and beyond, the event page
43 +                * can be directly checked to get the id of the channel
44 +                * that has the interrupt pending.
45 +                */
46 +               maxdword = HV_EVENT_FLAGS_DWORD_COUNT;
47 +               page_addr = hv_context.synic_event_page[cpu];
48 +               event = (union hv_synic_event_flags *)page_addr +
49 +                                                VMBUS_MESSAGE_SINT;
50 +               recv_int_page = event->flags32;
51 +       }
52 +
53 +
54  
55         /* Check events */
56         if (!recv_int_page)
57 diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c
58 index 8e1a9ec..c583a04 100644
59 --- a/drivers/hv/vmbus_drv.c
60 +++ b/drivers/hv/vmbus_drv.c
61 @@ -460,15 +460,32 @@ static irqreturn_t vmbus_isr(int irq, void *dev_id)
62          * Hyper-V, and the Windows team suggested we do the same.
63          */
64  
65 -       page_addr = hv_context.synic_event_page[cpu];
66 -       event = (union hv_synic_event_flags *)page_addr + VMBUS_MESSAGE_SINT;
67 +       if ((vmbus_proto_version == VERSION_WS2008) ||
68 +               (vmbus_proto_version == VERSION_WIN7)) {
69  
70 -       /* Since we are a child, we only need to check bit 0 */
71 -       if (sync_test_and_clear_bit(0, (unsigned long *) &event->flags32[0])) {
72 +               page_addr = hv_context.synic_event_page[cpu];
73 +               event = (union hv_synic_event_flags *)page_addr +
74 +                                        VMBUS_MESSAGE_SINT;
75 +
76 +               /* Since we are a child, we only need to check bit 0 */
77 +               if (sync_test_and_clear_bit(0,
78 +                       (unsigned long *) &event->flags32[0])) {
79 +                       handled = true;
80 +               }
81 +       } else {
82 +               /*
83 +                * Our host is win8 or above. The signaling mechanism
84 +                * has changed and we can directly look at the event page.
85 +                * If bit n is set then we have an interrup on the channel
86 +                * whose id is n.
87 +                */
88                 handled = true;
89 -               tasklet_schedule(&event_dpc);
90         }
91  
92 +       if (handled)
93 +               tasklet_schedule(&event_dpc);
94 +
95 +
96         page_addr = hv_context.synic_message_page[cpu];
97         msg = (struct hv_message *)page_addr + VMBUS_MESSAGE_SINT;
98  
99 -- 
100 1.8.0.1
101