else
encp->enc_fec_counters = B_FALSE;
+ if (CAP_FLAGS1(req, RX_RSS_LIMITED)) {
+ /* Only one exclusive RSS context is available per port. */
+ encp->enc_rx_scale_max_exclusive_contexts = 1;
+
+ switch (enp->en_family) {
+ case EFX_FAMILY_MEDFORD2:
+ encp->enc_rx_scale_hash_alg_mask =
+ (1U << EFX_RX_HASHALG_TOEPLITZ);
+ break;
+
+ case EFX_FAMILY_MEDFORD:
+ case EFX_FAMILY_HUNTINGTON:
+ /*
+ * Packed stream firmware variant maintains a
+ * non-standard algorithm for hash computation.
+ * It implies explicit XORing together
+ * source + destination IP addresses (or last
+ * four bytes in the case of IPv6) and using the
+ * resulting value as the input to a Toeplitz hash.
+ */
+ encp->enc_rx_scale_hash_alg_mask =
+ (1U << EFX_RX_HASHALG_PACKED_STREAM);
+ break;
+
+ default:
+ rc = EINVAL;
+ goto fail5;
+ }
+
+ /* Port numbers cannot contribute to the hash value */
+ encp->enc_rx_scale_l4_hash_supported = B_FALSE;
+ } else {
+ /*
+ * Maximum number of exclusive RSS contexts.
+ * EF10 hardware supports 64 in total, but 6 are reserved
+ * for shared contexts. They are a global resource so
+ * not all may be available.
+ */
+ encp->enc_rx_scale_max_exclusive_contexts = 64 - 6;
+
+ encp->enc_rx_scale_hash_alg_mask =
+ (1U << EFX_RX_HASHALG_TOEPLITZ);
+
+ /*
+ * It is possible to use port numbers as
+ * the input data for hash computation.
+ */
+ encp->enc_rx_scale_l4_hash_supported = B_TRUE;
+ }
+
#undef CAP_FLAGS1
#undef CAP_FLAGS2
return (0);
+fail5:
+ EFSYS_PROBE(fail5);
fail4:
EFSYS_PROBE(fail4);
fail3:
/* Alignment for WPTR updates */
encp->enc_rx_push_align = EF10_RX_WPTR_ALIGN;
- /*
- * Maximum number of exclusive RSS contexts. EF10 hardware supports 64
- * in total, but 6 are reserved for shared contexts. They are a global
- * resource so not all may be available.
- */
- encp->enc_rx_scale_max_exclusive_contexts = 64 - 6;
-
encp->enc_tx_dma_desc_size_max = EFX_MASK32(ESF_DZ_RX_KER_BYTE_CNT);
/* No boundary crossing limits */
encp->enc_tx_dma_desc_boundary = 0;
__in efx_rx_hash_type_t type,
__in boolean_t insert)
{
+ efx_nic_cfg_t *encp = &enp->en_nic_cfg;
efx_rc_t rc;
- EFSYS_ASSERT3U(alg, ==, EFX_RX_HASHALG_TOEPLITZ);
EFSYS_ASSERT3U(insert, ==, B_TRUE);
- if ((alg != EFX_RX_HASHALG_TOEPLITZ) || (insert == B_FALSE)) {
+ if ((encp->enc_rx_scale_hash_alg_mask & (1U << alg)) == 0 ||
+ insert == B_FALSE) {
rc = EINVAL;
goto fail1;
}
_NOTE(ARGUNUSED(enp))
switch (func) {
+ case EFX_RX_HASHALG_PACKED_STREAM:
case EFX_RX_HASHALG_TOEPLITZ:
return (buffer[0] |
(buffer[1] << 8) |
uint32_t enc_rx_buf_align_start;
uint32_t enc_rx_buf_align_end;
uint32_t enc_rx_scale_max_exclusive_contexts;
+ /*
+ * Mask of supported hash algorithms.
+ * Hash algorithm types are used as the bit indices.
+ */
+ uint32_t enc_rx_scale_hash_alg_mask;
+ /*
+ * Indicates whether port numbers can be included to the
+ * input data for hash computation.
+ */
+ boolean_t enc_rx_scale_l4_hash_supported;
boolean_t enc_rx_scale_additional_modes_supported;
#if EFSYS_OPT_LOOPBACK
efx_qword_t enc_loopback_types[EFX_LINK_NMODES];
typedef enum efx_rx_hash_alg_e {
EFX_RX_HASHALG_LFSR = 0,
- EFX_RX_HASHALG_TOEPLITZ
+ EFX_RX_HASHALG_TOEPLITZ,
+ EFX_RX_HASHALG_PACKED_STREAM,
+ EFX_RX_NHASHALGS
} efx_rx_hash_alg_t;
/*
__out unsigned int *nflagsp)
{
efx_nic_cfg_t *encp = &enp->en_nic_cfg;
+ boolean_t l4;
boolean_t additional_modes;
unsigned int *entryp = flags;
efx_rc_t rc;
goto fail1;
}
+ l4 = encp->enc_rx_scale_l4_hash_supported;
additional_modes = encp->enc_rx_scale_additional_modes_supported;
#define LIST_FLAGS(_entryp, _class, _l4_hashing, _additional_modes) \
} 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:
- LIST_FLAGS(entryp, IPV4_TCP, B_TRUE, additional_modes);
- LIST_FLAGS(entryp, IPV6_TCP, B_TRUE, additional_modes);
+ if ((encp->enc_rx_scale_hash_alg_mask & (1U << hash_alg)) == 0)
+ break;
+
+ LIST_FLAGS(entryp, IPV4_TCP, l4, additional_modes);
+ LIST_FLAGS(entryp, IPV6_TCP, l4, additional_modes);
if (additional_modes) {
- LIST_FLAGS(entryp, IPV4_UDP, B_TRUE, additional_modes);
- LIST_FLAGS(entryp, IPV6_UDP, B_TRUE, additional_modes);
+ LIST_FLAGS(entryp, IPV4_UDP, l4, additional_modes);
+ LIST_FLAGS(entryp, IPV6_UDP, l4, additional_modes);
}
LIST_FLAGS(entryp, IPV4, B_FALSE, additional_modes);
/* There is one RSS context per function */
encp->enc_rx_scale_max_exclusive_contexts = 1;
+ encp->enc_rx_scale_hash_alg_mask |= (1U << EFX_RX_HASHALG_LFSR);
+ encp->enc_rx_scale_hash_alg_mask |= (1U << EFX_RX_HASHALG_TOEPLITZ);
+
+ /*
+ * It is always possible to use port numbers
+ * as the input data for hash computation.
+ */
+ encp->enc_rx_scale_l4_hash_supported = B_TRUE;
+
/* There is no support for additional RSS modes */
encp->enc_rx_scale_additional_modes_supported = B_FALSE;