aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Brown <broonie@kernel.org>2017-04-30 09:15:35 -0400
committerMark Brown <broonie@kernel.org>2017-04-30 09:15:35 -0400
commitec7f9844ef90ee3ac18194f24fa478577dcfc4ae (patch)
tree124d03b74fb66aac9f622dc4f893a2ea203a7504
parent5a7ad1146caa895ad718a534399e38bd2ba721b7 (diff)
parentdc9617cb81c4130858b6dd026039f42a39e93c18 (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.c4
-rw-r--r--sound/soc/intel/boards/bytcr_rt5651.c2
-rw-r--r--sound/soc/soc-topology.c1
-rw-r--r--sound/soc/sti/uniperif.h1
-rw-r--r--sound/soc/sti/uniperif_player.c35
-rw-r--r--sound/soc/sti/uniperif_reader.c24
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
938err: 939err:
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
146stream_unlock:
147 snd_pcm_stream_unlock(player->substream);
148irq_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
997static int uni_player_parse_dt_audio_glue(struct platform_device *pdev, 1009static 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
73stream_unlock:
74 snd_pcm_stream_unlock(reader->substream);
75irq_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
386static const struct snd_soc_dai_ops uni_reader_dai_ops = { 400static 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}
420EXPORT_SYMBOL_GPL(uni_reader_init); 436EXPORT_SYMBOL_GPL(uni_reader_init);