Skip to content

Commit 87a7f32

Browse files
jfrakerdavem330
authored andcommitted
gve: Recover from queue stall due to missed IRQ
Don't always reset the driver on a TX timeout. Attempt to recover by kicking the queue in case an IRQ was missed. Fixes: 9e5f7d2 ("gve: Add workqueue and reset support") Signed-off-by: John Fraker <[email protected]> Signed-off-by: David Awogbemila <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 61d72c7 commit 87a7f32

File tree

3 files changed

+51
-2
lines changed

3 files changed

+51
-2
lines changed

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
#define GVE_MIN_MSIX 3
3131

3232
/* Numbers of gve tx/rx stats in stats report. */
33-
#define GVE_TX_STATS_REPORT_NUM 5
33+
#define GVE_TX_STATS_REPORT_NUM 6
3434
#define GVE_RX_STATS_REPORT_NUM 2
3535

3636
/* Interval to schedule a stats report update, 20000ms. */
@@ -413,7 +413,9 @@ struct gve_tx_ring {
413413
u32 q_num ____cacheline_aligned; /* queue idx */
414414
u32 stop_queue; /* count of queue stops */
415415
u32 wake_queue; /* count of queue wakes */
416+
u32 queue_timeout; /* count of queue timeouts */
416417
u32 ntfy_id; /* notification block index */
418+
u32 last_kick_msec; /* Last time the queue was kicked */
417419
dma_addr_t bus; /* dma address of the descr ring */
418420
dma_addr_t q_resources_bus; /* dma address of the queue resources */
419421
dma_addr_t complq_bus_dqo; /* dma address of the dqo.compl_ring */

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,7 @@ enum gve_stat_names {
270270
TX_LAST_COMPLETION_PROCESSED = 5,
271271
RX_NEXT_EXPECTED_SEQUENCE = 6,
272272
RX_BUFFERS_POSTED = 7,
273+
TX_TIMEOUT_CNT = 8,
273274
// stats from NIC
274275
RX_QUEUE_DROP_CNT = 65,
275276
RX_NO_BUFFERS_POSTED = 66,

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

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@
2424
#define GVE_VERSION "1.0.0"
2525
#define GVE_VERSION_PREFIX "GVE-"
2626

27+
// Minimum amount of time between queue kicks in msec (10 seconds)
28+
#define MIN_TX_TIMEOUT_GAP (1000 * 10)
29+
2730
const char gve_version_str[] = GVE_VERSION;
2831
static const char gve_version_prefix[] = GVE_VERSION_PREFIX;
2932

@@ -1121,9 +1124,47 @@ static void gve_turnup(struct gve_priv *priv)
11211124

11221125
static void gve_tx_timeout(struct net_device *dev, unsigned int txqueue)
11231126
{
1124-
struct gve_priv *priv = netdev_priv(dev);
1127+
struct gve_notify_block *block;
1128+
struct gve_tx_ring *tx = NULL;
1129+
struct gve_priv *priv;
1130+
u32 last_nic_done;
1131+
u32 current_time;
1132+
u32 ntfy_idx;
1133+
1134+
netdev_info(dev, "Timeout on tx queue, %d", txqueue);
1135+
priv = netdev_priv(dev);
1136+
if (txqueue > priv->tx_cfg.num_queues)
1137+
goto reset;
1138+
1139+
ntfy_idx = gve_tx_idx_to_ntfy(priv, txqueue);
1140+
if (ntfy_idx > priv->num_ntfy_blks)
1141+
goto reset;
1142+
1143+
block = &priv->ntfy_blocks[ntfy_idx];
1144+
tx = block->tx;
11251145

1146+
current_time = jiffies_to_msecs(jiffies);
1147+
if (tx->last_kick_msec + MIN_TX_TIMEOUT_GAP > current_time)
1148+
goto reset;
1149+
1150+
/* Check to see if there are missed completions, which will allow us to
1151+
* kick the queue.
1152+
*/
1153+
last_nic_done = gve_tx_load_event_counter(priv, tx);
1154+
if (last_nic_done - tx->done) {
1155+
netdev_info(dev, "Kicking queue %d", txqueue);
1156+
iowrite32be(GVE_IRQ_MASK, gve_irq_doorbell(priv, block));
1157+
napi_schedule(&block->napi);
1158+
tx->last_kick_msec = current_time;
1159+
goto out;
1160+
} // Else reset.
1161+
1162+
reset:
11261163
gve_schedule_reset(priv);
1164+
1165+
out:
1166+
if (tx)
1167+
tx->queue_timeout++;
11271168
priv->tx_timeo_cnt++;
11281169
}
11291170

@@ -1252,6 +1293,11 @@ void gve_handle_report_stats(struct gve_priv *priv)
12521293
.value = cpu_to_be64(last_completion),
12531294
.queue_id = cpu_to_be32(idx),
12541295
};
1296+
stats[stats_idx++] = (struct stats) {
1297+
.stat_name = cpu_to_be32(TX_TIMEOUT_CNT),
1298+
.value = cpu_to_be64(priv->tx[idx].queue_timeout),
1299+
.queue_id = cpu_to_be32(idx),
1300+
};
12551301
}
12561302
}
12571303
/* rx stats */

0 commit comments

Comments
 (0)