Re: How should we handle isochronous underruns?

2013-07-22 Thread Ming Lei
On Sun, Jul 21, 2013 at 11:28 PM, Alan Stern st...@rowland.harvard.edu wrote:
 On Sun, 21 Jul 2013, Ming Lei wrote:

 On Sun, Jul 21, 2013 at 2:00 AM, Alan Stern st...@rowland.harvard.edu 
 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

Re: How should we handle isochronous underruns?

2013-07-22 Thread Alan Stern
On Mon, 22 Jul 2013, Ming Lei wrote:

  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).

On EHCI, valid time slots run from 0 to 8191 (or less).  On OHCI they
run from 0 to 65535.  On UHCI they run from 0 to 1023.

  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.

This just adds complexity with no benefit.

  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.

It is implicit.  If bandwidth gets allocated then drivers can assume it
is available.  If it were then freed by the HCD, it might not be
available when a driver wanted to use it.

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

No problem.  The bandwidth will be allocated when the default interface 
setting is installed.

  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.

Okay.

  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.

That might work.  (What if the thread is preempted while the completion
handler is running and then continues on a different CPU?)  But I think
it would still have higher overhead than calling usb_new_iso_stream
once, whenever a new stream is started.

Alan Stern

--
To unsubscribe from this list: send the line unsubscribe linux-usb in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: How should we handle isochronous underruns?

2013-07-22 Thread Alan Stern
On Tue, 23 Jul 2013, Ming Lei wrote:

 On Mon, Jul 22, 2013 at 11:09 PM, Alan Stern st...@rowland.harvard.edu 
 wrote:
  On Mon, 22 Jul 2013, Ming Lei wrote:
 
   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).
 
  On EHCI, valid time slots run from 0 to 8191 (or less).  On OHCI they
  run from 0 to 65535.  On UHCI they run from 0 to 1023.
 
 There are also lots of non-standard HCs, and going to be many in future.
 When one new API is introduced, maybe we can't ignore these HCs, also
 need consider coming HCs.

The authors of those HCDs can implement the new API however they want.

  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.
 
  This just adds complexity with no benefit.
 
 The symmetrical(start, stop) APIs may be easy to understand
 and use, and looks no extra complexity introduced.

I disagree.  (Start) is just as easy to understand as (start,stop).  
Adding stop calls that do nothing is indeed extra complexity with no
benefit.

Think about it: What is an HCD going to do when it gets a stop call?

 One benefit is that we may remove the assumption of  -1 being
 invalid frame/uframe on all HCs, another one is that HCD can know
 clearly if stream is on or off currently, which might be helpful in the
 future.

This is not an assumption for all HCDs; it is just the way that _my_
HCDs will work.  Other HCDs can implement the new API in a different 
way if the author likes.

 The approach is only helpful if most of isoc drivers need to use
 the new API. Considered most of drivers resubmit isoc URBs inside
 completion handler, we can use this automatic way to decide new
 stream for these drivers and avoid lots of changes.

Have you tried to find the places where an isochronous URB is submitted 
without URB_ISO_ASAP?  Those are the only places that will need to be 
changed.

Alan Stern

--
To unsubscribe from this list: send the line unsubscribe linux-usb in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: How should we handle isochronous underruns?

2013-07-22 Thread Ming Lei
On Mon, Jul 22, 2013 at 11:09 PM, Alan Stern st...@rowland.harvard.edu wrote:
 On Mon, 22 Jul 2013, Ming Lei wrote:

  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).

 On EHCI, valid time slots run from 0 to 8191 (or less).  On OHCI they
 run from 0 to 65535.  On UHCI they run from 0 to 1023.

There are also lots of non-standard HCs, and going to be many in future.
When one new API is introduced, maybe we can't ignore these HCs, also
need consider coming HCs.


  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.

 This just adds complexity with no benefit.

The symmetrical(start, stop) APIs may be easy to understand
and use, and looks no extra complexity introduced.

One benefit is that we may remove the assumption of  -1 being
invalid frame/uframe on all HCs, another one is that HCD can know
clearly if stream is on or off currently, which might be helpful in the
future.


  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.

 It is implicit.  If bandwidth gets allocated then drivers can assume it
 is available.  If it were then freed by the HCD, it might not be
 available when a driver wanted to use it.

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

 No problem.  The bandwidth will be allocated when the default interface
 setting is installed.

  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.

 Okay.

  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.

 That might work.  (What if the thread is preempted while the completion
 handler is running and then continues on a different CPU?)  But I think

It works under the situation because both interrupt handler and tasklet
can't be preempted.

If the thread of urb submission is preempted, that means it isn't run
in completion handler, so no matter if it is migrated into other CPUs,
the approach can work well.

 it would still have higher overhead than calling usb_new_iso_stream
 once, whenever a new stream is started.

Yes, the approach introduces overhead of two stores to percpu variable
in complete() path.

But it can't replace the API because it can't work out in case that urb
is resubmitted in tasklet or workqueue whch is scheduled in completion
handler.

The approach is only helpful if most of isoc drivers need to use
the new API. Considered most of drivers resubmit isoc URBs inside
completion handler, we can use this automatic way to decide new
stream for these drivers and avoid lots of changes.

Thanks,
-- 
Ming Lei
--
To unsubscribe from this list: send the line unsubscribe linux-usb in
the body of a message to majord...@vger.kernel.org
More majordomo info at  

Re: How should we handle isochronous underruns?

2013-07-21 Thread Ming Lei
On Sun, Jul 21, 2013 at 2:00 AM, Alan Stern st...@rowland.harvard.edu 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.


   But never mind.  For a new API, how about
  
   void usb_new_iso_stream(struct usb_device *, struct usb_host_endpoint 
   *);
  
   Does that look okay?
 
  Looks you missed one parameter of 'int on'.
 
  I don't understand.  Why is another parameter needed?

 So do you only want to set streaming on and not streaming off?
 If so, that looks a bit weird, could you describe its usage?

 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.  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.

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.

Also with both streaming on and off information, the HCD might improve
bandwidth management in the future.


 In short, it would simply tell the HCD to act as though the next URB
 has URB_ISO_ASAP set.  For HCDs that act as though URB_ISO_ASAP was
 always set, the new call wouldn't do anything -- they would not need to
 implement it.

  (with extra overhead for every URB!) to fix a problem that ought to be

 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.

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.

Anyway this approach is only helpful if much lots of drivers need
changes for underrun case.


Thanks,
-- 
Ming Lei
--
To unsubscribe from this list: send the line unsubscribe linux-usb in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: How should we handle isochronous underruns?

2013-07-21 Thread Alan Stern
On Sun, 21 Jul 2013, Ming Lei wrote:

 On Sun, Jul 21, 2013 at 2:00 AM, Alan Stern st...@rowland.harvard.edu 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.

 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?

 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.

  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?

 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?

 Anyway this approach is only helpful if much lots of drivers need
 changes for underrun case.

Alan Stern

--
To unsubscribe from this list: send the line unsubscribe linux-usb in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: How should we handle isochronous underruns?

2013-07-20 Thread Alan Stern
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.

   But never mind.  For a new API, how about
  
   void usb_new_iso_stream(struct usb_device *, struct usb_host_endpoint *);
  
   Does that look okay?
 
  Looks you missed one parameter of 'int on'.
 
  I don't understand.  Why is another parameter needed?
 
 So do you only want to set streaming on and not streaming off?
 If so, that looks a bit weird, could you describe its usage?

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).

In short, it would simply tell the HCD to act as though the next URB
has URB_ISO_ASAP set.  For HCDs that act as though URB_ISO_ASAP was
always set, the new call wouldn't do anything -- they would not need to
implement it.

  (with extra overhead for every URB!) to fix a problem that ought to be
 
 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.

  fixed by changing drivers.
 
 If only very less drivers need the change, I agree with you.

Okay, good.

Alan Stern

--
To unsubscribe from this list: send the line unsubscribe linux-usb in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: How should we handle isochronous underruns?

2013-07-19 Thread Clemens Ladisch
Ming Lei wrote:
 On Fri, Jul 19, 2013 at 5:20 AM, Alan Stern st...@rowland.harvard.edu wrote:
 On Thu, 18 Jul 2013, Clemens Ladisch wrote:
 In any case, there must be _some_ mechanism to explicitly restart
 a stream.  I do not really care if this is some URB flag or some
 function call.

 I prefer a function call over the flag.  The function call can easily
 be issued just once, but the completion routine would have to clear the
 flag every time the URB gets used.

 IMO, one good candidate is to do it in usb_set_interface()

This will result in a control request to be sent to the device, which
might confuse its firmware.

 also it is reasonable, see blow:

 From 5.6.3 Isochronous Transfer Packet Size Constraints of USB spec 2.0:

   All device default interface settings must not include any isochronous
   endpoints with non-zero data payload sizes.

That's what the spec says.  In reality, there are devices that have non-
zero data payload sizes in the default interface setting, and have no
other alternate setting.

 that said all drivers which are using isoc endpoints have to call
 usb_set_interface(altsetting) explicitly before starting isoc schedule.

But a set_interface request does not necessarily affect a single stream;
there are devices that have multiple isochronous and bulk endpoints in
a single interface, and where restarting one stream must not affect the
others.

 Maybe we can use usb_reset_endpoint() for this purpose after all.  It
 is a perfect fit, because we want to tell the HCD to reset the
 isochronous endpoint back to the start of stream state.

 I suggest not to introduce extra starting stream function to 
 usb_reset_endpoint(),
 and if we have to do this, I suggest to add a new API for the purpose cleanly.

I agree.


Regards,
Clemens
--
To unsubscribe from this list: send the line unsubscribe linux-usb in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: How should we handle isochronous underruns?

