Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2] soc: fsl: qe: panic on ioremap() failure in qe_reset()
From: Wang Jun @ 2026-03-27  0:12 UTC (permalink / raw)
  To: Qiang Zhao, Christophe Leroy, linuxppc-dev, linux-arm-kernel
  Cc: linux-kernel, gszhai, 25125332, 25125283, 23120469, Wang Jun,
	stable
In-Reply-To: <780c1ba3-6639-478e-896f-e35ec059b58c@kernel.org>

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();
 
-- 
2.43.0



^ permalink raw reply related

* [PATCH v3 0/2] Rockchip DRM use-after-free & null-ptr-deref fixes
From: Cristian Ciocaltea @ 2026-03-27  0:55 UTC (permalink / raw)
  To: Sandy Huang, Heiko Stübner, Andy Yan, Maarten Lankhorst,
	Maxime Ripard, Thomas Zimmermann, David Airlie, Simona Vetter,
	Dmitry Baryshkov, Dmitry Baryshkov, Andrzej Hajda, Neil Armstrong,
	Robert Foss, Laurent Pinchart, Jonas Karlman, Jernej Skrabec
  Cc: kernel, dri-devel, linux-arm-kernel, linux-rockchip, linux-kernel

The first three patches in the series are fixes for use-after-free &
null-ptr-deref related issues found in dw_dp and inno-hdmi Rockchip DRM
drivers.

The following three patches provide a few minor improvements to dw_dp
and dw_hdmi_qp, while the remaining two address use-after-free and
memory allocation in DW DP core library.

Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
---
Changes in v3:
- Dropped patches 1..6,8 already applied by Heiko
- Reworked remaining patch "drm/bridge: synopsys: dw-dp: Unregister AUX
  channel on bridge detach" into:
  * drm/bridge: synopsys: dw-dp: Support unregistering the AUX channel
  * drm/rockchip: dw_dp: Release core resources
- Link to v2: https://lore.kernel.org/r/20260310-drm-rk-fixes-v2-0-645ecfb43f49@collabora.com

Changes in v2:
- Fixed conflicts while rebasing onto latest drm-misc-next
- Added two more patches:
  * drm/bridge: synopsys: dw-dp: Unregister AUX channel on bridge detach
  * drm/bridge: synopsys: dw-dp: Drop useless memory allocation
- Link to v1: https://lore.kernel.org/r/20260122-drm-rk-fixes-v1-0-3942f185750e@collabora.com

---
Cristian Ciocaltea (2):
      drm/bridge: synopsys: dw-dp: Support unregistering the AUX channel
      drm/rockchip: dw_dp: Release core resources

 drivers/gpu/drm/bridge/synopsys/dw-dp.c   |  6 ++++++
 drivers/gpu/drm/rockchip/dw_dp-rockchip.c | 20 +++++++++++++++++---
 include/drm/bridge/dw_dp.h                |  1 +
 3 files changed, 24 insertions(+), 3 deletions(-)
---
base-commit: 46c31e1604d121221167cb09380de8c7d53290b9
change-id: 20260122-drm-rk-fixes-a7622c71553e



^ permalink raw reply

* [PATCH v3 2/2] drm/rockchip: dw_dp: Release core resources
From: Cristian Ciocaltea @ 2026-03-27  0:55 UTC (permalink / raw)
  To: Sandy Huang, Heiko Stübner, Andy Yan, Maarten Lankhorst,
	Maxime Ripard, Thomas Zimmermann, David Airlie, Simona Vetter,
	Dmitry Baryshkov, Dmitry Baryshkov, Andrzej Hajda, Neil Armstrong,
	Robert Foss, Laurent Pinchart, Jonas Karlman, Jernej Skrabec
  Cc: kernel, dri-devel, linux-arm-kernel, linux-rockchip, linux-kernel
In-Reply-To: <20260327-drm-rk-fixes-v3-0-fd2e6900c08c@collabora.com>

Core resources such as the DisplayPort AUX channel get initialized and
registered during dw_dp_bind(), but are never unregistered, which may
lead to memory leaks and/or use-after-free:

[  224.661371] BUG: KASAN: slab-use-after-free in device_is_dependent+0xe0/0x2b0
[  224.662015] Read of size 8 at addr ffff00011aee8550 by task modprobe/658
[  224.662612]
[  224.662752] CPU: 7 UID: 0 PID: 658 Comm: modprobe Not tainted 7.0.0-rc2-next-20260305 #14 PREEMPT
[  224.662759] Hardware name: Radxa ROCK 5B (DT)
[  224.662762] Call trace:
[  224.662764]  show_stack+0x20/0x38 (C)
[  224.662772]  dump_stack_lvl+0x6c/0x98
[  224.662777]  print_report+0x160/0x4b8
[  224.662783]  kasan_report+0xb4/0xe0
[  224.662790]  __asan_report_load8_noabort+0x20/0x30
[  224.662796]  device_is_dependent+0xe0/0x2b0
[  224.662802]  device_is_dependent+0x108/0x2b0
[  224.662808]  device_link_add+0x1f8/0x10b0
[  224.662813]  devm_of_phy_get_by_index+0x120/0x200
[  224.662819]  dw_dp_bind+0x34c/0xb10 [dw_dp]
[  224.662830]  dw_dp_rockchip_bind+0x194/0x250 [rockchipdrm]
[  224.662864]  component_bind_all+0x3a8/0x720
[  224.662869]  rockchip_drm_bind+0x120/0x390 [rockchipdrm]
[  224.662899]  try_to_bring_up_aggregate_device+0x76c/0x838
[  224.662904]  component_master_add_with_match+0x1f4/0x230
[  224.662909]  rockchip_drm_platform_probe+0x420/0x538 [rockchipdrm]
[  224.662939]  platform_probe+0xe8/0x168
[  224.662945]  really_probe+0x340/0x828
[  224.662950]  __driver_probe_device+0x2e0/0x350
[  224.662954]  driver_probe_device+0x80/0x140
[  224.662959]  __driver_attach+0x398/0x460
[  224.662964]  bus_for_each_dev+0xe0/0x198
[  224.662968]  driver_attach+0x50/0x68
[  224.662972]  bus_add_driver+0x2a0/0x4c0
[  224.662977]  driver_register+0x294/0x360
[  224.662982]  __platform_driver_register+0x7c/0x98
[  224.662987]  rockchip_drm_init+0xc4/0xff8 [rockchipdrm]

Since a previous commit exported dw_dp_unbind() function in DW DP core
library to take care of the necessary cleanup, use this in the
component's unbind() callback, as well as in its bind() error path.

Fixes: d68ba7bac955 ("drm/rockchip: Add RK3588 DPTX output support")
Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
---
 drivers/gpu/drm/rockchip/dw_dp-rockchip.c | 20 +++++++++++++++++---
 1 file changed, 17 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/dw_dp-rockchip.c b/drivers/gpu/drm/rockchip/dw_dp-rockchip.c
index 22c0911f1896..8cba90d2dd56 100644
--- a/drivers/gpu/drm/rockchip/dw_dp-rockchip.c
+++ b/drivers/gpu/drm/rockchip/dw_dp-rockchip.c
@@ -108,14 +108,28 @@ static int dw_dp_rockchip_bind(struct device *dev, struct device *master, void *
 
 	connector = drm_bridge_connector_init(drm_dev, encoder);
 	if (IS_ERR(connector))
-		return dev_err_probe(dev, PTR_ERR(connector),
-				     "Failed to init bridge connector");
+		ret = dev_err_probe(dev, PTR_ERR(connector),
+				    "Failed to init bridge connector");
+	else
+		ret = drm_connector_attach_encoder(connector, encoder);
 
-	return drm_connector_attach_encoder(connector, encoder);
+	if (ret)
+		dw_dp_unbind(dp->base);
+
+	return ret;
+}
+
+static void dw_dp_rockchip_unbind(struct device *dev, struct device *master,
+				  void *data)
+{
+	struct rockchip_dw_dp *dp = dev_get_drvdata(dev);
+
+	dw_dp_unbind(dp->base);
 }
 
 static const struct component_ops dw_dp_rockchip_component_ops = {
 	.bind = dw_dp_rockchip_bind,
+	.unbind = dw_dp_rockchip_unbind,
 };
 
 static int dw_dp_probe(struct platform_device *pdev)

-- 
2.52.0



^ permalink raw reply related

* [PATCH v3 1/2] drm/bridge: synopsys: dw-dp: Support unregistering the AUX channel
From: Cristian Ciocaltea @ 2026-03-27  0:55 UTC (permalink / raw)
  To: Sandy Huang, Heiko Stübner, Andy Yan, Maarten Lankhorst,
	Maxime Ripard, Thomas Zimmermann, David Airlie, Simona Vetter,
	Dmitry Baryshkov, Dmitry Baryshkov, Andrzej Hajda, Neil Armstrong,
	Robert Foss, Laurent Pinchart, Jonas Karlman, Jernej Skrabec
  Cc: kernel, dri-devel, linux-arm-kernel, linux-rockchip, linux-kernel
In-Reply-To: <20260327-drm-rk-fixes-v3-0-fd2e6900c08c@collabora.com>

The DisplayPort AUX channel gets initialized and registered during
dw_dp_bind(), but it is never unregistered, which may lead to resource
leaks and/or use-after-free.

Add the missing dw_dp_unbind() function to allow the users of the
library to handle the required cleanup, i.e. unregister the AUX adapter.

Fixes: 86eecc3a9c2e ("drm/bridge: synopsys: Add DW DPTX Controller support library")
Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
---
 drivers/gpu/drm/bridge/synopsys/dw-dp.c | 6 ++++++
 include/drm/bridge/dw_dp.h              | 1 +
 2 files changed, 7 insertions(+)

diff --git a/drivers/gpu/drm/bridge/synopsys/dw-dp.c b/drivers/gpu/drm/bridge/synopsys/dw-dp.c
index 3f4530c117c7..6211ba6ba7bd 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-dp.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-dp.c
@@ -2093,6 +2093,12 @@ struct dw_dp *dw_dp_bind(struct device *dev, struct drm_encoder *encoder,
 }
 EXPORT_SYMBOL_GPL(dw_dp_bind);
 
+void dw_dp_unbind(struct dw_dp *dp)
+{
+	drm_dp_aux_unregister(&dp->aux);
+}
+EXPORT_SYMBOL_GPL(dw_dp_unbind);
+
 MODULE_AUTHOR("Andy Yan <andyshrk@163.com>");
 MODULE_DESCRIPTION("DW DP Core Library");
 MODULE_LICENSE("GPL");
