From nobody Sun Mar 22 02:35:44 2026 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4fdgQZ32sWz6VlPn for ; Sun, 22 Mar 2026 02:35:50 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R12" (not verified)) by mx1.freebsd.org (Postfix) with ESMTPS id 4fdgQZ1Tfdz42vp for ; Sun, 22 Mar 2026 02:35:50 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1774146950; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=4f+Evu+KTKFJoxuXBrHpDt40rR+GayYt62hHKtOUJNk=; b=NWBDoadKiWcZm8FQDfwYpooQGWn+WNmMzWvfCwX9yoeRXEPZL5jTFL1/iHtX3liJTfuhSj ZG3SfFOOvrowZJ+dVSTf1r1coZDmgVrDSSLg0ZJu6s+voWLLtqsoJ2nIuo27hXg5gBy/nP S31Fzyob7P/pPjAWJrY4ceORROMcALiSQrlN5a4Q/CRU13wne6f6H35HRH1BJJFP1T8K+M i7XJfQFH0YeYxJkSYEG4aSJmF2IiU0G4WDCbeOoHVWX/6ut4MId4DbX58zL2WAuFdMH1jY maHONeziZ0NKvNd7tEonl79wSTgsJvKMyexJfcUHdPoWhcNQPnWtPbztUoGKOw== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1774146950; a=rsa-sha256; cv=none; b=UMuWPt6vDs02NTYklLkGdos+UN0lunMsKWXq5R2y0nwRuJeevA7v14Ej+sDb0JZ5M6xWkW OqYnkVbyePrDT6HHru9I8LIbIkrlnTCEmh5EWUx4rRnXOqfN5wUqeDQXcWMiYJUmGqn3Ca ddAXRyLzRarqXqqCIQW77ojewHLDeTzf93Yj6PACqfS9004mD7XZkt50dgcJLDpoNOv7lu hy/0ccyVUlqx2/XNjDboyLwOF5it+b2QiThjeG8pjRZDJVHWCoIzwpOKbdV+O7X+dYk6RI aI6XyUvY9DrOqHvOOiPzy3XXK0djU+B5ebFn4le0LjGMS3iIValcvUCV3+IDVQ== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1774146950; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=4f+Evu+KTKFJoxuXBrHpDt40rR+GayYt62hHKtOUJNk=; b=HFyi3nUWJ5H1oAetTADvuY4TXlXWaIxR8vur5qQhS70jCFoFFRi9ZxqdAa1HoSGxQCwIJ3 1bhMDDbBW/4O6kL87oQyredlV/ps/Kg2zvxX3ngfeAAakHuUqi3DWsx7Cs7S95z1ixi3oD yc8h1/DPSc3zgTD7vOW8sY+QpqfBHwAr9vWp/VKYyb9rRgetBFam3+8hhOycbAbdgdCrY2 UtsitjKgRLiMJCxZe7EDg8kFIa7bMsSPTD1nqQvnsddzt9K5/LM9O3ev658H3nMkYZSbjA 6Gaap3Z+JjoZpfDMm7A4yMQaNJPkpRpbeoyxvIs25c2FRUDME9Pm2HfOMKeE4g== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4fdgQY6mS2zgGL for ; Sun, 22 Mar 2026 02:35:49 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 462ae by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Sun, 22 Mar 2026 02:35:44 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: ShengYi Hung Subject: git: 191f47bcd650 - main - hwpstate_amd: Refactor the cpufreq code by using delegation pattenr List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-all@freebsd.org Sender: owner-dev-commits-src-all@FreeBSD.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: aokblast X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 191f47bcd65097599a962b46ae293e5ebe4e5b67 Auto-Submitted: auto-generated Date: Sun, 22 Mar 2026 02:35:44 +0000 Message-Id: <69bf5580.462ae.4b8ad64e@gitrepo.freebsd.org> The branch main has been updated by aokblast: URL: https://cgit.FreeBSD.org/src/commit/?id=191f47bcd65097599a962b46ae293e5ebe4e5b67 commit 191f47bcd65097599a962b46ae293e5ebe4e5b67 Author: ShengYi Hung AuthorDate: 2026-02-24 07:22:52 +0000 Commit: ShengYi Hung CommitDate: 2026-03-22 02:35:36 +0000 hwpstate_amd: Refactor the cpufreq code by using delegation pattenr We separate the code of CPPC and legacy pstate driver to make it easier to read. Reviewed by: olce Approved by: markj (mentor) Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D55604 --- sys/x86/cpufreq/hwpstate_amd.c | 213 +++++++++++++++++++++++++++-------------- 1 file changed, 142 insertions(+), 71 deletions(-) diff --git a/sys/x86/cpufreq/hwpstate_amd.c b/sys/x86/cpufreq/hwpstate_amd.c index 2649fcc5779f..ccf13f06a6d1 100644 --- a/sys/x86/cpufreq/hwpstate_amd.c +++ b/sys/x86/cpufreq/hwpstate_amd.c @@ -152,6 +152,13 @@ struct hwpstate_setting { #define HWPFL_USE_CPPC (1 << 0) #define HWPFL_CPPC_REQUEST_NOT_READ (1 << 1) +struct hwpstate_cpufreq_methods { + int (*get)(device_t dev, struct cf_setting *cf); + int (*set)(device_t dev, const struct cf_setting *cf); + int (*settings)(device_t dev, struct cf_setting *sets, int *count); + int (*type)(device_t dev, int *type); +}; + /* * Atomicity is achieved by only modifying a given softc on its associated CPU * and with interrupts disabled. @@ -161,6 +168,7 @@ struct hwpstate_setting { struct hwpstate_softc { device_t dev; u_int flags; + const struct hwpstate_cpufreq_methods *cpufreq_methods; union { struct { struct hwpstate_setting @@ -620,80 +628,105 @@ hwpstate_goto_pstate(device_t dev, int id) } static int -hwpstate_set(device_t dev, const struct cf_setting *cf) +hwpstate_set_cppc(device_t dev __unused, const struct cf_setting *cf __unused) +{ + return (EOPNOTSUPP); +} + +static int +hwpstate_set_pstate(device_t dev, const struct cf_setting *cf) { struct hwpstate_softc *sc; struct hwpstate_setting *set; int i; - if (cf == NULL) - return (EINVAL); sc = device_get_softc(dev); - if ((sc->flags & HWPFL_USE_CPPC) != 0) - return (EOPNOTSUPP); set = sc->hwpstate_settings; for (i = 0; i < sc->cfnum; i++) if (CPUFREQ_CMP(cf->freq, set[i].freq)) break; if (i == sc->cfnum) return (EINVAL); - return (hwpstate_goto_pstate(dev, set[i].pstate_id)); } static int -hwpstate_get(device_t dev, struct cf_setting *cf) +hwpstate_set(device_t dev, const struct cf_setting *cf) +{ + struct hwpstate_softc *sc = device_get_softc(dev); + + if (cf == NULL) + return (EINVAL); + return (sc->cpufreq_methods->set(dev, cf)); +} + +static int +hwpstate_get_cppc(device_t dev, struct cf_setting *cf) { - struct hwpstate_softc *sc; - struct hwpstate_setting set; struct pcpu *pc; - uint64_t msr; uint64_t rate; int ret; + pc = cpu_get_pcpu(dev); + if (pc == NULL) + return (ENXIO); + + memset(cf, CPUFREQ_VAL_UNKNOWN, sizeof(*cf)); + cf->dev = dev; + if ((ret = cpu_est_clockrate(pc->pc_cpuid, &rate))) + return (ret); + cf->freq = rate / 1000000; + return (0); +} + +static int +hwpstate_get_pstate(device_t dev, struct cf_setting *cf) +{ + struct hwpstate_softc *sc; + struct hwpstate_setting set; + uint64_t msr; + sc = device_get_softc(dev); - if (cf == NULL) + msr = rdmsr(MSR_AMD_10H_11H_STATUS); + if (msr >= sc->cfnum) return (EINVAL); + set = sc->hwpstate_settings[msr]; - if ((sc->flags & HWPFL_USE_CPPC) != 0) { - pc = cpu_get_pcpu(dev); - if (pc == NULL) - return (ENXIO); - - memset(cf, CPUFREQ_VAL_UNKNOWN, sizeof(*cf)); - cf->dev = dev; - if ((ret = cpu_est_clockrate(pc->pc_cpuid, &rate))) - return (ret); - cf->freq = rate / 1000000; - } else { - msr = rdmsr(MSR_AMD_10H_11H_STATUS); - if (msr >= sc->cfnum) - return (EINVAL); - set = sc->hwpstate_settings[msr]; - - cf->freq = set.freq; - cf->volts = set.volts; - cf->power = set.power; - cf->lat = set.lat; - cf->dev = dev; - } + cf->freq = set.freq; + cf->volts = set.volts; + cf->power = set.power; + cf->lat = set.lat; + cf->dev = dev; return (0); } static int -hwpstate_settings(device_t dev, struct cf_setting *sets, int *count) +hwpstate_get(device_t dev, struct cf_setting *cf) { struct hwpstate_softc *sc; + + sc = device_get_softc(dev); + if (cf == NULL) + return (EINVAL); + return (sc->cpufreq_methods->get(dev, cf)); +} + +static int +hwpstate_settings_cppc(device_t dev __unused, struct cf_setting *sets __unused, + int *count __unused) +{ + return (EOPNOTSUPP); +} + +static int +hwpstate_settings_pstate(device_t dev, struct cf_setting *sets, int *count) +{ struct hwpstate_setting set; + struct hwpstate_softc *sc; int i; - if (sets == NULL || count == NULL) - return (EINVAL); sc = device_get_softc(dev); - if ((sc->flags & HWPFL_USE_CPPC) != 0) - return (EOPNOTSUPP); - if (*count < sc->cfnum) return (E2BIG); for (i = 0; i < sc->cfnum; i++, sets++) { @@ -710,21 +743,40 @@ hwpstate_settings(device_t dev, struct cf_setting *sets, int *count) } static int -hwpstate_type(device_t dev, int *type) +hwpstate_settings(device_t dev, struct cf_setting *sets, int *count) { struct hwpstate_softc *sc; - if (type == NULL) + if (sets == NULL || count == NULL) return (EINVAL); sc = device_get_softc(dev); + return (sc->cpufreq_methods->settings(dev, sets, count)); +} +static int +hwpstate_type_cppc(device_t dev, int *type) +{ + *type |= CPUFREQ_TYPE_ABSOLUTE | CPUFREQ_FLAG_INFO_ONLY | + CPUFREQ_FLAG_UNCACHED; + return (0); +} + +static int +hwpstate_type_pstate(device_t dev, int *type) +{ *type = CPUFREQ_TYPE_ABSOLUTE; - *type |= (sc->flags & HWPFL_USE_CPPC) != 0 ? - CPUFREQ_FLAG_INFO_ONLY | CPUFREQ_FLAG_UNCACHED : - 0; return (0); } +static int +hwpstate_type(device_t dev, int *type) +{ + struct hwpstate_softc *sc; + + sc = device_get_softc(dev); + return (sc->cpufreq_methods->type(dev, type)); +} + static void hwpstate_identify(driver_t *driver, device_t parent) { @@ -909,34 +961,14 @@ enable_cppc(struct hwpstate_softc *sc) } static int -hwpstate_probe(device_t dev) +hwpstate_probe_pstate(device_t dev) { struct hwpstate_softc *sc; device_t perf_dev; - uint64_t msr; int error, type; + uint64_t msr; sc = device_get_softc(dev); - - if (hwpstate_amd_cppc_enable && - (amd_extended_feature_extensions & AMDFEID_CPPC)) { - sc->flags |= HWPFL_USE_CPPC; - device_set_desc(dev, - "AMD Collaborative Processor Performance Control (CPPC)"); - } else { - /* - * No CPPC support. Only keep hwpstate0, it goes well with - * acpi_throttle. - */ - if (device_get_unit(dev) != 0) - return (ENXIO); - device_set_desc(dev, "Cool`n'Quiet 2.0"); - } - - sc->dev = dev; - if ((sc->flags & HWPFL_USE_CPPC) != 0) - return (0); - /* * Check if acpi_perf has INFO only flag. */ @@ -984,10 +1016,49 @@ hwpstate_probe(device_t dev) */ if (error) error = hwpstate_get_info_from_msr(dev); - if (error) - return (error); + return (error); +} - return (0); +static const struct hwpstate_cpufreq_methods cppc_methods = { + .get = hwpstate_get_cppc, + .set = hwpstate_set_cppc, + .settings = hwpstate_settings_cppc, + .type = hwpstate_type_cppc }; + +static const struct hwpstate_cpufreq_methods pstate_methods = { + .get = hwpstate_get_pstate, + .set = hwpstate_set_pstate, + .settings = hwpstate_settings_pstate, + .type = hwpstate_type_pstate }; + +static int +hwpstate_probe(device_t dev) +{ + struct hwpstate_softc *sc; + sc = device_get_softc(dev); + + if (hwpstate_amd_cppc_enable && + (amd_extended_feature_extensions & AMDFEID_CPPC)) { + sc->flags |= HWPFL_USE_CPPC; + device_set_desc(dev, + "AMD Collaborative Processor Performance Control (CPPC)"); + } else { + /* + * No CPPC support. Only keep hwpstate0, it goes well with + * acpi_throttle. + */ + if (device_get_unit(dev) != 0) + return (ENXIO); + device_set_desc(dev, "Cool`n'Quiet 2.0"); + } + + sc->dev = dev; + if ((sc->flags & HWPFL_USE_CPPC) != 0) { + sc->cpufreq_methods = &cppc_methods; + return (0); + } + sc->cpufreq_methods = &pstate_methods; + return (hwpstate_probe_pstate(dev)); } static int @@ -1037,8 +1108,8 @@ hwpstate_attach(device_t dev) SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, "desired_performance", - CTLTYPE_UINT | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, - dev, AMD_CPPC_REQUEST_DES_PERF_BITS, + CTLTYPE_UINT | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, dev, + AMD_CPPC_REQUEST_DES_PERF_BITS, sysctl_cppc_request_field_handler, "IU", "Desired performance level (from 0 to 255; " "0 enables autonomous mode, otherwise value should be "