@@ -1041,6 +1041,12 @@ ef10_get_datapath_caps(
}
encp->enc_rx_prefix_size = 14;
+ /* Check if the firmware supports additional RSS modes */
+ if (CAP_FLAGS1(req, ADDITIONAL_RSS_MODES))
+ encp->enc_rx_scale_additional_modes_supported = B_TRUE;
+ else
+ encp->enc_rx_scale_additional_modes_supported = B_FALSE;
+
/* Check if the firmware supports TSO */
if (CAP_FLAGS1(req, TX_TSO))
encp->enc_fw_assisted_tso_enabled = B_TRUE;
@@ -298,10 +298,12 @@ efx_mcdi_rss_context_set_flags(
__in uint32_t rss_context,
__in efx_rx_hash_type_t type)
{
+ efx_nic_cfg_t *encp = &enp->en_nic_cfg;
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_rx_hash_type_t modes;
efx_mcdi_req_t req;
uint8_t payload[MAX(MC_CMD_RSS_CONTEXT_SET_FLAGS_IN_LEN,
MC_CMD_RSS_CONTEXT_SET_FLAGS_OUT_LEN)];
@@ -339,7 +341,28 @@ efx_mcdi_rss_context_set_flags(
MCDI_IN_SET_DWORD(req, RSS_CONTEXT_SET_FLAGS_IN_RSS_CONTEXT_ID,
rss_context);
- MCDI_IN_POPULATE_DWORD_4(req, RSS_CONTEXT_SET_FLAGS_IN_FLAGS,
+ /*
+ * Create a copy of the original hash type.
+ * The copy will be used to fill in RSS_MODE bits and
+ * may be cleared beforehand. The original variable
+ * and, thus, EN bits will remain unaffected.
+ */
+ modes = type;
+
+ /*
+ * If the firmware lacks support for additional modes, RSS_MODE
+ * fields must contain zeros, otherwise the operation will fail.
+ */
+ if (encp->enc_rx_scale_additional_modes_supported == B_FALSE)
+ modes = 0;
+
+#define EXTRACT_RSS_MODE(_type, _class) \
+ (EFX_EXTRACT_NATIVE(_type, 0, 31, \
+ EFX_LOW_BIT(EFX_RX_CLASS_##_class), \
+ EFX_HIGH_BIT(EFX_RX_CLASS_##_class)) & \
+ EFX_MASK32(EFX_RX_CLASS_##_class))
+
+ MCDI_IN_POPULATE_DWORD_10(req, RSS_CONTEXT_SET_FLAGS_IN_FLAGS,
RSS_CONTEXT_SET_FLAGS_IN_TOEPLITZ_IPV4_EN,
((type & type_ipv4) == type_ipv4) ? 1 : 0,
RSS_CONTEXT_SET_FLAGS_IN_TOEPLITZ_TCPV4_EN,
@@ -347,7 +370,21 @@ efx_mcdi_rss_context_set_flags(
RSS_CONTEXT_SET_FLAGS_IN_TOEPLITZ_IPV6_EN,
((type & type_ipv6) == type_ipv6) ? 1 : 0,
RSS_CONTEXT_SET_FLAGS_IN_TOEPLITZ_TCPV6_EN,
- ((type & type_ipv6_tcp) == type_ipv6_tcp) ? 1 : 0);
+ ((type & type_ipv6_tcp) == type_ipv6_tcp) ? 1 : 0,
+ RSS_CONTEXT_SET_FLAGS_IN_TCP_IPV4_RSS_MODE,
+ EXTRACT_RSS_MODE(modes, IPV4_TCP),
+ RSS_CONTEXT_SET_FLAGS_IN_UDP_IPV4_RSS_MODE,
+ EXTRACT_RSS_MODE(modes, IPV4_UDP),
+ RSS_CONTEXT_SET_FLAGS_IN_OTHER_IPV4_RSS_MODE,
+ EXTRACT_RSS_MODE(modes, IPV4),
+ RSS_CONTEXT_SET_FLAGS_IN_TCP_IPV6_RSS_MODE,
+ EXTRACT_RSS_MODE(modes, IPV6_TCP),
+ RSS_CONTEXT_SET_FLAGS_IN_UDP_IPV6_RSS_MODE,
+ EXTRACT_RSS_MODE(modes, IPV6_UDP),
+ RSS_CONTEXT_SET_FLAGS_IN_OTHER_IPV6_RSS_MODE,
+ EXTRACT_RSS_MODE(modes, IPV6));
+
+#undef EXTRACT_RSS_MODE
efx_mcdi_execute(enp, &req);
@@ -1192,6 +1192,7 @@ typedef struct efx_nic_cfg_s {
uint32_t enc_rx_buf_align_start;
uint32_t enc_rx_buf_align_end;
uint32_t enc_rx_scale_max_exclusive_contexts;
+ boolean_t enc_rx_scale_additional_modes_supported;
#if EFSYS_OPT_LOOPBACK
efx_qword_t enc_loopback_types[EFX_LINK_NMODES];
#endif /* EFSYS_OPT_LOOPBACK */
@@ -2120,14 +2121,18 @@ typedef enum efx_rx_scale_context_type_e {
*/
#define EFX_RX_CLASS_IPV4_TCP_LBN 8
#define EFX_RX_CLASS_IPV4_TCP_WIDTH 4
+#define EFX_RX_CLASS_IPV4_UDP_LBN 12
+#define EFX_RX_CLASS_IPV4_UDP_WIDTH 4
#define EFX_RX_CLASS_IPV4_LBN 16
#define EFX_RX_CLASS_IPV4_WIDTH 4
#define EFX_RX_CLASS_IPV6_TCP_LBN 20
#define EFX_RX_CLASS_IPV6_TCP_WIDTH 4
+#define EFX_RX_CLASS_IPV6_UDP_LBN 24
+#define EFX_RX_CLASS_IPV6_UDP_WIDTH 4
#define EFX_RX_CLASS_IPV6_LBN 28
#define EFX_RX_CLASS_IPV6_WIDTH 4
-#define EFX_RX_NCLASSES 4
+#define EFX_RX_NCLASSES 6
/*
* Ancillary flags used to construct generic hash tuples.
@@ -2147,17 +2152,28 @@ typedef enum efx_rx_scale_context_type_e {
*/
#define EFX_RX_CLASS_HASH_DISABLE 0
+#define EFX_RX_CLASS_HASH_1TUPLE_SRC EFX_RX_CLASS_HASH_SRC_ADDR
+#define EFX_RX_CLASS_HASH_1TUPLE_DST EFX_RX_CLASS_HASH_DST_ADDR
+
#define EFX_RX_CLASS_HASH_2TUPLE \
(EFX_RX_CLASS_HASH_SRC_ADDR | \
EFX_RX_CLASS_HASH_DST_ADDR)
+#define EFX_RX_CLASS_HASH_2TUPLE_SRC \
+ (EFX_RX_CLASS_HASH_SRC_ADDR | \
+ EFX_RX_CLASS_HASH_SRC_PORT)
+
+#define EFX_RX_CLASS_HASH_2TUPLE_DST \
+ (EFX_RX_CLASS_HASH_DST_ADDR | \
+ EFX_RX_CLASS_HASH_DST_PORT)
+
#define EFX_RX_CLASS_HASH_4TUPLE \
(EFX_RX_CLASS_HASH_SRC_ADDR | \
EFX_RX_CLASS_HASH_DST_ADDR | \
EFX_RX_CLASS_HASH_SRC_PORT | \
EFX_RX_CLASS_HASH_DST_PORT)
-#define EFX_RX_CLASS_HASH_NTUPLES 3
+#define EFX_RX_CLASS_HASH_NTUPLES 7
/*
* Hash flag constructor.
@@ -301,6 +301,8 @@ efx_rx_scale_hash_flags_get(
__inout_ecount(EFX_RX_HASH_NFLAGS) unsigned int *flags,
__out unsigned int *nflagsp)
{
+ efx_nic_cfg_t *encp = &enp->en_nic_cfg;
+ boolean_t additional_modes;
unsigned int *entryp = flags;
efx_rc_t rc;
@@ -309,12 +311,28 @@ efx_rx_scale_hash_flags_get(
goto fail1;
}
-#define LIST_FLAGS(_entryp, _class, _l4_hashing) \
+ additional_modes = encp->enc_rx_scale_additional_modes_supported;
+
+#define LIST_FLAGS(_entryp, _class, _l4_hashing, _additional_modes) \
do { \
- if (_l4_hashing) \
+ 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) \
@@ -322,10 +340,16 @@ efx_rx_scale_hash_flags_get(
switch (hash_alg) {
case EFX_RX_HASHALG_TOEPLITZ:
- LIST_FLAGS(entryp, IPV4_TCP, B_TRUE);
- LIST_FLAGS(entryp, IPV6_TCP, B_TRUE);
- LIST_FLAGS(entryp, IPV4, B_FALSE);
- LIST_FLAGS(entryp, IPV6, B_FALSE);
+ LIST_FLAGS(entryp, IPV4_TCP, B_TRUE, additional_modes);
+ LIST_FLAGS(entryp, IPV6_TCP, B_TRUE, 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, B_FALSE, additional_modes);
+ LIST_FLAGS(entryp, IPV6, B_FALSE, additional_modes);
break;
default:
@@ -118,6 +118,9 @@ siena_board_cfg(
/* There is one RSS context per function */
encp->enc_rx_scale_max_exclusive_contexts = 1;
+ /* There is no support for additional RSS modes */
+ encp->enc_rx_scale_additional_modes_supported = B_FALSE;
+
encp->enc_tx_dma_desc_size_max = EFX_MASK32(FSF_AZ_TX_KER_BYTE_COUNT);
/* Fragments must not span 4k boundaries. */
encp->enc_tx_dma_desc_boundary = 4096;