/* SPDX-License-Identifier: BSD-3-Clause
*
- * Copyright (c) 2007-2018 Solarflare Communications Inc.
- * All rights reserved.
+ * Copyright(c) 2019-2020 Xilinx, Inc.
+ * Copyright(c) 2007-2019 Solarflare Communications Inc.
*/
#include "efx.h"
__in unsigned int index,
__in unsigned int label,
__in efx_rxq_type_t type,
- __in const efx_rxq_type_data_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,
};
#endif /* EFSYS_OPT_SIENA */
-#if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2
+#if EFX_OPTS_EF10()
static const efx_rx_ops_t __efx_rx_ef10_ops = {
ef10_rx_init, /* erxo_init */
ef10_rx_fini, /* erxo_fini */
ef10_rx_qcreate, /* erxo_qcreate */
ef10_rx_qdestroy, /* erxo_qdestroy */
};
-#endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2 */
+#endif /* EFX_OPTS_EF10() */
__checkReturn efx_rc_t
efx_rx_scale_hash_flags_get(
__in efx_nic_t *enp,
__in efx_rx_hash_alg_t hash_alg,
- __inout_ecount(EFX_RX_HASH_NFLAGS) unsigned int *flagsp,
+ __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;
- boolean_t l4;
- boolean_t additional_modes;
- unsigned int *entryp = flagsp;
+ unsigned int nflags = 0;
efx_rc_t rc;
if (flagsp == NULL || nflagsp == NULL) {
goto fail1;
}
- l4 = encp->enc_rx_scale_l4_hash_supported;
- additional_modes = encp->enc_rx_scale_additional_modes_supported;
+ if ((encp->enc_rx_scale_hash_alg_mask & (1U << hash_alg)) == 0) {
+ nflags = 0;
+ goto done;
+ }
-#define LIST_FLAGS(_entryp, _class, _l4_hashing, _additional_modes) \
- do { \
- if (_l4_hashing) { \
- *(_entryp++) = EFX_RX_HASH(_class, 4TUPLE); \
- \
- if (_additional_modes) { \
- *(_entryp++) = \
- EFX_RX_HASH(_class, 2TUPLE_DST); \
- *(_entryp++) = \
- EFX_RX_HASH(_class, 2TUPLE_SRC); \
- } \
- } \
- \
- *(_entryp++) = EFX_RX_HASH(_class, 2TUPLE); \
- \
- if (_additional_modes) { \
- *(_entryp++) = EFX_RX_HASH(_class, 1TUPLE_DST); \
- *(_entryp++) = EFX_RX_HASH(_class, 1TUPLE_SRC); \
- } \
- \
- *(_entryp++) = EFX_RX_HASH(_class, DISABLE); \
- \
- _NOTE(CONSTANTCONDITION) \
+ /* 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)
- switch (hash_alg) {
- case EFX_RX_HASHALG_PACKED_STREAM:
- if ((encp->enc_rx_scale_hash_alg_mask & (1U << hash_alg)) == 0)
- break;
- /* FALLTHRU */
- case EFX_RX_HASHALG_TOEPLITZ:
- if ((encp->enc_rx_scale_hash_alg_mask & (1U << hash_alg)) == 0)
- break;
+ 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));
+ }
- LIST_FLAGS(entryp, IPV4_TCP, l4, additional_modes);
- LIST_FLAGS(entryp, IPV6_TCP, l4, additional_modes);
+ 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));
- if (additional_modes) {
- LIST_FLAGS(entryp, IPV4_UDP, l4, additional_modes);
- LIST_FLAGS(entryp, IPV6_UDP, l4, additional_modes);
- }
+ INSERT_FLAGS(EFX_RX_HASH(IPV6_TCP, 2TUPLE_DST));
+ INSERT_FLAGS(EFX_RX_HASH(IPV6_TCP, 2TUPLE_SRC));
- LIST_FLAGS(entryp, IPV4, B_FALSE, additional_modes);
- LIST_FLAGS(entryp, IPV6, B_FALSE, additional_modes);
- break;
+ 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));
- default:
- rc = EINVAL;
- goto fail2;
+ 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));
}
-#undef LIST_FLAGS
+ 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));
- *nflagsp = (unsigned int)(entryp - flagsp);
- EFSYS_ASSERT3U(*nflagsp, <=, EFX_RX_HASH_NFLAGS);
+ 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);
__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;
- unsigned int type_flags[EFX_RX_HASH_NFLAGS];
- unsigned int type_nflags;
efx_rx_hash_type_t type_check;
unsigned int i;
efx_rc_t rc;
}
/*
- * Translate legacy flags to the new representation
- * so that chip-specific handlers will consider the
- * new flags only.
+ * 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.
*/
- if (type & EFX_RX_HASH_IPV4) {
- type |= EFX_RX_HASH(IPV4, 2TUPLE);
- type |= EFX_RX_HASH(IPV4_TCP, 2TUPLE);
- type |= EFX_RX_HASH(IPV4_UDP, 2TUPLE);
- }
-
- if (type & EFX_RX_HASH_TCPIPV4)
- type |= EFX_RX_HASH(IPV4_TCP, 4TUPLE);
+ type_check = type & ~EFX_RX_HASH_LEGACY_MASK;
+ if (type_check != 0) {
+ unsigned int type_flags[EFX_RX_HASH_NFLAGS];
+ unsigned int type_nflags;
- if (type & EFX_RX_HASH_IPV6) {
- type |= EFX_RX_HASH(IPV6, 2TUPLE);
- type |= EFX_RX_HASH(IPV6_TCP, 2TUPLE);
- type |= EFX_RX_HASH(IPV6_UDP, 2TUPLE);
- }
+ rc = efx_rx_scale_hash_flags_get(enp, alg, type_flags,
+ EFX_ARRAY_SIZE(type_flags), &type_nflags);
+ if (rc != 0)
+ goto fail2;
- if (type & EFX_RX_HASH_TCPIPV6)
- type |= EFX_RX_HASH(IPV6_TCP, 4TUPLE);
+ for (i = 0; i < type_nflags; ++i) {
+ if ((type_check & type_flags[i]) == type_flags[i])
+ type_check &= ~(type_flags[i]);
+ }
- type &= ~EFX_RX_HASH_LEGACY_MASK;
- type_check = type;
+ if (type_check != 0) {
+ rc = EINVAL;
+ goto fail3;
+ }
+ }
/*
- * Get the list of supported hash flags and sanitise the input.
+ * Translate EFX_RX_HASH() flags to their legacy counterparts
+ * provided that the FW claims no support for additional modes.
*/
- rc = efx_rx_scale_hash_flags_get(enp, alg, 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 (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;
+ }
- if (type_check != 0) {
- rc = EINVAL;
- goto fail3;
+ type &= EFX_RX_HASH_LEGACY_MASK;
}
if (erxop->erxo_scale_mode_set != NULL) {
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);
}
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)
__in unsigned int index,
__in unsigned int label,
__in efx_rxq_type_t type,
- __in const efx_rxq_type_data_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,
{
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;
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);
__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,
__in efx_evq_t *eep,
__deref_out efx_rxq_t **erpp)
{
- return efx_rx_qcreate_internal(enp, index, label, type, NULL,
+ 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);
}
__in efx_rx_hash_type_t type,
__in boolean_t insert)
{
- efx_rx_hash_type_t type_ipv4 = EFX_RX_HASH(IPV4, 2TUPLE);
- efx_rx_hash_type_t type_ipv4_tcp = EFX_RX_HASH(IPV4_TCP, 4TUPLE);
- efx_rx_hash_type_t type_ipv6 = EFX_RX_HASH(IPV6, 2TUPLE);
- efx_rx_hash_type_t type_ipv6_tcp = EFX_RX_HASH(IPV6_TCP, 4TUPLE);
efx_rc_t rc;
if (rss_context != EFX_RSS_CONTEXT_DEFAULT) {
case EFX_RX_HASHALG_TOEPLITZ:
EFX_RX_TOEPLITZ_IPV4_HASH(enp, insert,
- (type & type_ipv4) == type_ipv4,
- (type & type_ipv4_tcp) == type_ipv4_tcp);
+ (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 & type_ipv6) == type_ipv6,
- (type & type_ipv6_tcp) == type_ipv6_tcp,
+ (type & EFX_RX_HASH_IPV6) ? B_TRUE : B_FALSE,
+ (type & EFX_RX_HASH_TCPIPV6) ? B_TRUE : B_FALSE,
rc);
if (rc != 0)
goto fail2;
__in unsigned int index,
__in unsigned int label,
__in efx_rxq_type_t type,
- __in const efx_rxq_type_data_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,
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) {
jumbo = B_TRUE;
#else
rc = EINVAL;
- goto fail5;
+ goto fail4;
#endif /* EFSYS_OPT_RX_SCATTER */
}
return (0);
#if !EFSYS_OPT_RX_SCATTER
-fail5:
- EFSYS_PROBE(fail5);
-#endif
fail4:
EFSYS_PROBE(fail4);
+#endif
fail3:
EFSYS_PROBE(fail3);
fail2: