0001
0002
0003
0004
0005
0006 #include <linux/cpuidle.h>
0007 #include <linux/sched.h>
0008 #include <linux/sched/clock.h>
0009 #include <linux/sched/idle.h>
0010
0011 #define POLL_IDLE_RELAX_COUNT 200
0012
0013 static int __cpuidle poll_idle(struct cpuidle_device *dev,
0014 struct cpuidle_driver *drv, int index)
0015 {
0016 u64 time_start = local_clock();
0017
0018 dev->poll_time_limit = false;
0019
0020 local_irq_enable();
0021 if (!current_set_polling_and_test()) {
0022 unsigned int loop_count = 0;
0023 u64 limit;
0024
0025 limit = cpuidle_poll_time(drv, dev);
0026
0027 while (!need_resched()) {
0028 cpu_relax();
0029 if (loop_count++ < POLL_IDLE_RELAX_COUNT)
0030 continue;
0031
0032 loop_count = 0;
0033 if (local_clock() - time_start > limit) {
0034 dev->poll_time_limit = true;
0035 break;
0036 }
0037 }
0038 }
0039 current_clr_polling();
0040
0041 return index;
0042 }
0043
0044 void cpuidle_poll_state_init(struct cpuidle_driver *drv)
0045 {
0046 struct cpuidle_state *state = &drv->states[0];
0047
0048 snprintf(state->name, CPUIDLE_NAME_LEN, "POLL");
0049 snprintf(state->desc, CPUIDLE_DESC_LEN, "CPUIDLE CORE POLL IDLE");
0050 state->exit_latency = 0;
0051 state->target_residency = 0;
0052 state->exit_latency_ns = 0;
0053 state->target_residency_ns = 0;
0054 state->power_usage = -1;
0055 state->enter = poll_idle;
0056 state->flags = CPUIDLE_FLAG_POLLING;
0057 }
0058 EXPORT_SYMBOL_GPL(cpuidle_poll_state_init);