For non-IOMMU systems, it makes little sense (or even buggy) to use dma_alloc_noncontiguous() as an x86 SG-buffer allocation, as it always results in the big continuous pages instead of SG buffer. Also, for Xen PV, this seems also not working well as the pages allocated there aren't guaranteed to be coherent. This patch is a first step to address those problems. It changes the memalloc helper to go for the explicit SG-page allocations via the existing fallback allocation primarily for such a platform instead of dma_alloc_noncontiguous(). Fixes: a8d302a0b770 ("ALSA: memalloc: Revive x86-specific WC page allocations again") Fixes: 9736a325137b ("ALSA: memalloc: Don't fall back for SG-buffer with IOMMU") Reported-and-tested-by: Marek Marczykowski-Górecki <marmarek@xxxxxxxxxxxxxxxxxxxxxx> Link: https://lore.kernel.org/r/87tu256lqs.wl-tiwai@xxxxxxx Signed-off-by: Takashi Iwai <tiwai@xxxxxxx> --- sound/core/memalloc.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/sound/core/memalloc.c b/sound/core/memalloc.c index 81025f50a542..30c9ad192986 100644 --- a/sound/core/memalloc.c +++ b/sound/core/memalloc.c @@ -541,10 +541,9 @@ static void *snd_dma_noncontig_alloc(struct snd_dma_buffer *dmab, size_t size) struct sg_table *sgt; void *p; - sgt = dma_alloc_noncontiguous(dmab->dev.dev, size, dmab->dev.dir, - DEFAULT_GFP, 0); #ifdef CONFIG_SND_DMA_SGBUF - if (!sgt && !get_dma_ops(dmab->dev.dev)) { + if (cpu_feature_enabled(X86_FEATURE_XENPV) || + !get_dma_ops(dmab->dev.dev)) { if (dmab->dev.type == SNDRV_DMA_TYPE_DEV_WC_SG) dmab->dev.type = SNDRV_DMA_TYPE_DEV_WC_SG_FALLBACK; else @@ -552,6 +551,8 @@ static void *snd_dma_noncontig_alloc(struct snd_dma_buffer *dmab, size_t size) return snd_dma_sg_fallback_alloc(dmab, size); } #endif + sgt = dma_alloc_noncontiguous(dmab->dev.dev, size, dmab->dev.dir, + DEFAULT_GFP, 0); if (!sgt) return NULL; -- 2.35.3