This patchset is the preparation for the software algorithm. UADK will support the software algorithm later.
Weili Qian (3): uadk/sec: move function to wd_digest_drv.h uadk/digest: add partial_block to store partial data uadk/digest: add wd_ctx_spin_lock function
drv/hisi_sec.c | 52 +++++++++-------------------------- include/drv/wd_digest_drv.h | 31 ++++++++++++++++++++- include/wd_util.h | 23 ++++++++++++++++ wd_digest.c | 54 +++++++++++++++++++++++-------------- 4 files changed, 100 insertions(+), 60 deletions(-)
Since function get_hash_bd_type() will be used in multiple files, move it to wd_digest_drv.h. And rename get_hash_bd_type to get_hash_msg_type to make the function generic.
Signed-off-by: Weili Qian qianweili@huawei.com --- drv/hisi_sec.c | 52 ++++++++++--------------------------- include/drv/wd_digest_drv.h | 27 ++++++++++++++++++- 2 files changed, 39 insertions(+), 40 deletions(-)
diff --git a/drv/hisi_sec.c b/drv/hisi_sec.c index 5b114f6..9da21a8 100644 --- a/drv/hisi_sec.c +++ b/drv/hisi_sec.c @@ -200,13 +200,6 @@ enum sec_c_width { C_WIDTH_CS3 = 0x3, };
-enum hash_bd_type { - HASH_SINGLE_BD, - HASH_FRIST_BD, - HASH_MIDDLE_BD, - HASH_END_BD, -}; - struct hisi_sec_ctx { struct wd_ctx_config_internal config; }; @@ -1549,29 +1542,10 @@ static int long_hash_param_check(handle_t h_qp, struct wd_digest_msg *msg) return 0; }
-static enum hash_bd_type get_hash_bd_type(struct wd_digest_msg *msg) -{ - /* - * [has_next , iv_bytes] - * [ 1 , 0 ] = long hash(frist bd) - * [ 1 , 1 ] = long hash(middle bd) - * [ 0 , 1 ] = long hash(end bd) - * [ 0 , 0 ] = block hash(single bd) - */ - if (msg->has_next && !msg->iv_bytes) - return HASH_FRIST_BD; - else if (msg->has_next && msg->iv_bytes) - return HASH_MIDDLE_BD; - else if (!msg->has_next && msg->iv_bytes) - return HASH_END_BD; - else - return HASH_SINGLE_BD; -} - static int fill_digest_long_hash(handle_t h_qp, struct wd_digest_msg *msg, struct hisi_sec_sqe *sqe) { - enum hash_bd_type bd_type = get_hash_bd_type(msg); + enum hash_block_type block_type = get_hash_block_type(msg); __u64 total_bits; int ret;
@@ -1579,20 +1553,20 @@ static int fill_digest_long_hash(handle_t h_qp, struct wd_digest_msg *msg, if (ret) return ret;
- if (bd_type == HASH_FRIST_BD) { + if (block_type == HASH_FRIST_BLOCK) { /* Long hash first */ sqe->ai_apd_cs = AI_GEN_INNER; sqe->ai_apd_cs |= AUTHPAD_NOPAD << AUTHPAD_OFFSET; }
- if (bd_type == HASH_MIDDLE_BD) { + if (block_type == HASH_MIDDLE_BLOCK) { /* Long hash middle */ sqe->ai_apd_cs = AI_GEN_IVIN_ADDR; sqe->ai_apd_cs |= AUTHPAD_NOPAD << AUTHPAD_OFFSET; sqe->type2.a_ivin_addr = sqe->type2.mac_addr; }
- if (bd_type == HASH_END_BD) { + if (block_type == HASH_END_BLOCK) { /* Long hash end */ sqe->ai_apd_cs = AI_GEN_IVIN_ADDR; sqe->ai_apd_cs |= AUTHPAD_PAD << AUTHPAD_OFFSET; @@ -1658,16 +1632,16 @@ static int digest_long_bd_align_check(struct wd_digest_msg *msg)
static int digest_bd2_type_check(struct wd_digest_msg *msg) { - enum hash_bd_type type = get_hash_bd_type(msg); + enum hash_block_type type = get_hash_block_type(msg);
/* Long hash first and middle bd */ - if (type == HASH_FRIST_BD || type == HASH_MIDDLE_BD) { + if (type == HASH_FRIST_BLOCK || type == HASH_MIDDLE_BLOCK) { WD_ERR("hardware v2 not supports 0 size in long hash!\n"); return -WD_EINVAL; }
/* Block mode hash bd */ - if (type == HASH_SINGLE_BD) { + if (type == HASH_SINGLE_BLOCK) { WD_ERR("hardware v2 not supports 0 size in block hash!\n"); return -WD_EINVAL; } @@ -1677,9 +1651,9 @@ static int digest_bd2_type_check(struct wd_digest_msg *msg)
static int digest_bd3_type_check(struct wd_digest_msg *msg) { - enum hash_bd_type type = get_hash_bd_type(msg); + enum hash_block_type type = get_hash_block_type(msg); /* Long hash first and middle bd */ - if (type == HASH_FRIST_BD || type == HASH_MIDDLE_BD) { + if (type == HASH_FRIST_BLOCK || type == HASH_MIDDLE_BLOCK) { WD_ERR("invalid: hardware v3 not supports 0 size in long hash!\n"); return -WD_EINVAL; } @@ -1920,7 +1894,7 @@ static int aes_auth_long_hash_check(struct wd_digest_msg *msg) static int fill_digest_long_hash3(handle_t h_qp, struct wd_digest_msg *msg, struct hisi_sec_sqe3 *sqe) { - enum hash_bd_type bd_type = get_hash_bd_type(msg); + enum hash_block_type block_type = get_hash_block_type(msg); __u64 total_bits; int ret;
@@ -1932,20 +1906,20 @@ static int fill_digest_long_hash3(handle_t h_qp, struct wd_digest_msg *msg, if (ret) return ret;
- if (bd_type == HASH_FRIST_BD) { + if (block_type == HASH_FRIST_BLOCK) { /* Long hash first */ sqe->auth_mac_key |= AI_GEN_INNER << SEC_AI_GEN_OFFSET_V3; sqe->stream_scene.stream_auth_pad = AUTHPAD_NOPAD; }
- if (bd_type == HASH_MIDDLE_BD) { + if (block_type == HASH_MIDDLE_BLOCK) { /* Long hash middle */ sqe->auth_mac_key |= AI_GEN_IVIN_ADDR << SEC_AI_GEN_OFFSET_V3; sqe->stream_scene.stream_auth_pad = AUTHPAD_NOPAD; sqe->auth_ivin.a_ivin_addr = sqe->mac_addr; }
- if (bd_type == HASH_END_BD) { + if (block_type == HASH_END_BLOCK) { /* Long hash end */ sqe->auth_mac_key |= AI_GEN_IVIN_ADDR << SEC_AI_GEN_OFFSET_V3; sqe->stream_scene.stream_auth_pad = AUTHPAD_PAD; diff --git a/include/drv/wd_digest_drv.h b/include/drv/wd_digest_drv.h index 3c4477d..304b506 100644 --- a/include/drv/wd_digest_drv.h +++ b/include/drv/wd_digest_drv.h @@ -10,7 +10,13 @@ extern "C" { #endif
-/* fixme wd_digest_msg */ +enum hash_block_type { + HASH_FRIST_BLOCK, + HASH_MIDDLE_BLOCK, + HASH_END_BLOCK, + HASH_SINGLE_BLOCK, +}; + struct wd_digest_msg { struct wd_digest_req req; /* request identifier */ @@ -51,6 +57,25 @@ struct wd_digest_msg { __u64 long_data_len; };
+static inline enum hash_block_type get_hash_block_type(struct wd_digest_msg *msg) +{ + /* + * [has_next , iv_bytes] + * [ 1 , 0 ] = long hash(frist bd) + * [ 1 , 1 ] = long hash(middle bd) + * [ 0 , 1 ] = long hash(end bd) + * [ 0 , 0 ] = block hash(single bd) + */ + if (msg->has_next && !msg->iv_bytes) + return HASH_FRIST_BLOCK; + else if (msg->has_next && msg->iv_bytes) + return HASH_MIDDLE_BLOCK; + else if (!msg->has_next && msg->iv_bytes) + return HASH_END_BLOCK; + else + return HASH_SINGLE_BLOCK; +} + struct wd_digest_msg *wd_digest_get_msg(__u32 idx, __u32 tag);
#ifdef __cplusplus
For the long hash first blcok and middle block, if the size of the data is not aligned with the block size, the partial data is stored in partial_block and combined with the next block to form an aligned length for calculation. Currently, partial_block is added to struct wd_digest_sess to store partial data.
Signed-off-by: Weili Qian qianweili@huawei.com --- include/drv/wd_digest_drv.h | 4 +++ wd_digest.c | 50 ++++++++++++++++++++++++------------- 2 files changed, 36 insertions(+), 18 deletions(-)
diff --git a/include/drv/wd_digest_drv.h b/include/drv/wd_digest_drv.h index 304b506..8a4aa0b 100644 --- a/include/drv/wd_digest_drv.h +++ b/include/drv/wd_digest_drv.h @@ -44,6 +44,8 @@ struct wd_digest_msg { __u32 in_bytes; /* out_bytes */ __u32 out_bytes; + /* partial bytes for stream mode */ + __u32 partial_bytes;
/* input key pointer */ __u8 *key; @@ -53,6 +55,8 @@ struct wd_digest_msg { __u8 *in; /* output data pointer */ __u8 *out; + /* partial pointer for stream mode */ + __u8 *partial_block; /* total of data for stream mode */ __u64 long_data_len; }; diff --git a/wd_digest.c b/wd_digest.c index acf341a..dba2f95 100644 --- a/wd_digest.c +++ b/wd_digest.c @@ -11,6 +11,7 @@ #include "wd_digest.h"
#define GMAC_IV_LEN 16 +#define MAX_BLOCK_SIZE 128
static __u32 g_digest_mac_len[WD_DIGEST_TYPE_MAX] = { WD_DIGEST_SM3_LEN, WD_DIGEST_MD5_LEN, WD_DIGEST_SHA1_LEN, @@ -45,6 +46,19 @@ struct wd_digest_setting { void *dlh_list; } wd_digest_setting;
+struct wd_digest_stream_data { + /* Long hash mode, first and middle block misaligned data */ + unsigned char partial_block[MAX_BLOCK_SIZE]; + __u32 partial_bytes; + /* Total data length for stream mode */ + __u64 long_data_len; + /* + * Notify the stream message state, zero is frist message, + * non-zero is middle or final message. + */ + int msg_state; +}; + struct wd_digest_sess { char *alg_name; enum wd_digest_type alg; @@ -53,14 +67,7 @@ struct wd_digest_sess { unsigned char key[MAX_HMAC_KEY_SIZE]; __u32 key_bytes; void *sched_key; - /* - * Notify the stream message state, zero is frist message, - * non-zero is middle or final message. - */ - int msg_state; - - /* Total data length for stream mode */ - __u64 long_data_len; + struct wd_digest_stream_data stream_data; };
struct wd_env_config wd_digest_env_config; @@ -536,12 +543,12 @@ static void fill_request_msg(struct wd_digest_msg *msg, memcpy(&msg->req, req, sizeof(struct wd_digest_req));
if (unlikely(req->has_next == WD_DIGEST_STREAM_END)) { - sess->long_data_len = req->long_data_len; - sess->msg_state = WD_DIGEST_DOING; + sess->stream_data.long_data_len = req->long_data_len; + sess->stream_data.msg_state = WD_DIGEST_DOING; req->has_next = WD_DIGEST_END; } else if (unlikely(req->has_next == WD_DIGEST_STREAM_DOING)) { - sess->long_data_len = req->long_data_len; - sess->msg_state = WD_DIGEST_DOING; + sess->stream_data.long_data_len = req->long_data_len; + sess->stream_data.msg_state = WD_DIGEST_DOING; req->has_next = WD_DIGEST_DOING; }
@@ -557,10 +564,12 @@ static void fill_request_msg(struct wd_digest_msg *msg, msg->out_bytes = req->out_bytes; msg->data_fmt = req->data_fmt; msg->has_next = req->has_next; - msg->long_data_len = sess->long_data_len + req->in_bytes; + msg->long_data_len = sess->stream_data.long_data_len + req->in_bytes; + msg->partial_block = sess->stream_data.partial_block; + msg->partial_bytes = sess->stream_data.partial_bytes;
/* Use iv_bytes to store the stream message state */ - msg->iv_bytes = sess->msg_state; + msg->iv_bytes = sess->stream_data.msg_state; }
static int send_recv_sync(struct wd_ctx_internal *ctx, struct wd_digest_sess *dsess, @@ -579,17 +588,22 @@ static int send_recv_sync(struct wd_ctx_internal *ctx, struct wd_digest_sess *ds if (unlikely(ret)) return ret;
- /* After a stream mode job was done, update session long_data_len */ + /* + * After a stream mode job was done, update session + * long_data_len and partial_bytes. + */ if (msg->has_next) { /* Long hash(first and middle message) */ - dsess->long_data_len += msg->in_bytes; + dsess->stream_data.long_data_len += msg->in_bytes; + dsess->stream_data.partial_bytes = msg->partial_bytes; } else if (msg->iv_bytes) { /* Long hash(final message) */ - dsess->long_data_len = 0; + dsess->stream_data.long_data_len = 0; + dsess->stream_data.partial_bytes = 0; }
/* Update session message state */ - dsess->msg_state = msg->has_next; + dsess->stream_data.msg_state = msg->has_next;
return 0; }
In synchronous mode, to protect hardware queue resources and prevent multiple threads from sending packets to the same queue at the same time, lock is added before packets are sent in function send_recv_sync().
In non-hard computing scenarios, the resources are independent, and multiple synchronization threads can process at the same time. If lock is added before packets are sent, the multi-thread performance deteriorates. Therefore, the wd_ctx_spin_lock and wd_ctx_spin_unlock interfaces are added. In non-hard computing scenarios, the lock is not added.
Signed-off-by: Weili Qian qianweili@huawei.com --- include/wd_util.h | 23 +++++++++++++++++++++++ wd_digest.c | 4 ++-- 2 files changed, 25 insertions(+), 2 deletions(-)
diff --git a/include/wd_util.h b/include/wd_util.h index 3059ac1..f217f0f 100644 --- a/include/wd_util.h +++ b/include/wd_util.h @@ -527,6 +527,29 @@ static inline void wd_dfx_msg_cnt(struct wd_ctx_config_internal *config, config->msg_cnt[sqn]++; }
+/** + * wd_ctx_spin_lock() - Lock interface, which is used in the synchronization process. + * @ctx: queue context. + * @type: the type of the driver. + * + * If the drvier type is not UADK_ALG_HW, the lock is not required. + */ +static inline void wd_ctx_spin_lock(struct wd_ctx_internal *ctx, int type) +{ + if (type != UADK_ALG_HW) + return; + + pthread_spin_lock(&ctx->lock); +} + +static inline void wd_ctx_spin_unlock(struct wd_ctx_internal *ctx, int type) +{ + if (type != UADK_ALG_HW) + return; + + pthread_spin_unlock(&ctx->lock); +} + #ifdef __cplusplus } #endif diff --git a/wd_digest.c b/wd_digest.c index dba2f95..c59184d 100644 --- a/wd_digest.c +++ b/wd_digest.c @@ -581,10 +581,10 @@ static int send_recv_sync(struct wd_ctx_internal *ctx, struct wd_digest_sess *ds msg_handle.send = wd_digest_setting.driver->send; msg_handle.recv = wd_digest_setting.driver->recv;
- pthread_spin_lock(&ctx->lock); + wd_ctx_spin_lock(ctx, wd_digest_setting.driver->calc_type); ret = wd_handle_msg_sync(wd_digest_setting.driver, &msg_handle, ctx->ctx, msg, NULL, wd_digest_setting.config.epoll_en); - pthread_spin_unlock(&ctx->lock); + wd_ctx_spin_unlock(ctx, wd_digest_setting.driver->calc_type); if (unlikely(ret)) return ret;