From: Vanshika Shukla <vanshika.shu...@nxp.com>

This patch adds DPBP APIs for setting and getting the depletion/surplus
thresholds for controlling pause frame generation.

By default, depletion_entry is set as 128 by MC. This API would help user
configure the buffer in depletion state as per requirement.

Signed-off-by: Vanshika Shukla <vanshika.shu...@nxp.com>
---
 doc/guides/platform/dpaa2.rst             |  2 +-
 drivers/bus/fslmc/mc/dpbp.c               | 78 ++++++++++++++++++++++-
 drivers/bus/fslmc/mc/fsl_dpbp.h           | 41 +++++++++++-
 drivers/mempool/dpaa2/dpaa2_hw_mempool.c  | 26 ++++++++
 drivers/mempool/dpaa2/dpaa2_hw_mempool.h  |  1 +
 drivers/mempool/dpaa2/rte_dpaa2_mempool.h | 12 ++++
 drivers/net/dpaa2/dpaa2_ethdev.c          | 39 +++++++++++-
 drivers/net/dpaa2/dpaa2_ethdev.h          |  1 +
 8 files changed, 194 insertions(+), 6 deletions(-)

diff --git a/doc/guides/platform/dpaa2.rst b/doc/guides/platform/dpaa2.rst
index c9ec21334f..e32ba5d300 100644
--- a/doc/guides/platform/dpaa2.rst
+++ b/doc/guides/platform/dpaa2.rst
@@ -106,7 +106,7 @@ separately:
 Currently supported by DPDK:
 
 - NXP SDK **LSDK 21.08++**.
-- MC Firmware version **10.37.0** and higher.
+- MC Firmware version **10.39.0** and higher.
 - Supported architectures:  **arm64 LE**.
 
 - Follow the DPDK :ref:`Getting Started Guide for Linux <linux_gsg>`
diff --git a/drivers/bus/fslmc/mc/dpbp.c b/drivers/bus/fslmc/mc/dpbp.c
index 08f24d33e8..5529a1fe9c 100644
--- a/drivers/bus/fslmc/mc/dpbp.c
+++ b/drivers/bus/fslmc/mc/dpbp.c
@@ -1,7 +1,7 @@
 /* SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0)
  *
  * Copyright 2013-2016 Freescale Semiconductor Inc.
- * Copyright 2016-2017 NXP
+ * Copyright 2016-2017, 2025 NXP
  *
  */
 #include <fsl_mc_sys.h>
@@ -362,3 +362,79 @@ int dpbp_get_num_free_bufs(struct fsl_mc_io *mc_io,
 
        return 0;
 }
