action = desc->action;
        if (unlikely(!action || irqd_irq_disabled(&desc->irq_data))) {
                desc->istate |= IRQS_PENDING;
-               goto out_unlock;
+               raw_spin_unlock_irq(&desc->lock);
+               return;
        }
 
        kstat_incr_irqs_this_cpu(desc);
-       irqd_set(&desc->irq_data, IRQD_IRQ_INPROGRESS);
+       atomic_inc(&desc->threads_active);
        raw_spin_unlock_irq(&desc->lock);
 
        action_ret = IRQ_NONE;
        if (!irq_settings_no_debug(desc))
                note_interrupt(desc, action_ret);
 
-       raw_spin_lock_irq(&desc->lock);
-       irqd_clear(&desc->irq_data, IRQD_IRQ_INPROGRESS);
-
-out_unlock:
-       raw_spin_unlock_irq(&desc->lock);
+       wake_threads_waitq(desc);
 }
 EXPORT_SYMBOL_GPL(handle_nested_irq);
 
 
 bool irq_wait_for_poll(struct irq_desc *desc);
 void __irq_wake_thread(struct irq_desc *desc, struct irqaction *action);
 
+void wake_threads_waitq(struct irq_desc *desc);
+
 #ifdef CONFIG_PROC_FS
 extern void register_irq_proc(unsigned int irq, struct irq_desc *desc);
 extern void unregister_irq_proc(unsigned int irq, struct irq_desc *desc);
 
 }
 EXPORT_SYMBOL(synchronize_hardirq);
 
+static void __synchronize_irq(struct irq_desc *desc)
+{
+       __synchronize_hardirq(desc, true);
+       /*
+        * We made sure that no hardirq handler is running. Now verify that no
+        * threaded handlers are active.
+        */
+       wait_event(desc->wait_for_threads, !atomic_read(&desc->threads_active));
+}
+
 /**
  *     synchronize_irq - wait for pending IRQ handlers (on other CPUs)
  *     @irq: interrupt number to wait for
 {
        struct irq_desc *desc = irq_to_desc(irq);
 
-       if (desc) {
-               __synchronize_hardirq(desc, true);
-               /*
-                * We made sure that no hardirq handler is
-                * running. Now verify that no threaded handlers are
-                * active.
-                */
-               wait_event(desc->wait_for_threads,
-                          !atomic_read(&desc->threads_active));
-       }
+       if (desc)
+               __synchronize_irq(desc);
 }
 EXPORT_SYMBOL(synchronize_irq);
 
        return ret;
 }
 
-static void wake_threads_waitq(struct irq_desc *desc)
+void wake_threads_waitq(struct irq_desc *desc)
 {
        if (atomic_dec_and_test(&desc->threads_active))
                wake_up(&desc->wait_for_threads);
         * supports it also make sure that there is no (not yet serviced)
         * interrupt in flight at the hardware level.
         */
-       __synchronize_hardirq(desc, true);
+       __synchronize_irq(desc);
 
 #ifdef CONFIG_DEBUG_SHIRQ
        /*