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

gve: Add RSS cache for non RSS device option scenario

Not all the devices have the capability for the driver to query for the
registered RSS configuration. The driver can discover this by checking
the relevant device option during setup. If it cannot, the driver needs
to store the RSS config cache and directly return such cache when
queried by the ethtool. RSS config is inited when driver probes. Also the
default RSS config will be adjusted when there is RX queue count change.

At this point, only keys of GVE_RSS_KEY_SIZE and indirection tables of
GVE_RSS_INDIR_SIZE are supported.

Signed-off-by: Ziwei Xiao <ziweixiao@google.com>
Reviewed-by: Harshitha Ramamurthy <hramamurthy@google.com>
Reviewed-by: Willem de Bruijn <willemb@google.com>
Signed-off-by: Praveen Kaligineedi <pkaligineedi@google.com>
Signed-off-by: Jeroen de Borst <jeroendb@google.com>
Link: https://patch.msgid.link/20250219200451.3348166-1-jeroendb@google.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Ziwei Xiao and committed by
Jakub Kicinski
4b9c7d8f c451715d

+205 -23
+15 -1
drivers/net/ethernet/google/gve/gve.h
··· 68 68 #define GVE_FLOW_RULE_IDS_CACHE_SIZE \ 69 69 (GVE_ADMINQ_BUFFER_SIZE / sizeof(((struct gve_adminq_queried_flow_rule *)0)->location)) 70 70 71 + #define GVE_RSS_KEY_SIZE 40 72 + #define GVE_RSS_INDIR_SIZE 128 73 + 71 74 #define GVE_XDP_ACTIONS 5 72 75 73 76 #define GVE_GQ_TX_MIN_PKT_DESC_BYTES 182 ··· 675 672 u16 packet_buffer_size; 676 673 bool raw_addressing; 677 674 bool enable_header_split; 675 + bool reset_rss; 678 676 679 677 /* Allocated resources are returned here */ 680 678 struct gve_rx_ring *rx; ··· 724 720 /* The total number of queried rules that stored in the caches */ 725 721 u32 rules_cache_num; 726 722 u32 rule_ids_cache_num; 723 + }; 724 + 725 + struct gve_rss_config { 726 + u8 *hash_key; 727 + u32 *hash_lut; 727 728 }; 728 729 729 730 struct gve_priv { ··· 851 842 852 843 u16 rss_key_size; 853 844 u16 rss_lut_size; 845 + bool cache_rss_config; 846 + struct gve_rss_config rss_config; 854 847 }; 855 848 856 849 enum gve_service_task_flags_bit { ··· 1231 1220 struct gve_rx_alloc_rings_cfg *rx_alloc_cfg); 1232 1221 int gve_adjust_queues(struct gve_priv *priv, 1233 1222 struct gve_queue_config new_rx_config, 1234 - struct gve_queue_config new_tx_config); 1223 + struct gve_queue_config new_tx_config, 1224 + bool reset_rss); 1235 1225 /* flow steering rule */ 1236 1226 int gve_get_flow_rule_entry(struct gve_priv *priv, struct ethtool_rxnfc *cmd); 1237 1227 int gve_get_flow_rule_ids(struct gve_priv *priv, struct ethtool_rxnfc *cmd, u32 *rule_locs); 1238 1228 int gve_add_flow_rule(struct gve_priv *priv, struct ethtool_rxnfc *cmd); 1239 1229 int gve_del_flow_rule(struct gve_priv *priv, struct ethtool_rxnfc *cmd); 1240 1230 int gve_flow_rules_reset(struct gve_priv *priv); 1231 + /* RSS config */ 1232 + int gve_init_rss_config(struct gve_priv *priv, u16 num_queues); 1241 1233 /* report stats handling */ 1242 1234 void gve_handle_report_stats(struct gve_priv *priv); 1243 1235 /* exported by ethtool.c */
+53 -13
drivers/net/ethernet/google/gve/gve_adminq.c
··· 885 885 priv->min_rx_desc_cnt = priv->rx_desc_cnt; 886 886 } 887 887 888 + static void gve_set_default_rss_sizes(struct gve_priv *priv) 889 + { 890 + if (!gve_is_gqi(priv)) { 891 + priv->rss_key_size = GVE_RSS_KEY_SIZE; 892 + priv->rss_lut_size = GVE_RSS_INDIR_SIZE; 893 + priv->cache_rss_config = true; 894 + } 895 + } 896 + 888 897 static void gve_enable_supported_features(struct gve_priv *priv, 889 898 u32 supported_features_mask, 890 899 const struct gve_device_option_jumbo_frames ··· 977 968 be16_to_cpu(dev_op_rss_config->hash_key_size); 978 969 priv->rss_lut_size = 979 970 be16_to_cpu(dev_op_rss_config->hash_lut_size); 971 + priv->cache_rss_config = false; 972 + dev_dbg(&priv->pdev->dev, 973 + "RSS device option enabled with key size of %u, lut size of %u.\n", 974 + priv->rss_key_size, priv->rss_lut_size); 980 975 } 981 976 } 982 977 ··· 1064 1051 1065 1052 /* set default descriptor counts */ 1066 1053 gve_set_default_desc_cnt(priv, descriptor); 1054 + 1055 + gve_set_default_rss_sizes(priv); 1067 1056 1068 1057 /* DQO supports LRO. */ 1069 1058 if (!gve_is_gqi(priv)) ··· 1291 1276 1292 1277 int gve_adminq_configure_rss(struct gve_priv *priv, struct ethtool_rxfh_param *rxfh) 1293 1278 { 1279 + const u32 *hash_lut_to_config = NULL; 1280 + const u8 *hash_key_to_config = NULL; 1294 1281 dma_addr_t lut_bus = 0, key_bus = 0; 1295 - u16 key_size = 0, lut_size = 0; 1296 1282 union gve_adminq_command cmd; 1297 1283 __be32 *lut = NULL; 1298 1284 u8 hash_alg = 0; ··· 1303 1287 1304 1288 switch (rxfh->hfunc) { 1305 1289 case ETH_RSS_HASH_NO_CHANGE: 1306 - break; 1290 + fallthrough; 1307 1291 case ETH_RSS_HASH_TOP: 1308 1292 hash_alg = ETH_RSS_HASH_TOP; 1309 1293 break; ··· 1312 1296 } 1313 1297 1314 1298 if (rxfh->indir) { 1315 - lut_size = priv->rss_lut_size; 1299 + if (rxfh->indir_size != priv->rss_lut_size) 1300 + return -EINVAL; 1301 + 1302 + hash_lut_to_config = rxfh->indir; 1303 + } else if (priv->cache_rss_config) { 1304 + hash_lut_to_config = priv->rss_config.hash_lut; 1305 + } 1306 + 1307 + if (hash_lut_to_config) { 1316 1308 lut = dma_alloc_coherent(&priv->pdev->dev, 1317 - lut_size * sizeof(*lut), 1309 + priv->rss_lut_size * sizeof(*lut), 1318 1310 &lut_bus, GFP_KERNEL); 1319 1311 if (!lut) 1320 1312 return -ENOMEM; 1321 1313 1322 1314 for (i = 0; i < priv->rss_lut_size; i++) 1323 - lut[i] = cpu_to_be32(rxfh->indir[i]); 1315 + lut[i] = cpu_to_be32(hash_lut_to_config[i]); 1324 1316 } 1325 1317 1326 1318 if (rxfh->key) { 1327 - key_size = priv->rss_key_size; 1319 + if (rxfh->key_size != priv->rss_key_size) { 1320 + err = -EINVAL; 1321 + goto out; 1322 + } 1323 + 1324 + hash_key_to_config = rxfh->key; 1325 + } else if (priv->cache_rss_config) { 1326 + hash_key_to_config = priv->rss_config.hash_key; 1327 + } 1328 + 1329 + if (hash_key_to_config) { 1328 1330 key = dma_alloc_coherent(&priv->pdev->dev, 1329 - key_size, &key_bus, GFP_KERNEL); 1331 + priv->rss_key_size, 1332 + &key_bus, GFP_KERNEL); 1330 1333 if (!key) { 1331 1334 err = -ENOMEM; 1332 1335 goto out; 1333 1336 } 1334 1337 1335 - memcpy(key, rxfh->key, key_size); 1338 + memcpy(key, hash_key_to_config, priv->rss_key_size); 1336 1339 } 1337 1340 1338 1341 /* Zero-valued fields in the cmd.configure_rss instruct the device to ··· 1365 1330 BIT(GVE_RSS_HASH_TCPV6) | 1366 1331 BIT(GVE_RSS_HASH_UDPV6)), 1367 1332 .hash_alg = hash_alg, 1368 - .hash_key_size = cpu_to_be16(key_size), 1369 - .hash_lut_size = cpu_to_be16(lut_size), 1333 + .hash_key_size = 1334 + cpu_to_be16((key_bus) ? priv->rss_key_size : 0), 1335 + .hash_lut_size = 1336 + cpu_to_be16((lut_bus) ? priv->rss_lut_size : 0), 1370 1337 .hash_key_addr = cpu_to_be64(key_bus), 1371 1338 .hash_lut_addr = cpu_to_be64(lut_bus), 1372 1339 }; ··· 1378 1341 out: 1379 1342 if (lut) 1380 1343 dma_free_coherent(&priv->pdev->dev, 1381 - lut_size * sizeof(*lut), 1344 + priv->rss_lut_size * sizeof(*lut), 1382 1345 lut, lut_bus); 1383 1346 if (key) 1384 1347 dma_free_coherent(&priv->pdev->dev, 1385 - key_size, key, key_bus); 1348 + priv->rss_key_size, key, key_bus); 1386 1349 return err; 1387 1350 } 1388 1351 ··· 1486 1449 rxfh->hfunc = descriptor->hash_alg; 1487 1450 1488 1451 rss_info_addr = (void *)(descriptor + 1); 1489 - if (rxfh->key) 1452 + if (rxfh->key) { 1453 + rxfh->key_size = priv->rss_key_size; 1490 1454 memcpy(rxfh->key, rss_info_addr, priv->rss_key_size); 1455 + } 1491 1456 1492 1457 rss_info_addr += priv->rss_key_size; 1493 1458 lut = (__be32 *)rss_info_addr; 1494 1459 if (rxfh->indir) { 1460 + rxfh->indir_size = priv->rss_lut_size; 1495 1461 for (i = 0; i < priv->rss_lut_size; i++) 1496 1462 rxfh->indir[i] = be32_to_cpu(lut[i]); 1497 1463 }
+53 -7
drivers/net/ethernet/google/gve/gve_ethtool.c
··· 482 482 struct ethtool_channels old_settings; 483 483 int new_tx = cmd->tx_count; 484 484 int new_rx = cmd->rx_count; 485 + bool reset_rss = false; 485 486 486 487 gve_get_channels(netdev, &old_settings); 487 488 ··· 499 498 return -EINVAL; 500 499 } 501 500 502 - if (!netif_running(netdev)) { 503 - priv->tx_cfg.num_queues = new_tx; 504 - priv->rx_cfg.num_queues = new_rx; 505 - return 0; 506 - } 501 + if (new_rx != priv->rx_cfg.num_queues && 502 + priv->cache_rss_config && !netif_is_rxfh_configured(netdev)) 503 + reset_rss = true; 507 504 508 505 new_tx_cfg.num_queues = new_tx; 509 506 new_rx_cfg.num_queues = new_rx; 510 507 511 - return gve_adjust_queues(priv, new_rx_cfg, new_tx_cfg); 508 + return gve_adjust_queues(priv, new_rx_cfg, new_tx_cfg, reset_rss); 512 509 } 513 510 514 511 static void gve_get_ringparam(struct net_device *netdev, ··· 854 855 return priv->rss_lut_size; 855 856 } 856 857 858 + static void gve_get_rss_config_cache(struct gve_priv *priv, 859 + struct ethtool_rxfh_param *rxfh) 860 + { 861 + struct gve_rss_config *rss_config = &priv->rss_config; 862 + 863 + rxfh->hfunc = ETH_RSS_HASH_TOP; 864 + 865 + if (rxfh->key) { 866 + rxfh->key_size = priv->rss_key_size; 867 + memcpy(rxfh->key, rss_config->hash_key, priv->rss_key_size); 868 + } 869 + 870 + if (rxfh->indir) { 871 + rxfh->indir_size = priv->rss_lut_size; 872 + memcpy(rxfh->indir, rss_config->hash_lut, 873 + priv->rss_lut_size * sizeof(*rxfh->indir)); 874 + } 875 + } 876 + 857 877 static int gve_get_rxfh(struct net_device *netdev, struct ethtool_rxfh_param *rxfh) 858 878 { 859 879 struct gve_priv *priv = netdev_priv(netdev); ··· 880 862 if (!priv->rss_key_size || !priv->rss_lut_size) 881 863 return -EOPNOTSUPP; 882 864 865 + if (priv->cache_rss_config) { 866 + gve_get_rss_config_cache(priv, rxfh); 867 + return 0; 868 + } 869 + 883 870 return gve_adminq_query_rss_config(priv, rxfh); 871 + } 872 + 873 + static void gve_set_rss_config_cache(struct gve_priv *priv, 874 + struct ethtool_rxfh_param *rxfh) 875 + { 876 + struct gve_rss_config *rss_config = &priv->rss_config; 877 + 878 + if (rxfh->key) 879 + memcpy(rss_config->hash_key, rxfh->key, priv->rss_key_size); 880 + 881 + if (rxfh->indir) 882 + memcpy(rss_config->hash_lut, rxfh->indir, 883 + priv->rss_lut_size * sizeof(*rxfh->indir)); 884 884 } 885 885 886 886 static int gve_set_rxfh(struct net_device *netdev, struct ethtool_rxfh_param *rxfh, 887 887 struct netlink_ext_ack *extack) 888 888 { 889 889 struct gve_priv *priv = netdev_priv(netdev); 890 + int err; 890 891 891 892 if (!priv->rss_key_size || !priv->rss_lut_size) 892 893 return -EOPNOTSUPP; 893 894 894 - return gve_adminq_configure_rss(priv, rxfh); 895 + err = gve_adminq_configure_rss(priv, rxfh); 896 + if (err) { 897 + NL_SET_ERR_MSG_MOD(extack, "Fail to configure RSS config"); 898 + return err; 899 + } 900 + 901 + if (priv->cache_rss_config) 902 + gve_set_rss_config_cache(priv, rxfh); 903 + 904 + return 0; 895 905 } 896 906 897 907 const struct ethtool_ops gve_ethtool_ops = {
+84 -2
drivers/net/ethernet/google/gve/gve_main.c
··· 184 184 flow_rules_cache->rules_cache = NULL; 185 185 } 186 186 187 + static int gve_alloc_rss_config_cache(struct gve_priv *priv) 188 + { 189 + struct gve_rss_config *rss_config = &priv->rss_config; 190 + 191 + if (!priv->cache_rss_config) 192 + return 0; 193 + 194 + rss_config->hash_key = kcalloc(priv->rss_key_size, 195 + sizeof(rss_config->hash_key[0]), 196 + GFP_KERNEL); 197 + if (!rss_config->hash_key) 198 + return -ENOMEM; 199 + 200 + rss_config->hash_lut = kcalloc(priv->rss_lut_size, 201 + sizeof(rss_config->hash_lut[0]), 202 + GFP_KERNEL); 203 + if (!rss_config->hash_lut) 204 + goto free_rss_key_cache; 205 + 206 + return 0; 207 + 208 + free_rss_key_cache: 209 + kfree(rss_config->hash_key); 210 + rss_config->hash_key = NULL; 211 + return -ENOMEM; 212 + } 213 + 214 + static void gve_free_rss_config_cache(struct gve_priv *priv) 215 + { 216 + struct gve_rss_config *rss_config = &priv->rss_config; 217 + 218 + kfree(rss_config->hash_key); 219 + kfree(rss_config->hash_lut); 220 + 221 + memset(rss_config, 0, sizeof(*rss_config)); 222 + } 223 + 187 224 static int gve_alloc_counter_array(struct gve_priv *priv) 188 225 { 189 226 priv->counter_array = ··· 612 575 err = gve_alloc_flow_rule_caches(priv); 613 576 if (err) 614 577 return err; 615 - err = gve_alloc_counter_array(priv); 578 + err = gve_alloc_rss_config_cache(priv); 616 579 if (err) 617 580 goto abort_with_flow_rule_caches; 581 + err = gve_alloc_counter_array(priv); 582 + if (err) 583 + goto abort_with_rss_config_cache; 618 584 err = gve_alloc_notify_blocks(priv); 619 585 if (err) 620 586 goto abort_with_counter; ··· 651 611 } 652 612 } 653 613 614 + err = gve_init_rss_config(priv, priv->rx_cfg.num_queues); 615 + if (err) { 616 + dev_err(&priv->pdev->dev, "Failed to init RSS config"); 617 + goto abort_with_ptype_lut; 618 + } 619 + 654 620 err = gve_adminq_report_stats(priv, priv->stats_report_len, 655 621 priv->stats_report_bus, 656 622 GVE_STATS_REPORT_TIMER_PERIOD); ··· 675 629 gve_free_notify_blocks(priv); 676 630 abort_with_counter: 677 631 gve_free_counter_array(priv); 632 + abort_with_rss_config_cache: 633 + gve_free_rss_config_cache(priv); 678 634 abort_with_flow_rule_caches: 679 635 gve_free_flow_rule_caches(priv); 680 636 ··· 717 669 priv->ptype_lut_dqo = NULL; 718 670 719 671 gve_free_flow_rule_caches(priv); 672 + gve_free_rss_config_cache(priv); 720 673 gve_free_counter_array(priv); 721 674 gve_free_notify_blocks(priv); 722 675 gve_free_stats_report(priv); ··· 1439 1390 if (err) 1440 1391 goto stop_and_free_rings; 1441 1392 1393 + if (rx_alloc_cfg->reset_rss) { 1394 + err = gve_init_rss_config(priv, priv->rx_cfg.num_queues); 1395 + if (err) 1396 + goto reset; 1397 + } 1398 + 1442 1399 err = gve_register_qpls(priv); 1443 1400 if (err) 1444 1401 goto reset; ··· 1841 1786 } 1842 1787 } 1843 1788 1789 + int gve_init_rss_config(struct gve_priv *priv, u16 num_queues) 1790 + { 1791 + struct gve_rss_config *rss_config = &priv->rss_config; 1792 + struct ethtool_rxfh_param rxfh = {0}; 1793 + u16 i; 1794 + 1795 + if (!priv->cache_rss_config) 1796 + return 0; 1797 + 1798 + for (i = 0; i < priv->rss_lut_size; i++) 1799 + rss_config->hash_lut[i] = 1800 + ethtool_rxfh_indir_default(i, num_queues); 1801 + 1802 + netdev_rss_key_fill(rss_config->hash_key, priv->rss_key_size); 1803 + 1804 + rxfh.hfunc = ETH_RSS_HASH_TOP; 1805 + 1806 + return gve_adminq_configure_rss(priv, &rxfh); 1807 + } 1808 + 1844 1809 int gve_flow_rules_reset(struct gve_priv *priv) 1845 1810 { 1846 1811 if (!priv->max_flow_rules) ··· 1909 1834 1910 1835 int gve_adjust_queues(struct gve_priv *priv, 1911 1836 struct gve_queue_config new_rx_config, 1912 - struct gve_queue_config new_tx_config) 1837 + struct gve_queue_config new_tx_config, 1838 + bool reset_rss) 1913 1839 { 1914 1840 struct gve_tx_alloc_rings_cfg tx_alloc_cfg = {0}; 1915 1841 struct gve_rx_alloc_rings_cfg rx_alloc_cfg = {0}; ··· 1923 1847 tx_alloc_cfg.qcfg = &new_tx_config; 1924 1848 rx_alloc_cfg.qcfg_tx = &new_tx_config; 1925 1849 rx_alloc_cfg.qcfg = &new_rx_config; 1850 + rx_alloc_cfg.reset_rss = reset_rss; 1926 1851 tx_alloc_cfg.num_rings = new_tx_config.num_queues; 1927 1852 1928 1853 /* Add dedicated XDP TX queues if enabled. */ ··· 1935 1858 return err; 1936 1859 } 1937 1860 /* Set the config for the next up. */ 1861 + if (reset_rss) { 1862 + err = gve_init_rss_config(priv, new_rx_config.num_queues); 1863 + if (err) 1864 + return err; 1865 + } 1938 1866 priv->tx_cfg = new_tx_config; 1939 1867 priv->rx_cfg = new_rx_config; 1940 1868