Hi Takashi et al,

I did a bit more research, please find my findings at the end of the email.

On Friday, October 6, 2017 4:50 PM Axel Holzinger wrote:
> On Friday, October 6, 2017 2:30 PM Takashi Iwai wrote:
> > On Tue, 03 Oct 2017 19:23:04 +0200,
> > Axel Holzinger wrote:
> > >
> > > On Thursday, June 8, 2017 10:40 AM Takashi Iwai wrote:
> > >
> > > > On Thu, 08 Jun 2017 10:15:34 +0200,
> > > > Axel Holzinger wrote:
> > > > >
> > > > > On Tuesday, June 6, 2017 8:27 PM Takashi Iwai wrote:
> > > > > > On Mon, 05 Jun 2017 11:49:53 +0200,
> > > > > > Axel Holzinger wrote:
> > > > > > >
> > > > > > > Hi,
> > > > > > >
> > > > > > > I'm trying to get a RME HDSPe MADI card to run in an ARM box
> with
> > > > Linux
> > > > > > > 4.1.6. I configured the (vendor specific TI) kernel to support
> the
> > > card
> > > > > (via
> > > > > > > hdspm) compiled into the kernel (not as loadable module).
> > > > > > >
> > > > > > > The MADI card is detected as a PCI device and the ALSA driver
is
> > > loaded.
> > > > > > > Unfortunately playout does NOT work: aplay is reporting an
> error:
> > > > > > > ALSA lib pcm_mmap.c:374:(snd_pcm_mmap) mmap failed: No
> such
> > > > device
> > > > > > or
> > > > > > > address
> > > > > >
> > > > > > Hm, this sounds odd.  But the line doesn't really correspond to
> the
> > > > > > latest version of alsa-lib.  Could you try to upgrade to the
> latest
> > > > > > version?  Otherwise it's hard to debug.
> > > > >
> > > > > I installed ALSA with Debian apt-get. How would I update to a
newer
> > > > version?
> > > >
> > > > Compiling by yourself?
> > > > alsa-lib has very few dependency, so it should be easy.
> > > >
> > > > > > > strace:
> > > > > > > open("/dev/snd/pcmC0D0p",
> > O_RDWR|O_NONBLOCK|O_CLOEXEC) =
> > > > 4
> > > > > > > fcntl64(4, F_SETFD, FD_CLOEXEC)         = 0
> > > > > > > ioctl(4, AGPIOC_ACQUIRE or APM_IOC_STANDBY or
> > > > > > SNDRV_PCM_IOCTL_INFO,
> > > > > > > 0xbecdfb64) = 0
> > > > > > > fcntl64(4, F_GETFL)                     = 0x802 (flags
> > > > > O_RDWR|O_NONBLOCK)
> > > > > > > ioctl(4, AGPIOC_INFO or SNDRV_PCM_IOCTL_PVERSION,
> > 0xbecdfacc) =
> > > > 0
> > > > > > > ioctl(4, AGPIOC_SETUP or SNDRV_PCM_IOCTL_TTSTAMP,
> > 0xbecdfad4)
> > > > = 0
> > > > > > > mmap2(NULL, 4096, PROT_READ, MAP_SHARED, 4, 0x80000000) =
> -1
> > > > ENXIO
> > > > > > (No such
> > > > > > > device or address)
> > > > > >
> > > > > > This error is expected and should be OK.  It's an mmap of
> > > > > > status/control page, and this isn't supported on ARM, thus the
> kernel
> > > > > > returns -ENXIO.  alsa-lib then falls back to the normal ioctl
> instead
> > > > > > of status/control mmap.
> > > > >
> > > > > Okay, got it. So is the mmap emulation plugin via asound.conf
> > suggested
> > > by
> > > > > Anders needed then anyhow?
> > > >
> > > > It's irrelevant with the mmap emulation.
> > > >
> > > > > > But the ring-buffer mmap is supported as normal on ARM for MADI
> > > > > > driver, at least.  MADI provides the SG-buffer that is mappable
> via
> > > > > > DMA coherent pages, and it should work on most of archs as is.
> > > > >
> > > > > Well I found out something more: If I don't give a "--device"
> parameter
> > > to
> > > > > aplay and the RME card is default, then audio is playing. But I
give
> the
> > > "
> > > > > --device=default:CARD=HDSPMx5c74" then the error is occuring. That
> > > > doesn't
> > > > > make sense to me at all. The tests made were with the asound.conf
> > Anders
> > > > > suggested. Isn't that strange?
> > > >
> > > > Are you using dmix or such?  It appears more like a configuration
> > > > issue.  With the unmodified configuration, the "default" PCM for
> HDSPM
> > > > should be equivalent with "plughw".
> > > >
> > > > Could you check whether aplay -M works without device option?
> > > >
> > > > > > You should have another error from mmap, with a different offset
> > > > > > value.  That's the real error we need to track down.
> > > > >
> > > > > I attached the complete strace.
> > > >
> > > > OK, the strace shows the mmap failure of the second channel.
> > > >
> > > > > > (And, 4.1.x is pretty old, rather too old for debugging, too...)
> > > > >
> > > > > Well, I know, but the kernel is a TI based manufacturer kernel for
a
> SoC
> > > > > (AM5728). I'm not such an expert to update that to current kernel
> > > version
> > > > > unfortunately.
> > > > >
> > > > > If you don't mind I have another question: If specifying a device
> > > > > "--device", how would I "send" audio to the "upper"
channels/tracks
> of
> > > the
> > > > > MADI card? If I ommit the "--device" parameter audio is playing on
> > > > > channels/tracks 1+2. How would I play audio to channels/tracks
33+34
> > for
> > > > > example?
> > > >
> > > > Well, you likely need to fiddle with the asoundrc in such a case.
> > > > Maybe a better option is to use JACK or such, I suppose.
> > > >
> > > >
> > > > Takashi
> > >
> > > Hello Takashi, hello list,
> > >
> > > I did some further testing with a Sound Blaster Live Audigy Rx
(Emu10k1
> > > driver based) and this card works without any change in asound.conf,
> etc.
> >
> > Yes, it's because emu10k1 supports only interleaved stereo format (two
> > channels) which works with one-shot mmap via dma_mmap_coherent().
> > Meanwhile HDSP MADI supports only non-interleaved format that
> performs
> > multiple mmaps, and currently it doesn't work with
> > dma_mmap_coherent().
> 
> Understood.
> 
> > > While with the RME MADI card:
> > >
> > > debian@arm:~/48kHz$ aplay -vv audio.wav
> > > Playing WAVE 'audio.wav' : Signed 16 bit Little Endian, Rate 48000 Hz,
> > > Stereo ALSA lib pcm_mmap.c:374:(snd_pcm_mmap) mmap failed:
> > > No such device or address
> >
> > So my previous patch didn't help?
> > (BTW, area->pgoff was indeed a typo of area->vm_pgoff, so your change
> >  should be OK.)
> 
> Correct, didn't help.
> 
> > If it didn't work, try to put some printk() around the call of
> > dma_mmap_coherent() and check whether it's really called with which
> > value and which return (error) code it gets.
> 
> int snd_pcm_lib_default_mmap(struct snd_pcm_substream *substream,
>                            struct vm_area_struct *area)
> {
>       area->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP;
> #ifdef CONFIG_GENERIC_ALLOCATOR
>       if (substream->dma_buffer.dev.type ==
> SNDRV_DMA_TYPE_DEV_IRAM) {
>               area->vm_page_prot =
> pgprot_writecombine(area->vm_page_prot);
>               return remap_pfn_range(area, area->vm_start,
>                               substream->dma_buffer.addr >>
> PAGE_SHIFT,
>                               area->vm_end - area->vm_start,
> area->vm_page_prot);
>       }
> #endif /* CONFIG_GENERIC_ALLOCATOR */
> #ifndef CONFIG_X86 /* for avoiding warnings arch/x86/mm/pat.c */
>       if (!substream->ops->page &&
>           substream->dma_buffer.dev.type == SNDRV_DMA_TYPE_DEV) {
>               unsigned long offset = area->vm_pgoff << PAGE_SHIFT;
> 
>               const char *init_name         =
> substream->dma_buffer.dev.dev->init_name;
>               u64        *dma_mask          =
> substream->dma_buffer.dev.dev->dma_mask;
>               u64         u64_dma_mask      = dma_mask ? *dma_mask : 0;
>               u64         coherent_dma_mask =
> substream->dma_buffer.dev.dev->coherent_dma_mask;
>               u64         dma_pfn_offset    =
> substream->dma_buffer.dev.dev->dma_pfn_offset;
>               u64         vm_start          = area->vm_start;
>               u64         vm_end            = area->vm_end;
>               u64         vm_size           = vm_end - vm_start;
>               u64         offs              = offset;
>               u64         rb_subtree_gap    = area->rb_subtree_gap;
>               u64         vm_flags          = area->vm_flags;
>               void       *cpu_addr          = substream->runtime->dma_area
> + offset;
>               u64         dma_addr          = substream->runtime->dma_addr
> + offset;
> 
>               int result =
> dma_mmap_coherent(substream->dma_buffer.dev.dev,
>                                        area,
>                                        substream->runtime->dma_area +
> offset,
>                                        substream->runtime->dma_addr +
> offset,
>                                        area->vm_end - area->vm_start);
> 
>               printk(KERN_DEBUG "dma_mmap_coherent returned %d,
> init_name
> = \"%s\", dma_mask = %p, *dma_mask = %llu, coherent_dma_mask = %llu,
> dma_pfn_offset = %llu, vm_start = %llu, vm_end = %llu, vm_size = %llu,
> offset = %llu, rb_subtree_gap = %llu, vm_flags = %llu, cpu_addr = %p,
> dma_addr = %llu",
>                 result,
>                 init_name,
>                 dma_mask,
>                 u64_dma_mask,
>                 coherent_dma_mask,
>                 dma_pfn_offset,
>                 vm_start,
>                 vm_end,
>                 vm_size,
>                 offs,
>                 rb_subtree_gap,
>                 vm_flags,
>                 cpu_addr,
>                 dma_addr);
>               return result;
>       }
> #endif /* CONFIG_X86 */
>       /* mmap with fault handler */
>       area->vm_ops = &snd_pcm_vm_ops_data_fault;
>       return 0;
> }
> 
> debian@arm:~/48kHz$ aplay -vv audio.wav
> 
> output:
> Playing WAVE 'audio.wav' : Signed 16 bit Little Endian, Rate 48000 Hz,
> Stereo
> ALSA lib pcm_mmap.c:374:(snd_pcm_mmap) mmap failed: No such device or
> address
> aplay: set_params:1297: Unable to install hw params:
> ACCESS:  RW_INTERLEAVED
> FORMAT:  S16_LE
> SUBFORMAT:  STD
> SAMPLE_BITS: 16
> FRAME_BITS: 32
> CHANNELS: 2
> RATE: 48000
> PERIOD_TIME: (21333 21334)
> PERIOD_SIZE: 1024
> PERIOD_BYTES: 4096
> PERIODS: 2
> BUFFER_TIME: (42666 42667)
> BUFFER_SIZE: 2048
> BUFFER_BYTES: 8192
> TICK_TIME: 0
> 
> dmesg:
> [  251.739831] dma_mmap_coherent returned 0, init_name = "(null)",
> dma_mask
> = ed804c40, *dma_mask = 4294967295, coherent_dma_mask = 4294967295,
> dma_pfn_offset = 0, vm_start = 3069702144, vm_end = 3069710336, vm_size
> =
> 8192, offset = 0, rb_subtree_gap = 0, vm_flags = 67371259, cpu_addr =
> f01d1000, dma_addr = 4266655744
> [  251.739857] dma_mmap_coherent returned -6, init_name = "(null)",
> dma_mask
> = ed804c40, *dma_mask = 4294967295, coherent_dma_mask = 4294967295,
> dma_pfn_offset = 0, vm_start = 3069693952, vm_end = 3069702144, vm_size
> =
> 8192, offset = 65536, rb_subtree_gap = 0, vm_flags = 67371259, cpu_addr =
> f01e1000, dma_addr = 4266721280
> 
> Thanks a lot
> Axel
> 
> > thanks,
> >
> > Takashi

