poll_state.c 1.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * poll_state.c - Polling idle state
  4. */
  5. #include <linux/cpuidle.h>
  6. #include <linux/export.h>
  7. #include <linux/irqflags.h>
  8. #include <linux/sched.h>
  9. #include <linux/sched/clock.h>
  10. #include <linux/sched/idle.h>
  11. #include <linux/sprintf.h>
  12. #include <linux/types.h>
  13. #define POLL_IDLE_RELAX_COUNT 200
  14. static int __cpuidle poll_idle(struct cpuidle_device *dev,
  15. struct cpuidle_driver *drv, int index)
  16. {
  17. u64 time_start;
  18. time_start = local_clock_noinstr();
  19. dev->poll_time_limit = false;
  20. raw_local_irq_enable();
  21. if (!current_set_polling_and_test()) {
  22. unsigned int loop_count = 0;
  23. u64 limit;
  24. limit = cpuidle_poll_time(drv, dev);
  25. while (!need_resched()) {
  26. cpu_relax();
  27. if (loop_count++ < POLL_IDLE_RELAX_COUNT)
  28. continue;
  29. loop_count = 0;
  30. if (local_clock_noinstr() - time_start > limit) {
  31. dev->poll_time_limit = true;
  32. break;
  33. }
  34. }
  35. }
  36. raw_local_irq_disable();
  37. current_clr_polling();
  38. return index;
  39. }
  40. void cpuidle_poll_state_init(struct cpuidle_driver *drv)
  41. {
  42. struct cpuidle_state *state = &drv->states[0];
  43. snprintf(state->name, CPUIDLE_NAME_LEN, "POLL");
  44. snprintf(state->desc, CPUIDLE_DESC_LEN, "CPUIDLE CORE POLL IDLE");
  45. state->exit_latency = 0;
  46. state->target_residency = 0;
  47. state->exit_latency_ns = 0;
  48. state->target_residency_ns = 0;
  49. state->power_usage = -1;
  50. state->enter = poll_idle;
  51. state->flags = CPUIDLE_FLAG_POLLING;
  52. }
  53. EXPORT_SYMBOL_GPL(cpuidle_poll_state_init);