[PATCH] Add debugging feature /proc/timer_list
[pandora-kernel.git] / kernel / softirq.c
index fd12f25..8b75008 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/kthread.h>
 #include <linux/rcupdate.h>
 #include <linux/smp.h>
+#include <linux/tick.h>
 
 #include <asm/irq.h>
 /*
@@ -65,6 +66,7 @@ static inline void wakeup_softirqd(void)
  * This one is for softirq.c-internal use,
  * where hardirqs are disabled legitimately:
  */
+#ifdef CONFIG_TRACE_IRQFLAGS
 static void __local_bh_disable(unsigned long ip)
 {
        unsigned long flags;
@@ -80,6 +82,13 @@ static void __local_bh_disable(unsigned long ip)
                trace_softirqs_off(ip);
        raw_local_irq_restore(flags);
 }
+#else /* !CONFIG_TRACE_IRQFLAGS */
+static inline void __local_bh_disable(unsigned long ip)
+{
+       add_preempt_count(SOFTIRQ_OFFSET);
+       barrier();
+}
+#endif /* CONFIG_TRACE_IRQFLAGS */
 
 void local_bh_disable(void)
 {
@@ -121,12 +130,16 @@ EXPORT_SYMBOL(_local_bh_enable);
 
 void local_bh_enable(void)
 {
+#ifdef CONFIG_TRACE_IRQFLAGS
        unsigned long flags;
 
        WARN_ON_ONCE(in_irq());
+#endif
        WARN_ON_ONCE(irqs_disabled());
 
+#ifdef CONFIG_TRACE_IRQFLAGS
        local_irq_save(flags);
+#endif
        /*
         * Are softirqs going to be turned on now:
         */
@@ -142,18 +155,22 @@ void local_bh_enable(void)
                do_softirq();
 
        dec_preempt_count();
+#ifdef CONFIG_TRACE_IRQFLAGS
        local_irq_restore(flags);
+#endif
        preempt_check_resched();
 }
 EXPORT_SYMBOL(local_bh_enable);
 
 void local_bh_enable_ip(unsigned long ip)
 {
+#ifdef CONFIG_TRACE_IRQFLAGS
        unsigned long flags;
 
        WARN_ON_ONCE(in_irq());
 
        local_irq_save(flags);
+#endif
        /*
         * Are softirqs going to be turned on now:
         */
@@ -169,7 +186,9 @@ void local_bh_enable_ip(unsigned long ip)
                do_softirq();
 
        dec_preempt_count();
+#ifdef CONFIG_TRACE_IRQFLAGS
        local_irq_restore(flags);
+#endif
        preempt_check_resched();
 }
 EXPORT_SYMBOL(local_bh_enable_ip);
@@ -255,6 +274,18 @@ EXPORT_SYMBOL(do_softirq);
 
 #endif
 
+/*
+ * Enter an interrupt context.
+ */
+void irq_enter(void)
+{
+       __irq_enter();
+#ifdef CONFIG_NO_HZ
+       if (idle_cpu(smp_processor_id()))
+               tick_nohz_update_jiffies();
+#endif
+}
+
 #ifdef __ARCH_IRQ_EXIT_IRQS_DISABLED
 # define invoke_softirq()      __do_softirq()
 #else
@@ -271,6 +302,12 @@ void irq_exit(void)
        sub_preempt_count(IRQ_EXIT_OFFSET);
        if (!in_interrupt() && local_softirq_pending())
                invoke_softirq();
+
+#ifdef CONFIG_NO_HZ
+       /* Make sure that timer wheel updates are propagated */
+       if (!in_interrupt() && idle_cpu(smp_processor_id()) && !need_resched())
+               tick_nohz_stop_sched_tick();
+#endif
        preempt_enable_no_resched();
 }
 
@@ -311,8 +348,6 @@ void open_softirq(int nr, void (*action)(struct softirq_action*), void *data)
        softirq_vec[nr].action = action;
 }
 
-EXPORT_UNUSED_SYMBOL(open_softirq);  /*  June 2006  */
-
 /* Tasklets */
 struct tasklet_head
 {
@@ -549,7 +584,7 @@ static void takeover_tasklets(unsigned int cpu)
 }
 #endif /* CONFIG_HOTPLUG_CPU */
 
-static int __devinit cpu_callback(struct notifier_block *nfb,
+static int __cpuinit cpu_callback(struct notifier_block *nfb,
                                  unsigned long action,
                                  void *hcpu)
 {
@@ -558,8 +593,6 @@ static int __devinit cpu_callback(struct notifier_block *nfb,
 
        switch (action) {
        case CPU_UP_PREPARE:
-               BUG_ON(per_cpu(tasklet_vec, hotcpu).list);
-               BUG_ON(per_cpu(tasklet_hi_vec, hotcpu).list);
                p = kthread_create(ksoftirqd, hcpu, "ksoftirqd/%d", hotcpu);
                if (IS_ERR(p)) {
                        printk("ksoftirqd for %i failed\n", hotcpu);
@@ -589,14 +622,16 @@ static int __devinit cpu_callback(struct notifier_block *nfb,
        return NOTIFY_OK;
 }
 
-static struct notifier_block __devinitdata cpu_nfb = {
+static struct notifier_block __cpuinitdata cpu_nfb = {
        .notifier_call = cpu_callback
 };
 
 __init int spawn_ksoftirqd(void)
 {
        void *cpu = (void *)(long)smp_processor_id();
-       cpu_callback(&cpu_nfb, CPU_UP_PREPARE, cpu);
+       int err = cpu_callback(&cpu_nfb, CPU_UP_PREPARE, cpu);
+
+       BUG_ON(err == NOTIFY_BAD);
        cpu_callback(&cpu_nfb, CPU_ONLINE, cpu);
        register_cpu_notifier(&cpu_nfb);
        return 0;