mail archive of the barebox mailing list
 help / color / mirror / Atom feed
* [PATCH 00/18] EHCI improvements
@ 2019-05-22  7:33 Andrey Smirnov
  2019-05-22  7:33 ` [PATCH 01/18] usb: host: ehci: Do not zero out DMA coherent memory Andrey Smirnov
                   ` (18 more replies)
  0 siblings, 19 replies; 20+ messages in thread
From: Andrey Smirnov @ 2019-05-22  7:33 UTC (permalink / raw)
  To: barebox; +Cc: Andrey Smirnov

Everyone:

This series is a number of improvements (or so I though) I made while
woring with USB on i.MX6. All of the patches are optional, so if some
of the changes don't seem like an improvmement they can be dropped.

Feedback is welcome!

Thanks,
Andrey Smirnov

Andrey Smirnov (18):
  usb: host: ehci: Do not zero out DMA coherent memory
  usb: host: ehci: Share code to enable/disable async schedule
  usb: host: ehci: Use to USBSTS to wait for transfer completion
  usb: host: ehci: Replace magic number with macros
  usb: host: ehci: Drop unnecessary cleanup code
  usb: host: ehci: Introduce ehci_prepare_qtd()
  usb: host: ehci: Simplify qTD buffer synchronization
  usb: host: ehci: Simplify ehci_td_buffer()
  usb: host: ehci: Initialize qTDs explicitly
  usb: host: ehci: Simplify ehci_submit_async()'s epilogue
  usb: host: ehci: Drop needless assignments in ehci_submit_async()
  usb: host: ehci: Use bool to simplify ehci_submit_async()
  usb: host: ehci: Add a comment explaing IOC setting for data
  usb: host: ehci: Replace explicit printf() with dev_err()
  usb: host: ehci: Drop explicit memset() in ehci_init()
  usb: host: ehci: Treat ehci->qh_list as an array
  ush: host: ehci: Simplify QH initialization in ehci_submit_async()
  usb: host: ehci: Allocate only NUM_QH queue heads for qh_list

 drivers/usb/host/ehci-hcd.c | 377 +++++++++++++++++++-----------------
 drivers/usb/host/ehci.h     |  52 +++--
 2 files changed, 242 insertions(+), 187 deletions(-)

-- 
2.21.0


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH 01/18] usb: host: ehci: Do not zero out DMA coherent memory
  2019-05-22  7:33 [PATCH 00/18] EHCI improvements Andrey Smirnov
@ 2019-05-22  7:33 ` Andrey Smirnov
  2019-05-22  7:33 ` [PATCH 02/18] usb: host: ehci: Share code to enable/disable async schedule Andrey Smirnov
                   ` (17 subsequent siblings)
  18 siblings, 0 replies; 20+ messages in thread
From: Andrey Smirnov @ 2019-05-22  7:33 UTC (permalink / raw)
  To: barebox; +Cc: Andrey Smirnov

Memory returned by dma_alloc_coherent() should already be zeroed
out, so there's no need to do this explicitly.

Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
---
 drivers/usb/host/ehci-hcd.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 87af95d2e..54ab32830 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -1069,8 +1069,6 @@ static struct int_queue *ehci_create_int_queue(struct usb_device *dev,
 	result->last = result->first + queuesize - 1;
 	result->tds = dma_alloc_coherent(sizeof(struct qTD) * queuesize,
 					 DMA_ADDRESS_BROKEN);
-	memset(result->first, 0, sizeof(struct QH) * queuesize);
-	memset(result->tds, 0, sizeof(struct qTD) * queuesize);
 
 	for (i = 0; i < queuesize; i++) {
 		struct QH *qh = result->first + i;
-- 
2.21.0


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH 02/18] usb: host: ehci: Share code to enable/disable async schedule
  2019-05-22  7:33 [PATCH 00/18] EHCI improvements Andrey Smirnov
  2019-05-22  7:33 ` [PATCH 01/18] usb: host: ehci: Do not zero out DMA coherent memory Andrey Smirnov
@ 2019-05-22  7:33 ` Andrey Smirnov
  2019-05-22  7:33 ` [PATCH 03/18] usb: host: ehci: Use to USBSTS to wait for transfer completion Andrey Smirnov
                   ` (16 subsequent siblings)
  18 siblings, 0 replies; 20+ messages in thread
From: Andrey Smirnov @ 2019-05-22  7:33 UTC (permalink / raw)
  To: barebox; +Cc: Andrey Smirnov

Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
---
 drivers/usb/host/ehci-hcd.c | 39 +++++++++++++++++++------------------
 1 file changed, 20 insertions(+), 19 deletions(-)

diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 54ab32830..4ccaec743 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -213,6 +213,23 @@ static int ehci_td_buffer(struct qTD *td, void *buf, size_t sz)
 	return 0;
 }
 
+static int ehci_enable_async_schedule(struct ehci_host *ehci, bool enable)
+{
+	uint32_t cmd, done;
+
+	cmd = ehci_readl(&ehci->hcor->or_usbcmd);
+	if (enable) {
+		cmd |= CMD_ASE;
+		done = STD_ASS;
+	} else {
+		cmd &= ~CMD_ASE;
+		done = 0;
+	}
+	ehci_writel(&ehci->hcor->or_usbcmd, cmd);
+
+	return handshake(&ehci->hcor->or_usbsts, STD_ASS, done, 100 * 1000);
+}
+
 static int
 ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
 		   int length, struct devrequest *req, int timeout_ms)
@@ -225,7 +242,6 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
 	uint32_t *tdp;
 	uint32_t endpt, token, usbsts;
 	uint32_t c, toggle;
-	uint32_t cmd;
 	int ret = 0, i;
 	uint64_t start, timeout_val;
 
@@ -353,11 +369,7 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
 	ehci_writel(&ehci->hcor->or_usbsts, (usbsts & 0x3f));
 
 	/* Enable async. schedule. */
-	cmd = ehci_readl(&ehci->hcor->or_usbcmd);
-	cmd |= CMD_ASE;
-	ehci_writel(&ehci->hcor->or_usbcmd, cmd);
-
-	ret = handshake(&ehci->hcor->or_usbsts, STD_ASS, STD_ASS, 100 * 1000);
+	ret = ehci_enable_async_schedule(ehci, true);
 	if (ret < 0) {
 		dev_err(ehci->dev, "fail timeout STD_ASS set\n");
 		goto fail;
@@ -370,12 +382,7 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
 	do {
 		token = hc32_to_cpu(vtd->qt_token);
 		if (is_timeout_non_interruptible(start, timeout_val)) {
-			/* Disable async schedule. */
-			cmd = ehci_readl(&ehci->hcor->or_usbcmd);
-			cmd &= ~CMD_ASE;
-			ehci_writel(&ehci->hcor->or_usbcmd, cmd);
-
-			ret = handshake(&ehci->hcor->or_usbsts, STD_ASS, 0, 100 * 1000);
+			ehci_enable_async_schedule(ehci, false);
 			ehci_writel(&qh->qt_token, 0);
 			return -ETIMEDOUT;
 		}
@@ -391,13 +398,7 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
 		}
 	}
 
-	/* Disable async schedule. */
-	cmd = ehci_readl(&ehci->hcor->or_usbcmd);
-	cmd &= ~CMD_ASE;
-	ehci_writel(&ehci->hcor->or_usbcmd, cmd);
-
-	ret = handshake(&ehci->hcor->or_usbsts, STD_ASS, 0,
-			100 * 1000);
+	ret = ehci_enable_async_schedule(ehci, false);
 	if (ret < 0) {
 		dev_err(ehci->dev, "fail timeout STD_ASS reset\n");
 		goto fail;
-- 
2.21.0


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH 03/18] usb: host: ehci: Use to USBSTS to wait for transfer completion
  2019-05-22  7:33 [PATCH 00/18] EHCI improvements Andrey Smirnov
  2019-05-22  7:33 ` [PATCH 01/18] usb: host: ehci: Do not zero out DMA coherent memory Andrey Smirnov
  2019-05-22  7:33 ` [PATCH 02/18] usb: host: ehci: Share code to enable/disable async schedule Andrey Smirnov
@ 2019-05-22  7:33 ` Andrey Smirnov
  2019-05-22  7:34 ` [PATCH 04/18] usb: host: ehci: Replace magic number with macros Andrey Smirnov
                   ` (15 subsequent siblings)
  18 siblings, 0 replies; 20+ messages in thread
From: Andrey Smirnov @ 2019-05-22  7:33 UTC (permalink / raw)
  To: barebox; +Cc: Andrey Smirnov

Since we already set up our last qTD to have IOC flag set we may as
well take advange of that and poll USBSTS to wait for transfer
completion. Doesn't change much, but allows us to drop a custom
polling loop and re-use handshake() instead.

Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
---
 drivers/usb/host/ehci-hcd.c | 21 +++++++--------------
 drivers/usb/host/ehci.h     |  1 +
 2 files changed, 8 insertions(+), 14 deletions(-)

diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 4ccaec743..0757ea44a 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -238,12 +238,10 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
 	struct ehci_host *ehci = to_ehci(host);
 	struct QH *qh;
 	struct qTD *td;
-	volatile struct qTD *vtd;
 	uint32_t *tdp;
 	uint32_t endpt, token, usbsts;
 	uint32_t c, toggle;
 	int ret = 0, i;
-	uint64_t start, timeout_val;
 
 	dev_dbg(ehci->dev, "pipe=%lx, buffer=%p, length=%d, req=%p\n", pipe,
 	      buffer, length, req);
@@ -375,18 +373,13 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
 		goto fail;
 	}
 