diff --git a/include/drm/bridge/dw_dp.h b/include/drm/bridge/dw_dp.h
index 25363541e69d..22105c3e8e4d 100644
--- a/include/drm/bridge/dw_dp.h
+++ b/include/drm/bridge/dw_dp.h
@@ -24,4 +24,5 @@ struct dw_dp_plat_data {
 
 struct dw_dp *dw_dp_bind(struct device *dev, struct drm_encoder *encoder,
 			 const struct dw_dp_plat_data *plat_data);
+void dw_dp_unbind(struct dw_dp *dp);
 #endif /* __DW_DP__ */

-- 
2.52.0



^ permalink raw reply related

* Re: [PATCH v2 7/8] drm/bridge: synopsys: dw-dp: Unregister AUX channel on bridge detach
From: Cristian Ciocaltea @ 2026-03-27  1:08 UTC (permalink / raw)
  To: Heiko Stuebner, Sandy Huang, Andy Yan, Maarten Lankhorst,
	Maxime Ripard, Thomas Zimmermann, David Airlie, Simona Vetter,
	Dmitry Baryshkov, Dmitry Baryshkov, Andrzej Hajda, Neil Armstrong,
	Robert Foss, Laurent Pinchart, Jonas Karlman, Jernej Skrabec
  Cc: kernel, dri-devel, linux-arm-kernel, linux-rockchip, linux-kernel
In-Reply-To: <2053748.usQuhbGJ8B@phil>

Hello Heiko,

On 3/26/26 9:28 PM, Heiko Stuebner wrote:
> Am Montag, 9. März 2026, 23:44:35 Mitteleuropäische Normalzeit schrieb Cristian Ciocaltea:
>> The DisplayPort AUX channel gets initialized and registered during
>> dw_dp_bind(), but it is never unregistered, which may lead to resource
>> leaks and/or use-after-free:
>>
>> [  224.661371] BUG: KASAN: slab-use-after-free in device_is_dependent+0xe0/0x2b0
>> [  224.662015] Read of size 8 at addr ffff00011aee8550 by task modprobe/658
>> ...
>> [  224.662796]  device_is_dependent+0xe0/0x2b0
>> [  224.662802]  device_is_dependent+0x108/0x2b0
>> [  224.662808]  device_link_add+0x1f8/0x10b0
>> [  224.662813]  devm_of_phy_get_by_index+0x120/0x200
>> [  224.662819]  dw_dp_bind+0x34c/0xb10 [dw_dp]
>> [  224.662830]  dw_dp_rockchip_bind+0x194/0x250 [rockchipdrm]
>> [  224.662864]  component_bind_all+0x3a8/0x720
>> [  224.662869]  rockchip_drm_bind+0x120/0x390 [rockchipdrm]
>> [  224.662899]  try_to_bring_up_aggregate_device+0x76c/0x838
>> [  224.662904]  component_master_add_with_match+0x1f4/0x230
>> [  224.662909]  rockchip_drm_platform_probe+0x420/0x538 [rockchipdrm]
>> [  224.662939]  platform_probe+0xe8/0x168
>> [  224.662945]  really_probe+0x340/0x828
>> [  224.662950]  __driver_probe_device+0x2e0/0x350
>> [  224.662954]  driver_probe_device+0x80/0x140
>> [  224.662959]  __driver_attach+0x398/0x460
>> [  224.662964]  bus_for_each_dev+0xe0/0x198
>> [  224.662968]  driver_attach+0x50/0x68
>> [  224.662972]  bus_add_driver+0x2a0/0x4c0
>> [  224.662977]  driver_register+0x294/0x360
>> [  224.662982]  __platform_driver_register+0x7c/0x98
>> [  224.662987]  rockchip_drm_init+0xc4/0xff8 [rockchipdrm]
>> ...
>>
>> Unregister the AUX adapter on bridge detach.
> 
> that sounds sort of asymmetrical though. drm_bridge_funcs has attach and
> detach callbacks and the component-framework also has bind and unbind
> callbacks.
> 
> This might cause confusion later on I guess, especially as I don't know
> if there could be a bridge attach, after the detach that unregisters the
> aux adapter.
> 
> Looking at the AnalogixDP for example, it does the the register and
> unregister in the bind/unbind callbacks of the core driver.
> 
> So I guess the in my eyes cleaner way would be to introduce a
> dw_dp_unbind() function and put the aux unregister there?
> 
> At least that way, everything would be at the same "level".

You are right.  As a matter of fact exporting the *_unbind() in the library was
my first thought, but for some reason I went with the "auto" approach.

I've just handled this in v3 [1].

Thanks for reviewing and picking the rest of the patches!

Regards,
Cristian

[1] https://lore.kernel.org/all/20260327-drm-rk-fixes-v3-0-fd2e6900c08c@collabora.com/



^ permalink raw reply

* Re: [PATCH net-next v15 0/3] Add support for Nuvoton MA35D1 GMAC
From: patchwork-bot+netdevbpf @ 2026-03-27  1:20 UTC (permalink / raw)
  To: Joey Lu
  Cc: andrew+netdev, davem, edumazet, kuba, pabeni, robh, krzk+dt,
	conor+dt, mcoquelin.stm32, richardcochran, alexandre.torgue,
	joabreu, ychuang3, schung, yclu4, peppe.cavallaro,
	linux-arm-kernel, netdev, devicetree, linux-kernel, openbmc,
	linux-stm32
In-Reply-To: <20260323101756.81849-1-a0987203069@gmail.com>

Hello:

This series was applied to netdev/net-next.git (main)
by Jakub Kicinski <kuba@kernel.org>:

On Mon, 23 Mar 2026 18:17:53 +0800 you wrote:
> This patch series is submitted to add GMAC support for Nuvoton MA35D1
> SoC platform. This work involves implementing a GMAC driver glue layer
> based on Synopsys DWMAC driver framework to leverage MA35D1's dual GMAC
> interface capabilities.
> 
> Overview:
>   1. Added a GMAC driver glue layer for MA35D1 SoC, providing support for
>   the platform's two GMAC interfaces.
>   2. Added device tree settings, with specific configurations for our
>   development boards:
>     a. SOM board: Configured for two RGMII interfaces.
>     b. IoT board: Configured with one RGMII and one RMII interface.
>   3. Added dt-bindings for the GMAC interfaces.
> 
> [...]

Here is the summary with links:
  - [net-next,v15,1/3] dt-bindings: net: nuvoton: Add schema for Nuvoton MA35 family GMAC
    https://git.kernel.org/netdev/net-next/c/8454478ef9ab
  - [net-next,v15,2/3] arm64: dts: nuvoton: Add Ethernet nodes
    (no matching commit)
  - [net-next,v15,3/3] net: stmmac: dwmac-nuvoton: Add dwmac glue for Nuvoton MA35 family
    https://git.kernel.org/netdev/net-next/c/4d7c557f58ef

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html




^ permalink raw reply

* Re: [PATCH 1/2] arm64/entry: Fix involuntary preemption exception masking
From: Jinjie Ruan @ 2026-03-27  1:27 UTC (permalink / raw)
  To: Mark Rutland, Thomas Gleixner
  Cc: vladimir.murzin, peterz, catalin.marinas, linux-kernel, luto,
	will, linux-arm-kernel
In-Reply-To: <acV2552t5X4OlNYi@J2N7QTR9R3>



On 2026/3/27 2:11, Mark Rutland wrote:
> On Wed, Mar 25, 2026 at 04:46:01PM +0100, Thomas Gleixner wrote:
>> On Wed, Mar 25 2026 at 11:03, Mark Rutland wrote:
>>> On Sun, Mar 22, 2026 at 12:25:06AM +0100, Thomas Gleixner wrote:
>>> I *think* what would work for us is we could split some of the exit
>>> handling (including involuntary preemption) into a "prepare" step, as we
>>> have for return to userspace. That way, arm64 could handle exiting
>>> something like:
>>>
>>> 	local_irq_disable();
>>> 	irqentry_exit_prepare(); // new, all generic logic
>>> 	local_daif_mask();
>>> 	arm64_exit_to_kernel_mode() {
>>> 		...
>>> 		irqentry_exit(); // ideally irqentry_exit_to_kernel_mode().
>>> 		...
>>> 	}
>>>
>>> ... and other architectures can use a combined exit_to_kernel_mode() (or
>>> whatever we call that), which does both, e.g.
>>>
>>> 	// either noinstr, __always_inline, or a macro
>>> 	void irqentry_prepare_and_exit(void)
>>
>> That's a bad idea as that would require to do a full kernel rename of
>> all existing irqentry_exit() users.
>>
>>> 	{
>>> 		irqentry_exit_prepare();
>>> 		irqentry_exit();
>>> 	}
>>
>> Aside of the naming that should work.
> 
> Thanks for confirming!
> 
> I've pushed a (very early, WIP) draft to
> 
>   https://git.kernel.org/pub/scm/linux/kernel/git/mark/linux.git/log/?h=arm64/entry/rework

The patch also looks good to me. Looking forward to seeing this move
forward.

> 
> ... which is missing commit messages, comments, etc, but seems to work.
> 
> I'll see about getting that tested, cleaned up, and on-list.
> 
> Mark.
> 


^ permalink raw reply

* Re: [PATCH net-next 0/5] net: stmmac: dwmac-socfpga: Cleanup .fix_mac_speed
From: patchwork-bot+netdevbpf @ 2026-03-27  1:32 UTC (permalink / raw)
  To: Maxime Chevallier
  Cc: andrew, kuba, davem, edumazet, pabeni, horms, mcoquelin.stm32,
	alexandre.torgue, linux, thomas.petazzoni, alexis.lothore,
	rohan.g.thomas, mun.yew.tham, netdev, linux-kernel,
	linux-arm-kernel, linux-stm32
In-Reply-To: <20260324092102.687082-1-maxime.chevallier@bootlin.com>

Hello:

This series was applied to netdev/net-next.git (main)
by Jakub Kicinski <kuba@kernel.org>:

On Tue, 24 Mar 2026 10:20:55 +0100 you wrote:
> Hi everyone,
> 
> This small series does a bit of cleanup in the dwmad-socfpga glue
> driver, especially around the .fix_mac_speed() operation.
> 
> It's mostly about re-using existing helpers from the glue driver, as
> well as reorganizing the code to make the local private structures a
> little bit smaller.
> 
> [...]

Here is the summary with links:
  - [net-next,1/5] net: stmmac: dwmac-socfpga: Move internal helpers
    https://git.kernel.org/netdev/net-next/c/845a04411118
  - [net-next,2/5] net: stmmac: dwmac-socfpga: Use the socfpga_sgmii_config() helper
    https://git.kernel.org/netdev/net-next/c/a7be7cc12442
  - [net-next,3/5] net: stmmac: dwmac-socfpga: Use the correct type for interface modes
    https://git.kernel.org/netdev/net-next/c/9b04ecdfb876
  - [net-next,4/5] net: stmmac: dwmac-socfpga: get the phy_mode with the dedicated helper
    https://git.kernel.org/netdev/net-next/c/adf1536f79a5
  - [net-next,5/5] net: stmmac: dwmac-sofcpga: Drop the struct device reference
    https://git.kernel.org/netdev/net-next/c/9bd1af853750

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html




^ permalink raw reply

* Re: [PATCH net-next v2 4/4] net: phy: Introduce Airoha AN8801/R Gigabit Ethernet PHY driver
From: Jakub Kicinski @ 2026-03-27  1:43 UTC (permalink / raw)
  To: Louis-Alexis Eyraud
  Cc: Andrew Lunn, Andrew Lunn, David S. Miller, Eric Dumazet,
	Paolo Abeni, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	AngeloGioacchino Del Regno, Heiner Kallweit, Russell King,
	kevin-kw.huang, macpaul.lin, matthias.bgg, kernel, netdev,
	devicetree, linux-arm-kernel, linux-mediatek, linux-kernel
In-Reply-To: <3688a285-7f98-4afa-80ad-697094cd7b97@lunn.ch>

On Thu, 26 Mar 2026 13:47:43 +0100 Andrew Lunn wrote:
> > +	if (phydev->link && prev_speed != phydev->speed) {
> > +		val = phydev->speed == SPEED_1000 ?
> > +		      AN8801_BPBUS_LINK_MODE_1000 : 0;
> > +
> > +		return an8801_buckpbus_reg_rmw(phydev,
> > +					       AN8801_BPBUS_REG_LINK_MODE,
> > +					       AN8801_BPBUS_LINK_MODE_1000,
> > +					       val);
> > +	};  
> 
> This is unusual. What is it doing? Please add a comment.

Also - nit spurious ; after if () {}


^ permalink raw reply

* [PATCH 6.1.y 2/3] net: phy: allow MDIO bus PM ops to start/stop state machine for phylink-controlled PHY
From: Rajani Kantha @ 2026-03-27  1:52 UTC (permalink / raw)
  To: gregkh, stable, vladimir.oltean
  Cc: patches, linux-kernel, andrew, hkallweit1, linux, davem, edumazet,
	kuba, pabeni, matthias.bgg, f.fainelli, netdev, linux-arm-kernel,
	linux-mediatek, wei.fang

From: Vladimir Oltean <vladimir.oltean@nxp.com>

[ Upstream commit fc75ea20ffb452652f0d4033f38fe88d7cfdae35 ]

DSA has 2 kinds of drivers:

1. Those who call dsa_switch_suspend() and dsa_switch_resume() from
   their device PM ops: qca8k-8xxx, bcm_sf2, microchip ksz
2. Those who don't: all others. The above methods should be optional.

For type 1, dsa_switch_suspend() calls dsa_user_suspend() -> phylink_stop(),
and dsa_switch_resume() calls dsa_user_resume() -> phylink_start().
These seem good candidates for setting mac_managed_pm = true because
that is essentially its definition [1], but that does not seem to be the
biggest problem for now, and is not what this change focuses on.

Talking strictly about the 2nd category of DSA drivers here (which
do not have MAC managed PM, meaning that for their attached PHYs,
mdio_bus_phy_suspend() and mdio_bus_phy_resume() should run in full),
I have noticed that the following warning from mdio_bus_phy_resume() is
triggered:

	WARN_ON(phydev->state != PHY_HALTED && phydev->state != PHY_READY &&
		phydev->state != PHY_UP);

because the PHY state machine is running.

It's running as a result of a previous dsa_user_open() -> ... ->
phylink_start() -> phy_start() having been initiated by the user.

The previous mdio_bus_phy_suspend() was supposed to have called
phy_stop_machine(), but it didn't. So this is why the PHY is in state
PHY_NOLINK by the time mdio_bus_phy_resume() runs.

mdio_bus_phy_suspend() did not call phy_stop_machine() because for
phylink, the phydev->adjust_link function pointer is NULL. This seems a
technicality introduced by commit fddd91016d16 ("phylib: fix PAL state
machine restart on resume"). That commit was written before phylink
existed, and was intended to avoid crashing with consumer drivers which
don't use the PHY state machine - phylink always does, when using a PHY.
But phylink itself has historically not been developed with
suspend/resume in mind, and apparently not tested too much in that
scenario, allowing this bug to exist unnoticed for so long. Plus, prior
to the WARN_ON(), it would have likely been invisible.

This issue is not in fact restricted to type 2 DSA drivers (according to
the above ad-hoc classification), but can be extrapolated to any MAC
driver with phylink and MDIO-bus-managed PHY PM ops. DSA is just where
the issue was reported. Assuming mac_managed_pm is set correctly, a
quick search indicates the following other drivers might be affected:

$ grep -Zlr PHYLINK_NETDEV drivers/ | xargs -0 grep -L mac_managed_pm
drivers/net/ethernet/atheros/ag71xx.c
drivers/net/ethernet/microchip/sparx5/sparx5_main.c
drivers/net/ethernet/microchip/lan966x/lan966x_main.c
drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c
drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c
drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
drivers/net/ethernet/freescale/ucc_geth.c
drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
drivers/net/ethernet/marvell/mvneta.c
drivers/net/ethernet/marvell/prestera/prestera_main.c
drivers/net/ethernet/mediatek/mtk_eth_soc.c
drivers/net/ethernet/altera/altera_tse_main.c
drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c
drivers/net/ethernet/meta/fbnic/fbnic_phylink.c
drivers/net/ethernet/tehuti/tn40_phy.c
drivers/net/ethernet/mscc/ocelot_net.c

Make the existing conditions dependent on the PHY device having a
phydev->phy_link_change() implementation equal to the default
phy_link_change() provided by phylib. Otherwise, we implicitly know that
the phydev has the phylink-provided phylink_phy_change() callback, and
when phylink is used, the PHY state machine always needs to be stopped/
started on the suspend/resume path. The code is structured as such that
if phydev->phy_link_change() is absent, it is a matter of time until the
kernel will crash - no need to further complicate the test.

Thus, for the situation where the PM is not managed by the MAC, we will
make the MDIO bus PM ops treat identically the phylink-controlled PHYs
with the phylib-controlled PHYs where an adjust_link() callback is
supplied. In both cases, the MDIO bus PM ops should stop and restart the
PHY state machine.

[1] https://lore.kernel.org/netdev/Z-1tiW9zjcoFkhwc@shell.armlinux.org.uk/

Fixes: 744d23c71af3 ("net: phy: Warn about incorrect mdio_bus_phy_resume() state")
Reported-by: Wei Fang <wei.fang@nxp.com>
Tested-by: Wei Fang <wei.fang@nxp.com>
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Link: https://patch.msgid.link/20250407094042.2155633-1-vladimir.oltean@nxp.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Rajani Kantha <681739313@139.com>
---
 drivers/net/phy/phy_device.c | 31 +++++++++++++++++++++++++++++--
 1 file changed, 29 insertions(+), 2 deletions(-)

diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index 7d19857a6dc4..fd49616c6608 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -247,6 +247,33 @@ static void phy_link_change(struct phy_device *phydev, bool up)
 		phydev->mii_ts->link_state(phydev->mii_ts, phydev);
 }
 
+/**
+ * phy_uses_state_machine - test whether consumer driver uses PAL state machine
+ * @phydev: the target PHY device structure
+ *
+ * Ultimately, this aims to indirectly determine whether the PHY is attached
+ * to a consumer which uses the state machine by calling phy_start() and
+ * phy_stop().
+ *
+ * When the PHY driver consumer uses phylib, it must have previously called
+ * phy_connect_direct() or one of its derivatives, so that phy_prepare_link()
+ * has set up a hook for monitoring state changes.
+ *
+ * When the PHY driver is used by the MAC driver consumer through phylink (the
+ * only other provider of a phy_link_change() method), using the PHY state
+ * machine is not optional.
+ *
+ * Return: true if consumer calls phy_start() and phy_stop(), false otherwise.
+ */
+static bool phy_uses_state_machine(struct phy_device *phydev)
+{
+	if (phydev->phy_link_change == phy_link_change)
+		return phydev->attached_dev && phydev->adjust_link;
+
+	/* phydev->phy_link_change is implicitly phylink_phy_change() */
+	return true;
+}
+
 static bool mdio_bus_phy_may_suspend(struct phy_device *phydev)
 {
 	struct device_driver *drv = phydev->mdio.dev.driver;
@@ -307,7 +334,7 @@ static __maybe_unused int mdio_bus_phy_suspend(struct device *dev)
 	 * may call phy routines that try to grab the same lock, and that may
 	 * lead to a deadlock.
 	 */
-	if (phydev->attached_dev && phydev->adjust_link)
+	if (phy_uses_state_machine(phydev))
 		phy_stop_machine(phydev);
 
 	if (!mdio_bus_phy_may_suspend(phydev))
@@ -361,7 +388,7 @@ static __maybe_unused int mdio_bus_phy_resume(struct device *dev)
 		}
 	}
 
