[5/8] common/sfc_efx/base: support selecting RSS table entry count

Message ID 20220201085002.320102-6-ivan.malov@oktetlabs.ru (mailing list archive)
State Accepted, archived
Delegated to: Ferruh Yigit
Headers
Series net/sfc: improve flow action RSS support on EF100 boards |

Checks

Context Check Description
ci/checkpatch warning coding style issues

Commit Message

Ivan Malov Feb. 1, 2022, 8:49 a.m. UTC
  On Riverhead boards, the client can control how many entries
to have in the indirection table of an exclusive RSS context.

Provide the new parameter to clients and indicate its bounds.
Extend the API for writing the table to have the flexibility.

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Reviewed-by: Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/base/ef10_impl.h  |   1 +
 drivers/common/sfc_efx/base/ef10_nic.c   |  13 +++
 drivers/common/sfc_efx/base/ef10_rx.c    | 136 +++++++++++++++++++++--
 drivers/common/sfc_efx/base/efx.h        |  18 +++
 drivers/common/sfc_efx/base/efx_impl.h   |   3 +-
 drivers/common/sfc_efx/base/efx_mcdi.h   |  11 ++
 drivers/common/sfc_efx/base/efx_rx.c     |  38 ++++++-
 drivers/common/sfc_efx/base/rhead_impl.h |   1 +
 drivers/common/sfc_efx/base/rhead_rx.c   |   4 +-
 drivers/common/sfc_efx/version.map       |   1 +
 10 files changed, 212 insertions(+), 14 deletions(-)
  

Comments

Ray Kinsella Feb. 2, 2022, 11:51 a.m. UTC | #1
Ivan Malov <ivan.malov@oktetlabs.ru> writes:

