>>>>> On Tue, 24 Jan 2006 03:07:25 +0000, Martin Michlmayr <tbm@xxxxxxxxxx> 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++; }