diff options
author | Edward Cree | 2024-06-27 16:33:49 +0100 |
---|---|---|
committer | Jakub Kicinski | 2024-06-28 18:53:21 -0700 |
commit | 847a8ab186767be6ee95643f9739fa9d0f839589 (patch) | |
tree | d4bc2f7ff295aa6e933b960609f61a5c2dc8e1b5 /net | |
parent | eac9122f0c41b832065e01977c34946ec8e76c24 (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.c | 6 | ||||
-rw-r--r-- | net/ethtool/ioctl.c | 46 |
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); |