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

Commit c2bbd16b authored by Neil Zhang's avatar Neil Zhang Committed by Felipe Balbi
Browse files

usb: gadget: mv_udc: fix bug in ep_dequeue



According to ChipIdea's SPEC, we cannot touch curr_dtd_ptr in dqh
directly, use prime endpoint instead.

Signed-off-by: default avatarNeil Zhang <zhangwm@marvell.com>
Signed-off-by: default avatarFelipe Balbi <balbi@ti.com>
parent a7250db3
Loading
Loading
Loading
Loading
+24 −5
Original line number Original line Diff line number Diff line
@@ -778,6 +778,27 @@ mv_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
	return 0;
	return 0;
}
}


static void mv_prime_ep(struct mv_ep *ep, struct mv_req *req)
{
	struct mv_dqh *dqh = ep->dqh;
	u32 bit_pos;

	/* Write dQH next pointer and terminate bit to 0 */
	dqh->next_dtd_ptr = req->head->td_dma
		& EP_QUEUE_HEAD_NEXT_POINTER_MASK;

	/* clear active and halt bit, in case set from a previous error */
	dqh->size_ioc_int_sts &= ~(DTD_STATUS_ACTIVE | DTD_STATUS_HALTED);

	/* Ensure that updates to the QH will occure before priming. */
	wmb();

	bit_pos = 1 << (((ep_dir(ep) == EP_DIR_OUT) ? 0 : 16) + ep->ep_num);

	/* Prime the Endpoint */
	writel(bit_pos, &ep->udc->op_regs->epprime);
}

/* dequeues (cancels, unlinks) an I/O request from an endpoint */
/* dequeues (cancels, unlinks) an I/O request from an endpoint */
static int mv_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req)
static int mv_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req)
{
{
@@ -820,15 +841,13 @@ static int mv_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req)


		/* The request isn't the last request in this ep queue */
		/* The request isn't the last request in this ep queue */
		if (req->queue.next != &ep->queue) {
		if (req->queue.next != &ep->queue) {
			struct mv_dqh *qh;
			struct mv_req *next_req;
			struct mv_req *next_req;


			qh = ep->dqh;
			next_req = list_entry(req->queue.next,
			next_req = list_entry(req->queue.next, struct mv_req,
				struct mv_req, queue);
					queue);


			/* Point the QH to the first TD of next request */
			/* Point the QH to the first TD of next request */
			writel((u32) next_req->head, &qh->curr_dtd_ptr);
			mv_prime_ep(ep, next_req);
		} else {
		} else {
			struct mv_dqh *qh;
			struct mv_dqh *qh;