aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/xen
diff options
context:
space:
mode:
authorJeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>2010-05-28 18:28:27 -0400
committerJeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>2010-05-28 18:28:27 -0400
commit3f5e554f669098c84c82ce75e7577f7e0f3fccde (patch)
treefb8147269b5f9b412e03e3539fdb2dd3cedc0ace /drivers/xen
parent1a1a17cddbfb1f81222b3f18ee8530c41fbc3b82 (diff)
xen/evtchn: don't do unbind_from_irqhandler under spinlock
unbind_from_irqhandler can end up doing /proc operations, which can't happen under a spinlock. So before removing the IRQ handler, disable the irq under the port_user lock (masking the underlying event channel and making sure the irq handler isn't running concurrently and won't start running), then remove the handler without the lock. Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>
Diffstat (limited to 'drivers/xen')
-rw-r--r--drivers/xen/evtchn.c13
1 files changed, 11 insertions, 2 deletions
diff --git a/drivers/xen/evtchn.c b/drivers/xen/evtchn.c
index f79ac5ca3793..6a3a12945d02 100644
--- a/drivers/xen/evtchn.c
+++ b/drivers/xen/evtchn.c
@@ -375,10 +375,12 @@ static long evtchn_ioctl(struct file *file,
375 break; 375 break;
376 } 376 }
377 377
378 evtchn_unbind_from_user(u, unbind.port); 378 disable_irq(irq_from_evtchn(unbind.port));
379 379
380 spin_unlock_irq(&port_user_lock); 380 spin_unlock_irq(&port_user_lock);
381 381
382 evtchn_unbind_from_user(u, unbind.port);
383
382 rc = 0; 384 rc = 0;
383 break; 385 break;
384 } 386 }
@@ -484,11 +486,18 @@ static int evtchn_release(struct inode *inode, struct file *filp)
484 if (get_port_user(i) != u) 486 if (get_port_user(i) != u)
485 continue; 487 continue;
486 488
487 evtchn_unbind_from_user(get_port_user(i), i); 489 disable_irq(irq_from_evtchn(i));
488 } 490 }
489 491
490 spin_unlock_irq(&port_user_lock); 492 spin_unlock_irq(&port_user_lock);
491 493
494 for (i = 0; i < NR_EVENT_CHANNELS; i++) {
495 if (get_port_user(i) != u)
496 continue;
497
498 evtchn_unbind_from_user(get_port_user(i), i);
499 }
500
492 kfree(u->name); 501 kfree(u->name);
493 kfree(u); 502 kfree(u);
494 503