mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-09 10:11:52 -04:00
Merge branch 'net-ethtool-fixes-for-hds-threshold'
Jakub Kicinski says: ==================== net: ethtool: fixes for HDS threshold Quick follow up on the HDS threshold work, since the merge window is upon us. Fix the bnxt implementation to apply the settings right away, because we update the parameters _after_ configuring HW user needed to reconfig the device twice to get the settings to stick. For this I took the liberty of moving the config to a separate struct. This follows my original thinking for the queue API. It should also fit more neatly into how many drivers which support safe config update operate. Drivers can allocate new objects using the "pending" struct. netdevsim: KTAP version 1 1..7 ok 1 hds.get_hds ok 2 hds.get_hds_thresh ok 3 hds.set_hds_disable ok 4 hds.set_hds_enable ok 5 hds.set_hds_thresh_zero ok 6 hds.set_hds_thresh_max ok 7 hds.set_hds_thresh_gt # Totals: pass:7 fail:0 xfail:0 xpass:0 skip:0 error:0 bnxt: KTAP version 1 1..7 ok 1 hds.get_hds ok 2 hds.get_hds_thresh ok 3 hds.set_hds_disable # SKIP disabling of HDS not supported by the device ok 4 hds.set_hds_enable ok 5 hds.set_hds_thresh_zero ok 6 hds.set_hds_thresh_max ok 7 hds.set_hds_thresh_gt # Totals: pass:6 fail:0 xfail:0 xpass:0 skip:1 error:0 v1: https://lore.kernel.org/20250117194815.1514410-1-kuba@kernel.org ==================== Link: https://patch.msgid.link/20250119020518.1962249-1-kuba@kernel.org Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
@@ -4609,8 +4609,13 @@ void bnxt_set_tpa_flags(struct bnxt *bp)
|
||||
|
||||
static void bnxt_init_ring_params(struct bnxt *bp)
|
||||
{
|
||||
unsigned int rx_size;
|
||||
|
||||
bp->rx_copybreak = BNXT_DEFAULT_RX_COPYBREAK;
|
||||
bp->dev->ethtool->hds_thresh = BNXT_DEFAULT_RX_COPYBREAK;
|
||||
/* Try to fit 4 chunks into a 4k page */
|
||||
rx_size = SZ_1K -
|
||||
NET_SKB_PAD - SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
|
||||
bp->dev->cfg->hds_thresh = max(BNXT_DEFAULT_RX_COPYBREAK, rx_size);
|
||||
}
|
||||
|
||||
/* bp->rx_ring_size, bp->tx_ring_size, dev->mtu, BNXT_FLAG_{G|L}RO flags must
|
||||
@@ -4671,9 +4676,10 @@ void bnxt_set_ring_params(struct bnxt *bp)
|
||||
ALIGN(max(NET_SKB_PAD, XDP_PACKET_HEADROOM), 8) -
|
||||
SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
|
||||
} else {
|
||||
rx_size = SKB_DATA_ALIGN(max(BNXT_DEFAULT_RX_COPYBREAK,
|
||||
bp->rx_copybreak) +
|
||||
NET_IP_ALIGN);
|
||||
rx_size = max3(BNXT_DEFAULT_RX_COPYBREAK,
|
||||
bp->rx_copybreak,
|
||||
bp->dev->cfg_pending->hds_thresh);
|
||||
rx_size = SKB_DATA_ALIGN(rx_size + NET_IP_ALIGN);
|
||||
rx_space = rx_size + NET_SKB_PAD +
|
||||
SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
|
||||
}
|
||||
@@ -6585,7 +6591,7 @@ static void bnxt_hwrm_update_rss_hash_cfg(struct bnxt *bp)
|
||||
|
||||
static int bnxt_hwrm_vnic_set_hds(struct bnxt *bp, struct bnxt_vnic_info *vnic)
|
||||
{
|
||||
u16 hds_thresh = (u16)bp->dev->ethtool->hds_thresh;
|
||||
u16 hds_thresh = (u16)bp->dev->cfg_pending->hds_thresh;
|
||||
struct hwrm_vnic_plcmodes_cfg_input *req;
|
||||
int rc;
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <linux/ptp_clock_kernel.h>
|
||||
#include <linux/net_tstamp.h>
|
||||
#include <linux/timecounter.h>
|
||||
#include <net/netdev_queues.h>
|
||||
#include <net/netlink.h>
|
||||
#include "bnxt_hsi.h"
|
||||
#include "bnxt.h"
|
||||
@@ -834,7 +835,6 @@ static void bnxt_get_ringparam(struct net_device *dev,
|
||||
ering->rx_jumbo_pending = bp->rx_agg_ring_size;
|
||||
ering->tx_pending = bp->tx_ring_size;
|
||||
|
||||
kernel_ering->hds_thresh = dev->ethtool->hds_thresh;
|
||||
kernel_ering->hds_thresh_max = BNXT_HDS_THRESHOLD_MAX;
|
||||
}
|
||||
|
||||
@@ -852,7 +852,7 @@ static int bnxt_set_ringparam(struct net_device *dev,
|
||||
(ering->tx_pending < BNXT_MIN_TX_DESC_CNT))
|
||||
return -EINVAL;
|
||||
|
||||
hds_config_mod = tcp_data_split != dev->ethtool->hds_config;
|
||||
hds_config_mod = tcp_data_split != dev->cfg->hds_config;
|
||||
if (tcp_data_split == ETHTOOL_TCP_DATA_SPLIT_DISABLED && hds_config_mod)
|
||||
return -EINVAL;
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/random.h>
|
||||
#include <net/netdev_queues.h>
|
||||
|
||||
#include "netdevsim.h"
|
||||
|
||||
@@ -71,8 +72,6 @@ static void nsim_get_ringparam(struct net_device *dev,
|
||||
struct netdevsim *ns = netdev_priv(dev);
|
||||
|
||||
memcpy(ring, &ns->ethtool.ring, sizeof(ns->ethtool.ring));
|
||||
kernel_ring->tcp_data_split = dev->ethtool->hds_config;
|
||||
kernel_ring->hds_thresh = dev->ethtool->hds_thresh;
|
||||
kernel_ring->hds_thresh_max = NSIM_HDS_THRESHOLD_MAX;
|
||||
|
||||
if (kernel_ring->tcp_data_split == ETHTOOL_TCP_DATA_SPLIT_UNKNOWN)
|
||||
@@ -189,9 +188,6 @@ static void nsim_ethtool_ring_init(struct netdevsim *ns)
|
||||
ns->ethtool.ring.rx_jumbo_max_pending = 4096;
|
||||
ns->ethtool.ring.rx_mini_max_pending = 4096;
|
||||
ns->ethtool.ring.tx_max_pending = 4096;
|
||||
|
||||
ns->netdev->ethtool->hds_config = ETHTOOL_TCP_DATA_SPLIT_UNKNOWN;
|
||||
ns->netdev->ethtool->hds_thresh = 0;
|
||||
}
|
||||
|
||||
void nsim_ethtool_init(struct netdevsim *ns)
|
||||
|
||||
@@ -55,10 +55,10 @@ static int nsim_forward_skb(struct net_device *dev, struct sk_buff *skb,
|
||||
static netdev_tx_t nsim_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
{
|
||||
struct netdevsim *ns = netdev_priv(dev);
|
||||
struct ethtool_netdev_state *ethtool;
|
||||
struct net_device *peer_dev;
|
||||
unsigned int len = skb->len;
|
||||
struct netdevsim *peer_ns;
|
||||
struct netdev_config *cfg;
|
||||
struct nsim_rq *rq;
|
||||
int rxq;
|
||||
|
||||
@@ -76,11 +76,11 @@ static netdev_tx_t nsim_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
rxq = rxq % peer_dev->num_rx_queues;
|
||||
rq = peer_ns->rq[rxq];
|
||||
|
||||
ethtool = peer_dev->ethtool;
|
||||
cfg = peer_dev->cfg;
|
||||
if (skb_is_nonlinear(skb) &&
|
||||
(ethtool->hds_config != ETHTOOL_TCP_DATA_SPLIT_ENABLED ||
|
||||
(ethtool->hds_config == ETHTOOL_TCP_DATA_SPLIT_ENABLED &&
|
||||
ethtool->hds_thresh > len)))
|
||||
(cfg->hds_config != ETHTOOL_TCP_DATA_SPLIT_ENABLED ||
|
||||
(cfg->hds_config == ETHTOOL_TCP_DATA_SPLIT_ENABLED &&
|
||||
cfg->hds_thresh > len)))
|
||||
skb_linearize(skb);
|
||||
|
||||
skb_tx_timestamp(skb);
|
||||
|
||||
@@ -1171,16 +1171,12 @@ int ethtool_virtdev_set_link_ksettings(struct net_device *dev,
|
||||
* @rss_ctx: XArray of custom RSS contexts
|
||||
* @rss_lock: Protects entries in @rss_ctx. May be taken from
|
||||
* within RTNL.
|
||||
* @hds_thresh: HDS Threshold value.
|
||||
* @hds_config: HDS value from userspace.
|
||||
* @wol_enabled: Wake-on-LAN is enabled
|
||||
* @module_fw_flash_in_progress: Module firmware flashing is in progress.
|
||||
*/
|
||||
struct ethtool_netdev_state {
|
||||
struct xarray rss_ctx;
|
||||
struct mutex rss_lock;
|
||||
u32 hds_thresh;
|
||||
u8 hds_config;
|
||||
unsigned wol_enabled:1;
|
||||
unsigned module_fw_flash_in_progress:1;
|
||||
};
|
||||
|
||||
@@ -63,6 +63,7 @@ struct dsa_port;
|
||||
struct ip_tunnel_parm_kern;
|
||||
struct macsec_context;
|
||||
struct macsec_ops;
|
||||
struct netdev_config;
|
||||
struct netdev_name_node;
|
||||
struct sd_flow_limit;
|
||||
struct sfp_bus;
|
||||
@@ -2410,6 +2411,14 @@ struct net_device {
|
||||
const struct udp_tunnel_nic_info *udp_tunnel_nic_info;
|
||||
struct udp_tunnel_nic *udp_tunnel_nic;
|
||||
|
||||
/** @cfg: net_device queue-related configuration */
|
||||
struct netdev_config *cfg;
|
||||
/**
|
||||
* @cfg_pending: same as @cfg but when device is being actively
|
||||
* reconfigured includes any changes to the configuration
|
||||
* requested by the user, but which may or may not be rejected.
|
||||
*/
|
||||
struct netdev_config *cfg_pending;
|
||||
struct ethtool_netdev_state *ethtool;
|
||||
|
||||
/* protected by rtnl_lock */
|
||||
|
||||
@@ -4,6 +4,16 @@
|
||||
|
||||
#include <linux/netdevice.h>
|
||||
|
||||
/**
|
||||
* struct netdev_config - queue-related configuration for a netdev
|
||||
* @hds_thresh: HDS Threshold value.
|
||||
* @hds_config: HDS value from userspace.
|
||||
*/
|
||||
struct netdev_config {
|
||||
u32 hds_thresh;
|
||||
u8 hds_config;
|
||||
};
|
||||
|
||||
/* See the netdev.yaml spec for definition of each statistic */
|
||||
struct netdev_queue_stats_rx {
|
||||
u64 bytes;
|
||||
|
||||
@@ -106,6 +106,7 @@
|
||||
#include <net/dst.h>
|
||||
#include <net/dst_metadata.h>
|
||||
#include <net/gro.h>
|
||||
#include <net/netdev_queues.h>
|
||||
#include <net/pkt_sched.h>
|
||||
#include <net/pkt_cls.h>
|
||||
#include <net/checksum.h>
|
||||
@@ -9719,7 +9720,7 @@ int dev_xdp_propagate(struct net_device *dev, struct netdev_bpf *bpf)
|
||||
if (!dev->netdev_ops->ndo_bpf)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (dev->ethtool->hds_config == ETHTOOL_TCP_DATA_SPLIT_ENABLED &&
|
||||
if (dev->cfg->hds_config == ETHTOOL_TCP_DATA_SPLIT_ENABLED &&
|
||||
bpf->command == XDP_SETUP_PROG &&
|
||||
bpf->prog && !bpf->prog->aux->xdp_has_frags) {
|
||||
NL_SET_ERR_MSG(bpf->extack,
|
||||
@@ -9764,7 +9765,7 @@ static int dev_xdp_install(struct net_device *dev, enum bpf_xdp_mode mode,
|
||||
struct netdev_bpf xdp;
|
||||
int err;
|
||||
|
||||
if (dev->ethtool->hds_config == ETHTOOL_TCP_DATA_SPLIT_ENABLED &&
|
||||
if (dev->cfg->hds_config == ETHTOOL_TCP_DATA_SPLIT_ENABLED &&
|
||||
prog && !prog->aux->xdp_has_frags) {
|
||||
NL_SET_ERR_MSG(extack, "unable to install XDP to device using tcp-data-split");
|
||||
return -EBUSY;
|
||||
@@ -11542,6 +11543,11 @@ struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name,
|
||||
if (!dev->ethtool)
|
||||
goto free_all;
|
||||
|
||||
dev->cfg = kzalloc(sizeof(*dev->cfg), GFP_KERNEL_ACCOUNT);
|
||||
if (!dev->cfg)
|
||||
goto free_all;
|
||||
dev->cfg_pending = dev->cfg;
|
||||
|
||||
napi_config_sz = array_size(maxqs, sizeof(*dev->napi_config));
|
||||
dev->napi_config = kvzalloc(napi_config_sz, GFP_KERNEL_ACCOUNT);
|
||||
if (!dev->napi_config)
|
||||
@@ -11610,6 +11616,8 @@ void free_netdev(struct net_device *dev)
|
||||
return;
|
||||
}
|
||||
|
||||
WARN_ON(dev->cfg != dev->cfg_pending);
|
||||
kfree(dev->cfg);
|
||||
kfree(dev->ethtool);
|
||||
netif_free_tx_queues(dev);
|
||||
netif_free_rx_queues(dev);
|
||||
|
||||
@@ -141,12 +141,12 @@ int net_devmem_bind_dmabuf_to_queue(struct net_device *dev, u32 rxq_idx,
|
||||
return -ERANGE;
|
||||
}
|
||||
|
||||
if (dev->ethtool->hds_config != ETHTOOL_TCP_DATA_SPLIT_ENABLED) {
|
||||
if (dev->cfg->hds_config != ETHTOOL_TCP_DATA_SPLIT_ENABLED) {
|
||||
NL_SET_ERR_MSG(extack, "tcp-data-split is disabled");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (dev->ethtool->hds_thresh) {
|
||||
if (dev->cfg->hds_thresh) {
|
||||
NL_SET_ERR_MSG(extack, "hds-thresh is not zero");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
#include <net/netdev_queues.h>
|
||||
#include <net/sock.h>
|
||||
#include <linux/ethtool_netlink.h>
|
||||
#include <linux/phy_link_topology.h>
|
||||
@@ -667,6 +668,7 @@ static int ethnl_default_set_doit(struct sk_buff *skb, struct genl_info *info)
|
||||
const struct ethnl_request_ops *ops;
|
||||
struct ethnl_req_info req_info = {};
|
||||
const u8 cmd = info->genlhdr->cmd;
|
||||
struct net_device *dev;
|
||||
int ret;
|
||||
|
||||
ops = ethnl_default_requests[cmd];
|
||||
@@ -688,20 +690,36 @@ static int ethnl_default_set_doit(struct sk_buff *skb, struct genl_info *info)
|
||||
goto out_dev;
|
||||
}
|
||||
|
||||
dev = req_info.dev;
|
||||
|
||||
rtnl_lock();
|
||||
ret = ethnl_ops_begin(req_info.dev);
|
||||
dev->cfg_pending = kmemdup(dev->cfg, sizeof(*dev->cfg),
|
||||
GFP_KERNEL_ACCOUNT);
|
||||
if (!dev->cfg_pending) {
|
||||
ret = -ENOMEM;
|
||||
goto out_tie_cfg;
|
||||
}
|
||||
|
||||
ret = ethnl_ops_begin(dev);
|
||||
if (ret < 0)
|
||||
goto out_rtnl;
|
||||
goto out_free_cfg;
|
||||
|
||||
ret = ops->set(&req_info, info);
|
||||
if (ret <= 0)
|
||||
if (ret < 0)
|
||||
goto out_ops;
|
||||
ethtool_notify(req_info.dev, ops->set_ntf_cmd, NULL);
|
||||
|
||||
swap(dev->cfg, dev->cfg_pending);
|
||||
if (!ret)
|
||||
goto out_ops;
|
||||
ethtool_notify(dev, ops->set_ntf_cmd, NULL);
|
||||
|
||||
ret = 0;
|
||||
out_ops:
|
||||
ethnl_ops_complete(req_info.dev);
|
||||
out_rtnl:
|
||||
ethnl_ops_complete(dev);
|
||||
out_free_cfg:
|
||||
kfree(dev->cfg_pending);
|
||||
out_tie_cfg:
|
||||
dev->cfg_pending = dev->cfg;
|
||||
rtnl_unlock();
|
||||
out_dev:
|
||||
ethnl_parse_header_dev_put(&req_info);
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
#include <net/netdev_queues.h>
|
||||
|
||||
#include "netlink.h"
|
||||
#include "common.h"
|
||||
|
||||
@@ -37,6 +39,10 @@ static int rings_prepare_data(const struct ethnl_req_info *req_base,
|
||||
ret = ethnl_ops_begin(dev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
data->kernel_ringparam.tcp_data_split = dev->cfg->hds_config;
|
||||
data->kernel_ringparam.hds_thresh = dev->cfg->hds_thresh;
|
||||
|
||||
dev->ethtool_ops->get_ringparam(dev, &data->ringparam,
|
||||
&data->kernel_ringparam, info->extack);
|
||||
ethnl_ops_complete(dev);
|
||||
@@ -219,7 +225,7 @@ ethnl_set_rings(struct ethnl_req_info *req_info, struct genl_info *info)
|
||||
|
||||
dev->ethtool_ops->get_ringparam(dev, &ringparam,
|
||||
&kernel_ringparam, info->extack);
|
||||
kernel_ringparam.tcp_data_split = dev->ethtool->hds_config;
|
||||
kernel_ringparam.tcp_data_split = dev->cfg->hds_config;
|
||||
|
||||
ethnl_update_u32(&ringparam.rx_pending, tb[ETHTOOL_A_RINGS_RX], &mod);
|
||||
ethnl_update_u32(&ringparam.rx_mini_pending,
|
||||
@@ -292,13 +298,11 @@ ethnl_set_rings(struct ethnl_req_info *req_info, struct genl_info *info)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
dev->cfg_pending->hds_config = kernel_ringparam.tcp_data_split;
|
||||
dev->cfg_pending->hds_thresh = kernel_ringparam.hds_thresh;
|
||||
|
||||
ret = dev->ethtool_ops->set_ringparam(dev, &ringparam,
|
||||
&kernel_ringparam, info->extack);
|
||||
if (!ret) {
|
||||
dev->ethtool->hds_config = kernel_ringparam.tcp_data_split;
|
||||
dev->ethtool->hds_thresh = kernel_ringparam.hds_thresh;
|
||||
}
|
||||
|
||||
return ret < 0 ? ret : 1;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user