Drivers: hv: Manage event tasklets on per-cpu basis
authorK. Y. Srinivasan <kys@microsoft.com>
Sat, 1 Dec 2012 14:46:53 +0000 (06:46 -0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 17 Jan 2013 19:39:15 +0000 (11:39 -0800)
Now that we can potentially take vmbus interrupts on any CPU, make the
tasklets per-CPU.

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>
drivers/hv/hv.c
drivers/hv/hyperv_vmbus.h
drivers/hv/vmbus_drv.c

index e989c6f..363532a 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/vmalloc.h>
 #include <linux/hyperv.h>
 #include <linux/version.h>
+#include <linux/interrupt.h>
 #include <asm/hyperv.h>
 #include "hyperv_vmbus.h"
 
@@ -137,6 +138,8 @@ int hv_init(void)
               sizeof(void *) * NR_CPUS);
        memset(hv_context.vp_index, 0,
               sizeof(int) * NR_CPUS);
+       memset(hv_context.event_dpc, 0,
+              sizeof(void *) * NR_CPUS);
 
        max_leaf = query_hypervisor_info();
 
@@ -285,6 +288,15 @@ void hv_synic_init(void *irqarg)
        /* Check the version */
        rdmsrl(HV_X64_MSR_SVERSION, version);
 
+       hv_context.event_dpc[cpu] = (struct tasklet_struct *)
+                                       kmalloc(sizeof(struct tasklet_struct),
+                                               GFP_ATOMIC);
+       if (hv_context.event_dpc[cpu] == NULL) {
+               pr_err("Unable to allocate event dpc\n");
+               goto cleanup;
+       }
+       tasklet_init(hv_context.event_dpc[cpu], vmbus_on_event, cpu);
+
        hv_context.synic_message_page[cpu] =
                (void *)get_zeroed_page(GFP_ATOMIC);
 
index 9135a6f..becb106 100644 (file)
@@ -504,6 +504,12 @@ struct hv_context {
         * Linux cpuid 'a'.
         */
        u32 vp_index[NR_CPUS];
+       /*
+        * Starting with win8, we can take channel interrupts on any CPU;
+        * we will manage the tasklet that handles events on a per CPU
+        * basis.
+        */
+       struct tasklet_struct *event_dpc[NR_CPUS];
 };
 
 extern struct hv_context hv_context;
index 4c92337..6e4f857 100644 (file)
@@ -41,7 +41,6 @@
 static struct acpi_device  *hv_acpi_dev;
 
 static struct tasklet_struct msg_dpc;
-static struct tasklet_struct event_dpc;
 static struct completion probe_event;
 static int irq;
 
@@ -483,7 +482,7 @@ static irqreturn_t vmbus_isr(int irq, void *dev_id)
        }
 
        if (handled)
-               tasklet_schedule(&event_dpc);
+               tasklet_schedule(hv_context.event_dpc[cpu]);
 
 
        page_addr = hv_context.synic_message_page[cpu];
@@ -523,7 +522,6 @@ static int vmbus_bus_init(int irq)
        }
 
        tasklet_init(&msg_dpc, vmbus_on_msg_dpc, 0);
-       tasklet_init(&event_dpc, vmbus_on_event, 0);
 
        ret = bus_register(&hv_bus);
        if (ret)