diff options
author | Mark Brown <broonie@kernel.org> | 2017-04-30 09:15:35 -0400 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2017-04-30 09:15:35 -0400 |
commit | ec7f9844ef90ee3ac18194f24fa478577dcfc4ae (patch) | |
tree | 124d03b74fb66aac9f622dc4f893a2ea203a7504 | |
parent | 5a7ad1146caa895ad718a534399e38bd2ba721b7 (diff) | |
parent | dc9617cb81c4130858b6dd026039f42a39e93c18 (diff) |
Merge tag 'asoc-fix-v4.11-rc7' into asoc-linus
ASoC: Fixes for v4.11
A few last minute fixes for v4.11, the STI fix is relatively large but
driver specific and has been cooking in -next for a little while now:
- A fix from Takashi for some suspend/resume related crashes in the
Intel drivers.
- A fix from Mousumi Jana for issues with incorrectly created
enumeration controls generated from topology files which could cause
problems for userspace.
- Fixes from Arnaud Pouliquen for some crashes due to races with the
interrupt handler in the STI driver.
# gpg: Signature made Wed 26 Apr 2017 00:27:33 KST
# gpg: using RSA key ADE668AA675718B59FE29FEA24D68B725D5487D0
# gpg: issuer "broonie@kernel.org"
# gpg: key 0D9EACE2CD7BEEBC: no public key for trusted key - skipped
# gpg: key 0D9EACE2CD7BEEBC marked as ultimately trusted
# gpg: key CCB0A420AF88CD16: no public key for trusted key - skipped
# gpg: key CCB0A420AF88CD16 marked as ultimately trusted
# gpg: key 162614E316005C11: no public key for trusted key - skipped
# gpg: key 162614E316005C11 marked as ultimately trusted
# gpg: key A730C53A5621E907: no public key for trusted key - skipped
# gpg: key A730C53A5621E907 marked as ultimately trusted
# gpg: key 276568D75C6153AD: no public key for trusted key - skipped
# gpg: key 276568D75C6153AD marked as ultimately trusted
# gpg: Good signature from "Mark Brown <broonie@sirena.org.uk>" [ultimate]
# gpg: aka "Mark Brown <broonie@debian.org>" [ultimate]
# gpg: aka "Mark Brown <broonie@kernel.org>" [ultimate]
# gpg: aka "Mark Brown <broonie@tardis.ed.ac.uk>" [ultimate]
# gpg: aka "Mark Brown <broonie@linaro.org>" [ultimate]
# gpg: aka "Mark Brown <Mark.Brown@linaro.org>" [ultimate]
-rw-r--r-- | sound/soc/intel/boards/bytcr_rt5640.c | 4 | ||||
-rw-r--r-- | sound/soc/intel/boards/bytcr_rt5651.c | 2 | ||||
-rw-r--r-- | sound/soc/soc-topology.c | 1 | ||||
-rw-r--r-- | sound/soc/sti/uniperif.h | 1 | ||||
-rw-r--r-- | sound/soc/sti/uniperif_player.c | 35 | ||||
-rw-r--r-- | sound/soc/sti/uniperif_reader.c | 24 |
6 files changed, 48 insertions, 19 deletions
diff --git a/sound/soc/intel/boards/bytcr_rt5640.c b/sound/soc/intel/boards/bytcr_rt5640.c index 5c7219fb3aa8..9e2a3404a836 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[] = { | |||
621 | .codec_dai_name = "snd-soc-dummy-dai", | 621 | .codec_dai_name = "snd-soc-dummy-dai", |
622 | .codec_name = "snd-soc-dummy", | 622 | .codec_name = "snd-soc-dummy", |
623 | .platform_name = "sst-mfld-platform", | 623 | .platform_name = "sst-mfld-platform", |
624 | .ignore_suspend = 1, | 624 | .nonatomic = true, |
625 | .dynamic = 1, | 625 | .dynamic = 1, |
626 | .dpcm_playback = 1, | 626 | .dpcm_playback = 1, |
627 | .dpcm_capture = 1, | 627 | .dpcm_capture = 1, |
@@ -634,7 +634,6 @@ static struct snd_soc_dai_link byt_rt5640_dais[] = { | |||
634 | .codec_dai_name = "snd-soc-dummy-dai", | 634 | .codec_dai_name = "snd-soc-dummy-dai", |
635 | .codec_name = "snd-soc-dummy", | 635 | .codec_name = "snd-soc-dummy", |
636 | .platform_name = "sst-mfld-platform", | 636 | .platform_name = "sst-mfld-platform", |
637 | .ignore_suspend = 1, | ||
638 | .nonatomic = true, | 637 | .nonatomic = true, |
639 | .dynamic = 1, | 638 | .dynamic = 1, |
640 | .dpcm_playback = 1, | 639 | .dpcm_playback = 1, |
@@ -661,6 +660,7 @@ static struct snd_soc_dai_link byt_rt5640_dais[] = { | |||
661 | | SND_SOC_DAIFMT_CBS_CFS, | 660 | | SND_SOC_DAIFMT_CBS_CFS, |
662 | .be_hw_params_fixup = byt_rt5640_codec_fixup, | 661 | .be_hw_params_fixup = byt_rt5640_codec_fixup, |
663 | .ignore_suspend = 1, | 662 | .ignore_suspend = 1, |
663 | .nonatomic = true, | ||
664 | .dpcm_playback = 1, | 664 | .dpcm_playback = 1, |
665 | .dpcm_capture = 1, | 665 | .dpcm_capture = 1, |
666 | .init = byt_rt5640_init, | 666 | .init = byt_rt5640_init, |
diff --git a/sound/soc/intel/boards/bytcr_rt5651.c b/sound/soc/intel/boards/bytcr_rt5651.c index 3186f015939f..8164bec63bf1 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[] = { | |||
235 | .codec_dai_name = "snd-soc-dummy-dai", | 235 | .codec_dai_name = "snd-soc-dummy-dai", |
236 | .codec_name = "snd-soc-dummy", | 236 | .codec_name = "snd-soc-dummy", |
237 | .platform_name = "sst-mfld-platform", | 237 | .platform_name = "sst-mfld-platform", |
238 | .ignore_suspend = 1, | ||
239 | .nonatomic = true, | 238 | .nonatomic = true, |
240 | .dynamic = 1, | 239 | .dynamic = 1, |
241 | .dpcm_playback = 1, | 240 | .dpcm_playback = 1, |
@@ -249,7 +248,6 @@ static struct snd_soc_dai_link byt_rt5651_dais[] = { | |||
249 | .codec_dai_name = "snd-soc-dummy-dai", | 248 | .codec_dai_name = "snd-soc-dummy-dai", |
250 | .codec_name = "snd-soc-dummy", | 249 | .codec_name = "snd-soc-dummy", |
251 | .platform_name = "sst-mfld-platform", | 250 | .platform_name = "sst-mfld-platform", |
252 | .ignore_suspend = 1, | ||
253 | .nonatomic = true, | 251 | .nonatomic = true, |
254 | .dynamic = 1, | 252 | .dynamic = 1, |
255 | .dpcm_playback = 1, | 253 | .dpcm_playback = 1, |
diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c index 3e9b1c0bb1ce..058bc99c6c34 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, | |||
933 | } | 933 | } |
934 | } | 934 | } |
935 | 935 | ||
936 | se->texts = (const char * const *)se->dobj.control.dtexts; | ||
936 | return 0; | 937 | return 0; |
937 | 938 | ||
938 | err: | 939 | err: |
diff --git a/sound/soc/sti/uniperif.h b/sound/soc/sti/uniperif.h index d487dd2ef016..cfcb0ea9d99d 100644 --- a/sound/soc/sti/uniperif.h +++ b/sound/soc/sti/uniperif.h | |||
@@ -1299,6 +1299,7 @@ struct uniperif { | |||
1299 | int ver; /* IP version, used by register access macros */ | 1299 | int ver; /* IP version, used by register access macros */ |
1300 | struct regmap_field *clk_sel; | 1300 | struct regmap_field *clk_sel; |
1301 | struct regmap_field *valid_sel; | 1301 | struct regmap_field *valid_sel; |
1302 | spinlock_t irq_lock; /* use to prevent race condition with IRQ */ | ||
1302 | 1303 | ||
1303 | /* capabilities */ | 1304 | /* capabilities */ |
1304 | const struct snd_pcm_hardware *hw; | 1305 | const struct snd_pcm_hardware *hw; |
diff --git a/sound/soc/sti/uniperif_player.c b/sound/soc/sti/uniperif_player.c index 60ae31a303ab..d7e8dd46d2cc 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) | |||
65 | unsigned int status; | 65 | unsigned int status; |
66 | unsigned int tmp; | 66 | unsigned int tmp; |
67 | 67 | ||
68 | if (player->state == UNIPERIF_STATE_STOPPED) { | 68 | spin_lock(&player->irq_lock); |
69 | /* Unexpected IRQ: do nothing */ | 69 | if (!player->substream) |
70 | return IRQ_NONE; | 70 | goto irq_spin_unlock; |
71 | } | 71 | |
72 | snd_pcm_stream_lock(player->substream); | ||
73 | if (player->state == UNIPERIF_STATE_STOPPED) | ||
74 | goto stream_unlock; | ||
72 | 75 | ||
73 | /* Get interrupt status & clear them immediately */ | 76 | /* Get interrupt status & clear them immediately */ |
74 | status = GET_UNIPERIF_ITS(player); | 77 | status = GET_UNIPERIF_ITS(player); |
@@ -88,9 +91,7 @@ static irqreturn_t uni_player_irq_handler(int irq, void *dev_id) | |||
88 | SET_UNIPERIF_ITM_BCLR_FIFO_ERROR(player); | 91 | SET_UNIPERIF_ITM_BCLR_FIFO_ERROR(player); |
89 | 92 | ||
90 | /* Stop the player */ | 93 | /* Stop the player */ |
91 | snd_pcm_stream_lock(player->substream); | ||
92 | snd_pcm_stop(player->substream, SNDRV_PCM_STATE_XRUN); | 94 | snd_pcm_stop(player->substream, SNDRV_PCM_STATE_XRUN); |
93 | snd_pcm_stream_unlock(player->substream); | ||
94 | } | 95 | } |
95 | 96 | ||
96 | ret = IRQ_HANDLED; | 97 | ret = IRQ_HANDLED; |
@@ -104,9 +105,7 @@ static irqreturn_t uni_player_irq_handler(int irq, void *dev_id) | |||
104 | SET_UNIPERIF_ITM_BCLR_DMA_ERROR(player); | 105 | SET_UNIPERIF_ITM_BCLR_DMA_ERROR(player); |
105 | 106 | ||
106 | /* Stop the player */ | 107 | /* Stop the player */ |
107 | snd_pcm_stream_lock(player->substream); | ||
108 | snd_pcm_stop(player->substream, SNDRV_PCM_STATE_XRUN); | 108 | snd_pcm_stop(player->substream, SNDRV_PCM_STATE_XRUN); |
109 | snd_pcm_stream_unlock(player->substream); | ||
110 | 109 | ||
111 | ret = IRQ_HANDLED; | 110 | ret = IRQ_HANDLED; |
112 | } | 111 | } |
@@ -116,7 +115,8 @@ static irqreturn_t uni_player_irq_handler(int irq, void *dev_id) | |||
116 | if (!player->underflow_enabled) { | 115 | if (!player->underflow_enabled) { |
117 | dev_err(player->dev, | 116 | dev_err(player->dev, |
118 | "unexpected Underflow recovering\n"); | 117 | "unexpected Underflow recovering\n"); |
119 | return -EPERM; | 118 | ret = -EPERM; |
119 | goto stream_unlock; | ||
120 | } | 120 | } |
121 | /* Read the underflow recovery duration */ | 121 | /* Read the underflow recovery duration */ |
122 | tmp = GET_UNIPERIF_STATUS_1_UNDERFLOW_DURATION(player); | 122 | tmp = GET_UNIPERIF_STATUS_1_UNDERFLOW_DURATION(player); |
@@ -138,13 +138,16 @@ static irqreturn_t uni_player_irq_handler(int irq, void *dev_id) | |||
138 | dev_err(player->dev, "Underflow recovery failed\n"); | 138 | dev_err(player->dev, "Underflow recovery failed\n"); |
139 | 139 | ||
140 | /* Stop the player */ | 140 | /* Stop the player */ |
141 | snd_pcm_stream_lock(player->substream); | ||
142 | snd_pcm_stop(player->substream, SNDRV_PCM_STATE_XRUN); | 141 | snd_pcm_stop(player->substream, SNDRV_PCM_STATE_XRUN); |
143 | snd_pcm_stream_unlock(player->substream); | ||
144 | 142 | ||
145 | ret = IRQ_HANDLED; | 143 | ret = IRQ_HANDLED; |
146 | } | 144 | } |
147 | 145 | ||
146 | stream_unlock: | ||
147 | snd_pcm_stream_unlock(player->substream); | ||
148 | irq_spin_unlock: | ||
149 | spin_unlock(&player->irq_lock); | ||
150 | |||
148 | return ret; | 151 | return ret; |
149 | } | 152 | } |
150 | 153 | ||
@@ -588,6 +591,7 @@ static int uni_player_ctl_iec958_put(struct snd_kcontrol *kcontrol, | |||
588 | struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai); | 591 | struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai); |
589 | struct uniperif *player = priv->dai_data.uni; | 592 | struct uniperif *player = priv->dai_data.uni; |
590 | struct snd_aes_iec958 *iec958 = &player->stream_settings.iec958; | 593 | struct snd_aes_iec958 *iec958 = &player->stream_settings.iec958; |
594 | unsigned long flags; | ||
591 | 595 | ||
592 | mutex_lock(&player->ctrl_lock); | 596 | mutex_lock(&player->ctrl_lock); |
593 | iec958->status[0] = ucontrol->value.iec958.status[0]; | 597 | iec958->status[0] = ucontrol->value.iec958.status[0]; |
@@ -596,12 +600,14 @@ static int uni_player_ctl_iec958_put(struct snd_kcontrol *kcontrol, | |||
596 | iec958->status[3] = ucontrol->value.iec958.status[3]; | 600 | iec958->status[3] = ucontrol->value.iec958.status[3]; |
597 | mutex_unlock(&player->ctrl_lock); | 601 | mutex_unlock(&player->ctrl_lock); |
598 | 602 | ||
603 | spin_lock_irqsave(&player->irq_lock, flags); | ||
599 | if (player->substream && player->substream->runtime) | 604 | if (player->substream && player->substream->runtime) |
600 | uni_player_set_channel_status(player, | 605 | uni_player_set_channel_status(player, |
601 | player->substream->runtime); | 606 | player->substream->runtime); |
602 | else | 607 | else |
603 | uni_player_set_channel_status(player, NULL); | 608 | uni_player_set_channel_status(player, NULL); |
604 | 609 | ||
610 | spin_unlock_irqrestore(&player->irq_lock, flags); | ||
605 | return 0; | 611 | return 0; |
606 | } | 612 | } |
607 | 613 | ||
@@ -686,9 +692,12 @@ static int uni_player_startup(struct snd_pcm_substream *substream, | |||
686 | { | 692 | { |
687 | struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai); | 693 | struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai); |
688 | struct uniperif *player = priv->dai_data.uni; | 694 | struct uniperif *player = priv->dai_data.uni; |
695 | unsigned long flags; | ||
689 | int ret; | 696 | int ret; |
690 | 697 | ||
698 | spin_lock_irqsave(&player->irq_lock, flags); | ||
691 | player->substream = substream; | 699 | player->substream = substream; |
700 | spin_unlock_irqrestore(&player->irq_lock, flags); | ||
692 | 701 | ||
693 | player->clk_adj = 0; | 702 | player->clk_adj = 0; |
694 | 703 | ||
@@ -986,12 +995,15 @@ static void uni_player_shutdown(struct snd_pcm_substream *substream, | |||
986 | { | 995 | { |
987 | struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai); | 996 | struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai); |
988 | struct uniperif *player = priv->dai_data.uni; | 997 | struct uniperif *player = priv->dai_data.uni; |
998 | unsigned long flags; | ||
989 | 999 | ||
1000 | spin_lock_irqsave(&player->irq_lock, flags); | ||
990 | if (player->state != UNIPERIF_STATE_STOPPED) | 1001 | if (player->state != UNIPERIF_STATE_STOPPED) |
991 | /* Stop the player */ | 1002 | /* Stop the player */ |
992 | uni_player_stop(player); | 1003 | uni_player_stop(player); |
993 | 1004 | ||
994 | player->substream = NULL; | 1005 | player->substream = NULL; |
1006 | spin_unlock_irqrestore(&player->irq_lock, flags); | ||
995 | } | 1007 | } |
996 | 1008 | ||
997 | static int uni_player_parse_dt_audio_glue(struct platform_device *pdev, | 1009 | static int uni_player_parse_dt_audio_glue(struct platform_device *pdev, |
@@ -1096,6 +1108,7 @@ int uni_player_init(struct platform_device *pdev, | |||
1096 | } | 1108 | } |
1097 | 1109 | ||
1098 | mutex_init(&player->ctrl_lock); | 1110 | mutex_init(&player->ctrl_lock); |
1111 | spin_lock_init(&player->irq_lock); | ||
1099 | 1112 | ||
1100 | /* Ensure that disabled by default */ | 1113 | /* Ensure that disabled by default */ |
1101 | SET_UNIPERIF_CONFIG_BACK_STALL_REQ_DISABLE(player); | 1114 | 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 93a8df6ed880..ee0055e60852 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) | |||
46 | struct uniperif *reader = dev_id; | 46 | struct uniperif *reader = dev_id; |
47 | unsigned int status; | 47 | unsigned int status; |
48 | 48 | ||
49 | spin_lock(&reader->irq_lock); | ||
50 | if (!reader->substream) | ||
51 | goto irq_spin_unlock; | ||
52 | |||
53 | snd_pcm_stream_lock(reader->substream); | ||
49 | if (reader->state == UNIPERIF_STATE_STOPPED) { | 54 | if (reader->state == UNIPERIF_STATE_STOPPED) { |
50 | /* Unexpected IRQ: do nothing */ | 55 | /* Unexpected IRQ: do nothing */ |
51 | dev_warn(reader->dev, "unexpected IRQ\n"); | 56 | dev_warn(reader->dev, "unexpected IRQ\n"); |
52 | return IRQ_HANDLED; | 57 | goto stream_unlock; |
53 | } | 58 | } |
54 | 59 | ||
55 | /* Get interrupt status & clear them immediately */ | 60 | /* Get interrupt status & clear them immediately */ |
@@ -60,13 +65,16 @@ static irqreturn_t uni_reader_irq_handler(int irq, void *dev_id) | |||
60 | if (unlikely(status & UNIPERIF_ITS_FIFO_ERROR_MASK(reader))) { | 65 | if (unlikely(status & UNIPERIF_ITS_FIFO_ERROR_MASK(reader))) { |
61 | dev_err(reader->dev, "FIFO error detected\n"); | 66 | dev_err(reader->dev, "FIFO error detected\n"); |
62 | 67 | ||
63 | snd_pcm_stream_lock(reader->substream); | ||
64 | snd_pcm_stop(reader->substream, SNDRV_PCM_STATE_XRUN); | 68 | snd_pcm_stop(reader->substream, SNDRV_PCM_STATE_XRUN); |
65 | snd_pcm_stream_unlock(reader->substream); | ||
66 | 69 | ||
67 | return IRQ_HANDLED; | 70 | ret = IRQ_HANDLED; |
68 | } | 71 | } |
69 | 72 | ||
73 | stream_unlock: | ||
74 | snd_pcm_stream_unlock(reader->substream); | ||
75 | irq_spin_unlock: | ||
76 | spin_unlock(&reader->irq_lock); | ||
77 | |||
70 | return ret; | 78 | return ret; |
71 | } | 79 | } |
72 | 80 | ||
@@ -347,9 +355,12 @@ static int uni_reader_startup(struct snd_pcm_substream *substream, | |||
347 | { | 355 | { |
348 | struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai); | 356 | struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai); |
349 | struct uniperif *reader = priv->dai_data.uni; | 357 | struct uniperif *reader = priv->dai_data.uni; |
358 | unsigned long flags; | ||
350 | int ret; | 359 | int ret; |
351 | 360 | ||
361 | spin_lock_irqsave(&reader->irq_lock, flags); | ||
352 | reader->substream = substream; | 362 | reader->substream = substream; |
363 | spin_unlock_irqrestore(&reader->irq_lock, flags); | ||
353 | 364 | ||
354 | if (!UNIPERIF_TYPE_IS_TDM(reader)) | 365 | if (!UNIPERIF_TYPE_IS_TDM(reader)) |
355 | return 0; | 366 | return 0; |
@@ -375,12 +386,15 @@ static void uni_reader_shutdown(struct snd_pcm_substream *substream, | |||
375 | { | 386 | { |
376 | struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai); | 387 | struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai); |
377 | struct uniperif *reader = priv->dai_data.uni; | 388 | struct uniperif *reader = priv->dai_data.uni; |
389 | unsigned long flags; | ||
378 | 390 | ||
391 | spin_lock_irqsave(&reader->irq_lock, flags); | ||
379 | if (reader->state != UNIPERIF_STATE_STOPPED) { | 392 | if (reader->state != UNIPERIF_STATE_STOPPED) { |
380 | /* Stop the reader */ | 393 | /* Stop the reader */ |
381 | uni_reader_stop(reader); | 394 | uni_reader_stop(reader); |
382 | } | 395 | } |
383 | reader->substream = NULL; | 396 | reader->substream = NULL; |
397 | spin_unlock_irqrestore(&reader->irq_lock, flags); | ||
384 | } | 398 | } |
385 | 399 | ||
386 | static const struct snd_soc_dai_ops uni_reader_dai_ops = { | 400 | static const struct snd_soc_dai_ops uni_reader_dai_ops = { |
@@ -415,6 +429,8 @@ int uni_reader_init(struct platform_device *pdev, | |||
415 | return -EBUSY; | 429 | return -EBUSY; |
416 | } | 430 | } |
417 | 431 | ||
432 | spin_lock_init(&reader->irq_lock); | ||
433 | |||
418 | return 0; | 434 | return 0; |
419 | } | 435 | } |
420 | EXPORT_SYMBOL_GPL(uni_reader_init); | 436 | EXPORT_SYMBOL_GPL(uni_reader_init); |