Re: How should we handle isochronous underruns?

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Sun, Jul 21, 2013 at 11:28 PM, Alan Stern <stern@xxxxxxxxxxxxxxxxxxx> wrote:
> On Sun, 21 Jul 2013, Ming Lei wrote:
>
>> On Sun, Jul 21, 2013 at 2:00 AM, Alan Stern <stern@xxxxxxxxxxxxxxxxxxx> wrote:
>> > On Sat, 20 Jul 2013, Ming Lei wrote:
>> >
>> >> > No, we don't have to change every driver using isochronous URBs.  Many
>> >> > of them set URB_ISO_ASAP on every URB -- in fact, AFAIK snd-usb-audio
>> >> > is the only one that has been fixed not to do this.
>> >>
>> >> OK, if you are sure just snd-usb-audio and very less drivers need the change,
>> >> using the API only is correct way.
>> >
>> > I haven't checked in detail, but this seems very likely.
>>
>> For ehci example, URB_ISO_ASAP is not checked when isoc queue is
>> empty, so will cause a new schedule when underrun happens.
>
> ehci-hcd is indeed one of the drivers that will need to be updated.
> So will ohci-hcd and uhci-hcd, when they start using tasklets.
>
>> > The new call doesn't turn streaming on or off.  The driver does that
>> > by submitting URBs or not submitting them.
>> >
>> > The new call merely separates an old stream from a new one.  It tells
>> > the HCD that the old stream (if any) is finished, so that any URBs
>> > submitted in the future will belong to a new stream.  In particular, it
>> > tells the HCD that the next URB for this endpoint should be assigned to
>> > a time slot that will be visible to the hardware, instead of being
>> > assigned to the next time slot after the last packet of the previous
>> > URB (which has probably expired already).
>>
>> OK, I got it, looks usb_new_iso_stream(udev, ep) need to be called
>> before starting a new stream.
>
> Or after ending an old stream.  Either way would work.
>
>>  From view of HCD, the hcd only
>> knows a stream has been started, and doesn't know if it has been stopped.
>> And the most possible usage for hcd is that:
>>
>> if (test_and_clear_bit(ISOC_NEW_STREAM, ep->stream_flag)
>>           ; /* new stream */
>>
>> So looks hcd has to write the flag.
>
> Not exactly.  The HCD has to keep track of the next available time slot
> for the endpoint.  Some special value, like -1, will indicate that no
> stream is running yet.  So the new function will merely have to set the
> slot value to -1.

I am wondering if -1 is special enough, since in theory -1 might
be a valid time slot when HCD uses time slot ANDed with (mod - 1).

>
>> If we define the API as usb_iso_stream(udev, ep, start), hcd only
>> need to read the flag, so it should be simper to use and implement.
>
> It wouldn't be simpler for drivers.  And what happens if the HCD gets
> an URB submitted for an endpoint where the stream_flag is off?

If the API is defined as usb_iso_stream(udev, ep, start), drivers are required
to call usb_iso_stream(udev, ep, 1) before starting stream, and call
usb_iso_stream(udev, ep, 0) after stopping stream.

>
>> Also with both streaming on and off information, the HCD might improve
>> bandwidth management in the future.
>
> I doubt it very much.  The USB spec states that bandwidth for periodic
> endpoints gets allocated whenever a new altsetting is installed, and
> that is the approach the HCDs will try to take.

Looks USB spec doesn't mention part of the bandwidth allocated by
set_interface can't be freed.

Also Clemens mentioned, there might be devices which exposes non-zero
payload sizes in the default interface setting.

>
>> >> In a normal system, the URB count won't be very much(<< 1000), and if
>> >> you mean the overhead is from memory, I guess it won't cause real memory
>> >> increase per URB for slab's sake. If you mean performance loss with
>> >> set/get the single lockless/common variable, maybe we should focus on
>> >> the big HCD lock, which might be the biggest bottle of USB protocol, :-)
>> >
>> > If you're talking about the hcd_urb_list_lock, note that it could
>> > easily be made hcd-specific.  I haven't done that because the regions
>> > it protects are all very short, so there probably isn't very much
>> > contention.
>>
>> I mean the HCD private lock, and there are heavy contention
>> on the lock.
>
> I don't have any ideas how to reduce that contention.  Do you?

For ehci example, one draft idea I thought about is to split the ehci->lock
into three locks: ehci->periodic_lock which covers intr & isoc transfer, and
ehci->async_lock which covers async schedule, and ehci->lock which
manages some global thing but is held with short time.

But the idea is far more mature, and might be wrong, and only for discussion
because I haven't considered much details already.

>
>> Also I thought of one improvement on the idea of 'urb->completing':
>>
>> - define one percpu 'struct urb *' variable inside 'struct hcd' to record
>> the completing urb, so HCD can see easily if the urb is being resubmitted
>> inside its completion handler.
>
> Even on a UP system, what happens if multiple URBs get completed before
> the tasklet runs and one of them is resubmitted?

On each CPU, for one HCD, one urb->complete() won't be preempted
by any other urb->complete() either running in tasklet or hardirq handler,
so  we can record the completing urb in one HCD percpu variable before
calling urb->complete() and clear the variable after returning form
urb->complete().  Then in submit path, we can find if the URB is scheduled
in its own completion handler.

Thanks,
-- 
Ming Lei
--
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




[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux