Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

cpuidle: pseries: Fix CEDE latency conversion from tb to us

Commit d947fb4c965c ("cpuidle: pseries: Fixup exit latency for
CEDE(0)") sets the exit latency of CEDE(0) based on the latency values
of the Extended CEDE states advertised by the platform. The values
advertised by the platform are in timebase ticks. However the cpuidle
framework requires the latency values in microseconds.

If the tb-ticks value advertised by the platform correspond to a value
smaller than 1us, during the conversion from tb-ticks to microseconds,
in the current code, the result becomes zero. This is incorrect as it
puts a CEDE state on par with the snooze state.

This patch fixes this by rounding up the result obtained while
converting the latency value from tb-ticks to microseconds. It also
prints a warning in case we discover an extended-cede state with
wakeup latency to be 0. In such a case, ensure that CEDE(0) has a
non-zero wakeup latency.

Fixes: d947fb4c965c ("cpuidle: pseries: Fixup exit latency for CEDE(0)")
Signed-off-by: Gautham R. Shenoy <ego@linux.vnet.ibm.com>
Reviewed-by: Vaidyanathan Srinivasan <svaidy@linux.ibm.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/1599125247-28488-1-git-send-email-ego@linux.vnet.ibm.com

authored by

Gautham R. Shenoy and committed by
Michael Ellerman
1d3ee7df 437ef802

+11 -4
+11 -4
drivers/cpuidle/cpuidle-pseries.c
··· 361 361 for (i = 0; i < nr_xcede_records; i++) { 362 362 struct xcede_latency_record *record = &payload->records[i]; 363 363 u64 latency_tb = be64_to_cpu(record->latency_ticks); 364 - u64 latency_us = tb_to_ns(latency_tb) / NSEC_PER_USEC; 364 + u64 latency_us = DIV_ROUND_UP_ULL(tb_to_ns(latency_tb), NSEC_PER_USEC); 365 + 366 + if (latency_us == 0) 367 + pr_warn("cpuidle: xcede record %d has an unrealistic latency of 0us.\n", i); 365 368 366 369 if (latency_us < min_latency_us) 367 370 min_latency_us = latency_us; ··· 381 378 * Perform the fix-up. 382 379 */ 383 380 if (min_latency_us < dedicated_states[1].exit_latency) { 384 - u64 cede0_latency = min_latency_us - 1; 381 + /* 382 + * We set a minimum of 1us wakeup latency for cede0 to 383 + * distinguish it from snooze 384 + */ 385 + u64 cede0_latency = 1; 385 386 386 - if (cede0_latency <= 0) 387 - cede0_latency = min_latency_us; 387 + if (min_latency_us > cede0_latency) 388 + cede0_latency = min_latency_us - 1; 388 389 389 390 dedicated_states[1].exit_latency = cede0_latency; 390 391 dedicated_states[1].target_residency = 10 * (cede0_latency);