Blame view

crypto/crypto_engine.c 15.3 KB
2874c5fd2   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-or-later
735d37b54   Baolin Wang   crypto: engine - ...
2
3
4
5
6
7
  /*
   * Handle async block request by crypto hardware engine.
   *
   * Copyright (C) 2016 Linaro, Inc.
   *
   * Author: Baolin Wang <baolin.wang@linaro.org>
735d37b54   Baolin Wang   crypto: engine - ...
8
9
10
11
   */
  
  #include <linux/err.h>
  #include <linux/delay.h>
0c3dc787a   Herbert Xu   crypto: algapi - ...
12
  #include <linux/device.h>
2589ad840   Corentin LABBE   crypto: engine - ...
13
  #include <crypto/engine.h>
ae7e81c07   Ingo Molnar   sched/headers: Pr...
14
  #include <uapi/linux/sched/types.h>
735d37b54   Baolin Wang   crypto: engine - ...
15
16
17
  #include "internal.h"
  
  #define CRYPTO_ENGINE_MAX_QLEN 10
735d37b54   Baolin Wang   crypto: engine - ...
18
  /**
218d1cc18   Corentin LABBE   crypto: engine - ...
19
20
21
22
23
24
   * crypto_finalize_request - finalize one request if the request is done
   * @engine: the hardware engine
   * @req: the request need to be finalized
   * @err: error number
   */
  static void crypto_finalize_request(struct crypto_engine *engine,
6a89f492f   Iuliana Prodan   crypto: engine - ...
25
  				    struct crypto_async_request *req, int err)
