From nobody Mon Jun 8 07:24:34 2026 Received: from layka.disroot.org (layka.disroot.org [178.21.23.139]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7EB1746AF35; Wed, 3 Jun 2026 12:01:37 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=178.21.23.139 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780488100; cv=none; b=b1HeTC5Kvycco4L2YjnQVuCCl1KyTC2Va5s41S7HYwMXYvckfWf3Q7llSD3phf/zKim2/L+ObeQxhjxAyrF+jHjKVmu64dnacmX0MKJNMM2wIOecd9m+GhGicL9TDW2PNp4Au0cnvI15jT8nmCE/TQsbuGMZmDw0/Qc5TcP5c+U= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780488100; c=relaxed/simple; bh=w53jTP55JGMEWudVbVJWcnW1SsDQrplJAM711/mWEP0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=qBlrGRc3hy6eBwl8S11v+N6px3oANNaoibZz815jdTboyyGOiS5t4VgT+H+W/NeMUoVpmCuJBAeolmXkri4BcTds+9NxR2en4rldBa0mFd10GAkC4zjDoU9dJ9NQU5u50zBTpwdp382QbLuyZ1smlCqDPZmfqxbV2qXletTpuVY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=disroot.org; spf=pass smtp.mailfrom=disroot.org; dkim=pass (2048-bit key) header.d=disroot.org header.i=@disroot.org header.b=g1c+1HSY; arc=none smtp.client-ip=178.21.23.139 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=disroot.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=disroot.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=disroot.org header.i=@disroot.org header.b="g1c+1HSY" Received: from mail01.disroot.lan (localhost [127.0.0.1]) by disroot.org (Postfix) with ESMTP id 4F39E27210; Wed, 3 Jun 2026 14:01:36 +0200 (CEST) X-Virus-Scanned: SPAM Filter at disroot.org Received: from layka.disroot.org ([127.0.0.1]) by localhost (disroot.org [127.0.0.1]) (amavis, port 10024) with ESMTP id hT91COlUxbpg; Wed, 3 Jun 2026 14:01:35 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=disroot.org; s=mail; t=1780488095; bh=w53jTP55JGMEWudVbVJWcnW1SsDQrplJAM711/mWEP0=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=g1c+1HSYKJ5wWqmC7aorW63EKblqgMd00f2wBiD2BinEDb7uSSwscfNHuaqfN9pWj TmZPGKteBuxBC9EFNbRXiQrUTPxthX9CYBK8Rv1Oy6EcsuRDQzmThO7wAQ84Dyg0QR IhgJGnh3Y6pC/CISPNJ2Bmn8Oc/XXE6dX0TNkm4DTcfl2pGH9l6v7GG0PV3bqIUXlM krDNHN6T8BGkg6fGN38UZJ7luWFUWocR66+nC4jFp6sYuuYFW1nzuzUduAiM+YmO3m Drx97NhBZ35FitD8T3YViC3zgXVk3xetleTuX/RVQdnJPF33NcsiyNBb2CJr2qljr3 jH8PPCjdq69kA== From: Marco Scardovi To: kprateek.nayak@amd.com Cc: linux-kernel@vger.kernel.org, linux-pm@vger.kernel.org, mario.limonciello@amd.com, perry.yuan@amd.com, rafael@kernel.org, ray.huang@amd.com, scardracs@disroot.org, stuartmeckle@gmail.com, viresh.kumar@linaro.org, wyes.karny@amd.com Subject: [PATCH v2 1/2] cpufreq/amd-pstate: Fix EPP initialization for shared memory systems Date: Wed, 3 Jun 2026 13:56:34 +0200 Message-ID: <20260603120121.25772-2-scardracs@disroot.org> In-Reply-To: <20260603120121.25772-1-scardracs@disroot.org> References: <4cb9459c-f471-478a-9670-58d898619f45@amd.com> <20260603120121.25772-1-scardracs@disroot.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" At CPU boot/initialization, the private cpudata structure is allocated via kzalloc, which means cpudata->cppc_req_cached is initialized to 0. This makes the default cached EPP value 0 (AMD_CPPC_EPP_PERFORMANCE). When initializing a system that defaults to performance EPP, the driver attempts to configure the EPP via shmem_set_epp(policy, 0). Because the requested EPP (0) matches the uninitialized cached value (0), the early return check (epp =3D=3D epp_cached) triggers, and the driver skips writing to the hardware. The cppc_set_epp_perf() helper is responsible for writing both the EPP register and the CPPC autonomous mode enable register (auto_sel). Skipping the EPP write on initialization due to the false cache hit consequently skips setting auto_sel to 1, leaving the CPU in non-autonomous mode. This prevents the hardware from boosting and leaves the CPU frequency stuck at the lowest non-linear frequency (1.7GHz). Fix this by introducing an `epp_hw_programmed` flag in struct amd_cpudata to track whether EPP has been configured on the hardware. Bypass the early return check in shmem_set_epp() if EPP has not yet been programmed on the hardware. Once EPP has been successfully programmed once, the cached EPP value becomes authoritative (representing driver intent rather than dynamic firmware state), allowing subsequent runtime mode transitions to use the cache guard optimization safely. Fixes: ffa5096a7c33 ("cpufreq: amd-pstate: implement Pstate EPP support for= the AMD processors") Link: https://bugzilla.kernel.org/show_bug.cgi?id=3D221473 Assisted-by: Antigravity:gemini-3.5-flash Signed-off-by: Marco Scardovi --- drivers/cpufreq/amd-pstate.c | 9 ++++++++- drivers/cpufreq/amd-pstate.h | 2 ++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/cpufreq/amd-pstate.c b/drivers/cpufreq/amd-pstate.c index 8d55e2be825b..e8057f3dfb1e 100644 --- a/drivers/cpufreq/amd-pstate.c +++ b/drivers/cpufreq/amd-pstate.c @@ -424,7 +424,13 @@ static int shmem_set_epp(struct cpufreq_policy *policy= , u8 epp) epp !=3D epp_cached); } =20 - if (epp =3D=3D epp_cached) + /* + * After the first successful programming, the cached EPP value + * becomes authoritative (representing driver intent rather than + * dynamic firmware state), allowing us to skip redundant hardware + * writes when the EPP value is unchanged. + */ + if (cpudata->epp_hw_programmed && epp =3D=3D epp_cached) return 0; =20 perf_ctrls.energy_perf =3D epp; @@ -434,6 +440,7 @@ static int shmem_set_epp(struct cpufreq_policy *policy,= u8 epp) return ret; } =20 + cpudata->epp_hw_programmed =3D true; value =3D READ_ONCE(cpudata->cppc_req_cached); FIELD_MODIFY(AMD_CPPC_EPP_PERF_MASK, &value, epp); WRITE_ONCE(cpudata->cppc_req_cached, value); diff --git a/drivers/cpufreq/amd-pstate.h b/drivers/cpufreq/amd-pstate.h index e4722e54387b..fc6cd4b873f6 100644 --- a/drivers/cpufreq/amd-pstate.h +++ b/drivers/cpufreq/amd-pstate.h @@ -128,6 +128,8 @@ struct amd_cpudata { u8 epp_default_dc; bool dynamic_epp; bool raw_epp; + /* Indicates that EPP has been successfully programmed at least once sinc= e boot. */ + bool epp_hw_programmed; struct notifier_block power_nb; =20 /* platform profile */ --=20 2.54.0 From nobody Mon Jun 8 07:24:34 2026 Received: from layka.disroot.org (layka.disroot.org [178.21.23.139]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 26CC846AEEA; Wed, 3 Jun 2026 12:01:38 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=178.21.23.139 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780488100; cv=none; b=S2pDQA7qUSts+hQdASCxeNSc29X5OdO3R5t9KQWWdXNjZlkjRrQxvRzH4emhGTnZQKNgOS1/zp+jSbOD4NNIV227uI3clzTUSejsqgn++xgPMKFgpLIX1fva/Zy49uI0Gv+yThuUB5S+zlZGqTtsE098zf6YBYB9NO78qnTum+A= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780488100; c=relaxed/simple; bh=wblGCJrCm/VgNeNEH8FYabjvGp1gDOUsjasETsshYbs=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=mpJTWxwiDe7Wwd6oub4Pl5Me1mKdZoudjUEOrJQz8SJgJXrU2EoYKVbjkPi1QpfmwfPxVedQl5Q/5zeFP4cgx/yl4JRua0PMm2ytPTZ9XCcQI4RNYx75uFzQHMDlEYvY2mq/8IThqed4EfV1jxvtAnbIuAKhQCbMhO/sZZTg7Wc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=disroot.org; spf=pass smtp.mailfrom=disroot.org; dkim=pass (2048-bit key) header.d=disroot.org header.i=@disroot.org header.b=WBj2Imz3; arc=none smtp.client-ip=178.21.23.139 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=disroot.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=disroot.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=disroot.org header.i=@disroot.org header.b="WBj2Imz3" Received: from mail01.disroot.lan (localhost [127.0.0.1]) by disroot.org (Postfix) with ESMTP id C048D27117; Wed, 3 Jun 2026 14:01:36 +0200 (CEST) X-Virus-Scanned: SPAM Filter at disroot.org Received: from layka.disroot.org ([127.0.0.1]) by localhost (disroot.org [127.0.0.1]) (amavis, port 10024) with ESMTP id fk7GTP6CTn4L; Wed, 3 Jun 2026 14:01:36 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=disroot.org; s=mail; t=1780488096; bh=wblGCJrCm/VgNeNEH8FYabjvGp1gDOUsjasETsshYbs=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=WBj2Imz3e/usopwYAbbMa4o6yTs+uG9aqDzmD+u1M3nk+JTxvBnvFYCakNx81as/m iyn1KVANe+/1Rw/1WpuuRlBU7eYtkP3/24Mk3PzcxgXCl7/vQZTLiTDBnoWKNNqilb xHXW83AHyU0pn4kN/6ZmL/ns3DNHSExqm0Zns/IxCUJ/PvTsYLfbLBfWALYevA+Bsz AQfrob2MRpxoGqZhJU3WVIbJgjwfEBNcn5vwXU+4sqnLKj2VB7+BuJiM2Ms/jeYISE +r1/KsFPEMqvrHj+UjZIVm0SlyNEE56Xslt+OCsJrQDY0BqK5Ex4qNB5qwoDqiWPdo mbPpDzfURpjjQ== From: Marco Scardovi To: kprateek.nayak@amd.com Cc: linux-kernel@vger.kernel.org, linux-pm@vger.kernel.org, mario.limonciello@amd.com, perry.yuan@amd.com, rafael@kernel.org, ray.huang@amd.com, scardracs@disroot.org, stuartmeckle@gmail.com, viresh.kumar@linaro.org, wyes.karny@amd.com Subject: [PATCH v2 2/2] cpufreq/amd-pstate: Prevent active mode on systems without EPP support Date: Wed, 3 Jun 2026 13:56:35 +0200 Message-ID: <20260603120121.25772-3-scardracs@disroot.org> In-Reply-To: <20260603120121.25772-1-scardracs@disroot.org> References: <4cb9459c-f471-478a-9670-58d898619f45@amd.com> <20260603120121.25772-1-scardracs@disroot.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Some AMD processors or firmware configurations do not support Collaborative Processor Performance Control (CPPC) Energy Performance Preference (EPP). When loading the amd-pstate driver in EPP-reliant "active" mode on these systems, the driver fails to function correctly. Unconditionally probe EPP support during driver initialization via a new amd_pstate_epp_supported() helper, which queries cppc_get_epp_perf() on the first online CPU. EPP capability is uniform across all CPUs on x86, making a single CPU query sufficient. Treat EPP support as a tri-state during probing: - Success: EPP is supported. - -EOPNOTSUPP: EPP is definitively unsupported. - Unknown error: Warn about the unexpected failure, but default to assuming EPP is supported to avoid false negatives. Cache the capability in a static global `epp_supported` boolean to avoid redundant capability checks during runtime mode switches. If EPP is unsupported: - Fall back to passive mode at boot to keep the driver functional rather than failing to load entirely. - Reject runtime switches to active mode via sysfs with -ENODEV and print a warning. Fixes: ffa5096a7c33 ("cpufreq: amd-pstate: implement Pstate EPP support for= the AMD processors") Link: https://bugzilla.kernel.org/show_bug.cgi?id=3D221473 Assisted-by: Antigravity:gemini-3.5-flash Signed-off-by: Marco Scardovi --- drivers/cpufreq/amd-pstate.c | 44 ++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/drivers/cpufreq/amd-pstate.c b/drivers/cpufreq/amd-pstate.c index e8057f3dfb1e..cd052880ecb3 100644 --- a/drivers/cpufreq/amd-pstate.c +++ b/drivers/cpufreq/amd-pstate.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -88,6 +89,8 @@ static struct cpufreq_driver amd_pstate_epp_driver; static int cppc_state =3D AMD_PSTATE_UNDEFINED; static bool amd_pstate_prefcore =3D true; static bool dynamic_epp; +/* EPP support capability cached for driver mode switches. */ +static bool epp_supported; static struct quirk_entry *quirks; =20 /* @@ -1772,6 +1775,11 @@ int amd_pstate_update_status(const char *buf, size_t= size) if (mode_idx < 0) return mode_idx; =20 + if (mode_idx =3D=3D AMD_PSTATE_ACTIVE && !epp_supported) { + pr_warn("EPP is not supported by this processor, active mode rejected\n"= ); + return -ENODEV; + } + if (mode_state_machine[cppc_state][mode_idx]) { guard(mutex)(&amd_pstate_driver_lock); return mode_state_machine[cppc_state][mode_idx](mode_idx); @@ -2229,6 +2237,36 @@ static bool amd_cppc_supported(void) return true; } =20 +static bool amd_pstate_epp_supported(void) +{ + unsigned int cpu =3D cpumask_first(cpu_online_mask); + u64 epp; + int ret; + + /* + * On symmetric x86 systems, CPPC EPP support is uniform across all + * CPUs. Probing the first online CPU is sufficient to determine + * system-wide capability. + */ + ret =3D cppc_get_epp_perf(cpu, &epp); + if (!ret) + return true; + + /* + * We treat EPP support as a tri-state: + * - Success (0): EPP is supported. + * - Unsupported (-EOPNOTSUPP): EPP is definitively unsupported. + * - Unknown error (others): Warn about the unexpected failure, but + * default to assuming support to avoid false negatives (this may + * be revisited if transient errors cause driver instability). + */ + if (ret =3D=3D -EOPNOTSUPP) + return false; + + pr_warn("Unable to determine EPP capability: %d\n", ret); + return true; +} + static int __init amd_pstate_init(void) { struct device *dev_root; @@ -2251,6 +2289,12 @@ static int __init amd_pstate_init(void) if (cpufreq_get_current_driver()) return -EEXIST; =20 + epp_supported =3D amd_pstate_epp_supported(); + if (cppc_state =3D=3D AMD_PSTATE_ACTIVE && !epp_supported) { + pr_warn("EPP not supported, falling back to passive mode\n"); + cppc_state =3D AMD_PSTATE_PASSIVE; + } + quirks =3D NULL; =20 /* check if this machine need CPPC quirks */ --=20 2.54.0