xref: /openbmc/linux/drivers/crypto/ccp/ccp-crypto-main.c (revision 9a87ffc99ec8eb8d35eed7c4f816d75f5cc9662e)
1d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2d3123599STom Lendacky /*
3d3123599STom Lendacky  * AMD Cryptographic Coprocessor (CCP) crypto API support
4d3123599STom Lendacky  *
568cc652fSGary R Hook  * Copyright (C) 2013,2017 Advanced Micro Devices, Inc.
6d3123599STom Lendacky  *
7d3123599STom Lendacky  * Author: Tom Lendacky <thomas.lendacky@amd.com>
8d3123599STom Lendacky  */
9d3123599STom Lendacky 
10d3123599STom Lendacky #include <linux/module.h>
11d81ed653STom Lendacky #include <linux/moduleparam.h>
12d3123599STom Lendacky #include <linux/kernel.h>
13d3123599STom Lendacky #include <linux/list.h>
14d3123599STom Lendacky #include <linux/ccp.h>
15d3123599STom Lendacky #include <linux/scatterlist.h>
16d3123599STom Lendacky #include <crypto/internal/hash.h>
17ceeec0afSGary R Hook #include <crypto/internal/akcipher.h>
18d3123599STom Lendacky 
19d3123599STom Lendacky #include "ccp-crypto.h"
20d3123599STom Lendacky 
21d3123599STom Lendacky MODULE_AUTHOR("Tom Lendacky <thomas.lendacky@amd.com>");
22d3123599STom Lendacky MODULE_LICENSE("GPL");
23d3123599STom Lendacky MODULE_VERSION("1.0.0");
24d3123599STom Lendacky MODULE_DESCRIPTION("AMD Cryptographic Coprocessor crypto API support");
25d3123599STom Lendacky 
26d81ed653STom Lendacky static unsigned int aes_disable;
27d81ed653STom Lendacky module_param(aes_disable, uint, 0444);
28d81ed653STom Lendacky MODULE_PARM_DESC(aes_disable, "Disable use of AES - any non-zero value");
29d81ed653STom Lendacky 
30d81ed653STom Lendacky static unsigned int sha_disable;
31d81ed653STom Lendacky module_param(sha_disable, uint, 0444);
32d81ed653STom Lendacky MODULE_PARM_DESC(sha_disable, "Disable use of SHA - any non-zero value");
33d81ed653STom Lendacky 
34990672d4SGary R Hook static unsigned int des3_disable;
35990672d4SGary R Hook module_param(des3_disable, uint, 0444);
36990672d4SGary R Hook MODULE_PARM_DESC(des3_disable, "Disable use of 3DES - any non-zero value");
37990672d4SGary R Hook 
38ceeec0afSGary R Hook static unsigned int rsa_disable;
39ceeec0afSGary R Hook module_param(rsa_disable, uint, 0444);
40ceeec0afSGary R Hook MODULE_PARM_DESC(rsa_disable, "Disable use of RSA - any non-zero value");
41ceeec0afSGary R Hook 
42d3123599STom Lendacky /* List heads for the supported algorithms */
43d3123599STom Lendacky static LIST_HEAD(hash_algs);
44be9fe620SArd Biesheuvel static LIST_HEAD(skcipher_algs);
4536cf515bSGary R Hook static LIST_HEAD(aead_algs);
46ceeec0afSGary R Hook static LIST_HEAD(akcipher_algs);
47d3123599STom Lendacky 
48bc385447STom Lendacky /* For any tfm, requests for that tfm must be returned on the order
49bc385447STom Lendacky  * received.  With multiple queues available, the CCP can process more
50bc385447STom Lendacky  * than one cmd at a time.  Therefore we must maintain a cmd list to insure
51bc385447STom Lendacky  * the proper ordering of requests on a given tfm.
52d3123599STom Lendacky  */
53bc385447STom Lendacky struct ccp_crypto_queue {
54d3123599STom Lendacky 	struct list_head cmds;
55d3123599STom Lendacky 	struct list_head *backlog;
56d3123599STom Lendacky 	unsigned int cmd_count;
57d3123599STom Lendacky };
588db88467STom Lendacky 
59bc385447STom Lendacky #define CCP_CRYPTO_MAX_QLEN	100
60d3123599STom Lendacky 
61bc385447STom Lendacky static struct ccp_crypto_queue req_queue;
6263655b62STang Yizhou static DEFINE_SPINLOCK(req_queue_lock);
63d3123599STom Lendacky 
64d3123599STom Lendacky struct ccp_crypto_cmd {
65d3123599STom Lendacky 	struct list_head entry;
66d3123599STom Lendacky 
67d3123599STom Lendacky 	struct ccp_cmd *cmd;
68d3123599STom Lendacky 
69d3123599STom Lendacky 	/* Save the crypto_tfm and crypto_async_request addresses
70d3123599STom Lendacky 	 * separately to avoid any reference to a possibly invalid
71d3123599STom Lendacky 	 * crypto_async_request structure after invoking the request
72d3123599STom Lendacky 	 * callback
73d3123599STom Lendacky 	 */
74d3123599STom Lendacky 	struct crypto_async_request *req;
75d3123599STom Lendacky 	struct crypto_tfm *tfm;
76d3123599STom Lendacky 
77d3123599STom Lendacky 	/* Used for held command processing to determine state */
78d3123599STom Lendacky 	int ret;
79d3123599STom Lendacky };
80d3123599STom Lendacky 
ccp_crypto_success(int err)81d3123599STom Lendacky static inline bool ccp_crypto_success(int err)
82d3123599STom Lendacky {
83d3123599STom Lendacky 	if (err && (err != -EINPROGRESS) && (err != -EBUSY))
84d3123599STom Lendacky 		return false;
85d3123599STom Lendacky 
86d3123599STom Lendacky 	return true;
87d3123599STom Lendacky }
88d3123599STom Lendacky 
ccp_crypto_cmd_complete(struct ccp_crypto_cmd * crypto_cmd,struct ccp_crypto_cmd ** backlog)89d3123599STom Lendacky static struct ccp_crypto_cmd *ccp_crypto_cmd_complete(
90d3123599STom Lendacky 	struct ccp_crypto_cmd *crypto_cmd, struct ccp_crypto_cmd **backlog)
91d3123599STom Lendacky {
92d3123599STom Lendacky 	struct ccp_crypto_cmd *held = NULL, *tmp;
93bc385447STom Lendacky 	unsigned long flags;
94d3123599STom Lendacky 
95d3123599STom Lendacky 	*backlog = NULL;
96d3123599STom Lendacky 
97bc385447STom Lendacky 	spin_lock_irqsave(&req_queue_lock, flags);
98d3123599STom Lendacky 
99d3123599STom Lendacky 	/* Held cmds will be after the current cmd in the queue so start
100d3123599STom Lendacky 	 * searching for a cmd with a matching tfm for submission.
101d3123599STom Lendacky 	 */
102d3123599STom Lendacky 	tmp = crypto_cmd;
103bc385447STom Lendacky 	list_for_each_entry_continue(tmp, &req_queue.cmds, entry) {
104d3123599STom Lendacky 		if (crypto_cmd->tfm != tmp->tfm)
105d3123599STom Lendacky 			continue;
106d3123599STom Lendacky 		held = tmp;
107d3123599STom Lendacky 		break;
108d3123599STom Lendacky 	}
109d3123599STom Lendacky 
110d3123599STom Lendacky 	/* Process the backlog:
111d3123599STom Lendacky 	 *   Because cmds can be executed from any point in the cmd list
112d3123599STom Lendacky 	 *   special precautions have to be taken when handling the backlog.
113d3123599STom Lendacky 	 */
114bc385447STom Lendacky 	if (req_queue.backlog != &req_queue.cmds) {
115d3123599STom Lendacky 		/* Skip over this cmd if it is the next backlog cmd */
116bc385447STom Lendacky 		if (req_queue.backlog == &crypto_cmd->entry)
117bc385447STom Lendacky 			req_queue.backlog = crypto_cmd->entry.next;
118d3123599STom Lendacky 
119bc385447STom Lendacky 		*backlog = container_of(req_queue.backlog,
120d3123599STom Lendacky 					struct ccp_crypto_cmd, entry);
121bc385447STom Lendacky 		req_queue.backlog = req_queue.backlog->next;
122d3123599STom Lendacky 
123d3123599STom Lendacky 		/* Skip over this cmd if it is now the next backlog cmd */
124bc385447STom Lendacky 		if (req_queue.backlog == &crypto_cmd->entry)
125bc385447STom Lendacky 			req_queue.backlog = crypto_cmd->entry.next;
126d3123599STom Lendacky 	}
127d3123599STom Lendacky 
128d3123599STom Lendacky 	/* Remove the cmd entry from the list of cmds */
129bc385447STom Lendacky 	req_queue.cmd_count--;
130d3123599STom Lendacky 	list_del(&crypto_cmd->entry);
131d3123599STom Lendacky 
132bc385447STom Lendacky 	spin_unlock_irqrestore(&req_queue_lock, flags);
133bc385447STom Lendacky 
134d3123599STom Lendacky 	return held;
135d3123599STom Lendacky }
136d3123599STom Lendacky 
ccp_crypto_complete(void * data,int err)137bc385447STom Lendacky static void ccp_crypto_complete(void *data, int err)
138d3123599STom Lendacky {
139bc385447STom Lendacky 	struct ccp_crypto_cmd *crypto_cmd = data;
140d3123599STom Lendacky 	struct ccp_crypto_cmd *held, *next, *backlog;
141d3123599STom Lendacky 	struct crypto_async_request *req = crypto_cmd->req;
14299c6b20eSHerbert Xu 	struct ccp_ctx *ctx = crypto_tfm_ctx_dma(req->tfm);
143bc385447STom Lendacky 	int ret;
144d3123599STom Lendacky 
145bc385447STom Lendacky 	if (err == -EINPROGRESS) {
1468db88467STom Lendacky 		/* Only propagate the -EINPROGRESS if necessary */
147d3123599STom Lendacky 		if (crypto_cmd->ret == -EBUSY) {
148d3123599STom Lendacky 			crypto_cmd->ret = -EINPROGRESS;
149*0c18d054SHerbert Xu 			crypto_request_complete(req, -EINPROGRESS);
150d3123599STom Lendacky 		}
151d3123599STom Lendacky 
152bc385447STom Lendacky 		return;
153d3123599STom Lendacky 	}
154d3123599STom Lendacky 
155d3123599STom Lendacky 	/* Operation has completed - update the queue before invoking
156d3123599STom Lendacky 	 * the completion callbacks and retrieve the next cmd (cmd with
157d3123599STom Lendacky 	 * a matching tfm) that can be submitted to the CCP.
158d3123599STom Lendacky 	 */
159d3123599STom Lendacky 	held = ccp_crypto_cmd_complete(crypto_cmd, &backlog);
160d3123599STom Lendacky 	if (backlog) {
161d3123599STom Lendacky 		backlog->ret = -EINPROGRESS;
162*0c18d054SHerbert Xu 		crypto_request_complete(backlog->req, -EINPROGRESS);
163d3123599STom Lendacky 	}
164d3123599STom Lendacky 
165d3123599STom Lendacky 	/* Transition the state from -EBUSY to -EINPROGRESS first */
166d3123599STom Lendacky 	if (crypto_cmd->ret == -EBUSY)
167*0c18d054SHerbert Xu 		crypto_request_complete(req, -EINPROGRESS);
168d3123599STom Lendacky 
169d3123599STom Lendacky 	/* Completion callbacks */
170bc385447STom Lendacky 	ret = err;
171d3123599STom Lendacky 	if (ctx->complete)
172d3123599STom Lendacky 		ret = ctx->complete(req, ret);
173*0c18d054SHerbert Xu 	crypto_request_complete(req, ret);
174d3123599STom Lendacky 
175d3123599STom Lendacky 	/* Submit the next cmd */
176d3123599STom Lendacky 	while (held) {
1770611451bSTom Lendacky 		/* Since we have already queued the cmd, we must indicate that
1780611451bSTom Lendacky 		 * we can backlog so as not to "lose" this request.
1790611451bSTom Lendacky 		 */
1800611451bSTom Lendacky 		held->cmd->flags |= CCP_CMD_MAY_BACKLOG;
181d3123599STom Lendacky 		ret = ccp_enqueue_cmd(held->cmd);
182d3123599STom Lendacky 		if (ccp_crypto_success(ret))
183d3123599STom Lendacky 			break;
184d3123599STom Lendacky 
185d3123599STom Lendacky 		/* Error occurred, report it and get the next entry */
18699c6b20eSHerbert Xu 		ctx = crypto_tfm_ctx_dma(held->req->tfm);
187950b10baSTom Lendacky 		if (ctx->complete)
188950b10baSTom Lendacky 			ret = ctx->complete(held->req, ret);
189*0c18d054SHerbert Xu 		crypto_request_complete(held->req, ret);
190d3123599STom Lendacky 
191d3123599STom Lendacky 		next = ccp_crypto_cmd_complete(held, &backlog);
192d3123599STom Lendacky 		if (backlog) {
193d3123599STom Lendacky 			backlog->ret = -EINPROGRESS;
194*0c18d054SHerbert Xu 			crypto_request_complete(backlog->req, -EINPROGRESS);
195d3123599STom Lendacky 		}
196d3123599STom Lendacky 
197d3123599STom Lendacky 		kfree(held);
198d3123599STom Lendacky 		held = next;
199d3123599STom Lendacky 	}
200d3123599STom Lendacky 
201d3123599STom Lendacky 	kfree(crypto_cmd);
202d3123599STom Lendacky }
203d3123599STom Lendacky 
ccp_crypto_enqueue_cmd(struct ccp_crypto_cmd * crypto_cmd)204d3123599STom Lendacky static int ccp_crypto_enqueue_cmd(struct ccp_crypto_cmd *crypto_cmd)
205d3123599STom Lendacky {
206d3123599STom Lendacky 	struct ccp_crypto_cmd *active = NULL, *tmp;
207bc385447STom Lendacky 	unsigned long flags;
208c65a52f8STom Lendacky 	bool free_cmd = true;
209bc385447STom Lendacky 	int ret;
210d3123599STom Lendacky 
211bc385447STom Lendacky 	spin_lock_irqsave(&req_queue_lock, flags);
212d3123599STom Lendacky 
213d3123599STom Lendacky 	/* Check if the cmd can/should be queued */
214bc385447STom Lendacky 	if (req_queue.cmd_count >= CCP_CRYPTO_MAX_QLEN) {
215cfba73d2SGilad Ben-Yossef 		if (!(crypto_cmd->cmd->flags & CCP_CMD_MAY_BACKLOG)) {
216cfba73d2SGilad Ben-Yossef 			ret = -ENOSPC;
217bc385447STom Lendacky 			goto e_lock;
218d3123599STom Lendacky 		}
219cfba73d2SGilad Ben-Yossef 	}
220d3123599STom Lendacky 
221d3123599STom Lendacky 	/* Look for an entry with the same tfm.  If there is a cmd
222bc385447STom Lendacky 	 * with the same tfm in the list then the current cmd cannot
223bc385447STom Lendacky 	 * be submitted to the CCP yet.
224d3123599STom Lendacky 	 */
225bc385447STom Lendacky 	list_for_each_entry(tmp, &req_queue.cmds, entry) {
226d3123599STom Lendacky 		if (crypto_cmd->tfm != tmp->tfm)
227d3123599STom Lendacky 			continue;
228d3123599STom Lendacky 		active = tmp;
229d3123599STom Lendacky 		break;
230d3123599STom Lendacky 	}
231d3123599STom Lendacky 
232d3123599STom Lendacky 	ret = -EINPROGRESS;
233d3123599STom Lendacky 	if (!active) {
234d3123599STom Lendacky 		ret = ccp_enqueue_cmd(crypto_cmd->cmd);
235d3123599STom Lendacky 		if (!ccp_crypto_success(ret))
236c65a52f8STom Lendacky 			goto e_lock;	/* Error, don't queue it */
237d3123599STom Lendacky 	}
238d3123599STom Lendacky 
239bc385447STom Lendacky 	if (req_queue.cmd_count >= CCP_CRYPTO_MAX_QLEN) {
240d3123599STom Lendacky 		ret = -EBUSY;
241bc385447STom Lendacky 		if (req_queue.backlog == &req_queue.cmds)
242bc385447STom Lendacky 			req_queue.backlog = &crypto_cmd->entry;
243d3123599STom Lendacky 	}
244d3123599STom Lendacky 	crypto_cmd->ret = ret;
245d3123599STom Lendacky 
246bc385447STom Lendacky 	req_queue.cmd_count++;
247bc385447STom Lendacky 	list_add_tail(&crypto_cmd->entry, &req_queue.cmds);
248d3123599STom Lendacky 
249c65a52f8STom Lendacky 	free_cmd = false;
250c65a52f8STom Lendacky 
251bc385447STom Lendacky e_lock:
252bc385447STom Lendacky 	spin_unlock_irqrestore(&req_queue_lock, flags);
253d3123599STom Lendacky 
254c65a52f8STom Lendacky 	if (free_cmd)
255c65a52f8STom Lendacky 		kfree(crypto_cmd);
256c65a52f8STom Lendacky 
257d3123599STom Lendacky 	return ret;
258d3123599STom Lendacky }
259d3123599STom Lendacky 
260d3123599STom Lendacky /**
261d3123599STom Lendacky  * ccp_crypto_enqueue_request - queue an crypto async request for processing
262d3123599STom Lendacky  *				by the CCP
263d3123599STom Lendacky  *
264d3123599STom Lendacky  * @req: crypto_async_request struct to be processed
265d3123599STom Lendacky  * @cmd: ccp_cmd struct to be sent to the CCP
266d3123599STom Lendacky  */
ccp_crypto_enqueue_request(struct crypto_async_request * req,struct ccp_cmd * cmd)267d3123599STom Lendacky int ccp_crypto_enqueue_request(struct crypto_async_request *req,
268d3123599STom Lendacky 			       struct ccp_cmd *cmd)
269d3123599STom Lendacky {
270d3123599STom Lendacky 	struct ccp_crypto_cmd *crypto_cmd;
271d3123599STom Lendacky 	gfp_t gfp;
272d3123599STom Lendacky 
273d3123599STom Lendacky 	gfp = req->flags & CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL : GFP_ATOMIC;
274d3123599STom Lendacky 
275d3123599STom Lendacky 	crypto_cmd = kzalloc(sizeof(*crypto_cmd), gfp);
276d3123599STom Lendacky 	if (!crypto_cmd)
277d3123599STom Lendacky 		return -ENOMEM;
278d3123599STom Lendacky 
279d3123599STom Lendacky 	/* The tfm pointer must be saved and not referenced from the
280d3123599STom Lendacky 	 * crypto_async_request (req) pointer because it is used after
281d3123599STom Lendacky 	 * completion callback for the request and the req pointer
282d3123599STom Lendacky 	 * might not be valid anymore.
283d3123599STom Lendacky 	 */
284d3123599STom Lendacky 	crypto_cmd->cmd = cmd;
285d3123599STom Lendacky 	crypto_cmd->req = req;
286d3123599STom Lendacky 	crypto_cmd->tfm = req->tfm;
287d3123599STom Lendacky 
288d3123599STom Lendacky 	cmd->callback = ccp_crypto_complete;
289d3123599STom Lendacky 	cmd->data = crypto_cmd;
290d3123599STom Lendacky 
291d3123599STom Lendacky 	if (req->flags & CRYPTO_TFM_REQ_MAY_BACKLOG)
292d3123599STom Lendacky 		cmd->flags |= CCP_CMD_MAY_BACKLOG;
293d3123599STom Lendacky 	else
294d3123599STom Lendacky 		cmd->flags &= ~CCP_CMD_MAY_BACKLOG;
295d3123599STom Lendacky 
296c65a52f8STom Lendacky 	return ccp_crypto_enqueue_cmd(crypto_cmd);
297d3123599STom Lendacky }
298d3123599STom Lendacky 
ccp_crypto_sg_table_add(struct sg_table * table,struct scatterlist * sg_add)299d3123599STom Lendacky struct scatterlist *ccp_crypto_sg_table_add(struct sg_table *table,
300d3123599STom Lendacky 					    struct scatterlist *sg_add)
301d3123599STom Lendacky {
302d3123599STom Lendacky 	struct scatterlist *sg, *sg_last = NULL;
303d3123599STom Lendacky 
304d3123599STom Lendacky 	for (sg = table->sgl; sg; sg = sg_next(sg))
305d3123599STom Lendacky 		if (!sg_page(sg))
306d3123599STom Lendacky 			break;
307355eba5dSTom Lendacky 	if (WARN_ON(!sg))
308355eba5dSTom Lendacky 		return NULL;
309d3123599STom Lendacky 
310d3123599STom Lendacky 	for (; sg && sg_add; sg = sg_next(sg), sg_add = sg_next(sg_add)) {
311d3123599STom Lendacky 		sg_set_page(sg, sg_page(sg_add), sg_add->length,
312d3123599STom Lendacky 			    sg_add->offset);
313d3123599STom Lendacky 		sg_last = sg;
314d3123599STom Lendacky 	}
315355eba5dSTom Lendacky 	if (WARN_ON(sg_add))
316355eba5dSTom Lendacky 		return NULL;
317d3123599STom Lendacky 
318d3123599STom Lendacky 	return sg_last;
319d3123599STom Lendacky }
320d3123599STom Lendacky 
ccp_register_algs(void)321d3123599STom Lendacky static int ccp_register_algs(void)
322d3123599STom Lendacky {
323d3123599STom Lendacky 	int ret;
324d3123599STom Lendacky 
325d81ed653STom Lendacky 	if (!aes_disable) {
326be9fe620SArd Biesheuvel 		ret = ccp_register_aes_algs(&skcipher_algs);
327d3123599STom Lendacky 		if (ret)
328d3123599STom Lendacky 			return ret;
329d3123599STom Lendacky 
330d3123599STom Lendacky 		ret = ccp_register_aes_cmac_algs(&hash_algs);
331d3123599STom Lendacky 		if (ret)
332d3123599STom Lendacky 			return ret;
333d3123599STom Lendacky 
334be9fe620SArd Biesheuvel 		ret = ccp_register_aes_xts_algs(&skcipher_algs);
335d3123599STom Lendacky 		if (ret)
336d3123599STom Lendacky 			return ret;
33736cf515bSGary R Hook 
33836cf515bSGary R Hook 		ret = ccp_register_aes_aeads(&aead_algs);
33936cf515bSGary R Hook 		if (ret)
34036cf515bSGary R Hook 			return ret;
341d81ed653STom Lendacky 	}
342d3123599STom Lendacky 
343990672d4SGary R Hook 	if (!des3_disable) {
344be9fe620SArd Biesheuvel 		ret = ccp_register_des3_algs(&skcipher_algs);
345990672d4SGary R Hook 		if (ret)
346990672d4SGary R Hook 			return ret;
347990672d4SGary R Hook 	}
348990672d4SGary R Hook 
349d81ed653STom Lendacky 	if (!sha_disable) {
350d3123599STom Lendacky 		ret = ccp_register_sha_algs(&hash_algs);
351d3123599STom Lendacky 		if (ret)
352d3123599STom Lendacky 			return ret;
353d81ed653STom Lendacky 	}
354d3123599STom Lendacky 
355ceeec0afSGary R Hook 	if (!rsa_disable) {
356ceeec0afSGary R Hook 		ret = ccp_register_rsa_algs(&akcipher_algs);
357ceeec0afSGary R Hook 		if (ret)
358ceeec0afSGary R Hook 			return ret;
359ceeec0afSGary R Hook 	}
360ceeec0afSGary R Hook 
361d3123599STom Lendacky 	return 0;
362d3123599STom Lendacky }
363d3123599STom Lendacky 
ccp_unregister_algs(void)364d3123599STom Lendacky static void ccp_unregister_algs(void)
365d3123599STom Lendacky {
366d3123599STom Lendacky 	struct ccp_crypto_ahash_alg *ahash_alg, *ahash_tmp;
367be9fe620SArd Biesheuvel 	struct ccp_crypto_skcipher_alg *ablk_alg, *ablk_tmp;
36836cf515bSGary R Hook 	struct ccp_crypto_aead *aead_alg, *aead_tmp;
369ceeec0afSGary R Hook 	struct ccp_crypto_akcipher_alg *akc_alg, *akc_tmp;
370d3123599STom Lendacky 
371d3123599STom Lendacky 	list_for_each_entry_safe(ahash_alg, ahash_tmp, &hash_algs, entry) {
372d3123599STom Lendacky 		crypto_unregister_ahash(&ahash_alg->alg);
373d3123599STom Lendacky 		list_del(&ahash_alg->entry);
374d3123599STom Lendacky 		kfree(ahash_alg);
375d3123599STom Lendacky 	}
376d3123599STom Lendacky 
377be9fe620SArd Biesheuvel 	list_for_each_entry_safe(ablk_alg, ablk_tmp, &skcipher_algs, entry) {
378be9fe620SArd Biesheuvel 		crypto_unregister_skcipher(&ablk_alg->alg);
379d3123599STom Lendacky 		list_del(&ablk_alg->entry);
380d3123599STom Lendacky 		kfree(ablk_alg);
381d3123599STom Lendacky 	}
38236cf515bSGary R Hook 
38336cf515bSGary R Hook 	list_for_each_entry_safe(aead_alg, aead_tmp, &aead_algs, entry) {
38436cf515bSGary R Hook 		crypto_unregister_aead(&aead_alg->alg);
38536cf515bSGary R Hook 		list_del(&aead_alg->entry);
38636cf515bSGary R Hook 		kfree(aead_alg);
38736cf515bSGary R Hook 	}
388ceeec0afSGary R Hook 
389ceeec0afSGary R Hook 	list_for_each_entry_safe(akc_alg, akc_tmp, &akcipher_algs, entry) {
390ceeec0afSGary R Hook 		crypto_unregister_akcipher(&akc_alg->alg);
391ceeec0afSGary R Hook 		list_del(&akc_alg->entry);
392ceeec0afSGary R Hook 		kfree(akc_alg);
393ceeec0afSGary R Hook 	}
394d3123599STom Lendacky }
395d3123599STom Lendacky 
ccp_crypto_init(void)396237f9eceSruanjinjie static int __init ccp_crypto_init(void)
397d3123599STom Lendacky {
398d3123599STom Lendacky 	int ret;
399d3123599STom Lendacky 
400c9f21cb6STom Lendacky 	ret = ccp_present();
401f6ebfd78SGary R Hook 	if (ret) {
402f6ebfd78SGary R Hook 		pr_err("Cannot load: there are no available CCPs\n");
403c9f21cb6STom Lendacky 		return ret;
404f6ebfd78SGary R Hook 	}
405c9f21cb6STom Lendacky 
406bc385447STom Lendacky 	INIT_LIST_HEAD(&req_queue.cmds);
407bc385447STom Lendacky 	req_queue.backlog = &req_queue.cmds;
408bc385447STom Lendacky 	req_queue.cmd_count = 0;
409d3123599STom Lendacky 
410d3123599STom Lendacky 	ret = ccp_register_algs();
411bc385447STom Lendacky 	if (ret)
412d3123599STom Lendacky 		ccp_unregister_algs();
413d3123599STom Lendacky 
414d3123599STom Lendacky 	return ret;
415d3123599STom Lendacky }
416d3123599STom Lendacky 
ccp_crypto_exit(void)417237f9eceSruanjinjie static void __exit ccp_crypto_exit(void)
418d3123599STom Lendacky {
419d3123599STom Lendacky 	ccp_unregister_algs();
420d3123599STom Lendacky }
421d3123599STom Lendacky 
422d3123599STom Lendacky module_init(ccp_crypto_init);
423d3123599STom Lendacky module_exit(ccp_crypto_exit);
424