2013-07-19 Thread Ming Lei
On Fri, Jul 19, 2013 at 1:44 AM, Clemens Ladisch clem...@ladisch.de wrote:
 Alan Stern wrote:
 On Thu, 18 Jul 2013, Ming Lei wrote:
 On Thu, Jul 18, 2013 at 3:24 AM, Alan Stern st...@rowland.harvard.edu 
 wrote:
 On Thu, 4 Jul 2013, Alan Stern wrote:
 On Thu, 4 Jul 2013, Ming Lei wrote:
 I had some more ideas about this.  Instead of requiring drivers to set
 URB_ISO_ASAP on just the first URB of an isochronous stream, we could
 ask drivers to call usb_reset_endpoint() between streams.  This would
 tell the HCD that the next URB marks the start of a new stream, with no
 need for a special flag.

 This idea still requires changes from old drivers.

 Also it might be not appropriate to call usb_reset_endpoint() in this case
 because other host controller's implementation may do other unnecessary
 thing for this situation.

 Perhaps.  I doubt that HCDs need to do anything when they reset an
 isochronous endpoint, but you're right.  It's safer to avoid the issue.

 Another possibility, which would be even simpler, is for HCDs to assume
 that if the endpoint's queue has been empty for more than 100 ms then a
 new stream is starting.  Then drivers wouldn't have to do anything
 special at all.  (Unless they are stopping and restarting streams very
 rapidly,

 ... which happens when a stream is restarted after an error, or when two
 sound files are played back-to-back.  The audio driver will always
 explicitly restart the stream (because checking whether the timeout has
 elapsed would be too much of a bother), so the timeout is not useful
 in practice.

 In this case, we may use changing altsetting to decide start of streaming.

 Yes indeed.  But that could still require changes to old drivers.

 To be even more safe, unlinking an URB should mark the end of a stream.
 That's what snd-usb-audio does when it closes a stream; it kills all
 the outstanding URBs.

 But it might be possible that the queue is empty at that point.


 In any case, there must be _some_ mechanism to explicitly restart
 a stream.  I do not really care if this is some URB flag or some
 function call.

Thought about the problem further,  looks there is one simple
approach for detecting underrun in case of empty queue:

if (list_empty (stream-td_list)) {
if (running from hcd interrupt or tasklet context)
 underrun
else
 new stream
}

Any comments on this way?

Thanks,
-- 
Ming Lei
--
To unsubscribe from this list: send the line unsubscribe linux-usb in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: How should we handle isochronous underruns?

2013-07-19 Thread Clemens Ladisch
Ming Lei wrote:
 On Fri, Jul 19, 2013 at 1:44 AM, Clemens Ladisch clem...@ladisch.de wrote:
 In any case, there must be _some_ mechanism to explicitly restart
 a stream.  I do not really care if this is some URB flag or some
 function call.

 Thought about the problem further,  looks there is one simple
 approach for detecting underrun in case of empty queue:

 if (list_empty (stream-td_list)) {
 if (running from hcd interrupt or tasklet context)
  underrun
 else
  new stream
 }

Why shouldn't a driver start a stream in an interrupt/tasklet,
or delay URB resubmission to a workqueue?


Regards,
Clemens
--
To unsubscribe from this list: send the line unsubscribe linux-usb in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: How should we handle isochronous underruns?

2013-07-19 Thread Ming Lei
On Fri, Jul 19, 2013 at 5:06 PM, Clemens Ladisch clem...@ladisch.de wrote:
 Ming Lei wrote:
 On Fri, Jul 19, 2013 at 1:44 AM, Clemens Ladisch clem...@ladisch.de wrote:
 In any case, there must be _some_ mechanism to explicitly restart
 a stream.  I do not really care if this is some URB flag or some
 function call.

 Thought about the problem further,  looks there is one simple
 approach for detecting underrun in case of empty queue:

 if (list_empty (stream-td_list)) {
 if (running from hcd interrupt or tasklet context)
  underrun
 else
  new stream
 }

 Why shouldn't a driver start a stream in an interrupt/tasklet,

It should, but actually one driver won't do this because generally
usb_set_interface() is required before starting stream.

If stream is started in another non-isoc URB complete(), this approach
can cover this situation easily.

But do you have examples in which one isoc stream is started in another
isoc URB's complete()? Anyway we need to consider current drivers'
implementation.

 or delay URB resubmission to a workqueue?

Yes, it is possible, and the isoc URBs can be resubmitted in tasklet too,
but it isn't a big deal:

- they have worked well for long time in the underrun situation before
switching to tasklet, so we needn't worry about the change introduced
by switching URB-complete() to tasklet.

or

- change the resubmission into complete() since there are very few
such usage(I only found two drivers which resubmit isoc URBs in tasklet
when I was doing urb complete() cleanup work)


Thanks,
-- 
Ming Lei
--
To unsubscribe from this list: send the line unsubscribe linux-usb in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: How should we handle isochronous underruns?

2013-07-19 Thread Clemens Ladisch
Ming Lei wrote:
 On Fri, Jul 19, 2013 at 5:06 PM, Clemens Ladisch clem...@ladisch.de wrote:
 Ming Lei wrote:
 if (list_empty (stream-td_list)) {
 if (running from hcd interrupt or tasklet context)
  underrun
 else
  new stream
 }

 Why shouldn't a driver start a stream in an interrupt/tasklet,

 It should, but actually one driver won't do this because generally
 usb_set_interface() is required before starting stream.

Not always, and the usb_set_interface() call can be done in a different
context.

 If stream is started in another non-isoc URB complete(), this approach
 can cover this situation easily.

 But do you have examples in which one isoc stream is started in another
 isoc URB's complete()?

There are quite a few audio devices using implicit rate feedback, where
playback URBs are submitted from the capture completions handler.

 or delay URB resubmission to a workqueue?

 Yes, it is possible, and the isoc URBs can be resubmitted in tasklet too,
 but it isn't a big deal:

But your proposed code would not be able to differentiate a workqueue
resubmission from a stream start.


Regards,
Clemens
--
To unsubscribe from this list: send the line unsubscribe linux-usb in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: How should we handle isochronous underruns?

2013-07-19 Thread Ming Lei
On Fri, Jul 19, 2013 at 6:30 PM, Clemens Ladisch clem...@ladisch.de wrote:
 Ming Lei wrote:
 On Fri, Jul 19, 2013 at 5:06 PM, Clemens Ladisch clem...@ladisch.de wrote:
 Ming Lei wrote:
 if (list_empty (stream-td_list)) {
 if (running from hcd interrupt or tasklet context)
  underrun
 else
  new stream
 }

 Why shouldn't a driver start a stream in an interrupt/tasklet,

 It should, but actually one driver won't do this because generally
 usb_set_interface() is required before starting stream.

 Not always, and the usb_set_interface() call can be done in a different
 context.

 If stream is started in another non-isoc URB complete(), this approach
 can cover this situation easily.

 But do you have examples in which one isoc stream is started in another
 isoc URB's complete()?

 There are quite a few audio devices using implicit rate feedback, where
 playback URBs are submitted from the capture completions handler.

That still can be covered easily by the approach since isoc direction is
different, :-)


 or delay URB resubmission to a workqueue?

 Yes, it is possible, and the isoc URBs can be resubmitted in tasklet too,
 but it isn't a big deal:

 But your proposed code would not be able to differentiate a workqueue
 resubmission from a stream start.

As I explained, it isn't a big deal. Either it is working well for long time
in case of underrun with empty queue, or we can change the resubmission
to complete(), right?

Thanks,
-- 
Ming Lei
--
To unsubscribe from this list: send the line unsubscribe linux-usb in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: How should we handle isochronous underruns?

2013-07-19 Thread Ming Lei
On Fri, Jul 19, 2013 at 6:36 PM, Ming Lei tom.leim...@gmail.com wrote:
 On Fri, Jul 19, 2013 at 6:30 PM, Clemens Ladisch clem...@ladisch.de wrote:
 Ming Lei wrote:
 On Fri, Jul 19, 2013 at 5:06 PM, Clemens Ladisch clem...@ladisch.de wrote:
 Ming Lei wrote:
 if (list_empty (stream-td_list)) {
 if (running from hcd interrupt or tasklet context)
  underrun
 else
  new stream
 }

 Why shouldn't a driver start a stream in an interrupt/tasklet,

 It should, but actually one driver won't do this because generally
 usb_set_interface() is required before starting stream.

 Not always, and the usb_set_interface() call can be done in a different
 context.

 If stream is started in another non-isoc URB complete(), this approach
 can cover this situation easily.

 But do you have examples in which one isoc stream is started in another
 isoc URB's complete()?

 There are quite a few audio devices using implicit rate feedback, where
 playback URBs are submitted from the capture completions handler.

 That still can be covered easily by the approach since isoc direction is
 different, :-)

Even we can introduce one flag of 'completing' in 'struct urb' to check if
the USB's submit is called inside its own complete(), by which we can
check if resubmission is in underrun easily.

Consider that isoc URB's resubmission in completion handler should
cover 99% cases, I think this approach is doable.

For other resubmission from tasklet or workque cases, either let them alone
or move the resubmission inside completion() handler, or introduce simple
helper to mark start of frame only for them.   Anyway, there are very few isoc
resubmissions from non-completion handler (only two drivers found in my
urb complet() cleanup work), so it shouldn't be a big deal.

What do you think about this approach?

Thanks,
-- 
Ming Lei
--
To unsubscribe from this list: send the line unsubscribe linux-usb in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: How should we handle isochronous underruns?

2013-07-19 Thread Alan Stern
On Fri, 19 Jul 2013, Ming Lei wrote:

 Even we can introduce one flag of 'completing' in 'struct urb' to check if
 the USB's submit is called inside its own complete(), by which we can
 check if resubmission is in underrun easily.
 
 Consider that isoc URB's resubmission in completion handler should
 cover 99% cases, I think this approach is doable.
 
 For other resubmission from tasklet or workque cases, either let them alone
 or move the resubmission inside completion() handler, or introduce simple
 helper to mark start of frame only for them.   Anyway, there are very few isoc
 resubmissions from non-completion handler (only two drivers found in my
 urb complet() cleanup work), so it shouldn't be a big deal.
 
 What do you think about this approach?

Why go to all this trouble?  We already have the URB_ISO_ASAP flag.

Trying to check the context of an URB submission strikes me as not 
robust at all.  Who knows what tricks drivers will get up to in the 
future?

Adding a new API seems like the cleanest solution.  (Although I still 
think that usb_reset_endpoint() would be appropriate.)

 Actually 'start of stream' should be done inside usbcore because it
 is HCD-independent function, so it is better to provide the information
 from usbcore and let HCD use it if HCD needs the flag.

I'm not quite sure what you mean.  Note that usb_reset_endpoint() _is_ 
a function in usbcore.

But never mind.  For a new API, how about

void usb_new_iso_stream(struct usb_device *, struct usb_host_endpoint *);

Does that look okay?

Alan Stern

--
To unsubscribe from this list: send the line unsubscribe linux-usb in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: How should we handle isochronous underruns?

2013-07-19 Thread Ming Lei
On Fri, Jul 19, 2013 at 10:53 PM, Alan Stern st...@rowland.harvard.edu wrote:
 On Fri, 19 Jul 2013, Ming Lei wrote:

 Even we can introduce one flag of 'completing' in 'struct urb' to check if
 the USB's submit is called inside its own complete(), by which we can
 check if resubmission is in underrun easily.

 Consider that isoc URB's resubmission in completion handler should
 cover 99% cases, I think this approach is doable.

 For other resubmission from tasklet or workque cases, either let them alone
 or move the resubmission inside completion() handler, or introduce simple
 helper to mark start of frame only for them.   Anyway, there are very few 
 isoc
 resubmissions from non-completion handler (only two drivers found in my
 urb complet() cleanup work), so it shouldn't be a big deal.

 What do you think about this approach?

 Why go to all this trouble?  We already have the URB_ISO_ASAP flag.

 Trying to check the context of an URB submission strikes me as not
 robust at all.  Who knows what tricks drivers will get up to in the
 future?

Firstly, it shouldn't be fragile as you image, with the below simple script, we
can find almost all isoc completion handler(276, but most of them are
false positive).

#/bin/sh
USB=drivers/usb
dirs=`ls -d drivers/* | grep -v $USB`
dirs=$dirs $USB/storage $USB/serial $USB/image $USB/class $USB/atm
$USB/misc sound/usb

export dir
for dir in ${dirs}; do
ss=$(git grep -l -w -E iso_frame_desc $dir)
if [ -n $ss ]; then
git grep -n struct\surb $dir | grep -E \(|\) | grep -v -E 
;|,
fi
done

Secondly, from the above script, only very few drivers resubmits isoc URB
in tasklet or other context, and most of them do it in complete()
handler directly.

Finally, suppose drivers do some trick to resubmit URBs in tasklet, workqueue
or other context, we even can ignore them since they worked well for long time
in case of underrun with empty queue, right?


 Adding a new API seems like the cleanest solution.  (Although I still
 think that usb_reset_endpoint() would be appropriate.)

After adding a new API, we still need to change every ISOC driver, and it
won't be simpler than only checking the completion handler, will it?


 Actually 'start of stream' should be done inside usbcore because it
 is HCD-independent function, so it is better to provide the information
 from usbcore and let HCD use it if HCD needs the flag.

 I'm not quite sure what you mean.  Note that usb_reset_endpoint() _is_
 a function in usbcore.

 But never mind.  For a new API, how about

 void usb_new_iso_stream(struct usb_device *, struct usb_host_endpoint *);

 Does that look okay?

Looks you missed one parameter of 'int on'.

But we need to change every ISOC driver to use the API, that is why I
suggest to add urb-completing to minimize changes on drivers.

So how about only using the API on drivers which don't resubmit isoc URBs
in its completion handler()? And I think we can document this usage.

