* Re: [PATCH v7 2/2] cpufreq: Add boost_freq_req QoS request
From: Pierre Gondois @ 2026-03-26 8:54 UTC (permalink / raw)
To: Viresh Kumar
Cc: linux-kernel, Lifeng Zheng, Huang Rui, Gautham R. Shenoy,
Mario Limonciello, Perry Yuan, Rafael J. Wysocki, linux-pm
In-Reply-To: <hajhezqrujiky7eo4eidogvjomixmhtdxpzfjibrd2xbhxawbd@ptljcesqpyqx>
On 3/26/26 09:48, Viresh Kumar wrote:
> On 25-03-26, 17:52, Pierre Gondois wrote:
>> @@ -1377,6 +1386,8 @@ static void cpufreq_policy_free(struct cpufreq_policy *policy)
>> }
>>
>> freq_qos_remove_request(policy->min_freq_req);
> Since this doesn't check min_freq_req (and depend on the routine to return
> early), shouldn't we do the same for below one ?
Yes it is possible,
there were different views but without the check is ok aswell.
>
>> + if (policy->boost_freq_req)
>> + freq_qos_remove_request(policy->boost_freq_req);
>> kfree(policy->min_freq_req);
>>
>> cpufreq_policy_put_kobj(policy);
^ permalink raw reply
* Re: [PATCH v7 0/8] Add support for handling PCIe M.2 Key E connectors in devicetree
From: Bartosz Golaszewski @ 2026-03-26 8:54 UTC (permalink / raw)
To: manivannan.sadhasivam
Cc: Manivannan Sadhasivam via B4 Relay, linux-serial, linux-kernel,
linux-kbuild, platform-driver-x86, linux-pci, devicetree,
linux-arm-msm, linux-bluetooth, linux-pm, Stephan Gerhold,
Dmitry Baryshkov, linux-acpi, Hans de Goede, Bartosz Golaszewski,
Bartosz Golaszewski, Rob Herring, Greg Kroah-Hartman, Jiri Slaby,
Nathan Chancellor, Nicolas Schier, Hans de Goede,
Ilpo Järvinen, Mark Pearson, Derek J. Clark,
Manivannan Sadhasivam, Krzysztof Kozlowski, Conor Dooley,
Marcel Holtmann, Luiz Augusto von Dentz, Bartosz Golaszewski,
Andy Shevchenko
In-Reply-To: <20260326-pci-m2-e-v7-0-43324a7866e6@oss.qualcomm.com>
On Thu, 26 Mar 2026 09:06:28 +0100, Manivannan Sadhasivam via B4 Relay
<devnull+manivannan.sadhasivam.oss.qualcomm.com@kernel.org> said:
> Hi,
>
> This series is the continuation of the series [1] that added the initial support
> for the PCIe M.2 connectors. This series extends it by adding support for Key E
> connectors. These connectors are used to connect the Wireless Connectivity
> devices such as WiFi, BT, NFC and GNSS devices to the host machine over
> interfaces such as PCIe/SDIO, USB/UART and NFC. This series adds support for
> connectors that expose PCIe interface for WiFi and UART interface for BT. Other
> interfaces are left for future improvements.
>
> Serdev device support for BT
> ============================
>
> Adding support for the PCIe interface was mostly straightforward and a lot
> similar to the previous Key M connector. But adding UART interface has proved to
> be tricky. This is mostly because of the fact UART is a non-discoverable bus,
> unlike PCIe which is discoverable. So this series relied on the PCI notifier to
> create the serdev device for UART/BT. This means the PCIe interface will be
> brought up first and after the PCIe device enumeration, the serdev device will
> be created by the pwrseq driver. This logic is necessary since the connector
> driver and DT node don't describe the device, but just the connector. So to make
> the connector interface Plug and Play, the connector driver uses the PCIe device
> ID to identify the card and creates the serdev device. This logic could be
> extended in the future to support more M.2 cards. Even if the M.2 card uses SDIO
> interface for connecting WLAN, a SDIO notifier could be added to create the
> serdev device.
>
> Testing
> =======
>
> This series, together with the devicetree changes [2] was tested on the
> Qualcomm X1e based Lenovo Thinkpad T14s Laptop which has the WCN7850 WLAN/BT
> 1620 LGA card connected over PCIe and UART.
>
> Merge Strategy
> ==============
>
> Due to the API dependency, both the serdev and pwrseq patches need to go through
> a single tree, maybe through pwrseq tree. So the serdev patches need Ack from
> Greg. But Bluetooth patch can be merged separately.
I think Rob Herring is the man in charge here. The power sequencing parts look
good to me now so with an Ack on the serdev changes I can queue them for v7.1.
I can also put it on an immutable branch if needed.
Bart
^ permalink raw reply
* Re: [PATCH v7 2/2] cpufreq: Add boost_freq_req QoS request
From: Viresh Kumar @ 2026-03-26 8:50 UTC (permalink / raw)
To: Zhongqiu Han
Cc: Pierre Gondois, linux-kernel, Lifeng Zheng, Huang Rui,
Gautham R. Shenoy, Mario Limonciello, Perry Yuan,
Rafael J. Wysocki, linux-pm
In-Reply-To: <a382a832-d71b-4227-a469-07c96b70c372@oss.qualcomm.com>
On 26-03-26, 16:18, Zhongqiu Han wrote:
> Would it be reasonable to add a NULL check for policy->boost_freq_req in
> policy_set_boost() before calling freq_qos_update_request(), even though
> callers already check policy->boost_supported? Thanks
Not required. policy_set_boost() should only be called if boost is supported.
--
viresh
^ permalink raw reply
* Re: [PATCH v7 2/2] cpufreq: Add boost_freq_req QoS request
From: Viresh Kumar @ 2026-03-26 8:48 UTC (permalink / raw)
To: Pierre Gondois
Cc: linux-kernel, Lifeng Zheng, Huang Rui, Gautham R. Shenoy,
Mario Limonciello, Perry Yuan, Rafael J. Wysocki, linux-pm
In-Reply-To: <20260325165255.386576-3-pierre.gondois@arm.com>
On 25-03-26, 17:52, Pierre Gondois wrote:
> @@ -1377,6 +1386,8 @@ static void cpufreq_policy_free(struct cpufreq_policy *policy)
> }
>
> freq_qos_remove_request(policy->min_freq_req);
Since this doesn't check min_freq_req (and depend on the routine to return
early), shouldn't we do the same for below one ?
> + if (policy->boost_freq_req)
> + freq_qos_remove_request(policy->boost_freq_req);
> kfree(policy->min_freq_req);
>
> cpufreq_policy_put_kobj(policy);
--
viresh
^ permalink raw reply
* Re: [PATCH v7 5/8] dt-bindings: connector: Add PCIe M.2 Mechanical Key E connector
From: Bartosz Golaszewski @ 2026-03-26 8:48 UTC (permalink / raw)
To: manivannan.sadhasivam
Cc: Manivannan Sadhasivam via B4 Relay, linux-serial, linux-kernel,
linux-kbuild, platform-driver-x86, linux-pci, devicetree,
linux-arm-msm, linux-bluetooth, linux-pm, Stephan Gerhold,
Dmitry Baryshkov, linux-acpi, Rob Herring, Greg Kroah-Hartman,
Jiri Slaby, Nathan Chancellor, Nicolas Schier, Hans de Goede,
Ilpo Järvinen, Mark Pearson, Derek J. Clark,
Manivannan Sadhasivam, Krzysztof Kozlowski, Conor Dooley,
Marcel Holtmann, Luiz Augusto von Dentz, Bartosz Golaszewski,
Andy Shevchenko, Bartosz Golaszewski
In-Reply-To: <20260326-pci-m2-e-v7-5-43324a7866e6@oss.qualcomm.com>
On Thu, 26 Mar 2026 09:06:33 +0100, Manivannan Sadhasivam via B4 Relay
<devnull+manivannan.sadhasivam.oss.qualcomm.com@kernel.org> said:
> From: Manivannan Sadhasivam <manivannan.sadhasivam@oss.qualcomm.com>
>
> Add the devicetree binding for PCIe M.2 Mechanical Key E connector defined
> in the PCI Express M.2 Specification, r4.0, sec 5.1.2. This connector
> provides interfaces like PCIe or SDIO to attach the WiFi devices to the
> host machine, USB or UART+PCM interfaces to attach the Bluetooth (BT)
> devices. Spec also provides an optional interface to connect the UIM card,
> but that is not covered in this binding.
>
> The connector provides a primary power supply of 3.3v, along with an
> optional 1.8v VIO supply for the Adapter I/O buffer circuitry operating at
> 1.8v sideband signaling.
>
> The connector also supplies optional signals in the form of GPIOs for fine
> grained power management.
>
> Reviewed-by: Rob Herring (Arm) <robh@kernel.org>
> Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@oss.qualcomm.com>
> ---
Reviewed-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
^ permalink raw reply
* Re: [PATCH v7 2/2] cpufreq: Add boost_freq_req QoS request
From: Viresh Kumar @ 2026-03-26 8:40 UTC (permalink / raw)
To: Pierre Gondois
Cc: linux-kernel, Lifeng Zheng, Huang Rui, Gautham R. Shenoy,
Mario Limonciello, Perry Yuan, Rafael J. Wysocki, linux-pm
In-Reply-To: <b9029378-7c8e-4700-9ded-5fd80aa73fd8@arm.com>
On 26-03-26, 09:10, Pierre Gondois wrote:
> I thought there was an issue by adding boost last:
> not all policies support boost frequencies (and thus requests).
>
> So blocking_notifier_call_chain() should be called if:
>
> + if ((policy->max_freq_req && !policy->boost_supported) || +
> policy->boost_freq_req) {
>
> This was in an earlier version, but Rafael and Lifeng suggested
> to add boost_freq_req first to simplify the logic:
>
> https://lore.kernel.org/all/20260225084930.1692228-3-pierre.gondois@arm.com/
Makes sense.
--
viresh
^ permalink raw reply
* Re: [RFC][RFT][PATCH 0/3] arm64: Enable asympacking for minor CPPC asymmetry
From: Vincent Guittot @ 2026-03-26 8:24 UTC (permalink / raw)
To: Christian Loehle
Cc: arighi, peterz, dietmar.eggemann, valentin.schneider, mingo,
rostedt, segall, mgorman, catalin.marinas, will, sudeep.holla,
rafael, linux-pm, linux-kernel, juri.lelli, kobak, fabecassis
In-Reply-To: <d40e57e0-aeff-45fb-82c0-6cefc4f4899d@arm.com>
On Thu, 26 Mar 2026 at 09:16, Christian Loehle <christian.loehle@arm.com> wrote:
>
> On 3/26/26 07:53, Vincent Guittot wrote:
> > On Wed, 25 Mar 2026 at 19:13, Christian Loehle <christian.loehle@arm.com> wrote:
> >>
> >> The scheduler currently handles CPU performance asymmetry via either:
> >>
> >> - SD_ASYM_PACKING: simple priority-based task placement (x86 ITMT)
> >> - SD_ASYM_CPUCAPACITY: capacity-aware scheduling
> >>
> >> On arm64, capacity-aware scheduling is used for any detected capacity
> >> differences.
> >>
> >> Some systems expose small per-CPU performance differences via CPPC
> >> highest_perf (e.g. due to chip binning), resulting in slightly different
> >> capacities (<~5%). These differences are sufficient to trigger
> >> SD_ASYM_CPUCAPACITY, even though the system is otherwise effectively
> >> symmetric.
> >>
> >> For such small deltas, capacity-aware scheduling is unnecessarily
> >> complex. A simpler priority-based approach, similar to x86 ITMT, is
> >> sufficient.
> >
> > I'm not convinced that moving to SD_ASYM_PACKING is the right way to
> > move forward.
> > t
> > 1st of all, do you target all kind of system or only SMT? It's not
> > clear in your cover letter
>
> AFAIK only Andrea has access to an unreleased asymmetric SMT system,
> I haven't done any tests on such a system (as the cover-letter mentions
> under RFT section).
>
> >
> > Moving on asym pack for !SMT doesn't make sense to me. If you don't
> > want EAS enabled, you can disable it with
> > /proc/sys/kernel/sched_energy_aware
>
> Sorry, what's EAS got to do with it? The system I care about here
> (primarily nvidia grace) has no EM.
I tried to understand the end goal of this patch
SD_ASYM_CPUCAPACITY works fine with !SMT system so why enabling
SD_ASYM_PACKING for <5% diff ?
That doesn't make sense to me
>
> >
> > For SMT system and small capacity difference, I would prefer that we
> > look at supporting SMT in SD_ASYM_CPUCAPACITY. Starting with
> > select_idle_capacity
>
> This series is actually targeted for primarily the !SMT case, although
> it may or may not be useful for some of the SMT woes, too!
> (Again, I wouldn't know, I don't have such a system to test with)
>
> >[snip]
^ permalink raw reply
* Re: [RFC][RFT][PATCH 0/3] arm64: Enable asympacking for minor CPPC asymmetry
From: Vincent Guittot @ 2026-03-26 8:20 UTC (permalink / raw)
To: Andrea Righi
Cc: Christian Loehle, peterz, dietmar.eggemann, valentin.schneider,
mingo, rostedt, segall, mgorman, catalin.marinas, will,
sudeep.holla, rafael, linux-pm, linux-kernel, juri.lelli, kobak,
fabecassis
In-Reply-To: <acTqSVd-FhywPQ6t@gpd4>
On Thu, 26 Mar 2026 at 09:12, Andrea Righi <arighi@nvidia.com> wrote:
>
> Hi Christian,
>
> On Wed, Mar 25, 2026 at 06:13:11PM +0000, Christian Loehle wrote:
> ...
> > RFT:
> > Andrea, please give this a try. This should perform better in particular
> > for single-threaded workloads and workloads that do not utilize all
> > cores (all the time anyway).
> > Capacity-aware scheduling wakeup works very different to the SMP path
> > used now, some workloads will benefit, some regress, it would be nice
> > to get some test results for these.
> > We already discussed DCPerf MediaWiki seems to benefit from
> > capacity-aware scheduling wakeup behavior, but others (most?) should
> > benefit from this series.
> >
> > I don't know if we can also be clever about ordering amongst SMT siblings.
> > That would be dependent on the uarch and I don't have a platform to
> > experiment with this though, so consider this series orthogonal to the
> > idle-core SMT considerations.
> > On platforms with SMT though asympacking makes a lot more sense than
> > capacity-aware scheduling, because arguing about capacity without
> > considering utilization of the sibling(s) (and the resulting potential
> > 'stolen' capacity we perceive) isn't theoretically sound.
>
> I did some early testing with this patch set. On Vera I'm getting much
> better performance that SD_ASYM_CPUCAPACITY of course (~1.5x avg speedup),
> mostly because we avoid using both SMT siblings. It's still not the same
> improvement that I get equalizing the capacity using the 5% threshold
> (~1.8x speedup).
IIRC the tests that you shared in your patch, you get an additonal
improvement when adding some SMT awarness to SD_ASYM_CPUCAPACITY
compared to equalizing the capacity
>
> Of course I need to test with more workloads and I haven't tested it on
> Grace yet, to check if we're regressing something, but in general it seems
> functional.
>
> Now it depends if SD_ASYM_PACKING is the route we want to take or if we
> should start addressing SMT in SD_ASYM_CPUCAPACITY, as pointed by Vincent.
> In general I think I agree with Vincent, independently on this particular
> case, it'd be nice to start improving SD_ASYM_CPUCAPACITY to support SMT.
>
> Thanks,
> -Andrea
^ permalink raw reply
* Re: [RFC][RFT][PATCH 0/3] arm64: Enable asympacking for minor CPPC asymmetry
From: Christian Loehle @ 2026-03-26 8:20 UTC (permalink / raw)
To: Vincent Guittot
Cc: arighi, peterz, dietmar.eggemann, valentin.schneider, mingo,
rostedt, segall, mgorman, catalin.marinas, will, sudeep.holla,
rafael, linux-pm, linux-kernel, juri.lelli, kobak, fabecassis
In-Reply-To: <CAKfTPtAOd2+e1Wyy1uhCzLANh9-KJpR5zc_RSSt+dQvHHxhmMQ@mail.gmail.com>
On 3/26/26 07:53, Vincent Guittot wrote:
> On Wed, 25 Mar 2026 at 19:13, Christian Loehle <christian.loehle@arm.com> wrote:
>>
>> The scheduler currently handles CPU performance asymmetry via either:
>>
>> - SD_ASYM_PACKING: simple priority-based task placement (x86 ITMT)
>> - SD_ASYM_CPUCAPACITY: capacity-aware scheduling
>>
>> On arm64, capacity-aware scheduling is used for any detected capacity
>> differences.
>>
>> Some systems expose small per-CPU performance differences via CPPC
>> highest_perf (e.g. due to chip binning), resulting in slightly different
>> capacities (<~5%). These differences are sufficient to trigger
>> SD_ASYM_CPUCAPACITY, even though the system is otherwise effectively
>> symmetric.
>>
>> For such small deltas, capacity-aware scheduling is unnecessarily
>> complex. A simpler priority-based approach, similar to x86 ITMT, is
>> sufficient.
>
> I'm not convinced that moving to SD_ASYM_PACKING is the right way to
> move forward.
>
> 1st of all, do you target all kind of system or only SMT? It's not
> clear in your cover letter
>
> Moving on asym pack for !SMT doesn't make sense to me. If you don't
> want EAS enabled, you can disable it with
> /proc/sys/kernel/sched_energy_aware
>
> For SMT system and small capacity difference, I would prefer that we
> look at supporting SMT in SD_ASYM_CPUCAPACITY. Starting with
> select_idle_capacity
Quoting the cover letter below, I don't think SMT + SD_ASYM_CPUCAPACITY
can ever be theoretically sound and the results will become so wildly
different on a per-platform / uArch + workload basis, I'm not convinced
something useful would come out of it, but I'd be keen to see some
experiments on this.
IME a busy sibling steals so much more capacity than the difference I care
about here (<5%, busy SMT sibling is often 20-30%, sometimes up to 50% but
entirely dependent on workload and uarch as I've mentioned).
In any case, this series isn't (primarily) for SMT systems...
> [snip]
>> On platforms with SMT though asympacking makes a lot more sense than
>> capacity-aware scheduling, because arguing about capacity without
>> considering utilization of the sibling(s) (and the resulting potential
>> 'stolen' capacity we perceive) isn't theoretically sound.
>>
>> Christian Loehle (3):
>> sched/topology: Introduce arch hooks for asympacking
>> arch_topology: Export CPPC-based asympacking prios
>> arm64/sched: Enable CPPC-based asympacking
>>
>> arch/arm64/include/asm/topology.h | 6 +++++
>> arch/arm64/kernel/topology.c | 34 ++++++++++++++++++++++++++
>> drivers/base/arch_topology.c | 40 +++++++++++++++++++++++++++++++
>> include/linux/arch_topology.h | 24 +++++++++++++++++++
>> include/linux/sched/topology.h | 9 +++++++
>> kernel/sched/fair.c | 16 -------------
>> kernel/sched/topology.c | 34 ++++++++++++++++++++------
>> 7 files changed, 140 insertions(+), 23 deletions(-)
>>
>> --
>> 2.34.1
>>
^ permalink raw reply
* Re: [PATCH v7 2/2] cpufreq: Add boost_freq_req QoS request
From: Zhongqiu Han @ 2026-03-26 8:18 UTC (permalink / raw)
To: Pierre Gondois, linux-kernel
Cc: Lifeng Zheng, Huang Rui, Gautham R. Shenoy, Mario Limonciello,
Perry Yuan, Rafael J. Wysocki, Viresh Kumar, linux-pm,
zhongqiu.han
In-Reply-To: <20260325165255.386576-3-pierre.gondois@arm.com>
On 3/26/2026 12:52 AM, Pierre Gondois wrote:
> The Power Management Quality of Service (PM QoS) allows to
> aggregate constraints from multiple entities. It is currently
> used to manage the min/max frequency of a given policy.
>
> Frequency constraints can come for instance from:
> - Thermal framework: acpi_thermal_cpufreq_init()
> - Firmware: _PPC objects: acpi_processor_ppc_init()
> - User: by setting policyX/scaling_[min|max]_freq
> The minimum of the max frequency constraints is used to compute
> the resulting maximum allowed frequency.
>
> When enabling boost frequencies, the same frequency request object
> (policy->max_freq_req) as to handle requests from users is used.
> As a result, when setting:
> - scaling_max_freq
> - boost
> The last sysfs file used overwrites the request from the other
> sysfs file.
>
> To avoid this, create a per-policy boost_freq_req to save the boost
> constraints instead of overwriting the last scaling_max_freq
> constraint.
>
> policy_set_boost() calls the cpufreq set_boost callback.
> Update the newly added boost_freq_req request from there:
> - whenever boost is toggled
> - to cover all possible paths
>
> In the existing .set_boost() callbacks:
> - Don't update policy->max as this is done through the qos notifier
> cpufreq_notifier_max() which calls cpufreq_set_policy().
> - Remove freq_qos_update_request() calls as the qos request is now
> done in policy_set_boost() and updates the new boost_freq_req
>
> $ ## Init state
> scaling_max_freq:1000000
> cpuinfo_max_freq:1000000
>
> $ echo 700000 > scaling_max_freq
> scaling_max_freq:700000
> cpuinfo_max_freq:1000000
>
> $ echo 1 > ../boost
> scaling_max_freq:1200000
> cpuinfo_max_freq:1200000
>
> $ echo 800000 > scaling_max_freq
> scaling_max_freq:800000
> cpuinfo_max_freq:1200000
>
> $ ## Final step:
> $ ## Without the patches:
> $ echo 0 > ../boost
> scaling_max_freq:1000000
> cpuinfo_max_freq:1000000
>
> $ ## With the patches:
> $ echo 0 > ../boost
> scaling_max_freq:800000
> cpuinfo_max_freq:1000000
>
> Note:
> cpufreq_frequency_table_cpuinfo() updates policy->min
> and max from:
> A.
> cpufreq_boost_set_sw()
> \-cpufreq_frequency_table_cpuinfo()
> B.
> cpufreq_policy_online()
> \-cpufreq_table_validate_and_sort()
> \-cpufreq_frequency_table_cpuinfo()
> Keep these updates as some drivers expect policy->min and
> max to be set through B.
>
> Signed-off-by: Pierre Gondois <pierre.gondois@arm.com>
> ---
> drivers/cpufreq/amd-pstate.c | 2 --
> drivers/cpufreq/cppc_cpufreq.c | 10 ++-----
> drivers/cpufreq/cpufreq.c | 51 ++++++++++++++++++++++++++--------
> include/linux/cpufreq.h | 1 +
> 4 files changed, 43 insertions(+), 21 deletions(-)
>
> diff --git a/drivers/cpufreq/amd-pstate.c b/drivers/cpufreq/amd-pstate.c
> index 5aa9fcd80cf51..d0675d6a19fe1 100644
> --- a/drivers/cpufreq/amd-pstate.c
> +++ b/drivers/cpufreq/amd-pstate.c
> @@ -769,8 +769,6 @@ static int amd_pstate_cpu_boost_update(struct cpufreq_policy *policy, bool on)
> else if (policy->cpuinfo.max_freq > nominal_freq)
> policy->cpuinfo.max_freq = nominal_freq;
>
> - policy->max = policy->cpuinfo.max_freq;
> -
> if (cppc_state == AMD_PSTATE_PASSIVE) {
> ret = freq_qos_update_request(&cpudata->req[1], policy->cpuinfo.max_freq);
> if (ret < 0)
> diff --git a/drivers/cpufreq/cppc_cpufreq.c b/drivers/cpufreq/cppc_cpufreq.c
> index 011f35cb47b94..f4f574fbe547b 100644
> --- a/drivers/cpufreq/cppc_cpufreq.c
> +++ b/drivers/cpufreq/cppc_cpufreq.c
> @@ -807,17 +807,11 @@ static int cppc_cpufreq_set_boost(struct cpufreq_policy *policy, int state)
> {
> struct cppc_cpudata *cpu_data = policy->driver_data;
> struct cppc_perf_caps *caps = &cpu_data->perf_caps;
> - int ret;
>
> if (state)
> - policy->max = cppc_perf_to_khz(caps, caps->highest_perf);
> + policy->cpuinfo.max_freq = cppc_perf_to_khz(caps, caps->highest_perf);
> else
> - policy->max = cppc_perf_to_khz(caps, caps->nominal_perf);
> - policy->cpuinfo.max_freq = policy->max;
> -
> - ret = freq_qos_update_request(policy->max_freq_req, policy->max);
> - if (ret < 0)
> - return ret;
> + policy->cpuinfo.max_freq = cppc_perf_to_khz(caps, caps->nominal_perf);
>
> return 0;
> }
> diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
> index 5757f12633d16..947ed87cf8d76 100644
> --- a/drivers/cpufreq/cpufreq.c
> +++ b/drivers/cpufreq/cpufreq.c
> @@ -609,10 +609,19 @@ static int policy_set_boost(struct cpufreq_policy *policy, bool enable)
> policy->boost_enabled = enable;
>
> ret = cpufreq_driver->set_boost(policy, enable);
> - if (ret)
> + if (ret) {
> policy->boost_enabled = !policy->boost_enabled;
> + return ret;
> + }
>
> - return ret;
> + ret = freq_qos_update_request(policy->boost_freq_req, policy->cpuinfo.max_freq);
Hello Pierre,
Would it be reasonable to add a NULL check for policy->boost_freq_req in
policy_set_boost() before calling freq_qos_update_request(), even though
callers already check policy->boost_supported? Thanks
> + if (ret < 0) {
> + policy->boost_enabled = !policy->boost_enabled;
> + cpufreq_driver->set_boost(policy, policy->boost_enabled);
> + return ret;
> + }
> +
> + return 0;
> }
>
> static ssize_t store_local_boost(struct cpufreq_policy *policy,
> @@ -1377,6 +1386,8 @@ static void cpufreq_policy_free(struct cpufreq_policy *policy)
> }
>
> freq_qos_remove_request(policy->min_freq_req);
> + if (policy->boost_freq_req)
> + freq_qos_remove_request(policy->boost_freq_req);
> kfree(policy->min_freq_req);
>
> cpufreq_policy_put_kobj(policy);
> @@ -1445,18 +1456,42 @@ static int cpufreq_policy_online(struct cpufreq_policy *policy,
> cpumask_and(policy->cpus, policy->cpus, cpu_online_mask);
>
> if (new_policy) {
> + unsigned int req_nr;
> +
> for_each_cpu(j, policy->related_cpus) {
> per_cpu(cpufreq_cpu_data, j) = policy;
> add_cpu_dev_symlink(policy, j, get_cpu_device(j));
> }
>
> - policy->min_freq_req = kzalloc(2 * sizeof(*policy->min_freq_req),
> + req_nr = policy->boost_supported ? 3 : 2;
> + policy->min_freq_req = kzalloc(req_nr * sizeof(*policy->min_freq_req),
> GFP_KERNEL);
> if (!policy->min_freq_req) {
> ret = -ENOMEM;
> goto out_destroy_policy;
> }
>
> + if (policy->boost_supported) {
> + policy->boost_freq_req = policy->min_freq_req + 2;
> +
> + /*
> + * If boost is supported,
> + * init the constraint with cpuinfo.max_freq.
> + */
> + ret = freq_qos_add_request(&policy->constraints,
> + policy->boost_freq_req,
> + FREQ_QOS_MAX,
> + policy->cpuinfo.max_freq);
> + if (ret < 0) {
> + /*
> + * So we don't call freq_qos_remove_request() for an
> + * uninitialized request.
> + */
> + policy->boost_freq_req = NULL;
> + goto out_destroy_policy;
> + }
> + }
> +
> ret = freq_qos_add_request(&policy->constraints,
> policy->min_freq_req, FREQ_QOS_MIN,
> FREQ_QOS_MIN_DEFAULT_VALUE);
> @@ -2788,16 +2823,10 @@ int cpufreq_boost_set_sw(struct cpufreq_policy *policy, int state)
> return -ENXIO;
>
> ret = cpufreq_frequency_table_cpuinfo(policy);
> - if (ret) {
> + if (ret)
> pr_err("%s: Policy frequency update failed\n", __func__);
> - return ret;
> - }
> -
> - ret = freq_qos_update_request(policy->max_freq_req, policy->max);
> - if (ret < 0)
> - return ret;
>
> - return 0;
> + return ret;
> }
> EXPORT_SYMBOL_GPL(cpufreq_boost_set_sw);
>
> diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
> index cc894fc389710..89157e367eefa 100644
> --- a/include/linux/cpufreq.h
> +++ b/include/linux/cpufreq.h
> @@ -81,6 +81,7 @@ struct cpufreq_policy {
> struct freq_constraints constraints;
> struct freq_qos_request *min_freq_req;
> struct freq_qos_request *max_freq_req;
> + struct freq_qos_request *boost_freq_req;
>
> struct cpufreq_frequency_table *freq_table;
> enum cpufreq_table_sorting freq_table_sorted;
--
Thx and BRs,
Zhongqiu Han
^ permalink raw reply
* Re: [RFC][RFT][PATCH 0/3] arm64: Enable asympacking for minor CPPC asymmetry
From: Christian Loehle @ 2026-03-26 8:16 UTC (permalink / raw)
To: Vincent Guittot
Cc: arighi, peterz, dietmar.eggemann, valentin.schneider, mingo,
rostedt, segall, mgorman, catalin.marinas, will, sudeep.holla,
rafael, linux-pm, linux-kernel, juri.lelli, kobak, fabecassis
In-Reply-To: <CAKfTPtAOd2+e1Wyy1uhCzLANh9-KJpR5zc_RSSt+dQvHHxhmMQ@mail.gmail.com>
On 3/26/26 07:53, Vincent Guittot wrote:
> On Wed, 25 Mar 2026 at 19:13, Christian Loehle <christian.loehle@arm.com> wrote:
>>
>> The scheduler currently handles CPU performance asymmetry via either:
>>
>> - SD_ASYM_PACKING: simple priority-based task placement (x86 ITMT)
>> - SD_ASYM_CPUCAPACITY: capacity-aware scheduling
>>
>> On arm64, capacity-aware scheduling is used for any detected capacity
>> differences.
>>
>> Some systems expose small per-CPU performance differences via CPPC
>> highest_perf (e.g. due to chip binning), resulting in slightly different
>> capacities (<~5%). These differences are sufficient to trigger
>> SD_ASYM_CPUCAPACITY, even though the system is otherwise effectively
>> symmetric.
>>
>> For such small deltas, capacity-aware scheduling is unnecessarily
>> complex. A simpler priority-based approach, similar to x86 ITMT, is
>> sufficient.
>
> I'm not convinced that moving to SD_ASYM_PACKING is the right way to
> move forward.
> t
> 1st of all, do you target all kind of system or only SMT? It's not
> clear in your cover letter
AFAIK only Andrea has access to an unreleased asymmetric SMT system,
I haven't done any tests on such a system (as the cover-letter mentions
under RFT section).
>
> Moving on asym pack for !SMT doesn't make sense to me. If you don't
> want EAS enabled, you can disable it with
> /proc/sys/kernel/sched_energy_aware
Sorry, what's EAS got to do with it? The system I care about here
(primarily nvidia grace) has no EM.
>
> For SMT system and small capacity difference, I would prefer that we
> look at supporting SMT in SD_ASYM_CPUCAPACITY. Starting with
> select_idle_capacity
This series is actually targeted for primarily the !SMT case, although
it may or may not be useful for some of the SMT woes, too!
(Again, I wouldn't know, I don't have such a system to test with)
>[snip]
^ permalink raw reply
* Re: [RFC][RFT][PATCH 0/3] arm64: Enable asympacking for minor CPPC asymmetry
From: Andrea Righi @ 2026-03-26 8:11 UTC (permalink / raw)
To: Christian Loehle
Cc: peterz, vincent.guittot, dietmar.eggemann, valentin.schneider,
mingo, rostedt, segall, mgorman, catalin.marinas, will,
sudeep.holla, rafael, linux-pm, linux-kernel, juri.lelli, kobak,
fabecassis
In-Reply-To: <20260325181314.3875909-1-christian.loehle@arm.com>
Hi Christian,
On Wed, Mar 25, 2026 at 06:13:11PM +0000, Christian Loehle wrote:
...
> RFT:
> Andrea, please give this a try. This should perform better in particular
> for single-threaded workloads and workloads that do not utilize all
> cores (all the time anyway).
> Capacity-aware scheduling wakeup works very different to the SMP path
> used now, some workloads will benefit, some regress, it would be nice
> to get some test results for these.
> We already discussed DCPerf MediaWiki seems to benefit from
> capacity-aware scheduling wakeup behavior, but others (most?) should
> benefit from this series.
>
> I don't know if we can also be clever about ordering amongst SMT siblings.
> That would be dependent on the uarch and I don't have a platform to
> experiment with this though, so consider this series orthogonal to the
> idle-core SMT considerations.
> On platforms with SMT though asympacking makes a lot more sense than
> capacity-aware scheduling, because arguing about capacity without
> considering utilization of the sibling(s) (and the resulting potential
> 'stolen' capacity we perceive) isn't theoretically sound.
I did some early testing with this patch set. On Vera I'm getting much
better performance that SD_ASYM_CPUCAPACITY of course (~1.5x avg speedup),
mostly because we avoid using both SMT siblings. It's still not the same
improvement that I get equalizing the capacity using the 5% threshold
(~1.8x speedup).
Of course I need to test with more workloads and I haven't tested it on
Grace yet, to check if we're regressing something, but in general it seems
functional.
Now it depends if SD_ASYM_PACKING is the route we want to take or if we
should start addressing SMT in SD_ASYM_CPUCAPACITY, as pointed by Vincent.
In general I think I agree with Vincent, independently on this particular
case, it'd be nice to start improving SD_ASYM_CPUCAPACITY to support SMT.
Thanks,
-Andrea
^ permalink raw reply
* Re: [PATCH v7 1/2] cpufreq: Remove per-CPU QoS constraint
From: Pierre Gondois @ 2026-03-26 8:10 UTC (permalink / raw)
To: Viresh Kumar
Cc: linux-kernel, Lifeng Zheng, Huang Rui, Gautham R. Shenoy,
Mario Limonciello, Perry Yuan, Rafael J. Wysocki, linux-pm
In-Reply-To: <4e2ui264m6y6u6xmixvt5q2elvxsenco4r2e2axdtue3xuuqf7@rs3qofhtgq7o>
On 3/26/26 05:37, Viresh Kumar wrote:
> What do you mean by per-CPU QOS constraint in Subject ? This is per-policy
> constraint and you are not removing it, you are just avoiding to update it in
> one of the paths.
Right, I ll update the patch header
> On 25-03-26, 17:52, Pierre Gondois wrote:
>> policy->max_freq_req QoS constraint represents the maximal allowed
>> frequency than can be requested. It is set by:
>> - writing to policyX/scaling_max sysfs file
>> - toggling the cpufreq/boost sysfs file
>>
>> Upon calling freq_qos_update_request(), a successful update
>> of the max_freq_req value triggers cpufreq_notifier_max(),
>> followed by cpufreq_set_policy() which update the requested
>> frequency for the policy.
>> If the new max_freq_req value is not different from the
>> original value, no frequency update is triggered.
>>
>> In a specific sequence of toggling:
>> - cpufreq/boost sysfs file
>> - CPU hot-plugging
>> a CPU could end up with boost enabled but running at the
>> maximal non-boost frequency, cpufreq_notifier_max() not being
>> triggered. The following fixed that:
>> commit 1608f0230510 ("cpufreq: Fix re-boost issue after hotplugging
>> a CPU")
>>
>> The following:
>> commit dd016f379ebc ("cpufreq: Introduce a more generic way to
>> set default per-policy boost flag")
>> also fixed the issue by correctly setting the max_freq_req
>> constraint of a policy that is re-activated. This makes the
>> first fix unnecessary.
>>
>> As the original issue is fixed by another method,
>> this patch reverts:
>> commit 1608f0230510 ("cpufreq: Fix re-boost issue after hotplugging
>> a CPU")
> Looks okay otherwise.
>
^ permalink raw reply
* Re: [PATCH v7 2/2] cpufreq: Add boost_freq_req QoS request
From: Pierre Gondois @ 2026-03-26 8:10 UTC (permalink / raw)
To: Viresh Kumar
Cc: linux-kernel, Lifeng Zheng, Huang Rui, Gautham R. Shenoy,
Mario Limonciello, Perry Yuan, Rafael J. Wysocki, linux-pm
In-Reply-To: <6vfexdrwtftix7k4zcyftxxdzbxyrcisegrcuukyy4cbuuioo4@zi6qlmloj4kg>
On 3/26/26 06:03, Viresh Kumar wrote:
> On 25-03-26, 17:52, Pierre Gondois wrote:
>> diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
>> @@ -1445,18 +1456,42 @@ static int cpufreq_policy_online(struct cpufreq_policy *policy,
>> cpumask_and(policy->cpus, policy->cpus, cpu_online_mask);
>>
>> if (new_policy) {
>> + unsigned int req_nr;
> Maybe rename to `count` ?
Ok
>
>> for_each_cpu(j, policy->related_cpus) {
>> per_cpu(cpufreq_cpu_data, j) = policy;
>> add_cpu_dev_symlink(policy, j, get_cpu_device(j));
>> }
>>
>> - policy->min_freq_req = kzalloc(2 * sizeof(*policy->min_freq_req),
>> + req_nr = policy->boost_supported ? 3 : 2;
>> + policy->min_freq_req = kzalloc(req_nr * sizeof(*policy->min_freq_req),
>> GFP_KERNEL);
>> if (!policy->min_freq_req) {
>> ret = -ENOMEM;
>> goto out_destroy_policy;
>> }
>>
>> + if (policy->boost_supported) {
> I would rather add this last: min -> max -> boost.
>
> And change the code in free as:
>
> diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
> index 58e3839a2140..7f5d18da78c6 100644
> --- a/drivers/cpufreq/cpufreq.c
> +++ b/drivers/cpufreq/cpufreq.c
> @@ -1358,17 +1358,18 @@ static void cpufreq_policy_free(struct cpufreq_policy *policy)
> /* Cancel any pending policy->update work before freeing the policy. */
> cancel_work_sync(&policy->update);
>
> - if (policy->max_freq_req) {
> + if (policy->boost_freq_req) {
> /*
> - * Remove max_freq_req after sending CPUFREQ_REMOVE_POLICY
> + * Remove boost_freq_req after sending CPUFREQ_REMOVE_POLICY
> * notification, since CPUFREQ_CREATE_POLICY notification was
> - * sent after adding max_freq_req earlier.
> + * sent after adding boost_freq_req earlier.
> */
> blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
> CPUFREQ_REMOVE_POLICY, policy);
> - freq_qos_remove_request(policy->max_freq_req);
> + freq_qos_remove_request(policy->boost_freq_req);
> }
>
> + freq_qos_remove_request(policy->max_freq_req);
> freq_qos_remove_request(policy->min_freq_req);
> kfree(policy->min_freq_req);
>
>
I thought there was an issue by adding boost last:
not all policies support boost frequencies (and thus requests).
So blocking_notifier_call_chain() should be called if:
+ if ((policy->max_freq_req && !policy->boost_supported) || +
policy->boost_freq_req) {
This was in an earlier version, but Rafael and Lifeng suggested
to add boost_freq_req first to simplify the logic:
https://lore.kernel.org/all/20260225084930.1692228-3-pierre.gondois@arm.com/
>> + policy->boost_freq_req = policy->min_freq_req + 2;
>> +
>> + /*
>> + * If boost is supported,
>> + * init the constraint with cpuinfo.max_freq.
>> + */
> Don't need a comment for obvious code ?
Ok
>
>> + ret = freq_qos_add_request(&policy->constraints,
>> + policy->boost_freq_req,
>> + FREQ_QOS_MAX,
>> + policy->cpuinfo.max_freq);
>> + if (ret < 0) {
>> + /*
>> + * So we don't call freq_qos_remove_request() for an
>> + * uninitialized request.
>> + */
> Actually we are calling freq_qos_remove_request() for NULL values. This comment
> and other exiting ones like this can be removed I guess. They aren't adding much
> value.
>
Ok
^ permalink raw reply
* [PATCH v7 7/8] power: sequencing: pcie-m2: Add support for PCIe M.2 Key E connectors
From: Manivannan Sadhasivam via B4 Relay @ 2026-03-26 8:06 UTC (permalink / raw)
To: Rob Herring, Greg Kroah-Hartman, Jiri Slaby, Nathan Chancellor,
Nicolas Schier, Hans de Goede, Ilpo Järvinen, Mark Pearson,
Derek J. Clark, Manivannan Sadhasivam, Krzysztof Kozlowski,
Conor Dooley, Marcel Holtmann, Luiz Augusto von Dentz,
Bartosz Golaszewski, Andy Shevchenko, Bartosz Golaszewski
Cc: linux-serial, linux-kernel, linux-kbuild, platform-driver-x86,
linux-pci, devicetree, linux-arm-msm, linux-bluetooth, linux-pm,
Stephan Gerhold, Dmitry Baryshkov, linux-acpi,
Manivannan Sadhasivam, Hans de Goede
In-Reply-To: <20260326-pci-m2-e-v7-0-43324a7866e6@oss.qualcomm.com>
From: Manivannan Sadhasivam <manivannan.sadhasivam@oss.qualcomm.com>
Add support for handling the power sequence of the PCIe M.2 Key E
connectors. These connectors are used to attach the Wireless Connectivity
devices to the host machine including combinations of WiFi, BT, NFC using
interfaces such as PCIe/SDIO for WiFi, USB/UART for BT and I2C for NFC.
Currently, this driver supports only the PCIe interface for WiFi and UART
interface for BT. The driver also only supports driving the 3.3v/1.8v power
supplies and W_DISABLE{1/2}# GPIOs. The optional signals of the Key E
connectors are not currently supported.
Tested-by: Hans de Goede <johannes.goede@oss.qualcomm.com> # ThinkPad T14s gen6 (arm64)
Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@oss.qualcomm.com>
---
drivers/power/sequencing/pwrseq-pcie-m2.c | 107 ++++++++++++++++++++++++++++--
1 file changed, 101 insertions(+), 6 deletions(-)
diff --git a/drivers/power/sequencing/pwrseq-pcie-m2.c b/drivers/power/sequencing/pwrseq-pcie-m2.c
index d31a7dd8b35c..3507cdcb1e7b 100644
--- a/drivers/power/sequencing/pwrseq-pcie-m2.c
+++ b/drivers/power/sequencing/pwrseq-pcie-m2.c
@@ -5,10 +5,13 @@
*/
#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_graph.h>
+#include <linux/of_platform.h>
#include <linux/platform_device.h>
#include <linux/pwrseq/provider.h>
#include <linux/regulator/consumer.h>
@@ -25,16 +28,18 @@ struct pwrseq_pcie_m2_ctx {
struct regulator_bulk_data *regs;
size_t num_vregs;
struct notifier_block nb;
+ struct gpio_desc *w_disable1_gpio;
+ struct gpio_desc *w_disable2_gpio;
};
-static int pwrseq_pcie_m2_m_vregs_enable(struct pwrseq_device *pwrseq)
+static int pwrseq_pcie_m2_vregs_enable(struct pwrseq_device *pwrseq)
{
struct pwrseq_pcie_m2_ctx *ctx = pwrseq_device_get_drvdata(pwrseq);
return regulator_bulk_enable(ctx->num_vregs, ctx->regs);
}
-static int pwrseq_pcie_m2_m_vregs_disable(struct pwrseq_device *pwrseq)
+static int pwrseq_pcie_m2_vregs_disable(struct pwrseq_device *pwrseq)
{
struct pwrseq_pcie_m2_ctx *ctx = pwrseq_device_get_drvdata(pwrseq);
@@ -43,18 +48,84 @@ static int pwrseq_pcie_m2_m_vregs_disable(struct pwrseq_device *pwrseq)
static const struct pwrseq_unit_data pwrseq_pcie_m2_vregs_unit_data = {
.name = "regulators-enable",
- .enable = pwrseq_pcie_m2_m_vregs_enable,
- .disable = pwrseq_pcie_m2_m_vregs_disable,
+ .enable = pwrseq_pcie_m2_vregs_enable,
+ .disable = pwrseq_pcie_m2_vregs_disable,
};
-static const struct pwrseq_unit_data *pwrseq_pcie_m2_m_unit_deps[] = {
+static const struct pwrseq_unit_data *pwrseq_pcie_m2_unit_deps[] = {
&pwrseq_pcie_m2_vregs_unit_data,
NULL
};
+static int pwrseq_pci_m2_e_uart_enable(struct pwrseq_device *pwrseq)
+{
+ struct pwrseq_pcie_m2_ctx *ctx = pwrseq_device_get_drvdata(pwrseq);
+
+ return gpiod_set_value_cansleep(ctx->w_disable2_gpio, 0);
+}
+
+static int pwrseq_pci_m2_e_uart_disable(struct pwrseq_device *pwrseq)
+{
+ struct pwrseq_pcie_m2_ctx *ctx = pwrseq_device_get_drvdata(pwrseq);
+
+ return gpiod_set_value_cansleep(ctx->w_disable2_gpio, 1);
+}
+
+static const struct pwrseq_unit_data pwrseq_pcie_m2_e_uart_unit_data = {
+ .name = "uart-enable",
+ .deps = pwrseq_pcie_m2_unit_deps,
+ .enable = pwrseq_pci_m2_e_uart_enable,
+ .disable = pwrseq_pci_m2_e_uart_disable,
+};
+
+static int pwrseq_pci_m2_e_pcie_enable(struct pwrseq_device *pwrseq)
+{
+ struct pwrseq_pcie_m2_ctx *ctx = pwrseq_device_get_drvdata(pwrseq);
+
+ return gpiod_set_value_cansleep(ctx->w_disable1_gpio, 0);
+}
+
+static int pwrseq_pci_m2_e_pcie_disable(struct pwrseq_device *pwrseq)
+{
+ struct pwrseq_pcie_m2_ctx *ctx = pwrseq_device_get_drvdata(pwrseq);
+
+ return gpiod_set_value_cansleep(ctx->w_disable1_gpio, 1);
+}
+
+static const struct pwrseq_unit_data pwrseq_pcie_m2_e_pcie_unit_data = {
+ .name = "pcie-enable",
+ .deps = pwrseq_pcie_m2_unit_deps,
+ .enable = pwrseq_pci_m2_e_pcie_enable,
+ .disable = pwrseq_pci_m2_e_pcie_disable,
+};
+
static const struct pwrseq_unit_data pwrseq_pcie_m2_m_pcie_unit_data = {
.name = "pcie-enable",
- .deps = pwrseq_pcie_m2_m_unit_deps,
+ .deps = pwrseq_pcie_m2_unit_deps,
+};
+
+static int pwrseq_pcie_m2_e_pwup_delay(struct pwrseq_device *pwrseq)
+{
+ /*
+ * FIXME: This delay is only required for some Qcom WLAN/BT cards like
+ * WCN7850 and not for all devices. But currently, there is no way to
+ * identify the device model before enumeration.
+ */
+ msleep(50);
+
+ return 0;
+}
+
+static const struct pwrseq_target_data pwrseq_pcie_m2_e_uart_target_data = {
+ .name = "uart",
+ .unit = &pwrseq_pcie_m2_e_uart_unit_data,
+ .post_enable = pwrseq_pcie_m2_e_pwup_delay,
+};
+
+static const struct pwrseq_target_data pwrseq_pcie_m2_e_pcie_target_data = {
+ .name = "pcie",
+ .unit = &pwrseq_pcie_m2_e_pcie_unit_data,
+ .post_enable = pwrseq_pcie_m2_e_pwup_delay,
};
static const struct pwrseq_target_data pwrseq_pcie_m2_m_pcie_target_data = {
@@ -62,11 +133,21 @@ static const struct pwrseq_target_data pwrseq_pcie_m2_m_pcie_target_data = {
.unit = &pwrseq_pcie_m2_m_pcie_unit_data,
};
+static const struct pwrseq_target_data *pwrseq_pcie_m2_e_targets[] = {
+ &pwrseq_pcie_m2_e_pcie_target_data,
+ &pwrseq_pcie_m2_e_uart_target_data,
+ NULL
+};
+
static const struct pwrseq_target_data *pwrseq_pcie_m2_m_targets[] = {
&pwrseq_pcie_m2_m_pcie_target_data,
NULL
};
+static const struct pwrseq_pcie_m2_pdata pwrseq_pcie_m2_e_of_data = {
+ .targets = pwrseq_pcie_m2_e_targets,
+};
+
static const struct pwrseq_pcie_m2_pdata pwrseq_pcie_m2_m_of_data = {
.targets = pwrseq_pcie_m2_m_targets,
};
@@ -125,6 +206,16 @@ static int pwrseq_pcie_m2_probe(struct platform_device *pdev)
return dev_err_probe(dev, ret,
"Failed to get all regulators\n");
+ ctx->w_disable1_gpio = devm_gpiod_get_optional(dev, "w-disable1", GPIOD_OUT_HIGH);
+ if (IS_ERR(ctx->w_disable1_gpio))
+ return dev_err_probe(dev, PTR_ERR(ctx->w_disable1_gpio),
+ "Failed to get the W_DISABLE_1# GPIO\n");
+
+ ctx->w_disable2_gpio = devm_gpiod_get_optional(dev, "w-disable2", GPIOD_OUT_HIGH);
+ if (IS_ERR(ctx->w_disable2_gpio))
+ return dev_err_probe(dev, PTR_ERR(ctx->w_disable2_gpio),
+ "Failed to get the W_DISABLE_2# GPIO\n");
+
ctx->num_vregs = ret;
ret = devm_add_action_or_reset(dev, pwrseq_pcie_m2_free_regulators, ctx);
@@ -150,6 +241,10 @@ static const struct of_device_id pwrseq_pcie_m2_of_match[] = {
.compatible = "pcie-m2-m-connector",
.data = &pwrseq_pcie_m2_m_of_data,
},
+ {
+ .compatible = "pcie-m2-e-connector",
+ .data = &pwrseq_pcie_m2_e_of_data,
+ },
{ }
};
MODULE_DEVICE_TABLE(of, pwrseq_pcie_m2_of_match);
--
2.51.0
^ permalink raw reply related
* [PATCH v7 6/8] Bluetooth: hci_qca: Add M.2 Bluetooth device support using pwrseq
From: Manivannan Sadhasivam via B4 Relay @ 2026-03-26 8:06 UTC (permalink / raw)
To: Rob Herring, Greg Kroah-Hartman, Jiri Slaby, Nathan Chancellor,
Nicolas Schier, Hans de Goede, Ilpo Järvinen, Mark Pearson,
Derek J. Clark, Manivannan Sadhasivam, Krzysztof Kozlowski,
Conor Dooley, Marcel Holtmann, Luiz Augusto von Dentz,
Bartosz Golaszewski, Andy Shevchenko, Bartosz Golaszewski
Cc: linux-serial, linux-kernel, linux-kbuild, platform-driver-x86,
linux-pci, devicetree, linux-arm-msm, linux-bluetooth, linux-pm,
Stephan Gerhold, Dmitry Baryshkov, linux-acpi,
Manivannan Sadhasivam, Hans de Goede, Bartosz Golaszewski
In-Reply-To: <20260326-pci-m2-e-v7-0-43324a7866e6@oss.qualcomm.com>
From: Manivannan Sadhasivam <manivannan.sadhasivam@oss.qualcomm.com>
Power supply to the M.2 Bluetooth device attached to the host using M.2
connector is controlled using the 'uart' pwrseq device. So add support for
getting the pwrseq device if the OF graph link is present. Once obtained,
the existing pwrseq APIs can be used to control the power supplies of the
M.2 card.
Tested-by: Hans de Goede <johannes.goede@oss.qualcomm.com> # ThinkPad T14s gen6 (arm64)
Reviewed-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@oss.qualcomm.com>
---
drivers/bluetooth/hci_qca.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c
index c17a462aef55..aaac3fb67d18 100644
--- a/drivers/bluetooth/hci_qca.c
+++ b/drivers/bluetooth/hci_qca.c
@@ -26,6 +26,7 @@
#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/of.h>
+#include <linux/of_graph.h>
#include <linux/acpi.h>
#include <linux/platform_device.h>
#include <linux/pwrseq/consumer.h>
@@ -2443,6 +2444,14 @@ static int qca_serdev_probe(struct serdev_device *serdev)
case QCA_WCN6750:
case QCA_WCN6855:
case QCA_WCN7850:
+ if (of_graph_is_present(dev_of_node(&serdev->ctrl->dev))) {
+ qcadev->bt_power->pwrseq = devm_pwrseq_get(&serdev->ctrl->dev,
+ "uart");
+ if (IS_ERR(qcadev->bt_power->pwrseq))
+ return PTR_ERR(qcadev->bt_power->pwrseq);
+ break;
+ }
+
if (!device_property_present(&serdev->dev, "enable-gpios")) {
/*
* Backward compatibility with old DT sources. If the
--
2.51.0
^ permalink raw reply related
* [PATCH v7 8/8] power: sequencing: pcie-m2: Create serdev device for WCN7850 bluetooth
From: Manivannan Sadhasivam via B4 Relay @ 2026-03-26 8:06 UTC (permalink / raw)
To: Rob Herring, Greg Kroah-Hartman, Jiri Slaby, Nathan Chancellor,
Nicolas Schier, Hans de Goede, Ilpo Järvinen, Mark Pearson,
Derek J. Clark, Manivannan Sadhasivam, Krzysztof Kozlowski,
Conor Dooley, Marcel Holtmann, Luiz Augusto von Dentz,
Bartosz Golaszewski, Andy Shevchenko, Bartosz Golaszewski
Cc: linux-serial, linux-kernel, linux-kbuild, platform-driver-x86,
linux-pci, devicetree, linux-arm-msm, linux-bluetooth, linux-pm,
Stephan Gerhold, Dmitry Baryshkov, linux-acpi,
Manivannan Sadhasivam, Hans de Goede
In-Reply-To: <20260326-pci-m2-e-v7-0-43324a7866e6@oss.qualcomm.com>
From: Manivannan Sadhasivam <manivannan.sadhasivam@oss.qualcomm.com>
For supporting bluetooth over the non-discoverable UART interface of
WCN7850, create the serdev device after enumerating the PCIe interface.
This is mandatory since the device ID is only known after the PCIe
enumeration and the ID is used for creating the serdev device.
Since by default there is no OF or ACPI node for the created serdev,
create a dynamic OF 'bluetooth' node with the 'compatible' property and
attach it to the serdev device. This will allow the serdev device to bind
to the existing bluetooth driver.
Tested-by: Hans de Goede <johannes.goede@oss.qualcomm.com> # ThinkPad T14s gen6 (arm64)
Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@oss.qualcomm.com>
---
drivers/power/sequencing/Kconfig | 3 +-
drivers/power/sequencing/pwrseq-pcie-m2.c | 253 ++++++++++++++++++++++++++++--
2 files changed, 240 insertions(+), 16 deletions(-)
diff --git a/drivers/power/sequencing/Kconfig b/drivers/power/sequencing/Kconfig
index f5fff84566ba..1ec142525a4a 100644
--- a/drivers/power/sequencing/Kconfig
+++ b/drivers/power/sequencing/Kconfig
@@ -37,7 +37,8 @@ config POWER_SEQUENCING_TH1520_GPU
config POWER_SEQUENCING_PCIE_M2
tristate "PCIe M.2 connector power sequencing driver"
- depends on OF || COMPILE_TEST
+ depends on (PCI && OF) || COMPILE_TEST
+ select OF_DYNAMIC if OF
help
Say Y here to enable the power sequencing driver for PCIe M.2
connectors. This driver handles the power sequencing for the M.2
diff --git a/drivers/power/sequencing/pwrseq-pcie-m2.c b/drivers/power/sequencing/pwrseq-pcie-m2.c
index 3507cdcb1e7b..a75ca4fda2eb 100644
--- a/drivers/power/sequencing/pwrseq-pcie-m2.c
+++ b/drivers/power/sequencing/pwrseq-pcie-m2.c
@@ -12,9 +12,11 @@
#include <linux/of.h>
#include <linux/of_graph.h>
#include <linux/of_platform.h>
+#include <linux/pci.h>
#include <linux/platform_device.h>
#include <linux/pwrseq/provider.h>
#include <linux/regulator/consumer.h>
+#include <linux/serdev.h>
#include <linux/slab.h>
struct pwrseq_pcie_m2_pdata {
@@ -30,6 +32,9 @@ struct pwrseq_pcie_m2_ctx {
struct notifier_block nb;
struct gpio_desc *w_disable1_gpio;
struct gpio_desc *w_disable2_gpio;
+ struct serdev_device *serdev;
+ struct of_changeset *ocs;
+ struct device *dev;
};
static int pwrseq_pcie_m2_vregs_enable(struct pwrseq_device *pwrseq)
@@ -172,11 +177,202 @@ static int pwrseq_pcie_m2_match(struct pwrseq_device *pwrseq,
return PWRSEQ_NO_MATCH;
}
-static void pwrseq_pcie_m2_free_regulators(void *data)
+static int pwrseq_m2_pcie_create_bt_node(struct pwrseq_pcie_m2_ctx *ctx,
+ struct device_node *parent)
{
- struct pwrseq_pcie_m2_ctx *ctx = data;
+ struct device *dev = ctx->dev;
+ struct device_node *np;
+ int ret;
- regulator_bulk_free(ctx->num_vregs, ctx->regs);
+ ctx->ocs = kzalloc_obj(*ctx->ocs);
+ if (!ctx->ocs)
+ return -ENOMEM;
+
+ of_changeset_init(ctx->ocs);
+
+ np = of_changeset_create_node(ctx->ocs, parent, "bluetooth");
+ if (!np) {
+ dev_err(dev, "Failed to create bluetooth node\n");
+ ret = -ENODEV;
+ goto err_destroy_changeset;
+ }
+
+ ret = of_changeset_add_prop_string(ctx->ocs, np, "compatible", "qcom,wcn7850-bt");
+ if (ret) {
+ dev_err(dev, "Failed to add bluetooth compatible: %d\n", ret);
+ goto err_destroy_changeset;
+ }
+
+ ret = of_changeset_apply(ctx->ocs);
+ if (ret) {
+ dev_err(dev, "Failed to apply changeset: %d\n", ret);
+ goto err_destroy_changeset;
+ }
+
+ ret = device_add_of_node(&ctx->serdev->dev, np);
+ if (ret) {
+ dev_err(dev, "Failed to add OF node: %d\n", ret);
+ goto err_revert_changeset;
+ }
+
+ return 0;
+
+err_revert_changeset:
+ of_changeset_revert(ctx->ocs);
+err_destroy_changeset:
+ of_changeset_destroy(ctx->ocs);
+ kfree(ctx->ocs);
+ ctx->ocs = NULL;
+
+ return ret;
+}
+
+static int pwrseq_pcie_m2_create_serdev(struct pwrseq_pcie_m2_ctx *ctx)
+{
+ struct serdev_controller *serdev_ctrl;
+ struct device *dev = ctx->dev;
+ int ret;
+
+ struct device_node *serdev_parent __free(device_node) =
+ of_graph_get_remote_node(dev_of_node(ctx->dev), 3, 0);
+ if (!serdev_parent)
+ return 0;
+
+ serdev_ctrl = of_find_serdev_controller_by_node(serdev_parent);
+ if (!serdev_ctrl)
+ return 0;
+
+ /* Bail out if the device was already attached to this controller */
+ if (serdev_ctrl->serdev) {
+ serdev_controller_put(serdev_ctrl);
+ return 0;
+ }
+
+ ctx->serdev = serdev_device_alloc(serdev_ctrl);
+ if (!ctx->serdev) {
+ ret = -ENOMEM;
+ goto err_put_ctrl;
+ }
+
+ ret = pwrseq_m2_pcie_create_bt_node(ctx, serdev_parent);
+ if (ret)
+ goto err_free_serdev;
+
+ ret = serdev_device_add(ctx->serdev);
+ if (ret) {
+ dev_err(dev, "Failed to add serdev for WCN7850: %d\n", ret);
+ goto err_free_dt_node;
+ }
+
+ serdev_controller_put(serdev_ctrl);
+
+ return 0;
+
+err_free_dt_node:
+ device_remove_of_node(&ctx->serdev->dev);
+ of_changeset_revert(ctx->ocs);
+ of_changeset_destroy(ctx->ocs);
+ kfree(ctx->ocs);
+ ctx->ocs = NULL;
+err_free_serdev:
+ serdev_device_put(ctx->serdev);
+ ctx->serdev = NULL;
+err_put_ctrl:
+ serdev_controller_put(serdev_ctrl);
+
+ return ret;
+}
+
+static void pwrseq_pcie_m2_remove_serdev(struct pwrseq_pcie_m2_ctx *ctx)
+{
+ if (ctx->serdev) {
+ device_remove_of_node(&ctx->serdev->dev);
+ serdev_device_remove(ctx->serdev);
+ ctx->serdev = NULL;
+ }
+
+ if (ctx->ocs) {
+ of_changeset_revert(ctx->ocs);
+ of_changeset_destroy(ctx->ocs);
+ kfree(ctx->ocs);
+ ctx->ocs = NULL;
+ }
+}
+
+static int pwrseq_m2_pcie_notify(struct notifier_block *nb, unsigned long action,
+ void *data)
+{
+ struct pwrseq_pcie_m2_ctx *ctx = container_of(nb, struct pwrseq_pcie_m2_ctx, nb);
+ struct pci_dev *pdev = to_pci_dev(data);
+ int ret;
+
+ /*
+ * Check whether the PCI device is associated with this M.2 connector or
+ * not, by comparing the OF node of the PCI device parent and the Port 0
+ * (PCIe) remote node parent OF node.
+ */
+ struct device_node *pci_parent __free(device_node) =
+ of_graph_get_remote_node(dev_of_node(ctx->dev), 0, 0);
+ if (!pci_parent || (pci_parent != pdev->dev.parent->of_node))
+ return NOTIFY_DONE;
+
+ switch (action) {
+ case BUS_NOTIFY_ADD_DEVICE:
+ /* Create serdev device for WCN7850 */
+ if (pdev->vendor == PCI_VENDOR_ID_QCOM && pdev->device == 0x1107) {
+ ret = pwrseq_pcie_m2_create_serdev(ctx);
+ if (ret)
+ return notifier_from_errno(ret);
+ }
+ break;
+ case BUS_NOTIFY_REMOVED_DEVICE:
+ /* Destroy serdev device for WCN7850 */
+ if (pdev->vendor == PCI_VENDOR_ID_QCOM && pdev->device == 0x1107)
+ pwrseq_pcie_m2_remove_serdev(ctx);
+
+ break;
+ }
+
+ return NOTIFY_OK;
+}
+
+static bool pwrseq_pcie_m2_check_remote_node(struct device *dev, u8 port, u8 endpoint,
+ const char *node)
+{
+ struct device_node *remote __free(device_node) =
+ of_graph_get_remote_node(dev_of_node(dev), port, endpoint);
+
+ if (remote && of_node_name_eq(remote, node))
+ return true;
+
+ return false;
+}
+
+/*
+ * If the connector exposes a non-discoverable bus like UART, the respective
+ * protocol device needs to be created manually with the help of the notifier
+ * of the discoverable bus like PCIe.
+ */
+static int pwrseq_pcie_m2_register_notifier(struct pwrseq_pcie_m2_ctx *ctx, struct device *dev)
+{
+ int ret;
+
+ /*
+ * Register a PCI notifier for Key E connector that has PCIe as Port
+ * 0/Endpoint 0 interface and Serial as Port 3/Endpoint 0 interface.
+ */
+ if (pwrseq_pcie_m2_check_remote_node(dev, 3, 0, "serial")) {
+ if (pwrseq_pcie_m2_check_remote_node(dev, 0, 0, "pcie")) {
+ ctx->dev = dev;
+ ctx->nb.notifier_call = pwrseq_m2_pcie_notify;
+ ret = bus_register_notifier(&pci_bus_type, &ctx->nb);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "Failed to register notifier for serdev\n");
+ }
+ }
+
+ return 0;
}
static int pwrseq_pcie_m2_probe(struct platform_device *pdev)
@@ -190,6 +386,7 @@ static int pwrseq_pcie_m2_probe(struct platform_device *pdev)
if (!ctx)
return -ENOMEM;
+ platform_set_drvdata(pdev, ctx);
ctx->of_node = of_node_get(dev->of_node);
ctx->pdata = device_get_match_data(dev);
if (!ctx->pdata)
@@ -206,21 +403,21 @@ static int pwrseq_pcie_m2_probe(struct platform_device *pdev)
return dev_err_probe(dev, ret,
"Failed to get all regulators\n");
+ ctx->num_vregs = ret;
+
ctx->w_disable1_gpio = devm_gpiod_get_optional(dev, "w-disable1", GPIOD_OUT_HIGH);
- if (IS_ERR(ctx->w_disable1_gpio))
- return dev_err_probe(dev, PTR_ERR(ctx->w_disable1_gpio),
+ if (IS_ERR(ctx->w_disable1_gpio)) {
+ ret = dev_err_probe(dev, PTR_ERR(ctx->w_disable1_gpio),
"Failed to get the W_DISABLE_1# GPIO\n");
+ goto err_free_regulators;
+ }
ctx->w_disable2_gpio = devm_gpiod_get_optional(dev, "w-disable2", GPIOD_OUT_HIGH);
- if (IS_ERR(ctx->w_disable2_gpio))
- return dev_err_probe(dev, PTR_ERR(ctx->w_disable2_gpio),
+ if (IS_ERR(ctx->w_disable2_gpio)) {
+ ret = dev_err_probe(dev, PTR_ERR(ctx->w_disable2_gpio),
"Failed to get the W_DISABLE_2# GPIO\n");
-
- ctx->num_vregs = ret;
-
- ret = devm_add_action_or_reset(dev, pwrseq_pcie_m2_free_regulators, ctx);
- if (ret)
- return ret;
+ goto err_free_regulators;
+ }
config.parent = dev;
config.owner = THIS_MODULE;
@@ -229,11 +426,36 @@ static int pwrseq_pcie_m2_probe(struct platform_device *pdev)
config.targets = ctx->pdata->targets;
ctx->pwrseq = devm_pwrseq_device_register(dev, &config);
- if (IS_ERR(ctx->pwrseq))
- return dev_err_probe(dev, PTR_ERR(ctx->pwrseq),
+ if (IS_ERR(ctx->pwrseq)) {
+ ret = dev_err_probe(dev, PTR_ERR(ctx->pwrseq),
"Failed to register the power sequencer\n");
+ goto err_free_regulators;
+ }
+
+ /*
+ * Register a notifier for creating protocol devices for
+ * non-discoverable busses like UART.
+ */
+ ret = pwrseq_pcie_m2_register_notifier(ctx, dev);
+ if (ret)
+ goto err_free_regulators;
return 0;
+
+err_free_regulators:
+ regulator_bulk_free(ctx->num_vregs, ctx->regs);
+
+ return ret;
+}
+
+static void pwrseq_pcie_m2_remove(struct platform_device *pdev)
+{
+ struct pwrseq_pcie_m2_ctx *ctx = platform_get_drvdata(pdev);
+
+ bus_unregister_notifier(&pci_bus_type, &ctx->nb);
+ pwrseq_pcie_m2_remove_serdev(ctx);
+
+ regulator_bulk_free(ctx->num_vregs, ctx->regs);
}
static const struct of_device_id pwrseq_pcie_m2_of_match[] = {
@@ -255,6 +477,7 @@ static struct platform_driver pwrseq_pcie_m2_driver = {
.of_match_table = pwrseq_pcie_m2_of_match,
},
.probe = pwrseq_pcie_m2_probe,
+ .remove = pwrseq_pcie_m2_remove,
};
module_platform_driver(pwrseq_pcie_m2_driver);
--
2.51.0
^ permalink raw reply related
* [PATCH v7 5/8] dt-bindings: connector: Add PCIe M.2 Mechanical Key E connector
From: Manivannan Sadhasivam via B4 Relay @ 2026-03-26 8:06 UTC (permalink / raw)
To: Rob Herring, Greg Kroah-Hartman, Jiri Slaby, Nathan Chancellor,
Nicolas Schier, Hans de Goede, Ilpo Järvinen, Mark Pearson,
Derek J. Clark, Manivannan Sadhasivam, Krzysztof Kozlowski,
Conor Dooley, Marcel Holtmann, Luiz Augusto von Dentz,
Bartosz Golaszewski, Andy Shevchenko, Bartosz Golaszewski
Cc: linux-serial, linux-kernel, linux-kbuild, platform-driver-x86,
linux-pci, devicetree, linux-arm-msm, linux-bluetooth, linux-pm,
Stephan Gerhold, Dmitry Baryshkov, linux-acpi,
Manivannan Sadhasivam
In-Reply-To: <20260326-pci-m2-e-v7-0-43324a7866e6@oss.qualcomm.com>
From: Manivannan Sadhasivam <manivannan.sadhasivam@oss.qualcomm.com>
Add the devicetree binding for PCIe M.2 Mechanical Key E connector defined
in the PCI Express M.2 Specification, r4.0, sec 5.1.2. This connector
provides interfaces like PCIe or SDIO to attach the WiFi devices to the
host machine, USB or UART+PCM interfaces to attach the Bluetooth (BT)
devices. Spec also provides an optional interface to connect the UIM card,
but that is not covered in this binding.
The connector provides a primary power supply of 3.3v, along with an
optional 1.8v VIO supply for the Adapter I/O buffer circuitry operating at
1.8v sideband signaling.
The connector also supplies optional signals in the form of GPIOs for fine
grained power management.
Reviewed-by: Rob Herring (Arm) <robh@kernel.org>
Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@oss.qualcomm.com>
---
.../bindings/connector/pcie-m2-e-connector.yaml | 184 +++++++++++++++++++++
MAINTAINERS | 1 +
2 files changed, 185 insertions(+)
diff --git a/Documentation/devicetree/bindings/connector/pcie-m2-e-connector.yaml b/Documentation/devicetree/bindings/connector/pcie-m2-e-connector.yaml
new file mode 100644
index 000000000000..f7859aa9b634
--- /dev/null
+++ b/Documentation/devicetree/bindings/connector/pcie-m2-e-connector.yaml
@@ -0,0 +1,184 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/connector/pcie-m2-e-connector.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: PCIe M.2 Mechanical Key E Connector
+
+maintainers:
+ - Manivannan Sadhasivam <manivannan.sadhasivam@oss.qualcomm.com>
+
+description:
+ A PCIe M.2 E connector node represents a physical PCIe M.2 Mechanical Key E
+ connector. Mechanical Key E connectors are used to connect Wireless
+ Connectivity devices including combinations of Wi-Fi, BT, NFC to the host
+ machine over interfaces like PCIe/SDIO, USB/UART+PCM, and I2C.
+
+properties:
+ compatible:
+ const: pcie-m2-e-connector
+
+ vpcie3v3-supply:
+ description: A phandle to the regulator for 3.3v supply.
+
+ vpcie1v8-supply:
+ description: A phandle to the regulator for VIO 1.8v supply.
+
+ i2c-parent:
+ $ref: /schemas/types.yaml#/definitions/phandle
+ description: I2C interface
+
+ clocks:
+ description: 32.768 KHz Suspend Clock (SUSCLK) input from the host system to
+ the M.2 card. Refer, PCI Express M.2 Specification r4.0, sec 3.1.12.1 for
+ more details.
+ maxItems: 1
+
+ w-disable1-gpios:
+ description: GPIO output to W_DISABLE1# signal. This signal is used by the
+ host system to disable WiFi radio in the M.2 card. Refer, PCI Express M.2
+ Specification r4.0, sec 3.1.12.3 for more details.
+ maxItems: 1
+
+ w-disable2-gpios:
+ description: GPIO output to W_DISABLE2# signal. This signal is used by the
+ host system to disable BT radio in the M.2 card. Refer, PCI Express M.2
+ Specification r4.0, sec 3.1.12.3 for more details.
+ maxItems: 1
+
+ viocfg-gpios:
+ description: GPIO input to IO voltage configuration (VIO_CFG) signal. The
+ card drives this signal to indicate to the host system whether the card
+ supports an independent IO voltage domain for sideband signals. Refer,
+ PCI Express M.2 Specification r4.0, sec 3.1.15.1 for more details.
+ maxItems: 1
+
+ uart-wake-gpios:
+ description: GPIO input to UART_WAKE# signal. The card asserts this signal
+ to wake the host system and initiate UART interface communication. Refer,
+ PCI Express M.2 Specification r4.0, sec 3.1.8.1 for more details.
+ maxItems: 1
+
+ sdio-wake-gpios:
+ description: GPIO input to SDIO_WAKE# signal. The card asserts this signal
+ to wake the host system and initiate SDIO interface communication. Refer,
+ PCI Express M.2 Specification r4.0, sec 3.1.7 for more details.
+ maxItems: 1
+
+ sdio-reset-gpios:
+ description: GPIO output to SDIO_RESET# signal. This signal is used by the
+ host system to reset SDIO interface of the M.2 card. Refer, PCI Express
+ M.2 Specification r4.0, sec 3.1.7 for more details.
+ maxItems: 1
+
+ vendor-porta-gpios:
+ description: GPIO for the first vendor specific signal (VENDOR_PORTA). This
+ signal's functionality is defined by the card manufacturer and may be
+ used for proprietary features. Refer the card vendor's documentation for
+ details.
+ maxItems: 1
+
+ vendor-portb-gpios:
+ description: GPIO for the second vendor specific signal (VENDOR_PORTB). This
+ signal's functionality is defined by the card manufacturer and may be
+ used for proprietary features. Refer the card vendor's documentation for
+ details.
+ maxItems: 1
+
+ vendor-portc-gpios:
+ description: GPIO for the third vendor specific signal (VENDOR_PORTC). This
+ signal's functionality is defined by the card manufacturer and may be
+ used for proprietary features. Refer the card vendor's documentation for
+ details.
+ maxItems: 1
+
+ ports:
+ $ref: /schemas/graph.yaml#/properties/ports
+ description: OF graph bindings modeling the interfaces exposed on the
+ connector. Since a single connector can have multiple interfaces, every
+ interface has an assigned OF graph port number as described below.
+
+ properties:
+ port@0:
+ $ref: /schemas/graph.yaml#/properties/port
+ description: PCIe interface for Wi-Fi
+
+ port@1:
+ $ref: /schemas/graph.yaml#/properties/port
+ description: SDIO interface for Wi-Fi
+
+ port@2:
+ $ref: /schemas/graph.yaml#/properties/port
+ description: USB 2.0 interface for BT
+
+ port@3:
+ $ref: /schemas/graph.yaml#/properties/port
+ description: UART interface for BT
+
+ port@4:
+ $ref: /schemas/graph.yaml#/properties/port
+ description: PCM/I2S interface
+
+ anyOf:
+ - anyOf:
+ - required:
+ - port@0
+ - required:
+ - port@1
+ - anyOf:
+ - required:
+ - port@2
+ - required:
+ - port@3
+
+required:
+ - compatible
+ - vpcie3v3-supply
+
+additionalProperties: false
+
+examples:
+ # PCI M.2 Key E connector for Wi-Fi/BT with PCIe/UART interfaces
+ - |
+ #include <dt-bindings/gpio/gpio.h>
+
+ connector {
+ compatible = "pcie-m2-e-connector";
+ vpcie3v3-supply = <&vreg_wcn_3p3>;
+ vpcie1v8-supply = <&vreg_l15b_1p8>;
+ i2c-parent = <&i2c0>;
+ w-disable1-gpios = <&tlmm 115 GPIO_ACTIVE_LOW>;
+ w-disable2-gpios = <&tlmm 116 GPIO_ACTIVE_LOW>;
+ viocfg-gpios = <&tlmm 117 GPIO_ACTIVE_HIGH>;
+ uart-wake-gpios = <&tlmm 118 GPIO_ACTIVE_LOW>;
+ sdio-wake-gpios = <&tlmm 119 GPIO_ACTIVE_LOW>;
+ sdio-reset-gpios = <&tlmm 120 GPIO_ACTIVE_LOW>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ endpoint@0 {
+ reg = <0>;
+ remote-endpoint = <&pcie4_port0_ep>;
+ };
+ };
+
+ port@3 {
+ reg = <3>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ endpoint@0 {
+ reg = <0>;
+ remote-endpoint = <&uart14_ep>;
+ };
+ };
+ };
+ };
diff --git a/MAINTAINERS b/MAINTAINERS
index a38fe0ed7144..bd72ce52f00c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -21029,6 +21029,7 @@ PCIE M.2 POWER SEQUENCING
M: Manivannan Sadhasivam <mani@kernel.org>
L: linux-pci@vger.kernel.org
S: Maintained
+F: Documentation/devicetree/bindings/connector/pcie-m2-e-connector.yaml
F: Documentation/devicetree/bindings/connector/pcie-m2-m-connector.yaml
F: drivers/power/sequencing/pwrseq-pcie-m2.c
--
2.51.0
^ permalink raw reply related
* [PATCH v7 4/8] dt-bindings: serial: Document the graph port
From: Manivannan Sadhasivam via B4 Relay @ 2026-03-26 8:06 UTC (permalink / raw)
To: Rob Herring, Greg Kroah-Hartman, Jiri Slaby, Nathan Chancellor,
Nicolas Schier, Hans de Goede, Ilpo Järvinen, Mark Pearson,
Derek J. Clark, Manivannan Sadhasivam, Krzysztof Kozlowski,
Conor Dooley, Marcel Holtmann, Luiz Augusto von Dentz,
Bartosz Golaszewski, Andy Shevchenko, Bartosz Golaszewski
Cc: linux-serial, linux-kernel, linux-kbuild, platform-driver-x86,
linux-pci, devicetree, linux-arm-msm, linux-bluetooth, linux-pm,
Stephan Gerhold, Dmitry Baryshkov, linux-acpi,
Manivannan Sadhasivam, Bartosz Golaszewski
In-Reply-To: <20260326-pci-m2-e-v7-0-43324a7866e6@oss.qualcomm.com>
From: Manivannan Sadhasivam <manivannan.sadhasivam@oss.qualcomm.com>
A serial controller could be connected to an external connector like PCIe
M.2 for controlling the serial interface of the card. Hence, document the
OF graph port.
Reviewed-by: Rob Herring (Arm) <robh@kernel.org>
Reviewed-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@oss.qualcomm.com>
---
Documentation/devicetree/bindings/serial/serial.yaml | 3 +++
1 file changed, 3 insertions(+)
diff --git a/Documentation/devicetree/bindings/serial/serial.yaml b/Documentation/devicetree/bindings/serial/serial.yaml
index 6aa9cfae417b..96eb1de8771e 100644
--- a/Documentation/devicetree/bindings/serial/serial.yaml
+++ b/Documentation/devicetree/bindings/serial/serial.yaml
@@ -87,6 +87,9 @@ properties:
description:
TX FIFO threshold configuration (in bytes).
+ port:
+ $ref: /schemas/graph.yaml#/properties/port
+
patternProperties:
"^(bluetooth|bluetooth-gnss|embedded-controller|gnss|gps|mcu|onewire)$":
if:
--
2.51.0
^ permalink raw reply related
* [PATCH v7 0/8] Add support for handling PCIe M.2 Key E connectors in devicetree
From: Manivannan Sadhasivam via B4 Relay @ 2026-03-26 8:06 UTC (permalink / raw)
To: Rob Herring, Greg Kroah-Hartman, Jiri Slaby, Nathan Chancellor,
Nicolas Schier, Hans de Goede, Ilpo Järvinen, Mark Pearson,
Derek J. Clark, Manivannan Sadhasivam, Krzysztof Kozlowski,
Conor Dooley, Marcel Holtmann, Luiz Augusto von Dentz,
Bartosz Golaszewski, Andy Shevchenko, Bartosz Golaszewski
Cc: linux-serial, linux-kernel, linux-kbuild, platform-driver-x86,
linux-pci, devicetree, linux-arm-msm, linux-bluetooth, linux-pm,
Stephan Gerhold, Dmitry Baryshkov, linux-acpi,
Manivannan Sadhasivam, Hans de Goede, Bartosz Golaszewski,
Bartosz Golaszewski
Hi,
This series is the continuation of the series [1] that added the initial support
for the PCIe M.2 connectors. This series extends it by adding support for Key E
connectors. These connectors are used to connect the Wireless Connectivity
devices such as WiFi, BT, NFC and GNSS devices to the host machine over
interfaces such as PCIe/SDIO, USB/UART and NFC. This series adds support for
connectors that expose PCIe interface for WiFi and UART interface for BT. Other
interfaces are left for future improvements.
Serdev device support for BT
============================
Adding support for the PCIe interface was mostly straightforward and a lot
similar to the previous Key M connector. But adding UART interface has proved to
be tricky. This is mostly because of the fact UART is a non-discoverable bus,
unlike PCIe which is discoverable. So this series relied on the PCI notifier to
create the serdev device for UART/BT. This means the PCIe interface will be
brought up first and after the PCIe device enumeration, the serdev device will
be created by the pwrseq driver. This logic is necessary since the connector
driver and DT node don't describe the device, but just the connector. So to make
the connector interface Plug and Play, the connector driver uses the PCIe device
ID to identify the card and creates the serdev device. This logic could be
extended in the future to support more M.2 cards. Even if the M.2 card uses SDIO
interface for connecting WLAN, a SDIO notifier could be added to create the
serdev device.
Testing
=======
This series, together with the devicetree changes [2] was tested on the
Qualcomm X1e based Lenovo Thinkpad T14s Laptop which has the WCN7850 WLAN/BT
1620 LGA card connected over PCIe and UART.
Merge Strategy
==============
Due to the API dependency, both the serdev and pwrseq patches need to go through
a single tree, maybe through pwrseq tree. So the serdev patches need Ack from
Greg. But Bluetooth patch can be merged separately.
NOTE
====
This series is based on bluetooth-next/master to resolve the conflict with the
Bluetooth patch. Other pathces should apply cleanly on top of v7.0-rc1.
[1] https://lore.kernel.org/linux-pci/20260107-pci-m2-v5-0-8173d8a72641@oss.qualcomm.com
[2] https://github.com/Mani-Sadhasivam/linux/commit/b50f8386900990eed3dce8d91c3b643fb0e8739d
Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@oss.qualcomm.com>
---
Changes in v7:
- Dropped the LGA binding change due to vendor prefix concern. This will be
submitted later once I get clarity.
- Fixed several issues in the cleanup path of the pwrseq-pci-m2 driver which
includes adding the .remove() callback.
- Rebased on top of bluetooth-next/master to resolve conflict with bluetooth
patch.
- Link to v6: https://lore.kernel.org/r/20260317-pci-m2-e-v6-0-9c898f108d3d@oss.qualcomm.com
Changes in v6:
- Added a check to bail out if the serdev device was already added during notifier.
- Collected tags
- Link to v5: https://lore.kernel.org/r/20260224-pci-m2-e-v5-0-dd9b9501d33c@oss.qualcomm.com
Changes in v5:
- Incorporated comments in the binding patch by using single endpoint per port,
reordering port nodes, adding missing properties and using a complete example.
- Incorporated comments in the pwrseq patch (nothing major)
- Fixed the build issue in patch 2
- Collected tags
- Rebased on top of 7.0-rc1
- Link to v4: https://lore.kernel.org/r/20260112-pci-m2-e-v4-0-eff84d2c6d26@oss.qualcomm.com
Changes in v4:
- Switched to dynamic OF node for serdev instead of swnode and dropped all
swnode related patches
- Link to v3: https://lore.kernel.org/r/20260110-pci-m2-e-v3-0-4faee7d0d5ae@oss.qualcomm.com
Changes in v3:
- Switched to swnode for the serdev device and dropped the custom
serdev_device_id related patches
- Added new swnode APIs to match the swnode with existing of_device_id
- Incorporated comments in the bindings patch
- Dropped the UIM interface from binding since it is not clear how it should get
wired
- Incorporated comments in the pwrseq driver patch
- Splitted the pwrseq patch into two
- Added the 1620 LGA compatible with Key E fallback based on Stephan's finding
- Link to v2: https://lore.kernel.org/r/20251125-pci-m2-e-v2-0-32826de07cc5@oss.qualcomm.com
Changes in v2:
- Used '-' for GPIO names in the binding and removed led*-gpios properties
- Described the endpoint nodes for port@0 and port@1 nodes
- Added the OF graph port to the serial binding
- Fixed the hci_qca driver to return err if devm_pwrseq_get() fails
- Incorporated various review comments in pwrseq driver
- Collected Ack
- Link to v1: https://lore.kernel.org/r/20251112-pci-m2-e-v1-0-97413d6bf824@oss.qualcomm.com
---
Manivannan Sadhasivam (8):
serdev: Convert to_serdev_*() helpers to macros and use container_of_const()
serdev: Add an API to find the serdev controller associated with the devicetree node
serdev: Do not return -ENODEV from of_serdev_register_devices() if external connector is used
dt-bindings: serial: Document the graph port
dt-bindings: connector: Add PCIe M.2 Mechanical Key E connector
Bluetooth: hci_qca: Add M.2 Bluetooth device support using pwrseq
power: sequencing: pcie-m2: Add support for PCIe M.2 Key E connectors
power: sequencing: pcie-m2: Create serdev device for WCN7850 bluetooth
.../bindings/connector/pcie-m2-e-connector.yaml | 184 +++++++++++
.../devicetree/bindings/serial/serial.yaml | 3 +
MAINTAINERS | 1 +
drivers/bluetooth/hci_qca.c | 9 +
drivers/power/sequencing/Kconfig | 3 +-
drivers/power/sequencing/pwrseq-pcie-m2.c | 346 ++++++++++++++++++++-
drivers/tty/serdev/core.c | 28 +-
include/linux/serdev.h | 24 +-
8 files changed, 570 insertions(+), 28 deletions(-)
---
base-commit: 559f264e403e4d58d56a17595c60a1de011c5e20
change-id: 20251112-pci-m2-e-94695ac9d657
Best regards,
--
Manivannan Sadhasivam <manivannan.sadhasivam@oss.qualcomm.com>
^ permalink raw reply
* [PATCH v7 1/8] serdev: Convert to_serdev_*() helpers to macros and use container_of_const()
From: Manivannan Sadhasivam via B4 Relay @ 2026-03-26 8:06 UTC (permalink / raw)
To: Rob Herring, Greg Kroah-Hartman, Jiri Slaby, Nathan Chancellor,
Nicolas Schier, Hans de Goede, Ilpo Järvinen, Mark Pearson,
Derek J. Clark, Manivannan Sadhasivam, Krzysztof Kozlowski,
Conor Dooley, Marcel Holtmann, Luiz Augusto von Dentz,
Bartosz Golaszewski, Andy Shevchenko, Bartosz Golaszewski
Cc: linux-serial, linux-kernel, linux-kbuild, platform-driver-x86,
linux-pci, devicetree, linux-arm-msm, linux-bluetooth, linux-pm,
Stephan Gerhold, Dmitry Baryshkov, linux-acpi,
Manivannan Sadhasivam, Hans de Goede, Bartosz Golaszewski
In-Reply-To: <20260326-pci-m2-e-v7-0-43324a7866e6@oss.qualcomm.com>
From: Manivannan Sadhasivam <manivannan.sadhasivam@oss.qualcomm.com>
If these helpers receive the 'const struct device' pointer, then the const
qualifier will get dropped, leading to below warning:
warning: passing argument 1 of ‘to_serdev_device_driver’ discards 'const'
qualifier from pointer target type [-Wdiscarded-qualifiers]
This is not an issue as of now, but with the future commits adding serdev
device based driver matching, this warning will get triggered. Hence,
convert these helpers to macros so that the qualifier get preserved and
also use container_of_const() as container_of() is deprecated.
Tested-by: Hans de Goede <johannes.goede@oss.qualcomm.com> # ThinkPad T14s gen6 (arm64)
Reviewed-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@oss.qualcomm.com>
---
include/linux/serdev.h | 15 +++------------
1 file changed, 3 insertions(+), 12 deletions(-)
diff --git a/include/linux/serdev.h b/include/linux/serdev.h
index 5654c58eb73c..0c7d3c27d1f8 100644
--- a/include/linux/serdev.h
+++ b/include/linux/serdev.h
@@ -49,10 +49,7 @@ struct serdev_device {
struct mutex write_lock;
};
-static inline struct serdev_device *to_serdev_device(struct device *d)
-{
- return container_of(d, struct serdev_device, dev);
-}
+#define to_serdev_device(d) container_of_const(d, struct serdev_device, dev)
/**
* struct serdev_device_driver - serdev slave device driver
@@ -68,10 +65,7 @@ struct serdev_device_driver {
void (*shutdown)(struct serdev_device *);
};
-static inline struct serdev_device_driver *to_serdev_device_driver(struct device_driver *d)
-{
- return container_of(d, struct serdev_device_driver, driver);
-}
+#define to_serdev_device_driver(d) container_of_const(d, struct serdev_device_driver, driver)
enum serdev_parity {
SERDEV_PARITY_NONE,
@@ -112,10 +106,7 @@ struct serdev_controller {
const struct serdev_controller_ops *ops;
};
-static inline struct serdev_controller *to_serdev_controller(struct device *d)
-{
- return container_of(d, struct serdev_controller, dev);
-}
+#define to_serdev_controller(d) container_of_const(d, struct serdev_controller, dev)
static inline void *serdev_device_get_drvdata(const struct serdev_device *serdev)
{
--
2.51.0
^ permalink raw reply related
* [PATCH v7 3/8] serdev: Do not return -ENODEV from of_serdev_register_devices() if external connector is used
From: Manivannan Sadhasivam via B4 Relay @ 2026-03-26 8:06 UTC (permalink / raw)
To: Rob Herring, Greg Kroah-Hartman, Jiri Slaby, Nathan Chancellor,
Nicolas Schier, Hans de Goede, Ilpo Järvinen, Mark Pearson,
Derek J. Clark, Manivannan Sadhasivam, Krzysztof Kozlowski,
Conor Dooley, Marcel Holtmann, Luiz Augusto von Dentz,
Bartosz Golaszewski, Andy Shevchenko, Bartosz Golaszewski
Cc: linux-serial, linux-kernel, linux-kbuild, platform-driver-x86,
linux-pci, devicetree, linux-arm-msm, linux-bluetooth, linux-pm,
Stephan Gerhold, Dmitry Baryshkov, linux-acpi,
Manivannan Sadhasivam, Hans de Goede, Bartosz Golaszewski
In-Reply-To: <20260326-pci-m2-e-v7-0-43324a7866e6@oss.qualcomm.com>
From: Manivannan Sadhasivam <manivannan.sadhasivam@oss.qualcomm.com>
If an external connector like M.2 is connected to the serdev controller
in DT, then the serdev devices may be created dynamically by the connector
driver. So do not return -ENODEV from of_serdev_register_devices() if the
static nodes are not found and the graph node is used.
Tested-by: Hans de Goede <johannes.goede@oss.qualcomm.com> # ThinkPad T14s gen6 (arm64)
Reviewed-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@oss.qualcomm.com>
---
drivers/tty/serdev/core.c | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/drivers/tty/serdev/core.c b/drivers/tty/serdev/core.c
index bf88b95f7458..e9d044a331b0 100644
--- a/drivers/tty/serdev/core.c
+++ b/drivers/tty/serdev/core.c
@@ -12,6 +12,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of.h>
+#include <linux/of_graph.h>
#include <linux/of_device.h>
#include <linux/pm_domain.h>
#include <linux/pm_runtime.h>
@@ -561,7 +562,13 @@ static int of_serdev_register_devices(struct serdev_controller *ctrl)
} else
found = true;
}
- if (!found)
+
+ /*
+ * When the serdev controller is connected to an external connector like
+ * M.2 in DT, then the serdev devices may be created dynamically by the
+ * connector driver.
+ */
+ if (!found && !of_graph_is_present(dev_of_node(&ctrl->dev)))
return -ENODEV;
return 0;
--
2.51.0
^ permalink raw reply related
* [PATCH v7 2/8] serdev: Add an API to find the serdev controller associated with the devicetree node
From: Manivannan Sadhasivam via B4 Relay @ 2026-03-26 8:06 UTC (permalink / raw)
To: Rob Herring, Greg Kroah-Hartman, Jiri Slaby, Nathan Chancellor,
Nicolas Schier, Hans de Goede, Ilpo Järvinen, Mark Pearson,
Derek J. Clark, Manivannan Sadhasivam, Krzysztof Kozlowski,
Conor Dooley, Marcel Holtmann, Luiz Augusto von Dentz,
Bartosz Golaszewski, Andy Shevchenko, Bartosz Golaszewski
Cc: linux-serial, linux-kernel, linux-kbuild, platform-driver-x86,
linux-pci, devicetree, linux-arm-msm, linux-bluetooth, linux-pm,
Stephan Gerhold, Dmitry Baryshkov, linux-acpi,
Manivannan Sadhasivam, Hans de Goede, Bartosz Golaszewski
In-Reply-To: <20260326-pci-m2-e-v7-0-43324a7866e6@oss.qualcomm.com>
From: Manivannan Sadhasivam <manivannan.sadhasivam@oss.qualcomm.com>
Add of_find_serdev_controller_by_node() API to find the serdev controller
device associated with the devicetree node.
Tested-by: Hans de Goede <johannes.goede@oss.qualcomm.com> # ThinkPad T14s gen6 (arm64)
Reviewed-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@oss.qualcomm.com>
---
drivers/tty/serdev/core.c | 19 +++++++++++++++++++
include/linux/serdev.h | 9 +++++++++
2 files changed, 28 insertions(+)
diff --git a/drivers/tty/serdev/core.c b/drivers/tty/serdev/core.c
index 8f25510f89b6..bf88b95f7458 100644
--- a/drivers/tty/serdev/core.c
+++ b/drivers/tty/serdev/core.c
@@ -514,6 +514,25 @@ struct serdev_controller *serdev_controller_alloc(struct device *host,
}
EXPORT_SYMBOL_GPL(serdev_controller_alloc);
+#ifdef CONFIG_OF
+/**
+ * of_find_serdev_controller_by_node() - Find the serdev controller associated
+ * with the devicetree node
+ * @node: Devicetree node
+ *
+ * Return: Pointer to the serdev controller associated with the node. NULL if
+ * the controller is not found. Caller is responsible for calling
+ * serdev_controller_put() to drop the reference.
+ */
+struct serdev_controller *of_find_serdev_controller_by_node(struct device_node *node)
+{
+ struct device *dev = bus_find_device_by_of_node(&serdev_bus_type, node);
+
+ return (dev && dev->type == &serdev_ctrl_type) ? to_serdev_controller(dev) : NULL;
+}
+EXPORT_SYMBOL_GPL(of_find_serdev_controller_by_node);
+#endif
+
static int of_serdev_register_devices(struct serdev_controller *ctrl)
{
struct device_node *node;
diff --git a/include/linux/serdev.h b/include/linux/serdev.h
index 0c7d3c27d1f8..188c0ba62d50 100644
--- a/include/linux/serdev.h
+++ b/include/linux/serdev.h
@@ -334,4 +334,13 @@ static inline bool serdev_acpi_get_uart_resource(struct acpi_resource *ares,
}
#endif /* CONFIG_ACPI */
+#ifdef CONFIG_OF
+struct serdev_controller *of_find_serdev_controller_by_node(struct device_node *node);
+#else
+static inline struct serdev_controller *of_find_serdev_controller_by_node(struct device_node *node)
+{
+ return NULL;
+}
+#endif /* CONFIG_OF */
+
#endif /*_LINUX_SERDEV_H */
--
2.51.0
^ permalink raw reply related
* Re: [RFC][RFT][PATCH 0/3] arm64: Enable asympacking for minor CPPC asymmetry
From: Vincent Guittot @ 2026-03-26 7:53 UTC (permalink / raw)
To: Christian Loehle
Cc: arighi, peterz, dietmar.eggemann, valentin.schneider, mingo,
rostedt, segall, mgorman, catalin.marinas, will, sudeep.holla,
rafael, linux-pm, linux-kernel, juri.lelli, kobak, fabecassis
In-Reply-To: <20260325181314.3875909-1-christian.loehle@arm.com>
On Wed, 25 Mar 2026 at 19:13, Christian Loehle <christian.loehle@arm.com> wrote:
>
> The scheduler currently handles CPU performance asymmetry via either:
>
> - SD_ASYM_PACKING: simple priority-based task placement (x86 ITMT)
> - SD_ASYM_CPUCAPACITY: capacity-aware scheduling
>
> On arm64, capacity-aware scheduling is used for any detected capacity
> differences.
>
> Some systems expose small per-CPU performance differences via CPPC
> highest_perf (e.g. due to chip binning), resulting in slightly different
> capacities (<~5%). These differences are sufficient to trigger
> SD_ASYM_CPUCAPACITY, even though the system is otherwise effectively
> symmetric.
>
> For such small deltas, capacity-aware scheduling is unnecessarily
> complex. A simpler priority-based approach, similar to x86 ITMT, is
> sufficient.
I'm not convinced that moving to SD_ASYM_PACKING is the right way to
move forward.
1st of all, do you target all kind of system or only SMT? It's not
clear in your cover letter
Moving on asym pack for !SMT doesn't make sense to me. If you don't
want EAS enabled, you can disable it with
/proc/sys/kernel/sched_energy_aware
For SMT system and small capacity difference, I would prefer that we
look at supporting SMT in SD_ASYM_CPUCAPACITY. Starting with
select_idle_capacity
>
> This series introduces support for using asymmetric packing in that case:
>
> - derive per-CPU priorities from CPPC highest_perf
> - detect when CPUs differ but not enough to form distinct capacity classes
> - suppress SD_ASYM_CPUCAPACITY for such domains
> - enable SD_ASYM_PACKING and use CPPC-based priority ordering instead
>
> The asympacking flag is exposed at all topology levels; domains with
> equal priorities are unaffected, while domains spanning CPUs with
> different priorities can honor the ordering.
>
> RFC:
> I'm not entirely sure if this is the best way to implement this.
> Currently this is baked into CPPC and arm64, while neither are strictly
> necessary, we could also use cpu_capacity directly to derive the
> ordering and enable this for non-CPPC and/or non-arm64.
> RFT:
> Andrea, please give this a try. This should perform better in particular
> for single-threaded workloads and workloads that do not utilize all
> cores (all the time anyway).
> Capacity-aware scheduling wakeup works very different to the SMP path
> used now, some workloads will benefit, some regress, it would be nice
> to get some test results for these.
> We already discussed DCPerf MediaWiki seems to benefit from
> capacity-aware scheduling wakeup behavior, but others (most?) should
> benefit from this series.
>
> I don't know if we can also be clever about ordering amongst SMT siblings.
> That would be dependent on the uarch and I don't have a platform to
> experiment with this though, so consider this series orthogonal to the
> idle-core SMT considerations.
> On platforms with SMT though asympacking makes a lot more sense than
> capacity-aware scheduling, because arguing about capacity without
> considering utilization of the sibling(s) (and the resulting potential
> 'stolen' capacity we perceive) isn't theoretically sound.
>
> Christian Loehle (3):
> sched/topology: Introduce arch hooks for asympacking
> arch_topology: Export CPPC-based asympacking prios
> arm64/sched: Enable CPPC-based asympacking
>
> arch/arm64/include/asm/topology.h | 6 +++++
> arch/arm64/kernel/topology.c | 34 ++++++++++++++++++++++++++
> drivers/base/arch_topology.c | 40 +++++++++++++++++++++++++++++++
> include/linux/arch_topology.h | 24 +++++++++++++++++++
> include/linux/sched/topology.h | 9 +++++++
> kernel/sched/fair.c | 16 -------------
> kernel/sched/topology.c | 34 ++++++++++++++++++++------
> 7 files changed, 140 insertions(+), 23 deletions(-)
>
> --
> 2.34.1
>
^ permalink raw reply
* Re: [PATCH v3 9/9] arm64: dts: mt6392: add mt6392 PMIC dtsi
From: Chen-Yu Tsai @ 2026-03-26 5:43 UTC (permalink / raw)
To: AngeloGioacchino Del Regno
Cc: wens, Luca Leonardo Scorcia, linux-mediatek, Val Packett,
Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Sen Chu, Sean Wang, Macpaul Lin, Lee Jones, Matthias Brugger,
Linus Walleij, Liam Girdwood, Mark Brown, Gary Bisson,
Julien Massot, Louis-Alexis Eyraud, Fabien Parent, Chen Zhong,
linux-input, devicetree, linux-kernel, linux-pm, linux-arm-kernel,
linux-gpio
In-Reply-To: <28102417-4a2a-4e29-afbd-d0f2aa76074b@collabora.com>
On Wed, Mar 18, 2026 at 06:22:42PM +0100, AngeloGioacchino Del Regno wrote:
> Il 18/03/26 14:54, Chen-Yu Tsai ha scritto:
> > On Wed, Mar 18, 2026 at 8:39 PM AngeloGioacchino Del Regno
> > <angelogioacchino.delregno@collabora.com> wrote:
> > >
> > > Il 17/03/26 19:43, Luca Leonardo Scorcia ha scritto:
> > > > From: Val Packett <val@packett.cool>
> > > >
> > > > Add the dts to be included by all boards using the MT6392 PMIC.
> > > >
> > > > Signed-off-by: Val Packett <val@packett.cool>
> > > > Signed-off-by: Luca Leonardo Scorcia <l.scorcia@gmail.com>
> > > > ---
> > > > arch/arm64/boot/dts/mediatek/mt6392.dtsi | 141 +++++++++++++++++++++++
> > > > 1 file changed, 141 insertions(+)
> > > > create mode 100644 arch/arm64/boot/dts/mediatek/mt6392.dtsi
> > > >
> > > > diff --git a/arch/arm64/boot/dts/mediatek/mt6392.dtsi b/arch/arm64/boot/dts/mediatek/mt6392.dtsi
> > > > new file mode 100644
> > > > index 000000000000..fbf6f671524c
> > > > --- /dev/null
> > > > +++ b/arch/arm64/boot/dts/mediatek/mt6392.dtsi
> > > > @@ -0,0 +1,141 @@
> > > > +// SPDX-License-Identifier: GPL-2.0
> > > > +/*
> > > > + * Copyright (c) 2019 MediaTek Inc.
> > > > + * Copyright (c) 2024 Val Packett <val@packett.cool>
> > > > + */
> > > > +
> > > > +#include <dt-bindings/input/input.h>
> > > > +
> > > > +&pwrap {
> > > > + pmic: pmic {
> > > > + compatible = "mediatek,mt6392", "mediatek,mt6323";
> > > > + interrupt-controller;
> > > > + #interrupt-cells = <2>;
> > > > +
> > > > + keys {
> > > > + compatible = "mediatek,mt6392-keys";
> > > > +
> > > > + key-power {
> > > > + linux,keycodes = <KEY_POWER>;
> > > > + wakeup-source;
> > > > + };
> > > > +
> > > > + key-home {
> > > > + linux,keycodes = <KEY_HOME>;
> > > > + wakeup-source;
> > > > + };
> > > > + };
> > > > +
> > > > + pio6392: pinctrl {
> > > > + compatible = "mediatek,mt6392-pinctrl";
> > > > +
> > > > + gpio-controller;
> > > > + #gpio-cells = <2>;
> > > > + };
> > > > +
> > > > + rtc {
> > > > + compatible = "mediatek,mt6392-rtc",
> > > > + "mediatek,mt6323-rtc";
> > > > + };
> > > > +
> > > > + regulators {
> > > > + compatible = "mediatek,mt6392-regulator";
> > > > +
> > > > + mt6392_vproc_reg: buck_vproc {
> > >
> > > s/buck//g
> > >
> > > Also, no min/max voltages?!
> >
> > We really shouldn't set min/max voltages in the PMIC dtsi file.
> >
> > The min/max voltages are supposed to be the intersection of the
> > consumers acceptable operating ranges. The min/max of the regulator
> > itself is already implied by the model / compatible.
> >
>
> Your point is fair, but it's also true that some of the regulators are not
> really meant to ever output anything different than what they are supposed
> to, though, with slight variations being possible... I guess the best option
> here is to leave declaring voltages to board DTs instead, which is sensible
> in the end.
>
> Okay, agreed. Let's go with no voltages.
>
> Reminder for myself: there's a bunch of PMIC devicetrees to cleanup in here...
And to be honest, even the default names are not needed. They are again
implied by the compatible, and even the regulator's own node name.
So either we could have a whole bunch of empty regulator nodes with
labels for easy reference, or just have the upper level "regulators"
wrapper node with a "mt63??_regulators" label for board dts files
to reference and add the _used_ regulators to.
If you agree, I can do the cleanup work.
ChenYu
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox