static void __init fixup_cede0_latency()

in cpuidle-pseries.c [346:400]


static void __init fixup_cede0_latency(void)
{
	struct xcede_latency_payload *payload;
	u64 min_xcede_latency_us = UINT_MAX;
	int i;

	if (parse_cede_parameters())
		return;

	pr_info("cpuidle: Skipping the %d Extended CEDE idle states\n",
		nr_xcede_records);

	payload = &xcede_latency_parameter.payload;

	/*
	 * The CEDE idle state maps to CEDE(0). While the hypervisor
	 * does not advertise CEDE(0) exit latency values, it does
	 * advertise the latency values of the extended CEDE states.
	 * We use the lowest advertised exit latency value as a proxy
	 * for the exit latency of CEDE(0).
	 */
	for (i = 0; i < nr_xcede_records; i++) {
		struct xcede_latency_record *record = &payload->records[i];
		u8 hint = record->hint;
		u64 latency_tb = be64_to_cpu(record->latency_ticks);
		u64 latency_us = DIV_ROUND_UP_ULL(tb_to_ns(latency_tb), NSEC_PER_USEC);

		/*
		 * We expect the exit latency of an extended CEDE
		 * state to be non-zero, it to since it takes at least
		 * a few nanoseconds to wakeup the idle CPU and
		 * dispatch the virtual processor into the Linux
		 * Guest.
		 *
		 * So we consider only non-zero value for performing
		 * the fixup of CEDE(0) latency.
		 */
		if (latency_us == 0) {
			pr_warn("cpuidle: Skipping xcede record %d [hint=%d]. Exit latency = 0us\n",
				i, hint);
			continue;
		}

		if (latency_us < min_xcede_latency_us)
			min_xcede_latency_us = latency_us;
	}

	if (min_xcede_latency_us != UINT_MAX) {
		dedicated_states[1].exit_latency = min_xcede_latency_us;
		dedicated_states[1].target_residency = 10 * (min_xcede_latency_us);
		pr_info("cpuidle: Fixed up CEDE exit latency to %llu us\n",
			min_xcede_latency_us);
	}

}