[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] linux: Fix enable_irq() crash by removing a BUG_ON() assumption in our
# HG changeset patch # User kfraser@xxxxxxxxxxxxxxxxxxxxx # Date 1169559560 0 # Node ID 914304b3a3da6fc5bad12f742bae3893b53d20bc # Parent ee7c422c5f7b79e0cc0ae5670af81b400a72357f linux: Fix enable_irq() crash by removing a BUG_ON() assumption in our event-channel retrigger() function. Also clean up bitmap usages. Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx> --- linux-2.6-xen-sparse/drivers/xen/core/evtchn.c | 52 ++++++++++++------------- linux-2.6-xen-sparse/include/xen/evtchn.h | 2 2 files changed, 26 insertions(+), 28 deletions(-) diff -r ee7c422c5f7b -r 914304b3a3da linux-2.6-xen-sparse/drivers/xen/core/evtchn.c --- a/linux-2.6-xen-sparse/drivers/xen/core/evtchn.c Tue Jan 23 11:39:32 2007 +0000 +++ b/linux-2.6-xen-sparse/drivers/xen/core/evtchn.c Tue Jan 23 13:39:20 2007 +0000 @@ -60,8 +60,6 @@ static int evtchn_to_irq[NR_EVENT_CHANNE /* Packed IRQ information: binding type, sub-type index, and event channel. */ static u32 irq_info[NR_IRQS]; -static int resend_irq_on_evtchn(unsigned int); - /* Binding types. */ enum { IRQT_UNBOUND, @@ -113,7 +111,7 @@ static int irq_bindcount[NR_IRQS]; static int irq_bindcount[NR_IRQS]; /* Bitmap indicating which PIRQs require Xen to be notified on unmask. */ -static unsigned long pirq_needs_eoi[NR_PIRQS/sizeof(unsigned long)]; +static DECLARE_BITMAP(pirq_needs_eoi, NR_PIRQS); #ifdef CONFIG_SMP @@ -613,6 +611,22 @@ static void set_affinity_irq(unsigned ir rebind_irq_to_cpu(irq, tcpu); } #endif + +static int resend_irq_on_evtchn(unsigned int i) +{ + int masked, evtchn = evtchn_from_irq(i); + shared_info_t *s = HYPERVISOR_shared_info; + + if (!VALID_EVTCHN(evtchn)) + return 1; + + masked = synch_test_and_set_bit(evtchn, s->evtchn_mask); + synch_set_bit(evtchn, s->evtchn_pending); + if (!masked) + unmask_evtchn(evtchn); + + return 1; +} /* * Interface to generic handling in irq.c @@ -688,7 +702,7 @@ static inline void pirq_unmask_notify(in static inline void pirq_unmask_notify(int pirq) { struct physdev_eoi eoi = { .irq = pirq }; - if (unlikely(test_bit(pirq, &pirq_needs_eoi[0]))) + if (unlikely(test_bit(pirq, pirq_needs_eoi))) (void)HYPERVISOR_physdev_op(PHYSDEVOP_eoi, &eoi); } @@ -697,9 +711,9 @@ static inline void pirq_query_unmask(int struct physdev_irq_status_query irq_status; irq_status.irq = pirq; (void)HYPERVISOR_physdev_op(PHYSDEVOP_irq_status_query, &irq_status); - clear_bit(pirq, &pirq_needs_eoi[0]); + clear_bit(pirq, pirq_needs_eoi); if (irq_status.flags & XENIRQSTAT_needs_eoi) - set_bit(pirq, &pirq_needs_eoi[0]); + set_bit(pirq, pirq_needs_eoi); } /* @@ -824,18 +838,6 @@ int irq_ignore_unhandled(unsigned int ir return !!(irq_status.flags & XENIRQSTAT_shared); } -static int resend_irq_on_evtchn(unsigned int i) -{ - int evtchn = evtchn_from_irq(i); - shared_info_t *s = HYPERVISOR_shared_info; - if (!VALID_EVTCHN(evtchn)) - return 0; - BUG_ON(!synch_test_bit(evtchn, &s->evtchn_mask[0])); - synch_set_bit(evtchn, &s->evtchn_pending[0]); - - return 1; -} - void notify_remote_via_irq(int irq) { int evtchn = evtchn_from_irq(irq); @@ -854,7 +856,7 @@ void mask_evtchn(int port) void mask_evtchn(int port) { shared_info_t *s = HYPERVISOR_shared_info; - synch_set_bit(port, &s->evtchn_mask[0]); + synch_set_bit(port, s->evtchn_mask); } EXPORT_SYMBOL_GPL(mask_evtchn); @@ -873,14 +875,10 @@ void unmask_evtchn(int port) return; } - synch_clear_bit(port, &s->evtchn_mask[0]); - - /* - * The following is basically the equivalent of 'hw_resend_irq'. Just - * like a real IO-APIC we 'lose the interrupt edge' if the channel is - * masked. - */ - if (synch_test_bit(port, &s->evtchn_pending[0]) && + synch_clear_bit(port, s->evtchn_mask); + + /* Did we miss an interrupt 'edge'? Re-fire if so. */ + if (synch_test_bit(port, s->evtchn_pending) && !synch_test_and_set_bit(port / BITS_PER_LONG, &vcpu_info->evtchn_pending_sel)) vcpu_info->evtchn_upcall_pending = 1; diff -r ee7c422c5f7b -r 914304b3a3da linux-2.6-xen-sparse/include/xen/evtchn.h --- a/linux-2.6-xen-sparse/include/xen/evtchn.h Tue Jan 23 11:39:32 2007 +0000 +++ b/linux-2.6-xen-sparse/include/xen/evtchn.h Tue Jan 23 13:39:20 2007 +0000 @@ -108,7 +108,7 @@ static inline void clear_evtchn(int port static inline void clear_evtchn(int port) { shared_info_t *s = HYPERVISOR_shared_info; - synch_clear_bit(port, &s->evtchn_pending[0]); + synch_clear_bit(port, s->evtchn_pending); } static inline void notify_remote_via_evtchn(int port) _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |