Re: [PATCH] usb: dwc3: ep0: fix delayed status is queued too early

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

 



Hi,

(using private email as I'm having issue with company's VPN, will get
that sorted out by tomorrow hopefully)

> On Thu, 8 May 2014, Zhuang Jin Can wrote:
> > > dwc3 _cannot_ return NYET to a SETUP packet.  The USB protocol does
> > > not 
> > > allow it.  A device must always respond to SETUP with ACK.
> > It true that device can not return NYET to a SETUP packet.
> > A device must always respond to SETUP with ACK _if_ the SETUP packet
> > is
> > correctly received. Because there's no buffer prepared in ep0 for dwc3
> > to receive the SETUP packet, I guess there will be no handshake
> > returned to host. I can confirm this by doing an experiment tomorrow:)
> 
> The dwc3 driver should always prepare a buffer for the next ep0 SETUP
> packet as soon as it retrieves the information for the current SETUP 
> packet from the buffer.
> 
> Otherwise, as you described it, if the gadget driver never sends its 
> delayed status response then the UDC will never respond to any more 
> control transfers.

we _do_ prepare transfers for setup packet everytime a Status phase is
completed (we also restart ep0 in case of stalls):

| static void dwc3_ep0_stall_and_restart(struct dwc3 *dwc)
| {
| 	struct dwc3_ep		*dep;
| 
| 	/* reinitialize physical ep1 */
| 	dep = dwc->eps[1];
| 	dep->flags = DWC3_EP_ENABLED;
| 
| 	/* stall is always issued on EP0 */
| 	dep = dwc->eps[0];
| 	__dwc3_gadget_ep_set_halt(dep, 1);
| 	dep->flags = DWC3_EP_ENABLED;
| 	dwc->delayed_status = false;
| 
| 	if (!list_empty(&dep->request_list)) {
| 		struct dwc3_request	*req;
| 
| 		req = next_request(&dep->request_list);
| 		dwc3_gadget_giveback(dep, req, -ECONNRESET);
| 	}
| 
| 	dwc->ep0state = EP0_SETUP_PHASE;
| 	dwc3_ep0_out_start(dwc);
| }

[ ... ]

| void dwc3_ep0_out_start(struct dwc3 *dwc)
| {
| 	int				ret;
| 
| 	ret = dwc3_ep0_start_trans(dwc, 0, dwc->ctrl_req_addr, 8,
| 			DWC3_TRBCTL_CONTROL_SETUP);
| 	WARN_ON(ret < 0);
| }

[ ... ]

| static void dwc3_ep0_complete_status(struct dwc3 *dwc,
| 		const struct dwc3_event_depevt *event)
| {
| 	struct dwc3_request	*r;
| 	struct dwc3_ep		*dep;
| 	struct dwc3_trb		*trb;
| 	u32			status;
| 
| 	dep = dwc->eps[0];
| 	trb = dwc->ep0_trb;
| 
| 	if (!list_empty(&dep->request_list)) {
| 		r = next_request(&dep->request_list);
| 
| 		dwc3_gadget_giveback(dep, r, 0);
| 	}
| 
| 	if (dwc->test_mode) {
| 		int ret;
| 
| 		ret = dwc3_gadget_set_test_mode(dwc, dwc->test_mode_nr);
| 		if (ret < 0) {
| 			dev_dbg(dwc->dev, "Invalid Test #%d\n",
| 					dwc->test_mode_nr);
| 			dwc3_ep0_stall_and_restart(dwc);
| 			return;
| 		}
| 	}
| 
| 	status = DWC3_TRB_SIZE_TRBSTS(trb->size);
| 	if (status == DWC3_TRBSTS_SETUP_PENDING)
| 		dev_dbg(dwc->dev, "Setup Pending received\n");
| 
| 	dwc->ep0state = EP0_SETUP_PHASE;
| 	dwc3_ep0_out_start(dwc);
| }

-- 
balbi

Attachment: signature.asc
Description: Digital signature


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

  Powered by Linux