All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] usbaudio fixes
@ 2003-06-19  7:00 Clemens Ladisch
  2003-06-20 18:14 ` Takashi Iwai
  0 siblings, 1 reply; 11+ messages in thread
From: Clemens Ladisch @ 2003-06-19  7:00 UTC (permalink / raw)
  To: alsa-devel; +Cc: Stephane Alnet


I botched my previous patch for the UA-5: the altsettings of the audio
interface would be ignored because bInterfaceSubClass isn't set to
USB_SUBCLASS_AUDIO_STREAMING on that device. This patch corrects this.

And some devices (e.g. the Logitech QuickCam Web) have an endpoint
with wMaxPacketSize == 0, and no class-specific descriptors in their
first altsetting (instead of no endpoints). The additional check now
suppresses an unnecessary warning message.


Index: alsa-kernel/usb/usbaudio.c
===================================================================
RCS file: /cvsroot/alsa/alsa-kernel/usb/usbaudio.c,v
retrieving revision 1.56
diff -u -r1.56 usbaudio.c
--- alsa-kernel/usb/usbaudio.c	4 Jun 2003 12:43:55 -0000	1.56
+++ alsa-kernel/usb/usbaudio.c	19 Jun 2003 06:51:04 -0000
@@ -2163,8 +2163,10 @@
 		/* skip invalid one */
 		if ((altsd->bInterfaceClass != USB_CLASS_AUDIO &&
 		     altsd->bInterfaceClass != USB_CLASS_VENDOR_SPEC) ||
-		    altsd->bInterfaceSubClass != USB_SUBCLASS_AUDIO_STREAMING ||
-		    altsd->bNumEndpoints < 1)
+		    (altsd->bInterfaceSubClass != USB_SUBCLASS_AUDIO_STREAMING &&
+		     altsd->bInterfaceSubClass != USB_SUBCLASS_VENDOR_SPEC) ||
+		    altsd->bNumEndpoints < 1 ||
+		    get_endpoint(alts, 0)->wMaxPacketSize == 0)
 			continue;
 		/* must be isochronous */
 		if ((get_endpoint(alts, 0)->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) !=
Index: alsa-kernel/usb/usbaudio.h
===================================================================
RCS file: /cvsroot/alsa/alsa-kernel/usb/usbaudio.h,v
retrieving revision 1.17
diff -u -r1.17 usbaudio.h
--- alsa-kernel/usb/usbaudio.h	13 May 2003 10:44:09 -0000	1.17
+++ alsa-kernel/usb/usbaudio.h	19 Jun 2003 06:51:04 -0000
@@ -28,6 +28,7 @@
 #define USB_SUBCLASS_AUDIO_CONTROL	0x01
 #define USB_SUBCLASS_AUDIO_STREAMING	0x02
 #define USB_SUBCLASS_MIDI_STREAMING	0x03
+#define USB_SUBCLASS_VENDOR_SPEC	0xff

 #define USB_DT_CS_DEVICE                0x21
 #define USB_DT_CS_CONFIG                0x22




-------------------------------------------------------
This SF.Net email is sponsored by: INetU
Attention Web Developers & Consultants: Become An INetU Hosting Partner.
Refer Dedicated Servers. We Manage Them. You Get 10% Monthly Commission!
INetU Dedicated Managed Hosting http://www.inetu.net/partner/index.php

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH] usbaudio fixes
  2003-06-19  7:00 Clemens Ladisch
@ 2003-06-20 18:14 ` Takashi Iwai
  0 siblings, 0 replies; 11+ messages in thread
From: Takashi Iwai @ 2003-06-20 18:14 UTC (permalink / raw)
  To: Clemens Ladisch; +Cc: alsa-devel, Stephane Alnet

At Thu, 19 Jun 2003 09:00:47 +0200 (METDST),
Clemens Ladisch wrote:
> 
> 
> I botched my previous patch for the UA-5: the altsettings of the audio
> interface would be ignored because bInterfaceSubClass isn't set to
> USB_SUBCLASS_AUDIO_STREAMING on that device. This patch corrects this.
> 
> And some devices (e.g. the Logitech QuickCam Web) have an endpoint
> with wMaxPacketSize == 0, and no class-specific descriptors in their
> first altsetting (instead of no endpoints). The additional check now
> suppresses an unnecessary warning message.

thanks, applied to cvs now.


Takashi


-------------------------------------------------------
This SF.Net email is sponsored by: INetU
Attention Web Developers & Consultants: Become An INetU Hosting Partner.
Refer Dedicated Servers. We Manage Them. You Get 10% Monthly Commission!
INetU Dedicated Managed Hosting http://www.inetu.net/partner/index.php

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH] usbaudio fixes
@ 2003-11-24  7:46 Clemens Ladisch
  2003-11-24 11:27 ` Takashi Iwai
  2003-11-24 11:37 ` Takashi Iwai
  0 siblings, 2 replies; 11+ messages in thread
From: Clemens Ladisch @ 2003-11-24  7:46 UTC (permalink / raw)
  To: alsa-devel


- don't clear active_mask bits until it's clear that the URB is _not_
  resubmitted, to prevent a race with unlinking
- initialize active_mask and unlink_mask each time before URBs are
  started
- don't call sleeping functions in trigger callback


Index: alsa-kernel/usb/usbaudio.c
===================================================================
RCS file: /cvsroot/alsa/alsa-kernel/usb/usbaudio.c,v
retrieving revision 1.70
diff -u -r1.70 usbaudio.c
--- alsa-kernel/usb/usbaudio.c	20 Nov 2003 16:08:26 -0000	1.70
+++ alsa-kernel/usb/usbaudio.c	24 Nov 2003 07:40:19 -0000
@@ -573,21 +573,18 @@
 	snd_urb_ctx_t *ctx = (snd_urb_ctx_t *)urb->context;
 	snd_usb_substream_t *subs = ctx->subs;
 	snd_pcm_substream_t *substream = ctx->subs->pcm_substream;
-	int err;
+	int err = 0;

