Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v14 05/12] media: mediatek: jpeg: Fix multi-core clk suspend and resume setting
From: Kyrie Wu @ 2026-04-23  9:46 UTC (permalink / raw)
  To: Hans Verkuil, Mauro Carvalho Chehab, Rob Herring,
	Krzysztof Kozlowski, Nicolas Dufresne, Conor Dooley,
	Matthias Brugger, AngeloGioacchino Del Regno, Kyrie Wu,
	linux-media, devicetree, linux-kernel, linux-arm-kernel,
	linux-mediatek
In-Reply-To: <20260423094656.32044-1-kyrie.wu@mediatek.com>

The suspend/resume callback function is defined in the dev_pm_ops
structure, which is defined in platform_driver. For multiple-core
architecture, each hardware driver will register a platform_driver
structure, so it is necessary to add a suspend/resume callback
function for each hardware to support this operation.

Fixes: 934e8bccac95 ("mtk-jpegenc: support jpegenc multi-hardware")
Fixes: 0fa49df4222f ("media: mtk-jpegdec: support jpegdec multi-hardware")
Signed-off-by: Kyrie Wu <kyrie.wu@mediatek.com>
---
 .../platform/mediatek/jpeg/mtk_jpeg_core.c    | 28 +++------
 .../platform/mediatek/jpeg/mtk_jpeg_dec_hw.c  | 62 +++++++++++++++++--
 .../platform/mediatek/jpeg/mtk_jpeg_enc_hw.c  | 60 ++++++++++++++++--
 3 files changed, 121 insertions(+), 29 deletions(-)

diff --git a/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c b/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c
index 6e5de2680e3a..e85a3d0bd8ac 100644
--- a/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c
+++ b/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c
@@ -1115,6 +1115,9 @@ static void mtk_jpeg_clk_on(struct mtk_jpeg_dev *jpeg)
 {
 	int ret;
 
+	if (jpeg->variant->multi_core)
+		return;
+
 	ret = clk_bulk_prepare_enable(jpeg->variant->num_clks,
 				      jpeg->variant->clks);
 	if (ret)
@@ -1123,6 +1126,9 @@ static void mtk_jpeg_clk_on(struct mtk_jpeg_dev *jpeg)
 
 static void mtk_jpeg_clk_off(struct mtk_jpeg_dev *jpeg)
 {
+	if (jpeg->variant->multi_core)
+		return;
+
 	clk_bulk_disable_unprepare(jpeg->variant->num_clks,
 				   jpeg->variant->clks);
 }
@@ -1646,13 +1652,6 @@ static void mtk_jpegenc_worker(struct work_struct *work)
 		goto enc_end;
 	}
 
-	ret = clk_prepare_enable(comp_jpeg[hw_id]->venc_clk.clks->clk);
-	if (ret) {
-		dev_err(jpeg->dev, "%s : %d, jpegenc clk_prepare_enable fail\n",
-			__func__, __LINE__);
-		goto enc_end;
-	}
-
 	v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
 	v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
 
@@ -1749,20 +1748,13 @@ static void mtk_jpegdec_worker(struct work_struct *work)
 	jpeg_dst_buf->frame_num = ctx->total_frame_num;
 
 	mtk_jpegdec_set_hw_param(ctx, hw_id, src_buf, dst_buf);
-	ret = pm_runtime_get_sync(comp_jpeg[hw_id]->dev);
+	ret = pm_runtime_resume_and_get(comp_jpeg[hw_id]->dev);
 	if (ret < 0) {
 		dev_err(jpeg->dev, "%s : %d, pm_runtime_get_sync fail !!!\n",
 			__func__, __LINE__);
 		goto dec_end;
 	}
 
-	ret = clk_prepare_enable(comp_jpeg[hw_id]->jdec_clk.clks->clk);
-	if (ret) {
-		dev_err(jpeg->dev, "%s : %d, jpegdec clk_prepare_enable fail\n",
-			__func__, __LINE__);
-		goto clk_end;
-	}
-
 	v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
 	v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
 
@@ -1772,7 +1764,7 @@ static void mtk_jpegdec_worker(struct work_struct *work)
 				 &dst_buf->vb2_buf, &fb)) {
 		dev_err(jpeg->dev, "%s : %d, mtk_jpeg_set_dec_dst fail\n",
 			__func__, __LINE__);
-		goto setdst_end;
+		goto set_dst_fail;
 	}
 
 	schedule_delayed_work(&comp_jpeg[hw_id]->job_timeout_work,
@@ -1793,9 +1785,7 @@ static void mtk_jpegdec_worker(struct work_struct *work)
 
 	return;
 
-setdst_end:
-	clk_disable_unprepare(comp_jpeg[hw_id]->jdec_clk.clks->clk);
-clk_end:
+set_dst_fail:
 	pm_runtime_put(comp_jpeg[hw_id]->dev);
 dec_end:
 	v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
diff --git a/drivers/media/platform/mediatek/jpeg/mtk_jpeg_dec_hw.c b/drivers/media/platform/mediatek/jpeg/mtk_jpeg_dec_hw.c
index 4534caeb104f..9a8dbca6af00 100644
--- a/drivers/media/platform/mediatek/jpeg/mtk_jpeg_dec_hw.c
+++ b/drivers/media/platform/mediatek/jpeg/mtk_jpeg_dec_hw.c
@@ -533,13 +533,12 @@ static void mtk_jpegdec_timeout_work(struct work_struct *work)
 	v4l2_m2m_buf_copy_metadata(src_buf, dst_buf);
 
 	mtk_jpeg_dec_reset(cjpeg->reg_base);
-	clk_disable_unprepare(cjpeg->jdec_clk.clks->clk);
-	pm_runtime_put(cjpeg->dev);
 	cjpeg->hw_state = MTK_JPEG_HW_IDLE;
 	atomic_inc(&master_jpeg->hw_rdy);
 	wake_up(&master_jpeg->hw_wq);
 	v4l2_m2m_buf_done(src_buf, buf_state);
 	mtk_jpegdec_put_buf(cjpeg);
+	pm_runtime_put(cjpeg->dev);
 }
 
 static irqreturn_t mtk_jpegdec_hw_irq_handler(int irq, void *priv)
@@ -547,7 +546,6 @@ static irqreturn_t mtk_jpegdec_hw_irq_handler(int irq, void *priv)
 	struct vb2_v4l2_buffer *src_buf, *dst_buf;
 	struct mtk_jpeg_src_buf *jpeg_src_buf;
 	enum vb2_buffer_state buf_state;
-	struct mtk_jpeg_ctx *ctx;
 	u32 dec_irq_ret;
 	u32 irq_status;
 	int i;
@@ -557,7 +555,6 @@ static irqreturn_t mtk_jpegdec_hw_irq_handler(int irq, void *priv)
 
 	cancel_delayed_work(&jpeg->job_timeout_work);
 
-	ctx = jpeg->hw_param.curr_ctx;
 	src_buf = jpeg->hw_param.src_buffer;
 	dst_buf = jpeg->hw_param.dst_buffer;
 	v4l2_m2m_buf_copy_metadata(src_buf, dst_buf);
@@ -580,12 +577,11 @@ static irqreturn_t mtk_jpegdec_hw_irq_handler(int irq, void *priv)
 	buf_state = VB2_BUF_STATE_DONE;
 	v4l2_m2m_buf_done(src_buf, buf_state);
 	mtk_jpegdec_put_buf(jpeg);
-	pm_runtime_put(ctx->jpeg->dev);
-	clk_disable_unprepare(jpeg->jdec_clk.clks->clk);
 
 	jpeg->hw_state = MTK_JPEG_HW_IDLE;
 	wake_up(&master_jpeg->hw_wq);
 	atomic_inc(&master_jpeg->hw_rdy);
+	pm_runtime_put(jpeg->dev);
 
 	return IRQ_HANDLED;
 }
@@ -668,15 +664,69 @@ static int mtk_jpegdec_hw_probe(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, dev);
 	pm_runtime_enable(&pdev->dev);
+	ret = devm_clk_bulk_get(dev->dev,
+				jpegdec_clk->clk_num,
+				jpegdec_clk->clks);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to init clk\n");
+		return ret;
+	}
 
 	return 0;
 }
 
+static int mtk_jpegdec_pm_suspend(struct device *dev)
+{
+	struct mtk_jpegdec_comp_dev *jpeg = dev_get_drvdata(dev);
+
+	clk_bulk_disable_unprepare(jpeg->jdec_clk.clk_num,
+				   jpeg->jdec_clk.clks);
+
+	return 0;
+}
+
+static int mtk_jpegdec_pm_resume(struct device *dev)
+{
+	struct mtk_jpegdec_comp_dev *jpeg = dev_get_drvdata(dev);
+
+	return clk_bulk_prepare_enable(jpeg->jdec_clk.clk_num,
+				       jpeg->jdec_clk.clks);
+}
+
+static int mtk_jpegdec_suspend(struct device *dev)
+{
+	struct mtk_jpegdec_comp_dev *jpeg = dev_get_drvdata(dev);
+
+	v4l2_m2m_suspend(jpeg->master_dev->m2m_dev);
+
+	return pm_runtime_force_suspend(dev);
+}
+
+static int mtk_jpegdec_resume(struct device *dev)
+{
+	struct mtk_jpegdec_comp_dev *jpeg = dev_get_drvdata(dev);
+	int ret;
+
+	ret = pm_runtime_force_resume(dev);
+	if (ret < 0)
+		return ret;
+
+	v4l2_m2m_resume(jpeg->master_dev->m2m_dev);
+
+	return 0;
+}
+
+static const struct dev_pm_ops mtk_jpegdec_pm_ops = {
+	SYSTEM_SLEEP_PM_OPS(mtk_jpegdec_suspend, mtk_jpegdec_resume)
+	RUNTIME_PM_OPS(mtk_jpegdec_pm_suspend, mtk_jpegdec_pm_resume, NULL)
+};
+
 static struct platform_driver mtk_jpegdec_hw_driver = {
 	.probe = mtk_jpegdec_hw_probe,
 	.driver = {
 		.name = "mtk-jpegdec-hw",
 		.of_match_table = mtk_jpegdec_hw_ids,
+		.pm             = &mtk_jpegdec_pm_ops,
 	},
 };
 
diff --git a/drivers/media/platform/mediatek/jpeg/mtk_jpeg_enc_hw.c b/drivers/media/platform/mediatek/jpeg/mtk_jpeg_enc_hw.c
index 2765dafab4ad..5d1c217fea0f 100644
--- a/drivers/media/platform/mediatek/jpeg/mtk_jpeg_enc_hw.c
+++ b/drivers/media/platform/mediatek/jpeg/mtk_jpeg_enc_hw.c
@@ -264,13 +264,12 @@ static void mtk_jpegenc_timeout_work(struct work_struct *work)
 	v4l2_m2m_buf_copy_metadata(src_buf, dst_buf);
 
 	mtk_jpeg_enc_reset(cjpeg->reg_base);
-	clk_disable_unprepare(cjpeg->venc_clk.clks->clk);
-	pm_runtime_put(cjpeg->dev);
 	cjpeg->hw_state = MTK_JPEG_HW_IDLE;
 	atomic_inc(&master_jpeg->hw_rdy);
 	wake_up(&master_jpeg->hw_wq);
 	v4l2_m2m_buf_done(src_buf, buf_state);
 	mtk_jpegenc_put_buf(cjpeg);
+	pm_runtime_put(cjpeg->dev);
 }
 
 static irqreturn_t mtk_jpegenc_hw_irq_handler(int irq, void *priv)
@@ -304,12 +303,11 @@ static irqreturn_t mtk_jpegenc_hw_irq_handler(int irq, void *priv)
 	buf_state = VB2_BUF_STATE_DONE;
 	v4l2_m2m_buf_done(src_buf, buf_state);
 	mtk_jpegenc_put_buf(jpeg);
-	pm_runtime_put(ctx->jpeg->dev);
-	clk_disable_unprepare(jpeg->venc_clk.clks->clk);
 
 	jpeg->hw_state = MTK_JPEG_HW_IDLE;
 	wake_up(&master_jpeg->hw_wq);
 	atomic_inc(&master_jpeg->hw_rdy);
+	pm_runtime_put(jpeg->dev);
 
 	return IRQ_HANDLED;
 }
@@ -390,15 +388,69 @@ static int mtk_jpegenc_hw_probe(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, dev);
 	pm_runtime_enable(&pdev->dev);
+	ret = devm_clk_bulk_get(dev->dev,
+				jpegenc_clk->clk_num,
+				jpegenc_clk->clks);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to init clk\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static int mtk_jpegenc_pm_suspend(struct device *dev)
+{
+	struct mtk_jpegenc_comp_dev *jpeg = dev_get_drvdata(dev);
+
+	clk_bulk_disable_unprepare(jpeg->venc_clk.clk_num,
+				   jpeg->venc_clk.clks);
 
 	return 0;
 }
 
+static int mtk_jpegenc_pm_resume(struct device *dev)
+{
+	struct mtk_jpegenc_comp_dev *jpeg = dev_get_drvdata(dev);
+
+	return clk_bulk_prepare_enable(jpeg->venc_clk.clk_num,
+				       jpeg->venc_clk.clks);
+}
+
+static int mtk_jpegenc_suspend(struct device *dev)
+{
+	struct mtk_jpegenc_comp_dev *jpeg = dev_get_drvdata(dev);
+
+	v4l2_m2m_suspend(jpeg->master_dev->m2m_dev);
+
+	return pm_runtime_force_suspend(dev);
+}
+
+static int mtk_jpegenc_resume(struct device *dev)
+{
+	struct mtk_jpegenc_comp_dev *jpeg = dev_get_drvdata(dev);
+	int ret;
+
+	ret = pm_runtime_force_resume(dev);
+	if (ret < 0)
+		return ret;
+
+	v4l2_m2m_resume(jpeg->master_dev->m2m_dev);
+
+	return 0;
+}
+
+static const struct dev_pm_ops mtk_jpegenc_pm_ops = {
+	SYSTEM_SLEEP_PM_OPS(mtk_jpegenc_suspend, mtk_jpegenc_resume)
+	RUNTIME_PM_OPS(mtk_jpegenc_pm_suspend, mtk_jpegenc_pm_resume, NULL)
+};
+
 static struct platform_driver mtk_jpegenc_hw_driver = {
 	.probe = mtk_jpegenc_hw_probe,
 	.driver = {
 		.name = "mtk-jpegenc-hw",
 		.of_match_table = mtk_jpegenc_drv_ids,
+		.pm = &mtk_jpegenc_pm_ops,
 	},
 };
 
