}
  
  /*
 - * Queue the entry and raise the IPI if needed.
 + * Enqueue the irq_work @entry unless it's already pending
 + * somewhere.
 + *
 + * Can be re-enqueued while the callback is still in progress.
   */
 -static void __irq_work_queue(struct irq_work *work)
 +void irq_work_queue(struct irq_work *work)
  {
-       bool empty;
- 
 +      /* Only queue if not already pending */
 +      if (!irq_work_claim(work))
 +              return;
 +
 +      /* Queue the entry and raise the IPI if needed. */
        preempt_disable();
  
-       empty = llist_add(&work->llnode, &__get_cpu_var(irq_work_list));
-       /* The list was empty, raise self-interrupt to start processing. */
-       if (empty)
-               arch_irq_work_raise();
+       llist_add(&work->llnode, &__get_cpu_var(irq_work_list));
+ 
+       /*
+        * If the work is not "lazy" or the tick is stopped, raise the irq
+        * work interrupt (if supported by the arch), otherwise, just wait
+        * for the next tick.
+        */
+       if (!(work->flags & IRQ_WORK_LAZY) || tick_nohz_tick_stopped()) {
+               if (!this_cpu_cmpxchg(irq_work_raised, 0, 1))
+                       arch_irq_work_raise();
+       }
  
        preempt_enable();
  }
 -
 -/*
 - * Enqueue the irq_work @entry, returns true on success, failure when the
 - * @entry was already enqueued by someone else.
 - *
 - * Can be re-enqueued while the callback is still in progress.
 - */
 -bool irq_work_queue(struct irq_work *work)
 -{
 -      if (!irq_work_claim(work)) {
 -              /*
 -               * Already enqueued, can't do!
 -               */
 -              return false;
 -      }
 -
 -      __irq_work_queue(work);
 -      return true;
 -}
  EXPORT_SYMBOL_GPL(irq_work_queue);
  
- /*
-  * Run the irq_work entries on this cpu. Requires to be ran from hardirq
-  * context with local IRQs disabled.
-  */
- void irq_work_run(void)
+ bool irq_work_needs_cpu(void)
+ {
+       struct llist_head *this_list;
+ 
+       this_list = &__get_cpu_var(irq_work_list);
+       if (llist_empty(this_list))
+               return false;
+ 
+       /* All work should have been flushed before going offline */
+       WARN_ON_ONCE(cpu_is_offline(smp_processor_id()));
+ 
+       return true;
+ }
+ 
+ static void __irq_work_run(void)
  {
+       unsigned long flags;
        struct irq_work *work;
        struct llist_head *this_list;
        struct llist_node *llnode;
 
  /*
   * Per cpu nohz control structure
   */
- static DEFINE_PER_CPU(struct tick_sched, tick_cpu_sched);
+ DEFINE_PER_CPU(struct tick_sched, tick_cpu_sched);
  
  /*
 - * The time, when the last jiffy update happened. Protected by xtime_lock.
 + * The time, when the last jiffy update happened. Protected by jiffies_lock.
   */
  static ktime_t last_jiffies_update;
  
                last_update = last_jiffies_update;
                last_jiffies = jiffies;
                time_delta = timekeeping_max_deferment();
 -      } while (read_seqretry(&xtime_lock, seq));
 +      } while (read_seqretry(&jiffies_lock, seq));
  
-       if (rcu_needs_cpu(cpu, &rcu_delta_jiffies) || printk_needs_cpu(cpu) ||
-           arch_needs_cpu(cpu)) {
+       if (rcu_needs_cpu(cpu, &rcu_delta_jiffies) ||
+           arch_needs_cpu(cpu) || irq_work_needs_cpu()) {
                next_jiffies = last_jiffies + 1;
                delta_jiffies = 1;
        } else {