Thanks,
-- 
Ming Lei
--
To unsubscribe from this list: send the line unsubscribe linux-usb in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: How should we handle isochronous underruns?

2013-07-19 Thread Alan Stern
On Sat, 20 Jul 2013, Ming Lei wrote:

  Trying to check the context of an URB submission strikes me as not
  robust at all.  Who knows what tricks drivers will get up to in the
  future?
 
 Firstly, it shouldn't be fragile as you image, with the below simple script, 
 we
 can find almost all isoc completion handler(276, but most of them are
 false positive).
 
 #/bin/sh
 USB=drivers/usb
 dirs=`ls -d drivers/* | grep -v $USB`
 dirs=$dirs $USB/storage $USB/serial $USB/image $USB/class $USB/atm
 $USB/misc sound/usb
 
 export dir
 for dir in ${dirs}; do
   ss=$(git grep -l -w -E iso_frame_desc $dir)
   if [ -n $ss ]; then
   git grep -n struct\surb $dir | grep -E \(|\) | grep -v -E 
 ;|,
   fi
 done
 
 Secondly, from the above script, only very few drivers resubmits isoc URB
 in tasklet or other context, and most of them do it in complete()
 handler directly.

This is irrelevant.  We have to handle drivers that haven't been 
written yet, as well as drivers that exist now.

 Finally, suppose drivers do some trick to resubmit URBs in tasklet, workqueue
 or other context, we even can ignore them since they worked well for long time
 in case of underrun with empty queue, right?

No.  This is an example of trying to be too clever.  Keep it simple.

  Adding a new API seems like the cleanest solution.  (Although I still
  think that usb_reset_endpoint() would be appropriate.)
 
 After adding a new API, we still need to change every ISOC driver, and it
 won't be simpler than only checking the completion handler, will it?

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.

We also don't have to change the isochronous code in every HCD.  Many
of them treat every URB as though URB_ISO_ASAP was set.  Only a few
make an attempt to implement proper handling of isochronous underruns 
-- and those have to be changed anyway.

  But never mind.  For a new API, how about
 
  void usb_new_iso_stream(struct usb_device *, struct usb_host_endpoint *);
 
  Does that look okay?
 
 Looks you missed one parameter of 'int on'.

I don't understand.  Why is another parameter needed?

 But we need to change every ISOC driver to use the API, that is why I
 suggest to add urb-completing to minimize changes on drivers.
 
 So how about only using the API on drivers which don't resubmit isoc URBs
 in its completion handler()? And I think we can document this usage.

I do not like the idea of adding a complex and non-robust mechanism
(with extra overhead for every URB!) to fix a problem that ought to be
fixed by changing drivers.

Alan Stern

--
To unsubscribe from this list: send the line unsubscribe linux-usb in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: How should we handle isochronous underruns?

2013-07-19 Thread Ming Lei
On Sat, Jul 20, 2013 at 11:57 AM, Alan Stern st...@rowland.harvard.edu wrote:
 On Sat, 20 Jul 2013, Ming Lei wrote:

  Trying to check the context of an URB submission strikes me as not
  robust at all.  Who knows what tricks drivers will get up to in the
  future?

 Firstly, it shouldn't be fragile as you image, with the below simple script, 
 we
 can find almost all isoc completion handler(276, but most of them are
 false positive).

 #/bin/sh
 USB=drivers/usb
 dirs=`ls -d drivers/* | grep -v $USB`
 dirs=$dirs $USB/storage $USB/serial $USB/image $USB/class $USB/atm
 $USB/misc sound/usb

 export dir
 for dir in ${dirs}; do
   ss=$(git grep -l -w -E iso_frame_desc $dir)
   if [ -n $ss ]; then
   git grep -n struct\surb $dir | grep -E \(|\) | grep -v -E 
 ;|,
   fi
 done

 Secondly, from the above script, only very few drivers resubmits isoc URB
 in tasklet or other context, and most of them do it in complete()
 handler directly.

 This is irrelevant.  We have to handle drivers that haven't been
 written yet, as well as drivers that exist now.

 Finally, suppose drivers do some trick to resubmit URBs in tasklet, workqueue
 or other context, we even can ignore them since they worked well for long 
 time
 in case of underrun with empty queue, right?

 No.  This is an example of trying to be too clever.  Keep it simple.

  Adding a new API seems like the cleanest solution.  (Although I still
  think that usb_reset_endpoint() would be appropriate.)

 After adding a new API, we still need to change every ISOC driver, and it
 won't be simpler than only checking the completion handler, will it?

 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.


 We also don't have to change the isochronous code in every HCD.  Many
 of them treat every URB as though URB_ISO_ASAP was set.  Only a few
 make an attempt to implement proper handling of isochronous underruns
 -- and those have to be changed anyway.

Yes.


  But never mind.  For a new API, how about
 
  void usb_new_iso_stream(struct usb_device *, struct usb_host_endpoint *);
 
  Does that look okay?

 Looks you missed one parameter of 'int on'.

 I don't understand.  Why is another parameter needed?

So do you only want to set streaming on and not streaming off?
If so, that looks a bit weird, could you describe its usage?


 But we need to change every ISOC driver to use the API, that is why I
 suggest to add urb-completing to minimize changes on drivers.

 So how about only using the API on drivers which don't resubmit isoc URBs
 in its completion handler()? And I think we can document this usage.

 I do not like the idea of adding a complex and non-robust mechanism

IMO, it is very simple, and only one flag inside urb is required for meeting
the demand.

For the non-robust part(new drivers don't resubmit URBs in complete()), we
can let the new introduced API cover it.

Looks it should cover all old drivers automatically.

 (with extra overhead for every URB!) to fix a problem that ought to be

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, :-)

 fixed by changing drivers.

If only very less drivers need the change, I agree with you.


Thanks,
-- 
Ming Lei
--
To unsubscribe from this list: send the line unsubscribe linux-usb in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: How should we handle isochronous underruns?

2013-07-18 Thread Alan Stern
On Thu, 18 Jul 2013, Ming Lei wrote:

 On Thu, Jul 18, 2013 at 3:24 AM, Alan Stern st...@rowland.harvard.edu wrote:
  On Thu, 4 Jul 2013, Alan Stern wrote:
 
  On Thu, 4 Jul 2013, Ming Lei wrote:
 
If so, your coming change may break ABI because as you described
that the flag should be set in the first URB of a new stream, but
some user-space drivers may not set it before. Even USB audio driver
doesn't set it in current -next tree.
 
  I had some more ideas about this.  Instead of requiring drivers to set
  URB_ISO_ASAP on just the first URB of an isochronous stream, we could
  ask drivers to call usb_reset_endpoint() between streams.  This would
  tell the HCD that the next URB marks the start of a new stream, with no
  need for a special flag.
 
 This idea still requires changes from old drivers.
 
 Also it might be not appropriate to call usb_reset_endpoint() in this case
 because other host controller's implementation may do other unnecessary
 thing for this situation.

Perhaps.  I doubt that HCDs need to do anything when they reset an 
isochronous endpoint, but you're right.  It's safer to avoid the issue.

  Another possibility, which would be even simpler, is for HCDs to assume
  that if the endpoint's queue has been empty for more than 100 ms then a
  new stream is starting.  Then drivers wouldn't have to do anything
  special at all.  (Unless they are stopping and restarting streams very
  rapidly, in which case something like usb_reset_endpoint() would be
 
 In this case, we may use changing altsetting to decide start of streaming.

Yes indeed.  But that could still require changes to old drivers.

To be even more safe, unlinking an URB should mark the end of a stream.  
That's what snd-usb-audio does when it closes a stream; it kills all 
the outstanding URBs.

  necessary.)
 
 IMO, this one should be OK, and looks it is a bit similar with unlinking
 empty interrupt qh.

In fact, it's necessary: ehci-hcd doesn't keep track of the state of a 
stream beyond 512 ms or so.

100 ms might even be overkill.  No stream should ever have a gap that
large unless something has gone drastically wrong, in which case it
doesn't much matter what we do.  (Except perhaps for isochronous
endpoints with a period of 128 ms or more.  I have never heard of such 
things; have you?)

Alan Stern

--
To unsubscribe from this list: send the line unsubscribe linux-usb in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: How should we handle isochronous underruns?