-- 
2.45.2



^ permalink raw reply related

* [PATCH v14 08/12] media: mediatek: jpeg: fix remove buffer removal timing for multi-core
From: Kyrie Wu @ 2026-04-23  9:46 UTC (permalink / raw)
  To: Hans Verkuil, Mauro Carvalho Chehab, Rob Herring,
	Krzysztof Kozlowski, Nicolas Dufresne, Conor Dooley,
	Matthias Brugger, AngeloGioacchino Del Regno, Kyrie Wu,
	linux-media, devicetree, linux-kernel, linux-arm-kernel,
	linux-mediatek
In-Reply-To: <20260423094656.32044-1-kyrie.wu@mediatek.com>

Move calls to v4l2_m2m_src/dst_buf_remove() inside of the spinlock
protected scope to ensure all necessary operations are performed
before buffers are removed from their queues and ensure proper
synchronization of buffer handling to avoid buffer lost.

Fixes: 86379bd9d399 ("media: mtk-jpeg: Fixes jpeg enc&dec worker sw flow")
Signed-off-by: Kyrie Wu <kyrie.wu@mediatek.com>
Reviewed-by: Nicolas Dufresne <nicolas.dufresne@collabora.com>
---
 drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c | 10 ++++------
 1 file changed, 4 insertions(+), 6 deletions(-)

diff --git a/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c b/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c
index 7e176a91404c..a5b0f7620121 100644
--- a/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c
+++ b/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c
@@ -1652,9 +1652,6 @@ static void mtk_jpegenc_worker(struct work_struct *work)
 		goto enc_end;
 	}
 
-	v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
-	v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
-
 	schedule_delayed_work(&comp_jpeg[hw_id]->job_timeout_work,
 			      msecs_to_jiffies(MTK_JPEG_HW_TIMEOUT_MSEC));
 
@@ -1672,6 +1669,8 @@ static void mtk_jpegenc_worker(struct work_struct *work)
 			     &src_buf->vb2_buf);
 	mtk_jpeg_set_enc_params(ctx, comp_jpeg[hw_id]->reg_base);
 	mtk_jpeg_enc_start(comp_jpeg[hw_id]->reg_base);
+	v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
+	v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
 	v4l2_m2m_job_finish(jpeg->m2m_dev, ctx->fh.m2m_ctx);
 	spin_unlock_irqrestore(&comp_jpeg[hw_id]->hw_lock, flags);
 
@@ -1753,9 +1752,6 @@ static void mtk_jpegdec_worker(struct work_struct *work)
 		goto dec_end;
 	}
 
-	v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
-	v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
-
 	mtk_jpeg_set_dec_src(ctx, &src_buf->vb2_buf, &bs);
 	if (mtk_jpeg_set_dec_dst(ctx,
 				 &jpeg_src_buf->dec_param,
@@ -1780,6 +1776,8 @@ static void mtk_jpegdec_worker(struct work_struct *work)
 				jpeg_src_buf->bs_size,
 				&bs,
 				&fb);
+	v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
+	v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
 	mtk_jpeg_dec_start(comp_jpeg[hw_id]->reg_base);
 	v4l2_m2m_job_finish(jpeg->m2m_dev, ctx->fh.m2m_ctx);
 	spin_unlock_irqrestore(&comp_jpeg[hw_id]->hw_lock, flags);
-- 
2.45.2



^ permalink raw reply related

* [PATCH v14 09/12] media: dt-bindings: mediatek,jpeg: Add mediatek, mt8196-jpgdec compatible
From: Kyrie Wu @ 2026-04-23  9:46 UTC (permalink / raw)
  To: Hans Verkuil, Mauro Carvalho Chehab, Rob Herring,
	Krzysztof Kozlowski, Nicolas Dufresne, Conor Dooley,
	Matthias Brugger, AngeloGioacchino Del Regno, Kyrie Wu,
	linux-media, devicetree, linux-kernel, linux-arm-kernel,
	linux-mediatek
  Cc: Krzysztof Kozlowski
In-Reply-To: <20260423094656.32044-1-kyrie.wu@mediatek.com>

Compared to the previous generation IC, the MT8196 uses SMMU
instead of IOMMU and supports features such as dynamic voltage
and frequency scaling. Therefore, add "mediatek,mt8196-jpgdec"
compatible to the binding document.

Signed-off-by: Kyrie Wu <kyrie.wu@mediatek.com>
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
---
 .../bindings/media/mediatek,mt8195-jpegdec.yaml           | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/media/mediatek,mt8195-jpegdec.yaml b/Documentation/devicetree/bindings/media/mediatek,mt8195-jpegdec.yaml
index e5448c60e3eb..28a9a9bfdbf8 100644
--- a/Documentation/devicetree/bindings/media/mediatek,mt8195-jpegdec.yaml
+++ b/Documentation/devicetree/bindings/media/mediatek,mt8195-jpegdec.yaml
@@ -14,7 +14,9 @@ description:
 
 properties:
   compatible:
-    const: mediatek,mt8195-jpgdec
+    enum:
+      - mediatek,mt8195-jpgdec
+      - mediatek,mt8196-jpgdec
 
   power-domains:
     maxItems: 1
@@ -44,7 +46,9 @@ patternProperties:
 
     properties:
       compatible:
-        const: mediatek,mt8195-jpgdec-hw
+        enum:
+          - mediatek,mt8195-jpgdec-hw
+          - mediatek,mt8196-jpgdec-hw
 
       reg:
         maxItems: 1
-- 
2.45.2



^ permalink raw reply related

* [PATCH v14 12/12] media: mediatek: jpeg: add jpeg smmu sid setting
From: Kyrie Wu @ 2026-04-23  9:46 UTC (permalink / raw)
  To: Hans Verkuil, Mauro Carvalho Chehab, Rob Herring,
	Krzysztof Kozlowski, Nicolas Dufresne, Conor Dooley,
	Matthias Brugger, AngeloGioacchino Del Regno, Kyrie Wu,
	linux-media, devicetree, linux-kernel, linux-arm-kernel,
	linux-mediatek
In-Reply-To: <20260423094656.32044-1-kyrie.wu@mediatek.com>

Add a configuration to set jpeg dec & enc smmu sid

Signed-off-by: Kyrie Wu <kyrie.wu@mediatek.com>
Reviewed-by: Nicolas Dufresne <nicolas.dufresne@collabora.com>
---
 .../platform/mediatek/jpeg/mtk_jpeg_core.c    | 29 +++++++++++++++++++
 .../platform/mediatek/jpeg/mtk_jpeg_core.h    | 15 ++++++++++
 .../platform/mediatek/jpeg/mtk_jpeg_dec_hw.c  | 23 +++++++++++++++
 .../platform/mediatek/jpeg/mtk_jpeg_enc_hw.c  | 23 +++++++++++++++
 4 files changed, 90 insertions(+)

diff --git a/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c b/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c
index 8bd52ca03e9f..30fc1feb42ad 100644
--- a/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c
+++ b/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c
@@ -15,6 +15,7 @@
 #include <linux/of_platform.h>
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
+#include <linux/regmap.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <media/v4l2-event.h>
@@ -1600,6 +1601,22 @@ static irqreturn_t mtk_jpeg_enc_done(struct mtk_jpeg_dev *jpeg)
 	return IRQ_HANDLED;
 }
 
