diff mbox series

[net-next,v2,02/12] eth: mvpp2: implement new RSS context API

Message ID 20240803042624.970352-3-kuba@kernel.org (mailing list archive)
State Superseded
Delegated to: Netdev Maintainers
Headers show
Series ethtool: rss: driver tweaks and netlink context dumps | expand

Checks

Context Check Description
netdev/series_format success Posting correctly formatted
netdev/tree_selection success Clearly marked for net-next
netdev/ynl success Generated files up to date; no warnings/errors; GEN HAS DIFF 2 files changed, 119 insertions(+);
netdev/fixes_present success Fixes tag not required for -next series
netdev/header_inline success No static functions without inline keyword in header files
netdev/build_32bit success Errors and warnings before: 29 this patch: 29
netdev/build_tools success No tools touched, skip
netdev/cc_maintainers success CCed 6 of 6 maintainers
netdev/build_clang success Errors and warnings before: 29 this patch: 29
netdev/verify_signedoff success Signed-off-by tag matches author and committer
netdev/deprecated_api success None detected
netdev/check_selftest success No net selftest shell script
netdev/verify_fixes success No Fixes tag
netdev/build_allmodconfig_warn success Errors and warnings before: 36 this patch: 36
netdev/checkpatch warning WARNING: line length of 85 exceeds 80 columns
netdev/build_clang_rust success No Rust files in patch. Skipping build
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/source_inline success Was 0 now: 0
netdev/contest success net-next-2024-08-06--00-00 (tests: 707)

Commit Message

Jakub Kicinski Aug. 3, 2024, 4:26 a.m. UTC
Implement the separate create/modify/delete ops for RSS.

No problems with IDs - even tho RSS tables are per device
the driver already seems to allocate IDs linearly per port.
There's a translation table from per-port context ID
to device context ID.

mvpp2 doesn't have a key for the hash, it defaults to
an empty/previous indir table.

Compile-tested only.

Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
v2:
 - copy the default indir table
 - use ID from the core
 - fix build issues

CC: marcin.s.wojtas@gmail.com
CC: linux@armlinux.org.uk
---
 .../net/ethernet/marvell/mvpp2/mvpp2_cls.c    |  18 +---
 .../net/ethernet/marvell/mvpp2/mvpp2_cls.h    |   2 +-
 .../net/ethernet/marvell/mvpp2/mvpp2_main.c   | 102 +++++++++++++-----
 3 files changed, 79 insertions(+), 43 deletions(-)

Comments

Edward Cree Aug. 5, 2024, 11:25 a.m. UTC | #1
On 03/08/2024 05:26, Jakub Kicinski wrote:
> Implement the separate create/modify/delete ops for RSS.
> 
> No problems with IDs - even tho RSS tables are per device
> the driver already seems to allocate IDs linearly per port.
> There's a translation table from per-port context ID
> to device context ID.
> 
> mvpp2 doesn't have a key for the hash, it defaults to
> an empty/previous indir table.

Given that, should this be after patch #6?  So as to make it
 obviously correct not to populate ethtool_rxfh_context_key(ctx)
 with the default context's key.

