Re: Segmentation Fault from MP3-Player with Etch on Qube2

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

 



On Wed, 16 May 2007 16:28:49 +0200, Martin Michlmayr <tbm@xxxxxxxxxx> wrote:
> > There are know problems with PCI soundcard on noncoherent MIPS
> > platform (including cobalt) and some patches are floating around.  For
> > example:
> > http://www.linux-mips.org/archives/linux-mips/2007-04/msg00072.html
> > 
> > This is a long standing issue and I wonder why your soundcard _did_
> > work with debian sid.  The kernel of sid contains fixes for this
> > issue?
> 
> I don't think it ever worked with 2.6, but it certainly worked with
> 2.4.  Is it much work to get 2.6 working again?  This problem comes up
> from time to time, so it seems it's hitting a number of users.

Did the 2.4 kernel use ALSA or OSS?  I think ALSA for kernel 2.4 had
same problem.

And this is a minimal patch for current git tree.  But I'm not sure if
this patch really fixes the reported segfault.


There are two problem.

1. virt_to_page() can not be used for a buffer returned by
   dma_alloc_coherent().

2. mmap() for a buffer returned by dma_alloc_coherent() should be
   uncached.

This patch is actually ugly and would not be acceptable as is.
So we need a plan to how to fix them _right_ way.


diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index a96733a..2d3660c 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -3138,6 +3138,9 @@ static struct page *snd_pcm_mmap_data_nopage(struct vm_area_struct *area,
 			return NOPAGE_OOM; /* XXX: is this really due to OOM? */
 	} else {
 		vaddr = runtime->dma_area + offset;
+#if defined(CONFIG_MIPS) && defined(CONFIG_DMA_NONCOHERENT)
+		vaddr = CAC_ADDR(vaddr);
+#endif
 		page = virt_to_page(vaddr);
 	}
 	get_page(page);
@@ -3159,6 +3162,10 @@ static struct vm_operations_struct snd_pcm_vm_ops_data =
 static int snd_pcm_default_mmap(struct snd_pcm_substream *substream,
 				struct vm_area_struct *area)
 {
+#if defined(CONFIG_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 --git a/sound/core/sgbuf.c b/sound/core/sgbuf.c
index cefd228..1dd1c9e 100644
--- a/sound/core/sgbuf.c
+++ b/sound/core/sgbuf.c
@@ -91,12 +91,21 @@ void *snd_malloc_sgbuf_pages(struct device *device,
 		}
 		sgbuf->table[i].buf = tmpb.area;
 		sgbuf->table[i].addr = tmpb.addr;
+#if defined(CONFIG_MIPS) && defined(CONFIG_DMA_NONCOHERENT)
+		sgbuf->page_table[i] = virt_to_page(CAC_ADDR(tmpb.area));
+#else
 		sgbuf->page_table[i] = virt_to_page(tmpb.area);
+#endif
 		sgbuf->pages++;
 	}
 
 	sgbuf->size = size;
+#if defined(CONFIG_MIPS) && defined(CONFIG_DMA_NONCOHERENT)
+	dmab->area = vmap(sgbuf->page_table, sgbuf->pages, VM_MAP,
+			  PAGE_KERNEL_UNCACHED);
+#else
 	dmab->area = vmap(sgbuf->page_table, sgbuf->pages, VM_MAP, PAGE_KERNEL);
+#endif
 	if (! dmab->area)
 		goto _failed;
 	return dmab->area;


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

  Powered by Linux