Update of /cvsroot/alsa/alsa-kernel/core
In directory sc8-pr-cvs1:/tmp/cvs-serv6169/core
Modified Files:
pcm_native.c
Log Message:
- prepare callback can sleep if a flag is given in pcm->info_flags.
- usbaudio driver uses non-atomic prepare callback for synchronization
of pending unlinked urbs.
- async_unlink option of usbaudio driver is enabled as default now.
- fixed the initialization of pseudo-dma pointers in usbaudio.
Index: pcm_native.c
===================================================================
RCS file: /cvsroot/alsa/alsa-kernel/core/pcm_native.c,v
retrieving revision 1.84
retrieving revision 1.85
diff -u -r1.84 -r1.85
--- pcm_native.c 21 Oct 2003 09:51:35 -0000 1.84
+++ pcm_native.c 25 Nov 2003 12:01:21 -0000 1.85
@@ -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:
-------------------------------------------------------
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/
_______________________________________________
Alsa-cvslog mailing list
[EMAIL PROTECTED]
https://lists.sourceforge.net/lists/listinfo/alsa-cvslog