Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* RE: [PATCH 0/3] tty: serial: Add Cortina-Access UART driver and platform support
From: Jason Li @ 2026-06-11  5:27 UTC (permalink / raw)
  To: Arnd Bergmann, Jason Li, Greg Kroah-Hartman, Jiri Slaby
  Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Catalin Marinas,
	Will Deacon, linux-serial@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org, devicetree@vger.kernel.org,
	linux-kernel@vger.kernel.org
In-Reply-To: <7dcc8386-a0e0-4c79-a9f7-f63188bb997e@app.fastmail.com>

Hi Arnd,

Your memory is truly amazing; you even remember a submission from a few years ago.
Since the last sumbission was drop so I though restart a new one this time.
OK, I'll review all feedback and fix them for the next V6 submission.

Yes, we expect actual end-user products based on these SoCs, and our intention is to provide complete upstream support over time. The UART driver and DTS support submitted in this series are the first step in that effort.

Cortina-System and Cortina-Access are now totally different company.
Current aarch64 chipset are totally different with legacy gemini processor.
Realtek has many business unit, different BU may have upstream plan but they are individual.
Although Cortina-Access is a wholly-owned subsidiary of Realtek, our product development is entirely independent.


Thanks,
Jason
> -----Original Message-----
> From: Arnd Bergmann <arnd@arndb.de>
> Sent: Wednesday, June 10, 2026 8:51 PM
> To: Jason Li <jason.lee651024@gmail.com>; Jason Li
> <jason.li@cortina-access.com>; Greg Kroah-Hartman
> <gregkh@linuxfoundation.org>; Jiri Slaby <jirislaby@kernel.org>
> Cc: Rob Herring <robh@kernel.org>; Krzysztof Kozlowski <krzk+dt@kernel.org>;
> Conor Dooley <conor+dt@kernel.org>; Catalin Marinas
> <catalin.marinas@arm.com>; Will Deacon <will@kernel.org>;
> linux-serial@vger.kernel.org; linux-arm-kernel@lists.infradead.org;
> devicetree@vger.kernel.org; linux-kernel@vger.kernel.org
> Subject: Re: [PATCH 0/3] tty: serial: Add Cortina-Access UART driver and
> platform support
> 
> External mail :
> This email originated from outside the organization. Do not reply, click links, or
> open attachments unless you recognize the sender and know the content is
> safe.
> 
> On Wed, Jun 10, 2026, at 13:28, Jason Li wrote:
> > This series adds Linux kernel support for the UART controller
> > integrated in Cortina-Access SoCs, with CA8289 (Venus) as the first supported
> device.
> 
> Hi Jason,
> 
> Thanks a lot for your submission!
> 
> I'm glad to see Cortina Access is getting back to upstreaming this support, I see
> that you first tries this in 2021 but didn't get very far at the time. The last
> submission was v4, so it would make sense to cound this one as v5 and
> continue with v6 next time.
> 
> You have already received a number of comments, so I'll skip looking at the
> details for the moment and let you work through them.
> 
> Regarding how to split up the patch series between uart and soc, I think
> sending them together during the review phase as you do here makes sense,
> but as they are loosely coupled, I think we will likely merge them separately.
> For simplicity, I would then just put the MAINTAINERS entry and the bindings
> for the vendor and board into the series for the soc tree.
> 
> It would also help me if you could add some more context about the SoC into
> the patch description for the patch that adds the arm64 platform, in particular:
> 
>  - is this the only one you are planning to upstream at this
>    point, or do you already have plans for other SoCs in this
>    family?
> 
>  - do you expect to see full support for actual end-user
>    products using these chips?
> 
>  - is there any shared lineage with the cortina-systems
>    (storlink/storm, now marvell) gemini 32-bit chips that we
>    already support, or with any of the Realtek SoCs that
>    are also being upstreamed now?
> 
>        Arnd


^ permalink raw reply

* RE: [PATCH 1/3] dt-bindings: serial: Add binding for Cortina-Access UART
From: Jason Li @ 2026-06-11  5:26 UTC (permalink / raw)
  To: Krzysztof Kozlowski, Jason Li, Greg Kroah-Hartman, Jiri Slaby
  Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Catalin Marinas,
	Will Deacon, Arnd Bergmann, linux-serial@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org, devicetree@vger.kernel.org,
	linux-kernel@vger.kernel.org
In-Reply-To: <021d5cb7-51bf-4221-8b58-0e8a777cb97c@kernel.org>

> -----Original Message-----
> From: Krzysztof Kozlowski <krzk@kernel.org>
> Sent: Wednesday, June 10, 2026 7:51 PM
> To: Jason Li <jason.lee651024@gmail.com>; Jason Li
> <jason.li@cortina-access.com>; Greg Kroah-Hartman
> <gregkh@linuxfoundation.org>; Jiri Slaby <jirislaby@kernel.org>
> Cc: Rob Herring <robh@kernel.org>; Krzysztof Kozlowski <krzk+dt@kernel.org>;
> Conor Dooley <conor+dt@kernel.org>; Catalin Marinas
> <catalin.marinas@arm.com>; Will Deacon <will@kernel.org>; Arnd Bergmann
> <arnd@arndb.de>; linux-serial@vger.kernel.org;
> linux-arm-kernel@lists.infradead.org; devicetree@vger.kernel.org;
> linux-kernel@vger.kernel.org
> Subject: Re: [PATCH 1/3] dt-bindings: serial: Add binding for Cortina-Access
> UART
> 
> External mail :
> This email originated from outside the organization. Do not reply, click links, or
> open attachments unless you recognize the sender and know the content is
> safe.
> 
> On 10/06/2026 13:28, Jason Li wrote:
> > +
> > +allOf:
> > +  - $ref: serial.yaml#
> > +
> > +properties:
> > +  compatible:
> > +    const: cortina-access,serial
> 
> Aren't writing bindings very clear about that? Please, take your time to read
> through the docs, so we will not need to repeat basic guidance. It is
> documented there on purpose.
> 
Appreciate for your time on reviewing.

> 
> Best regards,
> Krzysztof

Thanks,
Jason

^ permalink raw reply

* RE: [PATCH 3/3] arm64: dts: cortina-access: Add DTS for CA8289 SoC and Venus board
From: Jason Li @ 2026-06-11  5:26 UTC (permalink / raw)
  To: Krzysztof Kozlowski, Jason Li, Greg Kroah-Hartman, Jiri Slaby
  Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Catalin Marinas,
	Will Deacon, Arnd Bergmann, linux-serial@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org, devicetree@vger.kernel.org,
	linux-kernel@vger.kernel.org
In-Reply-To: <2fd7077e-1180-47eb-9d13-5a570b0959a4@kernel.org>

