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

Reply via email to