-	if (phydev->attached_dev && phydev->adjust_link)
+	if (phy_uses_state_machine(phydev))
 		phy_start_machine(phydev);
 
 	return 0;
-- 
2.34.1




^ permalink raw reply related

* [PATCH] ARM: dts: aspeed: g6: Add missing uart nodes
From: Jammy Huang @ 2026-03-27  1:58 UTC (permalink / raw)
  To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Joel Stanley,
	Andrew Jeffery
  Cc: devicetree, linux-arm-kernel, linux-aspeed, linux-kernel,
	Jammy Huang

Add nodes for uart10/11/12/13.

Signed-off-by: Jammy Huang <jammy_huang@aspeedtech.com>
---
 arch/arm/boot/dts/aspeed/aspeed-g6.dtsi | 56 +++++++++++++++++++++++++++++++++
 1 file changed, 56 insertions(+)

diff --git a/arch/arm/boot/dts/aspeed/aspeed-g6.dtsi b/arch/arm/boot/dts/aspeed/aspeed-g6.dtsi
index 189bc3bbb47..0ffe386fa9d 100644
--- a/arch/arm/boot/dts/aspeed/aspeed-g6.dtsi
+++ b/arch/arm/boot/dts/aspeed/aspeed-g6.dtsi
@@ -835,6 +835,62 @@ uart9: serial@1e790300 {
 				status = "disabled";
 			};
 
+			uart10: serial@1e790400 {
+				compatible = "ns16550a";
+				reg = <0x1e790400 0x20>;
+				reg-shift = <2>;
+				reg-io-width = <4>;
+				interrupts = <GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&syscon ASPEED_CLK_GATE_UART10CLK>;
+				no-loopback-test;
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_uart10_default>;
+
+				status = "disabled";
+			};
+
+			uart11: serial@1e790500 {
+				compatible = "ns16550a";
+				reg = <0x1e790500 0x20>;
+				reg-shift = <2>;
+				reg-io-width = <4>;
+				interrupts = <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&syscon ASPEED_CLK_GATE_UART11CLK>;
+				no-loopback-test;
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_uart11_default>;
+
+				status = "disabled";
+			};
+
+			uart12: serial@1e790600 {
+				compatible = "ns16550a";
+				reg = <0x1e790600 0x20>;
+				reg-shift = <2>;
+				reg-io-width = <4>;
+				interrupts = <GIC_SPI 63 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&syscon ASPEED_CLK_GATE_UART12CLK>;
+				no-loopback-test;
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_uart12g1_default>;
+
+				status = "disabled";
+			};
+
+			uart13: serial@1e790700 {
+				compatible = "ns16550a";
+				reg = <0x1e790700 0x20>;
+				reg-shift = <2>;
+				reg-io-width = <4>;
+				interrupts = <GIC_SPI 64 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&syscon ASPEED_CLK_GATE_UART13CLK>;
+				no-loopback-test;
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_uart13g1_default>;
+
+				status = "disabled";
+			};
+
 			i2c: bus@1e78a000 {
 				compatible = "simple-bus";
 				#address-cells = <1>;

---
base-commit: 5ee8dbf54602dc340d6235b1d6aa17c0f283f48c
change-id: 20260327-upstream_g6_dts_uart-78a5ce3b2873

Best regards,
-- 
Jammy Huang <jammy_huang@aspeedtech.com>



^ permalink raw reply related

* Re: [PATCH v1 00/10] devfreq: Fix NULL pointer dereference when a governor module is unloaded
From: Yaxiong Tian @ 2026-03-27  2:06 UTC (permalink / raw)
  To: Jie Zhan, cw00.choi, myungjoo.ham, kyungmin.park
  Cc: linux-pm, linux-arm-kernel, linuxarm, jonathan.cameron,
	zhenglifeng1, zhangpengjie2, lihuisong, prime.zeng
In-Reply-To: <1774576755240654.100.seg@mailgw.kylinos.cn>


在 2026/3/26 21:14, Jie Zhan 写道:
>
> On 3/26/2026 8:34 PM, Jie Zhan wrote:
>> When compiled as a kernel module, the governor module can be dynamically
>> inserted or removed.  'devfreq->governor' would become NULL if the governor
>> module is removed when it's in use, and NULL pointer dereference would be
>> triggered.  A similar issue was also reported in [1].
>>
>> To address this issue:
>>
>> Patch 1-5 rework mutex, factor out a common governor setting function, and
>> clean up some unreachable code.
>>
>> Patch 6-8 prevent a governor module in use from being removed (except for
>> force unload) by getting/putting a refcount of the governor's module when
>> switching governors.
>>
>> Patch 9-10 allow 'governor' and 'available_governors' to work normally even
>> when a governor module in use is force unloaded.
>>
>> Note that this series is based on [1] or devfreq-next, otherwise code

Sorry, please ignore the "remember to CC me on the patches." in my 
previous email.

  In my opinion, it would be better to prioritize the FIX first before 
proceeding with the lock mechanism optimizations and other work. This 
would make it easier to backport the patches to lower-version kernels. I 
noticed the patch is already in the devfreq-testing branch. I hope the 
FIX work can be moved forward smoothly to resolve the null pointer and 
other bugs. Thank you!



> sorry, based on [2] or devfreq-next
>> would conflict.
>>
>> [1] https://lore.kernel.org/all/20260319091409.998397-1-tianyaxiong@kylinos.cn/
>> [2] https://lore.kernel.org/all/20251216031153.2242306-1-zhangpengjie2@huawei.com/


^ permalink raw reply

* RE: [PATCH v3 net-next 02/14] dt-bindings: net: dsa: add NETC switch
From: Wei Fang @ 2026-03-27  2:09 UTC (permalink / raw)
  To: Frank Li
  Cc: Claudiu Manoil, Vladimir Oltean, Clark Wang,
	andrew+netdev@lunn.ch, davem@davemloft.net, edumazet@google.com,
	kuba@kernel.org, pabeni@redhat.com, robh@kernel.org,
	krzk+dt@kernel.org, conor+dt@kernel.org, f.fainelli@gmail.com,
	chleroy@kernel.org, horms@kernel.org, linux@armlinux.org.uk,
	andrew@lunn.ch, netdev@vger.kernel.org,
	linux-kernel@vger.kernel.org, devicetree@vger.kernel.org,
	linuxppc-dev@lists.ozlabs.org,
	linux-arm-kernel@lists.infradead.org, imx@lists.linux.dev
In-Reply-To: <acWR0QwRSnupmCvI@lizhi-Precision-Tower-5810>

> On Thu, Mar 26, 2026 at 02:29:05PM +0800, Wei Fang wrote:
> > Add bindings for NETC switch. This switch is a PCIe function of NETC
> > IP, it supports advanced QoS with 8 traffic classes and 4 drop
> > resilience levels, and a full range of  TSN standards capabilities.
> > The switch CPU
> 
> Nit: double space before TSN.

Thanks for catching this, I will fix it.

> 
> > port connects to an internal ENETC port, which is also a PCIe function
> > of NETC IP. So these two ports use a light-weight "pseudo MAC" instead
> > of a back-to-back MAC, because the "pseudo MAC" provides the
> > delineation between switch and ENETC, this translates to lower power
> > (less logic and
> 
> what's means "this translates", do you means "this help reduce power and
> latency."

This sentence is excerpted from the NETC Block Guide. It is equivalent to
"it means".

> 
> > memory) and lower delay (as there is no serialization delay across
> > this link).
> >
> > Signed-off-by: Wei Fang <wei.fang@nxp.com>
> > ---
> >  .../bindings/net/dsa/nxp,netc-switch.yaml     | 130 ++++++++++++++++++
> >  1 file changed, 130 insertions(+)
> >  create mode 100644
> > Documentation/devicetree/bindings/net/dsa/nxp,netc-switch.yaml
> >
> > diff --git
> > a/Documentation/devicetree/bindings/net/dsa/nxp,netc-switch.yaml
> > b/Documentation/devicetree/bindings/net/dsa/nxp,netc-switch.yaml
> > new file mode 100644
> > index 000000000000..e34a4e3504c3
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/net/dsa/nxp,netc-switch.yaml
> > @@ -0,0 +1,130 @@
> > +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) %YAML 1.2
> > +---
> > +$id: http://devicetree.org/schemas/net/dsa/nxp,netc-switch.yaml#
> > +$schema: http://devicetree.org/meta-schemas/core.yaml#
> > +
> > +title: NETC Switch family
> > +
> > +description:
> 
> Nit use ">" for multi paragraph.

Okay, I suppose I also need to add '>' to the below description of
"dsa,member" property.

> 
> others look good
> 
> Reviewed-by: Frank Li <Frank.Li@nxp.com>
> 
> > +  The NETC presents itself as a multi-function PCIe Root Complex
> > + Integrated  Endpoint (RCiEP) and provides full 802.1Q Ethernet
> > + switch functionality,  advanced QoS with 8 traffic classes and 4
> > + drop resilience levels, and a  full range of TSN standards capabilities.
> > +
> > +  The CPU port of the switch connects to an internal ENETC. The
> > + switch and  the internal ENETC are fully integrated into the NETC
> > + IP, a back-to-back  MAC is not required. Instead, a light-weight
> > + "pseudo MAC" provides the  delineation between the switch and ENETC.
> > + This translates to lower power  (less logic and memory) and lower
> > + delay (as there is no serialization  delay across this link).
> > +
> > +maintainers:
> > +  - Wei Fang <wei.fang@nxp.com>
> > +
> > +properties:
> > +  compatible:
> > +    enum:
> > +      - pci1131,eef2
> > +
> > +  reg:
> > +    maxItems: 1
> > +
> > +  dsa,member:
> > +    description:
> > +      The property indicates DSA cluster and switch index. For NETC switch,
> > +      the valid range of the switch index is 1 ~ 7, the index is reflected
> > +      in the switch tag as an indication of the switch ID where the frame
> > +      originated. The value 0 is reserved for ENETC VEPA switch, whose ID
> > +      is hardwired to zero.
> > +
> > +$ref: dsa.yaml#
> > +
> > +patternProperties:
> > +  "^(ethernet-)?ports$":
> > +    type: object
> > +    additionalProperties: true
> > +    patternProperties:
> > +      "^(ethernet-)?port@[0-9a-f]$":
> > +        type: object
> > +
> > +        $ref: dsa-port.yaml#
> > +
> > +        properties:
> > +          clocks:
> > +            items:
> > +              - description: MAC transmit/receive reference clock.
> > +
> > +          clock-names:
> > +            items:
> > +              - const: ref
> > +
> > +          mdio:
> > +            $ref: /schemas/net/mdio.yaml#
> > +            unevaluatedProperties: false
> > +            description:
> > +              Optional child node for switch port, otherwise use NETC
> EMDIO.
> > +
> > +        unevaluatedProperties: false
> > +
> > +required:
> > +  - compatible
> > +  - reg
> > +  - dsa,member
> > +
> > +allOf:
> > +  - $ref: /schemas/pci/pci-device.yaml
> > +
> > +unevaluatedProperties: false
> > +
> > +examples:
> > +  - |
> > +    pcie {
> > +        #address-cells = <3>;
> > +        #size-cells = <2>;
> > +
> > +        ethernet-switch@0,2 {
> > +            compatible = "pci1131,eef2";
> > +            reg = <0x200 0 0 0 0>;
> > +            dsa,member = <0 1>;
> > +            pinctrl-names = "default";
> > +            pinctrl-0 = <&pinctrl_switch>;
> > +
> > +            ports {
> > +                #address-cells = <1>;
> > +                #size-cells = <0>;
> > +
> > +                port@0 {
> > +                    reg = <0>;
> > +                    phy-handle = <&ethphy0>;
> > +                    phy-mode = "mii";
> > +                };
> > +
> > +                port@1 {
> > +                    reg = <1>;
> > +                    phy-handle = <&ethphy1>;
> > +                    phy-mode = "mii";
> > +                };
> > +
> > +                port@2 {
> > +                    reg = <2>;
> > +                    clocks = <&scmi_clk 103>;
> > +                    clock-names = "ref";
> > +                    phy-handle = <&ethphy2>;
> > +                    phy-mode = "rgmii-id";
> > +                };
> > +
> > +                port@3 {
> > +                    reg = <3>;
> > +                    ethernet = <&enetc3>;
> > +                    phy-mode = "internal";
> > +
> > +                    fixed-link {
> > +                        speed = <2500>;
> > +                        full-duplex;
> > +                        pause;
> > +                    };
> > +                };
> > +            };
> > +        };
> > +    };
> > --
> > 2.34.1
> >


^ permalink raw reply

* Re: [PATCH net] net: ethernet: mtk_ppe: avoid NULL deref when gmac0 is disabled
From: patchwork-bot+netdevbpf @ 2026-03-27  2:10 UTC (permalink / raw)
  To: Sven Eckelmann
  Cc: nbd, lorenzo, andrew+netdev, davem, edumazet, kuba, pabeni,
	matthias.bgg, angelogioacchino.delregno, eladwf, netdev,
	linux-kernel, linux-arm-kernel, linux-mediatek, stable
