Example #1
0
static boolean_t
sfxge_ev_exception(void *arg, uint32_t code, uint32_t data)
{
	struct sfxge_evq *evq;
	struct sfxge_softc *sc;

	evq = (struct sfxge_evq *)arg;
	SFXGE_EVQ_LOCK_ASSERT_OWNED(evq);

	sc = evq->sc;

	DBGPRINT(sc->dev, "[%d] %s", evq->index,
			  (code == EFX_EXCEPTION_RX_RECOVERY) ? "RX_RECOVERY" :
			  (code == EFX_EXCEPTION_RX_DSC_ERROR) ? "RX_DSC_ERROR" :
			  (code == EFX_EXCEPTION_TX_DSC_ERROR) ? "TX_DSC_ERROR" :
			  (code == EFX_EXCEPTION_UNKNOWN_SENSOREVT) ? "UNKNOWN_SENSOREVT" :
			  (code == EFX_EXCEPTION_FWALERT_SRAM) ? "FWALERT_SRAM" :
			  (code == EFX_EXCEPTION_UNKNOWN_FWALERT) ? "UNKNOWN_FWALERT" :
			  (code == EFX_EXCEPTION_RX_ERROR) ? "RX_ERROR" :
			  (code == EFX_EXCEPTION_TX_ERROR) ? "TX_ERROR" :
			  (code == EFX_EXCEPTION_EV_ERROR) ? "EV_ERROR" :
			  "UNKNOWN");

	evq->exception = B_TRUE;

	if (code != EFX_EXCEPTION_UNKNOWN_SENSOREVT) {
		device_printf(sc->dev,
			      "hardware exception (code=%u); resetting\n",
			      code);
		sfxge_schedule_reset(sc);
	}

	return (B_FALSE);
}
Example #2
0
static void
sfxge_mcdi_timeout(struct sfxge_softc *sc)
{
	device_t dev = sc->dev;

	log(LOG_WARNING, "[%s%d] MC_TIMEOUT", device_get_name(dev),
		device_get_unit(dev));

	EFSYS_PROBE(mcdi_timeout);
	sfxge_schedule_reset(sc);
}
Example #3
0
static boolean_t
sfxge_ev_rx(void *arg, uint32_t label, uint32_t id, uint32_t size,
    uint16_t flags)
{
	struct sfxge_evq *evq;
	struct sfxge_softc *sc;
	struct sfxge_rxq *rxq;
	unsigned int expected;
	struct sfxge_rx_sw_desc *rx_desc;

	evq = arg;
	sc = evq->sc;

	if (evq->exception)
		goto done;

	rxq = sc->rxq[label];
	KASSERT(rxq != NULL, ("rxq == NULL"));
	KASSERT(evq->index == rxq->index,
	    ("evq->index != rxq->index"));

	if (rxq->init_state != SFXGE_RXQ_STARTED)
		goto done;

	expected = rxq->pending++ & (SFXGE_NDESCS - 1);
	if (id != expected) {
		evq->exception = B_TRUE;

		device_printf(sc->dev, "RX completion out of order"
			      " (id=%#x expected=%#x flags=%#x); resetting\n",
			      id, expected, flags);
		sfxge_schedule_reset(sc);

		goto done;
	}

	rx_desc = &rxq->queue[id];

	KASSERT(rx_desc->flags == EFX_DISCARD,
	    ("rx_desc->flags != EFX_DISCARD"));
	rx_desc->flags = flags;

	KASSERT(size < (1 << 16), ("size > (1 << 16)"));
	rx_desc->size = (uint16_t)size;
	prefetch_read_many(rx_desc->mbuf);

	evq->rx_done++;

	if (rxq->pending - rxq->completed >= SFXGE_RX_BATCH)
		sfxge_ev_qcomplete(evq, B_FALSE);

done:
	return (evq->rx_done >= SFXGE_EV_BATCH);
}
Example #4
0
static void
sfxge_mcdi_exception(void *arg, efx_mcdi_exception_t eme)
{
	struct sfxge_softc *sc;
	device_t dev;

	sc = (struct sfxge_softc *)arg;
	dev = sc->dev;

	log(LOG_WARNING, "[%s%d] MC_%s", device_get_name(dev),
	    device_get_unit(dev),
	    (eme == EFX_MCDI_EXCEPTION_MC_REBOOT)
	    ? "REBOOT"
	    : (eme == EFX_MCDI_EXCEPTION_MC_BADASSERT)
	    ? "BADASSERT" : "UNKNOWN");

	EFSYS_PROBE(mcdi_exception);

	sfxge_schedule_reset(sc);
}
Example #5
0
static boolean_t
sfxge_ev_exception(void *arg, uint32_t code, uint32_t data)
{
	struct sfxge_evq *evq;
	struct sfxge_softc *sc;

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

	evq->exception = B_TRUE;

	if (code != EFX_EXCEPTION_UNKNOWN_SENSOREVT) {
		device_printf(sc->dev,
			      "hardware exception (code=%u); resetting\n",
			      code);
		sfxge_schedule_reset(sc);
	}

	return (B_FALSE);
}
Example #6
0
static boolean_t
sfxge_ev_rx(void *arg, uint32_t label, uint32_t id, uint32_t size,
	    uint16_t flags)
{
	struct sfxge_evq *evq;
	struct sfxge_softc *sc;
	struct sfxge_rxq *rxq;
	unsigned int stop;
	unsigned int delta;
	struct sfxge_rx_sw_desc *rx_desc;

	evq = arg;
	SFXGE_EVQ_LOCK_ASSERT_OWNED(evq);

	sc = evq->sc;

	if (evq->exception)
		goto done;

	rxq = sc->rxq[label];
	KASSERT(rxq != NULL, ("rxq == NULL"));
	KASSERT(evq->index == rxq->index,
	    ("evq->index != rxq->index"));

	if (__predict_false(rxq->init_state != SFXGE_RXQ_STARTED))
		goto done;

	stop = (id + 1) & rxq->ptr_mask;
	id = rxq->pending & rxq->ptr_mask;
	delta = (stop >= id) ? (stop - id) : (rxq->entries - id + stop);
	rxq->pending += delta;

	if (delta != 1) {
		if ((!efx_nic_cfg_get(sc->enp)->enc_rx_batching_enabled) ||
		    (delta <= 0) ||
		    (delta > efx_nic_cfg_get(sc->enp)->enc_rx_batch_max)) {
			evq->exception = B_TRUE;

			device_printf(sc->dev, "RX completion out of order"
						  " (id=%#x delta=%u flags=%#x); resetting\n",
						  id, delta, flags);
			sfxge_schedule_reset(sc);

			goto done;
		}
	}

	rx_desc = &rxq->queue[id];

	prefetch_read_many(rx_desc->mbuf);

	for (; id != stop; id = (id + 1) & rxq->ptr_mask) {
		rx_desc = &rxq->queue[id];
		KASSERT(rx_desc->flags == EFX_DISCARD,
				("rx_desc->flags != EFX_DISCARD"));
		rx_desc->flags = flags;

		KASSERT(size < (1 << 16), ("size > (1 << 16)"));
		rx_desc->size = (uint16_t)size;
	}

	evq->rx_done++;

	if (rxq->pending - rxq->completed >= SFXGE_RX_BATCH)
		sfxge_ev_qcomplete(evq, B_FALSE);

done:
	return (evq->rx_done >= SFXGE_EV_BATCH);
}
Example #7
0
int
sfxge_mcdi_ioctl(struct sfxge_softc *sc, sfxge_ioc_t *ip)
{
	const efx_nic_cfg_t *encp = efx_nic_cfg_get(sc->enp);
	struct sfxge_mcdi *mp = &(sc->mcdi);
	efx_mcdi_req_t emr;
	uint8_t *mcdibuf;
	int rc;

	if (mp->state == SFXGE_MCDI_UNINITIALIZED) {
		rc = ENODEV;
		goto fail1;
	}

	if (!(encp->enc_features & EFX_FEATURE_MCDI)) {
		rc = ENOTSUP;
		goto fail2;
	}

	if (ip->u.mcdi.len > SFXGE_MCDI_MAX_PAYLOAD) {
		rc = EINVAL;
		goto fail3;
	}

	mcdibuf = malloc(SFXGE_MCDI_MAX_PAYLOAD, M_TEMP, M_WAITOK | M_ZERO);
	if ((rc = copyin(ip->u.mcdi.payload, mcdibuf, ip->u.mcdi.len)) != 0) {
		goto fail5;
	}

	emr.emr_cmd = ip->u.mcdi.cmd;
	emr.emr_in_buf = mcdibuf;
	emr.emr_in_length = ip->u.mcdi.len;

	emr.emr_out_buf = mcdibuf;
	emr.emr_out_length = SFXGE_MCDI_MAX_PAYLOAD;

	sfxge_mcdi_execute(sc, &emr);

	ip->u.mcdi.rc = emr.emr_rc;
	ip->u.mcdi.cmd = emr.emr_cmd;
	ip->u.mcdi.len = emr.emr_out_length_used;
	if ((rc = copyout(mcdibuf, ip->u.mcdi.payload, ip->u.mcdi.len)) != 0) {
		goto fail6;
	}

	/*
	 * Helpfully trigger a device reset in response to an MCDI_CMD_REBOOT
	 * Both ports will see ->emt_exception callbacks on the next MCDI poll
	 */
	if (ip->u.mcdi.cmd == MC_CMD_REBOOT) {

		EFSYS_PROBE(mcdi_ioctl_mc_reboot);
		/* sfxge_t->s_state_lock held */
		(void) sfxge_schedule_reset(sc);
	}

	free(mcdibuf, M_TEMP);

	return (0);

fail6:
fail5:
	free(mcdibuf, M_TEMP);
fail3:
fail2:
fail1:
	return (rc);
}