-	/* Wait for TDs to be processed. */
-	timeout_val = timeout_ms * MSECOND;
-	start = get_time_ns();
-	vtd = td;
-	do {
-		token = hc32_to_cpu(vtd->qt_token);
-		if (is_timeout_non_interruptible(start, timeout_val)) {
-			ehci_enable_async_schedule(ehci, false);
-			ehci_writel(&qh->qt_token, 0);
-			return -ETIMEDOUT;
-		}
-	} while (token & 0x80);
+	ret = handshake(&ehci->hcor->or_usbsts, STS_USBINT, STS_USBINT,
+			timeout_ms * 1000);
+	if (ret < 0) {
+		ehci_enable_async_schedule(ehci, false);
+		ehci_writel(&qh->qt_token, 0);
+		return -ETIMEDOUT;
+	}
 
 	if (IS_ENABLED(CONFIG_MMU)) {
 		for (i = 0; i < NUM_TD; i ++) {
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index 39de76374..5b0920d0e 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -62,6 +62,7 @@ struct ehci_hcor {
 #define	STD_ASS		(1 << 15)
 #define STS_PSS         (1 << 14)
 #define STS_HALT	(1 << 12)
+#define STS_USBINT	BIT(0)
 	uint32_t or_usbintr;
 	uint32_t or_frindex;
 	uint32_t or_ctrldssegment;
-- 
2.21.0


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH 04/18] usb: host: ehci: Replace magic number with macros
  2019-05-22  7:33 [PATCH 00/18] EHCI improvements Andrey Smirnov
                   ` (2 preceding siblings ...)
  2019-05-22  7:33 ` [PATCH 03/18] usb: host: ehci: Use to USBSTS to wait for transfer completion Andrey Smirnov
@ 2019-05-22  7:34 ` Andrey Smirnov
  2019-05-22  7:34 ` [PATCH 05/18] usb: host: ehci: Drop unnecessary cleanup code Andrey Smirnov
                   ` (14 subsequent siblings)
  18 siblings, 0 replies; 20+ messages in thread
From: Andrey Smirnov @ 2019-05-22  7:34 UTC (permalink / raw)
  To: barebox; +Cc: Andrey Smirnov

Import a number of missing macros from U-Boot and convert ehci-hcd to
use them instead of explicitly specifying magic shifts. No functional
change intended.

Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
---
 drivers/usb/host/ehci-hcd.c | 96 +++++++++++++++++++++----------------
 drivers/usb/host/ehci.h     | 49 +++++++++++++++----
 2 files changed, 96 insertions(+), 49 deletions(-)

diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 0757ea44a..fadb403a9 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -259,31 +259,33 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
 	qh->qh_link = cpu_to_hc32((uint32_t)ehci->qh_list | QH_LINK_TYPE_QH);
 	c = (dev->speed != USB_SPEED_HIGH &&
 	     usb_pipeendpoint(pipe) == 0) ? 1 : 0;
-	endpt = (8 << 28) |
-	    (c << 27) |
-	    (usb_maxpacket(dev, pipe) << 16) |
-	    (0 << 15) |
-	    (1 << 14) |
-	    (usb_pipeendpoint(pipe) << 8) |
-	    (0 << 7) | (usb_pipedevice(pipe) << 0);
+	endpt = QH_ENDPT1_RL(8) | QH_ENDPT1_C(c) |
+		QH_ENDPT1_MAXPKTLEN(usb_maxpacket(dev, pipe)) |
+		QH_ENDPT1_H(0) |
+		QH_ENDPT1_DTC(QH_ENDPT1_DTC_DT_FROM_QTD) |
+		QH_ENDPT1_ENDPT(usb_pipeendpoint(pipe)) | QH_ENDPT1_I(0) |
+		QH_ENDPT1_DEVADDR(usb_pipedevice(pipe));
+
 	switch (dev->speed) {
 	case USB_SPEED_FULL:
-		endpt |= 0 << 12;
+		endpt |= QH_ENDPT1_EPS(0);
 		break;
 	case USB_SPEED_LOW:
-		endpt |= 1 << 12;
+		endpt |= QH_ENDPT1_EPS(1);
 		break;
 	case USB_SPEED_HIGH:
-		endpt |= 2 << 12;
+		endpt |= QH_ENDPT1_EPS(2);
 		break;
 	default:
 		return -EINVAL;
 	}
 
 	qh->qh_endpt1 = cpu_to_hc32(endpt);
-	endpt = (1 << 30) |
-	    (dev->portnr << 23) |
-	    (dev->parent->devnum << 16) | (0 << 8) | (0 << 0);
+	endpt = QH_ENDPT2_MULT(1) |
+		QH_ENDPT2_PORTNUM(dev->portnr) |
+		QH_ENDPT2_HUBADDR(dev->parent->devnum) |
+		QH_ENDPT2_UFCMASK(0) |
+		QH_ENDPT2_UFSMASK(0);
 	qh->qh_endpt2 = cpu_to_hc32(endpt);
 	qh->qt_next = cpu_to_hc32(QT_NEXT_TERMINATE);
 	qh->qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE);
@@ -299,9 +301,12 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
 
 		td->qt_next = cpu_to_hc32(QT_NEXT_TERMINATE);
 		td->qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE);
-		token = (0 << 31) |
-		    (sizeof(*req) << 16) |
-		    (0 << 15) | (0 << 12) | (3 << 10) | (2 << 8) | (0x80 << 0);
+		token = QT_TOKEN_DT(0) |
+			QT_TOKEN_TOTALBYTES(sizeof(*req)) |
+			QT_TOKEN_IOC(0) |
+			QT_TOKEN_CPAGE(0) | QT_TOKEN_CERR(3) |
+			QT_TOKEN_PID(QT_TOKEN_PID_SETUP) |
+			QT_TOKEN_STATUS(QT_TOKEN_STATUS_ACTIVE);
 		td->qt_token = cpu_to_hc32(token);
 		if (ehci_td_buffer(td, req, sizeof(*req)) != 0) {
 			dev_dbg(ehci->dev, "unable construct SETUP td\n");
@@ -318,12 +323,13 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
 
 		td->qt_next = cpu_to_hc32(QT_NEXT_TERMINATE);
 		td->qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE);
-		token = (toggle << 31) |
-		    (length << 16) |
-		    ((req == NULL ? 1 : 0) << 15) |
-		    (0 << 12) |
-		    (3 << 10) |
-		    ((usb_pipein(pipe) ? 1 : 0) << 8) | (0x80 << 0);
+		token = QT_TOKEN_DT(toggle) |
+			QT_TOKEN_TOTALBYTES(length) |
+			QT_TOKEN_IOC(req == NULL) |
+			QT_TOKEN_CPAGE(0) | QT_TOKEN_CERR(3) |
+			QT_TOKEN_PID(usb_pipein(pipe) ?
+				     QT_TOKEN_PID_IN : QT_TOKEN_PID_OUT) |
+			QT_TOKEN_STATUS(QT_TOKEN_STATUS_ACTIVE);
 		td->qt_token = cpu_to_hc32(token);
 		if (ehci_td_buffer(td, buffer, length) != 0) {
 			dev_err(ehci->dev, "unable construct DATA td\n");
@@ -338,12 +344,13 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
 
 		td->qt_next = cpu_to_hc32(QT_NEXT_TERMINATE);
 		td->qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE);
-		token = (toggle << 31) |
-		    (0 << 16) |
-		    (1 << 15) |
-		    (0 << 12) |
-		    (3 << 10) |
-		    ((usb_pipein(pipe) ? 0 : 1) << 8) | (0x80 << 0);
+		token = QT_TOKEN_DT(1) |
+			QT_TOKEN_TOTALBYTES(0) |
+			QT_TOKEN_IOC(1) |
+			QT_TOKEN_CPAGE(0) | QT_TOKEN_CERR(3) |
+			QT_TOKEN_PID(usb_pipein(pipe) ?
+				     QT_TOKEN_PID_OUT : QT_TOKEN_PID_IN) |
+			QT_TOKEN_STATUS(QT_TOKEN_STATUS_ACTIVE);
 		td->qt_token = cpu_to_hc32(token);
 		*tdp = cpu_to_hc32((uint32_t)td);
 		tdp = &td->qt_next;
@@ -400,33 +407,41 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
 	ehci->qh_list->qh_link = cpu_to_hc32((uint32_t)ehci->qh_list | QH_LINK_TYPE_QH);
 
 	token = hc32_to_cpu(qh->qt_token);
-	if (!(token & 0x80)) {
+	if (!(token & QT_TOKEN_STATUS_ACTIVE)) {
+		uint32_t status;
+
 		dev_dbg(ehci->dev, "TOKEN=0x%08x\n", token);
-		switch (token & 0xfc) {
+
+		status = QT_TOKEN_GET_STATUS(token);
+		status &= ~(QT_TOKEN_STATUS_SPLITXSTATE |
+			    QT_TOKEN_STATUS_PERR);
+
+		switch (status) {
 		case 0:
-			toggle = token >> 31;
+			toggle = QT_TOKEN_GET_DT(token);
 			usb_settoggle(dev, usb_pipeendpoint(pipe),
 				       usb_pipeout(pipe), toggle);
 			dev->status = 0;
 			break;
-		case 0x40:
+		case QT_TOKEN_STATUS_HALTED:
 			dev->status = USB_ST_STALLED;
 			break;
-		case 0xa0:
-		case 0x20:
+		case QT_TOKEN_STATUS_ACTIVE | QT_TOKEN_STATUS_DATBUFERR:
+		case QT_TOKEN_STATUS_DATBUFERR:
 			dev->status = USB_ST_BUF_ERR;
 			break;
-		case 0x50:
-		case 0x10:
+		case QT_TOKEN_STATUS_HALTED | QT_TOKEN_STATUS_BABBLEDET:
+		case QT_TOKEN_STATUS_BABBLEDET:
 			dev->status = USB_ST_BABBLE_DET;
 			break;
 		default:
 			dev->status = USB_ST_CRC_ERR;
-			if ((token & 0x40) == 0x40)
+			if (status & QT_TOKEN_STATUS_HALTED)
 				dev->status |= USB_ST_STALLED;
+
 			break;
 		}
-		dev->act_len = length - ((token >> 16) & 0x7fff);
+		dev->act_len = length - QT_TOKEN_GET_TOTALBYTES(token);
 	} else {
 		dev->act_len = 0;
 		dev_dbg(ehci->dev, "dev=%u, usbsts=%#x, p[1]=%#x, p[2]=%#x\n",
@@ -808,11 +823,12 @@ static int ehci_init(struct usb_host *host)
 	memset(ehci->qh_list, 0, sizeof(struct QH) * NUM_TD);
 
 	ehci->qh_list->qh_link = cpu_to_hc32((uint32_t)ehci->qh_list | QH_LINK_TYPE_QH);
-	ehci->qh_list->qh_endpt1 = cpu_to_hc32((1 << 15) | (USB_SPEED_HIGH << 12));
+	ehci->qh_list->qh_endpt1 = cpu_to_hc32(QH_ENDPT1_H(1) |
+					       QH_ENDPT1_EPS(USB_SPEED_HIGH));
 	ehci->qh_list->qh_curtd = cpu_to_hc32(QT_NEXT_TERMINATE);
 	ehci->qh_list->qt_next = cpu_to_hc32(QT_NEXT_TERMINATE);
 	ehci->qh_list->qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE);
-	ehci->qh_list->qt_token = cpu_to_hc32(0x40);
+	ehci->qh_list->qt_token = cpu_to_hc32(QT_TOKEN_STATUS_HALTED);
 
 	/* Set async. queue head pointer. */
 	ehci_writel(&ehci->hcor->or_asynclistaddr, (uint32_t)ehci->qh_list);
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index 5b0920d0e..f82b6a0d1 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -20,15 +20,6 @@
 
 #include <io.h>
 
-#define QH_ENDPT1_EPS(x)	(((x) & 0x3) << 12)	/* Endpoint Speed */
-#define QH_ENDPT2_PORTNUM(x)	(((x) & 0x7f) << 23)	/* Port Number */
-#define QH_ENDPT2_HUBADDR(x)	(((x) & 0x7f) << 16)	/* Hub Address */
-
-#define QT_TOKEN_DT(x)		(((x) & 0x1) << 31)	/* Data Toggle */
-#define QT_TOKEN_GET_STATUS(x)	(((x) >> 0) & 0xff)
-#define QT_TOKEN_STATUS_ACTIVE	0x80
-#define QT_TOKEN_GET_DT(x)	(((x) >> 31) & 0x1)
-
 #if !defined(CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS)
 #define CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS	16
 #endif
@@ -134,6 +125,27 @@ struct qTD {
 #define	QT_NEXT_TERMINATE	1
 	uint32_t qt_altnext;
 	uint32_t qt_token;
+#define QT_TOKEN_DT(x)		(((x) & 0x1) << 31)	/* Data Toggle */
+#define QT_TOKEN_GET_DT(x)		(((x) >> 31) & 0x1)
+#define QT_TOKEN_TOTALBYTES(x)	(((x) & 0x7fff) << 16)	/* Total Bytes to Transfer */
+#define QT_TOKEN_GET_TOTALBYTES(x)	(((x) >> 16) & 0x7fff)
+#define QT_TOKEN_IOC(x)		(((x) & 0x1) << 15)	/* Interrupt On Complete */
+#define QT_TOKEN_CPAGE(x)	(((x) & 0x7) << 12)	/* Current Page */
+#define QT_TOKEN_CERR(x)	(((x) & 0x3) << 10)	/* Error Counter */
+#define QT_TOKEN_PID(x)		(((x) & 0x3) << 8)	/* PID Code */
+#define QT_TOKEN_PID_OUT		0x0
+#define QT_TOKEN_PID_IN			0x1
+#define QT_TOKEN_PID_SETUP		0x2
+#define QT_TOKEN_STATUS(x)	(((x) & 0xff) << 0)	/* Status */
+#define QT_TOKEN_GET_STATUS(x)		(((x) >> 0) & 0xff)
+#define QT_TOKEN_STATUS_ACTIVE		0x80
+#define QT_TOKEN_STATUS_HALTED		0x40
+#define QT_TOKEN_STATUS_DATBUFERR	0x20
+#define QT_TOKEN_STATUS_BABBLEDET	0x10
+#define QT_TOKEN_STATUS_XACTERR		0x08
+#define QT_TOKEN_STATUS_MISSEDUFRAME	0x04
+#define QT_TOKEN_STATUS_SPLITXSTATE	0x02
+#define QT_TOKEN_STATUS_PERR		0x01
 	uint32_t qt_buffer[5];
 	unsigned long qtd_dma;
 	size_t length;
@@ -148,7 +160,26 @@ struct QH {
 #define	QH_LINK_TYPE_SITD	4
 #define	QH_LINK_TYPE_FSTN	6
 	uint32_t qh_endpt1;
+#define QH_ENDPT1_RL(x)		(((x) & 0xf) << 28)	/* NAK Count Reload */
+#define QH_ENDPT1_C(x)		(((x) & 0x1) << 27)	/* Control Endpoint Flag */
+#define QH_ENDPT1_MAXPKTLEN(x)	(((x) & 0x7ff) << 16)	/* Maximum Packet Length */
+#define QH_ENDPT1_H(x)		(((x) & 0x1) << 15)	/* Head of Reclamation List Flag */
+#define QH_ENDPT1_DTC(x)	(((x) & 0x1) << 14)	/* Data Toggle Control */
+#define QH_ENDPT1_DTC_IGNORE_QTD_TD	0x0
+#define QH_ENDPT1_DTC_DT_FROM_QTD	0x1
+#define QH_ENDPT1_EPS(x)	(((x) & 0x3) << 12)	/* Endpoint Speed */
+#define QH_ENDPT1_EPS_FS		0x0
+#define QH_ENDPT1_EPS_LS		0x1
+#define QH_ENDPT1_EPS_HS		0x2
+#define QH_ENDPT1_ENDPT(x)	(((x) & 0xf) << 8)	/* Endpoint Number */
+#define QH_ENDPT1_I(x)		(((x) & 0x1) << 7)	/* Inactivate on Next Transaction */
+#define QH_ENDPT1_DEVADDR(x)	(((x) & 0x7f) << 0)	/* Device Address */
 	uint32_t qh_endpt2;
+#define QH_ENDPT2_MULT(x)	(((x) & 0x3) << 30)	/* High-Bandwidth Pipe Multiplier */
+#define QH_ENDPT2_PORTNUM(x)	(((x) & 0x7f) << 23)	/* Port Number */
+#define QH_ENDPT2_HUBADDR(x)	(((x) & 0x7f) << 16)	/* Hub Address */
+#define QH_ENDPT2_UFCMASK(x)	(((x) & 0xff) << 8)	/* Split Completion Mask */
+#define QH_ENDPT2_UFSMASK(x)	(((x) & 0xff) << 0)	/* Interrupt Schedule Mask */
 	uint32_t qh_curtd;
 	 /* qtd overlay (hardware parts of a struct qTD) */
 	uint32_t qt_next;
-- 
2.21.0


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH 05/18] usb: host: ehci: Drop unnecessary cleanup code
  2019-05-22  7:33 [PATCH 00/18] EHCI improvements Andrey Smirnov
                   ` (3 preceding siblings ...)
  2019-05-22  7:34 ` [PATCH 04/18] usb: host: ehci: Replace magic number with macros Andrey Smirnov
@ 2019-05-22  7:34 ` Andrey Smirnov
  2019-05-22  7:34 ` [PATCH 06/18] usb: host: ehci: Introduce ehci_prepare_qtd() Andrey Smirnov
                   ` (13 subsequent siblings)
  18 siblings, 0 replies; 20+ messages in thread
From: Andrey Smirnov @ 2019-05-22  7:34 UTC (permalink / raw)
  To: barebox; +Cc: Andrey Smirnov

This looks like a leftover from U-Boot. Analogous code there would
walk all qTDs and call ehci_free() on each one of them, but since we
don't have anything of the sort it seems the whole loop can be
dropped. Note that U-Boot dropped that code in
de98e8b22a10676fd226318c92a9be7f519208ca

Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
---
 drivers/usb/host/ehci-hcd.c | 23 ++++++++---------------
 1 file changed, 8 insertions(+), 15 deletions(-)

diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index fadb403a9..be875d402 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -308,9 +308,10 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
 			QT_TOKEN_PID(QT_TOKEN_PID_SETUP) |
 			QT_TOKEN_STATUS(QT_TOKEN_STATUS_ACTIVE);
 		td->qt_token = cpu_to_hc32(token);
-		if (ehci_td_buffer(td, req, sizeof(*req)) != 0) {
+		ret = ehci_td_buffer(td, req, sizeof(*req));
+		if (ret) {
 			dev_dbg(ehci->dev, "unable construct SETUP td\n");
-			goto fail;
+			return ret;
 		}
 		*tdp = cpu_to_hc32((uint32_t) td);
 		tdp = &td->qt_next;
@@ -331,9 +332,10 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
 				     QT_TOKEN_PID_IN : QT_TOKEN_PID_OUT) |
 			QT_TOKEN_STATUS(QT_TOKEN_STATUS_ACTIVE);
 		td->qt_token = cpu_to_hc32(token);
-		if (ehci_td_buffer(td, buffer, length) != 0) {
+		ret = ehci_td_buffer(td, buffer, length);
+		if (ret) {
 			dev_err(ehci->dev, "unable construct DATA td\n");
-			goto fail;
+			return ret;
 		}
 		*tdp = cpu_to_hc32((uint32_t) td);
 		tdp = &td->qt_next;
@@ -377,7 +379,7 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
 	ret = ehci_enable_async_schedule(ehci, true);
 	if (ret < 0) {
 		dev_err(ehci->dev, "fail timeout STD_ASS set\n");
-		goto fail;
+		return ret;
 	}
 
 	ret = handshake(&ehci->hcor->or_usbsts, STS_USBINT, STS_USBINT,
@@ -401,7 +403,7 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
 	ret = ehci_enable_async_schedule(ehci, false);
 	if (ret < 0) {
 		dev_err(ehci->dev, "fail timeout STD_ASS reset\n");
-		goto fail;
+		return ret;
 	}
 
 	ehci->qh_list->qh_link = cpu_to_hc32((uint32_t)ehci->qh_list | QH_LINK_TYPE_QH);
@@ -451,15 +453,6 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
 	}
 
 	return (dev->status != USB_ST_NOT_PROC) ? 0 : -1;
-
-fail:
-	dev_err(ehci->dev, "fail1\n");
-	td = (void *)hc32_to_cpu(qh->qt_next);
-	while (td != (void *)QT_NEXT_TERMINATE) {
-		qh->qt_next = td->qt_next;
-		td = (void *)hc32_to_cpu(qh->qt_next);
-	}
-	return -1;
 }
 
 #if defined(CONFIG_MACH_EFIKA_MX_SMARTBOOK) && defined(CONFIG_USB_ULPI)
-- 
2.21.0


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH 06/18] usb: host: ehci: Introduce ehci_prepare_qtd()
  2019-05-22  7:33 [PATCH 00/18] EHCI improvements Andrey Smirnov
                   ` (4 preceding siblings ...)
  2019-05-22  7:34 ` [PATCH 05/18] usb: host: ehci: Drop unnecessary cleanup code Andrey Smirnov
@ 2019-05-22  7:34 ` Andrey Smirnov
  2019-05-22  7:34 ` [PATCH 07/18] usb: host: ehci: Simplify qTD buffer synchronization Andrey Smirnov
                   ` (12 subsequent siblings)
  18 siblings, 0 replies; 20+ messages in thread
From: Andrey Smirnov @ 2019-05-22  7:34 UTC (permalink / raw)
  To: barebox; +Cc: Andrey Smirnov

Move shared struct qTD initialization code into a subroutine and
convert the rest of the code to use it. No functional change intended.

Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
---
 drivers/usb/host/ehci-hcd.c | 66 ++++++++++++++++++++-----------------
 1 file changed, 35 insertions(+), 31 deletions(-)

diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index be875d402..ad244637e 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -213,6 +213,27 @@ static int ehci_td_buffer(struct qTD *td, void *buf, size_t sz)
 	return 0;
 }
 
+static int ehci_prepare_qtd(struct qTD *td, uint32_t token,
+			    void *buffer, size_t length)
+{
+	int ret;
+
+	td->qt_next = cpu_to_hc32(QT_NEXT_TERMINATE);
+	td->qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE);
+	token |= QT_TOKEN_TOTALBYTES(length) |
+		QT_TOKEN_CPAGE(0) | QT_TOKEN_CERR(3) |
+		QT_TOKEN_STATUS(QT_TOKEN_STATUS_ACTIVE);
+	td->qt_token = cpu_to_hc32(token);
+
+	if (length) {
+		ret = ehci_td_buffer(td, buffer, length);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
 static int ehci_enable_async_schedule(struct ehci_host *ehci, bool enable)
 {
 	uint32_t cmd, done;
@@ -299,16 +320,9 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
 	if (req != NULL) {
 		td = &ehci->td[0];
 
-		td->qt_next = cpu_to_hc32(QT_NEXT_TERMINATE);
-		td->qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE);
-		token = QT_TOKEN_DT(0) |
-			QT_TOKEN_TOTALBYTES(sizeof(*req)) |
-			QT_TOKEN_IOC(0) |
-			QT_TOKEN_CPAGE(0) | QT_TOKEN_CERR(3) |
-			QT_TOKEN_PID(QT_TOKEN_PID_SETUP) |
-			QT_TOKEN_STATUS(QT_TOKEN_STATUS_ACTIVE);
-		td->qt_token = cpu_to_hc32(token);
-		ret = ehci_td_buffer(td, req, sizeof(*req));
+		ret = ehci_prepare_qtd(td, QT_TOKEN_DT(0) | QT_TOKEN_IOC(0) |
+				       QT_TOKEN_PID(QT_TOKEN_PID_SETUP),
+				       req, sizeof(*req));
 		if (ret) {
 			dev_dbg(ehci->dev, "unable construct SETUP td\n");
 			return ret;
@@ -322,17 +336,12 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
 	if (length > 0 || req == NULL) {
 		td = &ehci->td[1];
 
-		td->qt_next = cpu_to_hc32(QT_NEXT_TERMINATE);
-		td->qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE);
-		token = QT_TOKEN_DT(toggle) |
-			QT_TOKEN_TOTALBYTES(length) |
-			QT_TOKEN_IOC(req == NULL) |
-			QT_TOKEN_CPAGE(0) | QT_TOKEN_CERR(3) |
-			QT_TOKEN_PID(usb_pipein(pipe) ?
-				     QT_TOKEN_PID_IN : QT_TOKEN_PID_OUT) |
-			QT_TOKEN_STATUS(QT_TOKEN_STATUS_ACTIVE);
-		td->qt_token = cpu_to_hc32(token);
-		ret = ehci_td_buffer(td, buffer, length);
+		ret = ehci_prepare_qtd(td, QT_TOKEN_DT(toggle) |
+				       QT_TOKEN_IOC(req == NULL) |
+				       QT_TOKEN_PID(usb_pipein(pipe) ?
+						    QT_TOKEN_PID_IN :
+						    QT_TOKEN_PID_OUT),
+				       buffer, length);
 		if (ret) {
 			dev_err(ehci->dev, "unable construct DATA td\n");
 			return ret;
@@ -344,16 +353,11 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
 	if (req) {
 		td = &ehci->td[2];
 
-		td->qt_next = cpu_to_hc32(QT_NEXT_TERMINATE);
-		td->qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE);
-		token = QT_TOKEN_DT(1) |
-			QT_TOKEN_TOTALBYTES(0) |
-			QT_TOKEN_IOC(1) |
-			QT_TOKEN_CPAGE(0) | QT_TOKEN_CERR(3) |
-			QT_TOKEN_PID(usb_pipein(pipe) ?
-				     QT_TOKEN_PID_OUT : QT_TOKEN_PID_IN) |
-			QT_TOKEN_STATUS(QT_TOKEN_STATUS_ACTIVE);
-		td->qt_token = cpu_to_hc32(token);
+		ehci_prepare_qtd(td, QT_TOKEN_DT(1) | QT_TOKEN_IOC(1) |
+				 QT_TOKEN_PID(usb_pipein(pipe) ?
+					      QT_TOKEN_PID_OUT :
+					      QT_TOKEN_PID_IN),
+				 NULL, 0);
 		*tdp = cpu_to_hc32((uint32_t)td);
 		tdp = &td->qt_next;
 	}
-- 
2.21.0


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH 07/18] usb: host: ehci: Simplify qTD buffer synchronization
  2019-05-22  7:33 [PATCH 00/18] EHCI improvements Andrey Smirnov
                   ` (5 preceding siblings ...)
  2019-05-22  7:34 ` [PATCH 06/18] usb: host: ehci: Introduce ehci_prepare_qtd() Andrey Smirnov
@ 2019-05-22  7:34 ` Andrey Smirnov
  2019-05-22  7:34 ` [PATCH 08/18] usb: host: ehci: Simplify ehci_td_buffer() Andrey Smirnov
                   ` (11 subsequent siblings)
  18 siblings, 0 replies; 20+ messages in thread
From: Andrey Smirnov @ 2019-05-22  7:34 UTC (permalink / raw)
  To: barebox; +Cc: Andrey Smirnov

Only two buffers ever need to be sychronized and DMA direction of it
is always known based on the type of request we are
processing. Simplify the code by moving synchronization to be a part
of ehci_prepare_qtd(). While at it convert the code to use
dma_map_single() API.

Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
---
 drivers/usb/host/ehci-hcd.c | 90 ++++++++++++++++++++-----------------
 drivers/usb/host/ehci.h     |  2 -
 2 files changed, 49 insertions(+), 43 deletions(-)

diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index ad244637e..9758e1ed7 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -184,15 +184,11 @@ out:
 	return ret;
 }
 