> -----Original Message-----
> From: Krzysztof Kozlowski <krzk@kernel.org>
> Sent: Wednesday, June 10, 2026 7:50 PM
> To: Jason Li <jason.lee651024@gmail.com>; Jason Li
> <jason.li@cortina-access.com>; Greg Kroah-Hartman
> <gregkh@linuxfoundation.org>; Jiri Slaby <jirislaby@kernel.org>
> Cc: Rob Herring <robh@kernel.org>; Krzysztof Kozlowski <krzk+dt@kernel.org>;
> Conor Dooley <conor+dt@kernel.org>; Catalin Marinas
> <catalin.marinas@arm.com>; Will Deacon <will@kernel.org>; Arnd Bergmann
> <arnd@arndb.de>; linux-serial@vger.kernel.org;
> linux-arm-kernel@lists.infradead.org; devicetree@vger.kernel.org;
> linux-kernel@vger.kernel.org
> Subject: Re: [PATCH 3/3] arm64: dts: cortina-access: Add DTS for CA8289 SoC
> and Venus board
> 
> External mail :
> This email originated from outside the organization. Do not reply, click links, or
> open attachments unless you recognize the sender and know the content is
> safe.
> 
> On 10/06/2026 13:28, Jason Li wrote:
> > Add SoC DTSI for the Cortina-Access CA8289 (Venus) and a board DTS for
> > the Venus engineering board. The description covers the minimum set of
> > hardware nodes needed to boot a kernel with an INITRD rootfs: CPUs,
> > GIC, timer, PSCI, fixed clock and UART.
> >
> > Signed-off-by: Jason Li <jason.li@cortina-access.com>
> > Assisted-by: Claude:claude-opus-4-8
> 
> SoB should be the last tag.
> 
> Also, it does not match From field.
> 
> > ---
> >  MAINTAINERS                                   |   1 +
> >  arch/arm64/Kconfig.platforms                  |  10 ++
> >  arch/arm64/boot/dts/Makefile                  |   1 +
> >  arch/arm64/boot/dts/cortina-access/Makefile   |   2 +
> >  .../dts/cortina-access/ca8289-engboard.dts    |  31 +++++
> >  .../boot/dts/cortina-access/ca8289-soc.dtsi   | 118 ++++++++++++++++++
> >  6 files changed, 163 insertions(+)
> >  create mode 100644 arch/arm64/boot/dts/cortina-access/Makefile
> >  create mode 100644
> > arch/arm64/boot/dts/cortina-access/ca8289-engboard.dts
> >  create mode 100644 arch/arm64/boot/dts/cortina-access/ca8289-soc.dtsi
> >
> > diff --git a/MAINTAINERS b/MAINTAINERS index
> > 515d89d96472..ebfdb9c267cc 100644
> > --- a/MAINTAINERS
> > +++ b/MAINTAINERS
> > @@ -2826,6 +2826,7 @@ L:      linux-arm-kernel@lists.infradead.org
> (moderated for non-subscribers)
> >  S:   Maintained
> >  F:   Documentation/devicetree/bindings/arm/cortina-access.yaml
> >  F:   Documentation/devicetree/bindings/serial/cortina-access,serial.yaml
> > +F:   arch/arm64/boot/dts/cortina-access/
> >
> >  ARM/CORTINA SYSTEMS GEMINI ARM ARCHITECTURE
> >  M:   Hans Ulli Kroll <ulli.kroll@googlemail.com>
> > diff --git a/arch/arm64/Kconfig.platforms
> > b/arch/arm64/Kconfig.platforms index dc995a732117..ba6dda0660c3
> 100644
> > --- a/arch/arm64/Kconfig.platforms
> > +++ b/arch/arm64/Kconfig.platforms
> > @@ -134,6 +134,16 @@ config ARCH_CIX
> >         This enables support for the Cixtech SoC family,
> >         like P1(sky1).
> >
> > +config ARCH_CORTINA_ACCESS
> > +     bool "Cortina-Access SoC Family"
> > +     select GPIOLIB
> > +     select PINCTRL
> > +     help
> > +       This enables support for Cortina-Access SoCs.  The family
> > +       includes ARMv8-based devices targeting networking and access
> > +       applications.
> > +       If you have a Cortina-Access board, say Y here.
> > +
> >  config ARCH_EXYNOS
> >       bool "Samsung Exynos SoC family"
> >       select COMMON_CLK_SAMSUNG
> > diff --git a/arch/arm64/boot/dts/Makefile
> > b/arch/arm64/boot/dts/Makefile index 98ec8f1b76e4..a599f525fb9a 100644
> > --- a/arch/arm64/boot/dts/Makefile
> > +++ b/arch/arm64/boot/dts/Makefile
> > @@ -16,6 +16,7 @@ subdir-y += broadcom  subdir-y += bst  subdir-y +=
> > cavium  subdir-y += cix
> > +subdir-y += cortina-access
> >  subdir-y += exynos
> >  subdir-y += freescale
> >  subdir-y += hisilicon
> > diff --git a/arch/arm64/boot/dts/cortina-access/Makefile
> > b/arch/arm64/boot/dts/cortina-access/Makefile
> > new file mode 100644
> > index 000000000000..554893f381fe
> > --- /dev/null
> > +++ b/arch/arm64/boot/dts/cortina-access/Makefile
> > @@ -0,0 +1,2 @@
> > +# SPDX-License-Identifier: GPL-2.0
> > +dtb-$(CONFIG_ARCH_CORTINA_ACCESS) += ca8289-engboard.dtb
> > diff --git a/arch/arm64/boot/dts/cortina-access/ca8289-engboard.dts
> > b/arch/arm64/boot/dts/cortina-access/ca8289-engboard.dts
> > new file mode 100644
> > index 000000000000..c8289a0f8269
> > --- /dev/null
> > +++ b/arch/arm64/boot/dts/cortina-access/ca8289-engboard.dts
> > @@ -0,0 +1,31 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * dts file for Cortina Access Venus Engineering Board
> > + *
> > + * Copyright (C) 2026, Cortina Access Inc.
> > + *
> > + */
> > +
> > +/dts-v1/;
> > +
> > +#include "ca8289-soc.dtsi"
> > +
> > +/ {
> > +     model = "Cortina Access Venus Engineering Board";
> > +     compatible = "cortina-access,ca8289-engboard";
> > +     #address-cells = <2>;
> > +     #size-cells = <2>;
> > +
> > +     aliases {
> > +             serial0 = &uart0;
> > +     };
> > +
> > +     chosen {
> > +             stdout-path = "serial0:115200n8";
> > +     };
> > +
> > +     memory@0 {      /* 512MB */
> > +             device_type = "memory";
> > +             reg = <0x00000000 0x00000000 0x0 0x20000000>;
> > +     };
> > +};
> > diff --git a/arch/arm64/boot/dts/cortina-access/ca8289-soc.dtsi
> > b/arch/arm64/boot/dts/cortina-access/ca8289-soc.dtsi
> > new file mode 100644
> > index 000000000000..8e7ffcf4ccab
> > --- /dev/null
> > +++ b/arch/arm64/boot/dts/cortina-access/ca8289-soc.dtsi
> > @@ -0,0 +1,118 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * dts file for Cortina Access CA8289 SoC
> > + *
> > + * Copyright (C) 2026, Cortina Access Inc.
> > + */
> > +
> > +#include <dt-bindings/interrupt-controller/arm-gic.h>
> > +#include <dt-bindings/interrupt-controller/irq.h>
> > +
> > +/ {
> > +     cpus {
> > +             #address-cells = <2>;
> > +             #size-cells = <0>;
> > +
> > +             cpu0: cpu@0 {
> > +                     compatible = "arm,cortex-a55", "arm,armv8";
> > +                     device_type = "cpu";
> > +                     reg = <0x0 0x0>;
> > +                     enable-method = "psci";
> > +             };
> 
> Missing blank lines. Look at existing code how this is supposed to look like.
OK

> > +             cpu1: cpu@100 {
> > +                     compatible = "arm,cortex-a55", "arm,armv8";
> > +                     device_type = "cpu";
> > +                     reg = <0x0 0x100>;
> > +                     enable-method = "psci";
> > +             };
> > +             cpu2: cpu@200 {
> > +                     compatible = "arm,cortex-a55", "arm,armv8";
> > +                     device_type = "cpu";
> > +                     reg = <0x0 0x200>;
> > +                     enable-method = "psci";
> > +             };
> > +             cpu3: cpu@300 {
> > +                     compatible = "arm,cortex-a55", "arm,armv8";
> > +                     device_type = "cpu";
> > +                     reg = <0x0 0x300>;
> > +                     enable-method = "psci";
> > +             };
> > +             cpu-map {
> > +                     cluster0 {
> > +                             core0 {
> > +                                     cpu = <&cpu0>;
> > +                             };
> > +                             core1 {
> > +                                     cpu = <&cpu1>;
> > +                             };
> > +                             core2 {
> > +                                     cpu = <&cpu2>;
> > +                             };
> > +                             core3 {
> > +                                     cpu = <&cpu3>;
> > +                             };
> > +                     };
> > +             };
> > +     };
> > +
> > +     psci {
> > +             compatible = "arm,psci-0.2";
> > +             method = "smc";
> > +     };
> > +
> > +     gic: interrupt-controller@4f8000000 {
> 
> And now you repeat basic mistakes:
> 1. Pointed out by W=1 dtbs_check build
> 2. Fixed long time in every source
> 3. Explicitly documented in writing bindings and DTS coding style
I'll revisit document and use dtbs_check to check that.

> 
> > +             compatible = "arm,gic-v3";
> > +             #interrupt-cells = <3>;
> > +             interrupt-controller;
> > +             #redistributor-regions = <1>;
> > +             reg = <0x00000004 0xF8000000 0 0x10000>,
> > +                   <0x00000004 0xF8040000 0 0x80000>;
> 
> Read DTS coding style.
> 
> > +     };
> > +
> > +     apb_pclk: apb-pclk {
> 
> Nope, drop entire node.
> 
> > +             compatible = "fixed-clock";
> > +             #clock-cells = <0>;
> > +             clock-frequency = <125000000>;
> > +     };
> > +
> > +     reserved-memory {
> > +             #address-cells = <2>;
> > +             #size-cells = <2>;
> > +             ranges;
> > +
> > +             /* TrustZone reserved region; must not be mapped by the
> kernel */
> > +             tz_pool: tz-buffer@f000000 {
> > +                     reg = <0x0 0x0F000000 0x0 0x1000000>;
> > +                     no-map;
> > +             };
> > +     };
> > +
> > +     /* See
> Documentation/devicetree/bindings/timer/arm,arch_timer.yaml */
> > +     timer {
> > +             compatible = "arm,armv8-timer";
> > +             interrupt-parent = <&gic>;
> > +             interrupts = <GIC_PPI 13 IRQ_TYPE_LEVEL_LOW>,
> > +                          <GIC_PPI 14 IRQ_TYPE_LEVEL_LOW>,
> > +                          <GIC_PPI 11 IRQ_TYPE_LEVEL_LOW>,
> > +                          <GIC_PPI 10 IRQ_TYPE_LEVEL_LOW>;
> > +             clock-frequency = <25000000>;
> > +     };
> > +
> > +     uart0: serial@f4329188 {
> > +             device_type = "serial";
> > +             compatible = "cortina-access,serial";
> > +             reg = <0x00000000 0xf4329188 0x0 0x30>;
> 
> This is AI slop. Whatever Claude convinced you to do, it is nothing like
> upstream kernel source.
> 
> Best regards,
> Krzysztof


Thanks,
Jason

^ permalink raw reply

* RE: [PATCH 1/3] dt-bindings: serial: Add binding for Cortina-Access UART
From: Jason Li @ 2026-06-11  5:25 UTC (permalink / raw)
  To: Krzysztof Kozlowski, Jason Li, Greg Kroah-Hartman, Jiri Slaby
  Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Catalin Marinas,
	Will Deacon, Arnd Bergmann, linux-serial@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org, devicetree@vger.kernel.org,
	linux-kernel@vger.kernel.org
In-Reply-To: <068a7ba8-5b1e-46e3-9388-ba288163eb10@kernel.org>

> -----Original Message-----
> From: Krzysztof Kozlowski <krzk@kernel.org>
> Sent: Wednesday, June 10, 2026 7:47 PM
> To: Jason Li <jason.lee651024@gmail.com>; Jason Li
> <jason.li@cortina-access.com>; Greg Kroah-Hartman
> <gregkh@linuxfoundation.org>; Jiri Slaby <jirislaby@kernel.org>
> Cc: Rob Herring <robh@kernel.org>; Krzysztof Kozlowski <krzk+dt@kernel.org>;
> Conor Dooley <conor+dt@kernel.org>; Catalin Marinas
> <catalin.marinas@arm.com>; Will Deacon <will@kernel.org>; Arnd Bergmann
> <arnd@arndb.de>; linux-serial@vger.kernel.org;
> linux-arm-kernel@lists.infradead.org; devicetree@vger.kernel.org;
> linux-kernel@vger.kernel.org
> Subject: Re: [PATCH 1/3] dt-bindings: serial: Add binding for Cortina-Access
> UART
> 
> External mail :
> This email originated from outside the organization. Do not reply, click links, or
> open attachments unless you recognize the sender and know the content is
> safe.
> 
> On 10/06/2026 13:28, Jason Li wrote:
> > Add DT binding schema for the Cortina-Access UART controller.
> > This IP is integrated into most CAXXXX SoC family members.
> >
> > Also add the vendor prefix for Cortina Access, Inc. and the top-level
> > ARM board binding document for the CA8289 (Venus) SoC.
> >
> > Signed-off-by: Jason Li <jason.li@cortina-access.com>
> > Assisted-by: Claude:claude-opus-4-8
> > ---
> >  .../bindings/arm/cortina-access.yaml          | 29 ++++++++++++
> >  .../serial/cortina-access,serial.yaml         | 46 +++++++++++++++++++
> >  .../devicetree/bindings/vendor-prefixes.yaml  |  2 +
> >  MAINTAINERS                                   |  7 +++
> 
> This is somehow complete mess. serial and arm together?
> 
> Please carefully read submitting patches (both documents!) and don't send
> AI-assisted slop.
> 
> You must not combine independent works together.
> 
> 
Thank you, I'll separate patch for different yaml

> >  4 files changed, 84 insertions(+)
> >  create mode 100644
> > Documentation/devicetree/bindings/arm/cortina-access.yaml
> >  create mode 100644
> > Documentation/devicetree/bindings/serial/cortina-access,serial.yaml
> >
> > diff --git a/Documentation/devicetree/bindings/arm/cortina-access.yaml
> > b/Documentation/devicetree/bindings/arm/cortina-access.yaml
> > new file mode 100644
> > index 000000000000..ec0320ed0c0b
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/arm/cortina-access.yaml
> > @@ -0,0 +1,29 @@
> > +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause %YAML 1.2
> > +---
> > +$id: http://devicetree.org/schemas/arm/cortina-access.yaml#
> > +$schema: http://devicetree.org/meta-schemas/core.yaml#
> > +
> > +title: Cortina-Access SoC boards
> > +
> > +maintainers:
> > +  - Jason Li <jason.li@cortina-access.com>
> > +
> > +description:
> > +  Boards based on Cortina-Access ARMv8 SoCs targeting networking and
> > +  access applications.
> > +
> > +properties:
> > +  $nodename:
> > +    const: /
> > +  compatible:
> > +    oneOf:
> > +      - description: Cortina-Access CA8289 (Venus) engineering board
> > +        const: cortina-access,ca8289-engboard
> > +
> > +      - description: Cortina-Access CA8289 (Venus) reference board
> > +        const: cortina-access,ca8289-refboard
> 
> 
> Where is the SoC? This looks like very poor contribution. If you opened any
> existing recent board binding you would see it is done differently.
> 
Thanks, I'll refer more exist examples to fix.

> Best regards,
> Krzysztof

Thanks,
Jason

^ permalink raw reply

* Re: [PATCH v6 04/20] dma-pool: track decrypted atomic pools and select them via attrs
From: Aneesh Kumar K.V @ 2026-06-11  5:25 UTC (permalink / raw)
  To: Jason Gunthorpe
  Cc: iommu, linux-arm-kernel, linux-kernel, linux-coco, Robin Murphy,
	Marek Szyprowski, Will Deacon, Marc Zyngier, Steven Price,
	Suzuki K Poulose, Catalin Marinas, Jiri Pirko, Mostafa Saleh,
	Petr Tesarik, Alexey Kardashevskiy, Dan Williams, Xu Yilun,
	linuxppc-dev, linux-s390, Madhavan Srinivasan, Michael Ellerman,
	Nicholas Piggin, Christophe Leroy (CS GROUP), Alexander Gordeev,
	Gerald Schaefer, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Sven Schnelle, x86, Jiri Pirko,
	Michael Kelley
In-Reply-To: <20260609143242.GK2764304@ziepe.ca>

Jason Gunthorpe <jgg@ziepe.ca> writes:

> The sashiko note does look legit though:
>
> 	if (IS_ENABLED(CONFIG_DMA_DIRECT_REMAP) &&
> 	    !gfpflags_allow_blocking(gfp) && !coherent) {
> 		page = dma_alloc_from_pool(dev, PAGE_ALIGN(size), &cpu_addr,
> 					   gfp, attrs, NULL);
> 		if (!page)
> 			return NULL;
>
> I don't see anything doing the force_dma_unencrypted test along this
> callchain..
>
> I guess it should be done one step up in dma_alloc_attrs() instead of
> in dma_direct_alloc()?
>

I think we should do something similar to what dma_map_phys() does here,
considering that we only support DMA direct with DMA_ATTR_CC_SHARED/DMA_ATTR_ALLOC_CC_SHARED.

@@ -637,6 +637,7 @@ void *dma_alloc_attrs(struct device *dev, size_t size, dma_addr_t *dma_handle,
 {
 	const struct dma_map_ops *ops = get_dma_ops(dev);
 	void *cpu_addr;
+	bool is_cc_shared;
 
 	WARN_ON_ONCE(!dev->coherent_dma_mask);
 
@@ -657,8 +658,17 @@ void *dma_alloc_attrs(struct device *dev, size_t size, dma_addr_t *dma_handle,
 	/* let the implementation decide on the zone to allocate from: */
 	flag &= ~(__GFP_DMA | __GFP_DMA32 | __GFP_HIGHMEM);
 
+	if (force_dma_unencrypted(dev))
+		attrs |= DMA_ATTR_ALLOC_CC_SHARED;
+
+	is_cc_shared = attrs & DMA_ATTR_CC_SHARED;
+
 	if (dma_alloc_direct(dev, ops) || arch_dma_alloc_direct(dev)) {
 		cpu_addr = dma_direct_alloc(dev, size, dma_handle, flag, attrs);
+	} else if (is_cc_shared) {
+		trace_dma_alloc(dev, NULL, 0, size, DMA_BIDIRECTIONAL, flag,
+				attrs);
+		return NULL;
 	} else if (use_dma_iommu(dev)) {
 		cpu_addr = iommu_dma_alloc(dev, size, dma_handle, flag, attrs);
 	} else if (ops->alloc) {

-aneesh


^ permalink raw reply

* Re: [PATCH v6 2/2] ARM: dts: aspeed: ventura2: Add Meta ventura2 BMC
From: Kyle Hsieh @ 2026-06-11  5:24 UTC (permalink / raw)
  To: Andrew Jeffery
  Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Joel Stanley,
	devicetree, linux-arm-kernel, linux-aspeed, linux-kernel
In-Reply-To: <a8cdc7c23166823a8e1969408c667e6a8d758fe7.camel@codeconstruct.com.au>

On Wed, Jun 10, 2026 at 7:22 PM Andrew Jeffery
<andrew@codeconstruct.com.au> wrote:
>
> Hi Kyle,
>
> On Wed, 2026-06-10 at 09:22 +0800, Kyle Hsieh wrote:
> > Add linux device tree entry related to the Meta(Facebook) rmc-node.
> > The system uses an AT2600 BMC.
> > This node is named "ventura2".
> >
> > Signed-off-by: Kyle Hsieh <kylehsieh1995@gmail.com>
>
> I have some comments on v5 that are applicable here too.
>
> https://lore.kernel.org/all/3d56889c004fc2d11b76ace6033c7ccfb8a37d03.camel@codeconstruct.com.au/
>
Hi Andrew,

Thanks for the review and suggestions!

To briefly answer your question: Ventura2 is Rack Management
Controller. It is a modular device primarily designed to manage liquid
cooling systems and monitor rack-level hardware states. Its key
hardware features include an extensive I2C/GPIO topology for
tray-level and rack-level liquid leakage detection, as well as MCTP
over I2C support for asynchronous device communications.

I will remove the redundant sentence and include this detailed
description of the platform's purpose and architecture in the commit
message for v7.

Also, the Sashiko AI bot just caught a missing `idle-state`
configuration for the MCTP I2C mux, so I will include that fix in v7
as well.

I will send out the v7 patch shortly.

Best regards,
Kyle Hsieh
> Andrew


^ permalink raw reply

* Re: [PATCH v2] usb: gadget: aspeed_udc: check endpoint DMA allocation
From: Andrew Jeffery @ 2026-06-11  5:06 UTC (permalink / raw)
  To: Ruoyu Wang, Neal Liu, Greg Kroah-Hartman
  Cc: Joel Stanley, linux-aspeed, linux-usb, linux-arm-kernel,
	linux-kernel
In-Reply-To: <20260610121022.3-1-ruoyuw560@gmail.com>

On Wed, 2026-06-10 at 20:10 +0800, Ruoyu Wang wrote:
> ast_udc_probe() allocates a coherent DMA buffer used as the backing store
> for endpoint buffers. ast_udc_init_ep() derives per-endpoint buffer
> pointers from udc->ep0_buf, so a failed allocation is dereferenced during
> probe.
> 
> Check the allocation before endpoint setup. The existing probe error path
> called ast_udc_remove(), which unregisters the gadget unconditionally and
> is not safe before usb_add_gadget_udc() succeeds. Add a local cleanup
> helper for probe failures so pre-registration failures only unwind the
> resources that were actually initialized.
> 
> This was found by a local static analysis checker for unchecked allocator
> returns while scanning Linux 6.16. The change was checked by applying it
> to current mainline and by running checkpatch. I do not have access to
> Aspeed UDC hardware, so no runtime testing was performed.
> 
> Fixes: 055276c13205 ("usb: gadget: add Aspeed ast2600 udc driver")
> Signed-off-by: Ruoyu Wang <ruoyuw560@gmail.com>

Reviewed-by: Andrew Jeffery <andrew@codeconstruct.com.au>


^ permalink raw reply

* Re: [PATCH] crypto: atmel-tdes - use scatterlist length before DMA mapping
From: Herbert Xu @ 2026-06-11  5:04 UTC (permalink / raw)
  To: Thorsten Blum
  Cc: David S. Miller, Nicolas Ferre, Alexandre Belloni, Claudiu Beznea,
	Nicolas Royer, Eric Bénard, stable, linux-crypto,
	linux-arm-kernel, linux-kernel
In-Reply-To: <20260531204115.689052-3-thorsten.blum@linux.dev>

On Sun, May 31, 2026 at 10:41:17PM +0200, Thorsten Blum wrote:
> Using sg_dma_len() is only valid after mapping the scatterlist with
> dma_map_sg(). However, atmel_tdes_crypt_start() uses it before mapping
> to compare input/output lengths and to compute the transfer count.
> 
> Use the original scatterlist lengths before DMA mapping to avoid reading
> stale or uninitialized DMA lengths when CONFIG_NEED_SG_DMA_LENGTH=y.
> 
> Fixes: 13802005d8f2 ("crypto: atmel - add Atmel DES/TDES driver")
> Fixes: 1f858040c2f7 ("crypto: atmel-tdes - add support for latest release of the IP (0x700)")
> Cc: stable@vger.kernel.org
> Signed-off-by: Thorsten Blum <thorsten.blum@linux.dev>
> ---
>  drivers/crypto/atmel-tdes.c | 6 +++---
>  1 file changed, 3 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/crypto/atmel-tdes.c b/drivers/crypto/atmel-tdes.c
> index 643e507f9c02..0d62b24e9fc7 100644
> --- a/drivers/crypto/atmel-tdes.c
> +++ b/drivers/crypto/atmel-tdes.c
> @@ -463,14 +463,14 @@ static int atmel_tdes_crypt_start(struct atmel_tdes_dev *dd)
>  			IS_ALIGNED(dd->out_sg->length, dd->ctx->block_size);
>  		fast = in && out;
>  
> -		if (sg_dma_len(dd->in_sg) != sg_dma_len(dd->out_sg))
> +		if (dd->in_sg->length != dd->out_sg->length)
>  			fast = 0;
>  	}
>  
>  
>  	if (fast)  {
> -		count = min_t(size_t, dd->total, sg_dma_len(dd->in_sg));
> -		count = min_t(size_t, count, sg_dma_len(dd->out_sg));
> +		count = min_t(size_t, dd->total, dd->in_sg->length);
> +		count = min_t(size_t, count, dd->out_sg->length);

If fast == 1, then dd->in_sg->length must be equal to dd->out_sg->length,
so the second line is redundant.

Cheers,
-- 
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt


^ permalink raw reply

* Re: [PATCH RESEND v2 1/1] crypto: atmel-sha204a - fix heap info leak on I2C transfer failure
From: Herbert Xu @ 2026-06-11  4:58 UTC (permalink / raw)
  To: Lothar Rubusch
  Cc: thorsten.blum, davem, nicolas.ferre, alexandre.belloni,
	claudiu.beznea, ardb, krzk+dt, linux-crypto, linux-arm-kernel,
	linux-kernel
In-Reply-To: <20260609094723.47237-1-l.rubusch@gmail.com>

On Tue, Jun 09, 2026 at 09:47:23AM +0000, Lothar Rubusch wrote:
>
> diff --git a/drivers/crypto/atmel-sha204a.c b/drivers/crypto/atmel-sha204a.c
> index 4c9af737b33a..20cd915ea8a3 100644
> --- a/drivers/crypto/atmel-sha204a.c
> +++ b/drivers/crypto/atmel-sha204a.c
> @@ -31,10 +31,15 @@ static void atmel_sha204a_rng_done(struct atmel_i2c_work_data *work_data,
>  	struct atmel_i2c_client_priv *i2c_priv = work_data->ctx;
>  	struct hwrng *rng = areq;
>  
> -	if (status)
> +	if (status) {
>  		dev_warn_ratelimited(&i2c_priv->client->dev,
>  				     "i2c transaction failed (%d)\n",
>  				     status);
> +		kfree(work_data);
> +		rng->priv = 0;

Why is this necessary? It appears that rng_read_nonblocking already
zeroes rng->priv.

Thanks,
-- 
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt


^ permalink raw reply

* Re: [PATCH v18 6/7] coresight: ctcu: enable byte-cntr for TMC ETR devices
From: Jie Gan @ 2026-06-11  4:57 UTC (permalink / raw)
  To: Suzuki K Poulose, Mike Leach, James Clark, Alexander Shishkin,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, Tingwei Zhang,
	Bjorn Andersson, Konrad Dybcio
  Cc: coresight, linux-arm-kernel, linux-kernel, linux-arm-msm,
	devicetree
In-Reply-To: <20260507-enable-byte-cntr-for-ctcu-v18-6-2b2d590463a3@oss.qualcomm.com>



On 5/7/2026 10:12 PM, Jie Gan wrote:
> The byte-cntr function provided by the CTCU device is used to transfer data
> from the ETR buffer to the userspace. An interrupt is triggered if the data
> size exceeds the threshold set in the BYTECNTRVAL register. The interrupt
> handler counts the number of triggered interruptions and the read function
> will read the data from the synced ETR buffer.
> 
> Switching the sysfs_buf when current buffer is full or the timeout is
> triggered and resets rrp and rwp registers after switched the buffer.
> The synced buffer will become available for reading after the switch.
> 
> Byte-cntr workflow:
> start -> ctcu_enable(ctcu_byte_cntr_start) -> tmc_enable_etr_sink ->
> tmc_read_prepare_etr(jump to tmc_read_prepare_byte_cntr) ->
> tmc_etr_get_sysfs_trace(jump to tmc_byte_cntr_get_data) ->
> tmc_disable_etr_sink -> ctcu_disable(ctcu_byte_cntr_stop) ->
> tmc_read_unprepare_etr(jump to tmc_read_unprepare_byte_cntr) -> finish
> 
> Signed-off-by: Jie Gan <jie.gan@oss.qualcomm.com>
> ---
>   .../ABI/testing/sysfs-bus-coresight-devices-ctcu   |   9 +
>   drivers/hwtracing/coresight/Makefile               |   2 +-
>   .../hwtracing/coresight/coresight-ctcu-byte-cntr.c | 304 +++++++++++++++++++++
>   drivers/hwtracing/coresight/coresight-ctcu-core.c  | 127 ++++++++-
>   drivers/hwtracing/coresight/coresight-ctcu.h       |  79 +++++-
>   drivers/hwtracing/coresight/coresight-tmc-core.c   |   3 +-
>   drivers/hwtracing/coresight/coresight-tmc-etr.c    | 114 +++++++-
>   drivers/hwtracing/coresight/coresight-tmc.h        |   9 +
>   8 files changed, 622 insertions(+), 25 deletions(-)
> 
> diff --git a/Documentation/ABI/testing/sysfs-bus-coresight-devices-ctcu b/Documentation/ABI/testing/sysfs-bus-coresight-devices-ctcu
> new file mode 100644
> index 000000000000..6e53a5197e53
> --- /dev/null
> +++ b/Documentation/ABI/testing/sysfs-bus-coresight-devices-ctcu
> @@ -0,0 +1,9 @@
> +What:           /sys/bus/coresight/devices/<ctcu-name>/irq_enabled[0:1]
> +Date:           May 2026
> +KernelVersion:  7.2
> +Contact:        Tingwei Zhang <tingwei.zhang@oss.qualcomm.com>; Jinlong Mao <jinlong.mao@oss.qualcomm.com>; Jie Gan <jie.gan@oss.qualcomm.com>
> +Description:
> +		(RW) Configure the flag to enable interrupt to count data during CTCU enablement.
> +		An interrupt is generated when the data size exceeds the value set in the IRQ register.
> +		0 : disable
> +		1 : enable
> diff --git a/drivers/hwtracing/coresight/Makefile b/drivers/hwtracing/coresight/Makefile
> index ab16d06783a5..821a1b06b20c 100644
> --- a/drivers/hwtracing/coresight/Makefile
> +++ b/drivers/hwtracing/coresight/Makefile
> @@ -55,5 +55,5 @@ coresight-cti-y := coresight-cti-core.o	coresight-cti-platform.o \
>   obj-$(CONFIG_ULTRASOC_SMB) += ultrasoc-smb.o
>   obj-$(CONFIG_CORESIGHT_DUMMY) += coresight-dummy.o
>   obj-$(CONFIG_CORESIGHT_CTCU) += coresight-ctcu.o
> -coresight-ctcu-y := coresight-ctcu-core.o
> +coresight-ctcu-y := coresight-ctcu-core.o coresight-ctcu-byte-cntr.o
>   obj-$(CONFIG_CORESIGHT_KUNIT_TESTS) += coresight-kunit-tests.o
> diff --git a/drivers/hwtracing/coresight/coresight-ctcu-byte-cntr.c b/drivers/hwtracing/coresight/coresight-ctcu-byte-cntr.c
> new file mode 100644
> index 000000000000..268194f35fd3
> --- /dev/null
> +++ b/drivers/hwtracing/coresight/coresight-ctcu-byte-cntr.c
> @@ -0,0 +1,304 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
> + */
> +
> +#include <linux/coresight.h>
> +#include <linux/device.h>
> +#include <linux/fs.h>
> +#include <linux/interrupt.h>
> +#include <linux/of_irq.h>
> +#include <linux/uaccess.h>
> +
> +#include "coresight-ctcu.h"
> +#include "coresight-priv.h"
> +#include "coresight-tmc.h"
> +
> +static irqreturn_t byte_cntr_handler(int irq, void *data)
> +{
> +	struct ctcu_byte_cntr *byte_cntr_data = data;
> +
> +	atomic_inc(&byte_cntr_data->irq_cnt);
> +	wake_up(&byte_cntr_data->wq);
> +
> +	return IRQ_HANDLED;
> +}
> +
> +static void ctcu_cfg_byte_cntr_reg(struct ctcu_drvdata *drvdata, u32 val,
> +				   u32 offset)
> +{
> +	/* A one value for IRQCTRL register represents 8 bytes */
> +	ctcu_program_register(drvdata, val / 8, offset);
> +}
> +
> +static struct ctcu_byte_cntr *ctcu_get_byte_cntr(struct coresight_device *ctcu,
> +						 struct coresight_device *etr)
> +{
> +	struct ctcu_drvdata *drvdata = dev_get_drvdata(ctcu->dev.parent);
> +	int port;
> +
> +	port = coresight_get_in_port(etr, ctcu);
> +	if (port < 0 || port > 1)
> +		return NULL;
> +
> +	return &drvdata->byte_cntr_data[port];
> +}
> +
> +static bool ctcu_byte_cntr_switch_buffer(struct tmc_drvdata *etr_drvdata,
> +					 struct ctcu_byte_cntr *byte_cntr_data)
> +{
> +	struct etr_buf_node *nd, *next, *curr_node = NULL, *picked_node = NULL;
> +	struct etr_buf *curr_buf = etr_drvdata->sysfs_buf;
> +	bool found_free_buf = false;
> +
> +	if (WARN_ON(!etr_drvdata || !byte_cntr_data))
> +		return false;
> +
> +	/* Stop the ETR before initiating the switch */
> +	if (coresight_get_mode(etr_drvdata->csdev) != CS_MODE_DISABLED)
> +		tmc_etr_enable_disable_hw(etr_drvdata, false);
> +
> +	list_for_each_entry_safe(nd, next, &etr_drvdata->etr_buf_list, link) {
> +		/* curr_buf is free for next round */
> +		if (nd->sysfs_buf == curr_buf) {
> +			nd->is_free = true;
> +			curr_node = nd;
> +		} else if (!found_free_buf && nd->is_free) {
> +			picked_node = nd;
> +			found_free_buf = true;
> +		}
> +	}
> +
> +	if (found_free_buf) {
> +		curr_node->pos = 0;
> +		curr_node->reading = true;
> +		byte_cntr_data->buf_node = curr_node;
> +		etr_drvdata->sysfs_buf = picked_node->sysfs_buf;
> +		etr_drvdata->etr_buf = picked_node->sysfs_buf;
> +		picked_node->is_free = false;
> +		/* Reset irq_cnt for next etr_buf */
> +		atomic_set(&byte_cntr_data->irq_cnt, 0);
> +		/* Restart the ETR once a free buffer is available */
> +		if (coresight_get_mode(etr_drvdata->csdev) != CS_MODE_DISABLED)
> +			tmc_etr_enable_disable_hw(etr_drvdata, true);
> +	}
> +
> +	return found_free_buf;
> +}
> +
> +/*
> + * ctcu_byte_cntr_get_data() - reads data from the deactivated and filled buffer.
> + * The byte-cntr reading work reads data from the deactivated and filled buffer.
> + * The read operation waits for a buffer to become available, either filled or
> + * upon timeout, and then reads trace data from the synced buffer.
> + */
> +static ssize_t tmc_byte_cntr_get_data(struct tmc_drvdata *etr_drvdata, loff_t pos,
> +				      size_t len, char **bufpp)
> +{
> +	struct coresight_device *ctcu = tmc_etr_get_ctcu_device(etr_drvdata);
> +	struct device *dev = &etr_drvdata->csdev->dev;
> +	struct ctcu_byte_cntr *byte_cntr_data;
> +	struct etr_buf *sysfs_buf;
> +	atomic_t *irq_cnt;
> +	ssize_t actual;
> +	int ret;
> +
> +	byte_cntr_data = ctcu_get_byte_cntr(ctcu, etr_drvdata->csdev);
> +	if (!byte_cntr_data || !byte_cntr_data->irq_enabled)
> +		return -EINVAL;
> +
> +	irq_cnt = &byte_cntr_data->irq_cnt;
> +
> +wait_buffer:
> +	if (!byte_cntr_data->buf_node) {
> +		ret = wait_event_interruptible_timeout(byte_cntr_data->wq,
> +				(atomic_read(irq_cnt) >= MAX_IRQ_CNT - 1) ||
> +				!byte_cntr_data->enable,
> +				BYTE_CNTR_TIMEOUT);
> +		if (ret < 0)
> +			return ret;
> +		/*
> +		 * The current etr_buf is almost full or timeout is triggered,
> +		 * so switch the buffer and mark the switched buffer as reading.
> +		 */
> +		if (byte_cntr_data->enable) {
> +			if (!ctcu_byte_cntr_switch_buffer(etr_drvdata, byte_cntr_data)) {
> +				dev_err(dev, "Switch buffer failed for the byte-cntr\n");
> +				return -ENOMEM;
> +			}
> +		} else {
> +			/* Exit byte-cntr reading */
> +			return 0;
> +		}
> +	}
> +
> +	/* Check the status of current etr_buf */
> +	if (atomic_read(irq_cnt) >= MAX_IRQ_CNT)
> +		dev_warn(dev, "Data overwrite happened\n");
> +
> +	pos = byte_cntr_data->buf_node->pos;
> +	sysfs_buf = byte_cntr_data->buf_node->sysfs_buf;
> +	actual = tmc_etr_read_sysfs_buf(sysfs_buf, pos, len, bufpp);
> +	if (actual <= 0) {
> +		/* Reset buf_node upon reading is finished or failed */
> +		byte_cntr_data->buf_node->reading = false;
> +		byte_cntr_data->buf_node = NULL;
> +
> +		/*
> +		 * Nothing in the buffer, waiting for the next buffer
> +		 * to be filled.
> +		 */
> +		if (actual == 0)
> +			goto wait_buffer;
> +	}
> +
> +	return actual;
> +}
> +
> +static int tmc_read_prepare_byte_cntr(struct tmc_drvdata *etr_drvdata)
> +{
> +	struct coresight_device *ctcu = tmc_etr_get_ctcu_device(etr_drvdata);
> +	struct ctcu_byte_cntr *byte_cntr_data;
> +	unsigned long flags;
> +	int ret = 0;
> +
> +	/* byte-cntr is operating with SYSFS mode being enabled only */
> +	if (coresight_get_mode(etr_drvdata->csdev) != CS_MODE_SYSFS)
> +		return -EINVAL;
> +
> +	byte_cntr_data = ctcu_get_byte_cntr(ctcu, etr_drvdata->csdev);
> +	if (!byte_cntr_data || !byte_cntr_data->irq_enabled)
> +		return -EINVAL;
> +
> +	raw_spin_lock_irqsave(&byte_cntr_data->spin_lock, flags);
> +	if (byte_cntr_data->reading) {
> +		raw_spin_unlock_irqrestore(&byte_cntr_data->spin_lock, flags);
> +		return -EBUSY;
> +	}
> +
> +	/* byte_cntr_data->enable may race with ctcu_platform_remove() */
> +	if (!byte_cntr_data->enable) {
> +		raw_spin_unlock_irqrestore(&byte_cntr_data->spin_lock, flags);
> +		return -ENODEV;
> +	}
> +
> +	byte_cntr_data->reading = true;
> +	raw_spin_unlock_irqrestore(&byte_cntr_data->spin_lock, flags);
> +	/* Setup an available etr_buf_list for byte-cntr */
> +	ret = tmc_create_etr_buf_list(etr_drvdata, 2);
> +	if (ret) {
> +		byte_cntr_data->reading = false;
> +		return ret;
> +	}
> +
> +	guard(raw_spinlock_irqsave)(&byte_cntr_data->spin_lock);
> +	atomic_set(&byte_cntr_data->irq_cnt, 0);
> +	/*
> +	 * Configure the byte-cntr register to enable IRQ. The configured
> +	 * size is 5% of the buffer_size.
> +	 */
> +	ctcu_cfg_byte_cntr_reg(byte_cntr_data->ctcu_drvdata,
> +			       etr_drvdata->size / MAX_IRQ_CNT,
> +			       byte_cntr_data->irq_ctrl_offset);
> +	enable_irq_wake(byte_cntr_data->irq);
> +	byte_cntr_data->buf_node = NULL;
> +
> +	return 0;
> +}
> +
> +static int tmc_read_unprepare_byte_cntr(struct tmc_drvdata *etr_drvdata)
> +{
> +	struct coresight_device *ctcu = tmc_etr_get_ctcu_device(etr_drvdata);
> +	struct ctcu_byte_cntr *byte_cntr_data;
> +
> +	byte_cntr_data = ctcu_get_byte_cntr(ctcu, etr_drvdata->csdev);
> +	if (!byte_cntr_data || !byte_cntr_data->irq_enabled)

Found an issue here. Need add one more condition to address the issue:

if (!byte_cntr_data || !byte_cntr_data->irq_enabled || 
!byte_cntr_data->reading)

In tmc_read_prepare_etr(), when byte_cntr_sysfs_ops is set but 
tmc_read_prepare_byte_cntr() returns an error,  the code falls through 
to the normal prepare path and sets drvdata->reading = true. In the 
paired tmc_read_unprepare_etr(), if byte_cntr_ops is still set and 
tmc_read_unprepare_byte_cntr() returns 0 (because irq_enabled=true, even 
though byte_cntr_data->reading was never set), the function returns 
early without clearing drvdata->reading.

Thanks,
Jie

> +		return -EINVAL;
> +
> +	tmc_clean_etr_buf_list(etr_drvdata);
> +	scoped_guard(raw_spinlock_irqsave, &byte_cntr_data->spin_lock) {
> +		/* Configure the byte-cntr register to disable IRQ */
> +		ctcu_cfg_byte_cntr_reg(byte_cntr_data->ctcu_drvdata, 0,
> +				       byte_cntr_data->irq_ctrl_offset);
> +		disable_irq_wake(byte_cntr_data->irq);
> +		byte_cntr_data->buf_node = NULL;
> +		byte_cntr_data->reading = false;
> +	}
> +	wake_up(&byte_cntr_data->wq);
> +
> +	return 0;
> +}
> +
> +const struct tmc_sysfs_ops byte_cntr_sysfs_ops = {
> +	.read_prepare	= tmc_read_prepare_byte_cntr,
> +	.read_unprepare	= tmc_read_unprepare_byte_cntr,
> +	.get_trace_data	= tmc_byte_cntr_get_data,
> +};
> +
> +/* Start the byte-cntr function when the path is enabled. */
> +void ctcu_byte_cntr_start(struct coresight_device *csdev, struct coresight_path *path)
> +{
> +	struct coresight_device *sink = coresight_get_sink(path);
> +	struct ctcu_byte_cntr *byte_cntr_data;
> +
> +	byte_cntr_data = ctcu_get_byte_cntr(csdev, sink);
> +	if (!byte_cntr_data)
> +		return;
> +
> +	/* Don't start byte-cntr function when irq_enabled is not set. */
> +	if (!byte_cntr_data->irq_enabled || byte_cntr_data->enable)
> +		return;
> +
> +	guard(raw_spinlock_irqsave)(&byte_cntr_data->spin_lock);
> +	byte_cntr_data->enable = true;
> +}
> +
> +/* Stop the byte-cntr function when the path is disabled. */
> +void ctcu_byte_cntr_stop(struct coresight_device *csdev, struct coresight_path *path)
> +{
> +	struct coresight_device *sink = coresight_get_sink(path);
> +	struct ctcu_byte_cntr *byte_cntr_data;
> +
> +	if (coresight_get_mode(sink) == CS_MODE_SYSFS)
> +		return;
> +
> +	byte_cntr_data = ctcu_get_byte_cntr(csdev, sink);
> +	if (!byte_cntr_data)
> +		return;
> +
> +	guard(raw_spinlock_irqsave)(&byte_cntr_data->spin_lock);
> +	byte_cntr_data->enable = false;
> +}
> +
> +void ctcu_byte_cntr_init(struct device *dev, struct ctcu_drvdata *drvdata, int etr_num)
> +{
> +	struct ctcu_byte_cntr *byte_cntr_data;
> +	struct device_node *nd = dev->of_node;
> +	int irq_num, ret, i, irq_registered = 0;
> +
> +	for (i = 0; i < etr_num; i++) {
> +		byte_cntr_data = &drvdata->byte_cntr_data[i];
> +		irq_num = of_irq_get(nd, i);
> +		if (irq_num < 0) {
> +			dev_err(dev, "Failed to get IRQ from DT for port%d\n", i);
> +			continue;
> +		}
> +
> +		ret = devm_request_irq(dev, irq_num, byte_cntr_handler,
> +				       IRQF_TRIGGER_RISING | IRQF_SHARED,
> +				       dev_name(dev), byte_cntr_data);
> +		if (ret) {
> +			dev_err(dev, "Failed to register IRQ for port%d\n", i);
> +			continue;
> +		}
> +
> +		byte_cntr_data->irq = irq_num;
> +		byte_cntr_data->ctcu_drvdata = drvdata;
> +		init_waitqueue_head(&byte_cntr_data->wq);
> +		raw_spin_lock_init(&byte_cntr_data->spin_lock);
> +		irq_registered++;
> +	}
> +
> +	if (irq_registered)
> +		tmc_etr_set_byte_cntr_sysfs_ops(&byte_cntr_sysfs_ops);
> +}
> diff --git a/drivers/hwtracing/coresight/coresight-ctcu-core.c b/drivers/hwtracing/coresight/coresight-ctcu-core.c
> index e8720026c9e3..2da1a6f3d29f 100644
> --- a/drivers/hwtracing/coresight/coresight-ctcu-core.c
> +++ b/drivers/hwtracing/coresight/coresight-ctcu-core.c
> @@ -1,6 +1,7 @@
>   // SPDX-License-Identifier: GPL-2.0-only
>   /*
> - * Copyright (c) 2024-2025 Qualcomm Innovation Center, Inc. All rights reserved.
> + * Copyright (c) 2024-2026 Qualcomm Innovation Center, Inc. All rights reserved.
> + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
>    */
>   
>   #include <linux/clk.h>
> @@ -18,6 +19,7 @@
>   
>   #include "coresight-ctcu.h"
>   #include "coresight-priv.h"
> +#include "coresight-tmc.h"
>   
>   #define ctcu_writel(drvdata, val, offset)	__raw_writel((val), drvdata->base + offset)
>   #define ctcu_readl(drvdata, offset)		__raw_readl(drvdata->base + offset)
> @@ -43,17 +45,21 @@
>   
>   #define CTCU_ATID_REG_BIT(traceid)	(traceid % 32)
>   #define CTCU_ATID_REG_SIZE		0x10
> +#define CTCU_ETR0_IRQCTRL               0x6c
> +#define CTCU_ETR1_IRQCTRL               0x70
>   #define CTCU_ETR0_ATID0			0xf8
>   #define CTCU_ETR1_ATID0			0x108
>   
>   static const struct ctcu_etr_config sa8775p_etr_cfgs[] = {
>   	{
> -		.atid_offset	= CTCU_ETR0_ATID0,
> -		.port_num	= 0,
> +		.atid_offset		= CTCU_ETR0_ATID0,
> +		.irq_ctrl_offset	= CTCU_ETR0_IRQCTRL,
> +		.port_num		= 0,
>   	},
>   	{
> -		.atid_offset	= CTCU_ETR1_ATID0,
> -		.port_num	= 1,
> +		.atid_offset		= CTCU_ETR1_ATID0,
> +		.irq_ctrl_offset	= CTCU_ETR1_IRQCTRL,
> +		.port_num		= 1,
>   	},
>   };
>   
> @@ -62,6 +68,85 @@ static const struct ctcu_config sa8775p_cfgs = {
>   	.num_etr_config	= ARRAY_SIZE(sa8775p_etr_cfgs),
>   };
>   
> +void ctcu_program_register(struct ctcu_drvdata *drvdata, u32 val, u32 offset)
> +{
> +	CS_UNLOCK(drvdata->base);
> +	ctcu_writel(drvdata, val, offset);
> +	CS_LOCK(drvdata->base);
> +}
> +
> +static ssize_t irq_enabled_show(struct device *dev,
> +				struct device_attribute *attr,
> +				char *buf)
> +{
> +	struct ctcu_byte_cntr_irq_attribute *irq_attr =
> +		container_of(attr, struct ctcu_byte_cntr_irq_attribute, attr);
> +	struct ctcu_drvdata *drvdata = dev_get_drvdata(dev->parent);
> +	u8 port = irq_attr->port;
> +
> +	if (!drvdata->byte_cntr_data[port].irq_ctrl_offset)
> +		return -EINVAL;
> +
> +	return sysfs_emit(buf, "%u\n",
> +			(unsigned int)drvdata->byte_cntr_data[port].irq_enabled);
> +}
> +
> +static ssize_t irq_enabled_store(struct device *dev,
> +				 struct device_attribute *attr,
> +				 const char *buf,
> +				 size_t size)
> +{
> +	struct ctcu_byte_cntr_irq_attribute *irq_attr =
> +		container_of(attr, struct ctcu_byte_cntr_irq_attribute, attr);
> +	struct ctcu_drvdata *drvdata = dev_get_drvdata(dev->parent);
> +	u8 port = irq_attr->port;
> +	unsigned long val;
> +
> +	if (kstrtoul(buf, 0, &val))
> +		return -EINVAL;
> +
> +	guard(raw_spinlock_irqsave)(&drvdata->byte_cntr_data[port].spin_lock);
> +	if (drvdata->byte_cntr_data[port].reading)
> +		return -EBUSY;
> +	else if (drvdata->byte_cntr_data[port].irq_ctrl_offset)
> +		drvdata->byte_cntr_data[port].irq_enabled = !!val;
> +
> +	return size;
> +}
> +
> +static umode_t irq_enabled_is_visible(struct kobject *kobj,
> +				      struct attribute *attr, int n)
> +{
> +	struct device_attribute *dev_attr =
> +		container_of(attr, struct device_attribute, attr);
> +	struct ctcu_byte_cntr_irq_attribute *irq_attr =
> +		container_of(dev_attr, struct ctcu_byte_cntr_irq_attribute, attr);
> +	struct device *dev = kobj_to_dev(kobj);
> +	struct ctcu_drvdata *drvdata = dev_get_drvdata(dev->parent);
> +	u8 port = irq_attr->port;
> +
> +	if (drvdata && drvdata->byte_cntr_data[port].irq_ctrl_offset)
> +		return attr->mode;
> +
> +	return 0;
> +}
> +
> +static struct attribute *ctcu_attrs[] = {
> +	ctcu_byte_cntr_irq_rw(0),
> +	ctcu_byte_cntr_irq_rw(1),
> +	NULL,
> +};
> +
> +static struct attribute_group ctcu_attr_grp = {
> +	.attrs = ctcu_attrs,
> +	.is_visible = irq_enabled_is_visible,
> +};
> +
> +static const struct attribute_group *ctcu_attr_grps[] = {
> +	&ctcu_attr_grp,
> +	NULL,
> +};
> +
>   static void ctcu_program_atid_register(struct ctcu_drvdata *drvdata, u32 reg_offset,
>   				       u8 bit, bool enable)
>   {
> @@ -140,11 +225,15 @@ static int ctcu_set_etr_traceid(struct coresight_device *csdev, struct coresight
>   static int ctcu_enable(struct coresight_device *csdev, enum cs_mode mode,
>   		       struct coresight_path *path)
>   {
> +	ctcu_byte_cntr_start(csdev, path);
> +
>   	return ctcu_set_etr_traceid(csdev, path, true);
>   }
>   
>   static int ctcu_disable(struct coresight_device *csdev, struct coresight_path *path)
>   {
> +	ctcu_byte_cntr_stop(csdev, path);
> +
>   	return ctcu_set_etr_traceid(csdev, path, false);
>   }
>   
> @@ -195,7 +284,10 @@ static int ctcu_probe(struct platform_device *pdev)
>   			for (i = 0; i < cfgs->num_etr_config; i++) {
>   				etr_cfg = &cfgs->etr_cfgs[i];
>   				drvdata->atid_offset[i] = etr_cfg->atid_offset;
> +				drvdata->byte_cntr_data[i].irq_ctrl_offset =
> +					etr_cfg->irq_ctrl_offset;
>   			}
> +			ctcu_byte_cntr_init(dev, drvdata, cfgs->num_etr_config);
>   		}
>   	}
>   
> @@ -209,6 +301,7 @@ static int ctcu_probe(struct platform_device *pdev)
>   	desc.dev = dev;
>   	desc.ops = &ctcu_ops;
>   	desc.access = CSDEV_ACCESS_IOMEM(base);
> +	desc.groups = ctcu_attr_grps;
>   	raw_spin_lock_init(&drvdata->spin_lock);
>   
>   	drvdata->csdev = coresight_register(&desc);
> @@ -244,10 +337,34 @@ static int ctcu_platform_probe(struct platform_device *pdev)
>   static void ctcu_platform_remove(struct platform_device *pdev)
>   {
>   	struct ctcu_drvdata *drvdata = platform_get_drvdata(pdev);
> +	struct ctcu_byte_cntr *byte_cntr_data;
> +	unsigned long flags;
> +	int i;
>   
>   	if (WARN_ON(!drvdata))
>   		return;
>   
> +	/*
> +	 * Signal all active byte-cntr readers to exit, then wait for them to
> +	 * finish before resetting the ops pointer and freeing driver data.
> +	 * Without this, a reader blocked in wait_event_interruptible_timeout()
> +	 * would access the freed ctcu_drvdata wait-queue head (use-after-free).
> +	 */
> +	for (i = 0; i < ETR_MAX_NUM; i++) {
> +		byte_cntr_data = &drvdata->byte_cntr_data[i];
> +		raw_spin_lock_irqsave(&byte_cntr_data->spin_lock, flags);
> +		/* Set enable=false for all ports to signal teardown to racing readers */
> +		byte_cntr_data->enable = false;
> +		if (!byte_cntr_data->reading) {
> +			raw_spin_unlock_irqrestore(&byte_cntr_data->spin_lock, flags);
> +			continue;
> +		}
> +		raw_spin_unlock_irqrestore(&byte_cntr_data->spin_lock, flags);
> +		wake_up_all(&byte_cntr_data->wq);
> +		wait_event(byte_cntr_data->wq, !byte_cntr_data->reading);
> +	}
> +
> +	tmc_etr_reset_byte_cntr_sysfs_ops();
>   	ctcu_remove(pdev);
>   	pm_runtime_disable(&pdev->dev);
>   }
> diff --git a/drivers/hwtracing/coresight/coresight-ctcu.h b/drivers/hwtracing/coresight/coresight-ctcu.h
> index e9594c38dd91..a2ae0a0d91d0 100644
> --- a/drivers/hwtracing/coresight/coresight-ctcu.h
> +++ b/drivers/hwtracing/coresight/coresight-ctcu.h
> @@ -1,23 +1,31 @@
>   /* SPDX-License-Identifier: GPL-2.0-only */
>   /*
> - * Copyright (c) 2024-2025 Qualcomm Innovation Center, Inc. All rights reserved.
> + * Copyright (c) 2024-2026 Qualcomm Innovation Center, Inc. All rights reserved.
> + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
>    */
>   
>   #ifndef _CORESIGHT_CTCU_H
>   #define _CORESIGHT_CTCU_H
> +
> +#include <linux/time.h>
>   #include "coresight-trace-id.h"
>   
>   /* Maximum number of supported ETR devices for a single CTCU. */
>   #define ETR_MAX_NUM	2
>   
> +#define BYTE_CNTR_TIMEOUT	(3 * HZ)
> +#define MAX_IRQ_CNT		20
> +
>   /**
>    * struct ctcu_etr_config
>    * @atid_offset:	offset to the ATID0 Register.
> - * @port_num:		in-port number of CTCU device that connected to ETR.
> + * @port_num:		in-port number of the CTCU device that connected to ETR.
> + * @irq_ctrl_offset:    offset to the BYTECNTRVAL register.
>    */
>   struct ctcu_etr_config {
>   	const u32 atid_offset;
>   	const u32 port_num;
> +	const u32 irq_ctrl_offset;
>   };
>   
>   struct ctcu_config {
> @@ -25,15 +33,68 @@ struct ctcu_config {
>   	int num_etr_config;
>   };
>   
> -struct ctcu_drvdata {
> -	void __iomem		*base;
> -	struct clk		*apb_clk;
> -	struct device		*dev;
> -	struct coresight_device	*csdev;
> +/**
> + * struct ctcu_byte_cntr
> + * @enable:		indicates that byte_cntr function is enabled or not.
> + * @irq_enabled:	indicates that the interruption is enabled.
> + * @reading:		indicates that byte_cntr is reading.
> + * @irq:		allocated number of the IRQ.
> + * @irq_cnt:		IRQ count number of the triggered interruptions.
> + * @wq:			waitqueue for reading data from ETR buffer.
> + * @spin_lock:		spinlock of the byte_cntr_data.
> + * @irq_ctrl_offset:	offset to the BYTECNTVAL Register.
> + * @ctcu_drvdata:	drvdata of the CTCU device.
> + * @buf_node:		etr_buf_node for reading.
> + */
> +struct ctcu_byte_cntr {
> +	bool			enable;
> +	bool			irq_enabled;
> +	bool			reading;
> +	int			irq;
> +	atomic_t		irq_cnt;
> +	wait_queue_head_t	wq;
>   	raw_spinlock_t		spin_lock;
> -	u32			atid_offset[ETR_MAX_NUM];
> +	u32			irq_ctrl_offset;
> +	struct ctcu_drvdata	*ctcu_drvdata;
> +	struct etr_buf_node	*buf_node;
> +};
> +
> +struct ctcu_drvdata {
> +	void __iomem			*base;
> +	struct clk			*apb_clk;
> +	struct device			*dev;
> +	struct coresight_device		*csdev;
> +	struct ctcu_byte_cntr		byte_cntr_data[ETR_MAX_NUM];
> +	raw_spinlock_t			spin_lock;
> +	u32				atid_offset[ETR_MAX_NUM];
>   	/* refcnt for each traceid of each sink */
> -	u8			traceid_refcnt[ETR_MAX_NUM][CORESIGHT_TRACE_ID_RES_TOP];
> +	u8				traceid_refcnt[ETR_MAX_NUM][CORESIGHT_TRACE_ID_RES_TOP];
>   };
>   
> +/**
> + * struct ctcu_byte_cntr_irq_attribute
> + * @attr:	The device attribute.
> + * @port:	port number.
> + */
> +struct ctcu_byte_cntr_irq_attribute {
> +	struct device_attribute	attr;
> +	u8			port;
> +};
> +
> +#define ctcu_byte_cntr_irq_rw(port)					\
> +	(&((struct ctcu_byte_cntr_irq_attribute[]) {			\
> +	   {								\
> +		__ATTR(irq_enabled##port, 0644, irq_enabled_show,	\
> +		irq_enabled_store),					\
> +		port,							\
> +	   }								\
> +	})[0].attr.attr)
> +
> +void ctcu_program_register(struct ctcu_drvdata *drvdata, u32 val, u32 offset);
> +
> +/* Byte-cntr functions */
> +void ctcu_byte_cntr_start(struct coresight_device *csdev, struct coresight_path *path);
> +void ctcu_byte_cntr_stop(struct coresight_device *csdev, struct coresight_path *path);
> +void ctcu_byte_cntr_init(struct device *dev, struct ctcu_drvdata *drvdata, int port_num);
> +
>   #endif
> diff --git a/drivers/hwtracing/coresight/coresight-tmc-core.c b/drivers/hwtracing/coresight/coresight-tmc-core.c
> index 110eedde077f..9f4fd86e8c32 100644
> --- a/drivers/hwtracing/coresight/coresight-tmc-core.c
> +++ b/drivers/hwtracing/coresight/coresight-tmc-core.c
> @@ -293,7 +293,8 @@ static ssize_t tmc_read(struct file *file, char __user *data, size_t len,
>   		return -EFAULT;
>   	}
>   
> -	*ppos += actual;
> +	if (!tmc_etr_update_buf_node_pos(drvdata, actual))
> +		*ppos += actual;
>   	dev_dbg(&drvdata->csdev->dev, "%zu bytes copied\n", actual);
>   
>   	return actual;
> diff --git a/drivers/hwtracing/coresight/coresight-tmc-etr.c b/drivers/hwtracing/coresight/coresight-tmc-etr.c
> index b0c5f3559085..54ca9616fa66 100644
> --- a/drivers/hwtracing/coresight/coresight-tmc-etr.c
> +++ b/drivers/hwtracing/coresight/coresight-tmc-etr.c
> @@ -1168,6 +1168,8 @@ static int tmc_etr_enable_hw(struct tmc_drvdata *drvdata,
>   	return rc;
>   }
>   
> +static const struct tmc_sysfs_ops *byte_cntr_sysfs_ops;
> +
>   /*
>    * Return the available trace data in the buffer (starts at etr_buf->offset,
>    * limited by etr_buf->len) from @pos, with a maximum limit of @len,
> @@ -1178,23 +1180,39 @@ static int tmc_etr_enable_hw(struct tmc_drvdata *drvdata,
>    * We are protected here by drvdata->reading != 0, which ensures the
>    * sysfs_buf stays alive.
>    */
> -ssize_t tmc_etr_get_sysfs_trace(struct tmc_drvdata *drvdata,
> -				loff_t pos, size_t len, char **bufpp)
> +ssize_t tmc_etr_read_sysfs_buf(struct etr_buf *sysfs_buf, loff_t pos,
> +			       size_t len, char **bufpp)
>   {
>   	s64 offset;
>   	ssize_t actual = len;
> -	struct etr_buf *etr_buf = drvdata->sysfs_buf;
>   
> -	if (pos + actual > etr_buf->len)
> -		actual = etr_buf->len - pos;
> +	if (pos + actual > sysfs_buf->len)
> +		actual = sysfs_buf->len - pos;
>   	if (actual <= 0)
>   		return actual;
>   
>   	/* Compute the offset from which we read the data */
> -	offset = etr_buf->offset + pos;
> -	if (offset >= etr_buf->size)
> -		offset -= etr_buf->size;
> -	return tmc_etr_buf_get_data(etr_buf, offset, actual, bufpp);
> +	offset = sysfs_buf->offset + pos;
> +	if (offset >= sysfs_buf->size)
> +		offset -= sysfs_buf->size;
> +	return tmc_etr_buf_get_data(sysfs_buf, offset, actual, bufpp);
> +}
> +EXPORT_SYMBOL_GPL(tmc_etr_read_sysfs_buf);
> +
> +ssize_t tmc_etr_get_sysfs_trace(struct tmc_drvdata *drvdata,
> +				loff_t pos, size_t len, char **bufpp)
> +{
> +	ssize_t ret;
> +	const struct tmc_sysfs_ops *byte_cntr_ops = READ_ONCE(byte_cntr_sysfs_ops);
> +
> +	if (byte_cntr_ops) {
> +		ret = byte_cntr_ops->get_trace_data(drvdata, pos, len, bufpp);
> +		/* Return the filled buffer */
> +		if (ret > 0 || ret == -ENOMEM)
> +			return ret;
> +	}
> +
> +	return tmc_etr_read_sysfs_buf(drvdata->sysfs_buf, pos, len, bufpp);
>   }
>   
>   static struct etr_buf *
> @@ -1248,6 +1266,39 @@ static void __tmc_etr_disable_hw(struct tmc_drvdata *drvdata)
>   
>   }
>   
> +static void tmc_etr_reset_sysfs_buf(struct tmc_drvdata *drvdata)
> +{
> +	u32 sts;
> +
> +	CS_UNLOCK(drvdata->base);
> +	tmc_write_rrp(drvdata, drvdata->sysfs_buf->hwaddr);
> +	tmc_write_rwp(drvdata, drvdata->sysfs_buf->hwaddr);
> +	sts = readl_relaxed(drvdata->base + TMC_STS) & ~TMC_STS_FULL;
> +	writel_relaxed(sts, drvdata->base + TMC_STS);
> +	CS_LOCK(drvdata->base);
> +}
> +
> +/**
> + * tmc_etr_enable_disable_hw - enable/disable the ETR hw.
> + * @drvdata:	drvdata of the TMC device.
> + * @enable:	indicates enable/disable.
> + */
> +void tmc_etr_enable_disable_hw(struct tmc_drvdata *drvdata, bool enable)
> +{
> +	unsigned long flags;
> +
> +	raw_spin_lock_irqsave(&drvdata->spinlock, flags);
> +	if (enable) {
> +		tmc_etr_reset_sysfs_buf(drvdata);
> +		__tmc_etr_enable_hw(drvdata);
> +	} else {
> +		__tmc_etr_disable_hw(drvdata);
> +	}
> +
> +	raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
> +}
> +EXPORT_SYMBOL_GPL(tmc_etr_enable_disable_hw);
> +
>   void tmc_etr_disable_hw(struct tmc_drvdata *drvdata)
>   {
>   	__tmc_etr_disable_hw(drvdata);
> @@ -2047,15 +2098,54 @@ int tmc_create_etr_buf_list(struct tmc_drvdata *drvdata, int num_nodes)
>   }
>   EXPORT_SYMBOL_GPL(tmc_create_etr_buf_list);
>   
> +void tmc_etr_set_byte_cntr_sysfs_ops(const struct tmc_sysfs_ops *sysfs_ops)
> +{
> +	WRITE_ONCE(byte_cntr_sysfs_ops, sysfs_ops);
> +}
> +EXPORT_SYMBOL_GPL(tmc_etr_set_byte_cntr_sysfs_ops);
> +
> +void tmc_etr_reset_byte_cntr_sysfs_ops(void)
> +{
> +	WRITE_ONCE(byte_cntr_sysfs_ops, NULL);
> +}
> +EXPORT_SYMBOL_GPL(tmc_etr_reset_byte_cntr_sysfs_ops);
> +
> +bool tmc_etr_update_buf_node_pos(struct tmc_drvdata *drvdata, ssize_t size)
> +{
> +	struct etr_buf_node *nd, *next;
> +
> +	if (drvdata->config_type != TMC_CONFIG_TYPE_ETR)
> +		return false;
> +
> +	list_for_each_entry_safe(nd, next, &drvdata->etr_buf_list, link) {
> +		if (nd && nd->reading) {
> +			nd->pos += size;
> +			return true;
> +		}
> +	}
> +
> +	return false;
> +}
> +
>   int tmc_read_prepare_etr(struct tmc_drvdata *drvdata)
>   {
>   	int ret = 0;
>   	unsigned long flags;
> +	const struct tmc_sysfs_ops *byte_cntr_ops;
>   
>   	/* config types are set a boot time and never change */
>   	if (WARN_ON_ONCE(drvdata->config_type != TMC_CONFIG_TYPE_ETR))
>   		return -EINVAL;
>   
> +	byte_cntr_ops = READ_ONCE(byte_cntr_sysfs_ops);
> +	if (byte_cntr_ops) {
> +		ret = byte_cntr_ops->read_prepare(drvdata);
> +		if (!ret || ret == -EBUSY)
> +			return ret;
> +
> +		ret = 0;
> +	}
> +
>   	raw_spin_lock_irqsave(&drvdata->spinlock, flags);
>   	if (drvdata->reading) {
>   		ret = -EBUSY;
> @@ -2087,11 +2177,17 @@ int tmc_read_unprepare_etr(struct tmc_drvdata *drvdata)
>   {
>   	unsigned long flags;
>   	struct etr_buf *sysfs_buf = NULL;
> +	const struct tmc_sysfs_ops *byte_cntr_ops;
>   
>   	/* config types are set a boot time and never change */
>   	if (WARN_ON_ONCE(drvdata->config_type != TMC_CONFIG_TYPE_ETR))
>   		return -EINVAL;
>   
> +	byte_cntr_ops = READ_ONCE(byte_cntr_sysfs_ops);
> +	if (byte_cntr_ops)
> +		if (!byte_cntr_ops->read_unprepare(drvdata))
> +			return 0;
> +
>   	raw_spin_lock_irqsave(&drvdata->spinlock, flags);
>   
>   	/* RE-enable the TMC if need be */
> diff --git a/drivers/hwtracing/coresight/coresight-tmc.h b/drivers/hwtracing/coresight/coresight-tmc.h
> index fbb015079872..a15e2f93f16a 100644
> --- a/drivers/hwtracing/coresight/coresight-tmc.h
> +++ b/drivers/hwtracing/coresight/coresight-tmc.h
> @@ -211,12 +211,15 @@ struct tmc_resrv_buf {
>   /**
>    * @sysfs_buf:	Allocated sysfs_buf.
>    * @is_free:	Indicates whether the buffer is free to choose.
> + * @reading:	Indicates byte_cntr is reading the buffer attached to
> + *		the node.
>    * @pos:	Offset to the start of the buffer.
>    * @link:	list_head of the node.
>    */
>   struct etr_buf_node {
>   	struct etr_buf		*sysfs_buf;
>   	bool			is_free;
> +	bool			reading;
>   	loff_t			pos;
>   	struct list_head	link;
>   };
> @@ -480,5 +483,11 @@ struct etr_buf *tmc_etr_get_buffer(struct coresight_device *csdev,
>   extern const struct attribute_group coresight_etr_group;
>   void tmc_clean_etr_buf_list(struct tmc_drvdata *drvdata);
>   int tmc_create_etr_buf_list(struct tmc_drvdata *drvdata, int num_nodes);
> +void tmc_etr_set_byte_cntr_sysfs_ops(const struct tmc_sysfs_ops *sysfs_ops);
> +void tmc_etr_reset_byte_cntr_sysfs_ops(void);
> +void tmc_etr_enable_disable_hw(struct tmc_drvdata *drvdata, bool enable);
> +bool tmc_etr_update_buf_node_pos(struct tmc_drvdata *drvdata, ssize_t size);
> +ssize_t tmc_etr_read_sysfs_buf(struct etr_buf *sysfs_buf, loff_t pos,
> +			       size_t len, char **bufpp);
>   
>   #endif
> 



^ permalink raw reply

* Re: [PATCH v6 04/20] dma-pool: track decrypted atomic pools and select them via attrs
From: Aneesh Kumar K.V @ 2026-06-11  4:51 UTC (permalink / raw)
  To: Jason Gunthorpe
  Cc: iommu, linux-arm-kernel, linux-kernel, linux-coco, Robin Murphy,
	Marek Szyprowski, Will Deacon, Marc Zyngier, Steven Price,
	Suzuki K Poulose, Catalin Marinas, Jiri Pirko, Mostafa Saleh,
	Petr Tesarik, Alexey Kardashevskiy, Dan Williams, Xu Yilun,
	linuxppc-dev, linux-s390, Madhavan Srinivasan, Michael Ellerman,
	Nicholas Piggin, Christophe Leroy (CS GROUP), Alexander Gordeev,
	Gerald Schaefer, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Sven Schnelle, x86, Jiri Pirko,
	Michael Kelley
In-Reply-To: <20260610164153.GQ2764304@ziepe.ca>

Jason Gunthorpe <jgg@ziepe.ca> writes:

> On Wed, Jun 10, 2026 at 01:37:26PM +0530, Aneesh Kumar K.V wrote:
>> Jason Gunthorpe <jgg@ziepe.ca> writes:
>> 
>> > On Thu, Jun 04, 2026 at 02:09:43PM +0530, Aneesh Kumar K.V (Arm) wrote:
>> >>  struct page *dma_alloc_from_pool(struct device *dev, size_t size,
>> >> -		void **cpu_addr, gfp_t gfp,
>> >> +		void **cpu_addr, gfp_t gfp, unsigned long attrs,
>> >>  		bool (*phys_addr_ok)(struct device *, phys_addr_t, size_t))
>> >>  {
>> >> -	struct gen_pool *pool = NULL;
>> >> +	struct dma_gen_pool *dma_pool = NULL;
>> >>  	struct page *page;
>> >>  	bool pool_found = false;
>> >>  
>> >> -	while ((pool = dma_guess_pool(pool, gfp))) {
>> >> +	while ((dma_pool = dma_guess_pool(dma_pool, gfp))) {
>> >> +
>> >> +		if (dma_pool->unencrypted != !!(attrs & DMA_ATTR_CC_SHARED))
>> >> +			continue;
>> >
>> > I don't think you should be overloading DMA_ATTR_CC_SHARED like this.
>> >
>> > 	/*
>> > 	 * DMA_ATTR_CC_SHARED is not a caller-visible dma_alloc_*()
>> > 	 * attribute. The direct allocator uses it internally after it has
>> > 	 * decided that the backing pages must be shared/decrypted, so the
>> > 	 * rest of the allocation path can consistently select DMA addresses,
>> > 	 * choose compatible pools and restore encryption on free.
>> > 	 */
>> > 	if (attrs & DMA_ATTR_CC_SHARED)
>> > 		return NULL;
>> >
>> > 	if (force_dma_unencrypted(dev)) {
>> > 		attrs |= DMA_ATTR_CC_SHARED;
>> > 		mark_mem_decrypt = true;
>> > 	}
>> >
>> > It is fine to have a bit inside the attrs that is only used by the
>> > internal logic, but it needs to have a clearer name
>> > __DMA_ATTR_REQUIRE_CC_SHARED perhaps.
>> >
>> 
>> Are you suggesting adding another attribute in addition to
>> DMA_ATTR_CC_SHARED?
>> 
>> Is the idea that __DMA_ATTR_REQUIRE_CC_SHARED would be used in the
>> allocation path to request a CC_SHARED allocation, while
>> DMA_ATTR_CC_SHARED would be used in the mapping path to describe the
>> attribute of the address?
>
> Yeah, it is a thought at least
>
> Maybe a comment is good enough.
>
> I just find it hard to follow when we have this dual usage. Like the
> code above for dma_pool->unencrypted is completely wrong if it is an
> "attribute of an address". Easy to cut & paste that into the wrong
> context.
>
> Especially if you move things up higher.. having the alloc set both
> CC_SHARED and REQUIRE_CC_SHARED or maybe ALLOC_CC_SHARED would make it
> clearer that the alloc code lives under that callchain
>
> Jason
>

If we are adding DMA_ATTR_ALLOC_SHARED, should we also allow
dma_alloc_attrs() to take that attribute value?

Does this look okay? 
(Note: Parts of the documentation text were updated using Codex.)

modified   Documentation/core-api/dma-attributes.rst
@@ -179,3 +179,32 @@ interface when building their uAPIs, when possible.
 
 It must never be used in an in-kernel driver that only works with
 kernel memory.
+
+DMA_ATTR_CC_SHARED
+------------------
+
+This attribute indicates that a DMA mapping is shared, or decrypted, for
+confidential computing guests. For normal system memory, the caller must
+already have marked the memory decrypted with set_memory_decrypted(). CPU
+PTEs for the mapping must use pgprot_decrypted(), and the same shared
+semantic may be passed to a vIOMMU when it sets up the IOPTE.
+
+This attribute describes an existing mapping. It does not allocate shared
+backing pages and must not be passed to dma_alloc_attrs(). For MMIO, use
+this together with DMA_ATTR_MMIO to indicate shared MMIO. Unless
+DMA_ATTR_MMIO is provided, the mapping requires a struct page.
+
+DMA_ATTR_ALLOC_CC_SHARED
+------------------------
+
+This attribute indicates that a dma_alloc_attrs() allocation must use
+shared, or decrypted, backing pages for confidential computing guests.
+Allocation paths use this request when they select shared DMA pools,
+decrypt newly allocated pages or restore encryption on free.
+
+DMA_ATTR_ALLOC_CC_SHARED differs from DMA_ATTR_CC_SHARED in that it
+requests shared backing memory from the allocation path. DMA_ATTR_CC_SHARED
+describes an already-shared mapping and requires the caller to have
+prepared normal system memory before mapping it. Callers that need shared
+memory from dma_alloc_attrs() should request DMA_ATTR_ALLOC_CC_SHARED
+instead of DMA_ATTR_CC_SHARED.
modified   include/linux/dma-mapping.h
@@ -103,6 +103,13 @@
  */
 #define DMA_ATTR_CC_SHARED	(1UL << 13)
 
+/*
+ * DMA_ATTR_ALLOC_CC_SHARED: Allocates DMA memory as shared (decrypted) for
+ * confidential computing guests. Unlike DMA_ATTR_CC_SHARED, this attribute
+ * is used by dma_alloc_attrs() paths that create shared backing pages;
+ * DMA_ATTR_CC_SHARED describes an already-shared mapping.
+ */
+#define DMA_ATTR_ALLOC_CC_SHARED	(1UL << 14)
 /*
  * A dma_addr_t can hold any valid DMA or bus address for the platform.  It can
  * be given to a device to use as a DMA source or target.  It is specific to a


^ permalink raw reply

* Re: [PATCH 00/39] Add i.MX95 DPU/DSI/LVDS support
From: Marek Vasut @ 2026-06-10 16:31 UTC (permalink / raw)
  To: Liu Ying
  Cc: Piyush Patle, dri-devel, imx, linux-arm-kernel, linux-clk,
	devicetree, Shawn Guo, Fabio Estevam, Peng Fan, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Lucas Stach, Laurent Pinchart,
	Thomas Zimmermann, Abel Vesa, Pengutronix Kernel Team
In-Reply-To: <aifOQtaAi_7F9hXt@raspi>

On 6/9/26 10:26 AM, Liu Ying wrote:

Hello Liu,

>>>> I brought this series up on the i.MX95 15x15 FRDM (IT6263 LVDS-to-HDMI on
>>>> LVDS ch1). It mostly works, but I ran into a few issues around DI routing,
>>>> LVDS format handling, and DC enable sequencing which needed rework before
>>>> HDMI would come up reliably on the board.
>>>>
>>>> I don't see a v2 of the series and things seem to have been quiet since
>>>> November. Are you planning to post an updated version?
>>>
>>> My plan was to enable prefetch engine support[1] for i.MX8QXP display
>>> controller and add device tree for a whole i.MX8QXP LVDS display pipeline,
>>> before adding i.MX95 display controller support.
>>>
>>> Unfortunately, it seems that Marek is not a big fan of [1]
>>
>> I am fine with [1] as long as it can be isolated and does not affect every
>> SoC that might reuse this driver, which I think it can be done.
> 
> How can it be isolated?

if (compatible("mx8q"))
   something->prefetch_op = somefunction;

And then wherever is prefetch used, do

if (something->prefetch_op)
   something->prefetch_op()

Or something along those lines ?

>>> and I'm busy
>>> with downstream development so the plan doesn't move forward well.  I still
>>> think [1] makes sense(maybe I need to rebase it on latest drm-misc-next),
>>> so I'd like to see review comments on [1] and hopefully people think that
>>> the overall idea of [1] is ok.
>>
>> My only concern is, to keep it isolated to MX8Q, so this driver can be
>> reused by MX95.
>>
>>>> I've accumulated a fair amount of rework while getting this running on the
>>>> FRDM. If you're not planning a v2, I can clean things up and send one based
>>>> on the current series.
>>>
>>> I still think that i.MX95 display controller driver should be in a separate
>>> driver, rather than sharing the same driver with i.MX8QXP display controller
>>> like this patch series does, because the two display controllers are quite
>>> different as I mentioned in comments on this patch series and in discussion
>>> in [1].  Also, the common part between the two display controllers should
>>> be extracted to a common helper library as I mentioned there too.
>> Are they really? It seems this series adds support for the MX95 DC without
>> that many changes, so are the DCs really that different ? It seems the MX95
>> DC is simply a reuse/evolution of the MX8Q DC blocks, so duplicating the
>> code seems like the wrong direction, it will only lead to disparate sets of
>> bugs in two drivers, which isn't desired.
> 
> I pointed out a lot of H/W differences between the two display controllers
> during the discussions for this patch series and my i.MX8QXP prefetch engine
> patch series[1].  Please take a look at [1], which clearly shows that the
> prefetch engine would considerably impact CRTC/plane atomic callback
> implementations.

Is the prefetch engine actually grown into the CRTC/DE or not ? I 
suspect it is separate and instead part of the built-in DMA, right ?

> Display controller internal blocks would also impact
> the implementations, e.g., DomainBlend block in i.MX95 display controller
> doesn't present in i.MX8QXP display controller.  It makes sense to use
> separate drivers for the two display controllers instead of adding 'if/else'
> checks to a single driver's atomic callbacks or introducing two pairs of
> atomic callbacks to that single driver.  I mentioned before, the code to
> simply add a DRM driver(struct drm_driver) is fairly limited.

Can't we simply have two sets of ops (one for mx8q and one for mx95) for 
those ops which are too complicated to implement as a single op with 
if/else statements ?

> I also mentioned before that separate drivers make them easier to maintain:
> we don't have to test both i.MX8QXP and i.MX95 if only one display controller
> specific code is changed.

The downside is lack of code reuse, which leads to disparate sets of 
bugs in these two drivers and code duplication. And it seems to me, that 
large parts of the MX8Q and MX95 DC are effectively identical.

>> (I might not fully understand what you have in mind with the helper library
>> though?)
> 
> I said this could be something like imx-ldb-helper.c and plus perhaps some
> callbacks like fg->dc_fg_cfg_videomode().
Do you perceive that the DC driver cannot be parametrized easily enough 
that it has to be turned into a library like that ? When I look at this 
patchset, esp. the first half which updates the various blocks, it does 
not seem to me that way.


^ permalink raw reply

* Re: [PATCH v2] virt: arm-cca-guest: use raw variant of smp_processor_id() in arm_cca_report_new()
From: Kohei Enju @ 2026-06-11  4:12 UTC (permalink / raw)
  To: Suzuki K Poulose
  Cc: Will Deacon, Catalin Marinas, Sami Mujawar, Gavin Shan,
	Steven Price, linux-arm-kernel, linux-kernel
In-Reply-To: <51a76d18-6db9-41f3-a1d4-60360088c442@arm.com>

On 06/09 14:44, Suzuki K Poulose wrote:
> On 09/06/2026 14:16, Kohei Enju wrote:
> > On 06/03 12:48, Will Deacon wrote:
> > > On Tue, Jun 02, 2026 at 04:48:43PM +0100, Suzuki K Poulose wrote:
> > > > On 02/06/2026 12:01, Will Deacon wrote:
> > > > > On Tue, May 19, 2026 at 07:12:08PM +0900, Kohei Enju wrote:
> > > > > > With CONFIG_DEBUG_PREEMPT=y, smp_processor_id() becomes an alias of
> > > > > > debug_smp_processor_id(). This debug function complains when certain
> > > > > > conditions that ensure CPU ID stability are not met, specifically when
> > > > > > it's called from a preemptible context.
> > > > > > 
> > > > > > In arm_cca_report_new(), which runs in a preemptible context,
> > > > > > smp_processor_id() triggers a splat [0] due to this.
> > > > > > 
> > > > > > However, the CPU ID obtained here is used as the target CPU for
> > > > > > smp_call_function_single() to designate a specific CPU for subsequent
> > > > > > operations, not to assert that the current thread will continue to
> > > > > > execute on the same CPU. Therefore, snapshotting the CPU ID itself is
> > > > > > correct, and thus there's no actual harm except for the splat.
> > > > > > 
> > > > > > Use raw_smp_processor_id() instead, to directly retrieve the current CPU
> > > > > > ID without the debug checks, avoiding the unnecessary warning message
> > > > > > while preserving the correct functional behavior.
> > > > > 
> > > > > That's pretty disgusting imo so I'd like to see some more justification
> > > > > for this approach.
> > > > > 
> > > > > > Note that while migrate_disable() would pin the task to the current CPU,
> > > > > > this path should not block CPU hotplug events. Therefore, we snapshot
> > > > > > the current CPU ID and accept that smp_call_function_single() may fail
> > > > > > if the CPU goes offline.
> > > > > 
> > > > > Why shouldn't it block CPU hotplug events? What happens if the CPU goes
> > > > > offline and comes back online again during the loop of continue calls?
> > > > 
> > > > It need not. It can continue the calls. The RMM keeps track of the internal
> > > > progress in the "REC" object for this "VCPU". Hotplug ON/OFF
> > > > doesn't change the REC object in CCA Guest. So, a REC can come back and
> > > > execute it. But the Linux could fail the operation if the CPU isn't
> > > > available for fetching the report, after we do a RSI_ATTEST_TOKEN_INIT.
> > > 
> > > I couldn't really shake that out of the RMM spec tbh:
> > > RSI_ATTESTATION_TOKEN_CONTINUE is allowed to return RSI_ERROR_UNKNOWN
> > > and I couldn't find anything about hotplug.
> 
> Like I said, we are dealing with Virtual CPUs (RECs here) and the only
> condition that the RMM enforces is the _CONTINUE calls are issued on the
> same VCPU (REC). Hotplug doesn't change the REC (as a REC cannot be
> modified or added once the Realm is ACTIVE).
> 
> > > 
> > > But my main point, really, is why are we not using migrate_disable()
> > > here? I can't see the justification.
> 
> There is no reason, why we couldn't use this. TBH, I wasn't aware of the
> helper ;-) at the time this was initially designed and we didn't want to
> block CPU hotplug. We could always request a new report, it is not like
> aborting a report generation has any side effects.
> 
> > 
> > Hi Will,
> > Sorry for the late reply.
> > 
> > I agree that using migrate_disable() makes this path simpler and
> > clearer.
> > 
> > I've reviewed the discussion where the original commit was introduced:
> >      https://lore.kernel.org/linux-arm-kernel/7a83461d-40fd-4e61-8833-5dae2abaf82b@arm.com/
> > but I couldn't find a strong reason why we shouldn't block CPU hotplug
> > or use migrate_disable(), even though I can see the current design was
> > intentional.
> > 
> > So I'm happy to rework the patch to use migrate_disable() and remove
> > the smp_call_function_single() calls if there are no objections.
> 
> I am fine with removing with migrate_disable() approach.

Hi Suzuki,

Thank you for your clarification, and explanation in this discussion.
I'll work on v3 soon.

> 
> Cheers
> Suzuki
> 
> > 
> > > 
> > > Will
> > > 
> 
> 


^ permalink raw reply

* Re: [PATCH 2/2] arm64: ftrace: allow DIRECT_CALLS without CALL_OPS
From: Xu Kuohai @ 2026-06-11  4:06 UTC (permalink / raw)
  To: Jose Fernandez (Anthropic), Steven Rostedt, Masami Hiramatsu,
	Mark Rutland, Catalin Marinas, Will Deacon, Nathan Chancellor,
	Nick Desaulniers, Bill Wendling, Justin Stitt
  Cc: linux-kernel, linux-trace-kernel, linux-arm-kernel, llvm, bpf,
	Florent Revest, Puranjay Mohan
In-Reply-To: <20260609-arm64-ftrace-direct-calls-v1-2-4a46f266697f@linux.dev>

On 6/9/2026 1:19 PM, Jose Fernandez (Anthropic) wrote:
> arm64 gained ftrace direct calls in commit 2aa6ac03516d ("arm64:
> ftrace: Add direct call support") on top of
> DYNAMIC_FTRACE_WITH_CALL_OPS, using the per-callsite ops pointer as a
> fast path to reach the direct trampoline. Since commit baaf553d3bc3
> ("arm64: Implement HAVE_DYNAMIC_FTRACE_WITH_CALL_OPS"), CALL_OPS is
> mutually exclusive with CFI: the pre-function NOPs would change the
> offset of the pre-function kCFI type hash, and the compiler support
> needed to keep that offset consistent does not exist yet.
> 
> The result is that a CONFIG_CFI=y kernel loses CALL_OPS, and with it
> DIRECT_CALLS, and with it every BPF trampoline attachment to kernel
> functions: register_fentry() returns -ENOTSUPP, so fentry/fexit,
> fmod_ret and BPF LSM programs cannot attach at all. This is a real
> problem for hardened arm64 deployments that rely on BPF LSM for
> security monitoring while keeping kCFI enabled.
> 
> CALL_OPS is an optimization for direct calls, not a dependency. When
> the direct trampoline is within BL range, the callsite branches
> straight to it and ftrace_caller is not involved. When it is out of
> range, ftrace_find_callable_addr() already falls back to
> ftrace_caller, and the DIRECT_CALLS machinery there
> (FREGS_DIRECT_TRAMP, ftrace_caller_direct_late) is gated on
> DIRECT_CALLS alone, not CALL_OPS: the ops dispatch invokes
> call_direct_funcs(), which stores the trampoline address in
> ftrace_regs, and ftrace_caller tail-calls it. s390 and loongarch use
> this same mechanism for HAVE_DYNAMIC_FTRACE_WITH_DIRECT_CALLS without
> having CALL_OPS at all, and DYNAMIC_FTRACE_WITH_ARGS without CALL_OPS
> is already a supported arm64 configuration (GCC builds with
> CC_OPTIMIZE_FOR_SIZE do not satisfy the CALL_OPS select condition).
> 
> Drop the CALL_OPS requirement from the
> HAVE_DYNAMIC_FTRACE_WITH_DIRECT_CALLS select. Configurations that
> keep CALL_OPS (!CFI clang builds, and GCC builds without
> CC_OPTIMIZE_FOR_SIZE) are unchanged. CALL_OPS-less configurations
> take the ftrace_caller ops-dispatch path for out-of-range direct
> calls, trading the per-callsite fast path for working BPF
> trampolines; in-range attachments still branch directly with no
> overhead. GCC -Os builds also gain DIRECT_CALLS as a side effect.
> That is intended: s390 and loongarch already ship DIRECT_CALLS
> without any per-callsite fast path.
> 
> Assisted-by: Claude:unspecified
> Signed-off-by: Jose Fernandez (Anthropic) <jose.fernandez@linux.dev>
> ---
>   arch/arm64/Kconfig | 2 +-
>   1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
> index fe60738e5943b..2cd7d536671c9 100644
> --- a/arch/arm64/Kconfig
> +++ b/arch/arm64/Kconfig
> @@ -188,7 +188,7 @@ config ARM64
>   		if (GCC_SUPPORTS_DYNAMIC_FTRACE_WITH_ARGS || \
>   		    CLANG_SUPPORTS_DYNAMIC_FTRACE_WITH_ARGS)
>   	select HAVE_DYNAMIC_FTRACE_WITH_DIRECT_CALLS \
> -		if DYNAMIC_FTRACE_WITH_ARGS && DYNAMIC_FTRACE_WITH_CALL_OPS
> +		if DYNAMIC_FTRACE_WITH_ARGS
>   	select HAVE_DYNAMIC_FTRACE_WITH_CALL_OPS \
>   		if (DYNAMIC_FTRACE_WITH_ARGS && !CFI && \
>   		    (CC_IS_CLANG || !CC_OPTIMIZE_FOR_SIZE))
> 
Acked-by: Xu Kuohai <xukuohai@huawei.com>



^ permalink raw reply

* Re: [PATCH 1/2] arm64: ftrace: prepare ftrace_modify_call() for use without CALL_OPS
From: Xu Kuohai @ 2026-06-11  4:06 UTC (permalink / raw)
  To: Jose Fernandez (Anthropic), Steven Rostedt, Masami Hiramatsu,
	Mark Rutland, Catalin Marinas, Will Deacon, Nathan Chancellor,
	Nick Desaulniers, Bill Wendling, Justin Stitt
  Cc: linux-kernel, linux-trace-kernel, linux-arm-kernel, llvm, bpf,
	Florent Revest, Puranjay Mohan
In-Reply-To: <20260609-arm64-ftrace-direct-calls-v1-1-4a46f266697f@linux.dev>

On 6/9/2026 1:19 PM, Jose Fernandez (Anthropic) wrote:
> ftrace_modify_call() is guarded by CONFIG_DYNAMIC_FTRACE_WITH_CALL_OPS
> and calls ftrace_rec_set_ops(rec, arm64_rec_get_ops(rec)) directly,
> which only exists when CALL_OPS is enabled.
> 
> Generic ftrace also needs ftrace_modify_call() when
> CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS is enabled, to retarget a
> callsite between two non-FTRACE_ADDR destinations, as happens when a
> direct trampoline is modified. The next patch allows DIRECT_CALLS without
> CALL_OPS, so widen the guard to cover both configurations and switch
> the body to the ftrace_rec_update_ops() wrapper, which already has a
> stub for the !CALL_OPS case. ftrace_make_call() already uses the same
> wrapper today.
> 
> No functional change: with CALL_OPS enabled, ftrace_rec_update_ops()
> expands to the exact call this replaces.
> 
> Assisted-by: Claude:unspecified
> Signed-off-by: Jose Fernandez (Anthropic) <jose.fernandez@linux.dev>
> ---
>   arch/arm64/kernel/ftrace.c | 5 +++--
>   1 file changed, 3 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/arm64/kernel/ftrace.c b/arch/arm64/kernel/ftrace.c
> index 5a1554a441628..e1a3c0b3a0514 100644
> --- a/arch/arm64/kernel/ftrace.c
> +++ b/arch/arm64/kernel/ftrace.c
> @@ -409,7 +409,8 @@ int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
>   	return ftrace_modify_code(pc, old, new, true);
>   }
>   
> -#ifdef CONFIG_DYNAMIC_FTRACE_WITH_CALL_OPS
> +#if defined(CONFIG_DYNAMIC_FTRACE_WITH_CALL_OPS) || \
> +	defined(CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS)
>   int ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr,
>   		       unsigned long addr)
>   {
> @@ -417,7 +418,7 @@ int ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr,
>   	u32 old, new;
>   	int ret;
>   
> -	ret = ftrace_rec_set_ops(rec, arm64_rec_get_ops(rec));
> +	ret = ftrace_rec_update_ops(rec);
>   	if (ret)
>   		return ret;
>   
>
Acked-by: Xu Kuohai <xukuohai@huawei.com>



^ permalink raw reply

* Re: [PATCH v3 0/9] ARM: dts: aspeed: anacapa: restructure devicetree for development-phase
From: Andrew Jeffery @ 2026-06-11  4:06 UTC (permalink / raw)
  To: u8813345, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Joel Stanley
  Cc: devicetree, linux-arm-kernel, linux-aspeed, linux-kernel,
	colin.huang2, Carl Lee, Rex Fu, Andy Chung, Peter Shen
In-Reply-To: <20260602-anacapa-devlop-phase-devicetree-v3-0-7c93c5df8d9b@gmail.com>

Hi Colin,

On Tue, 2026-06-02 at 21:24 +0800, Colin Huang via B4 Relay wrote:


...

> 
> Colin Huang (5):
>       ARM: dts: aspeed: anacapa: add EVT1 devicetree and point wrapper to it
>       ARM: dts: aspeed: anacapa: add EVT2 devicetree inheriting EVT1
>       ARM: dts: aspeed: anacapa: add DVT devicetree inheriting EVT2

So my concern with these three are that none of the EVT1, EVT2 or DVT
devicetrees correspond with the current Anacapa devicetree. All of them
have variations on the configured GPIOs. Some GPIO lines are renamed
while others are added.

Adding them is (eventually) fine, but I'd rather not do that while
we're shuffling the devicetree sources around.

Renaming them to accommodate changes in the one devicetree is what
we're trying to escape here, so having renames hide in the rest of the
shuffling is definitely problematic.

For example:

   -""                     
   +"L_FNIC_FLT"      
    "FM_CPU0_SYS_RESET_N"
   -""                                                                                                                                                            
   +"L_BNIC0_FLT"
    "CPU0_KBRST_N"
   -""
   +"L_BNIC1_FLT"
    "FM_CPU0_PROCHOT_trigger_N"
   -""
   +"L_BNIC2_FLT"
    "FM_CLR_CMOS_R_P0"
   -""
   +"L_BNIC3_FLT"
    "Force_I3C_SEL"
   -""
   +"L_RTM_SW_FLT"
    "SYSTEM_Force_Run_AC_Cycle"
    ""
    ""
   @@ -20,55 +20,57 @@
    "FM_SCM_JTAG_MUX_SEL"
    "Channel2_leakage_Manifold1"
    "FM_BRIDGE_JTAG_MUX_SEL"
   -"Channel3_leakage"
   +"Channel5_leakage_present_EAM1"

I've pasted a script below that helps compare the various dts files.
You can use it to generate the reference from the current aspeed-bmc-
facebook-anacapa.dts, then generate the comparison files from the newly
introduced dts files.

To reiterate, I expect the shuffling of the dts files to result in at
least one of the variants producing the same devicetree as the current
aspeed-bmc-facebook-anacapa.dts.

Andrew

   #!/usr/bin/bash
   
   set -x
   
   : ${ANACAPA_VARIANT:=""}
   : ${ANACAPA_REFERENCE:="arch/arm/boot/dts/aspeed/.aspeed-bmc-facebook-anacapa.dtb.rt.dts.tmp"}
   
   if [ -z "$ANACAPA_REFERENCE" ] || ! [ -e "$ANACAPA_REFERENCE" ]
   then
     gcc -E -Wp,-MMD,arch/arm/boot/dts/aspeed/.aspeed-bmc-facebook-anacapa.dtb.d.pre.tmp -nostdinc -I ../scripts/dtc/include-prefixes -undef -D__DTS__ -x assembler-with-cpp -o arch/arm/boot/dts/aspeed/.aspeed-bmc-facebook-anacapa.dtb.dts.tmp ../arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-anacapa.dts ; ./scripts/dtc/dtc -o arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-anacapa.dtb -b 0 -i../arch/arm/boot/dts/aspeed/ -i../scripts/dtc/include-prefixes -Wno-unique_unit_address -Wno-unit_address_vs_reg -Wno-avoid_unnecessary_addr_size -Wno-alias_paths -Wno-interrupt_map -Wno-simple_bus_reg   -d arch/arm/boot/dts/aspeed/.aspeed-bmc-facebook-anacapa.dtb.d.dtc.tmp arch/arm/boot/dts/aspeed/.aspeed-bmc-facebook-anacapa.dtb.dts.tmp ; cat arch/arm/boot/dts/aspeed/.aspeed-bmc-facebook-anacapa.dtb.d.pre.tmp arch/arm/boot/dts/aspeed/.aspeed-bmc-facebook-anacapa.dtb.d.dtc.tmp > arch/arm/boot/dts/aspeed/.aspeed-bmc-facebook-anacapa.dtb.d
     dtc -I dts -O dts -o arch/arm/boot/dts/aspeed/.aspeed-bmc-facebook-anacapa.dtb.rt.dts.tmp arch/arm/boot/dts/aspeed/.aspeed-bmc-facebook-anacapa.dtb.dts.tmp
     ANACAPA_REFERENCE=arch/arm/boot/dts/aspeed/.aspeed-bmc-facebook-anacapa.dtb.rt.dts.tmp
   fi
   
   if [ -n "$ANACAPA_VARIANT" ]
   then
     gcc -E -Wp,-MMD,arch/arm/boot/dts/aspeed/.aspeed-bmc-facebook-anacapa-${ANACAPA_VARIANT}.dtb.d.pre.tmp -nostdinc -I ../scripts/dtc/include-prefixes -undef -D__DTS__ -x assembler-with-cpp -o arch/arm/boot/dts/aspeed/.aspeed-bmc-facebook-anacapa-${ANACAPA_VARIANT}.dtb.dts.tmp ../arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-anacapa-${ANACAPA_VARIANT}.dts ; ./scripts/dtc/dtc -o arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-anacapa-${ANACAPA_VARIANT}.dtb -b 0 -i../arch/arm/boot/dts/aspeed/ -i../scripts/dtc/include-prefixes -Wno-unique_unit_address -Wno-unit_address_vs_reg -Wno-avoid_unnecessary_addr_size -Wno-alias_paths -Wno-interrupt_map -Wno-simple_bus_reg   -d arch/arm/boot/dts/aspeed/.aspeed-bmc-facebook-anacapa-${ANACAPA_VARIANT}.dtb.d.dtc.tmp arch/arm/boot/dts/aspeed/.aspeed-bmc-facebook-anacapa-${ANACAPA_VARIANT}.dtb.dts.tmp ; cat arch/arm/boot/dts/aspeed/.aspeed-bmc-facebook-anacapa-${ANACAPA_VARIANT}.dtb.d.pre.tmp arch/arm/boot/dts/aspeed/.aspeed-bmc-facebook-anacapa-${ANACAPA_VARIANT}.dtb.d.dtc.tmp > arch/arm/boot/dts/aspeed/.aspeed-bmc-facebook-anacapa-${ANACAPA_VARIANT}.dtb.d
     dtc -I dts -O dts -o arch/arm/boot/dts/aspeed/.aspeed-bmc-facebook-anacapa-${ANACAPA_VARIANT}.dtb.rt.dts.tmp arch/arm/boot/dts/aspeed/.aspeed-bmc-facebook-anacapa-${ANACAPA_VARIANT}.dtb.dts.tmp
     diff -u "$ANACAPA_REFERENCE" arch/arm/boot/dts/aspeed/.aspeed-bmc-facebook-anacapa-${ANACAPA_VARIANT}.dtb.rt.dts.tmp | tee ${ANACAPA_VARIANT}-{remove,add}
     grep '^-[^-]' ${ANACAPA_VARIANT}-remove | grep gpio-line-names | sed -E 's/.+gpio-line-names = //' | tr ',' '\n' | sed -E 's/^ //' | sponge ${ANACAPA_VARIANT}-remove
     grep '^[+][^+]' ${ANACAPA_VARIANT}-add | grep gpio-line-names | sed -E 's/.+gpio-line-names = //' | tr ',' '\n' | sed -E 's/^ //' | sponge ${ANACAPA_VARIANT}-add
     diff -u ${ANACAPA_VARIANT}-{remove,add}
   fi



^ permalink raw reply

* [PATCH] rtc: meson: fix refcount leak in meson_rtc_get_bus
From: WenTao Liang @ 2026-06-11  3:56 UTC (permalink / raw)
  To: alexandre.belloni, neil.armstrong, khilman, p.zabel
  Cc: jbrunet, martin.blumenstingl, ben.dooks, linux-rtc,
	linux-arm-kernel, linux-amlogic, linux-kernel, WenTao Liang,
	stable

In meson_rtc_get_bus(), reset_control_reset() is called to trigger
a hardware reset when the serial bus is not ready. The function may
retry up to three times, but neither the successful nor the failure
path calls reset_control_rearm() to balance the reference count,
leaking the triggered_count on shared reset controls.

Fix this by adding reset_control_rearm() after reset_control_reset()
on both the error return path and the success path within the retry
loop, ensuring the reset control can be re-triggered on subsequent
bus acquisition attempts.

Cc: stable@vger.kernel.org
Fixes: d8fe6009aa3e ("rtc: support for the Amlogic Meson RTC")
Signed-off-by: WenTao Liang <vulab@iscas.ac.cn>
---
 drivers/rtc/rtc-meson.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/rtc/rtc-meson.c b/drivers/rtc/rtc-meson.c
index 21eceb9e2e13..729384dceb12 100644
--- a/drivers/rtc/rtc-meson.c
+++ b/drivers/rtc/rtc-meson.c
@@ -146,8 +146,12 @@ static int meson_rtc_get_bus(struct meson_rtc *rtc)
 		dev_warn(rtc->dev, "failed to get bus, resetting RTC\n");
 
 		ret = reset_control_reset(rtc->reset);
-		if (ret)
+		if (ret) {
+			reset_control_rearm(rtc->reset);
 			return ret;
+		}
+
+		reset_control_rearm(rtc->reset);
 	}
 
 	dev_err(rtc->dev, "bus is not ready\n");
-- 
2.50.1 (Apple Git-155)



^ permalink raw reply related

* [PATCH RESEND] nvmem: apple-spmi-nvmem: wrap regmap calls to satisfy CFI
From: Aelin Reidel @ 2026-06-11  3:46 UTC (permalink / raw)
  To: Sven Peter, Janne Grunau, Neal Gompa, Srinivas Kandagatla,
	Greg Kroah-Hartman, Sasha Finkelstein, Hector Martin
  Cc: asahi, linux-arm-kernel, linux-kernel, Aelin Reidel,
	Clayton Craft, stable

The Apple SPMI NVMEM driver previously cast regmap_bulk_read/write to
void * when assigning them to nvmem_config's reg_read/reg_write
function pointers.

This cast breaks the expected function signature of nvmem_reg_read_t
and nvmem_reg_write_t. With CFI enabled, indirect calls through
these pointers fail:

  CFI failure at nvmem_reg_write+0x194/0x1e4 (target: regmap_bulk_write+0x0/0x2c8; expected type: 0x83a189c3)
  ...
  Call trace:
   nvmem_reg_write+0x194/0x1e4 (P)
   __nvmem_cell_entry_write+0x298/0x2e8
   nvmem_cell_write+0x24/0x34
   macsmc_reboot_probe+0x1dc/0x454 [macsmc_reboot]
  ...

Introduce thin wrapper functions with the correct nvmem function
pointer types to satisfy the CFI checks.

Fixes: fe91c24a551c ("nvmem: Add apple-spmi-nvmem driver")
Signed-off-by: Aelin Reidel <aelin@mainlining.org>
Reported-by: Clayton Craft <craftyguy@postmarketos.org>
Tested-by: Clayton Craft <craftyguy@postmarketos.org>
Reviewed-by: Sven Peter <sven@kernel.org>
Cc: stable@vger.kernel.org
---
Difference vs the original patch:
- Updated my name and email
- Picked up Sven's R-b
- Link to original: https://lore.kernel.org/all/20251118-apple-spmi-nvmem-cfi-v1-1-75b9ced0a2c2@mainlining.org/

It's been half a year, so I figured I'd gently poke for this to be
applied.
---
 drivers/nvmem/apple-spmi-nvmem.c | 20 ++++++++++++++++++--
 1 file changed, 18 insertions(+), 2 deletions(-)

diff --git a/drivers/nvmem/apple-spmi-nvmem.c b/drivers/nvmem/apple-spmi-nvmem.c
index 88614005d5ce..7acb0c07d6ab 100644
--- a/drivers/nvmem/apple-spmi-nvmem.c
+++ b/drivers/nvmem/apple-spmi-nvmem.c
@@ -18,6 +18,22 @@ static const struct regmap_config apple_spmi_regmap_config = {
 	.max_register	= 0xffff,
 };
 
+static int apple_spmi_nvmem_read(void *priv, unsigned int offset, void *val,
+				 size_t bytes)
+{
+	struct regmap *map = priv;
+
+	return regmap_bulk_read(map, offset, val, bytes);
+}
+
+static int apple_spmi_nvmem_write(void *priv, unsigned int offset, void *val,
+				  size_t bytes)
+{
+	struct regmap *map = priv;
+
+	return regmap_bulk_write(map, offset, val, bytes);
+}
+
 static int apple_spmi_nvmem_probe(struct spmi_device *sdev)
 {
 	struct regmap *regmap;
@@ -28,8 +44,8 @@ static int apple_spmi_nvmem_probe(struct spmi_device *sdev)
 		.word_size = 1,
 		.stride = 1,
 		.size = 0xffff,
-		.reg_read = (void *)regmap_bulk_read,
-		.reg_write = (void *)regmap_bulk_write,
+		.reg_read = apple_spmi_nvmem_read,
+		.reg_write = apple_spmi_nvmem_write,
 	};
 
 	regmap = devm_regmap_init_spmi_ext(sdev, &apple_spmi_regmap_config);

---
base-commit: abe651837cb394f76d738a7a747322fca3bf17ba
change-id: 20260611-apple-spmi-nvmem-cfi-673d5202f7e4

Best regards,
--  
Aelin Reidel <aelin@mainlining.org>


^ permalink raw reply related

* [PATCH] rtc: meson: fix refcount leak in meson_rtc_get_bus
From: WenTao Liang @ 2026-06-11  3:40 UTC (permalink / raw)
  To: alexandre.belloni
  Cc: neil.armstrong, khilman, jbrunet, martin.blumenstingl, p.zabel,
	ben.dooks, linux-rtc, linux-arm-kernel, linux-amlogic,
	linux-kernel, WenTao Liang, stable

In meson_rtc_get_bus(), reset_control_reset() is called to trigger
a hardware reset when the serial bus is not ready. The function may
retry up to three times, but neither the successful nor the failure
path calls reset_control_rearm() to balance the reference count,
leaking the triggered_count on shared reset controls.

Fix this by adding reset_control_rearm() after reset_control_reset()
on both the error return path and the success path within the retry
loop, ensuring the reset control can be re-triggered on subsequent
bus acquisition attempts.

Cc: stable@vger.kernel.org
Fixes: d8fe6009aa3e ("rtc: support for the Amlogic Meson RTC")
Signed-off-by: WenTao Liang <vulab@iscas.ac.cn>
---
 drivers/rtc/rtc-meson.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/rtc/rtc-meson.c b/drivers/rtc/rtc-meson.c
index 21eceb9e2e13..729384dceb12 100644
--- a/drivers/rtc/rtc-meson.c
+++ b/drivers/rtc/rtc-meson.c
@@ -146,8 +146,12 @@ static int meson_rtc_get_bus(struct meson_rtc *rtc)
 		dev_warn(rtc->dev, "failed to get bus, resetting RTC\n");
 
 		ret = reset_control_reset(rtc->reset);
-		if (ret)
+		if (ret) {
+			reset_control_rearm(rtc->reset);
 			return ret;
+		}
+
+		reset_control_rearm(rtc->reset);
 	}
 
 	dev_err(rtc->dev, "bus is not ready\n");
-- 
2.50.1 (Apple Git-155)



^ permalink raw reply related

* [PATCHv3 4/6] serial: mxs-auart: fix IRQ registration ordering and manage console clock
From: Rosen Penev @ 2026-06-11  3:38 UTC (permalink / raw)
  To: linux-serial
  Cc: Greg Kroah-Hartman, Jiri Slaby, Frank Li, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam,
	open list:TTY LAYER AND SERIAL DRIVERS,
	open list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE,
	moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE
In-Reply-To: <20260611033856.6476-1-rosenp@gmail.com>

Move the main UART IRQ registration after uart_add_one_port so that
s->port.state and s->port.lock are initialized before the interrupt
handler can run. Mask all UART interrupts before adding the port to
prevent spurious IRQs left by the bootloader.

After probe succeeds, disable the module clock for non-console ports
since startup will re-enable it on port open. For console ports, keep
the clock prepared so auart_console_write() can safely call
clk_enable() from atomic context.

Guard the IRQ handler and get_mctrl with clk_enable/clk_disable since
GPIO IRQs and serial-core status queries can fire while the clock is
disabled for non-console ports.

In remove, disable the clock for console ports to balance the enable
done in probe, preventing a clock leak on unbind.

Assisted-by: opencode:big-pickle
---
 drivers/tty/serial/mxs-auart.c | 49 +++++++++++++++++++++++++++-------
 1 file changed, 39 insertions(+), 10 deletions(-)

diff --git a/drivers/tty/serial/mxs-auart.c b/drivers/tty/serial/mxs-auart.c
index 4499e3206e85..e2b656638ab3 100644
--- a/drivers/tty/serial/mxs-auart.c
+++ b/drivers/tty/serial/mxs-auart.c
@@ -738,9 +738,13 @@ static u32 mxs_auart_modem_status(struct mxs_auart_port *s, u32 mctrl)
 static u32 mxs_auart_get_mctrl(struct uart_port *u)
 {
 	struct mxs_auart_port *s = to_auart_port(u);
-	u32 stat = mxs_read(s, REG_STAT);
+	u32 stat;
 	u32 mctrl = 0;
 
+	clk_enable(s->clk);
+	stat = mxs_read(s, REG_STAT);
+	clk_disable(s->clk);
+
 	if (stat & AUART_STAT_CTS)
 		mctrl |= TIOCM_CTS;
 
@@ -1079,6 +1083,7 @@ static irqreturn_t mxs_auart_irq_handle(int irq, void *context)
 	struct mxs_auart_port *s = context;
 	u32 mctrl_temp = s->mctrl_prev;
 
+	clk_enable(s->clk);
 	uart_port_lock(&s->port);
 
 	stat = mxs_read(s, REG_STAT);
@@ -1118,6 +1123,7 @@ static irqreturn_t mxs_auart_irq_handle(int irq, void *context)
 	}
 
 	uart_port_unlock(&s->port);
+	clk_disable(s->clk);
 
 	return IRQ_HANDLED;
 }
@@ -1603,10 +1609,6 @@ static int mxs_auart_probe(struct platform_device *pdev)
 	}
 
 	s->port.irq = irq;
-	ret = devm_request_irq(&pdev->dev, irq, mxs_auart_irq_handle, 0,
-			       dev_name(&pdev->dev), s);
-	if (ret)
-		goto out_disable_clk;
 
 	platform_set_drvdata(pdev, s);
 
@@ -1627,9 +1629,28 @@ static int mxs_auart_probe(struct platform_device *pdev)
 
 	mxs_auart_reset_deassert(s);
 
+	/* Mask all UART interrupts to prevent spurious IRQs from bootloader */
+	mxs_write(0, s, REG_INTR);
+
 	ret = uart_add_one_port(&auart_driver, &s->port);
-	if (ret)
-		goto out_free_qpio_irq;
+	if (ret) {
+		auart_port[s->port.line] = NULL;
+		goto out_disable_clk;
+	}
+
+	/*
+	 * Request the main IRQ after uart_add_one_port so that
+	 * s->port.state and s->port.lock are initialized before
+	 * the handler can run in response to a bootloader-left
+	 * interrupt.
+	 */
+	ret = devm_request_irq(&pdev->dev, irq, mxs_auart_irq_handle, 0,
+			       dev_name(&pdev->dev), s);
+	if (ret) {
+		uart_remove_one_port(&auart_driver, &s->port);
+		auart_port[s->port.line] = NULL;
+		goto out_disable_clk;
+	}
 
 	/* ASM9260 don't have version reg */
 	if (is_asm9260_auart(s)) {
@@ -1641,10 +1662,16 @@ static int mxs_auart_probe(struct platform_device *pdev)
 			 (version >> 16) & 0xff, version & 0xffff);
 	}
 
-	return 0;
+	/*
+	 * Disable clock -- startup will re-enable when the port is opened.
+	 * For the console port the clock must stay prepared so that
+	 * auart_console_write() can safely call clk_enable() from
+	 * atomic context.
+	 */
+	if (!uart_console(&s->port))
+		clk_disable_unprepare(s->clk);
 
-out_free_qpio_irq:
-	auart_port[s->port.line] = NULL;
+	return 0;
 
 out_disable_clk:
 	clk_disable_unprepare(s->clk);
@@ -1657,6 +1684,8 @@ static void mxs_auart_remove(struct platform_device *pdev)
 
 	uart_remove_one_port(&auart_driver, &s->port);
 	auart_port[s->port.line] = NULL;
+	if (uart_console(&s->port))
+		clk_disable_unprepare(s->clk);
 }
 
 static struct platform_driver mxs_auart_driver = {
-- 
2.54.0



^ permalink raw reply related

* [PATCHv3 6/6] serial: mxs-auart: terminate DMA before releasing channels in exit
From: Rosen Penev @ 2026-06-11  3:38 UTC (permalink / raw)
  To: linux-serial
  Cc: Greg Kroah-Hartman, Jiri Slaby, Frank Li, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam,
	open list:TTY LAYER AND SERIAL DRIVERS,
	open list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE,
	moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE
In-Reply-To: <20260611033856.6476-1-rosenp@gmail.com>

mxs_auart_dma_exit_channel() calls dma_release_channel() and then
kfree() on the DMA buffers without first terminating any in-flight
transfers. If an asynchronous DMA transfer completes after the buffers
have been freed, the callback will access freed memory.

Call dmaengine_terminate_sync() on each channel before releasing it
to safely abort pending transfers.

Assisted-by: opencode:big-pickle
Signed-off-by: Rosen Penev <rosenp@gmail.com>
---
 drivers/tty/serial/mxs-auart.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/tty/serial/mxs-auart.c b/drivers/tty/serial/mxs-auart.c
index fe48a372d022..ec2c60dd0f52 100644
--- a/drivers/tty/serial/mxs-auart.c
+++ b/drivers/tty/serial/mxs-auart.c
@@ -872,10 +872,12 @@ static int mxs_auart_dma_prep_rx(struct mxs_auart_port *s)
 static void mxs_auart_dma_exit_channel(struct mxs_auart_port *s)
 {
 	if (s->tx_dma_chan) {
+		dmaengine_terminate_sync(s->tx_dma_chan);
 		dma_release_channel(s->tx_dma_chan);
 		s->tx_dma_chan = NULL;
 	}
 	if (s->rx_dma_chan) {
+		dmaengine_terminate_sync(s->rx_dma_chan);
 		dma_release_channel(s->rx_dma_chan);
 		s->rx_dma_chan = NULL;
 	}
-- 
2.54.0



^ permalink raw reply related

* [PATCHv3 5/6] serial: mxs-auart: clamp RX DMA count to buffer size
From: Rosen Penev @ 2026-06-11  3:38 UTC (permalink / raw)
  To: linux-serial
  Cc: Greg Kroah-Hartman, Jiri Slaby, Frank Li, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam,
	open list:TTY LAYER AND SERIAL DRIVERS,
	open list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE,
	moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE
In-Reply-To: <20260611033856.6476-1-rosenp@gmail.com>

In dma_rx_callback(), the RX count from the hardware status register
(AUART_STAT_RXCOUNT_MASK = 0xffff) is passed directly to
tty_insert_flip_string() without any bounds check. Since rx_dma_buf
is allocated with UART_XMIT_SIZE (4096 bytes), a hardware fault or
compromised peripheral reporting a count larger than 4096 would cause
an out-of-bounds read, potentially leaking kernel memory.

Clamp the count to UART_XMIT_SIZE before use.

Assisted-by: opencode:big-pickle
Signed-off-by: Rosen Penev <rosenp@gmail.com>
---
 drivers/tty/serial/mxs-auart.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/tty/serial/mxs-auart.c b/drivers/tty/serial/mxs-auart.c
index e2b656638ab3..fe48a372d022 100644
--- a/drivers/tty/serial/mxs-auart.c
+++ b/drivers/tty/serial/mxs-auart.c
@@ -823,7 +823,7 @@ static void dma_rx_callback(void *arg)
 	stat &= ~(AUART_STAT_OERR | AUART_STAT_BERR |
 			AUART_STAT_PERR | AUART_STAT_FERR);
 
-	count = stat & AUART_STAT_RXCOUNT_MASK;
+	count = min_t(u32, stat & AUART_STAT_RXCOUNT_MASK, UART_XMIT_SIZE);
 	tty_insert_flip_string(port, s->rx_dma_buf, count);
 
 	mxs_write(stat, s, REG_STAT);
-- 
2.54.0



^ permalink raw reply related

* [PATCHv3 3/6] serial: mxs-auart: use devm resources for iomem and GPIO IRQs
From: Rosen Penev @ 2026-06-11  3:38 UTC (permalink / raw)
  To: linux-serial
  Cc: Greg Kroah-Hartman, Jiri Slaby, Frank Li, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam,
	open list:TTY LAYER AND SERIAL DRIVERS,
	open list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE,
	moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE
In-Reply-To: <20260611033856.6476-1-rosenp@gmail.com>

Replace platform_get_resource + ioremap with
devm_platform_get_and_ioremap_resource and convert GPIO IRQ
request_irq/free_irq to devm_request_irq. This eliminates the
mxs_auart_free_gpio_irq function and its call sites, and the
out_iounmap error label. Simplify the remove function accordingly.

Assisted-by: opencode:big-pickle
Signed-off-by: Rosen Penev <rosenp@gmail.com>
---
 drivers/tty/serial/mxs-auart.c | 53 +++++++---------------------------
 1 file changed, 11 insertions(+), 42 deletions(-)

diff --git a/drivers/tty/serial/mxs-auart.c b/drivers/tty/serial/mxs-auart.c
index aa59a48bfad7..4499e3206e85 100644
--- a/drivers/tty/serial/mxs-auart.c
+++ b/drivers/tty/serial/mxs-auart.c
@@ -1517,15 +1517,6 @@ static int mxs_auart_init_gpios(struct mxs_auart_port *s, struct device *dev)
 	return 0;
 }
 
-static void mxs_auart_free_gpio_irq(struct mxs_auart_port *s)
-{
-	enum mctrl_gpio_idx i;
-
-	for (i = 0; i < UART_GPIO_MAX; i++)
-		if (s->gpio_irq[i] >= 0)
-			free_irq(s->gpio_irq[i], s);
-}
-
 static int mxs_auart_request_gpio_irq(struct mxs_auart_port *s)
 {
 	int *irq = s->gpio_irq;
@@ -1537,21 +1528,13 @@ static int mxs_auart_request_gpio_irq(struct mxs_auart_port *s)
 			continue;
 
 		irq_set_status_flags(irq[i], IRQ_NOAUTOEN);
-		err = request_irq(irq[i], mxs_auart_irq_handle,
-				IRQ_TYPE_EDGE_BOTH, dev_name(s->dev), s);
+		err = devm_request_irq(s->dev, irq[i], mxs_auart_irq_handle,
+				       IRQ_TYPE_EDGE_BOTH, dev_name(s->dev), s);
 		if (err)
 			dev_err(s->dev, "%s - Can't get %d irq\n",
 				__func__, irq[i]);
 	}
 
-	/*
-	 * If something went wrong, rollback.
-	 * Be careful: i may be unsigned.
-	 */
-	while (err && (i-- > 0))
-		if (irq[i] >= 0)
-			free_irq(irq[i], s);
-
 	return err;
 }
 
@@ -1596,18 +1579,12 @@ static int mxs_auart_probe(struct platform_device *pdev)
 	if (ret)
 		return ret;
 
-	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!r) {
-		ret = -ENXIO;
+	s->port.membase = devm_platform_get_and_ioremap_resource(pdev, 0, &r);
+	if (IS_ERR(s->port.membase)) {
+		ret = PTR_ERR(s->port.membase);
 		goto out_disable_clk;
 	}
-
 	s->port.mapbase = r->start;
-	s->port.membase = ioremap(r->start, resource_size(r));
-	if (!s->port.membase) {
-		ret = -ENOMEM;
-		goto out_disable_clk;
-	}
 	s->port.ops = &mxs_auart_ops;
 	s->port.iotype = UPIO_MEM;
 	s->port.fifosize = MXS_AUART_FIFO_SIZE;
@@ -1622,21 +1599,21 @@ static int mxs_auart_probe(struct platform_device *pdev)
 	irq = platform_get_irq(pdev, 0);
 	if (irq < 0) {
 		ret = irq;
-		goto out_iounmap;
+		goto out_disable_clk;
 	}
 
 	s->port.irq = irq;
 	ret = devm_request_irq(&pdev->dev, irq, mxs_auart_irq_handle, 0,
 			       dev_name(&pdev->dev), s);
 	if (ret)
-		goto out_iounmap;
+		goto out_disable_clk;
 
 	platform_set_drvdata(pdev, s);
 
 	ret = mxs_auart_init_gpios(s, &pdev->dev);
 	if (ret) {
 		dev_err(&pdev->dev, "Failed to initialize GPIOs.\n");
-		goto out_iounmap;
+		goto out_disable_clk;
 	}
 
 	/*
@@ -1644,7 +1621,7 @@ static int mxs_auart_probe(struct platform_device *pdev)
 	 */
 	ret = mxs_auart_request_gpio_irq(s);
 	if (ret)
-		goto out_iounmap;
+		goto out_disable_clk;
 
 	auart_port[s->port.line] = s;
 
@@ -1667,11 +1644,7 @@ static int mxs_auart_probe(struct platform_device *pdev)
 	return 0;
 
 out_free_qpio_irq:
-	mxs_auart_free_gpio_irq(s);
-	auart_port[pdev->id] = NULL;
-
-out_iounmap:
-	iounmap(s->port.membase);
+	auart_port[s->port.line] = NULL;
 
 out_disable_clk:
 	clk_disable_unprepare(s->clk);
@@ -1683,11 +1656,7 @@ static void mxs_auart_remove(struct platform_device *pdev)
 	struct mxs_auart_port *s = platform_get_drvdata(pdev);
 
 	uart_remove_one_port(&auart_driver, &s->port);
-	auart_port[pdev->id] = NULL;
-	mxs_auart_free_gpio_irq(s);
-	iounmap(s->port.membase);
-	if (is_asm9260_auart(s))
-		clk_disable_unprepare(s->clk);
+	auart_port[s->port.line] = NULL;
 }
 
 static struct platform_driver mxs_auart_driver = {
-- 
2.54.0



^ permalink raw reply related

* [PATCHv3 1/6] serial: mxs-auart: fix cast type for of_device_get_match_data
From: Rosen Penev @ 2026-06-11  3:38 UTC (permalink / raw)
  To: linux-serial
  Cc: Greg Kroah-Hartman, Jiri Slaby, Frank Li, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam,
	open list:TTY LAYER AND SERIAL DRIVERS,
	open list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE,
	moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE
In-Reply-To: <20260611033856.6476-1-rosenp@gmail.com>

of_device_get_match_data returns const void*. Cast to unsigned long to
avoid implicit integer truncation warnings. All the data parameters are
correct anyway.

Assisted-by: opencode:big-pickle
Signed-off-by: Rosen Penev <rosenp@gmail.com>
---
 drivers/tty/serial/mxs-auart.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/tty/serial/mxs-auart.c b/drivers/tty/serial/mxs-auart.c
index 697318dbb146..de97c0f74e7d 100644
--- a/drivers/tty/serial/mxs-auart.c
+++ b/drivers/tty/serial/mxs-auart.c
@@ -1598,7 +1598,7 @@ static int mxs_auart_probe(struct platform_device *pdev)
 		return -EINVAL;
 	}
 
-	s->devtype = (enum mxs_auart_type)of_device_get_match_data(&pdev->dev);
+	s->devtype = (unsigned long)of_device_get_match_data(&pdev->dev);
 
 	ret = mxs_get_clks(s, pdev);
 	if (ret)
-- 
2.54.0



^ permalink raw reply related

* [PATCHv3 2/6] serial: mxs-auart: rework clock handling in mxs_get_clks and probe
From: Rosen Penev @ 2026-06-11  3:38 UTC (permalink / raw)
  To: linux-serial
  Cc: Greg Kroah-Hartman, Jiri Slaby, Frank Li, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam,
	open list:TTY LAYER AND SERIAL DRIVERS,
	open list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE,
	moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE
In-Reply-To: <20260611033856.6476-1-rosenp@gmail.com>

Use devm_clk_get_enabled for the AHB clock so its enable/disable
lifetime is managed by the driver model. Move the mod clock
(clk) prepare_enable out of mxs_get_clks and into probe so that
clk_set_rate is called while the clock is still disabled, avoiding
CLK_SET_RATE_GATE failures. Clean up the error labels accordingly.

Assisted-by: opencode:big-pickle
Signed-off-by: Rosen Penev <rosenp@gmail.com>
---
 drivers/tty/serial/mxs-auart.c | 47 ++++++++++++----------------------
 1 file changed, 17 insertions(+), 30 deletions(-)

diff --git a/drivers/tty/serial/mxs-auart.c b/drivers/tty/serial/mxs-auart.c
index de97c0f74e7d..aa59a48bfad7 100644
--- a/drivers/tty/serial/mxs-auart.c
+++ b/drivers/tty/serial/mxs-auart.c
@@ -1470,34 +1470,22 @@ static int mxs_get_clks(struct mxs_auart_port *s,
 		return PTR_ERR(s->clk);
 	}
 
-	s->clk_ahb = devm_clk_get(s->dev, "ahb");
+	s->clk_ahb = devm_clk_get_enabled(s->dev, "ahb");
 	if (IS_ERR(s->clk_ahb)) {
 		dev_err(s->dev, "Failed to get \"ahb\" clk\n");
 		return PTR_ERR(s->clk_ahb);
 	}
 
-	err = clk_prepare_enable(s->clk_ahb);
-	if (err) {
-		dev_err(s->dev, "Failed to enable ahb_clk!\n");
-		return err;
-	}
-
+	/*
+	 * Set mod clock rate while it is still disabled so
+	 * CLK_SET_RATE_GATE does not cause clk_set_rate to fail.
+	 * The mod clock will be enabled in mxs_auart_startup()
+	 * and in probe after mxs_get_clks returns.
+	 */
 	err = clk_set_rate(s->clk, clk_get_rate(s->clk_ahb));
-	if (err) {
+	if (err)
 		dev_err(s->dev, "Failed to set rate!\n");
-		goto disable_clk_ahb;
-	}
 
-	err = clk_prepare_enable(s->clk);
-	if (err) {
-		dev_err(s->dev, "Failed to enable clk!\n");
-		goto disable_clk_ahb;
-	}
-
-	return 0;
-
-disable_clk_ahb:
-	clk_disable_unprepare(s->clk_ahb);
 	return err;
 }
 
@@ -1604,17 +1592,21 @@ static int mxs_auart_probe(struct platform_device *pdev)
 	if (ret)
 		return ret;
 
+	ret = clk_prepare_enable(s->clk);
+	if (ret)
+		return ret;
+
 	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!r) {
 		ret = -ENXIO;
-		goto out_disable_clks;
+		goto out_disable_clk;
 	}
 
 	s->port.mapbase = r->start;
 	s->port.membase = ioremap(r->start, resource_size(r));
 	if (!s->port.membase) {
 		ret = -ENOMEM;
-		goto out_disable_clks;
+		goto out_disable_clk;
 	}
 	s->port.ops = &mxs_auart_ops;
 	s->port.iotype = UPIO_MEM;
@@ -1681,11 +1673,8 @@ static int mxs_auart_probe(struct platform_device *pdev)
 out_iounmap:
 	iounmap(s->port.membase);
 
-out_disable_clks:
-	if (is_asm9260_auart(s)) {
-		clk_disable_unprepare(s->clk);
-		clk_disable_unprepare(s->clk_ahb);
-	}
+out_disable_clk:
+	clk_disable_unprepare(s->clk);
 	return ret;
 }
 
@@ -1697,10 +1686,8 @@ static void mxs_auart_remove(struct platform_device *pdev)
 	auart_port[pdev->id] = NULL;
 	mxs_auart_free_gpio_irq(s);
 	iounmap(s->port.membase);
-	if (is_asm9260_auart(s)) {
+	if (is_asm9260_auart(s))
 		clk_disable_unprepare(s->clk);
-		clk_disable_unprepare(s->clk_ahb);
-	}
 }
 
 static struct platform_driver mxs_auart_driver = {
-- 
2.54.0



^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox