net/ena/base: rework interrupt moderation
authorMichal Krawczyk <mk@semihalf.com>
Wed, 8 Apr 2020 08:28:58 +0000 (10:28 +0200)
committerFerruh Yigit <ferruh.yigit@intel.com>
Tue, 21 Apr 2020 11:57:06 +0000 (13:57 +0200)
This feature allows for adaptive interrupt moderation. It's not used by
the DPDK PMD, but is a part of the newest HAL version.

Signed-off-by: Michal Krawczyk <mk@semihalf.com>
Reviewed-by: Igor Chauskin <igorch@amazon.com>
Reviewed-by: Guy Tzalik <gtzalik@amazon.com>
drivers/net/ena/base/ena_com.c
drivers/net/ena/base/ena_com.h
drivers/net/ena/base/ena_plat_dpdk.h

index d500e1d..8a1cac3 100644 (file)
@@ -1279,39 +1279,29 @@ static int ena_com_ind_tbl_convert_to_device(struct ena_com_dev *ena_dev)
        return 0;
 }
 
-static int ena_com_init_interrupt_moderation_table(struct ena_com_dev *ena_dev)
-{
-       size_t size;
-
-       size = sizeof(struct ena_intr_moder_entry) * ENA_INTR_MAX_NUM_OF_LEVELS;
-
-       ena_dev->intr_moder_tbl = ENA_MEM_ALLOC(ena_dev->dmadev, size);
-       if (!ena_dev->intr_moder_tbl)
-               return ENA_COM_NO_MEM;
-
-       ena_com_config_default_interrupt_moderation_table(ena_dev);
-
-       return 0;
-}
-
 static void ena_com_update_intr_delay_resolution(struct ena_com_dev *ena_dev,
                                                 u16 intr_delay_resolution)
 {
-       struct ena_intr_moder_entry *intr_moder_tbl = ena_dev->intr_moder_tbl;
-       unsigned int i;
+       u16 prev_intr_delay_resolution = ena_dev->intr_delay_resolution;
 
-       if (!intr_delay_resolution) {
+       if (unlikely(!intr_delay_resolution)) {
                ena_trc_err("Illegal intr_delay_resolution provided. Going to use default 1 usec resolution\n");
-               intr_delay_resolution = 1;
+               intr_delay_resolution = ENA_DEFAULT_INTR_DELAY_RESOLUTION;
        }
-       ena_dev->intr_delay_resolution = intr_delay_resolution;
 
        /* update Rx */
-       for (i = 0; i < ENA_INTR_MAX_NUM_OF_LEVELS; i++)
-               intr_moder_tbl[i].intr_moder_interval /= intr_delay_resolution;
+       ena_dev->intr_moder_rx_interval =
+               ena_dev->intr_moder_rx_interval *
+               prev_intr_delay_resolution /
+               intr_delay_resolution;
 
        /* update Tx */
-       ena_dev->intr_moder_tx_interval /= intr_delay_resolution;
+       ena_dev->intr_moder_tx_interval =
+               ena_dev->intr_moder_tx_interval *
+               prev_intr_delay_resolution /
+               intr_delay_resolution;
+
+       ena_dev->intr_delay_resolution = intr_delay_resolution;
 }
 
 /*****************************************************************************/
@@ -2880,44 +2870,35 @@ bool ena_com_interrupt_moderation_supported(struct ena_com_dev *ena_dev)
                                                  ENA_ADMIN_INTERRUPT_MODERATION);
 }
 
