Re: [RFC/PATCH 2/2] usb: dwc3: gadget: implement SG support

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

 



* Felipe Balbi | 2011-11-22 11:42:06 [+0200]:

>diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
>index c04a0d3..c9bdada 100644
>--- a/drivers/usb/dwc3/gadget.c
>+++ b/drivers/usb/dwc3/gadget.c
>@@ -539,6 +539,83 @@ static void dwc3_gadget_ep_free_request(struct usb_ep *ep,
> 	kfree(req);
> }
> 
>+static int dwc3_gadget_ep_sg_prepare(struct usb_ep *ep,
>+		struct usb_request_sg *rsg, struct scatterlist *sg,
>+		unsigned int num_entries, unsigned int length,
>+		gfp_t gfp_flags)
>+{
>+	struct dwc3_ep		*dep = to_dwc3_ep(ep);
>+	int			ret = -ENOMEM;
>+	int			i;
>+
>+	if (!rsg || !sg || num_entries == 0)
>+		return -EINVAL;
>+
>+	rsg->requests = kcalloc(num_entries, sizeof(*rsg->requests), gfp_flags);
>+	if (!rsg->requests)
>+		goto err0;
>+
>+	for_each_sg(sg, sg, rsg->num_entries, i) {
>+		struct usb_request	*request;
>+		unsigned		len;
>+
>+		request = usb_ep_alloc_request(ep, gfp_flags);
>+		if (!request) {
>+			rsg->num_entries = i;
>+			goto err1;
>+		}
>+
>+		len = length;
>+		if (len == 0) {
>+			struct scatterlist	*sg2;
>+			int			j;
>+
>+			for_each_sg(sg, sg2, num_entries, j)
>+				len += sg2->length;
>+		}

Why do iterate twice in case length is zero? And we do we have multiple
requests with the same size then?

What imagine for sg supportis th follwing: if the udc supports sg we can
queue sg-based requests which have buf = NULL. A request which we
receive could look like: req->length = 8192 and req->num_sgs = 3.
And the sgs are:
sg 1 starts at mem_page_offset + 2048 len 2048
sg 2 starts at mem_page_offset + 0 len 4096
sg 3 starts at mem_page_offset + 0 len 2048

Those three transfers should be part of _one_ request. Therefore you
don't need this no_interrupt field or anything else like that because
you call ->complete() once the whole thing is through. With one struct
usb_request only.

If you queue 2 usb_request struct and the gadget can wait with its
notification after the second is compled, this is another story.

>+
>+		request->no_interrupt = true;
>+		request->buf = NULL;
>+		request->num_sgs = num_entries;
>+
>+		request->length = len;
>+
>+		if (usb_endpoint_dir_in(dep->desc))
>+			request->short_not_ok = true;

Why is this for you to decice? Shouldn't the gadget take care of this?

>+		rsg->requests[i] = request;
>+
>+		/* FIXME allocate a TRB, prepare TRB, set CHN bit, etc */

We have 16 or 32 TRBs waiting. All we need to do prepare then and set
the CHN bit.

>+	}
>+
>+	/* we want interrupt on the last request */
>+	rsg->requests[--i]->no_interrupt = false;
>+
>+	rsg->num_entries = num_entries;
>+	rsg->status = 0;
>+	rsg->actual = 0;
>+
>+	return 0;
>+
>+err1:
>+	kfree(rsg->requests);
>+
>+err0:
>+	return ret;
>+}
>+

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