2013-07-18 Thread Clemens Ladisch
Alan Stern wrote:
 On Thu, 18 Jul 2013, Ming Lei wrote:
 On Thu, Jul 18, 2013 at 3:24 AM, Alan Stern st...@rowland.harvard.edu 
 wrote:
 On Thu, 4 Jul 2013, Alan Stern wrote:
 On Thu, 4 Jul 2013, Ming Lei wrote:
 I had some more ideas about this.  Instead of requiring drivers to set
 URB_ISO_ASAP on just the first URB of an isochronous stream, we could
 ask drivers to call usb_reset_endpoint() between streams.  This would
 tell the HCD that the next URB marks the start of a new stream, with no
 need for a special flag.

 This idea still requires changes from old drivers.

 Also it might be not appropriate to call usb_reset_endpoint() in this case
 because other host controller's implementation may do other unnecessary
 thing for this situation.

 Perhaps.  I doubt that HCDs need to do anything when they reset an
 isochronous endpoint, but you're right.  It's safer to avoid the issue.

 Another possibility, which would be even simpler, is for HCDs to assume
 that if the endpoint's queue has been empty for more than 100 ms then a
 new stream is starting.  Then drivers wouldn't have to do anything
 special at all.  (Unless they are stopping and restarting streams very
 rapidly,

... which happens when a stream is restarted after an error, or when two
sound files are played back-to-back.  The audio driver will always
explicitly restart the stream (because checking whether the timeout has
elapsed would be too much of a bother), so the timeout is not useful
in practice.

 In this case, we may use changing altsetting to decide start of streaming.

 Yes indeed.  But that could still require changes to old drivers.

 To be even more safe, unlinking an URB should mark the end of a stream.
 That's what snd-usb-audio does when it closes a stream; it kills all
 the outstanding URBs.

But it might be possible that the queue is empty at that point.


In any case, there must be _some_ mechanism to explicitly restart
a stream.  I do not really care if this is some URB flag or some
function call.


Regards,
Clemens
--
To unsubscribe from this list: send the line unsubscribe linux-usb in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: How should we handle isochronous underruns?

2013-07-18 Thread Alan Stern
On Thu, 18 Jul 2013, Clemens Ladisch wrote:

 In any case, there must be _some_ mechanism to explicitly restart
 a stream.  I do not really care if this is some URB flag or some
 function call.

I prefer a function call over the flag.  The function call can easily
be issued just once, but the completion routine would have to clear the
flag every time the URB gets used.

Maybe we can use usb_reset_endpoint() for this purpose after all.  It
is a perfect fit, because we want to tell the HCD to reset the
isochronous endpoint back to the start of stream state.

A search under drivers/ shows that only a few HCDs other than ehci
currently implement the endpoint_reset method: xhci, whci, dwc2, and
ozwpan.  It would not be hard to fix them up to ignore calls for
isochronous endpoints.

Any objections to this approach?

Alan Stern

--
To unsubscribe from this list: send the line unsubscribe linux-usb in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: How should we handle isochronous underruns?

2013-07-18 Thread Ming Lei
On Fri, Jul 19, 2013 at 5:20 AM, Alan Stern st...@rowland.harvard.edu wrote:
 On Thu, 18 Jul 2013, Clemens Ladisch wrote:

 In any case, there must be _some_ mechanism to explicitly restart
 a stream.  I do not really care if this is some URB flag or some
 function call.

 I prefer a function call over the flag.  The function call can easily
 be issued just once, but the completion routine would have to clear the
 flag every time the URB gets used.

IMO, one good candidate is to do it in usb_set_interface(), and we may
avoid changes on most of drivers which are using isoc endpoints, also
it is reasonable, see blow:

From 5.6.3 Isochronous Transfer Packet Size Constraints of USB spec 2.0:

  All device default interface settings must not include any isochronous
  endpoints with non-zero data payload sizes (specified via
wMaxPacketSize
  in the endpoint descriptor). Alternate interface settings may specify
  non-zero data payload sizes for isochronous endpoints.

that said all drivers which are using isoc endpoints have to call
usb_set_interface(altsetting) explicitly before starting isoc schedule.

So for isoc drivers, it is very reasonable to call usb_set_interface(altsetting)
before starting streaming and call usb_set_interface(0) after stopping
streaming. I think we may document this usage, then use this info as
starting/stopping stream flag.

Looks both uvc and uac drivers support this way.

If one driver doesn't call usb_set_interface(0) after streaming off, we
can think it as buggy since the device still consumes bus bandwidth
unnecessary and may cause other device's bandwidth requirement not
satisfied on same bus.


 Maybe we can use usb_reset_endpoint() for this purpose after all.  It
 is a perfect fit, because we want to tell the HCD to reset the
 isochronous endpoint back to the start of stream state.

I suggest not to introduce extra starting stream function to
usb_reset_endpoint(),
and if we have to do this, I suggest to add a new API for the purpose cleanly.

 A search under drivers/ shows that only a few HCDs other than ehci
 currently implement the endpoint_reset method: xhci, whci, dwc2, and
 ozwpan.  It would not be hard to fix them up to ignore calls for
 isochronous endpoints.

From xhci_endpoint_reset(), looks the hcd doesn't rule out isoc
endpoint.

Actually 'start of stream' should be done inside usbcore because it
is HCD-independent function, so it is better to provide the information
from usbcore and let HCD use it if HCD needs the flag.


Thanks,
-- 
Ming Lei
--
To unsubscribe from this list: send the line unsubscribe linux-usb in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: How should we handle isochronous underruns?

2013-07-17 Thread Alan Stern
On Thu, 4 Jul 2013, Alan Stern wrote:

 On Thu, 4 Jul 2013, Ming Lei wrote:
 
   If so, your coming change may break ABI because as you described
   that the flag should be set in the first URB of a new stream, but
   some user-space drivers may not set it before. Even USB audio driver
   doesn't set it in current -next tree.

I had some more ideas about this.  Instead of requiring drivers to set
URB_ISO_ASAP on just the first URB of an isochronous stream, we could
ask drivers to call usb_reset_endpoint() between streams.  This would
tell the HCD that the next URB marks the start of a new stream, with no 
need for a special flag.

Another possibility, which would be even simpler, is for HCDs to assume
that if the endpoint's queue has been empty for more than 100 ms then a
new stream is starting.  Then drivers wouldn't have to do anything
special at all.  (Unless they are stopping and restarting streams very
rapidly, in which case something like usb_reset_endpoint() would be
necessary.)

What do you think?

Alan Stern

--
To unsubscribe from this list: send the line unsubscribe linux-usb in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: How should we handle isochronous underruns?

2013-07-17 Thread Ming Lei
On Thu, Jul 18, 2013 at 3:24 AM, Alan Stern st...@rowland.harvard.edu wrote:
 On Thu, 4 Jul 2013, Alan Stern wrote:

 On Thu, 4 Jul 2013, Ming Lei wrote:

   If so, your coming change may break ABI because as you described
   that the flag should be set in the first URB of a new stream, but
   some user-space drivers may not set it before. Even USB audio driver
   doesn't set it in current -next tree.

 I had some more ideas about this.  Instead of requiring drivers to set
 URB_ISO_ASAP on just the first URB of an isochronous stream, we could
 ask drivers to call usb_reset_endpoint() between streams.  This would
 tell the HCD that the next URB marks the start of a new stream, with no
 need for a special flag.

This idea still requires changes from old drivers.

Also it might be not appropriate to call usb_reset_endpoint() in this case
because other host controller's implementation may do other unnecessary
thing for this situation.


 Another possibility, which would be even simpler, is for HCDs to assume
 that if the endpoint's queue has been empty for more than 100 ms then a
 new stream is starting.  Then drivers wouldn't have to do anything
 special at all.  (Unless they are stopping and restarting streams very
 rapidly, in which case something like usb_reset_endpoint() would be

In this case, we may use changing altsetting to decide start of streaming.

 necessary.)

IMO, this one should be OK, and looks it is a bit similar with unlinking
empty interrupt qh.


Thanks,
-- 
Ming Lei
--
To unsubscribe from this list: send the line unsubscribe linux-usb in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: How should we handle isochronous underruns?

2013-07-04 Thread Alan Stern
On Thu, 4 Jul 2013, Ming Lei wrote:

  If so, your coming change may break ABI because as you described
  that the flag should be set in the first URB of a new stream, but
  some user-space drivers may not set it before. Even USB audio driver
  doesn't set it in current -next tree.
 
  Really?  I thought Clemens's changes were already merged.  In any case,
 
 Looks the change isn't found in linux-next-20130701.

You are right.  I was thinking of commit c75c5ab575af (ALSA: USB: 
adjust for changed 3.8 USB API).  It turns off URB_ISO_ASAP completely, 
but now we will need it to be turned on for the first URB in a stream.

  User programs probably don't matter much.  In general, the practice is
  to leave the interface on altsetting 0 when nothing is running and then
  change to a different altsetting when starting an isochronous stream.
  Changing the altsetting is another way to tell the HCD that a stream is
  starting fresh.
 
 Yes, it might work, but many details need to be payed attention to, such
 as, changing altsetting may not be done during suspend/resume.

Hmmm.  I don't know how snd-usb-audio handles a suspend/resume in the
middle of playback or recording.

HCDs may need to be smart enough to realize that all isochronous
streams must be restarted following a root-hub suspend.

 According to the discussion, URB_ISO_ASAP should be set on the first URB
 of one audio stream, and keep unset on all other URBs, which looks a new 
 usage,
 IMO.

It's the same as the current usage.  I didn't realize that the audio 
driver wasn't setting URB_ISO_ASAP on the first URB of a stream -- 
it's not necessary with the current API.  But it will be needed with 
the new API; that will have to be fixed.

Here's a short explanation, in case the reasoning isn't clear to 
everyone.  Suppose an isochronous stream is started, then stopped, and 
then restarted.  If URB_ISO_ASAP isn't set in the URB that restarts the 
stream, then the HCD will think the stream was running all along -- the 
gap will look like a _very_ large underrun.  Consequently, the restart 
will get messed up.

With the old code, the HCD could tell the difference between an
underrun and a genuine gap.  With an underrun, the pipeline would never
empty out, because each URB would be resubmitted _before_ its
completion was finished.  With tasklets that is no longer true; a
sufficiently bad underrun could cause the pipeline to become completely
empty.

Alan Stern

--
To unsubscribe from this list: send the line unsubscribe linux-usb in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: How should we handle isochronous underruns?

2013-07-04 Thread Clemens Ladisch
Alan Stern wrote:
 On Thu, 4 Jul 2013, Ming Lei wrote:
 Changing the altsetting is another way to tell the HCD that a stream is
 starting fresh.

 Yes, it might work, but many details need to be payed attention to, such
 as, changing altsetting may not be done during suspend/resume.

 Hmmm.  I don't know how snd-usb-audio handles a suspend/resume in the
 middle of playback or recording.

In this case, the ALSA framework will stop the PCM stream, and on resume,
report this like an underrun; the application will then reinitialize the
stream.  (Handling suspend/resume transparently would require that the
driver can restart playing from an arbitrary position in the ring buffer;
snd-usb-audio does not bother to implement this.)


Regards,
Clemens
--
To unsubscribe from this list: send the line unsubscribe linux-usb in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: How should we handle isochronous underruns?

2013-07-04 Thread Alan Stern
On Thu, 4 Jul 2013, Clemens Ladisch wrote:

 Alan Stern wrote:
  On Thu, 4 Jul 2013, Ming Lei wrote:
  Changing the altsetting is another way to tell the HCD that a stream is
  starting fresh.
 
  Yes, it might work, but many details need to be payed attention to, such
  as, changing altsetting may not be done during suspend/resume.
 
  Hmmm.  I don't know how snd-usb-audio handles a suspend/resume in the
  middle of playback or recording.
 
 In this case, the ALSA framework will stop the PCM stream, and on resume,
 report this like an underrun; the application will then reinitialize the
 stream.  (Handling suspend/resume transparently would require that the
 driver can restart playing from an arbitrary position in the ring buffer;
 snd-usb-audio does not bother to implement this.)

Good; that means we don't have to worry about it.  :-)

Alan Stern

--
To unsubscribe from this list: send the line unsubscribe linux-usb in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: How should we handle isochronous underruns?

2013-07-03 Thread Alan Stern
On Wed, 3 Jul 2013, Ming Lei wrote:

  Yes, that is the change tasklet is bringing, so looks we need to find a way
  to distinguish streaming-on from underrun when stream-td_list becomes
  empty in iso_stream_schedule().
 
  The difference will be the URB_ISO_ASAP flag.  The flag should be set
  in the first URB of a new stream.  It should not be set in any other
  URBs, unless the client driver doesn't care about losing
  synchronization when an underrun occurs.
 
 So sounds a better name for the flag should be URB_ISO_STREAM_ON, :-)

I agree, but the existing name is already exposed to userspace in 
include/uapi/linux/usbdevice_fs.h.  We could change the internal name 
while leaving the external name the same, but that would be confusing.

(URB_ISO_ASAP used to mean that the HCD was responsible for scheduling
the URB, and if the flag wasn't set then the value of urb-start_frame
would be used directly.  This doesn't make sense, because drivers
should not be in charge of URB scheduling -- HCDs should take care of
it.  So I have felt free to alter the flag's meaning.)

 Also looks drivers need fix for the API change.

I don't know if any drivers will need to be fixed.  I suspect many of
them simply set URB_ISO_ASAP on all their URBs.  Clemens has already
added a fix for the snd-usb-audio driver.

Alan Stern

--
To unsubscribe from this list: send the line unsubscribe linux-usb in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: How should we handle isochronous underruns?

2013-07-03 Thread Alan Stern
On Wed, 3 Jul 2013, Laurent Pinchart wrote:

  Of course, it has been true all along that the status fields in the URB's
  individual usb_iso_packet_descriptor structures indicate any errors.  But
  HCDs tend to set urb-status to 0 always, for isochronous URBs.  Is there
  any advantage to setting urb-status to -EXDEV, given that we already set
  urb-iso_frame_desc[i].status to -EXDEV for each i?
 
 Not that I see, for the uvcvideo driver at least.

And probably not for anybody else either.

  With (2) or (3), the driver could also recover right away by setting
  the URB_ISO_ASAP flag on its next URB, but then synchronization would
  be lost.  You wouldn't want to do this if synchronization matters.
  But if it doesn't, the driver could simply set URB_ISO_ASAP on every
  URB to avoid worrying about the problem -- the flag would have no
  effect in the absence of underruns.
 
 That's what the uvcvideo driver does. This could be changed, but I don't have 
 time to investigate at the moment. (Tested) patches are of course welcome :-)

Based on your earlier comments, it sounds like always using 
URB_ISO_ASAP will do just what uvcvideo wants.

Thanks for your feedback,

Alan Stern

--
To unsubscribe from this list: send the line unsubscribe linux-usb in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: How should we handle isochronous underruns?

