linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
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

  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).