-int ena_com_update_nonadaptive_moderation_interval_tx(struct ena_com_dev *ena_dev,
-                                                     u32 tx_coalesce_usecs)
+static int ena_com_update_nonadaptive_moderation_interval(u32 coalesce_usecs,
+                                                         u32 intr_delay_resolution,
+                                                         u32 *intr_moder_interval)
 {
-       if (!ena_dev->intr_delay_resolution) {
+       if (!intr_delay_resolution) {
                ena_trc_err("Illegal interrupt delay granularity value\n");
                return ENA_COM_FAULT;
        }
 
-       ena_dev->intr_moder_tx_interval = tx_coalesce_usecs /
-               ena_dev->intr_delay_resolution;
+       *intr_moder_interval = coalesce_usecs / intr_delay_resolution;
 
        return 0;
 }
 
-int ena_com_update_nonadaptive_moderation_interval_rx(struct ena_com_dev *ena_dev,
-                                                     u32 rx_coalesce_usecs)
-{
-       if (!ena_dev->intr_delay_resolution) {
-               ena_trc_err("Illegal interrupt delay granularity value\n");
-               return ENA_COM_FAULT;
-       }
 
-       /* We use LOWEST entry of moderation table for storing
-        * nonadaptive interrupt coalescing values
-        */
-       ena_dev->intr_moder_tbl[ENA_INTR_MODER_LOWEST].intr_moder_interval =
-               rx_coalesce_usecs / ena_dev->intr_delay_resolution;
-
-       return 0;
+int ena_com_update_nonadaptive_moderation_interval_tx(struct ena_com_dev *ena_dev,
+                                                     u32 tx_coalesce_usecs)
+{
+       return ena_com_update_nonadaptive_moderation_interval(tx_coalesce_usecs,
+                                                             ena_dev->intr_delay_resolution,
+                                                             &ena_dev->intr_moder_tx_interval);
 }
 
-void ena_com_destroy_interrupt_moderation(struct ena_com_dev *ena_dev)
+int ena_com_update_nonadaptive_moderation_interval_rx(struct ena_com_dev *ena_dev,
+                                                     u32 rx_coalesce_usecs)
 {
-       if (ena_dev->intr_moder_tbl)
-               ENA_MEM_FREE(ena_dev->dmadev,
-                            ena_dev->intr_moder_tbl,
-                            (sizeof(struct ena_intr_moder_entry) * ENA_INTR_MAX_NUM_OF_LEVELS));
-       ena_dev->intr_moder_tbl = NULL;
+       return ena_com_update_nonadaptive_moderation_interval(rx_coalesce_usecs,
+                                                             ena_dev->intr_delay_resolution,
+                                                             &ena_dev->intr_moder_rx_interval);
 }
 
 int ena_com_init_interrupt_moderation(struct ena_com_dev *ena_dev)
@@ -2944,10 +2925,6 @@ int ena_com_init_interrupt_moderation(struct ena_com_dev *ena_dev)
                return rc;
        }
 
-       rc = ena_com_init_interrupt_moderation_table(ena_dev);
-       if (rc)
-               goto err;
-
        /* if moderation is supported by device we set adaptive moderation */
        delay_resolution = get_resp.u.intr_moderation.intr_delay_resolution;
        ena_com_update_intr_delay_resolution(ena_dev, delay_resolution);
@@ -2956,52 +2933,6 @@ int ena_com_init_interrupt_moderation(struct ena_com_dev *ena_dev)
        ena_com_disable_adaptive_moderation(ena_dev);
 
        return 0;
-err:
-       ena_com_destroy_interrupt_moderation(ena_dev);
-       return rc;
-}
-
-void ena_com_config_default_interrupt_moderation_table(struct ena_com_dev *ena_dev)
-{
-       struct ena_intr_moder_entry *intr_moder_tbl = ena_dev->intr_moder_tbl;
-
-       if (!intr_moder_tbl)
-               return;
-
-       intr_moder_tbl[ENA_INTR_MODER_LOWEST].intr_moder_interval =
-               ENA_INTR_LOWEST_USECS;
-       intr_moder_tbl[ENA_INTR_MODER_LOWEST].pkts_per_interval =
-               ENA_INTR_LOWEST_PKTS;
-       intr_moder_tbl[ENA_INTR_MODER_LOWEST].bytes_per_interval =
-               ENA_INTR_LOWEST_BYTES;
-
-       intr_moder_tbl[ENA_INTR_MODER_LOW].intr_moder_interval =
-               ENA_INTR_LOW_USECS;
-       intr_moder_tbl[ENA_INTR_MODER_LOW].pkts_per_interval =
-               ENA_INTR_LOW_PKTS;
-       intr_moder_tbl[ENA_INTR_MODER_LOW].bytes_per_interval =
-               ENA_INTR_LOW_BYTES;
-
-       intr_moder_tbl[ENA_INTR_MODER_MID].intr_moder_interval =
-               ENA_INTR_MID_USECS;
-       intr_moder_tbl[ENA_INTR_MODER_MID].pkts_per_interval =
-               ENA_INTR_MID_PKTS;
-       intr_moder_tbl[ENA_INTR_MODER_MID].bytes_per_interval =
-               ENA_INTR_MID_BYTES;
-
-       intr_moder_tbl[ENA_INTR_MODER_HIGH].intr_moder_interval =
-               ENA_INTR_HIGH_USECS;
-       intr_moder_tbl[ENA_INTR_MODER_HIGH].pkts_per_interval =
-               ENA_INTR_HIGH_PKTS;
-       intr_moder_tbl[ENA_INTR_MODER_HIGH].bytes_per_interval =
-               ENA_INTR_HIGH_BYTES;
-
-       intr_moder_tbl[ENA_INTR_MODER_HIGHEST].intr_moder_interval =
-               ENA_INTR_HIGHEST_USECS;
-       intr_moder_tbl[ENA_INTR_MODER_HIGHEST].pkts_per_interval =
-               ENA_INTR_HIGHEST_PKTS;
-       intr_moder_tbl[ENA_INTR_MODER_HIGHEST].bytes_per_interval =
-               ENA_INTR_HIGHEST_BYTES;
 }
 
 unsigned int ena_com_get_nonadaptive_moderation_interval_tx(struct ena_com_dev *ena_dev)
