Message ID | 1494896518-23399-4-git-send-email-subhransu.s.prusty@intel.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Hi, On May 16 2017 10:01, Subhransu S. Prusty wrote: > From: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com> > > In case of mmap, by default alsa-lib mmaps both control and status data. > > If driver subscribes for application pointer update, driver needs to get > notification whenever appl ptr changes. With the above case driver won't > get appl ptr notifications. > > This patch check on a hw info flag and returns error when user land asks > for mmaping control & status data, thus forcing user to issue > IOCTL_SYNC_PTR. > > Suggested-by: Takashi Iwai <tiwai@suse.de> > Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com> > Signed-off-by: Ramesh Babu <ramesh.babu@intel.com> > Signed-off-by: Jaikrishna Nemallapudi <jaikrishnax.nemallapudi@intel.com> > Signed-off-by: Subhransu S. Prusty <subhransu.s.prusty@intel.com> > --- > include/uapi/sound/asound.h | 1 + > sound/core/pcm_native.c | 17 +++++++++++++++++ > 2 files changed, 18 insertions(+) Would you please explain about the case that drivers can't support page frame mapping, please? As long as I know, it depends on kernel and platform architecture whether mapping is available or not, because the data of 'struct snd_pcm_mmap_status' and 'struct snd_pcm_mmap_control' is not directly related to data transmission and independent of target device design. Of course, I can understand your intension for previous patches. But the code comment is quite misleading and worthless. > diff --git a/include/uapi/sound/asound.h b/include/uapi/sound/asound.h > index c697ff90450d..dea7d89b41ca 100644 > --- a/include/uapi/sound/asound.h > +++ b/include/uapi/sound/asound.h > @@ -284,6 +284,7 @@ enum { > #define SNDRV_PCM_INFO_HAS_LINK_ABSOLUTE_ATIME 0x02000000 /* report absolute hardware link audio time, not reset on startup */ > #define SNDRV_PCM_INFO_HAS_LINK_ESTIMATED_ATIME 0x04000000 /* report estimated link audio time */ > #define SNDRV_PCM_INFO_HAS_LINK_SYNCHRONIZED_ATIME 0x08000000 /* report synchronized audio/system time */ > +#define SNDRV_PCM_INFO_NO_STATUS_MMAP 0x10000000 /* status and control mmap not supported */ > > #define SNDRV_PCM_INFO_DRAIN_TRIGGER 0x40000000 /* internal kernel flag - trigger in drain */ > #define SNDRV_PCM_INFO_FIFO_IN_FRAMES 0x80000000 /* internal kernel flag - FIFO size is in frames */ > diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c > index c14cdbd9ff86..2635a7d4d1fa 100644 > --- a/sound/core/pcm_native.c > +++ b/sound/core/pcm_native.c > @@ -3524,21 +3524,38 @@ static int snd_pcm_mmap(struct file *file, struct vm_area_struct *area) > struct snd_pcm_file * pcm_file; > struct snd_pcm_substream *substream; > unsigned long offset; > + unsigned int info; > > pcm_file = file->private_data; > substream = pcm_file->substream; > if (PCM_RUNTIME_CHECK(substream)) > return -ENXIO; > + info = substream->runtime->hw.info; > > offset = area->vm_pgoff << PAGE_SHIFT; > switch (offset) { > case SNDRV_PCM_MMAP_OFFSET_STATUS: > if (pcm_file->no_compat_mmap) > return -ENXIO; > + /* > + * force fallback to ioctl if driver doesn't support status > + * and control mmap. > + */ > + if (info & SNDRV_PCM_INFO_NO_STATUS_MMAP) > + return -ENXIO; > + > return snd_pcm_mmap_status(substream, file, area); > case SNDRV_PCM_MMAP_OFFSET_CONTROL: > if (pcm_file->no_compat_mmap) > return -ENXIO; > + > + /* > + * force fallback to ioctl if driver doesn't support status > + * and control mmap. > + */ > + if (info & SNDRV_PCM_INFO_NO_STATUS_MMAP) > + return -ENXIO; > + > return snd_pcm_mmap_control(substream, file, area); > default: > return snd_pcm_mmap_data(substream, file, area); Regards Takashi Sakamoto
On Tue, 16 May 2017 07:38:40 +0200, Takashi Sakamoto wrote: > > Hi, > > On May 16 2017 10:01, Subhransu S. Prusty wrote: > > From: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com> > > > > In case of mmap, by default alsa-lib mmaps both control and status data. > > > > If driver subscribes for application pointer update, driver needs to get > > notification whenever appl ptr changes. With the above case driver won't > > get appl ptr notifications. > > > > This patch check on a hw info flag and returns error when user land asks > > for mmaping control & status data, thus forcing user to issue > > IOCTL_SYNC_PTR. > > > > Suggested-by: Takashi Iwai <tiwai@suse.de> > > Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com> > > Signed-off-by: Ramesh Babu <ramesh.babu@intel.com> > > Signed-off-by: Jaikrishna Nemallapudi <jaikrishnax.nemallapudi@intel.com> > > Signed-off-by: Subhransu S. Prusty <subhransu.s.prusty@intel.com> > > --- > > include/uapi/sound/asound.h | 1 + > > sound/core/pcm_native.c | 17 +++++++++++++++++ > > 2 files changed, 18 insertions(+) > > Would you please explain about the case that drivers can't support > page frame mapping, please? > > As long as I know, it depends on kernel and platform architecture > whether mapping is available or not, because the data of 'struct > snd_pcm_mmap_status' and 'struct snd_pcm_mmap_control' is not directly > related to data transmission and independent of target device design. It's only a part of the condition. In this case, the problem is that the mmap control allows the appl_ptr being changed silently without interaction with the driver. If the driver requires some explicit action for changing the appl_ptr, it won't work. > Of course, I can understand your intension for previous patches. But > the code comment is quite misleading and worthless. Worthless is a too strong word, but I agree that more clarification would be more helpful. thanks, Takashi > > > diff --git a/include/uapi/sound/asound.h b/include/uapi/sound/asound.h > > index c697ff90450d..dea7d89b41ca 100644 > > --- a/include/uapi/sound/asound.h > > +++ b/include/uapi/sound/asound.h > > @@ -284,6 +284,7 @@ enum { > > #define SNDRV_PCM_INFO_HAS_LINK_ABSOLUTE_ATIME 0x02000000 /* report absolute hardware link audio time, not reset on startup */ > > #define SNDRV_PCM_INFO_HAS_LINK_ESTIMATED_ATIME 0x04000000 /* report estimated link audio time */ > > #define SNDRV_PCM_INFO_HAS_LINK_SYNCHRONIZED_ATIME 0x08000000 /* report synchronized audio/system time */ > > +#define SNDRV_PCM_INFO_NO_STATUS_MMAP 0x10000000 /* status and control mmap not supported */ > > > > #define SNDRV_PCM_INFO_DRAIN_TRIGGER 0x40000000 /* internal kernel flag - trigger in drain */ > > #define SNDRV_PCM_INFO_FIFO_IN_FRAMES 0x80000000 /* internal kernel flag - FIFO size is in frames */ > > diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c > > index c14cdbd9ff86..2635a7d4d1fa 100644 > > --- a/sound/core/pcm_native.c > > +++ b/sound/core/pcm_native.c > > @@ -3524,21 +3524,38 @@ static int snd_pcm_mmap(struct file *file, struct vm_area_struct *area) > > struct snd_pcm_file * pcm_file; > > struct snd_pcm_substream *substream; > > unsigned long offset; > > + unsigned int info; > > > > pcm_file = file->private_data; > > substream = pcm_file->substream; > > if (PCM_RUNTIME_CHECK(substream)) > > return -ENXIO; > > + info = substream->runtime->hw.info; > > > > offset = area->vm_pgoff << PAGE_SHIFT; > > switch (offset) { > > case SNDRV_PCM_MMAP_OFFSET_STATUS: > > if (pcm_file->no_compat_mmap) > > return -ENXIO; > > + /* > > + * force fallback to ioctl if driver doesn't support status > > + * and control mmap. > > + */ > > + if (info & SNDRV_PCM_INFO_NO_STATUS_MMAP) > > + return -ENXIO; > > + > > return snd_pcm_mmap_status(substream, file, area); > > case SNDRV_PCM_MMAP_OFFSET_CONTROL: > > if (pcm_file->no_compat_mmap) > > return -ENXIO; > > + > > + /* > > + * force fallback to ioctl if driver doesn't support status > > + * and control mmap. > > + */ > > + if (info & SNDRV_PCM_INFO_NO_STATUS_MMAP) > > + return -ENXIO; > > + > > return snd_pcm_mmap_control(substream, file, area); > > default: > > return snd_pcm_mmap_data(substream, file, area); > > Regards > > Takashi Sakamoto >
On May 16 2017 14:46, Takashi Iwai wrote: > In this case, the problem is that the mmap control allows the appl_ptr > being changed silently without interaction with the driver. If the > driver requires some explicit action for changing the appl_ptr, it > won't work. I think 'struct snd_pcm_ops.pointer' is available for this purpose, too. static snd_pcm_sframes_t snd_pcm_playback_rewind(...) { ... hw_avail = snd_pcm_playback_hw_avail(runtime); (->struct snd_pcm_ops.pointer()) ... (rewind PCM frames) ... + substream->ops->pointer(...); (->struct snd_pcm_ops.pointer()) ... } If drivers need to handle event to update the appl_ptr, it records value of the appl_ptr, then compare it to current value to get the updates. I note that the callback is done in both of process/irq contexts. On May 16 2017 14:46, Takashi Iwai wrote: > Worthless is a too strong word, but I agree that more clarification > would be more helpful. Sorry to use such strong expression. I'll care of it. Regards Takashi Sakamoto
On Tue, 16 May 2017 07:57:30 +0200, Takashi Sakamoto wrote: > > On May 16 2017 14:46, Takashi Iwai wrote: > > In this case, the problem is that the mmap control allows the appl_ptr > > being changed silently without interaction with the driver. If the > > driver requires some explicit action for changing the appl_ptr, it > > won't work. > > I think 'struct snd_pcm_ops.pointer' is available for this purpose, too. > > static snd_pcm_sframes_t snd_pcm_playback_rewind(...) > { > ... > hw_avail = snd_pcm_playback_hw_avail(runtime); > (->struct snd_pcm_ops.pointer()) > ... > (rewind PCM frames) > ... > + substream->ops->pointer(...); > (->struct snd_pcm_ops.pointer()) > ... > } > > If drivers need to handle event to update the appl_ptr, it records > value of the appl_ptr, then compare it to current value to get the > updates. IIRC, the problem isn't about the forward / rewind but about the normal data transfer. In mmap mode, we transfer data on the mmap buffer, and update appl_ptr via mmap control. Both are done without notification to the driver (which is intentional for avoiding the context switching). So we want to disable this optimization and always notify to the driver. Disabling mmap status/control is the straight hack as it falls back to ioctl and then the driver can know the change. Takashi
On May 16 2017 15:18, Takashi Iwai wrote: > On Tue, 16 May 2017 07:57:30 +0200, > Takashi Sakamoto wrote: >> >> On May 16 2017 14:46, Takashi Iwai wrote: >>> In this case, the problem is that the mmap control allows the appl_ptr >>> being changed silently without interaction with the driver. If the >>> driver requires some explicit action for changing the appl_ptr, it >>> won't work. >> >> I think 'struct snd_pcm_ops.pointer' is available for this purpose, too. >> >> static snd_pcm_sframes_t snd_pcm_playback_rewind(...) >> { >> ... >> hw_avail = snd_pcm_playback_hw_avail(runtime); >> (->struct snd_pcm_ops.pointer()) >> ... >> (rewind PCM frames) >> ... >> + substream->ops->pointer(...); >> (->struct snd_pcm_ops.pointer()) >> ... >> } >> >> If drivers need to handle event to update the appl_ptr, it records >> value of the appl_ptr, then compare it to current value to get the >> updates. > > IIRC, the problem isn't about the forward / rewind but about the > normal data transfer. In mmap mode, we transfer data on the mmap > buffer, and update appl_ptr via mmap control. Both are done without > notification to the driver (which is intentional for avoiding the > context switching). > > So we want to disable this optimization and always notify to the > driver. Disabling mmap status/control is the straight hack as it > falls back to ioctl and then the driver can know the change. There's SNDRV_PCM_IOCTL_HW_SYNC command. In kernel land implementation, this command is handled with a call of 'struct snd_pcm_ops.pointer'. In alsa-lib, this command is often executed in most cases to handle PCM frames. Regards Takashi Sakamoto
On Tue, 16 May 2017 08:24:39 +0200, Takashi Sakamoto wrote: > > On May 16 2017 15:18, Takashi Iwai wrote: > > On Tue, 16 May 2017 07:57:30 +0200, > > Takashi Sakamoto wrote: > >> > >> On May 16 2017 14:46, Takashi Iwai wrote: > >>> In this case, the problem is that the mmap control allows the appl_ptr > >>> being changed silently without interaction with the driver. If the > >>> driver requires some explicit action for changing the appl_ptr, it > >>> won't work. > >> > >> I think 'struct snd_pcm_ops.pointer' is available for this purpose, too. > >> > >> static snd_pcm_sframes_t snd_pcm_playback_rewind(...) > >> { > >> ... > >> hw_avail = snd_pcm_playback_hw_avail(runtime); > >> (->struct snd_pcm_ops.pointer()) > >> ... > >> (rewind PCM frames) > >> ... > >> + substream->ops->pointer(...); > >> (->struct snd_pcm_ops.pointer()) > >> ... > >> } > >> > >> If drivers need to handle event to update the appl_ptr, it records > >> value of the appl_ptr, then compare it to current value to get the > >> updates. > > > > IIRC, the problem isn't about the forward / rewind but about the > > normal data transfer. In mmap mode, we transfer data on the mmap > > buffer, and update appl_ptr via mmap control. Both are done without > > notification to the driver (which is intentional for avoiding the > > context switching). > > > > So we want to disable this optimization and always notify to the > > driver. Disabling mmap status/control is the straight hack as it > > falls back to ioctl and then the driver can know the change. > > There's SNDRV_PCM_IOCTL_HW_SYNC command. In kernel land > implementation, this command is handled with a call of 'struct > snd_pcm_ops.pointer'. > > In alsa-lib, this command is often executed in most cases to handle > PCM frames. The HWSYNC or SYNC_PTR ioctls are used only as the fallback when mmap failed. It's the exact goal of this patch :) Takashi
On May 16 2017 15:34, Takashi Iwai wrote: >>> IIRC, the problem isn't about the forward / rewind but about the >>> normal data transfer. In mmap mode, we transfer data on the mmap >>> buffer, and update appl_ptr via mmap control. Both are done without >>> notification to the driver (which is intentional for avoiding the >>> context switching). >>> >>> So we want to disable this optimization and always notify to the >>> driver. Disabling mmap status/control is the straight hack as it >>> falls back to ioctl and then the driver can know the change. >> >> There's SNDRV_PCM_IOCTL_HW_SYNC command. In kernel land >> implementation, this command is handled with a call of 'struct >> snd_pcm_ops.pointer'. >> >> In alsa-lib, this command is often executed in most cases to handle >> PCM frames. > > The HWSYNC or SYNC_PTR ioctls are used only as the fallback when mmap > failed. It's the exact goal of this patch :) Although SYNC_PTR is in the fallback mechanism of alsa-lib, HWSYNC is not in. (alsa-lib) ioctl(SNDRV_PCM_IOCTL_HWSYNC) <-snd_pcm_hw_hw_sync() = struct snd_pcm_fast_ops.hwsync <-__snd_pcm_hw_hwsync() <-snd_pcm_hwsync() <-snd_pcm_avail() <-snd_pcm_read_areas() <-snd_pcm_mmap_readi() <-snd_pcm_mmap_readn() <-snd_pcm_avail_delay() <-snd_pcm_write_areas() <-snd_pcm_mmap_writei() <-snd_pcm_mmap_writen() For a case that applications execute ioctl(2) with SNDRV_PCM_IOCTL_READN/READI/WRITEN/WRITEI, in kernel land snd_pcm_lib_read1()/snd_pcm_lib_write1() should have calls of 'struct snd_pcm_ops.pointer', I think. Regards Takashi Sakamoto
On Tue, 16 May 2017 08:54:17 +0200, Takashi Sakamoto wrote: > > On May 16 2017 15:34, Takashi Iwai wrote: > >>> IIRC, the problem isn't about the forward / rewind but about the > >>> normal data transfer. In mmap mode, we transfer data on the mmap > >>> buffer, and update appl_ptr via mmap control. Both are done without > >>> notification to the driver (which is intentional for avoiding the > >>> context switching). > >>> > >>> So we want to disable this optimization and always notify to the > >>> driver. Disabling mmap status/control is the straight hack as it > >>> falls back to ioctl and then the driver can know the change. > >> > >> There's SNDRV_PCM_IOCTL_HW_SYNC command. In kernel land > >> implementation, this command is handled with a call of 'struct > >> snd_pcm_ops.pointer'. > >> > >> In alsa-lib, this command is often executed in most cases to handle > >> PCM frames. > > > > The HWSYNC or SYNC_PTR ioctls are used only as the fallback when mmap > > failed. It's the exact goal of this patch :) > > Although SYNC_PTR is in the fallback mechanism of alsa-lib, HWSYNC is > not in. > > (alsa-lib) > ioctl(SNDRV_PCM_IOCTL_HWSYNC) > <-snd_pcm_hw_hw_sync() > = struct snd_pcm_fast_ops.hwsync > <-__snd_pcm_hw_hwsync() > <-snd_pcm_hwsync() > <-snd_pcm_avail() > <-snd_pcm_read_areas() > <-snd_pcm_mmap_readi() > <-snd_pcm_mmap_readn() > <-snd_pcm_avail_delay() > <-snd_pcm_write_areas() > <-snd_pcm_mmap_writei() > <-snd_pcm_mmap_writen() > > For a case that applications execute ioctl(2) with > SNDRV_PCM_IOCTL_READN/READI/WRITEN/WRITEI, in kernel land > snd_pcm_lib_read1()/snd_pcm_lib_write1() should have calls of 'struct > snd_pcm_ops.pointer', I think. It's about the less-optimized code path with snd_pcm_mmap_read/write. For the code path calling snd_pcm_mmap_begin() / snd_pcm_mmap_commit(), there is no hwsync ioctl call. Takashi
On May 16 2017 16:02, Takashi Iwai wrote: > On Tue, 16 May 2017 08:54:17 +0200, > Takashi Sakamoto wrote: >> >> On May 16 2017 15:34, Takashi Iwai wrote: >>>>> IIRC, the problem isn't about the forward / rewind but about the >>>>> normal data transfer. In mmap mode, we transfer data on the mmap >>>>> buffer, and update appl_ptr via mmap control. Both are done without >>>>> notification to the driver (which is intentional for avoiding the >>>>> context switching). >>>>> >>>>> So we want to disable this optimization and always notify to the >>>>> driver. Disabling mmap status/control is the straight hack as it >>>>> falls back to ioctl and then the driver can know the change. >>>> >>>> There's SNDRV_PCM_IOCTL_HW_SYNC command. In kernel land >>>> implementation, this command is handled with a call of 'struct >>>> snd_pcm_ops.pointer'. >>>> >>>> In alsa-lib, this command is often executed in most cases to handle >>>> PCM frames. >>> >>> The HWSYNC or SYNC_PTR ioctls are used only as the fallback when mmap >>> failed. It's the exact goal of this patch :) >> >> Although SYNC_PTR is in the fallback mechanism of alsa-lib, HWSYNC is >> not in. >> >> (alsa-lib) >> ioctl(SNDRV_PCM_IOCTL_HWSYNC) >> <-snd_pcm_hw_hw_sync() >> = struct snd_pcm_fast_ops.hwsync >> <-__snd_pcm_hw_hwsync() >> <-snd_pcm_hwsync() >> <-snd_pcm_avail() >> <-snd_pcm_read_areas() >> <-snd_pcm_mmap_readi() >> <-snd_pcm_mmap_readn() >> <-snd_pcm_avail_delay() >> <-snd_pcm_write_areas() >> <-snd_pcm_mmap_writei() >> <-snd_pcm_mmap_writen() >> >> For a case that applications execute ioctl(2) with >> SNDRV_PCM_IOCTL_READN/READI/WRITEN/WRITEI, in kernel land >> snd_pcm_lib_read1()/snd_pcm_lib_write1() should have calls of 'struct >> snd_pcm_ops.pointer', I think. > > It's about the less-optimized code path with snd_pcm_mmap_read/write. > For the code path calling snd_pcm_mmap_begin() / > snd_pcm_mmap_commit(), there is no hwsync ioctl call. Indeed. I recalled it from my memory just after posting the previous message. In a case of the fallback, ioctl(2) with SYNC_PTR is surely executed: ioctl(SNDRV_PCM_IOCTL_SYNC_PTR) <-snd_pcm_hw_hw_mmap_commit) = struct snd_pcm_fast_ops.mmap_commit() <-__snd_pcm_mmap_commit() <-snd_pcm_mmap_commit() Now I agreed with the aim of this patch. In alsa-lib, 0 is passed as a 'flags' option to ioctl(2) with SYNC_PTR in the call of snd_pcm_mmap_commit(). In kernel land, overhead to handle the ioctl is lighter than HWSYNC because hwptr is not synchronized. However, in my opinion, disabling mmap the status and control data is exaggerated to the aim. SYNC_PTR ioctl is still available when page frame of these data is mapped. I can assume an idea to take alsa-lib to execute this command in snd_pcm_mmap_commit() when the NO_REWIND flag is enabled. Here, I assume that the flag and SYNC_PTR are tight coupling. (but we should concern about backward compatibility of relevant stuffs...) By the way, at present, I think that this patchset may also be convenient to IEC 611883-1/6 engine and drivers in ALSA firewire stack. The engine is programmed to execute packetization in both of irq context of OHCI1394 isochronous context and process context of HWSYNC, to reduce packetization delay for PCM data substream. However, to the process context, this design expects applications to call ioctl(2) periodically with some commands; e.g. HWSYNC. As Iwai-san said, this ioctl command is not executed in snd_pcm_mmap_begin()/snd_pcm_mmap_commit() loop and I had concerns about it. (For example, PulseAudio is programmed to execute snd_pcm_avail() in the loop, but jackd isn't.) But I forgot it, oops :p Thanks Takashi Sakamoto
diff --git a/include/uapi/sound/asound.h b/include/uapi/sound/asound.h index c697ff90450d..dea7d89b41ca 100644 --- a/include/uapi/sound/asound.h +++ b/include/uapi/sound/asound.h @@ -284,6 +284,7 @@ enum { #define SNDRV_PCM_INFO_HAS_LINK_ABSOLUTE_ATIME 0x02000000 /* report absolute hardware link audio time, not reset on startup */ #define SNDRV_PCM_INFO_HAS_LINK_ESTIMATED_ATIME 0x04000000 /* report estimated link audio time */ #define SNDRV_PCM_INFO_HAS_LINK_SYNCHRONIZED_ATIME 0x08000000 /* report synchronized audio/system time */ +#define SNDRV_PCM_INFO_NO_STATUS_MMAP 0x10000000 /* status and control mmap not supported */ #define SNDRV_PCM_INFO_DRAIN_TRIGGER 0x40000000 /* internal kernel flag - trigger in drain */ #define SNDRV_PCM_INFO_FIFO_IN_FRAMES 0x80000000 /* internal kernel flag - FIFO size is in frames */ diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index c14cdbd9ff86..2635a7d4d1fa 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -3524,21 +3524,38 @@ static int snd_pcm_mmap(struct file *file, struct vm_area_struct *area) struct snd_pcm_file * pcm_file; struct snd_pcm_substream *substream; unsigned long offset; + unsigned int info; pcm_file = file->private_data; substream = pcm_file->substream; if (PCM_RUNTIME_CHECK(substream)) return -ENXIO; + info = substream->runtime->hw.info; offset = area->vm_pgoff << PAGE_SHIFT; switch (offset) { case SNDRV_PCM_MMAP_OFFSET_STATUS: if (pcm_file->no_compat_mmap) return -ENXIO; + /* + * force fallback to ioctl if driver doesn't support status + * and control mmap. + */ + if (info & SNDRV_PCM_INFO_NO_STATUS_MMAP) + return -ENXIO; + return snd_pcm_mmap_status(substream, file, area); case SNDRV_PCM_MMAP_OFFSET_CONTROL: if (pcm_file->no_compat_mmap) return -ENXIO; + + /* + * force fallback to ioctl if driver doesn't support status + * and control mmap. + */ + if (info & SNDRV_PCM_INFO_NO_STATUS_MMAP) + return -ENXIO; + return snd_pcm_mmap_control(substream, file, area); default: return snd_pcm_mmap_data(substream, file, area);