218d1cc18   Corentin LABBE   crypto: engine - ...
26
27
  {
  	unsigned long flags;
6a89f492f   Iuliana Prodan   crypto: engine - ...
28
  	bool finalize_req = false;
218d1cc18   Corentin LABBE   crypto: engine - ...
29
30
  	int ret;
  	struct crypto_engine_ctx *enginectx;
6a89f492f   Iuliana Prodan   crypto: engine - ...
31
32
33
34
35
36
37
38
39
40
41
42
43
  	/*
  	 * If hardware cannot enqueue more requests
  	 * and retry mechanism is not supported
  	 * make sure we are completing the current request
  	 */
  	if (!engine->retry_support) {
  		spin_lock_irqsave(&engine->queue_lock, flags);
  		if (engine->cur_req == req) {
  			finalize_req = true;
  			engine->cur_req = NULL;
  		}
  		spin_unlock_irqrestore(&engine->queue_lock, flags);
  	}
218d1cc18   Corentin LABBE   crypto: engine - ...
44

6a89f492f   Iuliana Prodan   crypto: engine - ...
45
  	if (finalize_req || engine->retry_support) {
218d1cc18   Corentin LABBE   crypto: engine - ...
46
  		enginectx = crypto_tfm_ctx(req->tfm);
6a89f492f   Iuliana Prodan   crypto: engine - ...
47
  		if (enginectx->op.prepare_request &&
218d1cc18   Corentin LABBE   crypto: engine - ...
48
49
50
51
52
53
  		    enginectx->op.unprepare_request) {
  			ret = enginectx->op.unprepare_request(engine, req);
  			if (ret)
  				dev_err(engine->dev, "failed to unprepare request
  ");
  		}
218d1cc18   Corentin LABBE   crypto: engine - ...
54
  	}
218d1cc18   Corentin LABBE   crypto: engine - ...
55
56
57
58
59
60
  	req->complete(req, err);
  
  	kthread_queue_work(engine->kworker, &engine->pump_requests);
  }
  
  /**
735d37b54   Baolin Wang   crypto: engine - ...
61
62
63
64
65
66
67
68
69
70
71
72
   * crypto_pump_requests - dequeue one request from engine queue to process
   * @engine: the hardware engine
   * @in_kthread: true if we are in the context of the request pump thread
   *
   * This function checks if there is any request in the engine queue that
   * needs processing and if so call out to the driver to initialize hardware
   * and handle each request.
   */
  static void crypto_pump_requests(struct crypto_engine *engine,
  				 bool in_kthread)
  {
  	struct crypto_async_request *async_req, *backlog;
735d37b54   Baolin Wang   crypto: engine - ...
73
74
  	unsigned long flags;
  	bool was_busy = false;
218d1cc18   Corentin LABBE   crypto: engine - ...
75
76
  	int ret;
  	struct crypto_engine_ctx *enginectx;
735d37b54   Baolin Wang   crypto: engine - ...
77
78
79
80
  
  	spin_lock_irqsave(&engine->queue_lock, flags);
  
  	/* Make sure we are not already running a request */
6a89f492f   Iuliana Prodan   crypto: engine - ...
81
  	if (!engine->retry_support && engine->cur_req)
735d37b54   Baolin Wang   crypto: engine - ...
82
83
84
85
  		goto out;
  
  	/* If another context is idling then defer */
  	if (engine->idling) {
c4ca2b0b2   Petr Mladek   crypto: engine - ...
86
  		kthread_queue_work(engine->kworker, &engine->pump_requests);
735d37b54   Baolin Wang   crypto: engine - ...
87
88
89
90
91
92
93
94
95
96
  		goto out;
  	}
  
  	/* Check if the engine queue is idle */
  	if (!crypto_queue_len(&engine->queue) || !engine->running) {
  		if (!engine->busy)
  			goto out;
  
  		/* Only do teardown in the thread */
  		if (!in_kthread) {
c4ca2b0b2   Petr Mladek   crypto: engine - ...
97
  			kthread_queue_work(engine->kworker,
735d37b54   Baolin Wang   crypto: engine - ...
98
99
100
101
102
103
104
105
106
107
  					   &engine->pump_requests);
  			goto out;
  		}
  
  		engine->busy = false;
  		engine->idling = true;
  		spin_unlock_irqrestore(&engine->queue_lock, flags);
  
  		if (engine->unprepare_crypt_hardware &&
  		    engine->unprepare_crypt_hardware(engine))
88d58ef89   Corentin LABBE   crypto: engine - ...
108
109
  			dev_err(engine->dev, "failed to unprepare crypt hardware
  ");
735d37b54   Baolin Wang   crypto: engine - ...
110
111
112
113
114
  
  		spin_lock_irqsave(&engine->queue_lock, flags);
  		engine->idling = false;
  		goto out;
  	}
6a89f492f   Iuliana Prodan   crypto: engine - ...
115
  start_request:
735d37b54   Baolin Wang   crypto: engine - ...
116
117
118
119
120
  	/* Get the fist request from the engine queue to handle */
  	backlog = crypto_get_backlog(&engine->queue);
  	async_req = crypto_dequeue_request(&engine->queue);
  	if (!async_req)
  		goto out;
6a89f492f   Iuliana Prodan   crypto: engine - ...
121
122
123
124
125
126
127
  	/*
  	 * If hardware doesn't support the retry mechanism,
  	 * keep track of the request we are processing now.
  	 * We'll need it on completion (crypto_finalize_request).
  	 */
  	if (!engine->retry_support)
  		engine->cur_req = async_req;
735d37b54   Baolin Wang   crypto: engine - ...
128
129
130
131
132
133
134
135
136
137
138
139
140
141
  	if (backlog)
  		backlog->complete(backlog, -EINPROGRESS);
  
  	if (engine->busy)
  		was_busy = true;
  	else
  		engine->busy = true;
  
  	spin_unlock_irqrestore(&engine->queue_lock, flags);
  
  	/* Until here we get the request need to be encrypted successfully */
  	if (!was_busy && engine->prepare_crypt_hardware) {
  		ret = engine->prepare_crypt_hardware(engine);
  		if (ret) {
88d58ef89   Corentin LABBE   crypto: engine - ...
142
143
  			dev_err(engine->dev, "failed to prepare crypt hardware
  ");
6a89f492f   Iuliana Prodan   crypto: engine - ...
144
  			goto req_err_2;
735d37b54   Baolin Wang   crypto: engine - ...
145
146
  		}
  	}
218d1cc18   Corentin LABBE   crypto: engine - ...
147
148
149
150
  	enginectx = crypto_tfm_ctx(async_req->tfm);
  
  	if (enginectx->op.prepare_request) {
  		ret = enginectx->op.prepare_request(engine, async_req);
4cba7cf02   Corentin LABBE   crypto: engine - ...
151
  		if (ret) {
218d1cc18   Corentin LABBE   crypto: engine - ...
152
153
154
  			dev_err(engine->dev, "failed to prepare request: %d
  ",
  				ret);
6a89f492f   Iuliana Prodan   crypto: engine - ...
155
  			goto req_err_2;
4cba7cf02   Corentin LABBE   crypto: engine - ...
156
  		}
218d1cc18   Corentin LABBE   crypto: engine - ...
157
158
159
160
161
  	}
  	if (!enginectx->op.do_one_request) {
  		dev_err(engine->dev, "failed to do request
  ");
  		ret = -EINVAL;
6a89f492f   Iuliana Prodan   crypto: engine - ...
162
  		goto req_err_1;
735d37b54   Baolin Wang   crypto: engine - ...
163
  	}
6a89f492f   Iuliana Prodan   crypto: engine - ...
164

218d1cc18   Corentin LABBE   crypto: engine - ...
165
  	ret = enginectx->op.do_one_request(engine, async_req);
6a89f492f   Iuliana Prodan   crypto: engine - ...
166
167
168
169
170
171
  
  	/* Request unsuccessfully executed by hardware */
  	if (ret < 0) {
  		/*
  		 * If hardware queue is full (-ENOSPC), requeue request
  		 * regardless of backlog flag.
6a89f492f   Iuliana Prodan   crypto: engine - ...
172
173
174
  		 * Otherwise, unprepare and complete the request.
  		 */
  		if (!engine->retry_support ||
d1c72f6e4   Iuliana Prodan   crypto: engine - ...
175
  		    (ret != -ENOSPC)) {
6a89f492f   Iuliana Prodan   crypto: engine - ...
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
  			dev_err(engine->dev,
  				"Failed to do one request from queue: %d
  ",
  				ret);
  			goto req_err_1;
  		}
  		/*
  		 * If retry mechanism is supported,
  		 * unprepare current request and
  		 * enqueue it back into crypto-engine queue.
  		 */
  		if (enginectx->op.unprepare_request) {
  			ret = enginectx->op.unprepare_request(engine,
  							      async_req);
  			if (ret)
  				dev_err(engine->dev,
  					"failed to unprepare request
  ");
  		}
  		spin_lock_irqsave(&engine->queue_lock, flags);
  		/*
  		 * If hardware was unable to execute request, enqueue it
  		 * back in front of crypto-engine queue, to keep the order
  		 * of requests.
  		 */
  		crypto_enqueue_request_head(&engine->queue, async_req);
  
  		kthread_queue_work(engine->kworker, &engine->pump_requests);
  		goto out;
218d1cc18   Corentin LABBE   crypto: engine - ...
205
  	}
735d37b54   Baolin Wang   crypto: engine - ...
206

6a89f492f   Iuliana Prodan   crypto: engine - ...
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
  	goto retry;
  
  req_err_1:
  	if (enginectx->op.unprepare_request) {
  		ret = enginectx->op.unprepare_request(engine, async_req);
  		if (ret)
  			dev_err(engine->dev, "failed to unprepare request
  ");
  	}
  
  req_err_2:
  	async_req->complete(async_req, ret);
  
  retry:
  	/* If retry mechanism is supported, send new requests to engine */
  	if (engine->retry_support) {
  		spin_lock_irqsave(&engine->queue_lock, flags);
  		goto start_request;
  	}
735d37b54   Baolin Wang   crypto: engine - ...
226
227
228
229
  	return;
  
  out:
  	spin_unlock_irqrestore(&engine->queue_lock, flags);
8d9082264   Iuliana Prodan   crypto: engine - ...
230
231
232
233
234
235
236
237
238
239
240
241
  
  	/*
  	 * Batch requests is possible only if
  	 * hardware can enqueue multiple requests
  	 */
  	if (engine->do_batch_requests) {
  		ret = engine->do_batch_requests(engine);
  		if (ret)
  			dev_err(engine->dev, "failed to do batch requests: %d
  ",
  				ret);
  	}
6a89f492f   Iuliana Prodan   crypto: engine - ...
242
  	return;
735d37b54   Baolin Wang   crypto: engine - ...
243
244
245
246
247
248
249
250
251
252
253
  }
  
  static void crypto_pump_work(struct kthread_work *work)
  {
  	struct crypto_engine *engine =
  		container_of(work, struct crypto_engine, pump_requests);
  
  	crypto_pump_requests(engine, true);
  }
  
  /**
218d1cc18   Corentin LABBE   crypto: engine - ...
254
   * crypto_transfer_request - transfer the new request into the engine queue
735d37b54   Baolin Wang   crypto: engine - ...
255
256
257
   * @engine: the hardware engine
   * @req: the request need to be listed into the engine queue
   */
218d1cc18   Corentin LABBE   crypto: engine - ...
258
259
  static int crypto_transfer_request(struct crypto_engine *engine,
  				   struct crypto_async_request *req,
4cba7cf02   Corentin LABBE   crypto: engine - ...
260
  				   bool need_pump)
735d37b54   Baolin Wang   crypto: engine - ...
261
262
263
264
265
266
267
268
269
270
  {
  	unsigned long flags;
  	int ret;
  
  	spin_lock_irqsave(&engine->queue_lock, flags);
  
  	if (!engine->running) {
  		spin_unlock_irqrestore(&engine->queue_lock, flags);
  		return -ESHUTDOWN;
  	}
218d1cc18   Corentin LABBE   crypto: engine - ...
271
  	ret = crypto_enqueue_request(&engine->queue, req);
735d37b54   Baolin Wang   crypto: engine - ...
272
273
  
  	if (!engine->busy && need_pump)
c4ca2b0b2   Petr Mladek   crypto: engine - ...
274
  		kthread_queue_work(engine->kworker, &engine->pump_requests);
735d37b54   Baolin Wang   crypto: engine - ...
275
276
277
278
  
  	spin_unlock_irqrestore(&engine->queue_lock, flags);
  	return ret;
  }
4cba7cf02   Corentin LABBE   crypto: engine - ...
279
280
  
  /**
218d1cc18   Corentin LABBE   crypto: engine - ...
281
   * crypto_transfer_request_to_engine - transfer one request to list
4cba7cf02   Corentin LABBE   crypto: engine - ...
282
283
284
285
   * into the engine queue
   * @engine: the hardware engine
   * @req: the request need to be listed into the engine queue
   */
218d1cc18   Corentin LABBE   crypto: engine - ...
286
287
  static int crypto_transfer_request_to_engine(struct crypto_engine *engine,
  					     struct crypto_async_request *req)
4cba7cf02   Corentin LABBE   crypto: engine - ...
288
  {
218d1cc18   Corentin LABBE   crypto: engine - ...
289
  	return crypto_transfer_request(engine, req, true);
4cba7cf02   Corentin LABBE   crypto: engine - ...
290
  }
4cba7cf02   Corentin LABBE   crypto: engine - ...
291
292
  
  /**
218d1cc18   Corentin LABBE   crypto: engine - ...
293
294
295
296
297
298
299
300
301
302
303
   * crypto_transfer_aead_request_to_engine - transfer one aead_request
   * to list into the engine queue
   * @engine: the hardware engine
   * @req: the request need to be listed into the engine queue
   */
  int crypto_transfer_aead_request_to_engine(struct crypto_engine *engine,
  					   struct aead_request *req)
  {
  	return crypto_transfer_request_to_engine(engine, &req->base);
  }
  EXPORT_SYMBOL_GPL(crypto_transfer_aead_request_to_engine);
4cba7cf02   Corentin LABBE   crypto: engine - ...
304

218d1cc18   Corentin LABBE   crypto: engine - ...
305
306
307
308
309
310
311
312
313
314
  /**
   * crypto_transfer_akcipher_request_to_engine - transfer one akcipher_request
   * to list into the engine queue
   * @engine: the hardware engine
   * @req: the request need to be listed into the engine queue
   */
  int crypto_transfer_akcipher_request_to_engine(struct crypto_engine *engine,
  					       struct akcipher_request *req)
  {
  	return crypto_transfer_request_to_engine(engine, &req->base);
4cba7cf02   Corentin LABBE   crypto: engine - ...
315
  }
218d1cc18   Corentin LABBE   crypto: engine - ...
316
  EXPORT_SYMBOL_GPL(crypto_transfer_akcipher_request_to_engine);
735d37b54   Baolin Wang   crypto: engine - ...
317
318
  
  /**
218d1cc18   Corentin LABBE   crypto: engine - ...
319
320
   * crypto_transfer_hash_request_to_engine - transfer one ahash_request
   * to list into the engine queue
735d37b54   Baolin Wang   crypto: engine - ...
321
322
323
   * @engine: the hardware engine
   * @req: the request need to be listed into the engine queue
   */
4cba7cf02   Corentin LABBE   crypto: engine - ...
324
325
  int crypto_transfer_hash_request_to_engine(struct crypto_engine *engine,
  					   struct ahash_request *req)
735d37b54   Baolin Wang   crypto: engine - ...
326
  {
218d1cc18   Corentin LABBE   crypto: engine - ...
327
  	return crypto_transfer_request_to_engine(engine, &req->base);
735d37b54   Baolin Wang   crypto: engine - ...
328
  }
4cba7cf02   Corentin LABBE   crypto: engine - ...
329
  EXPORT_SYMBOL_GPL(crypto_transfer_hash_request_to_engine);
735d37b54   Baolin Wang   crypto: engine - ...
330
331
  
  /**
218d1cc18   Corentin LABBE   crypto: engine - ...
332
333
334
335
336
337
338
339
340
341
342
343
344
   * crypto_transfer_skcipher_request_to_engine - transfer one skcipher_request
   * to list into the engine queue
   * @engine: the hardware engine
   * @req: the request need to be listed into the engine queue
   */
  int crypto_transfer_skcipher_request_to_engine(struct crypto_engine *engine,
  					       struct skcipher_request *req)
  {
  	return crypto_transfer_request_to_engine(engine, &req->base);
  }
  EXPORT_SYMBOL_GPL(crypto_transfer_skcipher_request_to_engine);
  
  /**
218d1cc18   Corentin LABBE   crypto: engine - ...
345
346
347
348
349
350
351
352
353
354
355
356
   * crypto_finalize_aead_request - finalize one aead_request if
   * the request is done
   * @engine: the hardware engine
   * @req: the request need to be finalized
   * @err: error number
   */
  void crypto_finalize_aead_request(struct crypto_engine *engine,
  				  struct aead_request *req, int err)
  {
  	return crypto_finalize_request(engine, &req->base, err);
  }
  EXPORT_SYMBOL_GPL(crypto_finalize_aead_request);
735d37b54   Baolin Wang   crypto: engine - ...
357

218d1cc18   Corentin LABBE   crypto: engine - ...
358
359
360
361
362
363
364
365
366
367
368
  /**
   * crypto_finalize_akcipher_request - finalize one akcipher_request if
   * the request is done
   * @engine: the hardware engine
   * @req: the request need to be finalized
   * @err: error number
   */
  void crypto_finalize_akcipher_request(struct crypto_engine *engine,
  				      struct akcipher_request *req, int err)
  {
  	return crypto_finalize_request(engine, &req->base, err);
4cba7cf02   Corentin LABBE   crypto: engine - ...
369
  }
218d1cc18   Corentin LABBE   crypto: engine - ...
370
  EXPORT_SYMBOL_GPL(crypto_finalize_akcipher_request);
4cba7cf02   Corentin LABBE   crypto: engine - ...
371
372
  
  /**
218d1cc18   Corentin LABBE   crypto: engine - ...
373
374
   * crypto_finalize_hash_request - finalize one ahash_request if
   * the request is done
4cba7cf02   Corentin LABBE   crypto: engine - ...
375
376
377
378
379
380
381
   * @engine: the hardware engine
   * @req: the request need to be finalized
   * @err: error number
   */
  void crypto_finalize_hash_request(struct crypto_engine *engine,
  				  struct ahash_request *req, int err)
  {
218d1cc18   Corentin LABBE   crypto: engine - ...
382
  	return crypto_finalize_request(engine, &req->base, err);
735d37b54   Baolin Wang   crypto: engine - ...
383
  }
4cba7cf02   Corentin LABBE   crypto: engine - ...
384
  EXPORT_SYMBOL_GPL(crypto_finalize_hash_request);
735d37b54   Baolin Wang   crypto: engine - ...
385
386
  
  /**
218d1cc18   Corentin LABBE   crypto: engine - ...
387
388
389
390
391
392
393
394
395
396
397
398
399
400
   * crypto_finalize_skcipher_request - finalize one skcipher_request if
   * the request is done
   * @engine: the hardware engine
   * @req: the request need to be finalized
   * @err: error number
   */
  void crypto_finalize_skcipher_request(struct crypto_engine *engine,
  				      struct skcipher_request *req, int err)
  {
  	return crypto_finalize_request(engine, &req->base, err);
  }
  EXPORT_SYMBOL_GPL(crypto_finalize_skcipher_request);
  
  /**
735d37b54   Baolin Wang   crypto: engine - ...
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
   * crypto_engine_start - start the hardware engine
   * @engine: the hardware engine need to be started
   *
   * Return 0 on success, else on fail.
   */
  int crypto_engine_start(struct crypto_engine *engine)
  {
  	unsigned long flags;
  
  	spin_lock_irqsave(&engine->queue_lock, flags);
  
  	if (engine->running || engine->busy) {
  		spin_unlock_irqrestore(&engine->queue_lock, flags);
  		return -EBUSY;
  	}
  
  	engine->running = true;
  	spin_unlock_irqrestore(&engine->queue_lock, flags);
c4ca2b0b2   Petr Mladek   crypto: engine - ...
419
  	kthread_queue_work(engine->kworker, &engine->pump_requests);
735d37b54   Baolin Wang   crypto: engine - ...
420
421
422
423
424
425
426
427
428
429
430
431
432
433
  
  	return 0;
  }
  EXPORT_SYMBOL_GPL(crypto_engine_start);
  
  /**
   * crypto_engine_stop - stop the hardware engine
   * @engine: the hardware engine need to be stopped
   *
   * Return 0 on success, else on fail.
   */
  int crypto_engine_stop(struct crypto_engine *engine)
  {
  	unsigned long flags;
4cba7cf02   Corentin LABBE   crypto: engine - ...
434
  	unsigned int limit = 500;
735d37b54   Baolin Wang   crypto: engine - ...
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
  	int ret = 0;
  
  	spin_lock_irqsave(&engine->queue_lock, flags);
  
  	/*
  	 * If the engine queue is not empty or the engine is on busy state,
  	 * we need to wait for a while to pump the requests of engine queue.
  	 */
  	while ((crypto_queue_len(&engine->queue) || engine->busy) && limit--) {
  		spin_unlock_irqrestore(&engine->queue_lock, flags);
  		msleep(20);
  		spin_lock_irqsave(&engine->queue_lock, flags);
  	}
  
  	if (crypto_queue_len(&engine->queue) || engine->busy)
  		ret = -EBUSY;
  	else
  		engine->running = false;
  
  	spin_unlock_irqrestore(&engine->queue_lock, flags);
  
  	if (ret)
88d58ef89   Corentin LABBE   crypto: engine - ...
457
458
  		dev_warn(engine->dev, "could not stop engine
  ");
735d37b54   Baolin Wang   crypto: engine - ...
459
460
461
462
463
464
  
  	return ret;
  }
  EXPORT_SYMBOL_GPL(crypto_engine_stop);
  
  /**
6a89f492f   Iuliana Prodan   crypto: engine - ...
465
466
467
   * crypto_engine_alloc_init_and_set - allocate crypto hardware engine structure
   * and initialize it by setting the maximum number of entries in the software
   * crypto-engine queue.
735d37b54   Baolin Wang   crypto: engine - ...
468
   * @dev: the device attached with one hardware engine
6a89f492f   Iuliana Prodan   crypto: engine - ...
469
   * @retry_support: whether hardware has support for retry mechanism
40a3af45d   Randy Dunlap   crypto: engine - ...
470
   * @cbk_do_batch: pointer to a callback function to be invoked when executing
8d9082264   Iuliana Prodan   crypto: engine - ...
471
472
473
474
475
   *                a batch of requests.
   *                This has the form:
   *                callback(struct crypto_engine *engine)
   *                where:
   *                @engine: the crypto engine structure.
735d37b54   Baolin Wang   crypto: engine - ...
476
   * @rt: whether this queue is set to run as a realtime task
6a89f492f   Iuliana Prodan   crypto: engine - ...
477
   * @qlen: maximum size of the crypto-engine queue
735d37b54   Baolin Wang   crypto: engine - ...
478
479
480
481
   *
   * This must be called from context that can sleep.
   * Return: the crypto engine structure on success, else NULL.
   */
6a89f492f   Iuliana Prodan   crypto: engine - ...
482
483
  struct crypto_engine *crypto_engine_alloc_init_and_set(struct device *dev,
  						       bool retry_support,
8d9082264   Iuliana Prodan   crypto: engine - ...
484
  						       int (*cbk_do_batch)(struct crypto_engine *engine),
6a89f492f   Iuliana Prodan   crypto: engine - ...
485
  						       bool rt, int qlen)
735d37b54   Baolin Wang   crypto: engine - ...
486
  {
735d37b54   Baolin Wang   crypto: engine - ...
487
488
489
490
491
492
493
494
  	struct crypto_engine *engine;
  
  	if (!dev)
  		return NULL;
  
  	engine = devm_kzalloc(dev, sizeof(*engine), GFP_KERNEL);
  	if (!engine)
  		return NULL;
88d58ef89   Corentin LABBE   crypto: engine - ...
495
  	engine->dev = dev;
735d37b54   Baolin Wang   crypto: engine - ...
496
497
498
499
  	engine->rt = rt;
  	engine->running = false;
  	engine->busy = false;
  	engine->idling = false;
6a89f492f   Iuliana Prodan   crypto: engine - ...
500
  	engine->retry_support = retry_support;
735d37b54   Baolin Wang   crypto: engine - ...
501
  	engine->priv_data = dev;
8d9082264   Iuliana Prodan   crypto: engine - ...
502
503
504
505
506
  	/*
  	 * Batch requests is possible only if
  	 * hardware has support for retry mechanism.
  	 */
  	engine->do_batch_requests = retry_support ? cbk_do_batch : NULL;
735d37b54   Baolin Wang   crypto: engine - ...
507
508
  	snprintf(engine->name, sizeof(engine->name),
  		 "%s-engine", dev_name(dev));
6a89f492f   Iuliana Prodan   crypto: engine - ...
509
  	crypto_init_queue(&engine->queue, qlen);
735d37b54   Baolin Wang   crypto: engine - ...
510
  	spin_lock_init(&engine->queue_lock);
c4ca2b0b2   Petr Mladek   crypto: engine - ...
511
512
  	engine->kworker = kthread_create_worker(0, "%s", engine->name);
  	if (IS_ERR(engine->kworker)) {
735d37b54   Baolin Wang   crypto: engine - ...
513
514
515
516
  		dev_err(dev, "failed to create crypto request pump task
  ");
  		return NULL;
  	}
3989144f8   Petr Mladek   kthread: kthread ...
517
  	kthread_init_work(&engine->pump_requests, crypto_pump_work);
735d37b54   Baolin Wang   crypto: engine - ...
518
519
520
521
  
  	if (engine->rt) {
  		dev_info(dev, "will run requests pump with realtime priority
  ");
dbc6d0d5a   Peter Zijlstra   sched,crypto: Con...
522
  		sched_set_fifo(engine->kworker->task);
735d37b54   Baolin Wang   crypto: engine - ...
523
524
525
526
  	}
  
  	return engine;
  }
6a89f492f   Iuliana Prodan   crypto: engine - ...
527
528
529
530
531
532
533
534
535
536
537
538
539
  EXPORT_SYMBOL_GPL(crypto_engine_alloc_init_and_set);
  
  /**
   * crypto_engine_alloc_init - allocate crypto hardware engine structure and
   * initialize it.
   * @dev: the device attached with one hardware engine
   * @rt: whether this queue is set to run as a realtime task
   *
   * This must be called from context that can sleep.
   * Return: the crypto engine structure on success, else NULL.
   */
  struct crypto_engine *crypto_engine_alloc_init(struct device *dev, bool rt)
  {
8d9082264   Iuliana Prodan   crypto: engine - ...
540
  	return crypto_engine_alloc_init_and_set(dev, false, NULL, rt,
6a89f492f   Iuliana Prodan   crypto: engine - ...
541
542
  						CRYPTO_ENGINE_MAX_QLEN);
  }
735d37b54   Baolin Wang   crypto: engine - ...
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
  EXPORT_SYMBOL_GPL(crypto_engine_alloc_init);
  
  /**
   * crypto_engine_exit - free the resources of hardware engine when exit
   * @engine: the hardware engine need to be freed
   *
   * Return 0 for success.
   */
  int crypto_engine_exit(struct crypto_engine *engine)
  {
  	int ret;
  
  	ret = crypto_engine_stop(engine);
  	if (ret)
  		return ret;
c4ca2b0b2   Petr Mladek   crypto: engine - ...
558
  	kthread_destroy_worker(engine->kworker);
735d37b54   Baolin Wang   crypto: engine - ...
559
560
561
562
563
564
565
  
  	return 0;
  }
  EXPORT_SYMBOL_GPL(crypto_engine_exit);
  
  MODULE_LICENSE("GPL");
  MODULE_DESCRIPTION("Crypto hardware engine framework");