aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2014-11-07 11:08:28 -0500
committerTakashi Iwai <tiwai@suse.de>2014-11-09 12:20:40 -0500
commit1fb8510cdb5b7befe8a59f533c7fc12ef0dac73e (patch)
treeb44569425ea7683d02893cfd145081a11d7677f1
parent31584ed18c073176a7ad96ddbfd09765e21e813d (diff)
ALSA: pcm: Add snd_pcm_stop_xrun() helper
Add a new helper function snd_pcm_stop_xrun() to the standard sequnce lock/snd_pcm_stop(XRUN)/unlock by a single call, and replace the existing open codes with this helper. The function checks the PCM running state to prevent setting the wrong state, too, for more safety. Signed-off-by: Takashi Iwai <tiwai@suse.de>
-rw-r--r--drivers/media/pci/saa7134/saa7134-alsa.c4
-rw-r--r--include/sound/pcm.h1
-rw-r--r--sound/arm/pxa2xx-pcm-lib.c4
-rw-r--r--sound/core/pcm_native.c23
-rw-r--r--sound/firewire/amdtp.c8
-rw-r--r--sound/firewire/isight.c10
-rw-r--r--sound/pci/asihpi/asihpi.c5
-rw-r--r--sound/pci/atiixp.c4
-rw-r--r--sound/pci/atiixp_modem.c4
-rw-r--r--sound/soc/atmel/atmel-pcm-dma.c4
-rw-r--r--sound/soc/fsl/fsl_dma.c9
-rw-r--r--sound/usb/6fire/pcm.c17
-rw-r--r--sound/usb/endpoint.c4
-rw-r--r--sound/usb/misc/ua101.c18
-rw-r--r--sound/usb/usx2y/usbusx2yaudio.c9
15 files changed, 46 insertions, 78 deletions
diff --git a/drivers/media/pci/saa7134/saa7134-alsa.c b/drivers/media/pci/saa7134/saa7134-alsa.c
index 40569894c1c9..ac3cd74e824e 100644
--- a/drivers/media/pci/saa7134/saa7134-alsa.c
+++ b/drivers/media/pci/saa7134/saa7134-alsa.c
@@ -173,9 +173,7 @@ static void saa7134_irq_alsa_done(struct saa7134_dev *dev,
173 dprintk("irq: overrun [full=%d/%d] - Blocks in %d\n",dev->dmasound.read_count, 173 dprintk("irq: overrun [full=%d/%d] - Blocks in %d\n",dev->dmasound.read_count,
174 dev->dmasound.bufsize, dev->dmasound.blocks); 174 dev->dmasound.bufsize, dev->dmasound.blocks);
175 spin_unlock(&dev->slock); 175 spin_unlock(&dev->slock);
176 snd_pcm_stream_lock(dev->dmasound.substream); 176 snd_pcm_stop_xrun(dev->dmasound.substream);
177 snd_pcm_stop(dev->dmasound.substream,SNDRV_PCM_STATE_XRUN);
178 snd_pcm_stream_unlock(dev->dmasound.substream);
179 return; 177 return;
180 } 178 }
181 179
diff --git a/include/sound/pcm.h b/include/sound/pcm.h
index 0b8daeed0a33..40289ec2451c 100644
--- a/include/sound/pcm.h
+++ b/include/sound/pcm.h
@@ -506,6 +506,7 @@ int snd_pcm_status(struct snd_pcm_substream *substream,
506int snd_pcm_start(struct snd_pcm_substream *substream); 506int snd_pcm_start(struct snd_pcm_substream *substream);
507int snd_pcm_stop(struct snd_pcm_substream *substream, snd_pcm_state_t status); 507int snd_pcm_stop(struct snd_pcm_substream *substream, snd_pcm_state_t status);
508int snd_pcm_drain_done(struct snd_pcm_substream *substream); 508int snd_pcm_drain_done(struct snd_pcm_substream *substream);
509int snd_pcm_stop_xrun(struct snd_pcm_substream *substream);
509#ifdef CONFIG_PM 510#ifdef CONFIG_PM
510int snd_pcm_suspend(struct snd_pcm_substream *substream); 511int snd_pcm_suspend(struct snd_pcm_substream *substream);
511int snd_pcm_suspend_all(struct snd_pcm *pcm); 512int snd_pcm_suspend_all(struct snd_pcm *pcm);
diff --git a/sound/arm/pxa2xx-pcm-lib.c b/sound/arm/pxa2xx-pcm-lib.c
index a61d7a9a995e..01f8fdc42b1b 100644
--- a/sound/arm/pxa2xx-pcm-lib.c
+++ b/sound/arm/pxa2xx-pcm-lib.c
@@ -200,9 +200,7 @@ void pxa2xx_pcm_dma_irq(int dma_ch, void *dev_id)
200 } else { 200 } else {
201 printk(KERN_ERR "DMA error on channel %d (DCSR=%#x)\n", 201 printk(KERN_ERR "DMA error on channel %d (DCSR=%#x)\n",
202 dma_ch, dcsr); 202 dma_ch, dcsr);
203 snd_pcm_stream_lock(substream); 203 snd_pcm_stop_xrun(substream);
204 snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
205 snd_pcm_stream_unlock(substream);
206 } 204 }
207} 205}
208EXPORT_SYMBOL(pxa2xx_pcm_dma_irq); 206EXPORT_SYMBOL(pxa2xx_pcm_dma_irq);
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index dfb5031969f8..a3d122109704 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -1098,6 +1098,29 @@ int snd_pcm_drain_done(struct snd_pcm_substream *substream)
1098 SNDRV_PCM_STATE_SETUP); 1098 SNDRV_PCM_STATE_SETUP);
1099} 1099}
1100 1100
1101/**
1102 * snd_pcm_stop_xrun - stop the running streams as XRUN
1103 * @substream: the PCM substream instance
1104 * @state: PCM state after stopping the stream
1105 *
1106 * This stops the given running substream (and all linked substreams) as XRUN.
1107 * Unlike snd_pcm_stop(), this function takes the substream lock by itself.
1108 *
1109 * Return: Zero if successful, or a negative error code.
1110 */
1111int snd_pcm_stop_xrun(struct snd_pcm_substream *substream)
1112{
1113 unsigned long flags;
1114 int ret = 0;
1115
1116 snd_pcm_stream_lock_irqsave(substream, flags);
1117 if (snd_pcm_running(substream))
1118 ret = snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
1119 snd_pcm_stream_unlock_irqrestore(substream, flags);
1120 return ret;
1121}
1122EXPORT_SYMBOL_GPL(snd_pcm_stop_xrun);
1123
1101/* 1124/*
1102 * pause callbacks 1125 * pause callbacks
1103 */ 1126 */
diff --git a/sound/firewire/amdtp.c b/sound/firewire/amdtp.c
index 95fc2eaf11dc..3badc70124ab 100644
--- a/sound/firewire/amdtp.c
+++ b/sound/firewire/amdtp.c
@@ -1006,11 +1006,7 @@ void amdtp_stream_pcm_abort(struct amdtp_stream *s)
1006 struct snd_pcm_substream *pcm; 1006 struct snd_pcm_substream *pcm;
1007 1007
1008 pcm = ACCESS_ONCE(s->pcm); 1008 pcm = ACCESS_ONCE(s->pcm);
1009 if (pcm) { 1009 if (pcm)
1010 snd_pcm_stream_lock_irq(pcm); 1010 snd_pcm_stop_xrun(pcm);
1011 if (snd_pcm_running(pcm))
1012 snd_pcm_stop(pcm, SNDRV_PCM_STATE_XRUN);
1013 snd_pcm_stream_unlock_irq(pcm);
1014 }
1015} 1011}
1016EXPORT_SYMBOL(amdtp_stream_pcm_abort); 1012EXPORT_SYMBOL(amdtp_stream_pcm_abort);
diff --git a/sound/firewire/isight.c b/sound/firewire/isight.c
index 7ac94439e758..48d6dca471c6 100644
--- a/sound/firewire/isight.c
+++ b/sound/firewire/isight.c
@@ -131,14 +131,8 @@ static void isight_samples(struct isight *isight,
131 131
132static void isight_pcm_abort(struct isight *isight) 132static void isight_pcm_abort(struct isight *isight)
133{ 133{
134 unsigned long flags; 134 if (ACCESS_ONCE(isight->pcm_active))
135 135 snd_pcm_stop_xrun(isight->pcm);
136 if (ACCESS_ONCE(isight->pcm_active)) {
137 snd_pcm_stream_lock_irqsave(isight->pcm, flags);
138 if (snd_pcm_running(isight->pcm))
139 snd_pcm_stop(isight->pcm, SNDRV_PCM_STATE_XRUN);
140 snd_pcm_stream_unlock_irqrestore(isight->pcm, flags);
141 }
142} 136}
143 137
144static void isight_dropped_samples(struct isight *isight, unsigned int total) 138static void isight_dropped_samples(struct isight *isight, unsigned int total)
diff --git a/sound/pci/asihpi/asihpi.c b/sound/pci/asihpi/asihpi.c
index ac66b3228a34..ff9f9f1c0391 100644
--- a/sound/pci/asihpi/asihpi.c
+++ b/sound/pci/asihpi/asihpi.c
@@ -769,10 +769,7 @@ static void snd_card_asihpi_timer_function(unsigned long data)
769 s->number); 769 s->number);
770 ds->drained_count++; 770 ds->drained_count++;
771 if (ds->drained_count > 20) { 771 if (ds->drained_count > 20) {
772 unsigned long flags; 772 snd_pcm_stop_xrun(s);
773 snd_pcm_stream_lock_irqsave(s, flags);
774 snd_pcm_stop(s, SNDRV_PCM_STATE_XRUN);
775 snd_pcm_stream_unlock_irqrestore(s, flags);
776 continue; 773 continue;
777 } 774 }
778 } else { 775 } else {
diff --git a/sound/pci/atiixp.c b/sound/pci/atiixp.c
index 7895c5d300c7..9c1c4452a8ee 100644
--- a/sound/pci/atiixp.c
+++ b/sound/pci/atiixp.c
@@ -688,9 +688,7 @@ static void snd_atiixp_xrun_dma(struct atiixp *chip, struct atiixp_dma *dma)
688 if (! dma->substream || ! dma->running) 688 if (! dma->substream || ! dma->running)
689 return; 689 return;
690 dev_dbg(chip->card->dev, "XRUN detected (DMA %d)\n", dma->ops->type); 690 dev_dbg(chip->card->dev, "XRUN detected (DMA %d)\n", dma->ops->type);
691 snd_pcm_stream_lock(dma->substream); 691 snd_pcm_stop_xrun(dma->substream);
692 snd_pcm_stop(dma->substream, SNDRV_PCM_STATE_XRUN);
693 snd_pcm_stream_unlock(dma->substream);
694} 692}
695 693
696/* 694/*
diff --git a/sound/pci/atiixp_modem.c b/sound/pci/atiixp_modem.c
index 3c3241309a30..b2f63e0727de 100644
--- a/sound/pci/atiixp_modem.c
+++ b/sound/pci/atiixp_modem.c
@@ -638,9 +638,7 @@ static void snd_atiixp_xrun_dma(struct atiixp_modem *chip,
638 if (! dma->substream || ! dma->running) 638 if (! dma->substream || ! dma->running)
639 return; 639 return;
640 dev_dbg(chip->card->dev, "XRUN detected (DMA %d)\n", dma->ops->type); 640 dev_dbg(chip->card->dev, "XRUN detected (DMA %d)\n", dma->ops->type);
641 snd_pcm_stream_lock(dma->substream); 641 snd_pcm_stop_xrun(dma->substream);
642 snd_pcm_stop(dma->substream, SNDRV_PCM_STATE_XRUN);
643 snd_pcm_stream_unlock(dma->substream);
644} 642}
645 643
646/* 644/*
diff --git a/sound/soc/atmel/atmel-pcm-dma.c b/sound/soc/atmel/atmel-pcm-dma.c
index b79a2a864513..33fb3bb133df 100644
--- a/sound/soc/atmel/atmel-pcm-dma.c
+++ b/sound/soc/atmel/atmel-pcm-dma.c
@@ -80,9 +80,7 @@ static void atmel_pcm_dma_irq(u32 ssc_sr,
80 80
81 /* stop RX and capture: will be enabled again at restart */ 81 /* stop RX and capture: will be enabled again at restart */
82 ssc_writex(prtd->ssc->regs, SSC_CR, prtd->mask->ssc_disable); 82 ssc_writex(prtd->ssc->regs, SSC_CR, prtd->mask->ssc_disable);
83 snd_pcm_stream_lock(substream); 83 snd_pcm_stop_xrun(substream);
84 snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
85 snd_pcm_stream_unlock(substream);
86 84
87 /* now drain RHR and read status to remove xrun condition */ 85 /* now drain RHR and read status to remove xrun condition */
88 ssc_readx(prtd->ssc->regs, SSC_RHR); 86 ssc_readx(prtd->ssc->regs, SSC_RHR);
diff --git a/sound/soc/fsl/fsl_dma.c b/sound/soc/fsl/fsl_dma.c
index a609aafc994d..b2b108805b24 100644
--- a/sound/soc/fsl/fsl_dma.c
+++ b/sound/soc/fsl/fsl_dma.c
@@ -151,14 +151,7 @@ static const struct snd_pcm_hardware fsl_dma_hardware = {
151 */ 151 */
152static void fsl_dma_abort_stream(struct snd_pcm_substream *substream) 152static void fsl_dma_abort_stream(struct snd_pcm_substream *substream)
153{ 153{
154 unsigned long flags; 154 snd_pcm_stop_xrun(substream);
155
156 snd_pcm_stream_lock_irqsave(substream, flags);
157
158 if (snd_pcm_running(substream))
159 snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
160
161 snd_pcm_stream_unlock_irqrestore(substream, flags);
162} 155}
163 156
164/** 157/**
diff --git a/sound/usb/6fire/pcm.c b/sound/usb/6fire/pcm.c
index ba40489b2de4..36f4115eb1cd 100644
--- a/sound/usb/6fire/pcm.c
+++ b/sound/usb/6fire/pcm.c
@@ -679,25 +679,16 @@ int usb6fire_pcm_init(struct sfire_chip *chip)
679void usb6fire_pcm_abort(struct sfire_chip *chip) 679void usb6fire_pcm_abort(struct sfire_chip *chip)
680{ 680{
681 struct pcm_runtime *rt = chip->pcm; 681 struct pcm_runtime *rt = chip->pcm;
682 unsigned long flags;
683 int i; 682 int i;
684 683
685 if (rt) { 684 if (rt) {
686 rt->panic = true; 685 rt->panic = true;
687 686
688 if (rt->playback.instance) { 687 if (rt->playback.instance)
689 snd_pcm_stream_lock_irqsave(rt->playback.instance, flags); 688 snd_pcm_stop_xrun(rt->playback.instance);
690 snd_pcm_stop(rt->playback.instance,
691 SNDRV_PCM_STATE_XRUN);
692 snd_pcm_stream_unlock_irqrestore(rt->playback.instance, flags);
693 }
694 689
695 if (rt->capture.instance) { 690 if (rt->capture.instance)
696 snd_pcm_stream_lock_irqsave(rt->capture.instance, flags); 691 snd_pcm_stop_xrun(rt->capture.instance);
697 snd_pcm_stop(rt->capture.instance,
698 SNDRV_PCM_STATE_XRUN);
699 snd_pcm_stream_unlock_irqrestore(rt->capture.instance, flags);
700 }
701 692
702 for (i = 0; i < PCM_N_URBS; i++) { 693 for (i = 0; i < PCM_N_URBS; i++) {
703 usb_poison_urb(&rt->in_urbs[i].instance); 694 usb_poison_urb(&rt->in_urbs[i].instance);
diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c
index a4679913b0aa..03b074419964 100644
--- a/sound/usb/endpoint.c
+++ b/sound/usb/endpoint.c
@@ -391,9 +391,7 @@ static void snd_complete_urb(struct urb *urb)
391 usb_audio_err(ep->chip, "cannot submit urb (err = %d)\n", err); 391 usb_audio_err(ep->chip, "cannot submit urb (err = %d)\n", err);
392 if (ep->data_subs && ep->data_subs->pcm_substream) { 392 if (ep->data_subs && ep->data_subs->pcm_substream) {
393 substream = ep->data_subs->pcm_substream; 393 substream = ep->data_subs->pcm_substream;
394 snd_pcm_stream_lock_irqsave(substream, flags); 394 snd_pcm_stop_xrun(substream);
395 snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
396 snd_pcm_stream_unlock_irqrestore(substream, flags);
397 } 395 }
398 396
399exit_clear: 397exit_clear:
diff --git a/sound/usb/misc/ua101.c b/sound/usb/misc/ua101.c
index a1bab149df4d..9581089c28c5 100644
--- a/sound/usb/misc/ua101.c
+++ b/sound/usb/misc/ua101.c
@@ -613,24 +613,14 @@ static int start_usb_playback(struct ua101 *ua)
613 613
614static void abort_alsa_capture(struct ua101 *ua) 614static void abort_alsa_capture(struct ua101 *ua)
615{ 615{
616 unsigned long flags; 616 if (test_bit(ALSA_CAPTURE_RUNNING, &ua->states))
617 617 snd_pcm_stop_xrun(ua->capture.substream);
618 if (test_bit(ALSA_CAPTURE_RUNNING, &ua->states)) {
619 snd_pcm_stream_lock_irqsave(ua->capture.substream, flags);
620 snd_pcm_stop(ua->capture.substream, SNDRV_PCM_STATE_XRUN);
621 snd_pcm_stream_unlock_irqrestore(ua->capture.substream, flags);
622 }
623} 618}
624 619
625static void abort_alsa_playback(struct ua101 *ua) 620static void abort_alsa_playback(struct ua101 *ua)
626{ 621{
627 unsigned long flags; 622 if (test_bit(ALSA_PLAYBACK_RUNNING, &ua->states))
628 623 snd_pcm_stop_xrun(ua->playback.substream);
629 if (test_bit(ALSA_PLAYBACK_RUNNING, &ua->states)) {
630 snd_pcm_stream_lock_irqsave(ua->playback.substream, flags);
631 snd_pcm_stop(ua->playback.substream, SNDRV_PCM_STATE_XRUN);
632 snd_pcm_stream_unlock_irqrestore(ua->playback.substream, flags);
633 }
634} 624}
635 625
636static int set_stream_hw(struct ua101 *ua, struct snd_pcm_substream *substream, 626static int set_stream_hw(struct ua101 *ua, struct snd_pcm_substream *substream,
diff --git a/sound/usb/usx2y/usbusx2yaudio.c b/sound/usb/usx2y/usbusx2yaudio.c
index a63330dd1407..61d5dc2a3421 100644
--- a/sound/usb/usx2y/usbusx2yaudio.c
+++ b/sound/usb/usx2y/usbusx2yaudio.c
@@ -272,13 +272,8 @@ static void usX2Y_clients_stop(struct usX2Ydev *usX2Y)
272 for (s = 0; s < 4; s++) { 272 for (s = 0; s < 4; s++) {
273 struct snd_usX2Y_substream *subs = usX2Y->subs[s]; 273 struct snd_usX2Y_substream *subs = usX2Y->subs[s];
274 if (subs) { 274 if (subs) {
275 if (atomic_read(&subs->state) >= state_PRERUNNING) { 275 if (atomic_read(&subs->state) >= state_PRERUNNING)
276 unsigned long flags; 276 snd_pcm_stop_xrun(subs->pcm_substream);
277
278 snd_pcm_stream_lock_irqsave(subs->pcm_substream, flags);
279 snd_pcm_stop(subs->pcm_substream, SNDRV_PCM_STATE_XRUN);
280 snd_pcm_stream_unlock_irqrestore(subs->pcm_substream, flags);
281 }
282 for (u = 0; u < NRURBS; u++) { 277 for (u = 0; u < NRURBS; u++) {
283 struct urb *urb = subs->urb[u]; 278 struct urb *urb = subs->urb[u];
284 if (NULL != urb) 279 if (NULL != urb)