2013-07-03 Thread Alan Stern
On Thu, 4 Jul 2013, Ming Lei wrote:

 On Wed, Jul 3, 2013 at 10:15 PM, Alan Stern st...@rowland.harvard.edu wrote:
  On Wed, 3 Jul 2013, Ming Lei wrote:
 
   Yes, that is the change tasklet is bringing, so looks we need to find a 
   way
   to distinguish streaming-on from underrun when stream-td_list becomes
   empty in iso_stream_schedule().
  
   The difference will be the URB_ISO_ASAP flag.  The flag should be set
   in the first URB of a new stream.  It should not be set in any other
   URBs, unless the client driver doesn't care about losing
   synchronization when an underrun occurs.
 
  So sounds a better name for the flag should be URB_ISO_STREAM_ON, :-)
 
  I agree, but the existing name is already exposed to userspace in
  include/uapi/linux/usbdevice_fs.h.  We could change the internal name
 
 If so, your coming change may break ABI because as you described
 that the flag should be set in the first URB of a new stream, but
 some user-space drivers may not set it before. Even USB audio driver
 doesn't set it in current -next tree.

Really?  I thought Clemens's changes were already merged.  In any case, 
the audio driver should be easy enough to change.  Setting the flag on 
the first URB isn't a big deal.

User programs probably don't matter much.  In general, the practice is
to leave the interface on altsetting 0 when nothing is running and then
change to a different altsetting when starting an isochronous stream.  
Changing the altsetting is another way to tell the HCD that a stream is
starting fresh.

  while leaving the external name the same, but that would be confusing.
 
  (URB_ISO_ASAP used to mean that the HCD was responsible for scheduling
  the URB, and if the flag wasn't set then the value of urb-start_frame
  would be used directly.  This doesn't make sense, because drivers
  should not be in charge of URB scheduling -- HCDs should take care of
  it.  So I have felt free to alter the flag's meaning.)
 
 Anyway the name will become a bit confusing, so if we don't plan to
 change it, we should add detailed comment about its usage.

Yes.  There already are detailed comments; they will need to be 
updated.  But I never did add anything to Documentation/usb/URB.txt; 
obviously that file needs attention.

  them simply set URB_ISO_ASAP on all their URBs.  Clemens has already
  added a fix for the snd-usb-audio driver.
 
 I am wondering the fix has been added because it may depend on the
 coming change of URB_ISO_ASAP, :-)

The new meaning of URB_ISO_ASAP is very close to the current meaning.  
Whatever changes Clemens made ought to work for both the current code 
and the upcoming code.

Alan Stern

--
To unsubscribe from this list: send the line unsubscribe linux-usb in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: How should we handle isochronous underruns?

2013-07-02 Thread Ming Lei
On Mon, Jul 1, 2013 at 10:48 PM, Alan Stern st...@rowland.harvard.edu wrote:
 On Mon, 1 Jul 2013, Ming Lei wrote:
 The fact that the delay is small doesn't matter -- what's important is
 that it will be  0 whereas now there is no delay between completion
 and resubmission (in fact, the resubmission occurs before the
 completion ends).

Yes, that is the change tasklet is bringing, so looks we need to find a way
to distinguish streaming-on from underrun when stream-td_list becomes
empty in iso_stream_schedule().


 I don't think
 the introduced tasklet delay is a problem for EHCI since per EHCI spec
 the maximum rate at which the host controller will issue interrupts is one
 microframe(125us), which means isochronous transfer completion can be
 reported to CPU with about 125us delay in hardware level.

 Irrelevant.  Besides, the delay can be longer than 125 us if another
 interrupt is being handled.

  Thus, for example, even if the pipeline contains only a single URB,
  with the current code it will not become empty.  But with the new code
  it will.  If the load on the system is too high, the pipeline could
  empty out even if it normally contains two or more URBs.

 Single URB may not work well too when running complete() in hard
 irq context.

 It could work very well indeed, if the interval between URBs was larger
 than 1 ms.

It is too fragile so that single isoc URB is seldom used, isn't it?


Thanks,
-- 
Ming Lei
--
To unsubscribe from this list: send the line unsubscribe linux-usb in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: How should we handle isochronous underruns?

2013-07-02 Thread Alan Stern
On Tue, 2 Jul 2013, Ming Lei wrote:

 On Mon, Jul 1, 2013 at 10:48 PM, Alan Stern st...@rowland.harvard.edu wrote:
  On Mon, 1 Jul 2013, Ming Lei wrote:
  The fact that the delay is small doesn't matter -- what's important is
  that it will be  0 whereas now there is no delay between completion
  and resubmission (in fact, the resubmission occurs before the
  completion ends).
 
 Yes, that is the change tasklet is bringing, so looks we need to find a way
 to distinguish streaming-on from underrun when stream-td_list becomes
 empty in iso_stream_schedule().

The difference will be the URB_ISO_ASAP flag.  The flag should be set 
in the first URB of a new stream.  It should not be set in any other 
URBs, unless the client driver doesn't care about losing 
synchronization when an underrun occurs.

   Thus, for example, even if the pipeline contains only a single URB,
   with the current code it will not become empty.  But with the new code
   it will.  If the load on the system is too high, the pipeline could
   empty out even if it normally contains two or more URBs.
 
  Single URB may not work well too when running complete() in hard
  irq context.
 
  It could work very well indeed, if the interval between URBs was larger
  than 1 ms.
 
 It is too fragile so that single isoc URB is seldom used, isn't it?

Maybe not for isochronous.  Interrupt transfers almost always use a 
single URB, though, and they don't have any trouble.

Alan Stern

--
To unsubscribe from this list: send the line unsubscribe linux-usb in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: How should we handle isochronous underruns?

2013-07-02 Thread Laurent Pinchart
Hi Alan,

On Monday 01 July 2013 15:39:46 Alan Stern wrote:
 On Mon, 1 Jul 2013, Laurent Pinchart wrote:
   What about error recovery for insane systems?  If we do get a 50-ms gap
   in the data stream, what's the best way for the UVC driver to learn this
   has happens and attempt to carry on?
  
  When isochronous packets are lost video frames get corrupted. UVC doesn't
  provide sequence numbers for packets, so there's no way to know exactly
  how many packets have been lost.
  
  However, several synchronization methods are available for the driver to
  detect frame boundaries (namely an End-Of-Frame bit and a Frame ID bit
  that toggles for every frame in isochronous packet headers). The driver
  already handles those bits and marks video frames as complete when the EOF
  bit or an FID transition is detected. For uncompressed formats the driver
  then checks whether the received data size matches the frame size, and
  marks the frame as bad if it doesn't. That check can't be performed for
  compressed formats as the frame size is then variable.
  
  It would thus be helpful to receive a notification when a gap in the data
  stream is detected, through the URB status field for instance. The driver
  could then mark the frame being received as faulty and reset its state
  machine to resynchronize to the next frame boundary.
 
 One possibility is to set urb-status to -EXDEV if an underrun has caused
 the entire URB to be too late.  Currently, under those conditions the HCD
 rejects the URB submission with a -EXDEV error code, which doesn't seem to
 be the right approach.  Drivers don't expect isochronous _submissions_ to
 fail, although they are prepared to see failure statuses for isochronous
 _completions_.
 
 Of course, it has been true all along that the status fields in the URB's
 individual usb_iso_packet_descriptor structures indicate any errors.  But
 HCDs tend to set urb-status to 0 always, for isochronous URBs.  Is there
 any advantage to setting urb-status to -EXDEV, given that we already set
 urb-iso_frame_desc[i].status to -EXDEV for each i?

Not that I see, for the uvcvideo driver at least.

 (There's also an urb-error_count field, which reports how many of the
 isochronous packets got an error.  It is hardly used; I think we could
 remove it.)
 
 This boils down to three possibilities for how to handle URBs that were
 submitted too late -- that is, so late that all the time slots for all
 the URB's packets are known to have expired already:
 
 (1) Reject the submission with -EXDEV -- this is what we do now.
 
 (2) Accept the submission, but have the URB complete immediately
   with urb-status and all the packet statuses set to -EXDEV.
 
 (3) Accept the submission, but have the URB complete immediately
   with urb-status set to 0 and all the packet statuses set to
   -EXDEV.
 
 For (1), the only way to recover is to submit an URB with URB_ISO_ASAP
 set.  This is essentially the same as shutting down the stream and
 restarting it.
 
 For (2) and (3), the stream's next time slot value would be updated
 in the usual way.  For example, if 10 slots had expired and the driver
 was submitting URBs containing 4 packets each, then the first and
 second URBs would complete right away with errors, and the first two
 packets of the third URB would get errors, but the last two packets of
 the third URB would be assigned to the two upcoming time slots and
 would be treated normally.  Thus recovery would be automatic, at the
 cost of wasting two URBs.  Since we expect underruns to be rare,
 maybe this is acceptable.
 
 With (2) or (3), the driver could also recover right away by setting
 the URB_ISO_ASAP flag on its next URB, but then synchronization would
 be lost.  You wouldn't want to do this if synchronization matters.
 But if it doesn't, the driver could simply set URB_ISO_ASAP on every
 URB to avoid worrying about the problem -- the flag would have no
 effect in the absence of underruns.

That's what the uvcvideo driver does. This could be changed, but I don't have 
time to investigate at the moment. (Tested) patches are of course welcome :-)

 (The main reason the current code uses (1) is because (2) and (3)
 require completion to occur _during_ submission.  Resubmissions would
 thus be nested, consuming excessive stack space, and there would be a
 deadlock if the completion handler tried to acquire a lock that was
 held during submission.  When a tasklet is used for completions, none
 of these problems arise.)
 
 Any preference?  Clemens, what do you think?

-- 
Regards,

Laurent Pinchart

--
To unsubscribe from this list: send the line unsubscribe linux-usb in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: How should we handle isochronous underruns?

2013-07-01 Thread Pratyush Anand

On 6/30/2013 8:32 PM, Alan Stern wrote:

There are several possible things the HCD could do when an underrun
occurs:


I do not have much experience in working with ISOC host.But by the 
experience of device side I can say that, There could be problem 
irrespective of tasklet or irq context, only that tasklet would be more 
prone to it. Should not we have same approach in handling isoc packet in 
either of the cases?




It could schedule the URB for the first time slot known to be
available, even if that means skipping some time slots which
the hardware might (or might not) be able to use.



IMO, this approach is better. But, what should we call as first time 
slot known to be available. Current code calculates it as now (current 
time slot) + delta microframe, and delta is kept as fixed. However, 
different system works with different values of delta. IMO, This delta 
should be dynamic and software should update it on the basis of initial 
value and feedback (past failure/missed isoc experience).



It could try to schedule the URB for the next time slot after
the last one used by the preceding URB, even if that time slot
has already expired.



There is no meaning of submitting an URB for expired time slot. In 
anyway, it is not going to be transferred and will further result in 
under-run/missed packet.




Something in between...


Making this offset dynamic will cause software to be further complex, 
but that would be the best way to handle such situation.


Regards
Pratyush



What would be best for your purposes?  Or do you have any different
suggestions?



--
To unsubscribe from this list: send the line unsubscribe linux-usb in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: How should we handle isochronous underruns?

2013-07-01 Thread Clemens Ladisch
Pratyush Anand wrote:
 On 6/30/2013 8:32 PM, Alan Stern wrote:
 It could schedule the URB for the first time slot known to be
 available, even if that means skipping some time slots which
 the hardware might (or might not) be able to use.

 IMO, this approach is better.

To quote the USB spec:
| Isochronous Data
| A stream of data whose timing is implied by its delivery rate.

Isochronous transfers are usually used for real-time applications where
it is better to drop a single packet than to delay *all* following
packets.

 It could try to schedule the URB for the next time slot after
 the last one used by the preceding URB, even if that time slot
 has already expired.

 There is no meaning of submitting an URB for expired time slot.

Of course there is.  The HCD cannot exactly know whether the current
slot will expire before the URB is enqueued, so it is not always
possible to label the slot as expired or not during submission.