-static int ehci_td_buffer(struct qTD *td, void *buf, size_t sz)
+static int ehci_td_buffer(struct qTD *td, dma_addr_t addr, size_t sz)
 {
-	uint32_t addr, delta, next;
+	uint32_t delta, next;
 	int idx;
 
-	addr = (uint32_t) buf;
-	td->qtd_dma = addr;
-	td->length = sz;
-
 	idx = 0;
 	while (idx < 5) {
 		td->qt_buffer[idx] = cpu_to_hc32(addr);
@@ -213,8 +209,11 @@ static int ehci_td_buffer(struct qTD *td, void *buf, size_t sz)
 	return 0;
 }
 
-static int ehci_prepare_qtd(struct qTD *td, uint32_t token,
-			    void *buffer, size_t length)
+static int ehci_prepare_qtd(struct device_d *dev,
+			    struct qTD *td, uint32_t token,
+			    void *buffer, size_t length,
+			    dma_addr_t *buffer_dma,
+			    enum dma_data_direction dma_direction)
 {
 	int ret;
 
@@ -226,7 +225,12 @@ static int ehci_prepare_qtd(struct qTD *td, uint32_t token,
 	td->qt_token = cpu_to_hc32(token);
 
 	if (length) {
-		ret = ehci_td_buffer(td, buffer, length);
+		*buffer_dma = dma_map_single(dev, buffer, length,
+					     dma_direction);
+		if (dma_mapping_error(dev, *buffer_dma))
+			return -EFAULT;
+
+		ret = ehci_td_buffer(td, *buffer_dma, length);
 		if (ret)
 			return ret;
 	}
@@ -257,12 +261,15 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
 {
 	struct usb_host *host = dev->host;
 	struct ehci_host *ehci = to_ehci(host);
+	const bool dir_in = usb_pipein(pipe);
+	dma_addr_t buffer_dma, req_dma;
 	struct QH *qh;
 	struct qTD *td;
 	uint32_t *tdp;
 	uint32_t endpt, token, usbsts;
 	uint32_t c, toggle;
-	int ret = 0, i;
+	int ret = 0;
+
 
 	dev_dbg(ehci->dev, "pipe=%lx, buffer=%p, length=%d, req=%p\n", pipe,
 	      buffer, length, req);
@@ -320,9 +327,11 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
 	if (req != NULL) {
 		td = &ehci->td[0];
 
-		ret = ehci_prepare_qtd(td, QT_TOKEN_DT(0) | QT_TOKEN_IOC(0) |
+		ret = ehci_prepare_qtd(ehci->dev,
+				       td, QT_TOKEN_DT(0) | QT_TOKEN_IOC(0) |
 				       QT_TOKEN_PID(QT_TOKEN_PID_SETUP),
-				       req, sizeof(*req));
+				       req, sizeof(*req),
+				       &req_dma, DMA_TO_DEVICE);
 		if (ret) {
 			dev_dbg(ehci->dev, "unable construct SETUP td\n");
 			return ret;
@@ -334,14 +343,25 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
 	}
 
 	if (length > 0 || req == NULL) {
+		enum dma_data_direction dir;
+		unsigned int pid;
+
 		td = &ehci->td[1];
 
-		ret = ehci_prepare_qtd(td, QT_TOKEN_DT(toggle) |
+		if (dir_in) {
+			dir = DMA_FROM_DEVICE;
+			pid = QT_TOKEN_PID_IN;
+		} else {
+			dir = DMA_TO_DEVICE;
+			pid = QT_TOKEN_PID_OUT;
+		}
+
+		ret = ehci_prepare_qtd(ehci->dev,
+				       td, QT_TOKEN_DT(toggle) |
 				       QT_TOKEN_IOC(req == NULL) |
-				       QT_TOKEN_PID(usb_pipein(pipe) ?
-						    QT_TOKEN_PID_IN :
-						    QT_TOKEN_PID_OUT),
-				       buffer, length);
+				       QT_TOKEN_PID(pid),
+				       buffer, length,
+				       &buffer_dma, dir);
 		if (ret) {
 			dev_err(ehci->dev, "unable construct DATA td\n");
 			return ret;
@@ -353,29 +373,19 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
 	if (req) {
 		td = &ehci->td[2];
 
-		ehci_prepare_qtd(td, QT_TOKEN_DT(1) | QT_TOKEN_IOC(1) |
-				 QT_TOKEN_PID(usb_pipein(pipe) ?
+		ehci_prepare_qtd(ehci->dev,
+				 td, QT_TOKEN_DT(1) | QT_TOKEN_IOC(1) |
+				 QT_TOKEN_PID(dir_in ?
 					      QT_TOKEN_PID_OUT :
 					      QT_TOKEN_PID_IN),
-				 NULL, 0);
+				 NULL, 0,
+				 NULL, DMA_NONE);
 		*tdp = cpu_to_hc32((uint32_t)td);
 		tdp = &td->qt_next;
 	}
 
 	ehci->qh_list->qh_link = cpu_to_hc32((uint32_t) qh | QH_LINK_TYPE_QH);
 
-	/* Flush dcache */
-	if (IS_ENABLED(CONFIG_MMU)) {
-		for (i = 0; i < NUM_TD; i ++) {
-			struct qTD *qtd = &ehci->td[i];
-			if (!qtd->qtd_dma)
-				continue;
-			dma_sync_single_for_device((unsigned long)qtd->qtd_dma,
-						   qtd->length,
-						   DMA_BIDIRECTIONAL);
-		}
-	}
-
 	usbsts = ehci_readl(&ehci->hcor->or_usbsts);
 	ehci_writel(&ehci->hcor->or_usbsts, (usbsts & 0x3f));
 
@@ -394,15 +404,13 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
 		return -ETIMEDOUT;
 	}
 
-	if (IS_ENABLED(CONFIG_MMU)) {
-		for (i = 0; i < NUM_TD; i ++) {
-			struct qTD *qtd = &ehci->td[i];
-			if (!qtd->qtd_dma)
-				continue;
-			dma_sync_single_for_cpu((unsigned long)qtd->qtd_dma,
-						qtd->length, DMA_BIDIRECTIONAL);
-		}
-	}
+	if (req)
+		dma_unmap_single(ehci->dev, req_dma, sizeof(*req),
+				 DMA_TO_DEVICE);
+
+	if (length)
+		dma_unmap_single(ehci->dev, buffer_dma, length,
+				 dir_in ? DMA_FROM_DEVICE : DMA_TO_DEVICE);
 
 	ret = ehci_enable_async_schedule(ehci, false);
 	if (ret < 0) {
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index f82b6a0d1..e88e37e14 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -147,8 +147,6 @@ struct qTD {
 #define QT_TOKEN_STATUS_SPLITXSTATE	0x02
 #define QT_TOKEN_STATUS_PERR		0x01
 	uint32_t qt_buffer[5];
-	unsigned long qtd_dma;
-	size_t length;
 } __attribute__ ((aligned (32)));
 
 /* Queue Head (QH). */
-- 
2.21.0


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH 08/18] usb: host: ehci: Simplify ehci_td_buffer()
  2019-05-22  7:33 [PATCH 00/18] EHCI improvements Andrey Smirnov
                   ` (6 preceding siblings ...)
  2019-05-22  7:34 ` [PATCH 07/18] usb: host: ehci: Simplify qTD buffer synchronization Andrey Smirnov
@ 2019-05-22  7:34 ` Andrey Smirnov
  2019-05-22  7:34 ` [PATCH 09/18] usb: host: ehci: Initialize qTDs explicitly Andrey Smirnov
                   ` (10 subsequent siblings)
  18 siblings, 0 replies; 20+ messages in thread
From: Andrey Smirnov @ 2019-05-22  7:34 UTC (permalink / raw)
  To: barebox; +Cc: Andrey Smirnov

Rework the code of ehci_td_buffer() with following trivial changes:

    * Switch to using dma_addr_t for 'delta' and 'next'
    * Convert while to for loop
    * Replace explicit magic number with dedicated contants derived
      via ARRAY_SIZE
    * Use ALIGN_DOWN to calculate 'next'
    * Return -ENOMEM instead of -1 when we ran out of buffers

Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
---
 drivers/usb/host/ehci-hcd.c | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 9758e1ed7..6742a67de 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -31,6 +31,7 @@
 #include <of.h>
 #include <usb/ehci.h>
 #include <linux/err.h>
+#include <linux/sizes.h>
 
 #include "ehci.h"
 
@@ -186,24 +187,23 @@ out:
 
 static int ehci_td_buffer(struct qTD *td, dma_addr_t addr, size_t sz)
 {
-	uint32_t delta, next;
+	const size_t buffer_count = ARRAY_SIZE(td->qt_buffer);
+	dma_addr_t delta, next;
 	int idx;
 
-	idx = 0;
-	while (idx < 5) {
+	for (idx = 0; idx < buffer_count; idx++) {
 		td->qt_buffer[idx] = cpu_to_hc32(addr);
-		next = (addr + 4096) & ~4095;
+		next = ALIGN_DOWN(addr + SZ_4K, SZ_4K);
 		delta = next - addr;
 		if (delta >= sz)
 			break;
 		sz -= delta;
 		addr = next;
-		idx++;
 	}
 
-	if (idx == 5) {
+	if (idx == buffer_count) {
 		pr_debug("out of buffer pointers (%u bytes left)\n", sz);
-		return -1;
+		return -ENOMEM;
 	}
 
 	return 0;
-- 
2.21.0


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH 09/18] usb: host: ehci: Initialize qTDs explicitly
  2019-05-22  7:33 [PATCH 00/18] EHCI improvements Andrey Smirnov
                   ` (7 preceding siblings ...)
  2019-05-22  7:34 ` [PATCH 08/18] usb: host: ehci: Simplify ehci_td_buffer() Andrey Smirnov
@ 2019-05-22  7:34 ` Andrey Smirnov
  2019-05-22  7:34 ` [PATCH 10/18] usb: host: ehci: Simplify ehci_submit_async()'s epilogue Andrey Smirnov
                   ` (9 subsequent siblings)
  18 siblings, 0 replies; 20+ messages in thread
From: Andrey Smirnov @ 2019-05-22  7:34 UTC (permalink / raw)
  To: barebox; +Cc: Andrey Smirnov

Convert the code to initialize only used qTDs as well as initializing
all of the fields explicitly without doing a wholesale memset() first.

Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
---
 drivers/usb/host/ehci-hcd.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 6742a67de..2b890cbc9 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -206,6 +206,9 @@ static int ehci_td_buffer(struct qTD *td, dma_addr_t addr, size_t sz)
 		return -ENOMEM;
 	}
 
+	for (idx++; idx < buffer_count; idx++)
+		td->qt_buffer[idx] = 0;
+
 	return 0;
 }
 
@@ -233,6 +236,8 @@ static int ehci_prepare_qtd(struct device_d *dev,
 		ret = ehci_td_buffer(td, *buffer_dma, length);
 		if (ret)
 			return ret;
+	} else {
+		memset(td->qt_buffer, 0, sizeof(td->qt_buffer));
 	}
 
 	return 0;
@@ -281,7 +286,6 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
 		      le16_to_cpu(req->index));
 
 	memset(&ehci->qh_list[1], 0, sizeof(struct QH));
-	memset(ehci->td, 0, sizeof(struct qTD) * NUM_TD);
 
 	qh = &ehci->qh_list[1];
 	qh->qh_link = cpu_to_hc32((uint32_t)ehci->qh_list | QH_LINK_TYPE_QH);
-- 
2.21.0


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH 10/18] usb: host: ehci: Simplify ehci_submit_async()'s epilogue
  2019-05-22  7:33 [PATCH 00/18] EHCI improvements Andrey Smirnov
                   ` (8 preceding siblings ...)
  2019-05-22  7:34 ` [PATCH 09/18] usb: host: ehci: Initialize qTDs explicitly Andrey Smirnov
@ 2019-05-22  7:34 ` Andrey Smirnov
  2019-05-22  7:34 ` [PATCH 11/18] usb: host: ehci: Drop needless assignments in ehci_submit_async() Andrey Smirnov
                   ` (8 subsequent siblings)
  18 siblings, 0 replies; 20+ messages in thread
From: Andrey Smirnov @ 2019-05-22  7:34 UTC (permalink / raw)
  To: barebox; +Cc: Andrey Smirnov

Re-organize the epilogue of ehci_submit_async() to bail out early if
token is still marked as "active" and drop no longer necessary check
for "dev->status != USB_ST_NOT_PROC". While at it return -EIO instead
of -1 in the case of error.

Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
---
 drivers/usb/host/ehci-hcd.c | 76 ++++++++++++++++++-------------------
 1 file changed, 38 insertions(+), 38 deletions(-)

diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 2b890cbc9..7194a48c0 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -272,6 +272,7 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
 	struct qTD *td;
 	uint32_t *tdp;
 	uint32_t endpt, token, usbsts;
+	uint32_t status;
 	uint32_t c, toggle;
 	int ret = 0;
 
@@ -425,50 +426,49 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
 	ehci->qh_list->qh_link = cpu_to_hc32((uint32_t)ehci->qh_list | QH_LINK_TYPE_QH);
 
 	token = hc32_to_cpu(qh->qt_token);
-	if (!(token & QT_TOKEN_STATUS_ACTIVE)) {
-		uint32_t status;
+	if (token & QT_TOKEN_STATUS_ACTIVE) {
+		dev->act_len = 0;
+		dev_dbg(ehci->dev, "dev=%u, usbsts=%#x, p[1]=%#x, p[2]=%#x\n",
+			dev->devnum, ehci_readl(&ehci->hcor->or_usbsts),
+			ehci_readl(&ehci->hcor->or_portsc[0]),
+			ehci_readl(&ehci->hcor->or_portsc[1]));
+		return -EIO;
+	}
 
-		dev_dbg(ehci->dev, "TOKEN=0x%08x\n", token);
+	dev_dbg(ehci->dev, "TOKEN=0x%08x\n", token);
 
-		status = QT_TOKEN_GET_STATUS(token);
-		status &= ~(QT_TOKEN_STATUS_SPLITXSTATE |
-			    QT_TOKEN_STATUS_PERR);
+	status = QT_TOKEN_GET_STATUS(token);
+	status &= ~(QT_TOKEN_STATUS_SPLITXSTATE |
+		    QT_TOKEN_STATUS_PERR);
 
-		switch (status) {
-		case 0:
-			toggle = QT_TOKEN_GET_DT(token);
-			usb_settoggle(dev, usb_pipeendpoint(pipe),
-				       usb_pipeout(pipe), toggle);
-			dev->status = 0;
-			break;
-		case QT_TOKEN_STATUS_HALTED:
-			dev->status = USB_ST_STALLED;
-			break;
-		case QT_TOKEN_STATUS_ACTIVE | QT_TOKEN_STATUS_DATBUFERR:
-		case QT_TOKEN_STATUS_DATBUFERR:
-			dev->status = USB_ST_BUF_ERR;
-			break;
-		case QT_TOKEN_STATUS_HALTED | QT_TOKEN_STATUS_BABBLEDET:
-		case QT_TOKEN_STATUS_BABBLEDET:
-			dev->status = USB_ST_BABBLE_DET;
-			break;
-		default:
-			dev->status = USB_ST_CRC_ERR;
-			if (status & QT_TOKEN_STATUS_HALTED)
-				dev->status |= USB_ST_STALLED;
+	switch (status) {
+	case 0:
+		toggle = QT_TOKEN_GET_DT(token);
+		usb_settoggle(dev, usb_pipeendpoint(pipe),
+			      usb_pipeout(pipe), toggle);
+		dev->status = 0;
+		break;
+	case QT_TOKEN_STATUS_HALTED:
+		dev->status = USB_ST_STALLED;
+		break;
+	case QT_TOKEN_STATUS_ACTIVE | QT_TOKEN_STATUS_DATBUFERR:
+	case QT_TOKEN_STATUS_DATBUFERR:
+		dev->status = USB_ST_BUF_ERR;
+		break;
+	case QT_TOKEN_STATUS_HALTED | QT_TOKEN_STATUS_BABBLEDET:
+	case QT_TOKEN_STATUS_BABBLEDET:
+		dev->status = USB_ST_BABBLE_DET;
+		break;
+	default:
+		dev->status = USB_ST_CRC_ERR;
+		if (status & QT_TOKEN_STATUS_HALTED)
+			dev->status |= USB_ST_STALLED;
 
-			break;
-		}
-		dev->act_len = length - QT_TOKEN_GET_TOTALBYTES(token);
-	} else {
-		dev->act_len = 0;
-		dev_dbg(ehci->dev, "dev=%u, usbsts=%#x, p[1]=%#x, p[2]=%#x\n",
-		      dev->devnum, ehci_readl(&ehci->hcor->or_usbsts),
-		      ehci_readl(&ehci->hcor->or_portsc[0]),
-		      ehci_readl(&ehci->hcor->or_portsc[1]));
+		break;
 	}
+	dev->act_len = length - QT_TOKEN_GET_TOTALBYTES(token);
 
-	return (dev->status != USB_ST_NOT_PROC) ? 0 : -1;
+	return 0;
 }
 
 #if defined(CONFIG_MACH_EFIKA_MX_SMARTBOOK) && defined(CONFIG_USB_ULPI)
-- 
2.21.0


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH 11/18] usb: host: ehci: Drop needless assignments in ehci_submit_async()
  2019-05-22  7:33 [PATCH 00/18] EHCI improvements Andrey Smirnov
                   ` (9 preceding siblings ...)
  2019-05-22  7:34 ` [PATCH 10/18] usb: host: ehci: Simplify ehci_submit_async()'s epilogue Andrey Smirnov
@ 2019-05-22  7:34 ` Andrey Smirnov
  2019-05-22  7:34 ` [PATCH 12/18] usb: host: ehci: Use bool to simplify ehci_submit_async() Andrey Smirnov
                   ` (7 subsequent siblings)
  18 siblings, 0 replies; 20+ messages in thread
From: Andrey Smirnov @ 2019-05-22  7:34 UTC (permalink / raw)
  To: barebox; +Cc: Andrey Smirnov

Neither of those is necessary, since both will be overwritten further
down in the code.

Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
---
 drivers/usb/host/ehci-hcd.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 7194a48c0..03ab56b30 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -274,7 +274,7 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
 	uint32_t endpt, token, usbsts;
 	uint32_t status;
 	uint32_t c, toggle;
-	int ret = 0;
+	int ret;
 
 
 	dev_dbg(ehci->dev, "pipe=%lx, buffer=%p, length=%d, req=%p\n", pipe,
@@ -323,7 +323,6 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
 	qh->qt_next = cpu_to_hc32(QT_NEXT_TERMINATE);
 	qh->qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE);
 
-	td = NULL;
 	tdp = &qh->qt_next;
 
 	toggle =
-- 
2.21.0


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH 12/18] usb: host: ehci: Use bool to simplify ehci_submit_async()
  2019-05-22  7:33 [PATCH 00/18] EHCI improvements Andrey Smirnov
                   ` (10 preceding siblings ...)
  2019-05-22  7:34 ` [PATCH 11/18] usb: host: ehci: Drop needless assignments in ehci_submit_async() Andrey Smirnov
@ 2019-05-22  7:34 ` Andrey Smirnov
  2019-05-22  7:34 ` [PATCH 13/18] usb: host: ehci: Add a comment explaing IOC setting for data Andrey Smirnov
                   ` (6 subsequent siblings)
  18 siblings, 0 replies; 20+ messages in thread
From: Andrey Smirnov @ 2019-05-22  7:34 UTC (permalink / raw)
  To: barebox; +Cc: Andrey Smirnov

Change the type of 'c' to bool and drop the trigrah.

Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
---
 drivers/usb/host/ehci-hcd.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 03ab56b30..f0d899e82 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -273,7 +273,8 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
 	uint32_t *tdp;
 	uint32_t endpt, token, usbsts;
 	uint32_t status;
-	uint32_t c, toggle;
+	uint32_t toggle;
+	bool c;
 	int ret;
 
 
@@ -290,8 +291,7 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
 
 	qh = &ehci->qh_list[1];
 	qh->qh_link = cpu_to_hc32((uint32_t)ehci->qh_list | QH_LINK_TYPE_QH);
-	c = (dev->speed != USB_SPEED_HIGH &&
-	     usb_pipeendpoint(pipe) == 0) ? 1 : 0;
+	c = dev->speed != USB_SPEED_HIGH && !usb_pipeendpoint(pipe);
 	endpt = QH_ENDPT1_RL(8) | QH_ENDPT1_C(c) |
 		QH_ENDPT1_MAXPKTLEN(usb_maxpacket(dev, pipe)) |
 		QH_ENDPT1_H(0) |
-- 
2.21.0


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH 13/18] usb: host: ehci: Add a comment explaing IOC setting for data
  2019-05-22  7:33 [PATCH 00/18] EHCI improvements Andrey Smirnov
                   ` (11 preceding siblings ...)
  2019-05-22  7:34 ` [PATCH 12/18] usb: host: ehci: Use bool to simplify ehci_submit_async() Andrey Smirnov
@ 2019-05-22  7:34 ` Andrey Smirnov
  2019-05-22  7:34 ` [PATCH 14/18] usb: host: ehci: Replace explicit printf() with dev_err() Andrey Smirnov
                   ` (5 subsequent siblings)
  18 siblings, 0 replies; 20+ messages in thread
From: Andrey Smirnov @ 2019-05-22  7:34 UTC (permalink / raw)
  To: barebox; +Cc: Andrey Smirnov

Add a comment explaining the rationale behinde QT_TOKEN_IOC(req ==
NULL).

Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
---
 drivers/usb/host/ehci-hcd.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index f0d899e82..a6f497925 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -362,6 +362,15 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
 
 		ret = ehci_prepare_qtd(ehci->dev,
 				       td, QT_TOKEN_DT(toggle) |
+				       /*
+					* We only want this qTD to
+					* generate an interrupt if
+					* this is a BULK
+					* request. Otherwise, we'll
+					* rely on following status
+					* stage qTD's IOC to notify us
+					* that transfer is complete
+					*/
 				       QT_TOKEN_IOC(req == NULL) |
 				       QT_TOKEN_PID(pid),
 				       buffer, length,
-- 
2.21.0


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH 14/18] usb: host: ehci: Replace explicit printf() with dev_err()
  2019-05-22  7:33 [PATCH 00/18] EHCI improvements Andrey Smirnov
                   ` (12 preceding siblings ...)
  2019-05-22  7:34 ` [PATCH 13/18] usb: host: ehci: Add a comment explaing IOC setting for data Andrey Smirnov
@ 2019-05-22  7:34 ` Andrey Smirnov
  2019-05-22  7:34 ` [PATCH 15/18] usb: host: ehci: Drop explicit memset() in ehci_init() Andrey Smirnov
                   ` (4 subsequent siblings)
  18 siblings, 0 replies; 20+ messages in thread
From: Andrey Smirnov @ 2019-05-22  7:34 UTC (permalink / raw)
  To: barebox; +Cc: Andrey Smirnov

Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
---
 drivers/usb/host/ehci-hcd.c | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index a6f497925..050a3166e 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -542,7 +542,9 @@ ehci_submit_root(struct usb_device *dev, unsigned long pipe, void *buffer,
 	case USB_REQ_SET_FEATURE | ((USB_DIR_OUT | USB_RT_PORT) << 8):
 	case USB_REQ_CLEAR_FEATURE | ((USB_DIR_OUT | USB_RT_PORT) << 8):
 		if (!port || port > CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS) {
-			printf("The request port(%d) is not configured\n", port - 1);
+			dev_err(ehci->dev,
+				"The request port(%d) is not configured\n",
+				port - 1);
 			return -1;
 		}
 		status_reg = (uint32_t *)&ehci->hcor->or_portsc[port - 1];
@@ -972,7 +974,8 @@ disable_periodic(struct ehci_host *ehci)
 	ret = handshake((uint32_t *)&hcor->or_usbsts,
 			STS_PSS, 0, 100 * 1000);
 	if (ret < 0) {
-		printf("EHCI failed: timeout when disabling periodic list\n");
+		dev_err(ehci->dev,
+			"EHCI failed: timeout when disabling periodic list\n");
 		return -ETIMEDOUT;
 	}
 	return 0;
@@ -993,7 +996,8 @@ enable_periodic(struct ehci_host *ehci)
 	ret = handshake((uint32_t *)&hcor->or_usbsts,
 			STS_PSS, STS_PSS, 100 * 1000);
 	if (ret < 0) {
-		printf("EHCI failed: timeout when enabling periodic list\n");
+		dev_err(ehci->dev,
+			"EHCI failed: timeout when enabling periodic list\n");
 		return -ETIMEDOUT;
 	}
 
-- 
2.21.0


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH 15/18] usb: host: ehci: Drop explicit memset() in ehci_init()
  2019-05-22  7:33 [PATCH 00/18] EHCI improvements Andrey Smirnov
                   ` (13 preceding siblings ...)
  2019-05-22  7:34 ` [PATCH 14/18] usb: host: ehci: Replace explicit printf() with dev_err() Andrey Smirnov
@ 2019-05-22  7:34 ` Andrey Smirnov
  2019-05-22  7:34 ` [PATCH 16/18] usb: host: ehci: Treat ehci->qh_list as an array Andrey Smirnov
                   ` (3 subsequent siblings)
  18 siblings, 0 replies; 20+ messages in thread
From: Andrey Smirnov @ 2019-05-22  7:34 UTC (permalink / raw)
  To: barebox; +Cc: Andrey Smirnov

Memory allocated by dma_alloc_coherent() is already zeroed out,
ehci->qh_list[0] never changes during the operation of the driver and
ehci->qh_list[1] will be explicitly initialized by ehci_submit_async()
so this additional memset() shouldn't be necessary.

Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
---
 drivers/usb/host/ehci-hcd.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 050a3166e..11c34d8a2 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -839,8 +839,6 @@ static int ehci_init(struct usb_host *host)
 			return ret;
 	}
 
-	memset(ehci->qh_list, 0, sizeof(struct QH) * NUM_TD);
-
 	ehci->qh_list->qh_link = cpu_to_hc32((uint32_t)ehci->qh_list | QH_LINK_TYPE_QH);
 	ehci->qh_list->qh_endpt1 = cpu_to_hc32(QH_ENDPT1_H(1) |
 					       QH_ENDPT1_EPS(USB_SPEED_HIGH));
-- 
2.21.0


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH 16/18] usb: host: ehci: Treat ehci->qh_list as an array
  2019-05-22  7:33 [PATCH 00/18] EHCI improvements Andrey Smirnov
                   ` (14 preceding siblings ...)
  2019-05-22  7:34 ` [PATCH 15/18] usb: host: ehci: Drop explicit memset() in ehci_init() Andrey Smirnov
