Example #1
0
static int
sfxge_ev_qstart(struct sfxge_softc *sc, unsigned int index)
{
	struct sfxge_evq *evq;
	efsys_mem_t *esmp;
	int count;
	int rc;

	evq = sc->evq[index];
	esmp = &evq->mem;

	KASSERT(evq->init_state == SFXGE_EVQ_INITIALIZED,
	    ("evq->init_state != SFXGE_EVQ_INITIALIZED"));

	/* Clear all events. */
	(void)memset(esmp->esm_base, 0xff, EFX_EVQ_SIZE(SFXGE_NEVS));

	/* Program the buffer table. */
	if ((rc = efx_sram_buf_tbl_set(sc->enp, evq->buf_base_id, esmp,
	    EFX_EVQ_NBUFS(SFXGE_NEVS))) != 0)
		return rc;

	/* Create the common code event queue. */
	if ((rc = efx_ev_qcreate(sc->enp, index, esmp, SFXGE_NEVS,
	    evq->buf_base_id, &evq->common)) != 0)
		goto fail;

	mtx_lock(&evq->lock);

	/* Set the default moderation */
	(void)efx_ev_qmoderate(evq->common, sc->ev_moderation);

	/* Prime the event queue for interrupts */
	if ((rc = efx_ev_qprime(evq->common, evq->read_ptr)) != 0)
		goto fail2;

	evq->init_state = SFXGE_EVQ_STARTING;

	mtx_unlock(&evq->lock);

	/* Wait for the initialization event */
	count = 0;
	do {
		/* Pause for 100 ms */
		pause("sfxge evq init", hz / 10);

		/* Check to see if the test event has been processed */
		if (evq->init_state == SFXGE_EVQ_STARTED)
			goto done;

	} while (++count < 20);

	rc = ETIMEDOUT;
	goto fail3;

done:
	return (0);

fail3:
	mtx_lock(&evq->lock);
	evq->init_state = SFXGE_EVQ_INITIALIZED;
fail2:
	mtx_unlock(&evq->lock);
	efx_ev_qdestroy(evq->common);
fail:
	efx_sram_buf_tbl_clear(sc->enp, evq->buf_base_id,
	    EFX_EVQ_NBUFS(SFXGE_NEVS));

	return (rc);
}
Example #2
0
/* Event queue HW index allocation scheme is described in sfc_ev.h. */
int
sfc_ev_qstart(struct sfc_evq *evq, unsigned int hw_index)
{
	struct sfc_adapter *sa = evq->sa;
	efsys_mem_t *esmp;
	uint32_t evq_flags = sa->evq_flags;
	unsigned int total_delay_us;
	unsigned int delay_us;
	int rc;

	sfc_log_init(sa, "hw_index=%u", hw_index);

	esmp = &evq->mem;

	evq->evq_index = hw_index;

	/* Clear all events */
	(void)memset((void *)esmp->esm_base, 0xff, EFX_EVQ_SIZE(evq->entries));

	if (sa->intr.lsc_intr && hw_index == sa->mgmt_evq_index)
		evq_flags |= EFX_EVQ_FLAGS_NOTIFY_INTERRUPT;
	else
		evq_flags |= EFX_EVQ_FLAGS_NOTIFY_DISABLED;

	/* Create the common code event queue */
	rc = efx_ev_qcreate(sa->nic, hw_index, esmp, evq->entries,
			    0 /* unused on EF10 */, 0, evq_flags,
			    &evq->common);
	if (rc != 0)
		goto fail_ev_qcreate;

	SFC_ASSERT(evq->dp_rxq == NULL || evq->dp_txq == NULL);
	if (evq->dp_rxq != 0) {
		if (strcmp(sa->dp_rx->dp.name, SFC_KVARG_DATAPATH_EFX) == 0)
			evq->callbacks = &sfc_ev_callbacks_efx_rx;
		else
			evq->callbacks = &sfc_ev_callbacks_dp_rx;
	} else if (evq->dp_txq != 0) {
		if (strcmp(sa->dp_tx->dp.name, SFC_KVARG_DATAPATH_EFX) == 0)
			evq->callbacks = &sfc_ev_callbacks_efx_tx;
		else
			evq->callbacks = &sfc_ev_callbacks_dp_tx;
	} else {
		evq->callbacks = &sfc_ev_callbacks;
	}

	evq->init_state = SFC_EVQ_STARTING;

	/* Wait for the initialization event */
	total_delay_us = 0;
	delay_us = SFC_EVQ_INIT_BACKOFF_START_US;
	do {
		(void)sfc_ev_qpoll(evq);

		/* Check to see if the initialization complete indication
		 * posted by the hardware.
		 */
		if (evq->init_state == SFC_EVQ_STARTED)
			goto done;

		/* Give event queue some time to init */
		rte_delay_us(delay_us);

		total_delay_us += delay_us;

		/* Exponential backoff */
		delay_us *= 2;
		if (delay_us > SFC_EVQ_INIT_BACKOFF_MAX_US)
			delay_us = SFC_EVQ_INIT_BACKOFF_MAX_US;

	} while (total_delay_us < SFC_EVQ_INIT_TIMEOUT_US);

	rc = ETIMEDOUT;
	goto fail_timedout;

done:
	return 0;

fail_timedout:
	evq->init_state = SFC_EVQ_INITIALIZED;
	efx_ev_qdestroy(evq->common);

fail_ev_qcreate:
	sfc_log_init(sa, "failed %d", rc);
	return rc;
}