The meaning of an isochronous URB submission is try to transmit this
data in that frame; whether the URB actually was transferred will be
reported to the completion callback.


Regards,
Clemens
--
To unsubscribe from this list: send the line unsubscribe linux-usb in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: How should we handle isochronous underruns?

2013-07-01 Thread Clemens Ladisch
Ming Lei wrote:
 On Sun, Jun 30, 2013 at 11:02 PM, Alan Stern st...@rowland.harvard.edu 
 wrote:
 Thus, for example, even if the pipeline contains only a single URB,
 with the current code it will not become empty.  But with the new code
 it will.  If the load on the system is too high, the pipeline could
 empty out even if it normally contains two or more URBs.

 [...]
 But I don't know how USB audio driver uses URBs, and could it
 submit only one isoc URB to playback/record audio data?

The audio drivers uses at least two URBs.  (The actual number and length
of URBs depends on how the application configures its buffer.)


Regards,
Clemens
--
To unsubscribe from this list: send the line unsubscribe linux-usb in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: How should we handle isochronous underruns?

2013-07-01 Thread Ming Lei
On Sun, Jun 30, 2013 at 11:02 PM, Alan Stern st...@rowland.harvard.edu wrote:

 Naturally, under normal circumstances this won't matter, because
 underruns shouldn't occur.  But I know from experience that people try
 to push the latency as far down as they can, which increases the
 likelihood of underruns.

I understand the latency is effected by packet count in one URB,
and it shouldn't be related with URB count, so looks we still can ease
the problem by submitting more URBs concurrently, and at the same
time make less packets per URB if guys care latency.

Correct me if it is wrong...

On Mon, Jul 1, 2013 at 7:36 PM, Clemens Ladisch clem...@ladisch.de wrote:

 The audio drivers uses at least two URBs.  (The actual number and length
 of URBs depends on how the application configures its buffer.)

Clemens, thanks for your input.

Also, another important data about the problem is that how much time one
isoc URB may span, which depends on the endpoint interval and
packet number of URB.

Thanks,
-- 
Ming Lei
--
To unsubscribe from this list: send the line unsubscribe linux-usb in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: How should we handle isochronous underruns?

2013-07-01 Thread Pratyush Anand

On 7/1/2013 4:48 PM, Clemens Ladisch wrote:

 It could try to schedule the URB for the next time slot after
 the last one used by the preceding URB, even if that time slot
 has already expired.


There is no meaning of submitting an URB for expired time slot.

Of course there is.  The HCD cannot exactly know whether the current
slot will expire before the URB is enqueued, so it is not always
possible to label the slot as expired or not during submission.

The meaning of an isochronous URB submission is try to transmit this
data in that frame; whether the URB actually was transferred will be
reported to the completion callback.


Correct, I understand it. Let me explain with an example what I wanted 
to convey:


Lets assume that URB1-8 has been submitted to HCD driver from upper 
layer. HCD driver has also further submitted them to the controller 
hardware for execution in n to (n+7)th uf respectively. Now URB3 was not 
able to be transmitted in time and resulted in missed isoc. This failure 
will cause mainly because of two reasons:
1. SW was slow enough in submission of URB to HW. It actually submitted 
when timing was already expired. In this case, it is most likely that 
following URBs (4-8) will also result in missed isoc. So, if we add 
further URB9 for transmission in (n + 8) uf, most likely it may also 
result in missed isoc.
2. SW submitted well in time, but HW was slow enough and could not fetch 
data in time. (In case HS it may not occur, but in case of SS it may 
occur sometime, so this case may not be valid for ehci-hcd). In such 
situation, HW will flush current descriptor and most likely will be able 
to transmit next URB correctly.


So, What I was proposing, to go for dynamic, something like this... When 
an HCD gets an URB request for any isoc pipe, and if there is any 
pending missed isoc flag then wait.. do not submit it to controller. May 
be just keep them in received list(submitted_list). If during any of the 
pending completion callback, SW observes success then submit all from 
submitted_list to be scheduled in very next uf, and clear pending 
missed isoc flag.
If none of the submitted URB results in success, then do not submit them 
in very next frame, rather submit for the first time slot known to be 
available.


Regards
Pratyush

--
To unsubscribe from this list: send the line unsubscribe linux-usb in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: How should we handle isochronous underruns?

2013-07-01 Thread Clemens Ladisch
Ming Lei wrote:
 On Sun, Jun 30, 2013 at 11:02 PM, Alan Stern st...@rowland.harvard.edu 
 wrote:
 Naturally, under normal circumstances this won't matter, because
 underruns shouldn't occur.  But I know from experience that people try
 to push the latency as far down as they can, which increases the
 likelihood of underruns.

 I understand the latency is effected by packet count in one URB,
 and it shouldn't be related with URB count,

This is true only when capturing.  For playback, the latency is the
length of the entire pipeline.


Regards,
Clemens
--
To unsubscribe from this list: send the line unsubscribe linux-usb in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: How should we handle isochronous underruns?

2013-07-01 Thread Laurent Pinchart
Hello,

On Monday 01 July 2013 13:19:05 Ming Lei wrote:
 On Sun, Jun 30, 2013 at 11:02 PM, Alan Stern wrote:
  Clement and Laurent:
  
  The two of you seem to be the people who make the most use of
  isochronous USB transfers.  Since the ehci-hcd driver is being changed
  to use a tasklet for URB completion callbacks, it looks like I will
  need to reconsider how isochronous underruns get handled.
 
 Without using tasklet, the hard interrupt handler still can be delayed
 for some time, and switching to tasklet doesn't change the fact of the
 probable delay of URB handling.
 
  The basic prolem is simple enough: What should the HCD do when an
  URB is submitted after an isochronous pipeline has emptied out?
 
 I think some time-related data should be helpful for the discussion, for
 example, how long the isochronous pipeline may become empty in current
 audio/video driver(application) without any URB resubmit during the period?
 
  The problem will be more acute than in the past, because URB
  resubmissions will no longer be synchronous with URB completions,
  thanks to the tasklet.  That is, in the current code, if the completion
  handler resubmits the URB, the resubmission occurs before the HCD
  finishes the completion callback.  But in the new code, the HCD will
  simply hand the URB over to the tasklet, and the resubmission won't
  occur until some time later (when the tasklet wakes up and invokes the
  completion handler).  As far as the HCD is concerned, the completion
 
 The delay should be very small(generally several microseconds) since
 isochronous URBs are completed in high priority tasklet. I don't think
 the introduced tasklet delay is a problem for EHCI since per EHCI spec
 the maximum rate at which the host controller will issue interrupts is one
 microframe(125us), which means isochronous transfer completion can be
 reported to CPU with about 125us delay in hardware level.
 
  will already be finished.
  
  Thus, for example, even if the pipeline contains only a single URB, with
  the current code it will not become empty. But with the new code it will. 
  If the load on the system is too high, the pipeline could empty out even
  if it normally contains two or more URBs.
 
 Single URB may not work well too when running complete() in hard
 irq context.
 
 In UVC driver, looks it may submit at most 5 URBs which can include max
 32 packets, so it will take about 5*32*125us(20ms) to make isoc pipeline
 empty suppose the interval is 1uF.

That's correct. Unlike the UAC driver, the UVC driver doesn't care too much 
about exact timings. Avoiding packet loss is my main concern. As video frames 
are not delivered to userspace before they are fully transmitted, and given 
the large number of URBs required to transmit a video frame, I can submit more 
URBs (without reasonable limits) if that can help avoiding underruns.

 But I don't know how USB audio driver uses URBs, and could it
 submit only one isoc URB to playback/record audio data?
 
  This means that the HCD will have trouble telling the difference
  between an underrun and a normal restart of a stopped I/O stream.  In
  both cases it will see an URB being submitted to an empty queue.
 
 IMO, we should try to avoid the situation, and in UVC cases looks it is
 impossible to see an URB being submitted to an empty queue except
 for at the moment of starting streaming or interrupt disabled for extremely
 long.

A couple of users have experienced underruns in the past due to a rogue driver 
disabling interrupts for tens of milliseconds. I don't think switching to 
tasklets will have a strong adverse effect, the 20ms buffer time should be 
large enough to avoid underruns in sane systems.

  Here's where the URB_ISO_ASAP flag will be useful; if that flag is set
  then the URB is restarting a stopped stream, but if it isn't set then
  the pipeline experienced an underrun.
  
  Naturally, under normal circumstances this won't matter, because
  underruns shouldn't occur.  But I know from experience that people try
  to push the latency as far down as they can, which increases the
  likelihood of underruns.
  
  There are several possible things the HCD could do when an underrun
  occurs:
  It could schedule the URB for the first time slot known to be
  available, even if that means skipping some time slots which
  the hardware might (or might not) be able to use.
  
  It could try to schedule the URB for the next time slot after
  the last one used by the preceding URB, even if that time slot
  has already expired.
  
  Something in between...
  
  What would be best for your purposes?  Or do you have any different
  suggestions?

-- 
Regards,

Laurent Pinchart

--
To unsubscribe from this list: send the line unsubscribe linux-usb in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: How should we handle isochronous underruns?

2013-07-01 Thread Ming Lei
On Mon, Jul 1, 2013 at 9:06 PM, Clemens Ladisch clem...@ladisch.de wrote:
 Ming Lei wrote:
 On Sun, Jun 30, 2013 at 11:02 PM, Alan Stern st...@rowland.harvard.edu 
 wrote:
 Naturally, under normal circumstances this won't matter, because
 underruns shouldn't occur.  But I know from experience that people try
 to push the latency as far down as they can, which increases the
 likelihood of underruns.

 I understand the latency is effected by packet count in one URB,
 and it shouldn't be related with URB count,

 This is true only when capturing.  For playback, the latency is the
 length of the entire pipeline.

For playback, every URB submitted is added into hw table
immediately, then the data will be played to speaker. I don't
understand why the latency is the entire pipeline.  If you submitted
a bit more URBs, underruns shouldn't happen at all.

Could you explain it in a bit detail?

Thanks,
-- 
Ming Lei
--
To unsubscribe from this list: send the line unsubscribe linux-usb in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: How should we handle isochronous underruns?

2013-07-01 Thread Clemens Ladisch
Ming Lei wrote:
 On Mon, Jul 1, 2013 at 9:06 PM, Clemens Ladisch clem...@ladisch.de wrote:
 Ming Lei wrote:
 I understand the latency is effected by packet count in one URB,
 and it shouldn't be related with URB count,

 This is true only when capturing.  For playback, the latency is the
 length of the entire pipeline.

 For playback, every URB submitted is added into hw table
 immediately, then the data will be played to speaker. I don't
 understand why the latency is the entire pipeline.

A submitted packet will be transmitted only after all the other packets
in the pipeline have been transmitted.


Regards,
Clemens
--
To unsubscribe from this list: send the line unsubscribe linux-usb in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: How should we handle isochronous underruns?

2013-07-01 Thread Ming Lei
On Mon, Jul 1, 2013 at 9:27 PM, Clemens Ladisch clem...@ladisch.de wrote:
 Ming Lei wrote:
 On Mon, Jul 1, 2013 at 9:06 PM, Clemens Ladisch clem...@ladisch.de wrote:
 Ming Lei wrote:
 I understand the latency is effected by packet count in one URB,
 and it shouldn't be related with URB count,

 This is true only when capturing.  For playback, the latency is the
 length of the entire pipeline.

 For playback, every URB submitted is added into hw table
 immediately, then the data will be played to speaker. I don't
 understand why the latency is the entire pipeline.

 A submitted packet will be transmitted only after all the other packets
 in the pipeline have been transmitted.

Yes, that is always true since EHCI HW will send out data(packet) to
device one by one at the scheduled frame/uframe according to the
order of URB submitting , so the USB audio driver can submit URBs
in advance, can't it?