@@ -3011,49 +2942,7 @@ unsigned int ena_com_get_nonadaptive_moderation_interval_tx(struct ena_com_dev *
 
 unsigned int ena_com_get_nonadaptive_moderation_interval_rx(struct ena_com_dev *ena_dev)
 {
-       struct ena_intr_moder_entry *intr_moder_tbl = ena_dev->intr_moder_tbl;
-
-       if (intr_moder_tbl)
-               return intr_moder_tbl[ENA_INTR_MODER_LOWEST].intr_moder_interval;
-
-       return 0;
-}
-
-void ena_com_init_intr_moderation_entry(struct ena_com_dev *ena_dev,
-                                       enum ena_intr_moder_level level,
-                                       struct ena_intr_moder_entry *entry)
-{
-       struct ena_intr_moder_entry *intr_moder_tbl = ena_dev->intr_moder_tbl;
-
-       if (level >= ENA_INTR_MAX_NUM_OF_LEVELS)
-               return;
-
-       intr_moder_tbl[level].intr_moder_interval = entry->intr_moder_interval;
-       if (ena_dev->intr_delay_resolution)
-               intr_moder_tbl[level].intr_moder_interval /=
-                       ena_dev->intr_delay_resolution;
-       intr_moder_tbl[level].pkts_per_interval = entry->pkts_per_interval;
-
-       /* use hardcoded value until ethtool supports bytecount parameter */
-       if (entry->bytes_per_interval != ENA_INTR_BYTE_COUNT_NOT_SUPPORTED)
-               intr_moder_tbl[level].bytes_per_interval = entry->bytes_per_interval;
-}
-
-void ena_com_get_intr_moderation_entry(struct ena_com_dev *ena_dev,
-                                      enum ena_intr_moder_level level,
-                                      struct ena_intr_moder_entry *entry)
-{
-       struct ena_intr_moder_entry *intr_moder_tbl = ena_dev->intr_moder_tbl;
-
-       if (level >= ENA_INTR_MAX_NUM_OF_LEVELS)
-               return;
-
-       entry->intr_moder_interval = intr_moder_tbl[level].intr_moder_interval;
-       if (ena_dev->intr_delay_resolution)
-               entry->intr_moder_interval *= ena_dev->intr_delay_resolution;
-       entry->pkts_per_interval =
-       intr_moder_tbl[level].pkts_per_interval;
-       entry->bytes_per_interval = intr_moder_tbl[level].bytes_per_interval;
+       return ena_dev->intr_moder_rx_interval;
 }
 
 int ena_com_config_dev_mode(struct ena_com_dev *ena_dev,
index d58c802..88cf6a8 100644 (file)
 /*****************************************************************************/
 /* ENA adaptive interrupt moderation settings */
 
-#define ENA_INTR_LOWEST_USECS           (0)
-#define ENA_INTR_LOWEST_PKTS            (3)
-#define ENA_INTR_LOWEST_BYTES           (2 * 1524)
-
-#define ENA_INTR_LOW_USECS              (32)
-#define ENA_INTR_LOW_PKTS               (12)
-#define ENA_INTR_LOW_BYTES              (16 * 1024)
-
-#define ENA_INTR_MID_USECS              (80)
-#define ENA_INTR_MID_PKTS               (48)
-#define ENA_INTR_MID_BYTES              (64 * 1024)
-
-#define ENA_INTR_HIGH_USECS             (128)
-#define ENA_INTR_HIGH_PKTS              (96)
-#define ENA_INTR_HIGH_BYTES             (128 * 1024)
-
-#define ENA_INTR_HIGHEST_USECS          (192)
-#define ENA_INTR_HIGHEST_PKTS           (128)
-#define ENA_INTR_HIGHEST_BYTES          (192 * 1024)
-
-#define ENA_INTR_INITIAL_TX_INTERVAL_USECS             196
-#define ENA_INTR_INITIAL_RX_INTERVAL_USECS             4
-#define ENA_INTR_DELAY_OLD_VALUE_WEIGHT                        6
-#define ENA_INTR_DELAY_NEW_VALUE_WEIGHT                        4
-#define ENA_INTR_MODER_LEVEL_STRIDE                    1
-#define ENA_INTR_BYTE_COUNT_NOT_SUPPORTED              0xFFFFFF
+#define ENA_INTR_INITIAL_TX_INTERVAL_USECS ENA_INTR_INITIAL_TX_INTERVAL_USECS_PLAT
+#define ENA_INTR_INITIAL_RX_INTERVAL_USECS 0
+#define ENA_DEFAULT_INTR_DELAY_RESOLUTION 1
+
 #define ENA_HASH_KEY_SIZE                              40
 
 #define ENA_HW_HINTS_NO_TIMEOUT                                0xFFFF
 
 #define ENA_FEATURE_MAX_QUEUE_EXT_VER  1
 
-enum ena_intr_moder_level {
-       ENA_INTR_MODER_LOWEST = 0,
-       ENA_INTR_MODER_LOW,
-       ENA_INTR_MODER_MID,
-       ENA_INTR_MODER_HIGH,
-       ENA_INTR_MODER_HIGHEST,
-       ENA_INTR_MAX_NUM_OF_LEVELS,
-};
-
 struct ena_llq_configurations {
        enum ena_admin_llq_header_location llq_header_location;
        enum ena_admin_llq_ring_entry_size llq_ring_entry_size;
@@ -76,12 +45,6 @@ struct ena_llq_configurations {
        u16 llq_ring_entry_size_value;
 };
 
-struct ena_intr_moder_entry {
-       unsigned int intr_moder_interval;
-       unsigned int pkts_per_interval;
-       unsigned int bytes_per_interval;
-};
-
 enum queue_direction {
        ENA_COM_IO_QUEUE_DIRECTION_TX,
        ENA_COM_IO_QUEUE_DIRECTION_RX
@@ -353,7 +316,13 @@ struct ena_com_dev {
        struct ena_host_attribute host_attr;
        bool adaptive_coalescing;
        u16 intr_delay_resolution;
+
+       /* interrupt moderation intervals are in usec divided by
+        * intr_delay_resolution, which is supplied by the device.
+        */
        u32 intr_moder_tx_interval;
+       u32 intr_moder_rx_interval;
+
        struct ena_intr_moder_entry *intr_moder_tbl;
 
        struct ena_com_llq_info llq_info;
@@ -921,11 +890,6 @@ int ena_com_execute_admin_command(struct ena_com_admin_queue *admin_queue,
  */
 int ena_com_init_interrupt_moderation(struct ena_com_dev *ena_dev);
 
-/* ena_com_destroy_interrupt_moderation - Destroy interrupt moderation resources
- * @ena_dev: ENA communication layer struct
- */
-void ena_com_destroy_interrupt_moderation(struct ena_com_dev *ena_dev);
-
 /* ena_com_interrupt_moderation_supported - Return if interrupt moderation
  * capability is supported by the device.
  *
@@ -933,12 +897,6 @@ void ena_com_destroy_interrupt_moderation(struct ena_com_dev *ena_dev);
  */
 bool ena_com_interrupt_moderation_supported(struct ena_com_dev *ena_dev);
 
-/* ena_com_config_default_interrupt_moderation_table - Restore the interrupt
- * moderation table back to the default parameters.
- * @ena_dev: ENA communication layer struct
- */
-void ena_com_config_default_interrupt_moderation_table(struct ena_com_dev *ena_dev);
-
 /* ena_com_update_nonadaptive_moderation_interval_tx - Update the
  * non-adaptive interval in Tx direction.
  * @ena_dev: ENA communication layer struct
@@ -975,29 +933,6 @@ unsigned int ena_com_get_nonadaptive_moderation_interval_tx(struct ena_com_dev *
  */
 unsigned int ena_com_get_nonadaptive_moderation_interval_rx(struct ena_com_dev *ena_dev);
 
-/* ena_com_init_intr_moderation_entry - Update a single entry in the interrupt
- * moderation table.
- * @ena_dev: ENA communication layer struct
- * @level: Interrupt moderation table level
- * @entry: Entry value
- *
- * Update a single entry in the interrupt moderation table.
- */
-void ena_com_init_intr_moderation_entry(struct ena_com_dev *ena_dev,
-                                       enum ena_intr_moder_level level,
-                                       struct ena_intr_moder_entry *entry);
-
-/* ena_com_get_intr_moderation_entry - Init ena_intr_moder_entry.
- * @ena_dev: ENA communication layer struct
- * @level: Interrupt moderation table level
- * @entry: Entry to fill.
- *
- * Initialize the entry according to the adaptive interrupt moderation table.
- */
-void ena_com_get_intr_moderation_entry(struct ena_com_dev *ena_dev,
-                                      enum ena_intr_moder_level level,
-                                      struct ena_intr_moder_entry *entry);
-
 /* ena_com_config_dev_mode - Configure the placement policy of the device.
  * @ena_dev: ENA communication layer struct
  * @llq_features: LLQ feature descriptor, retrieve via
@@ -1023,75 +958,6 @@ static inline void ena_com_disable_adaptive_moderation(struct ena_com_dev *ena_d
        ena_dev->adaptive_coalescing = false;
 }
 
-/* ena_com_calculate_interrupt_delay - Calculate new interrupt delay
- * @ena_dev: ENA communication layer struct
- * @pkts: Number of packets since the last update
- * @bytes: Number of bytes received since the last update.
- * @smoothed_interval: Returned interval
- * @moder_tbl_idx: Current table level as input update new level as return
- * value.
- */
-static inline void ena_com_calculate_interrupt_delay(struct ena_com_dev *ena_dev,
-                                                    unsigned int pkts,
-                                                    unsigned int bytes,
-                                                    unsigned int *smoothed_interval,
-                                                    unsigned int *moder_tbl_idx)
-{
-       enum ena_intr_moder_level curr_moder_idx, new_moder_idx;
-       struct ena_intr_moder_entry *curr_moder_entry;
-       struct ena_intr_moder_entry *pred_moder_entry;
-       struct ena_intr_moder_entry *new_moder_entry;
-       struct ena_intr_moder_entry *intr_moder_tbl = ena_dev->intr_moder_tbl;
-       unsigned int interval;
-
-       /* We apply adaptive moderation on Rx path only.
-        * Tx uses static interrupt moderation.
-        */
-       if (!pkts || !bytes)
-               /* Tx interrupt, or spurious interrupt,
-                * in both cases we just use same delay values
-                */
-               return;
-
-       curr_moder_idx = (enum ena_intr_moder_level)(*moder_tbl_idx);
-       if (unlikely(curr_moder_idx >=  ENA_INTR_MAX_NUM_OF_LEVELS)) {
-               ena_trc_err("Wrong moderation index %u\n", curr_moder_idx);
-               return;
-       }
-
-       curr_moder_entry = &intr_moder_tbl[curr_moder_idx];
-       new_moder_idx = curr_moder_idx;
-
-       if (curr_moder_idx == ENA_INTR_MODER_LOWEST) {
-               if ((pkts > curr_moder_entry->pkts_per_interval) ||
-                   (bytes > curr_moder_entry->bytes_per_interval))
-                       new_moder_idx =
-                               (enum ena_intr_moder_level)(curr_moder_idx + ENA_INTR_MODER_LEVEL_STRIDE);
-       } else {
-               pred_moder_entry = &intr_moder_tbl[curr_moder_idx - ENA_INTR_MODER_LEVEL_STRIDE];
-
-               if ((pkts <= pred_moder_entry->pkts_per_interval) ||
-                   (bytes <= pred_moder_entry->bytes_per_interval))
-                       new_moder_idx =
-                               (enum ena_intr_moder_level)(curr_moder_idx - ENA_INTR_MODER_LEVEL_STRIDE);
-               else if ((pkts > curr_moder_entry->pkts_per_interval) ||
-                        (bytes > curr_moder_entry->bytes_per_interval)) {
-                       if (curr_moder_idx != ENA_INTR_MODER_HIGHEST)
-                               new_moder_idx =
-                                       (enum ena_intr_moder_level)(curr_moder_idx + ENA_INTR_MODER_LEVEL_STRIDE);
-               }
-       }
-       new_moder_entry = &intr_moder_tbl[new_moder_idx];
-
-       interval = new_moder_entry->intr_moder_interval;
-       *smoothed_interval = (
-               (interval * ENA_INTR_DELAY_NEW_VALUE_WEIGHT +
-               ENA_INTR_DELAY_OLD_VALUE_WEIGHT * (*smoothed_interval)) + 5) /
-               10;
-
-       *moder_tbl_idx = new_moder_idx;
-}
-
 /* ena_com_update_intr_reg - Prepare interrupt register
  * @intr_reg: interrupt register to update.
  * @rx_delay_interval: Rx interval in usecs
index e9b3c02..a0f088c 100644 (file)
@@ -307,6 +307,7 @@ void ena_rss_key_fill(void *key, size_t size);
 
 #define ENA_RSS_FILL_KEY(key, size) ena_rss_key_fill(key, size)
 
-#include "ena_includes.h"
+#define ENA_INTR_INITIAL_TX_INTERVAL_USECS_PLAT 0
 
+#include "ena_includes.h"
 #endif /* DPDK_ENA_COM_ENA_PLAT_DPDK_H_ */