@ 2019-05-22  7:34 ` Andrey Smirnov
  2019-05-22  7:34 ` [PATCH 17/18] ush: host: ehci: Simplify QH initialization in ehci_submit_async() Andrey Smirnov
                   ` (2 subsequent siblings)
  18 siblings, 0 replies; 20+ messages in thread
From: Andrey Smirnov @ 2019-05-22  7:34 UTC (permalink / raw)
  To: barebox; +Cc: Andrey Smirnov

Since ehci->qh_list is an array, convert the code to use
ehci->qh_list[0] to access its first element to make things a bit more
clear. No functional change intended.

Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
---
 drivers/usb/host/ehci-hcd.c | 15 ++++++++-------
 1 file changed, 8 insertions(+), 7 deletions(-)

diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 11c34d8a2..bd033c23c 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -839,13 +839,14 @@ static int ehci_init(struct usb_host *host)
 			return ret;
 	}
 
-	ehci->qh_list->qh_link = cpu_to_hc32((uint32_t)ehci->qh_list | QH_LINK_TYPE_QH);
-	ehci->qh_list->qh_endpt1 = cpu_to_hc32(QH_ENDPT1_H(1) |
-					       QH_ENDPT1_EPS(USB_SPEED_HIGH));
-	ehci->qh_list->qh_curtd = cpu_to_hc32(QT_NEXT_TERMINATE);
-	ehci->qh_list->qt_next = cpu_to_hc32(QT_NEXT_TERMINATE);
-	ehci->qh_list->qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE);
-	ehci->qh_list->qt_token = cpu_to_hc32(QT_TOKEN_STATUS_HALTED);
+	ehci->qh_list[0].qh_link = cpu_to_hc32((uint32_t)&ehci->qh_list[0] |
+					       QH_LINK_TYPE_QH);
+	ehci->qh_list[0].qh_endpt1 = cpu_to_hc32(QH_ENDPT1_H(1) |
+						 QH_ENDPT1_EPS(USB_SPEED_HIGH));
+	ehci->qh_list[0].qh_curtd = cpu_to_hc32(QT_NEXT_TERMINATE);
+	ehci->qh_list[0].qt_next = cpu_to_hc32(QT_NEXT_TERMINATE);
+	ehci->qh_list[0].qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE);
+	ehci->qh_list[0].qt_token = cpu_to_hc32(QT_TOKEN_STATUS_HALTED);
 
 	/* Set async. queue head pointer. */
 	ehci_writel(&ehci->hcor->or_asynclistaddr, (uint32_t)ehci->qh_list);
-- 
2.21.0


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH 17/18] ush: host: ehci: Simplify QH initialization in ehci_submit_async()
  2019-05-22  7:33 [PATCH 00/18] EHCI improvements Andrey Smirnov
                   ` (15 preceding siblings ...)
  2019-05-22  7:34 ` [PATCH 16/18] usb: host: ehci: Treat ehci->qh_list as an array Andrey Smirnov
@ 2019-05-22  7:34 ` Andrey Smirnov
  2019-05-22  7:34 ` [PATCH 18/18] usb: host: ehci: Allocate only NUM_QH queue heads for qh_list Andrey Smirnov
  2019-05-23  7:57 ` [PATCH 00/18] EHCI improvements Sascha Hauer
  18 siblings, 0 replies; 20+ messages in thread
