Skip to content

Commit 847a8ab

Browse files
Edward Creekuba-moo
authored andcommitted
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 <[email protected]> Reviewed-by: Przemek Kitszel <[email protected]> Link: https://patch.msgid.link/45f1fe61df2163c091ec394c9f52000c8b16cc3b.1719502240.git.ecree.xilinx@gmail.com Signed-off-by: Jakub Kicinski <[email protected]>
1 parent eac9122 commit 847a8ab

File tree

3 files changed

+79
-13
lines changed

3 files changed

+79
-13
lines changed

include/linux/ethtool.h

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -723,6 +723,10 @@ struct ethtool_rxfh_param {
723723
* RSS.
724724
* @rxfh_priv_size: size of the driver private data area the core should
725725
* allocate for an RSS context (in &struct ethtool_rxfh_context).
726+
* @rxfh_max_context_id: maximum (exclusive) supported RSS context ID. If this
727+
* is zero then the core may choose any (nonzero) ID, otherwise the core
728+
* will only use IDs strictly less than this value, as the @rss_context
729+
* argument to @create_rxfh_context and friends.
726730
* @supported_coalesce_params: supported types of interrupt coalescing.
727731
* @supported_ring_params: supported ring params.
728732
* @get_drvinfo: Report driver/device information. Modern drivers no
@@ -819,6 +823,32 @@ struct ethtool_rxfh_param {
819823
* will remain unchanged.
820824
* Returns a negative error code or zero. An error code must be returned
821825
* if at least one unsupported change was requested.
826+
* @create_rxfh_context: Create a new RSS context with the specified RX flow
827+
* hash indirection table, hash key, and hash function.
828+
* The &struct ethtool_rxfh_context for this context is passed in @ctx;
829+
* note that the indir table, hkey and hfunc are not yet populated as
830+
* of this call. The driver does not need to update these; the core
831+
* will do so if this op succeeds.
832+
* However, if @rxfh.indir is set to %NULL, the driver must update the
833+
* indir table in @ctx with the (default or inherited) table actually in
834+
* use; similarly, if @rxfh.key is %NULL, @rxfh.hfunc is
835+
* %ETH_RSS_HASH_NO_CHANGE, or @rxfh.input_xfrm is %RXH_XFRM_NO_CHANGE,
836+
* the driver should update the corresponding information in @ctx.
837+
* If the driver provides this method, it must also provide
838+
* @modify_rxfh_context and @remove_rxfh_context.
839+
* Returns a negative error code or zero.
840+
* @modify_rxfh_context: Reconfigure the specified RSS context. Allows setting
841+
* the contents of the RX flow hash indirection table, hash key, and/or
842+
* hash function associated with the given context.
843+
* Parameters which are set to %NULL or zero will remain unchanged.
844+
* The &struct ethtool_rxfh_context for this context is passed in @ctx;
845+
* note that it will still contain the *old* settings. The driver does
846+
* not need to update these; the core will do so if this op succeeds.
847+
* Returns a negative error code or zero. An error code must be returned
848+
* if at least one unsupported change was requested.
849+
* @remove_rxfh_context: Remove the specified RSS context.
850+
* The &struct ethtool_rxfh_context for this context is passed in @ctx.
851+
* Returns a negative error code or zero.
822852
* @get_channels: Get number of channels.
823853
* @set_channels: Set number of channels. Returns a negative error code or
824854
* zero.
@@ -909,6 +939,7 @@ struct ethtool_ops {
909939
u32 cap_rss_ctx_supported:1;
910940
u32 cap_rss_sym_xor_supported:1;
911941
u16 rxfh_priv_size;
942+
u32 rxfh_max_context_id;
912943
u32 supported_coalesce_params;
913944
u32 supported_ring_params;
914945
void (*get_drvinfo)(struct net_device *, struct ethtool_drvinfo *);
@@ -971,6 +1002,15 @@ struct ethtool_ops {
9711002
int (*get_rxfh)(struct net_device *, struct ethtool_rxfh_param *);
9721003
int (*set_rxfh)(struct net_device *, struct ethtool_rxfh_param *,
9731004
struct netlink_ext_ack *extack);
1005+
int (*create_rxfh_context)(struct net_device *,
1006+
struct ethtool_rxfh_context *ctx,
1007+
const struct ethtool_rxfh_param *rxfh);
1008+
int (*modify_rxfh_context)(struct net_device *,
1009+
struct ethtool_rxfh_context *ctx,
1010+
const struct ethtool_rxfh_param *rxfh);
1011+
int (*remove_rxfh_context)(struct net_device *,
1012+
struct ethtool_rxfh_context *ctx,
1013+
u32 rss_context);
9741014
void (*get_channels)(struct net_device *, struct ethtool_channels *);
9751015
int (*set_channels)(struct net_device *, struct ethtool_channels *);
9761016
int (*get_dump_flag)(struct net_device *, struct ethtool_dump *);

net/core/dev.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11254,7 +11254,11 @@ static void netdev_rss_contexts_free(struct net_device *dev)
1125411254
rxfh.rss_delete = true;
1125511255

1125611256
xa_erase(&dev->ethtool->rss_ctx, context);
11257-
dev->ethtool_ops->set_rxfh(dev, &rxfh, NULL);
11257+
if (dev->ethtool_ops->create_rxfh_context)
11258+
dev->ethtool_ops->remove_rxfh_context(dev, ctx,
11259+
context);
11260+
else
11261+
dev->ethtool_ops->set_rxfh(dev, &rxfh, NULL);
1125811262
kfree(ctx);
1125911263
}
1126011264
xa_destroy(&dev->ethtool->rss_ctx);

net/ethtool/ioctl.c

Lines changed: 34 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1395,9 +1395,24 @@ static noinline_for_stack int ethtool_set_rxfh(struct net_device *dev,
13951395
}
13961396
ctx->indir_size = dev_indir_size;
13971397
ctx->key_size = dev_key_size;
1398-
ctx->hfunc = rxfh.hfunc;
1399-
ctx->input_xfrm = rxfh.input_xfrm;
14001398
ctx->priv_size = ops->rxfh_priv_size;
1399+
/* Initialise to an empty context */
1400+
ctx->hfunc = ETH_RSS_HASH_NO_CHANGE;
1401+
ctx->input_xfrm = RXH_XFRM_NO_CHANGE;
1402+
if (ops->create_rxfh_context) {
1403+
u32 limit = ops->rxfh_max_context_id ?: U32_MAX;
1404+
u32 ctx_id;
1405+
1406+
/* driver uses new API, core allocates ID */
1407+
ret = xa_alloc(&dev->ethtool->rss_ctx, &ctx_id, ctx,
1408+
XA_LIMIT(1, limit), GFP_KERNEL_ACCOUNT);
1409+
if (ret < 0) {
1410+
kfree(ctx);
1411+
goto out;
1412+
}
1413+
WARN_ON(!ctx_id); /* can't happen */
1414+
rxfh.rss_context = ctx_id;
1415+
}
14011416
} else if (rxfh.rss_context) {
14021417
ctx = xa_load(&dev->ethtool->rss_ctx, rxfh.rss_context);
14031418
if (!ctx) {
@@ -1409,11 +1424,24 @@ static noinline_for_stack int ethtool_set_rxfh(struct net_device *dev,
14091424
rxfh_dev.rss_context = rxfh.rss_context;
14101425
rxfh_dev.input_xfrm = rxfh.input_xfrm;
14111426

1412-
ret = ops->set_rxfh(dev, &rxfh_dev, extack);
1413-
if (ret) {
1427+
if (rxfh.rss_context && ops->create_rxfh_context) {
14141428
if (create)
1429+
ret = ops->create_rxfh_context(dev, ctx, &rxfh_dev);
1430+
else if (rxfh_dev.rss_delete)
1431+
ret = ops->remove_rxfh_context(dev, ctx,
1432+
rxfh.rss_context);
1433+
else
1434+
ret = ops->modify_rxfh_context(dev, ctx, &rxfh_dev);
1435+
} else {
1436+
ret = ops->set_rxfh(dev, &rxfh_dev, extack);
1437+
}
1438+
if (ret) {
1439+
if (create) {
14151440
/* failed to create, free our new tracking entry */
1441+
if (ops->create_rxfh_context)
1442+
xa_erase(&dev->ethtool->rss_ctx, rxfh.rss_context);
14161443
kfree(ctx);
1444+
}
14171445
goto out;
14181446
}
14191447

@@ -1429,12 +1457,8 @@ static noinline_for_stack int ethtool_set_rxfh(struct net_device *dev,
14291457
dev->priv_flags |= IFF_RXFH_CONFIGURED;
14301458
}
14311459
/* Update rss_ctx tracking */
1432-
if (create) {
1433-
/* Ideally this should happen before calling the driver,
1434-
* so that we can fail more cleanly; but we don't have the
1435-
* context ID until the driver picks it, so we have to
1436-
* wait until after.
1437-
*/
1460+
if (create && !ops->create_rxfh_context) {
1461+
/* driver uses old API, it chose context ID */
14381462
if (WARN_ON(xa_load(&dev->ethtool->rss_ctx, rxfh.rss_context))) {
14391463
/* context ID reused, our tracking is screwed */
14401464
kfree(ctx);
@@ -1446,8 +1470,6 @@ static noinline_for_stack int ethtool_set_rxfh(struct net_device *dev,
14461470
kfree(ctx);
14471471
goto out;
14481472
}
1449-
ctx->indir_configured = rxfh.indir_size != ETH_RXFH_INDIR_NO_CHANGE;
1450-
ctx->key_configured = !!rxfh.key_size;
14511473
}
14521474
if (rxfh_dev.rss_delete) {
14531475
WARN_ON(xa_erase(&dev->ethtool->rss_ctx, rxfh.rss_context) != ctx);

0 commit comments

Comments
 (0)