Merge branch 'net-migrate-remaining-drivers-to-dedicated-_rxfh_context-ops'

Jakub Kicinski says:

====================
net: migrate remaining drivers to dedicated _rxfh_context ops

Around a year ago Ed added dedicated ops for managing RSS contexts.
This significantly improved the clarity of the driver facing API.
Migrate the remaining 3 drivers and remove the old way of muxing
the RSS context operations via .set_rxfh().

v2: https://lore.kernel.org/20250702030606.1776293-1-kuba@kernel.org
v1: https://lore.kernel.org/20250630160953.1093267-1-kuba@kernel.org
====================

Link: https://patch.msgid.link/20250707184115.2285277-1-kuba@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Jakub Kicinski 2025-07-08 11:56:42 -07:00
commit 0a49abff43
15 changed files with 250 additions and 265 deletions

View File

@ -3591,11 +3591,10 @@ static int
ice_get_rxfh(struct net_device *netdev, struct ethtool_rxfh_param *rxfh)
{
struct ice_netdev_priv *np = netdev_priv(netdev);
u32 rss_context = rxfh->rss_context;
struct ice_vsi *vsi = np->vsi;
struct ice_pf *pf = vsi->back;
u16 qcount, offset;
int err, num_tc, i;
int err, i;
u8 *lut;
if (!test_bit(ICE_FLAG_RSS_ENA, pf->flags)) {
@ -3603,24 +3602,8 @@ ice_get_rxfh(struct net_device *netdev, struct ethtool_rxfh_param *rxfh)
return -EOPNOTSUPP;
}
if (rss_context && !ice_is_adq_active(pf)) {
netdev_err(netdev, "RSS context cannot be non-zero when ADQ is not configured.\n");
return -EINVAL;
}
qcount = vsi->mqprio_qopt.qopt.count[rss_context];
offset = vsi->mqprio_qopt.qopt.offset[rss_context];
if (rss_context && ice_is_adq_active(pf)) {
num_tc = vsi->mqprio_qopt.qopt.num_tc;
if (rss_context >= num_tc) {
netdev_err(netdev, "RSS context:%d > num_tc:%d\n",
rss_context, num_tc);
return -EINVAL;
}
/* Use channel VSI of given TC */
vsi = vsi->tc_map_vsi[rss_context];
}
qcount = vsi->mqprio_qopt.qopt.count[0];
offset = vsi->mqprio_qopt.qopt.offset[0];
rxfh->hfunc = ETH_RSS_HASH_TOP;
if (vsi->rss_hfunc == ICE_AQ_VSI_Q_OPT_RSS_HASH_SYM_TPLZ)
@ -3680,9 +3663,6 @@ ice_set_rxfh(struct net_device *netdev, struct ethtool_rxfh_param *rxfh,
rxfh->hfunc != ETH_RSS_HASH_TOP)
return -EOPNOTSUPP;
if (rxfh->rss_context)
return -EOPNOTSUPP;
if (!test_bit(ICE_FLAG_RSS_ENA, pf->flags)) {
/* RSS not supported return error here */
netdev_warn(netdev, "RSS is not configured on this VSI!\n");
@ -4750,12 +4730,10 @@ static int ice_repr_ethtool_reset(struct net_device *dev, u32 *flags)
}
static const struct ethtool_ops ice_ethtool_ops = {
.cap_rss_ctx_supported = true,
.supported_coalesce_params = ETHTOOL_COALESCE_USECS |
ETHTOOL_COALESCE_USE_ADAPTIVE |
ETHTOOL_COALESCE_RX_USECS_HIGH,
.supported_input_xfrm = RXH_XFRM_SYM_XOR,
.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,

View File

@ -318,21 +318,20 @@ int otx2_set_flowkey_cfg(struct otx2_nic *pfvf)
return err;
}
int otx2_set_rss_table(struct otx2_nic *pfvf, int ctx_id)
int otx2_set_rss_table(struct otx2_nic *pfvf, int ctx_id, const u32 *ind_tbl)
{
struct otx2_rss_info *rss = &pfvf->hw.rss_info;
const int index = rss->rss_size * ctx_id;
struct mbox *mbox = &pfvf->mbox;
struct otx2_rss_ctx *rss_ctx;
struct nix_aq_enq_req *aq;
int idx, err;
mutex_lock(&mbox->lock);
rss_ctx = rss->rss_ctx[ctx_id];
ind_tbl = ind_tbl ?: rss->ind_tbl;
/* Get memory to put this msg */
for (idx = 0; idx < rss->rss_size; idx++) {
/* Ignore the queue if AF_XDP zero copy is enabled */
if (test_bit(rss_ctx->ind_tbl[idx], pfvf->af_xdp_zc_qidx))
if (test_bit(ind_tbl[idx], pfvf->af_xdp_zc_qidx))
continue;
aq = otx2_mbox_alloc_msg_nix_aq_enq(mbox);
@ -352,7 +351,7 @@ int otx2_set_rss_table(struct otx2_nic *pfvf, int ctx_id)
}
}
aq->rss.rq = rss_ctx->ind_tbl[idx];
aq->rss.rq = ind_tbl[idx];
/* Fill AQ info */
aq->qidx = index + idx;
@ -390,30 +389,22 @@ void otx2_set_rss_key(struct otx2_nic *pfvf)
int otx2_rss_init(struct otx2_nic *pfvf)
{
struct otx2_rss_info *rss = &pfvf->hw.rss_info;
struct otx2_rss_ctx *rss_ctx;
int idx, ret = 0;
rss->rss_size = sizeof(*rss->rss_ctx[DEFAULT_RSS_CONTEXT_GROUP]);
rss->rss_size = sizeof(*rss->ind_tbl);
/* Init RSS key if it is not setup already */
if (!rss->enable)
netdev_rss_key_fill(rss->key, sizeof(rss->key));
otx2_set_rss_key(pfvf);
if (!netif_is_rxfh_configured(pfvf->netdev)) {
/* Set RSS group 0 as default indirection table */
rss->rss_ctx[DEFAULT_RSS_CONTEXT_GROUP] = kzalloc(rss->rss_size,
GFP_KERNEL);
if (!rss->rss_ctx[DEFAULT_RSS_CONTEXT_GROUP])
return -ENOMEM;
rss_ctx = rss->rss_ctx[DEFAULT_RSS_CONTEXT_GROUP];
if (!netif_is_rxfh_configured(pfvf->netdev))
for (idx = 0; idx < rss->rss_size; idx++)
rss_ctx->ind_tbl[idx] =
rss->ind_tbl[idx] =
ethtool_rxfh_indir_default(idx,
pfvf->hw.rx_queues);
}
ret = otx2_set_rss_table(pfvf, DEFAULT_RSS_CONTEXT_GROUP);
ret = otx2_set_rss_table(pfvf, DEFAULT_RSS_CONTEXT_GROUP, NULL);
if (ret)
return ret;

View File

@ -93,10 +93,6 @@ struct otx2_lmt_info {
u64 lmt_addr;
u16 lmt_id;
};
/* RSS configuration */
struct otx2_rss_ctx {
u8 ind_tbl[MAX_RSS_INDIR_TBL_SIZE];
};
struct otx2_rss_info {
u8 enable;
@ -104,7 +100,7 @@ struct otx2_rss_info {
u16 rss_size;
#define RSS_HASH_KEY_SIZE 44 /* 352 bit key */
u8 key[RSS_HASH_KEY_SIZE];
struct otx2_rss_ctx *rss_ctx[MAX_RSS_GROUPS];
u32 ind_tbl[MAX_RSS_INDIR_TBL_SIZE];
};
/* NIX (or NPC) RX errors */
@ -1067,7 +1063,7 @@ int otx2_set_hw_capabilities(struct otx2_nic *pfvf);
int otx2_rss_init(struct otx2_nic *pfvf);
int otx2_set_flowkey_cfg(struct otx2_nic *pfvf);
void otx2_set_rss_key(struct otx2_nic *pfvf);
int otx2_set_rss_table(struct otx2_nic *pfvf, int ctx_id);
int otx2_set_rss_table(struct otx2_nic *pfvf, int ctx_id, const u32 *ind_tbl);
/* Mbox handlers */
void mbox_handler_msix_offset(struct otx2_nic *pfvf,

View File

@ -796,35 +796,75 @@ static u32 otx2_get_rxfh_indir_size(struct net_device *dev)
return MAX_RSS_INDIR_TBL_SIZE;
}
static int otx2_rss_ctx_delete(struct otx2_nic *pfvf, int ctx_id)
static int otx2_create_rxfh(struct net_device *dev,
struct ethtool_rxfh_context *ctx,
const struct ethtool_rxfh_param *rxfh,
struct netlink_ext_ack *extack)
{
struct otx2_rss_info *rss = &pfvf->hw.rss_info;
struct otx2_nic *pfvf = netdev_priv(dev);
struct otx2_rss_info *rss;
unsigned int queues;
u32 *ind_tbl;
int idx;
otx2_rss_ctx_flow_del(pfvf, ctx_id);
kfree(rss->rss_ctx[ctx_id]);
rss->rss_ctx[ctx_id] = NULL;
rss = &pfvf->hw.rss_info;
queues = pfvf->hw.rx_queues;
if (rxfh->hfunc && rxfh->hfunc != ETH_RSS_HASH_TOP)
return -EOPNOTSUPP;
ctx->hfunc = ETH_RSS_HASH_TOP;
if (!rss->enable) {
netdev_err(dev, "RSS is disabled, cannot change settings\n");
return -EIO;
}
ind_tbl = rxfh->indir;
if (!ind_tbl) {
ind_tbl = ethtool_rxfh_context_indir(ctx);
for (idx = 0; idx < rss->rss_size; idx++)
ind_tbl[idx] = ethtool_rxfh_indir_default(idx, queues);
}
otx2_set_rss_table(pfvf, rxfh->rss_context, ind_tbl);
return 0;
}
static int otx2_modify_rxfh(struct net_device *dev,
struct ethtool_rxfh_context *ctx,
const struct ethtool_rxfh_param *rxfh,
struct netlink_ext_ack *extack)
{
struct otx2_nic *pfvf = netdev_priv(dev);
if (rxfh->hfunc != ETH_RSS_HASH_NO_CHANGE &&
rxfh->hfunc != ETH_RSS_HASH_TOP)
return -EOPNOTSUPP;
if (!pfvf->hw.rss_info.enable) {
netdev_err(dev, "RSS is disabled, cannot change settings\n");
return -EIO;
}
if (rxfh->indir)
otx2_set_rss_table(pfvf, rxfh->rss_context, rxfh->indir);
return 0;
}
static int otx2_rss_ctx_create(struct otx2_nic *pfvf,
u32 *rss_context)
static int otx2_remove_rxfh(struct net_device *dev,
struct ethtool_rxfh_context *ctx,
u32 rss_context,
struct netlink_ext_ack *extack)
{
struct otx2_rss_info *rss = &pfvf->hw.rss_info;
u8 ctx;
struct otx2_nic *pfvf = netdev_priv(dev);
for (ctx = 0; ctx < MAX_RSS_GROUPS; ctx++) {
if (!rss->rss_ctx[ctx])
break;
if (!pfvf->hw.rss_info.enable) {
netdev_err(dev, "RSS is disabled, cannot change settings\n");
return -EIO;
}
if (ctx == MAX_RSS_GROUPS)
return -EINVAL;
rss->rss_ctx[ctx] = kzalloc(sizeof(*rss->rss_ctx[ctx]), GFP_KERNEL);
if (!rss->rss_ctx[ctx])
return -ENOMEM;
*rss_context = ctx;
otx2_rss_ctx_flow_del(pfvf, rss_context);
return 0;
}
@ -833,23 +873,14 @@ static int otx2_set_rxfh(struct net_device *dev,
struct ethtool_rxfh_param *rxfh,
struct netlink_ext_ack *extack)
{
u32 rss_context = DEFAULT_RSS_CONTEXT_GROUP;
struct otx2_nic *pfvf = netdev_priv(dev);
struct otx2_rss_ctx *rss_ctx;
struct otx2_rss_info *rss;
int ret, idx;
int idx;
if (rxfh->hfunc != ETH_RSS_HASH_NO_CHANGE &&
rxfh->hfunc != ETH_RSS_HASH_TOP)
return -EOPNOTSUPP;
if (rxfh->rss_context)
rss_context = rxfh->rss_context;
if (rss_context != ETH_RXFH_CONTEXT_ALLOC &&
rss_context >= MAX_RSS_GROUPS)
return -EINVAL;
rss = &pfvf->hw.rss_info;
if (!rss->enable) {
@ -861,21 +892,12 @@ static int otx2_set_rxfh(struct net_device *dev,
memcpy(rss->key, rxfh->key, sizeof(rss->key));
otx2_set_rss_key(pfvf);
}
if (rxfh->rss_delete)
return otx2_rss_ctx_delete(pfvf, rss_context);
if (rss_context == ETH_RXFH_CONTEXT_ALLOC) {
ret = otx2_rss_ctx_create(pfvf, &rss_context);
rxfh->rss_context = rss_context;
if (ret)
return ret;
}
if (rxfh->indir) {
rss_ctx = rss->rss_ctx[rss_context];
for (idx = 0; idx < rss->rss_size; idx++)
rss_ctx->ind_tbl[idx] = rxfh->indir[idx];
rss->ind_tbl[idx] = rxfh->indir[idx];
}
otx2_set_rss_table(pfvf, rss_context);
otx2_set_rss_table(pfvf, DEFAULT_RSS_CONTEXT_GROUP, NULL);
return 0;
}
@ -884,9 +906,7 @@ static int otx2_set_rxfh(struct net_device *dev,
static int otx2_get_rxfh(struct net_device *dev,
struct ethtool_rxfh_param *rxfh)
{
u32 rss_context = DEFAULT_RSS_CONTEXT_GROUP;
struct otx2_nic *pfvf = netdev_priv(dev);
struct otx2_rss_ctx *rss_ctx;
struct otx2_rss_info *rss;
u32 *indir = rxfh->indir;
int idx, rx_queues;
@ -894,32 +914,21 @@ static int otx2_get_rxfh(struct net_device *dev,
rss = &pfvf->hw.rss_info;
rxfh->hfunc = ETH_RSS_HASH_TOP;
if (rxfh->rss_context)
rss_context = rxfh->rss_context;
if (!indir)
return 0;
if (!rss->enable && rss_context == DEFAULT_RSS_CONTEXT_GROUP) {
if (!rss->enable) {
rx_queues = pfvf->hw.rx_queues;
for (idx = 0; idx < MAX_RSS_INDIR_TBL_SIZE; idx++)
indir[idx] = ethtool_rxfh_indir_default(idx, rx_queues);
return 0;
}
if (rss_context >= MAX_RSS_GROUPS)
return -ENOENT;
rss_ctx = rss->rss_ctx[rss_context];
if (!rss_ctx)
return -ENOENT;
if (indir) {
for (idx = 0; idx < rss->rss_size; idx++) {
/* Ignore if the rx queue is AF_XDP zero copy enabled */
if (test_bit(rss_ctx->ind_tbl[idx], pfvf->af_xdp_zc_qidx))
continue;
indir[idx] = rss_ctx->ind_tbl[idx];
}
for (idx = 0; idx < rss->rss_size; idx++) {
/* Ignore if the rx queue is AF_XDP zero copy enabled */
if (test_bit(rss->ind_tbl[idx], pfvf->af_xdp_zc_qidx))
continue;
indir[idx] = rss->ind_tbl[idx];
}
if (rxfh->key)
memcpy(rxfh->key, rss->key, sizeof(rss->key));
@ -1307,12 +1316,12 @@ static void otx2_get_fec_stats(struct net_device *netdev,
}
static const struct ethtool_ops otx2_ethtool_ops = {
.cap_rss_ctx_supported = true,
.supported_coalesce_params = ETHTOOL_COALESCE_USECS |
ETHTOOL_COALESCE_MAX_FRAMES |
ETHTOOL_COALESCE_USE_ADAPTIVE,
.supported_ring_params = ETHTOOL_RING_USE_RX_BUF_LEN |
ETHTOOL_RING_USE_CQE_SIZE,
.rxfh_max_num_contexts = MAX_RSS_GROUPS,
.get_link = otx2_get_link,
.get_drvinfo = otx2_get_drvinfo,
.get_strings = otx2_get_strings,
@ -1332,6 +1341,9 @@ static const struct ethtool_ops otx2_ethtool_ops = {
.set_rxfh = otx2_set_rxfh,
.get_rxfh_fields = otx2_get_rss_hash_opts,
.set_rxfh_fields = otx2_set_rss_hash_opts,
.create_rxfh_context = otx2_create_rxfh,
.modify_rxfh_context = otx2_modify_rxfh,
.remove_rxfh_context = otx2_remove_rxfh,
.get_msglevel = otx2_get_msglevel,
.set_msglevel = otx2_set_msglevel,
.get_pauseparam = otx2_get_pauseparam,
@ -1426,12 +1438,12 @@ static int otx2vf_get_link_ksettings(struct net_device *netdev,
}
static const struct ethtool_ops otx2vf_ethtool_ops = {
.cap_rss_ctx_supported = true,
.supported_coalesce_params = ETHTOOL_COALESCE_USECS |
ETHTOOL_COALESCE_MAX_FRAMES |
ETHTOOL_COALESCE_USE_ADAPTIVE,
.supported_ring_params = ETHTOOL_RING_USE_RX_BUF_LEN |
ETHTOOL_RING_USE_CQE_SIZE,
.rxfh_max_num_contexts = MAX_RSS_GROUPS,
.get_link = otx2_get_link,
.get_drvinfo = otx2vf_get_drvinfo,
.get_strings = otx2vf_get_strings,
@ -1447,6 +1459,9 @@ static const struct ethtool_ops otx2vf_ethtool_ops = {
.set_rxfh = otx2_set_rxfh,
.get_rxfh_fields = otx2_get_rss_hash_opts,
.set_rxfh_fields = otx2_set_rss_hash_opts,
.create_rxfh_context = otx2_create_rxfh,
.modify_rxfh_context = otx2_modify_rxfh,
.remove_rxfh_context = otx2_remove_rxfh,
.get_ringparam = otx2_get_ringparam,
.set_ringparam = otx2_set_ringparam,
.get_coalesce = otx2_get_coalesce,

View File

@ -2158,7 +2158,6 @@ int otx2_stop(struct net_device *netdev)
struct otx2_nic *pf = netdev_priv(netdev);
struct otx2_cq_poll *cq_poll = NULL;
struct otx2_qset *qset = &pf->qset;
struct otx2_rss_info *rss;
int qidx, vec, wrk;
/* If the DOWN flag is set resources are already freed */
@ -2176,10 +2175,7 @@ int otx2_stop(struct net_device *netdev)
otx2_rxtx_enable(pf, false);
/* Clear RSS enable flag */
rss = &pf->hw.rss_info;
rss->enable = false;
if (!netif_is_rxfh_configured(netdev))
kfree(rss->rss_ctx[DEFAULT_RSS_CONTEXT_GROUP]);
pf->hw.rss_info.enable = false;
/* Cleanup Queue IRQ */
vec = pci_irq_vector(pf->pdev,

View File

@ -132,7 +132,7 @@ int otx2_xsk_pool_enable(struct otx2_nic *pf, struct xsk_buff_pool *pool, u16 qi
set_bit(qidx, pf->af_xdp_zc_qidx);
otx2_clean_up_rq(pf, qidx);
/* Reconfigure RSS table as 'qidx' cannot be part of RSS now */
otx2_set_rss_table(pf, DEFAULT_RSS_CONTEXT_GROUP);
otx2_set_rss_table(pf, DEFAULT_RSS_CONTEXT_GROUP, NULL);
/* Kick start the NAPI context so that receiving will start */
return otx2_xsk_wakeup(pf->netdev, qidx, XDP_WAKEUP_RX);
}
@ -153,7 +153,7 @@ int otx2_xsk_pool_disable(struct otx2_nic *pf, u16 qidx)
clear_bit(qidx, pf->af_xdp_zc_qidx);
xsk_pool_dma_unmap(pool, DMA_ATTR_SKIP_CPU_SYNC | DMA_ATTR_WEAK_ORDERING);
/* Reconfigure RSS table as 'qidx' now need to be part of RSS now */
otx2_set_rss_table(pf, DEFAULT_RSS_CONTEXT_GROUP);
otx2_set_rss_table(pf, DEFAULT_RSS_CONTEXT_GROUP, NULL);
return 0;
}

View File

@ -567,7 +567,8 @@ int mlx5e_rss_packet_merge_set_param(struct mlx5e_rss *rss,
return final_err;
}
int mlx5e_rss_get_rxfh(struct mlx5e_rss *rss, u32 *indir, u8 *key, u8 *hfunc, bool *symmetric)
void mlx5e_rss_get_rxfh(struct mlx5e_rss *rss, u32 *indir, u8 *key, u8 *hfunc,
bool *symmetric)
{
if (indir)
memcpy(indir, rss->indir.table,
@ -582,8 +583,6 @@ int mlx5e_rss_get_rxfh(struct mlx5e_rss *rss, u32 *indir, u8 *key, u8 *hfunc, bo
if (symmetric)
*symmetric = rss->hash.symmetric;
return 0;
}
int mlx5e_rss_set_rxfh(struct mlx5e_rss *rss, const u32 *indir,

View File

@ -47,7 +47,8 @@ void mlx5e_rss_disable(struct mlx5e_rss *rss);
int mlx5e_rss_packet_merge_set_param(struct mlx5e_rss *rss,
struct mlx5e_packet_merge_param *pkt_merge_param);
int mlx5e_rss_get_rxfh(struct mlx5e_rss *rss, u32 *indir, u8 *key, u8 *hfunc, bool *symmetric);
void mlx5e_rss_get_rxfh(struct mlx5e_rss *rss, u32 *indir, u8 *key, u8 *hfunc,
bool *symmetric);
int mlx5e_rss_set_rxfh(struct mlx5e_rss *rss, const u32 *indir,
const u8 *key, const u8 *hfunc, const bool *symmetric,
u32 *rqns, u32 *vhca_ids, unsigned int num_rqns);

View File

@ -71,17 +71,12 @@ static int mlx5e_rx_res_rss_init_def(struct mlx5e_rx_res *res,
return 0;
}
int mlx5e_rx_res_rss_init(struct mlx5e_rx_res *res, u32 *rss_idx, unsigned int init_nch)
int mlx5e_rx_res_rss_init(struct mlx5e_rx_res *res, u32 rss_idx, unsigned int init_nch)
{
bool inner_ft_support = res->features & MLX5E_RX_RES_FEATURE_INNER_FT;
struct mlx5e_rss *rss;
int i;
for (i = 1; i < MLX5E_MAX_NUM_RSS; i++)
if (!res->rss[i])
break;
if (i == MLX5E_MAX_NUM_RSS)
if (WARN_ON_ONCE(res->rss[rss_idx]))
return -ENOSPC;
rss = mlx5e_rss_init(res->mdev, inner_ft_support, res->drop_rqn,
@ -97,8 +92,7 @@ int mlx5e_rx_res_rss_init(struct mlx5e_rx_res *res, u32 *rss_idx, unsigned int i
mlx5e_rss_enable(rss, res->rss_rqns, vhca_ids, res->rss_nch);
}
res->rss[i] = rss;
*rss_idx = i;
res->rss[rss_idx] = rss;
return 0;
}
@ -193,19 +187,17 @@ void mlx5e_rx_res_rss_set_indir_uniform(struct mlx5e_rx_res *res, unsigned int n
mlx5e_rss_set_indir_uniform(res->rss[0], nch);
}
int mlx5e_rx_res_rss_get_rxfh(struct mlx5e_rx_res *res, u32 rss_idx,
u32 *indir, u8 *key, u8 *hfunc, bool *symmetric)
void mlx5e_rx_res_rss_get_rxfh(struct mlx5e_rx_res *res, u32 rss_idx,
u32 *indir, u8 *key, u8 *hfunc, bool *symmetric)
{
struct mlx5e_rss *rss;
struct mlx5e_rss *rss = NULL;
if (rss_idx >= MLX5E_MAX_NUM_RSS)
return -EINVAL;
if (rss_idx < MLX5E_MAX_NUM_RSS)
rss = res->rss[rss_idx];
if (WARN_ON_ONCE(!rss))
return;
rss = res->rss[rss_idx];
if (!rss)
return -ENOENT;
return mlx5e_rss_get_rxfh(rss, indir, key, hfunc, symmetric);
mlx5e_rss_get_rxfh(rss, indir, key, hfunc, symmetric);
}
int mlx5e_rx_res_rss_set_rxfh(struct mlx5e_rx_res *res, u32 rss_idx,

View File

@ -48,8 +48,9 @@ void mlx5e_rx_res_xsk_update(struct mlx5e_rx_res *res, struct mlx5e_channels *ch
/* Configuration API */
void mlx5e_rx_res_rss_set_indir_uniform(struct mlx5e_rx_res *res, unsigned int nch);
int mlx5e_rx_res_rss_get_rxfh(struct mlx5e_rx_res *res, u32 rss_idx,
u32 *indir, u8 *key, u8 *hfunc, bool *symmetric);
void mlx5e_rx_res_rss_get_rxfh(struct mlx5e_rx_res *res, u32 rss_idx,
u32 *indir, u8 *key, u8 *hfunc,
bool *symmetric);
int mlx5e_rx_res_rss_set_rxfh(struct mlx5e_rx_res *res, u32 rss_idx,
const u32 *indir, const u8 *key, const u8 *hfunc,
const bool *symmetric);
@ -61,7 +62,7 @@ int mlx5e_rx_res_rss_set_hash_fields(struct mlx5e_rx_res *res, u32 rss_idx,
int mlx5e_rx_res_packet_merge_set_param(struct mlx5e_rx_res *res,
struct mlx5e_packet_merge_param *pkt_merge_param);
int mlx5e_rx_res_rss_init(struct mlx5e_rx_res *res, u32 *rss_idx, unsigned int init_nch);
int mlx5e_rx_res_rss_init(struct mlx5e_rx_res *res, u32 rss_idx, unsigned int init_nch);
int mlx5e_rx_res_rss_destroy(struct mlx5e_rx_res *res, u32 rss_idx);
int mlx5e_rx_res_rss_cnt(struct mlx5e_rx_res *res);
int mlx5e_rx_res_rss_index(struct mlx5e_rx_res *res, struct mlx5e_rss *rss);

View File

@ -1480,61 +1480,55 @@ static u32 mlx5e_get_rxfh_indir_size(struct net_device *netdev)
static int mlx5e_get_rxfh(struct net_device *netdev, struct ethtool_rxfh_param *rxfh)
{
struct mlx5e_priv *priv = netdev_priv(netdev);
u32 rss_context = rxfh->rss_context;
bool symmetric;
int err;
mutex_lock(&priv->state_lock);
err = mlx5e_rx_res_rss_get_rxfh(priv->rx_res, rss_context,
rxfh->indir, rxfh->key, &rxfh->hfunc, &symmetric);
mlx5e_rx_res_rss_get_rxfh(priv->rx_res, 0, rxfh->indir, rxfh->key,
&rxfh->hfunc, &symmetric);
mutex_unlock(&priv->state_lock);
if (err)
return err;
if (symmetric)
rxfh->input_xfrm = RXH_XFRM_SYM_OR_XOR;
return 0;
}
static int mlx5e_set_rxfh(struct net_device *dev, struct ethtool_rxfh_param *rxfh,
static int mlx5e_rxfh_hfunc_check(struct mlx5e_priv *priv,
const struct ethtool_rxfh_param *rxfh)
{
unsigned int count;
count = priv->channels.params.num_channels;
if (rxfh->hfunc == ETH_RSS_HASH_XOR) {
unsigned int xor8_max_channels = mlx5e_rqt_max_num_channels_allowed_for_xor8();
if (count > xor8_max_channels) {
netdev_err(priv->netdev, "%s: Cannot set RSS hash function to XOR, current number of channels (%d) exceeds the maximum allowed for XOR8 RSS hfunc (%d)\n",
__func__, count, xor8_max_channels);
return -EINVAL;
}
}
return 0;
}
static int mlx5e_set_rxfh(struct net_device *dev,
struct ethtool_rxfh_param *rxfh,
struct netlink_ext_ack *extack)
{
bool symmetric = rxfh->input_xfrm == RXH_XFRM_SYM_OR_XOR;
struct mlx5e_priv *priv = netdev_priv(dev);
u32 *rss_context = &rxfh->rss_context;
u8 hfunc = rxfh->hfunc;
unsigned int count;
int err;
mutex_lock(&priv->state_lock);
count = priv->channels.params.num_channels;
if (hfunc == ETH_RSS_HASH_XOR) {
unsigned int xor8_max_channels = mlx5e_rqt_max_num_channels_allowed_for_xor8();
if (count > xor8_max_channels) {
err = -EINVAL;
netdev_err(priv->netdev, "%s: Cannot set RSS hash function to XOR, current number of channels (%d) exceeds the maximum allowed for XOR8 RSS hfunc (%d)\n",
__func__, count, xor8_max_channels);
goto unlock;
}
}
if (*rss_context && rxfh->rss_delete) {
err = mlx5e_rx_res_rss_destroy(priv->rx_res, *rss_context);
err = mlx5e_rxfh_hfunc_check(priv, rxfh);
if (err)
goto unlock;
}
if (*rss_context == ETH_RXFH_CONTEXT_ALLOC) {
err = mlx5e_rx_res_rss_init(priv->rx_res, rss_context, count);
if (err)
goto unlock;
}
err = mlx5e_rx_res_rss_set_rxfh(priv->rx_res, *rss_context,
err = mlx5e_rx_res_rss_set_rxfh(priv->rx_res, rxfh->rss_context,
rxfh->indir, rxfh->key,
hfunc == ETH_RSS_HASH_NO_CHANGE ? NULL : &hfunc,
rxfh->input_xfrm == RXH_XFRM_NO_CHANGE ? NULL : &symmetric);
@ -1544,6 +1538,86 @@ static int mlx5e_set_rxfh(struct net_device *dev, struct ethtool_rxfh_param *rxf
return err;
}
static int mlx5e_create_rxfh_context(struct net_device *dev,
struct ethtool_rxfh_context *ctx,
const struct ethtool_rxfh_param *rxfh,
struct netlink_ext_ack *extack)
{
bool symmetric = rxfh->input_xfrm == RXH_XFRM_SYM_OR_XOR;
struct mlx5e_priv *priv = netdev_priv(dev);
u8 hfunc = rxfh->hfunc;
int err;
mutex_lock(&priv->state_lock);
err = mlx5e_rxfh_hfunc_check(priv, rxfh);
if (err)
goto unlock;
err = mlx5e_rx_res_rss_init(priv->rx_res, rxfh->rss_context,
priv->channels.params.num_channels);
if (err)
goto unlock;
err = mlx5e_rx_res_rss_set_rxfh(priv->rx_res, rxfh->rss_context,
rxfh->indir, rxfh->key,
hfunc == ETH_RSS_HASH_NO_CHANGE ? NULL : &hfunc,
rxfh->input_xfrm == RXH_XFRM_NO_CHANGE ? NULL : &symmetric);
if (err)
goto unlock;
mlx5e_rx_res_rss_get_rxfh(priv->rx_res, rxfh->rss_context,
ethtool_rxfh_context_indir(ctx),
ethtool_rxfh_context_key(ctx),
&ctx->hfunc, &symmetric);
if (symmetric)
ctx->input_xfrm = RXH_XFRM_SYM_OR_XOR;
unlock:
mutex_unlock(&priv->state_lock);
return err;
}
static int mlx5e_modify_rxfh_context(struct net_device *dev,
struct ethtool_rxfh_context *ctx,
const struct ethtool_rxfh_param *rxfh,
struct netlink_ext_ack *extack)
{
bool symmetric = rxfh->input_xfrm == RXH_XFRM_SYM_OR_XOR;
struct mlx5e_priv *priv = netdev_priv(dev);
u8 hfunc = rxfh->hfunc;
int err;
mutex_lock(&priv->state_lock);
err = mlx5e_rxfh_hfunc_check(priv, rxfh);
if (err)
goto unlock;
err = mlx5e_rx_res_rss_set_rxfh(priv->rx_res, rxfh->rss_context,
rxfh->indir, rxfh->key,
hfunc == ETH_RSS_HASH_NO_CHANGE ? NULL : &hfunc,
rxfh->input_xfrm == RXH_XFRM_NO_CHANGE ? NULL : &symmetric);
unlock:
mutex_unlock(&priv->state_lock);
return err;
}
static int mlx5e_remove_rxfh_context(struct net_device *dev,
struct ethtool_rxfh_context *ctx,
u32 rss_context,
struct netlink_ext_ack *extack)
{
struct mlx5e_priv *priv = netdev_priv(dev);
int err;
mutex_lock(&priv->state_lock);
err = mlx5e_rx_res_rss_destroy(priv->rx_res, rss_context);
mutex_unlock(&priv->state_lock);
return err;
}
#define MLX5E_PFC_PREVEN_AUTO_TOUT_MSEC 100
#define MLX5E_PFC_PREVEN_TOUT_MAX_MSEC 8000
#define MLX5E_PFC_PREVEN_MINOR_PRECENT 85
@ -2654,9 +2728,9 @@ static void mlx5e_get_ts_stats(struct net_device *netdev,
const struct ethtool_ops mlx5e_ethtool_ops = {
.cap_link_lanes_supported = true,
.cap_rss_ctx_supported = true,
.rxfh_per_ctx_fields = true,
.rxfh_per_ctx_key = true,
.rxfh_max_num_contexts = MLX5E_MAX_NUM_RSS,
.supported_coalesce_params = ETHTOOL_COALESCE_USECS |
ETHTOOL_COALESCE_MAX_FRAMES |
ETHTOOL_COALESCE_USE_ADAPTIVE |
@ -2685,6 +2759,9 @@ const struct ethtool_ops mlx5e_ethtool_ops = {
.set_rxfh = mlx5e_set_rxfh,
.get_rxfh_fields = mlx5e_get_rxfh_fields,
.set_rxfh_fields = mlx5e_set_rxfh_fields,
.create_rxfh_context = mlx5e_create_rxfh_context,
.modify_rxfh_context = mlx5e_modify_rxfh_context,
.remove_rxfh_context = mlx5e_remove_rxfh_context,
.get_rxnfc = mlx5e_get_rxnfc,
.set_rxnfc = mlx5e_set_rxnfc,
.get_tunable = mlx5e_get_tunable,

View File

@ -865,9 +865,6 @@ struct kernel_ethtool_ts_info {
* @supported_input_xfrm: supported types of input xfrm from %RXH_XFRM_*.
* @cap_link_lanes_supported: indicates if the driver supports lanes
* parameter.
* @cap_rss_ctx_supported: indicates if the driver supports RSS
* contexts via legacy API, drivers implementing @create_rxfh_context
* do not have to set this bit.
* @rxfh_per_ctx_fields: device supports selecting different header fields
* for Rx hash calculation and RSS for each additional context.
* @rxfh_per_ctx_key: device supports setting different RSS key for each
@ -1100,7 +1097,6 @@ struct kernel_ethtool_ts_info {
struct ethtool_ops {
u32 supported_input_xfrm:8;
u32 cap_link_lanes_supported:1;
u32 cap_rss_ctx_supported:1;
u32 rxfh_per_ctx_fields:1;
u32 rxfh_per_ctx_key:1;
u32 cap_rss_rxnfc_adds:1;

View File

@ -11979,21 +11979,8 @@ static void netdev_rss_contexts_free(struct net_device *dev)
mutex_lock(&dev->ethtool->rss_lock);
xa_for_each(&dev->ethtool->rss_ctx, context, ctx) {
struct ethtool_rxfh_param rxfh;
rxfh.indir = ethtool_rxfh_context_indir(ctx);
rxfh.key = ethtool_rxfh_context_key(ctx);
rxfh.hfunc = ctx->hfunc;
rxfh.input_xfrm = ctx->input_xfrm;
rxfh.rss_context = context;
rxfh.rss_delete = true;
xa_erase(&dev->ethtool->rss_ctx, context);
if (dev->ethtool_ops->create_rxfh_context)
dev->ethtool_ops->remove_rxfh_context(dev, ctx,
context, NULL);
else
dev->ethtool_ops->set_rxfh(dev, &rxfh, NULL);
dev->ethtool_ops->remove_rxfh_context(dev, ctx, context, NULL);
kfree(ctx);
}
xa_destroy(&dev->ethtool->rss_ctx);

View File

@ -1391,8 +1391,7 @@ static noinline_for_stack int ethtool_get_rxfh(struct net_device *dev,
if (rxfh.rsvd8[0] || rxfh.rsvd8[1] || rxfh.rsvd32)
return -EINVAL;
/* Most drivers don't handle rss_context, check it's 0 as well */
if (rxfh.rss_context && !(ops->cap_rss_ctx_supported ||
ops->create_rxfh_context))
if (rxfh.rss_context && !ops->create_rxfh_context)
return -EOPNOTSUPP;
rxfh.indir_size = rxfh_dev.indir_size;
@ -1534,8 +1533,7 @@ static noinline_for_stack int ethtool_set_rxfh(struct net_device *dev,
if (rxfh.rsvd8[0] || rxfh.rsvd8[1] || rxfh.rsvd32)
return -EINVAL;
/* Most drivers don't handle rss_context, check it's 0 as well */
if (rxfh.rss_context && !(ops->cap_rss_ctx_supported ||
ops->create_rxfh_context))
if (rxfh.rss_context && !ops->create_rxfh_context)
return -EOPNOTSUPP;
/* Check input data transformation capabilities */
if (rxfh.input_xfrm && rxfh.input_xfrm != RXH_XFRM_SYM_XOR &&
@ -1634,6 +1632,8 @@ static noinline_for_stack int ethtool_set_rxfh(struct net_device *dev,
}
if (create) {
u32 limit, ctx_id;
if (rxfh_dev.rss_delete) {
ret = -EINVAL;
goto out_unlock;
@ -1644,21 +1644,15 @@ static noinline_for_stack int ethtool_set_rxfh(struct net_device *dev,
goto out_unlock;
}
if (ops->create_rxfh_context) {
u32 limit = ops->rxfh_max_num_contexts ?: 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 - 1),
GFP_KERNEL_ACCOUNT);
if (ret < 0) {
kfree(ctx);
goto out_unlock;
}
WARN_ON(!ctx_id); /* can't happen */
rxfh.rss_context = ctx_id;
limit = ops->rxfh_max_num_contexts ?: U32_MAX;
ret = xa_alloc(&dev->ethtool->rss_ctx, &ctx_id, ctx,
XA_LIMIT(1, limit - 1), GFP_KERNEL_ACCOUNT);
if (ret < 0) {
kfree(ctx);
goto out_unlock;
}
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) {
@ -1670,31 +1664,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;
if (rxfh.rss_context && ops->create_rxfh_context) {
if (create) {
ret = ops->create_rxfh_context(dev, ctx, &rxfh_dev,
extack);
/* Make sure driver populates defaults */
WARN_ON_ONCE(!ret && !rxfh_dev.key &&
ops->rxfh_per_ctx_key &&
!memchr_inv(ethtool_rxfh_context_key(ctx),
0, ctx->key_size));
} else if (rxfh_dev.rss_delete) {
ret = ops->remove_rxfh_context(dev, ctx,
rxfh.rss_context,
extack);
} else {
ret = ops->modify_rxfh_context(dev, ctx, &rxfh_dev,
extack);
}
} else {
if (!rxfh.rss_context) {
ret = ops->set_rxfh(dev, &rxfh_dev, extack);
} else if (create) {
ret = ops->create_rxfh_context(dev, ctx, &rxfh_dev, extack);
/* Make sure driver populates defaults */
WARN_ON_ONCE(!ret && !rxfh_dev.key && ops->rxfh_per_ctx_key &&
!memchr_inv(ethtool_rxfh_context_key(ctx), 0,
ctx->key_size));
} else if (rxfh_dev.rss_delete) {
ret = ops->remove_rxfh_context(dev, ctx, rxfh.rss_context,
extack);
} else {
ret = ops->modify_rxfh_context(dev, ctx, &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);
xa_erase(&dev->ethtool->rss_ctx, rxfh.rss_context);
kfree(ctx);
}
goto out_unlock;
@ -1713,36 +1700,6 @@ static noinline_for_stack int ethtool_set_rxfh(struct net_device *dev,
dev->priv_flags |= IFF_RXFH_CONFIGURED;
}
/* Update rss_ctx tracking */
if (create && !ops->create_rxfh_context) {
/* driver uses old API, it chose context ID */
if (WARN_ON(xa_load(&dev->ethtool->rss_ctx, rxfh_dev.rss_context))) {
/* context ID reused, our tracking is screwed */
kfree(ctx);
goto out_unlock;
}
/* Allocate the exact ID the driver gave us */
if (xa_is_err(xa_store(&dev->ethtool->rss_ctx, rxfh_dev.rss_context,
ctx, GFP_KERNEL))) {
kfree(ctx);
goto out_unlock;
}
/* Fetch the defaults for the old API, in the new API drivers
* should write defaults into ctx themselves.
*/
rxfh_dev.indir = (u32 *)rss_config;
rxfh_dev.indir_size = dev_indir_size;
rxfh_dev.key = rss_config + indir_bytes;
rxfh_dev.key_size = dev_key_size;
ret = ops->get_rxfh(dev, &rxfh_dev);
if (WARN_ON(ret)) {
xa_erase(&dev->ethtool->rss_ctx, rxfh.rss_context);
kfree(ctx);
goto out_unlock;
}
}
if (rxfh_dev.rss_delete) {
WARN_ON(xa_erase(&dev->ethtool->rss_ctx, rxfh.rss_context) != ctx);
kfree(ctx);

View File

@ -163,8 +163,7 @@ rss_prepare_data(const struct ethnl_req_info *req_base,
return -EOPNOTSUPP;
/* Some drivers don't handle rss_context */
if (request->rss_context &&
!ops->cap_rss_ctx_supported && !ops->create_rxfh_context)
if (request->rss_context && !ops->create_rxfh_context)
return -EOPNOTSUPP;
mutex_lock(&dev->ethtool->rss_lock);