Index: sys/dev/sfxge/common/ef10_nic.c =================================================================== --- sys/dev/sfxge/common/ef10_nic.c +++ sys/dev/sfxge/common/ef10_nic.c @@ -1266,11 +1266,63 @@ 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: @@ -1740,13 +1792,6 @@ /* 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; Index: sys/dev/sfxge/common/ef10_rx.c =================================================================== --- sys/dev/sfxge/common/ef10_rx.c +++ sys/dev/sfxge/common/ef10_rx.c @@ -643,12 +643,13 @@ __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; } @@ -797,6 +798,7 @@ _NOTE(ARGUNUSED(enp)) switch (func) { + case EFX_RX_HASHALG_PACKED_STREAM: case EFX_RX_HASHALG_TOEPLITZ: return (buffer[0] | (buffer[1] << 8) | Index: sys/dev/sfxge/common/efx.h =================================================================== --- sys/dev/sfxge/common/efx.h +++ sys/dev/sfxge/common/efx.h @@ -1220,6 +1220,16 @@ 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]; @@ -2096,7 +2106,9 @@ 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; /* Index: sys/dev/sfxge/common/efx_rx.c =================================================================== --- sys/dev/sfxge/common/efx_rx.c +++ sys/dev/sfxge/common/efx_rx.c @@ -331,6 +331,7 @@ __out unsigned int *nflagsp) { efx_nic_cfg_t *encp = &enp->en_nic_cfg; + boolean_t l4; boolean_t additional_modes; unsigned int *entryp = flagsp; efx_rc_t rc; @@ -340,6 +341,7 @@ 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) \ @@ -368,13 +370,20 @@ } 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); Index: sys/dev/sfxge/common/siena_nic.c =================================================================== --- sys/dev/sfxge/common/siena_nic.c +++ sys/dev/sfxge/common/siena_nic.c @@ -147,6 +147,15 @@ /* 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;