In-Reply-To: <20260324-wed-crash-gmac0-disabled-v1-1-3bc388aee565@simonwunderlich.de>

Hello:

This patch was applied to netdev/net.git (main)
by Jakub Kicinski <kuba@kernel.org>:

On Tue, 24 Mar 2026 09:36:01 +0100 you wrote:
> If the gmac0 is disabled, the precheck for a valid ingress device will
> cause a NULL pointer deref and crash the system. This happens because
> eth->netdev[0] will be NULL but the code will directly try to access
> netdev_ops.
> 
> Instead of just checking for the first net_device, it must be checked if
> any of the mtk_eth net_devices is matching the netdev_ops of the ingress
> device.
> 
> [...]

Here is the summary with links:
  - [net] net: ethernet: mtk_ppe: avoid NULL deref when gmac0 is disabled
    https://git.kernel.org/netdev/net/c/976ff48c2ac6

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html




^ permalink raw reply

* Re: [PATCH v12 2/7] qcom-tgu: Add TGU driver
From: Jie Gan @ 2026-03-27  2:16 UTC (permalink / raw)
  To: Songwei Chai, andersson, alexander.shishkin, mike.leach,
	konrad.dybcio, suzuki.poulose, james.clark, krzk+dt, conor+dt
  Cc: linux-kernel, linux-arm-kernel, linux-arm-msm, coresight,
	devicetree, gregkh
In-Reply-To: <20260317032639.2393221-3-songwei.chai@oss.qualcomm.com>



On 3/17/2026 11:26 AM, Songwei Chai wrote:
> Add driver to support device TGU (Trigger Generation Unit).
> TGU is a Data Engine which can be utilized to sense a plurality of
> signals and create a trigger into the CTI or generate interrupts to
> processors. Add probe/enable/disable functions for tgu.
> 
> Signed-off-by: Songwei Chai <songwei.chai@oss.qualcomm.com>
> ---
>   .../ABI/testing/sysfs-bus-amba-devices-tgu    |   9 +
>   drivers/Makefile                              |   1 +
>   drivers/hwtracing/Kconfig                     |   2 +
>   drivers/hwtracing/qcom/Kconfig                |  18 ++
>   drivers/hwtracing/qcom/Makefile               |   3 +
>   drivers/hwtracing/qcom/tgu.c                  | 183 ++++++++++++++++++
>   drivers/hwtracing/qcom/tgu.h                  |  51 +++++
>   7 files changed, 267 insertions(+)
>   create mode 100644 Documentation/ABI/testing/sysfs-bus-amba-devices-tgu
>   create mode 100644 drivers/hwtracing/qcom/Kconfig
>   create mode 100644 drivers/hwtracing/qcom/Makefile
>   create mode 100644 drivers/hwtracing/qcom/tgu.c
>   create mode 100644 drivers/hwtracing/qcom/tgu.h
> 
> diff --git a/Documentation/ABI/testing/sysfs-bus-amba-devices-tgu b/Documentation/ABI/testing/sysfs-bus-amba-devices-tgu
> new file mode 100644
> index 000000000000..ead237bb7d89
> --- /dev/null
> +++ b/Documentation/ABI/testing/sysfs-bus-amba-devices-tgu
> @@ -0,0 +1,9 @@
> +What:		/sys/bus/amba/devices/<tgu-name>/enable_tgu
> +Date:		March 2026
> +KernelVersion	7.1
> +Contact:	Jinlong Mao <jinlong.mao@oss.qualcomm.com>, Songwei Chai <songwei.chai@oss.qualcomm.com>
> +Description:
> +		(RW) Set/Get the enable/disable status of TGU
> +		Accepts only one of the 2 values -  0 or 1.
> +		0 : disable TGU.
> +		1 : enable TGU.
> diff --git a/drivers/Makefile b/drivers/Makefile
> index 53fbd2e0acdd..82b712a12a26 100644
> --- a/drivers/Makefile
> +++ b/drivers/Makefile
> @@ -177,6 +177,7 @@ obj-$(CONFIG_RAS)		+= ras/
>   obj-$(CONFIG_USB4)		+= thunderbolt/
>   obj-$(CONFIG_CORESIGHT)		+= hwtracing/coresight/
>   obj-y				+= hwtracing/intel_th/
> +obj-y				+= hwtracing/qcom/
>   obj-$(CONFIG_STM)		+= hwtracing/stm/
>   obj-$(CONFIG_HISI_PTT)		+= hwtracing/ptt/
>   obj-y				+= android/
> diff --git a/drivers/hwtracing/Kconfig b/drivers/hwtracing/Kconfig
> index 911ee977103c..8a640218eed8 100644
> --- a/drivers/hwtracing/Kconfig
> +++ b/drivers/hwtracing/Kconfig
> @@ -7,4 +7,6 @@ source "drivers/hwtracing/intel_th/Kconfig"
>   
>   source "drivers/hwtracing/ptt/Kconfig"
>   
> +source "drivers/hwtracing/qcom/Kconfig"
> +
>   endmenu
> diff --git a/drivers/hwtracing/qcom/Kconfig b/drivers/hwtracing/qcom/Kconfig
> new file mode 100644
> index 000000000000..d6f6d4b0f28e
> --- /dev/null
> +++ b/drivers/hwtracing/qcom/Kconfig
> @@ -0,0 +1,18 @@
> +# SPDX-License-Identifier: GPL-2.0-only
> +#
> +# QCOM specific hwtracing drivers
> +#
> +menu "Qualcomm specific hwtracing drivers"
> +
> +config QCOM_TGU
> +	tristate "QCOM Trigger Generation Unit driver"
> +	help
> +	  This driver provides support for Trigger Generation Unit that is
> +	  used to detect patterns or sequences on a given set of signals.
> +	  TGU is used to monitor a particular bus within a given region to
> +	  detect illegal transaction sequences or slave responses. It is also
> +	  used to monitor a data stream to detect protocol violations and to
> +	  provide a trigger point for centering data around a specific event
> +	  within the trace data buffer.
> +
> +endmenu
> diff --git a/drivers/hwtracing/qcom/Makefile b/drivers/hwtracing/qcom/Makefile
> new file mode 100644
> index 000000000000..5a0a868c1ea0
> --- /dev/null
> +++ b/drivers/hwtracing/qcom/Makefile
> @@ -0,0 +1,3 @@
> +# SPDX-License-Identifier: GPL-2.0
> +
> +obj-$(CONFIG_QCOM_TGU) += tgu.o
> diff --git a/drivers/hwtracing/qcom/tgu.c b/drivers/hwtracing/qcom/tgu.c
> new file mode 100644
> index 000000000000..58c19f12f3d7
> --- /dev/null
> +++ b/drivers/hwtracing/qcom/tgu.c
> @@ -0,0 +1,183 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
> + */
> +
> +#include <linux/amba/bus.h>
> +#include <linux/device.h>
> +#include <linux/err.h>
> +#include <linux/io.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/pm_runtime.h>
> +
> +#include "tgu.h"
> +
> +static void tgu_write_all_hw_regs(struct tgu_drvdata *drvdata)
> +{
> +	TGU_UNLOCK(drvdata->base);
> +	/* Enable TGU to program the triggers */
> +	writel(1, drvdata->base + TGU_CONTROL);
> +	TGU_LOCK(drvdata->base);
> +}
> +
> +static int tgu_enable(struct device *dev)
> +{
> +	struct tgu_drvdata *drvdata = dev_get_drvdata(dev);
> +
> +	guard(spinlock)(&drvdata->lock);
> +	if (drvdata->enabled)
> +		return -EBUSY;
> +
> +	tgu_write_all_hw_regs(drvdata);
> +	drvdata->enabled = true;
> +
> +	return 0;
> +}
> +
> +static void tgu_do_disable(struct tgu_drvdata *drvdata)
> +{
> +	TGU_UNLOCK(drvdata->base);
> +	writel(0, drvdata->base + TGU_CONTROL);
> +	TGU_LOCK(drvdata->base);
> +
> +	drvdata->enabled = false;
> +}
> +
> +static void tgu_disable(struct device *dev)
> +{
> +	struct tgu_drvdata *drvdata = dev_get_drvdata(dev);
> +
> +	guard(spinlock)(&drvdata->lock);
> +	if (!drvdata->enabled)
> +		return;
> +
> +	tgu_do_disable(drvdata);
> +}
> +
> +static ssize_t enable_tgu_show(struct device *dev,
> +			       struct device_attribute *attr, char *buf)
> +{
> +	struct tgu_drvdata *drvdata = dev_get_drvdata(dev);
> +	bool enabled;
> +
> +	guard(spinlock)(&drvdata->lock);
> +	enabled = drvdata->enabled;
> +
> +	return sysfs_emit(buf, "%d\n", !!enabled);
> +}
> +
> +/* enable_tgu_store - Configure Trace and Gating Unit (TGU) triggers. */
> +static ssize_t enable_tgu_store(struct device *dev,
> +				struct device_attribute *attr,
> +				const char *buf,
> +				size_t size)
> +{
> +	unsigned long val;
> +	int ret;
> +
> +	ret = kstrtoul(buf, 0, &val);
> +	if (ret || val > 1)
> +		return -EINVAL;
> +
> +	if (val) {
> +		ret = pm_runtime_resume_and_get(dev);
> +		if (ret)
> +			return ret;
> +		ret = tgu_enable(dev);
> +		if (ret) {
> +			pm_runtime_put(dev);
> +			return ret;
> +		}
> +	} else {
> +		tgu_disable(dev);
> +		pm_runtime_put(dev);

Sorry I didnt observe this issue with my previous check.

echo 0 to the disabled device will result in the pm_runtime reference 
number goes to negative. We dont need pm_runtime_put(dev) when we try to 
disable a diabled device.

Thanks,
Jie

> +	}
> +
> +	return size;
> +}
> +static DEVICE_ATTR_RW(enable_tgu);
> +
> +static struct attribute *tgu_common_attrs[] = {
> +	&dev_attr_enable_tgu.attr,
> +	NULL,
> +};
> +
> +static const struct attribute_group tgu_common_grp = {
> +	.attrs = tgu_common_attrs,
> +	NULL,
> +};
> +
> +static const struct attribute_group *tgu_attr_groups[] = {
> +	&tgu_common_grp,
> +	NULL,
> +};
> +
> +static int tgu_probe(struct amba_device *adev, const struct amba_id *id)
> +{
> +	struct device *dev = &adev->dev;
> +	struct tgu_drvdata *drvdata;
> +	int ret;
> +
> +	drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
> +	if (!drvdata)
> +		return -ENOMEM;
> +
> +	drvdata->dev = &adev->dev;
> +	dev_set_drvdata(dev, drvdata);
> +
> +	drvdata->base = devm_ioremap_resource(dev, &adev->res);
> +	if (IS_ERR(drvdata->base))
> +		return PTR_ERR(drvdata->base);
> +
> +	spin_lock_init(&drvdata->lock);
> +
> +	ret = sysfs_create_groups(&dev->kobj, tgu_attr_groups);
> +	if (ret) {
> +		dev_err(dev, "failed to create sysfs groups: %d\n", ret);
> +		return ret;
> +	}
> +
> +	drvdata->enabled = false;
> +
> +	pm_runtime_put(&adev->dev);
> +
> +	return 0;
> +}
> +
> +static void tgu_remove(struct amba_device *adev)
> +{
> +	struct device *dev = &adev->dev;
> +
> +	sysfs_remove_groups(&dev->kobj, tgu_attr_groups);
> +
> +	tgu_disable(dev);
> +}
> +
> +static const struct amba_id tgu_ids[] = {
> +	{
> +		.id = 0x000f0e00,
> +		.mask = 0x000fffff,
> +	},
> +	{ 0, 0, NULL },
> +};
> +
> +MODULE_DEVICE_TABLE(amba, tgu_ids);
> +
> +static struct amba_driver tgu_driver = {
> +	.drv = {
> +		.name = "qcom-tgu",
> +		.suppress_bind_attrs = true,
> +	},
> +	.probe = tgu_probe,
> +	.remove = tgu_remove,
> +	.id_table = tgu_ids,
> +};
> +
> +module_amba_driver(tgu_driver);
> +
> +MODULE_AUTHOR("Songwei Chai <songwei.chai@oss.qualcomm.com>");
> +MODULE_AUTHOR("Jinlong Mao <jinlong.mao@oss.qualcomm.com>");
> +MODULE_DESCRIPTION("Qualcomm Trigger Generation Unit driver");
> +MODULE_LICENSE("GPL");
> diff --git a/drivers/hwtracing/qcom/tgu.h b/drivers/hwtracing/qcom/tgu.h
> new file mode 100644
> index 000000000000..dd7533b9d735
> --- /dev/null
> +++ b/drivers/hwtracing/qcom/tgu.h
> @@ -0,0 +1,51 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
> + */
> +
> +#ifndef _QCOM_TGU_H
> +#define _QCOM_TGU_H
> +
> +/* Register addresses */
> +#define TGU_CONTROL		0x0000
> +#define TGU_LAR		0xfb0
> +#define TGU_UNLOCK_OFFSET	0xc5acce55
> +
> +static inline void TGU_LOCK(void __iomem *addr)
> +{
> +	do {
> +		/* Wait for things to settle */
> +		mb();
> +		writel_relaxed(0x0, addr + TGU_LAR);
> +	} while (0);
> +}
> +
> +static inline void TGU_UNLOCK(void __iomem *addr)
> +{
> +	do {
> +		writel_relaxed(TGU_UNLOCK_OFFSET, addr + TGU_LAR);
> +		/* Make sure everyone has seen this */
> +		mb();
> +	} while (0);
> +}
> +
> +/**
> + * struct tgu_drvdata - Data structure for a TGU (Trigger Generator Unit)
> + * @base: Memory-mapped base address of the TGU device
> + * @dev: Pointer to the associated device structure
> + * @lock: Spinlock for handling concurrent access to private data
> + * @enabled: Flag indicating whether the TGU device is enabled
> + *
> + * This structure defines the data associated with a TGU device,
> + * including its base address, device pointers, clock, spinlock for
> + * synchronization, trigger data pointers, maximum limits for various
> + * trigger-related parameters, and enable status.
> + */
> +struct tgu_drvdata {
> +	void __iomem *base;
> +	struct device *dev;
> +	spinlock_t lock;
> +	bool enabled;
> +};
> +
> +#endif



