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

Commit e8244d86 authored by Vijayavardhan Vennapusa's avatar Vijayavardhan Vennapusa
Browse files

USB: dwc3: gadget: Add support for sending zero length packets



Currently driver is not honouring req->zero flag even though
function driver sets this flag. If device has to send IN data back
to host and length is multiple of endpoint maximum packet size, it
should send additional zero length packet at the end to terminate
transfer.

CRs-Fixed: 592504
Change-Id: I5a8aecc504098ed386a9a9d19f4f5b78c911a376
Signed-off-by: default avatarVijayavardhan Vennapusa <vvreddy@codeaurora.org>
parent 012fce15
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -648,6 +648,7 @@ struct dwc3_request {

	u8			epnum;
	struct dwc3_trb		*trb;
	struct dwc3_trb		*ztrb;
	dma_addr_t		trb_dma;

	unsigned		direction:1;
+54 −3
Original line number Diff line number Diff line
@@ -294,6 +294,15 @@ void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req,
				dep->busy_slot++;
		} while(++i < req->request.num_mapped_sgs);
		req->queued = false;

		if (req->request.zero && req->ztrb) {
			dep->busy_slot++;
			req->ztrb = NULL;
			if (((dep->busy_slot & DWC3_TRB_MASK) ==
				DWC3_TRB_NUM - 1) &&
				usb_endpoint_xfer_isoc(dep->endpoint.desc))
				dep->busy_slot++;
		}
	}
	list_del(&req->list);
	req->trb = NULL;
@@ -863,6 +872,7 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep,

	dep->free_slot++;

update_trb:
	trb->size = DWC3_TRB_SIZE_LENGTH(length);
	trb->bpl = lower_32_bits(dma);
	trb->bph = upper_32_bits(dma);
@@ -897,8 +907,6 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep,
	if (usb_endpoint_xfer_isoc(dep->endpoint.desc)) {
		trb->ctrl |= DWC3_TRB_CTRL_ISP_IMI;
		trb->ctrl |= DWC3_TRB_CTRL_CSP;
	} else if (last) {
		trb->ctrl |= DWC3_TRB_CTRL_LST;
	}

	if (chain)
@@ -908,6 +916,25 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep,
		trb->ctrl |= DWC3_TRB_CTRL_SID_SOFN(req->request.stream_id);

	trb->ctrl |= DWC3_TRB_CTRL_HWO;

	if (req->request.zero && length &&
			(length % usb_endpoint_maxp(dep->endpoint.desc) == 0)) {
		/* Skip the LINK-TRB on ISOC */
		if (((dep->free_slot & DWC3_TRB_MASK) == DWC3_TRB_NUM - 1) &&
			usb_endpoint_xfer_isoc(dep->endpoint.desc))
			dep->free_slot++;

		trb = &dep->trb_pool[dep->free_slot & DWC3_TRB_MASK];
		dep->free_slot++;

		req->ztrb = trb;
		length = 0;

		goto update_trb;
	}

	if (!usb_endpoint_xfer_isoc(dep->endpoint.desc) && last)
		trb->ctrl |= DWC3_TRB_CTRL_LST;
}

/*
@@ -1011,12 +1038,25 @@ static void dwc3_prepare_trbs(struct dwc3_ep *dep, bool starting)
			}
			dbg_queue(dep->number, &req->request, 0);
		} else {
			struct dwc3_request	*req1;
			int maxpkt_size = usb_endpoint_maxp(dep->endpoint.desc);

			dma = req->request.dma;
			length = req->request.length;
			trbs_left--;

			if (!trbs_left)
			if (req->request.zero && length &&
						(length % maxpkt_size == 0))
				trbs_left--;

			if (!trbs_left) {
				last_one = 1;
			} else if (dep->direction && (trbs_left <= 1)) {
				req1 = next_request(&req->list);
				if (req1->request.zero && req1->request.length
				 && (req1->request.length % maxpkt_size == 0))
					last_one = 1;
			}

			/* Is this the last request? */
			if (list_is_last(&req->list, &dep->request_list))
@@ -2201,6 +2241,17 @@ static int dwc3_cleanup_done_reqs(struct dwc3 *dwc, struct dwc3_ep *dep,
				break;
		}while (++i < req->request.num_mapped_sgs);

		if (req->ztrb) {
			trb = req->ztrb;
			if ((event->status & DEPEVT_STATUS_LST) &&
				(trb->ctrl & (DWC3_TRB_CTRL_LST |
					DWC3_TRB_CTRL_HWO)))
				ret = 1;

			if ((event->status & DEPEVT_STATUS_IOC) &&
					(trb->ctrl & DWC3_TRB_CTRL_IOC))
				ret = 1;
		}
		dwc3_gadget_giveback(dep, req, status);

		if (ret)