mail archive of the barebox mailing list
 help / color / mirror / Atom feed
* [PATCH v6 0/5] input: add usb keyboard driver
@ 2015-09-22 15:58 Peter Mamonov
  2015-09-22 15:58 ` [PATCH 1/5] common: clock: introduce mdelay_non_interruptible() Peter Mamonov
                   ` (5 more replies)
  0 siblings, 6 replies; 23+ messages in thread
From: Peter Mamonov @ 2015-09-22 15:58 UTC (permalink / raw)
  To: barebox; +Cc: pmamonov

Changes since v5:
	- Address issues reported here: 
	  http://lists.infradead.org/pipermail/barebox/2015-September/024726.html

	- input: usb_kbd: set idle time to minimum and limit polling rate

	  Idle time is the amount of time, during which the usb device will wait before
	  replying to the host interrupt packet. We don't want to waste that time, 
	  so keep it as small as possible. In particular this resolves the problem of 
	  very poor tftp performance, when the usb keyboard is enabled.

Peter Mamonov (5):
	common: clock: introduce mdelay_non_interruptible()
	usb: ehci-hcd: port periodic transactions implementation
	usb: ehci-hcd: detect re-entrance
	usb: ehci-hcd: use mdelay_non_inerruptible()
	input: port usb keyboard driver from the u-boot

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

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

* [PATCH 1/5] common: clock: introduce mdelay_non_interruptible()
  2015-09-22 15:58 [PATCH v6 0/5] input: add usb keyboard driver Peter Mamonov
@ 2015-09-22 15:58 ` Peter Mamonov
  2015-09-22 21:15   ` Antony Pavlov
  2015-09-22 15:58 ` [PATCH 2/5] usb: ehci-hcd: port periodic transactions implementation from the u-boot Peter Mamonov
                   ` (4 subsequent siblings)
  5 siblings, 1 reply; 23+ messages in thread
From: Peter Mamonov @ 2015-09-22 15:58 UTC (permalink / raw)
  To: barebox; +Cc: pmamonov

Signed-off-by: Peter Mamonov <pmamonov@gmail.com>
---
 common/clock.c   | 8 ++++++++
 include/clock.h  | 1 +
 include/common.h | 1 +
 3 files changed, 10 insertions(+)

diff --git a/common/clock.c b/common/clock.c
index 35c9e6c..51cf9e4 100644
--- a/common/clock.c
+++ b/common/clock.c
@@ -202,6 +202,14 @@ void mdelay(unsigned long msecs)
 }
 EXPORT_SYMBOL(mdelay);
 