From: Andrey Smirnov @ 2019-05-22  7:34 UTC (permalink / raw)
  To: barebox; +Cc: Andrey Smirnov

We use a fixed circular list for asynchronous schedule that never
changes, so if we drop an explicit memset() that zeros out an entire
struct and replace it with code initializine all of the fields
explicitly, we can set QH list once in ehci_init() and never touch it
again.

While at it move qt_altnext initialization to ehci_init() as well
since we never change that field either.

Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
---
 drivers/usb/host/ehci-hcd.c | 21 +++++++++------------
 1 file changed, 9 insertions(+), 12 deletions(-)

diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index bd033c23c..b336164f6 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -268,7 +268,7 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
 	struct ehci_host *ehci = to_ehci(host);
 	const bool dir_in = usb_pipein(pipe);
 	dma_addr_t buffer_dma, req_dma;
-	struct QH *qh;
+	struct QH *qh = &ehci->qh_list[1];
 	struct qTD *td;
 	uint32_t *tdp;
 	uint32_t endpt, token, usbsts;
@@ -287,10 +287,6 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
 		      le16_to_cpu(req->value), le16_to_cpu(req->value),
 		      le16_to_cpu(req->index));
 
-	memset(&ehci->qh_list[1], 0, sizeof(struct QH));
-
-	qh = &ehci->qh_list[1];
-	qh->qh_link = cpu_to_hc32((uint32_t)ehci->qh_list | QH_LINK_TYPE_QH);
 	c = dev->speed != USB_SPEED_HIGH && !usb_pipeendpoint(pipe);
 	endpt = QH_ENDPT1_RL(8) | QH_ENDPT1_C(c) |
 		QH_ENDPT1_MAXPKTLEN(usb_maxpacket(dev, pipe)) |
