[PATCH v3 3/5] usb: dwc3: gadget: Write GEVNTCOUNT in interrupt

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

 



Currently GEVNTCOUNT is written in the threaded interrupt handler while
processing each event. This commit moves the GEVNTCOUNT write to the
hard IRQ. We then copy the events to a separate buffer for the event
handler to read from.

This change is in preparation of working around an issue in core version
3.00a where the interrupt cannot be de-asserted in the normal way.
However, if we enable interrupt moderation, we can also de-assert it by
writing to GEVNTCOUNT.

Signed-off-by: John Youn <johnyoun@xxxxxxxxxxxx>
---
 drivers/usb/dwc3/core.c   |  4 ++++
 drivers/usb/dwc3/core.h   |  2 ++
 drivers/usb/dwc3/gadget.c | 22 +++++++++++++---------
 3 files changed, 19 insertions(+), 9 deletions(-)

diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index af42346..f0bb6df 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -251,6 +251,10 @@ static struct dwc3_event_buffer *dwc3_alloc_one_event_buffer(struct dwc3 *dwc,
 
 	evt->dwc	= dwc;
 	evt->length	= length;
+	evt->cache	= devm_kzalloc(dwc->dev, length, GFP_KERNEL);
+	if (!evt->cache)
+		return ERR_PTR(-ENOMEM);
+
 	evt->buf	= dma_alloc_coherent(dwc->dev, length,
 			&evt->dma, GFP_KERNEL);
 	if (!evt->buf)
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index 354de24..bf63756 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -472,6 +472,7 @@ struct dwc3_trb;
 /**
  * struct dwc3_event_buffer - Software event buffer representation
  * @buf: _THE_ buffer
+ * @cache: The buffer cache used in the threaded interrupt
  * @length: size of this buffer
  * @lpos: event offset
  * @count: cache of last read event count register
@@ -481,6 +482,7 @@ struct dwc3_trb;
  */
 struct dwc3_event_buffer {
 	void			*buf;
+	void			*cache;
 	unsigned		length;
 	unsigned int		lpos;
 	unsigned int		count;
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 22ccc34..f07dd84 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -2829,18 +2829,16 @@ static irqreturn_t dwc3_process_event_buf(struct dwc3_event_buffer *evt)
 {
 	struct dwc3 *dwc = evt->dwc;
 	irqreturn_t ret = IRQ_NONE;
-	int left;
+	int idx;
 	u32 reg;
 
-	left = evt->count;
-
 	if (!(evt->flags & DWC3_EVENT_PENDING))
 		return IRQ_NONE;
 
-	while (left > 0) {
+	for (idx = 0; idx < evt->count; idx += 4) {
 		union dwc3_event event;
 
-		event.raw = *(u32 *) (evt->buf + evt->lpos);
+		event.raw = *(u32 *)(evt->cache + idx);
 
 		dwc3_process_event_entry(dwc, &event);
 
@@ -2853,10 +2851,6 @@ static irqreturn_t dwc3_process_event_buf(struct dwc3_event_buffer *evt)
 		 * boundary so I worry about that once we try to handle
 		 * that.
 		 */
-		evt->lpos = (evt->lpos + 4) % DWC3_EVENT_BUFFERS_SIZE;
-		left -= 4;
-
-		dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(0), 4);
 	}
 
 	evt->count = 0;
@@ -2889,6 +2883,7 @@ static irqreturn_t dwc3_check_event_buf(struct dwc3_event_buffer *evt)
 {
 	struct dwc3 *dwc = evt->dwc;
 	u32 count;
+	u32 amount;
 	u32 reg;
 
 	if (pm_runtime_suspended(dwc->dev)) {
@@ -2906,6 +2901,15 @@ static irqreturn_t dwc3_check_event_buf(struct dwc3_event_buffer *evt)
 	evt->count = count;
 	evt->flags |= DWC3_EVENT_PENDING;
 
+	amount = min(count, DWC3_EVENT_BUFFERS_SIZE - evt->lpos);
+	memcpy(evt->cache, evt->buf + evt->lpos, amount);
+
+	if (amount < count)
+		memcpy(evt->cache + amount, evt->buf, count - amount);
+
+	evt->lpos = (evt->lpos + count) % DWC3_EVENT_BUFFERS_SIZE;
+	dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(0), count);
+
 	/* Mask interrupt */
 	reg = dwc3_readl(dwc->regs, DWC3_GEVNTSIZ(0));
 	reg |= DWC3_GEVNTSIZ_INTMASK;
-- 
2.10.0

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux