Re: Call to mmap in ALSA lib 1.0.13 fails in src/pcm/pcm_mmap.c line 367

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

 



At Wed, 20 Dec 2006 14:06:37 -0500,
David Cullen wrote:
> 
> >> >> Also, could you give me some pointers regarding my previous e-mails
> >> >> regarding this issue:
> >> >> 
> >> >> Takashi Iwai wrote:
> >> >> > At Mon, 27 Nov 2006 17:01:52 -0500,
> >> >> > David Cullen wrote:
> >> >> >>
> >> >> >> I am trying to get ALSA version 1.0.13 working on an AMCC PowerPC
> >> >> >> PPC405EP Taihu board with a Sound Blaster Live! 24-bit 7.1 PCI
> >> >> >> card.  I am using a patched 2.6.13 kernel that comes with the
> >> >> >> board.  I built the kernel with the sound core built in and I
> >> >> >> used the cross-compiler tools to build the ALSA driver, library,
> >> >> >> and utils. When I run "speaker-test", it crashes in the ALSA
> >> >> >> library.  The problem is that the call to mmap in
> >> >> >>
> >> >> >>    alsa-lib-1.0.13/src/pcm/pcm_mmap.c line 367
> >> >> >>
> >> >> >> which looks like
> >> >> >>
> >> >> >>    ptr = mmap(NULL, size, PROT_READ|PROT_WRITE,
> >> >> >> MAP_FILE|MAP_SHARED, i->u.mmap.fd, i->u.mmap.offset);
> >> >> >>
> >> >> >> returns a pointer that appears to be valid (0x3001E000) but
> >> >> >> causes a kernel OOPS when accessed.
> >> >> >>
> >> >> >> Previous calls to mmap in pcm_hw.c on lines 822 and 854 both
> >> >> >> succeed, and the pointers returned can be successfully accessed,
> >> >> >> but they use the status and control offsets as parameters to
> >> >> >> mmap.
> >> >> >>
> >> >> >> I haved traced the problem on the target into the ALSA library
> >> >> >> using gdb and into the kernel using kgdb and everything looks
> >> >> >> like it works properly.  If I disable the semaphore acquisition
> >> >> >> in do_mmap2, I can print the contents of the address in kgdb
> >> >> >> using
> >> >> >>
> >> >> >>    (gdb) print ((char *)vma->vm_start)[0]
> >> >> >>
> >> >> >> after the call to vm_link in do_mmap_pgoff.  However, the board
> >> >> >> locks up after the print command.
> >> >> >>
> >> >> >> Anyone have any experience with this type of problem on PowerPC
> >> >> >> systems?
> >> >> >
> >> >> > Possibly a memory coherency problem.  The memory allocated via
> >> >> > dma_alloc_coherent() isn't simply mmappable.
> >> >> >
> >> >> > An essential fix would be to add dma_mmap_coherent() to all
> >> >> > architectures and use it for ALSA mmap.  I made some patches quite
> >> >> > ago, but left it rotten for the time being...
> >> >> >
> >> >> 
> >> >> How do I "add dma_mmap_coherent() to all architectures and use it
> >> >> for ALSA mmap"?
> >> > 
> >> > Well, for that, we need to patch the kernel itself and add
> >> > dma_mmap_coherent() call.  The problem is that the memory returned
> >> > from dma_alloc_coherent() isn't the address of the really allocated
> >> > pages in your case.  Since the ALSA mmap mode obtains the page via
> >> > virt_to_page(), this doesn't work.  Thus, a new function,
> >> > dma_mmap_coherent() is required to calculate the real page address and
> >> > do the rest of low-level mmap jobs.
> >> 
> >> Where would dma_mmap_coherent be placed?  Which specific file?
> > 
> > It's somewhere in arch/*/* directory.
> > 
> >> Would I replace all calls to mmap with dma_mmap_coherent?  I can
> >> probably figure out how to implement it if you can give me an
> >> example for another architecture.  I tried looking at old patches on
> >> the web, but I had difficulty understanding them.  I think they were
> >> for the ARM architecture.
> > 
> > Yes, ARM has already it.
> >
> 
> In arch/arm/mm/consistent.c I find the following lines:
> 
> int dma_mmap_coherent(struct device *dev,
>     struct vm_area_struct *vma, void *cpu_addr,
>     dma_addr_t dma_addr, size_t size)
> {
>     vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
>     return dma_mmap(dev, vma, cpu_addr, dma_addr, size);
> }
> EXPORT_SYMBOL(dma_mmap_coherent);
> 
> Can I add this code verbatim to a file in arch/ppc/mm?  For example,
> could I add it to 4xx_mmu.c?  Or do I need to make a copy of
> consistent.c in arch/ppc/mm?  I apologize for all the questions, but
> when I look at this code I am reminded of the quote from ADVENT:
> "You are in a maze of twisty little passages, all alike."

