Skip to content

Commit c343c8f

Browse files
ziweixiaoNipaLocal
authored and
NipaLocal
committed
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 <[email protected]> Reviewed-by: Harshitha Ramamurthy <[email protected]> Reviewed-by: Willem de Bruijn <[email protected]> Signed-off-by: Praveen Kaligineedi <[email protected]> Signed-off-by: Jeroen de Borst <[email protected]> Signed-off-by: NipaLocal <nipa@local>
1 parent f1263fc commit c343c8f

File tree

4 files changed

+205
-23
lines changed

4 files changed

+205
-23
lines changed

drivers/net/ethernet/google/gve/gve.h

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,9 @@
6868
#define GVE_FLOW_RULE_IDS_CACHE_SIZE \
6969
(GVE_ADMINQ_BUFFER_SIZE / sizeof(((struct gve_adminq_queried_flow_rule *)0)->location))
7070

71+
#define GVE_RSS_KEY_SIZE 40
72+
#define GVE_RSS_INDIR_SIZE 128
73+
7174
#define GVE_XDP_ACTIONS 5
7275

7376
#define GVE_GQ_TX_MIN_PKT_DESC_BYTES 182
@@ -672,6 +675,7 @@ struct gve_rx_alloc_rings_cfg {
672675
u16 packet_buffer_size;
673676
bool raw_addressing;
674677
bool enable_header_split;
678+
bool reset_rss;
675679

676680
/* Allocated resources are returned here */
677681
struct gve_rx_ring *rx;
@@ -722,6 +726,11 @@ struct gve_flow_rules_cache {
722726
u32 rule_ids_cache_num;
723727
};
724728

729+
struct gve_rss_config {
730+
u8 *hash_key;
731+
u32 *hash_lut;
732+
};
733+
725734
struct gve_priv {
726735
struct net_device *dev;
727736
struct gve_tx_ring *tx; /* array of tx_cfg.num_queues */
@@ -842,6 +851,8 @@ struct gve_priv {
842851

843852
u16 rss_key_size;
844853
u16 rss_lut_size;
854+
bool cache_rss_config;
855+
struct gve_rss_config rss_config;
845856
};
846857

847858
enum gve_service_task_flags_bit {
@@ -1210,13 +1221,16 @@ int gve_adjust_config(struct gve_priv *priv,
12101221
struct gve_rx_alloc_rings_cfg *rx_alloc_cfg);
12111222
int gve_adjust_queues(struct gve_priv *priv,
12121223
struct gve_queue_config new_rx_config,
1213-
struct gve_queue_config new_tx_config);
1224+
struct gve_queue_config new_tx_config,
1225+
bool reset_rss);
12141226
/* flow steering rule */
12151227
int gve_get_flow_rule_entry(struct gve_priv *priv, struct ethtool_rxnfc *cmd);
12161228
int gve_get_flow_rule_ids(struct gve_priv *priv, struct ethtool_rxnfc *cmd, u32 *rule_locs);
12171229
int gve_add_flow_rule(struct gve_priv *priv, struct ethtool_rxnfc *cmd);
12181230
int gve_del_flow_rule(struct gve_priv *priv, struct ethtool_rxnfc *cmd);
12191231
int gve_flow_rules_reset(struct gve_priv *priv);
1232+
/* RSS config */
1233+
int gve_init_rss_config(struct gve_priv *priv, u16 num_queues);
12201234
/* report stats handling */
12211235
void gve_handle_report_stats(struct gve_priv *priv);
12221236
/* exported by ethtool.c */

drivers/net/ethernet/google/gve/gve_adminq.c

Lines changed: 53 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -885,6 +885,15 @@ static void gve_set_default_desc_cnt(struct gve_priv *priv,
885885
priv->min_rx_desc_cnt = priv->rx_desc_cnt;
886886
}
887887

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+
888897
static void gve_enable_supported_features(struct gve_priv *priv,
889898
u32 supported_features_mask,
890899
const struct gve_device_option_jumbo_frames
@@ -968,6 +977,10 @@ static void gve_enable_supported_features(struct gve_priv *priv,
968977
be16_to_cpu(dev_op_rss_config->hash_key_size);
969978
priv->rss_lut_size =
970979
be16_to_cpu(dev_op_rss_config->hash_lut_size);
980+
priv->cache_rss_config = false;
981+
dev_dbg(&priv->pdev->dev,
982+
"RSS device option enabled with key size of %u, lut size of %u.\n",
983+
priv->rss_key_size, priv->rss_lut_size);
971984
}
972985
}
973986

@@ -1052,6 +1065,8 @@ int gve_adminq_describe_device(struct gve_priv *priv)
10521065
/* set default descriptor counts */
10531066
gve_set_default_desc_cnt(priv, descriptor);
10541067

1068+
gve_set_default_rss_sizes(priv);
1069+
10551070
/* DQO supports LRO. */
10561071
if (!gve_is_gqi(priv))
10571072
priv->dev->hw_features |= NETIF_F_LRO;
@@ -1276,8 +1291,9 @@ int gve_adminq_reset_flow_rules(struct gve_priv *priv)
12761291

12771292
int gve_adminq_configure_rss(struct gve_priv *priv, struct ethtool_rxfh_param *rxfh)
12781293
{
1294+
const u32 *hash_lut_to_config = NULL;
1295+
const u8 *hash_key_to_config = NULL;
12791296
dma_addr_t lut_bus = 0, key_bus = 0;
1280-
u16 key_size = 0, lut_size = 0;
12811297
union gve_adminq_command cmd;
12821298
__be32 *lut = NULL;
12831299
u8 hash_alg = 0;
@@ -1287,7 +1303,7 @@ int gve_adminq_configure_rss(struct gve_priv *priv, struct ethtool_rxfh_param *r
12871303

12881304
switch (rxfh->hfunc) {
12891305
case ETH_RSS_HASH_NO_CHANGE:
1290-
break;
1306+
fallthrough;
12911307
case ETH_RSS_HASH_TOP:
12921308
hash_alg = ETH_RSS_HASH_TOP;
12931309
break;
@@ -1296,27 +1312,46 @@ int gve_adminq_configure_rss(struct gve_priv *priv, struct ethtool_rxfh_param *r
12961312
}
12971313

12981314
if (rxfh->indir) {
1299-
lut_size = priv->rss_lut_size;
1315+
if (rxfh->indir_size != priv->rss_lut_size)
1316+
return -EINVAL;
1317+
1318+
hash_lut_to_config = rxfh->indir;
1319+
} else if (priv->cache_rss_config) {
1320+
hash_lut_to_config = priv->rss_config.hash_lut;
1321+
}
1322+
1323+
if (hash_lut_to_config) {
13001324
lut = dma_alloc_coherent(&priv->pdev->dev,
1301-
lut_size * sizeof(*lut),
1325+
priv->rss_lut_size * sizeof(*lut),
13021326
&lut_bus, GFP_KERNEL);
13031327
if (!lut)
13041328
return -ENOMEM;
13051329

13061330
for (i = 0; i < priv->rss_lut_size; i++)
1307-
lut[i] = cpu_to_be32(rxfh->indir[i]);
1331+
lut[i] = cpu_to_be32(hash_lut_to_config[i]);
13081332
}
13091333

13101334
if (rxfh->key) {
1311-
key_size = priv->rss_key_size;
1335+
if (rxfh->key_size != priv->rss_key_size) {
1336+
err = -EINVAL;
1337+
goto out;
1338+
}
1339+
1340+
hash_key_to_config = rxfh->key;
1341+
} else if (priv->cache_rss_config) {
1342+
hash_key_to_config = priv->rss_config.hash_key;
1343+
}
1344+
1345+
if (hash_key_to_config) {
13121346
key = dma_alloc_coherent(&priv->pdev->dev,
1313-
key_size, &key_bus, GFP_KERNEL);
1347+
priv->rss_key_size,
1348+
&key_bus, GFP_KERNEL);
13141349
if (!key) {
13151350
err = -ENOMEM;
13161351
goto out;
13171352
}
13181353

1319-
memcpy(key, rxfh->key, key_size);
1354+
memcpy(key, hash_key_to_config, priv->rss_key_size);
13201355
}
13211356

13221357
/* Zero-valued fields in the cmd.configure_rss instruct the device to
@@ -1330,8 +1365,10 @@ int gve_adminq_configure_rss(struct gve_priv *priv, struct ethtool_rxfh_param *r
13301365
BIT(GVE_RSS_HASH_TCPV6) |
13311366
BIT(GVE_RSS_HASH_UDPV6)),
13321367
.hash_alg = hash_alg,
1333-
.hash_key_size = cpu_to_be16(key_size),
1334-
.hash_lut_size = cpu_to_be16(lut_size),
1368+
.hash_key_size =
1369+
cpu_to_be16((key_bus) ? priv->rss_key_size : 0),
1370+
.hash_lut_size =
1371+
cpu_to_be16((lut_bus) ? priv->rss_lut_size : 0),
13351372
.hash_key_addr = cpu_to_be64(key_bus),
13361373
.hash_lut_addr = cpu_to_be64(lut_bus),
13371374
};
@@ -1341,11 +1378,11 @@ int gve_adminq_configure_rss(struct gve_priv *priv, struct ethtool_rxfh_param *r
13411378
out:
13421379
if (lut)
13431380
dma_free_coherent(&priv->pdev->dev,
1344-
lut_size * sizeof(*lut),
1381+
priv->rss_lut_size * sizeof(*lut),
13451382
lut, lut_bus);
13461383
if (key)
13471384
dma_free_coherent(&priv->pdev->dev,
1348-
key_size, key, key_bus);
1385+
priv->rss_key_size, key, key_bus);
13491386
return err;
13501387
}
13511388

@@ -1449,12 +1486,15 @@ static int gve_adminq_process_rss_query(struct gve_priv *priv,
14491486
rxfh->hfunc = descriptor->hash_alg;
14501487

14511488
rss_info_addr = (void *)(descriptor + 1);
1452-
if (rxfh->key)
1489+
if (rxfh->key) {
1490+
rxfh->key_size = priv->rss_key_size;
14531491
memcpy(rxfh->key, rss_info_addr, priv->rss_key_size);
1492+
}
14541493

14551494
rss_info_addr += priv->rss_key_size;
14561495
lut = (__be32 *)rss_info_addr;
14571496
if (rxfh->indir) {
1497+
rxfh->indir_size = priv->rss_lut_size;
14581498
for (i = 0; i < priv->rss_lut_size; i++)
14591499
rxfh->indir[i] = be32_to_cpu(lut[i]);
14601500
}

drivers/net/ethernet/google/gve/gve_ethtool.c

Lines changed: 53 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -482,6 +482,7 @@ static int gve_set_channels(struct net_device *netdev,
482482
struct ethtool_channels old_settings;
483483
int new_tx = cmd->tx_count;
484484
int new_rx = cmd->rx_count;
485+
bool reset_rss = false;
485486

486487
gve_get_channels(netdev, &old_settings);
487488

@@ -498,16 +499,14 @@ static int gve_set_channels(struct net_device *netdev,
498499
return -EINVAL;
499500
}
500501

501-
if (!netif_running(netdev)) {
502-
priv->tx_cfg.num_queues = new_tx;
503-
priv->rx_cfg.num_queues = new_rx;
504-
return 0;
505-
}
502+
if (new_rx != priv->rx_cfg.num_queues &&
503+
priv->cache_rss_config && !netif_is_rxfh_configured(netdev))
504+
reset_rss = true;
506505

507506
new_tx_cfg.num_queues = new_tx;
508507
new_rx_cfg.num_queues = new_rx;
509508

510-
return gve_adjust_queues(priv, new_rx_cfg, new_tx_cfg);
509+
return gve_adjust_queues(priv, new_rx_cfg, new_tx_cfg, reset_rss);
511510
}
512511

513512
static void gve_get_ringparam(struct net_device *netdev,
@@ -855,25 +854,72 @@ static u32 gve_get_rxfh_indir_size(struct net_device *netdev)
855854
return priv->rss_lut_size;
856855
}
857856

857+
static void gve_get_rss_config_cache(struct gve_priv *priv,
858+
struct ethtool_rxfh_param *rxfh)
859+
{
860+
struct gve_rss_config *rss_config = &priv->rss_config;
861+
862+
rxfh->hfunc = ETH_RSS_HASH_TOP;
863+
864+
if (rxfh->key) {
865+
rxfh->key_size = priv->rss_key_size;
866+
memcpy(rxfh->key, rss_config->hash_key, priv->rss_key_size);
867+
}
868+
869+
if (rxfh->indir) {
870+
rxfh->indir_size = priv->rss_lut_size;
871+
memcpy(rxfh->indir, rss_config->hash_lut,
872+
priv->rss_lut_size * sizeof(*rxfh->indir));
873+
}
874+
}
875+
858876
static int gve_get_rxfh(struct net_device *netdev, struct ethtool_rxfh_param *rxfh)
859877
{
860878
struct gve_priv *priv = netdev_priv(netdev);
861879

862880
if (!priv->rss_key_size || !priv->rss_lut_size)
863881
return -EOPNOTSUPP;
864882

883+
if (priv->cache_rss_config) {
884+
gve_get_rss_config_cache(priv, rxfh);
885+
return 0;
886+
}
887+
865888
return gve_adminq_query_rss_config(priv, rxfh);
866889
}
867890

891+
static void gve_set_rss_config_cache(struct gve_priv *priv,
892+
struct ethtool_rxfh_param *rxfh)
893+
{
894+
struct gve_rss_config *rss_config = &priv->rss_config;
895+
896+
if (rxfh->key)
897+
memcpy(rss_config->hash_key, rxfh->key, priv->rss_key_size);
898+
899+
if (rxfh->indir)
900+
memcpy(rss_config->hash_lut, rxfh->indir,
901+
priv->rss_lut_size * sizeof(*rxfh->indir));
902+
}
903+
868904
static int gve_set_rxfh(struct net_device *netdev, struct ethtool_rxfh_param *rxfh,
869905
struct netlink_ext_ack *extack)
870906
{
871907
struct gve_priv *priv = netdev_priv(netdev);
908+
int err;
872909

873910
if (!priv->rss_key_size || !priv->rss_lut_size)
874911
return -EOPNOTSUPP;
875912

876-
return gve_adminq_configure_rss(priv, rxfh);
913+
err = gve_adminq_configure_rss(priv, rxfh);
914+
if (err) {
915+
NL_SET_ERR_MSG_MOD(extack, "Fail to configure RSS config\n");
916+
return err;
917+
}
918+
919+
if (priv->cache_rss_config)
920+
gve_set_rss_config_cache(priv, rxfh);
921+
922+
return 0;
877923
}
878924

879925
const struct ethtool_ops gve_ethtool_ops = {

0 commit comments

Comments
 (0)