On Wed, 24 Jul 2013, James Stone wrote: > Ok - this does seem to be a vast improvement over 3.8.x (and even, in > some ways the 3.6x series) - with the addition of Clemen's patch. > However, very low realtime latencies (which seemed to be somewhat > possible - 64 frames/period or lower - in the 3.6x series) will no > longer work properly. 128 frames/period looks fairly usable. Will > continue with bisect to see if I can discover anything else. I suspect this remaining problem is partly caused by the ALSA driver misinterpreting the parameters. For example, when you specify 64 frames/period, what you actually get is 41.3 (on average). The patch below ought to help. It is certainly not the correct solution, but try it out anyway with 64 frames/packet to see if it works. And collect a usbmon trace, so I can see whether it really does behave as intended. (The patch is meant to apply on top of the one Clemens sent earlier.) Alan Stern Index: usb-3.10/sound/usb/endpoint.c =================================================================== --- usb-3.10.orig/sound/usb/endpoint.c +++ usb-3.10/sound/usb/endpoint.c @@ -575,6 +575,7 @@ static int data_ep_set_params(struct snd struct snd_usb_endpoint *sync_ep) { unsigned int maxsize, i, urb_packs, total_packs, packs_per_ms; + unsigned int min_urbs, max_packs; int is_playback = usb_pipeout(ep->pipe); int frame_bits = snd_pcm_format_physical_width(pcm_format) * channels; @@ -608,10 +609,15 @@ static int data_ep_set_params(struct snd else ep->curpacksize = maxsize; - if (snd_usb_get_speed(ep->chip->dev) != USB_SPEED_FULL) + if (snd_usb_get_speed(ep->chip->dev) != USB_SPEED_FULL) { packs_per_ms = 8 >> ep->datainterval; - else + min_urbs = 3; + max_packs = MAX_PACKS_HS; + } else { packs_per_ms = 1; + min_urbs = 2; + max_packs = MAX_PACKS; + } if (is_playback && !snd_usb_endpoint_implicit_feedback_sink(ep)) { urb_packs = max(ep->chip->nrpacks, 1); @@ -625,42 +631,23 @@ static int data_ep_set_params(struct snd if (sync_ep && !snd_usb_endpoint_implicit_feedback_sink(ep)) urb_packs = min(urb_packs, 1U << sync_ep->syncinterval); - /* decide how many packets to be used */ - if (is_playback && !snd_usb_endpoint_implicit_feedback_sink(ep)) { - unsigned int minsize, maxpacks; - /* determine how small a packet can be */ - minsize = (ep->freqn >> (16 - ep->datainterval)) - * (frame_bits >> 3); - /* with sync from device, assume it can be 12% lower */ - if (sync_ep) - minsize -= minsize >> 3; - minsize = max(minsize, 1u); - total_packs = (period_bytes + minsize - 1) / minsize; - /* we need at least two URBs for queueing */ - if (total_packs < 2) { - total_packs = 2; - } else { - /* and we don't want too long a queue either */ - maxpacks = max(MAX_QUEUE * packs_per_ms, urb_packs * 2); - total_packs = min(total_packs, maxpacks); - } - } else { - while (urb_packs > 1 && urb_packs * maxsize >= period_bytes) - urb_packs >>= 1; - total_packs = MAX_URBS * urb_packs; - } + /* each URB must fit into one period */ + urb_packs = min(urb_packs, period_bytes / maxsize); + urb_packs = max(1u, urb_packs); - ep->nurbs = (total_packs + urb_packs - 1) / urb_packs; + total_packs = min(MAX_QUEUE * packs_per_ms, max_packs); + ep->nurbs = total_packs / urb_packs; if (ep->nurbs > MAX_URBS) { /* too much... */ ep->nurbs = MAX_URBS; - total_packs = MAX_URBS * urb_packs; - } else if (ep->nurbs < 2) { - /* too little - we need at least two packets + } else if (ep->nurbs < min_urbs) { + /* too little - we need at least min_urbs URBs * to ensure contiguous playback/capture */ - ep->nurbs = 2; + ep->nurbs = min_urbs; + urb_packs = total_packs / ep->nurbs; } + total_packs = ep->nurbs * urb_packs; /* allocate and initialize data urbs */ for (i = 0; i < ep->nurbs; i++) { -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html