The patch provides a series of interfaces for managing<br />and controlling the configuration, start, stop,<br />resource management, etc. of compression devices.<br /> <br />Signed-off-by: Hanxiao Li <li.hanxiao@zte.com.cn> <br />---<br /> drivers/common/zsda/meson.build       |   2 +-<br /> drivers/compress/zsda/zsda_comp_pmd.c | 464 ++++++++++++++++++++++++++<br /> drivers/compress/zsda/zsda_comp_pmd.h |  34 ++<br /> 3 files changed, 499 insertions(+), 1 deletion(-)<br /> create mode 100644 drivers/compress/zsda/zsda_comp_pmd.c<br /> create mode 100644 drivers/compress/zsda/zsda_comp_pmd.h<br /> <br />diff --git a/drivers/common/zsda/meson.build b/drivers/common/zsda/meson.build<br />index f873a357e3..20fb37caaf 100644<br />--- a/drivers/common/zsda/meson.build<br />+++ b/drivers/common/zsda/meson.build<br />@@ -20,7 +20,7 @@ zsda_compress_path = 'compress/zsda' <br /> zsda_compress_relpath = '../../' + zsda_compress_path<br /> includes += include_directories(zsda_compress_relpath)<br /> if zsda_compress<br />-    foreach f: ['zsda_comp.c']<br />+    foreach f: ['zsda_comp.c', 'zsda_comp_pmd.c']<br />         sources += files(join_paths(zsda_compress_relpath, f))<br />     endforeach<br /> endif<br />diff --git a/drivers/compress/zsda/zsda_comp_pmd.c b/drivers/compress/zsda/zsda_comp_pmd.c<br />new file mode 100644<br />index 0000000000..32221c42a3<br />--- /dev/null<br />+++ b/drivers/compress/zsda/zsda_comp_pmd.c<br />@@ -0,0 +1,464 @@<br />+/* SPDX-License-Identifier: BSD-3-Clause<br />+ * Copyright(c) 2024 ZTE Corporation<br />+ */<br />+<br />+#include <rte_malloc.h> <br />+<br />+#include "zsda_comp.h" <br />+#include "zsda_comp_pmd.h" <br />+<br />+static const struct rte_compressdev_capabilities zsda_comp_capabilities[] = {<br />+    {<br />+        .algo = RTE_COMP_ALGO_DEFLATE,<br />+        .comp_feature_flags = RTE_COMP_FF_HUFFMAN_DYNAMIC |<br />+                            RTE_COMP_FF_OOP_SGL_IN_SGL_OUT |<br />+                            RTE_COMP_FF_OOP_SGL_IN_LB_OUT |<br />+                            RTE_COMP_FF_OOP_LB_IN_SGL_OUT |<br />+                            RTE_COMP_FF_CRC32_CHECKSUM |<br />+                            RTE_COMP_FF_ADLER32_CHECKSUM,<br />+        .window_size = {.min = 15, .max = 15, .increment = 0},<br />+    },<br />+};<br />+<br />+static void<br />+zsda_comp_stats_get(struct rte_compressdev *dev,<br />+            struct rte_compressdev_stats *stats)<br />+{<br />+    struct zsda_common_stat comm = {0};<br />+<br />+    zsda_stats_get(dev->data->queue_pairs, dev->data->nb_queue_pairs,<br />+               &comm);<br />+    stats->enqueued_count = comm.enqueued_count;<br />+    stats->dequeued_count = comm.dequeued_count;<br />+    stats->enqueue_err_count = comm.enqueue_err_count;<br />+    stats->dequeue_err_count = comm.dequeue_err_count;<br />+}<br />+<br />+static void<br />+zsda_comp_stats_reset(struct rte_compressdev *dev)<br />+{<br />+    zsda_stats_reset(dev->data->queue_pairs, dev->data->nb_queue_pairs);<br />+}<br />+<br />+static int<br />+zsda_comp_qp_release(struct rte_compressdev *dev, uint16_t queue_pair_id)<br />+{<br />+    return zsda_queue_pair_release(<br />+        (struct zsda_qp **)&(dev->data->queue_pairs[queue_pair_id]));<br />+}<br />+<br />+<br />+static int<br />+zsda_setup_comp_queue(struct zsda_pci_device *zsda_pci_dev, const uint16_t qp_id,<br />+         struct zsda_qp *qp, uint16_t nb_des, int socket_id)<br />+{<br />+    enum zsda_service_type type = ZSDA_SERVICE_COMPRESSION;<br />+    struct zsda_qp_config conf;<br />+    int ret = 0;<br />+    struct zsda_qp_hw *qp_hw;<br />+<br />+    qp_hw = zsda_qps_hw_per_service(zsda_pci_dev, type);<br />+    conf.hw = qp_hw->data + qp_id;<br />+    conf.service_type = type;<br />+    conf.cookie_size = sizeof(struct zsda_op_cookie);<br />+    conf.nb_descriptors = nb_des;<br />+    conf.socket_id = socket_id;<br />+    conf.service_str = "comp";<br />+<br />+    ret = zsda_common_setup_qp(zsda_pci_dev->zsda_dev_id, &qp, qp_id, &conf);<br />+    qp->srv[type].rx_cb = zsda_comp_callback;<br />+    qp->srv[type].tx_cb = zsda_build_comp_request;<br />+    qp->srv[type].match = zsda_comp_match;<br />+<br />+    return ret;<br />+}<br />+<br />+static int<br />+zsda_setup_decomp_queue(struct zsda_pci_device *zsda_pci_dev, const uint16_t qp_id,<br />+           struct zsda_qp *qp, uint16_t nb_des, int socket_id)<br />+{<br />+    enum zsda_service_type type = ZSDA_SERVICE_DECOMPRESSION;<br />+    struct zsda_qp_config conf;<br />+    int ret = 0;<br />+    struct zsda_qp_hw *qp_hw;<br />+<br />+    qp_hw = zsda_qps_hw_per_service(zsda_pci_dev, type);<br />+    conf.hw = qp_hw->data + qp_id;<br />+    conf.service_type = type;<br />+    conf.cookie_size = sizeof(struct zsda_op_cookie);<br />+    conf.nb_descriptors = nb_des;<br />+    conf.socket_id = socket_id;<br />+    conf.service_str = "decomp";<br />+<br />+    ret = zsda_common_setup_qp(zsda_pci_dev->zsda_dev_id, &qp, qp_id, &conf);<br />+    qp->srv[type].rx_cb = zsda_comp_callback;<br />+    qp->srv[type].tx_cb = zsda_build_decomp_request;<br />+    qp->srv[type].match = zsda_decomp_match;<br />+<br />+    return ret;<br />+}<br />+<br />+static int<br />+zsda_comp_qp_setup(struct rte_compressdev *dev, uint16_t qp_id,<br />+           uint32_t max_inflight_ops, int socket_id)<br />+{<br />+    int ret = 0;<br />+    struct zsda_qp *qp_new;<br />+<br />+    struct zsda_qp **qp_addr =<br />+        (struct zsda_qp **)&(dev->data->queue_pairs[qp_id]);<br />+    struct zsda_comp_dev_private *comp_priv = dev->data->dev_private;<br />+    struct zsda_pci_device *zsda_pci_dev = comp_priv->zsda_pci_dev;<br />+    uint16_t num_qps_comp = zsda_nb_qps.encomp;<br />+    uint16_t num_qps_decomp = zsda_nb_qps.decomp;<br />+    uint16_t nb_des = max_inflight_ops & 0xffff;<br />+<br />+    nb_des = (nb_des == NB_DES) ? nb_des : NB_DES;<br />+<br />+    if (*qp_addr != NULL) {<br />+        ret = zsda_comp_qp_release(dev, qp_id);<br />+        if (ret)<br />+            return ret;<br />+    }<br />+<br />+    qp_new = rte_zmalloc_socket("zsda PMD qp metadata", sizeof(*qp_new),<br />+                    RTE_CACHE_LINE_SIZE, socket_id);<br />+    if (qp_new == NULL) {<br />+        ZSDA_LOG(ERR, E_MALLOC);<br />+        return -ENOMEM;<br />+    }<br />+<br />+    if (num_qps_comp == MAX_QPS_ON_FUNCTION)<br />+        ret = zsda_setup_comp_queue(zsda_pci_dev, qp_id, qp_new, nb_des,<br />+                    socket_id);<br />+    else if (num_qps_decomp == MAX_QPS_ON_FUNCTION)<br />+        ret = zsda_setup_decomp_queue(zsda_pci_dev, qp_id, qp_new, nb_des,<br />+                      socket_id);<br />+    else {<br />+        ret = zsda_setup_comp_queue(zsda_pci_dev, qp_id, qp_new, nb_des,<br />+                    socket_id);<br />+        ret |= zsda_setup_decomp_queue(zsda_pci_dev, qp_id, qp_new, nb_des,<br />+                      socket_id);<br />+    }<br />+<br />+    if (ret) {<br />+        rte_free(qp_new);<br />+        return ret;<br />+    }<br />+<br />+    *qp_addr = qp_new;<br />+<br />+    return ret;<br />+}<br />+<br />+static int<br />+zsda_comp_xform_size(void)<br />+{<br />+    return RTE_ALIGN_CEIL(sizeof(struct zsda_comp_xform), 8);<br />+}<br />+<br />+static struct rte_mempool *<br />+zsda_comp_create_xform_pool(struct zsda_comp_dev_private *comp_dev,<br />+                struct rte_compressdev_config *config,<br />+                uint32_t num_elements)<br />+{<br />+    char xform_pool_name[RTE_MEMPOOL_NAMESIZE];<br />+    struct rte_mempool *mp;<br />+<br />+    snprintf(xform_pool_name, RTE_MEMPOOL_NAMESIZE, "%s_xforms",<br />+         comp_dev->zsda_pci_dev->name);<br />+<br />+    ZSDA_LOG(DEBUG, "xformpool: %s", xform_pool_name);<br />+    mp = rte_mempool_lookup(xform_pool_name);<br />+<br />+    if (mp != NULL) {<br />+        ZSDA_LOG(DEBUG, "xformpool already created");<br />+        if (mp->size != num_elements) {<br />+            ZSDA_LOG(DEBUG, "xformpool wrong size - delete it");<br />+            rte_mempool_free(mp);<br />+            mp = NULL;<br />+            comp_dev->xformpool = NULL;<br />+        }<br />+    }<br />+<br />+    if (mp == NULL)<br />+        mp = rte_mempool_create(xform_pool_name, num_elements,<br />+                    zsda_comp_xform_size(), 0, 0, NULL,<br />+                    NULL, NULL, NULL, config->socket_id, 0);<br />+    if (mp == NULL) {<br />+        ZSDA_LOG(ERR, E_CREATE);<br />+        return NULL;<br />+    }<br />+<br />+    return mp;<br />+}<br />+<br />+static int<br />+zsda_comp_private_xform_create(struct rte_compressdev *dev,<br />+                   const struct rte_comp_xform *xform,<br />+                   void **private_xform)<br />+{<br />+    struct zsda_comp_dev_private *zsda = dev->data->dev_private;<br />+<br />+    if (unlikely(private_xform == NULL)) {<br />+        ZSDA_LOG(ERR, E_NULL);<br />+        return -EINVAL;<br />+    }<br />+    if (unlikely(zsda->xformpool == NULL)) {<br />+        ZSDA_LOG(ERR, E_NULL);<br />+        return -ENOMEM;<br />+    }<br />+    if (rte_mempool_get(zsda->xformpool, private_xform)) {<br />+        ZSDA_LOG(ERR, E_NULL);<br />+        return -ENOMEM;<br />+    }<br />+<br />+    struct zsda_comp_xform *zsda_xform = *private_xform;<br />+    zsda_xform->type = xform->type;<br />+<br />+    if (zsda_xform->type == RTE_COMP_COMPRESS)<br />+        zsda_xform->checksum_type = xform->compress.chksum;<br />+    else<br />+        zsda_xform->checksum_type = xform->decompress.chksum;<br />+<br />+    if (zsda_xform->checksum_type == RTE_COMP_CHECKSUM_CRC32_ADLER32)<br />+        return -EINVAL;<br />+<br />+    return 0;<br />+}<br />+<br />+static int<br />+zsda_comp_private_xform_free(struct rte_compressdev *dev __rte_unused,<br />+                 void *private_xform)<br />+{<br />+    struct zsda_comp_xform *zsda_xform = private_xform;<br />+<br />+    if (zsda_xform) {<br />+        memset(zsda_xform, 0, zsda_comp_xform_size());<br />+        struct rte_mempool *mp = rte_mempool_from_obj(zsda_xform);<br />+<br />+        rte_mempool_put(mp, zsda_xform);<br />+        return 0;<br />+    }<br />+    return -EINVAL;<br />+}<br />+<br />+static int<br />+zsda_comp_dev_close(struct rte_compressdev *dev)<br />+{<br />+    uint16_t i;<br />+    struct zsda_comp_dev_private *comp_dev = dev->data->dev_private;<br />+<br />+    for (i = 0; i < dev->data->nb_queue_pairs; i++)<br />+        zsda_comp_qp_release(dev, i);<br />+<br />+    rte_mempool_free(comp_dev->xformpool);<br />+    comp_dev->xformpool = NULL;<br />+<br />+    return 0;<br />+}<br />+<br />+static int<br />+zsda_comp_dev_config(struct rte_compressdev *dev,<br />+             struct rte_compressdev_config *config)<br />+{<br />+    struct zsda_comp_dev_private *comp_dev = dev->data->dev_private;<br />+<br />+    if (config->max_nb_priv_xforms) {<br />+        comp_dev->xformpool = zsda_comp_create_xform_pool(<br />+            comp_dev, config, config->max_nb_priv_xforms);<br />+        if (comp_dev->xformpool == NULL)<br />+            return -ENOMEM;<br />+    } else<br />+        comp_dev->xformpool = NULL;<br />+<br />+    return 0;<br />+}<br />+<br />+static int<br />+zsda_comp_dev_start(struct rte_compressdev *dev)<br />+{<br />+    struct zsda_comp_dev_private *comp_dev = dev->data->dev_private;<br />+    int ret = 0;<br />+<br />+    ret = zsda_queue_start(comp_dev->zsda_pci_dev->pci_dev);<br />+<br />+    if (ret)<br />+        ZSDA_LOG(ERR, E_START_Q);<br />+<br />+    return ret;<br />+}<br />+<br />+static void<br />+zsda_comp_dev_stop(struct rte_compressdev *dev)<br />+{<br />+    struct zsda_comp_dev_private *comp_dev = dev->data->dev_private;<br />+<br />+    zsda_queue_stop(comp_dev->zsda_pci_dev->pci_dev);<br />+}<br />+<br />+static uint16_t<br />+zsda_comp_max_nb_qps(void)<br />+{<br />+    uint16_t comp = zsda_nb_qps.encomp;<br />+    uint16_t decomp = zsda_nb_qps.decomp;<br />+    uint16_t min = 0;<br />+<br />+    if ((comp == MAX_QPS_ON_FUNCTION) ||<br />+        (decomp == MAX_QPS_ON_FUNCTION))<br />+        min = MAX_QPS_ON_FUNCTION;<br />+    else<br />+        min = (comp < decomp) ? comp : decomp;<br />+    if (min == 0)<br />+        return MAX_QPS_ON_FUNCTION;<br />+    return min;<br />+}<br />+<br />+<br />+static void<br />+zsda_comp_dev_info_get(struct rte_compressdev *dev,<br />+               struct rte_compressdev_info *info)<br />+{<br />+    struct zsda_comp_dev_private *comp_dev = dev->data->dev_private;<br />+<br />+    if (info != NULL) {<br />+        info->max_nb_queue_pairs = zsda_comp_max_nb_qps();<br />+        info->feature_flags = dev->feature_flags;<br />+        info->capabilities = comp_dev->zsda_dev_capabilities;<br />+    }<br />+}<br />+<br />+static uint16_t<br />+zsda_comp_pmd_enqueue_op_burst(void *qp, struct rte_comp_op **ops,<br />+                   uint16_t nb_ops)<br />+{<br />+    return zsda_enqueue_op_burst((struct zsda_qp *)qp, (void **)ops,<br />+                     nb_ops);<br />+}<br />+<br />+static uint16_t<br />+zsda_comp_pmd_dequeue_op_burst(void *qp, struct rte_comp_op **ops,<br />+                   uint16_t nb_ops)<br />+{<br />+    return zsda_dequeue_op_burst((struct zsda_qp *)qp, (void **)ops,<br />+                     nb_ops);<br />+}<br />+<br />+static struct rte_compressdev_ops compress_zsda_ops = {<br />+<br />+    .dev_configure = zsda_comp_dev_config,<br />+    .dev_start = zsda_comp_dev_start,<br />+    .dev_stop = zsda_comp_dev_stop,<br />+    .dev_close = zsda_comp_dev_close,<br />+    .dev_infos_get = zsda_comp_dev_info_get,<br />+<br />+    .stats_get = zsda_comp_stats_get,<br />+    .stats_reset = zsda_comp_stats_reset,<br />+    .queue_pair_setup = zsda_comp_qp_setup,<br />+    .queue_pair_release = zsda_comp_qp_release,<br />+<br />+    .private_xform_create = zsda_comp_private_xform_create,<br />+    .private_xform_free = zsda_comp_private_xform_free};<br />+<br />+/* An rte_driver is needed in the registration of the device with compressdev.<br />+ * The actual zsda pci's rte_driver can't be used as its name represents<br />+ * the whole pci device with all services. Think of this as a holder for a name<br />+ * for the compression part of the pci device.<br />+ */<br />+static const char zsda_comp_drv_name[] = RTE_STR(COMPRESSDEV_NAME_ZSDA_PMD);<br />+static const struct rte_driver compdev_zsda_driver = {<br />+    .name = zsda_comp_drv_name, .alias = zsda_comp_drv_name};<br />+<br />+int<br />+zsda_comp_dev_create(struct zsda_pci_device *zsda_pci_dev)<br />+{<br />+    struct zsda_device_info *dev_info =<br />+        &zsda_devs[zsda_pci_dev->zsda_dev_id];<br />+<br />+    struct rte_compressdev_pmd_init_params init_params = {<br />+        .name = "",<br />+        .socket_id = (int)rte_socket_id(),<br />+    };<br />+<br />+    char name[RTE_COMPRESSDEV_NAME_MAX_LEN];<br />+    char capa_memz_name[RTE_COMPRESSDEV_NAME_MAX_LEN];<br />+    struct rte_compressdev *compressdev;<br />+    struct zsda_comp_dev_private *comp_dev;<br />+    const struct rte_compressdev_capabilities *capabilities;<br />+    uint16_t capa_size = sizeof(struct rte_compressdev_capabilities);<br />+<br />+    snprintf(name, RTE_COMPRESSDEV_NAME_MAX_LEN, "%s_%s",<br />+         zsda_pci_dev->name, "comp");<br />+<br />+    if (rte_eal_process_type() != RTE_PROC_PRIMARY)<br />+        return 0;<br />+<br />+    dev_info->comp_rte_dev.driver = &compdev_zsda_driver;<br />+    dev_info->comp_rte_dev.numa_node = dev_info->pci_dev->device.numa_node;<br />+    dev_info->comp_rte_dev.devargs = NULL;<br />+<br />+    compressdev = rte_compressdev_pmd_create(<br />+        name, &(dev_info->comp_rte_dev),<br />+        sizeof(struct zsda_comp_dev_private), &init_params);<br />+<br />+    if (compressdev == NULL)<br />+        return -ENODEV;<br />+<br />+    compressdev->dev_ops = &compress_zsda_ops;<br />+<br />+    compressdev->enqueue_burst = zsda_comp_pmd_enqueue_op_burst;<br />+    compressdev->dequeue_burst = zsda_comp_pmd_dequeue_op_burst;<br />+<br />+    compressdev->feature_flags = RTE_COMPDEV_FF_HW_ACCELERATED;<br />+<br />+    snprintf(capa_memz_name, RTE_COMPRESSDEV_NAME_MAX_LEN,<br />+         "ZSDA_COMP_CAPA");<br />+<br />+    comp_dev = compressdev->data->dev_private;<br />+    comp_dev->zsda_pci_dev = zsda_pci_dev;<br />+    comp_dev->compressdev = compressdev;<br />+    capabilities = zsda_comp_capabilities;<br />+<br />+    comp_dev->capa_mz = rte_memzone_lookup(capa_memz_name);<br />+    if (comp_dev->capa_mz == NULL) {<br />+        comp_dev->capa_mz = rte_memzone_reserve(<br />+            capa_memz_name, capa_size, rte_socket_id(), 0);<br />+    }<br />+    if (comp_dev->capa_mz == NULL) {<br />+        ZSDA_LOG(DEBUG, E_MALLOC);<br />+        memset(&dev_info->comp_rte_dev, 0,<br />+               sizeof(dev_info->comp_rte_dev));<br />+        rte_compressdev_pmd_destroy(compressdev);<br />+        return -EFAULT;<br />+    }<br />+<br />+    memcpy(comp_dev->capa_mz->addr, capabilities, capa_size);<br />+    comp_dev->zsda_dev_capabilities = comp_dev->capa_mz->addr;<br />+<br />+    zsda_pci_dev->comp_dev = comp_dev;<br />+<br />+    return 0;<br />+}<br />+<br />+int<br />+zsda_comp_dev_destroy(struct zsda_pci_device *zsda_pci_dev)<br />+{<br />+    struct zsda_comp_dev_private *comp_dev;<br />+<br />+    if (zsda_pci_dev == NULL)<br />+        return -ENODEV;<br />+<br />+    comp_dev = zsda_pci_dev->comp_dev;<br />+    if (comp_dev == NULL)<br />+        return 0;<br />+<br />+    if (rte_eal_process_type() == RTE_PROC_PRIMARY)<br />+        rte_memzone_free(zsda_pci_dev->comp_dev->capa_mz);<br />+<br />+    zsda_comp_dev_close(comp_dev->compressdev);<br />+<br />+    rte_compressdev_pmd_destroy(comp_dev->compressdev);<br />+    zsda_pci_dev->comp_dev = NULL;<br />+<br />+    return 0;<br />+}<br />diff --git a/drivers/compress/zsda/zsda_comp_pmd.h b/drivers/compress/zsda/zsda_comp_pmd.h<br />new file mode 100644<br />index 0000000000..da91cf06c3<br />--- /dev/null<br />+++ b/drivers/compress/zsda/zsda_comp_pmd.h<br />@@ -0,0 +1,34 @@<br />+/* SPDX-License-Identifier: BSD-3-Clause<br />+ * Copyright(c) 2024 ZTE Corporation<br />+ */<br />+<br />+#ifndef _ZSDA_COMP_PMD_H_<br />+#define _ZSDA_COMP_PMD_H_<br />+<br />+#include <rte_compressdev_pmd.h> <br />+<br />+/**< ZSDA Compression PMD driver name */<br />+#define COMPRESSDEV_NAME_ZSDA_PMD compress_zsda<br />+<br />+/** private data structure for a ZSDA compression device.<br />+ * This ZSDA device is a device offering only a compression service,<br />+ * there can be one of these on each zsda_pci_device (VF).<br />+ */<br />+struct zsda_comp_dev_private {<br />+    struct zsda_pci_device *zsda_pci_dev;<br />+    /**< The zsda pci device hosting the service */<br />+    struct rte_compressdev *compressdev;<br />+    /**< The pointer to this compression device structure */<br />+    const struct rte_compressdev_capabilities *zsda_dev_capabilities;<br />+    /* ZSDA device compression capabilities */<br />+    struct rte_mempool *xformpool;<br />+    /**< The device's pool for zsda_comp_xforms */<br />+    const struct rte_memzone *capa_mz;<br />+    /* Shared memzone for storing capabilities */<br />+};<br />+<br />+int zsda_comp_dev_create(struct zsda_pci_device *zsda_pci_dev);<br />+<br />+int zsda_comp_dev_destroy(struct zsda_pci_device *zsda_pci_dev);<br />+<br />+#endif /* _ZSDA_COMP_PMD_H_ */<br />--  <br />2.27.0<br />