diff options
author | Preeti U Murthy <preeti@linux.vnet.ibm.com> | 2015-01-28 13:13:06 +0530 |
---|---|---|
committer | Stewart Smith <stewart@linux.vnet.ibm.com> | 2015-01-28 19:44:06 +1100 |
commit | 0d7b1161a5ac221372a6b3d515af0017f3ea51fc (patch) | |
tree | 76bd2a2e34d24ac258ebf5f31b475146febb42ff /hw/slw.c | |
parent | 959079e2ca18e00e7aff7febe1733bc76349dc5c (diff) | |
download | skiboot-0d7b1161a5ac221372a6b3d515af0017f3ea51fc.zip skiboot-0d7b1161a5ac221372a6b3d515af0017f3ea51fc.tar.gz skiboot-0d7b1161a5ac221372a6b3d515af0017f3ea51fc.tar.bz2 |
cpuidle: Add validated metrics for idle states
The idle states are characterized by latency and residency
numbers which determine the breakeven point for entry into them. The
latency is a measure of the exit overhead from the idle state and
residency is the minimum amount of time that a CPU must be predicted
to be idle so as to reap the powersavings from entering into that idle
state.
These numbers are made use of by the cpuidle governors in the kernel to
arrive at the appropriate idle state that a CPU must enter into when there is
no work to be done. Today the kernel uses the latency numbers given by the
firmware. To arrive at a value for residency, it uses a multiplier of 10 on
the latency number. The latency number coded in the firmware is inaccurate
as is the technique for calculating the residency. This patch codes in the
the measured latency numbers for the idle states. The residency numbers have
been arrived at experimentally after ensuring that the performance of latency
sensitive workloads do not regress while allowing deeper idle states to be
entered into during low load situations. The kernel is expected to use these
values for optimal power efficiency.
Signed-off-by: Preeti U Murthy <preeti@linux.vnet.ibm.com>
Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com>
Diffstat (limited to 'hw/slw.c')
-rw-r--r-- | hw/slw.c | 21 |
1 files changed, 18 insertions, 3 deletions
@@ -395,6 +395,7 @@ static bool idle_prepare_core(struct proc_chip *chip, struct cpu_thread *c) struct cpu_idle_states { char name[MAX_NAME_LEN]; u32 latency_ns; + u32 residency_ns; u32 flags; u64 pmicr; u64 pmicr_mask; @@ -427,7 +428,8 @@ struct cpu_idle_states { static struct cpu_idle_states power7_cpu_idle_states[] = { { /* nap */ .name = "nap", - .latency_ns = 1000, + .latency_ns = 4000, + .residency_ns = 100000, .flags = 0*IDLE_DEC_STOP \ | 0*IDLE_TB_STOP \ | 1*IDLE_LOSE_USER_CONTEXT \ @@ -444,7 +446,8 @@ static struct cpu_idle_states power7_cpu_idle_states[] = { static struct cpu_idle_states power8_cpu_idle_states[] = { { /* nap */ .name = "nap", - .latency_ns = 1000, + .latency_ns = 4000, + .residency_ns = 100000, .flags = 0*IDLE_DEC_STOP \ | 0*IDLE_TB_STOP \ | 1*IDLE_LOSE_USER_CONTEXT \ @@ -456,7 +459,8 @@ static struct cpu_idle_states power8_cpu_idle_states[] = { .pmicr_mask = 0 }, { /* fast sleep (with workaround) */ .name = "fastsleep_", - .latency_ns = 100000, + .latency_ns = 40000, + .residency_ns = 300000000, .flags = 1*IDLE_DEC_STOP \ | 1*IDLE_TB_STOP \ | 1*IDLE_LOSE_USER_CONTEXT \ @@ -470,6 +474,8 @@ static struct cpu_idle_states power8_cpu_idle_states[] = { { /* Winkle */ .name = "winkle", .latency_ns = 10000000, + .residency_ns = 1000000000, /* Placeholder only.Winkle is not used by + the cpuidle subsystem today */ .flags = 1*IDLE_DEC_STOP \ | 1*IDLE_TB_STOP \ | 1*IDLE_LOSE_USER_CONTEXT \ @@ -496,6 +502,7 @@ static void add_cpu_idle_state_properties(void) /* Buffers to hold idle state properties */ char *name_buf; u32 *latency_ns_buf; + u32 *residency_ns_buf; u32 *flags_buf; u64 *pmicr_buf; u64 *pmicr_mask_buf; @@ -571,6 +578,7 @@ static void add_cpu_idle_state_properties(void) /* Allocate memory to idle state property buffers. */ name_buf = (char *) malloc(nr_states * sizeof(char) * MAX_NAME_LEN); latency_ns_buf = (u32 *) malloc(nr_states * sizeof(u32)); + residency_ns_buf= (u32 *) malloc(nr_states * sizeof(u32)); flags_buf = (u32 *) malloc(nr_states * sizeof(u32)); pmicr_buf = (u64 *) malloc(nr_states * sizeof(u64)); pmicr_mask_buf = (u64 *) malloc(nr_states * sizeof(u64)); @@ -594,6 +602,9 @@ static void add_cpu_idle_state_properties(void) *latency_ns_buf = cpu_to_fdt32(states[i].latency_ns); latency_ns_buf++; + *residency_ns_buf = cpu_to_fdt32(states[i].residency_ns); + residency_ns_buf++; + *flags_buf = cpu_to_fdt32(states[i].flags); flags_buf++; @@ -612,6 +623,7 @@ static void add_cpu_idle_state_properties(void) /* Point buffer pointers back to beginning of the buffer */ name_buf -= name_buf_len; latency_ns_buf -= num_supported_idle_states; + residency_ns_buf -= num_supported_idle_states; flags_buf -= num_supported_idle_states; pmicr_buf -= num_supported_idle_states; pmicr_mask_buf -= num_supported_idle_states; @@ -621,6 +633,8 @@ static void add_cpu_idle_state_properties(void) name_buf_len* sizeof(char)); dt_add_property(power_mgt, "ibm,cpu-idle-state-latencies-ns", latency_ns_buf, num_supported_idle_states * sizeof(u32)); + dt_add_property(power_mgt, "ibm,cpu-idle-state-residency-ns", + residency_ns_buf, num_supported_idle_states * sizeof(u32)); dt_add_property(power_mgt, "ibm,cpu-idle-state-flags", flags_buf, num_supported_idle_states * sizeof(u32)); dt_add_property(power_mgt, "ibm,cpu-idle-state-pmicr", pmicr_buf, @@ -630,6 +644,7 @@ static void add_cpu_idle_state_properties(void) free(name_buf); free(latency_ns_buf); + free(residency_ns_buf); free(flags_buf); free(pmicr_buf); free(pmicr_mask_buf); |