lkml.org 
[lkml]   [2012]   [Nov]   [14]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[ 18/38] ALSA: PCM: Fix some races at disconnection
    Date
    3.0-stable review patch.  If anyone has any objections, please let me know.

    ------------------

    From: Takashi Iwai <tiwai@suse.de>

    commit 9b0573c07f278e9888c352aa9724035c75784ea0 upstream.

    Fix races at PCM disconnection:
    - while a PCM device is being opened or closed
    - while the PCM state is being changed without lock in prepare,
    hw_params, hw_free ops

    Reported-by: Matthieu CASTET <matthieu.castet@parrot.com>
    Signed-off-by: Takashi Iwai <tiwai@suse.de>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    ---
    sound/core/pcm.c | 7 ++++++-
    sound/core/pcm_native.c | 16 ++++++++++++----
    2 files changed, 18 insertions(+), 5 deletions(-)

    --- a/sound/core/pcm.c
    +++ b/sound/core/pcm.c
    @@ -1045,11 +1045,15 @@ static int snd_pcm_dev_disconnect(struct
    if (list_empty(&pcm->list))
    goto unlock;

    + mutex_lock(&pcm->open_mutex);
    list_del_init(&pcm->list);
    for (cidx = 0; cidx < 2; cidx++)
    - for (substream = pcm->streams[cidx].substream; substream; substream = substream->next)
    + for (substream = pcm->streams[cidx].substream; substream; substream = substream->next) {
    + snd_pcm_stream_lock_irq(substream);
    if (substream->runtime)
    substream->runtime->status->state = SNDRV_PCM_STATE_DISCONNECTED;
    + snd_pcm_stream_unlock_irq(substream);
    + }
    list_for_each_entry(notify, &snd_pcm_notify_list, list) {
    notify->n_disconnect(pcm);
    }
    @@ -1065,6 +1069,7 @@ static int snd_pcm_dev_disconnect(struct
    }
    snd_unregister_device(devtype, pcm->card, pcm->device);
    }
    + mutex_unlock(&pcm->open_mutex);
    unlock:
    mutex_unlock(&register_mutex);
    return 0;
    --- a/sound/core/pcm_native.c
    +++ b/sound/core/pcm_native.c
    @@ -368,6 +368,14 @@ static int period_to_usecs(struct snd_pc
    return usecs;
    }

    +static void snd_pcm_set_state(struct snd_pcm_substream *substream, int state)
    +{
    + snd_pcm_stream_lock_irq(substream);
    + if (substream->runtime->status->state != SNDRV_PCM_STATE_DISCONNECTED)
    + substream->runtime->status->state = state;
    + snd_pcm_stream_unlock_irq(substream);
    +}
    +
    static int snd_pcm_hw_params(struct snd_pcm_substream *substream,
    struct snd_pcm_hw_params *params)
    {
    @@ -451,7 +459,7 @@ static int snd_pcm_hw_params(struct snd_
    runtime->boundary *= 2;

    snd_pcm_timer_resolution_change(substream);
    - runtime->status->state = SNDRV_PCM_STATE_SETUP;
    + snd_pcm_set_state(substream, SNDRV_PCM_STATE_SETUP);

    if (pm_qos_request_active(&substream->latency_pm_qos_req))
    pm_qos_remove_request(&substream->latency_pm_qos_req);
    @@ -463,7 +471,7 @@ static int snd_pcm_hw_params(struct snd_
    /* hardware might be unusable from this time,
    so we force application to retry to set
    the correct hardware parameter settings */
    - runtime->status->state = SNDRV_PCM_STATE_OPEN;
    + snd_pcm_set_state(substream, SNDRV_PCM_STATE_OPEN);
    if (substream->ops->hw_free != NULL)
    substream->ops->hw_free(substream);
    return err;
    @@ -511,7 +519,7 @@ static int snd_pcm_hw_free(struct snd_pc
    return -EBADFD;
    if (substream->ops->hw_free)
    result = substream->ops->hw_free(substream);
    - runtime->status->state = SNDRV_PCM_STATE_OPEN;
    + snd_pcm_set_state(substream, SNDRV_PCM_STATE_OPEN);
    pm_qos_remove_request(&substream->latency_pm_qos_req);
    return result;
    }
    @@ -1319,7 +1327,7 @@ static void snd_pcm_post_prepare(struct
    {
    struct snd_pcm_runtime *runtime = substream->runtime;
    runtime->control->appl_ptr = runtime->status->hw_ptr;
    - runtime->status->state = SNDRV_PCM_STATE_PREPARED;
    + snd_pcm_set_state(substream, SNDRV_PCM_STATE_PREPARED);
    }

    static struct action_ops snd_pcm_action_prepare = {



    \
     
     \ /
      Last update: 2012-11-15 06:01    [W:5.045 / U:0.024 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site