在 2022/11/25 14:46, fanghao (A) 写道:
在 2022/11/24 15:43, liulongfang 写道:
According to the logical layering of UADK, the device driver has been updated from the previous fixed binding HiSilicon accelerator to the dynamic registration method through the algorithm linked list method.
After the update, it can support the use of instruction acceleration and third-party device drivers.
Signed-off-by: liulongfang liulongfang@huawei.com
Makefile.am | 4 +- include/wd_alg.h | 85 +++++++++++++ include/wd_alg_common.h | 1 + libwd.map | 8 ++ wd_alg.c | 265 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 361 insertions(+), 2 deletions(-) create mode 100644 include/wd_alg.h create mode 100644 wd_alg.c
diff --git a/Makefile.am b/Makefile.am index 4ef5c2c..5b45626 100644 --- a/Makefile.am +++ b/Makefile.am @@ -33,7 +33,7 @@ AM_CFLAGS+= -DUADK_RELEASED_TIME=""Released ${MONTH} ${DAY}, ${YEAR}"" pkginclude_HEADERS = include/wd.h include/wd_cipher.h include/wd_aead.h \ include/wd_comp.h include/wd_dh.h include/wd_digest.h \ include/wd_rsa.h include/uacce.h include/wd_alg_common.h \ - include/wd_ecc.h include/wd_sched.h + include/wd_ecc.h include/wd_sched.h include/wd_alg.h nobase_pkginclude_HEADERS = v1/wd.h v1/wd_cipher.h v1/wd_aead.h v1/uacce.h v1/wd_dh.h \ v1/wd_digest.h v1/wd_rsa.h v1/wd_bmm.h @@ -41,7 +41,7 @@ nobase_pkginclude_HEADERS = v1/wd.h v1/wd_cipher.h v1/wd_aead.h v1/uacce.h v1/wd lib_LTLIBRARIES=libwd.la libwd_comp.la libwd_crypto.la libhisi_zip.la \ libhisi_hpre.la libhisi_sec.la -libwd_la_SOURCES=wd.c wd_mempool.c wd.h \ +libwd_la_SOURCES=wd.c wd_mempool.c wd.h wd_alg.c wd_alg.h \ v1/wd.c v1/wd.h v1/wd_adapter.c v1/wd_adapter.h \ v1/wd_rng.c v1/wd_rng.h \ v1/wd_rsa.c v1/wd_rsa.h \ diff --git a/include/wd_alg.h b/include/wd_alg.h new file mode 100644 index 0000000..965c0aa --- /dev/null +++ b/include/wd_alg.h @@ -0,0 +1,85 @@ +// SPDX-License-Identifier: Apache-2.0 +/*
- Copyright 2020-2021 Huawei Technologies Co.,Ltd. All rights reserved.
- Copyright 2020-2021 Linaro ltd.
2022, why start 2020?
- */
+#ifndef __WD_ALG_H +#define __WD_ALG_H +#include <errno.h> +#include <fcntl.h> +#include <stdbool.h> +#include <stdint.h> +#include <stdio.h> +#include <string.h> +#include <syslog.h> +#include <unistd.h> +#include <asm/types.h>
check if header not used
+#ifdef __cplusplus +extern "C" { +#endif
+#define handle_t uintptr_t +enum alg_priority { + UADK_ALG_SOFT = 0x0, + UADK_ALG_CE_INSTR = 0x1, + UADK_ALG_SVE_INSTR = 0x2, + UADK_ALG_HW = 0x3 +};
+/*
- @init: callback interface for initializing device drivers
- @exit: callback interface for destroying device drivers
- @send: callback interface used to send task packets to
- * hardware devices.
- @recv: callback interface used to retrieve the calculation
- * result of the task packets from the hardware device.
- @get_usage: callback interface used to obtain the
- * utilization rate of hardware devices.
The comment is incomplete.
- */
+struct wd_alg_driver { + const char *drv_name; + const char *alg_name; + int priority; + int queue_num; + int op_type_num; + int priv_size; + handle_t fallback;
+ int (*init)(void *conf, void *priv); + void (*exit)(void *priv); + int (*send)(handle_t ctx, void *drv_msg); + int (*recv)(handle_t ctx, void *drv_msg); + int (*get_usage)(void *param); +};
+int wd_alg_driver_register(struct wd_alg_driver *drv); +void wd_alg_driver_unregister(struct wd_alg_driver *drv);
+struct wd_alg_list { + const char *alg_name; + const char *drv_name; + int priority;
these have defined in wd_alg_driver *drv.
You can see this by trying to change it after you read it yourself. The list operation without this part of ALG will be particularly complicated.
I currently keep it to ensure the simplicity and efficiency of list queries.
Thanks, Longfang.
+ bool available; + int refcnt;
+ struct wd_alg_driver *drv; + struct wd_alg_list *next; +};
+struct wd_alg_driver *wd_request_drv(const char *alg_name, bool hw_mask); +void wd_release_drv(struct wd_alg_driver *drv);
+int wd_drv_alg_support(const char *alg_name, + struct wd_alg_driver *drv); +void wd_enable_drv(struct wd_alg_driver *drv); +void wd_disable_drv(struct wd_alg_driver *drv);
+struct wd_alg_list *wd_get_alg_head(void);
+#ifdef __cplusplus +} +#endif
+#endif diff --git a/include/wd_alg_common.h b/include/wd_alg_common.h index 7a9b739..6938e50 100644 --- a/include/wd_alg_common.h +++ b/include/wd_alg_common.h @@ -10,6 +10,7 @@ #include <pthread.h> #include <stdbool.h> #include "wd.h" +#include "wd_alg.h" #ifdef __cplusplus extern "C" { diff --git a/libwd.map b/libwd.map index 459f9ba..5522ec0 100644 --- a/libwd.map +++ b/libwd.map @@ -41,5 +41,13 @@ global: wd_add_dev_to_list; wd_find_dev_by_numa; + wd_alg_driver_register; + wd_alg_driver_unregister; + wd_request_drv; + wd_release_drv; + wd_drv_alg_support; + wd_enable_drv; + wd_disable_drv; + wd_get_alg_head; local: *; }; diff --git a/wd_alg.c b/wd_alg.c new file mode 100644 index 0000000..2cc9d1e --- /dev/null +++ b/wd_alg.c @@ -0,0 +1,265 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +/*
- Copyright 2020-2021 Huawei Technologies Co.,Ltd. All rights reserved.
- Copyright 2020-2021 Linaro ltd.
Same as above
- */
+#define _GNU_SOURCE +#include <ctype.h> +#include <dirent.h> +#include <errno.h> +#include <stdbool.h> +#include <stdlib.h> +#include <string.h> +#include <pthread.h>
Same as above
+#include "wd.h" +#include "wd_alg.h"
+#define SYS_CLASS_DIR "/sys/class/uacce" +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;
+bool wd_check_accel_dev(const char *drv_name)
static bool wd_check_accel_dev() ?
+{ + struct dirent *dev_dir; + DIR *wd_class;
+ wd_class = opendir(SYS_CLASS_DIR); + if (!wd_class) { + WD_ERR("UADK framework isn't enabled in system!\n"); + return NULL; + }
+ while ((dev_dir = readdir(wd_class)) != NULL) { + if (!strncmp(dev_dir->d_name, ".", LINUX_CRTDIR_SIZE) || + !strncmp(dev_dir->d_name, "..", LINUX_PRTDIR_SIZE)) + continue;
+ if (!strncmp(dev_dir->d_name, drv_name, strlen(drv_name))) { + closedir(wd_class); + return true; + } + } + closedir(wd_class);
+ return false; +}
+int wd_alg_driver_register(struct wd_alg_driver *drv) +{ + struct wd_alg_list *new_alg;
+ if (!drv) { + WD_ERR("invalid: register drv is NULL!\n"); + return -WD_ENOMEM;
WD_INVAL maybe better?
+ }
+ new_alg = calloc(1, sizeof(struct wd_alg_list)); + if (!new_alg) { + WD_ERR("faild to alloc alg driver memory!\n"); + return -WD_ENOMEM; + }
+ new_alg->alg_name = drv->alg_name; + new_alg->drv_name = drv->drv_name; + new_alg->priority = drv->priority; + new_alg->drv = drv; + new_alg->refcnt = 0; + new_alg->next = NULL;
+ if (drv->priority == UADK_ALG_HW) {
Normally use the digit indicate priority. but here use ALG_HW/ ALG_SOFT. So: drv->type == 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("faild 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; + }
+ pthread_mutex_lock(&mutex); + alg_list_tail->next = new_alg; + alg_list_tail = new_alg; + pthread_mutex_unlock(&mutex);
+ WD_ERR("Successful to register %s alg!\n", drv->alg_name)
remove or not use WD_ERR
+ return 0; +}
+void wd_alg_driver_unregister(struct wd_alg_driver *drv) +{ + struct wd_alg_list *npre = &alg_list_head; + struct wd_alg_list *pnext = npre->next;
+ /* Alg driver list has no drivers */ + if (!pnext || !drv) + return;
+ 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) { + break; + } + npre = pnext; + pnext = pnext->next; + }
+ if (pnext->refcnt > 0) { + WD_ERR("driver<%s> still in used: %d\n", pnext->drv_name, pnext->refcnt); + pthread_mutex_unlock(&mutex); + return; + }
+ if (pnext == alg_list_tail) + alg_list_tail = npre;
+ npre->next = pnext->next; + free(pnext); + pthread_mutex_unlock(&mutex);
+ WD_ERR("Successful to unregister %s alg!\n", drv->alg_name); +}
+struct wd_alg_list *wd_get_alg_head(void) +{ + return &alg_list_head; +}
+int wd_drv_alg_support(const char *alg_name, + struct wd_alg_driver *drv) +{ + struct wd_alg_list *head = &alg_list_head; + struct wd_alg_list *pnext = head->next;
+ while (pnext) { + if (!strcmp(alg_name, pnext->alg_name) && + pnext->drv == drv) { + return 0;
true
+ } + pnext = pnext->next; + }
+ return -WD_EINVAL;
false
+}
+void wd_enable_drv(struct wd_alg_driver *drv) +{ + struct wd_alg_list *head = &alg_list_head; + struct wd_alg_list *pnext = head->next;
+ if (!pnext || !drv) + return;
+ 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) { + 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; + } + pthread_mutex_unlock(&mutex); +}
+void wd_disable_drv(struct wd_alg_driver *drv) +{ + struct wd_alg_list *head = &alg_list_head; + struct wd_alg_list *pnext = head->next;
+ if (!pnext || !drv) + return;
+ 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) { + break; + } + pnext = pnext->next; + }
+ pnext->available = false; + pthread_mutex_unlock(&mutex); +}
wd_enable_drv() and wd_disable_drv()
how to use them? if no use need to remove.
+struct wd_alg_driver *wd_request_drv(const char *alg_name, bool hw_mask) +{ + struct wd_alg_list *head = &alg_list_head; + struct wd_alg_list *pnext = head->next; + struct wd_alg_list *select_node = NULL; + struct wd_alg_driver *drv = NULL; + int tmp_priority = -1;
+ if (!pnext || !alg_name) { + WD_ERR("invalid: request alg param is error!\n"); + return NULL; + }
+ /* Check the list to get an best driver */ + pthread_mutex_lock(&mutex); + while (pnext) { + /* hw_mask true mean not to used hardware dev */ + if (hw_mask && pnext->drv->priority == UADK_ALG_HW) { + pnext = pnext->next; + continue; + }
+ if (!strcmp(alg_name, pnext->alg_name) && pnext->available && + pnext->drv->priority > tmp_priority) { + tmp_priority = pnext->drv->priority; + select_node = pnext; + drv = pnext->drv; + } + pnext = pnext->next; + }
+ if (select_node) + select_node->refcnt++; + pthread_mutex_unlock(&mutex);
+ return drv; +}
+void wd_release_drv(struct wd_alg_driver *drv) +{ + struct wd_alg_list *head = &alg_list_head; + struct wd_alg_list *pnext = head->next;
+ if (!pnext || !drv) + return;
+ 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) { + break; + } + pnext = pnext->next; + }
+ if (pnext->refcnt > 0) { + pnext->refcnt--; + } + pthread_mutex_unlock(&mutex); +}
.