* Re: [Question mpam mpam/snapshot+extras/v6.18-rc1] Question with Configuring iommu_group in 'task'
From: Zeng Heng @ 2026-04-16 3:02 UTC (permalink / raw)
To: Ben Horgan, James Morse
Cc: Qinxin Xia, amitsinght, baisheng.gao, baolin.wang, carl,
dave.martin, david, dfustini, fenghuay, gshan, jonathan.cameron,
kobak, lcherian, linux-arm-kernel, linux-kernel, peternewman,
punit.agrawal, quic_jiles, reinette.chatre, rohit.mathew, scott,
sdonthineni, xhao, Linuxarm
In-Reply-To: <f800f0d5-7a00-4dad-95fe-a2aac2ece5ef@arm.com>
On 2026/4/15 20:42, Ben Horgan wrote:
> Hi Zeng,
>
> On 4/15/26 02:27, Zeng Heng wrote:
>> Hi Ben,
>>
>> On 2026/4/13 23:02, Ben Horgan wrote:
>>> Hi Qinxin,
>>>
>>> On 4/3/26 03:44, Qinxin Xia wrote:
>>>>
>>>>
>>>> On 2026/3/27 18:47:49, Ben Horgan <ben.horgan@arm.com> wrote:
>>>>> Hi Qinxin,
>>>>>
>>>>> On 3/27/26 10:21, Qinxin Xia wrote:
>>>>>>
>>>>>> Hello everyone!
>>>>>>
>>>>>> In earlier versions, mpam supports the configuration of iommu_groups.
>>>>>>
>>>>>> 823 static ssize_t rdtgroup_tasks_write(struct kernfs_open_file *of,
>>>>>> 824 char *buf, size_t nbytes,
>>>>>> loff_t off)
>>>>>> 825 {
>>>>>> 826 struct rdtgroup *rdtgrp;
>>>>>> 827 int iommu_group_id;
>>>>>> 828 bool is_iommu;
>>>>>> 829 char *pid_str;
>>>>>> 830 int ret = 0;
>>>>>> 831 pid_t pid;
>>>>>> 832
>>>>>> 833 rdtgrp = rdtgroup_kn_lock_live(of->kn);
>>>>>> 834 if (!rdtgrp) {
>>>>>> 835 rdtgroup_kn_unlock(of->kn);
>>>>>> 836 return -ENOENT;
>>>>>> 837 }
>>>>>> 838 rdt_last_cmd_clear();
>>>>>> 839
>>>>>> 840 if (rdtgrp->mode == RDT_MODE_PSEUDO_LOCKED ||
>>>>>> 841 rdtgrp->mode == RDT_MODE_PSEUDO_LOCKSETUP) {
>>>>>> 842 ret = -EINVAL;
>>>>>> 843 rdt_last_cmd_puts("Pseudo-locking in progress\n");
>>>>>> 844 goto unlock;
>>>>>> 845 }
>>>>>> 846
>>>>>> 847 while (buf && buf[0] != '\0' && buf[0] != '\n') {
>>>>>> 848 pid_str = strim(strsep(&buf, ","));
>>>>>> 849
>>>>>> 850 is_iommu = string_is_iommu_group(pid_str, &iommu_group_id);
>>>>>>
>>>>>> What puzzles me is why we would put it under 'task'—this seems a little
>>>>>> strange to users.It seems they are not related.Why don't we add a new
>>>>>> interface like 'iommu'?
>>>>>
>>>>> I think it is likely that this interface would change if upstream support is added.
>>>>>
>>>>
>>>> I have done some work in this direction before, and I will release an
>>>> RFC later for further discussion.:-)
>>>
>>> Looking forward to seeing it.
>>>
>>> Ben
>>>
>>
>> Following the current SMMU approach, I've submitted several bugfix
>> patches for the MPAM driver, but haven't received any review feedback
>> yet.
>>
>> To avoid these being overlooked, I'd like to kindly remind to take a
>> look:
>> v2: https://lore.kernel.org/all/20260414032610.1523958-1-zengheng4@huawei.com/
>> v1: https://lore.kernel.org/all/20251107063300.1580046-1-zengheng4@huawei.com/
>>
>> Additionally, I'd like to check on the status of this branch — is it
>> still actively maintained? It would be helpful to understand the future
>> plans for MPAM development.
>
> The MPAM snapshot and extras branches are no longer maintained. Work on these has stopped so that we can focus on
> upstream. Apologies for not making this clear earlier.
>
Ack. If the extras branch scheme mentioned above is rebased onto
upstream, these bugfix patches would remain applicable and worth
reviewing.
Best regards,
Zeng Heng
^ permalink raw reply
* [PATCH v3 0/6] soc: mediatek: Add devapc support
From: Xiaoshun Xu @ 2026-04-16 3:12 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Matthias Brugger,
AngeloGioacchino Del Regno, Xiaoshun Xu
Cc: devicetree, linux-kernel, linux-arm-kernel, linux-mediatek,
Sirius Wang, Vince-wl Liu, Project_Global_Chrome_Upstream_Group,
Xiaoshun Xu
From: Xiaoshun Xu <xiaoshun.xu@mediatek.corp-partner.google.com>
Based on tag: next-20260415, linux-next/master
This series of patches add support for Mediatek devapc of MT8189 and
MT8196 soc.
Xiaoshun Xu (6):
soc: mediatek: mtk-devapc: refine devapc interrupt handler
soc: mediatek: mtk-devapc: refine DEVAPC clock control
soc: mediatek: mtk-devapc: Add support for MT8189 DEVAPC
dt-bindings: soc: mediatek: devapc: Add bindings for MT8189
soc: mediatek: mtk-devapc: Add support for MT8196 DEVAPC
dt-bindings: soc: mediatek: devapc: Add bindings for MT8196
Changes in v3:
- Add support for MT8196 devapc
- Updated yaml for dt-bindings
Changes in v2:
- Updated cover letter subject
- Updated yaml for dt-bindings
- Add support for MT8189 devapc
- Refine devapc clock control flow
- Refine devapc interrupt handler
Changes in v1:
- Add support for MT8189 devapc
- Updated yaml for MT8189
.../bindings/soc/mediatek/devapc.yaml | 11 +-
drivers/soc/mediatek/mtk-devapc.c | 197 ++++++++++++++----
2 files changed, 168 insertions(+), 40 deletions(-)
--
2.45.2
^ permalink raw reply
* [PATCH v3 2/6] soc: mediatek: mtk-devapc: refine DEVAPC clock control
From: Xiaoshun Xu @ 2026-04-16 3:12 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Matthias Brugger,
AngeloGioacchino Del Regno, Xiaoshun Xu
Cc: devicetree, linux-kernel, linux-arm-kernel, linux-mediatek,
Sirius Wang, Vince-wl Liu, Project_Global_Chrome_Upstream_Group
In-Reply-To: <20260416031231.2932493-1-xiaoshun.xu@mediatek.com>
Because the new DEVAPC design, DEVAPC clock is controlled by
HW power domains, the control flow of DEVAPC clock is not
necessary, but to maintain compatibility with legacy ICs,
keep this part of code.
Signed-off-by: Xiaoshun Xu <xiaoshun.xu@mediatek.com>
---
drivers/soc/mediatek/mtk-devapc.c | 25 ++++++++++++++++++++-----
1 file changed, 20 insertions(+), 5 deletions(-)
diff --git a/drivers/soc/mediatek/mtk-devapc.c b/drivers/soc/mediatek/mtk-devapc.c
index c9e1401315ad..f54e310791e5 100644
--- a/drivers/soc/mediatek/mtk-devapc.c
+++ b/drivers/soc/mediatek/mtk-devapc.c
@@ -284,16 +284,28 @@ static int mtk_devapc_probe(struct platform_device *pdev)
goto err;
}
- ctx->infra_clk = devm_clk_get_enabled(&pdev->dev, "devapc-infra-clock");
+ /*
+ * The new design of DAPC clock is controlled by HW power domains,
+ * making it unnecessary to provide the clock control driver.
+ */
+ ctx->infra_clk = devm_clk_get_optional(&pdev->dev, "devapc-infra-clock");
if (IS_ERR(ctx->infra_clk)) {
- ret = -EINVAL;
- goto err;
+ dev_err(ctx->dev, "Cannot get devapc clock from CCF\n");
+ ctx->infra_clk = NULL;
+ } else {
+ if (clk_prepare_enable(ctx->infra_clk)) {
+ ret = -EINVAL;
+ goto err;
+ }
}
ret = devm_request_irq(&pdev->dev, devapc_irq, devapc_violation_irq,
- IRQF_TRIGGER_NONE, "devapc", ctx);
- if (ret)
+ IRQF_TRIGGER_NONE | IRQF_SHARED, "devapc", ctx);
+ if (ret) {
+ if (ctx->infra_clk)
+ clk_disable_unprepare(ctx->infra_clk);
goto err;
+ }
platform_set_drvdata(pdev, ctx);
@@ -311,6 +323,9 @@ static void mtk_devapc_remove(struct platform_device *pdev)
struct mtk_devapc_context *ctx = platform_get_drvdata(pdev);
stop_devapc(ctx);
+
+ clk_disable_unprepare(ctx->infra_clk);
+
iounmap(ctx->infra_base);
}
--
2.45.2
^ permalink raw reply related
* [PATCH v3 1/6] soc: mediatek: mtk-devapc: refine devapc interrupt handler
From: Xiaoshun Xu @ 2026-04-16 3:12 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Matthias Brugger,
AngeloGioacchino Del Regno, Xiaoshun Xu
Cc: devicetree, linux-kernel, linux-arm-kernel, linux-mediatek,
Sirius Wang, Vince-wl Liu, Project_Global_Chrome_Upstream_Group
In-Reply-To: <20260416031231.2932493-1-xiaoshun.xu@mediatek.com>
Because the violation IRQ uses a while loop, it might cause the
system to remain in the interrupt handler indefinitely. We are
currently optimizing this part of the process to handle only 20
violations for debug violation issues, and then exit the loop
Signed-off-by: Xiaoshun Xu <xiaoshun.xu@mediatek.com>
---
drivers/soc/mediatek/mtk-devapc.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/drivers/soc/mediatek/mtk-devapc.c b/drivers/soc/mediatek/mtk-devapc.c
index f54c966138b5..c9e1401315ad 100644
--- a/drivers/soc/mediatek/mtk-devapc.c
+++ b/drivers/soc/mediatek/mtk-devapc.c
@@ -12,6 +12,7 @@
#include <linux/of_irq.h>
#include <linux/of_address.h>
+#define MAX_VIO_NUM 20
#define VIO_MOD_TO_REG_IND(m) ((m) / 32)
#define VIO_MOD_TO_REG_OFF(m) ((m) % 32)
@@ -188,13 +189,18 @@ static void devapc_extract_vio_dbg(struct mtk_devapc_context *ctx)
*/
static irqreturn_t devapc_violation_irq(int irq_number, void *data)
{
+ u32 vio_num = 0;
struct mtk_devapc_context *ctx = data;
- while (devapc_sync_vio_dbg(ctx))
+ mask_module_irq(ctx, true);
+
+ for (vio_num = 0; (vio_num < MAX_VIO_NUM) && (devapc_sync_vio_dbg(ctx)); ++vio_num)
devapc_extract_vio_dbg(ctx);
clear_vio_status(ctx);
+ mask_module_irq(ctx, false);
+
return IRQ_HANDLED;
}
--
2.45.2
^ permalink raw reply related
* [PATCH v3 3/6] soc: mediatek: mtk-devapc: Add support for MT8189 DEVAPC
From: Xiaoshun Xu @ 2026-04-16 3:12 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Matthias Brugger,
AngeloGioacchino Del Regno, Xiaoshun Xu
Cc: devicetree, linux-kernel, linux-arm-kernel, linux-mediatek,
Sirius Wang, Vince-wl Liu, Project_Global_Chrome_Upstream_Group
In-Reply-To: <20260416031231.2932493-1-xiaoshun.xu@mediatek.com>
Add support for MT8189 DEVAPC, DEVAPC debug registers have new version,
so refine the structure of devapc_regs_ofs_xxxx to devapc_regs_ofs_verX,
and rename the infra_base to base in mtk_devapc_context because devapc
not only access the infra_base to dump debug information when violation
happens
Signed-off-by: Xiaoshun Xu <xiaoshun.xu@mediatek.com>
---
drivers/soc/mediatek/mtk-devapc.c | 171 +++++++++++++++++++++++-------
1 file changed, 134 insertions(+), 37 deletions(-)
diff --git a/drivers/soc/mediatek/mtk-devapc.c b/drivers/soc/mediatek/mtk-devapc.c
index f54e310791e5..824b49613c5a 100644
--- a/drivers/soc/mediatek/mtk-devapc.c
+++ b/drivers/soc/mediatek/mtk-devapc.c
@@ -27,9 +27,19 @@ struct mtk_devapc_vio_dbgs {
u32 addr_h:4;
u32 resv:4;
} dbg0_bits;
+
+ struct {
+ u32 dmnid:6;
+ u32 vio_w:1;
+ u32 vio_r:1;
+ u32 addr_h:4;
+ u32 resv:20;
+ } dbg0_bits_ver2;
};
u32 vio_dbg1;
+ u32 vio_dbg2;
+ u32 vio_dbg3;
};
struct mtk_devapc_regs_ofs {
@@ -38,6 +48,8 @@ struct mtk_devapc_regs_ofs {
u32 vio_sta_offset;
u32 vio_dbg0_offset;
u32 vio_dbg1_offset;
+ u32 vio_dbg2_offset;
+ u32 vio_dbg3_offset;
u32 apc_con_offset;
u32 vio_shift_sta_offset;
u32 vio_shift_sel_offset;
@@ -45,16 +57,20 @@ struct mtk_devapc_regs_ofs {
};
struct mtk_devapc_data {
- /* numbers of violation index */
- u32 vio_idx_num;
+ u32 version;
+ /* Default numbers of violation index */
+ u32 default_vio_idx_num;
const struct mtk_devapc_regs_ofs *regs_ofs;
};
struct mtk_devapc_context {
struct device *dev;
- void __iomem *infra_base;
+ void __iomem *base;
struct clk *infra_clk;
const struct mtk_devapc_data *data;
+
+ /* numbers of violation index */
+ u32 vio_idx_num;
};
static void clear_vio_status(struct mtk_devapc_context *ctx)
@@ -62,12 +78,12 @@ static void clear_vio_status(struct mtk_devapc_context *ctx)
void __iomem *reg;
int i;
- reg = ctx->infra_base + ctx->data->regs_ofs->vio_sta_offset;
+ reg = ctx->base + ctx->data->regs_ofs->vio_sta_offset;
- for (i = 0; i < VIO_MOD_TO_REG_IND(ctx->data->vio_idx_num) - 1; i++)
+ for (i = 0; i < VIO_MOD_TO_REG_IND(ctx->vio_idx_num - 1); i++)
writel(GENMASK(31, 0), reg + 4 * i);
- writel(GENMASK(VIO_MOD_TO_REG_OFF(ctx->data->vio_idx_num) - 1, 0),
+ writel(GENMASK(VIO_MOD_TO_REG_OFF(ctx->vio_idx_num - 1), 0),
reg + 4 * i);
}
@@ -77,22 +93,22 @@ static void mask_module_irq(struct mtk_devapc_context *ctx, bool mask)
u32 val;
int i;
- reg = ctx->infra_base + ctx->data->regs_ofs->vio_mask_offset;
+ reg = ctx->base + ctx->data->regs_ofs->vio_mask_offset;
if (mask)
val = GENMASK(31, 0);
else
val = 0;
- for (i = 0; i < VIO_MOD_TO_REG_IND(ctx->data->vio_idx_num) - 1; i++)
+ for (i = 0; i < VIO_MOD_TO_REG_IND(ctx->vio_idx_num - 1); i++)
writel(val, reg + 4 * i);
val = readl(reg + 4 * i);
if (mask)
- val |= GENMASK(VIO_MOD_TO_REG_OFF(ctx->data->vio_idx_num) - 1,
+ val |= GENMASK(VIO_MOD_TO_REG_OFF(ctx->vio_idx_num - 1),
0);
else
- val &= ~GENMASK(VIO_MOD_TO_REG_OFF(ctx->data->vio_idx_num) - 1,
+ val &= ~GENMASK(VIO_MOD_TO_REG_OFF(ctx->vio_idx_num - 1),
0);
writel(val, reg + 4 * i);
@@ -119,11 +135,11 @@ static int devapc_sync_vio_dbg(struct mtk_devapc_context *ctx)
int ret;
u32 val;
- pd_vio_shift_sta_reg = ctx->infra_base +
+ pd_vio_shift_sta_reg = ctx->base +
ctx->data->regs_ofs->vio_shift_sta_offset;
- pd_vio_shift_sel_reg = ctx->infra_base +
+ pd_vio_shift_sel_reg = ctx->base +
ctx->data->regs_ofs->vio_shift_sel_offset;
- pd_vio_shift_con_reg = ctx->infra_base +
+ pd_vio_shift_con_reg = ctx->base +
ctx->data->regs_ofs->vio_shift_con_offset;
/* Find the minimum shift group which has violation */
@@ -134,7 +150,7 @@ static int devapc_sync_vio_dbg(struct mtk_devapc_context *ctx)
min_shift_group = __ffs(val);
/* Assign the group to sync */
- writel(0x1 << min_shift_group, pd_vio_shift_sel_reg);
+ writel(BIT(min_shift_group), pd_vio_shift_sel_reg);
/* Start syncing */
writel(0x1, pd_vio_shift_con_reg);
@@ -150,7 +166,7 @@ static int devapc_sync_vio_dbg(struct mtk_devapc_context *ctx)
writel(0x0, pd_vio_shift_con_reg);
/* Write clear */
- writel(0x1 << min_shift_group, pd_vio_shift_sta_reg);
+ writel(BIT(min_shift_group), pd_vio_shift_sta_reg);
return true;
}
@@ -164,22 +180,52 @@ static void devapc_extract_vio_dbg(struct mtk_devapc_context *ctx)
struct mtk_devapc_vio_dbgs vio_dbgs;
void __iomem *vio_dbg0_reg;
void __iomem *vio_dbg1_reg;
+ void __iomem *vio_dbg2_reg;
+ void __iomem *vio_dbg3_reg;
+ u32 vio_addr_l, vio_addr_h, bus_id, domain_id;
+ u32 vio_w, vio_r;
+ u64 vio_addr;
- vio_dbg0_reg = ctx->infra_base + ctx->data->regs_ofs->vio_dbg0_offset;
- vio_dbg1_reg = ctx->infra_base + ctx->data->regs_ofs->vio_dbg1_offset;
+ vio_dbg0_reg = ctx->base + ctx->data->regs_ofs->vio_dbg0_offset;
+ vio_dbg1_reg = ctx->base + ctx->data->regs_ofs->vio_dbg1_offset;
+ vio_dbg2_reg = ctx->base + ctx->data->regs_ofs->vio_dbg2_offset;
+ vio_dbg3_reg = ctx->base + ctx->data->regs_ofs->vio_dbg3_offset;
vio_dbgs.vio_dbg0 = readl(vio_dbg0_reg);
vio_dbgs.vio_dbg1 = readl(vio_dbg1_reg);
+ if (ctx->data->version >= 2U)
+ vio_dbgs.vio_dbg2 = readl(vio_dbg2_reg);
+ if (ctx->data->version == 3U)
+ vio_dbgs.vio_dbg3 = readl(vio_dbg3_reg);
+
+ if (ctx->data->version == 1U) {
+ /* arch version 1 */
+ bus_id = vio_dbgs.dbg0_bits.mstid;
+ vio_addr = vio_dbgs.vio_dbg1;
+ domain_id = vio_dbgs.dbg0_bits.dmnid;
+ vio_w = vio_dbgs.dbg0_bits.vio_w;
+ vio_r = vio_dbgs.dbg0_bits.vio_r;
+ } else {
+ /* arch version 2 & 3 */
+ bus_id = vio_dbgs.vio_dbg1;
+
+ vio_addr_l = vio_dbgs.vio_dbg2;
+ vio_addr_h = ctx->data->version == 2U ? vio_dbgs.dbg0_bits_ver2.addr_h :
+ vio_dbgs.vio_dbg3;
+ vio_addr = ((u64)vio_addr_h << 32) + vio_addr_l;
+ domain_id = vio_dbgs.dbg0_bits_ver2.dmnid;
+ vio_w = vio_dbgs.dbg0_bits_ver2.vio_w;
+ vio_r = vio_dbgs.dbg0_bits_ver2.vio_r;
+ }
/* Print violation information */
- if (vio_dbgs.dbg0_bits.vio_w)
+ if (vio_w)
dev_info(ctx->dev, "Write Violation\n");
- else if (vio_dbgs.dbg0_bits.vio_r)
+ else if (vio_r)
dev_info(ctx->dev, "Read Violation\n");
- dev_info(ctx->dev, "Bus ID:0x%x, Dom ID:0x%x, Vio Addr:0x%x\n",
- vio_dbgs.dbg0_bits.mstid, vio_dbgs.dbg0_bits.dmnid,
- vio_dbgs.vio_dbg1);
+ dev_info(ctx->dev, "Bus ID:0x%x, Dom ID:0x%x, Vio Addr:0x%llx\n",
+ bus_id, domain_id, vio_addr);
}
/*
@@ -209,7 +255,8 @@ static irqreturn_t devapc_violation_irq(int irq_number, void *data)
*/
static void start_devapc(struct mtk_devapc_context *ctx)
{
- writel(BIT(31), ctx->infra_base + ctx->data->regs_ofs->apc_con_offset);
+
+ writel(BIT(31), ctx->base + ctx->data->regs_ofs->apc_con_offset);
mask_module_irq(ctx, false);
}
@@ -221,28 +268,60 @@ static void stop_devapc(struct mtk_devapc_context *ctx)
{
mask_module_irq(ctx, true);
- writel(BIT(2), ctx->infra_base + ctx->data->regs_ofs->apc_con_offset);
+ writel(BIT(2), ctx->base + ctx->data->regs_ofs->apc_con_offset);
}
-static const struct mtk_devapc_regs_ofs devapc_regs_ofs_mt6779 = {
+static const struct mtk_devapc_regs_ofs devapc_regs_ofs_ver1 = {
+ .vio_mask_offset = 0x0,
+ .vio_sta_offset = 0x400,
+ .vio_dbg0_offset = 0x900,
+ .vio_dbg1_offset = 0x904,
+ .apc_con_offset = 0xf00,
+ .vio_shift_sta_offset = 0xf10,
+ .vio_shift_sel_offset = 0xf14,
+ .vio_shift_con_offset = 0xf20,
+};
+
+static const struct mtk_devapc_regs_ofs devapc_regs_ofs_ver2 = {
.vio_mask_offset = 0x0,
.vio_sta_offset = 0x400,
.vio_dbg0_offset = 0x900,
.vio_dbg1_offset = 0x904,
- .apc_con_offset = 0xF00,
- .vio_shift_sta_offset = 0xF10,
- .vio_shift_sel_offset = 0xF14,
- .vio_shift_con_offset = 0xF20,
+ .vio_dbg2_offset = 0x908,
+ .apc_con_offset = 0xf00,
+ .vio_shift_sta_offset = 0xf20,
+ .vio_shift_sel_offset = 0xf30,
+ .vio_shift_con_offset = 0xf10,
+};
+
+static const struct mtk_devapc_regs_ofs devapc_regs_ofs_ver3 = {
+ .vio_mask_offset = 0x0,
+ .vio_sta_offset = 0x400,
+ .vio_dbg0_offset = 0x900,
+ .vio_dbg1_offset = 0x904,
+ .vio_dbg2_offset = 0x908,
+ .vio_dbg3_offset = 0x90c,
+ .apc_con_offset = 0xf00,
+ .vio_shift_sta_offset = 0xf20,
+ .vio_shift_sel_offset = 0xf30,
+ .vio_shift_con_offset = 0xf10,
};
static const struct mtk_devapc_data devapc_mt6779 = {
- .vio_idx_num = 511,
- .regs_ofs = &devapc_regs_ofs_mt6779,
+ .version = 1,
+ .default_vio_idx_num = 511,
+ .regs_ofs = &devapc_regs_ofs_ver1,
};
static const struct mtk_devapc_data devapc_mt8186 = {
- .vio_idx_num = 519,
- .regs_ofs = &devapc_regs_ofs_mt6779,
+ .version = 1,
+ .default_vio_idx_num = 519,
+ .regs_ofs = &devapc_regs_ofs_ver1,
+};
+
+static const struct mtk_devapc_data devapc_mt8189 = {
+ .version = 3,
+ .regs_ofs = &devapc_regs_ofs_ver3,
};
static const struct of_device_id mtk_devapc_dt_match[] = {
@@ -252,6 +331,9 @@ static const struct of_device_id mtk_devapc_dt_match[] = {
}, {
.compatible = "mediatek,mt8186-devapc",
.data = &devapc_mt8186,
+ }, {
+ .compatible = "mediatek,mt8189-devapc",
+ .data = &devapc_mt8189,
}, {
},
};
@@ -274,9 +356,24 @@ static int mtk_devapc_probe(struct platform_device *pdev)
ctx->data = of_device_get_match_data(&pdev->dev);
ctx->dev = &pdev->dev;
- ctx->infra_base = of_iomap(node, 0);
- if (!ctx->infra_base)
+ ctx->base = of_iomap(node, 0);
+ if (!ctx->base) {
+ dev_err(ctx->dev, "Failed to map devapc registers\n");
return -EINVAL;
+ }
+
+ /*
+ * Set effective vio_idx_num from default value.
+ * If vio_idx_num is 0, get the info from DT.
+ */
+ ctx->vio_idx_num = ctx->data->default_vio_idx_num;
+ if (ctx->vio_idx_num == 0)
+ if (of_property_read_u32(node,
+ "vio-idx-num",
+ &ctx->vio_idx_num)) {
+ ret = -EINVAL;
+ goto err;
+ }
devapc_irq = irq_of_parse_and_map(node, 0);
if (!devapc_irq) {
@@ -314,7 +411,7 @@ static int mtk_devapc_probe(struct platform_device *pdev)
return 0;
err:
- iounmap(ctx->infra_base);
+ iounmap(ctx->base);
return ret;
}
@@ -326,7 +423,7 @@ static void mtk_devapc_remove(struct platform_device *pdev)
clk_disable_unprepare(ctx->infra_clk);
- iounmap(ctx->infra_base);
+ iounmap(ctx->base);
}
static struct platform_driver mtk_devapc_driver = {
--
2.45.2
^ permalink raw reply related
* [PATCH v3 4/6] dt-bindings: soc: mediatek: devapc: Add bindings for MT8189
From: Xiaoshun Xu @ 2026-04-16 3:12 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Matthias Brugger,
AngeloGioacchino Del Regno, Xiaoshun Xu
Cc: devicetree, linux-kernel, linux-arm-kernel, linux-mediatek,
Sirius Wang, Vince-wl Liu, Project_Global_Chrome_Upstream_Group
In-Reply-To: <20260416031231.2932493-1-xiaoshun.xu@mediatek.com>
Extend the devapc device tree bindings to support the MediaTek MT8189
SoC. This includes:
- Adding "mediatek,mt8189-devapc" to the list of compatible strings.
- Introducing the "vio-idx-num" property to specify the number of bus
slaves managed by devapc.
These changes enable proper configuration and integration of devapc on
MT8189 platforms, ensuring accurate device matching and resource
allocation in the device tree.
Signed-off-by: Xiaoshun Xu <xiaoshun.xu@mediatek.com>
---
.../devicetree/bindings/soc/mediatek/devapc.yaml | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/Documentation/devicetree/bindings/soc/mediatek/devapc.yaml b/Documentation/devicetree/bindings/soc/mediatek/devapc.yaml
index 99e2caafeadf..06a096440331 100644
--- a/Documentation/devicetree/bindings/soc/mediatek/devapc.yaml
+++ b/Documentation/devicetree/bindings/soc/mediatek/devapc.yaml
@@ -14,13 +14,14 @@ description: |
analysis and countermeasures.
maintainers:
- - Neal Liu <neal.liu@mediatek.com>
+ - Xiaoshun Xu <xiaoshun.xu@mediatek.com>
properties:
compatible:
enum:
- mediatek,mt6779-devapc
- mediatek,mt8186-devapc
+ - mediatek,mt8189-devapc
reg:
description: The base address of devapc register bank
@@ -30,6 +31,10 @@ properties:
description: A single interrupt specifier
maxItems: 1
+ vio-idx-num:
+ description: Describe the number of bus slaves controlled by devapc
+ $ref: /schemas/types.yaml#/definitions/uint32
+
clocks:
description: Contains module clock source and clock names
maxItems: 1
@@ -42,8 +47,6 @@ required:
- compatible
- reg
- interrupts
- - clocks
- - clock-names
additionalProperties: false
@@ -55,6 +58,7 @@ examples:
devapc: devapc@10207000 {
compatible = "mediatek,mt6779-devapc";
reg = <0x10207000 0x1000>;
+ vio-idx-num = <132>;
interrupts = <GIC_SPI 168 IRQ_TYPE_LEVEL_LOW>;
clocks = <&infracfg_ao CLK_INFRA_DEVICE_APC>;
clock-names = "devapc-infra-clock";
--
2.45.2
^ permalink raw reply related
* [PATCH v3 6/6] dt-bindings: soc: mediatek: devapc: Add bindings for MT8196
From: Xiaoshun Xu @ 2026-04-16 3:12 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Matthias Brugger,
AngeloGioacchino Del Regno, Xiaoshun Xu
Cc: devicetree, linux-kernel, linux-arm-kernel, linux-mediatek,
Sirius Wang, Vince-wl Liu, Project_Global_Chrome_Upstream_Group
In-Reply-To: <20260416031231.2932493-1-xiaoshun.xu@mediatek.com>
Extend the devapc device tree bindings to support the MediaTek MT8196
SoC. This includes:
- Adding "mediatek,mt8196-devapc" to the list of compatible strings.
These changes enable proper configuration and integration of devapc on
MT8196 platforms, ensuring accurate device matching and resource
allocation in the device tree.
Signed-off-by: Xiaoshun Xu <xiaoshun.xu@mediatek.com>
---
Documentation/devicetree/bindings/soc/mediatek/devapc.yaml | 1 +
1 file changed, 1 insertion(+)
diff --git a/Documentation/devicetree/bindings/soc/mediatek/devapc.yaml b/Documentation/devicetree/bindings/soc/mediatek/devapc.yaml
index 06a096440331..5eb260bf3dde 100644
--- a/Documentation/devicetree/bindings/soc/mediatek/devapc.yaml
+++ b/Documentation/devicetree/bindings/soc/mediatek/devapc.yaml
@@ -22,6 +22,7 @@ properties:
- mediatek,mt6779-devapc
- mediatek,mt8186-devapc
- mediatek,mt8189-devapc
+ - mediatek,mt8196-devapc
reg:
description: The base address of devapc register bank
--
2.45.2
^ permalink raw reply related
* [PATCH v3 5/6] soc: mediatek: mtk-devapc: Add support for MT8196 DEVAPC
From: Xiaoshun Xu @ 2026-04-16 3:12 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Matthias Brugger,
AngeloGioacchino Del Regno, Xiaoshun Xu
Cc: devicetree, linux-kernel, linux-arm-kernel, linux-mediatek,
Sirius Wang, Vince-wl Liu, Project_Global_Chrome_Upstream_Group
In-Reply-To: <20260416031231.2932493-1-xiaoshun.xu@mediatek.com>
Add support for MT8196 DEVAPC, MT8196 DEVAPC debug registers are
version 3 and add compatible for MT8196
Signed-off-by: Xiaoshun Xu <xiaoshun.xu@mediatek.com>
---
drivers/soc/mediatek/mtk-devapc.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/drivers/soc/mediatek/mtk-devapc.c b/drivers/soc/mediatek/mtk-devapc.c
index 824b49613c5a..0f828028bdb4 100644
--- a/drivers/soc/mediatek/mtk-devapc.c
+++ b/drivers/soc/mediatek/mtk-devapc.c
@@ -324,6 +324,11 @@ static const struct mtk_devapc_data devapc_mt8189 = {
.regs_ofs = &devapc_regs_ofs_ver3,
};
+static const struct mtk_devapc_data devapc_mt8196 = {
+ .version = 3,
+ .regs_ofs = &devapc_regs_ofs_ver3,
+};
+
static const struct of_device_id mtk_devapc_dt_match[] = {
{
.compatible = "mediatek,mt6779-devapc",
@@ -334,6 +339,9 @@ static const struct of_device_id mtk_devapc_dt_match[] = {
}, {
.compatible = "mediatek,mt8189-devapc",
.data = &devapc_mt8189,
+ }, {
+ .compatible = "mediatek,mt8196-devapc",
+ .data = &devapc_mt8196,
}, {
},
};
--
2.45.2
^ permalink raw reply related
* Re: [PATCH v13 3/3] of: Respect #{iommu,msi}-cells in maps
From: Vijayanand Jitta @ 2026-04-16 3:26 UTC (permalink / raw)
To: Nipun Gupta, Nikhil Agarwal, Joerg Roedel, Will Deacon,
Robin Murphy, Marc Zyngier, Lorenzo Pieralisi, Thomas Gleixner,
Saravana Kannan, Richard Zhu, Lucas Stach,
Krzysztof Wilczyński, Manivannan Sadhasivam, Bjorn Helgaas,
Frank Li, Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
Juergen Gross, Stefano Stabellini, Oleksandr Tyshchenko,
Dmitry Baryshkov, Konrad Dybcio, Bjorn Andersson, Rob Herring,
Conor Dooley, Krzysztof Kozlowski, Prakash Gupta, Vikash Garodia
Cc: linux-kernel, iommu, linux-arm-kernel, devicetree, linux-pci, imx,
xen-devel, linux-arm-msm, Charan Teja Kalla
In-Reply-To: <20260408-parse_iommu_cells-v13-3-fa921e92661b@oss.qualcomm.com>
On 4/8/2026 3:33 PM, Vijayanand Jitta wrote:
> From: Robin Murphy <robin.murphy@arm.com>
>
> So far our parsing of {iommu,msi}-map properties has always blindly
> assumed that the output specifiers will always have exactly 1 cell.
> This typically does happen to be the case, but is not actually enforced
> (and the PCI msi-map binding even explicitly states support for 0 or 1
> cells) - as a result we've now ended up with dodgy DTs out in the field
> which depend on this behaviour to map a 1-cell specifier for a 2-cell
> provider, despite that being bogus per the bindings themselves.
>
> Since there is some potential use in being able to map at least single
> input IDs to multi-cell output specifiers (and properly support 0-cell
> outputs as well), add support for properly parsing and using the target
> nodes' #cells values, albeit with the unfortunate complication of still
> having to work around expectations of the old behaviour too.
>
> Since there are multi-cell output specifiers, the callers of of_map_id()
> may need to get the exact cell output value for further processing.
> Update of_map_id() to set args_count in the output to reflect the actual
> number of output specifier cells.
>
> Signed-off-by: Robin Murphy <robin.murphy@arm.com>
> Signed-off-by: Charan Teja Kalla <charan.kalla@oss.qualcomm.com>
> Signed-off-by: Vijayanand Jitta <vijayanand.jitta@oss.qualcomm.com>
> ---
> drivers/of/base.c | 157 +++++++++++++++++++++++++++++++++++++++++------------
> include/linux/of.h | 6 +-
> 2 files changed, 125 insertions(+), 38 deletions(-)
>
> diff --git a/drivers/of/base.c b/drivers/of/base.c
> index b3d002015192..2554e4f1a181 100644
> --- a/drivers/of/base.c
> +++ b/drivers/of/base.c
> @@ -2096,18 +2096,48 @@ int of_find_last_cache_level(unsigned int cpu)
> return cache_level;
> }
>
> +/*
> + * Some DTs have an iommu-map targeting a 2-cell IOMMU node while
> + * specifying only 1 cell. Fortunately they all consist of value '1'
> + * as the 2nd cell entry with the same target, so check for that pattern.
> + *
> + * Example:
> + * IOMMU node:
> + * #iommu-cells = <2>;
> + *
> + * Device node:
> + * iommu-map = <0x0000 &smmu 0x0000 0x1>,
> + * <0x0100 &smmu 0x0100 0x1>;
> + */
> +static bool of_check_bad_map(const __be32 *map, int len)
> +{
> + __be32 phandle = map[1];
> +
> + if (len % 4)
> + return false;
> + for (int i = 0; i < len; i += 4) {
> + if (map[i + 1] != phandle || map[i + 3] != cpu_to_be32(1))
> + return false;
> + }
> + return true;
> +}
> +
> /**
> * of_map_id - Translate an ID through a downstream mapping.
> * @np: root complex device node.
> * @id: device ID to map.
> * @map_name: property name of the map to use.
> + * @cells_name: property name of target specifier cells.
> * @map_mask_name: optional property name of the mask to use.
> * @filter_np: optional device node to filter matches by, or NULL to match any.
> * If non-NULL, only map entries targeting this node will be matched.
> * @arg: pointer to a &struct of_phandle_args for the result. On success,
> - * @arg->args[0] will contain the translated ID. If a map entry was
> - * matched, @arg->np will be set to the target node with a reference
> - * held that the caller must release with of_node_put().
> + * @arg->args_count will be set to the number of output specifier cells
> + * as defined by @cells_name in the target node, and
> + * @arg->args[0..args_count-1] will contain the translated output
> + * specifier values. If a map entry was matched, @arg->np will be set
> + * to the target node with a reference held that the caller must release
> + * with of_node_put().
> *
> * Given a device ID, look up the appropriate implementation-defined
> * platform ID and/or the target device which receives transactions on that
> @@ -2116,17 +2146,19 @@ int of_find_last_cache_level(unsigned int cpu)
> * Return: 0 on success or a standard error code on failure.
> */
> int of_map_id(const struct device_node *np, u32 id,
> - const char *map_name, const char *map_mask_name,
> + const char *map_name, const char *cells_name,
> + const char *map_mask_name,
> const struct device_node *filter_np, struct of_phandle_args *arg)
> {
> u32 map_mask, masked_id;
> - int map_len;
> + int map_bytes, map_len, offset = 0;
> + bool bad_map = false;
> const __be32 *map = NULL;
>
> if (!np || !map_name || !arg)
> return -EINVAL;
>
> - map = of_get_property(np, map_name, &map_len);
> + map = of_get_property(np, map_name, &map_bytes);
> if (!map) {
> if (filter_np)
> return -ENODEV;
> @@ -2136,11 +2168,9 @@ int of_map_id(const struct device_node *np, u32 id,
> return 0;
> }
>
> - if (!map_len || map_len % (4 * sizeof(*map))) {
> - pr_err("%pOF: Error: Bad %s length: %d\n", np,
> - map_name, map_len);
> - return -EINVAL;
> - }
> + if (map_bytes % sizeof(*map))
> + goto err_map_len;
> + map_len = map_bytes / sizeof(*map);
>
> /* The default is to select all bits. */
> map_mask = 0xffffffff;
> @@ -2153,39 +2183,84 @@ int of_map_id(const struct device_node *np, u32 id,
> of_property_read_u32(np, map_mask_name, &map_mask);
>
> masked_id = map_mask & id;
> - for ( ; map_len > 0; map_len -= 4 * sizeof(*map), map += 4) {
> +
> + while (offset < map_len) {
> struct device_node *phandle_node;
> - u32 id_base = be32_to_cpup(map + 0);
> - u32 phandle = be32_to_cpup(map + 1);
> - u32 out_base = be32_to_cpup(map + 2);
> - u32 id_len = be32_to_cpup(map + 3);
> + u32 id_base, phandle, id_len, id_off, cells = 0;
> + const __be32 *out_base;
> +
> + if (map_len - offset < 2)
> + goto err_map_len;
> +
> + id_base = be32_to_cpup(map + offset);
>
> if (id_base & ~map_mask) {
> - pr_err("%pOF: Invalid %s translation - %s-mask (0x%x) ignores id-base (0x%x)\n",
> - np, map_name, map_name,
> - map_mask, id_base);
> + pr_err("%pOF: Invalid %s translation - %s (0x%x) ignores id-base (0x%x)\n",
> + np, map_name, map_mask_name, map_mask, id_base);
> return -EFAULT;
> }
>
> - if (masked_id < id_base || masked_id >= id_base + id_len)
> - continue;
> -
> + phandle = be32_to_cpup(map + offset + 1);
> phandle_node = of_find_node_by_phandle(phandle);
> if (!phandle_node)
> return -ENODEV;
>
> + if (bad_map) {
> + cells = 1;
> + } else if (of_property_read_u32(phandle_node, cells_name, &cells)) {
> + pr_err("%pOF: missing %s property\n", phandle_node, cells_name);
> + of_node_put(phandle_node);
> + return -EINVAL;
> + }
> +
> + if (map_len - offset < 3 + cells) {
> + of_node_put(phandle_node);
> + goto err_map_len;
> + }
> +
> + if (offset == 0 && cells == 2) {
> + bad_map = of_check_bad_map(map, map_len);
> + if (bad_map) {
> + pr_warn_once("%pOF: %s mismatches target %s, assuming extra cell of 0\n",
> + np, map_name, cells_name);
> + cells = 1;
> + }
> + }
> +
> + out_base = map + offset + 2;
> + offset += 3 + cells;
> +
> + id_len = be32_to_cpup(map + offset - 1);
> + if (id_len > 1 && cells > 1) {
> + /*
> + * With 1 output cell we reasonably assume its value
> + * has a linear relationship to the input; with more,
> + * we'd need help from the provider to know what to do.
> + */
> + pr_err("%pOF: Unsupported %s - cannot handle %d-ID range with %d-cell output specifier\n",
> + np, map_name, id_len, cells);
> + of_node_put(phandle_node);
> + return -EINVAL;
> + }
> + id_off = masked_id - id_base;
> + if (masked_id < id_base || id_off >= id_len) {
> + of_node_put(phandle_node);
> + continue;
> + }
> +
> if (filter_np && filter_np != phandle_node) {
> of_node_put(phandle_node);
> continue;
> }
>
> arg->np = phandle_node;
> - arg->args[0] = masked_id - id_base + out_base;
> - arg->args_count = 1;
> + for (int i = 0; i < cells; i++)
> + arg->args[i] = id_off + be32_to_cpu(out_base[i]);
> + arg->args_count = cells;
>
> pr_debug("%pOF: %s, using mask %08x, id-base: %08x, out-base: %08x, length: %08x, id: %08x -> %08x\n",
> - np, map_name, map_mask, id_base, out_base,
> - id_len, id, masked_id - id_base + out_base);
> + np, map_name, map_mask, id_base, be32_to_cpup(out_base),
> + id_len, id, id_off + be32_to_cpup(out_base));
> return 0;
> }
>
> @@ -2196,6 +2271,10 @@ int of_map_id(const struct device_node *np, u32 id,
> arg->args[0] = id;
> arg->args_count = 1;
> return 0;
> +
> +err_map_len:
> + pr_err("%pOF: Error: Bad %s length: %d\n", np, map_name, map_bytes);
> + return -EINVAL;
> }
> EXPORT_SYMBOL_GPL(of_map_id);
>
> @@ -2205,18 +2284,21 @@ EXPORT_SYMBOL_GPL(of_map_id);
> * @id: Requester ID of the device (e.g. PCI RID/BDF or a platform
> * stream/device ID) used as the lookup key in the iommu-map table.
> * @arg: pointer to a &struct of_phandle_args for the result. On success,
> - * @arg->args[0] contains the translated ID. If a map entry was matched,
> - * @arg->np holds a reference to the target node that the caller must
> - * release with of_node_put().
> + * @arg->args_count will be set to the number of output specifier cells
> + * and @arg->args[0..args_count-1] will contain the translated output
> + * specifier values. If a map entry was matched, @arg->np holds a
> + * reference to the target node that the caller must release with
> + * of_node_put().
> *
> - * Convenience wrapper around of_map_id() using "iommu-map" and "iommu-map-mask".
> + * Convenience wrapper around of_map_id() using "iommu-map", "#iommu-cells",
> + * and "iommu-map-mask".
> *
> * Return: 0 on success or a standard error code on failure.
> */
> int of_map_iommu_id(const struct device_node *np, u32 id,
> struct of_phandle_args *arg)
> {
> - return of_map_id(np, id, "iommu-map", "iommu-map-mask", NULL, arg);
> + return of_map_id(np, id, "iommu-map", "#iommu-cells", "iommu-map-mask", NULL, arg);
> }
> EXPORT_SYMBOL_GPL(of_map_iommu_id);
>
> @@ -2229,17 +2311,20 @@ EXPORT_SYMBOL_GPL(of_map_iommu_id);
> * to match any. If non-NULL, only map entries targeting this node will
> * be matched.
> * @arg: pointer to a &struct of_phandle_args for the result. On success,
> - * @arg->args[0] contains the translated ID. If a map entry was matched,
> - * @arg->np holds a reference to the target node that the caller must
> - * release with of_node_put().
> + * @arg->args_count will be set to the number of output specifier cells
> + * and @arg->args[0..args_count-1] will contain the translated output
> + * specifier values. If a map entry was matched, @arg->np holds a
> + * reference to the target node that the caller must release with
> + * of_node_put().
> *
> - * Convenience wrapper around of_map_id() using "msi-map" and "msi-map-mask".
> + * Convenience wrapper around of_map_id() using "msi-map", "#msi-cells",
> + * and "msi-map-mask".
> *
> * Return: 0 on success or a standard error code on failure.
> */
> int of_map_msi_id(const struct device_node *np, u32 id,
> const struct device_node *filter_np, struct of_phandle_args *arg)
> {
> - return of_map_id(np, id, "msi-map", "msi-map-mask", filter_np, arg);
> + return of_map_id(np, id, "msi-map", "#msi-cells", "msi-map-mask", filter_np, arg);
> }
> EXPORT_SYMBOL_GPL(of_map_msi_id);
> diff --git a/include/linux/of.h b/include/linux/of.h
> index 8548cd9eb4f1..51ac8539f2c3 100644
> --- a/include/linux/of.h
> +++ b/include/linux/of.h
> @@ -462,7 +462,8 @@ const char *of_prop_next_string(const struct property *prop, const char *cur);
> bool of_console_check(const struct device_node *dn, char *name, int index);
>
> int of_map_id(const struct device_node *np, u32 id,
> - const char *map_name, const char *map_mask_name,
> + const char *map_name, const char *cells_name,
> + const char *map_mask_name,
> const struct device_node *filter_np, struct of_phandle_args *arg);
>
> int of_map_iommu_id(const struct device_node *np, u32 id,
> @@ -934,7 +935,8 @@ static inline void of_property_clear_flag(struct property *p, unsigned long flag
> }
>
> static inline int of_map_id(const struct device_node *np, u32 id,
> - const char *map_name, const char *map_mask_name,
> + const char *map_name, const char *cells_name,
> + const char *map_mask_name,
> const struct device_node *filter_np,
> struct of_phandle_args *arg)
> {
>
Gentle ping.
Thanks,
Vijay
^ permalink raw reply
* Re: [PATCH v3 1/6] soc: mediatek: mtk-devapc: refine devapc interrupt handler
From: CK Hu (胡俊光) @ 2026-04-16 3:45 UTC (permalink / raw)
To: robh@kernel.org, Xiaoshun Xu (徐晓顺),
krzk+dt@kernel.org, conor+dt@kernel.org, matthias.bgg@gmail.com,
AngeloGioacchino Del Regno
Cc: linux-arm-kernel@lists.infradead.org,
linux-mediatek@lists.infradead.org, devicetree@vger.kernel.org,
linux-kernel@vger.kernel.org,
Sirius Wang (王皓昱),
Project_Global_Chrome_Upstream_Group,
Vince-WL Liu (劉文龍)
In-Reply-To: <20260416031231.2932493-2-xiaoshun.xu@mediatek.com>
On Thu, 2026-04-16 at 11:12 +0800, Xiaoshun Xu wrote:
> Because the violation IRQ uses a while loop, it might cause the
> system to remain in the interrupt handler indefinitely. We are
> currently optimizing this part of the process to handle only 20
> violations for debug violation issues, and then exit the loop
>
> Signed-off-by: Xiaoshun Xu <xiaoshun.xu@mediatek.com>
> ---
> drivers/soc/mediatek/mtk-devapc.c | 8 +++++++-
> 1 file changed, 7 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/soc/mediatek/mtk-devapc.c b/drivers/soc/mediatek/mtk-devapc.c
> index f54c966138b5..c9e1401315ad 100644
> --- a/drivers/soc/mediatek/mtk-devapc.c
> +++ b/drivers/soc/mediatek/mtk-devapc.c
> @@ -12,6 +12,7 @@
> #include <linux/of_irq.h>
> #include <linux/of_address.h>
>
> +#define MAX_VIO_NUM 20
> #define VIO_MOD_TO_REG_IND(m) ((m) / 32)
> #define VIO_MOD_TO_REG_OFF(m) ((m) % 32)
>
> @@ -188,13 +189,18 @@ static void devapc_extract_vio_dbg(struct mtk_devapc_context *ctx)
> */
> static irqreturn_t devapc_violation_irq(int irq_number, void *data)
> {
> + u32 vio_num = 0;
> struct mtk_devapc_context *ctx = data;
>
> - while (devapc_sync_vio_dbg(ctx))
> + mask_module_irq(ctx, true);
mask irq is not related to this patch. This patch care about the infinite loop.
So separate mask irq part to an independent patch and describe why do this.
Regards,
CK
> +
> + for (vio_num = 0; (vio_num < MAX_VIO_NUM) && (devapc_sync_vio_dbg(ctx)); ++vio_num)
> devapc_extract_vio_dbg(ctx);
>
> clear_vio_status(ctx);
>
> + mask_module_irq(ctx, false);
> +
> return IRQ_HANDLED;
> }
>
^ permalink raw reply
* Re: [PATCH v5 07/12] coresight: etm4x: fix inconsistencies with sysfs configuration
From: Jie Gan @ 2026-04-16 4:35 UTC (permalink / raw)
To: Yeoreum Yun, coresight, linux-arm-kernel, linux-kernel
Cc: suzuki.poulose, mike.leach, james.clark, alexander.shishkin,
leo.yan
In-Reply-To: <20260415165528.3369607-8-yeoreum.yun@arm.com>
On 4/16/2026 12:55 AM, Yeoreum Yun wrote:
> The current ETM4x configuration via sysfs can lead to
> several inconsistencies:
>
> - If the configuration is modified via sysfs while a perf session is
> active, the running configuration may differ before a sched-out and
> after a subsequent sched-in.
>
> - If a perf session and a sysfs session enable tracing concurrently,
> the configuration from configfs may become corrupted.
>
> - There is a risk of corrupting drvdata->config if a perf session enables
> tracing while cscfg_csdev_disable_active_config() is being handled in
> etm4_disable_sysfs().
>
> To resolve these issues, separate the configuration into:
>
> - active_config: the configuration applied to the current session
> - config: the configuration set via sysfs
>
> Additionally:
>
> - Apply the configuration from configfs after taking the appropriate mode.
>
> - Since active_config and related fields are accessed only by the local CPU
> in etm4_enable/disable_sysfs_smp_call() (similar to perf enable/disable),
> remove the lock/unlock from the sysfs enable/disable path and
> startup/dying_cpu except when to access config fields.
>
> Signed-off-by: Yeoreum Yun <yeoreum.yun@arm.com>
> ---
<...>
> @@ -618,23 +624,45 @@ static int etm4_enable_hw(struct etmv4_drvdata *drvdata)
> static void etm4_enable_sysfs_smp_call(void *info)
> {
> struct etm4_enable_arg *arg = info;
> + struct etmv4_drvdata *drvdata;
> struct coresight_device *csdev;
>
> if (WARN_ON(!arg))
> return;
>
> - csdev = arg->drvdata->csdev;
> + drvdata = arg->drvdata;
> + csdev = drvdata->csdev;
> if (!coresight_take_mode(csdev, CS_MODE_SYSFS)) {
> /* Someone is already using the tracer */
> arg->rc = -EBUSY;
> return;
> }
>
> - arg->rc = etm4_enable_hw(arg->drvdata);
> + drvdata->active_config = arg->config;
>
> - /* The tracer didn't start */
> + if (arg->cfg_hash) {
> + arg->rc = cscfg_csdev_enable_active_config(csdev,
> + arg->cfg_hash,
> + arg->preset);
> + if (arg->rc)
> + goto err;
> + }
> +
> + drvdata->trcid = arg->trace_id;
> +
> + /* Tracer will never be paused in sysfs mode */
> + drvdata->paused = false;
> +
> + arg->rc = etm4_enable_hw(drvdata);
> if (arg->rc)
> - coresight_set_mode(csdev, CS_MODE_DISABLED);
needs disable the active config in error path:
cscfg_csdev_disable_active_config(drvdata->csdev);
Thanks,
Jie
> + goto err;
> +
> + drvdata->sticky_enable = true;
> +
> + return;
> +err:
> + /* The tracer didn't start */
> + coresight_set_mode(csdev, CS_MODE_DISABLED);
> }
>
> /*
> @@ -672,7 +700,7 @@ static int etm4_config_timestamp_event(struct etmv4_drvdata *drvdata,
> int ctridx;
> int rselector;
> const struct etmv4_caps *caps = &drvdata->caps;
> - struct etmv4_config *config = &drvdata->config;
> + struct etmv4_config *config = &drvdata->active_config;
>
> /* No point in trying if we don't have at least one counter */
> if (!caps->nr_cntr)
> @@ -756,7 +784,7 @@ static int etm4_parse_event_config(struct coresight_device *csdev,
> int ret = 0;
> struct etmv4_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
> const struct etmv4_caps *caps = &drvdata->caps;
> - struct etmv4_config *config = &drvdata->config;
> + struct etmv4_config *config = &drvdata->active_config;
> struct perf_event_attr max_timestamp = {
> .ATTR_CFG_FLD_timestamp_CFG = U64_MAX,
> };
> @@ -918,40 +946,29 @@ static int etm4_enable_sysfs(struct coresight_device *csdev, struct coresight_pa
>
> /* enable any config activated by configfs */
> cscfg_config_sysfs_get_active_cfg(&cfg_hash, &preset);
> - if (cfg_hash) {
> - ret = cscfg_csdev_enable_active_config(csdev, cfg_hash, preset);
> - if (ret) {
> - etm4_release_trace_id(drvdata);
> - return ret;
> - }
> - }
> -
> - raw_spin_lock(&drvdata->spinlock);
> -
> - drvdata->trcid = path->trace_id;
> -
> - /* Tracer will never be paused in sysfs mode */
> - drvdata->paused = false;
>
> /*
> * Executing etm4_enable_hw on the cpu whose ETM is being enabled
> * ensures that register writes occur when cpu is powered.
> */
> arg.drvdata = drvdata;
> + arg.cfg_hash = cfg_hash;
> + arg.preset = preset;
> + arg.trace_id = path->trace_id;
> +
> + raw_spin_lock(&drvdata->spinlock);
> + arg.config = drvdata->config;
> + raw_spin_unlock(&drvdata->spinlock);
> +
> ret = smp_call_function_single(drvdata->cpu,
> etm4_enable_sysfs_smp_call, &arg, 1);
> if (!ret)
> ret = arg.rc;
> if (!ret)
> - drvdata->sticky_enable = true;
> -
> - if (ret)
> + dev_dbg(&csdev->dev, "ETM tracing enabled\n");
> + else
> etm4_release_trace_id(drvdata);
>
> - raw_spin_unlock(&drvdata->spinlock);
> -
> - if (!ret)
> - dev_dbg(&csdev->dev, "ETM tracing enabled\n");
> return ret;
> }
>
> @@ -1038,7 +1055,7 @@ static void etm4_disable_hw(struct etmv4_drvdata *drvdata)
> {
> u32 control;
> const struct etmv4_caps *caps = &drvdata->caps;
> - struct etmv4_config *config = &drvdata->config;
> + struct etmv4_config *config = &drvdata->active_config;
> struct coresight_device *csdev = drvdata->csdev;
> struct csdev_access *csa = &csdev->access;
> int i;
> @@ -1074,6 +1091,8 @@ static void etm4_disable_sysfs_smp_call(void *info)
>
> etm4_disable_hw(drvdata);
>
> + cscfg_csdev_disable_active_config(drvdata->csdev);
> +
> coresight_set_mode(drvdata->csdev, CS_MODE_DISABLED);
> }
>
> @@ -1124,7 +1143,6 @@ static void etm4_disable_sysfs(struct coresight_device *csdev)
> * DYING hotplug callback is serviced by the ETM driver.
> */
> cpus_read_lock();
> - raw_spin_lock(&drvdata->spinlock);
>
> /*
> * Executing etm4_disable_hw on the cpu whose ETM is being disabled
> @@ -1133,10 +1151,6 @@ static void etm4_disable_sysfs(struct coresight_device *csdev)
> smp_call_function_single(drvdata->cpu, etm4_disable_sysfs_smp_call,
> drvdata, 1);
>
> - raw_spin_unlock(&drvdata->spinlock);
> -
> - cscfg_csdev_disable_active_config(csdev);
> -
> cpus_read_unlock();
>
> /*
> @@ -1379,6 +1393,7 @@ static void etm4_init_arch_data(void *info)
> struct etm4_init_arg *init_arg = info;
> struct etmv4_drvdata *drvdata;
> struct etmv4_caps *caps;
> + struct etmv4_config *config;
> struct csdev_access *csa;
> struct device *dev = init_arg->dev;
> int i;
> @@ -1386,6 +1401,7 @@ static void etm4_init_arch_data(void *info)
> drvdata = dev_get_drvdata(init_arg->dev);
> caps = &drvdata->caps;
> csa = init_arg->csa;
> + config = &drvdata->active_config;
>
> /*
> * If we are unable to detect the access mechanism,
> @@ -1446,7 +1462,7 @@ static void etm4_init_arch_data(void *info)
>
> /* EXLEVEL_S, bits[19:16] Secure state instruction tracing */
> caps->s_ex_level = FIELD_GET(TRCIDR3_EXLEVEL_S_MASK, etmidr3);
> - drvdata->config.s_ex_level = caps->s_ex_level;
> + config->s_ex_level = caps->s_ex_level;
> /* EXLEVEL_NS, bits[23:20] Non-secure state instruction tracing */
> caps->ns_ex_level = FIELD_GET(TRCIDR3_EXLEVEL_NS_MASK, etmidr3);
> /*
> @@ -1692,7 +1708,7 @@ static void etm4_set_default(struct etmv4_config *config)
> static int etm4_get_next_comparator(struct etmv4_drvdata *drvdata, u32 type)
> {
> int nr_comparator, index = 0;
> - struct etmv4_config *config = &drvdata->config;
> + struct etmv4_config *config = &drvdata->active_config;
>
> /*
> * nr_addr_cmp holds the number of comparator _pair_, so time 2
> @@ -1733,7 +1749,7 @@ static int etm4_set_event_filters(struct etmv4_drvdata *drvdata,
> {
> int i, comparator, ret = 0;
> u64 address;
> - struct etmv4_config *config = &drvdata->config;
> + struct etmv4_config *config = &drvdata->active_config;
> struct etm_filters *filters = event->hw.addr_filters;
>
> if (!filters)
> @@ -1851,13 +1867,11 @@ static int etm4_starting_cpu(unsigned int cpu)
> if (!etmdrvdata[cpu])
> return 0;
>
> - raw_spin_lock(&etmdrvdata[cpu]->spinlock);
> if (!etmdrvdata[cpu]->os_unlock)
> etm4_os_unlock(etmdrvdata[cpu]);
>
> if (coresight_get_mode(etmdrvdata[cpu]->csdev))
> etm4_enable_hw(etmdrvdata[cpu]);
> - raw_spin_unlock(&etmdrvdata[cpu]->spinlock);
> return 0;
> }
>
> @@ -1866,10 +1880,8 @@ static int etm4_dying_cpu(unsigned int cpu)
> if (!etmdrvdata[cpu])
> return 0;
>
> - raw_spin_lock(&etmdrvdata[cpu]->spinlock);
> if (coresight_get_mode(etmdrvdata[cpu]->csdev))
> etm4_disable_hw(etmdrvdata[cpu]);
> - raw_spin_unlock(&etmdrvdata[cpu]->spinlock);
> return 0;
> }
>
> @@ -2255,7 +2267,8 @@ static int etm4_add_coresight_dev(struct etm4_init_arg *init_arg)
> if (!desc.name)
> return -ENOMEM;
>
> - etm4_set_default(&drvdata->config);
> + etm4_set_default(&drvdata->active_config);
> + drvdata->config = drvdata->active_config;
>
> pdata = coresight_get_platform_data(dev);
> if (IS_ERR(pdata))
> diff --git a/drivers/hwtracing/coresight/coresight-etm4x.h b/drivers/hwtracing/coresight/coresight-etm4x.h
> index cbd8890d166a..9b50aaa368cf 100644
> --- a/drivers/hwtracing/coresight/coresight-etm4x.h
> +++ b/drivers/hwtracing/coresight/coresight-etm4x.h
> @@ -1069,6 +1069,7 @@ struct etmv4_save_state {
> * allows tracing at all ELs. We don't want to compute this
> * at runtime, due to the additional setting of TRFCR_CX when
> * in EL2. Otherwise, 0.
> + * @active_config: structure holding current applied configuration parameters.
> * @config: structure holding configuration parameters.
> * @save_state: State to be preserved across power loss
> * @paused: Indicates if the trace unit is paused.
> @@ -1089,6 +1090,7 @@ struct etmv4_drvdata {
> bool os_unlock : 1;
> bool paused : 1;
> u64 trfcr;
> + struct etmv4_config active_config;
> struct etmv4_config config;
> struct etmv4_save_state *save_state;
> DECLARE_BITMAP(arch_features, ETM4_IMPDEF_FEATURE_MAX);
^ permalink raw reply
* Re: [PATCH] arm_pmu: acpi: fix reference leak on failed device registration
From: Greg Kroah-Hartman @ 2026-04-16 4:40 UTC (permalink / raw)
To: Mark Rutland
Cc: Guangshuo Li, Will Deacon, Anshuman Khandual, linux-arm-kernel,
linux-perf-users, linux-kernel, stable
In-Reply-To: <ad_WmuauLJ3xDKqh@J2N7QTR9R3>
On Wed, Apr 15, 2026 at 07:19:06PM +0100, Mark Rutland wrote:
> Hi,
>
> Thanks for the patch, but from a quick skim, I don't think this is the right
> fix.
>
> Greg, I think we might want to rework the core API here; question for
> you at the end.
>
> On Thu, Apr 16, 2026 at 01:41:59AM +0800, Guangshuo Li wrote:
> > When platform_device_register() fails in arm_acpi_register_pmu_device(),
> > the embedded struct device in pdev has already been initialized by
> > device_initialize(), but the failure path only unregisters the GSI and
> > does not drop the device reference for the current platform device:
> >
> > arm_acpi_register_pmu_device()
> > -> platform_device_register(pdev)
> > -> device_initialize(&pdev->dev)
> > -> setup_pdev_dma_masks(pdev)
> > -> platform_device_add(pdev)
> >
> > This leads to a reference leak when platform_device_register() fails.
>
> AFAICT you're saying that the reference was taken *within*
> platform_device_register(), and then platform_device_register() itself
> has failed. I think it's surprising that platform_device_register()
> doesn't clean that up itself in the case of an error.
>
> There are *tonnes* of calls to platform_device_register() throughout the
> kernel that don't even bother to check the return value, and many that
> just pass the return onto a caller that can't possibly know to call
> platform_device_put().
>
> Code in the same file as platform_device_register() expects it to clean up
> after itself, e.g.
>
> | int platform_add_devices(struct platform_device **devs, int num)
> | {
> | int i, ret = 0;
> |
> | for (i = 0; i < num; i++) {
> | ret = platform_device_register(devs[i]);
> | if (ret) {
> | while (--i >= 0)
> | platform_device_unregister(devs[i]);
> | break;
> | }
> | }
> |
> | return ret;
> | }
>
> That's been there since the initial git commit, and back then,
> platform_device_register() didn't mention that callers needed to perform
> any cleanup.
>
> I see a comment was added to platform_device_register() in commit:
>
> 67e532a42cf4 ("driver core: platform: document registration-failure requirement")
>
> ... and that copied the commend added for device_register() in commit:
>
> 5739411acbaa ("Driver core: Clarify device cleanup.")
>
> ... but the potential brokenness is so widespread, and the behaviour is
> so surprising, that I'd argue the real but is that device_register()
> doesn't clean up in case of error. I don't think it's worth changing
> this single instance given the prevalance and churn fixing all of that
> would involve.
>
> I think it would be far better to fix the core driver API such that when
> those functions return an error, they've already cleaned up for
> themselves.
>
> Greg, am I missing some functional reason why we can't rework
> device_register() and friends to handle cleanup themselves? I appreciate
> that'll involve churn for some callers, but AFAICT the majority of
> callers don't have the required cleanup.
Yes, we should fix the platform core code here, this should not be
required to do everywhere as obviously we all got it wrong.
Guangshuo, can you submit a patch to do that instead and ask for all of
your other patches to not be applied as well?
thanks,
greg k-h
^ permalink raw reply
* RE: [PATCH v4 3/9] media: chips-media: wave6: Add Wave6 VPU interface
From: Nas Chung @ 2026-04-16 5:25 UTC (permalink / raw)
To: Nicolas Dufresne, mchehab@kernel.org, hverkuil@xs4all.nl,
robh@kernel.org, krzk+dt@kernel.org, conor+dt@kernel.org,
shawnguo@kernel.org, s.hauer@pengutronix.de
Cc: linux-media@vger.kernel.org, devicetree@vger.kernel.org,
linux-kernel@vger.kernel.org, linux-imx@nxp.com,
linux-arm-kernel@lists.infradead.org, jackson.lee, lafley.kim,
marek.vasut@mailbox.org, Ming Qian
In-Reply-To: <7306c00b626f4030d92b908022b9a39669b07bb7.camel@ndufresne.ca>
Hi, Nicolas.
Sorry, I just realized that I never replied to your earlier email.
>-----Original Message-----
>From: Nicolas Dufresne <nicolas@ndufresne.ca>
>Sent: Thursday, December 11, 2025 4:54 AM
>To: Nas Chung <nas.chung@chipsnmedia.com>; mchehab@kernel.org;
>hverkuil@xs4all.nl; robh@kernel.org; krzk+dt@kernel.org;
>conor+dt@kernel.org; shawnguo@kernel.org; s.hauer@pengutronix.de
>Cc: linux-media@vger.kernel.org; devicetree@vger.kernel.org; linux-
>kernel@vger.kernel.org; linux-imx@nxp.com; linux-arm-
>kernel@lists.infradead.org; jackson.lee <jackson.lee@chipsnmedia.com>;
>lafley.kim <lafley.kim@chipsnmedia.com>; marek.vasut@mailbox.org; Ming Qian
><ming.qian@oss.nxp.com>
>Subject: Re: [PATCH v4 3/9] media: chips-media: wave6: Add Wave6 VPU
>interface
>
>Hi,
>
>Le mercredi 22 octobre 2025 à 16:47 +0900, Nas Chung a écrit :
>> Add an interface layer to manage hardware register configuration
>> and communication with the Chips&Media Wave6 video codec IP.
>>
>> The interface provides low-level helper functions used by the
>> Wave6 core driver to implement video encoding and decoding operations.
>> It handles command submission to the firmware via MMIO registers,
>> and waits for a response by polling the firmware busy flag.
>>
>> Signed-off-by: Nas Chung <nas.chung@chipsnmedia.com>
>> Tested-by: Ming Qian <ming.qian@oss.nxp.com>
>> Tested-by: Marek Vasut <marek.vasut@mailbox.org>
>> ---
[...]
>
>[...]
>
>stopping there for now. I feel like we did a big mistake in wave5 by
>allowing a
>heavy abstraction, its a lot harder to fix and it served no purpose since
>you
>went for a fresh driver for wave6. I think its proper to ask for a slimmer
>interface.
>
>The V4L2 API is the front-end, and where all the validation should take
>place.
>The HW interface should simply manage the HW in a readable and non-
>redundant
>way. In V4L2, strides and buffer size are part of the try/s/g_fmt API, so
>these
>should not be duplicated here and they should clearly use the common code.
I agree that the HW interface should be slimmer and should not duplicate
validation handled in the V4L2 layer.
>
>I know its painful to ear, but you will be remove 50% of the code, which
>long
>term will be a massive win on maintenance.
I am reworking the series to address your earlier feedback as well, and I will
include that in the next patch version.
Thanks again for your feedback.
Thanks.
Nas.
>
>regards,
>Nicolas
^ permalink raw reply
* Re: [PATCH v5 04/12] coresight: etm4x: exclude ss_status from drvdata->config
From: Jie Gan @ 2026-04-16 5:42 UTC (permalink / raw)
To: Yeoreum Yun, coresight, linux-arm-kernel, linux-kernel
Cc: suzuki.poulose, mike.leach, james.clark, alexander.shishkin,
leo.yan
In-Reply-To: <20260415165528.3369607-5-yeoreum.yun@arm.com>
On 4/16/2026 12:55 AM, Yeoreum Yun wrote:
> The purpose of TRCSSCSRn register is to show status of
> the corresponding Single-shot Comparator Control and input supports.
> That means writable field's purpose for reset or restore from idle status
> not for configuration.
>
> Therefore, exclude ss_status from drvdata->config, move it to etm4x_caps
> and rename it to ss_smp.
>
> This includes remove TRCSSCRn from configurable item and
> remove saving in etm4_disable_hw().
>
> Signed-off-by: Yeoreum Yun <yeoreum.yun@arm.com>
> ---
> .../hwtracing/coresight/coresight-etm4x-cfg.c | 1 -
> .../coresight/coresight-etm4x-core.c | 19 ++++++-------------
> .../coresight/coresight-etm4x-sysfs.c | 7 ++-----
> drivers/hwtracing/coresight/coresight-etm4x.h | 7 ++++++-
> 4 files changed, 14 insertions(+), 20 deletions(-)
>
> diff --git a/drivers/hwtracing/coresight/coresight-etm4x-cfg.c b/drivers/hwtracing/coresight/coresight-etm4x-cfg.c
> index c302072b293a..d14d7c8a23e5 100644
> --- a/drivers/hwtracing/coresight/coresight-etm4x-cfg.c
> +++ b/drivers/hwtracing/coresight/coresight-etm4x-cfg.c
> @@ -86,7 +86,6 @@ static int etm4_cfg_map_reg_offset(struct etmv4_drvdata *drvdata,
> off_mask = (offset & GENMASK(11, 5));
> do {
> CHECKREGIDX(TRCSSCCRn(0), ss_ctrl, idx, off_mask);
> - CHECKREGIDX(TRCSSCSRn(0), ss_status, idx, off_mask);
> CHECKREGIDX(TRCSSPCICRn(0), ss_pe_cmp, idx, off_mask);
> } while (0);
> } else if ((offset >= TRCCIDCVRn(0)) && (offset <= TRCVMIDCVRn(7))) {
> diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c
> index b2b092a76eb5..f55338a4989d 100644
> --- a/drivers/hwtracing/coresight/coresight-etm4x-core.c
> +++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c
> @@ -91,7 +91,7 @@ static bool etm4x_sspcicrn_present(struct etmv4_drvdata *drvdata, int n)
> const struct etmv4_caps *caps = &drvdata->caps;
>
> return (n < caps->nr_ss_cmp) && caps->nr_pe_cmp &&
> - (drvdata->config.ss_status[n] & TRCSSCSRn_PC);
> + (caps->ss_cmp[n] & TRCSSCSRn_PC);
> }
>
> u64 etm4x_sysreg_read(u32 offset, bool _relaxed, bool _64bit)
> @@ -573,11 +573,9 @@ static int etm4_enable_hw(struct etmv4_drvdata *drvdata)
> etm4x_relaxed_write32(csa, config->res_ctrl[i], TRCRSCTLRn(i));
>
> for (i = 0; i < caps->nr_ss_cmp; i++) {
> - /* always clear status bit on restart if using single-shot */
> - if (config->ss_ctrl[i] || config->ss_pe_cmp[i])
> - config->ss_status[i] &= ~TRCSSCSRn_STATUS;
> etm4x_relaxed_write32(csa, config->ss_ctrl[i], TRCSSCCRn(i));
> - etm4x_relaxed_write32(csa, config->ss_status[i], TRCSSCSRn(i));
> + /* always clear status and pending bits on restart if using single-shot */
> + etm4x_relaxed_write32(csa, 0x0, TRCSSCSRn(i));
> if (etm4x_sspcicrn_present(drvdata, i))
> etm4x_relaxed_write32(csa, config->ss_pe_cmp[i], TRCSSPCICRn(i));
> }
> @@ -1055,12 +1053,6 @@ static void etm4_disable_hw(struct etmv4_drvdata *drvdata)
>
> etm4_disable_trace_unit(drvdata);
>
> - /* read the status of the single shot comparators */
> - for (i = 0; i < caps->nr_ss_cmp; i++) {
> - config->ss_status[i] =
> - etm4x_relaxed_read32(csa, TRCSSCSRn(i));
> - }
> -
> /* read back the current counter values */
> for (i = 0; i < caps->nr_cntr; i++) {
> config->cntr_val[i] =
> @@ -1503,8 +1495,9 @@ static void etm4_init_arch_data(void *info)
> */
> caps->nr_ss_cmp = FIELD_GET(TRCIDR4_NUMSSCC_MASK, etmidr4);
> for (i = 0; i < caps->nr_ss_cmp; i++) {
> - drvdata->config.ss_status[i] =
> - etm4x_relaxed_read32(csa, TRCSSCSRn(i));
> + caps->ss_cmp[i] = etm4x_relaxed_read32(csa, TRCSSCSRn(i));
> + caps->ss_cmp[i] &= (TRCSSCSRn_PC | TRCSSCSRn_DV |
> + TRCSSCSRn_DA | TRCSSCSRn_INST);
Just re-go through this patch and had a question here:
I’m not sure whether this new change should be documented in the ABI,
given that the TRCSSCSRn_STATUS bit is masked. In my opinion, this
change breaks the existing ABI description.
Description from the ABI document:
What: /sys/bus/coresight/devices/etm<N>/sshot_status
Date: December 2019
KernelVersion: 5.5
Contact: Mathieu Poirier <mathieu.poirier@linaro.org>
Description: (Read) Print the current value of the selected single
shot status register.
Thanks,
Jie
> }
> /* NUMCIDC, bits[27:24] number of Context ID comparators for tracing */
> caps->numcidc = FIELD_GET(TRCIDR4_NUMCIDC_MASK, etmidr4);
> diff --git a/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c b/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c
> index 8bd28e71d4c9..5e26c2ec8f7b 100644
> --- a/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c
> +++ b/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c
> @@ -1829,8 +1829,6 @@ static ssize_t sshot_ctrl_store(struct device *dev,
> raw_spin_lock(&drvdata->spinlock);
> idx = config->ss_idx;
> config->ss_ctrl[idx] = FIELD_PREP(TRCSSCCRn_SAC_ARC_RST_MASK, val);
> - /* must clear bit 31 in related status register on programming */
> - config->ss_status[idx] &= ~TRCSSCSRn_STATUS;
> raw_spin_unlock(&drvdata->spinlock);
> return size;
> }
> @@ -1841,10 +1839,11 @@ static ssize_t sshot_status_show(struct device *dev,
> {
> unsigned long val;
> struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
> + const struct etmv4_caps *caps = &drvdata->caps;
> struct etmv4_config *config = &drvdata->config;
>
> raw_spin_lock(&drvdata->spinlock);
> - val = config->ss_status[config->ss_idx];
> + val = caps->ss_cmp[config->ss_idx];
> raw_spin_unlock(&drvdata->spinlock);
> return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
> }
> @@ -1879,8 +1878,6 @@ static ssize_t sshot_pe_ctrl_store(struct device *dev,
> raw_spin_lock(&drvdata->spinlock);
> idx = config->ss_idx;
> config->ss_pe_cmp[idx] = FIELD_PREP(TRCSSPCICRn_PC_MASK, val);
> - /* must clear bit 31 in related status register on programming */
> - config->ss_status[idx] &= ~TRCSSCSRn_STATUS;
> raw_spin_unlock(&drvdata->spinlock);
> return size;
> }
> diff --git a/drivers/hwtracing/coresight/coresight-etm4x.h b/drivers/hwtracing/coresight/coresight-etm4x.h
> index 8168676f2945..db56c4414873 100644
> --- a/drivers/hwtracing/coresight/coresight-etm4x.h
> +++ b/drivers/hwtracing/coresight/coresight-etm4x.h
> @@ -213,6 +213,7 @@
> #define TRCACATRn_EXLEVEL_MASK GENMASK(14, 8)
>
> #define TRCSSCSRn_STATUS BIT(31)
> +#define TRCSSCSRn_PENDING BIT(30)
> #define TRCSSCCRn_SAC_ARC_RST_MASK GENMASK(24, 0)
>
> #define TRCSSPCICRn_PC_MASK GENMASK(7, 0)
> @@ -729,6 +730,9 @@ static inline u32 etm4_res_sel_pair(u8 res_sel_idx)
> #define ETM_DEFAULT_ADDR_COMP 0
>
> #define TRCSSCSRn_PC BIT(3)
> +#define TRCSSCSRn_DV BIT(2)
> +#define TRCSSCSRn_DA BIT(1)
> +#define TRCSSCSRn_INST BIT(0)
>
> /* PowerDown Control Register bits */
> #define TRCPDCR_PU BIT(3)
> @@ -861,6 +865,7 @@ enum etm_impdef_type {
> * @lpoverride: If the implementation can support low-power state over.
> * @skip_power_up: Indicates if an implementation can skip powering up
> * the trace unit.
> + * @ss_cmp: Indicates supported single-shot comparators.
> */
> struct etmv4_caps {
> u8 nr_pe;
> @@ -899,6 +904,7 @@ struct etmv4_caps {
> bool atbtrig : 1;
> bool lpoverride : 1;
> bool skip_power_up : 1;
> + u32 ss_cmp[ETM_MAX_SS_CMP];
> };
>
> /**
> @@ -977,7 +983,6 @@ struct etmv4_config {
> u32 res_ctrl[ETM_MAX_RES_SEL]; /* TRCRSCTLRn */
> u8 ss_idx;
> u32 ss_ctrl[ETM_MAX_SS_CMP];
> - u32 ss_status[ETM_MAX_SS_CMP];
> u32 ss_pe_cmp[ETM_MAX_SS_CMP];
> u8 addr_idx;
> u64 addr_val[ETM_MAX_SINGLE_ADDR_CMP];
^ permalink raw reply
* Re: [PATCH v8 08/10] ASoC: mediatek: mt8196: add platform driver
From: Cyril Chao (钞悦) @ 2026-04-16 5:53 UTC (permalink / raw)
To: broonie@kernel.org
Cc: linux-kernel@vger.kernel.org, linux-mediatek@lists.infradead.org,
devicetree@vger.kernel.org, Darren Ye (叶飞),
linux-sound@vger.kernel.org, conor+dt@kernel.org, tiwai@suse.com,
robh@kernel.org, lgirdwood@gmail.com,
linux-arm-kernel@lists.infradead.org,
Project_Global_Chrome_Upstream_Group, matthias.bgg@gmail.com,
krzk+dt@kernel.org, perex@perex.cz, AngeloGioacchino Del Regno
In-Reply-To: <892468cc-7eb4-411e-b91b-f14789d8da0c@sirena.org.uk>
Thank you for your assistance in reviewing. Could you please also
review the modifications in the diff? If everything is okay, I will
include them in v9 in the next update.
diff --git a/sound/soc/mediatek/mt8196/mt8196-afe-pcm.c
b/sound/soc/mediatek/mt8196/mt8196-afe-pcm.c
index 3d3174cd8efb..ff7aa89e4779 100644
--- a/sound/soc/mediatek/mt8196/mt8196-afe-pcm.c
+++ b/sound/soc/mediatek/mt8196/mt8196-afe-pcm.c
@@ -90,9 +90,20 @@ static int mt8196_set_cm(struct mtk_base_afe *afe,
int id,
struct mt8196_afe_private *afe_priv = afe->platform_priv;
unsigned int rate = afe_priv->cm_rate[id];
unsigned int rate_val = mt8196_rate_transform(afe->dev, rate);
- unsigned int update_val = update ? ((((26000000 / rate) - 10) /
(ch / 2)) - 1) : 0x64;
+ unsigned int ch_pair = ch / 2;
+ unsigned int update_val;
int reg = AFE_CM0_CON0 + 0x10 * id;
+ if (update) {
+ if (ch_pair == 0) {
+ dev_err(afe->dev, "CM%d: invalid channel count
%u\n", id, ch);
+ return -EINVAL;
+ }
+ update_val = (26000000 / rate - 10) / ch_pair - 1;
+ } else {
+ update_val = 0x64;
+ }
+
dev_dbg(afe->dev, "CM%d, rate %d, update %d, swap %d, ch %d\n",
id, rate, update, swap, ch);
@@ -471,6 +482,7 @@ static int ul_cm0_event(struct snd_soc_dapm_widget
*w,
struct mtk_base_afe *afe =
snd_soc_component_get_drvdata(cmpnt);
struct mt8196_afe_private *afe_priv = afe->platform_priv;
unsigned int channels = afe_priv->cm_channels;
+ int ret;
dev_dbg(afe->dev, "event 0x%x, name %s, channels %u\n",
event, w->name, channels);
@@ -478,7 +490,9 @@ static int ul_cm0_event(struct snd_soc_dapm_widget
*w,
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
mt8196_enable_cm_bypass(afe, CM0, false);
- mt8196_set_cm(afe, CM0, true, false, channels);
+ ret = mt8196_set_cm(afe, CM0, true, false, channels);
+ if (ret)
+ return ret;
regmap_update_bits(afe->regmap, AUDIO_TOP_CON0,
PDN_CM0_MASK_SFT, 0 << PDN_CM0_SFT);
break;
@@ -502,6 +516,7 @@ static int ul_cm1_event(struct snd_soc_dapm_widget
*w,
struct mtk_base_afe *afe =
snd_soc_component_get_drvdata(cmpnt);
struct mt8196_afe_private *afe_priv = afe->platform_priv;
unsigned int channels = afe_priv->cm_channels;
+ int ret;
dev_dbg(afe->dev, "event 0x%x, name %s, channels %u\n",
event, w->name, channels);
@@ -509,7 +524,9 @@ static int ul_cm1_event(struct snd_soc_dapm_widget
*w,
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
mt8196_enable_cm_bypass(afe, CM1, false);
- mt8196_set_cm(afe, CM1, true, false, channels);
+ ret = mt8196_set_cm(afe, CM1, true, false, channels);
+ if (ret)
+ return ret;
regmap_update_bits(afe->regmap, AUDIO_TOP_CON0,
PDN_CM1_MASK_SFT, 0 << PDN_CM1_SFT);
break;
@@ -533,6 +550,7 @@ static int ul_cm2_event(struct snd_soc_dapm_widget
*w,
struct mtk_base_afe *afe =
snd_soc_component_get_drvdata(cmpnt);
struct mt8196_afe_private *afe_priv = afe->platform_priv;
unsigned int channels = afe_priv->cm_channels;
+ int ret;
dev_dbg(afe->dev, "event 0x%x, name %s, channels %u\n",
event, w->name, channels);
@@ -540,7 +558,9 @@ static int ul_cm2_event(struct snd_soc_dapm_widget
*w,
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
mt8196_enable_cm_bypass(afe, CM2, false);
- mt8196_set_cm(afe, CM2, true, false, channels);
+ ret = mt8196_set_cm(afe, CM2, true, false, channels);
+ if (ret)
+ return ret;
regmap_update_bits(afe->regmap, AUDIO_TOP_CON0,
PDN_CM2_MASK_SFT, 0 << PDN_CM2_SFT);
break;
Best Regards
Cyril Chao
On Fri, 2026-04-03 at 15:07 +0100, Mark Brown wrote:
> On Tue, Mar 24, 2026 at 09:56:49AM +0800, Cyril Chao wrote:
>
> > +static int mt8196_set_cm(struct mtk_base_afe *afe, int id,
> > + bool update, bool swap, unsigned int ch)
> > +{
> > + struct mt8196_afe_private *afe_priv = afe->platform_priv;
> > + unsigned int rate = afe_priv->cm_rate[id];
> > + unsigned int rate_val = mt8196_rate_transform(afe->dev, rate);
> > + unsigned int update_val = update ? ((((26000000 / rate) - 10) /
> > (ch / 2)) - 1) : 0x64;
> > + int reg = AFE_CM0_CON0 + 0x10 * id;
>
> The driver looks like it supports mono so won't this trigger divide
> by
> zero?
>
> Also please write normal conditional statements, it's much more
> leigible.
^ permalink raw reply related
* Re: [PATCH v3] pmdomain: imx: Make IMX8M/IMX9 BLK_CTRL tristate
From: Daniel Baluta @ 2026-04-16 6:01 UTC (permalink / raw)
To: Zhipeng Wang, ulfh, Frank.Li, s.hauer
Cc: kernel, festevam, linux-pm, imx, linux-arm-kernel, linux-kernel,
xuegang.liu, jindong.yue
In-Reply-To: <20260416015605.3536244-1-zhipeng.wang_1@nxp.com>
On 4/16/26 04:56, Zhipeng Wang wrote:
> Convert IMX8M_BLK_CTRL and IMX9_BLK_CTRL from bool to tristate
> to allow building as loadable modules.
>
> Add prompt strings to make these options visible and configurable
> in menuconfig, keeping them enabled by default on appropriate platforms.
>
> Also remove the IMX_GPCV2_PM_DOMAINS dependency from IMX9_BLK_CTRL.
> This dependency was incorrect from the beginning because i.MX93 uses a
> different power domain architecture compared to i.MX8M series:
>
> - i.MX8M uses GPCv2 (General Power Controller v2) for power domain
> management, hence IMX8M_BLK_CTRL correctly depends on it.
>
> - i.MX93 uses BLK_CTRL directly without GPCv2. The hardware doesn't
> have GPCv2 at all.
>
> Signed-off-by: Zhipeng Wang <zhipeng.wang_1@nxp.com>
> Reviewed-by: Frank Li <Frank.Li@nxp.com>
>
> ---
Please always add a change log here to help reviewers.
Change since v2:
* fixed typo reported by Frank
^ permalink raw reply
* Re: [PATCH v2 2/3] dt-bindings: gpio: Add EIO GPIO compatible to gpio-zynq
From: Michal Simek @ 2026-04-16 5:58 UTC (permalink / raw)
To: Conor Dooley, Shubhrajyoti Datta
Cc: linux-kernel, git, shubhrajyoti.datta, Srinivas Neeli,
Linus Walleij, Bartosz Golaszewski, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, linux-gpio, devicetree,
linux-arm-kernel
In-Reply-To: <20260415-rectal-visible-a8ccb534a176@spud>
On 4/15/26 17:01, Conor Dooley wrote:
> On Wed, Apr 15, 2026 at 04:26:27PM +0530, Shubhrajyoti Datta wrote:
>> EIO (Extended IO) is a GPIO block found on xa2ve3288 silicon..
>
>
> Why does the compatible have a "1.0" when it is in silicon?
Sorry not following what the problem is. Yes this is hard block in silicon
and it is silicon v1.
> Why doesn't the compatible contain "xa2ve3288"?
This unit can be used on different silicons too.
> Why is this device not compatible with existing ones, since
> gpio-lines-names appears to be the sole difference?
There is no way how to detect gpio width.
Pretty much soc_device_match() to some extend could be use to detect which
silicon it runs but on this particular one you have 3 gpio controllers described
by this binding (pmc, versal and eio).
Thanks,
Michal
^ permalink raw reply
* Re: [EXT] Re: [PATCH v2] pmdomain: imx: Make IMX8M/IMX9 BLK_CTRL tristate
From: Daniel Baluta @ 2026-04-16 6:04 UTC (permalink / raw)
To: Zhipeng Wang, Marco Felsch
Cc: ulfh@kernel.org, Frank Li, s.hauer@pengutronix.de,
imx@lists.linux.dev, linux-pm@vger.kernel.org, Xuegang Liu,
Jindong Yue, linux-kernel@vger.kernel.org, kernel@pengutronix.de,
festevam@gmail.com, linux-arm-kernel@lists.infradead.org
In-Reply-To: <AMBPR04MB123344C1F802528A10CEA7FADEB252@AMBPR04MB12334.eurprd04.prod.outlook.com>
On 4/14/26 04:59, Zhipeng Wang wrote:
> > On 26-04-13, Zhipeng Wang wrote:
>>> Convert IMX8M_BLK_CTRL and IMX9_BLK_CTRL from bool to tristate to
>>> allow building as loadable modules.
>> Out of curiosity, why do you want to have a PM driver to be buildable as
>> module?
>>
>> Regards,
>> Marco
>>
> Hi Marco,
>
> Thank you for your question.
>
> The primary motivation is to support Google's GKI (Generic Kernel Image)
> requirement for Android devices.
>
> GKI separates the kernel into two parts:
> 1. A unified kernel image (GKI) that is common across all Android devices
> 2. Vendor-specific drivers that must be built as loadable modules
>
> Under the GKI architecture, SoC-specific drivers like IMX8M/IMX9 BLK_CTRL
> cannot be built into the core kernel image. Instead, they must be loadable
> modules that vendors can ship separately. This allows:
>
> - A single kernel binary to support multiple hardware platforms
> - Vendors to update their drivers independently without rebuilding the entire kernel
> - Better compliance with Android's kernel update and security policies
>
Can you please add the below line in the commit message?
> For i.MX8M/i.MX9 devices running Android with GKI kernels, the BLK_CTRL
> drivers need to be loaded as modules during boot. Without tristate support,
> these devices cannot properly initialize their power domains, making them
> non-functional under GKI.
^ permalink raw reply
* Re: [PATCH net-next 5/6] net: stmmac: move PHY handling out of __stmmac_open()/release()
From: Alexander Stein @ 2026-04-16 6:20 UTC (permalink / raw)
To: Russell King (Oracle)
Cc: Andrew Lunn, Heiner Kallweit, Alexandre Torgue, Andrew Lunn,
David S. Miller, Eric Dumazet, Jakub Kicinski, linux-arm-kernel,
linux-stm32, Maxime Coquelin, netdev, Paolo Abeni
In-Reply-To: <ad-LtOBrKREM1tCk@shell.armlinux.org.uk>
Am Mittwoch, 15. April 2026, 14:59:32 CEST schrieb Russell King (Oracle):
> On Wed, Apr 15, 2026 at 08:08:40AM +0200, Alexander Stein wrote:
> > Hi,
> >
> > Am Dienstag, 23. September 2025, 13:26:19 CEST schrieb Russell King (Oracle):
> > > Move the PHY attachment/detachment from the network driver out of
> > > __stmmac_open() and __stmmac_release() into stmmac_open() and
> > > stmmac_release() where these actions will only happen when the
> > > interface is administratively brought up or down. It does not make
> > > sense to detach and re-attach the PHY during a change of MTU.
> >
> > Sorry for coming up now. But I recently noticed this commit breaks changing
> > the MTU on i.MX8MP. Once I simply change the MTU I run into some DMA error:
> > $ ip link set dev end1 mtu 1400
> > imx-dwmac 30bf0000.ethernet end1: Register MEM_TYPE_PAGE_POOL RxQ-0
> > imx-dwmac 30bf0000.ethernet end1: Register MEM_TYPE_PAGE_POOL RxQ-1
> > imx-dwmac 30bf0000.ethernet end1: Register MEM_TYPE_PAGE_POOL RxQ-2
> > imx-dwmac 30bf0000.ethernet end1: Register MEM_TYPE_PAGE_POOL RxQ-3
> > imx-dwmac 30bf0000.ethernet end1: Register MEM_TYPE_PAGE_POOL RxQ-4
> > imx-dwmac 30bf0000.ethernet end1: Link is Down
> > imx-dwmac 30bf0000.ethernet end1: Failed to reset the dma
> > imx-dwmac 30bf0000.ethernet end1: stmmac_hw_setup: DMA engine initialization failed
>
> This basically means that a clock is missing. Please provide more
> information:
>
> - what kernel version are you using?
Currently I am using v6.18.22.
$ ethtool -i end1
driver: st_gmac
version: 6.18.22
firmware-version:
expansion-rom-version:
bus-info: 30bf0000.ethernet
supports-statistics: yes
supports-test: no
supports-eeprom-access: no
supports-register-dump: yes
supports-priv-flags: no
> - has EEE been negotiated?
No. It is marked as not supported
$ ethtool --show-eee end1
EEE settings for end1:
EEE status: not supported
> - does the problem persist when EEE is disabled?
As EEE is not supported the problem occurs even with EEE disabled.
> - which PHY is attached to stmmac?
It is a TI DP83867.
imx-dwmac 30bf0000.ethernet eth1: PHY [stmmac-1:03] driver [TI DP83867] (irq=136)
> - which PHY interface mode is being used to connect the PHY to stmmac?
For this interface
> phy-mode = "rgmii-id";
is set.
In case it is helpful. My platform is arch/arm64/boot/dts/freescale/imx8mp-tqma8mpql-mba8mpxl.dts
Thanks for assisting. If there a further questions, don't hesitate to ask.
Thanks and best regards
Alexander
--
TQ-Systems GmbH | Mühlstraße 2, Gut Delling | 82229 Seefeld, Germany
Amtsgericht München, HRB 105018
Geschäftsführer: Detlef Schneider, Rüdiger Stahl, Stefan Schneider
http://www.tq-group.com/
^ permalink raw reply
* Re: [PATCH v3 3/3] dt-bindings: i3c: Add AST2600 I3C global registers
From: Krzysztof Kozlowski @ 2026-04-16 6:21 UTC (permalink / raw)
To: Dawid Glazik
Cc: Alexandre Belloni, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Joel Stanley, Andrew Jeffery, linux-aspeed, linux-i3c, devicetree,
linux-arm-kernel, Frank Li, Maciej Lawniczak
In-Reply-To: <cb0d16bf-988d-403e-8a8e-c85bf2a208d0@linux.intel.com>
On 15/04/2026 20:21, Dawid Glazik wrote:
> On 4/9/2026 9:30 AM, Krzysztof Kozlowski wrote:
>> On 09/04/2026 09:28, Krzysztof Kozlowski wrote:
>>> On Wed, Apr 08, 2026 at 10:34:35PM +0200, Dawid Glazik wrote:
>>>> Introduce the device-tree bindings for I3C global registers found on
>>>> AST2600 SoCs.
>>>>
>>>> Signed-off-by: Dawid Glazik <dawid.glazik@linux.intel.com>
>>>> ---
>>>> I wasn't sure if I should add newline at the end of the
>>>> file or not so I took
>>>> https://github.com/torvalds/linux/tree/master/Documentation/devicetree/bindings/i3c
>>>> as an example.
>>>
>>> Answer is: you cannot have patch warnings.
>>>
>>> Documentation/devicetree/bindings/i3c does not have patch warning, does
>>> it?
>>
>> And if you tested this code with standard tools, you would see that...
>>
>> Best regards,
>> Krzysztof
>
> Thank you for the review and feedback. This is my first contribution to
> Linux kernel so I'm still learning the process and toolchain. I
> apologize for the rookie mistakes. I will address all the issues you've
> pointed out and resubmit the series.
So get the patch reviewed by Intel colleagues which would tell you what
tools you must run and what warnings are accepted or not (and patch
warning is never accepted).
Best regards,
Krzysztof
^ permalink raw reply
* Re: [PATCH v8 next 00/10] arm_mpam: Introduce Narrow-PARTID feature
From: Shaopeng Tan (Fujitsu) @ 2026-04-16 6:29 UTC (permalink / raw)
To: ben.horgan@arm.com, Dave.Martin@arm.com, james.morse@arm.com,
reinette.chatre@intel.com, fenghuay@nvidia.com, tglx@kernel.org,
will@kernel.org, hpa@zytor.com, bp@alien8.de, babu.moger@amd.com,
dave.hansen@linux.intel.com, mingo@redhat.com,
tony.luck@intel.com, gshan@redhat.com, catalin.marinas@arm.com
Cc: linux-arm-kernel@lists.infradead.org, x86@kernel.org,
linux-kernel@vger.kernel.org, wangkefeng.wang@huawei.com
In-Reply-To: <20260413085405.1166412-1-zengheng4@huawei.com>
Hello Zeng Heng,
Could you tell me which branch this patch series based on?
Best regards,
Shaopent TAN
^ permalink raw reply
* Re: [PATCH] arm_pmu: acpi: fix reference leak on failed device registration
From: Guangshuo Li @ 2026-04-16 6:34 UTC (permalink / raw)
To: Greg Kroah-Hartman
Cc: Mark Rutland, Will Deacon, Anshuman Khandual, linux-arm-kernel,
linux-perf-users, linux-kernel, stable
In-Reply-To: <2026041603-guts-crested-ef76@gregkh>
Hi Mark, Greg,
Thanks for the feedback.
On Thu, 16 Apr 2026 at 12:41, Greg Kroah-Hartman
<gregkh@linuxfoundation.org> wrote:
>
> On Wed, Apr 15, 2026 at 07:19:06PM +0100, Mark Rutland wrote:
> > Hi,
> >
> > Thanks for the patch, but from a quick skim, I don't think this is the right
> > fix.
> >
> > Greg, I think we might want to rework the core API here; question for
> > you at the end.
> >
> > On Thu, Apr 16, 2026 at 01:41:59AM +0800, Guangshuo Li wrote:
> > > When platform_device_register() fails in arm_acpi_register_pmu_device(),
> > > the embedded struct device in pdev has already been initialized by
> > > device_initialize(), but the failure path only unregisters the GSI and
> > > does not drop the device reference for the current platform device:
> > >
> > > arm_acpi_register_pmu_device()
> > > -> platform_device_register(pdev)
> > > -> device_initialize(&pdev->dev)
> > > -> setup_pdev_dma_masks(pdev)
> > > -> platform_device_add(pdev)
> > >
> > > This leads to a reference leak when platform_device_register() fails.
> >
> > AFAICT you're saying that the reference was taken *within*
> > platform_device_register(), and then platform_device_register() itself
> > has failed. I think it's surprising that platform_device_register()
> > doesn't clean that up itself in the case of an error.
> >
> > There are *tonnes* of calls to platform_device_register() throughout the
> > kernel that don't even bother to check the return value, and many that
> > just pass the return onto a caller that can't possibly know to call
> > platform_device_put().
> >
> > Code in the same file as platform_device_register() expects it to clean up
> > after itself, e.g.
> >
> > | int platform_add_devices(struct platform_device **devs, int num)
> > | {
> > | int i, ret = 0;
> > |
> > | for (i = 0; i < num; i++) {
> > | ret = platform_device_register(devs[i]);
> > | if (ret) {
> > | while (--i >= 0)
> > | platform_device_unregister(devs[i]);
> > | break;
> > | }
> > | }
> > |
> > | return ret;
> > | }
> >
> > That's been there since the initial git commit, and back then,
> > platform_device_register() didn't mention that callers needed to perform
> > any cleanup.
> >
> > I see a comment was added to platform_device_register() in commit:
> >
> > 67e532a42cf4 ("driver core: platform: document registration-failure requirement")
> >
> > ... and that copied the commend added for device_register() in commit:
> >
> > 5739411acbaa ("Driver core: Clarify device cleanup.")
> >
> > ... but the potential brokenness is so widespread, and the behaviour is
> > so surprising, that I'd argue the real but is that device_register()
> > doesn't clean up in case of error. I don't think it's worth changing
> > this single instance given the prevalance and churn fixing all of that
> > would involve.
> >
> > I think it would be far better to fix the core driver API such that when
> > those functions return an error, they've already cleaned up for
> > themselves.
> >
> > Greg, am I missing some functional reason why we can't rework
> > device_register() and friends to handle cleanup themselves? I appreciate
> > that'll involve churn for some callers, but AFAICT the majority of
> > callers don't have the required cleanup.
>
> Yes, we should fix the platform core code here, this should not be
> required to do everywhere as obviously we all got it wrong.
>
> Guangshuo, can you submit a patch to do that instead and ask for all of
> your other patches to not be applied as well?
>
> thanks,
>
> greg k-h
I agree that fixing this in the platform core makes more sense than
handling it in individual callers.
I'll look into the core code and send a patch for that instead. I'll
also ask for my other related patches not to be applied.
Thanks,
Guangshuo
^ permalink raw reply
* Re: [PATCH 0/7] TQMLX2160A-MBLS2160A DT fixes/updates
From: Alexander Stein @ 2026-04-16 6:39 UTC (permalink / raw)
To: Frank Li, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Shawn Guo
Cc: linux-arm-kernel, linux, devicetree, linux-kernel, Nora Schiffer
In-Reply-To: <20260331141915.2918927-1-alexander.stein@ew.tq-group.com>
Hi Frank,
Am Dienstag, 31. März 2026, 16:19:01 CEST schrieb Alexander Stein:
> Hi,
>
> this series adds small fixes and improvements for TQMLX2160A DTs.
> The DT overlays address specific hardware behaviour when serdes is configured
> differently.
Any feedback here?
Thanks and best regards
Alexander
>
> Best regards,
> Alexander
>
> Alexander Stein (1):
> arm64: dts: fsl-lx2160a-tqmlx2160a: Remove deprecated properties
>
> Nora Schiffer (6):
> arm64: dts: fsl-lx2160a-tqmlx2160a: fix LED polarity
> arm64: dts: fsl-lx2160a-tqmlx2160a-mblx2160a: use DPMAC 17 and 18 for
> SGMII in SERDES2 configs 7 and 11
> arm64: dts: fsl-lx2160a-tqmlx2160a: add aliases for all 18 DPMAC
> instances
> arm64: dts: fsl-lx2160a-tqmlx2160a-mbls2160a: add various GPIO hogs
> arm64: dts: fsl-lx2160a-tqmlx2160a-mbls2160a: enable pcs_mdio17 and
> pcs_mdio18 in appropriate overlays
> arm64: dts: fsl-lx2160a-tqmlx2160a-mbls2160a: specify Ethernet PHY
> reset GPIOs
>
> .../fsl-lx2160a-tqmlx2160a-mblx2160a.dts | 306 +++++++++++++++++-
> ...l-lx2160a-tqmlx2160a-mblx2160a_x_11_x.dtso | 20 ++
> ...sl-lx2160a-tqmlx2160a-mblx2160a_x_7_x.dtso | 20 ++
> .../dts/freescale/fsl-lx2160a-tqmlx2160a.dtsi | 23 +-
> 4 files changed, 357 insertions(+), 12 deletions(-)
>
>
--
TQ-Systems GmbH | Mühlstraße 2, Gut Delling | 82229 Seefeld, Germany
Amtsgericht München, HRB 105018
Geschäftsführer: Detlef Schneider, Rüdiger Stahl, Stefan Schneider
http://www.tq-group.com/
^ permalink raw reply
* Re: [PATCH] arm64: cpufeature: Fix GCIE field ordering in ftr_id_aa64pfr2
From: Marc Zyngier @ 2026-04-16 6:42 UTC (permalink / raw)
To: Mukesh Ojha; +Cc: Catalin Marinas, Will Deacon, linux-arm-kernel, linux-kernel
In-Reply-To: <20260415200031.1885440-1-mukesh.ojha@oss.qualcomm.com>
On Wed, 15 Apr 2026 21:00:31 +0100,
Mukesh Ojha <mukesh.ojha@oss.qualcomm.com> wrote:
>
> The ftr_id_aa64pfr2[] array must be sorted in descending order of
> shift value so that the overlap validation in init_cpu_features()
> works correctly. The GCIE field (bits 15:12, shift=12) was placed
> last in the array, after MTEFAR (bits 11:8, shift=8) and
> MTESTOREONLY (bits 7:4, shift=4), causing a spurious warning at
> boot:
>
> [ 0.000000] SYS_ID_AA64PFR2_EL1 has feature overlap at shift 12
> [ 0.000000] WARNING: arch/arm64/kernel/cpufeature.c:989 at init_cpu_features+0x144/0x3d0, CPU#0:
> swapper/0
> ..
>
> [ 0.000000] pc : init_cpu_features+0x144/0x3d0
> [ 0.000000] lr : init_cpu_features+0x144/0x3d0
> [ 0.000000] sp : ffffc08678f03dc0
>
> ...
> 0.000000] x2 : 0000000000000000 x1 : 0000000000000000 x0 : ffffc08678f14000
> [ 0.000000] Call trace:
> [ 0.000000] init_cpu_features+0x144/0x3d0 (P)
> [ 0.000000] cpuinfo_store_boot_cpu+0x4c/0x5c
> [ 0.000000] smp_prepare_boot_cpu+0x28/0x38
> [ 0.000000] start_kernel+0x1d4/0x848
> [ 0.000000] __primary_switched+0x88/0x90
>
> This is because the overlap check computes (shift + width) > prev_shift,
> i.e. (12 + 4) > 8, which triggers since GCIE occupies bits above MTEFAR
> but was listed after it.
>
> Fix the ordering to match the register layout: FPMR(35:32), GCIE(15:12),
> MTEFAR(11:8), MTESTOREONLY(7:4).
>
> Fixes: 899ff451fcee ("KVM: arm64: Advertise ID_AA64PFR2_EL1.GCIE")
> Signed-off-by: Mukesh Ojha <mukesh.ojha@oss.qualcomm.com>
This was present in next-20260403, identified the following day, a fix
proposed in [1], and the fixed commit appeared in next-20260407 (which
was the subsequent -next build) as 7e629348df81b.
May I humbly suggest that you check with the latest -next branch
before spending time on this sort of things? Two weeks is a pretty
long time...
Thanks,
M.
[1] https://lore.kernel.org/all/874ilqcu3c.wl-maz@kernel.org/
--
Without deviation from the norm, progress is not possible.
^ permalink raw reply
* Re: [PATCH v5 07/12] coresight: etm4x: fix inconsistencies with sysfs configuration
From: Yeoreum Yun @ 2026-04-16 6:49 UTC (permalink / raw)
To: Jie Gan
Cc: coresight, linux-arm-kernel, linux-kernel, suzuki.poulose,
mike.leach, james.clark, alexander.shishkin, leo.yan
In-Reply-To: <b9528488-b0c7-410b-b91b-b05c21fd0c08@oss.qualcomm.com>
Hi Jie,
>
>
> On 4/16/2026 12:55 AM, Yeoreum Yun wrote:
> > The current ETM4x configuration via sysfs can lead to
> > several inconsistencies:
> >
> > - If the configuration is modified via sysfs while a perf session is
> > active, the running configuration may differ before a sched-out and
> > after a subsequent sched-in.
> >
> > - If a perf session and a sysfs session enable tracing concurrently,
> > the configuration from configfs may become corrupted.
> >
> > - There is a risk of corrupting drvdata->config if a perf session enables
> > tracing while cscfg_csdev_disable_active_config() is being handled in
> > etm4_disable_sysfs().
> >
> > To resolve these issues, separate the configuration into:
> >
> > - active_config: the configuration applied to the current session
> > - config: the configuration set via sysfs
> >
> > Additionally:
> >
> > - Apply the configuration from configfs after taking the appropriate mode.
> >
> > - Since active_config and related fields are accessed only by the local CPU
> > in etm4_enable/disable_sysfs_smp_call() (similar to perf enable/disable),
> > remove the lock/unlock from the sysfs enable/disable path and
> > startup/dying_cpu except when to access config fields.
> >
> > Signed-off-by: Yeoreum Yun <yeoreum.yun@arm.com>
> > ---
>
> <...>
>
> > @@ -618,23 +624,45 @@ static int etm4_enable_hw(struct etmv4_drvdata *drvdata)
> > static void etm4_enable_sysfs_smp_call(void *info)
> > {
> > struct etm4_enable_arg *arg = info;
> > + struct etmv4_drvdata *drvdata;
> > struct coresight_device *csdev;
> > if (WARN_ON(!arg))
> > return;
> > - csdev = arg->drvdata->csdev;
> > + drvdata = arg->drvdata;
> > + csdev = drvdata->csdev;
> > if (!coresight_take_mode(csdev, CS_MODE_SYSFS)) {
> > /* Someone is already using the tracer */
> > arg->rc = -EBUSY;
> > return;
> > }
> > - arg->rc = etm4_enable_hw(arg->drvdata);
> > + drvdata->active_config = arg->config;
> > - /* The tracer didn't start */
> > + if (arg->cfg_hash) {
> > + arg->rc = cscfg_csdev_enable_active_config(csdev,
> > + arg->cfg_hash,
> > + arg->preset);
> > + if (arg->rc)
> > + goto err;
> > + }
> > +
> > + drvdata->trcid = arg->trace_id;
> > +
> > + /* Tracer will never be paused in sysfs mode */
> > + drvdata->paused = false;
> > +
> > + arg->rc = etm4_enable_hw(drvdata);
> > if (arg->rc)
> > - coresight_set_mode(csdev, CS_MODE_DISABLED);
>
> needs disable the active config in error path:
> cscfg_csdev_disable_active_config(drvdata->csdev);
You're right. I missed it. Thanks!
[...]
--
Sincerely,
Yeoreum Yun
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox