cond_resched();
 }
 
+#define PCM_LOCK_DEFAULT       0
+#define PCM_LOCK_IRQ   1
+#define PCM_LOCK_IRQSAVE       2
+
+static unsigned long __snd_pcm_stream_lock_mode(struct snd_pcm_substream *substream,
+                                               unsigned int mode)
+{
+       unsigned long flags = 0;
+       if (substream->pcm->nonatomic) {
+               down_read_nested(&snd_pcm_link_rwsem, SINGLE_DEPTH_NESTING);
+               mutex_lock(&substream->self_group.mutex);
+       } else {
+               switch (mode) {
+               case PCM_LOCK_DEFAULT:
+                       read_lock(&snd_pcm_link_rwlock);
+                       break;
+               case PCM_LOCK_IRQ:
+                       read_lock_irq(&snd_pcm_link_rwlock);
+                       break;
+               case PCM_LOCK_IRQSAVE:
+                       read_lock_irqsave(&snd_pcm_link_rwlock, flags);
+                       break;
+               }
+               spin_lock(&substream->self_group.lock);
+       }
+       return flags;
+}
+
+static void __snd_pcm_stream_unlock_mode(struct snd_pcm_substream *substream,
+                                        unsigned int mode, unsigned long flags)
+{
+       if (substream->pcm->nonatomic) {
+               mutex_unlock(&substream->self_group.mutex);
+               up_read(&snd_pcm_link_rwsem);
+       } else {
+               spin_unlock(&substream->self_group.lock);
+
+               switch (mode) {
+               case PCM_LOCK_DEFAULT:
+                       read_unlock(&snd_pcm_link_rwlock);
+                       break;
+               case PCM_LOCK_IRQ:
+                       read_unlock_irq(&snd_pcm_link_rwlock);
+                       break;
+               case PCM_LOCK_IRQSAVE:
+                       read_unlock_irqrestore(&snd_pcm_link_rwlock, flags);
+                       break;
+               }
+       }
+}
+
 /**
  * snd_pcm_stream_lock - Lock the PCM stream
  * @substream: PCM substream
  */
 void snd_pcm_stream_lock(struct snd_pcm_substream *substream)
 {
-       if (substream->pcm->nonatomic) {
-               down_read_nested(&snd_pcm_link_rwsem, SINGLE_DEPTH_NESTING);
-               mutex_lock(&substream->self_group.mutex);
-       } else {
-               read_lock(&snd_pcm_link_rwlock);
-               spin_lock(&substream->self_group.lock);
-       }
+       __snd_pcm_stream_lock_mode(substream, PCM_LOCK_DEFAULT);
 }
 EXPORT_SYMBOL_GPL(snd_pcm_stream_lock);
 
  */
 void snd_pcm_stream_unlock(struct snd_pcm_substream *substream)
 {
-       if (substream->pcm->nonatomic) {
-               mutex_unlock(&substream->self_group.mutex);
-               up_read(&snd_pcm_link_rwsem);
-       } else {
-               spin_unlock(&substream->self_group.lock);
-               read_unlock(&snd_pcm_link_rwlock);
-       }
+       __snd_pcm_stream_unlock_mode(substream, PCM_LOCK_DEFAULT, 0);
 }
 EXPORT_SYMBOL_GPL(snd_pcm_stream_unlock);
 
  */
 void snd_pcm_stream_lock_irq(struct snd_pcm_substream *substream)
 {
-       if (!substream->pcm->nonatomic)
-               local_irq_disable();
-       snd_pcm_stream_lock(substream);
+       __snd_pcm_stream_lock_mode(substream, PCM_LOCK_IRQ);
 }
 EXPORT_SYMBOL_GPL(snd_pcm_stream_lock_irq);
 
  */
 void snd_pcm_stream_unlock_irq(struct snd_pcm_substream *substream)
 {
-       snd_pcm_stream_unlock(substream);
-       if (!substream->pcm->nonatomic)
-               local_irq_enable();
+       __snd_pcm_stream_unlock_mode(substream, PCM_LOCK_IRQ, 0);
 }
 EXPORT_SYMBOL_GPL(snd_pcm_stream_unlock_irq);
 
 unsigned long _snd_pcm_stream_lock_irqsave(struct snd_pcm_substream *substream)
 {
-       unsigned long flags = 0;
-       if (!substream->pcm->nonatomic)
-               local_irq_save(flags);
-       snd_pcm_stream_lock(substream);
-       return flags;
+       return __snd_pcm_stream_lock_mode(substream, PCM_LOCK_IRQSAVE);
 }
 EXPORT_SYMBOL_GPL(_snd_pcm_stream_lock_irqsave);
 
 void snd_pcm_stream_unlock_irqrestore(struct snd_pcm_substream *substream,
                                      unsigned long flags)
 {
-       snd_pcm_stream_unlock(substream);
-       if (!substream->pcm->nonatomic)
-               local_irq_restore(flags);
+       __snd_pcm_stream_unlock_mode(substream, PCM_LOCK_IRQSAVE, flags);
 }
 EXPORT_SYMBOL_GPL(snd_pcm_stream_unlock_irqrestore);