RE: [PATCH net-next] net: mana: Add Interrupt Moderation support
From: Jagielski, Jedrzej
Date: Mon Jun 01 2026 - 05:46:47 EST
From: Haiyang Zhang <haiyangz@xxxxxxxxxxxxxxxxxxx>
Sent: Saturday, May 30, 2026 9:50 PM
>From: Haiyang Zhang <haiyangz@xxxxxxxxxxxxx>
>
>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 <haiyangz@xxxxxxxxxxxxx>
>---
> 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