partitions/efi: complete documentation of gpt kernel param purpose
[platform/adaptation/renesas_rcar/renesas_kernel.git] / kernel / softirq.c
index 9e368ef..8a1e6e1 100644 (file)
@@ -188,14 +188,48 @@ EXPORT_SYMBOL(__local_bh_enable_ip);
 #define MAX_SOFTIRQ_TIME  msecs_to_jiffies(2)
 #define MAX_SOFTIRQ_RESTART 10
 
+#ifdef CONFIG_TRACE_IRQFLAGS
+/*
+ * When we run softirqs from irq_exit() and thus on the hardirq stack we need
+ * to keep the lockdep irq context tracking as tight as possible in order to
+ * not miss-qualify lock contexts and miss possible deadlocks.
+ */
+
+static inline bool lockdep_softirq_start(void)
+{
+       bool in_hardirq = false;
+
+       if (trace_hardirq_context(current)) {
+               in_hardirq = true;
+               trace_hardirq_exit();
+       }
+
+       lockdep_softirq_enter();
+
+       return in_hardirq;
+}
+
+static inline void lockdep_softirq_end(bool in_hardirq)
+{
+       lockdep_softirq_exit();
+
+       if (in_hardirq)
+               trace_hardirq_enter();
+}
+#else
+static inline bool lockdep_softirq_start(void) { return false; }
+static inline void lockdep_softirq_end(bool in_hardirq) { }
+#endif
+
 asmlinkage void __do_softirq(void)
 {
-       struct softirq_action *h;
-       __u32 pending;
        unsigned long end = jiffies + MAX_SOFTIRQ_TIME;
-       int cpu;
        unsigned long old_flags = current->flags;
        int max_restart = MAX_SOFTIRQ_RESTART;
+       struct softirq_action *h;
+       bool in_hardirq;
+       __u32 pending;
+       int cpu;
 
        /*
         * Mask out PF_MEMALLOC s current task context is borrowed for the
@@ -208,7 +242,7 @@ asmlinkage void __do_softirq(void)
        account_irq_enter_time(current);
 
        __local_bh_disable_ip(_RET_IP_, SOFTIRQ_OFFSET);
-       lockdep_softirq_enter();
+       in_hardirq = lockdep_softirq_start();
 
        cpu = smp_processor_id();
 restart:
@@ -255,16 +289,13 @@ restart:
                wakeup_softirqd();
        }
 
-       lockdep_softirq_exit();
-
+       lockdep_softirq_end(in_hardirq);
        account_irq_exit_time(current);
        __local_bh_enable(SOFTIRQ_OFFSET);
        WARN_ON_ONCE(in_interrupt());
        tsk_restore_flags(current, old_flags, PF_MEMALLOC);
 }
 
-
-
 asmlinkage void do_softirq(void)
 {
        __u32 pending;
@@ -288,8 +319,6 @@ asmlinkage void do_softirq(void)
  */
 void irq_enter(void)
 {
-       int cpu = smp_processor_id();
-
        rcu_irq_enter();
        if (is_idle_task(current) && !in_interrupt()) {
                /*
@@ -297,7 +326,7 @@ void irq_enter(void)
                 * here, as softirq will be serviced on return from interrupt.
                 */
                local_bh_disable();
-               tick_check_idle(cpu);
+               tick_check_idle();
                _local_bh_enable();
        }
 
@@ -352,13 +381,13 @@ void irq_exit(void)
 #endif
 
        account_irq_exit_time(current);
-       trace_hardirq_exit();
        preempt_count_sub(HARDIRQ_OFFSET);
        if (!in_interrupt() && local_softirq_pending())
                invoke_softirq();
 
        tick_irq_exit();
        rcu_irq_exit();
+       trace_hardirq_exit(); /* must be last! */
 }
 
 /*