Exemplo n.º 1
0
static int
sfxge_intr_line_filter(void *arg)
{
	struct sfxge_evq *evq;
	struct sfxge_softc *sc;
	efx_nic_t *enp;
	struct sfxge_intr *intr;
	boolean_t fatal;
	uint32_t qmask;

	evq = (struct sfxge_evq *)arg;
	sc = evq->sc;
	enp = sc->enp;
	intr = &sc->intr;

	KASSERT(intr != NULL, ("intr == NULL"));
	KASSERT(intr->type == EFX_INTR_LINE,
	    ("intr->type != EFX_INTR_LINE"));

	if (intr->state != SFXGE_INTR_STARTED)
		return FILTER_STRAY;

	(void)efx_intr_status_line(enp, &fatal, &qmask);

	if (fatal) {
		(void) efx_intr_disable(enp);
		(void) efx_intr_fatal(enp);
		return FILTER_HANDLED;
	}

	if (qmask != 0) {
		intr->zero_count = 0;
		return FILTER_SCHEDULE_THREAD;
	}

	/* SF bug 15783: If the function is not asserting its IRQ and
	 * we read the queue mask on the cycle before a flag is added
	 * to the mask, this inhibits the function from asserting the
	 * IRQ even though we don't see the flag set.  To work around
	 * this, we must re-prime all event queues and report the IRQ
	 * as handled when we see a mask of zero.  To allow for shared
	 * IRQs, we don't repeat this if we see a mask of zero twice
	 * or more in a row.
	 */
	if (intr->zero_count++ == 0) {
		if (evq->init_state == SFXGE_EVQ_STARTED) {
			if (efx_ev_qpending(evq->common, evq->read_ptr))
				return FILTER_SCHEDULE_THREAD;
			efx_ev_qprime(evq->common, evq->read_ptr);
			return FILTER_HANDLED;
		}
	}

	return FILTER_STRAY;
}
Exemplo n.º 2
0
int
sfxge_ev_qpoll(struct sfxge_softc *sc, unsigned int index)
{
	struct sfxge_evq *evq;
	int rc;

	evq = sc->evq[index];

	mtx_lock(&evq->lock);

	if (evq->init_state != SFXGE_EVQ_STARTING &&
	    evq->init_state != SFXGE_EVQ_STARTED) {
		rc = EINVAL;
		goto fail;
	}

	/* Synchronize the DMA memory for reading */
	bus_dmamap_sync(evq->mem.esm_tag, evq->mem.esm_map,
	    BUS_DMASYNC_POSTREAD);

	KASSERT(evq->rx_done == 0, ("evq->rx_done != 0"));
	KASSERT(evq->tx_done == 0, ("evq->tx_done != 0"));
	KASSERT(evq->txq == NULL, ("evq->txq != NULL"));
	KASSERT(evq->txqs == &evq->txq, ("evq->txqs != &evq->txq"));

	/* Poll the queue */
	efx_ev_qpoll(evq->common, &evq->read_ptr, &sfxge_ev_callbacks, evq);

	evq->rx_done = 0;
	evq->tx_done = 0;

	/* Perform any pending completion processing */
	sfxge_ev_qcomplete(evq, B_TRUE);

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

	mtx_unlock(&evq->lock);

	return (0);

fail:
	mtx_unlock(&(evq->lock));
	return (rc);
}
Exemplo n.º 3
0
int
sfxge_ev_qpoll(struct sfxge_evq *evq)
{
	int rc;

	SFXGE_EVQ_LOCK(evq);

	if (__predict_false(evq->init_state != SFXGE_EVQ_STARTING &&
			    evq->init_state != SFXGE_EVQ_STARTED)) {
		rc = EINVAL;
		goto fail;
	}

	/* Synchronize the DMA memory for reading */
	bus_dmamap_sync(evq->mem.esm_tag, evq->mem.esm_map,
	    BUS_DMASYNC_POSTREAD);

	KASSERT(evq->rx_done == 0, ("evq->rx_done != 0"));
	KASSERT(evq->tx_done == 0, ("evq->tx_done != 0"));
	KASSERT(evq->txq == NULL, ("evq->txq != NULL"));
	KASSERT(evq->txqs == &evq->txq, ("evq->txqs != &evq->txq"));

	/* Poll the queue */
	efx_ev_qpoll(evq->common, &evq->read_ptr, &sfxge_ev_callbacks, evq);

	evq->rx_done = 0;
	evq->tx_done = 0;

	/* Perform any pending completion processing */
	sfxge_ev_qcomplete(evq, B_TRUE);

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

	SFXGE_EVQ_UNLOCK(evq);

	return (0);

fail:
	SFXGE_EVQ_UNLOCK(evq);
	return (rc);
}
Exemplo n.º 4
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);
}
Exemplo n.º 5
0
int
sfc_ev_qprime(struct sfc_evq *evq)
{
	SFC_ASSERT(evq->init_state == SFC_EVQ_STARTED);
	return efx_ev_qprime(evq->common, evq->read_ptr);
}