All of lore.kernel.org
 help / color / mirror / Atom feed
* ALSA on MIPS platform
@ 2006-01-25 14:50 Atsushi Nemoto
  2006-01-25 19:03 ` Takashi Iwai
  0 siblings, 1 reply; 37+ messages in thread
From: Atsushi Nemoto @ 2006-01-25 14:50 UTC (permalink / raw)
  To: linux-kernel; +Cc: tbm, t.sailer, perex, ralf

Hi.  I'm using PCI Sound cards on MIPS platform which has noncoherent
DMA.  There are some issues in ALSA for these platform.

(This topic comes from linux-mips ML.
http://www.linux-mips.org/cgi-bin/mesg.cgi?a=linux-mips&i=20060124030725.GA14063%40deprecation.cyrius.com)


1. virt_to_page vs. dma_alloc_coherent problem.

ALSA uses virt_to_page() to get 'struct page' for DMA area which was
allocated using dma_alloc_coherent().  On MIPS with
CONFIG_DMA_NONCOHERENT, typically physical address range
0x0-0x1fffffff are mapped to 0x8000000-0x9fffffff with cached and
mapped to 0xa0000000-0xbfffffff with uncached.  If we got physical
address 0x01000000 for DMA, the virtual address is 0xa1000000.  On the
other hand, virt_to_page() expects normal(cached) virtual address.  So
we can use virt_to_page() with kmalloc() or dma_alloc_noncoherent(),
but not with dma_alloc_coherent().

Here is some fragments from kernel code.  You can see what I mean exactly.

/* from include/asm-mips/mach-generic/spaces.h */
#define CAC_BASE		0x80000000
#define UNCAC_BASE		0xa0000000
#define PAGE_OFFSET		0x80000000UL
/* from include/asm-mips/page.h */
#define __pa(x)			((unsigned long) (x) - PAGE_OFFSET)
#define __va(x)			((void *)((unsigned long) (x) + PAGE_OFFSET))
#define pfn_to_page(pfn)	(mem_map + (pfn))
#define virt_to_page(kaddr)	pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
#define UNCAC_ADDR(addr)	((addr) - PAGE_OFFSET + UNCAC_BASE)
#define CAC_ADDR(addr)		((addr) - UNCAC_BASE + PAGE_OFFSET)
/* from arch/mips/mm/dma-noncoherent.c */
void *dma_alloc_coherent(struct device *dev, size_t size,
	dma_addr_t * dma_handle, gfp_t gfp)
{
	void *ret;

	ret = dma_alloc_noncoherent(dev, size, dma_handle, gfp);
	if (ret) {
		dma_cache_wback_inv((unsigned long) ret, size);
		ret = UNCAC_ADDR(ret);
	}

	return ret;
}

How do we fix this?

A.  hack sound/core/memalloc.c, pcm_native.c, sgbuf.c

something like:
#if defined(__mips__) && defined(CONFIG_DMA_NONCOHERENT)
		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

It's ugly.

B.  fix mips virt_to_page()

#define TO_PHYS_MASK 0x1fffffff
#define virt_to_page(kaddr)	pfn_to_page(((kaddr) & TO_PHYS_MASK) >> PAGE_SHIFT)

a bit slower.  MIPS need one instruction to create 0x80000000
constant, two instruction for 0x1fffffff.  There are many usage of
virt_to_page() in mm/slab.c so its performance might be important.

C.  introduce dma_to_page() which returns struct page * for dma_addr_t.

The comment in ALSA code (/* should be dma_to_page() */) mean this?

For MIPS, it would be:
#define dma_to_page(addr) pfn_to_page((addr) >> PAGE_SHIFT)
But I do not know for other platform.


Which is preferred, or is there other good way?


2. mmapping DMA area.

As described above, DMA area is uncached on those platform.  So mmap
should ensure user programs do not cache these area.
snd_pcm_default_mmap() is used for mmapping the DMA area but its
vm_page_prot is not configured as uncached.  On the other hand,
snd_pcm_lib_mmap_iomem() do it using pgprot_noncached().

snd_pcm_default_mmap() should do same thing for those MIPS platform.

static int snd_pcm_default_mmap(struct snd_pcm_substream *substream,
				struct vm_area_struct *area)
{
#if defined(__mips__) && defined(CONFIG_DMA_NONCOHERENT)
	area->vm_page_prot = pgprot_noncached(area->vm_page_prot);
#endif
	area->vm_ops = &snd_pcm_vm_ops_data;

Is this a right fix?  Are there any platform which have same problem?


---
Atsushi Nemoto

^ permalink raw reply	[flat|nested] 37+ messages in thread
* ALSA on MIPS platform
@ 2007-08-01  7:56 Songmao Tian
  2007-08-02 14:56 ` Atsushi Nemoto
  0 siblings, 1 reply; 37+ messages in thread