+static void mtk_jpeg_set_smmu_sid(struct regmap *smmu_regmap, unsigned int sid)
+{
+	if (sid == JPG_REG_GUSER_ID_DEC_SID)
+		regmap_update_bits(smmu_regmap, JPEG_DEC_SMMU_SID,
+				   JPG_REG_GUSER_ID_MASK <<
+				   JPG_REG_DEC_GUSER_ID_SHIFT,
+				   JPG_REG_GUSER_ID_DEC_SID <<
+				   JPG_REG_DEC_GUSER_ID_SHIFT);
+	else
+		regmap_update_bits(smmu_regmap, JPEG_ENC_SMMU_SID,
+				   JPG_REG_GUSER_ID_MASK <<
+				   JPG_REG_ENC_GUSER_ID_SHIFT,
+				   JPG_REG_GUSER_ID_ENC_SID <<
+				   JPG_REG_ENC_GUSER_ID_SHIFT);
+}
+
 static void mtk_jpegenc_worker(struct work_struct *work)
 {
 	struct mtk_jpegenc_comp_dev *comp_jpeg[MTK_JPEGENC_HW_MAX];
@@ -1661,6 +1678,11 @@ static void mtk_jpegenc_worker(struct work_struct *work)
 	jpeg_dst_buf->frame_num = ctx->total_frame_num;
 	ctx->total_frame_num++;
 	mtk_jpeg_enc_reset(comp_jpeg[hw_id]->reg_base);
+
+	if (jpeg->variant->support_smmu && comp_jpeg[hw_id]->smmu_regmap)
+		mtk_jpeg_set_smmu_sid(comp_jpeg[hw_id]->smmu_regmap,
+				      JPG_REG_GUSER_ID_ENC_SID);
+
 	mtk_jpeg_set_enc_dst(ctx,
 			     comp_jpeg[hw_id]->reg_base,
 			     &dst_buf->vb2_buf);
@@ -1770,6 +1792,11 @@ static void mtk_jpegdec_worker(struct work_struct *work)
 	jpeg_dst_buf->frame_num = ctx->total_frame_num;
 	ctx->total_frame_num++;
 	mtk_jpeg_dec_reset(comp_jpeg[hw_id]->reg_base);
+
+	if (jpeg->variant->support_smmu && comp_jpeg[hw_id]->smmu_regmap)
+		mtk_jpeg_set_smmu_sid(comp_jpeg[hw_id]->smmu_regmap,
+				      JPG_REG_GUSER_ID_DEC_SID);
+
 	mtk_jpeg_dec_set_config(comp_jpeg[hw_id]->reg_base,
 				jpeg->variant->support_34bit,
 				&jpeg_src_buf->dec_param,
@@ -1928,6 +1955,7 @@ static struct mtk_jpeg_variant mtk8196_jpegenc_drvdata = {
 	.cap_q_default_fourcc = V4L2_PIX_FMT_JPEG,
 	.multi_core = true,
 	.jpeg_worker = mtk_jpegenc_worker,
+	.support_smmu = true,
 };
 
 static const struct mtk_jpeg_variant mtk8195_jpegdec_drvdata = {
@@ -1954,6 +1982,7 @@ static const struct mtk_jpeg_variant mtk8196_jpegdec_drvdata = {
 	.cap_q_default_fourcc = V4L2_PIX_FMT_YUV420M,
 	.multi_core = true,
 	.jpeg_worker = mtk_jpegdec_worker,
+	.support_smmu = true,
 };
 
 static const struct of_device_id mtk_jpeg_match[] = {
diff --git a/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.h b/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.h
index 148fd41759b7..186cd1862028 100644
--- a/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.h
+++ b/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.h
@@ -11,6 +11,7 @@
 
 #include <linux/clk.h>
 #include <linux/interrupt.h>
+#include <linux/mfd/syscon.h>
 #include <media/v4l2-ctrls.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-fh.h>
@@ -34,6 +35,14 @@
 
 #define MTK_JPEG_MAX_EXIF_SIZE	(64 * 1024)
 
+#define JPEG_DEC_SMMU_SID				0
+#define JPEG_ENC_SMMU_SID				0
+#define JPG_REG_GUSER_ID_MASK			0x7
+#define JPG_REG_GUSER_ID_DEC_SID		0x4
+#define JPG_REG_GUSER_ID_ENC_SID		0x5
+#define JPG_REG_DEC_GUSER_ID_SHIFT		8
+#define JPG_REG_ENC_GUSER_ID_SHIFT		4
+
 #define MTK_JPEG_ADDR_MASK GENMASK(1, 0)
 
 /**
@@ -65,6 +74,7 @@ enum mtk_jpeg_ctx_state {
  * @multi_core:		mark jpeg hw is multi_core or not
  * @jpeg_worker:		jpeg dec or enc worker
  * @support_34bit:	flag to check support for 34-bit DMA address
+ * @support_smmu:	flag to check if support smmu
  */
 struct mtk_jpeg_variant {
 	struct clk_bulk_data *clks;
@@ -82,6 +92,7 @@ struct mtk_jpeg_variant {
 	bool multi_core;
 	void (*jpeg_worker)(struct work_struct *work);
 	bool support_34bit;
+	bool support_smmu;
 };
 
 struct mtk_jpeg_src_buf {
@@ -150,6 +161,7 @@ struct mtk_jpegdec_clk {
  * @hw_param:		jpeg encode hw parameters
  * @hw_state:		record hw state
  * @hw_lock:		spinlock protecting the hw device resource
+ * @smmu_regmap:	SMMU registers mapping
  */
 struct mtk_jpegenc_comp_dev {
 	struct device *dev;
@@ -163,6 +175,7 @@ struct mtk_jpegenc_comp_dev {
 	enum mtk_jpeg_hw_state hw_state;
 	/* spinlock protecting the hw device resource */
 	spinlock_t hw_lock;
+	struct regmap *smmu_regmap;
 };
 
 /**
@@ -177,6 +190,7 @@ struct mtk_jpegenc_comp_dev {
  * @hw_param:			jpeg decode hw parameters
  * @hw_state:			record hw state
  * @hw_lock:			spinlock protecting hw
+ * @smmu_regmap:		SMMU registers mapping
  */
 struct mtk_jpegdec_comp_dev {
 	struct device *dev;
@@ -190,6 +204,7 @@ struct mtk_jpegdec_comp_dev {
 	enum mtk_jpeg_hw_state hw_state;
 	/* spinlock protecting the hw device resource */
 	spinlock_t hw_lock;
+	struct regmap *smmu_regmap;
 };
 
 /**
diff --git a/drivers/media/platform/mediatek/jpeg/mtk_jpeg_dec_hw.c b/drivers/media/platform/mediatek/jpeg/mtk_jpeg_dec_hw.c
index 5a485e905787..2e079a6e5d5d 100644
--- a/drivers/media/platform/mediatek/jpeg/mtk_jpeg_dec_hw.c
+++ b/drivers/media/platform/mediatek/jpeg/mtk_jpeg_dec_hw.c
@@ -613,6 +613,25 @@ static int mtk_jpegdec_hw_init_irq(struct mtk_jpegdec_comp_dev *dev)
 	return 0;
 }
 
+static int mtk_jpegdec_smmu_init(struct mtk_jpegdec_comp_dev *dev)
+{
+	struct mtk_jpeg_dev *master_dev = dev->master_dev;
+
+	if (!master_dev->variant->support_smmu)
+		return 0;
+
+	dev->smmu_regmap =
+		syscon_regmap_lookup_by_phandle(dev->plat_dev->dev.of_node,
+						"mediatek,smmu-config");
+	if (IS_ERR(dev->smmu_regmap)) {
+		return dev_err_probe(dev->dev, PTR_ERR(dev->smmu_regmap),
+				     "mmap smmu_base failed(%ld)\n",
+				     PTR_ERR(dev->smmu_regmap));
+	}
+
+	return 0;
+}
+
 static int mtk_jpegdec_hw_probe(struct platform_device *pdev)
 {
 	struct mtk_jpegdec_clk *jpegdec_clk;
@@ -666,6 +685,10 @@ static int mtk_jpegdec_hw_probe(struct platform_device *pdev)
 	dev->master_dev = master_dev;
 	master_dev->max_hw_count++;
 
+	ret = mtk_jpegdec_smmu_init(dev);
+	if (ret)
+		return ret;
+
 	platform_set_drvdata(pdev, dev);
 	pm_runtime_enable(&pdev->dev);
 	ret = devm_clk_bulk_get(dev->dev,
diff --git a/drivers/media/platform/mediatek/jpeg/mtk_jpeg_enc_hw.c b/drivers/media/platform/mediatek/jpeg/mtk_jpeg_enc_hw.c
index 1cfdfac98829..0001d69ae7ba 100644
--- a/drivers/media/platform/mediatek/jpeg/mtk_jpeg_enc_hw.c
+++ b/drivers/media/platform/mediatek/jpeg/mtk_jpeg_enc_hw.c
@@ -339,6 +339,25 @@ static int mtk_jpegenc_hw_init_irq(struct mtk_jpegenc_comp_dev *dev)
 	return 0;
 }
 
+static int mtk_jpegenc_smmu_init(struct mtk_jpegenc_comp_dev *dev)
+{
+	struct mtk_jpeg_dev *master_dev = dev->master_dev;
+
+	if (!master_dev->variant->support_smmu)
+		return 0;
+
+	dev->smmu_regmap =
+		syscon_regmap_lookup_by_phandle(dev->plat_dev->dev.of_node,
+						"mediatek,smmu-config");
+	if (IS_ERR(dev->smmu_regmap)) {
+		return dev_err_probe(dev->dev, PTR_ERR(dev->smmu_regmap),
+				     "mmap smmu_base failed(%ld)\n",
+				     PTR_ERR(dev->smmu_regmap));
+	}
+
+	return 0;
+}
+
 static int mtk_jpegenc_hw_probe(struct platform_device *pdev)
 {
 	struct mtk_jpegenc_clk *jpegenc_clk;
@@ -390,6 +409,10 @@ static int mtk_jpegenc_hw_probe(struct platform_device *pdev)
 	dev->master_dev = master_dev;
 	master_dev->max_hw_count++;
 
+	ret = mtk_jpegenc_smmu_init(dev);
+	if (ret)
+		return ret;
+
 	platform_set_drvdata(pdev, dev);
 	pm_runtime_enable(&pdev->dev);
 	ret = devm_clk_bulk_get(dev->dev,
-- 
2.45.2



^ permalink raw reply related

* [PATCH v14 06/12] media: mediatek: jpeg: fix decoding buffer number setting timing issue
From: Kyrie Wu @ 2026-04-23  9:46 UTC (permalink / raw)
  To: Hans Verkuil, Mauro Carvalho Chehab, Rob Herring,
	Krzysztof Kozlowski, Nicolas Dufresne, Conor Dooley,
	Matthias Brugger, AngeloGioacchino Del Regno, Kyrie Wu,
	linux-media, devicetree, linux-kernel, linux-arm-kernel,
	linux-mediatek
In-Reply-To: <20260423094656.32044-1-kyrie.wu@mediatek.com>

The src buffer doesn't need set information and dst buf parameters
only need to set when the power set succussed and protect the
setting by spinlock ensuring that any later operations acting
on this buffer reflect accurate state and frame data.

Fixes: dedc21500334 ("media: mtk-jpegdec: add jpeg decode worker interface")
Signed-off-by: Kyrie Wu <kyrie.wu@mediatek.com>
---
 drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c   | 9 +++------
 drivers/media/platform/mediatek/jpeg/mtk_jpeg_dec_hw.c | 1 +
 drivers/media/platform/mediatek/jpeg/mtk_jpeg_enc_hw.c | 1 +
 3 files changed, 5 insertions(+), 6 deletions(-)

diff --git a/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c b/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c
index e85a3d0bd8ac..99f3f3b4d081 100644
--- a/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c
+++ b/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c
@@ -1733,7 +1733,6 @@ static void mtk_jpegdec_worker(struct work_struct *work)
 
 	v4l2_m2m_buf_copy_metadata(src_buf, dst_buf);
 	jpeg_src_buf = mtk_jpeg_vb2_to_srcbuf(&src_buf->vb2_buf);
-	jpeg_dst_buf = mtk_jpeg_vb2_to_srcbuf(&dst_buf->vb2_buf);
 
 	if (mtk_jpeg_check_resolution_change(ctx,
 					     &jpeg_src_buf->dec_param)) {
@@ -1742,11 +1741,6 @@ static void mtk_jpegdec_worker(struct work_struct *work)
 		goto getbuf_fail;
 	}
 
-	jpeg_src_buf->curr_ctx = ctx;
-	jpeg_src_buf->frame_num = ctx->total_frame_num;
-	jpeg_dst_buf->curr_ctx = ctx;
-	jpeg_dst_buf->frame_num = ctx->total_frame_num;
-
 	mtk_jpegdec_set_hw_param(ctx, hw_id, src_buf, dst_buf);
 	ret = pm_runtime_resume_and_get(comp_jpeg[hw_id]->dev);
 	if (ret < 0) {
@@ -1771,6 +1765,9 @@ static void mtk_jpegdec_worker(struct work_struct *work)
 			      msecs_to_jiffies(MTK_JPEG_HW_TIMEOUT_MSEC));
 
 	spin_lock_irqsave(&comp_jpeg[hw_id]->hw_lock, flags);
+	jpeg_dst_buf = mtk_jpeg_vb2_to_srcbuf(&dst_buf->vb2_buf);
+	jpeg_dst_buf->curr_ctx = ctx;
+	jpeg_dst_buf->frame_num = ctx->total_frame_num;
 	ctx->total_frame_num++;
 	mtk_jpeg_dec_reset(comp_jpeg[hw_id]->reg_base);
 	mtk_jpeg_dec_set_config(comp_jpeg[hw_id]->reg_base,
diff --git a/drivers/media/platform/mediatek/jpeg/mtk_jpeg_dec_hw.c b/drivers/media/platform/mediatek/jpeg/mtk_jpeg_dec_hw.c
index 9a8dbca6af00..e4d2c5d4ec73 100644
--- a/drivers/media/platform/mediatek/jpeg/mtk_jpeg_dec_hw.c
+++ b/drivers/media/platform/mediatek/jpeg/mtk_jpeg_dec_hw.c
@@ -513,6 +513,7 @@ static void mtk_jpegdec_put_buf(struct mtk_jpegdec_comp_dev *jpeg)
 				v4l2_m2m_buf_done(&tmp_dst_done_buf->b,
 						  VB2_BUF_STATE_DONE);
 				ctx->last_done_frame_num++;
+				break;
 			}
 		}
 	}
diff --git a/drivers/media/platform/mediatek/jpeg/mtk_jpeg_enc_hw.c b/drivers/media/platform/mediatek/jpeg/mtk_jpeg_enc_hw.c
index 5d1c217fea0f..2adea3aca50b 100644
--- a/drivers/media/platform/mediatek/jpeg/mtk_jpeg_enc_hw.c
+++ b/drivers/media/platform/mediatek/jpeg/mtk_jpeg_enc_hw.c
@@ -242,6 +242,7 @@ static void mtk_jpegenc_put_buf(struct mtk_jpegenc_comp_dev *jpeg)
 				v4l2_m2m_buf_done(&tmp_dst_done_buf->b,
 						  VB2_BUF_STATE_DONE);
 				ctx->last_done_frame_num++;
+				break;
 			}
 		}
 	}
-- 
2.45.2



^ permalink raw reply related

* [PATCH v14 11/12] media: mediatek: jpeg: add jpeg compatible
From: Kyrie Wu @ 2026-04-23  9:46 UTC (permalink / raw)
  To: Hans Verkuil, Mauro Carvalho Chehab, Rob Herring,
	Krzysztof Kozlowski, Nicolas Dufresne, Conor Dooley,
	Matthias Brugger, AngeloGioacchino Del Regno, Kyrie Wu,
	linux-media, devicetree, linux-kernel, linux-arm-kernel,
	linux-mediatek
In-Reply-To: <20260423094656.32044-1-kyrie.wu@mediatek.com>

Add jpeg dec and enc compatible for mt8196

Signed-off-by: Kyrie Wu <kyrie.wu@mediatek.com>
Reviewed-by: Nicolas Dufresne <nicolas.dufresne@collabora.com>
---
 .../platform/mediatek/jpeg/mtk_jpeg_core.c    | 34 +++++++++++++++++++
 .../platform/mediatek/jpeg/mtk_jpeg_dec_hw.c  |  3 ++
 .../platform/mediatek/jpeg/mtk_jpeg_enc_hw.c  |  3 ++
 3 files changed, 40 insertions(+)

diff --git a/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c b/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c
index a5b0f7620121..8bd52ca03e9f 100644
--- a/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c
+++ b/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c
@@ -1917,6 +1917,19 @@ static struct mtk_jpeg_variant mtk8195_jpegenc_drvdata = {
 	.jpeg_worker = mtk_jpegenc_worker,
 };
 
+static struct mtk_jpeg_variant mtk8196_jpegenc_drvdata = {
+	.formats = mtk_jpeg_enc_formats,
+	.num_formats = MTK_JPEG_ENC_NUM_FORMATS,
+	.qops = &mtk_jpeg_enc_qops,
+	.m2m_ops = &mtk_jpeg_multicore_enc_m2m_ops,
+	.dev_name = "mtk-jpeg-enc",
+	.ioctl_ops = &mtk_jpeg_enc_ioctl_ops,
+	.out_q_default_fourcc = V4L2_PIX_FMT_YUYV,
+	.cap_q_default_fourcc = V4L2_PIX_FMT_JPEG,
+	.multi_core = true,
+	.jpeg_worker = mtk_jpegenc_worker,
+};
+
 static const struct mtk_jpeg_variant mtk8195_jpegdec_drvdata = {
 	.formats = mtk_jpeg_dec_formats,
 	.num_formats = MTK_JPEG_DEC_NUM_FORMATS,
@@ -1930,6 +1943,19 @@ static const struct mtk_jpeg_variant mtk8195_jpegdec_drvdata = {
 	.jpeg_worker = mtk_jpegdec_worker,
 };
 
+static const struct mtk_jpeg_variant mtk8196_jpegdec_drvdata = {
+	.formats = mtk_jpeg_dec_formats,
+	.num_formats = MTK_JPEG_DEC_NUM_FORMATS,
+	.qops = &mtk_jpeg_dec_qops,
+	.m2m_ops = &mtk_jpeg_multicore_dec_m2m_ops,
+	.dev_name = "mtk-jpeg-dec",
+	.ioctl_ops = &mtk_jpeg_dec_ioctl_ops,
+	.out_q_default_fourcc = V4L2_PIX_FMT_JPEG,
+	.cap_q_default_fourcc = V4L2_PIX_FMT_YUV420M,
+	.multi_core = true,
+	.jpeg_worker = mtk_jpegdec_worker,
+};
+
 static const struct of_device_id mtk_jpeg_match[] = {
 	{
 		.compatible = "mediatek,mt8173-jpgdec",
@@ -1951,6 +1977,14 @@ static const struct of_device_id mtk_jpeg_match[] = {
 		.compatible = "mediatek,mt8195-jpgdec",
 		.data = &mtk8195_jpegdec_drvdata,
 	},
+	{
+		.compatible = "mediatek,mt8196-jpgenc",
+		.data = &mtk8196_jpegenc_drvdata,
+	},
+	{
+		.compatible = "mediatek,mt8196-jpgdec",
+		.data = &mtk8196_jpegdec_drvdata,
+	},
 	{},
 };
 
diff --git a/drivers/media/platform/mediatek/jpeg/mtk_jpeg_dec_hw.c b/drivers/media/platform/mediatek/jpeg/mtk_jpeg_dec_hw.c
index e4d2c5d4ec73..5a485e905787 100644
--- a/drivers/media/platform/mediatek/jpeg/mtk_jpeg_dec_hw.c
+++ b/drivers/media/platform/mediatek/jpeg/mtk_jpeg_dec_hw.c
@@ -45,6 +45,9 @@ static const struct of_device_id mtk_jpegdec_hw_ids[] = {
 	{
 		.compatible = "mediatek,mt8195-jpgdec-hw",
 	},
+	{
+		.compatible = "mediatek,mt8196-jpgdec-hw",
+	},
 	{},
 };
 MODULE_DEVICE_TABLE(of, mtk_jpegdec_hw_ids);
diff --git a/drivers/media/platform/mediatek/jpeg/mtk_jpeg_enc_hw.c b/drivers/media/platform/mediatek/jpeg/mtk_jpeg_enc_hw.c
index 2adea3aca50b..1cfdfac98829 100644
--- a/drivers/media/platform/mediatek/jpeg/mtk_jpeg_enc_hw.c
+++ b/drivers/media/platform/mediatek/jpeg/mtk_jpeg_enc_hw.c
@@ -52,6 +52,9 @@ static const struct of_device_id mtk_jpegenc_drv_ids[] = {
 	{
 		.compatible = "mediatek,mt8195-jpgenc-hw",
 	},
+	{
+		.compatible = "mediatek,mt8196-jpgenc-hw",
+	},
 	{},
 };
 MODULE_DEVICE_TABLE(of, mtk_jpegenc_drv_ids);
-- 
2.45.2



^ permalink raw reply related

* [PATCH v14 10/12] media: dt-bindings: mediatek,jpeg: Add mediatek, mt8196-jpgenc compatible
From: Kyrie Wu @ 2026-04-23  9:46 UTC (permalink / raw)
  To: Hans Verkuil, Mauro Carvalho Chehab, Rob Herring,
	Krzysztof Kozlowski, Nicolas Dufresne, Conor Dooley,
	Matthias Brugger, AngeloGioacchino Del Regno, Kyrie Wu,
	linux-media, devicetree, linux-kernel, linux-arm-kernel,
	linux-mediatek
  Cc: Krzysztof Kozlowski
In-Reply-To: <20260423094656.32044-1-kyrie.wu@mediatek.com>

Compared to the previous generation IC, the MT8196 uses SMMU
instead of IOMMU and supports features such as dynamic voltage
and frequency scaling. Therefore, add "mediatek,mt8196-jpgenc"
compatible to the binding document.

Signed-off-by: Kyrie Wu <kyrie.wu@mediatek.com>
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
---
 .../bindings/media/mediatek,mt8195-jpegenc.yaml           | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/media/mediatek,mt8195-jpegenc.yaml b/Documentation/devicetree/bindings/media/mediatek,mt8195-jpegenc.yaml
index 596186497b68..e2d772ea0fb0 100644
--- a/Documentation/devicetree/bindings/media/mediatek,mt8195-jpegenc.yaml
+++ b/Documentation/devicetree/bindings/media/mediatek,mt8195-jpegenc.yaml
@@ -14,7 +14,9 @@ description:
 
 properties:
   compatible:
-    const: mediatek,mt8195-jpgenc
+    enum:
+      - mediatek,mt8195-jpgenc
+      - mediatek,mt8196-jpgenc
 
   power-domains:
     maxItems: 1
@@ -44,7 +46,9 @@ patternProperties:
 
     properties:
       compatible:
-        const: mediatek,mt8195-jpgenc-hw
+        enum:
+          - mediatek,mt8195-jpgenc-hw
+          - mediatek,mt8196-jpgenc-hw
 
       reg:
         maxItems: 1
-- 
2.45.2



^ permalink raw reply related

* Re: [PATCH] iommu/arm-smmu-v3: Allow disabling Stage 1 translation
From: Will Deacon @ 2026-04-23  9:47 UTC (permalink / raw)
  To: Jason Gunthorpe
  Cc: Evangelos Petrongonas, Robin Murphy, Joerg Roedel, Nicolin Chen,
	Pranjal Shrivastava, Lu Baolu, linux-arm-kernel, iommu,
	linux-kernel, nh-open-source, Zeev Zilberman
In-Reply-To: <aenp6FHzx9rtUQkZ@willie-the-truck>

On Thu, Apr 23, 2026 at 10:44:08AM +0100, Will Deacon wrote:
> On Wed, Apr 22, 2026 at 01:23:51PM -0300, Jason Gunthorpe wrote:
> > On Wed, Apr 22, 2026 at 06:44:31AM +0000, Evangelos Petrongonas wrote:
> > > The motivation is live update of the hypervisor: we want to kexec into a
> > > new kernel while keeping DMA from passthrough devices flowing, which
> > > means the SMMU's translation state has to survive the handover. The Live
> > > Update Orchestrator work [1] and the in-progress  "iommu: Add live
> > > update state preservation" series [2] are building exactly this plumbing
> > > on top of KHO; [2]'s cover letter calls out Arm SMMUv3 support as future
> > > work, and an earlier RFC from Amazon [3] sketched the same idea for
> > > iommufd.
> > 
> > It would be appropriate to keep this patch with the rest of that out
> > of tree pile, for example in the series that enables s2 only support
> > in smmuv3.
> > 
> > > For this use case, Stage 2 is materially easier to persist than Stage 1,
> > > for structural rather than performance reasons: 
> > 
> > I don't think so. The driver needs to know each and every STE that
> > will survive KHO. The ones that don't survive need to be reset to
> > abort STEs. From that point it is trivial enough to include the CD
> > memory in the preservation.
> > 
> > It would help to send a preparation series to switch the ARM STE and
> > CD logic away from dma_alloc_coherent and use iommu-pages instead,
> > since we only expect iommu-pages to support preservation..
> 
> Does iommu-pages provide a mechanism to map the memory as non-cacheable
> if the SMMU isn't coherent? I really don't want to entertain CMOs for
> the queues.

Sorry, I said "queues" here but I was really referring to any of the
current dma_alloc_coherent() allocations and it's the CDs that matter
in this thread.

The rationale being that:

1. A cacheable mapping is going to pollute the cache unnecessarily.
2. Reasoning about atomicity and ordering is a lot more subtle with CMOs.
3. It seems like a pretty invasive driver change to support live update,
   which isn't relevant for a lot of systems.

Will


^ permalink raw reply

* Re: [PATCH] KVM: arm64: Validate the FF-A memory access descriptor placement
From: Sudeep Holla @ 2026-04-23  9:55 UTC (permalink / raw)
  To: Sebastian Ene
  Cc: Marc Zyngier, oupton, will, ayrton, catalin.marinas, joey.gouly,
	Sudeep Holla, korneld, kvmarm, linux-arm-kernel, linux-kernel,
	android-kvm, mrigendra.chaubey, perlarsen, suzuki.poulose,
	yuzenghui, stable
In-Reply-To: <aenjvY5VJxFye52e@google.com>

On Thu, Apr 23, 2026 at 09:17:49AM +0000, Sebastian Ene wrote:
> On Wed, Apr 22, 2026 at 08:29:06PM +0100, Sudeep Holla wrote:

[...]

> Hello Sudeep,
> 
> > That's just the current choice in the driver and can be changed in the future.
> > 
> > > and makes use of the same assumption in: ffa_mem_desc_offset().
> > > https://elixir.bootlin.com/linux/v7.0/source/include/linux/arm_ffa.h#L448
> > 
> > Again this is just in the transmit path of the message the driver is
> > constructing and hence it is a simple choice rather than wrong assumption.
> >
> > > The later one seems wrong IMO. because we should compute the offset
> > > based on the value stored in ep_mem_offset and not adding it up with
> > > sizeof(struct ffa_mem_region).
> > > 
> > 
> > Sorry what am I missing as the driver is building these descriptors to
> > send it across to SPMC, we are populating the field and it will be 0
> > before it is initialised
> 
> Right, what I meant is having something like this since this function is not limited
> to the driver scope and using it from other components would imply relying on the
> assumption: 'ep_mem_offset == sizeof(struct ffa_mem_region)'. We will also have to validate
> that the `ep_mem_offset` doesn't point outside of the mailbox designated buffer.
> 

Sure, we can extend the function itself or add addition helper to get the
functionality you are looking for the validation.

> ---
> diff --git a/include/linux/arm_ffa.h b/include/linux/arm_ffa.h
> index 81e603839c4a..62d67dae8b70 100644
> --- a/include/linux/arm_ffa.h
> +++ b/include/linux/arm_ffa.h
> @@ -445,7 +445,7 @@ ffa_mem_desc_offset(struct ffa_mem_region *buf, int count, u32 ffa_version)
>         if (!FFA_MEM_REGION_HAS_EP_MEM_OFFSET(ffa_version))
>                 offset += offsetof(struct ffa_mem_region, ep_mem_offset);
>         else
> -               offset += sizeof(struct ffa_mem_region);
> +               offset += buf->ep_mem_offset;
>
>         return offset;
>  }
> ---
> 
> And then move `ffa_mem_region_additional_setup` to be called earlier before `ffa_mem_desc_offset`:
> (so that it can setup the value for ep_mem_offset)
> 
> ---
> diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c
> index f2f94d4d533e..66de59c88aff 100644
> --- a/drivers/firmware/arm_ffa/driver.c
> +++ b/drivers/firmware/arm_ffa/driver.c
> @@ -691,6 +691,8 @@ ffa_setup_and_transmit(u32 func_id, void *buffer, u32 max_fragsize,
>         mem_region->flags = args->flags;
>         mem_region->sender_id = drv_info->vm_id;
>         mem_region->attributes = ffa_memory_attributes_get(func_id);
> +
> +       ffa_mem_region_additional_setup(drv_info->version, mem_region);

Ah this could do the trick. I need to check if all the usages are covered
though.

>         composite_offset = ffa_mem_desc_offset(buffer, args->nattrs,
>                                                drv_info->version);
>  
> @@ -708,7 +710,6 @@ ffa_setup_and_transmit(u32 func_id, void *buffer, u32 max_fragsize,
>         }
>         mem_region->handle = 0;
>         mem_region->ep_count = args->nattrs;
> -       ffa_mem_region_additional_setup(drv_info->version, mem_region);
> ---
> 
> > 
> > > Maybe this should be the fix instead and not the one in pKVM ? What do
> > > you think ?
> > > 
> > 
> > Can you share the diff you have in mind to understand your concern better
> > or are you referring to this patch itself.
> 
> Sure, please let me know if you think this is wrong. I might have misunderstood it. 
> 

Nope, the patch helped to understand it quicker. Thanks for that.

> > 
> > > The current implementation in pKVM makes use of the
> > > ffa_mem_desc_offset() to validate the first EMAD. If a compromised host
> > > places an EMAD at a different offset than sizeof(struct ffa_mem_region),
> > > then pKVM will not validate that EMAD.
> > >
> > 
> > Calling the host as compromised if it chooses a different offset seems bit
> > of extreme here. I am no sure if I am missing to understand something here.
> > 
> 
> Sorry for not explaining it, in pKVM model we don't trust the host kernel so
> we can assume that everything that doesn't pass the hypervisor validation(in
> this case the ff-a memory transaction) can be a potential attack that wants
> to compromise EL2.
> 

I am aware of the principle in general, but this example with different offset
can't be assumed as comprised host if the offset + size is well within the
Tx buffer size boundaries. That should be the way for you to cross check for
any compromise IHMO.

-- 
Regards,
Sudeep


^ permalink raw reply

* [PATCH v2] iommu/arm-smmu-qcom: Fix fastrpc compatible string in ACTLR client match table
From: bibek.patro @ 2026-04-23 10:02 UTC (permalink / raw)
  To: Rob Clark, Will Deacon, Robin Murphy, Joerg Roedel
  Cc: Dmitry Baryshkov, iommu, linux-arm-msm, linux-arm-kernel,
	linux-kernel, srinivas.kandagatla, Bibek Kumar Patro,
	Dmitry Baryshkov, Shawn Guo

From: Bibek Kumar Patro <bibek.patro@oss.qualcomm.com>

The qcom_smmu_actlr_client_of_match table contained "qcom,fastrpc" as
the compatible string for applying ACTLR prefetch settings to FastRPC
devices. However, "qcom,fastrpc" is the compatible string for the parent
rpmsg channel node, which is not an IOMMU client — it carries no
"iommus" property in the device tree and is never attached to an SMMU
context bank.

The actual IOMMU clients are the compute context bank (CB) child nodes,
which use the compatible string "qcom,fastrpc-compute-cb". These nodes
carry the "iommus" property and are probed by fastrpc_cb_driver via
fastrpc_cb_probe(), which sets up the DMA mask and IOMMU mappings for
each FastRPC session. The device tree structure is:

  fastrpc {
      compatible = "qcom,fastrpc";        /* rpmsg channel, no iommus */
      ...
      compute-cb@3 {
          compatible = "qcom,fastrpc-compute-cb";
          iommus = <&apps_smmu 0x1823 0x0>;  /* actual IOMMU client */
      };
  };

Since qcom_smmu_set_actlr_dev() calls of_match_device() against the
device being attached to the SMMU context bank, the "qcom,fastrpc"
entry was never matching any device. As a result, the ACTLR prefetch
settings (PREFETCH_DEEP | CPRE | CMTLB) were silently never applied
for FastRPC compute context banks.

Fix this by replacing "qcom,fastrpc" with "qcom,fastrpc-compute-cb"
in the match table so that the ACTLR settings are correctly applied
to the compute CB devices that are the true IOMMU clients.

Assisted-by: Claude:claude-sonnet-4-6
Fixes: 3e35c3e725de ("iommu/arm-smmu: Add ACTLR data and support for qcom_smmu_500")
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
Reviewed-by: Shawn Guo <shengchao.guo@oss.qualcomm.com>
Signed-off-by: Bibek Kumar Patro <bibek.patro@oss.qualcomm.com>
---

While there is an ongoing discussion [1] on how to differentiate ACTLR
prefetch settings between compute DSP and audio DSP fastrpc devices, it
is necessary to first fix the compatible string to
"qcom,fastrpc-compute-cb".
Both compute DSP and audio DSP fastrpc nodes use this compatible string,
so both will receive the ACTLR settings after this fix. However, for
audio DSP devices the effect remains the same as the current
state since they do not actively use prefetch — the write is effectively
a NOP for them. The fix is meaningful for compute DSP devices, which
actively use prefetch and were previously being silently skipped.

[1]:
https://lore.kernel.org/all/9b4c895a-c822-40e6-bb92-8fdcd09c82d3@oss.qualcomm.com/


v1->v2:
  - Collect "Reviewed-by" tags.
  - Address nit on "Assisted-by" tags format.
  - [v1]:
    https://lore.kernel.org/all/20260408130825.3268733-1-bibek.patro@oss.qualcomm.com/

 drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
index edd41b5a3b6a..2d006049dd61 100644
--- a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
+++ b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
@@ -39,7 +39,7 @@ static const struct of_device_id qcom_smmu_actlr_client_of_match[] = {
 			.data = (const void *) (PREFETCH_DEEP | CPRE | CMTLB) },
 	{ .compatible = "qcom,adreno-smmu",
 			.data = (const void *) (PREFETCH_DEEP | CPRE | CMTLB) },
-	{ .compatible = "qcom,fastrpc",
+	{ .compatible = "qcom,fastrpc-compute-cb",
 			.data = (const void *) (PREFETCH_DEEP | CPRE | CMTLB) },
 	{ .compatible = "qcom,qcm2290-mdss",
 			.data = (const void *) (PREFETCH_SHALLOW | CPRE | CMTLB) },
--
2.34.1



^ permalink raw reply related

* Re: [PATCH] cpu/hotplug: Fix NULL kobject warning in cpuhp_smt_enable()
From: Thomas Gleixner @ 2026-04-23 10:08 UTC (permalink / raw)
  To: Catalin Marinas, Jinjie Ruan
  Cc: peterz, sudeep.holla, yangyicong, dietmar.eggemann,
	Jonathan.Cameron, linux-kernel, James Morse, linux-arm-kernel
In-Reply-To: <aeNxKpHzTQX4_kId@arm.com>

On Sat, Apr 18 2026 at 12:55, Catalin Marinas wrote:
> Another option would have been to avoid marking such CPUs present but I
> think this will break other things. Yet another option is to register
> all CPU devices even if they never come up (like maxcpus greater than
> actual CPUs).
>
> Opinions? It might be an arm64+ACPI-only thing.

I think so. The proper thing to do is to apply sane limits:

 1) The possible CPUs enumerated by firmware N_POSSIBLE_FW

 2) The maxcpus limit on the command line N_MAXCPUS_CL

So the actual possible CPUs evaluates to:

   num_possible = min(N_POSSIBLE_FW, N_MAXCPUS_CL, CONFIG_NR_CPUS);

The evaluation of the firmware should not mark CPUs present which are
actually not. ACPI gives you that information. See:

         5.2.12.14 GIC CPU Interface (GICC) Structure

in the ACPI spec. That has two related bits:

Enabled:

   If this bit is set, the processor is ready for use. If this bit is
   clear and the Online Capable bit is set, the system supports enabling
   this processor during OS runtime. If this bit is clear and the Online
   Capable bit is also clear, this processor is un- usable, and the
   operating system support will not attempt to use it.

Online Capable:

   The information conveyed by this bit depends on the value of the
   Enabled bit. If the Enabled bit is set, this bit is reserved and must
   be zero. Otherwise, if this bit is set, the system supports enabling
   this processor later during OS runtime

So the combination of those gives you the right answer:

   Enabled	Online
   	        Capable
   0            0        Not present, not possible
   0            1        Not present, but possible to "hotplug" layter
   1            0        Present
   1            1        Invalid

The kernel sizes everything on the number of possible CPUs and the
present CPU mask is only there to figure out which CPUs are actually
usable and can be brought up.

The runtime physical hotplug mechanics use acpi_[un]map_cpu() to toggle
the present bit.

Thanks,

        tglx





^ permalink raw reply

* Re: [RFC PATCH v2 2/4] tpm: tpm_crb_ffa: revert defered_probed when tpm_crb_ffa is built-in
From: Jarkko Sakkinen @ 2026-04-23 10:17 UTC (permalink / raw)
  To: Yeoreum Yun
  Cc: linux-security-module, linux-kernel, linux-integrity,
	linux-arm-kernel, kvmarm, paul, jmorris, serge, zohar,
	roberto.sassu, dmitry.kasatkin, eric.snowberg, jgg, sudeep.holla,
	maz, oupton, joey.gouly, suzuki.poulose, yuzenghui,
	catalin.marinas, will, noodles, sebastianene
In-Reply-To: <20260422162449.1814615-3-yeoreum.yun@arm.com>

On Wed, Apr 22, 2026 at 05:24:47PM +0100, Yeoreum Yun wrote:
> commit 746d9e9f62a6 ("tpm: tpm_crb_ffa: try to probe tpm_crb_ffa when it's build_in")
> probe tpm_crb_ffa forcefully when it's built-in to integrate with IMA.
> 
> However, as IMA init function is changed to late_initcall_sync level.
> So, this change isn't required anymore.
> 
> Signed-off-by: Yeoreum Yun <yeoreum.yun@arm.com>
> ---
>  drivers/char/tpm/tpm_crb_ffa.c | 18 +++---------------
>  1 file changed, 3 insertions(+), 15 deletions(-)
> 
> diff --git a/drivers/char/tpm/tpm_crb_ffa.c b/drivers/char/tpm/tpm_crb_ffa.c
> index 99f1c1e5644b..025c4d4b17ca 100644
> --- a/drivers/char/tpm/tpm_crb_ffa.c
> +++ b/drivers/char/tpm/tpm_crb_ffa.c
> @@ -177,23 +177,13 @@ static int tpm_crb_ffa_to_linux_errno(int errno)
>   */
>  int tpm_crb_ffa_init(void)
>  {
> -	int ret = 0;
> -
> -	if (!IS_MODULE(CONFIG_TCG_ARM_CRB_FFA)) {
> -		ret = ffa_register(&tpm_crb_ffa_driver);
> -		if (ret) {
> -			tpm_crb_ffa = ERR_PTR(-ENODEV);
> -			return ret;
> -		}
> -	}
> -
>  	if (!tpm_crb_ffa)
> -		ret = -ENOENT;
> +		return -ENOENT;
> 
>  	if (IS_ERR_VALUE(tpm_crb_ffa))
> -		ret = -ENODEV;
> +		return -ENODEV;
> 
> -	return ret;
> +	return 0;
>  }
>  EXPORT_SYMBOL_GPL(tpm_crb_ffa_init);
> 
> @@ -405,9 +395,7 @@ static struct ffa_driver tpm_crb_ffa_driver = {
>  	.id_table = tpm_crb_ffa_device_id,
>  };
> 
> -#ifdef MODULE
>  module_ffa_driver(tpm_crb_ffa_driver);
> -#endif
> 
>  MODULE_AUTHOR("Arm");
>  MODULE_DESCRIPTION("TPM CRB FFA driver");
> --
> LEVI:{C3F47F37-75D8-414A-A8BA-3980EC8A46D7}
> 

I'll hold review to next version i.e. after Mimi's concerns
have been addressed.

BR, Jarkko


^ permalink raw reply

* Re: [PATCH 1/4] arm64: dts: imx8mp: switch usb controller to flattened model
From: Xu Yang @ 2026-04-23 10:20 UTC (permalink / raw)
  To: Frank Li
  Cc: robh, krzk+dt, conor+dt, s.hauer, kernel, festevam, devicetree,
	imx, linux-arm-kernel, linux-kernel, jun.li
In-Reply-To: <aehEXEsiFl2PVIye@lizhi-Precision-Tower-5810>

On Tue, Apr 21, 2026 at 11:45:32PM -0400, Frank Li wrote:
> On Tue, Apr 21, 2026 at 06:55:00PM +0800, Xu Yang wrote:
> > Switch to use flattened model for all USB controllers. To enable USB
> > controllers with restricted DMA access range to work correctly, add a
> > pseudo simple-bus to constrain the dma address.
> 
> This should not "pseudo", and bus is physical existed, which limited dma
> range since it transparent to SW, which may not mention in spec.

OK. Will remove the word "pseudo" in v2.

> 
> >
> > Also reorder USB-related nodes.
> 
> this need new patch to just do reorder.

OK. Will add a separate patch.

Thanks,
Xu Yang


^ permalink raw reply

* Re: [PATCH v3 4/8] thermal: amlogic: Add support for secure monitor calibration readout
From: Daniel Lezcano @ 2026-04-23 10:25 UTC (permalink / raw)
  To: Ronald Claveau, Guillaume La Roque, Rafael J. Wysocki,
	Daniel Lezcano, Zhang Rui, Lukasz Luba, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Neil Armstrong, Kevin Hilman,
	Jerome Brunet, Martin Blumenstingl
  Cc: linux-pm, linux-amlogic, devicetree, linux-kernel,
	linux-arm-kernel
In-Reply-To: <20260421-add-thermal-t7-vim4-v3-4-a2e7215ed003@aliel.fr>


Hi Ronald,

On 4/21/26 09:19, Ronald Claveau wrote:
> Some SoCs (e.g. T7) expose thermal calibration data through the secure
> monitor rather than a directly accessible eFuse register. Add a use_sm
> flag to amlogic_thermal_data to select this path, and retrieve the
> firmware handle and tsensor_id from the "amlogic,secure-monitor" DT
> phandle with one fixed argument.
> 
> Also introduce the amlogic,t7-thermal compatible using this new path.
> 
> Signed-off-by: Ronald Claveau <linux-kernel-dev@aliel.fr>
> ---
>   drivers/thermal/amlogic_thermal.c | 58 +++++++++++++++++++++++++++++++++++----
>   1 file changed, 53 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/thermal/amlogic_thermal.c b/drivers/thermal/amlogic_thermal.c
> index 5448d772db12a..11e3948cc0669 100644
> --- a/drivers/thermal/amlogic_thermal.c
> +++ b/drivers/thermal/amlogic_thermal.c
> @@ -25,6 +25,7 @@
>   #include <linux/platform_device.h>
>   #include <linux/regmap.h>
>   #include <linux/thermal.h>
> +#include <linux/firmware/meson/meson_sm.h>
>   
>   #include "thermal_hwmon.h"
>   
> @@ -84,12 +85,14 @@ struct amlogic_thermal_soc_calib_data {
>    * @u_efuse_off: register offset to read fused calibration value
>    * @calibration_parameters: calibration parameters structure pointer
>    * @regmap_config: regmap config for the device
> + * @use_sm: read data from secure monitor instead of efuse
>    * This structure is required for configuration of amlogic thermal driver.
>    */
>   struct amlogic_thermal_data {
>   	int u_efuse_off;
>   	const struct amlogic_thermal_soc_calib_data *calibration_parameters;
>   	const struct regmap_config *regmap_config;
> +	bool use_sm;
>   };
>   
>   struct amlogic_thermal {
> @@ -100,6 +103,8 @@ struct amlogic_thermal {
>   	struct clk *clk;
>   	struct thermal_zone_device *tzd;
>   	u32 trim_info;
> +	struct meson_sm_firmware *sm_fw;
> +	u32 tsensor_id;
>   };
>   
>   /*
> @@ -138,6 +143,12 @@ static int amlogic_thermal_initialize(struct amlogic_thermal *pdata)
>   	int ret = 0;
>   	int ver;
>   
> +	if (pdata->data->use_sm) {
> +		return meson_sm_get_thermal_calib(pdata->sm_fw,
> +						  &pdata->trim_info,
> +						  pdata->tsensor_id);
> +	}
> +
>   	regmap_read(pdata->sec_ao_map, pdata->data->u_efuse_off,
>   		    &pdata->trim_info);
>   
> @@ -226,6 +237,12 @@ static const struct amlogic_thermal_data amlogic_thermal_a1_cpu_param = {
>   	.regmap_config = &amlogic_thermal_regmap_config_g12a,
>   };
>   
> +static const struct amlogic_thermal_data amlogic_thermal_t7_param = {
> +	.use_sm			= true,
> +	.calibration_parameters	= &amlogic_thermal_g12a,
> +	.regmap_config		= &amlogic_thermal_regmap_config_g12a,
> +};
> +
>   static const struct of_device_id of_amlogic_thermal_match[] = {
>   	{
>   		.compatible = "amlogic,g12a-ddr-thermal",
> @@ -239,6 +256,10 @@ static const struct of_device_id of_amlogic_thermal_match[] = {
>   		.compatible = "amlogic,a1-cpu-thermal",
>   		.data = &amlogic_thermal_a1_cpu_param,
>   	},
> +	{
> +		.compatible = "amlogic,t7-thermal",
> +		.data = &amlogic_thermal_t7_param,
> +	},
>   	{ /* sentinel */ }
>   };
>   MODULE_DEVICE_TABLE(of, of_amlogic_thermal_match);
> @@ -271,11 +292,38 @@ static int amlogic_thermal_probe(struct platform_device *pdev)
>   	if (IS_ERR(pdata->clk))
>   		return dev_err_probe(dev, PTR_ERR(pdata->clk), "failed to get clock\n");
>   
> -	pdata->sec_ao_map = syscon_regmap_lookup_by_phandle
> -		(pdev->dev.of_node, "amlogic,ao-secure");
> -	if (IS_ERR(pdata->sec_ao_map)) {
> -		dev_err(dev, "syscon regmap lookup failed.\n");
> -		return PTR_ERR(pdata->sec_ao_map);
> +	if (pdata->data->use_sm) {
> +		struct device_node *sm_np;
> +		struct of_phandle_args ph_args;
> +
> +		ret = of_parse_phandle_with_fixed_args(pdev->dev.of_node,
> +						       "amlogic,secure-monitor",
> +						       1, 0, &ph_args);
> +		if (ret)
> +			return ret;
> +
> +		sm_np = ph_args.np;
> +		if (!sm_np) {
> +			dev_err(dev,
> +				"Failed to parse secure monitor phandle\n");
> +			return -ENODEV;
> +		}
> +
> +		pdata->sm_fw = meson_sm_get(sm_np);
> +		of_node_put(sm_np);
> +		if (!pdata->sm_fw) {
> +			dev_err(dev, "Failed to get secure monitor firmware\n");
> +			return -EPROBE_DEFER;
> +		}
> +
> +		pdata->tsensor_id = ph_args.args[0];
> +	} else {
> +		pdata->sec_ao_map = syscon_regmap_lookup_by_phandle
> +			(pdev->dev.of_node, "amlogic,ao-secure");
> +		if (IS_ERR(pdata->sec_ao_map)) {
> +			dev_err(dev, "syscon regmap lookup failed.\n");
> +			return PTR_ERR(pdata->sec_ao_map);
> +		}
>   	}

I suggest to separate these two routines into functions. That will help 
the readability.

>   	pdata->tzd = devm_thermal_of_zone_register(&pdev->dev

The thermal zone is registered before calling 
amlogic_thermal_initialize(), thus pdata->trim_info is not initialized. 
When a thermal zone is registered the thermal framework reads the 
temperature, so it reads an invalid value because:

devm_thermal_of_zone_register()
  -> thermal_of_zone_register()
    -> thermal_zone_device_register_with_trips()
    -> thermal_zone_device_enable()
       -> __thermal_zone_device_update()
         -> __thermal_zone_get_temp()
           -> amlogic_thermal_get_temp()
              -> amlogic_thermal_code_to_millicelsius()
                  [ Use of uninitialized pdata->trim_info ]

Right ?

IIUC, amlogic_thermal_initialize() can be also split and moved the 
corresponding blocks to the functions to be created in the comment above.


> 



^ permalink raw reply

* Re: [PATCH] crypto: sun8i-ss - avoid hash and rng references
From: Arnd Bergmann @ 2026-04-23 10:26 UTC (permalink / raw)
  To: Herbert Xu
  Cc: Arnd Bergmann, Corentin Labbe, David S . Miller, Chen-Yu Tsai,
	Jernej Skrabec, Samuel Holland, Eric Biggers, Ovidiu Panait,
	linux-crypto, linux-arm-kernel, linux-sunxi, linux-kernel
In-Reply-To: <aenmEQNhhw9bnxEa@gondor.apana.org.au>

On Thu, Apr 23, 2026, at 11:27, Herbert Xu wrote:
> On Thu, Apr 23, 2026 at 11:25:19AM +0200, Arnd Bergmann wrote:
>>
>> Yes, I can rework the patch that way. I had considered this originally
>> but decided this would end up less readable in this case because
>> of the extra indentation level. The drivers already has a lot of
>> #ifdef checks, so adding more of those felt more in line with the
>> style used here.
>
> If we're adding new code I prefer doing it inline instead of as
> an ifdef so that we maximise compiler coverage.

Sure, but I'm not adding new code here, I only reported a regression
from Eric's (otherwise very nice) cleanup and tried to come up
with a better workaround than adding another 'select'.

I've tried to rework one driver to use IS_ENABLED() checks now
instead of the #ifdef, and also replace the for()/switch()
loop with three separate loops for simplicity. See below for
what I ended up with compared with my first patch.

I'm still not entirely happy with that version either, especially
since this is getting beyond a purely mechanical cleanup.
If you think this is better, I can do it for all three drivers,
otherwise I'd just send the oneline change to work around the
third driver link failure the same way that Eric did for the
other two, and let the sunxi maintainters worry about cleaning
it up.

      Arnd

diff --git a/drivers/crypto/allwinner/sun4i-ss/sun4i-ss-core.c b/drivers/crypto/allwinner/sun4i-ss/sun4i-ss-core.c
index 813c4bc6312a..330a1ed7eb03 100644
--- a/drivers/crypto/allwinner/sun4i-ss/sun4i-ss-core.c
+++ b/drivers/crypto/allwinner/sun4i-ss/sun4i-ss-core.c
@@ -31,7 +31,7 @@ static const struct ss_variant ss_a33_variant = {
 	.sha1_in_be = true,
 };
 
-static struct sun4i_ss_alg_template ss_algs[] = {
+static struct sun4i_ss_alg_template ss_ahash_algs[] = {
 {       .type = CRYPTO_ALG_TYPE_AHASH,
 	.mode = SS_OP_MD5,
 	.alg.hash = {
@@ -84,6 +84,9 @@ static struct sun4i_ss_alg_template ss_algs[] = {
 		}
 	}
 },
+};
+
+static struct sun4i_ss_alg_template ss_skcipher_algs[] = {
 {       .type = CRYPTO_ALG_TYPE_SKCIPHER,
 	.alg.crypto = {
 		.setkey         = sun4i_ss_aes_setkey,
@@ -213,7 +216,9 @@ static struct sun4i_ss_alg_template ss_algs[] = {
 		}
 	}
 },
-#ifdef CONFIG_CRYPTO_DEV_SUN4I_SS_PRNG
+};
+
+static struct sun4i_ss_alg_template ss_rng_algs[] = {
 {
 	.type = CRYPTO_ALG_TYPE_RNG,
 	.alg.rng = {
@@ -229,40 +234,46 @@ static struct sun4i_ss_alg_template ss_algs[] = {
 		.seedsize               = SS_SEED_LEN / BITS_PER_BYTE,
 	}
 },
-#endif
 };
 
 static int sun4i_ss_debugfs_show(struct seq_file *seq, void *v)
 {
 	unsigned int i;
 
-	for (i = 0; i < ARRAY_SIZE(ss_algs); i++) {
-		if (!ss_algs[i].ss)
+	for (i = 0; i < ARRAY_SIZE(ss_skcipher_algs); i++) {
+		if (!ss_skcipher_algs[i].ss)
 			continue;
-		switch (ss_algs[i].type) {
-		case CRYPTO_ALG_TYPE_SKCIPHER:
-			seq_printf(seq, "%s %s reqs=%lu opti=%lu fallback=%lu tsize=%lu\n",
-				   ss_algs[i].alg.crypto.base.cra_driver_name,
-				   ss_algs[i].alg.crypto.base.cra_name,
-				   ss_algs[i].stat_req, ss_algs[i].stat_opti, ss_algs[i].stat_fb,
-				   ss_algs[i].stat_bytes);
-			break;
-#ifdef CONFIG_CRYPTO_DEV_SUN4I_SS_PRNG
-		case CRYPTO_ALG_TYPE_RNG:
-			seq_printf(seq, "%s %s reqs=%lu tsize=%lu\n",
-				   ss_algs[i].alg.rng.base.cra_driver_name,
-				   ss_algs[i].alg.rng.base.cra_name,
-				   ss_algs[i].stat_req, ss_algs[i].stat_bytes);
-			break;
-#endif
-		case CRYPTO_ALG_TYPE_AHASH:
-			seq_printf(seq, "%s %s reqs=%lu\n",
-				   ss_algs[i].alg.hash.halg.base.cra_driver_name,
-				   ss_algs[i].alg.hash.halg.base.cra_name,
-				   ss_algs[i].stat_req);
-			break;
-		}
+		seq_printf(seq, "%s %s reqs=%lu opti=%lu fallback=%lu tsize=%lu\n",
+			   ss_skcipher_algs[i].alg.crypto.base.cra_driver_name,
+			   ss_skcipher_algs[i].alg.crypto.base.cra_name,
+			   ss_skcipher_algs[i].stat_req,
+			   ss_skcipher_algs[i].stat_opti,
+			   ss_skcipher_algs[i].stat_fb,
+			   ss_skcipher_algs[i].stat_bytes);
 	}
+
+	for (i = 0; i < ARRAY_SIZE(ss_ahash_algs); i++) {
+		if (!ss_ahash_algs[i].ss)
+			continue;
+
+		seq_printf(seq, "%s %s reqs=%lu tsize=%lu\n",
+			   ss_ahash_algs[i].alg.rng.base.cra_driver_name,
+			   ss_ahash_algs[i].alg.rng.base.cra_name,
+			   ss_ahash_algs[i].stat_req,
+			   ss_ahash_algs[i].stat_bytes);
+	}
+
+	for (i = 0; i < ARRAY_SIZE(ss_rng_algs); i++) {
+		if (!IS_ENABLED(CONFIG_CRYPTO_DEV_SUN4I_SS_PRNG) ||
+		    !ss_rng_algs[i].ss)
+			continue;
+
+		seq_printf(seq, "%s %s reqs=%lu\n",
+			   ss_rng_algs[i].alg.hash.halg.base.cra_driver_name,
+			   ss_rng_algs[i].alg.hash.halg.base.cra_name,
+			   ss_rng_algs[i].stat_req);
+	}
+
 	return 0;
 }
 DEFINE_SHOW_ATTRIBUTE(sun4i_ss_debugfs);
@@ -454,34 +465,36 @@ static int sun4i_ss_probe(struct platform_device *pdev)
 
 	pm_runtime_put_sync(ss->dev);
 
-	for (i = 0; i < ARRAY_SIZE(ss_algs); i++) {
-		ss_algs[i].ss = ss;
-		switch (ss_algs[i].type) {
-		case CRYPTO_ALG_TYPE_SKCIPHER:
-			err = crypto_register_skcipher(&ss_algs[i].alg.crypto);
-			if (err) {
-				dev_err(ss->dev, "Fail to register %s\n",
-					ss_algs[i].alg.crypto.base.cra_name);
-				goto error_alg;
-			}
-			break;
-		case CRYPTO_ALG_TYPE_AHASH:
-			err = crypto_register_ahash(&ss_algs[i].alg.hash);
-			if (err) {
-				dev_err(ss->dev, "Fail to register %s\n",
-					ss_algs[i].alg.hash.halg.base.cra_name);
-				goto error_alg;
-			}
-			break;
-#ifdef CONFIG_CRYPTO_DEV_SUN4I_SS_PRNG
-		case CRYPTO_ALG_TYPE_RNG:
-			err = crypto_register_rng(&ss_algs[i].alg.rng);
-			if (err) {
-				dev_err(ss->dev, "Fail to register %s\n",
-					ss_algs[i].alg.rng.base.cra_name);
-			}
+	for (i = 0; i < ARRAY_SIZE(ss_skcipher_algs); i++) {
+		ss_skcipher_algs[i].ss = ss;
+		err = crypto_register_skcipher(&ss_skcipher_algs[i].alg.crypto);
+		if (err) {
+			dev_err(ss->dev, "Fail to register %s\n",
+				ss_skcipher_algs[i].alg.crypto.base.cra_name);
+			goto error_skcipher_alg;
+		}
+	}
+
+	for (i = 0; i < ARRAY_SIZE(ss_ahash_algs); i++) {
+		ss_ahash_algs[i].ss = ss;
+		err = crypto_register_ahash(&ss_ahash_algs[i].alg.hash);
+		if (err) {
+			dev_err(ss->dev, "Fail to register %s\n",
+				ss_ahash_algs[i].alg.hash.halg.base.cra_name);
+			goto error_ahash_alg;
+		}
+	}
+
+	for (i = 0; i < ARRAY_SIZE(ss_rng_algs); i++) {
+		if (!IS_ENABLED(CONFIG_CRYPTO_DEV_SUN4I_SS_PRNG))
 			break;
-#endif
+
+		ss_rng_algs[i].ss = ss;
+		err = crypto_register_rng(&ss_rng_algs[i].alg.rng);
+		if (err) {
+			dev_err(ss->dev, "Fail to register %s\n",
+				ss_rng_algs[i].alg.rng.base.cra_name);
+			goto error_rng_alg;
 		}
 	}
 
@@ -491,23 +504,20 @@ static int sun4i_ss_probe(struct platform_device *pdev)
 					      &sun4i_ss_debugfs_fops);
 
 	return 0;
-error_alg:
-	i--;
-	for (; i >= 0; i--) {
-		switch (ss_algs[i].type) {
-		case CRYPTO_ALG_TYPE_SKCIPHER:
-			crypto_unregister_skcipher(&ss_algs[i].alg.crypto);
-			break;
-		case CRYPTO_ALG_TYPE_AHASH:
-			crypto_unregister_ahash(&ss_algs[i].alg.hash);
-			break;
-#ifdef CONFIG_CRYPTO_DEV_SUN4I_SS_PRNG
-		case CRYPTO_ALG_TYPE_RNG:
-			crypto_unregister_rng(&ss_algs[i].alg.rng);
-			break;
-#endif
-		}
+
+error_rng_alg:
+	if (IS_ENABLED(CONFIG_CRYPTO_DEV_SUN4I_SS_PRNG)) {
+		for (i--; i >= 0; i--)
+			crypto_unregister_rng(&ss_rng_algs[i].alg.rng);
 	}
+	i = ARRAY_SIZE(ss_ahash_algs);
+error_ahash_alg:
+	for (i--; i >= 0; i--)
+		crypto_unregister_ahash(&ss_ahash_algs[i].alg.hash);
+	i = ARRAY_SIZE(ss_skcipher_algs);
+error_skcipher_alg:
+	for (i--; i >= 0; i--)
+		crypto_unregister_skcipher(&ss_skcipher_algs[i].alg.crypto);
 error_pm:
 	sun4i_ss_pm_exit(ss);
 	return err;
@@ -518,21 +528,14 @@ static void sun4i_ss_remove(struct platform_device *pdev)
 	int i;
 	struct sun4i_ss_ctx *ss = platform_get_drvdata(pdev);
 
-	for (i = 0; i < ARRAY_SIZE(ss_algs); i++) {
-		switch (ss_algs[i].type) {
-		case CRYPTO_ALG_TYPE_SKCIPHER:
-			crypto_unregister_skcipher(&ss_algs[i].alg.crypto);
-			break;
-		case CRYPTO_ALG_TYPE_AHASH:
-			crypto_unregister_ahash(&ss_algs[i].alg.hash);
-			break;
-#ifdef CONFIG_CRYPTO_DEV_SUN4I_SS_PRNG
-		case CRYPTO_ALG_TYPE_RNG:
-			crypto_unregister_rng(&ss_algs[i].alg.rng);
-			break;
-#endif
-		}
+	if (IS_ENABLED(CONFIG_CRYPTO_DEV_SUN4I_SS_PRNG)) {
+		for (i = ARRAY_SIZE(ss_rng_algs); i >= 0; i--)
+			crypto_unregister_rng(&ss_rng_algs[i].alg.rng);
 	}
+	for (i = ARRAY_SIZE(ss_ahash_algs); i >= 0; i--)
+		crypto_unregister_ahash(&ss_ahash_algs[i].alg.hash);
+	for (i = ARRAY_SIZE(ss_skcipher_algs) - 1; i >= 0; i--)
+		crypto_unregister_skcipher(&ss_skcipher_algs[i].alg.crypto);
 
 	sun4i_ss_pm_exit(ss);
 }



^ permalink raw reply related

* Re: [PATCH 2/4] arm64: dts: imx95: switch usb3 controller to flattened model
From: Xu Yang @ 2026-04-23 10:26 UTC (permalink / raw)
  To: Frank Li
  Cc: robh, krzk+dt, conor+dt, s.hauer, kernel, festevam, devicetree,
	imx, linux-arm-kernel, linux-kernel, jun.li
In-Reply-To: <aehGKE8qLXiBKvvB@lizhi-Precision-Tower-5810>

On Tue, Apr 21, 2026 at 11:53:12PM -0400, Frank Li wrote:
> On Tue, Apr 21, 2026 at 06:55:01PM +0800, Xu Yang wrote:
> > Switch to use flattened model for USB3 controller. To enable USB
> > controller with restricted DMA access range to work correctly, add a
> > pseudo simple-bus to constrain the dma address.
> 
> i.mx95 should fix >4G dma space's problem. Does it impact other no-nxp
> boards?

Yes, i.MX95 has fixed >3G address DMA access problem.

It's another issue. HSIO domain only support 36 bit bus access. If not use smmu,
no any issue. If use smmu, it will allocate memory space of 36 bit < iova < 48bit.
HSIO can't handle this case.

> 
> Need do break compatible judgement such as
> 
> i.MX95 is new SoC and still is heave development. The break compatible is
> accepable at development early phase.
> 
> You can rephrase it.

OK.

Thanks,
Xu Yang


^ permalink raw reply

* Re: [RFC PATCH v2 4/4] firmware: arm_ffa: check pkvm initailised when initailise ffa driver
From: Yeoreum Yun @ 2026-04-23 10:29 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: linux-security-module, linux-kernel, linux-integrity,
	linux-arm-kernel, kvmarm, paul, jmorris, serge, zohar,
	roberto.sassu, dmitry.kasatkin, eric.snowberg, jarkko, jgg,
	sudeep.holla, oupton, joey.gouly, suzuki.poulose, yuzenghui,
	catalin.marinas, will, noodles, sebastianene
In-Reply-To: <865x5i13dl.wl-maz@kernel.org>

Hi Marc,

> On Wed, 22 Apr 2026 17:24:49 +0100,
> Yeoreum Yun <yeoreum.yun@arm.com> wrote:
> >
> > When pKVM is enabled, the FF-A driver must be initialized after pKVM.
> > Otherwise, pKVM cannot negotiate the FF-A version or
> > obtain RX/TX buffer information, leading to failures in FF-A calls.
> >
> > During FF-A driver initialization, check whether pKVM has been initialized.
> > If pKVM isn't initailised, register notifier and do initialisation
> > of FF-A driver when pKVM is initialized.
> >
> > Signed-off-by: Yeoreum Yun <yeoreum.yun@arm.com>
> > ---
> >  arch/arm64/include/asm/virt.h     | 11 ++++++++++
> >  arch/arm64/kvm/arm.c              | 21 ++++++++++++++++++
> >  arch/arm64/kvm/pkvm.c             |  2 ++
> >  drivers/firmware/arm_ffa/common.h |  4 ++--
> >  drivers/firmware/arm_ffa/driver.c | 36 ++++++++++++++++++++++++++++++-
> >  drivers/firmware/arm_ffa/smccc.c  |  2 +-
> >  6 files changed, 72 insertions(+), 4 deletions(-)
> >
> > diff --git a/arch/arm64/include/asm/virt.h b/arch/arm64/include/asm/virt.h
> > index b51ab6840f9c..ad038a3b8727 100644
> > --- a/arch/arm64/include/asm/virt.h
> > +++ b/arch/arm64/include/asm/virt.h
> > @@ -68,6 +68,8 @@
> >  #include <asm/sysreg.h>
> >  #include <asm/cpufeature.h>
> >
> > +struct notifier_block;
> > +
> >  /*
> >   * __boot_cpu_mode records what mode CPUs were booted in.
> >   * A correctly-implemented bootloader must start all CPUs in the same mode:
> > @@ -166,6 +168,15 @@ static inline bool is_hyp_nvhe(void)
> >  	return is_hyp_mode_available() && !is_kernel_in_hyp_mode();
> >  }
> >
> > +enum kvm_arm_event {
> > +	PKVM_INITIALISED,
> > +	KVM_ARM_EVENT_MAX,
> > +};
>
> Well, no.
>
> You are adding a whole infrastructure for something that happens
> *once* in the lifetime of the system. What's next? D-Bus?
>
> We already have a dependency mechanism, which I pointed to you last
> time, and that you conveniently ignored. If that's not working for
> you, then consider improving it.
>
> If we had a whole set of in-kernel users depending on some global KVM
> state change, we could look into it. But they are none, and all KVM
> state changes are per-vcpu rather global.
>
> So I'm not entertaining this invasive infrastructure for something so
> limited.

I think I misunderstood your suggestion at first — I wasn’t ignoring it,
and I apologise for that.

I initially considered hooking into /dev/kvm registration,
but there doesn’t seem to be a dedicated class or bus notifier for misc devices:

  - https://lore.kernel.org/all/aecf57rWloQwDh6v@e129823.arm.com/


Also, as I understand it, to make use of device_link,
FF-A would need to represent itself (and pKVM) as proper devices.

However, even if we rely on notifiers for when the pKVM device and
FF-A device are added, the ordering becomes problematic.
When the pKVM device is added and probed, the FF-A consumer would add into
deferred list be device core and  deferred_probe is triggered later
(during late_initcall).

In other words, once FF-A itself is deferred,
the deferred probe queue would look something like:

  (device depending on FF-A) → (some FF-A device) → (FF-A core)

especially since finalise_pkvm() runs at late_initcall_sync.

Unfortunately, deferred_probe_initcall() (also at late_initcall) only
calls driver_deferred_probe_trigger() twice. In this scenario,
the last device in the chain would not be probed immediately but only after a timeout.
As a result, IMA would also fail to find the device in time.

This is why I felt that device_link might not be suitable in this case —
although I may be misunderstanding something.

If this understanding is correct, I’m not sure what alternative we have,
other than adding some kind of notifier support (bus or class) to
the misc driver, or introducing a custom notifier.

Am I missing something?

--
Sincerely,
Yeoreum Yun


^ permalink raw reply

* Re: [REGRESSION] rseq: refactoring in v6.19 broke everyone on arm64 and tcmalloc everywhere
From: Mathias Stearn @ 2026-04-23 10:38 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: Thomas Gleixner, Mathieu Desnoyers, Catalin Marinas, Will Deacon,
	Boqun Feng, Paul E. McKenney, Chris Kennelly, Dmitry Vyukov,
	regressions, linux-kernel, linux-arm-kernel, Ingo Molnar,
	Mark Rutland, Jinjie Ruan, Blake Oler
In-Reply-To: <20260422131338.GI3102924@noisy.programming.kicks-ass.net>

On Wed, Apr 22, 2026 at 3:13 PM Peter Zijlstra <peterz@infradead.org> wrote:
>
> On Wed, Apr 22, 2026 at 02:56:47PM +0200, Peter Zijlstra wrote:
> > On Wed, Apr 22, 2026 at 11:50:26AM +0200, Mathias Stearn wrote:
> >
> > > Additionally, it breaks tcmalloc specifically by failing to overwrite
> > > the cpu_id_start field at points where it was relied on for
> > > correctness.
> >
> > This specific behaviour was documented as being wrong and running with
> > DEBUG_RSEQ would have flagged it.
> >
> > The tcmalloc issue has been contentious for a long time. The tcmalloc
> > folks relied on something that was documented to be wrong. It has been
> > reported to the tcmalloc people many years ago and if you were to run
> > tcmalloc on most any kernel (very much including 6.19) with
> > DEBUG_RSEQ=y, it would have yelled.
> >
> > The tcmalloc people didn't care. There was a proposal for an RSEQ
> > extension for what they need, and they didn't care. All this should be
> > in their bugzilla or whatever.
> >
> > The RSEQ rework improved performance significantly for everyone, and
> > kept all the documented behaviour (+- arm64 bug). Tcmalloc got screwed
> > over because they relied on implementation behaviour that was
> > specifically documented to be broken. And they didn't care. Google was
> > very much aware of this. And hasn't lifted a finger to remedy it.
>
> Also: https://lore.kernel.org/all/874io5andc.ffs@tglx/

(Sorry for the resend to folks who got this already - I got an alert
that it was rejected by the mailinglists because it contained html so
attempting to resend as plain text)

I won't claim that tcmalloc _should_ be abusing cpu_id_start as it is.
I agree that it seems questionable at best. However, I will strongly
disagree with the following comment in that message:

> What it not longer does is updating the
> CPU number for the preemption case on the same CPU
> because that's just a massive waste of CPU cycles.

I don't think it will cost _any_ cycles to implement what I proposed.
And it especially should have no impact from just enabling rseq on a
thread as glibc now does. It should only result in different
instructions being executed when the program actually _uses_ rseq by
setting the rseq_cs variable to a non-null pointer. I will repeat the
proposal with a bit more commentary in case you missed some of the
details that make it free:

Any time a critical section might be aborted (migration, preemption,
signal delivery, and membarrier IPI), the kernel _already_ must check
the rseq_cs field to see if the thread is in a critical section [and
if it is null because the program isn't using rseq critical sections,
no further action is taken]. This is documented as nulling the pointer
after (I assume to make later checks cheaper) [if this changed, then
it *is* a change in _documented behavior_, not just an implementation
detail]. It would be sufficient for tcmalloc's internal usage if every
time the kernel nulled out rseq_cs, it also wrote the cpu id to
cpu_id_start. [This is one additional store to a cacheline you are
already writing to so it should be ~free on modern OoO CPUs and cheap
on others. There might be a small cost to loading the current cpu, but
since nothing depends on that other than the store, I still expect it
to be ~free]

To make this more concrete, I am proposing adding

unsafe_put_user((u32)task_cpu(t), &t->rseq.usrptr->cpu_id_start, efault);

after each place where you currently do

unsafe_put_user(0ULL, &t->rseq.usrptr->rseq_cs, efault);

in rseq_update_user_cs. Is that something that you would expect to
cause a performance issue?

Again, I'm not claiming that it is "good" that this needs to be done.
But it does seem like a small price to pay to keep existing binaries
working on new kernels. Quoting the first paragraph of
https://docs.kernel.org/admin-guide/reporting-regressions.html:

> “We don’t cause regressions” is the first rule of Linux kernel development; Linux founder and lead developer Linus Torvalds established it himself and ensures it’s obeyed.

I don't see anything on that page that says it doesn't count as a
regression if the userspace program "relied on implementation
behaviour that was specifically documented to be broken".


^ permalink raw reply

* Re: [REGRESSION] rseq: refactoring in v6.19 broke everyone on arm64 and tcmalloc everywhere
From: Thomas Gleixner @ 2026-04-23 10:39 UTC (permalink / raw)
  To: Dmitry Vyukov, Jinjie Ruan, linux-man
  Cc: Mark Rutland, Mathias Stearn, Mathieu Desnoyers, Catalin Marinas,
	Will Deacon, Boqun Feng, Paul E. McKenney, Chris Kennelly,
	regressions, linux-kernel, linux-arm-kernel, Peter Zijlstra,
	Ingo Molnar, Blake Oler
In-Reply-To: <CACT4Y+bxnQyHGdVNE1BYTx+Z2-cscLb38HYS9jBM5gPAz8=4bw@mail.gmail.com>

On Thu, Apr 23 2026 at 07:53, Dmitry Vyukov wrote:
> On Thu, 23 Apr 2026 at 03:48, Jinjie Ruan <ruanjinjie@huawei.com> wrote:
>
> This part of the rseq man page needs to be fixed as well I think. The
> kernel no longer reliably provides clearing of rseq_cs on preemption,
> right?
>
> https://git.kernel.org/pub/scm/libs/librseq/librseq.git/tree/doc/man/rseq.2#n241
>
> "and set to NULL by the kernel when it restarts an assembly
> instruction sequence block,
> as well as when the kernel detects that it is preempting or delivering
> a signal outside of the range targeted by the rseq_cs."

The kernel clears rseq_cs reliably when user space was interrupted and:

    the task was preempted
or
    the return from interrupt delivers a signal

If the task invoked a syscall then there is absolutely no reason to do
either of this because syscalls from within a critical section are a
bug and catched when enabling rseq debugging.

The original code did this along with unconditionally updating CPU/MMCID
which resulted in ~15% performance regression on a syscall heavy
database benchmark once glibc started to register rseq.

Thanks,

        tglx








^ permalink raw reply

* Re: [PATCH net v2 0/2] net: airoha: Fix NULL pointer derefrences in airoha_qdma_cleanup()
From: patchwork-bot+netdevbpf @ 2026-04-23 10:50 UTC (permalink / raw)
  To: Lorenzo Bianconi
  Cc: andrew+netdev, davem, edumazet, kuba, pabeni, horms,
	linux-arm-kernel, linux-mediatek, netdev
In-Reply-To: <20260420-airoha_qdma_init_rx_queue-fix-v2-0-d99347e5c18d@kernel.org>

Hello:

This series was applied to netdev/net.git (main)
by Paolo Abeni <pabeni@redhat.com>:

On Mon, 20 Apr 2026 10:07:46 +0200 you wrote:
> Fix two possible NULL pointer derefrences in airoha_qdma_cleanup routine
> if airoha_qdma_init() fails.
> 
> ---
> Changes in v2:
> - Move page_pool allocation after desc list allocation in
>   airoha_qdma_init_rx_queue()
> - Move netif_napi_add_tx() after irq desc queue allocation in
>   airoha_qdma_tx_irq_init()
> - Link to v1: https://lore.kernel.org/r/20260417-airoha_qdma_init_rx_queue-fix-v1-0-db9fa5e468e5@kernel.org
> 
> [...]

Here is the summary with links:
  - [net,v2,1/2] net: airoha: Move ndesc initialization at end of airoha_qdma_init_rx_queue()
    https://git.kernel.org/netdev/net/c/379050947a18
  - [net,v2,2/2] net: airoha: Add size check for TX NAPIs in airoha_qdma_cleanup()
    https://git.kernel.org/netdev/net/c/4b91cb65789b

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




^ permalink raw reply

* Re: [REGRESSION] rseq: refactoring in v6.19 broke everyone on arm64 and tcmalloc everywhere
From: Mathias Stearn @ 2026-04-23 10:51 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: Dmitry Vyukov, Jinjie Ruan, linux-man, Mark Rutland,
	Mathieu Desnoyers, Catalin Marinas, Will Deacon, Boqun Feng,
	Paul E. McKenney, Chris Kennelly, regressions, linux-kernel,
	linux-arm-kernel, Peter Zijlstra, Ingo Molnar, Blake Oler
In-Reply-To: <87ik9i0xlj.ffs@tglx>

On Thu, Apr 23, 2026 at 12:39 PM Thomas Gleixner <tglx@linutronix.de> wrote:
> The kernel clears rseq_cs reliably when user space was interrupted and:
>
>     the task was preempted
> or
>     the return from interrupt delivers a signal
>
> If the task invoked a syscall then there is absolutely no reason to do
> either of this because syscalls from within a critical section are a
> bug and catched when enabling rseq debugging.
>
> The original code did this along with unconditionally updating CPU/MMCID
> which resulted in ~15% performance regression on a syscall heavy
> database benchmark once glibc started to register rseq.

Just to be clear TCMalloc does not need either rseq_cs to be cleared
or cpu_id_start to be written to on syscalls because it doesn't do
syscalls from critical sections. It will actually benefit (slightly)
from not updating cpu_id_start on syscalls.

It is specifically in the cases where an rseq would need to be aborted
(preemption, signals, migration, and membarrier IPI with the rseq
flag) that TCMalloc relies on cpu_id_start being written. It does rely
on that write even when not inside the critical section, because it
effectively uses that to detect if there were any would-cause-abort
events in between two critical sections. But since it leaves the
rseq_cs pointer non-null between critical sections, so you dont need
to add _any_ overhead for programs that never make use of rseq after
registration, or add any overhead to syscalls even for those who do.


^ permalink raw reply

* Re: [PATCH v2 08/20] drm/plane: Add new atomic_create_state callback
From: Maxime Ripard @ 2026-04-23 10:54 UTC (permalink / raw)
  To: Thomas Zimmermann
  Cc: Maarten Lankhorst, David Airlie, Simona Vetter, Jonathan Corbet,
	Shuah Khan, Dmitry Baryshkov, Jyri Sarha, Tomi Valkeinen,
	Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
	Jonas Karlman, Jernej Skrabec, Simon Ser, Harry Wentland,
	Melissa Wen, Sebastian Wick, Alex Hung, Jani Nikula, Rodrigo Vivi,
	Joonas Lahtinen, Tvrtko Ursulin, Chen-Yu Tsai, Samuel Holland,
	Dave Stevenson, Maíra Canal, Raspberry Pi Kernel Maintenance,
	dri-devel, linux-doc, linux-kernel, Daniel Stone, intel-gfx,
	intel-xe, linux-arm-kernel, linux-sunxi
In-Reply-To: <55c24dca-e354-49d1-8eaa-edf66f679428@suse.de>

[-- Attachment #1: Type: text/plain, Size: 3377 bytes --]

On Tue, Apr 21, 2026 at 03:22:22PM +0200, Thomas Zimmermann wrote:
> Hi
> 
> Am 20.03.26 um 17:27 schrieb Maxime Ripard:
> > Commit 47b5ac7daa46 ("drm/atomic: Add new atomic_create_state callback
> > to drm_private_obj") introduced a new pattern for allocating drm object
> > states.
> > 
> > Instead of relying on the reset() callback, it created a new
> > atomic_create_state hook. This is helpful because reset is a bit
> > overloaded: it's used to create the initial software state, reset it,
> > but also reset the hardware.
> > 
> > It can also be used either at probe time, to create the initial state
> > and possibly reset the hardware to an expected default, but also during
> > suspend/resume.
> > 
> > Both these cases come with different expectations too: during the
> > initialization, we want to initialize all states, but during
> > suspend/resume, drm_private_states for example are expected to be kept
> > around.
> > 
> > And reset() isn't fallible, which makes it harder to handle
> > initialization errors properly.
> > 
> > And this is only really relevant for some drivers, since all the helpers
> > for reset only create a new state, and don't touch the hardware at all.
> > 
> > It was thus decided to create a new hook that would allocate and
> > initialize a pristine state without any side effect:
> > atomic_create_state to untangle a bit some of it, and to separate the
> > initialization with the actual reset one might need during a
> > suspend/resume.
> > 
> > Let's continue the transition to the new pattern with planes.
> > 
> > Signed-off-by: Maxime Ripard <mripard@kernel.org>
> > ---
> >   drivers/gpu/drm/drm_atomic_state_helper.c | 44 +++++++++++++++++++++++++++++++
> >   drivers/gpu/drm/drm_mode_config.c         | 21 ++++++++++++++-
> >   include/drm/drm_atomic_state_helper.h     |  4 +++
> >   include/drm/drm_plane.h                   | 13 +++++++++
> >   4 files changed, 81 insertions(+), 1 deletion(-)
> > 
> > diff --git a/drivers/gpu/drm/drm_atomic_state_helper.c b/drivers/gpu/drm/drm_atomic_state_helper.c
> > index 2548d6da13675f63304dc92423c5d225de0447a8..f4ce9d3573cbecf216904db54335e0cf84a01c39 100644
> > --- a/drivers/gpu/drm/drm_atomic_state_helper.c
> > +++ b/drivers/gpu/drm/drm_atomic_state_helper.c
> > @@ -319,10 +319,29 @@ void __drm_atomic_helper_plane_reset(struct drm_plane *plane,
> >   	plane->state = plane_state;
> >   }
> >   EXPORT_SYMBOL(__drm_atomic_helper_plane_reset);
> > +/**
> > + * __drm_atomic_helper_plane_create_state - initializes plane state
> > + * @plane: plane object
> > + * @state: new state to initialize
> > + *
> > + * Initializes the newly allocated @state, usually required when
> > + * initializing the drivers.
> > + *
> > + * @state is assumed to be zeroed.
> > + *
> > + * This is useful for drivers that subclass @drm_plane_state.
> > + */
> > +void __drm_atomic_helper_plane_create_state(struct drm_plane *plane,
> > +					    struct drm_plane_state *state)
> > +{
> > +	__drm_atomic_helper_plane_state_init(state, plane);
> > +}
> > +EXPORT_SYMBOL(__drm_atomic_helper_plane_create_state);
> 
> Will this function have another purpuse?  Could we just call
> _plane_state_init() directly from anywhere?

Yeah, I guess that makes sense. I'll drop that patch and the similar ones.

Thanks!
Maxime

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 273 bytes --]

^ permalink raw reply

* Re: [RFC PATCH 4/4] firmware: arm_ffa: check pkvm initailised when initailise ffa driver
From: Yeoreum Yun @ 2026-04-23 10:56 UTC (permalink / raw)
  To: Will Deacon
  Cc: Sudeep Holla, Marc Zyngier, linux-security-module, linux-kernel,
	linux-integrity, linux-arm-kernel, kvmarm, paul, jmorris, zohar,
	roberto.sassu, dmitry.kasatkin, eric.snowberg, jarkko, oupton,
	joey.gouly, suzuki.poulose, yuzenghui, catalin.marinas,
	sebastianene
In-Reply-To: <aene4KFD5kbSbFRm@willie-the-truck>

Hi Will,

> On Wed, Apr 22, 2026 at 02:32:23PM +0100, Yeoreum Yun wrote:
> > Hi All,
> >
> > > > On Tue, Apr 21, 2026 at 07:57:43AM +0100, Yeoreum Yun wrote:
> > > >
> > > > [...]
> > > >
> > > > >
> > > > > Also, the FF-A initialization is not driven by a device probe, but rather
> > > > > happens as part of the bus registration itself,
> > > > > so it does not fit well with a device_link or probe deferral based approach.
> > > > >
> > > > > Instead, perhaps we could go with the idea I mentioned previously:
> > > > > either introduce a notifier, or create a pseudo ffa_device
> > > > > once pKVM initialization has completed, and
> > > > > then let the ffa driver perform the additional initialization from there.
> > > > >
> > > > > Am I missing something?
> > > > >
> > > >
> > > > In order to handle/cleanup some ugliness in interrupt management in the
> > > > FF-A driver, we may introduce DT node eventually. But it will take sometime.
> > >
> > > Unfortunately, I think this DT node wouldn't be helpful to solve
> > > this situation for dependency with the kvm misc device...
> > >
> > > IMHO, current situation, the notifier seems to good option. unless
> > > we make the initcall to recongise this dependency.
> > >
> >
> > I think the best approach for now is to introduce a notifier to handle this situation.
> > If there are no further suggestions, I’ll send a v2 based on:
> >   - https://lore.kernel.org/all/aeS4rAeVQ0yJIPYw@e129823.arm.com/
>
> I can't say that I'm a huge fan of that :/
>
> The notifier will literally fire once, for a single listener. That's
> called a function call.


I revisited Marc’s suggestion about using device links
(https://lore.kernel.org/all/87pl3vb5bm.wl-maz@kernel.org/)

but unless I’m misunderstanding something, I don’t think it would be a viable solution:
 - https://lore.kernel.org/all/aen0j3qM2k06OdXC@e129823.arm.com/#t

Also, calling functions defined by FF-A from KVM would introduce
an unnecessary module dependency between the KVM and FF-A drivers.

I’ve been trying to find an alternative approach,
but I’m not confident about what would be appropriate.

If you don’t mind, could you share your thoughts on this?

Thanks!

--
Sincerely,
Yeoreum Yun


^ permalink raw reply

* Re: [PATCH] crypto: sun8i-ss - avoid hash and rng references
From: Herbert Xu @ 2026-04-23 11:09 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Arnd Bergmann, Corentin Labbe, David S . Miller, Chen-Yu Tsai,
	Jernej Skrabec, Samuel Holland, Eric Biggers, Ovidiu Panait,
	linux-crypto, linux-arm-kernel, linux-sunxi, linux-kernel
In-Reply-To: <3948e39f-dd20-44e2-b264-dc2a0a88f5b5@app.fastmail.com>

On Thu, Apr 23, 2026 at 12:26:23PM +0200, Arnd Bergmann wrote:
>
> Sure, but I'm not adding new code here, I only reported a regression
> from Eric's (otherwise very nice) cleanup and tried to come up
> with a better workaround than adding another 'select'.
> 
> I've tried to rework one driver to use IS_ENABLED() checks now
> instead of the #ifdef, and also replace the for()/switch()
> loop with three separate loops for simplicity. See below for
> what I ended up with compared with my first patch.
> 
> I'm still not entirely happy with that version either, especially
> since this is getting beyond a purely mechanical cleanup.
> If you think this is better, I can do it for all three drivers,
> otherwise I'd just send the oneline change to work around the
> third driver link failure the same way that Eric did for the
> other two, and let the sunxi maintainters worry about cleaning
> it up.

Sorry, I made my comment based on your original patch only which
simply added ifdefs.

Now that I see the wider context in the driver, I'm happy to take
your original patch as is.

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


^ permalink raw reply

* Re: [RFC PATCH v2 1/4] security: ima: call ima_init() again at late_initcall_sync for defered TPM
From: Mimi Zohar @ 2026-04-23 11:01 UTC (permalink / raw)
  To: Yeoreum Yun
  Cc: linux-security-module, linux-kernel, linux-integrity,
	linux-arm-kernel, kvmarm, paul, jmorris, serge, roberto.sassu,
	dmitry.kasatkin, eric.snowberg, jarkko, jgg, sudeep.holla, maz,
	oupton, joey.gouly, suzuki.poulose, yuzenghui, catalin.marinas,
	will, noodles, sebastianene
In-Reply-To: <aem0SSQuE1e3pGOS@e129823.arm.com>

On Thu, 2026-04-23 at 06:55 +0100, Yeoreum Yun wrote:
> > On Wed, 2026-04-22 at 20:41 +0100, Yeoreum Yun wrote:
> > > > Hi Mimi,
> > > > 
> > > > > On Wed, 2026-04-22 at 17:24 +0100, Yeoreum Yun wrote:
> > > > > > To generate the boot_aggregate log in the IMA subsystem with TPM PCR values,
> > > > > > the TPM driver must be built as built-in and
> > > > > > must be probed before the IMA subsystem is initialized.
> > > > > > 
> > > > > > However, when the TPM device operates over the FF-A protocol using
> > > > > > the CRB interface, probing fails and returns -EPROBE_DEFER if
> > > > > > the tpm_crb_ffa device — an FF-A device that provides the communication
> > > > > > interface to the tpm_crb driver — has not yet been probed.
> > > > > > 
> > > > > > To ensure the TPM device operating over the FF-A protocol with
> > > > > > the CRB interface is probed before IMA initialization,
> > > > > > the following conditions must be met:
> > > > > > 
> > > > > >    1. The corresponding ffa_device must be registered,
> > > > > >       which is done via ffa_init().
> > > > > > 
> > > > > >    2. The tpm_crb_driver must successfully probe this device via
> > > > > >       tpm_crb_ffa_init().
> > > > > > 
> > > > > >    3. The tpm_crb driver using CRB over FF-A can then
> > > > > >       be probed successfully. (See crb_acpi_add() and
> > > > > >       tpm_crb_ffa_init() for reference.)
> > > > > > 
> > > > > > Unfortunately, ffa_init(), tpm_crb_ffa_init(), and crb_acpi_driver_init() are
> > > > > > all registered with device_initcall, which means crb_acpi_driver_init() may
> > > > > > be invoked before ffa_init() and tpm_crb_ffa_init() are completed.
> > > > > > 
> > > > > > When this occurs, probing the TPM device is deferred.
> > > > > > However, the deferred probe can happen after the IMA subsystem
> > > > > > has already been initialized, since IMA initialization is performed
> > > > > > during late_initcall, and deferred_probe_initcall() is performed
> > > > > > at the same level.
> > > > > > 
> > > > > > To resolve this, call ima_init() again at late_inicall_sync level
> > > > > > so that let IMA not miss TPM PCR value when generating boot_aggregate
> > > > > > log though TPM device presents in the system.
> > > > > > 
> > > > > > Signed-off-by: Yeoreum Yun <yeoreum.yun@arm.com>
> > > > > 
> > > > > A lot of change for just detecting whether ima_init() is being called on
> > > > > late_initcall or late_initcall_sync(), without any explanation for all the other
> > > > > changes (e.g. ima_init_core).
> > > > > 
> > > > > Please just limit the change to just calling ima_init() twice.
> > > > 
> > > > My concern is that ima_update_policy_flags() will be called
> > > > when ima_init() is deferred -- not initialised anything.
> > > > though functionally, it might be okay however,
> > > > I think ima_update_policy_flags() and notifier should work after ima_init()
> > > > works logically.
> > > > 
> > > > This change I think not much quite a lot. just wrapper ima_init() with
> > > > ima_init_core() with some error handling.
> > > > 
> > > > Am I missing something?
> > > 
> > > Also, if we handle in ima_init() only, but it failed with other reason,
> > > we shouldn't call again ima_init() in the late_initcall_sync.
> > > 
> > > To handle this, It wouldn't do in the ima_init() but we need to handle
> > > it by caller of ima_init().
> > 
> > Only tpm_default_chip() is being called to set the ima_tpm_chip.  On failure,
> > instead of going into TPM-bypass mode, return immediately.  There are no calls
> > to anything else.  Just call ima_init() a second time.
> 
> I’m not fully convinced this is sufficient.
> 
> What I meant is the case where ima_init() fails due to other
> initialisation steps, not only tpm_default_chip() (e.g. ima_fs_init()).

The purpose of THIS patch is to add late_initcall_sync, when the TPM is not
available at late_initcall.  This would be classified as a bug fix and would be
backported.  No other changes should be included in this patch.

> 
> If it fails at the late_initcall stage for such reasons, then we
> should not call ima_init() again at late_initcall_sync.
> 
> For this reason, instead of adding a static variable inside
> ima_init(), I think it would be better to manage the state in the
> caller and introduce something like an ima_initialised flag. Also, if
> initialisation fails for other reasons, the notifier block should be
> unregistered.

Defining a global file static variable, in lieu of a local static variable, is
fine. Defining two functions, one for late_initcall and another for
late_initcall_sync, that do nothing other than call ima_init() is also fine.
Please keep this patch as simple as possible.

> 
> I’d also like to ask again whether it is fine to call
> ima_update_policy_flags() and keep the notifier registered in the
> deferred TPM case. While this may be functionally acceptable, it seems
> logically questionable to do so when ima_init() has not completed.

Other than extending the TPM, IMA should behave exactly the same whether there
is a TPM or goes into TPM-bypass mode.

> 
> There is also a possibility that a deferred case ultimately fails (e.g.
> deferred at late_initcall, but then failing at late_initcall_sync
> for another reason, even while entering TPM bypass mode). In that case,
> it seems more appropriate to handle this state in the caller of
> ima_init(), rather than inside ima_init() itself.

If the TPM isn't found at late_initcall_sync(), then IMA should go into TPM-
bypass mode.  Please don't make any other changes to the existing IMA behavior
and hide it here behind the late_initcall_sync change.

> 
> Am I still missing something?

When your original patch moved the initialization from late_initcall to
late_initcall_sync, you didn't question anything.  There's absolutely no
difference between that and calling ima_init twice, as long as on late_initcall
ima_init() returns immediately if the TPM chip isn't defined.

Any other changes are superfluous.  Keep the patch simple!

Mimi


^ permalink raw reply


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