According to the needs of device driver registration. Algorithm-driven priorities and types need to be distinguished. In addition, the name memory space of the algorithm linked list needs to be dynamically allocated, and direct pointer references will cause life cycle mismatches and errors. Finally, fix the code that matches part of the registered device with the driver.
Signed-off-by: Longfang Liu liulongfang@huawei.com --- include/wd_alg.h | 52 +++++++++++++++++- wd_alg.c | 139 ++++++++++++++++++++++++++++++++++------------- 2 files changed, 150 insertions(+), 41 deletions(-)
diff --git a/include/wd_alg.h b/include/wd_alg.h index e25e191..0f446cf 100644 --- a/include/wd_alg.h +++ b/include/wd_alg.h @@ -20,6 +20,9 @@ extern "C" { #endif
#define handle_t uintptr_t +#define ALG_NAME_SIZE 128 +#define DEV_NAME_LEN 128 + enum alg_priority { UADK_ALG_SOFT = 0x0, UADK_ALG_CE_INSTR = 0x1, @@ -31,6 +34,13 @@ enum alg_priority { * @drv_name: name of the current device driver * @alg_name: name of the algorithm supported by the driver * @priority: priority of the type of algorithm supported by the driver + * the larger the value of priority, the higher the priority of the driver, + * it will be used first when selecting a driver. + * soft calculation can be defined as 0. + * hard calculation can be defined as a value above 100. + * instruction acceleration can define a higher value according to + * the performance situation, such as 400. + * @calc_type: the calculation method of algorithm supported by the driver * @queue_num: number of device queues required by the device to * execute the algorithm task * @op_type_num: number of modes in which the device executes the @@ -52,6 +62,7 @@ struct wd_alg_driver { const char *drv_name; const char *alg_name; int priority; + int calc_type; int queue_num; int op_type_num; int priv_size; @@ -64,25 +75,62 @@ struct wd_alg_driver { int (*get_usage)(void *param); };
+/** + * wd_alg_driver_register() - Register a device driver. + * @wd_alg_driver: a device driver that supports an algorithm. + * + * Return the execution result, non-zero means error code. + */ int wd_alg_driver_register(struct wd_alg_driver *drv); void wd_alg_driver_unregister(struct wd_alg_driver *drv);
+/** + * @alg_name: name of the algorithm supported by the driver + * @drv_name: name of the current device driver + * @available: Indicates whether the current driver still has resources available + * @priority: priority of the type of algorithm supported by the driver + * @calc_type: the calculation method of algorithm supported by the driver + * @refcnt: the number of times the algorithm driver is being cited by the task + * + * @drv: device Drivers Supporting Algorithms + * @next: pointer to the next node of the algorithm linked list + */ struct wd_alg_list { - const char *alg_name; - const char *drv_name; + char alg_name[ALG_NAME_SIZE]; + char drv_name[DEV_NAME_LEN]; bool available; int priority; + int calc_type; int refcnt;
struct wd_alg_driver *drv; struct wd_alg_list *next; };
+/** + * wd_request_drv() - Apply for an algorithm driver. + * @alg_name: task algorithm name. + * @hw_mask: the flag of shield hardware device drivers. + * + * Returns the applied algorithm driver, non means error. + */ struct wd_alg_driver *wd_request_drv(const char *alg_name, bool hw_mask); void wd_release_drv(struct wd_alg_driver *drv);
+/** + * wd_drv_alg_support() - Check the algorithms supported by the driver. + * @alg_name: task algorithm name. + * @drv: a device driver that supports an algorithm. + * + * Return check result. + */ bool wd_drv_alg_support(const char *alg_name, struct wd_alg_driver *drv); + +/** + * wd_enable_drv() - Re-enable use of the current device driver. + * @drv: a device driver that supports an algorithm. + */ void wd_enable_drv(struct wd_alg_driver *drv); void wd_disable_drv(struct wd_alg_driver *drv);
diff --git a/wd_alg.c b/wd_alg.c index 5e4edaf..ffcadac 100644 --- a/wd_alg.c +++ b/wd_alg.c @@ -16,11 +16,55 @@ #include "wd_alg.h"
#define SYS_CLASS_DIR "/sys/class/uacce" +#define SVA_FILE_NAME "flags" +#define DEV_SVA_SIZE 32 +#define STR_DECIMAL 0xA + static struct wd_alg_list alg_list_head; static struct wd_alg_list *alg_list_tail = &alg_list_head;
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+static bool wd_check_dev_sva(const char *dev_name) +{ + char dev_path[PATH_MAX] = {'\0'}; + char buf[DEV_SVA_SIZE] = {'\0'}; + unsigned int val; + ssize_t ret; + int fd; + + ret = snprintf(dev_path, PATH_STR_SIZE, "%s/%s/%s", SYS_CLASS_DIR, + dev_name, SVA_FILE_NAME); + if (ret < 0) { + WD_ERR("failed to snprintf, device name: %s!\n", dev_name); + return false; + } + + /** + * The opened file is the specified device driver file. + * no need for realpath processing. + */ + fd = open(dev_path, O_RDONLY, 0); + if (fd < 0) { + WD_ERR("failed to open %s(%d)!\n", dev_path, -errno); + return false; + } + + ret = read(fd, buf, DEV_SVA_SIZE - 1); + if (ret <= 0) { + WD_ERR("failed to read anything at %s!\n", dev_path); + close(fd); + return false; + } + close(fd); + + val = strtol(buf, NULL, STR_DECIMAL); + if (val & UACCE_DEV_SVA) + return true; + + return false; +} + static bool wd_check_accel_dev(const char *dev_name) { struct dirent *dev_dir; @@ -37,7 +81,8 @@ static bool wd_check_accel_dev(const char *dev_name) !strncmp(dev_dir->d_name, "..", LINUX_PRTDIR_SIZE)) continue;
- if (!strncmp(dev_dir->d_name, dev_name, strlen(dev_name))) { + if (!strncmp(dev_dir->d_name, dev_name, strlen(dev_name)) && + wd_check_dev_sva(dev_dir->d_name)) { closedir(wd_class); return true; } @@ -47,6 +92,46 @@ static bool wd_check_accel_dev(const char *dev_name) return false; }
+static bool wd_alg_check_available(int calc_type, const char *dev_name) +{ + bool ret = false; + + switch (calc_type) { + case UADK_ALG_SOFT: + break; + /* Should find the CPU if not support CE */ + case UADK_ALG_CE_INSTR: + break; + /* Should find the CPU if not support SVE */ + case UADK_ALG_SVE_INSTR: + break; + /* Check if the current driver has device support */ + case UADK_ALG_HW: + ret = wd_check_accel_dev(dev_name); + break; + } + + return ret; +} + +static bool wd_alg_driver_match(struct wd_alg_driver *drv, + struct wd_alg_list *node) +{ + if (strcmp(drv->alg_name, node->alg_name)) + return false; + + if (strcmp(drv->drv_name, node->drv_name)) + return false; + + if (drv->priority != node->priority) + return false; + + if (drv->calc_type != node->calc_type) + return false; + + return true; +} + int wd_alg_driver_register(struct wd_alg_driver *drv) { struct wd_alg_list *new_alg; @@ -62,24 +147,18 @@ int wd_alg_driver_register(struct wd_alg_driver *drv) return -WD_ENOMEM; }
- new_alg->alg_name = drv->alg_name; - new_alg->drv_name = drv->drv_name; + strncpy(new_alg->alg_name, drv->alg_name, ALG_NAME_SIZE - 1); + strncpy(new_alg->drv_name, drv->drv_name, DEV_NAME_LEN - 1); new_alg->priority = drv->priority; + new_alg->calc_type = drv->calc_type; new_alg->drv = drv; new_alg->refcnt = 0; new_alg->next = NULL;
- if (drv->priority == UADK_ALG_HW) { - /* If not find dev, remove this driver node */ - new_alg->available = wd_check_accel_dev(drv->drv_name); - if (!new_alg->available) { - free(new_alg); - WD_ERR("failed to find alg driver's device!\n"); - return -WD_ENODEV; - } - } else { - /* Should find the CPU if not support SVE or CE */ - new_alg->available = true; + new_alg->available = wd_alg_check_available(drv->calc_type, drv->drv_name); + if (!new_alg->available) { + free(new_alg); + return -WD_ENODEV; }
pthread_mutex_lock(&mutex); @@ -101,11 +180,8 @@ void wd_alg_driver_unregister(struct wd_alg_driver *drv)
pthread_mutex_lock(&mutex); while (pnext) { - if (!strcmp(drv->alg_name, pnext->alg_name) && - !strcmp(drv->drv_name, pnext->drv_name) && - drv->priority == pnext->priority) { + if (wd_alg_driver_match(drv, pnext)) break; - } npre = pnext; pnext = pnext->next; } @@ -160,21 +236,12 @@ void wd_enable_drv(struct wd_alg_driver *drv)
pthread_mutex_lock(&mutex); while (pnext) { - if (!strcmp(drv->alg_name, pnext->alg_name) && - !strcmp(drv->drv_name, pnext->drv_name) && - drv->priority == pnext->priority) { + if (wd_alg_driver_match(drv, pnext)) break; - } pnext = pnext->next; }
- if (drv->priority == UADK_ALG_HW) { - /* If not find dev, remove this driver node */ - pnext->available = wd_check_accel_dev(drv->drv_name); - } else { - /* Should find the CPU if not support SVE or CE */ - pnext->available = true; - } + pnext->available = wd_alg_check_available(drv->calc_type, drv->drv_name); pthread_mutex_unlock(&mutex); }
@@ -188,11 +255,8 @@ void wd_disable_drv(struct wd_alg_driver *drv)
pthread_mutex_lock(&mutex); while (pnext) { - if (!strcmp(drv->alg_name, pnext->alg_name) && - !strcmp(drv->drv_name, pnext->drv_name) && - drv->priority == pnext->priority) { + if (wd_alg_driver_match(drv, pnext) && pnext->available) break; - } pnext = pnext->next; }
@@ -217,7 +281,7 @@ struct wd_alg_driver *wd_request_drv(const char *alg_name, bool hw_mask) pthread_mutex_lock(&mutex); while (pnext) { /* hw_mask true mean not to used hardware dev */ - if (hw_mask && pnext->drv->priority == UADK_ALG_HW) { + if (hw_mask && pnext->drv->calc_type == UADK_ALG_HW) { pnext = pnext->next; continue; } @@ -249,17 +313,14 @@ void wd_release_drv(struct wd_alg_driver *drv)
pthread_mutex_lock(&mutex); while (pnext) { - if (!strcmp(drv->alg_name, pnext->alg_name) && - !strcmp(drv->drv_name, pnext->drv_name) && - drv->priority == pnext->priority) { + if (wd_alg_driver_match(drv, pnext) && pnext->refcnt > 0) { select_node = pnext; break; } pnext = pnext->next; }
- if (select_node && select_node->refcnt > 0) + if (select_node) select_node->refcnt--; pthread_mutex_unlock(&mutex); } -