With a lot of printk output I finally found out what's happening and I think
Takashi you mentioned that there is only one map area available, so I think
my findings proove that opinion of yours.

The problem is occurring in the following function in
arch/arm/mm/dma-mapping.c at around line 700:
/*
 * Create userspace mapping for the DMA-coherent memory.
 */
int arm_dma_mmap(struct device *dev, struct vm_area_struct *vma,
                 void *cpu_addr, dma_addr_t dma_addr, size_t size,
                 struct dma_attrs *attrs)
{
        int ret = -ENXIO;
#ifdef CONFIG_MMU
        unsigned long nr_vma_pages = (vma->vm_end - vma->vm_start) >>
PAGE_SHIFT;
        unsigned long nr_pages = PAGE_ALIGN(size) >> PAGE_SHIFT;
        unsigned long pfn = dma_to_pfn(dev, dma_addr);
        unsigned long off = vma->vm_pgoff;

        vma->vm_page_prot = __get_dma_pgprot(attrs, vma->vm_page_prot);

        if (dma_mmap_from_coherent(dev, vma, cpu_addr, size, &ret))
                return ret;

        if (off < nr_pages && nr_vma_pages <= (nr_pages - off)) {
                ret = remap_pfn_range(vma, vma->vm_start,
                                      pfn + off,
                                      vma->vm_end - vma->vm_start,
                                      vma->vm_page_prot);
        }
#endif  /* CONFIG_MMU */

        return ret;
}

When this function is called first (by snd_pcm_lib_default_mmap and so on)
the if clause is executed (calling remap_pfn_range) because of the following
parameters:
off = 0
nr_pages = 2
nr_vma_pages = 2
while when called the second time (because asking aplay to play a stereo
audio file) the parameters are these
off = 16
nr_pages = 2
nr_vma_pages = 2
and so the if clause is not executed, remap_pfn_range is not called and the
return value ret remains in its initialised state of -ENXIO
(dma_mmap_from_coherent is succeeding and so ret is not changed).

So what can I do to make this work?

Thank you
Axel



------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
Alsa-user mailing list
Alsa-user@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/alsa-user

Reply via email to