From: Takashi Iwai <tiwai@suse.de>
To: Atsushi Nemoto <anemo@mba.ocn.ne.jp>
Cc: linux-kernel@vger.kernel.org, tbm@cyrius.com,
t.sailer@alumni.ethz.ch, perex@suse.cz, ralf@linux-mips.org
Subject: Re: ALSA on MIPS platform
Date: Wed, 25 Jan 2006 20:03:13 +0100 [thread overview]
Message-ID: <s5hek2wb05q.wl%tiwai@suse.de> (raw)
In-Reply-To: <20060125.235007.126576298.anemo@mba.ocn.ne.jp>
At Wed, 25 Jan 2006 23:50:07 +0900 (JST),
Atsushi Nemoto wrote:
>
> 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?
The right fix is, IMO, to port dma_mmap_coherent() to all archs.
Currently, it's only on ARM.
Takashi
next prev parent reply other threads:[~2006-01-25 18:55 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2006-01-25 14:50 ALSA on MIPS platform Atsushi Nemoto
2006-01-25 19:03 ` Takashi Iwai [this message]
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
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=s5hek2wb05q.wl%tiwai@suse.de \
--to=tiwai@suse.de \
--cc=anemo@mba.ocn.ne.jp \
--cc=linux-kernel@vger.kernel.org \
--cc=perex@suse.cz \
--cc=ralf@linux-mips.org \
--cc=t.sailer@alumni.ethz.ch \
--cc=tbm@cyrius.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).