> @@ -5750,6 +5792,7 @@ static const struct net_device_ops mvpp2_netdev_ops = {
>  
>  static const struct ethtool_ops mvpp2_eth_tool_ops = {
>  	.cap_rss_ctx_supported	= true,
> +	.rxfh_max_context_id	= MVPP22_N_RSS_TABLES,

Max ID is inclusive, not exclusive, so I think this should be
 MVPP22_N_RSS_TABLES - 1?
Jakub Kicinski Aug. 5, 2024, 9:29 p.m. UTC | #2
On Mon, 5 Aug 2024 12:25:28 +0100 Edward Cree wrote:
> > mvpp2 doesn't have a key for the hash, it defaults to
> > an empty/previous indir table.  
> 
> Given that, should this be after patch #6?  So as to make it
>  obviously correct not to populate ethtool_rxfh_context_key(ctx)
>  with the default context's key.

It's a bit different. Patch 6 is about devices which have a key but 
the same key is used for all contexts. mvpp2 has no key at all
even for context 0 (get_rxfh_key_size is not defined).

> > @@ -5750,6 +5792,7 @@ static const struct net_device_ops mvpp2_netdev_ops = {
> >  
> >  static const struct ethtool_ops mvpp2_eth_tool_ops = {
> >  	.cap_rss_ctx_supported	= true,
> > +	.rxfh_max_context_id	= MVPP22_N_RSS_TABLES,  
> 
> Max ID is inclusive, not exclusive, so I think this should be
>  MVPP22_N_RSS_TABLES - 1?

I totally did check this before sending:

 * @rxfh_max_context_id: maximum (exclusive) supported RSS context ID.  If this
 *	is zero then the core may choose any (nonzero) ID, otherwise the core
 *	will only use IDs strictly less than this value, as the @rss_context
 *	argument to @create_rxfh_context and friends.

But you're right, the code acts as if it was inclusive :S

Coincidentally, the default also appears exclusive:

	u32 limit = ops->rxfh_max_context_id ?: U32_MAX;

U32_MAX can't be used, it has special meaning:

#define ETH_RXFH_CONTEXT_ALLOC		0xffffffff

These seem like net-worthy fixes, no?
Edward Cree Aug. 6, 2024, 1:28 p.m. UTC | #3
On 05/08/2024 22:29, Jakub Kicinski wrote:
> On Mon, 5 Aug 2024 12:25:28 +0100 Edward Cree wrote:
>>> mvpp2 doesn't have a key for the hash, it defaults to
>>> an empty/previous indir table.  
>>
>> Given that, should this be after patch #6?  So as to make it
>>  obviously correct not to populate ethtool_rxfh_context_key(ctx)
>>  with the default context's key.
> 
> It's a bit different. Patch 6 is about devices which have a key but 
> the same key is used for all contexts. mvpp2 has no key at all
> even for context 0 (get_rxfh_key_size is not defined).

Oh, I see.  Clarify that in the commit message, perhaps?

>>> @@ -5750,6 +5792,7 @@ static const struct net_device_ops mvpp2_netdev_ops = {
>>>  
>>>  static const struct ethtool_ops mvpp2_eth_tool_ops = {
>>>  	.cap_rss_ctx_supported	= true,
>>> +	.rxfh_max_context_id	= MVPP22_N_RSS_TABLES,  
>>
>> Max ID is inclusive, not exclusive, so I think this should be
>>  MVPP22_N_RSS_TABLES - 1?
> 
> I totally did check this before sending:
> 
>  * @rxfh_max_context_id: maximum (exclusive) supported RSS context ID.  If this
>  *	is zero then the core may choose any (nonzero) ID, otherwise the core
>  *	will only use IDs strictly less than this value, as the @rss_context
>  *	argument to @create_rxfh_context and friends.
> 
> But you're right, the code acts as if it was inclusive :S

Mea culpa, clearly when I was porting to XArray I must have
 confused myself over this.

> Coincidentally, the default also appears exclusive:
> 
> 	u32 limit = ops->rxfh_max_context_id ?: U32_MAX;
> 
> U32_MAX can't be used, it has special meaning:
> 
> #define ETH_RXFH_CONTEXT_ALLOC		0xffffffff

Given that both the default and drivers look more reasonable
 with an exclusive than an inclusive limit (I assume most
 drivers with a limit will have an N, like mvpp2 does, rather
 than a MAX), I guess we should change the code to match the
 doc rather than the other way around.

> These seem like net-worthy fixes, no?

Yep, agreed.  I'll send a patch.
Jakub Kicinski Aug. 6, 2024, 2:11 p.m. UTC | #4
On Tue, 6 Aug 2024 14:28:16 +0100 Edward Cree wrote:
> > Coincidentally, the default also appears exclusive:
> > 
> > 	u32 limit = ops->rxfh_max_context_id ?: U32_MAX;
> > 
> > U32_MAX can't be used, it has special meaning:
> > 
> > #define ETH_RXFH_CONTEXT_ALLOC		0xffffffff  
> 
> Given that both the default and drivers look more reasonable
>  with an exclusive than an inclusive limit (I assume most
>  drivers with a limit will have an N, like mvpp2 does, rather
>  than a MAX), I guess we should change the code to match the
>  doc rather than the other way around.

Somewhat unclear, because context 0 may not count, so to speak.
At least for bnxt using inclusive max context worked well.
But no preference, with the (obvious?) caveat that if we change 
the definition of the field to be exclusive we should rename it.
diff mbox series

Patch

diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_cls.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_cls.c
index 40aeaa7bd739..1641791a2d5b 100644
--- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_cls.c
+++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_cls.c
@@ -1522,29 +1522,19 @@  static int mvpp22_rss_context_create(struct mvpp2_port *port, u32 *rss_ctx)
 	return 0;
 }
 
-int mvpp22_port_rss_ctx_create(struct mvpp2_port *port, u32 *port_ctx)
+int mvpp22_port_rss_ctx_create(struct mvpp2_port *port, u32 port_ctx)
 {
 	u32 rss_ctx;
-	int ret, i;
+	int ret;
 
 	ret = mvpp22_rss_context_create(port, &rss_ctx);
 	if (ret)
 		return ret;
 
-	/* Find the first available context number in the port, starting from 1.
-	 * Context 0 on each port is reserved for the default context.
-	 */
-	for (i = 1; i < MVPP22_N_RSS_TABLES; i++) {
-		if (port->rss_ctx[i] < 0)
-			break;
-	}
-
-	if (i == MVPP22_N_RSS_TABLES)
+	if (WARN_ON_ONCE(port->rss_ctx[port_ctx] >= 0))
 		return -EINVAL;
 
-	port->rss_ctx[i] = rss_ctx;
-	*port_ctx = i;
-
+	port->rss_ctx[port_ctx] = rss_ctx;
 	return 0;
 }
 
diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_cls.h b/drivers/net/ethernet/marvell/mvpp2/mvpp2_cls.h
index 663157dc8062..85c9c6e80678 100644
--- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_cls.h
+++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_cls.h
@@ -264,7 +264,7 @@  int mvpp22_port_rss_init(struct mvpp2_port *port);
 int mvpp22_port_rss_enable(struct mvpp2_port *port);
 int mvpp22_port_rss_disable(struct mvpp2_port *port);
 
-int mvpp22_port_rss_ctx_create(struct mvpp2_port *port, u32 *rss_ctx);
+int mvpp22_port_rss_ctx_create(struct mvpp2_port *port, u32 rss_ctx);
 int mvpp22_port_rss_ctx_delete(struct mvpp2_port *port, u32 rss_ctx);
 
 int mvpp22_port_rss_ctx_indir_set(struct mvpp2_port *port, u32 rss_ctx,
diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
index 0d62a33afa80..90182f6fd9a1 100644
--- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
+++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
@@ -5696,38 +5696,80 @@  static int mvpp2_ethtool_get_rxfh(struct net_device *dev,
 	return ret;
 }
 
+static bool mvpp2_ethtool_rxfh_okay(struct mvpp2_port *port,
+				    const struct ethtool_rxfh_param *rxfh)
+{
+	if (!mvpp22_rss_is_supported(port))
+		return false;
+
+	if (rxfh->hfunc != ETH_RSS_HASH_NO_CHANGE &&
+	    rxfh->hfunc != ETH_RSS_HASH_CRC32)
+		return false;
+
+	if (rxfh->key)
+		return false;
+
+	return true;
+}
+
+static int mvpp2_create_rxfh_context(struct net_device *dev,
+				     struct ethtool_rxfh_context *ctx,
+				     const struct ethtool_rxfh_param *rxfh,
+				     struct netlink_ext_ack *extack)
+{
+	struct mvpp2_port *port = netdev_priv(dev);
+	int ret = 0;
+
+	if (!mvpp2_ethtool_rxfh_okay(port, rxfh))
+		return -EOPNOTSUPP;
+
+	ctx->hfunc = ETH_RSS_HASH_CRC32;
+
+	ret = mvpp22_port_rss_ctx_create(port, rxfh->rss_context);
+	if (ret)
+		return ret;
+
+	if (!rxfh->indir)
+		ret = mvpp22_port_rss_ctx_indir_get(port, rxfh->rss_context,
+						    ethtool_rxfh_context_indir(ctx));
+	else
+		ret = mvpp22_port_rss_ctx_indir_set(port, rxfh->rss_context,
+						    rxfh->indir);
+	return ret;
+}
+
+static int mvpp2_modify_rxfh_context(struct net_device *dev,
+				     struct ethtool_rxfh_context *ctx,
+				     const struct ethtool_rxfh_param *rxfh,
+				     struct netlink_ext_ack *extack)
+{
+	struct mvpp2_port *port = netdev_priv(dev);
+	int ret = 0;
+
+	if (!mvpp2_ethtool_rxfh_okay(port, rxfh))
+		return -EOPNOTSUPP;
+
+	if (rxfh->indir)
+		ret = mvpp22_port_rss_ctx_indir_set(port, rxfh->rss_context,
+						    rxfh->indir);
+	return ret;
+}
+
+static int mvpp2_remove_rxfh_context(struct net_device *dev,
+				     struct ethtool_rxfh_context *ctx,
+				     u32 rss_context,
+				     struct netlink_ext_ack *extack)
+{
+	struct mvpp2_port *port = netdev_priv(dev);
+
+	return mvpp22_port_rss_ctx_delete(port, rss_context);
+}
+
 static int mvpp2_ethtool_set_rxfh(struct net_device *dev,
 				  struct ethtool_rxfh_param *rxfh,
 				  struct netlink_ext_ack *extack)
 {
-	struct mvpp2_port *port = netdev_priv(dev);
-	u32 *rss_context = &rxfh->rss_context;
-	int ret = 0;
-
-	if (!mvpp22_rss_is_supported(port))
-		return -EOPNOTSUPP;
-
-	if (rxfh->hfunc != ETH_RSS_HASH_NO_CHANGE &&
-	    rxfh->hfunc != ETH_RSS_HASH_CRC32)
-		return -EOPNOTSUPP;
-
-	if (rxfh->key)
-		return -EOPNOTSUPP;
-
-	if (*rss_context && rxfh->rss_delete)
-		return mvpp22_port_rss_ctx_delete(port, *rss_context);
-
-	if (*rss_context == ETH_RXFH_CONTEXT_ALLOC) {
-		ret = mvpp22_port_rss_ctx_create(port, rss_context);
-		if (ret)
-			return ret;
-	}
-
-	if (rxfh->indir)
-		ret = mvpp22_port_rss_ctx_indir_set(port, *rss_context,
-						    rxfh->indir);
-
-	return ret;
+	return mvpp2_modify_rxfh_context(dev, NULL, rxfh, extack);
 }
 
 /* Device ops */
@@ -5750,6 +5792,7 @@  static const struct net_device_ops mvpp2_netdev_ops = {
 
 static const struct ethtool_ops mvpp2_eth_tool_ops = {
 	.cap_rss_ctx_supported	= true,
+	.rxfh_max_context_id	= MVPP22_N_RSS_TABLES,
 	.supported_coalesce_params = ETHTOOL_COALESCE_USECS |
 				     ETHTOOL_COALESCE_MAX_FRAMES,
 	.nway_reset		= mvpp2_ethtool_nway_reset,
@@ -5772,6 +5815,9 @@  static const struct ethtool_ops mvpp2_eth_tool_ops = {
 	.get_rxfh_indir_size	= mvpp2_ethtool_get_rxfh_indir_size,
 	.get_rxfh		= mvpp2_ethtool_get_rxfh,
 	.set_rxfh		= mvpp2_ethtool_set_rxfh,
+	.create_rxfh_context	= mvpp2_create_rxfh_context,
+	.modify_rxfh_context	= mvpp2_modify_rxfh_context,
+	.remove_rxfh_context	= mvpp2_remove_rxfh_context,
 };
 
 /* Used for PPv2.1, or PPv2.2 with the old Device Tree binding that