forked from Minki/linux
Merge branch 'pm-cpuidle'
* pm-cpuidle: cpuidle: Make drivers initialize polling state cpuidle: Move polling state initialization code to separate file cpuidle: Eliminate the CPUIDLE_DRIVER_STATE_START symbol cpuidle: Convert to using %pOF instead of full_name
This commit is contained in:
commit
a1b5fd8fa2
@ -48,6 +48,8 @@
|
||||
#define _COMPONENT ACPI_PROCESSOR_COMPONENT
|
||||
ACPI_MODULE_NAME("processor_idle");
|
||||
|
||||
#define ACPI_IDLE_STATE_START (IS_ENABLED(CONFIG_ARCH_HAS_CPU_RELAX) ? 1 : 0)
|
||||
|
||||
static unsigned int max_cstate __read_mostly = ACPI_PROCESSOR_MAX_POWER;
|
||||
module_param(max_cstate, uint, 0000);
|
||||
static unsigned int nocst __read_mostly;
|
||||
@ -761,7 +763,7 @@ static int acpi_idle_enter(struct cpuidle_device *dev,
|
||||
|
||||
if (cx->type != ACPI_STATE_C1) {
|
||||
if (acpi_idle_fallback_to_c1(pr) && num_online_cpus() > 1) {
|
||||
index = CPUIDLE_DRIVER_STATE_START;
|
||||
index = ACPI_IDLE_STATE_START;
|
||||
cx = per_cpu(acpi_cstate[index], dev->cpu);
|
||||
} else if (cx->type == ACPI_STATE_C3 && pr->flags.bm_check) {
|
||||
if (cx->bm_sts_skip || !acpi_idle_bm_check()) {
|
||||
@ -813,7 +815,7 @@ static void acpi_idle_enter_freeze(struct cpuidle_device *dev,
|
||||
static int acpi_processor_setup_cpuidle_cx(struct acpi_processor *pr,
|
||||
struct cpuidle_device *dev)
|
||||
{
|
||||
int i, count = CPUIDLE_DRIVER_STATE_START;
|
||||
int i, count = ACPI_IDLE_STATE_START;
|
||||
struct acpi_processor_cx *cx;
|
||||
|
||||
if (max_cstate == 0)
|
||||
@ -840,7 +842,7 @@ static int acpi_processor_setup_cpuidle_cx(struct acpi_processor *pr,
|
||||
|
||||
static int acpi_processor_setup_cstates(struct acpi_processor *pr)
|
||||
{
|
||||
int i, count = CPUIDLE_DRIVER_STATE_START;
|
||||
int i, count;
|
||||
struct acpi_processor_cx *cx;
|
||||
struct cpuidle_state *state;
|
||||
struct cpuidle_driver *drv = &acpi_idle_driver;
|
||||
@ -848,6 +850,13 @@ static int acpi_processor_setup_cstates(struct acpi_processor *pr)
|
||||
if (max_cstate == 0)
|
||||
max_cstate = 1;
|
||||
|
||||
if (IS_ENABLED(CONFIG_ARCH_HAS_CPU_RELAX)) {
|
||||
cpuidle_poll_state_init(drv);
|
||||
count = 1;
|
||||
} else {
|
||||
count = 0;
|
||||
}
|
||||
|
||||
for (i = 1; i < ACPI_PROCESSOR_MAX_POWER && i <= max_cstate; i++) {
|
||||
cx = &pr->power.states[i];
|
||||
|
||||
@ -1291,7 +1300,7 @@ static int acpi_processor_setup_cpuidle_states(struct acpi_processor *pr)
|
||||
return -EINVAL;
|
||||
|
||||
drv->safe_state_index = -1;
|
||||
for (i = CPUIDLE_DRIVER_STATE_START; i < CPUIDLE_STATE_MAX; i++) {
|
||||
for (i = ACPI_IDLE_STATE_START; i < CPUIDLE_STATE_MAX; i++) {
|
||||
drv->states[i].name[0] = '\0';
|
||||
drv->states[i].desc[0] = '\0';
|
||||
}
|
||||
|
@ -5,6 +5,7 @@
|
||||
obj-y += cpuidle.o driver.o governor.o sysfs.o governors/
|
||||
obj-$(CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED) += coupled.o
|
||||
obj-$(CONFIG_DT_IDLE_STATES) += dt_idle_states.o
|
||||
obj-$(CONFIG_ARCH_HAS_CPU_RELAX) += poll_state.o
|
||||
|
||||
##################################################################################
|
||||
# ARM SoC drivers
|
||||
|
@ -179,36 +179,6 @@ static void __cpuidle_driver_init(struct cpuidle_driver *drv)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ARCH_HAS_CPU_RELAX
|
||||
static int __cpuidle poll_idle(struct cpuidle_device *dev,
|
||||
struct cpuidle_driver *drv, int index)
|
||||
{
|
||||
local_irq_enable();
|
||||
if (!current_set_polling_and_test()) {
|
||||
while (!need_resched())
|
||||
cpu_relax();
|
||||
}
|
||||
current_clr_polling();
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
static void poll_idle_init(struct cpuidle_driver *drv)
|
||||
{
|
||||
struct cpuidle_state *state = &drv->states[0];
|
||||
|
||||
snprintf(state->name, CPUIDLE_NAME_LEN, "POLL");
|
||||
snprintf(state->desc, CPUIDLE_DESC_LEN, "CPUIDLE CORE POLL IDLE");
|
||||
state->exit_latency = 0;
|
||||
state->target_residency = 0;
|
||||
state->power_usage = -1;
|
||||
state->enter = poll_idle;
|
||||
state->disabled = false;
|
||||
}
|
||||
#else
|
||||
static void poll_idle_init(struct cpuidle_driver *drv) {}
|
||||
#endif /* !CONFIG_ARCH_HAS_CPU_RELAX */
|
||||
|
||||
/**
|
||||
* __cpuidle_register_driver: register the driver
|
||||
* @drv: a valid pointer to a struct cpuidle_driver
|
||||
@ -246,8 +216,6 @@ static int __cpuidle_register_driver(struct cpuidle_driver *drv)
|
||||
on_each_cpu_mask(drv->cpumask, cpuidle_setup_broadcast_timer,
|
||||
(void *)1, 1);
|
||||
|
||||
poll_idle_init(drv);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -53,16 +53,16 @@ static int init_state_node(struct cpuidle_state *idle_state,
|
||||
err = of_property_read_u32(state_node, "entry-latency-us",
|
||||
&entry_latency);
|
||||
if (err) {
|
||||
pr_debug(" * %s missing entry-latency-us property\n",
|
||||
state_node->full_name);
|
||||
pr_debug(" * %pOF missing entry-latency-us property\n",
|
||||
state_node);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
err = of_property_read_u32(state_node, "exit-latency-us",
|
||||
&exit_latency);
|
||||
if (err) {
|
||||
pr_debug(" * %s missing exit-latency-us property\n",
|
||||
state_node->full_name);
|
||||
pr_debug(" * %pOF missing exit-latency-us property\n",
|
||||
state_node);
|
||||
return -EINVAL;
|
||||
}
|
||||
/*
|
||||
@ -75,8 +75,8 @@ static int init_state_node(struct cpuidle_state *idle_state,
|
||||
err = of_property_read_u32(state_node, "min-residency-us",
|
||||
&idle_state->target_residency);
|
||||
if (err) {
|
||||
pr_debug(" * %s missing min-residency-us property\n",
|
||||
state_node->full_name);
|
||||
pr_debug(" * %pOF missing min-residency-us property\n",
|
||||
state_node);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -186,8 +186,8 @@ int dt_init_idle_driver(struct cpuidle_driver *drv,
|
||||
}
|
||||
|
||||
if (!idle_state_valid(state_node, i, cpumask)) {
|
||||
pr_warn("%s idle state not valid, bailing out\n",
|
||||
state_node->full_name);
|
||||
pr_warn("%pOF idle state not valid, bailing out\n",
|
||||
state_node);
|
||||
err = -EINVAL;
|
||||
break;
|
||||
}
|
||||
@ -200,8 +200,8 @@ int dt_init_idle_driver(struct cpuidle_driver *drv,
|
||||
idle_state = &drv->states[state_idx++];
|
||||
err = init_state_node(idle_state, matches, state_node);
|
||||
if (err) {
|
||||
pr_err("Parsing idle state node %s failed with err %d\n",
|
||||
state_node->full_name, err);
|
||||
pr_err("Parsing idle state node %pOF failed with err %d\n",
|
||||
state_node, err);
|
||||
err = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
@ -69,6 +69,7 @@ static int ladder_select_state(struct cpuidle_driver *drv,
|
||||
struct ladder_device *ldev = this_cpu_ptr(&ladder_devices);
|
||||
struct ladder_device_state *last_state;
|
||||
int last_residency, last_idx = ldev->last_state_idx;
|
||||
int first_idx = drv->states[0].flags & CPUIDLE_FLAG_POLLING ? 1 : 0;
|
||||
int latency_req = pm_qos_request(PM_QOS_CPU_DMA_LATENCY);
|
||||
|
||||
/* Special case when user has set very strict latency requirement */
|
||||
@ -96,13 +97,13 @@ static int ladder_select_state(struct cpuidle_driver *drv,
|
||||
}
|
||||
|
||||
/* consider demotion */
|
||||
if (last_idx > CPUIDLE_DRIVER_STATE_START &&
|
||||
if (last_idx > first_idx &&
|
||||
(drv->states[last_idx].disabled ||
|
||||
dev->states_usage[last_idx].disable ||
|
||||
drv->states[last_idx].exit_latency > latency_req)) {
|
||||
int i;
|
||||
|
||||
for (i = last_idx - 1; i > CPUIDLE_DRIVER_STATE_START; i--) {
|
||||
for (i = last_idx - 1; i > first_idx; i--) {
|
||||
if (drv->states[i].exit_latency <= latency_req)
|
||||
break;
|
||||
}
|
||||
@ -110,7 +111,7 @@ static int ladder_select_state(struct cpuidle_driver *drv,
|
||||
return i;
|
||||
}
|
||||
|
||||
if (last_idx > CPUIDLE_DRIVER_STATE_START &&
|
||||
if (last_idx > first_idx &&
|
||||
last_residency < last_state->threshold.demotion_time) {
|
||||
last_state->stats.demotion_count++;
|
||||
last_state->stats.promotion_count = 0;
|
||||
@ -133,13 +134,14 @@ static int ladder_enable_device(struct cpuidle_driver *drv,
|
||||
struct cpuidle_device *dev)
|
||||
{
|
||||
int i;
|
||||
int first_idx = drv->states[0].flags & CPUIDLE_FLAG_POLLING ? 1 : 0;
|
||||
struct ladder_device *ldev = &per_cpu(ladder_devices, dev->cpu);
|
||||
struct ladder_device_state *lstate;
|
||||
struct cpuidle_state *state;
|
||||
|
||||
ldev->last_state_idx = CPUIDLE_DRIVER_STATE_START;
|
||||
ldev->last_state_idx = first_idx;
|
||||
|
||||
for (i = CPUIDLE_DRIVER_STATE_START; i < drv->state_count; i++) {
|
||||
for (i = first_idx; i < drv->state_count; i++) {
|
||||
state = &drv->states[i];
|
||||
lstate = &ldev->states[i];
|
||||
|
||||
@ -151,7 +153,7 @@ static int ladder_enable_device(struct cpuidle_driver *drv,
|
||||
|
||||
if (i < drv->state_count - 1)
|
||||
lstate->threshold.promotion_time = state->exit_latency;
|
||||
if (i > CPUIDLE_DRIVER_STATE_START)
|
||||
if (i > first_idx)
|
||||
lstate->threshold.demotion_time = state->exit_latency;
|
||||
}
|
||||
|
||||
|
@ -324,8 +324,9 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev)
|
||||
expected_interval = get_typical_interval(data);
|
||||
expected_interval = min(expected_interval, data->next_timer_us);
|
||||
|
||||
if (CPUIDLE_DRIVER_STATE_START > 0) {
|
||||
struct cpuidle_state *s = &drv->states[CPUIDLE_DRIVER_STATE_START];
|
||||
first_idx = 0;
|
||||
if (drv->states[0].flags & CPUIDLE_FLAG_POLLING) {
|
||||
struct cpuidle_state *s = &drv->states[1];
|
||||
unsigned int polling_threshold;
|
||||
|
||||
/*
|
||||
@ -336,12 +337,8 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev)
|
||||
polling_threshold = max_t(unsigned int, 20, s->target_residency);
|
||||
if (data->next_timer_us > polling_threshold &&
|
||||
latency_req > s->exit_latency && !s->disabled &&
|
||||
!dev->states_usage[CPUIDLE_DRIVER_STATE_START].disable)
|
||||
first_idx = CPUIDLE_DRIVER_STATE_START;
|
||||
else
|
||||
first_idx = CPUIDLE_DRIVER_STATE_START - 1;
|
||||
} else {
|
||||
first_idx = 0;
|
||||
!dev->states_usage[1].disable)
|
||||
first_idx = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
|
37
drivers/cpuidle/poll_state.c
Normal file
37
drivers/cpuidle/poll_state.c
Normal file
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* poll_state.c - Polling idle state
|
||||
*
|
||||
* This file is released under the GPLv2.
|
||||
*/
|
||||
|
||||
#include <linux/cpuidle.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/sched/idle.h>
|
||||
|
||||
static int __cpuidle poll_idle(struct cpuidle_device *dev,
|
||||
struct cpuidle_driver *drv, int index)
|
||||
{
|
||||
local_irq_enable();
|
||||
if (!current_set_polling_and_test()) {
|
||||
while (!need_resched())
|
||||
cpu_relax();
|
||||
}
|
||||
current_clr_polling();
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
void cpuidle_poll_state_init(struct cpuidle_driver *drv)
|
||||
{
|
||||
struct cpuidle_state *state = &drv->states[0];
|
||||
|
||||
snprintf(state->name, CPUIDLE_NAME_LEN, "POLL");
|
||||
snprintf(state->desc, CPUIDLE_DESC_LEN, "CPUIDLE CORE POLL IDLE");
|
||||
state->exit_latency = 0;
|
||||
state->target_residency = 0;
|
||||
state->power_usage = -1;
|
||||
state->enter = poll_idle;
|
||||
state->disabled = false;
|
||||
state->flags = CPUIDLE_FLAG_POLLING;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(cpuidle_poll_state_init);
|
@ -1331,6 +1331,7 @@ static void __init intel_idle_cpuidle_driver_init(void)
|
||||
|
||||
intel_idle_state_table_update();
|
||||
|
||||
cpuidle_poll_state_init(drv);
|
||||
drv->state_count = 1;
|
||||
|
||||
for (cstate = 0; cstate < CPUIDLE_STATE_MAX; ++cstate) {
|
||||
|
@ -63,6 +63,7 @@ struct cpuidle_state {
|
||||
|
||||
/* Idle State Flags */
|
||||
#define CPUIDLE_FLAG_NONE (0x00)
|
||||
#define CPUIDLE_FLAG_POLLING (0x01) /* polling state */
|
||||
#define CPUIDLE_FLAG_COUPLED (0x02) /* state applies to multiple cpus */
|
||||
#define CPUIDLE_FLAG_TIMER_STOP (0x04) /* timer is stopped on this state */
|
||||
|
||||
@ -224,6 +225,12 @@ static inline void cpuidle_coupled_parallel_barrier(struct cpuidle_device *dev,
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ARCH_HAS_CPU_RELAX
|
||||
void cpuidle_poll_state_init(struct cpuidle_driver *drv);
|
||||
#else
|
||||
static inline void cpuidle_poll_state_init(struct cpuidle_driver *drv) {}
|
||||
#endif
|
||||
|
||||
/******************************
|
||||
* CPUIDLE GOVERNOR INTERFACE *
|
||||
******************************/
|
||||
@ -250,12 +257,6 @@ static inline int cpuidle_register_governor(struct cpuidle_governor *gov)
|
||||
{return 0;}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ARCH_HAS_CPU_RELAX
|
||||
#define CPUIDLE_DRIVER_STATE_START 1
|
||||
#else
|
||||
#define CPUIDLE_DRIVER_STATE_START 0
|
||||
#endif
|
||||
|
||||
#define CPU_PM_CPU_IDLE_ENTER(low_level_idle_enter, idx) \
|
||||
({ \
|
||||
int __ret; \
|
||||
|
Loading…
Reference in New Issue
Block a user