]> git.hungrycats.org Git - linux/commitdiff
ASoC: soc-generic-dmaengine: Handle DMA channel request failures correctly
authorbui duc phuc <phucduc.bui@gmail.com>
Mon, 20 Jul 2026 06:41:31 +0000 (13:41 +0700)
committerMark Brown <broonie@kernel.org>
Tue, 28 Jul 2026 18:38:32 +0000 (19:38 +0100)
Currently any dma_request_chan() failure other than -EPROBE_DEFER is
silently ignored, since a missing channel is expected for devices that
only support one DMA direction.

Improve the handling of these failures by:
- reporting failures when a configured DMA channel cannot be requested;
- failing probe if neither playback nor capture obtains a DMA channel,
  since the PCM device would be unusable.

Devices that legitimately support only one DMA direction continue to
work as before.

Signed-off-by: bui duc phuc <phucduc.bui@gmail.com>
Link: https://patch.msgid.link/20260720064131.75156-1-phucduc.bui@gmail.com
Signed-off-by: Mark Brown <broonie@kernel.org>
sound/soc/soc-generic-dmaengine-pcm.c

index 467426d2b5e4e08658c5e5e11dda7a0b263d9e44..98ba9a836936076a07560b9bbe2f0bcb202fcaa0 100644 (file)
@@ -3,6 +3,7 @@
 //  Copyright (C) 2013, Analog Devices Inc.
 //     Author: Lars-Peter Clausen <lars@metafoo.de>
 
+#include <linux/acpi.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/dmaengine.h>
@@ -395,6 +396,27 @@ static int dmaengine_pcm_request_chan_of(struct dmaengine_pcm *pcm,
                         */
                        if (PTR_ERR(chan) == -EPROBE_DEFER)
                                return -EPROBE_DEFER;
+
+                       bool has_fw_node = dev->of_node || is_acpi_device_node(dev->fwnode);
+                       bool name_exists_in_fw = false;
+
+                       if (has_fw_node)
+                               name_exists_in_fw = device_property_match_string(dev,
+                                                                                "dma-names",
+                                                                                name) >= 0;
+
+                       if (has_fw_node && name_exists_in_fw)
+                               dev_warn(dev, "DTS/ACPI DMA channel '%s' request failed (%ld)\n",
+                                        name, PTR_ERR(chan));
+
+                       if (has_fw_node && !name_exists_in_fw)
+                               dev_warn(dev, "DTS/ACPI name '%s' not found, legacy failed (%ld)\n",
+                                        name, PTR_ERR(chan));
+
+                       if (!has_fw_node)
+                               dev_warn(dev, "Legacy DMA channel '%s' request failed (%ld)\n",
+                                        name, PTR_ERR(chan));
+
                        pcm->chan[i] = NULL;
                } else {
                        pcm->chan[i] = chan;
@@ -406,6 +428,12 @@ static int dmaengine_pcm_request_chan_of(struct dmaengine_pcm *pcm,
        if (pcm->flags & SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX)
                pcm->chan[1] = pcm->chan[0];
 
+       if (!pcm->chan[0] &&
+           !pcm->chan[1]) {
+               dev_err(dev, "no DMA channel found for either playback or capture\n");
+               return -ENODEV;
+       }
+
        return 0;
 }