Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1750899AbWAYSzn (ORCPT ); Wed, 25 Jan 2006 13:55:43 -0500 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1750883AbWAYSzm (ORCPT ); Wed, 25 Jan 2006 13:55:42 -0500 Received: from cantor.suse.de ([195.135.220.2]:21717 "EHLO mx1.suse.de") by vger.kernel.org with ESMTP id S1750834AbWAYSzm (ORCPT ); Wed, 25 Jan 2006 13:55:42 -0500 Date: Wed, 25 Jan 2006 20:03:13 +0100 Message-ID: From: Takashi Iwai To: Atsushi Nemoto 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 In-Reply-To: <20060125.235007.126576298.anemo@mba.ocn.ne.jp> References: <20060125.235007.126576298.anemo@mba.ocn.ne.jp> User-Agent: Wanderlust/2.12.0 (Your Wildest Dreams) SEMI/1.14.6 (Maruoka) FLIM/1.14.7 (=?ISO-8859-4?Q?Sanj=F2?=) APEL/10.6 MULE XEmacs/21.5 (beta21) (corn) (+CVS-20050720) (i386-suse-linux) MIME-Version: 1.0 (generated by SEMI 1.14.6 - "Maruoka") Content-Type: text/plain; charset=US-ASCII Sender: linux-kernel-owner@vger.kernel.org X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 4130 Lines: 114 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 - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/