* Re: [PATCH v4 11/14] dt-bindings: media: mediatek: vcodec: add decoder dt-bindings for mt8196
From: Krzysztof Kozlowski @ 2026-03-28 12:22 UTC (permalink / raw)
To: Yunfei Dong
Cc: Nícolas F . R . A . Prado, Sebastian Fricke,
Nicolas Dufresne, Hans Verkuil, AngeloGioacchino Del Regno,
Benjamin Gaignard, Nathan Hebert, Daniel Almeida, Hsin-Yi Wang,
Fritz Koenig, Daniel Vetter, Steve Cho, linux-media, devicetree,
linux-kernel, linux-arm-kernel, linux-mediatek,
Project_Global_Chrome_Upstream_Group
In-Reply-To: <20260328051630.7937-12-yunfei.dong@mediatek.com>
On Sat, Mar 28, 2026 at 01:16:21PM +0800, Yunfei Dong wrote:
> Add decoder document in dt-bindings yaml file for mt8196 platform.
>
> Signed-off-by: Yunfei Dong <yunfei.dong@mediatek.com>
> Acked-by: Nicolas Dufresne <nicolas.dufresne@collabora.com>
> ---
> .../bindings/media/mediatek,vcodec-subdev-decoder.yaml | 1 +
> 1 file changed, 1 insertion(+)
Still incomplete constraints. If the binding defines flexibly/variable
lists, each device MUST have them constrained.
Or explained WHY NOT in the commit msg. You have entire commit msg to
say something useful explaining unexpected changes, instead of repeating
the subject.
Also, reversed subject prefix:
Please use subject prefixes matching the subsystem. You can get them for
example with 'git log --oneline -- DIRECTORY_OR_FILE' on the directory
your patch is touching. For bindings, the preferred subjects are
explained here:
https://www.kernel.org/doc/html/latest/devicetree/bindings/submitting-patches.html#i-for-patch-submitters
Best regards,
Krzysztof
^ permalink raw reply
* [GIT PULL 3/3] Renesas DTS updates for v7.1 (take two)
From: Geert Uytterhoeven @ 2026-03-28 12:11 UTC (permalink / raw)
To: soc, soc
Cc: Magnus Damm, linux-arm-kernel, linux-renesas-soc,
Geert Uytterhoeven
In-Reply-To: <cover.1774606536.git.geert+renesas@glider.be>
The following changes since commit 0928a28daf017504e14920f4131bb99e3bc39dba:
ARM: dts: renesas: armadillo800eva: Add wakeup-source to st1232 (2026-03-13 11:00:48 +0100)
are available in the Git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/geert/renesas-devel.git tags/renesas-dts-for-v7.1-tag2
for you to fetch changes up to be3810a2ebc0c81303a15392097bac9ee0cd6297:
ARM: dts: renesas: Drop KSZ8041 PHY C22 compatible strings (2026-03-26 20:00:35 +0100)
----------------------------------------------------------------
Renesas DTS updates for v7.1 (take two)
- Add DT overlay support for the MayQueen PixPaper display on the
Yuridenki-Shokai Kakip board,
- Add Ethernet PHY interrupt support for the RZ/T2H and RZ/N2H EVK
boards,
- Add SPI and PCIe support for the RZ/G3E SoC and the RZ/G3E SMARC EVK
board,
- Add DT overlay support for the WaveShare 13.3" 1920x1080 DSI
Capacitive Touch Display and the Olimex MIPI-HDMI adapter on the
Retronix Sparrow Hawk board,
- Drop several superfluous C22 Ethernet PHY compatible strings,
- Remove WDT nodes meant for other CPU cores on the RZ/V2N SoC,
- Remove unavailable LVDS panel support for the Beacon ReneSoM base
board,
- Add initial support for the RZ/G3L (R9A08G046) SoC, and the RZ/G3L
SMARC SoM and EVK boards,
- Add Versa3 clock generator support for the RZ/V2H EVK development
board,
- Miscellaneous fixes and improvements.
----------------------------------------------------------------
Adam Ford (1):
arm64: dts: renesas: beacon-renesom: Remove LVDS Panel
Biju Das (5):
dt-bindings: clock: renesas,rzg2l-cpg: Document RZ/G3L SoC
arm64: dts: renesas: Add initial DTSI for RZ/G3L SoC
arm64: dts: renesas: Add initial support for RZ/G3L SMARC SoM
arm64: dts: renesas: renesas-smarc2: Move usb3 nodes to board DTS
arm64: dts: renesas: Add initial device tree for RZ/G3L SMARC EVK board
Fabrizio Castro (1):
arm64: dts: renesas: r9a09g056: Remove wdt{0,2,3} nodes
Geert Uytterhoeven (2):
arm64: dts: renesas: rzt2h-rzn2h-evk: Fix GMAC pins sort order
Merge tag 'renesas-r9a08g046-dt-binding-defs-tag1' into renesas-dts-for-v7.1
Herve Codina (Schneider Electric) (1):
ARM: dts: r9a06g032: Add #address-cells to the GIC node
John Madieu (3):
arm64: dts: renesas: r9a09g047: Add PCIe node
arm64: dts: renesas: r9a09g047e57-smarc-som: Add PCIe reference clock
arm64: dts: renesas: r9a09g047e57-smarc: Enable PCIe
Lad Prabhakar (4):
arm64: dts: renesas: r9a09g077m44-rzt2h-evk: Clarify SD0 power jumpers
arm64: dts: renesas: r9a09g087m44-rzn2h-evk: Clarify SD0 power jumper setup
arm64: dts: renesas: r9a09g087m44-rzn2h-evk: Add PHY interrupt support
arm64: dts: renesas: r9a09g077m44-rzt2h-evk: Add PHY interrupt support
Marek Vasut (8):
arm64: dts: renesas: sparrow-hawk: Add overlay for WaveShare Display 13.3"
arm64: dts: renesas: Drop RTL8211E PHY C22 compatible strings
arm64: dts: renesas: Drop RTL8211F PHY C22 compatible strings
arm64: dts: renesas: Drop KSZ9131 PHY C22 compatible strings
arm64: dts: renesas: Fix KSZ9131 PHY bogus txdv-skew-psec properties
ARM: dts: renesas: r8a7742-iwg21d-q7-dbcm-ca: Drop KSZ8081 PHY C22 compatible string
ARM: dts: renesas: rza2mevb: Drop RTL8201F PHY C22 compatible string
ARM: dts: renesas: Drop KSZ8041 PHY C22 compatible strings
Ovidiu Panait (1):
arm64: dts: renesas: r9a09g057h44-rzv2h-evk: Add versa3 clock generator node
Scott Murray (1):
arm64: dts: renesas: sparrow-hawk: Add overlay for Olimex MIPI-HDMI adapter
Tommaso Merciai (2):
arm64: dts: renesas: r9a09g047: Add RSPI nodes
arm64: dts: renesas: r9a09g047e57-smarc: Enable RSPI0
Wig Cheng (1):
arm64: dts: renesas: r9a09g057h48-kakip: Add pixpaper display overlay
.../bindings/clock/renesas,rzg2l-cpg.yaml | 40 ++-
arch/arm/boot/dts/renesas/r7s9210-rza2mevb.dts | 3 +-
.../boot/dts/renesas/r8a7742-iwg21d-q7-dbcm-ca.dts | 3 +-
arch/arm/boot/dts/renesas/r8a7743-sk-rzg1m.dts | 3 +-
arch/arm/boot/dts/renesas/r8a7745-sk-rzg1e.dts | 3 +-
arch/arm/boot/dts/renesas/r8a7790-lager.dts | 3 +-
arch/arm/boot/dts/renesas/r8a7790-stout.dts | 3 +-
arch/arm/boot/dts/renesas/r8a7791-koelsch.dts | 3 +-
arch/arm/boot/dts/renesas/r8a7791-porter.dts | 3 +-
arch/arm/boot/dts/renesas/r8a7793-gose.dts | 3 +-
arch/arm/boot/dts/renesas/r8a7794-alt.dts | 3 +-
arch/arm/boot/dts/renesas/r8a7794-silk.dts | 3 +-
arch/arm/boot/dts/renesas/r9a06g032.dtsi | 1 +
arch/arm64/boot/dts/renesas/Makefile | 11 +
.../boot/dts/renesas/beacon-renesom-baseboard.dtsi | 74 -----
.../arm64/boot/dts/renesas/beacon-renesom-som.dtsi | 3 +-
arch/arm64/boot/dts/renesas/cat875.dtsi | 3 +-
arch/arm64/boot/dts/renesas/hihope-rzg2-ex.dtsi | 3 +-
.../r8a779g3-sparrow-hawk-olimex-dsi-hdmi.dtso | 92 ++++++
.../r8a779g3-sparrow-hawk-ws-display-13in.dtso | 88 ++++++
arch/arm64/boot/dts/renesas/r9a08g046.dtsi | 212 +++++++++++++
arch/arm64/boot/dts/renesas/r9a08g046l48-smarc.dts | 37 +++
arch/arm64/boot/dts/renesas/r9a08g046l48.dtsi | 13 +
arch/arm64/boot/dts/renesas/r9a09g011-v2mevk2.dts | 3 +-
arch/arm64/boot/dts/renesas/r9a09g047.dtsi | 153 +++++++++
arch/arm64/boot/dts/renesas/r9a09g047e57-smarc.dts | 38 +++
arch/arm64/boot/dts/renesas/r9a09g056.dtsi | 30 --
.../boot/dts/renesas/r9a09g056n48-rzv2n-evk.dts | 8 +-
.../boot/dts/renesas/r9a09g057h44-rzv2h-evk.dts | 33 +-
.../dts/renesas/r9a09g057h48-kakip-pixpaper.dtso | 39 +++
arch/arm64/boot/dts/renesas/r9a09g077.dtsi | 18 ++
.../boot/dts/renesas/r9a09g077m44-rzt2h-evk.dts | 71 +++--
arch/arm64/boot/dts/renesas/r9a09g087.dtsi | 18 ++
.../boot/dts/renesas/r9a09g087m44-rzn2h-evk.dts | 71 +++--
arch/arm64/boot/dts/renesas/renesas-smarc2.dtsi | 12 +-
arch/arm64/boot/dts/renesas/rzg2l-smarc-som.dtsi | 6 +-
arch/arm64/boot/dts/renesas/rzg2lc-smarc-som.dtsi | 3 +-
arch/arm64/boot/dts/renesas/rzg2ul-smarc-som.dtsi | 6 +-
arch/arm64/boot/dts/renesas/rzg3e-smarc-som.dtsi | 21 +-
arch/arm64/boot/dts/renesas/rzg3l-smarc-som.dtsi | 20 ++
include/dt-bindings/clock/renesas,r9a08g046-cpg.h | 342 +++++++++++++++++++++
41 files changed, 1267 insertions(+), 235 deletions(-)
create mode 100644 arch/arm64/boot/dts/renesas/r8a779g3-sparrow-hawk-olimex-dsi-hdmi.dtso
create mode 100644 arch/arm64/boot/dts/renesas/r8a779g3-sparrow-hawk-ws-display-13in.dtso
create mode 100644 arch/arm64/boot/dts/renesas/r9a08g046.dtsi
create mode 100644 arch/arm64/boot/dts/renesas/r9a08g046l48-smarc.dts
create mode 100644 arch/arm64/boot/dts/renesas/r9a08g046l48.dtsi
create mode 100644 arch/arm64/boot/dts/renesas/r9a09g057h48-kakip-pixpaper.dtso
create mode 100644 arch/arm64/boot/dts/renesas/rzg3l-smarc-som.dtsi
create mode 100644 include/dt-bindings/clock/renesas,r9a08g046-cpg.h
^ permalink raw reply
* [GIT PULL 2/3] Renesas driver updates for v7.1 (take two)
From: Geert Uytterhoeven @ 2026-03-28 12:11 UTC (permalink / raw)
To: soc, soc
Cc: Magnus Damm, linux-arm-kernel, linux-renesas-soc,
Geert Uytterhoeven
In-Reply-To: <cover.1774606536.git.geert+renesas@glider.be>
The following changes since commit b1de9823fdc67a8e9cd0dcf1f6f0e9780d425d4e:
soc: renesas: rz-sysc: Add SoC identification for RZ/G3L SoC (2026-03-06 13:40:12 +0100)
are available in the Git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/geert/renesas-devel.git tags/renesas-drivers-for-v7.1-tag2
for you to fetch changes up to abf3502033cfc2797126f054eb081857f8e7e939:
soc: renesas: r9a09g056-sys: Mark rzv2n_sys_init_data as __initconst (2026-03-16 11:04:18 +0100)
----------------------------------------------------------------
Renesas driver updates for v7.1 (take two)
- Mark remaining rz_sysc_init_data structures __initconst.
----------------------------------------------------------------
Lad Prabhakar (3):
soc: renesas: r9a09g057-sys: Mark rzv2h_sys_init_data as __initconst
soc: renesas: r9a09g047-sys: Mark rzg3e_sys_init_data as __initconst
soc: renesas: r9a09g056-sys: Mark rzv2n_sys_init_data as __initconst
drivers/soc/renesas/r9a09g047-sys.c | 2 +-
drivers/soc/renesas/r9a09g056-sys.c | 2 +-
drivers/soc/renesas/r9a09g057-sys.c | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
^ permalink raw reply
* [GIT PULL 1/3] Renesas ARM SoC updates for v7.1
From: Geert Uytterhoeven @ 2026-03-28 12:11 UTC (permalink / raw)
To: soc, soc
Cc: Magnus Damm, linux-arm-kernel, linux-renesas-soc,
Geert Uytterhoeven
In-Reply-To: <cover.1774606536.git.geert+renesas@glider.be>
The following changes since commit 6de23f81a5e08be8fbf5e8d7e9febc72a5b5f27f:
Linux 7.0-rc1 (2026-02-22 13:18:59 -0800)
are available in the Git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/geert/renesas-devel.git tags/renesas-arm-soc-for-v7.1-tag1
for you to fetch changes up to d784bbad7fcbfad42e0d12c8dae2eb9c17b327b4:
ARM: shmobile: rcar-gen2: Use of_phandle_args_equal() helper (2026-03-16 10:59:59 +0100)
----------------------------------------------------------------
Renesas ARM SoC updates for v7.1
- Use the of_phandle_args_equal() helper.
----------------------------------------------------------------
Geert Uytterhoeven (1):
ARM: shmobile: rcar-gen2: Use of_phandle_args_equal() helper
arch/arm/mach-shmobile/regulator-quirk-rcar-gen2.c | 16 ++++------------
1 file changed, 4 insertions(+), 12 deletions(-)
^ permalink raw reply
* [GIT PULL 0/3] Renesas SoC updates for v7.1 (take two)
From: Geert Uytterhoeven @ 2026-03-28 12:11 UTC (permalink / raw)
To: soc, soc
Cc: Magnus Damm, linux-arm-kernel, linux-renesas-soc,
Geert Uytterhoeven
Hi SoC folks,
This is my second pull request for the inclusion of Renesas SoC updates
for v7.1.
It consists of 3 parts:
[GIT PULL 1/3] Renesas ARM SoC updates for v7.1
- Use the of_phandle_args_equal() helper.
[GIT PULL 2/3] Renesas driver updates for v7.1 (take two)
- Mark remaining rz_sysc_init_data structures __initconst.
[GIT PULL 3/3] Renesas DTS updates for v7.1 (take two)
- Add DT overlay support for the MayQueen PixPaper display on the
Yuridenki-Shokai Kakip board,
- Add Ethernet PHY interrupt support for the RZ/T2H and RZ/N2H EVK
boards,
- Add SPI and PCIe support for the RZ/G3E SoC and the RZ/G3E SMARC EVK
board,
- Add DT overlay support for the WaveShare 13.3" 1920x1080 DSI
Capacitive Touch Display and the Olimex MIPI-HDMI adapter on the
Retronix Sparrow Hawk board,
- Drop several superfluous C22 Ethernet PHY compatible strings,
- Remove WDT nodes meant for other CPU cores on the RZ/V2N SoC,
- Remove unavailable LVDS panel support for the Beacon ReneSoM base
board,
- Add initial support for the RZ/G3L (R9A08G046) SoC, and the RZ/G3L
SMARC SoM and EVK boards,
- Add Versa3 clock generator support for the RZ/V2H EVK development
board,
- Miscellaneous fixes and improvements.
Note that "[GIT PULL 3/3]" includes DT binding definitions for the
RZ/G3L SoC, which are shared by clock driver and DT source files.
Thanks for pulling!
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
^ permalink raw reply
* [GIT PULL] Renesas SoC fixes for v7.0 (take two)
From: Geert Uytterhoeven @ 2026-03-28 12:10 UTC (permalink / raw)
To: soc, soc
Cc: Magnus Damm, linux-arm-kernel, linux-renesas-soc,
Geert Uytterhoeven
Hi SoC folks,
The following changes since commit 85c2601e2c2feb60980c7ca23de28c49472f61f1:
arm64: dts: renesas: r8a78000: Fix out-of-range SPI interrupt numbers (2026-03-06 13:15:21 +0100)
are available in the Git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/geert/renesas-devel.git tags/renesas-fixes-for-v7.0-tag2
for you to fetch changes up to ed8444006df9863ffa682e315352c44a49d9f4cb:
arm64: dts: renesas: sparrow-hawk: Reserve first 128 MiB of DRAM (2026-03-25 18:26:10 +0100)
----------------------------------------------------------------
Renesas fixes for v7.0 (take two)
- Fix TFA BL31 memory corruption on Sparrow Hawk.
Thanks for pulling!
----------------------------------------------------------------
Marek Vasut (1):
arm64: dts: renesas: sparrow-hawk: Reserve first 128 MiB of DRAM
arch/arm64/boot/dts/renesas/r8a779g3-sparrow-hawk.dts | 11 +++++++++++
1 file changed, 11 insertions(+)
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
^ permalink raw reply
* Re: [PATCH 02/12] bus: fsl-mc: use generic driver_override infrastructure
From: Christophe Leroy (CS GROUP) @ 2026-03-28 12:10 UTC (permalink / raw)
To: Ioana Ciornei, Danilo Krummrich
Cc: Russell King, Greg Kroah-Hartman, Rafael J. Wysocki, Nipun Gupta,
Nikhil Agarwal, K. Y. Srinivasan, Haiyang Zhang, Wei Liu,
Dexuan Cui, Long Li, Bjorn Helgaas, Armin Wolf, Bjorn Andersson,
Mathieu Poirier, Vineeth Vijayan, Peter Oberparleiter,
Heiko Carstens, Vasily Gorbik, Alexander Gordeev,
Christian Borntraeger, Sven Schnelle, Harald Freudenberger,
Holger Dengler, Mark Brown, Michael S. Tsirkin, Jason Wang,
Xuan Zhuo, Eugenio Pérez, Alex Williamson,
Juergen Gross, Stefano Stabellini, Oleksandr Tyshchenko,
linux-kernel, driver-core, linuxppc-dev, linux-hyperv, linux-pci,
platform-driver-x86, linux-arm-msm, linux-remoteproc, linux-s390,
linux-spi, virtualization, kvm, xen-devel, linux-arm-kernel,
Gui-Dong Han
In-Reply-To: <cvcetxkxjq2tz6n2vsofhyzove3qdi2e4r6rq6yxou3joejk2h@rmt5ygav7ssu>
Le 25/03/2026 à 13:01, Ioana Ciornei a écrit :
> On Tue, Mar 24, 2026 at 01:59:06AM +0100, Danilo Krummrich wrote:
>> When a driver is probed through __driver_attach(), the bus' match()
>> callback is called without the device lock held, thus accessing the
>> driver_override field without a lock, which can cause a UAF.
>>
>> Fix this by using the driver-core driver_override infrastructure taking
>> care of proper locking internally.
>>
>> Note that calling match() from __driver_attach() without the device lock
>> held is intentional. [1]
>>
>> Link: https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Flore.kernel.org%2Fdriver-core%2FDGRGTIRHA62X.3RY09D9SOK77P%40kernel.org%2F&data=05%7C02%7Cchristophe.leroy%40csgroup.eu%7C4b9262ddecdd4ce29f9808de8a66485e%7C8b87af7d86474dc78df45f69a2011bb5%7C0%7C0%7C639100369055903282%7CUnknown%7CTWFpbGZsb3d8eyJFbXB0eU1hcGkiOnRydWUsIlYiOiIwLjAuMDAwMCIsIlAiOiJXaW4zMiIsIkFOIjoiTWFpbCIsIldUIjoyfQ%3D%3D%7C0%7C%7C%7C&sdata=%2BRfjlUkq7oWV%2F0v2S2B%2BEuxCY%2FLRQv6qHiEWiupd6kc%3D&reserved=0 [1]
>> Reported-by: Gui-Dong Han <hanguidong02@gmail.com>
>> Closes: https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fbugzilla.kernel.org%2Fshow_bug.cgi%3Fid%3D220789&data=05%7C02%7Cchristophe.leroy%40csgroup.eu%7C4b9262ddecdd4ce29f9808de8a66485e%7C8b87af7d86474dc78df45f69a2011bb5%7C0%7C0%7C639100369055936232%7CUnknown%7CTWFpbGZsb3d8eyJFbXB0eU1hcGkiOnRydWUsIlYiOiIwLjAuMDAwMCIsIlAiOiJXaW4zMiIsIkFOIjoiTWFpbCIsIldUIjoyfQ%3D%3D%7C0%7C%7C%7C&sdata=XL1K1ICiygOZnlvDUbQFe192KnLsBQms0HFNGCuyz%2Fw%3D&reserved=0
>> Fixes: 1f86a00c1159 ("bus/fsl-mc: add support for 'driver_override' in the mc-bus")
>> Signed-off-by: Danilo Krummrich <dakr@kernel.org>
>
> Tested-by: Ioana Ciornei <ioana.ciornei@nxp.com>
> Signed-off-by: Ioana Ciornei <ioana.ciornei@nxp.com>
>
Applied, thanks
^ permalink raw reply
* Re: [PATCH v2] soc: fsl: qe: panic on ioremap() failure in qe_reset()
From: Christophe Leroy (CS GROUP) @ 2026-03-28 12:09 UTC (permalink / raw)
To: Wang Jun, Qiang Zhao, linuxppc-dev, linux-arm-kernel
Cc: linux-kernel, gszhai, 25125332, 25125283, 23120469, stable
In-Reply-To: <tencent_FED49CF5331CC0C7910618883332A08E2606@qq.com>
Le 27/03/2026 à 01:12, Wang Jun a écrit :
> [Vous ne recevez pas souvent de courriers de 1742789905@qq.com. Découvrez pourquoi ceci est important à https://aka.ms/LearnAboutSenderIdentification ]
>
> When ioremap() fails in qe_reset(), the global pointer qe_immr remains
> NULL, leading to a subsequent NULL pointer dereference when the pointer
> is accessed. Since this happens early in the boot process, a failure to
> map a few bytes of I/O memory indicates a fatal error from which the
> system cannot recover.
>
> Follow the same pattern as qe_sdma_init() and panic immediately when
> ioremap() fails. This avoids a silent NULL pointer dereference later
> and makes the error explicit.
>
> Fixes: 986585385131 ("[POWERPC] Add QUICC Engine (QE) infrastructure")
> Cc: stable@vger.kernel.org
> Signed-off-by: Wang Jun <1742789905@qq.com>
> ---
> drivers/soc/fsl/qe/qe.c | 6 +++++-
> 1 file changed, 5 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/soc/fsl/qe/qe.c b/drivers/soc/fsl/qe/qe.c
> index 70b6eddb867b..9f6223043ee3 100644
> --- a/drivers/soc/fsl/qe/qe.c
> +++ b/drivers/soc/fsl/qe/qe.c
> @@ -86,8 +86,12 @@ static phys_addr_t get_qe_base(void)
>
> void qe_reset(void)
> {
> - if (qe_immr == NULL)
> + if (qe_immr == NULL) {
> qe_immr = ioremap(get_qe_base(), QE_IMMAP_SIZE);
> + if (qe_immr == NULL) {
> + panic("QE:ioremap failed!");
> + }
> + }
>
> qe_snums_init();
>
Applied, thanks.
^ permalink raw reply
* Re: [PATCH v2] media: nxp: imx8-isi: fix memory leaks in probe error paths and remove
From: Greg KH @ 2026-03-28 11:37 UTC (permalink / raw)
To: David CARLIER
Cc: laurent.pinchart, mchehab, Frank.Li, s.hauer, kernel, festevam,
jacopo, aisheng.dong, guoniu.zhou, linux-media, imx,
linux-arm-kernel, linux-kernel, stable
In-Reply-To: <CA+XhMqw+pR3fLGbysq3FnfpH+b2GtmdhSjjgCKhTwfZFrF0_0w@mail.gmail.com>
On Sat, Mar 28, 2026 at 11:15:18AM +0000, David CARLIER wrote:
> On Sat, 28 Mar 2026 at 10:21, Greg KH <greg@kroah.com> wrote:
> >
> > On Sat, Mar 28, 2026 at 10:00:10AM +0000, David Carlier wrote:
> > > mxc_isi_probe() allocates isi->pipes with kzalloc_objs() but never
> > > frees it on any probe failure path or in mxc_isi_remove(), leaking the
> > > allocation on every failed probe and every normal unbind.
> > >
> > > Additionally, when mxc_isi_pipe_init() fails partway through the
> > > channel loop or when mxc_isi_v4l2_init() fails, the already initialized
> > > pipes are not cleaned up — their media entities and mutexes are leaked.
> > >
> > > Fix both by adding kfree(isi->pipes) to all probe error paths and to
> > > mxc_isi_remove(), and cleaning up already-initialized pipes in the
> > > err_xbar error path.
> > >
> > > Fixes: cf21f328fcaf ("media: nxp: Add i.MX8 ISI driver")
> > > Signed-off-by: David Carlier <devnexen@gmail.com>
> > > ---
> >
> > <formletter>
> >
> > This is not the correct way to submit patches for inclusion in the
> > stable kernel tree. Please read:
> > https://www.kernel.org/doc/html/latest/process/stable-kernel-rules.html
> > for how to do this properly.
>
> Apologies for the confusion — I wasn't submitting this for stable
> inclusion directly. The Cc was added based on CI bot feedback since
> the Fixes target is in the
> stable tree, but I understand the correct flow is to let it go
> through the maintainer tree first and let the Fixes tag handle stable
> backporting.
If you read the above, "Fixes:" does not guarantee backporting at all,
so NEVER rely on that if you know you want something applied to a stable
kernel tree.
thanks,
greg k-h
^ permalink raw reply
* [PATCH v2] media: aspeed: fix missing of_reserved_mem_device_release() on probe failure
From: David Carlier @ 2026-03-28 11:23 UTC (permalink / raw)
To: eajames, mchehab
Cc: joel, andrew, hverkuil, linux-media, openbmc, linux-arm-kernel,
linux-aspeed, linux-kernel, David Carlier
In-Reply-To: <20260327220827.266556-1-devnexen@gmail.com>
aspeed_video_init() calls of_reserved_mem_device_init() to associate
reserved memory regions with the device. When aspeed_video_setup_video()
subsequently fails in aspeed_video_probe(), the error path frees the
JPEG buffer and unprepares the clocks but does not release the reserved
memory association, leaking the rmem_assigned_device entry on the global
list.
The normal remove path already calls of_reserved_mem_device_release()
correctly; only the probe error path was missing it.
Add the missing of_reserved_mem_device_release() call to the
aspeed_video_setup_video() failure cleanup.
Fixes: d2b4387f3bdf ("media: platform: Add Aspeed Video Engine driver")
Signed-off-by: David Carlier <devnexen@gmail.com>
---
drivers/media/platform/aspeed/aspeed-video.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/media/platform/aspeed/aspeed-video.c b/drivers/media/platform/aspeed/aspeed-video.c
index 41cb96f60110..a292275f6b7b 100644
--- a/drivers/media/platform/aspeed/aspeed-video.c
+++ b/drivers/media/platform/aspeed/aspeed-video.c
@@ -2343,6 +2343,7 @@ static int aspeed_video_probe(struct platform_device *pdev)
rc = aspeed_video_setup_video(video);
if (rc) {
aspeed_video_free_buf(video, &video->jpeg);
+ of_reserved_mem_device_release(&pdev->dev);
clk_unprepare(video->vclk);
clk_unprepare(video->eclk);
return rc;
--
2.53.0
^ permalink raw reply related
* Re: [PATCH v2] media: nxp: imx8-isi: fix memory leaks in probe error paths and remove
From: David CARLIER @ 2026-03-28 11:15 UTC (permalink / raw)
To: Greg KH
Cc: laurent.pinchart, mchehab, Frank.Li, s.hauer, kernel, festevam,
jacopo, aisheng.dong, guoniu.zhou, linux-media, imx,
linux-arm-kernel, linux-kernel, stable
In-Reply-To: <2026032803-tree-stubbed-1e9b@gregkh>
On Sat, 28 Mar 2026 at 10:21, Greg KH <greg@kroah.com> wrote:
>
> On Sat, Mar 28, 2026 at 10:00:10AM +0000, David Carlier wrote:
> > mxc_isi_probe() allocates isi->pipes with kzalloc_objs() but never
> > frees it on any probe failure path or in mxc_isi_remove(), leaking the
> > allocation on every failed probe and every normal unbind.
> >
> > Additionally, when mxc_isi_pipe_init() fails partway through the
> > channel loop or when mxc_isi_v4l2_init() fails, the already initialized
> > pipes are not cleaned up — their media entities and mutexes are leaked.
> >
> > Fix both by adding kfree(isi->pipes) to all probe error paths and to
> > mxc_isi_remove(), and cleaning up already-initialized pipes in the
> > err_xbar error path.
> >
> > Fixes: cf21f328fcaf ("media: nxp: Add i.MX8 ISI driver")
> > Signed-off-by: David Carlier <devnexen@gmail.com>
> > ---
>
> <formletter>
>
> This is not the correct way to submit patches for inclusion in the
> stable kernel tree. Please read:
> https://www.kernel.org/doc/html/latest/process/stable-kernel-rules.html
> for how to do this properly.
Apologies for the confusion — I wasn't submitting this for stable
inclusion directly. The Cc was added based on CI bot feedback since
the Fixes target is in the
stable tree, but I understand the correct flow is to let it go
through the maintainer tree first and let the Fixes tag handle stable
backporting.
Cheers.
>
> </formletter>
^ permalink raw reply
* Re: [PATCH] KVM: arm64: ptdump: Initialize parser_state before pgtable walk
From: Marc Zyngier @ 2026-03-28 11:13 UTC (permalink / raw)
To: kvmarm, linux-arm-kernel, Zenghui Yu; +Cc: oupton, joey.gouly, suzuki.poulose
In-Reply-To: <20260328053155.12219-1-zenghui.yu@linux.dev>
On Sat, 28 Mar 2026 13:31:55 +0800, Zenghui Yu wrote:
> If we go through the "need a bigger buffer" path in seq_read_iter(), which
> is likely to happen as we're dumping page tables, we will pass the
> populated-by-last-run st::parser_state to
> kvm_pgtable_walk()/kvm_ptdump_visitor(). As a result, the output of
> stage2_page_tables on my box looks like
>
> 0x0000000240000000-0x0000000000000000 17179869175G 1
> 0x0000000000000000-0x0000000000200000 2M 2 R px ux AF BLK
> 0x0000000000200000-0x0000000040000000 1022M 2
> 0x0000000040000000-0x0000000040200000 2M 2 R W PXNUXN AF BLK
> [...]
>
> [...]
Applied to next, thanks!
[1/1] KVM: arm64: ptdump: Initialize parser_state before pgtable walk
commit: 570428601ba506e76c265a65626524ef3c5cbc04
Cheers,
M.
--
Without deviation from the norm, progress is not possible.
^ permalink raw reply
* Re: [PATCH v2] media: nxp: imx8-isi: fix memory leaks in probe error paths and remove
From: Greg KH @ 2026-03-28 10:21 UTC (permalink / raw)
To: David Carlier
Cc: laurent.pinchart, mchehab, Frank.Li, s.hauer, kernel, festevam,
jacopo, aisheng.dong, guoniu.zhou, linux-media, imx,
linux-arm-kernel, linux-kernel, stable
In-Reply-To: <20260328100010.41236-1-devnexen@gmail.com>
On Sat, Mar 28, 2026 at 10:00:10AM +0000, David Carlier wrote:
> mxc_isi_probe() allocates isi->pipes with kzalloc_objs() but never
> frees it on any probe failure path or in mxc_isi_remove(), leaking the
> allocation on every failed probe and every normal unbind.
>
> Additionally, when mxc_isi_pipe_init() fails partway through the
> channel loop or when mxc_isi_v4l2_init() fails, the already initialized
> pipes are not cleaned up — their media entities and mutexes are leaked.
>
> Fix both by adding kfree(isi->pipes) to all probe error paths and to
> mxc_isi_remove(), and cleaning up already-initialized pipes in the
> err_xbar error path.
>
> Fixes: cf21f328fcaf ("media: nxp: Add i.MX8 ISI driver")
> Signed-off-by: David Carlier <devnexen@gmail.com>
> ---
<formletter>
This is not the correct way to submit patches for inclusion in the
stable kernel tree. Please read:
https://www.kernel.org/doc/html/latest/process/stable-kernel-rules.html
for how to do this properly.
</formletter>
^ permalink raw reply
* [RFC PATCH v2 0/5] Add debugfs support for ARM SMMUv3
From: Qinxin Xia @ 2026-03-28 10:17 UTC (permalink / raw)
To: robin.murphy, nicolinc, will, jpb
Cc: linux-arm-kernel, iommu, xiaqinxin, wangzhou1, prime.zeng,
fanghao11, jonathan.cameron, wuyifan50, linuxarm
Add a comprehensive debugfs framework to the ARM SMMUv3 driver,
providing visibility into internal hardware state for debugging
and performance analysis. The debugfs entries are organized under
/sys/kernel/debug/iommu/arm_smmu_v3/, with per-SMMU instance directories
and per-device stream table entries.
Each SMMU instance provides:
- capabilities – static SMMU features and queue sizes.
- registers – SMMU key registers.
- stream_table/ – a directory per device with subdirectories per Stream ID.
Each Stream ID subdirectory contains:
- ste – the Stream Table Entry in decoded and raw format.
- cd – all valid Context Descriptors (Stage 1 translation tables) associated with the device.
- a symlink named with the device’s BDF/name pointing to its sysfs directory for easy navigation.
/sys/kernel/debug/iommu/arm_smmu_v3/smmu0/stream_table/
└── <sid>/
├─── ste
├─── cd
└─── <dev_name>
Changes since V1:
Address the comments from Nicolin:
1.Fixed the incorrect comments and replaced 'kzalloc' with 'kzalloc_obj'
2.'stream_table_create/stream_table_remove' is called in probe_device/release_device
3.Reused some functions in the driver
Address the comments from Robin:
1.Remove unnecessary CR0*EN extra strings
2.Remove the limit on ssid
Address the comments from Robin and Nicolin:
1.The directory structure has been changed
2.Added lock protection for the ste_show and cd_show
Others:
1.'arm_smmu_debugfs_remove' is added to remove the corresponding debugfs when SMMU device is removed
2.'arm_smmu_debugfs_remove_stream_table' is added to remove the corresponding stream_dir when device is removed
3.Use scoped_guard for locks that include return
4.Added 'open' and 'release' operations to prevent the device from being released during dump
5.Merged 'stream_table_create' and 'ste_show' into one patch
6.Some other clean code
- Link: https://lore.kernel.org/all/20260313104351.3502293-1-xiaqinxin@huawei.com/
Qinxin Xia (5):
iommu/arm-smmu-v3: Add basic debugfs framework
iommu/arm-smmu-v3: Add register display to debugfs
iommu/arm-smmu-v3: Add Stream Table Entry display to debugfs
iommu/arm-smmu-v3: Add device symlink in stream table debugfs
iommu/arm-smmu-v3: Add Context Descriptor display to debugfs
drivers/iommu/Kconfig | 11 +
drivers/iommu/arm/arm-smmu-v3/Makefile | 1 +
.../arm/arm-smmu-v3/arm-smmu-v3-debugfs.c | 571 ++++++++++++++++++
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 33 +-
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h | 32 +
5 files changed, 646 insertions(+), 2 deletions(-)
create mode 100644 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-debugfs.c
--
2.33.0
^ permalink raw reply
* [RFC PATCH v2 2/5] iommu/arm-smmu-v3: Add register display to debugfs
From: Qinxin Xia @ 2026-03-28 10:17 UTC (permalink / raw)
To: robin.murphy, nicolinc, will, jpb
Cc: linux-arm-kernel, iommu, xiaqinxin, wangzhou1, prime.zeng,
fanghao11, jonathan.cameron, wuyifan50, linuxarm
In-Reply-To: <20260328101706.3448655-1-xiaqinxin@huawei.com>
Add register display functionality to debugfs.This allows reading
and displaying key SMMU register values including control registers
and queue pointers.
The registers file shows:
- CR0, CR1, CR2 control registers
- Command and Event queue pointers
Signed-off-by: Qinxin Xia <xiaqinxin@huawei.com>
---
.../arm/arm-smmu-v3/arm-smmu-v3-debugfs.c | 78 ++++++++++++++++++-
1 file changed, 77 insertions(+), 1 deletion(-)
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-debugfs.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-debugfs.c
index c764b28e5cfb..cfd296aebc9f 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-debugfs.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-debugfs.c
@@ -5,13 +5,18 @@
* Directory Structure:
* /sys/kernel/debug/iommu/arm_smmu_v3/
* └── smmu<ioaddr>/
- * └── capabilities # SMMU feature capabilities and configuration
+ * ├── capabilities # SMMU feature capabilities and configuration
+ * └── registers # SMMU Key registers
*
* The capabilities file provides detailed information about:
* - translation stage support (Stage1/Stage2)
* - System coherency, ATS, and PRI feature availability
* - Stream table size and command/event queue depths
*
+ * The registers display provides crucial visibility into:
+ * - CR0, CR1, CR2 control registers
+ * - Command and Event queue pointers
+ *
* Copyright (C) 2026 HiSilicon Limited.
* Author: Qinxin Xia <xiaqinxin@huawei.com>
*/
@@ -89,6 +94,74 @@ static const struct file_operations smmu_debugfs_capabilities_fops = {
.release = smmu_debugfs_capabilities_release,
};
+/**
+ * smmu_debugfs_registers_show() - Display SMMU register values
+ * @seq: seq_file to write to
+ *
+ * Errors are reported via seq_puts, the function always returns 0
+ */
+static int smmu_debugfs_registers_show(struct seq_file *seq, void *unused)
+{
+ struct arm_smmu_device *smmu = seq->private;
+ void __iomem *base;
+
+ if (!smmu || !smmu->base) {
+ seq_puts(seq, "SMMU not available\n");
+ return 0;
+ }
+
+ base = smmu->base;
+
+ seq_puts(seq, "SMMUv3 Key Registers:\n");
+
+ /* 32-bit control registers */
+ seq_printf(seq, "CR0: 0x%08x\n", readl_relaxed(base + ARM_SMMU_CR0));
+ seq_printf(seq, "CR1: 0x%08x\n", readl_relaxed(base + ARM_SMMU_CR1));
+ seq_printf(seq, "CR2: 0x%08x\n", readl_relaxed(base + ARM_SMMU_CR2));
+
+ /* 32-bit queue pointer registers */
+ seq_printf(seq, "CMDQ_PROD: 0x%08x\n",
+ readl_relaxed(base + ARM_SMMU_CMDQ_PROD));
+ seq_printf(seq, "CMDQ_CONS: 0x%08x\n",
+ readl_relaxed(base + ARM_SMMU_CMDQ_CONS));
+ seq_printf(seq, "EVTQ_PROD: 0x%08x\n",
+ readl_relaxed(base + ARM_SMMU_EVTQ_PROD));
+ seq_printf(seq, "EVTQ_CONS: 0x%08x\n",
+ readl_relaxed(base + ARM_SMMU_EVTQ_CONS));
+
+ return 0;
+}
+
+static int smmu_debugfs_registers_open(struct inode *inode, struct file *file)
+{
+ struct arm_smmu_device *smmu = inode->i_private;
+
+ if (!smmu || !get_device(smmu->dev))
+ return -ENODEV;
+
+ return single_open(file, smmu_debugfs_registers_show, smmu);
+}
+
+static int smmu_debugfs_registers_release(struct inode *inode, struct file *file)
+{
+ struct seq_file *seq = file->private_data;
+ struct arm_smmu_device *smmu = seq->private;
+
+ single_release(inode, file);
+ if (smmu)
+ put_device(smmu->dev);
+
+ return 0;
+}
+
+static const struct file_operations smmu_debugfs_registers_fops = {
+ .owner = THIS_MODULE,
+ .open = smmu_debugfs_registers_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = smmu_debugfs_registers_release,
+};
+
/**
* arm_smmu_debugfs_setup() - Initialize debugfs for SMMU device
* @smmu: SMMU device to setup debugfs for
@@ -134,6 +207,9 @@ int arm_smmu_debugfs_setup(struct arm_smmu_device *smmu, const char *name)
debugfs_create_file("capabilities", 0444, smmu_dir, smmu,
&smmu_debugfs_capabilities_fops);
+ debugfs_create_file("registers", 0444, smmu_dir, smmu,
+ &smmu_debugfs_registers_fops);
+
dev_dbg(smmu->dev, "debugfs initialized for %s\n", name);
return 0;
}
--
2.33.0
^ permalink raw reply related
* [RFC PATCH v2 1/5] iommu/arm-smmu-v3: Add basic debugfs framework
From: Qinxin Xia @ 2026-03-28 10:17 UTC (permalink / raw)
To: robin.murphy, nicolinc, will, jpb
Cc: linux-arm-kernel, iommu, xiaqinxin, wangzhou1, prime.zeng,
fanghao11, jonathan.cameron, wuyifan50, linuxarm
In-Reply-To: <20260328101706.3448655-1-xiaqinxin@huawei.com>
Add basic debugfs framework for ARM SMMUv3 driver.This creates the
root directory structure and provides capability display functionality.
The debugfs hierarchy is organized as:
/sys/kernel/debug/iommu/arm_smmu_v3/
└── smmu<ioaddr>/
└── capabilities
Signed-off-by: Qinxin Xia <xiaqinxin@huawei.com>
---
drivers/iommu/Kconfig | 11 ++
drivers/iommu/arm/arm-smmu-v3/Makefile | 1 +
.../arm/arm-smmu-v3/arm-smmu-v3-debugfs.c | 163 ++++++++++++++++++
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 15 ++
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h | 15 ++
5 files changed, 205 insertions(+)
create mode 100644 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-debugfs.c
diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index f86262b11416..f28f09adba03 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -93,6 +93,17 @@ config IOMMU_DEBUGFS
debug/iommu directory, and then populate a subdirectory with
entries as required.
+config ARM_SMMU_V3_DEBUGFS
+ bool "ARM SMMUv3 DebugFS support"
+ depends on ARM_SMMU_V3 && IOMMU_DEBUGFS
+ help
+ Expose ARM SMMUv3 internal state via debugfs for debugging and
+ diagnostics. This creates /sys/kernel/debug/iommu/arm_smmu_v3/
+ with detailed information about SMMU configuration, stream tables,
+ and context descriptors.
+
+ Say N unless you are debugging SMMU issues.
+
choice
prompt "IOMMU default domain type"
depends on IOMMU_API
diff --git a/drivers/iommu/arm/arm-smmu-v3/Makefile b/drivers/iommu/arm/arm-smmu-v3/Makefile
index 493a659cc66b..787538fb7054 100644
--- a/drivers/iommu/arm/arm-smmu-v3/Makefile
+++ b/drivers/iommu/arm/arm-smmu-v3/Makefile
@@ -4,5 +4,6 @@ arm_smmu_v3-y := arm-smmu-v3.o
arm_smmu_v3-$(CONFIG_ARM_SMMU_V3_IOMMUFD) += arm-smmu-v3-iommufd.o
arm_smmu_v3-$(CONFIG_ARM_SMMU_V3_SVA) += arm-smmu-v3-sva.o
arm_smmu_v3-$(CONFIG_TEGRA241_CMDQV) += tegra241-cmdqv.o
+arm_smmu_v3-$(CONFIG_ARM_SMMU_V3_DEBUGFS) += arm-smmu-v3-debugfs.o
obj-$(CONFIG_ARM_SMMU_V3_KUNIT_TEST) += arm-smmu-v3-test.o
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-debugfs.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-debugfs.c
new file mode 100644
index 000000000000..c764b28e5cfb
--- /dev/null
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-debugfs.c
@@ -0,0 +1,163 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * ARM SMMUv3 DebugFS Support
+ *
+ * Directory Structure:
+ * /sys/kernel/debug/iommu/arm_smmu_v3/
+ * └── smmu<ioaddr>/
+ * └── capabilities # SMMU feature capabilities and configuration
+ *
+ * The capabilities file provides detailed information about:
+ * - translation stage support (Stage1/Stage2)
+ * - System coherency, ATS, and PRI feature availability
+ * - Stream table size and command/event queue depths
+ *
+ * Copyright (C) 2026 HiSilicon Limited.
+ * Author: Qinxin Xia <xiaqinxin@huawei.com>
+ */
+
+#include <linux/cleanup.h>
+#include <linux/debugfs.h>
+#include <linux/slab.h>
+#include "arm-smmu-v3.h"
+
+static struct dentry *smmu_debugfs_root;
+static DEFINE_MUTEX(arm_smmu_debugfs_lock);
+
+/**
+ * smmu_debugfs_capabilities_show() - Display SMMU capabilities
+ * @seq: seq_file to write to
+ *
+ * Errors are reported via seq_puts, the function always returns 0
+ */
+static int smmu_debugfs_capabilities_show(struct seq_file *seq, void *unused)
+{
+ struct arm_smmu_device *smmu = seq->private;
+
+ if (!smmu) {
+ seq_puts(seq, "SMMU not available\n");
+ return 0;
+ }
+
+ seq_puts(seq, "SMMUv3 Capabilities:\n");
+ seq_printf(seq, " Stage1 Translation: %s\n",
+ smmu->features & ARM_SMMU_FEAT_TRANS_S1 ? "Yes" : "No");
+ seq_printf(seq, " Stage2 Translation: %s\n",
+ smmu->features & ARM_SMMU_FEAT_TRANS_S2 ? "Yes" : "No");
+ seq_printf(seq, " Coherent Walk: %s\n",
+ smmu->features & ARM_SMMU_FEAT_COHERENCY ? "Yes" : "No");
+ seq_printf(seq, " ATS Support: %s\n",
+ smmu->features & ARM_SMMU_FEAT_ATS ? "Yes" : "No");
+ seq_printf(seq, " PRI Support: %s\n",
+ smmu->features & ARM_SMMU_FEAT_PRI ? "Yes" : "No");
+ seq_printf(seq, " Stream Table Size: %d\n", 1 << smmu->sid_bits);
+ seq_printf(seq, " Command Queue Depth: %d\n",
+ 1 << smmu->cmdq.q.llq.max_n_shift);
+ seq_printf(seq, " Event Queue Depth: %d\n",
+ 1 << smmu->evtq.q.llq.max_n_shift);
+
+ return 0;
+}
+
+static int smmu_debugfs_capabilities_open(struct inode *inode, struct file *file)
+{
+ struct arm_smmu_device *smmu = inode->i_private;
+
+ if (!smmu || !get_device(smmu->dev))
+ return -ENODEV;
+
+ return single_open(file, smmu_debugfs_capabilities_show, smmu);
+}
+
+static int smmu_debugfs_capabilities_release(struct inode *inode, struct file *file)
+{
+ struct seq_file *seq = file->private_data;
+ struct arm_smmu_device *smmu = seq->private;
+
+ single_release(inode, file);
+ if (smmu)
+ put_device(smmu->dev);
+
+ return 0;
+}
+
+static const struct file_operations smmu_debugfs_capabilities_fops = {
+ .owner = THIS_MODULE,
+ .open = smmu_debugfs_capabilities_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = smmu_debugfs_capabilities_release,
+};
+
+/**
+ * arm_smmu_debugfs_setup() - Initialize debugfs for SMMU device
+ * @smmu: SMMU device to setup debugfs for
+ * @name: SMMU device name
+ *
+ * This function creates the basic debugfs directory structure for an SMMU device.
+ *
+ * Return: 0 on success, negative error code on failure
+ */
+int arm_smmu_debugfs_setup(struct arm_smmu_device *smmu, const char *name)
+{
+ struct arm_smmu_debugfs *debugfs;
+ struct dentry *smmu_dir;
+
+ /* Create root directory if it doesn't exist */
+ scoped_guard(mutex, &arm_smmu_debugfs_lock) {
+ if (!smmu_debugfs_root) {
+ /* Once created, it will not be removed */
+ smmu_debugfs_root = debugfs_create_dir("arm_smmu_v3",
+ iommu_debugfs_dir);
+ if (!smmu_debugfs_root)
+ return -ENOMEM;
+ }
+ }
+
+ /* Allocate debugfs structure */
+ debugfs = kzalloc_obj(*debugfs);
+ if (!debugfs)
+ return -ENOMEM;
+
+ /* Create SMMU instance directory */
+ smmu_dir = debugfs_create_dir(name, smmu_debugfs_root);
+ if (!smmu_dir) {
+ kfree(debugfs);
+ smmu->debugfs = NULL;
+ return -ENOMEM;
+ }
+
+ debugfs->smmu_dir = smmu_dir;
+ smmu->debugfs = debugfs;
+
+ /* Create capabilities file */
+ debugfs_create_file("capabilities", 0444, smmu_dir, smmu,
+ &smmu_debugfs_capabilities_fops);
+
+ dev_dbg(smmu->dev, "debugfs initialized for %s\n", name);
+ return 0;
+}
+
+/**
+ * arm_smmu_debugfs_remove() - Clean up debugfs entries for an SMMU device
+ * @smmu: SMMU device
+ *
+ * This function removes the debugfs directories created by setup.
+ */
+void arm_smmu_debugfs_remove(struct arm_smmu_device *smmu)
+{
+ struct arm_smmu_debugfs *debugfs;
+
+ scoped_guard(mutex, &arm_smmu_debugfs_lock) {
+ debugfs = smmu->debugfs;
+ if (!debugfs)
+ return;
+
+ /* Remove the entire SMMU instance directory */
+ debugfs_remove_recursive(debugfs->smmu_dir);
+
+ /* Free the debugfs structure */
+ kfree(debugfs);
+ smmu->debugfs = NULL;
+ }
+}
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
index 4d00d796f078..cbb3fccc501b 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -4904,6 +4904,15 @@ static int arm_smmu_device_probe(struct platform_device *pdev)
/* Check for RMRs and install bypass STEs if any */
arm_smmu_rmr_install_bypass_ste(smmu);
+#ifdef CONFIG_ARM_SMMU_V3_DEBUGFS
+ char name[32];
+
+ snprintf(name, sizeof(name), "smmu3.%pa", &ioaddr);
+ ret = arm_smmu_debugfs_setup(smmu, name);
+ if (ret)
+ dev_warn(dev, "Failed to create debugfs!\n");
+#endif
+
/* Reset the device */
ret = arm_smmu_device_reset(smmu);
if (ret)
@@ -4926,6 +4935,9 @@ static int arm_smmu_device_probe(struct platform_device *pdev)
err_free_sysfs:
iommu_device_sysfs_remove(&smmu->iommu);
err_disable:
+#ifdef CONFIG_ARM_SMMU_V3_DEBUGFS
+ arm_smmu_debugfs_remove(smmu);
+#endif
arm_smmu_device_disable(smmu);
err_free_iopf:
iopf_queue_free(smmu->evtq.iopf);
@@ -4938,6 +4950,9 @@ static void arm_smmu_device_remove(struct platform_device *pdev)
iommu_device_unregister(&smmu->iommu);
iommu_device_sysfs_remove(&smmu->iommu);
+#ifdef CONFIG_ARM_SMMU_V3_DEBUGFS
+ arm_smmu_debugfs_remove(smmu);
+#endif
arm_smmu_device_disable(smmu);
iopf_queue_free(smmu->evtq.iopf);
ida_destroy(&smmu->vmid_map);
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
index 3c6d65d36164..a54d72fb9e07 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
@@ -733,6 +733,16 @@ struct arm_smmu_impl_ops {
const struct iommu_user_data *user_data);
};
+#ifdef CONFIG_ARM_SMMU_V3_DEBUGFS
+struct arm_smmu_debugfs {
+ struct dentry *smmu_dir;
+ /* Reserved for future extensions */
+};
+
+int arm_smmu_debugfs_setup(struct arm_smmu_device *smmu, const char *name);
+void arm_smmu_debugfs_remove(struct arm_smmu_device *smmu);
+#endif
+
/* An SMMUv3 instance */
struct arm_smmu_device {
struct device *dev;
@@ -803,6 +813,11 @@ struct arm_smmu_device {
struct rb_root streams;
struct mutex streams_mutex;
+
+#ifdef CONFIG_ARM_SMMU_V3_DEBUGFS
+ /* DebugFS Info */
+ struct arm_smmu_debugfs *debugfs;
+#endif
};
struct arm_smmu_stream {
--
2.33.0
^ permalink raw reply related
* [RFC PATCH v2 4/5] iommu/arm-smmu-v3: Add device symlink in stream table debugfs
From: Qinxin Xia @ 2026-03-28 10:17 UTC (permalink / raw)
To: robin.murphy, nicolinc, will, jpb
Cc: linux-arm-kernel, iommu, xiaqinxin, wangzhou1, prime.zeng,
fanghao11, jonathan.cameron, wuyifan50, linuxarm
In-Reply-To: <20260328101706.3448655-1-xiaqinxin@huawei.com>
Add a symlink named under each stream table entry directory pointing to
the sysfs directory of the actual device. This aids debugging
by providing direct access to device attributes.
/sys/kernel/debug/iommu/arm_smmu_v3/smmu0/stream_table/
└── <sid>/
├─── ste
└─── <dev_name>
Signed-off-by: Qinxin Xia <xiaqinxin@huawei.com>
---
.../arm/arm-smmu-v3/arm-smmu-v3-debugfs.c | 19 +++++++++++++++++--
1 file changed, 17 insertions(+), 2 deletions(-)
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-debugfs.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-debugfs.c
index 70623b480d64..dbcc8fce6d8e 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-debugfs.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-debugfs.c
@@ -8,8 +8,9 @@
* ├── capabilities # SMMU feature capabilities and configuration
* ├── registers # SMMU Key registers
* └── stream_table
- * └─── <sid>/ # Stream ID 0
- * └── ste # Stream Table Entry
+ * └─── <sid>/ # Stream ID
+ * ├─── ste # Stream Table Entry
+ * └── <dev_name> # Symlink to device sysfs directory
*
* The capabilities file provides detailed information about:
* - translation stage support (Stage1/Stage2)
@@ -31,6 +32,7 @@
#include <linux/cleanup.h>
#include <linux/debugfs.h>
+#include <linux/kobject.h>
#include <linux/slab.h>
#include "arm-smmu-v3.h"
@@ -295,6 +297,7 @@ int arm_smmu_debugfs_create_stream_table(struct device *dev,
struct dentry *stream_dir, *dev_dir;
struct arm_smmu_master *master;
struct ste_context *ctx;
+ char *path, *full_path;
char name[64];
u32 sid;
int i;
@@ -333,6 +336,18 @@ int arm_smmu_debugfs_create_stream_table(struct device *dev,
debugfs_create_file("ste", 0444, dev_dir, ctx,
&smmu_debugfs_ste_fops);
+ /* Create a symlink to the device's sysfs directory */
+ path = kobject_get_path(&dev->kobj, GFP_KERNEL);
+ if (!path)
+ continue;
+
+ full_path = kasprintf(GFP_KERNEL, "/sys%s", path);
+ if (full_path) {
+ debugfs_create_symlink(dev_name(dev), dev_dir, full_path);
+ kfree(full_path);
+ }
+
+ kfree(path);
}
return 0;
--
2.33.0
^ permalink raw reply related
* [RFC PATCH v2 5/5] iommu/arm-smmu-v3: Add Context Descriptor display to debugfs
From: Qinxin Xia @ 2026-03-28 10:17 UTC (permalink / raw)
To: robin.murphy, nicolinc, will, jpb
Cc: linux-arm-kernel, iommu, xiaqinxin, wangzhou1, prime.zeng,
fanghao11, jonathan.cameron, wuyifan50, linuxarm
In-Reply-To: <20260328101706.3448655-1-xiaqinxin@huawei.com>
Add Context Descriptor (CD) display functionality to debugfs.
This allow inspecting CD contents for all Substream IDs including:
- CD validity and translation parameters
- TTBR0 and TCR configurations
- Raw CD data
/sys/kernel/debug/iommu/arm_smmu_v3/smmu0/stream_table/
└── <sid>/
├─── ste
├─── cd
└─── <dev_name>
Signed-off-by: Qinxin Xia <xiaqinxin@huawei.com>
---
.../arm/arm-smmu-v3/arm-smmu-v3-debugfs.c | 94 +++++++++++++++++++
1 file changed, 94 insertions(+)
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-debugfs.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-debugfs.c
index dbcc8fce6d8e..501437432809 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-debugfs.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-debugfs.c
@@ -10,6 +10,7 @@
* └── stream_table
* └─── <sid>/ # Stream ID
* ├─── ste # Stream Table Entry
+ * ├── cd # Context Descriptor
* └── <dev_name> # Symlink to device sysfs directory
*
* The capabilities file provides detailed information about:
@@ -26,6 +27,12 @@
* - Stage 1 and Stage 2 context pointers
* - Raw STE data
*
+ * CD Information Displayed:
+ * - T0SZ: Input address space size configuration
+ * - EPD0/EPD1: Stage 1 translation enable flags
+ * - TTBR0: Stage 1 translation table base address
+ * - Raw Data: Complete CD structure in hexadecimal format
+
* Copyright (C) 2026 HiSilicon Limited.
* Author: Qinxin Xia <xiaqinxin@huawei.com>
*/
@@ -284,6 +291,91 @@ static const struct file_operations smmu_debugfs_ste_fops = {
.release = smmu_debugfs_ste_release,
};
+/**
+ * smmu_debug_dump_cd() - Dump a single Context Descriptor
+ * @seq: seq_file to write to
+ * @cd: pointer to the Context Descriptor to dump
+ */
+static void smmu_debug_dump_cd(struct seq_file *seq, struct arm_smmu_cd *cd)
+{
+ u64 data;
+ int i;
+
+ /* CD 0 */
+ data = le64_to_cpu(cd->data[0]);
+ seq_printf(seq, " T0SZ: 0x%llx\n", data & CTXDESC_CD_0_TCR_T0SZ);
+ seq_printf(seq, " EPD0: %s\n", data & CTXDESC_CD_0_TCR_EPD0 ? "Yes" : "No");
+ seq_printf(seq, " EPD1: %s\n", data & CTXDESC_CD_0_TCR_EPD1 ? "Yes" : "No");
+
+ /* CD 1 */
+ data = le64_to_cpu(cd->data[1]);
+ seq_printf(seq, " TTBR0: 0x%016llx\n", data & CTXDESC_CD_1_TTB0_MASK);
+
+ /* Display raw CD data */
+ seq_puts(seq, " Raw Data:\n");
+ for (i = 0; i < CTXDESC_CD_DWORDS; i++)
+ seq_printf(seq, " CD[%d]: 0x%016llx\n", i,
+ le64_to_cpu(cd->data[i]));
+}
+
+static int smmu_debugfs_cd_show(struct seq_file *seq, void *unused)
+{
+ struct device *dev = seq->private;
+ struct arm_smmu_master *master = dev_iommu_priv_get(dev);
+ u32 max_ssids, ssid;
+
+ if (!master) {
+ seq_puts(seq, "No master data\n");
+ return 0;
+ }
+
+ mutex_lock(&arm_smmu_asid_lock);
+ max_ssids = 1 << master->ssid_bits;
+ seq_printf(seq, "Context Descriptors for device (max SSIDs: %u):\n",
+ max_ssids);
+
+ for (ssid = 0; ssid < max_ssids; ssid++) {
+ struct arm_smmu_cd *cd = arm_smmu_get_cd_ptr(master, ssid);
+
+ if (cd && (le64_to_cpu(cd->data[0]) & CTXDESC_CD_0_V)) {
+ seq_printf(seq, "\n--- SSID %u ---\n", ssid);
+ smmu_debug_dump_cd(seq, cd);
+ }
+ }
+
+ mutex_unlock(&arm_smmu_asid_lock);
+ return 0;
+}
+
+static int smmu_debugfs_cd_open(struct inode *inode, struct file *file)
+{
+ struct device *dev = inode->i_private;
+
+ if (!dev || !get_device(dev))
+ return -ENODEV;
+
+ return single_open(file, smmu_debugfs_cd_show, dev);
+}
+
+static int smmu_debugfs_cd_release(struct inode *inode, struct file *file)
+{
+ struct seq_file *seq = file->private_data;
+ struct device *dev = seq->private;
+
+ single_release(inode, file);
+ if (dev)
+ put_device(dev);
+ return 0;
+}
+
+static const struct file_operations smmu_debugfs_cd_fops = {
+ .owner = THIS_MODULE,
+ .open = smmu_debugfs_cd_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = smmu_debugfs_cd_release,
+};
+
/**
* arm_smmu_debugfs_create_stream_table() - Create debugfs entries for stream table
* @dev: device to create entries for
@@ -348,6 +440,8 @@ int arm_smmu_debugfs_create_stream_table(struct device *dev,
}
kfree(path);
+ /* Create CD file to dump all valid Context Descriptors */
+ debugfs_create_file("cd", 0444, dev_dir, dev, &smmu_debugfs_cd_fops);
}
return 0;
--
2.33.0
^ permalink raw reply related
* [RFC PATCH v2 3/5] iommu/arm-smmu-v3: Add Stream Table Entry display to debugfs
From: Qinxin Xia @ 2026-03-28 10:17 UTC (permalink / raw)
To: robin.murphy, nicolinc, will, jpb
Cc: linux-arm-kernel, iommu, xiaqinxin, wangzhou1, prime.zeng,
fanghao11, jonathan.cameron, wuyifan50, linuxarm
In-Reply-To: <20260328101706.3448655-1-xiaqinxin@huawei.com>
Add Stream Table Entry (STE) display functionality to debugfs.
This allow inspecting STE contents for each device stream including:
- STE validity and configuration
- Stage 1 and Stage 2 context pointers
- Raw STE data
/sys/kernel/debug/iommu/arm_smmu_v3/smmu0/stream_table/
└── <sid>/
└─── ste
Signed-off-by: Qinxin Xia <xiaqinxin@huawei.com>
---
.../arm/arm-smmu-v3/arm-smmu-v3-debugfs.c | 224 +++++++++++++++++-
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 18 +-
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h | 17 ++
3 files changed, 256 insertions(+), 3 deletions(-)
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-debugfs.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-debugfs.c
index cfd296aebc9f..70623b480d64 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-debugfs.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-debugfs.c
@@ -6,7 +6,10 @@
* /sys/kernel/debug/iommu/arm_smmu_v3/
* └── smmu<ioaddr>/
* ├── capabilities # SMMU feature capabilities and configuration
- * └── registers # SMMU Key registers
+ * ├── registers # SMMU Key registers
+ * └── stream_table
+ * └─── <sid>/ # Stream ID 0
+ * └── ste # Stream Table Entry
*
* The capabilities file provides detailed information about:
* - translation stage support (Stage1/Stage2)
@@ -17,6 +20,11 @@
* - CR0, CR1, CR2 control registers
* - Command and Event queue pointers
*
+ * The STE Information Displayed:
+ * - STE validity and configuration
+ * - Stage 1 and Stage 2 context pointers
+ * - Raw STE data
+ *
* Copyright (C) 2026 HiSilicon Limited.
* Author: Qinxin Xia <xiaqinxin@huawei.com>
*/
@@ -162,6 +170,218 @@ static const struct file_operations smmu_debugfs_registers_fops = {
.release = smmu_debugfs_registers_release,
};
+/**
+ * smmu_debugfs_ste_show() - Dump STE details to seq_file
+ * @seq: seq_file to write to
+ *
+ * Errors are reported via seq_puts, the function always returns 0
+ */
+static int smmu_debugfs_ste_show(struct seq_file *seq, void *unused)
+{
+ struct ste_context *ctx = seq->private;
+ struct arm_smmu_master *master = ctx->master;
+ struct arm_smmu_device *smmu;
+ struct arm_smmu_ste *ste;
+ u32 sid, cfg;
+ int i;
+
+ if (!master) {
+ seq_puts(seq, "No SMMU master data\n");
+ return 0;
+ }
+
+ smmu = master->smmu;
+ scoped_guard(mutex, &smmu->streams_mutex) {
+ sid = ctx->sid;
+
+ if (!arm_smmu_sid_in_range(smmu, sid)) {
+ seq_printf(seq, "Invalid Stream ID: %u (max %u)\n",
+ sid, (1 << smmu->sid_bits) - 1);
+ return 0;
+ }
+
+ ste = arm_smmu_get_step_for_sid(smmu, sid);
+ if (!ste) {
+ seq_printf(seq, "STE not available for SID %u\n", sid);
+ return 0;
+ }
+
+ seq_printf(seq, "STE for Stream ID %u\n", sid);
+ seq_printf(seq, " Valid: %s\n",
+ le64_to_cpu(ste->data[0]) & STRTAB_STE_0_V ? "Yes" : "No");
+
+ seq_puts(seq, " Config: ");
+
+ cfg = FIELD_GET(STRTAB_STE_0_CFG, le64_to_cpu(ste->data[0]));
+
+ switch (cfg) {
+ case STRTAB_STE_0_CFG_BYPASS:
+ seq_puts(seq, "BYPASS\n");
+ break;
+ case STRTAB_STE_0_CFG_S1_TRANS:
+ seq_puts(seq, "only S1_TRANS\n");
+ break;
+ case STRTAB_STE_0_CFG_S2_TRANS:
+ seq_puts(seq, "only S2_TRANS\n");
+ break;
+ case STRTAB_STE_0_CFG_NESTED:
+ seq_puts(seq, "S1+S2_TRANS\n");
+ break;
+ case STRTAB_STE_0_CFG_ABORT:
+ seq_puts(seq, "ABORT\n");
+ break;
+ default:
+ seq_puts(seq, "UNKNOWN\n");
+ }
+
+ if (le64_to_cpu(ste->data[0]) & STRTAB_STE_0_CFG_S1_TRANS) {
+ seq_printf(seq, " S1ContextPtr: 0x%016llx\n",
+ le64_to_cpu(ste->data[1]) & STRTAB_STE_0_S1CTXPTR_MASK);
+ }
+
+ if (le64_to_cpu(ste->data[0]) & STRTAB_STE_0_CFG_S2_TRANS) {
+ seq_printf(seq, " S2ContextPtr: 0x%016llx\n",
+ le64_to_cpu(ste->data[3]) & STRTAB_STE_3_S2TTB_MASK);
+ }
+
+ /* Display raw STE data */
+ seq_puts(seq, " Raw Data:\n");
+ for (i = 0; i < STRTAB_STE_DWORDS; i++)
+ seq_printf(seq, " STE[%d]: 0x%016llx\n", i,
+ le64_to_cpu(ste->data[i]));
+ }
+ return 0;
+}
+
+static int smmu_debugfs_ste_open(struct inode *inode, struct file *file)
+{
+ struct ste_context *ctx = inode->i_private;
+
+ if (!ctx || !get_device(ctx->master->dev))
+ return -ENODEV;
+
+ return single_open(file, smmu_debugfs_ste_show, ctx);
+}
+
+static int smmu_debugfs_ste_release(struct inode *inode, struct file *file)
+{
+ struct seq_file *seq = file->private_data;
+ struct ste_context *ctx = seq->private;
+
+ single_release(inode, file);
+ if (ctx)
+ put_device(ctx->master->dev);
+ return 0;
+}
+
+static const struct file_operations smmu_debugfs_ste_fops = {
+ .owner = THIS_MODULE,
+ .open = smmu_debugfs_ste_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = smmu_debugfs_ste_release,
+};
+
+/**
+ * arm_smmu_debugfs_create_stream_table() - Create debugfs entries for stream table
+ * @dev: device to create entries for
+ * @smmu: SMMU device
+ *
+ * Return: 0 on success, negative error code on failure
+ */
+int arm_smmu_debugfs_create_stream_table(struct device *dev,
+ struct arm_smmu_device *smmu)
+{
+ struct dentry *stream_dir, *dev_dir;
+ struct arm_smmu_master *master;
+ struct ste_context *ctx;
+ char name[64];
+ u32 sid;
+ int i;
+
+ scoped_guard(mutex, &arm_smmu_debugfs_lock) {
+ if (!smmu->debugfs->stream_dir) {
+ stream_dir = debugfs_create_dir("stream_table",
+ smmu->debugfs->smmu_dir);
+ if (!stream_dir)
+ return -ENOMEM;
+
+ smmu->debugfs->stream_dir = stream_dir;
+ } else {
+ stream_dir = smmu->debugfs->stream_dir;
+ }
+ }
+
+ master = dev_iommu_priv_get(dev);
+ if (!master || !master->num_streams)
+ return -ENODEV;
+
+ for (i = 0; i < master->num_streams; i++) {
+ sid = master->streams[i].id;
+ snprintf(name, sizeof(name), "%u", sid);
+ dev_dir = debugfs_create_dir(name, stream_dir);
+ if (!dev_dir)
+ continue;
+
+ /* Create STE file */
+ ctx = kzalloc_obj(*ctx);
+ ctx->master = master;
+ ctx->sid = sid;
+ spin_lock(&smmu->debugfs->stream_lock);
+ list_add_tail(&ctx->node, &smmu->debugfs->stream_list);
+ spin_unlock(&smmu->debugfs->stream_lock);
+ debugfs_create_file("ste", 0444, dev_dir, ctx,
+ &smmu_debugfs_ste_fops);
+
+ }
+
+ return 0;
+}
+
+/**
+ * arm_smmu_debugfs_remove_stream_table() - Remove debugfs entries for stream table
+ * @dev: device to remove entries for
+ * @smmu: SMMU device
+ *
+ * This function removes the debugfs directories created by
+ * arm_smmu_debugfs_create_stream_table().
+ */
+void arm_smmu_debugfs_remove_stream_table(struct device *dev,
+ struct arm_smmu_device *smmu)
+{
+ struct dentry *stream_dir, *dev_dir;
+ struct arm_smmu_master *master;
+ struct ste_context *ctx, *tmp;
+ char name[64];
+ int i;
+
+ /* Check if stream_table directory exists */
+ if (!smmu->debugfs || !smmu->debugfs->stream_dir)
+ return;
+
+ stream_dir = smmu->debugfs->stream_dir;
+ master = dev_iommu_priv_get(dev);
+ if (!master)
+ return;
+
+ /* Remove directories for each stream ID */
+ for (i = 0; i < master->num_streams; i++) {
+ snprintf(name, sizeof(name), "%u", master->streams[i].id);
+ dev_dir = debugfs_lookup(name, stream_dir);
+ debugfs_remove_recursive(dev_dir);
+ }
+
+ /* Free stream context */
+ spin_lock(&smmu->debugfs->stream_lock);
+ list_for_each_entry_safe(ctx, tmp, &smmu->debugfs->stream_list, node) {
+ if (ctx->master->dev == dev) {
+ list_del(&ctx->node);
+ kfree(ctx);
+ }
+ }
+ spin_unlock(&smmu->debugfs->stream_lock);
+}
+
/**
* arm_smmu_debugfs_setup() - Initialize debugfs for SMMU device
* @smmu: SMMU device to setup debugfs for
@@ -201,6 +421,8 @@ int arm_smmu_debugfs_setup(struct arm_smmu_device *smmu, const char *name)
}
debugfs->smmu_dir = smmu_dir;
+ INIT_LIST_HEAD(&debugfs->stream_list);
+ spin_lock_init(&debugfs->stream_lock);
smmu->debugfs = debugfs;
/* Create capabilities file */
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
index cbb3fccc501b..6be132b2f3f0 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -2654,7 +2654,10 @@ static int arm_smmu_domain_finalise(struct arm_smmu_domain *smmu_domain,
return 0;
}
-static struct arm_smmu_ste *
+#ifndef CONFIG_ARM_SMMU_V3_DEBUGFS
+static
+#endif
+struct arm_smmu_ste *
arm_smmu_get_step_for_sid(struct arm_smmu_device *smmu, u32 sid)
{
struct arm_smmu_strtab_cfg *cfg = &smmu->strtab_cfg;
@@ -3489,7 +3492,10 @@ struct arm_smmu_device *arm_smmu_get_by_fwnode(struct fwnode_handle *fwnode)
return dev ? dev_get_drvdata(dev) : NULL;
}
-static bool arm_smmu_sid_in_range(struct arm_smmu_device *smmu, u32 sid)
+#ifndef CONFIG_ARM_SMMU_V3_DEBUGFS
+static
+#endif
+bool arm_smmu_sid_in_range(struct arm_smmu_device *smmu, u32 sid)
{
if (smmu->features & ARM_SMMU_FEAT_2_LVL_STRTAB)
return arm_smmu_strtab_l1_idx(sid) < smmu->strtab_cfg.l2.num_l1_ents;
@@ -3635,6 +3641,10 @@ static struct iommu_device *arm_smmu_probe_device(struct device *dev)
pci_prepare_ats(to_pci_dev(dev), stu);
}
+#ifdef CONFIG_ARM_SMMU_V3_DEBUGFS
+ arm_smmu_debugfs_create_stream_table(dev, smmu);
+#endif
+
return &smmu->iommu;
err_free_master:
@@ -3648,10 +3658,14 @@ static void arm_smmu_release_device(struct device *dev)
WARN_ON(master->iopf_refcount);
+#ifdef CONFIG_ARM_SMMU_V3_DEBUGFS
+ arm_smmu_debugfs_remove_stream_table(dev, master->smmu);
+#endif
arm_smmu_disable_pasid(master);
arm_smmu_remove_master(master);
if (arm_smmu_cdtab_allocated(&master->cd_table))
arm_smmu_free_cd_tables(master);
+
kfree(master);
}
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
index a54d72fb9e07..d9ea803a2e4e 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
@@ -734,13 +734,30 @@ struct arm_smmu_impl_ops {
};
#ifdef CONFIG_ARM_SMMU_V3_DEBUGFS
+struct ste_context {
+ struct arm_smmu_master *master;
+ u32 sid;
+ struct list_head node;
+};
+
struct arm_smmu_debugfs {
+ struct list_head stream_list;
+ spinlock_t stream_lock;
struct dentry *smmu_dir;
+ struct dentry *stream_dir;
/* Reserved for future extensions */
};
int arm_smmu_debugfs_setup(struct arm_smmu_device *smmu, const char *name);
void arm_smmu_debugfs_remove(struct arm_smmu_device *smmu);
+int arm_smmu_debugfs_create_stream_table(struct device *dev,
+ struct arm_smmu_device *smmu);
+void arm_smmu_debugfs_remove_stream_table(struct device *dev,
+ struct arm_smmu_device *smmu);
+
+struct arm_smmu_ste *
+arm_smmu_get_step_for_sid(struct arm_smmu_device *smmu, u32 sid);
+bool arm_smmu_sid_in_range(struct arm_smmu_device *smmu, u32 sid);
#endif
/* An SMMUv3 instance */
--
2.33.0
^ permalink raw reply related
* Re: [RFC PATCH v2 0/5] Add debugfs support for ARM SMMUv3
From: Qinxin Xia @ 2026-03-28 10:14 UTC (permalink / raw)
To: robin.murphy, nicolinc, will, jpb
Cc: linux-arm-kernel, iommu, wangzhou1, prime.zeng, fanghao11,
jonathan.cameron, wuyifan50, linuxarm
In-Reply-To: <20260328100953.3441915-1-xiaqinxin@huawei.com>
Sorry!patch 2 cannot convert from y to UTF-8,I will release a new
version soon; please ignore this one.
On 2026/3/28 18:09:48, Qinxin Xia <xiaqinxin@huawei.com> wrote:
> Add a comprehensive debugfs framework to the ARM SMMUv3 driver,
> providing visibility into internal hardware state for debugging
> and performance analysis. The debugfs entries are organized under
> /sys/kernel/debug/iommu/arm_smmu_v3/, with per-SMMU instance directories
> and per-device stream table entries.
>
> Each SMMU instance provides:
> - capabilities – static SMMU features and queue sizes.
> - registers – SMMU key registers.
> - stream_table/ – a directory per device with subdirectories per Stream ID.
>
> Each Stream ID subdirectory contains:
> - ste – the Stream Table Entry in decoded and raw format.
> - cd – all valid Context Descriptors (Stage 1 translation tables) associated with the device.
> - a symlink named with the device’s BDF/name pointing to its sysfs directory for easy navigation.
>
> /sys/kernel/debug/iommu/arm_smmu_v3/smmu0/stream_table/
> └── <sid>/
> ├─── ste
> ├─── cd
> └─── <dev_name>
>
> Changes since V1:
> Address the comments from Nicolin:
> 1.Fixed the incorrect comments and replaced 'kzalloc' with 'kzalloc_obj'
> 2.'stream_table_create/stream_table_remove' is called in probe_device/release_device
> 3.Reused some functions in the driver
>
> Address the comments from Robin:
> 1.Remove unnecessary CR0*EN extra strings
> 2.Remove the limit on ssid
>
> Address the comments from Robin and Nicolin:
> 1.The directory structure has been changed
> 2.Added lock protection for the ste_show and cd_show
>
> Others:
> 1.'arm_smmu_debugfs_remove' is added to remove the corresponding debugfs when SMMU device is removed
> 2.'arm_smmu_debugfs_remove_stream_table' is added to remove the corresponding stream_dir when device is removed
> 3.Use scoped_guard for locks that include return
> 4.Added 'open' and 'release' operations to prevent the device from being released during dump
> 5.Merged 'stream_table_create' and 'ste_show' into one patch
> 6.Some other clean code
>
> - Link: https://lore.kernel.org/all/20260313104351.3502293-1-xiaqinxin@huawei.com/
>
> Qinxin Xia (5):
> iommu/arm-smmu-v3: Add basic debugfs framework
> iommu/arm-smmu-v3: Add register display to debugfs
> iommu/arm-smmu-v3: Add Stream Table Entry display to debugfs
> iommu/arm-smmu-v3: Add device symlink in stream table debugfs
> iommu/arm-smmu-v3: Add Context Descriptor display to debugfs
>
> drivers/iommu/Kconfig | 11 +
> drivers/iommu/arm/arm-smmu-v3/Makefile | 1 +
> .../arm/arm-smmu-v3/arm-smmu-v3-debugfs.c | 571 ++++++++++++++++++
> drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 33 +-
> drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h | 32 +
> 5 files changed, 646 insertions(+), 2 deletions(-)
> create mode 100644 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-debugfs.c
>
--
Thanks,
Qinxin
^ permalink raw reply
* [RFC PATCH v2 3/5] iommu/arm-smmu-v3: Add Stream Table Entry display to debugfs
From: Qinxin Xia @ 2026-03-28 10:09 UTC (permalink / raw)
To: robin.murphy, nicolinc, will, jpb
Cc: linux-arm-kernel, iommu, xiaqinxin, wangzhou1, prime.zeng,
fanghao11, jonathan.cameron, wuyifan50, linuxarm
In-Reply-To: <20260328100953.3441915-1-xiaqinxin@huawei.com>
Add Stream Table Entry (STE) display functionality to debugfs.
This allow inspecting STE contents for each device stream including:
- STE validity and configuration
- Stage 1 and Stage 2 context pointers
- Raw STE data
/sys/kernel/debug/iommu/arm_smmu_v3/smmu0/stream_table/
└── <sid>/
└─── ste
Signed-off-by: Qinxin Xia <xiaqinxin@huawei.com>
---
.../arm/arm-smmu-v3/arm-smmu-v3-debugfs.c | 224 +++++++++++++++++-
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 18 +-
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h | 17 ++
3 files changed, 256 insertions(+), 3 deletions(-)
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-debugfs.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-debugfs.c
index cfd296aebc9f..70623b480d64 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-debugfs.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-debugfs.c
@@ -6,7 +6,10 @@
* /sys/kernel/debug/iommu/arm_smmu_v3/
* └── smmu<ioaddr>/
* ├── capabilities # SMMU feature capabilities and configuration
- * └── registers # SMMU Key registers
+ * ├── registers # SMMU Key registers
+ * └── stream_table
+ * └─── <sid>/ # Stream ID 0
+ * └── ste # Stream Table Entry
*
* The capabilities file provides detailed information about:
* - translation stage support (Stage1/Stage2)
@@ -17,6 +20,11 @@
* - CR0, CR1, CR2 control registers
* - Command and Event queue pointers
*
+ * The STE Information Displayed:
+ * - STE validity and configuration
+ * - Stage 1 and Stage 2 context pointers
+ * - Raw STE data
+ *
* Copyright (C) 2026 HiSilicon Limited.
* Author: Qinxin Xia <xiaqinxin@huawei.com>
*/
@@ -162,6 +170,218 @@ static const struct file_operations smmu_debugfs_registers_fops = {
.release = smmu_debugfs_registers_release,
};
+/**
+ * smmu_debugfs_ste_show() - Dump STE details to seq_file
+ * @seq: seq_file to write to
+ *
+ * Errors are reported via seq_puts, the function always returns 0
+ */
+static int smmu_debugfs_ste_show(struct seq_file *seq, void *unused)
+{
+ struct ste_context *ctx = seq->private;
+ struct arm_smmu_master *master = ctx->master;
+ struct arm_smmu_device *smmu;
+ struct arm_smmu_ste *ste;
+ u32 sid, cfg;
+ int i;
+
+ if (!master) {
+ seq_puts(seq, "No SMMU master data\n");
+ return 0;
+ }
+
+ smmu = master->smmu;
+ scoped_guard(mutex, &smmu->streams_mutex) {
+ sid = ctx->sid;
+
+ if (!arm_smmu_sid_in_range(smmu, sid)) {
+ seq_printf(seq, "Invalid Stream ID: %u (max %u)\n",
+ sid, (1 << smmu->sid_bits) - 1);
+ return 0;
+ }
+
+ ste = arm_smmu_get_step_for_sid(smmu, sid);
+ if (!ste) {
+ seq_printf(seq, "STE not available for SID %u\n", sid);
+ return 0;
+ }
+
+ seq_printf(seq, "STE for Stream ID %u\n", sid);
+ seq_printf(seq, " Valid: %s\n",
+ le64_to_cpu(ste->data[0]) & STRTAB_STE_0_V ? "Yes" : "No");
+
+ seq_puts(seq, " Config: ");
+
+ cfg = FIELD_GET(STRTAB_STE_0_CFG, le64_to_cpu(ste->data[0]));
+
+ switch (cfg) {
+ case STRTAB_STE_0_CFG_BYPASS:
+ seq_puts(seq, "BYPASS\n");
+ break;
+ case STRTAB_STE_0_CFG_S1_TRANS:
+ seq_puts(seq, "only S1_TRANS\n");
+ break;
+ case STRTAB_STE_0_CFG_S2_TRANS:
+ seq_puts(seq, "only S2_TRANS\n");
+ break;
+ case STRTAB_STE_0_CFG_NESTED:
+ seq_puts(seq, "S1+S2_TRANS\n");
+ break;
+ case STRTAB_STE_0_CFG_ABORT:
+ seq_puts(seq, "ABORT\n");
+ break;
+ default:
+ seq_puts(seq, "UNKNOWN\n");
+ }
+
+ if (le64_to_cpu(ste->data[0]) & STRTAB_STE_0_CFG_S1_TRANS) {
+ seq_printf(seq, " S1ContextPtr: 0x%016llx\n",
+ le64_to_cpu(ste->data[1]) & STRTAB_STE_0_S1CTXPTR_MASK);
+ }
+
+ if (le64_to_cpu(ste->data[0]) & STRTAB_STE_0_CFG_S2_TRANS) {
+ seq_printf(seq, " S2ContextPtr: 0x%016llx\n",
+ le64_to_cpu(ste->data[3]) & STRTAB_STE_3_S2TTB_MASK);
+ }
+
+ /* Display raw STE data */
+ seq_puts(seq, " Raw Data:\n");
+ for (i = 0; i < STRTAB_STE_DWORDS; i++)
+ seq_printf(seq, " STE[%d]: 0x%016llx\n", i,
+ le64_to_cpu(ste->data[i]));
+ }
+ return 0;
+}
+
+static int smmu_debugfs_ste_open(struct inode *inode, struct file *file)
+{
+ struct ste_context *ctx = inode->i_private;
+
+ if (!ctx || !get_device(ctx->master->dev))
+ return -ENODEV;
+
+ return single_open(file, smmu_debugfs_ste_show, ctx);
+}
+
+static int smmu_debugfs_ste_release(struct inode *inode, struct file *file)
+{
+ struct seq_file *seq = file->private_data;
+ struct ste_context *ctx = seq->private;
+
+ single_release(inode, file);
+ if (ctx)
+ put_device(ctx->master->dev);
+ return 0;
+}
+
+static const struct file_operations smmu_debugfs_ste_fops = {
+ .owner = THIS_MODULE,
+ .open = smmu_debugfs_ste_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = smmu_debugfs_ste_release,
+};
+
+/**
+ * arm_smmu_debugfs_create_stream_table() - Create debugfs entries for stream table
+ * @dev: device to create entries for
+ * @smmu: SMMU device
+ *
+ * Return: 0 on success, negative error code on failure
+ */
+int arm_smmu_debugfs_create_stream_table(struct device *dev,
+ struct arm_smmu_device *smmu)
+{
+ struct dentry *stream_dir, *dev_dir;
+ struct arm_smmu_master *master;
+ struct ste_context *ctx;
+ char name[64];
+ u32 sid;
+ int i;
+
+ scoped_guard(mutex, &arm_smmu_debugfs_lock) {
+ if (!smmu->debugfs->stream_dir) {
+ stream_dir = debugfs_create_dir("stream_table",
+ smmu->debugfs->smmu_dir);
+ if (!stream_dir)
+ return -ENOMEM;
+
+ smmu->debugfs->stream_dir = stream_dir;
+ } else {
+ stream_dir = smmu->debugfs->stream_dir;
+ }
+ }
+
+ master = dev_iommu_priv_get(dev);
+ if (!master || !master->num_streams)
+ return -ENODEV;
+
+ for (i = 0; i < master->num_streams; i++) {
+ sid = master->streams[i].id;
+ snprintf(name, sizeof(name), "%u", sid);
+ dev_dir = debugfs_create_dir(name, stream_dir);
+ if (!dev_dir)
+ continue;
+
+ /* Create STE file */
+ ctx = kzalloc_obj(*ctx);
+ ctx->master = master;
+ ctx->sid = sid;
+ spin_lock(&smmu->debugfs->stream_lock);
+ list_add_tail(&ctx->node, &smmu->debugfs->stream_list);
+ spin_unlock(&smmu->debugfs->stream_lock);
+ debugfs_create_file("ste", 0444, dev_dir, ctx,
+ &smmu_debugfs_ste_fops);
+
+ }
+
+ return 0;
+}
+
+/**
+ * arm_smmu_debugfs_remove_stream_table() - Remove debugfs entries for stream table
+ * @dev: device to remove entries for
+ * @smmu: SMMU device
+ *
+ * This function removes the debugfs directories created by
+ * arm_smmu_debugfs_create_stream_table().
+ */
+void arm_smmu_debugfs_remove_stream_table(struct device *dev,
+ struct arm_smmu_device *smmu)
+{
+ struct dentry *stream_dir, *dev_dir;
+ struct arm_smmu_master *master;
+ struct ste_context *ctx, *tmp;
+ char name[64];
+ int i;
+
+ /* Check if stream_table directory exists */
+ if (!smmu->debugfs || !smmu->debugfs->stream_dir)
+ return;
+
+ stream_dir = smmu->debugfs->stream_dir;
+ master = dev_iommu_priv_get(dev);
+ if (!master)
+ return;
+
+ /* Remove directories for each stream ID */
+ for (i = 0; i < master->num_streams; i++) {
+ snprintf(name, sizeof(name), "%u", master->streams[i].id);
+ dev_dir = debugfs_lookup(name, stream_dir);
+ debugfs_remove_recursive(dev_dir);
+ }
+
+ /* Free stream context */
+ spin_lock(&smmu->debugfs->stream_lock);
+ list_for_each_entry_safe(ctx, tmp, &smmu->debugfs->stream_list, node) {
+ if (ctx->master->dev == dev) {
+ list_del(&ctx->node);
+ kfree(ctx);
+ }
+ }
+ spin_unlock(&smmu->debugfs->stream_lock);
+}
+
/**
* arm_smmu_debugfs_setup() - Initialize debugfs for SMMU device
* @smmu: SMMU device to setup debugfs for
@@ -201,6 +421,8 @@ int arm_smmu_debugfs_setup(struct arm_smmu_device *smmu, const char *name)
}
debugfs->smmu_dir = smmu_dir;
+ INIT_LIST_HEAD(&debugfs->stream_list);
+ spin_lock_init(&debugfs->stream_lock);
smmu->debugfs = debugfs;
/* Create capabilities file */
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
index cbb3fccc501b..6be132b2f3f0 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -2654,7 +2654,10 @@ static int arm_smmu_domain_finalise(struct arm_smmu_domain *smmu_domain,
return 0;
}
-static struct arm_smmu_ste *
+#ifndef CONFIG_ARM_SMMU_V3_DEBUGFS
+static
+#endif
+struct arm_smmu_ste *
arm_smmu_get_step_for_sid(struct arm_smmu_device *smmu, u32 sid)
{
struct arm_smmu_strtab_cfg *cfg = &smmu->strtab_cfg;
@@ -3489,7 +3492,10 @@ struct arm_smmu_device *arm_smmu_get_by_fwnode(struct fwnode_handle *fwnode)
return dev ? dev_get_drvdata(dev) : NULL;
}
-static bool arm_smmu_sid_in_range(struct arm_smmu_device *smmu, u32 sid)
+#ifndef CONFIG_ARM_SMMU_V3_DEBUGFS
+static
+#endif
+bool arm_smmu_sid_in_range(struct arm_smmu_device *smmu, u32 sid)
{
if (smmu->features & ARM_SMMU_FEAT_2_LVL_STRTAB)
return arm_smmu_strtab_l1_idx(sid) < smmu->strtab_cfg.l2.num_l1_ents;
@@ -3635,6 +3641,10 @@ static struct iommu_device *arm_smmu_probe_device(struct device *dev)
pci_prepare_ats(to_pci_dev(dev), stu);
}
+#ifdef CONFIG_ARM_SMMU_V3_DEBUGFS
+ arm_smmu_debugfs_create_stream_table(dev, smmu);
+#endif
+
return &smmu->iommu;
err_free_master:
@@ -3648,10 +3658,14 @@ static void arm_smmu_release_device(struct device *dev)
WARN_ON(master->iopf_refcount);
+#ifdef CONFIG_ARM_SMMU_V3_DEBUGFS
+ arm_smmu_debugfs_remove_stream_table(dev, master->smmu);
+#endif
arm_smmu_disable_pasid(master);
arm_smmu_remove_master(master);
if (arm_smmu_cdtab_allocated(&master->cd_table))
arm_smmu_free_cd_tables(master);
+
kfree(master);
}
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
index a54d72fb9e07..d9ea803a2e4e 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
@@ -734,13 +734,30 @@ struct arm_smmu_impl_ops {
};
#ifdef CONFIG_ARM_SMMU_V3_DEBUGFS
+struct ste_context {
+ struct arm_smmu_master *master;
+ u32 sid;
+ struct list_head node;
+};
+
struct arm_smmu_debugfs {
+ struct list_head stream_list;
+ spinlock_t stream_lock;
struct dentry *smmu_dir;
+ struct dentry *stream_dir;
/* Reserved for future extensions */
};
int arm_smmu_debugfs_setup(struct arm_smmu_device *smmu, const char *name);
void arm_smmu_debugfs_remove(struct arm_smmu_device *smmu);
+int arm_smmu_debugfs_create_stream_table(struct device *dev,
+ struct arm_smmu_device *smmu);
+void arm_smmu_debugfs_remove_stream_table(struct device *dev,
+ struct arm_smmu_device *smmu);
+
+struct arm_smmu_ste *
+arm_smmu_get_step_for_sid(struct arm_smmu_device *smmu, u32 sid);
+bool arm_smmu_sid_in_range(struct arm_smmu_device *smmu, u32 sid);
#endif
/* An SMMUv3 instance */
--
2.33.0
^ permalink raw reply related
* [RFC PATCH v2 0/5] Add debugfs support for ARM SMMUv3
From: Qinxin Xia @ 2026-03-28 10:09 UTC (permalink / raw)
To: robin.murphy, nicolinc, will, jpb
Cc: linux-arm-kernel, iommu, xiaqinxin, wangzhou1, prime.zeng,
fanghao11, jonathan.cameron, wuyifan50, linuxarm
Add a comprehensive debugfs framework to the ARM SMMUv3 driver,
providing visibility into internal hardware state for debugging
and performance analysis. The debugfs entries are organized under
/sys/kernel/debug/iommu/arm_smmu_v3/, with per-SMMU instance directories
and per-device stream table entries.
Each SMMU instance provides:
- capabilities – static SMMU features and queue sizes.
- registers – SMMU key registers.
- stream_table/ – a directory per device with subdirectories per Stream ID.
Each Stream ID subdirectory contains:
- ste – the Stream Table Entry in decoded and raw format.
- cd – all valid Context Descriptors (Stage 1 translation tables) associated with the device.
- a symlink named with the device’s BDF/name pointing to its sysfs directory for easy navigation.
/sys/kernel/debug/iommu/arm_smmu_v3/smmu0/stream_table/
└── <sid>/
├─── ste
├─── cd
└─── <dev_name>
Changes since V1:
Address the comments from Nicolin:
1.Fixed the incorrect comments and replaced 'kzalloc' with 'kzalloc_obj'
2.'stream_table_create/stream_table_remove' is called in probe_device/release_device
3.Reused some functions in the driver
Address the comments from Robin:
1.Remove unnecessary CR0*EN extra strings
2.Remove the limit on ssid
Address the comments from Robin and Nicolin:
1.The directory structure has been changed
2.Added lock protection for the ste_show and cd_show
Others:
1.'arm_smmu_debugfs_remove' is added to remove the corresponding debugfs when SMMU device is removed
2.'arm_smmu_debugfs_remove_stream_table' is added to remove the corresponding stream_dir when device is removed
3.Use scoped_guard for locks that include return
4.Added 'open' and 'release' operations to prevent the device from being released during dump
5.Merged 'stream_table_create' and 'ste_show' into one patch
6.Some other clean code
- Link: https://lore.kernel.org/all/20260313104351.3502293-1-xiaqinxin@huawei.com/
Qinxin Xia (5):
iommu/arm-smmu-v3: Add basic debugfs framework
iommu/arm-smmu-v3: Add register display to debugfs
iommu/arm-smmu-v3: Add Stream Table Entry display to debugfs
iommu/arm-smmu-v3: Add device symlink in stream table debugfs
iommu/arm-smmu-v3: Add Context Descriptor display to debugfs
drivers/iommu/Kconfig | 11 +
drivers/iommu/arm/arm-smmu-v3/Makefile | 1 +
.../arm/arm-smmu-v3/arm-smmu-v3-debugfs.c | 571 ++++++++++++++++++
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 33 +-
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h | 32 +
5 files changed, 646 insertions(+), 2 deletions(-)
create mode 100644 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-debugfs.c
--
2.33.0
^ permalink raw reply
* [RFC PATCH v2 1/5] iommu/arm-smmu-v3: Add basic debugfs framework
From: Qinxin Xia @ 2026-03-28 10:09 UTC (permalink / raw)
To: robin.murphy, nicolinc, will, jpb
Cc: linux-arm-kernel, iommu, xiaqinxin, wangzhou1, prime.zeng,
fanghao11, jonathan.cameron, wuyifan50, linuxarm
In-Reply-To: <20260328100953.3441915-1-xiaqinxin@huawei.com>
Add basic debugfs framework for ARM SMMUv3 driver.This creates the
root directory structure and provides capability display functionality.
The debugfs hierarchy is organized as:
/sys/kernel/debug/iommu/arm_smmu_v3/
└── smmu<ioaddr>/
└── capabilities
Signed-off-by: Qinxin Xia <xiaqinxin@huawei.com>
---
drivers/iommu/Kconfig | 11 ++
drivers/iommu/arm/arm-smmu-v3/Makefile | 1 +
.../arm/arm-smmu-v3/arm-smmu-v3-debugfs.c | 163 ++++++++++++++++++
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 15 ++
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h | 15 ++
5 files changed, 205 insertions(+)
create mode 100644 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-debugfs.c
diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index f86262b11416..f28f09adba03 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -93,6 +93,17 @@ config IOMMU_DEBUGFS
debug/iommu directory, and then populate a subdirectory with
entries as required.
+config ARM_SMMU_V3_DEBUGFS
+ bool "ARM SMMUv3 DebugFS support"
+ depends on ARM_SMMU_V3 && IOMMU_DEBUGFS
+ help
+ Expose ARM SMMUv3 internal state via debugfs for debugging and
+ diagnostics. This creates /sys/kernel/debug/iommu/arm_smmu_v3/
+ with detailed information about SMMU configuration, stream tables,
+ and context descriptors.
+
+ Say N unless you are debugging SMMU issues.
+
choice
prompt "IOMMU default domain type"
depends on IOMMU_API
diff --git a/drivers/iommu/arm/arm-smmu-v3/Makefile b/drivers/iommu/arm/arm-smmu-v3/Makefile
index 493a659cc66b..787538fb7054 100644
--- a/drivers/iommu/arm/arm-smmu-v3/Makefile
+++ b/drivers/iommu/arm/arm-smmu-v3/Makefile
@@ -4,5 +4,6 @@ arm_smmu_v3-y := arm-smmu-v3.o
arm_smmu_v3-$(CONFIG_ARM_SMMU_V3_IOMMUFD) += arm-smmu-v3-iommufd.o
arm_smmu_v3-$(CONFIG_ARM_SMMU_V3_SVA) += arm-smmu-v3-sva.o
arm_smmu_v3-$(CONFIG_TEGRA241_CMDQV) += tegra241-cmdqv.o
+arm_smmu_v3-$(CONFIG_ARM_SMMU_V3_DEBUGFS) += arm-smmu-v3-debugfs.o
obj-$(CONFIG_ARM_SMMU_V3_KUNIT_TEST) += arm-smmu-v3-test.o
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-debugfs.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-debugfs.c
new file mode 100644
index 000000000000..c764b28e5cfb
--- /dev/null
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-debugfs.c
@@ -0,0 +1,163 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * ARM SMMUv3 DebugFS Support
+ *
+ * Directory Structure:
+ * /sys/kernel/debug/iommu/arm_smmu_v3/
+ * └── smmu<ioaddr>/
+ * └── capabilities # SMMU feature capabilities and configuration
+ *
+ * The capabilities file provides detailed information about:
+ * - translation stage support (Stage1/Stage2)
+ * - System coherency, ATS, and PRI feature availability
+ * - Stream table size and command/event queue depths
+ *
+ * Copyright (C) 2026 HiSilicon Limited.
+ * Author: Qinxin Xia <xiaqinxin@huawei.com>
+ */
+
+#include <linux/cleanup.h>
+#include <linux/debugfs.h>
+#include <linux/slab.h>
+#include "arm-smmu-v3.h"
+
+static struct dentry *smmu_debugfs_root;
+static DEFINE_MUTEX(arm_smmu_debugfs_lock);
+
+/**
+ * smmu_debugfs_capabilities_show() - Display SMMU capabilities
+ * @seq: seq_file to write to
+ *
+ * Errors are reported via seq_puts, the function always returns 0
+ */
+static int smmu_debugfs_capabilities_show(struct seq_file *seq, void *unused)
+{
+ struct arm_smmu_device *smmu = seq->private;
+
+ if (!smmu) {
+ seq_puts(seq, "SMMU not available\n");
+ return 0;
+ }
+
+ seq_puts(seq, "SMMUv3 Capabilities:\n");
+ seq_printf(seq, " Stage1 Translation: %s\n",
+ smmu->features & ARM_SMMU_FEAT_TRANS_S1 ? "Yes" : "No");
+ seq_printf(seq, " Stage2 Translation: %s\n",
+ smmu->features & ARM_SMMU_FEAT_TRANS_S2 ? "Yes" : "No");
+ seq_printf(seq, " Coherent Walk: %s\n",
+ smmu->features & ARM_SMMU_FEAT_COHERENCY ? "Yes" : "No");
+ seq_printf(seq, " ATS Support: %s\n",
+ smmu->features & ARM_SMMU_FEAT_ATS ? "Yes" : "No");
+ seq_printf(seq, " PRI Support: %s\n",
+ smmu->features & ARM_SMMU_FEAT_PRI ? "Yes" : "No");
+ seq_printf(seq, " Stream Table Size: %d\n", 1 << smmu->sid_bits);
+ seq_printf(seq, " Command Queue Depth: %d\n",
+ 1 << smmu->cmdq.q.llq.max_n_shift);
+ seq_printf(seq, " Event Queue Depth: %d\n",
+ 1 << smmu->evtq.q.llq.max_n_shift);
+
+ return 0;
+}
+
+static int smmu_debugfs_capabilities_open(struct inode *inode, struct file *file)
+{
+ struct arm_smmu_device *smmu = inode->i_private;
+
+ if (!smmu || !get_device(smmu->dev))
+ return -ENODEV;
+
+ return single_open(file, smmu_debugfs_capabilities_show, smmu);
+}
+
+static int smmu_debugfs_capabilities_release(struct inode *inode, struct file *file)
+{
+ struct seq_file *seq = file->private_data;
+ struct arm_smmu_device *smmu = seq->private;
+
+ single_release(inode, file);
+ if (smmu)
+ put_device(smmu->dev);
+
+ return 0;
+}
+
+static const struct file_operations smmu_debugfs_capabilities_fops = {
+ .owner = THIS_MODULE,
+ .open = smmu_debugfs_capabilities_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = smmu_debugfs_capabilities_release,
+};
+
+/**
+ * arm_smmu_debugfs_setup() - Initialize debugfs for SMMU device
+ * @smmu: SMMU device to setup debugfs for
+ * @name: SMMU device name
+ *
+ * This function creates the basic debugfs directory structure for an SMMU device.
+ *
+ * Return: 0 on success, negative error code on failure
+ */
+int arm_smmu_debugfs_setup(struct arm_smmu_device *smmu, const char *name)
+{
+ struct arm_smmu_debugfs *debugfs;
+ struct dentry *smmu_dir;
+
+ /* Create root directory if it doesn't exist */
+ scoped_guard(mutex, &arm_smmu_debugfs_lock) {
+ if (!smmu_debugfs_root) {
+ /* Once created, it will not be removed */
+ smmu_debugfs_root = debugfs_create_dir("arm_smmu_v3",
+ iommu_debugfs_dir);
+ if (!smmu_debugfs_root)
+ return -ENOMEM;
+ }
+ }
+
+ /* Allocate debugfs structure */
+ debugfs = kzalloc_obj(*debugfs);
+ if (!debugfs)
+ return -ENOMEM;
+
+ /* Create SMMU instance directory */
+ smmu_dir = debugfs_create_dir(name, smmu_debugfs_root);
+ if (!smmu_dir) {
+ kfree(debugfs);
+ smmu->debugfs = NULL;
+ return -ENOMEM;
+ }
+
+ debugfs->smmu_dir = smmu_dir;
+ smmu->debugfs = debugfs;
+
+ /* Create capabilities file */
+ debugfs_create_file("capabilities", 0444, smmu_dir, smmu,
+ &smmu_debugfs_capabilities_fops);
+
+ dev_dbg(smmu->dev, "debugfs initialized for %s\n", name);
+ return 0;
+}
+
+/**
+ * arm_smmu_debugfs_remove() - Clean up debugfs entries for an SMMU device
+ * @smmu: SMMU device
+ *
+ * This function removes the debugfs directories created by setup.
+ */
+void arm_smmu_debugfs_remove(struct arm_smmu_device *smmu)
+{
+ struct arm_smmu_debugfs *debugfs;
+
+ scoped_guard(mutex, &arm_smmu_debugfs_lock) {
+ debugfs = smmu->debugfs;
+ if (!debugfs)
+ return;
+
+ /* Remove the entire SMMU instance directory */
+ debugfs_remove_recursive(debugfs->smmu_dir);
+
+ /* Free the debugfs structure */
+ kfree(debugfs);
+ smmu->debugfs = NULL;
+ }
+}
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
index 4d00d796f078..cbb3fccc501b 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -4904,6 +4904,15 @@ static int arm_smmu_device_probe(struct platform_device *pdev)
/* Check for RMRs and install bypass STEs if any */
arm_smmu_rmr_install_bypass_ste(smmu);
+#ifdef CONFIG_ARM_SMMU_V3_DEBUGFS
+ char name[32];
+
+ snprintf(name, sizeof(name), "smmu3.%pa", &ioaddr);
+ ret = arm_smmu_debugfs_setup(smmu, name);
+ if (ret)
+ dev_warn(dev, "Failed to create debugfs!\n");
+#endif
+
/* Reset the device */
ret = arm_smmu_device_reset(smmu);
if (ret)
@@ -4926,6 +4935,9 @@ static int arm_smmu_device_probe(struct platform_device *pdev)
err_free_sysfs:
iommu_device_sysfs_remove(&smmu->iommu);
err_disable:
+#ifdef CONFIG_ARM_SMMU_V3_DEBUGFS
+ arm_smmu_debugfs_remove(smmu);
+#endif
arm_smmu_device_disable(smmu);
err_free_iopf:
iopf_queue_free(smmu->evtq.iopf);
@@ -4938,6 +4950,9 @@ static void arm_smmu_device_remove(struct platform_device *pdev)
iommu_device_unregister(&smmu->iommu);
iommu_device_sysfs_remove(&smmu->iommu);
+#ifdef CONFIG_ARM_SMMU_V3_DEBUGFS
+ arm_smmu_debugfs_remove(smmu);
+#endif
arm_smmu_device_disable(smmu);
iopf_queue_free(smmu->evtq.iopf);
ida_destroy(&smmu->vmid_map);
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
index 3c6d65d36164..a54d72fb9e07 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
@@ -733,6 +733,16 @@ struct arm_smmu_impl_ops {
const struct iommu_user_data *user_data);
};
+#ifdef CONFIG_ARM_SMMU_V3_DEBUGFS
+struct arm_smmu_debugfs {
+ struct dentry *smmu_dir;
+ /* Reserved for future extensions */
+};
+
+int arm_smmu_debugfs_setup(struct arm_smmu_device *smmu, const char *name);
+void arm_smmu_debugfs_remove(struct arm_smmu_device *smmu);
+#endif
+
/* An SMMUv3 instance */
struct arm_smmu_device {
struct device *dev;
@@ -803,6 +813,11 @@ struct arm_smmu_device {
struct rb_root streams;
struct mutex streams_mutex;
+
+#ifdef CONFIG_ARM_SMMU_V3_DEBUGFS
+ /* DebugFS Info */
+ struct arm_smmu_debugfs *debugfs;
+#endif
};
struct arm_smmu_stream {
--
2.33.0
^ permalink raw reply related
* [RFC PATCH v2 5/5] iommu/arm-smmu-v3: Add Context Descriptor display to debugfs
From: Qinxin Xia @ 2026-03-28 10:09 UTC (permalink / raw)
To: robin.murphy, nicolinc, will, jpb
Cc: linux-arm-kernel, iommu, xiaqinxin, wangzhou1, prime.zeng,
fanghao11, jonathan.cameron, wuyifan50, linuxarm
In-Reply-To: <20260328100953.3441915-1-xiaqinxin@huawei.com>
Add Context Descriptor (CD) display functionality to debugfs.
This allow inspecting CD contents for all Substream IDs including:
- CD validity and translation parameters
- TTBR0 and TCR configurations
- Raw CD data
/sys/kernel/debug/iommu/arm_smmu_v3/smmu0/stream_table/
└── <sid>/
├─── ste
├─── cd
└─── <dev_name>
Signed-off-by: Qinxin Xia <xiaqinxin@huawei.com>
---
.../arm/arm-smmu-v3/arm-smmu-v3-debugfs.c | 94 +++++++++++++++++++
1 file changed, 94 insertions(+)
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-debugfs.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-debugfs.c
index dbcc8fce6d8e..501437432809 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-debugfs.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-debugfs.c
@@ -10,6 +10,7 @@
* └── stream_table
* └─── <sid>/ # Stream ID
* ├─── ste # Stream Table Entry
+ * ├── cd # Context Descriptor
* └── <dev_name> # Symlink to device sysfs directory
*
* The capabilities file provides detailed information about:
@@ -26,6 +27,12 @@
* - Stage 1 and Stage 2 context pointers
* - Raw STE data
*
+ * CD Information Displayed:
+ * - T0SZ: Input address space size configuration
+ * - EPD0/EPD1: Stage 1 translation enable flags
+ * - TTBR0: Stage 1 translation table base address
+ * - Raw Data: Complete CD structure in hexadecimal format
+
* Copyright (C) 2026 HiSilicon Limited.
* Author: Qinxin Xia <xiaqinxin@huawei.com>
*/
@@ -284,6 +291,91 @@ static const struct file_operations smmu_debugfs_ste_fops = {
.release = smmu_debugfs_ste_release,
};
+/**
+ * smmu_debug_dump_cd() - Dump a single Context Descriptor
+ * @seq: seq_file to write to
+ * @cd: pointer to the Context Descriptor to dump
+ */
+static void smmu_debug_dump_cd(struct seq_file *seq, struct arm_smmu_cd *cd)
+{
+ u64 data;
+ int i;
+
+ /* CD 0 */
+ data = le64_to_cpu(cd->data[0]);
+ seq_printf(seq, " T0SZ: 0x%llx\n", data & CTXDESC_CD_0_TCR_T0SZ);
+ seq_printf(seq, " EPD0: %s\n", data & CTXDESC_CD_0_TCR_EPD0 ? "Yes" : "No");
+ seq_printf(seq, " EPD1: %s\n", data & CTXDESC_CD_0_TCR_EPD1 ? "Yes" : "No");
+
+ /* CD 1 */
+ data = le64_to_cpu(cd->data[1]);
+ seq_printf(seq, " TTBR0: 0x%016llx\n", data & CTXDESC_CD_1_TTB0_MASK);
+
+ /* Display raw CD data */
+ seq_puts(seq, " Raw Data:\n");
+ for (i = 0; i < CTXDESC_CD_DWORDS; i++)
+ seq_printf(seq, " CD[%d]: 0x%016llx\n", i,
+ le64_to_cpu(cd->data[i]));
+}
+
+static int smmu_debugfs_cd_show(struct seq_file *seq, void *unused)
+{
+ struct device *dev = seq->private;
+ struct arm_smmu_master *master = dev_iommu_priv_get(dev);
+ u32 max_ssids, ssid;
+
+ if (!master) {
+ seq_puts(seq, "No master data\n");
+ return 0;
+ }
+
+ mutex_lock(&arm_smmu_asid_lock);
+ max_ssids = 1 << master->ssid_bits;
+ seq_printf(seq, "Context Descriptors for device (max SSIDs: %u):\n",
+ max_ssids);
+
+ for (ssid = 0; ssid < max_ssids; ssid++) {
+ struct arm_smmu_cd *cd = arm_smmu_get_cd_ptr(master, ssid);
+
+ if (cd && (le64_to_cpu(cd->data[0]) & CTXDESC_CD_0_V)) {
+ seq_printf(seq, "\n--- SSID %u ---\n", ssid);
+ smmu_debug_dump_cd(seq, cd);
+ }
+ }
+
+ mutex_unlock(&arm_smmu_asid_lock);
+ return 0;
+}
+
+static int smmu_debugfs_cd_open(struct inode *inode, struct file *file)
+{
+ struct device *dev = inode->i_private;
+
+ if (!dev || !get_device(dev))
+ return -ENODEV;
+
+ return single_open(file, smmu_debugfs_cd_show, dev);
+}
+
+static int smmu_debugfs_cd_release(struct inode *inode, struct file *file)
+{
+ struct seq_file *seq = file->private_data;
+ struct device *dev = seq->private;
+
+ single_release(inode, file);
+ if (dev)
+ put_device(dev);
+ return 0;
+}
+
+static const struct file_operations smmu_debugfs_cd_fops = {
+ .owner = THIS_MODULE,
+ .open = smmu_debugfs_cd_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = smmu_debugfs_cd_release,
+};
+
/**
* arm_smmu_debugfs_create_stream_table() - Create debugfs entries for stream table
* @dev: device to create entries for
@@ -348,6 +440,8 @@ int arm_smmu_debugfs_create_stream_table(struct device *dev,
}
kfree(path);
+ /* Create CD file to dump all valid Context Descriptors */
+ debugfs_create_file("cd", 0444, dev_dir, dev, &smmu_debugfs_cd_fops);
}
return 0;
--
2.33.0
^ permalink raw reply related
* [RFC PATCH v2 2/5] iommu/arm-smmu-v3: Add register display to debugfs
From: Qinxin Xia @ 2026-03-28 10:09 UTC (permalink / raw)
To: robin.murphy, nicolinc, will, jpb
Cc: linux-arm-kernel, iommu, xiaqinxin, wangzhou1, prime.zeng,
fanghao11, jonathan.cameron, wuyifan50, linuxarm
In-Reply-To: <20260328100953.3441915-1-xiaqinxin@huawei.com>
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset="y", Size: 4059 bytes --]
Add register display functionality to debugfs.This allows reading
and displaying key SMMU register values including control registers
and queue pointers.
The registers file shows:
- CR0, CR1, CR2 control registers
- Command and Event queue pointers
Signed-off-by: Qinxin Xia <xiaqinxin@huawei.com>
---
.../arm/arm-smmu-v3/arm-smmu-v3-debugfs.c | 78 ++++++++++++++++++-
1 file changed, 77 insertions(+), 1 deletion(-)
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-debugfs.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-debugfs.c
index c764b28e5cfb..cfd296aebc9f 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-debugfs.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-debugfs.c
@@ -5,13 +5,18 @@
* Directory Structure:
* /sys/kernel/debug/iommu/arm_smmu_v3/
* └── smmu<ioaddr>/
- * └── capabilities # SMMU feature capabilities and configuration
+ * ├── capabilities # SMMU feature capabilities and configuration
+ * └── registers # SMMU Key registers
*
* The capabilities file provides detailed information about:
* - translation stage support (Stage1/Stage2)
* - System coherency, ATS, and PRI feature availability
* - Stream table size and command/event queue depths
*
+ * The registers display provides crucial visibility into:
+ * - CR0, CR1, CR2 control registers
+ * - Command and Event queue pointers
+ *
* Copyright (C) 2026 HiSilicon Limited.
* Author: Qinxin Xia <xiaqinxin@huawei.com>
*/
@@ -89,6 +94,74 @@ static const struct file_operations smmu_debugfs_capabilities_fops = {
.release = smmu_debugfs_capabilities_release,
};
+/**
+ * smmu_debugfs_registers_show() - Display SMMU register values
+ * @seq: seq_file to write to
+ *
+ * Errors are reported via seq_puts, the function always returns 0
+ */
+static int smmu_debugfs_registers_show(struct seq_file *seq, void *unused)
+{
+ struct arm_smmu_device *smmu = seq->private;
+ void __iomem *base;
+
+ if (!smmu || !smmu->base) {
+ seq_puts(seq, "SMMU not available\n");
+ return 0;
+ }
+
+ base = smmu->base;
+
+ seq_puts(seq, "SMMUv3 Key Registers:\n");
+
+ /* 32-bit control registers */
+ seq_printf(seq, "CR0: 0x%08x\n", readl_relaxed(base + ARM_SMMU_CR0));
+ seq_printf(seq, "CR1: 0x%08x\n", readl_relaxed(base + ARM_SMMU_CR1));
+ seq_printf(seq, "CR2: 0x%08x\n", readl_relaxed(base + ARM_SMMU_CR2));
+
+ /* 32-bit queue pointer registers */
+ seq_printf(seq, "CMDQ_PROD: 0x%08x\n",
+ readl_relaxed(base + ARM_SMMU_CMDQ_PROD));
+ seq_printf(seq, "CMDQ_CONS: 0x%08x\n",
+ readl_relaxed(base + ARM_SMMU_CMDQ_CONS));
+ seq_printf(seq, "EVTQ_PROD: 0x%08x\n",
+ readl_relaxed(base + ARM_SMMU_EVTQ_PROD));
+ seq_printf(seq, "EVTQ_CONS: 0x%08x\n",
+ readl_relaxed(base + ARM_SMMU_EVTQ_CONS));
+
+ return 0;
+}
+
+static int smmu_debugfs_registers_open(struct inode *inode, struct file *file)
+{
+ struct arm_smmu_device *smmu = inode->i_private;
+
+ if (!smmu || !get_device(smmu->dev))
+ return -ENODEV;
+
+ return single_open(file, smmu_debugfs_registers_show, smmu);
+}
+
+static int smmu_debugfs_registers_release(struct inode *inode, struct file *file)
+{
+ struct seq_file *seq = file->private_data;
+ struct arm_smmu_device *smmu = seq->private;
+
+ single_release(inode, file);
+ if (smmu)
+ put_device(smmu->dev);
+
+ return 0;
+}
+
+static const struct file_operations smmu_debugfs_registers_fops = {
+ .owner = THIS_MODULE,
+ .open = smmu_debugfs_registers_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = smmu_debugfs_registers_release,
+};
+
/**
* arm_smmu_debugfs_setup() - Initialize debugfs for SMMU device
* @smmu: SMMU device to setup debugfs for
@@ -134,6 +207,9 @@ int arm_smmu_debugfs_setup(struct arm_smmu_device *smmu, const char *name)
debugfs_create_file("capabilities", 0444, smmu_dir, smmu,
&smmu_debugfs_capabilities_fops);
+ debugfs_create_file("registers", 0444, smmu_dir, smmu,
+ &smmu_debugfs_registers_fops);
+
dev_dbg(smmu->dev, "debugfs initialized for %s\n", name);
return 0;
}
--
2.33.0
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox