Re: [PATCH] usb: gadget: file_storage: don't assume wMaxPacketSize to be 512

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

 



On Mon, Apr 04, 2011 at 11:39:49AM -0400, Alan Stern wrote:
> On Mon, 4 Apr 2011, Felipe Balbi wrote:
> 
> > Like I said before: HW requests me to give lengths which are divisible
> > by wMaxPacketSize. I can't quote parts of the HW docs here, but I *must*
> > give the HW sizes which are divisible by wMaxPacketSize in case of OUT
> > transfers.
> 
> Ah, I didn't realize this.  It's ironic then that Mian's patch reducing
> the size of the CBW request length was just submitted.  Well, we can

heh.

> retract that patch easily enough if necessary...

ok. I think it's better to revert that and apply the patch using
set_bulk_out_req_length() which I sent earlier, see below...

> This hardware restriction doesn't affect only g_file_storage; you will
> have to take it into account with _every_ gadget driver.  The only
> general solution is to use a bounce buffer.  Collect all but the last
> partial packet in the gdaget's transfer buffer as usual, then use a
> private maxpacket-sized buffer for the remainder, which you then copy
> to the end of the transfer buffer.

A bounce buffer isn't good enough. Remember I'm talking USB3, with the
current 16K buffer size in g_file_storage, we will get one IRQ every:

(16 << 10) / (5 << 30) = ~3us

If every 3us I need to do a memcpy() of the remaining 1..1023 bytes that
won't fly. The internal DMA, of course, can handle many requests and
interrupt only at the end, which would decrease the amount of
interrupts, but that would mean I would have to:

list_for_each_entry(req, &dev->req_list, list) {
	memcpy(req->request.buf + req->request.actual,
		req->bounce_buffer, req->remaining);

	req->request.complete(&req->ep, &req->request);
}

depending on the amount of requests which I have, that'll mean a lot of
time spent handling one IRQ. IMHO, it's much easier - and much better
for most of the other UDC controllers, to have req->length for OUT
transfers to be aligned on ep->maxpacket.

That way, I don't need bounce buffers, I don't need to do any memcpy()
and I only need to iterate over the list of requests and call the
complete() method like it should be.

What I actually need from gadget drivers, for USB3 at least, is for them
to queue as many requests as possible, so the storm of interrupts can
be decreased and we have many buffers to play with.

If we have, e.g. 8 requests for a particular gadget driver, we could
interrupt after every 4 requests so that while HW is handling 4, gadget
driver is processing and recycling the other 4.

BTW, from what I could see, Storage gadget is the only one doesn't
ensure OUT transfers to be aligned on ep->maxpacket, see gadget ether
for instance:

	/* Padding up to RX_EXTRA handles minor disagreements with host.
	 * Normally we use the USB "terminate on short read" convention;
	 * so allow up to (N*maxpacket), since that memory is normally
	 * already allocated.  Some hardware doesn't deal well with short
	 * reads (e.g. DMA must be N*maxpacket), so for now don't trim a
	 * byte off the end (to force hardware errors on overflow).
	 *
	 * RNDIS uses internal framing, and explicitly allows senders to
	 * pad to end-of-packet.  That's potentially nice for speed, but
	 * means receivers can't recover lost synch on their own (because
	 * new packets don't only start after a short RX).
	 */
	size += sizeof(struct ethhdr) + dev->net->mtu + RX_EXTRA;
	size += dev->port_usb->header_len;
	size += out->maxpacket - 1;
	size -= size % out->maxpacket;

the same goes for serial gadget, but that thing queues requests which
are exactly ep->maxpacket:

	for (i = 0; i < n; i++) {
		req = gs_alloc_req(ep, ep->maxpacket, GFP_ATOMIC);
		if (!req)
			return list_empty(head) ? -ENOMEM : 0;
		req->complete = fn;
		list_add_tail(&req->list, head);
		if (allocated)
			(*allocated)++;
	}

same goes for EHCI debug driver:

#define DBGP_REQ_LEN                  512
...

	req->length = DBGP_REQ_LEN;

so IMHO, it's better to keep request->length for OUT transfers aligned
on ep->maxpacket. What do you say ?

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