diff options
-rw-r--r-- | drivers/hv/hv.c | 85 | ||||
-rw-r--r-- | drivers/hv/hyperv_vmbus.h | 4 | ||||
-rw-r--r-- | drivers/hv/vmbus_drv.c | 8 |
3 files changed, 63 insertions, 34 deletions
diff --git a/drivers/hv/hv.c b/drivers/hv/hv.c index ae4923756d98..88f4096fa078 100644 --- a/drivers/hv/hv.c +++ b/drivers/hv/hv.c | |||
@@ -265,6 +265,59 @@ u16 hv_signal_event(void *con_id) | |||
265 | return status; | 265 | return status; |
266 | } | 266 | } |
267 | 267 | ||
268 | |||
269 | int hv_synic_alloc(void) | ||
270 | { | ||
271 | size_t size = sizeof(struct tasklet_struct); | ||
272 | int cpu; | ||
273 | |||
274 | for_each_online_cpu(cpu) { | ||
275 | hv_context.event_dpc[cpu] = kmalloc(size, GFP_ATOMIC); | ||
276 | if (hv_context.event_dpc[cpu] == NULL) { | ||
277 | pr_err("Unable to allocate event dpc\n"); | ||
278 | goto err; | ||
279 | } | ||
280 | tasklet_init(hv_context.event_dpc[cpu], vmbus_on_event, cpu); | ||
281 | |||
282 | hv_context.synic_message_page[cpu] = | ||
283 | (void *)get_zeroed_page(GFP_ATOMIC); | ||
284 | |||
285 | if (hv_context.synic_message_page[cpu] == NULL) { | ||
286 | pr_err("Unable to allocate SYNIC message page\n"); | ||
287 | goto err; | ||
288 | } | ||
289 | |||
290 | hv_context.synic_event_page[cpu] = | ||
291 | (void *)get_zeroed_page(GFP_ATOMIC); | ||
292 | |||
293 | if (hv_context.synic_event_page[cpu] == NULL) { | ||
294 | pr_err("Unable to allocate SYNIC event page\n"); | ||
295 | goto err; | ||
296 | } | ||
297 | } | ||
298 | |||
299 | return 0; | ||
300 | err: | ||
301 | return -ENOMEM; | ||
302 | } | ||
303 | |||
304 | void hv_synic_free_cpu(int cpu) | ||
305 | { | ||
306 | kfree(hv_context.event_dpc[cpu]); | ||
307 | if (hv_context.synic_message_page[cpu]) | ||
308 | free_page((unsigned long)hv_context.synic_event_page[cpu]); | ||
309 | if (hv_context.synic_message_page[cpu]) | ||
310 | free_page((unsigned long)hv_context.synic_message_page[cpu]); | ||
311 | } | ||
312 | |||
313 | void hv_synic_free(void) | ||
314 | { | ||
315 | int cpu; | ||
316 | |||
317 | for_each_online_cpu(cpu) | ||
318 | hv_synic_free_cpu(cpu); | ||
319 | } | ||
320 | |||
268 | /* | 321 | /* |
269 | * hv_synic_init - Initialize the Synthethic Interrupt Controller. | 322 | * hv_synic_init - Initialize the Synthethic Interrupt Controller. |
270 | * | 323 | * |
@@ -289,30 +342,6 @@ void hv_synic_init(void *arg) | |||
289 | /* Check the version */ | 342 | /* Check the version */ |
290 | rdmsrl(HV_X64_MSR_SVERSION, version); | 343 | rdmsrl(HV_X64_MSR_SVERSION, version); |
291 | 344 | ||
292 | hv_context.event_dpc[cpu] = kmalloc(sizeof(struct tasklet_struct), | ||
293 | GFP_ATOMIC); | ||
294 | if (hv_context.event_dpc[cpu] == NULL) { | ||
295 | pr_err("Unable to allocate event dpc\n"); | ||
296 | goto cleanup; | ||
297 | } | ||
298 | tasklet_init(hv_context.event_dpc[cpu], vmbus_on_event, cpu); | ||
299 | |||
300 | hv_context.synic_message_page[cpu] = | ||
301 | (void *)get_zeroed_page(GFP_ATOMIC); | ||
302 | |||
303 | if (hv_context.synic_message_page[cpu] == NULL) { | ||
304 | pr_err("Unable to allocate SYNIC message page\n"); | ||
305 | goto cleanup; | ||
306 | } | ||
307 | |||
308 | hv_context.synic_event_page[cpu] = | ||
309 | (void *)get_zeroed_page(GFP_ATOMIC); | ||
310 | |||
311 | if (hv_context.synic_event_page[cpu] == NULL) { | ||
312 | pr_err("Unable to allocate SYNIC event page\n"); | ||
313 | goto cleanup; | ||
314 | } | ||
315 | |||
316 | /* Setup the Synic's message page */ | 345 | /* Setup the Synic's message page */ |
317 | rdmsrl(HV_X64_MSR_SIMP, simp.as_uint64); | 346 | rdmsrl(HV_X64_MSR_SIMP, simp.as_uint64); |
318 | simp.simp_enabled = 1; | 347 | simp.simp_enabled = 1; |
@@ -355,14 +384,6 @@ void hv_synic_init(void *arg) | |||
355 | rdmsrl(HV_X64_MSR_VP_INDEX, vp_index); | 384 | rdmsrl(HV_X64_MSR_VP_INDEX, vp_index); |
356 | hv_context.vp_index[cpu] = (u32)vp_index; | 385 | hv_context.vp_index[cpu] = (u32)vp_index; |
357 | return; | 386 | return; |
358 | |||
359 | cleanup: | ||
360 | if (hv_context.synic_event_page[cpu]) | ||
361 | free_page((unsigned long)hv_context.synic_event_page[cpu]); | ||
362 | |||
363 | if (hv_context.synic_message_page[cpu]) | ||
364 | free_page((unsigned long)hv_context.synic_message_page[cpu]); | ||
365 | return; | ||
366 | } | 387 | } |
367 | 388 | ||
368 | /* | 389 | /* |
diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h index 12f2f9e989f7..d84918fe19ab 100644 --- a/drivers/hv/hyperv_vmbus.h +++ b/drivers/hv/hyperv_vmbus.h | |||
@@ -527,6 +527,10 @@ extern int hv_post_message(union hv_connection_id connection_id, | |||
527 | 527 | ||
528 | extern u16 hv_signal_event(void *con_id); | 528 | extern u16 hv_signal_event(void *con_id); |
529 | 529 | ||
530 | extern int hv_synic_alloc(void); | ||
531 | |||
532 | extern void hv_synic_free(void); | ||
533 | |||
530 | extern void hv_synic_init(void *irqarg); | 534 | extern void hv_synic_init(void *irqarg); |
531 | 535 | ||
532 | extern void hv_synic_cleanup(void *arg); | 536 | extern void hv_synic_cleanup(void *arg); |
diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c index 4004e54ef05d..a2464bf07c49 100644 --- a/drivers/hv/vmbus_drv.c +++ b/drivers/hv/vmbus_drv.c | |||
@@ -563,6 +563,9 @@ static int vmbus_bus_init(int irq) | |||
563 | */ | 563 | */ |
564 | hv_register_vmbus_handler(irq, vmbus_isr); | 564 | hv_register_vmbus_handler(irq, vmbus_isr); |
565 | 565 | ||
566 | ret = hv_synic_alloc(); | ||
567 | if (ret) | ||
568 | goto err_alloc; | ||
566 | /* | 569 | /* |
567 | * Initialize the per-cpu interrupt state and | 570 | * Initialize the per-cpu interrupt state and |
568 | * connect to the host. | 571 | * connect to the host. |
@@ -570,13 +573,14 @@ static int vmbus_bus_init(int irq) | |||
570 | on_each_cpu(hv_synic_init, NULL, 1); | 573 | on_each_cpu(hv_synic_init, NULL, 1); |
571 | ret = vmbus_connect(); | 574 | ret = vmbus_connect(); |
572 | if (ret) | 575 | if (ret) |
573 | goto err_irq; | 576 | goto err_alloc; |
574 | 577 | ||
575 | vmbus_request_offers(); | 578 | vmbus_request_offers(); |
576 | 579 | ||
577 | return 0; | 580 | return 0; |
578 | 581 | ||
579 | err_irq: | 582 | err_alloc: |
583 | hv_synic_free(); | ||
580 | free_irq(irq, hv_acpi_dev); | 584 | free_irq(irq, hv_acpi_dev); |
581 | 585 | ||
582 | err_unregister: | 586 | err_unregister: |