0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/bug.h>
0010 #include <linux/kernel.h>
0011 #include <linux/export.h>
0012 #include <linux/irq_work.h>
0013 #include <linux/percpu.h>
0014 #include <linux/hardirq.h>
0015 #include <linux/irqflags.h>
0016 #include <linux/sched.h>
0017 #include <linux/tick.h>
0018 #include <linux/cpu.h>
0019 #include <linux/notifier.h>
0020 #include <linux/smp.h>
0021 #include <linux/smpboot.h>
0022 #include <asm/processor.h>
0023 #include <linux/kasan.h>
0024
0025 static DEFINE_PER_CPU(struct llist_head, raised_list);
0026 static DEFINE_PER_CPU(struct llist_head, lazy_list);
0027 static DEFINE_PER_CPU(struct task_struct *, irq_workd);
0028
0029 static void wake_irq_workd(void)
0030 {
0031 struct task_struct *tsk = __this_cpu_read(irq_workd);
0032
0033 if (!llist_empty(this_cpu_ptr(&lazy_list)) && tsk)
0034 wake_up_process(tsk);
0035 }
0036
0037 #ifdef CONFIG_SMP
0038 static void irq_work_wake(struct irq_work *entry)
0039 {
0040 wake_irq_workd();
0041 }
0042
0043 static DEFINE_PER_CPU(struct irq_work, irq_work_wakeup) =
0044 IRQ_WORK_INIT_HARD(irq_work_wake);
0045 #endif
0046
0047 static int irq_workd_should_run(unsigned int cpu)
0048 {
0049 return !llist_empty(this_cpu_ptr(&lazy_list));
0050 }
0051
0052
0053
0054
0055 static bool irq_work_claim(struct irq_work *work)
0056 {
0057 int oflags;
0058
0059 oflags = atomic_fetch_or(IRQ_WORK_CLAIMED | CSD_TYPE_IRQ_WORK, &work->node.a_flags);
0060
0061
0062
0063
0064
0065 if (oflags & IRQ_WORK_PENDING)
0066 return false;
0067 return true;
0068 }
0069
0070 void __weak arch_irq_work_raise(void)
0071 {
0072
0073
0074
0075 }
0076
0077
0078 static void __irq_work_queue_local(struct irq_work *work)
0079 {
0080 struct llist_head *list;
0081 bool rt_lazy_work = false;
0082 bool lazy_work = false;
0083 int work_flags;
0084
0085 work_flags = atomic_read(&work->node.a_flags);
0086 if (work_flags & IRQ_WORK_LAZY)
0087 lazy_work = true;
0088 else if (IS_ENABLED(CONFIG_PREEMPT_RT) &&
0089 !(work_flags & IRQ_WORK_HARD_IRQ))
0090 rt_lazy_work = true;
0091
0092 if (lazy_work || rt_lazy_work)
0093 list = this_cpu_ptr(&lazy_list);
0094 else
0095 list = this_cpu_ptr(&raised_list);
0096
0097 if (!llist_add(&work->node.llist, list))
0098 return;
0099
0100
0101 if (!lazy_work || tick_nohz_tick_stopped())
0102 arch_irq_work_raise();
0103 }
0104
0105
0106 bool irq_work_queue(struct irq_work *work)
0107 {
0108
0109 if (!irq_work_claim(work))
0110 return false;
0111
0112
0113 preempt_disable();
0114 __irq_work_queue_local(work);
0115 preempt_enable();
0116
0117 return true;
0118 }
0119 EXPORT_SYMBOL_GPL(irq_work_queue);
0120
0121
0122
0123
0124
0125
0126
0127 bool irq_work_queue_on(struct irq_work *work, int cpu)
0128 {
0129 #ifndef CONFIG_SMP
0130 return irq_work_queue(work);
0131
0132 #else
0133
0134 WARN_ON_ONCE(cpu_is_offline(cpu));
0135
0136
0137 if (!irq_work_claim(work))
0138 return false;
0139
0140 kasan_record_aux_stack_noalloc(work);
0141
0142 preempt_disable();
0143 if (cpu != smp_processor_id()) {
0144
0145 WARN_ON_ONCE(in_nmi());
0146
0147
0148
0149
0150
0151
0152 if (IS_ENABLED(CONFIG_PREEMPT_RT) &&
0153 !(atomic_read(&work->node.a_flags) & IRQ_WORK_HARD_IRQ)) {
0154
0155 if (!llist_add(&work->node.llist, &per_cpu(lazy_list, cpu)))
0156 goto out;
0157
0158 work = &per_cpu(irq_work_wakeup, cpu);
0159 if (!irq_work_claim(work))
0160 goto out;
0161 }
0162
0163 __smp_call_single_queue(cpu, &work->node.llist);
0164 } else {
0165 __irq_work_queue_local(work);
0166 }
0167 out:
0168 preempt_enable();
0169
0170 return true;
0171 #endif
0172 }
0173
0174 bool irq_work_needs_cpu(void)
0175 {
0176 struct llist_head *raised, *lazy;
0177
0178 raised = this_cpu_ptr(&raised_list);
0179 lazy = this_cpu_ptr(&lazy_list);
0180
0181 if (llist_empty(raised) || arch_irq_work_has_interrupt())
0182 if (llist_empty(lazy))
0183 return false;
0184
0185
0186 WARN_ON_ONCE(cpu_is_offline(smp_processor_id()));
0187
0188 return true;
0189 }
0190
0191 void irq_work_single(void *arg)
0192 {
0193 struct irq_work *work = arg;
0194 int flags;
0195
0196
0197
0198
0199
0200
0201 flags = atomic_read(&work->node.a_flags);
0202 flags &= ~IRQ_WORK_PENDING;
0203 atomic_set(&work->node.a_flags, flags);
0204
0205
0206
0207
0208 smp_mb();
0209
0210 lockdep_irq_work_enter(flags);
0211 work->func(work);
0212 lockdep_irq_work_exit(flags);
0213
0214
0215
0216
0217
0218 (void)atomic_cmpxchg(&work->node.a_flags, flags, flags & ~IRQ_WORK_BUSY);
0219
0220 if ((IS_ENABLED(CONFIG_PREEMPT_RT) && !irq_work_is_hard(work)) ||
0221 !arch_irq_work_has_interrupt())
0222 rcuwait_wake_up(&work->irqwait);
0223 }
0224
0225 static void irq_work_run_list(struct llist_head *list)
0226 {
0227 struct irq_work *work, *tmp;
0228 struct llist_node *llnode;
0229
0230
0231
0232
0233
0234
0235 BUG_ON(!irqs_disabled() && !IS_ENABLED(CONFIG_PREEMPT_RT));
0236
0237 if (llist_empty(list))
0238 return;
0239
0240 llnode = llist_del_all(list);
0241 llist_for_each_entry_safe(work, tmp, llnode, node.llist)
0242 irq_work_single(work);
0243 }
0244
0245
0246
0247
0248
0249 void irq_work_run(void)
0250 {
0251 irq_work_run_list(this_cpu_ptr(&raised_list));
0252 if (!IS_ENABLED(CONFIG_PREEMPT_RT))
0253 irq_work_run_list(this_cpu_ptr(&lazy_list));
0254 else
0255 wake_irq_workd();
0256 }
0257 EXPORT_SYMBOL_GPL(irq_work_run);
0258
0259 void irq_work_tick(void)
0260 {
0261 struct llist_head *raised = this_cpu_ptr(&raised_list);
0262
0263 if (!llist_empty(raised) && !arch_irq_work_has_interrupt())
0264 irq_work_run_list(raised);
0265
0266 if (!IS_ENABLED(CONFIG_PREEMPT_RT))
0267 irq_work_run_list(this_cpu_ptr(&lazy_list));
0268 else
0269 wake_irq_workd();
0270 }
0271
0272
0273
0274
0275
0276 void irq_work_sync(struct irq_work *work)
0277 {
0278 lockdep_assert_irqs_enabled();
0279 might_sleep();
0280
0281 if ((IS_ENABLED(CONFIG_PREEMPT_RT) && !irq_work_is_hard(work)) ||
0282 !arch_irq_work_has_interrupt()) {
0283 rcuwait_wait_event(&work->irqwait, !irq_work_is_busy(work),
0284 TASK_UNINTERRUPTIBLE);
0285 return;
0286 }
0287
0288 while (irq_work_is_busy(work))
0289 cpu_relax();
0290 }
0291 EXPORT_SYMBOL_GPL(irq_work_sync);
0292
0293 static void run_irq_workd(unsigned int cpu)
0294 {
0295 irq_work_run_list(this_cpu_ptr(&lazy_list));
0296 }
0297
0298 static void irq_workd_setup(unsigned int cpu)
0299 {
0300 sched_set_fifo_low(current);
0301 }
0302
0303 static struct smp_hotplug_thread irqwork_threads = {
0304 .store = &irq_workd,
0305 .setup = irq_workd_setup,
0306 .thread_should_run = irq_workd_should_run,
0307 .thread_fn = run_irq_workd,
0308 .thread_comm = "irq_work/%u",
0309 };
0310
0311 static __init int irq_work_init_threads(void)
0312 {
0313 if (IS_ENABLED(CONFIG_PREEMPT_RT))
0314 BUG_ON(smpboot_register_percpu_thread(&irqwork_threads));
0315 return 0;
0316 }
0317 early_initcall(irq_work_init_threads);