Well, it seems that I'm going to have to answer my own self ... :)


The following is what I've been able to find using additional tracing
info. Also there's a fix for usbaudio.c.

Basically, it's as I said before: the usbaudio driver uses URBs
without even checking if they're in use or not. Surprisingly, it
does this with one channel, but not the other. Here's what I get
in the traces when I separated the events by channel:
Channel A (the hex data is the value of *subs):
-----------------------------------------------------------------------------------
...
Complete URB           11,242,322,467     0     48     Completing URB 3: 0xC1F6040C
Complete URB           11,242,326,465     0     48     Completing URB 4: 0xC1F6040C
Complete URB           11,242,330,493     0     48     Completing URB 0: 0xC1F6040C
Complete URB           11,242,334,460     0     48     Completing URB 1: 0xC1F6040C
Complete URB           11,242,338,640     126     48     Completing URB 2: 0xC1F6040C
Start URB              11,242,338,945     126     45     Sending URB 0: 0xC1F6040C
Start URB              11,242,339,159     126     45     Sending URB 1: 0xC1F6040C
Start URB              11,242,339,342     126     45     Sending URB 2: 0xC1F6040C
Start URB              11,242,339,495     126     45     Sending URB 3: 0xC1F6040C
Abuse URB              11,242,339,617     126     45     Abusing URB 3: 0xC1F6040C
Deactivate URB         11,242,356,553     126     50     Deactivating URB 0: 0xC1F6040C
Complete URB           11,242,357,621     0     48     Completing URB 3: 0xC1F6040C
Complete URB           11,242,357,834     0     48     Completing URB 4: 0xC1F6040C
Complete URB           11,242,358,323     0     48     Completing URB 0: 0xC1F6040C
Complete URB           11,242,358,933     0     48     Completing URB 1: 0xC1F6040C
URB Active Mask        11,242,359,787     126     57     Active Mask NOT set for 1: 
0xC1F6040C
Deactivate URB         11,242,359,970     126     50     Deactivating URB 2: 0xC1F6040C
Complete URB           11,242,360,611     0     48     Completing URB 2: 0xC1F6040C
URB Active Mask        11,242,361,008     126     57     Active Mask NOT set for 3: 
0xC1F6040C
URB Active Mask        11,242,361,100     126     57     Active Mask NOT set for 4: 
0xC1F6040C
Start URB              11,242,362,442     126     45     Sending URB 0: 0xC1F6040C
Start URB              11,242,362,656     126     45     Sending URB 1: 0xC1F6040C
Start URB              11,242,362,839     126     45     Sending URB 2: 0xC1F6040C
Start URB              11,242,362,991     126     45     Sending URB 3: 0xC1F6040C
Start URB              11,242,363,144     126     45     Sending URB 4: 0xC1F6040C
Complete URB           11,242,376,479     0     48     Completing URB 0: 0xC1F6040C
Complete URB           11,242,380,477     0     48     Completing URB 1: 0xC1F6040C
Complete URB           11,242,384,474     0     48     Completing URB 2: 0xC1F6040C
Complete URB           11,242,388,472     0     48     Completing URB 3: 0xC1F6040C
Complete URB           11,242,392,469     0     48     Completing URB 4: 0xC1F6040C
...
-----------------------------------------------------------------------------------

In this first channel, the deactivation function was never called at any
point prior to sending being initiated. Hence, a URB already in use was
reused without proper deactivation. Looking at the timestamps above, it
is clear that when sending is initiated on URB 3, this one is in its 4ms
playing period and would be interupted.

