Commit 2cb67ab1 authored by Yangchun Fu's avatar Yangchun Fu Committed by David S. Miller

gve: Switch to use napi_complete_done

Use napi_complete_done to allow for the use of gro_flush_timeout.

Fixes: f5cedc84 ("gve: Add transmit and receive support")
Signed-off-by: default avatarYangchun Fu <yangchun@google.com>
Signed-off-by: default avatarCatherine Sullivan <csully@google.com>
Signed-off-by: default avatarDavid Awogbemila <awogbemila@google.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent ce8bd03c
...@@ -825,11 +825,10 @@ __be32 gve_tx_load_event_counter(struct gve_priv *priv, ...@@ -825,11 +825,10 @@ __be32 gve_tx_load_event_counter(struct gve_priv *priv,
struct gve_tx_ring *tx); struct gve_tx_ring *tx);
/* rx handling */ /* rx handling */
void gve_rx_write_doorbell(struct gve_priv *priv, struct gve_rx_ring *rx); void gve_rx_write_doorbell(struct gve_priv *priv, struct gve_rx_ring *rx);
bool gve_rx_poll(struct gve_notify_block *block, int budget); int gve_rx_poll(struct gve_notify_block *block, int budget);
bool gve_rx_work_pending(struct gve_rx_ring *rx);
int gve_rx_alloc_rings(struct gve_priv *priv); int gve_rx_alloc_rings(struct gve_priv *priv);
void gve_rx_free_rings_gqi(struct gve_priv *priv); void gve_rx_free_rings_gqi(struct gve_priv *priv);
bool gve_clean_rx_done(struct gve_rx_ring *rx, int budget,
netdev_features_t feat);
/* Reset */ /* Reset */
void gve_schedule_reset(struct gve_priv *priv); void gve_schedule_reset(struct gve_priv *priv);
int gve_reset(struct gve_priv *priv, bool attempt_teardown); int gve_reset(struct gve_priv *priv, bool attempt_teardown);
......
...@@ -192,19 +192,23 @@ static int gve_napi_poll(struct napi_struct *napi, int budget) ...@@ -192,19 +192,23 @@ static int gve_napi_poll(struct napi_struct *napi, int budget)
__be32 __iomem *irq_doorbell; __be32 __iomem *irq_doorbell;
bool reschedule = false; bool reschedule = false;
struct gve_priv *priv; struct gve_priv *priv;
int work_done = 0;
block = container_of(napi, struct gve_notify_block, napi); block = container_of(napi, struct gve_notify_block, napi);
priv = block->priv; priv = block->priv;
if (block->tx) if (block->tx)
reschedule |= gve_tx_poll(block, budget); reschedule |= gve_tx_poll(block, budget);
if (block->rx) if (block->rx) {
reschedule |= gve_rx_poll(block, budget); work_done = gve_rx_poll(block, budget);
reschedule |= work_done == budget;
}
if (reschedule) if (reschedule)
return budget; return budget;
napi_complete(napi); /* Complete processing - don't unmask irq if busy polling is enabled */
if (likely(napi_complete_done(napi, work_done))) {
irq_doorbell = gve_irq_doorbell(priv, block); irq_doorbell = gve_irq_doorbell(priv, block);
iowrite32be(GVE_IRQ_ACK | GVE_IRQ_EVENT, irq_doorbell); iowrite32be(GVE_IRQ_ACK | GVE_IRQ_EVENT, irq_doorbell);
...@@ -212,14 +216,16 @@ static int gve_napi_poll(struct napi_struct *napi, int budget) ...@@ -212,14 +216,16 @@ static int gve_napi_poll(struct napi_struct *napi, int budget)
* Ensure unmask synchronizes with checking for work. * Ensure unmask synchronizes with checking for work.
*/ */
mb(); mb();
if (block->tx) if (block->tx)
reschedule |= gve_tx_poll(block, -1); reschedule |= gve_tx_poll(block, -1);
if (block->rx) if (block->rx)
reschedule |= gve_rx_poll(block, -1); reschedule |= gve_rx_work_pending(block->rx);
if (reschedule && napi_reschedule(napi)) if (reschedule && napi_reschedule(napi))
iowrite32be(GVE_IRQ_MASK, irq_doorbell); iowrite32be(GVE_IRQ_MASK, irq_doorbell);
}
return 0; return work_done;
} }
static int gve_napi_poll_dqo(struct napi_struct *napi, int budget) static int gve_napi_poll_dqo(struct napi_struct *napi, int budget)
......
...@@ -456,7 +456,7 @@ static bool gve_rx(struct gve_rx_ring *rx, struct gve_rx_desc *rx_desc, ...@@ -456,7 +456,7 @@ static bool gve_rx(struct gve_rx_ring *rx, struct gve_rx_desc *rx_desc,
return true; return true;
} }
static bool gve_rx_work_pending(struct gve_rx_ring *rx) bool gve_rx_work_pending(struct gve_rx_ring *rx)
{ {
struct gve_rx_desc *desc; struct gve_rx_desc *desc;
__be16 flags_seq; __be16 flags_seq;
...@@ -524,7 +524,7 @@ static bool gve_rx_refill_buffers(struct gve_priv *priv, struct gve_rx_ring *rx) ...@@ -524,7 +524,7 @@ static bool gve_rx_refill_buffers(struct gve_priv *priv, struct gve_rx_ring *rx)
return true; return true;
} }
bool gve_clean_rx_done(struct gve_rx_ring *rx, int budget, static int gve_clean_rx_done(struct gve_rx_ring *rx, int budget,
netdev_features_t feat) netdev_features_t feat)
{ {
struct gve_priv *priv = rx->gve; struct gve_priv *priv = rx->gve;
...@@ -559,13 +559,15 @@ bool gve_clean_rx_done(struct gve_rx_ring *rx, int budget, ...@@ -559,13 +559,15 @@ bool gve_clean_rx_done(struct gve_rx_ring *rx, int budget,
} }
if (!work_done && rx->fill_cnt - cnt > rx->db_threshold) if (!work_done && rx->fill_cnt - cnt > rx->db_threshold)
return false; return 0;
if (work_done) {
u64_stats_update_begin(&rx->statss); u64_stats_update_begin(&rx->statss);
rx->rpackets += packets; rx->rpackets += packets;
rx->rbytes += bytes; rx->rbytes += bytes;
u64_stats_update_end(&rx->statss); u64_stats_update_end(&rx->statss);
rx->cnt = cnt; rx->cnt = cnt;
}
/* restock ring slots */ /* restock ring slots */
if (!rx->data.raw_addressing) { if (!rx->data.raw_addressing) {
...@@ -576,26 +578,26 @@ bool gve_clean_rx_done(struct gve_rx_ring *rx, int budget, ...@@ -576,26 +578,26 @@ bool gve_clean_rx_done(struct gve_rx_ring *rx, int budget,
* falls below a threshold. * falls below a threshold.
*/ */
if (!gve_rx_refill_buffers(priv, rx)) if (!gve_rx_refill_buffers(priv, rx))
return false; return 0;
/* If we were not able to completely refill buffers, we'll want /* If we were not able to completely refill buffers, we'll want
* to schedule this queue for work again to refill buffers. * to schedule this queue for work again to refill buffers.
*/ */
if (rx->fill_cnt - cnt <= rx->db_threshold) { if (rx->fill_cnt - cnt <= rx->db_threshold) {
gve_rx_write_doorbell(priv, rx); gve_rx_write_doorbell(priv, rx);
return true; return budget;
} }
} }
gve_rx_write_doorbell(priv, rx); gve_rx_write_doorbell(priv, rx);
return gve_rx_work_pending(rx); return work_done;
} }
bool gve_rx_poll(struct gve_notify_block *block, int budget) int gve_rx_poll(struct gve_notify_block *block, int budget)
{ {
struct gve_rx_ring *rx = block->rx; struct gve_rx_ring *rx = block->rx;
netdev_features_t feat; netdev_features_t feat;
bool repoll = false; int work_done = 0;
feat = block->napi.dev->features; feat = block->napi.dev->features;
...@@ -604,8 +606,7 @@ bool gve_rx_poll(struct gve_notify_block *block, int budget) ...@@ -604,8 +606,7 @@ bool gve_rx_poll(struct gve_notify_block *block, int budget)
budget = INT_MAX; budget = INT_MAX;
if (budget > 0) if (budget > 0)
repoll |= gve_clean_rx_done(rx, budget, feat); work_done = gve_clean_rx_done(rx, budget, feat);
else
repoll |= gve_rx_work_pending(rx); return work_done;
return repoll;
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment