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
next prev parent 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 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.