Channel B:
-----------------------------------------------------------------------------------
...
In the second channel, I had this:
Complete URB           11,242,319,446     0     48     Completing URB 4: 0xC1F6058C
Complete URB           11,242,323,474     0     48     Completing URB 0: 0xC1F6058C
Complete URB           11,242,327,472     0     48     Completing URB 1: 0xC1F6058C
Deactivate URB         11,242,330,767     126     50     Deactivating URB 0: 0xC1F6058C
Complete URB           11,242,331,500     0     48     Completing URB 2: 0xC1F6058C
Complete URB           11,242,331,713     0     48     Completing URB 0: 0xC1F6058C
Deactivate URB         11,242,331,896     126     50     Deactivating URB 1: 0xC1F6058C
Complete URB           11,242,332,537     0     48     Completing URB 1: 0xC1F6058C
URB Active Mask        11,242,332,720     126     57     Active Mask NOT set for 2: 
0xC1F6058C
Deactivate URB         11,242,332,812     126     50     Deactivating URB 3: 0xC1F6058C
Complete URB           11,242,333,514     0     48     Completing URB 3: 0xC1F6058C
Deactivate URB         11,242,333,697     126     50     Deactivating URB 4: 0xC1F6058C
Complete URB           11,242,334,643     0     48     Completing URB 4: 0xC1F6058C
Start URB              11,242,335,833     126     45     Sending URB 0: 0xC1F6058C
Start URB              11,242,336,047     126     45     Sending URB 1: 0xC1F6058C
Start URB              11,242,336,199     126     45     Sending URB 2: 0xC1F6058C
Start URB              11,242,336,382     126     45     Sending URB 3: 0xC1F6058C
Start URB              11,242,336,535     126     45     Sending URB 4: 0xC1F6058C
Complete URB           11,242,357,987     0     48     Completing URB 0: 0xC1F6058C
Complete URB           11,242,358,628     0     48     Completing URB 1: 0xC1F6058C
Complete URB           11,242,359,168     0     48     Completing URB 2: 0xC1F6058C
Complete URB           11,242,361,557     126     48     Completing URB 3: 0xC1F6058C
Complete URB           11,242,365,555     0     48     Completing URB 4: 0xC1F6058C
Complete URB           11,242,369,522     0     48     Completing URB 0: 0xC1F6058C
...
-----------------------------------------------------------------------------------

In no occurence did the second channel reuse a URB prior to deactivating it.
Hence, there are no errors that ever occur on this channel.

To make a long story short, the most important issue here is to check whether
the URB is active before using it. If it is, then it must be unlinked first.

Here's my modified start_urbs() function from usbaudio.c:
static int start_urbs(snd_usb_substream_t *subs, snd_pcm_runtime_t *runtime)
{
    unsigned int i;
    int err;

    for (i = 0; i < subs->nurbs; i++) {
        snd_assert(subs->dataurb[i].urb, return -EINVAL);
        /* Deactivate URB prior to using it. K.Y. */
        if (test_and_clear_bit(i, &subs->active_mask)) {
            set_bit(i, &subs->unlink_mask);
            usb_unlink_urb(subs->dataurb[i].urb);
        }
        if (subs->ops.prepare(subs, runtime, subs->dataurb[i].urb) < 0) {
            snd_printk(KERN_ERR "cannot prepare datapipe for urb %d\n", i);
            goto __error;
        }
    }
    if (subs->syncpipe) {
        for (i = 0; i < SYNC_URBS; i++) {
            snd_assert(subs->syncurb[i].urb, return -EINVAL);
            if (subs->ops.prepare_sync(subs, runtime, subs->syncurb[i].urb) < 0) {
                snd_printk(KERN_ERR "cannot prepare syncpipe for urb %d\n", i);
                goto __error;
            }
        }
    }

    subs->running = 1;
    for (i = 0; i < subs->nurbs; i++) {
        trace_std_formatted_event(event_start_urb, i,  (unsigned int) subs);
        if ((err = usb_submit_urb(subs->dataurb[i].urb, GFP_KERNEL)) < 0) {
            trace_std_formatted_event(event_abuse_urb, i,  (unsigned int) subs);
            snd_printk(KERN_ERR "cannot submit datapipe for urb %d, err = %d\n", i, 
err);
            goto __error;
        }
        set_bit(i, &subs->active_mask);
        clear_bit(i, &subs->unlink_mask);
    }
    if (subs->syncpipe) {
        for (i = 0; i < SYNC_URBS; i++) {
            if ((err = usb_submit_urb(subs->syncurb[i].urb, GFP_KERNEL)) < 0) {
                snd_printk(KERN_ERR "cannot submit syncpipe for urb %d, err = %d\n", 
i, err);
                goto __error;
            }
            set_bit(i + 16, &subs->active_mask);
        }
    }
    return 0;

 __error:
    // snd_pcm_stop(subs->pcm_substream, SNDRV_PCM_STATE_XRUN);
    deactivate_urbs(subs, 0);
    return -EPIPE;
}

Using this code, I haven't had any more errors at all.

In order to use this, just remove all the trace_* functions. This new
function just checks if a URB is already in use prior to using it and
clears it. Also, it clears the unlink_mask after the call to
usb_submit_urb in order for it to be "clearable" by deactivate_urbs().
Without this last clear_bit(), URBs can only be cleared once by
deactivate_urbs() and it takes a new init_substream_urbs() to set the
entire mask back to 0. I don't see how this makes any sense.

Feedback is welcome.

Karim
--
Author, Speaker, Developer, Consultant
Pushing Embedded and Real-Time Linux Systems Beyond the Limits
http://www.opersys.com || [EMAIL PROTECTED] || 514-812-4145




------------------------------------------------------- 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-devel mailing list [EMAIL PROTECTED] https://lists.sourceforge.net/lists/listinfo/alsa-devel

Reply via email to