^ permalink raw reply

* Re: [PATCH v12 7/7] qcom-tgu: Add reset node to initialize
From: Jie Gan @ 2026-03-27  2:26 UTC (permalink / raw)
  To: Songwei Chai, andersson, alexander.shishkin, mike.leach,
	konrad.dybcio, suzuki.poulose, james.clark, krzk+dt, conor+dt
  Cc: linux-kernel, linux-arm-kernel, linux-arm-msm, coresight,
	devicetree, gregkh
In-Reply-To: <20260317032639.2393221-8-songwei.chai@oss.qualcomm.com>



On 3/17/2026 11:26 AM, Songwei Chai wrote:
> Add reset node to initialize the value of
> priority/condition_decode/condition_select/timer/counter nodes.
> 
> Signed-off-by: Songwei Chai <songwei.chai@oss.qualcomm.com>
> ---
>   .../ABI/testing/sysfs-bus-amba-devices-tgu    |  7 ++
>   drivers/hwtracing/qcom/tgu.c                  | 77 +++++++++++++++++++
>   2 files changed, 84 insertions(+)
> 
> diff --git a/Documentation/ABI/testing/sysfs-bus-amba-devices-tgu b/Documentation/ABI/testing/sysfs-bus-amba-devices-tgu
> index 5370882333bc..1dcb8fb71cd9 100644
> --- a/Documentation/ABI/testing/sysfs-bus-amba-devices-tgu
> +++ b/Documentation/ABI/testing/sysfs-bus-amba-devices-tgu
> @@ -42,3 +42,10 @@ KernelVersion	7.1
>   Contact:	Jinlong Mao <jinlong.mao@oss.qualcomm.com>, Songwei Chai <songwei.chai@oss.qualcomm.com>
>   Description:
>   		(RW) Set/Get the counter value with specific step for TGU.
> +
> +What:		/sys/bus/amba/devices/<tgu-name>/reset_tgu
> +Date:		March 2026
> +KernelVersion	7.1
> +Contact:	Jinlong Mao <jinlong.mao@oss.qualcomm.com>, Songwei Chai <songwei.chai@oss.qualcomm.com>
> +Description:
> +		(Write) Write 1 to reset the dataset for TGU.
> diff --git a/drivers/hwtracing/qcom/tgu.c b/drivers/hwtracing/qcom/tgu.c
> index 4539415571f6..e28e6d27cf56 100644
> --- a/drivers/hwtracing/qcom/tgu.c
> +++ b/drivers/hwtracing/qcom/tgu.c
> @@ -410,8 +410,85 @@ static ssize_t enable_tgu_store(struct device *dev,
>   }
>   static DEVICE_ATTR_RW(enable_tgu);
>   
> +/* reset_tgu_store - Reset Trace and Gating Unit (TGU) configuration. */
> +static ssize_t reset_tgu_store(struct device *dev,
> +			       struct device_attribute *attr, const char *buf,
> +			       size_t size)
> +{
> +	struct tgu_drvdata *drvdata = dev_get_drvdata(dev);
> +	struct value_table *vt = drvdata->value_table;
> +	u32 *cond_decode = drvdata->value_table->condition_decode;
> +	bool need_pm_put = false;
> +	unsigned long value;
> +	int i, j, ret;
> +
> +	if (kstrtoul(buf, 0, &value) || value != 1)
> +		return -EINVAL;
> +
> +	spin_lock(&drvdata->lock);
> +	if (!drvdata->enabled) {
> +		spin_unlock(&drvdata->lock);
> +		ret = pm_runtime_resume_and_get(drvdata->dev);
> +		if (ret)
> +			return ret;
> +		need_pm_put = true;
> +		spin_lock(&drvdata->lock);
> +	}
> +
> +	tgu_do_disable(drvdata);

need_pm_put flag is not set when reset a enabled device. I think we also 
need do pm_runtime_put after we did tgu_do_disable for an enabled device 
because we have pm_runtime_resume_and_get while enabling it.

Thanks,
Jie

> +
> +	if (vt->priority) {
> +		size_t size = MAX_PRIORITY * drvdata->num_step *
> +				drvdata->num_reg * sizeof(unsigned int);
> +		memset(vt->priority, 0, size);
> +	}
> +
> +	if (vt->condition_decode) {
> +		size_t size = drvdata->num_condition_decode *
> +			      drvdata->num_step * sizeof(unsigned int);
> +		memset(vt->condition_decode, 0, size);
> +	}
> +
> +	/* Initialize all condition registers to NOT(value=0x1000000) */
> +	for (i = 0; i < drvdata->num_step; i++) {
> +		for (j = 0; j < drvdata->num_condition_decode; j++) {
> +			cond_decode[calculate_array_location(drvdata, i,
> +			TGU_CONDITION_DECODE, j)] = 0x1000000;
> +		}
> +	}
> +
> +	if (vt->condition_select) {
> +		size_t size = drvdata->num_condition_select *
> +			      drvdata->num_step * sizeof(unsigned int);
> +		memset(vt->condition_select, 0, size);
> +	}
> +
> +	if (vt->timer) {
> +		size_t size = (drvdata->num_step) * (drvdata->num_timer) *
> +				sizeof(unsigned int);
> +		memset(vt->timer, 0, size);
> +	}
> +
> +	if (vt->counter) {
> +		size_t size = (drvdata->num_step) * (drvdata->num_counter) *
> +			      sizeof(unsigned int);
> +		memset(vt->counter, 0, size);
> +	}
> +
> +	spin_unlock(&drvdata->lock);
> +
> +	dev_dbg(dev, "Qualcomm-TGU reset complete\n");
> +
> +	if (need_pm_put)
> +		pm_runtime_put(drvdata->dev);
> +
> +	return size;
> +}
> +static DEVICE_ATTR_WO(reset_tgu);
> +
>   static struct attribute *tgu_common_attrs[] = {
>   	&dev_attr_enable_tgu.attr,
> +	&dev_attr_reset_tgu.attr,
>   	NULL,
>   };
>   



^ permalink raw reply

* Re: [PATCH v12 2/7] qcom-tgu: Add TGU driver
From: Jie Gan @ 2026-03-27  2:35 UTC (permalink / raw)
  To: Songwei Chai, andersson, alexander.shishkin, mike.leach,
	konrad.dybcio, suzuki.poulose, james.clark, krzk+dt, conor+dt
  Cc: linux-kernel, linux-arm-kernel, linux-arm-msm, coresight,
	devicetree, gregkh
In-Reply-To: <20260317032639.2393221-3-songwei.chai@oss.qualcomm.com>



On 3/17/2026 11:26 AM, Songwei Chai wrote:
> Add driver to support device TGU (Trigger Generation Unit).
> TGU is a Data Engine which can be utilized to sense a plurality of
> signals and create a trigger into the CTI or generate interrupts to
> processors. Add probe/enable/disable functions for tgu.
> 
> Signed-off-by: Songwei Chai <songwei.chai@oss.qualcomm.com>
> ---
>   .../ABI/testing/sysfs-bus-amba-devices-tgu    |   9 +
>   drivers/Makefile                              |   1 +
>   drivers/hwtracing/Kconfig                     |   2 +
>   drivers/hwtracing/qcom/Kconfig                |  18 ++
>   drivers/hwtracing/qcom/Makefile               |   3 +
>   drivers/hwtracing/qcom/tgu.c                  | 183 ++++++++++++++++++
>   drivers/hwtracing/qcom/tgu.h                  |  51 +++++
>   7 files changed, 267 insertions(+)
>   create mode 100644 Documentation/ABI/testing/sysfs-bus-amba-devices-tgu
>   create mode 100644 drivers/hwtracing/qcom/Kconfig
>   create mode 100644 drivers/hwtracing/qcom/Makefile
>   create mode 100644 drivers/hwtracing/qcom/tgu.c
>   create mode 100644 drivers/hwtracing/qcom/tgu.h
> 
> diff --git a/Documentation/ABI/testing/sysfs-bus-amba-devices-tgu b/Documentation/ABI/testing/sysfs-bus-amba-devices-tgu
> new file mode 100644
> index 000000000000..ead237bb7d89
> --- /dev/null
> +++ b/Documentation/ABI/testing/sysfs-bus-amba-devices-tgu
> @@ -0,0 +1,9 @@
> +What:		/sys/bus/amba/devices/<tgu-name>/enable_tgu
> +Date:		March 2026
> +KernelVersion	7.1

missed ":" in all patches.

Thanks,
Jie

> +Contact:	Jinlong Mao <jinlong.mao@oss.qualcomm.com>, Songwei Chai <songwei.chai@oss.qualcomm.com>
> +Description:
> +		(RW) Set/Get the enable/disable status of TGU
> +		Accepts only one of the 2 values -  0 or 1.
> +		0 : disable TGU.
> +		1 : enable TGU.
> diff --git a/drivers/Makefile b/drivers/Makefile
> index 53fbd2e0acdd..82b712a12a26 100644
> --- a/drivers/Makefile
> +++ b/drivers/Makefile
> @@ -177,6 +177,7 @@ obj-$(CONFIG_RAS)		+= ras/
>   obj-$(CONFIG_USB4)		+= thunderbolt/
>   obj-$(CONFIG_CORESIGHT)		+= hwtracing/coresight/
>   obj-y				+= hwtracing/intel_th/
> +obj-y				+= hwtracing/qcom/
>   obj-$(CONFIG_STM)		+= hwtracing/stm/
>   obj-$(CONFIG_HISI_PTT)		+= hwtracing/ptt/
>   obj-y				+= android/
> diff --git a/drivers/hwtracing/Kconfig b/drivers/hwtracing/Kconfig
> index 911ee977103c..8a640218eed8 100644
> --- a/drivers/hwtracing/Kconfig
> +++ b/drivers/hwtracing/Kconfig
> @@ -7,4 +7,6 @@ source "drivers/hwtracing/intel_th/Kconfig"
>   
>   source "drivers/hwtracing/ptt/Kconfig"
>   
> +source "drivers/hwtracing/qcom/Kconfig"
> +
>   endmenu
> diff --git a/drivers/hwtracing/qcom/Kconfig b/drivers/hwtracing/qcom/Kconfig
> new file mode 100644
> index 000000000000..d6f6d4b0f28e
> --- /dev/null
> +++ b/drivers/hwtracing/qcom/Kconfig
> @@ -0,0 +1,18 @@
> +# SPDX-License-Identifier: GPL-2.0-only
> +#
> +# QCOM specific hwtracing drivers
> +#
> +menu "Qualcomm specific hwtracing drivers"
> +
> +config QCOM_TGU
> +	tristate "QCOM Trigger Generation Unit driver"
> +	help
> +	  This driver provides support for Trigger Generation Unit that is
> +	  used to detect patterns or sequences on a given set of signals.
> +	  TGU is used to monitor a particular bus within a given region to
> +	  detect illegal transaction sequences or slave responses. It is also
> +	  used to monitor a data stream to detect protocol violations and to
> +	  provide a trigger point for centering data around a specific event
> +	  within the trace data buffer.
> +
> +endmenu
> diff --git a/drivers/hwtracing/qcom/Makefile b/drivers/hwtracing/qcom/Makefile
> new file mode 100644
> index 000000000000..5a0a868c1ea0
> --- /dev/null
> +++ b/drivers/hwtracing/qcom/Makefile
> @@ -0,0 +1,3 @@
> +# SPDX-License-Identifier: GPL-2.0
> +
> +obj-$(CONFIG_QCOM_TGU) += tgu.o
> diff --git a/drivers/hwtracing/qcom/tgu.c b/drivers/hwtracing/qcom/tgu.c
> new file mode 100644
> index 000000000000..58c19f12f3d7
> --- /dev/null
> +++ b/drivers/hwtracing/qcom/tgu.c
> @@ -0,0 +1,183 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
> + */
> +
> +#include <linux/amba/bus.h>
> +#include <linux/device.h>
> +#include <linux/err.h>
> +#include <linux/io.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/pm_runtime.h>
> +
> +#include "tgu.h"
> +
> +static void tgu_write_all_hw_regs(struct tgu_drvdata *drvdata)
> +{
> +	TGU_UNLOCK(drvdata->base);
> +	/* Enable TGU to program the triggers */
> +	writel(1, drvdata->base + TGU_CONTROL);
> +	TGU_LOCK(drvdata->base);
> +}
> +
> +static int tgu_enable(struct device *dev)
> +{
> +	struct tgu_drvdata *drvdata = dev_get_drvdata(dev);
> +
> +	guard(spinlock)(&drvdata->lock);
> +	if (drvdata->enabled)
> +		return -EBUSY;
> +
> +	tgu_write_all_hw_regs(drvdata);
> +	drvdata->enabled = true;
> +
> +	return 0;
> +}
> +
> +static void tgu_do_disable(struct tgu_drvdata *drvdata)
> +{
> +	TGU_UNLOCK(drvdata->base);
> +	writel(0, drvdata->base + TGU_CONTROL);
> +	TGU_LOCK(drvdata->base);
> +
> +	drvdata->enabled = false;
> +}
> +
> +static void tgu_disable(struct device *dev)
> +{
> +	struct tgu_drvdata *drvdata = dev_get_drvdata(dev);
> +
> +	guard(spinlock)(&drvdata->lock);
> +	if (!drvdata->enabled)
> +		return;
> +
> +	tgu_do_disable(drvdata);
> +}
> +
> +static ssize_t enable_tgu_show(struct device *dev,
> +			       struct device_attribute *attr, char *buf)
> +{
> +	struct tgu_drvdata *drvdata = dev_get_drvdata(dev);
> +	bool enabled;
> +
> +	guard(spinlock)(&drvdata->lock);
> +	enabled = drvdata->enabled;
> +
> +	return sysfs_emit(buf, "%d\n", !!enabled);
> +}
> +
> +/* enable_tgu_store - Configure Trace and Gating Unit (TGU) triggers. */
> +static ssize_t enable_tgu_store(struct device *dev,
> +				struct device_attribute *attr,
> +				const char *buf,
> +				size_t size)
> +{
> +	unsigned long val;
> +	int ret;
> +
> +	ret = kstrtoul(buf, 0, &val);
> +	if (ret || val > 1)
> +		return -EINVAL;
> +
> +	if (val) {
> +		ret = pm_runtime_resume_and_get(dev);
> +		if (ret)
> +			return ret;
> +		ret = tgu_enable(dev);
> +		if (ret) {
> +			pm_runtime_put(dev);
> +			return ret;
> +		}
> +	} else {
> +		tgu_disable(dev);
> +		pm_runtime_put(dev);
> +	}
> +
> +	return size;
> +}
> +static DEVICE_ATTR_RW(enable_tgu);
> +
> +static struct attribute *tgu_common_attrs[] = {
> +	&dev_attr_enable_tgu.attr,
> +	NULL,
> +};
> +
> +static const struct attribute_group tgu_common_grp = {
> +	.attrs = tgu_common_attrs,
> +	NULL,
> +};
> +
> +static const struct attribute_group *tgu_attr_groups[] = {
> +	&tgu_common_grp,
> +	NULL,
> +};
> +
> +static int tgu_probe(struct amba_device *adev, const struct amba_id *id)
> +{
> +	struct device *dev = &adev->dev;
> +	struct tgu_drvdata *drvdata;
> +	int ret;
> +
> +	drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
> +	if (!drvdata)
> +		return -ENOMEM;
> +
> +	drvdata->dev = &adev->dev;
> +	dev_set_drvdata(dev, drvdata);
> +
> +	drvdata->base = devm_ioremap_resource(dev, &adev->res);
> +	if (IS_ERR(drvdata->base))
> +		return PTR_ERR(drvdata->base);
> +
> +	spin_lock_init(&drvdata->lock);
> +
> +	ret = sysfs_create_groups(&dev->kobj, tgu_attr_groups);
> +	if (ret) {
> +		dev_err(dev, "failed to create sysfs groups: %d\n", ret);
> +		return ret;
> +	}
> +
> +	drvdata->enabled = false;
> +
> +	pm_runtime_put(&adev->dev);
> +
> +	return 0;
> +}
> +
> +static void tgu_remove(struct amba_device *adev)
> +{
> +	struct device *dev = &adev->dev;
> +
> +	sysfs_remove_groups(&dev->kobj, tgu_attr_groups);
> +
> +	tgu_disable(dev);
> +}
> +
> +static const struct amba_id tgu_ids[] = {
> +	{
> +		.id = 0x000f0e00,
> +		.mask = 0x000fffff,
> +	},
> +	{ 0, 0, NULL },
> +};
> +
> +MODULE_DEVICE_TABLE(amba, tgu_ids);
> +
> +static struct amba_driver tgu_driver = {
> +	.drv = {
> +		.name = "qcom-tgu",
> +		.suppress_bind_attrs = true,
> +	},
> +	.probe = tgu_probe,
> +	.remove = tgu_remove,
> +	.id_table = tgu_ids,
> +};
> +
> +module_amba_driver(tgu_driver);
> +
> +MODULE_AUTHOR("Songwei Chai <songwei.chai@oss.qualcomm.com>");
> +MODULE_AUTHOR("Jinlong Mao <jinlong.mao@oss.qualcomm.com>");
> +MODULE_DESCRIPTION("Qualcomm Trigger Generation Unit driver");
> +MODULE_LICENSE("GPL");
> diff --git a/drivers/hwtracing/qcom/tgu.h b/drivers/hwtracing/qcom/tgu.h
> new file mode 100644
> index 000000000000..dd7533b9d735
> --- /dev/null
> +++ b/drivers/hwtracing/qcom/tgu.h
> @@ -0,0 +1,51 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
> + */
> +
> +#ifndef _QCOM_TGU_H
> +#define _QCOM_TGU_H
> +
> +/* Register addresses */
> +#define TGU_CONTROL		0x0000
> +#define TGU_LAR		0xfb0
> +#define TGU_UNLOCK_OFFSET	0xc5acce55
> +
> +static inline void TGU_LOCK(void __iomem *addr)
> +{
> +	do {
> +		/* Wait for things to settle */
> +		mb();
> +		writel_relaxed(0x0, addr + TGU_LAR);
> +	} while (0);
> +}
> +
> +static inline void TGU_UNLOCK(void __iomem *addr)
> +{
> +	do {
> +		writel_relaxed(TGU_UNLOCK_OFFSET, addr + TGU_LAR);
> +		/* Make sure everyone has seen this */
> +		mb();
> +	} while (0);
> +}
> +
> +/**
> + * struct tgu_drvdata - Data structure for a TGU (Trigger Generator Unit)
> + * @base: Memory-mapped base address of the TGU device
> + * @dev: Pointer to the associated device structure
> + * @lock: Spinlock for handling concurrent access to private data
> + * @enabled: Flag indicating whether the TGU device is enabled
> + *
> + * This structure defines the data associated with a TGU device,
> + * including its base address, device pointers, clock, spinlock for
> + * synchronization, trigger data pointers, maximum limits for various
> + * trigger-related parameters, and enable status.
> + */
> +struct tgu_drvdata {
> +	void __iomem *base;
> +	struct device *dev;
> +	spinlock_t lock;
> +	bool enabled;
> +};
> +
> +#endif



