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

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

 



Add support for SG lists on dwc3 driver.

Signed-off-by: Felipe Balbi <balbi@xxxxxx>
---
 drivers/usb/dwc3/gadget.c |   80 +++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 80 insertions(+), 0 deletions(-)

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;
+		}
+
+		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;
+
+		rsg->requests[i] = request;
+
+		/* FIXME allocate a TRB, prepare TRB, set CHN bit, etc */
+	}
+
+	/* 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;
+}
+
+static int dwc3_gadget_ep_sg_queue(struct usb_ep *ep,
+		struct usb_request_sg *rsg, gfp_t gfp_flags)
+{
+	return 0;
+}
+
+static int dwc3_gadget_ep_sg_dequeue(struct usb_ep *ep,
+		struct usb_request_sg *rsg)
+{
+	return 0;
+}
+
 /*
  * dwc3_prepare_trbs - setup TRBs from requests
  * @dep: endpoint for which requests are being prepared
@@ -976,6 +1053,9 @@ static const struct usb_ep_ops dwc3_gadget_ep_ops = {
 	.disable	= dwc3_gadget_ep_disable,
 	.alloc_request	= dwc3_gadget_ep_alloc_request,
 	.free_request	= dwc3_gadget_ep_free_request,
+	.sg_prepare	= dwc3_gadget_ep_sg_prepare,
+	.sg_queue	= dwc3_gadget_ep_sg_queue,
+	.sg_dequeue	= dwc3_gadget_ep_sg_dequeue,
 	.queue		= dwc3_gadget_ep_queue,
 	.dequeue	= dwc3_gadget_ep_dequeue,
 	.set_halt	= dwc3_gadget_ep_set_halt,
-- 
1.7.8.rc0

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