From: Arthur Kiyanovski Date: Mon, 16 Sep 2019 14:31:27 +0300 Subject: [PATCH] net: ena: switch to dim algorithm for rx adaptive interrupt moderation Origin: https://git.kernel.org/linus/282faf61a053be43910fcc42d86ecf16c0d30123 Bug-Debian: https://bugs.debian.org/941291 Use the dim library for the rx adaptive interrupt moderation implementation Signed-off-by: Arthur Kiyanovski Signed-off-by: David S. Miller --- drivers/net/ethernet/amazon/ena/ena_com.c | 4 +- drivers/net/ethernet/amazon/ena/ena_netdev.c | 55 +++++++++++++------- drivers/net/ethernet/amazon/ena/ena_netdev.h | 3 ++ 3 files changed, 41 insertions(+), 21 deletions(-) Index: linux/drivers/net/ethernet/amazon/ena/ena_com.c =================================================================== --- linux.orig/drivers/net/ethernet/amazon/ena/ena_com.c +++ linux/drivers/net/ethernet/amazon/ena/ena_com.c @@ -2839,9 +2839,7 @@ int ena_com_init_interrupt_moderation(st delay_resolution = get_resp.u.intr_moderation.intr_delay_resolution; ena_com_update_intr_delay_resolution(ena_dev, delay_resolution); - /* Disable adaptive moderation by default - can be enabled from - * ethtool - */ + /* Disable adaptive moderation by default - can be enabled later */ ena_com_disable_adaptive_moderation(ena_dev); return 0; Index: linux/drivers/net/ethernet/amazon/ena/ena_netdev.c =================================================================== --- linux.orig/drivers/net/ethernet/amazon/ena/ena_netdev.c +++ linux/drivers/net/ethernet/amazon/ena/ena_netdev.c @@ -196,6 +196,7 @@ static void ena_init_io_rings(struct ena rxr->smoothed_interval = ena_com_get_nonadaptive_moderation_interval_rx(ena_dev); rxr->empty_rx_queue = 0; + adapter->ena_napi[i].dim.mode = NET_DIM_CQ_PERIOD_MODE_START_FROM_EQE; } } @@ -712,6 +713,7 @@ static void ena_destroy_all_rx_queues(st for (i = 0; i < adapter->num_queues; i++) { ena_qid = ENA_IO_RXQ_IDX(i); + cancel_work_sync(&adapter->ena_napi[i].dim.work); ena_com_destroy_io_queue(adapter->ena_dev, ena_qid); } } @@ -1156,23 +1158,35 @@ error: return 0; } -void ena_adjust_intr_moderation(struct ena_ring *rx_ring, - struct ena_ring *tx_ring) +static void ena_dim_work(struct work_struct *w) { - /* We apply adaptive moderation on Rx path only. - * Tx uses static interrupt moderation. - */ - ena_com_calculate_interrupt_delay(rx_ring->ena_dev, - rx_ring->per_napi_packets, - rx_ring->per_napi_bytes, - &rx_ring->smoothed_interval, - &rx_ring->moder_tbl_idx); - - /* Reset per napi packets/bytes */ - tx_ring->per_napi_packets = 0; - tx_ring->per_napi_bytes = 0; + struct net_dim *dim = container_of(w, struct net_dim, work); + struct net_dim_cq_moder cur_moder = + net_dim_get_rx_moderation(dim->mode, dim->profile_ix); + struct ena_napi *ena_napi = container_of(dim, struct ena_napi, dim); + + ena_napi->rx_ring->smoothed_interval = cur_moder.usec; + dim->state = NET_DIM_START_MEASURE; +} + +static void ena_adjust_adaptive_rx_intr_moderation(struct ena_napi *ena_napi) +{ + struct net_dim_sample dim_sample; + struct ena_ring *rx_ring = ena_napi->rx_ring; + + if (!rx_ring->per_napi_packets) + return; + + rx_ring->non_empty_napi_events++; + + net_dim_sample(rx_ring->non_empty_napi_events, + rx_ring->rx_stats.cnt, + rx_ring->rx_stats.bytes, + &dim_sample); + + net_dim(&ena_napi->dim, dim_sample); + rx_ring->per_napi_packets = 0; - rx_ring->per_napi_bytes = 0; } static void ena_unmask_interrupt(struct ena_ring *tx_ring, @@ -1261,9 +1275,11 @@ static int ena_io_poll(struct napi_struc * from the interrupt context (vs from sk_busy_loop) */ if (napi_complete_done(napi, rx_work_done)) { - /* Tx and Rx share the same interrupt vector */ + /* We apply adaptive moderation on Rx path only. + * Tx uses static interrupt moderation. + */ if (ena_com_get_adaptive_moderation_enabled(rx_ring->ena_dev)) - ena_adjust_intr_moderation(rx_ring, tx_ring); + ena_adjust_adaptive_rx_intr_moderation(ena_napi); ena_unmask_interrupt(tx_ring, rx_ring); } @@ -1741,13 +1757,16 @@ static int ena_create_all_io_rx_queues(s rc = ena_create_io_rx_queue(adapter, i); if (rc) goto create_err; + INIT_WORK(&adapter->ena_napi[i].dim.work, ena_dim_work); } return 0; create_err: - while (i--) + while (i--) { + cancel_work_sync(&adapter->ena_napi[i].dim.work); ena_com_destroy_io_queue(ena_dev, ENA_IO_RXQ_IDX(i)); + } return rc; } Index: linux/drivers/net/ethernet/amazon/ena/ena_netdev.h =================================================================== --- linux.orig/drivers/net/ethernet/amazon/ena/ena_netdev.h +++ linux/drivers/net/ethernet/amazon/ena/ena_netdev.h @@ -34,6 +34,7 @@ #define ENA_H #include +#include #include #include #include @@ -153,6 +154,7 @@ struct ena_napi { struct ena_ring *tx_ring; struct ena_ring *rx_ring; u32 qid; + struct net_dim dim; }; struct ena_calc_queue_size_ctx { @@ -280,6 +282,7 @@ struct ena_ring { u32 per_napi_packets; u32 per_napi_bytes; enum ena_intr_moder_level moder_tbl_idx; + u16 non_empty_napi_events; struct u64_stats_sync syncp; union { struct ena_stats_tx tx_stats;