summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTerin Stock <terin@terinstock.com>2018-09-10 00:24:31 -0400
committerFelipe Balbi <felipe.balbi@linux.intel.com>2018-12-05 04:13:14 -0500
commit6ed30a7d8ec29d3aba46e47aa8b4a44f077dda4e (patch)
tree75c572da124c9259ddfd1fbf18d94aacd8480c29
parent47b6f8bf870035d420614844de5e308abe505e8a (diff)
usb: dwc2: host: use hrtimer for NAK retries
Modify the wait delay utilize the high resolution timer API to allow for more precisely scheduled callbacks. A previous commit added a 1ms retry delay after multiple consecutive NAKed transactions using jiffies. On systems with a low timer interrupt frequency, this delay may be significantly longer than specified, resulting in misbehavior with some USB devices. This scenario was reached on a Raspberry Pi 3B with a Macally FDD-USB floppy drive (identified as 0424:0fdc Standard Microsystems Corp. Floppy, based on the USB97CFDC USB FDC). With the relay delay, the drive would be unable to mount a disk, replying with NAKs until the device was reset. Using ktime, the delta between starting the timer (in dwc2_hcd_qh_add) and the callback function can be determined. With the original delay implementation, this value was consistently approximately 12ms. (output in us). <idle>-0 [000] ..s. 1600.559974: dwc2_wait_timer_fn: wait_timer delta: 11976 <idle>-0 [000] ..s. 1600.571974: dwc2_wait_timer_fn: wait_timer delta: 11977 <idle>-0 [000] ..s. 1600.583974: dwc2_wait_timer_fn: wait_timer delta: 11976 <idle>-0 [000] ..s. 1600.595974: dwc2_wait_timer_fn: wait_timer delta: 11977 After converting the relay delay to using a higher resolution timer, the delay was much closer to 1ms. <idle>-0 [000] d.h. 1956.553017: dwc2_wait_timer_fn: wait_timer delta: 1002 <idle>-0 [000] d.h. 1956.554114: dwc2_wait_timer_fn: wait_timer delta: 1002 <idle>-0 [000] d.h. 1957.542660: dwc2_wait_timer_fn: wait_timer delta: 1004 <idle>-0 [000] d.h. 1957.543701: dwc2_wait_timer_fn: wait_timer delta: 1002 The floppy drive operates properly with delays up to approximately 5ms, and sends NAKs for any delays that are longer. Fixes: 38d2b5fb75c1 ("usb: dwc2: host: Don't retry NAKed transactions right away") Cc: <stable@vger.kernel.org> Reviewed-by: Douglas Anderson <dianders@chromium.org> Acked-by: Minas Harutyunyan <hminas@synopsys.com> Signed-off-by: Terin Stock <terin@terinstock.com> Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
-rw-r--r--drivers/usb/dwc2/hcd.h2
-rw-r--r--drivers/usb/dwc2/hcd_queue.c19
2 files changed, 13 insertions, 8 deletions
diff --git a/drivers/usb/dwc2/hcd.h b/drivers/usb/dwc2/hcd.h
index 3f9bccc95add..c089ffa1f0a8 100644
--- a/drivers/usb/dwc2/hcd.h
+++ b/drivers/usb/dwc2/hcd.h
@@ -366,7 +366,7 @@ struct dwc2_qh {
366 u32 desc_list_sz; 366 u32 desc_list_sz;
367 u32 *n_bytes; 367 u32 *n_bytes;
368 struct timer_list unreserve_timer; 368 struct timer_list unreserve_timer;
369 struct timer_list wait_timer; 369 struct hrtimer wait_timer;
370 struct dwc2_tt *dwc_tt; 370 struct dwc2_tt *dwc_tt;
371 int ttport; 371 int ttport;
372 unsigned tt_buffer_dirty:1; 372 unsigned tt_buffer_dirty:1;
diff --git a/drivers/usb/dwc2/hcd_queue.c b/drivers/usb/dwc2/hcd_queue.c
index 40839591d2ec..ea3aa640c15c 100644
--- a/drivers/usb/dwc2/hcd_queue.c
+++ b/drivers/usb/dwc2/hcd_queue.c
@@ -59,7 +59,7 @@
59#define DWC2_UNRESERVE_DELAY (msecs_to_jiffies(5)) 59#define DWC2_UNRESERVE_DELAY (msecs_to_jiffies(5))
60 60
61/* If we get a NAK, wait this long before retrying */ 61/* If we get a NAK, wait this long before retrying */
62#define DWC2_RETRY_WAIT_DELAY (msecs_to_jiffies(1)) 62#define DWC2_RETRY_WAIT_DELAY 1*1E6L
63 63
64/** 64/**
65 * dwc2_periodic_channel_available() - Checks that a channel is available for a 65 * dwc2_periodic_channel_available() - Checks that a channel is available for a
@@ -1464,10 +1464,12 @@ static void dwc2_deschedule_periodic(struct dwc2_hsotg *hsotg,
1464 * qh back to the "inactive" list, then queues transactions. 1464 * qh back to the "inactive" list, then queues transactions.
1465 * 1465 *
1466 * @t: Pointer to wait_timer in a qh. 1466 * @t: Pointer to wait_timer in a qh.
1467 *
1468 * Return: HRTIMER_NORESTART to not automatically restart this timer.
1467 */ 1469 */
1468static void dwc2_wait_timer_fn(struct timer_list *t) 1470static enum hrtimer_restart dwc2_wait_timer_fn(struct hrtimer *t)
1469{ 1471{
1470 struct dwc2_qh *qh = from_timer(qh, t, wait_timer); 1472 struct dwc2_qh *qh = container_of(t, struct dwc2_qh, wait_timer);
1471 struct dwc2_hsotg *hsotg = qh->hsotg; 1473 struct dwc2_hsotg *hsotg = qh->hsotg;
1472 unsigned long flags; 1474 unsigned long flags;
1473 1475
@@ -1491,6 +1493,7 @@ static void dwc2_wait_timer_fn(struct timer_list *t)
1491 } 1493 }
1492 1494
1493 spin_unlock_irqrestore(&hsotg->lock, flags); 1495 spin_unlock_irqrestore(&hsotg->lock, flags);
1496 return HRTIMER_NORESTART;
1494} 1497}
1495 1498
1496/** 1499/**
@@ -1521,7 +1524,8 @@ static void dwc2_qh_init(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh,
1521 /* Initialize QH */ 1524 /* Initialize QH */
1522 qh->hsotg = hsotg; 1525 qh->hsotg = hsotg;
1523 timer_setup(&qh->unreserve_timer, dwc2_unreserve_timer_fn, 0); 1526 timer_setup(&qh->unreserve_timer, dwc2_unreserve_timer_fn, 0);
1524 timer_setup(&qh->wait_timer, dwc2_wait_timer_fn, 0); 1527 hrtimer_init(&qh->wait_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
1528 qh->wait_timer.function = &dwc2_wait_timer_fn;
1525 qh->ep_type = ep_type; 1529 qh->ep_type = ep_type;
1526 qh->ep_is_in = ep_is_in; 1530 qh->ep_is_in = ep_is_in;
1527 1531
@@ -1690,7 +1694,7 @@ void dwc2_hcd_qh_free(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh)
1690 * won't do anything anyway, but we want it to finish before we free 1694 * won't do anything anyway, but we want it to finish before we free
1691 * memory. 1695 * memory.
1692 */ 1696 */
1693 del_timer_sync(&qh->wait_timer); 1697 hrtimer_cancel(&qh->wait_timer);
1694 1698
1695 dwc2_host_put_tt_info(hsotg, qh->dwc_tt); 1699 dwc2_host_put_tt_info(hsotg, qh->dwc_tt);
1696 1700
@@ -1716,6 +1720,7 @@ int dwc2_hcd_qh_add(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh)
1716{ 1720{
1717 int status; 1721 int status;
1718 u32 intr_mask; 1722 u32 intr_mask;
1723 ktime_t delay;
1719 1724
1720 if (dbg_qh(qh)) 1725 if (dbg_qh(qh))
1721 dev_vdbg(hsotg->dev, "%s()\n", __func__); 1726 dev_vdbg(hsotg->dev, "%s()\n", __func__);
@@ -1734,8 +1739,8 @@ int dwc2_hcd_qh_add(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh)
1734 list_add_tail(&qh->qh_list_entry, 1739 list_add_tail(&qh->qh_list_entry,
1735 &hsotg->non_periodic_sched_waiting); 1740 &hsotg->non_periodic_sched_waiting);
1736 qh->wait_timer_cancel = false; 1741 qh->wait_timer_cancel = false;
1737 mod_timer(&qh->wait_timer, 1742 delay = ktime_set(0, DWC2_RETRY_WAIT_DELAY);
1738 jiffies + DWC2_RETRY_WAIT_DELAY + 1); 1743 hrtimer_start(&qh->wait_timer, delay, HRTIMER_MODE_REL);
1739 } else { 1744 } else {
1740 list_add_tail(&qh->qh_list_entry, 1745 list_add_tail(&qh->qh_list_entry,
1741 &hsotg->non_periodic_sched_inactive); 1746 &hsotg->non_periodic_sched_inactive);