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); }
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); }
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); }
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); }
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); }
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); }
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); }