* Re: [PATCH v3 1/8] dt-bindings: mfd: khadas: Add new compatible for Khadas VIM4 MCU
From: Ronald Claveau @ 2026-04-21 9:45 UTC (permalink / raw)
To: Conor Dooley
Cc: Neil Armstrong, Lee Jones, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andi Shyti, Kevin Hilman, Jerome Brunet,
Martin Blumenstingl, Beniamino Galvani, Rafael J. Wysocki,
Daniel Lezcano, Zhang Rui, Lukasz Luba, Liam Girdwood, Mark Brown,
linux-amlogic, devicetree, linux-kernel, linux-i2c,
linux-arm-kernel, linux-pm
In-Reply-To: <20260420-viable-plot-862e0c545837@spud>
On 4/20/26 6:22 PM, Conor Dooley wrote:
> On Fri, Apr 17, 2026 at 06:27:17PM +0200, Ronald Claveau wrote:
>> The Khadas VIM4 MCU register is slightly different
>> from previous boards' MCU.
>> This board also features a switchable power source for its fan.
>>
>> Signed-off-by: Ronald Claveau <linux-kernel-dev@aliel.fr>
>> ---
>> Documentation/devicetree/bindings/mfd/khadas,mcu.yaml | 5 +++++
>> 1 file changed, 5 insertions(+)
>>
>> diff --git a/Documentation/devicetree/bindings/mfd/khadas,mcu.yaml b/Documentation/devicetree/bindings/mfd/khadas,mcu.yaml
>> index 084960fd5a1fd..a80718f7595ce 100644
>> --- a/Documentation/devicetree/bindings/mfd/khadas,mcu.yaml
>> +++ b/Documentation/devicetree/bindings/mfd/khadas,mcu.yaml
>> @@ -18,6 +18,7 @@ properties:
>> compatible:
>> enum:
>> - khadas,mcu # MCU revision is discoverable
>> + - khadas,vim4-mcu # Different MCU variant, not discoverable
>>
>> "#cooling-cells": # Only needed for boards having FAN control feature
>> const: 2
>> @@ -25,6 +26,10 @@ properties:
>> reg:
>> maxItems: 1
>>
>> + fan-supply:
>> + description: Phandle to the regulator that powers the fan.
>> + $ref: /schemas/types.yaml#/definitions/phandle
>
> Can you limit this by compatible please?
> pw-bot: changes-requested
>
Thanks for your feedback, I will add that.
>> +
>> required:
>> - compatible
>> - reg
>>
>> --
>> 2.49.0
>>
--
Best regards,
Ronald
^ permalink raw reply
* [PATCH v2 0/2] arm64: dts: rockchip: fix Ethernet PHY on Theobroma PX30 devices
From: Quentin Schulz @ 2026-04-21 9:45 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Heiko Stuebner
Cc: Andrew Lunn, Heiko Stuebner, devicetree, linux-arm-kernel,
linux-rockchip, linux-kernel, Quentin Schulz, stable
This removes the reliance on the bootloader setting up the Ethernet PHY
for the Linux kernel to be able to use Ethernet.
This is due to the HW default of the PHY reset line being active and the
MDIO auto-detection mechanism not controlling a PHY's reset line such
that we need to hardcode the PHY ID in the compatible property for it to
be usable by the kernel, regardless of what the bootloader is doing.
We only ever had one PHY (DP83825) for both devices, so it's fine to
hardcode this way.
As discussed in v1[1][2], even though they suffer from the same
limitation, only the patch for Ringneck is targeted for stable releases.
Ethernet is currently broken if the bootloader is built without Ethernet
support for those two boards. Cobra is a product for which the software
stack can only be replaced or updated by Cherry. Ringneck is a SoM
supported since kernel 6.1, the user is likely going to write their own
bootloader support based on the motherboard they attach the SoM to. They
may disable Ethernet support in the bootloader if they don't need to
(e.g. to reduce the attack surface or have an easier time certifying a
device when arguing with an audit company).
Ethernet-less bootloader was supported until commit e463625af7f9
("arm64: dts: rockchip: move reset to dedicated eth-phy node on
ringneck") for Ringneck. Because I do not control what our users have
made with Ringneck, and that it used to work before commit e463625af7f9,
the patch fixing the issue on Ringneck is a candidate for backporting to
stable.
Cobra never supported it due to its support in the kernel being added
with this (unknown at the time) limitation. Moreover, Cherry controls
the whole software stack so this is already patched downstream whenever
required. Therefore, the patch fixing the issue on Cobra is not marked
as a candidate for backporting to stable (but if it ends up being
backported, it's fine as well).
[1] https://lore.kernel.org/linux-rockchip/38452338-6e65-47ad-a696-b90c02ac42f0@lunn.ch/
[2] https://lore.kernel.org/linux-rockchip/b2f12140-ee3d-45bc-864e-d51317c83b8d@cherry.de/
Signed-off-by: Quentin Schulz <quentin.schulz@cherry.de>
---
Changes in v2:
- removed Cc stable on Cobra's patch,
- Link to v1: https://patch.msgid.link/20260202-px30-eth-phy-v1-0-ef365be64922@cherry.de
---
Quentin Schulz (2):
arm64: dts: rockchip: fix Ethernet PHY not found on PX30 Cobra
arm64: dts: rockchip: fix Ethernet PHY not found on PX30 Ringneck
arch/arm64/boot/dts/rockchip/px30-cobra.dtsi | 2 +-
arch/arm64/boot/dts/rockchip/px30-ringneck.dtsi | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
---
base-commit: c1f49dea2b8f335813d3b348fd39117fb8efb428
change-id: 20260130-px30-eth-phy-676fa181e116
Best regards,
--
Quentin Schulz <quentin.schulz@cherry.de>
^ permalink raw reply
* [PATCH v2 2/2] arm64: dts: rockchip: fix Ethernet PHY not found on PX30 Ringneck
From: Quentin Schulz @ 2026-04-21 9:45 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Heiko Stuebner
Cc: Andrew Lunn, Heiko Stuebner, devicetree, linux-arm-kernel,
linux-rockchip, linux-kernel, Quentin Schulz, stable
In-Reply-To: <20260421-px30-eth-phy-v2-0-68c375b120fd@cherry.de>
From: Quentin Schulz <quentin.schulz@cherry.de>
When not passing the PHY ID with an ethernet-phy-idX.Y compatible
property, the MDIO bus will attempt to auto-detect the PHY by reading
its registers and then probing the appropriate driver. For this to work,
the PHY needs to be in a working state.
Unfortunately, the net subsystem doesn't control the PHY reset GPIO when
attempting to auto-detect the PHY. This means the PHY needs to be in a
working state when entering the Linux kernel. This historically has been
the case for this device, but only because the bootloader was taking
care of initializing the Ethernet controller even when not using it.
We're attempting to support the removal of the network stack in the
bootloader, which means the Linux kernel will be entered with the PHY
still in reset and now Ethernet doesn't work anymore.
The devices in the field only ever had a TI DP83825, so let's simply
bypass the auto-detection mechanism entirely by passing the appropriate
PHY IDs via the compatible.
Note that this is only an issue since commit e463625af7f9 ("arm64: dts:
rockchip: move reset to dedicated eth-phy node on ringneck") as before
that commit the reset was done by the MAC controller before starting the
MDIO auto-detection mechanism, via the snps,reset-* properties.
Cc: stable@vger.kernel.org
Fixes: e463625af7f9 ("arm64: dts: rockchip: move reset to dedicated eth-phy node on ringneck")
Signed-off-by: Quentin Schulz <quentin.schulz@cherry.de>
---
arch/arm64/boot/dts/rockchip/px30-ringneck.dtsi | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm64/boot/dts/rockchip/px30-ringneck.dtsi b/arch/arm64/boot/dts/rockchip/px30-ringneck.dtsi
index 4203b335a2633..973b4c5880e24 100644
--- a/arch/arm64/boot/dts/rockchip/px30-ringneck.dtsi
+++ b/arch/arm64/boot/dts/rockchip/px30-ringneck.dtsi
@@ -344,7 +344,7 @@ &io_domains {
&mdio {
dp83825: ethernet-phy@0 {
- compatible = "ethernet-phy-ieee802.3-c22";
+ compatible = "ethernet-phy-id2000.a140";
reg = <0x0>;
pinctrl-names = "default";
pinctrl-0 = <&phy_rst>;
--
2.53.0
^ permalink raw reply related
* [PATCH v2 1/2] arm64: dts: rockchip: fix Ethernet PHY not found on PX30 Cobra
From: Quentin Schulz @ 2026-04-21 9:45 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Heiko Stuebner
Cc: Andrew Lunn, Heiko Stuebner, devicetree, linux-arm-kernel,
linux-rockchip, linux-kernel, Quentin Schulz
In-Reply-To: <20260421-px30-eth-phy-v2-0-68c375b120fd@cherry.de>
From: Quentin Schulz <quentin.schulz@cherry.de>
When not passing the PHY ID with an ethernet-phy-idX.Y compatible
property, the MDIO bus will attempt to auto-detect the PHY by reading
its registers and then probing the appropriate driver. For this to work,
the PHY needs to be in a working state.
Unfortunately, the net subsystem doesn't control the PHY reset GPIO when
attempting to auto-detect the PHY. This means the PHY needs to be in a
working state when entering the Linux kernel. This historically has been
the case for this device, but only because the bootloader was taking
care of initializing the Ethernet controller even when not using it.
We're attempting to support the removal of the network stack in the
bootloader, which means the Linux kernel will be entered with the PHY
still in reset and now Ethernet doesn't work anymore.
The devices in the field only ever had a TI DP83825, so let's simply
bypass the auto-detection mechanism entirely by passing the appropriate
PHY IDs via the compatible.
Fixes: bb510ddc9d3e ("arm64: dts: rockchip: add px30-cobra base dtsi and board variants")
Signed-off-by: Quentin Schulz <quentin.schulz@cherry.de>
---
arch/arm64/boot/dts/rockchip/px30-cobra.dtsi | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm64/boot/dts/rockchip/px30-cobra.dtsi b/arch/arm64/boot/dts/rockchip/px30-cobra.dtsi
index b7e669d8ba4d1..add917af5de78 100644
--- a/arch/arm64/boot/dts/rockchip/px30-cobra.dtsi
+++ b/arch/arm64/boot/dts/rockchip/px30-cobra.dtsi
@@ -397,7 +397,7 @@ &io_domains {
&mdio {
dp83825: ethernet-phy@0 {
- compatible = "ethernet-phy-ieee802.3-c22";
+ compatible = "ethernet-phy-id2000.a140";
reg = <0x0>;
pinctrl-names = "default";
pinctrl-0 = <&phy_rst>;
--
2.53.0
^ permalink raw reply related
* Re: [PATCH v5 01/12] coresight: etm4x: fix wrong check of etm4x_sspcicrn_present()
From: Yeoreum Yun @ 2026-04-21 9:48 UTC (permalink / raw)
To: Suzuki K Poulose
Cc: coresight, linux-arm-kernel, linux-kernel, mike.leach,
james.clark, alexander.shishkin, leo.yan, jie.gan
In-Reply-To: <d733a0b3-60a6-4bd8-909a-a2ee0c121dde@arm.com>
On Tue, Apr 21, 2026 at 09:47:54AM +0100, Suzuki K Poulose wrote:
> On 15/04/2026 17:55, Yeoreum Yun wrote:
> > According to Embedded Trace Macrocell Architecture Specification
> > ETMv4.0 to ETM4.6 [0], TRCSSPCICR<n> is present only if all of
> > the following are true:
> >
> > - TRCIDR4.NUMSSCC > n.
> > - TRCIDR4.NUMPC > 0b0000.
> > - TRCSSCSR<n>.PC == 0b1.
> >
> > Comment for etm4x_sspcicrn_present() is align with the specification.
> > However, the check should use drvdata->nr_pe_cmp to check TRCIDR4.NUMPC
> > not nr_pe.
> >
> > Link: https://developer.arm.com/documentation/ihi0064/latest/ [0]
>
> Fixes: f6a18f354c58 ("coresight: etm4x: Handle access to TRCSSPCICRn")
>
> With that looks good to me
Thanks!
>
> Suzuki
>
> > Signed-off-by: Yeoreum Yun <yeoreum.yun@arm.com>
> > ---
> > drivers/hwtracing/coresight/coresight-etm4x-core.c | 2 +-
> > 1 file changed, 1 insertion(+), 1 deletion(-)
> >
> > diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c
> > index d565a73f0042..74b7063d130e 100644
> > --- a/drivers/hwtracing/coresight/coresight-etm4x-core.c
> > +++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c
> > @@ -89,7 +89,7 @@ static int etm4_probe_cpu(unsigned int cpu);
> > static bool etm4x_sspcicrn_present(struct etmv4_drvdata *drvdata, int n)
> > {
> > return (n < drvdata->nr_ss_cmp) &&
> > - drvdata->nr_pe &&
> > + drvdata->nr_pe_cmp &&
> > (drvdata->config.ss_status[n] & TRCSSCSRn_PC);
> > }
>
--
Sincerely,
Yeoreum Yun
^ permalink raw reply
* Re: [PATCH v3 5/6] soc: qcom: pmic-glink-altmode: pass down HPD_IRQ events
From: Konrad Dybcio @ 2026-04-21 9:51 UTC (permalink / raw)
To: Dmitry Baryshkov, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, David Airlie, Simona Vetter, Heikki Krogerus,
Greg Kroah-Hartman, Andrzej Hajda, Neil Armstrong, Robert Foss,
Laurent Pinchart, Jonas Karlman, Jernej Skrabec, Adrien Grassein,
Jani Nikula, Rodrigo Vivi, Joonas Lahtinen, Tvrtko Ursulin,
Kevin Hilman, Jerome Brunet, Martin Blumenstingl, Rob Clark,
Dmitry Baryshkov, Abhinav Kumar, Jessica Zhang, Sean Paul,
Marijn Suijten, Tomi Valkeinen, Bjorn Andersson, Konrad Dybcio,
Pengyu Luo, Nikita Travkin, Yongxing Mou
Cc: dri-devel, linux-kernel, linux-usb, intel-gfx, intel-xe,
linux-amlogic, linux-arm-kernel, linux-arm-msm, freedreno
In-Reply-To: <20260421-hpd-irq-events-v3-5-44d2bf40dfc2@oss.qualcomm.com>
On 4/21/26 1:33 AM, Dmitry Baryshkov wrote:
> Pass IRQ_HPD events to the HPD bridge, letting those to be delivered to
> the DisplayPort driver.
>
> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
> ---
Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Konrad
^ permalink raw reply
* Re: [PATCH] ACPI: arm64: cpuidle: Tolerate platforms with no deep PSCI idle states
From: Breno Leitao @ 2026-04-21 9:51 UTC (permalink / raw)
To: Sudeep Holla
Cc: Lorenzo Pieralisi, Hanjun Guo, Catalin Marinas, Will Deacon,
Rafael J. Wysocki, Len Brown, Huisong Li, Rafael J. Wysocki,
linux-acpi, linux-arm-kernel, linux-kernel, pjaroszynski, rmikey,
kernel-team, stable
In-Reply-To: <20260420-sturdy-unique-shark-c4ca8c@sudeepholla>
On Mon, Apr 20, 2026 at 04:12:38PM +0100, Sudeep Holla wrote:
> On Mon, Apr 20, 2026 at 02:27:13AM -0700, Breno Leitao wrote:
> > - count = pr->power.count - 1;
> > - if (count <= 0)
> > - return -ENODEV;
> > -
>
> Does it make sense to retain this check like
> if (pr->power.count < 1)
> return -EINVAL;
>
> Though I see the assignment to pr->power.count in drivers/acpi/processor_idle.c
> is through unsigned int. So I am fine even without the above check.
I don't think the check is necessary. When count is 0 or 1, the loop
for (i = 1; i < pr->power.count; i++) body won't execute, and the
function will return 0.
This seems like the correct behavior — if there are no FFH PSCI states
to validate, there's nothing that should fail.
Additionally, returning -ENODEV would trigger the "Invalid FFH LPI data"
error message, which would be misleading since the LPI data isn't
invalid, it's just not present.
That said, please take this with a grain of salt since I'm not deeply
familiar with _LPI states and their expected behavior.
Thanks for the review,
--breno
^ permalink raw reply
* RE: [PATCH v5 3/4] thermal: qoriq: workaround unexpected temperature readings from tmu
From: Jacky Bai @ 2026-04-21 9:56 UTC (permalink / raw)
To: Frank Li
Cc: Rafael J. Wysocki, Daniel Lezcano, Zhang Rui, Lukasz Luba,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Shawn Guo,
Sascha Hauer, Fabio Estevam, Pengutronix Kernel Team,
linux-pm@vger.kernel.org, devicetree@vger.kernel.org,
imx@lists.linux.dev, linux-arm-kernel@lists.infradead.org
In-Reply-To: <aec_TlguJkc4A1qN@lizhi-Precision-Tower-5810>
> Subject: Re: [PATCH v5 3/4] thermal: qoriq: workaround unexpected
> temperature readings from tmu
>
[...]
> >
> > + /* ERR052243: If a raising or falling edge happens, try later */
> > + if (qoriq_tmu_has_errata(qdata->drvdata, TMU_ERR052243)) {
> > + regmap_read(qdata->regmap, REGS_TIDR, &tidr);
> > + if (tidr & TEMP_RATE_IRQ_MASK) {
> > + regmap_write(qdata->regmap, REGS_TIDR,
> TEMP_RATE_IRQ_MASK);
> > + return -EAGAIN;
> > + }
> > + }
> > +
> > if (regmap_read_poll_timeout(qdata->regmap,
> > REGS_TRITSR(qsensor->id),
> > val,
> > @@ -130,6 +159,15 @@ static int tmu_get_temp(struct
> thermal_zone_device *tz, int *temp)
> > 10 * USEC_PER_MSEC))
> > return -ENODATA;
> >
> > + /*ERR052243: If a raising or falling edge happens, try later */
> > + if (qoriq_tmu_has_errata(qdata->drvdata, TMU_ERR052243)) {
> > + regmap_read(qdata->regmap, REGS_TIDR, &tidr);
> > + if (tidr & TEMP_RATE_IRQ_MASK) {
> > + regmap_write(qdata->regmap, REGS_TIDR,
> TEMP_RATE_IRQ_MASK);
> > + return -EAGAIN;
> > + }
> > + }
> > +
>
> The above two code blocks are the same. Use helper function to avoid
> duplicat code. And why need check twice?
>
> ret = qoriq_tmu_err052243()
> if (ret)
> return ret;
>
The first check is to make sure no error already happened. if any error, no need
to polling read the sensor value from tmu, return early to save time. The secondary
check is to make sure the sensor value just read out is still a valid one as the error may
happen after the first check.
It should be ok to remove the first check. As the error only happens in some rare
corner case, the sensor read polling delay is acceptable.
If only keep the secondary check, I think no need to wrap this code block into a helper function?
BR
> Frank
>
> > if (qdata->ver == TMU_VER1) {
> > *temp = (val & GENMASK(7, 0)) * MILLIDEGREE_PER_DEGREE;
> > } else {
> > @@ -247,6 +285,14 @@ static void qoriq_tmu_init_device(struct
> qoriq_tmu_data *data)
> > regmap_write(data->regmap, REGS_V2_TEUMR(0), teumr0_val);
> > }
> >
> > + /* ERR052243: Set the raising & falling edge monitor */
> > + if (qoriq_tmu_has_errata(data->drvdata, TMU_ERR052243)) {
> > + regmap_write(data->regmap, TMRTRCTR, TMRTRCTR_EN |
> > + FIELD_PREP(TMRTRCTR_TEMP_MASK,
> TEMP_RATE_THR_LVL));
> > + regmap_write(data->regmap, TMFTRCTR, TMFTRCTR_EN |
> > + FIELD_PREP(TMFTRCTR_TEMP_MASK,
> TEMP_RATE_THR_LVL));
> > +
> > + }
> > /* Disable monitoring */
> > regmap_write(data->regmap, REGS_TMR, TMR_DISABLE); } @@
> -400,6
> > +446,7 @@ static const struct tmu_drvdata imx8mq_tmu_data = {
> >
> > static const struct tmu_drvdata imx93_data = {
> > .teumr0 = TEUMR0_V21,
> > + .tmu_errata = TMU_ERR052243,
> > };
> >
> > static const struct of_device_id qoriq_tmu_match[] = {
> >
> > --
> > 2.34.1
> >
^ permalink raw reply
* Re: [PATCH v5 02/12] coresight: etm4x: fix underflow for nrseqstate
From: Yeoreum Yun @ 2026-04-21 9:56 UTC (permalink / raw)
To: Suzuki K Poulose
Cc: Leo Yan, coresight, linux-arm-kernel, linux-kernel, mike.leach,
james.clark, alexander.shishkin, jie.gan
In-Reply-To: <6dcb14c1-0759-4f2a-8bbc-b85adf3d12f4@arm.com>
On Tue, Apr 21, 2026 at 09:50:56AM +0100, Suzuki K Poulose wrote:
> On 21/04/2026 09:50, Suzuki K Poulose wrote:
> > On 16/04/2026 16:11, Leo Yan wrote:
> > > On Wed, Apr 15, 2026 at 05:55:18PM +0100, Yeoreum Yun wrote:
> > > > TCRSEQEVR<n> is implemented only when TCRIDR5.NUMSEQSTATE is 0b100,
> > > > in which case n ranges from 0 to 2; otherwise,
> > > > TCRIDR5.NUMSEQSTATE is 0b000.
> > >
> > > My suggestion in previous version is not quite right, thanks for
> > > making this correct.
> > >
> > > [...]
> > >
> > > > @@ -1395,6 +1395,8 @@ static ssize_t seq_idx_store(struct device *dev,
> > > > struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
> > > > struct etmv4_config *config = &drvdata->config;
> > > > + if (!drvdata->nrseqstate)
> > > > + return -EINVAL;
> > >
> > > For "nrseqstate = 0" case, would it return -EOPNOTSUPP instead?
> >
> > Or should we make this only visible if the nrseqstore is meaningful ?
> >
> > Suzuki
> >
> > >
> > > Otherwise, LGTM:
> > >
> > > Reviewed-by: Leo Yan <leo.yan@arm.com>
> >
>
> Also, please add Fixes: tag for these bug fixes
Okay. I'll add the tag. Thanks!
--
Sincerely,
Yeoreum Yun
^ permalink raw reply
* Re: [PATCH] ACPI: arm64: cpuidle: Tolerate platforms with no deep PSCI idle states
From: Sudeep Holla @ 2026-04-21 9:58 UTC (permalink / raw)
To: Breno Leitao
Cc: Lorenzo Pieralisi, Hanjun Guo, Sudeep Holla, Catalin Marinas,
Will Deacon, Rafael J. Wysocki, Len Brown, Huisong Li,
Rafael J. Wysocki, linux-acpi, linux-arm-kernel, linux-kernel,
pjaroszynski, rmikey, kernel-team, stable
In-Reply-To: <aedGoi-Fk5HPK0OO@gmail.com>
On Tue, Apr 21, 2026 at 02:51:42AM -0700, Breno Leitao wrote:
> On Mon, Apr 20, 2026 at 04:12:38PM +0100, Sudeep Holla wrote:
> > On Mon, Apr 20, 2026 at 02:27:13AM -0700, Breno Leitao wrote:
> > > - count = pr->power.count - 1;
> > > - if (count <= 0)
> > > - return -ENODEV;
> > > -
> >
> > Does it make sense to retain this check like
> > if (pr->power.count < 1)
> > return -EINVAL;
> >
> > Though I see the assignment to pr->power.count in drivers/acpi/processor_idle.c
> > is through unsigned int. So I am fine even without the above check.
>
> I don't think the check is necessary. When count is 0 or 1, the loop
> for (i = 1; i < pr->power.count; i++) body won't execute, and the
> function will return 0.
>
Yes but the point is to handle invalid pr->power.count(0 or less) which
is not possible here though it is signed it because it is assigned from
an unsigned int during initialisation.
> This seems like the correct behavior — if there are no FFH PSCI states
> to validate, there's nothing that should fail.
>
Agreed, but I was thinking of error in parsing _LPI being propogated here
but again that's not happening here.
> Additionally, returning -ENODEV would trigger the "Invalid FFH LPI data"
> error message, which would be misleading since the LPI data isn't
> invalid, it's just not present.
>
The point was to throw that error if _LPI parsing fails.
> That said, please take this with a grain of salt since I'm not deeply
> familiar with _LPI states and their expected behavior.
>
No worries, I agree the check I asked for is not needed.
--
Regards,
Sudeep
^ permalink raw reply
* RE: [PATCH v5 2/4] thermal: qoriq: add i.MX93 tmu support
From: Jacky Bai @ 2026-04-21 9:59 UTC (permalink / raw)
To: Daniel Baluta (OSS), Rafael J. Wysocki, Daniel Lezcano, Zhang Rui,
Lukasz Luba, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Shawn Guo, Sascha Hauer, Fabio Estevam, Pengutronix Kernel Team,
Frank Li
Cc: linux-pm@vger.kernel.org, devicetree@vger.kernel.org,
imx@lists.linux.dev, linux-arm-kernel@lists.infradead.org,
Alice Guo
In-Reply-To: <2d1bbd53-1f03-4432-8681-939e0c638d37@oss.nxp.com>
> Subject: Re: [PATCH v5 2/4] thermal: qoriq: add i.MX93 tmu support
>
[...]
> > static struct qoriq_tmu_data *qoriq_sensor_to_data(struct
> > qoriq_sensor *s) @@ -225,6 +232,8 @@ static int
> > qoriq_tmu_calibration(struct device *dev,
> >
> > static void qoriq_tmu_init_device(struct qoriq_tmu_data *data) {
> > + u32 teumr0_val;
>
> No need for this here you can just use directly: data->drvdata->teumr0
>
Thx, will resolve it in next version.
BR
> > +
> > /* Disable interrupt, using polling instead */
> > regmap_write(data->regmap, REGS_TIER, TIER_DISABLE);
> >
> > @@ -234,7 +243,8 @@ static void qoriq_tmu_init_device(struct
> qoriq_tmu_data *data)
> > regmap_write(data->regmap, REGS_TMTMIR, TMTMIR_DEFAULT);
> > } else {
> > regmap_write(data->regmap, REGS_V2_TMTMIR,
> TMTMIR_DEFAULT);
> > - regmap_write(data->regmap, REGS_V2_TEUMR(0), TEUMR0_V2);
> > + teumr0_val = data->drvdata->teumr0;
> > + regmap_write(data->regmap, REGS_V2_TEUMR(0), teumr0_val);
> > }
>
^ permalink raw reply
* Re: [PATCH v5 04/12] coresight: etm4x: exclude ss_status from drvdata->config
From: Mike Leach @ 2026-04-21 9:58 UTC (permalink / raw)
To: Suzuki K Poulose, Leo Yan, Yeoreum Yun
Cc: coresight, linux-arm-kernel, linux-kernel, james.clark,
alexander.shishkin, jie.gan
In-Reply-To: <57dbea1b-670b-4b8f-a590-1d4239bc2c76@arm.com>
Hi,
This register [bit 31] indicates if a single shot comparator has
matched. So read-back provides information to the user post run to
determine which if any of the comparators set in this way has actually
matched.
Moreover, the specification states "Software must reset this bit to 0 to
re-enable single-shot control" and "Reset state is unknown. STATUS must
be written to set an initial state...."
Therefore this register must be written as part of any configuration so
should be available in the drvdata->config for both read and write,
Regards
Mike
On 4/21/26 09:57, Suzuki K Poulose wrote:
> On 16/04/2026 16:51, Leo Yan wrote:
>> On Wed, Apr 15, 2026 at 05:55:20PM +0100, Yeoreum Yun wrote:
>>
>> [...]
>>
>>> @@ -573,11 +573,9 @@ static int etm4_enable_hw(struct etmv4_drvdata
>>> *drvdata)
>>> etm4x_relaxed_write32(csa, config->res_ctrl[i],
>>> TRCRSCTLRn(i));
>>> for (i = 0; i < caps->nr_ss_cmp; i++) {
>>> - /* always clear status bit on restart if using single-shot */
>>> - if (config->ss_ctrl[i] || config->ss_pe_cmp[i])
>>> - config->ss_status[i] &= ~TRCSSCSRn_STATUS;
>>> etm4x_relaxed_write32(csa, config->ss_ctrl[i], TRCSSCCRn(i));
>>> - etm4x_relaxed_write32(csa, config->ss_status[i], TRCSSCSRn(i));
>>> + /* always clear status and pending bits on restart if using
>>> single-shot */
>>> + etm4x_relaxed_write32(csa, 0x0, TRCSSCSRn(i));
>>
>> In Arm ARM, D24.4.60 TRCSSCSR<n>, bits[0..3] are RO. I think it is
>> fine for directly clear the regiser with zero (means it will only
>> clear status / pending bits).
>>
>> [...]
>>
>>> @@ -1841,10 +1839,11 @@ static ssize_t sshot_status_show(struct
>>> device *dev,
>>> {
>>> unsigned long val;
>>> struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
>>> + const struct etmv4_caps *caps = &drvdata->caps;
>>> struct etmv4_config *config = &drvdata->config;
>>> raw_spin_lock(&drvdata->spinlock);
>>> - val = config->ss_status[config->ss_idx];
>>> + val = caps->ss_cmp[config->ss_idx];
>>> raw_spin_unlock(&drvdata->spinlock);
>>> return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
>>> }
>>
>> This sysfs knob never can print out a realtime status for sshot, I am
>
> Won't it give the status, when the ETM was disabled (and saved back to
> config), for as sysfs mode operation, where the user collects
> information about the status via sysfs ? ( The question of if someone
> actually makes use of this is a different question )
>
>
> Cheers
> Suzuki
>
>
>> fine for only printing caps->ss_cmp, this can avoid any misleading.
>>
>> @Suzuki, @Mike, do you agree with the change above?
>>
>> If maintainers agree with this, as Jie suggested, it is good to add a
>> comment in the code and update the document:
>>
>> Documentation/trace/coresight/coresight-etm4x-reference.rst
>>
>> Thanks,
>> Leo
>
^ permalink raw reply
* [PATCH 6.18.y 0/6] arm64: Stable backport of the C1-Pro erratum 4193714 workaround
From: Catalin Marinas @ 2026-04-21 10:00 UTC (permalink / raw)
To: stable; +Cc: Will Deacon, linux-arm-kernel
Hi Greg, Sasha,
As the workaround for this CPU bug just went in, I'm sending it for
stable 6.18. The first two patches are prerequisites to make the
backporting easier. I do not intend to send them for stable 6.12 since
SME is not supported in that version anyway (Android folk did their own
backports already).
A heads-up, the workaround itself is larger than the recommended max 100
lines suitability for stable backports.
Thanks.
Catalin Marinas (4):
arm64: tlb: Introduce __tlbi_sync_s1ish_{kernel,batch}() for TLB
maintenance
arm64: tlb: Pass the corresponding mm to __tlbi_sync_s1ish()
arm64: cputype: Add C1-Pro definitions
arm64: errata: Work around early CME DVMSync acknowledgement
Mark Rutland (2):
arm64: tlb: Allow XZR argument to TLBI ops
arm64: tlb: Optimize ARM64_WORKAROUND_REPEAT_TLBI
Documentation/arch/arm64/silicon-errata.rst | 2 +
arch/arm64/Kconfig | 12 ++
arch/arm64/include/asm/cpucaps.h | 2 +
arch/arm64/include/asm/cputype.h | 2 +
arch/arm64/include/asm/fpsimd.h | 21 +++
arch/arm64/include/asm/tlbbatch.h | 10 +-
arch/arm64/include/asm/tlbflush.h | 143 ++++++++++++++++----
arch/arm64/kernel/cpu_errata.c | 30 ++++
arch/arm64/kernel/entry-common.c | 3 +
arch/arm64/kernel/fpsimd.c | 79 +++++++++++
arch/arm64/kernel/process.c | 36 +++++
arch/arm64/kernel/sys_compat.c | 2 +-
arch/arm64/kvm/hyp/nvhe/mm.c | 2 +-
arch/arm64/kvm/hyp/nvhe/tlb.c | 8 +-
arch/arm64/kvm/hyp/pgtable.c | 2 +-
arch/arm64/kvm/hyp/vhe/tlb.c | 10 +-
arch/arm64/tools/cpucaps | 1 +
17 files changed, 325 insertions(+), 40 deletions(-)
^ permalink raw reply
* [PATCH 6.18.y 1/6] arm64: tlb: Allow XZR argument to TLBI ops
From: Catalin Marinas @ 2026-04-21 10:00 UTC (permalink / raw)
To: stable; +Cc: Will Deacon, linux-arm-kernel
In-Reply-To: <20260421100018.335793-1-catalin.marinas@arm.com>
From: Mark Rutland <mark.rutland@arm.com>
commit bfd9c931d19aa59fb8371d557774fa169b15db9a upstream.
The TLBI instruction accepts XZR as a register argument, and for TLBI
operations with a register argument, there is no functional difference
between using XZR or another GPR which contains zeroes. Operations
without a register argument are encoded as if XZR were used.
Allow the __TLBI_1() macro to use XZR when a register argument is all
zeroes.
Today this only results in a trivial code saving in
__do_compat_cache_op()'s workaround for Neoverse-N1 erratum #1542419. In
subsequent patches this pattern will be used more generally.
There should be no functional change as a result of this patch.
Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Marc Zyngier <maz@kernel.org>
Cc: Oliver Upton <oupton@kernel.org>
Cc: Ryan Roberts <ryan.roberts@arm.com>
Cc: Will Deacon <will@kernel.org>
Signed-off-by: Will Deacon <will@kernel.org>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
---
arch/arm64/include/asm/tlbflush.h | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/arch/arm64/include/asm/tlbflush.h b/arch/arm64/include/asm/tlbflush.h
index 18a5dc0c9a54..0ddb344f83b4 100644
--- a/arch/arm64/include/asm/tlbflush.h
+++ b/arch/arm64/include/asm/tlbflush.h
@@ -38,12 +38,12 @@
: : )
#define __TLBI_1(op, arg) asm (ARM64_ASM_PREAMBLE \
- "tlbi " #op ", %0\n" \
+ "tlbi " #op ", %x0\n" \
ALTERNATIVE("nop\n nop", \
- "dsb ish\n tlbi " #op ", %0", \
+ "dsb ish\n tlbi " #op ", %x0", \
ARM64_WORKAROUND_REPEAT_TLBI, \
CONFIG_ARM64_WORKAROUND_REPEAT_TLBI) \
- : : "r" (arg))
+ : : "rZ" (arg))
#define __TLBI_N(op, arg, n, ...) __TLBI_##n(op, arg)
^ permalink raw reply related
* [PATCH 6.18.y 5/6] arm64: cputype: Add C1-Pro definitions
From: Catalin Marinas @ 2026-04-21 10:00 UTC (permalink / raw)
To: stable; +Cc: Will Deacon, linux-arm-kernel
In-Reply-To: <20260421100018.335793-1-catalin.marinas@arm.com>
commit 2c99561016c591f4c3d5ad7d22a61b8726e79735 upstream.
Add cputype definitions for C1-Pro. These will be used for errata
detection in subsequent patches.
These values can be found in "Table A-303: MIDR_EL1 bit descriptions" in
issue 07 of the C1-Pro TRM:
https://documentation-service.arm.com/static/6930126730f8f55a656570af
Acked-by: Mark Rutland <mark.rutland@arm.com>
Cc: Will Deacon <will@kernel.org>
Cc: James Morse <james.morse@arm.com>
Reviewed-by: Will Deacon <will@kernel.org>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
---
arch/arm64/include/asm/cputype.h | 2 ++
1 file changed, 2 insertions(+)
diff --git a/arch/arm64/include/asm/cputype.h b/arch/arm64/include/asm/cputype.h
index 9b00b75acbf2..18f98fb7ee78 100644
--- a/arch/arm64/include/asm/cputype.h
+++ b/arch/arm64/include/asm/cputype.h
@@ -98,6 +98,7 @@
#define ARM_CPU_PART_CORTEX_A725 0xD87
#define ARM_CPU_PART_CORTEX_A720AE 0xD89
#define ARM_CPU_PART_NEOVERSE_N3 0xD8E
+#define ARM_CPU_PART_C1_PRO 0xD8B
#define APM_CPU_PART_XGENE 0x000
#define APM_CPU_VAR_POTENZA 0x00
@@ -189,6 +190,7 @@
#define MIDR_CORTEX_A725 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A725)
#define MIDR_CORTEX_A720AE MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A720AE)
#define MIDR_NEOVERSE_N3 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_NEOVERSE_N3)
+#define MIDR_C1_PRO MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_C1_PRO)
#define MIDR_THUNDERX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX)
#define MIDR_THUNDERX_81XX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX_81XX)
#define MIDR_THUNDERX_83XX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX_83XX)
^ permalink raw reply related
* [PATCH 6.18.y 6/6] arm64: errata: Work around early CME DVMSync acknowledgement
From: Catalin Marinas @ 2026-04-21 10:00 UTC (permalink / raw)
To: stable; +Cc: Will Deacon, linux-arm-kernel
In-Reply-To: <20260421100018.335793-1-catalin.marinas@arm.com>
commit 0baba94a9779c13c857f6efc55807e6a45b1d4e4 upstream.
C1-Pro acknowledges DVMSync messages before completing the SME/CME
memory accesses. Work around this by issuing an IPI to the affected CPUs
if they are running in EL0 with SME enabled.
Note that we avoid the local DSB in the IPI handler as the kernel runs
with SCTLR_EL1.IESB=1. This is sufficient to complete SME memory
accesses at EL0 on taking an exception to EL1. On the return to user
path, no barrier is necessary either. See the comment in
sme_set_active() and the more detailed explanation in the link below.
To avoid a potential IPI flood from malicious applications (e.g.
madvise(MADV_PAGEOUT) in a tight loop), track where a process is active
via mm_cpumask() and only interrupt those CPUs.
Link: https://lore.kernel.org/r/ablEXwhfKyJW1i7l@J2N7QTR9R3
Cc: Will Deacon <will@kernel.org>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: James Morse <james.morse@arm.com>
Cc: Mark Brown <broonie@kernel.org>
Reviewed-by: Will Deacon <will@kernel.org>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
---
Documentation/arch/arm64/silicon-errata.rst | 2 +
arch/arm64/Kconfig | 12 ++++
arch/arm64/include/asm/cpucaps.h | 2 +
arch/arm64/include/asm/fpsimd.h | 21 ++++++
arch/arm64/include/asm/tlbbatch.h | 10 ++-
arch/arm64/include/asm/tlbflush.h | 72 ++++++++++++++++++-
arch/arm64/kernel/cpu_errata.c | 30 ++++++++
arch/arm64/kernel/entry-common.c | 3 +
arch/arm64/kernel/fpsimd.c | 79 +++++++++++++++++++++
arch/arm64/kernel/process.c | 36 ++++++++++
arch/arm64/tools/cpucaps | 1 +
11 files changed, 264 insertions(+), 4 deletions(-)
diff --git a/Documentation/arch/arm64/silicon-errata.rst b/Documentation/arch/arm64/silicon-errata.rst
index a7ec57060f64..93cdf1693715 100644
--- a/Documentation/arch/arm64/silicon-errata.rst
+++ b/Documentation/arch/arm64/silicon-errata.rst
@@ -202,6 +202,8 @@ stable kernels.
+----------------+-----------------+-----------------+-----------------------------+
| ARM | Neoverse-V3AE | #3312417 | ARM64_ERRATUM_3194386 |
+----------------+-----------------+-----------------+-----------------------------+
+| ARM | C1-Pro | #4193714 | ARM64_ERRATUM_4193714 |
++----------------+-----------------+-----------------+-----------------------------+
| ARM | MMU-500 | #841119,826419 | ARM_SMMU_MMU_500_CPRE_ERRATA|
| | | #562869,1047329 | |
+----------------+-----------------+-----------------+-----------------------------+
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 6663ffd23f25..840a945cb4ac 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -1154,6 +1154,18 @@ config ARM64_ERRATUM_3194386
If unsure, say Y.
+config ARM64_ERRATUM_4193714
+ bool "C1-Pro: 4193714: SME DVMSync early acknowledgement"
+ depends on ARM64_SME
+ default y
+ help
+ Enable workaround for C1-Pro acknowledging the DVMSync before
+ the SME memory accesses are complete. This will cause TLB
+ maintenance for processes using SME to also issue an IPI to
+ the affected CPUs.
+
+ If unsure, say Y.
+
config CAVIUM_ERRATUM_22375
bool "Cavium erratum 22375, 24313"
default y
diff --git a/arch/arm64/include/asm/cpucaps.h b/arch/arm64/include/asm/cpucaps.h
index 9d769291a306..121210b7ffd0 100644
--- a/arch/arm64/include/asm/cpucaps.h
+++ b/arch/arm64/include/asm/cpucaps.h
@@ -66,6 +66,8 @@ cpucap_is_possible(const unsigned int cap)
return IS_ENABLED(CONFIG_ARM64_WORKAROUND_REPEAT_TLBI);
case ARM64_WORKAROUND_SPECULATIVE_SSBS:
return IS_ENABLED(CONFIG_ARM64_ERRATUM_3194386);
+ case ARM64_WORKAROUND_4193714:
+ return IS_ENABLED(CONFIG_ARM64_ERRATUM_4193714);
case ARM64_MPAM:
/*
* KVM MPAM support doesn't rely on the host kernel supporting MPAM.
diff --git a/arch/arm64/include/asm/fpsimd.h b/arch/arm64/include/asm/fpsimd.h
index b8cf0ea43cc0..0fa8d1d5722e 100644
--- a/arch/arm64/include/asm/fpsimd.h
+++ b/arch/arm64/include/asm/fpsimd.h
@@ -428,6 +428,24 @@ static inline size_t sme_state_size(struct task_struct const *task)
return __sme_state_size(task_get_sme_vl(task));
}
+void sme_enable_dvmsync(void);
+void sme_set_active(void);
+void sme_clear_active(void);
+
+static inline void sme_enter_from_user_mode(void)
+{
+ if (alternative_has_cap_unlikely(ARM64_WORKAROUND_4193714) &&
+ test_thread_flag(TIF_SME))
+ sme_clear_active();
+}
+
+static inline void sme_exit_to_user_mode(void)
+{
+ if (alternative_has_cap_unlikely(ARM64_WORKAROUND_4193714) &&
+ test_thread_flag(TIF_SME))
+ sme_set_active();
+}
+
#else
static inline void sme_user_disable(void) { BUILD_BUG(); }
@@ -456,6 +474,9 @@ static inline size_t sme_state_size(struct task_struct const *task)
return 0;
}
+static inline void sme_enter_from_user_mode(void) { }
+static inline void sme_exit_to_user_mode(void) { }
+
#endif /* ! CONFIG_ARM64_SME */
/* For use by EFI runtime services calls only */
diff --git a/arch/arm64/include/asm/tlbbatch.h b/arch/arm64/include/asm/tlbbatch.h
index fedb0b87b8db..6297631532e5 100644
--- a/arch/arm64/include/asm/tlbbatch.h
+++ b/arch/arm64/include/asm/tlbbatch.h
@@ -2,11 +2,17 @@
#ifndef _ARCH_ARM64_TLBBATCH_H
#define _ARCH_ARM64_TLBBATCH_H
+#include <linux/cpumask.h>
+
struct arch_tlbflush_unmap_batch {
+#ifdef CONFIG_ARM64_ERRATUM_4193714
/*
- * For arm64, HW can do tlb shootdown, so we don't
- * need to record cpumask for sending IPI
+ * Track CPUs that need SME DVMSync on completion of this batch.
+ * Otherwise, the arm64 HW can do tlb shootdown, so we don't need to
+ * record cpumask for sending IPI
*/
+ cpumask_var_t cpumask;
+#endif
};
#endif /* _ARCH_ARM64_TLBBATCH_H */
diff --git a/arch/arm64/include/asm/tlbflush.h b/arch/arm64/include/asm/tlbflush.h
index ba36e91aefb8..f53ab3ba0c48 100644
--- a/arch/arm64/include/asm/tlbflush.h
+++ b/arch/arm64/include/asm/tlbflush.h
@@ -80,6 +80,71 @@ static inline unsigned long get_trans_granule(void)
}
}
+#ifdef CONFIG_ARM64_ERRATUM_4193714
+
+void sme_do_dvmsync(const struct cpumask *mask);
+
+static inline void sme_dvmsync(struct mm_struct *mm)
+{
+ if (!alternative_has_cap_unlikely(ARM64_WORKAROUND_4193714))
+ return;
+
+ sme_do_dvmsync(mm_cpumask(mm));
+}
+
+static inline void sme_dvmsync_add_pending(struct arch_tlbflush_unmap_batch *batch,
+ struct mm_struct *mm)
+{
+ if (!alternative_has_cap_unlikely(ARM64_WORKAROUND_4193714))
+ return;
+
+ /*
+ * Order the mm_cpumask() read after the hardware DVMSync.
+ */
+ dsb(ish);
+ if (cpumask_empty(mm_cpumask(mm)))
+ return;
+
+ /*
+ * Allocate the batch cpumask on first use. Fall back to an immediate
+ * IPI for this mm in case of failure.
+ */
+ if (!cpumask_available(batch->cpumask) &&
+ !zalloc_cpumask_var(&batch->cpumask, GFP_ATOMIC)) {
+ sme_do_dvmsync(mm_cpumask(mm));
+ return;
+ }
+
+ cpumask_or(batch->cpumask, batch->cpumask, mm_cpumask(mm));
+}
+
+static inline void sme_dvmsync_batch(struct arch_tlbflush_unmap_batch *batch)
+{
+ if (!alternative_has_cap_unlikely(ARM64_WORKAROUND_4193714))
+ return;
+
+ if (!cpumask_available(batch->cpumask))
+ return;
+
+ sme_do_dvmsync(batch->cpumask);
+ cpumask_clear(batch->cpumask);
+}
+
+#else
+
+static inline void sme_dvmsync(struct mm_struct *mm)
+{
+}
+static inline void sme_dvmsync_add_pending(struct arch_tlbflush_unmap_batch *batch,
+ struct mm_struct *mm)
+{
+}
+static inline void sme_dvmsync_batch(struct arch_tlbflush_unmap_batch *batch)
+{
+}
+
+#endif /* CONFIG_ARM64_ERRATUM_4193714 */
+
/*
* Level-based TLBI operations.
*
@@ -189,12 +254,14 @@ static inline void __tlbi_sync_s1ish(struct mm_struct *mm)
{
dsb(ish);
__repeat_tlbi_sync(vale1is, 0);
+ sme_dvmsync(mm);
}
-static inline void __tlbi_sync_s1ish_batch(void)
+static inline void __tlbi_sync_s1ish_batch(struct arch_tlbflush_unmap_batch *batch)
{
dsb(ish);
__repeat_tlbi_sync(vale1is, 0);
+ sme_dvmsync_batch(batch);
}
static inline void __tlbi_sync_s1ish_kernel(void)
@@ -357,7 +424,7 @@ static inline bool arch_tlbbatch_should_defer(struct mm_struct *mm)
*/
static inline void arch_tlbbatch_flush(struct arch_tlbflush_unmap_batch *batch)
{
- __tlbi_sync_s1ish_batch();
+ __tlbi_sync_s1ish_batch(batch);
}
/*
@@ -546,6 +613,7 @@ static inline void arch_tlbbatch_add_pending(struct arch_tlbflush_unmap_batch *b
struct mm_struct *mm, unsigned long start, unsigned long end)
{
__flush_tlb_range_nosync(mm, start, end, PAGE_SIZE, true, 3);
+ sme_dvmsync_add_pending(batch, mm);
}
#endif
diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c
index 8cb3b575a031..6c8c4301d9c6 100644
--- a/arch/arm64/kernel/cpu_errata.c
+++ b/arch/arm64/kernel/cpu_errata.c
@@ -11,6 +11,7 @@
#include <asm/cpu.h>
#include <asm/cputype.h>
#include <asm/cpufeature.h>
+#include <asm/fpsimd.h>
#include <asm/kvm_asm.h>
#include <asm/smp_plat.h>
@@ -551,6 +552,23 @@ static const struct midr_range erratum_spec_ssbs_list[] = {
};
#endif
+#ifdef CONFIG_ARM64_ERRATUM_4193714
+static bool has_sme_dvmsync_erratum(const struct arm64_cpu_capabilities *entry,
+ int scope)
+{
+ if (!id_aa64pfr1_sme(read_sanitised_ftr_reg(SYS_ID_AA64PFR1_EL1)))
+ return false;
+
+ return is_affected_midr_range(entry, scope);
+}
+
+static void cpu_enable_sme_dvmsync(const struct arm64_cpu_capabilities *__unused)
+{
+ if (this_cpu_has_cap(ARM64_WORKAROUND_4193714))
+ sme_enable_dvmsync();
+}
+#endif
+
#ifdef CONFIG_AMPERE_ERRATUM_AC03_CPU_38
static const struct midr_range erratum_ac03_cpu_38_list[] = {
MIDR_ALL_VERSIONS(MIDR_AMPERE1),
@@ -870,6 +888,18 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
ERRATA_MIDR_RANGE_LIST(erratum_spec_ssbs_list),
},
#endif
+#ifdef CONFIG_ARM64_ERRATUM_4193714
+ {
+ .desc = "C1-Pro SME DVMSync early acknowledgement",
+ .capability = ARM64_WORKAROUND_4193714,
+ .type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM,
+ .matches = has_sme_dvmsync_erratum,
+ .cpu_enable = cpu_enable_sme_dvmsync,
+ /* C1-Pro r0p0 - r1p2 (the latter only when REVIDR_EL1[0]==0) */
+ .midr_range = MIDR_RANGE(MIDR_C1_PRO, 0, 0, 1, 2),
+ MIDR_FIXED(MIDR_CPU_VAR_REV(1, 2), BIT(0)),
+ },
+#endif
#ifdef CONFIG_ARM64_WORKAROUND_SPECULATIVE_UNPRIV_LOAD
{
.desc = "ARM errata 2966298, 3117295",
diff --git a/arch/arm64/kernel/entry-common.c b/arch/arm64/kernel/entry-common.c
index a9c81715ce59..5b97dfcf796d 100644
--- a/arch/arm64/kernel/entry-common.c
+++ b/arch/arm64/kernel/entry-common.c
@@ -21,6 +21,7 @@
#include <asm/daifflags.h>
#include <asm/esr.h>
#include <asm/exception.h>
+#include <asm/fpsimd.h>
#include <asm/irq_regs.h>
#include <asm/kprobes.h>
#include <asm/mmu.h>
@@ -84,6 +85,7 @@ static __always_inline void __enter_from_user_mode(struct pt_regs *regs)
{
enter_from_user_mode(regs);
mte_disable_tco_entry(current);
+ sme_enter_from_user_mode();
}
static __always_inline void arm64_enter_from_user_mode(struct pt_regs *regs)
@@ -102,6 +104,7 @@ static __always_inline void arm64_exit_to_user_mode(struct pt_regs *regs)
local_irq_disable();
exit_to_user_mode_prepare(regs);
local_daif_mask();
+ sme_exit_to_user_mode();
mte_check_tfsr_exit();
exit_to_user_mode();
}
diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c
index e3f8f51748bc..ca18214ce2ab 100644
--- a/arch/arm64/kernel/fpsimd.c
+++ b/arch/arm64/kernel/fpsimd.c
@@ -15,6 +15,7 @@
#include <linux/compiler.h>
#include <linux/cpu.h>
#include <linux/cpu_pm.h>
+#include <linux/cpumask.h>
#include <linux/ctype.h>
#include <linux/kernel.h>
#include <linux/linkage.h>
@@ -28,6 +29,7 @@
#include <linux/sched/task_stack.h>
#include <linux/signal.h>
#include <linux/slab.h>
+#include <linux/smp.h>
#include <linux/stddef.h>
#include <linux/sysctl.h>
#include <linux/swab.h>
@@ -1384,6 +1386,83 @@ void do_sve_acc(unsigned long esr, struct pt_regs *regs)
put_cpu_fpsimd_context();
}
+#ifdef CONFIG_ARM64_ERRATUM_4193714
+
+/*
+ * SME/CME erratum handling.
+ */
+static cpumask_t sme_dvmsync_cpus;
+
+/*
+ * These helpers are only called from non-preemptible contexts, so
+ * smp_processor_id() is safe here.
+ */
+void sme_set_active(void)
+{
+ unsigned int cpu = smp_processor_id();
+
+ if (!cpumask_test_cpu(cpu, &sme_dvmsync_cpus))
+ return;
+
+ cpumask_set_cpu(cpu, mm_cpumask(current->mm));
+
+ /*
+ * A subsequent (post ERET) SME access may use a stale address
+ * translation. On C1-Pro, a TLBI+DSB on a different CPU will wait for
+ * the completion of cpumask_set_cpu() above as it appears in program
+ * order before the SME access. The post-TLBI+DSB read of mm_cpumask()
+ * will lead to the IPI being issued.
+ *
+ * https://lore.kernel.org/r/ablEXwhfKyJW1i7l@J2N7QTR9R3
+ */
+}
+
+void sme_clear_active(void)
+{
+ unsigned int cpu = smp_processor_id();
+
+ if (!cpumask_test_cpu(cpu, &sme_dvmsync_cpus))
+ return;
+
+ /*
+ * With SCTLR_EL1.IESB enabled, the SME memory transactions are
+ * completed on entering EL1.
+ */
+ cpumask_clear_cpu(cpu, mm_cpumask(current->mm));
+}
+
+static void sme_dvmsync_ipi(void *unused)
+{
+ /*
+ * With SCTLR_EL1.IESB on, taking an exception is sufficient to ensure
+ * the completion of the SME memory accesses, so no need for an
+ * explicit DSB.
+ */
+}
+
+void sme_do_dvmsync(const struct cpumask *mask)
+{
+ /*
+ * This is called from the TLB maintenance functions after the DSB ISH
+ * to send the hardware DVMSync message. If this CPU sees the mask as
+ * empty, the remote CPU executing sme_set_active() would have seen
+ * the DVMSync and no IPI required.
+ */
+ if (cpumask_empty(mask))
+ return;
+
+ preempt_disable();
+ smp_call_function_many(mask, sme_dvmsync_ipi, NULL, true);
+ preempt_enable();
+}
+
+void sme_enable_dvmsync(void)
+{
+ cpumask_set_cpu(smp_processor_id(), &sme_dvmsync_cpus);
+}
+
+#endif /* CONFIG_ARM64_ERRATUM_4193714 */
+
/*
* Trapped SME access
*
diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c
index 489554931231..4c328b7c79ba 100644
--- a/arch/arm64/kernel/process.c
+++ b/arch/arm64/kernel/process.c
@@ -26,6 +26,7 @@
#include <linux/reboot.h>
#include <linux/interrupt.h>
#include <linux/init.h>
+#include <linux/cpumask.h>
#include <linux/cpu.h>
#include <linux/elfcore.h>
#include <linux/pm.h>
@@ -339,8 +340,41 @@ void flush_thread(void)
flush_gcs();
}
+#ifdef CONFIG_ARM64_ERRATUM_4193714
+
+static void arch_dup_tlbbatch_mask(struct task_struct *dst)
+{
+ /*
+ * Clear the inherited cpumask with memset() to cover both cases where
+ * cpumask_var_t is a pointer or an array. It will be allocated lazily
+ * in sme_dvmsync_add_pending() if CPUMASK_OFFSTACK=y.
+ */
+ if (alternative_has_cap_unlikely(ARM64_WORKAROUND_4193714))
+ memset(&dst->tlb_ubc.arch.cpumask, 0,
+ sizeof(dst->tlb_ubc.arch.cpumask));
+}
+
+static void arch_release_tlbbatch_mask(struct task_struct *tsk)
+{
+ if (alternative_has_cap_unlikely(ARM64_WORKAROUND_4193714))
+ free_cpumask_var(tsk->tlb_ubc.arch.cpumask);
+}
+
+#else
+
+static void arch_dup_tlbbatch_mask(struct task_struct *dst)
+{
+}
+
+static void arch_release_tlbbatch_mask(struct task_struct *tsk)
+{
+}
+
+#endif /* CONFIG_ARM64_ERRATUM_4193714 */
+
void arch_release_task_struct(struct task_struct *tsk)
{
+ arch_release_tlbbatch_mask(tsk);
fpsimd_release_task(tsk);
}
@@ -356,6 +390,8 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
*dst = *src;
+ arch_dup_tlbbatch_mask(dst);
+
/*
* Drop stale reference to src's sve_state and convert dst to
* non-streaming FPSIMD mode.
diff --git a/arch/arm64/tools/cpucaps b/arch/arm64/tools/cpucaps
index 1b32c1232d28..16d123088ddd 100644
--- a/arch/arm64/tools/cpucaps
+++ b/arch/arm64/tools/cpucaps
@@ -101,6 +101,7 @@ WORKAROUND_2077057
WORKAROUND_2457168
WORKAROUND_2645198
WORKAROUND_2658417
+WORKAROUND_4193714
WORKAROUND_AMPERE_AC03_CPU_38
WORKAROUND_AMPERE_AC04_CPU_23
WORKAROUND_TRBE_OVERWRITE_FILL_MODE
^ permalink raw reply related
* [PATCH 6.18.y 4/6] arm64: tlb: Pass the corresponding mm to __tlbi_sync_s1ish()
From: Catalin Marinas @ 2026-04-21 10:00 UTC (permalink / raw)
To: stable; +Cc: Will Deacon, linux-arm-kernel
In-Reply-To: <20260421100018.335793-1-catalin.marinas@arm.com>
commit d9fb08ba946a6190c371dcd9f9e465d0d52c5021 upstream.
The mm structure will be used for workarounds that need limiting to
specific tasks.
Acked-by: Mark Rutland <mark.rutland@arm.com>
Cc: Will Deacon <will@kernel.org>
Reviewed-by: Will Deacon <will@kernel.org>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
---
arch/arm64/include/asm/tlbflush.h | 8 ++++----
arch/arm64/kernel/sys_compat.c | 2 +-
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/arch/arm64/include/asm/tlbflush.h b/arch/arm64/include/asm/tlbflush.h
index 387bd86af702..ba36e91aefb8 100644
--- a/arch/arm64/include/asm/tlbflush.h
+++ b/arch/arm64/include/asm/tlbflush.h
@@ -185,7 +185,7 @@ do { \
* Complete broadcast TLB maintenance issued by the host which invalidates
* stage 1 information in the host's own translation regime.
*/
-static inline void __tlbi_sync_s1ish(void)
+static inline void __tlbi_sync_s1ish(struct mm_struct *mm)
{
dsb(ish);
__repeat_tlbi_sync(vale1is, 0);
@@ -310,7 +310,7 @@ static inline void flush_tlb_mm(struct mm_struct *mm)
asid = __TLBI_VADDR(0, ASID(mm));
__tlbi(aside1is, asid);
__tlbi_user(aside1is, asid);
- __tlbi_sync_s1ish();
+ __tlbi_sync_s1ish(mm);
mmu_notifier_arch_invalidate_secondary_tlbs(mm, 0, -1UL);
}
@@ -337,7 +337,7 @@ static inline void flush_tlb_page(struct vm_area_struct *vma,
unsigned long uaddr)
{
flush_tlb_page_nosync(vma, uaddr);
- __tlbi_sync_s1ish();
+ __tlbi_sync_s1ish(vma->vm_mm);
}
static inline bool arch_tlbbatch_should_defer(struct mm_struct *mm)
@@ -492,7 +492,7 @@ static inline void __flush_tlb_range(struct vm_area_struct *vma,
{
__flush_tlb_range_nosync(vma->vm_mm, start, end, stride,
last_level, tlb_level);
- __tlbi_sync_s1ish();
+ __tlbi_sync_s1ish(vma->vm_mm);
}
static inline void flush_tlb_range(struct vm_area_struct *vma,
diff --git a/arch/arm64/kernel/sys_compat.c b/arch/arm64/kernel/sys_compat.c
index b9d4998c97ef..03fde2677d5b 100644
--- a/arch/arm64/kernel/sys_compat.c
+++ b/arch/arm64/kernel/sys_compat.c
@@ -37,7 +37,7 @@ __do_compat_cache_op(unsigned long start, unsigned long end)
* We pick the reserved-ASID to minimise the impact.
*/
__tlbi(aside1is, __TLBI_VADDR(0, 0));
- __tlbi_sync_s1ish();
+ __tlbi_sync_s1ish(current->mm);
}
ret = caches_clean_inval_user_pou(start, start + chunk);
^ permalink raw reply related
* [PATCH 6.18.y 3/6] arm64: tlb: Introduce __tlbi_sync_s1ish_{kernel,batch}() for TLB maintenance
From: Catalin Marinas @ 2026-04-21 10:00 UTC (permalink / raw)
To: stable; +Cc: Will Deacon, linux-arm-kernel
In-Reply-To: <20260421100018.335793-1-catalin.marinas@arm.com>
commit 6bfbf574a39139da11af9fdf6e8d56fe1989cd3e upstream.
Add __tlbi_sync_s1ish_kernel() similar to __tlbi_sync_s1ish() and use it
for kernel TLB maintenance. Also use this function in flush_tlb_all()
which is only used in relation to kernel mappings. Subsequent patches
can differentiate between workarounds that apply to user only or both
user and kernel.
A subsequent patch will add mm_struct to __tlbi_sync_s1ish(). Since
arch_tlbbatch_flush() is not specific to an mm, add a corresponding
__tlbi_sync_s1ish_batch() helper.
Acked-by: Mark Rutland <mark.rutland@arm.com>
Cc: Will Deacon <will@kernel.org>
Reviewed-by: Will Deacon <will@kernel.org>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
---
arch/arm64/include/asm/tlbflush.h | 20 ++++++++++++++++----
1 file changed, 16 insertions(+), 4 deletions(-)
diff --git a/arch/arm64/include/asm/tlbflush.h b/arch/arm64/include/asm/tlbflush.h
index c87d13bee37d..387bd86af702 100644
--- a/arch/arm64/include/asm/tlbflush.h
+++ b/arch/arm64/include/asm/tlbflush.h
@@ -191,6 +191,18 @@ static inline void __tlbi_sync_s1ish(void)
__repeat_tlbi_sync(vale1is, 0);
}
+static inline void __tlbi_sync_s1ish_batch(void)
+{
+ dsb(ish);
+ __repeat_tlbi_sync(vale1is, 0);
+}
+
+static inline void __tlbi_sync_s1ish_kernel(void)
+{
+ dsb(ish);
+ __repeat_tlbi_sync(vale1is, 0);
+}
+
/*
* Complete broadcast TLB maintenance issued by hyp code which invalidates
* stage 1 translation information in any translation regime.
@@ -286,7 +298,7 @@ static inline void flush_tlb_all(void)
{
dsb(ishst);
__tlbi(vmalle1is);
- __tlbi_sync_s1ish();
+ __tlbi_sync_s1ish_kernel();
isb();
}
@@ -345,7 +357,7 @@ static inline bool arch_tlbbatch_should_defer(struct mm_struct *mm)
*/
static inline void arch_tlbbatch_flush(struct arch_tlbflush_unmap_batch *batch)
{
- __tlbi_sync_s1ish();
+ __tlbi_sync_s1ish_batch();
}
/*
@@ -512,7 +524,7 @@ static inline void flush_tlb_kernel_range(unsigned long start, unsigned long end
dsb(ishst);
__flush_tlb_range_op(vaale1is, start, pages, stride, 0,
TLBI_TTL_UNKNOWN, false, lpa2_is_enabled());
- __tlbi_sync_s1ish();
+ __tlbi_sync_s1ish_kernel();
isb();
}
@@ -526,7 +538,7 @@ static inline void __flush_tlb_kernel_pgtable(unsigned long kaddr)
dsb(ishst);
__tlbi(vaae1is, addr);
- __tlbi_sync_s1ish();
+ __tlbi_sync_s1ish_kernel();
isb();
}
^ permalink raw reply related
* [PATCH 6.18.y 2/6] arm64: tlb: Optimize ARM64_WORKAROUND_REPEAT_TLBI
From: Catalin Marinas @ 2026-04-21 10:00 UTC (permalink / raw)
To: stable; +Cc: Will Deacon, linux-arm-kernel
In-Reply-To: <20260421100018.335793-1-catalin.marinas@arm.com>
From: Mark Rutland <mark.rutland@arm.com>
commit a8f78680ee6bf795086384e8aea159a52814f827 upstream.
The ARM64_WORKAROUND_REPEAT_TLBI workaround is used to mitigate several
errata where broadcast TLBI;DSB sequences don't provide all the
architecturally required synchronization. The workaround performs more
work than necessary, and can have significant overhead. This patch
optimizes the workaround, as explained below.
The workaround was originally added for Qualcomm Falkor erratum 1009 in
commit:
d9ff80f83ecb ("arm64: Work around Falkor erratum 1009")
As noted in the message for that commit, the workaround is applied even
in cases where it is not strictly necessary.
The workaround was later reused without changes for:
* Arm Cortex-A76 erratum #1286807
SDEN v33: https://developer.arm.com/documentation/SDEN-885749/33-0/
* Arm Cortex-A55 erratum #2441007
SDEN v16: https://developer.arm.com/documentation/SDEN-859338/1600/
* Arm Cortex-A510 erratum #2441009
SDEN v19: https://developer.arm.com/documentation/SDEN-1873351/1900/
The important details to note are as follows:
1. All relevant errata only affect the ordering and/or completion of
memory accesses which have been translated by an invalidated TLB
entry. The actual invalidation of TLB entries is unaffected.
2. The existing workaround is applied to both broadcast and local TLB
invalidation, whereas for all relevant errata it is only necessary to
apply a workaround for broadcast invalidation.
3. The existing workaround replaces every TLBI with a TLBI;DSB;TLBI
sequence, whereas for all relevant errata it is only necessary to
execute a single additional TLBI;DSB sequence after any number of
TLBIs are completed by a DSB.
For example, for a sequence of batched TLBIs:
TLBI <op1>[, <arg1>]
TLBI <op2>[, <arg2>]
TLBI <op3>[, <arg3>]
DSB ISH
... the existing workaround will expand this to:
TLBI <op1>[, <arg1>]
DSB ISH // additional
TLBI <op1>[, <arg1>] // additional
TLBI <op2>[, <arg2>]
DSB ISH // additional
TLBI <op2>[, <arg2>] // additional
TLBI <op3>[, <arg3>]
DSB ISH // additional
TLBI <op3>[, <arg3>] // additional
DSB ISH
... whereas it is sufficient to have:
TLBI <op1>[, <arg1>]
TLBI <op2>[, <arg2>]
TLBI <op3>[, <arg3>]
DSB ISH
TLBI <opX>[, <argX>] // additional
DSB ISH // additional
Using a single additional TBLI and DSB at the end of the sequence can
have significantly lower overhead as each DSB which completes a TLBI
must synchronize with other PEs in the system, with potential
performance effects both locally and system-wide.
4. The existing workaround repeats each specific TLBI operation, whereas
for all relevant errata it is sufficient for the additional TLBI to
use *any* operation which will be broadcast, regardless of which
translation regime or stage of translation the operation applies to.
For example, for a single TLBI:
TLBI ALLE2IS
DSB ISH
... the existing workaround will expand this to:
TLBI ALLE2IS
DSB ISH
TLBI ALLE2IS // additional
DSB ISH // additional
... whereas it is sufficient to have:
TLBI ALLE2IS
DSB ISH
TLBI VALE1IS, XZR // additional
DSB ISH // additional
As the additional TLBI doesn't have to match a specific earlier TLBI,
the additional TLBI can be implemented in separate code, with no
memory of the earlier TLBIs. The additional TLBI can also use a
cheaper TLBI operation.
5. The existing workaround is applied to both Stage-1 and Stage-2 TLB
invalidation, whereas for all relevant errata it is only necessary to
apply a workaround for Stage-1 invalidation.
Architecturally, TLBI operations which invalidate only Stage-2
information (e.g. IPAS2E1IS) are not required to invalidate TLB
entries which combine information from Stage-1 and Stage-2
translation table entries, and consequently may not complete memory
accesses translated by those combined entries. In these cases,
completion of memory accesses is only guaranteed after subsequent
invalidation of Stage-1 information (e.g. VMALLE1IS).
Taking the above points into account, this patch reworks the workaround
logic to reduce overhead:
* New __tlbi_sync_s1ish() and __tlbi_sync_s1ish_hyp() functions are
added and used in place of any dsb(ish) which is used to complete
broadcast Stage-1 TLB maintenance. When the
ARM64_WORKAROUND_REPEAT_TLBI workaround is enabled, these helpers will
execute an additional TLBI;DSB sequence.
For consistency, it might make sense to add __tlbi_sync_*() helpers
for local and stage 2 maintenance. For now I've left those with
open-coded dsb() to keep the diff small.
* The duplication of TLBIs in __TLBI_0() and __TLBI_1() is removed. This
is no longer needed as the necessary synchronization will happen in
__tlbi_sync_s1ish() or __tlbi_sync_s1ish_hyp().
* The additional TLBI operation is chosen to have minimal impact:
- __tlbi_sync_s1ish() uses "TLBI VALE1IS, XZR". This is only used at
EL1 or at EL2 with {E2H,TGE}=={1,1}, where it will target an unused
entry for the reserved ASID in the kernel's own translation regime,
and have no adverse affect.
- __tlbi_sync_s1ish_hyp() uses "TLBI VALE2IS, XZR". This is only used
in hyp code, where it will target an unused entry in the hyp code's
TTBR0 mapping, and should have no adverse effect.
* As __TLBI_0() and __TLBI_1() no longer replace each TLBI with a
TLBI;DSB;TLBI sequence, batching TLBIs is worthwhile, and there's no
need for arch_tlbbatch_should_defer() to consider
ARM64_WORKAROUND_REPEAT_TLBI.
When building defconfig with GCC 15.1.0, compared to v6.19-rc1, this
patch saves ~1KiB of text, makes the vmlinux ~42KiB smaller, and makes
the resulting Image 64KiB smaller:
| [mark@lakrids:~/src/linux]% size vmlinux-*
| text data bss dec hex filename
| 21179831 19660919 708216 41548966 279fca6 vmlinux-after
| 21181075 19660903 708216 41550194 27a0172 vmlinux-before
| [mark@lakrids:~/src/linux]% ls -l vmlinux-*
| -rwxr-xr-x 1 mark mark 157771472 Feb 4 12:05 vmlinux-after
| -rwxr-xr-x 1 mark mark 157815432 Feb 4 12:05 vmlinux-before
| [mark@lakrids:~/src/linux]% ls -l Image-*
| -rw-r--r-- 1 mark mark 41007616 Feb 4 12:05 Image-after
| -rw-r--r-- 1 mark mark 41073152 Feb 4 12:05 Image-before
Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Marc Zyngier <maz@kernel.org>
Cc: Oliver Upton <oupton@kernel.org>
Cc: Ryan Roberts <ryan.roberts@arm.com>
Cc: Will Deacon <will@kernel.org>
Signed-off-by: Will Deacon <will@kernel.org>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
---
arch/arm64/include/asm/tlbflush.h | 59 ++++++++++++++++++-------------
arch/arm64/kernel/sys_compat.c | 2 +-
arch/arm64/kvm/hyp/nvhe/mm.c | 2 +-
arch/arm64/kvm/hyp/nvhe/tlb.c | 8 ++---
arch/arm64/kvm/hyp/pgtable.c | 2 +-
arch/arm64/kvm/hyp/vhe/tlb.c | 10 +++---
6 files changed, 47 insertions(+), 36 deletions(-)
diff --git a/arch/arm64/include/asm/tlbflush.h b/arch/arm64/include/asm/tlbflush.h
index 0ddb344f83b4..c87d13bee37d 100644
--- a/arch/arm64/include/asm/tlbflush.h
+++ b/arch/arm64/include/asm/tlbflush.h
@@ -31,18 +31,10 @@
*/
#define __TLBI_0(op, arg) asm (ARM64_ASM_PREAMBLE \
"tlbi " #op "\n" \
- ALTERNATIVE("nop\n nop", \
- "dsb ish\n tlbi " #op, \
- ARM64_WORKAROUND_REPEAT_TLBI, \
- CONFIG_ARM64_WORKAROUND_REPEAT_TLBI) \
: : )
#define __TLBI_1(op, arg) asm (ARM64_ASM_PREAMBLE \
"tlbi " #op ", %x0\n" \
- ALTERNATIVE("nop\n nop", \
- "dsb ish\n tlbi " #op ", %x0", \
- ARM64_WORKAROUND_REPEAT_TLBI, \
- CONFIG_ARM64_WORKAROUND_REPEAT_TLBI) \
: : "rZ" (arg))
#define __TLBI_N(op, arg, n, ...) __TLBI_##n(op, arg)
@@ -181,6 +173,34 @@ static inline unsigned long get_trans_granule(void)
(__pages >> (5 * (scale) + 1)) - 1; \
})
+#define __repeat_tlbi_sync(op, arg...) \
+do { \
+ if (!alternative_has_cap_unlikely(ARM64_WORKAROUND_REPEAT_TLBI)) \
+ break; \
+ __tlbi(op, ##arg); \
+ dsb(ish); \
+} while (0)
+
+/*
+ * Complete broadcast TLB maintenance issued by the host which invalidates
+ * stage 1 information in the host's own translation regime.
+ */
+static inline void __tlbi_sync_s1ish(void)
+{
+ dsb(ish);
+ __repeat_tlbi_sync(vale1is, 0);
+}
+
+/*
+ * Complete broadcast TLB maintenance issued by hyp code which invalidates
+ * stage 1 translation information in any translation regime.
+ */
+static inline void __tlbi_sync_s1ish_hyp(void)
+{
+ dsb(ish);
+ __repeat_tlbi_sync(vale2is, 0);
+}
+
/*
* TLB Invalidation
* ================
@@ -266,7 +286,7 @@ static inline void flush_tlb_all(void)
{
dsb(ishst);
__tlbi(vmalle1is);
- dsb(ish);
+ __tlbi_sync_s1ish();
isb();
}
@@ -278,7 +298,7 @@ static inline void flush_tlb_mm(struct mm_struct *mm)
asid = __TLBI_VADDR(0, ASID(mm));
__tlbi(aside1is, asid);
__tlbi_user(aside1is, asid);
- dsb(ish);
+ __tlbi_sync_s1ish();
mmu_notifier_arch_invalidate_secondary_tlbs(mm, 0, -1UL);
}
@@ -305,20 +325,11 @@ static inline void flush_tlb_page(struct vm_area_struct *vma,
unsigned long uaddr)
{
flush_tlb_page_nosync(vma, uaddr);
- dsb(ish);
+ __tlbi_sync_s1ish();
}
static inline bool arch_tlbbatch_should_defer(struct mm_struct *mm)
{
- /*
- * TLB flush deferral is not required on systems which are affected by
- * ARM64_WORKAROUND_REPEAT_TLBI, as __tlbi()/__tlbi_user() implementation
- * will have two consecutive TLBI instructions with a dsb(ish) in between
- * defeating the purpose (i.e save overall 'dsb ish' cost).
- */
- if (alternative_has_cap_unlikely(ARM64_WORKAROUND_REPEAT_TLBI))
- return false;
-
return true;
}
@@ -334,7 +345,7 @@ static inline bool arch_tlbbatch_should_defer(struct mm_struct *mm)
*/
static inline void arch_tlbbatch_flush(struct arch_tlbflush_unmap_batch *batch)
{
- dsb(ish);
+ __tlbi_sync_s1ish();
}
/*
@@ -469,7 +480,7 @@ static inline void __flush_tlb_range(struct vm_area_struct *vma,
{
__flush_tlb_range_nosync(vma->vm_mm, start, end, stride,
last_level, tlb_level);
- dsb(ish);
+ __tlbi_sync_s1ish();
}
static inline void flush_tlb_range(struct vm_area_struct *vma,
@@ -501,7 +512,7 @@ static inline void flush_tlb_kernel_range(unsigned long start, unsigned long end
dsb(ishst);
__flush_tlb_range_op(vaale1is, start, pages, stride, 0,
TLBI_TTL_UNKNOWN, false, lpa2_is_enabled());
- dsb(ish);
+ __tlbi_sync_s1ish();
isb();
}
@@ -515,7 +526,7 @@ static inline void __flush_tlb_kernel_pgtable(unsigned long kaddr)
dsb(ishst);
__tlbi(vaae1is, addr);
- dsb(ish);
+ __tlbi_sync_s1ish();
isb();
}
diff --git a/arch/arm64/kernel/sys_compat.c b/arch/arm64/kernel/sys_compat.c
index 4a609e9b65de..b9d4998c97ef 100644
--- a/arch/arm64/kernel/sys_compat.c
+++ b/arch/arm64/kernel/sys_compat.c
@@ -37,7 +37,7 @@ __do_compat_cache_op(unsigned long start, unsigned long end)
* We pick the reserved-ASID to minimise the impact.
*/
__tlbi(aside1is, __TLBI_VADDR(0, 0));
- dsb(ish);
+ __tlbi_sync_s1ish();
}
ret = caches_clean_inval_user_pou(start, start + chunk);
diff --git a/arch/arm64/kvm/hyp/nvhe/mm.c b/arch/arm64/kvm/hyp/nvhe/mm.c
index ae8391baebc3..218976287d3f 100644
--- a/arch/arm64/kvm/hyp/nvhe/mm.c
+++ b/arch/arm64/kvm/hyp/nvhe/mm.c
@@ -271,7 +271,7 @@ static void fixmap_clear_slot(struct hyp_fixmap_slot *slot)
*/
dsb(ishst);
__tlbi_level(vale2is, __TLBI_VADDR(addr, 0), level);
- dsb(ish);
+ __tlbi_sync_s1ish_hyp();
isb();
}
diff --git a/arch/arm64/kvm/hyp/nvhe/tlb.c b/arch/arm64/kvm/hyp/nvhe/tlb.c
index 48da9ca9763f..3dc1ce0d27fe 100644
--- a/arch/arm64/kvm/hyp/nvhe/tlb.c
+++ b/arch/arm64/kvm/hyp/nvhe/tlb.c
@@ -169,7 +169,7 @@ void __kvm_tlb_flush_vmid_ipa(struct kvm_s2_mmu *mmu,
*/
dsb(ish);
__tlbi(vmalle1is);
- dsb(ish);
+ __tlbi_sync_s1ish_hyp();
isb();
exit_vmid_context(&cxt);
@@ -226,7 +226,7 @@ void __kvm_tlb_flush_vmid_range(struct kvm_s2_mmu *mmu,
dsb(ish);
__tlbi(vmalle1is);
- dsb(ish);
+ __tlbi_sync_s1ish_hyp();
isb();
exit_vmid_context(&cxt);
@@ -240,7 +240,7 @@ void __kvm_tlb_flush_vmid(struct kvm_s2_mmu *mmu)
enter_vmid_context(mmu, &cxt, false);
__tlbi(vmalls12e1is);
- dsb(ish);
+ __tlbi_sync_s1ish_hyp();
isb();
exit_vmid_context(&cxt);
@@ -266,5 +266,5 @@ void __kvm_flush_vm_context(void)
/* Same remark as in enter_vmid_context() */
dsb(ish);
__tlbi(alle1is);
- dsb(ish);
+ __tlbi_sync_s1ish_hyp();
}
diff --git a/arch/arm64/kvm/hyp/pgtable.c b/arch/arm64/kvm/hyp/pgtable.c
index c351b4abd5db..cbf8cd2e1673 100644
--- a/arch/arm64/kvm/hyp/pgtable.c
+++ b/arch/arm64/kvm/hyp/pgtable.c
@@ -483,7 +483,7 @@ static int hyp_unmap_walker(const struct kvm_pgtable_visit_ctx *ctx,
*unmapped += granule;
}
- dsb(ish);
+ __tlbi_sync_s1ish_hyp();
isb();
mm_ops->put_page(ctx->ptep);
diff --git a/arch/arm64/kvm/hyp/vhe/tlb.c b/arch/arm64/kvm/hyp/vhe/tlb.c
index ec2569818629..35855dadfb1b 100644
--- a/arch/arm64/kvm/hyp/vhe/tlb.c
+++ b/arch/arm64/kvm/hyp/vhe/tlb.c
@@ -115,7 +115,7 @@ void __kvm_tlb_flush_vmid_ipa(struct kvm_s2_mmu *mmu,
*/
dsb(ish);
__tlbi(vmalle1is);
- dsb(ish);
+ __tlbi_sync_s1ish_hyp();
isb();
exit_vmid_context(&cxt);
@@ -176,7 +176,7 @@ void __kvm_tlb_flush_vmid_range(struct kvm_s2_mmu *mmu,
dsb(ish);
__tlbi(vmalle1is);
- dsb(ish);
+ __tlbi_sync_s1ish_hyp();
isb();
exit_vmid_context(&cxt);
@@ -192,7 +192,7 @@ void __kvm_tlb_flush_vmid(struct kvm_s2_mmu *mmu)
enter_vmid_context(mmu, &cxt);
__tlbi(vmalls12e1is);
- dsb(ish);
+ __tlbi_sync_s1ish_hyp();
isb();
exit_vmid_context(&cxt);
@@ -217,7 +217,7 @@ void __kvm_flush_vm_context(void)
{
dsb(ishst);
__tlbi(alle1is);
- dsb(ish);
+ __tlbi_sync_s1ish_hyp();
}
/*
@@ -358,7 +358,7 @@ int __kvm_tlbi_s1e2(struct kvm_s2_mmu *mmu, u64 va, u64 sys_encoding)
default:
ret = -EINVAL;
}
- dsb(ish);
+ __tlbi_sync_s1ish_hyp();
isb();
if (mmu)
^ permalink raw reply related
* Re: [PATCH v5 04/12] coresight: etm4x: exclude ss_status from drvdata->config
From: Yeoreum Yun @ 2026-04-21 10:03 UTC (permalink / raw)
To: Mike Leach
Cc: Suzuki K Poulose, Leo Yan, coresight, linux-arm-kernel,
linux-kernel, james.clark, alexander.shishkin, jie.gan
In-Reply-To: <f2b0dcc5-8002-4ee9-a219-fb361573a9c3@arm.com>
Hi Mike,
> Hi,
>
> This register [bit 31] indicates if a single shot comparator has matched. So
> read-back provides information to the user post run to determine which if
> any of the comparators set in this way has actually matched.
Okay. so after disable sysfs session, to check former session
check whether comprator has matched.
>
> Moreover, the specification states "Software must reset this bit to 0 to
> re-enable single-shot control" and "Reset state is unknown. STATUS must be
> written to set an initial state...."
>
> Therefore this register must be written as part of any configuration so
> should be available in the drvdata->config for both read and write,
But I don't think this is the reason for locate ss_status into "config"
since its write purpose is not to configure but the "clear" former bit.
That's why I think it's enough to clear when the new sysfs session starts.
Am I missing something?
Thanks!
--
Sincerely,
Yeoreum Yun
^ permalink raw reply
* Re: [PATCH v2 1/3] MAINTAINERS: Move Peter De Schrijver to CREDITS
From: Thierry Reding @ 2026-04-21 10:10 UTC (permalink / raw)
To: Geert Uytterhoeven
Cc: Thierry Reding, Aaro Koskinen, linux-tegra, linux-arm-kernel,
linux-pm, linux-omap, linux-m68k, devicetree, linux-kernel,
Paul Walmsley
In-Reply-To: <CAMuHMdWeXS3ytgozp-mSrW4jcMRCW7_tbDTbMoEdXdbVj0dqJA@mail.gmail.com>
[-- Attachment #1: Type: text/plain, Size: 1034 bytes --]
On Mon, Apr 20, 2026 at 08:50:06AM +0200, Geert Uytterhoeven wrote:
> Hi Thierry,
>
> On Fri, 17 Apr 2026 at 15:15, Thierry Reding <thierry.reding@kernel.org> wrote:
> > From: Thierry Reding <treding@nvidia.com>
> >
> > Peter sadly passed away a while back. Paul did a much better job at
> > finding the right words to mourn this loss than I ever could, so I will
> > leave this link here:
> >
> > https://lore.kernel.org/lkml/alpine.DEB.2.21.999.2407240345480.11116@utopia.booyaka.com/T/#u
> >
> > Co-developed-by: Paul Walmsley <pjw@kernel.org>
> > Co-developed-by: Aaro Koskinen <aaro.koskinen@iki.fi>
> > Co-developed-by: Geert Uytterhoeven <geert@linux-m68k.org>
>
> "every Co-developed-by: must be immediately
> followed by a Signed-off-by: of the associated co-author."
>
> https://elixir.bootlin.com/linux/v7.0/source/Documentation/process/submitting-patches.rst#L506
>
> Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
Good point. Thanks, I'll add that to the patch.
Thierry
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply
* Re: [PATCH v2 2/2] arm64: dts: amlogic: add support for X98Q
From: Krzysztof Kozlowski @ 2026-04-21 10:22 UTC (permalink / raw)
To: christian.koever-draxl, robh, krzk+dt, conor+dt, neil.armstrong,
khilman
Cc: jbrunet, martin.blumenstingl, funderscore, devicetree,
linux-kernel, linux-arm-kernel, linux-amlogic
In-Reply-To: <20260420061854.5421-3-christian.koever-draxl@student.uibk.ac.at>
On 20/04/2026 08:18, christian.koever-draxl@student.uibk.ac.at wrote:
> From: Christian Stefan Kövér-Draxl <christian.koever-draxl@student.uibk.ac.at>
>
> Signed-off-by: Christian Stefan Kövér-Draxl <christian.koever-draxl@student.uibk.ac.at>
> ---
> arch/arm64/boot/dts/amlogic/Makefile | 1 +
> .../boot/dts/amlogic/meson-s4-s905w2-x98q.dts | 250 ++++++++++++++++++
> 2 files changed, 251 insertions(+)
> create mode 100644 arch/arm64/boot/dts/amlogic/meson-s4-s905w2-x98q.dts
>
> diff --git a/arch/arm64/boot/dts/amlogic/Makefile b/arch/arm64/boot/dts/amlogic/Makefile
> index 15f9c817e502..c7752684dea6 100644
> --- a/arch/arm64/boot/dts/amlogic/Makefile
> +++ b/arch/arm64/boot/dts/amlogic/Makefile
> @@ -85,6 +85,7 @@ dtb-$(CONFIG_ARCH_MESON) += meson-gxm-ugoos-am3.dtb
> dtb-$(CONFIG_ARCH_MESON) += meson-gxm-vega-s96.dtb
> dtb-$(CONFIG_ARCH_MESON) += meson-gxm-wetek-core2.dtb
> dtb-$(CONFIG_ARCH_MESON) += meson-s4-s805x2-aq222.dtb
> +dtb-$(CONFIG_ARCH_MESON) += meson-s4-s905w2-x98q.dtb
> dtb-$(CONFIG_ARCH_MESON) += meson-s4-s905y4-khadas-vim1s.dtb
> dtb-$(CONFIG_ARCH_MESON) += meson-sm1-a95xf3-air-gbit.dtb
> dtb-$(CONFIG_ARCH_MESON) += meson-sm1-a95xf3-air.dtb
> diff --git a/arch/arm64/boot/dts/amlogic/meson-s4-s905w2-x98q.dts b/arch/arm64/boot/dts/amlogic/meson-s4-s905w2-x98q.dts
> new file mode 100644
> index 000000000000..26c60a4c2a43
> --- /dev/null
> +++ b/arch/arm64/boot/dts/amlogic/meson-s4-s905w2-x98q.dts
> @@ -0,0 +1,250 @@
> +
> +// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
You have still the same warnings as before. Fix them ALL, not just one
warning. Are you sure you tested your work with standard tools?
Please run scripts/checkpatch.pl on the patches and fix reported
warnings. After that, run also 'scripts/checkpatch.pl --strict' on the
patches and (probably) fix more warnings. Some warnings can be ignored,
especially from --strict run, but the code here looks like it needs a
fix. Feel free to get in touch if the warning is not clear.
Best regards,
Krzysztof
^ permalink raw reply
* Re: [PATCH V3] dmaengine: imx-sdma: Fix SPBA bus detection on multi-SPBA platforms
From: Shengjiu Wang @ 2026-04-21 10:25 UTC (permalink / raw)
To: Marco Felsch
Cc: Shengjiu Wang, vkoul, Frank.Li, s.hauer, kernel, festevam,
dmaengine, imx, linux-arm-kernel, linux-kernel
In-Reply-To: <4xbeeozhngkkc66r3ho523vr45yksbyftdckfzwk72zfvwzgv2@7lodth3abysr>
On Tue, Apr 21, 2026 at 5:44 PM Marco Felsch <m.felsch@pengutronix.de> wrote:
>
> On 26-04-21, Shengjiu Wang wrote:
> > On Tue, Apr 21, 2026 at 4:57 PM Marco Felsch <m.felsch@pengutronix.de> wrote:
> > >
> > > On 26-04-20, Shengjiu Wang wrote:
> > > > i.MX8M platforms have multiple SPBA buses under different AIPS buses.
> > > > The current code searches the entire device tree and returns the first
> > > > SPBA bus found, which may not be under the same AIPS bus as the SDMA
> > > > controller.
> > > >
> > > > This breaks SDMA P2P transfers because the SDMA script needs to know
> > > > if peripherals are on SPBA or AIPS to configure watermark levels
> > > > correctly. Using the wrong SPBA bus causes DMA timeouts and transfer
> > > > failures.
> > > >
> > > > Fix by searching for the SPBA bus under the SDMA's parent node (AIPS)
> > > > first, then falling back to a global search for backward compatibility.
> > > >
> > > > Example device tree showing the issue:
> > > > aips1 {
> > > > spba1 { sai@...; }; /* Correct SPBA for sdma1 */
> > > > sdma1@...;
> > > > };
> > > > aips2 {
> > > > spba2 { uart@...; }; /* Wrong SPBA - found first by old code */
> > > > };
> > > >
> > > > Fixes: 8391ecf465ec ("dmaengine: imx-sdma: Add device to device support")
> > > > Cc: stable@vger.kernel.org
> > > > Signed-off-by: Shengjiu Wang <shengjiu.wang@nxp.com>
> > > > ---
> > > > changs in v3:
> > > > - add fallback to a global search for backward compatibility, which is
> > > > to address comments from sashiko.dev
> > > > - update commit subject and commit message
> > > > - add comments in code.
> > > > - add Cc stable tag
> > > > - Don't add Frank's RB on v2 as there are several other changes.
> > > >
> > > > changes in v2:
> > > > - add fixes tag
> > > > - use __free(device_node) for auto release.
> > > >
> > > > drivers/dma/imx-sdma.c | 13 ++++++++++++-
> > > > 1 file changed, 12 insertions(+), 1 deletion(-)
> > > >
> > > > diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
> > > > index 3d527883776b..592705af2319 100644
> > > > --- a/drivers/dma/imx-sdma.c
> > > > +++ b/drivers/dma/imx-sdma.c
> > > > @@ -2364,7 +2364,18 @@ static int sdma_probe(struct platform_device *pdev)
> > > > return dev_err_probe(&pdev->dev, ret,
> > > > "failed to register controller\n");
> > > >
> > > > - spba_bus = of_find_compatible_node(NULL, NULL, "fsl,spba-bus");
> > > > + /*
> > > > + * On i.MX8M platforms with multiple SPBA buses, we need to find
> > > > + * the SPBA bus that's under the same AIPS bus as this SDMA controller.
> > > > + * First check the SDMA's parent (AIPS bus) for a child SPBA bus.
> > > > + * If not found, fall back to searching the entire device tree for
> > > > + * backward compatibility with older platforms.
> > > > + */
> > > > + struct device_node *sdma_parent_np __free(device_node) = of_get_parent(np);
> > > > +
> > > > + spba_bus = of_get_compatible_child(sdma_parent_np, "fsl,spba-bus");
> > > > + if (!spba_bus)
> > > > + spba_bus = of_find_compatible_node(NULL, NULL, "fsl,spba-bus");
> > >
> > > And yet the search is still broken for i.MX8MP case since this platform
> > > has two sdma engines below the bus@30df0000.
> >
> > I tested on i.MX8MP. It works. Above line is for backward compatibility
> >
> > The search has no dependence on the number of sdma engines. It searches the
> > spba-bus, not the sdma node. it will find the aips5 first, then find
> > the spba-bus for
> > sdma2 and sdma3.
>
> And you're abosulte certain that NXP doesn't introduce a 2nd SPBA bus
> below the same AIPS in which case the driver is broken again?
Good question. Currently there are no two SPBA buses in the same AIPS
for all existing i.MX platforms and there is no such plan in the
current roadmap,
SDMA is replaced by EDMA from i.MX9.
>
> Sorry for beeing a bit picky. I do see that NXP decided to drop the SDMA
> for i.MX9, at least I don't find any reference in which case I'm fine
> with the patch.
Thanks. The change should be safe.
Best regards
Shengjiu Wang
^ permalink raw reply
* [PATCH RESEND v4 0/8] can: flexcan: Add NXP S32N79 SoC support
From: Ciprian Costea @ 2026-04-21 10:25 UTC (permalink / raw)
To: Marc Kleine-Budde, Vincent Mailhol, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Frank Li, Sascha Hauer,
Fabio Estevam
Cc: Pengutronix Kernel Team, linux-can, devicetree, linux-kernel, imx,
linux-arm-kernel, NXP S32 Linux Team, Christophe Lizzi,
Alberto Ruiz, Enric Balletbo, Eric Chanudet,
Ciprian Marian Costea
From: Ciprian Marian Costea <ciprianmarian.costea@oss.nxp.com>
This patch series adds FlexCAN support for the NXP S32N79 SoC.
The S32N79 is an automotive-grade processor from NXP with multiple
FlexCAN instances. The FlexCAN IP integration on S32N79 differs from
other SoCs in the interrupt routing - it uses two separate interrupt
lines:
- one interrupt for mailboxes 0-127
- one interrupt for bus error detection and device state changes
The CAN controllers are connected through an irqsteer interrupt
controller in the RCU (Resource Control Unit) domain.
This series:
1. Splits flexcan_irq() into dedicated handlers for multi-IRQ platforms
2. Adds dt-bindings documentation for S32N79 FlexCAN
3. Introduces FLEXCAN_QUIRK_IRQ_BERR to handle the two-interrupt
configuration
4. Adds S32N79 device data and compatible string to the driver
5. Adds FlexCAN device tree nodes for S32N79 SoC
6. Enables FlexCAN devices on the S32N79-RDB board
Tested on S32N79-RDB board with CAN and CAN FD communication.
This is a resend of v4 with no changes.
v4 -> v3
- flexcan_chip_interrupts_enable(): disable/enable all IRQ lines
(not just dev->irq) during IMASK register writes
- Split rx/tx masks per mailbox IRQ line (struct flexcan_mb_irq) so
each handler on S32G2 only processes its own MB range
- Added received Acked-by tag on DT bindings patch
v3 -> v2
- Split flexcan_irq() into dedicated handlers (flexcan_irq_mb,
flexcan_irq_boff, flexcan_irq_berr) to fix duplicate event
processing when multiple IRQ lines run concurrently (new patch).
- Added flexcan_irq_esr() handler composing state + berr for S32N79
- Ordered quirks used by s32n devtype data by value.
v2 -> v1
- Renamed FLEXCAN_QUIRK_NR_IRQ_2 to FLEXCAN_QUIRK_IRQ_BERR to better
describe the actual hardware feature
- Appended new quirk at the end
- Switched from platform_get_irq to platform_get_irq_byname usage
- Updated interrupt description in dt-bindings
Ciprian Marian Costea (8):
can: flexcan: use dedicated IRQ handlers for multi-IRQ platforms
can: flexcan: disable all IRQ lines in
flexcan_chip_interrupts_enable()
can: flexcan: split rx/tx masks per mailbox IRQ line
dt-bindings: can: fsl,flexcan: add NXP S32N79 SoC support
can: flexcan: add FLEXCAN_QUIRK_IRQ_BERR quirk
can: flexcan: add NXP S32N79 SoC support
arm64: dts: s32n79: add FlexCAN nodes
arm64: dts: s32n79: enable FlexCAN devices
.../bindings/net/can/fsl,flexcan.yaml | 30 ++-
arch/arm64/boot/dts/freescale/s32n79-rdb.dts | 12 +
arch/arm64/boot/dts/freescale/s32n79.dtsi | 50 ++++
drivers/net/can/flexcan/flexcan-core.c | 249 +++++++++++++++---
drivers/net/can/flexcan/flexcan.h | 12 +-
5 files changed, 316 insertions(+), 37 deletions(-)
--
2.43.0
^ permalink raw reply
* [PATCH RESEND v4 1/8] can: flexcan: use dedicated IRQ handlers for multi-IRQ platforms
From: Ciprian Costea @ 2026-04-21 10:25 UTC (permalink / raw)
To: Marc Kleine-Budde, Vincent Mailhol, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Frank Li, Sascha Hauer,
Fabio Estevam
Cc: Pengutronix Kernel Team, linux-can, devicetree, linux-kernel, imx,
linux-arm-kernel, NXP S32 Linux Team, Christophe Lizzi,
Alberto Ruiz, Enric Balletbo, Eric Chanudet,
Ciprian Marian Costea
In-Reply-To: <20260421102603.4122332-1-ciprianmarian.costea@oss.nxp.com>
From: Ciprian Marian Costea <ciprianmarian.costea@oss.nxp.com>
On platforms with multiple IRQ lines (S32G2, MCF5441X), all lines are
registered to the same flexcan_irq() handler. Since these are distinct IRQ
numbers, they can be dispatched concurrently on different CPUs. Both
instances then read the same iflag and ESR registers unconditionally,
leading to duplicate frame processing.
Fix this by splitting the monolithic handler into focused parts:
- flexcan_do_mb(): processes mailbox events
- flexcan_do_state(): processes device state change events
- flexcan_do_berr(): processes bus error events
Introduce dedicated IRQ handlers for multi-IRQ platforms:
- flexcan_irq_mb(): mailbox-only, used for mb-0, mb-1 IRQ lines
- flexcan_irq_boff(): state-change-only, used for boff/state IRQ line
- flexcan_irq_berr(): bus-error-only, used for berr IRQ line
The combined flexcan_irq() handler is preserved for single-IRQ
platforms with no functional change.
Fixes: d9cead75b1c6 ("can: flexcan: add mcf5441x support")
Signed-off-by: Ciprian Marian Costea <ciprianmarian.costea@oss.nxp.com>
---
drivers/net/can/flexcan/flexcan-core.c | 128 +++++++++++++++++++++----
1 file changed, 111 insertions(+), 17 deletions(-)
diff --git a/drivers/net/can/flexcan/flexcan-core.c b/drivers/net/can/flexcan/flexcan-core.c
index f5d22c61503f..f73ff442d530 100644
--- a/drivers/net/can/flexcan/flexcan-core.c
+++ b/drivers/net/can/flexcan/flexcan-core.c
@@ -1070,16 +1070,14 @@ static struct sk_buff *flexcan_mailbox_read(struct can_rx_offload *offload,
return skb;
}
-static irqreturn_t flexcan_irq(int irq, void *dev_id)
+/* Process mailbox (RX + TX) events */
+static irqreturn_t flexcan_do_mb(struct net_device *dev)
{
- struct net_device *dev = dev_id;
struct net_device_stats *stats = &dev->stats;
struct flexcan_priv *priv = netdev_priv(dev);
struct flexcan_regs __iomem *regs = priv->regs;
irqreturn_t handled = IRQ_NONE;
u64 reg_iflag_tx;
- u32 reg_esr;
- enum can_state last_state = priv->can.state;
/* reception interrupt */
if (priv->devtype_data.quirks & FLEXCAN_QUIRK_USE_RX_MAILBOX) {
@@ -1131,25 +1129,57 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id)
netif_wake_queue(dev);
}
+ return handled;
+}
+
+/* Process bus error events */
+static irqreturn_t flexcan_do_berr(struct net_device *dev)
+{
+ struct flexcan_priv *priv = netdev_priv(dev);
+ struct flexcan_regs __iomem *regs = priv->regs;
+ irqreturn_t handled = IRQ_NONE;
+ u32 reg_esr;
+
reg_esr = priv->read(®s->esr);
- /* ACK all bus error, state change and wake IRQ sources */
- if (reg_esr & (FLEXCAN_ESR_ALL_INT | FLEXCAN_ESR_WAK_INT)) {
+ /* ACK bus error interrupt source */
+ if (reg_esr & FLEXCAN_ESR_ERR_INT) {
handled = IRQ_HANDLED;
- priv->write(reg_esr & (FLEXCAN_ESR_ALL_INT | FLEXCAN_ESR_WAK_INT), ®s->esr);
+ priv->write(FLEXCAN_ESR_ERR_INT, ®s->esr);
}
- /* state change interrupt or broken error state quirk fix is enabled */
- if ((reg_esr & FLEXCAN_ESR_ERR_STATE) ||
- (priv->devtype_data.quirks & (FLEXCAN_QUIRK_BROKEN_WERR_STATE |
- FLEXCAN_QUIRK_BROKEN_PERR_STATE)))
- flexcan_irq_state(dev, reg_esr);
-
/* bus error IRQ - handle if bus error reporting is activated */
if ((reg_esr & FLEXCAN_ESR_ERR_BUS) &&
(priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING))
flexcan_irq_bus_err(dev, reg_esr);
+ return handled;
+}
+
+/* Process device state change events */
+static irqreturn_t flexcan_do_state(struct net_device *dev)
+{
+ struct flexcan_priv *priv = netdev_priv(dev);
+ struct flexcan_regs __iomem *regs = priv->regs;
+ irqreturn_t handled = IRQ_NONE;
+ u32 reg_esr;
+ enum can_state last_state = priv->can.state;
+
+ reg_esr = priv->read(®s->esr);
+
+ /* ACK state change and wake IRQ sources */
+ if (reg_esr & (FLEXCAN_ESR_ERR_STATE | FLEXCAN_ESR_WAK_INT)) {
+ handled = IRQ_HANDLED;
+ priv->write(reg_esr & (FLEXCAN_ESR_ERR_STATE | FLEXCAN_ESR_WAK_INT),
+ ®s->esr);
+ }
+
+ /* state change interrupt or broken error state quirk fix is enabled */
+ if ((reg_esr & FLEXCAN_ESR_ERR_STATE) ||
+ (priv->devtype_data.quirks &
+ (FLEXCAN_QUIRK_BROKEN_WERR_STATE | FLEXCAN_QUIRK_BROKEN_PERR_STATE)))
+ flexcan_irq_state(dev, reg_esr);
+
/* availability of error interrupt among state transitions in case
* bus error reporting is de-activated and
* FLEXCAN_QUIRK_BROKEN_PERR_STATE is enabled:
@@ -1188,6 +1218,65 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id)
}
}
+ return handled;
+}
+
+/* Combined IRQ handler for single-IRQ platforms */
+static irqreturn_t flexcan_irq(int irq, void *dev_id)
+{
+ struct net_device *dev = dev_id;
+ struct flexcan_priv *priv = netdev_priv(dev);
+ irqreturn_t handled;
+
+ handled = flexcan_do_mb(dev);
+ handled |= flexcan_do_state(dev);
+ handled |= flexcan_do_berr(dev);
+
+ if (handled)
+ can_rx_offload_irq_finish(&priv->offload);
+
+ return handled;
+}
+
+/* Mailbox IRQ handler for multi-IRQ platforms */
+static irqreturn_t flexcan_irq_mb(int irq, void *dev_id)
+{
+ struct net_device *dev = dev_id;
+ struct flexcan_priv *priv = netdev_priv(dev);
+ irqreturn_t handled;
+
+ handled = flexcan_do_mb(dev);
+
+ if (handled)
+ can_rx_offload_irq_finish(&priv->offload);
+
+ return handled;
+}
+
+/* Bus error IRQ handler for multi-IRQ platforms */
+static irqreturn_t flexcan_irq_berr(int irq, void *dev_id)
+{
+ struct net_device *dev = dev_id;
+ struct flexcan_priv *priv = netdev_priv(dev);
+ irqreturn_t handled;
+
+ handled = flexcan_do_berr(dev);
+
+ if (handled)
+ can_rx_offload_irq_finish(&priv->offload);
+
+ return handled;
+}
+
+/* Device state change IRQ handler for multi-IRQ platforms */
+static irqreturn_t flexcan_irq_boff(int irq, void *dev_id)
+{
+ struct net_device *dev = dev_id;
+ struct flexcan_priv *priv = netdev_priv(dev);
+ irqreturn_t handled;
+
+ handled = flexcan_do_state(dev);
+
if (handled)
can_rx_offload_irq_finish(&priv->offload);
@@ -1761,25 +1850,30 @@ static int flexcan_open(struct net_device *dev)
can_rx_offload_enable(&priv->offload);
- err = request_irq(dev->irq, flexcan_irq, IRQF_SHARED, dev->name, dev);
+ if (priv->devtype_data.quirks & FLEXCAN_QUIRK_NR_IRQ_3)
+ err = request_irq(dev->irq, flexcan_irq_mb,
+ IRQF_SHARED, dev->name, dev);
+ else
+ err = request_irq(dev->irq, flexcan_irq,
+ IRQF_SHARED, dev->name, dev);
if (err)
goto out_can_rx_offload_disable;
if (priv->devtype_data.quirks & FLEXCAN_QUIRK_NR_IRQ_3) {
err = request_irq(priv->irq_boff,
- flexcan_irq, IRQF_SHARED, dev->name, dev);
+ flexcan_irq_boff, IRQF_SHARED, dev->name, dev);
if (err)
goto out_free_irq;
err = request_irq(priv->irq_err,
- flexcan_irq, IRQF_SHARED, dev->name, dev);
+ flexcan_irq_berr, IRQF_SHARED, dev->name, dev);
if (err)
goto out_free_irq_boff;
}
if (priv->devtype_data.quirks & FLEXCAN_QUIRK_SECONDARY_MB_IRQ) {
err = request_irq(priv->irq_secondary_mb,
- flexcan_irq, IRQF_SHARED, dev->name, dev);
+ flexcan_irq_mb, IRQF_SHARED, dev->name, dev);
if (err)
goto out_free_irq_err;
}
--
2.43.0
^ permalink raw reply related
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