Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/8] SM8450 QoL changes
From: Esteban Urrutia via B4 Relay @ 2026-06-23  0:54 UTC (permalink / raw)
  To: Bjorn Andersson, Michael Turquette, Stephen Boyd, Brian Masney,
	Konrad Dybcio, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Rob Clark, Will Deacon, Robin Murphy, Joerg Roedel (AMD),
	Vinod Koul, Neil Armstrong
  Cc: linux-arm-msm, linux-clk, linux-kernel, devicetree, iommu,
	linux-arm-kernel, linux-phy, Esteban Urrutia

Hello. This is my first attempt at contributing to the Linux kernel.

I've been mainlining an SM8475 based device for quite some time now and
I feel now's the proper time to start submitting patches.
I'm starting with the smallest part which are mostly modifications
regarding the current support for the SM8450 SoC.

Regards,
Esteban

Signed-off-by: Esteban Urrutia <esteuwu@proton.me>
---
Esteban Urrutia (8):
      clk: qcom: dispcc-sm8450: Fix mdss clocks
      arm64: dts: qcom: sm8450: Remove unneeded reserved memory nodes
      arm64: dts: qcom: sm8450: Modify GPU operating points
      arm64: dts: qcom: sm8450: Add missing PCM_OUT port
      iommu/arm-smmu-qcom: Add SM8450 MDSS compatible
      phy: qcom: qmp-combo: Drop qmp_v4_calibrate_dp_phy
      phy: qcom: qmp-combo: Correct pre-emphasis table for QMP v4 DP PHYs
      arm64: defconfig: Add SM8450 camcc

 arch/arm64/boot/dts/qcom/sm8450.dtsi       | 50 ++++++------------------------
 arch/arm64/configs/defconfig               |  1 +
 drivers/clk/qcom/dispcc-sm8450.c           |  6 ++--
 drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c |  1 +
 drivers/phy/qualcomm/phy-qcom-qmp-combo.c  | 33 +-------------------
 5 files changed, 16 insertions(+), 75 deletions(-)
---
base-commit: 948efecf22e49aa4bf55bb73ec79a0ddcfd38571
change-id: 20260622-sm8450-qol-466b8c07eb5f

Best regards,
--  
Esteban Urrutia <esteuwu@proton.me>




^ permalink raw reply

* [PATCH 1/8] clk: qcom: dispcc-sm8450: Fix mdss clocks
From: Esteban Urrutia via B4 Relay @ 2026-06-23  0:54 UTC (permalink / raw)
  To: Bjorn Andersson, Michael Turquette, Stephen Boyd, Brian Masney,
	Konrad Dybcio, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Rob Clark, Will Deacon, Robin Murphy, Joerg Roedel (AMD),
	Vinod Koul, Neil Armstrong
  Cc: linux-arm-msm, linux-clk, linux-kernel, devicetree, iommu,
	linux-arm-kernel, linux-phy, Esteban Urrutia
In-Reply-To: <20260622-sm8450-qol-v1-0-37e2ee8df9da@proton.me>

From: Esteban Urrutia <esteuwu@proton.me>

Both of these changes allow the framebuffer to show upon boot and let
the mdss driver take over afterwards.
Before, none of these actions were possible. Only mdss takeover was
possible, but screen had to be turned off first.

OLE configuration may have been a misinterpretation... that's not
something that's done on the downstream driver.

Changing disp_cc_mdss_mdp_clk_src from clk_rcg2_shared_ops to
clk_rcg2_shared_no_init_park_ops fixes this warning as well:

[    0.075780] ------------[ cut here ]------------
[    0.075791] disp_cc_mdss_mdp_clk_src: rcg didn't update its configuration.
[    0.075812] WARNING: drivers/clk/qcom/clk-rcg2.c:136 at update_config+0xd4/0xe4, CPU#3: swapper/0/1
[    0.075840] Modules linked in:
[    0.075856] CPU: 3 UID: 0 PID: 1 Comm: swapper/0 Tainted: G S                  7.1.0-rc2+ #320 PREEMPT
[    0.075870] Tainted: [S]=CPU_OUT_OF_SPEC
[    0.075877] Hardware name: Motorola ThinkPhone by motorola (DT)
[    0.075887] pstate: 61400005 (nZCv daif +PAN -UAO -TCO +DIT -SSBS BTYPE=--)
[    0.075897] pc : update_config+0xd4/0xe4
[    0.075906] lr : update_config+0xd4/0xe4
[    0.075914] sp : ffff80008005b9f0
[    0.075921] x29: ffff80008005ba00 x28: 0000000000000004 x27: ffff000782892200
[    0.075937] x26: ffff0007823a46c0 x25: 0000000000000004 x24: ffffffffffffffff
[    0.075953] x23: ffff0007823a0240 x22: ffffdbc0a0940220 x21: ffffdbc0a0940220
[    0.075967] x20: ffffdbc0a0dcb388 x19: 0000000000000000 x18: 0000000000000048
[    0.075981] x17: 0000000000000014 x16: 0000000000010008 x15: fffffffffffea870
[    0.075996] x14: ffffdbc0a0c5d580 x13: ffffdbc0a0c5d600 x12: 00000000000001ee
[    0.076010] x11: fffffffffffea870 x10: fffffffffffea828 x9 : ffffdbc0a0c5d600
[    0.076024] x8 : 3fffffffffffefff x7 : ffffdbc0a0cb5600 x6 : 00000000000001ef
[    0.076038] x5 : 3ffffffffffff1ee x4 : 00000000000001ee x3 : 0000000000000000
[    0.076052] x2 : 0000000000000000 x1 : 0000000000000000 x0 : ffff00078066adc0
[    0.076067] Call trace:
[    0.076074]  update_config+0xd4/0xe4 (P)
[    0.076085]  clk_rcg2_shared_disable+0x50/0x80
[    0.076096]  clk_rcg2_shared_init+0x10/0x20
[    0.076107]  __clk_register+0x1b4/0x9ec
[    0.076118]  devm_clk_hw_register+0x5c/0xd4
[    0.076128]  devm_clk_register_regmap+0x44/0x84
[    0.076139]  qcom_cc_really_probe+0x304/0x514
[    0.076149]  disp_cc_sm8450_probe+0x104/0x200
[    0.076160]  platform_probe+0x5c/0xa4
[    0.076172]  really_probe+0xbc/0x2ac
[    0.076182]  __driver_probe_device+0x80/0x154
[    0.076193]  driver_probe_device+0x3c/0x184
[    0.076203]  __driver_attach+0x90/0x18c
[    0.076213]  bus_for_each_dev+0x7c/0xdc
[    0.076224]  driver_attach+0x24/0x30
[    0.076233]  bus_add_driver+0xe4/0x20c
[    0.076243]  driver_register+0x68/0x130
[    0.076251]  __platform_driver_register+0x20/0x2c
[    0.076260]  disp_cc_sm8450_driver_init+0x1c/0x28
[    0.076273]  do_one_initcall+0x60/0x1d4
[    0.076287]  kernel_init_freeable+0x24c/0x2d4
[    0.076299]  kernel_init+0x24/0x140
[    0.076311]  ret_from_fork+0x10/0x20
[    0.076323] ---[ end trace 0000000000000000 ]---

Signed-off-by: Esteban Urrutia <esteuwu@proton.me>
---
 drivers/clk/qcom/dispcc-sm8450.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/clk/qcom/dispcc-sm8450.c b/drivers/clk/qcom/dispcc-sm8450.c
index 2e91332dd92a..b99d3eb5e195 100644
--- a/drivers/clk/qcom/dispcc-sm8450.c
+++ b/drivers/clk/qcom/dispcc-sm8450.c
@@ -614,7 +614,7 @@ static struct clk_rcg2 disp_cc_mdss_mdp_clk_src = {
 		.parent_data = disp_cc_parent_data_5,
 		.num_parents = ARRAY_SIZE(disp_cc_parent_data_5),
 		.flags = CLK_SET_RATE_PARENT,
-		.ops = &clk_rcg2_shared_ops,
+		.ops = &clk_rcg2_shared_no_init_park_ops,
 	},
 };
 
@@ -1824,8 +1824,8 @@ static int disp_cc_sm8450_probe(struct platform_device *pdev)
 		disp_cc_pll1.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE];
 		disp_cc_pll1.clkr.hw.init = &sm8475_disp_cc_pll1_init;
 
