diff --git a/sound/core/seq/seq_lock.c b/sound/core/seq/seq_lock.c index 3b693e924db745c0ec8be74171bb189f17dfc53d..12ba83367b1bc882f6d6fbab9329185d58125090 100644 --- a/sound/core/seq/seq_lock.c +++ b/sound/core/seq/seq_lock.c @@ -28,19 +28,16 @@ /* wait until all locks are released */ void snd_use_lock_sync_helper(snd_use_lock_t *lockp, const char *file, int line) { - int max_count = 5 * HZ; + int warn_count = 5 * HZ; if (atomic_read(lockp) < 0) { pr_warn("ALSA: seq_lock: lock trouble [counter = %d] in %s:%d\n", atomic_read(lockp), file, line); return; } while (atomic_read(lockp) > 0) { - if (max_count == 0) { - pr_warn("ALSA: seq_lock: timeout [%d left] in %s:%d\n", atomic_read(lockp), file, line); - break; - } + if (warn_count-- == 0) + pr_warn("ALSA: seq_lock: waiting [%d left] in %s:%d\n", atomic_read(lockp), file, line); schedule_timeout_uninterruptible(1); - max_count--; } } diff --git a/sound/firewire/lib.h b/sound/firewire/lib.h index f6769312ebfccbe473ac291e81b386b48b45488f..c3768cd494a5f3fe3bb9059bd8e588c73b806c86 100644 --- a/sound/firewire/lib.h +++ b/sound/firewire/lib.h @@ -45,7 +45,7 @@ struct snd_fw_async_midi_port { struct snd_rawmidi_substream *substream; snd_fw_async_midi_port_fill fill; - unsigned int consume_bytes; + int consume_bytes; }; int snd_fw_async_midi_port_init(struct snd_fw_async_midi_port *port, diff --git a/sound/firewire/oxfw/oxfw.c b/sound/firewire/oxfw/oxfw.c index 74d7fb6efce6ca8258ece95a83c3460588a3e99e..413ab6313bb66515c284734ca92c87bef014c5fd 100644 --- a/sound/firewire/oxfw/oxfw.c +++ b/sound/firewire/oxfw/oxfw.c @@ -227,11 +227,11 @@ static void do_registration(struct work_struct *work) if (err < 0) goto error; - err = detect_quirks(oxfw); + err = snd_oxfw_stream_discover(oxfw); if (err < 0) goto error; - err = snd_oxfw_stream_discover(oxfw); + err = detect_quirks(oxfw); if (err < 0) goto error; diff --git a/sound/soc/intel/boards/bytcr_rt5640.c b/sound/soc/intel/boards/bytcr_rt5640.c index 5c7219fb3aa86738a49cff98bf6f16693f7a0192..9e2a3404a836bf919f68b6cbd33c8f569b3c8843 100644 --- a/sound/soc/intel/boards/bytcr_rt5640.c +++ b/sound/soc/intel/boards/bytcr_rt5640.c @@ -621,7 +621,7 @@ static struct snd_soc_dai_link byt_rt5640_dais[] = { .codec_dai_name = "snd-soc-dummy-dai", .codec_name = "snd-soc-dummy", .platform_name = "sst-mfld-platform", - .ignore_suspend = 1, + .nonatomic = true, .dynamic = 1, .dpcm_playback = 1, .dpcm_capture = 1, @@ -634,7 +634,6 @@ static struct snd_soc_dai_link byt_rt5640_dais[] = { .codec_dai_name = "snd-soc-dummy-dai", .codec_name = "snd-soc-dummy", .platform_name = "sst-mfld-platform", - .ignore_suspend = 1, .nonatomic = true, .dynamic = 1, .dpcm_playback = 1, @@ -661,6 +660,7 @@ static struct snd_soc_dai_link byt_rt5640_dais[] = { | SND_SOC_DAIFMT_CBS_CFS, .be_hw_params_fixup = byt_rt5640_codec_fixup, .ignore_suspend = 1, + .nonatomic = true, .dpcm_playback = 1, .dpcm_capture = 1, .init = byt_rt5640_init, diff --git a/sound/soc/intel/boards/bytcr_rt5651.c b/sound/soc/intel/boards/bytcr_rt5651.c index 3186f015939fb5fce3e8393fd40463362464dbf8..8164bec63bf15b874da49a4406ae9f6124cd776c 100644 --- a/sound/soc/intel/boards/bytcr_rt5651.c +++ b/sound/soc/intel/boards/bytcr_rt5651.c @@ -235,7 +235,6 @@ static struct snd_soc_dai_link byt_rt5651_dais[] = { .codec_dai_name = "snd-soc-dummy-dai", .codec_name = "snd-soc-dummy", .platform_name = "sst-mfld-platform", - .ignore_suspend = 1, .nonatomic = true, .dynamic = 1, .dpcm_playback = 1, @@ -249,7 +248,6 @@ static struct snd_soc_dai_link byt_rt5651_dais[] = { .codec_dai_name = "snd-soc-dummy-dai", .codec_name = "snd-soc-dummy", .platform_name = "sst-mfld-platform", - .ignore_suspend = 1, .nonatomic = true, .dynamic = 1, .dpcm_playback = 1, diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c index 3e9b1c0bb1ce3cb1864e1825ade56720803df289..058bc99c6c3479e4d7a92c97a885f634b168105d 100644 --- a/sound/soc/soc-topology.c +++ b/sound/soc/soc-topology.c @@ -933,6 +933,7 @@ static int soc_tplg_denum_create_texts(struct soc_enum *se, } } + se->texts = (const char * const *)se->dobj.control.dtexts; return 0; err: diff --git a/sound/soc/sti/uniperif.h b/sound/soc/sti/uniperif.h index d487dd2ef016fee0f25d6a5705feb98a0f26356a..cfcb0ea9d99d8981abc2425d15f3e7148e0dc7a6 100644 --- a/sound/soc/sti/uniperif.h +++ b/sound/soc/sti/uniperif.h @@ -1299,6 +1299,7 @@ struct uniperif { int ver; /* IP version, used by register access macros */ struct regmap_field *clk_sel; struct regmap_field *valid_sel; + spinlock_t irq_lock; /* use to prevent race condition with IRQ */ /* capabilities */ const struct snd_pcm_hardware *hw; diff --git a/sound/soc/sti/uniperif_player.c b/sound/soc/sti/uniperif_player.c index 60ae31a303ab001e5724518248f59ef12033570b..d7e8dd46d2cc40ba2c937a4ea627f4859fe1f478 100644 --- a/sound/soc/sti/uniperif_player.c +++ b/sound/soc/sti/uniperif_player.c @@ -65,10 +65,13 @@ static irqreturn_t uni_player_irq_handler(int irq, void *dev_id) unsigned int status; unsigned int tmp; - if (player->state == UNIPERIF_STATE_STOPPED) { - /* Unexpected IRQ: do nothing */ - return IRQ_NONE; - } + spin_lock(&player->irq_lock); + if (!player->substream) + goto irq_spin_unlock; + + snd_pcm_stream_lock(player->substream); + if (player->state == UNIPERIF_STATE_STOPPED) + goto stream_unlock; /* Get interrupt status & clear them immediately */ status = GET_UNIPERIF_ITS(player); @@ -88,9 +91,7 @@ static irqreturn_t uni_player_irq_handler(int irq, void *dev_id) SET_UNIPERIF_ITM_BCLR_FIFO_ERROR(player); /* Stop the player */ - snd_pcm_stream_lock(player->substream); snd_pcm_stop(player->substream, SNDRV_PCM_STATE_XRUN); - snd_pcm_stream_unlock(player->substream); } ret = IRQ_HANDLED; @@ -104,9 +105,7 @@ static irqreturn_t uni_player_irq_handler(int irq, void *dev_id) SET_UNIPERIF_ITM_BCLR_DMA_ERROR(player); /* Stop the player */ - snd_pcm_stream_lock(player->substream); snd_pcm_stop(player->substream, SNDRV_PCM_STATE_XRUN); - snd_pcm_stream_unlock(player->substream); ret = IRQ_HANDLED; } @@ -116,7 +115,8 @@ static irqreturn_t uni_player_irq_handler(int irq, void *dev_id) if (!player->underflow_enabled) { dev_err(player->dev, "unexpected Underflow recovering\n"); - return -EPERM; + ret = -EPERM; + goto stream_unlock; } /* Read the underflow recovery duration */ tmp = GET_UNIPERIF_STATUS_1_UNDERFLOW_DURATION(player); @@ -138,13 +138,16 @@ static irqreturn_t uni_player_irq_handler(int irq, void *dev_id) dev_err(player->dev, "Underflow recovery failed\n"); /* Stop the player */ - snd_pcm_stream_lock(player->substream); snd_pcm_stop(player->substream, SNDRV_PCM_STATE_XRUN); - snd_pcm_stream_unlock(player->substream); ret = IRQ_HANDLED; } +stream_unlock: + snd_pcm_stream_unlock(player->substream); +irq_spin_unlock: + spin_unlock(&player->irq_lock); + return ret; } @@ -588,6 +591,7 @@ static int uni_player_ctl_iec958_put(struct snd_kcontrol *kcontrol, struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai); struct uniperif *player = priv->dai_data.uni; struct snd_aes_iec958 *iec958 = &player->stream_settings.iec958; + unsigned long flags; mutex_lock(&player->ctrl_lock); iec958->status[0] = ucontrol->value.iec958.status[0]; @@ -596,12 +600,14 @@ static int uni_player_ctl_iec958_put(struct snd_kcontrol *kcontrol, iec958->status[3] = ucontrol->value.iec958.status[3]; mutex_unlock(&player->ctrl_lock); + spin_lock_irqsave(&player->irq_lock, flags); if (player->substream && player->substream->runtime) uni_player_set_channel_status(player, player->substream->runtime); else uni_player_set_channel_status(player, NULL); + spin_unlock_irqrestore(&player->irq_lock, flags); return 0; } @@ -686,9 +692,12 @@ static int uni_player_startup(struct snd_pcm_substream *substream, { struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai); struct uniperif *player = priv->dai_data.uni; + unsigned long flags; int ret; + spin_lock_irqsave(&player->irq_lock, flags); player->substream = substream; + spin_unlock_irqrestore(&player->irq_lock, flags); player->clk_adj = 0; @@ -986,12 +995,15 @@ static void uni_player_shutdown(struct snd_pcm_substream *substream, { struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai); struct uniperif *player = priv->dai_data.uni; + unsigned long flags; + spin_lock_irqsave(&player->irq_lock, flags); if (player->state != UNIPERIF_STATE_STOPPED) /* Stop the player */ uni_player_stop(player); player->substream = NULL; + spin_unlock_irqrestore(&player->irq_lock, flags); } static int uni_player_parse_dt_audio_glue(struct platform_device *pdev, @@ -1096,6 +1108,7 @@ int uni_player_init(struct platform_device *pdev, } mutex_init(&player->ctrl_lock); + spin_lock_init(&player->irq_lock); /* Ensure that disabled by default */ SET_UNIPERIF_CONFIG_BACK_STALL_REQ_DISABLE(player); diff --git a/sound/soc/sti/uniperif_reader.c b/sound/soc/sti/uniperif_reader.c index 93a8df6ed880ea8cc32b62f94ab0b44befbe06ef..ee0055e608529195fda9b76a4226ebf752ead6e3 100644 --- a/sound/soc/sti/uniperif_reader.c +++ b/sound/soc/sti/uniperif_reader.c @@ -46,10 +46,15 @@ static irqreturn_t uni_reader_irq_handler(int irq, void *dev_id) struct uniperif *reader = dev_id; unsigned int status; + spin_lock(&reader->irq_lock); + if (!reader->substream) + goto irq_spin_unlock; + + snd_pcm_stream_lock(reader->substream); if (reader->state == UNIPERIF_STATE_STOPPED) { /* Unexpected IRQ: do nothing */ dev_warn(reader->dev, "unexpected IRQ\n"); - return IRQ_HANDLED; + goto stream_unlock; } /* Get interrupt status & clear them immediately */ @@ -60,13 +65,16 @@ static irqreturn_t uni_reader_irq_handler(int irq, void *dev_id) if (unlikely(status & UNIPERIF_ITS_FIFO_ERROR_MASK(reader))) { dev_err(reader->dev, "FIFO error detected\n"); - snd_pcm_stream_lock(reader->substream); snd_pcm_stop(reader->substream, SNDRV_PCM_STATE_XRUN); - snd_pcm_stream_unlock(reader->substream); - return IRQ_HANDLED; + ret = IRQ_HANDLED; } +stream_unlock: + snd_pcm_stream_unlock(reader->substream); +irq_spin_unlock: + spin_unlock(&reader->irq_lock); + return ret; } @@ -347,9 +355,12 @@ static int uni_reader_startup(struct snd_pcm_substream *substream, { struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai); struct uniperif *reader = priv->dai_data.uni; + unsigned long flags; int ret; + spin_lock_irqsave(&reader->irq_lock, flags); reader->substream = substream; + spin_unlock_irqrestore(&reader->irq_lock, flags); if (!UNIPERIF_TYPE_IS_TDM(reader)) return 0; @@ -375,12 +386,15 @@ static void uni_reader_shutdown(struct snd_pcm_substream *substream, { struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai); struct uniperif *reader = priv->dai_data.uni; + unsigned long flags; + spin_lock_irqsave(&reader->irq_lock, flags); if (reader->state != UNIPERIF_STATE_STOPPED) { /* Stop the reader */ uni_reader_stop(reader); } reader->substream = NULL; + spin_unlock_irqrestore(&reader->irq_lock, flags); } static const struct snd_soc_dai_ops uni_reader_dai_ops = { @@ -415,6 +429,8 @@ int uni_reader_init(struct platform_device *pdev, return -EBUSY; } + spin_lock_init(&reader->irq_lock); + return 0; } EXPORT_SYMBOL_GPL(uni_reader_init);