From nobody Wed Sep 30 16:20:14 2026 Received: from mail-pj2-f9.google.com (mail-pj2-f9.google.com [74.125.227.137]) (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 DF53B44839D for ; Fri, 7 Aug 2026 06:12:08 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.227.137 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786083131; cv=none; b=uzs3zXYqQLDUe37Y4xQ5ZNq3SilaI+ykCoy0ZSKHBI2KsSJGrY4MDZnAaDihm0M7Y8A1aDrZCk/toLuJPh7LWvZlsCGMKfc2DArgw7e+uDrjo1x8WyCCTstWMBTTOKoeKIGpzzjq2vpSRO7oXAyiWgnVLTFv4rp4YA7yFOuwb5Y= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786083131; c=relaxed/simple; bh=CBkY0c3xbjJo5xy0a0Ya0TPioAfVbM03GZcCRoqC/+A=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=G11h3W+dH3MStNrtmUoQIhcsCv/5m6IOT9yK3odQ+0d/zdFbfj8eB98/T9+vlk2dEqzKuVP6WXdv5Lb7fpEzcDZrOIVvffeVBXEgA1mu6UqZTN0qVSsCi12O+ozcEqI5AfTNYo3TObybom/tKHcKgL/OPxrE6gvBR56yovfWjVQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=kylinos.cn; spf=pass smtp.mailfrom=gmail.com; arc=none smtp.client-ip=74.125.227.137 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=kylinos.cn Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Received: by mail-pj2-f9.google.com with SMTP id 98e67ed59e1d1-38eca9b7114so1710132a91.1 for ; Thu, 06 Aug 2026 23:12:08 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1786083128; x=1786687928; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=rIKFf5IUphGedu29HI3S87K+WXZgW1+znZSL9A0NdHw=; b=YFVndA1EnGLJyEkvzOa82cW4K9xdPnZDqrVrkivAaPPHS9hos7/6LXv3v9fgGYS34p GRh1AhPPFrx1euqp/B/hJufut7Zek6rcUcufE61uY/kqXSHu2OFw+LnF3Ri0WYtZb7Hl 7n7kAxPm3uXOZnQoWABdTt4LPhWFqIUPDOUafFe1ufFHwNKAetQbeuDH0CqBj4HNcCP8 evz4/bAmglKp6cVO66EDWYX0RxO16J1A9KKaBlbvrdI6PL4UN6j6jaTQhZhNU0eqygFe +FfhBipsCE0lGps63KGOUKpDsUWOjBSUqS0+HKb3fo1sPZHCvOs/UOEJ3H+gtN+RB3WV eC9A== X-Forwarded-Encrypted: i=1; AHgh+RrsqfNpCEQCfTRNV81snVG9sh4rw7oRr9qEWKTf/6+hwf/rZMhw/Ji/H6dOD+hyrw1IIp+vR3JKjCgXnMs=@vger.kernel.org X-Gm-Message-State: AOJu0Yw3TrOk0aErNW94S/1ofcy5mUsN0bcKuSZ2EoZA7l2UiyeUp2at Mp5DQq9gY1eAkaNz3YYhUFxmZDVBXwH54IhoNXAsu8wtZLt80acKDLfU X-Gm-Gg: AR+sD10U6YQ7kE5a7Pc2m/JVi6RKtbmHo4UFYaEXAjq48l6UxUZxDgwjINI8nEcT5tY xUmwtoPW3H/BHmDbpNZcfTHL0Saxz9DKnileTppBC/Q+WUNqO4DsWdJwcFWgn8xKinrcTwXaBRH 00AU4cGQ04P5De8Qw5HG9Qa5JiLBaGPLMiRru438H1p4UmxEpG+ZbjBtGyNRbd+U6hC+KaWluHH 2RZ3XNv9hegsINyPmJx46lky+6RAPB/3q3GJ2+bZ2N+WaBsjrRVSFNbTR0KFmOIbvYb6hgQRzfZ nMUI8Pct9oOUSd1A6FnnErCNBsl2fwCwTCD+4HVwQkks/2vr+0Jue/B3VVwQsAIdUG5mj8JQAKT OQD1nU//qAO3tHoR8MFSZlEN+isLs1Waa/lA+RLuO+qbC4WZwtlQACX2s9xaSuHeqdljmsZx+wq yPY12DImV026NLNI2dMPHy0K7mKIMCFzPdmKMdzMX8PKM/o9CsL896UQRqqdpOjJ266Fjpg30Aw UbsPWwwxQ== X-Received: by 2002:a17:90b:1d02:b0:37f:fdc8:71b4 with SMTP id 98e67ed59e1d1-3903c599356mr20672051a91.2.1786083128112; Thu, 06 Aug 2026 23:12:08 -0700 (PDT) Received: from kylin-XiaoXinPro-16-AHP9.. ([116.128.244.171]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-39085dbe349sm3434375a91.4.2026.08.06.23.12.02 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 06 Aug 2026 23:12:07 -0700 (PDT) From: Xueqin Luo To: Sudeep Holla , Greg Kroah-Hartman , "Rafael J . Wysocki" , Danilo Krummrich , Viresh Kumar Cc: Jie Zhan , Lifeng Zheng , Pierre Gondois , Sumit Gupta , linux-kernel@vger.kernel.org, driver-core@lists.linux.dev, linux-pm@vger.kernel.org, Xueqin Luo Subject: [PATCH v5 1/3] cpufreq: cppc: Add update_limits support for Highest Performance changes Date: Fri, 7 Aug 2026 14:08:46 +0800 Message-ID: <20260807060848.832929-2-luoxueqin@kylinos.cn> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260807060848.832929-1-luoxueqin@kylinos.cn> References: <20260807060848.832929-1-luoxueqin@kylinos.cn> 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" ACPI CPPC specification requires OSPM to re-evaluate the Highest Performance register when Notify(0x85) is received for a processor device. Implement cppc_cpufreq_update_limits() to refresh the cached highest_perf capability through cppc_get_highest_perf() and update policy->cpuinfo.max_freq from Highest Performance. Use refresh_frequency_limits() so policy->max follows the standard cpufreq_set_policy() path. cpuinfo.max_freq always tracks Highest Performance. When boost is disabled but still supported, constrain policy->max by updating the existing boost_freq_req (created in cpufreq_policy_init_qos) to nominal, instead of hiding the hardware maximum in cpuinfo. Signed-off-by: Xueqin Luo --- drivers/cpufreq/cppc_cpufreq.c | 98 ++++++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) diff --git a/drivers/cpufreq/cppc_cpufreq.c b/drivers/cpufreq/cppc_cpufreq.c index 6fe0e972952a..089f734f851b 100644 --- a/drivers/cpufreq/cppc_cpufreq.c +++ b/drivers/cpufreq/cppc_cpufreq.c @@ -855,6 +855,103 @@ static int cppc_cpufreq_set_boost(struct cpufreq_poli= cy *policy, int state) return 0; } =20 +/** + * cppc_cpufreq_sync_boost_limits - Sync boost flag, cpuinfo max and boost= QoS + * @policy: cpufreq policy + * @boost_supported: whether highest_perf currently exceeds nominal_perf + * + * Highest Performance can appear or disappear at runtime via Notify(0x85). + * + * cpuinfo.max_freq always tracks the hardware maximum derived from Highest + * Performance so that sysfs reflects Notify(0x85) updates. Boost being off + * is enforced by updating the existing boost_freq_req to nominal (capping + * policy->max) rather than by hiding the hardware max in cpuinfo. + * boost_freq_req itself is only created at policy init, not here. + */ +static void cppc_cpufreq_sync_boost_limits(struct cpufreq_policy *policy, + bool boost_supported) +{ + struct cppc_cpudata *cpu_data =3D policy->driver_data; + struct cppc_perf_caps *caps =3D &cpu_data->perf_caps; + unsigned int highest_freq, nominal_freq, qos_freq; + int ret; + + if (!boost_supported && policy->boost_enabled) + policy->boost_enabled =3D false; + + policy->boost_supported =3D boost_supported; + + highest_freq =3D cppc_perf_to_khz(caps, caps->highest_perf); + nominal_freq =3D cppc_perf_to_khz(caps, caps->nominal_perf); + + /* + * Report the current hardware maximum. If Highest dropped below + * Nominal (unusual, but possible with test overrides), never + * advertise more than Highest allows. + */ + policy->cpuinfo.max_freq =3D highest_freq; + + if (boost_supported && !policy->boost_enabled) + qos_freq =3D min(nominal_freq, highest_freq); + else + qos_freq =3D highest_freq; + + /* + * boost_freq_req is created in cpufreq_policy_init_qos() when + * boost_supported is true at policy init. Runtime Highest changes + * only update that existing request; they do not add or remove it. + */ + if (freq_qos_request_active(&policy->boost_freq_req)) { + ret =3D freq_qos_update_request(&policy->boost_freq_req, + qos_freq); + if (ret < 0) + pr_debug("CPU%d: failed to sync boost QoS: %d\n", + policy->cpu, ret); + } + + pr_debug("CPU%d: highest_perf=3D%u boost_en=3D%d cpuinfo_max=3D%u qos_max= =3D%u\n", + policy->cpu, caps->highest_perf, policy->boost_enabled, + policy->cpuinfo.max_freq, qos_freq); +} + +static void cppc_cpufreq_update_limits(struct cpufreq_policy *policy) +{ + struct cppc_cpudata *cpu_data; + struct cppc_perf_caps *caps; + u64 prev_highest_perf; + u64 highest_perf; + int ret; + + guard(cpufreq_policy_write)(policy); + + cpu_data =3D policy->driver_data; + caps =3D &cpu_data->perf_caps; + + prev_highest_perf =3D caps->highest_perf; + + ret =3D cppc_get_highest_perf(policy->cpu, &highest_perf); + if (ret) + return; + + if (highest_perf =3D=3D prev_highest_perf) + return; + + caps->highest_perf =3D highest_perf; + + /* + * Re-evaluate boost capability/status based on the updated Highest + * Performance. Boost is supported when highest_perf exceeds + * nominal_perf. + */ + cppc_cpufreq_sync_boost_limits(policy, + highest_perf > caps->nominal_perf); + + refresh_frequency_limits(policy); + + pr_debug("CPU%d: highest_perf updated %llu -> %llu\n", + policy->cpu, prev_highest_perf, highest_perf); +} + static ssize_t show_freqdomain_cpus(struct cpufreq_policy *policy, char *b= uf) { struct cppc_cpudata *cpu_data =3D policy->driver_data; @@ -1048,6 +1145,7 @@ static struct cpufreq_driver cppc_cpufreq_driver =3D { .init =3D cppc_cpufreq_cpu_init, .exit =3D cppc_cpufreq_cpu_exit, .set_boost =3D cppc_cpufreq_set_boost, + .update_limits =3D cppc_cpufreq_update_limits, .attr =3D cppc_cpufreq_attr, .name =3D "cppc_cpufreq", }; --=20 2.43.0 From nobody Wed Sep 30 16:20:14 2026 Received: from mail-pj2-f11.google.com (mail-pj2-f11.google.com [74.125.227.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 B9249448BAB for ; Fri, 7 Aug 2026 06:12:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.227.139 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786083137; cv=none; b=EBkFpqwCBHTTAniSNweM2OK7VKfwU6ztnl1ruiyl5BhKipJjU5zavfJvbjZJaedQIFpMMkvyxi5pJJkWAJNSWeO6BqHAOjdvMIpP9GYFmV/C1qVAecLHZnA+NR4292S+iuBNT4Qzn7Mjvb4JjGHjz+bKF+kFPGnr+kpMTqFLZC4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786083137; c=relaxed/simple; bh=oetLtZV/iWveJIyrgkmKXIj79dzYiKvpZNDFjPJZPJY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=p0VHCtmknVH07iOjEglopj8zV/Mv8Z7DVb3fn0F2It7teoMQz5b5mA9Chrs9AuPt+Bexdxoxvjn7VpIzMyN88bJnmb7R2jOJgISOIfKyrLxmC0+N/o2tUI4fHXSrfu47VxOSaZwLDIIhtf82bWLyqp+Npzd5p4opAeqo7YFtKQQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=kylinos.cn; spf=pass smtp.mailfrom=gmail.com; arc=none smtp.client-ip=74.125.227.139 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=kylinos.cn Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Received: by mail-pj2-f11.google.com with SMTP id 98e67ed59e1d1-38dbe53179bso1062190a91.0 for ; Thu, 06 Aug 2026 23:12:15 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1786083135; x=1786687935; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=YmaMOn1E77zLCE2VFOMBiSvTaQ+1cOqxSJYgxhNCMNs=; b=LFJyhsk79y31mGfLH9LM14NcvOjum/FnIyToIc2QtiqatrH05g50ctoctKP4vN4rxp RVzg2jfaWFOzgWZUuODvLyFnrf8UY50v67G1dc5XzYuJIpUYtXzDYXMAMVjAEGFb20Tn 9nojYmc9FKKyxy4rxChJviUPvppbZS5GYEAj4WtAVdKvI/PTvQirMznmyxZiqZsCvKA/ Pbo3IU0o8BSSClTa96LCY0qM6XMCx/pTEE31pDdqL3gZFenwPzwZDf5a1bTmgcL7rHXc sIEBXQW3hJGaRf2yOVHtfAOUx4f0mfEqbn1ggSP1CkNQJ6LIkmJT9m2Uf4MABXte7Qg/ qsfA== X-Forwarded-Encrypted: i=1; AHgh+RpuFnQwncKJ27ETOo1r/+Tp9Wse/rheaZ51ay3/zduhfP6OxNT764znuhp13yjCBi8jAxu9hvMOVzoMRwA=@vger.kernel.org X-Gm-Message-State: AOJu0YyGPaBbx82u2pcTnS1yhP1pYxpuvT+mBjxFGgwW/KmiKbgRYPoT hT4hXAtJmnsTHTnTRl52phsoDy6lIrO/nH5dqLLzuig6Ypy4BARHvCZq X-Gm-Gg: AR+sD13eeeNiYvB8rVGJKmR3Nrrd4eksjSHQ58JBV4AGUNEESapqbWXIquX7g/X6rnt RF8soJacOPTthYB3yiBZVwl/jphBJ6vXkVwWR92jC5YaKcWl1Z3yBV9v2ACkLonCHTTLhkc5QFo tavccxkVWsoOOIhHMuyDlTdoqt2juLDFYMDIBxMkPbE89kxYu460TziC7aQXogijrN+SsgJG1zs CJeEf6iQi3hGavK93+mex3SZfshuR+Zd02O9+J40MwBUFgT05UmvJQPxNuxwyrhryLMryi2klFe aJZCyQ4X/pMXyfe63Tfs56FL9PwuvBuGV0yuGMommPJoRo19YAW627OsYUGfIBIBmjrtF0eNKkE oWoVZWBGSDX1LvwfLeON9Wqpains9b0Y3oqtqPlAk0Ws1rxwriHg3JomWuEsSn+qPEKC7zBwPb/ 0POXQQsbS2nazAspC0Tc1FldNfMKS1lVDBLW7HZoUVYy6Eou6l4i/fNdNleKQvcDum4PBIPwtsZ SQUnngApQ== X-Received: by 2002:a17:90b:3c84:b0:38f:efed:5448 with SMTP id 98e67ed59e1d1-3903c54ac31mr21765970a91.8.1786083135001; Thu, 06 Aug 2026 23:12:15 -0700 (PDT) Received: from kylin-XiaoXinPro-16-AHP9.. ([116.128.244.171]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-39085dbe349sm3434375a91.4.2026.08.06.23.12.09 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 06 Aug 2026 23:12:14 -0700 (PDT) From: Xueqin Luo To: Sudeep Holla , Greg Kroah-Hartman , "Rafael J . Wysocki" , Danilo Krummrich , Viresh Kumar Cc: Jie Zhan , Lifeng Zheng , Pierre Gondois , Sumit Gupta , linux-kernel@vger.kernel.org, driver-core@lists.linux.dev, linux-pm@vger.kernel.org, Xueqin Luo Subject: [PATCH v5 2/3] cpufreq: cppc: Refactor autonomous perf bounds into helper Date: Fri, 7 Aug 2026 14:08:47 +0800 Message-ID: <20260807060848.832929-3-luoxueqin@kylinos.cn> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260807060848.832929-1-luoxueqin@kylinos.cn> References: <20260807060848.832929-1-luoxueqin@kylinos.cn> 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" Extract the autonomous selection performance bounds programming from store_auto_select() into a reusable cppc_cpufreq_set_autonomous_perf() helper. The helper saves and restores MIN/MAX performance on failure, keeping the rollback logic co-located with the programming sequence. Reuse the helper in cppc_cpufreq_update_limits() so that when Highest Performance changes at runtime, the autonomous MIN/MAX envelope is re-programmed against the updated capability. Add a pr_debug message on failure for diagnostics. Signed-off-by: Xueqin Luo --- drivers/cpufreq/cppc_cpufreq.c | 57 ++++++++++++++++++++++++++-------- 1 file changed, 44 insertions(+), 13 deletions(-) diff --git a/drivers/cpufreq/cppc_cpufreq.c b/drivers/cpufreq/cppc_cpufreq.c index 089f734f851b..09d7745a609f 100644 --- a/drivers/cpufreq/cppc_cpufreq.c +++ b/drivers/cpufreq/cppc_cpufreq.c @@ -868,6 +868,37 @@ static int cppc_cpufreq_set_boost(struct cpufreq_polic= y *policy, int state) * policy->max) rather than by hiding the hardware max in cpuinfo. * boost_freq_req itself is only created at policy init, not here. */ + +/** + * cppc_cpufreq_set_autonomous_perf - Configure performance bounds for + * autonomous mode + * @policy: cpufreq policy structure + * + * When autonomous selection is enabled, program MIN_PERF and MAX_PERF + * from current policy limits so that the platform uses the correct + * performance bounds immediately. + * + * Return: 0 on success, negative error code on failure. + */ +static int cppc_cpufreq_set_autonomous_perf(struct cpufreq_policy *policy) +{ + struct cppc_cpudata *cpu_data =3D policy->driver_data; + u32 old_min_perf =3D cpu_data->perf_ctrls.min_perf; + u32 old_max_perf =3D cpu_data->perf_ctrls.max_perf; + int ret; + + cppc_cpufreq_update_perf_limits(cpu_data, policy); + + ret =3D cppc_set_perf(policy->cpu, &cpu_data->perf_ctrls); + if (ret) { + cpu_data->perf_ctrls.min_perf =3D old_min_perf; + cpu_data->perf_ctrls.max_perf =3D old_max_perf; + return ret; + } + + return 0; +} + static void cppc_cpufreq_sync_boost_limits(struct cpufreq_policy *policy, bool boost_supported) { @@ -948,6 +979,18 @@ static void cppc_cpufreq_update_limits(struct cpufreq_= policy *policy) =20 refresh_frequency_limits(policy); =20 + /* + * Autonomous selection mode uses MIN/MAX performance as runtime + * hardware control bounds. Re-program them when highest_perf + * changes so that the platform uses the updated bounds. + */ + if (cpu_data->perf_ctrls.auto_sel) { + ret =3D cppc_cpufreq_set_autonomous_perf(policy); + if (ret) + pr_debug("CPU%d: failed to update autonomous perf: %d\n", + policy->cpu, ret); + } + pr_debug("CPU%d: highest_perf updated %llu -> %llu\n", policy->cpu, prev_highest_perf, highest_perf); } @@ -994,20 +1037,8 @@ static ssize_t store_auto_select(struct cpufreq_polic= y *policy, cpu_data->perf_ctrls.auto_sel =3D val; =20 if (val) { - u32 old_min_perf =3D cpu_data->perf_ctrls.min_perf; - u32 old_max_perf =3D cpu_data->perf_ctrls.max_perf; - - /* - * When enabling autonomous selection, program MIN_PERF and - * MAX_PERF from current policy limits so that the platform - * uses the correct performance bounds immediately. - */ - cppc_cpufreq_update_perf_limits(cpu_data, policy); - - ret =3D cppc_set_perf(policy->cpu, &cpu_data->perf_ctrls); + ret =3D cppc_cpufreq_set_autonomous_perf(policy); if (ret) { - cpu_data->perf_ctrls.min_perf =3D old_min_perf; - cpu_data->perf_ctrls.max_perf =3D old_max_perf; cppc_set_auto_sel(policy->cpu, false); cpu_data->perf_ctrls.auto_sel =3D false; return ret; --=20 2.43.0 From nobody Wed Sep 30 16:20:14 2026 Received: from mail-pj2-f8.google.com (mail-pj2-f8.google.com [74.125.227.136]) (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 17DBA448BB2 for ; Fri, 7 Aug 2026 06:12:22 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.227.136 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786083144; cv=none; b=Li6pbWdqN1hx7O4uFpGHmHTUOUtURxMjxKjJCtmV2GF+qLvIG+XgVQFGl2e82ZUnboAgUDTe/hIENwg5yGWW24JFZ5Hky3aWMGdZY7P439jbHgZUdu+n5G39gjjMn6EXjie6lhmAK7Od7GCHlrcIslIvaB2GIwd6NUQdNEsZOgg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786083144; c=relaxed/simple; bh=mBdQuOd2+orI7EhARk3z3raKkDlXH+X/4B3FrZzB/fY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=HKyRF2/NSAdfmpISXkAwDt60CClAGFgj9z2hy6ovDYSVIG5UxJkZq/cWCTdBWG0EJ6mvQYsGNIb/S0lZhnR0kRkGIBRF+5ddaS6Iwulo0MgeUFF69VrqFcYI3IbEEZ+c3WeIKpQ1HhAEHtr5Y1j2ThPfXUTD+fxLf5ztZVY51EQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=kylinos.cn; spf=pass smtp.mailfrom=gmail.com; arc=none smtp.client-ip=74.125.227.136 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=kylinos.cn Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Received: by mail-pj2-f8.google.com with SMTP id 98e67ed59e1d1-38fd9408220so1042673a91.1 for ; Thu, 06 Aug 2026 23:12:22 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1786083142; x=1786687942; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=m2XI3tymrAXIanNBdwarSxOFR4nQgsGCTq88+6vG+F8=; b=MYfh/rzxuRqdcfvyxSV8kzb0Y3kIMknas/8+W6Wx/7RhzpFnR5EMqf4zRrLvG9r5Nb /NofZZm7RZhXpY0inhQlcrI9Y3/nIovM8QvO5lJlU8hgJZ9EBxZ/dereu7qUWpfF5X/+ 86yE4NLd+N5vZ/FLwwd/jaVenDvqsfre7JAa9nOMDV4xK3/xHXCv7EUYP/reFXT35/Yh L8YOFcOoQsrhjcWo1GKp9QI1zVn/yMokPmgC2hZt/IfXOqdwCu2H86+2XMfBtUVPpwJS WmDhqq22m8jj0U7GJdMDYKgNyocErWB23ApclpoRMLmoLMefpkxuhs1cSGjyYvg+Pd0P N5xg== X-Forwarded-Encrypted: i=1; AHgh+RpJdaTbf6ccShMjSaXFC5+TlyAGpPi8lNnwPNy2C9FniuBku8vhvVyWmFbm6IF+BMmociPs3f7EgGDXznY=@vger.kernel.org X-Gm-Message-State: AOJu0Yyx7MuMzX2JlVaY964ljCDXfy1pCmuhn01propW47/fDQ07s7n+ QtunwTBYW5yk5wlvFckdj7WGS2zp5b3L5Ju4rKKtuRUv3zzYKWjVVpBZ X-Gm-Gg: AR+sD12vZIqWtrC7uui+DKgBCvHBE3AQuJBCa7S4MzJAvQa3k0VPSeB7Ic73VKWdMUp bfBjB3rglKRb+MBVxWThoJkDGYHUfJid3eP5QSaxEoKoM5eNN4zi0sPWv3kMbXYgfCWb4brILv4 MROAp4S3Vuh1O8Z9HItEtkkZYNx7EaW4mrv82HAM2AwUb/MfBpsQ5i+Z3Qvpedccda3jxFMAlcS oyHbB/HhGx5uord+Ov30DuwKlt3XYR+PRYQ1At0Vhr//RJtsJAxGlKnwXAiNd+AR0nn77/6Zlwp yXIIEoCKS7YMa3JKQheCoOE3sPD/FTZ5BEhBZ29KeDlD4eXtQtuh1KqCtEQigxk2VznUYBYqhWM 4bronXTCm4H+hLipfz5/FlhSeVraJQXU/lzC1HZTPWxV5o95XSWLLRJ8RkUlbLkfo6n4cNjMsJw gH33um7+qJRLeMoJW1Z3txBJYnREfsZ8DZgB+7yuT3lmy2RY5Auo7MoY2TIj320o7+CLZnn0Jy/ ea8cbv5Hg== X-Received: by 2002:a17:90a:d010:b0:38d:eaec:4396 with SMTP id 98e67ed59e1d1-3903c58bdd2mr20324647a91.11.1786083142215; Thu, 06 Aug 2026 23:12:22 -0700 (PDT) Received: from kylin-XiaoXinPro-16-AHP9.. ([116.128.244.171]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-39085dbe349sm3434375a91.4.2026.08.06.23.12.16 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 06 Aug 2026 23:12:21 -0700 (PDT) From: Xueqin Luo To: Sudeep Holla , Greg Kroah-Hartman , "Rafael J . Wysocki" , Danilo Krummrich , Viresh Kumar Cc: Jie Zhan , Lifeng Zheng , Pierre Gondois , Sumit Gupta , linux-kernel@vger.kernel.org, driver-core@lists.linux.dev, linux-pm@vger.kernel.org, Xueqin Luo Subject: [PATCH v5 3/3] arch_topology: Add topology_update_cpu_capacity() for runtime updates Date: Fri, 7 Aug 2026 14:08:48 +0800 Message-ID: <20260807060848.832929-4-luoxueqin@kylinos.cn> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260807060848.832929-1-luoxueqin@kylinos.cn> References: <20260807060848.832929-1-luoxueqin@kylinos.cn> 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" When the CPPC Highest Performance register changes at runtime (e.g. via ACPI Notify(0x85)), the scheduler's view of CPU capacity and the frequency invariance engine's reference values become stale, as topology_init_cpu_capacity_cppc() is only called once during boot. Keep raw_capacity allocated after CPPC init instead of freeing it, and introduce topology_update_cpu_capacity() to update per-CPU raw_capacity, capacity_freq_ref, and the normalized CPU capacity scale at runtime. Provide a no-op stub when GENERIC_ARCH_TOPOLOGY is disabled so cppc_cpufreq can link on those configs. Skip updates when the value is unchanged and reject a zero capacity_scale to avoid division by zero. Call this from cppc_cpufreq_update_limits() for every CPU in the policy so shared-policy Notify(0x85) targeting a non-policy CPU still refreshes the correct topology capacity. Signed-off-by: Xueqin Luo --- drivers/base/arch_topology.c | 76 ++++++++++++++++++++++++++++++++++ drivers/cpufreq/cppc_cpufreq.c | 2 + include/linux/arch_topology.h | 13 ++++++ 3 files changed, 91 insertions(+) diff --git a/drivers/base/arch_topology.c b/drivers/base/arch_topology.c index 8c5e47c28d9a..27f2bfa9f326 100644 --- a/drivers/base/arch_topology.c +++ b/drivers/base/arch_topology.c @@ -229,6 +229,7 @@ static void update_topology_flags_workfn(struct work_st= ruct *work) } =20 static u32 *raw_capacity; +static DEFINE_MUTEX(raw_capacity_lock); =20 static int free_raw_capacity(void) { @@ -372,13 +373,88 @@ static inline void topology_init_cpu_capacity_cppc(vo= id) schedule_work(&update_topology_flags_work); pr_debug("cpu_capacity: cpu_capacity initialization done\n"); =20 + /* + * Keep raw_capacity for runtime updates via + * topology_update_cpu_capacity(). + */ + return; + exit: free_raw_capacity(); } + void acpi_processor_init_invariance_cppc(void) { topology_init_cpu_capacity_cppc(); } + +/** + * topology_update_cpu_capacity - Update CPU capacity after highest_perf c= hange + * @cpu: CPU whose highest performance changed + * @perf_caps: Updated CPPC performance capabilities for @cpu + * + * When the CPPC Highest Performance register changes at runtime + * (e.g. via Notify(0x85)), the scheduler's view of CPU capacity + * and the frequency invariance engine's reference values become + * stale. This function updates the per-CPU raw_capacity, + * capacity_freq_ref and freq_inv max ratio, then re-normalizes the + * CPU capacity scale for all possible CPUs and triggers a sched + * domain rebuild. If the value is unchanged, everything is skipped. + */ +void topology_update_cpu_capacity(unsigned int cpu, + struct cppc_perf_caps *perf_caps) +{ + u32 highest_perf =3D perf_caps->highest_perf; + u64 capacity, capacity_scale =3D 0; + int c; + + guard(mutex)(&raw_capacity_lock); + + if (!raw_capacity || cpu >=3D num_possible_cpus()) + return; + + /* + * Validate: highest_perf must be >=3D nominal_perf and >=3D lowest_perf, + * consistent with the boot-time check in topology_init_cpu_capacity_cppc= (). + */ + if (highest_perf < perf_caps->lowest_perf) { + pr_warn("cpu_capacity: CPU%d invalid highest_perf=3D%u (nominal=3D%u, lo= west=3D%u), skipping\n", + cpu, highest_perf, perf_caps->nominal_perf, + perf_caps->lowest_perf); + return; + } + + if (raw_capacity[cpu] =3D=3D highest_perf) + return; + + pr_debug("cpu_capacity: CPU%d cpu_capacity=3D%u -> %u (raw)\n", + cpu, raw_capacity[cpu], highest_perf); + + raw_capacity[cpu] =3D highest_perf; + per_cpu(capacity_freq_ref, cpu) =3D + cppc_perf_to_khz(perf_caps, highest_perf); + freq_inv_set_max_ratio(cpu, + per_cpu(capacity_freq_ref, cpu) * HZ_PER_KHZ); + + /* Re-normalize all CPUs: capacity is relative. */ + for_each_possible_cpu(c) + capacity_scale =3D max_t(u64, capacity_scale, raw_capacity[c]); + + if (!capacity_scale) + return; + + for_each_possible_cpu(c) { + capacity =3D raw_capacity[c]; + capacity =3D div64_u64(capacity << SCHED_CAPACITY_SHIFT, + capacity_scale); + topology_set_cpu_scale(c, capacity); + pr_debug("cpu_capacity: CPU%d cpu_capacity=3D%lu\n", + c, topology_get_cpu_scale(c)); + } + + schedule_work(&update_topology_flags_work); +} +EXPORT_SYMBOL_GPL(topology_update_cpu_capacity); #endif =20 #ifdef CONFIG_CPU_FREQ diff --git a/drivers/cpufreq/cppc_cpufreq.c b/drivers/cpufreq/cppc_cpufreq.c index 09d7745a609f..1480be537eaa 100644 --- a/drivers/cpufreq/cppc_cpufreq.c +++ b/drivers/cpufreq/cppc_cpufreq.c @@ -979,6 +979,8 @@ static void cppc_cpufreq_update_limits(struct cpufreq_p= olicy *policy) =20 refresh_frequency_limits(policy); =20 + topology_update_cpu_capacity(policy->cpu, caps); + /* * Autonomous selection mode uses MIN/MAX performance as runtime * hardware control bounds. Re-program them when highest_perf diff --git a/include/linux/arch_topology.h b/include/linux/arch_topology.h index ebd7f8935f96..9415cb6a6c2b 100644 --- a/include/linux/arch_topology.h +++ b/include/linux/arch_topology.h @@ -11,6 +11,19 @@ void topology_normalize_cpu_scale(void); int topology_update_cpu_topology(void); =20 +#ifdef CONFIG_ACPI_CPPC_LIB +struct cppc_perf_caps; +#ifdef CONFIG_GENERIC_ARCH_TOPOLOGY +void topology_update_cpu_capacity(unsigned int cpu, + struct cppc_perf_caps *perf_caps); +#else +static inline void +topology_update_cpu_capacity(unsigned int cpu, struct cppc_perf_caps *perf= _caps) +{ +} +#endif +#endif + struct device_node; bool topology_parse_cpu_capacity(struct device_node *cpu_node, int cpu); =20 --=20 2.43.0