Skip to content

Commit

Permalink
Merge branch 'ethtool-rss-driver-tweaks'
Browse files Browse the repository at this point in the history
Jakub Kicinski says:

====================
ethtool: rss: driver tweaks and netlink context dumps

This series is a semi-related collection of RSS patches.
Main point is supporting dumping RSS contexts via ethtool netlink.
At present additional RSS contexts can be queried one by one, and
assuming user know the right IDs. This series uses the XArray
added by Ed to provide netlink dump support for ETHTOOL_GET_RSS.

Patch 1 is a trivial selftest debug patch.
Patch 2 coverts mvpp2 for no real reason other than that I had
	a grand plan of converting all drivers at some stage.
Patch 3 removes a now moot check from mlx5 so that all tests
	can pass.
Patch 4 and 5 make a bit used for context support optional,
	for easier grepping of drivers which need converting
	if nothing else.
Patch 6 OTOH adds a new cap bit; some devices don't support
	using a different key per context and currently act
	in surprising ways.
Patch 7 and 8 update the RSS netlink code to use XArray.
Patch 9 and 10 add support for dumping contexts.
Patch 11 and 12 are small adjustments to spec and a new test.

I'm getting distracted with other work, so probably won't have
the time soon to complete next steps, but things which are missing
are (and some of these may be bad ideas):

 - better discovery

   Some sort of API to tell the user who many contexts the device
   can create. Upper bound, devices often share contexts between
   ports etc. so it's hard to tell exactly and upfront number of
   contexts for a netdev. But order of magnitude (4 vs 10s) may
   be enough for container management system to know whether to bother.

 - create/modify/delete via netlink

   The only question here is how to handle all the tricky IOCTL
   legacy. "No change" maps trivially to attribute not present.
   "reset" (indir_size = 0) probably needs to be a new NLA_FLAG?

 - better table size handling

   The current API assumes the LUT has fixed size, which isn't
   true for modern devices. We should have better APIs for the
   drivers to resize the tables, and in user facing API -
   the ability to specify pattern and min size rather than
   exact table expected (sort of like ethtool CLI already does).

 - recounted / socket-bound contexts

   Support for contexts which get "cleaned up" when their parent
   netlink socket gets closed. The major catch is that ntuple
   filters (which we don't currently track) depend on the context,
   so we need auto-removal for both.

v5:
 - fix build
v4: https://lore.kernel.org/[email protected]
 - adjust to the meaning of max context from net
v3: https://lore.kernel.org/[email protected]
 - quite a few code comments and commit message changes
 - mvpp2: fix interpretation of max_context_id (I'll take care of
   the net -> net-next merge as needed)
 - filter by ifindex in the selftest
v2: https://lore.kernel.org/[email protected]
 - fix bugs and build in mvpp2
v1: https://lore.kernel.org/[email protected]
====================

Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
davem330 committed Aug 12, 2024
2 parents 6b8a024 + c1ad8ef commit fe1f433
Show file tree
Hide file tree
Showing 18 changed files with 432 additions and 81 deletions.
14 changes: 12 additions & 2 deletions Documentation/netlink/specs/ethtool.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1022,12 +1022,16 @@ attribute-sets:
-
name: indir
type: binary
sub-type: u32
-
name: hkey
type: binary
-
name: input_xfrm
type: u32
-
name: start-context
type: u32
-
name: plca
attributes:
Expand Down Expand Up @@ -1749,19 +1753,25 @@ operations:

attribute-set: rss

do: &rss-get-op
do:
request:
attributes:
- header
- context
reply:
reply: &rss-reply
attributes:
- header
- context
- hfunc
- indir
- hkey
- input_xfrm
dump:
request:
attributes:
- header
- start-context
reply: *rss-reply
-
name: plca-get-cfg
doc: Get PLCA params.
Expand Down
12 changes: 10 additions & 2 deletions Documentation/networking/ethtool-netlink.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1866,10 +1866,18 @@ RSS context of an interface similar to ``ETHTOOL_GRSSH`` ioctl request.

Request contents:

===================================== ====== ==========================
===================================== ====== ============================
``ETHTOOL_A_RSS_HEADER`` nested request header
``ETHTOOL_A_RSS_CONTEXT`` u32 context number
===================================== ====== ==========================
``ETHTOOL_A_RSS_START_CONTEXT`` u32 start context number (dumps)
===================================== ====== ============================

``ETHTOOL_A_RSS_CONTEXT`` specifies which RSS context number to query,
if not set context 0 (the main context) is queried. Dumps can be filtered
by device (only listing contexts of a given netdev). Filtering single
context number is not supported but ``ETHTOOL_A_RSS_START_CONTEXT``
can be used to start dumping context from the given number (primarily
used to ignore context 0s and only dump additional contexts).

Kernel response contents:

Expand Down
2 changes: 1 addition & 1 deletion drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
Original file line number Diff line number Diff line change
Expand Up @@ -5289,7 +5289,7 @@ void bnxt_ethtool_free(struct bnxt *bp)

const struct ethtool_ops bnxt_ethtool_ops = {
.cap_link_lanes_supported = 1,
.cap_rss_ctx_supported = 1,
.rxfh_per_ctx_key = 1,
.rxfh_max_num_contexts = BNXT_MAX_ETH_RSS_CTX + 1,
.rxfh_indir_space = BNXT_MAX_RSS_TABLE_ENTRIES_P5,
.rxfh_priv_size = sizeof(struct bnxt_rss_ctx),
Expand Down
1 change: 1 addition & 0 deletions drivers/net/ethernet/intel/ice/ice_ethtool.c
Original file line number Diff line number Diff line change
Expand Up @@ -4725,6 +4725,7 @@ static const struct ethtool_ops ice_ethtool_ops = {
ETHTOOL_COALESCE_USE_ADAPTIVE |
ETHTOOL_COALESCE_RX_USECS_HIGH,
.cap_rss_sym_xor_supported = true,
.rxfh_per_ctx_key = true,
.get_link_ksettings = ice_get_link_ksettings,
.set_link_ksettings = ice_set_link_ksettings,
.get_fec_stats = ice_get_fec_stats,
Expand Down
18 changes: 4 additions & 14 deletions drivers/net/ethernet/marvell/mvpp2/mvpp2_cls.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down
2 changes: 1 addition & 1 deletion drivers/net/ethernet/marvell/mvpp2/mvpp2_cls.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
83 changes: 64 additions & 19 deletions drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -5696,40 +5696,82 @@ static int mvpp2_ethtool_get_rxfh(struct net_device *dev,
return ret;
}

static int mvpp2_ethtool_set_rxfh(struct net_device *dev,
struct ethtool_rxfh_param *rxfh,
struct netlink_ext_ack *extack)
static bool mvpp2_ethtool_rxfh_okay(struct mvpp2_port *port,
const struct ethtool_rxfh_param *rxfh)
{
struct mvpp2_port *port = netdev_priv(dev);
u32 *rss_context = &rxfh->rss_context;
int ret = 0;

if (!mvpp22_rss_is_supported(port))
return -EOPNOTSUPP;
return false;

if (rxfh->hfunc != ETH_RSS_HASH_NO_CHANGE &&
rxfh->hfunc != ETH_RSS_HASH_CRC32)
return -EOPNOTSUPP;
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;

if (*rss_context && rxfh->rss_delete)
return mvpp22_port_rss_ctx_delete(port, *rss_context);
ctx->hfunc = ETH_RSS_HASH_CRC32;

if (*rss_context == ETH_RXFH_CONTEXT_ALLOC) {
ret = mvpp22_port_rss_ctx_create(port, rss_context);
if (ret)
return ret;
}
ret = mvpp22_port_rss_ctx_create(port, rxfh->rss_context);
if (ret)
return ret;

if (rxfh->indir)
ret = mvpp22_port_rss_ctx_indir_set(port, *rss_context,
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)
{
return mvpp2_modify_rxfh_context(dev, NULL, rxfh, extack);
}

/* Device ops */

static const struct net_device_ops mvpp2_netdev_ops = {
Expand All @@ -5749,7 +5791,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_num_contexts = MVPP22_N_RSS_TABLES,
.supported_coalesce_params = ETHTOOL_COALESCE_USECS |
ETHTOOL_COALESCE_MAX_FRAMES,
.nway_reset = mvpp2_ethtool_nway_reset,
Expand All @@ -5772,6 +5814,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
Expand Down
13 changes: 1 addition & 12 deletions drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
Original file line number Diff line number Diff line change
Expand Up @@ -433,7 +433,6 @@ int mlx5e_ethtool_set_channels(struct mlx5e_priv *priv,
unsigned int count = ch->combined_count;
struct mlx5e_params new_params;
bool arfs_enabled;
int rss_cnt;
bool opened;
int err = 0;

Expand Down Expand Up @@ -487,17 +486,6 @@ int mlx5e_ethtool_set_channels(struct mlx5e_priv *priv,
goto out;
}

/* Don't allow changing the number of channels if non-default RSS contexts exist,
* the kernel doesn't protect against set_channels operations that break them.
*/
rss_cnt = mlx5e_rx_res_rss_cnt(priv->rx_res) - 1;
if (rss_cnt) {
err = -EINVAL;
netdev_err(priv->netdev, "%s: Non-default RSS contexts exist (%d), cannot change the number of channels\n",
__func__, rss_cnt);
goto out;
}

/* Don't allow changing the number of channels if MQPRIO mode channel offload is active,
* because it defines a partition over the channels queues.
*/
Expand Down Expand Up @@ -2607,6 +2595,7 @@ static void mlx5e_get_ts_stats(struct net_device *netdev,

const struct ethtool_ops mlx5e_ethtool_ops = {
.cap_rss_ctx_supported = true,
.rxfh_per_ctx_key = true,
.supported_coalesce_params = ETHTOOL_COALESCE_USECS |
ETHTOOL_COALESCE_MAX_FRAMES |
ETHTOOL_COALESCE_USE_ADAPTIVE |
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/ethernet/sfc/ef100_ethtool.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ ef100_ethtool_get_ringparam(struct net_device *net_dev,
/* Ethtool options available
*/
const struct ethtool_ops ef100_ethtool_ops = {
.cap_rss_ctx_supported = true,
.get_drvinfo = efx_ethtool_get_drvinfo,
.get_msglevel = efx_ethtool_get_msglevel,
.set_msglevel = efx_ethtool_set_msglevel,
Expand All @@ -59,6 +58,7 @@ const struct ethtool_ops ef100_ethtool_ops = {

.get_rxfh_indir_size = efx_ethtool_get_rxfh_indir_size,
.get_rxfh_key_size = efx_ethtool_get_rxfh_key_size,
.rxfh_per_ctx_key = true,
.rxfh_priv_size = sizeof(struct efx_rss_context_priv),
.get_rxfh = efx_ethtool_get_rxfh,
.set_rxfh = efx_ethtool_set_rxfh,
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/ethernet/sfc/ethtool.c
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,6 @@ static int efx_ethtool_get_ts_info(struct net_device *net_dev,
}

const struct ethtool_ops efx_ethtool_ops = {
.cap_rss_ctx_supported = true,
.supported_coalesce_params = ETHTOOL_COALESCE_USECS |
ETHTOOL_COALESCE_USECS_IRQ |
ETHTOOL_COALESCE_USE_ADAPTIVE_RX,
Expand Down Expand Up @@ -268,6 +267,7 @@ const struct ethtool_ops efx_ethtool_ops = {
.set_rxnfc = efx_ethtool_set_rxnfc,
.get_rxfh_indir_size = efx_ethtool_get_rxfh_indir_size,
.get_rxfh_key_size = efx_ethtool_get_rxfh_key_size,
.rxfh_per_ctx_key = true,
.rxfh_priv_size = sizeof(struct efx_rss_context_priv),
.get_rxfh = efx_ethtool_get_rxfh,
.set_rxfh = efx_ethtool_set_rxfh,
Expand Down
7 changes: 6 additions & 1 deletion include/linux/ethtool.h
Original file line number Diff line number Diff line change
Expand Up @@ -727,9 +727,13 @@ struct kernel_ethtool_ts_info {
* @cap_link_lanes_supported: indicates if the driver supports lanes
* parameter.
* @cap_rss_ctx_supported: indicates if the driver supports RSS
* contexts.
* contexts via legacy API, drivers implementing @create_rxfh_context
* do not have to set this bit.
* @cap_rss_sym_xor_supported: indicates if the driver supports symmetric-xor
* RSS.
* @rxfh_per_ctx_key: device supports setting different RSS key for each
* additional context. Netlink API should report hfunc, key, and input_xfrm
* for every context, not just context 0.
* @rxfh_indir_space: max size of RSS indirection tables, if indirection table
* size as returned by @get_rxfh_indir_size may change during lifetime
* of the device. Leave as 0 if the table size is constant.
Expand Down Expand Up @@ -951,6 +955,7 @@ struct ethtool_ops {
u32 cap_link_lanes_supported:1;
u32 cap_rss_ctx_supported:1;
u32 cap_rss_sym_xor_supported:1;
u32 rxfh_per_ctx_key:1;
u32 rxfh_indir_space;
u16 rxfh_key_space;
u16 rxfh_priv_size;
Expand Down
1 change: 1 addition & 0 deletions include/uapi/linux/ethtool_netlink.h
Original file line number Diff line number Diff line change
Expand Up @@ -965,6 +965,7 @@ enum {
ETHTOOL_A_RSS_INDIR, /* binary */
ETHTOOL_A_RSS_HKEY, /* binary */
ETHTOOL_A_RSS_INPUT_XFRM, /* u32 */
ETHTOOL_A_RSS_START_CONTEXT, /* u32 */

__ETHTOOL_A_RSS_CNT,
ETHTOOL_A_RSS_MAX = (__ETHTOOL_A_RSS_CNT - 1),
Expand Down
Loading

0 comments on commit fe1f433

Please sign in to comment.