X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=drivers%2Fnet%2Fsfc%2Fbase%2Fefx_rx.c;h=26999a92fb92f232504ad845706432dafd8d7362;hb=d622cad892a1fc715635d137d1598053fd0b8e3a;hp=d0dd605785448123386c61ee18f637e9d1bde917;hpb=b749646dade4844bce3c0e071271605ee878d246;p=dpdk.git diff --git a/drivers/net/sfc/base/efx_rx.c b/drivers/net/sfc/base/efx_rx.c index d0dd605785..26999a92fb 100644 --- a/drivers/net/sfc/base/efx_rx.c +++ b/drivers/net/sfc/base/efx_rx.c @@ -1,31 +1,7 @@ -/* - * 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: +/* SPDX-License-Identifier: BSD-3-Clause * - * 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 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" @@ -131,7 +107,7 @@ siena_rx_qcreate( __in unsigned int index, __in unsigned int label, __in efx_rxq_type_t type, - __in uint32_t type_data, + __in_opt const efx_rxq_type_data_t *type_data, __in efsys_mem_t *esmp, __in size_t ndescs, __in uint32_t id, @@ -175,7 +151,7 @@ static const efx_rx_ops_t __efx_rx_siena_ops = { }; #endif /* EFSYS_OPT_SIENA */ -#if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD +#if EFX_OPTS_EF10() static const efx_rx_ops_t __efx_rx_ef10_ops = { ef10_rx_init, /* erxo_init */ ef10_rx_fini, /* erxo_fini */ @@ -202,7 +178,7 @@ static const efx_rx_ops_t __efx_rx_ef10_ops = { ef10_rx_qcreate, /* erxo_qcreate */ ef10_rx_qdestroy, /* erxo_qdestroy */ }; -#endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD */ +#endif /* EFX_OPTS_EF10() */ __checkReturn efx_rc_t @@ -244,6 +220,12 @@ efx_rx_init( break; #endif /* EFSYS_OPT_MEDFORD */ +#if EFSYS_OPT_MEDFORD2 + case EFX_FAMILY_MEDFORD2: + erxop = &__efx_rx_ef10_ops; + break; +#endif /* EFSYS_OPT_MEDFORD2 */ + default: EFSYS_ASSERT(0); rc = ENOTSUP; @@ -312,6 +294,114 @@ fail1: #endif /* EFSYS_OPT_RX_SCATTER */ #if EFSYS_OPT_RX_SCALE + __checkReturn efx_rc_t +efx_rx_scale_hash_flags_get( + __in efx_nic_t *enp, + __in efx_rx_hash_alg_t hash_alg, + __out_ecount_part(max_nflags, *nflagsp) unsigned int *flagsp, + __in unsigned int max_nflags, + __out unsigned int *nflagsp) +{ + efx_nic_cfg_t *encp = &enp->en_nic_cfg; + unsigned int nflags = 0; + efx_rc_t rc; + + if (flagsp == NULL || nflagsp == NULL) { + rc = EINVAL; + goto fail1; + } + + if ((encp->enc_rx_scale_hash_alg_mask & (1U << hash_alg)) == 0) { + nflags = 0; + goto done; + } + + /* Helper to add flags word to flags array without buffer overflow */ +#define INSERT_FLAGS(_flags) \ + do { \ + if (nflags >= max_nflags) { \ + rc = E2BIG; \ + goto fail2; \ + } \ + *(flagsp + nflags) = (_flags); \ + nflags++; \ + \ + _NOTE(CONSTANTCONDITION) \ + } while (B_FALSE) + + if (encp->enc_rx_scale_l4_hash_supported != B_FALSE) { + INSERT_FLAGS(EFX_RX_HASH(IPV4_TCP, 4TUPLE)); + INSERT_FLAGS(EFX_RX_HASH(IPV6_TCP, 4TUPLE)); + } + + if ((encp->enc_rx_scale_l4_hash_supported != B_FALSE) && + (encp->enc_rx_scale_additional_modes_supported != B_FALSE)) { + INSERT_FLAGS(EFX_RX_HASH(IPV4_TCP, 2TUPLE_DST)); + INSERT_FLAGS(EFX_RX_HASH(IPV4_TCP, 2TUPLE_SRC)); + + INSERT_FLAGS(EFX_RX_HASH(IPV6_TCP, 2TUPLE_DST)); + INSERT_FLAGS(EFX_RX_HASH(IPV6_TCP, 2TUPLE_SRC)); + + INSERT_FLAGS(EFX_RX_HASH(IPV4_UDP, 4TUPLE)); + INSERT_FLAGS(EFX_RX_HASH(IPV4_UDP, 2TUPLE_DST)); + INSERT_FLAGS(EFX_RX_HASH(IPV4_UDP, 2TUPLE_SRC)); + + INSERT_FLAGS(EFX_RX_HASH(IPV6_UDP, 4TUPLE)); + INSERT_FLAGS(EFX_RX_HASH(IPV6_UDP, 2TUPLE_DST)); + INSERT_FLAGS(EFX_RX_HASH(IPV6_UDP, 2TUPLE_SRC)); + } + + INSERT_FLAGS(EFX_RX_HASH(IPV4_TCP, 2TUPLE)); + INSERT_FLAGS(EFX_RX_HASH(IPV6_TCP, 2TUPLE)); + + INSERT_FLAGS(EFX_RX_HASH(IPV4, 2TUPLE)); + INSERT_FLAGS(EFX_RX_HASH(IPV6, 2TUPLE)); + + if (encp->enc_rx_scale_additional_modes_supported != B_FALSE) { + INSERT_FLAGS(EFX_RX_HASH(IPV4_TCP, 1TUPLE_DST)); + INSERT_FLAGS(EFX_RX_HASH(IPV4_TCP, 1TUPLE_SRC)); + + INSERT_FLAGS(EFX_RX_HASH(IPV6_TCP, 1TUPLE_DST)); + INSERT_FLAGS(EFX_RX_HASH(IPV6_TCP, 1TUPLE_SRC)); + + INSERT_FLAGS(EFX_RX_HASH(IPV4_UDP, 2TUPLE)); + INSERT_FLAGS(EFX_RX_HASH(IPV4_UDP, 1TUPLE_DST)); + INSERT_FLAGS(EFX_RX_HASH(IPV4_UDP, 1TUPLE_SRC)); + + INSERT_FLAGS(EFX_RX_HASH(IPV6_UDP, 2TUPLE)); + INSERT_FLAGS(EFX_RX_HASH(IPV6_UDP, 1TUPLE_DST)); + INSERT_FLAGS(EFX_RX_HASH(IPV6_UDP, 1TUPLE_SRC)); + + INSERT_FLAGS(EFX_RX_HASH(IPV4, 1TUPLE_DST)); + INSERT_FLAGS(EFX_RX_HASH(IPV4, 1TUPLE_SRC)); + + INSERT_FLAGS(EFX_RX_HASH(IPV6, 1TUPLE_DST)); + INSERT_FLAGS(EFX_RX_HASH(IPV6, 1TUPLE_SRC)); + } + + INSERT_FLAGS(EFX_RX_HASH(IPV4_TCP, DISABLE)); + INSERT_FLAGS(EFX_RX_HASH(IPV6_TCP, DISABLE)); + + INSERT_FLAGS(EFX_RX_HASH(IPV4_UDP, DISABLE)); + INSERT_FLAGS(EFX_RX_HASH(IPV6_UDP, DISABLE)); + + INSERT_FLAGS(EFX_RX_HASH(IPV4, DISABLE)); + INSERT_FLAGS(EFX_RX_HASH(IPV6, DISABLE)); + +#undef INSERT_FLAGS + +done: + *nflagsp = nflags; + return (0); + +fail2: + EFSYS_PROBE(fail2); +fail1: + EFSYS_PROBE1(fail1, efx_rc_t, rc); + + return (rc); +} + __checkReturn efx_rc_t efx_rx_hash_default_support_get( __in efx_nic_t *enp, @@ -442,20 +532,96 @@ efx_rx_scale_mode_set( __in efx_rx_hash_type_t type, __in boolean_t insert) { + efx_nic_cfg_t *encp = &enp->en_nic_cfg; const efx_rx_ops_t *erxop = enp->en_erxop; + efx_rx_hash_type_t type_check; + unsigned int i; efx_rc_t rc; EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_RX); + /* + * Legacy flags and modern bits cannot be + * used at the same time in the hash type. + */ + if ((type & EFX_RX_HASH_LEGACY_MASK) && + (type & ~EFX_RX_HASH_LEGACY_MASK)) { + rc = EINVAL; + goto fail1; + } + + /* + * If RSS hash type is represented by additional bits + * in the value, the latter need to be verified since + * not all bit combinations are valid RSS modes. Also, + * depending on the firmware, some valid combinations + * may be unsupported. Discern additional bits in the + * type value and try to recognise valid combinations. + * If some bits remain unrecognised, report the error. + */ + type_check = type & ~EFX_RX_HASH_LEGACY_MASK; + if (type_check != 0) { + unsigned int type_flags[EFX_RX_HASH_NFLAGS]; + unsigned int type_nflags; + + rc = efx_rx_scale_hash_flags_get(enp, alg, type_flags, + EFX_ARRAY_SIZE(type_flags), &type_nflags); + if (rc != 0) + goto fail2; + + for (i = 0; i < type_nflags; ++i) { + if ((type_check & type_flags[i]) == type_flags[i]) + type_check &= ~(type_flags[i]); + } + + if (type_check != 0) { + rc = EINVAL; + goto fail3; + } + } + + /* + * Translate EFX_RX_HASH() flags to their legacy counterparts + * provided that the FW claims no support for additional modes. + */ + if (encp->enc_rx_scale_additional_modes_supported == B_FALSE) { + efx_rx_hash_type_t t_ipv4 = EFX_RX_HASH(IPV4, 2TUPLE) | + EFX_RX_HASH(IPV4_TCP, 2TUPLE); + efx_rx_hash_type_t t_ipv6 = EFX_RX_HASH(IPV6, 2TUPLE) | + EFX_RX_HASH(IPV6_TCP, 2TUPLE); + efx_rx_hash_type_t t_ipv4_tcp = EFX_RX_HASH(IPV4_TCP, 4TUPLE); + efx_rx_hash_type_t t_ipv6_tcp = EFX_RX_HASH(IPV6_TCP, 4TUPLE); + + if ((type & t_ipv4) == t_ipv4) + type |= EFX_RX_HASH_IPV4; + if ((type & t_ipv6) == t_ipv6) + type |= EFX_RX_HASH_IPV6; + + if (encp->enc_rx_scale_l4_hash_supported == B_TRUE) { + if ((type & t_ipv4_tcp) == t_ipv4_tcp) + type |= EFX_RX_HASH_TCPIPV4; + if ((type & t_ipv6_tcp) == t_ipv6_tcp) + type |= EFX_RX_HASH_TCPIPV6; + } + + type &= EFX_RX_HASH_LEGACY_MASK; + } + if (erxop->erxo_scale_mode_set != NULL) { if ((rc = erxop->erxo_scale_mode_set(enp, rss_context, alg, type, insert)) != 0) - goto fail1; + goto fail4; } return (0); +fail4: + EFSYS_PROBE(fail4); +fail3: + EFSYS_PROBE(fail3); +fail2: + EFSYS_PROBE(fail2); fail1: EFSYS_PROBE1(fail1, efx_rc_t, rc); return (rc); @@ -527,6 +693,7 @@ efx_rx_qpost( const efx_rx_ops_t *erxop = enp->en_erxop; EFSYS_ASSERT3U(erp->er_magic, ==, EFX_RXQ_MAGIC); + EFSYS_ASSERT(erp->er_buf_size == 0 || size == erp->er_buf_size); erxop->erxo_qpost(erp, addrp, size, ndescs, completed, added); } @@ -600,6 +767,24 @@ fail1: return (rc); } + __checkReturn size_t +efx_rxq_size( + __in const efx_nic_t *enp, + __in unsigned int ndescs) +{ + const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp); + + return (ndescs * encp->enc_rx_desc_size); +} + + __checkReturn unsigned int +efx_rxq_nbufs( + __in const efx_nic_t *enp, + __in unsigned int ndescs) +{ + return (EFX_DIV_ROUND_UP(efx_rxq_size(enp, ndescs), EFX_BUF_SIZE)); +} + void efx_rx_qenable( __in efx_rxq_t *erp) @@ -618,7 +803,7 @@ efx_rx_qcreate_internal( __in unsigned int index, __in unsigned int label, __in efx_rxq_type_t type, - __in uint32_t type_data, + __in_opt const efx_rxq_type_data_t *type_data, __in efsys_mem_t *esmp, __in size_t ndescs, __in uint32_t id, @@ -628,17 +813,28 @@ efx_rx_qcreate_internal( { const efx_rx_ops_t *erxop = enp->en_erxop; efx_rxq_t *erp; + const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp); efx_rc_t rc; EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_RX); + EFSYS_ASSERT(ISP2(encp->enc_rxq_max_ndescs)); + EFSYS_ASSERT(ISP2(encp->enc_rxq_min_ndescs)); + + if (!ISP2(ndescs) || + ndescs < encp->enc_rxq_min_ndescs || + ndescs > encp->enc_rxq_max_ndescs) { + rc = EINVAL; + goto fail1; + } + /* Allocate an RXQ object */ EFSYS_KMEM_ALLOC(enp->en_esip, sizeof (efx_rxq_t), erp); if (erp == NULL) { rc = ENOMEM; - goto fail1; + goto fail2; } erp->er_magic = EFX_RXQ_MAGIC; @@ -649,17 +845,19 @@ efx_rx_qcreate_internal( if ((rc = erxop->erxo_qcreate(enp, index, label, type, type_data, esmp, ndescs, id, flags, eep, erp)) != 0) - goto fail2; + goto fail3; enp->en_rx_qcount++; *erpp = erp; return (0); -fail2: - EFSYS_PROBE(fail2); +fail3: + EFSYS_PROBE(fail3); EFSYS_KMEM_FREE(enp->en_esip, sizeof (efx_rxq_t), erp); +fail2: + EFSYS_PROBE(fail2); fail1: EFSYS_PROBE1(fail1, efx_rc_t, rc); @@ -672,6 +870,7 @@ efx_rx_qcreate( __in unsigned int index, __in unsigned int label, __in efx_rxq_type_t type, + __in size_t buf_size, __in efsys_mem_t *esmp, __in size_t ndescs, __in uint32_t id, @@ -679,8 +878,14 @@ efx_rx_qcreate( __in efx_evq_t *eep, __deref_out efx_rxq_t **erpp) { - return efx_rx_qcreate_internal(enp, index, label, type, 0, esmp, ndescs, - id, flags, eep, erpp); + efx_rxq_type_data_t type_data; + + memset(&type_data, 0, sizeof (type_data)); + + type_data.ertd_default.ed_buf_size = buf_size; + + return efx_rx_qcreate_internal(enp, index, label, type, &type_data, + esmp, ndescs, id, flags, eep, erpp); } #if EFSYS_OPT_RX_PACKED_STREAM @@ -696,13 +901,71 @@ efx_rx_qcreate_packed_stream( __in efx_evq_t *eep, __deref_out efx_rxq_t **erpp) { + efx_rxq_type_data_t type_data; + + memset(&type_data, 0, sizeof (type_data)); + + type_data.ertd_packed_stream.eps_buf_size = ps_buf_size; + return efx_rx_qcreate_internal(enp, index, label, - EFX_RXQ_TYPE_PACKED_STREAM, ps_buf_size, esmp, ndescs, + EFX_RXQ_TYPE_PACKED_STREAM, &type_data, esmp, ndescs, 0 /* id unused on EF10 */, EFX_RXQ_FLAG_NONE, eep, erpp); } #endif +#if EFSYS_OPT_RX_ES_SUPER_BUFFER + + __checkReturn efx_rc_t +efx_rx_qcreate_es_super_buffer( + __in efx_nic_t *enp, + __in unsigned int index, + __in unsigned int label, + __in uint32_t n_bufs_per_desc, + __in uint32_t max_dma_len, + __in uint32_t buf_stride, + __in uint32_t hol_block_timeout, + __in efsys_mem_t *esmp, + __in size_t ndescs, + __in unsigned int flags, + __in efx_evq_t *eep, + __deref_out efx_rxq_t **erpp) +{ + efx_rc_t rc; + efx_rxq_type_data_t type_data; + + if (hol_block_timeout > EFX_RXQ_ES_SUPER_BUFFER_HOL_BLOCK_MAX) { + rc = EINVAL; + goto fail1; + } + + memset(&type_data, 0, sizeof (type_data)); + + type_data.ertd_es_super_buffer.eessb_bufs_per_desc = n_bufs_per_desc; + type_data.ertd_es_super_buffer.eessb_max_dma_len = max_dma_len; + type_data.ertd_es_super_buffer.eessb_buf_stride = buf_stride; + type_data.ertd_es_super_buffer.eessb_hol_block_timeout = + hol_block_timeout; + + rc = efx_rx_qcreate_internal(enp, index, label, + EFX_RXQ_TYPE_ES_SUPER_BUFFER, &type_data, esmp, ndescs, + 0 /* id unused on EF10 */, flags, eep, erpp); + if (rc != 0) + goto fail2; + + return (0); + +fail2: + EFSYS_PROBE(fail2); +fail1: + EFSYS_PROBE1(fail1, efx_rc_t, rc); + + return (rc); +} + +#endif + + void efx_rx_qdestroy( __in efx_rxq_t *erp) @@ -913,12 +1176,12 @@ siena_rx_scale_mode_set( case EFX_RX_HASHALG_TOEPLITZ: EFX_RX_TOEPLITZ_IPV4_HASH(enp, insert, - type & EFX_RX_HASH_IPV4, - type & EFX_RX_HASH_TCPIPV4); + (type & EFX_RX_HASH_IPV4) ? B_TRUE : B_FALSE, + (type & EFX_RX_HASH_TCPIPV4) ? B_TRUE : B_FALSE); EFX_RX_TOEPLITZ_IPV6_HASH(enp, - type & EFX_RX_HASH_IPV6, - type & EFX_RX_HASH_TCPIPV6, + (type & EFX_RX_HASH_IPV6) ? B_TRUE : B_FALSE, + (type & EFX_RX_HASH_TCPIPV6) ? B_TRUE : B_FALSE, rc); if (rc != 0) goto fail2; @@ -1344,7 +1607,7 @@ siena_rx_qcreate( __in unsigned int index, __in unsigned int label, __in efx_rxq_type_t type, - __in uint32_t type_data, + __in_opt const efx_rxq_type_data_t *type_data, __in efsys_mem_t *esmp, __in size_t ndescs, __in uint32_t id, @@ -1359,41 +1622,34 @@ siena_rx_qcreate( efx_rc_t rc; _NOTE(ARGUNUSED(esmp)) - _NOTE(ARGUNUSED(type_data)) EFX_STATIC_ASSERT(EFX_EV_RX_NLABELS == (1 << FRF_AZ_RX_DESCQ_LABEL_WIDTH)); EFSYS_ASSERT3U(label, <, EFX_EV_RX_NLABELS); EFSYS_ASSERT3U(enp->en_rx_qcount + 1, <, encp->enc_rxq_limit); - EFX_STATIC_ASSERT(ISP2(EFX_RXQ_MAXNDESCS)); - EFX_STATIC_ASSERT(ISP2(EFX_RXQ_MINNDESCS)); - - if (!ISP2(ndescs) || - (ndescs < EFX_RXQ_MINNDESCS) || (ndescs > EFX_RXQ_MAXNDESCS)) { - rc = EINVAL; - goto fail1; - } if (index >= encp->enc_rxq_limit) { rc = EINVAL; - goto fail2; + goto fail1; } - for (size = 0; (1 << size) <= (EFX_RXQ_MAXNDESCS / EFX_RXQ_MINNDESCS); + for (size = 0; + (1U << size) <= encp->enc_rxq_max_ndescs / encp->enc_rxq_min_ndescs; size++) - if ((1 << size) == (int)(ndescs / EFX_RXQ_MINNDESCS)) + if ((1U << size) == (uint32_t)ndescs / encp->enc_rxq_min_ndescs) break; if (id + (1 << size) >= encp->enc_buftbl_limit) { rc = EINVAL; - goto fail3; + goto fail2; } switch (type) { case EFX_RXQ_TYPE_DEFAULT: + erp->er_buf_size = type_data->ertd_default.ed_buf_size; break; default: rc = EINVAL; - goto fail4; + goto fail3; } if (flags & EFX_RXQ_FLAG_SCATTER) { @@ -1401,7 +1657,7 @@ siena_rx_qcreate( jumbo = B_TRUE; #else rc = EINVAL; - goto fail5; + goto fail4; #endif /* EFSYS_OPT_RX_SCATTER */ } @@ -1421,11 +1677,9 @@ siena_rx_qcreate( return (0); #if !EFSYS_OPT_RX_SCATTER -fail5: - EFSYS_PROBE(fail5); -#endif fail4: EFSYS_PROBE(fail4); +#endif fail3: EFSYS_PROBE(fail3); fail2: