>>>>> On Tue, 24 Jan 2006 03:07:25 +0000, Martin Michlmayr <tbm@cyrius.com>
>>>>> said:
tbm> I get the following problems on a Cobalt MIPS machine with PCI
tbm> and an Ensoniq ES1371 sound card when the module is being loaded.
tbm> It occurs both with the ALSA and the OSS driver so I assume
tbm> there's some MIPS related issue. Note that the OSS driver worked
tbm> fine under 2.4. This is now with 2.6.15.
ALSA uses virt_to_page() but this is not work for buffers returned by
pci_alloc_consistent() on MIPS with CONFIG_DMA_NONCOHERENT. We can
make virt_to_page() bulletproof but it might have some performance
impact. It seems API something like dma_to_page() should be
introduced.
This issue was discussed years ago:
http://www.linux-mips.org/cgi-bin/mesg.cgi?a=linux-mips&i=20030523215935.71373.qmail%40web11901.mail.yahoo.com
Also I suppose snd_pcm_default_mmap() should return uncached page for
DMA area, but I do not sure to where to fix this too.
Anyway, here is my ugly patch against 2.6.15. It would fix some
problems with ALSA on noncoherent MIPS platform.
diff -ur linux-2.6.15/sound/core/memalloc.c linux/sound/core/memalloc.c
--- linux-2.6.15/sound/core/memalloc.c 2006-01-03 12:21:10.000000000 +0900
+++ linux/sound/core/memalloc.c 2006-01-05 11:46:55.000000000 +0900
@@ -248,8 +248,13 @@
res = dma_alloc_coherent(dev, PAGE_SIZE << pg, dma, gfp_flags);
if (res != NULL) {
#ifdef NEED_RESERVE_PAGES
+#if defined(__mips__) && defined(CONFIG_DMA_NONCOHERENT)
+ /* res is nocache addr */
+ mark_pages(virt_to_page(CAC_ADDR(res)), pg); /* should be
dma_to_page() */
+#else
mark_pages(virt_to_page(res), pg); /* should be dma_to_page() */
#endif
+#endif
inc_snd_pages(pg);
}
@@ -267,8 +272,13 @@
pg = get_order(size);
dec_snd_pages(pg);
#ifdef NEED_RESERVE_PAGES
+#if defined(__mips__) && defined(CONFIG_DMA_NONCOHERENT)
+ /* ptr is nocache addr */
+ unmark_pages(virt_to_page(CAC_ADDR(ptr)), pg); /* should be
dma_to_page() */
+#else
unmark_pages(virt_to_page(ptr), pg); /* should be dma_to_page() */
#endif
+#endif
dma_free_coherent(dev, PAGE_SIZE << pg, ptr, dma);
}
diff -ur linux-2.6.15/sound/core/pcm_native.c linux/sound/core/pcm_native.c
--- linux-2.6.15/sound/core/pcm_native.c 2006-01-03 12:21:10.000000000
+0900
+++ linux/sound/core/pcm_native.c 2006-01-05 11:46:55.000000000 +0900
@@ -3056,6 +3056,10 @@
return NOPAGE_OOM;
} else {
vaddr = runtime->dma_area + offset;
+#if defined(__mips__) && defined(CONFIG_DMA_NONCOHERENT)
+ /* dma_area is nocache addr */
+ vaddr = CAC_ADDR(vaddr);
+#endif
page = virt_to_page(vaddr);
}
get_page(page);
@@ -3076,6 +3080,10 @@
*/
static int snd_pcm_default_mmap(snd_pcm_substream_t *substream, struct
vm_area_struct *area)
{
+#if defined(__mips__) && defined(CONFIG_DMA_NONCOHERENT)
+ /* use uncached access for dma_area */
+ area->vm_page_prot = pgprot_noncached(area->vm_page_prot);
+#endif
area->vm_ops = &snd_pcm_vm_ops_data;
area->vm_private_data = substream;
area->vm_flags |= VM_RESERVED;
diff -ur linux-2.6.15/sound/core/sgbuf.c linux/sound/core/sgbuf.c
--- linux-2.6.15/sound/core/sgbuf.c 2006-01-03 12:21:10.000000000 +0900
+++ linux/sound/core/sgbuf.c 2005-03-04 11:07:45.000000000 +0900
@@ -95,7 +95,12 @@
}
sgbuf->table[i].buf = tmpb.area;
sgbuf->table[i].addr = tmpb.addr;
+#if defined(__mips__) && defined(CONFIG_DMA_NONCOHERENT)
+ /* snd_dma_malloc_pages returns nocache addr */
+ sgbuf->page_table[i] = virt_to_page(CAC_ADDR(tmpb.area));
+#else
sgbuf->page_table[i] = virt_to_page(tmpb.area);
+#endif
sgbuf->pages++;
}
|