Skip to content

Commit c880a51

Browse files
committed
ALSA: memalloc: Use proper DMA mapping API for x86 WC buffer allocations
The x86 WC page allocation assumes incorrectly the DMA address directly taken from the page. Also it checks the DMA ops inappropriately for switching to the own method. This patch rewrites the stuff to use the proper DMA mapping API instead. Link: https://patch.msgid.link/[email protected] Signed-off-by: Takashi Iwai <[email protected]>
1 parent a51c925 commit c880a51

File tree

1 file changed

+31
-18
lines changed

1 file changed

+31
-18
lines changed

sound/core/memalloc.c

Lines changed: 31 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -496,41 +496,54 @@ static const struct snd_malloc_ops snd_dma_dev_ops = {
496496
/*
497497
* Write-combined pages
498498
*/
499-
/* x86-specific allocations */
500499
#ifdef CONFIG_SND_DMA_SGBUF
501-
#define x86_fallback(dmab) (!get_dma_ops(dmab->dev.dev))
502-
#else
503-
#define x86_fallback(dmab) false
504-
#endif
500+
/* x86-specific allocations */
501+
static void *snd_dma_wc_alloc(struct snd_dma_buffer *dmab, size_t size)
502+
{
503+
void *p = do_alloc_pages(dmab->dev.dev, size, &dmab->addr, true);
504+
505+
if (!p)
506+
return NULL;
507+
dmab->addr = dma_map_single(dmab->dev.dev, p, size, DMA_BIDIRECTIONAL);
508+
if (dmab->addr == DMA_MAPPING_ERROR) {
509+
do_free_pages(dmab->area, size, true);
510+
return NULL;
511+
}
512+
return p;
513+
}
514+
515+
static void snd_dma_wc_free(struct snd_dma_buffer *dmab)
516+
{
517+
dma_unmap_single(dmab->dev.dev, dmab->addr, dmab->bytes,
518+
DMA_BIDIRECTIONAL);
519+
do_free_pages(dmab->area, dmab->bytes, true);
520+
}
505521

522+
static int snd_dma_wc_mmap(struct snd_dma_buffer *dmab,
523+
struct vm_area_struct *area)
524+
{
525+
area->vm_page_prot = pgprot_writecombine(area->vm_page_prot);
526+
return dma_mmap_coherent(dmab->dev.dev, area,
527+
dmab->area, dmab->addr, dmab->bytes);
528+
}
529+
#else
506530
static void *snd_dma_wc_alloc(struct snd_dma_buffer *dmab, size_t size)
507531
{
508-
if (x86_fallback(dmab))
509-
return do_alloc_pages(dmab->dev.dev, size, &dmab->addr, true);
510532
return dma_alloc_wc(dmab->dev.dev, size, &dmab->addr, DEFAULT_GFP);
511533
}
512534

513535
static void snd_dma_wc_free(struct snd_dma_buffer *dmab)
514536
{
515-
if (x86_fallback(dmab)) {
516-
do_free_pages(dmab->area, dmab->bytes, true);
517-
return;
518-
}
519537
dma_free_wc(dmab->dev.dev, dmab->bytes, dmab->area, dmab->addr);
520538
}
521539

522540
static int snd_dma_wc_mmap(struct snd_dma_buffer *dmab,
523541
struct vm_area_struct *area)
524542
{
525-
#ifdef CONFIG_SND_DMA_SGBUF
526-
if (x86_fallback(dmab)) {
527-
area->vm_page_prot = pgprot_writecombine(area->vm_page_prot);
528-
return snd_dma_continuous_mmap(dmab, area);
529-
}
530-
#endif
531543
return dma_mmap_wc(dmab->dev.dev, area,
532544
dmab->area, dmab->addr, dmab->bytes);
533545
}
546+
#endif
534547

535548
static const struct snd_malloc_ops snd_dma_wc_ops = {
536549
.alloc = snd_dma_wc_alloc,
@@ -804,7 +817,7 @@ static void *snd_dma_sg_alloc(struct snd_dma_buffer *dmab, size_t size)
804817

805818
dmab->dev.type = type; /* restore the type */
806819
/* if IOMMU is present but failed, give up */
807-
if (!x86_fallback(dmab))
820+
if (get_dma_ops(dmab->dev.dev))
808821
return NULL;
809822
/* try fallback */
810823
return snd_dma_sg_fallback_alloc(dmab, size);

0 commit comments

Comments
 (0)