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

Commit 347109c9 authored by Vijayavardhan Vennapusa's avatar Vijayavardhan Vennapusa Committed by Stephen Boyd
Browse files

USB: ci13xxx_udc: Convert ATDTW loop into finite one



Currently while queueing requests to HW, waiting in infinite
loop till ATDTW bit set for HW semaphore to be released by HW
to avoid race conditions between HW and SW. This could lead to
watchdog timer expiry if bus infrastructure is stuck. Hence
convert this loop into finite loop of 100msec which is atmost
required for USB HW to release HW semaphore as per HW team.

CRs-Fixed: 368769
Change-Id: Ibb2ab281f22230cf40574554273c3e4faf453b50
Signed-off-by: default avatarVijayavardhan Vennapusa <vvreddy@codeaurora.org>
parent 3b1a1ebb
Loading
Loading
Loading
Loading
+15 −0
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@
#include <linux/dmapool.h>
#include <linux/err.h>
#include <linux/irqreturn.h>
#include <linux/ratelimit.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/pm_runtime.h>
@@ -28,6 +29,8 @@
#include "bits.h"
#include "debug.h"

#define ATDTW_SET_DELAY		100 /* 100msec delay */

/* control endpoint description */
static const struct usb_endpoint_descriptor
ctrl_endpt_out_desc = {
@@ -442,6 +445,7 @@ static int _hardware_enqueue(struct ci13xxx_ep *mEp, struct ci13xxx_req *mReq)
		int n = hw_ep_bit(mEp->num, mEp->dir);
		int tmp_stat;
		u32 next = mReq->dma & TD_ADDR_MASK;
		ktime_t start, diff;

		mReqPrev = list_entry(mEp->qh.queue.prev,
				struct ci13xxx_req, queue);
@@ -452,9 +456,20 @@ static int _hardware_enqueue(struct ci13xxx_ep *mEp, struct ci13xxx_req *mReq)
		wmb();
		if (hw_read(ci, OP_ENDPTPRIME, BIT(n)))
			goto done;
		start = ktime_get();
		do {
			hw_write(ci, OP_USBCMD, USBCMD_ATDTW, USBCMD_ATDTW);
			tmp_stat = hw_read(ci, OP_ENDPTSTAT, BIT(n));
			diff = ktime_sub(ktime_get(), start);
			/* poll for max. 100ms */
			if (ktime_to_ms(diff) > ATDTW_SET_DELAY) {
				if (hw_read(ci, OP_USBCMD, USBCMD_ATDTW))
					break;
				printk_ratelimited(KERN_ERR
				"%s:queue failed ep#%d %s\n",
				 __func__, mEp->num, mEp->dir ? "IN" : "OUT");
				return -EAGAIN;
			}
		} while (!hw_read(ci, OP_USBCMD, USBCMD_ATDTW));
		hw_write(ci, OP_USBCMD, USBCMD_ATDTW, 0);
		if (tmp_stat)