^ permalink raw reply

* [PATCH v2 0/3] Add i.MX94 remoteproc support and reset vector handling improvements
From: Peng Fan (OSS) @ 2026-03-27  2:42 UTC (permalink / raw)
  To: Bjorn Andersson, Mathieu Poirier, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Frank Li, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam, Daniel Baluta
  Cc: linux-remoteproc, devicetree, imx, linux-arm-kernel, linux-kernel,
	Peng Fan

This series adds remoteproc support for the i.MX94 family, including the
CM70, CM71, and CM33S cores, and derive the hardware reset vector for
Cortex‑M processors whose ELF entry point does not directly correspond to
the actual reset address.

Background:
Cortex‑M processors fetch their initial SP and PC from a fixed reset vector
table. While ELF images embed the entry point (e_entry), this value is
not always aligned to the hardware reset address. On platforms such as
i.MX94 CM33S, masking is required to compute the correct reset vector
address before programming the SoC reset registers.

Similarly, on i.MX95, the existing implementation always programs a reset
vector of 0x0, which only works when executing entirely from TCM. When
firmware is loaded into DDR, the driver must pass the correct reset vector
to the SM CPU/LMM interfaces.

Summary of patches:
[1]dt-bindings: remoteproc: imx-rproc: Introduce fsl,reset-vector-mask
Adds a new DT property allowing SoCs to specify a mask for deriving the
hardware reset vector from the ELF entry point.

[2]remoteproc: imx_rproc: Pass bootaddr to SM CPU/LMM reset vector
Ensures the correct reset vector is passed to SM APIs by introducing a
driver‑level helper (imx_rproc_get_boot_addr()) that applies the
reset‑vector mask.

[3]remoteproc: imx_rproc: Add support for i.MX94 remoteproc
Adds address translation tables and configuration data for CM70, CM71,
and CM33S, enabling full remoteproc operation on i.MX94.

Signed-off-by: Peng Fan <peng.fan@nxp.com>
---
Changes in v2:
- Drop fsl,reset-vector-mask by using fixed value in driver for per device
- Add R-b for i.MX94 dt-binding
- Update commit log to include dev addr and sys addr
- Link to v1: https://lore.kernel.org/r/20260312-imx943-rproc-v1-0-3e66596592a8@nxp.com

---
Peng Fan (3):
      dt-bindings: remoteproc: imx-rproc: Support i.MX94
      remoteproc: imx_rproc: Pass bootaddr to SM CPU/LMM reset vector
      remoteproc: imx_rproc: Add support for i.MX94

 .../bindings/remoteproc/fsl,imx-rproc.yaml         |  3 +
 drivers/remoteproc/imx_rproc.c                     | 88 +++++++++++++++++++++-
 drivers/remoteproc/imx_rproc.h                     |  2 +
 3 files changed, 90 insertions(+), 3 deletions(-)
---
base-commit: a2f31c83962f7f298b2975ab004810f3ac4875dc
change-id: 20260311-imx943-rproc-2050e00b65f7

Best regards,
-- 
Peng Fan <peng.fan@nxp.com>



^ permalink raw reply

* [PATCH v2 1/3] dt-bindings: remoteproc: imx-rproc: Support i.MX94
From: Peng Fan (OSS) @ 2026-03-27  2:42 UTC (permalink / raw)
  To: Bjorn Andersson, Mathieu Poirier, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Frank Li, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam, Daniel Baluta
  Cc: linux-remoteproc, devicetree, imx, linux-arm-kernel, linux-kernel,
	Peng Fan
In-Reply-To: <20260327-imx943-rproc-v2-0-a547a3588730@nxp.com>

From: Peng Fan <peng.fan@nxp.com>

Add compatible string for:
 Cortex-M7 core[0,1] in i.MX94
 Cortex-M33 Sync core in i.MX94

To i.MX94, Cortex-M7 core0 and core1 have different memory view from
Cortex-A55 core, so different compatible string is used.

Reviewed-by: Daniel Baluta <daniel.baluta@nxp.com>
Acked-by: Rob Herring (Arm) <robh@kernel.org>
Reviewed-by: Frank Li <Frank.Li@nxp.com>
Signed-off-by: Peng Fan <peng.fan@nxp.com>
---
 Documentation/devicetree/bindings/remoteproc/fsl,imx-rproc.yaml | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/Documentation/devicetree/bindings/remoteproc/fsl,imx-rproc.yaml b/Documentation/devicetree/bindings/remoteproc/fsl,imx-rproc.yaml
index ce8ec0119469c8fc0979a192b6e3d3a03108d7d2..c18f71b648890da9c25a2f3309d8dbec5bb8d226 100644
--- a/Documentation/devicetree/bindings/remoteproc/fsl,imx-rproc.yaml
+++ b/Documentation/devicetree/bindings/remoteproc/fsl,imx-rproc.yaml
@@ -28,6 +28,9 @@ properties:
       - fsl,imx8qxp-cm4
       - fsl,imx8ulp-cm33
       - fsl,imx93-cm33
+      - fsl,imx94-cm33s
+      - fsl,imx94-cm70
+      - fsl,imx94-cm71
       - fsl,imx95-cm7
 
   clocks:

-- 
2.37.1



^ permalink raw reply related

* [PATCH v2 2/3] remoteproc: imx_rproc: Pass bootaddr to SM CPU/LMM reset vector
From: Peng Fan (OSS) @ 2026-03-27  2:42 UTC (permalink / raw)
  To: Bjorn Andersson, Mathieu Poirier, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Frank Li, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam, Daniel Baluta
  Cc: linux-remoteproc, devicetree, imx, linux-arm-kernel, linux-kernel,
	Peng Fan
In-Reply-To: <20260327-imx943-rproc-v2-0-a547a3588730@nxp.com>

From: Peng Fan <peng.fan@nxp.com>

Cortex-M[7,33] processors use a fixed reset vector table format:

  0x00  Initial SP value
  0x04  Reset vector
  0x08  NMI
  0x0C  ...
  ...
  IRQ[n]

In ELF images, the corresponding layout is:

reset_vectors:  --> hardware reset address
        .word __stack_end__
        .word Reset_Handler
        .word NMI_Handler
        .word HardFault_Handler
        ...
        .word UART_IRQHandler
        .word SPI_IRQHandler
        ...

Reset_Handler:  --> ELF entry point address
        ...

The hardware fetches the first two words from reset_vectors and populates
SP with __stack_end__ and PC with Reset_Handler. Execution proceeds from
Reset_Handler.

However, the ELF entry point does not always match the hardware reset
address. For example, on i.MX94 CM33S:

  ELF entry point:     0x0ffc211d
  hardware reset base: 0x0ffc0000 (default reset value, sw programmable)

To derive the correct hardware reset address, the unused lower bits must
be masked off. The boot code should apply a SoC-specific mask before
programming the reset address registers, e.g.:

  reset_address = entry & reset_vector_mask

Current driver always programs the reset vector as 0. But i.MX94 CM33S's
default reset base is 0x0ffc0000, so the correct reset vector must be
passed to the SM API; otherwise the M33 Sync core cannot boot successfully.

rproc_elf_get_boot_addr() returns the ELF entry point, which is not the
hardware reset vector address. To derive the proper reset vector, this
patch introduces imx_rproc_get_boot_addr(), which masks the ELF entry
point using the SoC‑specific 'reset_vector_mask'. The resulting reset
vector address is then passed to the SM CPU/LMM reset vector API calls.

Signed-off-by: Peng Fan <peng.fan@nxp.com>
---
 drivers/remoteproc/imx_rproc.c | 17 ++++++++++++++---
 drivers/remoteproc/imx_rproc.h |  2 ++
 2 files changed, 16 insertions(+), 3 deletions(-)

diff --git a/drivers/remoteproc/imx_rproc.c b/drivers/remoteproc/imx_rproc.c
index 0dd80e688b0ea3df4c66e5726884dc86c8a5a881..d8ead42640881bd523d605fa7002935ef6e98077 100644
--- a/drivers/remoteproc/imx_rproc.c
+++ b/drivers/remoteproc/imx_rproc.c
@@ -345,7 +345,7 @@ static int imx_rproc_sm_cpu_start(struct rproc *rproc)
 	const struct imx_rproc_dcfg *dcfg = priv->dcfg;
 	int ret;
 
