From: Haiyang Zhang <[email protected]> 
Sent: Saturday, May 30, 2026 9:50 PM

>From: Haiyang Zhang <[email protected]>
>
>Add Static and Dynamic Interrupt Moderation (DIM) support for
>Rx and Tx.
>Update queue creation procedure with new data struct with the related
>settings.
>Add functions to collect stat for DIM, and workers to update DIM data
>and settings.
>Update ethtool handler to get/set the moderation settings from a user.
>By default, adaptive-rx/tx (DIM) are enabled.
>
>Signed-off-by: Haiyang Zhang <[email protected]>
>---
> drivers/net/ethernet/microsoft/Kconfig        |   1 +
> .../net/ethernet/microsoft/mana/gdma_main.c   |  27 ++++
> drivers/net/ethernet/microsoft/mana/mana_en.c | 101 ++++++++++++++-
> .../ethernet/microsoft/mana/mana_ethtool.c    | 120 +++++++++++++++++-
> include/net/mana/gdma.h                       |  24 +++-
> include/net/mana/mana.h                       |  42 ++++++
> 6 files changed, 309 insertions(+), 6 deletions(-)
>
>diff --git a/drivers/net/ethernet/microsoft/Kconfig 
>b/drivers/net/ethernet/microsoft/Kconfig
>index 3f36ee6a8ece..e9be18c92ca5 100644
>--- a/drivers/net/ethernet/microsoft/Kconfig
>+++ b/drivers/net/ethernet/microsoft/Kconfig
>@@ -21,6 +21,7 @@ config MICROSOFT_MANA
>       depends on X86_64 || (ARM64 && !CPU_BIG_ENDIAN)
>       depends on PCI_HYPERV
>       select AUXILIARY_BUS
>+      select DIMLIB
>       select PAGE_POOL
>       select NET_SHAPER
>       help
>diff --git a/drivers/net/ethernet/microsoft/mana/gdma_main.c 
>b/drivers/net/ethernet/microsoft/mana/gdma_main.c
>index 712a0881d720..5aa0ea794a00 100644
>--- a/drivers/net/ethernet/microsoft/mana/gdma_main.c
>+++ b/drivers/net/ethernet/microsoft/mana/gdma_main.c
>@@ -405,6 +405,7 @@ static int mana_gd_disable_queue(struct gdma_queue *queue)
> #define DOORBELL_OFFSET_RQ    0x400
> #define DOORBELL_OFFSET_CQ    0x800
> #define DOORBELL_OFFSET_EQ    0xFF8
>+#define DOORBELL_OFFSET_DIM   0x820
> 
> static void mana_gd_ring_doorbell(struct gdma_context *gc, u32 db_index,
>                                 enum gdma_queue_type q_type, u32 qid,
>@@ -445,6 +446,16 @@ static void mana_gd_ring_doorbell(struct gdma_context 
>*gc, u32 db_index,
>               addr += DOORBELL_OFFSET_SQ;
>               break;
> 
>+      case GDMA_DIM:
>+              e.dim.id = qid;
>+              e.dim.mod_usec = tail_ptr;
>+              e.dim.mod_usec_vld = tail_ptr >> 15;
>+              e.dim.mod_comps = tail_ptr >> 16;

please use defines instead of magic

>+              e.dim.mod_comps_vld = num_req;
>+
>+              addr += DOORBELL_OFFSET_DIM;
>+              break;
>+
>       default:
>               WARN_ON(1);
>               return;
>@@ -479,6 +490,22 @@ void mana_gd_ring_cq(struct gdma_queue *cq, u8 arm_bit)
> }
> EXPORT_SYMBOL_NS(mana_gd_ring_cq, "NET_MANA");
> 
>+void mana_gd_ring_dim(struct gdma_queue *cq, u32 mod_usec, bool mod_usec_vld,
>+                    u32 mod_comps, bool mod_comps_vld)
>+{
>+      struct gdma_context *gc = cq->gdma_dev->gdma_context;
>+      u32 dim_val;
>+
>+      /* Convert the DIM values to doorbell parameters */
>+      dim_val = (mod_usec & MANA_INTR_MODR_USEC_MAX) |
>+                (((u32)mod_usec_vld & 1) << 15) |
>+                ((mod_comps & MANA_INTR_MODR_COMP_MAX) << 16);

i believe FIELD_PREP if preferrable in such cases

>+
>+      mana_gd_ring_doorbell(gc, cq->gdma_dev->doorbell, GDMA_DIM, cq->id,
>+                            dim_val, (u8)mod_comps_vld & 1);
>+}
>+EXPORT_SYMBOL_NS(mana_gd_ring_dim, "NET_MANA");
>+
> #define MANA_SERVICE_PERIOD 10
> 
> static void mana_serv_rescan(struct pci_dev *pdev)
>diff --git a/drivers/net/ethernet/microsoft/mana/mana_en.c 
>b/drivers/net/ethernet/microsoft/mana/mana_en.c
>index 82f1461a48e9..f1a16f8aca66 100644
>--- a/drivers/net/ethernet/microsoft/mana/mana_en.c
>+++ b/drivers/net/ethernet/microsoft/mana/mana_en.c
>@@ -1551,6 +1551,9 @@ int mana_create_wq_obj(struct mana_port_context *apc,
> 
>       mana_gd_init_req_hdr(&req.hdr, MANA_CREATE_WQ_OBJ,
>                            sizeof(req), sizeof(resp));
>+
>+      req.hdr.req.msg_version = GDMA_MESSAGE_V3;
>+      req.hdr.resp.msg_version = GDMA_MESSAGE_V2;
>       req.vport = vport;
>       req.wq_type = wq_type;
>       req.wq_gdma_region = wq_spec->gdma_region;
>@@ -1559,6 +1562,9 @@ int mana_create_wq_obj(struct mana_port_context *apc,
>       req.cq_size = cq_spec->queue_size;
>       req.cq_moderation_ctx_id = cq_spec->modr_ctx_id;
>       req.cq_parent_qid = cq_spec->attached_eq;
>+      req.req_cq_moderation = cq_spec->req_cq_moderation;
>+      req.cq_moderation_comp = cq_spec->cq_moderation_comp;
>+      req.cq_moderation_usec = cq_spec->cq_moderation_usec;
> 
>       err = mana_send_request(apc->ac, &req, sizeof(req), &resp,
>                               sizeof(resp));
>@@ -2253,6 +2259,66 @@ static void mana_poll_rx_cq(struct mana_cq *cq)
>               xdp_do_flush();
> }
> 
>+static void mana_rx_dim_work(struct work_struct *work)
>+{
>+      struct dim *dim = container_of(work, struct dim, work);
>+      struct mana_cq *cq = container_of(dim, struct mana_cq, dim);
>+      struct dim_cq_moder cur_moder =
>+              net_dim_get_rx_moderation(dim->mode, dim->profile_ix);

RCT; here and for following

>+
>+      cur_moder.usec = min_t(u16, cur_moder.usec, MANA_INTR_MODR_USEC_MAX);
>+      cur_moder.pkts = min_t(u16, cur_moder.pkts, MANA_INTR_MODR_COMP_MAX);
>+
>+      mana_gd_ring_dim(cq->gdma_cq, cur_moder.usec, true,
>+                       cur_moder.pkts, true);
>+
>+      dim->state = DIM_START_MEASURE;
>+}
>+
>+static void mana_tx_dim_work(struct work_struct *work)
>+{
>+      struct dim *dim = container_of(work, struct dim, work);
>+      struct mana_cq *cq = container_of(dim, struct mana_cq, dim);
>+      struct dim_cq_moder cur_moder =
>+              net_dim_get_tx_moderation(dim->mode, dim->profile_ix);
>+
>+      cur_moder.usec = min_t(u16, cur_moder.usec, MANA_INTR_MODR_USEC_MAX);
>+      cur_moder.pkts = min_t(u16, cur_moder.pkts, MANA_INTR_MODR_COMP_MAX);
>+
>+      mana_gd_ring_dim(cq->gdma_cq, cur_moder.usec, true,
>+                       cur_moder.pkts, true);
>+
>+      dim->state = DIM_START_MEASURE;
>+}
>+
>+static void mana_update_rx_dim(struct mana_cq *cq)
>+{
>+      struct mana_rxq *rxq = cq->rxq;
>+      struct mana_port_context *apc = netdev_priv(rxq->ndev);
>+      struct dim_sample dim_sample = {};
>+
>+      if (!apc->rx_dim_enabled)
>+              return;
>+
>+      dim_update_sample(READ_ONCE(cq->dim_event_ctr), rxq->stats.packets,
>+                        rxq->stats.bytes, &dim_sample);
>+      net_dim(&cq->dim, &dim_sample);
>+}
>+
>+static void mana_update_tx_dim(struct mana_cq *cq)
>+{
>+      struct mana_txq *txq = cq->txq;
>+      struct mana_port_context *apc = netdev_priv(txq->ndev);
>+      struct dim_sample dim_sample = {};
>+
>+      if (!apc->tx_dim_enabled)
>+              return;
>+
>+      dim_update_sample(READ_ONCE(cq->dim_event_ctr), txq->stats.packets,
>+                        txq->stats.bytes, &dim_sample);
>+      net_dim(&cq->dim, &dim_sample);
>+}
>+
> static int mana_cq_handler(void *context, struct gdma_queue *gdma_queue)
> {
>       struct mana_cq *cq = context;
>@@ -2271,7 +2337,13 @@ static int mana_cq_handler(void *context, struct 
>gdma_queue *gdma_queue)
>       if (w < cq->budget) {
>               mana_gd_ring_cq(gdma_queue, SET_ARM_BIT);
>               cq->work_done_since_doorbell = 0;
>-              napi_complete_done(&cq->napi, w);
>+
>+              if (napi_complete_done(&cq->napi, w)) {
>+                      if (cq->type == MANA_CQ_TYPE_RX)
>+                              mana_update_rx_dim(cq);
>+                      else
>+                              mana_update_tx_dim(cq);
>+              }
>       } else if (cq->work_done_since_doorbell >=
>                  (cq->gdma_cq->queue_size / COMP_ENTRY_SIZE) * 4) {
>               /* MANA hardware requires at least one doorbell ring every 8
>@@ -2303,6 +2375,7 @@ static void mana_schedule_napi(void *context, struct 
>gdma_queue *gdma_queue)
> {
>       struct mana_cq *cq = context;
> 
>+      WRITE_ONCE(cq->dim_event_ctr, cq->dim_event_ctr + 1);
>       napi_schedule_irqoff(&cq->napi);
> }
> 
>@@ -2345,6 +2418,7 @@ static void mana_destroy_txq(struct mana_port_context 
>*apc)
>               if (apc->tx_qp[i]->txq.napi_initialized) {
>                       napi_synchronize(napi);
>                       napi_disable_locked(napi);
>+                      cancel_work_sync(&apc->tx_qp[i]->tx_cq.dim.work);
>                       netif_napi_del_locked(napi);
>                       apc->tx_qp[i]->txq.napi_initialized = false;
>               }
>@@ -2475,6 +2549,10 @@ static int mana_create_txq(struct mana_port_context 
>*apc,
>               cq_spec.queue_size = cq->gdma_cq->queue_size;
>               cq_spec.modr_ctx_id = 0;
>               cq_spec.attached_eq = cq->gdma_cq->cq.parent->id;
>+              cq_spec.req_cq_moderation = apc->tx_dim_enabled ||
>+                      (apc->intr_modr_tx_usec && apc->intr_modr_tx_comp);
>+              cq_spec.cq_moderation_usec = apc->intr_modr_tx_usec;
>+              cq_spec.cq_moderation_comp = apc->intr_modr_tx_comp;
> 
>               err = mana_create_wq_obj(apc, apc->port_handle, GDMA_SQ,
>                                        &wq_spec, &cq_spec,
>@@ -2509,6 +2587,9 @@ static int mana_create_txq(struct mana_port_context *apc,
>               napi_enable_locked(&cq->napi);
>               txq->napi_initialized = true;
> 
>+              INIT_WORK(&cq->dim.work, mana_tx_dim_work);
>+              cq->dim.mode = DIM_CQ_PERIOD_MODE_START_FROM_EQE;
>+
>               mana_gd_ring_cq(cq->gdma_cq, SET_ARM_BIT);
>       }
> 
>@@ -2543,6 +2624,7 @@ static void mana_destroy_rxq(struct mana_port_context 
>*apc,
>               napi_synchronize(napi);
> 
>               napi_disable_locked(napi);
>+              cancel_work_sync(&rxq->rx_cq.dim.work);
>               netif_napi_del_locked(napi);
>       }
> 
>@@ -2780,6 +2862,10 @@ static struct mana_rxq *mana_create_rxq(struct 
>mana_port_context *apc,
>       cq_spec.queue_size = cq->gdma_cq->queue_size;
>       cq_spec.modr_ctx_id = 0;
>       cq_spec.attached_eq = cq->gdma_cq->cq.parent->id;
>+      cq_spec.req_cq_moderation = apc->rx_dim_enabled ||
>+              (apc->intr_modr_rx_usec && apc->intr_modr_rx_comp);
>+      cq_spec.cq_moderation_usec = apc->intr_modr_rx_usec;
>+      cq_spec.cq_moderation_comp = apc->intr_modr_rx_comp;
> 
>       err = mana_create_wq_obj(apc, apc->port_handle, GDMA_RQ,
>                                &wq_spec, &cq_spec, &rxq->rxobj);
>@@ -2815,6 +2901,9 @@ static struct mana_rxq *mana_create_rxq(struct 
>mana_port_context *apc,
> 
>       napi_enable_locked(&cq->napi);
> 
>+      INIT_WORK(&cq->dim.work, mana_rx_dim_work);
>+      cq->dim.mode = DIM_CQ_PERIOD_MODE_START_FROM_EQE;
>+
>       mana_gd_ring_cq(cq->gdma_cq, SET_ARM_BIT);
> out:
>       if (!err)
>@@ -3432,6 +3521,16 @@ static int mana_probe_port(struct mana_context *ac, int 
>port_idx,
>       apc->port_idx = port_idx;
>       apc->cqe_coalescing_enable = 0;
> 
>+      /* Initialize interrupt moderation settings if supported by HW */
>+      if (gc->pf_cap_flags1 & GDMA_PF_CAP_FLAG_1_DYN_INTERRUPT_MODERATION) {
>+              apc->intr_modr_rx_usec = MANA_INTR_MODR_USEC_DEF;
>+              apc->intr_modr_rx_comp = MANA_INTR_MODR_COMP_DEF;
>+              apc->intr_modr_tx_usec = MANA_INTR_MODR_USEC_DEF;
>+              apc->intr_modr_tx_comp = MANA_INTR_MODR_COMP_DEF;
>+              apc->rx_dim_enabled = MANA_ADAPTIVE_RX_DEF;
>+              apc->tx_dim_enabled = MANA_ADAPTIVE_TX_DEF;
>+      }
>+
>       mutex_init(&apc->vport_mutex);
>       apc->vport_use_count = 0;
> 
>diff --git a/drivers/net/ethernet/microsoft/mana/mana_ethtool.c 
>b/drivers/net/ethernet/microsoft/mana/mana_ethtool.c
>index 04350973e19e..a90216eba794 100644
>--- a/drivers/net/ethernet/microsoft/mana/mana_ethtool.c
>+++ b/drivers/net/ethernet/microsoft/mana/mana_ethtool.c
>@@ -419,6 +419,15 @@ static int mana_get_coalesce(struct net_device *ndev,
>           !kernel_coal->rx_cqe_nsecs)
>               kernel_coal->rx_cqe_nsecs = MANA_RX_CQE_NSEC_DEF;
> 
>+      ec->rx_coalesce_usecs = apc->intr_modr_rx_usec;
>+      ec->rx_max_coalesced_frames = apc->intr_modr_rx_comp;
>+
>+      ec->tx_coalesce_usecs = apc->intr_modr_tx_usec;
>+      ec->tx_max_coalesced_frames = apc->intr_modr_tx_comp;
>+
>+      ec->use_adaptive_rx_coalesce = apc->rx_dim_enabled;
>+      ec->use_adaptive_tx_coalesce = apc->tx_dim_enabled;
>+
>       return 0;
> }
> 
>@@ -429,8 +438,28 @@ static int mana_set_coalesce(struct net_device *ndev,
> {
>       struct mana_port_context *apc = netdev_priv(ndev);
>       u8 saved_cqe_coalescing_enable;
>+      u16 old_rx_usec, old_rx_comp;
>+      u16 old_tx_usec, old_tx_comp;
>+      bool old_rx_dim, old_tx_dim;

how about using some sort of struct instead of declaring a number
of params for bookkeeping? imho would be cleaner

>+      bool modr_changed = false;
>+      bool dim_changed = false;
>+      struct gdma_context *gc;
>       int err;
> 
>+      gc = apc->ac->gdma_dev->gdma_context;
>+
>+      /* Both static and dynamic interrupt moderation (DIM) rely on the
>+       * same HW capability advertised by the PF.
>+       */
>+      if ((ec->use_adaptive_rx_coalesce || ec->use_adaptive_tx_coalesce ||
>+           ec->rx_coalesce_usecs || ec->tx_coalesce_usecs ||
>+           ec->rx_max_coalesced_frames || ec->tx_max_coalesced_frames) &&
>+          !(gc->pf_cap_flags1 & GDMA_PF_CAP_FLAG_1_DYN_INTERRUPT_MODERATION)) 
>{
>+              NL_SET_ERR_MSG(extack,
>+                             "Interrupt Moderation is not supported by HW");
>+              return -EOPNOTSUPP;
>+      }
>+
>       if (kernel_coal->rx_cqe_frames != 1 &&
>           kernel_coal->rx_cqe_frames != MANA_RXCOMP_OOB_NUM_PPI) {
>               NL_SET_ERR_MSG_FMT(extack,
>@@ -440,6 +469,47 @@ static int mana_set_coalesce(struct net_device *ndev,
>               return -EINVAL;
>       }
> 
>+      if (ec->rx_coalesce_usecs > MANA_INTR_MODR_USEC_MAX ||
>+          ec->tx_coalesce_usecs > MANA_INTR_MODR_USEC_MAX) {
>+              NL_SET_ERR_MSG_FMT(extack,
>+                                 "coalesce usecs must be <= %u",
>+                                 MANA_INTR_MODR_USEC_MAX);
>+              return -EINVAL;
>+      }
>+
>+      if (ec->rx_max_coalesced_frames > MANA_INTR_MODR_COMP_MAX ||
>+          ec->tx_max_coalesced_frames > MANA_INTR_MODR_COMP_MAX) {
>+              NL_SET_ERR_MSG_FMT(extack,
>+                                 "coalesce frames must be <= %u",
>+                                 MANA_INTR_MODR_COMP_MAX);
>+              return -EINVAL;
>+      }
>+
>+      if (ec->rx_coalesce_usecs != apc->intr_modr_rx_usec ||
>+          ec->rx_max_coalesced_frames != apc->intr_modr_rx_comp ||
>+          ec->tx_coalesce_usecs != apc->intr_modr_tx_usec ||
>+          ec->tx_max_coalesced_frames != apc->intr_modr_tx_comp)
>+              modr_changed = true;
>+
>+      old_rx_usec = apc->intr_modr_rx_usec;
>+      old_rx_comp = apc->intr_modr_rx_comp;
>+      old_tx_usec = apc->intr_modr_tx_usec;
>+      old_tx_comp = apc->intr_modr_tx_comp;
>+
>+      apc->intr_modr_rx_usec = ec->rx_coalesce_usecs;
>+      apc->intr_modr_rx_comp = ec->rx_max_coalesced_frames;
>+      apc->intr_modr_tx_usec = ec->tx_coalesce_usecs;
>+      apc->intr_modr_tx_comp = ec->tx_max_coalesced_frames;
>+
>+      if (!!ec->use_adaptive_rx_coalesce != apc->rx_dim_enabled ||
>+          !!ec->use_adaptive_tx_coalesce != apc->tx_dim_enabled)
>+              dim_changed = true;
>+
>+      old_rx_dim = apc->rx_dim_enabled;
>+      old_tx_dim = apc->tx_dim_enabled;
>+      apc->rx_dim_enabled = !!ec->use_adaptive_rx_coalesce;
>+      apc->tx_dim_enabled = !!ec->use_adaptive_tx_coalesce;
>+
>       saved_cqe_coalescing_enable = apc->cqe_coalescing_enable;
>       apc->cqe_coalescing_enable =
>               kernel_coal->rx_cqe_frames == MANA_RXCOMP_OOB_NUM_PPI;
>@@ -447,10 +517,46 @@ static int mana_set_coalesce(struct net_device *ndev,
>       if (!apc->port_is_up)
>               return 0;
> 
>-      err = mana_config_rss(apc, TRI_STATE_TRUE, false, false);
>-      if (err)
>-              apc->cqe_coalescing_enable = saved_cqe_coalescing_enable;
>+      if (apc->cqe_coalescing_enable != saved_cqe_coalescing_enable &&
>+          !modr_changed && !dim_changed) {
>+              /* If only CQE coalescing setting is changed, we can just update
>+               * RSS configuration.
>+               */
>+              err = mana_config_rss(apc, TRI_STATE_TRUE, false, false);
>+              if (err) {
>+                      netdev_err(ndev, "Change CQE coalescing failed: %d\n",
>+                                 err);
>+                      apc->cqe_coalescing_enable =
>+                              saved_cqe_coalescing_enable;
>+                      return err;
>+              }
>+              return 0;
>+      }
>+
>+      if (modr_changed || dim_changed) {
>+              err = mana_detach(ndev, false);
>+              if (err) {
>+                      netdev_err(ndev, "mana_detach failed: %d\n", err);
>+                      goto restore_modr;
>+              }
>+
>+              err = mana_attach(ndev);
>+              if (err) {
>+                      netdev_err(ndev, "mana_attach failed: %d\n", err);
>+                      goto restore_modr;

i see there is already such pattern in the mana code; how about
creating a helper?

>+              }
>+      }
>+
>+      return 0;
> 
>+restore_modr:
>+      apc->cqe_coalescing_enable = saved_cqe_coalescing_enable;
>+      apc->intr_modr_rx_usec = old_rx_usec;
>+      apc->intr_modr_rx_comp = old_rx_comp;
>+      apc->intr_modr_tx_usec = old_tx_usec;
>+      apc->intr_modr_tx_comp = old_tx_comp;
>+      apc->rx_dim_enabled = old_rx_dim;
>+      apc->tx_dim_enabled = old_tx_dim;
>       return err;
> }
> 
>@@ -574,7 +680,13 @@ static int mana_get_link_ksettings(struct net_device 
>*ndev,
> }
> 
> const struct ethtool_ops mana_ethtool_ops = {
>-      .supported_coalesce_params = ETHTOOL_COALESCE_RX_CQE_FRAMES,
>+      .supported_coalesce_params = ETHTOOL_COALESCE_RX_CQE_FRAMES |
>+                                  ETHTOOL_COALESCE_RX_USECS |
>+                                  ETHTOOL_COALESCE_RX_MAX_FRAMES |
>+                                  ETHTOOL_COALESCE_TX_USECS |
>+                                  ETHTOOL_COALESCE_TX_MAX_FRAMES |
>+                                  ETHTOOL_COALESCE_USE_ADAPTIVE_RX |
>+                                  ETHTOOL_COALESCE_USE_ADAPTIVE_TX,
>       .get_ethtool_stats      = mana_get_ethtool_stats,
>       .get_sset_count         = mana_get_sset_count,
>       .get_strings            = mana_get_strings,
>diff --git a/include/net/mana/gdma.h b/include/net/mana/gdma.h
>index 70d62bc32837..0a0cc7b080d3 100644
>--- a/include/net/mana/gdma.h
>+++ b/include/net/mana/gdma.h
>@@ -47,6 +47,7 @@ enum gdma_queue_type {
>       GDMA_RQ,
>       GDMA_CQ,
>       GDMA_EQ,
>+      GDMA_DIM,
> };
> 
> enum gdma_work_request_flags {
>@@ -126,6 +127,17 @@ union gdma_doorbell_entry {
>               u64 tail_ptr    : 31;
>               u64 arm         : 1;
>       } eq;
>+
>+      struct {
>+              u64 id           : 24;
>+              u64 reserved     : 8;
>+              u64 mod_usec     : 10;
>+              u64 reserve1     : 5;
>+              u64 mod_usec_vld : 1;
>+              u64 mod_comps    : 8;
>+              u64 reserve2     : 7;
>+              u64 mod_comps_vld: 1;
>+      } dim;
> }; /* HW DATA */
> 
> struct gdma_msg_hdr {
>@@ -484,6 +496,9 @@ void mana_gd_ring_cq(struct gdma_queue *cq, u8 arm_bit);
> 
> int mana_schedule_serv_work(struct gdma_context *gc, enum gdma_eqe_type type);
> 
>+void mana_gd_ring_dim(struct gdma_queue *cq, u32 mod_usec, bool mod_usec_vld,
>+                    u32 mod_comps, bool mod_comps_vld);
>+
> struct gdma_wqe {
>       u32 reserved    :24;
>       u32 last_vbytes :8;
>@@ -629,6 +644,9 @@ enum {
> /* Driver supports self recovery on Hardware Channel timeouts */
> #define GDMA_DRV_CAP_FLAG_1_HWC_TIMEOUT_RECOVERY BIT(25)
> 
>+/* Driver supports dynamic interrupt moderation - DIM */
>+#define GDMA_DRV_CAP_FLAG_1_DYN_INTERRUPT_MODERATION BIT(27)
>+
> #define GDMA_DRV_CAP_FLAGS1 \
>       (GDMA_DRV_CAP_FLAG_1_EQ_SHARING_MULTI_VPORT | \
>        GDMA_DRV_CAP_FLAG_1_NAPI_WKDONE_FIX | \
>@@ -643,7 +661,8 @@ enum {
>        GDMA_DRV_CAP_FLAG_1_SKB_LINEARIZE | \
>        GDMA_DRV_CAP_FLAG_1_PROBE_RECOVERY | \
>        GDMA_DRV_CAP_FLAG_1_HANDLE_STALL_SQ_RECOVERY | \
>-       GDMA_DRV_CAP_FLAG_1_HWC_TIMEOUT_RECOVERY)
>+       GDMA_DRV_CAP_FLAG_1_HWC_TIMEOUT_RECOVERY | \
>+       GDMA_DRV_CAP_FLAG_1_DYN_INTERRUPT_MODERATION)
> 
> #define GDMA_DRV_CAP_FLAGS2 0
> 
>@@ -679,6 +698,9 @@ struct gdma_verify_ver_req {
>       u8 os_ver_str4[128];
> }; /* HW DATA */
> 
>+/* HW supports dynamic interrupt moderation - DIM */
>+#define GDMA_PF_CAP_FLAG_1_DYN_INTERRUPT_MODERATION BIT(15)
>+
> struct gdma_verify_ver_resp {
>       struct gdma_resp_hdr hdr;
>       u64 gdma_protocol_ver;
>diff --git a/include/net/mana/mana.h b/include/net/mana/mana.h
>index d9c27310fd04..57868a79f23d 100644
>--- a/include/net/mana/mana.h
>+++ b/include/net/mana/mana.h
>@@ -4,6 +4,7 @@
> #ifndef _MANA_H
> #define _MANA_H
> 
>+#include <linux/dim.h>
> #include <net/xdp.h>
> #include <net/net_shaper.h>
> 
>@@ -64,6 +65,16 @@ enum TRI_STATE {
> /* Maximum number of packets per coalesced CQE */
> #define MANA_RXCOMP_OOB_NUM_PPI 4
> 
>+/* Default/max interrupt moderation settings */
>+#define MANA_INTR_MODR_USEC_DEF 0
>+#define MANA_INTR_MODR_COMP_DEF 0
>+
>+#define MANA_ADAPTIVE_RX_DEF true
>+#define MANA_ADAPTIVE_TX_DEF true
>+
>+#define MANA_INTR_MODR_USEC_MAX 1023
>+#define MANA_INTR_MODR_COMP_MAX 255

used as a limiter and mask - for mask case i believe
GENMASK cand be used


Reply via email to