writel(tx_gl_reg, tqp_vector->mask_addr + HNS3_VECTOR_GL1_OFFSET);
 }
 
-static void hns3_vector_gl_rl_init(struct hns3_enet_tqp_vector *tqp_vector,
-                                  struct hns3_nic_priv *priv)
+void hns3_set_vector_coalesce_tx_ql(struct hns3_enet_tqp_vector *tqp_vector,
+                                   u32 ql_value)
 {
+       writel(ql_value, tqp_vector->mask_addr + HNS3_VECTOR_TX_QL_OFFSET);
+}
+
+void hns3_set_vector_coalesce_rx_ql(struct hns3_enet_tqp_vector *tqp_vector,
+                                   u32 ql_value)
+{
+       writel(ql_value, tqp_vector->mask_addr + HNS3_VECTOR_RX_QL_OFFSET);
+}
+
+static void hns3_vector_coalesce_init(struct hns3_enet_tqp_vector *tqp_vector,
+                                     struct hns3_nic_priv *priv)
+{
+       struct hnae3_ae_dev *ae_dev = pci_get_drvdata(priv->ae_handle->pdev);
+       struct hns3_enet_coalesce *tx_coal = &tqp_vector->tx_group.coal;
+       struct hns3_enet_coalesce *rx_coal = &tqp_vector->rx_group.coal;
+
        /* initialize the configuration for interrupt coalescing.
         * 1. GL (Interrupt Gap Limiter)
         * 2. RL (Interrupt Rate Limiter)
+        * 3. QL (Interrupt Quantity Limiter)
         *
         * Default: enable interrupt coalescing self-adaptive and GL
         */
-       tqp_vector->tx_group.coal.gl_adapt_enable = 1;
-       tqp_vector->rx_group.coal.gl_adapt_enable = 1;
+       tx_coal->gl_adapt_enable = 1;
+       rx_coal->gl_adapt_enable = 1;
+
+       tx_coal->int_gl = HNS3_INT_GL_50K;
+       rx_coal->int_gl = HNS3_INT_GL_50K;
 
-       tqp_vector->tx_group.coal.int_gl = HNS3_INT_GL_50K;
-       tqp_vector->rx_group.coal.int_gl = HNS3_INT_GL_50K;
+       rx_coal->flow_level = HNS3_FLOW_LOW;
+       tx_coal->flow_level = HNS3_FLOW_LOW;
 
-       tqp_vector->rx_group.coal.flow_level = HNS3_FLOW_LOW;
-       tqp_vector->tx_group.coal.flow_level = HNS3_FLOW_LOW;
+       if (ae_dev->dev_specs.int_ql_max) {
+               tx_coal->ql_enable = 1;
+               rx_coal->ql_enable = 1;
+               tx_coal->int_ql_max = ae_dev->dev_specs.int_ql_max;
+               rx_coal->int_ql_max = ae_dev->dev_specs.int_ql_max;
+               tx_coal->int_ql = HNS3_INT_QL_DEFAULT_CFG;
+               rx_coal->int_ql = HNS3_INT_QL_DEFAULT_CFG;
+       }
 }
 
-static void hns3_vector_gl_rl_init_hw(struct hns3_enet_tqp_vector *tqp_vector,
-                                     struct hns3_nic_priv *priv)
+static void
+hns3_vector_coalesce_init_hw(struct hns3_enet_tqp_vector *tqp_vector,
+                            struct hns3_nic_priv *priv)
 {
+       struct hns3_enet_coalesce *tx_coal = &tqp_vector->tx_group.coal;
+       struct hns3_enet_coalesce *rx_coal = &tqp_vector->rx_group.coal;
        struct hnae3_handle *h = priv->ae_handle;
 
-       hns3_set_vector_coalesce_tx_gl(tqp_vector,
-                                      tqp_vector->tx_group.coal.int_gl);
-       hns3_set_vector_coalesce_rx_gl(tqp_vector,
-                                      tqp_vector->rx_group.coal.int_gl);
+       hns3_set_vector_coalesce_tx_gl(tqp_vector, tx_coal->int_gl);
+       hns3_set_vector_coalesce_rx_gl(tqp_vector, rx_coal->int_gl);
        hns3_set_vector_coalesce_rl(tqp_vector, h->kinfo.int_rl_setting);
+
+       if (tx_coal->ql_enable)
+               hns3_set_vector_coalesce_tx_ql(tqp_vector, tx_coal->int_ql);
+
+       if (rx_coal->ql_enable)
+               hns3_set_vector_coalesce_rx_ql(tqp_vector, rx_coal->int_ql);
 }
 
 static int hns3_nic_set_real_num_queue(struct net_device *netdev)
 
        for (i = 0; i < priv->vector_num; i++) {
                tqp_vector = &priv->tqp_vector[i];
-               hns3_vector_gl_rl_init_hw(tqp_vector, priv);
+               hns3_vector_coalesce_init_hw(tqp_vector, priv);
                tqp_vector->num_tqps = 0;
        }
 
                tqp_vector->idx = i;
                tqp_vector->mask_addr = vector[i].io_addr;
                tqp_vector->vector_irq = vector[i].vector;
-               hns3_vector_gl_rl_init(tqp_vector, priv);
+               hns3_vector_coalesce_init(tqp_vector, priv);
        }
 
 out:
 
 #define HNS3_VECTOR_GL2_OFFSET                 0x300
 #define HNS3_VECTOR_RL_OFFSET                  0x900
 #define HNS3_VECTOR_RL_EN_B                    6