> On Riverhead boards, the client can control how many entries
> to have in the indirection table of an exclusive RSS context.
>
> Provide the new parameter to clients and indicate its bounds.
> Extend the API for writing the table to have the flexibility.
>
> Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
> Reviewed-by: Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>
> Reviewed-by: Andy Moreton <amoreton@xilinx.com>
> ---
>  drivers/common/sfc_efx/base/ef10_impl.h  |   1 +
>  drivers/common/sfc_efx/base/ef10_nic.c   |  13 +++
>  drivers/common/sfc_efx/base/ef10_rx.c    | 136 +++++++++++++++++++++--
>  drivers/common/sfc_efx/base/efx.h        |  18 +++
>  drivers/common/sfc_efx/base/efx_impl.h   |   3 +-
>  drivers/common/sfc_efx/base/efx_mcdi.h   |  11 ++
>  drivers/common/sfc_efx/base/efx_rx.c     |  38 ++++++-
>  drivers/common/sfc_efx/base/rhead_impl.h |   1 +
>  drivers/common/sfc_efx/base/rhead_rx.c   |   4 +-
>  drivers/common/sfc_efx/version.map       |   1 +
>  10 files changed, 212 insertions(+), 14 deletions(-)
>
>  
> diff --git a/drivers/common/sfc_efx/version.map b/drivers/common/sfc_efx/version.map
> index 97dd943ec4..9510897b83 100644
> --- a/drivers/common/sfc_efx/version.map
> +++ b/drivers/common/sfc_efx/version.map
> @@ -216,6 +216,7 @@ INTERNAL {
>  	efx_rx_qpost;
>  	efx_rx_qpush;
>  	efx_rx_scale_context_alloc;
> +	efx_rx_scale_context_alloc_v2;
>  	efx_rx_scale_context_free;
>  	efx_rx_scale_default_support_get;
>  	efx_rx_scale_hash_flags_get;

So this internal, so ordinarly I have little enough to do or say about
it. In this case, I do have to ask is the _v2 version of the function
avoidable?
  
Ivan Malov Feb. 2, 2022, 12:24 p.m. UTC | #2
Hi,

On Wed, 2 Feb 2022, Ray Kinsella wrote:

>
> Ivan Malov <ivan.malov@oktetlabs.ru> writes:
>
>> On Riverhead boards, the client can control how many entries
>> to have in the indirection table of an exclusive RSS context.
>>
>> Provide the new parameter to clients and indicate its bounds.
>> Extend the API for writing the table to have the flexibility.
>>
>> Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
>> Reviewed-by: Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>
>> Reviewed-by: Andy Moreton <amoreton@xilinx.com>
>> ---
>>  drivers/common/sfc_efx/base/ef10_impl.h  |   1 +
>>  drivers/common/sfc_efx/base/ef10_nic.c   |  13 +++
>>  drivers/common/sfc_efx/base/ef10_rx.c    | 136 +++++++++++++++++++++--
>>  drivers/common/sfc_efx/base/efx.h        |  18 +++
>>  drivers/common/sfc_efx/base/efx_impl.h   |   3 +-
>>  drivers/common/sfc_efx/base/efx_mcdi.h   |  11 ++
>>  drivers/common/sfc_efx/base/efx_rx.c     |  38 ++++++-
>>  drivers/common/sfc_efx/base/rhead_impl.h |   1 +
>>  drivers/common/sfc_efx/base/rhead_rx.c   |   4 +-
>>  drivers/common/sfc_efx/version.map       |   1 +
>>  10 files changed, 212 insertions(+), 14 deletions(-)
>>
>>
>> diff --git a/drivers/common/sfc_efx/version.map b/drivers/common/sfc_efx/version.map
>> index 97dd943ec4..9510897b83 100644
>> --- a/drivers/common/sfc_efx/version.map
>> +++ b/drivers/common/sfc_efx/version.map
>> @@ -216,6 +216,7 @@ INTERNAL {
>>  	efx_rx_qpost;
>>  	efx_rx_qpush;
>>  	efx_rx_scale_context_alloc;
>> +	efx_rx_scale_context_alloc_v2;
>>  	efx_rx_scale_context_free;
>>  	efx_rx_scale_default_support_get;
>>  	efx_rx_scale_hash_flags_get;
>
> So this internal, so ordinarly I have little enough to do or say about
> it. In this case, I do have to ask is the _v2 version of the function
> avoidable?

The PMD in question is not the only driver based on libefx. Extending
efx_rx_scale_context_alloc() to add an extra argument would require
that the other libefx-based drivers be updated accordingly. That
is not always reasonable / robust. Hence the v2 method.

Thank you.

--
Ivan M
  

Patch

diff --git a/drivers/common/sfc_efx/base/ef10_impl.h b/drivers/common/sfc_efx/base/ef10_impl.h
index 597dd24909..342a9a2006 100644
--- a/drivers/common/sfc_efx/base/ef10_impl.h
+++ b/drivers/common/sfc_efx/base/ef10_impl.h
@@ -1137,6 +1137,7 @@  ef10_rx_scale_context_alloc(
 	__in		efx_nic_t *enp,
 	__in		efx_rx_scale_context_type_t type,
 	__in		uint32_t num_queues,
+	__in		uint32_t table_nentries,
 	__out		uint32_t *rss_contextp);
 
 LIBEFX_INTERNAL
diff --git a/drivers/common/sfc_efx/base/ef10_nic.c b/drivers/common/sfc_efx/base/ef10_nic.c
index d9f7c0f362..cca31bc725 100644
--- a/drivers/common/sfc_efx/base/ef10_nic.c
+++ b/drivers/common/sfc_efx/base/ef10_nic.c
@@ -1409,6 +1409,11 @@  ef10_get_datapath_caps(
 		 */
 		encp->enc_rx_scale_l4_hash_supported = B_TRUE;
 	}
+
+	if (CAP_FLAGS3(req, RSS_SELECTABLE_TABLE_SIZE))
+		encp->enc_rx_scale_tbl_entry_count_is_selectable = B_TRUE;
+	else
+		encp->enc_rx_scale_tbl_entry_count_is_selectable = B_FALSE;
 #endif /* EFSYS_OPT_RX_SCALE */
 
 	/* Check if the firmware supports "FLAG" and "MARK" filter actions */
@@ -1471,8 +1476,16 @@  ef10_get_datapath_caps(
 		encp->enc_rx_scale_indirection_max_nqueues =
 		    MCDI_OUT_DWORD(req,
 			GET_CAPABILITIES_V9_OUT_RSS_MAX_INDIRECTION_QUEUES);
+		encp->enc_rx_scale_tbl_min_nentries =
+		    MCDI_OUT_DWORD(req,
+			GET_CAPABILITIES_V9_OUT_RSS_MIN_INDIRECTION_TABLE_SIZE);
+		encp->enc_rx_scale_tbl_max_nentries =
+		    MCDI_OUT_DWORD(req,
+			GET_CAPABILITIES_V9_OUT_RSS_MAX_INDIRECTION_TABLE_SIZE);
 	} else {
 		encp->enc_rx_scale_indirection_max_nqueues = EFX_MAXRSS;
+		encp->enc_rx_scale_tbl_min_nentries = EFX_RSS_TBL_SIZE;
+		encp->enc_rx_scale_tbl_max_nentries = EFX_RSS_TBL_SIZE;
 	}
 #endif /* EFSYS_OPT_RX_SCALE */
 
diff --git a/drivers/common/sfc_efx/base/ef10_rx.c b/drivers/common/sfc_efx/base/ef10_rx.c
index 5008139a3f..78af7300a0 100644
--- a/drivers/common/sfc_efx/base/ef10_rx.c
+++ b/drivers/common/sfc_efx/base/ef10_rx.c
@@ -16,11 +16,12 @@  efx_mcdi_rss_context_alloc(
 	__in		efx_nic_t *enp,
 	__in		efx_rx_scale_context_type_t type,
 	__in		uint32_t num_queues,
+	__in		uint32_t table_nentries,
 	__out		uint32_t *rss_contextp)
 {
 	const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
 	efx_mcdi_req_t req;
-	EFX_MCDI_DECLARE_BUF(payload, MC_CMD_RSS_CONTEXT_ALLOC_IN_LEN,
+	EFX_MCDI_DECLARE_BUF(payload, MC_CMD_RSS_CONTEXT_ALLOC_V2_IN_LEN,
 		MC_CMD_RSS_CONTEXT_ALLOC_OUT_LEN);
 	uint32_t rss_context;
 	uint32_t context_type;
@@ -31,6 +32,13 @@  efx_mcdi_rss_context_alloc(
 		goto fail1;
 	}
 
+	if (table_nentries < encp->enc_rx_scale_tbl_min_nentries ||
+	    table_nentries > encp->enc_rx_scale_tbl_max_nentries ||
+	    !ISP2(table_nentries)) {
+		rc = EINVAL;
+		goto fail2;
+	}
+
 	switch (type) {
 	case EFX_RX_SCALE_EXCLUSIVE:
 		context_type = MC_CMD_RSS_CONTEXT_ALLOC_IN_TYPE_EXCLUSIVE;
@@ -40,12 +48,15 @@  efx_mcdi_rss_context_alloc(
 		break;
 	default:
 		rc = EINVAL;
-		goto fail2;
+		goto fail3;
 	}
 
 	req.emr_cmd = MC_CMD_RSS_CONTEXT_ALLOC;
 	req.emr_in_buf = payload;
-	req.emr_in_length = MC_CMD_RSS_CONTEXT_ALLOC_IN_LEN;
+	req.emr_in_length =
+	    (encp->enc_rx_scale_tbl_entry_count_is_selectable != B_FALSE) ?
+	    MC_CMD_RSS_CONTEXT_ALLOC_V2_IN_LEN :
+	    MC_CMD_RSS_CONTEXT_ALLOC_IN_LEN;
 	req.emr_out_buf = payload;
 	req.emr_out_length = MC_CMD_RSS_CONTEXT_ALLOC_OUT_LEN;
 
@@ -61,28 +72,36 @@  efx_mcdi_rss_context_alloc(
 	 */
 	MCDI_IN_SET_DWORD(req, RSS_CONTEXT_ALLOC_IN_NUM_QUEUES, num_queues);
 
+	if (encp->enc_rx_scale_tbl_entry_count_is_selectable != B_FALSE) {
+		MCDI_IN_SET_DWORD(req,
+		    RSS_CONTEXT_ALLOC_V2_IN_INDIRECTION_TABLE_SIZE,
+		    table_nentries);
+	}
+
 	efx_mcdi_execute(enp, &req);
 
 	if (req.emr_rc != 0) {
 		rc = req.emr_rc;
-		goto fail3;
+		goto fail4;
 	}
 
 	if (req.emr_out_length_used < MC_CMD_RSS_CONTEXT_ALLOC_OUT_LEN) {
 		rc = EMSGSIZE;
-		goto fail4;
+		goto fail5;
 	}
 
 	rss_context = MCDI_OUT_DWORD(req, RSS_CONTEXT_ALLOC_OUT_RSS_CONTEXT_ID);
 	if (rss_context == EF10_RSS_CONTEXT_INVALID) {
 		rc = ENOENT;
-		goto fail5;
+		goto fail6;
 	}
 
 	*rss_contextp = rss_context;
 
 	return (0);
 
+fail6:
+	EFSYS_PROBE(fail6);
 fail5:
 	EFSYS_PROBE(fail5);
 fail4:
@@ -347,6 +366,76 @@  efx_mcdi_rss_context_set_table(
 }
 #endif /* EFSYS_OPT_RX_SCALE */
 
+#if EFSYS_OPT_RX_SCALE
+static	__checkReturn		efx_rc_t
+efx_mcdi_rss_context_write_table(
+	__in			efx_nic_t *enp,
+	__in			uint32_t context,
+	__in			unsigned int start_idx,
+	__in_ecount(nentries)	unsigned int *table,
+	__in			unsigned int nentries)
+{
+	const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
+	efx_mcdi_req_t req;
+	EFX_MCDI_DECLARE_BUF(payload,
+	     MC_CMD_RSS_CONTEXT_WRITE_TABLE_IN_LENMAX_MCDI2,
+	     MC_CMD_RSS_CONTEXT_WRITE_TABLE_OUT_LEN);
+	unsigned int i;
+	int rc;
+
+	if (nentries >
+	    MC_CMD_RSS_CONTEXT_WRITE_TABLE_IN_ENTRIES_MAXNUM_MCDI2) {
+		rc = EINVAL;
+		goto fail1;
+	}
+
+	if (start_idx + nentries >
+	    encp->enc_rx_scale_tbl_max_nentries) {
+		rc = EINVAL;
+		goto fail2;
+	}
+
+	req.emr_cmd = MC_CMD_RSS_CONTEXT_WRITE_TABLE;
+	req.emr_in_buf = payload;
+	req.emr_in_length = MC_CMD_RSS_CONTEXT_WRITE_TABLE_IN_LEN(nentries);
+	req.emr_out_buf = payload;
+	req.emr_out_length = MC_CMD_RSS_CONTEXT_WRITE_TABLE_OUT_LEN;
+
+	MCDI_IN_SET_DWORD(req,
+	    RSS_CONTEXT_WRITE_TABLE_IN_RSS_CONTEXT_ID, context);
+
+	for (i = 0; i < nentries; ++i) {
+		if (table[i] >= encp->enc_rx_scale_indirection_max_nqueues) {
+			rc = EINVAL;
+			goto fail3;
+		}
+
+		MCDI_IN_POPULATE_INDEXED_DWORD_2(req,
+		    RSS_CONTEXT_WRITE_TABLE_IN_ENTRIES, i,
+		    RSS_CONTEXT_WRITE_TABLE_ENTRY_INDEX, start_idx + i,
+		    RSS_CONTEXT_WRITE_TABLE_ENTRY_VALUE, table[i]);
+	}
+
+	efx_mcdi_execute(enp, &req);
+	if (req.emr_rc != 0) {
+		rc = req.emr_rc;
+		goto fail4;
+	}
+
+	return (0);
+
+fail4:
+	EFSYS_PROBE(fail4);
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+	return (rc);
+}
+#endif /* EFSYS_OPT_RX_SCALE */
+
 
 	__checkReturn	efx_rc_t
 ef10_rx_init(
@@ -355,7 +444,7 @@  ef10_rx_init(
 #if EFSYS_OPT_RX_SCALE
 
 	if (efx_mcdi_rss_context_alloc(enp, EFX_RX_SCALE_EXCLUSIVE, EFX_MAXRSS,
-		&enp->en_rss_context) == 0) {
+		EFX_RSS_TBL_SIZE, &enp->en_rss_context) == 0) {
 		/*
 		 * Allocated an exclusive RSS context, which allows both the
 		 * indirection table and key to be modified.
@@ -398,11 +487,13 @@  ef10_rx_scale_context_alloc(
 	__in		efx_nic_t *enp,
 	__in		efx_rx_scale_context_type_t type,
 	__in		uint32_t num_queues,
+	__in		uint32_t table_nentries,
 	__out		uint32_t *rss_contextp)
 {
 	efx_rc_t rc;
 
-	rc = efx_mcdi_rss_context_alloc(enp, type, num_queues, rss_contextp);
+	rc = efx_mcdi_rss_context_alloc(enp, type, num_queues, table_nentries,
+					rss_contextp);
 	if (rc != 0)
 		goto fail1;
 
@@ -522,6 +613,7 @@  ef10_rx_scale_tbl_set(
 	__in_ecount(nentries)	unsigned int *table,
 	__in			size_t nentries)
 {
+	const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
 	efx_rc_t rc;
 
 
@@ -533,12 +625,34 @@  ef10_rx_scale_tbl_set(
 		rss_context = enp->en_rss_context;
 	}
 
-	if ((rc = efx_mcdi_rss_context_set_table(enp,
-		    rss_context, table, nentries)) != 0)
-		goto fail2;
+	if (encp->enc_rx_scale_tbl_entry_count_is_selectable != B_FALSE) {
+		uint32_t index, remain, batch;
+
+		batch = MC_CMD_RSS_CONTEXT_WRITE_TABLE_IN_ENTRIES_MAXNUM_MCDI2;
+		index = 0;
+
+		for (remain = nentries; remain > 0; remain -= batch) {
+			if (batch > remain)
+				batch = remain;
+
+			rc = efx_mcdi_rss_context_write_table(enp, rss_context,
+				    index, &table[index], batch);
+			if (rc != 0)
+				goto fail2;
+
+			index += batch;
+		}
+	} else {
+		rc = efx_mcdi_rss_context_set_table(enp, rss_context, table,
+			    nentries);
+		if (rc != 0)
+			goto fail3;
+	}
 
 	return (0);
 
+fail3:
+	EFSYS_PROBE(fail3);
 fail2:
 	EFSYS_PROBE(fail2);
 fail1:
diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h
index a35e29ebcf..4523829eb2 100644
--- a/drivers/common/sfc_efx/base/efx.h
+++ b/drivers/common/sfc_efx/base/efx.h
@@ -1502,6 +1502,10 @@  typedef struct efx_nic_cfg_s {
 	 * This means that the maximum offset has to be less than this value.
 	 */
 	uint32_t		enc_rx_scale_indirection_max_nqueues;
+	/* Minimum number of entries an RSS indirection table can contain. */
+	uint32_t		enc_rx_scale_tbl_min_nentries;
+	/* Maximum number of entries an RSS indirection table can contain. */
+	uint32_t		enc_rx_scale_tbl_max_nentries;
 	uint32_t		enc_rx_scale_max_exclusive_contexts;
 	/*
 	 * Mask of supported hash algorithms.
@@ -1514,6 +1518,11 @@  typedef struct efx_nic_cfg_s {
 	 */
 	boolean_t		enc_rx_scale_l4_hash_supported;
 	boolean_t		enc_rx_scale_additional_modes_supported;
+	/*
+	 * Indicates whether the user can decide how many entries to
+	 * have in the indirection table of an exclusive RSS context.
+	 */
+	boolean_t		enc_rx_scale_tbl_entry_count_is_selectable;
 #endif /* EFSYS_OPT_RX_SCALE */
 #if EFSYS_OPT_LOOPBACK
 	efx_qword_t		enc_loopback_types[EFX_LINK_NMODES];
@@ -2887,6 +2896,15 @@  efx_rx_scale_context_alloc(
 	__in		uint32_t num_queues,
 	__out		uint32_t *rss_contextp);
 
+LIBEFX_API
+extern	__checkReturn	efx_rc_t
+efx_rx_scale_context_alloc_v2(
+	__in		efx_nic_t *enp,
+	__in		efx_rx_scale_context_type_t type,
+	__in		uint32_t num_queues,
+	__in		uint32_t table_nentries,
+	__out		uint32_t *rss_contextp);
+
 LIBEFX_API
 extern	__checkReturn	efx_rc_t
 efx_rx_scale_context_free(
diff --git a/drivers/common/sfc_efx/base/efx_impl.h b/drivers/common/sfc_efx/base/efx_impl.h
index e2802e6672..7dfe30b695 100644
--- a/drivers/common/sfc_efx/base/efx_impl.h
+++ b/drivers/common/sfc_efx/base/efx_impl.h
@@ -173,7 +173,8 @@  typedef struct efx_rx_ops_s {
 #if EFSYS_OPT_RX_SCALE
 	efx_rc_t	(*erxo_scale_context_alloc)(efx_nic_t *,
 						    efx_rx_scale_context_type_t,
-						    uint32_t, uint32_t *);
+						    uint32_t, uint32_t,
+						    uint32_t *);
 	efx_rc_t	(*erxo_scale_context_free)(efx_nic_t *, uint32_t);
 	efx_rc_t	(*erxo_scale_mode_set)(efx_nic_t *, uint32_t,
 					       efx_rx_hash_alg_t,
diff --git a/drivers/common/sfc_efx/base/efx_mcdi.h b/drivers/common/sfc_efx/base/efx_mcdi.h
index c91ea41911..14a3833567 100644
--- a/drivers/common/sfc_efx/base/efx_mcdi.h
+++ b/drivers/common/sfc_efx/base/efx_mcdi.h
@@ -315,6 +315,10 @@  efx_mcdi_set_nic_addr_regions(
 #define	MCDI_IN2(_emr, _type, _ofst)					\
 	MCDI_IN(_emr, _type, MC_CMD_ ## _ofst ## _OFST)
 
+#define	MCDI_INDEXED_IN2(_emr, _type, _ofst, _idx)			\
+	MCDI_IN(_emr, _type, MC_CMD_ ## _ofst ## _OFST +		\
+		_idx * MC_CMD_ ## _ofst ## _LEN)
+
 #define	MCDI_IN_SET_BYTE(_emr, _ofst, _value)				\
 	EFX_POPULATE_BYTE_1(*MCDI_IN2(_emr, efx_byte_t, _ofst),		\
 		EFX_BYTE_0, _value)
@@ -356,6 +360,13 @@  efx_mcdi_set_nic_addr_regions(
 		MC_CMD_ ## _field1, _value1,				\
 		MC_CMD_ ## _field2, _value2)
 
+#define	MCDI_IN_POPULATE_INDEXED_DWORD_2(_emr, _ofst, _idx,		\
+		_field1, _value1, _field2, _value2)			\
+	EFX_POPULATE_DWORD_2(						\
+		*MCDI_INDEXED_IN2(_emr, efx_dword_t, _ofst, _idx),	\
+		MC_CMD_ ## _field1, _value1,				\
+		MC_CMD_ ## _field2, _value2)
+
 #define	MCDI_IN_POPULATE_DWORD_3(_emr, _ofst, _field1, _value1,		\
 		_field2, _value2, _field3, _value3)			\
 	EFX_POPULATE_DWORD_3(*MCDI_IN2(_emr, efx_dword_t, _ofst),	\
diff --git a/drivers/common/sfc_efx/base/efx_rx.c b/drivers/common/sfc_efx/base/efx_rx.c
index eb3f736f63..d10b990259 100644
--- a/drivers/common/sfc_efx/base/efx_rx.c
+++ b/drivers/common/sfc_efx/base/efx_rx.c
@@ -514,8 +514,44 @@  efx_rx_scale_context_alloc(
 		rc = ENOTSUP;
 		goto fail1;
 	}
+
+	if ((rc = erxop->erxo_scale_context_alloc(enp, type, num_queues,
+			    EFX_RSS_TBL_SIZE, rss_contextp)) != 0) {
+		goto fail2;
+	}
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+	return (rc);
+}
+#endif	/* EFSYS_OPT_RX_SCALE */
+
+#if EFSYS_OPT_RX_SCALE
+	__checkReturn	efx_rc_t
+efx_rx_scale_context_alloc_v2(
+	__in		efx_nic_t *enp,
+	__in		efx_rx_scale_context_type_t type,
+	__in		uint32_t num_queues,
+	__in		uint32_t table_nentries,
+	__out		uint32_t *rss_contextp)
+{
+	const efx_rx_ops_t *erxop = enp->en_erxop;
+	efx_rc_t rc;
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_RX);
+
+	if (erxop->erxo_scale_context_alloc == NULL) {
+		rc = ENOTSUP;
+		goto fail1;
+	}
+
 	if ((rc = erxop->erxo_scale_context_alloc(enp, type,
-			    num_queues, rss_contextp)) != 0) {
+			    num_queues, table_nentries, rss_contextp)) != 0) {
 		goto fail2;
 	}
 
diff --git a/drivers/common/sfc_efx/base/rhead_impl.h b/drivers/common/sfc_efx/base/rhead_impl.h
index e0d95ba2aa..fb0ecca79d 100644
--- a/drivers/common/sfc_efx/base/rhead_impl.h
+++ b/drivers/common/sfc_efx/base/rhead_impl.h
@@ -261,6 +261,7 @@  rhead_rx_scale_context_alloc(
 	__in		efx_nic_t *enp,
 	__in		efx_rx_scale_context_type_t type,
 	__in		uint32_t num_queues,
+	__in		uint32_t table_nentries,
 	__out		uint32_t *rss_contextp);
 
 LIBEFX_INTERNAL
diff --git a/drivers/common/sfc_efx/base/rhead_rx.c b/drivers/common/sfc_efx/base/rhead_rx.c
index d28f936ab7..d0ac5c02f8 100644
--- a/drivers/common/sfc_efx/base/rhead_rx.c
+++ b/drivers/common/sfc_efx/base/rhead_rx.c
@@ -88,11 +88,13 @@  rhead_rx_scale_context_alloc(
 	__in		efx_nic_t *enp,
 	__in		efx_rx_scale_context_type_t type,
 	__in		uint32_t num_queues,
+	__in		uint32_t table_nentries,
 	__out		uint32_t *rss_contextp)
 {
 	efx_rc_t rc;
 
-	rc = ef10_rx_scale_context_alloc(enp, type, num_queues, rss_contextp);
+	rc = ef10_rx_scale_context_alloc(enp, type, num_queues, table_nentries,
+		    rss_contextp);
 	if (rc != 0)
 		goto fail1;
 
diff --git a/drivers/common/sfc_efx/version.map b/drivers/common/sfc_efx/version.map
index 97dd943ec4..9510897b83 100644
--- a/drivers/common/sfc_efx/version.map
+++ b/drivers/common/sfc_efx/version.map
@@ -216,6 +216,7 @@  INTERNAL {
 	efx_rx_qpost;
 	efx_rx_qpush;
 	efx_rx_scale_context_alloc;
+	efx_rx_scale_context_alloc_v2;
 	efx_rx_scale_context_free;
 	efx_rx_scale_default_support_get;
 	efx_rx_scale_hash_flags_get;