+void mdelay_non_interruptible(unsigned long msecs)
+{
+	uint64_t start = get_time_ns();
+
+	while(!is_timeout_non_interruptible(start, msecs * MSECOND));
+}
+EXPORT_SYMBOL(mdelay_non_interruptible);
+
 int init_clock(struct clocksource *cs)
 {
 	current_clock = cs;
diff --git a/include/clock.h b/include/clock.h
index 691befc..68d71d7 100644
--- a/include/clock.h
+++ b/include/clock.h
@@ -38,6 +38,7 @@ int is_timeout_non_interruptible(uint64_t start_ns, uint64_t time_offset_ns);
 
 void ndelay(unsigned long nsecs);
 void mdelay(unsigned long msecs);
+void mdelay_non_interruptible (unsigned long msecs);
 
 #define SECOND ((uint64_t)(1000 * 1000 * 1000))
 #define MSECOND ((uint64_t)(1000 * 1000))
diff --git a/include/common.h b/include/common.h
index 553a7f4..c576908 100644
--- a/include/common.h
+++ b/include/common.h
@@ -72,6 +72,7 @@ void __noreturn poweroff(void);
 /* lib_$(ARCH)/time.c */
 void	udelay (unsigned long);
 void	mdelay (unsigned long);
+void	mdelay_non_interruptible (unsigned long);
 
 /* lib_generic/crc32.c */
 uint32_t crc32(uint32_t, const void*, unsigned int);
-- 
2.1.4


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

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

* [PATCH 2/5] usb: ehci-hcd: port periodic transactions implementation from the u-boot
  2015-09-22 15:58 [PATCH v6 0/5] input: add usb keyboard driver Peter Mamonov
  2015-09-22 15:58 ` [PATCH 1/5] common: clock: introduce mdelay_non_interruptible() Peter Mamonov
@ 2015-09-22 15:58 ` Peter Mamonov
  2015-09-22 15:58 ` [PATCH 3/5] usb: ehci-hcd: detect re-entrance Peter Mamonov
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 23+ messages in thread
From: Peter Mamonov @ 2015-09-22 15:58 UTC (permalink / raw)
  To: barebox; +Cc: pmamonov

Signed-off-by: Peter Mamonov <pmamonov@gmail.com>
---
 drivers/usb/host/ehci-hcd.c | 396 +++++++++++++++++++++++++++++++++++++++++++-
 drivers/usb/host/ehci.h     |  15 +-
 2 files changed, 409 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 551d1a0..e6748b0 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -48,6 +48,19 @@ struct ehci_priv {
 	int (*init)(void *drvdata);
 	int (*post_init)(void *drvdata);
 	void *drvdata;
+	int periodic_schedules;
+	struct QH *periodic_queue;
+	uint32_t *periodic_list;
+};
+
+struct int_queue {
+	int elementsize;
+	int queuesize;
+	unsigned long pipe;
+	struct QH *first;
+	struct QH *current;
+	struct QH *last;
+	struct qTD *tds;
 };
 
 #define to_ehci(ptr) container_of(ptr, struct ehci_priv, host)
@@ -768,6 +781,8 @@ static int ehci_init(struct usb_host *host)
 	uint32_t reg;
 	uint32_t cmd;
 	int ret = 0;
+	struct QH *periodic;
+	int i;
 
 	ehci_halt(ehci);
 
@@ -798,6 +813,44 @@ static int ehci_init(struct usb_host *host)
 		ehci_writel(&ehci->hcor->or_asynclistaddr, ba);
 	}
 
+	/*
+	 * Set up periodic list
+	 * Step 1: Parent QH for all periodic transfers.
+	 */
+	ehci->periodic_schedules = 0;
+	periodic = ehci->periodic_queue;
+	memset(periodic, 0, sizeof(*periodic));
+	periodic->qh_link = cpu_to_hc32(QH_LINK_TERMINATE);
+	periodic->qt_next = cpu_to_hc32(QT_NEXT_TERMINATE);
+	periodic->qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE);
+
+	/*
+	 * Step 2: Setup frame-list: Every microframe, USB tries the same list.
+	 *         In particular, device specifications on polling frequency
+	 *         are disregarded. Keyboards seem to send NAK/NYet reliably
+	 *         when polled with an empty buffer.
+	 *
+	 *         Split Transactions will be spread across microframes using
+	 *         S-mask and C-mask.
+	 */
+	if (ehci->periodic_list == NULL)
+		/*
+		 * FIXME: this memory chunk have to be 4k aligned AND
+		 * reside in coherent memory. Current implementation of
+		 * dma_alloc_coherent() allocates PAGE_SIZE aligned memory chunks.
+		 * PAGE_SIZE less then 4k will break this code.
+		 */
+		ehci->periodic_list = dma_alloc_coherent(1024 * 4,
+							 DMA_ADDRESS_BROKEN);
+	for (i = 0; i < 1024; i++) {
+		ehci->periodic_list[i] = cpu_to_hc32((unsigned long)periodic
+						| QH_LINK_TYPE_QH);
+	}
+
+	/* Set periodic list base address */
+	ehci_writel(&ehci->hcor->or_periodiclistbase,
+		(unsigned long)ehci->periodic_list);
+
 	reg = ehci_readl(&ehci->hccr->cr_hcsparams);
 	descriptor.hub.bNbrPorts = HCS_N_PORTS(reg);
 
@@ -869,15 +922,354 @@ submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
 }
 
 static int
+disable_periodic(struct ehci_priv *ehci)
+{
+	uint32_t cmd;
+	struct ehci_hcor *hcor = ehci->hcor;
+	int ret;
+
+	cmd = ehci_readl(&hcor->or_usbcmd);
+	cmd &= ~CMD_PSE;
+	ehci_writel(&hcor->or_usbcmd, cmd);
+
+	ret = handshake((uint32_t *)&hcor->or_usbsts,
+			STS_PSS, 0, 100 * 1000);
+	if (ret < 0) {
+		printf("EHCI failed: timeout when disabling periodic list\n");
+		return -ETIMEDOUT;
+	}
+	return 0;
+}
+
+#define NEXT_QH(qh) (struct QH *)((unsigned long)hc32_to_cpu((qh)->qh_link) & ~0x1f)
+
+static int
+enable_periodic(struct ehci_priv *ehci)
+{
+	uint32_t cmd;
+	struct ehci_hcor *hcor = ehci->hcor;
+	int ret;
+
+	cmd = ehci_readl(&hcor->or_usbcmd);
+	cmd |= CMD_PSE;
+	ehci_writel(&hcor->or_usbcmd, cmd);
+	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");
+		return -ETIMEDOUT;
+	}
+	mdelay_non_interruptible(1);
+	return 0;
+}
+
+static inline u8 ehci_encode_speed(enum usb_device_speed speed)
+{
+	#define QH_HIGH_SPEED	2
+	#define QH_FULL_SPEED	0
+	#define QH_LOW_SPEED	1
+	if (speed == USB_SPEED_HIGH)
+		return QH_HIGH_SPEED;
+	if (speed == USB_SPEED_LOW)
+		return QH_LOW_SPEED;
+	return QH_FULL_SPEED;
+}
+
+static void ehci_update_endpt2_dev_n_port(struct usb_device *udev,
+					  struct QH *qh)
+{
+	struct usb_device *ttdev;
+	int parent_devnum;
+
+	if (udev->speed != USB_SPEED_LOW && udev->speed != USB_SPEED_FULL)
+		return;
+
+	/*
+	 * For full / low speed devices we need to get the devnum and portnr of
+	 * the tt, so of the first upstream usb-2 hub, there may be usb-1 hubs
+	 * in the tree before that one!
+	 */
+
+	ttdev = udev;
+	while (ttdev->parent && ttdev->parent->speed != USB_SPEED_HIGH)
+		ttdev = ttdev->parent;
+	if (!ttdev->parent)
+		return;
+	parent_devnum = ttdev->parent->devnum;
+
+	qh->qh_endpt2 |= cpu_to_hc32(QH_ENDPT2_PORTNUM(ttdev->portnr) |
+				     QH_ENDPT2_HUBADDR(parent_devnum));
+}
+
+static struct int_queue *ehci_create_int_queue(struct usb_device *dev,
+			unsigned long pipe, int queuesize, int elementsize,
+			void *buffer, int interval)
+{
+	struct usb_host *host = dev->host;
+	struct ehci_priv *ehci = to_ehci(host);
+	struct int_queue *result = NULL;
+	uint32_t i, toggle;
+	struct QH *list = ehci->periodic_queue;
+
+	/*
+	 * Interrupt transfers requiring several transactions are not supported
+	 * because bInterval is ignored.
+	 *
+	 * Also, ehci_submit_async() relies on wMaxPacketSize being a power of 2
+	 * <= PKT_ALIGN if several qTDs are required, while the USB
+	 * specification does not constrain this for interrupt transfers. That
+	 * means that ehci_submit_async() would support interrupt transfers
+	 * requiring several transactions only as long as the transfer size does
+	 * not require more than a single qTD.
+	 */
+	if (elementsize > usb_maxpacket(dev, pipe)) {
+		dev_err(&dev->dev,
+			"%s: xfers requiring several transactions are not supported.\n",
+			__func__);
+		return NULL;
+	}
+
+	debug("Enter create_int_queue\n");
+	if (usb_pipetype(pipe) != PIPE_INTERRUPT) {
+		dev_dbg(&dev->dev,
+			"non-interrupt pipe (type=%lu)",
+			usb_pipetype(pipe));
+		return NULL;
+	}
+
+	/* limit to 4 full pages worth of data -
+	 * we can safely fit them in a single TD,
+	 * no matter the alignment
+	 */
+	if (elementsize >= 16384) {
+		dev_dbg(&dev->dev,
+			"too large elements for interrupt transfers\n");
+		return NULL;
+	}
+
+	result = xzalloc(sizeof(*result));
+	result->elementsize = elementsize;
+	result->queuesize = queuesize;
+	result->pipe = pipe;
+	result->first = dma_alloc_coherent(sizeof(struct QH) * queuesize,
+					   DMA_ADDRESS_BROKEN);
+	result->current = result->first;
+	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);
+
+	toggle = usb_gettoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe));
+
+	for (i = 0; i < queuesize; i++) {
+		struct QH *qh = result->first + i;
+		struct qTD *td = result->tds + i;
+		void **buf = &qh->buffer;
+
+		qh->qh_link = cpu_to_hc32((unsigned long)(qh+1) | QH_LINK_TYPE_QH);
+		if (i == queuesize - 1)
+			qh->qh_link = cpu_to_hc32(QH_LINK_TERMINATE);
+
+		qh->qt_next = cpu_to_hc32((unsigned long)td);
+		qh->qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE);
+		qh->qh_endpt1 =
+			cpu_to_hc32((0 << 28) | /* No NAK reload (ehci 4.9) */
+			(usb_maxpacket(dev, pipe) << 16) | /* MPS */
+			(1 << 14) |
+			QH_ENDPT1_EPS(ehci_encode_speed(dev->speed)) |
+			(usb_pipeendpoint(pipe) << 8) | /* Endpoint Number */
+			(usb_pipedevice(pipe) << 0));
+		qh->qh_endpt2 = cpu_to_hc32((1 << 30) | /* 1 Tx per mframe */
+			(1 << 0)); /* S-mask: microframe 0 */
+		if (dev->speed == USB_SPEED_LOW ||
+				dev->speed == USB_SPEED_FULL) {
+			/* C-mask: microframes 2-4 */
+			qh->qh_endpt2 |= cpu_to_hc32((0x1c << 8));
+		}
+		ehci_update_endpt2_dev_n_port(dev, qh);
+
+		td->qt_next = cpu_to_hc32(QT_NEXT_TERMINATE);
+		td->qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE);
+		dev_dbg(&dev->dev,
+			"communication direction is '%s'\n",
+			usb_pipein(pipe) ? "in" : "out");
+		td->qt_token = cpu_to_hc32(
+			QT_TOKEN_DT(toggle) |
+			(elementsize << 16) |
+			((usb_pipein(pipe) ? 1 : 0) << 8) | /* IN/OUT token */
+			0x80); /* active */
+		td->qt_buffer[0] =
+		    cpu_to_hc32((unsigned long)buffer + i * elementsize);
+		td->qt_buffer[1] =
+		    cpu_to_hc32((td->qt_buffer[0] + 0x1000) & ~0xfff);
+		td->qt_buffer[2] =
+		    cpu_to_hc32((td->qt_buffer[0] + 0x2000) & ~0xfff);
+		td->qt_buffer[3] =
+		    cpu_to_hc32((td->qt_buffer[0] + 0x3000) & ~0xfff);
+		td->qt_buffer[4] =
+		    cpu_to_hc32((td->qt_buffer[0] + 0x4000) & ~0xfff);
+
+		*buf = buffer + i * elementsize;
+		toggle ^= 1;
+	}
+
+	if (ehci->periodic_schedules > 0) {
+		if (disable_periodic(ehci) < 0) {
+			dev_err(&dev->dev,
+				"FATAL: periodic should never fail, but did");
+			goto fail3;
+		}
+	}
+
+	/* hook up to periodic list */
+	result->last->qh_link = list->qh_link;
+	list->qh_link = cpu_to_hc32((unsigned long)result->first | QH_LINK_TYPE_QH);
+
+	if (enable_periodic(ehci) < 0) {
+		dev_err(&dev->dev,
+			"FATAL: periodic should never fail, but did");
+		goto fail3;
+	}
+	ehci->periodic_schedules++;
+
+	dev_dbg(&dev->dev, "Exit create_int_queue\n");
+	return result;
+fail3:
+	dma_free_coherent(result->tds, 0, sizeof(struct qTD) * queuesize);
+	dma_free_coherent(result->first, 0, sizeof(struct QH) * queuesize);
+	free(result);
+	return NULL;
+}
+
+static void *ehci_poll_int_queue(struct usb_device *dev,
+				  struct int_queue *queue)
+{
+	struct QH *cur = queue->current;
+	struct qTD *cur_td;
+	uint32_t token, toggle;
+	unsigned long pipe = queue->pipe;
+
+	/* depleted queue */
+	if (cur == NULL) {
+		dev_dbg(&dev->dev, "Exit poll_int_queue with completed queue\n");
+		return NULL;
+	}
+	/* still active */
+	cur_td = &queue->tds[queue->current - queue->first];
+	token = hc32_to_cpu(cur_td->qt_token);
+	if (QT_TOKEN_GET_STATUS(token) & QT_TOKEN_STATUS_ACTIVE) {
+		dev_dbg(&dev->dev,
+			"Exit poll_int_queue with no completed intr transfer. token is %x\n",
+			token);
+		return NULL;
+	}
+
+	toggle = QT_TOKEN_GET_DT(token);
+	usb_settoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe), toggle);
+
+	if (!(cur->qh_link & QH_LINK_TERMINATE))
+		queue->current++;
+	else
+		queue->current = NULL;
+
+	dev_dbg(&dev->dev,
+		"Exit poll_int_queue with completed intr transfer. token is %x at %p (first at %p)\n",
+		token, cur, queue->first);
+	return cur->buffer;
+}
+
+static int ehci_destroy_int_queue(struct usb_device *dev,
+				   struct int_queue *queue)
+{
+	int result = -EINVAL;
+	struct usb_host *host = dev->host;
+	struct ehci_priv *ehci = to_ehci(host);
+	struct QH *cur = ehci->periodic_queue;
+	uint64_t start;
+
+	if (disable_periodic(ehci) < 0) {
+		dev_err(&dev->dev,
+			"FATAL: periodic should never fail, but did\n");
+		goto out;
+	}
+	ehci->periodic_schedules--;
+
+	start = get_time_ns();
+	while (!(cur->qh_link & cpu_to_hc32(QH_LINK_TERMINATE))) {
+		dev_dbg(&dev->dev,
+			"considering %p, with qh_link %x\n",
+			cur, cur->qh_link);
+		if (NEXT_QH(cur) == queue->first) {
+			dev_dbg(&dev->dev,
+				"found candidate. removing from chain\n");
+			cur->qh_link = queue->last->qh_link;
+			result = 0;
+			break;
+		}
+		cur = NEXT_QH(cur);
+		if (is_timeout_non_interruptible(start, 500 * MSECOND)) {
+			dev_err(&dev->dev,
+				"Timeout destroying interrupt endpoint queue\n");
+			result = -ETIMEDOUT;
+			goto out;
+		}
+	}
+
+	if (ehci->periodic_schedules > 0) {
+		result = enable_periodic(ehci);
+		if (result < 0)
+			dev_err(&dev->dev,
+				"FATAL: periodic should never fail, but did");
+	}
+
+out:
+	dma_free_coherent(queue->tds, 0, sizeof(struct qTD) * queue->queuesize);
+	dma_free_coherent(queue->first, 0, sizeof(struct QH) * queue->queuesize);
+	free(queue);
+	return result;
+}
+
+static int
 submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
 	       int length, int interval)
 {
 	struct usb_host *host = dev->host;
 	struct ehci_priv *ehci = to_ehci(host);
+	struct int_queue *queue;
+	uint64_t start;
+	void *backbuffer;
+	int result = 0, ret;
 
 	dev_dbg(ehci->dev, "dev=%p, pipe=%lu, buffer=%p, length=%d, interval=%d",
 	      dev, pipe, buffer, length, interval);
-	return -1;
+
+	queue = ehci_create_int_queue(dev, pipe, 1, length, buffer, interval);
+	if (!queue)
+		return -EINVAL;
+
+	start = get_time_ns();
+	while ((backbuffer = ehci_poll_int_queue(dev, queue)) == NULL)
+		if (is_timeout_non_interruptible(start,
+						 USB_CNTL_TIMEOUT * MSECOND)) {
+			dev_err(&dev->dev,
+				"Timeout poll on interrupt endpoint\n");
+			result = -ETIMEDOUT;
+			break;
+		}
+
+	if (backbuffer != buffer) {
+		dev_err(&dev->dev,
+			"got wrong buffer back (%p instead of %p)\n",
+			backbuffer, buffer);
+		if (!result)
+			result = -EINVAL;
+	}
+
+	ret = ehci_destroy_int_queue(dev, queue);
+	if (!result)
+		result = ret;
+	return result;
 }
 
 static int ehci_detect(struct device_d *dev)
@@ -912,6 +1304,8 @@ int ehci_register(struct device_d *dev, struct ehci_data *data)
 
 	ehci->qh_list = dma_alloc_coherent(sizeof(struct QH) * NUM_TD,
 					   DMA_ADDRESS_BROKEN);
+	ehci->periodic_queue = dma_alloc_coherent(sizeof(struct QH),
+						  DMA_ADDRESS_BROKEN);
 	ehci->td = dma_alloc_coherent(sizeof(struct qTD) * NUM_TD,
 				      DMA_ADDRESS_BROKEN);
 
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index d71d056..39de763 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -20,6 +20,15 @@
 
 #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
@@ -51,6 +60,7 @@ struct ehci_hcor {
 #define CMD_RUN		(1 << 0)		/* start/stop HC */
 	uint32_t or_usbsts;
 #define	STD_ASS		(1 << 15)
+#define STS_PSS         (1 << 14)
 #define STS_HALT	(1 << 12)
 	uint32_t or_usbintr;
 	uint32_t or_frindex;
@@ -148,7 +158,10 @@ struct QH {
 	 * Add dummy fill value to make the size of this struct
 	 * aligned to 32 bytes
 	 */
-	uint8_t fill[16];
+	union {
+		uint8_t fill[16];
+		void* buffer;
+	};
 };
 
 #endif /* USB_EHCI_H */
-- 
2.1.4


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

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

* [PATCH 3/5] usb: ehci-hcd: detect re-entrance
  2015-09-22 15:58 [PATCH v6 0/5] input: add usb keyboard driver Peter Mamonov
  2015-09-22 15:58 ` [PATCH 1/5] common: clock: introduce mdelay_non_interruptible() Peter Mamonov
  2015-09-22 15:58 ` [PATCH 2/5] usb: ehci-hcd: port periodic transactions implementation from the u-boot Peter Mamonov
@ 2015-09-22 15:58 ` Peter Mamonov
  2015-09-23 14:23   ` Sascha Hauer
  2015-09-22 15:58 ` [PATCH 4/5] usb: ehci-hcd: use mdelay_non_inerruptible() Peter Mamonov
                   ` (2 subsequent siblings)
  5 siblings, 1 reply; 23+ messages in thread
From: Peter Mamonov @ 2015-09-22 15:58 UTC (permalink / raw)
  To: barebox; +Cc: pmamonov

Signed-off-by: Peter Mamonov <pmamonov@gmail.com>
---
 drivers/usb/host/ehci-hcd.c | 38 ++++++++++++++++++++++++++++++++++----
 1 file changed, 34 insertions(+), 4 deletions(-)

diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index e6748b0..d6df7b8 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -51,6 +51,8 @@ struct ehci_priv {
 	int periodic_schedules;
 	struct QH *periodic_queue;
 	uint32_t *periodic_list;
+	int sem;
+	struct device_d *usedby;
 };
 
 struct int_queue {
@@ -136,6 +138,16 @@ static struct descriptor {
 
 #define ehci_is_TDI()	(ehci->flags & EHCI_HAS_TT)
 
+#define ehci_reentrance_detect(ehci) \
+	if (ehci->sem) \
+		dev_err(&dev->dev, "%s: re-entrance %d (%s:%s)\n", \
+			__func__, \
+			ehci->sem, \
+			ehci->usedby->driver->name, \
+			ehci->usedby->name); \
+	ehci->sem++; \
+	ehci->usedby = &dev->dev;
+
 static int handshake(uint32_t *ptr, uint32_t mask, uint32_t done, int usec)
 {
 	uint32_t result;
@@ -893,12 +905,18 @@ submit_bulk_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
 {
 	struct usb_host *host = dev->host;
 	struct ehci_priv *ehci = to_ehci(host);
+	int ret;
+
+	ehci_reentrance_detect(ehci);
 
 	if (usb_pipetype(pipe) != PIPE_BULK) {
 		dev_dbg(ehci->dev, "non-bulk pipe (type=%lu)", usb_pipetype(pipe));
+		ehci->sem--;
 		return -1;
 	}
-	return ehci_submit_async(dev, pipe, buffer, length, NULL);
+	ret = ehci_submit_async(dev, pipe, buffer, length, NULL);
+	ehci->sem--;
+	return ret;
 }
 
 static int
@@ -907,6 +925,9 @@ submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
 {
 	struct usb_host *host = dev->host;
 	struct ehci_priv *ehci = to_ehci(host);
+	int ret;
+
+	ehci_reentrance_detect(ehci);
 
 	if (usb_pipetype(pipe) != PIPE_CONTROL) {
 		dev_dbg(ehci->dev, "non-control pipe (type=%lu)", usb_pipetype(pipe));
@@ -916,9 +937,13 @@ submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
 	if (usb_pipedevice(pipe) == ehci->rootdev) {
 		if (ehci->rootdev == 0)
 			dev->speed = USB_SPEED_HIGH;
-		return ehci_submit_root(dev, pipe, buffer, length, setup);
+		ret = ehci_submit_root(dev, pipe, buffer, length, setup);
+		ehci->sem--;
+		return ret;
 	}
-	return ehci_submit_async(dev, pipe, buffer, length, setup);
+	ret = ehci_submit_async(dev, pipe, buffer, length, setup);
+	ehci->sem--;
+	return ret;
 }
 
 static int
@@ -1241,12 +1266,16 @@ submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
 	void *backbuffer;
 	int result = 0, ret;
 
+	ehci_reentrance_detect(ehci);
+
 	dev_dbg(ehci->dev, "dev=%p, pipe=%lu, buffer=%p, length=%d, interval=%d",
 	      dev, pipe, buffer, length, interval);
 
 	queue = ehci_create_int_queue(dev, pipe, 1, length, buffer, interval);
-	if (!queue)
+	if (!queue) {
+		ehci->sem--;
 		return -EINVAL;
+	}
 
 	start = get_time_ns();
 	while ((backbuffer = ehci_poll_int_queue(dev, queue)) == NULL)
@@ -1269,6 +1298,7 @@ submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
 	ret = ehci_destroy_int_queue(dev, queue);
 	if (!result)
 		result = ret;
+	ehci->sem--;
 	return result;
 }
 
-- 
2.1.4


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

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

* [PATCH 4/5] usb: ehci-hcd: use mdelay_non_inerruptible()
  2015-09-22 15:58 [PATCH v6 0/5] input: add usb keyboard driver Peter Mamonov
                   ` (2 preceding siblings ...)
  2015-09-22 15:58 ` [PATCH 3/5] usb: ehci-hcd: detect re-entrance Peter Mamonov
@ 2015-09-22 15:58 ` Peter Mamonov
  2015-10-07 13:47   ` Jean-Christophe PLAGNIOL-VILLARD
  2015-09-22 15:58 ` [PATCH 5/5] input: port usb keyboard driver from the u-boot Peter Mamonov
  2015-09-23 14:34 ` [PATCH 1/2] fixup! usb: ehci-hcd: port periodic transactions implementation " Sascha Hauer
  5 siblings, 1 reply; 23+ messages in thread
From: Peter Mamonov @ 2015-09-22 15:58 UTC (permalink / raw)
  To: barebox; +Cc: pmamonov

Signed-off-by: Peter Mamonov <pmamonov@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 d6df7b8..03d6150 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -684,7 +684,7 @@ ehci_submit_root(struct usb_device *dev, unsigned long pipe, void *buffer,
 				 * root
 				 */
 				ehci_powerup_fixup(ehci);
-				mdelay(50);
+				mdelay_non_interruptible(50);
 				ehci->portreset |= 1 << port;
 				/* terminate the reset */
 				ehci_writel(status_reg, reg & ~EHCI_PS_PR);
@@ -747,7 +747,7 @@ ehci_submit_root(struct usb_device *dev, unsigned long pipe, void *buffer,
 		goto unknown;
 	}
 
-	mdelay(1);
+	mdelay_non_interruptible(1);
 	len = min3(srclen, (int)le16_to_cpu(req->length), length);
 	if (srcptr != NULL && len > 0)
 		memcpy(buffer, srcptr, len);
@@ -889,7 +889,7 @@ static int ehci_init(struct usb_host *host)
 	ehci_writel(&ehci->hcor->or_configflag, cmd);
 	/* unblock posted write */
 	cmd = ehci_readl(&ehci->hcor->or_usbcmd);
-	mdelay(5);
+	mdelay_non_interruptible(5);
 
 	ehci->rootdev = 0;
 
-- 
2.1.4


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

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

* [PATCH 5/5] input: port usb keyboard driver from the u-boot
  2015-09-22 15:58 [PATCH v6 0/5] input: add usb keyboard driver Peter Mamonov
                   ` (3 preceding siblings ...)
  2015-09-22 15:58 ` [PATCH 4/5] usb: ehci-hcd: use mdelay_non_inerruptible() Peter Mamonov
@ 2015-09-22 15:58 ` Peter Mamonov
  2015-09-23 14:34 ` [PATCH 1/2] fixup! usb: ehci-hcd: port periodic transactions implementation " Sascha Hauer
  5 siblings, 0 replies; 23+ messages in thread
From: Peter Mamonov @ 2015-09-22 15:58 UTC (permalink / raw)
  To: barebox; +Cc: pmamonov

Signed-off-by: Peter Mamonov <pmamonov@gmail.com>
---
 drivers/input/Kconfig   |   7 +
 drivers/input/Makefile  |   1 +
 drivers/input/usb_kbd.c | 421 ++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 429 insertions(+)
 create mode 100644 drivers/input/usb_kbd.c

diff --git a/drivers/input/Kconfig b/drivers/input/Kconfig
index b4e86fd..24a5d10 100644
--- a/drivers/input/Kconfig
+++ b/drivers/input/Kconfig
@@ -46,4 +46,11 @@ config KEYBOARD_TWL6030
 	help
 	  Say Y here if you want to use TWL6030 power button as a key.
 
+config KEYBOARD_USB
+	bool "USB keyboard"
+	depends on USB_HOST
+	select POLLER
+	help
+	  This driver implements support for usb keyboard.
+
 endmenu
diff --git a/drivers/input/Makefile b/drivers/input/Makefile
index 2143336..40b898c 100644
--- a/drivers/input/Makefile
+++ b/drivers/input/Makefile
@@ -1,3 +1,4 @@
+obj-$(CONFIG_KEYBOARD_USB) += usb_kbd.o
 obj-$(CONFIG_KEYBOARD_GPIO) += gpio_keys.o
 obj-$(CONFIG_KEYBOARD_TWL6030) += twl6030_pwrbtn.o
 obj-$(CONFIG_KEYBOARD_IMX_KEYPAD) += imx_keypad.o
diff --git a/drivers/input/usb_kbd.c b/drivers/input/usb_kbd.c
new file mode 100644
index 0000000..3d70c8d
--- /dev/null
+++ b/drivers/input/usb_kbd.c
@@ -0,0 +1,421 @@
+/*
+ * USB keyboard driver for barebox
+ *
+ * (C) Copyright 2001 Denis Peter, MPL AG Switzerland
+ * (C) Copyright 2015 Peter Mamonov
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <common.h>
+#include <init.h>
+#include <clock.h>
+#include <poller.h>
+#include <usb/usb.h>
+#include <string.h>
+#include <dma.h>
+#include <kfifo.h>
+
+#define USB_KBD_FIFO_SIZE	50
+
+#define REPEAT_RATE	40		/* 40msec -> 25cps */
+#define REPEAT_DELAY	10		/* 10 x REPEAT_RATE = 400msec */
+
+#define NUM_LOCK	0x53
+#define CAPS_LOCK	0x39
+#define SCROLL_LOCK	0x47
+
+/* Modifier bits */
+#define LEFT_CNTR	(1 << 0)
+#define LEFT_SHIFT	(1 << 1)
+#define LEFT_ALT	(1 << 2)
+#define LEFT_GUI	(1 << 3)
+#define RIGHT_CNTR	(1 << 4)
+#define RIGHT_SHIFT	(1 << 5)
+#define RIGHT_ALT	(1 << 6)
+#define RIGHT_GUI	(1 << 7)
+
+/* Size of the keyboard buffer */
+#define USB_KBD_BUFFER_LEN	0x20
+
+/* Keyboard maps */
+static const unsigned char usb_kbd_numkey[] = {
+	'1', '2', '3', '4', '5', '6', '7', '8', '9', '0',
+	'\r', 0x1b, '\b', '\t', ' ', '-', '=', '[', ']',
+	'\\', '#', ';', '\'', '`', ',', '.', '/'
+};
+static const unsigned char usb_kbd_numkey_shifted[] = {
+	'!', '@', '#', '$', '%', '^', '&', '*', '(', ')',
+	'\r', 0x1b, '\b', '\t', ' ', '_', '+', '{', '}',
+	'|', '~', ':', '"', '~', '<', '>', '?'
+};
+
+static const unsigned char usb_kbd_num_keypad[] = {
+	'/', '*', '-', '+', '\r',
+	'1', '2', '3', '4', '5', '6', '7', '8', '9', '0',
+	'.', 0, 0, 0, '='
+};
+
+/*
+ * map arrow keys to ^F/^B ^N/^P, can't really use the proper
+ * ANSI sequence for arrow keys because the queuing code breaks
+ * when a single keypress expands to 3 queue elements
+ */
+static const unsigned char usb_kbd_arrow[] = {
+	0x6, 0x2, 0xe, 0x10
+};
+
+/*
+ * NOTE: It's important for the NUM, CAPS, SCROLL-lock bits to be in this
+ *       order. See usb_kbd_setled() function!
+ */
+#define USB_KBD_NUMLOCK		(1 << 0)
+#define USB_KBD_CAPSLOCK	(1 << 1)
+#define USB_KBD_SCROLLLOCK	(1 << 2)
+#define USB_KBD_CTRL		(1 << 3)
+
+#define USB_KBD_LEDMASK		\
+	(USB_KBD_NUMLOCK | USB_KBD_CAPSLOCK | USB_KBD_SCROLLLOCK)
+
+/*
+ * USB Keyboard reports are 8 bytes in boot protocol.
+ * Appendix B of HID Device Class Definition 1.11
+ */
+#define USB_KBD_BOOT_REPORT_SIZE 8
+
+struct usb_kbd_pdata;
+
+struct usb_kbd_pdata {
+	uint64_t	last_report;
+	uint64_t	last_poll;
+	uint8_t		*new;
+	uint8_t		old[USB_KBD_BOOT_REPORT_SIZE];
+	uint32_t	repeat_delay;
+	uint8_t		flags;
+	struct poller_struct	poller;
+	struct usb_device	*usbdev;
+	struct console_device	cdev;
+	struct kfifo		*recv_fifo;
+	int		lock;
+	unsigned long	intpipe;
+	int		intpktsize;
+	int		intinterval;
+	struct usb_endpoint_descriptor *ep;
+	int (*do_poll)(struct usb_kbd_pdata *);
+};
+
+static int usb_kbd_int_poll(struct usb_kbd_pdata *data)
+{
+	return usb_submit_int_msg(data->usbdev, data->intpipe, data->new,
+				  data->intpktsize, data->intinterval);
+}
+
+static int usb_kbd_cnt_poll(struct usb_kbd_pdata *data)
+{
+	struct usb_interface *iface = &data->usbdev->config.interface[0];
+
+	return usb_get_report(data->usbdev, iface->desc.bInterfaceNumber,
+			      1, 0, data->new, USB_KBD_BOOT_REPORT_SIZE);
+}
+
+#define CAPITAL_MASK	0x20
+/* Translate the scancode in ASCII */
+static int usb_kbd_translate(struct usb_kbd_pdata *data, unsigned char scancode,
+				unsigned char modifier, int pressed)
+{
+	int keycode = 0;
+
+	/* Key released */
+	if (pressed == 0) {
+		data->repeat_delay = 0;
+		return 0;
+	}
+
+	if (pressed == 2) {
+		data->repeat_delay++;
+		if (data->repeat_delay < REPEAT_DELAY)
+			return 0;
+
+		data->repeat_delay = REPEAT_DELAY;
+	}
+
+	/* Alphanumeric values */
+	if ((scancode > 3) && (scancode <= 0x1d)) {
+		keycode = scancode - 4 + 'a';
+
+		if (data->flags & USB_KBD_CAPSLOCK)
+			keycode &= ~CAPITAL_MASK;
+
+		if (modifier & (LEFT_SHIFT | RIGHT_SHIFT)) {
+			/* Handle CAPSLock + Shift pressed simultaneously */
+			if (keycode & CAPITAL_MASK)
+				keycode &= ~CAPITAL_MASK;
+			else
+				keycode |= CAPITAL_MASK;
+		}
+	}
+
+	if ((scancode > 0x1d) && (scancode < 0x3a)) {
+		/* Shift pressed */
+		if (modifier & (LEFT_SHIFT | RIGHT_SHIFT))
+			keycode = usb_kbd_numkey_shifted[scancode - 0x1e];
+		else
+			keycode = usb_kbd_numkey[scancode - 0x1e];
+	}
+
+	/* Arrow keys */
+	if ((scancode >= 0x4f) && (scancode <= 0x52))
+		keycode = usb_kbd_arrow[scancode - 0x4f];
+
+	/* Numeric keypad */
+	if ((scancode >= 0x54) && (scancode <= 0x67))
+		keycode = usb_kbd_num_keypad[scancode - 0x54];
+
+	if (data->flags & USB_KBD_CTRL)
+		keycode = scancode - 0x3;
+
+	if (pressed == 1) {
+		if (scancode == NUM_LOCK) {
+			data->flags ^= USB_KBD_NUMLOCK;
+			return 1;
+		}
+
+		if (scancode == CAPS_LOCK) {
+			data->flags ^= USB_KBD_CAPSLOCK;
+			return 1;
+		}
+		if (scancode == SCROLL_LOCK) {
+			data->flags ^= USB_KBD_SCROLLLOCK;
+			return 1;
+		}
+	}
+
+	/* Report keycode if any */
+	if (keycode) {
+		pr_debug("%s: key pressed: '%c'\n", __FUNCTION__, keycode);
+		kfifo_put(data->recv_fifo, (u_char*)&keycode, sizeof(keycode));
+	}
+
+	return 0;
+}
+
+static uint32_t usb_kbd_service_key(struct usb_kbd_pdata *data, int i, int up)
+{
+	uint32_t res = 0;
+	uint8_t *new;
+	uint8_t *old;
+
+	if (up) {
+		new = data->old;
+		old = data->new;
+	} else {
+		new = data->new;
+		old = data->old;
+	}
+
+	if ((old[i] > 3) &&
+	    (memscan(new + 2, old[i], USB_KBD_BOOT_REPORT_SIZE - 2) ==
+			new + USB_KBD_BOOT_REPORT_SIZE)) {
+		res |= usb_kbd_translate(data, old[i], data->new[0], up);
+	}
+
+	return res;
+}
+
+static void usb_kbd_setled(struct usb_kbd_pdata *data)
+{
+	struct usb_device *usbdev = data->usbdev;
+	struct usb_interface *iface = &usbdev->config.interface[0];
+	uint8_t leds = (uint8_t)(data->flags & USB_KBD_LEDMASK);
+
+	usb_control_msg(usbdev, usb_sndctrlpipe(usbdev, 0),
+		USB_REQ_SET_REPORT, USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+		0x200, iface->desc.bInterfaceNumber, &leds, 1, USB_CNTL_TIMEOUT);
+}
+
+
+static int usb_kbd_process(struct usb_kbd_pdata *data)
+{
+	int i, res = 0;
+
+	/* No combo key pressed */
+	if (data->new[0] == 0x00)
+		data->flags &= ~USB_KBD_CTRL;
+	/* Left or Right Ctrl pressed */
+	else if ((data->new[0] == LEFT_CNTR) || (data->new[0] == RIGHT_CNTR))
+		data->flags |= USB_KBD_CTRL;
+
+	for (i = 2; i < USB_KBD_BOOT_REPORT_SIZE; i++) {
+		res |= usb_kbd_service_key(data, i, 0);
+		res |= usb_kbd_service_key(data, i, 1);
+	}
+
+	/* Key is still pressed */
+	if ((data->new[2] > 3) && (data->old[2] == data->new[2]))
+		res |= usb_kbd_translate(data, data->new[2], data->new[0], 2);
+
+	if (res == 1)
+		usb_kbd_setled(data);
+
+	return 1;
+}
+
+static void usb_kbd_poll(struct poller_struct *poller)
+{
+	struct usb_kbd_pdata *data = container_of(poller,
+						  struct usb_kbd_pdata, poller);
+	struct usb_device *usbdev = data->usbdev;
+	int diff, tout;
+
+	if (data->lock)
+		return;
+	data->lock = 1;
+
+	if (!is_timeout_non_interruptible(data->last_poll, REPEAT_RATE * MSECOND / 2))
+		goto exit;
+	data->last_poll = get_time_ns();
+
+	if (0 > data->do_poll(data)) {
+		/* exit and lock forever */
+		dev_err(&usbdev->dev,
+			"usb_submit_int_msg() failed. Keyboard disconnect?\n");
+		return;
+	}
+	diff = memcmp(data->old, data->new, USB_KBD_BOOT_REPORT_SIZE);
+	tout = get_time_ns() > data->last_report + REPEAT_RATE * MSECOND;
+	if (diff || tout) {
+		data->last_report = get_time_ns();
+		if (diff) {
+			pr_debug("%s: old report: %016llx\n",
+				__func__,
+				*((volatile uint64_t *)data->old));
+			pr_debug("%s: new report: %016llx\n\n",
+				__func__,
+				*((volatile uint64_t *)data->new));
+		}
+		usb_kbd_process(data);
+		memcpy(data->old, data->new, USB_KBD_BOOT_REPORT_SIZE);
+	}
+
+exit:
+	data->lock = 0;
+}
+
+static int usb_kbd_getc(struct console_device *cdev)
+{
+	int code = 0;
+	struct usb_kbd_pdata *data = container_of(cdev, struct usb_kbd_pdata, cdev);
+
+	kfifo_get(data->recv_fifo, (u_char*)&code, sizeof(int));
+	return code;
+}
+
+static int usb_kbd_tstc(struct console_device *cdev)
+{
+	struct usb_kbd_pdata *data = container_of(cdev, struct usb_kbd_pdata, cdev);
+
+	return (kfifo_len(data->recv_fifo) == 0) ? 0 : 1;
+}
+
+static int usb_kbd_probe(struct usb_device *usbdev,
+			 const struct usb_device_id *id)
+{
+	int ret;
+	struct usb_interface *iface = &usbdev->config.interface[0];
+	struct usb_kbd_pdata *data;
+	struct console_device *cdev;
+
+	dev_info(&usbdev->dev, "USB keyboard found\n");
+	dev_dbg(&usbdev->dev, "Debug enabled\n");
+	ret = usb_set_protocol(usbdev, iface->desc.bInterfaceNumber, 0);
+	if (ret < 0)
+		return ret;
+
+	ret = usb_set_idle(usbdev, iface->desc.bInterfaceNumber, 1, 0);
+	if (ret < 0)
+		return ret;
+
+	data = xzalloc(sizeof(struct usb_kbd_pdata));
+	usbdev->drv_data = data;
+	data->recv_fifo = kfifo_alloc(USB_KBD_FIFO_SIZE);
+	data->new = dma_alloc_coherent(USB_KBD_BOOT_REPORT_SIZE, NULL);
+
+	data->usbdev = usbdev;
+	data->last_report = get_time_ns();
+
+	data->ep = &iface->ep_desc[0];
+	data->intpipe = usb_rcvintpipe(usbdev, data->ep->bEndpointAddress);
+	data->intpktsize = min(usb_maxpacket(usbdev, data->intpipe),
+			       USB_KBD_BOOT_REPORT_SIZE);
+	data->intinterval = data->ep->bInterval;
+	/* test polling via interrupt endpoint */
+	data->do_poll = usb_kbd_int_poll;
+	ret = data->do_poll(data);
+	if (ret < 0) {
+		/* fall back to polling via control enpoint */
+		data->do_poll = usb_kbd_cnt_poll;
+		usb_set_idle(usbdev,
+			     iface->desc.bInterfaceNumber, 0, 0);
+		ret = data->do_poll(data);
+		if (ret < 0) {
+			/* no luck */
+			kfifo_free(data->recv_fifo);
+			dma_free_coherent(data->new, 0,
+					  USB_KBD_BOOT_REPORT_SIZE);
+			free(data);
+			return ret;
+		} else
+			dev_dbg(&usbdev->dev, "poll keyboard via cont ep\n");
+	} else
+		dev_dbg(&usbdev->dev, "poll keyboard via int ep\n");
+
+	cdev = &data->cdev;
+	usbdev->dev.type_data = cdev;
+	cdev->dev = &usbdev->dev;
+	cdev->tstc = usb_kbd_tstc;
+	cdev->getc = usb_kbd_getc;
+
+	console_register(cdev);
+	console_set_active(cdev, CONSOLE_STDIN);
+
+	data->poller.func = usb_kbd_poll;
+	return poller_register(&data->poller);
+}
+
+static void usb_kbd_disconnect(struct usb_device *usbdev)
+{
+	struct usb_kbd_pdata *data = usbdev->drv_data;
+
+	poller_unregister(&data->poller);
+	console_unregister(&data->cdev);
+	kfifo_free(data->recv_fifo);
+	dma_free_coherent(data->new, 0, USB_KBD_BOOT_REPORT_SIZE);
+	free(data);
+}
+
+static struct usb_device_id usb_kbd_usb_ids[] = {
+	{ USB_INTERFACE_INFO(3, 1, 1) }, // usb keyboard
+	{ }
+};
+
+static struct usb_driver usb_kbd_driver = {
+	.name =		"usb-keyboard",
+	.id_table =	usb_kbd_usb_ids,
+	.probe =	usb_kbd_probe,
+	.disconnect =	usb_kbd_disconnect,
+};
+
+static int __init usb_kbd_init(void)
+{
+	return usb_driver_register(&usb_kbd_driver);
+}
+device_initcall(usb_kbd_init);
-- 
2.1.4


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

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

