diff options
author | Takashi Iwai <tiwai@suse.de> | 2014-11-07 11:08:28 -0500 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2014-11-09 12:20:40 -0500 |
commit | 1fb8510cdb5b7befe8a59f533c7fc12ef0dac73e (patch) | |
tree | b44569425ea7683d02893cfd145081a11d7677f1 | |
parent | 31584ed18c073176a7ad96ddbfd09765e21e813d (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.c | 4 | ||||
-rw-r--r-- | include/sound/pcm.h | 1 | ||||
-rw-r--r-- | sound/arm/pxa2xx-pcm-lib.c | 4 | ||||
-rw-r--r-- | sound/core/pcm_native.c | 23 | ||||
-rw-r--r-- | sound/firewire/amdtp.c | 8 | ||||
-rw-r--r-- | sound/firewire/isight.c | 10 | ||||
-rw-r--r-- | sound/pci/asihpi/asihpi.c | 5 | ||||
-rw-r--r-- | sound/pci/atiixp.c | 4 | ||||
-rw-r--r-- | sound/pci/atiixp_modem.c | 4 | ||||
-rw-r--r-- | sound/soc/atmel/atmel-pcm-dma.c | 4 | ||||
-rw-r--r-- | sound/soc/fsl/fsl_dma.c | 9 | ||||
-rw-r--r-- | sound/usb/6fire/pcm.c | 17 | ||||
-rw-r--r-- | sound/usb/endpoint.c | 4 | ||||
-rw-r--r-- | sound/usb/misc/ua101.c | 18 | ||||
-rw-r--r-- | sound/usb/usx2y/usbusx2yaudio.c | 9 |
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, | |||
506 | int snd_pcm_start(struct snd_pcm_substream *substream); | 506 | int snd_pcm_start(struct snd_pcm_substream *substream); |
507 | int snd_pcm_stop(struct snd_pcm_substream *substream, snd_pcm_state_t status); | 507 | int snd_pcm_stop(struct snd_pcm_substream *substream, snd_pcm_state_t status); |
508 | int snd_pcm_drain_done(struct snd_pcm_substream *substream); | 508 | int snd_pcm_drain_done(struct snd_pcm_substream *substream); |
509 | int snd_pcm_stop_xrun(struct snd_pcm_substream *substream); | ||
509 | #ifdef CONFIG_PM | 510 | #ifdef CONFIG_PM |
510 | int snd_pcm_suspend(struct snd_pcm_substream *substream); | 511 | int snd_pcm_suspend(struct snd_pcm_substream *substream); |
511 | int snd_pcm_suspend_all(struct snd_pcm *pcm); | 512 | int 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 | } |
208 | EXPORT_SYMBOL(pxa2xx_pcm_dma_irq); | 206 | EXPORT_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 | */ | ||
1111 | int 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 | } | ||
1122 | EXPORT_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 | } |
1016 | EXPORT_SYMBOL(amdtp_stream_pcm_abort); | 1012 | EXPORT_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 | ||
132 | static void isight_pcm_abort(struct isight *isight) | 132 | static 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 | ||
144 | static void isight_dropped_samples(struct isight *isight, unsigned int total) | 138 | static 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 | */ |
152 | static void fsl_dma_abort_stream(struct snd_pcm_substream *substream) | 152 | static 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) | |||
679 | void usb6fire_pcm_abort(struct sfire_chip *chip) | 679 | void 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 | ||
399 | exit_clear: | 397 | exit_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 | ||
614 | static void abort_alsa_capture(struct ua101 *ua) | 614 | static 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 | ||
625 | static void abort_alsa_playback(struct ua101 *ua) | 620 | static 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 | ||
636 | static int set_stream_hw(struct ua101 *ua, struct snd_pcm_substream *substream, | 626 | static 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) |