Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * poll_state.c - Polling idle state
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);