@@ -320,8 +316,9 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
 		QH_ENDPT2_UFCMASK(0) |
 		QH_ENDPT2_UFSMASK(0);
 	qh->qh_endpt2 = cpu_to_hc32(endpt);
-	qh->qt_next = cpu_to_hc32(QT_NEXT_TERMINATE);
-	qh->qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE);
+	qh->qh_curtd = 0;
+	qh->qt_token = 0;
+	memset(qh->qt_buffer, 0, sizeof(qh->qt_buffer));
 
 	tdp = &qh->qt_next;
 
@@ -397,8 +394,6 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
 		tdp = &td->qt_next;
 	}
 
-	ehci->qh_list->qh_link = cpu_to_hc32((uint32_t) qh | QH_LINK_TYPE_QH);
-
 	usbsts = ehci_readl(&ehci->hcor->or_usbsts);
 	ehci_writel(&ehci->hcor->or_usbsts, (usbsts & 0x3f));
 
@@ -431,8 +426,6 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
 		return ret;
 	}
 
-	ehci->qh_list->qh_link = cpu_to_hc32((uint32_t)ehci->qh_list | QH_LINK_TYPE_QH);
-
 	token = hc32_to_cpu(qh->qt_token);
 	if (token & QT_TOKEN_STATUS_ACTIVE) {
 		dev->act_len = 0;
@@ -839,7 +832,7 @@ static int ehci_init(struct usb_host *host)
 			return ret;
 	}
 