+
+/**
+ * dpbp_set_notifications() - Set notifications towards software
+ * @mc_io:     Pointer to MC portal's I/O object
+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:     Token of DPBP object
+ * @cfg:       notifications configuration
+ *
+ * Return:     '0' on Success; Error code otherwise.
+ */
+RTE_EXPORT_INTERNAL_SYMBOL(dpbp_set_notifications)
+int dpbp_set_notifications(struct fsl_mc_io *mc_io,
+       uint32_t cmd_flags,
+       uint16_t token,
+       struct dpbp_notification_cfg *cfg)
+{
+       struct dpbp_cmd_set_notifications *cmd_params;
+       struct mc_command cmd = { 0 };
+
+       /* prepare command */
+       cmd.header = mc_encode_cmd_header(DPBP_CMDID_SET_NOTIFICATIONS,
+                       cmd_flags, token);
+       cmd_params = (struct dpbp_cmd_set_notifications *)cmd.params;
+       cmd_params->depletion_entry = cpu_to_le32(cfg->depletion_entry);
+       cmd_params->depletion_exit = cpu_to_le32(cfg->depletion_exit);
+       cmd_params->surplus_entry = cpu_to_le32(cfg->surplus_entry);
+       cmd_params->surplus_exit = cpu_to_le32(cfg->surplus_exit);
+       cmd_params->options = cpu_to_le32(cfg->options);
+       cmd_params->message_ctx = cpu_to_le64(cfg->message_ctx);
+       cmd_params->message_iova = cpu_to_le64(cfg->message_iova);
+
+       /* send command to mc*/
+       return mc_send_command(mc_io, &cmd);
+}
+
+/**
+ * dpbp_get_notifications() - Get the notifications configuration
+ * @mc_io:     Pointer to MC portal's I/O object
+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:     Token of DPBP object
+ * @cfg:       notifications configuration
+ *
+ * Return:     '0' on Success; Error code otherwise.
+ */
+RTE_EXPORT_INTERNAL_SYMBOL(dpbp_get_notifications)
+int dpbp_get_notifications(struct fsl_mc_io *mc_io,
+       uint32_t cmd_flags,
+       uint16_t token,
+       struct dpbp_notification_cfg *cfg)
+{
+       struct dpbp_rsp_get_notifications *rsp_params;
+       struct mc_command cmd = { 0 };
+       int err;
+
+       /* prepare command */
+       cmd.header = mc_encode_cmd_header(DPBP_CMDID_GET_NOTIFICATIONS,
+                         cmd_flags,
+                         token);
+
+       /* send command to mc*/
+       err = mc_send_command(mc_io, &cmd);
+       if (err)
+               return err;
+
+       /* retrieve response parameters */
+       rsp_params = (struct dpbp_rsp_get_notifications *)cmd.params;
+       cfg->depletion_entry = le32_to_cpu(rsp_params->depletion_entry);
+       cfg->depletion_exit = le32_to_cpu(rsp_params->depletion_exit);
+       cfg->surplus_entry = le32_to_cpu(rsp_params->surplus_entry);
+       cfg->surplus_exit = le32_to_cpu(rsp_params->surplus_exit);
+       cfg->options = le32_to_cpu(rsp_params->options);
+       cfg->message_ctx = le64_to_cpu(rsp_params->message_ctx);
+       cfg->message_iova = le64_to_cpu(rsp_params->message_iova);
+
+       return 0;
+}
diff --git a/drivers/bus/fslmc/mc/fsl_dpbp.h b/drivers/bus/fslmc/mc/fsl_dpbp.h
index 8a021f55f1..c79b511715 100644
--- a/drivers/bus/fslmc/mc/fsl_dpbp.h
+++ b/drivers/bus/fslmc/mc/fsl_dpbp.h
@@ -1,7 +1,7 @@
 /* SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0)
  *
  * Copyright 2013-2016 Freescale Semiconductor Inc.
- * Copyright 2016-2017 NXP
+ * Copyright 2016-2017, 2025 NXP
  *
  */
 #ifndef __FSL_DPBP_H
@@ -16,6 +16,34 @@
 
 struct fsl_mc_io;
 
