aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hv/hv.c
diff options
context:
space:
mode:
authorJason Wang <jasowang@redhat.com>2013-06-18 23:28:10 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-06-24 19:24:17 -0400
commit2608fb653103419ac163206ff6d51b7b6528e2d9 (patch)
tree772e6b8d52a07a4cb1fc6f5825689666e501cfe6 /drivers/hv/hv.c
parente91e84fa4cfeb67a9a096f1adaa1a1a692474724 (diff)
drivers: hv: allocate synic structures before hv_synic_init()
We currently allocate synic structures in hv_sync_init(), but there's no way for the driver to know about the allocation failure and it may continue to use the uninitialized pointers. Solve this by introducing helpers for allocating and freeing and doing the allocation before the on_each_cpu() call in vmbus_bus_init(). Cc: Haiyang Zhang <haiyangz@microsoft.com> Signed-off-by: Jason Wang <jasowang@redhat.com> Signed-off-by: K. Y. Srinivasan <kys@microsoft.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/hv/hv.c')
-rw-r--r--drivers/hv/hv.c85
1 files changed, 53 insertions, 32 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
269int 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;
300err:
301 return -ENOMEM;
302}
303
304void 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
313void 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
359cleanup:
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/*