[PATCH 3/3] usb: dwc2: host: do not schedule delayed QH unnecessarily

From: Dmitry Torokhov
Date: Fri Jun 15 2018 - 18:01:49 EST


When we are ready to retry the delayed QH, we do not need to manually
scan queues and schedule them if controller is already running; we only
need to do that if SOF interrupt is masked, otherwise we'll pick them up
at the next frame.

Signed-off-by: Dmitry Torokhov <dmitry.torokhov@xxxxxxxxx>
---
drivers/usb/dwc2/hcd_queue.c | 31 ++++++++++++++++++-------------
1 file changed, 18 insertions(+), 13 deletions(-)

diff --git a/drivers/usb/dwc2/hcd_queue.c b/drivers/usb/dwc2/hcd_queue.c
index e34ad5e653501..db9e7c9d31554 100644
--- a/drivers/usb/dwc2/hcd_queue.c
+++ b/drivers/usb/dwc2/hcd_queue.c
@@ -1468,6 +1468,8 @@ static void dwc2_wait_timer_fn(struct timer_list *t)
{
struct dwc2_qh *qh = from_timer(qh, t, wait_timer);
struct dwc2_hsotg *hsotg = qh->hsotg;
+ enum dwc2_transaction_type tr_type;
+ u32 intr_mask;
unsigned long flags;

spin_lock_irqsave(&hsotg->lock, flags);
@@ -1476,19 +1478,22 @@ static void dwc2_wait_timer_fn(struct timer_list *t)
* We'll set wait_timer_cancel to true if we want to cancel this
* operation in dwc2_hcd_qh_unlink().
*/
- if (!qh->wait_timer_cancel) {
- enum dwc2_transaction_type tr_type;
+ if (qh->wait_timer_cancel)
+ goto out_unlock;

- qh->want_wait = false;
+ list_move(&qh->qh_list_entry, &hsotg->non_periodic_sched_inactive);

- list_move(&qh->qh_list_entry,
- &hsotg->non_periodic_sched_inactive);
+ /* See if we should kick the controller if it was idle */
+ intr_mask = dwc2_readl(hsotg->regs + GINTMSK);
+ if (intr_mask & GINTSTS_SOF)
+ goto out_unlock;

- tr_type = dwc2_hcd_select_transactions(hsotg);
- if (tr_type != DWC2_TRANSACTION_NONE)
- dwc2_hcd_queue_transactions(hsotg, tr_type);
- }
+ /* The controller was idle, let's try queue our postponed work */
+ tr_type = dwc2_hcd_select_transactions(hsotg);
+ if (tr_type != DWC2_TRANSACTION_NONE)
+ dwc2_hcd_queue_transactions(hsotg, tr_type);

+out_unlock:
spin_unlock_irqrestore(&hsotg->lock, flags);
}

@@ -1722,10 +1727,6 @@ int dwc2_hcd_qh_add(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh)

/* Add the new QH to the appropriate schedule */
if (dwc2_qh_is_non_per(qh)) {
- /* Schedule right away */
- qh->start_active_frame = hsotg->frame_number;
- qh->next_active_frame = qh->start_active_frame;
-
if (qh->want_wait) {
list_add_tail(&qh->qh_list_entry,
&hsotg->non_periodic_sched_waiting);
@@ -1733,6 +1734,10 @@ int dwc2_hcd_qh_add(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh)
mod_timer(&qh->wait_timer,
jiffies + DWC2_RETRY_WAIT_DELAY + 1);
} else {
+ /* Schedule right away */
+ qh->start_active_frame = hsotg->frame_number;
+ qh->next_active_frame = qh->start_active_frame;
+
list_add_tail(&qh->qh_list_entry,
&hsotg->non_periodic_sched_inactive);
}
--
2.18.0.rc1.244.gcf134e6275-goog