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

Commit bbab5447 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "usb: dwc3: Stop processing more events after erratic error"

parents c379e29a ec053b1f
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -1096,6 +1096,9 @@ void dwc3_gadget_restart(struct dwc3 *dwc);
void dwc3_post_host_reset_core_init(struct dwc3 *dwc);
int dwc3_event_buffers_setup(struct dwc3 *dwc);

void dwc3_gadget_enable_irq(struct dwc3 *dwc);
void dwc3_gadget_disable_irq(struct dwc3 *dwc);

extern void dwc3_set_notifier(
		void (*notify) (struct dwc3 *dwc3, unsigned event));
extern int dwc3_notify_event(struct dwc3 *dwc3, unsigned event);
+7 −21
Original line number Diff line number Diff line
@@ -1123,7 +1123,7 @@ static void dwc3_msm_notify_event(struct dwc3 *dwc, unsigned event)
	case DWC3_CONTROLLER_ERROR_EVENT:
		dev_info(mdwc->dev, "DWC3_CONTROLLER_ERROR_EVENT received\n");
		dwc3_msm_dump_phy_info(mdwc);
		dwc3_msm_write_reg(mdwc->base, DWC3_DEVTEN, 0);
		dwc3_gadget_disable_irq(dwc);
		/*
		 * schedule work for doing block reset for recovery from erratic
		 * error event.
@@ -1211,30 +1211,16 @@ static void dwc3_block_reset_usb_work(struct work_struct *w)
{
	struct dwc3_msm *mdwc = container_of(w, struct dwc3_msm,
						usb_block_reset_work);
	u32 reg;
	struct dwc3 *dwc = platform_get_drvdata(mdwc->dwc3);
	unsigned long flags;

	dev_dbg(mdwc->dev, "%s\n", __func__);

	dwc3_msm_block_reset(&mdwc->ext_xceiv, true);

	reg = (DWC3_DEVTEN_EVNTOVERFLOWEN |
			DWC3_DEVTEN_CMDCMPLTEN |
			DWC3_DEVTEN_ERRTICERREN |
			DWC3_DEVTEN_WKUPEVTEN |
			DWC3_DEVTEN_CONNECTDONEEN |
			DWC3_DEVTEN_USBRSTEN |
			DWC3_DEVTEN_DISCONNEVTEN);
	/*
	 * Enable SUSPENDEVENT(BIT:6) for version 230A and above
	 * else enable USB Link change event (BIT:3) for older version
	 */
	if (dwc3_msm_read_reg(mdwc->base, DWC3_GSNPSID) < DWC3_REVISION_230A)
		reg |= DWC3_DEVTEN_ULSTCNGEN;
	else
		reg |= DWC3_DEVTEN_SUSPEND;

	dwc3_msm_write_reg(mdwc->base, DWC3_DEVTEN, reg);

	dwc3_gadget_enable_irq(dwc);
	spin_lock_irqsave(&dwc->lock, flags);
	dwc->err_evt_seen = 0;
	spin_unlock_irqrestore(&dwc->lock, flags);
}

static void dwc3_chg_enable_secondary_det(struct dwc3_msm *mdwc)
+26 −4
Original line number Diff line number Diff line
@@ -1986,7 +1986,7 @@ static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on)
	return ret;
}

static void dwc3_gadget_enable_irq(struct dwc3 *dwc)
void dwc3_gadget_enable_irq(struct dwc3 *dwc)
{
	u32			reg;

@@ -2011,7 +2011,7 @@ static void dwc3_gadget_enable_irq(struct dwc3 *dwc)
	dwc3_writel(dwc->regs, DWC3_DEVTEN, reg);
}

static void dwc3_gadget_disable_irq(struct dwc3 *dwc)
void dwc3_gadget_disable_irq(struct dwc3 *dwc)
{
	/* mask all interrupts */
	dwc3_writel(dwc->regs, DWC3_DEVTEN, 0x00);
@@ -3278,8 +3278,6 @@ static void dwc3_dump_reg_info(struct dwc3 *dwc)
	dbg_print_reg("OCTL", dwc3_readl(dwc->regs, DWC3_OCTL));
	dbg_print_reg("OEVT", dwc3_readl(dwc->regs, DWC3_OEVT));
	dbg_print_reg("OSTS", dwc3_readl(dwc->regs, DWC3_OSTS));

	dwc3_notify_event(dwc, DWC3_CONTROLLER_ERROR_EVENT);
}

static void dwc3_gadget_interrupt(struct dwc3 *dwc,
@@ -3429,6 +3427,21 @@ static irqreturn_t dwc3_thread_interrupt(int irq, void *_dwc)

			dwc3_process_event_entry(dwc, &event);

			if (dwc->err_evt_seen) {
				/*
				 * if erratic error, skip remaining events
				 * while controller undergoes reset
				 */
				evt->lpos = (evt->lpos + left) %
						DWC3_EVENT_BUFFERS_SIZE;
				dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(i),
						left);
				if (dwc3_notify_event(dwc,
						DWC3_CONTROLLER_ERROR_EVENT))
					dwc->err_evt_seen = 0;
				break;
			}

			/*
			 * FIXME we wrap around correctly to the next entry as
			 * almost all entries are 4 bytes in size. There is one
@@ -3447,6 +3460,9 @@ static irqreturn_t dwc3_thread_interrupt(int irq, void *_dwc)
		evt->count = 0;
		evt->flags &= ~DWC3_EVENT_PENDING;
		ret = IRQ_HANDLED;

		if (dwc->err_evt_seen)
			break;
	}

	spin_unlock_irqrestore(&dwc->lock, flags);
@@ -3496,6 +3512,12 @@ static irqreturn_t dwc3_interrupt(int irq, void *_dwc)

	spin_lock(&dwc->lock);

	if (dwc->err_evt_seen) {
		/* controller reset is still pending */
		spin_unlock(&dwc->lock);
		return IRQ_HANDLED;
	}

	for (i = 0; i < dwc->num_event_buffers; i++) {
		irqreturn_t status;