diff options
| author | Jiawen Wu <jiawenwu@trustnetic.com> | 2025-08-21 10:34:08 +0800 |
|---|---|---|
| committer | Jakub Kicinski <kuba@kernel.org> | 2025-08-22 17:07:49 -0700 |
| commit | 40477b8bb04876940b2045a47a48b31e8c69c553 (patch) | |
| tree | e85fc18ca03294065e119e41b47702a0ae292854 /drivers/net/ethernet/wangxun/libwx/wx_lib.c | |
| parent | 5f43f2171abb4ad326f861ea3f00b7d0afbf6675 (diff) | |
net: wangxun: support to use adaptive RX/TX coalescing
Support to turn on/off adaptive RX/TX coalesce. When adaptive coalesce
is on, use DIM algorithm for a dynamic interrupt moderation.
Signed-off-by: Jiawen Wu <jiawenwu@trustnetic.com>
Link: https://patch.msgid.link/20250821023408.53472-5-jiawenwu@trustnetic.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Diffstat (limited to 'drivers/net/ethernet/wangxun/libwx/wx_lib.c')
| -rw-r--r-- | drivers/net/ethernet/wangxun/libwx/wx_lib.c | 103 |
1 files changed, 102 insertions, 1 deletions
diff --git a/drivers/net/ethernet/wangxun/libwx/wx_lib.c b/drivers/net/ethernet/wangxun/libwx/wx_lib.c index 723785ef87bb..5086db060c61 100644 --- a/drivers/net/ethernet/wangxun/libwx/wx_lib.c +++ b/drivers/net/ethernet/wangxun/libwx/wx_lib.c @@ -16,6 +16,7 @@ #include "wx_lib.h" #include "wx_ptp.h" #include "wx_hw.h" +#include "wx_vf_lib.h" /* Lookup table mapping the HW PTYPE to the bit field for decoding */ static struct wx_dec_ptype wx_ptype_lookup[256] = { @@ -832,6 +833,36 @@ static bool wx_clean_tx_irq(struct wx_q_vector *q_vector, return !!budget; } +static void wx_update_rx_dim_sample(struct wx_q_vector *q_vector) +{ + struct dim_sample sample = {}; + + dim_update_sample(q_vector->total_events, + q_vector->rx.total_packets, + q_vector->rx.total_bytes, + &sample); + + net_dim(&q_vector->rx.dim, &sample); +} + +static void wx_update_tx_dim_sample(struct wx_q_vector *q_vector) +{ + struct dim_sample sample = {}; + + dim_update_sample(q_vector->total_events, + q_vector->tx.total_packets, + q_vector->tx.total_bytes, + &sample); + + net_dim(&q_vector->tx.dim, &sample); +} + +static void wx_update_dim_sample(struct wx_q_vector *q_vector) +{ + wx_update_rx_dim_sample(q_vector); + wx_update_tx_dim_sample(q_vector); +} + /** * wx_poll - NAPI polling RX/TX cleanup routine * @napi: napi struct with our devices info in it @@ -878,6 +909,8 @@ static int wx_poll(struct napi_struct *napi, int budget) /* all work done, exit the polling mode */ if (likely(napi_complete_done(napi, work_done))) { + if (wx->adaptive_itr) + wx_update_dim_sample(q_vector); if (netif_running(wx->netdev)) wx_intr_enable(wx, WX_INTR_Q(q_vector->v_idx)); } @@ -1591,6 +1624,65 @@ netdev_tx_t wx_xmit_frame(struct sk_buff *skb, } EXPORT_SYMBOL(wx_xmit_frame); +static void wx_set_itr(struct wx_q_vector *q_vector) +{ + struct wx *wx = q_vector->wx; + u32 new_itr; + + if (!wx->adaptive_itr) + return; + + /* use the smallest value of new ITR delay calculations */ + new_itr = min(q_vector->rx.itr, q_vector->tx.itr); + new_itr <<= 2; + + if (new_itr != q_vector->itr) { + /* save the algorithm value here */ + q_vector->itr = new_itr; + + if (wx->pdev->is_virtfn) + wx_write_eitr_vf(q_vector); + else + wx_write_eitr(q_vector); + } +} + +static void wx_rx_dim_work(struct work_struct *work) +{ + struct dim *dim = container_of(work, struct dim, work); + struct dim_cq_moder rx_moder; + struct wx_ring_container *rx; + struct wx_q_vector *q_vector; + + rx = container_of(dim, struct wx_ring_container, dim); + + rx_moder = net_dim_get_rx_moderation(dim->mode, dim->profile_ix); + rx->itr = rx_moder.usec; + + q_vector = container_of(rx, struct wx_q_vector, rx); + wx_set_itr(q_vector); + + dim->state = DIM_START_MEASURE; +} + +static void wx_tx_dim_work(struct work_struct *work) +{ + struct dim *dim = container_of(work, struct dim, work); + struct dim_cq_moder tx_moder; + struct wx_ring_container *tx; + struct wx_q_vector *q_vector; + + tx = container_of(dim, struct wx_ring_container, dim); + + tx_moder = net_dim_get_tx_moderation(dim->mode, dim->profile_ix); + tx->itr = tx_moder.usec; + + q_vector = container_of(tx, struct wx_q_vector, tx); + wx_set_itr(q_vector); + + dim->state = DIM_START_MEASURE; +} + void wx_napi_enable_all(struct wx *wx) { struct wx_q_vector *q_vector; @@ -1598,6 +1690,11 @@ void wx_napi_enable_all(struct wx *wx) for (q_idx = 0; q_idx < wx->num_q_vectors; q_idx++) { q_vector = wx->q_vector[q_idx]; + + INIT_WORK(&q_vector->rx.dim.work, wx_rx_dim_work); + INIT_WORK(&q_vector->tx.dim.work, wx_tx_dim_work); + q_vector->rx.dim.mode = DIM_CQ_PERIOD_MODE_START_FROM_CQE; + q_vector->tx.dim.mode = DIM_CQ_PERIOD_MODE_START_FROM_CQE; napi_enable(&q_vector->napi); } } @@ -1611,6 +1708,8 @@ void wx_napi_disable_all(struct wx *wx) for (q_idx = 0; q_idx < wx->num_q_vectors; q_idx++) { q_vector = wx->q_vector[q_idx]; napi_disable(&q_vector->napi); + disable_work_sync(&q_vector->rx.dim.work); + disable_work_sync(&q_vector->tx.dim.work); } } EXPORT_SYMBOL(wx_napi_disable_all); @@ -2197,8 +2296,10 @@ irqreturn_t wx_msix_clean_rings(int __always_unused irq, void *data) struct wx_q_vector *q_vector = data; /* EIAM disabled interrupts (on this vector) for us */ - if (q_vector->rx.ring || q_vector->tx.ring) + if (q_vector->rx.ring || q_vector->tx.ring) { napi_schedule_irqoff(&q_vector->napi); + q_vector->total_events++; + } return IRQ_HANDLED; } |