-	clear_bit(ctx->index, &subs->active_mask);
-	clear_bit(ctx->index, &subs->unlink_mask);
-	if (subs->running && subs->ops.retire(subs, substream->runtime, urb))
-		return;
-	if (! subs->running) /* can be stopped during retire callback */
-		return;
-	if ((err = subs->ops.prepare(subs, substream->runtime, urb)) < 0 ||
+	if ((subs->running && subs->ops.retire(subs, substream->runtime, urb)) ||
+	    ! subs->running || /* can be stopped during retire callback */
+	    (err = subs->ops.prepare(subs, substream->runtime, urb)) < 0 ||
 	    (err = usb_submit_urb(urb, GFP_ATOMIC)) < 0) {
-		snd_printd(KERN_ERR "cannot submit urb (err = %d)\n", err);
-		snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
-		return;
+		clear_bit(ctx->index, &subs->active_mask);
+		if (err < 0) {
+			snd_printd(KERN_ERR "cannot submit urb (err = %d)\n", err);
+			snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
+		}
 	}
-	set_bit(ctx->index, &subs->active_mask);
 }


@@ -599,21 +596,18 @@
 	snd_urb_ctx_t *ctx = (snd_urb_ctx_t *)urb->context;
 	snd_usb_substream_t *subs = ctx->subs;
 	snd_pcm_substream_t *substream = ctx->subs->pcm_substream;
-	int err;
+	int err = 0;

-	clear_bit(ctx->index + 16, &subs->active_mask);
-	clear_bit(ctx->index + 16, &subs->unlink_mask);
-	if (subs->running && subs->ops.retire_sync(subs, substream->runtime, urb))
-		return;
-	if (! subs->running) /* can be stopped during retire callback */
-		return;
-	if ((err = subs->ops.prepare_sync(subs, substream->runtime, urb))  < 0 ||
+	if ((subs->running && subs->ops.retire_sync(subs, substream->runtime, urb)) ||
+	    ! subs->running || /* can be stopped during retire callback */
+	    (err = subs->ops.prepare_sync(subs, substream->runtime, urb)) < 0 ||
 	    (err = usb_submit_urb(urb, GFP_ATOMIC)) < 0) {
-		snd_printd(KERN_ERR "cannot submit sync urb (err = %d)\n", err);
-		snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
-		return;
+		clear_bit(ctx->index + 16, &subs->active_mask);
+		if (err < 0) {
+			snd_printd(KERN_ERR "cannot submit sync urb (err = %d)\n", err);
+			snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
+		}
 	}
-	set_bit(ctx->index + 16, &subs->active_mask);
 }


@@ -694,9 +688,11 @@
 		}
 	}

+	subs->active_mask = 0;
+	subs->unlink_mask = 0;
 	subs->running = 1;
 	for (i = 0; i < subs->nurbs; i++) {
-		if ((err = usb_submit_urb(subs->dataurb[i].urb, GFP_KERNEL)) < 0) {
+		if ((err = usb_submit_urb(subs->dataurb[i].urb, GFP_ATOMIC)) < 0) {
 			snd_printk(KERN_ERR "cannot submit datapipe for urb %d, err = %d\n", i, err);
 			goto __error;
 		}
@@ -704,7 +700,7 @@
 	}
 	if (subs->syncpipe) {
 		for (i = 0; i < SYNC_URBS; i++) {
-			if ((err = usb_submit_urb(subs->syncurb[i].urb, GFP_KERNEL)) < 0) {
+			if ((err = usb_submit_urb(subs->syncurb[i].urb, GFP_ATOMIC)) < 0) {
 				snd_printk(KERN_ERR "cannot submit syncpipe for urb %d, err = %d\n", i, err);
 				goto __error;
 			}
@@ -843,8 +839,6 @@
 	subs->hwptr_done = 0;
 	subs->transfer_sched = 0;
 	subs->transfer_done = 0;
-	subs->active_mask = 0;
-	subs->unlink_mask = 0;

 	/* calculate the max. size of packet */
 	maxsize = ((subs->freqmax + 0x3fff) * (frame_bits >> 3)) >> 14;
@@ -1282,9 +1276,6 @@
 	/* some unit conversions in runtime */
 	subs->maxframesize = bytes_to_frames(runtime, subs->maxpacksize);
 	subs->curframesize = bytes_to_frames(runtime, subs->curpacksize);
-
-	/* deactivate urbs to be sure */
-	deactivate_urbs(subs, 0, 0);

 	return 0;
 }




-------------------------------------------------------
This SF.net email is sponsored by: SF.net Giveback Program.
Does SourceForge.net help you be more productive?  Does it
help you create better code?  SHARE THE LOVE, and help us help
YOU!  Click Here: http://sourceforge.net/donate/

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH] usbaudio fixes
  2003-11-24  7:46 [PATCH] usbaudio fixes Clemens Ladisch
@ 2003-11-24 11:27 ` Takashi Iwai
  2003-11-24 12:10   ` Clemens Ladisch
  2003-11-24 11:37 ` Takashi Iwai
  1 sibling, 1 reply; 11+ messages in thread
From: Takashi Iwai @ 2003-11-24 11:27 UTC (permalink / raw)
  To: Clemens Ladisch; +Cc: alsa-devel

At Mon, 24 Nov 2003 08:46:08 +0100 (MET),
Clemens Ladisch wrote:
> 
> 
> - don't clear active_mask bits until it's clear that the URB is _not_
>   resubmitted, to prevent a race with unlinking
> - initialize active_mask and unlink_mask each time before URBs are
>   started

we still need to check here whether the urbs are really free, since
a path like trigger stop -> prepare -> trigger_start is possible. 
in this case, the operation can be done quickly enough before urbs are
really unlinked.

the question is then where we can do a long wait.  perpare would be a
better place than trigger, but unfortunately, prepare callback is also
regarded as atomic because of linked streams.

the patch looks nice, btw.  i already have a similar version on my
tree for testing, but wasn't applied because of the reason above.
i'll apply your patch now to cvs, and let's solve the prepare problem
later.


Takashi


-------------------------------------------------------
This SF.net email is sponsored by: SF.net Giveback Program.
Does SourceForge.net help you be more productive?  Does it
help you create better code?  SHARE THE LOVE, and help us help
YOU!  Click Here: http://sourceforge.net/donate/

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH] usbaudio fixes
  2003-11-24  7:46 [PATCH] usbaudio fixes Clemens Ladisch
  2003-11-24 11:27 ` Takashi Iwai
@ 2003-11-24 11:37 ` Takashi Iwai
  1 sibling, 0 replies; 11+ messages in thread
From: Takashi Iwai @ 2003-11-24 11:37 UTC (permalink / raw)
  To: Clemens Ladisch; +Cc: alsa-devel

At Mon, 24 Nov 2003 08:46:08 +0100 (MET),
Clemens Ladisch wrote:
> 
> 
> - don't clear active_mask bits until it's clear that the URB is _not_
>   resubmitted, to prevent a race with unlinking
> - initialize active_mask and unlink_mask each time before URBs are
>   started

we still need to check here whether the urbs are really free, since
a path like trigger stop -> prepare -> trigger_start is possible. 
in this case, the operation can be done quickly enough before urbs are
really unlinked.

the question is then where we can do a long wait.  perpare would be a
better place than trigger, but unfortunately, prepare callback is also
regarded as atomic because of linked streams.

the patch looks nice, btw.  i already have a similar version on my
tree for testing, but wasn't applied because of the reason above.
i'll apply your patch now to cvs, and let's solve the prepare problem
later.


Takashi


-------------------------------------------------------
This SF.net email is sponsored by: SF.net Giveback Program.
Does SourceForge.net help you be more productive?  Does it
help you create better code?  SHARE THE LOVE, and help us help
YOU!  Click Here: http://sourceforge.net/donate/

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH] usbaudio fixes
  2003-11-24 11:27 ` Takashi Iwai
@ 2003-11-24 12:10   ` Clemens Ladisch
  2003-11-24 12:36     ` Takashi Iwai
  0 siblings, 1 reply; 11+ messages in thread
From: Clemens Ladisch @ 2003-11-24 12:10 UTC (permalink / raw)
  To: Takashi Iwai; +Cc: alsa-devel

Takashi Iwai wrote:

> Clemens Ladisch wrote:
> >
> > - initialize active_mask and unlink_mask each time before URBs are
> >   started
>
> we still need to check here whether the urbs are really free, since
> a path like trigger stop -> prepare -> trigger_start is possible.
> in this case, the operation can be done quickly enough before urbs are
> really unlinked.
>
> the question is then where we can do a long wait.  perpare would be a
> better place than trigger, but unfortunately, prepare callback is also
> regarded as atomic because of linked streams.

If we cannot sleep until the URBs are completely unlinked, we have to
1) busy-wait until the URBs are inactive (*ouch!*), or
2) let trigger_start fail with "device not yet ready", or
3) allocate a new set of URBs, and put the old ones in some list to be
   freed later.

