Merge branch 'irq-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 6 Mar 2013 02:10:04 +0000 (18:10 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 6 Mar 2013 02:10:04 +0000 (18:10 -0800)
Pull irq fixes and cleanups from Thomas Gleixner:
 "Commit e5ab012c3271 ("nohz: Make tick_nohz_irq_exit() irq safe") is
  the first commit in the series and the minimal necessary bugfix, which
  needs to go back into stable.

  The remanining commits enforce irq disabling in irq_exit(), sanitize
  the hardirq/softirq preempt count transition and remove a bunch of no
  longer necessary conditionals."

I personally love getting rid of the very subtle and confusing
IRQ_EXIT_OFFSET thing.  Even apart from the whole "more lines removed
than added" thing.

* 'irq-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  irq: Don't re-enable interrupts at the end of irq_exit
  irq: Remove IRQ_EXIT_OFFSET workaround
  Revert "nohz: Make tick_nohz_irq_exit() irq safe"
  irq: Sanitize invoke_softirq
  irq: Ensure irq_exit() code runs with interrupts disabled
  nohz: Make tick_nohz_irq_exit() irq safe

1  2 
kernel/softirq.c

diff --combined kernel/softirq.c
index b4d252fd195b927afd402977b64efb3faa7ed96f,dce38fac4f323f415cff156907b8ea44da1b9698..14d7758074aadf4d1c43947ecef675e8bb6c044e
@@@ -195,21 -195,21 +195,21 @@@ void local_bh_enable_ip(unsigned long i
  EXPORT_SYMBOL(local_bh_enable_ip);
  
  /*
 - * We restart softirq processing MAX_SOFTIRQ_RESTART times,
 - * and we fall back to softirqd after that.
 + * We restart softirq processing for at most 2 ms,
 + * and if need_resched() is not set.
   *
 - * This number has been established via experimentation.
 + * These limits have been established via experimentation.
   * The two things to balance is latency against fairness -
   * we want to handle softirqs as soon as possible, but they
   * should not be able to lock up the box.
   */
 -#define MAX_SOFTIRQ_RESTART 10
 +#define MAX_SOFTIRQ_TIME  msecs_to_jiffies(2)
  
  asmlinkage void __do_softirq(void)
  {
        struct softirq_action *h;
        __u32 pending;
 -      int max_restart = MAX_SOFTIRQ_RESTART;
 +      unsigned long end = jiffies + MAX_SOFTIRQ_TIME;
        int cpu;
        unsigned long old_flags = current->flags;
  
@@@ -264,12 -264,11 +264,12 @@@ restart
        local_irq_disable();
  
        pending = local_softirq_pending();
 -      if (pending && --max_restart)
 -              goto restart;
 +      if (pending) {
 +              if (time_before(jiffies, end) && !need_resched())
 +                      goto restart;
  
 -      if (pending)
                wakeup_softirqd();
 +      }
  
        lockdep_softirq_exit();
  
@@@ -323,18 -322,10 +323,10 @@@ void irq_enter(void
  
  static inline void invoke_softirq(void)
  {
-       if (!force_irqthreads) {
- #ifdef __ARCH_IRQ_EXIT_IRQS_DISABLED
+       if (!force_irqthreads)
                __do_softirq();
- #else
-               do_softirq();
- #endif
-       } else {
-               __local_bh_disable((unsigned long)__builtin_return_address(0),
-                               SOFTIRQ_OFFSET);
+       else
                wakeup_softirqd();
-               __local_bh_enable(SOFTIRQ_OFFSET);
-       }
  }
  
  /*
   */
  void irq_exit(void)
  {
+ #ifndef __ARCH_IRQ_EXIT_IRQS_DISABLED
+       local_irq_disable();
+ #else
+       WARN_ON_ONCE(!irqs_disabled());
+ #endif
        account_irq_exit_time(current);
        trace_hardirq_exit();
-       sub_preempt_count(IRQ_EXIT_OFFSET);
+       sub_preempt_count(HARDIRQ_OFFSET);
        if (!in_interrupt() && local_softirq_pending())
                invoke_softirq();
  
                tick_nohz_irq_exit();
  #endif
        rcu_irq_exit();
-       sched_preempt_enable_no_resched();
  }
  
  /*