]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
firmware: samsung: acpm: Fix mailbox channel leak on probe error
authorTudor Ambarus <tudor.ambarus@linaro.org>
Tue, 5 May 2026 13:12:59 +0000 (13:12 +0000)
committerKrzysztof Kozlowski <krzk@kernel.org>
Thu, 14 May 2026 16:54:58 +0000 (18:54 +0200)
Sashiko identified the leak at [1].

The ACPM driver allocates hardware mailbox channels using
`mbox_request_channel()` during `acpm_channels_init()`. However, the
driver lacked a `.remove` callback and did not free these channels on
subsequent error paths inside `acpm_probe()`.

Additionally, if `acpm_achan_alloc_cmds()` failed during the channel
initialization loop, the function returned immediately, bypassing the
manual cleanup and permanently leaking any channels successfully
requested in previous loop iterations.

Fix this by modifying `acpm_free_mbox_chans()` to match the `devres`
action signature and registering it via `devm_add_action_or_reset()`.

Cc: stable@vger.kernel.org
Fixes: a88927b534ba ("firmware: add Exynos ACPM protocol driver")
Closes: https://sashiko.dev/#/patchset/20260420-acpm-tmu-v3-0-3dc8e93f0b26%40linaro.org [1]
Signed-off-by: Tudor Ambarus <tudor.ambarus@linaro.org>
Link: https://patch.msgid.link/20260505-acpm-fixes-sashiko-reports-v5-2-43b5ee7f1674@linaro.org
Signed-off-by: Krzysztof Kozlowski <krzk@kernel.org>
drivers/firmware/samsung/exynos-acpm.c

index e95edc350efa6c5607325dc4d324653a1aa7853f..9766425a44aba3445219791b1accaebc7e5bb652 100644 (file)
@@ -527,10 +527,11 @@ static int acpm_achan_alloc_cmds(struct acpm_chan *achan)
 
 /**
  * acpm_free_mbox_chans() - free mailbox channels.
- * @acpm:      pointer to driver data.
+ * @data:      pointer to driver data.
  */
-static void acpm_free_mbox_chans(struct acpm_info *acpm)
+static void acpm_free_mbox_chans(void *data)
 {
+       struct acpm_info *acpm = data;
        int i;
 
        for (i = 0; i < acpm->num_chans; i++)
@@ -558,6 +559,10 @@ static int acpm_channels_init(struct acpm_info *acpm)
        if (!acpm->chans)
                return -ENOMEM;
 
+       ret = devm_add_action_or_reset(dev, acpm_free_mbox_chans, acpm);
+       if (ret)
+               return dev_err_probe(dev, ret, "Failed to add mbox free action.\n");
+
        chans_shmem = acpm->sram_base + readl(&shmem->chans);
 
        for (i = 0; i < acpm->num_chans; i++) {
@@ -579,10 +584,8 @@ static int acpm_channels_init(struct acpm_info *acpm)
                cl->dev = dev;
 
                achan->chan = mbox_request_channel(cl, 0);
-               if (IS_ERR(achan->chan)) {
-                       acpm_free_mbox_chans(acpm);
+               if (IS_ERR(achan->chan))
                        return PTR_ERR(achan->chan);
-               }
        }
 
        return 0;