The implementation depends pretty much on the architecture.
(Also, dma_mmap() is no global function but specific only for ARM.)
Since the vm_region struct is different between ppc and arm (the page
pointer is missing in ppc version), it cannot be copied as it is.

A simple (but totally untested) version would be like below:

int dma_mmap_coherent(struct device *dev,
		struct vm_area_struct *vma, void *cpu_addr,
		dma_addr_t dma_addr, size_t size)
{
	unsigned long pfn;

	pfn = page_to_pfn(virt_to_page(bus_to_virt(dma_addr)));
	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
	return remap_pfn_range(vma, vma->vm_start, pfn + vma->vm_pgoff,
				vma->vm_end - vma->vm_start,
				vma->vm_pgprot);
}

(This might not work for some ppc models, though...)

Then either add .mmap callback to each of snd_pcm_ops table in ca0106
that calls dma_mmap_coherent() above, or change snd_pcm_default_mmap
to call dma_mmap_coherent() directly instead of nopage method.
For the former way, take a look at sound/arm/aaci.c (and devdma.c) as
a reference.

> 
> >> > A simple solution would be simply disable mmap.
> >> > In pci/ca0106/ca0106_main.c, remove SNDRV_PCM_INFO_MMAP and
> >> > SNDRV_PCM_INFO_MMAP_VALID from snd_ca0106_playback_hw and
> >> > snd_ca0106_capture_hw structs.
> >> > 
> >> > Also, disable #if defined(CONFIG_PPC) around
> >> > snd_pcm_mmap_status_*() in core/pcm_native.c.
> >> > 
> >> > This will reduce the sound system functionality (e.g. no dmix is
> >> > available), though.
> >> 
> >> At this point, if we can get speaker-test to work, we will be happy.
> >>  So dmix is not necessary (I believe...).  However, I do not know
> >> the complete details of the end user's application, so dmix may be
> >> needed eventually.  If you can give me a few pointers on how to
> >> implement dma_mmap_coherent and sew it into ALSA, that would really
> >> help.
> > 
> > When mmap is disabled in the driver, change the default alsa-lib
> > configuration, too.  Either edit alsa-lib/src/conf/cards/CA0106.conf
> > or override the default PCM configuration in /etc/asound.conf, such as
> > 	pcm.!default plughw
> > 
> > 
> 
> Currently, /etc/asound.conf is
> 
> pcm.ca0106 {
>     type hw
>     card 0
> }
> 
> ctl.ca0106 {
>     type hw
>     card 0
> }
> 
> I am confused about where is the right place to put
> 
>     pcm.!default plughw
> 
> Do I just add another section that looks like this
> 
> pcm.!default {
>     type plughw
>     card 0
> }
> 
> or do I just add the line to asound.conf?

The above (using aliasing) might work possibly only with the recent
alsa-lib.  With the older alsa-lib, you'd need to define the following
in /etc/asound.conf:

pcm.!default {
	type plug
	slave.pcm {
		type hw
		card 0
	}
}

This will override the default PCM.


Takashi

-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys - and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
Alsa-devel mailing list
Alsa-devel@xxxxxxxxxxxxxxxxxxxxx
https://lists.sourceforge.net/lists/listinfo/alsa-devel

[Index of Archives]     [ALSA User]     [Linux Audio Users]     [Kernel Archive]     [Asterisk PBX]     [Photo Sharing]     [Linux Sound]     [Video 4 Linux]     [Gimp]     [Yosemite News]

  Powered by Linux