Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 25496cae authored by Thomas Renninger's avatar Thomas Renninger Committed by Len Brown
Browse files

ACPI: Only use IPI on known broken machines (AMD, Dothan/BaniasPentium M)



Use IPI for blacklisted CPUs, add parameter IPI vs LAPIC

Currently, Linux disables lapic timer for all machines with C2 and higher
C-state support.

According to Intel only specific Intel models (Banias/Dothan) are broken
in respect of not waking up from C2 with lapic.

However, I am not sure about the naming of the parameter and how it
could/should get integrated into the dyntick part
(CONFIG_GENERIC_CLOCKEVENTS). There, a more fine grained check (TSC
still running?, ..) is needed? Does this make sense (always use
CLOCK_EVT_NOTIFY_BROADCAST_ON, but use OFF if forced by use_ipi=0:
clockevents_notify(use_ipi ? CLOCK_EVT_NOTIFY_BROADCAST_ON :
CLOCK_EVT_NOTIFY_BROADCAST_OFF, &pr->id);

Signed-off-by: default avatarThomas Renninger <trenn@suse.de>
Signed-off-by: default avatarLen Brown <len.brown@intel.com>
parent db98e0b4
Loading
Loading
Loading
Loading
+29 −9
Original line number Diff line number Diff line
@@ -89,6 +89,12 @@ module_param(nocst, uint, 0000);
static unsigned int bm_history __read_mostly =
    (HZ >= 800 ? 0xFFFFFFFF : ((1U << (HZ / 25)) - 1));
module_param(bm_history, uint, 0644);

static unsigned use_ipi = 2;
module_param(use_ipi, uint, 0644);
MODULE_PARM_DESC(use_ipi, "IPI (vs. LAPIC) irqs for not waking up from C2/C3"
		 " machines. 0=apic, 1=ipi, 2=auto\n");

/* --------------------------------------------------------------------------
                                Power Management
   -------------------------------------------------------------------------- */
@@ -260,9 +266,8 @@ static void acpi_cstate_enter(struct acpi_processor_cx *cstate)

/*
 * Some BIOS implementations switch to C3 in the published C2 state.
 * This seems to be a common problem on AMD boxen, but other vendors
 * are affected too. We pick the most conservative approach: we assume
 * that the local APIC stops in both C2 and C3.
 * This seems to be a common problem on AMD boxen and Intel Dothan/Banias
 * Pentium M machines.
 */
static void acpi_timer_check_state(int state, struct acpi_processor *pr,
				   struct acpi_processor_cx *cx)
@@ -276,8 +281,17 @@ static void acpi_timer_check_state(int state, struct acpi_processor *pr,
	if (pwr->timer_broadcast_on_state < state)
		return;

	if (cx->type >= ACPI_STATE_C2)
	if (cx->type >= ACPI_STATE_C2) {
		if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD)
			pr->power.timer_broadcast_on_state = state;
		else if ((boot_cpu_data.x86_vendor == X86_VENDOR_INTEL &&
			  boot_cpu_data.x86 == 6) &&
			 (boot_cpu_data.x86_model == 13 ||
			  boot_cpu_data.x86_model == 9))
		{
			pr->power.timer_broadcast_on_state = state;
		}
	}
}

static void acpi_propagate_timer_broadcast(struct acpi_processor *pr)
@@ -292,10 +306,16 @@ static void acpi_propagate_timer_broadcast(struct acpi_processor *pr)
#else
	cpumask_t mask = cpumask_of_cpu(pr->id);

	if (use_ipi == 0)
		on_each_cpu(switch_APIC_timer_to_ipi, &mask, 1, 1);
	else if (use_ipi == 1)
		on_each_cpu(switch_ipi_to_APIC_timer, &mask, 1, 1);
	else {
		if (pr->power.timer_broadcast_on_state < INT_MAX)
			on_each_cpu(switch_APIC_timer_to_ipi, &mask, 1, 1);
		else
			on_each_cpu(switch_ipi_to_APIC_timer, &mask, 1, 1);
	}
#endif
}

@@ -1013,13 +1033,13 @@ static int acpi_processor_power_verify(struct acpi_processor *pr)

		case ACPI_STATE_C2:
			acpi_processor_power_verify_c2(cx);
			if (cx->valid)
			if (cx->valid && use_ipi != 0 && use_ipi != 1)
				acpi_timer_check_state(i, pr, cx);
			break;

		case ACPI_STATE_C3:
			acpi_processor_power_verify_c3(pr, cx);
			if (cx->valid)
			if (cx->valid && use_ipi != 0 && use_ipi != 1)
				acpi_timer_check_state(i, pr, cx);
			break;
		}