Merge tag 'v5.8-rc1' into regulator-5.8
[linux-2.6-microblaze.git] / sound / core / pcm_native.c
index 47838f5..9630d25 100644 (file)
@@ -138,6 +138,16 @@ void snd_pcm_stream_lock_irq(struct snd_pcm_substream *substream)
 }
 EXPORT_SYMBOL_GPL(snd_pcm_stream_lock_irq);
 
+static void snd_pcm_stream_lock_nested(struct snd_pcm_substream *substream)
+{
+       struct snd_pcm_group *group = &substream->self_group;
+
+       if (substream->pcm->nonatomic)
+               mutex_lock_nested(&group->mutex, SINGLE_DEPTH_NESTING);
+       else
+               spin_lock_nested(&group->lock, SINGLE_DEPTH_NESTING);
+}
+
 /**
  * snd_pcm_stream_unlock_irq - Unlock the PCM stream
  * @substream: PCM substream
@@ -2166,6 +2176,12 @@ static int snd_pcm_link(struct snd_pcm_substream *substream, int fd)
        }
        pcm_file = f.file->private_data;
        substream1 = pcm_file->substream;
+
+       if (substream == substream1) {
+               res = -EINVAL;
+               goto _badf;
+       }
+
        group = kzalloc(sizeof(*group), GFP_KERNEL);
        if (!group) {
                res = -ENOMEM;
@@ -2194,7 +2210,7 @@ static int snd_pcm_link(struct snd_pcm_substream *substream, int fd)
        snd_pcm_stream_unlock_irq(substream);
 
        snd_pcm_group_lock_irq(target_group, nonatomic);
-       snd_pcm_stream_lock(substream1);
+       snd_pcm_stream_lock_nested(substream1);
        snd_pcm_group_assign(substream1, target_group);
        refcount_inc(&target_group->refs);
        snd_pcm_stream_unlock(substream1);
@@ -2210,7 +2226,7 @@ static int snd_pcm_link(struct snd_pcm_substream *substream, int fd)
 
 static void relink_to_local(struct snd_pcm_substream *substream)
 {
-       snd_pcm_stream_lock(substream);
+       snd_pcm_stream_lock_nested(substream);
        snd_pcm_group_assign(substream, &substream->self_group);
        snd_pcm_stream_unlock(substream);
 }