diff options
-rw-r--r-- | drivers/xen/events/events_fifo.c | 48 |
1 files changed, 28 insertions, 20 deletions
diff --git a/drivers/xen/events/events_fifo.c b/drivers/xen/events/events_fifo.c index 84b4bfb84344..c7ff2035b98e 100644 --- a/drivers/xen/events/events_fifo.c +++ b/drivers/xen/events/events_fifo.c | |||
@@ -100,6 +100,25 @@ static unsigned evtchn_fifo_nr_channels(void) | |||
100 | return event_array_pages * EVENT_WORDS_PER_PAGE; | 100 | return event_array_pages * EVENT_WORDS_PER_PAGE; |
101 | } | 101 | } |
102 | 102 | ||
103 | static int init_control_block(int cpu, | ||
104 | struct evtchn_fifo_control_block *control_block) | ||
105 | { | ||
106 | struct evtchn_fifo_queue *q = &per_cpu(cpu_queue, cpu); | ||
107 | struct evtchn_init_control init_control; | ||
108 | unsigned int i; | ||
109 | |||
110 | /* Reset the control block and the local HEADs. */ | ||
111 | clear_page(control_block); | ||
112 | for (i = 0; i < EVTCHN_FIFO_MAX_QUEUES; i++) | ||
113 | q->head[i] = 0; | ||
114 | |||
115 | init_control.control_gfn = virt_to_mfn(control_block); | ||
116 | init_control.offset = 0; | ||
117 | init_control.vcpu = cpu; | ||
118 | |||
119 | return HYPERVISOR_event_channel_op(EVTCHNOP_init_control, &init_control); | ||
120 | } | ||
121 | |||
103 | static void free_unused_array_pages(void) | 122 | static void free_unused_array_pages(void) |
104 | { | 123 | { |
105 | unsigned i; | 124 | unsigned i; |
@@ -324,7 +343,6 @@ static void evtchn_fifo_resume(void) | |||
324 | 343 | ||
325 | for_each_possible_cpu(cpu) { | 344 | for_each_possible_cpu(cpu) { |
326 | void *control_block = per_cpu(cpu_control_block, cpu); | 345 | void *control_block = per_cpu(cpu_control_block, cpu); |
327 | struct evtchn_init_control init_control; | ||
328 | int ret; | 346 | int ret; |
329 | 347 | ||
330 | if (!control_block) | 348 | if (!control_block) |
@@ -341,12 +359,7 @@ static void evtchn_fifo_resume(void) | |||
341 | continue; | 359 | continue; |
342 | } | 360 | } |
343 | 361 | ||
344 | init_control.control_gfn = virt_to_mfn(control_block); | 362 | ret = init_control_block(cpu, control_block); |
345 | init_control.offset = 0; | ||
346 | init_control.vcpu = cpu; | ||
347 | |||
348 | ret = HYPERVISOR_event_channel_op(EVTCHNOP_init_control, | ||
349 | &init_control); | ||
350 | if (ret < 0) | 363 | if (ret < 0) |
351 | BUG(); | 364 | BUG(); |
352 | } | 365 | } |
@@ -374,30 +387,25 @@ static const struct evtchn_ops evtchn_ops_fifo = { | |||
374 | .resume = evtchn_fifo_resume, | 387 | .resume = evtchn_fifo_resume, |
375 | }; | 388 | }; |
376 | 389 | ||
377 | static int evtchn_fifo_init_control_block(unsigned cpu) | 390 | static int evtchn_fifo_alloc_control_block(unsigned cpu) |
378 | { | 391 | { |
379 | struct page *control_block = NULL; | 392 | void *control_block = NULL; |
380 | struct evtchn_init_control init_control; | ||
381 | int ret = -ENOMEM; | 393 | int ret = -ENOMEM; |
382 | 394 | ||
383 | control_block = alloc_page(GFP_KERNEL|__GFP_ZERO); | 395 | control_block = (void *)__get_free_page(GFP_KERNEL); |
384 | if (control_block == NULL) | 396 | if (control_block == NULL) |
385 | goto error; | 397 | goto error; |
386 | 398 | ||
387 | init_control.control_gfn = virt_to_mfn(page_address(control_block)); | 399 | ret = init_control_block(cpu, control_block); |
388 | init_control.offset = 0; | ||
389 | init_control.vcpu = cpu; | ||
390 | |||
391 | ret = HYPERVISOR_event_channel_op(EVTCHNOP_init_control, &init_control); | ||
392 | if (ret < 0) | 400 | if (ret < 0) |
393 | goto error; | 401 | goto error; |
394 | 402 | ||
395 | per_cpu(cpu_control_block, cpu) = page_address(control_block); | 403 | per_cpu(cpu_control_block, cpu) = control_block; |
396 | 404 | ||
397 | return 0; | 405 | return 0; |
398 | 406 | ||
399 | error: | 407 | error: |
400 | __free_page(control_block); | 408 | free_page((unsigned long)control_block); |
401 | return ret; | 409 | return ret; |
402 | } | 410 | } |
403 | 411 | ||
@@ -411,7 +419,7 @@ static int evtchn_fifo_cpu_notification(struct notifier_block *self, | |||
411 | switch (action) { | 419 | switch (action) { |
412 | case CPU_UP_PREPARE: | 420 | case CPU_UP_PREPARE: |
413 | if (!per_cpu(cpu_control_block, cpu)) | 421 | if (!per_cpu(cpu_control_block, cpu)) |
414 | ret = evtchn_fifo_init_control_block(cpu); | 422 | ret = evtchn_fifo_alloc_control_block(cpu); |
415 | break; | 423 | break; |
416 | default: | 424 | default: |
417 | break; | 425 | break; |
@@ -428,7 +436,7 @@ int __init xen_evtchn_fifo_init(void) | |||
428 | int cpu = get_cpu(); | 436 | int cpu = get_cpu(); |
429 | int ret; | 437 | int ret; |
430 | 438 | ||
431 | ret = evtchn_fifo_init_control_block(cpu); | 439 | ret = evtchn_fifo_alloc_control_block(cpu); |
432 | if (ret < 0) | 440 | if (ret < 0) |
433 | goto out; | 441 | goto out; |
434 | 442 | ||