* Re: [PATCH 1/5] common: clock: introduce mdelay_non_interruptible()
  2015-09-22 15:58 ` [PATCH 1/5] common: clock: introduce mdelay_non_interruptible() Peter Mamonov
@ 2015-09-22 21:15   ` Antony Pavlov
  2015-09-22 21:20     ` Peter Mamonov
  0 siblings, 1 reply; 23+ messages in thread
From: Antony Pavlov @ 2015-09-22 21:15 UTC (permalink / raw)
  To: Peter Mamonov; +Cc: barebox

On Tue, 22 Sep 2015 18:58:30 +0300
Peter Mamonov <pmamonov@gmail.com> wrote:

> Signed-off-by: Peter Mamonov <pmamonov@gmail.com>
> ---
>  common/clock.c   | 8 ++++++++
>  include/clock.h  | 1 +
>  include/common.h | 1 +
>  3 files changed, 10 insertions(+)
> 
> diff --git a/common/clock.c b/common/clock.c
> index 35c9e6c..51cf9e4 100644
> --- a/common/clock.c
> +++ b/common/clock.c
> @@ -202,6 +202,14 @@ void mdelay(unsigned long msecs)
>  }
>  EXPORT_SYMBOL(mdelay);
>  
> +void mdelay_non_interruptible(unsigned long msecs)
> +{
> +	uint64_t start = get_time_ns();
> +
> +	while(!is_timeout_non_interruptible(start, msecs * MSECOND));

ERROR: space required before the open parenthesis '('
#107: FILE: common/clock.c:209:
+	while(!is_timeout_non_interruptible(start, msecs * MSECOND));

ERROR: trailing statements should be on next line
#107: FILE: common/clock.c:209:
+	while(!is_timeout_non_interruptible(start, msecs * MSECOND));


> +}
> +EXPORT_SYMBOL(mdelay_non_interruptible);
> +
>  int init_clock(struct clocksource *cs)
>  {
>  	current_clock = cs;
> diff --git a/include/clock.h b/include/clock.h
> index 691befc..68d71d7 100644
> --- a/include/clock.h
> +++ b/include/clock.h
> @@ -38,6 +38,7 @@ int is_timeout_non_interruptible(uint64_t start_ns, uint64_t time_offset_ns);
>  
>  void ndelay(unsigned long nsecs);
>  void mdelay(unsigned long msecs);
> +void mdelay_non_interruptible (unsigned long msecs);
>  
>  #define SECOND ((uint64_t)(1000 * 1000 * 1000))
>  #define MSECOND ((uint64_t)(1000 * 1000))
> diff --git a/include/common.h b/include/common.h
> index 553a7f4..c576908 100644
> --- a/include/common.h
> +++ b/include/common.h
> @@ -72,6 +72,7 @@ void __noreturn poweroff(void);
>  /* lib_$(ARCH)/time.c */
>  void	udelay (unsigned long);
>  void	mdelay (unsigned long);
> +void	mdelay_non_interruptible (unsigned long);
>  
>  /* lib_generic/crc32.c */
>  uint32_t crc32(uint32_t, const void*, unsigned int);
> -- 
> 2.1.4
> 
> 
> _______________________________________________
> barebox mailing list
> barebox@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/barebox


-- 
-- 
Best regards,
  Antony Pavlov

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

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

* Re: [PATCH 1/5] common: clock: introduce mdelay_non_interruptible()
  2015-09-22 21:15   ` Antony Pavlov
