As we know, the uacce driver (e.g. hisi_acc DMA driver) reads the API of
the hardware device (through /sysfs/class/uacce/xxx/api) and compares it
with the API supported by the driver to match the corresponding hardware
device.

Hardware devices will continue to evolve, which means their APIs will
change, but business requirements demand that they support old
programming interfaces as much as possible.

To adapt to this situation, this commit supports forward compatibility
of driver APIs. For example, if the driver supports the hisi_qm_v5 API,
it can drive the hardware device that supports the hisi_qm_v6 or
hisi_qm_v7 API.

In addition, a driver flag (RTE_UACCE_DRV_FORWARD_COMPATIBILITY_DEV) is
introduced. The driver supports forward compatibility of APIs only when
this flag is defined.

Signed-off-by: Chengwen Feng <[email protected]>
---
 drivers/bus/uacce/bus_uacce_driver.h |  5 +++
 drivers/bus/uacce/uacce.c            | 51 ++++++++++++++++++++++++++--
 2 files changed, 53 insertions(+), 3 deletions(-)

diff --git a/drivers/bus/uacce/bus_uacce_driver.h 
b/drivers/bus/uacce/bus_uacce_driver.h
index 618e0f9b76..c7445778a6 100644
--- a/drivers/bus/uacce/bus_uacce_driver.h
+++ b/drivers/bus/uacce/bus_uacce_driver.h
@@ -50,6 +50,7 @@ struct rte_uacce_device {
        char dev_root[RTE_UACCE_DEV_PATH_SIZE];  /**< Sysfs path with device 
name. */
        char cdev_path[RTE_UACCE_DEV_PATH_SIZE]; /**< Device path in devfs. */
        char api[RTE_UACCE_API_NAME_SIZE];       /**< Device context type. */
+       uint32_t api_ver;                        /**< Device api version used 
for compatibility. */
        char algs[RTE_UACCE_ALGS_NAME_SIZE];     /**< Device supported 
algorithms. */
        uint32_t flags;                          /**< Device flags. */
        int numa_node;                           /**< NUMA node connection, -1 
if unknown. */
@@ -100,8 +101,12 @@ struct rte_uacce_driver {
        rte_uacce_probe_t *probe;               /**< Device probe function. */
        rte_uacce_remove_t *remove;             /**< Device remove function. */
        const struct rte_uacce_id *id_table;    /**< ID table, NULL terminated. 
*/
+       uint32_t drv_flags;                     /**< Flags RTE_UACCE_DRV_*. */
 };
 
+/** Device driver supports forward compatibility device */
+#define RTE_UACCE_DRV_FORWARD_COMPATIBILITY_DEV        0x1
+
 /**
  * Get available queue number.
  *
diff --git a/drivers/bus/uacce/uacce.c b/drivers/bus/uacce/uacce.c
index 79f990c54c..a471edcad0 100644
--- a/drivers/bus/uacce/uacce.c
+++ b/drivers/bus/uacce/uacce.c
@@ -2,6 +2,7 @@
  * Copyright(c) 2024 HiSilicon Limited
  */
 
+#include <ctype.h>
 #include <dirent.h>
 #include <errno.h>
 #include <fcntl.h>
@@ -324,19 +325,62 @@ uacce_scan(void)
        return -1;
 }
 
+static uint32_t
+uacce_calc_api_ver(const char *api, int *offset)
+{
+       int len = strlen(api);
+       int end = len - 1;
+       unsigned long ver;
+
+       while (end >= 0 && isdigit(api[end]))
+               end--;
+
+       if (end <= 0 || end == len - 1 || api[end] != 'v')
+               return 0;
+
+       ver = strtoul(api + end + 1, NULL, 10);
+       if (ver > UINT32_MAX)
+               return 0;
+
+       if (offset != NULL)
+               *offset = end + 1;
+       return (uint32_t)ver;
+}
+
+static bool
+uacce_match_api(const struct rte_uacce_device *dev, bool forward_compat,
+               const struct rte_uacce_id *id_table)
+{
+       int dev_ver_off = 0, id_ver_off = 0;
+       uint32_t dev_ver, id_ver;
+
+       if (!forward_compat)
+               return strcmp(id_table->dev_api, dev->api) == 0;
+
+       dev_ver = uacce_calc_api_ver(dev->api, &dev_ver_off);
+       id_ver = uacce_calc_api_ver(id_table->dev_api, &id_ver_off);
+       return dev_ver > 0 && id_ver > 0 && dev_ver_off == id_ver_off &&
+               strncmp(id_table->dev_api, dev->api, dev_ver_off) == 0 &&
+               dev_ver >= id_ver;
+}
+
 static bool
-uacce_match(const struct rte_uacce_driver *dr, const struct rte_uacce_device 
*dev)
+uacce_match(const struct rte_uacce_driver *dr, struct rte_uacce_device *dev)
 {
+       bool forward_compat = !!(dr->drv_flags & 
RTE_UACCE_DRV_FORWARD_COMPATIBILITY_DEV);
+       uint32_t api_ver = uacce_calc_api_ver(dev->api, NULL);
        const struct rte_uacce_id *id_table;
        const char *map;
        uint32_t len;
 
        for (id_table = dr->id_table; id_table->dev_api != NULL; id_table++) {
-               if (strcmp(id_table->dev_api, dev->api) != 0)
+               if (!uacce_match_api(dev, forward_compat, id_table))
                        continue;
 
-               if (id_table->dev_alg == NULL)
+               if (id_table->dev_alg == NULL) {
+                       dev->api_ver = api_ver;
                        return true;
+               }
 
                /* The dev->algs's algrothims is separated by new line, for
                 * example: dev->algs could be: aaa\nbbbb\ncc, which has three
@@ -352,6 +396,7 @@ uacce_match(const struct rte_uacce_driver *dr, const struct 
rte_uacce_device *de
                if (map[len] != '\0' && map[len] != '\n')
                        continue;
 
+               dev->api_ver = api_ver;
                return true;
        }
 
-- 
2.17.1

Reply via email to