From: Weili Qian <qianweili@huawei.com> uadk supports obtaining the bandwidth utilization of specified devices and algorithms through user-space drivers. After hardware resources are initialized, the bandwidth utilization can be directly obtained through the hardware mmio space, replacing the method of reading sysfs files and reducing system calls. Signed-off-by: Weili Qian <qianweili@huawei.com> --- drv/hisi_comp.c | 39 +++++++++++++++++++++ drv/hisi_dae.c | 5 --- drv/hisi_dae.h | 1 + drv/hisi_dae_common.c | 38 +++++++++++++++++++++ drv/hisi_dae_join_gather.c | 1 + drv/hisi_hpre.c | 69 +++++++++++++++++++++++++++++++++++--- drv/hisi_qm_udrv.c | 39 +++++++++++++++++++++ drv/hisi_qm_udrv.h | 1 + drv/hisi_sec.c | 35 ++++++++++++++++++- drv/hisi_udma.c | 35 ++++++++++++++++++- include/wd_alg.h | 7 ++++ libwd.map | 1 + wd.c | 14 +++++++- wd_alg.c | 34 +++++++++++++++++++ 14 files changed, 306 insertions(+), 13 deletions(-) diff --git a/drv/hisi_comp.c b/drv/hisi_comp.c index 65dcf8e..cad21fa 100644 --- a/drv/hisi_comp.c +++ b/drv/hisi_comp.c @@ -1755,6 +1755,44 @@ static int hisi_zip_comp_recv(struct wd_alg_driver *drv, handle_t ctx, void *com return 0; } +static int hisi_zip_get_usage(void *param) +{ + struct hisi_dev_usage *zip_usage = (struct hisi_dev_usage *)param; + struct wd_alg_driver *drv = zip_usage->drv; + struct wd_ctx_config_internal *config; + struct hisi_zip_ctx *priv; + char *ctx_dev_name; + handle_t ctx = 0; + handle_t qp = 0; + __u32 i; + + if (zip_usage->alg_op_type >= drv->op_type_num) { + WD_ERR("invalid: alg_op_type %u is error!\n", zip_usage->alg_op_type); + return -WD_EINVAL; + } + + priv = (struct hisi_zip_ctx *)drv->priv; + if (!priv) + return -WD_EACCES; + + config = &priv->config; + for (i = 0; i < config->ctx_num; i++) { + ctx_dev_name = wd_ctx_get_dev_name(config->ctxs[i].ctx); + if (!strcmp(zip_usage->dev_name, ctx_dev_name)) { + ctx = config->ctxs[i].ctx; + break; + } + } + + if (ctx) + qp = (handle_t)wd_ctx_get_priv(ctx); + + if (qp) + return hisi_qm_get_usage(qp, zip_usage->alg_op_type); + + return -WD_EACCES; +} + #define GEN_ZIP_ALG_DRIVER(zip_alg_name) \ {\ .drv_name = "hisi_zip",\ @@ -1768,6 +1806,7 @@ static int hisi_zip_comp_recv(struct wd_alg_driver *drv, handle_t ctx, void *com .exit = hisi_zip_exit,\ .send = hisi_zip_comp_send,\ .recv = hisi_zip_comp_recv,\ + .get_usage = hisi_zip_get_usage, \ } static struct wd_alg_driver zip_alg_driver[] = { diff --git a/drv/hisi_dae.c b/drv/hisi_dae.c index 49387aa..d7b34c2 100644 --- a/drv/hisi_dae.c +++ b/drv/hisi_dae.c @@ -1283,11 +1283,6 @@ static int agg_hash_table_init(struct wd_alg_driver *drv, hash_table, agg_ctx->row_size); } -static int dae_get_usage(void *param) -{ - return 0; -} - static int dae_get_extend_ops(void *ops) { struct wd_agg_ops *agg_ops = (struct wd_agg_ops *)ops; diff --git a/drv/hisi_dae.h b/drv/hisi_dae.h index 050b872..f82b13c 100644 --- a/drv/hisi_dae.h +++ b/drv/hisi_dae.h @@ -220,6 +220,7 @@ int get_free_ext_addr(struct dae_extend_addr *ext_addr); void put_ext_addr(struct dae_extend_addr *ext_addr, int idx); __u32 get_data_type_size(enum dae_data_type type, __u16 data_info); int dae_decimal_precision_check(__u16 data_info, bool longdecimal); +int dae_get_usage(void *param); #ifdef __cplusplus } diff --git a/drv/hisi_dae_common.c b/drv/hisi_dae_common.c index 5cfc105..c077d1d 100644 --- a/drv/hisi_dae_common.c +++ b/drv/hisi_dae_common.c @@ -389,3 +389,41 @@ void dae_exit(struct wd_alg_driver *drv) free(priv); drv->priv = NULL; } + +int dae_get_usage(void *param) +{ + struct hisi_dev_usage *dae_usage = (struct hisi_dev_usage *)param; + struct wd_alg_driver *drv = dae_usage->drv; + struct wd_ctx_config_internal *config; + struct hisi_dae_ctx *priv; + char *ctx_dev_name; + handle_t ctx = 0; + handle_t qp = 0; + __u32 i; + + if (dae_usage->alg_op_type >= drv->op_type_num) { + WD_ERR("invalid: alg_op_type %u is error!\n", dae_usage->alg_op_type); + return -WD_EINVAL; + } + + priv = (struct hisi_dae_ctx *)drv->priv; + if (!priv) + return -WD_EACCES; + + config = &priv->config; + for (i = 0; i < config->ctx_num; i++) { + ctx_dev_name = wd_ctx_get_dev_name(config->ctxs[i].ctx); + if (!strcmp(dae_usage->dev_name, ctx_dev_name)) { + ctx = config->ctxs[i].ctx; + break; + } + } + + if (ctx) + qp = (handle_t)wd_ctx_get_priv(ctx); + + if (qp) + return hisi_qm_get_usage(qp, DAE_SQC_ALG_TYPE); + + return -WD_EACCES; +} diff --git a/drv/hisi_dae_join_gather.c b/drv/hisi_dae_join_gather.c index 63c7670..92fae1a 100644 --- a/drv/hisi_dae_join_gather.c +++ b/drv/hisi_dae_join_gather.c @@ -1007,6 +1007,7 @@ static int join_gather_get_extend_ops(void *ops) .send = join_gather_send,\ .recv = join_gather_recv,\ .get_extend_ops = join_gather_get_extend_ops,\ + .get_usage = dae_get_usage,\ } static struct wd_alg_driver join_gather_driver[] = { diff --git a/drv/hisi_hpre.c b/drv/hisi_hpre.c index f3f2451..3c41826 100644 --- a/drv/hisi_hpre.c +++ b/drv/hisi_hpre.c @@ -2777,9 +2777,68 @@ static int ecc_recv(struct wd_alg_driver *drv, handle_t ctx, void *ecc_msg) return ecc_sqe_parse((struct hisi_qp *)h_qp, msg, &hw_msg); } -static int hpre_get_usage(void *param) +static handle_t hpre_find_dev_qp(struct wd_alg_driver *drv, const char *dev_name) { - return WD_SUCCESS; + struct wd_ctx_config_internal *config; + struct hisi_hpre_ctx *priv; + char *ctx_dev_name; + handle_t ctx = 0; + handle_t qp = 0; + __u32 i; + + priv = (struct hisi_hpre_ctx *)drv->priv; + if (!priv) + return 0; + + config = &priv->config; + for (i = 0; i < config->ctx_num; i++) { + ctx_dev_name = wd_ctx_get_dev_name(config->ctxs[i].ctx); + if (!strcmp(ctx_dev_name, dev_name)) { + ctx = config->ctxs[i].ctx; + break; + } + } + + if (ctx) + qp = (handle_t)wd_ctx_get_priv(ctx); + + return qp; +} + +static int hpre_ecc_get_usage(void *param) +{ + struct hisi_dev_usage *hpre_usage = (struct hisi_dev_usage *)param; + struct wd_alg_driver *drv = hpre_usage->drv; + handle_t qp; + + if (hpre_usage->alg_op_type >= drv->op_type_num) { + WD_ERR("invalid: alg_op_type %u is error!\n", hpre_usage->alg_op_type); + return -WD_EINVAL; + } + + qp = hpre_find_dev_qp(drv, hpre_usage->dev_name); + if (qp) + return hisi_qm_get_usage(qp, HPRE_HW_V3_ECC_ALG_TYPE); + + return -WD_EACCES; +} + +static int hpre_rsa_get_usage(void *param) +{ + struct hisi_dev_usage *hpre_usage = (struct hisi_dev_usage *)param; + struct wd_alg_driver *drv = hpre_usage->drv; + handle_t qp; + + if (hpre_usage->alg_op_type >= drv->op_type_num) { + WD_ERR("invalid: alg_op_type %u is error!\n", hpre_usage->alg_op_type); + return -WD_EINVAL; + } + + qp = hpre_find_dev_qp(drv, hpre_usage->dev_name); + if (qp) + return hisi_qm_get_usage(qp, HPRE_HW_V2_ALG_TYPE); + + return -WD_EACCES; } static int ecc_sess_eops_init(struct wd_alg_driver *drv, void **params) @@ -2886,7 +2945,7 @@ static int hpre_ecc_get_extend_ops(void *ops) .exit = hpre_exit,\ .send = ecc_send,\ .recv = ecc_recv,\ - .get_usage = hpre_get_usage,\ + .get_usage = hpre_ecc_get_usage,\ .get_extend_ops = hpre_ecc_get_extend_ops,\ } @@ -2910,7 +2969,7 @@ static struct wd_alg_driver hpre_rsa_driver = { .exit = hpre_exit, .send = rsa_send, .recv = rsa_recv, - .get_usage = hpre_get_usage, + .get_usage = hpre_rsa_get_usage, }; static struct wd_alg_driver hpre_dh_driver = { @@ -2925,7 +2984,7 @@ static struct wd_alg_driver hpre_dh_driver = { .exit = hpre_exit, .send = dh_send, .recv = dh_recv, - .get_usage = hpre_get_usage, + .get_usage = hpre_rsa_get_usage, }; #ifdef WD_STATIC_DRV diff --git a/drv/hisi_qm_udrv.c b/drv/hisi_qm_udrv.c index 216b80a..a47c596 100644 --- a/drv/hisi_qm_udrv.c +++ b/drv/hisi_qm_udrv.c @@ -42,6 +42,12 @@ #define ADDR_ALIGN_64(addr) ((((uintptr_t)(addr) >> 6) + 1) << 6) +#define QM_TYPE_USAGE_OFFSET 0x1100 +#define QM_DEV_USAGE_OFFSET 16 +#define QM_CHANNEL_ADDR_INTRVL 0x4 +#define QM_MAX_DEV_USAGE 100 +#define QM_DEV_USAGE_RATE 100 + struct hisi_qm_type { __u16 qm_ver; int qm_db_offs; @@ -154,6 +160,39 @@ static struct hisi_qm_type qm_type[] = { } }; +int hisi_qm_get_usage(handle_t h_qp, __u8 type) +{ + struct hisi_qp *qp = (struct hisi_qp *)h_qp; + struct hisi_qm_queue_info *q_info; + __u16 count; + __u32 val; + int usage; + + if (!qp) + return -WD_EINVAL; + + q_info = &qp->q_info; + if (q_info->hw_type < HISI_QM_API_VER5_BASE) { + WD_ERR("invalid: device not support get usage!\n"); + return -WD_EINVAL; + } + + val = wd_ioread32(q_info->mmio_base + QM_TYPE_USAGE_OFFSET + + type * QM_CHANNEL_ADDR_INTRVL); + count = val >> QM_DEV_USAGE_OFFSET; + if (!count) { + WD_ERR("failed to get dev count usage!\n"); + return -WD_EINVAL; + } + + if (count <= (__u16)val) + return QM_MAX_DEV_USAGE; + + usage = (int)((__u16)val) * QM_DEV_USAGE_RATE / count; + + return usage; +} + static void hisi_qm_fill_sqe(const void *sqe, struct hisi_qm_queue_info *info, __u16 tail, __u16 num) { diff --git a/drv/hisi_qm_udrv.h b/drv/hisi_qm_udrv.h index f066881..a7222ce 100644 --- a/drv/hisi_qm_udrv.h +++ b/drv/hisi_qm_udrv.h @@ -210,6 +210,7 @@ int hisi_qm_get_free_sqe_num(handle_t h_qp); */ __u32 hisi_qm_get_list_size(struct wd_datalist *start_node, struct wd_datalist *end_node); +int hisi_qm_get_usage(handle_t h_qp, __u8 type); #ifdef __cplusplus } diff --git a/drv/hisi_sec.c b/drv/hisi_sec.c index e64fd5c..53bf334 100644 --- a/drv/hisi_sec.c +++ b/drv/hisi_sec.c @@ -600,7 +600,40 @@ static int aead_recv(struct wd_alg_driver *drv, handle_t ctx, void *msg) static int hisi_sec_get_usage(void *param) { - return 0; + struct hisi_dev_usage *sec_usage = (struct hisi_dev_usage *)param; + struct wd_alg_driver *drv = sec_usage->drv; + struct wd_ctx_config_internal *config; + struct hisi_sec_ctx *priv; + char *ctx_dev_name; + handle_t ctx = 0; + handle_t qp = 0; + __u32 i; + + if (sec_usage->alg_op_type >= drv->op_type_num) { + WD_ERR("invalid: alg_op_type %u is error!\n", sec_usage->alg_op_type); + return -WD_EINVAL; + } + + priv = (struct hisi_sec_ctx *)drv->priv; + if (!priv) + return -WD_EACCES; + + config = &priv->config; + for (i = 0; i < config->ctx_num; i++) { + ctx_dev_name = wd_ctx_get_dev_name(config->ctxs[i].ctx); + if (!strcmp(sec_usage->dev_name, ctx_dev_name)) { + ctx = config->ctxs[i].ctx; + break; + } + } + + if (ctx) + qp = (handle_t)wd_ctx_get_priv(ctx); + + if (qp) + return hisi_qm_get_usage(qp, 0); + + return -WD_EACCES; } static int eops_param_check(struct wd_alg_driver *drv, struct wd_mm_ops *mm_ops) diff --git a/drv/hisi_udma.c b/drv/hisi_udma.c index 37f0550..a9f5607 100644 --- a/drv/hisi_udma.c +++ b/drv/hisi_udma.c @@ -521,7 +521,40 @@ static void udma_exit(struct wd_alg_driver *drv) static int udma_get_usage(void *param) { - return 0; + struct hisi_dev_usage *udma_usage = (struct hisi_dev_usage *)param; + struct wd_alg_driver *drv = udma_usage->drv; + struct wd_ctx_config_internal *config; + struct hisi_udma_ctx *priv; + char *ctx_dev_name; + handle_t ctx = 0; + handle_t qp = 0; + __u32 i; + + if (udma_usage->alg_op_type >= drv->op_type_num) { + WD_ERR("invalid: alg_op_type %u is error!\n", udma_usage->alg_op_type); + return -WD_EINVAL; + } + + priv = (struct hisi_udma_ctx *)drv->priv; + if (!priv) + return -WD_EACCES; + + config = &priv->config; + for (i = 0; i < config->ctx_num; i++) { + ctx_dev_name = wd_ctx_get_dev_name(config->ctxs[i].ctx); + if (!strcmp(udma_usage->dev_name, ctx_dev_name)) { + ctx = config->ctxs[i].ctx; + break; + } + } + + if (ctx) + qp = (handle_t)wd_ctx_get_priv(ctx); + + if (qp) + return hisi_qm_get_usage(qp, UDMA_ALG_TYPE); + + return -WD_EACCES; } static struct wd_alg_driver udma_driver = { diff --git a/include/wd_alg.h b/include/wd_alg.h index 848bdf1..7a3ae5f 100644 --- a/include/wd_alg.h +++ b/include/wd_alg.h @@ -115,6 +115,12 @@ struct wd_alg_driver { int (*get_extend_ops)(void *ops); }; +struct hisi_dev_usage { + struct wd_alg_driver *drv; + const char *dev_name; + __u8 alg_op_type; +}; + /* * wd_alg_driver_register() - Register a device driver. * @wd_alg_driver: a device driver that supports an algorithm. @@ -179,6 +185,7 @@ int wd_alg_driver_init(struct wd_alg_driver *drv, void *conf); void wd_alg_driver_exit(struct wd_alg_driver *drv); int wd_alg_driver_send(struct wd_alg_driver *drv, handle_t ctx, void *msg); int wd_alg_driver_recv(struct wd_alg_driver *drv, handle_t ctx, void *msg); +int wd_alg_get_dev_usage(const char *dev_name, const char *alg_type, __u8 op_type); int wd_get_alg_type(const char *alg_name, char *alg_type); struct wd_alg_list *wd_get_alg_head(void); diff --git a/libwd.map b/libwd.map index aeba098..1267a8d 100644 --- a/libwd.map +++ b/libwd.map @@ -54,6 +54,7 @@ global: wd_alg_driver_exit; wd_alg_driver_send; wd_alg_driver_recv; + wd_alg_get_dev_usage; wd_get_alg_type; wd_find_ctx; diff --git a/wd.c b/wd.c index 2b2a15e..bf83ca1 100644 --- a/wd.c +++ b/wd.c @@ -1129,6 +1129,8 @@ static int wd_read_dev_usage(struct uacce_dev *dev, const char *alg_name, __u8 a int wd_get_dev_usage(struct uacce_dev *dev, const char *alg_name, __u8 alg_op_type) { + char *dev_name; + int ret; if (!dev || !alg_name) { WD_ERR("invalid: dev or alg name is NULL!\n"); return -WD_EINVAL; @@ -1139,5 +1141,15 @@ int wd_get_dev_usage(struct uacce_dev *dev, const char *alg_name, __u8 alg_op_ty return -WD_EINVAL; } - return wd_read_dev_usage(dev, alg_name, alg_op_type); + dev_name = strrchr(dev->char_dev_path, '/'); + if (!dev_name) { + WD_ERR("failed to get dev_nmae!\n"); + return -WD_EINVAL; + } + + ret = wd_alg_get_dev_usage(dev_name + 1, alg_name, alg_op_type); + if (ret == -WD_EACCES) + return wd_read_dev_usage(dev, alg_name, alg_op_type); + + return ret; } diff --git a/wd_alg.c b/wd_alg.c index 919483b..1e4f14a 100644 --- a/wd_alg.c +++ b/wd_alg.c @@ -485,3 +485,37 @@ int wd_alg_driver_recv(struct wd_alg_driver *drv, handle_t ctx, void *msg) return drv->recv(drv, ctx, msg); } +int wd_alg_get_dev_usage(const char *dev_name, const char *alg_type, __u8 alg_op_type) +{ + struct wd_alg_list *pnext = alg_list_head.next; + struct hisi_dev_usage dev_usage; + struct wd_alg_driver *drv; + size_t len; + + if (!dev_name || !alg_type) { + WD_ERR("dev_name or alg_type is NULL!\n"); + return -WD_EINVAL; + } + + while (pnext) { + len = strlen(pnext->drv_name); + if (!strncmp(dev_name, pnext->drv_name, len) && *(dev_name + len) == '-' && + !strcmp(alg_type, pnext->alg_type) && pnext->drv->priv) + break; + + pnext = pnext->next; + } + + if (!pnext) + return -WD_EACCES; + + drv = pnext->drv; + if (!drv->get_usage) + return -WD_EINVAL; + + dev_usage.drv = drv; + dev_usage.alg_op_type = alg_op_type; + dev_usage.dev_name = dev_name; + + return drv->get_usage(&dev_usage); +} -- 2.33.0