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. When user updates ring parameter, the new hds_config value is updated and current hds_config value is stored to old_hdsconfig. Driver's .set_ringparam() callback can distinguish a passed tcp-data-split value is came from user explicitly. If .set_ringparam() is failed, hds_config is rollbacked immediately.
Unified · Split
| @@ -1157,12 +1157,14 @@ int ethtool_virtdev_set_link_ksettings(struct net_device *dev, · 1156 unmodified lines | |||
| 1157 | * @rss_ctx: XArray of custom RSS contexts | 1157 | * @rss_ctx: XArray of custom RSS contexts |
| 1158 | * @rss_lock: Protects entries in @rss_ctx. May be taken from | 1158 | * @rss_lock: Protects entries in @rss_ctx. May be taken from |
| 1159 | * within RTNL. | 1159 | * within RTNL. |
| 1160 | * @hds_config: HDS value from userspace. | ||
| 1160 | * @wol_enabled: Wake-on-LAN is enabled | 1161 | * @wol_enabled: Wake-on-LAN is enabled |
| 1161 | * @module_fw_flash_in_progress: Module firmware flashing is in progress. | 1162 | * @module_fw_flash_in_progress: Module firmware flashing is in progress. |
| 1162 | */ | 1163 | */ |
| 1163 | struct ethtool_netdev_state { | 1164 | struct ethtool_netdev_state { |
| 1164 | struct xarray rss_ctx; | 1165 | struct xarray rss_ctx; |
| 1165 | struct mutex rss_lock; | 1166 | struct mutex rss_lock; |
| 1167 | u8 hds_config; | ||
| 1166 | unsigned wol_enabled:1; | 1168 | unsigned wol_enabled:1; |
| 1167 | unsigned module_fw_flash_in_progress:1; | 1169 | unsigned module_fw_flash_in_progress:1; |
| 1168 | }; | 1170 | }; |
| @@ -4082,6 +4082,7 @@ struct sk_buff *dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev, · 4081 unmodified lines | |||
| 4082 | int bpf_xdp_link_attach(const union bpf_attr *attr, struct bpf_prog *prog); | 4082 | int bpf_xdp_link_attach(const union bpf_attr *attr, struct bpf_prog *prog); |
| 4083 | u8 dev_xdp_prog_count(struct net_device *dev); | 4083 | u8 dev_xdp_prog_count(struct net_device *dev); |
| 4084 | int dev_xdp_propagate(struct net_device *dev, struct netdev_bpf *bpf); | 4084 | int dev_xdp_propagate(struct net_device *dev, struct netdev_bpf *bpf); |
| 4085 | u8 dev_xdp_sb_prog_count(struct net_device *dev); | ||
| 4085 | u32 dev_xdp_prog_id(struct net_device *dev, enum bpf_xdp_mode mode); | 4086 | u32 dev_xdp_prog_id(struct net_device *dev, enum bpf_xdp_mode mode); |
| 4086 | 4087 | ||
| 4087 | u32 dev_get_min_mp_channel_count(const struct net_device *dev); | 4088 | u32 dev_get_min_mp_channel_count(const struct net_device *dev); |
| @@ -9550,6 +9550,18 @@ u8 dev_xdp_prog_count(struct net_device *dev) · 9549 unmodified lines | |||
| 9550 | } | 9550 | } |
| 9551 | EXPORT_SYMBOL_GPL(dev_xdp_prog_count); | 9551 | EXPORT_SYMBOL_GPL(dev_xdp_prog_count); |
| 9552 | 9552 | ||
| 9553 | u8 dev_xdp_sb_prog_count(struct net_device *dev) | ||
| 9554 | { | ||
| 9555 | u8 count = 0; | ||
| 9556 | int i; | ||
| 9557 | |||
| 9558 | for (i = 0; i < __MAX_XDP_MODE; i++) | ||
| 9559 | if (dev->xdp_state[i].prog && | ||
| 9560 | !dev->xdp_state[i].prog->aux->xdp_has_frags) | ||
| 9561 | count++; | ||
| 9562 | return count; | ||
| 9563 | } | ||
| 9564 | |||
| 9553 | int dev_xdp_propagate(struct net_device *dev, struct netdev_bpf *bpf) | 9565 | int dev_xdp_propagate(struct net_device *dev, struct netdev_bpf *bpf) |
| 9554 | { | 9566 | { |
| 9555 | if (!dev->netdev_ops->ndo_bpf) | 9567 | if (!dev->netdev_ops->ndo_bpf) |
| @@ -203,6 +203,7 @@ ethnl_set_rings(struct ethnl_req_info *req_info, struct genl_info *info) · 202 unmodified lines | |||
| 203 | 203 | ||
| 204 | dev->ethtool_ops->get_ringparam(dev, &ringparam, | 204 | dev->ethtool_ops->get_ringparam(dev, &ringparam, |
| 205 | &kernel_ringparam, info->extack); | 205 | &kernel_ringparam, info->extack); |
| 206 | kernel_ringparam.tcp_data_split = dev->ethtool->hds_config; | ||
| 206 | 207 | ||
| 207 | ethnl_update_u32(&ringparam.rx_pending, tb[ETHTOOL_A_RINGS_RX], &mod); | 208 | ethnl_update_u32(&ringparam.rx_pending, tb[ETHTOOL_A_RINGS_RX], &mod); |
| 208 | ethnl_update_u32(&ringparam.rx_mini_pending, | 209 | ethnl_update_u32(&ringparam.rx_mini_pending, |
| @@ -225,6 +226,14 @@ ethnl_set_rings(struct ethnl_req_info *req_info, struct genl_info *info) · 16 unmodified lines | |||
| 225 | if (!mod) | 226 | if (!mod) |
| 226 | return 0; | 227 | return 0; |
| 227 | 228 | ||
| 229 | if (kernel_ringparam.tcp_data_split == ETHTOOL_TCP_DATA_SPLIT_ENABLED && | ||
| 230 | dev_xdp_sb_prog_count(dev)) { | ||
| 231 | NL_SET_ERR_MSG_ATTR(info->extack, | ||
| 232 | tb[ETHTOOL_A_RINGS_TCP_DATA_SPLIT], | ||
| 233 | "tcp-data-split can not be enabled with single buffer XDP"); | ||
| 234 | return -EINVAL; | ||
| 235 | } | ||
| 236 | |||
| 228 | /* ensure new ring parameters are within limits */ | 237 | /* ensure new ring parameters are within limits */ |
| 229 | if (ringparam.rx_pending > ringparam.rx_max_pending) | 238 | if (ringparam.rx_pending > ringparam.rx_max_pending) |
| 230 | err_attr = tb[ETHTOOL_A_RINGS_RX]; | 239 | err_attr = tb[ETHTOOL_A_RINGS_RX]; |
| @@ -252,6 +261,9 @@ ethnl_set_rings(struct ethnl_req_info *req_info, struct genl_info *info) · 21 unmodified lines | |||
| 252 | 261 | ||
| 253 | ret = dev->ethtool_ops->set_ringparam(dev, &ringparam, | 262 | ret = dev->ethtool_ops->set_ringparam(dev, &ringparam, |
| 254 | &kernel_ringparam, info->extack); | 263 | &kernel_ringparam, info->extack); |
| 264 | if (!ret) | ||
| 265 | dev->ethtool->hds_config = kernel_ringparam.tcp_data_split; | ||
| 266 | |||
| 255 | return ret < 0 ? ret : 1; | 267 | return ret < 0 ? ret : 1; |
| 256 | } | 268 | } |
| 257 | 269 | ||