When tcp-data-split is UNKNOWN mode, drivers arbitrarily handle it. For example, bnxt_en driver automatically enables if at least one of LRO/GRO/JUMBO is enabled. If tcp-data-split is UNKNOWN and LRO is enabled, a driver returns ENABLES of tcp-data-split, not UNKNOWN. So, `ethtool -g eth0` shows tcp-data-split is enabled. The problem is in the setting situation. In the ethnl_set_rings(), it first calls get_ringparam() to get the current driver's config. At that moment, if driver's tcp-data-split config is UNKNOWN, it returns ENABLE if LRO/GRO/JUMBO is enabled. Then, it sets values from the user and driver's current config to kernel_ethtool_ringparam. Last it calls .set_ringparam(). The driver, especially bnxt_en driver receives ETHTOOL_TCP_DATA_SPLIT_ENABLED. But it can't distinguish whether it is set by the user or just the current config. The new tcp_data_split_mod member indicates the tcp-data-split value is explicitly set by the user. So the driver can handle ETHTOOL_TCP_DATA_SPLIT_ENABLED properly. Signed-off-by: Taehee Yoo <ap420073@xxxxxxxxx> --- v5: - Patch added. include/linux/ethtool.h | 2 ++ net/ethtool/rings.c | 3 +++ 2 files changed, 5 insertions(+) diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h index 1199e308c8dd..ecd52b99a63a 100644 --- a/include/linux/ethtool.h +++ b/include/linux/ethtool.h @@ -73,6 +73,7 @@ enum { * struct kernel_ethtool_ringparam - RX/TX ring configuration * @rx_buf_len: Current length of buffers on the rx ring. * @tcp_data_split: Scatter packet headers and data to separate buffers + * @tcp_data_split_mod: Updated tcp-data-split from user * @tx_push: The flag of tx push mode * @rx_push: The flag of rx push mode * @cqe_size: Size of TX/RX completion queue event @@ -82,6 +83,7 @@ enum { struct kernel_ethtool_ringparam { u32 rx_buf_len; u8 tcp_data_split; + bool tcp_data_split_mod; u8 tx_push; u8 rx_push; u32 cqe_size; diff --git a/net/ethtool/rings.c b/net/ethtool/rings.c index b7865a14fdf8..c12ebb61394d 100644 --- a/net/ethtool/rings.c +++ b/net/ethtool/rings.c @@ -250,6 +250,9 @@ ethnl_set_rings(struct ethnl_req_info *req_info, struct genl_info *info) return -EINVAL; } + if (tb[ETHTOOL_A_RINGS_TCP_DATA_SPLIT]) + kernel_ringparam.tcp_data_split_mod = true; + ret = dev->ethtool_ops->set_ringparam(dev, &ringparam, &kernel_ringparam, info->extack); return ret < 0 ? ret : 1; -- 2.34.1