Alsa-Devel Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: Takashi Iwai <tiwai@suse.de>
To: Clemens Ladisch <clemens@ladisch.de>
Cc: alsa-devel@lists.sourceforge.net
Subject: Re: [PATCH] usbaudio fixes
Date: Mon, 24 Nov 2003 13:51:50 +0100	[thread overview]
Message-ID: <s5hoev22al5.wl@alsa2.suse.de> (raw)
In-Reply-To: <s5hptfi2bad.wl@alsa2.suse.de>

[-- 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

  reply	other threads:[~2003-11-24 12:51 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
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 [this message]
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

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=s5hoev22al5.wl@alsa2.suse.de \
    --to=tiwai@suse.de \
    --cc=alsa-devel@lists.sourceforge.net \
    --cc=clemens@ladisch.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox