Re: [RFC] ARM i.MX21 Host Controller Driver

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

 



On Mon, 9 Mar 2009, Martin Fuzzey wrote:

> >> Case 2) seems very strange to me - how can more data be sent than expected?
> >> I have run usbmon traces on both the mx21 and intel systems and the camera
> >> setup commands are the same.
> >>     
> > One possibility is that the amount expected is wrong (too small).
> >   
> Yes I thought of that but it doesn't explain:
> 
> PC (UHCI + PWC)
>     URB requests 10 * 196 bytes
>     Received 10 * 192 bytes
> 
> iMX21
>     URB requests 10 * 196 bytes
>     Received 196 bytes + data overrun

What I meant was that an error in the driver might cause the hardware
to expect < 196 bytes -- the length might be copied wrongly from the
URB.  But given the rest of your explanation, this seems pretty
unlikely.

In fact, are you sure the numbers above are correct?  Why does the 
iMX21 see 196 bytes rather than 192 for the first frame?  Could the TD 
be set up wrong?

> I use something similar to determine the start frame for each URB and
> hence the frame for each TD (using interval). Hence in
> imx21_hc_urb_enqueue_isoc() I get a list of struct td each with its
> frame number.
> 
> Now the iMX21 hardware has:
>     32 ETD structures
>     Data memory
>     Various registers
> 
> Any type of transfer (isoc or otherwise) goes like this from a hardware
> point of view:
>     Obtain a free ETD
>     Fill it in (transfer type, data memory offset, frame number for
> isoc, ...)
>     Setup DMA between USB Data memory and system memory
>     Activate ETD
>     Get interrupt when done.
> 
> For isoc transfers I use 2 ETDs. I setup the first two with the first
> two struct td s calculated during enqueuing.
> Then when the first ETD done interrupt occurs I replace the first ETD
> with the third struct td etc. (schedule_iso_etds())
> 
> So all this means that I calculate all the frame numbers up front during
> submission but get one interrupt per TD. So my question is what should I
> do if when the interrupt occurs the current frame number (as read from
> the hardware) is already > precalculated frame number (latency,...) [I
> have actually seen this happen occasionally]:
>     Signal an error for the URB?

In general, the return status for an Isoc URB should be nonzero if 
there is an error in any of the individual frames.  Of course, each 
the status in each frame descriptor structure should be set to the 
appropriate value for its frame.

In this case the driver was unable to schedule the frame in time, so 
the appropriate status value would be -EXDEV.  In fact, it will 
occasionally happen that the interrupt occurs when the current frame 
number is == the precalculated frame number, in which case the driver 
won't know until the frame is over whether or not it was too late.

>     Recalculate the frame numbers?

That's a good question.  Truthfully, it depends on the application and
the HCD can't know what's best.  IMO the most suitable approach overall
is to treat it the same as a transmission error -- later frames should
still go in the slots that you precalculated for them.

> More generally I notice the UHCI and OHCI drivers only generate an
> interrupt for the last TD of the URB.
> Unfortunately with my hardware I can't do that. I could do a little
> better because it is in fact possible to send two  data packets per ETD
> (not done in my driver yet). Alternatively I could use more ETDs per
> endpoint but there are only 32 of them.
> > 	If the stream isn't already active, choose a suitable start
> > 	frame in the near future.
> >   
> I use current frame + 1 (maybe too soon?)

uhci-hcd uses current frame + 10, which is maybe too much (but then it
has more work to do, because it has to allocate and fill in a
potentially large number of TDs).  Whatever works reliably is okay.  
You probably should make it + 2, just in case the submission is very
close to the end of the current frame.

> > 	If the stream is active but no URBs are queued and
> > 	URB_ISO_ASAP is not set, use the next slot after the most
> > 	recent URB.  The frame for this slot may already have
> > 	expired; if it has then one or more of the 
> > 	urb->iso_frame_desc[].status values will be set to -EXDEV.
> >   
> I thought that if URB_ISO_ASAP is not set the submitter is supposed to
> specify the frame number in urb->start_frame.

In practice that is unworkable, because drivers don't know the
scheduling parameters of the HCDs.  The existing HCDs basically assume
URB_ISO_ASAP is always set and ignore the value in urb->start_frame.  
After all, it is documented as output-only. (It's also documented as an
input parameter -- the kerneldoc for struct urb is inconsistent in this
respect.  But at least it does go on to explain why drivers can't set
the value reliably.)

Alan Stern

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

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

  Powered by Linux