From: Songmao Tian @ 2007-08-01  7:56 UTC (permalink / raw)
  To: alsa-devel, linux-mips

Hi,
    In 
http://www.linux-mips.org/archives/linux-mips/2007-04/msg00114.html, 
Atsushi Nemoto pointed out the problem is discussed before, the thread 
can be found at http://lkml.org/lkml/2006/1/25/117. Thanks Atsushi Nemoto:)
    The problem is clear:
1. dma_alloc_noncoherent() return a non-cached address, and 
virt_to_page() need a cached logical addr (Have I named it right?)
2. mmaped dam buffer should be non-cached.

We have a ugly patch, but we want to solve the problem cleanly, so can 
anyone show me the way?

Regards,
Tian

diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index 59b29cd..fd0aa66 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -3138,7 +3138,11 @@ 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(__mips__) && defined(CONFIG_DMA_NONCOHERENT)
+        page = virt_to_page(CAC_ADDR(vaddr));
+#else
         page = virt_to_page(vaddr);
+#endif
     }
     get_page(page);
     if (type)
@@ -3254,6 +3258,11 @@ static int snd_pcm_mmap(struct file *file, struct 
vm_area_struct *area)
     substream = pcm_file->substream;
     snd_assert(substream != NULL, return -ENXIO);
 
+#if defined(__mips__) && defined(CONFIG_DMA_NONCOHERENT)
+    /* all mmap using uncached mode */
+    area->vm_page_prot = pgprot_noncached(area->vm_page_prot);
+#endif
+
     offset = area->vm_pgoff << PAGE_SHIFT;
     switch (offset) {
     case SNDRV_PCM_MMAP_OFFSET_STATUS:
diff --git a/sound/core/sgbuf.c b/sound/core/sgbuf.c
index cefd228..2251e70 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(__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(__mips__) && defined(CONFIG_DMA_NONCOHERENT)
+    /* maybe we should use uncached accelerated mode */
+    dmab->area = vmap(sgbuf->page_table, sgbuf->pages, VM_MAP, 
pgprot_noncached(PAGE_KERNEL));
+#else
     dmab->area = vmap(sgbuf->page_table, sgbuf->pages, VM_MAP, 
PAGE_KERNEL);
+#endif
     if (! dmab->area)
         goto _failed;
     return dmab->area;

^ permalink raw reply related	[flat|nested] 37+ messages in thread

end of thread, other threads:[~2007-08-09  1:26 UTC | newest]

Thread overview: 37+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-01-25 14:50 ALSA on MIPS platform Atsushi Nemoto
2006-01-25 19:03 ` Takashi Iwai
2006-01-26 15:29   ` Atsushi Nemoto
2006-01-26 16:02     ` Takashi Iwai
2006-01-26 19:19       ` Hugh Dickins
2006-01-27 15:45       ` Atsushi Nemoto
2006-01-27 15:49         ` Martin Michlmayr
2006-01-27 16:01           ` Takashi Iwai
2006-01-27 15:57         ` Takashi Iwai
2006-01-30  9:56           ` Atsushi Nemoto
2006-01-30 10:18             ` Takashi Iwai
2006-01-30 10:38               ` Atsushi Nemoto
2006-01-30 12:25               ` Ralf Baechle
2006-01-30 15:46               ` Martin Michlmayr
2006-01-30 15:52                 ` Takashi Iwai
  -- strict thread matches above, loose matches on Subject: below --
2007-08-01  7:56 Songmao Tian
2007-08-02 14:56 ` Atsushi Nemoto
2007-08-03 13:50   ` Songmao Tian
2007-08-03 13:50     ` Songmao Tian
2007-08-03 13:59     ` Takashi Iwai
2007-08-03 15:57       ` Songmao Tian
2007-08-06 12:17         ` Takashi Iwai
2007-08-07  5:53     ` Dajie Tan
2007-08-07  6:18       ` Dajie Tan
2007-08-07 14:01         ` Atsushi Nemoto
2007-08-07 17:54           ` Ralf Baechle
2007-08-07 17:54             ` Ralf Baechle
2007-08-07 18:41             ` Takashi Iwai
2007-08-07 18:41               ` Takashi Iwai
2007-08-08 11:58               ` Ralf Baechle
2007-08-08 11:58                 ` Ralf Baechle
2007-08-08 12:40                 ` Maciej W. Rozycki
2007-08-08 12:57                 ` Takashi Iwai
2007-08-08 12:57                   ` Takashi Iwai
2007-08-09  1:24             ` Songmao Tian
2007-08-09  1:24               ` Songmao Tian
2007-08-08  0:40           ` Songmao Tian

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.