@ 2015-09-22 21:20     ` Peter Mamonov
  0 siblings, 0 replies; 23+ messages in thread
From: Peter Mamonov @ 2015-09-22 21:20 UTC (permalink / raw)
  To: Antony Pavlov; +Cc: barebox

On Wed, 23 Sep 2015 00:15:28 +0300
Antony Pavlov <antonynpavlov@gmail.com> wrote:

> On Tue, 22 Sep 2015 18:58:30 +0300
> Peter Mamonov <pmamonov@gmail.com> wrote:
> 
> > Signed-off-by: Peter Mamonov <pmamonov@gmail.com>
> > ---
> >  common/clock.c   | 8 ++++++++
> >  include/clock.h  | 1 +
> >  include/common.h | 1 +
> >  3 files changed, 10 insertions(+)
> > 
> > diff --git a/common/clock.c b/common/clock.c
> > index 35c9e6c..51cf9e4 100644
> > --- a/common/clock.c
> > +++ b/common/clock.c
> > @@ -202,6 +202,14 @@ void mdelay(unsigned long msecs)
> >  }
> >  EXPORT_SYMBOL(mdelay);
> >  
> > +void mdelay_non_interruptible(unsigned long msecs)
> > +{
> > +	uint64_t start = get_time_ns();
> > +
> > +	while(!is_timeout_non_interruptible(start, msecs *
> > MSECOND));
> 
> ERROR: space required before the open parenthesis '('
> #107: FILE: common/clock.c:209:
> +	while(!is_timeout_non_interruptible(start, msecs * MSECOND));
> 
> ERROR: trailing statements should be on next line
> #107: FILE: common/clock.c:209:
> +	while(!is_timeout_non_interruptible(start, msecs * MSECOND));

Same formatting 8 lines above, where I copied this code from :P
Anyway, will fix it tomorrow.

> 
> 
> > +}
> > +EXPORT_SYMBOL(mdelay_non_interruptible);
> > +
> >  int init_clock(struct clocksource *cs)
> >  {
> >  	current_clock = cs;
> > diff --git a/include/clock.h b/include/clock.h
> > index 691befc..68d71d7 100644
> > --- a/include/clock.h
> > +++ b/include/clock.h
> > @@ -38,6 +38,7 @@ int is_timeout_non_interruptible(uint64_t
> > start_ns, uint64_t time_offset_ns); 
> >  void ndelay(unsigned long nsecs);
> >  void mdelay(unsigned long msecs);
> > +void mdelay_non_interruptible (unsigned long msecs);
> >  
> >  #define SECOND ((uint64_t)(1000 * 1000 * 1000))
> >  #define MSECOND ((uint64_t)(1000 * 1000))
> > diff --git a/include/common.h b/include/common.h
> > index 553a7f4..c576908 100644
> > --- a/include/common.h
> > +++ b/include/common.h
> > @@ -72,6 +72,7 @@ void __noreturn poweroff(void);
> >  /* lib_$(ARCH)/time.c */
> >  void	udelay (unsigned long);
> >  void	mdelay (unsigned long);
> > +void	mdelay_non_interruptible (unsigned long);
> >  
> >  /* lib_generic/crc32.c */
> >  uint32_t crc32(uint32_t, const void*, unsigned int);
> > -- 
> > 2.1.4
> > 
> > 
> > _______________________________________________
> > barebox mailing list
> > barebox@lists.infradead.org
> > http://lists.infradead.org/mailman/listinfo/barebox
> 
> 


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

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

* Re: [PATCH 3/5] usb: ehci-hcd: detect re-entrance
  2015-09-22 15:58 ` [PATCH 3/5] usb: ehci-hcd: detect re-entrance Peter Mamonov
