Changeset View
Changeset View
Standalone View
Standalone View
head/sys/dev/sfxge/sfxge_ev.c
Property | Old Value | New Value |
---|---|---|
svn:eol-style | null | native \ No newline at end of property |
svn:mime-type | null | text/plain \ No newline at end of property |
/*- | /*- | ||||
* Copyright (c) 2010-2011 Solarflare Communications, Inc. | * Copyright (c) 2010-2015 Solarflare Communications Inc. | ||||
* All rights reserved. | * All rights reserved. | ||||
* | * | ||||
* This software was developed in part by Philip Paeps under contract for | * This software was developed in part by Philip Paeps under contract for | ||||
* Solarflare Communications, Inc. | * Solarflare Communications, Inc. | ||||
* | * | ||||
* Redistribution and use in source and binary forms, with or without | * Redistribution and use in source and binary forms, with or without | ||||
* modification, are permitted provided that the following conditions | * modification, are permitted provided that the following conditions are met: | ||||
* are met: | |||||
* 1. Redistributions of source code must retain the above copyright | |||||
* notice, this list of conditions and the following disclaimer. | |||||
* 2. Redistributions in binary form must reproduce the above copyright | |||||
* notice, this list of conditions and the following disclaimer in the | |||||
* documentation and/or other materials provided with the distribution. | |||||
* | * | ||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND | * 1. Redistributions of source code must retain the above copyright notice, | ||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | * this list of conditions and the following disclaimer. | ||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | * 2. Redistributions in binary form must reproduce the above copyright notice, | ||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE | * this list of conditions and the following disclaimer in the documentation | ||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | * and/or other materials provided with the distribution. | ||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | * | ||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, | ||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | ||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR | ||||
* SUCH DAMAGE. | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | ||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | |||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; | |||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, | |||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | |||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, | |||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |||||
* | |||||
* The views and conclusions contained in the software and documentation are | |||||
* those of the authors and should not be interpreted as representing official | |||||
* policies, either expressed or implied, of the FreeBSD Project. | |||||
*/ | */ | ||||
#include <sys/cdefs.h> | #include <sys/cdefs.h> | ||||
__FBSDID("$FreeBSD$"); | __FBSDID("$FreeBSD$"); | ||||
#include <sys/param.h> | #include <sys/param.h> | ||||
#include <sys/kernel.h> | #include <sys/kernel.h> | ||||
#include <sys/malloc.h> | #include <sys/malloc.h> | ||||
▲ Show 20 Lines • Show All 41 Lines • ▼ Show 20 Lines | sfxge_ev_qcomplete(struct sfxge_evq *evq, boolean_t eop) | ||||
} | } | ||||
if (rxq->pending != rxq->completed) | if (rxq->pending != rxq->completed) | ||||
sfxge_rx_qcomplete(rxq, eop); | sfxge_rx_qcomplete(rxq, eop); | ||||
} | } | ||||
static boolean_t | static boolean_t | ||||
sfxge_ev_rx(void *arg, uint32_t label, uint32_t id, uint32_t size, | sfxge_ev_rx(void *arg, uint32_t label, uint32_t id, uint32_t size, | ||||
uint16_t flags) | uint16_t flags) | ||||
{ | { | ||||
struct sfxge_evq *evq; | struct sfxge_evq *evq; | ||||
struct sfxge_softc *sc; | struct sfxge_softc *sc; | ||||
struct sfxge_rxq *rxq; | struct sfxge_rxq *rxq; | ||||
unsigned int expected; | unsigned int stop; | ||||
unsigned int delta; | |||||
struct sfxge_rx_sw_desc *rx_desc; | struct sfxge_rx_sw_desc *rx_desc; | ||||
evq = arg; | evq = arg; | ||||
SFXGE_EVQ_LOCK_ASSERT_OWNED(evq); | SFXGE_EVQ_LOCK_ASSERT_OWNED(evq); | ||||
sc = evq->sc; | sc = evq->sc; | ||||
if (evq->exception) | if (evq->exception) | ||||
goto done; | goto done; | ||||
rxq = sc->rxq[label]; | rxq = sc->rxq[label]; | ||||
KASSERT(rxq != NULL, ("rxq == NULL")); | KASSERT(rxq != NULL, ("rxq == NULL")); | ||||
KASSERT(evq->index == rxq->index, | KASSERT(evq->index == rxq->index, | ||||
("evq->index != rxq->index")); | ("evq->index != rxq->index")); | ||||
if (__predict_false(rxq->init_state != SFXGE_RXQ_STARTED)) | if (__predict_false(rxq->init_state != SFXGE_RXQ_STARTED)) | ||||
goto done; | goto done; | ||||
expected = rxq->pending++ & rxq->ptr_mask; | stop = (id + 1) & rxq->ptr_mask; | ||||
if (id != expected) { | 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; | evq->exception = B_TRUE; | ||||
device_printf(sc->dev, "RX completion out of order" | device_printf(sc->dev, "RX completion out of order" | ||||
" (id=%#x expected=%#x flags=%#x); resetting\n", | " (id=%#x delta=%u flags=%#x); resetting\n", | ||||
id, expected, flags); | id, delta, flags); | ||||
sfxge_schedule_reset(sc); | sfxge_schedule_reset(sc); | ||||
goto done; | goto done; | ||||
} | } | ||||
} | |||||
rx_desc = &rxq->queue[id]; | 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, | KASSERT(rx_desc->flags == EFX_DISCARD, | ||||
("rx_desc->flags != EFX_DISCARD")); | ("rx_desc->flags != EFX_DISCARD")); | ||||
rx_desc->flags = flags; | rx_desc->flags = flags; | ||||
KASSERT(size < (1 << 16), ("size > (1 << 16)")); | KASSERT(size < (1 << 16), ("size > (1 << 16)")); | ||||
rx_desc->size = (uint16_t)size; | rx_desc->size = (uint16_t)size; | ||||
prefetch_read_many(rx_desc->mbuf); | } | ||||
evq->rx_done++; | evq->rx_done++; | ||||
if (rxq->pending - rxq->completed >= SFXGE_RX_BATCH) | if (rxq->pending - rxq->completed >= SFXGE_RX_BATCH) | ||||
sfxge_ev_qcomplete(evq, B_FALSE); | sfxge_ev_qcomplete(evq, B_FALSE); | ||||
done: | done: | ||||
return (evq->rx_done >= SFXGE_EV_BATCH); | return (evq->rx_done >= SFXGE_EV_BATCH); | ||||
} | } | ||||
static boolean_t | static boolean_t | ||||
sfxge_ev_exception(void *arg, uint32_t code, uint32_t data) | sfxge_ev_exception(void *arg, uint32_t code, uint32_t data) | ||||
{ | { | ||||
struct sfxge_evq *evq; | struct sfxge_evq *evq; | ||||
struct sfxge_softc *sc; | struct sfxge_softc *sc; | ||||
evq = (struct sfxge_evq *)arg; | evq = (struct sfxge_evq *)arg; | ||||
SFXGE_EVQ_LOCK_ASSERT_OWNED(evq); | SFXGE_EVQ_LOCK_ASSERT_OWNED(evq); | ||||
sc = evq->sc; | 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; | evq->exception = B_TRUE; | ||||
if (code != EFX_EXCEPTION_UNKNOWN_SENSOREVT) { | if (code != EFX_EXCEPTION_UNKNOWN_SENSOREVT) { | ||||
device_printf(sc->dev, | device_printf(sc->dev, | ||||
"hardware exception (code=%u); resetting\n", | "hardware exception (code=%u); resetting\n", | ||||
code); | code); | ||||
sfxge_schedule_reset(sc); | sfxge_schedule_reset(sc); | ||||
} | } | ||||
Show All 16 Lines | sfxge_ev_rxq_flush_done(void *arg, uint32_t rxq_index) | ||||
sc = evq->sc; | sc = evq->sc; | ||||
rxq = sc->rxq[rxq_index]; | rxq = sc->rxq[rxq_index]; | ||||
KASSERT(rxq != NULL, ("rxq == NULL")); | KASSERT(rxq != NULL, ("rxq == NULL")); | ||||
/* Resend a software event on the correct queue */ | /* Resend a software event on the correct queue */ | ||||
index = rxq->index; | index = rxq->index; | ||||
if (index == evq->index) { | |||||
sfxge_rx_qflush_done(rxq); | |||||
return (B_FALSE); | |||||
} | |||||
evq = sc->evq[index]; | evq = sc->evq[index]; | ||||
label = rxq_index; | label = rxq_index; | ||||
KASSERT((label & SFXGE_MAGIC_DMAQ_LABEL_MASK) == label, | KASSERT((label & SFXGE_MAGIC_DMAQ_LABEL_MASK) == label, | ||||
("(label & SFXGE_MAGIC_DMAQ_LABEL_MASK) != level")); | ("(label & SFXGE_MAGIC_DMAQ_LABEL_MASK) != level")); | ||||
magic = SFXGE_MAGIC_RX_QFLUSH_DONE | label; | magic = SFXGE_MAGIC_RX_QFLUSH_DONE | label; | ||||
KASSERT(evq->init_state == SFXGE_EVQ_STARTED, | KASSERT(evq->init_state == SFXGE_EVQ_STARTED, | ||||
▲ Show 20 Lines • Show All 103 Lines • ▼ Show 20 Lines | sfxge_ev_txq_flush_done(void *arg, uint32_t txq_index) | ||||
sc = evq->sc; | sc = evq->sc; | ||||
txq = sc->txq[txq_index]; | txq = sc->txq[txq_index]; | ||||
KASSERT(txq != NULL, ("txq == NULL")); | KASSERT(txq != NULL, ("txq == NULL")); | ||||
KASSERT(txq->init_state == SFXGE_TXQ_INITIALIZED, | KASSERT(txq->init_state == SFXGE_TXQ_INITIALIZED, | ||||
("txq not initialized")); | ("txq not initialized")); | ||||
if (txq->evq_index == evq->index) { | |||||
sfxge_tx_qflush_done(txq); | |||||
return (B_FALSE); | |||||
} | |||||
/* Resend a software event on the correct queue */ | /* Resend a software event on the correct queue */ | ||||
evq = sc->evq[txq->evq_index]; | evq = sc->evq[txq->evq_index]; | ||||
label = txq->type; | label = txq->type; | ||||
KASSERT((label & SFXGE_MAGIC_DMAQ_LABEL_MASK) == label, | KASSERT((label & SFXGE_MAGIC_DMAQ_LABEL_MASK) == label, | ||||
("(label & SFXGE_MAGIC_DMAQ_LABEL_MASK) != label")); | ("(label & SFXGE_MAGIC_DMAQ_LABEL_MASK) != label")); | ||||
magic = SFXGE_MAGIC_TX_QFLUSH_DONE | label; | magic = SFXGE_MAGIC_TX_QFLUSH_DONE | label; | ||||
▲ Show 20 Lines • Show All 236 Lines • ▼ Show 20 Lines | |||||
static boolean_t | static boolean_t | ||||
sfxge_ev_initialized(void *arg) | sfxge_ev_initialized(void *arg) | ||||
{ | { | ||||
struct sfxge_evq *evq; | struct sfxge_evq *evq; | ||||
evq = (struct sfxge_evq *)arg; | evq = (struct sfxge_evq *)arg; | ||||
SFXGE_EVQ_LOCK_ASSERT_OWNED(evq); | SFXGE_EVQ_LOCK_ASSERT_OWNED(evq); | ||||
KASSERT(evq->init_state == SFXGE_EVQ_STARTING, | /* Init done events may be duplicated on 7xxx */ | ||||
KASSERT(evq->init_state == SFXGE_EVQ_STARTING || | |||||
evq->init_state == SFXGE_EVQ_STARTED, | |||||
("evq not starting")); | ("evq not starting")); | ||||
evq->init_state = SFXGE_EVQ_STARTED; | evq->init_state = SFXGE_EVQ_STARTED; | ||||
return (0); | return (0); | ||||
} | } | ||||
static boolean_t | static boolean_t | ||||
▲ Show 20 Lines • Show All 365 Lines • Show Last 20 Lines |