-	ret = scmi_imx_cpu_reset_vector_set(dcfg->cpuid, 0, true, false, false);
+	ret = scmi_imx_cpu_reset_vector_set(dcfg->cpuid, rproc->bootaddr, true, false, false);
 	if (ret) {
 		dev_err(priv->dev, "Failed to set reset vector cpuid(%u): %d\n", dcfg->cpuid, ret);
 		return ret;
@@ -365,7 +365,7 @@ static int imx_rproc_sm_lmm_start(struct rproc *rproc)
 	 * If the remoteproc core can't start the M7, it will already be
 	 * handled in imx_rproc_sm_lmm_prepare().
 	 */
-	ret = scmi_imx_lmm_reset_vector_set(dcfg->lmid, dcfg->cpuid, 0, 0);
+	ret = scmi_imx_lmm_reset_vector_set(dcfg->lmid, dcfg->cpuid, 0, rproc->bootaddr);
 	if (ret) {
 		dev_err(dev, "Failed to set reset vector lmid(%u), cpuid(%u): %d\n",
 			dcfg->lmid, dcfg->cpuid, ret);
@@ -739,6 +739,17 @@ imx_rproc_elf_find_loaded_rsc_table(struct rproc *rproc, const struct firmware *
 	return rproc_elf_find_loaded_rsc_table(rproc, fw);
 }
 
+static u64 imx_rproc_get_boot_addr(struct rproc *rproc, const struct firmware *fw)
+{
+	struct imx_rproc *priv = rproc->priv;
+	u32 reset_vector_mask = GENMASK_U32(31, 0);
+
+	if (priv->dcfg->reset_vector_mask)
+		reset_vector_mask = priv->dcfg->reset_vector_mask;
+
+	return rproc_elf_get_boot_addr(rproc, fw) & reset_vector_mask;
+}
+
 static const struct rproc_ops imx_rproc_ops = {
 	.prepare	= imx_rproc_prepare,
 	.attach		= imx_rproc_attach,
@@ -752,7 +763,7 @@ static const struct rproc_ops imx_rproc_ops = {
 	.find_loaded_rsc_table = imx_rproc_elf_find_loaded_rsc_table,
 	.get_loaded_rsc_table = imx_rproc_get_loaded_rsc_table,
 	.sanity_check	= rproc_elf_sanity_check,
-	.get_boot_addr	= rproc_elf_get_boot_addr,
+	.get_boot_addr	= imx_rproc_get_boot_addr,
 };
 
 static int imx_rproc_addr_init(struct imx_rproc *priv,
diff --git a/drivers/remoteproc/imx_rproc.h b/drivers/remoteproc/imx_rproc.h
index d37e6f90548cec727b4aeb874680b42af85bdbb4..0d7d48352a1091ad24e8e083172ce6da6d26ae10 100644
--- a/drivers/remoteproc/imx_rproc.h
+++ b/drivers/remoteproc/imx_rproc.h
@@ -41,6 +41,8 @@ struct imx_rproc_dcfg {
 	/* For System Manager(SM) based SoCs */
 	u32				cpuid; /* ID of the remote core */
 	u32				lmid;  /* ID of the Logcial Machine */
+	/* reset_vector = elf_entry_addr & reset_vector_mask */
+	u32				reset_vector_mask;
 };
 
 #endif /* _IMX_RPROC_H */

-- 
2.37.1



^ permalink raw reply related

* [PATCH v2 3/3] remoteproc: imx_rproc: Add support for i.MX94
From: Peng Fan (OSS) @ 2026-03-27  2:42 UTC (permalink / raw)
  To: Bjorn Andersson, Mathieu Poirier, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Frank Li, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam, Daniel Baluta
  Cc: linux-remoteproc, devicetree, imx, linux-arm-kernel, linux-kernel,
	Peng Fan
In-Reply-To: <20260327-imx943-rproc-v2-0-a547a3588730@nxp.com>

From: Peng Fan <peng.fan@nxp.com>

Add basic remoteproc support for the i.MX94 M-core processors, including
address translation tables(dev addr is from view of remote processor,
sys addr is from view of main processor) and device configuration data for
the CM70, CM71, and CM33S cores.

Signed-off-by: Peng Fan <peng.fan@nxp.com>
---
 drivers/remoteproc/imx_rproc.c | 71 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 71 insertions(+)

diff --git a/drivers/remoteproc/imx_rproc.c b/drivers/remoteproc/imx_rproc.c
index d8ead42640881bd523d605fa7002935ef6e98077..525a92e03e8ab540697a3ef1f593b079f55e10ee 100644
--- a/drivers/remoteproc/imx_rproc.c
+++ b/drivers/remoteproc/imx_rproc.c
@@ -145,6 +145,47 @@ static const struct imx_rproc_att imx_rproc_att_imx95_m7[] = {
 	{ 0x80000000, 0x80000000, 0x50000000, 0 },
 };
 
+static const struct imx_rproc_att imx_rproc_att_imx94_m70[] = {
+	/* dev addr , sys addr  , size	    , flags */
+	/* TCM CODE NON-SECURE */
+	{ 0x00000000, 0x203C0000, 0x00040000, ATT_OWN | ATT_IOMEM },
+	/* TCM SYS NON-SECURE*/
+	{ 0x20000000, 0x20400000, 0x00040000, ATT_OWN | ATT_IOMEM },
+
+	/* DDR */
+	{ 0x80000000, 0x80000000, 0x50000000, 0 },
+};
+
+static const struct imx_rproc_att imx_rproc_att_imx94_m71[] = {
+	/* dev addr , sys addr  , size	    , flags */
+	/* TCM CODE NON-SECURE */
+	{ 0x00000000, 0x202C0000, 0x00040000, ATT_OWN | ATT_IOMEM },
+	/* TCM SYS NON-SECURE*/
+	{ 0x20000000, 0x20300000, 0x00040000, ATT_OWN | ATT_IOMEM },
+
+	/* DDR */
+	{ 0x80000000, 0x80000000, 0x50000000, 0 },
+};
+
+static const struct imx_rproc_att imx_rproc_att_imx94_m33s[] = {
+	/* dev addr , sys addr  , size	    , flags */
+	/* TCM CODE NON-SECURE */
+	{ 0x0FFC0000, 0x209C0000, 0x00040000, ATT_OWN | ATT_IOMEM },
+	/* TCM CODE SECURE */
+	{ 0x1FFC0000, 0x209C0000, 0x00040000, ATT_OWN | ATT_IOMEM },
+
+	/* TCM SYS NON-SECURE */
+	{ 0x20000000, 0x20A00000, 0x00040000, ATT_OWN | ATT_IOMEM },
+	/* TCM SYS SECURE */
+	{ 0x30000000, 0x20A00000, 0x00040000, ATT_OWN | ATT_IOMEM },
+
+	/* M33S OCRAM */
+	{ 0x20800000, 0x20800000, 0x180000, ATT_OWN | ATT_IOMEM },
+
+	/* DDR */
+	{ 0x80000000, 0x80000000, 0x50000000, 0 },
+};
+
 static const struct imx_rproc_att imx_rproc_att_imx93[] = {
 	/* dev addr , sys addr  , size	    , flags */
 	/* TCM CODE NON-SECURE */
@@ -1466,6 +1507,33 @@ static const struct imx_rproc_dcfg imx_rproc_cfg_imx93 = {
 	.flags		= IMX_RPROC_NEED_CLKS,
 };
 
+static const struct imx_rproc_dcfg imx_rproc_cfg_imx94_m70 = {
+	.att		= imx_rproc_att_imx94_m70,
+	.att_size	= ARRAY_SIZE(imx_rproc_att_imx94_m70),
+	.ops		= &imx_rproc_ops_sm_lmm,
+	.cpuid		= 1,
+	.lmid		= 2,
+	.reset_vector_mask = GENMASK_U32(31, 16),
+};
+
+static const struct imx_rproc_dcfg imx_rproc_cfg_imx94_m71 = {
+	.att		= imx_rproc_att_imx94_m71,
+	.att_size	= ARRAY_SIZE(imx_rproc_att_imx94_m71),
+	.ops		= &imx_rproc_ops_sm_lmm,
+	.cpuid		= 7,
+	.lmid		= 3,
+	.reset_vector_mask = GENMASK_U32(31, 16),
+};
+
+static const struct imx_rproc_dcfg imx_rproc_cfg_imx94_m33s = {
+	.att		= imx_rproc_att_imx94_m33s,
+	.att_size	= ARRAY_SIZE(imx_rproc_att_imx94_m33s),
+	.ops		= &imx_rproc_ops_sm_lmm,
+	.cpuid		= 8,
+	.lmid		= 1,
+	.reset_vector_mask = GENMASK_U32(31, 16),
+};
+
 static const struct imx_rproc_dcfg imx_rproc_cfg_imx95_m7 = {
 	.att		= imx_rproc_att_imx95_m7,
 	.att_size	= ARRAY_SIZE(imx_rproc_att_imx95_m7),
@@ -1489,6 +1557,9 @@ static const struct of_device_id imx_rproc_of_match[] = {
 	{ .compatible = "fsl,imx8qm-cm4", .data = &imx_rproc_cfg_imx8qm },
 	{ .compatible = "fsl,imx8ulp-cm33", .data = &imx_rproc_cfg_imx8ulp },
 	{ .compatible = "fsl,imx93-cm33", .data = &imx_rproc_cfg_imx93 },
+	{ .compatible = "fsl,imx94-cm70", .data = &imx_rproc_cfg_imx94_m70 },
+	{ .compatible = "fsl,imx94-cm71", .data = &imx_rproc_cfg_imx94_m71 },
+	{ .compatible = "fsl,imx94-cm33s", .data = &imx_rproc_cfg_imx94_m33s },
 	{ .compatible = "fsl,imx95-cm7", .data = &imx_rproc_cfg_imx95_m7 },
 	{},
 };

-- 
2.37.1



^ permalink raw reply related

* Re: [RFC PATCH v2 1/5] arm_mpam: resctrl: Pick classes for use as mbm counters
From: Shaopeng Tan (Fujitsu) @ 2026-03-27  2:53 UTC (permalink / raw)
  To: Ben Horgan
  Cc: amitsinght@marvell.com, baisheng.gao@unisoc.com,
	baolin.wang@linux.alibaba.com, carl@os.amperecomputing.com,
	dave.martin@arm.com, david@kernel.org, dfustini@baylibre.com,
	fenghuay@nvidia.com, gshan@redhat.com, james.morse@arm.com,
	jonathan.cameron@huawei.com, kobak@nvidia.com,
	lcherian@marvell.com, linux-arm-kernel@lists.infradead.org,
	linux-kernel@vger.kernel.org, peternewman@google.com,
	punit.agrawal@oss.qualcomm.com, quic_jiles@quicinc.com,
	reinette.chatre@intel.com, rohit.mathew@arm.com,
	scott@os.amperecomputing.com, sdonthineni@nvidia.com,
	xhao@linux.alibaba.com, zengheng4@huawei.com
In-Reply-To: <20260319165540.381410-2-ben.horgan@arm.com>

Hello Ben,


> resctrl has two types of counters, NUMA-local and global. MPAM can only
> count global either using MSC at the L3 cache or in the memory controllers.
> When global and local equate to the same thing continue just to call it
> global.
> 
> Tested-by: Shaopeng Tan <tan.shaopeng@jp.fujitsu.com>
> Tested-by: Zeng Heng <zengheng4@huawei.com>
> Reviewed-by: Shaopeng Tan <tan.shaopeng@jp.fujitsu.com>
> Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com>
> Signed-off-by: James Morse <james.morse@arm.com>
> Signed-off-by: Ben Horgan <ben.horgan@arm.com>
> ---
> Changes since rfc v1:
> Move finding any_mon_comp into monitor boilerplate patch
> Move mpam_resctrl_get_domain_from_cpu() into monitor boilerplate
> Remove free running check
> Trim commit message
> ---
>  drivers/resctrl/mpam_resctrl.c | 26 ++++++++++++++++++++++++++
>  1 file changed, 26 insertions(+)
> 
> diff --git a/drivers/resctrl/mpam_resctrl.c b/drivers/resctrl/mpam_resctrl.c
> index a7691c66553a..c17577e52f58 100644
> --- a/drivers/resctrl/mpam_resctrl.c
> +++ b/drivers/resctrl/mpam_resctrl.c
> @@ -598,6 +598,16 @@ static bool cache_has_usable_csu(struct mpam_class *class)
>          return true;
>  }
>  
> +static bool class_has_usable_mbwu(struct mpam_class *class)
> +{
> +       struct mpam_props *cprops = &class->props;
> +
> +       if (!mpam_has_feature(mpam_feat_msmon_mbwu, cprops))
> +               return false;
> +
> +       return true;
> +}
> +
>  /*
>   * Calculate the worst-case percentage change from each implemented step
>   * in the control.
> @@ -981,6 +991,22 @@ static void mpam_resctrl_pick_counters(void)
>                                  break;
>                          }
>                  }
> +
> +               if (class_has_usable_mbwu(class) &&
> +                   topology_matches_l3(class) &&
> +                   traffic_matches_l3(class)) {
> +                       pr_debug("class %u has usable MBWU, and matches L3 topology and traffic\n",
> +                                class->level);
> +
> +                       /*
> +                        * We can't distinguish traffic by destination so
> +                        * we don't know if it's staying on the same NUMA
> +                        * node. Hence, we can't calculate mbm_local except
> +                        * when we only have one L3 and it's equivalent to
> +                        * mbm_total and so always use mbm_total.
> +                        */
> +                       counter_update_class(QOS_L3_MBM_TOTAL_EVENT_ID, class);
> +               }
>          }
>  }
>  
> --
> 2.43.0
> 
> 

There are environments with multiple L3 caches within a single NUMA node.
In this case, mbm_total will be the sum of traffic from all caches within that NUAM node.
Is my understanding correct?


Best regards,
Shaopeng TAN


^ permalink raw reply

* Re: [PATCH 05/10] am68k/PCI: Remove unnecessary second application of align
From: Greg Ungerer @ 2026-03-27  2:55 UTC (permalink / raw)
  To: Ilpo Järvinen, linux-pci, Bjorn Helgaas, Guenter Roeck,
	linux-alpha, linux-arm-kernel, linux-m68k, linux-mips,
	linux-parisc, linuxppc-dev, linux-s390, linux-sh, Russell King,
	Geert Uytterhoeven, Thomas Bogendoerfer, James E.J. Bottomley,
	Helge Deller, Michael Ellerman, Thomas Gleixner, Ingo Molnar,
	Borislav Petkov, Dave Hansen, H. Peter Anvin, Chris Zankel,
	Max Filippov, Madhavan Srinivasan, Yoshinori Sato, Rich Felker,
	John Paul Adrian Glaubitz, linux-kernel
In-Reply-To: <20260324165633.4583-6-ilpo.jarvinen@linux.intel.com>



On 25/3/26 02:56, Ilpo Järvinen wrote:
> Aligning res->start by align inside pcibios_align_resource() is
> unnecessary because caller of pcibios_align_resource() is
> __find_resource_space() that aligns res->start with align before
> calling pcibios_align_resource().
> 
> Aligning by align in case of IORESOURCE_IO && start & 0x300 cannot ever
> result in changing start either because 0x300 bits would have not
> survived the earlier alignment if align was large enough to have an
> impact.
> 
> Thus, remove the duplicated aligning from pcibios_align_resource().
> 
> Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>

LGTM.

Acked-by: Greg Ungerer <gerg@linux-m68k.org>


> ---
>   arch/m68k/kernel/pcibios.c | 2 --
>   1 file changed, 2 deletions(-)
> 
> diff --git a/arch/m68k/kernel/pcibios.c b/arch/m68k/kernel/pcibios.c
> index 1415f6e4e5ce..7e286ee1976b 100644
> --- a/arch/m68k/kernel/pcibios.c
> +++ b/arch/m68k/kernel/pcibios.c
> @@ -36,8 +36,6 @@ resource_size_t pcibios_align_resource(void *data, const struct resource *res,
>   	if ((res->flags & IORESOURCE_IO) && (start & 0x300))
>   		start = (start + 0x3ff) & ~0x3ff;
>   
> -	start = (start + align - 1) & ~(align - 1);
> -
>   	return start;
>   }
>   



^ permalink raw reply

* Re: [RFC PATCH v2 2/5] arm_mpam: resctrl: Pre-allocate assignable monitors
From: Shaopeng Tan (Fujitsu) @ 2026-03-27  3:00 UTC (permalink / raw)
  To: Ben Horgan
  Cc: amitsinght@marvell.com, baisheng.gao@unisoc.com,
	baolin.wang@linux.alibaba.com, carl@os.amperecomputing.com,
	dave.martin@arm.com, david@kernel.org, dfustini@baylibre.com,
	fenghuay@nvidia.com, gshan@redhat.com, james.morse@arm.com,
	jonathan.cameron@huawei.com, kobak@nvidia.com,
	lcherian@marvell.com, linux-arm-kernel@lists.infradead.org,
	linux-kernel@vger.kernel.org, peternewman@google.com,
	punit.agrawal@oss.qualcomm.com, quic_jiles@quicinc.com,
	reinette.chatre@intel.com, rohit.mathew@arm.com,
	scott@os.amperecomputing.com, sdonthineni@nvidia.com,
	xhao@linux.alibaba.com, zengheng4@huawei.com
In-Reply-To: <20260319165540.381410-3-ben.horgan@arm.com>

Hello Ben,

> MPAM is able to emulate ABMC, i.e. mbm_event mode, by making memory
> bandwidth monitors assignable. Rather than supporting the 'default'
> mbm_assign_mode always use 'mbm_event'mode even if there are sufficient
> memory bandwidth monitors. The per monitor event configuration is only
> provided by resctrl when in 'mbm_event' mode and so only allowing
> 'mbm_event' mode will make it easier to support per-monitor event
> configuration for MPAM. For the moment, the only event supported is
> mbm_total_event with no bandwidth type configuration. The 'mbm_assign_mode'
> file will still show 'default' when there is no support for memory
> bandwidth monitoring.
> 
> The monitors need to be allocated from the driver, and mapped to whichever
> control/monitor group resctrl wants to use them with.
> 
> Add a second array to hold the monitor values indexed by resctrl's cntr_id.
> 
> When CDP is in use, two monitors are needed so the available number of
> counters halves. Platforms with one monitor will have zero monitors when
> CDP is in use.
> 
> Co-developed-by: James Morse <james.morse@arm.com>
> Signed-off-by: James Morse <james.morse@arm.com>
> Signed-off-by: Ben Horgan <ben.horgan@arm.com>
> ---
> Changes since rfc v1:
> abmc enabled even if enough counters
> Helpers from dropped free running commits
> carry on with zero counters if using cdp
> set config bits
> use kmalloc_objs
> drop tags for rework
> Configure mbm_cntr_configurable, mbm_cntr_assign_fixed
> ---
>  drivers/resctrl/mpam_internal.h |   6 +-
>  drivers/resctrl/mpam_resctrl.c  | 135 +++++++++++++++++++++++++++++++-
>  2 files changed, 137 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/resctrl/mpam_internal.h b/drivers/resctrl/mpam_internal.h
> index dbb99d9b0795..02807531bd1b 100644
> --- a/drivers/resctrl/mpam_internal.h
> +++ b/drivers/resctrl/mpam_internal.h
> @@ -415,7 +415,11 @@ struct mpam_resctrl_res {
>  struct mpam_resctrl_mon {
>          struct mpam_class       *class;
>  
> -       /* per-class data that resctrl needs will live here */
> +       /* Array of allocated MBWU monitors, indexed by (closid, rmid). */
> +       int                     *mbwu_idx_to_mon;
> +
> +       /* Array of assigned MBWU monitors, indexed by idx argument. */
> +       int                     *assigned_counters;
>  };
>  
>  static inline int mpam_alloc_csu_mon(struct mpam_class *class)
> diff --git a/drivers/resctrl/mpam_resctrl.c b/drivers/resctrl/mpam_resctrl.c
> index c17577e52f58..74b6ca59ce4a 100644
> --- a/drivers/resctrl/mpam_resctrl.c
> +++ b/drivers/resctrl/mpam_resctrl.c
> @@ -75,6 +75,8 @@ static DECLARE_WAIT_QUEUE_HEAD(wait_cacheinfo_ready);
>   */
>  static bool resctrl_enabled;
>  
> +static unsigned int l3_num_allocated_mbwu = ~0;
> +
>  bool resctrl_arch_alloc_capable(void)
>  {
>          struct mpam_resctrl_res *res;
> @@ -140,7 +142,7 @@ int resctrl_arch_cntr_read(struct rdt_resource *r, struct rdt_l3_mon_domain *d,
>  
>  bool resctrl_arch_mbm_cntr_assign_enabled(struct rdt_resource *r)
>  {
> -       return false;
> +       return (r == &mpam_resctrl_controls[RDT_RESOURCE_L3].resctrl_res);
>  }
>  
>  int resctrl_arch_mbm_cntr_assign_set(struct rdt_resource *r, bool enable)
> @@ -185,6 +187,22 @@ static void resctrl_reset_task_closids(void)
>          read_unlock(&tasklist_lock);
>  }
>  
> +static void mpam_resctrl_monitor_sync_abmc_vals(struct rdt_resource *l3)
> +{
> +       l3->mon.num_mbm_cntrs = l3_num_allocated_mbwu;
> +       if (cdp_enabled)
> +               l3->mon.num_mbm_cntrs /= 2;
> +
> +       /*
> +        * Continue as normal even if there are zero counters to avoid giving
> +        * resctrl mixed messages.
> +        */
> +       l3->mon.mbm_cntr_assignable = true;
> +       l3->mon.mbm_assign_on_mkdir = true;
> +       l3->mon.mbm_cntr_configurable = false;
> +       l3->mon.mbm_cntr_assign_fixed = true;
> +}
> +
>  int resctrl_arch_set_cdp_enabled(enum resctrl_res_level rid, bool enable)
>  {
>          u32 partid_i = RESCTRL_RESERVED_CLOSID, partid_d = RESCTRL_RESERVED_CLOSID;
> @@ -236,6 +254,7 @@ int resctrl_arch_set_cdp_enabled(enum resctrl_res_level rid, bool enable)
>          WRITE_ONCE(arm64_mpam_global_default, mpam_get_regval(current));
>  
>          resctrl_reset_task_closids();
> +       mpam_resctrl_monitor_sync_abmc_vals(l3);

Why is ABMC supported by default when CDP is enabled?

>          for_each_possible_cpu(cpu)
>                  mpam_set_cpu_defaults(cpu, partid_d, partid_i, 0, 0);
> @@ -605,6 +624,9 @@ static bool class_has_usable_mbwu(struct mpam_class *class)
>          if (!mpam_has_feature(mpam_feat_msmon_mbwu, cprops))
>                  return false;
>  
> +       if (!cprops->num_mbwu_mon)
> +               return false;
> +
>          return true;
>  }
>  
> @@ -933,6 +955,52 @@ static void mpam_resctrl_pick_mba(void)
>          }
>  }
>  
> +static void __free_mbwu_mon(struct mpam_class *class, int *array,
> +                           u16 num_mbwu_mon)
> +{
> +       for (int i = 0; i < num_mbwu_mon; i++) {
> +               if (array[i] < 0)
> +                       continue;
> +
> +               mpam_free_mbwu_mon(class, array[i]);
> +               array[i] = ~0;
> +       }
> +}
> +
> +static int __alloc_mbwu_mon(struct mpam_class *class, int *array,
> +                           u16 num_mbwu_mon)
> +{
> +       for (int i = 0; i < num_mbwu_mon; i++) {
> +               int mbwu_mon = mpam_alloc_mbwu_mon(class);
> +
> +               if (mbwu_mon < 0) {
> +                       __free_mbwu_mon(class, array, num_mbwu_mon);
> +                       return mbwu_mon;
> +               }
> +               array[i] = mbwu_mon;
> +       }
> +
> +       l3_num_allocated_mbwu = min(l3_num_allocated_mbwu, num_mbwu_mon);
> +
> +       return 0;
> +}
> +
> +static int *__alloc_mbwu_array(struct mpam_class *class, u16 num_mbwu_mon)
> +{
> +       int err;
> +       int *array __free(kfree) = kmalloc_objs(*array, num_mbwu_mon);
> +
> +       if (!array)
> +               return ERR_PTR(-ENOMEM);
> +
> +       memset(array, -1, num_mbwu_mon * sizeof(*array));
> +
> +       err = __alloc_mbwu_mon(class, array, num_mbwu_mon);
> +       if (err)
> +               return ERR_PTR(err);
> +       return_ptr(array);
> +}
> +
>  static void counter_update_class(enum resctrl_event_id evt_id,
>                                   struct mpam_class *class)
>  {
> @@ -1087,9 +1155,46 @@ static int mpam_resctrl_pick_domain_id(int cpu, struct mpam_component *comp)
>          return comp->comp_id;
>  }
>  
> +/*
> + * This must run after all event counters have been picked so that any free
> + * running counters have already been allocated.
> + */
> +static int mpam_resctrl_monitor_init_abmc(struct mpam_resctrl_mon *mon)
> +{
> +       struct mpam_resctrl_res *res = &mpam_resctrl_controls[RDT_RESOURCE_L3];
> +       struct rdt_resource *l3 = &res->resctrl_res;
> +       struct mpam_class *class = mon->class;
> +       u16 num_mbwu_mon;
> +       size_t num_rmid = resctrl_arch_system_num_rmid_idx();
> +
> +       if (mon->mbwu_idx_to_mon) {
> +               pr_debug("monitors free running\n");
> +               return 0;
> +       }

ABMC is not supported under this condition. 
Why does this condition conclude that there are enough monitors(monitors freee running)?

Best regards,
Shaopeng TAN

> +       int *rmid_array __free(kfree) = kmalloc_objs(*rmid_array, num_rmid);
> +
> +       if (!rmid_array) {
> +               pr_debug("Failed to allocate RMID array\n");
> +               return -ENOMEM;
> +       }
> +       memset(rmid_array, -1, num_rmid * sizeof(*rmid_array));
> +
> +       num_mbwu_mon = class->props.num_mbwu_mon;
> +       mon->assigned_counters = __alloc_mbwu_array(mon->class, num_mbwu_mon);
> +       if (IS_ERR(mon->assigned_counters))
> +               return PTR_ERR(mon->assigned_counters);
> +       mon->mbwu_idx_to_mon = no_free_ptr(rmid_array);
> +
> +       mpam_resctrl_monitor_sync_abmc_vals(l3);
> +
> +       return 0;
> +}
> +
>  static int mpam_resctrl_monitor_init(struct mpam_resctrl_mon *mon,
>                                       enum resctrl_event_id type)
>  {
> +       int err = 0;
>          struct mpam_resctrl_res *res = &mpam_resctrl_controls[RDT_RESOURCE_L3];
>          struct rdt_resource *l3 = &res->resctrl_res;
>  
> @@ -1131,8 +1236,19 @@ static int mpam_resctrl_monitor_init(struct mpam_resctrl_mon *mon,
>           */
>          l3->mon.num_rmid = resctrl_arch_system_num_rmid_idx();
>  
> -       if (resctrl_enable_mon_event(type, false, 0, NULL))
> -               l3->mon_capable = true;
> +       if (type == QOS_L3_MBM_TOTAL_EVENT_ID) {
> +               err = mpam_resctrl_monitor_init_abmc(mon);
> +               if (err)
> +                       return err;
> +
> +               static_assert(MAX_EVT_CONFIG_BITS == 0x7f);
> +               l3->mon.mbm_cfg_mask = MAX_EVT_CONFIG_BITS;
> +       }
> +
> +       if (!resctrl_enable_mon_event(type, false, 0, NULL))
> +               return -EINVAL;
> +
> +       l3->mon_capable = true;
>  
>          return 0;
>  }
> @@ -1695,6 +1811,17 @@ void mpam_resctrl_exit(void)
>          resctrl_exit();
>  }
>  
> +static void mpam_resctrl_teardown_mon(struct mpam_resctrl_mon *mon, struct mpam_class *class)
> +{
> +       u32 num_mbwu_mon = resctrl_arch_system_num_rmid_idx();
> +
> +       if (!mon->mbwu_idx_to_mon)
> +               return;
> +
> +       __free_mbwu_mon(class, mon->mbwu_idx_to_mon, num_mbwu_mon);
> +       mon->mbwu_idx_to_mon = NULL;
> +}
> +
>  /*
>   * The driver is detaching an MSC from this class, if resctrl was using it,
>   * pull on resctrl_exit().
> @@ -1717,6 +1844,8 @@ void mpam_resctrl_teardown_class(struct mpam_class *class)
>          for_each_mpam_resctrl_mon(mon, eventid) {
>                  if (mon->class == class) {
>                          mon->class = NULL;
> +
> +                       mpam_resctrl_teardown_mon(mon, class);
>                          break;
>                  }
>          }
> --
> 2.43.0


^ permalink raw reply

* Re: [PATCH net-next] net: airoha: Grab flow_offload_mutex running airoha_register_gdm_devices()
From: Jakub Kicinski @ 2026-03-27  3:06 UTC (permalink / raw)
  To: Lorenzo Bianconi
  Cc: Andrew Lunn, David S. Miller, Eric Dumazet, Paolo Abeni,
	linux-arm-kernel, linux-mediatek, netdev
In-Reply-To: <20260324-airoha-regiser-race-fix-v1-1-6014df55886b@kernel.org>

On Tue, 24 Mar 2026 17:54:45 +0100 Lorenzo Bianconi wrote:
> Netfilter flowtable can theoretically try offload flower rules as soon
> as a net-device is registered while not all the other ones are
> registered/initialized, triggering a possible NULL pointer dereferencing
> of qdma pointer in airoha_ppe_set_cpu_port routine. In order to avoid any
> possible race, grab the flow_offload_mutex running
> airoha_register_gdm_devices().

Sashiko says this causes a lock ordering issue:
https://sashiko.dev/#/patchset/20260324-airoha-regiser-race-fix-v1-1-6014df55886b@kernel.org


^ permalink raw reply


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