[alsa-devel] [PATCH] Add M2Tech hiFace USB-SPDIF driver

Takashi Iwai tiwai at suse.de
Tue Feb 12 16:29:56 CET 2013


At Tue, 12 Feb 2013 15:29:19 +0100,
Clemens Ladisch wrote:
> 
> >>> +			snd_pcm_stop(rt->playback.instance,
> >>> +					SNDRV_PCM_STATE_XRUN);
> >>
> >> This requres locking the stream with something like
> >> snd_pcm_stream_lock_irq().
> >
> > OK, but would you mind elaborating a little more why this is needed?
> >
> > I do not see other drivers doing that,
> 
> sound/firewire/{amdtp,isight}.c do.  I've never said that all those
> other drivers would be correct.  (And you have to be careful to avoid
> deadlocks.)
> 
> > and BTW I see also that some other drivers not calling snd_pcm_stop()
> > at all, e.g. it is commented in sound/usb/endpoint.c::snd_complete_urb().
> 
> It's commented because it would crash.  That driver isn't in a very
> good state regarding state changes.

The problem is that you can't kill the urb itself gracefully while in
the complete callback.  But a patch like below could work a little bit
better, although it doesn't notify the XRUN at that moment.


Takashi

---
diff --git a/sound/usb/card.h b/sound/usb/card.h
index 8a751b4..d98e7bc 100644
--- a/sound/usb/card.h
+++ b/sound/usb/card.h
@@ -118,6 +118,7 @@ struct snd_usb_substream {
 	unsigned int fmt_type;		/* USB audio format type (1-3) */
 
 	unsigned int running: 1;	/* running status */
+	unsigned int xrun:1;
 
 	unsigned int hwptr_done;	/* processed byte position in the buffer */
 	unsigned int transfer_done;		/* processed frames since last period update */
diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c
index 21049b8..e52aee9 100644
--- a/sound/usb/endpoint.c
+++ b/sound/usb/endpoint.c
@@ -357,6 +357,9 @@ static void snd_complete_urb(struct urb *urb)
 		     ep->chip->shutdown))		/* device disconnected */
 		goto exit_clear;
 
+	if (ep->data_subs && ep->data_subs->xrun)
+		goto exit_clear;
+
 	if (usb_pipeout(ep->pipe)) {
 		retire_outbound_urb(ep, ctx);
 		/* can be stopped during retire callback */
@@ -389,7 +392,8 @@ static void snd_complete_urb(struct urb *urb)
 		return;
 
 	snd_printk(KERN_ERR "cannot submit urb (err = %d)\n", err);
-	//snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
+	if (ep->data_subs)
+		ep->data_subs->xrun = 1;
 
 exit_clear:
 	clear_bit(ctx->index, &ep->active_mask);
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
index f94397b..6be6662 100644
--- a/sound/usb/pcm.c
+++ b/sound/usb/pcm.c
@@ -79,7 +79,7 @@ static snd_pcm_uframes_t snd_usb_pcm_pointer(struct snd_pcm_substream *substream
 	unsigned int hwptr_done;
 
 	subs = (struct snd_usb_substream *)substream->runtime->private_data;
-	if (subs->stream->chip->shutdown)
+	if (subs->xrun || subs->stream->chip->shutdown)
 		return SNDRV_PCM_POS_XRUN;
 	spin_lock(&subs->lock);
 	hwptr_done = subs->hwptr_done;
@@ -726,6 +726,7 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream)
 	subs->transfer_done = 0;
 	subs->last_delay = 0;
 	subs->last_frame_number = 0;
+	subs->xrun = 0;
 	runtime->delay = 0;
 
 	/* for playback, submit the URBs now; otherwise, the first hwptr_done



More information about the Alsa-devel mailing list