(1) would be really evil; (2) a quick hack; (3) would be most useful,
but it's anything but elegant.


Regards,
Clemens




-------------------------------------------------------
This SF.net email is sponsored by: SF.net Giveback Program.
Does SourceForge.net help you be more productive?  Does it
help you create better code?  SHARE THE LOVE, and help us help
YOU!  Click Here: http://sourceforge.net/donate/

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH] usbaudio fixes
  2003-11-24 12:10   ` Clemens Ladisch
@ 2003-11-24 12:36     ` Takashi Iwai
  2003-11-24 12:51       ` Takashi Iwai
  0 siblings, 1 reply; 11+ messages in thread
From: Takashi Iwai @ 2003-11-24 12:36 UTC (permalink / raw)
  To: Clemens Ladisch; +Cc: alsa-devel

At Mon, 24 Nov 2003 13:10:55 +0100 (MET),
Clemens Ladisch wrote:
> 
> Takashi Iwai wrote:
> 
> > Clemens Ladisch wrote:
> > >
> > > - initialize active_mask and unlink_mask each time before URBs are
> > >   started
> >
> > we still need to check here whether the urbs are really free, since
> > a path like trigger stop -> prepare -> trigger_start is possible.
> > in this case, the operation can be done quickly enough before urbs are
> > really unlinked.
> >
> > the question is then where we can do a long wait.  perpare would be a
> > better place than trigger, but unfortunately, prepare callback is also
> > regarded as atomic because of linked streams.
> 
> If we cannot sleep until the URBs are completely unlinked, we have to
> 1) busy-wait until the URBs are inactive (*ouch!*), or
> 2) let trigger_start fail with "device not yet ready", or
> 3) allocate a new set of URBs, and put the old ones in some list to be
>    freed later.
> 
> (1) would be really evil; (2) a quick hack; (3) would be most useful,
> but it's anything but elegant.

(1) is difficult because the callback is performed with irq disabled.
thus complete callback will be never called inside the prepare or
trigger callback.

(2) will bring many complains, i guess :)

(3) looks like a good idea as a workaround.


meanwhile, i'm trying to implement:

(4) allow prepare callback to sleep with a special flag.

this will be useful for other drivers, too, such as vx and korg1212
drivers which require the handshaking.
but what i'm doing is still a hack, and will be a fundamental rewrite
later.


Takashi


-------------------------------------------------------
This SF.net email is sponsored by: SF.net Giveback Program.
Does SourceForge.net help you be more productive?  Does it
help you create better code?  SHARE THE LOVE, and help us help
YOU!  Click Here: http://sourceforge.net/donate/

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH] usbaudio fixes
  2003-11-24 12:36     ` Takashi Iwai
@ 2003-11-24 12:51       ` Takashi Iwai
  2003-11-24 17:59         ` Takashi Iwai
  0 siblings, 1 reply; 11+ messages in thread
From: Takashi Iwai @ 2003-11-24 12:51 UTC (permalink / raw)
  To: Clemens Ladisch; +Cc: alsa-devel

