Blame view

drivers/crypto/picoxcell_crypto.c 50.4 KB
1a59d1b8e   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-or-later
ce9213684   Jamie Iles   crypto: picoxcell...
2
3
  /*
   * Copyright (c) 2010-2011 Picochip Ltd., Jamie Iles
ce9213684   Jamie Iles   crypto: picoxcell...
4
   */
2d78db093   Herbert Xu   crypto: nx - Incl...
5
  #include <crypto/internal/aead.h>
ce9213684   Jamie Iles   crypto: picoxcell...
6
7
8
  #include <crypto/aes.h>
  #include <crypto/algapi.h>
  #include <crypto/authenc.h>
0157fb268   Ard Biesheuvel   crypto: picoxcell...
9
  #include <crypto/internal/des.h>
ce9213684   Jamie Iles   crypto: picoxcell...
10
11
12
13
14
15
16
17
18
19
20
21
22
23
  #include <crypto/md5.h>
  #include <crypto/sha.h>
  #include <crypto/internal/skcipher.h>
  #include <linux/clk.h>
  #include <linux/crypto.h>
  #include <linux/delay.h>
  #include <linux/dma-mapping.h>
  #include <linux/dmapool.h>
  #include <linux/err.h>
  #include <linux/init.h>
  #include <linux/interrupt.h>
  #include <linux/io.h>
  #include <linux/list.h>
  #include <linux/module.h>
30343ef1d   Jamie Iles   crypto: picoxcell...
24
  #include <linux/of.h>
ce9213684   Jamie Iles   crypto: picoxcell...
25
26
27
28
29
  #include <linux/platform_device.h>
  #include <linux/pm.h>
  #include <linux/rtnetlink.h>
  #include <linux/scatterlist.h>
  #include <linux/sched.h>
72071fe43   Herbert Xu   crypto: picoxcell...
30
  #include <linux/sizes.h>
ce9213684   Jamie Iles   crypto: picoxcell...
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
  #include <linux/slab.h>
  #include <linux/timer.h>
  
  #include "picoxcell_crypto_regs.h"
  
  /*
   * The threshold for the number of entries in the CMD FIFO available before
   * the CMD0_CNT interrupt is raised. Increasing this value will reduce the
   * number of interrupts raised to the CPU.
   */
  #define CMD0_IRQ_THRESHOLD   1
  
  /*
   * The timeout period (in jiffies) for a PDU. When the the number of PDUs in
   * flight is greater than the STAT_IRQ_THRESHOLD or 0 the timer is disabled.
   * When there are packets in flight but lower than the threshold, we enable
   * the timer and at expiry, attempt to remove any processed packets from the
   * queue and if there are still packets left, schedule the timer again.
   */
  #define PACKET_TIMEOUT	    1
  
  /* The priority to register each algorithm with. */
  #define SPACC_CRYPTO_ALG_PRIORITY	10000
  
  #define SPACC_CRYPTO_KASUMI_F8_KEY_LEN	16
  #define SPACC_CRYPTO_IPSEC_CIPHER_PG_SZ 64
  #define SPACC_CRYPTO_IPSEC_HASH_PG_SZ	64
  #define SPACC_CRYPTO_IPSEC_MAX_CTXS	32
  #define SPACC_CRYPTO_IPSEC_FIFO_SZ	32
  #define SPACC_CRYPTO_L2_CIPHER_PG_SZ	64
  #define SPACC_CRYPTO_L2_HASH_PG_SZ	64
  #define SPACC_CRYPTO_L2_MAX_CTXS	128
  #define SPACC_CRYPTO_L2_FIFO_SZ		128
  
  #define MAX_DDT_LEN			16
  
  /* DDT format. This must match the hardware DDT format exactly. */
  struct spacc_ddt {
  	dma_addr_t	p;
  	u32		len;
  };
  
  /*
   * Asynchronous crypto request structure.
   *
   * This structure defines a request that is either queued for processing or
   * being processed.
   */
  struct spacc_req {
  	struct list_head		list;
  	struct spacc_engine		*engine;
  	struct crypto_async_request	*req;
  	int				result;
  	bool				is_encrypt;
  	unsigned			ctx_id;
  	dma_addr_t			src_addr, dst_addr;
  	struct spacc_ddt		*src_ddt, *dst_ddt;
  	void				(*complete)(struct spacc_req *req);
dc6e71c9d   Ard Biesheuvel   crypto: picoxcell...
89
  	struct skcipher_request		fallback_req;	// keep at the end
c1359495c   Herbert Xu   crypto: picoxcell...
90
  };
ce9213684   Jamie Iles   crypto: picoxcell...
91

c1359495c   Herbert Xu   crypto: picoxcell...
92
93
94
95
96
97
98
99
  struct spacc_aead {
  	unsigned long			ctrl_default;
  	unsigned long			type;
  	struct aead_alg			alg;
  	struct spacc_engine		*engine;
  	struct list_head		entry;
  	int				key_offs;
  	int				iv_offs;
ce9213684   Jamie Iles   crypto: picoxcell...
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
  };
  
  struct spacc_engine {
  	void __iomem			*regs;
  	struct list_head		pending;
  	int				next_ctx;
  	spinlock_t			hw_lock;
  	int				in_flight;
  	struct list_head		completed;
  	struct list_head		in_progress;
  	struct tasklet_struct		complete;
  	unsigned long			fifo_sz;
  	void __iomem			*cipher_ctx_base;
  	void __iomem			*hash_key_base;
  	struct spacc_alg		*algs;
  	unsigned			num_algs;
  	struct list_head		registered_algs;
c1359495c   Herbert Xu   crypto: picoxcell...
117
118
119
  	struct spacc_aead		*aeads;
  	unsigned			num_aeads;
  	struct list_head		registered_aeads;
ce9213684   Jamie Iles   crypto: picoxcell...
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
  	size_t				cipher_pg_sz;
  	size_t				hash_pg_sz;
  	const char			*name;
  	struct clk			*clk;
  	struct device			*dev;
  	unsigned			max_ctxs;
  	struct timer_list		packet_timeout;
  	unsigned			stat_irq_thresh;
  	struct dma_pool			*req_pool;
  };
  
  /* Algorithm type mask. */
  #define SPACC_CRYPTO_ALG_MASK		0x7
  
  /* SPACC definition of a crypto algorithm. */
  struct spacc_alg {
  	unsigned long			ctrl_default;
  	unsigned long			type;
b3cde6bab   Ard Biesheuvel   crypto: picoxcell...
138
  	struct skcipher_alg		alg;
ce9213684   Jamie Iles   crypto: picoxcell...
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
  	struct spacc_engine		*engine;
  	struct list_head		entry;
  	int				key_offs;
  	int				iv_offs;
  };
  
  /* Generic context structure for any algorithm type. */
  struct spacc_generic_ctx {
  	struct spacc_engine		*engine;
  	int				flags;
  	int				key_offs;
  	int				iv_offs;
  };
  
  /* Block cipher context. */
  struct spacc_ablk_ctx {
  	struct spacc_generic_ctx	generic;
  	u8				key[AES_MAX_KEY_SIZE];
  	u8				key_len;
  	/*
  	 * The fallback cipher. If the operation can't be done in hardware,
  	 * fallback to a software version.
  	 */
dc6e71c9d   Ard Biesheuvel   crypto: picoxcell...
162
  	struct crypto_skcipher		*sw_cipher;
ce9213684   Jamie Iles   crypto: picoxcell...
163
164
165
166
167
168
169
170
171
172
  };
  
  /* AEAD cipher context. */
  struct spacc_aead_ctx {
  	struct spacc_generic_ctx	generic;
  	u8				cipher_key[AES_MAX_KEY_SIZE];
  	u8				hash_ctx[SPACC_CRYPTO_IPSEC_HASH_PG_SZ];
  	u8				cipher_key_len;
  	u8				hash_key_len;
  	struct crypto_aead		*sw_cipher;
ce9213684   Jamie Iles   crypto: picoxcell...
173
  };
40bfc14f3   Jamie Iles   crypto: picoxcell...
174
  static int spacc_ablk_submit(struct spacc_req *req);
b3cde6bab   Ard Biesheuvel   crypto: picoxcell...
175
  static inline struct spacc_alg *to_spacc_skcipher(struct skcipher_alg *alg)
ce9213684   Jamie Iles   crypto: picoxcell...
176
177
178
  {
  	return alg ? container_of(alg, struct spacc_alg, alg) : NULL;
  }
c1359495c   Herbert Xu   crypto: picoxcell...
179
180
181
182
  static inline struct spacc_aead *to_spacc_aead(struct aead_alg *alg)
  {
  	return container_of(alg, struct spacc_aead, alg);
  }
ce9213684   Jamie Iles   crypto: picoxcell...
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
  static inline int spacc_fifo_cmd_full(struct spacc_engine *engine)
  {
  	u32 fifo_stat = readl(engine->regs + SPA_FIFO_STAT_REG_OFFSET);
  
  	return fifo_stat & SPA_FIFO_CMD_FULL;
  }
  
  /*
   * Given a cipher context, and a context number, get the base address of the
   * context page.
   *
   * Returns the address of the context page where the key/context may
   * be written.
   */
  static inline void __iomem *spacc_ctx_page_addr(struct spacc_generic_ctx *ctx,
  						unsigned indx,
  						bool is_cipher_ctx)
  {
  	return is_cipher_ctx ? ctx->engine->cipher_ctx_base +
  			(indx * ctx->engine->cipher_pg_sz) :
  		ctx->engine->hash_key_base + (indx * ctx->engine->hash_pg_sz);
  }
  
  /* The context pages can only be written with 32-bit accesses. */
  static inline void memcpy_toio32(u32 __iomem *dst, const void *src,
  				 unsigned count)
  {
  	const u32 *src32 = (const u32 *) src;
  
  	while (count--)
  		writel(*src32++, dst++);
  }
  
  static void spacc_cipher_write_ctx(struct spacc_generic_ctx *ctx,
  				   void __iomem *page_addr, const u8 *key,
  				   size_t key_len, const u8 *iv, size_t iv_len)
  {
  	void __iomem *key_ptr = page_addr + ctx->key_offs;
  	void __iomem *iv_ptr = page_addr + ctx->iv_offs;
  
  	memcpy_toio32(key_ptr, key, key_len / 4);
  	memcpy_toio32(iv_ptr, iv, iv_len / 4);
  }
  
  /*
   * Load a context into the engines context memory.
   *
   * Returns the index of the context page where the context was loaded.
   */
  static unsigned spacc_load_ctx(struct spacc_generic_ctx *ctx,
  			       const u8 *ciph_key, size_t ciph_len,
  			       const u8 *iv, size_t ivlen, const u8 *hash_key,
  			       size_t hash_len)
  {
  	unsigned indx = ctx->engine->next_ctx++;
  	void __iomem *ciph_page_addr, *hash_page_addr;
  
  	ciph_page_addr = spacc_ctx_page_addr(ctx, indx, 1);
  	hash_page_addr = spacc_ctx_page_addr(ctx, indx, 0);
  
  	ctx->engine->next_ctx &= ctx->engine->fifo_sz - 1;
  	spacc_cipher_write_ctx(ctx, ciph_page_addr, ciph_key, ciph_len, iv,
  			       ivlen);
  	writel(ciph_len | (indx << SPA_KEY_SZ_CTX_INDEX_OFFSET) |
  	       (1 << SPA_KEY_SZ_CIPHER_OFFSET),
  	       ctx->engine->regs + SPA_KEY_SZ_REG_OFFSET);
  
  	if (hash_key) {
  		memcpy_toio32(hash_page_addr, hash_key, hash_len / 4);
  		writel(hash_len | (indx << SPA_KEY_SZ_CTX_INDEX_OFFSET),
  		       ctx->engine->regs + SPA_KEY_SZ_REG_OFFSET);
  	}
  
  	return indx;
  }