Also could you provide the typical time one URB in audio driver may
span?

Thanks,
-- 
Ming Lei
--
To unsubscribe from this list: send the line unsubscribe linux-usb in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: How should we handle isochronous underruns?

2013-07-01 Thread Clemens Ladisch
Pratyush Anand wrote:
 On 7/1/2013 4:48 PM, Clemens Ladisch wrote:
 There is no meaning of submitting an URB for expired time slot.

 Of course there is.  The HCD cannot exactly know whether the current
 slot will expire before the URB is enqueued, so it is not always
 possible to label the slot as expired or not during submission.

 The meaning of an isochronous URB submission is try to transmit this
 data in that frame; whether the URB actually was transferred will be
 reported to the completion callback.

 Correct, I understand it. Let me explain with an example what I wanted
 to convey:

 Lets assume that URB1-8 has been submitted to HCD driver from upper
 layer. HCD driver has also further submitted them to the controller
 hardware for execution in n to (n+7)th uf respectively. Now URB3 was
 not able to be transmitted in time and resulted in missed isoc. This
 failure will cause mainly because of two reasons:
 1. SW was slow enough in submission of URB to HW. It actually
submitted when timing was already expired. In this case, it is most
likely that following URBs (4-8) will also result in missed isoc.
So, if we add further URB9 for transmission in (n + 8) uf, most
likely it may also result in missed isoc.

But there is _some_ uf that has not yet expired.  If the HCD delays
enqueuing URBs, it just increases the risk that that uf will expire too.

 2. SW submitted well in time, but HW was slow enough and could not
fetch data in time. In such situation, HW will flush current
descriptor and most likely will be able to transmit next URB
correctly.

 So, What I was proposing, to go for dynamic, something like this...
 When an HCD gets an URB request for any isoc pipe, and if there is any
 pending missed isoc flag then wait.. do not submit it to controller.
 May be just keep them in received list(submitted_list). If during any
 of the pending completion callback, SW observes success then submit
 all from submitted_list to be scheduled in very next uf

This is not possible with a very short pipeline where there is no other
packet that could complete.

And even if it is possible in some cases: why should submitted packets
be delayed at all?  The UAC driver wants all packets at their correct
position in time (or else to be dropped), and the UVC driver does not
want delays which could make it lose some data sent by the device.


Regards,
Clemens
--
To unsubscribe from this list: send the line unsubscribe linux-usb in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: How should we handle isochronous underruns?

2013-07-01 Thread Clemens Ladisch
Ming Lei wrote:
 On Mon, Jul 1, 2013 at 9:27 PM, Clemens Ladisch clem...@ladisch.de wrote:
 Ming Lei wrote:
 On Mon, Jul 1, 2013 at 9:06 PM, Clemens Ladisch clem...@ladisch.de wrote:
 Ming Lei wrote:
 I understand the latency is effected by packet count in one URB,
 and it shouldn't be related with URB count,

 This is true only when capturing.  For playback, the latency is the
 length of the entire pipeline.

 For playback, every URB submitted is added into hw table
 immediately, then the data will be played to speaker. I don't
 understand why the latency is the entire pipeline.

 A submitted packet will be transmitted only after all the other packets
 in the pipeline have been transmitted.

 Yes, that is always true since EHCI HW will send out data(packet) to
 device one by one at the scheduled frame/uframe according to the
 order of URB submitting , so the USB audio driver can submit URBs
 in advance, can't it?

Latency is defined as the time interval between the software generating
the sample data, and the data actually being played.  When the driver
submits URBs in advance, latency increases accordingly.

(The Linux USB API does not allow changing a URB's buffer after it has
been submitted.)

 Also could you provide the typical time one URB in audio driver may
 span?

Anything between one microframe and twenty milliseconds.  Most software
ends up using eight milliseconds.


Regards,
Clemens
--
To unsubscribe from this list: send the line unsubscribe linux-usb in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: How should we handle isochronous underruns?

2013-07-01 Thread Alan Stern
On Sun, 30 Jun 2013, Clemens Ladisch wrote:

 Alan Stern wrote:
  [...]
  This means that the HCD will have trouble telling the difference
  between an underrun and a normal restart of a stopped I/O stream.  In
  both cases it will see an URB being submitted to an empty queue.
  Here's where the URB_ISO_ASAP flag will be useful; if that flag is set
  then the URB is restarting a stopped stream, but if it isn't set then
  the pipeline experienced an underrun.
 
  Naturally, under normal circumstances this won't matter, because
  underruns shouldn't occur.  But I know from experience that people try
  to push the latency as far down as they can, which increases the
  likelihood of underruns.
 
  There are several possible things the HCD could do when an underrun
  occurs:
 
  It could schedule the URB for the first time slot known to be
  available, even if that means skipping some time slots which
  the hardware might (or might not) be able to use.
 
 The word might shows an important point: due to software and hardware
 racing against each other, it is _not possible_ to know whether some URB
 to be submitted will actually still be on time or not.

That's a very important point.  On the other hand, sometimes it _is_ 
possible to know that a particular slot has already expired (for 
example, if a register read indicates the hardware has already reached 
frame N+1 then we know that frame N is over).

  It could try to schedule the URB for the next time slot after
  the last one used by the preceding URB, even if that time slot
  has already expired.
 
 For audio, it is important to _try_ to transmit the packet at the
 _correct_ time; a guarantee that the packet will be transmitted at
 _some_ time would be worthless.  (This is what isochronous is all
 about.)
 
 That the error reporting is delayed from submission to the completion
 callback is no problem.

Should the behavior change if the submission is _extremely_ late?  The
rogue driver leaving interrupts disabled for over 50 ms is a good
example (and one that I actually encountered!).  Even when that
happens, would you prefer to require the audio driver to submit 50-ms
worth of URBs before doing any real I/O?

Alan Stern

--
To unsubscribe from this list: send the line unsubscribe linux-usb in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: How should we handle isochronous underruns?

2013-07-01 Thread Alan Stern
On Mon, 1 Jul 2013, Ming Lei wrote:

 On Sun, Jun 30, 2013 at 11:02 PM, Alan Stern st...@rowland.harvard.edu 
 wrote:
  Clement and Laurent:
 
  The two of you seem to be the people who make the most use of
  isochronous USB transfers.  Since the ehci-hcd driver is being changed
  to use a tasklet for URB completion callbacks, it looks like I will
  need to reconsider how isochronous underruns get handled.
 
 Without using tasklet, the hard interrupt handler still can be delayed
 for some time, and switching to tasklet doesn't change the fact of the
 probable delay of URB handling.

Yes.  That wasn't the point.

  The problem will be more acute than in the past, because URB
  resubmissions will no longer be synchronous with URB completions,
  thanks to the tasklet.  That is, in the current code, if the completion
  handler resubmits the URB, the resubmission occurs before the HCD
  finishes the completion callback.  But in the new code, the HCD will
  simply hand the URB over to the tasklet, and the resubmission won't
  occur until some time later (when the tasklet wakes up and invokes the
  completion handler).  As far as the HCD is concerned, the completion
 
 The delay should be very small(generally several microseconds) since
 isochronous URBs are completed in high priority tasklet.

The fact that the delay is small doesn't matter -- what's important is 
that it will be  0 whereas now there is no delay between completion 
and resubmission (in fact, the resubmission occurs before the 
completion ends).

 I don't think
 the introduced tasklet delay is a problem for EHCI since per EHCI spec
 the maximum rate at which the host controller will issue interrupts is one
 microframe(125us), which means isochronous transfer completion can be
 reported to CPU with about 125us delay in hardware level.

Irrelevant.  Besides, the delay can be longer than 125 us if another 
interrupt is being handled.

  Thus, for example, even if the pipeline contains only a single URB,
  with the current code it will not become empty.  But with the new code
  it will.  If the load on the system is too high, the pipeline could
  empty out even if it normally contains two or more URBs.
 
 Single URB may not work well too when running complete() in hard
 irq context.

It could work very well indeed, if the interval between URBs was larger 
than 1 ms.

Alan Stern

--
To unsubscribe from this list: send the line unsubscribe linux-usb in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: How should we handle isochronous underruns?

2013-07-01 Thread Alan Stern
On Mon, 1 Jul 2013, Pratyush Anand wrote:

 On 6/30/2013 8:32 PM, Alan Stern wrote:
  There are several possible things the HCD could do when an underrun
  occurs:
 
 I do not have much experience in working with ISOC host.But by the 
 experience of device side I can say that, There could be problem 
 irrespective of tasklet or irq context, only that tasklet would be more 
 prone to it. Should not we have same approach in handling isoc packet in 
 either of the cases?

Of course we should.

  It could schedule the URB for the first time slot known to be
  available, even if that means skipping some time slots which
  the hardware might (or might not) be able to use.
 
 
 IMO, this approach is better. But, what should we call as first time 
 slot known to be available. Current code calculates it as now (current 
 time slot) + delta microframe, and delta is kept as fixed. However, 
 different system works with different values of delta. IMO, This delta 
 should be dynamic and software should update it on the basis of initial 
 value and feedback (past failure/missed isoc experience).

Clemens disagrees, and I accept his recommendation.

  It could try to schedule the URB for the next time slot after
  the last one used by the preceding URB, even if that time slot
  has already expired.
 
 
 There is no meaning of submitting an URB for expired time slot. In 
 anyway, it is not going to be transferred and will further result in 
 under-run/missed packet.

That is not true.  For example, suppose 2 time slots have already 
expired, but the submitted URB contains 5 packets.  Even though it's 
too late for the first two packets, the last three can still be 
transferred.

Alan Stern

--
To unsubscribe from this list: send the line unsubscribe linux-usb in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: How should we handle isochronous underruns?

2013-07-01 Thread Alan Stern
On Mon, 1 Jul 2013, Laurent Pinchart wrote:

 That's correct. Unlike the UAC driver, the UVC driver doesn't care too much 
 about exact timings. Avoiding packet loss is my main concern. As video frames 
 are not delivered to userspace before they are fully transmitted, and given 
 the large number of URBs required to transmit a video frame, I can submit 
 more 
 URBs (without reasonable limits) if that can help avoiding underruns.

 A couple of users have experienced underruns in the past due to a rogue 
 driver 
 disabling interrupts for tens of milliseconds. I don't think switching to 
 tasklets will have a strong adverse effect, the 20ms buffer time should be 
 large enough to avoid underruns in sane systems.

What about error recovery for insane systems?  If we do get a 50-ms gap
in the data stream, what's the best way for the UVC driver to learn
this has happens and attempt to carry on?

Alan Stern

--
To unsubscribe from this list: send the line unsubscribe linux-usb in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: How should we handle isochronous underruns?

2013-07-01 Thread Laurent Pinchart
Hi Alan,

On Monday 01 July 2013 11:08:33 Alan Stern wrote:
 On Mon, 1 Jul 2013, Laurent Pinchart wrote:
  That's correct. Unlike the UAC driver, the UVC driver doesn't care too
  much about exact timings. Avoiding packet loss is my main concern. As
  video frames are not delivered to userspace before they are fully
  transmitted, and given the large number of URBs required to transmit a
  video frame, I can submit more URBs (without reasonable limits) if that
  can help avoiding underruns.
  
  A couple of users have experienced underruns in the past due to a rogue
  driver disabling interrupts for tens of milliseconds. I don't think
  switching to tasklets will have a strong adverse effect, the 20ms buffer
  time should be large enough to avoid underruns in sane systems.
 
 What about error recovery for insane systems?  If we do get a 50-ms gap in
 the data stream, what's the best way for the UVC driver to learn this has
 happens and attempt to carry on?

When isochronous packets are lost video frames get corrupted. UVC doesn't 
provide sequence numbers for packets, so there's no way to know exactly how 
many packets have been lost.

