/* 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);
        }
    }
}
Esempio n. 2
0
/* 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);
		}
	}
}