xref: /linux/drivers/crypto/talitos.c (revision 0ea5c948cb64bab5bc7a5516774eb8536f05aa0d)
11a59d1b8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
29c4a7965SKim Phillips /*
39c4a7965SKim Phillips  * talitos - Freescale Integrated Security Engine (SEC) device driver
49c4a7965SKim Phillips  *
55228f0f7SKim Phillips  * Copyright (c) 2008-2011 Freescale Semiconductor, Inc.
69c4a7965SKim Phillips  *
79c4a7965SKim Phillips  * Scatterlist Crypto API glue code copied from files with the following:
89c4a7965SKim Phillips  * Copyright (c) 2006-2007 Herbert Xu <herbert@gondor.apana.org.au>
99c4a7965SKim Phillips  *
109c4a7965SKim Phillips  * Crypto algorithm registration code copied from hifn driver:
119c4a7965SKim Phillips  * 2007+ Copyright (c) Evgeniy Polyakov <johnpol@2ka.mipt.ru>
129c4a7965SKim Phillips  * All rights reserved.
139c4a7965SKim Phillips  */
149c4a7965SKim Phillips 
159c4a7965SKim Phillips #include <linux/kernel.h>
169c4a7965SKim Phillips #include <linux/module.h>
179c4a7965SKim Phillips #include <linux/mod_devicetable.h>
189c4a7965SKim Phillips #include <linux/device.h>
199c4a7965SKim Phillips #include <linux/interrupt.h>
209c4a7965SKim Phillips #include <linux/crypto.h>
219c4a7965SKim Phillips #include <linux/hw_random.h>
22b0cc7491SRob Herring #include <linux/of.h>
235af50730SRob Herring #include <linux/of_irq.h>
24b0cc7491SRob Herring #include <linux/platform_device.h>
259c4a7965SKim Phillips #include <linux/dma-mapping.h>
269c4a7965SKim Phillips #include <linux/io.h>
279c4a7965SKim Phillips #include <linux/spinlock.h>
289c4a7965SKim Phillips #include <linux/rtnetlink.h>
295a0e3ad6STejun Heo #include <linux/slab.h>
309c4a7965SKim Phillips 
319c4a7965SKim Phillips #include <crypto/algapi.h>
329c4a7965SKim Phillips #include <crypto/aes.h>
339d574ae8SArd Biesheuvel #include <crypto/internal/des.h>
34a24d22b2SEric Biggers #include <crypto/sha1.h>
35a24d22b2SEric Biggers #include <crypto/sha2.h>
36497f2e6bSLee Nipper #include <crypto/md5.h>
37e98014abSHerbert Xu #include <crypto/internal/aead.h>
389c4a7965SKim Phillips #include <crypto/authenc.h>
39373960d7SArd Biesheuvel #include <crypto/internal/skcipher.h>
40acbf7c62SLee Nipper #include <crypto/hash.h>
41acbf7c62SLee Nipper #include <crypto/internal/hash.h>
424de9d0b5SLee Nipper #include <crypto/scatterwalk.h>
439c4a7965SKim Phillips 
449c4a7965SKim Phillips #include "talitos.h"
459c4a7965SKim Phillips 
to_talitos_ptr(struct talitos_ptr * ptr,dma_addr_t dma_addr,unsigned int len,bool is_sec1)46922f9dc8SLEROY Christophe static void to_talitos_ptr(struct talitos_ptr *ptr, dma_addr_t dma_addr,
47da9de146SLEROY Christophe 			   unsigned int len, bool is_sec1)
4881eb024cSKim Phillips {
49edc6bd69SLEROY Christophe 	ptr->ptr = cpu_to_be32(lower_32_bits(dma_addr));
50da9de146SLEROY Christophe 	if (is_sec1) {
51da9de146SLEROY Christophe 		ptr->len1 = cpu_to_be16(len);
52da9de146SLEROY Christophe 	} else {
53da9de146SLEROY Christophe 		ptr->len = cpu_to_be16(len);
54edc6bd69SLEROY Christophe 		ptr->eptr = upper_32_bits(dma_addr);
5581eb024cSKim Phillips 	}
56da9de146SLEROY Christophe }
5781eb024cSKim Phillips 
copy_talitos_ptr(struct talitos_ptr * dst_ptr,struct talitos_ptr * src_ptr,bool is_sec1)58340ff60aSHoria Geant? static void copy_talitos_ptr(struct talitos_ptr *dst_ptr,
59340ff60aSHoria Geant? 			     struct talitos_ptr *src_ptr, bool is_sec1)
60340ff60aSHoria Geant? {
61340ff60aSHoria Geant? 	dst_ptr->ptr = src_ptr->ptr;
62922f9dc8SLEROY Christophe 	if (is_sec1) {
63da9de146SLEROY Christophe 		dst_ptr->len1 = src_ptr->len1;
64922f9dc8SLEROY Christophe 	} else {
65da9de146SLEROY Christophe 		dst_ptr->len = src_ptr->len;
66da9de146SLEROY Christophe 		dst_ptr->eptr = src_ptr->eptr;
67538caf83SLEROY Christophe 	}
68922f9dc8SLEROY Christophe }
69538caf83SLEROY Christophe 
from_talitos_ptr_len(struct talitos_ptr * ptr,bool is_sec1)70922f9dc8SLEROY Christophe static unsigned short from_talitos_ptr_len(struct talitos_ptr *ptr,
71922f9dc8SLEROY Christophe 					   bool is_sec1)
72538caf83SLEROY Christophe {
73922f9dc8SLEROY Christophe 	if (is_sec1)
74922f9dc8SLEROY Christophe 		return be16_to_cpu(ptr->len1);
75922f9dc8SLEROY Christophe 	else
76538caf83SLEROY Christophe 		return be16_to_cpu(ptr->len);
77538caf83SLEROY Christophe }
78538caf83SLEROY Christophe 
to_talitos_ptr_ext_set(struct talitos_ptr * ptr,u8 val,bool is_sec1)79b096b544SLEROY Christophe static void to_talitos_ptr_ext_set(struct talitos_ptr *ptr, u8 val,
80b096b544SLEROY Christophe 				   bool is_sec1)
81185eb79fSLEROY Christophe {
82922f9dc8SLEROY Christophe 	if (!is_sec1)
83b096b544SLEROY Christophe 		ptr->j_extent = val;
84b096b544SLEROY Christophe }
85b096b544SLEROY Christophe 
to_talitos_ptr_ext_or(struct talitos_ptr * ptr,u8 val,bool is_sec1)86b096b544SLEROY Christophe static void to_talitos_ptr_ext_or(struct talitos_ptr *ptr, u8 val, bool is_sec1)
87b096b544SLEROY Christophe {
88b096b544SLEROY Christophe 	if (!is_sec1)
89b096b544SLEROY Christophe 		ptr->j_extent |= val;
90185eb79fSLEROY Christophe }
91185eb79fSLEROY Christophe 
929c4a7965SKim Phillips /*
939c4a7965SKim Phillips  * map virtual single (contiguous) pointer to h/w descriptor pointer
949c4a7965SKim Phillips  */
__map_single_talitos_ptr(struct device * dev,struct talitos_ptr * ptr,unsigned int len,void * data,enum dma_data_direction dir,unsigned long attrs)956a4967c3SLEROY Christophe static void __map_single_talitos_ptr(struct device *dev,
966a4967c3SLEROY Christophe 				     struct talitos_ptr *ptr,
976a4967c3SLEROY Christophe 				     unsigned int len, void *data,
986a4967c3SLEROY Christophe 				     enum dma_data_direction dir,
996a4967c3SLEROY Christophe 				     unsigned long attrs)
1006a4967c3SLEROY Christophe {
1016a4967c3SLEROY Christophe 	dma_addr_t dma_addr = dma_map_single_attrs(dev, data, len, dir, attrs);
1026a4967c3SLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
1036a4967c3SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
1046a4967c3SLEROY Christophe 
1056a4967c3SLEROY Christophe 	to_talitos_ptr(ptr, dma_addr, len, is_sec1);
1066a4967c3SLEROY Christophe }
1076a4967c3SLEROY Christophe 
map_single_talitos_ptr(struct device * dev,struct talitos_ptr * ptr,unsigned int len,void * data,enum dma_data_direction dir)1089c4a7965SKim Phillips static void map_single_talitos_ptr(struct device *dev,
109edc6bd69SLEROY Christophe 				   struct talitos_ptr *ptr,
11042e8b0d7SHoria Geant? 				   unsigned int len, void *data,
1119c4a7965SKim Phillips 				   enum dma_data_direction dir)
1129c4a7965SKim Phillips {
1136a4967c3SLEROY Christophe 	__map_single_talitos_ptr(dev, ptr, len, data, dir, 0);
1146a4967c3SLEROY Christophe }
11581eb024cSKim Phillips 
map_single_talitos_ptr_nosync(struct device * dev,struct talitos_ptr * ptr,unsigned int len,void * data,enum dma_data_direction dir)1166a4967c3SLEROY Christophe static void map_single_talitos_ptr_nosync(struct device *dev,
1176a4967c3SLEROY Christophe 					  struct talitos_ptr *ptr,
1186a4967c3SLEROY Christophe 					  unsigned int len, void *data,
1196a4967c3SLEROY Christophe 					  enum dma_data_direction dir)
1206a4967c3SLEROY Christophe {
1216a4967c3SLEROY Christophe 	__map_single_talitos_ptr(dev, ptr, len, data, dir,
1226a4967c3SLEROY Christophe 				 DMA_ATTR_SKIP_CPU_SYNC);
1239c4a7965SKim Phillips }
1249c4a7965SKim Phillips 
1259c4a7965SKim Phillips /*
1269c4a7965SKim Phillips  * unmap bus single (contiguous) h/w descriptor pointer
1279c4a7965SKim Phillips  */
unmap_single_talitos_ptr(struct device * dev,struct talitos_ptr * ptr,enum dma_data_direction dir)1289c4a7965SKim Phillips static void unmap_single_talitos_ptr(struct device *dev,
129edc6bd69SLEROY Christophe 				     struct talitos_ptr *ptr,
1309c4a7965SKim Phillips 				     enum dma_data_direction dir)
1319c4a7965SKim Phillips {
132922f9dc8SLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
133922f9dc8SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
134922f9dc8SLEROY Christophe 
135edc6bd69SLEROY Christophe 	dma_unmap_single(dev, be32_to_cpu(ptr->ptr),
136922f9dc8SLEROY Christophe 			 from_talitos_ptr_len(ptr, is_sec1), dir);
1379c4a7965SKim Phillips }
1389c4a7965SKim Phillips 
reset_channel(struct device * dev,int ch)1399c4a7965SKim Phillips static int reset_channel(struct device *dev, int ch)
1409c4a7965SKim Phillips {
1419c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
1429c4a7965SKim Phillips 	unsigned int timeout = TALITOS_TIMEOUT;
143dd3c0987SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
1449c4a7965SKim Phillips 
145dd3c0987SLEROY Christophe 	if (is_sec1) {
146dd3c0987SLEROY Christophe 		setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO,
147dd3c0987SLEROY Christophe 			  TALITOS1_CCCR_LO_RESET);
1489c4a7965SKim Phillips 
149dd3c0987SLEROY Christophe 		while ((in_be32(priv->chan[ch].reg + TALITOS_CCCR_LO) &
150dd3c0987SLEROY Christophe 			TALITOS1_CCCR_LO_RESET) && --timeout)
1519c4a7965SKim Phillips 			cpu_relax();
152dd3c0987SLEROY Christophe 	} else {
153dd3c0987SLEROY Christophe 		setbits32(priv->chan[ch].reg + TALITOS_CCCR,
154dd3c0987SLEROY Christophe 			  TALITOS2_CCCR_RESET);
155dd3c0987SLEROY Christophe 
156dd3c0987SLEROY Christophe 		while ((in_be32(priv->chan[ch].reg + TALITOS_CCCR) &
157dd3c0987SLEROY Christophe 			TALITOS2_CCCR_RESET) && --timeout)
158dd3c0987SLEROY Christophe 			cpu_relax();
159dd3c0987SLEROY Christophe 	}
1609c4a7965SKim Phillips 
1619c4a7965SKim Phillips 	if (timeout == 0) {
1629c4a7965SKim Phillips 		dev_err(dev, "failed to reset channel %d\n", ch);
1639c4a7965SKim Phillips 		return -EIO;
1649c4a7965SKim Phillips 	}
1659c4a7965SKim Phillips 
16681eb024cSKim Phillips 	/* set 36-bit addressing, done writeback enable and done IRQ enable */
167ad42d5fcSKim Phillips 	setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO, TALITOS_CCCR_LO_EAE |
16881eb024cSKim Phillips 		  TALITOS_CCCR_LO_CDWE | TALITOS_CCCR_LO_CDIE);
16937b5e889SLEROY Christophe 	/* enable chaining descriptors */
17037b5e889SLEROY Christophe 	if (is_sec1)
17137b5e889SLEROY Christophe 		setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO,
17237b5e889SLEROY Christophe 			  TALITOS_CCCR_LO_NE);
1739c4a7965SKim Phillips 
174fe5720e2SKim Phillips 	/* and ICCR writeback, if available */
175fe5720e2SKim Phillips 	if (priv->features & TALITOS_FTR_HW_AUTH_CHECK)
176ad42d5fcSKim Phillips 		setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO,
177fe5720e2SKim Phillips 		          TALITOS_CCCR_LO_IWSE);
178fe5720e2SKim Phillips 
1799c4a7965SKim Phillips 	return 0;
1809c4a7965SKim Phillips }
1819c4a7965SKim Phillips 
reset_device(struct device * dev)1829c4a7965SKim Phillips static int reset_device(struct device *dev)
1839c4a7965SKim Phillips {
1849c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
1859c4a7965SKim Phillips 	unsigned int timeout = TALITOS_TIMEOUT;
186dd3c0987SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
187dd3c0987SLEROY Christophe 	u32 mcr = is_sec1 ? TALITOS1_MCR_SWR : TALITOS2_MCR_SWR;
1889c4a7965SKim Phillips 
189c3e337f8SKim Phillips 	setbits32(priv->reg + TALITOS_MCR, mcr);
1909c4a7965SKim Phillips 
191dd3c0987SLEROY Christophe 	while ((in_be32(priv->reg + TALITOS_MCR) & mcr)
1929c4a7965SKim Phillips 	       && --timeout)
1939c4a7965SKim Phillips 		cpu_relax();
1949c4a7965SKim Phillips 
1952cdba3cfSKim Phillips 	if (priv->irq[1]) {
196c3e337f8SKim Phillips 		mcr = TALITOS_MCR_RCA1 | TALITOS_MCR_RCA3;
197c3e337f8SKim Phillips 		setbits32(priv->reg + TALITOS_MCR, mcr);
198c3e337f8SKim Phillips 	}
199c3e337f8SKim Phillips 
2009c4a7965SKim Phillips 	if (timeout == 0) {
2019c4a7965SKim Phillips 		dev_err(dev, "failed to reset device\n");
2029c4a7965SKim Phillips 		return -EIO;
2039c4a7965SKim Phillips 	}
2049c4a7965SKim Phillips 
2059c4a7965SKim Phillips 	return 0;
2069c4a7965SKim Phillips }
2079c4a7965SKim Phillips 
2089c4a7965SKim Phillips /*
2099c4a7965SKim Phillips  * Reset and initialize the device
2109c4a7965SKim Phillips  */
init_device(struct device * dev)2119c4a7965SKim Phillips static int init_device(struct device *dev)
2129c4a7965SKim Phillips {
2139c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
2149c4a7965SKim Phillips 	int ch, err;
215dd3c0987SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
2169c4a7965SKim Phillips 
2179c4a7965SKim Phillips 	/*
2189c4a7965SKim Phillips 	 * Master reset
2199c4a7965SKim Phillips 	 * errata documentation: warning: certain SEC interrupts
2209c4a7965SKim Phillips 	 * are not fully cleared by writing the MCR:SWR bit,
2219c4a7965SKim Phillips 	 * set bit twice to completely reset
2229c4a7965SKim Phillips 	 */
2239c4a7965SKim Phillips 	err = reset_device(dev);
2249c4a7965SKim Phillips 	if (err)
2259c4a7965SKim Phillips 		return err;
2269c4a7965SKim Phillips 
2279c4a7965SKim Phillips 	err = reset_device(dev);
2289c4a7965SKim Phillips 	if (err)
2299c4a7965SKim Phillips 		return err;
2309c4a7965SKim Phillips 
2319c4a7965SKim Phillips 	/* reset channels */
2329c4a7965SKim Phillips 	for (ch = 0; ch < priv->num_channels; ch++) {
2339c4a7965SKim Phillips 		err = reset_channel(dev, ch);
2349c4a7965SKim Phillips 		if (err)
2359c4a7965SKim Phillips 			return err;
2369c4a7965SKim Phillips 	}
2379c4a7965SKim Phillips 
2389c4a7965SKim Phillips 	/* enable channel done and error interrupts */
239dd3c0987SLEROY Christophe 	if (is_sec1) {
240dd3c0987SLEROY Christophe 		clrbits32(priv->reg + TALITOS_IMR, TALITOS1_IMR_INIT);
241dd3c0987SLEROY Christophe 		clrbits32(priv->reg + TALITOS_IMR_LO, TALITOS1_IMR_LO_INIT);
242dd3c0987SLEROY Christophe 		/* disable parity error check in DEU (erroneous? test vect.) */
243dd3c0987SLEROY Christophe 		setbits32(priv->reg_deu + TALITOS_EUICR, TALITOS1_DEUICR_KPE);
244dd3c0987SLEROY Christophe 	} else {
245dd3c0987SLEROY Christophe 		setbits32(priv->reg + TALITOS_IMR, TALITOS2_IMR_INIT);
246dd3c0987SLEROY Christophe 		setbits32(priv->reg + TALITOS_IMR_LO, TALITOS2_IMR_LO_INIT);
247dd3c0987SLEROY Christophe 	}
2489c4a7965SKim Phillips 
249fe5720e2SKim Phillips 	/* disable integrity check error interrupts (use writeback instead) */
250fe5720e2SKim Phillips 	if (priv->features & TALITOS_FTR_HW_AUTH_CHECK)
2515fa7fa14SLEROY Christophe 		setbits32(priv->reg_mdeu + TALITOS_EUICR_LO,
252fe5720e2SKim Phillips 		          TALITOS_MDEUICR_LO_ICE);
253fe5720e2SKim Phillips 
2549c4a7965SKim Phillips 	return 0;
2559c4a7965SKim Phillips }
2569c4a7965SKim Phillips 
2579c4a7965SKim Phillips /**
2589c4a7965SKim Phillips  * talitos_submit - submits a descriptor to the device for processing
2599c4a7965SKim Phillips  * @dev:	the SEC device to be used
2605228f0f7SKim Phillips  * @ch:		the SEC device channel to be used
2619c4a7965SKim Phillips  * @desc:	the descriptor to be processed by the device
2629c4a7965SKim Phillips  * @callback:	whom to call when processing is complete
2639c4a7965SKim Phillips  * @context:	a handle for use by caller (optional)
2649c4a7965SKim Phillips  *
2659c4a7965SKim Phillips  * desc must contain valid dma-mapped (bus physical) address pointers.
2669c4a7965SKim Phillips  * callback must check err and feedback in descriptor header
2679c4a7965SKim Phillips  * for device processing status.
2689c4a7965SKim Phillips  */
talitos_submit(struct device * dev,int ch,struct talitos_desc * desc,void (* callback)(struct device * dev,struct talitos_desc * desc,void * context,int error),void * context)269fbb8d46eSChristophe Leroy static int talitos_submit(struct device *dev, int ch, struct talitos_desc *desc,
2709c4a7965SKim Phillips 			  void (*callback)(struct device *dev,
2719c4a7965SKim Phillips 					   struct talitos_desc *desc,
2729c4a7965SKim Phillips 					   void *context, int error),
2739c4a7965SKim Phillips 			  void *context)
2749c4a7965SKim Phillips {
2759c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
2769c4a7965SKim Phillips 	struct talitos_request *request;
2775228f0f7SKim Phillips 	unsigned long flags;
2789c4a7965SKim Phillips 	int head;
2797d607c6aSLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
2809c4a7965SKim Phillips 
2814b992628SKim Phillips 	spin_lock_irqsave(&priv->chan[ch].head_lock, flags);
2829c4a7965SKim Phillips 
2834b992628SKim Phillips 	if (!atomic_inc_not_zero(&priv->chan[ch].submit_count)) {
284ec6644d6SKim Phillips 		/* h/w fifo is full */
2854b992628SKim Phillips 		spin_unlock_irqrestore(&priv->chan[ch].head_lock, flags);
2869c4a7965SKim Phillips 		return -EAGAIN;
2879c4a7965SKim Phillips 	}
2889c4a7965SKim Phillips 
2894b992628SKim Phillips 	head = priv->chan[ch].head;
2904b992628SKim Phillips 	request = &priv->chan[ch].fifo[head];
291ec6644d6SKim Phillips 
2929c4a7965SKim Phillips 	/* map descriptor and save caller data */
2937d607c6aSLEROY Christophe 	if (is_sec1) {
2947d607c6aSLEROY Christophe 		desc->hdr1 = desc->hdr;
2957d607c6aSLEROY Christophe 		request->dma_desc = dma_map_single(dev, &desc->hdr1,
2967d607c6aSLEROY Christophe 						   TALITOS_DESC_SIZE,
2979c4a7965SKim Phillips 						   DMA_BIDIRECTIONAL);
2987d607c6aSLEROY Christophe 	} else {
2997d607c6aSLEROY Christophe 		request->dma_desc = dma_map_single(dev, desc,
3007d607c6aSLEROY Christophe 						   TALITOS_DESC_SIZE,
3017d607c6aSLEROY Christophe 						   DMA_BIDIRECTIONAL);
3027d607c6aSLEROY Christophe 	}
3039c4a7965SKim Phillips 	request->callback = callback;
3049c4a7965SKim Phillips 	request->context = context;
3059c4a7965SKim Phillips 
3069c4a7965SKim Phillips 	/* increment fifo head */
3074b992628SKim Phillips 	priv->chan[ch].head = (priv->chan[ch].head + 1) & (priv->fifo_len - 1);
3089c4a7965SKim Phillips 
3099c4a7965SKim Phillips 	smp_wmb();
3109c4a7965SKim Phillips 	request->desc = desc;
3119c4a7965SKim Phillips 
3129c4a7965SKim Phillips 	/* GO! */
3139c4a7965SKim Phillips 	wmb();
314ad42d5fcSKim Phillips 	out_be32(priv->chan[ch].reg + TALITOS_FF,
315ad42d5fcSKim Phillips 		 upper_32_bits(request->dma_desc));
316ad42d5fcSKim Phillips 	out_be32(priv->chan[ch].reg + TALITOS_FF_LO,
317a752447aSKim Phillips 		 lower_32_bits(request->dma_desc));
3189c4a7965SKim Phillips 
3194b992628SKim Phillips 	spin_unlock_irqrestore(&priv->chan[ch].head_lock, flags);
3209c4a7965SKim Phillips 
3219c4a7965SKim Phillips 	return -EINPROGRESS;
3229c4a7965SKim Phillips }
3239c4a7965SKim Phillips 
get_request_hdr(struct talitos_request * request,bool is_sec1)32458cdbc6dSChristophe Leroy static __be32 get_request_hdr(struct talitos_request *request, bool is_sec1)
32558cdbc6dSChristophe Leroy {
32658cdbc6dSChristophe Leroy 	struct talitos_edesc *edesc;
32758cdbc6dSChristophe Leroy 
32858cdbc6dSChristophe Leroy 	if (!is_sec1)
32958cdbc6dSChristophe Leroy 		return request->desc->hdr;
33058cdbc6dSChristophe Leroy 
33158cdbc6dSChristophe Leroy 	if (!request->desc->next_desc)
33258cdbc6dSChristophe Leroy 		return request->desc->hdr1;
33358cdbc6dSChristophe Leroy 
33458cdbc6dSChristophe Leroy 	edesc = container_of(request->desc, struct talitos_edesc, desc);
33558cdbc6dSChristophe Leroy 
33658cdbc6dSChristophe Leroy 	return ((struct talitos_desc *)(edesc->buf + edesc->dma_len))->hdr1;
33758cdbc6dSChristophe Leroy }
3389c4a7965SKim Phillips 
3399c4a7965SKim Phillips /*
3409c4a7965SKim Phillips  * process what was done, notify callback of error if not
3419c4a7965SKim Phillips  */
flush_channel(struct device * dev,int ch,int error,int reset_ch)3429c4a7965SKim Phillips static void flush_channel(struct device *dev, int ch, int error, int reset_ch)
3439c4a7965SKim Phillips {
3449c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
3459c4a7965SKim Phillips 	struct talitos_request *request, saved_req;
3469c4a7965SKim Phillips 	unsigned long flags;
3479c4a7965SKim Phillips 	int tail, status;
3487d607c6aSLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
3499c4a7965SKim Phillips 
3504b992628SKim Phillips 	spin_lock_irqsave(&priv->chan[ch].tail_lock, flags);
3519c4a7965SKim Phillips 
3524b992628SKim Phillips 	tail = priv->chan[ch].tail;
3534b992628SKim Phillips 	while (priv->chan[ch].fifo[tail].desc) {
3547d607c6aSLEROY Christophe 		__be32 hdr;
3557d607c6aSLEROY Christophe 
3564b992628SKim Phillips 		request = &priv->chan[ch].fifo[tail];
3579c4a7965SKim Phillips 
3589c4a7965SKim Phillips 		/* descriptors with their done bits set don't get the error */
3599c4a7965SKim Phillips 		rmb();
36058cdbc6dSChristophe Leroy 		hdr = get_request_hdr(request, is_sec1);
3617d607c6aSLEROY Christophe 
3627d607c6aSLEROY Christophe 		if ((hdr & DESC_HDR_DONE) == DESC_HDR_DONE)
3639c4a7965SKim Phillips 			status = 0;
364ca38a814SLee Nipper 		else
3659c4a7965SKim Phillips 			if (!error)
3669c4a7965SKim Phillips 				break;
3679c4a7965SKim Phillips 			else
3689c4a7965SKim Phillips 				status = error;
3699c4a7965SKim Phillips 
3709c4a7965SKim Phillips 		dma_unmap_single(dev, request->dma_desc,
3717d607c6aSLEROY Christophe 				 TALITOS_DESC_SIZE,
372e938e465SKim Phillips 				 DMA_BIDIRECTIONAL);
3739c4a7965SKim Phillips 
3749c4a7965SKim Phillips 		/* copy entries so we can call callback outside lock */
3759c4a7965SKim Phillips 		saved_req.desc = request->desc;
3769c4a7965SKim Phillips 		saved_req.callback = request->callback;
3779c4a7965SKim Phillips 		saved_req.context = request->context;
3789c4a7965SKim Phillips 
3799c4a7965SKim Phillips 		/* release request entry in fifo */
3809c4a7965SKim Phillips 		smp_wmb();
3819c4a7965SKim Phillips 		request->desc = NULL;
3829c4a7965SKim Phillips 
3839c4a7965SKim Phillips 		/* increment fifo tail */
3844b992628SKim Phillips 		priv->chan[ch].tail = (tail + 1) & (priv->fifo_len - 1);
3859c4a7965SKim Phillips 
3864b992628SKim Phillips 		spin_unlock_irqrestore(&priv->chan[ch].tail_lock, flags);
387ec6644d6SKim Phillips 
3884b992628SKim Phillips 		atomic_dec(&priv->chan[ch].submit_count);
389ec6644d6SKim Phillips 
3909c4a7965SKim Phillips 		saved_req.callback(dev, saved_req.desc, saved_req.context,
3919c4a7965SKim Phillips 				   status);
3929c4a7965SKim Phillips 		/* channel may resume processing in single desc error case */
3939c4a7965SKim Phillips 		if (error && !reset_ch && status == error)
3949c4a7965SKim Phillips 			return;
3954b992628SKim Phillips 		spin_lock_irqsave(&priv->chan[ch].tail_lock, flags);
3964b992628SKim Phillips 		tail = priv->chan[ch].tail;
3979c4a7965SKim Phillips 	}
3989c4a7965SKim Phillips 
3994b992628SKim Phillips 	spin_unlock_irqrestore(&priv->chan[ch].tail_lock, flags);
4009c4a7965SKim Phillips }
4019c4a7965SKim Phillips 
4029c4a7965SKim Phillips /*
4039c4a7965SKim Phillips  * process completed requests for channels that have done status
4049c4a7965SKim Phillips  */
405dd3c0987SLEROY Christophe #define DEF_TALITOS1_DONE(name, ch_done_mask)				\
406dd3c0987SLEROY Christophe static void talitos1_done_##name(unsigned long data)			\
407dd3c0987SLEROY Christophe {									\
408dd3c0987SLEROY Christophe 	struct device *dev = (struct device *)data;			\
409dd3c0987SLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);		\
410dd3c0987SLEROY Christophe 	unsigned long flags;						\
411dd3c0987SLEROY Christophe 									\
412dd3c0987SLEROY Christophe 	if (ch_done_mask & 0x10000000)					\
413dd3c0987SLEROY Christophe 		flush_channel(dev, 0, 0, 0);			\
414dd3c0987SLEROY Christophe 	if (ch_done_mask & 0x40000000)					\
415dd3c0987SLEROY Christophe 		flush_channel(dev, 1, 0, 0);			\
416dd3c0987SLEROY Christophe 	if (ch_done_mask & 0x00010000)					\
417dd3c0987SLEROY Christophe 		flush_channel(dev, 2, 0, 0);			\
418dd3c0987SLEROY Christophe 	if (ch_done_mask & 0x00040000)					\
419dd3c0987SLEROY Christophe 		flush_channel(dev, 3, 0, 0);			\
420dd3c0987SLEROY Christophe 									\
421dd3c0987SLEROY Christophe 	/* At this point, all completed channels have been processed */	\
422dd3c0987SLEROY Christophe 	/* Unmask done interrupts for channels completed later on. */	\
423dd3c0987SLEROY Christophe 	spin_lock_irqsave(&priv->reg_lock, flags);			\
424dd3c0987SLEROY Christophe 	clrbits32(priv->reg + TALITOS_IMR, ch_done_mask);		\
425dd3c0987SLEROY Christophe 	clrbits32(priv->reg + TALITOS_IMR_LO, TALITOS1_IMR_LO_INIT);	\
426dd3c0987SLEROY Christophe 	spin_unlock_irqrestore(&priv->reg_lock, flags);			\
427dd3c0987SLEROY Christophe }
428dd3c0987SLEROY Christophe 
429dd3c0987SLEROY Christophe DEF_TALITOS1_DONE(4ch, TALITOS1_ISR_4CHDONE)
DEF_TALITOS1_DONE(ch0,TALITOS1_ISR_CH_0_DONE)4309c02e285SLEROY Christophe DEF_TALITOS1_DONE(ch0, TALITOS1_ISR_CH_0_DONE)
431dd3c0987SLEROY Christophe 
432dd3c0987SLEROY Christophe #define DEF_TALITOS2_DONE(name, ch_done_mask)				\
433dd3c0987SLEROY Christophe static void talitos2_done_##name(unsigned long data)			\
434c3e337f8SKim Phillips {									\
435c3e337f8SKim Phillips 	struct device *dev = (struct device *)data;			\
436c3e337f8SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);		\
437511d63cbSHoria Geanta 	unsigned long flags;						\
438c3e337f8SKim Phillips 									\
439c3e337f8SKim Phillips 	if (ch_done_mask & 1)						\
440c3e337f8SKim Phillips 		flush_channel(dev, 0, 0, 0);				\
441c3e337f8SKim Phillips 	if (ch_done_mask & (1 << 2))					\
442c3e337f8SKim Phillips 		flush_channel(dev, 1, 0, 0);				\
443c3e337f8SKim Phillips 	if (ch_done_mask & (1 << 4))					\
444c3e337f8SKim Phillips 		flush_channel(dev, 2, 0, 0);				\
445c3e337f8SKim Phillips 	if (ch_done_mask & (1 << 6))					\
446c3e337f8SKim Phillips 		flush_channel(dev, 3, 0, 0);				\
447c3e337f8SKim Phillips 									\
448c3e337f8SKim Phillips 	/* At this point, all completed channels have been processed */	\
449c3e337f8SKim Phillips 	/* Unmask done interrupts for channels completed later on. */	\
450511d63cbSHoria Geanta 	spin_lock_irqsave(&priv->reg_lock, flags);			\
451c3e337f8SKim Phillips 	setbits32(priv->reg + TALITOS_IMR, ch_done_mask);		\
452dd3c0987SLEROY Christophe 	setbits32(priv->reg + TALITOS_IMR_LO, TALITOS2_IMR_LO_INIT);	\
453511d63cbSHoria Geanta 	spin_unlock_irqrestore(&priv->reg_lock, flags);			\
4549c4a7965SKim Phillips }
455dd3c0987SLEROY Christophe 
456dd3c0987SLEROY Christophe DEF_TALITOS2_DONE(4ch, TALITOS2_ISR_4CHDONE)
4579c02e285SLEROY Christophe DEF_TALITOS2_DONE(ch0, TALITOS2_ISR_CH_0_DONE)
458dd3c0987SLEROY Christophe DEF_TALITOS2_DONE(ch0_2, TALITOS2_ISR_CH_0_2_DONE)
459dd3c0987SLEROY Christophe DEF_TALITOS2_DONE(ch1_3, TALITOS2_ISR_CH_1_3_DONE)
4609c4a7965SKim Phillips 
4619c4a7965SKim Phillips /*
4629c4a7965SKim Phillips  * locate current (offending) descriptor
4639c4a7965SKim Phillips  */
46402376161SChristophe Leroy static __be32 current_desc_hdr(struct device *dev, int ch)
4659c4a7965SKim Phillips {
4669c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
467b62ffd8cSHoria Geanta 	int tail, iter;
4689c4a7965SKim Phillips 	dma_addr_t cur_desc;
4699c4a7965SKim Phillips 
470b62ffd8cSHoria Geanta 	cur_desc = ((u64)in_be32(priv->chan[ch].reg + TALITOS_CDPR)) << 32;
471b62ffd8cSHoria Geanta 	cur_desc |= in_be32(priv->chan[ch].reg + TALITOS_CDPR_LO);
4729c4a7965SKim Phillips 
473b62ffd8cSHoria Geanta 	if (!cur_desc) {
474b62ffd8cSHoria Geanta 		dev_err(dev, "CDPR is NULL, giving up search for offending descriptor\n");
475b62ffd8cSHoria Geanta 		return 0;
476b62ffd8cSHoria Geanta 	}
477b62ffd8cSHoria Geanta 
478b62ffd8cSHoria Geanta 	tail = priv->chan[ch].tail;
479b62ffd8cSHoria Geanta 
480b62ffd8cSHoria Geanta 	iter = tail;
48137b5e889SLEROY Christophe 	while (priv->chan[ch].fifo[iter].dma_desc != cur_desc &&
482195404dbSChristophe Leroy 	       priv->chan[ch].fifo[iter].desc->next_desc != cpu_to_be32(cur_desc)) {
483b62ffd8cSHoria Geanta 		iter = (iter + 1) & (priv->fifo_len - 1);
484b62ffd8cSHoria Geanta 		if (iter == tail) {
4859c4a7965SKim Phillips 			dev_err(dev, "couldn't locate current descriptor\n");
4863e721aebSKim Phillips 			return 0;
4879c4a7965SKim Phillips 		}
4889c4a7965SKim Phillips 	}
4899c4a7965SKim Phillips 
490195404dbSChristophe Leroy 	if (priv->chan[ch].fifo[iter].desc->next_desc == cpu_to_be32(cur_desc)) {
49158cdbc6dSChristophe Leroy 		struct talitos_edesc *edesc;
49258cdbc6dSChristophe Leroy 
49358cdbc6dSChristophe Leroy 		edesc = container_of(priv->chan[ch].fifo[iter].desc,
49458cdbc6dSChristophe Leroy 				     struct talitos_edesc, desc);
49558cdbc6dSChristophe Leroy 		return ((struct talitos_desc *)
49658cdbc6dSChristophe Leroy 			(edesc->buf + edesc->dma_len))->hdr;
49758cdbc6dSChristophe Leroy 	}
49837b5e889SLEROY Christophe 
499b62ffd8cSHoria Geanta 	return priv->chan[ch].fifo[iter].desc->hdr;
5009c4a7965SKim Phillips }
5019c4a7965SKim Phillips 
5029c4a7965SKim Phillips /*
5039c4a7965SKim Phillips  * user diagnostics; report root cause of error based on execution unit status
5049c4a7965SKim Phillips  */
report_eu_error(struct device * dev,int ch,__be32 desc_hdr)50502376161SChristophe Leroy static void report_eu_error(struct device *dev, int ch, __be32 desc_hdr)
5069c4a7965SKim Phillips {
5079c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
5089c4a7965SKim Phillips 	int i;
5099c4a7965SKim Phillips 
5103e721aebSKim Phillips 	if (!desc_hdr)
51102376161SChristophe Leroy 		desc_hdr = cpu_to_be32(in_be32(priv->chan[ch].reg + TALITOS_DESCBUF));
5123e721aebSKim Phillips 
5133e721aebSKim Phillips 	switch (desc_hdr & DESC_HDR_SEL0_MASK) {
5149c4a7965SKim Phillips 	case DESC_HDR_SEL0_AFEU:
5159c4a7965SKim Phillips 		dev_err(dev, "AFEUISR 0x%08x_%08x\n",
5165fa7fa14SLEROY Christophe 			in_be32(priv->reg_afeu + TALITOS_EUISR),
5175fa7fa14SLEROY Christophe 			in_be32(priv->reg_afeu + TALITOS_EUISR_LO));
5189c4a7965SKim Phillips 		break;
5199c4a7965SKim Phillips 	case DESC_HDR_SEL0_DEU:
5209c4a7965SKim Phillips 		dev_err(dev, "DEUISR 0x%08x_%08x\n",
5215fa7fa14SLEROY Christophe 			in_be32(priv->reg_deu + TALITOS_EUISR),
5225fa7fa14SLEROY Christophe 			in_be32(priv->reg_deu + TALITOS_EUISR_LO));
5239c4a7965SKim Phillips 		break;
5249c4a7965SKim Phillips 	case DESC_HDR_SEL0_MDEUA:
5259c4a7965SKim Phillips 	case DESC_HDR_SEL0_MDEUB:
5269c4a7965SKim Phillips 		dev_err(dev, "MDEUISR 0x%08x_%08x\n",
5275fa7fa14SLEROY Christophe 			in_be32(priv->reg_mdeu + TALITOS_EUISR),
5285fa7fa14SLEROY Christophe 			in_be32(priv->reg_mdeu + TALITOS_EUISR_LO));
5299c4a7965SKim Phillips 		break;
5309c4a7965SKim Phillips 	case DESC_HDR_SEL0_RNG:
5319c4a7965SKim Phillips 		dev_err(dev, "RNGUISR 0x%08x_%08x\n",
5325fa7fa14SLEROY Christophe 			in_be32(priv->reg_rngu + TALITOS_ISR),
5335fa7fa14SLEROY Christophe 			in_be32(priv->reg_rngu + TALITOS_ISR_LO));
5349c4a7965SKim Phillips 		break;
5359c4a7965SKim Phillips 	case DESC_HDR_SEL0_PKEU:
5369c4a7965SKim Phillips 		dev_err(dev, "PKEUISR 0x%08x_%08x\n",
5375fa7fa14SLEROY Christophe 			in_be32(priv->reg_pkeu + TALITOS_EUISR),
5385fa7fa14SLEROY Christophe 			in_be32(priv->reg_pkeu + TALITOS_EUISR_LO));
5399c4a7965SKim Phillips 		break;
5409c4a7965SKim Phillips 	case DESC_HDR_SEL0_AESU:
5419c4a7965SKim Phillips 		dev_err(dev, "AESUISR 0x%08x_%08x\n",
5425fa7fa14SLEROY Christophe 			in_be32(priv->reg_aesu + TALITOS_EUISR),
5435fa7fa14SLEROY Christophe 			in_be32(priv->reg_aesu + TALITOS_EUISR_LO));
5449c4a7965SKim Phillips 		break;
5459c4a7965SKim Phillips 	case DESC_HDR_SEL0_CRCU:
5469c4a7965SKim Phillips 		dev_err(dev, "CRCUISR 0x%08x_%08x\n",
5475fa7fa14SLEROY Christophe 			in_be32(priv->reg_crcu + TALITOS_EUISR),
5485fa7fa14SLEROY Christophe 			in_be32(priv->reg_crcu + TALITOS_EUISR_LO));
5499c4a7965SKim Phillips 		break;
5509c4a7965SKim Phillips 	case DESC_HDR_SEL0_KEU:
5519c4a7965SKim Phillips 		dev_err(dev, "KEUISR 0x%08x_%08x\n",
5525fa7fa14SLEROY Christophe 			in_be32(priv->reg_pkeu + TALITOS_EUISR),
5535fa7fa14SLEROY Christophe 			in_be32(priv->reg_pkeu + TALITOS_EUISR_LO));
5549c4a7965SKim Phillips 		break;
5559c4a7965SKim Phillips 	}
5569c4a7965SKim Phillips 
5573e721aebSKim Phillips 	switch (desc_hdr & DESC_HDR_SEL1_MASK) {
5589c4a7965SKim Phillips 	case DESC_HDR_SEL1_MDEUA:
5599c4a7965SKim Phillips 	case DESC_HDR_SEL1_MDEUB:
5609c4a7965SKim Phillips 		dev_err(dev, "MDEUISR 0x%08x_%08x\n",
5615fa7fa14SLEROY Christophe 			in_be32(priv->reg_mdeu + TALITOS_EUISR),
5625fa7fa14SLEROY Christophe 			in_be32(priv->reg_mdeu + TALITOS_EUISR_LO));
5639c4a7965SKim Phillips 		break;
5649c4a7965SKim Phillips 	case DESC_HDR_SEL1_CRCU:
5659c4a7965SKim Phillips 		dev_err(dev, "CRCUISR 0x%08x_%08x\n",
5665fa7fa14SLEROY Christophe 			in_be32(priv->reg_crcu + TALITOS_EUISR),
5675fa7fa14SLEROY Christophe 			in_be32(priv->reg_crcu + TALITOS_EUISR_LO));
5689c4a7965SKim Phillips 		break;
5699c4a7965SKim Phillips 	}
5709c4a7965SKim Phillips 
5719c4a7965SKim Phillips 	for (i = 0; i < 8; i++)
5729c4a7965SKim Phillips 		dev_err(dev, "DESCBUF 0x%08x_%08x\n",
573ad42d5fcSKim Phillips 			in_be32(priv->chan[ch].reg + TALITOS_DESCBUF + 8*i),
574ad42d5fcSKim Phillips 			in_be32(priv->chan[ch].reg + TALITOS_DESCBUF_LO + 8*i));
5759c4a7965SKim Phillips }
5769c4a7965SKim Phillips 
5779c4a7965SKim Phillips /*
5789c4a7965SKim Phillips  * recover from error interrupts
5799c4a7965SKim Phillips  */
talitos_error(struct device * dev,u32 isr,u32 isr_lo)5805e718a09SKim Phillips static void talitos_error(struct device *dev, u32 isr, u32 isr_lo)
5819c4a7965SKim Phillips {
5829c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
5839c4a7965SKim Phillips 	unsigned int timeout = TALITOS_TIMEOUT;
584dd3c0987SLEROY Christophe 	int ch, error, reset_dev = 0;
58542e8b0d7SHoria Geant? 	u32 v_lo;
586dd3c0987SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
587dd3c0987SLEROY Christophe 	int reset_ch = is_sec1 ? 1 : 0; /* only SEC2 supports continuation */
5889c4a7965SKim Phillips 
5899c4a7965SKim Phillips 	for (ch = 0; ch < priv->num_channels; ch++) {
5909c4a7965SKim Phillips 		/* skip channels without errors */
591dd3c0987SLEROY Christophe 		if (is_sec1) {
592dd3c0987SLEROY Christophe 			/* bits 29, 31, 17, 19 */
593dd3c0987SLEROY Christophe 			if (!(isr & (1 << (29 + (ch & 1) * 2 - (ch & 2) * 6))))
594dd3c0987SLEROY Christophe 				continue;
595dd3c0987SLEROY Christophe 		} else {
5969c4a7965SKim Phillips 			if (!(isr & (1 << (ch * 2 + 1))))
5979c4a7965SKim Phillips 				continue;
598dd3c0987SLEROY Christophe 		}
5999c4a7965SKim Phillips 
6009c4a7965SKim Phillips 		error = -EINVAL;
6019c4a7965SKim Phillips 
602ad42d5fcSKim Phillips 		v_lo = in_be32(priv->chan[ch].reg + TALITOS_CCPSR_LO);
6039c4a7965SKim Phillips 
6049c4a7965SKim Phillips 		if (v_lo & TALITOS_CCPSR_LO_DOF) {
6059c4a7965SKim Phillips 			dev_err(dev, "double fetch fifo overflow error\n");
6069c4a7965SKim Phillips 			error = -EAGAIN;
6079c4a7965SKim Phillips 			reset_ch = 1;
6089c4a7965SKim Phillips 		}
6099c4a7965SKim Phillips 		if (v_lo & TALITOS_CCPSR_LO_SOF) {
6109c4a7965SKim Phillips 			/* h/w dropped descriptor */
6119c4a7965SKim Phillips 			dev_err(dev, "single fetch fifo overflow error\n");
6129c4a7965SKim Phillips 			error = -EAGAIN;
6139c4a7965SKim Phillips 		}
6149c4a7965SKim Phillips 		if (v_lo & TALITOS_CCPSR_LO_MDTE)
6159c4a7965SKim Phillips 			dev_err(dev, "master data transfer error\n");
6169c4a7965SKim Phillips 		if (v_lo & TALITOS_CCPSR_LO_SGDLZ)
6174d9b3a5bSColin Ian King 			dev_err(dev, is_sec1 ? "pointer not complete error\n"
618dd3c0987SLEROY Christophe 					     : "s/g data length zero error\n");
6199c4a7965SKim Phillips 		if (v_lo & TALITOS_CCPSR_LO_FPZ)
620dd3c0987SLEROY Christophe 			dev_err(dev, is_sec1 ? "parity error\n"
621dd3c0987SLEROY Christophe 					     : "fetch pointer zero error\n");
6229c4a7965SKim Phillips 		if (v_lo & TALITOS_CCPSR_LO_IDH)
6239c4a7965SKim Phillips 			dev_err(dev, "illegal descriptor header error\n");
6249c4a7965SKim Phillips 		if (v_lo & TALITOS_CCPSR_LO_IEU)
625dd3c0987SLEROY Christophe 			dev_err(dev, is_sec1 ? "static assignment error\n"
626dd3c0987SLEROY Christophe 					     : "invalid exec unit error\n");
6279c4a7965SKim Phillips 		if (v_lo & TALITOS_CCPSR_LO_EU)
6283e721aebSKim Phillips 			report_eu_error(dev, ch, current_desc_hdr(dev, ch));
629dd3c0987SLEROY Christophe 		if (!is_sec1) {
6309c4a7965SKim Phillips 			if (v_lo & TALITOS_CCPSR_LO_GB)
6319c4a7965SKim Phillips 				dev_err(dev, "gather boundary error\n");
6329c4a7965SKim Phillips 			if (v_lo & TALITOS_CCPSR_LO_GRL)
6339c4a7965SKim Phillips 				dev_err(dev, "gather return/length error\n");
6349c4a7965SKim Phillips 			if (v_lo & TALITOS_CCPSR_LO_SB)
6359c4a7965SKim Phillips 				dev_err(dev, "scatter boundary error\n");
6369c4a7965SKim Phillips 			if (v_lo & TALITOS_CCPSR_LO_SRL)
6379c4a7965SKim Phillips 				dev_err(dev, "scatter return/length error\n");
638dd3c0987SLEROY Christophe 		}
6399c4a7965SKim Phillips 
6409c4a7965SKim Phillips 		flush_channel(dev, ch, error, reset_ch);
6419c4a7965SKim Phillips 
6429c4a7965SKim Phillips 		if (reset_ch) {
6439c4a7965SKim Phillips 			reset_channel(dev, ch);
6449c4a7965SKim Phillips 		} else {
645ad42d5fcSKim Phillips 			setbits32(priv->chan[ch].reg + TALITOS_CCCR,
646dd3c0987SLEROY Christophe 				  TALITOS2_CCCR_CONT);
647ad42d5fcSKim Phillips 			setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO, 0);
648ad42d5fcSKim Phillips 			while ((in_be32(priv->chan[ch].reg + TALITOS_CCCR) &
649dd3c0987SLEROY Christophe 			       TALITOS2_CCCR_CONT) && --timeout)
6509c4a7965SKim Phillips 				cpu_relax();
6519c4a7965SKim Phillips 			if (timeout == 0) {
6529c4a7965SKim Phillips 				dev_err(dev, "failed to restart channel %d\n",
6539c4a7965SKim Phillips 					ch);
6549c4a7965SKim Phillips 				reset_dev = 1;
6559c4a7965SKim Phillips 			}
6569c4a7965SKim Phillips 		}
6579c4a7965SKim Phillips 	}
658dd3c0987SLEROY Christophe 	if (reset_dev || (is_sec1 && isr & ~TALITOS1_ISR_4CHERR) ||
659dd3c0987SLEROY Christophe 	    (!is_sec1 && isr & ~TALITOS2_ISR_4CHERR) || isr_lo) {
660dd3c0987SLEROY Christophe 		if (is_sec1 && (isr_lo & TALITOS1_ISR_TEA_ERR))
661dd3c0987SLEROY Christophe 			dev_err(dev, "TEA error: ISR 0x%08x_%08x\n",
662dd3c0987SLEROY Christophe 				isr, isr_lo);
663dd3c0987SLEROY Christophe 		else
664dd3c0987SLEROY Christophe 			dev_err(dev, "done overflow, internal time out, or "
665dd3c0987SLEROY Christophe 				"rngu error: ISR 0x%08x_%08x\n", isr, isr_lo);
6669c4a7965SKim Phillips 
6679c4a7965SKim Phillips 		/* purge request queues */
6689c4a7965SKim Phillips 		for (ch = 0; ch < priv->num_channels; ch++)
6699c4a7965SKim Phillips 			flush_channel(dev, ch, -EIO, 1);
6709c4a7965SKim Phillips 
6719c4a7965SKim Phillips 		/* reset and reinitialize the device */
6729c4a7965SKim Phillips 		init_device(dev);
6739c4a7965SKim Phillips 	}
6749c4a7965SKim Phillips }
6759c4a7965SKim Phillips 
676dd3c0987SLEROY Christophe #define DEF_TALITOS1_INTERRUPT(name, ch_done_mask, ch_err_mask, tlet)	       \
677dd3c0987SLEROY Christophe static irqreturn_t talitos1_interrupt_##name(int irq, void *data)	       \
678dd3c0987SLEROY Christophe {									       \
679dd3c0987SLEROY Christophe 	struct device *dev = data;					       \
680dd3c0987SLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);		       \
681dd3c0987SLEROY Christophe 	u32 isr, isr_lo;						       \
682dd3c0987SLEROY Christophe 	unsigned long flags;						       \
683dd3c0987SLEROY Christophe 									       \
684dd3c0987SLEROY Christophe 	spin_lock_irqsave(&priv->reg_lock, flags);			       \
685dd3c0987SLEROY Christophe 	isr = in_be32(priv->reg + TALITOS_ISR);				       \
686dd3c0987SLEROY Christophe 	isr_lo = in_be32(priv->reg + TALITOS_ISR_LO);			       \
687dd3c0987SLEROY Christophe 	/* Acknowledge interrupt */					       \
688dd3c0987SLEROY Christophe 	out_be32(priv->reg + TALITOS_ICR, isr & (ch_done_mask | ch_err_mask)); \
689dd3c0987SLEROY Christophe 	out_be32(priv->reg + TALITOS_ICR_LO, isr_lo);			       \
690dd3c0987SLEROY Christophe 									       \
691dd3c0987SLEROY Christophe 	if (unlikely(isr & ch_err_mask || isr_lo & TALITOS1_IMR_LO_INIT)) {    \
692dd3c0987SLEROY Christophe 		spin_unlock_irqrestore(&priv->reg_lock, flags);		       \
693dd3c0987SLEROY Christophe 		talitos_error(dev, isr & ch_err_mask, isr_lo);		       \
694dd3c0987SLEROY Christophe 	}								       \
695dd3c0987SLEROY Christophe 	else {								       \
696dd3c0987SLEROY Christophe 		if (likely(isr & ch_done_mask)) {			       \
697dd3c0987SLEROY Christophe 			/* mask further done interrupts. */		       \
698dd3c0987SLEROY Christophe 			setbits32(priv->reg + TALITOS_IMR, ch_done_mask);      \
699dd3c0987SLEROY Christophe 			/* done_task will unmask done interrupts at exit */    \
700dd3c0987SLEROY Christophe 			tasklet_schedule(&priv->done_task[tlet]);	       \
701dd3c0987SLEROY Christophe 		}							       \
702dd3c0987SLEROY Christophe 		spin_unlock_irqrestore(&priv->reg_lock, flags);		       \
703dd3c0987SLEROY Christophe 	}								       \
704dd3c0987SLEROY Christophe 									       \
705dd3c0987SLEROY Christophe 	return (isr & (ch_done_mask | ch_err_mask) || isr_lo) ? IRQ_HANDLED :  \
706dd3c0987SLEROY Christophe 								IRQ_NONE;      \
707dd3c0987SLEROY Christophe }
708dd3c0987SLEROY Christophe 
709dd3c0987SLEROY Christophe DEF_TALITOS1_INTERRUPT(4ch, TALITOS1_ISR_4CHDONE, TALITOS1_ISR_4CHERR, 0)
710dd3c0987SLEROY Christophe 
711dd3c0987SLEROY Christophe #define DEF_TALITOS2_INTERRUPT(name, ch_done_mask, ch_err_mask, tlet)	       \
712dd3c0987SLEROY Christophe static irqreturn_t talitos2_interrupt_##name(int irq, void *data)	       \
713c3e337f8SKim Phillips {									       \
714c3e337f8SKim Phillips 	struct device *dev = data;					       \
715c3e337f8SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);		       \
716c3e337f8SKim Phillips 	u32 isr, isr_lo;						       \
717511d63cbSHoria Geanta 	unsigned long flags;						       \
718c3e337f8SKim Phillips 									       \
719511d63cbSHoria Geanta 	spin_lock_irqsave(&priv->reg_lock, flags);			       \
720c3e337f8SKim Phillips 	isr = in_be32(priv->reg + TALITOS_ISR);				       \
721c3e337f8SKim Phillips 	isr_lo = in_be32(priv->reg + TALITOS_ISR_LO);			       \
722c3e337f8SKim Phillips 	/* Acknowledge interrupt */					       \
723c3e337f8SKim Phillips 	out_be32(priv->reg + TALITOS_ICR, isr & (ch_done_mask | ch_err_mask)); \
724c3e337f8SKim Phillips 	out_be32(priv->reg + TALITOS_ICR_LO, isr_lo);			       \
725c3e337f8SKim Phillips 									       \
726511d63cbSHoria Geanta 	if (unlikely(isr & ch_err_mask || isr_lo)) {			       \
727511d63cbSHoria Geanta 		spin_unlock_irqrestore(&priv->reg_lock, flags);		       \
728511d63cbSHoria Geanta 		talitos_error(dev, isr & ch_err_mask, isr_lo);		       \
729511d63cbSHoria Geanta 	}								       \
730511d63cbSHoria Geanta 	else {								       \
731c3e337f8SKim Phillips 		if (likely(isr & ch_done_mask)) {			       \
732c3e337f8SKim Phillips 			/* mask further done interrupts. */		       \
733c3e337f8SKim Phillips 			clrbits32(priv->reg + TALITOS_IMR, ch_done_mask);      \
734c3e337f8SKim Phillips 			/* done_task will unmask done interrupts at exit */    \
735c3e337f8SKim Phillips 			tasklet_schedule(&priv->done_task[tlet]);	       \
736c3e337f8SKim Phillips 		}							       \
737511d63cbSHoria Geanta 		spin_unlock_irqrestore(&priv->reg_lock, flags);		       \
738511d63cbSHoria Geanta 	}								       \
739c3e337f8SKim Phillips 									       \
740c3e337f8SKim Phillips 	return (isr & (ch_done_mask | ch_err_mask) || isr_lo) ? IRQ_HANDLED :  \
741c3e337f8SKim Phillips 								IRQ_NONE;      \
7421c2e8811SLee Nipper }
743dd3c0987SLEROY Christophe 
744dd3c0987SLEROY Christophe DEF_TALITOS2_INTERRUPT(4ch, TALITOS2_ISR_4CHDONE, TALITOS2_ISR_4CHERR, 0)
745dd3c0987SLEROY Christophe DEF_TALITOS2_INTERRUPT(ch0_2, TALITOS2_ISR_CH_0_2_DONE, TALITOS2_ISR_CH_0_2_ERR,
746dd3c0987SLEROY Christophe 		       0)
747dd3c0987SLEROY Christophe DEF_TALITOS2_INTERRUPT(ch1_3, TALITOS2_ISR_CH_1_3_DONE, TALITOS2_ISR_CH_1_3_ERR,
748dd3c0987SLEROY Christophe 		       1)
7499c4a7965SKim Phillips 
7509c4a7965SKim Phillips /*
7519c4a7965SKim Phillips  * hwrng
7529c4a7965SKim Phillips  */
talitos_rng_data_present(struct hwrng * rng,int wait)7539c4a7965SKim Phillips static int talitos_rng_data_present(struct hwrng *rng, int wait)
7549c4a7965SKim Phillips {
7559c4a7965SKim Phillips 	struct device *dev = (struct device *)rng->priv;
7569c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
7579c4a7965SKim Phillips 	u32 ofl;
7589c4a7965SKim Phillips 	int i;
7599c4a7965SKim Phillips 
7609c4a7965SKim Phillips 	for (i = 0; i < 20; i++) {
7615fa7fa14SLEROY Christophe 		ofl = in_be32(priv->reg_rngu + TALITOS_EUSR_LO) &
7629c4a7965SKim Phillips 		      TALITOS_RNGUSR_LO_OFL;
7639c4a7965SKim Phillips 		if (ofl || !wait)
7649c4a7965SKim Phillips 			break;
7659c4a7965SKim Phillips 		udelay(10);
7669c4a7965SKim Phillips 	}
7679c4a7965SKim Phillips 
7689c4a7965SKim Phillips 	return !!ofl;
7699c4a7965SKim Phillips }
7709c4a7965SKim Phillips 
talitos_rng_data_read(struct hwrng * rng,u32 * data)7719c4a7965SKim Phillips static int talitos_rng_data_read(struct hwrng *rng, u32 *data)
7729c4a7965SKim Phillips {
7739c4a7965SKim Phillips 	struct device *dev = (struct device *)rng->priv;
7749c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
7759c4a7965SKim Phillips 
7769c4a7965SKim Phillips 	/* rng fifo requires 64-bit accesses */
7775fa7fa14SLEROY Christophe 	*data = in_be32(priv->reg_rngu + TALITOS_EU_FIFO);
7785fa7fa14SLEROY Christophe 	*data = in_be32(priv->reg_rngu + TALITOS_EU_FIFO_LO);
7799c4a7965SKim Phillips 
7809c4a7965SKim Phillips 	return sizeof(u32);
7819c4a7965SKim Phillips }
7829c4a7965SKim Phillips 
talitos_rng_init(struct hwrng * rng)7839c4a7965SKim Phillips static int talitos_rng_init(struct hwrng *rng)
7849c4a7965SKim Phillips {
7859c4a7965SKim Phillips 	struct device *dev = (struct device *)rng->priv;
7869c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
7879c4a7965SKim Phillips 	unsigned int timeout = TALITOS_TIMEOUT;
7889c4a7965SKim Phillips 
7895fa7fa14SLEROY Christophe 	setbits32(priv->reg_rngu + TALITOS_EURCR_LO, TALITOS_RNGURCR_LO_SR);
7905fa7fa14SLEROY Christophe 	while (!(in_be32(priv->reg_rngu + TALITOS_EUSR_LO)
7915fa7fa14SLEROY Christophe 		 & TALITOS_RNGUSR_LO_RD)
7929c4a7965SKim Phillips 	       && --timeout)
7939c4a7965SKim Phillips 		cpu_relax();
7949c4a7965SKim Phillips 	if (timeout == 0) {
7959c4a7965SKim Phillips 		dev_err(dev, "failed to reset rng hw\n");
7969c4a7965SKim Phillips 		return -ENODEV;
7979c4a7965SKim Phillips 	}
7989c4a7965SKim Phillips 
7999c4a7965SKim Phillips 	/* start generating */
8005fa7fa14SLEROY Christophe 	setbits32(priv->reg_rngu + TALITOS_EUDSR_LO, 0);
8019c4a7965SKim Phillips 
8029c4a7965SKim Phillips 	return 0;
8039c4a7965SKim Phillips }
8049c4a7965SKim Phillips 
talitos_register_rng(struct device * dev)8059c4a7965SKim Phillips static int talitos_register_rng(struct device *dev)
8069c4a7965SKim Phillips {
8079c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
80835a3bb3dSAaron Sierra 	int err;
8099c4a7965SKim Phillips 
81077450fd7SJulia Lawall 	priv->rng.name		= dev_driver_string(dev);
81177450fd7SJulia Lawall 	priv->rng.init		= talitos_rng_init;
81277450fd7SJulia Lawall 	priv->rng.data_present	= talitos_rng_data_present;
81377450fd7SJulia Lawall 	priv->rng.data_read	= talitos_rng_data_read;
8149c4a7965SKim Phillips 	priv->rng.priv		= (unsigned long)dev;
8159c4a7965SKim Phillips 
81635a3bb3dSAaron Sierra 	err = hwrng_register(&priv->rng);
81735a3bb3dSAaron Sierra 	if (!err)
81835a3bb3dSAaron Sierra 		priv->rng_registered = true;
81935a3bb3dSAaron Sierra 
82035a3bb3dSAaron Sierra 	return err;
8219c4a7965SKim Phillips }
8229c4a7965SKim Phillips 
talitos_unregister_rng(struct device * dev)8239c4a7965SKim Phillips static void talitos_unregister_rng(struct device *dev)
8249c4a7965SKim Phillips {
8259c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
8269c4a7965SKim Phillips 
82735a3bb3dSAaron Sierra 	if (!priv->rng_registered)
82835a3bb3dSAaron Sierra 		return;
82935a3bb3dSAaron Sierra 
8309c4a7965SKim Phillips 	hwrng_unregister(&priv->rng);
83135a3bb3dSAaron Sierra 	priv->rng_registered = false;
8329c4a7965SKim Phillips }
8339c4a7965SKim Phillips 
8349c4a7965SKim Phillips /*
8359c4a7965SKim Phillips  * crypto alg
8369c4a7965SKim Phillips  */
8379c4a7965SKim Phillips #define TALITOS_CRA_PRIORITY		3000
8387405c8d7SLEROY Christophe /*
8397405c8d7SLEROY Christophe  * Defines a priority for doing AEAD with descriptors type
8407405c8d7SLEROY Christophe  * HMAC_SNOOP_NO_AFEA (HSNA) instead of type IPSEC_ESP
8417405c8d7SLEROY Christophe  */
8427405c8d7SLEROY Christophe #define TALITOS_CRA_PRIORITY_AEAD_HSNA	(TALITOS_CRA_PRIORITY - 1)
843192125edSChristophe Leroy #ifdef CONFIG_CRYPTO_DEV_TALITOS2
84403d2c511SMartin Hicks #define TALITOS_MAX_KEY_SIZE		(AES_MAX_KEY_SIZE + SHA512_BLOCK_SIZE)
845b8fbdc2bSChristophe Leroy #else
846b8fbdc2bSChristophe Leroy #define TALITOS_MAX_KEY_SIZE		(AES_MAX_KEY_SIZE + SHA256_BLOCK_SIZE)
847b8fbdc2bSChristophe Leroy #endif
8483952f17eSLee Nipper #define TALITOS_MAX_IV_LENGTH		16 /* max of AES_BLOCK_SIZE, DES3_EDE_BLOCK_SIZE */
84970bcaca7SLee Nipper 
8509c4a7965SKim Phillips struct talitos_ctx {
8519c4a7965SKim Phillips 	struct device *dev;
8525228f0f7SKim Phillips 	int ch;
8539c4a7965SKim Phillips 	__be32 desc_hdr_template;
8549c4a7965SKim Phillips 	u8 key[TALITOS_MAX_KEY_SIZE];
85570bcaca7SLee Nipper 	u8 iv[TALITOS_MAX_IV_LENGTH];
8562e13ce08SLEROY Christophe 	dma_addr_t dma_key;
8579c4a7965SKim Phillips 	unsigned int keylen;
8589c4a7965SKim Phillips 	unsigned int enckeylen;
8599c4a7965SKim Phillips 	unsigned int authkeylen;
8609c4a7965SKim Phillips };
8619c4a7965SKim Phillips 
862497f2e6bSLee Nipper #define HASH_MAX_BLOCK_SIZE		SHA512_BLOCK_SIZE
863497f2e6bSLee Nipper #define TALITOS_MDEU_MAX_CONTEXT_SIZE	TALITOS_MDEU_CONTEXT_SIZE_SHA384_SHA512
864497f2e6bSLee Nipper 
865497f2e6bSLee Nipper struct talitos_ahash_req_ctx {
86660f208d7SKim Phillips 	u32 hw_context[TALITOS_MDEU_MAX_CONTEXT_SIZE / sizeof(u32)];
867497f2e6bSLee Nipper 	unsigned int hw_context_size;
8683c0dd190SLEROY Christophe 	u8 buf[2][HASH_MAX_BLOCK_SIZE];
8693c0dd190SLEROY Christophe 	int buf_idx;
87060f208d7SKim Phillips 	unsigned int swinit;
871497f2e6bSLee Nipper 	unsigned int first;
872497f2e6bSLee Nipper 	unsigned int last;
873497f2e6bSLee Nipper 	unsigned int to_hash_later;
87442e8b0d7SHoria Geant? 	unsigned int nbuf;
875497f2e6bSLee Nipper 	struct scatterlist bufsl[2];
876497f2e6bSLee Nipper 	struct scatterlist *psrc;
877497f2e6bSLee Nipper };
878497f2e6bSLee Nipper 
8793639ca84SHoria Geant? struct talitos_export_state {
8803639ca84SHoria Geant? 	u32 hw_context[TALITOS_MDEU_MAX_CONTEXT_SIZE / sizeof(u32)];
8813639ca84SHoria Geant? 	u8 buf[HASH_MAX_BLOCK_SIZE];
8823639ca84SHoria Geant? 	unsigned int swinit;
8833639ca84SHoria Geant? 	unsigned int first;
8843639ca84SHoria Geant? 	unsigned int last;
8853639ca84SHoria Geant? 	unsigned int to_hash_later;
8863639ca84SHoria Geant? 	unsigned int nbuf;
8873639ca84SHoria Geant? };
8883639ca84SHoria Geant? 
aead_setkey(struct crypto_aead * authenc,const u8 * key,unsigned int keylen)88956af8cd4SLee Nipper static int aead_setkey(struct crypto_aead *authenc,
8909c4a7965SKim Phillips 		       const u8 *key, unsigned int keylen)
8919c4a7965SKim Phillips {
8929c4a7965SKim Phillips 	struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
8932e13ce08SLEROY Christophe 	struct device *dev = ctx->dev;
894c306a98dSMathias Krause 	struct crypto_authenc_keys keys;
8959c4a7965SKim Phillips 
896c306a98dSMathias Krause 	if (crypto_authenc_extractkeys(&keys, key, keylen) != 0)
8979c4a7965SKim Phillips 		goto badkey;
8989c4a7965SKim Phillips 
899c306a98dSMathias Krause 	if (keys.authkeylen + keys.enckeylen > TALITOS_MAX_KEY_SIZE)
9009c4a7965SKim Phillips 		goto badkey;
9019c4a7965SKim Phillips 
9022e13ce08SLEROY Christophe 	if (ctx->keylen)
9032e13ce08SLEROY Christophe 		dma_unmap_single(dev, ctx->dma_key, ctx->keylen, DMA_TO_DEVICE);
9042e13ce08SLEROY Christophe 
905c306a98dSMathias Krause 	memcpy(ctx->key, keys.authkey, keys.authkeylen);
906c306a98dSMathias Krause 	memcpy(&ctx->key[keys.authkeylen], keys.enckey, keys.enckeylen);
9079c4a7965SKim Phillips 
908c306a98dSMathias Krause 	ctx->keylen = keys.authkeylen + keys.enckeylen;
909c306a98dSMathias Krause 	ctx->enckeylen = keys.enckeylen;
910c306a98dSMathias Krause 	ctx->authkeylen = keys.authkeylen;
9112e13ce08SLEROY Christophe 	ctx->dma_key = dma_map_single(dev, ctx->key, ctx->keylen,
9122e13ce08SLEROY Christophe 				      DMA_TO_DEVICE);
9139c4a7965SKim Phillips 
9148f0691fcSTudor-Dan Ambarus 	memzero_explicit(&keys, sizeof(keys));
9159c4a7965SKim Phillips 	return 0;
9169c4a7965SKim Phillips 
9179c4a7965SKim Phillips badkey:
9188f0691fcSTudor-Dan Ambarus 	memzero_explicit(&keys, sizeof(keys));
9199c4a7965SKim Phillips 	return -EINVAL;
9209c4a7965SKim Phillips }
9219c4a7965SKim Phillips 
aead_des3_setkey(struct crypto_aead * authenc,const u8 * key,unsigned int keylen)922ef7c5c85SHerbert Xu static int aead_des3_setkey(struct crypto_aead *authenc,
923ef7c5c85SHerbert Xu 			    const u8 *key, unsigned int keylen)
924ef7c5c85SHerbert Xu {
925ef7c5c85SHerbert Xu 	struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
926ef7c5c85SHerbert Xu 	struct device *dev = ctx->dev;
927ef7c5c85SHerbert Xu 	struct crypto_authenc_keys keys;
928ef7c5c85SHerbert Xu 	int err;
929ef7c5c85SHerbert Xu 
930ef7c5c85SHerbert Xu 	err = crypto_authenc_extractkeys(&keys, key, keylen);
931ef7c5c85SHerbert Xu 	if (unlikely(err))
932674f368aSEric Biggers 		goto out;
933ef7c5c85SHerbert Xu 
934ef7c5c85SHerbert Xu 	err = -EINVAL;
935ef7c5c85SHerbert Xu 	if (keys.authkeylen + keys.enckeylen > TALITOS_MAX_KEY_SIZE)
936674f368aSEric Biggers 		goto out;
937ef7c5c85SHerbert Xu 
9389d574ae8SArd Biesheuvel 	err = verify_aead_des3_key(authenc, keys.enckey, keys.enckeylen);
9399d574ae8SArd Biesheuvel 	if (err)
940ef7c5c85SHerbert Xu 		goto out;
941ef7c5c85SHerbert Xu 
942ef7c5c85SHerbert Xu 	if (ctx->keylen)
943ef7c5c85SHerbert Xu 		dma_unmap_single(dev, ctx->dma_key, ctx->keylen, DMA_TO_DEVICE);
944ef7c5c85SHerbert Xu 
945ef7c5c85SHerbert Xu 	memcpy(ctx->key, keys.authkey, keys.authkeylen);
946ef7c5c85SHerbert Xu 	memcpy(&ctx->key[keys.authkeylen], keys.enckey, keys.enckeylen);
947ef7c5c85SHerbert Xu 
948ef7c5c85SHerbert Xu 	ctx->keylen = keys.authkeylen + keys.enckeylen;
949ef7c5c85SHerbert Xu 	ctx->enckeylen = keys.enckeylen;
950ef7c5c85SHerbert Xu 	ctx->authkeylen = keys.authkeylen;
951ef7c5c85SHerbert Xu 	ctx->dma_key = dma_map_single(dev, ctx->key, ctx->keylen,
952ef7c5c85SHerbert Xu 				      DMA_TO_DEVICE);
953ef7c5c85SHerbert Xu 
954ef7c5c85SHerbert Xu out:
955ef7c5c85SHerbert Xu 	memzero_explicit(&keys, sizeof(keys));
956ef7c5c85SHerbert Xu 	return err;
957ef7c5c85SHerbert Xu }
958ef7c5c85SHerbert Xu 
talitos_sg_unmap(struct device * dev,struct talitos_edesc * edesc,struct scatterlist * src,struct scatterlist * dst,unsigned int len,unsigned int offset)9594de9d0b5SLee Nipper static void talitos_sg_unmap(struct device *dev,
9604de9d0b5SLee Nipper 			     struct talitos_edesc *edesc,
9614de9d0b5SLee Nipper 			     struct scatterlist *src,
9626a1e8d14SLEROY Christophe 			     struct scatterlist *dst,
9636a1e8d14SLEROY Christophe 			     unsigned int len, unsigned int offset)
964246a87cdSLEROY Christophe {
965246a87cdSLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
966246a87cdSLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
9676a1e8d14SLEROY Christophe 	unsigned int src_nents = edesc->src_nents ? : 1;
9686a1e8d14SLEROY Christophe 	unsigned int dst_nents = edesc->dst_nents ? : 1;
969246a87cdSLEROY Christophe 
9706a1e8d14SLEROY Christophe 	if (is_sec1 && dst && dst_nents > 1) {
9716a1e8d14SLEROY Christophe 		dma_sync_single_for_device(dev, edesc->dma_link_tbl + offset,
972246a87cdSLEROY Christophe 					   len, DMA_FROM_DEVICE);
9736a1e8d14SLEROY Christophe 		sg_pcopy_from_buffer(dst, dst_nents, edesc->buf + offset, len,
9746a1e8d14SLEROY Christophe 				     offset);
975246a87cdSLEROY Christophe 	}
9766a1e8d14SLEROY Christophe 	if (src != dst) {
9776a1e8d14SLEROY Christophe 		if (src_nents == 1 || !is_sec1)
9786a1e8d14SLEROY Christophe 			dma_unmap_sg(dev, src, src_nents, DMA_TO_DEVICE);
9796a1e8d14SLEROY Christophe 
9806a1e8d14SLEROY Christophe 		if (dst && (dst_nents == 1 || !is_sec1))
9816a1e8d14SLEROY Christophe 			dma_unmap_sg(dev, dst, dst_nents, DMA_FROM_DEVICE);
9826a1e8d14SLEROY Christophe 	} else if (src_nents == 1 || !is_sec1) {
9836a1e8d14SLEROY Christophe 		dma_unmap_sg(dev, src, src_nents, DMA_BIDIRECTIONAL);
984246a87cdSLEROY Christophe 	}
985246a87cdSLEROY Christophe }
986246a87cdSLEROY Christophe 
ipsec_esp_unmap(struct device * dev,struct talitos_edesc * edesc,struct aead_request * areq,bool encrypt)9879c4a7965SKim Phillips static void ipsec_esp_unmap(struct device *dev,
98856af8cd4SLee Nipper 			    struct talitos_edesc *edesc,
9897ede4c36SChristophe Leroy 			    struct aead_request *areq, bool encrypt)
9909c4a7965SKim Phillips {
991549bd8bcSLEROY Christophe 	struct crypto_aead *aead = crypto_aead_reqtfm(areq);
992549bd8bcSLEROY Christophe 	struct talitos_ctx *ctx = crypto_aead_ctx(aead);
993549bd8bcSLEROY Christophe 	unsigned int ivsize = crypto_aead_ivsize(aead);
9947ede4c36SChristophe Leroy 	unsigned int authsize = crypto_aead_authsize(aead);
9957ede4c36SChristophe Leroy 	unsigned int cryptlen = areq->cryptlen - (encrypt ? 0 : authsize);
9969a655608SLEROY Christophe 	bool is_ipsec_esp = edesc->desc.hdr & DESC_HDR_TYPE_IPSEC_ESP;
9979a655608SLEROY Christophe 	struct talitos_ptr *civ_ptr = &edesc->desc.ptr[is_ipsec_esp ? 2 : 3];
998549bd8bcSLEROY Christophe 
9999a655608SLEROY Christophe 	if (is_ipsec_esp)
1000549bd8bcSLEROY Christophe 		unmap_single_talitos_ptr(dev, &edesc->desc.ptr[6],
1001549bd8bcSLEROY Christophe 					 DMA_FROM_DEVICE);
10029a655608SLEROY Christophe 	unmap_single_talitos_ptr(dev, civ_ptr, DMA_TO_DEVICE);
10039c4a7965SKim Phillips 
1004e345177dSChristophe Leroy 	talitos_sg_unmap(dev, edesc, areq->src, areq->dst,
1005e345177dSChristophe Leroy 			 cryptlen + authsize, areq->assoclen);
10069c4a7965SKim Phillips 
10079c4a7965SKim Phillips 	if (edesc->dma_len)
10089c4a7965SKim Phillips 		dma_unmap_single(dev, edesc->dma_link_tbl, edesc->dma_len,
10099c4a7965SKim Phillips 				 DMA_BIDIRECTIONAL);
1010549bd8bcSLEROY Christophe 
10119a655608SLEROY Christophe 	if (!is_ipsec_esp) {
1012549bd8bcSLEROY Christophe 		unsigned int dst_nents = edesc->dst_nents ? : 1;
1013549bd8bcSLEROY Christophe 
1014549bd8bcSLEROY Christophe 		sg_pcopy_to_buffer(areq->dst, dst_nents, ctx->iv, ivsize,
10157ede4c36SChristophe Leroy 				   areq->assoclen + cryptlen - ivsize);
1016549bd8bcSLEROY Christophe 	}
10179c4a7965SKim Phillips }
10189c4a7965SKim Phillips 
10199c4a7965SKim Phillips /*
10209c4a7965SKim Phillips  * ipsec_esp descriptor callbacks
10219c4a7965SKim Phillips  */
ipsec_esp_encrypt_done(struct device * dev,struct talitos_desc * desc,void * context,int err)10229c4a7965SKim Phillips static void ipsec_esp_encrypt_done(struct device *dev,
10239c4a7965SKim Phillips 				   struct talitos_desc *desc, void *context,
10249c4a7965SKim Phillips 				   int err)
10259c4a7965SKim Phillips {
10269c4a7965SKim Phillips 	struct aead_request *areq = context;
10279c4a7965SKim Phillips 	struct crypto_aead *authenc = crypto_aead_reqtfm(areq);
10282e13ce08SLEROY Christophe 	unsigned int ivsize = crypto_aead_ivsize(authenc);
102919bbbc63SKim Phillips 	struct talitos_edesc *edesc;
10309c4a7965SKim Phillips 
103119bbbc63SKim Phillips 	edesc = container_of(desc, struct talitos_edesc, desc);
103219bbbc63SKim Phillips 
10337ede4c36SChristophe Leroy 	ipsec_esp_unmap(dev, edesc, areq, true);
10349c4a7965SKim Phillips 
10352e13ce08SLEROY Christophe 	dma_unmap_single(dev, edesc->iv_dma, ivsize, DMA_TO_DEVICE);
10362e13ce08SLEROY Christophe 
10379c4a7965SKim Phillips 	kfree(edesc);
10389c4a7965SKim Phillips 
10399c4a7965SKim Phillips 	aead_request_complete(areq, err);
10409c4a7965SKim Phillips }
10419c4a7965SKim Phillips 
ipsec_esp_decrypt_swauth_done(struct device * dev,struct talitos_desc * desc,void * context,int err)1042fe5720e2SKim Phillips static void ipsec_esp_decrypt_swauth_done(struct device *dev,
1043e938e465SKim Phillips 					  struct talitos_desc *desc,
1044e938e465SKim Phillips 					  void *context, int err)
10459c4a7965SKim Phillips {
10469c4a7965SKim Phillips 	struct aead_request *req = context;
10479c4a7965SKim Phillips 	struct crypto_aead *authenc = crypto_aead_reqtfm(req);
1048aeb4c132SHerbert Xu 	unsigned int authsize = crypto_aead_authsize(authenc);
104919bbbc63SKim Phillips 	struct talitos_edesc *edesc;
1050aeb4c132SHerbert Xu 	char *oicv, *icv;
10519c4a7965SKim Phillips 
105219bbbc63SKim Phillips 	edesc = container_of(desc, struct talitos_edesc, desc);
105319bbbc63SKim Phillips 
10547ede4c36SChristophe Leroy 	ipsec_esp_unmap(dev, edesc, req, false);
10559c4a7965SKim Phillips 
10569c4a7965SKim Phillips 	if (!err) {
10579c4a7965SKim Phillips 		/* auth check */
1058e345177dSChristophe Leroy 		oicv = edesc->buf + edesc->dma_len;
1059e345177dSChristophe Leroy 		icv = oicv - authsize;
1060aeb4c132SHerbert Xu 
106179960943SDavid Gstir 		err = crypto_memneq(oicv, icv, authsize) ? -EBADMSG : 0;
10629c4a7965SKim Phillips 	}
10639c4a7965SKim Phillips 
10649c4a7965SKim Phillips 	kfree(edesc);
10659c4a7965SKim Phillips 
10669c4a7965SKim Phillips 	aead_request_complete(req, err);
10679c4a7965SKim Phillips }
10689c4a7965SKim Phillips 
ipsec_esp_decrypt_hwauth_done(struct device * dev,struct talitos_desc * desc,void * context,int err)1069fe5720e2SKim Phillips static void ipsec_esp_decrypt_hwauth_done(struct device *dev,
1070e938e465SKim Phillips 					  struct talitos_desc *desc,
1071e938e465SKim Phillips 					  void *context, int err)
1072fe5720e2SKim Phillips {
1073fe5720e2SKim Phillips 	struct aead_request *req = context;
107419bbbc63SKim Phillips 	struct talitos_edesc *edesc;
107519bbbc63SKim Phillips 
107619bbbc63SKim Phillips 	edesc = container_of(desc, struct talitos_edesc, desc);
1077fe5720e2SKim Phillips 
10787ede4c36SChristophe Leroy 	ipsec_esp_unmap(dev, edesc, req, false);
1079fe5720e2SKim Phillips 
1080fe5720e2SKim Phillips 	/* check ICV auth status */
1081e938e465SKim Phillips 	if (!err && ((desc->hdr_lo & DESC_HDR_LO_ICCR1_MASK) !=
1082e938e465SKim Phillips 		     DESC_HDR_LO_ICCR1_PASS))
1083fe5720e2SKim Phillips 		err = -EBADMSG;
1084fe5720e2SKim Phillips 
1085fe5720e2SKim Phillips 	kfree(edesc);
1086fe5720e2SKim Phillips 
1087fe5720e2SKim Phillips 	aead_request_complete(req, err);
1088fe5720e2SKim Phillips }
1089fe5720e2SKim Phillips 
10909c4a7965SKim Phillips /*
10919c4a7965SKim Phillips  * convert scatterlist to SEC h/w link table format
10929c4a7965SKim Phillips  * stop at cryptlen bytes
10939c4a7965SKim Phillips  */
sg_to_link_tbl_offset(struct scatterlist * sg,int sg_count,unsigned int offset,int datalen,int elen,struct talitos_ptr * link_tbl_ptr,int align)1094aeb4c132SHerbert Xu static int sg_to_link_tbl_offset(struct scatterlist *sg, int sg_count,
1095e345177dSChristophe Leroy 				 unsigned int offset, int datalen, int elen,
1096416b8467SChristophe Leroy 				 struct talitos_ptr *link_tbl_ptr, int align)
10979c4a7965SKim Phillips {
1098e345177dSChristophe Leroy 	int n_sg = elen ? sg_count + 1 : sg_count;
1099aeb4c132SHerbert Xu 	int count = 0;
1100e345177dSChristophe Leroy 	int cryptlen = datalen + elen;
1101416b8467SChristophe Leroy 	int padding = ALIGN(cryptlen, align) - cryptlen;
110270bcaca7SLee Nipper 
1103aeb4c132SHerbert Xu 	while (cryptlen && sg && n_sg--) {
1104aeb4c132SHerbert Xu 		unsigned int len = sg_dma_len(sg);
1105aeb4c132SHerbert Xu 
1106aeb4c132SHerbert Xu 		if (offset >= len) {
1107aeb4c132SHerbert Xu 			offset -= len;
1108aeb4c132SHerbert Xu 			goto next;
1109aeb4c132SHerbert Xu 		}
1110aeb4c132SHerbert Xu 
1111aeb4c132SHerbert Xu 		len -= offset;
1112aeb4c132SHerbert Xu 
1113aeb4c132SHerbert Xu 		if (len > cryptlen)
1114aeb4c132SHerbert Xu 			len = cryptlen;
1115aeb4c132SHerbert Xu 
1116e345177dSChristophe Leroy 		if (datalen > 0 && len > datalen) {
1117e345177dSChristophe Leroy 			to_talitos_ptr(link_tbl_ptr + count,
1118e345177dSChristophe Leroy 				       sg_dma_address(sg) + offset, datalen, 0);
1119e345177dSChristophe Leroy 			to_talitos_ptr_ext_set(link_tbl_ptr + count, 0, 0);
1120e345177dSChristophe Leroy 			count++;
1121e345177dSChristophe Leroy 			len -= datalen;
1122e345177dSChristophe Leroy 			offset += datalen;
1123e345177dSChristophe Leroy 		}
1124aeb4c132SHerbert Xu 		to_talitos_ptr(link_tbl_ptr + count,
1125416b8467SChristophe Leroy 			       sg_dma_address(sg) + offset, sg_next(sg) ? len : len + padding, 0);
1126b096b544SLEROY Christophe 		to_talitos_ptr_ext_set(link_tbl_ptr + count, 0, 0);
1127aeb4c132SHerbert Xu 		count++;
1128aeb4c132SHerbert Xu 		cryptlen -= len;
1129e345177dSChristophe Leroy 		datalen -= len;
1130aeb4c132SHerbert Xu 		offset = 0;
1131aeb4c132SHerbert Xu 
1132aeb4c132SHerbert Xu next:
11335be4d4c9SCristian Stoica 		sg = sg_next(sg);
11349c4a7965SKim Phillips 	}
11359c4a7965SKim Phillips 
11369c4a7965SKim Phillips 	/* tag end of link table */
1137aeb4c132SHerbert Xu 	if (count > 0)
1138b096b544SLEROY Christophe 		to_talitos_ptr_ext_set(link_tbl_ptr + count - 1,
1139e345177dSChristophe Leroy 				       DESC_PTR_LNKTBL_RET, 0);
114070bcaca7SLee Nipper 
1141aeb4c132SHerbert Xu 	return count;
1142aeb4c132SHerbert Xu }
1143aeb4c132SHerbert Xu 
talitos_sg_map_ext(struct device * dev,struct scatterlist * src,unsigned int len,struct talitos_edesc * edesc,struct talitos_ptr * ptr,int sg_count,unsigned int offset,int tbl_off,int elen,bool force,int align)11442b122730SLEROY Christophe static int talitos_sg_map_ext(struct device *dev, struct scatterlist *src,
1145246a87cdSLEROY Christophe 			      unsigned int len, struct talitos_edesc *edesc,
11462b122730SLEROY Christophe 			      struct talitos_ptr *ptr, int sg_count,
1147e345177dSChristophe Leroy 			      unsigned int offset, int tbl_off, int elen,
1148416b8467SChristophe Leroy 			      bool force, int align)
1149246a87cdSLEROY Christophe {
1150246a87cdSLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
1151246a87cdSLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
1152416b8467SChristophe Leroy 	int aligned_len = ALIGN(len, align);
1153246a87cdSLEROY Christophe 
115487a81dceSLEROY Christophe 	if (!src) {
115587a81dceSLEROY Christophe 		to_talitos_ptr(ptr, 0, 0, is_sec1);
115687a81dceSLEROY Christophe 		return 1;
115787a81dceSLEROY Christophe 	}
11582b122730SLEROY Christophe 	to_talitos_ptr_ext_set(ptr, elen, is_sec1);
1159e345177dSChristophe Leroy 	if (sg_count == 1 && !force) {
1160416b8467SChristophe Leroy 		to_talitos_ptr(ptr, sg_dma_address(src) + offset, aligned_len, is_sec1);
1161246a87cdSLEROY Christophe 		return sg_count;
1162246a87cdSLEROY Christophe 	}
1163246a87cdSLEROY Christophe 	if (is_sec1) {
1164416b8467SChristophe Leroy 		to_talitos_ptr(ptr, edesc->dma_link_tbl + offset, aligned_len, is_sec1);
11656a1e8d14SLEROY Christophe 		return sg_count;
1166246a87cdSLEROY Christophe 	}
1167e345177dSChristophe Leroy 	sg_count = sg_to_link_tbl_offset(src, sg_count, offset, len, elen,
1168416b8467SChristophe Leroy 					 &edesc->link_tbl[tbl_off], align);
1169e345177dSChristophe Leroy 	if (sg_count == 1 && !force) {
11706a1e8d14SLEROY Christophe 		/* Only one segment now, so no link tbl needed*/
11716a1e8d14SLEROY Christophe 		copy_talitos_ptr(ptr, &edesc->link_tbl[tbl_off], is_sec1);
11726a1e8d14SLEROY Christophe 		return sg_count;
11736a1e8d14SLEROY Christophe 	}
1174246a87cdSLEROY Christophe 	to_talitos_ptr(ptr, edesc->dma_link_tbl +
1175416b8467SChristophe Leroy 			    tbl_off * sizeof(struct talitos_ptr), aligned_len, is_sec1);
11766a1e8d14SLEROY Christophe 	to_talitos_ptr_ext_or(ptr, DESC_PTR_LNKTBL_JUMP, is_sec1);
11776a1e8d14SLEROY Christophe 
11786a1e8d14SLEROY Christophe 	return sg_count;
1179246a87cdSLEROY Christophe }
1180246a87cdSLEROY Christophe 
talitos_sg_map(struct device * dev,struct scatterlist * src,unsigned int len,struct talitos_edesc * edesc,struct talitos_ptr * ptr,int sg_count,unsigned int offset,int tbl_off)11812b122730SLEROY Christophe static int talitos_sg_map(struct device *dev, struct scatterlist *src,
11822b122730SLEROY Christophe 			  unsigned int len, struct talitos_edesc *edesc,
11832b122730SLEROY Christophe 			  struct talitos_ptr *ptr, int sg_count,
11842b122730SLEROY Christophe 			  unsigned int offset, int tbl_off)
11852b122730SLEROY Christophe {
11862b122730SLEROY Christophe 	return talitos_sg_map_ext(dev, src, len, edesc, ptr, sg_count, offset,
1187416b8467SChristophe Leroy 				  tbl_off, 0, false, 1);
11882b122730SLEROY Christophe }
11892b122730SLEROY Christophe 
11909c4a7965SKim Phillips /*
11919c4a7965SKim Phillips  * fill in and submit ipsec_esp descriptor
11929c4a7965SKim Phillips  */
ipsec_esp(struct talitos_edesc * edesc,struct aead_request * areq,bool encrypt,void (* callback)(struct device * dev,struct talitos_desc * desc,void * context,int error))119356af8cd4SLee Nipper static int ipsec_esp(struct talitos_edesc *edesc, struct aead_request *areq,
11947ede4c36SChristophe Leroy 		     bool encrypt,
1195aeb4c132SHerbert Xu 		     void (*callback)(struct device *dev,
11969c4a7965SKim Phillips 				      struct talitos_desc *desc,
11979c4a7965SKim Phillips 				      void *context, int error))
11989c4a7965SKim Phillips {
11999c4a7965SKim Phillips 	struct crypto_aead *aead = crypto_aead_reqtfm(areq);
1200aeb4c132SHerbert Xu 	unsigned int authsize = crypto_aead_authsize(aead);
12019c4a7965SKim Phillips 	struct talitos_ctx *ctx = crypto_aead_ctx(aead);
12029c4a7965SKim Phillips 	struct device *dev = ctx->dev;
12039c4a7965SKim Phillips 	struct talitos_desc *desc = &edesc->desc;
12047ede4c36SChristophe Leroy 	unsigned int cryptlen = areq->cryptlen - (encrypt ? 0 : authsize);
1205e41256f1SKim Phillips 	unsigned int ivsize = crypto_aead_ivsize(aead);
1206aeb4c132SHerbert Xu 	int tbl_off = 0;
1207fa86a267SKim Phillips 	int sg_count, ret;
12082b122730SLEROY Christophe 	int elen = 0;
1209549bd8bcSLEROY Christophe 	bool sync_needed = false;
1210549bd8bcSLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
1211549bd8bcSLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
12129a655608SLEROY Christophe 	bool is_ipsec_esp = desc->hdr & DESC_HDR_TYPE_IPSEC_ESP;
12139a655608SLEROY Christophe 	struct talitos_ptr *civ_ptr = &desc->ptr[is_ipsec_esp ? 2 : 3];
12149a655608SLEROY Christophe 	struct talitos_ptr *ckey_ptr = &desc->ptr[is_ipsec_esp ? 3 : 2];
1215e345177dSChristophe Leroy 	dma_addr_t dma_icv = edesc->dma_link_tbl + edesc->dma_len - authsize;
12169c4a7965SKim Phillips 
12179c4a7965SKim Phillips 	/* hmac key */
12182e13ce08SLEROY Christophe 	to_talitos_ptr(&desc->ptr[0], ctx->dma_key, ctx->authkeylen, is_sec1);
121979fd31d3SHoria Geanta 
1220549bd8bcSLEROY Christophe 	sg_count = edesc->src_nents ?: 1;
1221549bd8bcSLEROY Christophe 	if (is_sec1 && sg_count > 1)
1222549bd8bcSLEROY Christophe 		sg_copy_to_buffer(areq->src, sg_count, edesc->buf,
1223549bd8bcSLEROY Christophe 				  areq->assoclen + cryptlen);
1224549bd8bcSLEROY Christophe 	else
1225549bd8bcSLEROY Christophe 		sg_count = dma_map_sg(dev, areq->src, sg_count,
1226549bd8bcSLEROY Christophe 				      (areq->src == areq->dst) ?
1227549bd8bcSLEROY Christophe 				      DMA_BIDIRECTIONAL : DMA_TO_DEVICE);
1228549bd8bcSLEROY Christophe 
12299c4a7965SKim Phillips 	/* hmac data */
1230549bd8bcSLEROY Christophe 	ret = talitos_sg_map(dev, areq->src, areq->assoclen, edesc,
1231549bd8bcSLEROY Christophe 			     &desc->ptr[1], sg_count, 0, tbl_off);
123279fd31d3SHoria Geanta 
1233549bd8bcSLEROY Christophe 	if (ret > 1) {
1234340ff60aSHoria Geant? 		tbl_off += ret;
1235549bd8bcSLEROY Christophe 		sync_needed = true;
123679fd31d3SHoria Geanta 	}
123779fd31d3SHoria Geanta 
12389c4a7965SKim Phillips 	/* cipher iv */
12399a655608SLEROY Christophe 	to_talitos_ptr(civ_ptr, edesc->iv_dma, ivsize, is_sec1);
12409c4a7965SKim Phillips 
12419c4a7965SKim Phillips 	/* cipher key */
12422e13ce08SLEROY Christophe 	to_talitos_ptr(ckey_ptr, ctx->dma_key  + ctx->authkeylen,
12432e13ce08SLEROY Christophe 		       ctx->enckeylen, is_sec1);
12449c4a7965SKim Phillips 
12459c4a7965SKim Phillips 	/*
12469c4a7965SKim Phillips 	 * cipher in
12479c4a7965SKim Phillips 	 * map and adjust cipher len to aead request cryptlen.
12489c4a7965SKim Phillips 	 * extent is bytes of HMAC postpended to ciphertext,
12499c4a7965SKim Phillips 	 * typically 12 for ipsec
12509c4a7965SKim Phillips 	 */
12512b122730SLEROY Christophe 	if (is_ipsec_esp && (desc->hdr & DESC_HDR_MODE1_MDEU_CICV))
12522b122730SLEROY Christophe 		elen = authsize;
1253549bd8bcSLEROY Christophe 
12542b122730SLEROY Christophe 	ret = talitos_sg_map_ext(dev, areq->src, cryptlen, edesc, &desc->ptr[4],
1255e345177dSChristophe Leroy 				 sg_count, areq->assoclen, tbl_off, elen,
1256416b8467SChristophe Leroy 				 false, 1);
1257549bd8bcSLEROY Christophe 
1258ec8c7d14SLEROY Christophe 	if (ret > 1) {
1259ec8c7d14SLEROY Christophe 		tbl_off += ret;
1260549bd8bcSLEROY Christophe 		sync_needed = true;
1261340ff60aSHoria Geant? 	}
12629c4a7965SKim Phillips 
12639c4a7965SKim Phillips 	/* cipher out */
1264549bd8bcSLEROY Christophe 	if (areq->src != areq->dst) {
1265549bd8bcSLEROY Christophe 		sg_count = edesc->dst_nents ? : 1;
1266549bd8bcSLEROY Christophe 		if (!is_sec1 || sg_count == 1)
1267549bd8bcSLEROY Christophe 			dma_map_sg(dev, areq->dst, sg_count, DMA_FROM_DEVICE);
1268549bd8bcSLEROY Christophe 	}
12699c4a7965SKim Phillips 
1270e345177dSChristophe Leroy 	if (is_ipsec_esp && encrypt)
1271e345177dSChristophe Leroy 		elen = authsize;
1272e345177dSChristophe Leroy 	else
1273e345177dSChristophe Leroy 		elen = 0;
1274e345177dSChristophe Leroy 	ret = talitos_sg_map_ext(dev, areq->dst, cryptlen, edesc, &desc->ptr[5],
1275e345177dSChristophe Leroy 				 sg_count, areq->assoclen, tbl_off, elen,
1276416b8467SChristophe Leroy 				 is_ipsec_esp && !encrypt, 1);
1277e04a61beSLEROY Christophe 	tbl_off += ret;
1278549bd8bcSLEROY Christophe 
1279e345177dSChristophe Leroy 	if (!encrypt && is_ipsec_esp) {
128079fd31d3SHoria Geanta 		struct talitos_ptr *tbl_ptr = &edesc->link_tbl[tbl_off];
1281fe5720e2SKim Phillips 
1282f3c85bc1SLee Nipper 		/* Add an entry to the link table for ICV data */
1283e04a61beSLEROY Christophe 		to_talitos_ptr_ext_set(tbl_ptr - 1, 0, is_sec1);
1284e345177dSChristophe Leroy 		to_talitos_ptr_ext_set(tbl_ptr, DESC_PTR_LNKTBL_RET, is_sec1);
12859c4a7965SKim Phillips 
12869c4a7965SKim Phillips 		/* icv data follows link tables */
1287e345177dSChristophe Leroy 		to_talitos_ptr(tbl_ptr, dma_icv, authsize, is_sec1);
1288e345177dSChristophe Leroy 		to_talitos_ptr_ext_or(&desc->ptr[5], authsize, is_sec1);
1289e04a61beSLEROY Christophe 		sync_needed = true;
1290e345177dSChristophe Leroy 	} else if (!encrypt) {
1291e345177dSChristophe Leroy 		to_talitos_ptr(&desc->ptr[6], dma_icv, authsize, is_sec1);
1292e345177dSChristophe Leroy 		sync_needed = true;
1293e345177dSChristophe Leroy 	} else if (!is_ipsec_esp) {
1294e345177dSChristophe Leroy 		talitos_sg_map(dev, areq->dst, authsize, edesc, &desc->ptr[6],
1295e345177dSChristophe Leroy 			       sg_count, areq->assoclen + cryptlen, tbl_off);
1296340ff60aSHoria Geant? 	}
12979c4a7965SKim Phillips 
12989c4a7965SKim Phillips 	/* iv out */
12999a655608SLEROY Christophe 	if (is_ipsec_esp)
1300a2b35aa8SLEROY Christophe 		map_single_talitos_ptr(dev, &desc->ptr[6], ivsize, ctx->iv,
13019c4a7965SKim Phillips 				       DMA_FROM_DEVICE);
13029c4a7965SKim Phillips 
1303549bd8bcSLEROY Christophe 	if (sync_needed)
1304549bd8bcSLEROY Christophe 		dma_sync_single_for_device(dev, edesc->dma_link_tbl,
1305549bd8bcSLEROY Christophe 					   edesc->dma_len,
1306549bd8bcSLEROY Christophe 					   DMA_BIDIRECTIONAL);
1307549bd8bcSLEROY Christophe 
13085228f0f7SKim Phillips 	ret = talitos_submit(dev, ctx->ch, desc, callback, areq);
1309fa86a267SKim Phillips 	if (ret != -EINPROGRESS) {
13107ede4c36SChristophe Leroy 		ipsec_esp_unmap(dev, edesc, areq, encrypt);
1311fa86a267SKim Phillips 		kfree(edesc);
1312fa86a267SKim Phillips 	}
1313fa86a267SKim Phillips 	return ret;
13149c4a7965SKim Phillips }
13159c4a7965SKim Phillips 
13169c4a7965SKim Phillips /*
131756af8cd4SLee Nipper  * allocate and map the extended descriptor
13189c4a7965SKim Phillips  */
talitos_edesc_alloc(struct device * dev,struct scatterlist * src,struct scatterlist * dst,u8 * iv,unsigned int assoclen,unsigned int cryptlen,unsigned int authsize,unsigned int ivsize,int icv_stashing,u32 cryptoflags,bool encrypt)13194de9d0b5SLee Nipper static struct talitos_edesc *talitos_edesc_alloc(struct device *dev,
13204de9d0b5SLee Nipper 						 struct scatterlist *src,
13214de9d0b5SLee Nipper 						 struct scatterlist *dst,
132279fd31d3SHoria Geanta 						 u8 *iv,
132379fd31d3SHoria Geanta 						 unsigned int assoclen,
13244de9d0b5SLee Nipper 						 unsigned int cryptlen,
13254de9d0b5SLee Nipper 						 unsigned int authsize,
132679fd31d3SHoria Geanta 						 unsigned int ivsize,
13274de9d0b5SLee Nipper 						 int icv_stashing,
132862293a37SHoria Geanta 						 u32 cryptoflags,
132962293a37SHoria Geanta 						 bool encrypt)
13309c4a7965SKim Phillips {
133156af8cd4SLee Nipper 	struct talitos_edesc *edesc;
13326a1e8d14SLEROY Christophe 	int src_nents, dst_nents, alloc_len, dma_len, src_len, dst_len;
133379fd31d3SHoria Geanta 	dma_addr_t iv_dma = 0;
13344de9d0b5SLee Nipper 	gfp_t flags = cryptoflags & CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL :
1335586725f8SKim Phillips 		      GFP_ATOMIC;
13366f65f6acSLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
13376f65f6acSLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
13386f65f6acSLEROY Christophe 	int max_len = is_sec1 ? TALITOS1_MAX_DATA_LEN : TALITOS2_MAX_DATA_LEN;
13399c4a7965SKim Phillips 
13406f65f6acSLEROY Christophe 	if (cryptlen + authsize > max_len) {
13414de9d0b5SLee Nipper 		dev_err(dev, "length exceeds h/w max limit\n");
13429c4a7965SKim Phillips 		return ERR_PTR(-EINVAL);
13439c4a7965SKim Phillips 	}
13449c4a7965SKim Phillips 
134562293a37SHoria Geanta 	if (!dst || dst == src) {
13466a1e8d14SLEROY Christophe 		src_len = assoclen + cryptlen + authsize;
13476a1e8d14SLEROY Christophe 		src_nents = sg_nents_for_len(src, src_len);
13488e409fe1SLABBE Corentin 		if (src_nents < 0) {
13498e409fe1SLABBE Corentin 			dev_err(dev, "Invalid number of src SG.\n");
1350c56c2e17SChristophe Leroy 			return ERR_PTR(-EINVAL);
13518e409fe1SLABBE Corentin 		}
13529c4a7965SKim Phillips 		src_nents = (src_nents == 1) ? 0 : src_nents;
135362293a37SHoria Geanta 		dst_nents = dst ? src_nents : 0;
13546a1e8d14SLEROY Christophe 		dst_len = 0;
135562293a37SHoria Geanta 	} else { /* dst && dst != src*/
13566a1e8d14SLEROY Christophe 		src_len = assoclen + cryptlen + (encrypt ? 0 : authsize);
13576a1e8d14SLEROY Christophe 		src_nents = sg_nents_for_len(src, src_len);
13588e409fe1SLABBE Corentin 		if (src_nents < 0) {
13598e409fe1SLABBE Corentin 			dev_err(dev, "Invalid number of src SG.\n");
1360c56c2e17SChristophe Leroy 			return ERR_PTR(-EINVAL);
13618e409fe1SLABBE Corentin 		}
136262293a37SHoria Geanta 		src_nents = (src_nents == 1) ? 0 : src_nents;
13636a1e8d14SLEROY Christophe 		dst_len = assoclen + cryptlen + (encrypt ? authsize : 0);
13646a1e8d14SLEROY Christophe 		dst_nents = sg_nents_for_len(dst, dst_len);
13658e409fe1SLABBE Corentin 		if (dst_nents < 0) {
13668e409fe1SLABBE Corentin 			dev_err(dev, "Invalid number of dst SG.\n");
1367c56c2e17SChristophe Leroy 			return ERR_PTR(-EINVAL);
13688e409fe1SLABBE Corentin 		}
1369695ad589SLee Nipper 		dst_nents = (dst_nents == 1) ? 0 : dst_nents;
13709c4a7965SKim Phillips 	}
13719c4a7965SKim Phillips 
13729c4a7965SKim Phillips 	/*
13739c4a7965SKim Phillips 	 * allocate space for base edesc plus the link tables,
1374aeb4c132SHerbert Xu 	 * allowing for two separate entries for AD and generated ICV (+ 2),
1375aeb4c132SHerbert Xu 	 * and space for two sets of ICVs (stashed and generated)
13769c4a7965SKim Phillips 	 */
137756af8cd4SLee Nipper 	alloc_len = sizeof(struct talitos_edesc);
1378e345177dSChristophe Leroy 	if (src_nents || dst_nents || !encrypt) {
13796f65f6acSLEROY Christophe 		if (is_sec1)
13806a1e8d14SLEROY Christophe 			dma_len = (src_nents ? src_len : 0) +
1381e345177dSChristophe Leroy 				  (dst_nents ? dst_len : 0) + authsize;
13826f65f6acSLEROY Christophe 		else
1383aeb4c132SHerbert Xu 			dma_len = (src_nents + dst_nents + 2) *
1384e345177dSChristophe Leroy 				  sizeof(struct talitos_ptr) + authsize;
13859c4a7965SKim Phillips 		alloc_len += dma_len;
13869c4a7965SKim Phillips 	} else {
13879c4a7965SKim Phillips 		dma_len = 0;
13889c4a7965SKim Phillips 	}
1389e345177dSChristophe Leroy 	alloc_len += icv_stashing ? authsize : 0;
13909c4a7965SKim Phillips 
139137b5e889SLEROY Christophe 	/* if its a ahash, add space for a second desc next to the first one */
139237b5e889SLEROY Christophe 	if (is_sec1 && !dst)
139337b5e889SLEROY Christophe 		alloc_len += sizeof(struct talitos_desc);
13941bea445bSChristophe Leroy 	alloc_len += ivsize;
139537b5e889SLEROY Christophe 
13968e613cecSHerbert Xu 	edesc = kmalloc(ALIGN(alloc_len, dma_get_cache_alignment()), flags);
1397c56c2e17SChristophe Leroy 	if (!edesc)
1398c56c2e17SChristophe Leroy 		return ERR_PTR(-ENOMEM);
13991bea445bSChristophe Leroy 	if (ivsize) {
14001bea445bSChristophe Leroy 		iv = memcpy(((u8 *)edesc) + alloc_len - ivsize, iv, ivsize);
1401c56c2e17SChristophe Leroy 		iv_dma = dma_map_single(dev, iv, ivsize, DMA_TO_DEVICE);
14021bea445bSChristophe Leroy 	}
1403e4a647c4SLEROY Christophe 	memset(&edesc->desc, 0, sizeof(edesc->desc));
14049c4a7965SKim Phillips 
14059c4a7965SKim Phillips 	edesc->src_nents = src_nents;
14069c4a7965SKim Phillips 	edesc->dst_nents = dst_nents;
140779fd31d3SHoria Geanta 	edesc->iv_dma = iv_dma;
14089c4a7965SKim Phillips 	edesc->dma_len = dma_len;
140958cdbc6dSChristophe Leroy 	if (dma_len)
141058cdbc6dSChristophe Leroy 		edesc->dma_link_tbl = dma_map_single(dev, &edesc->link_tbl[0],
1411497f2e6bSLee Nipper 						     edesc->dma_len,
1412497f2e6bSLee Nipper 						     DMA_BIDIRECTIONAL);
141358cdbc6dSChristophe Leroy 
14149c4a7965SKim Phillips 	return edesc;
14159c4a7965SKim Phillips }
14169c4a7965SKim Phillips 
aead_edesc_alloc(struct aead_request * areq,u8 * iv,int icv_stashing,bool encrypt)141779fd31d3SHoria Geanta static struct talitos_edesc *aead_edesc_alloc(struct aead_request *areq, u8 *iv,
141862293a37SHoria Geanta 					      int icv_stashing, bool encrypt)
14194de9d0b5SLee Nipper {
14204de9d0b5SLee Nipper 	struct crypto_aead *authenc = crypto_aead_reqtfm(areq);
1421aeb4c132SHerbert Xu 	unsigned int authsize = crypto_aead_authsize(authenc);
14224de9d0b5SLee Nipper 	struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
142379fd31d3SHoria Geanta 	unsigned int ivsize = crypto_aead_ivsize(authenc);
14247ede4c36SChristophe Leroy 	unsigned int cryptlen = areq->cryptlen - (encrypt ? 0 : authsize);
14254de9d0b5SLee Nipper 
1426aeb4c132SHerbert Xu 	return talitos_edesc_alloc(ctx->dev, areq->src, areq->dst,
14277ede4c36SChristophe Leroy 				   iv, areq->assoclen, cryptlen,
1428aeb4c132SHerbert Xu 				   authsize, ivsize, icv_stashing,
142962293a37SHoria Geanta 				   areq->base.flags, encrypt);
14304de9d0b5SLee Nipper }
14314de9d0b5SLee Nipper 
aead_encrypt(struct aead_request * req)143256af8cd4SLee Nipper static int aead_encrypt(struct aead_request *req)
14339c4a7965SKim Phillips {
14349c4a7965SKim Phillips 	struct crypto_aead *authenc = crypto_aead_reqtfm(req);
14359c4a7965SKim Phillips 	struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
143656af8cd4SLee Nipper 	struct talitos_edesc *edesc;
14379c4a7965SKim Phillips 
14389c4a7965SKim Phillips 	/* allocate extended descriptor */
143962293a37SHoria Geanta 	edesc = aead_edesc_alloc(req, req->iv, 0, true);
14409c4a7965SKim Phillips 	if (IS_ERR(edesc))
14419c4a7965SKim Phillips 		return PTR_ERR(edesc);
14429c4a7965SKim Phillips 
14439c4a7965SKim Phillips 	/* set encrypt */
144470bcaca7SLee Nipper 	edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_MODE0_ENCRYPT;
14459c4a7965SKim Phillips 
14467ede4c36SChristophe Leroy 	return ipsec_esp(edesc, req, true, ipsec_esp_encrypt_done);
14479c4a7965SKim Phillips }
14489c4a7965SKim Phillips 
aead_decrypt(struct aead_request * req)144956af8cd4SLee Nipper static int aead_decrypt(struct aead_request *req)
14509c4a7965SKim Phillips {
14519c4a7965SKim Phillips 	struct crypto_aead *authenc = crypto_aead_reqtfm(req);
1452aeb4c132SHerbert Xu 	unsigned int authsize = crypto_aead_authsize(authenc);
14539c4a7965SKim Phillips 	struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
1454fe5720e2SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(ctx->dev);
145556af8cd4SLee Nipper 	struct talitos_edesc *edesc;
14569c4a7965SKim Phillips 	void *icvdata;
14579c4a7965SKim Phillips 
14589c4a7965SKim Phillips 	/* allocate extended descriptor */
145962293a37SHoria Geanta 	edesc = aead_edesc_alloc(req, req->iv, 1, false);
14609c4a7965SKim Phillips 	if (IS_ERR(edesc))
14619c4a7965SKim Phillips 		return PTR_ERR(edesc);
14629c4a7965SKim Phillips 
14634bbfb839SChristophe Leroy 	if ((edesc->desc.hdr & DESC_HDR_TYPE_IPSEC_ESP) &&
14644bbfb839SChristophe Leroy 	    (priv->features & TALITOS_FTR_HW_AUTH_CHECK) &&
1465e938e465SKim Phillips 	    ((!edesc->src_nents && !edesc->dst_nents) ||
1466e938e465SKim Phillips 	     priv->features & TALITOS_FTR_SRC_LINK_TBL_LEN_INCLUDES_EXTENT)) {
1467fe5720e2SKim Phillips 
1468fe5720e2SKim Phillips 		/* decrypt and check the ICV */
1469e938e465SKim Phillips 		edesc->desc.hdr = ctx->desc_hdr_template |
1470e938e465SKim Phillips 				  DESC_HDR_DIR_INBOUND |
1471fe5720e2SKim Phillips 				  DESC_HDR_MODE1_MDEU_CICV;
1472fe5720e2SKim Phillips 
1473fe5720e2SKim Phillips 		/* reset integrity check result bits */
1474fe5720e2SKim Phillips 
14757ede4c36SChristophe Leroy 		return ipsec_esp(edesc, req, false,
14767ede4c36SChristophe Leroy 				 ipsec_esp_decrypt_hwauth_done);
1477e938e465SKim Phillips 	}
1478fe5720e2SKim Phillips 
1479fe5720e2SKim Phillips 	/* Have to check the ICV with software */
1480fe5720e2SKim Phillips 	edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_DIR_INBOUND;
1481fe5720e2SKim Phillips 
14829c4a7965SKim Phillips 	/* stash incoming ICV for later cmp with ICV generated by the h/w */
1483e345177dSChristophe Leroy 	icvdata = edesc->buf + edesc->dma_len;
14849c4a7965SKim Phillips 
1485eae55a58SChristophe Leroy 	sg_pcopy_to_buffer(req->src, edesc->src_nents ? : 1, icvdata, authsize,
1486eae55a58SChristophe Leroy 			   req->assoclen + req->cryptlen - authsize);
14879c4a7965SKim Phillips 
14887ede4c36SChristophe Leroy 	return ipsec_esp(edesc, req, false, ipsec_esp_decrypt_swauth_done);
14899c4a7965SKim Phillips }
14909c4a7965SKim Phillips 
skcipher_setkey(struct crypto_skcipher * cipher,const u8 * key,unsigned int keylen)1491373960d7SArd Biesheuvel static int skcipher_setkey(struct crypto_skcipher *cipher,
14924de9d0b5SLee Nipper 			     const u8 *key, unsigned int keylen)
14934de9d0b5SLee Nipper {
1494373960d7SArd Biesheuvel 	struct talitos_ctx *ctx = crypto_skcipher_ctx(cipher);
14952e13ce08SLEROY Christophe 	struct device *dev = ctx->dev;
1496f384cdc4SLEROY Christophe 
14972e13ce08SLEROY Christophe 	if (ctx->keylen)
14982e13ce08SLEROY Christophe 		dma_unmap_single(dev, ctx->dma_key, ctx->keylen, DMA_TO_DEVICE);
14992e13ce08SLEROY Christophe 
15004de9d0b5SLee Nipper 	memcpy(&ctx->key, key, keylen);
15014de9d0b5SLee Nipper 	ctx->keylen = keylen;
15024de9d0b5SLee Nipper 
15032e13ce08SLEROY Christophe 	ctx->dma_key = dma_map_single(dev, ctx->key, keylen, DMA_TO_DEVICE);
15042e13ce08SLEROY Christophe 
15054de9d0b5SLee Nipper 	return 0;
15064de9d0b5SLee Nipper }
15074de9d0b5SLee Nipper 
skcipher_des_setkey(struct crypto_skcipher * cipher,const u8 * key,unsigned int keylen)1508373960d7SArd Biesheuvel static int skcipher_des_setkey(struct crypto_skcipher *cipher,
1509ef7c5c85SHerbert Xu 				 const u8 *key, unsigned int keylen)
1510ef7c5c85SHerbert Xu {
1511373960d7SArd Biesheuvel 	return verify_skcipher_des_key(cipher, key) ?:
1512373960d7SArd Biesheuvel 	       skcipher_setkey(cipher, key, keylen);
1513ef7c5c85SHerbert Xu }
1514ef7c5c85SHerbert Xu 
skcipher_des3_setkey(struct crypto_skcipher * cipher,const u8 * key,unsigned int keylen)1515373960d7SArd Biesheuvel static int skcipher_des3_setkey(struct crypto_skcipher *cipher,
1516ef7c5c85SHerbert Xu 				  const u8 *key, unsigned int keylen)
1517ef7c5c85SHerbert Xu {
1518373960d7SArd Biesheuvel 	return verify_skcipher_des3_key(cipher, key) ?:
1519373960d7SArd Biesheuvel 	       skcipher_setkey(cipher, key, keylen);
1520ef7c5c85SHerbert Xu }
1521ef7c5c85SHerbert Xu 
skcipher_aes_setkey(struct crypto_skcipher * cipher,const u8 * key,unsigned int keylen)1522373960d7SArd Biesheuvel static int skcipher_aes_setkey(struct crypto_skcipher *cipher,
15231ba34e71SChristophe Leroy 				  const u8 *key, unsigned int keylen)
15241ba34e71SChristophe Leroy {
15251ba34e71SChristophe Leroy 	if (keylen == AES_KEYSIZE_128 || keylen == AES_KEYSIZE_192 ||
15261ba34e71SChristophe Leroy 	    keylen == AES_KEYSIZE_256)
1527373960d7SArd Biesheuvel 		return skcipher_setkey(cipher, key, keylen);
15281ba34e71SChristophe Leroy 
15291ba34e71SChristophe Leroy 	return -EINVAL;
15301ba34e71SChristophe Leroy }
15311ba34e71SChristophe Leroy 
common_nonsnoop_unmap(struct device * dev,struct talitos_edesc * edesc,struct skcipher_request * areq)15324de9d0b5SLee Nipper static void common_nonsnoop_unmap(struct device *dev,
15334de9d0b5SLee Nipper 				  struct talitos_edesc *edesc,
1534373960d7SArd Biesheuvel 				  struct skcipher_request *areq)
15354de9d0b5SLee Nipper {
15364de9d0b5SLee Nipper 	unmap_single_talitos_ptr(dev, &edesc->desc.ptr[5], DMA_FROM_DEVICE);
1537032d197eSLEROY Christophe 
1538373960d7SArd Biesheuvel 	talitos_sg_unmap(dev, edesc, areq->src, areq->dst, areq->cryptlen, 0);
15394de9d0b5SLee Nipper 	unmap_single_talitos_ptr(dev, &edesc->desc.ptr[1], DMA_TO_DEVICE);
15404de9d0b5SLee Nipper 
15414de9d0b5SLee Nipper 	if (edesc->dma_len)
15424de9d0b5SLee Nipper 		dma_unmap_single(dev, edesc->dma_link_tbl, edesc->dma_len,
15434de9d0b5SLee Nipper 				 DMA_BIDIRECTIONAL);
15444de9d0b5SLee Nipper }
15454de9d0b5SLee Nipper 
skcipher_done(struct device * dev,struct talitos_desc * desc,void * context,int err)1546373960d7SArd Biesheuvel static void skcipher_done(struct device *dev,
15474de9d0b5SLee Nipper 			    struct talitos_desc *desc, void *context,
15484de9d0b5SLee Nipper 			    int err)
15494de9d0b5SLee Nipper {
1550373960d7SArd Biesheuvel 	struct skcipher_request *areq = context;
1551373960d7SArd Biesheuvel 	struct crypto_skcipher *cipher = crypto_skcipher_reqtfm(areq);
1552373960d7SArd Biesheuvel 	struct talitos_ctx *ctx = crypto_skcipher_ctx(cipher);
1553373960d7SArd Biesheuvel 	unsigned int ivsize = crypto_skcipher_ivsize(cipher);
155419bbbc63SKim Phillips 	struct talitos_edesc *edesc;
155519bbbc63SKim Phillips 
155619bbbc63SKim Phillips 	edesc = container_of(desc, struct talitos_edesc, desc);
15574de9d0b5SLee Nipper 
15584de9d0b5SLee Nipper 	common_nonsnoop_unmap(dev, edesc, areq);
1559373960d7SArd Biesheuvel 	memcpy(areq->iv, ctx->iv, ivsize);
15604de9d0b5SLee Nipper 
15614de9d0b5SLee Nipper 	kfree(edesc);
15624de9d0b5SLee Nipper 
1563234650bdSHerbert Xu 	skcipher_request_complete(areq, err);
15644de9d0b5SLee Nipper }
15654de9d0b5SLee Nipper 
common_nonsnoop(struct talitos_edesc * edesc,struct skcipher_request * areq,void (* callback)(struct device * dev,struct talitos_desc * desc,void * context,int error))15664de9d0b5SLee Nipper static int common_nonsnoop(struct talitos_edesc *edesc,
1567373960d7SArd Biesheuvel 			   struct skcipher_request *areq,
15684de9d0b5SLee Nipper 			   void (*callback) (struct device *dev,
15694de9d0b5SLee Nipper 					     struct talitos_desc *desc,
15704de9d0b5SLee Nipper 					     void *context, int error))
15714de9d0b5SLee Nipper {
1572373960d7SArd Biesheuvel 	struct crypto_skcipher *cipher = crypto_skcipher_reqtfm(areq);
1573373960d7SArd Biesheuvel 	struct talitos_ctx *ctx = crypto_skcipher_ctx(cipher);
15744de9d0b5SLee Nipper 	struct device *dev = ctx->dev;
15754de9d0b5SLee Nipper 	struct talitos_desc *desc = &edesc->desc;
1576373960d7SArd Biesheuvel 	unsigned int cryptlen = areq->cryptlen;
1577373960d7SArd Biesheuvel 	unsigned int ivsize = crypto_skcipher_ivsize(cipher);
15784de9d0b5SLee Nipper 	int sg_count, ret;
15796a1e8d14SLEROY Christophe 	bool sync_needed = false;
1580922f9dc8SLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
1581922f9dc8SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
1582416b8467SChristophe Leroy 	bool is_ctr = (desc->hdr & DESC_HDR_SEL0_MASK) == DESC_HDR_SEL0_AESU &&
1583416b8467SChristophe Leroy 		      (desc->hdr & DESC_HDR_MODE0_AESU_MASK) == DESC_HDR_MODE0_AESU_CTR;
15844de9d0b5SLee Nipper 
15854de9d0b5SLee Nipper 	/* first DWORD empty */
15864de9d0b5SLee Nipper 
15874de9d0b5SLee Nipper 	/* cipher iv */
1588da9de146SLEROY Christophe 	to_talitos_ptr(&desc->ptr[1], edesc->iv_dma, ivsize, is_sec1);
15894de9d0b5SLee Nipper 
15904de9d0b5SLee Nipper 	/* cipher key */
15912e13ce08SLEROY Christophe 	to_talitos_ptr(&desc->ptr[2], ctx->dma_key, ctx->keylen, is_sec1);
15924de9d0b5SLee Nipper 
15936a1e8d14SLEROY Christophe 	sg_count = edesc->src_nents ?: 1;
15946a1e8d14SLEROY Christophe 	if (is_sec1 && sg_count > 1)
15956a1e8d14SLEROY Christophe 		sg_copy_to_buffer(areq->src, sg_count, edesc->buf,
15966a1e8d14SLEROY Christophe 				  cryptlen);
15976a1e8d14SLEROY Christophe 	else
15986a1e8d14SLEROY Christophe 		sg_count = dma_map_sg(dev, areq->src, sg_count,
15996a1e8d14SLEROY Christophe 				      (areq->src == areq->dst) ?
16006a1e8d14SLEROY Christophe 				      DMA_BIDIRECTIONAL : DMA_TO_DEVICE);
16014de9d0b5SLee Nipper 	/*
16024de9d0b5SLee Nipper 	 * cipher in
16034de9d0b5SLee Nipper 	 */
1604416b8467SChristophe Leroy 	sg_count = talitos_sg_map_ext(dev, areq->src, cryptlen, edesc, &desc->ptr[3],
1605416b8467SChristophe Leroy 				      sg_count, 0, 0, 0, false, is_ctr ? 16 : 1);
16066a1e8d14SLEROY Christophe 	if (sg_count > 1)
16076a1e8d14SLEROY Christophe 		sync_needed = true;
16084de9d0b5SLee Nipper 
16094de9d0b5SLee Nipper 	/* cipher out */
16106a1e8d14SLEROY Christophe 	if (areq->src != areq->dst) {
16116a1e8d14SLEROY Christophe 		sg_count = edesc->dst_nents ? : 1;
16126a1e8d14SLEROY Christophe 		if (!is_sec1 || sg_count == 1)
16136a1e8d14SLEROY Christophe 			dma_map_sg(dev, areq->dst, sg_count, DMA_FROM_DEVICE);
16146a1e8d14SLEROY Christophe 	}
16156a1e8d14SLEROY Christophe 
16166a1e8d14SLEROY Christophe 	ret = talitos_sg_map(dev, areq->dst, cryptlen, edesc, &desc->ptr[4],
16176a1e8d14SLEROY Christophe 			     sg_count, 0, (edesc->src_nents + 1));
16186a1e8d14SLEROY Christophe 	if (ret > 1)
16196a1e8d14SLEROY Christophe 		sync_needed = true;
16204de9d0b5SLee Nipper 
16214de9d0b5SLee Nipper 	/* iv out */
1622a2b35aa8SLEROY Christophe 	map_single_talitos_ptr(dev, &desc->ptr[5], ivsize, ctx->iv,
16234de9d0b5SLee Nipper 			       DMA_FROM_DEVICE);
16244de9d0b5SLee Nipper 
16254de9d0b5SLee Nipper 	/* last DWORD empty */
16264de9d0b5SLee Nipper 
16276a1e8d14SLEROY Christophe 	if (sync_needed)
16286a1e8d14SLEROY Christophe 		dma_sync_single_for_device(dev, edesc->dma_link_tbl,
16296a1e8d14SLEROY Christophe 					   edesc->dma_len, DMA_BIDIRECTIONAL);
16306a1e8d14SLEROY Christophe 
16315228f0f7SKim Phillips 	ret = talitos_submit(dev, ctx->ch, desc, callback, areq);
16324de9d0b5SLee Nipper 	if (ret != -EINPROGRESS) {
16334de9d0b5SLee Nipper 		common_nonsnoop_unmap(dev, edesc, areq);
16344de9d0b5SLee Nipper 		kfree(edesc);
16354de9d0b5SLee Nipper 	}
16364de9d0b5SLee Nipper 	return ret;
16374de9d0b5SLee Nipper }
16384de9d0b5SLee Nipper 
skcipher_edesc_alloc(struct skcipher_request * areq,bool encrypt)1639373960d7SArd Biesheuvel static struct talitos_edesc *skcipher_edesc_alloc(struct skcipher_request *
164062293a37SHoria Geanta 						    areq, bool encrypt)
16414de9d0b5SLee Nipper {
1642373960d7SArd Biesheuvel 	struct crypto_skcipher *cipher = crypto_skcipher_reqtfm(areq);
1643373960d7SArd Biesheuvel 	struct talitos_ctx *ctx = crypto_skcipher_ctx(cipher);
1644373960d7SArd Biesheuvel 	unsigned int ivsize = crypto_skcipher_ivsize(cipher);
16454de9d0b5SLee Nipper 
1646aeb4c132SHerbert Xu 	return talitos_edesc_alloc(ctx->dev, areq->src, areq->dst,
1647373960d7SArd Biesheuvel 				   areq->iv, 0, areq->cryptlen, 0, ivsize, 0,
164862293a37SHoria Geanta 				   areq->base.flags, encrypt);
16494de9d0b5SLee Nipper }
16504de9d0b5SLee Nipper 
skcipher_encrypt(struct skcipher_request * areq)1651373960d7SArd Biesheuvel static int skcipher_encrypt(struct skcipher_request *areq)
16524de9d0b5SLee Nipper {
1653373960d7SArd Biesheuvel 	struct crypto_skcipher *cipher = crypto_skcipher_reqtfm(areq);
1654373960d7SArd Biesheuvel 	struct talitos_ctx *ctx = crypto_skcipher_ctx(cipher);
16554de9d0b5SLee Nipper 	struct talitos_edesc *edesc;
1656ee483d32SChristophe Leroy 	unsigned int blocksize =
1657373960d7SArd Biesheuvel 			crypto_tfm_alg_blocksize(crypto_skcipher_tfm(cipher));
1658ee483d32SChristophe Leroy 
1659373960d7SArd Biesheuvel 	if (!areq->cryptlen)
1660ee483d32SChristophe Leroy 		return 0;
1661ee483d32SChristophe Leroy 
1662373960d7SArd Biesheuvel 	if (areq->cryptlen % blocksize)
1663ee483d32SChristophe Leroy 		return -EINVAL;
16644de9d0b5SLee Nipper 
16654de9d0b5SLee Nipper 	/* allocate extended descriptor */
1666373960d7SArd Biesheuvel 	edesc = skcipher_edesc_alloc(areq, true);
16674de9d0b5SLee Nipper 	if (IS_ERR(edesc))
16684de9d0b5SLee Nipper 		return PTR_ERR(edesc);
16694de9d0b5SLee Nipper 
16704de9d0b5SLee Nipper 	/* set encrypt */
16714de9d0b5SLee Nipper 	edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_MODE0_ENCRYPT;
16724de9d0b5SLee Nipper 
1673373960d7SArd Biesheuvel 	return common_nonsnoop(edesc, areq, skcipher_done);
16744de9d0b5SLee Nipper }
16754de9d0b5SLee Nipper 
skcipher_decrypt(struct skcipher_request * areq)1676373960d7SArd Biesheuvel static int skcipher_decrypt(struct skcipher_request *areq)
16774de9d0b5SLee Nipper {
1678373960d7SArd Biesheuvel 	struct crypto_skcipher *cipher = crypto_skcipher_reqtfm(areq);
1679373960d7SArd Biesheuvel 	struct talitos_ctx *ctx = crypto_skcipher_ctx(cipher);
16804de9d0b5SLee Nipper 	struct talitos_edesc *edesc;
1681ee483d32SChristophe Leroy 	unsigned int blocksize =
1682373960d7SArd Biesheuvel 			crypto_tfm_alg_blocksize(crypto_skcipher_tfm(cipher));
1683ee483d32SChristophe Leroy 
1684373960d7SArd Biesheuvel 	if (!areq->cryptlen)
1685ee483d32SChristophe Leroy 		return 0;
1686ee483d32SChristophe Leroy 
1687373960d7SArd Biesheuvel 	if (areq->cryptlen % blocksize)
1688ee483d32SChristophe Leroy 		return -EINVAL;
16894de9d0b5SLee Nipper 
16904de9d0b5SLee Nipper 	/* allocate extended descriptor */
1691373960d7SArd Biesheuvel 	edesc = skcipher_edesc_alloc(areq, false);
16924de9d0b5SLee Nipper 	if (IS_ERR(edesc))
16934de9d0b5SLee Nipper 		return PTR_ERR(edesc);
16944de9d0b5SLee Nipper 
16954de9d0b5SLee Nipper 	edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_DIR_INBOUND;
16964de9d0b5SLee Nipper 
1697373960d7SArd Biesheuvel 	return common_nonsnoop(edesc, areq, skcipher_done);
16984de9d0b5SLee Nipper }
16994de9d0b5SLee Nipper 
common_nonsnoop_hash_unmap(struct device * dev,struct talitos_edesc * edesc,struct ahash_request * areq)1700497f2e6bSLee Nipper static void common_nonsnoop_hash_unmap(struct device *dev,
1701497f2e6bSLee Nipper 				       struct talitos_edesc *edesc,
1702497f2e6bSLee Nipper 				       struct ahash_request *areq)
1703497f2e6bSLee Nipper {
1704497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
17057a6eda5bSChristophe Leroy 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
1706ad4cd51fSLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
1707ad4cd51fSLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
1708ad4cd51fSLEROY Christophe 	struct talitos_desc *desc = &edesc->desc;
170958cdbc6dSChristophe Leroy 	struct talitos_desc *desc2 = (struct talitos_desc *)
171058cdbc6dSChristophe Leroy 				     (edesc->buf + edesc->dma_len);
1711ad4cd51fSLEROY Christophe 
17126ae7a8b1Sjianchunfu 	unmap_single_talitos_ptr(dev, &desc->ptr[5], DMA_FROM_DEVICE);
1713ad4cd51fSLEROY Christophe 	if (desc->next_desc &&
1714ad4cd51fSLEROY Christophe 	    desc->ptr[5].ptr != desc2->ptr[5].ptr)
1715ad4cd51fSLEROY Christophe 		unmap_single_talitos_ptr(dev, &desc2->ptr[5], DMA_FROM_DEVICE);
17167a6eda5bSChristophe Leroy 	if (req_ctx->last)
17177a6eda5bSChristophe Leroy 		memcpy(areq->result, req_ctx->hw_context,
17187a6eda5bSChristophe Leroy 		       crypto_ahash_digestsize(tfm));
1719497f2e6bSLee Nipper 
172058cdbc6dSChristophe Leroy 	if (req_ctx->psrc)
17216a1e8d14SLEROY Christophe 		talitos_sg_unmap(dev, edesc, req_ctx->psrc, NULL, 0, 0);
1722032d197eSLEROY Christophe 
1723ad4cd51fSLEROY Christophe 	/* When using hashctx-in, must unmap it. */
17246ae7a8b1Sjianchunfu 	if (from_talitos_ptr_len(&desc->ptr[1], is_sec1))
17256ae7a8b1Sjianchunfu 		unmap_single_talitos_ptr(dev, &desc->ptr[1],
1726ad4cd51fSLEROY Christophe 					 DMA_TO_DEVICE);
1727ad4cd51fSLEROY Christophe 	else if (desc->next_desc)
1728ad4cd51fSLEROY Christophe 		unmap_single_talitos_ptr(dev, &desc2->ptr[1],
1729ad4cd51fSLEROY Christophe 					 DMA_TO_DEVICE);
1730ad4cd51fSLEROY Christophe 
1731ad4cd51fSLEROY Christophe 	if (is_sec1 && req_ctx->nbuf)
1732ad4cd51fSLEROY Christophe 		unmap_single_talitos_ptr(dev, &desc->ptr[3],
1733ad4cd51fSLEROY Christophe 					 DMA_TO_DEVICE);
1734ad4cd51fSLEROY Christophe 
1735497f2e6bSLee Nipper 	if (edesc->dma_len)
1736497f2e6bSLee Nipper 		dma_unmap_single(dev, edesc->dma_link_tbl, edesc->dma_len,
1737497f2e6bSLee Nipper 				 DMA_BIDIRECTIONAL);
1738497f2e6bSLee Nipper 
17396ae7a8b1Sjianchunfu 	if (desc->next_desc)
17406ae7a8b1Sjianchunfu 		dma_unmap_single(dev, be32_to_cpu(desc->next_desc),
174137b5e889SLEROY Christophe 				 TALITOS_DESC_SIZE, DMA_BIDIRECTIONAL);
1742497f2e6bSLee Nipper }
1743497f2e6bSLee Nipper 
ahash_done(struct device * dev,struct talitos_desc * desc,void * context,int err)1744497f2e6bSLee Nipper static void ahash_done(struct device *dev,
1745497f2e6bSLee Nipper 		       struct talitos_desc *desc, void *context,
1746497f2e6bSLee Nipper 		       int err)
1747497f2e6bSLee Nipper {
1748497f2e6bSLee Nipper 	struct ahash_request *areq = context;
1749497f2e6bSLee Nipper 	struct talitos_edesc *edesc =
1750497f2e6bSLee Nipper 		 container_of(desc, struct talitos_edesc, desc);
1751497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
1752497f2e6bSLee Nipper 
1753497f2e6bSLee Nipper 	if (!req_ctx->last && req_ctx->to_hash_later) {
1754497f2e6bSLee Nipper 		/* Position any partial block for next update/final/finup */
17553c0dd190SLEROY Christophe 		req_ctx->buf_idx = (req_ctx->buf_idx + 1) & 1;
17565e833bc4SLee Nipper 		req_ctx->nbuf = req_ctx->to_hash_later;
1757497f2e6bSLee Nipper 	}
1758497f2e6bSLee Nipper 	common_nonsnoop_hash_unmap(dev, edesc, areq);
1759497f2e6bSLee Nipper 
1760497f2e6bSLee Nipper 	kfree(edesc);
1761497f2e6bSLee Nipper 
1762234650bdSHerbert Xu 	ahash_request_complete(areq, err);
1763497f2e6bSLee Nipper }
1764497f2e6bSLee Nipper 
17652d02905eSLEROY Christophe /*
17662d02905eSLEROY Christophe  * SEC1 doesn't like hashing of 0 sized message, so we do the padding
17672d02905eSLEROY Christophe  * ourself and submit a padded block
17682d02905eSLEROY Christophe  */
talitos_handle_buggy_hash(struct talitos_ctx * ctx,struct talitos_edesc * edesc,struct talitos_ptr * ptr)17695b2cf268SLEROY Christophe static void talitos_handle_buggy_hash(struct talitos_ctx *ctx,
17702d02905eSLEROY Christophe 			       struct talitos_edesc *edesc,
17712d02905eSLEROY Christophe 			       struct talitos_ptr *ptr)
17722d02905eSLEROY Christophe {
17732d02905eSLEROY Christophe 	static u8 padded_hash[64] = {
17742d02905eSLEROY Christophe 		0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
17752d02905eSLEROY Christophe 		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
17762d02905eSLEROY Christophe 		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
17772d02905eSLEROY Christophe 		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
17782d02905eSLEROY Christophe 	};
17792d02905eSLEROY Christophe 
17802d02905eSLEROY Christophe 	pr_err_once("Bug in SEC1, padding ourself\n");
17812d02905eSLEROY Christophe 	edesc->desc.hdr &= ~DESC_HDR_MODE0_MDEU_PAD;
17822d02905eSLEROY Christophe 	map_single_talitos_ptr(ctx->dev, ptr, sizeof(padded_hash),
17832d02905eSLEROY Christophe 			       (char *)padded_hash, DMA_TO_DEVICE);
17842d02905eSLEROY Christophe }
17852d02905eSLEROY Christophe 
common_nonsnoop_hash(struct talitos_edesc * edesc,struct ahash_request * areq,unsigned int length,void (* callback)(struct device * dev,struct talitos_desc * desc,void * context,int error))1786497f2e6bSLee Nipper static int common_nonsnoop_hash(struct talitos_edesc *edesc,
1787497f2e6bSLee Nipper 				struct ahash_request *areq, unsigned int length,
1788497f2e6bSLee Nipper 				void (*callback) (struct device *dev,
1789497f2e6bSLee Nipper 						  struct talitos_desc *desc,
1790497f2e6bSLee Nipper 						  void *context, int error))
1791497f2e6bSLee Nipper {
1792497f2e6bSLee Nipper 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
1793497f2e6bSLee Nipper 	struct talitos_ctx *ctx = crypto_ahash_ctx(tfm);
1794497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
1795497f2e6bSLee Nipper 	struct device *dev = ctx->dev;
1796497f2e6bSLee Nipper 	struct talitos_desc *desc = &edesc->desc;
1797032d197eSLEROY Christophe 	int ret;
17986a1e8d14SLEROY Christophe 	bool sync_needed = false;
1799922f9dc8SLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
1800922f9dc8SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
18016a1e8d14SLEROY Christophe 	int sg_count;
1802497f2e6bSLee Nipper 
1803497f2e6bSLee Nipper 	/* first DWORD empty */
1804497f2e6bSLee Nipper 
180560f208d7SKim Phillips 	/* hash context in */
180660f208d7SKim Phillips 	if (!req_ctx->first || req_ctx->swinit) {
18076a4967c3SLEROY Christophe 		map_single_talitos_ptr_nosync(dev, &desc->ptr[1],
1808ad4cd51fSLEROY Christophe 					      req_ctx->hw_context_size,
18096a4967c3SLEROY Christophe 					      req_ctx->hw_context,
1810ad4cd51fSLEROY Christophe 					      DMA_TO_DEVICE);
181160f208d7SKim Phillips 		req_ctx->swinit = 0;
1812afd62fa2SLEROY Christophe 	}
1813497f2e6bSLee Nipper 	/* Indicate next op is not the first. */
1814497f2e6bSLee Nipper 	req_ctx->first = 0;
1815497f2e6bSLee Nipper 
1816497f2e6bSLee Nipper 	/* HMAC key */
1817497f2e6bSLee Nipper 	if (ctx->keylen)
18182e13ce08SLEROY Christophe 		to_talitos_ptr(&desc->ptr[2], ctx->dma_key, ctx->keylen,
18192e13ce08SLEROY Christophe 			       is_sec1);
1820497f2e6bSLee Nipper 
182137b5e889SLEROY Christophe 	if (is_sec1 && req_ctx->nbuf)
182237b5e889SLEROY Christophe 		length -= req_ctx->nbuf;
182337b5e889SLEROY Christophe 
18246a1e8d14SLEROY Christophe 	sg_count = edesc->src_nents ?: 1;
18256a1e8d14SLEROY Christophe 	if (is_sec1 && sg_count > 1)
182658cdbc6dSChristophe Leroy 		sg_copy_to_buffer(req_ctx->psrc, sg_count, edesc->buf, length);
182737b5e889SLEROY Christophe 	else if (length)
18286a1e8d14SLEROY Christophe 		sg_count = dma_map_sg(dev, req_ctx->psrc, sg_count,
18296a1e8d14SLEROY Christophe 				      DMA_TO_DEVICE);
1830497f2e6bSLee Nipper 	/*
1831497f2e6bSLee Nipper 	 * data in
1832497f2e6bSLee Nipper 	 */
183337b5e889SLEROY Christophe 	if (is_sec1 && req_ctx->nbuf) {
1834ad4cd51fSLEROY Christophe 		map_single_talitos_ptr(dev, &desc->ptr[3], req_ctx->nbuf,
1835ad4cd51fSLEROY Christophe 				       req_ctx->buf[req_ctx->buf_idx],
1836ad4cd51fSLEROY Christophe 				       DMA_TO_DEVICE);
183737b5e889SLEROY Christophe 	} else {
18386a1e8d14SLEROY Christophe 		sg_count = talitos_sg_map(dev, req_ctx->psrc, length, edesc,
183958cdbc6dSChristophe Leroy 					  &desc->ptr[3], sg_count, 0, 0);
18406a1e8d14SLEROY Christophe 		if (sg_count > 1)
18416a1e8d14SLEROY Christophe 			sync_needed = true;
184237b5e889SLEROY Christophe 	}
1843497f2e6bSLee Nipper 
1844497f2e6bSLee Nipper 	/* fifth DWORD empty */
1845497f2e6bSLee Nipper 
1846497f2e6bSLee Nipper 	/* hash/HMAC out -or- hash context out */
1847497f2e6bSLee Nipper 	if (req_ctx->last)
1848497f2e6bSLee Nipper 		map_single_talitos_ptr(dev, &desc->ptr[5],
1849497f2e6bSLee Nipper 				       crypto_ahash_digestsize(tfm),
18507a6eda5bSChristophe Leroy 				       req_ctx->hw_context, DMA_FROM_DEVICE);
1851497f2e6bSLee Nipper 	else
18526a4967c3SLEROY Christophe 		map_single_talitos_ptr_nosync(dev, &desc->ptr[5],
1853ad4cd51fSLEROY Christophe 					      req_ctx->hw_context_size,
18546a4967c3SLEROY Christophe 					      req_ctx->hw_context,
18556a4967c3SLEROY Christophe 					      DMA_FROM_DEVICE);
1856497f2e6bSLee Nipper 
1857497f2e6bSLee Nipper 	/* last DWORD empty */
1858497f2e6bSLee Nipper 
18592d02905eSLEROY Christophe 	if (is_sec1 && from_talitos_ptr_len(&desc->ptr[3], true) == 0)
18602d02905eSLEROY Christophe 		talitos_handle_buggy_hash(ctx, edesc, &desc->ptr[3]);
18612d02905eSLEROY Christophe 
186237b5e889SLEROY Christophe 	if (is_sec1 && req_ctx->nbuf && length) {
186358cdbc6dSChristophe Leroy 		struct talitos_desc *desc2 = (struct talitos_desc *)
186458cdbc6dSChristophe Leroy 					     (edesc->buf + edesc->dma_len);
186537b5e889SLEROY Christophe 		dma_addr_t next_desc;
186637b5e889SLEROY Christophe 
186737b5e889SLEROY Christophe 		memset(desc2, 0, sizeof(*desc2));
186837b5e889SLEROY Christophe 		desc2->hdr = desc->hdr;
186937b5e889SLEROY Christophe 		desc2->hdr &= ~DESC_HDR_MODE0_MDEU_INIT;
187037b5e889SLEROY Christophe 		desc2->hdr1 = desc2->hdr;
187137b5e889SLEROY Christophe 		desc->hdr &= ~DESC_HDR_MODE0_MDEU_PAD;
187237b5e889SLEROY Christophe 		desc->hdr |= DESC_HDR_MODE0_MDEU_CONT;
187337b5e889SLEROY Christophe 		desc->hdr &= ~DESC_HDR_DONE_NOTIFY;
187437b5e889SLEROY Christophe 
1875ad4cd51fSLEROY Christophe 		if (desc->ptr[1].ptr)
1876ad4cd51fSLEROY Christophe 			copy_talitos_ptr(&desc2->ptr[1], &desc->ptr[1],
1877ad4cd51fSLEROY Christophe 					 is_sec1);
1878ad4cd51fSLEROY Christophe 		else
18796a4967c3SLEROY Christophe 			map_single_talitos_ptr_nosync(dev, &desc2->ptr[1],
1880ad4cd51fSLEROY Christophe 						      req_ctx->hw_context_size,
1881ad4cd51fSLEROY Christophe 						      req_ctx->hw_context,
1882ad4cd51fSLEROY Christophe 						      DMA_TO_DEVICE);
188337b5e889SLEROY Christophe 		copy_talitos_ptr(&desc2->ptr[2], &desc->ptr[2], is_sec1);
188437b5e889SLEROY Christophe 		sg_count = talitos_sg_map(dev, req_ctx->psrc, length, edesc,
188558cdbc6dSChristophe Leroy 					  &desc2->ptr[3], sg_count, 0, 0);
188637b5e889SLEROY Christophe 		if (sg_count > 1)
188737b5e889SLEROY Christophe 			sync_needed = true;
188837b5e889SLEROY Christophe 		copy_talitos_ptr(&desc2->ptr[5], &desc->ptr[5], is_sec1);
188937b5e889SLEROY Christophe 		if (req_ctx->last)
18906a4967c3SLEROY Christophe 			map_single_talitos_ptr_nosync(dev, &desc->ptr[5],
1891ad4cd51fSLEROY Christophe 						      req_ctx->hw_context_size,
1892ad4cd51fSLEROY Christophe 						      req_ctx->hw_context,
1893ad4cd51fSLEROY Christophe 						      DMA_FROM_DEVICE);
189437b5e889SLEROY Christophe 
189537b5e889SLEROY Christophe 		next_desc = dma_map_single(dev, &desc2->hdr1, TALITOS_DESC_SIZE,
189637b5e889SLEROY Christophe 					   DMA_BIDIRECTIONAL);
189737b5e889SLEROY Christophe 		desc->next_desc = cpu_to_be32(next_desc);
189837b5e889SLEROY Christophe 	}
189937b5e889SLEROY Christophe 
19006a1e8d14SLEROY Christophe 	if (sync_needed)
19016a1e8d14SLEROY Christophe 		dma_sync_single_for_device(dev, edesc->dma_link_tbl,
19026a1e8d14SLEROY Christophe 					   edesc->dma_len, DMA_BIDIRECTIONAL);
19036a1e8d14SLEROY Christophe 
19045228f0f7SKim Phillips 	ret = talitos_submit(dev, ctx->ch, desc, callback, areq);
1905497f2e6bSLee Nipper 	if (ret != -EINPROGRESS) {
1906497f2e6bSLee Nipper 		common_nonsnoop_hash_unmap(dev, edesc, areq);
1907497f2e6bSLee Nipper 		kfree(edesc);
1908497f2e6bSLee Nipper 	}
1909497f2e6bSLee Nipper 	return ret;
1910497f2e6bSLee Nipper }
1911497f2e6bSLee Nipper 
ahash_edesc_alloc(struct ahash_request * areq,unsigned int nbytes)1912497f2e6bSLee Nipper static struct talitos_edesc *ahash_edesc_alloc(struct ahash_request *areq,
1913497f2e6bSLee Nipper 					       unsigned int nbytes)
1914497f2e6bSLee Nipper {
1915497f2e6bSLee Nipper 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
1916497f2e6bSLee Nipper 	struct talitos_ctx *ctx = crypto_ahash_ctx(tfm);
1917497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
191837b5e889SLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(ctx->dev);
191937b5e889SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
192037b5e889SLEROY Christophe 
192137b5e889SLEROY Christophe 	if (is_sec1)
192237b5e889SLEROY Christophe 		nbytes -= req_ctx->nbuf;
1923497f2e6bSLee Nipper 
1924aeb4c132SHerbert Xu 	return talitos_edesc_alloc(ctx->dev, req_ctx->psrc, NULL, NULL, 0,
192562293a37SHoria Geanta 				   nbytes, 0, 0, 0, areq->base.flags, false);
1926497f2e6bSLee Nipper }
1927497f2e6bSLee Nipper 
ahash_init(struct ahash_request * areq)1928497f2e6bSLee Nipper static int ahash_init(struct ahash_request *areq)
1929497f2e6bSLee Nipper {
1930497f2e6bSLee Nipper 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
19316a4967c3SLEROY Christophe 	struct talitos_ctx *ctx = crypto_ahash_ctx(tfm);
19326a4967c3SLEROY Christophe 	struct device *dev = ctx->dev;
1933497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
193449f9783bSLEROY Christophe 	unsigned int size;
19356a4967c3SLEROY Christophe 	dma_addr_t dma;
1936497f2e6bSLee Nipper 
1937497f2e6bSLee Nipper 	/* Initialize the context */
19383c0dd190SLEROY Christophe 	req_ctx->buf_idx = 0;
19395e833bc4SLee Nipper 	req_ctx->nbuf = 0;
194060f208d7SKim Phillips 	req_ctx->first = 1; /* first indicates h/w must init its context */
194160f208d7SKim Phillips 	req_ctx->swinit = 0; /* assume h/w init of context */
194249f9783bSLEROY Christophe 	size =	(crypto_ahash_digestsize(tfm) <= SHA256_DIGEST_SIZE)
1943497f2e6bSLee Nipper 			? TALITOS_MDEU_CONTEXT_SIZE_MD5_SHA1_SHA256
1944497f2e6bSLee Nipper 			: TALITOS_MDEU_CONTEXT_SIZE_SHA384_SHA512;
194549f9783bSLEROY Christophe 	req_ctx->hw_context_size = size;
1946497f2e6bSLee Nipper 
19476a4967c3SLEROY Christophe 	dma = dma_map_single(dev, req_ctx->hw_context, req_ctx->hw_context_size,
19486a4967c3SLEROY Christophe 			     DMA_TO_DEVICE);
19496a4967c3SLEROY Christophe 	dma_unmap_single(dev, dma, req_ctx->hw_context_size, DMA_TO_DEVICE);
19506a4967c3SLEROY Christophe 
1951497f2e6bSLee Nipper 	return 0;
1952497f2e6bSLee Nipper }
1953497f2e6bSLee Nipper 
195460f208d7SKim Phillips /*
195560f208d7SKim Phillips  * on h/w without explicit sha224 support, we initialize h/w context
195660f208d7SKim Phillips  * manually with sha224 constants, and tell it to run sha256.
195760f208d7SKim Phillips  */
ahash_init_sha224_swinit(struct ahash_request * areq)195860f208d7SKim Phillips static int ahash_init_sha224_swinit(struct ahash_request *areq)
195960f208d7SKim Phillips {
196060f208d7SKim Phillips 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
196160f208d7SKim Phillips 
1962a752447aSKim Phillips 	req_ctx->hw_context[0] = SHA224_H0;
1963a752447aSKim Phillips 	req_ctx->hw_context[1] = SHA224_H1;
1964a752447aSKim Phillips 	req_ctx->hw_context[2] = SHA224_H2;
1965a752447aSKim Phillips 	req_ctx->hw_context[3] = SHA224_H3;
1966a752447aSKim Phillips 	req_ctx->hw_context[4] = SHA224_H4;
1967a752447aSKim Phillips 	req_ctx->hw_context[5] = SHA224_H5;
1968a752447aSKim Phillips 	req_ctx->hw_context[6] = SHA224_H6;
1969a752447aSKim Phillips 	req_ctx->hw_context[7] = SHA224_H7;
197060f208d7SKim Phillips 
197160f208d7SKim Phillips 	/* init 64-bit count */
197260f208d7SKim Phillips 	req_ctx->hw_context[8] = 0;
197360f208d7SKim Phillips 	req_ctx->hw_context[9] = 0;
197460f208d7SKim Phillips 
19756a4967c3SLEROY Christophe 	ahash_init(areq);
19766a4967c3SLEROY Christophe 	req_ctx->swinit = 1;/* prevent h/w initting context with sha256 values*/
19776a4967c3SLEROY Christophe 
197860f208d7SKim Phillips 	return 0;
197960f208d7SKim Phillips }
198060f208d7SKim Phillips 
ahash_process_req(struct ahash_request * areq,unsigned int nbytes)1981497f2e6bSLee Nipper static int ahash_process_req(struct ahash_request *areq, unsigned int nbytes)
1982497f2e6bSLee Nipper {
1983497f2e6bSLee Nipper 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
1984497f2e6bSLee Nipper 	struct talitos_ctx *ctx = crypto_ahash_ctx(tfm);
1985497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
1986497f2e6bSLee Nipper 	struct talitos_edesc *edesc;
1987497f2e6bSLee Nipper 	unsigned int blocksize =
1988497f2e6bSLee Nipper 			crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm));
1989497f2e6bSLee Nipper 	unsigned int nbytes_to_hash;
1990497f2e6bSLee Nipper 	unsigned int to_hash_later;
19915e833bc4SLee Nipper 	unsigned int nsg;
19928e409fe1SLABBE Corentin 	int nents;
199337b5e889SLEROY Christophe 	struct device *dev = ctx->dev;
199437b5e889SLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
199537b5e889SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
19963c0dd190SLEROY Christophe 	u8 *ctx_buf = req_ctx->buf[req_ctx->buf_idx];
1997497f2e6bSLee Nipper 
19985e833bc4SLee Nipper 	if (!req_ctx->last && (nbytes + req_ctx->nbuf <= blocksize)) {
19995e833bc4SLee Nipper 		/* Buffer up to one whole block */
20008e409fe1SLABBE Corentin 		nents = sg_nents_for_len(areq->src, nbytes);
20018e409fe1SLABBE Corentin 		if (nents < 0) {
2002854e25a6Sjianchunfu 			dev_err(dev, "Invalid number of src SG.\n");
20038e409fe1SLABBE Corentin 			return nents;
20048e409fe1SLABBE Corentin 		}
20058e409fe1SLABBE Corentin 		sg_copy_to_buffer(areq->src, nents,
20063c0dd190SLEROY Christophe 				  ctx_buf + req_ctx->nbuf, nbytes);
20075e833bc4SLee Nipper 		req_ctx->nbuf += nbytes;
2008497f2e6bSLee Nipper 		return 0;
2009497f2e6bSLee Nipper 	}
2010497f2e6bSLee Nipper 
20115e833bc4SLee Nipper 	/* At least (blocksize + 1) bytes are available to hash */
20125e833bc4SLee Nipper 	nbytes_to_hash = nbytes + req_ctx->nbuf;
20135e833bc4SLee Nipper 	to_hash_later = nbytes_to_hash & (blocksize - 1);
20145e833bc4SLee Nipper 
20155e833bc4SLee Nipper 	if (req_ctx->last)
20165e833bc4SLee Nipper 		to_hash_later = 0;
20175e833bc4SLee Nipper 	else if (to_hash_later)
20185e833bc4SLee Nipper 		/* There is a partial block. Hash the full block(s) now */
20195e833bc4SLee Nipper 		nbytes_to_hash -= to_hash_later;
20205e833bc4SLee Nipper 	else {
20215e833bc4SLee Nipper 		/* Keep one block buffered */
20225e833bc4SLee Nipper 		nbytes_to_hash -= blocksize;
20235e833bc4SLee Nipper 		to_hash_later = blocksize;
2024497f2e6bSLee Nipper 	}
20255e833bc4SLee Nipper 
20265e833bc4SLee Nipper 	/* Chain in any previously buffered data */
202737b5e889SLEROY Christophe 	if (!is_sec1 && req_ctx->nbuf) {
20285e833bc4SLee Nipper 		nsg = (req_ctx->nbuf < nbytes_to_hash) ? 2 : 1;
20295e833bc4SLee Nipper 		sg_init_table(req_ctx->bufsl, nsg);
20303c0dd190SLEROY Christophe 		sg_set_buf(req_ctx->bufsl, ctx_buf, req_ctx->nbuf);
20315e833bc4SLee Nipper 		if (nsg > 1)
2032c56f6d12SDan Williams 			sg_chain(req_ctx->bufsl, 2, areq->src);
20335e833bc4SLee Nipper 		req_ctx->psrc = req_ctx->bufsl;
203437b5e889SLEROY Christophe 	} else if (is_sec1 && req_ctx->nbuf && req_ctx->nbuf < blocksize) {
203558cdbc6dSChristophe Leroy 		int offset;
203658cdbc6dSChristophe Leroy 
203737b5e889SLEROY Christophe 		if (nbytes_to_hash > blocksize)
203837b5e889SLEROY Christophe 			offset = blocksize - req_ctx->nbuf;
203937b5e889SLEROY Christophe 		else
204037b5e889SLEROY Christophe 			offset = nbytes_to_hash - req_ctx->nbuf;
204137b5e889SLEROY Christophe 		nents = sg_nents_for_len(areq->src, offset);
204237b5e889SLEROY Christophe 		if (nents < 0) {
2043854e25a6Sjianchunfu 			dev_err(dev, "Invalid number of src SG.\n");
204437b5e889SLEROY Christophe 			return nents;
204537b5e889SLEROY Christophe 		}
204637b5e889SLEROY Christophe 		sg_copy_to_buffer(areq->src, nents,
20473c0dd190SLEROY Christophe 				  ctx_buf + req_ctx->nbuf, offset);
204837b5e889SLEROY Christophe 		req_ctx->nbuf += offset;
204958cdbc6dSChristophe Leroy 		req_ctx->psrc = scatterwalk_ffwd(req_ctx->bufsl, areq->src,
205058cdbc6dSChristophe Leroy 						 offset);
20515e833bc4SLee Nipper 	} else
20525e833bc4SLee Nipper 		req_ctx->psrc = areq->src;
20535e833bc4SLee Nipper 
2054497f2e6bSLee Nipper 	if (to_hash_later) {
20558e409fe1SLABBE Corentin 		nents = sg_nents_for_len(areq->src, nbytes);
20568e409fe1SLABBE Corentin 		if (nents < 0) {
2057854e25a6Sjianchunfu 			dev_err(dev, "Invalid number of src SG.\n");
20588e409fe1SLABBE Corentin 			return nents;
20598e409fe1SLABBE Corentin 		}
2060d0525723SAkinobu Mita 		sg_pcopy_to_buffer(areq->src, nents,
20613c0dd190SLEROY Christophe 				   req_ctx->buf[(req_ctx->buf_idx + 1) & 1],
2062497f2e6bSLee Nipper 				      to_hash_later,
2063497f2e6bSLee Nipper 				      nbytes - to_hash_later);
2064497f2e6bSLee Nipper 	}
2065497f2e6bSLee Nipper 	req_ctx->to_hash_later = to_hash_later;
2066497f2e6bSLee Nipper 
20675e833bc4SLee Nipper 	/* Allocate extended descriptor */
2068497f2e6bSLee Nipper 	edesc = ahash_edesc_alloc(areq, nbytes_to_hash);
2069497f2e6bSLee Nipper 	if (IS_ERR(edesc))
2070497f2e6bSLee Nipper 		return PTR_ERR(edesc);
2071497f2e6bSLee Nipper 
2072497f2e6bSLee Nipper 	edesc->desc.hdr = ctx->desc_hdr_template;
2073497f2e6bSLee Nipper 
2074497f2e6bSLee Nipper 	/* On last one, request SEC to pad; otherwise continue */
2075497f2e6bSLee Nipper 	if (req_ctx->last)
2076497f2e6bSLee Nipper 		edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_PAD;
2077497f2e6bSLee Nipper 	else
2078497f2e6bSLee Nipper 		edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_CONT;
2079497f2e6bSLee Nipper 
208060f208d7SKim Phillips 	/* request SEC to INIT hash. */
208160f208d7SKim Phillips 	if (req_ctx->first && !req_ctx->swinit)
2082497f2e6bSLee Nipper 		edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_INIT;
2083497f2e6bSLee Nipper 
2084497f2e6bSLee Nipper 	/* When the tfm context has a keylen, it's an HMAC.
2085497f2e6bSLee Nipper 	 * A first or last (ie. not middle) descriptor must request HMAC.
2086497f2e6bSLee Nipper 	 */
2087497f2e6bSLee Nipper 	if (ctx->keylen && (req_ctx->first || req_ctx->last))
2088497f2e6bSLee Nipper 		edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_HMAC;
2089497f2e6bSLee Nipper 
209058cdbc6dSChristophe Leroy 	return common_nonsnoop_hash(edesc, areq, nbytes_to_hash, ahash_done);
2091497f2e6bSLee Nipper }
2092497f2e6bSLee Nipper 
ahash_update(struct ahash_request * areq)2093497f2e6bSLee Nipper static int ahash_update(struct ahash_request *areq)
2094497f2e6bSLee Nipper {
2095497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
2096497f2e6bSLee Nipper 
2097497f2e6bSLee Nipper 	req_ctx->last = 0;
2098497f2e6bSLee Nipper 
2099497f2e6bSLee Nipper 	return ahash_process_req(areq, areq->nbytes);
2100497f2e6bSLee Nipper }
2101497f2e6bSLee Nipper 
ahash_final(struct ahash_request * areq)2102497f2e6bSLee Nipper static int ahash_final(struct ahash_request *areq)
2103497f2e6bSLee Nipper {
2104497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
2105497f2e6bSLee Nipper 
2106497f2e6bSLee Nipper 	req_ctx->last = 1;
2107497f2e6bSLee Nipper 
2108497f2e6bSLee Nipper 	return ahash_process_req(areq, 0);
2109497f2e6bSLee Nipper }
2110497f2e6bSLee Nipper 
ahash_finup(struct ahash_request * areq)2111497f2e6bSLee Nipper static int ahash_finup(struct ahash_request *areq)
2112497f2e6bSLee Nipper {
2113497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
2114497f2e6bSLee Nipper 
2115497f2e6bSLee Nipper 	req_ctx->last = 1;
2116497f2e6bSLee Nipper 
2117497f2e6bSLee Nipper 	return ahash_process_req(areq, areq->nbytes);
2118497f2e6bSLee Nipper }
2119497f2e6bSLee Nipper 
ahash_digest(struct ahash_request * areq)2120497f2e6bSLee Nipper static int ahash_digest(struct ahash_request *areq)
2121497f2e6bSLee Nipper {
2122*9826d1d6SEric Biggers 	ahash_init(areq);
2123*9826d1d6SEric Biggers 	return ahash_finup(areq);
2124*9826d1d6SEric Biggers }
2125497f2e6bSLee Nipper 
ahash_digest_sha224_swinit(struct ahash_request * areq)2126*9826d1d6SEric Biggers static int ahash_digest_sha224_swinit(struct ahash_request *areq)
2127*9826d1d6SEric Biggers {
2128*9826d1d6SEric Biggers 	ahash_init_sha224_swinit(areq);
2129*9826d1d6SEric Biggers 	return ahash_finup(areq);
2130497f2e6bSLee Nipper }
2131497f2e6bSLee Nipper 
ahash_export(struct ahash_request * areq,void * out)21323639ca84SHoria Geant? static int ahash_export(struct ahash_request *areq, void *out)
21333639ca84SHoria Geant? {
21343639ca84SHoria Geant? 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
21353639ca84SHoria Geant? 	struct talitos_export_state *export = out;
21366a4967c3SLEROY Christophe 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
21376a4967c3SLEROY Christophe 	struct talitos_ctx *ctx = crypto_ahash_ctx(tfm);
21386a4967c3SLEROY Christophe 	struct device *dev = ctx->dev;
21396a4967c3SLEROY Christophe 	dma_addr_t dma;
21406a4967c3SLEROY Christophe 
21416a4967c3SLEROY Christophe 	dma = dma_map_single(dev, req_ctx->hw_context, req_ctx->hw_context_size,
21426a4967c3SLEROY Christophe 			     DMA_FROM_DEVICE);
21436a4967c3SLEROY Christophe 	dma_unmap_single(dev, dma, req_ctx->hw_context_size, DMA_FROM_DEVICE);
21443639ca84SHoria Geant? 
21453639ca84SHoria Geant? 	memcpy(export->hw_context, req_ctx->hw_context,
21463639ca84SHoria Geant? 	       req_ctx->hw_context_size);
21473c0dd190SLEROY Christophe 	memcpy(export->buf, req_ctx->buf[req_ctx->buf_idx], req_ctx->nbuf);
21483639ca84SHoria Geant? 	export->swinit = req_ctx->swinit;
21493639ca84SHoria Geant? 	export->first = req_ctx->first;
21503639ca84SHoria Geant? 	export->last = req_ctx->last;
21513639ca84SHoria Geant? 	export->to_hash_later = req_ctx->to_hash_later;
21523639ca84SHoria Geant? 	export->nbuf = req_ctx->nbuf;
21533639ca84SHoria Geant? 
21543639ca84SHoria Geant? 	return 0;
21553639ca84SHoria Geant? }
21563639ca84SHoria Geant? 
ahash_import(struct ahash_request * areq,const void * in)21573639ca84SHoria Geant? static int ahash_import(struct ahash_request *areq, const void *in)
21583639ca84SHoria Geant? {
21593639ca84SHoria Geant? 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
21603639ca84SHoria Geant? 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
21616a4967c3SLEROY Christophe 	struct talitos_ctx *ctx = crypto_ahash_ctx(tfm);
21626a4967c3SLEROY Christophe 	struct device *dev = ctx->dev;
21633639ca84SHoria Geant? 	const struct talitos_export_state *export = in;
216449f9783bSLEROY Christophe 	unsigned int size;
21656a4967c3SLEROY Christophe 	dma_addr_t dma;
21663639ca84SHoria Geant? 
21673639ca84SHoria Geant? 	memset(req_ctx, 0, sizeof(*req_ctx));
216849f9783bSLEROY Christophe 	size = (crypto_ahash_digestsize(tfm) <= SHA256_DIGEST_SIZE)
21693639ca84SHoria Geant? 			? TALITOS_MDEU_CONTEXT_SIZE_MD5_SHA1_SHA256
21703639ca84SHoria Geant? 			: TALITOS_MDEU_CONTEXT_SIZE_SHA384_SHA512;
217149f9783bSLEROY Christophe 	req_ctx->hw_context_size = size;
217249f9783bSLEROY Christophe 	memcpy(req_ctx->hw_context, export->hw_context, size);
21733c0dd190SLEROY Christophe 	memcpy(req_ctx->buf[0], export->buf, export->nbuf);
21743639ca84SHoria Geant? 	req_ctx->swinit = export->swinit;
21753639ca84SHoria Geant? 	req_ctx->first = export->first;
21763639ca84SHoria Geant? 	req_ctx->last = export->last;
21773639ca84SHoria Geant? 	req_ctx->to_hash_later = export->to_hash_later;
21783639ca84SHoria Geant? 	req_ctx->nbuf = export->nbuf;
21793639ca84SHoria Geant? 
21806a4967c3SLEROY Christophe 	dma = dma_map_single(dev, req_ctx->hw_context, req_ctx->hw_context_size,
21816a4967c3SLEROY Christophe 			     DMA_TO_DEVICE);
21826a4967c3SLEROY Christophe 	dma_unmap_single(dev, dma, req_ctx->hw_context_size, DMA_TO_DEVICE);
21836a4967c3SLEROY Christophe 
21843639ca84SHoria Geant? 	return 0;
21853639ca84SHoria Geant? }
21863639ca84SHoria Geant? 
keyhash(struct crypto_ahash * tfm,const u8 * key,unsigned int keylen,u8 * hash)218779b3a418SLee Nipper static int keyhash(struct crypto_ahash *tfm, const u8 *key, unsigned int keylen,
218879b3a418SLee Nipper 		   u8 *hash)
218979b3a418SLee Nipper {
219079b3a418SLee Nipper 	struct talitos_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm));
219179b3a418SLee Nipper 
219279b3a418SLee Nipper 	struct scatterlist sg[1];
219379b3a418SLee Nipper 	struct ahash_request *req;
2194f1c90ac3SGilad Ben-Yossef 	struct crypto_wait wait;
219579b3a418SLee Nipper 	int ret;
219679b3a418SLee Nipper 
2197f1c90ac3SGilad Ben-Yossef 	crypto_init_wait(&wait);
219879b3a418SLee Nipper 
219979b3a418SLee Nipper 	req = ahash_request_alloc(tfm, GFP_KERNEL);
220079b3a418SLee Nipper 	if (!req)
220179b3a418SLee Nipper 		return -ENOMEM;
220279b3a418SLee Nipper 
220379b3a418SLee Nipper 	/* Keep tfm keylen == 0 during hash of the long key */
220479b3a418SLee Nipper 	ctx->keylen = 0;
220579b3a418SLee Nipper 	ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
2206f1c90ac3SGilad Ben-Yossef 				   crypto_req_done, &wait);
220779b3a418SLee Nipper 
220879b3a418SLee Nipper 	sg_init_one(&sg[0], key, keylen);
220979b3a418SLee Nipper 
221079b3a418SLee Nipper 	ahash_request_set_crypt(req, sg, hash, keylen);
2211f1c90ac3SGilad Ben-Yossef 	ret = crypto_wait_req(crypto_ahash_digest(req), &wait);
2212f1c90ac3SGilad Ben-Yossef 
221379b3a418SLee Nipper 	ahash_request_free(req);
221479b3a418SLee Nipper 
221579b3a418SLee Nipper 	return ret;
221679b3a418SLee Nipper }
221779b3a418SLee Nipper 
ahash_setkey(struct crypto_ahash * tfm,const u8 * key,unsigned int keylen)221879b3a418SLee Nipper static int ahash_setkey(struct crypto_ahash *tfm, const u8 *key,
221979b3a418SLee Nipper 			unsigned int keylen)
222079b3a418SLee Nipper {
222179b3a418SLee Nipper 	struct talitos_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm));
22222e13ce08SLEROY Christophe 	struct device *dev = ctx->dev;
222379b3a418SLee Nipper 	unsigned int blocksize =
222479b3a418SLee Nipper 			crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm));
222579b3a418SLee Nipper 	unsigned int digestsize = crypto_ahash_digestsize(tfm);
222679b3a418SLee Nipper 	unsigned int keysize = keylen;
222779b3a418SLee Nipper 	u8 hash[SHA512_DIGEST_SIZE];
222879b3a418SLee Nipper 	int ret;
222979b3a418SLee Nipper 
223079b3a418SLee Nipper 	if (keylen <= blocksize)
223179b3a418SLee Nipper 		memcpy(ctx->key, key, keysize);
223279b3a418SLee Nipper 	else {
223379b3a418SLee Nipper 		/* Must get the hash of the long key */
223479b3a418SLee Nipper 		ret = keyhash(tfm, key, keylen, hash);
223579b3a418SLee Nipper 
2236674f368aSEric Biggers 		if (ret)
223779b3a418SLee Nipper 			return -EINVAL;
223879b3a418SLee Nipper 
223979b3a418SLee Nipper 		keysize = digestsize;
224079b3a418SLee Nipper 		memcpy(ctx->key, hash, digestsize);
224179b3a418SLee Nipper 	}
224279b3a418SLee Nipper 
22432e13ce08SLEROY Christophe 	if (ctx->keylen)
22442e13ce08SLEROY Christophe 		dma_unmap_single(dev, ctx->dma_key, ctx->keylen, DMA_TO_DEVICE);
22452e13ce08SLEROY Christophe 
224679b3a418SLee Nipper 	ctx->keylen = keysize;
22472e13ce08SLEROY Christophe 	ctx->dma_key = dma_map_single(dev, ctx->key, keysize, DMA_TO_DEVICE);
224879b3a418SLee Nipper 
224979b3a418SLee Nipper 	return 0;
225079b3a418SLee Nipper }
225179b3a418SLee Nipper 
225279b3a418SLee Nipper 
22539c4a7965SKim Phillips struct talitos_alg_template {
2254d5e4aaefSLee Nipper 	u32 type;
2255b0057763SLEROY Christophe 	u32 priority;
2256d5e4aaefSLee Nipper 	union {
2257373960d7SArd Biesheuvel 		struct skcipher_alg skcipher;
2258acbf7c62SLee Nipper 		struct ahash_alg hash;
2259aeb4c132SHerbert Xu 		struct aead_alg aead;
2260d5e4aaefSLee Nipper 	} alg;
22619c4a7965SKim Phillips 	__be32 desc_hdr_template;
22629c4a7965SKim Phillips };
22639c4a7965SKim Phillips 
22649c4a7965SKim Phillips static struct talitos_alg_template driver_algs[] = {
2265991155baSHoria Geanta 	/* AEAD algorithms.  These use a single-pass ipsec_esp descriptor */
2266d5e4aaefSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2267aeb4c132SHerbert Xu 		.alg.aead = {
2268aeb4c132SHerbert Xu 			.base = {
226956af8cd4SLee Nipper 				.cra_name = "authenc(hmac(sha1),cbc(aes))",
2270aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha1-"
2271aeb4c132SHerbert Xu 						   "cbc-aes-talitos",
227256af8cd4SLee Nipper 				.cra_blocksize = AES_BLOCK_SIZE,
2273b8aa7dc5SMikulas Patocka 				.cra_flags = CRYPTO_ALG_ASYNC |
2274b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY,
2275aeb4c132SHerbert Xu 			},
22763952f17eSLee Nipper 			.ivsize = AES_BLOCK_SIZE,
22773952f17eSLee Nipper 			.maxauthsize = SHA1_DIGEST_SIZE,
22789c4a7965SKim Phillips 		},
22799c4a7965SKim Phillips 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
22809c4a7965SKim Phillips 			             DESC_HDR_SEL0_AESU |
22819c4a7965SKim Phillips 		                     DESC_HDR_MODE0_AESU_CBC |
22829c4a7965SKim Phillips 		                     DESC_HDR_SEL1_MDEUA |
22839c4a7965SKim Phillips 		                     DESC_HDR_MODE1_MDEU_INIT |
22849c4a7965SKim Phillips 		                     DESC_HDR_MODE1_MDEU_PAD |
22859c4a7965SKim Phillips 		                     DESC_HDR_MODE1_MDEU_SHA1_HMAC,
228670bcaca7SLee Nipper 	},
2287d5e4aaefSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AEAD,
22887405c8d7SLEROY Christophe 		.priority = TALITOS_CRA_PRIORITY_AEAD_HSNA,
22897405c8d7SLEROY Christophe 		.alg.aead = {
22907405c8d7SLEROY Christophe 			.base = {
22917405c8d7SLEROY Christophe 				.cra_name = "authenc(hmac(sha1),cbc(aes))",
22927405c8d7SLEROY Christophe 				.cra_driver_name = "authenc-hmac-sha1-"
2293a1a42f84SChristophe Leroy 						   "cbc-aes-talitos-hsna",
22947405c8d7SLEROY Christophe 				.cra_blocksize = AES_BLOCK_SIZE,
2295b8aa7dc5SMikulas Patocka 				.cra_flags = CRYPTO_ALG_ASYNC |
2296b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY,
22977405c8d7SLEROY Christophe 			},
22987405c8d7SLEROY Christophe 			.ivsize = AES_BLOCK_SIZE,
22997405c8d7SLEROY Christophe 			.maxauthsize = SHA1_DIGEST_SIZE,
23007405c8d7SLEROY Christophe 		},
23017405c8d7SLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU |
23027405c8d7SLEROY Christophe 				     DESC_HDR_SEL0_AESU |
23037405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_AESU_CBC |
23047405c8d7SLEROY Christophe 				     DESC_HDR_SEL1_MDEUA |
23057405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_INIT |
23067405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_PAD |
23077405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_SHA1_HMAC,
23087405c8d7SLEROY Christophe 	},
23097405c8d7SLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2310aeb4c132SHerbert Xu 		.alg.aead = {
2311aeb4c132SHerbert Xu 			.base = {
2312aeb4c132SHerbert Xu 				.cra_name = "authenc(hmac(sha1),"
2313aeb4c132SHerbert Xu 					    "cbc(des3_ede))",
2314aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha1-"
2315aeb4c132SHerbert Xu 						   "cbc-3des-talitos",
231656af8cd4SLee Nipper 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
2317b8aa7dc5SMikulas Patocka 				.cra_flags = CRYPTO_ALG_ASYNC |
2318b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY,
2319aeb4c132SHerbert Xu 			},
23203952f17eSLee Nipper 			.ivsize = DES3_EDE_BLOCK_SIZE,
23213952f17eSLee Nipper 			.maxauthsize = SHA1_DIGEST_SIZE,
2322ef7c5c85SHerbert Xu 			.setkey = aead_des3_setkey,
232370bcaca7SLee Nipper 		},
232470bcaca7SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
232570bcaca7SLee Nipper 			             DESC_HDR_SEL0_DEU |
232670bcaca7SLee Nipper 		                     DESC_HDR_MODE0_DEU_CBC |
232770bcaca7SLee Nipper 		                     DESC_HDR_MODE0_DEU_3DES |
232870bcaca7SLee Nipper 		                     DESC_HDR_SEL1_MDEUA |
232970bcaca7SLee Nipper 		                     DESC_HDR_MODE1_MDEU_INIT |
233070bcaca7SLee Nipper 		                     DESC_HDR_MODE1_MDEU_PAD |
233170bcaca7SLee Nipper 		                     DESC_HDR_MODE1_MDEU_SHA1_HMAC,
23323952f17eSLee Nipper 	},
2333d5e4aaefSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AEAD,
23347405c8d7SLEROY Christophe 		.priority = TALITOS_CRA_PRIORITY_AEAD_HSNA,
23357405c8d7SLEROY Christophe 		.alg.aead = {
23367405c8d7SLEROY Christophe 			.base = {
23377405c8d7SLEROY Christophe 				.cra_name = "authenc(hmac(sha1),"
23387405c8d7SLEROY Christophe 					    "cbc(des3_ede))",
23397405c8d7SLEROY Christophe 				.cra_driver_name = "authenc-hmac-sha1-"
2340a1a42f84SChristophe Leroy 						   "cbc-3des-talitos-hsna",
23417405c8d7SLEROY Christophe 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
2342b8aa7dc5SMikulas Patocka 				.cra_flags = CRYPTO_ALG_ASYNC |
2343b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY,
23447405c8d7SLEROY Christophe 			},
23457405c8d7SLEROY Christophe 			.ivsize = DES3_EDE_BLOCK_SIZE,
23467405c8d7SLEROY Christophe 			.maxauthsize = SHA1_DIGEST_SIZE,
2347ef7c5c85SHerbert Xu 			.setkey = aead_des3_setkey,
23487405c8d7SLEROY Christophe 		},
23497405c8d7SLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU |
23507405c8d7SLEROY Christophe 				     DESC_HDR_SEL0_DEU |
23517405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_DEU_CBC |
23527405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_DEU_3DES |
23537405c8d7SLEROY Christophe 				     DESC_HDR_SEL1_MDEUA |
23547405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_INIT |
23557405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_PAD |
23567405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_SHA1_HMAC,
23577405c8d7SLEROY Christophe 	},
23587405c8d7SLEROY Christophe 	{       .type = CRYPTO_ALG_TYPE_AEAD,
2359aeb4c132SHerbert Xu 		.alg.aead = {
2360aeb4c132SHerbert Xu 			.base = {
2361357fb605SHoria Geanta 				.cra_name = "authenc(hmac(sha224),cbc(aes))",
2362aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha224-"
2363aeb4c132SHerbert Xu 						   "cbc-aes-talitos",
2364357fb605SHoria Geanta 				.cra_blocksize = AES_BLOCK_SIZE,
2365b8aa7dc5SMikulas Patocka 				.cra_flags = CRYPTO_ALG_ASYNC |
2366b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY,
2367aeb4c132SHerbert Xu 			},
2368357fb605SHoria Geanta 			.ivsize = AES_BLOCK_SIZE,
2369357fb605SHoria Geanta 			.maxauthsize = SHA224_DIGEST_SIZE,
2370357fb605SHoria Geanta 		},
2371357fb605SHoria Geanta 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
2372357fb605SHoria Geanta 				     DESC_HDR_SEL0_AESU |
2373357fb605SHoria Geanta 				     DESC_HDR_MODE0_AESU_CBC |
2374357fb605SHoria Geanta 				     DESC_HDR_SEL1_MDEUA |
2375357fb605SHoria Geanta 				     DESC_HDR_MODE1_MDEU_INIT |
2376357fb605SHoria Geanta 				     DESC_HDR_MODE1_MDEU_PAD |
2377357fb605SHoria Geanta 				     DESC_HDR_MODE1_MDEU_SHA224_HMAC,
2378357fb605SHoria Geanta 	},
2379357fb605SHoria Geanta 	{       .type = CRYPTO_ALG_TYPE_AEAD,
23807405c8d7SLEROY Christophe 		.priority = TALITOS_CRA_PRIORITY_AEAD_HSNA,
23817405c8d7SLEROY Christophe 		.alg.aead = {
23827405c8d7SLEROY Christophe 			.base = {
23837405c8d7SLEROY Christophe 				.cra_name = "authenc(hmac(sha224),cbc(aes))",
23847405c8d7SLEROY Christophe 				.cra_driver_name = "authenc-hmac-sha224-"
2385a1a42f84SChristophe Leroy 						   "cbc-aes-talitos-hsna",
23867405c8d7SLEROY Christophe 				.cra_blocksize = AES_BLOCK_SIZE,
2387b8aa7dc5SMikulas Patocka 				.cra_flags = CRYPTO_ALG_ASYNC |
2388b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY,
23897405c8d7SLEROY Christophe 			},
23907405c8d7SLEROY Christophe 			.ivsize = AES_BLOCK_SIZE,
23917405c8d7SLEROY Christophe 			.maxauthsize = SHA224_DIGEST_SIZE,
23927405c8d7SLEROY Christophe 		},
23937405c8d7SLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU |
23947405c8d7SLEROY Christophe 				     DESC_HDR_SEL0_AESU |
23957405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_AESU_CBC |
23967405c8d7SLEROY Christophe 				     DESC_HDR_SEL1_MDEUA |
23977405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_INIT |
23987405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_PAD |
23997405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_SHA224_HMAC,
24007405c8d7SLEROY Christophe 	},
24017405c8d7SLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2402aeb4c132SHerbert Xu 		.alg.aead = {
2403aeb4c132SHerbert Xu 			.base = {
2404aeb4c132SHerbert Xu 				.cra_name = "authenc(hmac(sha224),"
2405aeb4c132SHerbert Xu 					    "cbc(des3_ede))",
2406aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha224-"
2407aeb4c132SHerbert Xu 						   "cbc-3des-talitos",
2408357fb605SHoria Geanta 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
2409b8aa7dc5SMikulas Patocka 				.cra_flags = CRYPTO_ALG_ASYNC |
2410b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY,
2411aeb4c132SHerbert Xu 			},
2412357fb605SHoria Geanta 			.ivsize = DES3_EDE_BLOCK_SIZE,
2413357fb605SHoria Geanta 			.maxauthsize = SHA224_DIGEST_SIZE,
2414ef7c5c85SHerbert Xu 			.setkey = aead_des3_setkey,
2415357fb605SHoria Geanta 		},
2416357fb605SHoria Geanta 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
2417357fb605SHoria Geanta 			             DESC_HDR_SEL0_DEU |
2418357fb605SHoria Geanta 		                     DESC_HDR_MODE0_DEU_CBC |
2419357fb605SHoria Geanta 		                     DESC_HDR_MODE0_DEU_3DES |
2420357fb605SHoria Geanta 		                     DESC_HDR_SEL1_MDEUA |
2421357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_INIT |
2422357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_PAD |
2423357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_SHA224_HMAC,
2424357fb605SHoria Geanta 	},
2425357fb605SHoria Geanta 	{	.type = CRYPTO_ALG_TYPE_AEAD,
24267405c8d7SLEROY Christophe 		.priority = TALITOS_CRA_PRIORITY_AEAD_HSNA,
24277405c8d7SLEROY Christophe 		.alg.aead = {
24287405c8d7SLEROY Christophe 			.base = {
24297405c8d7SLEROY Christophe 				.cra_name = "authenc(hmac(sha224),"
24307405c8d7SLEROY Christophe 					    "cbc(des3_ede))",
24317405c8d7SLEROY Christophe 				.cra_driver_name = "authenc-hmac-sha224-"
2432a1a42f84SChristophe Leroy 						   "cbc-3des-talitos-hsna",
24337405c8d7SLEROY Christophe 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
2434b8aa7dc5SMikulas Patocka 				.cra_flags = CRYPTO_ALG_ASYNC |
2435b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY,
24367405c8d7SLEROY Christophe 			},
24377405c8d7SLEROY Christophe 			.ivsize = DES3_EDE_BLOCK_SIZE,
24387405c8d7SLEROY Christophe 			.maxauthsize = SHA224_DIGEST_SIZE,
2439ef7c5c85SHerbert Xu 			.setkey = aead_des3_setkey,
24407405c8d7SLEROY Christophe 		},
24417405c8d7SLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU |
24427405c8d7SLEROY Christophe 				     DESC_HDR_SEL0_DEU |
24437405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_DEU_CBC |
24447405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_DEU_3DES |
24457405c8d7SLEROY Christophe 				     DESC_HDR_SEL1_MDEUA |
24467405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_INIT |
24477405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_PAD |
24487405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_SHA224_HMAC,
24497405c8d7SLEROY Christophe 	},
24507405c8d7SLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2451aeb4c132SHerbert Xu 		.alg.aead = {
2452aeb4c132SHerbert Xu 			.base = {
245356af8cd4SLee Nipper 				.cra_name = "authenc(hmac(sha256),cbc(aes))",
2454aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha256-"
2455aeb4c132SHerbert Xu 						   "cbc-aes-talitos",
245656af8cd4SLee Nipper 				.cra_blocksize = AES_BLOCK_SIZE,
2457b8aa7dc5SMikulas Patocka 				.cra_flags = CRYPTO_ALG_ASYNC |
2458b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY,
2459aeb4c132SHerbert Xu 			},
24603952f17eSLee Nipper 			.ivsize = AES_BLOCK_SIZE,
24613952f17eSLee Nipper 			.maxauthsize = SHA256_DIGEST_SIZE,
24623952f17eSLee Nipper 		},
24633952f17eSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
24643952f17eSLee Nipper 			             DESC_HDR_SEL0_AESU |
24653952f17eSLee Nipper 		                     DESC_HDR_MODE0_AESU_CBC |
24663952f17eSLee Nipper 		                     DESC_HDR_SEL1_MDEUA |
24673952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_INIT |
24683952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_PAD |
24693952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_SHA256_HMAC,
24703952f17eSLee Nipper 	},
2471d5e4aaefSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AEAD,
24727405c8d7SLEROY Christophe 		.priority = TALITOS_CRA_PRIORITY_AEAD_HSNA,
24737405c8d7SLEROY Christophe 		.alg.aead = {
24747405c8d7SLEROY Christophe 			.base = {
24757405c8d7SLEROY Christophe 				.cra_name = "authenc(hmac(sha256),cbc(aes))",
24767405c8d7SLEROY Christophe 				.cra_driver_name = "authenc-hmac-sha256-"
2477a1a42f84SChristophe Leroy 						   "cbc-aes-talitos-hsna",
24787405c8d7SLEROY Christophe 				.cra_blocksize = AES_BLOCK_SIZE,
2479b8aa7dc5SMikulas Patocka 				.cra_flags = CRYPTO_ALG_ASYNC |
2480b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY,
24817405c8d7SLEROY Christophe 			},
24827405c8d7SLEROY Christophe 			.ivsize = AES_BLOCK_SIZE,
24837405c8d7SLEROY Christophe 			.maxauthsize = SHA256_DIGEST_SIZE,
24847405c8d7SLEROY Christophe 		},
24857405c8d7SLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU |
24867405c8d7SLEROY Christophe 				     DESC_HDR_SEL0_AESU |
24877405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_AESU_CBC |
24887405c8d7SLEROY Christophe 				     DESC_HDR_SEL1_MDEUA |
24897405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_INIT |
24907405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_PAD |
24917405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_SHA256_HMAC,
24927405c8d7SLEROY Christophe 	},
24937405c8d7SLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2494aeb4c132SHerbert Xu 		.alg.aead = {
2495aeb4c132SHerbert Xu 			.base = {
2496aeb4c132SHerbert Xu 				.cra_name = "authenc(hmac(sha256),"
2497aeb4c132SHerbert Xu 					    "cbc(des3_ede))",
2498aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha256-"
2499aeb4c132SHerbert Xu 						   "cbc-3des-talitos",
250056af8cd4SLee Nipper 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
2501b8aa7dc5SMikulas Patocka 				.cra_flags = CRYPTO_ALG_ASYNC |
2502b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY,
2503aeb4c132SHerbert Xu 			},
25043952f17eSLee Nipper 			.ivsize = DES3_EDE_BLOCK_SIZE,
25053952f17eSLee Nipper 			.maxauthsize = SHA256_DIGEST_SIZE,
2506ef7c5c85SHerbert Xu 			.setkey = aead_des3_setkey,
25073952f17eSLee Nipper 		},
25083952f17eSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
25093952f17eSLee Nipper 			             DESC_HDR_SEL0_DEU |
25103952f17eSLee Nipper 		                     DESC_HDR_MODE0_DEU_CBC |
25113952f17eSLee Nipper 		                     DESC_HDR_MODE0_DEU_3DES |
25123952f17eSLee Nipper 		                     DESC_HDR_SEL1_MDEUA |
25133952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_INIT |
25143952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_PAD |
25153952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_SHA256_HMAC,
25163952f17eSLee Nipper 	},
2517d5e4aaefSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AEAD,
25187405c8d7SLEROY Christophe 		.priority = TALITOS_CRA_PRIORITY_AEAD_HSNA,
25197405c8d7SLEROY Christophe 		.alg.aead = {
25207405c8d7SLEROY Christophe 			.base = {
25217405c8d7SLEROY Christophe 				.cra_name = "authenc(hmac(sha256),"
25227405c8d7SLEROY Christophe 					    "cbc(des3_ede))",
25237405c8d7SLEROY Christophe 				.cra_driver_name = "authenc-hmac-sha256-"
2524a1a42f84SChristophe Leroy 						   "cbc-3des-talitos-hsna",
25257405c8d7SLEROY Christophe 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
2526b8aa7dc5SMikulas Patocka 				.cra_flags = CRYPTO_ALG_ASYNC |
2527b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY,
25287405c8d7SLEROY Christophe 			},
25297405c8d7SLEROY Christophe 			.ivsize = DES3_EDE_BLOCK_SIZE,
25307405c8d7SLEROY Christophe 			.maxauthsize = SHA256_DIGEST_SIZE,
2531ef7c5c85SHerbert Xu 			.setkey = aead_des3_setkey,
25327405c8d7SLEROY Christophe 		},
25337405c8d7SLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU |
25347405c8d7SLEROY Christophe 				     DESC_HDR_SEL0_DEU |
25357405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_DEU_CBC |
25367405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_DEU_3DES |
25377405c8d7SLEROY Christophe 				     DESC_HDR_SEL1_MDEUA |
25387405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_INIT |
25397405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_PAD |
25407405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_SHA256_HMAC,
25417405c8d7SLEROY Christophe 	},
25427405c8d7SLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2543aeb4c132SHerbert Xu 		.alg.aead = {
2544aeb4c132SHerbert Xu 			.base = {
2545357fb605SHoria Geanta 				.cra_name = "authenc(hmac(sha384),cbc(aes))",
2546aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha384-"
2547aeb4c132SHerbert Xu 						   "cbc-aes-talitos",
2548357fb605SHoria Geanta 				.cra_blocksize = AES_BLOCK_SIZE,
2549b8aa7dc5SMikulas Patocka 				.cra_flags = CRYPTO_ALG_ASYNC |
2550b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY,
2551aeb4c132SHerbert Xu 			},
2552357fb605SHoria Geanta 			.ivsize = AES_BLOCK_SIZE,
2553357fb605SHoria Geanta 			.maxauthsize = SHA384_DIGEST_SIZE,
2554357fb605SHoria Geanta 		},
2555357fb605SHoria Geanta 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
2556357fb605SHoria Geanta 			             DESC_HDR_SEL0_AESU |
2557357fb605SHoria Geanta 		                     DESC_HDR_MODE0_AESU_CBC |
2558357fb605SHoria Geanta 		                     DESC_HDR_SEL1_MDEUB |
2559357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_INIT |
2560357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_PAD |
2561357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEUB_SHA384_HMAC,
2562357fb605SHoria Geanta 	},
2563357fb605SHoria Geanta 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2564aeb4c132SHerbert Xu 		.alg.aead = {
2565aeb4c132SHerbert Xu 			.base = {
2566aeb4c132SHerbert Xu 				.cra_name = "authenc(hmac(sha384),"
2567aeb4c132SHerbert Xu 					    "cbc(des3_ede))",
2568aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha384-"
2569aeb4c132SHerbert Xu 						   "cbc-3des-talitos",
2570357fb605SHoria Geanta 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
2571b8aa7dc5SMikulas Patocka 				.cra_flags = CRYPTO_ALG_ASYNC |
2572b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY,
2573aeb4c132SHerbert Xu 			},
2574357fb605SHoria Geanta 			.ivsize = DES3_EDE_BLOCK_SIZE,
2575357fb605SHoria Geanta 			.maxauthsize = SHA384_DIGEST_SIZE,
2576ef7c5c85SHerbert Xu 			.setkey = aead_des3_setkey,
2577357fb605SHoria Geanta 		},
2578357fb605SHoria Geanta 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
2579357fb605SHoria Geanta 			             DESC_HDR_SEL0_DEU |
2580357fb605SHoria Geanta 		                     DESC_HDR_MODE0_DEU_CBC |
2581357fb605SHoria Geanta 		                     DESC_HDR_MODE0_DEU_3DES |
2582357fb605SHoria Geanta 		                     DESC_HDR_SEL1_MDEUB |
2583357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_INIT |
2584357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_PAD |
2585357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEUB_SHA384_HMAC,
2586357fb605SHoria Geanta 	},
2587357fb605SHoria Geanta 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2588aeb4c132SHerbert Xu 		.alg.aead = {
2589aeb4c132SHerbert Xu 			.base = {
2590357fb605SHoria Geanta 				.cra_name = "authenc(hmac(sha512),cbc(aes))",
2591aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha512-"
2592aeb4c132SHerbert Xu 						   "cbc-aes-talitos",
2593357fb605SHoria Geanta 				.cra_blocksize = AES_BLOCK_SIZE,
2594b8aa7dc5SMikulas Patocka 				.cra_flags = CRYPTO_ALG_ASYNC |
2595b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY,
2596aeb4c132SHerbert Xu 			},
2597357fb605SHoria Geanta 			.ivsize = AES_BLOCK_SIZE,
2598357fb605SHoria Geanta 			.maxauthsize = SHA512_DIGEST_SIZE,
2599357fb605SHoria Geanta 		},
2600357fb605SHoria Geanta 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
2601357fb605SHoria Geanta 			             DESC_HDR_SEL0_AESU |
2602357fb605SHoria Geanta 		                     DESC_HDR_MODE0_AESU_CBC |
2603357fb605SHoria Geanta 		                     DESC_HDR_SEL1_MDEUB |
2604357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_INIT |
2605357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_PAD |
2606357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEUB_SHA512_HMAC,
2607357fb605SHoria Geanta 	},
2608357fb605SHoria Geanta 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2609aeb4c132SHerbert Xu 		.alg.aead = {
2610aeb4c132SHerbert Xu 			.base = {
2611aeb4c132SHerbert Xu 				.cra_name = "authenc(hmac(sha512),"
2612aeb4c132SHerbert Xu 					    "cbc(des3_ede))",
2613aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha512-"
2614aeb4c132SHerbert Xu 						   "cbc-3des-talitos",
2615357fb605SHoria Geanta 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
2616b8aa7dc5SMikulas Patocka 				.cra_flags = CRYPTO_ALG_ASYNC |
2617b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY,
2618aeb4c132SHerbert Xu 			},
2619357fb605SHoria Geanta 			.ivsize = DES3_EDE_BLOCK_SIZE,
2620357fb605SHoria Geanta 			.maxauthsize = SHA512_DIGEST_SIZE,
2621ef7c5c85SHerbert Xu 			.setkey = aead_des3_setkey,
2622357fb605SHoria Geanta 		},
2623357fb605SHoria Geanta 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
2624357fb605SHoria Geanta 			             DESC_HDR_SEL0_DEU |
2625357fb605SHoria Geanta 		                     DESC_HDR_MODE0_DEU_CBC |
2626357fb605SHoria Geanta 		                     DESC_HDR_MODE0_DEU_3DES |
2627357fb605SHoria Geanta 		                     DESC_HDR_SEL1_MDEUB |
2628357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_INIT |
2629357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_PAD |
2630357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEUB_SHA512_HMAC,
2631357fb605SHoria Geanta 	},
2632357fb605SHoria Geanta 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2633aeb4c132SHerbert Xu 		.alg.aead = {
2634aeb4c132SHerbert Xu 			.base = {
263556af8cd4SLee Nipper 				.cra_name = "authenc(hmac(md5),cbc(aes))",
2636aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-md5-"
2637aeb4c132SHerbert Xu 						   "cbc-aes-talitos",
263856af8cd4SLee Nipper 				.cra_blocksize = AES_BLOCK_SIZE,
2639b8aa7dc5SMikulas Patocka 				.cra_flags = CRYPTO_ALG_ASYNC |
2640b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY,
2641aeb4c132SHerbert Xu 			},
26423952f17eSLee Nipper 			.ivsize = AES_BLOCK_SIZE,
26433952f17eSLee Nipper 			.maxauthsize = MD5_DIGEST_SIZE,
26443952f17eSLee Nipper 		},
26453952f17eSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
26463952f17eSLee Nipper 			             DESC_HDR_SEL0_AESU |
26473952f17eSLee Nipper 		                     DESC_HDR_MODE0_AESU_CBC |
26483952f17eSLee Nipper 		                     DESC_HDR_SEL1_MDEUA |
26493952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_INIT |
26503952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_PAD |
26513952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_MD5_HMAC,
26523952f17eSLee Nipper 	},
2653d5e4aaefSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AEAD,
26547405c8d7SLEROY Christophe 		.priority = TALITOS_CRA_PRIORITY_AEAD_HSNA,
26557405c8d7SLEROY Christophe 		.alg.aead = {
26567405c8d7SLEROY Christophe 			.base = {
26577405c8d7SLEROY Christophe 				.cra_name = "authenc(hmac(md5),cbc(aes))",
26587405c8d7SLEROY Christophe 				.cra_driver_name = "authenc-hmac-md5-"
2659a1a42f84SChristophe Leroy 						   "cbc-aes-talitos-hsna",
26607405c8d7SLEROY Christophe 				.cra_blocksize = AES_BLOCK_SIZE,
2661b8aa7dc5SMikulas Patocka 				.cra_flags = CRYPTO_ALG_ASYNC |
2662b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY,
26637405c8d7SLEROY Christophe 			},
26647405c8d7SLEROY Christophe 			.ivsize = AES_BLOCK_SIZE,
26657405c8d7SLEROY Christophe 			.maxauthsize = MD5_DIGEST_SIZE,
26667405c8d7SLEROY Christophe 		},
26677405c8d7SLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU |
26687405c8d7SLEROY Christophe 				     DESC_HDR_SEL0_AESU |
26697405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_AESU_CBC |
26707405c8d7SLEROY Christophe 				     DESC_HDR_SEL1_MDEUA |
26717405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_INIT |
26727405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_PAD |
26737405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_MD5_HMAC,
26747405c8d7SLEROY Christophe 	},
26757405c8d7SLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2676aeb4c132SHerbert Xu 		.alg.aead = {
2677aeb4c132SHerbert Xu 			.base = {
267856af8cd4SLee Nipper 				.cra_name = "authenc(hmac(md5),cbc(des3_ede))",
2679aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-md5-"
2680aeb4c132SHerbert Xu 						   "cbc-3des-talitos",
268156af8cd4SLee Nipper 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
2682b8aa7dc5SMikulas Patocka 				.cra_flags = CRYPTO_ALG_ASYNC |
2683b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY,
2684aeb4c132SHerbert Xu 			},
26853952f17eSLee Nipper 			.ivsize = DES3_EDE_BLOCK_SIZE,
26863952f17eSLee Nipper 			.maxauthsize = MD5_DIGEST_SIZE,
2687ef7c5c85SHerbert Xu 			.setkey = aead_des3_setkey,
26883952f17eSLee Nipper 		},
26893952f17eSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
26903952f17eSLee Nipper 			             DESC_HDR_SEL0_DEU |
26913952f17eSLee Nipper 		                     DESC_HDR_MODE0_DEU_CBC |
26923952f17eSLee Nipper 		                     DESC_HDR_MODE0_DEU_3DES |
26933952f17eSLee Nipper 		                     DESC_HDR_SEL1_MDEUA |
26943952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_INIT |
26953952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_PAD |
26963952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_MD5_HMAC,
26974de9d0b5SLee Nipper 	},
26987405c8d7SLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_AEAD,
26997405c8d7SLEROY Christophe 		.priority = TALITOS_CRA_PRIORITY_AEAD_HSNA,
27007405c8d7SLEROY Christophe 		.alg.aead = {
27017405c8d7SLEROY Christophe 			.base = {
27027405c8d7SLEROY Christophe 				.cra_name = "authenc(hmac(md5),cbc(des3_ede))",
27037405c8d7SLEROY Christophe 				.cra_driver_name = "authenc-hmac-md5-"
2704a1a42f84SChristophe Leroy 						   "cbc-3des-talitos-hsna",
27057405c8d7SLEROY Christophe 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
2706b8aa7dc5SMikulas Patocka 				.cra_flags = CRYPTO_ALG_ASYNC |
2707b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY,
27087405c8d7SLEROY Christophe 			},
27097405c8d7SLEROY Christophe 			.ivsize = DES3_EDE_BLOCK_SIZE,
27107405c8d7SLEROY Christophe 			.maxauthsize = MD5_DIGEST_SIZE,
2711ef7c5c85SHerbert Xu 			.setkey = aead_des3_setkey,
27127405c8d7SLEROY Christophe 		},
27137405c8d7SLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU |
27147405c8d7SLEROY Christophe 				     DESC_HDR_SEL0_DEU |
27157405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_DEU_CBC |
27167405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_DEU_3DES |
27177405c8d7SLEROY Christophe 				     DESC_HDR_SEL1_MDEUA |
27187405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_INIT |
27197405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_PAD |
27207405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_MD5_HMAC,
27217405c8d7SLEROY Christophe 	},
2722373960d7SArd Biesheuvel 	/* SKCIPHER algorithms. */
2723373960d7SArd Biesheuvel 	{	.type = CRYPTO_ALG_TYPE_SKCIPHER,
2724373960d7SArd Biesheuvel 		.alg.skcipher = {
2725373960d7SArd Biesheuvel 			.base.cra_name = "ecb(aes)",
2726373960d7SArd Biesheuvel 			.base.cra_driver_name = "ecb-aes-talitos",
2727373960d7SArd Biesheuvel 			.base.cra_blocksize = AES_BLOCK_SIZE,
2728b8aa7dc5SMikulas Patocka 			.base.cra_flags = CRYPTO_ALG_ASYNC |
2729b8aa7dc5SMikulas Patocka 					  CRYPTO_ALG_ALLOCATES_MEMORY,
27305e75ae1bSLEROY Christophe 			.min_keysize = AES_MIN_KEY_SIZE,
27315e75ae1bSLEROY Christophe 			.max_keysize = AES_MAX_KEY_SIZE,
2732373960d7SArd Biesheuvel 			.setkey = skcipher_aes_setkey,
27335e75ae1bSLEROY Christophe 		},
27345e75ae1bSLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
27355e75ae1bSLEROY Christophe 				     DESC_HDR_SEL0_AESU,
27365e75ae1bSLEROY Christophe 	},
2737373960d7SArd Biesheuvel 	{	.type = CRYPTO_ALG_TYPE_SKCIPHER,
2738373960d7SArd Biesheuvel 		.alg.skcipher = {
2739373960d7SArd Biesheuvel 			.base.cra_name = "cbc(aes)",
2740373960d7SArd Biesheuvel 			.base.cra_driver_name = "cbc-aes-talitos",
2741373960d7SArd Biesheuvel 			.base.cra_blocksize = AES_BLOCK_SIZE,
2742b8aa7dc5SMikulas Patocka 			.base.cra_flags = CRYPTO_ALG_ASYNC |
2743b8aa7dc5SMikulas Patocka 					  CRYPTO_ALG_ALLOCATES_MEMORY,
27444de9d0b5SLee Nipper 			.min_keysize = AES_MIN_KEY_SIZE,
27454de9d0b5SLee Nipper 			.max_keysize = AES_MAX_KEY_SIZE,
27464de9d0b5SLee Nipper 			.ivsize = AES_BLOCK_SIZE,
2747373960d7SArd Biesheuvel 			.setkey = skcipher_aes_setkey,
27484de9d0b5SLee Nipper 		},
27494de9d0b5SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
27504de9d0b5SLee Nipper 				     DESC_HDR_SEL0_AESU |
27514de9d0b5SLee Nipper 				     DESC_HDR_MODE0_AESU_CBC,
27524de9d0b5SLee Nipper 	},
2753373960d7SArd Biesheuvel 	{	.type = CRYPTO_ALG_TYPE_SKCIPHER,
2754373960d7SArd Biesheuvel 		.alg.skcipher = {
2755373960d7SArd Biesheuvel 			.base.cra_name = "ctr(aes)",
2756373960d7SArd Biesheuvel 			.base.cra_driver_name = "ctr-aes-talitos",
2757373960d7SArd Biesheuvel 			.base.cra_blocksize = 1,
2758b8aa7dc5SMikulas Patocka 			.base.cra_flags = CRYPTO_ALG_ASYNC |
2759b8aa7dc5SMikulas Patocka 					  CRYPTO_ALG_ALLOCATES_MEMORY,
27605e75ae1bSLEROY Christophe 			.min_keysize = AES_MIN_KEY_SIZE,
27615e75ae1bSLEROY Christophe 			.max_keysize = AES_MAX_KEY_SIZE,
27625e75ae1bSLEROY Christophe 			.ivsize = AES_BLOCK_SIZE,
2763373960d7SArd Biesheuvel 			.setkey = skcipher_aes_setkey,
27645e75ae1bSLEROY Christophe 		},
276570d355ccSLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_AESU_CTR_NONSNOOP |
27665e75ae1bSLEROY Christophe 				     DESC_HDR_SEL0_AESU |
27675e75ae1bSLEROY Christophe 				     DESC_HDR_MODE0_AESU_CTR,
27685e75ae1bSLEROY Christophe 	},
2769373960d7SArd Biesheuvel 	{	.type = CRYPTO_ALG_TYPE_SKCIPHER,
2770373960d7SArd Biesheuvel 		.alg.skcipher = {
277143a942d2SChristophe Leroy 			.base.cra_name = "ctr(aes)",
277243a942d2SChristophe Leroy 			.base.cra_driver_name = "ctr-aes-talitos",
277343a942d2SChristophe Leroy 			.base.cra_blocksize = 1,
277443a942d2SChristophe Leroy 			.base.cra_flags = CRYPTO_ALG_ASYNC |
277543a942d2SChristophe Leroy 					  CRYPTO_ALG_ALLOCATES_MEMORY,
277643a942d2SChristophe Leroy 			.min_keysize = AES_MIN_KEY_SIZE,
277743a942d2SChristophe Leroy 			.max_keysize = AES_MAX_KEY_SIZE,
277843a942d2SChristophe Leroy 			.ivsize = AES_BLOCK_SIZE,
277943a942d2SChristophe Leroy 			.setkey = skcipher_aes_setkey,
278043a942d2SChristophe Leroy 		},
278143a942d2SChristophe Leroy 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
278243a942d2SChristophe Leroy 				     DESC_HDR_SEL0_AESU |
278343a942d2SChristophe Leroy 				     DESC_HDR_MODE0_AESU_CTR,
278443a942d2SChristophe Leroy 	},
278543a942d2SChristophe Leroy 	{	.type = CRYPTO_ALG_TYPE_SKCIPHER,
278643a942d2SChristophe Leroy 		.alg.skcipher = {
2787373960d7SArd Biesheuvel 			.base.cra_name = "ecb(des)",
2788373960d7SArd Biesheuvel 			.base.cra_driver_name = "ecb-des-talitos",
2789373960d7SArd Biesheuvel 			.base.cra_blocksize = DES_BLOCK_SIZE,
2790b8aa7dc5SMikulas Patocka 			.base.cra_flags = CRYPTO_ALG_ASYNC |
2791b8aa7dc5SMikulas Patocka 					  CRYPTO_ALG_ALLOCATES_MEMORY,
27925e75ae1bSLEROY Christophe 			.min_keysize = DES_KEY_SIZE,
27935e75ae1bSLEROY Christophe 			.max_keysize = DES_KEY_SIZE,
2794373960d7SArd Biesheuvel 			.setkey = skcipher_des_setkey,
27955e75ae1bSLEROY Christophe 		},
27965e75ae1bSLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
27975e75ae1bSLEROY Christophe 				     DESC_HDR_SEL0_DEU,
27985e75ae1bSLEROY Christophe 	},
2799373960d7SArd Biesheuvel 	{	.type = CRYPTO_ALG_TYPE_SKCIPHER,
2800373960d7SArd Biesheuvel 		.alg.skcipher = {
2801373960d7SArd Biesheuvel 			.base.cra_name = "cbc(des)",
2802373960d7SArd Biesheuvel 			.base.cra_driver_name = "cbc-des-talitos",
2803373960d7SArd Biesheuvel 			.base.cra_blocksize = DES_BLOCK_SIZE,
2804b8aa7dc5SMikulas Patocka 			.base.cra_flags = CRYPTO_ALG_ASYNC |
2805b8aa7dc5SMikulas Patocka 					  CRYPTO_ALG_ALLOCATES_MEMORY,
28065e75ae1bSLEROY Christophe 			.min_keysize = DES_KEY_SIZE,
28075e75ae1bSLEROY Christophe 			.max_keysize = DES_KEY_SIZE,
28085e75ae1bSLEROY Christophe 			.ivsize = DES_BLOCK_SIZE,
2809373960d7SArd Biesheuvel 			.setkey = skcipher_des_setkey,
28105e75ae1bSLEROY Christophe 		},
28115e75ae1bSLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
28125e75ae1bSLEROY Christophe 				     DESC_HDR_SEL0_DEU |
28135e75ae1bSLEROY Christophe 				     DESC_HDR_MODE0_DEU_CBC,
28145e75ae1bSLEROY Christophe 	},
2815373960d7SArd Biesheuvel 	{	.type = CRYPTO_ALG_TYPE_SKCIPHER,
2816373960d7SArd Biesheuvel 		.alg.skcipher = {
2817373960d7SArd Biesheuvel 			.base.cra_name = "ecb(des3_ede)",
2818373960d7SArd Biesheuvel 			.base.cra_driver_name = "ecb-3des-talitos",
2819373960d7SArd Biesheuvel 			.base.cra_blocksize = DES3_EDE_BLOCK_SIZE,
2820b8aa7dc5SMikulas Patocka 			.base.cra_flags = CRYPTO_ALG_ASYNC |
2821b8aa7dc5SMikulas Patocka 					  CRYPTO_ALG_ALLOCATES_MEMORY,
28225e75ae1bSLEROY Christophe 			.min_keysize = DES3_EDE_KEY_SIZE,
28235e75ae1bSLEROY Christophe 			.max_keysize = DES3_EDE_KEY_SIZE,
2824373960d7SArd Biesheuvel 			.setkey = skcipher_des3_setkey,
28255e75ae1bSLEROY Christophe 		},
28265e75ae1bSLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
28275e75ae1bSLEROY Christophe 				     DESC_HDR_SEL0_DEU |
28285e75ae1bSLEROY Christophe 				     DESC_HDR_MODE0_DEU_3DES,
28295e75ae1bSLEROY Christophe 	},
2830373960d7SArd Biesheuvel 	{	.type = CRYPTO_ALG_TYPE_SKCIPHER,
2831373960d7SArd Biesheuvel 		.alg.skcipher = {
2832373960d7SArd Biesheuvel 			.base.cra_name = "cbc(des3_ede)",
2833373960d7SArd Biesheuvel 			.base.cra_driver_name = "cbc-3des-talitos",
2834373960d7SArd Biesheuvel 			.base.cra_blocksize = DES3_EDE_BLOCK_SIZE,
2835b8aa7dc5SMikulas Patocka 			.base.cra_flags = CRYPTO_ALG_ASYNC |
2836b8aa7dc5SMikulas Patocka 					  CRYPTO_ALG_ALLOCATES_MEMORY,
28374de9d0b5SLee Nipper 			.min_keysize = DES3_EDE_KEY_SIZE,
28384de9d0b5SLee Nipper 			.max_keysize = DES3_EDE_KEY_SIZE,
28394de9d0b5SLee Nipper 			.ivsize = DES3_EDE_BLOCK_SIZE,
2840373960d7SArd Biesheuvel 			.setkey = skcipher_des3_setkey,
28414de9d0b5SLee Nipper 		},
28424de9d0b5SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
28434de9d0b5SLee Nipper 			             DESC_HDR_SEL0_DEU |
28444de9d0b5SLee Nipper 		                     DESC_HDR_MODE0_DEU_CBC |
28454de9d0b5SLee Nipper 		                     DESC_HDR_MODE0_DEU_3DES,
2846497f2e6bSLee Nipper 	},
2847497f2e6bSLee Nipper 	/* AHASH algorithms. */
2848497f2e6bSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
2849497f2e6bSLee Nipper 		.alg.hash = {
2850497f2e6bSLee Nipper 			.halg.digestsize = MD5_DIGEST_SIZE,
28513639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
2852497f2e6bSLee Nipper 			.halg.base = {
2853497f2e6bSLee Nipper 				.cra_name = "md5",
2854497f2e6bSLee Nipper 				.cra_driver_name = "md5-talitos",
2855b3988618SMartin Hicks 				.cra_blocksize = MD5_HMAC_BLOCK_SIZE,
2856b8aa7dc5SMikulas Patocka 				.cra_flags = CRYPTO_ALG_ASYNC |
2857b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY,
28589c4a7965SKim Phillips 			}
2859497f2e6bSLee Nipper 		},
2860497f2e6bSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
2861497f2e6bSLee Nipper 				     DESC_HDR_SEL0_MDEUA |
2862497f2e6bSLee Nipper 				     DESC_HDR_MODE0_MDEU_MD5,
2863497f2e6bSLee Nipper 	},
2864497f2e6bSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
2865497f2e6bSLee Nipper 		.alg.hash = {
2866497f2e6bSLee Nipper 			.halg.digestsize = SHA1_DIGEST_SIZE,
28673639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
2868497f2e6bSLee Nipper 			.halg.base = {
2869497f2e6bSLee Nipper 				.cra_name = "sha1",
2870497f2e6bSLee Nipper 				.cra_driver_name = "sha1-talitos",
2871497f2e6bSLee Nipper 				.cra_blocksize = SHA1_BLOCK_SIZE,
2872b8aa7dc5SMikulas Patocka 				.cra_flags = CRYPTO_ALG_ASYNC |
2873b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY,
2874497f2e6bSLee Nipper 			}
2875497f2e6bSLee Nipper 		},
2876497f2e6bSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
2877497f2e6bSLee Nipper 				     DESC_HDR_SEL0_MDEUA |
2878497f2e6bSLee Nipper 				     DESC_HDR_MODE0_MDEU_SHA1,
2879497f2e6bSLee Nipper 	},
2880497f2e6bSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
2881497f2e6bSLee Nipper 		.alg.hash = {
288260f208d7SKim Phillips 			.halg.digestsize = SHA224_DIGEST_SIZE,
28833639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
288460f208d7SKim Phillips 			.halg.base = {
288560f208d7SKim Phillips 				.cra_name = "sha224",
288660f208d7SKim Phillips 				.cra_driver_name = "sha224-talitos",
288760f208d7SKim Phillips 				.cra_blocksize = SHA224_BLOCK_SIZE,
2888b8aa7dc5SMikulas Patocka 				.cra_flags = CRYPTO_ALG_ASYNC |
2889b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY,
289060f208d7SKim Phillips 			}
289160f208d7SKim Phillips 		},
289260f208d7SKim Phillips 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
289360f208d7SKim Phillips 				     DESC_HDR_SEL0_MDEUA |
289460f208d7SKim Phillips 				     DESC_HDR_MODE0_MDEU_SHA224,
289560f208d7SKim Phillips 	},
289660f208d7SKim Phillips 	{	.type = CRYPTO_ALG_TYPE_AHASH,
289760f208d7SKim Phillips 		.alg.hash = {
2898497f2e6bSLee Nipper 			.halg.digestsize = SHA256_DIGEST_SIZE,
28993639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
2900497f2e6bSLee Nipper 			.halg.base = {
2901497f2e6bSLee Nipper 				.cra_name = "sha256",
2902497f2e6bSLee Nipper 				.cra_driver_name = "sha256-talitos",
2903497f2e6bSLee Nipper 				.cra_blocksize = SHA256_BLOCK_SIZE,
2904b8aa7dc5SMikulas Patocka 				.cra_flags = CRYPTO_ALG_ASYNC |
2905b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY,
2906497f2e6bSLee Nipper 			}
2907497f2e6bSLee Nipper 		},
2908497f2e6bSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
2909497f2e6bSLee Nipper 				     DESC_HDR_SEL0_MDEUA |
2910497f2e6bSLee Nipper 				     DESC_HDR_MODE0_MDEU_SHA256,
2911497f2e6bSLee Nipper 	},
2912497f2e6bSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
2913497f2e6bSLee Nipper 		.alg.hash = {
2914497f2e6bSLee Nipper 			.halg.digestsize = SHA384_DIGEST_SIZE,
29153639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
2916497f2e6bSLee Nipper 			.halg.base = {
2917497f2e6bSLee Nipper 				.cra_name = "sha384",
2918497f2e6bSLee Nipper 				.cra_driver_name = "sha384-talitos",
2919497f2e6bSLee Nipper 				.cra_blocksize = SHA384_BLOCK_SIZE,
2920b8aa7dc5SMikulas Patocka 				.cra_flags = CRYPTO_ALG_ASYNC |
2921b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY,
2922497f2e6bSLee Nipper 			}
2923497f2e6bSLee Nipper 		},
2924497f2e6bSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
2925497f2e6bSLee Nipper 				     DESC_HDR_SEL0_MDEUB |
2926497f2e6bSLee Nipper 				     DESC_HDR_MODE0_MDEUB_SHA384,
2927497f2e6bSLee Nipper 	},
2928497f2e6bSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
2929497f2e6bSLee Nipper 		.alg.hash = {
2930497f2e6bSLee Nipper 			.halg.digestsize = SHA512_DIGEST_SIZE,
29313639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
2932497f2e6bSLee Nipper 			.halg.base = {
2933497f2e6bSLee Nipper 				.cra_name = "sha512",
2934497f2e6bSLee Nipper 				.cra_driver_name = "sha512-talitos",
2935497f2e6bSLee Nipper 				.cra_blocksize = SHA512_BLOCK_SIZE,
2936b8aa7dc5SMikulas Patocka 				.cra_flags = CRYPTO_ALG_ASYNC |
2937b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY,
2938497f2e6bSLee Nipper 			}
2939497f2e6bSLee Nipper 		},
2940497f2e6bSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
2941497f2e6bSLee Nipper 				     DESC_HDR_SEL0_MDEUB |
2942497f2e6bSLee Nipper 				     DESC_HDR_MODE0_MDEUB_SHA512,
2943497f2e6bSLee Nipper 	},
294479b3a418SLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
294579b3a418SLee Nipper 		.alg.hash = {
294679b3a418SLee Nipper 			.halg.digestsize = MD5_DIGEST_SIZE,
29473639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
294879b3a418SLee Nipper 			.halg.base = {
294979b3a418SLee Nipper 				.cra_name = "hmac(md5)",
295079b3a418SLee Nipper 				.cra_driver_name = "hmac-md5-talitos",
2951b3988618SMartin Hicks 				.cra_blocksize = MD5_HMAC_BLOCK_SIZE,
2952b8aa7dc5SMikulas Patocka 				.cra_flags = CRYPTO_ALG_ASYNC |
2953b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY,
295479b3a418SLee Nipper 			}
295579b3a418SLee Nipper 		},
295679b3a418SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
295779b3a418SLee Nipper 				     DESC_HDR_SEL0_MDEUA |
295879b3a418SLee Nipper 				     DESC_HDR_MODE0_MDEU_MD5,
295979b3a418SLee Nipper 	},
296079b3a418SLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
296179b3a418SLee Nipper 		.alg.hash = {
296279b3a418SLee Nipper 			.halg.digestsize = SHA1_DIGEST_SIZE,
29633639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
296479b3a418SLee Nipper 			.halg.base = {
296579b3a418SLee Nipper 				.cra_name = "hmac(sha1)",
296679b3a418SLee Nipper 				.cra_driver_name = "hmac-sha1-talitos",
296779b3a418SLee Nipper 				.cra_blocksize = SHA1_BLOCK_SIZE,
2968b8aa7dc5SMikulas Patocka 				.cra_flags = CRYPTO_ALG_ASYNC |
2969b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY,
297079b3a418SLee Nipper 			}
297179b3a418SLee Nipper 		},
297279b3a418SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
297379b3a418SLee Nipper 				     DESC_HDR_SEL0_MDEUA |
297479b3a418SLee Nipper 				     DESC_HDR_MODE0_MDEU_SHA1,
297579b3a418SLee Nipper 	},
297679b3a418SLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
297779b3a418SLee Nipper 		.alg.hash = {
297879b3a418SLee Nipper 			.halg.digestsize = SHA224_DIGEST_SIZE,
29793639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
298079b3a418SLee Nipper 			.halg.base = {
298179b3a418SLee Nipper 				.cra_name = "hmac(sha224)",
298279b3a418SLee Nipper 				.cra_driver_name = "hmac-sha224-talitos",
298379b3a418SLee Nipper 				.cra_blocksize = SHA224_BLOCK_SIZE,
2984b8aa7dc5SMikulas Patocka 				.cra_flags = CRYPTO_ALG_ASYNC |
2985b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY,
298679b3a418SLee Nipper 			}
298779b3a418SLee Nipper 		},
298879b3a418SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
298979b3a418SLee Nipper 				     DESC_HDR_SEL0_MDEUA |
299079b3a418SLee Nipper 				     DESC_HDR_MODE0_MDEU_SHA224,
299179b3a418SLee Nipper 	},
299279b3a418SLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
299379b3a418SLee Nipper 		.alg.hash = {
299479b3a418SLee Nipper 			.halg.digestsize = SHA256_DIGEST_SIZE,
29953639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
299679b3a418SLee Nipper 			.halg.base = {
299779b3a418SLee Nipper 				.cra_name = "hmac(sha256)",
299879b3a418SLee Nipper 				.cra_driver_name = "hmac-sha256-talitos",
299979b3a418SLee Nipper 				.cra_blocksize = SHA256_BLOCK_SIZE,
3000b8aa7dc5SMikulas Patocka 				.cra_flags = CRYPTO_ALG_ASYNC |
3001b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY,
300279b3a418SLee Nipper 			}
300379b3a418SLee Nipper 		},
300479b3a418SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
300579b3a418SLee Nipper 				     DESC_HDR_SEL0_MDEUA |
300679b3a418SLee Nipper 				     DESC_HDR_MODE0_MDEU_SHA256,
300779b3a418SLee Nipper 	},
300879b3a418SLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
300979b3a418SLee Nipper 		.alg.hash = {
301079b3a418SLee Nipper 			.halg.digestsize = SHA384_DIGEST_SIZE,
30113639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
301279b3a418SLee Nipper 			.halg.base = {
301379b3a418SLee Nipper 				.cra_name = "hmac(sha384)",
301479b3a418SLee Nipper 				.cra_driver_name = "hmac-sha384-talitos",
301579b3a418SLee Nipper 				.cra_blocksize = SHA384_BLOCK_SIZE,
3016b8aa7dc5SMikulas Patocka 				.cra_flags = CRYPTO_ALG_ASYNC |
3017b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY,
301879b3a418SLee Nipper 			}
301979b3a418SLee Nipper 		},
302079b3a418SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
302179b3a418SLee Nipper 				     DESC_HDR_SEL0_MDEUB |
302279b3a418SLee Nipper 				     DESC_HDR_MODE0_MDEUB_SHA384,
302379b3a418SLee Nipper 	},
302479b3a418SLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
302579b3a418SLee Nipper 		.alg.hash = {
302679b3a418SLee Nipper 			.halg.digestsize = SHA512_DIGEST_SIZE,
30273639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
302879b3a418SLee Nipper 			.halg.base = {
302979b3a418SLee Nipper 				.cra_name = "hmac(sha512)",
303079b3a418SLee Nipper 				.cra_driver_name = "hmac-sha512-talitos",
303179b3a418SLee Nipper 				.cra_blocksize = SHA512_BLOCK_SIZE,
3032b8aa7dc5SMikulas Patocka 				.cra_flags = CRYPTO_ALG_ASYNC |
3033b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY,
303479b3a418SLee Nipper 			}
303579b3a418SLee Nipper 		},
303679b3a418SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
303779b3a418SLee Nipper 				     DESC_HDR_SEL0_MDEUB |
303879b3a418SLee Nipper 				     DESC_HDR_MODE0_MDEUB_SHA512,
303979b3a418SLee Nipper 	}
30409c4a7965SKim Phillips };
30419c4a7965SKim Phillips 
30429c4a7965SKim Phillips struct talitos_crypto_alg {
30439c4a7965SKim Phillips 	struct list_head entry;
30449c4a7965SKim Phillips 	struct device *dev;
3045acbf7c62SLee Nipper 	struct talitos_alg_template algt;
30469c4a7965SKim Phillips };
30479c4a7965SKim Phillips 
talitos_init_common(struct talitos_ctx * ctx,struct talitos_crypto_alg * talitos_alg)304889d124cbSJonas Eymann static int talitos_init_common(struct talitos_ctx *ctx,
304989d124cbSJonas Eymann 			       struct talitos_crypto_alg *talitos_alg)
30509c4a7965SKim Phillips {
30515228f0f7SKim Phillips 	struct talitos_private *priv;
30529c4a7965SKim Phillips 
30539c4a7965SKim Phillips 	/* update context with ptr to dev */
30549c4a7965SKim Phillips 	ctx->dev = talitos_alg->dev;
305519bbbc63SKim Phillips 
30565228f0f7SKim Phillips 	/* assign SEC channel to tfm in round-robin fashion */
30575228f0f7SKim Phillips 	priv = dev_get_drvdata(ctx->dev);
30585228f0f7SKim Phillips 	ctx->ch = atomic_inc_return(&priv->last_chan) &
30595228f0f7SKim Phillips 		  (priv->num_channels - 1);
30605228f0f7SKim Phillips 
30619c4a7965SKim Phillips 	/* copy descriptor header template value */
3062acbf7c62SLee Nipper 	ctx->desc_hdr_template = talitos_alg->algt.desc_hdr_template;
30639c4a7965SKim Phillips 
3064602dba5aSKim Phillips 	/* select done notification */
3065602dba5aSKim Phillips 	ctx->desc_hdr_template |= DESC_HDR_DONE_NOTIFY;
3066602dba5aSKim Phillips 
3067497f2e6bSLee Nipper 	return 0;
3068497f2e6bSLee Nipper }
3069497f2e6bSLee Nipper 
talitos_cra_init_aead(struct crypto_aead * tfm)3070aeb4c132SHerbert Xu static int talitos_cra_init_aead(struct crypto_aead *tfm)
3071497f2e6bSLee Nipper {
307289d124cbSJonas Eymann 	struct aead_alg *alg = crypto_aead_alg(tfm);
307389d124cbSJonas Eymann 	struct talitos_crypto_alg *talitos_alg;
307489d124cbSJonas Eymann 	struct talitos_ctx *ctx = crypto_aead_ctx(tfm);
307589d124cbSJonas Eymann 
307689d124cbSJonas Eymann 	talitos_alg = container_of(alg, struct talitos_crypto_alg,
307789d124cbSJonas Eymann 				   algt.alg.aead);
307889d124cbSJonas Eymann 
307989d124cbSJonas Eymann 	return talitos_init_common(ctx, talitos_alg);
30809c4a7965SKim Phillips }
30819c4a7965SKim Phillips 
talitos_cra_init_skcipher(struct crypto_skcipher * tfm)3082373960d7SArd Biesheuvel static int talitos_cra_init_skcipher(struct crypto_skcipher *tfm)
3083373960d7SArd Biesheuvel {
3084373960d7SArd Biesheuvel 	struct skcipher_alg *alg = crypto_skcipher_alg(tfm);
3085373960d7SArd Biesheuvel 	struct talitos_crypto_alg *talitos_alg;
3086373960d7SArd Biesheuvel 	struct talitos_ctx *ctx = crypto_skcipher_ctx(tfm);
3087373960d7SArd Biesheuvel 
3088373960d7SArd Biesheuvel 	talitos_alg = container_of(alg, struct talitos_crypto_alg,
3089373960d7SArd Biesheuvel 				   algt.alg.skcipher);
3090373960d7SArd Biesheuvel 
3091373960d7SArd Biesheuvel 	return talitos_init_common(ctx, talitos_alg);
3092373960d7SArd Biesheuvel }
3093373960d7SArd Biesheuvel 
talitos_cra_init_ahash(struct crypto_tfm * tfm)3094497f2e6bSLee Nipper static int talitos_cra_init_ahash(struct crypto_tfm *tfm)
3095497f2e6bSLee Nipper {
3096373960d7SArd Biesheuvel 	struct crypto_alg *alg = tfm->__crt_alg;
3097373960d7SArd Biesheuvel 	struct talitos_crypto_alg *talitos_alg;
3098497f2e6bSLee Nipper 	struct talitos_ctx *ctx = crypto_tfm_ctx(tfm);
3099497f2e6bSLee Nipper 
3100373960d7SArd Biesheuvel 	talitos_alg = container_of(__crypto_ahash_alg(alg),
3101373960d7SArd Biesheuvel 				   struct talitos_crypto_alg,
3102373960d7SArd Biesheuvel 				   algt.alg.hash);
3103497f2e6bSLee Nipper 
3104497f2e6bSLee Nipper 	ctx->keylen = 0;
3105497f2e6bSLee Nipper 	crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm),
3106497f2e6bSLee Nipper 				 sizeof(struct talitos_ahash_req_ctx));
3107497f2e6bSLee Nipper 
3108373960d7SArd Biesheuvel 	return talitos_init_common(ctx, talitos_alg);
3109497f2e6bSLee Nipper }
3110497f2e6bSLee Nipper 
talitos_cra_exit(struct crypto_tfm * tfm)31112e13ce08SLEROY Christophe static void talitos_cra_exit(struct crypto_tfm *tfm)
31122e13ce08SLEROY Christophe {
31132e13ce08SLEROY Christophe 	struct talitos_ctx *ctx = crypto_tfm_ctx(tfm);
31142e13ce08SLEROY Christophe 	struct device *dev = ctx->dev;
31152e13ce08SLEROY Christophe 
31162e13ce08SLEROY Christophe 	if (ctx->keylen)
31172e13ce08SLEROY Christophe 		dma_unmap_single(dev, ctx->dma_key, ctx->keylen, DMA_TO_DEVICE);
31182e13ce08SLEROY Christophe }
31192e13ce08SLEROY Christophe 
31209c4a7965SKim Phillips /*
31219c4a7965SKim Phillips  * given the alg's descriptor header template, determine whether descriptor
31229c4a7965SKim Phillips  * type and primary/secondary execution units required match the hw
31239c4a7965SKim Phillips  * capabilities description provided in the device tree node.
31249c4a7965SKim Phillips  */
hw_supports(struct device * dev,__be32 desc_hdr_template)31259c4a7965SKim Phillips static int hw_supports(struct device *dev, __be32 desc_hdr_template)
31269c4a7965SKim Phillips {
31279c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
31289c4a7965SKim Phillips 	int ret;
31299c4a7965SKim Phillips 
31309c4a7965SKim Phillips 	ret = (1 << DESC_TYPE(desc_hdr_template) & priv->desc_types) &&
31319c4a7965SKim Phillips 	      (1 << PRIMARY_EU(desc_hdr_template) & priv->exec_units);
31329c4a7965SKim Phillips 
31339c4a7965SKim Phillips 	if (SECONDARY_EU(desc_hdr_template))
31349c4a7965SKim Phillips 		ret = ret && (1 << SECONDARY_EU(desc_hdr_template)
31359c4a7965SKim Phillips 		              & priv->exec_units);
31369c4a7965SKim Phillips 
31379c4a7965SKim Phillips 	return ret;
31389c4a7965SKim Phillips }
31399c4a7965SKim Phillips 
talitos_remove(struct platform_device * ofdev)3140ce52705eSUwe Kleine-König static void talitos_remove(struct platform_device *ofdev)
31419c4a7965SKim Phillips {
31429c4a7965SKim Phillips 	struct device *dev = &ofdev->dev;
31439c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
31449c4a7965SKim Phillips 	struct talitos_crypto_alg *t_alg, *n;
31459c4a7965SKim Phillips 	int i;
31469c4a7965SKim Phillips 
31479c4a7965SKim Phillips 	list_for_each_entry_safe(t_alg, n, &priv->alg_list, entry) {
3148acbf7c62SLee Nipper 		switch (t_alg->algt.type) {
3149373960d7SArd Biesheuvel 		case CRYPTO_ALG_TYPE_SKCIPHER:
3150373960d7SArd Biesheuvel 			crypto_unregister_skcipher(&t_alg->algt.alg.skcipher);
3151acbf7c62SLee Nipper 			break;
3152aeb4c132SHerbert Xu 		case CRYPTO_ALG_TYPE_AEAD:
3153aeb4c132SHerbert Xu 			crypto_unregister_aead(&t_alg->algt.alg.aead);
31545fc194eaSGustavo A. R. Silva 			break;
3155acbf7c62SLee Nipper 		case CRYPTO_ALG_TYPE_AHASH:
3156acbf7c62SLee Nipper 			crypto_unregister_ahash(&t_alg->algt.alg.hash);
3157acbf7c62SLee Nipper 			break;
3158acbf7c62SLee Nipper 		}
31599c4a7965SKim Phillips 		list_del(&t_alg->entry);
31609c4a7965SKim Phillips 	}
31619c4a7965SKim Phillips 
31629c4a7965SKim Phillips 	if (hw_supports(dev, DESC_HDR_SEL0_RNG))
31639c4a7965SKim Phillips 		talitos_unregister_rng(dev);
31649c4a7965SKim Phillips 
3165c3e337f8SKim Phillips 	for (i = 0; i < 2; i++)
31662cdba3cfSKim Phillips 		if (priv->irq[i]) {
3167c3e337f8SKim Phillips 			free_irq(priv->irq[i], dev);
3168c3e337f8SKim Phillips 			irq_dispose_mapping(priv->irq[i]);
31699c4a7965SKim Phillips 		}
31709c4a7965SKim Phillips 
3171c3e337f8SKim Phillips 	tasklet_kill(&priv->done_task[0]);
31722cdba3cfSKim Phillips 	if (priv->irq[1])
3173c3e337f8SKim Phillips 		tasklet_kill(&priv->done_task[1]);
31749c4a7965SKim Phillips }
31759c4a7965SKim Phillips 
talitos_alg_alloc(struct device * dev,struct talitos_alg_template * template)31769c4a7965SKim Phillips static struct talitos_crypto_alg *talitos_alg_alloc(struct device *dev,
31779c4a7965SKim Phillips 						    struct talitos_alg_template
31789c4a7965SKim Phillips 						           *template)
31799c4a7965SKim Phillips {
318060f208d7SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
31819c4a7965SKim Phillips 	struct talitos_crypto_alg *t_alg;
31829c4a7965SKim Phillips 	struct crypto_alg *alg;
31839c4a7965SKim Phillips 
318424b92ff2SLEROY Christophe 	t_alg = devm_kzalloc(dev, sizeof(struct talitos_crypto_alg),
318524b92ff2SLEROY Christophe 			     GFP_KERNEL);
31869c4a7965SKim Phillips 	if (!t_alg)
31879c4a7965SKim Phillips 		return ERR_PTR(-ENOMEM);
31889c4a7965SKim Phillips 
3189acbf7c62SLee Nipper 	t_alg->algt = *template;
3190acbf7c62SLee Nipper 
3191acbf7c62SLee Nipper 	switch (t_alg->algt.type) {
3192373960d7SArd Biesheuvel 	case CRYPTO_ALG_TYPE_SKCIPHER:
3193373960d7SArd Biesheuvel 		alg = &t_alg->algt.alg.skcipher.base;
31942e13ce08SLEROY Christophe 		alg->cra_exit = talitos_cra_exit;
3195373960d7SArd Biesheuvel 		t_alg->algt.alg.skcipher.init = talitos_cra_init_skcipher;
3196373960d7SArd Biesheuvel 		t_alg->algt.alg.skcipher.setkey =
3197373960d7SArd Biesheuvel 			t_alg->algt.alg.skcipher.setkey ?: skcipher_setkey;
3198373960d7SArd Biesheuvel 		t_alg->algt.alg.skcipher.encrypt = skcipher_encrypt;
3199373960d7SArd Biesheuvel 		t_alg->algt.alg.skcipher.decrypt = skcipher_decrypt;
320043a942d2SChristophe Leroy 		if (!strcmp(alg->cra_name, "ctr(aes)") && !has_ftr_sec1(priv) &&
320143a942d2SChristophe Leroy 		    DESC_TYPE(t_alg->algt.desc_hdr_template) !=
320243a942d2SChristophe Leroy 		    DESC_TYPE(DESC_HDR_TYPE_AESU_CTR_NONSNOOP)) {
320343a942d2SChristophe Leroy 			devm_kfree(dev, t_alg);
320443a942d2SChristophe Leroy 			return ERR_PTR(-ENOTSUPP);
320543a942d2SChristophe Leroy 		}
3206497f2e6bSLee Nipper 		break;
3207acbf7c62SLee Nipper 	case CRYPTO_ALG_TYPE_AEAD:
3208aeb4c132SHerbert Xu 		alg = &t_alg->algt.alg.aead.base;
32092e13ce08SLEROY Christophe 		alg->cra_exit = talitos_cra_exit;
3210aeb4c132SHerbert Xu 		t_alg->algt.alg.aead.init = talitos_cra_init_aead;
3211ef7c5c85SHerbert Xu 		t_alg->algt.alg.aead.setkey = t_alg->algt.alg.aead.setkey ?:
3212ef7c5c85SHerbert Xu 					      aead_setkey;
3213aeb4c132SHerbert Xu 		t_alg->algt.alg.aead.encrypt = aead_encrypt;
3214aeb4c132SHerbert Xu 		t_alg->algt.alg.aead.decrypt = aead_decrypt;
32156cda075aSLEROY Christophe 		if (!(priv->features & TALITOS_FTR_SHA224_HWINIT) &&
32166cda075aSLEROY Christophe 		    !strncmp(alg->cra_name, "authenc(hmac(sha224)", 20)) {
321724b92ff2SLEROY Christophe 			devm_kfree(dev, t_alg);
32186cda075aSLEROY Christophe 			return ERR_PTR(-ENOTSUPP);
32196cda075aSLEROY Christophe 		}
3220acbf7c62SLee Nipper 		break;
3221acbf7c62SLee Nipper 	case CRYPTO_ALG_TYPE_AHASH:
3222acbf7c62SLee Nipper 		alg = &t_alg->algt.alg.hash.halg.base;
3223497f2e6bSLee Nipper 		alg->cra_init = talitos_cra_init_ahash;
3224ad4cd51fSLEROY Christophe 		alg->cra_exit = talitos_cra_exit;
3225b286e003SKim Phillips 		t_alg->algt.alg.hash.init = ahash_init;
3226b286e003SKim Phillips 		t_alg->algt.alg.hash.update = ahash_update;
3227b286e003SKim Phillips 		t_alg->algt.alg.hash.final = ahash_final;
3228b286e003SKim Phillips 		t_alg->algt.alg.hash.finup = ahash_finup;
3229b286e003SKim Phillips 		t_alg->algt.alg.hash.digest = ahash_digest;
323056136631SLEROY Christophe 		if (!strncmp(alg->cra_name, "hmac", 4))
3231b286e003SKim Phillips 			t_alg->algt.alg.hash.setkey = ahash_setkey;
32323639ca84SHoria Geant? 		t_alg->algt.alg.hash.import = ahash_import;
32333639ca84SHoria Geant? 		t_alg->algt.alg.hash.export = ahash_export;
3234b286e003SKim Phillips 
323579b3a418SLee Nipper 		if (!(priv->features & TALITOS_FTR_HMAC_OK) &&
32360b2730d8SKim Phillips 		    !strncmp(alg->cra_name, "hmac", 4)) {
323724b92ff2SLEROY Christophe 			devm_kfree(dev, t_alg);
323879b3a418SLee Nipper 			return ERR_PTR(-ENOTSUPP);
32390b2730d8SKim Phillips 		}
324060f208d7SKim Phillips 		if (!(priv->features & TALITOS_FTR_SHA224_HWINIT) &&
324179b3a418SLee Nipper 		    (!strcmp(alg->cra_name, "sha224") ||
324279b3a418SLee Nipper 		     !strcmp(alg->cra_name, "hmac(sha224)"))) {
324360f208d7SKim Phillips 			t_alg->algt.alg.hash.init = ahash_init_sha224_swinit;
3244*9826d1d6SEric Biggers 			t_alg->algt.alg.hash.digest =
3245*9826d1d6SEric Biggers 				ahash_digest_sha224_swinit;
324660f208d7SKim Phillips 			t_alg->algt.desc_hdr_template =
324760f208d7SKim Phillips 					DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
324860f208d7SKim Phillips 					DESC_HDR_SEL0_MDEUA |
324960f208d7SKim Phillips 					DESC_HDR_MODE0_MDEU_SHA256;
325060f208d7SKim Phillips 		}
3251497f2e6bSLee Nipper 		break;
32521d11911aSKim Phillips 	default:
32531d11911aSKim Phillips 		dev_err(dev, "unknown algorithm type %d\n", t_alg->algt.type);
325424b92ff2SLEROY Christophe 		devm_kfree(dev, t_alg);
32551d11911aSKim Phillips 		return ERR_PTR(-EINVAL);
3256acbf7c62SLee Nipper 	}
32579c4a7965SKim Phillips 
32589c4a7965SKim Phillips 	alg->cra_module = THIS_MODULE;
3259b0057763SLEROY Christophe 	if (t_alg->algt.priority)
3260b0057763SLEROY Christophe 		alg->cra_priority = t_alg->algt.priority;
3261b0057763SLEROY Christophe 	else
32629c4a7965SKim Phillips 		alg->cra_priority = TALITOS_CRA_PRIORITY;
3263492444c3SEric Biggers 	if (has_ftr_sec1(priv) && t_alg->algt.type != CRYPTO_ALG_TYPE_AHASH)
3264c9cca703SChristophe Leroy 		alg->cra_alignmask = 3;
3265c9cca703SChristophe Leroy 	else
32669c4a7965SKim Phillips 		alg->cra_alignmask = 0;
32679c4a7965SKim Phillips 	alg->cra_ctxsize = sizeof(struct talitos_ctx);
3268d912bb76SNikos Mavrogiannopoulos 	alg->cra_flags |= CRYPTO_ALG_KERN_DRIVER_ONLY;
32699c4a7965SKim Phillips 
32709c4a7965SKim Phillips 	t_alg->dev = dev;
32719c4a7965SKim Phillips 
32729c4a7965SKim Phillips 	return t_alg;
32739c4a7965SKim Phillips }
32749c4a7965SKim Phillips 
talitos_probe_irq(struct platform_device * ofdev)3275c3e337f8SKim Phillips static int talitos_probe_irq(struct platform_device *ofdev)
3276c3e337f8SKim Phillips {
3277c3e337f8SKim Phillips 	struct device *dev = &ofdev->dev;
3278c3e337f8SKim Phillips 	struct device_node *np = ofdev->dev.of_node;
3279c3e337f8SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
3280c3e337f8SKim Phillips 	int err;
3281dd3c0987SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
3282c3e337f8SKim Phillips 
3283c3e337f8SKim Phillips 	priv->irq[0] = irq_of_parse_and_map(np, 0);
32842cdba3cfSKim Phillips 	if (!priv->irq[0]) {
3285c3e337f8SKim Phillips 		dev_err(dev, "failed to map irq\n");
3286c3e337f8SKim Phillips 		return -EINVAL;
3287c3e337f8SKim Phillips 	}
3288dd3c0987SLEROY Christophe 	if (is_sec1) {
3289dd3c0987SLEROY Christophe 		err = request_irq(priv->irq[0], talitos1_interrupt_4ch, 0,
3290dd3c0987SLEROY Christophe 				  dev_driver_string(dev), dev);
3291dd3c0987SLEROY Christophe 		goto primary_out;
3292dd3c0987SLEROY Christophe 	}
3293c3e337f8SKim Phillips 
3294c3e337f8SKim Phillips 	priv->irq[1] = irq_of_parse_and_map(np, 1);
3295c3e337f8SKim Phillips 
3296c3e337f8SKim Phillips 	/* get the primary irq line */
32972cdba3cfSKim Phillips 	if (!priv->irq[1]) {
3298dd3c0987SLEROY Christophe 		err = request_irq(priv->irq[0], talitos2_interrupt_4ch, 0,
3299c3e337f8SKim Phillips 				  dev_driver_string(dev), dev);
3300c3e337f8SKim Phillips 		goto primary_out;
3301c3e337f8SKim Phillips 	}
3302c3e337f8SKim Phillips 
3303dd3c0987SLEROY Christophe 	err = request_irq(priv->irq[0], talitos2_interrupt_ch0_2, 0,
3304c3e337f8SKim Phillips 			  dev_driver_string(dev), dev);
3305c3e337f8SKim Phillips 	if (err)
3306c3e337f8SKim Phillips 		goto primary_out;
3307c3e337f8SKim Phillips 
3308c3e337f8SKim Phillips 	/* get the secondary irq line */
3309dd3c0987SLEROY Christophe 	err = request_irq(priv->irq[1], talitos2_interrupt_ch1_3, 0,
3310c3e337f8SKim Phillips 			  dev_driver_string(dev), dev);
3311c3e337f8SKim Phillips 	if (err) {
3312c3e337f8SKim Phillips 		dev_err(dev, "failed to request secondary irq\n");
3313c3e337f8SKim Phillips 		irq_dispose_mapping(priv->irq[1]);
33142cdba3cfSKim Phillips 		priv->irq[1] = 0;
3315c3e337f8SKim Phillips 	}
3316c3e337f8SKim Phillips 
3317c3e337f8SKim Phillips 	return err;
3318c3e337f8SKim Phillips 
3319c3e337f8SKim Phillips primary_out:
3320c3e337f8SKim Phillips 	if (err) {
3321c3e337f8SKim Phillips 		dev_err(dev, "failed to request primary irq\n");
3322c3e337f8SKim Phillips 		irq_dispose_mapping(priv->irq[0]);
33232cdba3cfSKim Phillips 		priv->irq[0] = 0;
3324c3e337f8SKim Phillips 	}
3325c3e337f8SKim Phillips 
3326c3e337f8SKim Phillips 	return err;
3327c3e337f8SKim Phillips }
3328c3e337f8SKim Phillips 
talitos_probe(struct platform_device * ofdev)33291c48a5c9SGrant Likely static int talitos_probe(struct platform_device *ofdev)
33309c4a7965SKim Phillips {
33319c4a7965SKim Phillips 	struct device *dev = &ofdev->dev;
333261c7a080SGrant Likely 	struct device_node *np = ofdev->dev.of_node;
33339c4a7965SKim Phillips 	struct talitos_private *priv;
33349c4a7965SKim Phillips 	int i, err;
33355fa7fa14SLEROY Christophe 	int stride;
3336fd5ea7f0SLEROY Christophe 	struct resource *res;
33379c4a7965SKim Phillips 
333824b92ff2SLEROY Christophe 	priv = devm_kzalloc(dev, sizeof(struct talitos_private), GFP_KERNEL);
33399c4a7965SKim Phillips 	if (!priv)
33409c4a7965SKim Phillips 		return -ENOMEM;
33419c4a7965SKim Phillips 
3342f3de9cb1SKevin Hao 	INIT_LIST_HEAD(&priv->alg_list);
3343f3de9cb1SKevin Hao 
33449c4a7965SKim Phillips 	dev_set_drvdata(dev, priv);
33459c4a7965SKim Phillips 
33469c4a7965SKim Phillips 	priv->ofdev = ofdev;
33479c4a7965SKim Phillips 
3348511d63cbSHoria Geanta 	spin_lock_init(&priv->reg_lock);
3349511d63cbSHoria Geanta 
3350fd5ea7f0SLEROY Christophe 	res = platform_get_resource(ofdev, IORESOURCE_MEM, 0);
3351fd5ea7f0SLEROY Christophe 	if (!res)
3352fd5ea7f0SLEROY Christophe 		return -ENXIO;
3353fd5ea7f0SLEROY Christophe 	priv->reg = devm_ioremap(dev, res->start, resource_size(res));
33549c4a7965SKim Phillips 	if (!priv->reg) {
33559c4a7965SKim Phillips 		dev_err(dev, "failed to of_iomap\n");
33569c4a7965SKim Phillips 		err = -ENOMEM;
33579c4a7965SKim Phillips 		goto err_out;
33589c4a7965SKim Phillips 	}
33599c4a7965SKim Phillips 
33609c4a7965SKim Phillips 	/* get SEC version capabilities from device tree */
3361fa14c6cfSLEROY Christophe 	of_property_read_u32(np, "fsl,num-channels", &priv->num_channels);
3362fa14c6cfSLEROY Christophe 	of_property_read_u32(np, "fsl,channel-fifo-len", &priv->chfifo_len);
3363fa14c6cfSLEROY Christophe 	of_property_read_u32(np, "fsl,exec-units-mask", &priv->exec_units);
3364fa14c6cfSLEROY Christophe 	of_property_read_u32(np, "fsl,descriptor-types-mask",
3365fa14c6cfSLEROY Christophe 			     &priv->desc_types);
33669c4a7965SKim Phillips 
33679c4a7965SKim Phillips 	if (!is_power_of_2(priv->num_channels) || !priv->chfifo_len ||
33689c4a7965SKim Phillips 	    !priv->exec_units || !priv->desc_types) {
33699c4a7965SKim Phillips 		dev_err(dev, "invalid property data in device tree node\n");
33709c4a7965SKim Phillips 		err = -EINVAL;
33719c4a7965SKim Phillips 		goto err_out;
33729c4a7965SKim Phillips 	}
33739c4a7965SKim Phillips 
3374f3c85bc1SLee Nipper 	if (of_device_is_compatible(np, "fsl,sec3.0"))
3375f3c85bc1SLee Nipper 		priv->features |= TALITOS_FTR_SRC_LINK_TBL_LEN_INCLUDES_EXTENT;
3376f3c85bc1SLee Nipper 
3377fe5720e2SKim Phillips 	if (of_device_is_compatible(np, "fsl,sec2.1"))
337860f208d7SKim Phillips 		priv->features |= TALITOS_FTR_HW_AUTH_CHECK |
337979b3a418SLee Nipper 				  TALITOS_FTR_SHA224_HWINIT |
338079b3a418SLee Nipper 				  TALITOS_FTR_HMAC_OK;
3381fe5720e2SKim Phillips 
338221590888SLEROY Christophe 	if (of_device_is_compatible(np, "fsl,sec1.0"))
338321590888SLEROY Christophe 		priv->features |= TALITOS_FTR_SEC1;
338421590888SLEROY Christophe 
33855fa7fa14SLEROY Christophe 	if (of_device_is_compatible(np, "fsl,sec1.2")) {
33865fa7fa14SLEROY Christophe 		priv->reg_deu = priv->reg + TALITOS12_DEU;
33875fa7fa14SLEROY Christophe 		priv->reg_aesu = priv->reg + TALITOS12_AESU;
33885fa7fa14SLEROY Christophe 		priv->reg_mdeu = priv->reg + TALITOS12_MDEU;
33895fa7fa14SLEROY Christophe 		stride = TALITOS1_CH_STRIDE;
33905fa7fa14SLEROY Christophe 	} else if (of_device_is_compatible(np, "fsl,sec1.0")) {
33915fa7fa14SLEROY Christophe 		priv->reg_deu = priv->reg + TALITOS10_DEU;
33925fa7fa14SLEROY Christophe 		priv->reg_aesu = priv->reg + TALITOS10_AESU;
33935fa7fa14SLEROY Christophe 		priv->reg_mdeu = priv->reg + TALITOS10_MDEU;
33945fa7fa14SLEROY Christophe 		priv->reg_afeu = priv->reg + TALITOS10_AFEU;
33955fa7fa14SLEROY Christophe 		priv->reg_rngu = priv->reg + TALITOS10_RNGU;
33965fa7fa14SLEROY Christophe 		priv->reg_pkeu = priv->reg + TALITOS10_PKEU;
33975fa7fa14SLEROY Christophe 		stride = TALITOS1_CH_STRIDE;
33985fa7fa14SLEROY Christophe 	} else {
33995fa7fa14SLEROY Christophe 		priv->reg_deu = priv->reg + TALITOS2_DEU;
34005fa7fa14SLEROY Christophe 		priv->reg_aesu = priv->reg + TALITOS2_AESU;
34015fa7fa14SLEROY Christophe 		priv->reg_mdeu = priv->reg + TALITOS2_MDEU;
34025fa7fa14SLEROY Christophe 		priv->reg_afeu = priv->reg + TALITOS2_AFEU;
34035fa7fa14SLEROY Christophe 		priv->reg_rngu = priv->reg + TALITOS2_RNGU;
34045fa7fa14SLEROY Christophe 		priv->reg_pkeu = priv->reg + TALITOS2_PKEU;
34055fa7fa14SLEROY Christophe 		priv->reg_keu = priv->reg + TALITOS2_KEU;
34065fa7fa14SLEROY Christophe 		priv->reg_crcu = priv->reg + TALITOS2_CRCU;
34075fa7fa14SLEROY Christophe 		stride = TALITOS2_CH_STRIDE;
34085fa7fa14SLEROY Christophe 	}
34095fa7fa14SLEROY Christophe 
3410dd3c0987SLEROY Christophe 	err = talitos_probe_irq(ofdev);
3411dd3c0987SLEROY Christophe 	if (err)
3412dd3c0987SLEROY Christophe 		goto err_out;
3413dd3c0987SLEROY Christophe 
3414c8c74647SChristophe Leroy 	if (has_ftr_sec1(priv)) {
34159c02e285SLEROY Christophe 		if (priv->num_channels == 1)
34169c02e285SLEROY Christophe 			tasklet_init(&priv->done_task[0], talitos1_done_ch0,
34179c02e285SLEROY Christophe 				     (unsigned long)dev);
34189c02e285SLEROY Christophe 		else
3419dd3c0987SLEROY Christophe 			tasklet_init(&priv->done_task[0], talitos1_done_4ch,
3420dd3c0987SLEROY Christophe 				     (unsigned long)dev);
3421dd3c0987SLEROY Christophe 	} else {
34229c02e285SLEROY Christophe 		if (priv->irq[1]) {
3423dd3c0987SLEROY Christophe 			tasklet_init(&priv->done_task[0], talitos2_done_ch0_2,
3424dd3c0987SLEROY Christophe 				     (unsigned long)dev);
3425dd3c0987SLEROY Christophe 			tasklet_init(&priv->done_task[1], talitos2_done_ch1_3,
3426dd3c0987SLEROY Christophe 				     (unsigned long)dev);
34279c02e285SLEROY Christophe 		} else if (priv->num_channels == 1) {
34289c02e285SLEROY Christophe 			tasklet_init(&priv->done_task[0], talitos2_done_ch0,
34299c02e285SLEROY Christophe 				     (unsigned long)dev);
34309c02e285SLEROY Christophe 		} else {
34319c02e285SLEROY Christophe 			tasklet_init(&priv->done_task[0], talitos2_done_4ch,
34329c02e285SLEROY Christophe 				     (unsigned long)dev);
3433dd3c0987SLEROY Christophe 		}
3434dd3c0987SLEROY Christophe 	}
3435dd3c0987SLEROY Christophe 
3436a86854d0SKees Cook 	priv->chan = devm_kcalloc(dev,
3437a86854d0SKees Cook 				  priv->num_channels,
3438a86854d0SKees Cook 				  sizeof(struct talitos_channel),
3439a86854d0SKees Cook 				  GFP_KERNEL);
34404b992628SKim Phillips 	if (!priv->chan) {
34414b992628SKim Phillips 		dev_err(dev, "failed to allocate channel management space\n");
34429c4a7965SKim Phillips 		err = -ENOMEM;
34439c4a7965SKim Phillips 		goto err_out;
34449c4a7965SKim Phillips 	}
34459c4a7965SKim Phillips 
3446f641ddddSMartin Hicks 	priv->fifo_len = roundup_pow_of_two(priv->chfifo_len);
3447f641ddddSMartin Hicks 
3448c3e337f8SKim Phillips 	for (i = 0; i < priv->num_channels; i++) {
34495fa7fa14SLEROY Christophe 		priv->chan[i].reg = priv->reg + stride * (i + 1);
34502cdba3cfSKim Phillips 		if (!priv->irq[1] || !(i & 1))
3451c3e337f8SKim Phillips 			priv->chan[i].reg += TALITOS_CH_BASE_OFFSET;
3452ad42d5fcSKim Phillips 
34534b992628SKim Phillips 		spin_lock_init(&priv->chan[i].head_lock);
34544b992628SKim Phillips 		spin_lock_init(&priv->chan[i].tail_lock);
34559c4a7965SKim Phillips 
3456a86854d0SKees Cook 		priv->chan[i].fifo = devm_kcalloc(dev,
3457a86854d0SKees Cook 						priv->fifo_len,
3458a86854d0SKees Cook 						sizeof(struct talitos_request),
3459a86854d0SKees Cook 						GFP_KERNEL);
34604b992628SKim Phillips 		if (!priv->chan[i].fifo) {
34619c4a7965SKim Phillips 			dev_err(dev, "failed to allocate request fifo %d\n", i);
34629c4a7965SKim Phillips 			err = -ENOMEM;
34639c4a7965SKim Phillips 			goto err_out;
34649c4a7965SKim Phillips 		}
34659c4a7965SKim Phillips 
34664b992628SKim Phillips 		atomic_set(&priv->chan[i].submit_count,
34674b992628SKim Phillips 			   -(priv->chfifo_len - 1));
3468f641ddddSMartin Hicks 	}
34699c4a7965SKim Phillips 
347081eb024cSKim Phillips 	dma_set_mask(dev, DMA_BIT_MASK(36));
347181eb024cSKim Phillips 
34729c4a7965SKim Phillips 	/* reset and initialize the h/w */
34739c4a7965SKim Phillips 	err = init_device(dev);
34749c4a7965SKim Phillips 	if (err) {
34759c4a7965SKim Phillips 		dev_err(dev, "failed to initialize device\n");
34769c4a7965SKim Phillips 		goto err_out;
34779c4a7965SKim Phillips 	}
34789c4a7965SKim Phillips 
34799c4a7965SKim Phillips 	/* register the RNG, if available */
34809c4a7965SKim Phillips 	if (hw_supports(dev, DESC_HDR_SEL0_RNG)) {
34819c4a7965SKim Phillips 		err = talitos_register_rng(dev);
34829c4a7965SKim Phillips 		if (err) {
34839c4a7965SKim Phillips 			dev_err(dev, "failed to register hwrng: %d\n", err);
34849c4a7965SKim Phillips 			goto err_out;
34859c4a7965SKim Phillips 		} else
34869c4a7965SKim Phillips 			dev_info(dev, "hwrng\n");
34879c4a7965SKim Phillips 	}
34889c4a7965SKim Phillips 
34899c4a7965SKim Phillips 	/* register crypto algorithms the device supports */
34909c4a7965SKim Phillips 	for (i = 0; i < ARRAY_SIZE(driver_algs); i++) {
34919c4a7965SKim Phillips 		if (hw_supports(dev, driver_algs[i].desc_hdr_template)) {
34929c4a7965SKim Phillips 			struct talitos_crypto_alg *t_alg;
3493aeb4c132SHerbert Xu 			struct crypto_alg *alg = NULL;
34949c4a7965SKim Phillips 
34959c4a7965SKim Phillips 			t_alg = talitos_alg_alloc(dev, &driver_algs[i]);
34969c4a7965SKim Phillips 			if (IS_ERR(t_alg)) {
34979c4a7965SKim Phillips 				err = PTR_ERR(t_alg);
34980b2730d8SKim Phillips 				if (err == -ENOTSUPP)
349979b3a418SLee Nipper 					continue;
35009c4a7965SKim Phillips 				goto err_out;
35019c4a7965SKim Phillips 			}
35029c4a7965SKim Phillips 
3503acbf7c62SLee Nipper 			switch (t_alg->algt.type) {
3504373960d7SArd Biesheuvel 			case CRYPTO_ALG_TYPE_SKCIPHER:
3505373960d7SArd Biesheuvel 				err = crypto_register_skcipher(
3506373960d7SArd Biesheuvel 						&t_alg->algt.alg.skcipher);
3507373960d7SArd Biesheuvel 				alg = &t_alg->algt.alg.skcipher.base;
3508acbf7c62SLee Nipper 				break;
3509aeb4c132SHerbert Xu 
3510aeb4c132SHerbert Xu 			case CRYPTO_ALG_TYPE_AEAD:
3511aeb4c132SHerbert Xu 				err = crypto_register_aead(
3512aeb4c132SHerbert Xu 					&t_alg->algt.alg.aead);
3513aeb4c132SHerbert Xu 				alg = &t_alg->algt.alg.aead.base;
3514aeb4c132SHerbert Xu 				break;
3515aeb4c132SHerbert Xu 
3516acbf7c62SLee Nipper 			case CRYPTO_ALG_TYPE_AHASH:
3517acbf7c62SLee Nipper 				err = crypto_register_ahash(
3518acbf7c62SLee Nipper 						&t_alg->algt.alg.hash);
3519aeb4c132SHerbert Xu 				alg = &t_alg->algt.alg.hash.halg.base;
3520acbf7c62SLee Nipper 				break;
3521acbf7c62SLee Nipper 			}
35229c4a7965SKim Phillips 			if (err) {
35239c4a7965SKim Phillips 				dev_err(dev, "%s alg registration failed\n",
3524aeb4c132SHerbert Xu 					alg->cra_driver_name);
352524b92ff2SLEROY Christophe 				devm_kfree(dev, t_alg);
3526991155baSHoria Geanta 			} else
35279c4a7965SKim Phillips 				list_add_tail(&t_alg->entry, &priv->alg_list);
35289c4a7965SKim Phillips 		}
35299c4a7965SKim Phillips 	}
35305b859b6eSKim Phillips 	if (!list_empty(&priv->alg_list))
35315b859b6eSKim Phillips 		dev_info(dev, "%s algorithms registered in /proc/crypto\n",
35325b859b6eSKim Phillips 			 (char *)of_get_property(np, "compatible", NULL));
35339c4a7965SKim Phillips 
35349c4a7965SKim Phillips 	return 0;
35359c4a7965SKim Phillips 
35369c4a7965SKim Phillips err_out:
35379c4a7965SKim Phillips 	talitos_remove(ofdev);
35389c4a7965SKim Phillips 
35399c4a7965SKim Phillips 	return err;
35409c4a7965SKim Phillips }
35419c4a7965SKim Phillips 
35426c3f975aSMárton Németh static const struct of_device_id talitos_match[] = {
35430635b7dbSLEROY Christophe #ifdef CONFIG_CRYPTO_DEV_TALITOS1
35440635b7dbSLEROY Christophe 	{
35450635b7dbSLEROY Christophe 		.compatible = "fsl,sec1.0",
35460635b7dbSLEROY Christophe 	},
35470635b7dbSLEROY Christophe #endif
35480635b7dbSLEROY Christophe #ifdef CONFIG_CRYPTO_DEV_TALITOS2
35499c4a7965SKim Phillips 	{
35509c4a7965SKim Phillips 		.compatible = "fsl,sec2.0",
35519c4a7965SKim Phillips 	},
35520635b7dbSLEROY Christophe #endif
35539c4a7965SKim Phillips 	{},
35549c4a7965SKim Phillips };
35559c4a7965SKim Phillips MODULE_DEVICE_TABLE(of, talitos_match);
35569c4a7965SKim Phillips 
35571c48a5c9SGrant Likely static struct platform_driver talitos_driver = {
35584018294bSGrant Likely 	.driver = {
35599c4a7965SKim Phillips 		.name = "talitos",
35604018294bSGrant Likely 		.of_match_table = talitos_match,
35614018294bSGrant Likely 	},
35629c4a7965SKim Phillips 	.probe = talitos_probe,
3563ce52705eSUwe Kleine-König 	.remove_new = talitos_remove,
35649c4a7965SKim Phillips };
35659c4a7965SKim Phillips 
3566741e8c2dSAxel Lin module_platform_driver(talitos_driver);
35679c4a7965SKim Phillips 
35689c4a7965SKim Phillips MODULE_LICENSE("GPL");
35699c4a7965SKim Phillips MODULE_AUTHOR("Kim Phillips <kim.phillips@freescale.com>");
35709c4a7965SKim Phillips MODULE_DESCRIPTION("Freescale integrated security engine (SEC) driver");
3571