[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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.