Merge tag 'asoc-fix-v4.11-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound into for-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.

+48 -19
+2 -2
sound/soc/intel/boards/bytcr_rt5640.c
··· 621 .codec_dai_name = "snd-soc-dummy-dai", 622 .codec_name = "snd-soc-dummy", 623 .platform_name = "sst-mfld-platform", 624 - .ignore_suspend = 1, 625 .dynamic = 1, 626 .dpcm_playback = 1, 627 .dpcm_capture = 1, ··· 634 .codec_dai_name = "snd-soc-dummy-dai", 635 .codec_name = "snd-soc-dummy", 636 .platform_name = "sst-mfld-platform", 637 - .ignore_suspend = 1, 638 .nonatomic = true, 639 .dynamic = 1, 640 .dpcm_playback = 1, ··· 660 | SND_SOC_DAIFMT_CBS_CFS, 661 .be_hw_params_fixup = byt_rt5640_codec_fixup, 662 .ignore_suspend = 1, 663 .dpcm_playback = 1, 664 .dpcm_capture = 1, 665 .init = byt_rt5640_init,
··· 621 .codec_dai_name = "snd-soc-dummy-dai", 622 .codec_name = "snd-soc-dummy", 623 .platform_name = "sst-mfld-platform", 624 + .nonatomic = true, 625 .dynamic = 1, 626 .dpcm_playback = 1, 627 .dpcm_capture = 1, ··· 634 .codec_dai_name = "snd-soc-dummy-dai", 635 .codec_name = "snd-soc-dummy", 636 .platform_name = "sst-mfld-platform", 637 .nonatomic = true, 638 .dynamic = 1, 639 .dpcm_playback = 1, ··· 661 | SND_SOC_DAIFMT_CBS_CFS, 662 .be_hw_params_fixup = byt_rt5640_codec_fixup, 663 .ignore_suspend = 1, 664 + .nonatomic = true, 665 .dpcm_playback = 1, 666 .dpcm_capture = 1, 667 .init = byt_rt5640_init,
-2
sound/soc/intel/boards/bytcr_rt5651.c
··· 235 .codec_dai_name = "snd-soc-dummy-dai", 236 .codec_name = "snd-soc-dummy", 237 .platform_name = "sst-mfld-platform", 238 - .ignore_suspend = 1, 239 .nonatomic = true, 240 .dynamic = 1, 241 .dpcm_playback = 1, ··· 248 .codec_dai_name = "snd-soc-dummy-dai", 249 .codec_name = "snd-soc-dummy", 250 .platform_name = "sst-mfld-platform", 251 - .ignore_suspend = 1, 252 .nonatomic = true, 253 .dynamic = 1, 254 .dpcm_playback = 1,
··· 235 .codec_dai_name = "snd-soc-dummy-dai", 236 .codec_name = "snd-soc-dummy", 237 .platform_name = "sst-mfld-platform", 238 .nonatomic = true, 239 .dynamic = 1, 240 .dpcm_playback = 1, ··· 249 .codec_dai_name = "snd-soc-dummy-dai", 250 .codec_name = "snd-soc-dummy", 251 .platform_name = "sst-mfld-platform", 252 .nonatomic = true, 253 .dynamic = 1, 254 .dpcm_playback = 1,
+1
sound/soc/soc-topology.c
··· 933 } 934 } 935 936 return 0; 937 938 err:
··· 933 } 934 } 935 936 + se->texts = (const char * const *)se->dobj.control.dtexts; 937 return 0; 938 939 err:
+1
sound/soc/sti/uniperif.h
··· 1299 int ver; /* IP version, used by register access macros */ 1300 struct regmap_field *clk_sel; 1301 struct regmap_field *valid_sel; 1302 1303 /* capabilities */ 1304 const struct snd_pcm_hardware *hw;
··· 1299 int ver; /* IP version, used by register access macros */ 1300 struct regmap_field *clk_sel; 1301 struct regmap_field *valid_sel; 1302 + spinlock_t irq_lock; /* use to prevent race condition with IRQ */ 1303 1304 /* capabilities */ 1305 const struct snd_pcm_hardware *hw;
+24 -11
sound/soc/sti/uniperif_player.c
··· 65 unsigned int status; 66 unsigned int tmp; 67 68 - if (player->state == UNIPERIF_STATE_STOPPED) { 69 - /* Unexpected IRQ: do nothing */ 70 - return IRQ_NONE; 71 - } 72 73 /* Get interrupt status & clear them immediately */ 74 status = GET_UNIPERIF_ITS(player); ··· 91 SET_UNIPERIF_ITM_BCLR_FIFO_ERROR(player); 92 93 /* Stop the player */ 94 - snd_pcm_stream_lock(player->substream); 95 snd_pcm_stop(player->substream, SNDRV_PCM_STATE_XRUN); 96 - snd_pcm_stream_unlock(player->substream); 97 } 98 99 ret = IRQ_HANDLED; ··· 105 SET_UNIPERIF_ITM_BCLR_DMA_ERROR(player); 106 107 /* Stop the player */ 108 - snd_pcm_stream_lock(player->substream); 109 snd_pcm_stop(player->substream, SNDRV_PCM_STATE_XRUN); 110 - snd_pcm_stream_unlock(player->substream); 111 112 ret = IRQ_HANDLED; 113 } ··· 115 if (!player->underflow_enabled) { 116 dev_err(player->dev, 117 "unexpected Underflow recovering\n"); 118 - return -EPERM; 119 } 120 /* Read the underflow recovery duration */ 121 tmp = GET_UNIPERIF_STATUS_1_UNDERFLOW_DURATION(player); ··· 138 dev_err(player->dev, "Underflow recovery failed\n"); 139 140 /* Stop the player */ 141 - snd_pcm_stream_lock(player->substream); 142 snd_pcm_stop(player->substream, SNDRV_PCM_STATE_XRUN); 143 - snd_pcm_stream_unlock(player->substream); 144 145 ret = IRQ_HANDLED; 146 } 147 148 return ret; 149 } ··· 591 struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai); 592 struct uniperif *player = priv->dai_data.uni; 593 struct snd_aes_iec958 *iec958 = &player->stream_settings.iec958; 594 595 mutex_lock(&player->ctrl_lock); 596 iec958->status[0] = ucontrol->value.iec958.status[0]; ··· 600 iec958->status[3] = ucontrol->value.iec958.status[3]; 601 mutex_unlock(&player->ctrl_lock); 602 603 if (player->substream && player->substream->runtime) 604 uni_player_set_channel_status(player, 605 player->substream->runtime); 606 else 607 uni_player_set_channel_status(player, NULL); 608 609 return 0; 610 } 611 ··· 692 { 693 struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai); 694 struct uniperif *player = priv->dai_data.uni; 695 int ret; 696 697 player->substream = substream; 698 699 player->clk_adj = 0; 700 ··· 995 { 996 struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai); 997 struct uniperif *player = priv->dai_data.uni; 998 999 if (player->state != UNIPERIF_STATE_STOPPED) 1000 /* Stop the player */ 1001 uni_player_stop(player); 1002 1003 player->substream = NULL; 1004 } 1005 1006 static int uni_player_parse_dt_audio_glue(struct platform_device *pdev, ··· 1108 } 1109 1110 mutex_init(&player->ctrl_lock); 1111 1112 /* Ensure that disabled by default */ 1113 SET_UNIPERIF_CONFIG_BACK_STALL_REQ_DISABLE(player);
··· 65 unsigned int status; 66 unsigned int tmp; 67 68 + spin_lock(&player->irq_lock); 69 + if (!player->substream) 70 + goto irq_spin_unlock; 71 + 72 + snd_pcm_stream_lock(player->substream); 73 + if (player->state == UNIPERIF_STATE_STOPPED) 74 + goto stream_unlock; 75 76 /* Get interrupt status & clear them immediately */ 77 status = GET_UNIPERIF_ITS(player); ··· 88 SET_UNIPERIF_ITM_BCLR_FIFO_ERROR(player); 89 90 /* Stop the player */ 91 snd_pcm_stop(player->substream, SNDRV_PCM_STATE_XRUN); 92 } 93 94 ret = IRQ_HANDLED; ··· 104 SET_UNIPERIF_ITM_BCLR_DMA_ERROR(player); 105 106 /* Stop the player */ 107 snd_pcm_stop(player->substream, SNDRV_PCM_STATE_XRUN); 108 109 ret = IRQ_HANDLED; 110 } ··· 116 if (!player->underflow_enabled) { 117 dev_err(player->dev, 118 "unexpected Underflow recovering\n"); 119 + ret = -EPERM; 120 + goto stream_unlock; 121 } 122 /* Read the underflow recovery duration */ 123 tmp = GET_UNIPERIF_STATUS_1_UNDERFLOW_DURATION(player); ··· 138 dev_err(player->dev, "Underflow recovery failed\n"); 139 140 /* Stop the player */ 141 snd_pcm_stop(player->substream, SNDRV_PCM_STATE_XRUN); 142 143 ret = IRQ_HANDLED; 144 } 145 + 146 + stream_unlock: 147 + snd_pcm_stream_unlock(player->substream); 148 + irq_spin_unlock: 149 + spin_unlock(&player->irq_lock); 150 151 return ret; 152 } ··· 588 struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai); 589 struct uniperif *player = priv->dai_data.uni; 590 struct snd_aes_iec958 *iec958 = &player->stream_settings.iec958; 591 + unsigned long flags; 592 593 mutex_lock(&player->ctrl_lock); 594 iec958->status[0] = ucontrol->value.iec958.status[0]; ··· 596 iec958->status[3] = ucontrol->value.iec958.status[3]; 597 mutex_unlock(&player->ctrl_lock); 598 599 + spin_lock_irqsave(&player->irq_lock, flags); 600 if (player->substream && player->substream->runtime) 601 uni_player_set_channel_status(player, 602 player->substream->runtime); 603 else 604 uni_player_set_channel_status(player, NULL); 605 606 + spin_unlock_irqrestore(&player->irq_lock, flags); 607 return 0; 608 } 609 ··· 686 { 687 struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai); 688 struct uniperif *player = priv->dai_data.uni; 689 + unsigned long flags; 690 int ret; 691 692 + spin_lock_irqsave(&player->irq_lock, flags); 693 player->substream = substream; 694 + spin_unlock_irqrestore(&player->irq_lock, flags); 695 696 player->clk_adj = 0; 697 ··· 986 { 987 struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai); 988 struct uniperif *player = priv->dai_data.uni; 989 + unsigned long flags; 990 991 + spin_lock_irqsave(&player->irq_lock, flags); 992 if (player->state != UNIPERIF_STATE_STOPPED) 993 /* Stop the player */ 994 uni_player_stop(player); 995 996 player->substream = NULL; 997 + spin_unlock_irqrestore(&player->irq_lock, flags); 998 } 999 1000 static int uni_player_parse_dt_audio_glue(struct platform_device *pdev, ··· 1096 } 1097 1098 mutex_init(&player->ctrl_lock); 1099 + spin_lock_init(&player->irq_lock); 1100 1101 /* Ensure that disabled by default */ 1102 SET_UNIPERIF_CONFIG_BACK_STALL_REQ_DISABLE(player);
+20 -4
sound/soc/sti/uniperif_reader.c
··· 46 struct uniperif *reader = dev_id; 47 unsigned int status; 48 49 if (reader->state == UNIPERIF_STATE_STOPPED) { 50 /* Unexpected IRQ: do nothing */ 51 dev_warn(reader->dev, "unexpected IRQ\n"); 52 - return IRQ_HANDLED; 53 } 54 55 /* Get interrupt status & clear them immediately */ ··· 65 if (unlikely(status & UNIPERIF_ITS_FIFO_ERROR_MASK(reader))) { 66 dev_err(reader->dev, "FIFO error detected\n"); 67 68 - snd_pcm_stream_lock(reader->substream); 69 snd_pcm_stop(reader->substream, SNDRV_PCM_STATE_XRUN); 70 - snd_pcm_stream_unlock(reader->substream); 71 72 - return IRQ_HANDLED; 73 } 74 75 return ret; 76 } ··· 355 { 356 struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai); 357 struct uniperif *reader = priv->dai_data.uni; 358 int ret; 359 360 reader->substream = substream; 361 362 if (!UNIPERIF_TYPE_IS_TDM(reader)) 363 return 0; ··· 386 { 387 struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai); 388 struct uniperif *reader = priv->dai_data.uni; 389 390 if (reader->state != UNIPERIF_STATE_STOPPED) { 391 /* Stop the reader */ 392 uni_reader_stop(reader); 393 } 394 reader->substream = NULL; 395 } 396 397 static const struct snd_soc_dai_ops uni_reader_dai_ops = { ··· 428 dev_err(&pdev->dev, "Failed to request IRQ\n"); 429 return -EBUSY; 430 } 431 432 return 0; 433 }
··· 46 struct uniperif *reader = dev_id; 47 unsigned int status; 48 49 + spin_lock(&reader->irq_lock); 50 + if (!reader->substream) 51 + goto irq_spin_unlock; 52 + 53 + snd_pcm_stream_lock(reader->substream); 54 if (reader->state == UNIPERIF_STATE_STOPPED) { 55 /* Unexpected IRQ: do nothing */ 56 dev_warn(reader->dev, "unexpected IRQ\n"); 57 + goto stream_unlock; 58 } 59 60 /* Get interrupt status & clear them immediately */ ··· 60 if (unlikely(status & UNIPERIF_ITS_FIFO_ERROR_MASK(reader))) { 61 dev_err(reader->dev, "FIFO error detected\n"); 62 63 snd_pcm_stop(reader->substream, SNDRV_PCM_STATE_XRUN); 64 65 + ret = IRQ_HANDLED; 66 } 67 + 68 + stream_unlock: 69 + snd_pcm_stream_unlock(reader->substream); 70 + irq_spin_unlock: 71 + spin_unlock(&reader->irq_lock); 72 73 return ret; 74 } ··· 347 { 348 struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai); 349 struct uniperif *reader = priv->dai_data.uni; 350 + unsigned long flags; 351 int ret; 352 353 + spin_lock_irqsave(&reader->irq_lock, flags); 354 reader->substream = substream; 355 + spin_unlock_irqrestore(&reader->irq_lock, flags); 356 357 if (!UNIPERIF_TYPE_IS_TDM(reader)) 358 return 0; ··· 375 { 376 struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai); 377 struct uniperif *reader = priv->dai_data.uni; 378 + unsigned long flags; 379 380 + spin_lock_irqsave(&reader->irq_lock, flags); 381 if (reader->state != UNIPERIF_STATE_STOPPED) { 382 /* Stop the reader */ 383 uni_reader_stop(reader); 384 } 385 reader->substream = NULL; 386 + spin_unlock_irqrestore(&reader->irq_lock, flags); 387 } 388 389 static const struct snd_soc_dai_ops uni_reader_dai_ops = { ··· 414 dev_err(&pdev->dev, "Failed to request IRQ\n"); 415 return -EBUSY; 416 } 417 + 418 + spin_lock_init(&reader->irq_lock); 419 420 return 0; 421 }