+/**
+ * struct dpbp_notification_cfg - Structure representing DPBP notifications
+ *     towards software
+ * @depletion_entry: below this threshold the pool is "depleted";
+ *     set it to '0' to disable it
+ * @depletion_exit: greater than or equal to this threshold the pool exit its
+ *     "depleted" state
+ * @surplus_entry: above this threshold the pool is in "surplus" state;
+ *     set it to '0' to disable it
+ * @surplus_exit: less than or equal to this threshold the pool exit its
+ *     "surplus" state
+ * @message_iova: MUST be given if either 'depletion_entry' or 'surplus_entry'
+ *     is not '0' (enable); I/O virtual address (must be in DMA-able memory),
+ *     must be 16B aligned.
+ * @message_ctx: The context that will be part of the BPSCN message and will
+ *     be written to 'message_iova'
+ * @options: Mask of available options; use 'DPBP_NOTIF_OPT_<X>' values
+ */
+struct dpbp_notification_cfg {
+       uint32_t depletion_entry;
+       uint32_t depletion_exit;
+       uint32_t surplus_entry;
+       uint32_t surplus_exit;
+       uint64_t message_iova;
+       uint64_t message_ctx;
+       uint32_t options;
+};
+
 __rte_internal
 int dpbp_open(struct fsl_mc_io *mc_io,
              uint32_t cmd_flags,
@@ -25,7 +53,18 @@ int dpbp_open(struct fsl_mc_io *mc_io,
 int dpbp_close(struct fsl_mc_io *mc_io,
               uint32_t cmd_flags,
               uint16_t token);
+__rte_internal
+int dpbp_set_notifications(struct fsl_mc_io *mc_io,
+               uint32_t cmd_flags,
+               uint16_t token,
+               struct dpbp_notification_cfg *cfg);
+__rte_internal
+int dpbp_get_notifications(struct fsl_mc_io *mc_io,
+               uint32_t cmd_flags,
+               uint16_t token,
+               struct dpbp_notification_cfg *cfg);
 
+#define DPBP_NOTIF_OPT_WRIOP               0x00010000
 /**
  * struct dpbp_cfg - Structure representing DPBP configuration
  * @options:   place holder
diff --git a/drivers/mempool/dpaa2/dpaa2_hw_mempool.c 
b/drivers/mempool/dpaa2/dpaa2_hw_mempool.c
index 09729d2828..eb22a14fb5 100644
--- a/drivers/mempool/dpaa2/dpaa2_hw_mempool.c
+++ b/drivers/mempool/dpaa2/dpaa2_hw_mempool.c
@@ -38,6 +38,32 @@ RTE_EXPORT_INTERNAL_SYMBOL(rte_dpaa2_bpid_info)
 struct dpaa2_bp_info *rte_dpaa2_bpid_info;
 static struct dpaa2_bp_list *h_bp_list;
 
+int
+rte_dpaa2_dpbp_set_notifications(struct rte_mempool *mp,
+                                       struct dpaa2_dpbp_cfg *dpbp_cfg)
+{
+       struct dpaa2_dpbp_dev *avail_dpbp;
+       struct dpaa2_bp_info *bpinfo;
+       struct dpaa2_bp_list *bp;
+       int ret;
+
+       bpinfo = mempool_to_bpinfo(mp);
+       bp = bpinfo->bp_list;
+
+       avail_dpbp = bp->buf_pool.dpbp_node;
+
+       ret = dpbp_set_notifications(&avail_dpbp->dpbp, CMD_PRI_LOW,
+                                       avail_dpbp->token,
+                                       (struct dpbp_notification_cfg *) 
dpbp_cfg);
+       if (ret) {
+               DPAA2_MEMPOOL_ERR("DPBP set notifications failure!");
+               return ret;
+       }
+       bp->dpbp_notification_enable = true;
+
+       return 0;
+}
+
 static int
 rte_hw_mbuf_create_pool(struct rte_mempool *mp)
 {
diff --git a/drivers/mempool/dpaa2/dpaa2_hw_mempool.h 
b/drivers/mempool/dpaa2/dpaa2_hw_mempool.h
index 9e21823fb6..f2583be4c6 100644
--- a/drivers/mempool/dpaa2/dpaa2_hw_mempool.h
+++ b/drivers/mempool/dpaa2/dpaa2_hw_mempool.h
@@ -48,6 +48,7 @@ struct dpaa2_bp_list {
        struct rte_mempool *mp; /**< DPDK RTE EAL pool reference */
        int32_t dpaa2_ops_index; /**< Index into DPDK Mempool ops table */
        struct buf_pool buf_pool;
+       bool dpbp_notification_enable;
 };
 
 struct dpaa2_bp_info {
diff --git a/drivers/mempool/dpaa2/rte_dpaa2_mempool.h 
b/drivers/mempool/dpaa2/rte_dpaa2_mempool.h
index 0286090b1b..c1cf160a21 100644
--- a/drivers/mempool/dpaa2/rte_dpaa2_mempool.h
+++ b/drivers/mempool/dpaa2/rte_dpaa2_mempool.h
@@ -19,6 +19,16 @@
 extern "C" {
 #endif
 
+struct dpaa2_dpbp_cfg {
+       uint32_t depletion_entry;
+       uint32_t depletion_exit;
+       uint32_t surplus_entry;
+       uint32_t surplus_exit;
+       uint64_t message_iova;
+       uint64_t message_ctx;
+       uint32_t options;
+};
+
 /**
  * Get BPID corresponding to the packet pool
  *
@@ -62,6 +72,8 @@ rte_dpaa2_mbuf_from_buf_addr(struct rte_mempool *mp, void 
*buf_addr);
 __rte_internal
 int rte_dpaa2_bpid_info_init(struct rte_mempool *mp);
 
+int rte_dpaa2_dpbp_set_notifications(struct rte_mempool *mp, struct 
dpaa2_dpbp_cfg *dpbp_cfg);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c
index c154a574ce..d17785a6ee 100644
--- a/drivers/net/dpaa2/dpaa2_ethdev.c
+++ b/drivers/net/dpaa2/dpaa2_ethdev.c
@@ -745,6 +745,9 @@ dpaa2_dev_rx_queue_setup(struct rte_eth_dev *dev,
        dpaa2_q->nb_desc = UINT16_MAX;
        dpaa2_q->offloads = rx_conf->offloads;
 
+       if (priv->bp_list->dpbp_notification_enable)
+               priv->enable_bp_flow_ctrl = true;
+
        /*Get the flow id from given VQ id*/
        flow_id = dpaa2_q->flow_id;
        memset(&cfg, 0, sizeof(struct dpni_queue));
@@ -1176,7 +1179,7 @@ dpaa2_eth_setup_irqs(struct rte_eth_dev *dev, int enable)
 
        return err;
 }
-
+static int dpaa2_flow_ctrl_set(struct rte_eth_dev *dev, struct rte_eth_fc_conf 
*fc_conf);
 static int
 dpaa2_dev_start(struct rte_eth_dev *dev)
 {
@@ -1191,11 +1194,27 @@ dpaa2_dev_start(struct rte_eth_dev *dev)
        struct dpaa2_queue *dpaa2_q;
        int ret, i;
        struct rte_intr_handle *intr_handle;
+       struct rte_eth_fc_conf *fc_conf;
+
+       PMD_INIT_FUNC_TRACE();
 
        dpaa2_dev = container_of(rdev, struct rte_dpaa2_device, device);
        intr_handle = dpaa2_dev->intr_handle;
 
-       PMD_INIT_FUNC_TRACE();
+       if (priv->enable_bp_flow_ctrl) {
+               fc_conf = rte_zmalloc(NULL, sizeof(struct rte_eth_fc_conf),
+                               RTE_CACHE_LINE_SIZE);
+               fc_conf->autoneg = 0;
+               fc_conf->mode = RTE_ETH_FC_FULL;
+
+               ret = dpaa2_flow_ctrl_set(dev, fc_conf);
+               if (ret) {
+                       DPAA2_PMD_ERR("Unable to set flow ctrl");
+                       return ret;
+               }
+               rte_free(fc_conf);
+       }
+
        ret = dpni_enable(dpni, CMD_PRI_LOW, priv->token);
        if (ret) {
                DPAA2_PMD_ERR("Failure in enabling dpni %d device: err=%d",
@@ -1298,6 +1317,7 @@ dpaa2_dev_stop(struct rte_eth_dev *dev)
        struct rte_device *rdev = dev->device;
        struct rte_intr_handle *intr_handle;
        struct rte_dpaa2_device *dpaa2_dev;
+       struct rte_eth_fc_conf *fc_conf;
        uint16_t i;
 
        dpaa2_dev = container_of(rdev, struct rte_dpaa2_device, device);
@@ -1305,6 +1325,19 @@ dpaa2_dev_stop(struct rte_eth_dev *dev)
 
        PMD_INIT_FUNC_TRACE();
 
+       if (priv->enable_bp_flow_ctrl) {
+               fc_conf = rte_zmalloc(NULL, sizeof(struct rte_eth_fc_conf),
+                       RTE_CACHE_LINE_SIZE);
+               fc_conf->mode = RTE_ETH_FC_NONE;
+
+               ret = dpaa2_flow_ctrl_set(dev, fc_conf);
+               if (ret) {
+                       DPAA2_PMD_ERR("Unable to set flow ctrl");
+                       return ret;
+               }
+               rte_free(fc_conf);
+       }
+
        /* reset interrupt callback  */
        if (intr_handle && rte_intr_fd_get(intr_handle) &&
            dev->data->dev_conf.intr_conf.lsc != 0) {
@@ -2110,7 +2143,7 @@ dpaa2_flow_ctrl_get(struct rte_eth_dev *dev, struct 
rte_eth_fc_conf *fc_conf)
        return ret;
 }
 
-static int
+int
 dpaa2_flow_ctrl_set(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf)
 {
        int ret = -EINVAL;
diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h
index f32c31c763..103fa2ca67 100644
--- a/drivers/net/dpaa2/dpaa2_ethdev.h
+++ b/drivers/net/dpaa2/dpaa2_ethdev.h
@@ -409,6 +409,7 @@ struct dpaa2_dev_priv {
        struct rte_eth_dev *eth_dev; /**< Pointer back to holding ethdev */
        rte_spinlock_t lpbk_qp_lock;
 
+       bool enable_bp_flow_ctrl;
        uint8_t channel_inuse;
        /* Stores correction offset for one step timestamping */
        uint16_t ptp_correction_offset;
-- 
2.25.1

Reply via email to