+#define HNS3_VECTOR_TX_QL_OFFSET               0xe00
+#define HNS3_VECTOR_RX_QL_OFFSET               0xf00
 
 #define HNS3_RING_EN_B                         0
 
 #define HNS3_INT_RL_MAX                        0x00EC
 #define HNS3_INT_RL_ENABLE_MASK                0x40
 
+#define HNS3_INT_QL_DEFAULT_CFG                0x20
+
 struct hns3_enet_coalesce {
        u16 int_gl;
-       u8 gl_adapt_enable;
+       u16 int_ql;
+       u16 int_ql_max;
+       u8 gl_adapt_enable:1;
+       u8 ql_enable:1;
        enum hns3_flow_level_range flow_level;
 };
 
                                    u32 gl_value);
 void hns3_set_vector_coalesce_rl(struct hns3_enet_tqp_vector *tqp_vector,
                                 u32 rl_value);
+void hns3_set_vector_coalesce_rx_ql(struct hns3_enet_tqp_vector *tqp_vector,
+                                   u32 ql_value);
+void hns3_set_vector_coalesce_tx_ql(struct hns3_enet_tqp_vector *tqp_vector,
+                                   u32 ql_value);
 
 void hns3_enable_vlan_filter(struct net_device *netdev, bool enable);
 void hns3_request_update_promisc_mode(struct hnae3_handle *handle);
 
        cmd->tx_coalesce_usecs_high = h->kinfo.int_rl_setting;
        cmd->rx_coalesce_usecs_high = h->kinfo.int_rl_setting;
 
+       cmd->tx_max_coalesced_frames = tx_vector->tx_group.coal.int_ql;
+       cmd->rx_max_coalesced_frames = rx_vector->rx_group.coal.int_ql;
+
        return 0;
 }
 
        return 0;
 }
 
+static int hns3_check_ql_coalesce_param(struct net_device *netdev,
+                                       struct ethtool_coalesce *cmd)
+{
+       struct hnae3_handle *handle = hns3_get_handle(netdev);
+       struct hnae3_ae_dev *ae_dev = pci_get_drvdata(handle->pdev);
+
+       if ((cmd->tx_max_coalesced_frames || cmd->rx_max_coalesced_frames) &&
+           !ae_dev->dev_specs.int_ql_max) {
+               netdev_err(netdev, "coalesced frames is not supported\n");
+               return -EOPNOTSUPP;
+       }
+
+       if (cmd->tx_max_coalesced_frames > ae_dev->dev_specs.int_ql_max ||
+           cmd->rx_max_coalesced_frames > ae_dev->dev_specs.int_ql_max) {
+               netdev_err(netdev,
+                          "invalid coalesced_frames value, range is 0-%u\n",
+                          ae_dev->dev_specs.int_ql_max);
+               return -ERANGE;
+       }
+
+       return 0;
+}
+
 static int hns3_check_coalesce_para(struct net_device *netdev,
                                    struct ethtool_coalesce *cmd)
 {
                return ret;
        }
 
+       ret = hns3_check_ql_coalesce_param(netdev, cmd);
+       if (ret)
+               return ret;
+
        if (cmd->use_adaptive_tx_coalesce == 1 ||
            cmd->use_adaptive_rx_coalesce == 1) {
                netdev_info(netdev,
        tx_vector->tx_group.coal.int_gl = cmd->tx_coalesce_usecs;
        rx_vector->rx_group.coal.int_gl = cmd->rx_coalesce_usecs;
 
+       tx_vector->tx_group.coal.int_ql = cmd->tx_max_coalesced_frames;
+       rx_vector->rx_group.coal.int_ql = cmd->rx_max_coalesced_frames;
+
        hns3_set_vector_coalesce_tx_gl(tx_vector,
                                       tx_vector->tx_group.coal.int_gl);
        hns3_set_vector_coalesce_rx_gl(rx_vector,
 
        hns3_set_vector_coalesce_rl(tx_vector, h->kinfo.int_rl_setting);
        hns3_set_vector_coalesce_rl(rx_vector, h->kinfo.int_rl_setting);
+
+       if (tx_vector->tx_group.coal.ql_enable)
+               hns3_set_vector_coalesce_tx_ql(tx_vector,
+                                              tx_vector->tx_group.coal.int_ql);
+       if (rx_vector->rx_group.coal.ql_enable)
+               hns3_set_vector_coalesce_rx_ql(rx_vector,
+                                              rx_vector->rx_group.coal.int_ql);
 }
 
 static int hns3_set_coalesce(struct net_device *netdev,
 #define HNS3_ETHTOOL_COALESCE  (ETHTOOL_COALESCE_USECS |               \
                                 ETHTOOL_COALESCE_USE_ADAPTIVE |        \
                                 ETHTOOL_COALESCE_RX_USECS_HIGH |       \
-                                ETHTOOL_COALESCE_TX_USECS_HIGH)
+                                ETHTOOL_COALESCE_TX_USECS_HIGH |       \
+                                ETHTOOL_COALESCE_MAX_FRAMES)
 
 static const struct ethtool_ops hns3vf_ethtool_ops = {
        .supported_coalesce_params = HNS3_ETHTOOL_COALESCE,