X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=drivers%2Fnet%2Fsfc%2Fbase%2Fefx_ev.c;h=949d352a25a19b9f11dfd2642dcd5f6c976ec9a6;hb=f07f9bcdb4d6aaaef7469ac4b03d8dd8d43a41db;hp=65094c1d29f6d2059a16ead62f7d3f55222722d4;hpb=e7cd430c864f9bd1ba76026f7b5ffe8fbb020c7a;p=dpdk.git diff --git a/drivers/net/sfc/base/efx_ev.c b/drivers/net/sfc/base/efx_ev.c index 65094c1d29..949d352a25 100644 --- a/drivers/net/sfc/base/efx_ev.c +++ b/drivers/net/sfc/base/efx_ev.c @@ -1,37 +1,24 @@ -/* - * Copyright (c) 2007-2016 Solarflare Communications Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions 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. +/* SPDX-License-Identifier: BSD-3-Clause * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * 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. + * Copyright (c) 2007-2018 Solarflare Communications Inc. + * All rights reserved. */ #include "efx.h" #include "efx_impl.h" +#if EFSYS_OPT_MON_MCDI +#include "mcdi_mon.h" +#endif +#if EFSYS_OPT_QSTATS +#define EFX_EV_QSTAT_INCR(_eep, _stat) \ + do { \ + (_eep)->ee_stat[_stat]++; \ + _NOTE(CONSTANTCONDITION) \ + } while (B_FALSE) +#else #define EFX_EV_QSTAT_INCR(_eep, _stat) +#endif #define EFX_EV_PRESENT(_qword) \ (EFX_QWORD_FIELD((_qword), EFX_DWORD_0) != 0xffffffff && \ @@ -54,7 +41,7 @@ siena_ev_qcreate( __in efx_nic_t *enp, __in unsigned int index, __in efsys_mem_t *esmp, - __in size_t n, + __in size_t ndescs, __in uint32_t id, __in uint32_t us, __in uint32_t flags, @@ -79,6 +66,14 @@ siena_ev_qmoderate( __in efx_evq_t *eep, __in unsigned int us); +#if EFSYS_OPT_QSTATS +static void +siena_ev_qstats_update( + __in efx_evq_t *eep, + __inout_ecount(EV_NQSTATS) efsys_stat_t *stat); + +#endif + #endif /* EFSYS_OPT_SIENA */ #if EFSYS_OPT_SIENA @@ -90,6 +85,9 @@ static const efx_ev_ops_t __efx_ev_siena_ops = { siena_ev_qprime, /* eevo_qprime */ siena_ev_qpost, /* eevo_qpost */ siena_ev_qmoderate, /* eevo_qmoderate */ +#if EFSYS_OPT_QSTATS + siena_ev_qstats_update, /* eevo_qstats_update */ +#endif }; #endif /* EFSYS_OPT_SIENA */ @@ -102,6 +100,9 @@ static const efx_ev_ops_t __efx_ev_ef10_ops = { ef10_ev_qprime, /* eevo_qprime */ ef10_ev_qpost, /* eevo_qpost */ ef10_ev_qmoderate, /* eevo_qmoderate */ +#if EFSYS_OPT_QSTATS + ef10_ev_qstats_update, /* eevo_qstats_update */ +#endif }; #endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD */ @@ -134,6 +135,12 @@ efx_ev_init( break; #endif /* EFSYS_OPT_HUNTINGTON */ +#if EFSYS_OPT_MEDFORD + case EFX_FAMILY_MEDFORD: + eevop = &__efx_ev_ef10_ops; + break; +#endif /* EFSYS_OPT_MEDFORD */ + default: EFSYS_ASSERT(0); rc = ENOTSUP; @@ -185,21 +192,21 @@ efx_ev_qcreate( __in efx_nic_t *enp, __in unsigned int index, __in efsys_mem_t *esmp, - __in size_t n, + __in size_t ndescs, __in uint32_t id, __in uint32_t us, __in uint32_t flags, __deref_out efx_evq_t **eepp) { const efx_ev_ops_t *eevop = enp->en_eevop; - efx_nic_cfg_t *encp = &(enp->en_nic_cfg); efx_evq_t *eep; efx_rc_t rc; EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_EV); - EFSYS_ASSERT3U(enp->en_ev_qcount + 1, <, encp->enc_evq_limit); + EFSYS_ASSERT3U(enp->en_ev_qcount + 1, <, + enp->en_nic_cfg.enc_evq_limit); switch (flags & EFX_EVQ_FLAGS_NOTIFY_MASK) { case EFX_EVQ_FLAGS_NOTIFY_INTERRUPT: @@ -225,7 +232,7 @@ efx_ev_qcreate( eep->ee_magic = EFX_EVQ_MAGIC; eep->ee_enp = enp; eep->ee_index = index; - eep->ee_mask = n - 1; + eep->ee_mask = ndescs - 1; eep->ee_flags = flags; eep->ee_esmp = esmp; @@ -240,7 +247,7 @@ efx_ev_qcreate( enp->en_ev_qcount++; *eepp = eep; - if ((rc = eevop->eevo_qcreate(enp, index, esmp, n, id, us, flags, + if ((rc = eevop->eevo_qcreate(enp, index, esmp, ndescs, id, us, flags, eep)) != 0) goto fail4; @@ -323,6 +330,23 @@ efx_ev_qpending( return (EFX_EV_PRESENT(qword)); } +#if EFSYS_OPT_EV_PREFETCH + + void +efx_ev_qprefetch( + __in efx_evq_t *eep, + __in unsigned int count) +{ + unsigned int offset; + + EFSYS_ASSERT3U(eep->ee_magic, ==, EFX_EVQ_MAGIC); + + offset = (count & eep->ee_mask) * sizeof (efx_qword_t); + EFSYS_MEM_PREFETCH(eep->ee_esmp, offset); +} + +#endif /* EFSYS_OPT_EV_PREFETCH */ + #define EFX_EV_BATCH 8 void @@ -375,11 +399,32 @@ efx_ev_qpoll( offset += sizeof (efx_qword_t); } +#if EFSYS_OPT_EV_PREFETCH && (EFSYS_OPT_EV_PREFETCH_PERIOD > 1) + /* + * Prefetch the next batch when we get within PREFETCH_PERIOD + * of a completed batch. If the batch is smaller, then prefetch + * immediately. + */ + if (total == batch && total < EFSYS_OPT_EV_PREFETCH_PERIOD) + EFSYS_MEM_PREFETCH(eep->ee_esmp, offset); +#endif /* EFSYS_OPT_EV_PREFETCH */ + /* Process the batch of events */ for (index = 0; index < total; ++index) { boolean_t should_abort; uint32_t code; +#if EFSYS_OPT_EV_PREFETCH + /* Prefetch if we've now reached the batch period */ + if (total == batch && + index + EFSYS_OPT_EV_PREFETCH_PERIOD == total) { + offset = (count + batch) & eep->ee_mask; + offset *= sizeof (efx_qword_t); + + EFSYS_MEM_PREFETCH(eep->ee_esmp, offset); + } +#endif /* EFSYS_OPT_EV_PREFETCH */ + EFX_EV_QSTAT_INCR(eep, EV_ALL); code = EFX_QWORD_FIELD(ev[index], FSF_AZ_EV_CODE); @@ -518,6 +563,22 @@ fail1: return (rc); } +#if EFSYS_OPT_QSTATS + void +efx_ev_qstats_update( + __in efx_evq_t *eep, + __inout_ecount(EV_NQSTATS) efsys_stat_t *stat) + +{ efx_nic_t *enp = eep->ee_enp; + const efx_ev_ops_t *eevop = enp->en_eevop; + + EFSYS_ASSERT3U(eep->ee_magic, ==, EFX_EVQ_MAGIC); + + eevop->eevo_qstats_update(eep, stat); +} + +#endif /* EFSYS_OPT_QSTATS */ + #if EFSYS_OPT_SIENA static __checkReturn efx_rc_t @@ -564,6 +625,22 @@ siena_ev_rx_not_ok( EFX_EV_QSTAT_INCR(eep, EV_RX_FRM_TRUNC); (*flagsp) |= EFX_DISCARD; +#if EFSYS_OPT_RX_SCATTER + /* + * Lookout for payload queue ran dry errors and ignore them. + * + * Sadly for the header/data split cases, the descriptor + * pointer in this event refers to the header queue and + * therefore cannot be easily detected as duplicate. + * So we drop these and rely on the receive processing seeing + * a subsequent packet with FSF_AZ_RX_EV_SOP set to discard + * the partially received packet. + */ + if ((EFX_QWORD_FIELD(*eqp, FSF_AZ_RX_EV_SOP) == 0) && + (EFX_QWORD_FIELD(*eqp, FSF_AZ_RX_EV_JUMBO_CONT) == 0) && + (EFX_QWORD_FIELD(*eqp, FSF_AZ_RX_EV_BYTE_CNT) == 0)) + ignore = B_TRUE; +#endif /* EFSYS_OPT_RX_SCATTER */ } if (EFX_QWORD_FIELD(*eqp, FSF_AZ_RX_EV_ETH_CRC_ERR) != 0) { @@ -623,6 +700,10 @@ siena_ev_rx( uint32_t size; uint32_t label; boolean_t ok; +#if EFSYS_OPT_RX_SCATTER + boolean_t sop; + boolean_t jumbo_cont; +#endif /* EFSYS_OPT_RX_SCATTER */ uint32_t hdr_type; boolean_t is_v6; uint16_t flags; @@ -637,6 +718,11 @@ siena_ev_rx( label = EFX_QWORD_FIELD(*eqp, FSF_AZ_RX_EV_Q_LABEL); ok = (EFX_QWORD_FIELD(*eqp, FSF_AZ_RX_EV_PKT_OK) != 0); +#if EFSYS_OPT_RX_SCATTER + sop = (EFX_QWORD_FIELD(*eqp, FSF_AZ_RX_EV_SOP) != 0); + jumbo_cont = (EFX_QWORD_FIELD(*eqp, FSF_AZ_RX_EV_JUMBO_CONT) != 0); +#endif /* EFSYS_OPT_RX_SCATTER */ + hdr_type = EFX_QWORD_FIELD(*eqp, FSF_AZ_RX_EV_HDR_TYPE); is_v6 = (EFX_QWORD_FIELD(*eqp, FSF_CZ_RX_EV_IPV6_PKT) != 0); @@ -689,6 +775,14 @@ siena_ev_rx( break; } +#if EFSYS_OPT_RX_SCATTER + /* Report scatter and header/lookahead split buffer flags */ + if (sop) + flags |= EFX_PKT_START; + if (jumbo_cont) + flags |= EFX_PKT_CONT; +#endif /* EFSYS_OPT_RX_SCATTER */ + /* Detect errors included in the FSF_AZ_RX_EV_PKT_OK indication */ if (!ok) { ignore = siena_ev_rx_not_ok(eep, eqp, label, id, &flags); @@ -985,6 +1079,9 @@ siena_ev_mcdi( EFSYS_ASSERT(eecp->eec_link_change != NULL); EFSYS_ASSERT(eecp->eec_exception != NULL); +#if EFSYS_OPT_MON_STATS + EFSYS_ASSERT(eecp->eec_monitor != NULL); +#endif EFX_EV_QSTAT_INCR(eep, EV_MCDI_RESPONSE); @@ -1009,7 +1106,22 @@ siena_ev_mcdi( break; } case MCDI_EVENT_CODE_SENSOREVT: { +#if EFSYS_OPT_MON_STATS + efx_mon_stat_t id; + efx_mon_stat_value_t value; + efx_rc_t rc; + + if ((rc = mcdi_mon_ev(enp, eqp, &id, &value)) == 0) + should_abort = eecp->eec_monitor(arg, id, value); + else if (rc == ENOTSUP) { + should_abort = eecp->eec_exception(arg, + EFX_EXCEPTION_UNKNOWN_SENSOREVT, + MCDI_EV_FIELD(eqp, DATA)); + } else + EFSYS_ASSERT(rc == ENODEV); /* Wrong port */ +#else should_abort = B_FALSE; +#endif break; } case MCDI_EVENT_CODE_SCHEDERR: @@ -1021,6 +1133,12 @@ siena_ev_mcdi( break; case MCDI_EVENT_CODE_MAC_STATS_DMA: +#if EFSYS_OPT_MAC_STATS + if (eecp->eec_mac_stats != NULL) { + eecp->eec_mac_stats(arg, + MCDI_EV_FIELD(eqp, MAC_STATS_DMA_GENERATION)); + } +#endif break; case MCDI_EVENT_CODE_FWALERT: { @@ -1139,7 +1257,7 @@ siena_ev_qcreate( __in efx_nic_t *enp, __in unsigned int index, __in efsys_mem_t *esmp, - __in size_t n, + __in size_t ndescs, __in uint32_t id, __in uint32_t us, __in uint32_t flags, @@ -1156,7 +1274,8 @@ siena_ev_qcreate( EFX_STATIC_ASSERT(ISP2(EFX_EVQ_MAXNEVS)); EFX_STATIC_ASSERT(ISP2(EFX_EVQ_MINNEVS)); - if (!ISP2(n) || (n < EFX_EVQ_MINNEVS) || (n > EFX_EVQ_MAXNEVS)) { + if (!ISP2(ndescs) || + (ndescs < EFX_EVQ_MINNEVS) || (ndescs > EFX_EVQ_MAXNEVS)) { rc = EINVAL; goto fail1; } @@ -1164,9 +1283,16 @@ siena_ev_qcreate( rc = EINVAL; goto fail2; } +#if EFSYS_OPT_RX_SCALE + if (enp->en_intr.ei_type == EFX_INTR_LINE && + index >= EFX_MAXRSS_LEGACY) { + rc = EINVAL; + goto fail3; + } +#endif for (size = 0; (1 << size) <= (EFX_EVQ_MAXNEVS / EFX_EVQ_MINNEVS); size++) - if ((1 << size) == (int)(n / EFX_EVQ_MINNEVS)) + if ((1 << size) == (int)(ndescs / EFX_EVQ_MINNEVS)) break; if (id + (1 << size) >= encp->enc_buftbl_limit) { rc = EINVAL; @@ -1204,6 +1330,10 @@ siena_ev_qcreate( fail4: EFSYS_PROBE(fail4); +#if EFSYS_OPT_RX_SCALE +fail3: + EFSYS_PROBE(fail3); +#endif fail2: EFSYS_PROBE(fail2); fail1: @@ -1214,8 +1344,84 @@ fail1: #endif /* EFSYS_OPT_SIENA */ +#if EFSYS_OPT_QSTATS +#if EFSYS_OPT_NAMES +/* START MKCONFIG GENERATED EfxEventQueueStatNamesBlock c0f3bc5083b40532 */ +static const char * const __efx_ev_qstat_name[] = { + "all", + "rx", + "rx_ok", + "rx_frm_trunc", + "rx_tobe_disc", + "rx_pause_frm_err", + "rx_buf_owner_id_err", + "rx_ipv4_hdr_chksum_err", + "rx_tcp_udp_chksum_err", + "rx_eth_crc_err", + "rx_ip_frag_err", + "rx_mcast_pkt", + "rx_mcast_hash_match", + "rx_tcp_ipv4", + "rx_tcp_ipv6", + "rx_udp_ipv4", + "rx_udp_ipv6", + "rx_other_ipv4", + "rx_other_ipv6", + "rx_non_ip", + "rx_batch", + "tx", + "tx_wq_ff_full", + "tx_pkt_err", + "tx_pkt_too_big", + "tx_unexpected", + "global", + "global_mnt", + "driver", + "driver_srm_upd_done", + "driver_tx_descq_fls_done", + "driver_rx_descq_fls_done", + "driver_rx_descq_fls_failed", + "driver_rx_dsc_error", + "driver_tx_dsc_error", + "drv_gen", + "mcdi_response", +}; +/* END MKCONFIG GENERATED EfxEventQueueStatNamesBlock */ + + const char * +efx_ev_qstat_name( + __in efx_nic_t *enp, + __in unsigned int id) +{ + _NOTE(ARGUNUSED(enp)) + + EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); + EFSYS_ASSERT3U(id, <, EV_NQSTATS); + + return (__efx_ev_qstat_name[id]); +} +#endif /* EFSYS_OPT_NAMES */ +#endif /* EFSYS_OPT_QSTATS */ + #if EFSYS_OPT_SIENA +#if EFSYS_OPT_QSTATS +static void +siena_ev_qstats_update( + __in efx_evq_t *eep, + __inout_ecount(EV_NQSTATS) efsys_stat_t *stat) +{ + unsigned int id; + + for (id = 0; id < EV_NQSTATS; id++) { + efsys_stat_t *essp = &stat[id]; + + EFSYS_STAT_INCR(essp, eep->ee_stat[id]); + eep->ee_stat[id] = 0; + } +} +#endif /* EFSYS_OPT_QSTATS */ + static void siena_ev_qdestroy( __in efx_evq_t *eep)