[PATCH v4 1/2] mfd: loongson-se: Fix miscellaneous issues

From: Qunqin Zhao

Date: Mon Jun 29 2026 - 03:30:16 EST


Address multiple historical driver issues discovered by the Sashiko
Automation system within the loongson_se_probe() initialization flow
and the driver's interrupt service routines [1].

- Add an explicit bounds check for 'id' before accessing the fixed-size
'engines' array in se_irq_handler() to prevent potential out-of-bounds
memory writes.

- Switch the allocations from devm_kmalloc() to devm_kzalloc() to
guarantee the descriptor structures are properly zero-initialized.

- Return an error code from loongson_se_probe() if devm_request_irq()
fails, preventing an indefinite hang during completion waits.

- Add a reinit_completion() before waiting on the completions to ensure
proper hardware synchronization.

- Prevent writing uninitialized stack memory to device registers in
loongson_se_init() by properly initializing local command structures.

- Add a .remove callback to the platform driver to properly halt the
hardware.

Link: https://lore.kernel.org/all/20260618095949.GB1672911@xxxxxxxxxx/ [1]
Fixes: e551fa3159e3 ("mfd: Add support for Loongson Security Engine chip controller")
Signed-off-by: Qunqin Zhao <zhaoqunqin@xxxxxxxxxxx>
---
drivers/mfd/loongson-se.c | 23 +++++++++++++++++++----
include/linux/mfd/loongson-se.h | 1 +
2 files changed, 20 insertions(+), 4 deletions(-)

diff --git a/drivers/mfd/loongson-se.c b/drivers/mfd/loongson-se.c
index 3902ba377d..aa34e663c4 100644
--- a/drivers/mfd/loongson-se.c
+++ b/drivers/mfd/loongson-se.c
@@ -85,6 +85,8 @@ int loongson_se_send_engine_cmd(struct loongson_se_engine *engine)
if (err)
return err;

+ reinit_completion(&engine->completion);
+
return wait_for_completion_interruptible(&engine->completion);
}
EXPORT_SYMBOL_GPL(loongson_se_send_engine_cmd);
@@ -150,7 +152,8 @@ static irqreturn_t se_irq_handler(int irq, void *dev_id)
/* For engines */
while (int_status) {
id = __ffs(int_status);
- complete(&se->engines[id].completion);
+ if (id < SE_ENGINE_MAX)
+ complete(&se->engines[id].completion);
int_status &= ~BIT(id);
writel(BIT(id), se->base + SE_S2LINT_CL);
}
@@ -162,7 +165,7 @@ static irqreturn_t se_irq_handler(int irq, void *dev_id)

static int loongson_se_init(struct loongson_se *se, dma_addr_t addr, int size)
{
- struct loongson_se_controller_cmd cmd;
+ struct loongson_se_controller_cmd cmd = {0};
int err;

cmd.command_id = SE_CMD_START;
@@ -190,7 +193,7 @@ static int loongson_se_probe(struct platform_device *pdev)
int nr_irq, irq, err, i;
dma_addr_t paddr;

- se = devm_kmalloc(dev, sizeof(*se), GFP_KERNEL);
+ se = devm_kzalloc(dev, sizeof(*se), GFP_KERNEL);
if (!se)
return -ENOMEM;

@@ -220,8 +223,10 @@ static int loongson_se_probe(struct platform_device *pdev)
for (i = 0; i < nr_irq; i++) {
irq = platform_get_irq(pdev, i);
err = devm_request_irq(dev, irq, se_irq_handler, 0, "loongson-se", se);
- if (err)
+ if (err) {
dev_err(dev, "failed to request IRQ: %d\n", irq);
+ return err;
+ }
}

err = loongson_se_init(se, paddr, se->dmam_size);
@@ -232,6 +237,15 @@ static int loongson_se_probe(struct platform_device *pdev)
ARRAY_SIZE(engines), NULL, 0, NULL);
}

+static void loongson_se_remove(struct platform_device *pdev)
+{
+ struct loongson_se *se = dev_get_drvdata(&pdev->dev);
+ struct loongson_se_controller_cmd cmd = {0};
+
+ cmd.command_id = SE_CMD_STOP;
+ loongson_se_send_controller_cmd(se, &cmd);
+}
+
static const struct acpi_device_id loongson_se_acpi_match[] = {
{ "LOON0011", 0 },
{ }
@@ -240,6 +254,7 @@ MODULE_DEVICE_TABLE(acpi, loongson_se_acpi_match);

static struct platform_driver loongson_se_driver = {
.probe = loongson_se_probe,
+ .remove = loongson_se_remove,
.driver = {
.name = "loongson-se",
.acpi_match_table = loongson_se_acpi_match,
diff --git a/include/linux/mfd/loongson-se.h b/include/linux/mfd/loongson-se.h
index 07afa0c252..8237ccab7b 100644
--- a/include/linux/mfd/loongson-se.h
+++ b/include/linux/mfd/loongson-se.h
@@ -9,6 +9,7 @@
#define SE_SEND_CMD_REG_LEN 0x8
/* Controller command ID */
#define SE_CMD_START 0x0
+#define SE_CMD_STOP 0x1
#define SE_CMD_SET_DMA 0x3
#define SE_CMD_SET_ENGINE_CMDBUF 0x4

--
2.47.2