summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/acpi/processor_idle.c17
-rw-r--r--drivers/cpuidle/Makefile1
-rw-r--r--drivers/cpuidle/driver.c32
-rw-r--r--drivers/cpuidle/dt_idle_states.c20
-rw-r--r--drivers/cpuidle/governors/ladder.c14
-rw-r--r--drivers/cpuidle/governors/menu.c13
-rw-r--r--drivers/cpuidle/poll_state.c37
-rw-r--r--drivers/idle/intel_idle.c1
-rw-r--r--include/linux/cpuidle.h13
9 files changed, 82 insertions, 66 deletions
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
index 5c8aa9cf62d7..df38e81cc672 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -48,6 +48,8 @@
48#define _COMPONENT ACPI_PROCESSOR_COMPONENT 48#define _COMPONENT ACPI_PROCESSOR_COMPONENT
49ACPI_MODULE_NAME("processor_idle"); 49ACPI_MODULE_NAME("processor_idle");
50 50
51#define ACPI_IDLE_STATE_START (IS_ENABLED(CONFIG_ARCH_HAS_CPU_RELAX) ? 1 : 0)
52
51static unsigned int max_cstate __read_mostly = ACPI_PROCESSOR_MAX_POWER; 53static unsigned int max_cstate __read_mostly = ACPI_PROCESSOR_MAX_POWER;
52module_param(max_cstate, uint, 0000); 54module_param(max_cstate, uint, 0000);
53static unsigned int nocst __read_mostly; 55static unsigned int nocst __read_mostly;
@@ -761,7 +763,7 @@ static int acpi_idle_enter(struct cpuidle_device *dev,
761 763
762 if (cx->type != ACPI_STATE_C1) { 764 if (cx->type != ACPI_STATE_C1) {
763 if (acpi_idle_fallback_to_c1(pr) && num_online_cpus() > 1) { 765 if (acpi_idle_fallback_to_c1(pr) && num_online_cpus() > 1) {
764 index = CPUIDLE_DRIVER_STATE_START; 766 index = ACPI_IDLE_STATE_START;
765 cx = per_cpu(acpi_cstate[index], dev->cpu); 767 cx = per_cpu(acpi_cstate[index], dev->cpu);
766 } else if (cx->type == ACPI_STATE_C3 && pr->flags.bm_check) { 768 } else if (cx->type == ACPI_STATE_C3 && pr->flags.bm_check) {
767 if (cx->bm_sts_skip || !acpi_idle_bm_check()) { 769 if (cx->bm_sts_skip || !acpi_idle_bm_check()) {
@@ -813,7 +815,7 @@ static void acpi_idle_enter_freeze(struct cpuidle_device *dev,
813static int acpi_processor_setup_cpuidle_cx(struct acpi_processor *pr, 815static int acpi_processor_setup_cpuidle_cx(struct acpi_processor *pr,
814 struct cpuidle_device *dev) 816 struct cpuidle_device *dev)
815{ 817{
816 int i, count = CPUIDLE_DRIVER_STATE_START; 818 int i, count = ACPI_IDLE_STATE_START;
817 struct acpi_processor_cx *cx; 819 struct acpi_processor_cx *cx;
818 820
819 if (max_cstate == 0) 821 if (max_cstate == 0)
@@ -840,7 +842,7 @@ static int acpi_processor_setup_cpuidle_cx(struct acpi_processor *pr,
840 842
841static int acpi_processor_setup_cstates(struct acpi_processor *pr) 843static int acpi_processor_setup_cstates(struct acpi_processor *pr)
842{ 844{
843 int i, count = CPUIDLE_DRIVER_STATE_START; 845 int i, count;
844 struct acpi_processor_cx *cx; 846 struct acpi_processor_cx *cx;
845 struct cpuidle_state *state; 847 struct cpuidle_state *state;
846 struct cpuidle_driver *drv = &acpi_idle_driver; 848 struct cpuidle_driver *drv = &acpi_idle_driver;
@@ -848,6 +850,13 @@ static int acpi_processor_setup_cstates(struct acpi_processor *pr)
848 if (max_cstate == 0) 850 if (max_cstate == 0)
849 max_cstate = 1; 851 max_cstate = 1;
850 852
853 if (IS_ENABLED(CONFIG_ARCH_HAS_CPU_RELAX)) {
854 cpuidle_poll_state_init(drv);
855 count = 1;
856 } else {
857 count = 0;
858 }
859
851 for (i = 1; i < ACPI_PROCESSOR_MAX_POWER && i <= max_cstate; i++) { 860 for (i = 1; i < ACPI_PROCESSOR_MAX_POWER && i <= max_cstate; i++) {
852 cx = &pr->power.states[i]; 861 cx = &pr->power.states[i];
853 862
@@ -1291,7 +1300,7 @@ static int acpi_processor_setup_cpuidle_states(struct acpi_processor *pr)
1291 return -EINVAL; 1300 return -EINVAL;
1292 1301
1293 drv->safe_state_index = -1; 1302 drv->safe_state_index = -1;
1294 for (i = CPUIDLE_DRIVER_STATE_START; i < CPUIDLE_STATE_MAX; i++) { 1303 for (i = ACPI_IDLE_STATE_START; i < CPUIDLE_STATE_MAX; i++) {
1295 drv->states[i].name[0] = '\0'; 1304 drv->states[i].name[0] = '\0';
1296 drv->states[i].desc[0] = '\0'; 1305 drv->states[i].desc[0] = '\0';
1297 } 1306 }
diff --git a/drivers/cpuidle/Makefile b/drivers/cpuidle/Makefile
index 3ba81b1dffad..0b67a05a7aae 100644
--- a/drivers/cpuidle/Makefile
+++ b/drivers/cpuidle/Makefile
@@ -5,6 +5,7 @@
5obj-y += cpuidle.o driver.o governor.o sysfs.o governors/ 5obj-y += cpuidle.o driver.o governor.o sysfs.o governors/
6obj-$(CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED) += coupled.o 6obj-$(CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED) += coupled.o
7obj-$(CONFIG_DT_IDLE_STATES) += dt_idle_states.o 7obj-$(CONFIG_DT_IDLE_STATES) += dt_idle_states.o
8obj-$(CONFIG_ARCH_HAS_CPU_RELAX) += poll_state.o
8 9
9################################################################################## 10##################################################################################
10# ARM SoC drivers 11# ARM SoC drivers
diff --git a/drivers/cpuidle/driver.c b/drivers/cpuidle/driver.c
index e53fb861beb0..dc32f34e68d9 100644
--- a/drivers/cpuidle/driver.c
+++ b/drivers/cpuidle/driver.c
@@ -179,36 +179,6 @@ static void __cpuidle_driver_init(struct cpuidle_driver *drv)
179 } 179 }
180} 180}
181 181
182#ifdef CONFIG_ARCH_HAS_CPU_RELAX
183static int __cpuidle poll_idle(struct cpuidle_device *dev,
184 struct cpuidle_driver *drv, int index)
185{
186 local_irq_enable();
187 if (!current_set_polling_and_test()) {
188 while (!need_resched())
189 cpu_relax();
190 }
191 current_clr_polling();
192
193 return index;
194}
195
196static void poll_idle_init(struct cpuidle_driver *drv)
197{
198 struct cpuidle_state *state = &drv->states[0];
199
200 snprintf(state->name, CPUIDLE_NAME_LEN, "POLL");
201 snprintf(state->desc, CPUIDLE_DESC_LEN, "CPUIDLE CORE POLL IDLE");
202 state->exit_latency = 0;
203 state->target_residency = 0;
204 state->power_usage = -1;
205 state->enter = poll_idle;
206 state->disabled = false;
207}
208#else
209static void poll_idle_init(struct cpuidle_driver *drv) {}
210#endif /* !CONFIG_ARCH_HAS_CPU_RELAX */
211
212/** 182/**
213 * __cpuidle_register_driver: register the driver 183 * __cpuidle_register_driver: register the driver
214 * @drv: a valid pointer to a struct cpuidle_driver 184 * @drv: a valid pointer to a struct cpuidle_driver
@@ -246,8 +216,6 @@ static int __cpuidle_register_driver(struct cpuidle_driver *drv)
246 on_each_cpu_mask(drv->cpumask, cpuidle_setup_broadcast_timer, 216 on_each_cpu_mask(drv->cpumask, cpuidle_setup_broadcast_timer,
247 (void *)1, 1); 217 (void *)1, 1);
248 218
249 poll_idle_init(drv);
250
251 return 0; 219 return 0;
252} 220}
253 221
diff --git a/drivers/cpuidle/dt_idle_states.c b/drivers/cpuidle/dt_idle_states.c
index ae8eb0359889..bafd4dbf55d4 100644
--- a/drivers/cpuidle/dt_idle_states.c
+++ b/drivers/cpuidle/dt_idle_states.c
@@ -53,16 +53,16 @@ static int init_state_node(struct cpuidle_state *idle_state,
53 err = of_property_read_u32(state_node, "entry-latency-us", 53 err = of_property_read_u32(state_node, "entry-latency-us",
54 &entry_latency); 54 &entry_latency);
55 if (err) { 55 if (err) {
56 pr_debug(" * %s missing entry-latency-us property\n", 56 pr_debug(" * %pOF missing entry-latency-us property\n",
57 state_node->full_name); 57 state_node);
58 return -EINVAL; 58 return -EINVAL;
59 } 59 }
60 60
61 err = of_property_read_u32(state_node, "exit-latency-us", 61 err = of_property_read_u32(state_node, "exit-latency-us",
62 &exit_latency); 62 &exit_latency);
63 if (err) { 63 if (err) {
64 pr_debug(" * %s missing exit-latency-us property\n", 64 pr_debug(" * %pOF missing exit-latency-us property\n",
65 state_node->full_name); 65 state_node);
66 return -EINVAL; 66 return -EINVAL;
67 } 67 }
68 /* 68 /*
@@ -75,8 +75,8 @@ static int init_state_node(struct cpuidle_state *idle_state,
75 err = of_property_read_u32(state_node, "min-residency-us", 75 err = of_property_read_u32(state_node, "min-residency-us",
76 &idle_state->target_residency); 76 &idle_state->target_residency);
77 if (err) { 77 if (err) {
78 pr_debug(" * %s missing min-residency-us property\n", 78 pr_debug(" * %pOF missing min-residency-us property\n",
79 state_node->full_name); 79 state_node);
80 return -EINVAL; 80 return -EINVAL;
81 } 81 }
82 82
@@ -186,8 +186,8 @@ int dt_init_idle_driver(struct cpuidle_driver *drv,
186 } 186 }
187 187
188 if (!idle_state_valid(state_node, i, cpumask)) { 188 if (!idle_state_valid(state_node, i, cpumask)) {
189 pr_warn("%s idle state not valid, bailing out\n", 189 pr_warn("%pOF idle state not valid, bailing out\n",
190 state_node->full_name); 190 state_node);
191 err = -EINVAL; 191 err = -EINVAL;
192 break; 192 break;
193 } 193 }
@@ -200,8 +200,8 @@ int dt_init_idle_driver(struct cpuidle_driver *drv,
200 idle_state = &drv->states[state_idx++]; 200 idle_state = &drv->states[state_idx++];
201 err = init_state_node(idle_state, matches, state_node); 201 err = init_state_node(idle_state, matches, state_node);
202 if (err) { 202 if (err) {
203 pr_err("Parsing idle state node %s failed with err %d\n", 203 pr_err("Parsing idle state node %pOF failed with err %d\n",
204 state_node->full_name, err); 204 state_node, err);
205 err = -EINVAL; 205 err = -EINVAL;
206 break; 206 break;
207 } 207 }
diff --git a/drivers/cpuidle/governors/ladder.c b/drivers/cpuidle/governors/ladder.c
index ac321f09e717..ce1a2ffffb2a 100644
--- a/drivers/cpuidle/governors/ladder.c
+++ b/drivers/cpuidle/governors/ladder.c
@@ -69,6 +69,7 @@ static int ladder_select_state(struct cpuidle_driver *drv,
69 struct ladder_device *ldev = this_cpu_ptr(&ladder_devices); 69 struct ladder_device *ldev = this_cpu_ptr(&ladder_devices);
70 struct ladder_device_state *last_state; 70 struct ladder_device_state *last_state;
71 int last_residency, last_idx = ldev->last_state_idx; 71 int last_residency, last_idx = ldev->last_state_idx;
72 int first_idx = drv->states[0].flags & CPUIDLE_FLAG_POLLING ? 1 : 0;
72 int latency_req = pm_qos_request(PM_QOS_CPU_DMA_LATENCY); 73 int latency_req = pm_qos_request(PM_QOS_CPU_DMA_LATENCY);
73 74
74 /* Special case when user has set very strict latency requirement */ 75 /* Special case when user has set very strict latency requirement */
@@ -96,13 +97,13 @@ static int ladder_select_state(struct cpuidle_driver *drv,
96 } 97 }
97 98
98 /* consider demotion */ 99 /* consider demotion */
99 if (last_idx > CPUIDLE_DRIVER_STATE_START && 100 if (last_idx > first_idx &&
100 (drv->states[last_idx].disabled || 101 (drv->states[last_idx].disabled ||
101 dev->states_usage[last_idx].disable || 102 dev->states_usage[last_idx].disable ||
102 drv->states[last_idx].exit_latency > latency_req)) { 103 drv->states[last_idx].exit_latency > latency_req)) {
103 int i; 104 int i;
104 105
105 for (i = last_idx - 1; i > CPUIDLE_DRIVER_STATE_START; i--) { 106 for (i = last_idx - 1; i > first_idx; i--) {
106 if (drv->states[i].exit_latency <= latency_req) 107 if (drv->states[i].exit_latency <= latency_req)
107 break; 108 break;
108 } 109 }
@@ -110,7 +111,7 @@ static int ladder_select_state(struct cpuidle_driver *drv,
110 return i; 111 return i;
111 } 112 }
112 113
113 if (last_idx > CPUIDLE_DRIVER_STATE_START && 114 if (last_idx > first_idx &&
114 last_residency < last_state->threshold.demotion_time) { 115 last_residency < last_state->threshold.demotion_time) {
115 last_state->stats.demotion_count++; 116 last_state->stats.demotion_count++;
116 last_state->stats.promotion_count = 0; 117 last_state->stats.promotion_count = 0;
@@ -133,13 +134,14 @@ static int ladder_enable_device(struct cpuidle_driver *drv,
133 struct cpuidle_device *dev) 134 struct cpuidle_device *dev)
134{ 135{
135 int i; 136 int i;
137 int first_idx = drv->states[0].flags & CPUIDLE_FLAG_POLLING ? 1 : 0;
136 struct ladder_device *ldev = &per_cpu(ladder_devices, dev->cpu); 138 struct ladder_device *ldev = &per_cpu(ladder_devices, dev->cpu);
137 struct ladder_device_state *lstate; 139 struct ladder_device_state *lstate;
138 struct cpuidle_state *state; 140 struct cpuidle_state *state;
139 141
140 ldev->last_state_idx = CPUIDLE_DRIVER_STATE_START; 142 ldev->last_state_idx = first_idx;
141 143
142 for (i = CPUIDLE_DRIVER_STATE_START; i < drv->state_count; i++) { 144 for (i = first_idx; i < drv->state_count; i++) {
143 state = &drv->states[i]; 145 state = &drv->states[i];
144 lstate = &ldev->states[i]; 146 lstate = &ldev->states[i];
145 147
@@ -151,7 +153,7 @@ static int ladder_enable_device(struct cpuidle_driver *drv,
151 153
152 if (i < drv->state_count - 1) 154 if (i < drv->state_count - 1)
153 lstate->threshold.promotion_time = state->exit_latency; 155 lstate->threshold.promotion_time = state->exit_latency;
154 if (i > CPUIDLE_DRIVER_STATE_START) 156 if (i > first_idx)
155 lstate->threshold.demotion_time = state->exit_latency; 157 lstate->threshold.demotion_time = state->exit_latency;
156 } 158 }
157 159
diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c
index 61b64c2b2cb8..48eaf2879228 100644
--- a/drivers/cpuidle/governors/menu.c
+++ b/drivers/cpuidle/governors/menu.c
@@ -324,8 +324,9 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev)
324 expected_interval = get_typical_interval(data); 324 expected_interval = get_typical_interval(data);
325 expected_interval = min(expected_interval, data->next_timer_us); 325 expected_interval = min(expected_interval, data->next_timer_us);
326 326
327 if (CPUIDLE_DRIVER_STATE_START > 0) { 327 first_idx = 0;
328 struct cpuidle_state *s = &drv->states[CPUIDLE_DRIVER_STATE_START]; 328 if (drv->states[0].flags & CPUIDLE_FLAG_POLLING) {
329 struct cpuidle_state *s = &drv->states[1];
329 unsigned int polling_threshold; 330 unsigned int polling_threshold;
330 331
331 /* 332 /*
@@ -336,12 +337,8 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev)
336 polling_threshold = max_t(unsigned int, 20, s->target_residency); 337 polling_threshold = max_t(unsigned int, 20, s->target_residency);
337 if (data->next_timer_us > polling_threshold && 338 if (data->next_timer_us > polling_threshold &&
338 latency_req > s->exit_latency && !s->disabled && 339 latency_req > s->exit_latency && !s->disabled &&
339 !dev->states_usage[CPUIDLE_DRIVER_STATE_START].disable) 340 !dev->states_usage[1].disable)
340 first_idx = CPUIDLE_DRIVER_STATE_START; 341 first_idx = 1;
341 else
342 first_idx = CPUIDLE_DRIVER_STATE_START - 1;
343 } else {
344 first_idx = 0;
345 } 342 }
346 343
347 /* 344 /*
diff --git a/drivers/cpuidle/poll_state.c b/drivers/cpuidle/poll_state.c
new file mode 100644
index 000000000000..7416b16287de
--- /dev/null
+++ b/drivers/cpuidle/poll_state.c
@@ -0,0 +1,37 @@
1/*
2 * poll_state.c - Polling idle state
3 *
4 * This file is released under the GPLv2.
5 */
6
7#include <linux/cpuidle.h>
8#include <linux/sched.h>
9#include <linux/sched/idle.h>
10
11static int __cpuidle poll_idle(struct cpuidle_device *dev,
12 struct cpuidle_driver *drv, int index)
13{
14 local_irq_enable();
15 if (!current_set_polling_and_test()) {
16 while (!need_resched())
17 cpu_relax();
18 }
19 current_clr_polling();
20
21 return index;
22}
23
24void cpuidle_poll_state_init(struct cpuidle_driver *drv)
25{
26 struct cpuidle_state *state = &drv->states[0];
27
28 snprintf(state->name, CPUIDLE_NAME_LEN, "POLL");
29 snprintf(state->desc, CPUIDLE_DESC_LEN, "CPUIDLE CORE POLL IDLE");
30 state->exit_latency = 0;
31 state->target_residency = 0;
32 state->power_usage = -1;
33 state->enter = poll_idle;
34 state->disabled = false;
35 state->flags = CPUIDLE_FLAG_POLLING;
36}
37EXPORT_SYMBOL_GPL(cpuidle_poll_state_init);
diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c
index c2ae819a871c..7bf8739e33bc 100644
--- a/drivers/idle/intel_idle.c
+++ b/drivers/idle/intel_idle.c
@@ -1331,6 +1331,7 @@ static void __init intel_idle_cpuidle_driver_init(void)
1331 1331
1332 intel_idle_state_table_update(); 1332 intel_idle_state_table_update();
1333 1333
1334 cpuidle_poll_state_init(drv);
1334 drv->state_count = 1; 1335 drv->state_count = 1;
1335 1336
1336 for (cstate = 0; cstate < CPUIDLE_STATE_MAX; ++cstate) { 1337 for (cstate = 0; cstate < CPUIDLE_STATE_MAX; ++cstate) {
diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h
index fc1e5d7fc1c7..5baacd3a0559 100644
--- a/include/linux/cpuidle.h
+++ b/include/linux/cpuidle.h
@@ -63,6 +63,7 @@ struct cpuidle_state {
63 63
64/* Idle State Flags */ 64/* Idle State Flags */
65#define CPUIDLE_FLAG_NONE (0x00) 65#define CPUIDLE_FLAG_NONE (0x00)
66#define CPUIDLE_FLAG_POLLING (0x01) /* polling state */
66#define CPUIDLE_FLAG_COUPLED (0x02) /* state applies to multiple cpus */ 67#define CPUIDLE_FLAG_COUPLED (0x02) /* state applies to multiple cpus */
67#define CPUIDLE_FLAG_TIMER_STOP (0x04) /* timer is stopped on this state */ 68#define CPUIDLE_FLAG_TIMER_STOP (0x04) /* timer is stopped on this state */
68 69
@@ -224,6 +225,12 @@ static inline void cpuidle_coupled_parallel_barrier(struct cpuidle_device *dev,
224} 225}
225#endif 226#endif
226 227
228#ifdef CONFIG_ARCH_HAS_CPU_RELAX
229void cpuidle_poll_state_init(struct cpuidle_driver *drv);
230#else
231static inline void cpuidle_poll_state_init(struct cpuidle_driver *drv) {}
232#endif
233
227/****************************** 234/******************************
228 * CPUIDLE GOVERNOR INTERFACE * 235 * CPUIDLE GOVERNOR INTERFACE *
229 ******************************/ 236 ******************************/
@@ -250,12 +257,6 @@ static inline int cpuidle_register_governor(struct cpuidle_governor *gov)
250{return 0;} 257{return 0;}
251#endif 258#endif
252 259
253#ifdef CONFIG_ARCH_HAS_CPU_RELAX
254#define CPUIDLE_DRIVER_STATE_START 1
255#else
256#define CPUIDLE_DRIVER_STATE_START 0
257#endif
258
259#define CPU_PM_CPU_IDLE_ENTER(low_level_idle_enter, idx) \ 260#define CPU_PM_CPU_IDLE_ENTER(low_level_idle_enter, idx) \
260({ \ 261({ \
261 int __ret; \ 262 int __ret; \