@ 2015-09-23 14:23   ` Sascha Hauer
  0 siblings, 0 replies; 23+ messages in thread
From: Sascha Hauer @ 2015-09-23 14:23 UTC (permalink / raw)
  To: Peter Mamonov; +Cc: barebox

On Tue, Sep 22, 2015 at 06:58:32PM +0300, Peter Mamonov wrote:
> Signed-off-by: Peter Mamonov <pmamonov@gmail.com>
> ---
>  drivers/usb/host/ehci-hcd.c | 38 ++++++++++++++++++++++++++++++++++----
>  1 file changed, 34 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
> index e6748b0..d6df7b8 100644
> --- a/drivers/usb/host/ehci-hcd.c
> +++ b/drivers/usb/host/ehci-hcd.c
> @@ -51,6 +51,8 @@ struct ehci_priv {
>  	int periodic_schedules;
>  	struct QH *periodic_queue;
>  	uint32_t *periodic_list;
> +	int sem;
> +	struct device_d *usedby;
>  };
>  
>  struct int_queue {
> @@ -136,6 +138,16 @@ static struct descriptor {
>  
>  #define ehci_is_TDI()	(ehci->flags & EHCI_HAS_TT)
>  
> +#define ehci_reentrance_detect(ehci) \
> +	if (ehci->sem) \
> +		dev_err(&dev->dev, "%s: re-entrance %d (%s:%s)\n", \
> +			__func__, \
> +			ehci->sem, \
> +			ehci->usedby->driver->name, \
> +			ehci->usedby->name); \
> +	ehci->sem++; \
> +	ehci->usedby = &dev->dev;

This should be a static inline function rather than a define. You can
pass the function name as const char *.

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] 23+ messages in thread

* [PATCH 1/2] fixup! usb: ehci-hcd: port periodic transactions implementation from the u-boot
  2015-09-22 15:58 [PATCH v6 0/5] input: add usb keyboard driver Peter Mamonov
                   ` (4 preceding siblings ...)
  2015-09-22 15:58 ` [PATCH 5/5] input: port usb keyboard driver from the u-boot Peter Mamonov
@ 2015-09-23 14:34 ` Sascha Hauer
  2015-09-23 14:34   ` [PATCH 2/2] fixup! input: port usb keyboard driver " Sascha Hauer
  5 siblings, 1 reply; 23+ messages in thread
From: Sascha Hauer @ 2015-09-23 14:34 UTC (permalink / raw)
  To: Barebox List

Flush/invalidate caches for interrupt transfers.
---
 drivers/usb/host/ehci-hcd.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 394f2d1..4946bfa 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -1266,6 +1266,9 @@ submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
 	dev_dbg(ehci->dev, "dev=%p, pipe=%lu, buffer=%p, length=%d, interval=%d",
 	      dev, pipe, buffer, length, interval);
 
+	dma_sync_single_for_device((unsigned long)buffer, length,
+				   DMA_BIDIRECTIONAL);
+
 	queue = ehci_create_int_queue(dev, pipe, 1, length, buffer, interval);
 	if (!queue) {
 		ehci->sem--;
@@ -1290,6 +1293,9 @@ submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
 			result = -EINVAL;
 	}
 
+	dma_sync_single_for_cpu((unsigned long)buffer, length,
+				DMA_BIDIRECTIONAL);
+
 	ret = ehci_destroy_int_queue(dev, queue);
 	if (!result)
 		result = ret;
-- 
2.5.1


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

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

* [PATCH 2/2] fixup! input: port usb keyboard driver from the u-boot
  2015-09-23 14:34 ` [PATCH 1/2] fixup! usb: ehci-hcd: port periodic transactions implementation " Sascha Hauer
@ 2015-09-23 14:34   ` Sascha Hauer
  0 siblings, 0 replies; 23+ messages in thread
From: Sascha Hauer @ 2015-09-23 14:34 UTC (permalink / raw)
  To: Barebox List

No need for coherent memory in the keyboard driver. The USB driver should
handle the cache handling.
---
 drivers/input/usb_kbd.c | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/drivers/input/usb_kbd.c b/drivers/input/usb_kbd.c
index 3d70c8d..8c08aba 100644
--- a/drivers/input/usb_kbd.c
+++ b/drivers/input/usb_kbd.c
@@ -347,7 +347,7 @@ static int usb_kbd_probe(struct usb_device *usbdev,
 	data = xzalloc(sizeof(struct usb_kbd_pdata));
 	usbdev->drv_data = data;
 	data->recv_fifo = kfifo_alloc(USB_KBD_FIFO_SIZE);
-	data->new = dma_alloc_coherent(USB_KBD_BOOT_REPORT_SIZE, NULL);
+	data->new = dma_alloc(USB_KBD_BOOT_REPORT_SIZE);
 
 	data->usbdev = usbdev;
 	data->last_report = get_time_ns();
@@ -369,8 +369,7 @@ static int usb_kbd_probe(struct usb_device *usbdev,
 		if (ret < 0) {
 			/* no luck */
 			kfifo_free(data->recv_fifo);
-			dma_free_coherent(data->new, 0,
-					  USB_KBD_BOOT_REPORT_SIZE);
+			dma_free(data->new);
 			free(data);
 			return ret;
 		} else
@@ -398,7 +397,7 @@ static void usb_kbd_disconnect(struct usb_device *usbdev)
 	poller_unregister(&data->poller);
 	console_unregister(&data->cdev);
 	kfifo_free(data->recv_fifo);
-	dma_free_coherent(data->new, 0, USB_KBD_BOOT_REPORT_SIZE);
+	dma_free(data->new);
 	free(data);
 }
 
-- 
2.5.1


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

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

* Re: [PATCH 4/5] usb: ehci-hcd: use mdelay_non_inerruptible()
  2015-09-22 15:58 ` [PATCH 4/5] usb: ehci-hcd: use mdelay_non_inerruptible() Peter Mamonov
@ 2015-10-07 13:47   ` Jean-Christophe PLAGNIOL-VILLARD
  2015-10-07 14:40     ` Peter Mamonov
  0 siblings, 1 reply; 23+ messages in thread
From: Jean-Christophe PLAGNIOL-VILLARD @ 2015-10-07 13:47 UTC (permalink / raw)
  To: Peter Mamonov; +Cc: barebox

