[PATCH v3] ASoC: loongson: Fix invalid position error in ls_pcm_pointer

Li Jun posted 1 patch 6 days, 1 hour ago
sound/soc/loongson/loongson_dma.c | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
[PATCH v3] ASoC: loongson: Fix invalid position error in ls_pcm_pointer
Posted by Li Jun 6 days, 1 hour ago
The "invalid position" error occurred when the DMA position descriptor
returned an invalid address value (e.g., pos = -1048838144). This happened
because the `bytes_to_frames()` function returns a signed value, but when
`addr < runtime->dma_addr`, the subtraction produces a negative result that
gets interpreted as a large unsigned integer in comparisons.
when the addr is abnormal, for example,the DMA controller is abnormal in
hardware,x=0 should not be a point(x == runtime->buffer_size),but a range,
which includes the addr address being less than runtime ->dma1-adr, and
the addr exceeding the DMA address range.the value of pos should not better
a negative,return 0, maybe better.

[   32.834431][ 2]  soc-audio soc-audio: invalid position: , pos = -1048838144
[   32.845019][ 2]  soc-audio soc-audio: invalid position: , pos = -1048838144
[   32.855588][ 2]  soc-audio soc-audio: invalid position: , pos = -1048838144
[   32.866145][ 2]  soc-audio soc-audio: invalid position: , pos = -1048838144
[   32.995394][ 2]  soc-audio soc-audio: invalid position: , pos = -1048838144
[   33.006025][ 2]  soc-audio soc-audio: invalid position: , pos = -1048838144
[   33.016748][ 2]  soc-audio soc-audio: invalid position: , pos = -1048838144

Signed-off-by: Li Jun <lijun01@kylinos.cn>
---
 sound/soc/loongson/loongson_dma.c | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/sound/soc/loongson/loongson_dma.c b/sound/soc/loongson/loongson_dma.c
index a149b643175c..281bc991b110 100644
--- a/sound/soc/loongson/loongson_dma.c
+++ b/sound/soc/loongson/loongson_dma.c
@@ -199,6 +199,7 @@ loongson_pcm_pointer(struct snd_soc_component *component,
 		     struct snd_pcm_substream *substream)
 {
 	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct device *dev = substream->pcm->card->dev;
 	struct loongson_runtime_data *prtd = runtime->private_data;
 	struct loongson_dma_desc *desc;
 	snd_pcm_uframes_t x;
@@ -207,9 +208,16 @@ loongson_pcm_pointer(struct snd_soc_component *component,
 	desc = dma_desc_save(prtd);
 	addr = ((u64)desc->saddr_hi << 32) | desc->saddr;
 
-	x = bytes_to_frames(runtime, addr - runtime->dma_addr);
-	if (x == runtime->buffer_size)
+	if (addr < runtime->dma_addr ||
+	    addr > runtime->dma_addr + runtime->dma_bytes) {
+		dev_warn(dev, "WARNING! dma_addr:0x%x\n", addr);
 		x = 0;
+	} else {
+		x = bytes_to_frames(runtime, addr - runtime->dma_addr);
+		if (x == runtime->buffer_size)
+			x = 0;
+	}
+
 	return x;
 }
 
-- 
2.25.1