static void
sfc_mcdi_poll(struct sfc_adapter *sa)
{
	efx_nic_t *enp;
	unsigned int delay_total;
	unsigned int delay_us;
	boolean_t aborted __rte_unused;

	delay_total = 0;
	delay_us = SFC_MCDI_POLL_INTERVAL_MIN_US;
	enp = sa->nic;

	do {
		if (efx_mcdi_request_poll(enp))
			return;

		if (delay_total > SFC_MCDI_WATCHDOG_INTERVAL_US) {
			aborted = efx_mcdi_request_abort(enp);
			SFC_ASSERT(aborted);
			sfc_mcdi_timeout(sa);
			return;
		}

		rte_delay_us(delay_us);

		delay_total += delay_us;

		/* Exponentially back off the poll frequency */
		RTE_BUILD_BUG_ON(SFC_MCDI_POLL_INTERVAL_MAX_US > UINT_MAX / 2);
		delay_us *= 2;
		if (delay_us > SFC_MCDI_POLL_INTERVAL_MAX_US)
			delay_us = SFC_MCDI_POLL_INTERVAL_MAX_US;

	} while (1);
}
Exemple #2
0
static void
sfxge_mcdi_poll(struct sfxge_softc *sc)
{
	efx_nic_t *enp;
	clock_t delay_total;
	clock_t delay_us;
	boolean_t aborted;

	delay_total = 0;
	delay_us = SFXGE_MCDI_POLL_INTERVAL_MIN;
	enp = sc->enp;

	do {
		if (efx_mcdi_request_poll(enp)) {
			EFSYS_PROBE1(mcdi_delay, clock_t, delay_total);
			return;
		}

		if (delay_total > SFXGE_MCDI_WATCHDOG_INTERVAL) {
			aborted = efx_mcdi_request_abort(enp);
			KASSERT(aborted, ("abort failed"));
			sfxge_mcdi_timeout(sc);
			return;
		}

		/* Spin or block depending on delay interval. */
		if (delay_us < 1000000)
			DELAY(delay_us);
		else
			pause("mcdi wait", delay_us * hz / 1000000);

		delay_total += delay_us;

		/* Exponentially back off the poll frequency. */
		delay_us = delay_us * 2;
		if (delay_us > SFXGE_MCDI_POLL_INTERVAL_MAX)
			delay_us = SFXGE_MCDI_POLL_INTERVAL_MAX;

	} while (1);
}