ALSA: pcm: Disable only control mmap for explicit appl_ptr sync

Now that user-space (typically alsa-lib) can specify which protocol
version it supports, we can optimize the kernel code depending on the
reported protocol version.

In this patch, we change the previous hack for enforcing the appl_ptr
sync by disabling status/control mmap.  Instead of forcibly disabling
both mmaps, we disable only the control mmap when user-space declares
the supported protocol version new enough.  For older user-space,
still both PCM status and control mmaps are disabled when requested by
the driver due to the compatibility reason.

Reviewed-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
Takashi Iwai 2017-06-27 11:54:37 +02:00
parent 4b671f5774
commit b602aa8eb1
1 changed files with 17 additions and 5 deletions

View File

@ -3388,12 +3388,23 @@ static bool pcm_status_mmap_allowed(struct snd_pcm_file *pcm_file)
{
if (pcm_file->no_compat_mmap)
return false;
/* Disallow the status/control mmap when SYNC_APPLPTR flag is set;
/* See pcm_control_mmap_allowed() below.
* Since older alsa-lib requires both status and control mmaps to be
* coupled, we have to disable the status mmap for old alsa-lib, too.
*/
if (pcm_file->user_pversion < SNDRV_PROTOCOL_VERSION(2, 0, 14) &&
(pcm_file->substream->runtime->hw.info & SNDRV_PCM_INFO_SYNC_APPLPTR))
return false;
return true;
}
static bool pcm_control_mmap_allowed(struct snd_pcm_file *pcm_file)
{
if (pcm_file->no_compat_mmap)
return false;
/* Disallow the control mmap when SYNC_APPLPTR flag is set;
* it enforces the user-space to fall back to snd_pcm_sync_ptr(),
* thus it effectively assures the manual update of appl_ptr.
* In theory, it should be enough to disallow only PCM control mmap,
* but since the current alsa-lib implementation requires both status
* and control mmaps always paired, we have to disable both of them.
*/
if (pcm_file->substream->runtime->hw.info & SNDRV_PCM_INFO_SYNC_APPLPTR)
return false;
@ -3405,6 +3416,7 @@ static bool pcm_status_mmap_allowed(struct snd_pcm_file *pcm_file)
* don't support mmap for status and control records.
*/
#define pcm_status_mmap_allowed(pcm_file) false
#define pcm_control_mmap_allowed(pcm_file) false
static int snd_pcm_mmap_status(struct snd_pcm_substream *substream, struct file *file,
struct vm_area_struct *area)
@ -3593,7 +3605,7 @@ static int snd_pcm_mmap(struct file *file, struct vm_area_struct *area)
return -ENXIO;
return snd_pcm_mmap_status(substream, file, area);
case SNDRV_PCM_MMAP_OFFSET_CONTROL:
if (!pcm_status_mmap_allowed(pcm_file))
if (!pcm_control_mmap_allowed(pcm_file))
return -ENXIO;
return snd_pcm_mmap_control(substream, file, area);
default: