diff options
| -rw-r--r-- | drivers/xen/events.c | 17 |
1 files changed, 14 insertions, 3 deletions
diff --git a/drivers/xen/events.c b/drivers/xen/events.c index 7595581d032c..36bf17dc7bfc 100644 --- a/drivers/xen/events.c +++ b/drivers/xen/events.c | |||
| @@ -373,11 +373,22 @@ static void unmask_evtchn(int port) | |||
| 373 | { | 373 | { |
| 374 | struct shared_info *s = HYPERVISOR_shared_info; | 374 | struct shared_info *s = HYPERVISOR_shared_info; |
| 375 | unsigned int cpu = get_cpu(); | 375 | unsigned int cpu = get_cpu(); |
| 376 | int do_hypercall = 0, evtchn_pending = 0; | ||
| 376 | 377 | ||
| 377 | BUG_ON(!irqs_disabled()); | 378 | BUG_ON(!irqs_disabled()); |
| 378 | 379 | ||
| 379 | /* Slow path (hypercall) if this is a non-local port. */ | 380 | if (unlikely((cpu != cpu_from_evtchn(port)))) |
| 380 | if (unlikely(cpu != cpu_from_evtchn(port))) { | 381 | do_hypercall = 1; |
| 382 | else | ||
| 383 | evtchn_pending = sync_test_bit(port, &s->evtchn_pending[0]); | ||
| 384 | |||
| 385 | if (unlikely(evtchn_pending && xen_hvm_domain())) | ||
| 386 | do_hypercall = 1; | ||
| 387 | |||
| 388 | /* Slow path (hypercall) if this is a non-local port or if this is | ||
| 389 | * an hvm domain and an event is pending (hvm domains don't have | ||
| 390 | * their own implementation of irq_enable). */ | ||
| 391 | if (do_hypercall) { | ||
| 381 | struct evtchn_unmask unmask = { .port = port }; | 392 | struct evtchn_unmask unmask = { .port = port }; |
| 382 | (void)HYPERVISOR_event_channel_op(EVTCHNOP_unmask, &unmask); | 393 | (void)HYPERVISOR_event_channel_op(EVTCHNOP_unmask, &unmask); |
| 383 | } else { | 394 | } else { |
| @@ -390,7 +401,7 @@ static void unmask_evtchn(int port) | |||
| 390 | * 'hw_resend_irq'. Just like a real IO-APIC we 'lose | 401 | * 'hw_resend_irq'. Just like a real IO-APIC we 'lose |
| 391 | * the interrupt edge' if the channel is masked. | 402 | * the interrupt edge' if the channel is masked. |
| 392 | */ | 403 | */ |
| 393 | if (sync_test_bit(port, &s->evtchn_pending[0]) && | 404 | if (evtchn_pending && |
| 394 | !sync_test_and_set_bit(port / BITS_PER_LONG, | 405 | !sync_test_and_set_bit(port / BITS_PER_LONG, |
| 395 | &vcpu_info->evtchn_pending_sel)) | 406 | &vcpu_info->evtchn_pending_sel)) |
| 396 | vcpu_info->evtchn_upcall_pending = 1; | 407 | vcpu_info->evtchn_upcall_pending = 1; |
