|
@@ -1247,24 +1247,27 @@ static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
|
|
|
|
|
|
static void scan_async (struct ehci_hcd *ehci)
|
|
|
{
|
|
|
+ bool stopped;
|
|
|
struct ehci_qh *qh;
|
|
|
enum ehci_timer_action action = TIMER_IO_WATCHDOG;
|
|
|
|
|
|
ehci->stamp = ehci_readl(ehci, &ehci->regs->frame_index);
|
|
|
timer_action_done (ehci, TIMER_ASYNC_SHRINK);
|
|
|
rescan:
|
|
|
+ stopped = !HC_IS_RUNNING(ehci_to_hcd(ehci)->state);
|
|
|
qh = ehci->async->qh_next.qh;
|
|
|
if (likely (qh != NULL)) {
|
|
|
do {
|
|
|
/* clean any finished work for this qh */
|
|
|
- if (!list_empty (&qh->qtd_list)
|
|
|
- && qh->stamp != ehci->stamp) {
|
|
|
+ if (!list_empty(&qh->qtd_list) && (stopped ||
|
|
|
+ qh->stamp != ehci->stamp)) {
|
|
|
int temp;
|
|
|
|
|
|
/* unlinks could happen here; completion
|
|
|
* reporting drops the lock. rescan using
|
|
|
* the latest schedule, but don't rescan
|
|
|
- * qhs we already finished (no looping).
|
|
|
+ * qhs we already finished (no looping)
|
|
|
+ * unless the controller is stopped.
|
|
|
*/
|
|
|
qh = qh_get (qh);
|
|
|
qh->stamp = ehci->stamp;
|
|
@@ -1285,9 +1288,9 @@ rescan:
|
|
|
*/
|
|
|
if (list_empty(&qh->qtd_list)
|
|
|
&& qh->qh_state == QH_STATE_LINKED) {
|
|
|
- if (!ehci->reclaim
|
|
|
- && ((ehci->stamp - qh->stamp) & 0x1fff)
|
|
|
- >= (EHCI_SHRINK_FRAMES * 8))
|
|
|
+ if (!ehci->reclaim && (stopped ||
|
|
|
+ ((ehci->stamp - qh->stamp) & 0x1fff)
|
|
|
+ >= EHCI_SHRINK_FRAMES * 8))
|
|
|
start_unlink_async(ehci, qh);
|
|
|
else
|
|
|
action = TIMER_ASYNC_SHRINK;
|