-	ehci->qh_list[0].qh_link = cpu_to_hc32((uint32_t)&ehci->qh_list[0] |
+	ehci->qh_list[0].qh_link = cpu_to_hc32((uint32_t)&ehci->qh_list[1] |
 					       QH_LINK_TYPE_QH);
 	ehci->qh_list[0].qh_endpt1 = cpu_to_hc32(QH_ENDPT1_H(1) |
 						 QH_ENDPT1_EPS(USB_SPEED_HIGH));
@@ -848,6 +841,10 @@ static int ehci_init(struct usb_host *host)
 	ehci->qh_list[0].qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE);
 	ehci->qh_list[0].qt_token = cpu_to_hc32(QT_TOKEN_STATUS_HALTED);
 
+	ehci->qh_list[1].qh_link = cpu_to_hc32((uint32_t)&ehci->qh_list[0] |
+					       QH_LINK_TYPE_QH);
+	ehci->qh_list[1].qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE);
+
 	/* Set async. queue head pointer. */
 	ehci_writel(&ehci->hcor->or_asynclistaddr, (uint32_t)ehci->qh_list);
 
-- 
2.21.0


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH 18/18] usb: host: ehci: Allocate only NUM_QH queue heads for qh_list
  2019-05-22  7:33 [PATCH 00/18] EHCI improvements Andrey Smirnov
                   ` (16 preceding siblings ...)
  2019-05-22  7:34 ` [PATCH 17/18] ush: host: ehci: Simplify QH initialization in ehci_submit_async() Andrey Smirnov