-		clk_lucid_ole_pll_configure(&disp_cc_pll0, regmap, &sm8475_disp_cc_pll0_config);
-		clk_lucid_ole_pll_configure(&disp_cc_pll1, regmap, &sm8475_disp_cc_pll1_config);
+		clk_lucid_evo_pll_configure(&disp_cc_pll0, regmap, &sm8475_disp_cc_pll0_config);
+		clk_lucid_evo_pll_configure(&disp_cc_pll1, regmap, &sm8475_disp_cc_pll1_config);
 	} else {
 		clk_lucid_evo_pll_configure(&disp_cc_pll0, regmap, &disp_cc_pll0_config);
 		clk_lucid_evo_pll_configure(&disp_cc_pll1, regmap, &disp_cc_pll1_config);

-- 
2.54.0




^ permalink raw reply related

* [PATCH 4/8] arm64: dts: qcom: sm8450: Add missing PCM_OUT port
From: Esteban Urrutia via B4 Relay @ 2026-06-23  0:54 UTC (permalink / raw)
  To: Bjorn Andersson, Michael Turquette, Stephen Boyd, Brian Masney,
	Konrad Dybcio, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Rob Clark, Will Deacon, Robin Murphy, Joerg Roedel (AMD),
	Vinod Koul, Neil Armstrong
  Cc: linux-arm-msm, linux-clk, linux-kernel, devicetree, iommu,
	linux-arm-kernel, linux-phy, Esteban Urrutia
In-Reply-To: <20260622-sm8450-qol-v1-0-37e2ee8df9da@proton.me>

From: Esteban Urrutia <esteuwu@proton.me>

An error in dmesg shows there is a mismatch between controller and DT
dout-ports.
Add PCM_OUT port to fix this.

Signed-off-by: Esteban Urrutia <esteuwu@proton.me>
---
 arch/arm64/boot/dts/qcom/sm8450.dtsi | 20 ++++++++++----------
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/arch/arm64/boot/dts/qcom/sm8450.dtsi b/arch/arm64/boot/dts/qcom/sm8450.dtsi
index 5e331a25e22a..8fc58a02e5c5 100644
--- a/arch/arm64/boot/dts/qcom/sm8450.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm8450.dtsi
@@ -2914,20 +2914,20 @@ swr1: soundwire@3210000 {
 			clock-names = "iface";
 			label = "RX";
 			qcom,din-ports = <0>;
-			qcom,dout-ports = <5>;
+			qcom,dout-ports = <6>;
 
 			pinctrl-0 = <&rx_swr_active>;
 			pinctrl-names = "default";
 
-			qcom,ports-sinterval-low =	/bits/ 8 <0x03 0x1f 0x1f 0x07 0x00>;
-			qcom,ports-offset1 =		/bits/ 8 <0x00 0x00 0x0b 0x01 0x00>;
-			qcom,ports-offset2 =		/bits/ 8 <0x00 0x00 0x0b 0x00 0x00>;
-			qcom,ports-hstart =		/bits/ 8 <0xff 0x03 0xff 0xff 0xff>;
-			qcom,ports-hstop =		/bits/ 8 <0xff 0x06 0xff 0xff 0xff>;
-			qcom,ports-word-length =	/bits/ 8 <0x01 0x07 0x04 0xff 0xff>;
-			qcom,ports-block-pack-mode =	/bits/ 8 <0xff 0x00 0x01 0xff 0xff>;
-			qcom,ports-block-group-count =	/bits/ 8 <0xff 0xff 0xff 0xff 0x00>;
-			qcom,ports-lane-control =	/bits/ 8 <0x01 0x00 0x00 0x00 0x00>;
+			qcom,ports-sinterval =		/bits/ 16 <0x03 0x3f 0x1f 0x07 0x00 0x18f>;
+			qcom,ports-offset1 =		/bits/ 8 <0x00 0x00 0x0b 0x01 0x00 0x00>;
+			qcom,ports-offset2 =		/bits/ 8 <0x00 0x00 0x0b 0x00 0x00 0x00>;
+			qcom,ports-hstart =		/bits/ 8 <0xff 0x03 0xff 0xff 0xff 0x08>;
+			qcom,ports-hstop =		/bits/ 8 <0xff 0x06 0xff 0xff 0xff 0x08>;
+			qcom,ports-word-length =	/bits/ 8 <0x01 0x07 0x04 0xff 0xff 0x0f>;
+			qcom,ports-block-pack-mode =	/bits/ 8 <0xff 0x00 0x01 0xff 0xff 0x00>;
+			qcom,ports-block-group-count =	/bits/ 8 <0xff 0xff 0xff 0xff 0x00 0x00>;
+			qcom,ports-lane-control =	/bits/ 8 <0x01 0x00 0x00 0x00 0x00 0x00>;
 
 			#address-cells = <2>;
 			#size-cells = <0>;

-- 
2.54.0




^ permalink raw reply related

* [PATCH 6/8] phy: qcom: qmp-combo: Drop qmp_v4_calibrate_dp_phy
From: Esteban Urrutia via B4 Relay @ 2026-06-23  0:54 UTC (permalink / raw)
  To: Bjorn Andersson, Michael Turquette, Stephen Boyd, Brian Masney,
	Konrad Dybcio, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Rob Clark, Will Deacon, Robin Murphy, Joerg Roedel (AMD),
	Vinod Koul, Neil Armstrong
  Cc: linux-arm-msm, linux-clk, linux-kernel, devicetree, iommu,
	linux-arm-kernel, linux-phy, Esteban Urrutia
In-Reply-To: <20260622-sm8450-qol-v1-0-37e2ee8df9da@proton.me>

From: Esteban Urrutia <esteuwu@proton.me>

There are no downstream device trees that specify five values in the
qcom,aux-cfg1-settings array.
Plus, after cross referencing both downstream device trees and entries
which refer this function, only 0x13 is specified.
Since 0x13 is written at initialization time, drop this function as a
whole, and remove now unused variable assignations.

Signed-off-by: Esteban Urrutia <esteuwu@proton.me>
---
 drivers/phy/qualcomm/phy-qcom-qmp-combo.c | 31 -------------------------------
 1 file changed, 31 deletions(-)

diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c
index cdcfad2e86b1..9bd666ac2c49 100644
--- a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c
+++ b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c
@@ -2325,7 +2325,6 @@ static int qmp_v3_calibrate_dp_phy(struct qmp_combo *qmp);
 static void qmp_v4_dp_aux_init(struct qmp_combo *qmp);
 static void qmp_v4_configure_dp_tx(struct qmp_combo *qmp);
 static int qmp_v4_configure_dp_phy(struct qmp_combo *qmp);
-static int qmp_v4_calibrate_dp_phy(struct qmp_combo *qmp);
 
 static void qmp_v8_dp_aux_init(struct qmp_combo *qmp);
 static int qmp_v8_configure_dp_clocks(struct qmp_combo *qmp);
@@ -2466,7 +2465,6 @@ static const struct qmp_phy_cfg sar2130p_usb3dpphy_cfg = {
 	.configure_dp_tx	= qmp_v4_configure_dp_tx,
 	.configure_dp_clocks	= qmp_v3_configure_dp_clocks,
 	.configure_dp_phy	= qmp_v4_configure_dp_phy,
-	.calibrate_dp_phy	= qmp_v4_calibrate_dp_phy,
 
 	.regs			= qmp_v6_usb3phy_regs_layout,
 	.reset_list		= msm8996_usb3phy_reset_l,
@@ -2603,7 +2601,6 @@ static const struct qmp_phy_cfg sc8180x_usb3dpphy_cfg = {
 	.configure_dp_tx	= qmp_v4_configure_dp_tx,
 	.configure_dp_clocks	= qmp_v3_configure_dp_clocks,
 	.configure_dp_phy	= qmp_v4_configure_dp_phy,
-	.calibrate_dp_phy	= qmp_v4_calibrate_dp_phy,
 
 	.reset_list		= msm8996_usb3phy_reset_l,
 	.num_resets		= ARRAY_SIZE(msm8996_usb3phy_reset_l),
@@ -2650,7 +2647,6 @@ static const struct qmp_phy_cfg sc8280xp_usb43dpphy_cfg = {
 	.configure_dp_tx	= qmp_v4_configure_dp_tx,
 	.configure_dp_clocks	= qmp_v3_configure_dp_clocks,
 	.configure_dp_phy	= qmp_v4_configure_dp_phy,
-	.calibrate_dp_phy	= qmp_v4_calibrate_dp_phy,
 
 	.reset_list		= msm8996_usb3phy_reset_l,
 	.num_resets		= ARRAY_SIZE(msm8996_usb3phy_reset_l),
@@ -2696,7 +2692,6 @@ static const struct qmp_phy_cfg x1e80100_usb3dpphy_cfg = {
 	.configure_dp_tx	= qmp_v4_configure_dp_tx,
 	.configure_dp_clocks	= qmp_v3_configure_dp_clocks,
 	.configure_dp_phy	= qmp_v4_configure_dp_phy,
-	.calibrate_dp_phy	= qmp_v4_calibrate_dp_phy,
 
 	.reset_list		= msm8996_usb3phy_reset_l,
 	.num_resets		= ARRAY_SIZE(msm8996_usb3phy_reset_l),
@@ -2785,7 +2780,6 @@ static const struct qmp_phy_cfg sm8250_usb3dpphy_cfg = {
 	.configure_dp_tx	= qmp_v4_configure_dp_tx,
 	.configure_dp_clocks	= qmp_v3_configure_dp_clocks,
 	.configure_dp_phy	= qmp_v4_configure_dp_phy,
-	.calibrate_dp_phy	= qmp_v4_calibrate_dp_phy,
 
 	.reset_list		= msm8996_usb3phy_reset_l,
 	.num_resets		= ARRAY_SIZE(msm8996_usb3phy_reset_l),
@@ -2834,7 +2828,6 @@ static const struct qmp_phy_cfg sm8350_usb3dpphy_cfg = {
 	.configure_dp_tx	= qmp_v4_configure_dp_tx,
 	.configure_dp_clocks	= qmp_v3_configure_dp_clocks,
 	.configure_dp_phy	= qmp_v4_configure_dp_phy,
-	.calibrate_dp_phy	= qmp_v4_calibrate_dp_phy,
 
 	.reset_list		= msm8996_usb3phy_reset_l,
 	.num_resets		= ARRAY_SIZE(msm8996_usb3phy_reset_l),
@@ -2882,7 +2875,6 @@ static const struct qmp_phy_cfg sm8550_usb3dpphy_cfg = {
 	.configure_dp_tx	= qmp_v4_configure_dp_tx,
 	.configure_dp_clocks	= qmp_v3_configure_dp_clocks,
 	.configure_dp_phy	= qmp_v4_configure_dp_phy,
-	.calibrate_dp_phy	= qmp_v4_calibrate_dp_phy,
 
 	.regs			= qmp_v6_usb3phy_regs_layout,
 	.reset_list		= msm8996_usb3phy_reset_l,
@@ -2928,7 +2920,6 @@ static const struct qmp_phy_cfg sm8650_usb3dpphy_cfg = {
 	.configure_dp_tx	= qmp_v4_configure_dp_tx,
 	.configure_dp_clocks	= qmp_v3_configure_dp_clocks,
 	.configure_dp_phy	= qmp_v4_configure_dp_phy,
-	.calibrate_dp_phy	= qmp_v4_calibrate_dp_phy,
 
 	.regs			= qmp_v6_usb3phy_regs_layout,
 	.reset_list		= msm8996_usb3phy_reset_l,
@@ -2974,7 +2965,6 @@ static const struct qmp_phy_cfg sm8750_usb3dpphy_cfg = {
 	.configure_dp_tx	= qmp_v4_configure_dp_tx,
 	.configure_dp_clocks	= qmp_v3_configure_dp_clocks,
 	.configure_dp_phy	= qmp_v4_configure_dp_phy,
-	.calibrate_dp_phy	= qmp_v4_calibrate_dp_phy,
 
 	.regs			= qmp_v8_usb3phy_regs_layout,
 	.reset_list		= msm8996_usb3phy_reset_l,
@@ -3020,7 +3010,6 @@ static const struct qmp_phy_cfg glymur_usb3dpphy_cfg = {
 	.configure_dp_tx	= qmp_v4_configure_dp_tx,
 	.configure_dp_clocks	= qmp_v8_configure_dp_clocks,
 	.configure_dp_phy	= qmp_v8_configure_dp_phy,
-	.calibrate_dp_phy	= qmp_v4_calibrate_dp_phy,
 
 	.regs			= qmp_v8_n3_usb43dpphy_regs_layout,
 	.reset_list		= msm8996_usb3phy_reset_l,
@@ -3316,7 +3305,6 @@ static void qmp_v4_dp_aux_init(struct qmp_combo *qmp)
 	writel(0x03, qmp->dp_dp_phy + QSERDES_DP_PHY_AUX_CFG7);
 	writel(0xb7, qmp->dp_dp_phy + QSERDES_DP_PHY_AUX_CFG8);
 	writel(0x03, qmp->dp_dp_phy + QSERDES_DP_PHY_AUX_CFG9);
-	qmp->dp_aux_cfg = 0;
 
 	writel(PHY_AUX_STOP_ERR_MASK | PHY_AUX_DEC_ERR_MASK |
 	       PHY_AUX_SYNC_ERR_MASK | PHY_AUX_ALIGN_ERR_MASK |
@@ -3345,7 +3333,6 @@ static void qmp_v8_dp_aux_init(struct qmp_combo *qmp)
 	writel(0x03, qmp->dp_dp_phy + QSERDES_DP_PHY_AUX_CFG7);
 	writel(0xb7, qmp->dp_dp_phy + QSERDES_DP_PHY_AUX_CFG8);
 	writel(0x03, qmp->dp_dp_phy + QSERDES_DP_PHY_AUX_CFG9);
-	qmp->dp_aux_cfg = 0;
 
 	writel(PHY_AUX_STOP_ERR_MASK | PHY_AUX_DEC_ERR_MASK |
 	       PHY_AUX_SYNC_ERR_MASK | PHY_AUX_ALIGN_ERR_MASK |
@@ -3605,24 +3592,6 @@ static int qmp_v8_configure_dp_phy(struct qmp_combo *qmp)
 	return 0;
 }
 
-/*
- * We need to calibrate the aux setting here as many times
- * as the caller tries
- */
-static int qmp_v4_calibrate_dp_phy(struct qmp_combo *qmp)
-{
-	static const u8 cfg1_settings[] = { 0x20, 0x13, 0x23, 0x1d };
-	u8 val;
-
-	qmp->dp_aux_cfg++;
-	qmp->dp_aux_cfg %= ARRAY_SIZE(cfg1_settings);
-	val = cfg1_settings[qmp->dp_aux_cfg];
-
-	writel(val, qmp->dp_dp_phy + QSERDES_DP_PHY_AUX_CFG1);
-
-	return 0;
-}
-
 static int qmp_combo_dp_configure(struct phy *phy, union phy_configure_opts *opts)
 {
 	const struct phy_configure_opts_dp *dp_opts = &opts->dp;

-- 
2.54.0




^ permalink raw reply related

* [PATCH 8/8] arm64: defconfig: Add SM8450 camcc
From: Esteban Urrutia via B4 Relay @ 2026-06-23  0:54 UTC (permalink / raw)
  To: Bjorn Andersson, Michael Turquette, Stephen Boyd, Brian Masney,
	Konrad Dybcio, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Rob Clark, Will Deacon, Robin Murphy, Joerg Roedel (AMD),
	Vinod Koul, Neil Armstrong
  Cc: linux-arm-msm, linux-clk, linux-kernel, devicetree, iommu,
	linux-arm-kernel, linux-phy, Esteban Urrutia
In-Reply-To: <20260622-sm8450-qol-v1-0-37e2ee8df9da@proton.me>

From: Esteban Urrutia <esteuwu@proton.me>

Add SM8450 camcc as a module since it's enabled in SM8450 dtsi.

Signed-off-by: Esteban Urrutia <esteuwu@proton.me>
---
 arch/arm64/configs/defconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index f2e6ae93e533..8c50c16ee0b8 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -1541,6 +1541,7 @@ CONFIG_SDX_GCC_75=y
 CONFIG_SM_CAMCC_6350=m
 CONFIG_SM_CAMCC_MILOS=m
 CONFIG_SM_CAMCC_8250=m
+CONFIG_SM_CAMCC_8450=m
 CONFIG_SM_CAMCC_8550=m
 CONFIG_SM_CAMCC_8650=m
 CONFIG_SM_CAMCC_8750=m

-- 
2.54.0




^ permalink raw reply related

* [PATCH 3/8] arm64: dts: qcom: sm8450: Modify GPU operating points
From: Esteban Urrutia via B4 Relay @ 2026-06-23  0:54 UTC (permalink / raw)
  To: Bjorn Andersson, Michael Turquette, Stephen Boyd, Brian Masney,
	Konrad Dybcio, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Rob Clark, Will Deacon, Robin Murphy, Joerg Roedel (AMD),
	Vinod Koul, Neil Armstrong
  Cc: linux-arm-msm, linux-clk, linux-kernel, devicetree, iommu,
	linux-arm-kernel, linux-phy, Esteban Urrutia
In-Reply-To: <20260622-sm8450-qol-v1-0-37e2ee8df9da@proton.me>

From: Esteban Urrutia <esteuwu@proton.me>

These frecuencies don't exist in downstream device trees.
Both 220MHz and 285MHz belong to SM8475, and I'm not sure where 317MHz
came from.

Signed-off-by: Esteban Urrutia <esteuwu@proton.me>
---
 arch/arm64/boot/dts/qcom/sm8450.dtsi | 15 ---------------
 1 file changed, 15 deletions(-)

diff --git a/arch/arm64/boot/dts/qcom/sm8450.dtsi b/arch/arm64/boot/dts/qcom/sm8450.dtsi
index e34e3c05bf74..5e331a25e22a 100644
--- a/arch/arm64/boot/dts/qcom/sm8450.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm8450.dtsi
@@ -2495,21 +2495,6 @@ opp-350000000 {
 					opp-hz = /bits/ 64 <350000000>;
 					opp-level = <RPMH_REGULATOR_LEVEL_LOW_SVS>;
 				};
-
-				opp-317000000 {
-					opp-hz = /bits/ 64 <317000000>;
-					opp-level = <RPMH_REGULATOR_LEVEL_LOW_SVS>;
-				};
-
-				opp-285000000 {
-					opp-hz = /bits/ 64 <285000000>;
-					opp-level = <RPMH_REGULATOR_LEVEL_LOW_SVS_D1>;
-				};
-
-				opp-220000000 {
-					opp-hz = /bits/ 64 <220000000>;
-					opp-level = <RPMH_REGULATOR_LEVEL_LOW_SVS_D1>;
-				};
 			};
 		};
 

-- 
2.54.0




^ permalink raw reply related

* [PATCH 5/8] iommu/arm-smmu-qcom: Add SM8450 MDSS compatible
From: Esteban Urrutia via B4 Relay @ 2026-06-23  0:54 UTC (permalink / raw)
  To: Bjorn Andersson, Michael Turquette, Stephen Boyd, Brian Masney,
	Konrad Dybcio, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Rob Clark, Will Deacon, Robin Murphy, Joerg Roedel (AMD),
	Vinod Koul, Neil Armstrong
  Cc: linux-arm-msm, linux-clk, linux-kernel, devicetree, iommu,
	linux-arm-kernel, linux-phy, Esteban Urrutia
In-Reply-To: <20260622-sm8450-qol-v1-0-37e2ee8df9da@proton.me>

From: Esteban Urrutia <esteuwu@proton.me>

Add the compatible for the MDSS client on the Snapdragon 8 Gen 1 so it
can be properly configured by the IOMMU driver.

Otherwise, there is an unhandled context fault.

Signed-off-by: Esteban Urrutia <esteuwu@proton.me>
---
 drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
index e2c914fccd6f..795e8ec7e8fa 100644
--- a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
+++ b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
@@ -425,6 +425,7 @@ static const struct of_device_id qcom_smmu_client_of_match[] __maybe_unused = {
 	{ .compatible = "qcom,sm6375-mdss" },
 	{ .compatible = "qcom,sm8150-mdss" },
 	{ .compatible = "qcom,sm8250-mdss" },
+	{ .compatible = "qcom,sm8450-mdss" },
 	{ .compatible = "qcom,x1e80100-mdss" },
 	{ }
 };

-- 
2.54.0




^ permalink raw reply related

* Re: [PATCH net v2] net: ethernet: ti: icssg: guard PA stat lookups
From: patchwork-bot+netdevbpf @ 2026-06-23  0:40 UTC (permalink / raw)
  To: Philippe Schenker
  Cc: netdev, philippe.schenker, horms, danishanwar, rogerq,
	linux-arm-kernel, stable, andrew+netdev, devnexen, davem,
	edumazet, jacob.e.keller, kuba, haokexin, m-malladi, pabeni,
	vadim.fedorenko, linux-kernel
In-Reply-To: <20260618093037.3448858-1-dev@pschenker.ch>

Hello:

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

On Thu, 18 Jun 2026 11:30:24 +0200 you wrote:
> From: Philippe Schenker <philippe.schenker@impulsing.ch>
> 
> icssg_ndo_get_stats64() unconditionally calls emac_get_stat_by_name()
> with FW PA stat names regardless of whether the PA stats block is
> present on the hardware.  emac_get_stat_by_name() already guards the
> PA stats lookup with `if (emac->prueth->pa_stats)`; when that pointer
> is NULL the lookup falls through to netdev_err() and returns -EINVAL.
> Because ndo_get_stats64 is polled regularly by the networking stack
> this produces thousands of log entries of the form:
> 
> [...]

Here is the summary with links:
  - [net,v2] net: ethernet: ti: icssg: guard PA stat lookups
    https://git.kernel.org/netdev/net/c/27b9daba5060

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 0/2] KVM: arm64: Fix and test MMIO sign-extending loads
From: Oliver Upton @ 2026-06-23  0:20 UTC (permalink / raw)
  To: Fuad Tabba
  Cc: Marc Zyngier, Joey Gouly, Suzuki K Poulose, Zenghui Yu,
	Steffen Eiden, Catalin Marinas, Will Deacon, Shuah Khan,
	Christoffer Dall, Victor Kamensky, linux-arm-kernel, kvmarm,
	linux-kernel
In-Reply-To: <20260622190701.2039766-1-fuad.tabba@linux.dev>

On Mon, Jun 22, 2026 at 08:06:59PM +0100, Fuad Tabba wrote:
> Hi folks,
> 
> A sign-extending load (LDRSB/LDRSH/LDRSW) from emulated MMIO returns a
> zero-extended value rather than the sign-extended one the architecture
> requires; vcpu_data_host_to_guest() strips the sign bits when it masks
> the data to the access width.
> 
> If my git archeology is right, the masking dates to 2014 (b30070862edbd,
> big-endian support) and has been wrong ever since, but sign-extending
> loads from device memory are rare enough that nobody hit it. Patch 1
> fixes it; patch 2 adds a selftest so it doesn't regress.
> 
> Cheers,
> /fuad
> 
> Fuad Tabba (2):
>   KVM: arm64: Fix sign-extension of MMIO loads
>   KVM: arm64: selftests: Add MMIO sign-extending load test

For the oddball guest :)

Reviewed-by: Oliver Upton <oupton@kernel.org>

Thanks,
Oliver


^ permalink raw reply

* [PATCH] ARM: entry: Convert IRQ handling to generic IRQ entry
From: Linus Walleij @ 2026-06-22 22:52 UTC (permalink / raw)
  To: Paul E. McKenney, Jinjie Ruan, Arnd Bergmann, Russell King,
	Oleg Nesterov, Thomas Gleixner
  Cc: linux-arm-kernel, linux-kernel, Linus Walleij

Bring ARM to the same level of generic-ness as ARM64 by enabling
GENERIC_IRQ_ENTRY.

Route ARM IRQ entry through C wrappers that use the generic IRQ entry
helpers. Conversely put the FIQ entry under the generic NMI-style entry
helpers.

Select GENERIC_IRQ_ENTRY, add the ARM entry prototypes, and provide
regs_irqs_disabled() for the generic IRQ entry return path.

The kernel-mode IRQ return path relies on the generic IRQ entry
preemption handling, matching the arm64 structure and avoiding the old
assembly reschedule check.

The reschedule check is now done in raw_irqentry_exit_cond_resched()
in kernel/entry/common.c.

User-mode IRQs __irq_usr is neither calling ct_user_exit/enter
or asm_trace_hardirqs_off/on anymore. The corresponding calls happen on
irqentry_enter/exit() call paths, e.g the irq-disabled C variants
__ct_user_exit/enter() are called instead.

As __irq_usr no longer returns by jumping to ret_to_user_from_irq,
the corresponding code has been inlined, except the slow_work_pending
part, which is now also handled by generic entry. ret_to_user_from_irq
is only called from v7m so it has been renamed accordingly.

arch_do_signal_or_restart() is required, but we only need a very small
stub, since we keep the existing syscall restart code around in assembly.

Tested on with multi_v7_defconfig and qemu-system-arm vexpress-a15
using vexpress-v2p-ca15-tc1.dtb and some different loads.

A note on V7M: the reason we cannot switch the V7M entry over to generic
entry is that it raises a "pendable service call" ("pendv") exception to
process deferred work at the end of the interrupt handler. This is done
so higher priority work can come in. This has no corresponding structure
in other ARM cores.

This is a reduced patch based on the earlier generic entry series avoiding
all the syscall handling changes.

Link: https://lore.kernel.org/linux-arm-kernel/20250420-arm-generic-entry-v6-0-95f1fcdfeeb2@linaro.org/
Signed-off-by: Linus Walleij <linusw@kernel.org>
---
 arch/arm/Kconfig                    |  1 +
 arch/arm/include/asm/entry-common.h |  7 ++++
 arch/arm/include/asm/entry.h        | 10 +++++
 arch/arm/include/asm/ptrace.h       |  7 +++-
 arch/arm/kernel/Makefile            |  2 +-
 arch/arm/kernel/entry-armv.S        | 75 ++++++++-----------------------------
 arch/arm/kernel/entry-common.S      |  5 ++-
 arch/arm/kernel/entry-header.S      |  7 +++-
 arch/arm/kernel/entry-v7m.S         |  2 +-
 arch/arm/kernel/entry.c             | 51 +++++++++++++++++++++++++
 arch/arm/kernel/irq.c               |  6 +++
 arch/arm/kernel/irq.h               |  2 +
 arch/arm/kernel/signal.c            |  6 +++
 13 files changed, 116 insertions(+), 65 deletions(-)

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 73e6647bea46..aad21d645ff3 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -71,6 +71,7 @@ config ARM
 	select GENERIC_CPU_AUTOPROBE
 	select GENERIC_CPU_DEVICES
 	select GENERIC_EARLY_IOREMAP
+	select GENERIC_IRQ_ENTRY if !CPU_V7M
 	select GENERIC_IDLE_POLL_SETUP
 	select GENERIC_IRQ_MULTI_HANDLER
 	select GENERIC_IRQ_PROBE
diff --git a/arch/arm/include/asm/entry-common.h b/arch/arm/include/asm/entry-common.h
new file mode 100644
index 000000000000..c017df5f39d5
--- /dev/null
+++ b/arch/arm/include/asm/entry-common.h
@@ -0,0 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __ASM_ARM_ENTRY_COMMON_H
+#define __ASM_ARM_ENTRY_COMMON_H
+
+#include <asm/stacktrace.h>
+
+#endif
diff --git a/arch/arm/include/asm/entry.h b/arch/arm/include/asm/entry.h
new file mode 100644
index 000000000000..864c9b3abbf1
--- /dev/null
+++ b/arch/arm/include/asm/entry.h
@@ -0,0 +1,10 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+#ifndef __ASM_ENTRY_H__
+#define __ASM_ENTRY_H__
+
+struct pt_regs;
+
+void arm_irq_handler(struct pt_regs *regs, int mode);
+void arm_fiq_handler(struct pt_regs *regs);
+
+#endif /* __ASM_ENTRY_H__ */
diff --git a/arch/arm/include/asm/ptrace.h b/arch/arm/include/asm/ptrace.h
index 6eb311fb2da0..88ddb9371a02 100644
--- a/arch/arm/include/asm/ptrace.h
+++ b/arch/arm/include/asm/ptrace.h
@@ -46,8 +46,13 @@ struct svc_pt_regs {
 #define processor_mode(regs) \
 	((regs)->ARM_cpsr & MODE_MASK)
 
+static inline bool regs_irqs_disabled(const struct pt_regs *regs)
+{
+	return regs->ARM_cpsr & PSR_I_BIT;
+}
+
 #define interrupts_enabled(regs) \
-	(!((regs)->ARM_cpsr & PSR_I_BIT))
+	(!regs_irqs_disabled(regs))
 
 #define fast_interrupts_enabled(regs) \
 	(!((regs)->ARM_cpsr & PSR_F_BIT))
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
index b36cf0cfd4a7..3b8a62f6f54d 100644
--- a/arch/arm/kernel/Makefile
+++ b/arch/arm/kernel/Makefile
@@ -17,7 +17,7 @@ CFLAGS_REMOVE_return_address.o = -pg
 
 # Object file lists.
 
-obj-y		:= elf.o entry-common.o irq.o opcodes.o \
+obj-y		:= elf.o entry.o entry-common.o irq.o opcodes.o \
 		   process.o ptrace.o reboot.o io.o \
 		   setup.o signal.o sigreturn_codes.o \
 		   stacktrace.o sys_arm.o time.o traps.o
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index a3d050ce9b79..8ac7f1512ee8 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -36,35 +36,6 @@
 #define RELOC_TEXT_NONE
 #endif
 
-/*
- * Interrupt handling.
- */
-	.macro	irq_handler, from_user:req
-	mov	r1, sp
-	ldr_this_cpu r2, irq_stack_ptr, r2, r3
-	.if	\from_user == 0
-	@
-	@ If we took the interrupt while running in the kernel, we may already
-	@ be using the IRQ stack, so revert to the original value in that case.
-	@
-	subs	r3, r2, r1		@ SP above bottom of IRQ stack?
-	rsbscs	r3, r3, #THREAD_SIZE	@ ... and below the top?
-#ifdef CONFIG_VMAP_STACK
-	ldr_va	r3, high_memory, cc	@ End of the linear region
-	cmpcc	r3, r1			@ Stack pointer was below it?
-#endif
-	bcc	0f			@ If not, switch to the IRQ stack
-	mov	r0, r1
-	bl	generic_handle_arch_irq
-	b	1f
-0:
-	.endif
-
-	mov_l	r0, generic_handle_arch_irq
-	bl	call_with_stack
-1:
-	.endm
-
 	.macro	pabt_helper
 	@ PABORT handler takes pt_regs in r2, fault address in r4 and psr in r5
 #ifdef MULTI_PABORT
@@ -224,34 +195,17 @@ ENDPROC(__dabt_svc)
 
 	.align	5
 __irq_svc:
-	svc_entry
-	irq_handler from_user=0
-
-#ifdef CONFIG_PREEMPTION
-	ldr	r8, [tsk, #TI_PREEMPT]		@ get preempt count
-	ldr	r0, [tsk, #TI_FLAGS]		@ get flags
-	teq	r8, #0				@ if preempt count != 0
-	movne	r0, #0				@ force flags to 0
-	tst	r0, #_TIF_NEED_RESCHED
-	blne	svc_preempt
-#endif
+	svc_entry trace=0
+	mov	r0, sp				@ regs
+	mov	r1, #0				@ from kernel mode
+	bl	arm_irq_handler
 
-	svc_exit r5, irq = 1			@ return from exception
+	svc_exit r5, irqentry = 1		@ return from exception
  UNWIND(.fnend		)
 ENDPROC(__irq_svc)
 
 	.ltorg
 
-#ifdef CONFIG_PREEMPTION
-svc_preempt:
-	mov	r8, lr
-1:	bl	preempt_schedule_irq		@ irq en/disable is done inside
-	ldr	r0, [tsk, #TI_FLAGS]		@ get new tasks TI_FLAGS
-	tst	r0, #_TIF_NEED_RESCHED
-	reteq	r8				@ go again
-	b	1b
-#endif
-
 __und_fault:
 	@ Correct the PC such that it is pointing at the instruction
 	@ which caused the fault.  If the faulting instruction was ARM
@@ -302,7 +256,7 @@ ENDPROC(__pabt_svc)
 __fiq_svc:
 	svc_entry trace=0
 	mov	r0, sp				@ struct pt_regs *regs
-	bl	handle_fiq_as_nmi
+	bl	arm_fiq_handler
 	svc_exit_via_fiq
  UNWIND(.fnend		)
 ENDPROC(__fiq_svc)
@@ -331,7 +285,7 @@ __fiq_abt:
 	stmfd	sp!, {r1 - r2}
 
 	add	r0, sp, #8			@ struct pt_regs *regs
-	bl	handle_fiq_as_nmi
+	bl	arm_fiq_handler
 
 	ldmfd	sp!, {r1 - r2}
  ARM(	msr	cpsr_c, #ABT_MODE | PSR_I_BIT | PSR_F_BIT )
@@ -438,12 +392,15 @@ ENDPROC(__dabt_usr)
 
 	.align	5
 __irq_usr:
-	usr_entry
+	usr_entry trace=0
 	kuser_cmpxchg_check
-	irq_handler from_user=1
-	get_thread_info tsk
-	mov	why, #0
-	b	ret_to_user_from_irq
+	mov	r0, sp				@ regs
+	mov	r1, #1				@ from user mode
+	bl	arm_irq_handler
+#ifdef CONFIG_KSTACK_ERASE
+	bl	stackleak_erase_on_task_stack
+#endif
+	restore_user_regs fast = 0, offset = 0
  UNWIND(.fnend		)
 ENDPROC(__irq_usr)
 
@@ -498,7 +455,7 @@ __fiq_usr:
 	usr_entry trace=0
 	kuser_cmpxchg_check
 	mov	r0, sp				@ struct pt_regs *regs
-	bl	handle_fiq_as_nmi
+	bl	arm_fiq_handler
 	get_thread_info tsk
 	restore_user_regs fast = 0, offset = 0
  UNWIND(.fnend		)
diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S
index 88336a1292bb..d5fdb234c1d4 100644
--- a/arch/arm/kernel/entry-common.S
+++ b/arch/arm/kernel/entry-common.S
@@ -110,7 +110,8 @@ ret_slow_syscall:
 	bl	do_rseq_syscall
 #endif
 	disable_irq_notrace			@ disable interrupts
-ENTRY(ret_to_user_from_irq)
+ENTRY(v7m_ret_to_user_from_irq)
+	/* Only the v7m jumps directly to v7m_ret_to_user_from_irq */
 	ldr	r1, [tsk, #TI_FLAGS]
 	movs	r1, r1, lsl #16
 	bne	slow_work_pending
@@ -123,7 +124,7 @@ no_work_pending:
 	bl	stackleak_erase_on_task_stack
 #endif
 	restore_user_regs fast = 0, offset = 0
-ENDPROC(ret_to_user_from_irq)
+ENDPROC(v7m_ret_to_user_from_irq)
 ENDPROC(ret_to_user)
 
 /*
diff --git a/arch/arm/kernel/entry-header.S b/arch/arm/kernel/entry-header.S
index 99411fa91350..e83f2fb8a592 100644
--- a/arch/arm/kernel/entry-header.S
+++ b/arch/arm/kernel/entry-header.S
@@ -199,7 +199,11 @@
 	.endm
 
 
-	.macro	svc_exit, rpsr, irq = 0
+	.macro	svc_exit, rpsr, irq = 0, irqentry = 0
+	.if	\irqentry != 0
+	@ Generic IRQ entry already handled tracing and lockdep state.
+	disable_irq_notrace
+	.else
 	.if	\irq != 0
 	@ IRQs already off
 #ifdef CONFIG_TRACE_IRQFLAGS
@@ -216,6 +220,7 @@
 	tst	\rpsr, #PSR_I_BIT
 	blne	trace_hardirqs_off
 #endif
+	.endif
 	.endif
 	uaccess_exit tsk, r0, r1
 
diff --git a/arch/arm/kernel/entry-v7m.S b/arch/arm/kernel/entry-v7m.S
index 52bacf07ba16..49a3a34e2913 100644
--- a/arch/arm/kernel/entry-v7m.S
+++ b/arch/arm/kernel/entry-v7m.S
@@ -94,7 +94,7 @@ __pendsv_entry:
 	@ execute the pending work, including reschedule
 	get_thread_info tsk
 	mov	why, #0
-	b	ret_to_user_from_irq
+	b	v7m_ret_to_user_from_irq
 ENDPROC(__pendsv_entry)
 
 /*
diff --git a/arch/arm/kernel/entry.c b/arch/arm/kernel/entry.c
new file mode 100644
index 000000000000..1142e418d161
--- /dev/null
+++ b/arch/arm/kernel/entry.c
@@ -0,0 +1,51 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <linux/hardirq.h>
+#include <linux/irq-entry-common.h>
+#include <linux/irq.h>
+
+#include <asm/entry.h>
+#include <asm/stacktrace.h>
+#include <asm/traps.h>
+
+#include "irq.h"
+
+static void noinstr handle_arm_irq(void *data)
+{
+	struct pt_regs *regs = data;
+	struct pt_regs *old_regs;
+
+	irq_enter_rcu();
+	old_regs = set_irq_regs(regs);
+
+	handle_arch_irq(regs);
+
+	set_irq_regs(old_regs);
+	irq_exit_rcu();
+}
+
+noinstr void arm_irq_handler(struct pt_regs *regs, int mode)
+{
+	irqentry_state_t state = irqentry_enter(regs);
+
+	/*
+	 * mode == 1 means we came from userspace, and then we
+	 * should just immediately switch to the irq stack.
+	 * Then we check of we are on the thread stack. If we are
+	 * not, then by definition we are already using the irq stack.
+	 */
+	if (mode == 1 || on_thread_stack())
+		call_on_irq_stack(handle_arm_irq, regs);
+	else
+		handle_arm_irq(regs);
+
+	irqentry_exit(regs, state);
+}
+
+noinstr void arm_fiq_handler(struct pt_regs *regs)
+{
+	irqentry_state_t state = irqentry_nmi_enter(regs);
+
+	handle_fiq_as_nmi(regs);
+
+	irqentry_nmi_exit(regs, state);
+}
diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c
index e1993e28a9ec..f99d6b24d8ff 100644
--- a/arch/arm/kernel/irq.c
+++ b/arch/arm/kernel/irq.c
@@ -43,6 +43,7 @@
 #include <asm/mach/irq.h>
 #include <asm/mach/time.h>
 
+#include "irq.h"
 #include "reboot.h"
 
 unsigned long irq_err_count;
@@ -71,6 +72,11 @@ static void __init init_irq_stacks(void)
 	}
 }
 
+void call_on_irq_stack(void (*fn)(void *), void *arg)
+{
+	call_with_stack(fn, arg, __this_cpu_read(irq_stack_ptr));
+}
+
 #ifdef CONFIG_SOFTIRQ_ON_OWN_STACK
 static void ____do_softirq(void *arg)
 {
diff --git a/arch/arm/kernel/irq.h b/arch/arm/kernel/irq.h
new file mode 100644
index 000000000000..80dd5bfe6403
--- /dev/null
+++ b/arch/arm/kernel/irq.h
@@ -0,0 +1,2 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+void call_on_irq_stack(void (*fn)(void *), void *arg);
diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c
index 7be9188d83d9..9084c04c07f7 100644
--- a/arch/arm/kernel/signal.c
+++ b/arch/arm/kernel/signal.c
@@ -12,6 +12,7 @@
 #include <linux/resume_user_mode.h>
 #include <linux/uprobes.h>
 #include <linux/syscalls.h>
+#include <linux/irq-entry-common.h>
 
 #include <asm/elf.h>
 #include <asm/cacheflush.h>
@@ -599,6 +600,11 @@ static int do_signal(struct pt_regs *regs, int syscall)
 	return 0;
 }
 
+void arch_do_signal_or_restart(struct pt_regs *regs)
+{
+	do_signal(regs, 0);
+}
+
 asmlinkage int
 do_work_pending(struct pt_regs *regs, unsigned int thread_flags, int syscall)
 {

---
base-commit: 8cd9520d35a6c38db6567e97dd93b1f11f185dc6
change-id: 20260622-arm-generic-irq-entry-v7-1-ff6c1d6c9c48

Best regards,
--  
Linus Walleij <linusw@kernel.org>



^ permalink raw reply related

* Re: [PATCH] remoteproc: xlnx: refactor start & stop ops
From: Shah, Tanmay @ 2026-06-22 22:29 UTC (permalink / raw)
  To: Michal Simek, Tanmay Shah, andersson, mathieu.poirier
  Cc: linux-arm-kernel, linux-kernel, linux-remoteproc
In-Reply-To: <4a4e518a-61e6-4beb-aaeb-5056fbe2a07a@amd.com>

Hello,


On 6/22/2026 7:25 AM, Michal Simek wrote:
> 
> 
> On 6/19/26 18:38, Tanmay Shah wrote:
>> Current _start and _stop ops are implemented using various APIs from the
>> platform management firmware driver. Instead provide respective RPU
>> start and stop API in the firmware driver and move the logic to interact
>> with the PM firmware in the firmware driver. The remoteproc driver
>> doesn't
>> need to know actual logic, but only the final result i.e. RPU start/stop
>> was success or not. This refactor keeps the remoteproc driver simple and
>> moves firmware interaction logic to the firmware driver.
>>
>> Signed-off-by: Tanmay Shah <tanmay.shah@amd.com>
>> ---
>>   drivers/firmware/xilinx/zynqmp.c        | 93 +++++++++++++++++++++++++
>>   drivers/remoteproc/xlnx_r5_remoteproc.c | 68 ++----------------
>>   include/linux/firmware/xlnx-zynqmp.h    | 12 ++++
>>   3 files changed, 110 insertions(+), 63 deletions(-)
>>
>> diff --git a/drivers/firmware/xilinx/zynqmp.c b/drivers/firmware/
>> xilinx/zynqmp.c
>> index af838b2dc327..f9a3a95b0638 100644
>> --- a/drivers/firmware/xilinx/zynqmp.c
>> +++ b/drivers/firmware/xilinx/zynqmp.c
>> @@ -1513,6 +1513,99 @@ int zynqmp_pm_request_wake(const u32 node,
>>   }
>>   EXPORT_SYMBOL_GPL(zynqmp_pm_request_wake);
>>   +/**
>> + * zynqmp_pm_start_rpu - Boot Real-time Processing Unit (Cortex-R) on
>> SoC
>> + *
>> + * @node: power-domains id of the core
>> + * @bootaddr: Boot address of elf
>> + *
>> + * Return: status, either success or error+reason
>> + */
>> +int zynqmp_pm_start_rpu(const u32 node, const u64 bootaddr)
>> +{
>> +    enum rpu_boot_mem bootmem;
>> +    int ret;
>> +
>> +    /*
>> +     * The exception vector pointers (EVP) refer to the base-address of
>> +     * exception vectors (for reset, IRQ, FIQ, etc). The reset-vector
>> +     * starts at the base-address and subsequent vectors are on 4-byte
>> +     * boundaries.
>> +     *
>> +     * Exception vectors can start either from 0x0000_0000 (LOVEC) or
>> +     * from 0xFFFF_0000 (HIVEC) which is mapped in the OCM (On-Chip
>> Memory)
> 
> here
> 
>> +     *
>> +     * Usually firmware will put Exception vectors at LOVEC.
>> +     *
>> +     * It is not recommend that you change the exception vector.
>> +     * Changing the EVP to HIVEC will result in increased interrupt
>> latency
>> +     * and jitter. Also, if the OCM is secured and the Cortex-R5F
>> processor
>> +     * is non-secured, then the Cortex-R5F processor cannot access the
>> +     * HIVEC exception vectors in the OCM.
>> +     */
>> +    bootmem = (bootaddr >= 0xFFFC0000) ?
> 
> and here you have different values without any explanation why.
> 

The value in the comment is correct, but the check is done for all of
OCM address range. This is just refactoring of the interfaces and not
the actual logic. There is a separate patch which actually refactors the
logic, I will send it later. I would like to keep this as it is because
this was originally there, and the intent of the commit is not to modify it.

Thanks,
Tanmay

> The rest looks good to me. It is a step in a right direction.
> 
> Thanks,
> Michal
> 



^ permalink raw reply

* Re: [RFC PATCH v2 1/3] mm/huge_memory: make persistent huge zero folio read-only
From: Yang Shi @ 2026-06-22 22:07 UTC (permalink / raw)
  To: David Hildenbrand (Arm), Xueyuan Chen
  Cc: dave.hansen, akpm, linux-mm, linux-kernel, linux-arm-kernel, x86,
	catalin.marinas, will, tglx, mingo, bp, dave.hansen, luto, peterz,
	hpa, ljs, liam, vbabka, rppt, surenb, mhocko, ziy, baolin.wang,
	npache, ryan.roberts, dev.jain, baohua, lance.yang, jannh
In-Reply-To: <f679fc68-5ff6-4715-9a07-9eb3074b2d1e@kernel.org>



On 6/19/26 4:09 AM, David Hildenbrand (Arm) wrote:
> On 6/19/26 04:55, Xueyuan Chen wrote:
>> On Thu, Jun 18, 2026 at 02:36:25PM +0200, David Hildenbrand (Arm) wrote:
>>
>> Hi, David
>>
>> [...]
>>
>>> Best to wait for some feedback.
>> Sure.
>>
>>> I do wonder whether we want to pass an address instead of a page.
>>>
>>> https://lore.kernel.org/r/20260410151746.61150-2-kalyazin@amazon.com
>>>
>>> Wants to convert existing ones as well.
>>>
>>> That would imply that the caller must check for highmem.
>>>
>>> But then, we could just use existing set_memory_ro(), right?
>>>
>> Agreed. Passing an address and reusing the existing set_memory_ro()
>> definitely makes things simpler.
>>
>> However, there is an arm64 specific limitation:
>> currently, the set_memory_r* api on arm64 only support the vmap
>> region and do not handle linear map addresses.
>>
>> If we go this route, should I extend the arm64 set_memory_r*
>> implementation in the next version? The plan would be to make it check
>> for the bblm2 feature and modify the linear map PTEs accordingly.
>> What do you think?
> Good point! It's not really clear on which ranges set_memory*() is supposed to
> work ...
>
> arm64 only works on vmalloc/vmap, x86 and riscv on ordinary directmap ... what a
> mess.

arm64 version works on vmalloc/vmap *and* the linear map alias if rodata 
is on (a.k.a. full before). It should be not hard to make it work for 
linear map address (w/o vmalloc/vmap alias). I think we can just follow 
riscv's implementation by doing:

if (vmalloc or vmap address)
     ...
else if (linear map address)
     ...

Thanks,
Yang

>
> Having a new direct-map specific function with clear semantics might indeed
> avoid even messing with that.
>
> So, yeah, given that we have
>
> 	set_direct_map_invalid_noflush
> 	set_direct_map_default_noflush
> 	set_direct_map_valid_noflush
>
> Let's add a
>
> 	set_direct_map_ro()
>
> Or (my preference)
>
> 	change_direct_map_ro()
>
> But given the existing naming scheme ... maybe just set_direct_map_ro() and
> we'll clean this up another day.
>
>
> Now, should there also be a "_noflush" in there, or who is supposed to flush the
> TLB (or don't we flush at all, because it's used early during boot so far)?
>
> In any case, for this function we should add excessive documentation and define
> clear semantics.
>



^ permalink raw reply

* Re: [PATCH v2 0/5] mm: reduce mmap_lock contention and improve page fault performance
From: Barry Song @ 2026-06-22 21:35 UTC (permalink / raw)
  To: Liam R. Howlett
  Cc: Matthew Wilcox, Suren Baghdasaryan, Lorenzo Stoakes,
	David Hildenbrand (Arm), akpm, linux-mm, vbabka, rppt, mhocko,
	jack, pfalcato, wanglian, chentao, lianux.mm, kunwu.chan,
	liyangouwen1, chrisl, kasong, shikemeng, nphamcs, bhe,
	youngjun.park, linux-arm-kernel, linux-kernel, loongarch,
	linuxppc-dev, linux-riscv, linux-s390, Nanzhe Zhao, Hongru Zhang
In-Reply-To: <c5soxcu245cerfljr2ddto4h7xqksfxzxti47mq6sqn6pnmnxh@th5kxapvnaj3>

On Mon, Jun 22, 2026 at 10:50 PM Liam R. Howlett <liam@infradead.org> wrote:
>
> On 26/06/22 08:15AM, Barry Song wrote:
> > On Mon, Jun 22, 2026 at 4:49 AM Matthew Wilcox <willy@infradead.org> wrote:
> > >
> > > On Sat, Jun 20, 2026 at 04:48:57PM -0700, Suren Baghdasaryan wrote:
> > > > Just checking in on the followup plans. IIUC the RFC mentioned will
> > > > try to implement the solution we discussed at LSFMM: splitting
> > > > VM_FAULT_RETRY into two flags - one for retrying under per-VMA locks
> > > > and another one to fallback to mmap_lock.
> > >
> > > I continue to hate this idea.  I don't believe that those who were
> > > pushing for it have ever tried to understand the whole fault path.
> > > It's utterly byzantine.
> > >
> > > I defy anyone to make sense of this:
> > >
> > >         /*
> > >          * NOTE! This will make us return with VM_FAULT_RETRY, but with
> > >          * the fault lock still held. That's how FAULT_FLAG_RETRY_NOWAIT
> > >          * is supposed to work. We have way too many special cases..
> > >          */
> > >         if (vmf->flags & FAULT_FLAG_RETRY_NOWAIT)
> > >                 return 0;
> > >
> > >         *fpin = maybe_unlock_mmap_for_io(vmf, *fpin);
> > >         if (vmf->flags & FAULT_FLAG_KILLABLE) {
> > >                 if (__folio_lock_killable(folio)) {
> > >                         /*
> > >                          * We didn't have the right flags to drop the
> > >                          * fault lock, but all fault_handlers only check
> > >                          * for fatal signals if we return VM_FAULT_RETRY,
> > >                          * so we need to drop the fault lock here and
> > >                          * return 0 if we don't have a fpin.
> > >                          */
> > >                         if (*fpin == NULL)
> > >                                 release_fault_lock(vmf);
> > >                         return 0;
> > >                 }
> > >
> > > Wed need to simplify the fault path, not add additional complexity.
> > > Josef has said he wouldn't've done the lock dropping had we had per-VMA
> > > locks.  We should rip it out.
> >
> > I think you have agreed that, at least for anon vma, we can
> > keep the current policy, since anon vma is much more volatile
> > than file vma.
>
> I don't think any of the above has to do with anon vmas.  Does any anon
> vma handling have anything to do with your problem?

Hi Liam,

I think there may be a misunderstanding about the motivation behind
this series.

Currently, for both file-backed and anonymous VMAs, when a page fault
cannot lock the required folios—for example, because a folio is under
I/O during a major fault—the fault handler drops any locks it is
holding (either per-VMA locks or the mmap lock) and retries the fault
under the mmap_lock. This page-fault retry pattern requiring the
mmap_lock can lead to significant mmap_lock contention.

The entire purpose of this series is to avoid reacquiring the mmap_lock
where possible, while ensuring that the implementation does not
introduce new priority inversion issues or unnecessary complexity.

We have two possible approaches:

1. Keep the page-fault retry path, but retry under the per-VMA lock
whenever possible. In this case, we would need a flag to indicate
whether the retry should be performed under the per-VMA lock or the
mmap_lock.

2. Remove the page-fault retry path entirely. Instead, wait for the
folio to become lockable while retaining the locks currently held,
and continue the fault handling without retrying the page fault.

Approach 1 is the direction taken by both the current patch and the
RFC that was suggested.

Approach 2 is a potential alternative, but I have never posted an RFC
proposing it.

For Approach 1, the primary concern seems to be the added complexity.

For Approach 2, my concern is the increased risk of priority
inversion. With this approach, we may end up holding a lock while
waiting for I/O completion, potentially for a considerable amount of
time. As a result, a concurrent VMA writer, along with any subsequent
mmap_lock acquirers blocked behind it, could be stalled for an
extended period.

If there is an approach 3, it could be:
for file VMAs, we take approach 2; for anonymous VMAs, we take
approach 1.

>
> This would be needed if anon vmas were being faulted while being
> unmapped or merged?  Do we really need a fast path for that?  Note that
> anon vmas cannot be merged if the vma chain... you know what, I wonder
> how many people know what I'm talking about here... Let's just say that
> they can't be merged if they were around for a fork.

In terms of fork(), this is the concern I raised when considering
approach 2—holding the VMA lock while performing I/O, since a
concurrent fork would need to acquire the VMA write lock.

I had Hongru add some tracing code and run it against the top 200
Android applications in the China market. All of them are heavily
multi-threaded. Unfortunately, we found that 82 of these 200 Android
applications call fork(), and some even call fork() from multiple
threads.

So, although it may be technically a bad idea to call fork() in a
multi-threaded application, it appears that in practice it is still
widely used in real-world applications.

I guess Hongru (Cc-ed) will share his observations later today or
tomorrow.

>
> So, then, we're looking at anon vmas taking the mmap lock on:
> 1. single task anon vmas being expanded and faulted at the same time
> 2. single task anon vmas being unmapped and faulted at the same time
>
> I think that's it?

Yes and no. It could also include mprotect, UFFDIO_REGISTER,
UFFDIO_UNREGISTER, and setting VMA names, etc.

Note that Java GC may also invoke UFFDIO_REGISTER and
UFFDIO_UNREGISTER on Java heaps.

Note that priority inversion can still occur between threads that are
not operating on the same VMA if we take approach 2.

For example:

Thread A: page fault in vma1, holding the VMA lock and waiting for I/O.

Thread B: concurrent write on vma1 (takes mmap_lock and then waits for
the VMA write lock);

Thread C: concurrent write on vma2 or do VMA iteration (acquires
mmap_lock).

In this scenario, Thread C may end up indirectly waiting for Thread A.

>
> But maybe I missed something critical about your use case here?
>
> I don't understand why you are involving anon vmas in this discussion,
> so I must have missed something with your IO completion issue.  Is there
> an anon vma causing your priority inversion?

As explained, the primary goal is to reduce mmap_lock contention by
avoiding taking the mmap_lock whenever possible, while ensuring that
the implementation does not introduce new priority inversion issues.

>
> > Concurrent page faults and VMA modifications can happen more
> > often than with file VMAs.
>
> But it's only a problem for anon vmas with per-vma locking if it's the
> same vma (or the vma lock sequence counter overflows, but let's say
> that's a statistically insignificant non-zero value).
>
> >
> > For file vmas, how much code can we actually remove, given that
> > the first page fault might already be holding mmap_lock?
>
> How much complexity can we remove and maintain the performance, might be
> a better question.

Right, thanks for improving the question.

>
> > It could be the case that lock_vma_under_rcu() fails, and then
> > on the first page fault we end up holding mmap_lock before
> > retrying. So are we also going to rip out the lock release,
> > even if it risks holding mmap_lock for a long time?
> >
> >         vma = lock_vma_under_rcu(mm, addr);
> >         if (!vma)
> >                 goto lock_mmap;
> >        ...
> > lock_mmap:
> >
> >         vma = lock_mm_and_find_vma(mm, addr, regs);
> >         if (unlikely(!vma)) {
> >                 fault = 0;
> >                 si_code = SEGV_MAPERR;
> >                 goto bad_area;
> >         }
> >
> > If we still need to keep the page fault retry code there, it
> > doesn't seem like "ripping out" really reduces complexity in
> > the page fault code?
>
> This seems unrelated to be above complexity that might be the target of
> removal?

I think it is highly related. If we take approach 2—holding locks to
perform I/O and removing the page-fault retry path—we need to
consider whether the same behavior should also apply when we are
already holding the mmap_lock. We should understand the full picture
before focusing on a specific part in isolation.

Thanks
Barry


^ permalink raw reply

* Re: [PATCH] iommu/arm-smmu-v3: Disable PRI when no priq IRQ is available
From: Nicolin Chen @ 2026-06-22 20:51 UTC (permalink / raw)
  To: Breno Leitao
  Cc: Will Deacon, Robin Murphy, Joerg Roedel (AMD), linux-arm-kernel,
	iommu, linux-kernel, rmikey, rneu, kernel-team
In-Reply-To: <20260622-smmu_pri-v1-1-14ad92b6043f@debian.org>

On Mon, Jun 22, 2026 at 09:17:03AM -0700, Breno Leitao wrote:
> When platform firmware advertises an SMMU as PRI-capable in IDR0.PRI
> but does not assign a GSIV for its priq, arm_smmu_setup_unique_irqs()
> warns and continues. ARM_SMMU_FEAT_PRI remains set, so the driver
> still allocates the PRI queue, programs PRIQ_BASE/PROD/CONS, enables
> IRQ_CTRL_PRIQ_IRQEN, and lets IOMMU_DEV_FEAT_IOPF be advertised to
> upper layers. Page Request messages from devices land in a queue no
> one drains, and SVA binds appear to succeed while silently dropping
> every page fault.
> 
> Clear ARM_SMMU_FEAT_PRI in the missing-IRQ path so every PRI-gated
> site in the driver consistently treats the SMMU as PRI-less, instead of
> the half-baked stated.
> 
> Signed-off-by: Breno Leitao <leitao@debian.org>
> ---
>  drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
> index a10affb483a4f..44bafbb38e242 100644
> --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
> +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
> @@ -4659,7 +4659,8 @@ static void arm_smmu_setup_unique_irqs(struct arm_smmu_device *smmu)
>  				dev_warn(smmu->dev,
>  					 "failed to enable priq irq\n");
>  		} else {
> -			dev_warn(smmu->dev, "no priq irq - PRI will be broken\n");
> +			dev_warn(smmu->dev, "no priq irq - disabling PRI\n");
> +			smmu->features &= ~ARM_SMMU_FEAT_PRI;

This is covered by PATCH-7 in my PRI series:
https://lore.kernel.org/linux-iommu/cover.1779944354.git.nicolinc@nvidia.com/

FWIW, changing arm_smmu_setup_unique_irqs() alone isn't complete,
as Sashiko pointed it out:
https://sashiko.dev/#/patchset/20260622-smmu_pri-v1-1-14ad92b6043f%40debian.org

Nicolin


^ permalink raw reply

* Re: [PATCH 3/3] soc: samsung: exynos-pmu: fix error paths in cpuhotplug/idle states setup
From: Peter Griffin @ 2026-06-22 20:43 UTC (permalink / raw)
  To: Alexey Klimov
  Cc: Krzysztof Kozlowski, Alim Akhtar, Sam Protsenko,
	linux-samsung-soc, linux-arm-kernel, linux-kernel, stable,
	Sashiko
In-Reply-To: <DJFT3TXC0OJA.1ZK17YA2RSQXK@linaro.org>

Hi Alexey,

On Mon, 22 Jun 2026 at 19:57, Alexey Klimov <alexey.klimov@linaro.org> wrote:
[..]
> >> >
> >> > I originally made the failure non-fatal because the system still boots
> >> > without the notifiers registered (and all other Arm64 Exynos SoCs
> >> > upstream don't register notifiers and AFAICT have broken cpu hotplug
> >> > and cpu idle).
> >> >
> >> > In hindsight, that seems like a mistake. I think your patch to fully
> >> > unwind everything in case of failure makes more sense.  See small
> >> > comment below about destroy_cpuhp_and_cpuidle()
> >>
> >> Wait, setup_cpuhp_and_cpuidle() should be non-fatal and shouldn't
> >> return any errors?
> >
> > I suggest you re-read my above comment above ^^
>
> Could you please clarify what specifically addresses my question about
> notifiers?

Sure, I was referring to this part of my previous reply:

> >> > In hindsight, that seems like a mistake. I think your patch to fully
> >> > unwind everything in case of failure makes more sense.

[..]
>
> If c2 idles are used during reboot/shutdown then they fail or what?

This followed similar logic to the Samsung downstream kernel drivers.
I have no extra information about it beyond the downstream kernel
source. It seemed reasonable though that CPU's will be hotplugged
during suspend and reboot so you may wish to ignore these.

The proper solution of course is a fully PSCI compliant firmware,
which doesn't require these side channel hints.

>
> I am not saying that patch is correct and some rework is needed but I don't
> get why we should completely ignore errors from hotplug states registration
> and should not check registration of notifiers. At least warning should be
> shown to user that pm functionality might be unreliable.

As mentioned above, and in my previous reply, I think your proposed
patch is a good idea.

regards,

Peter


^ permalink raw reply

* Re: [PATCH 3/4] memory: brcmstb_dpfe: support DPFE API v4
From: Markus Mayer @ 2026-06-22 20:38 UTC (permalink / raw)
  To: Krzysztof Kozlowski
  Cc: Florian Fainelli, Rob Herring, Conor Dooley,
	Linux ARM Kernel List, Device Tree Mailing List,
	Linux Kernel Mailing List
In-Reply-To: <CAGt4E5tGHJFXswic6vTx-ThN2K9xBtO8oA4ybrXg+q5cA6GYCA@mail.gmail.com>

On Thu, 28 May 2026 at 14:45, Markus Mayer <mmayer@broadcom.com> wrote:

> > > Thanks for providing justification, quite reasonable. A pity that none
> > > of the commit msgs answered this way.
> >
> > The real pity is how this API was designed, making all of this
> > necessary in the first place.
> >
> > We can definitely spell out more clearly in the commit messages what
> > is going on and why all of this is needed. I'll pull all the pieces
> > together from the various responses. As long as there's a way we can
> > reasonably implement what we need, we'll be happy.
>
> It has been a minute, but we'd like to resume this effort[1] to
> upstream these changes or some variation thereof.
>
> What are the best steps to resume this undertaking? There are still a
> few topics where I am not entirely clear on how to better explain
> things or how to address the feedback provided. My apologies for that.
> I will do my best to address whatever concerns there are.
>
> Should I put together a new pull request that contains improved commit
> messages and addresses some of the feedback and we hash out whatever
> questions remain on the new thread? Or would it be better for me to
> reply to the old thread with some of the questions that remain before
> sending a revised series?

Any advice on how to best proceed from here?

Thanks,
-Markus

> [1] https://lore.kernel.org/all/20231205184741.3092376-1-mmayer@broadcom.com/


^ permalink raw reply

* [PATCH 2/2] KVM: arm64: selftests: Add MMIO sign-extending load test
From: Fuad Tabba @ 2026-06-22 19:07 UTC (permalink / raw)
  To: Marc Zyngier, Oliver Upton
  Cc: Joey Gouly, Suzuki K Poulose, Zenghui Yu, Steffen Eiden,
	Catalin Marinas, Will Deacon, Shuah Khan, Christoffer Dall,
	Victor Kamensky, linux-arm-kernel, kvmarm, linux-kernel
In-Reply-To: <20260622190701.2039766-1-fuad.tabba@linux.dev>

Add a test for sign-extending MMIO loads (LDRSB, LDRSH, LDRSW) into Xt
and Wt destinations, with and without the sign bit set. The host supplies
the MMIO data and checks the guest register holds the sign-extended value.

Signed-off-by: Fuad Tabba <fuad.tabba@linux.dev>
---
 tools/testing/selftests/kvm/Makefile.kvm      |   1 +
 .../selftests/kvm/arm64/mmio_sign_ext.c       | 133 ++++++++++++++++++
 2 files changed, 134 insertions(+)
 create mode 100644 tools/testing/selftests/kvm/arm64/mmio_sign_ext.c

diff --git a/tools/testing/selftests/kvm/Makefile.kvm b/tools/testing/selftests/kvm/Makefile.kvm
index 9118a5a51b89f..0f5803a1092e1 100644
--- a/tools/testing/selftests/kvm/Makefile.kvm
+++ b/tools/testing/selftests/kvm/Makefile.kvm
@@ -171,6 +171,7 @@ TEST_GEN_PROGS_arm64 += arm64/hello_el2
 TEST_GEN_PROGS_arm64 += arm64/host_sve
 TEST_GEN_PROGS_arm64 += arm64/hypercalls
 TEST_GEN_PROGS_arm64 += arm64/external_aborts
+TEST_GEN_PROGS_arm64 += arm64/mmio_sign_ext
 TEST_GEN_PROGS_arm64 += arm64/page_fault_test
 TEST_GEN_PROGS_arm64 += arm64/psci_test
 TEST_GEN_PROGS_arm64 += arm64/sea_to_user
diff --git a/tools/testing/selftests/kvm/arm64/mmio_sign_ext.c b/tools/testing/selftests/kvm/arm64/mmio_sign_ext.c
new file mode 100644
index 0000000000000..d1efbccd1603a
--- /dev/null
+++ b/tools/testing/selftests/kvm/arm64/mmio_sign_ext.c
@@ -0,0 +1,133 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * mmio_sign_ext - Test sign-extending MMIO load emulation (LDRSB/LDRSH/LDRSW)
+ *
+ * Copyright (c) 2026 Google LLC
+ */
+
+#include "processor.h"
+#include "test_util.h"
+
+#define MMIO_ADDR	0x8000000ULL
+
+struct mmio_test {
+	const char *name;
+	uint64_t data;
+	uint8_t len;
+	uint64_t expected;
+};
+
+/* Paired 1:1, in order, with the loads in guest_code() below. */
+static const struct mmio_test tests[] = {
+	/* LDRSB Xt: byte sign-extended to 64 bits */
+	{ "LDRSB Xt 0xFF",	0xFF,		1, 0xFFFFFFFFFFFFFFFFULL },
+	{ "LDRSB Xt 0x7F",	0x7F,		1, 0x7FULL },
+
+	/* LDRSB Wt: byte sign-extended to 32 bits, upper 32 bits zeroed */
+	{ "LDRSB Wt 0xFF",	0xFF,		1, 0xFFFFFFFFULL },
+	{ "LDRSB Wt 0x7F",	0x7F,		1, 0x7FULL },
+
+	/* LDRSH Xt: halfword sign-extended to 64 bits */
+	{ "LDRSH Xt 0x8001",	0x8001,		2, 0xFFFFFFFFFFFF8001ULL },
+	{ "LDRSH Xt 0x7FFF",	0x7FFF,		2, 0x7FFFULL },
+
+	/* LDRSH Wt: halfword sign-extended to 32 bits, upper 32 bits zeroed */
+	{ "LDRSH Wt 0x8001",	0x8001,		2, 0xFFFF8001ULL },
+	{ "LDRSH Wt 0x7FFF",	0x7FFF,		2, 0x7FFFULL },
+
+	/* LDRSW Xt: word sign-extended to 64 bits (no Wt form) */
+	{ "LDRSW Xt 0x80000001", 0x80000001,	4, 0xFFFFFFFF80000001ULL },
+	{ "LDRSW Xt 0x7FFFFFFF", 0x7FFFFFFF,	4, 0x7FFFFFFFULL },
+};
+
+static void guest_code(void)
+{
+	uint64_t val;
+
+	asm volatile("ldrsb %0, [%1]" : "=r"(val) : "r"(MMIO_ADDR) : "memory");
+	GUEST_SYNC(val);
+
+	asm volatile("ldrsb %0, [%1]" : "=r"(val) : "r"(MMIO_ADDR) : "memory");
+	GUEST_SYNC(val);
+
+	asm volatile("ldrsb %w0, [%1]" : "=r"(val) : "r"(MMIO_ADDR) : "memory");
+	GUEST_SYNC(val);
+
+	asm volatile("ldrsb %w0, [%1]" : "=r"(val) : "r"(MMIO_ADDR) : "memory");
+	GUEST_SYNC(val);
+
+	asm volatile("ldrsh %0, [%1]" : "=r"(val) : "r"(MMIO_ADDR) : "memory");
+	GUEST_SYNC(val);
+
+	asm volatile("ldrsh %0, [%1]" : "=r"(val) : "r"(MMIO_ADDR) : "memory");
+	GUEST_SYNC(val);
+
+	asm volatile("ldrsh %w0, [%1]" : "=r"(val) : "r"(MMIO_ADDR) : "memory");
+	GUEST_SYNC(val);
+
+	asm volatile("ldrsh %w0, [%1]" : "=r"(val) : "r"(MMIO_ADDR) : "memory");
+	GUEST_SYNC(val);
+
+	asm volatile("ldrsw %0, [%1]" : "=r"(val) : "r"(MMIO_ADDR) : "memory");
+	GUEST_SYNC(val);
+
+	asm volatile("ldrsw %0, [%1]" : "=r"(val) : "r"(MMIO_ADDR) : "memory");
+	GUEST_SYNC(val);
+
+	GUEST_DONE();
+}
+
+static void handle_mmio(struct kvm_run *run, const struct mmio_test *t)
+{
+	TEST_ASSERT_EQ(run->mmio.phys_addr, MMIO_ADDR);
+	TEST_ASSERT(!run->mmio.is_write, "Expected MMIO read for %s", t->name);
+	TEST_ASSERT_EQ(run->mmio.len, t->len);
+
+	memset(run->mmio.data, 0, sizeof(run->mmio.data));
+	/* Works because arm64 KVM hosts are always little-endian. */
+	memcpy(run->mmio.data, &t->data, t->len);
+}
+
+int main(void)
+{
+	struct kvm_vcpu *vcpu;
+	struct kvm_vm *vm;
+	struct ucall uc;
+	unsigned int i;
+
+	vm = vm_create_with_one_vcpu(&vcpu, guest_code);
+	virt_map(vm, MMIO_ADDR, MMIO_ADDR, 1);
+
+	ksft_print_header();
+	ksft_set_plan(ARRAY_SIZE(tests));
+
+	for (i = 0; i < ARRAY_SIZE(tests); i++) {
+		const struct mmio_test *t = &tests[i];
+
+		vcpu_run(vcpu);
+		TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_MMIO);
+
+		handle_mmio(vcpu->run, t);
+		vcpu_run(vcpu);
+
+		switch (get_ucall(vcpu, &uc)) {
+		case UCALL_SYNC:
+			TEST_ASSERT_EQ(uc.args[1], t->expected);
+			break;
+		case UCALL_ABORT:
+			REPORT_GUEST_ASSERT(uc);
+			break;
+		default:
+			TEST_FAIL("Unexpected ucall for %s", t->name);
+		}
+
+		ksft_test_result_pass("%s\n", t->name);
+	}
+
+	vcpu_run(vcpu);
+	TEST_ASSERT(get_ucall(vcpu, &uc) == UCALL_DONE, "Expected UCALL_DONE");
+
+	kvm_vm_free(vm);
+
+	ksft_finished();
+}
-- 
2.39.5



^ permalink raw reply related

* [PATCH 1/2] KVM: arm64: Fix sign-extension of MMIO loads
From: Fuad Tabba @ 2026-06-22 19:07 UTC (permalink / raw)
  To: Marc Zyngier, Oliver Upton
  Cc: Joey Gouly, Suzuki K Poulose, Zenghui Yu, Steffen Eiden,
	Catalin Marinas, Will Deacon, Shuah Khan, Christoffer Dall,
	Victor Kamensky, linux-arm-kernel, kvmarm, linux-kernel
In-Reply-To: <20260622190701.2039766-1-fuad.tabba@linux.dev>

A sign-extending load from MMIO (LDRSB, LDRSH, LDRSW) delivers a
zero-extended value: in kvm_handle_mmio_return(), vcpu_data_host_to_guest()
masks the data to the access width after sign-extension, stripping the
sign bits.

Move vcpu_data_host_to_guest() ahead of sign-extension so the width mask
runs first. trace_kvm_mmio() moves with it and keeps reporting the raw
access-width data.

Fixes: b30070862edbd ("ARM64: KVM: MMIO support BE host running LE code")
Signed-off-by: Fuad Tabba <fuad.tabba@linux.dev>
---
 arch/arm64/kvm/mmio.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/arch/arm64/kvm/mmio.c b/arch/arm64/kvm/mmio.c
index e2285ed8c91de..d1c3a352d5a22 100644
--- a/arch/arm64/kvm/mmio.c
+++ b/arch/arm64/kvm/mmio.c
@@ -126,6 +126,10 @@ int kvm_handle_mmio_return(struct kvm_vcpu *vcpu)
 		len = kvm_vcpu_dabt_get_as(vcpu);
 		data = kvm_mmio_read_buf(run->mmio.data, len);
 
+		trace_kvm_mmio(KVM_TRACE_MMIO_READ, len, run->mmio.phys_addr,
+			       &data);
+		data = vcpu_data_host_to_guest(vcpu, data, len);
+
 		if (kvm_vcpu_dabt_issext(vcpu) &&
 		    len < sizeof(unsigned long)) {
 			mask = 1U << ((len * 8) - 1);
@@ -135,9 +139,6 @@ int kvm_handle_mmio_return(struct kvm_vcpu *vcpu)
 		if (!kvm_vcpu_dabt_issf(vcpu))
 			data = data & 0xffffffff;
 
-		trace_kvm_mmio(KVM_TRACE_MMIO_READ, len, run->mmio.phys_addr,
-			       &data);
-		data = vcpu_data_host_to_guest(vcpu, data, len);
 		vcpu_set_reg(vcpu, kvm_vcpu_dabt_get_rd(vcpu), data);
 	}
 
-- 
2.39.5



^ permalink raw reply related

* [PATCH 0/2] KVM: arm64: Fix and test MMIO sign-extending loads
From: Fuad Tabba @ 2026-06-22 19:06 UTC (permalink / raw)
  To: Marc Zyngier, Oliver Upton
  Cc: Joey Gouly, Suzuki K Poulose, Zenghui Yu, Steffen Eiden,
	Catalin Marinas, Will Deacon, Shuah Khan, Christoffer Dall,
	Victor Kamensky, linux-arm-kernel, kvmarm, linux-kernel

Hi folks,

A sign-extending load (LDRSB/LDRSH/LDRSW) from emulated MMIO returns a
zero-extended value rather than the sign-extended one the architecture
requires; vcpu_data_host_to_guest() strips the sign bits when it masks
the data to the access width.

If my git archeology is right, the masking dates to 2014 (b30070862edbd,
big-endian support) and has been wrong ever since, but sign-extending
loads from device memory are rare enough that nobody hit it. Patch 1
fixes it; patch 2 adds a selftest so it doesn't regress.

Cheers,
/fuad

Fuad Tabba (2):
  KVM: arm64: Fix sign-extension of MMIO loads
  KVM: arm64: selftests: Add MMIO sign-extending load test

 arch/arm64/kvm/mmio.c                         |   7 +-
 tools/testing/selftests/kvm/Makefile.kvm      |   1 +
 .../selftests/kvm/arm64/mmio_sign_ext.c       | 133 ++++++++++++++++++
 3 files changed, 138 insertions(+), 3 deletions(-)
 create mode 100644 tools/testing/selftests/kvm/arm64/mmio_sign_ext.c


base-commit: 8cd9520d35a6c38db6567e97dd93b1f11f185dc6
-- 
2.39.5



^ permalink raw reply

* Re: [PATCH 3/3] soc: samsung: exynos-pmu: fix error paths in cpuhotplug/idle states setup
From: Alexey Klimov @ 2026-06-22 18:57 UTC (permalink / raw)
  To: Peter Griffin
  Cc: Krzysztof Kozlowski, Alim Akhtar, Sam Protsenko,
	linux-samsung-soc, linux-arm-kernel, linux-kernel, stable,
	Sashiko
In-Reply-To: <CADrjBPqF6GPRLNUZtzkGUHTUQ6NOPoaRvVvF1mUUj_DJ9As1dg@mail.gmail.com>

Hi Peter,

On Thu Jun 11, 2026 at 8:07 AM BST, Peter Griffin wrote:
> Hi Alexey,
>
> On Wed, 10 Jun 2026 at 16:07, Alexey Klimov <alexey.klimov@linaro.org> wrote:
>>
>> On Wed Jun 10, 2026 at 2:34 PM BST, Peter Griffin wrote:
>> > Hi Alexey,
>>
>> Hi Peter,
>>
>> > Thanks for your patch!
>> >
>> > On Fri, 5 Jun 2026 at 21:19, Alexey Klimov <alexey.klimov@linaro.org> wrote:
>> >>
>> >> The setup_cpuhp_and_cpuidle() initialisation sequence currently ignores
>> >> the return values of cpuhp_setup_state(), cpu_pm_register_notifier(), and
>> >> register_reboot_notifier(). If any of these registrations fail during
>> >> probe() routine, the driver returns 0, leaving the driver partially
>> >> configured.
>> >
>> > I originally made the failure non-fatal because the system still boots
>> > without the notifiers registered (and all other Arm64 Exynos SoCs
>> > upstream don't register notifiers and AFAICT have broken cpu hotplug
>> > and cpu idle).
>> >
>> > In hindsight, that seems like a mistake. I think your patch to fully
>> > unwind everything in case of failure makes more sense.  See small
>> > comment below about destroy_cpuhp_and_cpuidle()
>>
>> Wait, setup_cpuhp_and_cpuidle() should be non-fatal and shouldn't
>> return any errors?
>
> I suggest you re-read my above comment above ^^

Could you please clarify what specifically addresses my question about
notifiers?

Looking further into this, it seems that, for instance, if one of the
hotplug states fails to register then tracking of pmu_context->in_cpuhp
becomes broken.
If reboot notifier silently fails to be registered, then it is unclear how
this from gs101_cpu_pmu_offline() supposed to work:

/* Ignore CPU_PM_ENTER event in reboot or suspend sequence. */
if (pmu_context->sys_insuspend || pmu_context->sys_inreboot) {
	raw_spin_unlock(&pmu_context->cpupm_lock);
	return NOTIFY_OK;
}

If c2 idles are used during reboot/shutdown then they fail or what?

I am not saying that patch is correct and some rework is needed but I don't
get why we should completely ignore errors from hotplug states registration
and should not check registration of notifiers. At least warning should be
shown to user that pm functionality might be unreliable.

Best regards,
Alexey.



^ permalink raw reply

* [linusw-nomadik:ux500-power-domains-v7.1] BUILD REGRESSION 10278e18bc5a61397cb538310a6388075a4f21dd
From: kernel test robot @ 2026-06-22 18:42 UTC (permalink / raw)
  To: Linus Walleij; +Cc: linux-arm-kernel

tree/branch: https://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-nomadik.git ux500-power-domains-v7.1
branch HEAD: 10278e18bc5a61397cb538310a6388075a4f21dd  ARM: dts: ux500: Remove DB8500 EPOD regulators

Error/Warning (recently discovered and may have been fixed):

    https://lore.kernel.org/oe-kbuild-all/202606180825.vUSQntkJ-lkp@intel.com

    include/linux/mfd/dbx500-prcmu.h:408:19: error: redefinition of 'prcmu_abb_read'
    include/linux/mfd/dbx500-prcmu.h:413:19: error: redefinition of 'prcmu_abb_write'
    include/linux/mfd/dbx500-prcmu.h:424:19: error: redefinition of 'prcmu_config_clkout'
    include/linux/mfd/dbx500-prcmu.h:486:19: error: redefinition of 'prcmu_ac_wake_req'
    include/linux/mfd/dbx500-prcmu.h:491:20: error: redefinition of 'prcmu_ac_sleep_req'

Error/Warning ids grouped by kconfigs:

recent_errors
|-- arc-allmodconfig
|   |-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_abb_read
|   |-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_abb_write
|   |-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_ac_sleep_req
|   |-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_ac_wake_req
|   `-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_config_clkout
|-- arc-allyesconfig
|   |-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_abb_read
|   |-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_abb_write
|   |-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_ac_sleep_req
|   |-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_ac_wake_req
|   `-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_config_clkout
|-- arm-randconfig-004-20260622
|   |-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_abb_read
|   |-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_abb_write
|   |-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_ac_sleep_req
|   |-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_ac_wake_req
|   `-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_config_clkout
|-- arm64-allmodconfig
|   |-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_abb_read
|   |-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_abb_write
|   |-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_ac_sleep_req
|   |-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_ac_wake_req
|   `-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_config_clkout
|-- i386-allmodconfig
|   |-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_abb_read
|   |-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_abb_write
|   |-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_ac_sleep_req
|   |-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_ac_wake_req
|   `-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_config_clkout
|-- i386-allyesconfig
|   |-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_abb_read
|   |-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_abb_write
|   |-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_ac_sleep_req
|   |-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_ac_wake_req
|   `-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_config_clkout
|-- loongarch-allmodconfig
|   |-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_abb_read
|   |-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_abb_write
|   |-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_ac_sleep_req
|   |-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_ac_wake_req
|   `-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_config_clkout
|-- loongarch-randconfig-001-20260622
|   |-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_abb_read
|   |-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_abb_write
|   |-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_ac_sleep_req
|   |-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_ac_wake_req
|   `-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_config_clkout
|-- loongarch-randconfig-002-20260622
|   |-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_abb_read
|   |-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_abb_write
|   |-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_ac_sleep_req
|   |-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_ac_wake_req
|   `-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_config_clkout
|-- mips-allmodconfig
|   |-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_abb_read
|   |-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_abb_write
|   |-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_ac_sleep_req
|   |-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_ac_wake_req
|   `-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_config_clkout
|-- mips-allyesconfig
|   |-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_abb_read
|   |-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_abb_write
|   |-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_ac_sleep_req
|   |-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_ac_wake_req
|   `-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_config_clkout
|-- powerpc-allmodconfig
|   |-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_abb_read
|   |-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_abb_write
|   |-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_ac_sleep_req
|   |-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_ac_wake_req
|   `-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_config_clkout
|-- powerpc-randconfig-002-20260622
|   |-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_abb_read
|   |-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_abb_write
|   |-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_ac_sleep_req
|   |-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_ac_wake_req
|   `-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_config_clkout
|-- powerpc64-randconfig-001-20260622
|   |-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_abb_read
|   |-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_abb_write
|   |-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_ac_sleep_req
|   |-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_ac_wake_req
|   `-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_config_clkout
|-- riscv-allmodconfig
|   |-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_abb_read
|   |-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_abb_write
|   |-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_ac_sleep_req
|   |-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_ac_wake_req
|   `-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_config_clkout
|-- riscv-allyesconfig
|   |-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_abb_read
|   |-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_abb_write
|   |-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_ac_sleep_req
|   |-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_ac_wake_req
|   `-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_config_clkout
|-- sh-allmodconfig
|   |-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_abb_read
|   |-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_abb_write
|   |-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_ac_sleep_req
|   |-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_ac_wake_req
|   `-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_config_clkout
|-- sh-allyesconfig
|   |-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_abb_read
|   |-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_abb_write
|   |-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_ac_sleep_req
|   |-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_ac_wake_req
|   `-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_config_clkout
|-- sparc64-allmodconfig
|   |-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_abb_read
|   |-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_abb_write
|   |-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_ac_sleep_req
|   |-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_ac_wake_req
|   `-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_config_clkout
|-- um-allmodconfig
|   |-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_abb_read
|   |-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_abb_write
|   |-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_ac_sleep_req
|   |-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_ac_wake_req
|   `-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_config_clkout
|-- um-allyesconfig
|   |-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_abb_read
|   |-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_abb_write
|   |-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_ac_sleep_req
|   |-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_ac_wake_req
|   `-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_config_clkout
|-- x86_64-allmodconfig
|   |-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_abb_read
|   |-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_abb_write
|   |-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_ac_sleep_req
|   |-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_ac_wake_req
|   `-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_config_clkout
|-- x86_64-allyesconfig
|   |-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_abb_read
|   |-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_abb_write
|   |-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_ac_sleep_req
|   |-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_ac_wake_req
|   `-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_config_clkout
|-- xtensa-allyesconfig
|   |-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_abb_read
|   |-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_abb_write
|   |-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_ac_sleep_req
|   |-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_ac_wake_req
|   `-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_config_clkout
`-- xtensa-randconfig-001-20260622
    |-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_abb_read
    |-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_abb_write
    |-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_ac_sleep_req
    |-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_ac_wake_req
    `-- include-linux-mfd-dbx500-prcmu.h:error:redefinition-of-prcmu_config_clkout

elapsed time: 952m

configs tested: 148
configs skipped: 2

tested configs:
alpha                             allnoconfig    gcc-16.1.0
alpha                            allyesconfig    gcc-16.1.0
alpha                               defconfig    gcc-16.1.0
arc                              allmodconfig    gcc-16.1.0
arc                               allnoconfig    gcc-16.1.0
arc                              allyesconfig    gcc-16.1.0
arc                                 defconfig    gcc-16.1.0
arc                   randconfig-001-20260622    gcc-15.2.0
arc                   randconfig-002-20260622    gcc-9.5.0
arm                               allnoconfig    clang-23
arm                              allyesconfig    gcc-16.1.0
arm                                 defconfig    clang-23
arm                   randconfig-001-20260622    gcc-13.4.0
arm                   randconfig-002-20260622    clang-23
arm                   randconfig-003-20260622    gcc-8.5.0
arm                   randconfig-004-20260622    gcc-15.2.0
arm64                            allmodconfig    clang-23
arm64                             allnoconfig    gcc-16.1.0
arm64                               defconfig    gcc-16.1.0
arm64                 randconfig-001-20260622    gcc-8.5.0
arm64                 randconfig-002-20260622    gcc-13.4.0
arm64                 randconfig-003-20260622    gcc-8.5.0
arm64                 randconfig-004-20260622    clang-22
csky                             allmodconfig    gcc-16.1.0
csky                              allnoconfig    gcc-16.1.0
csky                                defconfig    gcc-16.1.0
csky                  randconfig-001-20260622    gcc-13.4.0
csky                  randconfig-002-20260622    gcc-11.5.0
hexagon                          allmodconfig    clang-23
hexagon                           allnoconfig    clang-23
hexagon                             defconfig    clang-23
hexagon               randconfig-001-20260622    clang-23
hexagon               randconfig-002-20260622    clang-23
i386                             allmodconfig    gcc-14
i386                              allnoconfig    gcc-14
i386                             allyesconfig    gcc-14
i386        buildonly-randconfig-001-20260622    gcc-14
i386        buildonly-randconfig-002-20260622    clang-22
i386        buildonly-randconfig-003-20260622    gcc-14
i386        buildonly-randconfig-004-20260622    gcc-12
i386        buildonly-randconfig-005-20260622    gcc-14
i386        buildonly-randconfig-006-20260622    gcc-14
i386                                defconfig    clang-22
i386                  randconfig-011-20260622    gcc-14
i386                  randconfig-012-20260622    clang-22
i386                  randconfig-013-20260622    gcc-14
i386                  randconfig-014-20260622    clang-22
i386                  randconfig-015-20260622    clang-22
i386                  randconfig-016-20260622    clang-22
i386                  randconfig-017-20260622    clang-22
loongarch                        allmodconfig    clang-19
loongarch                         allnoconfig    clang-20
loongarch                           defconfig    clang-23
loongarch             randconfig-001-20260622    clang-18
loongarch             randconfig-002-20260622    clang-18
m68k                             allmodconfig    gcc-16.1.0
m68k                              allnoconfig    gcc-16.1.0
m68k                             allyesconfig    gcc-16.1.0
m68k                                defconfig    gcc-16.1.0
microblaze                        allnoconfig    gcc-16.1.0
microblaze                       allyesconfig    gcc-16.1.0
microblaze                          defconfig    gcc-16.1.0
mips                             allmodconfig    gcc-16.1.0
mips                              allnoconfig    gcc-16.1.0
mips                             allyesconfig    gcc-16.1.0
nios2                            allmodconfig    gcc-11.5.0
nios2                             allnoconfig    gcc-11.5.0
nios2                               defconfig    gcc-11.5.0
nios2                 randconfig-001-20260622    gcc-8.5.0
nios2                 randconfig-002-20260622    gcc-8.5.0
openrisc                         allmodconfig    gcc-16.1.0
openrisc                          allnoconfig    gcc-16.1.0
openrisc                            defconfig    gcc-16.1.0
parisc                           allmodconfig    gcc-16.1.0
parisc                            allnoconfig    gcc-16.1.0
parisc                           allyesconfig    gcc-16.1.0
parisc                              defconfig    gcc-16.1.0
parisc                randconfig-001-20260622    gcc-14.3.0
parisc                randconfig-002-20260622    gcc-12.5.0
parisc64                            defconfig    gcc-16.1.0
powerpc                          allmodconfig    gcc-16.1.0
powerpc                           allnoconfig    gcc-16.1.0
powerpc               randconfig-001-20260622    gcc-8.5.0
powerpc               randconfig-002-20260622    gcc-8.5.0
powerpc64             randconfig-001-20260622    clang-21
powerpc64             randconfig-002-20260622    clang-20
riscv                            allmodconfig    clang-23
riscv                             allnoconfig    gcc-16.1.0
riscv                            allyesconfig    clang-23
riscv                               defconfig    clang-23
riscv                 randconfig-001-20260622    clang-23
s390                             allmodconfig    clang-23
s390                              allnoconfig    clang-23
s390                             allyesconfig    gcc-16.1.0
s390                                defconfig    clang-18
s390                  randconfig-001-20260622    gcc-14.3.0
s390                  randconfig-002-20260622    clang-23
sh                               allmodconfig    gcc-16.1.0
sh                                allnoconfig    gcc-16.1.0
sh                               allyesconfig    gcc-16.1.0
sh                                  defconfig    gcc-16.1.0
sh                    randconfig-001-20260622    gcc-13.4.0
sh                    randconfig-002-20260622    gcc-15.2.0
sparc                             allnoconfig    gcc-16.1.0
sparc                               defconfig    gcc-16.1.0
sparc                          randconfig-001    gcc-16.1.0
sparc                 randconfig-001-20260622    gcc-16.1.0
sparc                          randconfig-002    gcc-11.5.0
sparc                 randconfig-002-20260622    gcc-8.5.0
sparc64                          allmodconfig    clang-20
sparc64                             defconfig    clang-23
sparc64                        randconfig-001    gcc-12.5.0
sparc64               randconfig-001-20260622    gcc-16.1.0
sparc64                        randconfig-002    clang-20
sparc64               randconfig-002-20260622    clang-23
um                               allmodconfig    clang-23
um                                allnoconfig    clang-16
um                               allyesconfig    gcc-14
um                                  defconfig    clang-23
um                             i386_defconfig    gcc-14
um                             randconfig-001    clang-23
um                    randconfig-001-20260622    gcc-14
um                             randconfig-002    clang-23
um                    randconfig-002-20260622    gcc-14
x86_64                           allmodconfig    clang-22
x86_64                            allnoconfig    clang-22
x86_64                           allyesconfig    clang-22
x86_64      buildonly-randconfig-001-20260622    clang-22
x86_64      buildonly-randconfig-002-20260622    clang-22
x86_64      buildonly-randconfig-003-20260622    clang-22
x86_64      buildonly-randconfig-004-20260622    clang-22
x86_64      buildonly-randconfig-005-20260622    gcc-14
x86_64      buildonly-randconfig-006-20260622    clang-22
x86_64                              defconfig    gcc-14
x86_64                randconfig-002-20260622    gcc-14
x86_64                randconfig-011-20260622    clang-22
x86_64                randconfig-012-20260622    clang-22
x86_64                randconfig-013-20260622    gcc-14
x86_64                randconfig-014-20260622    gcc-14
x86_64                randconfig-015-20260622    clang-22
x86_64                randconfig-016-20260622    clang-22
x86_64                          rhel-9.4-rust    clang-22
xtensa                            allnoconfig    gcc-16.1.0
xtensa                           allyesconfig    gcc-16.1.0
xtensa                         randconfig-001    gcc-8.5.0
xtensa                randconfig-001-20260622    gcc-16.1.0
xtensa                         randconfig-002    gcc-13.4.0
xtensa                randconfig-002-20260622    gcc-8.5.0

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki


^ permalink raw reply

* Re: [PATCH RFC v8 01/24] mm: Introduce kpkeys
From: David Hildenbrand (Arm) @ 2026-06-22 18:38 UTC (permalink / raw)
  To: Linus Walleij
  Cc: Kevin Brodsky, linux-hardening, Andrew Morton, Andy Lutomirski,
	Catalin Marinas, Dave Hansen, Ira Weiny, Jann Horn, Jeff Xu,
	Joey Gouly, Kees Cook, Marc Zyngier, Mark Brown, Matthew Wilcox,
	Maxwell Bland, Mike Rapoport (IBM), Peter Zijlstra,
	Pierre Langlois, Quentin Perret, Rick Edgecombe, Ryan Roberts,
	Vlastimil Babka, Will Deacon, Yang Shi, Yeoreum Yun,
	linux-arm-kernel, linux-mm, x86, Lorenzo Stoakes, Thomas Gleixner
In-Reply-To: <CAD++jL=km9hqTuTMFUhyx_QPuMEwWqmnUVQtPtMXnp8paHH1_A@mail.gmail.com>

On 6/18/26 15:22, Linus Walleij wrote:
> On Tue, Jun 16, 2026 at 5:19 PM David Hildenbrand (Arm)
> <david@kernel.org> wrote:
> 
>> Looking at this, and wondering about "why do we get registers involved in this
>> API" I would probably have an interface like:
>>
>>         arch_kpkeys_enter_context()
>>         arch_kpkeys_leave_context()
>>
>> Whereby you return a "struct kpkeys_state" or sth like that.
> 
> This is close to what I was looking for as well.

Cool :)

> 
> enter/leave makes the code look more like generic entry.
> 
> Passing some kind of state cookie around is inevitable in
> this design and IIUC Kevin argued that it would be inefficient
> (another level of abstraction) as opposed to just hammering
> in the context we want, where we want it.
> 
> But I think the compiler will optimize that out by constant
> propagation if the backing architecture implementation is
> simple.

Yes, it should be wrapped somehow. I don't think this will be a problem
performance-wise that cannot be solved differently.

Returning an u64 ("register") here is really arm64-sepcific and should be
abstracted.

-- 
Cheers,

David


^ permalink raw reply

* [GIT PULL] Mailbox changes for v7.2
From: Jassi Brar @ 2026-06-22 18:37 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: Linux Kernel Mailing List, linux-arm-kernel

Hi Linus,
The following changes since commit 5200f5f493f79f14bbdc349e402a40dfb32f23c8:

  Linux 7.1-rc4 (2026-05-17 13:59:58 -0700)

are available in the Git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/jassibrar/mailbox.git
tags/mailbox-v7.2

for you to fetch changes up to 36cac4b5101f8ecbc851356df175b99543c84ec6:

  mailbox: imx: Don't force-thread the primary handler (2026-06-20
21:18:39 -0500)

----------------------------------------------------------------
mailbox: updates for v7.2

- core: add debugfs support for used channels, fix resource leak on
startup failure, propagate tx error codes, and clarify blocking mode
thread support
- exynos: remove unused register definitions
- imx: refactor IRQ handlers, migrate to devm helpers, and other minor
improvements
- mpfs: fix syscon presence check in inbox ISR
- mtk-adsp: fix use-after-free during device teardown
- qcom: add dt-bindings for QCOM Maili, Hawi, Shikra APCS, and Nord
CPUCP platform support

----------------------------------------------------------------
Chunkai Deng (1):
      dt-bindings: mailbox: qcom: Add IPCC support for Maili Platform

Conor Dooley (1):
      mailbox: mpfs: fix check for syscon presence in mpfs_mbox_inbox_isr()

Deepti Jaggi (2):
      dt-bindings: mailbox: qcom: Document Nord CPUCP mailbox controller
      mailbox: qcom-cpucp: Add support for Nord CPUCP mailbox controller

Joonwon Kang (2):
      mailbox: Clarify multi-thread is not supported in blocking mode
      mailbox: Make mbox_send_message() return error code when tx fails

Komal Bajaj (1):
      dt-bindings: mailbox: qcom: Add Shikra APCS compatible

Krzysztof Kozlowski (1):
      mailbox: qcom: Unify user-visible "Qualcomm" name

Mukesh Ojha (2):
      dt-bindings: mailbox: qcom,cpucp-mbox: Add Hawi compatible
      dt-bindings: mailbox: qcom: Add IPCC support for Hawi Platform

Sebastian Andrzej Siewior (9):
      mailbox: imx: Forward the timeout/ error in imx_mu_generic_tx()
      mailbox: imx: Add a channel shutdown field
      mailbox: imx: Use devm_pm_runtime_enable()
      mailbox: imx: use devm_of_platform_populate()
      mailbox: imx: Use channel index instead of zero in imx_mu_specific_rx()
      mailbox: imx: Start splitting the IRQ handler in primary and
threaded handler
      mailbox: imx: Move the RX part of the mailbox into the threaded handler
      mailbox: imx: Move the RXDB part of the mailbox into the threaded handler
      mailbox: imx: Don't force-thread the primary handler

Sergey Senozhatsky (1):
      mailbox: mtk-adsp: fix UAF during device teardown

Tudor Ambarus (1):
      mailbox: exynos: Drop unused register definitions

Wolfram Sang (2):
      mailbox: don't free the channel if the startup callback failed
      mailbox: add list of used channels to debugfs

 .../bindings/mailbox/qcom,apcs-kpss-global.yaml    |   1 +
 .../bindings/mailbox/qcom,cpucp-mbox.yaml          |   2 +
 .../devicetree/bindings/mailbox/qcom-ipcc.yaml     |   2 +
 drivers/mailbox/Kconfig                            |   4 +-
 drivers/mailbox/exynos-mailbox.c                   |   7 --
 drivers/mailbox/imx-mailbox.c                      | 117 +++++++++++++++------
 drivers/mailbox/mailbox-mpfs.c                     |   2 +-
 drivers/mailbox/mailbox.c                          | 101 +++++++++++++++---
 drivers/mailbox/mtk-adsp-mailbox.c                 |   9 +-
 drivers/mailbox/qcom-cpucp-mbox.c                  |  35 +++++-
 include/linux/mailbox_controller.h                 |   2 +
 11 files changed, 224 insertions(+), 58 deletions(-)


^ permalink raw reply

* Re: [PATCH] arm64: mm: Defer read-only remap of data/bss linear alias
From: Fuad Tabba @ 2026-06-22 18:13 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: linux-arm-kernel, linux-kernel, catalin.marinas, will,
	Ard Biesheuvel
In-Reply-To: <20260619163940.3185308-2-ardb+git@google.com>

On Fri, 19 Jun 2026 at 17:40, Ard Biesheuvel <ardb+git@google.com> wrote:
>
> From: Ard Biesheuvel <ardb@kernel.org>
>
> Fuad reports that in some cases, the KVM init code may apply relocations
> to variables that reside in .data, and does so via the linear map. This
> means that remapping .data read-only beforehand is a bad idea, and
> results in an early boot crash.
>
> These variables in .data are only present when CONFIG_NVHE_EL2_DEBUG or
> CONFIG_NVHE_EL2_TRACING are enabled, which is why it was not spotted in
> testing.
>
> So move the remap to mark_rodata_ro(), which is a reasonable place to
> put this, and ensures that it happens much later during the boot. It
> also means that rodata=off is now taken into account, and so the linear
> alias will remain writable in that case.
>
> Cc: Fuad Tabba <fuad.tabba@linux.dev>
> Fixes: f2ba877402e5 ("arm64: mm: Map the kernel data/bss read-only in the linear map")
> Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
> ---

This fixes it, and the changes look good to me, thanks.

Reviewed-by: Fuad Tabba <fuad.tabba@linux.dev>
Tested-by: Fuad Tabba < fuad.tabba@linux.dev>

Cheers,
/fuad

>  arch/arm64/mm/mmu.c | 11 ++++++-----
>  1 file changed, 6 insertions(+), 5 deletions(-)
>
> diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
> index 9f354971b7e4..1f7eca86b5c1 100644
> --- a/arch/arm64/mm/mmu.c
> +++ b/arch/arm64/mm/mmu.c
> @@ -1198,11 +1198,6 @@ static void __init map_mem(void)
>                 __map_memblock(start, end, pgprot_tagged(PAGE_KERNEL),
>                                flags);
>         }
> -
> -       /* Map the kernel data/bss read-only in the linear map */
> -       __map_memblock(init_end, kernel_end, PAGE_KERNEL_RO, flags);
> -       flush_tlb_kernel_range((unsigned long)lm_alias(__init_end),
> -                              (unsigned long)lm_alias(__bss_stop));
>  }
>
>  void mark_rodata_ro(void)
> @@ -1221,6 +1216,12 @@ void mark_rodata_ro(void)
>         update_mapping_prot(__pa_symbol(_text), (unsigned long)_text,
>                             (unsigned long)_stext - (unsigned long)_text,
>                             PAGE_KERNEL_RO);
> +
> +       /* Map the kernel data/bss read-only in the linear map */
> +       update_mapping_prot(__pa_symbol(__init_end),
> +                           (unsigned long)lm_alias(__init_end),
> +                           (unsigned long)__bss_stop - (unsigned long)__init_end,
> +                           PAGE_KERNEL_RO);
>  }
>
>  static void __init declare_vma(struct vm_struct *vma,
> --
> 2.55.0.rc0.738.g0c8ab3ebcc-goog
>


^ permalink raw reply

* [PATCH v2] phy: Add USB3 PHY support to Google Tensor SoC USB PHY driver
From: RD Babiera @ 2026-06-22 17:52 UTC (permalink / raw)
  To: vkoul, peter.griffin, andre.draszik, tudor.ambarus, p.zabel,
	neil.armstrong
  Cc: badhri, linux-arm-kernel, linux-samsung-soc, linux-phy,
	linux-kernel, RD Babiera

Add USB3 PHY support for the Google Tensor G5 USB PHY driver.
This patch adds functionality for the usb3_tca register, usb3 clock,
and usb3 reset as defined in google,lga-usb-phy.yaml. Kconfig now lists
USB SuperSpeed support.

Refactor the probe sequence to initialize the USB2 and USB3 PHYs, and then
initialize clocks and resets for both PHYs afterwards.

Refactor set_vbus_valid to reduce duplicated code.

Implement USB3 phy_ops for phy_init, phy_exit, and phy_power_on.
combo_phy_state enum is added to track PHY bringup state across
PHY API calls.

Signed-off-by: RD Babiera <rdbabiera@google.com>
---
Changes since v1:
* Removed mix of goto-based and scope-based cleanup from usb3 phy_init
* Removed unused usb3_core resource from probe
* Added combo_phy_state enum to interally track ComboPHY bringup state
  to allow google_usb_set_orientation() to change TCA orientation.
* Modify Kconfig documentation to reflect SuperSpeed support
---
 drivers/phy/Kconfig          |   2 +-
 drivers/phy/phy-google-usb.c | 379 +++++++++++++++++++++++++++++++----
 2 files changed, 346 insertions(+), 35 deletions(-)

diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index 19f3b7d12b7d..d2d401129af7 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -100,7 +100,7 @@ config PHY_GOOGLE_USB
 	  the G5 generation (Laguna). This driver provides the PHY interfaces
 	  to interact with the SNPS eUSB2 and USB 3.2/DisplayPort Combo PHY,
 	  both of which are integrated with the DWC3 USB DRD controller.
-	  This driver currently supports USB high-speed.
+	  This driver currently supports USB high-speed and SuperSpeed.
 
 config USB_LGM_PHY
 	tristate "INTEL Lightning Mountain USB PHY Driver"
diff --git a/drivers/phy/phy-google-usb.c b/drivers/phy/phy-google-usb.c
index ab20bc20f19e..c6f4d8283e7c 100644
--- a/drivers/phy/phy-google-usb.c
+++ b/drivers/phy/phy-google-usb.c
@@ -20,6 +20,7 @@
 #include <linux/reset.h>
 #include <linux/usb/typec_mux.h>
 
+/* USB_CFG_CSR */
 #define USBCS_USB2PHY_CFG19_OFFSET 0x0
 #define USBCS_USB2PHY_CFG19_PHY_CFG_PLL_FB_DIV GENMASK(19, 8)
 
@@ -28,11 +29,41 @@
 #define USBCS_USB2PHY_CFG21_REF_FREQ_SEL GENMASK(15, 13)
 #define USBCS_USB2PHY_CFG21_PHY_TX_DIG_BYPASS_SEL BIT(19)
 
+/* USBDP_TOP */
 #define USBCS_PHY_CFG1_OFFSET 0x28
+#define USBCS_PHY_CFG1_PHY0_MPLLA_SSC_EN BIT(1)
+#define USBCS_PHY_CFG1_PHY0_SRAM_BYPASS_MODE GENMASK(11, 10)
+#define SRAM_BYPASS_MODE_BYPASS_FIRMWARE BIT(0)
+#define SRAM_BYPASS_MODE_BYPASS_CONTEXT BIT(1)
 #define USBCS_PHY_CFG1_SYS_VBUSVALID BIT(17)
 
+#define USBDP_TOP_CFG_REG_OFFSET 0x44
+#define USBDP_TOP_CFG_REG_PMGT_REF_CLK_REQ_N BIT(0)
+
+#define PHY_POWER_CONFIG_REG1_OFFSET 0x48
+#define PHY_POWER_CONFIG_REG1_PG_MODE_EN BIT(1)
+#define PHY_POWER_CONFIG_REG1_UPCS_PIPE_CONFIG GENMASK(31, 14)
+#define UPCS_PIPE_CONFIG_ISO_CPM BIT(5)
+#define UPCS_PIPE_CONFIG_PG_MODE_STATIC BIT(6)
+#define UPCS_PIPE_CONFIG_LANE_RESET_NO_PG_EXIT BIT(9)
+
+/* USB3_TCA */
+#define TCA_INTR_STS_OFFSET 0x8
+#define TCA_INTR_STS_XA_ACT_EVT BIT(0)
+#define TCA_TCPC_OFFSET 0x14
+#define TCA_TCPC_MUX_CONTROL GENMASK(2, 0)
+#define TCA_TCPC_MUX_CONTROL_USB_ONLY 0x1
+#define TCA_TCPC_CONNECTOR_ORIENTATION BIT(3)
+#define TCA_TCPC_VALID BIT(4)
+#define TCA_PSTATE_0_OFFSET 0x50
+#define TCA_PSTATE_0_UPCS_LANE0_PHYSTATUS BIT(8)
+
+#define GPHY_TCA_DELAY_US 10
+#define GPHY_TCA_TIMEOUT_US 2500000
+
 enum google_usb_phy_id {
 	GOOGLE_USB2_PHY,
+	GOOGLE_USB3_PHY,
 	GOOGLE_USB_PHY_NUM,
 };
 
@@ -46,34 +77,152 @@ struct google_usb_phy_instance {
 	struct reset_control_bulk_data *rsts;
 };
 
+struct google_usb_phy_config {
+	const char * const *clk_names;
+	unsigned int num_clks;
+	const char * const *rst_names;
+	unsigned int num_rsts;
+};
+
+static const char * const u2phy_clk_names[] = {
+	"usb2",
+	"usb2_apb",
+};
+static const char * const u3phy_clk_names[] = {
+	"usb3"
+};
+static const char * const u2phy_rst_names[] = {
+	"usb2",
+	"usb2_apb",
+};
+static const char * const u3phy_rst_names[] = {
+	"usb3"
+};
+
+static const struct google_usb_phy_config phy_configs[GOOGLE_USB_PHY_NUM] = {
+	[GOOGLE_USB2_PHY] = {
+		.clk_names = u2phy_clk_names,
+		.num_clks = ARRAY_SIZE(u2phy_clk_names),
+		.rst_names = u2phy_rst_names,
+		.num_rsts = ARRAY_SIZE(u2phy_rst_names),
+	},
+	[GOOGLE_USB3_PHY] = {
+		.clk_names = u3phy_clk_names,
+		.num_clks = ARRAY_SIZE(u3phy_clk_names),
+		.rst_names = u3phy_rst_names,
+		.num_rsts = ARRAY_SIZE(u3phy_rst_names),
+	},
+};
+
+/*
+ * combo_phy_state
+ *	COMBO_PHY_IDLE: The ComboPHY has been torn down and USB3 has not completed
+ *			bringup
+ *	COMBO_PHY_INIT_DONE: The ComboPHY bringup sequence is complete.
+ *	COMBO_PHY_TCA_READY: The PoR => NC transition is complete, and the TCA can be
+ *			     moved into USB.
+ */
+enum combo_phy_state {
+	COMBO_PHY_IDLE,
+	COMBO_PHY_INIT_DONE,
+	COMBO_PHY_TCA_READY,
+};
+
 struct google_usb_phy {
 	struct device *dev;
 	struct regmap *usb_cfg_regmap;
 	unsigned int usb2_cfg_offset;
 	void __iomem *usbdp_top_base;
+	void __iomem *usb3_tca_base;
 	struct google_usb_phy_instance *insts;
 	/*
 	 * Protect phy registers from concurrent access, specifically via
-	 * google_usb_set_orientation callback.
+	 * google_usb_set_orientation callback. phy_mutex also protects
+	 * concurrent access to phy_state.
 	 */
 	struct mutex phy_mutex;
 	struct typec_switch_dev *sw;
 	enum typec_orientation orientation;
+	enum combo_phy_state phy_state;
 };
 
 static void set_vbus_valid(struct google_usb_phy *gphy)
 {
 	u32 reg;
 
-	if (gphy->orientation == TYPEC_ORIENTATION_NONE) {
-		reg = readl(gphy->usbdp_top_base + USBCS_PHY_CFG1_OFFSET);
+	reg = readl(gphy->usbdp_top_base + USBCS_PHY_CFG1_OFFSET);
+	if (gphy->orientation == TYPEC_ORIENTATION_NONE)
 		reg &= ~USBCS_PHY_CFG1_SYS_VBUSVALID;
-		writel(reg, gphy->usbdp_top_base + USBCS_PHY_CFG1_OFFSET);
-	} else {
-		reg = readl(gphy->usbdp_top_base + USBCS_PHY_CFG1_OFFSET);
+	else
 		reg |= USBCS_PHY_CFG1_SYS_VBUSVALID;
-		writel(reg, gphy->usbdp_top_base + USBCS_PHY_CFG1_OFFSET);
-	}
+	writel(reg, gphy->usbdp_top_base + USBCS_PHY_CFG1_OFFSET);
+}
+
+static void set_sram_bypass(struct google_usb_phy *gphy, u32 bypass)
+{
+	u32 reg;
+
+	reg = readl(gphy->usbdp_top_base + USBCS_PHY_CFG1_OFFSET);
+	reg &= ~USBCS_PHY_CFG1_PHY0_SRAM_BYPASS_MODE;
+	reg |= FIELD_PREP(USBCS_PHY_CFG1_PHY0_SRAM_BYPASS_MODE, bypass);
+	writel(reg, gphy->usbdp_top_base + USBCS_PHY_CFG1_OFFSET);
+}
+
+static void set_pmgt_ref_clk_req_n(struct google_usb_phy *gphy, bool resume)
+{
+	u32 reg;
+
+	reg = readl(gphy->usbdp_top_base + USBDP_TOP_CFG_REG_OFFSET);
+	if (resume)
+		reg |= USBDP_TOP_CFG_REG_PMGT_REF_CLK_REQ_N;
+	else
+		reg &= ~USBDP_TOP_CFG_REG_PMGT_REF_CLK_REQ_N;
+	writel(reg, gphy->usbdp_top_base + USBDP_TOP_CFG_REG_OFFSET);
+}
+
+static int wait_tca_xa_ack(struct google_usb_phy *gphy)
+{
+	int ret;
+	u32 reg;
+
+	ret = readl_poll_timeout(gphy->usb3_tca_base + TCA_INTR_STS_OFFSET,
+				 reg, !!(reg & TCA_INTR_STS_XA_ACT_EVT),
+				 GPHY_TCA_DELAY_US, GPHY_TCA_TIMEOUT_US);
+	if (ret)
+		dev_err(gphy->dev, "tca xa_ack timeout, ret=%d", ret);
+
+	return ret;
+}
+
+static int program_tca_locked(struct google_usb_phy *gphy)
+	   __must_hold(&gphy->phy_mutex)
+{
+	int ret;
+	u32 reg;
+
+	reg = readl(gphy->usb3_tca_base + TCA_INTR_STS_OFFSET);
+	writel(reg, gphy->usb3_tca_base + TCA_INTR_STS_OFFSET);
+
+	reg = readl(gphy->usb3_tca_base + TCA_TCPC_OFFSET);
+	reg &= ~TCA_TCPC_MUX_CONTROL;
+	reg |= FIELD_PREP(TCA_TCPC_MUX_CONTROL, TCA_TCPC_MUX_CONTROL_USB_ONLY);
+	if (gphy->orientation == TYPEC_ORIENTATION_REVERSE)
+		reg |= TCA_TCPC_CONNECTOR_ORIENTATION;
+	else
+		reg &= ~TCA_TCPC_CONNECTOR_ORIENTATION;
+	reg |= TCA_TCPC_VALID;
+	writel(reg, gphy->usb3_tca_base + TCA_TCPC_OFFSET);
+
+	ret = wait_tca_xa_ack(gphy);
+	dev_dbg(gphy->dev, "TCA switch %s, mux %lu, orientation %s",
+		ret ? "failed" : "success",
+		FIELD_GET(TCA_TCPC_MUX_CONTROL, reg),
+		FIELD_GET(TCA_TCPC_CONNECTOR_ORIENTATION, reg) ? "reverse" : "normal");
+
+	reg = readl(gphy->usb3_tca_base + TCA_INTR_STS_OFFSET);
+	writel(reg, gphy->usb3_tca_base + TCA_INTR_STS_OFFSET);
+
+	return ret;
 }
 
 static int google_usb_set_orientation(struct typec_switch_dev *sw,
@@ -92,6 +241,9 @@ static int google_usb_set_orientation(struct typec_switch_dev *sw,
 
 	set_vbus_valid(gphy);
 
+	if (gphy->phy_state == COMBO_PHY_TCA_READY && orientation != TYPEC_ORIENTATION_NONE)
+		return program_tca_locked(gphy);
+
 	return 0;
 }
 
@@ -161,6 +313,118 @@ static const struct phy_ops google_usb2_phy_ops = {
 	.exit		= google_usb2_phy_exit,
 };
 
+static int google_usb3_phy_init(struct phy *_phy)
+{
+	struct google_usb_phy_instance *inst = phy_get_drvdata(_phy);
+	struct google_usb_phy *gphy = inst->parent;
+	int ret = 0;
+	u32 reg;
+
+	dev_dbg(gphy->dev, "initializing usb3 phy\n");
+
+	guard(mutex)(&gphy->phy_mutex);
+
+	if (gphy->phy_state != COMBO_PHY_IDLE) {
+		dev_warn(gphy->dev, "usb3 phy init called when combo phy state is not idle");
+		return 0;
+	}
+
+	reg = readl(gphy->usbdp_top_base + PHY_POWER_CONFIG_REG1_OFFSET);
+	reg |= PHY_POWER_CONFIG_REG1_PG_MODE_EN;
+	reg &= ~PHY_POWER_CONFIG_REG1_UPCS_PIPE_CONFIG;
+	reg |= FIELD_PREP(PHY_POWER_CONFIG_REG1_UPCS_PIPE_CONFIG,
+			  (UPCS_PIPE_CONFIG_ISO_CPM |
+			   UPCS_PIPE_CONFIG_PG_MODE_STATIC |
+			   UPCS_PIPE_CONFIG_LANE_RESET_NO_PG_EXIT));
+	writel(reg, gphy->usbdp_top_base + PHY_POWER_CONFIG_REG1_OFFSET);
+
+	set_vbus_valid(gphy);
+
+	reg = readl(gphy->usbdp_top_base + USBCS_PHY_CFG1_OFFSET);
+	reg |= USBCS_PHY_CFG1_PHY0_MPLLA_SSC_EN;
+	writel(reg, gphy->usbdp_top_base + USBCS_PHY_CFG1_OFFSET);
+
+	set_sram_bypass(gphy, SRAM_BYPASS_MODE_BYPASS_FIRMWARE |
+			SRAM_BYPASS_MODE_BYPASS_CONTEXT);
+	set_pmgt_ref_clk_req_n(gphy, true);
+
+	ret = clk_bulk_prepare_enable(inst->num_clks, inst->clks);
+	if (ret)
+		return ret;
+
+	ret = reset_control_bulk_deassert(inst->num_rsts, inst->rsts);
+	if (ret) {
+		clk_bulk_disable_unprepare(inst->num_clks, inst->clks);
+		return ret;
+	}
+
+	ret = readl_poll_timeout(gphy->usb3_tca_base + TCA_PSTATE_0_OFFSET,
+				 reg, !(reg & TCA_PSTATE_0_UPCS_LANE0_PHYSTATUS),
+				 GPHY_TCA_DELAY_US, GPHY_TCA_TIMEOUT_US);
+	if (ret) {
+		dev_err(gphy->dev, "wait for lane0 phystatus timed out");
+		reset_control_bulk_assert(inst->num_rsts, inst->rsts);
+		clk_bulk_disable_unprepare(inst->num_clks, inst->clks);
+		return ret;
+	}
+
+	gphy->phy_state = COMBO_PHY_INIT_DONE;
+
+	return 0;
+}
+
+static int google_usb3_phy_exit(struct phy *_phy)
+{
+	struct google_usb_phy_instance *inst = phy_get_drvdata(_phy);
+	struct google_usb_phy *gphy = inst->parent;
+
+	dev_dbg(gphy->dev, "exiting usb3 phy\n");
+
+	guard(mutex)(&gphy->phy_mutex);
+
+	set_pmgt_ref_clk_req_n(gphy, false);
+	reset_control_bulk_assert(inst->num_rsts, inst->rsts);
+	clk_bulk_disable_unprepare(inst->num_clks, inst->clks);
+
+	gphy->phy_state = COMBO_PHY_IDLE;
+
+	return 0;
+}
+
+static int google_usb3_phy_power_on(struct phy *_phy)
+{
+	struct google_usb_phy_instance *inst = phy_get_drvdata(_phy);
+	struct google_usb_phy *gphy = inst->parent;
+	int ret;
+
+	dev_dbg(gphy->dev, "power on usb3 phy\n");
+
+	guard(mutex)(&gphy->phy_mutex);
+
+	if (gphy->phy_state == COMBO_PHY_TCA_READY) {
+		dev_warn(gphy->dev, "usb3 phy already powered on");
+		return 0;
+	}
+
+	ret = wait_tca_xa_ack(gphy);
+	if (ret) {
+		dev_err(gphy->dev, "PoR->NC transition timeout");
+		return ret;
+	}
+
+	gphy->phy_state = COMBO_PHY_TCA_READY;
+
+	ret = program_tca_locked(gphy);
+
+	return ret;
+}
+
+static const struct phy_ops google_usb3_phy_ops = {
+	.init		= google_usb3_phy_init,
+	.exit		= google_usb3_phy_exit,
+	.power_on	= google_usb3_phy_power_on,
+};
+
 static struct phy *google_usb_phy_xlate(struct device *dev,
 					const struct of_phandle_args *args)
 {
@@ -173,14 +437,61 @@ static struct phy *google_usb_phy_xlate(struct device *dev,
 	return gphy->insts[args->args[0]].phy;
 }
 
+static int google_usb_phy_parse_clocks(struct google_usb_phy *gphy)
+{
+	struct device *dev = gphy->dev;
+	int id, i, ret;
+
+	for (id = 0; id < GOOGLE_USB_PHY_NUM; id++) {
+		const struct google_usb_phy_config *cfg = &phy_configs[id];
+		struct google_usb_phy_instance *inst = &gphy->insts[id];
+
+		inst->num_clks = cfg->num_clks;
+		inst->clks = devm_kcalloc(dev, inst->num_clks, sizeof(*inst->clks), GFP_KERNEL);
+		if (!inst->clks)
+			return -ENOMEM;
+
+		for (i = 0; i < inst->num_clks; i++)
+			inst->clks[i].id = cfg->clk_names[i];
+
+		ret = devm_clk_bulk_get(dev, inst->num_clks, inst->clks);
+		if (ret)
+			return dev_err_probe(dev, ret, "failed to get phy%d clks\n", id);
+	}
+
+	return 0;
+}
+
+static int google_usb_phy_parse_resets(struct google_usb_phy *gphy)
+{
+	struct device *dev = gphy->dev;
+	int id, i, ret;
+
+	for (id = 0; id < GOOGLE_USB_PHY_NUM; id++) {
+		const struct google_usb_phy_config *cfg = &phy_configs[id];
+		struct google_usb_phy_instance *inst = &gphy->insts[id];
+
+		inst->num_rsts = cfg->num_rsts;
+		inst->rsts = devm_kcalloc(dev, inst->num_rsts, sizeof(*inst->rsts), GFP_KERNEL);
+		if (!inst->rsts)
+			return -ENOMEM;
+
+		for (i = 0; i < inst->num_rsts; i++)
+			inst->rsts[i].id = cfg->rst_names[i];
+		ret = devm_reset_control_bulk_get_exclusive(dev, inst->num_rsts, inst->rsts);
+		if (ret)
+			return dev_err_probe(dev, ret, "failed to get phy%d resets\n", id);
+	}
+
+	return 0;
+}
+
 static int google_usb_phy_probe(struct platform_device *pdev)
 {
 	struct typec_switch_desc sw_desc = { };
-	struct google_usb_phy_instance *inst;
 	struct phy_provider *phy_provider;
 	struct device *dev = &pdev->dev;
 	struct google_usb_phy *gphy;
-	struct phy *phy;
 	u32 args[1];
 	int ret;
 
@@ -212,39 +523,39 @@ static int google_usb_phy_probe(struct platform_device *pdev)
 		return dev_err_probe(dev, PTR_ERR(gphy->usbdp_top_base),
 				    "invalid usbdp top\n");
 
+	gphy->usb3_tca_base = devm_platform_ioremap_resource_byname(pdev,
+								    "usb3_tca");
+	if (IS_ERR(gphy->usb3_tca_base))
+		return dev_err_probe(dev, PTR_ERR(gphy->usb3_tca_base),
+				    "invalid usb3 tca\n");
+
 	gphy->insts = devm_kcalloc(dev, GOOGLE_USB_PHY_NUM, sizeof(*gphy->insts), GFP_KERNEL);
 	if (!gphy->insts)
 		return -ENOMEM;
 
-	inst = &gphy->insts[GOOGLE_USB2_PHY];
-	inst->parent = gphy;
-	inst->index = GOOGLE_USB2_PHY;
-	phy = devm_phy_create(dev, NULL, &google_usb2_phy_ops);
-	if (IS_ERR(phy))
-		return dev_err_probe(dev, PTR_ERR(phy),
+	gphy->insts[GOOGLE_USB2_PHY].phy = devm_phy_create(dev, NULL, &google_usb2_phy_ops);
+	gphy->insts[GOOGLE_USB2_PHY].index = GOOGLE_USB2_PHY;
+	gphy->insts[GOOGLE_USB2_PHY].parent = gphy;
+	if (IS_ERR(gphy->insts[GOOGLE_USB2_PHY].phy))
+		return dev_err_probe(dev, PTR_ERR(gphy->insts[GOOGLE_USB2_PHY].phy),
 				     "failed to create usb2 phy instance\n");
-	inst->phy = phy;
-	phy_set_drvdata(phy, inst);
+	phy_set_drvdata(gphy->insts[GOOGLE_USB2_PHY].phy, &gphy->insts[GOOGLE_USB2_PHY]);
 
-	inst->num_clks = 2;
-	inst->clks = devm_kcalloc(dev, inst->num_clks, sizeof(*inst->clks), GFP_KERNEL);
-	if (!inst->clks)
-		return -ENOMEM;
-	inst->clks[0].id = "usb2";
-	inst->clks[1].id = "usb2_apb";
-	ret = devm_clk_bulk_get(dev, inst->num_clks, inst->clks);
+	gphy->insts[GOOGLE_USB3_PHY].phy = devm_phy_create(dev, NULL, &google_usb3_phy_ops);
+	gphy->insts[GOOGLE_USB3_PHY].index = GOOGLE_USB3_PHY;
+	gphy->insts[GOOGLE_USB3_PHY].parent = gphy;
+	if (IS_ERR(gphy->insts[GOOGLE_USB3_PHY].phy))
+		return dev_err_probe(dev, PTR_ERR(gphy->insts[GOOGLE_USB3_PHY].phy),
+				     "failed to create usb3 phy instance\n");
+	phy_set_drvdata(gphy->insts[GOOGLE_USB3_PHY].phy, &gphy->insts[GOOGLE_USB3_PHY]);
+
+	ret = google_usb_phy_parse_clocks(gphy);
 	if (ret)
-		return dev_err_probe(dev, ret, "failed to get u2 phy clks\n");
+		return ret;
 
-	inst->num_rsts = 2;
-	inst->rsts = devm_kcalloc(dev, inst->num_rsts, sizeof(*inst->rsts), GFP_KERNEL);
-	if (!inst->rsts)
-		return -ENOMEM;
-	inst->rsts[0].id = "usb2";
-	inst->rsts[1].id = "usb2_apb";
-	ret = devm_reset_control_bulk_get_exclusive(dev, inst->num_rsts, inst->rsts);
+	ret = google_usb_phy_parse_resets(gphy);
 	if (ret)
-		return dev_err_probe(dev, ret, "failed to get u2 phy resets\n");
+		return ret;
 
 	phy_provider = devm_of_phy_provider_register(dev, google_usb_phy_xlate);
 	if (IS_ERR(phy_provider))

base-commit: 2ace2e949979b82f82f12dd76d7c5a6145246ca3
-- 
2.55.0.rc0.786.g65d90a0328-goog



^ permalink raw reply related


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