Ring the doorbell again for the following scenarios: * No receives posted but Rx queue not empty after deadline * No transmits posted but Tx work still pending after deadline * Admin queue work still pending after deadline
This will help the queues recover in the extremely rare case that a doorbell is missed by the FW. Signed-off-by: Andrew Boyer <andrew.bo...@amd.com> --- drivers/net/ionic/ionic_dev.h | 4 +++ drivers/net/ionic/ionic_lif.h | 3 ++ drivers/net/ionic/ionic_main.c | 22 ++++++++++++ drivers/net/ionic/ionic_rxtx.c | 1 + drivers/net/ionic/ionic_rxtx_sg.c | 50 ++++++++++++++++++++++++++- drivers/net/ionic/ionic_rxtx_simple.c | 50 ++++++++++++++++++++++++++- 6 files changed, 128 insertions(+), 2 deletions(-) diff --git a/drivers/net/ionic/ionic_dev.h b/drivers/net/ionic/ionic_dev.h index 5e238e8ab7..b1e74fbd89 100644 --- a/drivers/net/ionic/ionic_dev.h +++ b/drivers/net/ionic/ionic_dev.h @@ -26,6 +26,10 @@ #define IONIC_DEVCMD_CHECK_PERIOD_US 10 /* devcmd status chk period */ #define IONIC_DEVCMD_RETRY_WAIT_US 20000 +#define IONIC_Q_WDOG_MS 10 /* 10ms */ +#define IONIC_Q_WDOG_MAX_MS 5000 /* 5s */ +#define IONIC_ADMINQ_WDOG_MS 500 /* 500ms */ + #define IONIC_ALIGN 4096 struct ionic_adapter; diff --git a/drivers/net/ionic/ionic_lif.h b/drivers/net/ionic/ionic_lif.h index 00c8add95c..36b3bcc5a9 100644 --- a/drivers/net/ionic/ionic_lif.h +++ b/drivers/net/ionic/ionic_lif.h @@ -85,6 +85,8 @@ struct ionic_rx_qcq { struct rte_mempool *mb_pool; uint64_t rearm_data; uint64_t rearm_seg_data; + uint64_t last_wdog_cycles; + uint64_t wdog_ms; uint16_t frame_size; /* Based on configured MTU */ uint16_t hdr_seg_size; /* Length of first segment of RX chain */ uint16_t seg_size; /* Length of all subsequent segments */ @@ -103,6 +105,7 @@ struct ionic_tx_qcq { struct ionic_qcq qcq; /* cacheline2 */ + uint64_t last_wdog_cycles; uint16_t num_segs_fw; /* # segs supported by current FW */ uint16_t free_thresh; uint16_t flags; diff --git a/drivers/net/ionic/ionic_main.c b/drivers/net/ionic/ionic_main.c index 26e08d06c9..c957d55bf9 100644 --- a/drivers/net/ionic/ionic_main.c +++ b/drivers/net/ionic/ionic_main.c @@ -230,10 +230,16 @@ static int ionic_adminq_wait_for_completion(struct ionic_lif *lif, struct ionic_admin_ctx *ctx, unsigned long max_wait) { + struct ionic_queue *q = &lif->adminqcq->qcq.q; unsigned long step_usec = IONIC_DEVCMD_CHECK_PERIOD_US; + unsigned long step_deadline; unsigned long max_wait_usec = max_wait * 1000000L; unsigned long elapsed_usec = 0; int budget = 8; + uint16_t idx; + void **info; + + step_deadline = IONIC_ADMINQ_WDOG_MS * 1000 / step_usec; while (ctx->pending_work && elapsed_usec < max_wait_usec) { /* @@ -245,10 +251,26 @@ ionic_adminq_wait_for_completion(struct ionic_lif *lif, ionic_qcq_service(&lif->adminqcq->qcq, budget, ionic_adminq_service, NULL); + /* + * Ring the doorbell again if work is pending after deadline. + */ + if (ctx->pending_work && !step_deadline) { + step_deadline = IONIC_ADMINQ_WDOG_MS * + 1000 / step_usec; + + rte_spinlock_lock(&lif->adminq_lock); + idx = Q_NEXT_TO_POST(q, -1); + info = IONIC_INFO_PTR(q, idx); + if (info[0] == ctx) + ionic_q_flush(q); + rte_spinlock_unlock(&lif->adminq_lock); + } + rte_spinlock_unlock(&lif->adminq_service_lock); rte_delay_us_block(step_usec); elapsed_usec += step_usec; + step_deadline--; } return (!ctx->pending_work); diff --git a/drivers/net/ionic/ionic_rxtx.c b/drivers/net/ionic/ionic_rxtx.c index d216980450..b9e73b4871 100644 --- a/drivers/net/ionic/ionic_rxtx.c +++ b/drivers/net/ionic/ionic_rxtx.c @@ -551,6 +551,7 @@ ionic_dev_rx_queue_setup(struct rte_eth_dev *eth_dev, } rxq->mb_pool = mp; + rxq->wdog_ms = IONIC_Q_WDOG_MS; /* * Note: the interface does not currently support diff --git a/drivers/net/ionic/ionic_rxtx_sg.c b/drivers/net/ionic/ionic_rxtx_sg.c index 4e4a18e5d7..2752ba2acd 100644 --- a/drivers/net/ionic/ionic_rxtx_sg.c +++ b/drivers/net/ionic/ionic_rxtx_sg.c @@ -167,6 +167,7 @@ ionic_xmit_pkts_sg(void *tx_queue, struct rte_mbuf **tx_pkts, struct rte_mbuf *mbuf; uint32_t bytes_tx = 0; uint16_t nb_avail, nb_tx = 0; + uint64_t then, now, hz, delta; int err; struct ionic_txq_desc *desc_base = q->base; @@ -220,8 +221,26 @@ ionic_xmit_pkts_sg(void *tx_queue, struct rte_mbuf **tx_pkts, rte_wmb(); ionic_q_flush(q); + txq->last_wdog_cycles = rte_get_timer_cycles(); + stats->packets += nb_tx; stats->bytes += bytes_tx; + } else { + /* + * Ring the doorbell again if no work could be posted and work + * is still pending after the deadline. + */ + if (q->head_idx != q->tail_idx) { + then = txq->last_wdog_cycles; + now = rte_get_timer_cycles(); + hz = rte_get_timer_hz(); + delta = (now - then) * 1000; + + if (delta >= hz * IONIC_Q_WDOG_MS) { + ionic_q_flush(q); + txq->last_wdog_cycles = now; + } + } } return nb_tx; @@ -421,6 +440,7 @@ ionic_rxq_service_sg(struct ionic_rx_qcq *rxq, uint32_t work_to_do, struct ionic_rxq_desc *q_desc_base = q->base; struct ionic_rxq_comp *cq_desc, *cq_desc_base = cq->base; uint32_t work_done = 0; + uint64_t then, now, hz, delta; cq_desc = &cq_desc_base[cq->tail_idx]; @@ -453,8 +473,36 @@ ionic_rxq_service_sg(struct ionic_rx_qcq *rxq, uint32_t work_to_do, } /* Update the queue indices and ring the doorbell */ - if (work_done) + if (work_done) { ionic_q_flush(q); + rxq->last_wdog_cycles = rte_get_timer_cycles(); + rxq->wdog_ms = IONIC_Q_WDOG_MS; + } else { + /* + * Ring the doorbell again if no recvs were posted and the + * recv queue is not empty after the deadline. + * + * Exponentially back off the deadline to avoid excessive + * doorbells when the recv queue is idle. + */ + if (q->head_idx != q->tail_idx) { + then = rxq->last_wdog_cycles; + now = rte_get_timer_cycles(); + hz = rte_get_timer_hz(); + delta = (now - then) * 1000; + + if (delta >= hz * rxq->wdog_ms) { + ionic_q_flush(q); + rxq->last_wdog_cycles = now; + + delta = 2 * rxq->wdog_ms; + if (delta > IONIC_Q_WDOG_MAX_MS) + delta = IONIC_Q_WDOG_MAX_MS; + + rxq->wdog_ms = delta; + } + } + } } uint16_t diff --git a/drivers/net/ionic/ionic_rxtx_simple.c b/drivers/net/ionic/ionic_rxtx_simple.c index a191fd3ec9..0421fb32b2 100644 --- a/drivers/net/ionic/ionic_rxtx_simple.c +++ b/drivers/net/ionic/ionic_rxtx_simple.c @@ -140,6 +140,7 @@ ionic_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, struct rte_mbuf *mbuf; uint32_t bytes_tx = 0; uint16_t nb_avail, nb_tx = 0; + uint64_t then, now, hz, delta; int err; struct ionic_txq_desc *desc_base = q->base; @@ -193,8 +194,26 @@ ionic_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, rte_wmb(); ionic_q_flush(q); + txq->last_wdog_cycles = rte_get_timer_cycles(); + stats->packets += nb_tx; stats->bytes += bytes_tx; + } else { + /* + * Ring the doorbell again if no work could be posted and work + * is still pending after the deadline. + */ + if (q->head_idx != q->tail_idx) { + then = txq->last_wdog_cycles; + now = rte_get_timer_cycles(); + hz = rte_get_timer_hz(); + delta = (now - then) * 1000; + + if (delta >= hz * IONIC_Q_WDOG_MS) { + ionic_q_flush(q); + txq->last_wdog_cycles = now; + } + } } return nb_tx; @@ -342,6 +361,7 @@ ionic_rxq_service(struct ionic_rx_qcq *rxq, uint32_t work_to_do, struct ionic_rxq_desc *q_desc_base = q->base; struct ionic_rxq_comp *cq_desc, *cq_desc_base = cq->base; uint32_t work_done = 0; + uint64_t then, now, hz, delta; cq_desc = &cq_desc_base[cq->tail_idx]; @@ -374,8 +394,36 @@ ionic_rxq_service(struct ionic_rx_qcq *rxq, uint32_t work_to_do, } /* Update the queue indices and ring the doorbell */ - if (work_done) + if (work_done) { ionic_q_flush(q); + rxq->last_wdog_cycles = rte_get_timer_cycles(); + rxq->wdog_ms = IONIC_Q_WDOG_MS; + } else { + /* + * Ring the doorbell again if no recvs were posted and the + * recv queue is not empty after the deadline. + * + * Exponentially back off the deadline to avoid excessive + * doorbells when the recv queue is idle. + */ + if (q->head_idx != q->tail_idx) { + then = rxq->last_wdog_cycles; + now = rte_get_timer_cycles(); + hz = rte_get_timer_hz(); + delta = (now - then) * 1000; + + if (delta >= hz * rxq->wdog_ms) { + ionic_q_flush(q); + rxq->last_wdog_cycles = now; + + delta = 2 * rxq->wdog_ms; + if (delta > IONIC_Q_WDOG_MAX_MS) + delta = IONIC_Q_WDOG_MAX_MS; + + rxq->wdog_ms = delta; + } + } + } } uint16_t -- 2.17.1