Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ab794fee authored by Sriharsha Allenki's avatar Sriharsha Allenki
Browse files

usb: dwc3: Disable device events after maximum error retries



Currently if the core could not recover even after maximum
number of error retries there can storm of error interrupts
generated since the interrupts are not handled because
of dwc->err_evt_seen being set on first error event seen.
Hence after maximum error retries disable the device
events and keep the core in softreset state.

Also, reset the err_evt_seen on run/stop clear to ensure
that the interrupts on the next connect/session are
processed properly.

Change-Id: I760e163733bdcc6230d926fa548aa93a5da918a5
Signed-off-by: default avatarSriharsha Allenki <sallenki@codeaurora.org>
parent ec12b494
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -44,6 +44,7 @@
#define DWC3_EP0_BOUNCE_SIZE	512
#define DWC3_ENDPOINTS_NUM	32
#define DWC3_XHCI_RESOURCES_NUM	2
#define MAX_ERROR_RECOVERY_TRIES	3

#define DWC3_SCRATCHBUF_SIZE	4096	/* each buffer is assumed to be 4KiB */
#define DWC3_EVENT_BUFFERS_SIZE	4096
+7 −2
Original line number Diff line number Diff line
@@ -1950,7 +1950,12 @@ static void dwc3_msm_notify_event(struct dwc3 *dwc, unsigned int event,
		reg |= DWC3_GCTL_CORESOFTRESET;
		dwc3_msm_write_reg(mdwc->base, DWC3_GCTL, reg);

		/* restart USB which performs full reset and reconnect */
		/*
		 * If the core could not recover after MAX_ERROR_RECOVERY_TRIES,
		 * skip the restart USB work and keep the core in softreset
		 * state.
		 */
		if (dwc->retries_on_error < MAX_ERROR_RECOVERY_TRIES)
			schedule_work(&mdwc->restart_usb_work);
		break;
	case DWC3_CONTROLLER_RESET_EVENT:
+8 −7
Original line number Diff line number Diff line
@@ -37,8 +37,6 @@
#include "gadget.h"
#include "io.h"

#define MAX_ERROR_RECOVERY_TRIES	3

static void dwc3_gadget_wakeup_interrupt(struct dwc3 *dwc, bool remote_wakeup);
static int dwc3_gadget_wakeup_int(struct dwc3 *dwc);
static void dwc3_stop_active_transfers(struct dwc3 *dwc);
@@ -1954,6 +1952,11 @@ static int dwc3_gadget_run_stop(struct dwc3 *dwc, int is_on, int suspend)
		reg1 |= DWC3_GEVNTSIZ_INTMASK;
		dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(0), reg1);

		/*
		 * Reset the err_evt_seen so that the interrupts on
		 * next connect/session is processed correctly.
		 */
		dwc->err_evt_seen = false;
		dwc->pullups_connected = false;

		__dwc3_gadget_ep_disable(dwc->eps[0]);
@@ -3638,12 +3641,10 @@ static irqreturn_t dwc3_process_event_buf(struct dwc3 *dwc)
			evt->lpos = (evt->lpos + left) %
					DWC3_EVENT_BUFFERS_SIZE;
			dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(0), left);
			if (dwc->retries_on_error < MAX_ERROR_RECOVERY_TRIES) {
			if (dwc3_notify_event(dwc,
						DWC3_CONTROLLER_ERROR_EVENT, 0))
				dwc->err_evt_seen = 0;
			dwc->retries_on_error++;
			}
			break;
		}