@@ -980,13 +980,16 @@ static inline bool ena_com_get_cap(struct ena_com_dev *ena_dev,
* @rx_delay_interval: Rx interval in usecs
* @tx_delay_interval: Tx interval in usecs
* @unmask: unmask enable/disable
+ * @no_moderation_update: 0 - Indicates that any of the TX/RX intervals was
+ * updated, 1 - otherwise
*
* Prepare interrupt update register with the supplied parameters.
*/
static inline void ena_com_update_intr_reg(struct ena_eth_io_intr_reg *intr_reg,
u32 rx_delay_interval,
u32 tx_delay_interval,
- bool unmask)
+ bool unmask,
+ bool no_moderation_update)
{
intr_reg->intr_control = 0;
intr_reg->intr_control |= rx_delay_interval &
@@ -998,6 +1001,10 @@ static inline void ena_com_update_intr_reg(struct ena_eth_io_intr_reg *intr_reg,
if (unmask)
intr_reg->intr_control |= ENA_ETH_IO_INTR_REG_INTR_UNMASK_MASK;
+
+ intr_reg->intr_control |=
+ (((u32)no_moderation_update) << ENA_ETH_IO_INTR_REG_NO_MODERATION_UPDATE_SHIFT) &
+ ENA_ETH_IO_INTR_REG_NO_MODERATION_UPDATE_MASK;
}
static inline u8 *ena_com_get_next_bounce_buffer(struct ena_com_io_bounce_buffer_control *bounce_buf_ctrl)
@@ -261,7 +261,8 @@ struct ena_eth_io_intr_reg {
/* 14:0 : rx_intr_delay
* 29:15 : tx_intr_delay
* 30 : intr_unmask
- * 31 : reserved
+ * 31 : no_moderation_update - 0 - moderation
+ * updated, 1 - moderation not updated
*/
u32 intr_control;
};
@@ -381,6 +382,8 @@ struct ena_eth_io_numa_node_cfg_reg {
#define ENA_ETH_IO_INTR_REG_TX_INTR_DELAY_MASK GENMASK(29, 15)
#define ENA_ETH_IO_INTR_REG_INTR_UNMASK_SHIFT 30
#define ENA_ETH_IO_INTR_REG_INTR_UNMASK_MASK BIT(30)
+#define ENA_ETH_IO_INTR_REG_NO_MODERATION_UPDATE_SHIFT 31
+#define ENA_ETH_IO_INTR_REG_NO_MODERATION_UPDATE_MASK BIT(31)
/* numa_node_cfg_reg */
#define ENA_ETH_IO_NUMA_NODE_CFG_REG_NUMA_MASK GENMASK(7, 0)
@@ -390,8 +390,11 @@ static void ena_update_tx_rings_nonadaptive_intr_moderation(struct ena_adapter *
val = ena_com_get_nonadaptive_moderation_interval_tx(adapter->ena_dev);
- for (i = 0; i < adapter->num_io_queues; i++)
- adapter->tx_ring[i].smoothed_interval = val;
+ for (i = 0; i < adapter->num_io_queues; i++) {
+ adapter->tx_ring[i].interrupt_interval_changed =
+ adapter->tx_ring[i].interrupt_interval != val;
+ adapter->tx_ring[i].interrupt_interval = val;
+ }
}
static void ena_update_rx_rings_nonadaptive_intr_moderation(struct ena_adapter *adapter)
@@ -401,8 +404,11 @@ static void ena_update_rx_rings_nonadaptive_intr_moderation(struct ena_adapter *
val = ena_com_get_nonadaptive_moderation_interval_rx(adapter->ena_dev);
- for (i = 0; i < adapter->num_io_queues; i++)
- adapter->rx_ring[i].smoothed_interval = val;
+ for (i = 0; i < adapter->num_io_queues; i++) {
+ adapter->rx_ring[i].interrupt_interval_changed =
+ adapter->rx_ring[i].interrupt_interval != val;
+ adapter->rx_ring[i].interrupt_interval = val;
+ }
}
static int ena_set_coalesce(struct net_device *net_dev,
@@ -224,8 +224,10 @@ void ena_init_io_rings(struct ena_adapter *adapter,
txr->tx_max_header_size = ena_dev->tx_max_header_size;
txr->tx_mem_queue_type = ena_dev->tx_mem_queue_type;
txr->sgl_size = adapter->max_tx_sgl_size;
- txr->smoothed_interval =
+ txr->interrupt_interval =
ena_com_get_nonadaptive_moderation_interval_tx(ena_dev);
+ /* Initial value, mark as true */
+ txr->interrupt_interval_changed = true;
txr->disable_meta_caching = adapter->disable_meta_caching;
spin_lock_init(&txr->xdp_tx_lock);
@@ -238,8 +240,10 @@ void ena_init_io_rings(struct ena_adapter *adapter,
rxr->ring_size = adapter->requested_rx_ring_size;
rxr->rx_copybreak = adapter->rx_copybreak;
rxr->sgl_size = adapter->max_rx_sgl_size;
- rxr->smoothed_interval =
+ rxr->interrupt_interval =
ena_com_get_nonadaptive_moderation_interval_rx(ena_dev);
+ /* Initial value, mark as true */
+ rxr->interrupt_interval_changed = true;
rxr->empty_rx_queue = 0;
rxr->rx_headroom = NET_SKB_PAD;
adapter->ena_napi[i].dim.mode = DIM_CQ_PERIOD_MODE_START_FROM_EQE;
@@ -1364,7 +1368,10 @@ static void ena_dim_work(struct work_struct *w)
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;
+ ena_napi->rx_ring->interrupt_interval = cur_moder.usec;
+ /* DIM will schedule the work in case there was a change in the profile. */
+ ena_napi->rx_ring->interrupt_interval_changed = true;
+
dim->state = DIM_START_MEASURE;
}
@@ -1391,24 +1398,33 @@ static void ena_adjust_adaptive_rx_intr_moderation(struct ena_napi *ena_napi)
void ena_unmask_interrupt(struct ena_ring *tx_ring,
struct ena_ring *rx_ring)
{
- u32 rx_interval = tx_ring->smoothed_interval;
+ u32 rx_interval = tx_ring->interrupt_interval;
struct ena_eth_io_intr_reg intr_reg;
+ bool no_moderation_update = true;
/* Rx ring can be NULL when for XDP tx queues which don't have an
* accompanying rx_ring pair.
*/
- if (rx_ring)
+ if (rx_ring) {
rx_interval = ena_com_get_adaptive_moderation_enabled(rx_ring->ena_dev) ?
- rx_ring->smoothed_interval :
+ rx_ring->interrupt_interval :
ena_com_get_nonadaptive_moderation_interval_rx(rx_ring->ena_dev);
+ no_moderation_update &= !rx_ring->interrupt_interval_changed;
+ rx_ring->interrupt_interval_changed = false;
+ }
+
+ no_moderation_update &= !tx_ring->interrupt_interval_changed;
+ tx_ring->interrupt_interval_changed = false;
+
/* Update intr register: rx intr delay,
* tx intr delay and interrupt unmask
*/
ena_com_update_intr_reg(&intr_reg,
rx_interval,
- tx_ring->smoothed_interval,
- true);
+ tx_ring->interrupt_interval,
+ true,
+ no_moderation_update);
ena_increase_stat(&tx_ring->tx_stats.unmask_interrupt, 1,
&tx_ring->syncp);
@@ -267,8 +267,13 @@ struct ena_ring {
enum ena_admin_placement_policy_type tx_mem_queue_type;
struct ena_com_rx_buf_info ena_bufs[ENA_PKT_MAX_BUFS];
- u32 smoothed_interval;
- u32 per_napi_packets;
+ u32 interrupt_interval;
+ /* Indicates whether interrupt interval has changed since previous set.
+ * This flag will be kept up, until cleared by the routine which updates
+ * the device with the modified interrupt interval value.
+ */
+ bool interrupt_interval_changed;
+ u32 per_napi_packets;
u16 non_empty_napi_events;
struct u64_stats_sync syncp;
union {