Skip to content

Commit 9736a32

Browse files
committed
ALSA: memalloc: Don't fall back for SG-buffer with IOMMU
When the non-contiguous page allocation for SG buffer allocation fails, the memalloc helper tries to fall back to the old page allocation methods. This would, however, result in the bogus page addresses when IOMMU is enabled. Usually in such a case, the fallback allocation should fail as well, but occasionally it succeeds and hitting a bad access. The fallback was thought for non-IOMMU case, and as the error from dma_alloc_noncontiguous() with IOMMU essentially implies a fatal memory allocation error, we should return the error straightforwardly without fallback. This avoids the corner case like the above. The patch also renames the local variable "dma_ops" with snd_ prefix for avoiding the name conflict. Fixes: a8d302a ("ALSA: memalloc: Revive x86-specific WC page allocations again") Reported-by: Kai Vehmanen <[email protected]> Reviewed-by: Kai Vehmanen <[email protected]> Link: https://lore.kernel.org/r/alpine.DEB.2.22.394.2211041541090.3532114@eliteleevi.tm.intel.com Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Takashi Iwai <[email protected]>
1 parent bf990c1 commit 9736a32

File tree

1 file changed

+11
-9
lines changed

1 file changed

+11
-9
lines changed

sound/core/memalloc.c

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <linux/slab.h>
1010
#include <linux/mm.h>
1111
#include <linux/dma-mapping.h>
12+
#include <linux/dma-map-ops.h>
1213
#include <linux/genalloc.h>
1314
#include <linux/highmem.h>
1415
#include <linux/vmalloc.h>
@@ -541,19 +542,20 @@ static void *snd_dma_noncontig_alloc(struct snd_dma_buffer *dmab, size_t size)
541542
struct sg_table *sgt;
542543
void *p;
543544

544-
sgt = dma_alloc_noncontiguous(dmab->dev.dev, size, dmab->dev.dir,
545-
DEFAULT_GFP, 0);
546-
if (!sgt) {
547545
#ifdef CONFIG_SND_DMA_SGBUF
546+
if (!get_dma_ops(dmab->dev.dev)) {
548547
if (dmab->dev.type == SNDRV_DMA_TYPE_DEV_WC_SG)
549548
dmab->dev.type = SNDRV_DMA_TYPE_DEV_WC_SG_FALLBACK;
550549
else
551550
dmab->dev.type = SNDRV_DMA_TYPE_DEV_SG_FALLBACK;
552551
return snd_dma_sg_fallback_alloc(dmab, size);
553-
#else
554-
return NULL;
555-
#endif
556552
}
553+
#endif
554+
555+
sgt = dma_alloc_noncontiguous(dmab->dev.dev, size, dmab->dev.dir,
556+
DEFAULT_GFP, 0);
557+
if (!sgt)
558+
return NULL;
557559

558560
dmab->dev.need_sync = dma_need_sync(dmab->dev.dev,
559561
sg_dma_address(sgt->sgl));
@@ -857,7 +859,7 @@ static const struct snd_malloc_ops snd_dma_noncoherent_ops = {
857859
/*
858860
* Entry points
859861
*/
860-
static const struct snd_malloc_ops *dma_ops[] = {
862+
static const struct snd_malloc_ops *snd_dma_ops[] = {
861863
[SNDRV_DMA_TYPE_CONTINUOUS] = &snd_dma_continuous_ops,
862864
[SNDRV_DMA_TYPE_VMALLOC] = &snd_dma_vmalloc_ops,
863865
#ifdef CONFIG_HAS_DMA
@@ -883,7 +885,7 @@ static const struct snd_malloc_ops *snd_dma_get_ops(struct snd_dma_buffer *dmab)
883885
if (WARN_ON_ONCE(!dmab))
884886
return NULL;
885887
if (WARN_ON_ONCE(dmab->dev.type <= SNDRV_DMA_TYPE_UNKNOWN ||
886-
dmab->dev.type >= ARRAY_SIZE(dma_ops)))
888+
dmab->dev.type >= ARRAY_SIZE(snd_dma_ops)))
887889
return NULL;
888-
return dma_ops[dmab->dev.type];
890+
return snd_dma_ops[dmab->dev.type];
889891
}

0 commit comments

Comments
 (0)