xref: /linux/drivers/crypto/talitos.c (revision a1a42f84011fae6ff08441a91aefeb7febc984fc)
19c4a7965SKim Phillips /*
29c4a7965SKim Phillips  * talitos - Freescale Integrated Security Engine (SEC) device driver
39c4a7965SKim Phillips  *
45228f0f7SKim Phillips  * Copyright (c) 2008-2011 Freescale Semiconductor, Inc.
59c4a7965SKim Phillips  *
69c4a7965SKim Phillips  * Scatterlist Crypto API glue code copied from files with the following:
79c4a7965SKim Phillips  * Copyright (c) 2006-2007 Herbert Xu <herbert@gondor.apana.org.au>
89c4a7965SKim Phillips  *
99c4a7965SKim Phillips  * Crypto algorithm registration code copied from hifn driver:
109c4a7965SKim Phillips  * 2007+ Copyright (c) Evgeniy Polyakov <johnpol@2ka.mipt.ru>
119c4a7965SKim Phillips  * All rights reserved.
129c4a7965SKim Phillips  *
139c4a7965SKim Phillips  * This program is free software; you can redistribute it and/or modify
149c4a7965SKim Phillips  * it under the terms of the GNU General Public License as published by
159c4a7965SKim Phillips  * the Free Software Foundation; either version 2 of the License, or
169c4a7965SKim Phillips  * (at your option) any later version.
179c4a7965SKim Phillips  *
189c4a7965SKim Phillips  * This program is distributed in the hope that it will be useful,
199c4a7965SKim Phillips  * but WITHOUT ANY WARRANTY; without even the implied warranty of
209c4a7965SKim Phillips  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
219c4a7965SKim Phillips  * GNU General Public License for more details.
229c4a7965SKim Phillips  *
239c4a7965SKim Phillips  * You should have received a copy of the GNU General Public License
249c4a7965SKim Phillips  * along with this program; if not, write to the Free Software
259c4a7965SKim Phillips  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
269c4a7965SKim Phillips  */
279c4a7965SKim Phillips 
289c4a7965SKim Phillips #include <linux/kernel.h>
299c4a7965SKim Phillips #include <linux/module.h>
309c4a7965SKim Phillips #include <linux/mod_devicetable.h>
319c4a7965SKim Phillips #include <linux/device.h>
329c4a7965SKim Phillips #include <linux/interrupt.h>
339c4a7965SKim Phillips #include <linux/crypto.h>
349c4a7965SKim Phillips #include <linux/hw_random.h>
355af50730SRob Herring #include <linux/of_address.h>
365af50730SRob Herring #include <linux/of_irq.h>
379c4a7965SKim Phillips #include <linux/of_platform.h>
389c4a7965SKim Phillips #include <linux/dma-mapping.h>
399c4a7965SKim Phillips #include <linux/io.h>
409c4a7965SKim Phillips #include <linux/spinlock.h>
419c4a7965SKim Phillips #include <linux/rtnetlink.h>
425a0e3ad6STejun Heo #include <linux/slab.h>
439c4a7965SKim Phillips 
449c4a7965SKim Phillips #include <crypto/algapi.h>
459c4a7965SKim Phillips #include <crypto/aes.h>
463952f17eSLee Nipper #include <crypto/des.h>
479c4a7965SKim Phillips #include <crypto/sha.h>
48497f2e6bSLee Nipper #include <crypto/md5.h>
49e98014abSHerbert Xu #include <crypto/internal/aead.h>
509c4a7965SKim Phillips #include <crypto/authenc.h>
514de9d0b5SLee Nipper #include <crypto/skcipher.h>
52acbf7c62SLee Nipper #include <crypto/hash.h>
53acbf7c62SLee Nipper #include <crypto/internal/hash.h>
544de9d0b5SLee Nipper #include <crypto/scatterwalk.h>
559c4a7965SKim Phillips 
569c4a7965SKim Phillips #include "talitos.h"
579c4a7965SKim Phillips 
58922f9dc8SLEROY Christophe static void to_talitos_ptr(struct talitos_ptr *ptr, dma_addr_t dma_addr,
59da9de146SLEROY Christophe 			   unsigned int len, bool is_sec1)
6081eb024cSKim Phillips {
61edc6bd69SLEROY Christophe 	ptr->ptr = cpu_to_be32(lower_32_bits(dma_addr));
62da9de146SLEROY Christophe 	if (is_sec1) {
63da9de146SLEROY Christophe 		ptr->len1 = cpu_to_be16(len);
64da9de146SLEROY Christophe 	} else {
65da9de146SLEROY Christophe 		ptr->len = cpu_to_be16(len);
66edc6bd69SLEROY Christophe 		ptr->eptr = upper_32_bits(dma_addr);
6781eb024cSKim Phillips 	}
68da9de146SLEROY Christophe }
6981eb024cSKim Phillips 
70340ff60aSHoria Geant? static void copy_talitos_ptr(struct talitos_ptr *dst_ptr,
71340ff60aSHoria Geant? 			     struct talitos_ptr *src_ptr, bool is_sec1)
72340ff60aSHoria Geant? {
73340ff60aSHoria Geant? 	dst_ptr->ptr = src_ptr->ptr;
74922f9dc8SLEROY Christophe 	if (is_sec1) {
75da9de146SLEROY Christophe 		dst_ptr->len1 = src_ptr->len1;
76922f9dc8SLEROY Christophe 	} else {
77da9de146SLEROY Christophe 		dst_ptr->len = src_ptr->len;
78da9de146SLEROY Christophe 		dst_ptr->eptr = src_ptr->eptr;
79538caf83SLEROY Christophe 	}
80922f9dc8SLEROY Christophe }
81538caf83SLEROY Christophe 
82922f9dc8SLEROY Christophe static unsigned short from_talitos_ptr_len(struct talitos_ptr *ptr,
83922f9dc8SLEROY Christophe 					   bool is_sec1)
84538caf83SLEROY Christophe {
85922f9dc8SLEROY Christophe 	if (is_sec1)
86922f9dc8SLEROY Christophe 		return be16_to_cpu(ptr->len1);
87922f9dc8SLEROY Christophe 	else
88538caf83SLEROY Christophe 		return be16_to_cpu(ptr->len);
89538caf83SLEROY Christophe }
90538caf83SLEROY Christophe 
91b096b544SLEROY Christophe static void to_talitos_ptr_ext_set(struct talitos_ptr *ptr, u8 val,
92b096b544SLEROY Christophe 				   bool is_sec1)
93185eb79fSLEROY Christophe {
94922f9dc8SLEROY Christophe 	if (!is_sec1)
95b096b544SLEROY Christophe 		ptr->j_extent = val;
96b096b544SLEROY Christophe }
97b096b544SLEROY Christophe 
98b096b544SLEROY Christophe static void to_talitos_ptr_ext_or(struct talitos_ptr *ptr, u8 val, bool is_sec1)
99b096b544SLEROY Christophe {
100b096b544SLEROY Christophe 	if (!is_sec1)
101b096b544SLEROY Christophe 		ptr->j_extent |= val;
102185eb79fSLEROY Christophe }
103185eb79fSLEROY Christophe 
1049c4a7965SKim Phillips /*
1059c4a7965SKim Phillips  * map virtual single (contiguous) pointer to h/w descriptor pointer
1069c4a7965SKim Phillips  */
1076a4967c3SLEROY Christophe static void __map_single_talitos_ptr(struct device *dev,
1086a4967c3SLEROY Christophe 				     struct talitos_ptr *ptr,
1096a4967c3SLEROY Christophe 				     unsigned int len, void *data,
1106a4967c3SLEROY Christophe 				     enum dma_data_direction dir,
1116a4967c3SLEROY Christophe 				     unsigned long attrs)
1126a4967c3SLEROY Christophe {
1136a4967c3SLEROY Christophe 	dma_addr_t dma_addr = dma_map_single_attrs(dev, data, len, dir, attrs);
1146a4967c3SLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
1156a4967c3SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
1166a4967c3SLEROY Christophe 
1176a4967c3SLEROY Christophe 	to_talitos_ptr(ptr, dma_addr, len, is_sec1);
1186a4967c3SLEROY Christophe }
1196a4967c3SLEROY Christophe 
1209c4a7965SKim Phillips static void map_single_talitos_ptr(struct device *dev,
121edc6bd69SLEROY Christophe 				   struct talitos_ptr *ptr,
12242e8b0d7SHoria Geant? 				   unsigned int len, void *data,
1239c4a7965SKim Phillips 				   enum dma_data_direction dir)
1249c4a7965SKim Phillips {
1256a4967c3SLEROY Christophe 	__map_single_talitos_ptr(dev, ptr, len, data, dir, 0);
1266a4967c3SLEROY Christophe }
12781eb024cSKim Phillips 
1286a4967c3SLEROY Christophe static void map_single_talitos_ptr_nosync(struct device *dev,
1296a4967c3SLEROY Christophe 					  struct talitos_ptr *ptr,
1306a4967c3SLEROY Christophe 					  unsigned int len, void *data,
1316a4967c3SLEROY Christophe 					  enum dma_data_direction dir)
1326a4967c3SLEROY Christophe {
1336a4967c3SLEROY Christophe 	__map_single_talitos_ptr(dev, ptr, len, data, dir,
1346a4967c3SLEROY Christophe 				 DMA_ATTR_SKIP_CPU_SYNC);
1359c4a7965SKim Phillips }
1369c4a7965SKim Phillips 
1379c4a7965SKim Phillips /*
1389c4a7965SKim Phillips  * unmap bus single (contiguous) h/w descriptor pointer
1399c4a7965SKim Phillips  */
1409c4a7965SKim Phillips static void unmap_single_talitos_ptr(struct device *dev,
141edc6bd69SLEROY Christophe 				     struct talitos_ptr *ptr,
1429c4a7965SKim Phillips 				     enum dma_data_direction dir)
1439c4a7965SKim Phillips {
144922f9dc8SLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
145922f9dc8SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
146922f9dc8SLEROY Christophe 
147edc6bd69SLEROY Christophe 	dma_unmap_single(dev, be32_to_cpu(ptr->ptr),
148922f9dc8SLEROY Christophe 			 from_talitos_ptr_len(ptr, is_sec1), dir);
1499c4a7965SKim Phillips }
1509c4a7965SKim Phillips 
1519c4a7965SKim Phillips static int reset_channel(struct device *dev, int ch)
1529c4a7965SKim Phillips {
1539c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
1549c4a7965SKim Phillips 	unsigned int timeout = TALITOS_TIMEOUT;
155dd3c0987SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
1569c4a7965SKim Phillips 
157dd3c0987SLEROY Christophe 	if (is_sec1) {
158dd3c0987SLEROY Christophe 		setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO,
159dd3c0987SLEROY Christophe 			  TALITOS1_CCCR_LO_RESET);
1609c4a7965SKim Phillips 
161dd3c0987SLEROY Christophe 		while ((in_be32(priv->chan[ch].reg + TALITOS_CCCR_LO) &
162dd3c0987SLEROY Christophe 			TALITOS1_CCCR_LO_RESET) && --timeout)
1639c4a7965SKim Phillips 			cpu_relax();
164dd3c0987SLEROY Christophe 	} else {
165dd3c0987SLEROY Christophe 		setbits32(priv->chan[ch].reg + TALITOS_CCCR,
166dd3c0987SLEROY Christophe 			  TALITOS2_CCCR_RESET);
167dd3c0987SLEROY Christophe 
168dd3c0987SLEROY Christophe 		while ((in_be32(priv->chan[ch].reg + TALITOS_CCCR) &
169dd3c0987SLEROY Christophe 			TALITOS2_CCCR_RESET) && --timeout)
170dd3c0987SLEROY Christophe 			cpu_relax();
171dd3c0987SLEROY Christophe 	}
1729c4a7965SKim Phillips 
1739c4a7965SKim Phillips 	if (timeout == 0) {
1749c4a7965SKim Phillips 		dev_err(dev, "failed to reset channel %d\n", ch);
1759c4a7965SKim Phillips 		return -EIO;
1769c4a7965SKim Phillips 	}
1779c4a7965SKim Phillips 
17881eb024cSKim Phillips 	/* set 36-bit addressing, done writeback enable and done IRQ enable */
179ad42d5fcSKim Phillips 	setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO, TALITOS_CCCR_LO_EAE |
18081eb024cSKim Phillips 		  TALITOS_CCCR_LO_CDWE | TALITOS_CCCR_LO_CDIE);
18137b5e889SLEROY Christophe 	/* enable chaining descriptors */
18237b5e889SLEROY Christophe 	if (is_sec1)
18337b5e889SLEROY Christophe 		setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO,
18437b5e889SLEROY Christophe 			  TALITOS_CCCR_LO_NE);
1859c4a7965SKim Phillips 
186fe5720e2SKim Phillips 	/* and ICCR writeback, if available */
187fe5720e2SKim Phillips 	if (priv->features & TALITOS_FTR_HW_AUTH_CHECK)
188ad42d5fcSKim Phillips 		setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO,
189fe5720e2SKim Phillips 		          TALITOS_CCCR_LO_IWSE);
190fe5720e2SKim Phillips 
1919c4a7965SKim Phillips 	return 0;
1929c4a7965SKim Phillips }
1939c4a7965SKim Phillips 
1949c4a7965SKim Phillips static int reset_device(struct device *dev)
1959c4a7965SKim Phillips {
1969c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
1979c4a7965SKim Phillips 	unsigned int timeout = TALITOS_TIMEOUT;
198dd3c0987SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
199dd3c0987SLEROY Christophe 	u32 mcr = is_sec1 ? TALITOS1_MCR_SWR : TALITOS2_MCR_SWR;
2009c4a7965SKim Phillips 
201c3e337f8SKim Phillips 	setbits32(priv->reg + TALITOS_MCR, mcr);
2029c4a7965SKim Phillips 
203dd3c0987SLEROY Christophe 	while ((in_be32(priv->reg + TALITOS_MCR) & mcr)
2049c4a7965SKim Phillips 	       && --timeout)
2059c4a7965SKim Phillips 		cpu_relax();
2069c4a7965SKim Phillips 
2072cdba3cfSKim Phillips 	if (priv->irq[1]) {
208c3e337f8SKim Phillips 		mcr = TALITOS_MCR_RCA1 | TALITOS_MCR_RCA3;
209c3e337f8SKim Phillips 		setbits32(priv->reg + TALITOS_MCR, mcr);
210c3e337f8SKim Phillips 	}
211c3e337f8SKim Phillips 
2129c4a7965SKim Phillips 	if (timeout == 0) {
2139c4a7965SKim Phillips 		dev_err(dev, "failed to reset device\n");
2149c4a7965SKim Phillips 		return -EIO;
2159c4a7965SKim Phillips 	}
2169c4a7965SKim Phillips 
2179c4a7965SKim Phillips 	return 0;
2189c4a7965SKim Phillips }
2199c4a7965SKim Phillips 
2209c4a7965SKim Phillips /*
2219c4a7965SKim Phillips  * Reset and initialize the device
2229c4a7965SKim Phillips  */
2239c4a7965SKim Phillips static int init_device(struct device *dev)
2249c4a7965SKim Phillips {
2259c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
2269c4a7965SKim Phillips 	int ch, err;
227dd3c0987SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
2289c4a7965SKim Phillips 
2299c4a7965SKim Phillips 	/*
2309c4a7965SKim Phillips 	 * Master reset
2319c4a7965SKim Phillips 	 * errata documentation: warning: certain SEC interrupts
2329c4a7965SKim Phillips 	 * are not fully cleared by writing the MCR:SWR bit,
2339c4a7965SKim Phillips 	 * set bit twice to completely reset
2349c4a7965SKim Phillips 	 */
2359c4a7965SKim Phillips 	err = reset_device(dev);
2369c4a7965SKim Phillips 	if (err)
2379c4a7965SKim Phillips 		return err;
2389c4a7965SKim Phillips 
2399c4a7965SKim Phillips 	err = reset_device(dev);
2409c4a7965SKim Phillips 	if (err)
2419c4a7965SKim Phillips 		return err;
2429c4a7965SKim Phillips 
2439c4a7965SKim Phillips 	/* reset channels */
2449c4a7965SKim Phillips 	for (ch = 0; ch < priv->num_channels; ch++) {
2459c4a7965SKim Phillips 		err = reset_channel(dev, ch);
2469c4a7965SKim Phillips 		if (err)
2479c4a7965SKim Phillips 			return err;
2489c4a7965SKim Phillips 	}
2499c4a7965SKim Phillips 
2509c4a7965SKim Phillips 	/* enable channel done and error interrupts */
251dd3c0987SLEROY Christophe 	if (is_sec1) {
252dd3c0987SLEROY Christophe 		clrbits32(priv->reg + TALITOS_IMR, TALITOS1_IMR_INIT);
253dd3c0987SLEROY Christophe 		clrbits32(priv->reg + TALITOS_IMR_LO, TALITOS1_IMR_LO_INIT);
254dd3c0987SLEROY Christophe 		/* disable parity error check in DEU (erroneous? test vect.) */
255dd3c0987SLEROY Christophe 		setbits32(priv->reg_deu + TALITOS_EUICR, TALITOS1_DEUICR_KPE);
256dd3c0987SLEROY Christophe 	} else {
257dd3c0987SLEROY Christophe 		setbits32(priv->reg + TALITOS_IMR, TALITOS2_IMR_INIT);
258dd3c0987SLEROY Christophe 		setbits32(priv->reg + TALITOS_IMR_LO, TALITOS2_IMR_LO_INIT);
259dd3c0987SLEROY Christophe 	}
2609c4a7965SKim Phillips 
261fe5720e2SKim Phillips 	/* disable integrity check error interrupts (use writeback instead) */
262fe5720e2SKim Phillips 	if (priv->features & TALITOS_FTR_HW_AUTH_CHECK)
2635fa7fa14SLEROY Christophe 		setbits32(priv->reg_mdeu + TALITOS_EUICR_LO,
264fe5720e2SKim Phillips 		          TALITOS_MDEUICR_LO_ICE);
265fe5720e2SKim Phillips 
2669c4a7965SKim Phillips 	return 0;
2679c4a7965SKim Phillips }
2689c4a7965SKim Phillips 
2699c4a7965SKim Phillips /**
2709c4a7965SKim Phillips  * talitos_submit - submits a descriptor to the device for processing
2719c4a7965SKim Phillips  * @dev:	the SEC device to be used
2725228f0f7SKim Phillips  * @ch:		the SEC device channel to be used
2739c4a7965SKim Phillips  * @desc:	the descriptor to be processed by the device
2749c4a7965SKim Phillips  * @callback:	whom to call when processing is complete
2759c4a7965SKim Phillips  * @context:	a handle for use by caller (optional)
2769c4a7965SKim Phillips  *
2779c4a7965SKim Phillips  * desc must contain valid dma-mapped (bus physical) address pointers.
2789c4a7965SKim Phillips  * callback must check err and feedback in descriptor header
2799c4a7965SKim Phillips  * for device processing status.
2809c4a7965SKim Phillips  */
281865d5061SHoria Geanta int talitos_submit(struct device *dev, int ch, struct talitos_desc *desc,
2829c4a7965SKim Phillips 		   void (*callback)(struct device *dev,
2839c4a7965SKim Phillips 				    struct talitos_desc *desc,
2849c4a7965SKim Phillips 				    void *context, int error),
2859c4a7965SKim Phillips 		   void *context)
2869c4a7965SKim Phillips {
2879c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
2889c4a7965SKim Phillips 	struct talitos_request *request;
2895228f0f7SKim Phillips 	unsigned long flags;
2909c4a7965SKim Phillips 	int head;
2917d607c6aSLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
2929c4a7965SKim Phillips 
2934b992628SKim Phillips 	spin_lock_irqsave(&priv->chan[ch].head_lock, flags);
2949c4a7965SKim Phillips 
2954b992628SKim Phillips 	if (!atomic_inc_not_zero(&priv->chan[ch].submit_count)) {
296ec6644d6SKim Phillips 		/* h/w fifo is full */
2974b992628SKim Phillips 		spin_unlock_irqrestore(&priv->chan[ch].head_lock, flags);
2989c4a7965SKim Phillips 		return -EAGAIN;
2999c4a7965SKim Phillips 	}
3009c4a7965SKim Phillips 
3014b992628SKim Phillips 	head = priv->chan[ch].head;
3024b992628SKim Phillips 	request = &priv->chan[ch].fifo[head];
303ec6644d6SKim Phillips 
3049c4a7965SKim Phillips 	/* map descriptor and save caller data */
3057d607c6aSLEROY Christophe 	if (is_sec1) {
3067d607c6aSLEROY Christophe 		desc->hdr1 = desc->hdr;
3077d607c6aSLEROY Christophe 		request->dma_desc = dma_map_single(dev, &desc->hdr1,
3087d607c6aSLEROY Christophe 						   TALITOS_DESC_SIZE,
3099c4a7965SKim Phillips 						   DMA_BIDIRECTIONAL);
3107d607c6aSLEROY Christophe 	} else {
3117d607c6aSLEROY Christophe 		request->dma_desc = dma_map_single(dev, desc,
3127d607c6aSLEROY Christophe 						   TALITOS_DESC_SIZE,
3137d607c6aSLEROY Christophe 						   DMA_BIDIRECTIONAL);
3147d607c6aSLEROY Christophe 	}
3159c4a7965SKim Phillips 	request->callback = callback;
3169c4a7965SKim Phillips 	request->context = context;
3179c4a7965SKim Phillips 
3189c4a7965SKim Phillips 	/* increment fifo head */
3194b992628SKim Phillips 	priv->chan[ch].head = (priv->chan[ch].head + 1) & (priv->fifo_len - 1);
3209c4a7965SKim Phillips 
3219c4a7965SKim Phillips 	smp_wmb();
3229c4a7965SKim Phillips 	request->desc = desc;
3239c4a7965SKim Phillips 
3249c4a7965SKim Phillips 	/* GO! */
3259c4a7965SKim Phillips 	wmb();
326ad42d5fcSKim Phillips 	out_be32(priv->chan[ch].reg + TALITOS_FF,
327ad42d5fcSKim Phillips 		 upper_32_bits(request->dma_desc));
328ad42d5fcSKim Phillips 	out_be32(priv->chan[ch].reg + TALITOS_FF_LO,
329a752447aSKim Phillips 		 lower_32_bits(request->dma_desc));
3309c4a7965SKim Phillips 
3314b992628SKim Phillips 	spin_unlock_irqrestore(&priv->chan[ch].head_lock, flags);
3329c4a7965SKim Phillips 
3339c4a7965SKim Phillips 	return -EINPROGRESS;
3349c4a7965SKim Phillips }
335865d5061SHoria Geanta EXPORT_SYMBOL(talitos_submit);
3369c4a7965SKim Phillips 
3379c4a7965SKim Phillips /*
3389c4a7965SKim Phillips  * process what was done, notify callback of error if not
3399c4a7965SKim Phillips  */
3409c4a7965SKim Phillips static void flush_channel(struct device *dev, int ch, int error, int reset_ch)
3419c4a7965SKim Phillips {
3429c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
3439c4a7965SKim Phillips 	struct talitos_request *request, saved_req;
3449c4a7965SKim Phillips 	unsigned long flags;
3459c4a7965SKim Phillips 	int tail, status;
3467d607c6aSLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
3479c4a7965SKim Phillips 
3484b992628SKim Phillips 	spin_lock_irqsave(&priv->chan[ch].tail_lock, flags);
3499c4a7965SKim Phillips 
3504b992628SKim Phillips 	tail = priv->chan[ch].tail;
3514b992628SKim Phillips 	while (priv->chan[ch].fifo[tail].desc) {
3527d607c6aSLEROY Christophe 		__be32 hdr;
3537d607c6aSLEROY Christophe 
3544b992628SKim Phillips 		request = &priv->chan[ch].fifo[tail];
3559c4a7965SKim Phillips 
3569c4a7965SKim Phillips 		/* descriptors with their done bits set don't get the error */
3579c4a7965SKim Phillips 		rmb();
35837b5e889SLEROY Christophe 		if (!is_sec1)
35937b5e889SLEROY Christophe 			hdr = request->desc->hdr;
36037b5e889SLEROY Christophe 		else if (request->desc->next_desc)
36137b5e889SLEROY Christophe 			hdr = (request->desc + 1)->hdr1;
36237b5e889SLEROY Christophe 		else
36337b5e889SLEROY Christophe 			hdr = request->desc->hdr1;
3647d607c6aSLEROY Christophe 
3657d607c6aSLEROY Christophe 		if ((hdr & DESC_HDR_DONE) == DESC_HDR_DONE)
3669c4a7965SKim Phillips 			status = 0;
367ca38a814SLee Nipper 		else
3689c4a7965SKim Phillips 			if (!error)
3699c4a7965SKim Phillips 				break;
3709c4a7965SKim Phillips 			else
3719c4a7965SKim Phillips 				status = error;
3729c4a7965SKim Phillips 
3739c4a7965SKim Phillips 		dma_unmap_single(dev, request->dma_desc,
3747d607c6aSLEROY Christophe 				 TALITOS_DESC_SIZE,
375e938e465SKim Phillips 				 DMA_BIDIRECTIONAL);
3769c4a7965SKim Phillips 
3779c4a7965SKim Phillips 		/* copy entries so we can call callback outside lock */
3789c4a7965SKim Phillips 		saved_req.desc = request->desc;
3799c4a7965SKim Phillips 		saved_req.callback = request->callback;
3809c4a7965SKim Phillips 		saved_req.context = request->context;
3819c4a7965SKim Phillips 
3829c4a7965SKim Phillips 		/* release request entry in fifo */
3839c4a7965SKim Phillips 		smp_wmb();
3849c4a7965SKim Phillips 		request->desc = NULL;
3859c4a7965SKim Phillips 
3869c4a7965SKim Phillips 		/* increment fifo tail */
3874b992628SKim Phillips 		priv->chan[ch].tail = (tail + 1) & (priv->fifo_len - 1);
3889c4a7965SKim Phillips 
3894b992628SKim Phillips 		spin_unlock_irqrestore(&priv->chan[ch].tail_lock, flags);
390ec6644d6SKim Phillips 
3914b992628SKim Phillips 		atomic_dec(&priv->chan[ch].submit_count);
392ec6644d6SKim Phillips 
3939c4a7965SKim Phillips 		saved_req.callback(dev, saved_req.desc, saved_req.context,
3949c4a7965SKim Phillips 				   status);
3959c4a7965SKim Phillips 		/* channel may resume processing in single desc error case */
3969c4a7965SKim Phillips 		if (error && !reset_ch && status == error)
3979c4a7965SKim Phillips 			return;
3984b992628SKim Phillips 		spin_lock_irqsave(&priv->chan[ch].tail_lock, flags);
3994b992628SKim Phillips 		tail = priv->chan[ch].tail;
4009c4a7965SKim Phillips 	}
4019c4a7965SKim Phillips 
4024b992628SKim Phillips 	spin_unlock_irqrestore(&priv->chan[ch].tail_lock, flags);
4039c4a7965SKim Phillips }
4049c4a7965SKim Phillips 
4059c4a7965SKim Phillips /*
4069c4a7965SKim Phillips  * process completed requests for channels that have done status
4079c4a7965SKim Phillips  */
408dd3c0987SLEROY Christophe #define DEF_TALITOS1_DONE(name, ch_done_mask)				\
409dd3c0987SLEROY Christophe static void talitos1_done_##name(unsigned long data)			\
410dd3c0987SLEROY Christophe {									\
411dd3c0987SLEROY Christophe 	struct device *dev = (struct device *)data;			\
412dd3c0987SLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);		\
413dd3c0987SLEROY Christophe 	unsigned long flags;						\
414dd3c0987SLEROY Christophe 									\
415dd3c0987SLEROY Christophe 	if (ch_done_mask & 0x10000000)					\
416dd3c0987SLEROY Christophe 		flush_channel(dev, 0, 0, 0);			\
417dd3c0987SLEROY Christophe 	if (ch_done_mask & 0x40000000)					\
418dd3c0987SLEROY Christophe 		flush_channel(dev, 1, 0, 0);			\
419dd3c0987SLEROY Christophe 	if (ch_done_mask & 0x00010000)					\
420dd3c0987SLEROY Christophe 		flush_channel(dev, 2, 0, 0);			\
421dd3c0987SLEROY Christophe 	if (ch_done_mask & 0x00040000)					\
422dd3c0987SLEROY Christophe 		flush_channel(dev, 3, 0, 0);			\
423dd3c0987SLEROY Christophe 									\
424dd3c0987SLEROY Christophe 	/* At this point, all completed channels have been processed */	\
425dd3c0987SLEROY Christophe 	/* Unmask done interrupts for channels completed later on. */	\
426dd3c0987SLEROY Christophe 	spin_lock_irqsave(&priv->reg_lock, flags);			\
427dd3c0987SLEROY Christophe 	clrbits32(priv->reg + TALITOS_IMR, ch_done_mask);		\
428dd3c0987SLEROY Christophe 	clrbits32(priv->reg + TALITOS_IMR_LO, TALITOS1_IMR_LO_INIT);	\
429dd3c0987SLEROY Christophe 	spin_unlock_irqrestore(&priv->reg_lock, flags);			\
430dd3c0987SLEROY Christophe }
431dd3c0987SLEROY Christophe 
432dd3c0987SLEROY Christophe DEF_TALITOS1_DONE(4ch, TALITOS1_ISR_4CHDONE)
4339c02e285SLEROY Christophe DEF_TALITOS1_DONE(ch0, TALITOS1_ISR_CH_0_DONE)
434dd3c0987SLEROY Christophe 
435dd3c0987SLEROY Christophe #define DEF_TALITOS2_DONE(name, ch_done_mask)				\
436dd3c0987SLEROY Christophe static void talitos2_done_##name(unsigned long data)			\
437c3e337f8SKim Phillips {									\
438c3e337f8SKim Phillips 	struct device *dev = (struct device *)data;			\
439c3e337f8SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);		\
440511d63cbSHoria Geanta 	unsigned long flags;						\
441c3e337f8SKim Phillips 									\
442c3e337f8SKim Phillips 	if (ch_done_mask & 1)						\
443c3e337f8SKim Phillips 		flush_channel(dev, 0, 0, 0);				\
444c3e337f8SKim Phillips 	if (ch_done_mask & (1 << 2))					\
445c3e337f8SKim Phillips 		flush_channel(dev, 1, 0, 0);				\
446c3e337f8SKim Phillips 	if (ch_done_mask & (1 << 4))					\
447c3e337f8SKim Phillips 		flush_channel(dev, 2, 0, 0);				\
448c3e337f8SKim Phillips 	if (ch_done_mask & (1 << 6))					\
449c3e337f8SKim Phillips 		flush_channel(dev, 3, 0, 0);				\
450c3e337f8SKim Phillips 									\
451c3e337f8SKim Phillips 	/* At this point, all completed channels have been processed */	\
452c3e337f8SKim Phillips 	/* Unmask done interrupts for channels completed later on. */	\
453511d63cbSHoria Geanta 	spin_lock_irqsave(&priv->reg_lock, flags);			\
454c3e337f8SKim Phillips 	setbits32(priv->reg + TALITOS_IMR, ch_done_mask);		\
455dd3c0987SLEROY Christophe 	setbits32(priv->reg + TALITOS_IMR_LO, TALITOS2_IMR_LO_INIT);	\
456511d63cbSHoria Geanta 	spin_unlock_irqrestore(&priv->reg_lock, flags);			\
4579c4a7965SKim Phillips }
458dd3c0987SLEROY Christophe 
459dd3c0987SLEROY Christophe DEF_TALITOS2_DONE(4ch, TALITOS2_ISR_4CHDONE)
4609c02e285SLEROY Christophe DEF_TALITOS2_DONE(ch0, TALITOS2_ISR_CH_0_DONE)
461dd3c0987SLEROY Christophe DEF_TALITOS2_DONE(ch0_2, TALITOS2_ISR_CH_0_2_DONE)
462dd3c0987SLEROY Christophe DEF_TALITOS2_DONE(ch1_3, TALITOS2_ISR_CH_1_3_DONE)
4639c4a7965SKim Phillips 
4649c4a7965SKim Phillips /*
4659c4a7965SKim Phillips  * locate current (offending) descriptor
4669c4a7965SKim Phillips  */
4673e721aebSKim Phillips static u32 current_desc_hdr(struct device *dev, int ch)
4689c4a7965SKim Phillips {
4699c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
470b62ffd8cSHoria Geanta 	int tail, iter;
4719c4a7965SKim Phillips 	dma_addr_t cur_desc;
4729c4a7965SKim Phillips 
473b62ffd8cSHoria Geanta 	cur_desc = ((u64)in_be32(priv->chan[ch].reg + TALITOS_CDPR)) << 32;
474b62ffd8cSHoria Geanta 	cur_desc |= in_be32(priv->chan[ch].reg + TALITOS_CDPR_LO);
4759c4a7965SKim Phillips 
476b62ffd8cSHoria Geanta 	if (!cur_desc) {
477b62ffd8cSHoria Geanta 		dev_err(dev, "CDPR is NULL, giving up search for offending descriptor\n");
478b62ffd8cSHoria Geanta 		return 0;
479b62ffd8cSHoria Geanta 	}
480b62ffd8cSHoria Geanta 
481b62ffd8cSHoria Geanta 	tail = priv->chan[ch].tail;
482b62ffd8cSHoria Geanta 
483b62ffd8cSHoria Geanta 	iter = tail;
48437b5e889SLEROY Christophe 	while (priv->chan[ch].fifo[iter].dma_desc != cur_desc &&
48537b5e889SLEROY Christophe 	       priv->chan[ch].fifo[iter].desc->next_desc != cur_desc) {
486b62ffd8cSHoria Geanta 		iter = (iter + 1) & (priv->fifo_len - 1);
487b62ffd8cSHoria Geanta 		if (iter == tail) {
4889c4a7965SKim Phillips 			dev_err(dev, "couldn't locate current descriptor\n");
4893e721aebSKim Phillips 			return 0;
4909c4a7965SKim Phillips 		}
4919c4a7965SKim Phillips 	}
4929c4a7965SKim Phillips 
49337b5e889SLEROY Christophe 	if (priv->chan[ch].fifo[iter].desc->next_desc == cur_desc)
49437b5e889SLEROY Christophe 		return (priv->chan[ch].fifo[iter].desc + 1)->hdr;
49537b5e889SLEROY Christophe 
496b62ffd8cSHoria Geanta 	return priv->chan[ch].fifo[iter].desc->hdr;
4979c4a7965SKim Phillips }
4989c4a7965SKim Phillips 
4999c4a7965SKim Phillips /*
5009c4a7965SKim Phillips  * user diagnostics; report root cause of error based on execution unit status
5019c4a7965SKim Phillips  */
5023e721aebSKim Phillips static void report_eu_error(struct device *dev, int ch, u32 desc_hdr)
5039c4a7965SKim Phillips {
5049c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
5059c4a7965SKim Phillips 	int i;
5069c4a7965SKim Phillips 
5073e721aebSKim Phillips 	if (!desc_hdr)
508ad42d5fcSKim Phillips 		desc_hdr = in_be32(priv->chan[ch].reg + TALITOS_DESCBUF);
5093e721aebSKim Phillips 
5103e721aebSKim Phillips 	switch (desc_hdr & DESC_HDR_SEL0_MASK) {
5119c4a7965SKim Phillips 	case DESC_HDR_SEL0_AFEU:
5129c4a7965SKim Phillips 		dev_err(dev, "AFEUISR 0x%08x_%08x\n",
5135fa7fa14SLEROY Christophe 			in_be32(priv->reg_afeu + TALITOS_EUISR),
5145fa7fa14SLEROY Christophe 			in_be32(priv->reg_afeu + TALITOS_EUISR_LO));
5159c4a7965SKim Phillips 		break;
5169c4a7965SKim Phillips 	case DESC_HDR_SEL0_DEU:
5179c4a7965SKim Phillips 		dev_err(dev, "DEUISR 0x%08x_%08x\n",
5185fa7fa14SLEROY Christophe 			in_be32(priv->reg_deu + TALITOS_EUISR),
5195fa7fa14SLEROY Christophe 			in_be32(priv->reg_deu + TALITOS_EUISR_LO));
5209c4a7965SKim Phillips 		break;
5219c4a7965SKim Phillips 	case DESC_HDR_SEL0_MDEUA:
5229c4a7965SKim Phillips 	case DESC_HDR_SEL0_MDEUB:
5239c4a7965SKim Phillips 		dev_err(dev, "MDEUISR 0x%08x_%08x\n",
5245fa7fa14SLEROY Christophe 			in_be32(priv->reg_mdeu + TALITOS_EUISR),
5255fa7fa14SLEROY Christophe 			in_be32(priv->reg_mdeu + TALITOS_EUISR_LO));
5269c4a7965SKim Phillips 		break;
5279c4a7965SKim Phillips 	case DESC_HDR_SEL0_RNG:
5289c4a7965SKim Phillips 		dev_err(dev, "RNGUISR 0x%08x_%08x\n",
5295fa7fa14SLEROY Christophe 			in_be32(priv->reg_rngu + TALITOS_ISR),
5305fa7fa14SLEROY Christophe 			in_be32(priv->reg_rngu + TALITOS_ISR_LO));
5319c4a7965SKim Phillips 		break;
5329c4a7965SKim Phillips 	case DESC_HDR_SEL0_PKEU:
5339c4a7965SKim Phillips 		dev_err(dev, "PKEUISR 0x%08x_%08x\n",
5345fa7fa14SLEROY Christophe 			in_be32(priv->reg_pkeu + TALITOS_EUISR),
5355fa7fa14SLEROY Christophe 			in_be32(priv->reg_pkeu + TALITOS_EUISR_LO));
5369c4a7965SKim Phillips 		break;
5379c4a7965SKim Phillips 	case DESC_HDR_SEL0_AESU:
5389c4a7965SKim Phillips 		dev_err(dev, "AESUISR 0x%08x_%08x\n",
5395fa7fa14SLEROY Christophe 			in_be32(priv->reg_aesu + TALITOS_EUISR),
5405fa7fa14SLEROY Christophe 			in_be32(priv->reg_aesu + TALITOS_EUISR_LO));
5419c4a7965SKim Phillips 		break;
5429c4a7965SKim Phillips 	case DESC_HDR_SEL0_CRCU:
5439c4a7965SKim Phillips 		dev_err(dev, "CRCUISR 0x%08x_%08x\n",
5445fa7fa14SLEROY Christophe 			in_be32(priv->reg_crcu + TALITOS_EUISR),
5455fa7fa14SLEROY Christophe 			in_be32(priv->reg_crcu + TALITOS_EUISR_LO));
5469c4a7965SKim Phillips 		break;
5479c4a7965SKim Phillips 	case DESC_HDR_SEL0_KEU:
5489c4a7965SKim Phillips 		dev_err(dev, "KEUISR 0x%08x_%08x\n",
5495fa7fa14SLEROY Christophe 			in_be32(priv->reg_pkeu + TALITOS_EUISR),
5505fa7fa14SLEROY Christophe 			in_be32(priv->reg_pkeu + TALITOS_EUISR_LO));
5519c4a7965SKim Phillips 		break;
5529c4a7965SKim Phillips 	}
5539c4a7965SKim Phillips 
5543e721aebSKim Phillips 	switch (desc_hdr & DESC_HDR_SEL1_MASK) {
5559c4a7965SKim Phillips 	case DESC_HDR_SEL1_MDEUA:
5569c4a7965SKim Phillips 	case DESC_HDR_SEL1_MDEUB:
5579c4a7965SKim Phillips 		dev_err(dev, "MDEUISR 0x%08x_%08x\n",
5585fa7fa14SLEROY Christophe 			in_be32(priv->reg_mdeu + TALITOS_EUISR),
5595fa7fa14SLEROY Christophe 			in_be32(priv->reg_mdeu + TALITOS_EUISR_LO));
5609c4a7965SKim Phillips 		break;
5619c4a7965SKim Phillips 	case DESC_HDR_SEL1_CRCU:
5629c4a7965SKim Phillips 		dev_err(dev, "CRCUISR 0x%08x_%08x\n",
5635fa7fa14SLEROY Christophe 			in_be32(priv->reg_crcu + TALITOS_EUISR),
5645fa7fa14SLEROY Christophe 			in_be32(priv->reg_crcu + TALITOS_EUISR_LO));
5659c4a7965SKim Phillips 		break;
5669c4a7965SKim Phillips 	}
5679c4a7965SKim Phillips 
5689c4a7965SKim Phillips 	for (i = 0; i < 8; i++)
5699c4a7965SKim Phillips 		dev_err(dev, "DESCBUF 0x%08x_%08x\n",
570ad42d5fcSKim Phillips 			in_be32(priv->chan[ch].reg + TALITOS_DESCBUF + 8*i),
571ad42d5fcSKim Phillips 			in_be32(priv->chan[ch].reg + TALITOS_DESCBUF_LO + 8*i));
5729c4a7965SKim Phillips }
5739c4a7965SKim Phillips 
5749c4a7965SKim Phillips /*
5759c4a7965SKim Phillips  * recover from error interrupts
5769c4a7965SKim Phillips  */
5775e718a09SKim Phillips static void talitos_error(struct device *dev, u32 isr, u32 isr_lo)
5789c4a7965SKim Phillips {
5799c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
5809c4a7965SKim Phillips 	unsigned int timeout = TALITOS_TIMEOUT;
581dd3c0987SLEROY Christophe 	int ch, error, reset_dev = 0;
58242e8b0d7SHoria Geant? 	u32 v_lo;
583dd3c0987SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
584dd3c0987SLEROY Christophe 	int reset_ch = is_sec1 ? 1 : 0; /* only SEC2 supports continuation */
5859c4a7965SKim Phillips 
5869c4a7965SKim Phillips 	for (ch = 0; ch < priv->num_channels; ch++) {
5879c4a7965SKim Phillips 		/* skip channels without errors */
588dd3c0987SLEROY Christophe 		if (is_sec1) {
589dd3c0987SLEROY Christophe 			/* bits 29, 31, 17, 19 */
590dd3c0987SLEROY Christophe 			if (!(isr & (1 << (29 + (ch & 1) * 2 - (ch & 2) * 6))))
591dd3c0987SLEROY Christophe 				continue;
592dd3c0987SLEROY Christophe 		} else {
5939c4a7965SKim Phillips 			if (!(isr & (1 << (ch * 2 + 1))))
5949c4a7965SKim Phillips 				continue;
595dd3c0987SLEROY Christophe 		}
5969c4a7965SKim Phillips 
5979c4a7965SKim Phillips 		error = -EINVAL;
5989c4a7965SKim Phillips 
599ad42d5fcSKim Phillips 		v_lo = in_be32(priv->chan[ch].reg + TALITOS_CCPSR_LO);
6009c4a7965SKim Phillips 
6019c4a7965SKim Phillips 		if (v_lo & TALITOS_CCPSR_LO_DOF) {
6029c4a7965SKim Phillips 			dev_err(dev, "double fetch fifo overflow error\n");
6039c4a7965SKim Phillips 			error = -EAGAIN;
6049c4a7965SKim Phillips 			reset_ch = 1;
6059c4a7965SKim Phillips 		}
6069c4a7965SKim Phillips 		if (v_lo & TALITOS_CCPSR_LO_SOF) {
6079c4a7965SKim Phillips 			/* h/w dropped descriptor */
6089c4a7965SKim Phillips 			dev_err(dev, "single fetch fifo overflow error\n");
6099c4a7965SKim Phillips 			error = -EAGAIN;
6109c4a7965SKim Phillips 		}
6119c4a7965SKim Phillips 		if (v_lo & TALITOS_CCPSR_LO_MDTE)
6129c4a7965SKim Phillips 			dev_err(dev, "master data transfer error\n");
6139c4a7965SKim Phillips 		if (v_lo & TALITOS_CCPSR_LO_SGDLZ)
6144d9b3a5bSColin Ian King 			dev_err(dev, is_sec1 ? "pointer not complete error\n"
615dd3c0987SLEROY Christophe 					     : "s/g data length zero error\n");
6169c4a7965SKim Phillips 		if (v_lo & TALITOS_CCPSR_LO_FPZ)
617dd3c0987SLEROY Christophe 			dev_err(dev, is_sec1 ? "parity error\n"
618dd3c0987SLEROY Christophe 					     : "fetch pointer zero error\n");
6199c4a7965SKim Phillips 		if (v_lo & TALITOS_CCPSR_LO_IDH)
6209c4a7965SKim Phillips 			dev_err(dev, "illegal descriptor header error\n");
6219c4a7965SKim Phillips 		if (v_lo & TALITOS_CCPSR_LO_IEU)
622dd3c0987SLEROY Christophe 			dev_err(dev, is_sec1 ? "static assignment error\n"
623dd3c0987SLEROY Christophe 					     : "invalid exec unit error\n");
6249c4a7965SKim Phillips 		if (v_lo & TALITOS_CCPSR_LO_EU)
6253e721aebSKim Phillips 			report_eu_error(dev, ch, current_desc_hdr(dev, ch));
626dd3c0987SLEROY Christophe 		if (!is_sec1) {
6279c4a7965SKim Phillips 			if (v_lo & TALITOS_CCPSR_LO_GB)
6289c4a7965SKim Phillips 				dev_err(dev, "gather boundary error\n");
6299c4a7965SKim Phillips 			if (v_lo & TALITOS_CCPSR_LO_GRL)
6309c4a7965SKim Phillips 				dev_err(dev, "gather return/length error\n");
6319c4a7965SKim Phillips 			if (v_lo & TALITOS_CCPSR_LO_SB)
6329c4a7965SKim Phillips 				dev_err(dev, "scatter boundary error\n");
6339c4a7965SKim Phillips 			if (v_lo & TALITOS_CCPSR_LO_SRL)
6349c4a7965SKim Phillips 				dev_err(dev, "scatter return/length error\n");
635dd3c0987SLEROY Christophe 		}
6369c4a7965SKim Phillips 
6379c4a7965SKim Phillips 		flush_channel(dev, ch, error, reset_ch);
6389c4a7965SKim Phillips 
6399c4a7965SKim Phillips 		if (reset_ch) {
6409c4a7965SKim Phillips 			reset_channel(dev, ch);
6419c4a7965SKim Phillips 		} else {
642ad42d5fcSKim Phillips 			setbits32(priv->chan[ch].reg + TALITOS_CCCR,
643dd3c0987SLEROY Christophe 				  TALITOS2_CCCR_CONT);
644ad42d5fcSKim Phillips 			setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO, 0);
645ad42d5fcSKim Phillips 			while ((in_be32(priv->chan[ch].reg + TALITOS_CCCR) &
646dd3c0987SLEROY Christophe 			       TALITOS2_CCCR_CONT) && --timeout)
6479c4a7965SKim Phillips 				cpu_relax();
6489c4a7965SKim Phillips 			if (timeout == 0) {
6499c4a7965SKim Phillips 				dev_err(dev, "failed to restart channel %d\n",
6509c4a7965SKim Phillips 					ch);
6519c4a7965SKim Phillips 				reset_dev = 1;
6529c4a7965SKim Phillips 			}
6539c4a7965SKim Phillips 		}
6549c4a7965SKim Phillips 	}
655dd3c0987SLEROY Christophe 	if (reset_dev || (is_sec1 && isr & ~TALITOS1_ISR_4CHERR) ||
656dd3c0987SLEROY Christophe 	    (!is_sec1 && isr & ~TALITOS2_ISR_4CHERR) || isr_lo) {
657dd3c0987SLEROY Christophe 		if (is_sec1 && (isr_lo & TALITOS1_ISR_TEA_ERR))
658dd3c0987SLEROY Christophe 			dev_err(dev, "TEA error: ISR 0x%08x_%08x\n",
659dd3c0987SLEROY Christophe 				isr, isr_lo);
660dd3c0987SLEROY Christophe 		else
661dd3c0987SLEROY Christophe 			dev_err(dev, "done overflow, internal time out, or "
662dd3c0987SLEROY Christophe 				"rngu error: ISR 0x%08x_%08x\n", isr, isr_lo);
6639c4a7965SKim Phillips 
6649c4a7965SKim Phillips 		/* purge request queues */
6659c4a7965SKim Phillips 		for (ch = 0; ch < priv->num_channels; ch++)
6669c4a7965SKim Phillips 			flush_channel(dev, ch, -EIO, 1);
6679c4a7965SKim Phillips 
6689c4a7965SKim Phillips 		/* reset and reinitialize the device */
6699c4a7965SKim Phillips 		init_device(dev);
6709c4a7965SKim Phillips 	}
6719c4a7965SKim Phillips }
6729c4a7965SKim Phillips 
673dd3c0987SLEROY Christophe #define DEF_TALITOS1_INTERRUPT(name, ch_done_mask, ch_err_mask, tlet)	       \
674dd3c0987SLEROY Christophe static irqreturn_t talitos1_interrupt_##name(int irq, void *data)	       \
675dd3c0987SLEROY Christophe {									       \
676dd3c0987SLEROY Christophe 	struct device *dev = data;					       \
677dd3c0987SLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);		       \
678dd3c0987SLEROY Christophe 	u32 isr, isr_lo;						       \
679dd3c0987SLEROY Christophe 	unsigned long flags;						       \
680dd3c0987SLEROY Christophe 									       \
681dd3c0987SLEROY Christophe 	spin_lock_irqsave(&priv->reg_lock, flags);			       \
682dd3c0987SLEROY Christophe 	isr = in_be32(priv->reg + TALITOS_ISR);				       \
683dd3c0987SLEROY Christophe 	isr_lo = in_be32(priv->reg + TALITOS_ISR_LO);			       \
684dd3c0987SLEROY Christophe 	/* Acknowledge interrupt */					       \
685dd3c0987SLEROY Christophe 	out_be32(priv->reg + TALITOS_ICR, isr & (ch_done_mask | ch_err_mask)); \
686dd3c0987SLEROY Christophe 	out_be32(priv->reg + TALITOS_ICR_LO, isr_lo);			       \
687dd3c0987SLEROY Christophe 									       \
688dd3c0987SLEROY Christophe 	if (unlikely(isr & ch_err_mask || isr_lo & TALITOS1_IMR_LO_INIT)) {    \
689dd3c0987SLEROY Christophe 		spin_unlock_irqrestore(&priv->reg_lock, flags);		       \
690dd3c0987SLEROY Christophe 		talitos_error(dev, isr & ch_err_mask, isr_lo);		       \
691dd3c0987SLEROY Christophe 	}								       \
692dd3c0987SLEROY Christophe 	else {								       \
693dd3c0987SLEROY Christophe 		if (likely(isr & ch_done_mask)) {			       \
694dd3c0987SLEROY Christophe 			/* mask further done interrupts. */		       \
695dd3c0987SLEROY Christophe 			setbits32(priv->reg + TALITOS_IMR, ch_done_mask);      \
696dd3c0987SLEROY Christophe 			/* done_task will unmask done interrupts at exit */    \
697dd3c0987SLEROY Christophe 			tasklet_schedule(&priv->done_task[tlet]);	       \
698dd3c0987SLEROY Christophe 		}							       \
699dd3c0987SLEROY Christophe 		spin_unlock_irqrestore(&priv->reg_lock, flags);		       \
700dd3c0987SLEROY Christophe 	}								       \
701dd3c0987SLEROY Christophe 									       \
702dd3c0987SLEROY Christophe 	return (isr & (ch_done_mask | ch_err_mask) || isr_lo) ? IRQ_HANDLED :  \
703dd3c0987SLEROY Christophe 								IRQ_NONE;      \
704dd3c0987SLEROY Christophe }
705dd3c0987SLEROY Christophe 
706dd3c0987SLEROY Christophe DEF_TALITOS1_INTERRUPT(4ch, TALITOS1_ISR_4CHDONE, TALITOS1_ISR_4CHERR, 0)
707dd3c0987SLEROY Christophe 
708dd3c0987SLEROY Christophe #define DEF_TALITOS2_INTERRUPT(name, ch_done_mask, ch_err_mask, tlet)	       \
709dd3c0987SLEROY Christophe static irqreturn_t talitos2_interrupt_##name(int irq, void *data)	       \
710c3e337f8SKim Phillips {									       \
711c3e337f8SKim Phillips 	struct device *dev = data;					       \
712c3e337f8SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);		       \
713c3e337f8SKim Phillips 	u32 isr, isr_lo;						       \
714511d63cbSHoria Geanta 	unsigned long flags;						       \
715c3e337f8SKim Phillips 									       \
716511d63cbSHoria Geanta 	spin_lock_irqsave(&priv->reg_lock, flags);			       \
717c3e337f8SKim Phillips 	isr = in_be32(priv->reg + TALITOS_ISR);				       \
718c3e337f8SKim Phillips 	isr_lo = in_be32(priv->reg + TALITOS_ISR_LO);			       \
719c3e337f8SKim Phillips 	/* Acknowledge interrupt */					       \
720c3e337f8SKim Phillips 	out_be32(priv->reg + TALITOS_ICR, isr & (ch_done_mask | ch_err_mask)); \
721c3e337f8SKim Phillips 	out_be32(priv->reg + TALITOS_ICR_LO, isr_lo);			       \
722c3e337f8SKim Phillips 									       \
723511d63cbSHoria Geanta 	if (unlikely(isr & ch_err_mask || isr_lo)) {			       \
724511d63cbSHoria Geanta 		spin_unlock_irqrestore(&priv->reg_lock, flags);		       \
725511d63cbSHoria Geanta 		talitos_error(dev, isr & ch_err_mask, isr_lo);		       \
726511d63cbSHoria Geanta 	}								       \
727511d63cbSHoria Geanta 	else {								       \
728c3e337f8SKim Phillips 		if (likely(isr & ch_done_mask)) {			       \
729c3e337f8SKim Phillips 			/* mask further done interrupts. */		       \
730c3e337f8SKim Phillips 			clrbits32(priv->reg + TALITOS_IMR, ch_done_mask);      \
731c3e337f8SKim Phillips 			/* done_task will unmask done interrupts at exit */    \
732c3e337f8SKim Phillips 			tasklet_schedule(&priv->done_task[tlet]);	       \
733c3e337f8SKim Phillips 		}							       \
734511d63cbSHoria Geanta 		spin_unlock_irqrestore(&priv->reg_lock, flags);		       \
735511d63cbSHoria Geanta 	}								       \
736c3e337f8SKim Phillips 									       \
737c3e337f8SKim Phillips 	return (isr & (ch_done_mask | ch_err_mask) || isr_lo) ? IRQ_HANDLED :  \
738c3e337f8SKim Phillips 								IRQ_NONE;      \
7391c2e8811SLee Nipper }
740dd3c0987SLEROY Christophe 
741dd3c0987SLEROY Christophe DEF_TALITOS2_INTERRUPT(4ch, TALITOS2_ISR_4CHDONE, TALITOS2_ISR_4CHERR, 0)
742dd3c0987SLEROY Christophe DEF_TALITOS2_INTERRUPT(ch0_2, TALITOS2_ISR_CH_0_2_DONE, TALITOS2_ISR_CH_0_2_ERR,
743dd3c0987SLEROY Christophe 		       0)
744dd3c0987SLEROY Christophe DEF_TALITOS2_INTERRUPT(ch1_3, TALITOS2_ISR_CH_1_3_DONE, TALITOS2_ISR_CH_1_3_ERR,
745dd3c0987SLEROY Christophe 		       1)
7469c4a7965SKim Phillips 
7479c4a7965SKim Phillips /*
7489c4a7965SKim Phillips  * hwrng
7499c4a7965SKim Phillips  */
7509c4a7965SKim Phillips static int talitos_rng_data_present(struct hwrng *rng, int wait)
7519c4a7965SKim Phillips {
7529c4a7965SKim Phillips 	struct device *dev = (struct device *)rng->priv;
7539c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
7549c4a7965SKim Phillips 	u32 ofl;
7559c4a7965SKim Phillips 	int i;
7569c4a7965SKim Phillips 
7579c4a7965SKim Phillips 	for (i = 0; i < 20; i++) {
7585fa7fa14SLEROY Christophe 		ofl = in_be32(priv->reg_rngu + TALITOS_EUSR_LO) &
7599c4a7965SKim Phillips 		      TALITOS_RNGUSR_LO_OFL;
7609c4a7965SKim Phillips 		if (ofl || !wait)
7619c4a7965SKim Phillips 			break;
7629c4a7965SKim Phillips 		udelay(10);
7639c4a7965SKim Phillips 	}
7649c4a7965SKim Phillips 
7659c4a7965SKim Phillips 	return !!ofl;
7669c4a7965SKim Phillips }
7679c4a7965SKim Phillips 
7689c4a7965SKim Phillips static int talitos_rng_data_read(struct hwrng *rng, u32 *data)
7699c4a7965SKim Phillips {
7709c4a7965SKim Phillips 	struct device *dev = (struct device *)rng->priv;
7719c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
7729c4a7965SKim Phillips 
7739c4a7965SKim Phillips 	/* rng fifo requires 64-bit accesses */
7745fa7fa14SLEROY Christophe 	*data = in_be32(priv->reg_rngu + TALITOS_EU_FIFO);
7755fa7fa14SLEROY Christophe 	*data = in_be32(priv->reg_rngu + TALITOS_EU_FIFO_LO);
7769c4a7965SKim Phillips 
7779c4a7965SKim Phillips 	return sizeof(u32);
7789c4a7965SKim Phillips }
7799c4a7965SKim Phillips 
7809c4a7965SKim Phillips static int talitos_rng_init(struct hwrng *rng)
7819c4a7965SKim Phillips {
7829c4a7965SKim Phillips 	struct device *dev = (struct device *)rng->priv;
7839c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
7849c4a7965SKim Phillips 	unsigned int timeout = TALITOS_TIMEOUT;
7859c4a7965SKim Phillips 
7865fa7fa14SLEROY Christophe 	setbits32(priv->reg_rngu + TALITOS_EURCR_LO, TALITOS_RNGURCR_LO_SR);
7875fa7fa14SLEROY Christophe 	while (!(in_be32(priv->reg_rngu + TALITOS_EUSR_LO)
7885fa7fa14SLEROY Christophe 		 & TALITOS_RNGUSR_LO_RD)
7899c4a7965SKim Phillips 	       && --timeout)
7909c4a7965SKim Phillips 		cpu_relax();
7919c4a7965SKim Phillips 	if (timeout == 0) {
7929c4a7965SKim Phillips 		dev_err(dev, "failed to reset rng hw\n");
7939c4a7965SKim Phillips 		return -ENODEV;
7949c4a7965SKim Phillips 	}
7959c4a7965SKim Phillips 
7969c4a7965SKim Phillips 	/* start generating */
7975fa7fa14SLEROY Christophe 	setbits32(priv->reg_rngu + TALITOS_EUDSR_LO, 0);
7989c4a7965SKim Phillips 
7999c4a7965SKim Phillips 	return 0;
8009c4a7965SKim Phillips }
8019c4a7965SKim Phillips 
8029c4a7965SKim Phillips static int talitos_register_rng(struct device *dev)
8039c4a7965SKim Phillips {
8049c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
80535a3bb3dSAaron Sierra 	int err;
8069c4a7965SKim Phillips 
8079c4a7965SKim Phillips 	priv->rng.name		= dev_driver_string(dev),
8089c4a7965SKim Phillips 	priv->rng.init		= talitos_rng_init,
8099c4a7965SKim Phillips 	priv->rng.data_present	= talitos_rng_data_present,
8109c4a7965SKim Phillips 	priv->rng.data_read	= talitos_rng_data_read,
8119c4a7965SKim Phillips 	priv->rng.priv		= (unsigned long)dev;
8129c4a7965SKim Phillips 
81335a3bb3dSAaron Sierra 	err = hwrng_register(&priv->rng);
81435a3bb3dSAaron Sierra 	if (!err)
81535a3bb3dSAaron Sierra 		priv->rng_registered = true;
81635a3bb3dSAaron Sierra 
81735a3bb3dSAaron Sierra 	return err;
8189c4a7965SKim Phillips }
8199c4a7965SKim Phillips 
8209c4a7965SKim Phillips static void talitos_unregister_rng(struct device *dev)
8219c4a7965SKim Phillips {
8229c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
8239c4a7965SKim Phillips 
82435a3bb3dSAaron Sierra 	if (!priv->rng_registered)
82535a3bb3dSAaron Sierra 		return;
82635a3bb3dSAaron Sierra 
8279c4a7965SKim Phillips 	hwrng_unregister(&priv->rng);
82835a3bb3dSAaron Sierra 	priv->rng_registered = false;
8299c4a7965SKim Phillips }
8309c4a7965SKim Phillips 
8319c4a7965SKim Phillips /*
8329c4a7965SKim Phillips  * crypto alg
8339c4a7965SKim Phillips  */
8349c4a7965SKim Phillips #define TALITOS_CRA_PRIORITY		3000
8357405c8d7SLEROY Christophe /*
8367405c8d7SLEROY Christophe  * Defines a priority for doing AEAD with descriptors type
8377405c8d7SLEROY Christophe  * HMAC_SNOOP_NO_AFEA (HSNA) instead of type IPSEC_ESP
8387405c8d7SLEROY Christophe  */
8397405c8d7SLEROY Christophe #define TALITOS_CRA_PRIORITY_AEAD_HSNA	(TALITOS_CRA_PRIORITY - 1)
84003d2c511SMartin Hicks #define TALITOS_MAX_KEY_SIZE		(AES_MAX_KEY_SIZE + SHA512_BLOCK_SIZE)
8413952f17eSLee Nipper #define TALITOS_MAX_IV_LENGTH		16 /* max of AES_BLOCK_SIZE, DES3_EDE_BLOCK_SIZE */
84270bcaca7SLee Nipper 
8439c4a7965SKim Phillips struct talitos_ctx {
8449c4a7965SKim Phillips 	struct device *dev;
8455228f0f7SKim Phillips 	int ch;
8469c4a7965SKim Phillips 	__be32 desc_hdr_template;
8479c4a7965SKim Phillips 	u8 key[TALITOS_MAX_KEY_SIZE];
84870bcaca7SLee Nipper 	u8 iv[TALITOS_MAX_IV_LENGTH];
8492e13ce08SLEROY Christophe 	dma_addr_t dma_key;
8509c4a7965SKim Phillips 	unsigned int keylen;
8519c4a7965SKim Phillips 	unsigned int enckeylen;
8529c4a7965SKim Phillips 	unsigned int authkeylen;
8539c4a7965SKim Phillips };
8549c4a7965SKim Phillips 
855497f2e6bSLee Nipper #define HASH_MAX_BLOCK_SIZE		SHA512_BLOCK_SIZE
856497f2e6bSLee Nipper #define TALITOS_MDEU_MAX_CONTEXT_SIZE	TALITOS_MDEU_CONTEXT_SIZE_SHA384_SHA512
857497f2e6bSLee Nipper 
858497f2e6bSLee Nipper struct talitos_ahash_req_ctx {
85960f208d7SKim Phillips 	u32 hw_context[TALITOS_MDEU_MAX_CONTEXT_SIZE / sizeof(u32)];
860497f2e6bSLee Nipper 	unsigned int hw_context_size;
8613c0dd190SLEROY Christophe 	u8 buf[2][HASH_MAX_BLOCK_SIZE];
8623c0dd190SLEROY Christophe 	int buf_idx;
86360f208d7SKim Phillips 	unsigned int swinit;
864497f2e6bSLee Nipper 	unsigned int first;
865497f2e6bSLee Nipper 	unsigned int last;
866497f2e6bSLee Nipper 	unsigned int to_hash_later;
86742e8b0d7SHoria Geant? 	unsigned int nbuf;
868497f2e6bSLee Nipper 	struct scatterlist bufsl[2];
869497f2e6bSLee Nipper 	struct scatterlist *psrc;
870497f2e6bSLee Nipper };
871497f2e6bSLee Nipper 
8723639ca84SHoria Geant? struct talitos_export_state {
8733639ca84SHoria Geant? 	u32 hw_context[TALITOS_MDEU_MAX_CONTEXT_SIZE / sizeof(u32)];
8743639ca84SHoria Geant? 	u8 buf[HASH_MAX_BLOCK_SIZE];
8753639ca84SHoria Geant? 	unsigned int swinit;
8763639ca84SHoria Geant? 	unsigned int first;
8773639ca84SHoria Geant? 	unsigned int last;
8783639ca84SHoria Geant? 	unsigned int to_hash_later;
8793639ca84SHoria Geant? 	unsigned int nbuf;
8803639ca84SHoria Geant? };
8813639ca84SHoria Geant? 
88256af8cd4SLee Nipper static int aead_setkey(struct crypto_aead *authenc,
8839c4a7965SKim Phillips 		       const u8 *key, unsigned int keylen)
8849c4a7965SKim Phillips {
8859c4a7965SKim Phillips 	struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
8862e13ce08SLEROY Christophe 	struct device *dev = ctx->dev;
887c306a98dSMathias Krause 	struct crypto_authenc_keys keys;
8889c4a7965SKim Phillips 
889c306a98dSMathias Krause 	if (crypto_authenc_extractkeys(&keys, key, keylen) != 0)
8909c4a7965SKim Phillips 		goto badkey;
8919c4a7965SKim Phillips 
892c306a98dSMathias Krause 	if (keys.authkeylen + keys.enckeylen > TALITOS_MAX_KEY_SIZE)
8939c4a7965SKim Phillips 		goto badkey;
8949c4a7965SKim Phillips 
8952e13ce08SLEROY Christophe 	if (ctx->keylen)
8962e13ce08SLEROY Christophe 		dma_unmap_single(dev, ctx->dma_key, ctx->keylen, DMA_TO_DEVICE);
8972e13ce08SLEROY Christophe 
898c306a98dSMathias Krause 	memcpy(ctx->key, keys.authkey, keys.authkeylen);
899c306a98dSMathias Krause 	memcpy(&ctx->key[keys.authkeylen], keys.enckey, keys.enckeylen);
9009c4a7965SKim Phillips 
901c306a98dSMathias Krause 	ctx->keylen = keys.authkeylen + keys.enckeylen;
902c306a98dSMathias Krause 	ctx->enckeylen = keys.enckeylen;
903c306a98dSMathias Krause 	ctx->authkeylen = keys.authkeylen;
9042e13ce08SLEROY Christophe 	ctx->dma_key = dma_map_single(dev, ctx->key, ctx->keylen,
9052e13ce08SLEROY Christophe 				      DMA_TO_DEVICE);
9069c4a7965SKim Phillips 
9078f0691fcSTudor-Dan Ambarus 	memzero_explicit(&keys, sizeof(keys));
9089c4a7965SKim Phillips 	return 0;
9099c4a7965SKim Phillips 
9109c4a7965SKim Phillips badkey:
9119c4a7965SKim Phillips 	crypto_aead_set_flags(authenc, CRYPTO_TFM_RES_BAD_KEY_LEN);
9128f0691fcSTudor-Dan Ambarus 	memzero_explicit(&keys, sizeof(keys));
9139c4a7965SKim Phillips 	return -EINVAL;
9149c4a7965SKim Phillips }
9159c4a7965SKim Phillips 
916ef7c5c85SHerbert Xu static int aead_des3_setkey(struct crypto_aead *authenc,
917ef7c5c85SHerbert Xu 			    const u8 *key, unsigned int keylen)
918ef7c5c85SHerbert Xu {
919ef7c5c85SHerbert Xu 	struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
920ef7c5c85SHerbert Xu 	struct device *dev = ctx->dev;
921ef7c5c85SHerbert Xu 	struct crypto_authenc_keys keys;
922ef7c5c85SHerbert Xu 	u32 flags;
923ef7c5c85SHerbert Xu 	int err;
924ef7c5c85SHerbert Xu 
925ef7c5c85SHerbert Xu 	err = crypto_authenc_extractkeys(&keys, key, keylen);
926ef7c5c85SHerbert Xu 	if (unlikely(err))
927ef7c5c85SHerbert Xu 		goto badkey;
928ef7c5c85SHerbert Xu 
929ef7c5c85SHerbert Xu 	err = -EINVAL;
930ef7c5c85SHerbert Xu 	if (keys.authkeylen + keys.enckeylen > TALITOS_MAX_KEY_SIZE)
931ef7c5c85SHerbert Xu 		goto badkey;
932ef7c5c85SHerbert Xu 
933ef7c5c85SHerbert Xu 	if (keys.enckeylen != DES3_EDE_KEY_SIZE)
934ef7c5c85SHerbert Xu 		goto badkey;
935ef7c5c85SHerbert Xu 
936ef7c5c85SHerbert Xu 	flags = crypto_aead_get_flags(authenc);
937ef7c5c85SHerbert Xu 	err = __des3_verify_key(&flags, keys.enckey);
938ef7c5c85SHerbert Xu 	if (unlikely(err)) {
939ef7c5c85SHerbert Xu 		crypto_aead_set_flags(authenc, flags);
940ef7c5c85SHerbert Xu 		goto out;
941ef7c5c85SHerbert Xu 	}
942ef7c5c85SHerbert Xu 
943ef7c5c85SHerbert Xu 	if (ctx->keylen)
944ef7c5c85SHerbert Xu 		dma_unmap_single(dev, ctx->dma_key, ctx->keylen, DMA_TO_DEVICE);
945ef7c5c85SHerbert Xu 
946ef7c5c85SHerbert Xu 	memcpy(ctx->key, keys.authkey, keys.authkeylen);
947ef7c5c85SHerbert Xu 	memcpy(&ctx->key[keys.authkeylen], keys.enckey, keys.enckeylen);
948ef7c5c85SHerbert Xu 
949ef7c5c85SHerbert Xu 	ctx->keylen = keys.authkeylen + keys.enckeylen;
950ef7c5c85SHerbert Xu 	ctx->enckeylen = keys.enckeylen;
951ef7c5c85SHerbert Xu 	ctx->authkeylen = keys.authkeylen;
952ef7c5c85SHerbert Xu 	ctx->dma_key = dma_map_single(dev, ctx->key, ctx->keylen,
953ef7c5c85SHerbert Xu 				      DMA_TO_DEVICE);
954ef7c5c85SHerbert Xu 
955ef7c5c85SHerbert Xu out:
956ef7c5c85SHerbert Xu 	memzero_explicit(&keys, sizeof(keys));
957ef7c5c85SHerbert Xu 	return err;
958ef7c5c85SHerbert Xu 
959ef7c5c85SHerbert Xu badkey:
960ef7c5c85SHerbert Xu 	crypto_aead_set_flags(authenc, CRYPTO_TFM_RES_BAD_KEY_LEN);
961ef7c5c85SHerbert Xu 	goto out;
962ef7c5c85SHerbert Xu }
963ef7c5c85SHerbert Xu 
9649c4a7965SKim Phillips /*
96556af8cd4SLee Nipper  * talitos_edesc - s/w-extended descriptor
9669c4a7965SKim Phillips  * @src_nents: number of segments in input scatterlist
9679c4a7965SKim Phillips  * @dst_nents: number of segments in output scatterlist
968aeb4c132SHerbert Xu  * @icv_ool: whether ICV is out-of-line
96979fd31d3SHoria Geanta  * @iv_dma: dma address of iv for checking continuity and link table
9709c4a7965SKim Phillips  * @dma_len: length of dma mapped link_tbl space
9716f65f6acSLEROY Christophe  * @dma_link_tbl: bus physical address of link_tbl/buf
9729c4a7965SKim Phillips  * @desc: h/w descriptor
9736f65f6acSLEROY Christophe  * @link_tbl: input and output h/w link tables (if {src,dst}_nents > 1) (SEC2)
9746f65f6acSLEROY Christophe  * @buf: input and output buffeur (if {src,dst}_nents > 1) (SEC1)
9759c4a7965SKim Phillips  *
9769c4a7965SKim Phillips  * if decrypting (with authcheck), or either one of src_nents or dst_nents
9779c4a7965SKim Phillips  * is greater than 1, an integrity check value is concatenated to the end
9789c4a7965SKim Phillips  * of link_tbl data
9799c4a7965SKim Phillips  */
98056af8cd4SLee Nipper struct talitos_edesc {
9819c4a7965SKim Phillips 	int src_nents;
9829c4a7965SKim Phillips 	int dst_nents;
983aeb4c132SHerbert Xu 	bool icv_ool;
98479fd31d3SHoria Geanta 	dma_addr_t iv_dma;
9859c4a7965SKim Phillips 	int dma_len;
9869c4a7965SKim Phillips 	dma_addr_t dma_link_tbl;
9879c4a7965SKim Phillips 	struct talitos_desc desc;
9886f65f6acSLEROY Christophe 	union {
9899c4a7965SKim Phillips 		struct talitos_ptr link_tbl[0];
9906f65f6acSLEROY Christophe 		u8 buf[0];
9916f65f6acSLEROY Christophe 	};
9929c4a7965SKim Phillips };
9939c4a7965SKim Phillips 
9944de9d0b5SLee Nipper static void talitos_sg_unmap(struct device *dev,
9954de9d0b5SLee Nipper 			     struct talitos_edesc *edesc,
9964de9d0b5SLee Nipper 			     struct scatterlist *src,
9976a1e8d14SLEROY Christophe 			     struct scatterlist *dst,
9986a1e8d14SLEROY Christophe 			     unsigned int len, unsigned int offset)
999246a87cdSLEROY Christophe {
1000246a87cdSLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
1001246a87cdSLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
10026a1e8d14SLEROY Christophe 	unsigned int src_nents = edesc->src_nents ? : 1;
10036a1e8d14SLEROY Christophe 	unsigned int dst_nents = edesc->dst_nents ? : 1;
1004246a87cdSLEROY Christophe 
10056a1e8d14SLEROY Christophe 	if (is_sec1 && dst && dst_nents > 1) {
10066a1e8d14SLEROY Christophe 		dma_sync_single_for_device(dev, edesc->dma_link_tbl + offset,
1007246a87cdSLEROY Christophe 					   len, DMA_FROM_DEVICE);
10086a1e8d14SLEROY Christophe 		sg_pcopy_from_buffer(dst, dst_nents, edesc->buf + offset, len,
10096a1e8d14SLEROY Christophe 				     offset);
1010246a87cdSLEROY Christophe 	}
10116a1e8d14SLEROY Christophe 	if (src != dst) {
10126a1e8d14SLEROY Christophe 		if (src_nents == 1 || !is_sec1)
10136a1e8d14SLEROY Christophe 			dma_unmap_sg(dev, src, src_nents, DMA_TO_DEVICE);
10146a1e8d14SLEROY Christophe 
10156a1e8d14SLEROY Christophe 		if (dst && (dst_nents == 1 || !is_sec1))
10166a1e8d14SLEROY Christophe 			dma_unmap_sg(dev, dst, dst_nents, DMA_FROM_DEVICE);
10176a1e8d14SLEROY Christophe 	} else if (src_nents == 1 || !is_sec1) {
10186a1e8d14SLEROY Christophe 		dma_unmap_sg(dev, src, src_nents, DMA_BIDIRECTIONAL);
1019246a87cdSLEROY Christophe 	}
1020246a87cdSLEROY Christophe }
1021246a87cdSLEROY Christophe 
10229c4a7965SKim Phillips static void ipsec_esp_unmap(struct device *dev,
102356af8cd4SLee Nipper 			    struct talitos_edesc *edesc,
10249c4a7965SKim Phillips 			    struct aead_request *areq)
10259c4a7965SKim Phillips {
1026549bd8bcSLEROY Christophe 	struct crypto_aead *aead = crypto_aead_reqtfm(areq);
1027549bd8bcSLEROY Christophe 	struct talitos_ctx *ctx = crypto_aead_ctx(aead);
1028549bd8bcSLEROY Christophe 	unsigned int ivsize = crypto_aead_ivsize(aead);
10299a655608SLEROY Christophe 	bool is_ipsec_esp = edesc->desc.hdr & DESC_HDR_TYPE_IPSEC_ESP;
10309a655608SLEROY Christophe 	struct talitos_ptr *civ_ptr = &edesc->desc.ptr[is_ipsec_esp ? 2 : 3];
1031549bd8bcSLEROY Christophe 
10329a655608SLEROY Christophe 	if (is_ipsec_esp)
1033549bd8bcSLEROY Christophe 		unmap_single_talitos_ptr(dev, &edesc->desc.ptr[6],
1034549bd8bcSLEROY Christophe 					 DMA_FROM_DEVICE);
10359a655608SLEROY Christophe 	unmap_single_talitos_ptr(dev, civ_ptr, DMA_TO_DEVICE);
10369c4a7965SKim Phillips 
10376a1e8d14SLEROY Christophe 	talitos_sg_unmap(dev, edesc, areq->src, areq->dst, areq->cryptlen,
10386a1e8d14SLEROY Christophe 			 areq->assoclen);
10399c4a7965SKim Phillips 
10409c4a7965SKim Phillips 	if (edesc->dma_len)
10419c4a7965SKim Phillips 		dma_unmap_single(dev, edesc->dma_link_tbl, edesc->dma_len,
10429c4a7965SKim Phillips 				 DMA_BIDIRECTIONAL);
1043549bd8bcSLEROY Christophe 
10449a655608SLEROY Christophe 	if (!is_ipsec_esp) {
1045549bd8bcSLEROY Christophe 		unsigned int dst_nents = edesc->dst_nents ? : 1;
1046549bd8bcSLEROY Christophe 
1047549bd8bcSLEROY Christophe 		sg_pcopy_to_buffer(areq->dst, dst_nents, ctx->iv, ivsize,
1048549bd8bcSLEROY Christophe 				   areq->assoclen + areq->cryptlen - ivsize);
1049549bd8bcSLEROY Christophe 	}
10509c4a7965SKim Phillips }
10519c4a7965SKim Phillips 
10529c4a7965SKim Phillips /*
10539c4a7965SKim Phillips  * ipsec_esp descriptor callbacks
10549c4a7965SKim Phillips  */
10559c4a7965SKim Phillips static void ipsec_esp_encrypt_done(struct device *dev,
10569c4a7965SKim Phillips 				   struct talitos_desc *desc, void *context,
10579c4a7965SKim Phillips 				   int err)
10589c4a7965SKim Phillips {
1059549bd8bcSLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
1060549bd8bcSLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
10619c4a7965SKim Phillips 	struct aead_request *areq = context;
10629c4a7965SKim Phillips 	struct crypto_aead *authenc = crypto_aead_reqtfm(areq);
1063aeb4c132SHerbert Xu 	unsigned int authsize = crypto_aead_authsize(authenc);
10642e13ce08SLEROY Christophe 	unsigned int ivsize = crypto_aead_ivsize(authenc);
106519bbbc63SKim Phillips 	struct talitos_edesc *edesc;
10669c4a7965SKim Phillips 	struct scatterlist *sg;
10679c4a7965SKim Phillips 	void *icvdata;
10689c4a7965SKim Phillips 
106919bbbc63SKim Phillips 	edesc = container_of(desc, struct talitos_edesc, desc);
107019bbbc63SKim Phillips 
10719c4a7965SKim Phillips 	ipsec_esp_unmap(dev, edesc, areq);
10729c4a7965SKim Phillips 
10739c4a7965SKim Phillips 	/* copy the generated ICV to dst */
1074aeb4c132SHerbert Xu 	if (edesc->icv_ool) {
1075549bd8bcSLEROY Christophe 		if (is_sec1)
1076549bd8bcSLEROY Christophe 			icvdata = edesc->buf + areq->assoclen + areq->cryptlen;
1077549bd8bcSLEROY Christophe 		else
10789c4a7965SKim Phillips 			icvdata = &edesc->link_tbl[edesc->src_nents +
1079aeb4c132SHerbert Xu 						   edesc->dst_nents + 2];
10809c4a7965SKim Phillips 		sg = sg_last(areq->dst, edesc->dst_nents);
1081aeb4c132SHerbert Xu 		memcpy((char *)sg_virt(sg) + sg->length - authsize,
1082aeb4c132SHerbert Xu 		       icvdata, authsize);
10839c4a7965SKim Phillips 	}
10849c4a7965SKim Phillips 
10852e13ce08SLEROY Christophe 	dma_unmap_single(dev, edesc->iv_dma, ivsize, DMA_TO_DEVICE);
10862e13ce08SLEROY Christophe 
10879c4a7965SKim Phillips 	kfree(edesc);
10889c4a7965SKim Phillips 
10899c4a7965SKim Phillips 	aead_request_complete(areq, err);
10909c4a7965SKim Phillips }
10919c4a7965SKim Phillips 
1092fe5720e2SKim Phillips static void ipsec_esp_decrypt_swauth_done(struct device *dev,
1093e938e465SKim Phillips 					  struct talitos_desc *desc,
1094e938e465SKim Phillips 					  void *context, int err)
10959c4a7965SKim Phillips {
10969c4a7965SKim Phillips 	struct aead_request *req = context;
10979c4a7965SKim Phillips 	struct crypto_aead *authenc = crypto_aead_reqtfm(req);
1098aeb4c132SHerbert Xu 	unsigned int authsize = crypto_aead_authsize(authenc);
109919bbbc63SKim Phillips 	struct talitos_edesc *edesc;
11009c4a7965SKim Phillips 	struct scatterlist *sg;
1101aeb4c132SHerbert Xu 	char *oicv, *icv;
1102549bd8bcSLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
1103549bd8bcSLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
11049c4a7965SKim Phillips 
110519bbbc63SKim Phillips 	edesc = container_of(desc, struct talitos_edesc, desc);
110619bbbc63SKim Phillips 
11079c4a7965SKim Phillips 	ipsec_esp_unmap(dev, edesc, req);
11089c4a7965SKim Phillips 
11099c4a7965SKim Phillips 	if (!err) {
11109c4a7965SKim Phillips 		/* auth check */
11119c4a7965SKim Phillips 		sg = sg_last(req->dst, edesc->dst_nents ? : 1);
1112aeb4c132SHerbert Xu 		icv = (char *)sg_virt(sg) + sg->length - authsize;
1113aeb4c132SHerbert Xu 
1114aeb4c132SHerbert Xu 		if (edesc->dma_len) {
1115549bd8bcSLEROY Christophe 			if (is_sec1)
1116549bd8bcSLEROY Christophe 				oicv = (char *)&edesc->dma_link_tbl +
1117549bd8bcSLEROY Christophe 					       req->assoclen + req->cryptlen;
1118549bd8bcSLEROY Christophe 			else
1119549bd8bcSLEROY Christophe 				oicv = (char *)
1120549bd8bcSLEROY Christophe 				       &edesc->link_tbl[edesc->src_nents +
1121aeb4c132SHerbert Xu 							edesc->dst_nents + 2];
1122aeb4c132SHerbert Xu 			if (edesc->icv_ool)
1123aeb4c132SHerbert Xu 				icv = oicv + authsize;
1124aeb4c132SHerbert Xu 		} else
1125aeb4c132SHerbert Xu 			oicv = (char *)&edesc->link_tbl[0];
1126aeb4c132SHerbert Xu 
112779960943SDavid Gstir 		err = crypto_memneq(oicv, icv, authsize) ? -EBADMSG : 0;
11289c4a7965SKim Phillips 	}
11299c4a7965SKim Phillips 
11309c4a7965SKim Phillips 	kfree(edesc);
11319c4a7965SKim Phillips 
11329c4a7965SKim Phillips 	aead_request_complete(req, err);
11339c4a7965SKim Phillips }
11349c4a7965SKim Phillips 
1135fe5720e2SKim Phillips static void ipsec_esp_decrypt_hwauth_done(struct device *dev,
1136e938e465SKim Phillips 					  struct talitos_desc *desc,
1137e938e465SKim Phillips 					  void *context, int err)
1138fe5720e2SKim Phillips {
1139fe5720e2SKim Phillips 	struct aead_request *req = context;
114019bbbc63SKim Phillips 	struct talitos_edesc *edesc;
114119bbbc63SKim Phillips 
114219bbbc63SKim Phillips 	edesc = container_of(desc, struct talitos_edesc, desc);
1143fe5720e2SKim Phillips 
1144fe5720e2SKim Phillips 	ipsec_esp_unmap(dev, edesc, req);
1145fe5720e2SKim Phillips 
1146fe5720e2SKim Phillips 	/* check ICV auth status */
1147e938e465SKim Phillips 	if (!err && ((desc->hdr_lo & DESC_HDR_LO_ICCR1_MASK) !=
1148e938e465SKim Phillips 		     DESC_HDR_LO_ICCR1_PASS))
1149fe5720e2SKim Phillips 		err = -EBADMSG;
1150fe5720e2SKim Phillips 
1151fe5720e2SKim Phillips 	kfree(edesc);
1152fe5720e2SKim Phillips 
1153fe5720e2SKim Phillips 	aead_request_complete(req, err);
1154fe5720e2SKim Phillips }
1155fe5720e2SKim Phillips 
11569c4a7965SKim Phillips /*
11579c4a7965SKim Phillips  * convert scatterlist to SEC h/w link table format
11589c4a7965SKim Phillips  * stop at cryptlen bytes
11599c4a7965SKim Phillips  */
1160aeb4c132SHerbert Xu static int sg_to_link_tbl_offset(struct scatterlist *sg, int sg_count,
1161aeb4c132SHerbert Xu 				 unsigned int offset, int cryptlen,
1162aeb4c132SHerbert Xu 				 struct talitos_ptr *link_tbl_ptr)
11639c4a7965SKim Phillips {
116470bcaca7SLee Nipper 	int n_sg = sg_count;
1165aeb4c132SHerbert Xu 	int count = 0;
116670bcaca7SLee Nipper 
1167aeb4c132SHerbert Xu 	while (cryptlen && sg && n_sg--) {
1168aeb4c132SHerbert Xu 		unsigned int len = sg_dma_len(sg);
1169aeb4c132SHerbert Xu 
1170aeb4c132SHerbert Xu 		if (offset >= len) {
1171aeb4c132SHerbert Xu 			offset -= len;
1172aeb4c132SHerbert Xu 			goto next;
1173aeb4c132SHerbert Xu 		}
1174aeb4c132SHerbert Xu 
1175aeb4c132SHerbert Xu 		len -= offset;
1176aeb4c132SHerbert Xu 
1177aeb4c132SHerbert Xu 		if (len > cryptlen)
1178aeb4c132SHerbert Xu 			len = cryptlen;
1179aeb4c132SHerbert Xu 
1180aeb4c132SHerbert Xu 		to_talitos_ptr(link_tbl_ptr + count,
1181da9de146SLEROY Christophe 			       sg_dma_address(sg) + offset, len, 0);
1182b096b544SLEROY Christophe 		to_talitos_ptr_ext_set(link_tbl_ptr + count, 0, 0);
1183aeb4c132SHerbert Xu 		count++;
1184aeb4c132SHerbert Xu 		cryptlen -= len;
1185aeb4c132SHerbert Xu 		offset = 0;
1186aeb4c132SHerbert Xu 
1187aeb4c132SHerbert Xu next:
11885be4d4c9SCristian Stoica 		sg = sg_next(sg);
11899c4a7965SKim Phillips 	}
11909c4a7965SKim Phillips 
11919c4a7965SKim Phillips 	/* tag end of link table */
1192aeb4c132SHerbert Xu 	if (count > 0)
1193b096b544SLEROY Christophe 		to_talitos_ptr_ext_set(link_tbl_ptr + count - 1,
1194b096b544SLEROY Christophe 				       DESC_PTR_LNKTBL_RETURN, 0);
119570bcaca7SLee Nipper 
1196aeb4c132SHerbert Xu 	return count;
1197aeb4c132SHerbert Xu }
1198aeb4c132SHerbert Xu 
11992b122730SLEROY Christophe static int talitos_sg_map_ext(struct device *dev, struct scatterlist *src,
1200246a87cdSLEROY Christophe 			      unsigned int len, struct talitos_edesc *edesc,
12012b122730SLEROY Christophe 			      struct talitos_ptr *ptr, int sg_count,
12022b122730SLEROY Christophe 			      unsigned int offset, int tbl_off, int elen)
1203246a87cdSLEROY Christophe {
1204246a87cdSLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
1205246a87cdSLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
1206246a87cdSLEROY Christophe 
120787a81dceSLEROY Christophe 	if (!src) {
120887a81dceSLEROY Christophe 		to_talitos_ptr(ptr, 0, 0, is_sec1);
120987a81dceSLEROY Christophe 		return 1;
121087a81dceSLEROY Christophe 	}
12112b122730SLEROY Christophe 	to_talitos_ptr_ext_set(ptr, elen, is_sec1);
1212246a87cdSLEROY Christophe 	if (sg_count == 1) {
1213da9de146SLEROY Christophe 		to_talitos_ptr(ptr, sg_dma_address(src) + offset, len, is_sec1);
1214246a87cdSLEROY Christophe 		return sg_count;
1215246a87cdSLEROY Christophe 	}
1216246a87cdSLEROY Christophe 	if (is_sec1) {
1217da9de146SLEROY Christophe 		to_talitos_ptr(ptr, edesc->dma_link_tbl + offset, len, is_sec1);
12186a1e8d14SLEROY Christophe 		return sg_count;
1219246a87cdSLEROY Christophe 	}
12202b122730SLEROY Christophe 	sg_count = sg_to_link_tbl_offset(src, sg_count, offset, len + elen,
12216a1e8d14SLEROY Christophe 					 &edesc->link_tbl[tbl_off]);
1222246a87cdSLEROY Christophe 	if (sg_count == 1) {
12236a1e8d14SLEROY Christophe 		/* Only one segment now, so no link tbl needed*/
12246a1e8d14SLEROY Christophe 		copy_talitos_ptr(ptr, &edesc->link_tbl[tbl_off], is_sec1);
12256a1e8d14SLEROY Christophe 		return sg_count;
12266a1e8d14SLEROY Christophe 	}
1227246a87cdSLEROY Christophe 	to_talitos_ptr(ptr, edesc->dma_link_tbl +
1228da9de146SLEROY Christophe 			    tbl_off * sizeof(struct talitos_ptr), len, is_sec1);
12296a1e8d14SLEROY Christophe 	to_talitos_ptr_ext_or(ptr, DESC_PTR_LNKTBL_JUMP, is_sec1);
12306a1e8d14SLEROY Christophe 
12316a1e8d14SLEROY Christophe 	return sg_count;
1232246a87cdSLEROY Christophe }
1233246a87cdSLEROY Christophe 
12342b122730SLEROY Christophe static int talitos_sg_map(struct device *dev, struct scatterlist *src,
12352b122730SLEROY Christophe 			  unsigned int len, struct talitos_edesc *edesc,
12362b122730SLEROY Christophe 			  struct talitos_ptr *ptr, int sg_count,
12372b122730SLEROY Christophe 			  unsigned int offset, int tbl_off)
12382b122730SLEROY Christophe {
12392b122730SLEROY Christophe 	return talitos_sg_map_ext(dev, src, len, edesc, ptr, sg_count, offset,
12402b122730SLEROY Christophe 				  tbl_off, 0);
12412b122730SLEROY Christophe }
12422b122730SLEROY Christophe 
12439c4a7965SKim Phillips /*
12449c4a7965SKim Phillips  * fill in and submit ipsec_esp descriptor
12459c4a7965SKim Phillips  */
124656af8cd4SLee Nipper static int ipsec_esp(struct talitos_edesc *edesc, struct aead_request *areq,
1247aeb4c132SHerbert Xu 		     void (*callback)(struct device *dev,
12489c4a7965SKim Phillips 				      struct talitos_desc *desc,
12499c4a7965SKim Phillips 				      void *context, int error))
12509c4a7965SKim Phillips {
12519c4a7965SKim Phillips 	struct crypto_aead *aead = crypto_aead_reqtfm(areq);
1252aeb4c132SHerbert Xu 	unsigned int authsize = crypto_aead_authsize(aead);
12539c4a7965SKim Phillips 	struct talitos_ctx *ctx = crypto_aead_ctx(aead);
12549c4a7965SKim Phillips 	struct device *dev = ctx->dev;
12559c4a7965SKim Phillips 	struct talitos_desc *desc = &edesc->desc;
12569c4a7965SKim Phillips 	unsigned int cryptlen = areq->cryptlen;
1257e41256f1SKim Phillips 	unsigned int ivsize = crypto_aead_ivsize(aead);
1258aeb4c132SHerbert Xu 	int tbl_off = 0;
1259fa86a267SKim Phillips 	int sg_count, ret;
12602b122730SLEROY Christophe 	int elen = 0;
1261549bd8bcSLEROY Christophe 	bool sync_needed = false;
1262549bd8bcSLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
1263549bd8bcSLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
12649a655608SLEROY Christophe 	bool is_ipsec_esp = desc->hdr & DESC_HDR_TYPE_IPSEC_ESP;
12659a655608SLEROY Christophe 	struct talitos_ptr *civ_ptr = &desc->ptr[is_ipsec_esp ? 2 : 3];
12669a655608SLEROY Christophe 	struct talitos_ptr *ckey_ptr = &desc->ptr[is_ipsec_esp ? 3 : 2];
12679c4a7965SKim Phillips 
12689c4a7965SKim Phillips 	/* hmac key */
12692e13ce08SLEROY Christophe 	to_talitos_ptr(&desc->ptr[0], ctx->dma_key, ctx->authkeylen, is_sec1);
127079fd31d3SHoria Geanta 
1271549bd8bcSLEROY Christophe 	sg_count = edesc->src_nents ?: 1;
1272549bd8bcSLEROY Christophe 	if (is_sec1 && sg_count > 1)
1273549bd8bcSLEROY Christophe 		sg_copy_to_buffer(areq->src, sg_count, edesc->buf,
1274549bd8bcSLEROY Christophe 				  areq->assoclen + cryptlen);
1275549bd8bcSLEROY Christophe 	else
1276549bd8bcSLEROY Christophe 		sg_count = dma_map_sg(dev, areq->src, sg_count,
1277549bd8bcSLEROY Christophe 				      (areq->src == areq->dst) ?
1278549bd8bcSLEROY Christophe 				      DMA_BIDIRECTIONAL : DMA_TO_DEVICE);
1279549bd8bcSLEROY Christophe 
12809c4a7965SKim Phillips 	/* hmac data */
1281549bd8bcSLEROY Christophe 	ret = talitos_sg_map(dev, areq->src, areq->assoclen, edesc,
1282549bd8bcSLEROY Christophe 			     &desc->ptr[1], sg_count, 0, tbl_off);
128379fd31d3SHoria Geanta 
1284549bd8bcSLEROY Christophe 	if (ret > 1) {
1285340ff60aSHoria Geant? 		tbl_off += ret;
1286549bd8bcSLEROY Christophe 		sync_needed = true;
128779fd31d3SHoria Geanta 	}
128879fd31d3SHoria Geanta 
12899c4a7965SKim Phillips 	/* cipher iv */
12909a655608SLEROY Christophe 	to_talitos_ptr(civ_ptr, edesc->iv_dma, ivsize, is_sec1);
12919c4a7965SKim Phillips 
12929c4a7965SKim Phillips 	/* cipher key */
12932e13ce08SLEROY Christophe 	to_talitos_ptr(ckey_ptr, ctx->dma_key  + ctx->authkeylen,
12942e13ce08SLEROY Christophe 		       ctx->enckeylen, is_sec1);
12959c4a7965SKim Phillips 
12969c4a7965SKim Phillips 	/*
12979c4a7965SKim Phillips 	 * cipher in
12989c4a7965SKim Phillips 	 * map and adjust cipher len to aead request cryptlen.
12999c4a7965SKim Phillips 	 * extent is bytes of HMAC postpended to ciphertext,
13009c4a7965SKim Phillips 	 * typically 12 for ipsec
13019c4a7965SKim Phillips 	 */
13022b122730SLEROY Christophe 	if (is_ipsec_esp && (desc->hdr & DESC_HDR_MODE1_MDEU_CICV))
13032b122730SLEROY Christophe 		elen = authsize;
1304549bd8bcSLEROY Christophe 
13052b122730SLEROY Christophe 	ret = talitos_sg_map_ext(dev, areq->src, cryptlen, edesc, &desc->ptr[4],
13062b122730SLEROY Christophe 				 sg_count, areq->assoclen, tbl_off, elen);
1307549bd8bcSLEROY Christophe 
1308ec8c7d14SLEROY Christophe 	if (ret > 1) {
1309ec8c7d14SLEROY Christophe 		tbl_off += ret;
1310549bd8bcSLEROY Christophe 		sync_needed = true;
1311340ff60aSHoria Geant? 	}
13129c4a7965SKim Phillips 
13139c4a7965SKim Phillips 	/* cipher out */
1314549bd8bcSLEROY Christophe 	if (areq->src != areq->dst) {
1315549bd8bcSLEROY Christophe 		sg_count = edesc->dst_nents ? : 1;
1316549bd8bcSLEROY Christophe 		if (!is_sec1 || sg_count == 1)
1317549bd8bcSLEROY Christophe 			dma_map_sg(dev, areq->dst, sg_count, DMA_FROM_DEVICE);
1318549bd8bcSLEROY Christophe 	}
13199c4a7965SKim Phillips 
1320e04a61beSLEROY Christophe 	ret = talitos_sg_map(dev, areq->dst, cryptlen, edesc, &desc->ptr[5],
1321e04a61beSLEROY Christophe 			     sg_count, areq->assoclen, tbl_off);
13229c4a7965SKim Phillips 
13239a655608SLEROY Christophe 	if (is_ipsec_esp)
1324549bd8bcSLEROY Christophe 		to_talitos_ptr_ext_or(&desc->ptr[5], authsize, is_sec1);
1325aeb4c132SHerbert Xu 
1326e04a61beSLEROY Christophe 	/* ICV data */
1327e04a61beSLEROY Christophe 	if (ret > 1) {
1328e04a61beSLEROY Christophe 		tbl_off += ret;
1329549bd8bcSLEROY Christophe 		edesc->icv_ool = true;
1330549bd8bcSLEROY Christophe 		sync_needed = true;
1331549bd8bcSLEROY Christophe 
13329a655608SLEROY Christophe 		if (is_ipsec_esp) {
133379fd31d3SHoria Geanta 			struct talitos_ptr *tbl_ptr = &edesc->link_tbl[tbl_off];
1334549bd8bcSLEROY Christophe 			int offset = (edesc->src_nents + edesc->dst_nents + 2) *
1335549bd8bcSLEROY Christophe 				     sizeof(struct talitos_ptr) + authsize;
1336fe5720e2SKim Phillips 
1337f3c85bc1SLee Nipper 			/* Add an entry to the link table for ICV data */
1338e04a61beSLEROY Christophe 			to_talitos_ptr_ext_set(tbl_ptr - 1, 0, is_sec1);
1339549bd8bcSLEROY Christophe 			to_talitos_ptr_ext_set(tbl_ptr, DESC_PTR_LNKTBL_RETURN,
1340549bd8bcSLEROY Christophe 					       is_sec1);
13419c4a7965SKim Phillips 
13429c4a7965SKim Phillips 			/* icv data follows link tables */
1343549bd8bcSLEROY Christophe 			to_talitos_ptr(tbl_ptr, edesc->dma_link_tbl + offset,
1344da9de146SLEROY Christophe 				       authsize, is_sec1);
1345e04a61beSLEROY Christophe 		} else {
1346e04a61beSLEROY Christophe 			dma_addr_t addr = edesc->dma_link_tbl;
1347e04a61beSLEROY Christophe 
1348e04a61beSLEROY Christophe 			if (is_sec1)
1349e04a61beSLEROY Christophe 				addr += areq->assoclen + cryptlen;
1350e04a61beSLEROY Christophe 			else
1351e04a61beSLEROY Christophe 				addr += sizeof(struct talitos_ptr) * tbl_off;
1352e04a61beSLEROY Christophe 
1353da9de146SLEROY Christophe 			to_talitos_ptr(&desc->ptr[6], addr, authsize, is_sec1);
1354549bd8bcSLEROY Christophe 		}
13559a655608SLEROY Christophe 	} else if (!is_ipsec_esp) {
1356e04a61beSLEROY Christophe 		ret = talitos_sg_map(dev, areq->dst, authsize, edesc,
1357e04a61beSLEROY Christophe 				     &desc->ptr[6], sg_count, areq->assoclen +
1358e04a61beSLEROY Christophe 							      cryptlen,
1359e04a61beSLEROY Christophe 				     tbl_off);
1360e04a61beSLEROY Christophe 		if (ret > 1) {
1361e04a61beSLEROY Christophe 			tbl_off += ret;
1362e04a61beSLEROY Christophe 			edesc->icv_ool = true;
1363e04a61beSLEROY Christophe 			sync_needed = true;
1364340ff60aSHoria Geant? 		} else {
1365549bd8bcSLEROY Christophe 			edesc->icv_ool = false;
1366549bd8bcSLEROY Christophe 		}
1367e04a61beSLEROY Christophe 	} else {
1368e04a61beSLEROY Christophe 		edesc->icv_ool = false;
1369340ff60aSHoria Geant? 	}
13709c4a7965SKim Phillips 
13719c4a7965SKim Phillips 	/* iv out */
13729a655608SLEROY Christophe 	if (is_ipsec_esp)
1373a2b35aa8SLEROY Christophe 		map_single_talitos_ptr(dev, &desc->ptr[6], ivsize, ctx->iv,
13749c4a7965SKim Phillips 				       DMA_FROM_DEVICE);
13759c4a7965SKim Phillips 
1376549bd8bcSLEROY Christophe 	if (sync_needed)
1377549bd8bcSLEROY Christophe 		dma_sync_single_for_device(dev, edesc->dma_link_tbl,
1378549bd8bcSLEROY Christophe 					   edesc->dma_len,
1379549bd8bcSLEROY Christophe 					   DMA_BIDIRECTIONAL);
1380549bd8bcSLEROY Christophe 
13815228f0f7SKim Phillips 	ret = talitos_submit(dev, ctx->ch, desc, callback, areq);
1382fa86a267SKim Phillips 	if (ret != -EINPROGRESS) {
1383fa86a267SKim Phillips 		ipsec_esp_unmap(dev, edesc, areq);
1384fa86a267SKim Phillips 		kfree(edesc);
1385fa86a267SKim Phillips 	}
1386fa86a267SKim Phillips 	return ret;
13879c4a7965SKim Phillips }
13889c4a7965SKim Phillips 
13899c4a7965SKim Phillips /*
139056af8cd4SLee Nipper  * allocate and map the extended descriptor
13919c4a7965SKim Phillips  */
13924de9d0b5SLee Nipper static struct talitos_edesc *talitos_edesc_alloc(struct device *dev,
13934de9d0b5SLee Nipper 						 struct scatterlist *src,
13944de9d0b5SLee Nipper 						 struct scatterlist *dst,
139579fd31d3SHoria Geanta 						 u8 *iv,
139679fd31d3SHoria Geanta 						 unsigned int assoclen,
13974de9d0b5SLee Nipper 						 unsigned int cryptlen,
13984de9d0b5SLee Nipper 						 unsigned int authsize,
139979fd31d3SHoria Geanta 						 unsigned int ivsize,
14004de9d0b5SLee Nipper 						 int icv_stashing,
140162293a37SHoria Geanta 						 u32 cryptoflags,
140262293a37SHoria Geanta 						 bool encrypt)
14039c4a7965SKim Phillips {
140456af8cd4SLee Nipper 	struct talitos_edesc *edesc;
14056a1e8d14SLEROY Christophe 	int src_nents, dst_nents, alloc_len, dma_len, src_len, dst_len;
140679fd31d3SHoria Geanta 	dma_addr_t iv_dma = 0;
14074de9d0b5SLee Nipper 	gfp_t flags = cryptoflags & CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL :
1408586725f8SKim Phillips 		      GFP_ATOMIC;
14096f65f6acSLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
14106f65f6acSLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
14116f65f6acSLEROY Christophe 	int max_len = is_sec1 ? TALITOS1_MAX_DATA_LEN : TALITOS2_MAX_DATA_LEN;
14129c4a7965SKim Phillips 
14136f65f6acSLEROY Christophe 	if (cryptlen + authsize > max_len) {
14144de9d0b5SLee Nipper 		dev_err(dev, "length exceeds h/w max limit\n");
14159c4a7965SKim Phillips 		return ERR_PTR(-EINVAL);
14169c4a7965SKim Phillips 	}
14179c4a7965SKim Phillips 
141862293a37SHoria Geanta 	if (!dst || dst == src) {
14196a1e8d14SLEROY Christophe 		src_len = assoclen + cryptlen + authsize;
14206a1e8d14SLEROY Christophe 		src_nents = sg_nents_for_len(src, src_len);
14218e409fe1SLABBE Corentin 		if (src_nents < 0) {
14228e409fe1SLABBE Corentin 			dev_err(dev, "Invalid number of src SG.\n");
1423c56c2e17SChristophe Leroy 			return ERR_PTR(-EINVAL);
14248e409fe1SLABBE Corentin 		}
14259c4a7965SKim Phillips 		src_nents = (src_nents == 1) ? 0 : src_nents;
142662293a37SHoria Geanta 		dst_nents = dst ? src_nents : 0;
14276a1e8d14SLEROY Christophe 		dst_len = 0;
142862293a37SHoria Geanta 	} else { /* dst && dst != src*/
14296a1e8d14SLEROY Christophe 		src_len = assoclen + cryptlen + (encrypt ? 0 : authsize);
14306a1e8d14SLEROY Christophe 		src_nents = sg_nents_for_len(src, src_len);
14318e409fe1SLABBE Corentin 		if (src_nents < 0) {
14328e409fe1SLABBE Corentin 			dev_err(dev, "Invalid number of src SG.\n");
1433c56c2e17SChristophe Leroy 			return ERR_PTR(-EINVAL);
14348e409fe1SLABBE Corentin 		}
143562293a37SHoria Geanta 		src_nents = (src_nents == 1) ? 0 : src_nents;
14366a1e8d14SLEROY Christophe 		dst_len = assoclen + cryptlen + (encrypt ? authsize : 0);
14376a1e8d14SLEROY Christophe 		dst_nents = sg_nents_for_len(dst, dst_len);
14388e409fe1SLABBE Corentin 		if (dst_nents < 0) {
14398e409fe1SLABBE Corentin 			dev_err(dev, "Invalid number of dst SG.\n");
1440c56c2e17SChristophe Leroy 			return ERR_PTR(-EINVAL);
14418e409fe1SLABBE Corentin 		}
1442695ad589SLee Nipper 		dst_nents = (dst_nents == 1) ? 0 : dst_nents;
14439c4a7965SKim Phillips 	}
14449c4a7965SKim Phillips 
14459c4a7965SKim Phillips 	/*
14469c4a7965SKim Phillips 	 * allocate space for base edesc plus the link tables,
1447aeb4c132SHerbert Xu 	 * allowing for two separate entries for AD and generated ICV (+ 2),
1448aeb4c132SHerbert Xu 	 * and space for two sets of ICVs (stashed and generated)
14499c4a7965SKim Phillips 	 */
145056af8cd4SLee Nipper 	alloc_len = sizeof(struct talitos_edesc);
1451aeb4c132SHerbert Xu 	if (src_nents || dst_nents) {
14526f65f6acSLEROY Christophe 		if (is_sec1)
14536a1e8d14SLEROY Christophe 			dma_len = (src_nents ? src_len : 0) +
14546a1e8d14SLEROY Christophe 				  (dst_nents ? dst_len : 0);
14556f65f6acSLEROY Christophe 		else
1456aeb4c132SHerbert Xu 			dma_len = (src_nents + dst_nents + 2) *
1457aeb4c132SHerbert Xu 				  sizeof(struct talitos_ptr) + authsize * 2;
14589c4a7965SKim Phillips 		alloc_len += dma_len;
14599c4a7965SKim Phillips 	} else {
14609c4a7965SKim Phillips 		dma_len = 0;
14614de9d0b5SLee Nipper 		alloc_len += icv_stashing ? authsize : 0;
14629c4a7965SKim Phillips 	}
14639c4a7965SKim Phillips 
146437b5e889SLEROY Christophe 	/* if its a ahash, add space for a second desc next to the first one */
146537b5e889SLEROY Christophe 	if (is_sec1 && !dst)
146637b5e889SLEROY Christophe 		alloc_len += sizeof(struct talitos_desc);
14671bea445bSChristophe Leroy 	alloc_len += ivsize;
146837b5e889SLEROY Christophe 
1469586725f8SKim Phillips 	edesc = kmalloc(alloc_len, GFP_DMA | flags);
1470c56c2e17SChristophe Leroy 	if (!edesc)
1471c56c2e17SChristophe Leroy 		return ERR_PTR(-ENOMEM);
14721bea445bSChristophe Leroy 	if (ivsize) {
14731bea445bSChristophe Leroy 		iv = memcpy(((u8 *)edesc) + alloc_len - ivsize, iv, ivsize);
1474c56c2e17SChristophe Leroy 		iv_dma = dma_map_single(dev, iv, ivsize, DMA_TO_DEVICE);
14751bea445bSChristophe Leroy 	}
1476e4a647c4SLEROY Christophe 	memset(&edesc->desc, 0, sizeof(edesc->desc));
14779c4a7965SKim Phillips 
14789c4a7965SKim Phillips 	edesc->src_nents = src_nents;
14799c4a7965SKim Phillips 	edesc->dst_nents = dst_nents;
148079fd31d3SHoria Geanta 	edesc->iv_dma = iv_dma;
14819c4a7965SKim Phillips 	edesc->dma_len = dma_len;
148237b5e889SLEROY Christophe 	if (dma_len) {
148337b5e889SLEROY Christophe 		void *addr = &edesc->link_tbl[0];
148437b5e889SLEROY Christophe 
148537b5e889SLEROY Christophe 		if (is_sec1 && !dst)
148637b5e889SLEROY Christophe 			addr += sizeof(struct talitos_desc);
148737b5e889SLEROY Christophe 		edesc->dma_link_tbl = dma_map_single(dev, addr,
1488497f2e6bSLee Nipper 						     edesc->dma_len,
1489497f2e6bSLee Nipper 						     DMA_BIDIRECTIONAL);
149037b5e889SLEROY Christophe 	}
14919c4a7965SKim Phillips 	return edesc;
14929c4a7965SKim Phillips }
14939c4a7965SKim Phillips 
149479fd31d3SHoria Geanta static struct talitos_edesc *aead_edesc_alloc(struct aead_request *areq, u8 *iv,
149562293a37SHoria Geanta 					      int icv_stashing, bool encrypt)
14964de9d0b5SLee Nipper {
14974de9d0b5SLee Nipper 	struct crypto_aead *authenc = crypto_aead_reqtfm(areq);
1498aeb4c132SHerbert Xu 	unsigned int authsize = crypto_aead_authsize(authenc);
14994de9d0b5SLee Nipper 	struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
150079fd31d3SHoria Geanta 	unsigned int ivsize = crypto_aead_ivsize(authenc);
15014de9d0b5SLee Nipper 
1502aeb4c132SHerbert Xu 	return talitos_edesc_alloc(ctx->dev, areq->src, areq->dst,
150379fd31d3SHoria Geanta 				   iv, areq->assoclen, areq->cryptlen,
1504aeb4c132SHerbert Xu 				   authsize, ivsize, icv_stashing,
150562293a37SHoria Geanta 				   areq->base.flags, encrypt);
15064de9d0b5SLee Nipper }
15074de9d0b5SLee Nipper 
150856af8cd4SLee Nipper static int aead_encrypt(struct aead_request *req)
15099c4a7965SKim Phillips {
15109c4a7965SKim Phillips 	struct crypto_aead *authenc = crypto_aead_reqtfm(req);
15119c4a7965SKim Phillips 	struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
151256af8cd4SLee Nipper 	struct talitos_edesc *edesc;
15139c4a7965SKim Phillips 
15149c4a7965SKim Phillips 	/* allocate extended descriptor */
151562293a37SHoria Geanta 	edesc = aead_edesc_alloc(req, req->iv, 0, true);
15169c4a7965SKim Phillips 	if (IS_ERR(edesc))
15179c4a7965SKim Phillips 		return PTR_ERR(edesc);
15189c4a7965SKim Phillips 
15199c4a7965SKim Phillips 	/* set encrypt */
152070bcaca7SLee Nipper 	edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_MODE0_ENCRYPT;
15219c4a7965SKim Phillips 
1522aeb4c132SHerbert Xu 	return ipsec_esp(edesc, req, ipsec_esp_encrypt_done);
15239c4a7965SKim Phillips }
15249c4a7965SKim Phillips 
152556af8cd4SLee Nipper static int aead_decrypt(struct aead_request *req)
15269c4a7965SKim Phillips {
15279c4a7965SKim Phillips 	struct crypto_aead *authenc = crypto_aead_reqtfm(req);
1528aeb4c132SHerbert Xu 	unsigned int authsize = crypto_aead_authsize(authenc);
15299c4a7965SKim Phillips 	struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
1530fe5720e2SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(ctx->dev);
153156af8cd4SLee Nipper 	struct talitos_edesc *edesc;
15329c4a7965SKim Phillips 	struct scatterlist *sg;
15339c4a7965SKim Phillips 	void *icvdata;
15349c4a7965SKim Phillips 
15359c4a7965SKim Phillips 	req->cryptlen -= authsize;
15369c4a7965SKim Phillips 
15379c4a7965SKim Phillips 	/* allocate extended descriptor */
153862293a37SHoria Geanta 	edesc = aead_edesc_alloc(req, req->iv, 1, false);
15399c4a7965SKim Phillips 	if (IS_ERR(edesc))
15409c4a7965SKim Phillips 		return PTR_ERR(edesc);
15419c4a7965SKim Phillips 
1542fe5720e2SKim Phillips 	if ((priv->features & TALITOS_FTR_HW_AUTH_CHECK) &&
1543e938e465SKim Phillips 	    ((!edesc->src_nents && !edesc->dst_nents) ||
1544e938e465SKim Phillips 	     priv->features & TALITOS_FTR_SRC_LINK_TBL_LEN_INCLUDES_EXTENT)) {
1545fe5720e2SKim Phillips 
1546fe5720e2SKim Phillips 		/* decrypt and check the ICV */
1547e938e465SKim Phillips 		edesc->desc.hdr = ctx->desc_hdr_template |
1548e938e465SKim Phillips 				  DESC_HDR_DIR_INBOUND |
1549fe5720e2SKim Phillips 				  DESC_HDR_MODE1_MDEU_CICV;
1550fe5720e2SKim Phillips 
1551fe5720e2SKim Phillips 		/* reset integrity check result bits */
1552fe5720e2SKim Phillips 
1553aeb4c132SHerbert Xu 		return ipsec_esp(edesc, req, ipsec_esp_decrypt_hwauth_done);
1554e938e465SKim Phillips 	}
1555fe5720e2SKim Phillips 
1556fe5720e2SKim Phillips 	/* Have to check the ICV with software */
1557fe5720e2SKim Phillips 	edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_DIR_INBOUND;
1558fe5720e2SKim Phillips 
15599c4a7965SKim Phillips 	/* stash incoming ICV for later cmp with ICV generated by the h/w */
15609c4a7965SKim Phillips 	if (edesc->dma_len)
1561aeb4c132SHerbert Xu 		icvdata = (char *)&edesc->link_tbl[edesc->src_nents +
1562aeb4c132SHerbert Xu 						   edesc->dst_nents + 2];
15639c4a7965SKim Phillips 	else
15649c4a7965SKim Phillips 		icvdata = &edesc->link_tbl[0];
15659c4a7965SKim Phillips 
15669c4a7965SKim Phillips 	sg = sg_last(req->src, edesc->src_nents ? : 1);
15679c4a7965SKim Phillips 
1568aeb4c132SHerbert Xu 	memcpy(icvdata, (char *)sg_virt(sg) + sg->length - authsize, authsize);
15699c4a7965SKim Phillips 
1570aeb4c132SHerbert Xu 	return ipsec_esp(edesc, req, ipsec_esp_decrypt_swauth_done);
15719c4a7965SKim Phillips }
15729c4a7965SKim Phillips 
15734de9d0b5SLee Nipper static int ablkcipher_setkey(struct crypto_ablkcipher *cipher,
15744de9d0b5SLee Nipper 			     const u8 *key, unsigned int keylen)
15754de9d0b5SLee Nipper {
15764de9d0b5SLee Nipper 	struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher);
15772e13ce08SLEROY Christophe 	struct device *dev = ctx->dev;
1578f384cdc4SLEROY Christophe 
15792e13ce08SLEROY Christophe 	if (ctx->keylen)
15802e13ce08SLEROY Christophe 		dma_unmap_single(dev, ctx->dma_key, ctx->keylen, DMA_TO_DEVICE);
15812e13ce08SLEROY Christophe 
15824de9d0b5SLee Nipper 	memcpy(&ctx->key, key, keylen);
15834de9d0b5SLee Nipper 	ctx->keylen = keylen;
15844de9d0b5SLee Nipper 
15852e13ce08SLEROY Christophe 	ctx->dma_key = dma_map_single(dev, ctx->key, keylen, DMA_TO_DEVICE);
15862e13ce08SLEROY Christophe 
15874de9d0b5SLee Nipper 	return 0;
15884de9d0b5SLee Nipper }
15894de9d0b5SLee Nipper 
1590ef7c5c85SHerbert Xu static int ablkcipher_des_setkey(struct crypto_ablkcipher *cipher,
1591ef7c5c85SHerbert Xu 				 const u8 *key, unsigned int keylen)
1592ef7c5c85SHerbert Xu {
1593ef7c5c85SHerbert Xu 	u32 tmp[DES_EXPKEY_WORDS];
1594ef7c5c85SHerbert Xu 
1595ef7c5c85SHerbert Xu 	if (unlikely(crypto_ablkcipher_get_flags(cipher) &
1596ef7c5c85SHerbert Xu 		     CRYPTO_TFM_REQ_FORBID_WEAK_KEYS) &&
1597ef7c5c85SHerbert Xu 	    !des_ekey(tmp, key)) {
1598ef7c5c85SHerbert Xu 		crypto_ablkcipher_set_flags(cipher, CRYPTO_TFM_RES_WEAK_KEY);
1599ef7c5c85SHerbert Xu 		return -EINVAL;
1600ef7c5c85SHerbert Xu 	}
1601ef7c5c85SHerbert Xu 
1602ef7c5c85SHerbert Xu 	return ablkcipher_setkey(cipher, key, keylen);
1603ef7c5c85SHerbert Xu }
1604ef7c5c85SHerbert Xu 
1605ef7c5c85SHerbert Xu static int ablkcipher_des3_setkey(struct crypto_ablkcipher *cipher,
1606ef7c5c85SHerbert Xu 				  const u8 *key, unsigned int keylen)
1607ef7c5c85SHerbert Xu {
1608ef7c5c85SHerbert Xu 	u32 flags;
1609ef7c5c85SHerbert Xu 	int err;
1610ef7c5c85SHerbert Xu 
1611ef7c5c85SHerbert Xu 	flags = crypto_ablkcipher_get_flags(cipher);
1612ef7c5c85SHerbert Xu 	err = __des3_verify_key(&flags, key);
1613ef7c5c85SHerbert Xu 	if (unlikely(err)) {
1614ef7c5c85SHerbert Xu 		crypto_ablkcipher_set_flags(cipher, flags);
1615ef7c5c85SHerbert Xu 		return err;
1616ef7c5c85SHerbert Xu 	}
1617ef7c5c85SHerbert Xu 
1618ef7c5c85SHerbert Xu 	return ablkcipher_setkey(cipher, key, keylen);
1619ef7c5c85SHerbert Xu }
1620ef7c5c85SHerbert Xu 
16214de9d0b5SLee Nipper static void common_nonsnoop_unmap(struct device *dev,
16224de9d0b5SLee Nipper 				  struct talitos_edesc *edesc,
16234de9d0b5SLee Nipper 				  struct ablkcipher_request *areq)
16244de9d0b5SLee Nipper {
16254de9d0b5SLee Nipper 	unmap_single_talitos_ptr(dev, &edesc->desc.ptr[5], DMA_FROM_DEVICE);
1626032d197eSLEROY Christophe 
16276a1e8d14SLEROY Christophe 	talitos_sg_unmap(dev, edesc, areq->src, areq->dst, areq->nbytes, 0);
16284de9d0b5SLee Nipper 	unmap_single_talitos_ptr(dev, &edesc->desc.ptr[1], DMA_TO_DEVICE);
16294de9d0b5SLee Nipper 
16304de9d0b5SLee Nipper 	if (edesc->dma_len)
16314de9d0b5SLee Nipper 		dma_unmap_single(dev, edesc->dma_link_tbl, edesc->dma_len,
16324de9d0b5SLee Nipper 				 DMA_BIDIRECTIONAL);
16334de9d0b5SLee Nipper }
16344de9d0b5SLee Nipper 
16354de9d0b5SLee Nipper static void ablkcipher_done(struct device *dev,
16364de9d0b5SLee Nipper 			    struct talitos_desc *desc, void *context,
16374de9d0b5SLee Nipper 			    int err)
16384de9d0b5SLee Nipper {
16394de9d0b5SLee Nipper 	struct ablkcipher_request *areq = context;
16403e03e792SChristophe Leroy 	struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(areq);
16413e03e792SChristophe Leroy 	struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher);
16423e03e792SChristophe Leroy 	unsigned int ivsize = crypto_ablkcipher_ivsize(cipher);
164319bbbc63SKim Phillips 	struct talitos_edesc *edesc;
164419bbbc63SKim Phillips 
164519bbbc63SKim Phillips 	edesc = container_of(desc, struct talitos_edesc, desc);
16464de9d0b5SLee Nipper 
16474de9d0b5SLee Nipper 	common_nonsnoop_unmap(dev, edesc, areq);
16483e03e792SChristophe Leroy 	memcpy(areq->info, ctx->iv, ivsize);
16494de9d0b5SLee Nipper 
16504de9d0b5SLee Nipper 	kfree(edesc);
16514de9d0b5SLee Nipper 
16524de9d0b5SLee Nipper 	areq->base.complete(&areq->base, err);
16534de9d0b5SLee Nipper }
16544de9d0b5SLee Nipper 
16554de9d0b5SLee Nipper static int common_nonsnoop(struct talitos_edesc *edesc,
16564de9d0b5SLee Nipper 			   struct ablkcipher_request *areq,
16574de9d0b5SLee Nipper 			   void (*callback) (struct device *dev,
16584de9d0b5SLee Nipper 					     struct talitos_desc *desc,
16594de9d0b5SLee Nipper 					     void *context, int error))
16604de9d0b5SLee Nipper {
16614de9d0b5SLee Nipper 	struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(areq);
16624de9d0b5SLee Nipper 	struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher);
16634de9d0b5SLee Nipper 	struct device *dev = ctx->dev;
16644de9d0b5SLee Nipper 	struct talitos_desc *desc = &edesc->desc;
16654de9d0b5SLee Nipper 	unsigned int cryptlen = areq->nbytes;
166679fd31d3SHoria Geanta 	unsigned int ivsize = crypto_ablkcipher_ivsize(cipher);
16674de9d0b5SLee Nipper 	int sg_count, ret;
16686a1e8d14SLEROY Christophe 	bool sync_needed = false;
1669922f9dc8SLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
1670922f9dc8SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
16714de9d0b5SLee Nipper 
16724de9d0b5SLee Nipper 	/* first DWORD empty */
16734de9d0b5SLee Nipper 
16744de9d0b5SLee Nipper 	/* cipher iv */
1675da9de146SLEROY Christophe 	to_talitos_ptr(&desc->ptr[1], edesc->iv_dma, ivsize, is_sec1);
16764de9d0b5SLee Nipper 
16774de9d0b5SLee Nipper 	/* cipher key */
16782e13ce08SLEROY Christophe 	to_talitos_ptr(&desc->ptr[2], ctx->dma_key, ctx->keylen, is_sec1);
16794de9d0b5SLee Nipper 
16806a1e8d14SLEROY Christophe 	sg_count = edesc->src_nents ?: 1;
16816a1e8d14SLEROY Christophe 	if (is_sec1 && sg_count > 1)
16826a1e8d14SLEROY Christophe 		sg_copy_to_buffer(areq->src, sg_count, edesc->buf,
16836a1e8d14SLEROY Christophe 				  cryptlen);
16846a1e8d14SLEROY Christophe 	else
16856a1e8d14SLEROY Christophe 		sg_count = dma_map_sg(dev, areq->src, sg_count,
16866a1e8d14SLEROY Christophe 				      (areq->src == areq->dst) ?
16876a1e8d14SLEROY Christophe 				      DMA_BIDIRECTIONAL : DMA_TO_DEVICE);
16884de9d0b5SLee Nipper 	/*
16894de9d0b5SLee Nipper 	 * cipher in
16904de9d0b5SLee Nipper 	 */
16916a1e8d14SLEROY Christophe 	sg_count = talitos_sg_map(dev, areq->src, cryptlen, edesc,
16926a1e8d14SLEROY Christophe 				  &desc->ptr[3], sg_count, 0, 0);
16936a1e8d14SLEROY Christophe 	if (sg_count > 1)
16946a1e8d14SLEROY Christophe 		sync_needed = true;
16954de9d0b5SLee Nipper 
16964de9d0b5SLee Nipper 	/* cipher out */
16976a1e8d14SLEROY Christophe 	if (areq->src != areq->dst) {
16986a1e8d14SLEROY Christophe 		sg_count = edesc->dst_nents ? : 1;
16996a1e8d14SLEROY Christophe 		if (!is_sec1 || sg_count == 1)
17006a1e8d14SLEROY Christophe 			dma_map_sg(dev, areq->dst, sg_count, DMA_FROM_DEVICE);
17016a1e8d14SLEROY Christophe 	}
17026a1e8d14SLEROY Christophe 
17036a1e8d14SLEROY Christophe 	ret = talitos_sg_map(dev, areq->dst, cryptlen, edesc, &desc->ptr[4],
17046a1e8d14SLEROY Christophe 			     sg_count, 0, (edesc->src_nents + 1));
17056a1e8d14SLEROY Christophe 	if (ret > 1)
17066a1e8d14SLEROY Christophe 		sync_needed = true;
17074de9d0b5SLee Nipper 
17084de9d0b5SLee Nipper 	/* iv out */
1709a2b35aa8SLEROY Christophe 	map_single_talitos_ptr(dev, &desc->ptr[5], ivsize, ctx->iv,
17104de9d0b5SLee Nipper 			       DMA_FROM_DEVICE);
17114de9d0b5SLee Nipper 
17124de9d0b5SLee Nipper 	/* last DWORD empty */
17134de9d0b5SLee Nipper 
17146a1e8d14SLEROY Christophe 	if (sync_needed)
17156a1e8d14SLEROY Christophe 		dma_sync_single_for_device(dev, edesc->dma_link_tbl,
17166a1e8d14SLEROY Christophe 					   edesc->dma_len, DMA_BIDIRECTIONAL);
17176a1e8d14SLEROY Christophe 
17185228f0f7SKim Phillips 	ret = talitos_submit(dev, ctx->ch, desc, callback, areq);
17194de9d0b5SLee Nipper 	if (ret != -EINPROGRESS) {
17204de9d0b5SLee Nipper 		common_nonsnoop_unmap(dev, edesc, areq);
17214de9d0b5SLee Nipper 		kfree(edesc);
17224de9d0b5SLee Nipper 	}
17234de9d0b5SLee Nipper 	return ret;
17244de9d0b5SLee Nipper }
17254de9d0b5SLee Nipper 
1726e938e465SKim Phillips static struct talitos_edesc *ablkcipher_edesc_alloc(struct ablkcipher_request *
172762293a37SHoria Geanta 						    areq, bool encrypt)
17284de9d0b5SLee Nipper {
17294de9d0b5SLee Nipper 	struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(areq);
17304de9d0b5SLee Nipper 	struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher);
173179fd31d3SHoria Geanta 	unsigned int ivsize = crypto_ablkcipher_ivsize(cipher);
17324de9d0b5SLee Nipper 
1733aeb4c132SHerbert Xu 	return talitos_edesc_alloc(ctx->dev, areq->src, areq->dst,
173479fd31d3SHoria Geanta 				   areq->info, 0, areq->nbytes, 0, ivsize, 0,
173562293a37SHoria Geanta 				   areq->base.flags, encrypt);
17364de9d0b5SLee Nipper }
17374de9d0b5SLee Nipper 
17384de9d0b5SLee Nipper static int ablkcipher_encrypt(struct ablkcipher_request *areq)
17394de9d0b5SLee Nipper {
17404de9d0b5SLee Nipper 	struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(areq);
17414de9d0b5SLee Nipper 	struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher);
17424de9d0b5SLee Nipper 	struct talitos_edesc *edesc;
17434de9d0b5SLee Nipper 
17444de9d0b5SLee Nipper 	/* allocate extended descriptor */
174562293a37SHoria Geanta 	edesc = ablkcipher_edesc_alloc(areq, true);
17464de9d0b5SLee Nipper 	if (IS_ERR(edesc))
17474de9d0b5SLee Nipper 		return PTR_ERR(edesc);
17484de9d0b5SLee Nipper 
17494de9d0b5SLee Nipper 	/* set encrypt */
17504de9d0b5SLee Nipper 	edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_MODE0_ENCRYPT;
17514de9d0b5SLee Nipper 
1752febec542SKim Phillips 	return common_nonsnoop(edesc, areq, ablkcipher_done);
17534de9d0b5SLee Nipper }
17544de9d0b5SLee Nipper 
17554de9d0b5SLee Nipper static int ablkcipher_decrypt(struct ablkcipher_request *areq)
17564de9d0b5SLee Nipper {
17574de9d0b5SLee Nipper 	struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(areq);
17584de9d0b5SLee Nipper 	struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher);
17594de9d0b5SLee Nipper 	struct talitos_edesc *edesc;
17604de9d0b5SLee Nipper 
17614de9d0b5SLee Nipper 	/* allocate extended descriptor */
176262293a37SHoria Geanta 	edesc = ablkcipher_edesc_alloc(areq, false);
17634de9d0b5SLee Nipper 	if (IS_ERR(edesc))
17644de9d0b5SLee Nipper 		return PTR_ERR(edesc);
17654de9d0b5SLee Nipper 
17664de9d0b5SLee Nipper 	edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_DIR_INBOUND;
17674de9d0b5SLee Nipper 
1768febec542SKim Phillips 	return common_nonsnoop(edesc, areq, ablkcipher_done);
17694de9d0b5SLee Nipper }
17704de9d0b5SLee Nipper 
1771497f2e6bSLee Nipper static void common_nonsnoop_hash_unmap(struct device *dev,
1772497f2e6bSLee Nipper 				       struct talitos_edesc *edesc,
1773497f2e6bSLee Nipper 				       struct ahash_request *areq)
1774497f2e6bSLee Nipper {
1775497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
1776ad4cd51fSLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
1777ad4cd51fSLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
1778ad4cd51fSLEROY Christophe 	struct talitos_desc *desc = &edesc->desc;
1779ad4cd51fSLEROY Christophe 	struct talitos_desc *desc2 = desc + 1;
1780ad4cd51fSLEROY Christophe 
1781ad4cd51fSLEROY Christophe 	unmap_single_talitos_ptr(dev, &edesc->desc.ptr[5], DMA_FROM_DEVICE);
1782ad4cd51fSLEROY Christophe 	if (desc->next_desc &&
1783ad4cd51fSLEROY Christophe 	    desc->ptr[5].ptr != desc2->ptr[5].ptr)
1784ad4cd51fSLEROY Christophe 		unmap_single_talitos_ptr(dev, &desc2->ptr[5], DMA_FROM_DEVICE);
1785497f2e6bSLee Nipper 
17866a1e8d14SLEROY Christophe 	talitos_sg_unmap(dev, edesc, req_ctx->psrc, NULL, 0, 0);
1787032d197eSLEROY Christophe 
1788ad4cd51fSLEROY Christophe 	/* When using hashctx-in, must unmap it. */
1789ad4cd51fSLEROY Christophe 	if (from_talitos_ptr_len(&edesc->desc.ptr[1], is_sec1))
1790ad4cd51fSLEROY Christophe 		unmap_single_talitos_ptr(dev, &edesc->desc.ptr[1],
1791ad4cd51fSLEROY Christophe 					 DMA_TO_DEVICE);
1792ad4cd51fSLEROY Christophe 	else if (desc->next_desc)
1793ad4cd51fSLEROY Christophe 		unmap_single_talitos_ptr(dev, &desc2->ptr[1],
1794ad4cd51fSLEROY Christophe 					 DMA_TO_DEVICE);
1795ad4cd51fSLEROY Christophe 
1796ad4cd51fSLEROY Christophe 	if (is_sec1 && req_ctx->nbuf)
1797ad4cd51fSLEROY Christophe 		unmap_single_talitos_ptr(dev, &desc->ptr[3],
1798ad4cd51fSLEROY Christophe 					 DMA_TO_DEVICE);
1799ad4cd51fSLEROY Christophe 
1800497f2e6bSLee Nipper 	if (edesc->dma_len)
1801497f2e6bSLee Nipper 		dma_unmap_single(dev, edesc->dma_link_tbl, edesc->dma_len,
1802497f2e6bSLee Nipper 				 DMA_BIDIRECTIONAL);
1803497f2e6bSLee Nipper 
180437b5e889SLEROY Christophe 	if (edesc->desc.next_desc)
180537b5e889SLEROY Christophe 		dma_unmap_single(dev, be32_to_cpu(edesc->desc.next_desc),
180637b5e889SLEROY Christophe 				 TALITOS_DESC_SIZE, DMA_BIDIRECTIONAL);
1807497f2e6bSLee Nipper }
1808497f2e6bSLee Nipper 
1809497f2e6bSLee Nipper static void ahash_done(struct device *dev,
1810497f2e6bSLee Nipper 		       struct talitos_desc *desc, void *context,
1811497f2e6bSLee Nipper 		       int err)
1812497f2e6bSLee Nipper {
1813497f2e6bSLee Nipper 	struct ahash_request *areq = context;
1814497f2e6bSLee Nipper 	struct talitos_edesc *edesc =
1815497f2e6bSLee Nipper 		 container_of(desc, struct talitos_edesc, desc);
1816497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
1817497f2e6bSLee Nipper 
1818497f2e6bSLee Nipper 	if (!req_ctx->last && req_ctx->to_hash_later) {
1819497f2e6bSLee Nipper 		/* Position any partial block for next update/final/finup */
18203c0dd190SLEROY Christophe 		req_ctx->buf_idx = (req_ctx->buf_idx + 1) & 1;
18215e833bc4SLee Nipper 		req_ctx->nbuf = req_ctx->to_hash_later;
1822497f2e6bSLee Nipper 	}
1823497f2e6bSLee Nipper 	common_nonsnoop_hash_unmap(dev, edesc, areq);
1824497f2e6bSLee Nipper 
1825497f2e6bSLee Nipper 	kfree(edesc);
1826497f2e6bSLee Nipper 
1827497f2e6bSLee Nipper 	areq->base.complete(&areq->base, err);
1828497f2e6bSLee Nipper }
1829497f2e6bSLee Nipper 
18302d02905eSLEROY Christophe /*
18312d02905eSLEROY Christophe  * SEC1 doesn't like hashing of 0 sized message, so we do the padding
18322d02905eSLEROY Christophe  * ourself and submit a padded block
18332d02905eSLEROY Christophe  */
18345b2cf268SLEROY Christophe static void talitos_handle_buggy_hash(struct talitos_ctx *ctx,
18352d02905eSLEROY Christophe 			       struct talitos_edesc *edesc,
18362d02905eSLEROY Christophe 			       struct talitos_ptr *ptr)
18372d02905eSLEROY Christophe {
18382d02905eSLEROY Christophe 	static u8 padded_hash[64] = {
18392d02905eSLEROY Christophe 		0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
18402d02905eSLEROY Christophe 		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
18412d02905eSLEROY Christophe 		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
18422d02905eSLEROY Christophe 		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
18432d02905eSLEROY Christophe 	};
18442d02905eSLEROY Christophe 
18452d02905eSLEROY Christophe 	pr_err_once("Bug in SEC1, padding ourself\n");
18462d02905eSLEROY Christophe 	edesc->desc.hdr &= ~DESC_HDR_MODE0_MDEU_PAD;
18472d02905eSLEROY Christophe 	map_single_talitos_ptr(ctx->dev, ptr, sizeof(padded_hash),
18482d02905eSLEROY Christophe 			       (char *)padded_hash, DMA_TO_DEVICE);
18492d02905eSLEROY Christophe }
18502d02905eSLEROY Christophe 
1851497f2e6bSLee Nipper static int common_nonsnoop_hash(struct talitos_edesc *edesc,
1852497f2e6bSLee Nipper 				struct ahash_request *areq, unsigned int length,
185337b5e889SLEROY Christophe 				unsigned int offset,
1854497f2e6bSLee Nipper 				void (*callback) (struct device *dev,
1855497f2e6bSLee Nipper 						  struct talitos_desc *desc,
1856497f2e6bSLee Nipper 						  void *context, int error))
1857497f2e6bSLee Nipper {
1858497f2e6bSLee Nipper 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
1859497f2e6bSLee Nipper 	struct talitos_ctx *ctx = crypto_ahash_ctx(tfm);
1860497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
1861497f2e6bSLee Nipper 	struct device *dev = ctx->dev;
1862497f2e6bSLee Nipper 	struct talitos_desc *desc = &edesc->desc;
1863032d197eSLEROY Christophe 	int ret;
18646a1e8d14SLEROY Christophe 	bool sync_needed = false;
1865922f9dc8SLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
1866922f9dc8SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
18676a1e8d14SLEROY Christophe 	int sg_count;
1868497f2e6bSLee Nipper 
1869497f2e6bSLee Nipper 	/* first DWORD empty */
1870497f2e6bSLee Nipper 
187160f208d7SKim Phillips 	/* hash context in */
187260f208d7SKim Phillips 	if (!req_ctx->first || req_ctx->swinit) {
18736a4967c3SLEROY Christophe 		map_single_talitos_ptr_nosync(dev, &desc->ptr[1],
1874ad4cd51fSLEROY Christophe 					      req_ctx->hw_context_size,
18756a4967c3SLEROY Christophe 					      req_ctx->hw_context,
1876ad4cd51fSLEROY Christophe 					      DMA_TO_DEVICE);
187760f208d7SKim Phillips 		req_ctx->swinit = 0;
1878afd62fa2SLEROY Christophe 	}
1879497f2e6bSLee Nipper 	/* Indicate next op is not the first. */
1880497f2e6bSLee Nipper 	req_ctx->first = 0;
1881497f2e6bSLee Nipper 
1882497f2e6bSLee Nipper 	/* HMAC key */
1883497f2e6bSLee Nipper 	if (ctx->keylen)
18842e13ce08SLEROY Christophe 		to_talitos_ptr(&desc->ptr[2], ctx->dma_key, ctx->keylen,
18852e13ce08SLEROY Christophe 			       is_sec1);
1886497f2e6bSLee Nipper 
188737b5e889SLEROY Christophe 	if (is_sec1 && req_ctx->nbuf)
188837b5e889SLEROY Christophe 		length -= req_ctx->nbuf;
188937b5e889SLEROY Christophe 
18906a1e8d14SLEROY Christophe 	sg_count = edesc->src_nents ?: 1;
18916a1e8d14SLEROY Christophe 	if (is_sec1 && sg_count > 1)
189237b5e889SLEROY Christophe 		sg_pcopy_to_buffer(req_ctx->psrc, sg_count,
189337b5e889SLEROY Christophe 				   edesc->buf + sizeof(struct talitos_desc),
189437b5e889SLEROY Christophe 				   length, req_ctx->nbuf);
189537b5e889SLEROY Christophe 	else if (length)
18966a1e8d14SLEROY Christophe 		sg_count = dma_map_sg(dev, req_ctx->psrc, sg_count,
18976a1e8d14SLEROY Christophe 				      DMA_TO_DEVICE);
1898497f2e6bSLee Nipper 	/*
1899497f2e6bSLee Nipper 	 * data in
1900497f2e6bSLee Nipper 	 */
190137b5e889SLEROY Christophe 	if (is_sec1 && req_ctx->nbuf) {
1902ad4cd51fSLEROY Christophe 		map_single_talitos_ptr(dev, &desc->ptr[3], req_ctx->nbuf,
1903ad4cd51fSLEROY Christophe 				       req_ctx->buf[req_ctx->buf_idx],
1904ad4cd51fSLEROY Christophe 				       DMA_TO_DEVICE);
190537b5e889SLEROY Christophe 	} else {
19066a1e8d14SLEROY Christophe 		sg_count = talitos_sg_map(dev, req_ctx->psrc, length, edesc,
190737b5e889SLEROY Christophe 					  &desc->ptr[3], sg_count, offset, 0);
19086a1e8d14SLEROY Christophe 		if (sg_count > 1)
19096a1e8d14SLEROY Christophe 			sync_needed = true;
191037b5e889SLEROY Christophe 	}
1911497f2e6bSLee Nipper 
1912497f2e6bSLee Nipper 	/* fifth DWORD empty */
1913497f2e6bSLee Nipper 
1914497f2e6bSLee Nipper 	/* hash/HMAC out -or- hash context out */
1915497f2e6bSLee Nipper 	if (req_ctx->last)
1916497f2e6bSLee Nipper 		map_single_talitos_ptr(dev, &desc->ptr[5],
1917497f2e6bSLee Nipper 				       crypto_ahash_digestsize(tfm),
1918a2b35aa8SLEROY Christophe 				       areq->result, DMA_FROM_DEVICE);
1919497f2e6bSLee Nipper 	else
19206a4967c3SLEROY Christophe 		map_single_talitos_ptr_nosync(dev, &desc->ptr[5],
1921ad4cd51fSLEROY Christophe 					      req_ctx->hw_context_size,
19226a4967c3SLEROY Christophe 					      req_ctx->hw_context,
19236a4967c3SLEROY Christophe 					      DMA_FROM_DEVICE);
1924497f2e6bSLee Nipper 
1925497f2e6bSLee Nipper 	/* last DWORD empty */
1926497f2e6bSLee Nipper 
19272d02905eSLEROY Christophe 	if (is_sec1 && from_talitos_ptr_len(&desc->ptr[3], true) == 0)
19282d02905eSLEROY Christophe 		talitos_handle_buggy_hash(ctx, edesc, &desc->ptr[3]);
19292d02905eSLEROY Christophe 
193037b5e889SLEROY Christophe 	if (is_sec1 && req_ctx->nbuf && length) {
193137b5e889SLEROY Christophe 		struct talitos_desc *desc2 = desc + 1;
193237b5e889SLEROY Christophe 		dma_addr_t next_desc;
193337b5e889SLEROY Christophe 
193437b5e889SLEROY Christophe 		memset(desc2, 0, sizeof(*desc2));
193537b5e889SLEROY Christophe 		desc2->hdr = desc->hdr;
193637b5e889SLEROY Christophe 		desc2->hdr &= ~DESC_HDR_MODE0_MDEU_INIT;
193737b5e889SLEROY Christophe 		desc2->hdr1 = desc2->hdr;
193837b5e889SLEROY Christophe 		desc->hdr &= ~DESC_HDR_MODE0_MDEU_PAD;
193937b5e889SLEROY Christophe 		desc->hdr |= DESC_HDR_MODE0_MDEU_CONT;
194037b5e889SLEROY Christophe 		desc->hdr &= ~DESC_HDR_DONE_NOTIFY;
194137b5e889SLEROY Christophe 
1942ad4cd51fSLEROY Christophe 		if (desc->ptr[1].ptr)
1943ad4cd51fSLEROY Christophe 			copy_talitos_ptr(&desc2->ptr[1], &desc->ptr[1],
1944ad4cd51fSLEROY Christophe 					 is_sec1);
1945ad4cd51fSLEROY Christophe 		else
19466a4967c3SLEROY Christophe 			map_single_talitos_ptr_nosync(dev, &desc2->ptr[1],
1947ad4cd51fSLEROY Christophe 						      req_ctx->hw_context_size,
1948ad4cd51fSLEROY Christophe 						      req_ctx->hw_context,
1949ad4cd51fSLEROY Christophe 						      DMA_TO_DEVICE);
195037b5e889SLEROY Christophe 		copy_talitos_ptr(&desc2->ptr[2], &desc->ptr[2], is_sec1);
195137b5e889SLEROY Christophe 		sg_count = talitos_sg_map(dev, req_ctx->psrc, length, edesc,
195237b5e889SLEROY Christophe 					  &desc2->ptr[3], sg_count, offset, 0);
195337b5e889SLEROY Christophe 		if (sg_count > 1)
195437b5e889SLEROY Christophe 			sync_needed = true;
195537b5e889SLEROY Christophe 		copy_talitos_ptr(&desc2->ptr[5], &desc->ptr[5], is_sec1);
195637b5e889SLEROY Christophe 		if (req_ctx->last)
19576a4967c3SLEROY Christophe 			map_single_talitos_ptr_nosync(dev, &desc->ptr[5],
1958ad4cd51fSLEROY Christophe 						      req_ctx->hw_context_size,
1959ad4cd51fSLEROY Christophe 						      req_ctx->hw_context,
1960ad4cd51fSLEROY Christophe 						      DMA_FROM_DEVICE);
196137b5e889SLEROY Christophe 
196237b5e889SLEROY Christophe 		next_desc = dma_map_single(dev, &desc2->hdr1, TALITOS_DESC_SIZE,
196337b5e889SLEROY Christophe 					   DMA_BIDIRECTIONAL);
196437b5e889SLEROY Christophe 		desc->next_desc = cpu_to_be32(next_desc);
196537b5e889SLEROY Christophe 	}
196637b5e889SLEROY Christophe 
19676a1e8d14SLEROY Christophe 	if (sync_needed)
19686a1e8d14SLEROY Christophe 		dma_sync_single_for_device(dev, edesc->dma_link_tbl,
19696a1e8d14SLEROY Christophe 					   edesc->dma_len, DMA_BIDIRECTIONAL);
19706a1e8d14SLEROY Christophe 
19715228f0f7SKim Phillips 	ret = talitos_submit(dev, ctx->ch, desc, callback, areq);
1972497f2e6bSLee Nipper 	if (ret != -EINPROGRESS) {
1973497f2e6bSLee Nipper 		common_nonsnoop_hash_unmap(dev, edesc, areq);
1974497f2e6bSLee Nipper 		kfree(edesc);
1975497f2e6bSLee Nipper 	}
1976497f2e6bSLee Nipper 	return ret;
1977497f2e6bSLee Nipper }
1978497f2e6bSLee Nipper 
1979497f2e6bSLee Nipper static struct talitos_edesc *ahash_edesc_alloc(struct ahash_request *areq,
1980497f2e6bSLee Nipper 					       unsigned int nbytes)
1981497f2e6bSLee Nipper {
1982497f2e6bSLee Nipper 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
1983497f2e6bSLee Nipper 	struct talitos_ctx *ctx = crypto_ahash_ctx(tfm);
1984497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
198537b5e889SLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(ctx->dev);
198637b5e889SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
198737b5e889SLEROY Christophe 
198837b5e889SLEROY Christophe 	if (is_sec1)
198937b5e889SLEROY Christophe 		nbytes -= req_ctx->nbuf;
1990497f2e6bSLee Nipper 
1991aeb4c132SHerbert Xu 	return talitos_edesc_alloc(ctx->dev, req_ctx->psrc, NULL, NULL, 0,
199262293a37SHoria Geanta 				   nbytes, 0, 0, 0, areq->base.flags, false);
1993497f2e6bSLee Nipper }
1994497f2e6bSLee Nipper 
1995497f2e6bSLee Nipper static int ahash_init(struct ahash_request *areq)
1996497f2e6bSLee Nipper {
1997497f2e6bSLee Nipper 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
19986a4967c3SLEROY Christophe 	struct talitos_ctx *ctx = crypto_ahash_ctx(tfm);
19996a4967c3SLEROY Christophe 	struct device *dev = ctx->dev;
2000497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
200149f9783bSLEROY Christophe 	unsigned int size;
20026a4967c3SLEROY Christophe 	dma_addr_t dma;
2003497f2e6bSLee Nipper 
2004497f2e6bSLee Nipper 	/* Initialize the context */
20053c0dd190SLEROY Christophe 	req_ctx->buf_idx = 0;
20065e833bc4SLee Nipper 	req_ctx->nbuf = 0;
200760f208d7SKim Phillips 	req_ctx->first = 1; /* first indicates h/w must init its context */
200860f208d7SKim Phillips 	req_ctx->swinit = 0; /* assume h/w init of context */
200949f9783bSLEROY Christophe 	size =	(crypto_ahash_digestsize(tfm) <= SHA256_DIGEST_SIZE)
2010497f2e6bSLee Nipper 			? TALITOS_MDEU_CONTEXT_SIZE_MD5_SHA1_SHA256
2011497f2e6bSLee Nipper 			: TALITOS_MDEU_CONTEXT_SIZE_SHA384_SHA512;
201249f9783bSLEROY Christophe 	req_ctx->hw_context_size = size;
2013497f2e6bSLee Nipper 
20146a4967c3SLEROY Christophe 	dma = dma_map_single(dev, req_ctx->hw_context, req_ctx->hw_context_size,
20156a4967c3SLEROY Christophe 			     DMA_TO_DEVICE);
20166a4967c3SLEROY Christophe 	dma_unmap_single(dev, dma, req_ctx->hw_context_size, DMA_TO_DEVICE);
20176a4967c3SLEROY Christophe 
2018497f2e6bSLee Nipper 	return 0;
2019497f2e6bSLee Nipper }
2020497f2e6bSLee Nipper 
202160f208d7SKim Phillips /*
202260f208d7SKim Phillips  * on h/w without explicit sha224 support, we initialize h/w context
202360f208d7SKim Phillips  * manually with sha224 constants, and tell it to run sha256.
202460f208d7SKim Phillips  */
202560f208d7SKim Phillips static int ahash_init_sha224_swinit(struct ahash_request *areq)
202660f208d7SKim Phillips {
202760f208d7SKim Phillips 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
202860f208d7SKim Phillips 
2029a752447aSKim Phillips 	req_ctx->hw_context[0] = SHA224_H0;
2030a752447aSKim Phillips 	req_ctx->hw_context[1] = SHA224_H1;
2031a752447aSKim Phillips 	req_ctx->hw_context[2] = SHA224_H2;
2032a752447aSKim Phillips 	req_ctx->hw_context[3] = SHA224_H3;
2033a752447aSKim Phillips 	req_ctx->hw_context[4] = SHA224_H4;
2034a752447aSKim Phillips 	req_ctx->hw_context[5] = SHA224_H5;
2035a752447aSKim Phillips 	req_ctx->hw_context[6] = SHA224_H6;
2036a752447aSKim Phillips 	req_ctx->hw_context[7] = SHA224_H7;
203760f208d7SKim Phillips 
203860f208d7SKim Phillips 	/* init 64-bit count */
203960f208d7SKim Phillips 	req_ctx->hw_context[8] = 0;
204060f208d7SKim Phillips 	req_ctx->hw_context[9] = 0;
204160f208d7SKim Phillips 
20426a4967c3SLEROY Christophe 	ahash_init(areq);
20436a4967c3SLEROY Christophe 	req_ctx->swinit = 1;/* prevent h/w initting context with sha256 values*/
20446a4967c3SLEROY Christophe 
204560f208d7SKim Phillips 	return 0;
204660f208d7SKim Phillips }
204760f208d7SKim Phillips 
2048497f2e6bSLee Nipper static int ahash_process_req(struct ahash_request *areq, unsigned int nbytes)
2049497f2e6bSLee Nipper {
2050497f2e6bSLee Nipper 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
2051497f2e6bSLee Nipper 	struct talitos_ctx *ctx = crypto_ahash_ctx(tfm);
2052497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
2053497f2e6bSLee Nipper 	struct talitos_edesc *edesc;
2054497f2e6bSLee Nipper 	unsigned int blocksize =
2055497f2e6bSLee Nipper 			crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm));
2056497f2e6bSLee Nipper 	unsigned int nbytes_to_hash;
2057497f2e6bSLee Nipper 	unsigned int to_hash_later;
20585e833bc4SLee Nipper 	unsigned int nsg;
20598e409fe1SLABBE Corentin 	int nents;
206037b5e889SLEROY Christophe 	struct device *dev = ctx->dev;
206137b5e889SLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
206237b5e889SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
206337b5e889SLEROY Christophe 	int offset = 0;
20643c0dd190SLEROY Christophe 	u8 *ctx_buf = req_ctx->buf[req_ctx->buf_idx];
2065497f2e6bSLee Nipper 
20665e833bc4SLee Nipper 	if (!req_ctx->last && (nbytes + req_ctx->nbuf <= blocksize)) {
20675e833bc4SLee Nipper 		/* Buffer up to one whole block */
20688e409fe1SLABBE Corentin 		nents = sg_nents_for_len(areq->src, nbytes);
20698e409fe1SLABBE Corentin 		if (nents < 0) {
20708e409fe1SLABBE Corentin 			dev_err(ctx->dev, "Invalid number of src SG.\n");
20718e409fe1SLABBE Corentin 			return nents;
20728e409fe1SLABBE Corentin 		}
20738e409fe1SLABBE Corentin 		sg_copy_to_buffer(areq->src, nents,
20743c0dd190SLEROY Christophe 				  ctx_buf + req_ctx->nbuf, nbytes);
20755e833bc4SLee Nipper 		req_ctx->nbuf += nbytes;
2076497f2e6bSLee Nipper 		return 0;
2077497f2e6bSLee Nipper 	}
2078497f2e6bSLee Nipper 
20795e833bc4SLee Nipper 	/* At least (blocksize + 1) bytes are available to hash */
20805e833bc4SLee Nipper 	nbytes_to_hash = nbytes + req_ctx->nbuf;
20815e833bc4SLee Nipper 	to_hash_later = nbytes_to_hash & (blocksize - 1);
20825e833bc4SLee Nipper 
20835e833bc4SLee Nipper 	if (req_ctx->last)
20845e833bc4SLee Nipper 		to_hash_later = 0;
20855e833bc4SLee Nipper 	else if (to_hash_later)
20865e833bc4SLee Nipper 		/* There is a partial block. Hash the full block(s) now */
20875e833bc4SLee Nipper 		nbytes_to_hash -= to_hash_later;
20885e833bc4SLee Nipper 	else {
20895e833bc4SLee Nipper 		/* Keep one block buffered */
20905e833bc4SLee Nipper 		nbytes_to_hash -= blocksize;
20915e833bc4SLee Nipper 		to_hash_later = blocksize;
2092497f2e6bSLee Nipper 	}
20935e833bc4SLee Nipper 
20945e833bc4SLee Nipper 	/* Chain in any previously buffered data */
209537b5e889SLEROY Christophe 	if (!is_sec1 && req_ctx->nbuf) {
20965e833bc4SLee Nipper 		nsg = (req_ctx->nbuf < nbytes_to_hash) ? 2 : 1;
20975e833bc4SLee Nipper 		sg_init_table(req_ctx->bufsl, nsg);
20983c0dd190SLEROY Christophe 		sg_set_buf(req_ctx->bufsl, ctx_buf, req_ctx->nbuf);
20995e833bc4SLee Nipper 		if (nsg > 1)
2100c56f6d12SDan Williams 			sg_chain(req_ctx->bufsl, 2, areq->src);
21015e833bc4SLee Nipper 		req_ctx->psrc = req_ctx->bufsl;
210237b5e889SLEROY Christophe 	} else if (is_sec1 && req_ctx->nbuf && req_ctx->nbuf < blocksize) {
210337b5e889SLEROY Christophe 		if (nbytes_to_hash > blocksize)
210437b5e889SLEROY Christophe 			offset = blocksize - req_ctx->nbuf;
210537b5e889SLEROY Christophe 		else
210637b5e889SLEROY Christophe 			offset = nbytes_to_hash - req_ctx->nbuf;
210737b5e889SLEROY Christophe 		nents = sg_nents_for_len(areq->src, offset);
210837b5e889SLEROY Christophe 		if (nents < 0) {
210937b5e889SLEROY Christophe 			dev_err(ctx->dev, "Invalid number of src SG.\n");
211037b5e889SLEROY Christophe 			return nents;
211137b5e889SLEROY Christophe 		}
211237b5e889SLEROY Christophe 		sg_copy_to_buffer(areq->src, nents,
21133c0dd190SLEROY Christophe 				  ctx_buf + req_ctx->nbuf, offset);
211437b5e889SLEROY Christophe 		req_ctx->nbuf += offset;
211537b5e889SLEROY Christophe 		req_ctx->psrc = areq->src;
21165e833bc4SLee Nipper 	} else
21175e833bc4SLee Nipper 		req_ctx->psrc = areq->src;
21185e833bc4SLee Nipper 
2119497f2e6bSLee Nipper 	if (to_hash_later) {
21208e409fe1SLABBE Corentin 		nents = sg_nents_for_len(areq->src, nbytes);
21218e409fe1SLABBE Corentin 		if (nents < 0) {
21228e409fe1SLABBE Corentin 			dev_err(ctx->dev, "Invalid number of src SG.\n");
21238e409fe1SLABBE Corentin 			return nents;
21248e409fe1SLABBE Corentin 		}
2125d0525723SAkinobu Mita 		sg_pcopy_to_buffer(areq->src, nents,
21263c0dd190SLEROY Christophe 				   req_ctx->buf[(req_ctx->buf_idx + 1) & 1],
2127497f2e6bSLee Nipper 				      to_hash_later,
2128497f2e6bSLee Nipper 				      nbytes - to_hash_later);
2129497f2e6bSLee Nipper 	}
2130497f2e6bSLee Nipper 	req_ctx->to_hash_later = to_hash_later;
2131497f2e6bSLee Nipper 
21325e833bc4SLee Nipper 	/* Allocate extended descriptor */
2133497f2e6bSLee Nipper 	edesc = ahash_edesc_alloc(areq, nbytes_to_hash);
2134497f2e6bSLee Nipper 	if (IS_ERR(edesc))
2135497f2e6bSLee Nipper 		return PTR_ERR(edesc);
2136497f2e6bSLee Nipper 
2137497f2e6bSLee Nipper 	edesc->desc.hdr = ctx->desc_hdr_template;
2138497f2e6bSLee Nipper 
2139497f2e6bSLee Nipper 	/* On last one, request SEC to pad; otherwise continue */
2140497f2e6bSLee Nipper 	if (req_ctx->last)
2141497f2e6bSLee Nipper 		edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_PAD;
2142497f2e6bSLee Nipper 	else
2143497f2e6bSLee Nipper 		edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_CONT;
2144497f2e6bSLee Nipper 
214560f208d7SKim Phillips 	/* request SEC to INIT hash. */
214660f208d7SKim Phillips 	if (req_ctx->first && !req_ctx->swinit)
2147497f2e6bSLee Nipper 		edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_INIT;
2148497f2e6bSLee Nipper 
2149497f2e6bSLee Nipper 	/* When the tfm context has a keylen, it's an HMAC.
2150497f2e6bSLee Nipper 	 * A first or last (ie. not middle) descriptor must request HMAC.
2151497f2e6bSLee Nipper 	 */
2152497f2e6bSLee Nipper 	if (ctx->keylen && (req_ctx->first || req_ctx->last))
2153497f2e6bSLee Nipper 		edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_HMAC;
2154497f2e6bSLee Nipper 
215537b5e889SLEROY Christophe 	return common_nonsnoop_hash(edesc, areq, nbytes_to_hash, offset,
2156497f2e6bSLee Nipper 				    ahash_done);
2157497f2e6bSLee Nipper }
2158497f2e6bSLee Nipper 
2159497f2e6bSLee Nipper static int ahash_update(struct ahash_request *areq)
2160497f2e6bSLee Nipper {
2161497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
2162497f2e6bSLee Nipper 
2163497f2e6bSLee Nipper 	req_ctx->last = 0;
2164497f2e6bSLee Nipper 
2165497f2e6bSLee Nipper 	return ahash_process_req(areq, areq->nbytes);
2166497f2e6bSLee Nipper }
2167497f2e6bSLee Nipper 
2168497f2e6bSLee Nipper static int ahash_final(struct ahash_request *areq)
2169497f2e6bSLee Nipper {
2170497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
2171497f2e6bSLee Nipper 
2172497f2e6bSLee Nipper 	req_ctx->last = 1;
2173497f2e6bSLee Nipper 
2174497f2e6bSLee Nipper 	return ahash_process_req(areq, 0);
2175497f2e6bSLee Nipper }
2176497f2e6bSLee Nipper 
2177497f2e6bSLee Nipper static int ahash_finup(struct ahash_request *areq)
2178497f2e6bSLee Nipper {
2179497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
2180497f2e6bSLee Nipper 
2181497f2e6bSLee Nipper 	req_ctx->last = 1;
2182497f2e6bSLee Nipper 
2183497f2e6bSLee Nipper 	return ahash_process_req(areq, areq->nbytes);
2184497f2e6bSLee Nipper }
2185497f2e6bSLee Nipper 
2186497f2e6bSLee Nipper static int ahash_digest(struct ahash_request *areq)
2187497f2e6bSLee Nipper {
2188497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
218960f208d7SKim Phillips 	struct crypto_ahash *ahash = crypto_ahash_reqtfm(areq);
2190497f2e6bSLee Nipper 
219160f208d7SKim Phillips 	ahash->init(areq);
2192497f2e6bSLee Nipper 	req_ctx->last = 1;
2193497f2e6bSLee Nipper 
2194497f2e6bSLee Nipper 	return ahash_process_req(areq, areq->nbytes);
2195497f2e6bSLee Nipper }
2196497f2e6bSLee Nipper 
21973639ca84SHoria Geant? static int ahash_export(struct ahash_request *areq, void *out)
21983639ca84SHoria Geant? {
21993639ca84SHoria Geant? 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
22003639ca84SHoria Geant? 	struct talitos_export_state *export = out;
22016a4967c3SLEROY Christophe 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
22026a4967c3SLEROY Christophe 	struct talitos_ctx *ctx = crypto_ahash_ctx(tfm);
22036a4967c3SLEROY Christophe 	struct device *dev = ctx->dev;
22046a4967c3SLEROY Christophe 	dma_addr_t dma;
22056a4967c3SLEROY Christophe 
22066a4967c3SLEROY Christophe 	dma = dma_map_single(dev, req_ctx->hw_context, req_ctx->hw_context_size,
22076a4967c3SLEROY Christophe 			     DMA_FROM_DEVICE);
22086a4967c3SLEROY Christophe 	dma_unmap_single(dev, dma, req_ctx->hw_context_size, DMA_FROM_DEVICE);
22093639ca84SHoria Geant? 
22103639ca84SHoria Geant? 	memcpy(export->hw_context, req_ctx->hw_context,
22113639ca84SHoria Geant? 	       req_ctx->hw_context_size);
22123c0dd190SLEROY Christophe 	memcpy(export->buf, req_ctx->buf[req_ctx->buf_idx], req_ctx->nbuf);
22133639ca84SHoria Geant? 	export->swinit = req_ctx->swinit;
22143639ca84SHoria Geant? 	export->first = req_ctx->first;
22153639ca84SHoria Geant? 	export->last = req_ctx->last;
22163639ca84SHoria Geant? 	export->to_hash_later = req_ctx->to_hash_later;
22173639ca84SHoria Geant? 	export->nbuf = req_ctx->nbuf;
22183639ca84SHoria Geant? 
22193639ca84SHoria Geant? 	return 0;
22203639ca84SHoria Geant? }
22213639ca84SHoria Geant? 
22223639ca84SHoria Geant? static int ahash_import(struct ahash_request *areq, const void *in)
22233639ca84SHoria Geant? {
22243639ca84SHoria Geant? 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
22253639ca84SHoria Geant? 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
22266a4967c3SLEROY Christophe 	struct talitos_ctx *ctx = crypto_ahash_ctx(tfm);
22276a4967c3SLEROY Christophe 	struct device *dev = ctx->dev;
22283639ca84SHoria Geant? 	const struct talitos_export_state *export = in;
222949f9783bSLEROY Christophe 	unsigned int size;
22306a4967c3SLEROY Christophe 	dma_addr_t dma;
22313639ca84SHoria Geant? 
22323639ca84SHoria Geant? 	memset(req_ctx, 0, sizeof(*req_ctx));
223349f9783bSLEROY Christophe 	size = (crypto_ahash_digestsize(tfm) <= SHA256_DIGEST_SIZE)
22343639ca84SHoria Geant? 			? TALITOS_MDEU_CONTEXT_SIZE_MD5_SHA1_SHA256
22353639ca84SHoria Geant? 			: TALITOS_MDEU_CONTEXT_SIZE_SHA384_SHA512;
223649f9783bSLEROY Christophe 	req_ctx->hw_context_size = size;
223749f9783bSLEROY Christophe 	memcpy(req_ctx->hw_context, export->hw_context, size);
22383c0dd190SLEROY Christophe 	memcpy(req_ctx->buf[0], export->buf, export->nbuf);
22393639ca84SHoria Geant? 	req_ctx->swinit = export->swinit;
22403639ca84SHoria Geant? 	req_ctx->first = export->first;
22413639ca84SHoria Geant? 	req_ctx->last = export->last;
22423639ca84SHoria Geant? 	req_ctx->to_hash_later = export->to_hash_later;
22433639ca84SHoria Geant? 	req_ctx->nbuf = export->nbuf;
22443639ca84SHoria Geant? 
22456a4967c3SLEROY Christophe 	dma = dma_map_single(dev, req_ctx->hw_context, req_ctx->hw_context_size,
22466a4967c3SLEROY Christophe 			     DMA_TO_DEVICE);
22476a4967c3SLEROY Christophe 	dma_unmap_single(dev, dma, req_ctx->hw_context_size, DMA_TO_DEVICE);
22486a4967c3SLEROY Christophe 
22493639ca84SHoria Geant? 	return 0;
22503639ca84SHoria Geant? }
22513639ca84SHoria Geant? 
225279b3a418SLee Nipper static int keyhash(struct crypto_ahash *tfm, const u8 *key, unsigned int keylen,
225379b3a418SLee Nipper 		   u8 *hash)
225479b3a418SLee Nipper {
225579b3a418SLee Nipper 	struct talitos_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm));
225679b3a418SLee Nipper 
225779b3a418SLee Nipper 	struct scatterlist sg[1];
225879b3a418SLee Nipper 	struct ahash_request *req;
2259f1c90ac3SGilad Ben-Yossef 	struct crypto_wait wait;
226079b3a418SLee Nipper 	int ret;
226179b3a418SLee Nipper 
2262f1c90ac3SGilad Ben-Yossef 	crypto_init_wait(&wait);
226379b3a418SLee Nipper 
226479b3a418SLee Nipper 	req = ahash_request_alloc(tfm, GFP_KERNEL);
226579b3a418SLee Nipper 	if (!req)
226679b3a418SLee Nipper 		return -ENOMEM;
226779b3a418SLee Nipper 
226879b3a418SLee Nipper 	/* Keep tfm keylen == 0 during hash of the long key */
226979b3a418SLee Nipper 	ctx->keylen = 0;
227079b3a418SLee Nipper 	ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
2271f1c90ac3SGilad Ben-Yossef 				   crypto_req_done, &wait);
227279b3a418SLee Nipper 
227379b3a418SLee Nipper 	sg_init_one(&sg[0], key, keylen);
227479b3a418SLee Nipper 
227579b3a418SLee Nipper 	ahash_request_set_crypt(req, sg, hash, keylen);
2276f1c90ac3SGilad Ben-Yossef 	ret = crypto_wait_req(crypto_ahash_digest(req), &wait);
2277f1c90ac3SGilad Ben-Yossef 
227879b3a418SLee Nipper 	ahash_request_free(req);
227979b3a418SLee Nipper 
228079b3a418SLee Nipper 	return ret;
228179b3a418SLee Nipper }
228279b3a418SLee Nipper 
228379b3a418SLee Nipper static int ahash_setkey(struct crypto_ahash *tfm, const u8 *key,
228479b3a418SLee Nipper 			unsigned int keylen)
228579b3a418SLee Nipper {
228679b3a418SLee Nipper 	struct talitos_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm));
22872e13ce08SLEROY Christophe 	struct device *dev = ctx->dev;
228879b3a418SLee Nipper 	unsigned int blocksize =
228979b3a418SLee Nipper 			crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm));
229079b3a418SLee Nipper 	unsigned int digestsize = crypto_ahash_digestsize(tfm);
229179b3a418SLee Nipper 	unsigned int keysize = keylen;
229279b3a418SLee Nipper 	u8 hash[SHA512_DIGEST_SIZE];
229379b3a418SLee Nipper 	int ret;
229479b3a418SLee Nipper 
229579b3a418SLee Nipper 	if (keylen <= blocksize)
229679b3a418SLee Nipper 		memcpy(ctx->key, key, keysize);
229779b3a418SLee Nipper 	else {
229879b3a418SLee Nipper 		/* Must get the hash of the long key */
229979b3a418SLee Nipper 		ret = keyhash(tfm, key, keylen, hash);
230079b3a418SLee Nipper 
230179b3a418SLee Nipper 		if (ret) {
230279b3a418SLee Nipper 			crypto_ahash_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
230379b3a418SLee Nipper 			return -EINVAL;
230479b3a418SLee Nipper 		}
230579b3a418SLee Nipper 
230679b3a418SLee Nipper 		keysize = digestsize;
230779b3a418SLee Nipper 		memcpy(ctx->key, hash, digestsize);
230879b3a418SLee Nipper 	}
230979b3a418SLee Nipper 
23102e13ce08SLEROY Christophe 	if (ctx->keylen)
23112e13ce08SLEROY Christophe 		dma_unmap_single(dev, ctx->dma_key, ctx->keylen, DMA_TO_DEVICE);
23122e13ce08SLEROY Christophe 
231379b3a418SLee Nipper 	ctx->keylen = keysize;
23142e13ce08SLEROY Christophe 	ctx->dma_key = dma_map_single(dev, ctx->key, keysize, DMA_TO_DEVICE);
231579b3a418SLee Nipper 
231679b3a418SLee Nipper 	return 0;
231779b3a418SLee Nipper }
231879b3a418SLee Nipper 
231979b3a418SLee Nipper 
23209c4a7965SKim Phillips struct talitos_alg_template {
2321d5e4aaefSLee Nipper 	u32 type;
2322b0057763SLEROY Christophe 	u32 priority;
2323d5e4aaefSLee Nipper 	union {
2324d5e4aaefSLee Nipper 		struct crypto_alg crypto;
2325acbf7c62SLee Nipper 		struct ahash_alg hash;
2326aeb4c132SHerbert Xu 		struct aead_alg aead;
2327d5e4aaefSLee Nipper 	} alg;
23289c4a7965SKim Phillips 	__be32 desc_hdr_template;
23299c4a7965SKim Phillips };
23309c4a7965SKim Phillips 
23319c4a7965SKim Phillips static struct talitos_alg_template driver_algs[] = {
2332991155baSHoria Geanta 	/* AEAD algorithms.  These use a single-pass ipsec_esp descriptor */
2333d5e4aaefSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2334aeb4c132SHerbert Xu 		.alg.aead = {
2335aeb4c132SHerbert Xu 			.base = {
233656af8cd4SLee Nipper 				.cra_name = "authenc(hmac(sha1),cbc(aes))",
2337aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha1-"
2338aeb4c132SHerbert Xu 						   "cbc-aes-talitos",
233956af8cd4SLee Nipper 				.cra_blocksize = AES_BLOCK_SIZE,
2340aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2341aeb4c132SHerbert Xu 			},
23423952f17eSLee Nipper 			.ivsize = AES_BLOCK_SIZE,
23433952f17eSLee Nipper 			.maxauthsize = SHA1_DIGEST_SIZE,
23449c4a7965SKim Phillips 		},
23459c4a7965SKim Phillips 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
23469c4a7965SKim Phillips 			             DESC_HDR_SEL0_AESU |
23479c4a7965SKim Phillips 		                     DESC_HDR_MODE0_AESU_CBC |
23489c4a7965SKim Phillips 		                     DESC_HDR_SEL1_MDEUA |
23499c4a7965SKim Phillips 		                     DESC_HDR_MODE1_MDEU_INIT |
23509c4a7965SKim Phillips 		                     DESC_HDR_MODE1_MDEU_PAD |
23519c4a7965SKim Phillips 		                     DESC_HDR_MODE1_MDEU_SHA1_HMAC,
235270bcaca7SLee Nipper 	},
2353d5e4aaefSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AEAD,
23547405c8d7SLEROY Christophe 		.priority = TALITOS_CRA_PRIORITY_AEAD_HSNA,
23557405c8d7SLEROY Christophe 		.alg.aead = {
23567405c8d7SLEROY Christophe 			.base = {
23577405c8d7SLEROY Christophe 				.cra_name = "authenc(hmac(sha1),cbc(aes))",
23587405c8d7SLEROY Christophe 				.cra_driver_name = "authenc-hmac-sha1-"
2359*a1a42f84SChristophe Leroy 						   "cbc-aes-talitos-hsna",
23607405c8d7SLEROY Christophe 				.cra_blocksize = AES_BLOCK_SIZE,
23617405c8d7SLEROY Christophe 				.cra_flags = CRYPTO_ALG_ASYNC,
23627405c8d7SLEROY Christophe 			},
23637405c8d7SLEROY Christophe 			.ivsize = AES_BLOCK_SIZE,
23647405c8d7SLEROY Christophe 			.maxauthsize = SHA1_DIGEST_SIZE,
23657405c8d7SLEROY Christophe 		},
23667405c8d7SLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU |
23677405c8d7SLEROY Christophe 				     DESC_HDR_SEL0_AESU |
23687405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_AESU_CBC |
23697405c8d7SLEROY Christophe 				     DESC_HDR_SEL1_MDEUA |
23707405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_INIT |
23717405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_PAD |
23727405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_SHA1_HMAC,
23737405c8d7SLEROY Christophe 	},
23747405c8d7SLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2375aeb4c132SHerbert Xu 		.alg.aead = {
2376aeb4c132SHerbert Xu 			.base = {
2377aeb4c132SHerbert Xu 				.cra_name = "authenc(hmac(sha1),"
2378aeb4c132SHerbert Xu 					    "cbc(des3_ede))",
2379aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha1-"
2380aeb4c132SHerbert Xu 						   "cbc-3des-talitos",
238156af8cd4SLee Nipper 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
2382aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2383aeb4c132SHerbert Xu 			},
23843952f17eSLee Nipper 			.ivsize = DES3_EDE_BLOCK_SIZE,
23853952f17eSLee Nipper 			.maxauthsize = SHA1_DIGEST_SIZE,
2386ef7c5c85SHerbert Xu 			.setkey = aead_des3_setkey,
238770bcaca7SLee Nipper 		},
238870bcaca7SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
238970bcaca7SLee Nipper 			             DESC_HDR_SEL0_DEU |
239070bcaca7SLee Nipper 		                     DESC_HDR_MODE0_DEU_CBC |
239170bcaca7SLee Nipper 		                     DESC_HDR_MODE0_DEU_3DES |
239270bcaca7SLee Nipper 		                     DESC_HDR_SEL1_MDEUA |
239370bcaca7SLee Nipper 		                     DESC_HDR_MODE1_MDEU_INIT |
239470bcaca7SLee Nipper 		                     DESC_HDR_MODE1_MDEU_PAD |
239570bcaca7SLee Nipper 		                     DESC_HDR_MODE1_MDEU_SHA1_HMAC,
23963952f17eSLee Nipper 	},
2397d5e4aaefSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AEAD,
23987405c8d7SLEROY Christophe 		.priority = TALITOS_CRA_PRIORITY_AEAD_HSNA,
23997405c8d7SLEROY Christophe 		.alg.aead = {
24007405c8d7SLEROY Christophe 			.base = {
24017405c8d7SLEROY Christophe 				.cra_name = "authenc(hmac(sha1),"
24027405c8d7SLEROY Christophe 					    "cbc(des3_ede))",
24037405c8d7SLEROY Christophe 				.cra_driver_name = "authenc-hmac-sha1-"
2404*a1a42f84SChristophe Leroy 						   "cbc-3des-talitos-hsna",
24057405c8d7SLEROY Christophe 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
24067405c8d7SLEROY Christophe 				.cra_flags = CRYPTO_ALG_ASYNC,
24077405c8d7SLEROY Christophe 			},
24087405c8d7SLEROY Christophe 			.ivsize = DES3_EDE_BLOCK_SIZE,
24097405c8d7SLEROY Christophe 			.maxauthsize = SHA1_DIGEST_SIZE,
2410ef7c5c85SHerbert Xu 			.setkey = aead_des3_setkey,
24117405c8d7SLEROY Christophe 		},
24127405c8d7SLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU |
24137405c8d7SLEROY Christophe 				     DESC_HDR_SEL0_DEU |
24147405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_DEU_CBC |
24157405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_DEU_3DES |
24167405c8d7SLEROY Christophe 				     DESC_HDR_SEL1_MDEUA |
24177405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_INIT |
24187405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_PAD |
24197405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_SHA1_HMAC,
24207405c8d7SLEROY Christophe 	},
24217405c8d7SLEROY Christophe 	{       .type = CRYPTO_ALG_TYPE_AEAD,
2422aeb4c132SHerbert Xu 		.alg.aead = {
2423aeb4c132SHerbert Xu 			.base = {
2424357fb605SHoria Geanta 				.cra_name = "authenc(hmac(sha224),cbc(aes))",
2425aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha224-"
2426aeb4c132SHerbert Xu 						   "cbc-aes-talitos",
2427357fb605SHoria Geanta 				.cra_blocksize = AES_BLOCK_SIZE,
2428aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2429aeb4c132SHerbert Xu 			},
2430357fb605SHoria Geanta 			.ivsize = AES_BLOCK_SIZE,
2431357fb605SHoria Geanta 			.maxauthsize = SHA224_DIGEST_SIZE,
2432357fb605SHoria Geanta 		},
2433357fb605SHoria Geanta 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
2434357fb605SHoria Geanta 				     DESC_HDR_SEL0_AESU |
2435357fb605SHoria Geanta 				     DESC_HDR_MODE0_AESU_CBC |
2436357fb605SHoria Geanta 				     DESC_HDR_SEL1_MDEUA |
2437357fb605SHoria Geanta 				     DESC_HDR_MODE1_MDEU_INIT |
2438357fb605SHoria Geanta 				     DESC_HDR_MODE1_MDEU_PAD |
2439357fb605SHoria Geanta 				     DESC_HDR_MODE1_MDEU_SHA224_HMAC,
2440357fb605SHoria Geanta 	},
2441357fb605SHoria Geanta 	{       .type = CRYPTO_ALG_TYPE_AEAD,
24427405c8d7SLEROY Christophe 		.priority = TALITOS_CRA_PRIORITY_AEAD_HSNA,
24437405c8d7SLEROY Christophe 		.alg.aead = {
24447405c8d7SLEROY Christophe 			.base = {
24457405c8d7SLEROY Christophe 				.cra_name = "authenc(hmac(sha224),cbc(aes))",
24467405c8d7SLEROY Christophe 				.cra_driver_name = "authenc-hmac-sha224-"
2447*a1a42f84SChristophe Leroy 						   "cbc-aes-talitos-hsna",
24487405c8d7SLEROY Christophe 				.cra_blocksize = AES_BLOCK_SIZE,
24497405c8d7SLEROY Christophe 				.cra_flags = CRYPTO_ALG_ASYNC,
24507405c8d7SLEROY Christophe 			},
24517405c8d7SLEROY Christophe 			.ivsize = AES_BLOCK_SIZE,
24527405c8d7SLEROY Christophe 			.maxauthsize = SHA224_DIGEST_SIZE,
24537405c8d7SLEROY Christophe 		},
24547405c8d7SLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU |
24557405c8d7SLEROY Christophe 				     DESC_HDR_SEL0_AESU |
24567405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_AESU_CBC |
24577405c8d7SLEROY Christophe 				     DESC_HDR_SEL1_MDEUA |
24587405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_INIT |
24597405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_PAD |
24607405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_SHA224_HMAC,
24617405c8d7SLEROY Christophe 	},
24627405c8d7SLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2463aeb4c132SHerbert Xu 		.alg.aead = {
2464aeb4c132SHerbert Xu 			.base = {
2465aeb4c132SHerbert Xu 				.cra_name = "authenc(hmac(sha224),"
2466aeb4c132SHerbert Xu 					    "cbc(des3_ede))",
2467aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha224-"
2468aeb4c132SHerbert Xu 						   "cbc-3des-talitos",
2469357fb605SHoria Geanta 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
2470aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2471aeb4c132SHerbert Xu 			},
2472357fb605SHoria Geanta 			.ivsize = DES3_EDE_BLOCK_SIZE,
2473357fb605SHoria Geanta 			.maxauthsize = SHA224_DIGEST_SIZE,
2474ef7c5c85SHerbert Xu 			.setkey = aead_des3_setkey,
2475357fb605SHoria Geanta 		},
2476357fb605SHoria Geanta 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
2477357fb605SHoria Geanta 			             DESC_HDR_SEL0_DEU |
2478357fb605SHoria Geanta 		                     DESC_HDR_MODE0_DEU_CBC |
2479357fb605SHoria Geanta 		                     DESC_HDR_MODE0_DEU_3DES |
2480357fb605SHoria Geanta 		                     DESC_HDR_SEL1_MDEUA |
2481357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_INIT |
2482357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_PAD |
2483357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_SHA224_HMAC,
2484357fb605SHoria Geanta 	},
2485357fb605SHoria Geanta 	{	.type = CRYPTO_ALG_TYPE_AEAD,
24867405c8d7SLEROY Christophe 		.priority = TALITOS_CRA_PRIORITY_AEAD_HSNA,
24877405c8d7SLEROY Christophe 		.alg.aead = {
24887405c8d7SLEROY Christophe 			.base = {
24897405c8d7SLEROY Christophe 				.cra_name = "authenc(hmac(sha224),"
24907405c8d7SLEROY Christophe 					    "cbc(des3_ede))",
24917405c8d7SLEROY Christophe 				.cra_driver_name = "authenc-hmac-sha224-"
2492*a1a42f84SChristophe Leroy 						   "cbc-3des-talitos-hsna",
24937405c8d7SLEROY Christophe 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
24947405c8d7SLEROY Christophe 				.cra_flags = CRYPTO_ALG_ASYNC,
24957405c8d7SLEROY Christophe 			},
24967405c8d7SLEROY Christophe 			.ivsize = DES3_EDE_BLOCK_SIZE,
24977405c8d7SLEROY Christophe 			.maxauthsize = SHA224_DIGEST_SIZE,
2498ef7c5c85SHerbert Xu 			.setkey = aead_des3_setkey,
24997405c8d7SLEROY Christophe 		},
25007405c8d7SLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU |
25017405c8d7SLEROY Christophe 				     DESC_HDR_SEL0_DEU |
25027405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_DEU_CBC |
25037405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_DEU_3DES |
25047405c8d7SLEROY Christophe 				     DESC_HDR_SEL1_MDEUA |
25057405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_INIT |
25067405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_PAD |
25077405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_SHA224_HMAC,
25087405c8d7SLEROY Christophe 	},
25097405c8d7SLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2510aeb4c132SHerbert Xu 		.alg.aead = {
2511aeb4c132SHerbert Xu 			.base = {
251256af8cd4SLee Nipper 				.cra_name = "authenc(hmac(sha256),cbc(aes))",
2513aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha256-"
2514aeb4c132SHerbert Xu 						   "cbc-aes-talitos",
251556af8cd4SLee Nipper 				.cra_blocksize = AES_BLOCK_SIZE,
2516aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2517aeb4c132SHerbert Xu 			},
25183952f17eSLee Nipper 			.ivsize = AES_BLOCK_SIZE,
25193952f17eSLee Nipper 			.maxauthsize = SHA256_DIGEST_SIZE,
25203952f17eSLee Nipper 		},
25213952f17eSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
25223952f17eSLee Nipper 			             DESC_HDR_SEL0_AESU |
25233952f17eSLee Nipper 		                     DESC_HDR_MODE0_AESU_CBC |
25243952f17eSLee Nipper 		                     DESC_HDR_SEL1_MDEUA |
25253952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_INIT |
25263952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_PAD |
25273952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_SHA256_HMAC,
25283952f17eSLee Nipper 	},
2529d5e4aaefSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AEAD,
25307405c8d7SLEROY Christophe 		.priority = TALITOS_CRA_PRIORITY_AEAD_HSNA,
25317405c8d7SLEROY Christophe 		.alg.aead = {
25327405c8d7SLEROY Christophe 			.base = {
25337405c8d7SLEROY Christophe 				.cra_name = "authenc(hmac(sha256),cbc(aes))",
25347405c8d7SLEROY Christophe 				.cra_driver_name = "authenc-hmac-sha256-"
2535*a1a42f84SChristophe Leroy 						   "cbc-aes-talitos-hsna",
25367405c8d7SLEROY Christophe 				.cra_blocksize = AES_BLOCK_SIZE,
25377405c8d7SLEROY Christophe 				.cra_flags = CRYPTO_ALG_ASYNC,
25387405c8d7SLEROY Christophe 			},
25397405c8d7SLEROY Christophe 			.ivsize = AES_BLOCK_SIZE,
25407405c8d7SLEROY Christophe 			.maxauthsize = SHA256_DIGEST_SIZE,
25417405c8d7SLEROY Christophe 		},
25427405c8d7SLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU |
25437405c8d7SLEROY Christophe 				     DESC_HDR_SEL0_AESU |
25447405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_AESU_CBC |
25457405c8d7SLEROY Christophe 				     DESC_HDR_SEL1_MDEUA |
25467405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_INIT |
25477405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_PAD |
25487405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_SHA256_HMAC,
25497405c8d7SLEROY Christophe 	},
25507405c8d7SLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2551aeb4c132SHerbert Xu 		.alg.aead = {
2552aeb4c132SHerbert Xu 			.base = {
2553aeb4c132SHerbert Xu 				.cra_name = "authenc(hmac(sha256),"
2554aeb4c132SHerbert Xu 					    "cbc(des3_ede))",
2555aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha256-"
2556aeb4c132SHerbert Xu 						   "cbc-3des-talitos",
255756af8cd4SLee Nipper 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
2558aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2559aeb4c132SHerbert Xu 			},
25603952f17eSLee Nipper 			.ivsize = DES3_EDE_BLOCK_SIZE,
25613952f17eSLee Nipper 			.maxauthsize = SHA256_DIGEST_SIZE,
2562ef7c5c85SHerbert Xu 			.setkey = aead_des3_setkey,
25633952f17eSLee Nipper 		},
25643952f17eSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
25653952f17eSLee Nipper 			             DESC_HDR_SEL0_DEU |
25663952f17eSLee Nipper 		                     DESC_HDR_MODE0_DEU_CBC |
25673952f17eSLee Nipper 		                     DESC_HDR_MODE0_DEU_3DES |
25683952f17eSLee Nipper 		                     DESC_HDR_SEL1_MDEUA |
25693952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_INIT |
25703952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_PAD |
25713952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_SHA256_HMAC,
25723952f17eSLee Nipper 	},
2573d5e4aaefSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AEAD,
25747405c8d7SLEROY Christophe 		.priority = TALITOS_CRA_PRIORITY_AEAD_HSNA,
25757405c8d7SLEROY Christophe 		.alg.aead = {
25767405c8d7SLEROY Christophe 			.base = {
25777405c8d7SLEROY Christophe 				.cra_name = "authenc(hmac(sha256),"
25787405c8d7SLEROY Christophe 					    "cbc(des3_ede))",
25797405c8d7SLEROY Christophe 				.cra_driver_name = "authenc-hmac-sha256-"
2580*a1a42f84SChristophe Leroy 						   "cbc-3des-talitos-hsna",
25817405c8d7SLEROY Christophe 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
25827405c8d7SLEROY Christophe 				.cra_flags = CRYPTO_ALG_ASYNC,
25837405c8d7SLEROY Christophe 			},
25847405c8d7SLEROY Christophe 			.ivsize = DES3_EDE_BLOCK_SIZE,
25857405c8d7SLEROY Christophe 			.maxauthsize = SHA256_DIGEST_SIZE,
2586ef7c5c85SHerbert Xu 			.setkey = aead_des3_setkey,
25877405c8d7SLEROY Christophe 		},
25887405c8d7SLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU |
25897405c8d7SLEROY Christophe 				     DESC_HDR_SEL0_DEU |
25907405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_DEU_CBC |
25917405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_DEU_3DES |
25927405c8d7SLEROY Christophe 				     DESC_HDR_SEL1_MDEUA |
25937405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_INIT |
25947405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_PAD |
25957405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_SHA256_HMAC,
25967405c8d7SLEROY Christophe 	},
25977405c8d7SLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2598aeb4c132SHerbert Xu 		.alg.aead = {
2599aeb4c132SHerbert Xu 			.base = {
2600357fb605SHoria Geanta 				.cra_name = "authenc(hmac(sha384),cbc(aes))",
2601aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha384-"
2602aeb4c132SHerbert Xu 						   "cbc-aes-talitos",
2603357fb605SHoria Geanta 				.cra_blocksize = AES_BLOCK_SIZE,
2604aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2605aeb4c132SHerbert Xu 			},
2606357fb605SHoria Geanta 			.ivsize = AES_BLOCK_SIZE,
2607357fb605SHoria Geanta 			.maxauthsize = SHA384_DIGEST_SIZE,
2608357fb605SHoria Geanta 		},
2609357fb605SHoria Geanta 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
2610357fb605SHoria Geanta 			             DESC_HDR_SEL0_AESU |
2611357fb605SHoria Geanta 		                     DESC_HDR_MODE0_AESU_CBC |
2612357fb605SHoria Geanta 		                     DESC_HDR_SEL1_MDEUB |
2613357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_INIT |
2614357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_PAD |
2615357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEUB_SHA384_HMAC,
2616357fb605SHoria Geanta 	},
2617357fb605SHoria Geanta 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2618aeb4c132SHerbert Xu 		.alg.aead = {
2619aeb4c132SHerbert Xu 			.base = {
2620aeb4c132SHerbert Xu 				.cra_name = "authenc(hmac(sha384),"
2621aeb4c132SHerbert Xu 					    "cbc(des3_ede))",
2622aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha384-"
2623aeb4c132SHerbert Xu 						   "cbc-3des-talitos",
2624357fb605SHoria Geanta 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
2625aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2626aeb4c132SHerbert Xu 			},
2627357fb605SHoria Geanta 			.ivsize = DES3_EDE_BLOCK_SIZE,
2628357fb605SHoria Geanta 			.maxauthsize = SHA384_DIGEST_SIZE,
2629ef7c5c85SHerbert Xu 			.setkey = aead_des3_setkey,
2630357fb605SHoria Geanta 		},
2631357fb605SHoria Geanta 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
2632357fb605SHoria Geanta 			             DESC_HDR_SEL0_DEU |
2633357fb605SHoria Geanta 		                     DESC_HDR_MODE0_DEU_CBC |
2634357fb605SHoria Geanta 		                     DESC_HDR_MODE0_DEU_3DES |
2635357fb605SHoria Geanta 		                     DESC_HDR_SEL1_MDEUB |
2636357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_INIT |
2637357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_PAD |
2638357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEUB_SHA384_HMAC,
2639357fb605SHoria Geanta 	},
2640357fb605SHoria Geanta 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2641aeb4c132SHerbert Xu 		.alg.aead = {
2642aeb4c132SHerbert Xu 			.base = {
2643357fb605SHoria Geanta 				.cra_name = "authenc(hmac(sha512),cbc(aes))",
2644aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha512-"
2645aeb4c132SHerbert Xu 						   "cbc-aes-talitos",
2646357fb605SHoria Geanta 				.cra_blocksize = AES_BLOCK_SIZE,
2647aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2648aeb4c132SHerbert Xu 			},
2649357fb605SHoria Geanta 			.ivsize = AES_BLOCK_SIZE,
2650357fb605SHoria Geanta 			.maxauthsize = SHA512_DIGEST_SIZE,
2651357fb605SHoria Geanta 		},
2652357fb605SHoria Geanta 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
2653357fb605SHoria Geanta 			             DESC_HDR_SEL0_AESU |
2654357fb605SHoria Geanta 		                     DESC_HDR_MODE0_AESU_CBC |
2655357fb605SHoria Geanta 		                     DESC_HDR_SEL1_MDEUB |
2656357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_INIT |
2657357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_PAD |
2658357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEUB_SHA512_HMAC,
2659357fb605SHoria Geanta 	},
2660357fb605SHoria Geanta 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2661aeb4c132SHerbert Xu 		.alg.aead = {
2662aeb4c132SHerbert Xu 			.base = {
2663aeb4c132SHerbert Xu 				.cra_name = "authenc(hmac(sha512),"
2664aeb4c132SHerbert Xu 					    "cbc(des3_ede))",
2665aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha512-"
2666aeb4c132SHerbert Xu 						   "cbc-3des-talitos",
2667357fb605SHoria Geanta 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
2668aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2669aeb4c132SHerbert Xu 			},
2670357fb605SHoria Geanta 			.ivsize = DES3_EDE_BLOCK_SIZE,
2671357fb605SHoria Geanta 			.maxauthsize = SHA512_DIGEST_SIZE,
2672ef7c5c85SHerbert Xu 			.setkey = aead_des3_setkey,
2673357fb605SHoria Geanta 		},
2674357fb605SHoria Geanta 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
2675357fb605SHoria Geanta 			             DESC_HDR_SEL0_DEU |
2676357fb605SHoria Geanta 		                     DESC_HDR_MODE0_DEU_CBC |
2677357fb605SHoria Geanta 		                     DESC_HDR_MODE0_DEU_3DES |
2678357fb605SHoria Geanta 		                     DESC_HDR_SEL1_MDEUB |
2679357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_INIT |
2680357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_PAD |
2681357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEUB_SHA512_HMAC,
2682357fb605SHoria Geanta 	},
2683357fb605SHoria Geanta 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2684aeb4c132SHerbert Xu 		.alg.aead = {
2685aeb4c132SHerbert Xu 			.base = {
268656af8cd4SLee Nipper 				.cra_name = "authenc(hmac(md5),cbc(aes))",
2687aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-md5-"
2688aeb4c132SHerbert Xu 						   "cbc-aes-talitos",
268956af8cd4SLee Nipper 				.cra_blocksize = AES_BLOCK_SIZE,
2690aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2691aeb4c132SHerbert Xu 			},
26923952f17eSLee Nipper 			.ivsize = AES_BLOCK_SIZE,
26933952f17eSLee Nipper 			.maxauthsize = MD5_DIGEST_SIZE,
26943952f17eSLee Nipper 		},
26953952f17eSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
26963952f17eSLee Nipper 			             DESC_HDR_SEL0_AESU |
26973952f17eSLee Nipper 		                     DESC_HDR_MODE0_AESU_CBC |
26983952f17eSLee Nipper 		                     DESC_HDR_SEL1_MDEUA |
26993952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_INIT |
27003952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_PAD |
27013952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_MD5_HMAC,
27023952f17eSLee Nipper 	},
2703d5e4aaefSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AEAD,
27047405c8d7SLEROY Christophe 		.priority = TALITOS_CRA_PRIORITY_AEAD_HSNA,
27057405c8d7SLEROY Christophe 		.alg.aead = {
27067405c8d7SLEROY Christophe 			.base = {
27077405c8d7SLEROY Christophe 				.cra_name = "authenc(hmac(md5),cbc(aes))",
27087405c8d7SLEROY Christophe 				.cra_driver_name = "authenc-hmac-md5-"
2709*a1a42f84SChristophe Leroy 						   "cbc-aes-talitos-hsna",
27107405c8d7SLEROY Christophe 				.cra_blocksize = AES_BLOCK_SIZE,
27117405c8d7SLEROY Christophe 				.cra_flags = CRYPTO_ALG_ASYNC,
27127405c8d7SLEROY Christophe 			},
27137405c8d7SLEROY Christophe 			.ivsize = AES_BLOCK_SIZE,
27147405c8d7SLEROY Christophe 			.maxauthsize = MD5_DIGEST_SIZE,
27157405c8d7SLEROY Christophe 		},
27167405c8d7SLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU |
27177405c8d7SLEROY Christophe 				     DESC_HDR_SEL0_AESU |
27187405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_AESU_CBC |
27197405c8d7SLEROY Christophe 				     DESC_HDR_SEL1_MDEUA |
27207405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_INIT |
27217405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_PAD |
27227405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_MD5_HMAC,
27237405c8d7SLEROY Christophe 	},
27247405c8d7SLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2725aeb4c132SHerbert Xu 		.alg.aead = {
2726aeb4c132SHerbert Xu 			.base = {
272756af8cd4SLee Nipper 				.cra_name = "authenc(hmac(md5),cbc(des3_ede))",
2728aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-md5-"
2729aeb4c132SHerbert Xu 						   "cbc-3des-talitos",
273056af8cd4SLee Nipper 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
2731aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2732aeb4c132SHerbert Xu 			},
27333952f17eSLee Nipper 			.ivsize = DES3_EDE_BLOCK_SIZE,
27343952f17eSLee Nipper 			.maxauthsize = MD5_DIGEST_SIZE,
2735ef7c5c85SHerbert Xu 			.setkey = aead_des3_setkey,
27363952f17eSLee Nipper 		},
27373952f17eSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
27383952f17eSLee Nipper 			             DESC_HDR_SEL0_DEU |
27393952f17eSLee Nipper 		                     DESC_HDR_MODE0_DEU_CBC |
27403952f17eSLee Nipper 		                     DESC_HDR_MODE0_DEU_3DES |
27413952f17eSLee Nipper 		                     DESC_HDR_SEL1_MDEUA |
27423952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_INIT |
27433952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_PAD |
27443952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_MD5_HMAC,
27454de9d0b5SLee Nipper 	},
27467405c8d7SLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_AEAD,
27477405c8d7SLEROY Christophe 		.priority = TALITOS_CRA_PRIORITY_AEAD_HSNA,
27487405c8d7SLEROY Christophe 		.alg.aead = {
27497405c8d7SLEROY Christophe 			.base = {
27507405c8d7SLEROY Christophe 				.cra_name = "authenc(hmac(md5),cbc(des3_ede))",
27517405c8d7SLEROY Christophe 				.cra_driver_name = "authenc-hmac-md5-"
2752*a1a42f84SChristophe Leroy 						   "cbc-3des-talitos-hsna",
27537405c8d7SLEROY Christophe 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
27547405c8d7SLEROY Christophe 				.cra_flags = CRYPTO_ALG_ASYNC,
27557405c8d7SLEROY Christophe 			},
27567405c8d7SLEROY Christophe 			.ivsize = DES3_EDE_BLOCK_SIZE,
27577405c8d7SLEROY Christophe 			.maxauthsize = MD5_DIGEST_SIZE,
2758ef7c5c85SHerbert Xu 			.setkey = aead_des3_setkey,
27597405c8d7SLEROY Christophe 		},
27607405c8d7SLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU |
27617405c8d7SLEROY Christophe 				     DESC_HDR_SEL0_DEU |
27627405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_DEU_CBC |
27637405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_DEU_3DES |
27647405c8d7SLEROY Christophe 				     DESC_HDR_SEL1_MDEUA |
27657405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_INIT |
27667405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_PAD |
27677405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_MD5_HMAC,
27687405c8d7SLEROY Christophe 	},
27694de9d0b5SLee Nipper 	/* ABLKCIPHER algorithms. */
2770d5e4aaefSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_ABLKCIPHER,
2771d5e4aaefSLee Nipper 		.alg.crypto = {
27725e75ae1bSLEROY Christophe 			.cra_name = "ecb(aes)",
27735e75ae1bSLEROY Christophe 			.cra_driver_name = "ecb-aes-talitos",
27745e75ae1bSLEROY Christophe 			.cra_blocksize = AES_BLOCK_SIZE,
27755e75ae1bSLEROY Christophe 			.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
27765e75ae1bSLEROY Christophe 				     CRYPTO_ALG_ASYNC,
27775e75ae1bSLEROY Christophe 			.cra_ablkcipher = {
27785e75ae1bSLEROY Christophe 				.min_keysize = AES_MIN_KEY_SIZE,
27795e75ae1bSLEROY Christophe 				.max_keysize = AES_MAX_KEY_SIZE,
27805e75ae1bSLEROY Christophe 				.ivsize = AES_BLOCK_SIZE,
27815e75ae1bSLEROY Christophe 			}
27825e75ae1bSLEROY Christophe 		},
27835e75ae1bSLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
27845e75ae1bSLEROY Christophe 				     DESC_HDR_SEL0_AESU,
27855e75ae1bSLEROY Christophe 	},
27865e75ae1bSLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_ABLKCIPHER,
27875e75ae1bSLEROY Christophe 		.alg.crypto = {
27884de9d0b5SLee Nipper 			.cra_name = "cbc(aes)",
27894de9d0b5SLee Nipper 			.cra_driver_name = "cbc-aes-talitos",
27904de9d0b5SLee Nipper 			.cra_blocksize = AES_BLOCK_SIZE,
27914de9d0b5SLee Nipper 			.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
27924de9d0b5SLee Nipper                                      CRYPTO_ALG_ASYNC,
27934de9d0b5SLee Nipper 			.cra_ablkcipher = {
27944de9d0b5SLee Nipper 				.min_keysize = AES_MIN_KEY_SIZE,
27954de9d0b5SLee Nipper 				.max_keysize = AES_MAX_KEY_SIZE,
27964de9d0b5SLee Nipper 				.ivsize = AES_BLOCK_SIZE,
27974de9d0b5SLee Nipper 			}
27984de9d0b5SLee Nipper 		},
27994de9d0b5SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
28004de9d0b5SLee Nipper 				     DESC_HDR_SEL0_AESU |
28014de9d0b5SLee Nipper 				     DESC_HDR_MODE0_AESU_CBC,
28024de9d0b5SLee Nipper 	},
2803d5e4aaefSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_ABLKCIPHER,
2804d5e4aaefSLee Nipper 		.alg.crypto = {
28055e75ae1bSLEROY Christophe 			.cra_name = "ctr(aes)",
28065e75ae1bSLEROY Christophe 			.cra_driver_name = "ctr-aes-talitos",
28075e75ae1bSLEROY Christophe 			.cra_blocksize = AES_BLOCK_SIZE,
28085e75ae1bSLEROY Christophe 			.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
28095e75ae1bSLEROY Christophe 				     CRYPTO_ALG_ASYNC,
28105e75ae1bSLEROY Christophe 			.cra_ablkcipher = {
28115e75ae1bSLEROY Christophe 				.min_keysize = AES_MIN_KEY_SIZE,
28125e75ae1bSLEROY Christophe 				.max_keysize = AES_MAX_KEY_SIZE,
28135e75ae1bSLEROY Christophe 				.ivsize = AES_BLOCK_SIZE,
28145e75ae1bSLEROY Christophe 			}
28155e75ae1bSLEROY Christophe 		},
281670d355ccSLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_AESU_CTR_NONSNOOP |
28175e75ae1bSLEROY Christophe 				     DESC_HDR_SEL0_AESU |
28185e75ae1bSLEROY Christophe 				     DESC_HDR_MODE0_AESU_CTR,
28195e75ae1bSLEROY Christophe 	},
28205e75ae1bSLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_ABLKCIPHER,
28215e75ae1bSLEROY Christophe 		.alg.crypto = {
28225e75ae1bSLEROY Christophe 			.cra_name = "ecb(des)",
28235e75ae1bSLEROY Christophe 			.cra_driver_name = "ecb-des-talitos",
28245e75ae1bSLEROY Christophe 			.cra_blocksize = DES_BLOCK_SIZE,
28255e75ae1bSLEROY Christophe 			.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
28265e75ae1bSLEROY Christophe 				     CRYPTO_ALG_ASYNC,
28275e75ae1bSLEROY Christophe 			.cra_ablkcipher = {
28285e75ae1bSLEROY Christophe 				.min_keysize = DES_KEY_SIZE,
28295e75ae1bSLEROY Christophe 				.max_keysize = DES_KEY_SIZE,
28305e75ae1bSLEROY Christophe 				.ivsize = DES_BLOCK_SIZE,
2831ef7c5c85SHerbert Xu 				.setkey = ablkcipher_des_setkey,
28325e75ae1bSLEROY Christophe 			}
28335e75ae1bSLEROY Christophe 		},
28345e75ae1bSLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
28355e75ae1bSLEROY Christophe 				     DESC_HDR_SEL0_DEU,
28365e75ae1bSLEROY Christophe 	},
28375e75ae1bSLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_ABLKCIPHER,
28385e75ae1bSLEROY Christophe 		.alg.crypto = {
28395e75ae1bSLEROY Christophe 			.cra_name = "cbc(des)",
28405e75ae1bSLEROY Christophe 			.cra_driver_name = "cbc-des-talitos",
28415e75ae1bSLEROY Christophe 			.cra_blocksize = DES_BLOCK_SIZE,
28425e75ae1bSLEROY Christophe 			.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
28435e75ae1bSLEROY Christophe 				     CRYPTO_ALG_ASYNC,
28445e75ae1bSLEROY Christophe 			.cra_ablkcipher = {
28455e75ae1bSLEROY Christophe 				.min_keysize = DES_KEY_SIZE,
28465e75ae1bSLEROY Christophe 				.max_keysize = DES_KEY_SIZE,
28475e75ae1bSLEROY Christophe 				.ivsize = DES_BLOCK_SIZE,
2848ef7c5c85SHerbert Xu 				.setkey = ablkcipher_des_setkey,
28495e75ae1bSLEROY Christophe 			}
28505e75ae1bSLEROY Christophe 		},
28515e75ae1bSLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
28525e75ae1bSLEROY Christophe 				     DESC_HDR_SEL0_DEU |
28535e75ae1bSLEROY Christophe 				     DESC_HDR_MODE0_DEU_CBC,
28545e75ae1bSLEROY Christophe 	},
28555e75ae1bSLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_ABLKCIPHER,
28565e75ae1bSLEROY Christophe 		.alg.crypto = {
28575e75ae1bSLEROY Christophe 			.cra_name = "ecb(des3_ede)",
28585e75ae1bSLEROY Christophe 			.cra_driver_name = "ecb-3des-talitos",
28595e75ae1bSLEROY Christophe 			.cra_blocksize = DES3_EDE_BLOCK_SIZE,
28605e75ae1bSLEROY Christophe 			.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
28615e75ae1bSLEROY Christophe 				     CRYPTO_ALG_ASYNC,
28625e75ae1bSLEROY Christophe 			.cra_ablkcipher = {
28635e75ae1bSLEROY Christophe 				.min_keysize = DES3_EDE_KEY_SIZE,
28645e75ae1bSLEROY Christophe 				.max_keysize = DES3_EDE_KEY_SIZE,
28655e75ae1bSLEROY Christophe 				.ivsize = DES3_EDE_BLOCK_SIZE,
2866ef7c5c85SHerbert Xu 				.setkey = ablkcipher_des3_setkey,
28675e75ae1bSLEROY Christophe 			}
28685e75ae1bSLEROY Christophe 		},
28695e75ae1bSLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
28705e75ae1bSLEROY Christophe 				     DESC_HDR_SEL0_DEU |
28715e75ae1bSLEROY Christophe 				     DESC_HDR_MODE0_DEU_3DES,
28725e75ae1bSLEROY Christophe 	},
28735e75ae1bSLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_ABLKCIPHER,
28745e75ae1bSLEROY Christophe 		.alg.crypto = {
28754de9d0b5SLee Nipper 			.cra_name = "cbc(des3_ede)",
28764de9d0b5SLee Nipper 			.cra_driver_name = "cbc-3des-talitos",
28774de9d0b5SLee Nipper 			.cra_blocksize = DES3_EDE_BLOCK_SIZE,
28784de9d0b5SLee Nipper 			.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
28794de9d0b5SLee Nipper                                      CRYPTO_ALG_ASYNC,
28804de9d0b5SLee Nipper 			.cra_ablkcipher = {
28814de9d0b5SLee Nipper 				.min_keysize = DES3_EDE_KEY_SIZE,
28824de9d0b5SLee Nipper 				.max_keysize = DES3_EDE_KEY_SIZE,
28834de9d0b5SLee Nipper 				.ivsize = DES3_EDE_BLOCK_SIZE,
2884ef7c5c85SHerbert Xu 				.setkey = ablkcipher_des3_setkey,
28854de9d0b5SLee Nipper 			}
28864de9d0b5SLee Nipper 		},
28874de9d0b5SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
28884de9d0b5SLee Nipper 			             DESC_HDR_SEL0_DEU |
28894de9d0b5SLee Nipper 		                     DESC_HDR_MODE0_DEU_CBC |
28904de9d0b5SLee Nipper 		                     DESC_HDR_MODE0_DEU_3DES,
2891497f2e6bSLee Nipper 	},
2892497f2e6bSLee Nipper 	/* AHASH algorithms. */
2893497f2e6bSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
2894497f2e6bSLee Nipper 		.alg.hash = {
2895497f2e6bSLee Nipper 			.halg.digestsize = MD5_DIGEST_SIZE,
28963639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
2897497f2e6bSLee Nipper 			.halg.base = {
2898497f2e6bSLee Nipper 				.cra_name = "md5",
2899497f2e6bSLee Nipper 				.cra_driver_name = "md5-talitos",
2900b3988618SMartin Hicks 				.cra_blocksize = MD5_HMAC_BLOCK_SIZE,
29016a38f622SEric Biggers 				.cra_flags = CRYPTO_ALG_ASYNC,
29029c4a7965SKim Phillips 			}
2903497f2e6bSLee Nipper 		},
2904497f2e6bSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
2905497f2e6bSLee Nipper 				     DESC_HDR_SEL0_MDEUA |
2906497f2e6bSLee Nipper 				     DESC_HDR_MODE0_MDEU_MD5,
2907497f2e6bSLee Nipper 	},
2908497f2e6bSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
2909497f2e6bSLee Nipper 		.alg.hash = {
2910497f2e6bSLee Nipper 			.halg.digestsize = SHA1_DIGEST_SIZE,
29113639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
2912497f2e6bSLee Nipper 			.halg.base = {
2913497f2e6bSLee Nipper 				.cra_name = "sha1",
2914497f2e6bSLee Nipper 				.cra_driver_name = "sha1-talitos",
2915497f2e6bSLee Nipper 				.cra_blocksize = SHA1_BLOCK_SIZE,
29166a38f622SEric Biggers 				.cra_flags = CRYPTO_ALG_ASYNC,
2917497f2e6bSLee Nipper 			}
2918497f2e6bSLee Nipper 		},
2919497f2e6bSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
2920497f2e6bSLee Nipper 				     DESC_HDR_SEL0_MDEUA |
2921497f2e6bSLee Nipper 				     DESC_HDR_MODE0_MDEU_SHA1,
2922497f2e6bSLee Nipper 	},
2923497f2e6bSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
2924497f2e6bSLee Nipper 		.alg.hash = {
292560f208d7SKim Phillips 			.halg.digestsize = SHA224_DIGEST_SIZE,
29263639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
292760f208d7SKim Phillips 			.halg.base = {
292860f208d7SKim Phillips 				.cra_name = "sha224",
292960f208d7SKim Phillips 				.cra_driver_name = "sha224-talitos",
293060f208d7SKim Phillips 				.cra_blocksize = SHA224_BLOCK_SIZE,
29316a38f622SEric Biggers 				.cra_flags = CRYPTO_ALG_ASYNC,
293260f208d7SKim Phillips 			}
293360f208d7SKim Phillips 		},
293460f208d7SKim Phillips 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
293560f208d7SKim Phillips 				     DESC_HDR_SEL0_MDEUA |
293660f208d7SKim Phillips 				     DESC_HDR_MODE0_MDEU_SHA224,
293760f208d7SKim Phillips 	},
293860f208d7SKim Phillips 	{	.type = CRYPTO_ALG_TYPE_AHASH,
293960f208d7SKim Phillips 		.alg.hash = {
2940497f2e6bSLee Nipper 			.halg.digestsize = SHA256_DIGEST_SIZE,
29413639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
2942497f2e6bSLee Nipper 			.halg.base = {
2943497f2e6bSLee Nipper 				.cra_name = "sha256",
2944497f2e6bSLee Nipper 				.cra_driver_name = "sha256-talitos",
2945497f2e6bSLee Nipper 				.cra_blocksize = SHA256_BLOCK_SIZE,
29466a38f622SEric Biggers 				.cra_flags = CRYPTO_ALG_ASYNC,
2947497f2e6bSLee Nipper 			}
2948497f2e6bSLee Nipper 		},
2949497f2e6bSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
2950497f2e6bSLee Nipper 				     DESC_HDR_SEL0_MDEUA |
2951497f2e6bSLee Nipper 				     DESC_HDR_MODE0_MDEU_SHA256,
2952497f2e6bSLee Nipper 	},
2953497f2e6bSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
2954497f2e6bSLee Nipper 		.alg.hash = {
2955497f2e6bSLee Nipper 			.halg.digestsize = SHA384_DIGEST_SIZE,
29563639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
2957497f2e6bSLee Nipper 			.halg.base = {
2958497f2e6bSLee Nipper 				.cra_name = "sha384",
2959497f2e6bSLee Nipper 				.cra_driver_name = "sha384-talitos",
2960497f2e6bSLee Nipper 				.cra_blocksize = SHA384_BLOCK_SIZE,
29616a38f622SEric Biggers 				.cra_flags = CRYPTO_ALG_ASYNC,
2962497f2e6bSLee Nipper 			}
2963497f2e6bSLee Nipper 		},
2964497f2e6bSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
2965497f2e6bSLee Nipper 				     DESC_HDR_SEL0_MDEUB |
2966497f2e6bSLee Nipper 				     DESC_HDR_MODE0_MDEUB_SHA384,
2967497f2e6bSLee Nipper 	},
2968497f2e6bSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
2969497f2e6bSLee Nipper 		.alg.hash = {
2970497f2e6bSLee Nipper 			.halg.digestsize = SHA512_DIGEST_SIZE,
29713639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
2972497f2e6bSLee Nipper 			.halg.base = {
2973497f2e6bSLee Nipper 				.cra_name = "sha512",
2974497f2e6bSLee Nipper 				.cra_driver_name = "sha512-talitos",
2975497f2e6bSLee Nipper 				.cra_blocksize = SHA512_BLOCK_SIZE,
29766a38f622SEric Biggers 				.cra_flags = CRYPTO_ALG_ASYNC,
2977497f2e6bSLee Nipper 			}
2978497f2e6bSLee Nipper 		},
2979497f2e6bSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
2980497f2e6bSLee Nipper 				     DESC_HDR_SEL0_MDEUB |
2981497f2e6bSLee Nipper 				     DESC_HDR_MODE0_MDEUB_SHA512,
2982497f2e6bSLee Nipper 	},
298379b3a418SLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
298479b3a418SLee Nipper 		.alg.hash = {
298579b3a418SLee Nipper 			.halg.digestsize = MD5_DIGEST_SIZE,
29863639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
298779b3a418SLee Nipper 			.halg.base = {
298879b3a418SLee Nipper 				.cra_name = "hmac(md5)",
298979b3a418SLee Nipper 				.cra_driver_name = "hmac-md5-talitos",
2990b3988618SMartin Hicks 				.cra_blocksize = MD5_HMAC_BLOCK_SIZE,
29916a38f622SEric Biggers 				.cra_flags = CRYPTO_ALG_ASYNC,
299279b3a418SLee Nipper 			}
299379b3a418SLee Nipper 		},
299479b3a418SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
299579b3a418SLee Nipper 				     DESC_HDR_SEL0_MDEUA |
299679b3a418SLee Nipper 				     DESC_HDR_MODE0_MDEU_MD5,
299779b3a418SLee Nipper 	},
299879b3a418SLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
299979b3a418SLee Nipper 		.alg.hash = {
300079b3a418SLee Nipper 			.halg.digestsize = SHA1_DIGEST_SIZE,
30013639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
300279b3a418SLee Nipper 			.halg.base = {
300379b3a418SLee Nipper 				.cra_name = "hmac(sha1)",
300479b3a418SLee Nipper 				.cra_driver_name = "hmac-sha1-talitos",
300579b3a418SLee Nipper 				.cra_blocksize = SHA1_BLOCK_SIZE,
30066a38f622SEric Biggers 				.cra_flags = CRYPTO_ALG_ASYNC,
300779b3a418SLee Nipper 			}
300879b3a418SLee Nipper 		},
300979b3a418SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
301079b3a418SLee Nipper 				     DESC_HDR_SEL0_MDEUA |
301179b3a418SLee Nipper 				     DESC_HDR_MODE0_MDEU_SHA1,
301279b3a418SLee Nipper 	},
301379b3a418SLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
301479b3a418SLee Nipper 		.alg.hash = {
301579b3a418SLee Nipper 			.halg.digestsize = SHA224_DIGEST_SIZE,
30163639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
301779b3a418SLee Nipper 			.halg.base = {
301879b3a418SLee Nipper 				.cra_name = "hmac(sha224)",
301979b3a418SLee Nipper 				.cra_driver_name = "hmac-sha224-talitos",
302079b3a418SLee Nipper 				.cra_blocksize = SHA224_BLOCK_SIZE,
30216a38f622SEric Biggers 				.cra_flags = CRYPTO_ALG_ASYNC,
302279b3a418SLee Nipper 			}
302379b3a418SLee Nipper 		},
302479b3a418SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
302579b3a418SLee Nipper 				     DESC_HDR_SEL0_MDEUA |
302679b3a418SLee Nipper 				     DESC_HDR_MODE0_MDEU_SHA224,
302779b3a418SLee Nipper 	},
302879b3a418SLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
302979b3a418SLee Nipper 		.alg.hash = {
303079b3a418SLee Nipper 			.halg.digestsize = SHA256_DIGEST_SIZE,
30313639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
303279b3a418SLee Nipper 			.halg.base = {
303379b3a418SLee Nipper 				.cra_name = "hmac(sha256)",
303479b3a418SLee Nipper 				.cra_driver_name = "hmac-sha256-talitos",
303579b3a418SLee Nipper 				.cra_blocksize = SHA256_BLOCK_SIZE,
30366a38f622SEric Biggers 				.cra_flags = CRYPTO_ALG_ASYNC,
303779b3a418SLee Nipper 			}
303879b3a418SLee Nipper 		},
303979b3a418SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
304079b3a418SLee Nipper 				     DESC_HDR_SEL0_MDEUA |
304179b3a418SLee Nipper 				     DESC_HDR_MODE0_MDEU_SHA256,
304279b3a418SLee Nipper 	},
304379b3a418SLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
304479b3a418SLee Nipper 		.alg.hash = {
304579b3a418SLee Nipper 			.halg.digestsize = SHA384_DIGEST_SIZE,
30463639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
304779b3a418SLee Nipper 			.halg.base = {
304879b3a418SLee Nipper 				.cra_name = "hmac(sha384)",
304979b3a418SLee Nipper 				.cra_driver_name = "hmac-sha384-talitos",
305079b3a418SLee Nipper 				.cra_blocksize = SHA384_BLOCK_SIZE,
30516a38f622SEric Biggers 				.cra_flags = CRYPTO_ALG_ASYNC,
305279b3a418SLee Nipper 			}
305379b3a418SLee Nipper 		},
305479b3a418SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
305579b3a418SLee Nipper 				     DESC_HDR_SEL0_MDEUB |
305679b3a418SLee Nipper 				     DESC_HDR_MODE0_MDEUB_SHA384,
305779b3a418SLee Nipper 	},
305879b3a418SLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
305979b3a418SLee Nipper 		.alg.hash = {
306079b3a418SLee Nipper 			.halg.digestsize = SHA512_DIGEST_SIZE,
30613639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
306279b3a418SLee Nipper 			.halg.base = {
306379b3a418SLee Nipper 				.cra_name = "hmac(sha512)",
306479b3a418SLee Nipper 				.cra_driver_name = "hmac-sha512-talitos",
306579b3a418SLee Nipper 				.cra_blocksize = SHA512_BLOCK_SIZE,
30666a38f622SEric Biggers 				.cra_flags = CRYPTO_ALG_ASYNC,
306779b3a418SLee Nipper 			}
306879b3a418SLee Nipper 		},
306979b3a418SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
307079b3a418SLee Nipper 				     DESC_HDR_SEL0_MDEUB |
307179b3a418SLee Nipper 				     DESC_HDR_MODE0_MDEUB_SHA512,
307279b3a418SLee Nipper 	}
30739c4a7965SKim Phillips };
30749c4a7965SKim Phillips 
30759c4a7965SKim Phillips struct talitos_crypto_alg {
30769c4a7965SKim Phillips 	struct list_head entry;
30779c4a7965SKim Phillips 	struct device *dev;
3078acbf7c62SLee Nipper 	struct talitos_alg_template algt;
30799c4a7965SKim Phillips };
30809c4a7965SKim Phillips 
308189d124cbSJonas Eymann static int talitos_init_common(struct talitos_ctx *ctx,
308289d124cbSJonas Eymann 			       struct talitos_crypto_alg *talitos_alg)
30839c4a7965SKim Phillips {
30845228f0f7SKim Phillips 	struct talitos_private *priv;
30859c4a7965SKim Phillips 
30869c4a7965SKim Phillips 	/* update context with ptr to dev */
30879c4a7965SKim Phillips 	ctx->dev = talitos_alg->dev;
308819bbbc63SKim Phillips 
30895228f0f7SKim Phillips 	/* assign SEC channel to tfm in round-robin fashion */
30905228f0f7SKim Phillips 	priv = dev_get_drvdata(ctx->dev);
30915228f0f7SKim Phillips 	ctx->ch = atomic_inc_return(&priv->last_chan) &
30925228f0f7SKim Phillips 		  (priv->num_channels - 1);
30935228f0f7SKim Phillips 
30949c4a7965SKim Phillips 	/* copy descriptor header template value */
3095acbf7c62SLee Nipper 	ctx->desc_hdr_template = talitos_alg->algt.desc_hdr_template;
30969c4a7965SKim Phillips 
3097602dba5aSKim Phillips 	/* select done notification */
3098602dba5aSKim Phillips 	ctx->desc_hdr_template |= DESC_HDR_DONE_NOTIFY;
3099602dba5aSKim Phillips 
3100497f2e6bSLee Nipper 	return 0;
3101497f2e6bSLee Nipper }
3102497f2e6bSLee Nipper 
310389d124cbSJonas Eymann static int talitos_cra_init(struct crypto_tfm *tfm)
310489d124cbSJonas Eymann {
310589d124cbSJonas Eymann 	struct crypto_alg *alg = tfm->__crt_alg;
310689d124cbSJonas Eymann 	struct talitos_crypto_alg *talitos_alg;
310789d124cbSJonas Eymann 	struct talitos_ctx *ctx = crypto_tfm_ctx(tfm);
310889d124cbSJonas Eymann 
310989d124cbSJonas Eymann 	if ((alg->cra_flags & CRYPTO_ALG_TYPE_MASK) == CRYPTO_ALG_TYPE_AHASH)
311089d124cbSJonas Eymann 		talitos_alg = container_of(__crypto_ahash_alg(alg),
311189d124cbSJonas Eymann 					   struct talitos_crypto_alg,
311289d124cbSJonas Eymann 					   algt.alg.hash);
311389d124cbSJonas Eymann 	else
311489d124cbSJonas Eymann 		talitos_alg = container_of(alg, struct talitos_crypto_alg,
311589d124cbSJonas Eymann 					   algt.alg.crypto);
311689d124cbSJonas Eymann 
311789d124cbSJonas Eymann 	return talitos_init_common(ctx, talitos_alg);
311889d124cbSJonas Eymann }
311989d124cbSJonas Eymann 
3120aeb4c132SHerbert Xu static int talitos_cra_init_aead(struct crypto_aead *tfm)
3121497f2e6bSLee Nipper {
312289d124cbSJonas Eymann 	struct aead_alg *alg = crypto_aead_alg(tfm);
312389d124cbSJonas Eymann 	struct talitos_crypto_alg *talitos_alg;
312489d124cbSJonas Eymann 	struct talitos_ctx *ctx = crypto_aead_ctx(tfm);
312589d124cbSJonas Eymann 
312689d124cbSJonas Eymann 	talitos_alg = container_of(alg, struct talitos_crypto_alg,
312789d124cbSJonas Eymann 				   algt.alg.aead);
312889d124cbSJonas Eymann 
312989d124cbSJonas Eymann 	return talitos_init_common(ctx, talitos_alg);
31309c4a7965SKim Phillips }
31319c4a7965SKim Phillips 
3132497f2e6bSLee Nipper static int talitos_cra_init_ahash(struct crypto_tfm *tfm)
3133497f2e6bSLee Nipper {
3134497f2e6bSLee Nipper 	struct talitos_ctx *ctx = crypto_tfm_ctx(tfm);
3135497f2e6bSLee Nipper 
3136497f2e6bSLee Nipper 	talitos_cra_init(tfm);
3137497f2e6bSLee Nipper 
3138497f2e6bSLee Nipper 	ctx->keylen = 0;
3139497f2e6bSLee Nipper 	crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm),
3140497f2e6bSLee Nipper 				 sizeof(struct talitos_ahash_req_ctx));
3141497f2e6bSLee Nipper 
3142497f2e6bSLee Nipper 	return 0;
3143497f2e6bSLee Nipper }
3144497f2e6bSLee Nipper 
31452e13ce08SLEROY Christophe static void talitos_cra_exit(struct crypto_tfm *tfm)
31462e13ce08SLEROY Christophe {
31472e13ce08SLEROY Christophe 	struct talitos_ctx *ctx = crypto_tfm_ctx(tfm);
31482e13ce08SLEROY Christophe 	struct device *dev = ctx->dev;
31492e13ce08SLEROY Christophe 
31502e13ce08SLEROY Christophe 	if (ctx->keylen)
31512e13ce08SLEROY Christophe 		dma_unmap_single(dev, ctx->dma_key, ctx->keylen, DMA_TO_DEVICE);
31522e13ce08SLEROY Christophe }
31532e13ce08SLEROY Christophe 
31549c4a7965SKim Phillips /*
31559c4a7965SKim Phillips  * given the alg's descriptor header template, determine whether descriptor
31569c4a7965SKim Phillips  * type and primary/secondary execution units required match the hw
31579c4a7965SKim Phillips  * capabilities description provided in the device tree node.
31589c4a7965SKim Phillips  */
31599c4a7965SKim Phillips static int hw_supports(struct device *dev, __be32 desc_hdr_template)
31609c4a7965SKim Phillips {
31619c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
31629c4a7965SKim Phillips 	int ret;
31639c4a7965SKim Phillips 
31649c4a7965SKim Phillips 	ret = (1 << DESC_TYPE(desc_hdr_template) & priv->desc_types) &&
31659c4a7965SKim Phillips 	      (1 << PRIMARY_EU(desc_hdr_template) & priv->exec_units);
31669c4a7965SKim Phillips 
31679c4a7965SKim Phillips 	if (SECONDARY_EU(desc_hdr_template))
31689c4a7965SKim Phillips 		ret = ret && (1 << SECONDARY_EU(desc_hdr_template)
31699c4a7965SKim Phillips 		              & priv->exec_units);
31709c4a7965SKim Phillips 
31719c4a7965SKim Phillips 	return ret;
31729c4a7965SKim Phillips }
31739c4a7965SKim Phillips 
31742dc11581SGrant Likely static int talitos_remove(struct platform_device *ofdev)
31759c4a7965SKim Phillips {
31769c4a7965SKim Phillips 	struct device *dev = &ofdev->dev;
31779c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
31789c4a7965SKim Phillips 	struct talitos_crypto_alg *t_alg, *n;
31799c4a7965SKim Phillips 	int i;
31809c4a7965SKim Phillips 
31819c4a7965SKim Phillips 	list_for_each_entry_safe(t_alg, n, &priv->alg_list, entry) {
3182acbf7c62SLee Nipper 		switch (t_alg->algt.type) {
3183acbf7c62SLee Nipper 		case CRYPTO_ALG_TYPE_ABLKCIPHER:
3184acbf7c62SLee Nipper 			break;
3185aeb4c132SHerbert Xu 		case CRYPTO_ALG_TYPE_AEAD:
3186aeb4c132SHerbert Xu 			crypto_unregister_aead(&t_alg->algt.alg.aead);
3187acbf7c62SLee Nipper 		case CRYPTO_ALG_TYPE_AHASH:
3188acbf7c62SLee Nipper 			crypto_unregister_ahash(&t_alg->algt.alg.hash);
3189acbf7c62SLee Nipper 			break;
3190acbf7c62SLee Nipper 		}
31919c4a7965SKim Phillips 		list_del(&t_alg->entry);
31929c4a7965SKim Phillips 	}
31939c4a7965SKim Phillips 
31949c4a7965SKim Phillips 	if (hw_supports(dev, DESC_HDR_SEL0_RNG))
31959c4a7965SKim Phillips 		talitos_unregister_rng(dev);
31969c4a7965SKim Phillips 
3197c3e337f8SKim Phillips 	for (i = 0; i < 2; i++)
31982cdba3cfSKim Phillips 		if (priv->irq[i]) {
3199c3e337f8SKim Phillips 			free_irq(priv->irq[i], dev);
3200c3e337f8SKim Phillips 			irq_dispose_mapping(priv->irq[i]);
32019c4a7965SKim Phillips 		}
32029c4a7965SKim Phillips 
3203c3e337f8SKim Phillips 	tasklet_kill(&priv->done_task[0]);
32042cdba3cfSKim Phillips 	if (priv->irq[1])
3205c3e337f8SKim Phillips 		tasklet_kill(&priv->done_task[1]);
32069c4a7965SKim Phillips 
32079c4a7965SKim Phillips 	return 0;
32089c4a7965SKim Phillips }
32099c4a7965SKim Phillips 
32109c4a7965SKim Phillips static struct talitos_crypto_alg *talitos_alg_alloc(struct device *dev,
32119c4a7965SKim Phillips 						    struct talitos_alg_template
32129c4a7965SKim Phillips 						           *template)
32139c4a7965SKim Phillips {
321460f208d7SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
32159c4a7965SKim Phillips 	struct talitos_crypto_alg *t_alg;
32169c4a7965SKim Phillips 	struct crypto_alg *alg;
32179c4a7965SKim Phillips 
321824b92ff2SLEROY Christophe 	t_alg = devm_kzalloc(dev, sizeof(struct talitos_crypto_alg),
321924b92ff2SLEROY Christophe 			     GFP_KERNEL);
32209c4a7965SKim Phillips 	if (!t_alg)
32219c4a7965SKim Phillips 		return ERR_PTR(-ENOMEM);
32229c4a7965SKim Phillips 
3223acbf7c62SLee Nipper 	t_alg->algt = *template;
3224acbf7c62SLee Nipper 
3225acbf7c62SLee Nipper 	switch (t_alg->algt.type) {
3226acbf7c62SLee Nipper 	case CRYPTO_ALG_TYPE_ABLKCIPHER:
3227497f2e6bSLee Nipper 		alg = &t_alg->algt.alg.crypto;
3228497f2e6bSLee Nipper 		alg->cra_init = talitos_cra_init;
32292e13ce08SLEROY Christophe 		alg->cra_exit = talitos_cra_exit;
3230d4cd3283SKim Phillips 		alg->cra_type = &crypto_ablkcipher_type;
3231ef7c5c85SHerbert Xu 		alg->cra_ablkcipher.setkey = alg->cra_ablkcipher.setkey ?:
3232ef7c5c85SHerbert Xu 					     ablkcipher_setkey;
3233b286e003SKim Phillips 		alg->cra_ablkcipher.encrypt = ablkcipher_encrypt;
3234b286e003SKim Phillips 		alg->cra_ablkcipher.decrypt = ablkcipher_decrypt;
3235497f2e6bSLee Nipper 		break;
3236acbf7c62SLee Nipper 	case CRYPTO_ALG_TYPE_AEAD:
3237aeb4c132SHerbert Xu 		alg = &t_alg->algt.alg.aead.base;
32382e13ce08SLEROY Christophe 		alg->cra_exit = talitos_cra_exit;
3239aeb4c132SHerbert Xu 		t_alg->algt.alg.aead.init = talitos_cra_init_aead;
3240ef7c5c85SHerbert Xu 		t_alg->algt.alg.aead.setkey = t_alg->algt.alg.aead.setkey ?:
3241ef7c5c85SHerbert Xu 					      aead_setkey;
3242aeb4c132SHerbert Xu 		t_alg->algt.alg.aead.encrypt = aead_encrypt;
3243aeb4c132SHerbert Xu 		t_alg->algt.alg.aead.decrypt = aead_decrypt;
32446cda075aSLEROY Christophe 		if (!(priv->features & TALITOS_FTR_SHA224_HWINIT) &&
32456cda075aSLEROY Christophe 		    !strncmp(alg->cra_name, "authenc(hmac(sha224)", 20)) {
324624b92ff2SLEROY Christophe 			devm_kfree(dev, t_alg);
32476cda075aSLEROY Christophe 			return ERR_PTR(-ENOTSUPP);
32486cda075aSLEROY Christophe 		}
3249acbf7c62SLee Nipper 		break;
3250acbf7c62SLee Nipper 	case CRYPTO_ALG_TYPE_AHASH:
3251acbf7c62SLee Nipper 		alg = &t_alg->algt.alg.hash.halg.base;
3252497f2e6bSLee Nipper 		alg->cra_init = talitos_cra_init_ahash;
3253ad4cd51fSLEROY Christophe 		alg->cra_exit = talitos_cra_exit;
3254b286e003SKim Phillips 		t_alg->algt.alg.hash.init = ahash_init;
3255b286e003SKim Phillips 		t_alg->algt.alg.hash.update = ahash_update;
3256b286e003SKim Phillips 		t_alg->algt.alg.hash.final = ahash_final;
3257b286e003SKim Phillips 		t_alg->algt.alg.hash.finup = ahash_finup;
3258b286e003SKim Phillips 		t_alg->algt.alg.hash.digest = ahash_digest;
325956136631SLEROY Christophe 		if (!strncmp(alg->cra_name, "hmac", 4))
3260b286e003SKim Phillips 			t_alg->algt.alg.hash.setkey = ahash_setkey;
32613639ca84SHoria Geant? 		t_alg->algt.alg.hash.import = ahash_import;
32623639ca84SHoria Geant? 		t_alg->algt.alg.hash.export = ahash_export;
3263b286e003SKim Phillips 
326479b3a418SLee Nipper 		if (!(priv->features & TALITOS_FTR_HMAC_OK) &&
32650b2730d8SKim Phillips 		    !strncmp(alg->cra_name, "hmac", 4)) {
326624b92ff2SLEROY Christophe 			devm_kfree(dev, t_alg);
326779b3a418SLee Nipper 			return ERR_PTR(-ENOTSUPP);
32680b2730d8SKim Phillips 		}
326960f208d7SKim Phillips 		if (!(priv->features & TALITOS_FTR_SHA224_HWINIT) &&
327079b3a418SLee Nipper 		    (!strcmp(alg->cra_name, "sha224") ||
327179b3a418SLee Nipper 		     !strcmp(alg->cra_name, "hmac(sha224)"))) {
327260f208d7SKim Phillips 			t_alg->algt.alg.hash.init = ahash_init_sha224_swinit;
327360f208d7SKim Phillips 			t_alg->algt.desc_hdr_template =
327460f208d7SKim Phillips 					DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
327560f208d7SKim Phillips 					DESC_HDR_SEL0_MDEUA |
327660f208d7SKim Phillips 					DESC_HDR_MODE0_MDEU_SHA256;
327760f208d7SKim Phillips 		}
3278497f2e6bSLee Nipper 		break;
32791d11911aSKim Phillips 	default:
32801d11911aSKim Phillips 		dev_err(dev, "unknown algorithm type %d\n", t_alg->algt.type);
328124b92ff2SLEROY Christophe 		devm_kfree(dev, t_alg);
32821d11911aSKim Phillips 		return ERR_PTR(-EINVAL);
3283acbf7c62SLee Nipper 	}
32849c4a7965SKim Phillips 
32859c4a7965SKim Phillips 	alg->cra_module = THIS_MODULE;
3286b0057763SLEROY Christophe 	if (t_alg->algt.priority)
3287b0057763SLEROY Christophe 		alg->cra_priority = t_alg->algt.priority;
3288b0057763SLEROY Christophe 	else
32899c4a7965SKim Phillips 		alg->cra_priority = TALITOS_CRA_PRIORITY;
32909c4a7965SKim Phillips 	alg->cra_alignmask = 0;
32919c4a7965SKim Phillips 	alg->cra_ctxsize = sizeof(struct talitos_ctx);
3292d912bb76SNikos Mavrogiannopoulos 	alg->cra_flags |= CRYPTO_ALG_KERN_DRIVER_ONLY;
32939c4a7965SKim Phillips 
32949c4a7965SKim Phillips 	t_alg->dev = dev;
32959c4a7965SKim Phillips 
32969c4a7965SKim Phillips 	return t_alg;
32979c4a7965SKim Phillips }
32989c4a7965SKim Phillips 
3299c3e337f8SKim Phillips static int talitos_probe_irq(struct platform_device *ofdev)
3300c3e337f8SKim Phillips {
3301c3e337f8SKim Phillips 	struct device *dev = &ofdev->dev;
3302c3e337f8SKim Phillips 	struct device_node *np = ofdev->dev.of_node;
3303c3e337f8SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
3304c3e337f8SKim Phillips 	int err;
3305dd3c0987SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
3306c3e337f8SKim Phillips 
3307c3e337f8SKim Phillips 	priv->irq[0] = irq_of_parse_and_map(np, 0);
33082cdba3cfSKim Phillips 	if (!priv->irq[0]) {
3309c3e337f8SKim Phillips 		dev_err(dev, "failed to map irq\n");
3310c3e337f8SKim Phillips 		return -EINVAL;
3311c3e337f8SKim Phillips 	}
3312dd3c0987SLEROY Christophe 	if (is_sec1) {
3313dd3c0987SLEROY Christophe 		err = request_irq(priv->irq[0], talitos1_interrupt_4ch, 0,
3314dd3c0987SLEROY Christophe 				  dev_driver_string(dev), dev);
3315dd3c0987SLEROY Christophe 		goto primary_out;
3316dd3c0987SLEROY Christophe 	}
3317c3e337f8SKim Phillips 
3318c3e337f8SKim Phillips 	priv->irq[1] = irq_of_parse_and_map(np, 1);
3319c3e337f8SKim Phillips 
3320c3e337f8SKim Phillips 	/* get the primary irq line */
33212cdba3cfSKim Phillips 	if (!priv->irq[1]) {
3322dd3c0987SLEROY Christophe 		err = request_irq(priv->irq[0], talitos2_interrupt_4ch, 0,
3323c3e337f8SKim Phillips 				  dev_driver_string(dev), dev);
3324c3e337f8SKim Phillips 		goto primary_out;
3325c3e337f8SKim Phillips 	}
3326c3e337f8SKim Phillips 
3327dd3c0987SLEROY Christophe 	err = request_irq(priv->irq[0], talitos2_interrupt_ch0_2, 0,
3328c3e337f8SKim Phillips 			  dev_driver_string(dev), dev);
3329c3e337f8SKim Phillips 	if (err)
3330c3e337f8SKim Phillips 		goto primary_out;
3331c3e337f8SKim Phillips 
3332c3e337f8SKim Phillips 	/* get the secondary irq line */
3333dd3c0987SLEROY Christophe 	err = request_irq(priv->irq[1], talitos2_interrupt_ch1_3, 0,
3334c3e337f8SKim Phillips 			  dev_driver_string(dev), dev);
3335c3e337f8SKim Phillips 	if (err) {
3336c3e337f8SKim Phillips 		dev_err(dev, "failed to request secondary irq\n");
3337c3e337f8SKim Phillips 		irq_dispose_mapping(priv->irq[1]);
33382cdba3cfSKim Phillips 		priv->irq[1] = 0;
3339c3e337f8SKim Phillips 	}
3340c3e337f8SKim Phillips 
3341c3e337f8SKim Phillips 	return err;
3342c3e337f8SKim Phillips 
3343c3e337f8SKim Phillips primary_out:
3344c3e337f8SKim Phillips 	if (err) {
3345c3e337f8SKim Phillips 		dev_err(dev, "failed to request primary irq\n");
3346c3e337f8SKim Phillips 		irq_dispose_mapping(priv->irq[0]);
33472cdba3cfSKim Phillips 		priv->irq[0] = 0;
3348c3e337f8SKim Phillips 	}
3349c3e337f8SKim Phillips 
3350c3e337f8SKim Phillips 	return err;
3351c3e337f8SKim Phillips }
3352c3e337f8SKim Phillips 
33531c48a5c9SGrant Likely static int talitos_probe(struct platform_device *ofdev)
33549c4a7965SKim Phillips {
33559c4a7965SKim Phillips 	struct device *dev = &ofdev->dev;
335661c7a080SGrant Likely 	struct device_node *np = ofdev->dev.of_node;
33579c4a7965SKim Phillips 	struct talitos_private *priv;
33589c4a7965SKim Phillips 	int i, err;
33595fa7fa14SLEROY Christophe 	int stride;
3360fd5ea7f0SLEROY Christophe 	struct resource *res;
33619c4a7965SKim Phillips 
336224b92ff2SLEROY Christophe 	priv = devm_kzalloc(dev, sizeof(struct talitos_private), GFP_KERNEL);
33639c4a7965SKim Phillips 	if (!priv)
33649c4a7965SKim Phillips 		return -ENOMEM;
33659c4a7965SKim Phillips 
3366f3de9cb1SKevin Hao 	INIT_LIST_HEAD(&priv->alg_list);
3367f3de9cb1SKevin Hao 
33689c4a7965SKim Phillips 	dev_set_drvdata(dev, priv);
33699c4a7965SKim Phillips 
33709c4a7965SKim Phillips 	priv->ofdev = ofdev;
33719c4a7965SKim Phillips 
3372511d63cbSHoria Geanta 	spin_lock_init(&priv->reg_lock);
3373511d63cbSHoria Geanta 
3374fd5ea7f0SLEROY Christophe 	res = platform_get_resource(ofdev, IORESOURCE_MEM, 0);
3375fd5ea7f0SLEROY Christophe 	if (!res)
3376fd5ea7f0SLEROY Christophe 		return -ENXIO;
3377fd5ea7f0SLEROY Christophe 	priv->reg = devm_ioremap(dev, res->start, resource_size(res));
33789c4a7965SKim Phillips 	if (!priv->reg) {
33799c4a7965SKim Phillips 		dev_err(dev, "failed to of_iomap\n");
33809c4a7965SKim Phillips 		err = -ENOMEM;
33819c4a7965SKim Phillips 		goto err_out;
33829c4a7965SKim Phillips 	}
33839c4a7965SKim Phillips 
33849c4a7965SKim Phillips 	/* get SEC version capabilities from device tree */
3385fa14c6cfSLEROY Christophe 	of_property_read_u32(np, "fsl,num-channels", &priv->num_channels);
3386fa14c6cfSLEROY Christophe 	of_property_read_u32(np, "fsl,channel-fifo-len", &priv->chfifo_len);
3387fa14c6cfSLEROY Christophe 	of_property_read_u32(np, "fsl,exec-units-mask", &priv->exec_units);
3388fa14c6cfSLEROY Christophe 	of_property_read_u32(np, "fsl,descriptor-types-mask",
3389fa14c6cfSLEROY Christophe 			     &priv->desc_types);
33909c4a7965SKim Phillips 
33919c4a7965SKim Phillips 	if (!is_power_of_2(priv->num_channels) || !priv->chfifo_len ||
33929c4a7965SKim Phillips 	    !priv->exec_units || !priv->desc_types) {
33939c4a7965SKim Phillips 		dev_err(dev, "invalid property data in device tree node\n");
33949c4a7965SKim Phillips 		err = -EINVAL;
33959c4a7965SKim Phillips 		goto err_out;
33969c4a7965SKim Phillips 	}
33979c4a7965SKim Phillips 
3398f3c85bc1SLee Nipper 	if (of_device_is_compatible(np, "fsl,sec3.0"))
3399f3c85bc1SLee Nipper 		priv->features |= TALITOS_FTR_SRC_LINK_TBL_LEN_INCLUDES_EXTENT;
3400f3c85bc1SLee Nipper 
3401fe5720e2SKim Phillips 	if (of_device_is_compatible(np, "fsl,sec2.1"))
340260f208d7SKim Phillips 		priv->features |= TALITOS_FTR_HW_AUTH_CHECK |
340379b3a418SLee Nipper 				  TALITOS_FTR_SHA224_HWINIT |
340479b3a418SLee Nipper 				  TALITOS_FTR_HMAC_OK;
3405fe5720e2SKim Phillips 
340621590888SLEROY Christophe 	if (of_device_is_compatible(np, "fsl,sec1.0"))
340721590888SLEROY Christophe 		priv->features |= TALITOS_FTR_SEC1;
340821590888SLEROY Christophe 
34095fa7fa14SLEROY Christophe 	if (of_device_is_compatible(np, "fsl,sec1.2")) {
34105fa7fa14SLEROY Christophe 		priv->reg_deu = priv->reg + TALITOS12_DEU;
34115fa7fa14SLEROY Christophe 		priv->reg_aesu = priv->reg + TALITOS12_AESU;
34125fa7fa14SLEROY Christophe 		priv->reg_mdeu = priv->reg + TALITOS12_MDEU;
34135fa7fa14SLEROY Christophe 		stride = TALITOS1_CH_STRIDE;
34145fa7fa14SLEROY Christophe 	} else if (of_device_is_compatible(np, "fsl,sec1.0")) {
34155fa7fa14SLEROY Christophe 		priv->reg_deu = priv->reg + TALITOS10_DEU;
34165fa7fa14SLEROY Christophe 		priv->reg_aesu = priv->reg + TALITOS10_AESU;
34175fa7fa14SLEROY Christophe 		priv->reg_mdeu = priv->reg + TALITOS10_MDEU;
34185fa7fa14SLEROY Christophe 		priv->reg_afeu = priv->reg + TALITOS10_AFEU;
34195fa7fa14SLEROY Christophe 		priv->reg_rngu = priv->reg + TALITOS10_RNGU;
34205fa7fa14SLEROY Christophe 		priv->reg_pkeu = priv->reg + TALITOS10_PKEU;
34215fa7fa14SLEROY Christophe 		stride = TALITOS1_CH_STRIDE;
34225fa7fa14SLEROY Christophe 	} else {
34235fa7fa14SLEROY Christophe 		priv->reg_deu = priv->reg + TALITOS2_DEU;
34245fa7fa14SLEROY Christophe 		priv->reg_aesu = priv->reg + TALITOS2_AESU;
34255fa7fa14SLEROY Christophe 		priv->reg_mdeu = priv->reg + TALITOS2_MDEU;
34265fa7fa14SLEROY Christophe 		priv->reg_afeu = priv->reg + TALITOS2_AFEU;
34275fa7fa14SLEROY Christophe 		priv->reg_rngu = priv->reg + TALITOS2_RNGU;
34285fa7fa14SLEROY Christophe 		priv->reg_pkeu = priv->reg + TALITOS2_PKEU;
34295fa7fa14SLEROY Christophe 		priv->reg_keu = priv->reg + TALITOS2_KEU;
34305fa7fa14SLEROY Christophe 		priv->reg_crcu = priv->reg + TALITOS2_CRCU;
34315fa7fa14SLEROY Christophe 		stride = TALITOS2_CH_STRIDE;
34325fa7fa14SLEROY Christophe 	}
34335fa7fa14SLEROY Christophe 
3434dd3c0987SLEROY Christophe 	err = talitos_probe_irq(ofdev);
3435dd3c0987SLEROY Christophe 	if (err)
3436dd3c0987SLEROY Christophe 		goto err_out;
3437dd3c0987SLEROY Christophe 
3438dd3c0987SLEROY Christophe 	if (of_device_is_compatible(np, "fsl,sec1.0")) {
34399c02e285SLEROY Christophe 		if (priv->num_channels == 1)
34409c02e285SLEROY Christophe 			tasklet_init(&priv->done_task[0], talitos1_done_ch0,
34419c02e285SLEROY Christophe 				     (unsigned long)dev);
34429c02e285SLEROY Christophe 		else
3443dd3c0987SLEROY Christophe 			tasklet_init(&priv->done_task[0], talitos1_done_4ch,
3444dd3c0987SLEROY Christophe 				     (unsigned long)dev);
3445dd3c0987SLEROY Christophe 	} else {
34469c02e285SLEROY Christophe 		if (priv->irq[1]) {
3447dd3c0987SLEROY Christophe 			tasklet_init(&priv->done_task[0], talitos2_done_ch0_2,
3448dd3c0987SLEROY Christophe 				     (unsigned long)dev);
3449dd3c0987SLEROY Christophe 			tasklet_init(&priv->done_task[1], talitos2_done_ch1_3,
3450dd3c0987SLEROY Christophe 				     (unsigned long)dev);
34519c02e285SLEROY Christophe 		} else if (priv->num_channels == 1) {
34529c02e285SLEROY Christophe 			tasklet_init(&priv->done_task[0], talitos2_done_ch0,
34539c02e285SLEROY Christophe 				     (unsigned long)dev);
34549c02e285SLEROY Christophe 		} else {
34559c02e285SLEROY Christophe 			tasklet_init(&priv->done_task[0], talitos2_done_4ch,
34569c02e285SLEROY Christophe 				     (unsigned long)dev);
3457dd3c0987SLEROY Christophe 		}
3458dd3c0987SLEROY Christophe 	}
3459dd3c0987SLEROY Christophe 
3460a86854d0SKees Cook 	priv->chan = devm_kcalloc(dev,
3461a86854d0SKees Cook 				  priv->num_channels,
3462a86854d0SKees Cook 				  sizeof(struct talitos_channel),
3463a86854d0SKees Cook 				  GFP_KERNEL);
34644b992628SKim Phillips 	if (!priv->chan) {
34654b992628SKim Phillips 		dev_err(dev, "failed to allocate channel management space\n");
34669c4a7965SKim Phillips 		err = -ENOMEM;
34679c4a7965SKim Phillips 		goto err_out;
34689c4a7965SKim Phillips 	}
34699c4a7965SKim Phillips 
3470f641ddddSMartin Hicks 	priv->fifo_len = roundup_pow_of_two(priv->chfifo_len);
3471f641ddddSMartin Hicks 
3472c3e337f8SKim Phillips 	for (i = 0; i < priv->num_channels; i++) {
34735fa7fa14SLEROY Christophe 		priv->chan[i].reg = priv->reg + stride * (i + 1);
34742cdba3cfSKim Phillips 		if (!priv->irq[1] || !(i & 1))
3475c3e337f8SKim Phillips 			priv->chan[i].reg += TALITOS_CH_BASE_OFFSET;
3476ad42d5fcSKim Phillips 
34774b992628SKim Phillips 		spin_lock_init(&priv->chan[i].head_lock);
34784b992628SKim Phillips 		spin_lock_init(&priv->chan[i].tail_lock);
34799c4a7965SKim Phillips 
3480a86854d0SKees Cook 		priv->chan[i].fifo = devm_kcalloc(dev,
3481a86854d0SKees Cook 						priv->fifo_len,
3482a86854d0SKees Cook 						sizeof(struct talitos_request),
3483a86854d0SKees Cook 						GFP_KERNEL);
34844b992628SKim Phillips 		if (!priv->chan[i].fifo) {
34859c4a7965SKim Phillips 			dev_err(dev, "failed to allocate request fifo %d\n", i);
34869c4a7965SKim Phillips 			err = -ENOMEM;
34879c4a7965SKim Phillips 			goto err_out;
34889c4a7965SKim Phillips 		}
34899c4a7965SKim Phillips 
34904b992628SKim Phillips 		atomic_set(&priv->chan[i].submit_count,
34914b992628SKim Phillips 			   -(priv->chfifo_len - 1));
3492f641ddddSMartin Hicks 	}
34939c4a7965SKim Phillips 
349481eb024cSKim Phillips 	dma_set_mask(dev, DMA_BIT_MASK(36));
349581eb024cSKim Phillips 
34969c4a7965SKim Phillips 	/* reset and initialize the h/w */
34979c4a7965SKim Phillips 	err = init_device(dev);
34989c4a7965SKim Phillips 	if (err) {
34999c4a7965SKim Phillips 		dev_err(dev, "failed to initialize device\n");
35009c4a7965SKim Phillips 		goto err_out;
35019c4a7965SKim Phillips 	}
35029c4a7965SKim Phillips 
35039c4a7965SKim Phillips 	/* register the RNG, if available */
35049c4a7965SKim Phillips 	if (hw_supports(dev, DESC_HDR_SEL0_RNG)) {
35059c4a7965SKim Phillips 		err = talitos_register_rng(dev);
35069c4a7965SKim Phillips 		if (err) {
35079c4a7965SKim Phillips 			dev_err(dev, "failed to register hwrng: %d\n", err);
35089c4a7965SKim Phillips 			goto err_out;
35099c4a7965SKim Phillips 		} else
35109c4a7965SKim Phillips 			dev_info(dev, "hwrng\n");
35119c4a7965SKim Phillips 	}
35129c4a7965SKim Phillips 
35139c4a7965SKim Phillips 	/* register crypto algorithms the device supports */
35149c4a7965SKim Phillips 	for (i = 0; i < ARRAY_SIZE(driver_algs); i++) {
35159c4a7965SKim Phillips 		if (hw_supports(dev, driver_algs[i].desc_hdr_template)) {
35169c4a7965SKim Phillips 			struct talitos_crypto_alg *t_alg;
3517aeb4c132SHerbert Xu 			struct crypto_alg *alg = NULL;
35189c4a7965SKim Phillips 
35199c4a7965SKim Phillips 			t_alg = talitos_alg_alloc(dev, &driver_algs[i]);
35209c4a7965SKim Phillips 			if (IS_ERR(t_alg)) {
35219c4a7965SKim Phillips 				err = PTR_ERR(t_alg);
35220b2730d8SKim Phillips 				if (err == -ENOTSUPP)
352379b3a418SLee Nipper 					continue;
35249c4a7965SKim Phillips 				goto err_out;
35259c4a7965SKim Phillips 			}
35269c4a7965SKim Phillips 
3527acbf7c62SLee Nipper 			switch (t_alg->algt.type) {
3528acbf7c62SLee Nipper 			case CRYPTO_ALG_TYPE_ABLKCIPHER:
3529acbf7c62SLee Nipper 				err = crypto_register_alg(
3530acbf7c62SLee Nipper 						&t_alg->algt.alg.crypto);
3531aeb4c132SHerbert Xu 				alg = &t_alg->algt.alg.crypto;
3532acbf7c62SLee Nipper 				break;
3533aeb4c132SHerbert Xu 
3534aeb4c132SHerbert Xu 			case CRYPTO_ALG_TYPE_AEAD:
3535aeb4c132SHerbert Xu 				err = crypto_register_aead(
3536aeb4c132SHerbert Xu 					&t_alg->algt.alg.aead);
3537aeb4c132SHerbert Xu 				alg = &t_alg->algt.alg.aead.base;
3538aeb4c132SHerbert Xu 				break;
3539aeb4c132SHerbert Xu 
3540acbf7c62SLee Nipper 			case CRYPTO_ALG_TYPE_AHASH:
3541acbf7c62SLee Nipper 				err = crypto_register_ahash(
3542acbf7c62SLee Nipper 						&t_alg->algt.alg.hash);
3543aeb4c132SHerbert Xu 				alg = &t_alg->algt.alg.hash.halg.base;
3544acbf7c62SLee Nipper 				break;
3545acbf7c62SLee Nipper 			}
35469c4a7965SKim Phillips 			if (err) {
35479c4a7965SKim Phillips 				dev_err(dev, "%s alg registration failed\n",
3548aeb4c132SHerbert Xu 					alg->cra_driver_name);
354924b92ff2SLEROY Christophe 				devm_kfree(dev, t_alg);
3550991155baSHoria Geanta 			} else
35519c4a7965SKim Phillips 				list_add_tail(&t_alg->entry, &priv->alg_list);
35529c4a7965SKim Phillips 		}
35539c4a7965SKim Phillips 	}
35545b859b6eSKim Phillips 	if (!list_empty(&priv->alg_list))
35555b859b6eSKim Phillips 		dev_info(dev, "%s algorithms registered in /proc/crypto\n",
35565b859b6eSKim Phillips 			 (char *)of_get_property(np, "compatible", NULL));
35579c4a7965SKim Phillips 
35589c4a7965SKim Phillips 	return 0;
35599c4a7965SKim Phillips 
35609c4a7965SKim Phillips err_out:
35619c4a7965SKim Phillips 	talitos_remove(ofdev);
35629c4a7965SKim Phillips 
35639c4a7965SKim Phillips 	return err;
35649c4a7965SKim Phillips }
35659c4a7965SKim Phillips 
35666c3f975aSMárton Németh static const struct of_device_id talitos_match[] = {
35670635b7dbSLEROY Christophe #ifdef CONFIG_CRYPTO_DEV_TALITOS1
35680635b7dbSLEROY Christophe 	{
35690635b7dbSLEROY Christophe 		.compatible = "fsl,sec1.0",
35700635b7dbSLEROY Christophe 	},
35710635b7dbSLEROY Christophe #endif
35720635b7dbSLEROY Christophe #ifdef CONFIG_CRYPTO_DEV_TALITOS2
35739c4a7965SKim Phillips 	{
35749c4a7965SKim Phillips 		.compatible = "fsl,sec2.0",
35759c4a7965SKim Phillips 	},
35760635b7dbSLEROY Christophe #endif
35779c4a7965SKim Phillips 	{},
35789c4a7965SKim Phillips };
35799c4a7965SKim Phillips MODULE_DEVICE_TABLE(of, talitos_match);
35809c4a7965SKim Phillips 
35811c48a5c9SGrant Likely static struct platform_driver talitos_driver = {
35824018294bSGrant Likely 	.driver = {
35839c4a7965SKim Phillips 		.name = "talitos",
35844018294bSGrant Likely 		.of_match_table = talitos_match,
35854018294bSGrant Likely 	},
35869c4a7965SKim Phillips 	.probe = talitos_probe,
3587596f1034SAl Viro 	.remove = talitos_remove,
35889c4a7965SKim Phillips };
35899c4a7965SKim Phillips 
3590741e8c2dSAxel Lin module_platform_driver(talitos_driver);
35919c4a7965SKim Phillips 
35929c4a7965SKim Phillips MODULE_LICENSE("GPL");
35939c4a7965SKim Phillips MODULE_AUTHOR("Kim Phillips <kim.phillips@freescale.com>");
35949c4a7965SKim Phillips MODULE_DESCRIPTION("Freescale integrated security engine (SEC) driver");
3595