/* Poll the STS_ASS status bit; see when it agrees with CMD_ASE */ static void ehci_poll_ASS(struct ehci_hcd *ehci) { unsigned actual, want; /* Don't enable anything if the controller isn't running (e.g., died) */ if (ehci->rh_state != EHCI_RH_RUNNING) return; want = (ehci->command & CMD_ASE) ? STS_ASS : 0; actual = ehci_readl(ehci, &ehci->regs->status) & STS_ASS; if (want != actual) { /* Poll again later */ ehci_enable_event(ehci, EHCI_HRTIMER_POLL_ASS, true); ++ehci->ASS_poll_count; return; } if (ehci->ASS_poll_count > 20) ehci_dbg(ehci, "ASS poll count reached %d\n", ehci->ASS_poll_count); ehci->ASS_poll_count = 0; /* The status is up-to-date; restart or stop the schedule as needed */ if (want == 0) { /* Stopped */ if (ehci->async_count > 0) ehci_set_command_bit(ehci, CMD_ASE); } else { /* Running */ if (ehci->async_count == 0) { /* Turn off the schedule after a while */ ehci_enable_event(ehci, EHCI_HRTIMER_DISABLE_ASYNC, true); } } }
/* Poll the STS_PSS status bit; see when it agrees with CMD_PSE */ static void ehci_poll_PSS(struct ehci_hcd *ehci) { unsigned actual, want; /* Don't do anything if the controller isn't running (e.g., died) */ if (ehci->rh_state != EHCI_RH_RUNNING) return; want = (ehci->command & CMD_PSE) ? STS_PSS : 0; actual = ehci_readl(ehci, &ehci->regs->status) & STS_PSS; if (want != actual) { /* Poll again later, but give up after about 2-4 ms */ if (ehci->PSS_poll_count++ < 2) { ehci_enable_event(ehci, EHCI_HRTIMER_POLL_PSS, true); return; } ehci_dbg(ehci, "Waited too long for the periodic schedule status (%x/%x), giving up\n", want, actual); } ehci->PSS_poll_count = 0; /* The status is up-to-date; restart or stop the schedule as needed */ if (want == 0) { /* Stopped */ if (ehci->periodic_count > 0) ehci_set_command_bit(ehci, CMD_PSE); } else { /* Running */ if (ehci->periodic_count == 0) { /* Turn off the schedule after a while */ ehci_enable_event(ehci, EHCI_HRTIMER_DISABLE_PERIODIC, true); } } }