linux-mips
[Top] [All Lists]

Re: Ensoniq ES1371 problem on Cobalt MIPS

To: tbm@cyrius.com
Subject: Re: Ensoniq ES1371 problem on Cobalt MIPS
From: Atsushi Nemoto <anemo@mba.ocn.ne.jp>
Date: Tue, 24 Jan 2006 13:28:32 +0900 (JST)
Cc: linux-mips@linux-mips.org, t.sailer@alumni.ethz.ch, perex@suse.cz
In-reply-to: <20060124030725.GA14063@deprecation.cyrius.com>
Original-recipient: rfc822;linux-mips@linux-mips.org
References: <20060124030725.GA14063@deprecation.cyrius.com>
Sender: linux-mips-bounce@linux-mips.org
>>>>> 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++;
        }
 

<Prev in Thread] Current Thread [Next in Thread>