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

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

usb: dwc3: Prevent continuous retries on error event



Upon USB core generating an erratic error event, the
dwc3-msm driver resets and restarts the core. Even
after this if core could not recover, the driver
keep on trying the same in a infinite loop. This could
lead to the hogging of system resources leading to
system failure. Prevent this by trying a maximum of three
times to recover upon erratic error event.

An example of continuous generation of error events is
a DCP charger detected as SDP by the PMIC and core entering
device mode. In this case, the core could not recover
even after several tries.

Change-Id: Ic2f2f10e6bcc7480be5116746072b0fb1651ce10
Signed-off-by: default avatarSriharsha Allenki <sallenki@codeaurora.org>
parent 6e7c2de4
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -45,6 +45,7 @@
#define DWC3_EP0_SETUP_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
@@ -1204,6 +1205,7 @@ struct dwc3 {
	 * connected devices on PM resume.
	 */
	bool			host_poweroff_in_pm_suspend;
	int			retries_on_error;
};

#define work_to_dwc(w)		(container_of((w), struct dwc3, drd_work))
+7 −2
Original line number Diff line number Diff line
@@ -1885,7 +1885,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 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:
+6 −1
Original line number Diff line number Diff line
@@ -2091,6 +2091,7 @@ 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);

		dwc->err_evt_seen = false;
		dwc->pullups_connected = false;

		__dwc3_gadget_ep_disable(dwc->eps[0]);
@@ -3265,6 +3266,9 @@ static void dwc3_gadget_conndone_interrupt(struct dwc3 *dwc)
		dwc3_writel(dwc->regs, DWC3_DEVTEN, reg);
	}

	/* Reset the retry on erratic error event count */
	dwc->retries_on_error = 0;

	/*
	 * RAMClkSel is reset to 0 after USB reset, so it must be reprogrammed
	 * each time on Connect Done.
@@ -3628,7 +3632,7 @@ static void dwc3_gadget_interrupt(struct dwc3 *dwc,
		dwc->dbg_gadget_events.sof++;
		break;
	case DWC3_DEVICE_EVENT_ERRATIC_ERROR:
		dbg_event(0xFF, "ERROR", 0);
		dbg_event(0xFF, "ERROR", dwc->retries_on_error);
		dwc->dbg_gadget_events.erratic_error++;
		dwc->err_evt_seen = true;
		break;
@@ -3686,6 +3690,7 @@ static irqreturn_t dwc3_process_event_buf(struct dwc3_event_buffer *evt)
			if (dwc3_notify_event(dwc,
						DWC3_CONTROLLER_ERROR_EVENT, 0))
				dwc->err_evt_seen = 0;
			dwc->retries_on_error++;
			break;
		}