However, several synchronization methods are available for the driver to 
detect frame boundaries (namely an End-Of-Frame bit and a Frame ID bit that 
toggles for every frame in isochronous packet headers). The driver already 
handles those bits and marks video frames as complete when the EOF bit or an 
FID transition is detected. For uncompressed formats the driver then checks 
whether the received data size matches the frame size, and marks the frame as 
bad if it doesn't. That check can't be performed for compressed formats as the 
frame size is then variable.

It would thus be helpful to receive a notification when a gap in the data 
stream is detected, through the URB status field for instance. The driver 
could then mark the frame being received as faulty and reset its state machine 
to resynchronize to the next frame boundary.

-- 
Regards,

Laurent Pinchart

--
To unsubscribe from this list: send the line unsubscribe linux-usb in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: How should we handle isochronous underruns?

2013-07-01 Thread Alan Stern
On Mon, 1 Jul 2013, Laurent Pinchart wrote:

  What about error recovery for insane systems?  If we do get a 50-ms gap in
  the data stream, what's the best way for the UVC driver to learn this has
  happens and attempt to carry on?
 
 When isochronous packets are lost video frames get corrupted. UVC doesn't 
 provide sequence numbers for packets, so there's no way to know exactly how 
 many packets have been lost.
 
 However, several synchronization methods are available for the driver to 
 detect frame boundaries (namely an End-Of-Frame bit and a Frame ID bit that 
 toggles for every frame in isochronous packet headers). The driver already 
 handles those bits and marks video frames as complete when the EOF bit or an 
 FID transition is detected. For uncompressed formats the driver then checks 
 whether the received data size matches the frame size, and marks the frame as 
 bad if it doesn't. That check can't be performed for compressed formats as 
 the 
 frame size is then variable.
 
 It would thus be helpful to receive a notification when a gap in the data 
 stream is detected, through the URB status field for instance. The driver 
 could then mark the frame being received as faulty and reset its state 
 machine 
 to resynchronize to the next frame boundary.

One possibility is to set urb-status to -EXDEV if an underrun has
caused the entire URB to be too late.  Currently, under those
conditions the HCD rejects the URB submission with a -EXDEV error code,
which doesn't seem to be the right approach.  Drivers don't expect
isochronous _submissions_ to fail, although they are prepared to see
failure statuses for isochronous _completions_.

Of course, it has been true all along that the status fields in the
URB's individual usb_iso_packet_descriptor structures indicate any
errors.  But HCDs tend to set urb-status to 0 always, for isochronous
URBs.  Is there any advantage to setting urb-status to -EXDEV, given
that we already set urb-iso_frame_desc[i].status to -EXDEV for each i?

(There's also an urb-error_count field, which reports how many of the
isochronous packets got an error.  It is hardly used; I think we could
remove it.)

This boils down to three possibilities for how to handle URBs that were
submitted too late -- that is, so late that all the time slots for all
the URB's packets are known to have expired already:

(1) Reject the submission with -EXDEV -- this is what we do now.

(2) Accept the submission, but have the URB complete immediately
with urb-status and all the packet statuses set to -EXDEV.

(3) Accept the submission, but have the URB complete immediately
with urb-status set to 0 and all the packet statuses set to 
-EXDEV.

For (1), the only way to recover is to submit an URB with URB_ISO_ASAP
set.  This is essentially the same as shutting down the stream and 
restarting it.

For (2) and (3), the stream's next time slot value would be updated
in the usual way.  For example, if 10 slots had expired and the driver
was submitting URBs containing 4 packets each, then the first and
second URBs would complete right away with errors, and the first two
packets of the third URB would get errors, but the last two packets of
the third URB would be assigned to the two upcoming time slots and
would be treated normally.  Thus recovery would be automatic, at the
cost of wasting two URBs.  Since we expect underruns to be rare, 
maybe this is acceptable.

With (2) or (3), the driver could also recover right away by setting
the URB_ISO_ASAP flag on its next URB, but then synchronization would
be lost.  You wouldn't want to do this if synchronization matters.  
But if it doesn't, the driver could simply set URB_ISO_ASAP on every
URB to avoid worrying about the problem -- the flag would have no
effect in the absence of underruns.

(The main reason the current code uses (1) is because (2) and (3)  
require completion to occur _during_ submission.  Resubmissions would
thus be nested, consuming excessive stack space, and there would be a
deadlock if the completion handler tried to acquire a lock that was
held during submission.  When a tasklet is used for completions, none
of these problems arise.)

Any preference?  Clemens, what do you think?

Alan Stern

--
To unsubscribe from this list: send the line unsubscribe linux-usb in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: How should we handle isochronous underruns?

2013-07-01 Thread Clemens Ladisch
Alan Stern wrote:
 (1) Reject the submission with -EXDEV -- this is what we do now.

 (2) Accept the submission, but have the URB complete immediately
   with urb-status and all the packet statuses set to -EXDEV.

 (3) Accept the submission, but have the URB complete immediately
   with urb-status set to 0 and all the packet statuses set to
   -EXDEV.

The audio driver currently ignores submission errors (because of a bug:
the obvious way to stop the PCM stream would result in a deadlock; the
tasklet completion might change this), and checks urb-status only to
detect if the stream should be stopped (because of a 'normal' stop or
unplugging.)  So (2) or (3) (no matter which) is preferrable over (1).

 For (1), the only way to recover is to submit an URB with URB_ISO_ASAP
 set.  This is essentially the same as shutting down the stream and
 restarting it.

 For (2) and (3), the stream's next time slot value would be updated
 in the usual way.  For example, if 10 slots had expired and the driver
 was submitting URBs containing 4 packets each, then the first and
 second URBs would complete right away with errors, and the first two
 packets of the third URB would get errors, but the last two packets of
 the third URB would be assigned to the two upcoming time slots and
 would be treated normally.  Thus recovery would be automatic,

This is certainly preferrable over (1).

 at the cost of wasting two URBs.  Since we expect underruns to be
 rare, maybe this is acceptable.

And it's the only recovery mechanism that can preserves the timing/
synchronization of the overall stream.


Regards,
Clemens
--
To unsubscribe from this list: send the line unsubscribe linux-usb in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


How should we handle isochronous underruns?

2013-06-30 Thread Alan Stern
Clement and Laurent:

The two of you seem to be the people who make the most use of
isochronous USB transfers.  Since the ehci-hcd driver is being changed
to use a tasklet for URB completion callbacks, it looks like I will
need to reconsider how isochronous underruns get handled.

The basic prolem is simple enough: What should the HCD do when an 
URB is submitted after an isochronous pipeline has emptied out?

The problem will be more acute than in the past, because URB
resubmissions will no longer be synchronous with URB completions,
thanks to the tasklet.  That is, in the current code, if the completion
handler resubmits the URB, the resubmission occurs before the HCD
finishes the completion callback.  But in the new code, the HCD will
simply hand the URB over to the tasklet, and the resubmission won't
occur until some time later (when the tasklet wakes up and invokes the
completion handler).  As far as the HCD is concerned, the completion 
will already be finished.

Thus, for example, even if the pipeline contains only a single URB,
with the current code it will not become empty.  But with the new code 
it will.  If the load on the system is too high, the pipeline could 
empty out even if it normally contains two or more URBs.

This means that the HCD will have trouble telling the difference
between an underrun and a normal restart of a stopped I/O stream.  In
both cases it will see an URB being submitted to an empty queue.  
Here's where the URB_ISO_ASAP flag will be useful; if that flag is set
then the URB is restarting a stopped stream, but if it isn't set then
the pipeline experienced an underrun.

Naturally, under normal circumstances this won't matter, because 
underruns shouldn't occur.  But I know from experience that people try 
to push the latency as far down as they can, which increases the 
likelihood of underruns.

There are several possible things the HCD could do when an underrun 
occurs:

It could schedule the URB for the first time slot known to be
available, even if that means skipping some time slots which 
the hardware might (or might not) be able to use.

It could try to schedule the URB for the next time slot after 
the last one used by the preceding URB, even if that time slot
has already expired.

Something in between...

What would be best for your purposes?  Or do you have any different 
suggestions?

Alan Stern

--
To unsubscribe from this list: send the line unsubscribe linux-usb in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: How should we handle isochronous underruns?

2013-06-30 Thread Ming Lei
On Sun, Jun 30, 2013 at 11:02 PM, Alan Stern st...@rowland.harvard.edu wrote:
 Clement and Laurent:

 The two of you seem to be the people who make the most use of
 isochronous USB transfers.  Since the ehci-hcd driver is being changed
 to use a tasklet for URB completion callbacks, it looks like I will
 need to reconsider how isochronous underruns get handled.

Without using tasklet, the hard interrupt handler still can be delayed
for some time, and switching to tasklet doesn't change the fact of the
probable delay of URB handling.


 The basic prolem is simple enough: What should the HCD do when an
 URB is submitted after an isochronous pipeline has emptied out?

I think some time-related data should be helpful for the discussion,
for example,
how long the isochronous pipeline may become empty in current audio/video
driver(application) without any URB resubmit during the period?


 The problem will be more acute than in the past, because URB
 resubmissions will no longer be synchronous with URB completions,
 thanks to the tasklet.  That is, in the current code, if the completion
 handler resubmits the URB, the resubmission occurs before the HCD
 finishes the completion callback.  But in the new code, the HCD will
 simply hand the URB over to the tasklet, and the resubmission won't
 occur until some time later (when the tasklet wakes up and invokes the
 completion handler).  As far as the HCD is concerned, the completion

The delay should be very small(generally several microseconds) since
isochronous URBs are completed in high priority tasklet. I don't think
the introduced tasklet delay is a problem for EHCI since per EHCI spec
the maximum rate at which the host controller will issue interrupts is one
microframe(125us), which means isochronous transfer completion can be
reported to CPU with about 125us delay in hardware level.

 will already be finished.

 Thus, for example, even if the pipeline contains only a single URB,
 with the current code it will not become empty.  But with the new code
 it will.  If the load on the system is too high, the pipeline could
 empty out even if it normally contains two or more URBs.

Single URB may not work well too when running complete() in hard
irq context.

In UVC driver, looks it may submit at most 5 URBs which can include max
32 packets, so it will take about 5*32*125us(20ms) to make isoc pipeline
empty suppose the interval is 1uF.

But I don't know how USB audio driver uses URBs, and could it
submit only one isoc URB to playback/record audio data?


 This means that the HCD will have trouble telling the difference
 between an underrun and a normal restart of a stopped I/O stream.  In
 both cases it will see an URB being submitted to an empty queue.

IMO, we should try to avoid the situation, and in UVC cases looks it is
impossible to see an URB being submitted to an empty queue except
for at the moment of starting streaming or interrupt disabled for extremely
long.

 Here's where the URB_ISO_ASAP flag will be useful; if that flag is set
 then the URB is restarting a stopped stream, but if it isn't set then
 the pipeline experienced an underrun.

 Naturally, under normal circumstances this won't matter, because
 underruns shouldn't occur.  But I know from experience that people try
 to push the latency as far down as they can, which increases the
 likelihood of underruns.

 There are several possible things the HCD could do when an underrun
 occurs:

 It could schedule the URB for the first time slot known to be
 available, even if that means skipping some time slots which
 the hardware might (or might not) be able to use.

 It could try to schedule the URB for the next time slot after
 the last one used by the preceding URB, even if that time slot
 has already expired.

 Something in between...

 What would be best for your purposes?  Or do you have any different
 suggestions?

 Alan Stern

 --
 To unsubscribe from this list: send the line unsubscribe linux-usb in
 the body of a message to majord...@vger.kernel.org
 More majordomo info at  http://vger.kernel.org/majordomo-info.html


Thanks,
-- 
Ming Lei
--
To unsubscribe from this list: send the line unsubscribe linux-usb in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html