diff options
| -rw-r--r-- | drivers/usb/dwc3/ep0.c | 35 | 
1 files changed, 35 insertions, 0 deletions
diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index 24b447e40bc..36482f45b3b 100644 --- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c @@ -733,6 +733,41 @@ static void dwc3_ep0_do_control_status(struct dwc3 *dwc,  static void dwc3_ep0_xfernotready(struct dwc3 *dwc,  		const struct dwc3_event_depevt *event)  { +	/* +	 * This part is very tricky: If we has just handled +	 * XferNotReady(Setup) and we're now expecting a +	 * XferComplete but, instead, we receive another +	 * XferNotReady(Setup), we should STALL and restart +	 * the state machine. +	 * +	 * In all other cases, we just continue waiting +	 * for the XferComplete event. +	 * +	 * We are a little bit unsafe here because we're +	 * not trying to ensure that last event was, indeed, +	 * XferNotReady(Setup). +	 * +	 * Still, we don't expect any condition where that +	 * should happen and, even if it does, it would be +	 * another error condition. +	 */ +	if (dwc->ep0_next_event == DWC3_EP0_COMPLETE) { +		switch (event->status) { +		case DEPEVT_STATUS_CONTROL_SETUP: +			dev_vdbg(dwc->dev, "Unexpected XferNotReady(Setup)\n"); +			dwc3_ep0_stall_and_restart(dwc); +			break; +		case DEPEVT_STATUS_CONTROL_DATA: +			/* FALLTHROUGH */ +		case DEPEVT_STATUS_CONTROL_STATUS: +			/* FALLTHROUGH */ +		default: +			dev_vdbg(dwc->dev, "waiting for XferComplete\n"); +		} + +		return; +	} +  	switch (event->status) {  	case DEPEVT_STATUS_CONTROL_SETUP:  		dev_vdbg(dwc->dev, "Control Setup\n");  |