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