Changeset View
Changeset View
Standalone View
Standalone View
head/sys/dev/sfxge/sfxge_ev.c
Show First 20 Lines • Show All 437 Lines • ▼ Show 20 Lines | sfxge_ev_wake_up(void *arg, uint32_t index) | ||||
(void)index; | (void)index; | ||||
return (B_FALSE); | return (B_FALSE); | ||||
} | } | ||||
#if EFSYS_OPT_QSTATS | #if EFSYS_OPT_QSTATS | ||||
static void | static void | ||||
sfxge_evq_stat_update(struct sfxge_evq *evq) | |||||
{ | |||||
clock_t now; | |||||
SFXGE_EVQ_LOCK(evq); | |||||
if (__predict_false(evq->init_state != SFXGE_EVQ_STARTED)) | |||||
goto out; | |||||
now = ticks; | |||||
if ((unsigned int)(now - evq->stats_update_time) < (unsigned int)hz) | |||||
goto out; | |||||
evq->stats_update_time = now; | |||||
efx_ev_qstats_update(evq->common, evq->stats); | |||||
out: | |||||
SFXGE_EVQ_UNLOCK(evq); | |||||
} | |||||
static int | |||||
sfxge_evq_stat_handler(SYSCTL_HANDLER_ARGS) | |||||
{ | |||||
struct sfxge_evq *evq = arg1; | |||||
struct sfxge_softc *sc = evq->sc; | |||||
unsigned int id = arg2; | |||||
SFXGE_ADAPTER_LOCK(sc); | |||||
sfxge_evq_stat_update(evq); | |||||
SFXGE_ADAPTER_UNLOCK(sc); | |||||
return (SYSCTL_OUT(req, &evq->stats[id], sizeof(evq->stats[id]))); | |||||
} | |||||
static int | |||||
sfxge_evq_stat_init(struct sfxge_evq *evq) | |||||
{ | |||||
struct sfxge_softc *sc = evq->sc; | |||||
struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(sc->dev); | |||||
char name[16]; | |||||
struct sysctl_oid *evq_stats_node; | |||||
unsigned int id; | |||||
snprintf(name, sizeof(name), "%u", evq->index); | |||||
evq_stats_node = SYSCTL_ADD_NODE(ctx, | |||||
SYSCTL_CHILDREN(sc->evqs_stats_node), | |||||
OID_AUTO, name, CTLFLAG_RD, NULL, ""); | |||||
if (evq_stats_node == NULL) | |||||
return (ENOMEM); | |||||
for (id = 0; id < EV_NQSTATS; id++) { | |||||
SYSCTL_ADD_PROC( | |||||
ctx, SYSCTL_CHILDREN(evq_stats_node), | |||||
OID_AUTO, efx_ev_qstat_name(sc->enp, id), | |||||
CTLTYPE_U64|CTLFLAG_RD, | |||||
evq, id, sfxge_evq_stat_handler, "Q", | |||||
""); | |||||
} | |||||
return (0); | |||||
} | |||||
static void | |||||
sfxge_ev_stat_update(struct sfxge_softc *sc) | sfxge_ev_stat_update(struct sfxge_softc *sc) | ||||
{ | { | ||||
struct sfxge_evq *evq; | struct sfxge_evq *evq; | ||||
unsigned int index; | unsigned int index; | ||||
clock_t now; | clock_t now; | ||||
unsigned int id; | |||||
SFXGE_ADAPTER_LOCK(sc); | SFXGE_ADAPTER_LOCK(sc); | ||||
if (__predict_false(sc->evq[0]->init_state != SFXGE_EVQ_STARTED)) | |||||
goto out; | |||||
now = ticks; | now = ticks; | ||||
if ((unsigned int)(now - sc->ev_stats_update_time) < (unsigned int)hz) | if ((unsigned int)(now - sc->ev_stats_update_time) < (unsigned int)hz) | ||||
goto out; | goto out; | ||||
sc->ev_stats_update_time = now; | sc->ev_stats_update_time = now; | ||||
/* Add event counts from each event queue in turn */ | memset(sc->ev_stats, 0, sizeof(sc->ev_stats)); | ||||
/* Update and add event counts from each event queue in turn */ | |||||
for (index = 0; index < sc->evq_count; index++) { | for (index = 0; index < sc->evq_count; index++) { | ||||
evq = sc->evq[index]; | evq = sc->evq[index]; | ||||
SFXGE_EVQ_LOCK(evq); | sfxge_evq_stat_update(evq); | ||||
efx_ev_qstats_update(evq->common, sc->ev_stats); | for (id = 0; id < EV_NQSTATS; id++) | ||||
SFXGE_EVQ_UNLOCK(evq); | sc->ev_stats[id] += evq->stats[id]; | ||||
} | } | ||||
out: | out: | ||||
SFXGE_ADAPTER_UNLOCK(sc); | SFXGE_ADAPTER_UNLOCK(sc); | ||||
} | } | ||||
static int | static int | ||||
sfxge_ev_stat_handler(SYSCTL_HANDLER_ARGS) | sfxge_ev_stat_handler(SYSCTL_HANDLER_ARGS) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 190 Lines • ▼ Show 20 Lines | sfxge_ev_qstop(struct sfxge_softc *sc, unsigned int index) | ||||
SFXGE_EVQ_LOCK(evq); | SFXGE_EVQ_LOCK(evq); | ||||
evq->init_state = SFXGE_EVQ_INITIALIZED; | evq->init_state = SFXGE_EVQ_INITIALIZED; | ||||
evq->read_ptr = 0; | evq->read_ptr = 0; | ||||
evq->exception = B_FALSE; | evq->exception = B_FALSE; | ||||
#if EFSYS_OPT_QSTATS | #if EFSYS_OPT_QSTATS | ||||
/* Add event counts before discarding the common evq state */ | /* Add event counts before discarding the common evq state */ | ||||
efx_ev_qstats_update(evq->common, sc->ev_stats); | efx_ev_qstats_update(evq->common, evq->stats); | ||||
#endif | #endif | ||||
efx_ev_qdestroy(evq->common); | efx_ev_qdestroy(evq->common); | ||||
efx_sram_buf_tbl_clear(sc->enp, evq->buf_base_id, | efx_sram_buf_tbl_clear(sc->enp, evq->buf_base_id, | ||||
EFX_EVQ_NBUFS(evq->entries)); | EFX_EVQ_NBUFS(evq->entries)); | ||||
SFXGE_EVQ_UNLOCK(evq); | SFXGE_EVQ_UNLOCK(evq); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 184 Lines • ▼ Show 20 Lines | sfxge_ev_qinit(struct sfxge_softc *sc, unsigned int index) | ||||
/* Allocate buffer table entries. */ | /* Allocate buffer table entries. */ | ||||
sfxge_sram_buf_tbl_alloc(sc, EFX_EVQ_NBUFS(evq->entries), | sfxge_sram_buf_tbl_alloc(sc, EFX_EVQ_NBUFS(evq->entries), | ||||
&evq->buf_base_id); | &evq->buf_base_id); | ||||
SFXGE_EVQ_LOCK_INIT(evq, device_get_nameunit(sc->dev), index); | SFXGE_EVQ_LOCK_INIT(evq, device_get_nameunit(sc->dev), index); | ||||
evq->init_state = SFXGE_EVQ_INITIALIZED; | evq->init_state = SFXGE_EVQ_INITIALIZED; | ||||
#if EFSYS_OPT_QSTATS | |||||
rc = sfxge_evq_stat_init(evq); | |||||
if (rc != 0) | |||||
goto fail_evq_stat_init; | |||||
#endif | |||||
return (0); | return (0); | ||||
#if EFSYS_OPT_QSTATS | |||||
fail_evq_stat_init: | |||||
evq->init_state = SFXGE_EVQ_UNINITIALIZED; | |||||
SFXGE_EVQ_LOCK_DESTROY(evq); | |||||
sfxge_dma_free(esmp); | |||||
sc->evq[index] = NULL; | |||||
free(evq, M_SFXGE); | |||||
return (rc); | |||||
#endif | |||||
} | } | ||||
void | void | ||||
sfxge_ev_fini(struct sfxge_softc *sc) | sfxge_ev_fini(struct sfxge_softc *sc) | ||||
{ | { | ||||
struct sfxge_intr *intr; | struct sfxge_intr *intr; | ||||
int index; | int index; | ||||
Show All 32 Lines | sfxge_ev_init(struct sfxge_softc *sc) | ||||
* read and change it. | * read and change it. | ||||
*/ | */ | ||||
sc->ev_moderation = SFXGE_MODERATION; | sc->ev_moderation = SFXGE_MODERATION; | ||||
SYSCTL_ADD_PROC(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), | SYSCTL_ADD_PROC(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), | ||||
OID_AUTO, "int_mod", CTLTYPE_UINT|CTLFLAG_RW, | OID_AUTO, "int_mod", CTLTYPE_UINT|CTLFLAG_RW, | ||||
sc, 0, sfxge_int_mod_handler, "IU", | sc, 0, sfxge_int_mod_handler, "IU", | ||||
"sfxge interrupt moderation (us)"); | "sfxge interrupt moderation (us)"); | ||||
#if EFSYS_OPT_QSTATS | |||||
sc->evqs_stats_node = SYSCTL_ADD_NODE( | |||||
device_get_sysctl_ctx(sc->dev), SYSCTL_CHILDREN(sc->stats_node), | |||||
OID_AUTO, "evq", CTLFLAG_RD, NULL, "Event queues stats"); | |||||
if (sc->evqs_stats_node == NULL) { | |||||
rc = ENOMEM; | |||||
goto fail_evqs_stats_node; | |||||
} | |||||
#endif | |||||
/* | /* | ||||
* Initialize the event queue(s) - one per interrupt. | * Initialize the event queue(s) - one per interrupt. | ||||
*/ | */ | ||||
for (index = 0; index < sc->evq_count; index++) { | for (index = 0; index < sc->evq_count; index++) { | ||||
if ((rc = sfxge_ev_qinit(sc, index)) != 0) | if ((rc = sfxge_ev_qinit(sc, index)) != 0) | ||||
goto fail; | goto fail; | ||||
} | } | ||||
#if EFSYS_OPT_QSTATS | #if EFSYS_OPT_QSTATS | ||||
sfxge_ev_stat_init(sc); | sfxge_ev_stat_init(sc); | ||||
#endif | #endif | ||||
return (0); | return (0); | ||||
fail: | fail: | ||||
while (--index >= 0) | while (--index >= 0) | ||||
sfxge_ev_qfini(sc, index); | sfxge_ev_qfini(sc, index); | ||||
#if EFSYS_OPT_QSTATS | |||||
fail_evqs_stats_node: | |||||
#endif | |||||
sc->evq_count = 0; | sc->evq_count = 0; | ||||
return (rc); | return (rc); | ||||
} | } |