Loading drivers/cpuidle/governors/teo.c +59 −19 Original line number Diff line number Diff line Loading @@ -233,7 +233,7 @@ static int teo_select(struct cpuidle_driver *drv, struct cpuidle_device *dev, { struct teo_cpu *cpu_data = per_cpu_ptr(&teo_cpus, dev->cpu); int latency_req = cpuidle_governor_latency_req(dev->cpu); unsigned int duration_us, count; unsigned int duration_us, hits, misses, early_hits; int max_early_idx, constraint_idx, idx, i; ktime_t delta_tick; Loading @@ -247,7 +247,9 @@ static int teo_select(struct cpuidle_driver *drv, struct cpuidle_device *dev, cpu_data->sleep_length_ns = tick_nohz_get_sleep_length(&delta_tick); duration_us = ktime_to_us(cpu_data->sleep_length_ns); count = 0; hits = 0; misses = 0; early_hits = 0; max_early_idx = -1; constraint_idx = drv->state_count; idx = -1; Loading @@ -258,23 +260,61 @@ static int teo_select(struct cpuidle_driver *drv, struct cpuidle_device *dev, if (s->disabled || su->disable) { /* * If the "early hits" metric of a disabled state is * greater than the current maximum, it should be taken * into account, because it would be a mistake to select * a deeper state with lower "early hits" metric. The * index cannot be changed to point to it, however, so * just increase the max count alone and let the index * still point to a shallower idle state. * Ignore disabled states with target residencies beyond * the anticipated idle duration. */ if (max_early_idx >= 0 && count < cpu_data->states[i].early_hits) count = cpu_data->states[i].early_hits; if (s->target_residency > duration_us) continue; /* * This state is disabled, so the range of idle duration * values corresponding to it is covered by the current * candidate state, but still the "hits" and "misses" * metrics of the disabled state need to be used to * decide whether or not the state covering the range in * question is good enough. */ hits = cpu_data->states[i].hits; misses = cpu_data->states[i].misses; if (early_hits >= cpu_data->states[i].early_hits || idx < 0) continue; /* * If the current candidate state has been the one with * the maximum "early hits" metric so far, the "early * hits" metric of the disabled state replaces the * current "early hits" count to avoid selecting a * deeper state with lower "early hits" metric. */ if (max_early_idx == idx) { early_hits = cpu_data->states[i].early_hits; continue; } if (idx < 0) /* * The current candidate state is closer to the disabled * one than the current maximum "early hits" state, so * replace the latter with it, but in case the maximum * "early hits" state index has not been set so far, * check if the current candidate state is not too * shallow for that role. */ if (!(tick_nohz_tick_stopped() && drv->states[idx].target_residency < TICK_USEC)) { early_hits = cpu_data->states[i].early_hits; max_early_idx = idx; } continue; } if (idx < 0) { idx = i; /* first enabled state */ hits = cpu_data->states[i].hits; misses = cpu_data->states[i].misses; } if (s->target_residency > duration_us) break; Loading @@ -283,11 +323,13 @@ static int teo_select(struct cpuidle_driver *drv, struct cpuidle_device *dev, constraint_idx = i; idx = i; hits = cpu_data->states[i].hits; misses = cpu_data->states[i].misses; if (count < cpu_data->states[i].early_hits && if (early_hits < cpu_data->states[i].early_hits && !(tick_nohz_tick_stopped() && drv->states[i].target_residency < TICK_USEC)) { count = cpu_data->states[i].early_hits; early_hits = cpu_data->states[i].early_hits; max_early_idx = i; } } Loading @@ -300,8 +342,7 @@ static int teo_select(struct cpuidle_driver *drv, struct cpuidle_device *dev, * "early hits" metric, but if that cannot be determined, just use the * state selected so far. */ if (cpu_data->states[idx].hits <= cpu_data->states[idx].misses && max_early_idx >= 0) { if (hits <= misses && max_early_idx >= 0) { idx = max_early_idx; duration_us = drv->states[idx].target_residency; } Loading @@ -316,10 +357,9 @@ static int teo_select(struct cpuidle_driver *drv, struct cpuidle_device *dev, if (idx < 0) { idx = 0; /* No states enabled. Must use 0. */ } else if (idx > 0) { unsigned int count = 0; u64 sum = 0; count = 0; /* * Count and sum the most recent idle duration values less than * the current expected idle duration value. Loading Loading
drivers/cpuidle/governors/teo.c +59 −19 Original line number Diff line number Diff line Loading @@ -233,7 +233,7 @@ static int teo_select(struct cpuidle_driver *drv, struct cpuidle_device *dev, { struct teo_cpu *cpu_data = per_cpu_ptr(&teo_cpus, dev->cpu); int latency_req = cpuidle_governor_latency_req(dev->cpu); unsigned int duration_us, count; unsigned int duration_us, hits, misses, early_hits; int max_early_idx, constraint_idx, idx, i; ktime_t delta_tick; Loading @@ -247,7 +247,9 @@ static int teo_select(struct cpuidle_driver *drv, struct cpuidle_device *dev, cpu_data->sleep_length_ns = tick_nohz_get_sleep_length(&delta_tick); duration_us = ktime_to_us(cpu_data->sleep_length_ns); count = 0; hits = 0; misses = 0; early_hits = 0; max_early_idx = -1; constraint_idx = drv->state_count; idx = -1; Loading @@ -258,23 +260,61 @@ static int teo_select(struct cpuidle_driver *drv, struct cpuidle_device *dev, if (s->disabled || su->disable) { /* * If the "early hits" metric of a disabled state is * greater than the current maximum, it should be taken * into account, because it would be a mistake to select * a deeper state with lower "early hits" metric. The * index cannot be changed to point to it, however, so * just increase the max count alone and let the index * still point to a shallower idle state. * Ignore disabled states with target residencies beyond * the anticipated idle duration. */ if (max_early_idx >= 0 && count < cpu_data->states[i].early_hits) count = cpu_data->states[i].early_hits; if (s->target_residency > duration_us) continue; /* * This state is disabled, so the range of idle duration * values corresponding to it is covered by the current * candidate state, but still the "hits" and "misses" * metrics of the disabled state need to be used to * decide whether or not the state covering the range in * question is good enough. */ hits = cpu_data->states[i].hits; misses = cpu_data->states[i].misses; if (early_hits >= cpu_data->states[i].early_hits || idx < 0) continue; /* * If the current candidate state has been the one with * the maximum "early hits" metric so far, the "early * hits" metric of the disabled state replaces the * current "early hits" count to avoid selecting a * deeper state with lower "early hits" metric. */ if (max_early_idx == idx) { early_hits = cpu_data->states[i].early_hits; continue; } if (idx < 0) /* * The current candidate state is closer to the disabled * one than the current maximum "early hits" state, so * replace the latter with it, but in case the maximum * "early hits" state index has not been set so far, * check if the current candidate state is not too * shallow for that role. */ if (!(tick_nohz_tick_stopped() && drv->states[idx].target_residency < TICK_USEC)) { early_hits = cpu_data->states[i].early_hits; max_early_idx = idx; } continue; } if (idx < 0) { idx = i; /* first enabled state */ hits = cpu_data->states[i].hits; misses = cpu_data->states[i].misses; } if (s->target_residency > duration_us) break; Loading @@ -283,11 +323,13 @@ static int teo_select(struct cpuidle_driver *drv, struct cpuidle_device *dev, constraint_idx = i; idx = i; hits = cpu_data->states[i].hits; misses = cpu_data->states[i].misses; if (count < cpu_data->states[i].early_hits && if (early_hits < cpu_data->states[i].early_hits && !(tick_nohz_tick_stopped() && drv->states[i].target_residency < TICK_USEC)) { count = cpu_data->states[i].early_hits; early_hits = cpu_data->states[i].early_hits; max_early_idx = i; } } Loading @@ -300,8 +342,7 @@ static int teo_select(struct cpuidle_driver *drv, struct cpuidle_device *dev, * "early hits" metric, but if that cannot be determined, just use the * state selected so far. */ if (cpu_data->states[idx].hits <= cpu_data->states[idx].misses && max_early_idx >= 0) { if (hits <= misses && max_early_idx >= 0) { idx = max_early_idx; duration_us = drv->states[idx].target_residency; } Loading @@ -316,10 +357,9 @@ static int teo_select(struct cpuidle_driver *drv, struct cpuidle_device *dev, if (idx < 0) { idx = 0; /* No states enabled. Must use 0. */ } else if (idx > 0) { unsigned int count = 0; u64 sum = 0; count = 0; /* * Count and sum the most recent idle duration values less than * the current expected idle duration value. Loading