ce9213684   Jamie Iles   crypto: picoxcell...
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
  static inline void ddt_set(struct spacc_ddt *ddt, dma_addr_t phys, size_t len)
  {
  	ddt->p = phys;
  	ddt->len = len;
  }
  
  /*
   * Take a crypto request and scatterlists for the data and turn them into DDTs
   * for passing to the crypto engines. This also DMA maps the data so that the
   * crypto engines can DMA to/from them.
   */
  static struct spacc_ddt *spacc_sg_to_ddt(struct spacc_engine *engine,
  					 struct scatterlist *payload,
  					 unsigned nbytes,
  					 enum dma_data_direction dir,
  					 dma_addr_t *ddt_phys)
  {
f53e38afd   LABBE Corentin   crypto: picoxcell...
275
  	unsigned mapped_ents;
ce9213684   Jamie Iles   crypto: picoxcell...
276
277
278
  	struct scatterlist *cur;
  	struct spacc_ddt *ddt;
  	int i;
f53e38afd   LABBE Corentin   crypto: picoxcell...
279
  	int nents;
ce9213684   Jamie Iles   crypto: picoxcell...
280

f051f95eb   LABBE Corentin   crypto: picoxcell...
281
282
283
284
285
286
  	nents = sg_nents_for_len(payload, nbytes);
  	if (nents < 0) {
  		dev_err(engine->dev, "Invalid numbers of SG.
  ");
  		return NULL;
  	}
ce9213684   Jamie Iles   crypto: picoxcell...
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
  	mapped_ents = dma_map_sg(engine->dev, payload, nents, dir);
  
  	if (mapped_ents + 1 > MAX_DDT_LEN)
  		goto out;
  
  	ddt = dma_pool_alloc(engine->req_pool, GFP_ATOMIC, ddt_phys);
  	if (!ddt)
  		goto out;
  
  	for_each_sg(payload, cur, mapped_ents, i)
  		ddt_set(&ddt[i], sg_dma_address(cur), sg_dma_len(cur));
  	ddt_set(&ddt[mapped_ents], 0, 0);
  
  	return ddt;
  
  out:
  	dma_unmap_sg(engine->dev, payload, nents, dir);
  	return NULL;
  }
c1359495c   Herbert Xu   crypto: picoxcell...
306
  static int spacc_aead_make_ddts(struct aead_request *areq)
ce9213684   Jamie Iles   crypto: picoxcell...
307
  {
c1359495c   Herbert Xu   crypto: picoxcell...
308
309
  	struct crypto_aead *aead = crypto_aead_reqtfm(areq);
  	struct spacc_req *req = aead_request_ctx(areq);
ce9213684   Jamie Iles   crypto: picoxcell...
310
311
  	struct spacc_engine *engine = req->engine;
  	struct spacc_ddt *src_ddt, *dst_ddt;
81781e681   Herbert Xu   crypto: picoxcell...
312
  	unsigned total;
f53e38afd   LABBE Corentin   crypto: picoxcell...
313
  	int src_nents, dst_nents;
ce9213684   Jamie Iles   crypto: picoxcell...
314
  	struct scatterlist *cur;
c1359495c   Herbert Xu   crypto: picoxcell...
315
316
317
318
319
  	int i, dst_ents, src_ents;
  
  	total = areq->assoclen + areq->cryptlen;
  	if (req->is_encrypt)
  		total += crypto_aead_authsize(aead);
f051f95eb   LABBE Corentin   crypto: picoxcell...
320
321
322
323
324
325
  	src_nents = sg_nents_for_len(areq->src, total);
  	if (src_nents < 0) {
  		dev_err(engine->dev, "Invalid numbers of src SG.
  ");
  		return src_nents;
  	}
c1359495c   Herbert Xu   crypto: picoxcell...
326
327
328
329
330
  	if (src_nents + 1 > MAX_DDT_LEN)
  		return -E2BIG;
  
  	dst_nents = 0;
  	if (areq->src != areq->dst) {
f051f95eb   LABBE Corentin   crypto: picoxcell...
331
332
333
334
335
336
  		dst_nents = sg_nents_for_len(areq->dst, total);
  		if (dst_nents < 0) {
  			dev_err(engine->dev, "Invalid numbers of dst SG.
  ");
  			return dst_nents;
  		}
c1359495c   Herbert Xu   crypto: picoxcell...
337
338
339
  		if (src_nents + 1 > MAX_DDT_LEN)
  			return -E2BIG;
  	}
ce9213684   Jamie Iles   crypto: picoxcell...
340
341
342
  
  	src_ddt = dma_pool_alloc(engine->req_pool, GFP_ATOMIC, &req->src_addr);
  	if (!src_ddt)
c1359495c   Herbert Xu   crypto: picoxcell...
343
  		goto err;
ce9213684   Jamie Iles   crypto: picoxcell...
344
345
  
  	dst_ddt = dma_pool_alloc(engine->req_pool, GFP_ATOMIC, &req->dst_addr);
c1359495c   Herbert Xu   crypto: picoxcell...
346
347
  	if (!dst_ddt)
  		goto err_free_src;
ce9213684   Jamie Iles   crypto: picoxcell...
348
349
350
  
  	req->src_ddt = src_ddt;
  	req->dst_ddt = dst_ddt;
c1359495c   Herbert Xu   crypto: picoxcell...
351
352
  	if (dst_nents) {
  		src_ents = dma_map_sg(engine->dev, areq->src, src_nents,
ce9213684   Jamie Iles   crypto: picoxcell...
353
  				      DMA_TO_DEVICE);
c1359495c   Herbert Xu   crypto: picoxcell...
354
355
356
357
  		if (!src_ents)
  			goto err_free_dst;
  
  		dst_ents = dma_map_sg(engine->dev, areq->dst, dst_nents,
ce9213684   Jamie Iles   crypto: picoxcell...
358
  				      DMA_FROM_DEVICE);
c1359495c   Herbert Xu   crypto: picoxcell...
359
360
361
362
363
364
  
  		if (!dst_ents) {
  			dma_unmap_sg(engine->dev, areq->src, src_nents,
  				     DMA_TO_DEVICE);
  			goto err_free_dst;
  		}
ce9213684   Jamie Iles   crypto: picoxcell...
365
  	} else {
c1359495c   Herbert Xu   crypto: picoxcell...
366
  		src_ents = dma_map_sg(engine->dev, areq->src, src_nents,
ce9213684   Jamie Iles   crypto: picoxcell...
367
  				      DMA_BIDIRECTIONAL);
c1359495c   Herbert Xu   crypto: picoxcell...
368
369
370
  		if (!src_ents)
  			goto err_free_dst;
  		dst_ents = src_ents;
ce9213684   Jamie Iles   crypto: picoxcell...
371
372
373
  	}
  
  	/*
c1359495c   Herbert Xu   crypto: picoxcell...
374
375
  	 * Now map in the payload for the source and destination and terminate
  	 * with the NULL pointers.
ce9213684   Jamie Iles   crypto: picoxcell...
376
  	 */
c1359495c   Herbert Xu   crypto: picoxcell...
377
378
  	for_each_sg(areq->src, cur, src_ents, i)
  		ddt_set(src_ddt++, sg_dma_address(cur), sg_dma_len(cur));
ce9213684   Jamie Iles   crypto: picoxcell...
379

c1359495c   Herbert Xu   crypto: picoxcell...
380
381
382
  	/* For decryption we need to skip the associated data. */
  	total = req->is_encrypt ? 0 : areq->assoclen;
  	for_each_sg(areq->dst, cur, dst_ents, i) {
81781e681   Herbert Xu   crypto: picoxcell...
383
  		unsigned len = sg_dma_len(cur);
c1359495c   Herbert Xu   crypto: picoxcell...
384
385
386
387
  		if (len <= total) {
  			total -= len;
  			continue;
  		}
81781e681   Herbert Xu   crypto: picoxcell...
388

c1359495c   Herbert Xu   crypto: picoxcell...
389
  		ddt_set(dst_ddt++, sg_dma_address(cur) + total, len - total);
ce9213684   Jamie Iles   crypto: picoxcell...
390
  	}
ce9213684   Jamie Iles   crypto: picoxcell...
391
392
393
394
395
  
  	ddt_set(src_ddt, 0, 0);
  	ddt_set(dst_ddt, 0, 0);
  
  	return 0;
c1359495c   Herbert Xu   crypto: picoxcell...
396
397
398
399
400
401
402
  
  err_free_dst:
  	dma_pool_free(engine->req_pool, dst_ddt, req->dst_addr);
  err_free_src:
  	dma_pool_free(engine->req_pool, src_ddt, req->src_addr);
  err:
  	return -ENOMEM;
ce9213684   Jamie Iles   crypto: picoxcell...
403
404
405
406
407
408
  }
  
  static void spacc_aead_free_ddts(struct spacc_req *req)
  {
  	struct aead_request *areq = container_of(req->req, struct aead_request,
  						 base);
c1359495c   Herbert Xu   crypto: picoxcell...
409
410
411
412
  	struct crypto_aead *aead = crypto_aead_reqtfm(areq);
  	unsigned total = areq->assoclen + areq->cryptlen +
  			 (req->is_encrypt ? crypto_aead_authsize(aead) : 0);
  	struct spacc_aead_ctx *aead_ctx = crypto_aead_ctx(aead);
ce9213684   Jamie Iles   crypto: picoxcell...
413
  	struct spacc_engine *engine = aead_ctx->generic.engine;
f051f95eb   LABBE Corentin   crypto: picoxcell...
414
415
416
417
418
419
420
421
  	int nents = sg_nents_for_len(areq->src, total);
  
  	/* sg_nents_for_len should not fail since it works when mapping sg */
  	if (unlikely(nents < 0)) {
  		dev_err(engine->dev, "Invalid numbers of src SG.
  ");
  		return;
  	}
ce9213684   Jamie Iles   crypto: picoxcell...
422
423
424
  
  	if (areq->src != areq->dst) {
  		dma_unmap_sg(engine->dev, areq->src, nents, DMA_TO_DEVICE);
f051f95eb   LABBE Corentin   crypto: picoxcell...
425
426
427
428
429
430
431
  		nents = sg_nents_for_len(areq->dst, total);
  		if (unlikely(nents < 0)) {
  			dev_err(engine->dev, "Invalid numbers of dst SG.
  ");
  			return;
  		}
  		dma_unmap_sg(engine->dev, areq->dst, nents, DMA_FROM_DEVICE);
ce9213684   Jamie Iles   crypto: picoxcell...
432
433
  	} else
  		dma_unmap_sg(engine->dev, areq->src, nents, DMA_BIDIRECTIONAL);
ce9213684   Jamie Iles   crypto: picoxcell...
434
435
436
437
438
439
440
441
  	dma_pool_free(engine->req_pool, req->src_ddt, req->src_addr);
  	dma_pool_free(engine->req_pool, req->dst_ddt, req->dst_addr);
  }
  
  static void spacc_free_ddt(struct spacc_req *req, struct spacc_ddt *ddt,
  			   dma_addr_t ddt_addr, struct scatterlist *payload,
  			   unsigned nbytes, enum dma_data_direction dir)
  {
f051f95eb   LABBE Corentin   crypto: picoxcell...
442
443
444
445
446
447
448
  	int nents = sg_nents_for_len(payload, nbytes);
  
  	if (nents < 0) {
  		dev_err(req->engine->dev, "Invalid numbers of SG.
  ");
  		return;
  	}
ce9213684   Jamie Iles   crypto: picoxcell...
449
450
451
452
  
  	dma_unmap_sg(req->engine->dev, payload, nents, dir);
  	dma_pool_free(req->engine->req_pool, ddt, ddt_addr);
  }
ce9213684   Jamie Iles   crypto: picoxcell...
453
454
455
456
  static int spacc_aead_setkey(struct crypto_aead *tfm, const u8 *key,
  			     unsigned int keylen)
  {
  	struct spacc_aead_ctx *ctx = crypto_aead_ctx(tfm);
ab827fb39   Mathias Krause   crypto: picoxcell...
457
  	struct crypto_authenc_keys keys;
c1359495c   Herbert Xu   crypto: picoxcell...
458
459
460
461
462
463
  	int err;
  
  	crypto_aead_clear_flags(ctx->sw_cipher, CRYPTO_TFM_REQ_MASK);
  	crypto_aead_set_flags(ctx->sw_cipher, crypto_aead_get_flags(tfm) &
  					      CRYPTO_TFM_REQ_MASK);
  	err = crypto_aead_setkey(ctx->sw_cipher, key, keylen);
c1359495c   Herbert Xu   crypto: picoxcell...
464
465
  	if (err)
  		return err;
ce9213684   Jamie Iles   crypto: picoxcell...
466

ab827fb39   Mathias Krause   crypto: picoxcell...
467
  	if (crypto_authenc_extractkeys(&keys, key, keylen) != 0)
ce9213684   Jamie Iles   crypto: picoxcell...
468
  		goto badkey;
ab827fb39   Mathias Krause   crypto: picoxcell...
469
  	if (keys.enckeylen > AES_MAX_KEY_SIZE)
ce9213684   Jamie Iles   crypto: picoxcell...
470
  		goto badkey;
ab827fb39   Mathias Krause   crypto: picoxcell...
471
  	if (keys.authkeylen > sizeof(ctx->hash_ctx))
ce9213684   Jamie Iles   crypto: picoxcell...
472
  		goto badkey;
c1359495c   Herbert Xu   crypto: picoxcell...
473
474
  	memcpy(ctx->cipher_key, keys.enckey, keys.enckeylen);
  	ctx->cipher_key_len = keys.enckeylen;
ce9213684   Jamie Iles   crypto: picoxcell...
475

ab827fb39   Mathias Krause   crypto: picoxcell...
476
477
  	memcpy(ctx->hash_ctx, keys.authkey, keys.authkeylen);
  	ctx->hash_key_len = keys.authkeylen;
ce9213684   Jamie Iles   crypto: picoxcell...
478

a664b4b14   Tudor-Dan Ambarus   crypto: picoxcell...
479
  	memzero_explicit(&keys, sizeof(keys));
ce9213684   Jamie Iles   crypto: picoxcell...
480
481
482
  	return 0;
  
  badkey:
a664b4b14   Tudor-Dan Ambarus   crypto: picoxcell...
483
  	memzero_explicit(&keys, sizeof(keys));
ce9213684   Jamie Iles   crypto: picoxcell...
484
485
486
487
488
489
490
  	return -EINVAL;
  }
  
  static int spacc_aead_setauthsize(struct crypto_aead *tfm,
  				  unsigned int authsize)
  {
  	struct spacc_aead_ctx *ctx = crypto_tfm_ctx(crypto_aead_tfm(tfm));
c1359495c   Herbert Xu   crypto: picoxcell...
491
  	return crypto_aead_setauthsize(ctx->sw_cipher, authsize);
ce9213684   Jamie Iles   crypto: picoxcell...
492
493
494
495
496
497
498
  }
  
  /*
   * Check if an AEAD request requires a fallback operation. Some requests can't
   * be completed in hardware because the hardware may not support certain key
   * sizes. In these cases we need to complete the request in software.
   */
c1359495c   Herbert Xu   crypto: picoxcell...
499
  static int spacc_aead_need_fallback(struct aead_request *aead_req)
ce9213684   Jamie Iles   crypto: picoxcell...
500
  {
c1359495c   Herbert Xu   crypto: picoxcell...
501
502
503
504
  	struct crypto_aead *aead = crypto_aead_reqtfm(aead_req);
  	struct aead_alg *alg = crypto_aead_alg(aead);
  	struct spacc_aead *spacc_alg = to_spacc_aead(alg);
  	struct spacc_aead_ctx *ctx = crypto_aead_ctx(aead);
ce9213684   Jamie Iles   crypto: picoxcell...
505

ce9213684   Jamie Iles   crypto: picoxcell...
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
  	/*
  	 * If we have a non-supported key-length, then we need to do a
  	 * software fallback.
  	 */
  	if ((spacc_alg->ctrl_default & SPACC_CRYPTO_ALG_MASK) ==
  	    SPA_CTRL_CIPH_ALG_AES &&
  	    ctx->cipher_key_len != AES_KEYSIZE_128 &&
  	    ctx->cipher_key_len != AES_KEYSIZE_256)
  		return 1;
  
  	return 0;
  }
  
  static int spacc_aead_do_fallback(struct aead_request *req, unsigned alg_type,
  				  bool is_encrypt)
  {
  	struct crypto_tfm *old_tfm = crypto_aead_tfm(crypto_aead_reqtfm(req));
  	struct spacc_aead_ctx *ctx = crypto_tfm_ctx(old_tfm);
c1359495c   Herbert Xu   crypto: picoxcell...
524
  	struct aead_request *subreq = aead_request_ctx(req);
ce9213684   Jamie Iles   crypto: picoxcell...
525

c1359495c   Herbert Xu   crypto: picoxcell...
526
527
528
529
530
531
  	aead_request_set_tfm(subreq, ctx->sw_cipher);
  	aead_request_set_callback(subreq, req->base.flags,
  				  req->base.complete, req->base.data);
  	aead_request_set_crypt(subreq, req->src, req->dst, req->cryptlen,
  			       req->iv);
  	aead_request_set_ad(subreq, req->assoclen);
ce9213684   Jamie Iles   crypto: picoxcell...
532

c1359495c   Herbert Xu   crypto: picoxcell...
533
534
  	return is_encrypt ? crypto_aead_encrypt(subreq) :
  			    crypto_aead_decrypt(subreq);
ce9213684   Jamie Iles   crypto: picoxcell...
535
536
537
538
539
540
541
542
543
544
  }
  
  static void spacc_aead_complete(struct spacc_req *req)
  {
  	spacc_aead_free_ddts(req);
  	req->req->complete(req->req, req->result);
  }
  
  static int spacc_aead_submit(struct spacc_req *req)
  {
ce9213684   Jamie Iles   crypto: picoxcell...
545
546
  	struct aead_request *aead_req =
  		container_of(req->req, struct aead_request, base);
c1359495c   Herbert Xu   crypto: picoxcell...
547
548
549
550
551
552
553
  	struct crypto_aead *aead = crypto_aead_reqtfm(aead_req);
  	unsigned int authsize = crypto_aead_authsize(aead);
  	struct spacc_aead_ctx *ctx = crypto_aead_ctx(aead);
  	struct aead_alg *alg = crypto_aead_alg(aead);
  	struct spacc_aead *spacc_alg = to_spacc_aead(alg);
  	struct spacc_engine *engine = ctx->generic.engine;
  	u32 ctrl, proc_len, assoc_len;
ce9213684   Jamie Iles   crypto: picoxcell...
554
555
556
  
  	req->result = -EINPROGRESS;
  	req->ctx_id = spacc_load_ctx(&ctx->generic, ctx->cipher_key,
c1359495c   Herbert Xu   crypto: picoxcell...
557
  		ctx->cipher_key_len, aead_req->iv, crypto_aead_ivsize(aead),
ce9213684   Jamie Iles   crypto: picoxcell...
558
559
560
561
562
563
564
565
566
567
568
  		ctx->hash_ctx, ctx->hash_key_len);
  
  	/* Set the source and destination DDT pointers. */
  	writel(req->src_addr, engine->regs + SPA_SRC_PTR_REG_OFFSET);
  	writel(req->dst_addr, engine->regs + SPA_DST_PTR_REG_OFFSET);
  	writel(0, engine->regs + SPA_OFFSET_REG_OFFSET);
  
  	assoc_len = aead_req->assoclen;
  	proc_len = aead_req->cryptlen + assoc_len;
  
  	/*
ce9213684   Jamie Iles   crypto: picoxcell...
569
570
571
572
  	 * If we are decrypting, we need to take the length of the ICV out of
  	 * the processing length.
  	 */
  	if (!req->is_encrypt)
c1359495c   Herbert Xu   crypto: picoxcell...
573
  		proc_len -= authsize;
ce9213684   Jamie Iles   crypto: picoxcell...
574
575
576
  
  	writel(proc_len, engine->regs + SPA_PROC_LEN_REG_OFFSET);
  	writel(assoc_len, engine->regs + SPA_AAD_LEN_REG_OFFSET);
c1359495c   Herbert Xu   crypto: picoxcell...
577
  	writel(authsize, engine->regs + SPA_ICV_LEN_REG_OFFSET);
ce9213684   Jamie Iles   crypto: picoxcell...
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
  	writel(0, engine->regs + SPA_ICV_OFFSET_REG_OFFSET);
  	writel(0, engine->regs + SPA_AUX_INFO_REG_OFFSET);
  
  	ctrl = spacc_alg->ctrl_default | (req->ctx_id << SPA_CTRL_CTX_IDX) |
  		(1 << SPA_CTRL_ICV_APPEND);
  	if (req->is_encrypt)
  		ctrl |= (1 << SPA_CTRL_ENCRYPT_IDX) | (1 << SPA_CTRL_AAD_COPY);
  	else
  		ctrl |= (1 << SPA_CTRL_KEY_EXP);
  
  	mod_timer(&engine->packet_timeout, jiffies + PACKET_TIMEOUT);
  
  	writel(ctrl, engine->regs + SPA_CTRL_REG_OFFSET);
  
  	return -EINPROGRESS;
  }
40bfc14f3   Jamie Iles   crypto: picoxcell...
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
  static int spacc_req_submit(struct spacc_req *req);
  
  static void spacc_push(struct spacc_engine *engine)
  {
  	struct spacc_req *req;
  
  	while (!list_empty(&engine->pending) &&
  	       engine->in_flight + 1 <= engine->fifo_sz) {
  
  		++engine->in_flight;
  		req = list_first_entry(&engine->pending, struct spacc_req,
  				       list);
  		list_move_tail(&req->list, &engine->in_progress);
  
  		req->result = spacc_req_submit(req);
  	}
  }
ce9213684   Jamie Iles   crypto: picoxcell...
611
612
613
  /*
   * Setup an AEAD request for processing. This will configure the engine, load
   * the context and then start the packet processing.
ce9213684   Jamie Iles   crypto: picoxcell...
614
   */
c1359495c   Herbert Xu   crypto: picoxcell...
615
  static int spacc_aead_setup(struct aead_request *req,
ce9213684   Jamie Iles   crypto: picoxcell...
616
617
  			    unsigned alg_type, bool is_encrypt)
  {
c1359495c   Herbert Xu   crypto: picoxcell...
618
619
620
  	struct crypto_aead *aead = crypto_aead_reqtfm(req);
  	struct aead_alg *alg = crypto_aead_alg(aead);
  	struct spacc_engine *engine = to_spacc_aead(alg)->engine;
ce9213684   Jamie Iles   crypto: picoxcell...
621
  	struct spacc_req *dev_req = aead_request_ctx(req);
c1359495c   Herbert Xu   crypto: picoxcell...
622
  	int err;
ce9213684   Jamie Iles   crypto: picoxcell...
623
  	unsigned long flags;
ce9213684   Jamie Iles   crypto: picoxcell...
624

ce9213684   Jamie Iles   crypto: picoxcell...
625
626
627
628
629
  	dev_req->req		= &req->base;
  	dev_req->is_encrypt	= is_encrypt;
  	dev_req->result		= -EBUSY;
  	dev_req->engine		= engine;
  	dev_req->complete	= spacc_aead_complete;
c1359495c   Herbert Xu   crypto: picoxcell...
630
631
  	if (unlikely(spacc_aead_need_fallback(req) ||
  		     ((err = spacc_aead_make_ddts(req)) == -E2BIG)))
ce9213684   Jamie Iles   crypto: picoxcell...
632
  		return spacc_aead_do_fallback(req, alg_type, is_encrypt);
c1359495c   Herbert Xu   crypto: picoxcell...
633
634
  	if (err)
  		goto out;
ce9213684   Jamie Iles   crypto: picoxcell...
635
636
637
  
  	err = -EINPROGRESS;
  	spin_lock_irqsave(&engine->hw_lock, flags);
40bfc14f3   Jamie Iles   crypto: picoxcell...
638
639
  	if (unlikely(spacc_fifo_cmd_full(engine)) ||
  	    engine->in_flight + 1 > engine->fifo_sz) {
ce9213684   Jamie Iles   crypto: picoxcell...
640
641
642
643
644
645
646
  		if (!(req->base.flags & CRYPTO_TFM_REQ_MAY_BACKLOG)) {
  			err = -EBUSY;
  			spin_unlock_irqrestore(&engine->hw_lock, flags);
  			goto out_free_ddts;
  		}
  		list_add_tail(&dev_req->list, &engine->pending);
  	} else {
40bfc14f3   Jamie Iles   crypto: picoxcell...
647
648
  		list_add_tail(&dev_req->list, &engine->pending);
  		spacc_push(engine);
ce9213684   Jamie Iles   crypto: picoxcell...
649
650
651
652
653
654
655
656
657
658
659
660
661
662
  	}
  	spin_unlock_irqrestore(&engine->hw_lock, flags);
  
  	goto out;
  
  out_free_ddts:
  	spacc_aead_free_ddts(dev_req);
  out:
  	return err;
  }
  
  static int spacc_aead_encrypt(struct aead_request *req)
  {
  	struct crypto_aead *aead = crypto_aead_reqtfm(req);
c1359495c   Herbert Xu   crypto: picoxcell...
663
  	struct spacc_aead *alg = to_spacc_aead(crypto_aead_alg(aead));
ce9213684   Jamie Iles   crypto: picoxcell...
664

c1359495c   Herbert Xu   crypto: picoxcell...
665
  	return spacc_aead_setup(req, alg->type, 1);
ce9213684   Jamie Iles   crypto: picoxcell...
666
667
668
669
670
  }
  
  static int spacc_aead_decrypt(struct aead_request *req)
  {
  	struct crypto_aead *aead = crypto_aead_reqtfm(req);
c1359495c   Herbert Xu   crypto: picoxcell...
671
  	struct spacc_aead  *alg = to_spacc_aead(crypto_aead_alg(aead));
ce9213684   Jamie Iles   crypto: picoxcell...
672

c1359495c   Herbert Xu   crypto: picoxcell...
673
  	return spacc_aead_setup(req, alg->type, 0);
ce9213684   Jamie Iles   crypto: picoxcell...
674
675
676
677
678
679
  }
  
  /*
   * Initialise a new AEAD context. This is responsible for allocating the
   * fallback cipher and initialising the context.
   */
c1359495c   Herbert Xu   crypto: picoxcell...
680
  static int spacc_aead_cra_init(struct crypto_aead *tfm)
ce9213684   Jamie Iles   crypto: picoxcell...
681
  {
c1359495c   Herbert Xu   crypto: picoxcell...
682
683
684
  	struct spacc_aead_ctx *ctx = crypto_aead_ctx(tfm);
  	struct aead_alg *alg = crypto_aead_alg(tfm);
  	struct spacc_aead *spacc_alg = to_spacc_aead(alg);
ce9213684   Jamie Iles   crypto: picoxcell...
685
686
687
688
  	struct spacc_engine *engine = spacc_alg->engine;
  
  	ctx->generic.flags = spacc_alg->type;
  	ctx->generic.engine = engine;
c1359495c   Herbert Xu   crypto: picoxcell...
689
  	ctx->sw_cipher = crypto_alloc_aead(alg->base.cra_name, 0,
ce9213684   Jamie Iles   crypto: picoxcell...
690
  					   CRYPTO_ALG_NEED_FALLBACK);
c1359495c   Herbert Xu   crypto: picoxcell...
691
692
  	if (IS_ERR(ctx->sw_cipher))
  		return PTR_ERR(ctx->sw_cipher);
ce9213684   Jamie Iles   crypto: picoxcell...
693
694
  	ctx->generic.key_offs = spacc_alg->key_offs;
  	ctx->generic.iv_offs = spacc_alg->iv_offs;
c1359495c   Herbert Xu   crypto: picoxcell...
695
696
697
698
699
  	crypto_aead_set_reqsize(
  		tfm,
  		max(sizeof(struct spacc_req),
  		    sizeof(struct aead_request) +
  		    crypto_aead_reqsize(ctx->sw_cipher)));
ce9213684   Jamie Iles   crypto: picoxcell...
700
701
702
703
704
705
706
707
  
  	return 0;
  }
  
  /*
   * Destructor for an AEAD context. This is called when the transform is freed
   * and must free the fallback cipher.
   */
c1359495c   Herbert Xu   crypto: picoxcell...
708
  static void spacc_aead_cra_exit(struct crypto_aead *tfm)
ce9213684   Jamie Iles   crypto: picoxcell...
709
  {
c1359495c   Herbert Xu   crypto: picoxcell...
710
  	struct spacc_aead_ctx *ctx = crypto_aead_ctx(tfm);
ce9213684   Jamie Iles   crypto: picoxcell...
711

c1359495c   Herbert Xu   crypto: picoxcell...
712
  	crypto_free_aead(ctx->sw_cipher);
ce9213684   Jamie Iles   crypto: picoxcell...
713
714
715
716
717
718
  }
  
  /*
   * Set the DES key for a block cipher transform. This also performs weak key
   * checking if the transform has requested it.
   */
b3cde6bab   Ard Biesheuvel   crypto: picoxcell...
719
  static int spacc_des_setkey(struct crypto_skcipher *cipher, const u8 *key,
ce9213684   Jamie Iles   crypto: picoxcell...
720
721
  			    unsigned int len)
  {
b3cde6bab   Ard Biesheuvel   crypto: picoxcell...
722
  	struct spacc_ablk_ctx *ctx = crypto_skcipher_ctx(cipher);
0157fb268   Ard Biesheuvel   crypto: picoxcell...
723
  	int err;
b3cde6bab   Ard Biesheuvel   crypto: picoxcell...
724
  	err = verify_skcipher_des_key(cipher, key);
0157fb268   Ard Biesheuvel   crypto: picoxcell...
725
726
  	if (err)
  		return err;
ce9213684   Jamie Iles   crypto: picoxcell...
727
728
729
730
731
732
733
734
  
  	memcpy(ctx->key, key, len);
  	ctx->key_len = len;
  
  	return 0;
  }
  
  /*
aa113da29   Herbert Xu   crypto: picoxcell...
735
736
737
   * Set the 3DES key for a block cipher transform. This also performs weak key
   * checking if the transform has requested it.
   */
b3cde6bab   Ard Biesheuvel   crypto: picoxcell...
738
  static int spacc_des3_setkey(struct crypto_skcipher *cipher, const u8 *key,
aa113da29   Herbert Xu   crypto: picoxcell...
739
740
  			     unsigned int len)
  {
b3cde6bab   Ard Biesheuvel   crypto: picoxcell...
741
  	struct spacc_ablk_ctx *ctx = crypto_skcipher_ctx(cipher);
aa113da29   Herbert Xu   crypto: picoxcell...
742
  	int err;
b3cde6bab   Ard Biesheuvel   crypto: picoxcell...
743
  	err = verify_skcipher_des3_key(cipher, key);
0157fb268   Ard Biesheuvel   crypto: picoxcell...
744
  	if (err)
aa113da29   Herbert Xu   crypto: picoxcell...
745
  		return err;
aa113da29   Herbert Xu   crypto: picoxcell...
746
747
748
749
750
751
752
753
  
  	memcpy(ctx->key, key, len);
  	ctx->key_len = len;
  
  	return 0;
  }
  
  /*
ce9213684   Jamie Iles   crypto: picoxcell...
754
755
756
   * Set the key for an AES block cipher. Some key lengths are not supported in
   * hardware so this must also check whether a fallback is needed.
   */
b3cde6bab   Ard Biesheuvel   crypto: picoxcell...
757
  static int spacc_aes_setkey(struct crypto_skcipher *cipher, const u8 *key,
ce9213684   Jamie Iles   crypto: picoxcell...
758
759
  			    unsigned int len)
  {
b3cde6bab   Ard Biesheuvel   crypto: picoxcell...
760
  	struct crypto_tfm *tfm = crypto_skcipher_tfm(cipher);
ce9213684   Jamie Iles   crypto: picoxcell...
761
762
  	struct spacc_ablk_ctx *ctx = crypto_tfm_ctx(tfm);
  	int err = 0;
674f368a9   Eric Biggers   crypto: remove CR...
763
  	if (len > AES_MAX_KEY_SIZE)
ce9213684   Jamie Iles   crypto: picoxcell...
764
  		return -EINVAL;
ce9213684   Jamie Iles   crypto: picoxcell...
765
766
767
768
769
770
  
  	/*
  	 * IPSec engine only supports 128 and 256 bit AES keys. If we get a
  	 * request for any other size (192 bits) then we need to do a software
  	 * fallback.
  	 */
1eb60ff82   Herbert Xu   crypto: picoxcell...
771
772
773
  	if (len != AES_KEYSIZE_128 && len != AES_KEYSIZE_256) {
  		if (!ctx->sw_cipher)
  			return -EINVAL;
ce9213684   Jamie Iles   crypto: picoxcell...
774
775
776
777
  		/*
  		 * Set the fallback transform to use the same request flags as
  		 * the hardware transform.
  		 */
dc6e71c9d   Ard Biesheuvel   crypto: picoxcell...
778
  		crypto_skcipher_clear_flags(ctx->sw_cipher,
1eb60ff82   Herbert Xu   crypto: picoxcell...
779
  					    CRYPTO_TFM_REQ_MASK);
dc6e71c9d   Ard Biesheuvel   crypto: picoxcell...
780
  		crypto_skcipher_set_flags(ctx->sw_cipher,
1eb60ff82   Herbert Xu   crypto: picoxcell...
781
782
  					  cipher->base.crt_flags &
  					  CRYPTO_TFM_REQ_MASK);
dc6e71c9d   Ard Biesheuvel   crypto: picoxcell...
783
  		err = crypto_skcipher_setkey(ctx->sw_cipher, key, len);
ce9213684   Jamie Iles   crypto: picoxcell...
784
785
  		if (err)
  			goto sw_setkey_failed;
1eb60ff82   Herbert Xu   crypto: picoxcell...
786
  	}
ce9213684   Jamie Iles   crypto: picoxcell...
787
788
789
790
791
  
  	memcpy(ctx->key, key, len);
  	ctx->key_len = len;
  
  sw_setkey_failed:
ce9213684   Jamie Iles   crypto: picoxcell...
792
793
  	return err;
  }
b3cde6bab   Ard Biesheuvel   crypto: picoxcell...
794
  static int spacc_kasumi_f8_setkey(struct crypto_skcipher *cipher,
ce9213684   Jamie Iles   crypto: picoxcell...
795
796
  				  const u8 *key, unsigned int len)
  {
b3cde6bab   Ard Biesheuvel   crypto: picoxcell...
797
  	struct crypto_tfm *tfm = crypto_skcipher_tfm(cipher);
ce9213684   Jamie Iles   crypto: picoxcell...
798
799
800
801
  	struct spacc_ablk_ctx *ctx = crypto_tfm_ctx(tfm);
  	int err = 0;
  
  	if (len > AES_MAX_KEY_SIZE) {
ce9213684   Jamie Iles   crypto: picoxcell...
802
803
804
805
806
807
808
809
810
811
812
813
814
  		err = -EINVAL;
  		goto out;
  	}
  
  	memcpy(ctx->key, key, len);
  	ctx->key_len = len;
  
  out:
  	return err;
  }
  
  static int spacc_ablk_need_fallback(struct spacc_req *req)
  {
b3cde6bab   Ard Biesheuvel   crypto: picoxcell...
815
816
817
  	struct skcipher_request *ablk_req = skcipher_request_cast(req->req);
  	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(ablk_req);
  	struct spacc_alg *spacc_alg = to_spacc_skcipher(crypto_skcipher_alg(tfm));
ce9213684   Jamie Iles   crypto: picoxcell...
818
  	struct spacc_ablk_ctx *ctx;
ce9213684   Jamie Iles   crypto: picoxcell...
819

b3cde6bab   Ard Biesheuvel   crypto: picoxcell...
820
  	ctx = crypto_skcipher_ctx(tfm);
ce9213684   Jamie Iles   crypto: picoxcell...
821
822
823
824
825
826
827
828
829
  
  	return (spacc_alg->ctrl_default & SPACC_CRYPTO_ALG_MASK) ==
  			SPA_CTRL_CIPH_ALG_AES &&
  			ctx->key_len != AES_KEYSIZE_128 &&
  			ctx->key_len != AES_KEYSIZE_256;
  }
  
  static void spacc_ablk_complete(struct spacc_req *req)
  {
b3cde6bab   Ard Biesheuvel   crypto: picoxcell...
830
  	struct skcipher_request *ablk_req = skcipher_request_cast(req->req);
ce9213684   Jamie Iles   crypto: picoxcell...
831
832
833
  
  	if (ablk_req->src != ablk_req->dst) {
  		spacc_free_ddt(req, req->src_ddt, req->src_addr, ablk_req->src,
b3cde6bab   Ard Biesheuvel   crypto: picoxcell...
834
  			       ablk_req->cryptlen, DMA_TO_DEVICE);
ce9213684   Jamie Iles   crypto: picoxcell...
835
  		spacc_free_ddt(req, req->dst_ddt, req->dst_addr, ablk_req->dst,
b3cde6bab   Ard Biesheuvel   crypto: picoxcell...
836
  			       ablk_req->cryptlen, DMA_FROM_DEVICE);
ce9213684   Jamie Iles   crypto: picoxcell...
837
838
  	} else
  		spacc_free_ddt(req, req->dst_ddt, req->dst_addr, ablk_req->dst,
b3cde6bab   Ard Biesheuvel   crypto: picoxcell...
839
  			       ablk_req->cryptlen, DMA_BIDIRECTIONAL);
ce9213684   Jamie Iles   crypto: picoxcell...
840
841
842
843
844
845
  
  	req->req->complete(req->req, req->result);
  }
  
  static int spacc_ablk_submit(struct spacc_req *req)
  {
b3cde6bab   Ard Biesheuvel   crypto: picoxcell...
846
847
848
849
850
  	struct skcipher_request *ablk_req = skcipher_request_cast(req->req);
  	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(ablk_req);
  	struct skcipher_alg *alg = crypto_skcipher_alg(tfm);
  	struct spacc_alg *spacc_alg = to_spacc_skcipher(alg);
  	struct spacc_ablk_ctx *ctx = crypto_skcipher_ctx(tfm);
ce9213684   Jamie Iles   crypto: picoxcell...
851
852
853
854
  	struct spacc_engine *engine = ctx->generic.engine;
  	u32 ctrl;
  
  	req->ctx_id = spacc_load_ctx(&ctx->generic, ctx->key,
b3cde6bab   Ard Biesheuvel   crypto: picoxcell...
855
  		ctx->key_len, ablk_req->iv, alg->ivsize,
ce9213684   Jamie Iles   crypto: picoxcell...
856
857
858
859
860
  		NULL, 0);
  
  	writel(req->src_addr, engine->regs + SPA_SRC_PTR_REG_OFFSET);
  	writel(req->dst_addr, engine->regs + SPA_DST_PTR_REG_OFFSET);
  	writel(0, engine->regs + SPA_OFFSET_REG_OFFSET);
b3cde6bab   Ard Biesheuvel   crypto: picoxcell...
861
  	writel(ablk_req->cryptlen, engine->regs + SPA_PROC_LEN_REG_OFFSET);
ce9213684   Jamie Iles   crypto: picoxcell...
862
863
864
865
866
867
868
869
870
871
872
873
874
875
  	writel(0, engine->regs + SPA_ICV_OFFSET_REG_OFFSET);
  	writel(0, engine->regs + SPA_AUX_INFO_REG_OFFSET);
  	writel(0, engine->regs + SPA_AAD_LEN_REG_OFFSET);
  
  	ctrl = spacc_alg->ctrl_default | (req->ctx_id << SPA_CTRL_CTX_IDX) |
  		(req->is_encrypt ? (1 << SPA_CTRL_ENCRYPT_IDX) :
  		 (1 << SPA_CTRL_KEY_EXP));
  
  	mod_timer(&engine->packet_timeout, jiffies + PACKET_TIMEOUT);
  
  	writel(ctrl, engine->regs + SPA_CTRL_REG_OFFSET);
  
  	return -EINPROGRESS;
  }
b3cde6bab   Ard Biesheuvel   crypto: picoxcell...
876
  static int spacc_ablk_do_fallback(struct skcipher_request *req,
ce9213684   Jamie Iles   crypto: picoxcell...
877
878
879
  				  unsigned alg_type, bool is_encrypt)
  {
  	struct crypto_tfm *old_tfm =
b3cde6bab   Ard Biesheuvel   crypto: picoxcell...
880
  	    crypto_skcipher_tfm(crypto_skcipher_reqtfm(req));
ce9213684   Jamie Iles   crypto: picoxcell...
881
  	struct spacc_ablk_ctx *ctx = crypto_tfm_ctx(old_tfm);
dc6e71c9d   Ard Biesheuvel   crypto: picoxcell...
882
  	struct spacc_req *dev_req = skcipher_request_ctx(req);
ce9213684   Jamie Iles   crypto: picoxcell...
883
  	int err;
ce9213684   Jamie Iles   crypto: picoxcell...
884
885
886
887
888
  	/*
  	 * Change the request to use the software fallback transform, and once
  	 * the ciphering has completed, put the old transform back into the
  	 * request.
  	 */
dc6e71c9d   Ard Biesheuvel   crypto: picoxcell...
889
890
891
892
  	skcipher_request_set_tfm(&dev_req->fallback_req, ctx->sw_cipher);
  	skcipher_request_set_callback(&dev_req->fallback_req, req->base.flags,
  				      req->base.complete, req->base.data);
  	skcipher_request_set_crypt(&dev_req->fallback_req, req->src, req->dst,
b3cde6bab   Ard Biesheuvel   crypto: picoxcell...
893
  				   req->cryptlen, req->iv);
dc6e71c9d   Ard Biesheuvel   crypto: picoxcell...
894
895
  	err = is_encrypt ? crypto_skcipher_encrypt(&dev_req->fallback_req) :
  			   crypto_skcipher_decrypt(&dev_req->fallback_req);
ce9213684   Jamie Iles   crypto: picoxcell...
896
897
898
  
  	return err;
  }
b3cde6bab   Ard Biesheuvel   crypto: picoxcell...
899
  static int spacc_ablk_setup(struct skcipher_request *req, unsigned alg_type,
ce9213684   Jamie Iles   crypto: picoxcell...
900
901
  			    bool is_encrypt)
  {
b3cde6bab   Ard Biesheuvel   crypto: picoxcell...
902
903
904
905
  	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
  	struct skcipher_alg *alg = crypto_skcipher_alg(tfm);
  	struct spacc_engine *engine = to_spacc_skcipher(alg)->engine;
  	struct spacc_req *dev_req = skcipher_request_ctx(req);
ce9213684   Jamie Iles   crypto: picoxcell...
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
  	unsigned long flags;
  	int err = -ENOMEM;
  
  	dev_req->req		= &req->base;
  	dev_req->is_encrypt	= is_encrypt;
  	dev_req->engine		= engine;
  	dev_req->complete	= spacc_ablk_complete;
  	dev_req->result		= -EINPROGRESS;
  
  	if (unlikely(spacc_ablk_need_fallback(dev_req)))
  		return spacc_ablk_do_fallback(req, alg_type, is_encrypt);
  
  	/*
  	 * Create the DDT's for the engine. If we share the same source and
  	 * destination then we can optimize by reusing the DDT's.
  	 */
  	if (req->src != req->dst) {
  		dev_req->src_ddt = spacc_sg_to_ddt(engine, req->src,
b3cde6bab   Ard Biesheuvel   crypto: picoxcell...
924
  			req->cryptlen, DMA_TO_DEVICE, &dev_req->src_addr);
ce9213684   Jamie Iles   crypto: picoxcell...
925
926
927
928
  		if (!dev_req->src_ddt)
  			goto out;
  
  		dev_req->dst_ddt = spacc_sg_to_ddt(engine, req->dst,
b3cde6bab   Ard Biesheuvel   crypto: picoxcell...
929
  			req->cryptlen, DMA_FROM_DEVICE, &dev_req->dst_addr);
ce9213684   Jamie Iles   crypto: picoxcell...
930
931
932
933
  		if (!dev_req->dst_ddt)
  			goto out_free_src;
  	} else {
  		dev_req->dst_ddt = spacc_sg_to_ddt(engine, req->dst,
b3cde6bab   Ard Biesheuvel   crypto: picoxcell...
934
  			req->cryptlen, DMA_BIDIRECTIONAL, &dev_req->dst_addr);
ce9213684   Jamie Iles   crypto: picoxcell...
935
936
937
938
939
940
941
942
943
944
945
946
947
948
  		if (!dev_req->dst_ddt)
  			goto out;
  
  		dev_req->src_ddt = NULL;
  		dev_req->src_addr = dev_req->dst_addr;
  	}
  
  	err = -EINPROGRESS;
  	spin_lock_irqsave(&engine->hw_lock, flags);
  	/*
  	 * Check if the engine will accept the operation now. If it won't then
  	 * we either stick it on the end of a pending list if we can backlog,
  	 * or bailout with an error if not.
  	 */
40bfc14f3   Jamie Iles   crypto: picoxcell...
949
950
  	if (unlikely(spacc_fifo_cmd_full(engine)) ||
  	    engine->in_flight + 1 > engine->fifo_sz) {
ce9213684   Jamie Iles   crypto: picoxcell...
951
952
953
954
955
956
957
  		if (!(req->base.flags & CRYPTO_TFM_REQ_MAY_BACKLOG)) {
  			err = -EBUSY;
  			spin_unlock_irqrestore(&engine->hw_lock, flags);
  			goto out_free_ddts;
  		}
  		list_add_tail(&dev_req->list, &engine->pending);
  	} else {
40bfc14f3   Jamie Iles   crypto: picoxcell...
958
959
  		list_add_tail(&dev_req->list, &engine->pending);
  		spacc_push(engine);
ce9213684   Jamie Iles   crypto: picoxcell...
960
961
962
963
964
965
966
  	}
  	spin_unlock_irqrestore(&engine->hw_lock, flags);
  
  	goto out;
  
  out_free_ddts:
  	spacc_free_ddt(dev_req, dev_req->dst_ddt, dev_req->dst_addr, req->dst,
b3cde6bab   Ard Biesheuvel   crypto: picoxcell...
967
  		       req->cryptlen, req->src == req->dst ?
ce9213684   Jamie Iles   crypto: picoxcell...
968
969
970
971
  		       DMA_BIDIRECTIONAL : DMA_FROM_DEVICE);
  out_free_src:
  	if (req->src != req->dst)
  		spacc_free_ddt(dev_req, dev_req->src_ddt, dev_req->src_addr,
b3cde6bab   Ard Biesheuvel   crypto: picoxcell...
972
  			       req->src, req->cryptlen, DMA_TO_DEVICE);
ce9213684   Jamie Iles   crypto: picoxcell...
973
974
975
  out:
  	return err;
  }
b3cde6bab   Ard Biesheuvel   crypto: picoxcell...
976
  static int spacc_ablk_init_tfm(struct crypto_skcipher *tfm)
ce9213684   Jamie Iles   crypto: picoxcell...
977
  {
b3cde6bab   Ard Biesheuvel   crypto: picoxcell...
978
979
980
  	struct spacc_ablk_ctx *ctx = crypto_skcipher_ctx(tfm);
  	struct skcipher_alg *alg = crypto_skcipher_alg(tfm);
  	struct spacc_alg *spacc_alg = to_spacc_skcipher(alg);
ce9213684   Jamie Iles   crypto: picoxcell...
981
982
983
984
  	struct spacc_engine *engine = spacc_alg->engine;
  
  	ctx->generic.flags = spacc_alg->type;
  	ctx->generic.engine = engine;
b3cde6bab   Ard Biesheuvel   crypto: picoxcell...
985
  	if (alg->base.cra_flags & CRYPTO_ALG_NEED_FALLBACK) {
dc6e71c9d   Ard Biesheuvel   crypto: picoxcell...
986
987
  		ctx->sw_cipher = crypto_alloc_skcipher(alg->base.cra_name, 0,
  						       CRYPTO_ALG_NEED_FALLBACK);
ce9213684   Jamie Iles   crypto: picoxcell...
988
989
990
  		if (IS_ERR(ctx->sw_cipher)) {
  			dev_warn(engine->dev, "failed to allocate fallback for %s
  ",
b3cde6bab   Ard Biesheuvel   crypto: picoxcell...
991
  				 alg->base.cra_name);
1eb60ff82   Herbert Xu   crypto: picoxcell...
992
  			return PTR_ERR(ctx->sw_cipher);
ce9213684   Jamie Iles   crypto: picoxcell...
993
  		}
dc6e71c9d   Ard Biesheuvel   crypto: picoxcell...
994
995
996
997
998
999
  		crypto_skcipher_set_reqsize(tfm, sizeof(struct spacc_req) +
  						 crypto_skcipher_reqsize(ctx->sw_cipher));
  	} else {
  		/* take the size without the fallback skcipher_request at the end */
  		crypto_skcipher_set_reqsize(tfm, offsetof(struct spacc_req,
  							  fallback_req));
ce9213684   Jamie Iles   crypto: picoxcell...
1000
  	}
dc6e71c9d   Ard Biesheuvel   crypto: picoxcell...
1001

ce9213684   Jamie Iles   crypto: picoxcell...
1002
1003
  	ctx->generic.key_offs = spacc_alg->key_offs;
  	ctx->generic.iv_offs = spacc_alg->iv_offs;
ce9213684   Jamie Iles   crypto: picoxcell...
1004
1005
  	return 0;
  }
b3cde6bab   Ard Biesheuvel   crypto: picoxcell...
1006
  static void spacc_ablk_exit_tfm(struct crypto_skcipher *tfm)
ce9213684   Jamie Iles   crypto: picoxcell...
1007
  {
b3cde6bab   Ard Biesheuvel   crypto: picoxcell...
1008
  	struct spacc_ablk_ctx *ctx = crypto_skcipher_ctx(tfm);
ce9213684   Jamie Iles   crypto: picoxcell...
1009

dc6e71c9d   Ard Biesheuvel   crypto: picoxcell...
1010
  	crypto_free_skcipher(ctx->sw_cipher);
ce9213684   Jamie Iles   crypto: picoxcell...
1011
  }
b3cde6bab   Ard Biesheuvel   crypto: picoxcell...
1012
  static int spacc_ablk_encrypt(struct skcipher_request *req)
ce9213684   Jamie Iles   crypto: picoxcell...
1013
  {
b3cde6bab   Ard Biesheuvel   crypto: picoxcell...
1014
1015
1016
  	struct crypto_skcipher *cipher = crypto_skcipher_reqtfm(req);
  	struct skcipher_alg *alg = crypto_skcipher_alg(cipher);
  	struct spacc_alg *spacc_alg = to_spacc_skcipher(alg);
ce9213684   Jamie Iles   crypto: picoxcell...
1017

b3cde6bab   Ard Biesheuvel   crypto: picoxcell...
1018
  	return spacc_ablk_setup(req, spacc_alg->type, 1);
ce9213684   Jamie Iles   crypto: picoxcell...
1019
  }
b3cde6bab   Ard Biesheuvel   crypto: picoxcell...
1020
  static int spacc_ablk_decrypt(struct skcipher_request *req)
ce9213684   Jamie Iles   crypto: picoxcell...
1021
  {
b3cde6bab   Ard Biesheuvel   crypto: picoxcell...
1022
1023
1024
  	struct crypto_skcipher *cipher = crypto_skcipher_reqtfm(req);
  	struct skcipher_alg *alg = crypto_skcipher_alg(cipher);
  	struct spacc_alg *spacc_alg = to_spacc_skcipher(alg);
ce9213684   Jamie Iles   crypto: picoxcell...
1025

b3cde6bab   Ard Biesheuvel   crypto: picoxcell...
1026
  	return spacc_ablk_setup(req, spacc_alg->type, 0);
ce9213684   Jamie Iles   crypto: picoxcell...
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
  }
  
  static inline int spacc_fifo_stat_empty(struct spacc_engine *engine)
  {
  	return readl(engine->regs + SPA_FIFO_STAT_REG_OFFSET) &
  		SPA_FIFO_STAT_EMPTY;
  }
  
  static void spacc_process_done(struct spacc_engine *engine)
  {
  	struct spacc_req *req;
  	unsigned long flags;
  
  	spin_lock_irqsave(&engine->hw_lock, flags);
  
  	while (!spacc_fifo_stat_empty(engine)) {
  		req = list_first_entry(&engine->in_progress, struct spacc_req,
  				       list);
  		list_move_tail(&req->list, &engine->completed);
40bfc14f3   Jamie Iles   crypto: picoxcell...
1046
  		--engine->in_flight;
ce9213684   Jamie Iles   crypto: picoxcell...
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
  
  		/* POP the status register. */
  		writel(~0, engine->regs + SPA_STAT_POP_REG_OFFSET);
  		req->result = (readl(engine->regs + SPA_STATUS_REG_OFFSET) &
  		     SPA_STATUS_RES_CODE_MASK) >> SPA_STATUS_RES_CODE_OFFSET;
  
  		/*
  		 * Convert the SPAcc error status into the standard POSIX error
  		 * codes.
  		 */
  		if (unlikely(req->result)) {
  			switch (req->result) {
  			case SPA_STATUS_ICV_FAIL:
  				req->result = -EBADMSG;
  				break;
  
  			case SPA_STATUS_MEMORY_ERROR:
  				dev_warn(engine->dev,
  					 "memory error triggered
  ");
  				req->result = -EFAULT;
  				break;
  
  			case SPA_STATUS_BLOCK_ERROR:
  				dev_warn(engine->dev,
  					 "block error triggered
  ");
  				req->result = -EIO;
  				break;
  			}
  		}
  	}
  
  	tasklet_schedule(&engine->complete);
  
  	spin_unlock_irqrestore(&engine->hw_lock, flags);
  }
  
  static irqreturn_t spacc_spacc_irq(int irq, void *dev)
  {
  	struct spacc_engine *engine = (struct spacc_engine *)dev;
  	u32 spacc_irq_stat = readl(engine->regs + SPA_IRQ_STAT_REG_OFFSET);
  
  	writel(spacc_irq_stat, engine->regs + SPA_IRQ_STAT_REG_OFFSET);
  	spacc_process_done(engine);
  
  	return IRQ_HANDLED;
  }
f34d8d506   Kees Cook   crypto: Convert t...
1095
  static void spacc_packet_timeout(struct timer_list *t)
ce9213684   Jamie Iles   crypto: picoxcell...
1096
  {
f34d8d506   Kees Cook   crypto: Convert t...
1097
  	struct spacc_engine *engine = from_timer(engine, t, packet_timeout);
ce9213684   Jamie Iles   crypto: picoxcell...
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
  
  	spacc_process_done(engine);
  }
  
  static int spacc_req_submit(struct spacc_req *req)
  {
  	struct crypto_alg *alg = req->req->tfm->__crt_alg;
  
  	if (CRYPTO_ALG_TYPE_AEAD == (CRYPTO_ALG_TYPE_MASK & alg->cra_flags))
  		return spacc_aead_submit(req);
  	else
  		return spacc_ablk_submit(req);
  }
  
  static void spacc_spacc_complete(unsigned long data)
  {
  	struct spacc_engine *engine = (struct spacc_engine *)data;
  	struct spacc_req *req, *tmp;
  	unsigned long flags;
ce9213684   Jamie Iles   crypto: picoxcell...
1117
1118
1119
  	LIST_HEAD(completed);
  
  	spin_lock_irqsave(&engine->hw_lock, flags);
40bfc14f3   Jamie Iles   crypto: picoxcell...
1120

ce9213684   Jamie Iles   crypto: picoxcell...
1121
  	list_splice_init(&engine->completed, &completed);
40bfc14f3   Jamie Iles   crypto: picoxcell...
1122
1123
1124
  	spacc_push(engine);
  	if (engine->in_flight)
  		mod_timer(&engine->packet_timeout, jiffies + PACKET_TIMEOUT);
ce9213684   Jamie Iles   crypto: picoxcell...
1125
1126
1127
  	spin_unlock_irqrestore(&engine->hw_lock, flags);
  
  	list_for_each_entry_safe(req, tmp, &completed, list) {
40bfc14f3   Jamie Iles   crypto: picoxcell...
1128
  		list_del(&req->list);
b64dc04be   Jamie Iles   crypto: picoxcell...
1129
  		req->complete(req);
ce9213684   Jamie Iles   crypto: picoxcell...
1130
  	}
ce9213684   Jamie Iles   crypto: picoxcell...
1131
1132
1133
1134
1135
  }
  
  #ifdef CONFIG_PM
  static int spacc_suspend(struct device *dev)
  {
8ce31dca7   Wolfram Sang   crypto: drivers -...
1136
  	struct spacc_engine *engine = dev_get_drvdata(dev);
ce9213684   Jamie Iles   crypto: picoxcell...
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
  
  	/*
  	 * We only support standby mode. All we have to do is gate the clock to
  	 * the spacc. The hardware will preserve state until we turn it back
  	 * on again.
  	 */
  	clk_disable(engine->clk);
  
  	return 0;
  }
  
  static int spacc_resume(struct device *dev)
  {
8ce31dca7   Wolfram Sang   crypto: drivers -...
1150
  	struct spacc_engine *engine = dev_get_drvdata(dev);
ce9213684   Jamie Iles   crypto: picoxcell...
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
  
  	return clk_enable(engine->clk);
  }
  
  static const struct dev_pm_ops spacc_pm_ops = {
  	.suspend	= spacc_suspend,
  	.resume		= spacc_resume,
  };
  #endif /* CONFIG_PM */
  
  static inline struct spacc_engine *spacc_dev_to_engine(struct device *dev)
  {
0e4c61011   Kefeng Wang   crypto: picoxcell...
1163
  	return dev ? dev_get_drvdata(dev) : NULL;
ce9213684   Jamie Iles   crypto: picoxcell...
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
  }
  
  static ssize_t spacc_stat_irq_thresh_show(struct device *dev,
  					  struct device_attribute *attr,
  					  char *buf)
  {
  	struct spacc_engine *engine = spacc_dev_to_engine(dev);
  
  	return snprintf(buf, PAGE_SIZE, "%u
  ", engine->stat_irq_thresh);
  }
  
  static ssize_t spacc_stat_irq_thresh_store(struct device *dev,
  					   struct device_attribute *attr,
  					   const char *buf, size_t len)
  {
  	struct spacc_engine *engine = spacc_dev_to_engine(dev);
  	unsigned long thresh;
61e2d1a9b   Jingoo Han   crypto: picoxcell...
1182
  	if (kstrtoul(buf, 0, &thresh))
ce9213684   Jamie Iles   crypto: picoxcell...
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
  		return -EINVAL;
  
  	thresh = clamp(thresh, 1UL, engine->fifo_sz - 1);
  
  	engine->stat_irq_thresh = thresh;
  	writel(engine->stat_irq_thresh << SPA_IRQ_CTRL_STAT_CNT_OFFSET,
  	       engine->regs + SPA_IRQ_CTRL_REG_OFFSET);
  
  	return len;
  }
  static DEVICE_ATTR(stat_irq_thresh, 0644, spacc_stat_irq_thresh_show,
  		   spacc_stat_irq_thresh_store);
  
  static struct spacc_alg ipsec_engine_algs[] = {
  	{
  		.ctrl_default = SPA_CTRL_CIPH_ALG_AES | SPA_CTRL_CIPH_MODE_CBC,
  		.key_offs = 0,
  		.iv_offs = AES_MAX_KEY_SIZE,
  		.alg = {
b3cde6bab   Ard Biesheuvel   crypto: picoxcell...
1202
1203
1204
1205
1206
  			.base.cra_name		= "cbc(aes)",
  			.base.cra_driver_name	= "cbc-aes-picoxcell",
  			.base.cra_priority	= SPACC_CRYPTO_ALG_PRIORITY,
  			.base.cra_flags		= CRYPTO_ALG_KERN_DRIVER_ONLY |
  						  CRYPTO_ALG_ASYNC |
b8aa7dc5c   Mikulas Patocka   crypto: drivers -...
1207
  						  CRYPTO_ALG_ALLOCATES_MEMORY |
b3cde6bab   Ard Biesheuvel   crypto: picoxcell...
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
  						  CRYPTO_ALG_NEED_FALLBACK,
  			.base.cra_blocksize	= AES_BLOCK_SIZE,
  			.base.cra_ctxsize	= sizeof(struct spacc_ablk_ctx),
  			.base.cra_module	= THIS_MODULE,
  
  			.setkey			= spacc_aes_setkey,
  			.encrypt 		= spacc_ablk_encrypt,
  			.decrypt 		= spacc_ablk_decrypt,
  			.min_keysize 		= AES_MIN_KEY_SIZE,
  			.max_keysize 		= AES_MAX_KEY_SIZE,
  			.ivsize			= AES_BLOCK_SIZE,
  			.init			= spacc_ablk_init_tfm,
  			.exit			= spacc_ablk_exit_tfm,
ce9213684   Jamie Iles   crypto: picoxcell...
1221
1222
1223
1224
1225
1226
1227
  		},
  	},
  	{
  		.key_offs = 0,
  		.iv_offs = AES_MAX_KEY_SIZE,
  		.ctrl_default = SPA_CTRL_CIPH_ALG_AES | SPA_CTRL_CIPH_MODE_ECB,
  		.alg = {
b3cde6bab   Ard Biesheuvel   crypto: picoxcell...
1228
1229
1230
1231
1232
  			.base.cra_name		= "ecb(aes)",
  			.base.cra_driver_name	= "ecb-aes-picoxcell",
  			.base.cra_priority	= SPACC_CRYPTO_ALG_PRIORITY,
  			.base.cra_flags		= CRYPTO_ALG_KERN_DRIVER_ONLY |
  						  CRYPTO_ALG_ASYNC |
b8aa7dc5c   Mikulas Patocka   crypto: drivers -...
1233
  						  CRYPTO_ALG_ALLOCATES_MEMORY |
b3cde6bab   Ard Biesheuvel   crypto: picoxcell...
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
  						  CRYPTO_ALG_NEED_FALLBACK,
  			.base.cra_blocksize	= AES_BLOCK_SIZE,
  			.base.cra_ctxsize	= sizeof(struct spacc_ablk_ctx),
  			.base.cra_module	= THIS_MODULE,
  
  			.setkey			= spacc_aes_setkey,
  			.encrypt 		= spacc_ablk_encrypt,
  			.decrypt 		= spacc_ablk_decrypt,
  			.min_keysize 		= AES_MIN_KEY_SIZE,
  			.max_keysize 		= AES_MAX_KEY_SIZE,
  			.init			= spacc_ablk_init_tfm,
  			.exit			= spacc_ablk_exit_tfm,
ce9213684   Jamie Iles   crypto: picoxcell...
1246
1247
1248
1249
1250
1251
1252
  		},
  	},
  	{
  		.key_offs = DES_BLOCK_SIZE,
  		.iv_offs = 0,
  		.ctrl_default = SPA_CTRL_CIPH_ALG_DES | SPA_CTRL_CIPH_MODE_CBC,
  		.alg = {
b3cde6bab   Ard Biesheuvel   crypto: picoxcell...
1253
1254
1255
1256
  			.base.cra_name		= "cbc(des)",
  			.base.cra_driver_name	= "cbc-des-picoxcell",
  			.base.cra_priority	= SPACC_CRYPTO_ALG_PRIORITY,
  			.base.cra_flags		= CRYPTO_ALG_KERN_DRIVER_ONLY |
b8aa7dc5c   Mikulas Patocka   crypto: drivers -...
1257
1258
  						  CRYPTO_ALG_ASYNC |
  						  CRYPTO_ALG_ALLOCATES_MEMORY,
b3cde6bab   Ard Biesheuvel   crypto: picoxcell...
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
  			.base.cra_blocksize	= DES_BLOCK_SIZE,
  			.base.cra_ctxsize	= sizeof(struct spacc_ablk_ctx),
  			.base.cra_module	= THIS_MODULE,
  
  			.setkey			= spacc_des_setkey,
  			.encrypt		= spacc_ablk_encrypt,
  			.decrypt		= spacc_ablk_decrypt,
  			.min_keysize		= DES_KEY_SIZE,
  			.max_keysize		= DES_KEY_SIZE,
  			.ivsize			= DES_BLOCK_SIZE,
  			.init			= spacc_ablk_init_tfm,
  			.exit			= spacc_ablk_exit_tfm,
ce9213684   Jamie Iles   crypto: picoxcell...
1271
1272
1273
1274
1275
1276
1277
  		},
  	},
  	{
  		.key_offs = DES_BLOCK_SIZE,
  		.iv_offs = 0,
  		.ctrl_default = SPA_CTRL_CIPH_ALG_DES | SPA_CTRL_CIPH_MODE_ECB,
  		.alg = {
b3cde6bab   Ard Biesheuvel   crypto: picoxcell...
1278
1279
1280
1281
  			.base.cra_name		= "ecb(des)",
  			.base.cra_driver_name	= "ecb-des-picoxcell",
  			.base.cra_priority	= SPACC_CRYPTO_ALG_PRIORITY,
  			.base.cra_flags		= CRYPTO_ALG_KERN_DRIVER_ONLY |
b8aa7dc5c   Mikulas Patocka   crypto: drivers -...
1282
1283
  						  CRYPTO_ALG_ASYNC |
  						  CRYPTO_ALG_ALLOCATES_MEMORY,
b3cde6bab   Ard Biesheuvel   crypto: picoxcell...
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
  			.base.cra_blocksize	= DES_BLOCK_SIZE,
  			.base.cra_ctxsize	= sizeof(struct spacc_ablk_ctx),
  			.base.cra_module	= THIS_MODULE,
  
  			.setkey			= spacc_des_setkey,
  			.encrypt		= spacc_ablk_encrypt,
  			.decrypt		= spacc_ablk_decrypt,
  			.min_keysize		= DES_KEY_SIZE,
  			.max_keysize		= DES_KEY_SIZE,
  			.init			= spacc_ablk_init_tfm,
  			.exit			= spacc_ablk_exit_tfm,
ce9213684   Jamie Iles   crypto: picoxcell...
1295
1296
1297
1298
1299
1300
1301
  		},
  	},
  	{
  		.key_offs = DES_BLOCK_SIZE,
  		.iv_offs = 0,
  		.ctrl_default = SPA_CTRL_CIPH_ALG_DES | SPA_CTRL_CIPH_MODE_CBC,
  		.alg = {
b3cde6bab   Ard Biesheuvel   crypto: picoxcell...
1302
1303
1304
1305
  			.base.cra_name		= "cbc(des3_ede)",
  			.base.cra_driver_name	= "cbc-des3-ede-picoxcell",
  			.base.cra_priority	= SPACC_CRYPTO_ALG_PRIORITY,
  			.base.cra_flags		= CRYPTO_ALG_ASYNC |
b8aa7dc5c   Mikulas Patocka   crypto: drivers -...
1306
  						  CRYPTO_ALG_ALLOCATES_MEMORY |
b3cde6bab   Ard Biesheuvel   crypto: picoxcell...
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
  						  CRYPTO_ALG_KERN_DRIVER_ONLY,
  			.base.cra_blocksize	= DES3_EDE_BLOCK_SIZE,
  			.base.cra_ctxsize	= sizeof(struct spacc_ablk_ctx),
  			.base.cra_module	= THIS_MODULE,
  
  			.setkey			= spacc_des3_setkey,
  			.encrypt		= spacc_ablk_encrypt,
  			.decrypt		= spacc_ablk_decrypt,
  			.min_keysize		= DES3_EDE_KEY_SIZE,
  			.max_keysize		= DES3_EDE_KEY_SIZE,
  			.ivsize			= DES3_EDE_BLOCK_SIZE,
  			.init			= spacc_ablk_init_tfm,
  			.exit			= spacc_ablk_exit_tfm,
ce9213684   Jamie Iles   crypto: picoxcell...
1320
1321
1322
1323
1324
1325
1326
  		},
  	},
  	{
  		.key_offs = DES_BLOCK_SIZE,
  		.iv_offs = 0,
  		.ctrl_default = SPA_CTRL_CIPH_ALG_DES | SPA_CTRL_CIPH_MODE_ECB,
  		.alg = {
b3cde6bab   Ard Biesheuvel   crypto: picoxcell...
1327
1328
1329
1330
  			.base.cra_name		= "ecb(des3_ede)",
  			.base.cra_driver_name	= "ecb-des3-ede-picoxcell",
  			.base.cra_priority	= SPACC_CRYPTO_ALG_PRIORITY,
  			.base.cra_flags		= CRYPTO_ALG_ASYNC |
b8aa7dc5c   Mikulas Patocka   crypto: drivers -...
1331
  						  CRYPTO_ALG_ALLOCATES_MEMORY |
b3cde6bab   Ard Biesheuvel   crypto: picoxcell...
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
  						  CRYPTO_ALG_KERN_DRIVER_ONLY,
  			.base.cra_blocksize	= DES3_EDE_BLOCK_SIZE,
  			.base.cra_ctxsize	= sizeof(struct spacc_ablk_ctx),
  			.base.cra_module	= THIS_MODULE,
  
  			.setkey			= spacc_des3_setkey,
  			.encrypt		= spacc_ablk_encrypt,
  			.decrypt		= spacc_ablk_decrypt,
  			.min_keysize		= DES3_EDE_KEY_SIZE,
  			.max_keysize		= DES3_EDE_KEY_SIZE,
  			.init			= spacc_ablk_init_tfm,
  			.exit			= spacc_ablk_exit_tfm,
ce9213684   Jamie Iles   crypto: picoxcell...
1344
1345
  		},
  	},
c1359495c   Herbert Xu   crypto: picoxcell...
1346
1347
1348
  };
  
  static struct spacc_aead ipsec_engine_aeads[] = {
ce9213684   Jamie Iles   crypto: picoxcell...
1349
  	{
c1359495c   Herbert Xu   crypto: picoxcell...
1350
1351
1352
1353
  		.ctrl_default = SPA_CTRL_CIPH_ALG_AES |
  				SPA_CTRL_CIPH_MODE_CBC |
  				SPA_CTRL_HASH_ALG_SHA |
  				SPA_CTRL_HASH_MODE_HMAC,
ce9213684   Jamie Iles   crypto: picoxcell...
1354
1355
1356
  		.key_offs = 0,
  		.iv_offs = AES_MAX_KEY_SIZE,
  		.alg = {
c1359495c   Herbert Xu   crypto: picoxcell...
1357
1358
1359
1360
1361
1362
  			.base = {
  				.cra_name = "authenc(hmac(sha1),cbc(aes))",
  				.cra_driver_name = "authenc-hmac-sha1-"
  						   "cbc-aes-picoxcell",
  				.cra_priority = SPACC_CRYPTO_ALG_PRIORITY,
  				.cra_flags = CRYPTO_ALG_ASYNC |
b8aa7dc5c   Mikulas Patocka   crypto: drivers -...
1363
  					     CRYPTO_ALG_ALLOCATES_MEMORY |
c1359495c   Herbert Xu   crypto: picoxcell...
1364
1365
1366
1367
1368
  					     CRYPTO_ALG_NEED_FALLBACK |
  					     CRYPTO_ALG_KERN_DRIVER_ONLY,
  				.cra_blocksize = AES_BLOCK_SIZE,
  				.cra_ctxsize = sizeof(struct spacc_aead_ctx),
  				.cra_module = THIS_MODULE,
ce9213684   Jamie Iles   crypto: picoxcell...
1369
  			},
c1359495c   Herbert Xu   crypto: picoxcell...
1370
1371
1372
1373
1374
1375
1376
1377
  			.setkey = spacc_aead_setkey,
  			.setauthsize = spacc_aead_setauthsize,
  			.encrypt = spacc_aead_encrypt,
  			.decrypt = spacc_aead_decrypt,
  			.ivsize = AES_BLOCK_SIZE,
  			.maxauthsize = SHA1_DIGEST_SIZE,
  			.init = spacc_aead_cra_init,
  			.exit = spacc_aead_cra_exit,
ce9213684   Jamie Iles   crypto: picoxcell...
1378
1379
1380
  		},
  	},
  	{
c1359495c   Herbert Xu   crypto: picoxcell...
1381
1382
  		.ctrl_default = SPA_CTRL_CIPH_ALG_AES |
  				SPA_CTRL_CIPH_MODE_CBC |
ce9213684   Jamie Iles   crypto: picoxcell...
1383
1384
1385
1386
1387
  				SPA_CTRL_HASH_ALG_SHA256 |
  				SPA_CTRL_HASH_MODE_HMAC,
  		.key_offs = 0,
  		.iv_offs = AES_MAX_KEY_SIZE,
  		.alg = {
c1359495c   Herbert Xu   crypto: picoxcell...
1388
1389
1390
1391
1392
1393
  			.base = {
  				.cra_name = "authenc(hmac(sha256),cbc(aes))",
  				.cra_driver_name = "authenc-hmac-sha256-"
  						   "cbc-aes-picoxcell",
  				.cra_priority = SPACC_CRYPTO_ALG_PRIORITY,
  				.cra_flags = CRYPTO_ALG_ASYNC |
b8aa7dc5c   Mikulas Patocka   crypto: drivers -...
1394
  					     CRYPTO_ALG_ALLOCATES_MEMORY |
c1359495c   Herbert Xu   crypto: picoxcell...
1395
1396
1397
1398
1399
  					     CRYPTO_ALG_NEED_FALLBACK |
  					     CRYPTO_ALG_KERN_DRIVER_ONLY,
  				.cra_blocksize = AES_BLOCK_SIZE,
  				.cra_ctxsize = sizeof(struct spacc_aead_ctx),
  				.cra_module = THIS_MODULE,
ce9213684   Jamie Iles   crypto: picoxcell...
1400
  			},
c1359495c   Herbert Xu   crypto: picoxcell...
1401
1402
1403
1404
1405
1406
1407
1408
  			.setkey = spacc_aead_setkey,
  			.setauthsize = spacc_aead_setauthsize,
  			.encrypt = spacc_aead_encrypt,
  			.decrypt = spacc_aead_decrypt,
  			.ivsize = AES_BLOCK_SIZE,
  			.maxauthsize = SHA256_DIGEST_SIZE,
  			.init = spacc_aead_cra_init,
  			.exit = spacc_aead_cra_exit,
ce9213684   Jamie Iles   crypto: picoxcell...
1409
1410
1411
1412
1413
  		},
  	},
  	{
  		.key_offs = 0,
  		.iv_offs = AES_MAX_KEY_SIZE,
c1359495c   Herbert Xu   crypto: picoxcell...
1414
1415
1416
1417
  		.ctrl_default = SPA_CTRL_CIPH_ALG_AES |
  				SPA_CTRL_CIPH_MODE_CBC |
  				SPA_CTRL_HASH_ALG_MD5 |
  				SPA_CTRL_HASH_MODE_HMAC,
ce9213684   Jamie Iles   crypto: picoxcell...
1418
  		.alg = {
c1359495c   Herbert Xu   crypto: picoxcell...
1419
1420
1421
1422
1423
1424
  			.base = {
  				.cra_name = "authenc(hmac(md5),cbc(aes))",
  				.cra_driver_name = "authenc-hmac-md5-"
  						   "cbc-aes-picoxcell",
  				.cra_priority = SPACC_CRYPTO_ALG_PRIORITY,
  				.cra_flags = CRYPTO_ALG_ASYNC |
b8aa7dc5c   Mikulas Patocka   crypto: drivers -...
1425
  					     CRYPTO_ALG_ALLOCATES_MEMORY |
c1359495c   Herbert Xu   crypto: picoxcell...
1426
1427
1428
1429
1430
  					     CRYPTO_ALG_NEED_FALLBACK |
  					     CRYPTO_ALG_KERN_DRIVER_ONLY,
  				.cra_blocksize = AES_BLOCK_SIZE,
  				.cra_ctxsize = sizeof(struct spacc_aead_ctx),
  				.cra_module = THIS_MODULE,
ce9213684   Jamie Iles   crypto: picoxcell...
1431
  			},
c1359495c   Herbert Xu   crypto: picoxcell...
1432
1433
1434
1435
1436
1437
1438
1439
  			.setkey = spacc_aead_setkey,
  			.setauthsize = spacc_aead_setauthsize,
  			.encrypt = spacc_aead_encrypt,
  			.decrypt = spacc_aead_decrypt,
  			.ivsize = AES_BLOCK_SIZE,
  			.maxauthsize = MD5_DIGEST_SIZE,
  			.init = spacc_aead_cra_init,
  			.exit = spacc_aead_cra_exit,
ce9213684   Jamie Iles   crypto: picoxcell...
1440
1441
1442
1443
1444
  		},
  	},
  	{
  		.key_offs = DES_BLOCK_SIZE,
  		.iv_offs = 0,
c1359495c   Herbert Xu   crypto: picoxcell...
1445
1446
1447
1448
  		.ctrl_default = SPA_CTRL_CIPH_ALG_DES |
  				SPA_CTRL_CIPH_MODE_CBC |
  				SPA_CTRL_HASH_ALG_SHA |
  				SPA_CTRL_HASH_MODE_HMAC,
ce9213684   Jamie Iles   crypto: picoxcell...
1449
  		.alg = {
c1359495c   Herbert Xu   crypto: picoxcell...
1450
1451
1452
1453
1454
1455
  			.base = {
  				.cra_name = "authenc(hmac(sha1),cbc(des3_ede))",
  				.cra_driver_name = "authenc-hmac-sha1-"
  						   "cbc-3des-picoxcell",
  				.cra_priority = SPACC_CRYPTO_ALG_PRIORITY,
  				.cra_flags = CRYPTO_ALG_ASYNC |
b8aa7dc5c   Mikulas Patocka   crypto: drivers -...
1456
  					     CRYPTO_ALG_ALLOCATES_MEMORY |
c1359495c   Herbert Xu   crypto: picoxcell...
1457
1458
1459
1460
1461
  					     CRYPTO_ALG_NEED_FALLBACK |
  					     CRYPTO_ALG_KERN_DRIVER_ONLY,
  				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
  				.cra_ctxsize = sizeof(struct spacc_aead_ctx),
  				.cra_module = THIS_MODULE,
ce9213684   Jamie Iles   crypto: picoxcell...
1462
  			},
c1359495c   Herbert Xu   crypto: picoxcell...
1463
1464
1465
1466
1467
1468
1469
1470
  			.setkey = spacc_aead_setkey,
  			.setauthsize = spacc_aead_setauthsize,
  			.encrypt = spacc_aead_encrypt,
  			.decrypt = spacc_aead_decrypt,
  			.ivsize = DES3_EDE_BLOCK_SIZE,
  			.maxauthsize = SHA1_DIGEST_SIZE,
  			.init = spacc_aead_cra_init,
  			.exit = spacc_aead_cra_exit,
ce9213684   Jamie Iles   crypto: picoxcell...
1471
1472
1473
1474
1475
  		},
  	},
  	{
  		.key_offs = DES_BLOCK_SIZE,
  		.iv_offs = 0,
c1359495c   Herbert Xu   crypto: picoxcell...
1476
1477
  		.ctrl_default = SPA_CTRL_CIPH_ALG_AES |
  				SPA_CTRL_CIPH_MODE_CBC |
ce9213684   Jamie Iles   crypto: picoxcell...
1478
1479
1480
  				SPA_CTRL_HASH_ALG_SHA256 |
  				SPA_CTRL_HASH_MODE_HMAC,
  		.alg = {
c1359495c   Herbert Xu   crypto: picoxcell...
1481
1482
1483
1484
1485
1486
1487
  			.base = {
  				.cra_name = "authenc(hmac(sha256),"
  					    "cbc(des3_ede))",
  				.cra_driver_name = "authenc-hmac-sha256-"
  						   "cbc-3des-picoxcell",
  				.cra_priority = SPACC_CRYPTO_ALG_PRIORITY,
  				.cra_flags = CRYPTO_ALG_ASYNC |
b8aa7dc5c   Mikulas Patocka   crypto: drivers -...
1488
  					     CRYPTO_ALG_ALLOCATES_MEMORY |
c1359495c   Herbert Xu   crypto: picoxcell...
1489
1490
1491
1492
1493
  					     CRYPTO_ALG_NEED_FALLBACK |
  					     CRYPTO_ALG_KERN_DRIVER_ONLY,
  				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
  				.cra_ctxsize = sizeof(struct spacc_aead_ctx),
  				.cra_module = THIS_MODULE,
ce9213684   Jamie Iles   crypto: picoxcell...
1494
  			},
c1359495c   Herbert Xu   crypto: picoxcell...
1495
1496
1497
1498
1499
1500
1501
1502
  			.setkey = spacc_aead_setkey,
  			.setauthsize = spacc_aead_setauthsize,
  			.encrypt = spacc_aead_encrypt,
  			.decrypt = spacc_aead_decrypt,
  			.ivsize = DES3_EDE_BLOCK_SIZE,
  			.maxauthsize = SHA256_DIGEST_SIZE,
  			.init = spacc_aead_cra_init,
  			.exit = spacc_aead_cra_exit,
ce9213684   Jamie Iles   crypto: picoxcell...
1503
1504
1505
1506
1507
  		},
  	},
  	{
  		.key_offs = DES_BLOCK_SIZE,
  		.iv_offs = 0,
c1359495c   Herbert Xu   crypto: picoxcell...
1508
1509
1510
1511
  		.ctrl_default = SPA_CTRL_CIPH_ALG_DES |
  				SPA_CTRL_CIPH_MODE_CBC |
  				SPA_CTRL_HASH_ALG_MD5 |
  				SPA_CTRL_HASH_MODE_HMAC,
ce9213684   Jamie Iles   crypto: picoxcell...
1512
  		.alg = {
c1359495c   Herbert Xu   crypto: picoxcell...
1513
1514
1515
1516
1517
1518
  			.base = {
  				.cra_name = "authenc(hmac(md5),cbc(des3_ede))",
  				.cra_driver_name = "authenc-hmac-md5-"
  						   "cbc-3des-picoxcell",
  				.cra_priority = SPACC_CRYPTO_ALG_PRIORITY,
  				.cra_flags = CRYPTO_ALG_ASYNC |
b8aa7dc5c   Mikulas Patocka   crypto: drivers -...
1519
  					     CRYPTO_ALG_ALLOCATES_MEMORY |
c1359495c   Herbert Xu   crypto: picoxcell...
1520
1521
1522
1523
1524
  					     CRYPTO_ALG_NEED_FALLBACK |
  					     CRYPTO_ALG_KERN_DRIVER_ONLY,
  				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
  				.cra_ctxsize = sizeof(struct spacc_aead_ctx),
  				.cra_module = THIS_MODULE,
ce9213684   Jamie Iles   crypto: picoxcell...
1525
  			},
c1359495c   Herbert Xu   crypto: picoxcell...
1526
1527
1528
1529
1530
1531
1532
1533
  			.setkey = spacc_aead_setkey,
  			.setauthsize = spacc_aead_setauthsize,
  			.encrypt = spacc_aead_encrypt,
  			.decrypt = spacc_aead_decrypt,
  			.ivsize = DES3_EDE_BLOCK_SIZE,
  			.maxauthsize = MD5_DIGEST_SIZE,
  			.init = spacc_aead_cra_init,
  			.exit = spacc_aead_cra_exit,
ce9213684   Jamie Iles   crypto: picoxcell...
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
  		},
  	},
  };
  
  static struct spacc_alg l2_engine_algs[] = {
  	{
  		.key_offs = 0,
  		.iv_offs = SPACC_CRYPTO_KASUMI_F8_KEY_LEN,
  		.ctrl_default = SPA_CTRL_CIPH_ALG_KASUMI |
  				SPA_CTRL_CIPH_MODE_F8,
  		.alg = {
b3cde6bab   Ard Biesheuvel   crypto: picoxcell...
1545
1546
1547
1548
  			.base.cra_name		= "f8(kasumi)",
  			.base.cra_driver_name	= "f8-kasumi-picoxcell",
  			.base.cra_priority	= SPACC_CRYPTO_ALG_PRIORITY,
  			.base.cra_flags		= CRYPTO_ALG_ASYNC |
b8aa7dc5c   Mikulas Patocka   crypto: drivers -...
1549
  						  CRYPTO_ALG_ALLOCATES_MEMORY |
b3cde6bab   Ard Biesheuvel   crypto: picoxcell...
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
  						  CRYPTO_ALG_KERN_DRIVER_ONLY,
  			.base.cra_blocksize	= 8,
  			.base.cra_ctxsize	= sizeof(struct spacc_ablk_ctx),
  			.base.cra_module	= THIS_MODULE,
  
  			.setkey			= spacc_kasumi_f8_setkey,
  			.encrypt		= spacc_ablk_encrypt,
  			.decrypt		= spacc_ablk_decrypt,
  			.min_keysize		= 16,
  			.max_keysize		= 16,
  			.ivsize			= 8,
  			.init			= spacc_ablk_init_tfm,
  			.exit			= spacc_ablk_exit_tfm,
ce9213684   Jamie Iles   crypto: picoxcell...
1563
1564
1565
  		},
  	},
  };
30343ef1d   Jamie Iles   crypto: picoxcell...
1566
1567
1568
1569
1570
1571
  #ifdef CONFIG_OF
  static const struct of_device_id spacc_of_id_table[] = {
  	{ .compatible = "picochip,spacc-ipsec" },
  	{ .compatible = "picochip,spacc-l2" },
  	{}
  };
c3abc0f3b   Luis de Bethencourt   crypto: picoxcell...
1572
  MODULE_DEVICE_TABLE(of, spacc_of_id_table);
30343ef1d   Jamie Iles   crypto: picoxcell...
1573
  #endif /* CONFIG_OF */
7f8c36fe9   Chuhong Yuan   crypto: picoxcell...
1574
1575
1576
1577
  static void spacc_tasklet_kill(void *data)
  {
  	tasklet_kill(data);
  }
49cfe4db2   Greg Kroah-Hartman   Drivers: crypto: ...
1578
  static int spacc_probe(struct platform_device *pdev)
ce9213684   Jamie Iles   crypto: picoxcell...
1579
  {
2d55807b7   Alexey Khoroshilov   crypto: picoxcell...
1580
  	int i, err, ret;
9a8e0a513   YueHaibing   crypto: picoxcell...
1581
  	struct resource *irq;
012ef7033   Javier Martinez Canillas   crypto: picoxcell...
1582
  	struct device_node *np = pdev->dev.of_node;
ce9213684   Jamie Iles   crypto: picoxcell...
1583
1584
1585
1586
  	struct spacc_engine *engine = devm_kzalloc(&pdev->dev, sizeof(*engine),
  						   GFP_KERNEL);
  	if (!engine)
  		return -ENOMEM;
012ef7033   Javier Martinez Canillas   crypto: picoxcell...
1587
  	if (of_device_is_compatible(np, "picochip,spacc-ipsec")) {
c3f4200f5   Jamie Iles   crypto: picoxcell...
1588
1589
1590
1591
1592
1593
  		engine->max_ctxs	= SPACC_CRYPTO_IPSEC_MAX_CTXS;
  		engine->cipher_pg_sz	= SPACC_CRYPTO_IPSEC_CIPHER_PG_SZ;
  		engine->hash_pg_sz	= SPACC_CRYPTO_IPSEC_HASH_PG_SZ;
  		engine->fifo_sz		= SPACC_CRYPTO_IPSEC_FIFO_SZ;
  		engine->algs		= ipsec_engine_algs;
  		engine->num_algs	= ARRAY_SIZE(ipsec_engine_algs);
c1359495c   Herbert Xu   crypto: picoxcell...
1594
1595
  		engine->aeads		= ipsec_engine_aeads;
  		engine->num_aeads	= ARRAY_SIZE(ipsec_engine_aeads);
012ef7033   Javier Martinez Canillas   crypto: picoxcell...
1596
  	} else if (of_device_is_compatible(np, "picochip,spacc-l2")) {
c3f4200f5   Jamie Iles   crypto: picoxcell...
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
  		engine->max_ctxs	= SPACC_CRYPTO_L2_MAX_CTXS;
  		engine->cipher_pg_sz	= SPACC_CRYPTO_L2_CIPHER_PG_SZ;
  		engine->hash_pg_sz	= SPACC_CRYPTO_L2_HASH_PG_SZ;
  		engine->fifo_sz		= SPACC_CRYPTO_L2_FIFO_SZ;
  		engine->algs		= l2_engine_algs;
  		engine->num_algs	= ARRAY_SIZE(l2_engine_algs);
  	} else {
  		return -EINVAL;
  	}
  
  	engine->name = dev_name(&pdev->dev);
ce9213684   Jamie Iles   crypto: picoxcell...
1608

9a8e0a513   YueHaibing   crypto: picoxcell...
1609
  	engine->regs = devm_platform_ioremap_resource(pdev, 0);
32af1e180   Jingoo Han   crypto: picoxcell...
1610
1611
  	if (IS_ERR(engine->regs))
  		return PTR_ERR(engine->regs);
ce9213684   Jamie Iles   crypto: picoxcell...
1612
  	irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
32af1e180   Jingoo Han   crypto: picoxcell...
1613
  	if (!irq) {
ce9213684   Jamie Iles   crypto: picoxcell...
1614
1615
1616
1617
  		dev_err(&pdev->dev, "no memory/irq resource for engine
  ");
  		return -ENXIO;
  	}
7f8c36fe9   Chuhong Yuan   crypto: picoxcell...
1618
1619
1620
1621
1622
1623
1624
  	tasklet_init(&engine->complete, spacc_spacc_complete,
  		     (unsigned long)engine);
  
  	ret = devm_add_action(&pdev->dev, spacc_tasklet_kill,
  			      &engine->complete);
  	if (ret)
  		return ret;
ce9213684   Jamie Iles   crypto: picoxcell...
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
  	if (devm_request_irq(&pdev->dev, irq->start, spacc_spacc_irq, 0,
  			     engine->name, engine)) {
  		dev_err(engine->dev, "failed to request IRQ
  ");
  		return -EBUSY;
  	}
  
  	engine->dev		= &pdev->dev;
  	engine->cipher_ctx_base = engine->regs + SPA_CIPH_KEY_BASE_REG_OFFSET;
  	engine->hash_key_base	= engine->regs + SPA_HASH_KEY_BASE_REG_OFFSET;
  
  	engine->req_pool = dmam_pool_create(engine->name, engine->dev,
  		MAX_DDT_LEN * sizeof(struct spacc_ddt), 8, SZ_64K);
  	if (!engine->req_pool)
  		return -ENOMEM;
  
  	spin_lock_init(&engine->hw_lock);
4efae8c93   Jamie Iles   crypto: picoxcell...
1642
  	engine->clk = clk_get(&pdev->dev, "ref");
ce9213684   Jamie Iles   crypto: picoxcell...
1643
1644
1645
  	if (IS_ERR(engine->clk)) {
  		dev_info(&pdev->dev, "clk unavailable
  ");
ce9213684   Jamie Iles   crypto: picoxcell...
1646
1647
  		return PTR_ERR(engine->clk);
  	}
1bd2cd6bc   Michael van der Westhuizen   crypto: picoxcell...
1648
1649
1650
  	if (clk_prepare_enable(engine->clk)) {
  		dev_info(&pdev->dev, "unable to prepare/enable clk
  ");
2d55807b7   Alexey Khoroshilov   crypto: picoxcell...
1651
1652
  		ret = -EIO;
  		goto err_clk_put;
ce9213684   Jamie Iles   crypto: picoxcell...
1653
  	}
ce9213684   Jamie Iles   crypto: picoxcell...
1654
1655
1656
1657
1658
1659
  	/*
  	 * Use an IRQ threshold of 50% as a default. This seems to be a
  	 * reasonable trade off of latency against throughput but can be
  	 * changed at runtime.
  	 */
  	engine->stat_irq_thresh = (engine->fifo_sz / 2);
64f4a62e3   Madhuparna Bhowmik   crypto: picoxcell...
1660
1661
1662
  	ret = device_create_file(&pdev->dev, &dev_attr_stat_irq_thresh);
  	if (ret)
  		goto err_clk_disable;
ce9213684   Jamie Iles   crypto: picoxcell...
1663
1664
1665
1666
1667
1668
1669
1670
1671
  	/*
  	 * Configure the interrupts. We only use the STAT_CNT interrupt as we
  	 * only submit a new packet for processing when we complete another in
  	 * the queue. This minimizes time spent in the interrupt handler.
  	 */
  	writel(engine->stat_irq_thresh << SPA_IRQ_CTRL_STAT_CNT_OFFSET,
  	       engine->regs + SPA_IRQ_CTRL_REG_OFFSET);
  	writel(SPA_IRQ_EN_STAT_EN | SPA_IRQ_EN_GLBL_EN,
  	       engine->regs + SPA_IRQ_EN_REG_OFFSET);
f34d8d506   Kees Cook   crypto: Convert t...
1672
  	timer_setup(&engine->packet_timeout, spacc_packet_timeout, 0);
ce9213684   Jamie Iles   crypto: picoxcell...
1673
1674
1675
1676
1677
  
  	INIT_LIST_HEAD(&engine->pending);
  	INIT_LIST_HEAD(&engine->completed);
  	INIT_LIST_HEAD(&engine->in_progress);
  	engine->in_flight = 0;
ce9213684   Jamie Iles   crypto: picoxcell...
1678
1679
  
  	platform_set_drvdata(pdev, engine);
2d55807b7   Alexey Khoroshilov   crypto: picoxcell...
1680
  	ret = -EINVAL;
ce9213684   Jamie Iles   crypto: picoxcell...
1681
1682
1683
  	INIT_LIST_HEAD(&engine->registered_algs);
  	for (i = 0; i < engine->num_algs; ++i) {
  		engine->algs[i].engine = engine;
b3cde6bab   Ard Biesheuvel   crypto: picoxcell...
1684
  		err = crypto_register_skcipher(&engine->algs[i].alg);
ce9213684   Jamie Iles   crypto: picoxcell...
1685
1686
1687
1688
1689
1690
1691
1692
  		if (!err) {
  			list_add_tail(&engine->algs[i].entry,
  				      &engine->registered_algs);
  			ret = 0;
  		}
  		if (err)
  			dev_err(engine->dev, "failed to register alg \"%s\"
  ",
b3cde6bab   Ard Biesheuvel   crypto: picoxcell...
1693
  				engine->algs[i].alg.base.cra_name);
ce9213684   Jamie Iles   crypto: picoxcell...
1694
1695
1696
  		else
  			dev_dbg(engine->dev, "registered alg \"%s\"
  ",
b3cde6bab   Ard Biesheuvel   crypto: picoxcell...
1697
  				engine->algs[i].alg.base.cra_name);
ce9213684   Jamie Iles   crypto: picoxcell...
1698
  	}
c1359495c   Herbert Xu   crypto: picoxcell...
1699
1700
1701
  	INIT_LIST_HEAD(&engine->registered_aeads);
  	for (i = 0; i < engine->num_aeads; ++i) {
  		engine->aeads[i].engine = engine;
c1359495c   Herbert Xu   crypto: picoxcell...
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
  		err = crypto_register_aead(&engine->aeads[i].alg);
  		if (!err) {
  			list_add_tail(&engine->aeads[i].entry,
  				      &engine->registered_aeads);
  			ret = 0;
  		}
  		if (err)
  			dev_err(engine->dev, "failed to register alg \"%s\"
  ",
  				engine->aeads[i].alg.base.cra_name);
  		else
  			dev_dbg(engine->dev, "registered alg \"%s\"
  ",
  				engine->aeads[i].alg.base.cra_name);
  	}
2d55807b7   Alexey Khoroshilov   crypto: picoxcell...
1717
1718
1719
1720
1721
1722
1723
1724
1725
  	if (!ret)
  		return 0;
  
  	del_timer_sync(&engine->packet_timeout);
  	device_remove_file(&pdev->dev, &dev_attr_stat_irq_thresh);
  err_clk_disable:
  	clk_disable_unprepare(engine->clk);
  err_clk_put:
  	clk_put(engine->clk);
ce9213684   Jamie Iles   crypto: picoxcell...
1726
1727
  	return ret;
  }
49cfe4db2   Greg Kroah-Hartman   Drivers: crypto: ...
1728
  static int spacc_remove(struct platform_device *pdev)
ce9213684   Jamie Iles   crypto: picoxcell...
1729
  {
c1359495c   Herbert Xu   crypto: picoxcell...
1730
  	struct spacc_aead *aead, *an;
ce9213684   Jamie Iles   crypto: picoxcell...
1731
1732
1733
1734
1735
  	struct spacc_alg *alg, *next;
  	struct spacc_engine *engine = platform_get_drvdata(pdev);
  
  	del_timer_sync(&engine->packet_timeout);
  	device_remove_file(&pdev->dev, &dev_attr_stat_irq_thresh);
c1359495c   Herbert Xu   crypto: picoxcell...
1736
1737
1738
1739
  	list_for_each_entry_safe(aead, an, &engine->registered_aeads, entry) {
  		list_del(&aead->entry);
  		crypto_unregister_aead(&aead->alg);
  	}
ce9213684   Jamie Iles   crypto: picoxcell...
1740
1741
  	list_for_each_entry_safe(alg, next, &engine->registered_algs, entry) {
  		list_del(&alg->entry);
b3cde6bab   Ard Biesheuvel   crypto: picoxcell...
1742
  		crypto_unregister_skcipher(&alg->alg);
ce9213684   Jamie Iles   crypto: picoxcell...
1743
  	}
1bd2cd6bc   Michael van der Westhuizen   crypto: picoxcell...
1744
  	clk_disable_unprepare(engine->clk);
ce9213684   Jamie Iles   crypto: picoxcell...
1745
1746
1747
1748
  	clk_put(engine->clk);
  
  	return 0;
  }
c3f4200f5   Jamie Iles   crypto: picoxcell...
1749
1750
  static struct platform_driver spacc_driver = {
  	.probe		= spacc_probe,
49cfe4db2   Greg Kroah-Hartman   Drivers: crypto: ...
1751
  	.remove		= spacc_remove,
ce9213684   Jamie Iles   crypto: picoxcell...
1752
  	.driver		= {
c3f4200f5   Jamie Iles   crypto: picoxcell...
1753
  		.name	= "picochip,spacc",
ce9213684   Jamie Iles   crypto: picoxcell...
1754
1755
1756
  #ifdef CONFIG_PM
  		.pm	= &spacc_pm_ops,
  #endif /* CONFIG_PM */
5cec26e98   Sachin Kamat   crypto: picoxcell...
1757
  		.of_match_table	= of_match_ptr(spacc_of_id_table),
ce9213684   Jamie Iles   crypto: picoxcell...
1758
1759
  	},
  };
741e8c2d8   Axel Lin   crypto: convert d...
1760
  module_platform_driver(spacc_driver);
ce9213684   Jamie Iles   crypto: picoxcell...
1761
1762
1763
  
  MODULE_LICENSE("GPL");
  MODULE_AUTHOR("Jamie Iles");