Drivers: hv: vmbus: Support handling messages on multiple CPUs
Starting with Windows 2012 R2, message inteerupts can be delivered on any VCPU in the guest. Support this functionality. Signed-off-by: K. Y. Srinivasan <kys@microsoft.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
e66853b090
commit
d81274aae6
|
@ -204,6 +204,8 @@ int hv_init(void)
|
|||
sizeof(int) * NR_CPUS);
|
||||
memset(hv_context.event_dpc, 0,
|
||||
sizeof(void *) * NR_CPUS);
|
||||
memset(hv_context.msg_dpc, 0,
|
||||
sizeof(void *) * NR_CPUS);
|
||||
memset(hv_context.clk_evt, 0,
|
||||
sizeof(void *) * NR_CPUS);
|
||||
|
||||
|
@ -415,6 +417,13 @@ int hv_synic_alloc(void)
|
|||
}
|
||||
tasklet_init(hv_context.event_dpc[cpu], vmbus_on_event, cpu);
|
||||
|
||||
hv_context.msg_dpc[cpu] = kmalloc(size, GFP_ATOMIC);
|
||||
if (hv_context.msg_dpc[cpu] == NULL) {
|
||||
pr_err("Unable to allocate event dpc\n");
|
||||
goto err;
|
||||
}
|
||||
tasklet_init(hv_context.msg_dpc[cpu], vmbus_on_msg_dpc, cpu);
|
||||
|
||||
hv_context.clk_evt[cpu] = kzalloc(ced_size, GFP_ATOMIC);
|
||||
if (hv_context.clk_evt[cpu] == NULL) {
|
||||
pr_err("Unable to allocate clock event device\n");
|
||||
|
@ -456,6 +465,7 @@ int hv_synic_alloc(void)
|
|||
static void hv_synic_free_cpu(int cpu)
|
||||
{
|
||||
kfree(hv_context.event_dpc[cpu]);
|
||||
kfree(hv_context.msg_dpc[cpu]);
|
||||
kfree(hv_context.clk_evt[cpu]);
|
||||
if (hv_context.synic_event_page[cpu])
|
||||
free_page((unsigned long)hv_context.synic_event_page[cpu]);
|
||||
|
|
|
@ -449,10 +449,11 @@ struct hv_context {
|
|||
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
|
||||
* we will manage the tasklet that handles events messages on a per CPU
|
||||
* basis.
|
||||
*/
|
||||
struct tasklet_struct *event_dpc[NR_CPUS];
|
||||
struct tasklet_struct *msg_dpc[NR_CPUS];
|
||||
/*
|
||||
* To optimize the mapping of relid to channel, maintain
|
||||
* per-cpu list of the channels based on their CPU affinity.
|
||||
|
@ -675,6 +676,7 @@ int vmbus_post_msg(void *buffer, size_t buflen);
|
|||
void vmbus_set_event(struct vmbus_channel *channel);
|
||||
|
||||
void vmbus_on_event(unsigned long data);
|
||||
void vmbus_on_msg_dpc(unsigned long data);
|
||||
|
||||
int hv_kvp_init(struct hv_util_service *);
|
||||
void hv_kvp_deinit(void);
|
||||
|
|
|
@ -45,7 +45,6 @@
|
|||
|
||||
static struct acpi_device *hv_acpi_dev;
|
||||
|
||||
static struct tasklet_struct msg_dpc;
|
||||
static struct completion probe_event;
|
||||
|
||||
|
||||
|
@ -712,7 +711,7 @@ static void hv_process_timer_expiration(struct hv_message *msg, int cpu)
|
|||
vmbus_signal_eom(msg);
|
||||
}
|
||||
|
||||
static void vmbus_on_msg_dpc(unsigned long data)
|
||||
void vmbus_on_msg_dpc(unsigned long data)
|
||||
{
|
||||
int cpu = smp_processor_id();
|
||||
void *page_addr = hv_context.synic_message_page[cpu];
|
||||
|
@ -800,7 +799,7 @@ static void vmbus_isr(void)
|
|||
if (msg->header.message_type == HVMSG_TIMER_EXPIRED)
|
||||
hv_process_timer_expiration(msg, cpu);
|
||||
else
|
||||
tasklet_schedule(&msg_dpc);
|
||||
tasklet_schedule(hv_context.msg_dpc[cpu]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -824,8 +823,6 @@ static int vmbus_bus_init(void)
|
|||
return ret;
|
||||
}
|
||||
|
||||
tasklet_init(&msg_dpc, vmbus_on_msg_dpc, 0);
|
||||
|
||||
ret = bus_register(&hv_bus);
|
||||
if (ret)
|
||||
goto err_cleanup;
|
||||
|
@ -1321,7 +1318,8 @@ static void __exit vmbus_exit(void)
|
|||
hv_synic_clockevents_cleanup();
|
||||
vmbus_disconnect();
|
||||
hv_remove_vmbus_irq();
|
||||
tasklet_kill(&msg_dpc);
|
||||
for_each_online_cpu(cpu)
|
||||
tasklet_kill(hv_context.msg_dpc[cpu]);
|
||||
vmbus_free_channels();
|
||||
if (ms_hyperv.misc_features & HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE) {
|
||||
unregister_die_notifier(&hyperv_die_block);
|
||||
|
|
Loading…
Reference in New Issue