1212#include <linux/delay.h>
1313#include <linux/module.h>
1414#include <linux/of_platform.h>
15- #include <linux/pinctrl/consumer.h>
1615#include <linux/regmap.h>
1716#include <linux/reset.h>
1817
220219 * @slave_config: dma slave channel runtime config pointer
221220 * @phys_addr: SPDIFRX registers physical base address
222221 * @lock: synchronization enabling lock
222+ * @irq_lock: prevent race condition with IRQ on stream state
223223 * @cs: channel status buffer
224224 * @ub: user data buffer
225225 * @irq: SPDIFRX interrupt line
@@ -240,6 +240,7 @@ struct stm32_spdifrx_data {
240240 struct dma_slave_config slave_config ;
241241 dma_addr_t phys_addr ;
242242 spinlock_t lock ; /* Sync enabling lock */
243+ spinlock_t irq_lock ; /* Prevent race condition on stream state */
243244 unsigned char cs [SPDIFRX_CS_BYTES_NB ];
244245 unsigned char ub [SPDIFRX_UB_BYTES_NB ];
245246 int irq ;
@@ -320,14 +321,15 @@ static void stm32_spdifrx_dma_ctrl_stop(struct stm32_spdifrx_data *spdifrx)
320321static int stm32_spdifrx_start_sync (struct stm32_spdifrx_data * spdifrx )
321322{
322323 int cr , cr_mask , imr , ret ;
324+ unsigned long flags ;
323325
324326 /* Enable IRQs */
325327 imr = SPDIFRX_IMR_IFEIE | SPDIFRX_IMR_SYNCDIE | SPDIFRX_IMR_PERRIE ;
326328 ret = regmap_update_bits (spdifrx -> regmap , STM32_SPDIFRX_IMR , imr , imr );
327329 if (ret )
328330 return ret ;
329331
330- spin_lock (& spdifrx -> lock );
332+ spin_lock_irqsave (& spdifrx -> lock , flags );
331333
332334 spdifrx -> refcount ++ ;
333335
@@ -362,19 +364,20 @@ static int stm32_spdifrx_start_sync(struct stm32_spdifrx_data *spdifrx)
362364 "Failed to start synchronization\n" );
363365 }
364366
365- spin_unlock (& spdifrx -> lock );
367+ spin_unlock_irqrestore (& spdifrx -> lock , flags );
366368
367369 return ret ;
368370}
369371
370372static void stm32_spdifrx_stop (struct stm32_spdifrx_data * spdifrx )
371373{
372374 int cr , cr_mask , reg ;
375+ unsigned long flags ;
373376
374- spin_lock (& spdifrx -> lock );
377+ spin_lock_irqsave (& spdifrx -> lock , flags );
375378
376379 if (-- spdifrx -> refcount ) {
377- spin_unlock (& spdifrx -> lock );
380+ spin_unlock_irqrestore (& spdifrx -> lock , flags );
378381 return ;
379382 }
380383
@@ -393,7 +396,7 @@ static void stm32_spdifrx_stop(struct stm32_spdifrx_data *spdifrx)
393396 regmap_read (spdifrx -> regmap , STM32_SPDIFRX_DR , & reg );
394397 regmap_read (spdifrx -> regmap , STM32_SPDIFRX_CSR , & reg );
395398
396- spin_unlock (& spdifrx -> lock );
399+ spin_unlock_irqrestore (& spdifrx -> lock , flags );
397400}
398401
399402static int stm32_spdifrx_dma_ctrl_register (struct device * dev ,
@@ -480,8 +483,6 @@ static int stm32_spdifrx_get_ctrl_data(struct stm32_spdifrx_data *spdifrx)
480483 memset (spdifrx -> cs , 0 , SPDIFRX_CS_BYTES_NB );
481484 memset (spdifrx -> ub , 0 , SPDIFRX_UB_BYTES_NB );
482485
483- pinctrl_pm_select_default_state (& spdifrx -> pdev -> dev );
484-
485486 ret = stm32_spdifrx_dma_ctrl_start (spdifrx );
486487 if (ret < 0 )
487488 return ret ;
@@ -513,7 +514,6 @@ static int stm32_spdifrx_get_ctrl_data(struct stm32_spdifrx_data *spdifrx)
513514
514515end :
515516 clk_disable_unprepare (spdifrx -> kclk );
516- pinctrl_pm_select_sleep_state (& spdifrx -> pdev -> dev );
517517
518518 return ret ;
519519}
@@ -665,7 +665,6 @@ static const struct regmap_config stm32_h7_spdifrx_regmap_conf = {
665665static irqreturn_t stm32_spdifrx_isr (int irq , void * devid )
666666{
667667 struct stm32_spdifrx_data * spdifrx = (struct stm32_spdifrx_data * )devid ;
668- struct snd_pcm_substream * substream = spdifrx -> substream ;
669668 struct platform_device * pdev = spdifrx -> pdev ;
670669 unsigned int cr , mask , sr , imr ;
671670 unsigned int flags , sync_state ;
@@ -745,14 +744,19 @@ static irqreturn_t stm32_spdifrx_isr(int irq, void *devid)
745744 return IRQ_HANDLED ;
746745 }
747746
748- if (substream )
749- snd_pcm_stop (substream , SNDRV_PCM_STATE_DISCONNECTED );
747+ spin_lock (& spdifrx -> irq_lock );
748+ if (spdifrx -> substream )
749+ snd_pcm_stop (spdifrx -> substream ,
750+ SNDRV_PCM_STATE_DISCONNECTED );
751+ spin_unlock (& spdifrx -> irq_lock );
750752
751753 return IRQ_HANDLED ;
752754 }
753755
754- if (err_xrun && substream )
755- snd_pcm_stop_xrun (substream );
756+ spin_lock (& spdifrx -> irq_lock );
757+ if (err_xrun && spdifrx -> substream )
758+ snd_pcm_stop_xrun (spdifrx -> substream );
759+ spin_unlock (& spdifrx -> irq_lock );
756760
757761 return IRQ_HANDLED ;
758762}
@@ -761,9 +765,12 @@ static int stm32_spdifrx_startup(struct snd_pcm_substream *substream,
761765 struct snd_soc_dai * cpu_dai )
762766{
763767 struct stm32_spdifrx_data * spdifrx = snd_soc_dai_get_drvdata (cpu_dai );
768+ unsigned long flags ;
764769 int ret ;
765770
771+ spin_lock_irqsave (& spdifrx -> irq_lock , flags );
766772 spdifrx -> substream = substream ;
773+ spin_unlock_irqrestore (& spdifrx -> irq_lock , flags );
767774
768775 ret = clk_prepare_enable (spdifrx -> kclk );
769776 if (ret )
@@ -839,8 +846,12 @@ static void stm32_spdifrx_shutdown(struct snd_pcm_substream *substream,
839846 struct snd_soc_dai * cpu_dai )
840847{
841848 struct stm32_spdifrx_data * spdifrx = snd_soc_dai_get_drvdata (cpu_dai );
849+ unsigned long flags ;
842850
851+ spin_lock_irqsave (& spdifrx -> irq_lock , flags );
843852 spdifrx -> substream = NULL ;
853+ spin_unlock_irqrestore (& spdifrx -> irq_lock , flags );
854+
844855 clk_disable_unprepare (spdifrx -> kclk );
845856}
846857
@@ -944,6 +955,7 @@ static int stm32_spdifrx_probe(struct platform_device *pdev)
944955 spdifrx -> pdev = pdev ;
945956 init_completion (& spdifrx -> cs_completion );
946957 spin_lock_init (& spdifrx -> lock );
958+ spin_lock_init (& spdifrx -> irq_lock );
947959
948960 platform_set_drvdata (pdev , spdifrx );
949961
0 commit comments