Skip to content

Commit cc54ec5

Browse files
committed
Merge branch 'gve-xdp-fixes'
Joshua Washington says: ==================== gve: various XDP fixes This patch series contains the following XDP fixes: - clean up XDP tx queue when stopping rings - use RCU synchronization to guard existence of XDP queues - perform XSK TX as part of RX NAPI to fix busy polling - fix XDP allocation issues when non-XDP configurations occur ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents b6075c8 + de63ac4 commit cc54ec5

File tree

3 files changed

+60
-29
lines changed

3 files changed

+60
-29
lines changed

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1140,6 +1140,7 @@ int gve_xdp_xmit_one(struct gve_priv *priv, struct gve_tx_ring *tx,
11401140
void gve_xdp_tx_flush(struct gve_priv *priv, u32 xdp_qid);
11411141
bool gve_tx_poll(struct gve_notify_block *block, int budget);
11421142
bool gve_xdp_poll(struct gve_notify_block *block, int budget);
1143+
int gve_xsk_tx_poll(struct gve_notify_block *block, int budget);
11431144
int gve_tx_alloc_rings_gqi(struct gve_priv *priv,
11441145
struct gve_tx_alloc_rings_cfg *cfg);
11451146
void gve_tx_free_rings_gqi(struct gve_priv *priv,

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

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,14 @@ int gve_napi_poll(struct napi_struct *napi, int budget)
333333

334334
if (block->rx) {
335335
work_done = gve_rx_poll(block, budget);
336+
337+
/* Poll XSK TX as part of RX NAPI. Setup re-poll based on max of
338+
* TX and RX work done.
339+
*/
340+
if (priv->xdp_prog)
341+
work_done = max_t(int, work_done,
342+
gve_xsk_tx_poll(block, budget));
343+
336344
reschedule |= work_done == budget;
337345
}
338346

@@ -922,11 +930,13 @@ static void gve_init_sync_stats(struct gve_priv *priv)
922930
static void gve_tx_get_curr_alloc_cfg(struct gve_priv *priv,
923931
struct gve_tx_alloc_rings_cfg *cfg)
924932
{
933+
int num_xdp_queues = priv->xdp_prog ? priv->rx_cfg.num_queues : 0;
934+
925935
cfg->qcfg = &priv->tx_cfg;
926936
cfg->raw_addressing = !gve_is_qpl(priv);
927937
cfg->ring_size = priv->tx_desc_cnt;
928938
cfg->start_idx = 0;
929-
cfg->num_rings = gve_num_tx_queues(priv);
939+
cfg->num_rings = priv->tx_cfg.num_queues + num_xdp_queues;
930940
cfg->tx = priv->tx;
931941
}
932942

@@ -1623,8 +1633,8 @@ static int gve_xsk_pool_enable(struct net_device *dev,
16231633
if (err)
16241634
return err;
16251635

1626-
/* If XDP prog is not installed, return */
1627-
if (!priv->xdp_prog)
1636+
/* If XDP prog is not installed or interface is down, return. */
1637+
if (!priv->xdp_prog || !netif_running(dev))
16281638
return 0;
16291639

16301640
rx = &priv->rx[qid];
@@ -1669,21 +1679,16 @@ static int gve_xsk_pool_disable(struct net_device *dev,
16691679
if (qid >= priv->rx_cfg.num_queues)
16701680
return -EINVAL;
16711681

1672-
/* If XDP prog is not installed, unmap DMA and return */
1673-
if (!priv->xdp_prog)
1674-
goto done;
1675-
1676-
tx_qid = gve_xdp_tx_queue_id(priv, qid);
1677-
if (!netif_running(dev)) {
1678-
priv->rx[qid].xsk_pool = NULL;
1679-
xdp_rxq_info_unreg(&priv->rx[qid].xsk_rxq);
1680-
priv->tx[tx_qid].xsk_pool = NULL;
1682+
/* If XDP prog is not installed or interface is down, unmap DMA and
1683+
* return.
1684+
*/
1685+
if (!priv->xdp_prog || !netif_running(dev))
16811686
goto done;
1682-
}
16831687

16841688
napi_rx = &priv->ntfy_blocks[priv->rx[qid].ntfy_id].napi;
16851689
napi_disable(napi_rx); /* make sure current rx poll is done */
16861690

1691+
tx_qid = gve_xdp_tx_queue_id(priv, qid);
16871692
napi_tx = &priv->ntfy_blocks[priv->tx[tx_qid].ntfy_id].napi;
16881693
napi_disable(napi_tx); /* make sure current tx poll is done */
16891694

@@ -1711,6 +1716,9 @@ static int gve_xsk_wakeup(struct net_device *dev, u32 queue_id, u32 flags)
17111716
struct gve_priv *priv = netdev_priv(dev);
17121717
int tx_queue_id = gve_xdp_tx_queue_id(priv, queue_id);
17131718

1719+
if (!gve_get_napi_enabled(priv))
1720+
return -ENETDOWN;
1721+
17141722
if (queue_id >= priv->rx_cfg.num_queues || !priv->xdp_prog)
17151723
return -EINVAL;
17161724

@@ -1837,6 +1845,7 @@ int gve_adjust_queues(struct gve_priv *priv,
18371845
{
18381846
struct gve_tx_alloc_rings_cfg tx_alloc_cfg = {0};
18391847
struct gve_rx_alloc_rings_cfg rx_alloc_cfg = {0};
1848+
int num_xdp_queues;
18401849
int err;
18411850

18421851
gve_get_curr_alloc_cfgs(priv, &tx_alloc_cfg, &rx_alloc_cfg);
@@ -1847,6 +1856,10 @@ int gve_adjust_queues(struct gve_priv *priv,
18471856
rx_alloc_cfg.qcfg = &new_rx_config;
18481857
tx_alloc_cfg.num_rings = new_tx_config.num_queues;
18491858

1859+
/* Add dedicated XDP TX queues if enabled. */
1860+
num_xdp_queues = priv->xdp_prog ? new_rx_config.num_queues : 0;
1861+
tx_alloc_cfg.num_rings += num_xdp_queues;
1862+
18501863
if (netif_running(priv->dev)) {
18511864
err = gve_adjust_config(priv, &tx_alloc_cfg, &rx_alloc_cfg);
18521865
return err;
@@ -1899,6 +1912,9 @@ static void gve_turndown(struct gve_priv *priv)
18991912

19001913
gve_clear_napi_enabled(priv);
19011914
gve_clear_report_stats(priv);
1915+
1916+
/* Make sure that all traffic is finished processing. */
1917+
synchronize_net();
19021918
}
19031919

19041920
static void gve_turnup(struct gve_priv *priv)

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

Lines changed: 30 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,10 @@ void gve_tx_stop_ring_gqi(struct gve_priv *priv, int idx)
206206
return;
207207

208208
gve_remove_napi(priv, ntfy_idx);
209-
gve_clean_tx_done(priv, tx, priv->tx_desc_cnt, false);
209+
if (tx->q_num < priv->tx_cfg.num_queues)
210+
gve_clean_tx_done(priv, tx, priv->tx_desc_cnt, false);
211+
else
212+
gve_clean_xdp_done(priv, tx, priv->tx_desc_cnt);
210213
netdev_tx_reset_queue(tx->netdev_txq);
211214
gve_tx_remove_from_block(priv, idx);
212215
}
@@ -834,9 +837,12 @@ int gve_xdp_xmit(struct net_device *dev, int n, struct xdp_frame **frames,
834837
struct gve_tx_ring *tx;
835838
int i, err = 0, qid;
836839

837-
if (unlikely(flags & ~XDP_XMIT_FLAGS_MASK))
840+
if (unlikely(flags & ~XDP_XMIT_FLAGS_MASK) || !priv->xdp_prog)
838841
return -EINVAL;
839842

843+
if (!gve_get_napi_enabled(priv))
844+
return -ENETDOWN;
845+
840846
qid = gve_xdp_tx_queue_id(priv,
841847
smp_processor_id() % priv->num_xdp_queues);
842848

@@ -975,33 +981,41 @@ static int gve_xsk_tx(struct gve_priv *priv, struct gve_tx_ring *tx,
975981
return sent;
976982
}
977983

984+
int gve_xsk_tx_poll(struct gve_notify_block *rx_block, int budget)
985+
{
986+
struct gve_rx_ring *rx = rx_block->rx;
987+
struct gve_priv *priv = rx->gve;
988+
struct gve_tx_ring *tx;
989+
int sent = 0;
990+
991+
tx = &priv->tx[gve_xdp_tx_queue_id(priv, rx->q_num)];
992+
if (tx->xsk_pool) {
993+
sent = gve_xsk_tx(priv, tx, budget);
994+
995+
u64_stats_update_begin(&tx->statss);
996+
tx->xdp_xsk_sent += sent;
997+
u64_stats_update_end(&tx->statss);
998+
if (xsk_uses_need_wakeup(tx->xsk_pool))
999+
xsk_set_tx_need_wakeup(tx->xsk_pool);
1000+
}
1001+
1002+
return sent;
1003+
}
1004+
9781005
bool gve_xdp_poll(struct gve_notify_block *block, int budget)
9791006
{
9801007
struct gve_priv *priv = block->priv;
9811008
struct gve_tx_ring *tx = block->tx;
9821009
u32 nic_done;
983-
bool repoll;
9841010
u32 to_do;
9851011

9861012
/* Find out how much work there is to be done */
9871013
nic_done = gve_tx_load_event_counter(priv, tx);
9881014
to_do = min_t(u32, (nic_done - tx->done), budget);
9891015
gve_clean_xdp_done(priv, tx, to_do);
990-
repoll = nic_done != tx->done;
991-
992-
if (tx->xsk_pool) {
993-
int sent = gve_xsk_tx(priv, tx, budget);
994-
995-
u64_stats_update_begin(&tx->statss);
996-
tx->xdp_xsk_sent += sent;
997-
u64_stats_update_end(&tx->statss);
998-
repoll |= (sent == budget);
999-
if (xsk_uses_need_wakeup(tx->xsk_pool))
1000-
xsk_set_tx_need_wakeup(tx->xsk_pool);
1001-
}
10021016

10031017
/* If we still have work we want to repoll */
1004-
return repoll;
1018+
return nic_done != tx->done;
10051019
}
10061020

10071021
bool gve_tx_poll(struct gve_notify_block *block, int budget)

0 commit comments

Comments
 (0)