hi alan: >> > > BTW, I have another question about iso_stream_schedule. >> > > When if (likely (!list_empty (&stream->td_list))) happen, >> > > why don't we just take last scheduled microframe, stream->next_uframe >> > > as start point directly? >> > >> > We do exactly that if URB_ISO_ASAP isn't set. But first the routine >> > has to check and see if the schedule is already full, and it prints a >> > debugging message if all the assigned microframes have already expired. >> Does below source show us what you mean? >> if (unlikely(start < period)) { >> ehci_dbg(ehci, "iso sched full %p (%u-%u < %u mod %u)\n", >> urb, stream->next_uframe, base, >> period, mod); >> status = -ENOSPC; >> goto fail; >> } > > That's the first part (checking if the schedule is already full). > This is the second part (printing a debug message if all the assigned > microframes have already expired): Does this "expired" come from (controller frame pointer) > (stream->next_uframe)? Suppose controller frame pointer = 640 and stream->next_uframe = 600. And that mean Controller have scan our last schedule uframe? > > /* > * Not ASAP: Use the next slot in the stream, > * no matter what. > */ > else if (start + span - period < now2) { > ehci_dbg(ehci, "iso underrun %p (%u+%u < %u)\n", > urb, start + base, > span - period, now2 + base); > } > >> if so, I have one question, why we use ( (last scan frame and last >> schedule frame) < end point interval) to determine schedule is full? > > If start < period, it means that the last packet on the schedule (which > is assigned to uframe start - period) comes before base. The only way > this can happen is if the packets occupy the entire schedule and wrap > around. base in your example base should be 8's multiple, right? if so, I try to rewrite your example. (if anything wrong, please correct me) > (rewrite version) If you think about a few examples, you'll understand. Suppose the endpoint's interval is 8 uframes, starting from uframe 3. Suppose base is 496, and suppose the schedule really is full. Then there will be packets scheduled for uframes 507, 515, ..., 8187, 3, 11, ..., 491, 499 (note that 491 is slightly before 496), and stream->next_uframe will be 499. So start will be set to (499 - 496) & 8191 = 3. The fact that 3 < 8 indicates the schedule is full. (rewrite version) Now suppose everything else is the same, but the schedule isn't completely full. For this example, let's suppose the last scheduled packet is in uframe 483, so stream->next_uframe is equal to 491. Then start will be set to (491 - 496) & 8191 = 8196. The fact that 8196 >= 8 indicates the schedule isn't full. In above case, driver should try to stop this urb if it try to schedule more than 1 packet, right? (rewrite version) Consider one more example: Everything else is the same, but there's only one packet in the schedule. It is assigned to uframe 507, and stream->next_uframe is 515. Then start will be set to (515 - 496) & 8191 = 19, and the fact that 19 >= 8 indicates the schedule isn't full. > Does this help? Yes, it did help me a lot. :) > >> Below is where we handle URB_ISO_ASAP, >> if (urb->transfer_flags & URB_ISO_ASAP) >> start += (next - start + period - 1) & -period; >> >> Why don't we just use start as next? > > If start < next then we don't want to use it. Packets scheduled before > next might not be seen by the hardware, because of the isochronous > scheduling threshold (see section 4.7.2.1 in the EHCI spec). when we calculate next, we have already put isochronous scheduling threshold. if (ehci->i_thresh) next = now + ehci->i_thresh; /* uframe cache */ else next = (now + 2 + 7) & ~0x07; /* full frame cache */ so when handling URB_ISO_ASAP, is it possible to change as below if (urb->transfer_flags & URB_ISO_ASAP) - start += (next - start + period - 1) & -period; + start = (next + base); Appreciate your kind help, -- 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