provide meter ops implementations.<br /> <br />Signed-off-by: Junlong Wang <wang.junlong1@zte.com.cn> <br />---<br /> doc/guides/nics/features/zxdh.ini  |    3 +<br /> doc/guides/nics/zxdh.rst           |    1 +<br /> drivers/net/zxdh/meson.build       |    1 +<br /> drivers/net/zxdh/zxdh_ethdev.c     |   82 +-<br /> drivers/net/zxdh/zxdh_ethdev.h     |   17 +-<br /> drivers/net/zxdh/zxdh_ethdev_ops.c |    4 +<br /> drivers/net/zxdh/zxdh_ethdev_ops.h |    1 +<br /> drivers/net/zxdh/zxdh_msg.c        |  196 +++++<br /> drivers/net/zxdh/zxdh_msg.h        |   47 ++<br /> drivers/net/zxdh/zxdh_mtr.c        | 1223 ++++++++++++++++++++++++++++<br /> drivers/net/zxdh/zxdh_mtr.h        |  114 +++<br /> drivers/net/zxdh/zxdh_np.c         |  515 +++++++++++-<br /> drivers/net/zxdh/zxdh_np.h         |  224 +++++<br /> drivers/net/zxdh/zxdh_tables.h     |    2 +<br /> 14 files changed, 2382 insertions(+), 48 deletions(-)<br /> create mode 100644 drivers/net/zxdh/zxdh_mtr.c<br /> create mode 100644 drivers/net/zxdh/zxdh_mtr.h<br /> <br />diff --git a/doc/guides/nics/features/zxdh.ini b/doc/guides/nics/features/zxdh.ini<br />index 55da709e53..277e17a584 100644<br />--- a/doc/guides/nics/features/zxdh.ini<br />+++ b/doc/guides/nics/features/zxdh.ini<br />@@ -33,3 +33,6 @@ TSO                  = Y<br /> Extended stats       = Y<br /> FW version           = Y<br /> Module EEPROM dump   = Y<br />+<br />+[rte_flow actions]<br />+drop                 = Y<br />diff --git a/doc/guides/nics/zxdh.rst b/doc/guides/nics/zxdh.rst<br />index 3cf0615a7d..26dd527196 100644<br />--- a/doc/guides/nics/zxdh.rst<br />+++ b/doc/guides/nics/zxdh.rst<br />@@ -40,6 +40,7 @@ Features of the ZXDH PMD are:<br /> - Hardware LRO<br /> - Hardware TSO for generic IP or UDP tunnel, including VXLAN<br /> - Extended Statistics query<br />+- Ingress meter support<br />  <br />  <br /> Driver compilation and testing<br />diff --git a/drivers/net/zxdh/meson.build b/drivers/net/zxdh/meson.build<br />index a5acc67eb9..de2bd094b3 100644<br />--- a/drivers/net/zxdh/meson.build<br />+++ b/drivers/net/zxdh/meson.build<br />@@ -23,6 +23,7 @@ sources = files(<br />         'zxdh_tables.c',<br />         'zxdh_rxtx.c',<br />         'zxdh_ethdev_ops.c',<br />+        'zxdh_mtr.c',<br /> )<br />  <br /> cflags += no_wvla_cflag<br />diff --git a/drivers/net/zxdh/zxdh_ethdev.c b/drivers/net/zxdh/zxdh_ethdev.c<br />index 44a50d7dfd..e683cbd616 100644<br />--- a/drivers/net/zxdh/zxdh_ethdev.c<br />+++ b/drivers/net/zxdh/zxdh_ethdev.c<br />@@ -21,8 +21,9 @@<br /> struct zxdh_hw_internal zxdh_hw_internal[RTE_MAX_ETHPORTS];<br /> struct zxdh_dev_shared_data g_dev_sd[ZXDH_SLOT_MAX];<br /> static rte_spinlock_t zxdh_shared_data_lock = RTE_SPINLOCK_INITIALIZER;<br />-static struct zxdh_shared_data *zxdh_shared_data;<br />+struct zxdh_shared_data *zxdh_shared_data;<br /> struct zxdh_net_hdr_dl g_net_hdr_dl[RTE_MAX_ETHPORTS];<br />+struct zxdh_mtr_res g_mtr_res;<br />  <br /> #define ZXDH_INVALID_DTBQUE      0xFFFF<br /> #define ZXDH_INVALID_SLOT_IDX    0xFFFF<br />@@ -1404,6 +1405,7 @@ static const struct eth_dev_ops zxdh_eth_dev_ops = {<br />     .get_module_info         = zxdh_dev_get_module_info,<br />     .get_module_eeprom         = zxdh_dev_get_module_eeprom,<br />     .dev_supported_ptypes_get = zxdh_dev_supported_ptypes_get,<br />+    .mtr_ops_get             = zxdh_meter_ops_get,<br /> };<br />  <br /> static int32_t<br />@@ -1686,6 +1688,72 @@ zxdh_init_shared_data(void)<br />     return ret;<br /> }<br />  <br />+static void<br />+zxdh_free_sh_res(void)<br />+{<br />+    if (rte_eal_process_type() == RTE_PROC_PRIMARY) {<br />+        rte_spinlock_lock(&zxdh_shared_data_lock);<br />+        if (zxdh_shared_data != NULL && zxdh_shared_data->init_done && <br />+            (--zxdh_shared_data->dev_refcnt == 0)) {<br />+            rte_mempool_free(zxdh_shared_data->mtr_mp);<br />+            rte_mempool_free(zxdh_shared_data->mtr_profile_mp);<br />+            rte_mempool_free(zxdh_shared_data->mtr_policy_mp);<br />+        }<br />+        rte_spinlock_unlock(&zxdh_shared_data_lock);<br />+    }<br />+}<br />+<br />+static int<br />+zxdh_init_sh_res(struct zxdh_shared_data *sd)<br />+{<br />+    const char *MZ_ZXDH_MTR_MP         = "zxdh_mtr_mempool";<br />+    const char *MZ_ZXDH_MTR_PROFILE_MP = "zxdh_mtr_profile_mempool";<br />+    const char *MZ_ZXDH_MTR_POLICY_MP = "zxdh_mtr_policy_mempool";<br />+    struct rte_mempool *flow_mp = NULL;<br />+    struct rte_mempool *mtr_mp = NULL;<br />+    struct rte_mempool *mtr_profile_mp = NULL;<br />+    struct rte_mempool *mtr_policy_mp = NULL;<br />+<br />+    if (rte_eal_process_type() == RTE_PROC_PRIMARY) {<br />+        mtr_mp = rte_mempool_create(MZ_ZXDH_MTR_MP, ZXDH_MAX_MTR_NUM,<br />+            sizeof(struct zxdh_mtr_object), 64, 0,<br />+            NULL, NULL, NULL, NULL, SOCKET_ID_ANY, 0);<br />+        if (mtr_mp == NULL) {<br />+            PMD_DRV_LOG(ERR, "Cannot allocate zxdh mtr mempool");<br />+            goto error;<br />+        }<br />+        mtr_profile_mp = rte_mempool_create(MZ_ZXDH_MTR_PROFILE_MP,<br />+            MAX_MTR_PROFILE_NUM, sizeof(struct zxdh_meter_profile),<br />+            64, 0, NULL, NULL, NULL,<br />+            NULL, SOCKET_ID_ANY, 0);<br />+        if (mtr_profile_mp == NULL) {<br />+            PMD_DRV_LOG(ERR, "Cannot allocate zxdh mtr profile mempool");<br />+            goto error;<br />+        }<br />+        mtr_policy_mp = rte_mempool_create(MZ_ZXDH_MTR_POLICY_MP,<br />+            ZXDH_MAX_POLICY_NUM, sizeof(struct zxdh_meter_policy),<br />+            64, 0, NULL, NULL, NULL, NULL, SOCKET_ID_ANY, 0);<br />+        if (mtr_policy_mp == NULL) {<br />+            PMD_DRV_LOG(ERR, "Cannot allocate zxdh mtr profile mempool");<br />+            goto error;<br />+        }<br />+        sd->mtr_mp = mtr_mp;<br />+        sd->mtr_profile_mp = mtr_profile_mp;<br />+        sd->mtr_policy_mp = mtr_policy_mp;<br />+        TAILQ_INIT(&zxdh_shared_data->meter_profile_list);<br />+        TAILQ_INIT(&zxdh_shared_data->mtr_list);<br />+        TAILQ_INIT(&zxdh_shared_data->mtr_policy_list);<br />+    }<br />+    return 0;<br />+<br />+error:<br />+    rte_mempool_free(mtr_policy_mp);<br />+    rte_mempool_free(mtr_profile_mp);<br />+    rte_mempool_free(mtr_mp);<br />+    rte_mempool_free(flow_mp);<br />+    return -rte_errno;<br />+}<br />+<br /> static int<br /> zxdh_init_once(struct rte_eth_dev *eth_dev)<br /> {<br />@@ -1713,8 +1781,15 @@ zxdh_init_once(struct rte_eth_dev *eth_dev)<br />         goto out;<br />     }<br />     /* RTE_PROC_PRIMARY */<br />-    if (!sd->init_done)<br />+    if (!sd->init_done) {<br />+        /*shared struct and res init */<br />+        ret = zxdh_init_sh_res(sd);<br />+        if (ret != 0)<br />+            goto out;<br />+        rte_spinlock_init(&g_mtr_res.hw_plcr_res_lock);<br />+        memset(&g_mtr_res, 0, sizeof(g_mtr_res));<br />         sd->init_done = true;<br />+    }<br />     sd->dev_refcnt++;<br /> out:<br />     rte_spinlock_unlock(&sd->lock);<br />@@ -1927,6 +2002,9 @@ zxdh_eth_dev_init(struct rte_eth_dev *eth_dev)<br />     zxdh_np_uninit(eth_dev);<br />     zxdh_bar_msg_chan_exit();<br />     zxdh_priv_res_free(hw);<br />+    zxdh_free_sh_res();<br />+    rte_free(hw->dev_sd);<br />+    hw->dev_sd = NULL;<br />     rte_free(eth_dev->data->mac_addrs);<br />     eth_dev->data->mac_addrs = NULL;<br />     return ret;<br />diff --git a/drivers/net/zxdh/zxdh_ethdev.h b/drivers/net/zxdh/zxdh_ethdev.h<br />index 30df1eefe3..04b0b58c74 100644<br />--- a/drivers/net/zxdh/zxdh_ethdev.h<br />+++ b/drivers/net/zxdh/zxdh_ethdev.h<br />@@ -10,6 +10,8 @@<br /> #include <rte_interrupts.h> <br /> #include <eal_interrupts.h> <br />  <br />+#include "zxdh_mtr.h" <br />+<br /> /* ZXDH PCI vendor/device ID. */<br /> #define ZXDH_PCI_VENDOR_ID        0x1cf2<br />  <br />@@ -114,7 +116,10 @@ struct zxdh_hw {<br />  <br />     uint8_t use_msix;<br />     uint8_t duplex;<br />-    uint8_t is_pf;<br />+    uint8_t is_pf         : 1,<br />+            rsv : 1,<br />+            i_mtr_en      : 1,<br />+            e_mtr_en      : 1;<br />     uint8_t msg_chan_init;<br />     uint8_t phyport;<br />     uint8_t panel_id;<br />@@ -130,11 +135,11 @@ struct zxdh_hw {<br />     uint32_t dev_id;<br />  <br />     uint8_t queue_set_flag;<br />+    struct zxdh_vlan_offload_cfg vlan_offload_cfg;<br />     uint16_t queue_pool_count;<br />     uint16_t queue_pool_start;<br />-    struct zxdh_vlan_offload_cfg vlan_offload_cfg;<br />     uint8_t dl_net_hdr_len;<br />-    uint8_t rsv[2];<br />+    uint8_t rsv1[3];<br /> };<br />  <br /> struct zxdh_dtb_shared_data {<br />@@ -159,6 +164,12 @@ struct zxdh_shared_data {<br />     int32_t np_init_done;<br />     uint32_t dev_refcnt;<br />     struct zxdh_dtb_shared_data *dtb_data;<br />+    struct rte_mempool *mtr_mp;<br />+    struct rte_mempool *mtr_profile_mp;<br />+    struct rte_mempool *mtr_policy_mp;<br />+    struct zxdh_mtr_profile_list meter_profile_list;<br />+    struct zxdh_mtr_list mtr_list;<br />+    struct zxdh_mtr_policy_list mtr_policy_list;<br /> };<br />  <br /> struct zxdh_dev_shared_data {<br />diff --git a/drivers/net/zxdh/zxdh_ethdev_ops.c b/drivers/net/zxdh/zxdh_ethdev_ops.c<br />index ecf4c28b0f..2b02734c62 100644<br />--- a/drivers/net/zxdh/zxdh_ethdev_ops.c<br />+++ b/drivers/net/zxdh/zxdh_ethdev_ops.c<br />@@ -14,6 +14,7 @@<br /> #include "zxdh_rxtx.h" <br /> #include "zxdh_np.h" <br /> #include "zxdh_queue.h" <br />+#include "zxdh_mtr.h" <br />  <br /> #define ZXDH_VLAN_FILTER_GROUPS       64<br /> #define ZXDH_INVALID_LOGIC_QID        0xFFFFU<br />@@ -1624,6 +1625,9 @@ zxdh_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)<br />     stats->ierrors = vqm_stats.rx_error + mac_stats.rx_error + np_stats.rx_mtu_drop_pkts;<br />     stats->oerrors = vqm_stats.tx_error + mac_stats.tx_error + np_stats.tx_mtu_drop_pkts;<br />  <br />+    if (hw->i_mtr_en || hw->e_mtr_en)<br />+        stats->imissed  += np_stats.rx_mtr_drop_pkts;<br />+<br />     stats->rx_nombuf = dev->data->rx_mbuf_alloc_failed;<br />     for (i = 0; (i < dev->data->nb_rx_queues) && (i < RTE_ETHDEV_QUEUE_STAT_CNTRS); i++) {<br />         struct zxdh_virtnet_rx *rxvq = dev->data->rx_queues[i];<br />diff --git a/drivers/net/zxdh/zxdh_ethdev_ops.h b/drivers/net/zxdh/zxdh_ethdev_ops.h<br />index 1a87a2e201..a5162a6d6b 100644<br />--- a/drivers/net/zxdh/zxdh_ethdev_ops.h<br />+++ b/drivers/net/zxdh/zxdh_ethdev_ops.h<br />@@ -105,5 +105,6 @@ int32_t zxdh_dev_xstats_get_names(struct rte_eth_dev *dev,<br /> int zxdh_dev_fw_version_get(struct rte_eth_dev *dev, char *fw_version, size_t fw_size);<br /> int zxdh_dev_get_module_info(struct rte_eth_dev *dev, struct rte_eth_dev_module_info *modinfo);<br /> int zxdh_dev_get_module_eeprom(struct rte_eth_dev *dev, struct rte_dev_eeprom_info *info);<br />+int zxdh_meter_ops_get(struct rte_eth_dev *dev, void *arg);<br />  <br /> #endif /* ZXDH_ETHDEV_OPS_H */<br />diff --git a/drivers/net/zxdh/zxdh_msg.c b/drivers/net/zxdh/zxdh_msg.c<br />index 24894f2a42..96ad638e83 100644<br />--- a/drivers/net/zxdh/zxdh_msg.c<br />+++ b/drivers/net/zxdh/zxdh_msg.c<br />@@ -10,6 +10,7 @@<br /> #include <rte_cycles.h> <br /> #include <inttypes.h> <br /> #include <rte_malloc.h> <br />+#include "rte_mtr_driver.h" <br />  <br /> #include "zxdh_ethdev.h" <br /> #include "zxdh_logs.h" <br />@@ -1713,6 +1714,12 @@ zxdh_vf_port_attr_set(struct zxdh_hw *pf_hw, uint16_t vport, void *cfg_data,<br />     case ZXDH_PORT_LRO_OFFLOAD_FLAG:<br />         port_attr.lro_offload = attr_msg->value;<br />         break;<br />+    case ZXDH_PORT_EGRESS_METER_EN_OFF_FLAG:<br />+        port_attr.egress_meter_enable = attr_msg->value;<br />+        break;<br />+    case ZXDH_PORT_INGRESS_METER_EN_OFF_FLAG:<br />+        port_attr.ingress_meter_mode = attr_msg->value;<br />+        break;<br />     default:<br />         PMD_DRV_LOG(ERR, "unsupported attr 0x%x set", attr_msg->mode);<br />         return -1;<br />@@ -1865,6 +1872,190 @@ zxdh_vf_np_stats_update(struct zxdh_hw *pf_hw, uint16_t vport,<br />     return 0;<br /> }<br />  <br />+static int<br />+zxdh_vf_mtr_hw_stats_get(struct zxdh_hw *pf_hw,<br />+    uint16_t vport, void *cfg_data,<br />+    struct zxdh_msg_reply_body *res_info,<br />+    uint16_t *res_len)<br />+{<br />+    struct zxdh_mtr_stats_query  *zxdh_mtr_stats_query =<br />+            (struct zxdh_mtr_stats_query  *)cfg_data;<br />+    union zxdh_virport_num v_port = {.vport = vport};<br />+    int ret = 0;<br />+<br />+    uint32_t stat_baseaddr = zxdh_mtr_stats_query->direction ==<br />+                ZXDH_EGRESS ?<br />+                ZXDH_MTR_STATS_EGRESS_BASE : ZXDH_MTR_STATS_INGRESS_BASE;<br />+    uint32_t idx = zxdh_vport_to_vfid(v_port) + stat_baseaddr;<br />+<br />+    if (!res_len || !res_info) {<br />+        PMD_DRV_LOG(ERR, "get stat invalid in params");<br />+        return -1;<br />+    }<br />+    res_info->flag = ZXDH_REPS_FAIL;<br />+    ret = zxdh_np_dtb_stats_get(pf_hw->dev_id, pf_hw->dev_sd->dtb_sd.queueid,<br />+                1, idx, (uint32_t *)&res_info->hw_mtr_stats);<br />+    if (ret) {<br />+        PMD_DRV_LOG(ERR, "get dir %d stats  failed", zxdh_mtr_stats_query->direction);<br />+        return ret;<br />+    }<br />+    res_info->flag = ZXDH_REPS_SUCC;<br />+    *res_len = sizeof(struct zxdh_hw_mtr_stats);<br />+    return 0;<br />+}<br />+<br />+static int<br />+zxdh_vf_mtr_hw_profile_add(struct zxdh_hw *pf_hw,<br />+    uint16_t vport,<br />+    void *cfg_data,<br />+    struct zxdh_msg_reply_body *res_info,<br />+    uint16_t *res_len)<br />+{<br />+    if (!cfg_data || !res_len || !res_info) {<br />+        PMD_DRV_LOG(ERR, " get profileid invalid inparams");<br />+        return -1;<br />+    }<br />+    struct rte_mtr_error error = {0};<br />+    int ret = 0;<br />+    uint64_t profile_id = HW_PROFILE_MAX;<br />+<br />+    struct zxdh_plcr_profile_add  *zxdh_plcr_profile_add =<br />+        (struct zxdh_plcr_profile_add *)cfg_data;<br />+<br />+    res_info->flag = ZXDH_REPS_FAIL;<br />+    *res_len = sizeof(struct zxdh_mtr_profile_info);<br />+    ret = zxdh_hw_profile_alloc_direct(pf_hw->eth_dev,<br />+        zxdh_plcr_profile_add->car_type,<br />+        &profile_id, &error);<br />+<br />+    if (ret) {<br />+        PMD_DRV_LOG(ERR, "pf 0x%x for vf 0x%x alloc hw profile failed",<br />+            pf_hw->vport.vport,<br />+            vport<br />+        );<br />+        return -1;<br />+    }<br />+    zxdh_hw_profile_ref(profile_id);<br />+    res_info->mtr_profile_info.profile_id = profile_id;<br />+    res_info->flag = ZXDH_REPS_SUCC;<br />+<br />+    return 0;<br />+}<br />+<br />+static int<br />+zxdh_vf_mtr_hw_profile_del(struct zxdh_hw *pf_hw,<br />+    uint16_t vport,<br />+    void *cfg_data,<br />+    struct zxdh_msg_reply_body *res_info,<br />+    uint16_t *res_len)<br />+{<br />+    if (!cfg_data || !res_len || !res_info) {<br />+        PMD_DRV_LOG(ERR, " del profileid  invalid inparams");<br />+        return -1;<br />+    }<br />+<br />+    res_info->flag = ZXDH_REPS_FAIL;<br />+    *res_len = 0;<br />+    struct zxdh_plcr_profile_free *mtr_profile_free = (struct zxdh_plcr_profile_free *)cfg_data;<br />+    uint64_t profile_id = mtr_profile_free->profile_id;<br />+    struct rte_mtr_error error = {0};<br />+    int ret;<br />+<br />+    if (profile_id >= HW_PROFILE_MAX) {<br />+        PMD_DRV_LOG(ERR, " del profileid  invalid inparams");<br />+        return -rte_mtr_error_set(&error, ENOTSUP,<br />+                RTE_MTR_ERROR_TYPE_METER_PROFILE_ID, NULL,<br />+                "Meter offload del profile failed  profilie id invalid ");<br />+    }<br />+<br />+    ret = zxdh_hw_profile_unref(pf_hw->eth_dev, mtr_profile_free->car_type, profile_id, &error);<br />+    if (ret) {<br />+        PMD_DRV_LOG(ERR,<br />+            " del  hw vport %d profile %d failed. code:%d",<br />+            vport,<br />+            mtr_profile_free->profile_id,<br />+            ret<br />+        );<br />+        return -rte_mtr_error_set(&error, ENOTSUP,<br />+                RTE_MTR_ERROR_TYPE_METER_PROFILE_ID, NULL,<br />+                "Meter offload del profile failed ");<br />+    }<br />+    res_info->flag = ZXDH_REPS_SUCC;<br />+    return 0;<br />+}<br />+<br />+static int<br />+zxdh_vf_mtr_hw_plcrflow_cfg(struct zxdh_hw *pf_hw,<br />+    uint16_t vport,<br />+    void *cfg_data,<br />+    struct zxdh_msg_reply_body *res_info,<br />+    uint16_t *res_len)<br />+{<br />+    int ret = 0;<br />+<br />+    if (!cfg_data || !res_info || !res_len) {<br />+        PMD_DRV_LOG(ERR, " (vport %d) flow bind failed invalid inparams", vport);<br />+        return -1;<br />+    }<br />+    struct rte_mtr_error error = {0};<br />+    struct zxdh_plcr_flow_cfg *zxdh_plcr_flow_cfg = (struct zxdh_plcr_flow_cfg *)cfg_data;<br />+<br />+    res_info->flag = ZXDH_REPS_FAIL;<br />+    *res_len = 0;<br />+    ret = zxdh_np_stat_car_queue_cfg_set(pf_hw->dev_id,<br />+        zxdh_plcr_flow_cfg->car_type,<br />+        zxdh_plcr_flow_cfg->flow_id,<br />+        zxdh_plcr_flow_cfg->drop_flag,<br />+        zxdh_plcr_flow_cfg->plcr_en,<br />+        (uint64_t)zxdh_plcr_flow_cfg->profile_id);<br />+    if (ret) {<br />+        PMD_DRV_LOG(ERR,<br />+            " dpp_stat_car_queue_cfg_set failed flowid %d    profile id %d. code:%d",<br />+            zxdh_plcr_flow_cfg->flow_id,<br />+            zxdh_plcr_flow_cfg->profile_id,<br />+            ret<br />+        );<br />+        return -rte_mtr_error_set(&error, ENOTSUP,<br />+                RTE_MTR_ERROR_TYPE_MTR_PARAMS,<br />+                NULL, "Failed to bind plcr flow.");<br />+    }<br />+    res_info->flag = ZXDH_REPS_SUCC;<br />+    return 0;<br />+}<br />+<br />+static int<br />+zxdh_vf_mtr_hw_profile_cfg(struct zxdh_hw *pf_hw __rte_unused,<br />+    uint16_t vport,<br />+    void *cfg_data,<br />+    struct zxdh_msg_reply_body *res_info,<br />+    uint16_t *res_len)<br />+{<br />+    int ret = 0;<br />+<br />+    if (!cfg_data || !res_info || !res_len) {<br />+        PMD_DRV_LOG(ERR, " cfg profile invalid inparams");<br />+        return -1;<br />+    }<br />+    res_info->flag = ZXDH_REPS_FAIL;<br />+    *res_len = 0;<br />+    struct rte_mtr_error error = {0};<br />+    struct zxdh_plcr_profile_cfg *zxdh_plcr_profile_cfg =<br />+        (struct zxdh_plcr_profile_cfg *)cfg_data;<br />+    union zxdh_offload_profile_cfg *plcr_param = &zxdh_plcr_profile_cfg->plcr_param;<br />+<br />+    ret = zxdh_np_car_profile_cfg_set(vport,<br />+        zxdh_plcr_profile_cfg->car_type,<br />+        zxdh_plcr_profile_cfg->packet_mode,<br />+        zxdh_plcr_profile_cfg->hw_profile_id,<br />+        plcr_param);<br />+    if (ret) {<br />+        PMD_DRV_LOG(ERR, "(vport %d)config hw profilefailed", vport);<br />+        return -rte_mtr_error_set(&error, ENOTSUP, RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL, "Meter offload cfg profile failed");<br />+    }<br />+    res_info->flag = ZXDH_REPS_SUCC;<br />+    return 0;<br />+}<br />+<br /> static const zxdh_msg_process_callback zxdh_proc_cb[] = {<br />     [ZXDH_NULL] = NULL,<br />     [ZXDH_VF_PORT_INIT] = zxdh_vf_port_init,<br />@@ -1883,6 +2074,11 @@ static const zxdh_msg_process_callback zxdh_proc_cb[] = {<br />     [ZXDH_RSS_HF_GET] = zxdh_vf_rss_hf_get,<br />     [ZXDH_PORT_ATTRS_SET] = zxdh_vf_port_attr_set,<br />     [ZXDH_GET_NP_STATS] = zxdh_vf_np_stats_update,<br />+    [ZXDH_PORT_METER_STAT_GET] = zxdh_vf_mtr_hw_stats_get,<br />+    [ZXDH_PLCR_CAR_PROFILE_ID_ADD] = zxdh_vf_mtr_hw_profile_add,<br />+    [ZXDH_PLCR_CAR_PROFILE_ID_DELETE] =  zxdh_vf_mtr_hw_profile_del,<br />+    [ZXDH_PLCR_CAR_QUEUE_CFG_SET] = zxdh_vf_mtr_hw_plcrflow_cfg,<br />+    [ZXDH_PLCR_CAR_PROFILE_CFG_SET] = zxdh_vf_mtr_hw_profile_cfg,<br /> };<br />  <br /> static inline int<br />diff --git a/drivers/net/zxdh/zxdh_msg.h b/drivers/net/zxdh/zxdh_msg.h<br />index d5722838ae..58836bb4b7 100644<br />--- a/drivers/net/zxdh/zxdh_msg.h<br />+++ b/drivers/net/zxdh/zxdh_msg.h<br />@@ -10,6 +10,7 @@<br /> #include <ethdev_driver.h> <br />  <br /> #include "zxdh_ethdev_ops.h" <br />+#include "zxdh_mtr.h" <br />  <br /> #define ZXDH_BAR0_INDEX                 0<br /> #define ZXDH_CTRLCH_OFFSET              (0x2000)<br />@@ -230,6 +231,11 @@ enum zxdh_msg_type {<br />     ZXDH_PORT_PROMISC_SET = 26,<br />  <br />     ZXDH_GET_NP_STATS = 31,<br />+    ZXDH_PLCR_CAR_PROFILE_ID_ADD = 36,<br />+    ZXDH_PLCR_CAR_PROFILE_ID_DELETE = 37,<br />+    ZXDH_PLCR_CAR_PROFILE_CFG_SET,<br />+    ZXDH_PLCR_CAR_QUEUE_CFG_SET = 40,<br />+    ZXDH_PORT_METER_STAT_GET = 42,<br />  <br />     ZXDH_MSG_TYPE_END,<br /> };<br />@@ -373,6 +379,9 @@ struct zxdh_flash_msg {<br />     uint8_t firmware_version[ZXDH_FWVERS_LEN];<br /> };<br />  <br />+struct zxdh_mtr_profile_info {<br />+    uint64_t profile_id;<br />+};<br />  <br /> struct zxdh_msg_reply_body {<br />     enum zxdh_reps_flag flag;<br />@@ -386,6 +395,8 @@ struct zxdh_msg_reply_body {<br />         struct zxdh_mac_reply_msg mac_reply_msg;<br />         struct zxdh_flash_msg flash_msg;<br />         struct zxdh_mac_module_eeprom_msg module_eeprom_msg;<br />+        struct zxdh_mtr_profile_info mtr_profile_info;<br />+        struct zxdh_mtr_stats hw_mtr_stats;<br />     };<br /> };<br />  <br />@@ -452,6 +463,37 @@ struct zxdh_agent_msg_head {<br />     uint16_t pcie_id;<br /> };<br />  <br />+struct zxdh_plcr_profile_add {<br />+    uint8_t car_type;/* 0 :carA ; 1:carB ;2 carC*/<br />+};<br />+<br />+struct zxdh_mtr_stats_query {<br />+    uint8_t direction;<br />+    uint8_t is_clr;<br />+};<br />+<br />+struct zxdh_plcr_profile_cfg {<br />+    uint8_t car_type; /* 0 :carA ; 1:carB ;2 carC*/<br />+    uint8_t packet_mode;  /*0 bps  1 pps */<br />+    uint16_t hw_profile_id;<br />+    union zxdh_offload_profile_cfg plcr_param;<br />+};<br />+<br />+struct zxdh_plcr_flow_cfg {<br />+    uint8_t car_type;  /* 0:carA; 1:carB; 2:carC */<br />+    uint8_t drop_flag; /* default */<br />+    uint8_t plcr_en;   /* 1:bind, 0:unbind */<br />+    uint8_t rsv;<br />+    uint16_t flow_id;<br />+    uint16_t profile_id;<br />+};<br />+<br />+struct zxdh_plcr_profile_free {<br />+    uint8_t car_type;<br />+    uint8_t rsv;<br />+    uint16_t profile_id;<br />+};<br />+<br /> struct zxdh_msg_info {<br />     union {<br />         uint8_t head_len[ZXDH_MSG_HEAD_LEN];<br />@@ -473,6 +515,11 @@ struct zxdh_msg_info {<br />         struct zxdh_rss_hf rss_hf;<br />         struct zxdh_np_stats_updata_msg np_stats_query;<br />         struct zxdh_mac_module_eeprom_msg module_eeprom_msg;<br />+        struct zxdh_plcr_profile_add zxdh_plcr_profile_add;<br />+        struct zxdh_plcr_profile_free zxdh_plcr_profile_free;<br />+        struct zxdh_plcr_profile_cfg zxdh_plcr_profile_cfg;<br />+        struct zxdh_plcr_flow_cfg  zxdh_plcr_flow_cfg;<br />+        struct zxdh_mtr_stats_query  zxdh_mtr_stats_query;<br />     } data;<br /> };<br />  <br />diff --git a/drivers/net/zxdh/zxdh_mtr.c b/drivers/net/zxdh/zxdh_mtr.c<br />new file mode 100644<br />index 0000000000..3797a5b29b<br />--- /dev/null<br />+++ b/drivers/net/zxdh/zxdh_mtr.c<br />@@ -0,0 +1,1223 @@<br />+/* SPDX-License-Identifier: BSD-3-Clause<br />+ * Copyright(c) 2024 ZTE Corporation<br />+ */<br />+<br />+#include <bus_pci_driver.h> <br />+#include <rte_ethdev.h> <br />+#include <rte_mtr_driver.h> <br />+#include <rte_mempool.h> <br />+<br />+#include "zxdh_logs.h" <br />+#include "zxdh_mtr.h" <br />+#include "zxdh_msg.h" <br />+#include "zxdh_ethdev.h" <br />+#include "zxdh_tables.h" <br />+<br />+#define ZXDH_SHARE_FLOW_MAX       2048<br />+#define ZXDH_HW_PROFILE_MAX       512<br />+#define ZXDH_MAX_MTR_PROFILE_NUM  ZXDH_HW_PROFILE_MAX<br />+#define ZXDH_PORT_MTR_FID_BASE    8192<br />+<br />+/*  Maximum value of srTCM metering parameters, unit_step: 64kb<br />+ *  61K~400000000(400G) bps, uint 64Kbps CBS/EBS/PBS max bucket depth 128MB<br />+ *  PPS: 1pps~600Mpps<br />+ */<br />+#define ZXDH_SRTCM_CIR_MIN_BPS  (61 * (1ULL << 10))<br />+#define ZXDH_SRTCM_CIR_MAX_BPS  (400 * (1ULL << 30))<br />+#define ZXDH_SRTCM_EBS_MAX_B    (128 * (1ULL << 20))<br />+#define ZXDH_SRTCM_CBS_MAX_B    (128 * (1ULL << 20))<br />+#define ZXDH_TRTCM_PBS_MAX_B    (128 * (1ULL << 20))<br />+#define ZXDH_TRTCM_PIR_MAX_BPS  (400 * (1ULL << 30))<br />+#define ZXDH_TRTCM_PIR_MIN_BPS  (61 * (1ULL << 10))<br />+<br />+#define ZXDH_SRTCM_CIR_MIN_PPS  (1)<br />+#define ZXDH_SRTCM_CIR_MAX_PPS  (200 * (1ULL << 20))<br />+#define ZXDH_SRTCM_CBS_MAX_P    (8192)<br />+#define ZXDH_SRTCM_EBS_MAX_P    (8192)<br />+#define ZXDH_TRTCM_PBS_MAX_P    (8192)<br />+#define ZXDH_TRTCM_PIR_MIN_PPS  (1)<br />+#define ZXDH_TRTCM_PIR_MAX_PPS  (200 * (1ULL << 20))<br />+<br />+#define ZXDH_MP_ALLOC_OBJ_FUNC(mp, obj) rte_mempool_get(mp, (void **)&(obj))<br />+#define ZXDH_MP_FREE_OBJ_FUNC(mp, obj) rte_mempool_put(mp, obj)<br />+<br />+#define ZXDH_VFUNC_ACTIVE_BIT  11<br />+#define ZXDH_VFUNC_NUM_MASK    0xff<br />+#define ZXDH_GET_OWNER_PF_VPORT(vport) \<br />+    (((vport) & ~(ZXDH_VFUNC_NUM_MASK)) & (~(1 << ZXDH_VFUNC_ACTIVE_BIT)))<br />+<br />+enum ZXDH_PLCR_CD {<br />+    ZXDH_PLCR_CD_SRTCM = 0,<br />+    ZXDH_PLCR_CD_TRTCM,<br />+    ZXDH_PLCR_CD_MEF101,<br />+};<br />+enum ZXDH_PLCR_CM {<br />+    ZXDH_PLCR_CM_BLIND = 0,<br />+    ZXDH_PLCR_CM_AWARE,<br />+};<br />+enum ZXDH_PLCR_CF {<br />+    ZXDH_PLCR_CF_UNOVERFLOW = 0,<br />+    ZXDH_PLCR_CF_OVERFLOW,<br />+};<br />+<br />+int<br />+zxdh_hw_profile_ref(uint16_t hw_profile_id)<br />+{<br />+    if (hw_profile_id >= HW_PROFILE_MAX)<br />+        return  -1;<br />+<br />+    rte_spinlock_lock(&g_mtr_res.hw_plcr_res_lock);<br />+    g_mtr_res.hw_profile_refcnt[hw_profile_id]++;<br />+    rte_spinlock_unlock(&g_mtr_res.hw_plcr_res_lock);<br />+    return 0;<br />+}<br />+<br />+static struct zxdh_meter_policy<br />+*zxdh_mtr_policy_find_by_id(struct zxdh_mtr_policy_list *mtr_policy_list,<br />+    uint16_t policy_id, uint16_t dpdk_portid)<br />+{<br />+    struct zxdh_meter_policy *mtr_policy = NULL;<br />+<br />+    TAILQ_FOREACH(mtr_policy, mtr_policy_list, next) {<br />+        if (policy_id == mtr_policy->policy_id && <br />+            dpdk_portid == mtr_policy->dpdk_port_id)<br />+            return mtr_policy;<br />+    }<br />+    return NULL;<br />+}<br />+<br />+static int<br />+zxdh_policy_validate_actions(const struct rte_flow_action *actions[RTE_COLORS],<br />+    struct rte_mtr_error *error)<br />+{<br />+    if (!actions[RTE_COLOR_RED] || actions[RTE_COLOR_RED]->type != RTE_FLOW_ACTION_TYPE_DROP)<br />+        return -rte_mtr_error_set(error, ENOTSUP, RTE_MTR_ERROR_TYPE_METER_POLICY, NULL,<br />+            "Red color only supports drop action.");<br />+    return 0;<br />+}<br />+<br />+static int<br />+mtr_hw_stats_get(struct zxdh_hw *hw, uint8_t direction, struct zxdh_hw_mtr_stats *hw_mtr_stats)<br />+{<br />+    union zxdh_virport_num v_port = hw->vport;<br />+    uint32_t stat_baseaddr = (direction == ZXDH_EGRESS)<br />+        ? ZXDH_MTR_STATS_EGRESS_BASE<br />+        : ZXDH_MTR_STATS_INGRESS_BASE;<br />+    uint32_t idx = zxdh_vport_to_vfid(v_port) + stat_baseaddr;<br />+    struct zxdh_dtb_shared_data *dtb_sd = &hw->dev_sd->dtb_sd;<br />+<br />+    int ret = zxdh_np_dtb_stats_get(hw->dev_id,<br />+        dtb_sd->queueid, ZXDH_STAT_128_MODE,<br />+        idx, (uint32_t *)hw_mtr_stats);<br />+<br />+    if (ret) {<br />+        PMD_DRV_LOG(ERR, "get vport 0x%x (vfid 0x%x) dir %u stats failed",<br />+                v_port.vport,<br />+                hw->vfid,<br />+                direction);<br />+        return ret;<br />+    }<br />+    PMD_DRV_LOG(INFO, "get vport 0x%x (vfid 0x%x) dir %u stats",<br />+            v_port.vport,<br />+            hw->vfid,<br />+            direction);<br />+    return 0;<br />+}<br />+<br />+static int<br />+zxdh_mtr_stats_get(struct rte_eth_dev *dev, int dir, struct zxdh_mtr_stats *mtr_stats)<br />+{<br />+    struct zxdh_hw_mtr_stats hw_mtr_stat = {0};<br />+    struct zxdh_hw *hw = dev->data->dev_private;<br />+    int ret = mtr_hw_stats_get(hw, dir, &hw_mtr_stat);<br />+<br />+    if (ret) {<br />+        PMD_DRV_LOG(ERR, "port %u dir %u get mtr stats failed", hw->vport.vport, dir);<br />+        return ret;<br />+    }<br />+    mtr_stats->n_bytes_dropped =<br />+        (uint64_t)(rte_le_to_cpu_32(hw_mtr_stat.n_bytes_dropped_hi)) << 32 |<br />+        rte_le_to_cpu_32(hw_mtr_stat.n_bytes_dropped_lo);<br />+    mtr_stats->n_pkts_dropped =<br />+        (uint64_t)(rte_le_to_cpu_32(hw_mtr_stat.n_pkts_dropped_hi)) << 32 |<br />+        rte_le_to_cpu_32(hw_mtr_stat.n_pkts_dropped_lo);<br />+<br />+    return 0;<br />+}<br />+<br />+static int<br />+zxdh_meter_cap_get(struct rte_eth_dev *dev __rte_unused,<br />+    struct rte_mtr_capabilities *cap,<br />+    struct rte_mtr_error *error __rte_unused)<br />+{<br />+    struct rte_mtr_capabilities capa = {<br />+        .n_max = ZXDH_MAX_MTR_NUM,<br />+        .n_shared_max = ZXDH_SHARE_FLOW_MAX,<br />+        .meter_srtcm_rfc2697_n_max = ZXDH_MAX_MTR_PROFILE_NUM,<br />+        .meter_trtcm_rfc2698_n_max = ZXDH_MAX_MTR_PROFILE_NUM,<br />+        .color_aware_srtcm_rfc2697_supported = 1,<br />+        .color_aware_trtcm_rfc2698_supported = 1,<br />+        .meter_rate_max = ZXDH_SRTCM_CIR_MAX_BPS,<br />+        .meter_policy_n_max = ZXDH_MAX_POLICY_NUM,<br />+        .srtcm_rfc2697_byte_mode_supported   = 1,<br />+        .srtcm_rfc2697_packet_mode_supported = 1,<br />+        .trtcm_rfc2698_byte_mode_supported   = 1,<br />+        .trtcm_rfc2698_packet_mode_supported = 1,<br />+        .stats_mask = RTE_MTR_STATS_N_PKTS_DROPPED | RTE_MTR_STATS_N_BYTES_DROPPED,<br />+    };<br />+<br />+    *cap = capa;<br />+    return 0;<br />+}<br />+<br />+static int<br />+zxdh_mtr_profile_validate(uint32_t meter_profile_id,<br />+        struct rte_mtr_meter_profile *profile,<br />+        struct rte_mtr_error *error)<br />+{<br />+    uint64_t cir_min, cir_max, cbs_max, ebs_max, pir_min, pir_max, pbs_max;<br />+<br />+    if (profile == NULL || meter_profile_id >= ZXDH_MAX_MTR_PROFILE_NUM) {<br />+        return -rte_mtr_error_set(error, EINVAL, RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,<br />+            "Meter profile param id invalid or null");<br />+    }<br />+<br />+    if (profile->packet_mode == 0) {<br />+        cir_min = ZXDH_SRTCM_CIR_MIN_BPS / 8;<br />+        cir_max = ZXDH_SRTCM_CIR_MAX_BPS / 8;<br />+        cbs_max = ZXDH_SRTCM_CBS_MAX_B;<br />+        ebs_max = ZXDH_SRTCM_EBS_MAX_B;<br />+        pir_min = ZXDH_TRTCM_PIR_MIN_BPS / 8;<br />+        pir_max = ZXDH_TRTCM_PIR_MAX_BPS / 8;<br />+        pbs_max = ZXDH_TRTCM_PBS_MAX_B;<br />+    } else {<br />+        cir_min = ZXDH_SRTCM_CIR_MIN_PPS;<br />+        cir_max = ZXDH_SRTCM_CIR_MAX_PPS;<br />+        cbs_max = ZXDH_SRTCM_CBS_MAX_P;<br />+        ebs_max = ZXDH_SRTCM_EBS_MAX_P;<br />+        pir_min = ZXDH_TRTCM_PIR_MIN_PPS;<br />+        pir_max = ZXDH_TRTCM_PIR_MAX_PPS;<br />+        pbs_max = ZXDH_TRTCM_PBS_MAX_P;<br />+    }<br />+    if (profile->alg == RTE_MTR_SRTCM_RFC2697) {<br />+        if (profile->srtcm_rfc2697.cir >= cir_min && <br />+            profile->srtcm_rfc2697.cir < cir_max && <br />+            profile->srtcm_rfc2697.cbs < cbs_max && <br />+            profile->srtcm_rfc2697.cbs > 0 && <br />+            profile->srtcm_rfc2697.ebs > 0 && <br />+            profile->srtcm_rfc2697.ebs < ebs_max) {<br />+            goto check_exist;<br />+        } else {<br />+            return -rte_mtr_error_set<br />+                    (error, ENOTSUP,<br />+                    RTE_MTR_ERROR_TYPE_METER_PROFILE,<br />+                    NULL,<br />+                    "Invalid metering parameters");<br />+        }<br />+    } else if (profile->alg == RTE_MTR_TRTCM_RFC2698) {<br />+        if (profile->trtcm_rfc2698.cir >= cir_min && <br />+            profile->trtcm_rfc2698.cir < cir_max && <br />+            profile->trtcm_rfc2698.cbs < cbs_max && <br />+            profile->trtcm_rfc2698.cbs > 0 && <br />+            profile->trtcm_rfc2698.pir >= pir_min && <br />+            profile->trtcm_rfc2698.pir < pir_max && <br />+            profile->trtcm_rfc2698.cir < profile->trtcm_rfc2698.pir && <br />+            profile->trtcm_rfc2698.pbs > 0 && <br />+            profile->trtcm_rfc2698.pbs < pbs_max)<br />+            goto check_exist;<br />+        else<br />+            return -rte_mtr_error_set(error, ENOTSUP,<br />+                RTE_MTR_ERROR_TYPE_METER_PROFILE,<br />+                NULL,<br />+                "Invalid metering parameters");<br />+    } else {<br />+        return -rte_mtr_error_set(error, ENOTSUP,<br />+            RTE_MTR_ERROR_TYPE_METER_PROFILE,<br />+            NULL,<br />+            "algorithm not supported");<br />+    }<br />+<br />+check_exist:<br />+    return 0;<br />+}<br />+<br />+static struct zxdh_meter_profile<br />+*zxdh_mtr_profile_find_by_id(struct zxdh_mtr_profile_list *mpl,<br />+        uint32_t meter_profile_id, uint16_t dpdk_portid)<br />+{<br />+    struct zxdh_meter_profile *mp = NULL;<br />+<br />+    TAILQ_FOREACH(mp, mpl, next) {<br />+        if (meter_profile_id == mp->meter_profile_id && mp->dpdk_port_id == dpdk_portid)<br />+            return mp;<br />+    }<br />+    return NULL;<br />+}<br />+<br />+static struct zxdh_meter_profile<br />+*zxdh_mtr_profile_res_alloc(struct rte_mempool *mtr_profile_mp)<br />+{<br />+    struct zxdh_meter_profile *meter_profile = NULL;<br />+<br />+    if (ZXDH_MP_ALLOC_OBJ_FUNC(mtr_profile_mp, meter_profile) != 0)<br />+        return NULL;<br />+<br />+    return meter_profile;<br />+}<br />+<br />+static struct zxdh_meter_policy<br />+*zxdh_mtr_policy_res_alloc(struct rte_mempool *mtr_policy_mp)<br />+{<br />+    struct zxdh_meter_policy *policy = NULL;<br />+<br />+    rte_mempool_get(mtr_policy_mp, (void **)&policy);<br />+    PMD_DRV_LOG(INFO, "policy %p", policy);<br />+    return policy;<br />+}<br />+<br />+static int<br />+zxdh_hw_profile_free_direct(struct rte_eth_dev *dev, ZXDH_PROFILE_TYPE car_type,<br />+        uint16_t hw_profile_id, struct rte_mtr_error *error)<br />+{<br />+    struct zxdh_hw *hw = dev->data->dev_private;<br />+    uint16_t vport = hw->vport.vport;<br />+    int ret = zxdh_np_car_profile_id_delete(vport, car_type,<br />+            (uint64_t)hw_profile_id);<br />+    if (ret) {<br />+        PMD_DRV_LOG(ERR, "port %u free hw profile %u failed", vport, hw_profile_id);<br />+        return -rte_mtr_error_set(error, ENOTSUP, RTE_MTR_ERROR_TYPE_METER_PROFILE_ID, NULL,<br />+            "Meter free profile failed");<br />+    }<br />+<br />+    return 0;<br />+}<br />+<br />+int<br />+zxdh_hw_profile_alloc_direct(struct rte_eth_dev *dev, ZXDH_PROFILE_TYPE car_type,<br />+        uint64_t *hw_profile_id, struct rte_mtr_error *error)<br />+{<br />+    uint64_t profile_id = HW_PROFILE_MAX;<br />+    struct zxdh_hw *hw = dev->data->dev_private;<br />+    uint16_t vport = hw->vport.vport;<br />+    int ret = zxdh_np_car_profile_id_add(vport, car_type, &profile_id);<br />+<br />+    if (ret) {<br />+        PMD_DRV_LOG(ERR, "port %u alloc hw profile failed", vport);<br />+        return -rte_mtr_error_set(error, ENOTSUP, RTE_MTR_ERROR_TYPE_METER_PROFILE_ID, NULL,<br />+            "Meter offload alloc profile failed");<br />+    }<br />+    *hw_profile_id = profile_id;<br />+    if (*hw_profile_id == ZXDH_HW_PROFILE_MAX) {<br />+        return -rte_mtr_error_set(error, ENOTSUP, RTE_MTR_ERROR_TYPE_METER_PROFILE_ID, NULL,<br />+            "Meter offload alloc profile id invalid");<br />+    }<br />+<br />+    return 0;<br />+}<br />+<br />+static uint16_t<br />+zxdh_hw_profile_free(struct rte_eth_dev *dev, uint8_t car_type,<br />+        uint16_t hw_profile_id, struct rte_mtr_error *error)<br />+{<br />+    struct zxdh_hw *hw = dev->data->dev_private;<br />+    int ret = 0;<br />+<br />+    if (hw->is_pf) {<br />+        ret = zxdh_hw_profile_free_direct(dev, car_type, (uint64_t)hw_profile_id, error);<br />+    } else {<br />+        struct zxdh_msg_info msg_info = {0};<br />+        struct zxdh_msg_reply_info reply_info = {0};<br />+        struct zxdh_plcr_profile_free *zxdh_plcr_profile_free =<br />+            &msg_info.data.zxdh_plcr_profile_free;<br />+<br />+        zxdh_plcr_profile_free->profile_id = hw_profile_id;<br />+        zxdh_plcr_profile_free->car_type = car_type;<br />+        zxdh_msg_head_build(hw, ZXDH_PLCR_CAR_PROFILE_ID_DELETE, &msg_info);<br />+        ret = zxdh_vf_send_msg_to_pf(dev, &msg_info,<br />+            ZXDH_MSG_HEAD_LEN + sizeof(struct zxdh_plcr_profile_free),<br />+            &reply_info, sizeof(struct zxdh_msg_reply_info));<br />+<br />+        if (ret)<br />+            return -rte_mtr_error_set(error, ENOTSUP,<br />+                    RTE_MTR_ERROR_TYPE_METER_PROFILE_ID, NULL,<br />+                    "Meter free  profile failed ");<br />+    }<br />+<br />+    return ret;<br />+}<br />+<br />+static int<br />+zxdh_hw_profile_alloc(struct rte_eth_dev *dev, uint64_t *hw_profile_id,<br />+        struct rte_mtr_error *error)<br />+{<br />+    struct zxdh_hw *hw = dev->data->dev_private;<br />+    int ret = 0;<br />+<br />+    if (hw->is_pf) {<br />+        ret = zxdh_hw_profile_alloc_direct(dev, CAR_A, hw_profile_id, error);<br />+    } else {<br />+        struct zxdh_msg_info msg_info = {0};<br />+        struct zxdh_msg_reply_info reply_info = {0};<br />+        struct zxdh_plcr_profile_add  *zxdh_plcr_profile_add =<br />+            &msg_info.data.zxdh_plcr_profile_add;<br />+<br />+        zxdh_plcr_profile_add->car_type = CAR_A;<br />+        zxdh_msg_head_build(hw, ZXDH_PLCR_CAR_PROFILE_ID_ADD, &msg_info);<br />+        ret = zxdh_vf_send_msg_to_pf(dev, &msg_info,<br />+            ZXDH_MSG_HEAD_LEN + sizeof(struct zxdh_plcr_profile_add),<br />+            &reply_info, sizeof(struct zxdh_msg_reply_info));<br />+<br />+        if (ret) {<br />+            PMD_DRV_LOG(ERR,<br />+                "Failed to send msg: port 0x%x msg type ZXDH_PLCR_CAR_PROFILE_ID_ADD ",<br />+                hw->vport.vport);<br />+<br />+            return -rte_mtr_error_set(error, ENOTSUP,<br />+                    RTE_MTR_ERROR_TYPE_METER_PROFILE_ID, NULL,<br />+                    "Meter offload alloc profile  id msg failed ");<br />+        }<br />+        *hw_profile_id = reply_info.reply_body.mtr_profile_info.profile_id;<br />+        if (*hw_profile_id == ZXDH_HW_PROFILE_MAX) {<br />+            return -rte_mtr_error_set(error, ENOTSUP,<br />+                    RTE_MTR_ERROR_TYPE_METER_PROFILE_ID, NULL,<br />+                    "Meter offload alloc profile  id invalid  ");<br />+        }<br />+    }<br />+<br />+    return ret;<br />+}<br />+<br />+int<br />+zxdh_hw_profile_unref(struct rte_eth_dev *dev,<br />+    uint8_t car_type,<br />+    uint16_t hw_profile_id,<br />+    struct rte_mtr_error *error)<br />+{<br />+    if (hw_profile_id >= ZXDH_HW_PROFILE_MAX)<br />+        return -1;<br />+<br />+    rte_spinlock_lock(&g_mtr_res.hw_plcr_res_lock);<br />+    if (g_mtr_res.hw_profile_refcnt[hw_profile_id] == 0) {<br />+        PMD_DRV_LOG(ERR, "del hw profile id %d  but ref 0", hw_profile_id);<br />+        rte_spinlock_unlock(&g_mtr_res.hw_plcr_res_lock);<br />+        return -1;<br />+    }<br />+    if (--g_mtr_res.hw_profile_refcnt[hw_profile_id] == 0) {<br />+        PMD_DRV_LOG(INFO, "del hw profile id %d ", hw_profile_id);<br />+        zxdh_hw_profile_free(dev, car_type, hw_profile_id, error);<br />+    }<br />+    rte_spinlock_unlock(&g_mtr_res.hw_plcr_res_lock);<br />+    return 0;<br />+}<br />+<br />+static int<br />+zxdh_mtr_hw_counter_query(struct rte_eth_dev *dev,<br />+    bool clear,<br />+    bool dir,<br />+    struct zxdh_mtr_stats *mtr_stats,<br />+    struct rte_mtr_error *error)<br />+{<br />+    struct zxdh_hw *hw = dev->data->dev_private;<br />+    int ret = 0;<br />+<br />+    if (hw->is_pf) {<br />+        ret = zxdh_mtr_stats_get(dev, dir, mtr_stats);<br />+        if (ret) {<br />+            PMD_DRV_LOG(ERR,<br />+                "ZXDH_PORT_METER_STAT_GET port %u dir %d failed",<br />+                hw->vport.vport,<br />+                dir);<br />+<br />+            return -rte_mtr_error_set(error, ENOTSUP, RTE_MTR_ERROR_TYPE_STATS, NULL, "Failed to bind plcr flow.");<br />+        }<br />+    } else { /* send msg to pf */<br />+        struct zxdh_msg_info msg_info = {0};<br />+        struct zxdh_msg_reply_info reply_info = {0};<br />+        struct zxdh_mtr_stats_query *zxdh_mtr_stats_query =<br />+                &msg_info.data.zxdh_mtr_stats_query;<br />+<br />+        zxdh_mtr_stats_query->direction = dir;<br />+        zxdh_mtr_stats_query->is_clr = !!clear;<br />+        zxdh_msg_head_build(hw, ZXDH_PORT_METER_STAT_GET, &msg_info);<br />+        ret = zxdh_vf_send_msg_to_pf(dev,<br />+            &msg_info,<br />+            sizeof(msg_info),<br />+            &reply_info,<br />+            sizeof(struct zxdh_msg_reply_info));<br />+<br />+        if (ret) {<br />+            PMD_DRV_LOG(ERR,<br />+                "Failed to send msg: port 0x%x msg type ZXDH_PORT_METER_STAT_GET",<br />+                hw->vport.vport);<br />+            return -rte_mtr_error_set(error, ENOTSUP, RTE_MTR_ERROR_TYPE_STATS, NULL, "Meter offload alloc profile failed");<br />+        }<br />+        struct zxdh_mtr_stats *hw_mtr_stats = &reply_info.reply_body.hw_mtr_stats;<br />+<br />+        mtr_stats->n_bytes_dropped = hw_mtr_stats->n_bytes_dropped;<br />+        mtr_stats->n_pkts_dropped = hw_mtr_stats->n_pkts_dropped;<br />+    }<br />+<br />+    return ret;<br />+}<br />+<br />+<br />+static void<br />+zxdh_mtr_profile_res_free(struct rte_eth_dev *dev,<br />+        struct rte_mempool *mtr_profile_mp,<br />+        struct zxdh_meter_profile *meter_profile,<br />+        struct rte_mtr_error *error)<br />+{<br />+    if (meter_profile->ref_cnt == 0) {<br />+        ZXDH_MP_FREE_OBJ_FUNC(mtr_profile_mp, meter_profile);<br />+        return;<br />+    }<br />+    if (meter_profile->ref_cnt == 1) {<br />+        meter_profile->ref_cnt--;<br />+        zxdh_hw_profile_unref(dev, CAR_A, meter_profile->hw_profile_id, error);<br />+<br />+        TAILQ_REMOVE(&zxdh_shared_data->meter_profile_list, meter_profile, next);<br />+        ZXDH_MP_FREE_OBJ_FUNC(mtr_profile_mp, meter_profile);<br />+    } else {<br />+        PMD_DRV_LOG(INFO,<br />+            "profile %d ref %d is busy",<br />+            meter_profile->meter_profile_id,<br />+            meter_profile->ref_cnt);<br />+    }<br />+}<br />+<br />+static uint16_t<br />+zxdh_check_hw_profile_exist(struct zxdh_mtr_profile_list *mpl,<br />+    struct rte_mtr_meter_profile *profile,<br />+    uint16_t hw_profile_owner_vport)<br />+{<br />+    struct zxdh_meter_profile *mp;<br />+<br />+    TAILQ_FOREACH(mp, mpl, next) {<br />+        if ((memcmp(profile, &mp->profile, sizeof(struct rte_mtr_meter_profile)) == 0) && <br />+            hw_profile_owner_vport == mp->hw_profile_owner_vport) {<br />+            return mp->hw_profile_id;<br />+        }<br />+    }<br />+    return ZXDH_HW_PROFILE_MAX;<br />+}<br />+<br />+static void<br />+zxdh_plcr_param_build(struct rte_mtr_meter_profile *profile,<br />+        void *plcr_param, uint16_t profile_id)<br />+{<br />+    if (profile->packet_mode == 0) {<br />+        ZXDH_STAT_CAR_PROFILE_CFG_T *p_car_byte_profile_cfg =<br />+            (ZXDH_STAT_CAR_PROFILE_CFG_T *)plcr_param;<br />+<br />+        p_car_byte_profile_cfg->profile_id = profile_id;<br />+        p_car_byte_profile_cfg->pkt_sign = profile->packet_mode;<br />+        p_car_byte_profile_cfg->cf = ZXDH_PLCR_CF_UNOVERFLOW;<br />+        p_car_byte_profile_cfg->cm = ZXDH_PLCR_CM_BLIND;<br />+        if (profile->alg == RTE_MTR_SRTCM_RFC2697) {<br />+            p_car_byte_profile_cfg->cd  = ZXDH_PLCR_CD_SRTCM;<br />+            p_car_byte_profile_cfg->cir = profile->srtcm_rfc2697.cir * 8 / 1000;<br />+            p_car_byte_profile_cfg->cbs = profile->srtcm_rfc2697.cbs;<br />+            p_car_byte_profile_cfg->ebs = profile->srtcm_rfc2697.ebs;<br />+        } else {<br />+            p_car_byte_profile_cfg->cd  = ZXDH_PLCR_CD_TRTCM;<br />+            p_car_byte_profile_cfg->cir = profile->trtcm_rfc2698.cir * 8 / 1000;<br />+            p_car_byte_profile_cfg->cbs = profile->trtcm_rfc2698.cbs;<br />+            p_car_byte_profile_cfg->eir = (profile->trtcm_rfc2698.pir -<br />+                profile->trtcm_rfc2698.cir) * 8 / 1000;<br />+            p_car_byte_profile_cfg->ebs =<br />+                profile->trtcm_rfc2698.pbs - profile->trtcm_rfc2698.cbs;<br />+        }<br />+    } else {<br />+        ZXDH_STAT_CAR_PKT_PROFILE_CFG_T *p_car_pkt_profile_cfg =<br />+            (ZXDH_STAT_CAR_PKT_PROFILE_CFG_T *)plcr_param;<br />+<br />+        p_car_pkt_profile_cfg->profile_id = profile_id;<br />+        p_car_pkt_profile_cfg->pkt_sign = profile->packet_mode;<br />+<br />+        if (profile->alg == RTE_MTR_SRTCM_RFC2697) {<br />+            p_car_pkt_profile_cfg->cir = profile->srtcm_rfc2697.cir;<br />+            p_car_pkt_profile_cfg->cbs = profile->srtcm_rfc2697.cbs;<br />+        } else {<br />+            p_car_pkt_profile_cfg->cir = profile->trtcm_rfc2698.cir;<br />+            p_car_pkt_profile_cfg->cbs = profile->trtcm_rfc2698.cbs;<br />+        }<br />+    }<br />+}<br />+<br />+static int<br />+zxdh_hw_profile_config_direct(struct rte_eth_dev *dev __rte_unused,<br />+    ZXDH_PROFILE_TYPE car_type,<br />+    uint16_t hw_profile_id,<br />+    struct zxdh_meter_profile *mp,<br />+    struct rte_mtr_error *error)<br />+{<br />+    int ret = zxdh_np_car_profile_cfg_set(mp->hw_profile_owner_vport,<br />+        car_type, mp->profile.packet_mode,<br />+        (uint32_t)hw_profile_id, &mp->plcr_param);<br />+    if (ret) {<br />+        PMD_DRV_LOG(ERR, " config hw profile %u failed", hw_profile_id);<br />+        return -rte_mtr_error_set(error, ENOTSUP, RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,<br />+            "Meter offload cfg profile failed");<br />+    }<br />+<br />+    return 0;<br />+}<br />+<br />+static int zxdh_hw_profile_config(struct rte_eth_dev *dev, uint16_t hw_profile_id,<br />+    struct zxdh_meter_profile *mp, struct rte_mtr_error *error)<br />+{<br />+    struct zxdh_hw *hw = dev->data->dev_private;<br />+    int ret = 0;<br />+<br />+    if (hw->is_pf) {<br />+        ret = zxdh_hw_profile_config_direct(dev, CAR_A, hw_profile_id, mp, error);<br />+    } else {<br />+        struct zxdh_msg_info msg_info = {0};<br />+        struct zxdh_msg_reply_info reply_info = {0};<br />+        struct zxdh_plcr_profile_cfg *zxdh_plcr_profile_cfg =<br />+            &msg_info.data.zxdh_plcr_profile_cfg;<br />+<br />+        zxdh_plcr_profile_cfg->car_type = CAR_A;<br />+        zxdh_plcr_profile_cfg->packet_mode = mp->profile.packet_mode;<br />+        zxdh_plcr_profile_cfg->hw_profile_id = hw_profile_id;<br />+        rte_memcpy(&zxdh_plcr_profile_cfg->plcr_param,<br />+            &mp->plcr_param,<br />+            sizeof(zxdh_plcr_profile_cfg->plcr_param));<br />+<br />+        zxdh_msg_head_build(hw, ZXDH_PLCR_CAR_PROFILE_CFG_SET, &msg_info);<br />+        ret = zxdh_vf_send_msg_to_pf(dev,<br />+            &msg_info,<br />+            ZXDH_MSG_HEAD_LEN + sizeof(struct zxdh_plcr_profile_cfg),<br />+            &reply_info,<br />+            sizeof(struct zxdh_msg_reply_info));<br />+<br />+        if (ret) {<br />+            PMD_DRV_LOG(ERR,<br />+                "Failed msg: port 0x%x msg type ZXDH_PLCR_CAR_PROFILE_CFG_SET ",<br />+                hw->vport.vport);<br />+<br />+            return -rte_mtr_error_set(error, ENOTSUP,<br />+                    RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,<br />+                    "Meter offload cfg profile failed ");<br />+        }<br />+    }<br />+<br />+    return ret;<br />+}<br />+<br />+static int<br />+zxdh_mtr_profile_offload(struct rte_eth_dev *dev, struct zxdh_meter_profile *mp,<br />+        struct rte_mtr_meter_profile *profile, struct rte_mtr_error *error)<br />+{<br />+    struct zxdh_hw *hw = dev->data->dev_private;<br />+    uint16_t hw_profile_owner_vport = ZXDH_GET_OWNER_PF_VPORT(hw->vport.vport);<br />+<br />+    mp->hw_profile_owner_vport = hw_profile_owner_vport;<br />+    uint64_t hw_profile_id =<br />+        zxdh_check_hw_profile_exist(&zxdh_shared_data->meter_profile_list,<br />+            profile,<br />+            hw_profile_owner_vport);<br />+<br />+    if (hw_profile_id == ZXDH_HW_PROFILE_MAX) {<br />+        uint32_t ret = zxdh_hw_profile_alloc(dev, &hw_profile_id, error);<br />+<br />+        if (ret) {<br />+            PMD_DRV_LOG(ERR, "hw_profile alloc fail");<br />+            return ret;<br />+        }<br />+<br />+        zxdh_plcr_param_build(profile, &mp->plcr_param, hw_profile_id);<br />+        ret = zxdh_hw_profile_config(dev, hw_profile_id, mp, error);<br />+        if (ret) {<br />+            PMD_DRV_LOG(ERR, "zxdh_hw_profile_config fail");<br />+            hw_profile_id = ZXDH_HW_PROFILE_MAX;<br />+            return ret;<br />+        }<br />+    }<br />+    zxdh_hw_profile_ref(hw_profile_id);<br />+    mp->hw_profile_id = hw_profile_id;<br />+<br />+    return 0;<br />+}<br />+<br />+static int<br />+zxdh_meter_profile_add(struct rte_eth_dev *dev,<br />+                uint32_t meter_profile_id,<br />+                struct rte_mtr_meter_profile *profile,<br />+                struct rte_mtr_error *error)<br />+{<br />+    struct zxdh_meter_profile *mp;<br />+    int ret;<br />+<br />+    ret = zxdh_mtr_profile_validate(meter_profile_id, profile, error);<br />+    if (ret)<br />+        return -rte_mtr_error_set(error, ENOMEM,<br />+                    RTE_MTR_ERROR_TYPE_METER_PROFILE,<br />+                    NULL, "meter profile validate failed");<br />+    mp = zxdh_mtr_profile_find_by_id(&zxdh_shared_data->meter_profile_list,<br />+        meter_profile_id,<br />+        dev->data->port_id);<br />+<br />+    if (mp)<br />+        return -rte_mtr_error_set(error, EEXIST,<br />+                      RTE_MTR_ERROR_TYPE_METER_PROFILE,<br />+                      NULL,<br />+                      "meter profile is exists");<br />+<br />+    mp = zxdh_mtr_profile_res_alloc(zxdh_shared_data->mtr_profile_mp);<br />+    if (mp == NULL)<br />+        return -rte_mtr_error_set(error, ENOMEM,<br />+                    RTE_MTR_ERROR_TYPE_METER_PROFILE,<br />+                    NULL, "Meter profile res memory alloc failed.");<br />+<br />+    memset(mp, 0, sizeof(struct zxdh_meter_profile));<br />+<br />+    mp->meter_profile_id = meter_profile_id;<br />+    mp->dpdk_port_id = dev->data->port_id;<br />+    mp->hw_profile_id = UINT16_MAX;<br />+    rte_memcpy(&mp->profile, profile, sizeof(struct rte_mtr_meter_profile));<br />+<br />+    ret = zxdh_mtr_profile_offload(dev, mp, profile, error);<br />+    if (ret) {<br />+        PMD_DRV_LOG(ERR,<br />+            " port %d profile id  %d offload failed  ",<br />+            dev->data->port_id,<br />+            meter_profile_id);<br />+        goto error;<br />+    }<br />+<br />+    TAILQ_INSERT_TAIL(&zxdh_shared_data->meter_profile_list, mp, next);<br />+    PMD_DRV_LOG(DEBUG,<br />+        "add profile id %d mp %p  mp->ref_cnt %d",<br />+        meter_profile_id,<br />+        mp,<br />+        mp->ref_cnt);<br />+<br />+    mp->ref_cnt++;<br />+<br />+    return 0;<br />+error:<br />+    zxdh_mtr_profile_res_free(dev, zxdh_shared_data->mtr_profile_mp, mp, error);<br />+    return ret;<br />+}<br />+<br />+static int<br />+zxdh_meter_profile_delete(struct rte_eth_dev *dev,<br />+                uint32_t meter_profile_id,<br />+                struct rte_mtr_error *error)<br />+{<br />+    struct zxdh_meter_profile *mp;<br />+<br />+    mp = zxdh_mtr_profile_find_by_id(&zxdh_shared_data->meter_profile_list,<br />+        meter_profile_id,<br />+        dev->data->port_id);<br />+<br />+    if (mp == NULL) {<br />+        PMD_DRV_LOG(ERR, "del profile id %d  unfind ", meter_profile_id);<br />+        return -rte_mtr_error_set(error, ENOENT,<br />+                        RTE_MTR_ERROR_TYPE_METER_PROFILE,<br />+                        &meter_profile_id,<br />+                         "Meter profile id is not exists.");<br />+    }<br />+    zxdh_mtr_profile_res_free(dev, zxdh_shared_data->mtr_profile_mp, mp, error);<br />+<br />+    return 0;<br />+}<br />+<br />+static int<br />+zxdh_meter_policy_add(struct rte_eth_dev *dev,<br />+        uint32_t policy_id,<br />+        struct rte_mtr_meter_policy_params *policy,<br />+        struct rte_mtr_error *error)<br />+{<br />+    int ret = 0;<br />+    struct zxdh_meter_policy *mtr_policy = NULL;<br />+<br />+    if (policy_id >= ZXDH_MAX_POLICY_NUM)<br />+        return -rte_mtr_error_set(error, ENOTSUP,<br />+                    RTE_MTR_ERROR_TYPE_METER_POLICY_ID,<br />+                    NULL, "policy ID is invalid. ");<br />+    mtr_policy = zxdh_mtr_policy_find_by_id(&zxdh_shared_data->mtr_policy_list,<br />+                policy_id,<br />+                dev->data->port_id);<br />+<br />+    if (mtr_policy)<br />+        return -rte_mtr_error_set(error, EEXIST,<br />+                    RTE_MTR_ERROR_TYPE_METER_POLICY_ID,<br />+                    NULL, "policy ID  exists. ");<br />+    ret = zxdh_policy_validate_actions(policy->actions, error);<br />+    if (ret) {<br />+        return -rte_mtr_error_set(error, ENOTSUP,<br />+                RTE_MTR_ERROR_TYPE_METER_POLICY,<br />+                NULL, "  only supports def action.");<br />+    }<br />+<br />+    mtr_policy = zxdh_mtr_policy_res_alloc(zxdh_shared_data->mtr_policy_mp);<br />+    if (mtr_policy == NULL) {<br />+        return -rte_mtr_error_set(error, ENOMEM,<br />+                    RTE_MTR_ERROR_TYPE_METER_POLICY_ID,<br />+                    NULL, "Meter policy res memory alloc  failed.");<br />+    }<br />+    /* Fill profile info. */<br />+    memset(mtr_policy, 0, sizeof(struct zxdh_meter_policy));<br />+    mtr_policy->policy_id = policy_id;<br />+    mtr_policy->dpdk_port_id = dev->data->port_id;<br />+    rte_memcpy(&mtr_policy->policy, policy, sizeof(struct rte_mtr_meter_policy_params));<br />+    /* Add to list. */<br />+    TAILQ_INSERT_TAIL(&zxdh_shared_data->mtr_policy_list, mtr_policy, next);<br />+    mtr_policy->ref_cnt++;<br />+    PMD_DRV_LOG(INFO, "allic policy id %d ok %p ", mtr_policy->policy_id, mtr_policy);<br />+    return 0;<br />+}<br />+<br />+static int<br />+zxdh_meter_policy_delete(struct rte_eth_dev *dev,<br />+    uint32_t policy_id,<br />+    struct rte_mtr_error *error)<br />+{<br />+    struct zxdh_meter_policy *mtr_policy = NULL;<br />+<br />+    if (policy_id >= ZXDH_MAX_POLICY_NUM)<br />+        return -rte_mtr_error_set(error, ENOTSUP,<br />+                    RTE_MTR_ERROR_TYPE_METER_POLICY_ID,<br />+                    NULL, "policy ID is invalid. ");<br />+    mtr_policy = zxdh_mtr_policy_find_by_id(&zxdh_shared_data->mtr_policy_list,<br />+        policy_id, dev->data->port_id);<br />+<br />+    if (mtr_policy && mtr_policy->ref_cnt == 1) {<br />+        TAILQ_REMOVE(&zxdh_shared_data->mtr_policy_list, mtr_policy, next);<br />+        MP_FREE_OBJ_FUNC(zxdh_shared_data->mtr_policy_mp, mtr_policy);<br />+    } else {<br />+        if (mtr_policy) {<br />+            PMD_DRV_LOG(INFO,<br />+                " policy id %d ref %d is busy ",<br />+                mtr_policy->policy_id,<br />+                mtr_policy->ref_cnt);<br />+        } else {<br />+            PMD_DRV_LOG(ERR, " policy id %d  is not exist ", policy_id);<br />+            return -rte_mtr_error_set(error, ENOTSUP,<br />+                    RTE_MTR_ERROR_TYPE_METER_POLICY_ID,<br />+                    NULL, "policy ID is  not exist. ");<br />+        }<br />+    }<br />+    return 0;<br />+}<br />+<br />+static int<br />+zxdh_meter_validate(uint32_t meter_id,<br />+            struct rte_mtr_params *params,<br />+            struct rte_mtr_error *error)<br />+{<br />+    /* Meter params must not be NULL. */<br />+    if (params == NULL)<br />+        return -rte_mtr_error_set(error, EINVAL,<br />+                    RTE_MTR_ERROR_TYPE_MTR_PARAMS,<br />+                    NULL, "Meter object params null.");<br />+    /* Previous meter color is not supported. */<br />+    if (params->use_prev_mtr_color)<br />+        return -rte_mtr_error_set(error, EINVAL,<br />+                    RTE_MTR_ERROR_TYPE_MTR_PARAMS,<br />+                    NULL,<br />+                    "Previous meter color not supported");<br />+    if (meter_id > ZXDH_MAX_MTR_NUM / 2) {<br />+        return -rte_mtr_error_set(error, EINVAL,<br />+                RTE_MTR_ERROR_TYPE_MTR_PARAMS,<br />+                NULL,<br />+                " meter id exceed 1024 unsupported");<br />+    }<br />+    return 0;<br />+}<br />+<br />+static int<br />+zxdh_check_port_mtr_bind(struct rte_eth_dev *dev, uint32_t dir)<br />+{<br />+    struct zxdh_mtr_object *mtr_obj = NULL;<br />+<br />+    TAILQ_FOREACH(mtr_obj, &zxdh_shared_data->mtr_list, next) {<br />+        if (mtr_obj->direction != dir)<br />+            continue;<br />+        if (mtr_obj->port_id == dev->data->port_id) {<br />+            PMD_DRV_LOG(INFO,<br />+                "port %d dir %d already bind meter %d",<br />+                dev->data->port_id,<br />+                dir,<br />+                mtr_obj->meter_id);<br />+            return -1;<br />+        }<br />+    }<br />+<br />+    return 0;<br />+}<br />+<br />+static struct zxdh_mtr_object<br />+*zxdh_mtr_obj_alloc(struct rte_mempool *mtr_mp)<br />+{<br />+    struct zxdh_mtr_object *mtr_obj = NULL;<br />+<br />+    if (ZXDH_MP_ALLOC_OBJ_FUNC(mtr_mp, mtr_obj) != 0)<br />+        return NULL;<br />+<br />+    return mtr_obj;<br />+}<br />+<br />+static uint32_t dir_to_mtr_mode[] = {<br />+    ZXDH_PORT_EGRESS_METER_EN_OFF_FLAG,<br />+    ZXDH_PORT_INGRESS_METER_EN_OFF_FLAG<br />+};<br />+<br />+static int<br />+zxdh_set_mtr_enable(struct rte_eth_dev *dev, uint8_t dir, bool enable, struct rte_mtr_error *error)<br />+{<br />+    struct zxdh_hw *priv = dev->data->dev_private;<br />+    struct zxdh_port_attr_table port_attr = {0};<br />+    int ret = 0;<br />+<br />+    if (priv->is_pf) {<br />+        ret = zxdh_get_port_attr(priv, priv->vport.vport, &port_attr);<br />+        port_attr.ingress_meter_enable = enable;<br />+        ret = zxdh_set_port_attr(priv, priv->vport.vport, &port_attr);<br />+        if (ret) {<br />+            PMD_DRV_LOG(ERR, "%s set port attr failed", __func__);<br />+            return -ret;<br />+        }<br />+    } else {<br />+        struct zxdh_msg_info msg_info = {0};<br />+        struct zxdh_port_attr_set_msg *attr_msg = &msg_info.data.port_attr_msg;<br />+<br />+        attr_msg->mode  = dir_to_mtr_mode[dir];<br />+        attr_msg->value = enable;<br />+        zxdh_msg_head_build(priv, ZXDH_PORT_ATTRS_SET, &msg_info);<br />+        ret = zxdh_vf_send_msg_to_pf(dev, &msg_info,<br />+            sizeof(struct zxdh_msg_head) + sizeof(struct zxdh_port_attr_set_msg),<br />+            NULL, 0);<br />+    }<br />+    if (ret) {<br />+        PMD_DRV_LOG(ERR, " port %d  mtr enable failed", priv->port_id);<br />+        return -rte_mtr_error_set(error, EEXIST,<br />+                    RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL,<br />+                    "Meter  enable failed.");<br />+    }<br />+    if (dir == ZXDH_INGRESS)<br />+        priv->i_mtr_en = !!enable;<br />+    else<br />+        priv->e_mtr_en = !!enable;<br />+<br />+    return ret;<br />+}<br />+<br />+static void<br />+zxdh_meter_build_actions(struct zxdh_meter_action *mtr_action,<br />+        struct rte_mtr_params *params)<br />+{<br />+    mtr_action->stats_mask = params->stats_mask;<br />+    mtr_action->action[RTE_COLOR_RED] = ZXDH_MTR_POLICER_ACTION_DROP;<br />+}<br />+<br />+static int<br />+zxdh_hw_plcrflow_config(struct rte_eth_dev *dev, uint16_t hw_flow_id,<br />+        struct zxdh_mtr_object *mtr, struct rte_mtr_error *error)<br />+{<br />+    struct zxdh_hw *hw = dev->data->dev_private;<br />+    int ret = 0;<br />+<br />+    if (hw->is_pf) {<br />+        uint64_t hw_profile_id = (uint64_t)mtr->profile->hw_profile_id;<br />+<br />+        ret = zxdh_np_stat_car_queue_cfg_set(hw->dev_id, CAR_A,<br />+            hw_flow_id, 1, mtr->enable, hw_profile_id);<br />+<br />+        if (ret) {<br />+            PMD_DRV_LOG(ERR, "dpp_stat_car_queue_cfg_set failed flowid %d  profile id %d",<br />+                            hw_flow_id, mtr->profile->hw_profile_id);<br />+            return -rte_mtr_error_set(error, ENOTSUP,<br />+                    RTE_MTR_ERROR_TYPE_MTR_PARAMS,<br />+                    NULL, "Failed to  bind  plcr flow.");<br />+            ;<br />+        }<br />+    } else {<br />+        struct zxdh_msg_info msg_info = {0};<br />+        struct zxdh_msg_reply_info reply_info = {0};<br />+        struct zxdh_plcr_flow_cfg *zxdh_plcr_flow_cfg = &msg_info.data.zxdh_plcr_flow_cfg;<br />+<br />+        zxdh_plcr_flow_cfg->car_type = CAR_A;<br />+        zxdh_plcr_flow_cfg->flow_id = hw_flow_id;<br />+        zxdh_plcr_flow_cfg->drop_flag = 1;<br />+        zxdh_plcr_flow_cfg->plcr_en = mtr->enable;<br />+        zxdh_plcr_flow_cfg->profile_id = mtr->profile->hw_profile_id;<br />+        zxdh_msg_head_build(hw, ZXDH_PLCR_CAR_QUEUE_CFG_SET, &msg_info);<br />+        ret = zxdh_vf_send_msg_to_pf(dev, &msg_info,<br />+            ZXDH_MSG_HEAD_LEN + sizeof(struct zxdh_plcr_flow_cfg),<br />+            &reply_info,<br />+            sizeof(struct zxdh_msg_reply_info));<br />+        if (ret) {<br />+            PMD_DRV_LOG(ERR,<br />+                "Failed msg: port 0x%x msg type ZXDH_PLCR_CAR_QUEUE_CFG_SET ",<br />+                hw->vport.vport);<br />+            return -rte_mtr_error_set(error, ENOTSUP,<br />+                    RTE_MTR_ERROR_TYPE_MTR_PARAMS,<br />+                    NULL, "Failed to  bind  plcr flow.");<br />+        }<br />+    }<br />+<br />+    return ret;<br />+}<br />+<br />+static void<br />+zxdh_mtr_obj_free(struct rte_eth_dev *dev, struct zxdh_mtr_object *mtr_obj)<br />+{<br />+    struct zxdh_mtr_list *mtr_list = &zxdh_shared_data->mtr_list;<br />+    struct rte_mempool *mtr_mp = zxdh_shared_data->mtr_mp;<br />+<br />+    PMD_DRV_LOG(INFO, "free port %d dir %d meter %d  mtr refcnt:%d ....",<br />+        dev->data->port_id, mtr_obj->direction, mtr_obj->meter_id, mtr_obj->mtr_ref_cnt);<br />+<br />+    if (mtr_obj->policy)<br />+        mtr_obj->policy->ref_cnt--;<br />+<br />+    if (mtr_obj->profile)<br />+        mtr_obj->profile->ref_cnt--;<br />+<br />+    PMD_DRV_LOG(INFO,<br />+        "free port %d dir %d meter %d  profile refcnt:%d ",<br />+        dev->data->port_id,<br />+        mtr_obj->direction,<br />+        mtr_obj->meter_id,<br />+        mtr_obj->profile ? mtr_obj->profile->ref_cnt : 0);<br />+<br />+    if (--mtr_obj->mtr_ref_cnt == 0) {<br />+        PMD_DRV_LOG(INFO, "rm  mtr %p refcnt:%d ....", mtr_obj, mtr_obj->mtr_ref_cnt);<br />+        TAILQ_REMOVE(mtr_list, mtr_obj, next);<br />+        MP_FREE_OBJ_FUNC(mtr_mp, mtr_obj);<br />+    }<br />+}<br />+<br />+static int<br />+zxdh_mtr_flow_offlad(struct rte_eth_dev *dev,<br />+    struct zxdh_mtr_object *mtr,<br />+    struct rte_mtr_error *error)<br />+{<br />+    uint16_t hw_flow_id;<br />+<br />+    hw_flow_id = mtr->vfid * 2 + ZXDH_PORT_MTR_FID_BASE + mtr->direction;<br />+    return zxdh_hw_plcrflow_config(dev, hw_flow_id, mtr, error);<br />+}<br />+<br />+static struct zxdh_mtr_object *<br />+zxdh_mtr_find(uint32_t meter_id, uint16_t dpdk_portid)<br />+{<br />+    struct zxdh_mtr_list *mtr_list = &zxdh_shared_data->mtr_list;<br />+    struct zxdh_mtr_object *mtr = NULL;<br />+<br />+    TAILQ_FOREACH(mtr, mtr_list, next) {<br />+        PMD_DRV_LOG(INFO,<br />+            "mtrlist head %p  mtr %p mtr->meterid %d to find mtrid %d",<br />+            TAILQ_FIRST(mtr_list),<br />+            mtr,<br />+            mtr->meter_id,<br />+            meter_id<br />+        );<br />+<br />+        if (meter_id == mtr->meter_id && dpdk_portid == mtr->port_id)<br />+            return mtr;<br />+    }<br />+    return NULL;<br />+}<br />+<br />+static int<br />+zxdh_meter_create(struct rte_eth_dev *dev, uint32_t meter_id,<br />+                struct rte_mtr_params *params, int shared,<br />+                struct rte_mtr_error *error)<br />+{<br />+    struct zxdh_hw *priv = dev->data->dev_private;<br />+    struct zxdh_mtr_list *mtr_list = &zxdh_shared_data->mtr_list;<br />+    struct zxdh_mtr_object *mtr;<br />+    struct zxdh_meter_profile *mtr_profile;<br />+    struct zxdh_meter_policy *mtr_policy;<br />+    uint8_t dir = 0;<br />+    int ret;<br />+<br />+    if (shared)<br />+        return -rte_mtr_error_set(error, ENOTSUP,<br />+                    RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL,<br />+                    "Meter share is not supported");<br />+<br />+    ret = zxdh_meter_validate(meter_id, params, error);<br />+    if (ret)<br />+        return ret;<br />+<br />+    if (zxdh_check_port_mtr_bind(dev, dir))<br />+        return -rte_mtr_error_set(error, EEXIST,<br />+                RTE_MTR_ERROR_TYPE_MTR_ID, NULL,<br />+                "Meter object already bind to dev.");<br />+<br />+    mtr_profile = zxdh_mtr_profile_find_by_id(&zxdh_shared_data->meter_profile_list,<br />+            params->meter_profile_id,<br />+            dev->data->port_id<br />+    );<br />+<br />+    if (mtr_profile == NULL)<br />+        return -rte_mtr_error_set(error, EEXIST,<br />+                    RTE_MTR_ERROR_TYPE_METER_PROFILE, &params->meter_profile_id,<br />+                    "Meter profile object is not exists.");<br />+    mtr_profile->ref_cnt++;<br />+    mtr_policy = zxdh_mtr_policy_find_by_id(&zxdh_shared_data->mtr_policy_list,<br />+            params->meter_policy_id,<br />+            dev->data->port_id);<br />+<br />+    if (mtr_policy == NULL) {<br />+        ret = -rte_mtr_error_set(error, EEXIST,<br />+                    RTE_MTR_ERROR_TYPE_METER_PROFILE, &params->meter_policy_id,<br />+                    "Meter policy object is not exists.");<br />+        mtr_profile->ref_cnt--;<br />+        return ret;<br />+    }<br />+    mtr_policy->ref_cnt++;<br />+<br />+    mtr = zxdh_mtr_obj_alloc(zxdh_shared_data->mtr_mp);<br />+    if (mtr == NULL) {<br />+        ret = -rte_mtr_error_set(error, ENOMEM,<br />+                    RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL,<br />+                    "Memory alloc failed for meter.");<br />+        mtr_policy->ref_cnt--;<br />+        mtr_profile->ref_cnt--;<br />+        return ret;<br />+    }<br />+    memset(mtr, 0, sizeof(struct zxdh_mtr_object));<br />+<br />+    mtr->meter_id = meter_id;<br />+    mtr->profile = mtr_profile;<br />+<br />+    zxdh_meter_build_actions(&mtr->mtr_action, params);<br />+    TAILQ_INSERT_TAIL(mtr_list, mtr, next);<br />+    mtr->enable = !!params->meter_enable;<br />+    mtr->shared = !!shared;<br />+    mtr->mtr_ref_cnt++;<br />+    mtr->vfid = priv->vfid;<br />+    mtr->port_id = dev->data->port_id;<br />+    mtr->policy = mtr_policy;<br />+    mtr->direction = !!dir;<br />+    if (params->meter_enable) {<br />+        ret = zxdh_mtr_flow_offlad(dev, mtr, error);<br />+        if (ret)<br />+            goto error;<br />+    }<br />+    ret = zxdh_set_mtr_enable(dev, mtr->direction, 1, error);<br />+    if (ret)<br />+        goto error;<br />+    return ret;<br />+error:<br />+    zxdh_mtr_obj_free(dev, mtr);<br />+    return ret;<br />+}<br />+<br />+static int<br />+zxdh_meter_destroy(struct rte_eth_dev *dev, uint32_t meter_id,<br />+            struct rte_mtr_error *error)<br />+{<br />+    struct zxdh_mtr_object *mtr;<br />+<br />+    mtr = zxdh_mtr_find(meter_id, dev->data->port_id);<br />+    if (mtr == NULL)<br />+        return -rte_mtr_error_set(error, EEXIST,<br />+                      RTE_MTR_ERROR_TYPE_MTR_ID,<br />+                      NULL, "Meter object id not valid.");<br />+    mtr->enable = 0;<br />+    zxdh_set_mtr_enable(dev, mtr->direction, 0, error);<br />+<br />+    if (zxdh_mtr_flow_offlad(dev, mtr, error))<br />+        return -1;<br />+<br />+    zxdh_mtr_obj_free(dev, mtr);<br />+    return 0;<br />+}<br />+<br />+void<br />+zxdh_mtr_policy_res_free(struct rte_mempool *mtr_policy_mp, struct zxdh_meter_policy *policy)<br />+{<br />+    PMD_DRV_LOG(INFO, "to free policy %d  ref  %d  ", policy->policy_id,  policy->ref_cnt);<br />+<br />+    if (--policy->ref_cnt == 0) {<br />+        TAILQ_REMOVE(&zxdh_shared_data->mtr_policy_list, policy, next);<br />+        MP_FREE_OBJ_FUNC(mtr_policy_mp, policy);<br />+    }<br />+}<br />+<br />+static int<br />+zxdh_mtr_stats_read(struct rte_eth_dev *dev,<br />+                                uint32_t mtr_id,<br />+                                struct rte_mtr_stats *stats,<br />+                                uint64_t *stats_mask,<br />+                                int clear,<br />+                                struct rte_mtr_error *error)<br />+{<br />+    struct zxdh_mtr_stats mtr_stat = {0};<br />+    struct zxdh_mtr_object *mtr = NULL;<br />+    int ret = 0;<br />+    /* Meter object must exist. */<br />+    mtr = zxdh_mtr_find(mtr_id, dev->data->port_id);<br />+    if (mtr == NULL)<br />+        return -rte_mtr_error_set(error, ENOENT,<br />+                    RTE_MTR_ERROR_TYPE_MTR_ID,<br />+                    NULL, "Meter object id not valid.");<br />+    *stats_mask = RTE_MTR_STATS_N_BYTES_DROPPED | RTE_MTR_STATS_N_PKTS_DROPPED;<br />+    memset(&mtr_stat, 0, sizeof(mtr_stat));<br />+    ret = zxdh_mtr_hw_counter_query(dev, clear, mtr->direction, &mtr_stat, error);<br />+    if (ret)<br />+        goto error;<br />+    stats->n_bytes_dropped = mtr_stat.n_bytes_dropped;<br />+    stats->n_pkts_dropped = mtr_stat.n_pkts_dropped;<br />+<br />+    return 0;<br />+error:<br />+    return -rte_mtr_error_set(error, ret, RTE_MTR_ERROR_TYPE_STATS, NULL,<br />+                "Failed to read meter drop counters.");<br />+}<br />+<br />+static const struct rte_mtr_ops zxdh_mtr_ops = {<br />+    .capabilities_get = zxdh_meter_cap_get,<br />+    .meter_profile_add = zxdh_meter_profile_add,<br />+    .meter_profile_delete = zxdh_meter_profile_delete,<br />+    .create = zxdh_meter_create,<br />+    .destroy = zxdh_meter_destroy,<br />+    .stats_read = zxdh_mtr_stats_read,<br />+    .meter_policy_add = zxdh_meter_policy_add,<br />+    .meter_policy_delete = zxdh_meter_policy_delete,<br />+};<br />+<br />+int<br />+zxdh_meter_ops_get(struct rte_eth_dev *dev __rte_unused, void *arg)<br />+{<br />+    *(const struct rte_mtr_ops **)arg = &zxdh_mtr_ops;<br />+    return 0;<br />+}<br />+<br />+void<br />+zxdh_mtr_release(struct rte_eth_dev *dev)<br />+{<br />+    struct zxdh_hw *priv = dev->data->dev_private;<br />+    struct zxdh_meter_profile *profile;<br />+    struct rte_mtr_error error = {0};<br />+    struct zxdh_mtr_object *mtr_obj;<br />+<br />+    RTE_TAILQ_FOREACH(mtr_obj, &zxdh_shared_data->mtr_list, next) {<br />+        if (mtr_obj->port_id == priv->port_id)<br />+            zxdh_mtr_obj_free(dev, mtr_obj);<br />+    }<br />+<br />+<br />+    RTE_TAILQ_FOREACH(profile, &zxdh_shared_data->meter_profile_list, next) {<br />+        if (profile->dpdk_port_id == priv->port_id)<br />+            zxdh_mtr_profile_res_free(dev,<br />+                zxdh_shared_data->mtr_profile_mp,<br />+                profile,<br />+                &error<br />+            );<br />+    }<br />+<br />+    struct zxdh_meter_policy *policy;<br />+<br />+    RTE_TAILQ_FOREACH(policy, &zxdh_shared_data->mtr_policy_list, next) {<br />+        if (policy->dpdk_port_id == priv->port_id)<br />+            zxdh_mtr_policy_res_free(zxdh_shared_data->mtr_policy_mp, policy);<br />+    }<br />+}<br />diff --git a/drivers/net/zxdh/zxdh_mtr.h b/drivers/net/zxdh/zxdh_mtr.h<br />new file mode 100644<br />index 0000000000..749ceb7479<br />--- /dev/null<br />+++ b/drivers/net/zxdh/zxdh_mtr.h<br />@@ -0,0 +1,114 @@<br />+/* SPDX-License-Identifier: BSD-3-Clause<br />+ * Copyright(c) 2024 ZTE Corporation<br />+ */<br />+<br />+#ifndef ZXDH_MTR_H<br />+#define ZXDH_MTR_H<br />+<br />+#include <stddef.h> <br />+#include <stdint.h> <br />+#include <sys/queue.h> <br />+#include <rte_mtr.h> <br />+<br />+#include "zxdh_np.h" <br />+<br />+#define HW_PROFILE_MAX            512<br />+#define ZXDH_MAX_MTR_NUM          2048<br />+#define ZXDH_MAX_POLICY_NUM  ZXDH_MAX_MTR_NUM<br />+#define MAX_MTR_PROFILE_NUM  HW_PROFILE_MAX<br />+#define ZXDH_INGRESS              1<br />+#define ZXDH_EGRESS              2<br />+<br />+#define MP_FREE_OBJ_FUNC(mp, obj) rte_mempool_put(mp, obj)<br />+<br />+struct zxdh_mtr_res {<br />+    rte_spinlock_t hw_plcr_res_lock;<br />+    uint32_t hw_profile_refcnt[HW_PROFILE_MAX];<br />+    struct rte_mtr_meter_profile profile[HW_PROFILE_MAX];<br />+};<br />+<br />+extern struct zxdh_mtr_res g_mtr_res;<br />+extern struct zxdh_shared_data *zxdh_shared_data;<br />+<br />+enum rte_mtr_policer_action {<br />+    ZXDH_MTR_POLICER_ACTION_COLOR_GREEN = 0,<br />+    ZXDH_MTR_POLICER_ACTION_COLOR_YELLOW,<br />+    ZXDH_MTR_POLICER_ACTION_COLOR_RED,<br />+    ZXDH_MTR_POLICER_ACTION_DROP,<br />+};<br />+<br />+union zxdh_offload_profile_cfg {<br />+    ZXDH_STAT_CAR_PKT_PROFILE_CFG_T p_car_pkt_profile_cfg;<br />+    ZXDH_STAT_CAR_PROFILE_CFG_T     p_car_byte_profile_cfg;<br />+};<br />+<br />+/* meter profile structure. */<br />+struct zxdh_meter_profile {<br />+    TAILQ_ENTRY(zxdh_meter_profile) next; /* Pointer to the next flow meter structure. */<br />+    uint16_t dpdk_port_id;<br />+    uint16_t hw_profile_owner_vport;<br />+    uint16_t meter_profile_id;            /* software Profile id. */<br />+    uint16_t hw_profile_id;               /* hardware Profile id. */<br />+    struct rte_mtr_meter_profile profile; /* Profile detail. */<br />+    union zxdh_offload_profile_cfg plcr_param;<br />+    uint32_t ref_cnt;                     /* used count. */<br />+};<br />+TAILQ_HEAD(zxdh_mtr_profile_list, zxdh_meter_profile);<br />+<br />+struct zxdh_meter_policy {<br />+    TAILQ_ENTRY(zxdh_meter_policy) next;<br />+    uint16_t policy_id;<br />+    uint16_t ref_cnt;<br />+    uint16_t dpdk_port_id;<br />+    uint16_t rsv;<br />+    struct rte_mtr_meter_policy_params policy;<br />+};<br />+TAILQ_HEAD(zxdh_mtr_policy_list, zxdh_meter_policy);<br />+<br />+struct zxdh_meter_action {<br />+    enum rte_mtr_policer_action action[RTE_COLORS];<br />+    uint64_t stats_mask;<br />+};<br />+<br />+struct zxdh_mtr_object {<br />+    TAILQ_ENTRY(zxdh_mtr_object) next;<br />+    uint8_t direction:1, /* 0:ingress, 1:egress */<br />+            shared:1,<br />+            enable:1,<br />+            rsv:5;<br />+    uint8_t rsv8;<br />+    uint16_t port_id;<br />+    uint16_t vfid;<br />+    uint16_t meter_id;<br />+    uint16_t mtr_ref_cnt;<br />+    uint16_t rsv16;<br />+    struct zxdh_meter_profile *profile;<br />+    struct zxdh_meter_policy *policy;<br />+    struct zxdh_meter_action  mtr_action;<br />+};<br />+TAILQ_HEAD(zxdh_mtr_list, zxdh_mtr_object);<br />+<br />+struct zxdh_mtr_stats {<br />+    uint64_t n_pkts_dropped;<br />+    uint64_t n_bytes_dropped;<br />+};<br />+<br />+struct zxdh_hw_mtr_stats {<br />+    uint32_t n_pkts_dropped_hi;<br />+    uint32_t n_pkts_dropped_lo;<br />+    uint32_t n_bytes_dropped_hi;<br />+    uint32_t n_bytes_dropped_lo;<br />+};<br />+<br />+int zxdh_meter_ops_get(struct rte_eth_dev *dev, void *arg);<br />+void zxdh_mtr_release(struct rte_eth_dev *dev);<br />+void zxdh_mtr_policy_res_free(struct rte_mempool *mtr_policy_mp, struct zxdh_meter_policy *policy);<br />+int zxdh_hw_profile_unref(struct rte_eth_dev *dev,<br />+        uint8_t car_type,<br />+        uint16_t hw_profile_id,<br />+        struct rte_mtr_error *error);<br />+int zxdh_hw_profile_alloc_direct(struct rte_eth_dev *dev, ZXDH_PROFILE_TYPE car_type,<br />+        uint64_t *hw_profile_id, struct rte_mtr_error *error);<br />+int zxdh_hw_profile_ref(uint16_t hw_profile_id);<br />+<br />+#endif /* ZXDH_MTR_H */<br />diff --git a/drivers/net/zxdh/zxdh_np.c b/drivers/net/zxdh/zxdh_np.c<br />index 9922cf29a4..28c9e4c1c1 100644<br />--- a/drivers/net/zxdh/zxdh_np.c<br />+++ b/drivers/net/zxdh/zxdh_np.c<br />@@ -13,6 +13,7 @@<br />  <br /> #include "zxdh_np.h" <br /> #include "zxdh_logs.h" <br />+#include "zxdh_msg.h" <br />  <br /> static uint64_t g_np_bar_offset;<br /> static ZXDH_DEV_MGR_T g_dev_mgr;<br />@@ -142,6 +143,46 @@ do {\<br /> #define ZXDH_DTB_QUEUE_INIT_FLAG_GET(DEV_ID, QUEUE_ID)       \<br />         (p_dpp_dtb_mgr[(DEV_ID)]->queue_info[(QUEUE_ID)].init_flag)<br />  <br />+ZXDH_FIELD_T g_stat_car0_cara_queue_ram0_159_0_reg[] = {<br />+    {"cara_drop", ZXDH_FIELD_FLAG_RW, 147, 1, 0x0, 0x0},<br />+    {"cara_plcr_en", ZXDH_FIELD_FLAG_RW, 146, 1, 0x0, 0x0},<br />+    {"cara_profile_id", ZXDH_FIELD_FLAG_RW, 145, 9, 0x0, 0x0},<br />+    {"cara_tq_h", ZXDH_FIELD_FLAG_RO, 136, 13, 0x0, 0x0},<br />+    {"cara_tq_l", ZXDH_FIELD_FLAG_RO, 123, 32, 0x0, 0x0},<br />+    {"cara_ted", ZXDH_FIELD_FLAG_RO, 91, 19, 0x0, 0x0},<br />+    {"cara_tcd", ZXDH_FIELD_FLAG_RO, 72, 19, 0x0, 0x0},<br />+    {"cara_tei", ZXDH_FIELD_FLAG_RO, 53, 27, 0x0, 0x0},<br />+    {"cara_tci", ZXDH_FIELD_FLAG_RO, 26, 27, 0x0, 0x0},<br />+};<br />+<br />+ZXDH_FIELD_T g_stat_car0_carb_queue_ram0_159_0_reg[] = {<br />+    {"carb_drop", ZXDH_FIELD_FLAG_RW, 147, 1, 0x0, 0x0},<br />+    {"carb_plcr_en", ZXDH_FIELD_FLAG_RW, 146, 1, 0x0, 0x0},<br />+    {"carb_profile_id", ZXDH_FIELD_FLAG_RW, 145, 9, 0x0, 0x0},<br />+    {"carb_tq_h", ZXDH_FIELD_FLAG_RO, 136, 13, 0x0, 0x0},<br />+    {"carb_tq_l", ZXDH_FIELD_FLAG_RO, 123, 32, 0x0, 0x0},<br />+    {"carb_ted", ZXDH_FIELD_FLAG_RO, 91, 19, 0x0, 0x0},<br />+    {"carb_tcd", ZXDH_FIELD_FLAG_RO, 72, 19, 0x0, 0x0},<br />+    {"carb_tei", ZXDH_FIELD_FLAG_RO, 53, 27, 0x0, 0x0},<br />+    {"carb_tci", ZXDH_FIELD_FLAG_RO, 26, 27, 0x0, 0x0},<br />+};<br />+<br />+ZXDH_FIELD_T g_stat_car0_carc_queue_ram0_159_0_reg[] = {<br />+    {"carc_drop", ZXDH_FIELD_FLAG_RW, 147, 1, 0x0, 0x0},<br />+    {"carc_plcr_en", ZXDH_FIELD_FLAG_RW, 146, 1, 0x0, 0x0},<br />+    {"carc_profile_id", ZXDH_FIELD_FLAG_RW, 145, 9, 0x0, 0x0},<br />+    {"carc_tq_h", ZXDH_FIELD_FLAG_RO, 136, 13, 0x0, 0x0},<br />+    {"carc_tq_l", ZXDH_FIELD_FLAG_RO, 123, 32, 0x0, 0x0},<br />+    {"carc_ted", ZXDH_FIELD_FLAG_RO, 91, 19, 0x0, 0x0},<br />+    {"carc_tcd", ZXDH_FIELD_FLAG_RO, 72, 19, 0x0, 0x0},<br />+    {"carc_tei", ZXDH_FIELD_FLAG_RO, 53, 27, 0x0, 0x0},<br />+    {"carc_tci", ZXDH_FIELD_FLAG_RO, 26, 27, 0x0, 0x0},<br />+};<br />+<br />+ZXDH_FIELD_T g_nppu_pktrx_cfg_pktrx_glbal_cfg_0_reg[] = {<br />+    {"pktrx_glbal_cfg_0", ZXDH_FIELD_FLAG_RW, 31, 32, 0x0, 0x0},<br />+};<br />+<br /> static uint32_t<br /> zxdh_np_comm_is_big_endian(void)<br /> {<br />@@ -1167,11 +1208,11 @@ zxdh_np_dtb_data_write(uint8_t *p_data_buff,<br />     uint8_t *cmd = (uint8_t *)entry->cmd;<br />     uint8_t *data = (uint8_t *)entry->data;<br />  <br />-    rte_memcpy(p_cmd, cmd, cmd_size);<br />+    memcpy(p_cmd, cmd, cmd_size);<br />  <br />     if (!entry->data_in_cmd_flag) {<br />         zxdh_np_comm_swap(data, data_size);<br />-        rte_memcpy(p_data, data, data_size);<br />+        memcpy(p_data, data, data_size);<br />     }<br />  <br />     return 0;<br />@@ -1379,8 +1420,8 @@ zxdh_np_dtb_table_entry_write(uint32_t dev_id,<br />     ZXDH_DTB_ENTRY_T   dtb_one_entry = {0};<br />     uint8_t entry_cmd[ZXDH_DTB_TABLE_CMD_SIZE_BIT] = {0};<br />     uint8_t entry_data[ZXDH_ETCAM_WIDTH_MAX] = {0};<br />-    uint8_t *p_data_buff = NULL;<br />-    uint8_t *p_data_buff_ex = NULL;<br />+    uint8_t *p_data_buff;<br />+    uint8_t *p_data_buff_ex;<br />     uint32_t element_id = 0xff;<br />     uint32_t one_dtb_len = 0;<br />     uint32_t dtb_len = 0;<br />@@ -2049,7 +2090,6 @@ zxdh_np_se_smmu0_ind_read(uint32_t dev_id,<br />  <br />         switch (rd_mode) {<br />         case ZXDH_ERAM128_OPR_128b:<br />-        {<br />             if ((0xFFFFFFFF - (base_addr)) < (index))<br />                 return ZXDH_PAR_CHK_INVALID_INDEX;<br />  <br />@@ -2060,10 +2100,7 @@ zxdh_np_se_smmu0_ind_read(uint32_t dev_id,<br />  <br />             row_index = (index << 7) & ZXDH_ERAM128_BADDR_MASK;<br />             break;<br />-        }<br />-<br />         case ZXDH_ERAM128_OPR_64b:<br />-        {<br />             if ((base_addr + (index >> 1)) > ZXDH_SE_SMMU0_ERAM_ADDR_NUM_TOTAL - 1) {<br />                 PMD_DRV_LOG(ERR, "%s : index out of range !", __func__);<br />                 return -1;<br />@@ -2072,10 +2109,7 @@ zxdh_np_se_smmu0_ind_read(uint32_t dev_id,<br />             row_index = (index << 6) & ZXDH_ERAM128_BADDR_MASK;<br />             col_index = index & 0x1;<br />             break;<br />-        }<br />-<br />         case ZXDH_ERAM128_OPR_32b:<br />-        {<br />             if ((base_addr + (index >> 2)) > ZXDH_SE_SMMU0_ERAM_ADDR_NUM_TOTAL - 1) {<br />                 PMD_DRV_LOG(ERR, "%s : index out of range !", __func__);<br />                 return -1;<br />@@ -2084,10 +2118,7 @@ zxdh_np_se_smmu0_ind_read(uint32_t dev_id,<br />             row_index = (index << 5) & ZXDH_ERAM128_BADDR_MASK;<br />             col_index = index & 0x3;<br />             break;<br />-        }<br />-<br />         case ZXDH_ERAM128_OPR_1b:<br />-        {<br />             if ((base_addr + (index >> 7)) > ZXDH_SE_SMMU0_ERAM_ADDR_NUM_TOTAL - 1) {<br />                 PMD_DRV_LOG(ERR, "%s : index out of range !", __func__);<br />                 return -1;<br />@@ -2096,7 +2127,6 @@ zxdh_np_se_smmu0_ind_read(uint32_t dev_id,<br />             col_index = index & 0x7F;<br />             break;<br />         }<br />-        }<br />  <br />         cpu_ind_cmd.cpu_ind_addr = ((base_addr << 7) & ZXDH_ERAM128_BADDR_MASK) + row_index;<br />     } else {<br />@@ -2105,7 +2135,6 @@ zxdh_np_se_smmu0_ind_read(uint32_t dev_id,<br />  <br />         switch (rd_mode) {<br />         case ZXDH_ERAM128_OPR_128b:<br />-        {<br />             if ((0xFFFFFFFF - (base_addr)) < (index)) {<br />                 PMD_DRV_LOG(ERR, "%s : index 0x%x is invalid!", __func__, index);<br />                 return ZXDH_PAR_CHK_INVALID_INDEX;<br />@@ -2117,9 +2146,7 @@ zxdh_np_se_smmu0_ind_read(uint32_t dev_id,<br />             row_index = (index << 7);<br />             cpu_ind_cmd.cpu_req_mode = ZXDH_ERAM128_OPR_128b;<br />             break;<br />-        }<br />         case ZXDH_ERAM128_OPR_64b:<br />-        {<br />             if ((base_addr + (index >> 1)) > ZXDH_SE_SMMU0_ERAM_ADDR_NUM_TOTAL - 1) {<br />                 PMD_DRV_LOG(ERR, "%s : index out of range !", __func__);<br />                 return -1;<br />@@ -2128,9 +2155,7 @@ zxdh_np_se_smmu0_ind_read(uint32_t dev_id,<br />             row_index = (index << 6);<br />             cpu_ind_cmd.cpu_req_mode = 2;<br />             break;<br />-        }<br />         case ZXDH_ERAM128_OPR_32b:<br />-        {<br />             if ((base_addr + (index >> 2)) > ZXDH_SE_SMMU0_ERAM_ADDR_NUM_TOTAL - 1) {<br />                 PMD_DRV_LOG(ERR, "%s : index out of range !", __func__);<br />                 return -1;<br />@@ -2138,14 +2163,11 @@ zxdh_np_se_smmu0_ind_read(uint32_t dev_id,<br />             row_index = (index << 5);<br />             cpu_ind_cmd.cpu_req_mode = 1;<br />             break;<br />-        }<br />         case ZXDH_ERAM128_OPR_1b:<br />-        {<br />             PMD_DRV_LOG(ERR, "rd_clr_mode[%d] or rd_mode[%d] error! ",<br />                 rd_clr_mode, rd_mode);<br />             return -1;<br />         }<br />-        }<br />         cpu_ind_cmd.cpu_ind_addr = ((base_addr << 7) & ZXDH_ERAM128_BADDR_MASK) + row_index;<br />     }<br />  <br />@@ -2169,45 +2191,31 @@ zxdh_np_se_smmu0_ind_read(uint32_t dev_id,<br />     if (rd_clr_mode == ZXDH_RD_MODE_HOLD) {<br />         switch (rd_mode) {<br />         case ZXDH_ERAM128_OPR_128b:<br />-        {<br />-            rte_memcpy(p_data, p_temp_data, (128 / 8));<br />+            memcpy(p_data, p_temp_data, (128 / 8));<br />             break;<br />-        }<br />         case ZXDH_ERAM128_OPR_64b:<br />-        {<br />-            rte_memcpy(p_data, p_temp_data + ((1 - col_index) << 1), (64 / 8));<br />+            memcpy(p_data, p_temp_data + ((1 - col_index) << 1), (64 / 8));<br />             break;<br />-        }<br />         case ZXDH_ERAM128_OPR_32b:<br />-        {<br />-            rte_memcpy(p_data, p_temp_data + ((3 - col_index)), (32 / 8));<br />+            memcpy(p_data, p_temp_data + ((3 - col_index)), (32 / 8));<br />             break;<br />-        }<br />         case ZXDH_ERAM128_OPR_1b:<br />-        {<br />             ZXDH_COMM_UINT32_GET_BITS(p_data[0],<br />                 *(p_temp_data + (3 - col_index / 32)), (col_index % 32), 1);<br />             break;<br />         }<br />-        }<br />     } else {<br />         switch (rd_mode) {<br />         case ZXDH_ERAM128_OPR_128b:<br />-        {<br />-            rte_memcpy(p_data, p_temp_data, (128 / 8));<br />+            memcpy(p_data, p_temp_data, (128 / 8));<br />             break;<br />-        }<br />         case ZXDH_ERAM128_OPR_64b:<br />-        {<br />-            rte_memcpy(p_data, p_temp_data, (64 / 8));<br />+            memcpy(p_data, p_temp_data, (64 / 8));<br />             break;<br />-        }<br />         case ZXDH_ERAM128_OPR_32b:<br />-        {<br />-            rte_memcpy(p_data, p_temp_data, (64 / 8));<br />+            memcpy(p_data, p_temp_data, (64 / 8));<br />             break;<br />         }<br />-        }<br />     }<br />  <br />     return rc;<br />@@ -2256,3 +2264,424 @@ zxdh_np_stat_ppu_cnt_get_ex(uint32_t dev_id,<br />  <br />     return rc;<br /> }<br />+<br />+static uint32_t<br />+zxdh_np_agent_channel_sync_send(ZXDH_AGENT_CHANNEL_MSG_T *p_msg,<br />+                uint32_t *p_data,<br />+                uint32_t rep_len)<br />+{<br />+    uint32_t ret = 0;<br />+    uint32_t vport = 0;<br />+    struct zxdh_pci_bar_msg in = {0};<br />+    struct zxdh_msg_recviver_mem result = {0};<br />+    uint32_t *recv_buffer;<br />+    uint8_t *reply_ptr = NULL;<br />+    uint16_t reply_msg_len = 0;<br />+    uint64_t agent_addr = 0;<br />+<br />+    if (ZXDH_IS_PF(vport))<br />+        in.src = ZXDH_MSG_CHAN_END_PF;<br />+    else<br />+        in.src = ZXDH_MSG_CHAN_END_VF;<br />+<br />+    in.virt_addr = agent_addr;<br />+    in.payload_addr = p_msg->msg;<br />+    in.payload_len = p_msg->msg_len;<br />+    in.dst = ZXDH_MSG_CHAN_END_RISC;<br />+    in.module_id = ZXDH_BAR_MDOULE_NPSDK;<br />+<br />+    recv_buffer = (uint32_t *)rte_zmalloc(NULL, rep_len + ZXDH_CHANNEL_REPS_LEN, 0);<br />+    if (recv_buffer == NULL) {<br />+        PMD_DRV_LOG(ERR, "%s point null!", __func__);<br />+        return ZXDH_PAR_CHK_POINT_NULL;<br />+    }<br />+<br />+    result.buffer_len = rep_len + ZXDH_CHANNEL_REPS_LEN;<br />+    result.recv_buffer = recv_buffer;<br />+<br />+    ret = zxdh_bar_chan_sync_msg_send(&in, &result);<br />+    if (ret == ZXDH_BAR_MSG_OK) {<br />+        reply_ptr = (uint8_t *)(result.recv_buffer);<br />+        if (*reply_ptr == 0XFF) {<br />+            reply_msg_len = *(uint16_t *)(reply_ptr + 1);<br />+            memcpy(p_data, reply_ptr + 4,<br />+                ((reply_msg_len > rep_len) ? rep_len : reply_msg_len));<br />+        } else {<br />+            PMD_DRV_LOG(ERR, "Message not replied");<br />+        }<br />+    } else {<br />+        PMD_DRV_LOG(ERR, "Error[0x%x], %s failed!", ret, __func__);<br />+    }<br />+<br />+    rte_free(recv_buffer);<br />+    return ret;<br />+}<br />+<br />+static uint32_t<br />+zxdh_np_agent_channel_plcr_sync_send(ZXDH_AGENT_CHANNEL_PLCR_MSG_T *p_msg,<br />+        uint32_t *p_data, uint32_t rep_len)<br />+{<br />+    uint32_t ret = 0;<br />+    ZXDH_AGENT_CHANNEL_MSG_T agent_msg = {0};<br />+<br />+    agent_msg.msg = (void *)p_msg;<br />+    agent_msg.msg_len = sizeof(ZXDH_AGENT_CHANNEL_PLCR_MSG_T);<br />+<br />+    ret = zxdh_np_agent_channel_sync_send(&agent_msg, p_data, rep_len);<br />+    if (ret != 0)    {<br />+        PMD_DRV_LOG(ERR, "%s: agent_channel_sync_send failed.", __func__);<br />+        return 1;<br />+    }<br />+<br />+    return 0;<br />+}<br />+<br />+static uint32_t<br />+zxdh_np_agent_channel_plcr_profileid_request(uint32_t vport,<br />+    uint32_t car_type, uint32_t *p_profileid)<br />+{<br />+    uint32_t ret = 0;<br />+    uint32_t resp_buffer[2] = {0};<br />+<br />+    ZXDH_AGENT_CHANNEL_PLCR_MSG_T msgcfg = {0};<br />+<br />+    msgcfg.dev_id = 0;<br />+    msgcfg.type = ZXDH_PLCR_MSG;<br />+    msgcfg.oper = ZXDH_PROFILEID_REQUEST;<br />+    msgcfg.vport = vport;<br />+    msgcfg.car_type = car_type;<br />+    msgcfg.profile_id = 0xFFFF;<br />+<br />+    ret = zxdh_np_agent_channel_plcr_sync_send(&msgcfg,<br />+        resp_buffer, sizeof(resp_buffer));<br />+    if (ret != 0)    {<br />+        PMD_DRV_LOG(ERR, "%s: agent_channel_plcr_sync_send failed.", __func__);<br />+        return 1;<br />+    }<br />+<br />+    memcpy(p_profileid, resp_buffer, sizeof(uint32_t) * ZXDH_SCHE_RSP_LEN);<br />+<br />+    return ret;<br />+}<br />+<br />+static uint32_t<br />+zxdh_np_agent_channel_plcr_car_rate(uint32_t car_type,<br />+        uint32_t pkt_sign,<br />+        uint32_t profile_id __rte_unused,<br />+        void *p_car_profile_cfg)<br />+{<br />+    uint32_t ret = 0;<br />+    uint32_t resp_buffer[2] = {0};<br />+    uint32_t resp_len = 8;<br />+    uint32_t i = 0;<br />+    ZXDH_AGENT_CHANNEL_MSG_T agent_msg = {0};<br />+    ZXDH_AGENT_CAR_PKT_PROFILE_MSG_T msgpktcfg = {0};<br />+    ZXDH_AGENT_CAR_PROFILE_MSG_T msgcfg = {0};<br />+    ZXDH_STAT_CAR_PROFILE_CFG_T *p_stat_car_profile_cfg = NULL;<br />+    ZXDH_STAT_CAR_PKT_PROFILE_CFG_T *p_stat_pkt_car_profile_cfg = NULL;<br />+<br />+    if (car_type == ZXDH_STAT_CAR_A_TYPE && pkt_sign == 1) {<br />+        p_stat_pkt_car_profile_cfg = (ZXDH_STAT_CAR_PKT_PROFILE_CFG_T *)p_car_profile_cfg;<br />+        msgpktcfg.dev_id = 0;<br />+        msgpktcfg.type = ZXDH_PLCR_CAR_PKT_RATE;<br />+        msgpktcfg.car_level = car_type;<br />+        msgpktcfg.cir = p_stat_pkt_car_profile_cfg->cir;<br />+        msgpktcfg.cbs = p_stat_pkt_car_profile_cfg->cbs;<br />+        msgpktcfg.profile_id = p_stat_pkt_car_profile_cfg->profile_id;<br />+        msgpktcfg.pkt_sign = p_stat_pkt_car_profile_cfg->pkt_sign;<br />+        for (i = 0; i < ZXDH_CAR_PRI_MAX; i++)<br />+            msgpktcfg.pri[i] = p_stat_pkt_car_profile_cfg->pri[i];<br />+<br />+        agent_msg.msg = (void *)&msgpktcfg;<br />+        agent_msg.msg_len = sizeof(ZXDH_AGENT_CAR_PKT_PROFILE_MSG_T);<br />+<br />+        ret = zxdh_np_agent_channel_sync_send(&agent_msg, resp_buffer, resp_len);<br />+        if (ret != 0)    {<br />+            PMD_DRV_LOG(ERR, "%s: stat_car_a_type failed.", __func__);<br />+            return 1;<br />+        }<br />+<br />+        ret = *(uint8_t *)resp_buffer;<br />+    } else {<br />+        p_stat_car_profile_cfg = (ZXDH_STAT_CAR_PROFILE_CFG_T *)p_car_profile_cfg;<br />+        msgcfg.dev_id = 0;<br />+        msgcfg.type = ZXDH_PLCR_CAR_RATE;<br />+        msgcfg.car_level = car_type;<br />+        msgcfg.cir = p_stat_car_profile_cfg->cir;<br />+        msgcfg.cbs = p_stat_car_profile_cfg->cbs;<br />+        msgcfg.profile_id = p_stat_car_profile_cfg->profile_id;<br />+        msgcfg.pkt_sign = p_stat_car_profile_cfg->pkt_sign;<br />+        msgcfg.cd = p_stat_car_profile_cfg->cd;<br />+        msgcfg.cf = p_stat_car_profile_cfg->cf;<br />+        msgcfg.cm = p_stat_car_profile_cfg->cm;<br />+        msgcfg.cir = p_stat_car_profile_cfg->cir;<br />+        msgcfg.cbs = p_stat_car_profile_cfg->cbs;<br />+        msgcfg.eir = p_stat_car_profile_cfg->eir;<br />+        msgcfg.ebs = p_stat_car_profile_cfg->ebs;<br />+        msgcfg.random_disc_e = p_stat_car_profile_cfg->random_disc_e;<br />+        msgcfg.random_disc_c = p_stat_car_profile_cfg->random_disc_c;<br />+        for (i = 0; i < ZXDH_CAR_PRI_MAX; i++) {<br />+            msgcfg.c_pri[i] = p_stat_car_profile_cfg->c_pri[i];<br />+            msgcfg.e_green_pri[i] = p_stat_car_profile_cfg->e_green_pri[i];<br />+            msgcfg.e_yellow_pri[i] = p_stat_car_profile_cfg->e_yellow_pri[i];<br />+        }<br />+<br />+        agent_msg.msg = (void *)&msgcfg;<br />+        agent_msg.msg_len = sizeof(ZXDH_AGENT_CAR_PROFILE_MSG_T);<br />+<br />+        ret = zxdh_np_agent_channel_sync_send(&agent_msg, resp_buffer, resp_len);<br />+        if (ret != 0)    {<br />+            PMD_DRV_LOG(ERR, "%s: stat_car_b_type failed.", __func__);<br />+            return 1;<br />+        }<br />+<br />+        ret = *(uint8_t *)resp_buffer;<br />+    }<br />+<br />+    return ret;<br />+}<br />+<br />+static uint32_t<br />+zxdh_np_agent_channel_plcr_profileid_release(uint32_t vport,<br />+        uint32_t car_type __rte_unused,<br />+        uint32_t profileid)<br />+{<br />+    uint32_t ret = 0;<br />+    uint32_t resp_buffer[2] = {0};<br />+<br />+    ZXDH_AGENT_CHANNEL_PLCR_MSG_T msgcfg = {0};<br />+<br />+    msgcfg.dev_id = 0;<br />+    msgcfg.type = ZXDH_PLCR_MSG;<br />+    msgcfg.oper = ZXDH_PROFILEID_RELEASE;<br />+    msgcfg.vport = vport;<br />+    msgcfg.profile_id = profileid;<br />+<br />+    ret = zxdh_np_agent_channel_plcr_sync_send(&msgcfg,<br />+        resp_buffer, sizeof(resp_buffer));<br />+    if (ret != 0)    {<br />+        PMD_DRV_LOG(ERR, "%s: agent_channel_plcr_sync_send failed.", __func__);<br />+        return 1;<br />+    }<br />+<br />+    ret = *(uint8_t *)resp_buffer;<br />+<br />+    return ret;<br />+}<br />+<br />+static uint32_t<br />+zxdh_np_stat_cara_queue_cfg_set(uint32_t dev_id,<br />+        uint32_t flow_id,<br />+        uint32_t drop_flag,<br />+        uint32_t plcr_en,<br />+        uint32_t profile_id)<br />+{<br />+    uint32_t rc = 0;<br />+<br />+    ZXDH_STAT_CAR0_CARA_QUEUE_RAM0_159_0_T queue_cfg = {0};<br />+<br />+    queue_cfg.cara_drop = drop_flag;<br />+    queue_cfg.cara_plcr_en = plcr_en;<br />+    queue_cfg.cara_profile_id = profile_id;<br />+    rc = zxdh_np_reg_write(dev_id,<br />+                ZXDH_STAT_CAR0_CARA_QUEUE_RAM0,<br />+                0,<br />+                flow_id,<br />+                &queue_cfg);<br />+    ZXDH_COMM_CHECK_DEV_RC(dev_id, rc, "zxdh_np_reg_write");<br />+<br />+    return rc;<br />+}<br />+<br />+static uint32_t<br />+zxdh_np_stat_carb_queue_cfg_set(uint32_t dev_id,<br />+        uint32_t flow_id,<br />+        uint32_t drop_flag,<br />+        uint32_t plcr_en,<br />+        uint32_t profile_id)<br />+{<br />+    uint32_t rc = 0;<br />+<br />+    ZXDH_STAT_CAR0_CARB_QUEUE_RAM0_159_0_T queue_cfg = {0};<br />+<br />+    queue_cfg.carb_drop = drop_flag;<br />+    queue_cfg.carb_plcr_en = plcr_en;<br />+    queue_cfg.carb_profile_id = profile_id;<br />+<br />+    rc = zxdh_np_reg_write(dev_id,<br />+                ZXDH_STAT_CAR0_CARB_QUEUE_RAM0,<br />+                0,<br />+                flow_id,<br />+                &queue_cfg);<br />+    ZXDH_COMM_CHECK_DEV_RC(dev_id, rc, "zxdh_np_reg_write");<br />+<br />+    return rc;<br />+}<br />+<br />+static uint32_t<br />+zxdh_np_stat_carc_queue_cfg_set(uint32_t dev_id,<br />+        uint32_t flow_id,<br />+        uint32_t drop_flag,<br />+        uint32_t plcr_en,<br />+        uint32_t profile_id)<br />+{<br />+    uint32_t rc = 0;<br />+<br />+    ZXDH_STAT_CAR0_CARC_QUEUE_RAM0_159_0_T queue_cfg = {0};<br />+    queue_cfg.carc_drop = drop_flag;<br />+    queue_cfg.carc_plcr_en = plcr_en;<br />+    queue_cfg.carc_profile_id = profile_id;<br />+<br />+    rc = zxdh_np_reg_write(dev_id,<br />+                        ZXDH_STAT_CAR0_CARC_QUEUE_RAM0,<br />+                        0,<br />+                        flow_id,<br />+                        &queue_cfg);<br />+    ZXDH_COMM_CHECK_DEV_RC(dev_id, rc, "zxdh_np_reg_write");<br />+<br />+    return rc;<br />+}<br />+<br />+uint32_t<br />+zxdh_np_car_profile_id_add(uint32_t vport_id,<br />+        uint32_t flags,<br />+        uint64_t *p_profile_id)<br />+{<br />+    uint32_t ret = 0;<br />+    uint32_t *profile_id;<br />+    uint32_t profile_id_h = 0;<br />+    uint32_t profile_id_l = 0;<br />+    uint64_t temp_profile_id = 0;<br />+<br />+    profile_id = (uint32_t *)rte_zmalloc(NULL, ZXDH_G_PROFILE_ID_LEN, 0);<br />+    if (profile_id == NULL) {<br />+        PMD_DRV_LOG(ERR, "%s: profile_id point null!", __func__);<br />+        return ZXDH_PAR_CHK_POINT_NULL;<br />+    }<br />+    ret = zxdh_np_agent_channel_plcr_profileid_request(vport_id, flags, profile_id);<br />+<br />+    profile_id_h = *(profile_id + 1);<br />+    profile_id_l = *profile_id;<br />+    rte_free(profile_id);<br />+<br />+    temp_profile_id = (((uint64_t)profile_id_l) << 32) | ((uint64_t)profile_id_h);<br />+    if (0 != (uint32_t)(temp_profile_id >> 56)) {<br />+        PMD_DRV_LOG(ERR, "%s: profile_id is overflow!", __func__);<br />+        return 1;<br />+    }<br />+<br />+    *p_profile_id = temp_profile_id;<br />+<br />+    return ret;<br />+}<br />+<br />+uint32_t<br />+zxdh_np_car_profile_cfg_set(uint32_t vport_id __rte_unused,<br />+        uint32_t car_type,<br />+        uint32_t pkt_sign,<br />+        uint32_t profile_id,<br />+        void *p_car_profile_cfg)<br />+{<br />+    uint32_t ret = 0;<br />+<br />+    ret = zxdh_np_agent_channel_plcr_car_rate(car_type,<br />+        pkt_sign, profile_id, p_car_profile_cfg);<br />+    if (ret != 0) {<br />+        PMD_DRV_LOG(ERR, "%s: plcr_car_rate set failed!", __func__);<br />+        return 1;<br />+    }<br />+<br />+    return ret;<br />+}<br />+<br />+uint32_t<br />+zxdh_np_car_profile_id_delete(uint32_t vport_id,<br />+    uint32_t flags, uint64_t profile_id)<br />+{<br />+    uint32_t ret = 0;<br />+    uint32_t profileid = 0;<br />+<br />+    profileid = profile_id & 0xFFFF;<br />+<br />+    ret = zxdh_np_agent_channel_plcr_profileid_release(vport_id, flags, profileid);<br />+    if (ret != 0) {<br />+        PMD_DRV_LOG(ERR, "%s: plcr profiled id release failed!", __func__);<br />+        return 1;<br />+    }<br />+<br />+    return 0;<br />+}<br />+<br />+uint32_t<br />+zxdh_np_stat_car_queue_cfg_set(uint32_t dev_id,<br />+        uint32_t car_type,<br />+        uint32_t flow_id,<br />+        uint32_t drop_flag,<br />+        uint32_t plcr_en,<br />+        uint32_t profile_id)<br />+{<br />+    uint32_t rc = 0;<br />+<br />+    if (car_type == ZXDH_STAT_CAR_A_TYPE) {<br />+        if (flow_id > ZXDH_CAR_A_FLOW_ID_MAX) {<br />+            PMD_DRV_LOG(ERR, "%s: stat car a type flow_id invalid!", __func__);<br />+            return ZXDH_PAR_CHK_INVALID_INDEX;<br />+        }<br />+<br />+        if (profile_id > ZXDH_CAR_A_PROFILE_ID_MAX) {<br />+            PMD_DRV_LOG(ERR, "%s: stat car a type profile_id invalid!", __func__);<br />+            return ZXDH_PAR_CHK_INVALID_INDEX;<br />+        }<br />+    } else if (car_type == ZXDH_STAT_CAR_B_TYPE) {<br />+        if (flow_id > ZXDH_CAR_B_FLOW_ID_MAX) {<br />+            PMD_DRV_LOG(ERR, "%s: stat car b type flow_id invalid!", __func__);<br />+            return ZXDH_PAR_CHK_INVALID_INDEX;<br />+        }<br />+<br />+        if (profile_id > ZXDH_CAR_B_PROFILE_ID_MAX) {<br />+            PMD_DRV_LOG(ERR, "%s: stat car b type profile_id invalid!", __func__);<br />+            return ZXDH_PAR_CHK_INVALID_INDEX;<br />+        }<br />+    } else {<br />+        if (flow_id > ZXDH_CAR_C_FLOW_ID_MAX) {<br />+            PMD_DRV_LOG(ERR, "%s: stat car c type flow_id invalid!", __func__);<br />+            return ZXDH_PAR_CHK_INVALID_INDEX;<br />+        }<br />+<br />+        if (profile_id > ZXDH_CAR_C_PROFILE_ID_MAX) {<br />+            PMD_DRV_LOG(ERR, "%s: stat car c type profile_id invalid!", __func__);<br />+            return ZXDH_PAR_CHK_INVALID_INDEX;<br />+        }<br />+    }<br />+<br />+    switch (car_type) {<br />+    case ZXDH_STAT_CAR_A_TYPE:<br />+        rc = zxdh_np_stat_cara_queue_cfg_set(dev_id,<br />+                    flow_id,<br />+                    drop_flag,<br />+                    plcr_en,<br />+                    profile_id);<br />+        ZXDH_COMM_CHECK_DEV_RC(dev_id, rc, "stat_cara_queue_cfg_set");<br />+    break;<br />+<br />+    case ZXDH_STAT_CAR_B_TYPE:<br />+        rc = zxdh_np_stat_carb_queue_cfg_set(dev_id,<br />+                    flow_id,<br />+                    drop_flag,<br />+                    plcr_en,<br />+                    profile_id);<br />+        ZXDH_COMM_CHECK_DEV_RC(dev_id, rc, "stat_carb_queue_cfg_set");<br />+    break;<br />+<br />+    case ZXDH_STAT_CAR_C_TYPE:<br />+        rc = zxdh_np_stat_carc_queue_cfg_set(dev_id,<br />+                    flow_id,<br />+                    drop_flag,<br />+                    plcr_en,<br />+                    profile_id);<br />+        ZXDH_COMM_CHECK_DEV_RC(dev_id, rc, "stat_carc_queue_cfg_set");<br />+    break;<br />+    }<br />+<br />+    return rc;<br />+}<br />diff --git a/drivers/net/zxdh/zxdh_np.h b/drivers/net/zxdh/zxdh_np.h<br />index d793189657..7ff5c34c73 100644<br />--- a/drivers/net/zxdh/zxdh_np.h<br />+++ b/drivers/net/zxdh/zxdh_np.h<br />@@ -147,6 +147,44 @@<br /> #define ZXDH_RC_DTB_SEARCH_VPORT_QUEUE_ZERO     (ZXDH_RC_DTB_BASE | 0x17)<br /> #define ZXDH_RC_DTB_QUEUE_NOT_ENABLE            (ZXDH_RC_DTB_BASE | 0x18)<br />  <br />+#define ZXDH_SCHE_RSP_LEN                       (2)<br />+#define ZXDH_G_PROFILE_ID_LEN                   (8)<br />+<br />+#define ZXDH_CAR_A_FLOW_ID_MAX                  (0x7fff)<br />+#define ZXDH_CAR_B_FLOW_ID_MAX                  (0xfff)<br />+#define ZXDH_CAR_C_FLOW_ID_MAX                  (0x3ff)<br />+#define ZXDH_CAR_A_PROFILE_ID_MAX               (0x1ff)<br />+#define ZXDH_CAR_B_PROFILE_ID_MAX               (0x7f)<br />+#define ZXDH_CAR_C_PROFILE_ID_MAX               (0x1f)<br />+<br />+#define ZXDH_SYS_NP_BASE_ADDR0          (0x00000000)<br />+#define ZXDH_SYS_NP_BASE_ADDR1          (0x02000000)<br />+<br />+#define ZXDH_FIELD_FLAG_RO              (1 << 0)<br />+#define ZXDH_FIELD_FLAG_RW              (1 << 1)<br />+<br />+#define ZXDH_VF_ACTIVE(VPORT)                   (((VPORT) & 0x0800) >> 11)<br />+#define ZXDH_EPID_BY(VPORT)                     (((VPORT) & 0x7000) >> 12)<br />+#define ZXDH_FUNC_NUM(VPORT)                    (((VPORT) & 0x0700) >> 8)<br />+#define ZXDH_VFUNC_NUM(VPORT)                   (((VPORT) & 0x00FF))<br />+#define ZXDH_IS_PF(VPORT)                       (!ZXDH_VF_ACTIVE(VPORT))<br />+<br />+#define ZXDH_CHANNEL_REPS_LEN                   (4)<br />+<br />+typedef enum zxdh_module_base_addr_e {<br />+    ZXDH_MODULE_SE_SMMU0_BASE_ADDR = 0x00000000,<br />+    ZXDH_MODULE_DTB_ENQ_BASE_ADDR  = 0x00000000,<br />+    ZXDH_MODULE_NPPU_PKTRX_CFG_BASE_ADDR = 0x00000800,<br />+} ZXDH_MODULE_BASE_ADDR_E;<br />+<br />+typedef enum zxdh_sys_base_addr_e {<br />+    ZXDH_SYS_NPPU_BASE_ADDR     = (ZXDH_SYS_NP_BASE_ADDR0 + 0x00000000),<br />+    ZXDH_SYS_SE_SMMU0_BASE_ADDR = (ZXDH_SYS_NP_BASE_ADDR0 + 0x00300000),<br />+    ZXDH_SYS_DTB_BASE_ADDR      = (ZXDH_SYS_NP_BASE_ADDR1 + 0x00000000),<br />+    ZXDH_SYS_MAX_BASE_ADDR      = 0x20000000,<br />+} ZXDH_SYS_BASE_ADDR_E;<br />+<br />+<br /> typedef enum zxdh_module_init_e {<br />     ZXDH_MODULE_INIT_NPPU = 0,<br />     ZXDH_MODULE_INIT_PPU,<br />@@ -173,6 +211,10 @@ typedef enum zxdh_reg_info_e {<br />     ZXDH_DTB_CFG_QUEUE_DTB_LEN    = 2,<br />     ZXDH_DTB_INFO_QUEUE_BUF_SPACE = 3,<br />     ZXDH_DTB_CFG_EPID_V_FUNC_NUM  = 4,<br />+    ZXDH_STAT_CAR0_CARA_QUEUE_RAM0       = 9,<br />+    ZXDH_STAT_CAR0_CARB_QUEUE_RAM0       = 10,<br />+    ZXDH_STAT_CAR0_CARC_QUEUE_RAM0       = 11,<br />+    ZXDH_NPPU_PKTRX_CFG_GLBAL_CFG_0R     = 12,<br />     ZXDH_REG_ENUM_MAX_VALUE<br /> } ZXDH_REG_INFO_E;<br />  <br />@@ -597,6 +639,171 @@ typedef enum zxdh_se_opr_mode_e {<br />     ZXDH_SE_OPR_WR      = 1,<br /> } ZXDH_SE_OPR_MODE_E;<br />  <br />+typedef enum zxdh_stat_car_type_e {<br />+    ZXDH_STAT_CAR_A_TYPE  = 0,<br />+    ZXDH_STAT_CAR_B_TYPE,<br />+    ZXDH_STAT_CAR_C_TYPE,<br />+    ZXDH_STAT_CAR_MAX_TYPE<br />+} ZXDH_STAT_CAR_TYPE_E;<br />+<br />+typedef enum zxdh_car_priority_e {<br />+    ZXDH_CAR_PRI0 = 0,<br />+    ZXDH_CAR_PRI1 = 1,<br />+    ZXDH_CAR_PRI2 = 2,<br />+    ZXDH_CAR_PRI3 = 3,<br />+    ZXDH_CAR_PRI4 = 4,<br />+    ZXDH_CAR_PRI5 = 5,<br />+    ZXDH_CAR_PRI6 = 6,<br />+    ZXDH_CAR_PRI7 = 7,<br />+    ZXDH_CAR_PRI_MAX<br />+} ZXDH_CAR_PRIORITY_E;<br />+<br />+typedef struct zxdh_stat_car_pkt_profile_cfg_t {<br />+    uint32_t profile_id;<br />+    uint32_t pkt_sign;<br />+    uint32_t cir;<br />+    uint32_t cbs;<br />+    uint32_t pri[ZXDH_CAR_PRI_MAX];<br />+} ZXDH_STAT_CAR_PKT_PROFILE_CFG_T;<br />+<br />+typedef struct zxdh_stat_car_profile_cfg_t {<br />+    uint32_t profile_id;<br />+    uint32_t pkt_sign;<br />+    uint32_t cd;<br />+    uint32_t cf;<br />+    uint32_t cm;<br />+    uint32_t cir;<br />+    uint32_t cbs;<br />+    uint32_t eir;<br />+    uint32_t ebs;<br />+    uint32_t random_disc_e;<br />+    uint32_t random_disc_c;<br />+    uint32_t c_pri[ZXDH_CAR_PRI_MAX];<br />+    uint32_t e_green_pri[ZXDH_CAR_PRI_MAX];<br />+    uint32_t e_yellow_pri[ZXDH_CAR_PRI_MAX];<br />+} ZXDH_STAT_CAR_PROFILE_CFG_T;<br />+<br />+typedef struct zxdh_stat_car0_cara_queue_ram0_159_0_t {<br />+    uint32_t cara_drop;<br />+    uint32_t cara_plcr_en;<br />+    uint32_t cara_profile_id;<br />+    uint32_t cara_tq_h;<br />+    uint32_t cara_tq_l;<br />+    uint32_t cara_ted;<br />+    uint32_t cara_tcd;<br />+    uint32_t cara_tei;<br />+    uint32_t cara_tci;<br />+} ZXDH_STAT_CAR0_CARA_QUEUE_RAM0_159_0_T;<br />+<br />+typedef struct dpp_agent_car_profile_msg {<br />+    uint8_t dev_id;<br />+    uint8_t type;<br />+    uint8_t rsv;<br />+    uint8_t rsv1;<br />+    uint32_t car_level;<br />+    uint32_t profile_id;<br />+    uint32_t pkt_sign;<br />+    uint32_t cd;<br />+    uint32_t cf;<br />+    uint32_t cm;<br />+    uint32_t cir;<br />+    uint32_t cbs;<br />+    uint32_t eir;<br />+    uint32_t ebs;<br />+    uint32_t random_disc_e;<br />+    uint32_t random_disc_c;<br />+    uint32_t c_pri[ZXDH_CAR_PRI_MAX];<br />+    uint32_t e_green_pri[ZXDH_CAR_PRI_MAX];<br />+    uint32_t e_yellow_pri[ZXDH_CAR_PRI_MAX];<br />+} ZXDH_AGENT_CAR_PROFILE_MSG_T;<br />+<br />+typedef struct dpp_agent_car_pkt_profile_msg {<br />+    uint8_t dev_id;<br />+    uint8_t type;<br />+    uint8_t rsv;<br />+    uint8_t rsv1;<br />+    uint32_t car_level;<br />+    uint32_t profile_id;<br />+    uint32_t pkt_sign;<br />+    uint32_t cir;<br />+    uint32_t cbs;<br />+    uint32_t pri[ZXDH_CAR_PRI_MAX];<br />+} ZXDH_AGENT_CAR_PKT_PROFILE_MSG_T;<br />+<br />+typedef struct zxdh_agent_channel_msg_t {<br />+    uint32_t msg_len;<br />+    void *msg;<br />+} ZXDH_AGENT_CHANNEL_MSG_T;<br />+<br />+typedef struct zxdh_agent_channel_plcr_msg {<br />+    uint8_t dev_id;<br />+    uint8_t type;<br />+    uint8_t oper;<br />+    uint8_t rsv;<br />+    uint32_t vport;<br />+    uint32_t car_type;<br />+    uint32_t profile_id;<br />+} ZXDH_AGENT_CHANNEL_PLCR_MSG_T;<br />+<br />+typedef struct dpp_stat_car0_carc_queue_ram0_159_0_t {<br />+    uint32_t carc_drop;<br />+    uint32_t carc_plcr_en;<br />+    uint32_t carc_profile_id;<br />+    uint32_t carc_tq_h;<br />+    uint32_t carc_tq_l;<br />+    uint32_t carc_ted;<br />+    uint32_t carc_tcd;<br />+    uint32_t carc_tei;<br />+    uint32_t carc_tci;<br />+} ZXDH_STAT_CAR0_CARC_QUEUE_RAM0_159_0_T;<br />+<br />+typedef struct zxdh_stat_car0_carb_queue_ram0_159_0_t {<br />+    uint32_t carb_drop;<br />+    uint32_t carb_plcr_en;<br />+    uint32_t carb_profile_id;<br />+    uint32_t carb_tq_h;<br />+    uint32_t carb_tq_l;<br />+    uint32_t carb_ted;<br />+    uint32_t carb_tcd;<br />+    uint32_t carb_tei;<br />+    uint32_t carb_tci;<br />+} ZXDH_STAT_CAR0_CARB_QUEUE_RAM0_159_0_T;<br />+<br />+typedef enum zxdh_np_agent_msg_type_e {<br />+    ZXDH_REG_MSG = 0,<br />+    ZXDH_DTB_MSG,<br />+    ZXDH_TM_MSG,<br />+    ZXDH_PLCR_MSG,<br />+    ZXDH_PKTRX_IND_REG_RW_MSG,<br />+    ZXDH_PCIE_BAR_MSG,<br />+    ZXDH_RESET_MSG,<br />+    ZXDH_PXE_MSG,<br />+    ZXDH_TM_FLOW_SHAPE,<br />+    ZXDH_TM_TD,<br />+    ZXDH_TM_SE_SHAPE,<br />+    ZXDH_TM_PP_SHAPE,<br />+    ZXDH_PLCR_CAR_RATE,<br />+    ZXDH_PLCR_CAR_PKT_RATE,<br />+    ZXDH_PPU_THASH_RSK,<br />+    ZXDH_ACL_MSG,<br />+    ZXDH_STAT_MSG,<br />+    ZXDH_RES_MSG,<br />+    ZXDH_MSG_MAX<br />+} MSG_TYPE_E;<br />+<br />+typedef enum zxdh_msg_plcr_oper {<br />+    ZXDH_PROFILEID_REQUEST = 0,<br />+    ZXDH_PROFILEID_RELEASE = 1,<br />+} ZXDH_MSG_PLCR_OPER_E;<br />+<br />+typedef enum zxdh_profile_type {<br />+    CAR_A = 0,<br />+    CAR_B = 1,<br />+    CAR_C = 2,<br />+    CAR_MAX<br />+} ZXDH_PROFILE_TYPE;<br />+<br />+<br /> int zxdh_np_host_init(uint32_t dev_id, ZXDH_DEV_INIT_CTRL_T *p_dev_init_ctrl);<br /> int zxdh_np_online_uninit(uint32_t dev_id, char *port_name, uint32_t queue_id);<br /> int zxdh_np_dtb_table_entry_write(uint32_t dev_id, uint32_t queue_id,<br />@@ -615,5 +822,22 @@ uint32_t zxdh_np_stat_ppu_cnt_get_ex(uint32_t dev_id,<br />             uint32_t index,<br />             uint32_t clr_mode,<br />             uint32_t *p_data);<br />+uint32_t<br />+zxdh_np_car_profile_id_add(uint32_t vport_id,<br />+            uint32_t flags,<br />+            uint64_t *p_profile_id);<br />+uint32_t zxdh_np_car_profile_cfg_set(uint32_t vport_id,<br />+            uint32_t car_type,<br />+            uint32_t pkt_sign,<br />+            uint32_t profile_id,<br />+            void *p_car_profile_cfg);<br />+uint32_t zxdh_np_car_profile_id_delete(uint32_t vport_id,<br />+            uint32_t flags, uint64_t profile_id);<br />+uint32_t zxdh_np_stat_car_queue_cfg_set(uint32_t dev_id,<br />+            uint32_t car_type,<br />+            uint32_t flow_id,<br />+            uint32_t drop_flag,<br />+            uint32_t plcr_en,<br />+            uint32_t profile_id);<br />  <br /> #endif /* ZXDH_NP_H */<br />diff --git a/drivers/net/zxdh/zxdh_tables.h b/drivers/net/zxdh/zxdh_tables.h<br />index f44f444bd9..2f2ada3a9f 100644<br />--- a/drivers/net/zxdh/zxdh_tables.h<br />+++ b/drivers/net/zxdh/zxdh_tables.h<br />@@ -77,6 +77,8 @@<br /> #define ZXDH_UNICAST_STATS_INGRESS_BASE      0x8FC1<br />  <br /> #define ZXDH_FLOW_STATS_INGRESS_BASE         0xADC1<br />+#define ZXDH_MTR_STATS_EGRESS_BASE           0x7481<br />+#define ZXDH_MTR_STATS_INGRESS_BASE          0x7C81<br />  <br /> extern struct zxdh_dtb_shared_data g_dtb_data;<br />  <br />--  <br />2.27.0<br />