Re: [PATCH v3 2/2] ACPI: CPPC: Add ospm_nominal_perf support
Sumit Gupta <[email protected]> Mon, 15 Jun 2026 23:53:31 +0530
| Newsgroups | dev.linux.lists.acpica-devel,org.kernel.vger.linux-acpi,org.kernel.vger.linux-kernel,org.kernel.vger.linux-pm |
|---|---|
| Message-ID | <[email protected]> |
Hi Pierre, On 11/06/26 20:01, Pierre Gondois wrote: > External email: Use caution opening links or attachments > > > On 6/9/26 10:53, Sumit Gupta wrote: >> >> On 28/05/26 17:37, Pierre Gondois wrote: >>> External email: Use caution opening links or attachments >>> >>> >>> Hello Sumit, >>>> >>>> Hi Pierre, >>>> >>>> Thanks for the review and the complementary patch. >>>> Going point by point: >>>> >>>> 1. Rollback for a partially applied multiple CPU write in >>>> store_ospm_nominal_freq(): Agreed, will add into v4. >>>> >>>> 2. cppc_get_ospm_nominal_perf() and the show/init/exit coherence >>>> checks that rely on it: I'd skip these as the register is >>>> write-only >>>> as per spec. >>>> >>> NIT: >>> IIUC having a write-only register doesn't mean we cannot read it. >>> Cf. cppc_get_desired_perf() >> >> >> Good point. >> v5 reads the register via a new cppc_get_ospm_nominal_perf(). >> So, show() returns the register value or "<unsupported>", >> and dropped the cache/bool. >> >> >>> >>>> 3. Initializing the register at startup and restoring at exit: In >>>> v3, we >>>> dropped the unconditional cpu_init write so user values would >>>> survive CPU hotplug. The spec also makes the explicit init >>>> unnecessary: "If this register is not provided, then OSPM must >>>> assume that the OSPM Nominal Performance value is equal to >>>> the Nominal Performance value.". The unwritten default already >>>> looks well defined. >>> >>> The concern I had was for the scenario where: >>> >>> - the driver is loaded >>> >>> - the user sets an ospm_nominal_freq value >>> >>> - the driver is unloaded >>> >>> In such case, the ospm_nominal_freq value will still be set to a >>> non-default value. The modifications suggested previously would >>> allow to handle that case to come back to the default value. >>> >>> FWIU, we have: >>> >>> +------+ +---------+ +-----------+ +------+ >>> | User | <-> | CPPC | <-> | CPPC | <-> | CPPC | >>> +------+ | driver | | reg | | HW | >>> +---------+ | interface | | reg | >>> +-----------+ +------+ >>> >>> So if we want to handle: >>> >>> - the case described above >>> >>> - the case you mentioned, i.e. hot-plugging CPUs >>> >>> maybe the scratch values should be stored along the CPPC register >>> interface. This would allow to handle complex cases where CPUs >>> are hotplugged and the driver is loaded/unloaded ? >>> >>> Note: the same kind of scenario should apply to the auto_sel register >>> >> >> Right. >> After unload, the register keeps the user set value instead of the >> firmware value. In a follow-up, I will restore the firmware value on >> unload and reapply the user value across hotplug, grouping the >> OSPM-set registers together (ospm_nominal_perf, auto_sel and EPP). >> On my test platforms the registers survive hotplug, but that isn't >> guaranteed in general. >> >> I think it's better to keep the saved state in the cppc_cpufreq driver >> rather than the CPPC register interface. intel_pstate and amd-pstate >> do the same. >> For reapply, will use a CPU hotplug callback rather than ->online/ >> ->offline hooks. Those are only called when a policy gains its first >> online CPU or loses its last one. cppc_cpufreq also has shared >> (SHARED_TYPE_ANY) policy, offlining and onlining a single CPU >> keeps the policy active, so neither hook is called for it. A per-CPU >> hotplug callback is needed to cover that case. >> >> Let me know if you have other thoughts. >> > Is it necessary to have cpuhp callbacks ? > > The cppc_cpufreq driver should only support: > - SHARED_TYPE_HW/NONE: in such case, the polity should > only have one CPU > - SHARED_TYPE_ANY: in such case, configuring any CPU should > configure all the CPUs of the policy. The only issue is that > we currently don't know whether the CPUs in the policy > share the same CPPC registers or have individual registers. > I think it is currently strongly assumed there is only one > registers for all the CPUs. > > For instance, if: > - CPU0/1 are in the same perf. domain > - don't have the same CPPC registers > - have a SHARED_TYPE_ANY policy (i.e. writing to any > of CPU0/1's CPPC registers triggers an update of the > hardware for the 2 CPUs) > - policy->cpu = 0 > then: > - enabling auto_sel for the policy means configuring > CPU0's CPPC register > - if CPU0 is offlined, policy->cpu is updated to 1 (pointing to CPU1), > - then reading the policy's auto_sel register means reading > CPU1's CPPC register, which was not updated > > So using the already present online()/offline() callbacks should be > enough. It would also be good to check that, for a policy, all the > CPPC registers are identical. > > Note: having per-CPU CPPC registers + SHARED_TYPE_ANY > policy is theoretically valid, but unsupported FWIU. > > Let me know if it makes sense or not, > > Regards, > > Pierre > Agreed, the cpuhp callback isn't needed. For a SHARED_TYPE_ANY policy cppc_cpufreq treats the control registers as equivalent across the policy's CPUs. A single CPU offline/online within the policy therefore doesn't lose the value. Only a full teardown and bring-up can lose value on the platforms that reset the register on hotplug. That path already goes through ->exit/->init, so reapplying the saved value from ->init() covers it without adding callbacks. We can add a check that guards this assumption in cppc_cpufreq_cpu_init, for the CPUFREQ_SHARED_TYPE_ANY case. Compare the control registers each CPU in policy->cpus exposes (excluding per-CPU feedback counters) and warn on a mismatch rather than failing init. Since it concerns existing behavior, the change can be a separate independent patch. It flags the per CPU registers case you described. Does that match what you had in mind? Thank you, Sumit Gupta