On 18:58 Tue 22 Sep     , Peter Mamonov wrote:
> Signed-off-by: Peter Mamonov <pmamonov@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 d6df7b8..03d6150 100644
> --- a/drivers/usb/host/ehci-hcd.c
> +++ b/drivers/usb/host/ehci-hcd.c
> @@ -684,7 +684,7 @@ ehci_submit_root(struct usb_device *dev, unsigned long pipe, void *buffer,
>  				 * root
>  				 */
>  				ehci_powerup_fixup(ehci);
> -				mdelay(50);
> +				mdelay_non_interruptible(50);
>  				ehci->portreset |= 1 << port;
>  				/* terminate the reset */
>  				ehci_writel(status_reg, reg & ~EHCI_PS_PR);
> @@ -747,7 +747,7 @@ ehci_submit_root(struct usb_device *dev, unsigned long pipe, void *buffer,
>  		goto unknown;
>  	}
>  
> -	mdelay(1);
> +	mdelay_non_interruptible(1);
>  	len = min3(srclen, (int)le16_to_cpu(req->length), length);
>  	if (srcptr != NULL && len > 0)
>  		memcpy(buffer, srcptr, len);
> @@ -889,7 +889,7 @@ static int ehci_init(struct usb_host *host)
>  	ehci_writel(&ehci->hcor->or_configflag, cmd);
>  	/* unblock posted write */
>  	cmd = ehci_readl(&ehci->hcor->or_usbcmd);
> -	mdelay(5);
> +	mdelay_non_interruptible(5);
why do you need that much non interruptible delau?
>  
>  	ehci->rootdev = 0;
>  
> -- 
> 2.1.4
> 
> 
> _______________________________________________
> barebox mailing list
> barebox@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/barebox

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

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

* Re: [PATCH 4/5] usb: ehci-hcd: use mdelay_non_inerruptible()
  2015-10-07 13:47   ` Jean-Christophe PLAGNIOL-VILLARD
@ 2015-10-07 14:40     ` Peter Mamonov
  2015-10-07 15:40       ` Jean-Christophe PLAGNIOL-VILLARD
  0 siblings, 1 reply; 23+ messages in thread
From: Peter Mamonov @ 2015-10-07 14:40 UTC (permalink / raw)
  To: Jean-Christophe PLAGNIOL-VILLARD; +Cc: barebox

On Wed, 7 Oct 2015 15:47:03 +0200
Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com> wrote:

> On 18:58 Tue 22 Sep     , Peter Mamonov wrote:
> > Signed-off-by: Peter Mamonov <pmamonov@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 d6df7b8..03d6150 100644
> > --- a/drivers/usb/host/ehci-hcd.c
> > +++ b/drivers/usb/host/ehci-hcd.c
> > @@ -684,7 +684,7 @@ ehci_submit_root(struct usb_device *dev,
> > unsigned long pipe, void *buffer,
> >  				 * root
> >  				 */
> >  				ehci_powerup_fixup(ehci);
> > -				mdelay(50);
> > +				mdelay_non_interruptible(50);
> >  				ehci->portreset |= 1 << port;
> >  				/* terminate the reset */
> >  				ehci_writel(status_reg, reg &
> > ~EHCI_PS_PR); @@ -747,7 +747,7 @@ ehci_submit_root(struct
> > usb_device *dev, unsigned long pipe, void *buffer, goto unknown;
> >  	}
> >  
> > -	mdelay(1);
> > +	mdelay_non_interruptible(1);
> >  	len = min3(srclen, (int)le16_to_cpu(req->length), length);
> >  	if (srcptr != NULL && len > 0)
> >  		memcpy(buffer, srcptr, len);
> > @@ -889,7 +889,7 @@ static int ehci_init(struct usb_host *host)
> >  	ehci_writel(&ehci->hcor->or_configflag, cmd);
> >  	/* unblock posted write */
> >  	cmd = ehci_readl(&ehci->hcor->or_usbcmd);
> > -	mdelay(5);
> > +	mdelay_non_interruptible(5);
> why do you need that much non interruptible delau?

Non-interruptible delays are needed here to prevent ehci_* functions
re-entrance. The re-entrance occurs during a usb bus scan, after
detection of a usb keyboard. As soon as a USB keyboard is detected, it's
driver starts the poller, which interferes with the process of usb bus scan.
However that last one delay may be interruptible.


> >  
> >  	ehci->rootdev = 0;
> >  
> > -- 
> > 2.1.4
> > 
> > 
> > _______________________________________________
> > barebox mailing list
> > barebox@lists.infradead.org
> > http://lists.infradead.org/mailman/listinfo/barebox


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

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

* Re: [PATCH 4/5] usb: ehci-hcd: use mdelay_non_inerruptible()
  2015-10-07 14:40     ` Peter Mamonov
@ 2015-10-07 15:40       ` Jean-Christophe PLAGNIOL-VILLARD
  2015-10-07 16:52         ` Peter Mamonov
  0 siblings, 1 reply; 23+ messages in thread
From: Jean-Christophe PLAGNIOL-VILLARD @ 2015-10-07 15:40 UTC (permalink / raw)
  To: Peter Mamonov; +Cc: barebox

On 17:40 Wed 07 Oct     , Peter Mamonov wrote:
> On Wed, 7 Oct 2015 15:47:03 +0200
> Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com> wrote:
> 
> > On 18:58 Tue 22 Sep     , Peter Mamonov wrote:
> > > Signed-off-by: Peter Mamonov <pmamonov@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 d6df7b8..03d6150 100644
> > > --- a/drivers/usb/host/ehci-hcd.c
> > > +++ b/drivers/usb/host/ehci-hcd.c
> > > @@ -684,7 +684,7 @@ ehci_submit_root(struct usb_device *dev,
> > > unsigned long pipe, void *buffer,
> > >  				 * root
> > >  				 */
> > >  				ehci_powerup_fixup(ehci);
> > > -				mdelay(50);
> > > +				mdelay_non_interruptible(50);
> > >  				ehci->portreset |= 1 << port;
> > >  				/* terminate the reset */
> > >  				ehci_writel(status_reg, reg &
> > > ~EHCI_PS_PR); @@ -747,7 +747,7 @@ ehci_submit_root(struct
> > > usb_device *dev, unsigned long pipe, void *buffer, goto unknown;
> > >  	}
> > >  
> > > -	mdelay(1);
> > > +	mdelay_non_interruptible(1);
> > >  	len = min3(srclen, (int)le16_to_cpu(req->length), length);
> > >  	if (srcptr != NULL && len > 0)
> > >  		memcpy(buffer, srcptr, len);
> > > @@ -889,7 +889,7 @@ static int ehci_init(struct usb_host *host)
> > >  	ehci_writel(&ehci->hcor->or_configflag, cmd);
> > >  	/* unblock posted write */
> > >  	cmd = ehci_readl(&ehci->hcor->or_usbcmd);
> > > -	mdelay(5);
> > > +	mdelay_non_interruptible(5);
> > why do you need that much non interruptible delau?
> 
> Non-interruptible delays are needed here to prevent ehci_* functions
> re-entrance. The re-entrance occurs during a usb bus scan, after
> detection of a usb keyboard. As soon as a USB keyboard is detected, it's
> driver starts the poller, which interferes with the process of usb bus scan.
> However that last one delay may be interruptible.

my problem is as soon as you start a usb control msg you block everything

nothing else can run in barebox

can slow down barebox boot

I do think we need a real mdelay_non_interruptible feature but just forbidden
to recall usb control msg.
But the rest of barebox can run durring those 5ms

Best Regards,
J.

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

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

* Re: [PATCH 4/5] usb: ehci-hcd: use mdelay_non_inerruptible()
  2015-10-07 15:40       ` Jean-Christophe PLAGNIOL-VILLARD
@ 2015-10-07 16:52         ` Peter Mamonov
  2015-10-12  7:00           ` Sascha Hauer
  2015-10-13  2:04           ` Jean-Christophe PLAGNIOL-VILLARD
  0 siblings, 2 replies; 23+ messages in thread
From: Peter Mamonov @ 2015-10-07 16:52 UTC (permalink / raw)
  To: Jean-Christophe PLAGNIOL-VILLARD; +Cc: barebox

On Wed, 7 Oct 2015 17:40:24 +0200
Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com> wrote:

> On 17:40 Wed 07 Oct     , Peter Mamonov wrote:
> > On Wed, 7 Oct 2015 15:47:03 +0200
> > Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com> wrote:
> > 
> > > On 18:58 Tue 22 Sep     , Peter Mamonov wrote:
> > > > Signed-off-by: Peter Mamonov <pmamonov@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 d6df7b8..03d6150 100644
> > > > --- a/drivers/usb/host/ehci-hcd.c
> > > > +++ b/drivers/usb/host/ehci-hcd.c
> > > > @@ -684,7 +684,7 @@ ehci_submit_root(struct usb_device *dev,
> > > > unsigned long pipe, void *buffer,
> > > >  				 * root
> > > >  				 */
> > > >  				ehci_powerup_fixup(ehci);
> > > > -				mdelay(50);
> > > > +				mdelay_non_interruptible(50);
> > > >  				ehci->portreset |= 1 << port;
> > > >  				/* terminate the reset */
> > > >  				ehci_writel(status_reg, reg &
> > > > ~EHCI_PS_PR); @@ -747,7 +747,7 @@ ehci_submit_root(struct
> > > > usb_device *dev, unsigned long pipe, void *buffer, goto unknown;
> > > >  	}
> > > >  
> > > > -	mdelay(1);
> > > > +	mdelay_non_interruptible(1);
> > > >  	len = min3(srclen, (int)le16_to_cpu(req->length),
> > > > length); if (srcptr != NULL && len > 0)
> > > >  		memcpy(buffer, srcptr, len);
> > > > @@ -889,7 +889,7 @@ static int ehci_init(struct usb_host *host)
> > > >  	ehci_writel(&ehci->hcor->or_configflag, cmd);
> > > >  	/* unblock posted write */
> > > >  	cmd = ehci_readl(&ehci->hcor->or_usbcmd);
> > > > -	mdelay(5);
> > > > +	mdelay_non_interruptible(5);
> > > why do you need that much non interruptible delau?
> > 
> > Non-interruptible delays are needed here to prevent ehci_* functions
> > re-entrance. The re-entrance occurs during a usb bus scan, after
> > detection of a usb keyboard. As soon as a USB keyboard is detected,
> > it's driver starts the poller, which interferes with the process of
> > usb bus scan. However that last one delay may be interruptible.
> 
> my problem is as soon as you start a usb control msg you block
> everything
> 
> nothing else can run in barebox
> 
> can slow down barebox boot
> 
> I do think we need a real mdelay_non_interruptible feature but just
> forbidden to recall usb control msg.
> But the rest of barebox can run durring those 5ms

Well, I think it can be done by returning -EAGAIN on re-entrance
detection in ehci_* functions [1], and skipping the poll in the keyboard
driver.

By the way, could you clarify: do you really experience
considerable barebox slowdown or you make an assumtion based on the
code analysis?

[1]
http://lists.infradead.org/pipermail/barebox/2015-September/024715.html

Regards,
Peter

> 
> Best Regards,
> J.


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

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

* Re: [PATCH 4/5] usb: ehci-hcd: use mdelay_non_inerruptible()
  2015-10-07 16:52         ` Peter Mamonov
@ 2015-10-12  7:00           ` Sascha Hauer
  2015-10-12 11:43             ` Peter Mamonov
  2015-10-13  2:04           ` Jean-Christophe PLAGNIOL-VILLARD
  1 sibling, 1 reply; 23+ messages in thread
From: Sascha Hauer @ 2015-10-12  7:00 UTC (permalink / raw)
  To: Peter Mamonov; +Cc: barebox

On Wed, Oct 07, 2015 at 07:52:21PM +0300, Peter Mamonov wrote:
> On Wed, 7 Oct 2015 17:40:24 +0200
> > > Non-interruptible delays are needed here to prevent ehci_* functions
> > > re-entrance. The re-entrance occurs during a usb bus scan, after
> > > detection of a usb keyboard. As soon as a USB keyboard is detected,
> > > it's driver starts the poller, which interferes with the process of
> > > usb bus scan. However that last one delay may be interruptible.
> > 
> > my problem is as soon as you start a usb control msg you block
> > everything
> > 
> > nothing else can run in barebox
> > 
> > can slow down barebox boot
> > 
> > I do think we need a real mdelay_non_interruptible feature but just
> > forbidden to recall usb control msg.
> > But the rest of barebox can run durring those 5ms
> 
> Well, I think it can be done by returning -EAGAIN on re-entrance
> detection in ehci_* functions [1], and skipping the poll in the keyboard
> driver.

Could you tell us what you have done to get re-entrance problems? I have
just replaced the mdelay_non_interruptible with regular mdelay in the
ehci driver and didn't notice any problems. Could you verify the
_non_interruptible is still needed?

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] 23+ messages in thread

* Re: [PATCH 4/5] usb: ehci-hcd: use mdelay_non_inerruptible()
  2015-10-12  7:00           ` Sascha Hauer
@ 2015-10-12 11:43             ` Peter Mamonov
  2015-10-12 13:44               ` Sascha Hauer
  0 siblings, 1 reply; 23+ messages in thread
From: Peter Mamonov @ 2015-10-12 11:43 UTC (permalink / raw)
  To: Sascha Hauer; +Cc: barebox

On Mon, 12 Oct 2015 09:00:21 +0200
Sascha Hauer <s.hauer@pengutronix.de> wrote:

> On Wed, Oct 07, 2015 at 07:52:21PM +0300, Peter Mamonov wrote:
> > On Wed, 7 Oct 2015 17:40:24 +0200
> > > > Non-interruptible delays are needed here to prevent ehci_*
> > > > functions re-entrance. The re-entrance occurs during a usb bus
> > > > scan, after detection of a usb keyboard. As soon as a USB
> > > > keyboard is detected, it's driver starts the poller, which
> > > > interferes with the process of usb bus scan. However that last
> > > > one delay may be interruptible.
> > > 
> > > my problem is as soon as you start a usb control msg you block
> > > everything
> > > 
> > > nothing else can run in barebox
> > > 
> > > can slow down barebox boot
> > > 
> > > I do think we need a real mdelay_non_interruptible feature but
> > > just forbidden to recall usb control msg.
> > > But the rest of barebox can run durring those 5ms
> > 
> > Well, I think it can be done by returning -EAGAIN on re-entrance
> > detection in ehci_* functions [1], and skipping the poll in the
> > keyboard driver.
> 
> Could you tell us what you have done to get re-entrance problems? I
> have just replaced the mdelay_non_interruptible with regular mdelay
> in the ehci driver and didn't notice any problems. Could you verify
> the _non_interruptible is still needed?

If I revert the "usb: ehci-hcd: use mdelay_non_interruptible()" patch,
while leaving the "usb: ehci-hcd: detect re-entrance" applied, I get
the following messages after running the "usb" command:

barebox:/ usb                                                         
USB: scanning bus for devices...                                                
Bus 001 Device 001: ID 0000:0000 EHCI Host Controller                           
Bus 001 Device 002: ID 0424:2514                                                
Bus 001 Device 003: ID 413c:2112 Dell USB Wired Multimedia Keybo                
usb-keyboard usb1-0-0: USB keyboard found                                       
Bus 001 Device 004: ID 8564:1000 Mass Storage Device                            
Using index 0 for the new disk                                                  
usb-keyboard usb1-0-0: submit_int_msg: re-entrance 1 (usb-hub:usb1)             
usb-keyboard usb1-0-0: submit_int_msg: re-entrance 1 (usb-hub:usb1)             
usb-keyboard usb1-0-0: submit_int_msg: re-entrance 1 (usb-keyboard:usb1-0-0)    
usb-keyboard usb1-0-0: submit_int_msg: re-entrance 1 (usb-keyboard:usb1-0-0)    
usb-keyboard usb1-0-0: submit_int_msg: re-entrance 1 (usb-hub:usb1)             
usb-keyboard usb1-0-0: submit_int_msg: re-entrance 1 (usb-keyboard:usb1-0-0)    
usb-keyboard usb1-0-0: submit_int_msg: re-entrance 1 (usb-keyboard:usb1-0-0)    
Bus 001 Device 005: ID 0424:2514                                                
5 USB Device(s) found                                                       

According to the debug messages: submit_int_msg() is called by the usb-keyboard driver (from the poller function),
while "usb-hub" driver is executing submit_control_msg() (which calls mdelay() and poller_call() subsequently).
This occurs several times, until usb bus scan is completed.
Probably the problem can be reproduced by adding more usb devices.

> 
> Sascha
> 


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

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

* Re: [PATCH 4/5] usb: ehci-hcd: use mdelay_non_inerruptible()
  2015-10-12 11:43             ` Peter Mamonov
@ 2015-10-12 13:44               ` Sascha Hauer
  2015-10-13 10:37                 ` Peter Mamonov
  0 siblings, 1 reply; 23+ messages in thread
From: Sascha Hauer @ 2015-10-12 13:44 UTC (permalink / raw)
  To: Peter Mamonov; +Cc: barebox

On Mon, Oct 12, 2015 at 02:43:25PM +0300, Peter Mamonov wrote:
> On Mon, 12 Oct 2015 09:00:21 +0200
> Sascha Hauer <s.hauer@pengutronix.de> wrote:
> 
> > On Wed, Oct 07, 2015 at 07:52:21PM +0300, Peter Mamonov wrote:
> > > On Wed, 7 Oct 2015 17:40:24 +0200
> > > > > Non-interruptible delays are needed here to prevent ehci_*
> > > > > functions re-entrance. The re-entrance occurs during a usb bus
> > > > > scan, after detection of a usb keyboard. As soon as a USB
> > > > > keyboard is detected, it's driver starts the poller, which
> > > > > interferes with the process of usb bus scan. However that last
> > > > > one delay may be interruptible.
> > > > 
> > > > my problem is as soon as you start a usb control msg you block
> > > > everything
> > > > 
> > > > nothing else can run in barebox
> > > > 
> > > > can slow down barebox boot
> > > > 
> > > > I do think we need a real mdelay_non_interruptible feature but
> > > > just forbidden to recall usb control msg.
> > > > But the rest of barebox can run durring those 5ms
> > > 
> > > Well, I think it can be done by returning -EAGAIN on re-entrance
> > > detection in ehci_* functions [1], and skipping the poll in the
> > > keyboard driver.
> > 
> > Could you tell us what you have done to get re-entrance problems? I
> > have just replaced the mdelay_non_interruptible with regular mdelay
> > in the ehci driver and didn't notice any problems. Could you verify
> > the _non_interruptible is still needed?
> 
> If I revert the "usb: ehci-hcd: use mdelay_non_interruptible()" patch,
> while leaving the "usb: ehci-hcd: detect re-entrance" applied, I get
> the following messages after running the "usb" command:
> 
> barebox:/ usb                                                         
> USB: scanning bus for devices...                                                
> Bus 001 Device 001: ID 0000:0000 EHCI Host Controller                           
> Bus 001 Device 002: ID 0424:2514                                                
> Bus 001 Device 003: ID 413c:2112 Dell USB Wired Multimedia Keybo                
> usb-keyboard usb1-0-0: USB keyboard found                                       
> Bus 001 Device 004: ID 8564:1000 Mass Storage Device                            
> Using index 0 for the new disk                                                  
> usb-keyboard usb1-0-0: submit_int_msg: re-entrance 1 (usb-hub:usb1)             
> usb-keyboard usb1-0-0: submit_int_msg: re-entrance 1 (usb-hub:usb1)             
> usb-keyboard usb1-0-0: submit_int_msg: re-entrance 1 (usb-keyboard:usb1-0-0)    
> usb-keyboard usb1-0-0: submit_int_msg: re-entrance 1 (usb-keyboard:usb1-0-0)    
> usb-keyboard usb1-0-0: submit_int_msg: re-entrance 1 (usb-hub:usb1)             
> usb-keyboard usb1-0-0: submit_int_msg: re-entrance 1 (usb-keyboard:usb1-0-0)    
> usb-keyboard usb1-0-0: submit_int_msg: re-entrance 1 (usb-keyboard:usb1-0-0)    
> Bus 001 Device 005: ID 0424:2514                                                
> 5 USB Device(s) found                                                       
> 
> According to the debug messages: submit_int_msg() is called by the usb-keyboard driver (from the poller function),
> while "usb-hub" driver is executing submit_control_msg() (which calls mdelay() and poller_call() subsequently).
> This occurs several times, until usb bus scan is completed.
> Probably the problem can be reproduced by adding more usb devices.

I wonder why this does not happen here. I finally could reproduce this
by adding some additional delays to the ehci driver.

We should probably move the reentrance detection to the generic usb
layer to usb_submit_int_msg, usb_control_msg and usb_bulk_msg. This
would avoid running into the same problems in the other usb host
drivers. If I understand the issue correctly we could just use regular
*delay in the host drivers when we detect reentrancy correctly, right?
I mean we don't have to print an error message when we detect
reentrance, but instead just consider that a case that can happen.

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] 23+ messages in thread

* Re: [PATCH 4/5] usb: ehci-hcd: use mdelay_non_inerruptible()
  2015-10-07 16:52         ` Peter Mamonov
  2015-10-12  7:00           ` Sascha Hauer
@ 2015-10-13  2:04           ` Jean-Christophe PLAGNIOL-VILLARD
  2015-10-13  9:11             ` Antony Pavlov
  1 sibling, 1 reply; 23+ messages in thread
From: Jean-Christophe PLAGNIOL-VILLARD @ 2015-10-13  2:04 UTC (permalink / raw)
  To: Peter Mamonov; +Cc: barebox

On 19:52 Wed 07 Oct     , Peter Mamonov wrote:
> On Wed, 7 Oct 2015 17:40:24 +0200
> Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com> wrote:
> 
> > On 17:40 Wed 07 Oct     , Peter Mamonov wrote:
> > > On Wed, 7 Oct 2015 15:47:03 +0200
> > > Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com> wrote:
> > > 
> > > > On 18:58 Tue 22 Sep     , Peter Mamonov wrote:
> > > > > Signed-off-by: Peter Mamonov <pmamonov@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 d6df7b8..03d6150 100644
> > > > > --- a/drivers/usb/host/ehci-hcd.c
> > > > > +++ b/drivers/usb/host/ehci-hcd.c
> > > > > @@ -684,7 +684,7 @@ ehci_submit_root(struct usb_device *dev,
> > > > > unsigned long pipe, void *buffer,
> > > > >  				 * root
> > > > >  				 */
> > > > >  				ehci_powerup_fixup(ehci);
> > > > > -				mdelay(50);
> > > > > +				mdelay_non_interruptible(50);
> > > > >  				ehci->portreset |= 1 << port;
> > > > >  				/* terminate the reset */
> > > > >  				ehci_writel(status_reg, reg &
> > > > > ~EHCI_PS_PR); @@ -747,7 +747,7 @@ ehci_submit_root(struct
> > > > > usb_device *dev, unsigned long pipe, void *buffer, goto unknown;
> > > > >  	}
> > > > >  
> > > > > -	mdelay(1);
> > > > > +	mdelay_non_interruptible(1);
> > > > >  	len = min3(srclen, (int)le16_to_cpu(req->length),
> > > > > length); if (srcptr != NULL && len > 0)
> > > > >  		memcpy(buffer, srcptr, len);
> > > > > @@ -889,7 +889,7 @@ static int ehci_init(struct usb_host *host)
> > > > >  	ehci_writel(&ehci->hcor->or_configflag, cmd);
> > > > >  	/* unblock posted write */
> > > > >  	cmd = ehci_readl(&ehci->hcor->or_usbcmd);
> > > > > -	mdelay(5);
> > > > > +	mdelay_non_interruptible(5);
> > > > why do you need that much non interruptible delau?
> > > 
> > > Non-interruptible delays are needed here to prevent ehci_* functions
> > > re-entrance. The re-entrance occurs during a usb bus scan, after
> > > detection of a usb keyboard. As soon as a USB keyboard is detected,
> > > it's driver starts the poller, which interferes with the process of
> > > usb bus scan. However that last one delay may be interruptible.
> > 
> > my problem is as soon as you start a usb control msg you block
> > everything
> > 
> > nothing else can run in barebox
> > 
> > can slow down barebox boot
> > 
> > I do think we need a real mdelay_non_interruptible feature but just
> > forbidden to recall usb control msg.
> > But the rest of barebox can run durring those 5ms
> 
> Well, I think it can be done by returning -EAGAIN on re-entrance
> detection in ehci_* functions [1], and skipping the poll in the keyboard
> driver.
> 
> By the way, could you clarify: do you really experience
> considerable barebox slowdown or you make an assumtion based on the
> code analysis?

I've wrote similar code for barebox nearly 1 year ago and did notice it

Best Regards,
J.
> 
> [1]
> http://lists.infradead.org/pipermail/barebox/2015-September/024715.html
> 
> Regards,
> Peter
> 
> > 
> > Best Regards,
> > J.
> 

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

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

* Re: [PATCH 4/5] usb: ehci-hcd: use mdelay_non_inerruptible()
  2015-10-13  2:04           ` Jean-Christophe PLAGNIOL-VILLARD
@ 2015-10-13  9:11             ` Antony Pavlov
  0 siblings, 0 replies; 23+ messages in thread
From: Antony Pavlov @ 2015-10-13  9:11 UTC (permalink / raw)
  To: Jean-Christophe PLAGNIOL-VILLARD; +Cc: barebox, Peter Mamonov

On Tue, 13 Oct 2015 04:04:28 +0200
Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com> wrote:

> On 19:52 Wed 07 Oct     , Peter Mamonov wrote:
> > On Wed, 7 Oct 2015 17:40:24 +0200
> > Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com> wrote:
> > 
> > > On 17:40 Wed 07 Oct     , Peter Mamonov wrote:
> > > > On Wed, 7 Oct 2015 15:47:03 +0200
> > > > Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com> wrote:
> > > > 
> > > > > On 18:58 Tue 22 Sep     , Peter Mamonov wrote:
> > > > > > Signed-off-by: Peter Mamonov <pmamonov@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 d6df7b8..03d6150 100644
> > > > > > --- a/drivers/usb/host/ehci-hcd.c
> > > > > > +++ b/drivers/usb/host/ehci-hcd.c
> > > > > > @@ -684,7 +684,7 @@ ehci_submit_root(struct usb_device *dev,
> > > > > > unsigned long pipe, void *buffer,
> > > > > >  				 * root
> > > > > >  				 */
> > > > > >  				ehci_powerup_fixup(ehci);
> > > > > > -				mdelay(50);
> > > > > > +				mdelay_non_interruptible(50);
> > > > > >  				ehci->portreset |= 1 << port;
> > > > > >  				/* terminate the reset */
> > > > > >  				ehci_writel(status_reg, reg &
> > > > > > ~EHCI_PS_PR); @@ -747,7 +747,7 @@ ehci_submit_root(struct
> > > > > > usb_device *dev, unsigned long pipe, void *buffer, goto unknown;
> > > > > >  	}
> > > > > >  
> > > > > > -	mdelay(1);
> > > > > > +	mdelay_non_interruptible(1);
> > > > > >  	len = min3(srclen, (int)le16_to_cpu(req->length),
> > > > > > length); if (srcptr != NULL && len > 0)
> > > > > >  		memcpy(buffer, srcptr, len);
> > > > > > @@ -889,7 +889,7 @@ static int ehci_init(struct usb_host *host)
> > > > > >  	ehci_writel(&ehci->hcor->or_configflag, cmd);
> > > > > >  	/* unblock posted write */
> > > > > >  	cmd = ehci_readl(&ehci->hcor->or_usbcmd);
> > > > > > -	mdelay(5);
> > > > > > +	mdelay_non_interruptible(5);
> > > > > why do you need that much non interruptible delau?
> > > > 
> > > > Non-interruptible delays are needed here to prevent ehci_* functions
> > > > re-entrance. The re-entrance occurs during a usb bus scan, after
> > > > detection of a usb keyboard. As soon as a USB keyboard is detected,
> > > > it's driver starts the poller, which interferes with the process of
> > > > usb bus scan. However that last one delay may be interruptible.
> > > 
> > > my problem is as soon as you start a usb control msg you block
> > > everything
> > > 
> > > nothing else can run in barebox
> > > 
> > > can slow down barebox boot
> > > 
> > > I do think we need a real mdelay_non_interruptible feature but just
> > > forbidden to recall usb control msg.
> > > But the rest of barebox can run durring those 5ms
> > 
> > Well, I think it can be done by returning -EAGAIN on re-entrance
> > detection in ehci_* functions [1], and skipping the poll in the keyboard
> > driver.
> > 
> > By the way, could you clarify: do you really experience
> > considerable barebox slowdown or you make an assumtion based on the
> > code analysis?
> 
> I've wrote similar code for barebox nearly 1 year ago and did notice it

So you have not tested Peter's code.
Could you please test latest next branch and sand a word on slowdown?


> Best Regards,
> J.
> > 
> > [1]
> > http://lists.infradead.org/pipermail/barebox/2015-September/024715.html
> > 
> > Regards,
> > Peter
> > 
> > > 
> > > Best Regards,
> > > J.
> > 
> 
> _______________________________________________
> barebox mailing list
> barebox@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/barebox


-- 
-- 
Best regards,
  Antony Pavlov

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

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

* Re: [PATCH 4/5] usb: ehci-hcd: use mdelay_non_inerruptible()
  2015-10-12 13:44               ` Sascha Hauer
@ 2015-10-13 10:37                 ` Peter Mamonov
  2015-10-13 10:38                   ` Sascha Hauer
  0 siblings, 1 reply; 23+ messages in thread
From: Peter Mamonov @ 2015-10-13 10:37 UTC (permalink / raw)
  To: Sascha Hauer; +Cc: barebox

On Mon, 12 Oct 2015 15:44:01 +0200
Sascha Hauer <s.hauer@pengutronix.de> wrote:

> On Mon, Oct 12, 2015 at 02:43:25PM +0300, Peter Mamonov wrote:
> > On Mon, 12 Oct 2015 09:00:21 +0200
> > Sascha Hauer <s.hauer@pengutronix.de> wrote:
> > 
> > > On Wed, Oct 07, 2015 at 07:52:21PM +0300, Peter Mamonov wrote:
> > > > On Wed, 7 Oct 2015 17:40:24 +0200
> > > > > > Non-interruptible delays are needed here to prevent ehci_*
> > > > > > functions re-entrance. The re-entrance occurs during a usb
> > > > > > bus scan, after detection of a usb keyboard. As soon as a
> > > > > > USB keyboard is detected, it's driver starts the poller,
> > > > > > which interferes with the process of usb bus scan. However
> > > > > > that last one delay may be interruptible.
> > > > > 
> > > > > my problem is as soon as you start a usb control msg you block
> > > > > everything
> > > > > 
> > > > > nothing else can run in barebox
> > > > > 
> > > > > can slow down barebox boot
> > > > > 
> > > > > I do think we need a real mdelay_non_interruptible feature but
> > > > > just forbidden to recall usb control msg.
> > > > > But the rest of barebox can run durring those 5ms
> > > > 
> > > > Well, I think it can be done by returning -EAGAIN on re-entrance
> > > > detection in ehci_* functions [1], and skipping the poll in the
> > > > keyboard driver.
> > > 
> > > Could you tell us what you have done to get re-entrance problems?
> > > I have just replaced the mdelay_non_interruptible with regular
> > > mdelay in the ehci driver and didn't notice any problems. Could
> > > you verify the _non_interruptible is still needed?
> > 
> > If I revert the "usb: ehci-hcd: use mdelay_non_interruptible()"
> > patch, while leaving the "usb: ehci-hcd: detect re-entrance"
> > applied, I get the following messages after running the "usb"
> > command:
> > 
> > barebox:/
> > usb USB: scanning bus for
> > devices... Bus 001 Device 001: ID 0000:0000 EHCI Host
> > Controller Bus 001 Device 002: ID
> > 0424:2514 Bus 001 Device 003: ID 413c:2112 Dell USB Wired
> > Multimedia Keybo usb-keyboard usb1-0-0: USB keyboard
> > found Bus 001 Device 004: ID 8564:1000 Mass Storage
> > Device Using index 0 for the new
> > disk usb-keyboard usb1-0-0: submit_int_msg: re-entrance 1
> > (usb-hub:usb1) usb-keyboard usb1-0-0: submit_int_msg: re-entrance 1
> > (usb-hub:usb1) usb-keyboard usb1-0-0: submit_int_msg: re-entrance 1
> > (usb-keyboard:usb1-0-0) usb-keyboard usb1-0-0: submit_int_msg:
> > re-entrance 1 (usb-keyboard:usb1-0-0) usb-keyboard usb1-0-0:
> > submit_int_msg: re-entrance 1 (usb-hub:usb1) usb-keyboard usb1-0-0:
> > submit_int_msg: re-entrance 1 (usb-keyboard:usb1-0-0) usb-keyboard
> > usb1-0-0: submit_int_msg: re-entrance 1 (usb-keyboard:usb1-0-0) Bus
> > 001 Device 005: ID 0424:2514 5 USB Device(s)
> > found                                                       
> > 
> > According to the debug messages: submit_int_msg() is called by the
> > usb-keyboard driver (from the poller function), while "usb-hub"
> > driver is executing submit_control_msg() (which calls mdelay() and
> > poller_call() subsequently). This occurs several times, until usb
> > bus scan is completed. Probably the problem can be reproduced by
> > adding more usb devices.
> 
> I wonder why this does not happen here. I finally could reproduce this
> by adding some additional delays to the ehci driver.
> 
> We should probably move the reentrance detection to the generic usb
> layer to usb_submit_int_msg, usb_control_msg and usb_bulk_msg. This
> would avoid running into the same problems in the other usb host
> drivers. If I understand the issue correctly we could just use regular
> *delay in the host drivers when we detect reentrancy correctly, right?
> I mean we don't have to print an error message when we detect
> reentrance, but instead just consider that a case that can happen.

We can return -EAGAIN on reentrance detection in usb_* functions, but
the usb device driver should distinguish this case and do sane
things, i.e. it should not fail, but skip the action. This only
concerns the drivers that use pollers, i.e. for example usb storage
driver is not affected, since it doesn't use pollers.

> 
> Sascha
> 


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

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

* Re: [PATCH 4/5] usb: ehci-hcd: use mdelay_non_inerruptible()
  2015-10-13 10:37                 ` Peter Mamonov
@ 2015-10-13 10:38                   ` Sascha Hauer
  0 siblings, 0 replies; 23+ messages in thread
From: Sascha Hauer @ 2015-10-13 10:38 UTC (permalink / raw)
  To: Peter Mamonov; +Cc: barebox

On Tue, Oct 13, 2015 at 01:37:33PM +0300, Peter Mamonov wrote:
> On Mon, 12 Oct 2015 15:44:01 +0200
> Sascha Hauer <s.hauer@pengutronix.de> wrote:
> 
> > On Mon, Oct 12, 2015 at 02:43:25PM +0300, Peter Mamonov wrote:
> > > On Mon, 12 Oct 2015 09:00:21 +0200
> > > Sascha Hauer <s.hauer@pengutronix.de> wrote:
> > > 
> > > > On Wed, Oct 07, 2015 at 07:52:21PM +0300, Peter Mamonov wrote:
> > > > > On Wed, 7 Oct 2015 17:40:24 +0200
> > > > > > > Non-interruptible delays are needed here to prevent ehci_*
> > > > > > > functions re-entrance. The re-entrance occurs during a usb
> > > > > > > bus scan, after detection of a usb keyboard. As soon as a
> > > > > > > USB keyboard is detected, it's driver starts the poller,
> > > > > > > which interferes with the process of usb bus scan. However
> > > > > > > that last one delay may be interruptible.
> > > > > > 
> > > > > > my problem is as soon as you start a usb control msg you block
> > > > > > everything
> > > > > > 
> > > > > > nothing else can run in barebox
> > > > > > 
> > > > > > can slow down barebox boot
> > > > > > 
> > > > > > I do think we need a real mdelay_non_interruptible feature but
> > > > > > just forbidden to recall usb control msg.
> > > > > > But the rest of barebox can run durring those 5ms
> > > > > 
> > > > > Well, I think it can be done by returning -EAGAIN on re-entrance
> > > > > detection in ehci_* functions [1], and skipping the poll in the
> > > > > keyboard driver.
> > > > 
> > > > Could you tell us what you have done to get re-entrance problems?
> > > > I have just replaced the mdelay_non_interruptible with regular
> > > > mdelay in the ehci driver and didn't notice any problems. Could
> > > > you verify the _non_interruptible is still needed?
> > > 
> > > If I revert the "usb: ehci-hcd: use mdelay_non_interruptible()"
> > > patch, while leaving the "usb: ehci-hcd: detect re-entrance"
> > > applied, I get the following messages after running the "usb"
> > > command:
> > > 
> > > barebox:/
> > > usb USB: scanning bus for
> > > devices... Bus 001 Device 001: ID 0000:0000 EHCI Host
> > > Controller Bus 001 Device 002: ID
> > > 0424:2514 Bus 001 Device 003: ID 413c:2112 Dell USB Wired
> > > Multimedia Keybo usb-keyboard usb1-0-0: USB keyboard
> > > found Bus 001 Device 004: ID 8564:1000 Mass Storage
> > > Device Using index 0 for the new
> > > disk usb-keyboard usb1-0-0: submit_int_msg: re-entrance 1
> > > (usb-hub:usb1) usb-keyboard usb1-0-0: submit_int_msg: re-entrance 1
> > > (usb-hub:usb1) usb-keyboard usb1-0-0: submit_int_msg: re-entrance 1
> > > (usb-keyboard:usb1-0-0) usb-keyboard usb1-0-0: submit_int_msg:
> > > re-entrance 1 (usb-keyboard:usb1-0-0) usb-keyboard usb1-0-0:
> > > submit_int_msg: re-entrance 1 (usb-hub:usb1) usb-keyboard usb1-0-0:
> > > submit_int_msg: re-entrance 1 (usb-keyboard:usb1-0-0) usb-keyboard
> > > usb1-0-0: submit_int_msg: re-entrance 1 (usb-keyboard:usb1-0-0) Bus
> > > 001 Device 005: ID 0424:2514 5 USB Device(s)
> > > found                                                       
> > > 
> > > According to the debug messages: submit_int_msg() is called by the
> > > usb-keyboard driver (from the poller function), while "usb-hub"
> > > driver is executing submit_control_msg() (which calls mdelay() and
> > > poller_call() subsequently). This occurs several times, until usb
> > > bus scan is completed. Probably the problem can be reproduced by
> > > adding more usb devices.
> > 
> > I wonder why this does not happen here. I finally could reproduce this
> > by adding some additional delays to the ehci driver.
> > 
> > We should probably move the reentrance detection to the generic usb
> > layer to usb_submit_int_msg, usb_control_msg and usb_bulk_msg. This
> > would avoid running into the same problems in the other usb host
> > drivers. If I understand the issue correctly we could just use regular
> > *delay in the host drivers when we detect reentrancy correctly, right?
> > I mean we don't have to print an error message when we detect
> > reentrance, but instead just consider that a case that can happen.
> 
> We can return -EAGAIN on reentrance detection in usb_* functions, but
> the usb device driver should distinguish this case and do sane
> things, i.e. it should not fail, but skip the action.

Yes, that sounds like a sane approach to me.

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] 23+ messages in thread

* [PATCH 4/5] usb: ehci-hcd: use mdelay_non_inerruptible()
  2015-09-21 11:30 [RFC v5 0/2] WIP: add usb keyboard driver Peter Mamonov
@ 2015-09-21 11:30 ` Peter Mamonov
  0 siblings, 0 replies; 23+ messages in thread
From: Peter Mamonov @ 2015-09-21 11:30 UTC (permalink / raw)
  To: barebox; +Cc: Peter Mamonov

Signed-off-by: Peter Mamonov <pmamonov@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 133f42e..4a8bb58 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -684,7 +684,7 @@ ehci_submit_root(struct usb_device *dev, unsigned long pipe, void *buffer,
 				 * root
 				 */
 				ehci_powerup_fixup(ehci);
-				mdelay(50);
+				mdelay_non_interruptible(50);
 				ehci->portreset |= 1 << port;
 				/* terminate the reset */
 				ehci_writel(status_reg, reg & ~EHCI_PS_PR);
@@ -747,7 +747,7 @@ ehci_submit_root(struct usb_device *dev, unsigned long pipe, void *buffer,
 		goto unknown;
 	}
 
-	mdelay(1);
+	mdelay_non_interruptible(1);
 	len = min3(srclen, (int)le16_to_cpu(req->length), length);
 	if (srcptr != NULL && len > 0)
 		memcpy(buffer, srcptr, len);
@@ -889,7 +889,7 @@ static int ehci_init(struct usb_host *host)
 	ehci_writel(&ehci->hcor->or_configflag, cmd);
 	/* unblock posted write */
 	cmd = ehci_readl(&ehci->hcor->or_usbcmd);
-	mdelay(5);
+	mdelay_non_interruptible(5);
 
 	ehci->rootdev = 0;
 
-- 
2.1.4


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

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

end of thread, other threads:[~2015-10-13 10:38 UTC | newest]

Thread overview: 23+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-09-22 15:58 [PATCH v6 0/5] input: add usb keyboard driver Peter Mamonov
2015-09-22 15:58 ` [PATCH 1/5] common: clock: introduce mdelay_non_interruptible() Peter Mamonov
2015-09-22 21:15   ` Antony Pavlov
2015-09-22 21:20     ` Peter Mamonov
2015-09-22 15:58 ` [PATCH 2/5] usb: ehci-hcd: port periodic transactions implementation from the u-boot Peter Mamonov
2015-09-22 15:58 ` [PATCH 3/5] usb: ehci-hcd: detect re-entrance Peter Mamonov
2015-09-23 14:23   ` Sascha Hauer
2015-09-22 15:58 ` [PATCH 4/5] usb: ehci-hcd: use mdelay_non_inerruptible() Peter Mamonov
2015-10-07 13:47   ` Jean-Christophe PLAGNIOL-VILLARD
2015-10-07 14:40     ` Peter Mamonov
2015-10-07 15:40       ` Jean-Christophe PLAGNIOL-VILLARD
2015-10-07 16:52         ` Peter Mamonov
2015-10-12  7:00           ` Sascha Hauer
2015-10-12 11:43             ` Peter Mamonov
2015-10-12 13:44               ` Sascha Hauer
2015-10-13 10:37                 ` Peter Mamonov
2015-10-13 10:38                   ` Sascha Hauer
2015-10-13  2:04           ` Jean-Christophe PLAGNIOL-VILLARD
2015-10-13  9:11             ` Antony Pavlov
2015-09-22 15:58 ` [PATCH 5/5] input: port usb keyboard driver from the u-boot Peter Mamonov
2015-09-23 14:34 ` [PATCH 1/2] fixup! usb: ehci-hcd: port periodic transactions implementation " Sascha Hauer
2015-09-23 14:34   ` [PATCH 2/2] fixup! input: port usb keyboard driver " Sascha Hauer
  -- strict thread matches above, loose matches on Subject: below --
2015-09-21 11:30 [RFC v5 0/2] WIP: add usb keyboard driver Peter Mamonov
2015-09-21 11:30 ` [PATCH 4/5] usb: ehci-hcd: use mdelay_non_inerruptible() Peter Mamonov

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