一、以下是请求过程:
static inline int crypto_wait_req(int err, struct crypto_wait *wait)
{switch (err) {case -EINPROGRESS:case -EBUSY:wait_for_completion(&wait->completion);reinit_completion(&wait->completion);err = wait->err;break;};return err;
}static inline void crypto_init_wait(struct crypto_wait *wait)
{init_completion(&wait->completion);
}
二、 completion 用法
通常wait_for_completion需要completion唤醒配合,如下:
#include <linux/completion.h>static struct completion my_completion; // 1. 定义完成事件static int my_thread_function(void *data) {pr_info("Thread started...\n");msleep(5000); // 模拟一个长时间的操作pr_info("Operation completed!\n");complete(&my_completion); // 3. 标记完成事件return 0;
}static int __init my_init(void) {struct task_struct *thread;pr_info("Module init...\n");// 初始化完成事件init_completion(&my_completion);// 创建一个内核线程thread = kthread_run(my_thread_function, NULL, "my_thread");if (IS_ERR(thread)) {pr_err("Failed to create thread.\n");return PTR_ERR(thread);}// 等待完成事件wait_for_completion(&my_completion); //2. 阻塞当前线程,直到完成事件被标记为已完成。pr_info("Main thread: Operation completed!\n");return 0;
}
三、 set_callback
static inline void ahash_request_set_callback(struct ahash_request *req,u32 flags,crypto_completion_t compl,void *data)
{req->base.complete = compl;req->base.data = data;req->base.flags = flags;
}
四、crypto_ahash_update
硬件加速请求。
+static int ccp_do_sm3_update(struct ahash_request *req, unsigned int nbytes,
+ unsigned int final)
+{
+ struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
+ struct ccp_ctx *ctx = crypto_ahash_ctx(tfm);
+ struct ccp_sm3_req_ctx *rctx = ahash_request_ctx(req);+ ret = ccp_crypto_enqueue_request(&req->base, &rctx->cmd);
+
+ return ret;
+
+e_free:
+ sg_free_table(&rctx->data_sg);
+
+ return ret;
+}
int ccp_crypto_enqueue_request(struct crypto_async_request *req,struct ccp_cmd *cmd)
{struct ccp_crypto_cmd *crypto_cmd;gfp_t gfp;gfp = req->flags & CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL : GFP_ATOMIC;crypto_cmd = kzalloc(sizeof(*crypto_cmd), gfp);if (!crypto_cmd)return -ENOMEM;/* The tfm pointer must be saved and not referenced from the* crypto_async_request (req) pointer because it is used after* completion callback for the request and the req pointer* might not be valid anymore.*/crypto_cmd->cmd = cmd;crypto_cmd->req = req;crypto_cmd->tfm = req->tfm;cmd->callback = ccp_crypto_complete;cmd->data = crypto_cmd;if (req->flags & CRYPTO_TFM_REQ_MAY_BACKLOG)cmd->flags |= CCP_CMD_MAY_BACKLOG;elsecmd->flags &= ~CCP_CMD_MAY_BACKLOG;return ccp_crypto_enqueue_cmd(crypto_cmd);
}
ccp_crypto_enqueue_request使用例子
static struct completion my_completion;// CCP 操作完成的回调函数
static void ccp_crypto_complete(struct crypto_async_request *req, int error) {printk(KERN_INFO "CCP operation completed.\n");if (error) {printk(KERN_ERR "CCP operation failed with error code %d\n", error);} else {printk(KERN_INFO "CCP operation succeeded.\n");// 在这里处理操作的结果}// 唤醒等待完成的线程complete(&my_completion);
}static int __init my_init(void) {struct ccp_cmd cmd;struct crypto_async_request *req;int ret;printk(KERN_INFO "Module init...\n");// 初始化完成事件init_completion(&my_completion);// 分配 CCP 操作结构体req = crypto_req_alloc(ccp_queue, GFP_KERNEL);if (!req) {printk(KERN_ERR "Failed to allocate CCP request structure.\n");return -ENOMEM;}// 初始化 CCP 操作结构体memset(&cmd, 0, sizeof(cmd));cmd.req = req;cmd.req->complete = ccp_crypto_complete; // 操作完成的回调函数// 设置其他操作参数// ...// 提交请求给 CCP 硬件加速器ret = ccp_crypto_enqueue_request(cmd.req, &cmd);if (ret) {printk(KERN_ERR "Failed to enqueue request: %d\n", ret);crypto_req_put(req);return ret;}// 等待完成事件wait_for_completion(&my_completion);// 释放 CCP 操作结构体crypto_req_put(req);return 0;
}
struct ccp_cmd {/* The list_head, work_struct, ccp and ret variables are for use* by the CCP driver only.*/struct list_head entry;struct work_struct work;struct ccp_device *ccp;int ret;u32 flags;enum ccp_engine engine;u32 engine_error;union {struct ccp_aes_engine aes;struct ccp_xts_aes_engine xts;struct ccp_des3_engine des3;struct ccp_sha_engine sha;struct ccp_rsa_engine rsa;struct ccp_passthru_engine passthru;struct ccp_passthru_nomap_engine passthru_nomap;struct ccp_ecc_engine ecc;} u;/* Completion callback support */void (*callback)(void *data, int err);void *data;
};
struct crypto_async_request {struct list_head list;crypto_completion_t complete;void *data;struct crypto_tfm *tfm;u32 flags;
};
大致的逻辑应该是通过update 把硬件加速命令通过ccp_crypto_enqueue_request传递到硬件加速其中。如果处理完成直接返回正确,处理异常如果是设备忙碌,外部会通过crypto_wait_req等待,知道硬件加速器执行完毕唤醒wait。