Re: Ensoniq ES1371 problem on Cobalt MIPS

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



>>>>> 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++;
 	}
 


[Index of Archives]     [Linux MIPS Home]     [LKML Archive]     [Linux ARM Kernel]     [Linux ARM]     [Linux]     [Git]     [Yosemite News]     [Linux SCSI]     [Linux Hams]

  Powered by Linux