ALSA: pcm: Use guard() for PCM stream locks
authorTakashi Iwai <tiwai@suse.de>
Tue, 27 Feb 2024 08:53:04 +0000 (09:53 +0100)
committerTakashi Iwai <tiwai@suse.de>
Wed, 28 Feb 2024 14:01:22 +0000 (15:01 +0100)
Define guard() usage for PCM stream locking and use it in appropriate
places.

The pair of snd_pcm_stream_lock() and snd_pcm_stream_unlock() can be
presented with guard(pcm_stream_lock) now.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
Link: https://lore.kernel.org/r/20240227085306.9764-23-tiwai@suse.de
include/sound/pcm.h
sound/core/oss/pcm_oss.c
sound/core/pcm_compat.c
sound/core/pcm_lib.c
sound/core/pcm_native.c

index cc175c623dac71d63062beb2441f5b94ec35d346..210096f124eed5765960b2b512954fb3dfa5c4ec 100644 (file)
@@ -659,6 +659,18 @@ void snd_pcm_stream_unlock_irqrestore(struct snd_pcm_substream *substream,
                flags = _snd_pcm_stream_lock_irqsave_nested(substream); \
        } while (0)
 
+/* definitions for guard(); use like guard(pcm_stream_lock) */
+DEFINE_LOCK_GUARD_1(pcm_stream_lock, struct snd_pcm_substream,
+                   snd_pcm_stream_lock(_T->lock),
+                   snd_pcm_stream_unlock(_T->lock))
+DEFINE_LOCK_GUARD_1(pcm_stream_lock_irq, struct snd_pcm_substream,
+                   snd_pcm_stream_lock_irq(_T->lock),
+                   snd_pcm_stream_unlock_irq(_T->lock))
+DEFINE_LOCK_GUARD_1(pcm_stream_lock_irqsave, struct snd_pcm_substream,
+                   snd_pcm_stream_lock_irqsave(_T->lock, _T->flags),
+                   snd_pcm_stream_unlock_irqrestore(_T->lock, _T->flags),
+                   unsigned long flags)
+
 /**
  * snd_pcm_group_for_each_entry - iterate over the linked substreams
  * @s: the iterator
index e4e292b2db06e961a7c682401316fde428243df0..49ea092e90f96762fa02c3459cf981f450de68d3 100644 (file)
@@ -1623,9 +1623,8 @@ static int snd_pcm_oss_sync1(struct snd_pcm_substream *substream, size_t size)
                        break;
                result = 0;
                set_current_state(TASK_INTERRUPTIBLE);
-               snd_pcm_stream_lock_irq(substream);
-               state = runtime->state;
-               snd_pcm_stream_unlock_irq(substream);
+               scoped_guard(pcm_stream_lock_irq, substream)
+                       state = runtime->state;
                if (state != SNDRV_PCM_STATE_RUNNING) {
                        set_current_state(TASK_RUNNING);
                        break;
@@ -2840,23 +2839,23 @@ static __poll_t snd_pcm_oss_poll(struct file *file, poll_table * wait)
        if (psubstream != NULL) {
                struct snd_pcm_runtime *runtime = psubstream->runtime;
                poll_wait(file, &runtime->sleep, wait);
-               snd_pcm_stream_lock_irq(psubstream);
-               if (runtime->state != SNDRV_PCM_STATE_DRAINING &&
-                   (runtime->state != SNDRV_PCM_STATE_RUNNING ||
-                    snd_pcm_oss_playback_ready(psubstream)))
-                       mask |= EPOLLOUT | EPOLLWRNORM;
-               snd_pcm_stream_unlock_irq(psubstream);
+               scoped_guard(pcm_stream_lock_irq, psubstream) {
+                       if (runtime->state != SNDRV_PCM_STATE_DRAINING &&
+                           (runtime->state != SNDRV_PCM_STATE_RUNNING ||
+                            snd_pcm_oss_playback_ready(psubstream)))
+                               mask |= EPOLLOUT | EPOLLWRNORM;
+               }
        }
        if (csubstream != NULL) {
                struct snd_pcm_runtime *runtime = csubstream->runtime;
                snd_pcm_state_t ostate;
                poll_wait(file, &runtime->sleep, wait);
-               snd_pcm_stream_lock_irq(csubstream);
-               ostate = runtime->state;
-               if (ostate != SNDRV_PCM_STATE_RUNNING ||
-                   snd_pcm_oss_capture_ready(csubstream))
-                       mask |= EPOLLIN | EPOLLRDNORM;
-               snd_pcm_stream_unlock_irq(csubstream);
+               scoped_guard(pcm_stream_lock_irq, csubstream) {
+                       ostate = runtime->state;
+                       if (ostate != SNDRV_PCM_STATE_RUNNING ||
+                           snd_pcm_oss_capture_ready(csubstream))
+                               mask |= EPOLLIN | EPOLLRDNORM;
+               }
                if (ostate != SNDRV_PCM_STATE_RUNNING && runtime->oss.trigger) {
                        struct snd_pcm_oss_file ofile;
                        memset(&ofile, 0, sizeof(ofile));
index ef3c0d17751049336e56356046c6a69b8bf60153..a42ec7f5a1daf0688b758e56d5fcf09959cec8de 100644 (file)
@@ -432,22 +432,22 @@ static int snd_pcm_ioctl_sync_ptr_x32(struct snd_pcm_substream *substream,
        boundary = recalculate_boundary(runtime);
        if (!boundary)
                boundary = 0x7fffffff;
-       snd_pcm_stream_lock_irq(substream);
-       /* FIXME: we should consider the boundary for the sync from app */
-       if (!(sflags & SNDRV_PCM_SYNC_PTR_APPL))
-               control->appl_ptr = scontrol.appl_ptr;
-       else
-               scontrol.appl_ptr = control->appl_ptr % boundary;
-       if (!(sflags & SNDRV_PCM_SYNC_PTR_AVAIL_MIN))
-               control->avail_min = scontrol.avail_min;
-       else
-               scontrol.avail_min = control->avail_min;
-       sstatus.state = status->state;
-       sstatus.hw_ptr = status->hw_ptr % boundary;
-       sstatus.tstamp = status->tstamp;
-       sstatus.suspended_state = status->suspended_state;
-       sstatus.audio_tstamp = status->audio_tstamp;
-       snd_pcm_stream_unlock_irq(substream);
+       scoped_guard(pcm_stream_lock_irq, substream) {
+               /* FIXME: we should consider the boundary for the sync from app */
+               if (!(sflags & SNDRV_PCM_SYNC_PTR_APPL))
+                       control->appl_ptr = scontrol.appl_ptr;
+               else
+                       scontrol.appl_ptr = control->appl_ptr % boundary;
+               if (!(sflags & SNDRV_PCM_SYNC_PTR_AVAIL_MIN))
+                       control->avail_min = scontrol.avail_min;
+               else
+                       scontrol.avail_min = control->avail_min;
+               sstatus.state = status->state;
+               sstatus.hw_ptr = status->hw_ptr % boundary;
+               sstatus.tstamp = status->tstamp;
+               sstatus.suspended_state = status->suspended_state;
+               sstatus.audio_tstamp = status->audio_tstamp;
+       }
        if (!(sflags & SNDRV_PCM_SYNC_PTR_APPL))
                snd_pcm_dma_buffer_sync(substream, SNDRV_DMA_SYNC_DEVICE);
        if (put_user(sstatus.state, &src->s.status.state) ||
@@ -510,26 +510,24 @@ static int snd_pcm_ioctl_sync_ptr_buggy(struct snd_pcm_substream *substream,
                if (err < 0)
                        return err;
        }
-       snd_pcm_stream_lock_irq(substream);
-       if (!(sync_ptr.flags & SNDRV_PCM_SYNC_PTR_APPL)) {
-               err = pcm_lib_apply_appl_ptr(substream, sync_cp->appl_ptr);
-               if (err < 0) {
-                       snd_pcm_stream_unlock_irq(substream);
-                       return err;
+       scoped_guard(pcm_stream_lock_irq, substream) {
+               if (!(sync_ptr.flags & SNDRV_PCM_SYNC_PTR_APPL)) {
+                       err = pcm_lib_apply_appl_ptr(substream, sync_cp->appl_ptr);
+                       if (err < 0)
+                               return err;
+               } else {
+                       sync_cp->appl_ptr = control->appl_ptr;
                }
-       } else {
-               sync_cp->appl_ptr = control->appl_ptr;
+               if (!(sync_ptr.flags & SNDRV_PCM_SYNC_PTR_AVAIL_MIN))
+                       control->avail_min = sync_cp->avail_min;
+               else
+                       sync_cp->avail_min = control->avail_min;
+               sync_ptr.s.status.state = status->state;
+               sync_ptr.s.status.hw_ptr = status->hw_ptr;
+               sync_ptr.s.status.tstamp = status->tstamp;
+               sync_ptr.s.status.suspended_state = status->suspended_state;
+               sync_ptr.s.status.audio_tstamp = status->audio_tstamp;
        }
-       if (!(sync_ptr.flags & SNDRV_PCM_SYNC_PTR_AVAIL_MIN))
-               control->avail_min = sync_cp->avail_min;
-       else
-               sync_cp->avail_min = control->avail_min;
-       sync_ptr.s.status.state = status->state;
-       sync_ptr.s.status.hw_ptr = status->hw_ptr;
-       sync_ptr.s.status.tstamp = status->tstamp;
-       sync_ptr.s.status.suspended_state = status->suspended_state;
-       sync_ptr.s.status.audio_tstamp = status->audio_tstamp;
-       snd_pcm_stream_unlock_irq(substream);
        if (!(sync_ptr.flags & SNDRV_PCM_SYNC_PTR_APPL))
                snd_pcm_dma_buffer_sync(substream, SNDRV_DMA_SYNC_DEVICE);
        if (copy_to_user(_sync_ptr, &sync_ptr, sizeof(sync_ptr)))
index 41103e5c43ce5bf852908a3b72ed73468f21695a..6f73b3c2c205ee201552fb4fb1b2efbc6a63b1d0 100644 (file)
@@ -1744,8 +1744,8 @@ static int snd_pcm_lib_ioctl_reset(struct snd_pcm_substream *substream,
                                   void *arg)
 {
        struct snd_pcm_runtime *runtime = substream->runtime;
-       unsigned long flags;
-       snd_pcm_stream_lock_irqsave(substream, flags);
+
+       guard(pcm_stream_lock_irqsave)(substream);
        if (snd_pcm_running(substream) &&
            snd_pcm_update_hw_ptr(substream) >= 0)
                runtime->status->hw_ptr %= runtime->buffer_size;
@@ -1753,7 +1753,6 @@ static int snd_pcm_lib_ioctl_reset(struct snd_pcm_substream *substream,
                runtime->status->hw_ptr = 0;
                runtime->hw_ptr_wrap = 0;
        }
-       snd_pcm_stream_unlock_irqrestore(substream, flags);
        return 0;
 }
 
@@ -1899,14 +1898,11 @@ EXPORT_SYMBOL(snd_pcm_period_elapsed_under_stream_lock);
  */
 void snd_pcm_period_elapsed(struct snd_pcm_substream *substream)
 {
-       unsigned long flags;
-
        if (snd_BUG_ON(!substream))
                return;
 
-       snd_pcm_stream_lock_irqsave(substream, flags);
+       guard(pcm_stream_lock_irqsave)(substream);
        snd_pcm_period_elapsed_under_stream_lock(substream);
-       snd_pcm_stream_unlock_irqrestore(substream, flags);
 }
 EXPORT_SYMBOL(snd_pcm_period_elapsed);
 
index f2a0cbb25bb74615cd780e69bdc9d22f2cd2ecf1..c1396c802409178acabfede3fafe92de77c74c04 100644 (file)
@@ -604,10 +604,9 @@ static int period_to_usecs(struct snd_pcm_runtime *runtime)
 static void snd_pcm_set_state(struct snd_pcm_substream *substream,
                              snd_pcm_state_t state)
 {
-       snd_pcm_stream_lock_irq(substream);
+       guard(pcm_stream_lock_irq)(substream);
        if (substream->runtime->state != SNDRV_PCM_STATE_DISCONNECTED)
                __snd_pcm_set_state(substream->runtime, state);
-       snd_pcm_stream_unlock_irq(substream);
 }
 
 static inline void snd_pcm_timer_notify(struct snd_pcm_substream *substream,
@@ -733,20 +732,20 @@ static int snd_pcm_hw_params(struct snd_pcm_substream *substream,
        err = snd_pcm_buffer_access_lock(runtime);
        if (err < 0)
                return err;
-       snd_pcm_stream_lock_irq(substream);
-       switch (runtime->state) {
-       case SNDRV_PCM_STATE_OPEN:
-       case SNDRV_PCM_STATE_SETUP:
-       case SNDRV_PCM_STATE_PREPARED:
-               if (!is_oss_stream(substream) &&
-                   atomic_read(&substream->mmap_count))
+       scoped_guard(pcm_stream_lock_irq, substream) {
+               switch (runtime->state) {
+               case SNDRV_PCM_STATE_OPEN:
+               case SNDRV_PCM_STATE_SETUP:
+               case SNDRV_PCM_STATE_PREPARED:
+                       if (!is_oss_stream(substream) &&
+                           atomic_read(&substream->mmap_count))
+                               err = -EBADFD;
+                       break;
+               default:
                        err = -EBADFD;
-               break;
-       default:
-               err = -EBADFD;
-               break;
+                       break;
+               }
        }
-       snd_pcm_stream_unlock_irq(substream);
        if (err)
                goto unlock;
 
@@ -896,18 +895,18 @@ static int snd_pcm_hw_free(struct snd_pcm_substream *substream)
        result = snd_pcm_buffer_access_lock(runtime);
        if (result < 0)
                return result;
-       snd_pcm_stream_lock_irq(substream);
-       switch (runtime->state) {
-       case SNDRV_PCM_STATE_SETUP:
-       case SNDRV_PCM_STATE_PREPARED:
-               if (atomic_read(&substream->mmap_count))
+       scoped_guard(pcm_stream_lock_irq, substream) {
+               switch (runtime->state) {
+               case SNDRV_PCM_STATE_SETUP:
+               case SNDRV_PCM_STATE_PREPARED:
+                       if (atomic_read(&substream->mmap_count))
+                               result = -EBADFD;
+                       break;
+               default:
                        result = -EBADFD;
-               break;
-       default:
-               result = -EBADFD;
-               break;
+                       break;
+               }
        }
-       snd_pcm_stream_unlock_irq(substream);
        if (result)
                goto unlock;
        result = do_hw_free(substream);
@@ -927,12 +926,10 @@ static int snd_pcm_sw_params(struct snd_pcm_substream *substream,
        if (PCM_RUNTIME_CHECK(substream))
                return -ENXIO;
        runtime = substream->runtime;
-       snd_pcm_stream_lock_irq(substream);
-       if (runtime->state == SNDRV_PCM_STATE_OPEN) {
-               snd_pcm_stream_unlock_irq(substream);
-               return -EBADFD;
+       scoped_guard(pcm_stream_lock_irq, substream) {
+               if (runtime->state == SNDRV_PCM_STATE_OPEN)
+                       return -EBADFD;
        }
-       snd_pcm_stream_unlock_irq(substream);
 
        if (params->tstamp_mode < 0 ||
            params->tstamp_mode > SNDRV_PCM_TSTAMP_LAST)
@@ -952,24 +949,24 @@ static int snd_pcm_sw_params(struct snd_pcm_substream *substream,
                        return -EINVAL;
        }
        err = 0;
-       snd_pcm_stream_lock_irq(substream);
-       runtime->tstamp_mode = params->tstamp_mode;
-       if (params->proto >= SNDRV_PROTOCOL_VERSION(2, 0, 12))
-               runtime->tstamp_type = params->tstamp_type;
-       runtime->period_step = params->period_step;
-       runtime->control->avail_min = params->avail_min;
-       runtime->start_threshold = params->start_threshold;
-       runtime->stop_threshold = params->stop_threshold;
-       runtime->silence_threshold = params->silence_threshold;
-       runtime->silence_size = params->silence_size;
-        params->boundary = runtime->boundary;
-       if (snd_pcm_running(substream)) {
-               if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
-                   runtime->silence_size > 0)
-                       snd_pcm_playback_silence(substream, ULONG_MAX);
-               err = snd_pcm_update_state(substream, runtime);
+       scoped_guard(pcm_stream_lock_irq, substream) {
+               runtime->tstamp_mode = params->tstamp_mode;
+               if (params->proto >= SNDRV_PROTOCOL_VERSION(2, 0, 12))
+                       runtime->tstamp_type = params->tstamp_type;
+               runtime->period_step = params->period_step;
+               runtime->control->avail_min = params->avail_min;
+               runtime->start_threshold = params->start_threshold;
+               runtime->stop_threshold = params->stop_threshold;
+               runtime->silence_threshold = params->silence_threshold;
+               runtime->silence_size = params->silence_size;
+               params->boundary = runtime->boundary;
+               if (snd_pcm_running(substream)) {
+                       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
+                           runtime->silence_size > 0)
+                               snd_pcm_playback_silence(substream, ULONG_MAX);
+                       err = snd_pcm_update_state(substream, runtime);
+               }
        }
-       snd_pcm_stream_unlock_irq(substream);
        return err;
 }
 
@@ -1003,7 +1000,7 @@ int snd_pcm_status64(struct snd_pcm_substream *substream,
 {
        struct snd_pcm_runtime *runtime = substream->runtime;
 
-       snd_pcm_stream_lock_irq(substream);
+       guard(pcm_stream_lock_irq)(substream);
 
        snd_pcm_unpack_audio_tstamp_config(status->audio_tstamp_data,
                                        &runtime->audio_tstamp_config);
@@ -1024,7 +1021,7 @@ int snd_pcm_status64(struct snd_pcm_substream *substream,
        status->state = runtime->state;
        status->suspended_state = runtime->suspended_state;
        if (status->state == SNDRV_PCM_STATE_OPEN)
-               goto _end;
+               return 0;
        status->trigger_tstamp_sec = runtime->trigger_tstamp.tv_sec;
        status->trigger_tstamp_nsec = runtime->trigger_tstamp.tv_nsec;
        if (snd_pcm_running(substream)) {
@@ -1069,8 +1066,6 @@ int snd_pcm_status64(struct snd_pcm_substream *substream,
        status->overrange = runtime->overrange;
        runtime->avail_max = 0;
        runtime->overrange = 0;
- _end:
-       snd_pcm_stream_unlock_irq(substream);
        return 0;
 }
 
@@ -1155,12 +1150,10 @@ static int snd_pcm_channel_info(struct snd_pcm_substream *substream,
        
        channel = info->channel;
        runtime = substream->runtime;
-       snd_pcm_stream_lock_irq(substream);
-       if (runtime->state == SNDRV_PCM_STATE_OPEN) {
-               snd_pcm_stream_unlock_irq(substream);
-               return -EBADFD;
+       scoped_guard(pcm_stream_lock_irq, substream) {
+               if (runtime->state == SNDRV_PCM_STATE_OPEN)
+                       return -EBADFD;
        }
-       snd_pcm_stream_unlock_irq(substream);
        if (channel >= runtime->channels)
                return -EINVAL;
        memset(info, 0, sizeof(*info));
@@ -1381,12 +1374,8 @@ static int snd_pcm_action_lock_irq(const struct action_ops *ops,
                                   struct snd_pcm_substream *substream,
                                   snd_pcm_state_t state)
 {
-       int res;
-
-       snd_pcm_stream_lock_irq(substream);
-       res = snd_pcm_action(ops, substream, state);
-       snd_pcm_stream_unlock_irq(substream);
-       return res;
+       guard(pcm_stream_lock_irq)(substream);
+       return snd_pcm_action(ops, substream, state);
 }
 
 /*
@@ -1576,12 +1565,9 @@ int snd_pcm_drain_done(struct snd_pcm_substream *substream)
  */
 int snd_pcm_stop_xrun(struct snd_pcm_substream *substream)
 {
-       unsigned long flags;
-
-       snd_pcm_stream_lock_irqsave(substream, flags);
+       guard(pcm_stream_lock_irqsave)(substream);
        if (substream->runtime && snd_pcm_running(substream))
                __snd_pcm_xrun(substream);
-       snd_pcm_stream_unlock_irqrestore(substream, flags);
        return 0;
 }
 EXPORT_SYMBOL_GPL(snd_pcm_stop_xrun);
@@ -1733,14 +1719,9 @@ static const struct action_ops snd_pcm_action_suspend = {
  */
 static int snd_pcm_suspend(struct snd_pcm_substream *substream)
 {
-       int err;
-       unsigned long flags;
-
-       snd_pcm_stream_lock_irqsave(substream, flags);
-       err = snd_pcm_action(&snd_pcm_action_suspend, substream,
-                            ACTION_ARG_IGNORE);
-       snd_pcm_stream_unlock_irqrestore(substream, flags);
-       return err;
+       guard(pcm_stream_lock_irqsave)(substream);
+       return snd_pcm_action(&snd_pcm_action_suspend, substream,
+                             ACTION_ARG_IGNORE);
 }
 
 /**
@@ -1856,22 +1837,17 @@ static int snd_pcm_resume(struct snd_pcm_substream *substream)
 static int snd_pcm_xrun(struct snd_pcm_substream *substream)
 {
        struct snd_pcm_runtime *runtime = substream->runtime;
-       int result;
 
-       snd_pcm_stream_lock_irq(substream);
+       guard(pcm_stream_lock_irq)(substream);
        switch (runtime->state) {
        case SNDRV_PCM_STATE_XRUN:
-               result = 0;     /* already there */
-               break;
+               return 0;       /* already there */
        case SNDRV_PCM_STATE_RUNNING:
                __snd_pcm_xrun(substream);
-               result = 0;
-               break;
+               return 0;
        default:
-               result = -EBADFD;
+               return -EBADFD;
        }
-       snd_pcm_stream_unlock_irq(substream);
-       return result;
 }
 
 /*
@@ -1900,13 +1876,12 @@ static int snd_pcm_do_reset(struct snd_pcm_substream *substream,
        int err = snd_pcm_ops_ioctl(substream, SNDRV_PCM_IOCTL1_RESET, NULL);
        if (err < 0)
                return err;
-       snd_pcm_stream_lock_irq(substream);
+       guard(pcm_stream_lock_irq)(substream);
        runtime->hw_ptr_base = 0;
        runtime->hw_ptr_interrupt = runtime->status->hw_ptr -
                runtime->status->hw_ptr % runtime->period_size;
        runtime->silence_start = runtime->status->hw_ptr;
        runtime->silence_filled = 0;
-       snd_pcm_stream_unlock_irq(substream);
        return 0;
 }
 
@@ -1914,12 +1889,11 @@ static void snd_pcm_post_reset(struct snd_pcm_substream *substream,
                               snd_pcm_state_t state)
 {
        struct snd_pcm_runtime *runtime = substream->runtime;
-       snd_pcm_stream_lock_irq(substream);
+       guard(pcm_stream_lock_irq)(substream);
        runtime->control->appl_ptr = runtime->status->hw_ptr;
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
            runtime->silence_size > 0)
                snd_pcm_playback_silence(substream, ULONG_MAX);
-       snd_pcm_stream_unlock_irq(substream);
 }
 
 static const struct action_ops snd_pcm_action_reset = {
@@ -1995,16 +1969,16 @@ static int snd_pcm_prepare(struct snd_pcm_substream *substream,
        else
                f_flags = substream->f_flags;
 
-       snd_pcm_stream_lock_irq(substream);
-       switch (substream->runtime->state) {
-       case SNDRV_PCM_STATE_PAUSED:
-               snd_pcm_pause(substream, false);
-               fallthrough;
-       case SNDRV_PCM_STATE_SUSPENDED:
-               snd_pcm_stop(substream, SNDRV_PCM_STATE_SETUP);
-               break;
+       scoped_guard(pcm_stream_lock_irq, substream) {
+               switch (substream->runtime->state) {
+               case SNDRV_PCM_STATE_PAUSED:
+                       snd_pcm_pause(substream, false);
+                       fallthrough;
+               case SNDRV_PCM_STATE_SUSPENDED:
+                       snd_pcm_stop(substream, SNDRV_PCM_STATE_SETUP);
+                       break;
+               }
        }
-       snd_pcm_stream_unlock_irq(substream);
 
        return snd_pcm_action_nonatomic(&snd_pcm_action_prepare,
                                        substream,
@@ -2221,14 +2195,13 @@ static int snd_pcm_drop(struct snd_pcm_substream *substream)
            runtime->state == SNDRV_PCM_STATE_DISCONNECTED)
                return -EBADFD;
 
-       snd_pcm_stream_lock_irq(substream);
+       guard(pcm_stream_lock_irq)(substream);
        /* resume pause */
        if (runtime->state == SNDRV_PCM_STATE_PAUSED)
                snd_pcm_pause(substream, false);
 
        snd_pcm_stop(substream, SNDRV_PCM_STATE_SETUP);
        /* runtime->control->appl_ptr = runtime->status->hw_ptr; */
-       snd_pcm_stream_unlock_irq(substream);
 
        return result;
 }
@@ -2288,13 +2261,13 @@ static int snd_pcm_link(struct snd_pcm_substream *substream, int fd)
        if (snd_pcm_stream_linked(substream1))
                return -EALREADY;
 
-       snd_pcm_stream_lock_irq(substream);
-       if (!snd_pcm_stream_linked(substream)) {
-               snd_pcm_group_assign(substream, group);
-               group = NULL; /* assigned, don't free this one below */
+       scoped_guard(pcm_stream_lock_irq, substream) {
+               if (!snd_pcm_stream_linked(substream)) {
+                       snd_pcm_group_assign(substream, group);
+                       group = NULL; /* assigned, don't free this one below */
+               }
+               target_group = substream->group;
        }
-       target_group = substream->group;
-       snd_pcm_stream_unlock_irq(substream);
 
        snd_pcm_group_lock_irq(target_group, nonatomic);
        snd_pcm_stream_lock_nested(substream1);
@@ -3000,12 +2973,12 @@ static snd_pcm_sframes_t snd_pcm_rewind(struct snd_pcm_substream *substream,
        if (frames == 0)
                return 0;
 
-       snd_pcm_stream_lock_irq(substream);
-       ret = do_pcm_hwsync(substream);
-       if (!ret)
-               ret = rewind_appl_ptr(substream, frames,
-                                     snd_pcm_hw_avail(substream));
-       snd_pcm_stream_unlock_irq(substream);
+       scoped_guard(pcm_stream_lock_irq, substream) {
+               ret = do_pcm_hwsync(substream);
+               if (!ret)
+                       ret = rewind_appl_ptr(substream, frames,
+                                             snd_pcm_hw_avail(substream));
+       }
        if (ret >= 0)
                snd_pcm_dma_buffer_sync(substream, SNDRV_DMA_SYNC_DEVICE);
        return ret;
@@ -3019,12 +2992,12 @@ static snd_pcm_sframes_t snd_pcm_forward(struct snd_pcm_substream *substream,
        if (frames == 0)
                return 0;
 
-       snd_pcm_stream_lock_irq(substream);
-       ret = do_pcm_hwsync(substream);
-       if (!ret)
-               ret = forward_appl_ptr(substream, frames,
-                                      snd_pcm_avail(substream));
-       snd_pcm_stream_unlock_irq(substream);
+       scoped_guard(pcm_stream_lock_irq, substream) {
+               ret = do_pcm_hwsync(substream);
+               if (!ret)
+                       ret = forward_appl_ptr(substream, frames,
+                                              snd_pcm_avail(substream));
+       }
        if (ret >= 0)
                snd_pcm_dma_buffer_sync(substream, SNDRV_DMA_SYNC_DEVICE);
        return ret;
@@ -3035,11 +3008,11 @@ static int snd_pcm_delay(struct snd_pcm_substream *substream,
 {
        int err;
 
-       snd_pcm_stream_lock_irq(substream);
-       err = do_pcm_hwsync(substream);
-       if (delay && !err)
-               *delay = snd_pcm_calc_delay(substream);
-       snd_pcm_stream_unlock_irq(substream);
+       scoped_guard(pcm_stream_lock_irq, substream) {
+               err = do_pcm_hwsync(substream);
+               if (delay && !err)
+                       *delay = snd_pcm_calc_delay(substream);
+       }
        snd_pcm_dma_buffer_sync(substream, SNDRV_DMA_SYNC_CPU);
 
        return err;
@@ -3071,27 +3044,25 @@ static int snd_pcm_sync_ptr(struct snd_pcm_substream *substream,
                if (err < 0)
                        return err;
        }
-       snd_pcm_stream_lock_irq(substream);
-       if (!(sync_ptr.flags & SNDRV_PCM_SYNC_PTR_APPL)) {
-               err = pcm_lib_apply_appl_ptr(substream,
-                                            sync_ptr.c.control.appl_ptr);
-               if (err < 0) {
-                       snd_pcm_stream_unlock_irq(substream);
-                       return err;
+       scoped_guard(pcm_stream_lock_irq, substream) {
+               if (!(sync_ptr.flags & SNDRV_PCM_SYNC_PTR_APPL)) {
+                       err = pcm_lib_apply_appl_ptr(substream,
+                                                    sync_ptr.c.control.appl_ptr);
+                       if (err < 0)
+                               return err;
+               } else {
+                       sync_ptr.c.control.appl_ptr = control->appl_ptr;
                }
-       } else {
-               sync_ptr.c.control.appl_ptr = control->appl_ptr;
+               if (!(sync_ptr.flags & SNDRV_PCM_SYNC_PTR_AVAIL_MIN))
+                       control->avail_min = sync_ptr.c.control.avail_min;
+               else
+                       sync_ptr.c.control.avail_min = control->avail_min;
+               sync_ptr.s.status.state = status->state;
+               sync_ptr.s.status.hw_ptr = status->hw_ptr;
+               sync_ptr.s.status.tstamp = status->tstamp;
+               sync_ptr.s.status.suspended_state = status->suspended_state;
+               sync_ptr.s.status.audio_tstamp = status->audio_tstamp;
        }
-       if (!(sync_ptr.flags & SNDRV_PCM_SYNC_PTR_AVAIL_MIN))
-               control->avail_min = sync_ptr.c.control.avail_min;
-       else
-               sync_ptr.c.control.avail_min = control->avail_min;
-       sync_ptr.s.status.state = status->state;
-       sync_ptr.s.status.hw_ptr = status->hw_ptr;
-       sync_ptr.s.status.tstamp = status->tstamp;
-       sync_ptr.s.status.suspended_state = status->suspended_state;
-       sync_ptr.s.status.audio_tstamp = status->audio_tstamp;
-       snd_pcm_stream_unlock_irq(substream);
        if (!(sync_ptr.flags & SNDRV_PCM_SYNC_PTR_APPL))
                snd_pcm_dma_buffer_sync(substream, SNDRV_DMA_SYNC_DEVICE);
        if (copy_to_user(_sync_ptr, &sync_ptr, sizeof(sync_ptr)))
@@ -3169,27 +3140,25 @@ static int snd_pcm_ioctl_sync_ptr_compat(struct snd_pcm_substream *substream,
        boundary = recalculate_boundary(runtime);
        if (! boundary)
                boundary = 0x7fffffff;
-       snd_pcm_stream_lock_irq(substream);
-       /* FIXME: we should consider the boundary for the sync from app */
-       if (!(sflags & SNDRV_PCM_SYNC_PTR_APPL)) {
-               err = pcm_lib_apply_appl_ptr(substream,
-                               scontrol.appl_ptr);
-               if (err < 0) {
-                       snd_pcm_stream_unlock_irq(substream);
-                       return err;
-               }
-       } else
-               scontrol.appl_ptr = control->appl_ptr % boundary;
-       if (!(sflags & SNDRV_PCM_SYNC_PTR_AVAIL_MIN))
-               control->avail_min = scontrol.avail_min;
-       else
-               scontrol.avail_min = control->avail_min;
-       sstatus.state = status->state;
-       sstatus.hw_ptr = status->hw_ptr % boundary;
-       sstatus.tstamp = status->tstamp;
-       sstatus.suspended_state = status->suspended_state;
-       sstatus.audio_tstamp = status->audio_tstamp;
-       snd_pcm_stream_unlock_irq(substream);
+       scoped_guard(pcm_stream_lock_irq, substream) {
+               /* FIXME: we should consider the boundary for the sync from app */
+               if (!(sflags & SNDRV_PCM_SYNC_PTR_APPL)) {
+                       err = pcm_lib_apply_appl_ptr(substream,
+                                                    scontrol.appl_ptr);
+                       if (err < 0)
+                               return err;
+               } else
+                       scontrol.appl_ptr = control->appl_ptr % boundary;
+               if (!(sflags & SNDRV_PCM_SYNC_PTR_AVAIL_MIN))
+                       control->avail_min = scontrol.avail_min;
+               else
+                       scontrol.avail_min = control->avail_min;
+               sstatus.state = status->state;
+               sstatus.hw_ptr = status->hw_ptr % boundary;
+               sstatus.tstamp = status->tstamp;
+               sstatus.suspended_state = status->suspended_state;
+               sstatus.audio_tstamp = status->audio_tstamp;
+       }
        if (!(sflags & SNDRV_PCM_SYNC_PTR_APPL))
                snd_pcm_dma_buffer_sync(substream, SNDRV_DMA_SYNC_DEVICE);
        if (put_user(sstatus.state, &src->s.status.state) ||
@@ -3628,7 +3597,7 @@ static __poll_t snd_pcm_poll(struct file *file, poll_table *wait)
        poll_wait(file, &runtime->sleep, wait);
 
        mask = 0;
-       snd_pcm_stream_lock_irq(substream);
+       guard(pcm_stream_lock_irq)(substream);
        avail = snd_pcm_avail(substream);
        switch (runtime->state) {
        case SNDRV_PCM_STATE_RUNNING:
@@ -3648,7 +3617,6 @@ static __poll_t snd_pcm_poll(struct file *file, poll_table *wait)
                mask = ok | EPOLLERR;
                break;
        }
-       snd_pcm_stream_unlock_irq(substream);
        return mask;
 }