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

Drivers: hv: Manage event tasklets on per-cpu basis

Now that we can potentially take vmbus interrupts on any CPU, make the
tasklets per-CPU.
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 01986313
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
#include <linux/hyperv.h> #include <linux/hyperv.h>
#include <linux/version.h> #include <linux/version.h>
#include <linux/interrupt.h>
#include <asm/hyperv.h> #include <asm/hyperv.h>
#include "hyperv_vmbus.h" #include "hyperv_vmbus.h"
...@@ -137,6 +138,8 @@ int hv_init(void) ...@@ -137,6 +138,8 @@ int hv_init(void)
sizeof(void *) * NR_CPUS); sizeof(void *) * NR_CPUS);
memset(hv_context.vp_index, 0, memset(hv_context.vp_index, 0,
sizeof(int) * NR_CPUS); sizeof(int) * NR_CPUS);
memset(hv_context.event_dpc, 0,
sizeof(void *) * NR_CPUS);
max_leaf = query_hypervisor_info(); max_leaf = query_hypervisor_info();
...@@ -285,6 +288,15 @@ void hv_synic_init(void *irqarg) ...@@ -285,6 +288,15 @@ void hv_synic_init(void *irqarg)
/* Check the version */ /* Check the version */
rdmsrl(HV_X64_MSR_SVERSION, 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] = hv_context.synic_message_page[cpu] =
(void *)get_zeroed_page(GFP_ATOMIC); (void *)get_zeroed_page(GFP_ATOMIC);
......
...@@ -504,6 +504,12 @@ struct hv_context { ...@@ -504,6 +504,12 @@ struct hv_context {
* Linux cpuid 'a'. * Linux cpuid 'a'.
*/ */
u32 vp_index[NR_CPUS]; 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; extern struct hv_context hv_context;
......
...@@ -41,7 +41,6 @@ ...@@ -41,7 +41,6 @@
static struct acpi_device *hv_acpi_dev; static struct acpi_device *hv_acpi_dev;
static struct tasklet_struct msg_dpc; static struct tasklet_struct msg_dpc;
static struct tasklet_struct event_dpc;
static struct completion probe_event; static struct completion probe_event;
static int irq; static int irq;
...@@ -483,7 +482,7 @@ static irqreturn_t vmbus_isr(int irq, void *dev_id) ...@@ -483,7 +482,7 @@ static irqreturn_t vmbus_isr(int irq, void *dev_id)
} }
if (handled) if (handled)
tasklet_schedule(&event_dpc); tasklet_schedule(hv_context.event_dpc[cpu]);
page_addr = hv_context.synic_message_page[cpu]; page_addr = hv_context.synic_message_page[cpu];
...@@ -523,7 +522,6 @@ static int vmbus_bus_init(int irq) ...@@ -523,7 +522,6 @@ static int vmbus_bus_init(int irq)
} }
tasklet_init(&msg_dpc, vmbus_on_msg_dpc, 0); tasklet_init(&msg_dpc, vmbus_on_msg_dpc, 0);
tasklet_init(&event_dpc, vmbus_on_event, 0);
ret = bus_register(&hv_bus); ret = bus_register(&hv_bus);
if (ret) if (ret)
......
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