@ 2019-05-22  7:34 ` Andrey Smirnov
  2019-05-23  7:57 ` [PATCH 00/18] EHCI improvements Sascha Hauer
  18 siblings, 0 replies; 20+ messages in thread
From: Andrey Smirnov @ 2019-05-22  7:34 UTC (permalink / raw)
  To: barebox; +Cc: Andrey Smirnov

Use NUM_QH, not NUM_TD to specify allocation size.

Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
---
 drivers/usb/host/ehci-hcd.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index b336164f6..f3be177ce 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -1325,7 +1325,7 @@ struct ehci_host *ehci_register(struct device_d *dev, struct ehci_data *data)
 	ehci->init = data->init;
 	ehci->post_init = data->post_init;
 
-	ehci->qh_list = dma_alloc_coherent(sizeof(struct QH) * NUM_TD,
+	ehci->qh_list = dma_alloc_coherent(sizeof(struct QH) * NUM_QH,
 					   DMA_ADDRESS_BROKEN);
 	ehci->periodic_queue = dma_alloc_coherent(sizeof(struct QH),
 						  DMA_ADDRESS_BROKEN);
-- 
2.21.0


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH 00/18] EHCI improvements
  2019-05-22  7:33 [PATCH 00/18] EHCI improvements Andrey Smirnov
                   ` (17 preceding siblings ...)
  2019-05-22  7:34 ` [PATCH 18/18] usb: host: ehci: Allocate only NUM_QH queue heads for qh_list Andrey Smirnov
@ 2019-05-23  7:57 ` Sascha Hauer
  18 siblings, 0 replies; 20+ messages in thread
From: Sascha Hauer @ 2019-05-23  7:57 UTC (permalink / raw)
  To: Andrey Smirnov; +Cc: barebox

On Wed, May 22, 2019 at 12:33:56AM -0700, Andrey Smirnov wrote:
> Everyone:
> 
> This series is a number of improvements (or so I though) I made while
> woring with USB on i.MX6. All of the patches are optional, so if some
> of the changes don't seem like an improvmement they can be dropped.
> 
> Feedback is welcome!
> 
> Thanks,
> Andrey Smirnov

Applied, thanks

Sascha


-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 20+ messages in thread

end of thread, other threads:[~2019-05-23  7:57 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-05-22  7:33 [PATCH 00/18] EHCI improvements Andrey Smirnov
2019-05-22  7:33 ` [PATCH 01/18] usb: host: ehci: Do not zero out DMA coherent memory Andrey Smirnov
2019-05-22  7:33 ` [PATCH 02/18] usb: host: ehci: Share code to enable/disable async schedule Andrey Smirnov
2019-05-22  7:33 ` [PATCH 03/18] usb: host: ehci: Use to USBSTS to wait for transfer completion Andrey Smirnov
2019-05-22  7:34 ` [PATCH 04/18] usb: host: ehci: Replace magic number with macros Andrey Smirnov
2019-05-22  7:34 ` [PATCH 05/18] usb: host: ehci: Drop unnecessary cleanup code Andrey Smirnov
2019-05-22  7:34 ` [PATCH 06/18] usb: host: ehci: Introduce ehci_prepare_qtd() Andrey Smirnov
2019-05-22  7:34 ` [PATCH 07/18] usb: host: ehci: Simplify qTD buffer synchronization Andrey Smirnov
2019-05-22  7:34 ` [PATCH 08/18] usb: host: ehci: Simplify ehci_td_buffer() Andrey Smirnov
2019-05-22  7:34 ` [PATCH 09/18] usb: host: ehci: Initialize qTDs explicitly Andrey Smirnov
2019-05-22  7:34 ` [PATCH 10/18] usb: host: ehci: Simplify ehci_submit_async()'s epilogue Andrey Smirnov
2019-05-22  7:34 ` [PATCH 11/18] usb: host: ehci: Drop needless assignments in ehci_submit_async() Andrey Smirnov
2019-05-22  7:34 ` [PATCH 12/18] usb: host: ehci: Use bool to simplify ehci_submit_async() Andrey Smirnov
2019-05-22  7:34 ` [PATCH 13/18] usb: host: ehci: Add a comment explaing IOC setting for data Andrey Smirnov
2019-05-22  7:34 ` [PATCH 14/18] usb: host: ehci: Replace explicit printf() with dev_err() Andrey Smirnov
2019-05-22  7:34 ` [PATCH 15/18] usb: host: ehci: Drop explicit memset() in ehci_init() Andrey Smirnov
2019-05-22  7:34 ` [PATCH 16/18] usb: host: ehci: Treat ehci->qh_list as an array Andrey Smirnov
2019-05-22  7:34 ` [PATCH 17/18] ush: host: ehci: Simplify QH initialization in ehci_submit_async() Andrey Smirnov
2019-05-22  7:34 ` [PATCH 18/18] usb: host: ehci: Allocate only NUM_QH queue heads for qh_list Andrey Smirnov
2019-05-23  7:57 ` [PATCH 00/18] EHCI improvements Sascha Hauer

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox