188763a5cSDaniel Lezcano // SPDX-License-Identifier: GPL-2.0 288763a5cSDaniel Lezcano /* 388763a5cSDaniel Lezcano * Copyright 2018 Linaro Limited 488763a5cSDaniel Lezcano * 588763a5cSDaniel Lezcano * Author: Daniel Lezcano <daniel.lezcano@linaro.org> 688763a5cSDaniel Lezcano * 788763a5cSDaniel Lezcano * The idle injection framework provides a way to force CPUs to enter idle 888763a5cSDaniel Lezcano * states for a specified fraction of time over a specified period. 988763a5cSDaniel Lezcano * 1088763a5cSDaniel Lezcano * It relies on the smpboot kthreads feature providing common code for CPU 1188763a5cSDaniel Lezcano * hotplug and thread [un]parking. 1288763a5cSDaniel Lezcano * 1388763a5cSDaniel Lezcano * All of the kthreads used for idle injection are created at init time. 1488763a5cSDaniel Lezcano * 1588763a5cSDaniel Lezcano * Next, the users of the the idle injection framework provide a cpumask via 1688763a5cSDaniel Lezcano * its register function. The kthreads will be synchronized with respect to 1788763a5cSDaniel Lezcano * this cpumask. 1888763a5cSDaniel Lezcano * 1988763a5cSDaniel Lezcano * The idle + run duration is specified via separate helpers and that allows 2088763a5cSDaniel Lezcano * idle injection to be started. 2188763a5cSDaniel Lezcano * 220735069cSYangtao Li * The idle injection kthreads will call play_idle_precise() with the idle 230735069cSYangtao Li * duration and max allowed latency specified as per the above. 2488763a5cSDaniel Lezcano * 2588763a5cSDaniel Lezcano * After all of them have been woken up, a timer is set to start the next idle 2688763a5cSDaniel Lezcano * injection cycle. 2788763a5cSDaniel Lezcano * 2888763a5cSDaniel Lezcano * The timer interrupt handler will wake up the idle injection kthreads for 2988763a5cSDaniel Lezcano * all of the CPUs in the cpumask provided by the user. 3088763a5cSDaniel Lezcano * 3188763a5cSDaniel Lezcano * Idle injection is stopped synchronously and no leftover idle injection 3288763a5cSDaniel Lezcano * kthread activity after its completion is guaranteed. 3388763a5cSDaniel Lezcano * 3488763a5cSDaniel Lezcano * It is up to the user of this framework to provide a lock for higher-level 3588763a5cSDaniel Lezcano * synchronization to prevent race conditions like starting idle injection 3688763a5cSDaniel Lezcano * while unregistering from the framework. 3788763a5cSDaniel Lezcano */ 3888763a5cSDaniel Lezcano #define pr_fmt(fmt) "ii_dev: " fmt 3988763a5cSDaniel Lezcano 4088763a5cSDaniel Lezcano #include <linux/cpu.h> 4188763a5cSDaniel Lezcano #include <linux/hrtimer.h> 4288763a5cSDaniel Lezcano #include <linux/kthread.h> 4388763a5cSDaniel Lezcano #include <linux/sched.h> 4488763a5cSDaniel Lezcano #include <linux/slab.h> 4588763a5cSDaniel Lezcano #include <linux/smpboot.h> 46*00610935SPujin Shi #include <linux/idle_inject.h> 4788763a5cSDaniel Lezcano 4888763a5cSDaniel Lezcano #include <uapi/linux/sched/types.h> 4988763a5cSDaniel Lezcano 5088763a5cSDaniel Lezcano /** 5188763a5cSDaniel Lezcano * struct idle_inject_thread - task on/off switch structure 5288763a5cSDaniel Lezcano * @tsk: task injecting the idle cycles 5388763a5cSDaniel Lezcano * @should_run: whether or not to run the task (for the smpboot kthread API) 5488763a5cSDaniel Lezcano */ 5588763a5cSDaniel Lezcano struct idle_inject_thread { 5688763a5cSDaniel Lezcano struct task_struct *tsk; 5788763a5cSDaniel Lezcano int should_run; 5888763a5cSDaniel Lezcano }; 5988763a5cSDaniel Lezcano 6088763a5cSDaniel Lezcano /** 6188763a5cSDaniel Lezcano * struct idle_inject_device - idle injection data 6288763a5cSDaniel Lezcano * @timer: idle injection period timer 63cd4c0763SDaniel Lezcano * @idle_duration_us: duration of CPU idle time to inject 64cd4c0763SDaniel Lezcano * @run_duration_us: duration of CPU run time to allow 65333cff6cSDaniel Lezcano * @latency_us: max allowed latency 6688763a5cSDaniel Lezcano * @cpumask: mask of CPUs affected by idle injection 6788763a5cSDaniel Lezcano */ 6888763a5cSDaniel Lezcano struct idle_inject_device { 6988763a5cSDaniel Lezcano struct hrtimer timer; 70cd4c0763SDaniel Lezcano unsigned int idle_duration_us; 71cd4c0763SDaniel Lezcano unsigned int run_duration_us; 72333cff6cSDaniel Lezcano unsigned int latency_us; 7327565c9eSGustavo A. R. Silva unsigned long cpumask[]; 7488763a5cSDaniel Lezcano }; 7588763a5cSDaniel Lezcano 7688763a5cSDaniel Lezcano static DEFINE_PER_CPU(struct idle_inject_thread, idle_inject_thread); 7788763a5cSDaniel Lezcano static DEFINE_PER_CPU(struct idle_inject_device *, idle_inject_device); 7888763a5cSDaniel Lezcano 7988763a5cSDaniel Lezcano /** 8088763a5cSDaniel Lezcano * idle_inject_wakeup - Wake up idle injection threads 8188763a5cSDaniel Lezcano * @ii_dev: target idle injection device 8288763a5cSDaniel Lezcano * 8388763a5cSDaniel Lezcano * Every idle injection task associated with the given idle injection device 8488763a5cSDaniel Lezcano * and running on an online CPU will be woken up. 8588763a5cSDaniel Lezcano */ 8688763a5cSDaniel Lezcano static void idle_inject_wakeup(struct idle_inject_device *ii_dev) 8788763a5cSDaniel Lezcano { 8888763a5cSDaniel Lezcano struct idle_inject_thread *iit; 8988763a5cSDaniel Lezcano unsigned int cpu; 9088763a5cSDaniel Lezcano 9188763a5cSDaniel Lezcano for_each_cpu_and(cpu, to_cpumask(ii_dev->cpumask), cpu_online_mask) { 9288763a5cSDaniel Lezcano iit = per_cpu_ptr(&idle_inject_thread, cpu); 9388763a5cSDaniel Lezcano iit->should_run = 1; 9488763a5cSDaniel Lezcano wake_up_process(iit->tsk); 9588763a5cSDaniel Lezcano } 9688763a5cSDaniel Lezcano } 9788763a5cSDaniel Lezcano 9888763a5cSDaniel Lezcano /** 9988763a5cSDaniel Lezcano * idle_inject_timer_fn - idle injection timer function 10088763a5cSDaniel Lezcano * @timer: idle injection hrtimer 10188763a5cSDaniel Lezcano * 10288763a5cSDaniel Lezcano * This function is called when the idle injection timer expires. It wakes up 10388763a5cSDaniel Lezcano * idle injection tasks associated with the timer and they, in turn, invoke 1040735069cSYangtao Li * play_idle_precise() to inject a specified amount of CPU idle time. 10588763a5cSDaniel Lezcano * 10688763a5cSDaniel Lezcano * Return: HRTIMER_RESTART. 10788763a5cSDaniel Lezcano */ 10888763a5cSDaniel Lezcano static enum hrtimer_restart idle_inject_timer_fn(struct hrtimer *timer) 10988763a5cSDaniel Lezcano { 110cd4c0763SDaniel Lezcano unsigned int duration_us; 11188763a5cSDaniel Lezcano struct idle_inject_device *ii_dev = 11288763a5cSDaniel Lezcano container_of(timer, struct idle_inject_device, timer); 11388763a5cSDaniel Lezcano 114cd4c0763SDaniel Lezcano duration_us = READ_ONCE(ii_dev->run_duration_us); 115cd4c0763SDaniel Lezcano duration_us += READ_ONCE(ii_dev->idle_duration_us); 11688763a5cSDaniel Lezcano 11788763a5cSDaniel Lezcano idle_inject_wakeup(ii_dev); 11888763a5cSDaniel Lezcano 119cd4c0763SDaniel Lezcano hrtimer_forward_now(timer, ns_to_ktime(duration_us * NSEC_PER_USEC)); 12088763a5cSDaniel Lezcano 12188763a5cSDaniel Lezcano return HRTIMER_RESTART; 12288763a5cSDaniel Lezcano } 12388763a5cSDaniel Lezcano 12488763a5cSDaniel Lezcano /** 12588763a5cSDaniel Lezcano * idle_inject_fn - idle injection work function 12688763a5cSDaniel Lezcano * @cpu: the CPU owning the task 12788763a5cSDaniel Lezcano * 1280735069cSYangtao Li * This function calls play_idle_precise() to inject a specified amount of CPU 1290735069cSYangtao Li * idle time. 13088763a5cSDaniel Lezcano */ 13188763a5cSDaniel Lezcano static void idle_inject_fn(unsigned int cpu) 13288763a5cSDaniel Lezcano { 13388763a5cSDaniel Lezcano struct idle_inject_device *ii_dev; 13488763a5cSDaniel Lezcano struct idle_inject_thread *iit; 13588763a5cSDaniel Lezcano 13688763a5cSDaniel Lezcano ii_dev = per_cpu(idle_inject_device, cpu); 13788763a5cSDaniel Lezcano iit = per_cpu_ptr(&idle_inject_thread, cpu); 13888763a5cSDaniel Lezcano 13988763a5cSDaniel Lezcano /* 14088763a5cSDaniel Lezcano * Let the smpboot main loop know that the task should not run again. 14188763a5cSDaniel Lezcano */ 14288763a5cSDaniel Lezcano iit->should_run = 0; 14388763a5cSDaniel Lezcano 144333cff6cSDaniel Lezcano play_idle_precise(READ_ONCE(ii_dev->idle_duration_us) * NSEC_PER_USEC, 145333cff6cSDaniel Lezcano READ_ONCE(ii_dev->latency_us) * NSEC_PER_USEC); 14688763a5cSDaniel Lezcano } 14788763a5cSDaniel Lezcano 14888763a5cSDaniel Lezcano /** 14988763a5cSDaniel Lezcano * idle_inject_set_duration - idle and run duration update helper 150cd4c0763SDaniel Lezcano * @run_duration_us: CPU run time to allow in microseconds 151cd4c0763SDaniel Lezcano * @idle_duration_us: CPU idle time to inject in microseconds 15288763a5cSDaniel Lezcano */ 15388763a5cSDaniel Lezcano void idle_inject_set_duration(struct idle_inject_device *ii_dev, 154cd4c0763SDaniel Lezcano unsigned int run_duration_us, 155cd4c0763SDaniel Lezcano unsigned int idle_duration_us) 15688763a5cSDaniel Lezcano { 157cd4c0763SDaniel Lezcano if (run_duration_us && idle_duration_us) { 158cd4c0763SDaniel Lezcano WRITE_ONCE(ii_dev->run_duration_us, run_duration_us); 159cd4c0763SDaniel Lezcano WRITE_ONCE(ii_dev->idle_duration_us, idle_duration_us); 16088763a5cSDaniel Lezcano } 16188763a5cSDaniel Lezcano } 16288763a5cSDaniel Lezcano 16388763a5cSDaniel Lezcano /** 16488763a5cSDaniel Lezcano * idle_inject_get_duration - idle and run duration retrieval helper 165cd4c0763SDaniel Lezcano * @run_duration_us: memory location to store the current CPU run time 166cd4c0763SDaniel Lezcano * @idle_duration_us: memory location to store the current CPU idle time 16788763a5cSDaniel Lezcano */ 16888763a5cSDaniel Lezcano void idle_inject_get_duration(struct idle_inject_device *ii_dev, 169cd4c0763SDaniel Lezcano unsigned int *run_duration_us, 170cd4c0763SDaniel Lezcano unsigned int *idle_duration_us) 17188763a5cSDaniel Lezcano { 172cd4c0763SDaniel Lezcano *run_duration_us = READ_ONCE(ii_dev->run_duration_us); 173cd4c0763SDaniel Lezcano *idle_duration_us = READ_ONCE(ii_dev->idle_duration_us); 17488763a5cSDaniel Lezcano } 17588763a5cSDaniel Lezcano 17688763a5cSDaniel Lezcano /** 177333cff6cSDaniel Lezcano * idle_inject_set_latency - set the maximum latency allowed 178333cff6cSDaniel Lezcano * @latency_us: set the latency requirement for the idle state 179333cff6cSDaniel Lezcano */ 180333cff6cSDaniel Lezcano void idle_inject_set_latency(struct idle_inject_device *ii_dev, 181333cff6cSDaniel Lezcano unsigned int latency_us) 182333cff6cSDaniel Lezcano { 183333cff6cSDaniel Lezcano WRITE_ONCE(ii_dev->latency_us, latency_us); 184333cff6cSDaniel Lezcano } 185333cff6cSDaniel Lezcano 186333cff6cSDaniel Lezcano /** 18788763a5cSDaniel Lezcano * idle_inject_start - start idle injections 18888763a5cSDaniel Lezcano * @ii_dev: idle injection control device structure 18988763a5cSDaniel Lezcano * 19088763a5cSDaniel Lezcano * The function starts idle injection by first waking up all of the idle 19188763a5cSDaniel Lezcano * injection kthreads associated with @ii_dev to let them inject CPU idle time 19288763a5cSDaniel Lezcano * sets up a timer to start the next idle injection period. 19388763a5cSDaniel Lezcano * 19488763a5cSDaniel Lezcano * Return: -EINVAL if the CPU idle or CPU run time is not set or 0 on success. 19588763a5cSDaniel Lezcano */ 19688763a5cSDaniel Lezcano int idle_inject_start(struct idle_inject_device *ii_dev) 19788763a5cSDaniel Lezcano { 198cd4c0763SDaniel Lezcano unsigned int idle_duration_us = READ_ONCE(ii_dev->idle_duration_us); 199cd4c0763SDaniel Lezcano unsigned int run_duration_us = READ_ONCE(ii_dev->run_duration_us); 20088763a5cSDaniel Lezcano 201cd4c0763SDaniel Lezcano if (!idle_duration_us || !run_duration_us) 20288763a5cSDaniel Lezcano return -EINVAL; 20388763a5cSDaniel Lezcano 20488763a5cSDaniel Lezcano pr_debug("Starting injecting idle cycles on CPUs '%*pbl'\n", 20588763a5cSDaniel Lezcano cpumask_pr_args(to_cpumask(ii_dev->cpumask))); 20688763a5cSDaniel Lezcano 20788763a5cSDaniel Lezcano idle_inject_wakeup(ii_dev); 20888763a5cSDaniel Lezcano 20988763a5cSDaniel Lezcano hrtimer_start(&ii_dev->timer, 210cd4c0763SDaniel Lezcano ns_to_ktime((idle_duration_us + run_duration_us) * 211cd4c0763SDaniel Lezcano NSEC_PER_USEC), 21288763a5cSDaniel Lezcano HRTIMER_MODE_REL); 21388763a5cSDaniel Lezcano 21488763a5cSDaniel Lezcano return 0; 21588763a5cSDaniel Lezcano } 21688763a5cSDaniel Lezcano 21788763a5cSDaniel Lezcano /** 21888763a5cSDaniel Lezcano * idle_inject_stop - stops idle injections 21988763a5cSDaniel Lezcano * @ii_dev: idle injection control device structure 22088763a5cSDaniel Lezcano * 22188763a5cSDaniel Lezcano * The function stops idle injection and waits for the threads to finish work. 22288763a5cSDaniel Lezcano * If CPU idle time is being injected when this function runs, then it will 22388763a5cSDaniel Lezcano * wait until the end of the cycle. 22488763a5cSDaniel Lezcano * 22588763a5cSDaniel Lezcano * When it returns, there is no more idle injection kthread activity. The 22688763a5cSDaniel Lezcano * kthreads are scheduled out and the periodic timer is off. 22788763a5cSDaniel Lezcano */ 22888763a5cSDaniel Lezcano void idle_inject_stop(struct idle_inject_device *ii_dev) 22988763a5cSDaniel Lezcano { 23088763a5cSDaniel Lezcano struct idle_inject_thread *iit; 23188763a5cSDaniel Lezcano unsigned int cpu; 23288763a5cSDaniel Lezcano 23388763a5cSDaniel Lezcano pr_debug("Stopping idle injection on CPUs '%*pbl'\n", 23488763a5cSDaniel Lezcano cpumask_pr_args(to_cpumask(ii_dev->cpumask))); 23588763a5cSDaniel Lezcano 23688763a5cSDaniel Lezcano hrtimer_cancel(&ii_dev->timer); 23788763a5cSDaniel Lezcano 23888763a5cSDaniel Lezcano /* 23988763a5cSDaniel Lezcano * Stopping idle injection requires all of the idle injection kthreads 24088763a5cSDaniel Lezcano * associated with the given cpumask to be parked and stay that way, so 24188763a5cSDaniel Lezcano * prevent CPUs from going online at this point. Any CPUs going online 24288763a5cSDaniel Lezcano * after the loop below will be covered by clearing the should_run flag 24388763a5cSDaniel Lezcano * that will cause the smpboot main loop to schedule them out. 24488763a5cSDaniel Lezcano */ 24588763a5cSDaniel Lezcano cpu_hotplug_disable(); 24688763a5cSDaniel Lezcano 24788763a5cSDaniel Lezcano /* 24888763a5cSDaniel Lezcano * Iterate over all (online + offline) CPUs here in case one of them 24988763a5cSDaniel Lezcano * goes offline with the should_run flag set so as to prevent its idle 25088763a5cSDaniel Lezcano * injection kthread from running when the CPU goes online again after 25188763a5cSDaniel Lezcano * the ii_dev has been freed. 25288763a5cSDaniel Lezcano */ 25388763a5cSDaniel Lezcano for_each_cpu(cpu, to_cpumask(ii_dev->cpumask)) { 25488763a5cSDaniel Lezcano iit = per_cpu_ptr(&idle_inject_thread, cpu); 25588763a5cSDaniel Lezcano iit->should_run = 0; 25688763a5cSDaniel Lezcano 25788763a5cSDaniel Lezcano wait_task_inactive(iit->tsk, 0); 25888763a5cSDaniel Lezcano } 25988763a5cSDaniel Lezcano 26088763a5cSDaniel Lezcano cpu_hotplug_enable(); 26188763a5cSDaniel Lezcano } 26288763a5cSDaniel Lezcano 26388763a5cSDaniel Lezcano /** 26488763a5cSDaniel Lezcano * idle_inject_setup - prepare the current task for idle injection 26588763a5cSDaniel Lezcano * @cpu: not used 26688763a5cSDaniel Lezcano * 26788763a5cSDaniel Lezcano * Called once, this function is in charge of setting the current task's 26888763a5cSDaniel Lezcano * scheduler parameters to make it an RT task. 26988763a5cSDaniel Lezcano */ 27088763a5cSDaniel Lezcano static void idle_inject_setup(unsigned int cpu) 27188763a5cSDaniel Lezcano { 272c3f47cf9SPeter Zijlstra sched_set_fifo(current); 27388763a5cSDaniel Lezcano } 27488763a5cSDaniel Lezcano 27588763a5cSDaniel Lezcano /** 27688763a5cSDaniel Lezcano * idle_inject_should_run - function helper for the smpboot API 27788763a5cSDaniel Lezcano * @cpu: CPU the kthread is running on 27888763a5cSDaniel Lezcano * 27988763a5cSDaniel Lezcano * Return: whether or not the thread can run. 28088763a5cSDaniel Lezcano */ 28188763a5cSDaniel Lezcano static int idle_inject_should_run(unsigned int cpu) 28288763a5cSDaniel Lezcano { 28388763a5cSDaniel Lezcano struct idle_inject_thread *iit = 28488763a5cSDaniel Lezcano per_cpu_ptr(&idle_inject_thread, cpu); 28588763a5cSDaniel Lezcano 28688763a5cSDaniel Lezcano return iit->should_run; 28788763a5cSDaniel Lezcano } 28888763a5cSDaniel Lezcano 28988763a5cSDaniel Lezcano /** 29088763a5cSDaniel Lezcano * idle_inject_register - initialize idle injection on a set of CPUs 29188763a5cSDaniel Lezcano * @cpumask: CPUs to be affected by idle injection 29288763a5cSDaniel Lezcano * 29388763a5cSDaniel Lezcano * This function creates an idle injection control device structure for the 29488763a5cSDaniel Lezcano * given set of CPUs and initializes the timer associated with it. It does not 29588763a5cSDaniel Lezcano * start any injection cycles. 29688763a5cSDaniel Lezcano * 29788763a5cSDaniel Lezcano * Return: NULL if memory allocation fails, idle injection control device 29888763a5cSDaniel Lezcano * pointer on success. 29988763a5cSDaniel Lezcano */ 30088763a5cSDaniel Lezcano struct idle_inject_device *idle_inject_register(struct cpumask *cpumask) 30188763a5cSDaniel Lezcano { 30288763a5cSDaniel Lezcano struct idle_inject_device *ii_dev; 30388763a5cSDaniel Lezcano int cpu, cpu_rb; 30488763a5cSDaniel Lezcano 30588763a5cSDaniel Lezcano ii_dev = kzalloc(sizeof(*ii_dev) + cpumask_size(), GFP_KERNEL); 30688763a5cSDaniel Lezcano if (!ii_dev) 30788763a5cSDaniel Lezcano return NULL; 30888763a5cSDaniel Lezcano 30988763a5cSDaniel Lezcano cpumask_copy(to_cpumask(ii_dev->cpumask), cpumask); 31088763a5cSDaniel Lezcano hrtimer_init(&ii_dev->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); 31188763a5cSDaniel Lezcano ii_dev->timer.function = idle_inject_timer_fn; 312333cff6cSDaniel Lezcano ii_dev->latency_us = UINT_MAX; 31388763a5cSDaniel Lezcano 31488763a5cSDaniel Lezcano for_each_cpu(cpu, to_cpumask(ii_dev->cpumask)) { 31588763a5cSDaniel Lezcano 31688763a5cSDaniel Lezcano if (per_cpu(idle_inject_device, cpu)) { 31788763a5cSDaniel Lezcano pr_err("cpu%d is already registered\n", cpu); 31888763a5cSDaniel Lezcano goto out_rollback; 31988763a5cSDaniel Lezcano } 32088763a5cSDaniel Lezcano 32188763a5cSDaniel Lezcano per_cpu(idle_inject_device, cpu) = ii_dev; 32288763a5cSDaniel Lezcano } 32388763a5cSDaniel Lezcano 32488763a5cSDaniel Lezcano return ii_dev; 32588763a5cSDaniel Lezcano 32688763a5cSDaniel Lezcano out_rollback: 32788763a5cSDaniel Lezcano for_each_cpu(cpu_rb, to_cpumask(ii_dev->cpumask)) { 32888763a5cSDaniel Lezcano if (cpu == cpu_rb) 32988763a5cSDaniel Lezcano break; 33088763a5cSDaniel Lezcano per_cpu(idle_inject_device, cpu_rb) = NULL; 33188763a5cSDaniel Lezcano } 33288763a5cSDaniel Lezcano 33388763a5cSDaniel Lezcano kfree(ii_dev); 33488763a5cSDaniel Lezcano 33588763a5cSDaniel Lezcano return NULL; 33688763a5cSDaniel Lezcano } 33788763a5cSDaniel Lezcano 33888763a5cSDaniel Lezcano /** 33988763a5cSDaniel Lezcano * idle_inject_unregister - unregister idle injection control device 34088763a5cSDaniel Lezcano * @ii_dev: idle injection control device to unregister 34188763a5cSDaniel Lezcano * 34288763a5cSDaniel Lezcano * The function stops idle injection for the given control device, 34388763a5cSDaniel Lezcano * unregisters its kthreads and frees memory allocated when that device was 34488763a5cSDaniel Lezcano * created. 34588763a5cSDaniel Lezcano */ 34688763a5cSDaniel Lezcano void idle_inject_unregister(struct idle_inject_device *ii_dev) 34788763a5cSDaniel Lezcano { 34888763a5cSDaniel Lezcano unsigned int cpu; 34988763a5cSDaniel Lezcano 35088763a5cSDaniel Lezcano idle_inject_stop(ii_dev); 35188763a5cSDaniel Lezcano 35288763a5cSDaniel Lezcano for_each_cpu(cpu, to_cpumask(ii_dev->cpumask)) 35388763a5cSDaniel Lezcano per_cpu(idle_inject_device, cpu) = NULL; 35488763a5cSDaniel Lezcano 35588763a5cSDaniel Lezcano kfree(ii_dev); 35688763a5cSDaniel Lezcano } 35788763a5cSDaniel Lezcano 35888763a5cSDaniel Lezcano static struct smp_hotplug_thread idle_inject_threads = { 35988763a5cSDaniel Lezcano .store = &idle_inject_thread.tsk, 36088763a5cSDaniel Lezcano .setup = idle_inject_setup, 36188763a5cSDaniel Lezcano .thread_fn = idle_inject_fn, 36288763a5cSDaniel Lezcano .thread_comm = "idle_inject/%u", 36388763a5cSDaniel Lezcano .thread_should_run = idle_inject_should_run, 36488763a5cSDaniel Lezcano }; 36588763a5cSDaniel Lezcano 36688763a5cSDaniel Lezcano static int __init idle_inject_init(void) 36788763a5cSDaniel Lezcano { 36888763a5cSDaniel Lezcano return smpboot_register_percpu_thread(&idle_inject_threads); 36988763a5cSDaniel Lezcano } 37088763a5cSDaniel Lezcano early_initcall(idle_inject_init); 371