xref: /openbmc/linux/crypto/crypto_engine.c (revision c900529f3d9161bfde5cca0754f83b4d3c3e0220)
12874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
2735d37b5SBaolin Wang /*
3735d37b5SBaolin Wang  * Handle async block request by crypto hardware engine.
4735d37b5SBaolin Wang  *
5735d37b5SBaolin Wang  * Copyright (C) 2016 Linaro, Inc.
6735d37b5SBaolin Wang  *
7735d37b5SBaolin Wang  * Author: Baolin Wang <baolin.wang@linaro.org>
8735d37b5SBaolin Wang  */
9735d37b5SBaolin Wang 
10*e5e7eb02SHerbert Xu #include <crypto/internal/aead.h>
11*e5e7eb02SHerbert Xu #include <crypto/internal/akcipher.h>
1245c461c5SHerbert Xu #include <crypto/internal/engine.h>
13*e5e7eb02SHerbert Xu #include <crypto/internal/hash.h>
14*e5e7eb02SHerbert Xu #include <crypto/internal/kpp.h>
15*e5e7eb02SHerbert Xu #include <crypto/internal/skcipher.h>
16735d37b5SBaolin Wang #include <linux/err.h>
17735d37b5SBaolin Wang #include <linux/delay.h>
180c3dc787SHerbert Xu #include <linux/device.h>
19*e5e7eb02SHerbert Xu #include <linux/kernel.h>
20*e5e7eb02SHerbert Xu #include <linux/module.h>
21ae7e81c0SIngo Molnar #include <uapi/linux/sched/types.h>
22735d37b5SBaolin Wang #include "internal.h"
23735d37b5SBaolin Wang 
24735d37b5SBaolin Wang #define CRYPTO_ENGINE_MAX_QLEN 10
25735d37b5SBaolin Wang 
26*e5e7eb02SHerbert Xu /* Temporary algorithm flag used to indicate an updated driver. */
27*e5e7eb02SHerbert Xu #define CRYPTO_ALG_ENGINE 0x200
28*e5e7eb02SHerbert Xu 
29*e5e7eb02SHerbert Xu struct crypto_engine_alg {
30*e5e7eb02SHerbert Xu 	struct crypto_alg base;
31*e5e7eb02SHerbert Xu 	struct crypto_engine_op op;
32*e5e7eb02SHerbert Xu };
33*e5e7eb02SHerbert Xu 
34735d37b5SBaolin Wang /**
35218d1cc1SCorentin LABBE  * crypto_finalize_request - finalize one request if the request is done
36218d1cc1SCorentin LABBE  * @engine: the hardware engine
37218d1cc1SCorentin LABBE  * @req: the request need to be finalized
38218d1cc1SCorentin LABBE  * @err: error number
39218d1cc1SCorentin LABBE  */
crypto_finalize_request(struct crypto_engine * engine,struct crypto_async_request * req,int err)40218d1cc1SCorentin LABBE static void crypto_finalize_request(struct crypto_engine *engine,
41218d1cc1SCorentin LABBE 				    struct crypto_async_request *req, int err)
42218d1cc1SCorentin LABBE {
43218d1cc1SCorentin LABBE 	unsigned long flags;
44218d1cc1SCorentin LABBE 
456a89f492SIuliana Prodan 	/*
466a89f492SIuliana Prodan 	 * If hardware cannot enqueue more requests
476a89f492SIuliana Prodan 	 * and retry mechanism is not supported
486a89f492SIuliana Prodan 	 * make sure we are completing the current request
496a89f492SIuliana Prodan 	 */
506a89f492SIuliana Prodan 	if (!engine->retry_support) {
51218d1cc1SCorentin LABBE 		spin_lock_irqsave(&engine->queue_lock, flags);
526a89f492SIuliana Prodan 		if (engine->cur_req == req) {
536a89f492SIuliana Prodan 			engine->cur_req = NULL;
546a89f492SIuliana Prodan 		}
55218d1cc1SCorentin LABBE 		spin_unlock_irqrestore(&engine->queue_lock, flags);
566a89f492SIuliana Prodan 	}
57218d1cc1SCorentin LABBE 
584058cf08SCorentin Labbe 	lockdep_assert_in_softirq();
596909823dSHerbert Xu 	crypto_request_complete(req, err);
60218d1cc1SCorentin LABBE 
61218d1cc1SCorentin LABBE 	kthread_queue_work(engine->kworker, &engine->pump_requests);
62218d1cc1SCorentin LABBE }
63218d1cc1SCorentin LABBE 
64218d1cc1SCorentin LABBE /**
65735d37b5SBaolin Wang  * crypto_pump_requests - dequeue one request from engine queue to process
66735d37b5SBaolin Wang  * @engine: the hardware engine
67735d37b5SBaolin Wang  * @in_kthread: true if we are in the context of the request pump thread
68735d37b5SBaolin Wang  *
69735d37b5SBaolin Wang  * This function checks if there is any request in the engine queue that
70735d37b5SBaolin Wang  * needs processing and if so call out to the driver to initialize hardware
71735d37b5SBaolin Wang  * and handle each request.
72735d37b5SBaolin Wang  */
crypto_pump_requests(struct crypto_engine * engine,bool in_kthread)73735d37b5SBaolin Wang static void crypto_pump_requests(struct crypto_engine *engine,
74735d37b5SBaolin Wang 				 bool in_kthread)
75735d37b5SBaolin Wang {
76735d37b5SBaolin Wang 	struct crypto_async_request *async_req, *backlog;
77*e5e7eb02SHerbert Xu 	struct crypto_engine_alg *alg;
78*e5e7eb02SHerbert Xu 	struct crypto_engine_op *op;
79735d37b5SBaolin Wang 	unsigned long flags;
80735d37b5SBaolin Wang 	bool was_busy = false;
81218d1cc1SCorentin LABBE 	int ret;
82735d37b5SBaolin Wang 
83735d37b5SBaolin Wang 	spin_lock_irqsave(&engine->queue_lock, flags);
84735d37b5SBaolin Wang 
85735d37b5SBaolin Wang 	/* Make sure we are not already running a request */
866a89f492SIuliana Prodan 	if (!engine->retry_support && engine->cur_req)
87735d37b5SBaolin Wang 		goto out;
88735d37b5SBaolin Wang 
89735d37b5SBaolin Wang 	/* If another context is idling then defer */
90735d37b5SBaolin Wang 	if (engine->idling) {
91c4ca2b0bSPetr Mladek 		kthread_queue_work(engine->kworker, &engine->pump_requests);
92735d37b5SBaolin Wang 		goto out;
93735d37b5SBaolin Wang 	}
94735d37b5SBaolin Wang 
95735d37b5SBaolin Wang 	/* Check if the engine queue is idle */
96735d37b5SBaolin Wang 	if (!crypto_queue_len(&engine->queue) || !engine->running) {
97735d37b5SBaolin Wang 		if (!engine->busy)
98735d37b5SBaolin Wang 			goto out;
99735d37b5SBaolin Wang 
100735d37b5SBaolin Wang 		/* Only do teardown in the thread */
101735d37b5SBaolin Wang 		if (!in_kthread) {
102c4ca2b0bSPetr Mladek 			kthread_queue_work(engine->kworker,
103735d37b5SBaolin Wang 					   &engine->pump_requests);
104735d37b5SBaolin Wang 			goto out;
105735d37b5SBaolin Wang 		}
106735d37b5SBaolin Wang 
107735d37b5SBaolin Wang 		engine->busy = false;
108735d37b5SBaolin Wang 		engine->idling = true;
109735d37b5SBaolin Wang 		spin_unlock_irqrestore(&engine->queue_lock, flags);
110735d37b5SBaolin Wang 
111735d37b5SBaolin Wang 		if (engine->unprepare_crypt_hardware &&
112735d37b5SBaolin Wang 		    engine->unprepare_crypt_hardware(engine))
11388d58ef8SCorentin LABBE 			dev_err(engine->dev, "failed to unprepare crypt hardware\n");
114735d37b5SBaolin Wang 
115735d37b5SBaolin Wang 		spin_lock_irqsave(&engine->queue_lock, flags);
116735d37b5SBaolin Wang 		engine->idling = false;
117735d37b5SBaolin Wang 		goto out;
118735d37b5SBaolin Wang 	}
119735d37b5SBaolin Wang 
1206a89f492SIuliana Prodan start_request:
121735d37b5SBaolin Wang 	/* Get the fist request from the engine queue to handle */
122735d37b5SBaolin Wang 	backlog = crypto_get_backlog(&engine->queue);
123735d37b5SBaolin Wang 	async_req = crypto_dequeue_request(&engine->queue);
124735d37b5SBaolin Wang 	if (!async_req)
125735d37b5SBaolin Wang 		goto out;
126735d37b5SBaolin Wang 
1276a89f492SIuliana Prodan 	/*
1286a89f492SIuliana Prodan 	 * If hardware doesn't support the retry mechanism,
1296a89f492SIuliana Prodan 	 * keep track of the request we are processing now.
1306a89f492SIuliana Prodan 	 * We'll need it on completion (crypto_finalize_request).
1316a89f492SIuliana Prodan 	 */
1326a89f492SIuliana Prodan 	if (!engine->retry_support)
1334cba7cf0SCorentin LABBE 		engine->cur_req = async_req;
1346a89f492SIuliana Prodan 
135735d37b5SBaolin Wang 	if (engine->busy)
136735d37b5SBaolin Wang 		was_busy = true;
137735d37b5SBaolin Wang 	else
138735d37b5SBaolin Wang 		engine->busy = true;
139735d37b5SBaolin Wang 
140735d37b5SBaolin Wang 	spin_unlock_irqrestore(&engine->queue_lock, flags);
141735d37b5SBaolin Wang 
142735d37b5SBaolin Wang 	/* Until here we get the request need to be encrypted successfully */
143735d37b5SBaolin Wang 	if (!was_busy && engine->prepare_crypt_hardware) {
144735d37b5SBaolin Wang 		ret = engine->prepare_crypt_hardware(engine);
145735d37b5SBaolin Wang 		if (ret) {
14688d58ef8SCorentin LABBE 			dev_err(engine->dev, "failed to prepare crypt hardware\n");
147bcd6e41dSHerbert Xu 			goto req_err_1;
148735d37b5SBaolin Wang 		}
149735d37b5SBaolin Wang 	}
150735d37b5SBaolin Wang 
151*e5e7eb02SHerbert Xu 	if (async_req->tfm->__crt_alg->cra_flags & CRYPTO_ALG_ENGINE) {
152*e5e7eb02SHerbert Xu 		alg = container_of(async_req->tfm->__crt_alg,
153*e5e7eb02SHerbert Xu 				   struct crypto_engine_alg, base);
154*e5e7eb02SHerbert Xu 		op = &alg->op;
155*e5e7eb02SHerbert Xu 	} else {
156218d1cc1SCorentin LABBE 		dev_err(engine->dev, "failed to do request\n");
157218d1cc1SCorentin LABBE 		ret = -EINVAL;
1586a89f492SIuliana Prodan 		goto req_err_1;
159218d1cc1SCorentin LABBE 	}
160735d37b5SBaolin Wang 
161*e5e7eb02SHerbert Xu 	ret = op->do_one_request(engine, async_req);
1626a89f492SIuliana Prodan 
1636a89f492SIuliana Prodan 	/* Request unsuccessfully executed by hardware */
1646a89f492SIuliana Prodan 	if (ret < 0) {
1656a89f492SIuliana Prodan 		/*
1666a89f492SIuliana Prodan 		 * If hardware queue is full (-ENOSPC), requeue request
1676a89f492SIuliana Prodan 		 * regardless of backlog flag.
1686a89f492SIuliana Prodan 		 * Otherwise, unprepare and complete the request.
1696a89f492SIuliana Prodan 		 */
1706a89f492SIuliana Prodan 		if (!engine->retry_support ||
171d1c72f6eSIuliana Prodan 		    (ret != -ENOSPC)) {
1726a89f492SIuliana Prodan 			dev_err(engine->dev,
1736a89f492SIuliana Prodan 				"Failed to do one request from queue: %d\n",
1746a89f492SIuliana Prodan 				ret);
1756a89f492SIuliana Prodan 			goto req_err_1;
1766a89f492SIuliana Prodan 		}
1776a89f492SIuliana Prodan 		spin_lock_irqsave(&engine->queue_lock, flags);
1786a89f492SIuliana Prodan 		/*
1796a89f492SIuliana Prodan 		 * If hardware was unable to execute request, enqueue it
1806a89f492SIuliana Prodan 		 * back in front of crypto-engine queue, to keep the order
1816a89f492SIuliana Prodan 		 * of requests.
1826a89f492SIuliana Prodan 		 */
1836a89f492SIuliana Prodan 		crypto_enqueue_request_head(&engine->queue, async_req);
1846a89f492SIuliana Prodan 
1856a89f492SIuliana Prodan 		kthread_queue_work(engine->kworker, &engine->pump_requests);
1866a89f492SIuliana Prodan 		goto out;
1876a89f492SIuliana Prodan 	}
1886a89f492SIuliana Prodan 
1896a89f492SIuliana Prodan 	goto retry;
1906a89f492SIuliana Prodan 
1916a89f492SIuliana Prodan req_err_1:
1926909823dSHerbert Xu 	crypto_request_complete(async_req, ret);
1936a89f492SIuliana Prodan 
1946a89f492SIuliana Prodan retry:
1954140aafcSOlivier Bacon 	if (backlog)
1964140aafcSOlivier Bacon 		crypto_request_complete(backlog, -EINPROGRESS);
1974140aafcSOlivier Bacon 
1986a89f492SIuliana Prodan 	/* If retry mechanism is supported, send new requests to engine */
1996a89f492SIuliana Prodan 	if (engine->retry_support) {
2006a89f492SIuliana Prodan 		spin_lock_irqsave(&engine->queue_lock, flags);
2016a89f492SIuliana Prodan 		goto start_request;
2026a89f492SIuliana Prodan 	}
203735d37b5SBaolin Wang 	return;
204735d37b5SBaolin Wang 
205735d37b5SBaolin Wang out:
206735d37b5SBaolin Wang 	spin_unlock_irqrestore(&engine->queue_lock, flags);
2078d908226SIuliana Prodan 
2088d908226SIuliana Prodan 	/*
2098d908226SIuliana Prodan 	 * Batch requests is possible only if
2108d908226SIuliana Prodan 	 * hardware can enqueue multiple requests
2118d908226SIuliana Prodan 	 */
2128d908226SIuliana Prodan 	if (engine->do_batch_requests) {
2138d908226SIuliana Prodan 		ret = engine->do_batch_requests(engine);
2148d908226SIuliana Prodan 		if (ret)
2158d908226SIuliana Prodan 			dev_err(engine->dev, "failed to do batch requests: %d\n",
2168d908226SIuliana Prodan 				ret);
2178d908226SIuliana Prodan 	}
2188d908226SIuliana Prodan 
2196a89f492SIuliana Prodan 	return;
220735d37b5SBaolin Wang }
221735d37b5SBaolin Wang 
crypto_pump_work(struct kthread_work * work)222735d37b5SBaolin Wang static void crypto_pump_work(struct kthread_work *work)
223735d37b5SBaolin Wang {
224735d37b5SBaolin Wang 	struct crypto_engine *engine =
225735d37b5SBaolin Wang 		container_of(work, struct crypto_engine, pump_requests);
226735d37b5SBaolin Wang 
227735d37b5SBaolin Wang 	crypto_pump_requests(engine, true);
228735d37b5SBaolin Wang }
229735d37b5SBaolin Wang 
230735d37b5SBaolin Wang /**
231218d1cc1SCorentin LABBE  * crypto_transfer_request - transfer the new request into the engine queue
232735d37b5SBaolin Wang  * @engine: the hardware engine
233735d37b5SBaolin Wang  * @req: the request need to be listed into the engine queue
234d5db91d2SYang Li  * @need_pump: indicates whether queue the pump of request to kthread_work
235735d37b5SBaolin Wang  */
crypto_transfer_request(struct crypto_engine * engine,struct crypto_async_request * req,bool need_pump)236218d1cc1SCorentin LABBE static int crypto_transfer_request(struct crypto_engine *engine,
237218d1cc1SCorentin LABBE 				   struct crypto_async_request *req,
2384cba7cf0SCorentin LABBE 				   bool need_pump)
239735d37b5SBaolin Wang {
240735d37b5SBaolin Wang 	unsigned long flags;
241735d37b5SBaolin Wang 	int ret;
242735d37b5SBaolin Wang 
243735d37b5SBaolin Wang 	spin_lock_irqsave(&engine->queue_lock, flags);
244735d37b5SBaolin Wang 
245735d37b5SBaolin Wang 	if (!engine->running) {
246735d37b5SBaolin Wang 		spin_unlock_irqrestore(&engine->queue_lock, flags);
247735d37b5SBaolin Wang 		return -ESHUTDOWN;
248735d37b5SBaolin Wang 	}
249735d37b5SBaolin Wang 
250218d1cc1SCorentin LABBE 	ret = crypto_enqueue_request(&engine->queue, req);
251735d37b5SBaolin Wang 
252735d37b5SBaolin Wang 	if (!engine->busy && need_pump)
253c4ca2b0bSPetr Mladek 		kthread_queue_work(engine->kworker, &engine->pump_requests);
254735d37b5SBaolin Wang 
255735d37b5SBaolin Wang 	spin_unlock_irqrestore(&engine->queue_lock, flags);
256735d37b5SBaolin Wang 	return ret;
257735d37b5SBaolin Wang }
258735d37b5SBaolin Wang 
259735d37b5SBaolin Wang /**
260218d1cc1SCorentin LABBE  * crypto_transfer_request_to_engine - transfer one request to list
2614cba7cf0SCorentin LABBE  * into the engine queue
2624cba7cf0SCorentin LABBE  * @engine: the hardware engine
2634cba7cf0SCorentin LABBE  * @req: the request need to be listed into the engine queue
2644cba7cf0SCorentin LABBE  */
crypto_transfer_request_to_engine(struct crypto_engine * engine,struct crypto_async_request * req)265218d1cc1SCorentin LABBE static int crypto_transfer_request_to_engine(struct crypto_engine *engine,
266218d1cc1SCorentin LABBE 					     struct crypto_async_request *req)
267218d1cc1SCorentin LABBE {
268218d1cc1SCorentin LABBE 	return crypto_transfer_request(engine, req, true);
269218d1cc1SCorentin LABBE }
270218d1cc1SCorentin LABBE 
271218d1cc1SCorentin LABBE /**
272218d1cc1SCorentin LABBE  * crypto_transfer_aead_request_to_engine - transfer one aead_request
273218d1cc1SCorentin LABBE  * to list into the engine queue
274735d37b5SBaolin Wang  * @engine: the hardware engine
275735d37b5SBaolin Wang  * @req: the request need to be listed into the engine queue
276735d37b5SBaolin Wang  */
crypto_transfer_aead_request_to_engine(struct crypto_engine * engine,struct aead_request * req)277218d1cc1SCorentin LABBE int crypto_transfer_aead_request_to_engine(struct crypto_engine *engine,
278218d1cc1SCorentin LABBE 					   struct aead_request *req)
279735d37b5SBaolin Wang {
280218d1cc1SCorentin LABBE 	return crypto_transfer_request_to_engine(engine, &req->base);
281735d37b5SBaolin Wang }
282218d1cc1SCorentin LABBE EXPORT_SYMBOL_GPL(crypto_transfer_aead_request_to_engine);
283735d37b5SBaolin Wang 
284735d37b5SBaolin Wang /**
285218d1cc1SCorentin LABBE  * crypto_transfer_akcipher_request_to_engine - transfer one akcipher_request
286218d1cc1SCorentin LABBE  * to list into the engine queue
287218d1cc1SCorentin LABBE  * @engine: the hardware engine
288218d1cc1SCorentin LABBE  * @req: the request need to be listed into the engine queue
289218d1cc1SCorentin LABBE  */
crypto_transfer_akcipher_request_to_engine(struct crypto_engine * engine,struct akcipher_request * req)290218d1cc1SCorentin LABBE int crypto_transfer_akcipher_request_to_engine(struct crypto_engine *engine,
291218d1cc1SCorentin LABBE 					       struct akcipher_request *req)
292218d1cc1SCorentin LABBE {
293218d1cc1SCorentin LABBE 	return crypto_transfer_request_to_engine(engine, &req->base);
294218d1cc1SCorentin LABBE }
295218d1cc1SCorentin LABBE EXPORT_SYMBOL_GPL(crypto_transfer_akcipher_request_to_engine);
296218d1cc1SCorentin LABBE 
297218d1cc1SCorentin LABBE /**
298218d1cc1SCorentin LABBE  * crypto_transfer_hash_request_to_engine - transfer one ahash_request
299218d1cc1SCorentin LABBE  * to list into the engine queue
3004cba7cf0SCorentin LABBE  * @engine: the hardware engine
3014cba7cf0SCorentin LABBE  * @req: the request need to be listed into the engine queue
3024cba7cf0SCorentin LABBE  */
crypto_transfer_hash_request_to_engine(struct crypto_engine * engine,struct ahash_request * req)3034cba7cf0SCorentin LABBE int crypto_transfer_hash_request_to_engine(struct crypto_engine *engine,
3044cba7cf0SCorentin LABBE 					   struct ahash_request *req)
3054cba7cf0SCorentin LABBE {
306218d1cc1SCorentin LABBE 	return crypto_transfer_request_to_engine(engine, &req->base);
3074cba7cf0SCorentin LABBE }
3084cba7cf0SCorentin LABBE EXPORT_SYMBOL_GPL(crypto_transfer_hash_request_to_engine);
3094cba7cf0SCorentin LABBE 
3104cba7cf0SCorentin LABBE /**
3111730c5aaSPrabhjot Khurana  * crypto_transfer_kpp_request_to_engine - transfer one kpp_request to list
3121730c5aaSPrabhjot Khurana  * into the engine queue
3131730c5aaSPrabhjot Khurana  * @engine: the hardware engine
3141730c5aaSPrabhjot Khurana  * @req: the request need to be listed into the engine queue
3151730c5aaSPrabhjot Khurana  */
crypto_transfer_kpp_request_to_engine(struct crypto_engine * engine,struct kpp_request * req)3161730c5aaSPrabhjot Khurana int crypto_transfer_kpp_request_to_engine(struct crypto_engine *engine,
3171730c5aaSPrabhjot Khurana 					  struct kpp_request *req)
3181730c5aaSPrabhjot Khurana {
3191730c5aaSPrabhjot Khurana 	return crypto_transfer_request_to_engine(engine, &req->base);
3201730c5aaSPrabhjot Khurana }
3211730c5aaSPrabhjot Khurana EXPORT_SYMBOL_GPL(crypto_transfer_kpp_request_to_engine);
3221730c5aaSPrabhjot Khurana 
3231730c5aaSPrabhjot Khurana /**
324218d1cc1SCorentin LABBE  * crypto_transfer_skcipher_request_to_engine - transfer one skcipher_request
325218d1cc1SCorentin LABBE  * to list into the engine queue
326218d1cc1SCorentin LABBE  * @engine: the hardware engine
327218d1cc1SCorentin LABBE  * @req: the request need to be listed into the engine queue
328218d1cc1SCorentin LABBE  */
crypto_transfer_skcipher_request_to_engine(struct crypto_engine * engine,struct skcipher_request * req)329218d1cc1SCorentin LABBE int crypto_transfer_skcipher_request_to_engine(struct crypto_engine *engine,
330218d1cc1SCorentin LABBE 					       struct skcipher_request *req)
331218d1cc1SCorentin LABBE {
332218d1cc1SCorentin LABBE 	return crypto_transfer_request_to_engine(engine, &req->base);
333218d1cc1SCorentin LABBE }
334218d1cc1SCorentin LABBE EXPORT_SYMBOL_GPL(crypto_transfer_skcipher_request_to_engine);
335218d1cc1SCorentin LABBE 
336218d1cc1SCorentin LABBE /**
337218d1cc1SCorentin LABBE  * crypto_finalize_aead_request - finalize one aead_request if
338218d1cc1SCorentin LABBE  * the request is done
339735d37b5SBaolin Wang  * @engine: the hardware engine
340735d37b5SBaolin Wang  * @req: the request need to be finalized
341735d37b5SBaolin Wang  * @err: error number
342735d37b5SBaolin Wang  */
crypto_finalize_aead_request(struct crypto_engine * engine,struct aead_request * req,int err)343218d1cc1SCorentin LABBE void crypto_finalize_aead_request(struct crypto_engine *engine,
344218d1cc1SCorentin LABBE 				  struct aead_request *req, int err)
345735d37b5SBaolin Wang {
346218d1cc1SCorentin LABBE 	return crypto_finalize_request(engine, &req->base, err);
347735d37b5SBaolin Wang }
348218d1cc1SCorentin LABBE EXPORT_SYMBOL_GPL(crypto_finalize_aead_request);
3494cba7cf0SCorentin LABBE 
3504cba7cf0SCorentin LABBE /**
351218d1cc1SCorentin LABBE  * crypto_finalize_akcipher_request - finalize one akcipher_request if
352218d1cc1SCorentin LABBE  * the request is done
353218d1cc1SCorentin LABBE  * @engine: the hardware engine
354218d1cc1SCorentin LABBE  * @req: the request need to be finalized
355218d1cc1SCorentin LABBE  * @err: error number
356218d1cc1SCorentin LABBE  */
crypto_finalize_akcipher_request(struct crypto_engine * engine,struct akcipher_request * req,int err)357218d1cc1SCorentin LABBE void crypto_finalize_akcipher_request(struct crypto_engine *engine,
358218d1cc1SCorentin LABBE 				      struct akcipher_request *req, int err)
359218d1cc1SCorentin LABBE {
360218d1cc1SCorentin LABBE 	return crypto_finalize_request(engine, &req->base, err);
361218d1cc1SCorentin LABBE }
362218d1cc1SCorentin LABBE EXPORT_SYMBOL_GPL(crypto_finalize_akcipher_request);
363218d1cc1SCorentin LABBE 
364218d1cc1SCorentin LABBE /**
365218d1cc1SCorentin LABBE  * crypto_finalize_hash_request - finalize one ahash_request if
366218d1cc1SCorentin LABBE  * the request is done
3674cba7cf0SCorentin LABBE  * @engine: the hardware engine
3684cba7cf0SCorentin LABBE  * @req: the request need to be finalized
3694cba7cf0SCorentin LABBE  * @err: error number
3704cba7cf0SCorentin LABBE  */
crypto_finalize_hash_request(struct crypto_engine * engine,struct ahash_request * req,int err)3714cba7cf0SCorentin LABBE void crypto_finalize_hash_request(struct crypto_engine *engine,
3724cba7cf0SCorentin LABBE 				  struct ahash_request *req, int err)
3734cba7cf0SCorentin LABBE {
374218d1cc1SCorentin LABBE 	return crypto_finalize_request(engine, &req->base, err);
3754cba7cf0SCorentin LABBE }
3764cba7cf0SCorentin LABBE EXPORT_SYMBOL_GPL(crypto_finalize_hash_request);
377735d37b5SBaolin Wang 
378735d37b5SBaolin Wang /**
3791730c5aaSPrabhjot Khurana  * crypto_finalize_kpp_request - finalize one kpp_request if the request is done
3801730c5aaSPrabhjot Khurana  * @engine: the hardware engine
3811730c5aaSPrabhjot Khurana  * @req: the request need to be finalized
3821730c5aaSPrabhjot Khurana  * @err: error number
3831730c5aaSPrabhjot Khurana  */
crypto_finalize_kpp_request(struct crypto_engine * engine,struct kpp_request * req,int err)3841730c5aaSPrabhjot Khurana void crypto_finalize_kpp_request(struct crypto_engine *engine,
3851730c5aaSPrabhjot Khurana 				 struct kpp_request *req, int err)
3861730c5aaSPrabhjot Khurana {
3871730c5aaSPrabhjot Khurana 	return crypto_finalize_request(engine, &req->base, err);
3881730c5aaSPrabhjot Khurana }
3891730c5aaSPrabhjot Khurana EXPORT_SYMBOL_GPL(crypto_finalize_kpp_request);
3901730c5aaSPrabhjot Khurana 
3911730c5aaSPrabhjot Khurana /**
392218d1cc1SCorentin LABBE  * crypto_finalize_skcipher_request - finalize one skcipher_request if
393218d1cc1SCorentin LABBE  * the request is done
394218d1cc1SCorentin LABBE  * @engine: the hardware engine
395218d1cc1SCorentin LABBE  * @req: the request need to be finalized
396218d1cc1SCorentin LABBE  * @err: error number
397218d1cc1SCorentin LABBE  */
crypto_finalize_skcipher_request(struct crypto_engine * engine,struct skcipher_request * req,int err)398218d1cc1SCorentin LABBE void crypto_finalize_skcipher_request(struct crypto_engine *engine,
399218d1cc1SCorentin LABBE 				      struct skcipher_request *req, int err)
400218d1cc1SCorentin LABBE {
401218d1cc1SCorentin LABBE 	return crypto_finalize_request(engine, &req->base, err);
402218d1cc1SCorentin LABBE }
403218d1cc1SCorentin LABBE EXPORT_SYMBOL_GPL(crypto_finalize_skcipher_request);
404218d1cc1SCorentin LABBE 
405218d1cc1SCorentin LABBE /**
406735d37b5SBaolin Wang  * crypto_engine_start - start the hardware engine
407735d37b5SBaolin Wang  * @engine: the hardware engine need to be started
408735d37b5SBaolin Wang  *
409735d37b5SBaolin Wang  * Return 0 on success, else on fail.
410735d37b5SBaolin Wang  */
crypto_engine_start(struct crypto_engine * engine)411735d37b5SBaolin Wang int crypto_engine_start(struct crypto_engine *engine)
412735d37b5SBaolin Wang {
413735d37b5SBaolin Wang 	unsigned long flags;
414735d37b5SBaolin Wang 
415735d37b5SBaolin Wang 	spin_lock_irqsave(&engine->queue_lock, flags);
416735d37b5SBaolin Wang 
417735d37b5SBaolin Wang 	if (engine->running || engine->busy) {
418735d37b5SBaolin Wang 		spin_unlock_irqrestore(&engine->queue_lock, flags);
419735d37b5SBaolin Wang 		return -EBUSY;
420735d37b5SBaolin Wang 	}
421735d37b5SBaolin Wang 
422735d37b5SBaolin Wang 	engine->running = true;
423735d37b5SBaolin Wang 	spin_unlock_irqrestore(&engine->queue_lock, flags);
424735d37b5SBaolin Wang 
425c4ca2b0bSPetr Mladek 	kthread_queue_work(engine->kworker, &engine->pump_requests);
426735d37b5SBaolin Wang 
427735d37b5SBaolin Wang 	return 0;
428735d37b5SBaolin Wang }
429735d37b5SBaolin Wang EXPORT_SYMBOL_GPL(crypto_engine_start);
430735d37b5SBaolin Wang 
431735d37b5SBaolin Wang /**
432735d37b5SBaolin Wang  * crypto_engine_stop - stop the hardware engine
433735d37b5SBaolin Wang  * @engine: the hardware engine need to be stopped
434735d37b5SBaolin Wang  *
435735d37b5SBaolin Wang  * Return 0 on success, else on fail.
436735d37b5SBaolin Wang  */
crypto_engine_stop(struct crypto_engine * engine)437735d37b5SBaolin Wang int crypto_engine_stop(struct crypto_engine *engine)
438735d37b5SBaolin Wang {
439735d37b5SBaolin Wang 	unsigned long flags;
4404cba7cf0SCorentin LABBE 	unsigned int limit = 500;
441735d37b5SBaolin Wang 	int ret = 0;
442735d37b5SBaolin Wang 
443735d37b5SBaolin Wang 	spin_lock_irqsave(&engine->queue_lock, flags);
444735d37b5SBaolin Wang 
445735d37b5SBaolin Wang 	/*
446735d37b5SBaolin Wang 	 * If the engine queue is not empty or the engine is on busy state,
447735d37b5SBaolin Wang 	 * we need to wait for a while to pump the requests of engine queue.
448735d37b5SBaolin Wang 	 */
449735d37b5SBaolin Wang 	while ((crypto_queue_len(&engine->queue) || engine->busy) && limit--) {
450735d37b5SBaolin Wang 		spin_unlock_irqrestore(&engine->queue_lock, flags);
451735d37b5SBaolin Wang 		msleep(20);
452735d37b5SBaolin Wang 		spin_lock_irqsave(&engine->queue_lock, flags);
453735d37b5SBaolin Wang 	}
454735d37b5SBaolin Wang 
455735d37b5SBaolin Wang 	if (crypto_queue_len(&engine->queue) || engine->busy)
456735d37b5SBaolin Wang 		ret = -EBUSY;
457735d37b5SBaolin Wang 	else
458735d37b5SBaolin Wang 		engine->running = false;
459735d37b5SBaolin Wang 
460735d37b5SBaolin Wang 	spin_unlock_irqrestore(&engine->queue_lock, flags);
461735d37b5SBaolin Wang 
462735d37b5SBaolin Wang 	if (ret)
46388d58ef8SCorentin LABBE 		dev_warn(engine->dev, "could not stop engine\n");
464735d37b5SBaolin Wang 
465735d37b5SBaolin Wang 	return ret;
466735d37b5SBaolin Wang }
467735d37b5SBaolin Wang EXPORT_SYMBOL_GPL(crypto_engine_stop);
468735d37b5SBaolin Wang 
469735d37b5SBaolin Wang /**
4706a89f492SIuliana Prodan  * crypto_engine_alloc_init_and_set - allocate crypto hardware engine structure
4716a89f492SIuliana Prodan  * and initialize it by setting the maximum number of entries in the software
4726a89f492SIuliana Prodan  * crypto-engine queue.
473735d37b5SBaolin Wang  * @dev: the device attached with one hardware engine
4746a89f492SIuliana Prodan  * @retry_support: whether hardware has support for retry mechanism
47540a3af45SRandy Dunlap  * @cbk_do_batch: pointer to a callback function to be invoked when executing
4768d908226SIuliana Prodan  *                a batch of requests.
4778d908226SIuliana Prodan  *                This has the form:
4788d908226SIuliana Prodan  *                callback(struct crypto_engine *engine)
4798d908226SIuliana Prodan  *                where:
48042a9a08bSHerbert Xu  *                engine: the crypto engine structure.
481735d37b5SBaolin Wang  * @rt: whether this queue is set to run as a realtime task
4826a89f492SIuliana Prodan  * @qlen: maximum size of the crypto-engine queue
483735d37b5SBaolin Wang  *
484735d37b5SBaolin Wang  * This must be called from context that can sleep.
485735d37b5SBaolin Wang  * Return: the crypto engine structure on success, else NULL.
486735d37b5SBaolin Wang  */
crypto_engine_alloc_init_and_set(struct device * dev,bool retry_support,int (* cbk_do_batch)(struct crypto_engine * engine),bool rt,int qlen)4876a89f492SIuliana Prodan struct crypto_engine *crypto_engine_alloc_init_and_set(struct device *dev,
4886a89f492SIuliana Prodan 						       bool retry_support,
4898d908226SIuliana Prodan 						       int (*cbk_do_batch)(struct crypto_engine *engine),
4906a89f492SIuliana Prodan 						       bool rt, int qlen)
491735d37b5SBaolin Wang {
492735d37b5SBaolin Wang 	struct crypto_engine *engine;
493735d37b5SBaolin Wang 
494735d37b5SBaolin Wang 	if (!dev)
495735d37b5SBaolin Wang 		return NULL;
496735d37b5SBaolin Wang 
497735d37b5SBaolin Wang 	engine = devm_kzalloc(dev, sizeof(*engine), GFP_KERNEL);
498735d37b5SBaolin Wang 	if (!engine)
499735d37b5SBaolin Wang 		return NULL;
500735d37b5SBaolin Wang 
50188d58ef8SCorentin LABBE 	engine->dev = dev;
502735d37b5SBaolin Wang 	engine->rt = rt;
503735d37b5SBaolin Wang 	engine->running = false;
504735d37b5SBaolin Wang 	engine->busy = false;
505735d37b5SBaolin Wang 	engine->idling = false;
5066a89f492SIuliana Prodan 	engine->retry_support = retry_support;
507735d37b5SBaolin Wang 	engine->priv_data = dev;
5088d908226SIuliana Prodan 	/*
5098d908226SIuliana Prodan 	 * Batch requests is possible only if
5108d908226SIuliana Prodan 	 * hardware has support for retry mechanism.
5118d908226SIuliana Prodan 	 */
5128d908226SIuliana Prodan 	engine->do_batch_requests = retry_support ? cbk_do_batch : NULL;
5138d908226SIuliana Prodan 
514735d37b5SBaolin Wang 	snprintf(engine->name, sizeof(engine->name),
515735d37b5SBaolin Wang 		 "%s-engine", dev_name(dev));
516735d37b5SBaolin Wang 
5176a89f492SIuliana Prodan 	crypto_init_queue(&engine->queue, qlen);
518735d37b5SBaolin Wang 	spin_lock_init(&engine->queue_lock);
519735d37b5SBaolin Wang 
520c4ca2b0bSPetr Mladek 	engine->kworker = kthread_create_worker(0, "%s", engine->name);
521c4ca2b0bSPetr Mladek 	if (IS_ERR(engine->kworker)) {
522735d37b5SBaolin Wang 		dev_err(dev, "failed to create crypto request pump task\n");
523735d37b5SBaolin Wang 		return NULL;
524735d37b5SBaolin Wang 	}
5253989144fSPetr Mladek 	kthread_init_work(&engine->pump_requests, crypto_pump_work);
526735d37b5SBaolin Wang 
527735d37b5SBaolin Wang 	if (engine->rt) {
528735d37b5SBaolin Wang 		dev_info(dev, "will run requests pump with realtime priority\n");
529dbc6d0d5SPeter Zijlstra 		sched_set_fifo(engine->kworker->task);
530735d37b5SBaolin Wang 	}
531735d37b5SBaolin Wang 
532735d37b5SBaolin Wang 	return engine;
533735d37b5SBaolin Wang }
5346a89f492SIuliana Prodan EXPORT_SYMBOL_GPL(crypto_engine_alloc_init_and_set);
5356a89f492SIuliana Prodan 
5366a89f492SIuliana Prodan /**
5376a89f492SIuliana Prodan  * crypto_engine_alloc_init - allocate crypto hardware engine structure and
5386a89f492SIuliana Prodan  * initialize it.
5396a89f492SIuliana Prodan  * @dev: the device attached with one hardware engine
5406a89f492SIuliana Prodan  * @rt: whether this queue is set to run as a realtime task
5416a89f492SIuliana Prodan  *
5426a89f492SIuliana Prodan  * This must be called from context that can sleep.
5436a89f492SIuliana Prodan  * Return: the crypto engine structure on success, else NULL.
5446a89f492SIuliana Prodan  */
crypto_engine_alloc_init(struct device * dev,bool rt)5456a89f492SIuliana Prodan struct crypto_engine *crypto_engine_alloc_init(struct device *dev, bool rt)
5466a89f492SIuliana Prodan {
5478d908226SIuliana Prodan 	return crypto_engine_alloc_init_and_set(dev, false, NULL, rt,
5486a89f492SIuliana Prodan 						CRYPTO_ENGINE_MAX_QLEN);
5496a89f492SIuliana Prodan }
550735d37b5SBaolin Wang EXPORT_SYMBOL_GPL(crypto_engine_alloc_init);
551735d37b5SBaolin Wang 
552735d37b5SBaolin Wang /**
553735d37b5SBaolin Wang  * crypto_engine_exit - free the resources of hardware engine when exit
554735d37b5SBaolin Wang  * @engine: the hardware engine need to be freed
555735d37b5SBaolin Wang  *
556735d37b5SBaolin Wang  * Return 0 for success.
557735d37b5SBaolin Wang  */
crypto_engine_exit(struct crypto_engine * engine)558735d37b5SBaolin Wang int crypto_engine_exit(struct crypto_engine *engine)
559735d37b5SBaolin Wang {
560735d37b5SBaolin Wang 	int ret;
561735d37b5SBaolin Wang 
562735d37b5SBaolin Wang 	ret = crypto_engine_stop(engine);
563735d37b5SBaolin Wang 	if (ret)
564735d37b5SBaolin Wang 		return ret;
565735d37b5SBaolin Wang 
566c4ca2b0bSPetr Mladek 	kthread_destroy_worker(engine->kworker);
567735d37b5SBaolin Wang 
568735d37b5SBaolin Wang 	return 0;
569735d37b5SBaolin Wang }
570735d37b5SBaolin Wang EXPORT_SYMBOL_GPL(crypto_engine_exit);
571735d37b5SBaolin Wang 
crypto_engine_register_aead(struct aead_engine_alg * alg)572*e5e7eb02SHerbert Xu int crypto_engine_register_aead(struct aead_engine_alg *alg)
573*e5e7eb02SHerbert Xu {
574*e5e7eb02SHerbert Xu 	if (!alg->op.do_one_request)
575*e5e7eb02SHerbert Xu 		return -EINVAL;
576*e5e7eb02SHerbert Xu 
577*e5e7eb02SHerbert Xu 	alg->base.base.cra_flags |= CRYPTO_ALG_ENGINE;
578*e5e7eb02SHerbert Xu 
579*e5e7eb02SHerbert Xu 	return crypto_register_aead(&alg->base);
580*e5e7eb02SHerbert Xu }
581*e5e7eb02SHerbert Xu EXPORT_SYMBOL_GPL(crypto_engine_register_aead);
582*e5e7eb02SHerbert Xu 
crypto_engine_unregister_aead(struct aead_engine_alg * alg)583*e5e7eb02SHerbert Xu void crypto_engine_unregister_aead(struct aead_engine_alg *alg)
584*e5e7eb02SHerbert Xu {
585*e5e7eb02SHerbert Xu 	crypto_unregister_aead(&alg->base);
586*e5e7eb02SHerbert Xu }
587*e5e7eb02SHerbert Xu EXPORT_SYMBOL_GPL(crypto_engine_unregister_aead);
588*e5e7eb02SHerbert Xu 
crypto_engine_register_aeads(struct aead_engine_alg * algs,int count)589*e5e7eb02SHerbert Xu int crypto_engine_register_aeads(struct aead_engine_alg *algs, int count)
590*e5e7eb02SHerbert Xu {
591*e5e7eb02SHerbert Xu 	int i, ret;
592*e5e7eb02SHerbert Xu 
593*e5e7eb02SHerbert Xu 	for (i = 0; i < count; i++) {
594*e5e7eb02SHerbert Xu 		ret = crypto_engine_register_aead(&algs[i]);
595*e5e7eb02SHerbert Xu 		if (ret)
596*e5e7eb02SHerbert Xu 			goto err;
597*e5e7eb02SHerbert Xu 	}
598*e5e7eb02SHerbert Xu 
599*e5e7eb02SHerbert Xu 	return 0;
600*e5e7eb02SHerbert Xu 
601*e5e7eb02SHerbert Xu err:
602*e5e7eb02SHerbert Xu 	crypto_engine_unregister_aeads(algs, i);
603*e5e7eb02SHerbert Xu 
604*e5e7eb02SHerbert Xu 	return ret;
605*e5e7eb02SHerbert Xu }
606*e5e7eb02SHerbert Xu EXPORT_SYMBOL_GPL(crypto_engine_register_aeads);
607*e5e7eb02SHerbert Xu 
crypto_engine_unregister_aeads(struct aead_engine_alg * algs,int count)608*e5e7eb02SHerbert Xu void crypto_engine_unregister_aeads(struct aead_engine_alg *algs, int count)
609*e5e7eb02SHerbert Xu {
610*e5e7eb02SHerbert Xu 	int i;
611*e5e7eb02SHerbert Xu 
612*e5e7eb02SHerbert Xu 	for (i = count - 1; i >= 0; --i)
613*e5e7eb02SHerbert Xu 		crypto_engine_unregister_aead(&algs[i]);
614*e5e7eb02SHerbert Xu }
615*e5e7eb02SHerbert Xu EXPORT_SYMBOL_GPL(crypto_engine_unregister_aeads);
616*e5e7eb02SHerbert Xu 
crypto_engine_register_ahash(struct ahash_engine_alg * alg)617*e5e7eb02SHerbert Xu int crypto_engine_register_ahash(struct ahash_engine_alg *alg)
618*e5e7eb02SHerbert Xu {
619*e5e7eb02SHerbert Xu 	if (!alg->op.do_one_request)
620*e5e7eb02SHerbert Xu 		return -EINVAL;
621*e5e7eb02SHerbert Xu 
622*e5e7eb02SHerbert Xu 	alg->base.halg.base.cra_flags |= CRYPTO_ALG_ENGINE;
623*e5e7eb02SHerbert Xu 
624*e5e7eb02SHerbert Xu 	return crypto_register_ahash(&alg->base);
625*e5e7eb02SHerbert Xu }
626*e5e7eb02SHerbert Xu EXPORT_SYMBOL_GPL(crypto_engine_register_ahash);
627*e5e7eb02SHerbert Xu 
crypto_engine_unregister_ahash(struct ahash_engine_alg * alg)628*e5e7eb02SHerbert Xu void crypto_engine_unregister_ahash(struct ahash_engine_alg *alg)
629*e5e7eb02SHerbert Xu {
630*e5e7eb02SHerbert Xu 	crypto_unregister_ahash(&alg->base);
631*e5e7eb02SHerbert Xu }
632*e5e7eb02SHerbert Xu EXPORT_SYMBOL_GPL(crypto_engine_unregister_ahash);
633*e5e7eb02SHerbert Xu 
crypto_engine_register_ahashes(struct ahash_engine_alg * algs,int count)634*e5e7eb02SHerbert Xu int crypto_engine_register_ahashes(struct ahash_engine_alg *algs, int count)
635*e5e7eb02SHerbert Xu {
636*e5e7eb02SHerbert Xu 	int i, ret;
637*e5e7eb02SHerbert Xu 
638*e5e7eb02SHerbert Xu 	for (i = 0; i < count; i++) {
639*e5e7eb02SHerbert Xu 		ret = crypto_engine_register_ahash(&algs[i]);
640*e5e7eb02SHerbert Xu 		if (ret)
641*e5e7eb02SHerbert Xu 			goto err;
642*e5e7eb02SHerbert Xu 	}
643*e5e7eb02SHerbert Xu 
644*e5e7eb02SHerbert Xu 	return 0;
645*e5e7eb02SHerbert Xu 
646*e5e7eb02SHerbert Xu err:
647*e5e7eb02SHerbert Xu 	crypto_engine_unregister_ahashes(algs, i);
648*e5e7eb02SHerbert Xu 
649*e5e7eb02SHerbert Xu 	return ret;
650*e5e7eb02SHerbert Xu }
651*e5e7eb02SHerbert Xu EXPORT_SYMBOL_GPL(crypto_engine_register_ahashes);
652*e5e7eb02SHerbert Xu 
crypto_engine_unregister_ahashes(struct ahash_engine_alg * algs,int count)653*e5e7eb02SHerbert Xu void crypto_engine_unregister_ahashes(struct ahash_engine_alg *algs,
654*e5e7eb02SHerbert Xu 				      int count)
655*e5e7eb02SHerbert Xu {
656*e5e7eb02SHerbert Xu 	int i;
657*e5e7eb02SHerbert Xu 
658*e5e7eb02SHerbert Xu 	for (i = count - 1; i >= 0; --i)
659*e5e7eb02SHerbert Xu 		crypto_engine_unregister_ahash(&algs[i]);
660*e5e7eb02SHerbert Xu }
661*e5e7eb02SHerbert Xu EXPORT_SYMBOL_GPL(crypto_engine_unregister_ahashes);
662*e5e7eb02SHerbert Xu 
crypto_engine_register_akcipher(struct akcipher_engine_alg * alg)663*e5e7eb02SHerbert Xu int crypto_engine_register_akcipher(struct akcipher_engine_alg *alg)
664*e5e7eb02SHerbert Xu {
665*e5e7eb02SHerbert Xu 	if (!alg->op.do_one_request)
666*e5e7eb02SHerbert Xu 		return -EINVAL;
667*e5e7eb02SHerbert Xu 
668*e5e7eb02SHerbert Xu 	alg->base.base.cra_flags |= CRYPTO_ALG_ENGINE;
669*e5e7eb02SHerbert Xu 
670*e5e7eb02SHerbert Xu 	return crypto_register_akcipher(&alg->base);
671*e5e7eb02SHerbert Xu }
672*e5e7eb02SHerbert Xu EXPORT_SYMBOL_GPL(crypto_engine_register_akcipher);
673*e5e7eb02SHerbert Xu 
crypto_engine_unregister_akcipher(struct akcipher_engine_alg * alg)674*e5e7eb02SHerbert Xu void crypto_engine_unregister_akcipher(struct akcipher_engine_alg *alg)
675*e5e7eb02SHerbert Xu {
676*e5e7eb02SHerbert Xu 	crypto_unregister_akcipher(&alg->base);
677*e5e7eb02SHerbert Xu }
678*e5e7eb02SHerbert Xu EXPORT_SYMBOL_GPL(crypto_engine_unregister_akcipher);
679*e5e7eb02SHerbert Xu 
crypto_engine_register_kpp(struct kpp_engine_alg * alg)680*e5e7eb02SHerbert Xu int crypto_engine_register_kpp(struct kpp_engine_alg *alg)
681*e5e7eb02SHerbert Xu {
682*e5e7eb02SHerbert Xu 	if (!alg->op.do_one_request)
683*e5e7eb02SHerbert Xu 		return -EINVAL;
684*e5e7eb02SHerbert Xu 
685*e5e7eb02SHerbert Xu 	alg->base.base.cra_flags |= CRYPTO_ALG_ENGINE;
686*e5e7eb02SHerbert Xu 
687*e5e7eb02SHerbert Xu 	return crypto_register_kpp(&alg->base);
688*e5e7eb02SHerbert Xu }
689*e5e7eb02SHerbert Xu EXPORT_SYMBOL_GPL(crypto_engine_register_kpp);
690*e5e7eb02SHerbert Xu 
crypto_engine_unregister_kpp(struct kpp_engine_alg * alg)691*e5e7eb02SHerbert Xu void crypto_engine_unregister_kpp(struct kpp_engine_alg *alg)
692*e5e7eb02SHerbert Xu {
693*e5e7eb02SHerbert Xu 	crypto_unregister_kpp(&alg->base);
694*e5e7eb02SHerbert Xu }
695*e5e7eb02SHerbert Xu EXPORT_SYMBOL_GPL(crypto_engine_unregister_kpp);
696*e5e7eb02SHerbert Xu 
crypto_engine_register_skcipher(struct skcipher_engine_alg * alg)697*e5e7eb02SHerbert Xu int crypto_engine_register_skcipher(struct skcipher_engine_alg *alg)
698*e5e7eb02SHerbert Xu {
699*e5e7eb02SHerbert Xu 	if (!alg->op.do_one_request)
700*e5e7eb02SHerbert Xu 		return -EINVAL;
701*e5e7eb02SHerbert Xu 
702*e5e7eb02SHerbert Xu 	alg->base.base.cra_flags |= CRYPTO_ALG_ENGINE;
703*e5e7eb02SHerbert Xu 
704*e5e7eb02SHerbert Xu 	return crypto_register_skcipher(&alg->base);
705*e5e7eb02SHerbert Xu }
706*e5e7eb02SHerbert Xu EXPORT_SYMBOL_GPL(crypto_engine_register_skcipher);
707*e5e7eb02SHerbert Xu 
crypto_engine_unregister_skcipher(struct skcipher_engine_alg * alg)708*e5e7eb02SHerbert Xu void crypto_engine_unregister_skcipher(struct skcipher_engine_alg *alg)
709*e5e7eb02SHerbert Xu {
710*e5e7eb02SHerbert Xu 	return crypto_unregister_skcipher(&alg->base);
711*e5e7eb02SHerbert Xu }
712*e5e7eb02SHerbert Xu EXPORT_SYMBOL_GPL(crypto_engine_unregister_skcipher);
713*e5e7eb02SHerbert Xu 
crypto_engine_register_skciphers(struct skcipher_engine_alg * algs,int count)714*e5e7eb02SHerbert Xu int crypto_engine_register_skciphers(struct skcipher_engine_alg *algs,
715*e5e7eb02SHerbert Xu 				     int count)
716*e5e7eb02SHerbert Xu {
717*e5e7eb02SHerbert Xu 	int i, ret;
718*e5e7eb02SHerbert Xu 
719*e5e7eb02SHerbert Xu 	for (i = 0; i < count; i++) {
720*e5e7eb02SHerbert Xu 		ret = crypto_engine_register_skcipher(&algs[i]);
721*e5e7eb02SHerbert Xu 		if (ret)
722*e5e7eb02SHerbert Xu 			goto err;
723*e5e7eb02SHerbert Xu 	}
724*e5e7eb02SHerbert Xu 
725*e5e7eb02SHerbert Xu 	return 0;
726*e5e7eb02SHerbert Xu 
727*e5e7eb02SHerbert Xu err:
728*e5e7eb02SHerbert Xu 	crypto_engine_unregister_skciphers(algs, i);
729*e5e7eb02SHerbert Xu 
730*e5e7eb02SHerbert Xu 	return ret;
731*e5e7eb02SHerbert Xu }
732*e5e7eb02SHerbert Xu EXPORT_SYMBOL_GPL(crypto_engine_register_skciphers);
733*e5e7eb02SHerbert Xu 
crypto_engine_unregister_skciphers(struct skcipher_engine_alg * algs,int count)734*e5e7eb02SHerbert Xu void crypto_engine_unregister_skciphers(struct skcipher_engine_alg *algs,
735*e5e7eb02SHerbert Xu 					int count)
736*e5e7eb02SHerbert Xu {
737*e5e7eb02SHerbert Xu 	int i;
738*e5e7eb02SHerbert Xu 
739*e5e7eb02SHerbert Xu 	for (i = count - 1; i >= 0; --i)
740*e5e7eb02SHerbert Xu 		crypto_engine_unregister_skcipher(&algs[i]);
741*e5e7eb02SHerbert Xu }
742*e5e7eb02SHerbert Xu EXPORT_SYMBOL_GPL(crypto_engine_unregister_skciphers);
743*e5e7eb02SHerbert Xu 
744735d37b5SBaolin Wang MODULE_LICENSE("GPL");
745735d37b5SBaolin Wang MODULE_DESCRIPTION("Crypto hardware engine framework");
746