Exemple #1
0
static void dwc3_ep0_complete_data(struct dwc3 *dwc,
		const struct dwc3_event_depevt *event)
{
	struct dwc3_request	*r = NULL;
	struct usb_request	*ur;
	struct dwc3_trb		*trb;
	struct dwc3_ep		*ep0;
	unsigned		maxp;
	unsigned		remaining_ur_length;
	void			*buf;
	u32			transferred = 0;
	u32			status;
	u32			length;
	u8			epnum;

	epnum = event->endpoint_number;
	ep0 = dwc->eps[0];

	dwc->ep0_next_event = DWC3_EP0_NRDY_STATUS;
	trb = dwc->ep0_trb;
	trace_dwc3_complete_trb(ep0, trb);

	r = next_request(&ep0->pending_list);
	if (!r)
		return;

	status = DWC3_TRB_SIZE_TRBSTS(trb->size);
	if (status == DWC3_TRBSTS_SETUP_PENDING) {
		dwc->setup_packet_pending = true;
		if (r)
			dwc3_gadget_giveback(ep0, r, -ECONNRESET);

		return;
	}

	ur = &r->request;
	buf = ur->buf;
	remaining_ur_length = ur->length;

	length = trb->size & DWC3_TRB_SIZE_MASK;
	maxp = ep0->endpoint.maxpacket;
	transferred = ur->length - length;
	ur->actual += transferred;

	if ((IS_ALIGNED(ur->length, ep0->endpoint.maxpacket) &&
	     ur->length && ur->zero) || dwc->ep0_bounced) {
		trb++;
		trb->ctrl &= ~DWC3_TRB_CTRL_HWO;
		trace_dwc3_complete_trb(ep0, trb);
		ep0->trb_enqueue = 0;
		dwc->ep0_bounced = false;
	}

	if ((epnum & 1) && ur->actual < ur->length)
		dwc3_ep0_stall_and_restart(dwc);
	else
		dwc3_gadget_giveback(ep0, r, 0);
}
Exemple #2
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;

	trace_dwc3_complete_trb(dep, 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) {
			dwc3_trace(trace_dwc3_ep0, "Invalid Test #%d",
					dwc->test_mode_nr);
			dwc3_ep0_stall_and_restart(dwc);
			return;
		}
	}

	status = DWC3_TRB_SIZE_TRBSTS(trb->size);
	if (status == DWC3_TRBSTS_SETUP_PENDING) {
		dwc->setup_packet_pending = true;
		dwc3_trace(trace_dwc3_ep0, "Setup Pending received");
	}

	dwc->ep0state = EP0_SETUP_PHASE;
	dwc3_ep0_out_start(dwc);
}
Exemple #3
0
static void dwc3_ep0_complete_data(struct dwc3 *dwc,
		const struct dwc3_event_depevt *event)
{
	struct dwc3_request	*r = NULL;
	struct usb_request	*ur;
	struct dwc3_trb		*trb;
	struct dwc3_ep		*ep0;
	unsigned		transfer_size = 0;
	unsigned		maxp;
	unsigned		remaining_ur_length;
	void			*buf;
	u32			transferred = 0;
	u32			status;
	u32			length;
	u8			epnum;

	epnum = event->endpoint_number;
	ep0 = dwc->eps[0];

	dwc->ep0_next_event = DWC3_EP0_NRDY_STATUS;

	trb = dwc->ep0_trb;

	trace_dwc3_complete_trb(ep0, trb);

	r = next_request(&ep0->request_list);
	if (!r)
		return;

	status = DWC3_TRB_SIZE_TRBSTS(trb->size);
	if (status == DWC3_TRBSTS_SETUP_PENDING) {
		dwc->setup_packet_pending = true;

		dwc3_trace(trace_dwc3_ep0, "Setup Pending received");

		if (r)
			dwc3_gadget_giveback(ep0, r, -ECONNRESET);

		return;
	}

	ur = &r->request;
	buf = ur->buf;
	remaining_ur_length = ur->length;

	length = trb->size & DWC3_TRB_SIZE_MASK;

	maxp = ep0->endpoint.maxpacket;

	if (dwc->ep0_bounced) {
		/*
		 * Handle the first TRB before handling the bounce buffer if
		 * the request length is greater than the bounce buffer size
		 */
		if (ur->length > DWC3_EP0_BOUNCE_SIZE) {
			transfer_size = ALIGN(ur->length - maxp, maxp);
			transferred = transfer_size - length;
			buf = (u8 *)buf + transferred;
			ur->actual += transferred;
			remaining_ur_length -= transferred;

			trb++;
			length = trb->size & DWC3_TRB_SIZE_MASK;

			ep0->free_slot = 0;
		}

		transfer_size = roundup((ur->length - transfer_size),
					maxp);

		transferred = min_t(u32, remaining_ur_length,
				    transfer_size - length);
		memcpy(buf, dwc->ep0_bounce, transferred);
	} else {
		transferred = ur->length - length;
	}

	ur->actual += transferred;

	if ((epnum & 1) && ur->actual < ur->length) {
		/* for some reason we did not get everything out */

		dwc3_ep0_stall_and_restart(dwc);
	} else {
		dwc3_gadget_giveback(ep0, r, 0);

		if (IS_ALIGNED(ur->length, ep0->endpoint.maxpacket) &&
				ur->length && ur->zero) {
			int ret;

			dwc->ep0_next_event = DWC3_EP0_COMPLETE;

			ret = dwc3_ep0_start_trans(dwc, epnum,
					dwc->ctrl_req_addr, 0,
					DWC3_TRBCTL_CONTROL_DATA, false);
			WARN_ON(ret < 0);
		}
	}
}
Exemple #4
0
static void dwc3_ep0_complete_data(struct dwc3 *dwc,
		const struct dwc3_event_depevt *event)
{
	struct dwc3_request	*r = NULL;
	struct usb_request	*ur;
	struct dwc3_trb		*trb;
	struct dwc3_ep		*ep0;
	u32			transferred;
	u32			status;
	u32			length;
	u8			epnum;

	epnum = event->endpoint_number;
	ep0 = dwc->eps[0];

	dwc->ep0_next_event = DWC3_EP0_NRDY_STATUS;

	trb = dwc->ep0_trb;

	trace_dwc3_complete_trb(ep0, trb);

	r = next_request(&ep0->request_list);
	if (!r)
		return;

	status = DWC3_TRB_SIZE_TRBSTS(trb->size);
	if (status == DWC3_TRBSTS_SETUP_PENDING) {
		dwc3_trace(trace_dwc3_ep0, "Setup Pending received");

		if (r)
			dwc3_gadget_giveback(ep0, r, -ECONNRESET);

		return;
	}

	ur = &r->request;

	length = trb->size & DWC3_TRB_SIZE_MASK;

	if (dwc->ep0_bounced) {
		unsigned transfer_size = ur->length;
		unsigned maxp = ep0->endpoint.maxpacket;

		transfer_size += (maxp - (transfer_size % maxp));
		transferred = min_t(u32, ur->length,
				transfer_size - length);
		memcpy(ur->buf, dwc->ep0_bounce, transferred);
	} else {
		transferred = ur->length - length;
	}

	ur->actual += transferred;

	if ((epnum & 1) && ur->actual < ur->length) {
		/* for some reason we did not get everything out */

		dwc3_ep0_stall_and_restart(dwc);
	} else {
		dwc3_gadget_giveback(ep0, r, 0);

		if (IS_ALIGNED(ur->length, ep0->endpoint.maxpacket) &&
				ur->length && ur->zero) {
			int ret;

			dwc->ep0_next_event = DWC3_EP0_COMPLETE;

			ret = dwc3_ep0_start_trans(dwc, epnum,
					dwc->ctrl_req_addr, 0,
					DWC3_TRBCTL_CONTROL_DATA);
			WARN_ON(ret < 0);
		}
	}
}