aboutsummaryrefslogtreecommitdiff
path: root/net
diff options
context:
space:
mode:
authorEdward Cree2024-06-27 16:33:49 +0100
committerJakub Kicinski2024-06-28 18:53:21 -0700
commit847a8ab186767be6ee95643f9739fa9d0f839589 (patch)
treed4bc2f7ff295aa6e933b960609f61a5c2dc8e1b5 /net
parenteac9122f0c41b832065e01977c34946ec8e76c24 (diff)
net: ethtool: let the core choose RSS context IDs
Add a new API to create/modify/remove RSS contexts, that passes in the newly-chosen context ID (not as a pointer) rather than leaving the driver to choose it on create. Also pass in the ctx, allowing drivers to easily use its private data area to store their hardware-specific state. Keep the existing .set_rxfh API for now as a fallback, but deprecate it for custom contexts (rss_context != 0). Signed-off-by: Edward Cree <ecree.xilinx@gmail.com> Reviewed-by: Przemek Kitszel <przemyslaw.kitszel@intel.com> Link: https://patch.msgid.link/45f1fe61df2163c091ec394c9f52000c8b16cc3b.1719502240.git.ecree.xilinx@gmail.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Diffstat (limited to 'net')
-rw-r--r--net/core/dev.c6
-rw-r--r--net/ethtool/ioctl.c46
2 files changed, 39 insertions, 13 deletions
diff --git a/net/core/dev.c b/net/core/dev.c
index bce810f8ae53..8481dc4f2196 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -11254,7 +11254,11 @@ static void netdev_rss_contexts_free(struct net_device *dev)
rxfh.rss_delete = true;
xa_erase(&dev->ethtool->rss_ctx, context);
- dev->ethtool_ops->set_rxfh(dev, &rxfh, NULL);
+ if (dev->ethtool_ops->create_rxfh_context)
+ dev->ethtool_ops->remove_rxfh_context(dev, ctx,
+ context);
+ else
+ dev->ethtool_ops->set_rxfh(dev, &rxfh, NULL);
kfree(ctx);
}
xa_destroy(&dev->ethtool->rss_ctx);
diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c
index e901a20e97f5..46b50ddde013 100644
--- a/net/ethtool/ioctl.c
+++ b/net/ethtool/ioctl.c
@@ -1395,9 +1395,24 @@ static noinline_for_stack int ethtool_set_rxfh(struct net_device *dev,
}
ctx->indir_size = dev_indir_size;
ctx->key_size = dev_key_size;
- ctx->hfunc = rxfh.hfunc;
- ctx->input_xfrm = rxfh.input_xfrm;
ctx->priv_size = ops->rxfh_priv_size;
+ /* Initialise to an empty context */
+ ctx->hfunc = ETH_RSS_HASH_NO_CHANGE;
+ ctx->input_xfrm = RXH_XFRM_NO_CHANGE;
+ if (ops->create_rxfh_context) {
+ u32 limit = ops->rxfh_max_context_id ?: U32_MAX;
+ u32 ctx_id;
+
+ /* driver uses new API, core allocates ID */
+ ret = xa_alloc(&dev->ethtool->rss_ctx, &ctx_id, ctx,
+ XA_LIMIT(1, limit), GFP_KERNEL_ACCOUNT);
+ if (ret < 0) {
+ kfree(ctx);
+ goto out;
+ }
+ WARN_ON(!ctx_id); /* can't happen */
+ rxfh.rss_context = ctx_id;
+ }
} else if (rxfh.rss_context) {
ctx = xa_load(&dev->ethtool->rss_ctx, rxfh.rss_context);
if (!ctx) {
@@ -1409,11 +1424,24 @@ static noinline_for_stack int ethtool_set_rxfh(struct net_device *dev,
rxfh_dev.rss_context = rxfh.rss_context;
rxfh_dev.input_xfrm = rxfh.input_xfrm;
- ret = ops->set_rxfh(dev, &rxfh_dev, extack);
- if (ret) {
+ if (rxfh.rss_context && ops->create_rxfh_context) {
if (create)
+ ret = ops->create_rxfh_context(dev, ctx, &rxfh_dev);
+ else if (rxfh_dev.rss_delete)
+ ret = ops->remove_rxfh_context(dev, ctx,
+ rxfh.rss_context);
+ else
+ ret = ops->modify_rxfh_context(dev, ctx, &rxfh_dev);
+ } else {
+ ret = ops->set_rxfh(dev, &rxfh_dev, extack);
+ }
+ if (ret) {
+ if (create) {
/* failed to create, free our new tracking entry */
+ if (ops->create_rxfh_context)
+ xa_erase(&dev->ethtool->rss_ctx, rxfh.rss_context);
kfree(ctx);
+ }
goto out;
}
@@ -1429,12 +1457,8 @@ static noinline_for_stack int ethtool_set_rxfh(struct net_device *dev,
dev->priv_flags |= IFF_RXFH_CONFIGURED;
}
/* Update rss_ctx tracking */
- if (create) {
- /* Ideally this should happen before calling the driver,
- * so that we can fail more cleanly; but we don't have the
- * context ID until the driver picks it, so we have to
- * wait until after.
- */
+ if (create && !ops->create_rxfh_context) {
+ /* driver uses old API, it chose context ID */
if (WARN_ON(xa_load(&dev->ethtool->rss_ctx, rxfh.rss_context))) {
/* context ID reused, our tracking is screwed */
kfree(ctx);
@@ -1446,8 +1470,6 @@ static noinline_for_stack int ethtool_set_rxfh(struct net_device *dev,
kfree(ctx);
goto out;
}
- ctx->indir_configured = rxfh.indir_size != ETH_RXFH_INDIR_NO_CHANGE;
- ctx->key_configured = !!rxfh.key_size;
}
if (rxfh_dev.rss_delete) {
WARN_ON(xa_erase(&dev->ethtool->rss_ctx, rxfh.rss_context) != ctx);