diff --git a/drivers/net/sfc/base/ef10_nic.c b/drivers/net/sfc/base/ef10_nic.c
index ca11ff415..fa4f7a2c6 100644
--- a/drivers/net/sfc/base/ef10_nic.c
+++ b/drivers/net/sfc/base/ef10_nic.c
@@ -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;
diff --git a/drivers/net/sfc/base/ef10_rx.c b/drivers/net/sfc/base/ef10_rx.c
index d1971e38a..28b800414 100644
--- a/drivers/net/sfc/base/ef10_rx.c
+++ b/drivers/net/sfc/base/ef10_rx.c
@@ -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_type_t type_ipv4_tcp;
 	efx_rx_hash_type_t type_ipv6;
 	efx_rx_hash_type_t type_ipv6_tcp;
+	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,12 +341,35 @@ efx_mcdi_rss_context_set_flags(
 	MCDI_IN_SET_DWORD(req, RSS_CONTEXT_SET_FLAGS_IN_RSS_CONTEXT_ID,
 	    rss_context);
 
-	type_ipv4 = EFX_RX_HASH(IPV4, 2TUPLE) | EFX_RX_HASH(IPV4_TCP, 2TUPLE);
+	type_ipv4 = EFX_RX_HASH(IPV4, 2TUPLE) | EFX_RX_HASH(IPV4_TCP, 2TUPLE) |
+		    EFX_RX_HASH(IPV4_UDP, 2TUPLE);
 	type_ipv4_tcp = EFX_RX_HASH(IPV4_TCP, 4TUPLE);
-	type_ipv6 = EFX_RX_HASH(IPV6, 2TUPLE) | EFX_RX_HASH(IPV6_TCP, 2TUPLE);
+	type_ipv6 = EFX_RX_HASH(IPV6, 2TUPLE) | EFX_RX_HASH(IPV6_TCP, 2TUPLE) |
+		    EFX_RX_HASH(IPV6_UDP, 2TUPLE);
 	type_ipv6_tcp = EFX_RX_HASH(IPV6_TCP, 4TUPLE);
 
-	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,
@@ -352,7 +377,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);
 
diff --git a/drivers/net/sfc/base/efx.h b/drivers/net/sfc/base/efx.h
index 41aa505bc..21d2545f2 100644
--- a/drivers/net/sfc/base/efx.h
+++ b/drivers/net/sfc/base/efx.h
@@ -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.
diff --git a/drivers/net/sfc/base/efx_rx.c b/drivers/net/sfc/base/efx_rx.c
index a9995b4a4..b02c7f68d 100644
--- a/drivers/net/sfc/base/efx_rx.c
+++ b/drivers/net/sfc/base/efx_rx.c
@@ -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:
@@ -507,6 +531,7 @@ efx_rx_scale_mode_set(
 	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)
@@ -515,6 +540,7 @@ efx_rx_scale_mode_set(
 	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);
 	}
 
 	if (type & EFX_RX_HASH_TCPIPV6)
diff --git a/drivers/net/sfc/base/siena_nic.c b/drivers/net/sfc/base/siena_nic.c
index 6e57de468..0d6d07151 100644
--- a/drivers/net/sfc/base/siena_nic.c
+++ b/drivers/net/sfc/base/siena_nic.c
@@ -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;