[-- Attachment #1: Type: text/plain, Size: 455 bytes --]

At Mon, 24 Nov 2003 13:36:42 +0100,
I wrote:
> 
> meanwhile, i'm trying to implement:
> 
> (4) allow prepare callback to sleep with a special flag.
> 
> this will be useful for other drivers, too, such as vx and korg1212
> drivers which require the handshaking.
> but what i'm doing is still a hack, and will be a fundamental rewrite
> later.

the attached is a quick-hacked version.
it's untested for linked streams.  we need a test case here.


Takashi

[-- Attachment #2: nonatomic-prepare.dif --]
[-- Type: application/octet-stream, Size: 6888 bytes --]

Index: alsa-kernel/core/pcm_native.c
===================================================================
RCS file: /suse/tiwai/cvs/alsa/alsa-kernel/core/pcm_native.c,v
retrieving revision 1.63
diff -u -r1.63 pcm_native.c
--- alsa-kernel/core/pcm_native.c	21 Oct 2003 09:49:34 -0000	1.63
+++ alsa-kernel/core/pcm_native.c	24 Nov 2003 12:42:32 -0000
@@ -620,7 +620,7 @@
  */
 static int snd_pcm_action_group(struct action_ops *ops,
 				snd_pcm_substream_t *substream,
-				int state)
+				int state, int atomic_only)
 {
 	struct list_head *pos;
 	snd_pcm_substream_t *s = NULL;
@@ -628,6 +628,8 @@
 
 	snd_pcm_group_for_each(pos, substream) {
 		s = snd_pcm_group_substream_entry(pos);
+		if (atomic_only && (s->pcm->info_flags & SNDRV_PCM_INFO_NONATOMIC_OPS))
+			continue;
 		if (s != substream)
 			spin_lock(&s->self_group.lock);
 		res = ops->pre_action(s, state);
@@ -637,6 +639,8 @@
 	if (res >= 0) {
 		snd_pcm_group_for_each(pos, substream) {
 			s = snd_pcm_group_substream_entry(pos);
+			if (atomic_only && (s->pcm->info_flags & SNDRV_PCM_INFO_NONATOMIC_OPS))
+				continue;
 			err = ops->do_action(s, state);
 			if (err < 0) {
 				if (res == 0)
@@ -652,7 +656,9 @@
 		/* unlock all streams */
 		snd_pcm_group_for_each(pos, substream) {
 			s1 = snd_pcm_group_substream_entry(pos);
-			if (s1 != substream)
+			if (atomic_only && (s1->pcm->info_flags & SNDRV_PCM_INFO_NONATOMIC_OPS))
+				;
+			else if (s1 != substream)
 				spin_unlock(&s1->self_group.lock);
 			if (s1 == s)	/* end */
 				break;
@@ -682,6 +688,8 @@
 
 /*
  *  Note: call with stream lock
+ *
+ * NB2: this won't handle the non-atomic callbacks
  */
 static int snd_pcm_action(struct action_ops *ops,
 			  snd_pcm_substream_t *substream,
@@ -695,7 +703,7 @@
 			spin_lock(&substream->group->lock);
 			spin_lock(&substream->self_group.lock);
 		}
-		res = snd_pcm_action_group(ops, substream, state);
+		res = snd_pcm_action_group(ops, substream, state, 0);
 		spin_unlock(&substream->group->lock);
 	} else {
 		res = snd_pcm_action_single(ops, substream, state);
@@ -705,10 +713,14 @@
 
 /*
  *  Note: don't use any locks before
+ *
+ * NB2: this can handle the non-atomic callbacks if allow_nonatomic = 1
+ *      when the pcm->info_flags has NONATOMIC_OPS bit, it's handled
+ *      ouside the lock to allow sleep in the callback.
  */
 static int snd_pcm_action_lock_irq(struct action_ops *ops,
 				   snd_pcm_substream_t *substream,
-				   int state)
+				   int state, int allow_nonatomic)
 {
 	int res;
 
@@ -716,10 +728,42 @@
 	if (snd_pcm_stream_linked(substream)) {
 		spin_lock(&substream->group->lock);
 		spin_lock(&substream->self_group.lock);
-		res = snd_pcm_action_group(ops, substream, state);
+		res = snd_pcm_action_group(ops, substream, state, allow_nonatomic);
 		spin_unlock(&substream->self_group.lock);
 		spin_unlock(&substream->group->lock);
+		if (res >= 0 && allow_nonatomic) {
+			/* now process the non-atomic substreams separately
+			 * outside the lock
+			 */
+#define MAX_LINKED_STREAMS	16	/* FIXME: should be variable */
+
+			struct list_head *pos;
+			int i, num_s = 0;
+			snd_pcm_substream_t *s;
+			snd_pcm_substream_t *subs[MAX_LINKED_STREAMS];
+			snd_pcm_group_for_each(pos, substream) {
+				if (num_s >= MAX_LINKED_STREAMS) {
+					res = -ENOMEM;
+					num_s = 0; /* don't proceed */
+					break;
+				}
+				s = snd_pcm_group_substream_entry(pos);
+				if (s->pcm->info_flags & SNDRV_PCM_INFO_NONATOMIC_OPS)
+					subs[num_s++] = s;
+			}
+			if (num_s > 0) {
+				read_unlock_irq(&snd_pcm_link_rwlock);
+				for (i = 0; i < num_s && res >= 0; i++)
+					res = snd_pcm_action_single(ops, subs[i], state);
+				return res;
+			}
+		}
 	} else {
+		if (allow_nonatomic &&
+		    (substream->pcm->info_flags & SNDRV_PCM_INFO_NONATOMIC_OPS)) {
+			read_unlock_irq(&snd_pcm_link_rwlock);
+			return snd_pcm_action_single(ops, substream, state);
+		}
 		spin_lock(&substream->self_group.lock);
 		res = snd_pcm_action_single(ops, substream, state);
 		spin_unlock(&substream->self_group.lock);
@@ -993,7 +1037,7 @@
 
 	snd_power_lock(card);
 	if ((res = snd_power_wait(card, SNDRV_CTL_POWER_D0, substream->ffile)) >= 0)
-		return snd_pcm_action_lock_irq(&snd_pcm_action_resume, substream, 0);
+		return snd_pcm_action_lock_irq(&snd_pcm_action_resume, substream, 0, 0);
 	snd_power_unlock(card);
 	return res;
 }
@@ -1083,7 +1127,7 @@
 
 static int snd_pcm_reset(snd_pcm_substream_t *substream)
 {
-	return snd_pcm_action_lock_irq(&snd_pcm_action_reset, substream, 0);
+	return snd_pcm_action_lock_irq(&snd_pcm_action_reset, substream, 0, 0);
 }
 
 static int snd_pcm_pre_prepare(snd_pcm_substream_t * substream, int state)
@@ -1131,7 +1175,7 @@
 
 	snd_power_lock(card);
 	if ((res = snd_power_wait(card, SNDRV_CTL_POWER_D0, substream->ffile)) >= 0)
-		res = snd_pcm_action_lock_irq(&snd_pcm_action_prepare, substream, 0);
+		res = snd_pcm_action_lock_irq(&snd_pcm_action_prepare, substream, 0, 1); /* allow sleep if specified */
 	snd_power_unlock(card);
 	return res;
 }
Index: alsa-kernel/include/asound.h
===================================================================
RCS file: /suse/tiwai/cvs/alsa/alsa-kernel/include/asound.h,v
retrieving revision 1.24
diff -u -r1.24 asound.h
--- alsa-kernel/include/asound.h	22 Oct 2003 09:41:06 -0000	1.24
+++ alsa-kernel/include/asound.h	24 Nov 2003 12:23:47 -0000
@@ -272,6 +272,7 @@
 #define SNDRV_PCM_INFO_HALF_DUPLEX	0x00100000	/* only half duplex */
 #define SNDRV_PCM_INFO_JOINT_DUPLEX	0x00200000	/* playback and capture stream are somewhat correlated */
 #define SNDRV_PCM_INFO_SYNC_START	0x00400000	/* pcm support some kind of sync go */
+#define SNDRV_PCM_INFO_NONATOMIC_OPS	0x00800000	/* non-atomic prepare callback */
 
 enum sndrv_pcm_state {
 	SNDRV_PCM_STATE_OPEN = 0,	/* stream is open */
Index: alsa-kernel/usb/usbaudio.c
===================================================================
RCS file: /suse/tiwai/cvs/alsa/alsa-kernel/usb/usbaudio.c,v
retrieving revision 1.77
diff -u -r1.77 usbaudio.c
--- alsa-kernel/usb/usbaudio.c	24 Nov 2003 11:51:02 -0000	1.77
+++ alsa-kernel/usb/usbaudio.c	24 Nov 2003 12:44:47 -0000
@@ -804,8 +804,7 @@
 	int i;
 
 	/* stop urbs (to be sure) */
-	deactivate_urbs(subs, force, 1);
-	if (async_unlink)
+	if (deactivate_urbs(subs, force, 1) > 0)
 		wait_clear_urbs(subs);
 
 	for (i = 0; i < MAX_URBS; i++)
@@ -1277,6 +1276,10 @@
 	subs->maxframesize = bytes_to_frames(runtime, subs->maxpacksize);
 	subs->curframesize = bytes_to_frames(runtime, subs->curpacksize);
 
+	/* clear urbs (to be sure) */
+	if (deactivate_urbs(subs, 0, 1) > 0)
+		wait_clear_urbs(subs);
+
 	return 0;
 }
 
@@ -2002,7 +2005,7 @@
 	as->pcm = pcm;
 	pcm->private_data = as;
 	pcm->private_free = snd_usb_audio_pcm_free;
-	pcm->info_flags = 0;
+	pcm->info_flags = SNDRV_PCM_INFO_NONATOMIC_OPS;
 	if (chip->pcm_devs > 0)
 		sprintf(pcm->name, "USB Audio #%d", chip->pcm_devs);
 	else

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH] usbaudio fixes
  2003-11-24 12:51       ` Takashi Iwai
@ 2003-11-24 17:59         ` Takashi Iwai
  2003-11-25 11:51           ` Jaroslav Kysela
  0 siblings, 1 reply; 11+ messages in thread
From: Takashi Iwai @ 2003-11-24 17:59 UTC (permalink / raw)
  To: Clemens Ladisch; +Cc: alsa-devel, perex

[-- Attachment #1: Type: text/plain, Size: 695 bytes --]

At Mon, 24 Nov 2003 13:51:50 +0100,
I wrote:
> 
> At Mon, 24 Nov 2003 13:36:42 +0100,
> I wrote:
> > 
> > meanwhile, i'm trying to implement:
> > 
> > (4) allow prepare callback to sleep with a special flag.
> > 
> > this will be useful for other drivers, too, such as vx and korg1212
> > drivers which require the handshaking.
> > but what i'm doing is still a hack, and will be a fundamental rewrite
> > later.
> 
> the attached is a quick-hacked version.
> it's untested for linked streams.  we need a test case here.

ok, here is the final version.  this one seems working fine.

Jaroslav, could you check whether it's ok?
the changes in pcm_native.c shouldn't affect other cards.


Takashi

[-- Attachment #2: Type: text/plain, Size: 11056 bytes --]

Index: alsa-kernel/core/pcm_native.c
===================================================================
RCS file: /suse/tiwai/cvs/alsa/alsa-kernel/core/pcm_native.c,v
retrieving revision 1.63
diff -u -r1.63 pcm_native.c
--- alsa-kernel/core/pcm_native.c	21 Oct 2003 09:49:34 -0000	1.63
+++ alsa-kernel/core/pcm_native.c	24 Nov 2003 17:46:04 -0000
@@ -620,7 +620,7 @@
  */
 static int snd_pcm_action_group(struct action_ops *ops,
 				snd_pcm_substream_t *substream,
-				int state)
+				int state, int atomic_only)
 {
 	struct list_head *pos;
 	snd_pcm_substream_t *s = NULL;
@@ -628,6 +628,8 @@
 
 	snd_pcm_group_for_each(pos, substream) {
 		s = snd_pcm_group_substream_entry(pos);
+		if (atomic_only && (s->pcm->info_flags & SNDRV_PCM_INFO_NONATOMIC_OPS))
+			continue;
 		if (s != substream)
 			spin_lock(&s->self_group.lock);
 		res = ops->pre_action(s, state);
@@ -637,6 +639,8 @@
 	if (res >= 0) {
 		snd_pcm_group_for_each(pos, substream) {
 			s = snd_pcm_group_substream_entry(pos);
+			if (atomic_only && (s->pcm->info_flags & SNDRV_PCM_INFO_NONATOMIC_OPS))
+				continue;
 			err = ops->do_action(s, state);
 			if (err < 0) {
 				if (res == 0)
@@ -652,7 +656,9 @@
 		/* unlock all streams */
 		snd_pcm_group_for_each(pos, substream) {
 			s1 = snd_pcm_group_substream_entry(pos);
-			if (s1 != substream)
+			if (atomic_only && (s1->pcm->info_flags & SNDRV_PCM_INFO_NONATOMIC_OPS))
+				;
+			else if (s1 != substream)
 				spin_unlock(&s1->self_group.lock);
 			if (s1 == s)	/* end */
 				break;
@@ -682,6 +688,8 @@
 
 /*
  *  Note: call with stream lock
+ *
+ * NB2: this won't handle the non-atomic callbacks
  */
 static int snd_pcm_action(struct action_ops *ops,
 			  snd_pcm_substream_t *substream,
@@ -695,7 +703,7 @@
 			spin_lock(&substream->group->lock);
 			spin_lock(&substream->self_group.lock);
 		}
-		res = snd_pcm_action_group(ops, substream, state);
+		res = snd_pcm_action_group(ops, substream, state, 0);
 		spin_unlock(&substream->group->lock);
 	} else {
 		res = snd_pcm_action_single(ops, substream, state);
@@ -705,10 +713,14 @@
 
 /*
  *  Note: don't use any locks before
+ *
+ * NB2: this can handle the non-atomic callbacks if allow_nonatomic = 1
+ *      when the pcm->info_flags has NONATOMIC_OPS bit, it's handled
+ *      ouside the lock to allow sleep in the callback.
  */
 static int snd_pcm_action_lock_irq(struct action_ops *ops,
 				   snd_pcm_substream_t *substream,
-				   int state)
+				   int state, int allow_nonatomic)
 {
 	int res;
 
@@ -716,10 +728,43 @@
 	if (snd_pcm_stream_linked(substream)) {
 		spin_lock(&substream->group->lock);
 		spin_lock(&substream->self_group.lock);
-		res = snd_pcm_action_group(ops, substream, state);
+		res = snd_pcm_action_group(ops, substream, state, allow_nonatomic);
 		spin_unlock(&substream->self_group.lock);
 		spin_unlock(&substream->group->lock);
+		if (res >= 0 && allow_nonatomic) {
+			/* now process the non-atomic substreams separately
+			 * outside the lock
+			 */
+#define MAX_LINKED_STREAMS	16	/* FIXME: should be variable */
+
+			struct list_head *pos;
+			int i, num_s = 0;
+			snd_pcm_substream_t *s;
+			snd_pcm_substream_t *subs[MAX_LINKED_STREAMS];
+			snd_pcm_group_for_each(pos, substream) {
+				if (num_s >= MAX_LINKED_STREAMS) {
+					res = -ENOMEM;
+					num_s = 0; /* don't proceed */
+					break;
+				}
+				s = snd_pcm_group_substream_entry(pos);
+				if (s->pcm->info_flags & SNDRV_PCM_INFO_NONATOMIC_OPS)
+					subs[num_s++] = s;
+			}
+			if (num_s > 0) {
+				read_unlock_irq(&snd_pcm_link_rwlock);
+				for (i = 0; i < num_s && res >= 0; i++)
+					res = snd_pcm_action_single(ops, subs[i], state);
+				return res;
+			}
+		}
 	} else {
+		if (allow_nonatomic &&
+		    (substream->pcm->info_flags & SNDRV_PCM_INFO_NONATOMIC_OPS)) {
+			read_unlock_irq(&snd_pcm_link_rwlock);
+			/* process outside the lock */
+			return snd_pcm_action_single(ops, substream, state);
+		}
 		spin_lock(&substream->self_group.lock);
 		res = snd_pcm_action_single(ops, substream, state);
 		spin_unlock(&substream->self_group.lock);
@@ -993,7 +1038,7 @@
 
 	snd_power_lock(card);
 	if ((res = snd_power_wait(card, SNDRV_CTL_POWER_D0, substream->ffile)) >= 0)
-		return snd_pcm_action_lock_irq(&snd_pcm_action_resume, substream, 0);
+		return snd_pcm_action_lock_irq(&snd_pcm_action_resume, substream, 0, 0);
 	snd_power_unlock(card);
 	return res;
 }
@@ -1083,7 +1128,7 @@
 
 static int snd_pcm_reset(snd_pcm_substream_t *substream)
 {
-	return snd_pcm_action_lock_irq(&snd_pcm_action_reset, substream, 0);
+	return snd_pcm_action_lock_irq(&snd_pcm_action_reset, substream, 0, 0);
 }
 
 static int snd_pcm_pre_prepare(snd_pcm_substream_t * substream, int state)
@@ -1131,7 +1176,7 @@
 
 	snd_power_lock(card);
 	if ((res = snd_power_wait(card, SNDRV_CTL_POWER_D0, substream->ffile)) >= 0)
-		res = snd_pcm_action_lock_irq(&snd_pcm_action_prepare, substream, 0);
+		res = snd_pcm_action_lock_irq(&snd_pcm_action_prepare, substream, 0, 1); /* allow sleep if specified */
 	snd_power_unlock(card);
 	return res;
 }
@@ -2330,7 +2375,7 @@
 	case SNDRV_PCM_IOCTL_RESET:
 		return snd_pcm_reset(substream);
 	case SNDRV_PCM_IOCTL_START:
-		return snd_pcm_action(&snd_pcm_action_start, substream, 0);
+		return snd_pcm_action_lock_irq(&snd_pcm_action_start, substream, 0, 0);
 	case SNDRV_PCM_IOCTL_LINK:
 		return snd_pcm_link(substream, (long) arg);
 	case SNDRV_PCM_IOCTL_UNLINK:
Index: alsa-kernel/include/asound.h
===================================================================
RCS file: /suse/tiwai/cvs/alsa/alsa-kernel/include/asound.h,v
retrieving revision 1.24
diff -u -r1.24 asound.h
--- alsa-kernel/include/asound.h	22 Oct 2003 09:41:06 -0000	1.24
+++ alsa-kernel/include/asound.h	24 Nov 2003 12:23:47 -0000
@@ -272,6 +272,7 @@
 #define SNDRV_PCM_INFO_HALF_DUPLEX	0x00100000	/* only half duplex */
 #define SNDRV_PCM_INFO_JOINT_DUPLEX	0x00200000	/* playback and capture stream are somewhat correlated */
 #define SNDRV_PCM_INFO_SYNC_START	0x00400000	/* pcm support some kind of sync go */
+#define SNDRV_PCM_INFO_NONATOMIC_OPS	0x00800000	/* non-atomic prepare callback */
 
 enum sndrv_pcm_state {
 	SNDRV_PCM_STATE_OPEN = 0,	/* stream is open */
Index: alsa-kernel/usb/usbaudio.c
===================================================================
RCS file: /suse/tiwai/cvs/alsa/alsa-kernel/usb/usbaudio.c,v
retrieving revision 1.77
diff -u -r1.77 usbaudio.c
--- alsa-kernel/usb/usbaudio.c	24 Nov 2003 11:51:02 -0000	1.77
+++ alsa-kernel/usb/usbaudio.c	24 Nov 2003 17:49:59 -0000
@@ -28,9 +28,8 @@
  *  NOTES:
  *
  *   - async unlink should be used for avoiding the sleep inside lock.
- *     however, it causes oops by unknown reason on usb-uhci, and
- *     disabled as default.  the feature is enabled by async_unlink=1
- *     option (especially when preempt is used).
+ *     2.4.22 usb-uhci seems buggy for async unlinking and results in
+ *     oops.  in such a cse, pass async_unlink=0 option.
  *   - the linked URBs would be preferred but not used so far because of
  *     the instability of unlinking.
  *   - type II is not supported properly.  there is no device which supports
@@ -69,7 +68,7 @@
 static int vid[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = -1 }; /* Vendor ID for this card */
 static int pid[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = -1 }; /* Product ID for this card */
 static int nrpacks = 4;		/* max. number of packets per urb */
-static int async_unlink = 0;
+static int async_unlink = 1;
 
 MODULE_PARM(index, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
 MODULE_PARM_DESC(index, "Index value for the USB audio adapter.");
@@ -804,8 +803,7 @@
 	int i;
 
 	/* stop urbs (to be sure) */
-	deactivate_urbs(subs, force, 1);
-	if (async_unlink)
+	if (deactivate_urbs(subs, force, 1) > 0)
 		wait_clear_urbs(subs);
 
 	for (i = 0; i < MAX_URBS; i++)
@@ -834,12 +832,6 @@
 	subs->freqmax = subs->freqn + (subs->freqn >> 2); /* max. allowed frequency */
 	subs->phase = 0;
 
-	/* reset the pointer */
-	subs->hwptr = 0;
-	subs->hwptr_done = 0;
-	subs->transfer_sched = 0;
-	subs->transfer_done = 0;
-
 	/* calculate the max. size of packet */
 	maxsize = ((subs->freqmax + 0x3fff) * (frame_bits >> 3)) >> 14;
 	if (subs->maxpacksize && maxsize > subs->maxpacksize) {
@@ -1277,6 +1269,17 @@
 	subs->maxframesize = bytes_to_frames(runtime, subs->maxpacksize);
 	subs->curframesize = bytes_to_frames(runtime, subs->curpacksize);
 
+	/* reset the pointer */
+	subs->hwptr = 0;
+	subs->hwptr_done = 0;
+	subs->transfer_sched = 0;
+	subs->transfer_done = 0;
+	subs->phase = 0;
+
+	/* clear urbs (to be sure) */
+	if (deactivate_urbs(subs, 0, 0) > 0)
+		wait_clear_urbs(subs);
+
 	return 0;
 }
 
@@ -2002,7 +2005,7 @@
 	as->pcm = pcm;
 	pcm->private_data = as;
 	pcm->private_free = snd_usb_audio_pcm_free;
-	pcm->info_flags = 0;
+	pcm->info_flags = SNDRV_PCM_INFO_NONATOMIC_OPS;
 	if (chip->pcm_devs > 0)
 		sprintf(pcm->name, "USB Audio #%d", chip->pcm_devs);
 	else
Index: alsa-driver/usb/usbaudio.patch
===================================================================
RCS file: /suse/tiwai/cvs/alsa/alsa-driver/usb/usbaudio.patch,v
retrieving revision 1.1
diff -u -r1.1 usbaudio.patch
--- alsa-driver/usb/usbaudio.patch	2 Jun 2003 10:07:21 -0000	1.1
+++ alsa-driver/usb/usbaudio.patch	24 Nov 2003 17:51:55 -0000
@@ -1,11 +1,25 @@
---- usbaudio.c	2003-06-01 20:32:24.000000000 +0200
-+++ usbaudio.c.old	2003-06-01 20:32:42.000000000 +0200
+--- usbaudio.c	2003-11-24 18:49:59.000000000 +0100
++++ usbaudio.c	2003-11-24 18:51:33.000000000 +0100
 @@ -1,3 +1,4 @@
 +#include "usbaudio.inc"
  /*
   *   (Tentative) USB Audio Driver for ALSA
   *
-@@ -1656,9 +1657,11 @@
+@@ -68,7 +69,12 @@
+ static int vid[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = -1 }; /* Vendor ID for this card */
+ static int pid[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = -1 }; /* Product ID for this card */
+ static int nrpacks = 4;		/* max. number of packets per urb */
+-static int async_unlink = 1;
++static int async_unlink =
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
++1;
++#else
++0; /* disabled as default for buggy async-unlink handling */
++#endif
+ 
+ MODULE_PARM(index, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
+ MODULE_PARM_DESC(index, "Index value for the USB audio adapter.");
+@@ -1761,9 +1767,11 @@
   * entry point for linux usb interface
   */
  
@@ -17,7 +31,7 @@
  
  static struct usb_device_id usb_audio_ids [] = {
  #include "usbquirks.h"
-@@ -1671,10 +1674,15 @@
+@@ -1776,10 +1784,15 @@
  MODULE_DEVICE_TABLE (usb, usb_audio_ids);
  
  static struct usb_driver usb_audio_driver = {
@@ -33,7 +47,7 @@
  	.id_table =	usb_audio_ids,
  };
  
-@@ -2744,6 +2752,7 @@
+@@ -2918,6 +2931,7 @@
  	}
  }
  
@@ -41,7 +55,7 @@
  /*
   * new 2.5 USB kernel API
   */
-@@ -2764,6 +2773,8 @@
+@@ -2938,6 +2952,8 @@
  	snd_usb_audio_disconnect(interface_to_usbdev(intf),
  				 dev_get_drvdata(&intf->dev));
  }
@@ -50,7 +64,7 @@
  
  
  static int __init snd_usb_audio_init(void)
-@@ -2803,3 +2814,5 @@
+@@ -2981,3 +2997,5 @@
  __setup("snd-usb-audio=", snd_usb_audio_module_setup);
  
  #endif /* !MODULE */

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH] usbaudio fixes
  2003-11-24 17:59         ` Takashi Iwai
@ 2003-11-25 11:51           ` Jaroslav Kysela
  2003-11-25 11:56             ` Takashi Iwai
  0 siblings, 1 reply; 11+ messages in thread
From: Jaroslav Kysela @ 2003-11-25 11:51 UTC (permalink / raw)
  To: Takashi Iwai; +Cc: Clemens Ladisch, alsa-devel

On Mon, 24 Nov 2003, Takashi Iwai wrote:

> At Mon, 24 Nov 2003 13:51:50 +0100,
> I wrote:
> > 
> > At Mon, 24 Nov 2003 13:36:42 +0100,
> > I wrote:
> > > 
> > > meanwhile, i'm trying to implement:
> > > 
> > > (4) allow prepare callback to sleep with a special flag.
> > > 
> > > this will be useful for other drivers, too, such as vx and korg1212
> > > drivers which require the handshaking.
> > > but what i'm doing is still a hack, and will be a fundamental rewrite
> > > later.
> > 
> > the attached is a quick-hacked version.
> > it's untested for linked streams.  we need a test case here.
> 
> ok, here is the final version.  this one seems working fine.
> 
> Jaroslav, could you check whether it's ok?
> the changes in pcm_native.c shouldn't affect other cards.

It's ok, but it still looks like an ugly hack, but I don't see any other 
way to solve this problem so you can apply this code to CVS.

						Jaroslav

-----
Jaroslav Kysela <perex@suse.cz>
Linux Kernel Sound Maintainer
ALSA Project, SuSE Labs


-------------------------------------------------------
This SF.net email is sponsored by: SF.net Giveback Program.
Does SourceForge.net help you be more productive?  Does it
help you create better code?  SHARE THE LOVE, and help us help
YOU!  Click Here: http://sourceforge.net/donate/

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH] usbaudio fixes
  2003-11-25 11:51           ` Jaroslav Kysela
@ 2003-11-25 11:56             ` Takashi Iwai
  0 siblings, 0 replies; 11+ messages in thread
From: Takashi Iwai @ 2003-11-25 11:56 UTC (permalink / raw)
  To: Jaroslav Kysela; +Cc: Clemens Ladisch, alsa-devel

At Tue, 25 Nov 2003 12:51:11 +0100 (CET),
Jaroslav wrote:
> 
> On Mon, 24 Nov 2003, Takashi Iwai wrote:
> 
> > At Mon, 24 Nov 2003 13:51:50 +0100,
> > I wrote:
> > > 
> > > At Mon, 24 Nov 2003 13:36:42 +0100,
> > > I wrote:
> > > > 
> > > > meanwhile, i'm trying to implement:
> > > > 
> > > > (4) allow prepare callback to sleep with a special flag.
> > > > 
> > > > this will be useful for other drivers, too, such as vx and korg1212
> > > > drivers which require the handshaking.
> > > > but what i'm doing is still a hack, and will be a fundamental rewrite
> > > > later.
> > > 
> > > the attached is a quick-hacked version.
> > > it's untested for linked streams.  we need a test case here.
> > 
> > ok, here is the final version.  this one seems working fine.
> > 
> > Jaroslav, could you check whether it's ok?
> > the changes in pcm_native.c shouldn't affect other cards.
> 
> It's ok, but it still looks like an ugly hack, but I don't see any other 
> way to solve this problem so you can apply this code to CVS.

yeah, agreed, it's a quick'n'dirty hack :)

the better way would be to move all prepare callback in every driver
as non-atomic, and call it inside a mutex.  linking/unlinking streams
will need to issue both a mutex and a spinlock for prepare and trigger
callbacks.
but, for this, we have to audit all drivers.  let's beautify later.

ok, i'll commit the changes now.


thanks,

Takashi


-------------------------------------------------------
This SF.net email is sponsored by: SF.net Giveback Program.
Does SourceForge.net help you be more productive?  Does it
help you create better code?  SHARE THE LOVE, and help us help
YOU!  Click Here: http://sourceforge.net/donate/

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2003-11-25 11:56 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2003-11-24  7:46 [PATCH] usbaudio fixes Clemens Ladisch
2003-11-24 11:27 ` Takashi Iwai
2003-11-24 12:10   ` Clemens Ladisch
2003-11-24 12:36     ` Takashi Iwai
2003-11-24 12:51       ` Takashi Iwai
2003-11-24 17:59         ` Takashi Iwai
2003-11-25 11:51           ` Jaroslav Kysela
2003-11-25 11:56             ` Takashi Iwai
2003-11-24 11:37 ` Takashi Iwai
  -- strict thread matches above, loose matches on Subject: below --
2003-06-19  7:00 Clemens Ladisch
2003-06-20 18:14 ` Takashi Iwai

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.