Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'net-ethtool-add-dedicated-rxfh-driver-callbacks'

Jakub Kicinski says:

====================
net: ethtool: add dedicated RXFH driver callbacks

Andrew asked me to plumb the RXFH header fields configuration
thru to netlink. Before we do that we need to clean up the driver
facing API a little bit. Right now RXFH configuration shares the
callbacks with n-tuple filters. The future of n-tuple filters
is uncertain within netlink. Separate the two for clarity both
of the core code and the driver facing API.

This series adds the new callbacks and converts the initial
handful of drivers. There is 31 more driver patches to come,
then we can stop calling rxnfc in the core for rxfh.
====================

Link: https://patch.msgid.link/20250611145949.2674086-1-kuba@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+239 -177
-6
drivers/net/ethernet/google/gve/gve_ethtool.c
··· 798 798 case ETHTOOL_SRXCLSRLDEL: 799 799 err = gve_del_flow_rule(priv, cmd); 800 800 break; 801 - case ETHTOOL_SRXFH: 802 - err = -EOPNOTSUPP; 803 - break; 804 801 default: 805 802 err = -EOPNOTSUPP; 806 803 break; ··· 831 834 break; 832 835 case ETHTOOL_GRXCLSRLALL: 833 836 err = gve_get_flow_rule_ids(priv, cmd, (u32 *)rule_locs); 834 - break; 835 - case ETHTOOL_GRXFH: 836 - err = -EOPNOTSUPP; 837 837 break; 838 838 default: 839 839 err = -EOPNOTSUPP;
-2
drivers/net/ethernet/marvell/mvneta.c
··· 5014 5014 case ETHTOOL_GRXRINGS: 5015 5015 info->data = rxq_number; 5016 5016 return 0; 5017 - case ETHTOOL_GRXFH: 5018 - return -EOPNOTSUPP; 5019 5017 default: 5020 5018 return -EOPNOTSUPP; 5021 5019 }
+1
drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
··· 2616 2616 const struct ethtool_ops mlx5e_ethtool_ops = { 2617 2617 .cap_link_lanes_supported = true, 2618 2618 .cap_rss_ctx_supported = true, 2619 + .rxfh_per_ctx_fields = true, 2619 2620 .rxfh_per_ctx_key = true, 2620 2621 .supported_coalesce_params = ETHTOOL_COALESCE_USECS | 2621 2622 ETHTOOL_COALESCE_MAX_FRAMES |
+56 -55
drivers/net/ethernet/meta/fbnic/fbnic_ethtool.c
··· 531 531 return -1; 532 532 } 533 533 534 - static int 535 - fbnic_get_rss_hash_opts(struct fbnic_net *fbn, struct ethtool_rxnfc *cmd) 536 - { 537 - int hash_opt_idx = fbnic_get_rss_hash_idx(cmd->flow_type); 538 - 539 - if (hash_opt_idx < 0) 540 - return -EINVAL; 541 - 542 - /* Report options from rss_en table in fbn */ 543 - cmd->data = fbn->rss_flow_hash[hash_opt_idx]; 544 - 545 - return 0; 546 - } 547 - 548 534 static int fbnic_get_cls_rule_all(struct fbnic_net *fbn, 549 535 struct ethtool_rxnfc *cmd, 550 536 u32 *rule_locs) ··· 765 779 cmd->data = fbn->num_rx_queues; 766 780 ret = 0; 767 781 break; 768 - case ETHTOOL_GRXFH: 769 - ret = fbnic_get_rss_hash_opts(fbn, cmd); 770 - break; 771 782 case ETHTOOL_GRXCLSRULE: 772 783 ret = fbnic_get_cls_rule(fbn, cmd); 773 784 break; ··· 784 801 } 785 802 786 803 return ret; 787 - } 788 - 789 - #define FBNIC_L2_HASH_OPTIONS \ 790 - (RXH_L2DA | RXH_DISCARD) 791 - #define FBNIC_L3_HASH_OPTIONS \ 792 - (FBNIC_L2_HASH_OPTIONS | RXH_IP_SRC | RXH_IP_DST) 793 - #define FBNIC_L4_HASH_OPTIONS \ 794 - (FBNIC_L3_HASH_OPTIONS | RXH_L4_B_0_1 | RXH_L4_B_2_3) 795 - 796 - static int 797 - fbnic_set_rss_hash_opts(struct fbnic_net *fbn, const struct ethtool_rxnfc *cmd) 798 - { 799 - int hash_opt_idx; 800 - 801 - /* Verify the type requested is correct */ 802 - hash_opt_idx = fbnic_get_rss_hash_idx(cmd->flow_type); 803 - if (hash_opt_idx < 0) 804 - return -EINVAL; 805 - 806 - /* Verify the fields asked for can actually be assigned based on type */ 807 - if (cmd->data & ~FBNIC_L4_HASH_OPTIONS || 808 - (hash_opt_idx > FBNIC_L4_HASH_OPT && 809 - cmd->data & ~FBNIC_L3_HASH_OPTIONS) || 810 - (hash_opt_idx > FBNIC_IP_HASH_OPT && 811 - cmd->data & ~FBNIC_L2_HASH_OPTIONS)) 812 - return -EINVAL; 813 - 814 - fbn->rss_flow_hash[hash_opt_idx] = cmd->data; 815 - 816 - if (netif_running(fbn->netdev)) { 817 - fbnic_rss_reinit(fbn->fbd, fbn); 818 - fbnic_write_rules(fbn->fbd); 819 - } 820 - 821 - return 0; 822 804 } 823 805 824 806 static int fbnic_cls_rule_any_loc(struct fbnic_dev *fbd) ··· 1192 1244 int ret = -EOPNOTSUPP; 1193 1245 1194 1246 switch (cmd->cmd) { 1195 - case ETHTOOL_SRXFH: 1196 - ret = fbnic_set_rss_hash_opts(fbn, cmd); 1197 - break; 1198 1247 case ETHTOOL_SRXCLSRLINS: 1199 1248 ret = fbnic_set_cls_rule_ins(fbn, cmd); 1200 1249 break; ··· 1287 1342 1288 1343 if (changes && netif_running(netdev)) 1289 1344 fbnic_rss_reinit_hw(fbn->fbd, fbn); 1345 + 1346 + return 0; 1347 + } 1348 + 1349 + static int 1350 + fbnic_get_rss_hash_opts(struct net_device *netdev, 1351 + struct ethtool_rxfh_fields *cmd) 1352 + { 1353 + int hash_opt_idx = fbnic_get_rss_hash_idx(cmd->flow_type); 1354 + struct fbnic_net *fbn = netdev_priv(netdev); 1355 + 1356 + if (hash_opt_idx < 0) 1357 + return -EINVAL; 1358 + 1359 + /* Report options from rss_en table in fbn */ 1360 + cmd->data = fbn->rss_flow_hash[hash_opt_idx]; 1361 + 1362 + return 0; 1363 + } 1364 + 1365 + #define FBNIC_L2_HASH_OPTIONS \ 1366 + (RXH_L2DA | RXH_DISCARD) 1367 + #define FBNIC_L3_HASH_OPTIONS \ 1368 + (FBNIC_L2_HASH_OPTIONS | RXH_IP_SRC | RXH_IP_DST) 1369 + #define FBNIC_L4_HASH_OPTIONS \ 1370 + (FBNIC_L3_HASH_OPTIONS | RXH_L4_B_0_1 | RXH_L4_B_2_3) 1371 + 1372 + static int 1373 + fbnic_set_rss_hash_opts(struct net_device *netdev, 1374 + const struct ethtool_rxfh_fields *cmd, 1375 + struct netlink_ext_ack *extack) 1376 + { 1377 + struct fbnic_net *fbn = netdev_priv(netdev); 1378 + int hash_opt_idx; 1379 + 1380 + /* Verify the type requested is correct */ 1381 + hash_opt_idx = fbnic_get_rss_hash_idx(cmd->flow_type); 1382 + if (hash_opt_idx < 0) 1383 + return -EINVAL; 1384 + 1385 + /* Verify the fields asked for can actually be assigned based on type */ 1386 + if (cmd->data & ~FBNIC_L4_HASH_OPTIONS || 1387 + (hash_opt_idx > FBNIC_L4_HASH_OPT && 1388 + cmd->data & ~FBNIC_L3_HASH_OPTIONS) || 1389 + (hash_opt_idx > FBNIC_IP_HASH_OPT && 1390 + cmd->data & ~FBNIC_L2_HASH_OPTIONS)) 1391 + return -EINVAL; 1392 + 1393 + fbn->rss_flow_hash[hash_opt_idx] = cmd->data; 1394 + 1395 + if (netif_running(fbn->netdev)) { 1396 + fbnic_rss_reinit(fbn->fbd, fbn); 1397 + fbnic_write_rules(fbn->fbd); 1398 + } 1290 1399 1291 1400 return 0; 1292 1401 } ··· 1696 1697 .get_rxfh_indir_size = fbnic_get_rxfh_indir_size, 1697 1698 .get_rxfh = fbnic_get_rxfh, 1698 1699 .set_rxfh = fbnic_set_rxfh, 1700 + .get_rxfh_fields = fbnic_get_rss_hash_opts, 1701 + .set_rxfh_fields = fbnic_set_rss_hash_opts, 1699 1702 .create_rxfh_context = fbnic_create_rxfh_context, 1700 1703 .modify_rxfh_context = fbnic_modify_rxfh_context, 1701 1704 .remove_rxfh_context = fbnic_remove_rxfh_context,
+1
drivers/net/ethernet/sfc/ethtool.c
··· 262 262 .set_rxnfc = efx_ethtool_set_rxnfc, 263 263 .get_rxfh_indir_size = efx_ethtool_get_rxfh_indir_size, 264 264 .get_rxfh_key_size = efx_ethtool_get_rxfh_key_size, 265 + .rxfh_per_ctx_fields = true, 265 266 .rxfh_per_ctx_key = true, 266 267 .cap_rss_rxnfc_adds = true, 267 268 .rxfh_priv_size = sizeof(struct efx_rss_context_priv),
+11 -19
drivers/net/hyperv/netvsc_drv.c
··· 1580 1580 } 1581 1581 1582 1582 static int 1583 - netvsc_get_rss_hash_opts(struct net_device_context *ndc, 1584 - struct ethtool_rxnfc *info) 1583 + netvsc_get_rxfh_fields(struct net_device *ndev, 1584 + struct ethtool_rxfh_fields *info) 1585 1585 { 1586 + struct net_device_context *ndc = netdev_priv(ndev); 1586 1587 const u32 l4_flag = RXH_L4_B_0_1 | RXH_L4_B_2_3; 1587 1588 1588 1589 info->data = RXH_IP_SRC | RXH_IP_DST; ··· 1638 1637 case ETHTOOL_GRXRINGS: 1639 1638 info->data = nvdev->num_chn; 1640 1639 return 0; 1641 - 1642 - case ETHTOOL_GRXFH: 1643 - return netvsc_get_rss_hash_opts(ndc, info); 1644 1640 } 1645 1641 return -EOPNOTSUPP; 1646 1642 } 1647 1643 1648 - static int netvsc_set_rss_hash_opts(struct net_device_context *ndc, 1649 - struct ethtool_rxnfc *info) 1644 + static int 1645 + netvsc_set_rxfh_fields(struct net_device *dev, 1646 + const struct ethtool_rxfh_fields *info, 1647 + struct netlink_ext_ack *extack) 1650 1648 { 1649 + struct net_device_context *ndc = netdev_priv(dev); 1650 + 1651 1651 if (info->data == (RXH_IP_SRC | RXH_IP_DST | 1652 1652 RXH_L4_B_0_1 | RXH_L4_B_2_3)) { 1653 1653 switch (info->flow_type) { ··· 1699 1697 1700 1698 return 0; 1701 1699 } 1702 - 1703 - return -EOPNOTSUPP; 1704 - } 1705 - 1706 - static int 1707 - netvsc_set_rxnfc(struct net_device *ndev, struct ethtool_rxnfc *info) 1708 - { 1709 - struct net_device_context *ndc = netdev_priv(ndev); 1710 - 1711 - if (info->cmd == ETHTOOL_SRXFH) 1712 - return netvsc_set_rss_hash_opts(ndc, info); 1713 1700 1714 1701 return -EOPNOTSUPP; 1715 1702 } ··· 1970 1979 .set_channels = netvsc_set_channels, 1971 1980 .get_ts_info = ethtool_op_get_ts_info, 1972 1981 .get_rxnfc = netvsc_get_rxnfc, 1973 - .set_rxnfc = netvsc_set_rxnfc, 1974 1982 .get_rxfh_key_size = netvsc_get_rxfh_key_size, 1975 1983 .get_rxfh_indir_size = netvsc_rss_indir_size, 1976 1984 .get_rxfh = netvsc_get_rxfh, 1977 1985 .set_rxfh = netvsc_set_rxfh, 1986 + .get_rxfh_fields = netvsc_get_rxfh_fields, 1987 + .set_rxfh_fields = netvsc_set_rxfh_fields, 1978 1988 .get_link_ksettings = netvsc_get_link_ksettings, 1979 1989 .set_link_ksettings = netvsc_set_link_ksettings, 1980 1990 .get_ringparam = netvsc_get_ringparam,
+18 -29
drivers/net/virtio_net.c
··· 4193 4193 netdev_rss_key_fill(vi->rss_hash_key_data, vi->rss_key_size); 4194 4194 } 4195 4195 4196 - static void virtnet_get_hashflow(const struct virtnet_info *vi, struct ethtool_rxnfc *info) 4196 + static int virtnet_get_hashflow(struct net_device *dev, 4197 + struct ethtool_rxfh_fields *info) 4197 4198 { 4199 + struct virtnet_info *vi = netdev_priv(dev); 4200 + 4198 4201 info->data = 0; 4199 4202 switch (info->flow_type) { 4200 4203 case TCP_V4_FLOW: ··· 4246 4243 info->data = 0; 4247 4244 break; 4248 4245 } 4246 + 4247 + return 0; 4249 4248 } 4250 4249 4251 - static bool virtnet_set_hashflow(struct virtnet_info *vi, struct ethtool_rxnfc *info) 4250 + static int virtnet_set_hashflow(struct net_device *dev, 4251 + const struct ethtool_rxfh_fields *info, 4252 + struct netlink_ext_ack *extack) 4252 4253 { 4254 + struct virtnet_info *vi = netdev_priv(dev); 4253 4255 u32 new_hashtypes = vi->rss_hash_types_saved; 4254 4256 bool is_disable = info->data & RXH_DISCARD; 4255 4257 bool is_l4 = info->data == (RXH_IP_SRC | RXH_IP_DST | RXH_L4_B_0_1 | RXH_L4_B_2_3); 4256 4258 4257 4259 /* supports only 'sd', 'sdfn' and 'r' */ 4258 4260 if (!((info->data == (RXH_IP_SRC | RXH_IP_DST)) | is_l4 | is_disable)) 4259 - return false; 4261 + return -EINVAL; 4260 4262 4261 4263 switch (info->flow_type) { 4262 4264 case TCP_V4_FLOW: ··· 4300 4292 break; 4301 4293 default: 4302 4294 /* unsupported flow */ 4303 - return false; 4295 + return -EINVAL; 4304 4296 } 4305 4297 4306 4298 /* if unsupported hashtype was set */ 4307 4299 if (new_hashtypes != (new_hashtypes & vi->rss_hash_types_supported)) 4308 - return false; 4300 + return -EINVAL; 4309 4301 4310 4302 if (new_hashtypes != vi->rss_hash_types_saved) { 4311 4303 vi->rss_hash_types_saved = new_hashtypes; 4312 4304 vi->rss_hdr->hash_types = cpu_to_le32(vi->rss_hash_types_saved); 4313 4305 if (vi->dev->features & NETIF_F_RXHASH) 4314 - return virtnet_commit_rss_command(vi); 4306 + if (!virtnet_commit_rss_command(vi)) 4307 + return -EINVAL; 4315 4308 } 4316 4309 4317 - return true; 4310 + return 0; 4318 4311 } 4319 4312 4320 4313 static void virtnet_get_drvinfo(struct net_device *dev, ··· 5549 5540 case ETHTOOL_GRXRINGS: 5550 5541 info->data = vi->curr_queue_pairs; 5551 5542 break; 5552 - case ETHTOOL_GRXFH: 5553 - virtnet_get_hashflow(vi, info); 5554 - break; 5555 - default: 5556 - rc = -EOPNOTSUPP; 5557 - } 5558 - 5559 - return rc; 5560 - } 5561 - 5562 - static int virtnet_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *info) 5563 - { 5564 - struct virtnet_info *vi = netdev_priv(dev); 5565 - int rc = 0; 5566 - 5567 - switch (info->cmd) { 5568 - case ETHTOOL_SRXFH: 5569 - if (!virtnet_set_hashflow(vi, info)) 5570 - rc = -EINVAL; 5571 - 5572 - break; 5573 5543 default: 5574 5544 rc = -EOPNOTSUPP; 5575 5545 } ··· 5579 5591 .get_rxfh_indir_size = virtnet_get_rxfh_indir_size, 5580 5592 .get_rxfh = virtnet_get_rxfh, 5581 5593 .set_rxfh = virtnet_set_rxfh, 5594 + .get_rxfh_fields = virtnet_get_hashflow, 5595 + .set_rxfh_fields = virtnet_set_hashflow, 5582 5596 .get_rxnfc = virtnet_get_rxnfc, 5583 - .set_rxnfc = virtnet_set_rxnfc, 5584 5597 }; 5585 5598 5586 5599 static void virtnet_get_queue_stats_rx(struct net_device *dev, int i,
+25 -49
drivers/net/vmxnet3/vmxnet3_ethtool.c
··· 833 833 } 834 834 835 835 static int 836 - vmxnet3_get_rss_hash_opts(struct vmxnet3_adapter *adapter, 837 - struct ethtool_rxnfc *info) 836 + vmxnet3_get_rss_hash_opts(struct net_device *netdev, 837 + struct ethtool_rxfh_fields *info) 838 838 { 839 + struct vmxnet3_adapter *adapter = netdev_priv(netdev); 839 840 enum Vmxnet3_RSSField rss_fields; 841 + 842 + if (!VMXNET3_VERSION_GE_4(adapter)) 843 + return -EOPNOTSUPP; 844 + #ifdef VMXNET3_RSS 845 + if (!adapter->rss) 846 + return -EOPNOTSUPP; 847 + #endif 840 848 841 849 if (netif_running(adapter->netdev)) { 842 850 unsigned long flags; ··· 908 900 909 901 static int 910 902 vmxnet3_set_rss_hash_opt(struct net_device *netdev, 911 - struct vmxnet3_adapter *adapter, 912 - struct ethtool_rxnfc *nfc) 903 + const struct ethtool_rxfh_fields *nfc, 904 + struct netlink_ext_ack *extack) 913 905 { 914 - enum Vmxnet3_RSSField rss_fields = adapter->rss_fields; 906 + struct vmxnet3_adapter *adapter = netdev_priv(netdev); 907 + enum Vmxnet3_RSSField rss_fields; 908 + 909 + if (!VMXNET3_VERSION_GE_4(adapter)) 910 + return -EOPNOTSUPP; 911 + #ifdef VMXNET3_RSS 912 + if (!adapter->rss) 913 + return -EOPNOTSUPP; 914 + #endif 915 + 916 + rss_fields = adapter->rss_fields; 915 917 916 918 /* RSS does not support anything other than hashing 917 919 * to queues on src and dst IPs and ports ··· 1092 1074 case ETHTOOL_GRXRINGS: 1093 1075 info->data = adapter->num_rx_queues; 1094 1076 break; 1095 - case ETHTOOL_GRXFH: 1096 - if (!VMXNET3_VERSION_GE_4(adapter)) { 1097 - err = -EOPNOTSUPP; 1098 - break; 1099 - } 1100 - #ifdef VMXNET3_RSS 1101 - if (!adapter->rss) { 1102 - err = -EOPNOTSUPP; 1103 - break; 1104 - } 1105 - #endif 1106 - err = vmxnet3_get_rss_hash_opts(adapter, info); 1107 - break; 1108 1077 default: 1109 1078 err = -EOPNOTSUPP; 1110 1079 break; 1111 1080 } 1112 1081 1113 - return err; 1114 - } 1115 - 1116 - static int 1117 - vmxnet3_set_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *info) 1118 - { 1119 - struct vmxnet3_adapter *adapter = netdev_priv(netdev); 1120 - int err = 0; 1121 - 1122 - if (!VMXNET3_VERSION_GE_4(adapter)) { 1123 - err = -EOPNOTSUPP; 1124 - goto done; 1125 - } 1126 - #ifdef VMXNET3_RSS 1127 - if (!adapter->rss) { 1128 - err = -EOPNOTSUPP; 1129 - goto done; 1130 - } 1131 - #endif 1132 - 1133 - switch (info->cmd) { 1134 - case ETHTOOL_SRXFH: 1135 - err = vmxnet3_set_rss_hash_opt(netdev, adapter, info); 1136 - break; 1137 - default: 1138 - err = -EOPNOTSUPP; 1139 - break; 1140 - } 1141 - 1142 - done: 1143 1082 return err; 1144 1083 } 1145 1084 ··· 1336 1361 .get_ringparam = vmxnet3_get_ringparam, 1337 1362 .set_ringparam = vmxnet3_set_ringparam, 1338 1363 .get_rxnfc = vmxnet3_get_rxnfc, 1339 - .set_rxnfc = vmxnet3_set_rxnfc, 1340 1364 #ifdef VMXNET3_RSS 1341 1365 .get_rxfh_indir_size = vmxnet3_get_rss_indir_size, 1342 1366 .get_rxfh = vmxnet3_get_rss, 1343 1367 .set_rxfh = vmxnet3_set_rss, 1344 1368 #endif 1369 + .get_rxfh_fields = vmxnet3_get_rss_hash_opts, 1370 + .set_rxfh_fields = vmxnet3_set_rss_hash_opt, 1345 1371 .get_link_ksettings = vmxnet3_get_link_ksettings, 1346 1372 .get_channels = vmxnet3_get_channels, 1347 1373 };
+23
include/linux/ethtool.h
··· 826 826 }; 827 827 828 828 /** 829 + * struct ethtool_rxfh_fields - Rx Flow Hashing (RXFH) header field config 830 + * @data: which header fields are used for hashing, bitmask of RXH_* defines 831 + * @flow_type: L2-L4 network traffic flow type 832 + * @rss_context: RSS context, will only be used if rxfh_per_ctx_fields is 833 + * set in struct ethtool_ops 834 + */ 835 + struct ethtool_rxfh_fields { 836 + u32 data; 837 + u32 flow_type; 838 + u32 rss_context; 839 + }; 840 + 841 + /** 829 842 * struct kernel_ethtool_ts_info - kernel copy of struct ethtool_ts_info 830 843 * @cmd: command number = %ETHTOOL_GET_TS_INFO 831 844 * @so_timestamping: bit mask of the sum of the supported SO_TIMESTAMPING flags ··· 868 855 * @cap_rss_ctx_supported: indicates if the driver supports RSS 869 856 * contexts via legacy API, drivers implementing @create_rxfh_context 870 857 * do not have to set this bit. 858 + * @rxfh_per_ctx_fields: device supports selecting different header fields 859 + * for Rx hash calculation and RSS for each additional context. 871 860 * @rxfh_per_ctx_key: device supports setting different RSS key for each 872 861 * additional context. Netlink API should report hfunc, key, and input_xfrm 873 862 * for every context, not just context 0. ··· 983 968 * will remain unchanged. 984 969 * Returns a negative error code or zero. An error code must be returned 985 970 * if at least one unsupported change was requested. 971 + * @get_rxfh_fields: Get header fields used for flow hashing. 972 + * @set_rxfh_fields: Set header fields used for flow hashing. 986 973 * @create_rxfh_context: Create a new RSS context with the specified RX flow 987 974 * hash indirection table, hash key, and hash function. 988 975 * The &struct ethtool_rxfh_context for this context is passed in @ctx; ··· 1101 1084 u32 supported_input_xfrm:8; 1102 1085 u32 cap_link_lanes_supported:1; 1103 1086 u32 cap_rss_ctx_supported:1; 1087 + u32 rxfh_per_ctx_fields:1; 1104 1088 u32 rxfh_per_ctx_key:1; 1105 1089 u32 cap_rss_rxnfc_adds:1; 1106 1090 u32 rxfh_indir_space; ··· 1171 1153 int (*get_rxfh)(struct net_device *, struct ethtool_rxfh_param *); 1172 1154 int (*set_rxfh)(struct net_device *, struct ethtool_rxfh_param *, 1173 1155 struct netlink_ext_ack *extack); 1156 + int (*get_rxfh_fields)(struct net_device *, 1157 + struct ethtool_rxfh_fields *); 1158 + int (*set_rxfh_fields)(struct net_device *, 1159 + const struct ethtool_rxfh_fields *, 1160 + struct netlink_ext_ack *extack); 1174 1161 int (*create_rxfh_context)(struct net_device *, 1175 1162 struct ethtool_rxfh_context *ctx, 1176 1163 const struct ethtool_rxfh_param *rxfh,
+104 -17
net/ethtool/ioctl.c
··· 1048 1048 continue; 1049 1049 1050 1050 info.flow_type = i; 1051 - err = ops->get_rxnfc(dev, &info, NULL); 1052 - if (err) 1053 - continue; 1051 + 1052 + if (ops->get_rxfh_fields) { 1053 + struct ethtool_rxfh_fields fields = { 1054 + .flow_type = info.flow_type, 1055 + }; 1056 + 1057 + if (ops->get_rxfh_fields(dev, &fields)) 1058 + continue; 1059 + 1060 + info.data = fields.data; 1061 + } else { 1062 + if (ops->get_rxnfc(dev, &info, NULL)) 1063 + continue; 1064 + } 1054 1065 1055 1066 err = ethtool_check_xfrm_rxfh(input_xfrm, info.data); 1056 1067 if (err) ··· 1069 1058 } 1070 1059 1071 1060 return 0; 1061 + } 1062 + 1063 + static noinline_for_stack int 1064 + ethtool_set_rxfh_fields(struct net_device *dev, u32 cmd, void __user *useraddr) 1065 + { 1066 + const struct ethtool_ops *ops = dev->ethtool_ops; 1067 + struct ethtool_rxfh_fields fields = {}; 1068 + struct ethtool_rxnfc info; 1069 + size_t info_size = sizeof(info); 1070 + int rc; 1071 + 1072 + if (!ops->set_rxnfc && !ops->set_rxfh_fields) 1073 + return -EOPNOTSUPP; 1074 + 1075 + rc = ethtool_rxnfc_copy_struct(cmd, &info, &info_size, useraddr); 1076 + if (rc) 1077 + return rc; 1078 + 1079 + if (info.flow_type & FLOW_RSS && info.rss_context && 1080 + !ops->rxfh_per_ctx_fields) 1081 + return -EINVAL; 1082 + 1083 + if (ops->get_rxfh) { 1084 + struct ethtool_rxfh_param rxfh = {}; 1085 + 1086 + rc = ops->get_rxfh(dev, &rxfh); 1087 + if (rc) 1088 + return rc; 1089 + 1090 + rc = ethtool_check_xfrm_rxfh(rxfh.input_xfrm, info.data); 1091 + if (rc) 1092 + return rc; 1093 + } 1094 + 1095 + if (!ops->set_rxfh_fields) 1096 + return ops->set_rxnfc(dev, &info); 1097 + 1098 + fields.data = info.data; 1099 + fields.flow_type = info.flow_type & ~FLOW_RSS; 1100 + if (info.flow_type & FLOW_RSS) 1101 + fields.rss_context = info.rss_context; 1102 + 1103 + return ops->set_rxfh_fields(dev, &fields, NULL); 1104 + } 1105 + 1106 + static noinline_for_stack int 1107 + ethtool_get_rxfh_fields(struct net_device *dev, u32 cmd, void __user *useraddr) 1108 + { 1109 + struct ethtool_rxnfc info; 1110 + size_t info_size = sizeof(info); 1111 + const struct ethtool_ops *ops = dev->ethtool_ops; 1112 + int ret; 1113 + 1114 + if (!ops->get_rxnfc && !ops->get_rxfh_fields) 1115 + return -EOPNOTSUPP; 1116 + 1117 + ret = ethtool_rxnfc_copy_struct(cmd, &info, &info_size, useraddr); 1118 + if (ret) 1119 + return ret; 1120 + 1121 + if (info.flow_type & FLOW_RSS && info.rss_context && 1122 + !ops->rxfh_per_ctx_fields) 1123 + return -EINVAL; 1124 + 1125 + if (ops->get_rxfh_fields) { 1126 + struct ethtool_rxfh_fields fields = { 1127 + .flow_type = info.flow_type & ~FLOW_RSS, 1128 + }; 1129 + 1130 + if (info.flow_type & FLOW_RSS) 1131 + fields.rss_context = info.rss_context; 1132 + 1133 + ret = ops->get_rxfh_fields(dev, &fields); 1134 + if (ret < 0) 1135 + return ret; 1136 + 1137 + info.data = fields.data; 1138 + } else { 1139 + ret = ops->get_rxnfc(dev, &info, NULL); 1140 + if (ret < 0) 1141 + return ret; 1142 + } 1143 + 1144 + return ethtool_rxnfc_copy_to_user(useraddr, &info, info_size, NULL); 1072 1145 } 1073 1146 1074 1147 static noinline_for_stack int ethtool_set_rxnfc(struct net_device *dev, ··· 1181 1086 if (info.rss_context && 1182 1087 !xa_load(&dev->ethtool->rss_ctx, info.rss_context)) 1183 1088 return -EINVAL; 1184 - } 1185 - 1186 - if (cmd == ETHTOOL_SRXFH && ops->get_rxfh) { 1187 - struct ethtool_rxfh_param rxfh = {}; 1188 - 1189 - rc = ops->get_rxfh(dev, &rxfh); 1190 - if (rc) 1191 - return rc; 1192 - 1193 - rc = ethtool_check_xfrm_rxfh(rxfh.input_xfrm, info.data); 1194 - if (rc) 1195 - return rc; 1196 1089 } 1197 1090 1198 1091 rc = ops->set_rxnfc(dev, &info); ··· 1528 1445 u8 *rss_config; 1529 1446 int ret; 1530 1447 1531 - if (!ops->get_rxnfc || !ops->set_rxfh) 1448 + if ((!ops->get_rxnfc && !ops->get_rxfh_fields) || !ops->set_rxfh) 1532 1449 return -EOPNOTSUPP; 1533 1450 1534 1451 if (ops->get_rxfh_indir_size) ··· 3422 3339 dev->ethtool_ops->set_priv_flags); 3423 3340 break; 3424 3341 case ETHTOOL_GRXFH: 3342 + rc = ethtool_get_rxfh_fields(dev, ethcmd, useraddr); 3343 + break; 3344 + case ETHTOOL_SRXFH: 3345 + rc = ethtool_set_rxfh_fields(dev, ethcmd, useraddr); 3346 + break; 3425 3347 case ETHTOOL_GRXRINGS: 3426 3348 case ETHTOOL_GRXCLSRLCNT: 3427 3349 case ETHTOOL_GRXCLSRULE: 3428 3350 case ETHTOOL_GRXCLSRLALL: 3429 3351 rc = ethtool_get_rxnfc(dev, ethcmd, useraddr); 3430 3352 break; 3431 - case ETHTOOL_SRXFH: 3432 3353 case ETHTOOL_SRXCLSRLDEL: 3433 3354 case ETHTOOL_SRXCLSRLINS: 3434 3355 rc = ethtool_set_rxnfc(dev, ethcmd, useraddr);