xref: /linux/drivers/crypto/talitos.c (revision 70d355ccea899dad47dc22d3a4406998f55143fd)
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,
59922f9dc8SLEROY Christophe 			   bool is_sec1)
6081eb024cSKim Phillips {
61edc6bd69SLEROY Christophe 	ptr->ptr = cpu_to_be32(lower_32_bits(dma_addr));
62922f9dc8SLEROY Christophe 	if (!is_sec1)
63edc6bd69SLEROY Christophe 		ptr->eptr = upper_32_bits(dma_addr);
6481eb024cSKim Phillips }
6581eb024cSKim Phillips 
66340ff60aSHoria Geant? static void copy_talitos_ptr(struct talitos_ptr *dst_ptr,
67340ff60aSHoria Geant? 			     struct talitos_ptr *src_ptr, bool is_sec1)
68340ff60aSHoria Geant? {
69340ff60aSHoria Geant? 	dst_ptr->ptr = src_ptr->ptr;
70340ff60aSHoria Geant? 	if (!is_sec1)
71340ff60aSHoria Geant? 		dst_ptr->eptr = src_ptr->eptr;
72340ff60aSHoria Geant? }
73340ff60aSHoria Geant? 
7442e8b0d7SHoria Geant? static void to_talitos_ptr_len(struct talitos_ptr *ptr, unsigned int len,
75922f9dc8SLEROY Christophe 			       bool is_sec1)
76538caf83SLEROY Christophe {
77922f9dc8SLEROY Christophe 	if (is_sec1) {
78922f9dc8SLEROY Christophe 		ptr->res = 0;
79922f9dc8SLEROY Christophe 		ptr->len1 = cpu_to_be16(len);
80922f9dc8SLEROY Christophe 	} else {
81538caf83SLEROY Christophe 		ptr->len = cpu_to_be16(len);
82538caf83SLEROY Christophe 	}
83922f9dc8SLEROY Christophe }
84538caf83SLEROY Christophe 
85922f9dc8SLEROY Christophe static unsigned short from_talitos_ptr_len(struct talitos_ptr *ptr,
86922f9dc8SLEROY Christophe 					   bool is_sec1)
87538caf83SLEROY Christophe {
88922f9dc8SLEROY Christophe 	if (is_sec1)
89922f9dc8SLEROY Christophe 		return be16_to_cpu(ptr->len1);
90922f9dc8SLEROY Christophe 	else
91538caf83SLEROY Christophe 		return be16_to_cpu(ptr->len);
92538caf83SLEROY Christophe }
93538caf83SLEROY Christophe 
94b096b544SLEROY Christophe static void to_talitos_ptr_ext_set(struct talitos_ptr *ptr, u8 val,
95b096b544SLEROY Christophe 				   bool is_sec1)
96185eb79fSLEROY Christophe {
97922f9dc8SLEROY Christophe 	if (!is_sec1)
98b096b544SLEROY Christophe 		ptr->j_extent = val;
99b096b544SLEROY Christophe }
100b096b544SLEROY Christophe 
101b096b544SLEROY Christophe static void to_talitos_ptr_ext_or(struct talitos_ptr *ptr, u8 val, bool is_sec1)
102b096b544SLEROY Christophe {
103b096b544SLEROY Christophe 	if (!is_sec1)
104b096b544SLEROY Christophe 		ptr->j_extent |= val;
105185eb79fSLEROY Christophe }
106185eb79fSLEROY Christophe 
1079c4a7965SKim Phillips /*
1089c4a7965SKim Phillips  * map virtual single (contiguous) pointer to h/w descriptor pointer
1099c4a7965SKim Phillips  */
1109c4a7965SKim Phillips static void map_single_talitos_ptr(struct device *dev,
111edc6bd69SLEROY Christophe 				   struct talitos_ptr *ptr,
11242e8b0d7SHoria Geant? 				   unsigned int len, void *data,
1139c4a7965SKim Phillips 				   enum dma_data_direction dir)
1149c4a7965SKim Phillips {
11581eb024cSKim Phillips 	dma_addr_t dma_addr = dma_map_single(dev, data, len, dir);
116922f9dc8SLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
117922f9dc8SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
11881eb024cSKim Phillips 
119922f9dc8SLEROY Christophe 	to_talitos_ptr_len(ptr, len, is_sec1);
120922f9dc8SLEROY Christophe 	to_talitos_ptr(ptr, dma_addr, is_sec1);
121b096b544SLEROY Christophe 	to_talitos_ptr_ext_set(ptr, 0, is_sec1);
1229c4a7965SKim Phillips }
1239c4a7965SKim Phillips 
1249c4a7965SKim Phillips /*
1259c4a7965SKim Phillips  * unmap bus single (contiguous) h/w descriptor pointer
1269c4a7965SKim Phillips  */
1279c4a7965SKim Phillips static void unmap_single_talitos_ptr(struct device *dev,
128edc6bd69SLEROY Christophe 				     struct talitos_ptr *ptr,
1299c4a7965SKim Phillips 				     enum dma_data_direction dir)
1309c4a7965SKim Phillips {
131922f9dc8SLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
132922f9dc8SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
133922f9dc8SLEROY Christophe 
134edc6bd69SLEROY Christophe 	dma_unmap_single(dev, be32_to_cpu(ptr->ptr),
135922f9dc8SLEROY Christophe 			 from_talitos_ptr_len(ptr, is_sec1), dir);
1369c4a7965SKim Phillips }
1379c4a7965SKim Phillips 
1389c4a7965SKim Phillips static int reset_channel(struct device *dev, int ch)
1399c4a7965SKim Phillips {
1409c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
1419c4a7965SKim Phillips 	unsigned int timeout = TALITOS_TIMEOUT;
142dd3c0987SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
1439c4a7965SKim Phillips 
144dd3c0987SLEROY Christophe 	if (is_sec1) {
145dd3c0987SLEROY Christophe 		setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO,
146dd3c0987SLEROY Christophe 			  TALITOS1_CCCR_LO_RESET);
1479c4a7965SKim Phillips 
148dd3c0987SLEROY Christophe 		while ((in_be32(priv->chan[ch].reg + TALITOS_CCCR_LO) &
149dd3c0987SLEROY Christophe 			TALITOS1_CCCR_LO_RESET) && --timeout)
1509c4a7965SKim Phillips 			cpu_relax();
151dd3c0987SLEROY Christophe 	} else {
152dd3c0987SLEROY Christophe 		setbits32(priv->chan[ch].reg + TALITOS_CCCR,
153dd3c0987SLEROY Christophe 			  TALITOS2_CCCR_RESET);
154dd3c0987SLEROY Christophe 
155dd3c0987SLEROY Christophe 		while ((in_be32(priv->chan[ch].reg + TALITOS_CCCR) &
156dd3c0987SLEROY Christophe 			TALITOS2_CCCR_RESET) && --timeout)
157dd3c0987SLEROY Christophe 			cpu_relax();
158dd3c0987SLEROY Christophe 	}
1599c4a7965SKim Phillips 
1609c4a7965SKim Phillips 	if (timeout == 0) {
1619c4a7965SKim Phillips 		dev_err(dev, "failed to reset channel %d\n", ch);
1629c4a7965SKim Phillips 		return -EIO;
1639c4a7965SKim Phillips 	}
1649c4a7965SKim Phillips 
16581eb024cSKim Phillips 	/* set 36-bit addressing, done writeback enable and done IRQ enable */
166ad42d5fcSKim Phillips 	setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO, TALITOS_CCCR_LO_EAE |
16781eb024cSKim Phillips 		  TALITOS_CCCR_LO_CDWE | TALITOS_CCCR_LO_CDIE);
1689c4a7965SKim Phillips 
169fe5720e2SKim Phillips 	/* and ICCR writeback, if available */
170fe5720e2SKim Phillips 	if (priv->features & TALITOS_FTR_HW_AUTH_CHECK)
171ad42d5fcSKim Phillips 		setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO,
172fe5720e2SKim Phillips 		          TALITOS_CCCR_LO_IWSE);
173fe5720e2SKim Phillips 
1749c4a7965SKim Phillips 	return 0;
1759c4a7965SKim Phillips }
1769c4a7965SKim Phillips 
1779c4a7965SKim Phillips static int reset_device(struct device *dev)
1789c4a7965SKim Phillips {
1799c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
1809c4a7965SKim Phillips 	unsigned int timeout = TALITOS_TIMEOUT;
181dd3c0987SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
182dd3c0987SLEROY Christophe 	u32 mcr = is_sec1 ? TALITOS1_MCR_SWR : TALITOS2_MCR_SWR;
1839c4a7965SKim Phillips 
184c3e337f8SKim Phillips 	setbits32(priv->reg + TALITOS_MCR, mcr);
1859c4a7965SKim Phillips 
186dd3c0987SLEROY Christophe 	while ((in_be32(priv->reg + TALITOS_MCR) & mcr)
1879c4a7965SKim Phillips 	       && --timeout)
1889c4a7965SKim Phillips 		cpu_relax();
1899c4a7965SKim Phillips 
1902cdba3cfSKim Phillips 	if (priv->irq[1]) {
191c3e337f8SKim Phillips 		mcr = TALITOS_MCR_RCA1 | TALITOS_MCR_RCA3;
192c3e337f8SKim Phillips 		setbits32(priv->reg + TALITOS_MCR, mcr);
193c3e337f8SKim Phillips 	}
194c3e337f8SKim Phillips 
1959c4a7965SKim Phillips 	if (timeout == 0) {
1969c4a7965SKim Phillips 		dev_err(dev, "failed to reset device\n");
1979c4a7965SKim Phillips 		return -EIO;
1989c4a7965SKim Phillips 	}
1999c4a7965SKim Phillips 
2009c4a7965SKim Phillips 	return 0;
2019c4a7965SKim Phillips }
2029c4a7965SKim Phillips 
2039c4a7965SKim Phillips /*
2049c4a7965SKim Phillips  * Reset and initialize the device
2059c4a7965SKim Phillips  */
2069c4a7965SKim Phillips static int init_device(struct device *dev)
2079c4a7965SKim Phillips {
2089c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
2099c4a7965SKim Phillips 	int ch, err;
210dd3c0987SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
2119c4a7965SKim Phillips 
2129c4a7965SKim Phillips 	/*
2139c4a7965SKim Phillips 	 * Master reset
2149c4a7965SKim Phillips 	 * errata documentation: warning: certain SEC interrupts
2159c4a7965SKim Phillips 	 * are not fully cleared by writing the MCR:SWR bit,
2169c4a7965SKim Phillips 	 * set bit twice to completely reset
2179c4a7965SKim Phillips 	 */
2189c4a7965SKim Phillips 	err = reset_device(dev);
2199c4a7965SKim Phillips 	if (err)
2209c4a7965SKim Phillips 		return err;
2219c4a7965SKim Phillips 
2229c4a7965SKim Phillips 	err = reset_device(dev);
2239c4a7965SKim Phillips 	if (err)
2249c4a7965SKim Phillips 		return err;
2259c4a7965SKim Phillips 
2269c4a7965SKim Phillips 	/* reset channels */
2279c4a7965SKim Phillips 	for (ch = 0; ch < priv->num_channels; ch++) {
2289c4a7965SKim Phillips 		err = reset_channel(dev, ch);
2299c4a7965SKim Phillips 		if (err)
2309c4a7965SKim Phillips 			return err;
2319c4a7965SKim Phillips 	}
2329c4a7965SKim Phillips 
2339c4a7965SKim Phillips 	/* enable channel done and error interrupts */
234dd3c0987SLEROY Christophe 	if (is_sec1) {
235dd3c0987SLEROY Christophe 		clrbits32(priv->reg + TALITOS_IMR, TALITOS1_IMR_INIT);
236dd3c0987SLEROY Christophe 		clrbits32(priv->reg + TALITOS_IMR_LO, TALITOS1_IMR_LO_INIT);
237dd3c0987SLEROY Christophe 		/* disable parity error check in DEU (erroneous? test vect.) */
238dd3c0987SLEROY Christophe 		setbits32(priv->reg_deu + TALITOS_EUICR, TALITOS1_DEUICR_KPE);
239dd3c0987SLEROY Christophe 	} else {
240dd3c0987SLEROY Christophe 		setbits32(priv->reg + TALITOS_IMR, TALITOS2_IMR_INIT);
241dd3c0987SLEROY Christophe 		setbits32(priv->reg + TALITOS_IMR_LO, TALITOS2_IMR_LO_INIT);
242dd3c0987SLEROY Christophe 	}
2439c4a7965SKim Phillips 
244fe5720e2SKim Phillips 	/* disable integrity check error interrupts (use writeback instead) */
245fe5720e2SKim Phillips 	if (priv->features & TALITOS_FTR_HW_AUTH_CHECK)
2465fa7fa14SLEROY Christophe 		setbits32(priv->reg_mdeu + TALITOS_EUICR_LO,
247fe5720e2SKim Phillips 		          TALITOS_MDEUICR_LO_ICE);
248fe5720e2SKim Phillips 
2499c4a7965SKim Phillips 	return 0;
2509c4a7965SKim Phillips }
2519c4a7965SKim Phillips 
2529c4a7965SKim Phillips /**
2539c4a7965SKim Phillips  * talitos_submit - submits a descriptor to the device for processing
2549c4a7965SKim Phillips  * @dev:	the SEC device to be used
2555228f0f7SKim Phillips  * @ch:		the SEC device channel to be used
2569c4a7965SKim Phillips  * @desc:	the descriptor to be processed by the device
2579c4a7965SKim Phillips  * @callback:	whom to call when processing is complete
2589c4a7965SKim Phillips  * @context:	a handle for use by caller (optional)
2599c4a7965SKim Phillips  *
2609c4a7965SKim Phillips  * desc must contain valid dma-mapped (bus physical) address pointers.
2619c4a7965SKim Phillips  * callback must check err and feedback in descriptor header
2629c4a7965SKim Phillips  * for device processing status.
2639c4a7965SKim Phillips  */
264865d5061SHoria Geanta int talitos_submit(struct device *dev, int ch, struct talitos_desc *desc,
2659c4a7965SKim Phillips 		   void (*callback)(struct device *dev,
2669c4a7965SKim Phillips 				    struct talitos_desc *desc,
2679c4a7965SKim Phillips 				    void *context, int error),
2689c4a7965SKim Phillips 		   void *context)
2699c4a7965SKim Phillips {
2709c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
2719c4a7965SKim Phillips 	struct talitos_request *request;
2725228f0f7SKim Phillips 	unsigned long flags;
2739c4a7965SKim Phillips 	int head;
2747d607c6aSLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
2759c4a7965SKim Phillips 
2764b992628SKim Phillips 	spin_lock_irqsave(&priv->chan[ch].head_lock, flags);
2779c4a7965SKim Phillips 
2784b992628SKim Phillips 	if (!atomic_inc_not_zero(&priv->chan[ch].submit_count)) {
279ec6644d6SKim Phillips 		/* h/w fifo is full */
2804b992628SKim Phillips 		spin_unlock_irqrestore(&priv->chan[ch].head_lock, flags);
2819c4a7965SKim Phillips 		return -EAGAIN;
2829c4a7965SKim Phillips 	}
2839c4a7965SKim Phillips 
2844b992628SKim Phillips 	head = priv->chan[ch].head;
2854b992628SKim Phillips 	request = &priv->chan[ch].fifo[head];
286ec6644d6SKim Phillips 
2879c4a7965SKim Phillips 	/* map descriptor and save caller data */
2887d607c6aSLEROY Christophe 	if (is_sec1) {
2897d607c6aSLEROY Christophe 		desc->hdr1 = desc->hdr;
2907d607c6aSLEROY Christophe 		desc->next_desc = 0;
2917d607c6aSLEROY Christophe 		request->dma_desc = dma_map_single(dev, &desc->hdr1,
2927d607c6aSLEROY Christophe 						   TALITOS_DESC_SIZE,
2939c4a7965SKim Phillips 						   DMA_BIDIRECTIONAL);
2947d607c6aSLEROY Christophe 	} else {
2957d607c6aSLEROY Christophe 		request->dma_desc = dma_map_single(dev, desc,
2967d607c6aSLEROY Christophe 						   TALITOS_DESC_SIZE,
2977d607c6aSLEROY Christophe 						   DMA_BIDIRECTIONAL);
2987d607c6aSLEROY Christophe 	}
2999c4a7965SKim Phillips 	request->callback = callback;
3009c4a7965SKim Phillips 	request->context = context;
3019c4a7965SKim Phillips 
3029c4a7965SKim Phillips 	/* increment fifo head */
3034b992628SKim Phillips 	priv->chan[ch].head = (priv->chan[ch].head + 1) & (priv->fifo_len - 1);
3049c4a7965SKim Phillips 
3059c4a7965SKim Phillips 	smp_wmb();
3069c4a7965SKim Phillips 	request->desc = desc;
3079c4a7965SKim Phillips 
3089c4a7965SKim Phillips 	/* GO! */
3099c4a7965SKim Phillips 	wmb();
310ad42d5fcSKim Phillips 	out_be32(priv->chan[ch].reg + TALITOS_FF,
311ad42d5fcSKim Phillips 		 upper_32_bits(request->dma_desc));
312ad42d5fcSKim Phillips 	out_be32(priv->chan[ch].reg + TALITOS_FF_LO,
313a752447aSKim Phillips 		 lower_32_bits(request->dma_desc));
3149c4a7965SKim Phillips 
3154b992628SKim Phillips 	spin_unlock_irqrestore(&priv->chan[ch].head_lock, flags);
3169c4a7965SKim Phillips 
3179c4a7965SKim Phillips 	return -EINPROGRESS;
3189c4a7965SKim Phillips }
319865d5061SHoria Geanta EXPORT_SYMBOL(talitos_submit);
3209c4a7965SKim Phillips 
3219c4a7965SKim Phillips /*
3229c4a7965SKim Phillips  * process what was done, notify callback of error if not
3239c4a7965SKim Phillips  */
3249c4a7965SKim Phillips static void flush_channel(struct device *dev, int ch, int error, int reset_ch)
3259c4a7965SKim Phillips {
3269c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
3279c4a7965SKim Phillips 	struct talitos_request *request, saved_req;
3289c4a7965SKim Phillips 	unsigned long flags;
3299c4a7965SKim Phillips 	int tail, status;
3307d607c6aSLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
3319c4a7965SKim Phillips 
3324b992628SKim Phillips 	spin_lock_irqsave(&priv->chan[ch].tail_lock, flags);
3339c4a7965SKim Phillips 
3344b992628SKim Phillips 	tail = priv->chan[ch].tail;
3354b992628SKim Phillips 	while (priv->chan[ch].fifo[tail].desc) {
3367d607c6aSLEROY Christophe 		__be32 hdr;
3377d607c6aSLEROY Christophe 
3384b992628SKim Phillips 		request = &priv->chan[ch].fifo[tail];
3399c4a7965SKim Phillips 
3409c4a7965SKim Phillips 		/* descriptors with their done bits set don't get the error */
3419c4a7965SKim Phillips 		rmb();
3427d607c6aSLEROY Christophe 		hdr = is_sec1 ? request->desc->hdr1 : request->desc->hdr;
3437d607c6aSLEROY Christophe 
3447d607c6aSLEROY Christophe 		if ((hdr & DESC_HDR_DONE) == DESC_HDR_DONE)
3459c4a7965SKim Phillips 			status = 0;
346ca38a814SLee Nipper 		else
3479c4a7965SKim Phillips 			if (!error)
3489c4a7965SKim Phillips 				break;
3499c4a7965SKim Phillips 			else
3509c4a7965SKim Phillips 				status = error;
3519c4a7965SKim Phillips 
3529c4a7965SKim Phillips 		dma_unmap_single(dev, request->dma_desc,
3537d607c6aSLEROY Christophe 				 TALITOS_DESC_SIZE,
354e938e465SKim Phillips 				 DMA_BIDIRECTIONAL);
3559c4a7965SKim Phillips 
3569c4a7965SKim Phillips 		/* copy entries so we can call callback outside lock */
3579c4a7965SKim Phillips 		saved_req.desc = request->desc;
3589c4a7965SKim Phillips 		saved_req.callback = request->callback;
3599c4a7965SKim Phillips 		saved_req.context = request->context;
3609c4a7965SKim Phillips 
3619c4a7965SKim Phillips 		/* release request entry in fifo */
3629c4a7965SKim Phillips 		smp_wmb();
3639c4a7965SKim Phillips 		request->desc = NULL;
3649c4a7965SKim Phillips 
3659c4a7965SKim Phillips 		/* increment fifo tail */
3664b992628SKim Phillips 		priv->chan[ch].tail = (tail + 1) & (priv->fifo_len - 1);
3679c4a7965SKim Phillips 
3684b992628SKim Phillips 		spin_unlock_irqrestore(&priv->chan[ch].tail_lock, flags);
369ec6644d6SKim Phillips 
3704b992628SKim Phillips 		atomic_dec(&priv->chan[ch].submit_count);
371ec6644d6SKim Phillips 
3729c4a7965SKim Phillips 		saved_req.callback(dev, saved_req.desc, saved_req.context,
3739c4a7965SKim Phillips 				   status);
3749c4a7965SKim Phillips 		/* channel may resume processing in single desc error case */
3759c4a7965SKim Phillips 		if (error && !reset_ch && status == error)
3769c4a7965SKim Phillips 			return;
3774b992628SKim Phillips 		spin_lock_irqsave(&priv->chan[ch].tail_lock, flags);
3784b992628SKim Phillips 		tail = priv->chan[ch].tail;
3799c4a7965SKim Phillips 	}
3809c4a7965SKim Phillips 
3814b992628SKim Phillips 	spin_unlock_irqrestore(&priv->chan[ch].tail_lock, flags);
3829c4a7965SKim Phillips }
3839c4a7965SKim Phillips 
3849c4a7965SKim Phillips /*
3859c4a7965SKim Phillips  * process completed requests for channels that have done status
3869c4a7965SKim Phillips  */
387dd3c0987SLEROY Christophe #define DEF_TALITOS1_DONE(name, ch_done_mask)				\
388dd3c0987SLEROY Christophe static void talitos1_done_##name(unsigned long data)			\
389dd3c0987SLEROY Christophe {									\
390dd3c0987SLEROY Christophe 	struct device *dev = (struct device *)data;			\
391dd3c0987SLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);		\
392dd3c0987SLEROY Christophe 	unsigned long flags;						\
393dd3c0987SLEROY Christophe 									\
394dd3c0987SLEROY Christophe 	if (ch_done_mask & 0x10000000)					\
395dd3c0987SLEROY Christophe 		flush_channel(dev, 0, 0, 0);			\
396dd3c0987SLEROY Christophe 	if (priv->num_channels == 1)					\
397dd3c0987SLEROY Christophe 		goto out;						\
398dd3c0987SLEROY Christophe 	if (ch_done_mask & 0x40000000)					\
399dd3c0987SLEROY Christophe 		flush_channel(dev, 1, 0, 0);			\
400dd3c0987SLEROY Christophe 	if (ch_done_mask & 0x00010000)					\
401dd3c0987SLEROY Christophe 		flush_channel(dev, 2, 0, 0);			\
402dd3c0987SLEROY Christophe 	if (ch_done_mask & 0x00040000)					\
403dd3c0987SLEROY Christophe 		flush_channel(dev, 3, 0, 0);			\
404dd3c0987SLEROY Christophe 									\
405dd3c0987SLEROY Christophe out:									\
406dd3c0987SLEROY Christophe 	/* At this point, all completed channels have been processed */	\
407dd3c0987SLEROY Christophe 	/* Unmask done interrupts for channels completed later on. */	\
408dd3c0987SLEROY Christophe 	spin_lock_irqsave(&priv->reg_lock, flags);			\
409dd3c0987SLEROY Christophe 	clrbits32(priv->reg + TALITOS_IMR, ch_done_mask);		\
410dd3c0987SLEROY Christophe 	clrbits32(priv->reg + TALITOS_IMR_LO, TALITOS1_IMR_LO_INIT);	\
411dd3c0987SLEROY Christophe 	spin_unlock_irqrestore(&priv->reg_lock, flags);			\
412dd3c0987SLEROY Christophe }
413dd3c0987SLEROY Christophe 
414dd3c0987SLEROY Christophe DEF_TALITOS1_DONE(4ch, TALITOS1_ISR_4CHDONE)
415dd3c0987SLEROY Christophe 
416dd3c0987SLEROY Christophe #define DEF_TALITOS2_DONE(name, ch_done_mask)				\
417dd3c0987SLEROY Christophe static void talitos2_done_##name(unsigned long data)			\
418c3e337f8SKim Phillips {									\
419c3e337f8SKim Phillips 	struct device *dev = (struct device *)data;			\
420c3e337f8SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);		\
421511d63cbSHoria Geanta 	unsigned long flags;						\
422c3e337f8SKim Phillips 									\
423c3e337f8SKim Phillips 	if (ch_done_mask & 1)						\
424c3e337f8SKim Phillips 		flush_channel(dev, 0, 0, 0);				\
425c3e337f8SKim Phillips 	if (priv->num_channels == 1)					\
426c3e337f8SKim Phillips 		goto out;						\
427c3e337f8SKim Phillips 	if (ch_done_mask & (1 << 2))					\
428c3e337f8SKim Phillips 		flush_channel(dev, 1, 0, 0);				\
429c3e337f8SKim Phillips 	if (ch_done_mask & (1 << 4))					\
430c3e337f8SKim Phillips 		flush_channel(dev, 2, 0, 0);				\
431c3e337f8SKim Phillips 	if (ch_done_mask & (1 << 6))					\
432c3e337f8SKim Phillips 		flush_channel(dev, 3, 0, 0);				\
433c3e337f8SKim Phillips 									\
434c3e337f8SKim Phillips out:									\
435c3e337f8SKim Phillips 	/* At this point, all completed channels have been processed */	\
436c3e337f8SKim Phillips 	/* Unmask done interrupts for channels completed later on. */	\
437511d63cbSHoria Geanta 	spin_lock_irqsave(&priv->reg_lock, flags);			\
438c3e337f8SKim Phillips 	setbits32(priv->reg + TALITOS_IMR, ch_done_mask);		\
439dd3c0987SLEROY Christophe 	setbits32(priv->reg + TALITOS_IMR_LO, TALITOS2_IMR_LO_INIT);	\
440511d63cbSHoria Geanta 	spin_unlock_irqrestore(&priv->reg_lock, flags);			\
4419c4a7965SKim Phillips }
442dd3c0987SLEROY Christophe 
443dd3c0987SLEROY Christophe DEF_TALITOS2_DONE(4ch, TALITOS2_ISR_4CHDONE)
444dd3c0987SLEROY Christophe DEF_TALITOS2_DONE(ch0_2, TALITOS2_ISR_CH_0_2_DONE)
445dd3c0987SLEROY Christophe DEF_TALITOS2_DONE(ch1_3, TALITOS2_ISR_CH_1_3_DONE)
4469c4a7965SKim Phillips 
4479c4a7965SKim Phillips /*
4489c4a7965SKim Phillips  * locate current (offending) descriptor
4499c4a7965SKim Phillips  */
4503e721aebSKim Phillips static u32 current_desc_hdr(struct device *dev, int ch)
4519c4a7965SKim Phillips {
4529c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
453b62ffd8cSHoria Geanta 	int tail, iter;
4549c4a7965SKim Phillips 	dma_addr_t cur_desc;
4559c4a7965SKim Phillips 
456b62ffd8cSHoria Geanta 	cur_desc = ((u64)in_be32(priv->chan[ch].reg + TALITOS_CDPR)) << 32;
457b62ffd8cSHoria Geanta 	cur_desc |= in_be32(priv->chan[ch].reg + TALITOS_CDPR_LO);
4589c4a7965SKim Phillips 
459b62ffd8cSHoria Geanta 	if (!cur_desc) {
460b62ffd8cSHoria Geanta 		dev_err(dev, "CDPR is NULL, giving up search for offending descriptor\n");
461b62ffd8cSHoria Geanta 		return 0;
462b62ffd8cSHoria Geanta 	}
463b62ffd8cSHoria Geanta 
464b62ffd8cSHoria Geanta 	tail = priv->chan[ch].tail;
465b62ffd8cSHoria Geanta 
466b62ffd8cSHoria Geanta 	iter = tail;
467b62ffd8cSHoria Geanta 	while (priv->chan[ch].fifo[iter].dma_desc != cur_desc) {
468b62ffd8cSHoria Geanta 		iter = (iter + 1) & (priv->fifo_len - 1);
469b62ffd8cSHoria Geanta 		if (iter == tail) {
4709c4a7965SKim Phillips 			dev_err(dev, "couldn't locate current descriptor\n");
4713e721aebSKim Phillips 			return 0;
4729c4a7965SKim Phillips 		}
4739c4a7965SKim Phillips 	}
4749c4a7965SKim Phillips 
475b62ffd8cSHoria Geanta 	return priv->chan[ch].fifo[iter].desc->hdr;
4769c4a7965SKim Phillips }
4779c4a7965SKim Phillips 
4789c4a7965SKim Phillips /*
4799c4a7965SKim Phillips  * user diagnostics; report root cause of error based on execution unit status
4809c4a7965SKim Phillips  */
4813e721aebSKim Phillips static void report_eu_error(struct device *dev, int ch, u32 desc_hdr)
4829c4a7965SKim Phillips {
4839c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
4849c4a7965SKim Phillips 	int i;
4859c4a7965SKim Phillips 
4863e721aebSKim Phillips 	if (!desc_hdr)
487ad42d5fcSKim Phillips 		desc_hdr = in_be32(priv->chan[ch].reg + TALITOS_DESCBUF);
4883e721aebSKim Phillips 
4893e721aebSKim Phillips 	switch (desc_hdr & DESC_HDR_SEL0_MASK) {
4909c4a7965SKim Phillips 	case DESC_HDR_SEL0_AFEU:
4919c4a7965SKim Phillips 		dev_err(dev, "AFEUISR 0x%08x_%08x\n",
4925fa7fa14SLEROY Christophe 			in_be32(priv->reg_afeu + TALITOS_EUISR),
4935fa7fa14SLEROY Christophe 			in_be32(priv->reg_afeu + TALITOS_EUISR_LO));
4949c4a7965SKim Phillips 		break;
4959c4a7965SKim Phillips 	case DESC_HDR_SEL0_DEU:
4969c4a7965SKim Phillips 		dev_err(dev, "DEUISR 0x%08x_%08x\n",
4975fa7fa14SLEROY Christophe 			in_be32(priv->reg_deu + TALITOS_EUISR),
4985fa7fa14SLEROY Christophe 			in_be32(priv->reg_deu + TALITOS_EUISR_LO));
4999c4a7965SKim Phillips 		break;
5009c4a7965SKim Phillips 	case DESC_HDR_SEL0_MDEUA:
5019c4a7965SKim Phillips 	case DESC_HDR_SEL0_MDEUB:
5029c4a7965SKim Phillips 		dev_err(dev, "MDEUISR 0x%08x_%08x\n",
5035fa7fa14SLEROY Christophe 			in_be32(priv->reg_mdeu + TALITOS_EUISR),
5045fa7fa14SLEROY Christophe 			in_be32(priv->reg_mdeu + TALITOS_EUISR_LO));
5059c4a7965SKim Phillips 		break;
5069c4a7965SKim Phillips 	case DESC_HDR_SEL0_RNG:
5079c4a7965SKim Phillips 		dev_err(dev, "RNGUISR 0x%08x_%08x\n",
5085fa7fa14SLEROY Christophe 			in_be32(priv->reg_rngu + TALITOS_ISR),
5095fa7fa14SLEROY Christophe 			in_be32(priv->reg_rngu + TALITOS_ISR_LO));
5109c4a7965SKim Phillips 		break;
5119c4a7965SKim Phillips 	case DESC_HDR_SEL0_PKEU:
5129c4a7965SKim Phillips 		dev_err(dev, "PKEUISR 0x%08x_%08x\n",
5135fa7fa14SLEROY Christophe 			in_be32(priv->reg_pkeu + TALITOS_EUISR),
5145fa7fa14SLEROY Christophe 			in_be32(priv->reg_pkeu + TALITOS_EUISR_LO));
5159c4a7965SKim Phillips 		break;
5169c4a7965SKim Phillips 	case DESC_HDR_SEL0_AESU:
5179c4a7965SKim Phillips 		dev_err(dev, "AESUISR 0x%08x_%08x\n",
5185fa7fa14SLEROY Christophe 			in_be32(priv->reg_aesu + TALITOS_EUISR),
5195fa7fa14SLEROY Christophe 			in_be32(priv->reg_aesu + TALITOS_EUISR_LO));
5209c4a7965SKim Phillips 		break;
5219c4a7965SKim Phillips 	case DESC_HDR_SEL0_CRCU:
5229c4a7965SKim Phillips 		dev_err(dev, "CRCUISR 0x%08x_%08x\n",
5235fa7fa14SLEROY Christophe 			in_be32(priv->reg_crcu + TALITOS_EUISR),
5245fa7fa14SLEROY Christophe 			in_be32(priv->reg_crcu + TALITOS_EUISR_LO));
5259c4a7965SKim Phillips 		break;
5269c4a7965SKim Phillips 	case DESC_HDR_SEL0_KEU:
5279c4a7965SKim Phillips 		dev_err(dev, "KEUISR 0x%08x_%08x\n",
5285fa7fa14SLEROY Christophe 			in_be32(priv->reg_pkeu + TALITOS_EUISR),
5295fa7fa14SLEROY Christophe 			in_be32(priv->reg_pkeu + TALITOS_EUISR_LO));
5309c4a7965SKim Phillips 		break;
5319c4a7965SKim Phillips 	}
5329c4a7965SKim Phillips 
5333e721aebSKim Phillips 	switch (desc_hdr & DESC_HDR_SEL1_MASK) {
5349c4a7965SKim Phillips 	case DESC_HDR_SEL1_MDEUA:
5359c4a7965SKim Phillips 	case DESC_HDR_SEL1_MDEUB:
5369c4a7965SKim Phillips 		dev_err(dev, "MDEUISR 0x%08x_%08x\n",
5375fa7fa14SLEROY Christophe 			in_be32(priv->reg_mdeu + TALITOS_EUISR),
5385fa7fa14SLEROY Christophe 			in_be32(priv->reg_mdeu + TALITOS_EUISR_LO));
5399c4a7965SKim Phillips 		break;
5409c4a7965SKim Phillips 	case DESC_HDR_SEL1_CRCU:
5419c4a7965SKim Phillips 		dev_err(dev, "CRCUISR 0x%08x_%08x\n",
5425fa7fa14SLEROY Christophe 			in_be32(priv->reg_crcu + TALITOS_EUISR),
5435fa7fa14SLEROY Christophe 			in_be32(priv->reg_crcu + TALITOS_EUISR_LO));
5449c4a7965SKim Phillips 		break;
5459c4a7965SKim Phillips 	}
5469c4a7965SKim Phillips 
5479c4a7965SKim Phillips 	for (i = 0; i < 8; i++)
5489c4a7965SKim Phillips 		dev_err(dev, "DESCBUF 0x%08x_%08x\n",
549ad42d5fcSKim Phillips 			in_be32(priv->chan[ch].reg + TALITOS_DESCBUF + 8*i),
550ad42d5fcSKim Phillips 			in_be32(priv->chan[ch].reg + TALITOS_DESCBUF_LO + 8*i));
5519c4a7965SKim Phillips }
5529c4a7965SKim Phillips 
5539c4a7965SKim Phillips /*
5549c4a7965SKim Phillips  * recover from error interrupts
5559c4a7965SKim Phillips  */
5565e718a09SKim Phillips static void talitos_error(struct device *dev, u32 isr, u32 isr_lo)
5579c4a7965SKim Phillips {
5589c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
5599c4a7965SKim Phillips 	unsigned int timeout = TALITOS_TIMEOUT;
560dd3c0987SLEROY Christophe 	int ch, error, reset_dev = 0;
56142e8b0d7SHoria Geant? 	u32 v_lo;
562dd3c0987SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
563dd3c0987SLEROY Christophe 	int reset_ch = is_sec1 ? 1 : 0; /* only SEC2 supports continuation */
5649c4a7965SKim Phillips 
5659c4a7965SKim Phillips 	for (ch = 0; ch < priv->num_channels; ch++) {
5669c4a7965SKim Phillips 		/* skip channels without errors */
567dd3c0987SLEROY Christophe 		if (is_sec1) {
568dd3c0987SLEROY Christophe 			/* bits 29, 31, 17, 19 */
569dd3c0987SLEROY Christophe 			if (!(isr & (1 << (29 + (ch & 1) * 2 - (ch & 2) * 6))))
570dd3c0987SLEROY Christophe 				continue;
571dd3c0987SLEROY Christophe 		} else {
5729c4a7965SKim Phillips 			if (!(isr & (1 << (ch * 2 + 1))))
5739c4a7965SKim Phillips 				continue;
574dd3c0987SLEROY Christophe 		}
5759c4a7965SKim Phillips 
5769c4a7965SKim Phillips 		error = -EINVAL;
5779c4a7965SKim Phillips 
578ad42d5fcSKim Phillips 		v_lo = in_be32(priv->chan[ch].reg + TALITOS_CCPSR_LO);
5799c4a7965SKim Phillips 
5809c4a7965SKim Phillips 		if (v_lo & TALITOS_CCPSR_LO_DOF) {
5819c4a7965SKim Phillips 			dev_err(dev, "double fetch fifo overflow error\n");
5829c4a7965SKim Phillips 			error = -EAGAIN;
5839c4a7965SKim Phillips 			reset_ch = 1;
5849c4a7965SKim Phillips 		}
5859c4a7965SKim Phillips 		if (v_lo & TALITOS_CCPSR_LO_SOF) {
5869c4a7965SKim Phillips 			/* h/w dropped descriptor */
5879c4a7965SKim Phillips 			dev_err(dev, "single fetch fifo overflow error\n");
5889c4a7965SKim Phillips 			error = -EAGAIN;
5899c4a7965SKim Phillips 		}
5909c4a7965SKim Phillips 		if (v_lo & TALITOS_CCPSR_LO_MDTE)
5919c4a7965SKim Phillips 			dev_err(dev, "master data transfer error\n");
5929c4a7965SKim Phillips 		if (v_lo & TALITOS_CCPSR_LO_SGDLZ)
5934d9b3a5bSColin Ian King 			dev_err(dev, is_sec1 ? "pointer not complete error\n"
594dd3c0987SLEROY Christophe 					     : "s/g data length zero error\n");
5959c4a7965SKim Phillips 		if (v_lo & TALITOS_CCPSR_LO_FPZ)
596dd3c0987SLEROY Christophe 			dev_err(dev, is_sec1 ? "parity error\n"
597dd3c0987SLEROY Christophe 					     : "fetch pointer zero error\n");
5989c4a7965SKim Phillips 		if (v_lo & TALITOS_CCPSR_LO_IDH)
5999c4a7965SKim Phillips 			dev_err(dev, "illegal descriptor header error\n");
6009c4a7965SKim Phillips 		if (v_lo & TALITOS_CCPSR_LO_IEU)
601dd3c0987SLEROY Christophe 			dev_err(dev, is_sec1 ? "static assignment error\n"
602dd3c0987SLEROY Christophe 					     : "invalid exec unit error\n");
6039c4a7965SKim Phillips 		if (v_lo & TALITOS_CCPSR_LO_EU)
6043e721aebSKim Phillips 			report_eu_error(dev, ch, current_desc_hdr(dev, ch));
605dd3c0987SLEROY Christophe 		if (!is_sec1) {
6069c4a7965SKim Phillips 			if (v_lo & TALITOS_CCPSR_LO_GB)
6079c4a7965SKim Phillips 				dev_err(dev, "gather boundary error\n");
6089c4a7965SKim Phillips 			if (v_lo & TALITOS_CCPSR_LO_GRL)
6099c4a7965SKim Phillips 				dev_err(dev, "gather return/length error\n");
6109c4a7965SKim Phillips 			if (v_lo & TALITOS_CCPSR_LO_SB)
6119c4a7965SKim Phillips 				dev_err(dev, "scatter boundary error\n");
6129c4a7965SKim Phillips 			if (v_lo & TALITOS_CCPSR_LO_SRL)
6139c4a7965SKim Phillips 				dev_err(dev, "scatter return/length error\n");
614dd3c0987SLEROY Christophe 		}
6159c4a7965SKim Phillips 
6169c4a7965SKim Phillips 		flush_channel(dev, ch, error, reset_ch);
6179c4a7965SKim Phillips 
6189c4a7965SKim Phillips 		if (reset_ch) {
6199c4a7965SKim Phillips 			reset_channel(dev, ch);
6209c4a7965SKim Phillips 		} else {
621ad42d5fcSKim Phillips 			setbits32(priv->chan[ch].reg + TALITOS_CCCR,
622dd3c0987SLEROY Christophe 				  TALITOS2_CCCR_CONT);
623ad42d5fcSKim Phillips 			setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO, 0);
624ad42d5fcSKim Phillips 			while ((in_be32(priv->chan[ch].reg + TALITOS_CCCR) &
625dd3c0987SLEROY Christophe 			       TALITOS2_CCCR_CONT) && --timeout)
6269c4a7965SKim Phillips 				cpu_relax();
6279c4a7965SKim Phillips 			if (timeout == 0) {
6289c4a7965SKim Phillips 				dev_err(dev, "failed to restart channel %d\n",
6299c4a7965SKim Phillips 					ch);
6309c4a7965SKim Phillips 				reset_dev = 1;
6319c4a7965SKim Phillips 			}
6329c4a7965SKim Phillips 		}
6339c4a7965SKim Phillips 	}
634dd3c0987SLEROY Christophe 	if (reset_dev || (is_sec1 && isr & ~TALITOS1_ISR_4CHERR) ||
635dd3c0987SLEROY Christophe 	    (!is_sec1 && isr & ~TALITOS2_ISR_4CHERR) || isr_lo) {
636dd3c0987SLEROY Christophe 		if (is_sec1 && (isr_lo & TALITOS1_ISR_TEA_ERR))
637dd3c0987SLEROY Christophe 			dev_err(dev, "TEA error: ISR 0x%08x_%08x\n",
638dd3c0987SLEROY Christophe 				isr, isr_lo);
639dd3c0987SLEROY Christophe 		else
640dd3c0987SLEROY Christophe 			dev_err(dev, "done overflow, internal time out, or "
641dd3c0987SLEROY Christophe 				"rngu error: ISR 0x%08x_%08x\n", isr, isr_lo);
6429c4a7965SKim Phillips 
6439c4a7965SKim Phillips 		/* purge request queues */
6449c4a7965SKim Phillips 		for (ch = 0; ch < priv->num_channels; ch++)
6459c4a7965SKim Phillips 			flush_channel(dev, ch, -EIO, 1);
6469c4a7965SKim Phillips 
6479c4a7965SKim Phillips 		/* reset and reinitialize the device */
6489c4a7965SKim Phillips 		init_device(dev);
6499c4a7965SKim Phillips 	}
6509c4a7965SKim Phillips }
6519c4a7965SKim Phillips 
652dd3c0987SLEROY Christophe #define DEF_TALITOS1_INTERRUPT(name, ch_done_mask, ch_err_mask, tlet)	       \
653dd3c0987SLEROY Christophe static irqreturn_t talitos1_interrupt_##name(int irq, void *data)	       \
654dd3c0987SLEROY Christophe {									       \
655dd3c0987SLEROY Christophe 	struct device *dev = data;					       \
656dd3c0987SLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);		       \
657dd3c0987SLEROY Christophe 	u32 isr, isr_lo;						       \
658dd3c0987SLEROY Christophe 	unsigned long flags;						       \
659dd3c0987SLEROY Christophe 									       \
660dd3c0987SLEROY Christophe 	spin_lock_irqsave(&priv->reg_lock, flags);			       \
661dd3c0987SLEROY Christophe 	isr = in_be32(priv->reg + TALITOS_ISR);				       \
662dd3c0987SLEROY Christophe 	isr_lo = in_be32(priv->reg + TALITOS_ISR_LO);			       \
663dd3c0987SLEROY Christophe 	/* Acknowledge interrupt */					       \
664dd3c0987SLEROY Christophe 	out_be32(priv->reg + TALITOS_ICR, isr & (ch_done_mask | ch_err_mask)); \
665dd3c0987SLEROY Christophe 	out_be32(priv->reg + TALITOS_ICR_LO, isr_lo);			       \
666dd3c0987SLEROY Christophe 									       \
667dd3c0987SLEROY Christophe 	if (unlikely(isr & ch_err_mask || isr_lo & TALITOS1_IMR_LO_INIT)) {    \
668dd3c0987SLEROY Christophe 		spin_unlock_irqrestore(&priv->reg_lock, flags);		       \
669dd3c0987SLEROY Christophe 		talitos_error(dev, isr & ch_err_mask, isr_lo);		       \
670dd3c0987SLEROY Christophe 	}								       \
671dd3c0987SLEROY Christophe 	else {								       \
672dd3c0987SLEROY Christophe 		if (likely(isr & ch_done_mask)) {			       \
673dd3c0987SLEROY Christophe 			/* mask further done interrupts. */		       \
674dd3c0987SLEROY Christophe 			setbits32(priv->reg + TALITOS_IMR, ch_done_mask);      \
675dd3c0987SLEROY Christophe 			/* done_task will unmask done interrupts at exit */    \
676dd3c0987SLEROY Christophe 			tasklet_schedule(&priv->done_task[tlet]);	       \
677dd3c0987SLEROY Christophe 		}							       \
678dd3c0987SLEROY Christophe 		spin_unlock_irqrestore(&priv->reg_lock, flags);		       \
679dd3c0987SLEROY Christophe 	}								       \
680dd3c0987SLEROY Christophe 									       \
681dd3c0987SLEROY Christophe 	return (isr & (ch_done_mask | ch_err_mask) || isr_lo) ? IRQ_HANDLED :  \
682dd3c0987SLEROY Christophe 								IRQ_NONE;      \
683dd3c0987SLEROY Christophe }
684dd3c0987SLEROY Christophe 
685dd3c0987SLEROY Christophe DEF_TALITOS1_INTERRUPT(4ch, TALITOS1_ISR_4CHDONE, TALITOS1_ISR_4CHERR, 0)
686dd3c0987SLEROY Christophe 
687dd3c0987SLEROY Christophe #define DEF_TALITOS2_INTERRUPT(name, ch_done_mask, ch_err_mask, tlet)	       \
688dd3c0987SLEROY Christophe static irqreturn_t talitos2_interrupt_##name(int irq, void *data)	       \
689c3e337f8SKim Phillips {									       \
690c3e337f8SKim Phillips 	struct device *dev = data;					       \
691c3e337f8SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);		       \
692c3e337f8SKim Phillips 	u32 isr, isr_lo;						       \
693511d63cbSHoria Geanta 	unsigned long flags;						       \
694c3e337f8SKim Phillips 									       \
695511d63cbSHoria Geanta 	spin_lock_irqsave(&priv->reg_lock, flags);			       \
696c3e337f8SKim Phillips 	isr = in_be32(priv->reg + TALITOS_ISR);				       \
697c3e337f8SKim Phillips 	isr_lo = in_be32(priv->reg + TALITOS_ISR_LO);			       \
698c3e337f8SKim Phillips 	/* Acknowledge interrupt */					       \
699c3e337f8SKim Phillips 	out_be32(priv->reg + TALITOS_ICR, isr & (ch_done_mask | ch_err_mask)); \
700c3e337f8SKim Phillips 	out_be32(priv->reg + TALITOS_ICR_LO, isr_lo);			       \
701c3e337f8SKim Phillips 									       \
702511d63cbSHoria Geanta 	if (unlikely(isr & ch_err_mask || isr_lo)) {			       \
703511d63cbSHoria Geanta 		spin_unlock_irqrestore(&priv->reg_lock, flags);		       \
704511d63cbSHoria Geanta 		talitos_error(dev, isr & ch_err_mask, isr_lo);		       \
705511d63cbSHoria Geanta 	}								       \
706511d63cbSHoria Geanta 	else {								       \
707c3e337f8SKim Phillips 		if (likely(isr & ch_done_mask)) {			       \
708c3e337f8SKim Phillips 			/* mask further done interrupts. */		       \
709c3e337f8SKim Phillips 			clrbits32(priv->reg + TALITOS_IMR, ch_done_mask);      \
710c3e337f8SKim Phillips 			/* done_task will unmask done interrupts at exit */    \
711c3e337f8SKim Phillips 			tasklet_schedule(&priv->done_task[tlet]);	       \
712c3e337f8SKim Phillips 		}							       \
713511d63cbSHoria Geanta 		spin_unlock_irqrestore(&priv->reg_lock, flags);		       \
714511d63cbSHoria Geanta 	}								       \
715c3e337f8SKim Phillips 									       \
716c3e337f8SKim Phillips 	return (isr & (ch_done_mask | ch_err_mask) || isr_lo) ? IRQ_HANDLED :  \
717c3e337f8SKim Phillips 								IRQ_NONE;      \
7181c2e8811SLee Nipper }
719dd3c0987SLEROY Christophe 
720dd3c0987SLEROY Christophe DEF_TALITOS2_INTERRUPT(4ch, TALITOS2_ISR_4CHDONE, TALITOS2_ISR_4CHERR, 0)
721dd3c0987SLEROY Christophe DEF_TALITOS2_INTERRUPT(ch0_2, TALITOS2_ISR_CH_0_2_DONE, TALITOS2_ISR_CH_0_2_ERR,
722dd3c0987SLEROY Christophe 		       0)
723dd3c0987SLEROY Christophe DEF_TALITOS2_INTERRUPT(ch1_3, TALITOS2_ISR_CH_1_3_DONE, TALITOS2_ISR_CH_1_3_ERR,
724dd3c0987SLEROY Christophe 		       1)
7259c4a7965SKim Phillips 
7269c4a7965SKim Phillips /*
7279c4a7965SKim Phillips  * hwrng
7289c4a7965SKim Phillips  */
7299c4a7965SKim Phillips static int talitos_rng_data_present(struct hwrng *rng, int wait)
7309c4a7965SKim Phillips {
7319c4a7965SKim Phillips 	struct device *dev = (struct device *)rng->priv;
7329c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
7339c4a7965SKim Phillips 	u32 ofl;
7349c4a7965SKim Phillips 	int i;
7359c4a7965SKim Phillips 
7369c4a7965SKim Phillips 	for (i = 0; i < 20; i++) {
7375fa7fa14SLEROY Christophe 		ofl = in_be32(priv->reg_rngu + TALITOS_EUSR_LO) &
7389c4a7965SKim Phillips 		      TALITOS_RNGUSR_LO_OFL;
7399c4a7965SKim Phillips 		if (ofl || !wait)
7409c4a7965SKim Phillips 			break;
7419c4a7965SKim Phillips 		udelay(10);
7429c4a7965SKim Phillips 	}
7439c4a7965SKim Phillips 
7449c4a7965SKim Phillips 	return !!ofl;
7459c4a7965SKim Phillips }
7469c4a7965SKim Phillips 
7479c4a7965SKim Phillips static int talitos_rng_data_read(struct hwrng *rng, u32 *data)
7489c4a7965SKim Phillips {
7499c4a7965SKim Phillips 	struct device *dev = (struct device *)rng->priv;
7509c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
7519c4a7965SKim Phillips 
7529c4a7965SKim Phillips 	/* rng fifo requires 64-bit accesses */
7535fa7fa14SLEROY Christophe 	*data = in_be32(priv->reg_rngu + TALITOS_EU_FIFO);
7545fa7fa14SLEROY Christophe 	*data = in_be32(priv->reg_rngu + TALITOS_EU_FIFO_LO);
7559c4a7965SKim Phillips 
7569c4a7965SKim Phillips 	return sizeof(u32);
7579c4a7965SKim Phillips }
7589c4a7965SKim Phillips 
7599c4a7965SKim Phillips static int talitos_rng_init(struct hwrng *rng)
7609c4a7965SKim Phillips {
7619c4a7965SKim Phillips 	struct device *dev = (struct device *)rng->priv;
7629c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
7639c4a7965SKim Phillips 	unsigned int timeout = TALITOS_TIMEOUT;
7649c4a7965SKim Phillips 
7655fa7fa14SLEROY Christophe 	setbits32(priv->reg_rngu + TALITOS_EURCR_LO, TALITOS_RNGURCR_LO_SR);
7665fa7fa14SLEROY Christophe 	while (!(in_be32(priv->reg_rngu + TALITOS_EUSR_LO)
7675fa7fa14SLEROY Christophe 		 & TALITOS_RNGUSR_LO_RD)
7689c4a7965SKim Phillips 	       && --timeout)
7699c4a7965SKim Phillips 		cpu_relax();
7709c4a7965SKim Phillips 	if (timeout == 0) {
7719c4a7965SKim Phillips 		dev_err(dev, "failed to reset rng hw\n");
7729c4a7965SKim Phillips 		return -ENODEV;
7739c4a7965SKim Phillips 	}
7749c4a7965SKim Phillips 
7759c4a7965SKim Phillips 	/* start generating */
7765fa7fa14SLEROY Christophe 	setbits32(priv->reg_rngu + TALITOS_EUDSR_LO, 0);
7779c4a7965SKim Phillips 
7789c4a7965SKim Phillips 	return 0;
7799c4a7965SKim Phillips }
7809c4a7965SKim Phillips 
7819c4a7965SKim Phillips static int talitos_register_rng(struct device *dev)
7829c4a7965SKim Phillips {
7839c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
78435a3bb3dSAaron Sierra 	int err;
7859c4a7965SKim Phillips 
7869c4a7965SKim Phillips 	priv->rng.name		= dev_driver_string(dev),
7879c4a7965SKim Phillips 	priv->rng.init		= talitos_rng_init,
7889c4a7965SKim Phillips 	priv->rng.data_present	= talitos_rng_data_present,
7899c4a7965SKim Phillips 	priv->rng.data_read	= talitos_rng_data_read,
7909c4a7965SKim Phillips 	priv->rng.priv		= (unsigned long)dev;
7919c4a7965SKim Phillips 
79235a3bb3dSAaron Sierra 	err = hwrng_register(&priv->rng);
79335a3bb3dSAaron Sierra 	if (!err)
79435a3bb3dSAaron Sierra 		priv->rng_registered = true;
79535a3bb3dSAaron Sierra 
79635a3bb3dSAaron Sierra 	return err;
7979c4a7965SKim Phillips }
7989c4a7965SKim Phillips 
7999c4a7965SKim Phillips static void talitos_unregister_rng(struct device *dev)
8009c4a7965SKim Phillips {
8019c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
8029c4a7965SKim Phillips 
80335a3bb3dSAaron Sierra 	if (!priv->rng_registered)
80435a3bb3dSAaron Sierra 		return;
80535a3bb3dSAaron Sierra 
8069c4a7965SKim Phillips 	hwrng_unregister(&priv->rng);
80735a3bb3dSAaron Sierra 	priv->rng_registered = false;
8089c4a7965SKim Phillips }
8099c4a7965SKim Phillips 
8109c4a7965SKim Phillips /*
8119c4a7965SKim Phillips  * crypto alg
8129c4a7965SKim Phillips  */
8139c4a7965SKim Phillips #define TALITOS_CRA_PRIORITY		3000
8147405c8d7SLEROY Christophe /*
8157405c8d7SLEROY Christophe  * Defines a priority for doing AEAD with descriptors type
8167405c8d7SLEROY Christophe  * HMAC_SNOOP_NO_AFEA (HSNA) instead of type IPSEC_ESP
8177405c8d7SLEROY Christophe  */
8187405c8d7SLEROY Christophe #define TALITOS_CRA_PRIORITY_AEAD_HSNA	(TALITOS_CRA_PRIORITY - 1)
81903d2c511SMartin Hicks #define TALITOS_MAX_KEY_SIZE		(AES_MAX_KEY_SIZE + SHA512_BLOCK_SIZE)
8203952f17eSLee Nipper #define TALITOS_MAX_IV_LENGTH		16 /* max of AES_BLOCK_SIZE, DES3_EDE_BLOCK_SIZE */
82170bcaca7SLee Nipper 
8229c4a7965SKim Phillips struct talitos_ctx {
8239c4a7965SKim Phillips 	struct device *dev;
8245228f0f7SKim Phillips 	int ch;
8259c4a7965SKim Phillips 	__be32 desc_hdr_template;
8269c4a7965SKim Phillips 	u8 key[TALITOS_MAX_KEY_SIZE];
82770bcaca7SLee Nipper 	u8 iv[TALITOS_MAX_IV_LENGTH];
8289c4a7965SKim Phillips 	unsigned int keylen;
8299c4a7965SKim Phillips 	unsigned int enckeylen;
8309c4a7965SKim Phillips 	unsigned int authkeylen;
8319c4a7965SKim Phillips };
8329c4a7965SKim Phillips 
833497f2e6bSLee Nipper #define HASH_MAX_BLOCK_SIZE		SHA512_BLOCK_SIZE
834497f2e6bSLee Nipper #define TALITOS_MDEU_MAX_CONTEXT_SIZE	TALITOS_MDEU_CONTEXT_SIZE_SHA384_SHA512
835497f2e6bSLee Nipper 
836497f2e6bSLee Nipper struct talitos_ahash_req_ctx {
83760f208d7SKim Phillips 	u32 hw_context[TALITOS_MDEU_MAX_CONTEXT_SIZE / sizeof(u32)];
838497f2e6bSLee Nipper 	unsigned int hw_context_size;
839497f2e6bSLee Nipper 	u8 buf[HASH_MAX_BLOCK_SIZE];
840497f2e6bSLee Nipper 	u8 bufnext[HASH_MAX_BLOCK_SIZE];
84160f208d7SKim Phillips 	unsigned int swinit;
842497f2e6bSLee Nipper 	unsigned int first;
843497f2e6bSLee Nipper 	unsigned int last;
844497f2e6bSLee Nipper 	unsigned int to_hash_later;
84542e8b0d7SHoria Geant? 	unsigned int nbuf;
846497f2e6bSLee Nipper 	struct scatterlist bufsl[2];
847497f2e6bSLee Nipper 	struct scatterlist *psrc;
848497f2e6bSLee Nipper };
849497f2e6bSLee Nipper 
8503639ca84SHoria Geant? struct talitos_export_state {
8513639ca84SHoria Geant? 	u32 hw_context[TALITOS_MDEU_MAX_CONTEXT_SIZE / sizeof(u32)];
8523639ca84SHoria Geant? 	u8 buf[HASH_MAX_BLOCK_SIZE];
8533639ca84SHoria Geant? 	unsigned int swinit;
8543639ca84SHoria Geant? 	unsigned int first;
8553639ca84SHoria Geant? 	unsigned int last;
8563639ca84SHoria Geant? 	unsigned int to_hash_later;
8573639ca84SHoria Geant? 	unsigned int nbuf;
8583639ca84SHoria Geant? };
8593639ca84SHoria Geant? 
86056af8cd4SLee Nipper static int aead_setkey(struct crypto_aead *authenc,
8619c4a7965SKim Phillips 		       const u8 *key, unsigned int keylen)
8629c4a7965SKim Phillips {
8639c4a7965SKim Phillips 	struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
864c306a98dSMathias Krause 	struct crypto_authenc_keys keys;
8659c4a7965SKim Phillips 
866c306a98dSMathias Krause 	if (crypto_authenc_extractkeys(&keys, key, keylen) != 0)
8679c4a7965SKim Phillips 		goto badkey;
8689c4a7965SKim Phillips 
869c306a98dSMathias Krause 	if (keys.authkeylen + keys.enckeylen > TALITOS_MAX_KEY_SIZE)
8709c4a7965SKim Phillips 		goto badkey;
8719c4a7965SKim Phillips 
872c306a98dSMathias Krause 	memcpy(ctx->key, keys.authkey, keys.authkeylen);
873c306a98dSMathias Krause 	memcpy(&ctx->key[keys.authkeylen], keys.enckey, keys.enckeylen);
8749c4a7965SKim Phillips 
875c306a98dSMathias Krause 	ctx->keylen = keys.authkeylen + keys.enckeylen;
876c306a98dSMathias Krause 	ctx->enckeylen = keys.enckeylen;
877c306a98dSMathias Krause 	ctx->authkeylen = keys.authkeylen;
8789c4a7965SKim Phillips 
8799c4a7965SKim Phillips 	return 0;
8809c4a7965SKim Phillips 
8819c4a7965SKim Phillips badkey:
8829c4a7965SKim Phillips 	crypto_aead_set_flags(authenc, CRYPTO_TFM_RES_BAD_KEY_LEN);
8839c4a7965SKim Phillips 	return -EINVAL;
8849c4a7965SKim Phillips }
8859c4a7965SKim Phillips 
8869c4a7965SKim Phillips /*
88756af8cd4SLee Nipper  * talitos_edesc - s/w-extended descriptor
8889c4a7965SKim Phillips  * @src_nents: number of segments in input scatterlist
8899c4a7965SKim Phillips  * @dst_nents: number of segments in output scatterlist
890aeb4c132SHerbert Xu  * @icv_ool: whether ICV is out-of-line
89179fd31d3SHoria Geanta  * @iv_dma: dma address of iv for checking continuity and link table
8929c4a7965SKim Phillips  * @dma_len: length of dma mapped link_tbl space
8936f65f6acSLEROY Christophe  * @dma_link_tbl: bus physical address of link_tbl/buf
8949c4a7965SKim Phillips  * @desc: h/w descriptor
8956f65f6acSLEROY Christophe  * @link_tbl: input and output h/w link tables (if {src,dst}_nents > 1) (SEC2)
8966f65f6acSLEROY Christophe  * @buf: input and output buffeur (if {src,dst}_nents > 1) (SEC1)
8979c4a7965SKim Phillips  *
8989c4a7965SKim Phillips  * if decrypting (with authcheck), or either one of src_nents or dst_nents
8999c4a7965SKim Phillips  * is greater than 1, an integrity check value is concatenated to the end
9009c4a7965SKim Phillips  * of link_tbl data
9019c4a7965SKim Phillips  */
90256af8cd4SLee Nipper struct talitos_edesc {
9039c4a7965SKim Phillips 	int src_nents;
9049c4a7965SKim Phillips 	int dst_nents;
905aeb4c132SHerbert Xu 	bool icv_ool;
90679fd31d3SHoria Geanta 	dma_addr_t iv_dma;
9079c4a7965SKim Phillips 	int dma_len;
9089c4a7965SKim Phillips 	dma_addr_t dma_link_tbl;
9099c4a7965SKim Phillips 	struct talitos_desc desc;
9106f65f6acSLEROY Christophe 	union {
9119c4a7965SKim Phillips 		struct talitos_ptr link_tbl[0];
9126f65f6acSLEROY Christophe 		u8 buf[0];
9136f65f6acSLEROY Christophe 	};
9149c4a7965SKim Phillips };
9159c4a7965SKim Phillips 
9164de9d0b5SLee Nipper static void talitos_sg_unmap(struct device *dev,
9174de9d0b5SLee Nipper 			     struct talitos_edesc *edesc,
9184de9d0b5SLee Nipper 			     struct scatterlist *src,
9196a1e8d14SLEROY Christophe 			     struct scatterlist *dst,
9206a1e8d14SLEROY Christophe 			     unsigned int len, unsigned int offset)
921246a87cdSLEROY Christophe {
922246a87cdSLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
923246a87cdSLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
9246a1e8d14SLEROY Christophe 	unsigned int src_nents = edesc->src_nents ? : 1;
9256a1e8d14SLEROY Christophe 	unsigned int dst_nents = edesc->dst_nents ? : 1;
926246a87cdSLEROY Christophe 
9276a1e8d14SLEROY Christophe 	if (is_sec1 && dst && dst_nents > 1) {
9286a1e8d14SLEROY Christophe 		dma_sync_single_for_device(dev, edesc->dma_link_tbl + offset,
929246a87cdSLEROY Christophe 					   len, DMA_FROM_DEVICE);
9306a1e8d14SLEROY Christophe 		sg_pcopy_from_buffer(dst, dst_nents, edesc->buf + offset, len,
9316a1e8d14SLEROY Christophe 				     offset);
932246a87cdSLEROY Christophe 	}
9336a1e8d14SLEROY Christophe 	if (src != dst) {
9346a1e8d14SLEROY Christophe 		if (src_nents == 1 || !is_sec1)
9356a1e8d14SLEROY Christophe 			dma_unmap_sg(dev, src, src_nents, DMA_TO_DEVICE);
9366a1e8d14SLEROY Christophe 
9376a1e8d14SLEROY Christophe 		if (dst && (dst_nents == 1 || !is_sec1))
9386a1e8d14SLEROY Christophe 			dma_unmap_sg(dev, dst, dst_nents, DMA_FROM_DEVICE);
9396a1e8d14SLEROY Christophe 	} else if (src_nents == 1 || !is_sec1) {
9406a1e8d14SLEROY Christophe 		dma_unmap_sg(dev, src, src_nents, DMA_BIDIRECTIONAL);
941246a87cdSLEROY Christophe 	}
942246a87cdSLEROY Christophe }
943246a87cdSLEROY Christophe 
9449c4a7965SKim Phillips static void ipsec_esp_unmap(struct device *dev,
94556af8cd4SLee Nipper 			    struct talitos_edesc *edesc,
9469c4a7965SKim Phillips 			    struct aead_request *areq)
9479c4a7965SKim Phillips {
948549bd8bcSLEROY Christophe 	struct crypto_aead *aead = crypto_aead_reqtfm(areq);
949549bd8bcSLEROY Christophe 	struct talitos_ctx *ctx = crypto_aead_ctx(aead);
950549bd8bcSLEROY Christophe 	unsigned int ivsize = crypto_aead_ivsize(aead);
951549bd8bcSLEROY Christophe 
952549bd8bcSLEROY Christophe 	if (edesc->desc.hdr & DESC_HDR_TYPE_IPSEC_ESP)
953549bd8bcSLEROY Christophe 		unmap_single_talitos_ptr(dev, &edesc->desc.ptr[6],
954549bd8bcSLEROY Christophe 					 DMA_FROM_DEVICE);
9559c4a7965SKim Phillips 	unmap_single_talitos_ptr(dev, &edesc->desc.ptr[3], DMA_TO_DEVICE);
9569c4a7965SKim Phillips 	unmap_single_talitos_ptr(dev, &edesc->desc.ptr[2], DMA_TO_DEVICE);
9579c4a7965SKim Phillips 	unmap_single_talitos_ptr(dev, &edesc->desc.ptr[0], DMA_TO_DEVICE);
9589c4a7965SKim Phillips 
9596a1e8d14SLEROY Christophe 	talitos_sg_unmap(dev, edesc, areq->src, areq->dst, areq->cryptlen,
9606a1e8d14SLEROY Christophe 			 areq->assoclen);
9619c4a7965SKim Phillips 
9629c4a7965SKim Phillips 	if (edesc->dma_len)
9639c4a7965SKim Phillips 		dma_unmap_single(dev, edesc->dma_link_tbl, edesc->dma_len,
9649c4a7965SKim Phillips 				 DMA_BIDIRECTIONAL);
965549bd8bcSLEROY Christophe 
966549bd8bcSLEROY Christophe 	if (!(edesc->desc.hdr & DESC_HDR_TYPE_IPSEC_ESP)) {
967549bd8bcSLEROY Christophe 		unsigned int dst_nents = edesc->dst_nents ? : 1;
968549bd8bcSLEROY Christophe 
969549bd8bcSLEROY Christophe 		sg_pcopy_to_buffer(areq->dst, dst_nents, ctx->iv, ivsize,
970549bd8bcSLEROY Christophe 				   areq->assoclen + areq->cryptlen - ivsize);
971549bd8bcSLEROY Christophe 	}
9729c4a7965SKim Phillips }
9739c4a7965SKim Phillips 
9749c4a7965SKim Phillips /*
9759c4a7965SKim Phillips  * ipsec_esp descriptor callbacks
9769c4a7965SKim Phillips  */
9779c4a7965SKim Phillips static void ipsec_esp_encrypt_done(struct device *dev,
9789c4a7965SKim Phillips 				   struct talitos_desc *desc, void *context,
9799c4a7965SKim Phillips 				   int err)
9809c4a7965SKim Phillips {
981549bd8bcSLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
982549bd8bcSLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
9839c4a7965SKim Phillips 	struct aead_request *areq = context;
9849c4a7965SKim Phillips 	struct crypto_aead *authenc = crypto_aead_reqtfm(areq);
985aeb4c132SHerbert Xu 	unsigned int authsize = crypto_aead_authsize(authenc);
98619bbbc63SKim Phillips 	struct talitos_edesc *edesc;
9879c4a7965SKim Phillips 	struct scatterlist *sg;
9889c4a7965SKim Phillips 	void *icvdata;
9899c4a7965SKim Phillips 
99019bbbc63SKim Phillips 	edesc = container_of(desc, struct talitos_edesc, desc);
99119bbbc63SKim Phillips 
9929c4a7965SKim Phillips 	ipsec_esp_unmap(dev, edesc, areq);
9939c4a7965SKim Phillips 
9949c4a7965SKim Phillips 	/* copy the generated ICV to dst */
995aeb4c132SHerbert Xu 	if (edesc->icv_ool) {
996549bd8bcSLEROY Christophe 		if (is_sec1)
997549bd8bcSLEROY Christophe 			icvdata = edesc->buf + areq->assoclen + areq->cryptlen;
998549bd8bcSLEROY Christophe 		else
9999c4a7965SKim Phillips 			icvdata = &edesc->link_tbl[edesc->src_nents +
1000aeb4c132SHerbert Xu 						   edesc->dst_nents + 2];
10019c4a7965SKim Phillips 		sg = sg_last(areq->dst, edesc->dst_nents);
1002aeb4c132SHerbert Xu 		memcpy((char *)sg_virt(sg) + sg->length - authsize,
1003aeb4c132SHerbert Xu 		       icvdata, authsize);
10049c4a7965SKim Phillips 	}
10059c4a7965SKim Phillips 
10069c4a7965SKim Phillips 	kfree(edesc);
10079c4a7965SKim Phillips 
10089c4a7965SKim Phillips 	aead_request_complete(areq, err);
10099c4a7965SKim Phillips }
10109c4a7965SKim Phillips 
1011fe5720e2SKim Phillips static void ipsec_esp_decrypt_swauth_done(struct device *dev,
1012e938e465SKim Phillips 					  struct talitos_desc *desc,
1013e938e465SKim Phillips 					  void *context, int err)
10149c4a7965SKim Phillips {
10159c4a7965SKim Phillips 	struct aead_request *req = context;
10169c4a7965SKim Phillips 	struct crypto_aead *authenc = crypto_aead_reqtfm(req);
1017aeb4c132SHerbert Xu 	unsigned int authsize = crypto_aead_authsize(authenc);
101819bbbc63SKim Phillips 	struct talitos_edesc *edesc;
10199c4a7965SKim Phillips 	struct scatterlist *sg;
1020aeb4c132SHerbert Xu 	char *oicv, *icv;
1021549bd8bcSLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
1022549bd8bcSLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
10239c4a7965SKim Phillips 
102419bbbc63SKim Phillips 	edesc = container_of(desc, struct talitos_edesc, desc);
102519bbbc63SKim Phillips 
10269c4a7965SKim Phillips 	ipsec_esp_unmap(dev, edesc, req);
10279c4a7965SKim Phillips 
10289c4a7965SKim Phillips 	if (!err) {
10299c4a7965SKim Phillips 		/* auth check */
10309c4a7965SKim Phillips 		sg = sg_last(req->dst, edesc->dst_nents ? : 1);
1031aeb4c132SHerbert Xu 		icv = (char *)sg_virt(sg) + sg->length - authsize;
1032aeb4c132SHerbert Xu 
1033aeb4c132SHerbert Xu 		if (edesc->dma_len) {
1034549bd8bcSLEROY Christophe 			if (is_sec1)
1035549bd8bcSLEROY Christophe 				oicv = (char *)&edesc->dma_link_tbl +
1036549bd8bcSLEROY Christophe 					       req->assoclen + req->cryptlen;
1037549bd8bcSLEROY Christophe 			else
1038549bd8bcSLEROY Christophe 				oicv = (char *)
1039549bd8bcSLEROY Christophe 				       &edesc->link_tbl[edesc->src_nents +
1040aeb4c132SHerbert Xu 							edesc->dst_nents + 2];
1041aeb4c132SHerbert Xu 			if (edesc->icv_ool)
1042aeb4c132SHerbert Xu 				icv = oicv + authsize;
1043aeb4c132SHerbert Xu 		} else
1044aeb4c132SHerbert Xu 			oicv = (char *)&edesc->link_tbl[0];
1045aeb4c132SHerbert Xu 
104679960943SDavid Gstir 		err = crypto_memneq(oicv, icv, authsize) ? -EBADMSG : 0;
10479c4a7965SKim Phillips 	}
10489c4a7965SKim Phillips 
10499c4a7965SKim Phillips 	kfree(edesc);
10509c4a7965SKim Phillips 
10519c4a7965SKim Phillips 	aead_request_complete(req, err);
10529c4a7965SKim Phillips }
10539c4a7965SKim Phillips 
1054fe5720e2SKim Phillips static void ipsec_esp_decrypt_hwauth_done(struct device *dev,
1055e938e465SKim Phillips 					  struct talitos_desc *desc,
1056e938e465SKim Phillips 					  void *context, int err)
1057fe5720e2SKim Phillips {
1058fe5720e2SKim Phillips 	struct aead_request *req = context;
105919bbbc63SKim Phillips 	struct talitos_edesc *edesc;
106019bbbc63SKim Phillips 
106119bbbc63SKim Phillips 	edesc = container_of(desc, struct talitos_edesc, desc);
1062fe5720e2SKim Phillips 
1063fe5720e2SKim Phillips 	ipsec_esp_unmap(dev, edesc, req);
1064fe5720e2SKim Phillips 
1065fe5720e2SKim Phillips 	/* check ICV auth status */
1066e938e465SKim Phillips 	if (!err && ((desc->hdr_lo & DESC_HDR_LO_ICCR1_MASK) !=
1067e938e465SKim Phillips 		     DESC_HDR_LO_ICCR1_PASS))
1068fe5720e2SKim Phillips 		err = -EBADMSG;
1069fe5720e2SKim Phillips 
1070fe5720e2SKim Phillips 	kfree(edesc);
1071fe5720e2SKim Phillips 
1072fe5720e2SKim Phillips 	aead_request_complete(req, err);
1073fe5720e2SKim Phillips }
1074fe5720e2SKim Phillips 
10759c4a7965SKim Phillips /*
10769c4a7965SKim Phillips  * convert scatterlist to SEC h/w link table format
10779c4a7965SKim Phillips  * stop at cryptlen bytes
10789c4a7965SKim Phillips  */
1079aeb4c132SHerbert Xu static int sg_to_link_tbl_offset(struct scatterlist *sg, int sg_count,
1080aeb4c132SHerbert Xu 				 unsigned int offset, int cryptlen,
1081aeb4c132SHerbert Xu 				 struct talitos_ptr *link_tbl_ptr)
10829c4a7965SKim Phillips {
108370bcaca7SLee Nipper 	int n_sg = sg_count;
1084aeb4c132SHerbert Xu 	int count = 0;
108570bcaca7SLee Nipper 
1086aeb4c132SHerbert Xu 	while (cryptlen && sg && n_sg--) {
1087aeb4c132SHerbert Xu 		unsigned int len = sg_dma_len(sg);
1088aeb4c132SHerbert Xu 
1089aeb4c132SHerbert Xu 		if (offset >= len) {
1090aeb4c132SHerbert Xu 			offset -= len;
1091aeb4c132SHerbert Xu 			goto next;
1092aeb4c132SHerbert Xu 		}
1093aeb4c132SHerbert Xu 
1094aeb4c132SHerbert Xu 		len -= offset;
1095aeb4c132SHerbert Xu 
1096aeb4c132SHerbert Xu 		if (len > cryptlen)
1097aeb4c132SHerbert Xu 			len = cryptlen;
1098aeb4c132SHerbert Xu 
1099aeb4c132SHerbert Xu 		to_talitos_ptr(link_tbl_ptr + count,
1100aeb4c132SHerbert Xu 			       sg_dma_address(sg) + offset, 0);
1101b096b544SLEROY Christophe 		to_talitos_ptr_len(link_tbl_ptr + count, len, 0);
1102b096b544SLEROY Christophe 		to_talitos_ptr_ext_set(link_tbl_ptr + count, 0, 0);
1103aeb4c132SHerbert Xu 		count++;
1104aeb4c132SHerbert Xu 		cryptlen -= len;
1105aeb4c132SHerbert Xu 		offset = 0;
1106aeb4c132SHerbert Xu 
1107aeb4c132SHerbert Xu next:
11085be4d4c9SCristian Stoica 		sg = sg_next(sg);
11099c4a7965SKim Phillips 	}
11109c4a7965SKim Phillips 
11119c4a7965SKim Phillips 	/* tag end of link table */
1112aeb4c132SHerbert Xu 	if (count > 0)
1113b096b544SLEROY Christophe 		to_talitos_ptr_ext_set(link_tbl_ptr + count - 1,
1114b096b544SLEROY Christophe 				       DESC_PTR_LNKTBL_RETURN, 0);
111570bcaca7SLee Nipper 
1116aeb4c132SHerbert Xu 	return count;
1117aeb4c132SHerbert Xu }
1118aeb4c132SHerbert Xu 
11196a1e8d14SLEROY Christophe int talitos_sg_map(struct device *dev, struct scatterlist *src,
1120246a87cdSLEROY Christophe 		   unsigned int len, struct talitos_edesc *edesc,
11216a1e8d14SLEROY Christophe 		   struct talitos_ptr *ptr,
11226a1e8d14SLEROY Christophe 		   int sg_count, unsigned int offset, int tbl_off)
1123246a87cdSLEROY Christophe {
1124246a87cdSLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
1125246a87cdSLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
1126246a87cdSLEROY Christophe 
1127246a87cdSLEROY Christophe 	to_talitos_ptr_len(ptr, len, is_sec1);
1128246a87cdSLEROY Christophe 	to_talitos_ptr_ext_set(ptr, 0, is_sec1);
1129246a87cdSLEROY Christophe 
1130246a87cdSLEROY Christophe 	if (sg_count == 1) {
11316a1e8d14SLEROY Christophe 		to_talitos_ptr(ptr, sg_dma_address(src) + offset, is_sec1);
1132246a87cdSLEROY Christophe 		return sg_count;
1133246a87cdSLEROY Christophe 	}
1134246a87cdSLEROY Christophe 	if (is_sec1) {
11356a1e8d14SLEROY Christophe 		to_talitos_ptr(ptr, edesc->dma_link_tbl + offset, is_sec1);
11366a1e8d14SLEROY Christophe 		return sg_count;
1137246a87cdSLEROY Christophe 	}
11386a1e8d14SLEROY Christophe 	sg_count = sg_to_link_tbl_offset(src, sg_count, offset, len,
11396a1e8d14SLEROY Christophe 					 &edesc->link_tbl[tbl_off]);
1140246a87cdSLEROY Christophe 	if (sg_count == 1) {
11416a1e8d14SLEROY Christophe 		/* Only one segment now, so no link tbl needed*/
11426a1e8d14SLEROY Christophe 		copy_talitos_ptr(ptr, &edesc->link_tbl[tbl_off], is_sec1);
11436a1e8d14SLEROY Christophe 		return sg_count;
11446a1e8d14SLEROY Christophe 	}
1145246a87cdSLEROY Christophe 	to_talitos_ptr(ptr, edesc->dma_link_tbl +
11466a1e8d14SLEROY Christophe 			    tbl_off * sizeof(struct talitos_ptr), is_sec1);
11476a1e8d14SLEROY Christophe 	to_talitos_ptr_ext_or(ptr, DESC_PTR_LNKTBL_JUMP, is_sec1);
11486a1e8d14SLEROY Christophe 
11496a1e8d14SLEROY Christophe 	return sg_count;
1150246a87cdSLEROY Christophe }
1151246a87cdSLEROY Christophe 
11529c4a7965SKim Phillips /*
11539c4a7965SKim Phillips  * fill in and submit ipsec_esp descriptor
11549c4a7965SKim Phillips  */
115556af8cd4SLee Nipper static int ipsec_esp(struct talitos_edesc *edesc, struct aead_request *areq,
1156aeb4c132SHerbert Xu 		     void (*callback)(struct device *dev,
11579c4a7965SKim Phillips 				      struct talitos_desc *desc,
11589c4a7965SKim Phillips 				      void *context, int error))
11599c4a7965SKim Phillips {
11609c4a7965SKim Phillips 	struct crypto_aead *aead = crypto_aead_reqtfm(areq);
1161aeb4c132SHerbert Xu 	unsigned int authsize = crypto_aead_authsize(aead);
11629c4a7965SKim Phillips 	struct talitos_ctx *ctx = crypto_aead_ctx(aead);
11639c4a7965SKim Phillips 	struct device *dev = ctx->dev;
11649c4a7965SKim Phillips 	struct talitos_desc *desc = &edesc->desc;
11659c4a7965SKim Phillips 	unsigned int cryptlen = areq->cryptlen;
1166e41256f1SKim Phillips 	unsigned int ivsize = crypto_aead_ivsize(aead);
1167aeb4c132SHerbert Xu 	int tbl_off = 0;
1168fa86a267SKim Phillips 	int sg_count, ret;
1169fe5720e2SKim Phillips 	int sg_link_tbl_len;
1170549bd8bcSLEROY Christophe 	bool sync_needed = false;
1171549bd8bcSLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
1172549bd8bcSLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
11739c4a7965SKim Phillips 
11749c4a7965SKim Phillips 	/* hmac key */
11759c4a7965SKim Phillips 	map_single_talitos_ptr(dev, &desc->ptr[0], ctx->authkeylen, &ctx->key,
1176a2b35aa8SLEROY Christophe 			       DMA_TO_DEVICE);
117779fd31d3SHoria Geanta 
1178549bd8bcSLEROY Christophe 	sg_count = edesc->src_nents ?: 1;
1179549bd8bcSLEROY Christophe 	if (is_sec1 && sg_count > 1)
1180549bd8bcSLEROY Christophe 		sg_copy_to_buffer(areq->src, sg_count, edesc->buf,
1181549bd8bcSLEROY Christophe 				  areq->assoclen + cryptlen);
1182549bd8bcSLEROY Christophe 	else
1183549bd8bcSLEROY Christophe 		sg_count = dma_map_sg(dev, areq->src, sg_count,
1184549bd8bcSLEROY Christophe 				      (areq->src == areq->dst) ?
1185549bd8bcSLEROY Christophe 				      DMA_BIDIRECTIONAL : DMA_TO_DEVICE);
1186549bd8bcSLEROY Christophe 
11879c4a7965SKim Phillips 	/* hmac data */
1188549bd8bcSLEROY Christophe 	ret = talitos_sg_map(dev, areq->src, areq->assoclen, edesc,
1189549bd8bcSLEROY Christophe 			     &desc->ptr[1], sg_count, 0, tbl_off);
119079fd31d3SHoria Geanta 
1191549bd8bcSLEROY Christophe 	if (ret > 1) {
1192340ff60aSHoria Geant? 		tbl_off += ret;
1193549bd8bcSLEROY Christophe 		sync_needed = true;
119479fd31d3SHoria Geanta 	}
119579fd31d3SHoria Geanta 
11969c4a7965SKim Phillips 	/* cipher iv */
1197549bd8bcSLEROY Christophe 	if (desc->hdr & DESC_HDR_TYPE_IPSEC_ESP) {
1198549bd8bcSLEROY Christophe 		to_talitos_ptr(&desc->ptr[2], edesc->iv_dma, is_sec1);
1199549bd8bcSLEROY Christophe 		to_talitos_ptr_len(&desc->ptr[2], ivsize, is_sec1);
1200549bd8bcSLEROY Christophe 		to_talitos_ptr_ext_set(&desc->ptr[2], 0, is_sec1);
1201549bd8bcSLEROY Christophe 	} else {
1202549bd8bcSLEROY Christophe 		to_talitos_ptr(&desc->ptr[3], edesc->iv_dma, is_sec1);
1203549bd8bcSLEROY Christophe 		to_talitos_ptr_len(&desc->ptr[3], ivsize, is_sec1);
1204549bd8bcSLEROY Christophe 		to_talitos_ptr_ext_set(&desc->ptr[3], 0, is_sec1);
1205549bd8bcSLEROY Christophe 	}
12069c4a7965SKim Phillips 
12079c4a7965SKim Phillips 	/* cipher key */
1208549bd8bcSLEROY Christophe 	if (desc->hdr & DESC_HDR_TYPE_IPSEC_ESP)
12099c4a7965SKim Phillips 		map_single_talitos_ptr(dev, &desc->ptr[3], ctx->enckeylen,
1210a2b35aa8SLEROY Christophe 				       (char *)&ctx->key + ctx->authkeylen,
12119c4a7965SKim Phillips 				       DMA_TO_DEVICE);
1212549bd8bcSLEROY Christophe 	else
1213549bd8bcSLEROY Christophe 		map_single_talitos_ptr(dev, &desc->ptr[2], ctx->enckeylen,
1214549bd8bcSLEROY Christophe 				       (char *)&ctx->key + ctx->authkeylen,
1215549bd8bcSLEROY Christophe 				       DMA_TO_DEVICE);
12169c4a7965SKim Phillips 
12179c4a7965SKim Phillips 	/*
12189c4a7965SKim Phillips 	 * cipher in
12199c4a7965SKim Phillips 	 * map and adjust cipher len to aead request cryptlen.
12209c4a7965SKim Phillips 	 * extent is bytes of HMAC postpended to ciphertext,
12219c4a7965SKim Phillips 	 * typically 12 for ipsec
12229c4a7965SKim Phillips 	 */
1223549bd8bcSLEROY Christophe 	to_talitos_ptr_len(&desc->ptr[4], cryptlen, is_sec1);
1224549bd8bcSLEROY Christophe 	to_talitos_ptr_ext_set(&desc->ptr[4], 0, is_sec1);
12259c4a7965SKim Phillips 
1226fe5720e2SKim Phillips 	sg_link_tbl_len = cryptlen;
1227549bd8bcSLEROY Christophe 
1228549bd8bcSLEROY Christophe 	if (desc->hdr & DESC_HDR_TYPE_IPSEC_ESP) {
1229549bd8bcSLEROY Christophe 		to_talitos_ptr_ext_set(&desc->ptr[4], authsize, is_sec1);
1230549bd8bcSLEROY Christophe 
1231962a9c99SKim Phillips 		if (edesc->desc.hdr & DESC_HDR_MODE1_MDEU_CICV)
1232aeb4c132SHerbert Xu 			sg_link_tbl_len += authsize;
1233549bd8bcSLEROY Christophe 	}
1234e938e465SKim Phillips 
1235fbb22137SLEROY Christophe 	ret = talitos_sg_map(dev, areq->src, sg_link_tbl_len, edesc,
1236fbb22137SLEROY Christophe 			     &desc->ptr[4], sg_count, areq->assoclen, tbl_off);
1237549bd8bcSLEROY Christophe 
1238ec8c7d14SLEROY Christophe 	if (ret > 1) {
1239ec8c7d14SLEROY Christophe 		tbl_off += ret;
1240549bd8bcSLEROY Christophe 		sync_needed = true;
1241340ff60aSHoria Geant? 	}
12429c4a7965SKim Phillips 
12439c4a7965SKim Phillips 	/* cipher out */
1244549bd8bcSLEROY Christophe 	if (areq->src != areq->dst) {
1245549bd8bcSLEROY Christophe 		sg_count = edesc->dst_nents ? : 1;
1246549bd8bcSLEROY Christophe 		if (!is_sec1 || sg_count == 1)
1247549bd8bcSLEROY Christophe 			dma_map_sg(dev, areq->dst, sg_count, DMA_FROM_DEVICE);
1248549bd8bcSLEROY Christophe 	}
12499c4a7965SKim Phillips 
1250e04a61beSLEROY Christophe 	ret = talitos_sg_map(dev, areq->dst, cryptlen, edesc, &desc->ptr[5],
1251e04a61beSLEROY Christophe 			     sg_count, areq->assoclen, tbl_off);
12529c4a7965SKim Phillips 
1253549bd8bcSLEROY Christophe 	if (desc->hdr & DESC_HDR_TYPE_IPSEC_ESP)
1254549bd8bcSLEROY Christophe 		to_talitos_ptr_ext_or(&desc->ptr[5], authsize, is_sec1);
1255aeb4c132SHerbert Xu 
1256e04a61beSLEROY Christophe 	/* ICV data */
1257e04a61beSLEROY Christophe 	if (ret > 1) {
1258e04a61beSLEROY Christophe 		tbl_off += ret;
1259549bd8bcSLEROY Christophe 		edesc->icv_ool = true;
1260549bd8bcSLEROY Christophe 		sync_needed = true;
1261549bd8bcSLEROY Christophe 
1262549bd8bcSLEROY Christophe 		if (desc->hdr & DESC_HDR_TYPE_IPSEC_ESP) {
126379fd31d3SHoria Geanta 			struct talitos_ptr *tbl_ptr = &edesc->link_tbl[tbl_off];
1264549bd8bcSLEROY Christophe 			int offset = (edesc->src_nents + edesc->dst_nents + 2) *
1265549bd8bcSLEROY Christophe 				     sizeof(struct talitos_ptr) + authsize;
1266fe5720e2SKim Phillips 
1267f3c85bc1SLee Nipper 			/* Add an entry to the link table for ICV data */
1268e04a61beSLEROY Christophe 			to_talitos_ptr_ext_set(tbl_ptr - 1, 0, is_sec1);
1269549bd8bcSLEROY Christophe 			to_talitos_ptr_ext_set(tbl_ptr, DESC_PTR_LNKTBL_RETURN,
1270549bd8bcSLEROY Christophe 					       is_sec1);
1271549bd8bcSLEROY Christophe 			to_talitos_ptr_len(tbl_ptr, authsize, is_sec1);
12729c4a7965SKim Phillips 
12739c4a7965SKim Phillips 			/* icv data follows link tables */
1274549bd8bcSLEROY Christophe 			to_talitos_ptr(tbl_ptr, edesc->dma_link_tbl + offset,
1275549bd8bcSLEROY Christophe 				       is_sec1);
1276e04a61beSLEROY Christophe 		} else {
1277e04a61beSLEROY Christophe 			dma_addr_t addr = edesc->dma_link_tbl;
1278e04a61beSLEROY Christophe 
1279e04a61beSLEROY Christophe 			if (is_sec1)
1280e04a61beSLEROY Christophe 				addr += areq->assoclen + cryptlen;
1281e04a61beSLEROY Christophe 			else
1282e04a61beSLEROY Christophe 				addr += sizeof(struct talitos_ptr) * tbl_off;
1283e04a61beSLEROY Christophe 
1284e04a61beSLEROY Christophe 			to_talitos_ptr(&desc->ptr[6], addr, is_sec1);
1285e04a61beSLEROY Christophe 			to_talitos_ptr_len(&desc->ptr[6], authsize, is_sec1);
1286549bd8bcSLEROY Christophe 		}
1287e04a61beSLEROY Christophe 	} else if (!(desc->hdr & DESC_HDR_TYPE_IPSEC_ESP)) {
1288e04a61beSLEROY Christophe 		ret = talitos_sg_map(dev, areq->dst, authsize, edesc,
1289e04a61beSLEROY Christophe 				     &desc->ptr[6], sg_count, areq->assoclen +
1290e04a61beSLEROY Christophe 							      cryptlen,
1291e04a61beSLEROY Christophe 				     tbl_off);
1292e04a61beSLEROY Christophe 		if (ret > 1) {
1293e04a61beSLEROY Christophe 			tbl_off += ret;
1294e04a61beSLEROY Christophe 			edesc->icv_ool = true;
1295e04a61beSLEROY Christophe 			sync_needed = true;
1296340ff60aSHoria Geant? 		} else {
1297549bd8bcSLEROY Christophe 			edesc->icv_ool = false;
1298549bd8bcSLEROY Christophe 		}
1299e04a61beSLEROY Christophe 	} else {
1300e04a61beSLEROY Christophe 		edesc->icv_ool = false;
1301340ff60aSHoria Geant? 	}
13029c4a7965SKim Phillips 
13039c4a7965SKim Phillips 	/* iv out */
1304549bd8bcSLEROY Christophe 	if (desc->hdr & DESC_HDR_TYPE_IPSEC_ESP)
1305a2b35aa8SLEROY Christophe 		map_single_talitos_ptr(dev, &desc->ptr[6], ivsize, ctx->iv,
13069c4a7965SKim Phillips 				       DMA_FROM_DEVICE);
13079c4a7965SKim Phillips 
1308549bd8bcSLEROY Christophe 	if (sync_needed)
1309549bd8bcSLEROY Christophe 		dma_sync_single_for_device(dev, edesc->dma_link_tbl,
1310549bd8bcSLEROY Christophe 					   edesc->dma_len,
1311549bd8bcSLEROY Christophe 					   DMA_BIDIRECTIONAL);
1312549bd8bcSLEROY Christophe 
13135228f0f7SKim Phillips 	ret = talitos_submit(dev, ctx->ch, desc, callback, areq);
1314fa86a267SKim Phillips 	if (ret != -EINPROGRESS) {
1315fa86a267SKim Phillips 		ipsec_esp_unmap(dev, edesc, areq);
1316fa86a267SKim Phillips 		kfree(edesc);
1317fa86a267SKim Phillips 	}
1318fa86a267SKim Phillips 	return ret;
13199c4a7965SKim Phillips }
13209c4a7965SKim Phillips 
13219c4a7965SKim Phillips /*
132256af8cd4SLee Nipper  * allocate and map the extended descriptor
13239c4a7965SKim Phillips  */
13244de9d0b5SLee Nipper static struct talitos_edesc *talitos_edesc_alloc(struct device *dev,
13254de9d0b5SLee Nipper 						 struct scatterlist *src,
13264de9d0b5SLee Nipper 						 struct scatterlist *dst,
132779fd31d3SHoria Geanta 						 u8 *iv,
132879fd31d3SHoria Geanta 						 unsigned int assoclen,
13294de9d0b5SLee Nipper 						 unsigned int cryptlen,
13304de9d0b5SLee Nipper 						 unsigned int authsize,
133179fd31d3SHoria Geanta 						 unsigned int ivsize,
13324de9d0b5SLee Nipper 						 int icv_stashing,
133362293a37SHoria Geanta 						 u32 cryptoflags,
133462293a37SHoria Geanta 						 bool encrypt)
13359c4a7965SKim Phillips {
133656af8cd4SLee Nipper 	struct talitos_edesc *edesc;
13376a1e8d14SLEROY Christophe 	int src_nents, dst_nents, alloc_len, dma_len, src_len, dst_len;
133879fd31d3SHoria Geanta 	dma_addr_t iv_dma = 0;
13394de9d0b5SLee Nipper 	gfp_t flags = cryptoflags & CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL :
1340586725f8SKim Phillips 		      GFP_ATOMIC;
13416f65f6acSLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
13426f65f6acSLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
13436f65f6acSLEROY Christophe 	int max_len = is_sec1 ? TALITOS1_MAX_DATA_LEN : TALITOS2_MAX_DATA_LEN;
13448e409fe1SLABBE Corentin 	void *err;
13459c4a7965SKim Phillips 
13466f65f6acSLEROY Christophe 	if (cryptlen + authsize > max_len) {
13474de9d0b5SLee Nipper 		dev_err(dev, "length exceeds h/w max limit\n");
13489c4a7965SKim Phillips 		return ERR_PTR(-EINVAL);
13499c4a7965SKim Phillips 	}
13509c4a7965SKim Phillips 
1351935e99a3SHoria Geanta 	if (ivsize)
135279fd31d3SHoria Geanta 		iv_dma = dma_map_single(dev, iv, ivsize, DMA_TO_DEVICE);
135379fd31d3SHoria Geanta 
135462293a37SHoria Geanta 	if (!dst || dst == src) {
13556a1e8d14SLEROY Christophe 		src_len = assoclen + cryptlen + authsize;
13566a1e8d14SLEROY Christophe 		src_nents = sg_nents_for_len(src, src_len);
13578e409fe1SLABBE Corentin 		if (src_nents < 0) {
13588e409fe1SLABBE Corentin 			dev_err(dev, "Invalid number of src SG.\n");
13598e409fe1SLABBE Corentin 			err = ERR_PTR(-EINVAL);
13608e409fe1SLABBE Corentin 			goto error_sg;
13618e409fe1SLABBE Corentin 		}
13629c4a7965SKim Phillips 		src_nents = (src_nents == 1) ? 0 : src_nents;
136362293a37SHoria Geanta 		dst_nents = dst ? src_nents : 0;
13646a1e8d14SLEROY Christophe 		dst_len = 0;
136562293a37SHoria Geanta 	} else { /* dst && dst != src*/
13666a1e8d14SLEROY Christophe 		src_len = assoclen + cryptlen + (encrypt ? 0 : authsize);
13676a1e8d14SLEROY Christophe 		src_nents = sg_nents_for_len(src, src_len);
13688e409fe1SLABBE Corentin 		if (src_nents < 0) {
13698e409fe1SLABBE Corentin 			dev_err(dev, "Invalid number of src SG.\n");
13708e409fe1SLABBE Corentin 			err = ERR_PTR(-EINVAL);
13718e409fe1SLABBE Corentin 			goto error_sg;
13728e409fe1SLABBE Corentin 		}
137362293a37SHoria Geanta 		src_nents = (src_nents == 1) ? 0 : src_nents;
13746a1e8d14SLEROY Christophe 		dst_len = assoclen + cryptlen + (encrypt ? authsize : 0);
13756a1e8d14SLEROY Christophe 		dst_nents = sg_nents_for_len(dst, dst_len);
13768e409fe1SLABBE Corentin 		if (dst_nents < 0) {
13778e409fe1SLABBE Corentin 			dev_err(dev, "Invalid number of dst SG.\n");
13788e409fe1SLABBE Corentin 			err = ERR_PTR(-EINVAL);
13798e409fe1SLABBE Corentin 			goto error_sg;
13808e409fe1SLABBE Corentin 		}
1381695ad589SLee Nipper 		dst_nents = (dst_nents == 1) ? 0 : dst_nents;
13829c4a7965SKim Phillips 	}
13839c4a7965SKim Phillips 
13849c4a7965SKim Phillips 	/*
13859c4a7965SKim Phillips 	 * allocate space for base edesc plus the link tables,
1386aeb4c132SHerbert Xu 	 * allowing for two separate entries for AD and generated ICV (+ 2),
1387aeb4c132SHerbert Xu 	 * and space for two sets of ICVs (stashed and generated)
13889c4a7965SKim Phillips 	 */
138956af8cd4SLee Nipper 	alloc_len = sizeof(struct talitos_edesc);
1390aeb4c132SHerbert Xu 	if (src_nents || dst_nents) {
13916f65f6acSLEROY Christophe 		if (is_sec1)
13926a1e8d14SLEROY Christophe 			dma_len = (src_nents ? src_len : 0) +
13936a1e8d14SLEROY Christophe 				  (dst_nents ? dst_len : 0);
13946f65f6acSLEROY Christophe 		else
1395aeb4c132SHerbert Xu 			dma_len = (src_nents + dst_nents + 2) *
1396aeb4c132SHerbert Xu 				  sizeof(struct talitos_ptr) + authsize * 2;
13979c4a7965SKim Phillips 		alloc_len += dma_len;
13989c4a7965SKim Phillips 	} else {
13999c4a7965SKim Phillips 		dma_len = 0;
14004de9d0b5SLee Nipper 		alloc_len += icv_stashing ? authsize : 0;
14019c4a7965SKim Phillips 	}
14029c4a7965SKim Phillips 
1403586725f8SKim Phillips 	edesc = kmalloc(alloc_len, GFP_DMA | flags);
14049c4a7965SKim Phillips 	if (!edesc) {
14054de9d0b5SLee Nipper 		dev_err(dev, "could not allocate edescriptor\n");
14068e409fe1SLABBE Corentin 		err = ERR_PTR(-ENOMEM);
14078e409fe1SLABBE Corentin 		goto error_sg;
14089c4a7965SKim Phillips 	}
14099c4a7965SKim Phillips 
14109c4a7965SKim Phillips 	edesc->src_nents = src_nents;
14119c4a7965SKim Phillips 	edesc->dst_nents = dst_nents;
141279fd31d3SHoria Geanta 	edesc->iv_dma = iv_dma;
14139c4a7965SKim Phillips 	edesc->dma_len = dma_len;
1414497f2e6bSLee Nipper 	if (dma_len)
14154de9d0b5SLee Nipper 		edesc->dma_link_tbl = dma_map_single(dev, &edesc->link_tbl[0],
1416497f2e6bSLee Nipper 						     edesc->dma_len,
1417497f2e6bSLee Nipper 						     DMA_BIDIRECTIONAL);
14189c4a7965SKim Phillips 
14199c4a7965SKim Phillips 	return edesc;
14208e409fe1SLABBE Corentin error_sg:
14218e409fe1SLABBE Corentin 	if (iv_dma)
14228e409fe1SLABBE Corentin 		dma_unmap_single(dev, iv_dma, ivsize, DMA_TO_DEVICE);
14238e409fe1SLABBE Corentin 	return err;
14249c4a7965SKim Phillips }
14259c4a7965SKim Phillips 
142679fd31d3SHoria Geanta static struct talitos_edesc *aead_edesc_alloc(struct aead_request *areq, u8 *iv,
142762293a37SHoria Geanta 					      int icv_stashing, bool encrypt)
14284de9d0b5SLee Nipper {
14294de9d0b5SLee Nipper 	struct crypto_aead *authenc = crypto_aead_reqtfm(areq);
1430aeb4c132SHerbert Xu 	unsigned int authsize = crypto_aead_authsize(authenc);
14314de9d0b5SLee Nipper 	struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
143279fd31d3SHoria Geanta 	unsigned int ivsize = crypto_aead_ivsize(authenc);
14334de9d0b5SLee Nipper 
1434aeb4c132SHerbert Xu 	return talitos_edesc_alloc(ctx->dev, areq->src, areq->dst,
143579fd31d3SHoria Geanta 				   iv, areq->assoclen, areq->cryptlen,
1436aeb4c132SHerbert Xu 				   authsize, ivsize, icv_stashing,
143762293a37SHoria Geanta 				   areq->base.flags, encrypt);
14384de9d0b5SLee Nipper }
14394de9d0b5SLee Nipper 
144056af8cd4SLee Nipper static int aead_encrypt(struct aead_request *req)
14419c4a7965SKim Phillips {
14429c4a7965SKim Phillips 	struct crypto_aead *authenc = crypto_aead_reqtfm(req);
14439c4a7965SKim Phillips 	struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
144456af8cd4SLee Nipper 	struct talitos_edesc *edesc;
14459c4a7965SKim Phillips 
14469c4a7965SKim Phillips 	/* allocate extended descriptor */
144762293a37SHoria Geanta 	edesc = aead_edesc_alloc(req, req->iv, 0, true);
14489c4a7965SKim Phillips 	if (IS_ERR(edesc))
14499c4a7965SKim Phillips 		return PTR_ERR(edesc);
14509c4a7965SKim Phillips 
14519c4a7965SKim Phillips 	/* set encrypt */
145270bcaca7SLee Nipper 	edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_MODE0_ENCRYPT;
14539c4a7965SKim Phillips 
1454aeb4c132SHerbert Xu 	return ipsec_esp(edesc, req, ipsec_esp_encrypt_done);
14559c4a7965SKim Phillips }
14569c4a7965SKim Phillips 
145756af8cd4SLee Nipper static int aead_decrypt(struct aead_request *req)
14589c4a7965SKim Phillips {
14599c4a7965SKim Phillips 	struct crypto_aead *authenc = crypto_aead_reqtfm(req);
1460aeb4c132SHerbert Xu 	unsigned int authsize = crypto_aead_authsize(authenc);
14619c4a7965SKim Phillips 	struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
1462fe5720e2SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(ctx->dev);
146356af8cd4SLee Nipper 	struct talitos_edesc *edesc;
14649c4a7965SKim Phillips 	struct scatterlist *sg;
14659c4a7965SKim Phillips 	void *icvdata;
14669c4a7965SKim Phillips 
14679c4a7965SKim Phillips 	req->cryptlen -= authsize;
14689c4a7965SKim Phillips 
14699c4a7965SKim Phillips 	/* allocate extended descriptor */
147062293a37SHoria Geanta 	edesc = aead_edesc_alloc(req, req->iv, 1, false);
14719c4a7965SKim Phillips 	if (IS_ERR(edesc))
14729c4a7965SKim Phillips 		return PTR_ERR(edesc);
14739c4a7965SKim Phillips 
1474fe5720e2SKim Phillips 	if ((priv->features & TALITOS_FTR_HW_AUTH_CHECK) &&
1475e938e465SKim Phillips 	    ((!edesc->src_nents && !edesc->dst_nents) ||
1476e938e465SKim Phillips 	     priv->features & TALITOS_FTR_SRC_LINK_TBL_LEN_INCLUDES_EXTENT)) {
1477fe5720e2SKim Phillips 
1478fe5720e2SKim Phillips 		/* decrypt and check the ICV */
1479e938e465SKim Phillips 		edesc->desc.hdr = ctx->desc_hdr_template |
1480e938e465SKim Phillips 				  DESC_HDR_DIR_INBOUND |
1481fe5720e2SKim Phillips 				  DESC_HDR_MODE1_MDEU_CICV;
1482fe5720e2SKim Phillips 
1483fe5720e2SKim Phillips 		/* reset integrity check result bits */
1484fe5720e2SKim Phillips 		edesc->desc.hdr_lo = 0;
1485fe5720e2SKim Phillips 
1486aeb4c132SHerbert Xu 		return ipsec_esp(edesc, req, ipsec_esp_decrypt_hwauth_done);
1487e938e465SKim Phillips 	}
1488fe5720e2SKim Phillips 
1489fe5720e2SKim Phillips 	/* Have to check the ICV with software */
1490fe5720e2SKim Phillips 	edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_DIR_INBOUND;
1491fe5720e2SKim Phillips 
14929c4a7965SKim Phillips 	/* stash incoming ICV for later cmp with ICV generated by the h/w */
14939c4a7965SKim Phillips 	if (edesc->dma_len)
1494aeb4c132SHerbert Xu 		icvdata = (char *)&edesc->link_tbl[edesc->src_nents +
1495aeb4c132SHerbert Xu 						   edesc->dst_nents + 2];
14969c4a7965SKim Phillips 	else
14979c4a7965SKim Phillips 		icvdata = &edesc->link_tbl[0];
14989c4a7965SKim Phillips 
14999c4a7965SKim Phillips 	sg = sg_last(req->src, edesc->src_nents ? : 1);
15009c4a7965SKim Phillips 
1501aeb4c132SHerbert Xu 	memcpy(icvdata, (char *)sg_virt(sg) + sg->length - authsize, authsize);
15029c4a7965SKim Phillips 
1503aeb4c132SHerbert Xu 	return ipsec_esp(edesc, req, ipsec_esp_decrypt_swauth_done);
15049c4a7965SKim Phillips }
15059c4a7965SKim Phillips 
15064de9d0b5SLee Nipper static int ablkcipher_setkey(struct crypto_ablkcipher *cipher,
15074de9d0b5SLee Nipper 			     const u8 *key, unsigned int keylen)
15084de9d0b5SLee Nipper {
15094de9d0b5SLee Nipper 	struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher);
1510f384cdc4SLEROY Christophe 	u32 tmp[DES_EXPKEY_WORDS];
15114de9d0b5SLee Nipper 
151203d2c511SMartin Hicks 	if (keylen > TALITOS_MAX_KEY_SIZE) {
151303d2c511SMartin Hicks 		crypto_ablkcipher_set_flags(cipher, CRYPTO_TFM_RES_BAD_KEY_LEN);
151403d2c511SMartin Hicks 		return -EINVAL;
151503d2c511SMartin Hicks 	}
151603d2c511SMartin Hicks 
1517f384cdc4SLEROY Christophe 	if (unlikely(crypto_ablkcipher_get_flags(cipher) &
1518f384cdc4SLEROY Christophe 		     CRYPTO_TFM_REQ_WEAK_KEY) &&
1519f384cdc4SLEROY Christophe 	    !des_ekey(tmp, key)) {
1520f384cdc4SLEROY Christophe 		crypto_ablkcipher_set_flags(cipher, CRYPTO_TFM_RES_WEAK_KEY);
1521f384cdc4SLEROY Christophe 		return -EINVAL;
1522f384cdc4SLEROY Christophe 	}
1523f384cdc4SLEROY Christophe 
15244de9d0b5SLee Nipper 	memcpy(&ctx->key, key, keylen);
15254de9d0b5SLee Nipper 	ctx->keylen = keylen;
15264de9d0b5SLee Nipper 
15274de9d0b5SLee Nipper 	return 0;
15284de9d0b5SLee Nipper }
15294de9d0b5SLee Nipper 
15304de9d0b5SLee Nipper static void common_nonsnoop_unmap(struct device *dev,
15314de9d0b5SLee Nipper 				  struct talitos_edesc *edesc,
15324de9d0b5SLee Nipper 				  struct ablkcipher_request *areq)
15334de9d0b5SLee Nipper {
15344de9d0b5SLee Nipper 	unmap_single_talitos_ptr(dev, &edesc->desc.ptr[5], DMA_FROM_DEVICE);
1535032d197eSLEROY Christophe 
15366a1e8d14SLEROY Christophe 	talitos_sg_unmap(dev, edesc, areq->src, areq->dst, areq->nbytes, 0);
15374de9d0b5SLee Nipper 	unmap_single_talitos_ptr(dev, &edesc->desc.ptr[2], DMA_TO_DEVICE);
15384de9d0b5SLee Nipper 	unmap_single_talitos_ptr(dev, &edesc->desc.ptr[1], DMA_TO_DEVICE);
15394de9d0b5SLee Nipper 
15404de9d0b5SLee Nipper 	if (edesc->dma_len)
15414de9d0b5SLee Nipper 		dma_unmap_single(dev, edesc->dma_link_tbl, edesc->dma_len,
15424de9d0b5SLee Nipper 				 DMA_BIDIRECTIONAL);
15434de9d0b5SLee Nipper }
15444de9d0b5SLee Nipper 
15454de9d0b5SLee Nipper static void ablkcipher_done(struct device *dev,
15464de9d0b5SLee Nipper 			    struct talitos_desc *desc, void *context,
15474de9d0b5SLee Nipper 			    int err)
15484de9d0b5SLee Nipper {
15494de9d0b5SLee Nipper 	struct ablkcipher_request *areq = context;
155019bbbc63SKim Phillips 	struct talitos_edesc *edesc;
155119bbbc63SKim Phillips 
155219bbbc63SKim Phillips 	edesc = container_of(desc, struct talitos_edesc, desc);
15534de9d0b5SLee Nipper 
15544de9d0b5SLee Nipper 	common_nonsnoop_unmap(dev, edesc, areq);
15554de9d0b5SLee Nipper 
15564de9d0b5SLee Nipper 	kfree(edesc);
15574de9d0b5SLee Nipper 
15584de9d0b5SLee Nipper 	areq->base.complete(&areq->base, err);
15594de9d0b5SLee Nipper }
15604de9d0b5SLee Nipper 
15614de9d0b5SLee Nipper static int common_nonsnoop(struct talitos_edesc *edesc,
15624de9d0b5SLee Nipper 			   struct ablkcipher_request *areq,
15634de9d0b5SLee Nipper 			   void (*callback) (struct device *dev,
15644de9d0b5SLee Nipper 					     struct talitos_desc *desc,
15654de9d0b5SLee Nipper 					     void *context, int error))
15664de9d0b5SLee Nipper {
15674de9d0b5SLee Nipper 	struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(areq);
15684de9d0b5SLee Nipper 	struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher);
15694de9d0b5SLee Nipper 	struct device *dev = ctx->dev;
15704de9d0b5SLee Nipper 	struct talitos_desc *desc = &edesc->desc;
15714de9d0b5SLee Nipper 	unsigned int cryptlen = areq->nbytes;
157279fd31d3SHoria Geanta 	unsigned int ivsize = crypto_ablkcipher_ivsize(cipher);
15734de9d0b5SLee Nipper 	int sg_count, ret;
15746a1e8d14SLEROY Christophe 	bool sync_needed = false;
1575922f9dc8SLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
1576922f9dc8SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
15774de9d0b5SLee Nipper 
15784de9d0b5SLee Nipper 	/* first DWORD empty */
15792529bc37SLEROY Christophe 	desc->ptr[0] = zero_entry;
15804de9d0b5SLee Nipper 
15814de9d0b5SLee Nipper 	/* cipher iv */
1582922f9dc8SLEROY Christophe 	to_talitos_ptr(&desc->ptr[1], edesc->iv_dma, is_sec1);
1583922f9dc8SLEROY Christophe 	to_talitos_ptr_len(&desc->ptr[1], ivsize, is_sec1);
1584b096b544SLEROY Christophe 	to_talitos_ptr_ext_set(&desc->ptr[1], 0, is_sec1);
15854de9d0b5SLee Nipper 
15864de9d0b5SLee Nipper 	/* cipher key */
15874de9d0b5SLee Nipper 	map_single_talitos_ptr(dev, &desc->ptr[2], ctx->keylen,
1588a2b35aa8SLEROY Christophe 			       (char *)&ctx->key, DMA_TO_DEVICE);
15894de9d0b5SLee Nipper 
15906a1e8d14SLEROY Christophe 	sg_count = edesc->src_nents ?: 1;
15916a1e8d14SLEROY Christophe 	if (is_sec1 && sg_count > 1)
15926a1e8d14SLEROY Christophe 		sg_copy_to_buffer(areq->src, sg_count, edesc->buf,
15936a1e8d14SLEROY Christophe 				  cryptlen);
15946a1e8d14SLEROY Christophe 	else
15956a1e8d14SLEROY Christophe 		sg_count = dma_map_sg(dev, areq->src, sg_count,
15966a1e8d14SLEROY Christophe 				      (areq->src == areq->dst) ?
15976a1e8d14SLEROY Christophe 				      DMA_BIDIRECTIONAL : DMA_TO_DEVICE);
15984de9d0b5SLee Nipper 	/*
15994de9d0b5SLee Nipper 	 * cipher in
16004de9d0b5SLee Nipper 	 */
16016a1e8d14SLEROY Christophe 	sg_count = talitos_sg_map(dev, areq->src, cryptlen, edesc,
16026a1e8d14SLEROY Christophe 				  &desc->ptr[3], sg_count, 0, 0);
16036a1e8d14SLEROY Christophe 	if (sg_count > 1)
16046a1e8d14SLEROY Christophe 		sync_needed = true;
16054de9d0b5SLee Nipper 
16064de9d0b5SLee Nipper 	/* cipher out */
16076a1e8d14SLEROY Christophe 	if (areq->src != areq->dst) {
16086a1e8d14SLEROY Christophe 		sg_count = edesc->dst_nents ? : 1;
16096a1e8d14SLEROY Christophe 		if (!is_sec1 || sg_count == 1)
16106a1e8d14SLEROY Christophe 			dma_map_sg(dev, areq->dst, sg_count, DMA_FROM_DEVICE);
16116a1e8d14SLEROY Christophe 	}
16126a1e8d14SLEROY Christophe 
16136a1e8d14SLEROY Christophe 	ret = talitos_sg_map(dev, areq->dst, cryptlen, edesc, &desc->ptr[4],
16146a1e8d14SLEROY Christophe 			     sg_count, 0, (edesc->src_nents + 1));
16156a1e8d14SLEROY Christophe 	if (ret > 1)
16166a1e8d14SLEROY Christophe 		sync_needed = true;
16174de9d0b5SLee Nipper 
16184de9d0b5SLee Nipper 	/* iv out */
1619a2b35aa8SLEROY Christophe 	map_single_talitos_ptr(dev, &desc->ptr[5], ivsize, ctx->iv,
16204de9d0b5SLee Nipper 			       DMA_FROM_DEVICE);
16214de9d0b5SLee Nipper 
16224de9d0b5SLee Nipper 	/* last DWORD empty */
16232529bc37SLEROY Christophe 	desc->ptr[6] = zero_entry;
16244de9d0b5SLee Nipper 
16256a1e8d14SLEROY Christophe 	if (sync_needed)
16266a1e8d14SLEROY Christophe 		dma_sync_single_for_device(dev, edesc->dma_link_tbl,
16276a1e8d14SLEROY Christophe 					   edesc->dma_len, DMA_BIDIRECTIONAL);
16286a1e8d14SLEROY Christophe 
16295228f0f7SKim Phillips 	ret = talitos_submit(dev, ctx->ch, desc, callback, areq);
16304de9d0b5SLee Nipper 	if (ret != -EINPROGRESS) {
16314de9d0b5SLee Nipper 		common_nonsnoop_unmap(dev, edesc, areq);
16324de9d0b5SLee Nipper 		kfree(edesc);
16334de9d0b5SLee Nipper 	}
16344de9d0b5SLee Nipper 	return ret;
16354de9d0b5SLee Nipper }
16364de9d0b5SLee Nipper 
1637e938e465SKim Phillips static struct talitos_edesc *ablkcipher_edesc_alloc(struct ablkcipher_request *
163862293a37SHoria Geanta 						    areq, bool encrypt)
16394de9d0b5SLee Nipper {
16404de9d0b5SLee Nipper 	struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(areq);
16414de9d0b5SLee Nipper 	struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher);
164279fd31d3SHoria Geanta 	unsigned int ivsize = crypto_ablkcipher_ivsize(cipher);
16434de9d0b5SLee Nipper 
1644aeb4c132SHerbert Xu 	return talitos_edesc_alloc(ctx->dev, areq->src, areq->dst,
164579fd31d3SHoria Geanta 				   areq->info, 0, areq->nbytes, 0, ivsize, 0,
164662293a37SHoria Geanta 				   areq->base.flags, encrypt);
16474de9d0b5SLee Nipper }
16484de9d0b5SLee Nipper 
16494de9d0b5SLee Nipper static int ablkcipher_encrypt(struct ablkcipher_request *areq)
16504de9d0b5SLee Nipper {
16514de9d0b5SLee Nipper 	struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(areq);
16524de9d0b5SLee Nipper 	struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher);
16534de9d0b5SLee Nipper 	struct talitos_edesc *edesc;
16544de9d0b5SLee Nipper 
16554de9d0b5SLee Nipper 	/* allocate extended descriptor */
165662293a37SHoria Geanta 	edesc = ablkcipher_edesc_alloc(areq, true);
16574de9d0b5SLee Nipper 	if (IS_ERR(edesc))
16584de9d0b5SLee Nipper 		return PTR_ERR(edesc);
16594de9d0b5SLee Nipper 
16604de9d0b5SLee Nipper 	/* set encrypt */
16614de9d0b5SLee Nipper 	edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_MODE0_ENCRYPT;
16624de9d0b5SLee Nipper 
1663febec542SKim Phillips 	return common_nonsnoop(edesc, areq, ablkcipher_done);
16644de9d0b5SLee Nipper }
16654de9d0b5SLee Nipper 
16664de9d0b5SLee Nipper static int ablkcipher_decrypt(struct ablkcipher_request *areq)
16674de9d0b5SLee Nipper {
16684de9d0b5SLee Nipper 	struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(areq);
16694de9d0b5SLee Nipper 	struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher);
16704de9d0b5SLee Nipper 	struct talitos_edesc *edesc;
16714de9d0b5SLee Nipper 
16724de9d0b5SLee Nipper 	/* allocate extended descriptor */
167362293a37SHoria Geanta 	edesc = ablkcipher_edesc_alloc(areq, false);
16744de9d0b5SLee Nipper 	if (IS_ERR(edesc))
16754de9d0b5SLee Nipper 		return PTR_ERR(edesc);
16764de9d0b5SLee Nipper 
16774de9d0b5SLee Nipper 	edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_DIR_INBOUND;
16784de9d0b5SLee Nipper 
1679febec542SKim Phillips 	return common_nonsnoop(edesc, areq, ablkcipher_done);
16804de9d0b5SLee Nipper }
16814de9d0b5SLee Nipper 
1682497f2e6bSLee Nipper static void common_nonsnoop_hash_unmap(struct device *dev,
1683497f2e6bSLee Nipper 				       struct talitos_edesc *edesc,
1684497f2e6bSLee Nipper 				       struct ahash_request *areq)
1685497f2e6bSLee Nipper {
1686497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
1687922f9dc8SLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
1688922f9dc8SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
1689497f2e6bSLee Nipper 
1690497f2e6bSLee Nipper 	unmap_single_talitos_ptr(dev, &edesc->desc.ptr[5], DMA_FROM_DEVICE);
1691497f2e6bSLee Nipper 
16926a1e8d14SLEROY Christophe 	talitos_sg_unmap(dev, edesc, req_ctx->psrc, NULL, 0, 0);
1693032d197eSLEROY Christophe 
1694497f2e6bSLee Nipper 	/* When using hashctx-in, must unmap it. */
1695922f9dc8SLEROY Christophe 	if (from_talitos_ptr_len(&edesc->desc.ptr[1], is_sec1))
1696497f2e6bSLee Nipper 		unmap_single_talitos_ptr(dev, &edesc->desc.ptr[1],
1697497f2e6bSLee Nipper 					 DMA_TO_DEVICE);
1698497f2e6bSLee Nipper 
1699922f9dc8SLEROY Christophe 	if (from_talitos_ptr_len(&edesc->desc.ptr[2], is_sec1))
1700497f2e6bSLee Nipper 		unmap_single_talitos_ptr(dev, &edesc->desc.ptr[2],
1701497f2e6bSLee Nipper 					 DMA_TO_DEVICE);
1702497f2e6bSLee Nipper 
1703497f2e6bSLee Nipper 	if (edesc->dma_len)
1704497f2e6bSLee Nipper 		dma_unmap_single(dev, edesc->dma_link_tbl, edesc->dma_len,
1705497f2e6bSLee Nipper 				 DMA_BIDIRECTIONAL);
1706497f2e6bSLee Nipper 
1707497f2e6bSLee Nipper }
1708497f2e6bSLee Nipper 
1709497f2e6bSLee Nipper static void ahash_done(struct device *dev,
1710497f2e6bSLee Nipper 		       struct talitos_desc *desc, void *context,
1711497f2e6bSLee Nipper 		       int err)
1712497f2e6bSLee Nipper {
1713497f2e6bSLee Nipper 	struct ahash_request *areq = context;
1714497f2e6bSLee Nipper 	struct talitos_edesc *edesc =
1715497f2e6bSLee Nipper 		 container_of(desc, struct talitos_edesc, desc);
1716497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
1717497f2e6bSLee Nipper 
1718497f2e6bSLee Nipper 	if (!req_ctx->last && req_ctx->to_hash_later) {
1719497f2e6bSLee Nipper 		/* Position any partial block for next update/final/finup */
1720497f2e6bSLee Nipper 		memcpy(req_ctx->buf, req_ctx->bufnext, req_ctx->to_hash_later);
17215e833bc4SLee Nipper 		req_ctx->nbuf = req_ctx->to_hash_later;
1722497f2e6bSLee Nipper 	}
1723497f2e6bSLee Nipper 	common_nonsnoop_hash_unmap(dev, edesc, areq);
1724497f2e6bSLee Nipper 
1725497f2e6bSLee Nipper 	kfree(edesc);
1726497f2e6bSLee Nipper 
1727497f2e6bSLee Nipper 	areq->base.complete(&areq->base, err);
1728497f2e6bSLee Nipper }
1729497f2e6bSLee Nipper 
17302d02905eSLEROY Christophe /*
17312d02905eSLEROY Christophe  * SEC1 doesn't like hashing of 0 sized message, so we do the padding
17322d02905eSLEROY Christophe  * ourself and submit a padded block
17332d02905eSLEROY Christophe  */
17342d02905eSLEROY Christophe void talitos_handle_buggy_hash(struct talitos_ctx *ctx,
17352d02905eSLEROY Christophe 			       struct talitos_edesc *edesc,
17362d02905eSLEROY Christophe 			       struct talitos_ptr *ptr)
17372d02905eSLEROY Christophe {
17382d02905eSLEROY Christophe 	static u8 padded_hash[64] = {
17392d02905eSLEROY Christophe 		0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
17402d02905eSLEROY Christophe 		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
17412d02905eSLEROY Christophe 		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
17422d02905eSLEROY Christophe 		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
17432d02905eSLEROY Christophe 	};
17442d02905eSLEROY Christophe 
17452d02905eSLEROY Christophe 	pr_err_once("Bug in SEC1, padding ourself\n");
17462d02905eSLEROY Christophe 	edesc->desc.hdr &= ~DESC_HDR_MODE0_MDEU_PAD;
17472d02905eSLEROY Christophe 	map_single_talitos_ptr(ctx->dev, ptr, sizeof(padded_hash),
17482d02905eSLEROY Christophe 			       (char *)padded_hash, DMA_TO_DEVICE);
17492d02905eSLEROY Christophe }
17502d02905eSLEROY Christophe 
1751497f2e6bSLee Nipper static int common_nonsnoop_hash(struct talitos_edesc *edesc,
1752497f2e6bSLee Nipper 				struct ahash_request *areq, unsigned int length,
1753497f2e6bSLee Nipper 				void (*callback) (struct device *dev,
1754497f2e6bSLee Nipper 						  struct talitos_desc *desc,
1755497f2e6bSLee Nipper 						  void *context, int error))
1756497f2e6bSLee Nipper {
1757497f2e6bSLee Nipper 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
1758497f2e6bSLee Nipper 	struct talitos_ctx *ctx = crypto_ahash_ctx(tfm);
1759497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
1760497f2e6bSLee Nipper 	struct device *dev = ctx->dev;
1761497f2e6bSLee Nipper 	struct talitos_desc *desc = &edesc->desc;
1762032d197eSLEROY Christophe 	int ret;
17636a1e8d14SLEROY Christophe 	bool sync_needed = false;
1764922f9dc8SLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
1765922f9dc8SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
17666a1e8d14SLEROY Christophe 	int sg_count;
1767497f2e6bSLee Nipper 
1768497f2e6bSLee Nipper 	/* first DWORD empty */
1769497f2e6bSLee Nipper 	desc->ptr[0] = zero_entry;
1770497f2e6bSLee Nipper 
177160f208d7SKim Phillips 	/* hash context in */
177260f208d7SKim Phillips 	if (!req_ctx->first || req_ctx->swinit) {
1773497f2e6bSLee Nipper 		map_single_talitos_ptr(dev, &desc->ptr[1],
1774497f2e6bSLee Nipper 				       req_ctx->hw_context_size,
1775a2b35aa8SLEROY Christophe 				       (char *)req_ctx->hw_context,
1776497f2e6bSLee Nipper 				       DMA_TO_DEVICE);
177760f208d7SKim Phillips 		req_ctx->swinit = 0;
1778497f2e6bSLee Nipper 	} else {
1779497f2e6bSLee Nipper 		desc->ptr[1] = zero_entry;
1780afd62fa2SLEROY Christophe 	}
1781497f2e6bSLee Nipper 	/* Indicate next op is not the first. */
1782497f2e6bSLee Nipper 	req_ctx->first = 0;
1783497f2e6bSLee Nipper 
1784497f2e6bSLee Nipper 	/* HMAC key */
1785497f2e6bSLee Nipper 	if (ctx->keylen)
1786497f2e6bSLee Nipper 		map_single_talitos_ptr(dev, &desc->ptr[2], ctx->keylen,
1787a2b35aa8SLEROY Christophe 				       (char *)&ctx->key, DMA_TO_DEVICE);
1788497f2e6bSLee Nipper 	else
1789497f2e6bSLee Nipper 		desc->ptr[2] = zero_entry;
1790497f2e6bSLee Nipper 
17916a1e8d14SLEROY Christophe 	sg_count = edesc->src_nents ?: 1;
17926a1e8d14SLEROY Christophe 	if (is_sec1 && sg_count > 1)
1793886a27c0SLEROY Christophe 		sg_copy_to_buffer(req_ctx->psrc, sg_count, edesc->buf, length);
17946a1e8d14SLEROY Christophe 	else
17956a1e8d14SLEROY Christophe 		sg_count = dma_map_sg(dev, req_ctx->psrc, sg_count,
17966a1e8d14SLEROY Christophe 				      DMA_TO_DEVICE);
1797497f2e6bSLee Nipper 	/*
1798497f2e6bSLee Nipper 	 * data in
1799497f2e6bSLee Nipper 	 */
18006a1e8d14SLEROY Christophe 	sg_count = talitos_sg_map(dev, req_ctx->psrc, length, edesc,
18016a1e8d14SLEROY Christophe 				  &desc->ptr[3], sg_count, 0, 0);
18026a1e8d14SLEROY Christophe 	if (sg_count > 1)
18036a1e8d14SLEROY Christophe 		sync_needed = true;
1804497f2e6bSLee Nipper 
1805497f2e6bSLee Nipper 	/* fifth DWORD empty */
1806497f2e6bSLee Nipper 	desc->ptr[4] = zero_entry;
1807497f2e6bSLee Nipper 
1808497f2e6bSLee Nipper 	/* hash/HMAC out -or- hash context out */
1809497f2e6bSLee Nipper 	if (req_ctx->last)
1810497f2e6bSLee Nipper 		map_single_talitos_ptr(dev, &desc->ptr[5],
1811497f2e6bSLee Nipper 				       crypto_ahash_digestsize(tfm),
1812a2b35aa8SLEROY Christophe 				       areq->result, DMA_FROM_DEVICE);
1813497f2e6bSLee Nipper 	else
1814497f2e6bSLee Nipper 		map_single_talitos_ptr(dev, &desc->ptr[5],
1815497f2e6bSLee Nipper 				       req_ctx->hw_context_size,
1816a2b35aa8SLEROY Christophe 				       req_ctx->hw_context, DMA_FROM_DEVICE);
1817497f2e6bSLee Nipper 
1818497f2e6bSLee Nipper 	/* last DWORD empty */
1819497f2e6bSLee Nipper 	desc->ptr[6] = zero_entry;
1820497f2e6bSLee Nipper 
18212d02905eSLEROY Christophe 	if (is_sec1 && from_talitos_ptr_len(&desc->ptr[3], true) == 0)
18222d02905eSLEROY Christophe 		talitos_handle_buggy_hash(ctx, edesc, &desc->ptr[3]);
18232d02905eSLEROY Christophe 
18246a1e8d14SLEROY Christophe 	if (sync_needed)
18256a1e8d14SLEROY Christophe 		dma_sync_single_for_device(dev, edesc->dma_link_tbl,
18266a1e8d14SLEROY Christophe 					   edesc->dma_len, DMA_BIDIRECTIONAL);
18276a1e8d14SLEROY Christophe 
18285228f0f7SKim Phillips 	ret = talitos_submit(dev, ctx->ch, desc, callback, areq);
1829497f2e6bSLee Nipper 	if (ret != -EINPROGRESS) {
1830497f2e6bSLee Nipper 		common_nonsnoop_hash_unmap(dev, edesc, areq);
1831497f2e6bSLee Nipper 		kfree(edesc);
1832497f2e6bSLee Nipper 	}
1833497f2e6bSLee Nipper 	return ret;
1834497f2e6bSLee Nipper }
1835497f2e6bSLee Nipper 
1836497f2e6bSLee Nipper static struct talitos_edesc *ahash_edesc_alloc(struct ahash_request *areq,
1837497f2e6bSLee Nipper 					       unsigned int nbytes)
1838497f2e6bSLee Nipper {
1839497f2e6bSLee Nipper 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
1840497f2e6bSLee Nipper 	struct talitos_ctx *ctx = crypto_ahash_ctx(tfm);
1841497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
1842497f2e6bSLee Nipper 
1843aeb4c132SHerbert Xu 	return talitos_edesc_alloc(ctx->dev, req_ctx->psrc, NULL, NULL, 0,
184462293a37SHoria Geanta 				   nbytes, 0, 0, 0, areq->base.flags, false);
1845497f2e6bSLee Nipper }
1846497f2e6bSLee Nipper 
1847497f2e6bSLee Nipper static int ahash_init(struct ahash_request *areq)
1848497f2e6bSLee Nipper {
1849497f2e6bSLee Nipper 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
1850497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
1851497f2e6bSLee Nipper 
1852497f2e6bSLee Nipper 	/* Initialize the context */
18535e833bc4SLee Nipper 	req_ctx->nbuf = 0;
185460f208d7SKim Phillips 	req_ctx->first = 1; /* first indicates h/w must init its context */
185560f208d7SKim Phillips 	req_ctx->swinit = 0; /* assume h/w init of context */
1856497f2e6bSLee Nipper 	req_ctx->hw_context_size =
1857497f2e6bSLee Nipper 		(crypto_ahash_digestsize(tfm) <= SHA256_DIGEST_SIZE)
1858497f2e6bSLee Nipper 			? TALITOS_MDEU_CONTEXT_SIZE_MD5_SHA1_SHA256
1859497f2e6bSLee Nipper 			: TALITOS_MDEU_CONTEXT_SIZE_SHA384_SHA512;
1860497f2e6bSLee Nipper 
1861497f2e6bSLee Nipper 	return 0;
1862497f2e6bSLee Nipper }
1863497f2e6bSLee Nipper 
186460f208d7SKim Phillips /*
186560f208d7SKim Phillips  * on h/w without explicit sha224 support, we initialize h/w context
186660f208d7SKim Phillips  * manually with sha224 constants, and tell it to run sha256.
186760f208d7SKim Phillips  */
186860f208d7SKim Phillips static int ahash_init_sha224_swinit(struct ahash_request *areq)
186960f208d7SKim Phillips {
187060f208d7SKim Phillips 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
187160f208d7SKim Phillips 
187260f208d7SKim Phillips 	ahash_init(areq);
187360f208d7SKim Phillips 	req_ctx->swinit = 1;/* prevent h/w initting context with sha256 values*/
187460f208d7SKim Phillips 
1875a752447aSKim Phillips 	req_ctx->hw_context[0] = SHA224_H0;
1876a752447aSKim Phillips 	req_ctx->hw_context[1] = SHA224_H1;
1877a752447aSKim Phillips 	req_ctx->hw_context[2] = SHA224_H2;
1878a752447aSKim Phillips 	req_ctx->hw_context[3] = SHA224_H3;
1879a752447aSKim Phillips 	req_ctx->hw_context[4] = SHA224_H4;
1880a752447aSKim Phillips 	req_ctx->hw_context[5] = SHA224_H5;
1881a752447aSKim Phillips 	req_ctx->hw_context[6] = SHA224_H6;
1882a752447aSKim Phillips 	req_ctx->hw_context[7] = SHA224_H7;
188360f208d7SKim Phillips 
188460f208d7SKim Phillips 	/* init 64-bit count */
188560f208d7SKim Phillips 	req_ctx->hw_context[8] = 0;
188660f208d7SKim Phillips 	req_ctx->hw_context[9] = 0;
188760f208d7SKim Phillips 
188860f208d7SKim Phillips 	return 0;
188960f208d7SKim Phillips }
189060f208d7SKim Phillips 
1891497f2e6bSLee Nipper static int ahash_process_req(struct ahash_request *areq, unsigned int nbytes)
1892497f2e6bSLee Nipper {
1893497f2e6bSLee Nipper 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
1894497f2e6bSLee Nipper 	struct talitos_ctx *ctx = crypto_ahash_ctx(tfm);
1895497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
1896497f2e6bSLee Nipper 	struct talitos_edesc *edesc;
1897497f2e6bSLee Nipper 	unsigned int blocksize =
1898497f2e6bSLee Nipper 			crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm));
1899497f2e6bSLee Nipper 	unsigned int nbytes_to_hash;
1900497f2e6bSLee Nipper 	unsigned int to_hash_later;
19015e833bc4SLee Nipper 	unsigned int nsg;
19028e409fe1SLABBE Corentin 	int nents;
1903497f2e6bSLee Nipper 
19045e833bc4SLee Nipper 	if (!req_ctx->last && (nbytes + req_ctx->nbuf <= blocksize)) {
19055e833bc4SLee Nipper 		/* Buffer up to one whole block */
19068e409fe1SLABBE Corentin 		nents = sg_nents_for_len(areq->src, nbytes);
19078e409fe1SLABBE Corentin 		if (nents < 0) {
19088e409fe1SLABBE Corentin 			dev_err(ctx->dev, "Invalid number of src SG.\n");
19098e409fe1SLABBE Corentin 			return nents;
19108e409fe1SLABBE Corentin 		}
19118e409fe1SLABBE Corentin 		sg_copy_to_buffer(areq->src, nents,
19125e833bc4SLee Nipper 				  req_ctx->buf + req_ctx->nbuf, nbytes);
19135e833bc4SLee Nipper 		req_ctx->nbuf += nbytes;
1914497f2e6bSLee Nipper 		return 0;
1915497f2e6bSLee Nipper 	}
1916497f2e6bSLee Nipper 
19175e833bc4SLee Nipper 	/* At least (blocksize + 1) bytes are available to hash */
19185e833bc4SLee Nipper 	nbytes_to_hash = nbytes + req_ctx->nbuf;
19195e833bc4SLee Nipper 	to_hash_later = nbytes_to_hash & (blocksize - 1);
19205e833bc4SLee Nipper 
19215e833bc4SLee Nipper 	if (req_ctx->last)
19225e833bc4SLee Nipper 		to_hash_later = 0;
19235e833bc4SLee Nipper 	else if (to_hash_later)
19245e833bc4SLee Nipper 		/* There is a partial block. Hash the full block(s) now */
19255e833bc4SLee Nipper 		nbytes_to_hash -= to_hash_later;
19265e833bc4SLee Nipper 	else {
19275e833bc4SLee Nipper 		/* Keep one block buffered */
19285e833bc4SLee Nipper 		nbytes_to_hash -= blocksize;
19295e833bc4SLee Nipper 		to_hash_later = blocksize;
1930497f2e6bSLee Nipper 	}
19315e833bc4SLee Nipper 
19325e833bc4SLee Nipper 	/* Chain in any previously buffered data */
19335e833bc4SLee Nipper 	if (req_ctx->nbuf) {
19345e833bc4SLee Nipper 		nsg = (req_ctx->nbuf < nbytes_to_hash) ? 2 : 1;
19355e833bc4SLee Nipper 		sg_init_table(req_ctx->bufsl, nsg);
19365e833bc4SLee Nipper 		sg_set_buf(req_ctx->bufsl, req_ctx->buf, req_ctx->nbuf);
19375e833bc4SLee Nipper 		if (nsg > 1)
1938c56f6d12SDan Williams 			sg_chain(req_ctx->bufsl, 2, areq->src);
19395e833bc4SLee Nipper 		req_ctx->psrc = req_ctx->bufsl;
19405e833bc4SLee Nipper 	} else
19415e833bc4SLee Nipper 		req_ctx->psrc = areq->src;
19425e833bc4SLee Nipper 
1943497f2e6bSLee Nipper 	if (to_hash_later) {
19448e409fe1SLABBE Corentin 		nents = sg_nents_for_len(areq->src, nbytes);
19458e409fe1SLABBE Corentin 		if (nents < 0) {
19468e409fe1SLABBE Corentin 			dev_err(ctx->dev, "Invalid number of src SG.\n");
19478e409fe1SLABBE Corentin 			return nents;
19488e409fe1SLABBE Corentin 		}
1949d0525723SAkinobu Mita 		sg_pcopy_to_buffer(areq->src, nents,
1950497f2e6bSLee Nipper 				      req_ctx->bufnext,
1951497f2e6bSLee Nipper 				      to_hash_later,
1952497f2e6bSLee Nipper 				      nbytes - to_hash_later);
1953497f2e6bSLee Nipper 	}
1954497f2e6bSLee Nipper 	req_ctx->to_hash_later = to_hash_later;
1955497f2e6bSLee Nipper 
19565e833bc4SLee Nipper 	/* Allocate extended descriptor */
1957497f2e6bSLee Nipper 	edesc = ahash_edesc_alloc(areq, nbytes_to_hash);
1958497f2e6bSLee Nipper 	if (IS_ERR(edesc))
1959497f2e6bSLee Nipper 		return PTR_ERR(edesc);
1960497f2e6bSLee Nipper 
1961497f2e6bSLee Nipper 	edesc->desc.hdr = ctx->desc_hdr_template;
1962497f2e6bSLee Nipper 
1963497f2e6bSLee Nipper 	/* On last one, request SEC to pad; otherwise continue */
1964497f2e6bSLee Nipper 	if (req_ctx->last)
1965497f2e6bSLee Nipper 		edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_PAD;
1966497f2e6bSLee Nipper 	else
1967497f2e6bSLee Nipper 		edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_CONT;
1968497f2e6bSLee Nipper 
196960f208d7SKim Phillips 	/* request SEC to INIT hash. */
197060f208d7SKim Phillips 	if (req_ctx->first && !req_ctx->swinit)
1971497f2e6bSLee Nipper 		edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_INIT;
1972497f2e6bSLee Nipper 
1973497f2e6bSLee Nipper 	/* When the tfm context has a keylen, it's an HMAC.
1974497f2e6bSLee Nipper 	 * A first or last (ie. not middle) descriptor must request HMAC.
1975497f2e6bSLee Nipper 	 */
1976497f2e6bSLee Nipper 	if (ctx->keylen && (req_ctx->first || req_ctx->last))
1977497f2e6bSLee Nipper 		edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_HMAC;
1978497f2e6bSLee Nipper 
1979497f2e6bSLee Nipper 	return common_nonsnoop_hash(edesc, areq, nbytes_to_hash,
1980497f2e6bSLee Nipper 				    ahash_done);
1981497f2e6bSLee Nipper }
1982497f2e6bSLee Nipper 
1983497f2e6bSLee Nipper static int ahash_update(struct ahash_request *areq)
1984497f2e6bSLee Nipper {
1985497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
1986497f2e6bSLee Nipper 
1987497f2e6bSLee Nipper 	req_ctx->last = 0;
1988497f2e6bSLee Nipper 
1989497f2e6bSLee Nipper 	return ahash_process_req(areq, areq->nbytes);
1990497f2e6bSLee Nipper }
1991497f2e6bSLee Nipper 
1992497f2e6bSLee Nipper static int ahash_final(struct ahash_request *areq)
1993497f2e6bSLee Nipper {
1994497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
1995497f2e6bSLee Nipper 
1996497f2e6bSLee Nipper 	req_ctx->last = 1;
1997497f2e6bSLee Nipper 
1998497f2e6bSLee Nipper 	return ahash_process_req(areq, 0);
1999497f2e6bSLee Nipper }
2000497f2e6bSLee Nipper 
2001497f2e6bSLee Nipper static int ahash_finup(struct ahash_request *areq)
2002497f2e6bSLee Nipper {
2003497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
2004497f2e6bSLee Nipper 
2005497f2e6bSLee Nipper 	req_ctx->last = 1;
2006497f2e6bSLee Nipper 
2007497f2e6bSLee Nipper 	return ahash_process_req(areq, areq->nbytes);
2008497f2e6bSLee Nipper }
2009497f2e6bSLee Nipper 
2010497f2e6bSLee Nipper static int ahash_digest(struct ahash_request *areq)
2011497f2e6bSLee Nipper {
2012497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
201360f208d7SKim Phillips 	struct crypto_ahash *ahash = crypto_ahash_reqtfm(areq);
2014497f2e6bSLee Nipper 
201560f208d7SKim Phillips 	ahash->init(areq);
2016497f2e6bSLee Nipper 	req_ctx->last = 1;
2017497f2e6bSLee Nipper 
2018497f2e6bSLee Nipper 	return ahash_process_req(areq, areq->nbytes);
2019497f2e6bSLee Nipper }
2020497f2e6bSLee Nipper 
20213639ca84SHoria Geant? static int ahash_export(struct ahash_request *areq, void *out)
20223639ca84SHoria Geant? {
20233639ca84SHoria Geant? 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
20243639ca84SHoria Geant? 	struct talitos_export_state *export = out;
20253639ca84SHoria Geant? 
20263639ca84SHoria Geant? 	memcpy(export->hw_context, req_ctx->hw_context,
20273639ca84SHoria Geant? 	       req_ctx->hw_context_size);
20283639ca84SHoria Geant? 	memcpy(export->buf, req_ctx->buf, req_ctx->nbuf);
20293639ca84SHoria Geant? 	export->swinit = req_ctx->swinit;
20303639ca84SHoria Geant? 	export->first = req_ctx->first;
20313639ca84SHoria Geant? 	export->last = req_ctx->last;
20323639ca84SHoria Geant? 	export->to_hash_later = req_ctx->to_hash_later;
20333639ca84SHoria Geant? 	export->nbuf = req_ctx->nbuf;
20343639ca84SHoria Geant? 
20353639ca84SHoria Geant? 	return 0;
20363639ca84SHoria Geant? }
20373639ca84SHoria Geant? 
20383639ca84SHoria Geant? static int ahash_import(struct ahash_request *areq, const void *in)
20393639ca84SHoria Geant? {
20403639ca84SHoria Geant? 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
20413639ca84SHoria Geant? 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
20423639ca84SHoria Geant? 	const struct talitos_export_state *export = in;
20433639ca84SHoria Geant? 
20443639ca84SHoria Geant? 	memset(req_ctx, 0, sizeof(*req_ctx));
20453639ca84SHoria Geant? 	req_ctx->hw_context_size =
20463639ca84SHoria Geant? 		(crypto_ahash_digestsize(tfm) <= SHA256_DIGEST_SIZE)
20473639ca84SHoria Geant? 			? TALITOS_MDEU_CONTEXT_SIZE_MD5_SHA1_SHA256
20483639ca84SHoria Geant? 			: TALITOS_MDEU_CONTEXT_SIZE_SHA384_SHA512;
20493639ca84SHoria Geant? 	memcpy(req_ctx->hw_context, export->hw_context,
20503639ca84SHoria Geant? 	       req_ctx->hw_context_size);
20513639ca84SHoria Geant? 	memcpy(req_ctx->buf, export->buf, export->nbuf);
20523639ca84SHoria Geant? 	req_ctx->swinit = export->swinit;
20533639ca84SHoria Geant? 	req_ctx->first = export->first;
20543639ca84SHoria Geant? 	req_ctx->last = export->last;
20553639ca84SHoria Geant? 	req_ctx->to_hash_later = export->to_hash_later;
20563639ca84SHoria Geant? 	req_ctx->nbuf = export->nbuf;
20573639ca84SHoria Geant? 
20583639ca84SHoria Geant? 	return 0;
20593639ca84SHoria Geant? }
20603639ca84SHoria Geant? 
206179b3a418SLee Nipper struct keyhash_result {
206279b3a418SLee Nipper 	struct completion completion;
206379b3a418SLee Nipper 	int err;
206479b3a418SLee Nipper };
206579b3a418SLee Nipper 
206679b3a418SLee Nipper static void keyhash_complete(struct crypto_async_request *req, int err)
206779b3a418SLee Nipper {
206879b3a418SLee Nipper 	struct keyhash_result *res = req->data;
206979b3a418SLee Nipper 
207079b3a418SLee Nipper 	if (err == -EINPROGRESS)
207179b3a418SLee Nipper 		return;
207279b3a418SLee Nipper 
207379b3a418SLee Nipper 	res->err = err;
207479b3a418SLee Nipper 	complete(&res->completion);
207579b3a418SLee Nipper }
207679b3a418SLee Nipper 
207779b3a418SLee Nipper static int keyhash(struct crypto_ahash *tfm, const u8 *key, unsigned int keylen,
207879b3a418SLee Nipper 		   u8 *hash)
207979b3a418SLee Nipper {
208079b3a418SLee Nipper 	struct talitos_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm));
208179b3a418SLee Nipper 
208279b3a418SLee Nipper 	struct scatterlist sg[1];
208379b3a418SLee Nipper 	struct ahash_request *req;
208479b3a418SLee Nipper 	struct keyhash_result hresult;
208579b3a418SLee Nipper 	int ret;
208679b3a418SLee Nipper 
208779b3a418SLee Nipper 	init_completion(&hresult.completion);
208879b3a418SLee Nipper 
208979b3a418SLee Nipper 	req = ahash_request_alloc(tfm, GFP_KERNEL);
209079b3a418SLee Nipper 	if (!req)
209179b3a418SLee Nipper 		return -ENOMEM;
209279b3a418SLee Nipper 
209379b3a418SLee Nipper 	/* Keep tfm keylen == 0 during hash of the long key */
209479b3a418SLee Nipper 	ctx->keylen = 0;
209579b3a418SLee Nipper 	ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
209679b3a418SLee Nipper 				   keyhash_complete, &hresult);
209779b3a418SLee Nipper 
209879b3a418SLee Nipper 	sg_init_one(&sg[0], key, keylen);
209979b3a418SLee Nipper 
210079b3a418SLee Nipper 	ahash_request_set_crypt(req, sg, hash, keylen);
210179b3a418SLee Nipper 	ret = crypto_ahash_digest(req);
210279b3a418SLee Nipper 	switch (ret) {
210379b3a418SLee Nipper 	case 0:
210479b3a418SLee Nipper 		break;
210579b3a418SLee Nipper 	case -EINPROGRESS:
210679b3a418SLee Nipper 	case -EBUSY:
210779b3a418SLee Nipper 		ret = wait_for_completion_interruptible(
210879b3a418SLee Nipper 			&hresult.completion);
210979b3a418SLee Nipper 		if (!ret)
211079b3a418SLee Nipper 			ret = hresult.err;
211179b3a418SLee Nipper 		break;
211279b3a418SLee Nipper 	default:
211379b3a418SLee Nipper 		break;
211479b3a418SLee Nipper 	}
211579b3a418SLee Nipper 	ahash_request_free(req);
211679b3a418SLee Nipper 
211779b3a418SLee Nipper 	return ret;
211879b3a418SLee Nipper }
211979b3a418SLee Nipper 
212079b3a418SLee Nipper static int ahash_setkey(struct crypto_ahash *tfm, const u8 *key,
212179b3a418SLee Nipper 			unsigned int keylen)
212279b3a418SLee Nipper {
212379b3a418SLee Nipper 	struct talitos_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm));
212479b3a418SLee Nipper 	unsigned int blocksize =
212579b3a418SLee Nipper 			crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm));
212679b3a418SLee Nipper 	unsigned int digestsize = crypto_ahash_digestsize(tfm);
212779b3a418SLee Nipper 	unsigned int keysize = keylen;
212879b3a418SLee Nipper 	u8 hash[SHA512_DIGEST_SIZE];
212979b3a418SLee Nipper 	int ret;
213079b3a418SLee Nipper 
213179b3a418SLee Nipper 	if (keylen <= blocksize)
213279b3a418SLee Nipper 		memcpy(ctx->key, key, keysize);
213379b3a418SLee Nipper 	else {
213479b3a418SLee Nipper 		/* Must get the hash of the long key */
213579b3a418SLee Nipper 		ret = keyhash(tfm, key, keylen, hash);
213679b3a418SLee Nipper 
213779b3a418SLee Nipper 		if (ret) {
213879b3a418SLee Nipper 			crypto_ahash_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
213979b3a418SLee Nipper 			return -EINVAL;
214079b3a418SLee Nipper 		}
214179b3a418SLee Nipper 
214279b3a418SLee Nipper 		keysize = digestsize;
214379b3a418SLee Nipper 		memcpy(ctx->key, hash, digestsize);
214479b3a418SLee Nipper 	}
214579b3a418SLee Nipper 
214679b3a418SLee Nipper 	ctx->keylen = keysize;
214779b3a418SLee Nipper 
214879b3a418SLee Nipper 	return 0;
214979b3a418SLee Nipper }
215079b3a418SLee Nipper 
215179b3a418SLee Nipper 
21529c4a7965SKim Phillips struct talitos_alg_template {
2153d5e4aaefSLee Nipper 	u32 type;
2154b0057763SLEROY Christophe 	u32 priority;
2155d5e4aaefSLee Nipper 	union {
2156d5e4aaefSLee Nipper 		struct crypto_alg crypto;
2157acbf7c62SLee Nipper 		struct ahash_alg hash;
2158aeb4c132SHerbert Xu 		struct aead_alg aead;
2159d5e4aaefSLee Nipper 	} alg;
21609c4a7965SKim Phillips 	__be32 desc_hdr_template;
21619c4a7965SKim Phillips };
21629c4a7965SKim Phillips 
21639c4a7965SKim Phillips static struct talitos_alg_template driver_algs[] = {
2164991155baSHoria Geanta 	/* AEAD algorithms.  These use a single-pass ipsec_esp descriptor */
2165d5e4aaefSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2166aeb4c132SHerbert Xu 		.alg.aead = {
2167aeb4c132SHerbert Xu 			.base = {
216856af8cd4SLee Nipper 				.cra_name = "authenc(hmac(sha1),cbc(aes))",
2169aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha1-"
2170aeb4c132SHerbert Xu 						   "cbc-aes-talitos",
217156af8cd4SLee Nipper 				.cra_blocksize = AES_BLOCK_SIZE,
2172aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2173aeb4c132SHerbert Xu 			},
21743952f17eSLee Nipper 			.ivsize = AES_BLOCK_SIZE,
21753952f17eSLee Nipper 			.maxauthsize = SHA1_DIGEST_SIZE,
21769c4a7965SKim Phillips 		},
21779c4a7965SKim Phillips 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
21789c4a7965SKim Phillips 			             DESC_HDR_SEL0_AESU |
21799c4a7965SKim Phillips 		                     DESC_HDR_MODE0_AESU_CBC |
21809c4a7965SKim Phillips 		                     DESC_HDR_SEL1_MDEUA |
21819c4a7965SKim Phillips 		                     DESC_HDR_MODE1_MDEU_INIT |
21829c4a7965SKim Phillips 		                     DESC_HDR_MODE1_MDEU_PAD |
21839c4a7965SKim Phillips 		                     DESC_HDR_MODE1_MDEU_SHA1_HMAC,
218470bcaca7SLee Nipper 	},
2185d5e4aaefSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AEAD,
21867405c8d7SLEROY Christophe 		.priority = TALITOS_CRA_PRIORITY_AEAD_HSNA,
21877405c8d7SLEROY Christophe 		.alg.aead = {
21887405c8d7SLEROY Christophe 			.base = {
21897405c8d7SLEROY Christophe 				.cra_name = "authenc(hmac(sha1),cbc(aes))",
21907405c8d7SLEROY Christophe 				.cra_driver_name = "authenc-hmac-sha1-"
21917405c8d7SLEROY Christophe 						   "cbc-aes-talitos",
21927405c8d7SLEROY Christophe 				.cra_blocksize = AES_BLOCK_SIZE,
21937405c8d7SLEROY Christophe 				.cra_flags = CRYPTO_ALG_ASYNC,
21947405c8d7SLEROY Christophe 			},
21957405c8d7SLEROY Christophe 			.ivsize = AES_BLOCK_SIZE,
21967405c8d7SLEROY Christophe 			.maxauthsize = SHA1_DIGEST_SIZE,
21977405c8d7SLEROY Christophe 		},
21987405c8d7SLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU |
21997405c8d7SLEROY Christophe 				     DESC_HDR_SEL0_AESU |
22007405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_AESU_CBC |
22017405c8d7SLEROY Christophe 				     DESC_HDR_SEL1_MDEUA |
22027405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_INIT |
22037405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_PAD |
22047405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_SHA1_HMAC,
22057405c8d7SLEROY Christophe 	},
22067405c8d7SLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2207aeb4c132SHerbert Xu 		.alg.aead = {
2208aeb4c132SHerbert Xu 			.base = {
2209aeb4c132SHerbert Xu 				.cra_name = "authenc(hmac(sha1),"
2210aeb4c132SHerbert Xu 					    "cbc(des3_ede))",
2211aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha1-"
2212aeb4c132SHerbert Xu 						   "cbc-3des-talitos",
221356af8cd4SLee Nipper 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
2214aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2215aeb4c132SHerbert Xu 			},
22163952f17eSLee Nipper 			.ivsize = DES3_EDE_BLOCK_SIZE,
22173952f17eSLee Nipper 			.maxauthsize = SHA1_DIGEST_SIZE,
221870bcaca7SLee Nipper 		},
221970bcaca7SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
222070bcaca7SLee Nipper 			             DESC_HDR_SEL0_DEU |
222170bcaca7SLee Nipper 		                     DESC_HDR_MODE0_DEU_CBC |
222270bcaca7SLee Nipper 		                     DESC_HDR_MODE0_DEU_3DES |
222370bcaca7SLee Nipper 		                     DESC_HDR_SEL1_MDEUA |
222470bcaca7SLee Nipper 		                     DESC_HDR_MODE1_MDEU_INIT |
222570bcaca7SLee Nipper 		                     DESC_HDR_MODE1_MDEU_PAD |
222670bcaca7SLee Nipper 		                     DESC_HDR_MODE1_MDEU_SHA1_HMAC,
22273952f17eSLee Nipper 	},
2228d5e4aaefSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AEAD,
22297405c8d7SLEROY Christophe 		.priority = TALITOS_CRA_PRIORITY_AEAD_HSNA,
22307405c8d7SLEROY Christophe 		.alg.aead = {
22317405c8d7SLEROY Christophe 			.base = {
22327405c8d7SLEROY Christophe 				.cra_name = "authenc(hmac(sha1),"
22337405c8d7SLEROY Christophe 					    "cbc(des3_ede))",
22347405c8d7SLEROY Christophe 				.cra_driver_name = "authenc-hmac-sha1-"
22357405c8d7SLEROY Christophe 						   "cbc-3des-talitos",
22367405c8d7SLEROY Christophe 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
22377405c8d7SLEROY Christophe 				.cra_flags = CRYPTO_ALG_ASYNC,
22387405c8d7SLEROY Christophe 			},
22397405c8d7SLEROY Christophe 			.ivsize = DES3_EDE_BLOCK_SIZE,
22407405c8d7SLEROY Christophe 			.maxauthsize = SHA1_DIGEST_SIZE,
22417405c8d7SLEROY Christophe 		},
22427405c8d7SLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU |
22437405c8d7SLEROY Christophe 				     DESC_HDR_SEL0_DEU |
22447405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_DEU_CBC |
22457405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_DEU_3DES |
22467405c8d7SLEROY Christophe 				     DESC_HDR_SEL1_MDEUA |
22477405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_INIT |
22487405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_PAD |
22497405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_SHA1_HMAC,
22507405c8d7SLEROY Christophe 	},
22517405c8d7SLEROY Christophe 	{       .type = CRYPTO_ALG_TYPE_AEAD,
2252aeb4c132SHerbert Xu 		.alg.aead = {
2253aeb4c132SHerbert Xu 			.base = {
2254357fb605SHoria Geanta 				.cra_name = "authenc(hmac(sha224),cbc(aes))",
2255aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha224-"
2256aeb4c132SHerbert Xu 						   "cbc-aes-talitos",
2257357fb605SHoria Geanta 				.cra_blocksize = AES_BLOCK_SIZE,
2258aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2259aeb4c132SHerbert Xu 			},
2260357fb605SHoria Geanta 			.ivsize = AES_BLOCK_SIZE,
2261357fb605SHoria Geanta 			.maxauthsize = SHA224_DIGEST_SIZE,
2262357fb605SHoria Geanta 		},
2263357fb605SHoria Geanta 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
2264357fb605SHoria Geanta 				     DESC_HDR_SEL0_AESU |
2265357fb605SHoria Geanta 				     DESC_HDR_MODE0_AESU_CBC |
2266357fb605SHoria Geanta 				     DESC_HDR_SEL1_MDEUA |
2267357fb605SHoria Geanta 				     DESC_HDR_MODE1_MDEU_INIT |
2268357fb605SHoria Geanta 				     DESC_HDR_MODE1_MDEU_PAD |
2269357fb605SHoria Geanta 				     DESC_HDR_MODE1_MDEU_SHA224_HMAC,
2270357fb605SHoria Geanta 	},
2271357fb605SHoria Geanta 	{       .type = CRYPTO_ALG_TYPE_AEAD,
22727405c8d7SLEROY Christophe 		.priority = TALITOS_CRA_PRIORITY_AEAD_HSNA,
22737405c8d7SLEROY Christophe 		.alg.aead = {
22747405c8d7SLEROY Christophe 			.base = {
22757405c8d7SLEROY Christophe 				.cra_name = "authenc(hmac(sha224),cbc(aes))",
22767405c8d7SLEROY Christophe 				.cra_driver_name = "authenc-hmac-sha224-"
22777405c8d7SLEROY Christophe 						   "cbc-aes-talitos",
22787405c8d7SLEROY Christophe 				.cra_blocksize = AES_BLOCK_SIZE,
22797405c8d7SLEROY Christophe 				.cra_flags = CRYPTO_ALG_ASYNC,
22807405c8d7SLEROY Christophe 			},
22817405c8d7SLEROY Christophe 			.ivsize = AES_BLOCK_SIZE,
22827405c8d7SLEROY Christophe 			.maxauthsize = SHA224_DIGEST_SIZE,
22837405c8d7SLEROY Christophe 		},
22847405c8d7SLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU |
22857405c8d7SLEROY Christophe 				     DESC_HDR_SEL0_AESU |
22867405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_AESU_CBC |
22877405c8d7SLEROY Christophe 				     DESC_HDR_SEL1_MDEUA |
22887405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_INIT |
22897405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_PAD |
22907405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_SHA224_HMAC,
22917405c8d7SLEROY Christophe 	},
22927405c8d7SLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2293aeb4c132SHerbert Xu 		.alg.aead = {
2294aeb4c132SHerbert Xu 			.base = {
2295aeb4c132SHerbert Xu 				.cra_name = "authenc(hmac(sha224),"
2296aeb4c132SHerbert Xu 					    "cbc(des3_ede))",
2297aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha224-"
2298aeb4c132SHerbert Xu 						   "cbc-3des-talitos",
2299357fb605SHoria Geanta 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
2300aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2301aeb4c132SHerbert Xu 			},
2302357fb605SHoria Geanta 			.ivsize = DES3_EDE_BLOCK_SIZE,
2303357fb605SHoria Geanta 			.maxauthsize = SHA224_DIGEST_SIZE,
2304357fb605SHoria Geanta 		},
2305357fb605SHoria Geanta 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
2306357fb605SHoria Geanta 			             DESC_HDR_SEL0_DEU |
2307357fb605SHoria Geanta 		                     DESC_HDR_MODE0_DEU_CBC |
2308357fb605SHoria Geanta 		                     DESC_HDR_MODE0_DEU_3DES |
2309357fb605SHoria Geanta 		                     DESC_HDR_SEL1_MDEUA |
2310357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_INIT |
2311357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_PAD |
2312357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_SHA224_HMAC,
2313357fb605SHoria Geanta 	},
2314357fb605SHoria Geanta 	{	.type = CRYPTO_ALG_TYPE_AEAD,
23157405c8d7SLEROY Christophe 		.priority = TALITOS_CRA_PRIORITY_AEAD_HSNA,
23167405c8d7SLEROY Christophe 		.alg.aead = {
23177405c8d7SLEROY Christophe 			.base = {
23187405c8d7SLEROY Christophe 				.cra_name = "authenc(hmac(sha224),"
23197405c8d7SLEROY Christophe 					    "cbc(des3_ede))",
23207405c8d7SLEROY Christophe 				.cra_driver_name = "authenc-hmac-sha224-"
23217405c8d7SLEROY Christophe 						   "cbc-3des-talitos",
23227405c8d7SLEROY Christophe 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
23237405c8d7SLEROY Christophe 				.cra_flags = CRYPTO_ALG_ASYNC,
23247405c8d7SLEROY Christophe 			},
23257405c8d7SLEROY Christophe 			.ivsize = DES3_EDE_BLOCK_SIZE,
23267405c8d7SLEROY Christophe 			.maxauthsize = SHA224_DIGEST_SIZE,
23277405c8d7SLEROY Christophe 		},
23287405c8d7SLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU |
23297405c8d7SLEROY Christophe 				     DESC_HDR_SEL0_DEU |
23307405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_DEU_CBC |
23317405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_DEU_3DES |
23327405c8d7SLEROY Christophe 				     DESC_HDR_SEL1_MDEUA |
23337405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_INIT |
23347405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_PAD |
23357405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_SHA224_HMAC,
23367405c8d7SLEROY Christophe 	},
23377405c8d7SLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2338aeb4c132SHerbert Xu 		.alg.aead = {
2339aeb4c132SHerbert Xu 			.base = {
234056af8cd4SLee Nipper 				.cra_name = "authenc(hmac(sha256),cbc(aes))",
2341aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha256-"
2342aeb4c132SHerbert Xu 						   "cbc-aes-talitos",
234356af8cd4SLee Nipper 				.cra_blocksize = AES_BLOCK_SIZE,
2344aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2345aeb4c132SHerbert Xu 			},
23463952f17eSLee Nipper 			.ivsize = AES_BLOCK_SIZE,
23473952f17eSLee Nipper 			.maxauthsize = SHA256_DIGEST_SIZE,
23483952f17eSLee Nipper 		},
23493952f17eSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
23503952f17eSLee Nipper 			             DESC_HDR_SEL0_AESU |
23513952f17eSLee Nipper 		                     DESC_HDR_MODE0_AESU_CBC |
23523952f17eSLee Nipper 		                     DESC_HDR_SEL1_MDEUA |
23533952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_INIT |
23543952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_PAD |
23553952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_SHA256_HMAC,
23563952f17eSLee Nipper 	},
2357d5e4aaefSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AEAD,
23587405c8d7SLEROY Christophe 		.priority = TALITOS_CRA_PRIORITY_AEAD_HSNA,
23597405c8d7SLEROY Christophe 		.alg.aead = {
23607405c8d7SLEROY Christophe 			.base = {
23617405c8d7SLEROY Christophe 				.cra_name = "authenc(hmac(sha256),cbc(aes))",
23627405c8d7SLEROY Christophe 				.cra_driver_name = "authenc-hmac-sha256-"
23637405c8d7SLEROY Christophe 						   "cbc-aes-talitos",
23647405c8d7SLEROY Christophe 				.cra_blocksize = AES_BLOCK_SIZE,
23657405c8d7SLEROY Christophe 				.cra_flags = CRYPTO_ALG_ASYNC,
23667405c8d7SLEROY Christophe 			},
23677405c8d7SLEROY Christophe 			.ivsize = AES_BLOCK_SIZE,
23687405c8d7SLEROY Christophe 			.maxauthsize = SHA256_DIGEST_SIZE,
23697405c8d7SLEROY Christophe 		},
23707405c8d7SLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU |
23717405c8d7SLEROY Christophe 				     DESC_HDR_SEL0_AESU |
23727405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_AESU_CBC |
23737405c8d7SLEROY Christophe 				     DESC_HDR_SEL1_MDEUA |
23747405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_INIT |
23757405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_PAD |
23767405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_SHA256_HMAC,
23777405c8d7SLEROY Christophe 	},
23787405c8d7SLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2379aeb4c132SHerbert Xu 		.alg.aead = {
2380aeb4c132SHerbert Xu 			.base = {
2381aeb4c132SHerbert Xu 				.cra_name = "authenc(hmac(sha256),"
2382aeb4c132SHerbert Xu 					    "cbc(des3_ede))",
2383aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha256-"
2384aeb4c132SHerbert Xu 						   "cbc-3des-talitos",
238556af8cd4SLee Nipper 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
2386aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2387aeb4c132SHerbert Xu 			},
23883952f17eSLee Nipper 			.ivsize = DES3_EDE_BLOCK_SIZE,
23893952f17eSLee Nipper 			.maxauthsize = SHA256_DIGEST_SIZE,
23903952f17eSLee Nipper 		},
23913952f17eSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
23923952f17eSLee Nipper 			             DESC_HDR_SEL0_DEU |
23933952f17eSLee Nipper 		                     DESC_HDR_MODE0_DEU_CBC |
23943952f17eSLee Nipper 		                     DESC_HDR_MODE0_DEU_3DES |
23953952f17eSLee Nipper 		                     DESC_HDR_SEL1_MDEUA |
23963952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_INIT |
23973952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_PAD |
23983952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_SHA256_HMAC,
23993952f17eSLee Nipper 	},
2400d5e4aaefSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AEAD,
24017405c8d7SLEROY Christophe 		.priority = TALITOS_CRA_PRIORITY_AEAD_HSNA,
24027405c8d7SLEROY Christophe 		.alg.aead = {
24037405c8d7SLEROY Christophe 			.base = {
24047405c8d7SLEROY Christophe 				.cra_name = "authenc(hmac(sha256),"
24057405c8d7SLEROY Christophe 					    "cbc(des3_ede))",
24067405c8d7SLEROY Christophe 				.cra_driver_name = "authenc-hmac-sha256-"
24077405c8d7SLEROY Christophe 						   "cbc-3des-talitos",
24087405c8d7SLEROY Christophe 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
24097405c8d7SLEROY Christophe 				.cra_flags = CRYPTO_ALG_ASYNC,
24107405c8d7SLEROY Christophe 			},
24117405c8d7SLEROY Christophe 			.ivsize = DES3_EDE_BLOCK_SIZE,
24127405c8d7SLEROY Christophe 			.maxauthsize = SHA256_DIGEST_SIZE,
24137405c8d7SLEROY Christophe 		},
24147405c8d7SLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU |
24157405c8d7SLEROY Christophe 				     DESC_HDR_SEL0_DEU |
24167405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_DEU_CBC |
24177405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_DEU_3DES |
24187405c8d7SLEROY Christophe 				     DESC_HDR_SEL1_MDEUA |
24197405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_INIT |
24207405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_PAD |
24217405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_SHA256_HMAC,
24227405c8d7SLEROY Christophe 	},
24237405c8d7SLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2424aeb4c132SHerbert Xu 		.alg.aead = {
2425aeb4c132SHerbert Xu 			.base = {
2426357fb605SHoria Geanta 				.cra_name = "authenc(hmac(sha384),cbc(aes))",
2427aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha384-"
2428aeb4c132SHerbert Xu 						   "cbc-aes-talitos",
2429357fb605SHoria Geanta 				.cra_blocksize = AES_BLOCK_SIZE,
2430aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2431aeb4c132SHerbert Xu 			},
2432357fb605SHoria Geanta 			.ivsize = AES_BLOCK_SIZE,
2433357fb605SHoria Geanta 			.maxauthsize = SHA384_DIGEST_SIZE,
2434357fb605SHoria Geanta 		},
2435357fb605SHoria Geanta 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
2436357fb605SHoria Geanta 			             DESC_HDR_SEL0_AESU |
2437357fb605SHoria Geanta 		                     DESC_HDR_MODE0_AESU_CBC |
2438357fb605SHoria Geanta 		                     DESC_HDR_SEL1_MDEUB |
2439357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_INIT |
2440357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_PAD |
2441357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEUB_SHA384_HMAC,
2442357fb605SHoria Geanta 	},
2443357fb605SHoria Geanta 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2444aeb4c132SHerbert Xu 		.alg.aead = {
2445aeb4c132SHerbert Xu 			.base = {
2446aeb4c132SHerbert Xu 				.cra_name = "authenc(hmac(sha384),"
2447aeb4c132SHerbert Xu 					    "cbc(des3_ede))",
2448aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha384-"
2449aeb4c132SHerbert Xu 						   "cbc-3des-talitos",
2450357fb605SHoria Geanta 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
2451aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2452aeb4c132SHerbert Xu 			},
2453357fb605SHoria Geanta 			.ivsize = DES3_EDE_BLOCK_SIZE,
2454357fb605SHoria Geanta 			.maxauthsize = SHA384_DIGEST_SIZE,
2455357fb605SHoria Geanta 		},
2456357fb605SHoria Geanta 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
2457357fb605SHoria Geanta 			             DESC_HDR_SEL0_DEU |
2458357fb605SHoria Geanta 		                     DESC_HDR_MODE0_DEU_CBC |
2459357fb605SHoria Geanta 		                     DESC_HDR_MODE0_DEU_3DES |
2460357fb605SHoria Geanta 		                     DESC_HDR_SEL1_MDEUB |
2461357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_INIT |
2462357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_PAD |
2463357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEUB_SHA384_HMAC,
2464357fb605SHoria Geanta 	},
2465357fb605SHoria Geanta 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2466aeb4c132SHerbert Xu 		.alg.aead = {
2467aeb4c132SHerbert Xu 			.base = {
2468357fb605SHoria Geanta 				.cra_name = "authenc(hmac(sha512),cbc(aes))",
2469aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha512-"
2470aeb4c132SHerbert Xu 						   "cbc-aes-talitos",
2471357fb605SHoria Geanta 				.cra_blocksize = AES_BLOCK_SIZE,
2472aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2473aeb4c132SHerbert Xu 			},
2474357fb605SHoria Geanta 			.ivsize = AES_BLOCK_SIZE,
2475357fb605SHoria Geanta 			.maxauthsize = SHA512_DIGEST_SIZE,
2476357fb605SHoria Geanta 		},
2477357fb605SHoria Geanta 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
2478357fb605SHoria Geanta 			             DESC_HDR_SEL0_AESU |
2479357fb605SHoria Geanta 		                     DESC_HDR_MODE0_AESU_CBC |
2480357fb605SHoria Geanta 		                     DESC_HDR_SEL1_MDEUB |
2481357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_INIT |
2482357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_PAD |
2483357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEUB_SHA512_HMAC,
2484357fb605SHoria Geanta 	},
2485357fb605SHoria Geanta 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2486aeb4c132SHerbert Xu 		.alg.aead = {
2487aeb4c132SHerbert Xu 			.base = {
2488aeb4c132SHerbert Xu 				.cra_name = "authenc(hmac(sha512),"
2489aeb4c132SHerbert Xu 					    "cbc(des3_ede))",
2490aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha512-"
2491aeb4c132SHerbert Xu 						   "cbc-3des-talitos",
2492357fb605SHoria Geanta 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
2493aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2494aeb4c132SHerbert Xu 			},
2495357fb605SHoria Geanta 			.ivsize = DES3_EDE_BLOCK_SIZE,
2496357fb605SHoria Geanta 			.maxauthsize = SHA512_DIGEST_SIZE,
2497357fb605SHoria Geanta 		},
2498357fb605SHoria Geanta 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
2499357fb605SHoria Geanta 			             DESC_HDR_SEL0_DEU |
2500357fb605SHoria Geanta 		                     DESC_HDR_MODE0_DEU_CBC |
2501357fb605SHoria Geanta 		                     DESC_HDR_MODE0_DEU_3DES |
2502357fb605SHoria Geanta 		                     DESC_HDR_SEL1_MDEUB |
2503357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_INIT |
2504357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_PAD |
2505357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEUB_SHA512_HMAC,
2506357fb605SHoria Geanta 	},
2507357fb605SHoria Geanta 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2508aeb4c132SHerbert Xu 		.alg.aead = {
2509aeb4c132SHerbert Xu 			.base = {
251056af8cd4SLee Nipper 				.cra_name = "authenc(hmac(md5),cbc(aes))",
2511aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-md5-"
2512aeb4c132SHerbert Xu 						   "cbc-aes-talitos",
251356af8cd4SLee Nipper 				.cra_blocksize = AES_BLOCK_SIZE,
2514aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2515aeb4c132SHerbert Xu 			},
25163952f17eSLee Nipper 			.ivsize = AES_BLOCK_SIZE,
25173952f17eSLee Nipper 			.maxauthsize = MD5_DIGEST_SIZE,
25183952f17eSLee Nipper 		},
25193952f17eSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
25203952f17eSLee Nipper 			             DESC_HDR_SEL0_AESU |
25213952f17eSLee Nipper 		                     DESC_HDR_MODE0_AESU_CBC |
25223952f17eSLee Nipper 		                     DESC_HDR_SEL1_MDEUA |
25233952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_INIT |
25243952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_PAD |
25253952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_MD5_HMAC,
25263952f17eSLee Nipper 	},
2527d5e4aaefSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AEAD,
25287405c8d7SLEROY Christophe 		.priority = TALITOS_CRA_PRIORITY_AEAD_HSNA,
25297405c8d7SLEROY Christophe 		.alg.aead = {
25307405c8d7SLEROY Christophe 			.base = {
25317405c8d7SLEROY Christophe 				.cra_name = "authenc(hmac(md5),cbc(aes))",
25327405c8d7SLEROY Christophe 				.cra_driver_name = "authenc-hmac-md5-"
25337405c8d7SLEROY Christophe 						   "cbc-aes-talitos",
25347405c8d7SLEROY Christophe 				.cra_blocksize = AES_BLOCK_SIZE,
25357405c8d7SLEROY Christophe 				.cra_flags = CRYPTO_ALG_ASYNC,
25367405c8d7SLEROY Christophe 			},
25377405c8d7SLEROY Christophe 			.ivsize = AES_BLOCK_SIZE,
25387405c8d7SLEROY Christophe 			.maxauthsize = MD5_DIGEST_SIZE,
25397405c8d7SLEROY Christophe 		},
25407405c8d7SLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU |
25417405c8d7SLEROY Christophe 				     DESC_HDR_SEL0_AESU |
25427405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_AESU_CBC |
25437405c8d7SLEROY Christophe 				     DESC_HDR_SEL1_MDEUA |
25447405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_INIT |
25457405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_PAD |
25467405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_MD5_HMAC,
25477405c8d7SLEROY Christophe 	},
25487405c8d7SLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2549aeb4c132SHerbert Xu 		.alg.aead = {
2550aeb4c132SHerbert Xu 			.base = {
255156af8cd4SLee Nipper 				.cra_name = "authenc(hmac(md5),cbc(des3_ede))",
2552aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-md5-"
2553aeb4c132SHerbert Xu 						   "cbc-3des-talitos",
255456af8cd4SLee Nipper 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
2555aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2556aeb4c132SHerbert Xu 			},
25573952f17eSLee Nipper 			.ivsize = DES3_EDE_BLOCK_SIZE,
25583952f17eSLee Nipper 			.maxauthsize = MD5_DIGEST_SIZE,
25593952f17eSLee Nipper 		},
25603952f17eSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
25613952f17eSLee Nipper 			             DESC_HDR_SEL0_DEU |
25623952f17eSLee Nipper 		                     DESC_HDR_MODE0_DEU_CBC |
25633952f17eSLee Nipper 		                     DESC_HDR_MODE0_DEU_3DES |
25643952f17eSLee Nipper 		                     DESC_HDR_SEL1_MDEUA |
25653952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_INIT |
25663952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_PAD |
25673952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_MD5_HMAC,
25684de9d0b5SLee Nipper 	},
25697405c8d7SLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_AEAD,
25707405c8d7SLEROY Christophe 		.priority = TALITOS_CRA_PRIORITY_AEAD_HSNA,
25717405c8d7SLEROY Christophe 		.alg.aead = {
25727405c8d7SLEROY Christophe 			.base = {
25737405c8d7SLEROY Christophe 				.cra_name = "authenc(hmac(md5),cbc(des3_ede))",
25747405c8d7SLEROY Christophe 				.cra_driver_name = "authenc-hmac-md5-"
25757405c8d7SLEROY Christophe 						   "cbc-3des-talitos",
25767405c8d7SLEROY Christophe 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
25777405c8d7SLEROY Christophe 				.cra_flags = CRYPTO_ALG_ASYNC,
25787405c8d7SLEROY Christophe 			},
25797405c8d7SLEROY Christophe 			.ivsize = DES3_EDE_BLOCK_SIZE,
25807405c8d7SLEROY Christophe 			.maxauthsize = MD5_DIGEST_SIZE,
25817405c8d7SLEROY Christophe 		},
25827405c8d7SLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU |
25837405c8d7SLEROY Christophe 				     DESC_HDR_SEL0_DEU |
25847405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_DEU_CBC |
25857405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_DEU_3DES |
25867405c8d7SLEROY Christophe 				     DESC_HDR_SEL1_MDEUA |
25877405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_INIT |
25887405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_PAD |
25897405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_MD5_HMAC,
25907405c8d7SLEROY Christophe 	},
25914de9d0b5SLee Nipper 	/* ABLKCIPHER algorithms. */
2592d5e4aaefSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_ABLKCIPHER,
2593d5e4aaefSLee Nipper 		.alg.crypto = {
25945e75ae1bSLEROY Christophe 			.cra_name = "ecb(aes)",
25955e75ae1bSLEROY Christophe 			.cra_driver_name = "ecb-aes-talitos",
25965e75ae1bSLEROY Christophe 			.cra_blocksize = AES_BLOCK_SIZE,
25975e75ae1bSLEROY Christophe 			.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
25985e75ae1bSLEROY Christophe 				     CRYPTO_ALG_ASYNC,
25995e75ae1bSLEROY Christophe 			.cra_ablkcipher = {
26005e75ae1bSLEROY Christophe 				.min_keysize = AES_MIN_KEY_SIZE,
26015e75ae1bSLEROY Christophe 				.max_keysize = AES_MAX_KEY_SIZE,
26025e75ae1bSLEROY Christophe 				.ivsize = AES_BLOCK_SIZE,
26035e75ae1bSLEROY Christophe 			}
26045e75ae1bSLEROY Christophe 		},
26055e75ae1bSLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
26065e75ae1bSLEROY Christophe 				     DESC_HDR_SEL0_AESU,
26075e75ae1bSLEROY Christophe 	},
26085e75ae1bSLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_ABLKCIPHER,
26095e75ae1bSLEROY Christophe 		.alg.crypto = {
26104de9d0b5SLee Nipper 			.cra_name = "cbc(aes)",
26114de9d0b5SLee Nipper 			.cra_driver_name = "cbc-aes-talitos",
26124de9d0b5SLee Nipper 			.cra_blocksize = AES_BLOCK_SIZE,
26134de9d0b5SLee Nipper 			.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
26144de9d0b5SLee Nipper                                      CRYPTO_ALG_ASYNC,
26154de9d0b5SLee Nipper 			.cra_ablkcipher = {
26164de9d0b5SLee Nipper 				.min_keysize = AES_MIN_KEY_SIZE,
26174de9d0b5SLee Nipper 				.max_keysize = AES_MAX_KEY_SIZE,
26184de9d0b5SLee Nipper 				.ivsize = AES_BLOCK_SIZE,
26194de9d0b5SLee Nipper 			}
26204de9d0b5SLee Nipper 		},
26214de9d0b5SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
26224de9d0b5SLee Nipper 				     DESC_HDR_SEL0_AESU |
26234de9d0b5SLee Nipper 				     DESC_HDR_MODE0_AESU_CBC,
26244de9d0b5SLee Nipper 	},
2625d5e4aaefSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_ABLKCIPHER,
2626d5e4aaefSLee Nipper 		.alg.crypto = {
26275e75ae1bSLEROY Christophe 			.cra_name = "ctr(aes)",
26285e75ae1bSLEROY Christophe 			.cra_driver_name = "ctr-aes-talitos",
26295e75ae1bSLEROY Christophe 			.cra_blocksize = AES_BLOCK_SIZE,
26305e75ae1bSLEROY Christophe 			.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
26315e75ae1bSLEROY Christophe 				     CRYPTO_ALG_ASYNC,
26325e75ae1bSLEROY Christophe 			.cra_ablkcipher = {
26335e75ae1bSLEROY Christophe 				.min_keysize = AES_MIN_KEY_SIZE,
26345e75ae1bSLEROY Christophe 				.max_keysize = AES_MAX_KEY_SIZE,
26355e75ae1bSLEROY Christophe 				.ivsize = AES_BLOCK_SIZE,
26365e75ae1bSLEROY Christophe 			}
26375e75ae1bSLEROY Christophe 		},
2638*70d355ccSLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_AESU_CTR_NONSNOOP |
26395e75ae1bSLEROY Christophe 				     DESC_HDR_SEL0_AESU |
26405e75ae1bSLEROY Christophe 				     DESC_HDR_MODE0_AESU_CTR,
26415e75ae1bSLEROY Christophe 	},
26425e75ae1bSLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_ABLKCIPHER,
26435e75ae1bSLEROY Christophe 		.alg.crypto = {
26445e75ae1bSLEROY Christophe 			.cra_name = "ecb(des)",
26455e75ae1bSLEROY Christophe 			.cra_driver_name = "ecb-des-talitos",
26465e75ae1bSLEROY Christophe 			.cra_blocksize = DES_BLOCK_SIZE,
26475e75ae1bSLEROY Christophe 			.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
26485e75ae1bSLEROY Christophe 				     CRYPTO_ALG_ASYNC,
26495e75ae1bSLEROY Christophe 			.cra_ablkcipher = {
26505e75ae1bSLEROY Christophe 				.min_keysize = DES_KEY_SIZE,
26515e75ae1bSLEROY Christophe 				.max_keysize = DES_KEY_SIZE,
26525e75ae1bSLEROY Christophe 				.ivsize = DES_BLOCK_SIZE,
26535e75ae1bSLEROY Christophe 			}
26545e75ae1bSLEROY Christophe 		},
26555e75ae1bSLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
26565e75ae1bSLEROY Christophe 				     DESC_HDR_SEL0_DEU,
26575e75ae1bSLEROY Christophe 	},
26585e75ae1bSLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_ABLKCIPHER,
26595e75ae1bSLEROY Christophe 		.alg.crypto = {
26605e75ae1bSLEROY Christophe 			.cra_name = "cbc(des)",
26615e75ae1bSLEROY Christophe 			.cra_driver_name = "cbc-des-talitos",
26625e75ae1bSLEROY Christophe 			.cra_blocksize = DES_BLOCK_SIZE,
26635e75ae1bSLEROY Christophe 			.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
26645e75ae1bSLEROY Christophe 				     CRYPTO_ALG_ASYNC,
26655e75ae1bSLEROY Christophe 			.cra_ablkcipher = {
26665e75ae1bSLEROY Christophe 				.min_keysize = DES_KEY_SIZE,
26675e75ae1bSLEROY Christophe 				.max_keysize = DES_KEY_SIZE,
26685e75ae1bSLEROY Christophe 				.ivsize = DES_BLOCK_SIZE,
26695e75ae1bSLEROY Christophe 			}
26705e75ae1bSLEROY Christophe 		},
26715e75ae1bSLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
26725e75ae1bSLEROY Christophe 				     DESC_HDR_SEL0_DEU |
26735e75ae1bSLEROY Christophe 				     DESC_HDR_MODE0_DEU_CBC,
26745e75ae1bSLEROY Christophe 	},
26755e75ae1bSLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_ABLKCIPHER,
26765e75ae1bSLEROY Christophe 		.alg.crypto = {
26775e75ae1bSLEROY Christophe 			.cra_name = "ecb(des3_ede)",
26785e75ae1bSLEROY Christophe 			.cra_driver_name = "ecb-3des-talitos",
26795e75ae1bSLEROY Christophe 			.cra_blocksize = DES3_EDE_BLOCK_SIZE,
26805e75ae1bSLEROY Christophe 			.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
26815e75ae1bSLEROY Christophe 				     CRYPTO_ALG_ASYNC,
26825e75ae1bSLEROY Christophe 			.cra_ablkcipher = {
26835e75ae1bSLEROY Christophe 				.min_keysize = DES3_EDE_KEY_SIZE,
26845e75ae1bSLEROY Christophe 				.max_keysize = DES3_EDE_KEY_SIZE,
26855e75ae1bSLEROY Christophe 				.ivsize = DES3_EDE_BLOCK_SIZE,
26865e75ae1bSLEROY Christophe 			}
26875e75ae1bSLEROY Christophe 		},
26885e75ae1bSLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
26895e75ae1bSLEROY Christophe 				     DESC_HDR_SEL0_DEU |
26905e75ae1bSLEROY Christophe 				     DESC_HDR_MODE0_DEU_3DES,
26915e75ae1bSLEROY Christophe 	},
26925e75ae1bSLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_ABLKCIPHER,
26935e75ae1bSLEROY Christophe 		.alg.crypto = {
26944de9d0b5SLee Nipper 			.cra_name = "cbc(des3_ede)",
26954de9d0b5SLee Nipper 			.cra_driver_name = "cbc-3des-talitos",
26964de9d0b5SLee Nipper 			.cra_blocksize = DES3_EDE_BLOCK_SIZE,
26974de9d0b5SLee Nipper 			.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
26984de9d0b5SLee Nipper                                      CRYPTO_ALG_ASYNC,
26994de9d0b5SLee Nipper 			.cra_ablkcipher = {
27004de9d0b5SLee Nipper 				.min_keysize = DES3_EDE_KEY_SIZE,
27014de9d0b5SLee Nipper 				.max_keysize = DES3_EDE_KEY_SIZE,
27024de9d0b5SLee Nipper 				.ivsize = DES3_EDE_BLOCK_SIZE,
27034de9d0b5SLee Nipper 			}
27044de9d0b5SLee Nipper 		},
27054de9d0b5SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
27064de9d0b5SLee Nipper 			             DESC_HDR_SEL0_DEU |
27074de9d0b5SLee Nipper 		                     DESC_HDR_MODE0_DEU_CBC |
27084de9d0b5SLee Nipper 		                     DESC_HDR_MODE0_DEU_3DES,
2709497f2e6bSLee Nipper 	},
2710497f2e6bSLee Nipper 	/* AHASH algorithms. */
2711497f2e6bSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
2712497f2e6bSLee Nipper 		.alg.hash = {
2713497f2e6bSLee Nipper 			.halg.digestsize = MD5_DIGEST_SIZE,
27143639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
2715497f2e6bSLee Nipper 			.halg.base = {
2716497f2e6bSLee Nipper 				.cra_name = "md5",
2717497f2e6bSLee Nipper 				.cra_driver_name = "md5-talitos",
2718b3988618SMartin Hicks 				.cra_blocksize = MD5_HMAC_BLOCK_SIZE,
2719497f2e6bSLee Nipper 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
2720497f2e6bSLee Nipper 					     CRYPTO_ALG_ASYNC,
27219c4a7965SKim Phillips 			}
2722497f2e6bSLee Nipper 		},
2723497f2e6bSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
2724497f2e6bSLee Nipper 				     DESC_HDR_SEL0_MDEUA |
2725497f2e6bSLee Nipper 				     DESC_HDR_MODE0_MDEU_MD5,
2726497f2e6bSLee Nipper 	},
2727497f2e6bSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
2728497f2e6bSLee Nipper 		.alg.hash = {
2729497f2e6bSLee Nipper 			.halg.digestsize = SHA1_DIGEST_SIZE,
27303639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
2731497f2e6bSLee Nipper 			.halg.base = {
2732497f2e6bSLee Nipper 				.cra_name = "sha1",
2733497f2e6bSLee Nipper 				.cra_driver_name = "sha1-talitos",
2734497f2e6bSLee Nipper 				.cra_blocksize = SHA1_BLOCK_SIZE,
2735497f2e6bSLee Nipper 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
2736497f2e6bSLee Nipper 					     CRYPTO_ALG_ASYNC,
2737497f2e6bSLee Nipper 			}
2738497f2e6bSLee Nipper 		},
2739497f2e6bSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
2740497f2e6bSLee Nipper 				     DESC_HDR_SEL0_MDEUA |
2741497f2e6bSLee Nipper 				     DESC_HDR_MODE0_MDEU_SHA1,
2742497f2e6bSLee Nipper 	},
2743497f2e6bSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
2744497f2e6bSLee Nipper 		.alg.hash = {
274560f208d7SKim Phillips 			.halg.digestsize = SHA224_DIGEST_SIZE,
27463639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
274760f208d7SKim Phillips 			.halg.base = {
274860f208d7SKim Phillips 				.cra_name = "sha224",
274960f208d7SKim Phillips 				.cra_driver_name = "sha224-talitos",
275060f208d7SKim Phillips 				.cra_blocksize = SHA224_BLOCK_SIZE,
275160f208d7SKim Phillips 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
275260f208d7SKim Phillips 					     CRYPTO_ALG_ASYNC,
275360f208d7SKim Phillips 			}
275460f208d7SKim Phillips 		},
275560f208d7SKim Phillips 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
275660f208d7SKim Phillips 				     DESC_HDR_SEL0_MDEUA |
275760f208d7SKim Phillips 				     DESC_HDR_MODE0_MDEU_SHA224,
275860f208d7SKim Phillips 	},
275960f208d7SKim Phillips 	{	.type = CRYPTO_ALG_TYPE_AHASH,
276060f208d7SKim Phillips 		.alg.hash = {
2761497f2e6bSLee Nipper 			.halg.digestsize = SHA256_DIGEST_SIZE,
27623639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
2763497f2e6bSLee Nipper 			.halg.base = {
2764497f2e6bSLee Nipper 				.cra_name = "sha256",
2765497f2e6bSLee Nipper 				.cra_driver_name = "sha256-talitos",
2766497f2e6bSLee Nipper 				.cra_blocksize = SHA256_BLOCK_SIZE,
2767497f2e6bSLee Nipper 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
2768497f2e6bSLee Nipper 					     CRYPTO_ALG_ASYNC,
2769497f2e6bSLee Nipper 			}
2770497f2e6bSLee Nipper 		},
2771497f2e6bSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
2772497f2e6bSLee Nipper 				     DESC_HDR_SEL0_MDEUA |
2773497f2e6bSLee Nipper 				     DESC_HDR_MODE0_MDEU_SHA256,
2774497f2e6bSLee Nipper 	},
2775497f2e6bSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
2776497f2e6bSLee Nipper 		.alg.hash = {
2777497f2e6bSLee Nipper 			.halg.digestsize = SHA384_DIGEST_SIZE,
27783639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
2779497f2e6bSLee Nipper 			.halg.base = {
2780497f2e6bSLee Nipper 				.cra_name = "sha384",
2781497f2e6bSLee Nipper 				.cra_driver_name = "sha384-talitos",
2782497f2e6bSLee Nipper 				.cra_blocksize = SHA384_BLOCK_SIZE,
2783497f2e6bSLee Nipper 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
2784497f2e6bSLee Nipper 					     CRYPTO_ALG_ASYNC,
2785497f2e6bSLee Nipper 			}
2786497f2e6bSLee Nipper 		},
2787497f2e6bSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
2788497f2e6bSLee Nipper 				     DESC_HDR_SEL0_MDEUB |
2789497f2e6bSLee Nipper 				     DESC_HDR_MODE0_MDEUB_SHA384,
2790497f2e6bSLee Nipper 	},
2791497f2e6bSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
2792497f2e6bSLee Nipper 		.alg.hash = {
2793497f2e6bSLee Nipper 			.halg.digestsize = SHA512_DIGEST_SIZE,
27943639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
2795497f2e6bSLee Nipper 			.halg.base = {
2796497f2e6bSLee Nipper 				.cra_name = "sha512",
2797497f2e6bSLee Nipper 				.cra_driver_name = "sha512-talitos",
2798497f2e6bSLee Nipper 				.cra_blocksize = SHA512_BLOCK_SIZE,
2799497f2e6bSLee Nipper 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
2800497f2e6bSLee Nipper 					     CRYPTO_ALG_ASYNC,
2801497f2e6bSLee Nipper 			}
2802497f2e6bSLee Nipper 		},
2803497f2e6bSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
2804497f2e6bSLee Nipper 				     DESC_HDR_SEL0_MDEUB |
2805497f2e6bSLee Nipper 				     DESC_HDR_MODE0_MDEUB_SHA512,
2806497f2e6bSLee Nipper 	},
280779b3a418SLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
280879b3a418SLee Nipper 		.alg.hash = {
280979b3a418SLee Nipper 			.halg.digestsize = MD5_DIGEST_SIZE,
28103639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
281179b3a418SLee Nipper 			.halg.base = {
281279b3a418SLee Nipper 				.cra_name = "hmac(md5)",
281379b3a418SLee Nipper 				.cra_driver_name = "hmac-md5-talitos",
2814b3988618SMartin Hicks 				.cra_blocksize = MD5_HMAC_BLOCK_SIZE,
281579b3a418SLee Nipper 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
281679b3a418SLee Nipper 					     CRYPTO_ALG_ASYNC,
281779b3a418SLee Nipper 			}
281879b3a418SLee Nipper 		},
281979b3a418SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
282079b3a418SLee Nipper 				     DESC_HDR_SEL0_MDEUA |
282179b3a418SLee Nipper 				     DESC_HDR_MODE0_MDEU_MD5,
282279b3a418SLee Nipper 	},
282379b3a418SLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
282479b3a418SLee Nipper 		.alg.hash = {
282579b3a418SLee Nipper 			.halg.digestsize = SHA1_DIGEST_SIZE,
28263639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
282779b3a418SLee Nipper 			.halg.base = {
282879b3a418SLee Nipper 				.cra_name = "hmac(sha1)",
282979b3a418SLee Nipper 				.cra_driver_name = "hmac-sha1-talitos",
283079b3a418SLee Nipper 				.cra_blocksize = SHA1_BLOCK_SIZE,
283179b3a418SLee Nipper 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
283279b3a418SLee Nipper 					     CRYPTO_ALG_ASYNC,
283379b3a418SLee Nipper 			}
283479b3a418SLee Nipper 		},
283579b3a418SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
283679b3a418SLee Nipper 				     DESC_HDR_SEL0_MDEUA |
283779b3a418SLee Nipper 				     DESC_HDR_MODE0_MDEU_SHA1,
283879b3a418SLee Nipper 	},
283979b3a418SLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
284079b3a418SLee Nipper 		.alg.hash = {
284179b3a418SLee Nipper 			.halg.digestsize = SHA224_DIGEST_SIZE,
28423639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
284379b3a418SLee Nipper 			.halg.base = {
284479b3a418SLee Nipper 				.cra_name = "hmac(sha224)",
284579b3a418SLee Nipper 				.cra_driver_name = "hmac-sha224-talitos",
284679b3a418SLee Nipper 				.cra_blocksize = SHA224_BLOCK_SIZE,
284779b3a418SLee Nipper 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
284879b3a418SLee Nipper 					     CRYPTO_ALG_ASYNC,
284979b3a418SLee Nipper 			}
285079b3a418SLee Nipper 		},
285179b3a418SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
285279b3a418SLee Nipper 				     DESC_HDR_SEL0_MDEUA |
285379b3a418SLee Nipper 				     DESC_HDR_MODE0_MDEU_SHA224,
285479b3a418SLee Nipper 	},
285579b3a418SLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
285679b3a418SLee Nipper 		.alg.hash = {
285779b3a418SLee Nipper 			.halg.digestsize = SHA256_DIGEST_SIZE,
28583639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
285979b3a418SLee Nipper 			.halg.base = {
286079b3a418SLee Nipper 				.cra_name = "hmac(sha256)",
286179b3a418SLee Nipper 				.cra_driver_name = "hmac-sha256-talitos",
286279b3a418SLee Nipper 				.cra_blocksize = SHA256_BLOCK_SIZE,
286379b3a418SLee Nipper 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
286479b3a418SLee Nipper 					     CRYPTO_ALG_ASYNC,
286579b3a418SLee Nipper 			}
286679b3a418SLee Nipper 		},
286779b3a418SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
286879b3a418SLee Nipper 				     DESC_HDR_SEL0_MDEUA |
286979b3a418SLee Nipper 				     DESC_HDR_MODE0_MDEU_SHA256,
287079b3a418SLee Nipper 	},
287179b3a418SLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
287279b3a418SLee Nipper 		.alg.hash = {
287379b3a418SLee Nipper 			.halg.digestsize = SHA384_DIGEST_SIZE,
28743639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
287579b3a418SLee Nipper 			.halg.base = {
287679b3a418SLee Nipper 				.cra_name = "hmac(sha384)",
287779b3a418SLee Nipper 				.cra_driver_name = "hmac-sha384-talitos",
287879b3a418SLee Nipper 				.cra_blocksize = SHA384_BLOCK_SIZE,
287979b3a418SLee Nipper 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
288079b3a418SLee Nipper 					     CRYPTO_ALG_ASYNC,
288179b3a418SLee Nipper 			}
288279b3a418SLee Nipper 		},
288379b3a418SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
288479b3a418SLee Nipper 				     DESC_HDR_SEL0_MDEUB |
288579b3a418SLee Nipper 				     DESC_HDR_MODE0_MDEUB_SHA384,
288679b3a418SLee Nipper 	},
288779b3a418SLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
288879b3a418SLee Nipper 		.alg.hash = {
288979b3a418SLee Nipper 			.halg.digestsize = SHA512_DIGEST_SIZE,
28903639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
289179b3a418SLee Nipper 			.halg.base = {
289279b3a418SLee Nipper 				.cra_name = "hmac(sha512)",
289379b3a418SLee Nipper 				.cra_driver_name = "hmac-sha512-talitos",
289479b3a418SLee Nipper 				.cra_blocksize = SHA512_BLOCK_SIZE,
289579b3a418SLee Nipper 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
289679b3a418SLee Nipper 					     CRYPTO_ALG_ASYNC,
289779b3a418SLee Nipper 			}
289879b3a418SLee Nipper 		},
289979b3a418SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
290079b3a418SLee Nipper 				     DESC_HDR_SEL0_MDEUB |
290179b3a418SLee Nipper 				     DESC_HDR_MODE0_MDEUB_SHA512,
290279b3a418SLee Nipper 	}
29039c4a7965SKim Phillips };
29049c4a7965SKim Phillips 
29059c4a7965SKim Phillips struct talitos_crypto_alg {
29069c4a7965SKim Phillips 	struct list_head entry;
29079c4a7965SKim Phillips 	struct device *dev;
2908acbf7c62SLee Nipper 	struct talitos_alg_template algt;
29099c4a7965SKim Phillips };
29109c4a7965SKim Phillips 
291189d124cbSJonas Eymann static int talitos_init_common(struct talitos_ctx *ctx,
291289d124cbSJonas Eymann 			       struct talitos_crypto_alg *talitos_alg)
29139c4a7965SKim Phillips {
29145228f0f7SKim Phillips 	struct talitos_private *priv;
29159c4a7965SKim Phillips 
29169c4a7965SKim Phillips 	/* update context with ptr to dev */
29179c4a7965SKim Phillips 	ctx->dev = talitos_alg->dev;
291819bbbc63SKim Phillips 
29195228f0f7SKim Phillips 	/* assign SEC channel to tfm in round-robin fashion */
29205228f0f7SKim Phillips 	priv = dev_get_drvdata(ctx->dev);
29215228f0f7SKim Phillips 	ctx->ch = atomic_inc_return(&priv->last_chan) &
29225228f0f7SKim Phillips 		  (priv->num_channels - 1);
29235228f0f7SKim Phillips 
29249c4a7965SKim Phillips 	/* copy descriptor header template value */
2925acbf7c62SLee Nipper 	ctx->desc_hdr_template = talitos_alg->algt.desc_hdr_template;
29269c4a7965SKim Phillips 
2927602dba5aSKim Phillips 	/* select done notification */
2928602dba5aSKim Phillips 	ctx->desc_hdr_template |= DESC_HDR_DONE_NOTIFY;
2929602dba5aSKim Phillips 
2930497f2e6bSLee Nipper 	return 0;
2931497f2e6bSLee Nipper }
2932497f2e6bSLee Nipper 
293389d124cbSJonas Eymann static int talitos_cra_init(struct crypto_tfm *tfm)
293489d124cbSJonas Eymann {
293589d124cbSJonas Eymann 	struct crypto_alg *alg = tfm->__crt_alg;
293689d124cbSJonas Eymann 	struct talitos_crypto_alg *talitos_alg;
293789d124cbSJonas Eymann 	struct talitos_ctx *ctx = crypto_tfm_ctx(tfm);
293889d124cbSJonas Eymann 
293989d124cbSJonas Eymann 	if ((alg->cra_flags & CRYPTO_ALG_TYPE_MASK) == CRYPTO_ALG_TYPE_AHASH)
294089d124cbSJonas Eymann 		talitos_alg = container_of(__crypto_ahash_alg(alg),
294189d124cbSJonas Eymann 					   struct talitos_crypto_alg,
294289d124cbSJonas Eymann 					   algt.alg.hash);
294389d124cbSJonas Eymann 	else
294489d124cbSJonas Eymann 		talitos_alg = container_of(alg, struct talitos_crypto_alg,
294589d124cbSJonas Eymann 					   algt.alg.crypto);
294689d124cbSJonas Eymann 
294789d124cbSJonas Eymann 	return talitos_init_common(ctx, talitos_alg);
294889d124cbSJonas Eymann }
294989d124cbSJonas Eymann 
2950aeb4c132SHerbert Xu static int talitos_cra_init_aead(struct crypto_aead *tfm)
2951497f2e6bSLee Nipper {
295289d124cbSJonas Eymann 	struct aead_alg *alg = crypto_aead_alg(tfm);
295389d124cbSJonas Eymann 	struct talitos_crypto_alg *talitos_alg;
295489d124cbSJonas Eymann 	struct talitos_ctx *ctx = crypto_aead_ctx(tfm);
295589d124cbSJonas Eymann 
295689d124cbSJonas Eymann 	talitos_alg = container_of(alg, struct talitos_crypto_alg,
295789d124cbSJonas Eymann 				   algt.alg.aead);
295889d124cbSJonas Eymann 
295989d124cbSJonas Eymann 	return talitos_init_common(ctx, talitos_alg);
29609c4a7965SKim Phillips }
29619c4a7965SKim Phillips 
2962497f2e6bSLee Nipper static int talitos_cra_init_ahash(struct crypto_tfm *tfm)
2963497f2e6bSLee Nipper {
2964497f2e6bSLee Nipper 	struct talitos_ctx *ctx = crypto_tfm_ctx(tfm);
2965497f2e6bSLee Nipper 
2966497f2e6bSLee Nipper 	talitos_cra_init(tfm);
2967497f2e6bSLee Nipper 
2968497f2e6bSLee Nipper 	ctx->keylen = 0;
2969497f2e6bSLee Nipper 	crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm),
2970497f2e6bSLee Nipper 				 sizeof(struct talitos_ahash_req_ctx));
2971497f2e6bSLee Nipper 
2972497f2e6bSLee Nipper 	return 0;
2973497f2e6bSLee Nipper }
2974497f2e6bSLee Nipper 
29759c4a7965SKim Phillips /*
29769c4a7965SKim Phillips  * given the alg's descriptor header template, determine whether descriptor
29779c4a7965SKim Phillips  * type and primary/secondary execution units required match the hw
29789c4a7965SKim Phillips  * capabilities description provided in the device tree node.
29799c4a7965SKim Phillips  */
29809c4a7965SKim Phillips static int hw_supports(struct device *dev, __be32 desc_hdr_template)
29819c4a7965SKim Phillips {
29829c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
29839c4a7965SKim Phillips 	int ret;
29849c4a7965SKim Phillips 
29859c4a7965SKim Phillips 	ret = (1 << DESC_TYPE(desc_hdr_template) & priv->desc_types) &&
29869c4a7965SKim Phillips 	      (1 << PRIMARY_EU(desc_hdr_template) & priv->exec_units);
29879c4a7965SKim Phillips 
29889c4a7965SKim Phillips 	if (SECONDARY_EU(desc_hdr_template))
29899c4a7965SKim Phillips 		ret = ret && (1 << SECONDARY_EU(desc_hdr_template)
29909c4a7965SKim Phillips 		              & priv->exec_units);
29919c4a7965SKim Phillips 
29929c4a7965SKim Phillips 	return ret;
29939c4a7965SKim Phillips }
29949c4a7965SKim Phillips 
29952dc11581SGrant Likely static int talitos_remove(struct platform_device *ofdev)
29969c4a7965SKim Phillips {
29979c4a7965SKim Phillips 	struct device *dev = &ofdev->dev;
29989c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
29999c4a7965SKim Phillips 	struct talitos_crypto_alg *t_alg, *n;
30009c4a7965SKim Phillips 	int i;
30019c4a7965SKim Phillips 
30029c4a7965SKim Phillips 	list_for_each_entry_safe(t_alg, n, &priv->alg_list, entry) {
3003acbf7c62SLee Nipper 		switch (t_alg->algt.type) {
3004acbf7c62SLee Nipper 		case CRYPTO_ALG_TYPE_ABLKCIPHER:
3005acbf7c62SLee Nipper 			break;
3006aeb4c132SHerbert Xu 		case CRYPTO_ALG_TYPE_AEAD:
3007aeb4c132SHerbert Xu 			crypto_unregister_aead(&t_alg->algt.alg.aead);
3008acbf7c62SLee Nipper 		case CRYPTO_ALG_TYPE_AHASH:
3009acbf7c62SLee Nipper 			crypto_unregister_ahash(&t_alg->algt.alg.hash);
3010acbf7c62SLee Nipper 			break;
3011acbf7c62SLee Nipper 		}
30129c4a7965SKim Phillips 		list_del(&t_alg->entry);
30139c4a7965SKim Phillips 		kfree(t_alg);
30149c4a7965SKim Phillips 	}
30159c4a7965SKim Phillips 
30169c4a7965SKim Phillips 	if (hw_supports(dev, DESC_HDR_SEL0_RNG))
30179c4a7965SKim Phillips 		talitos_unregister_rng(dev);
30189c4a7965SKim Phillips 
301935a3bb3dSAaron Sierra 	for (i = 0; priv->chan && i < priv->num_channels; i++)
30204b992628SKim Phillips 		kfree(priv->chan[i].fifo);
30219c4a7965SKim Phillips 
30224b992628SKim Phillips 	kfree(priv->chan);
30239c4a7965SKim Phillips 
3024c3e337f8SKim Phillips 	for (i = 0; i < 2; i++)
30252cdba3cfSKim Phillips 		if (priv->irq[i]) {
3026c3e337f8SKim Phillips 			free_irq(priv->irq[i], dev);
3027c3e337f8SKim Phillips 			irq_dispose_mapping(priv->irq[i]);
30289c4a7965SKim Phillips 		}
30299c4a7965SKim Phillips 
3030c3e337f8SKim Phillips 	tasklet_kill(&priv->done_task[0]);
30312cdba3cfSKim Phillips 	if (priv->irq[1])
3032c3e337f8SKim Phillips 		tasklet_kill(&priv->done_task[1]);
30339c4a7965SKim Phillips 
30349c4a7965SKim Phillips 	iounmap(priv->reg);
30359c4a7965SKim Phillips 
30369c4a7965SKim Phillips 	kfree(priv);
30379c4a7965SKim Phillips 
30389c4a7965SKim Phillips 	return 0;
30399c4a7965SKim Phillips }
30409c4a7965SKim Phillips 
30419c4a7965SKim Phillips static struct talitos_crypto_alg *talitos_alg_alloc(struct device *dev,
30429c4a7965SKim Phillips 						    struct talitos_alg_template
30439c4a7965SKim Phillips 						           *template)
30449c4a7965SKim Phillips {
304560f208d7SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
30469c4a7965SKim Phillips 	struct talitos_crypto_alg *t_alg;
30479c4a7965SKim Phillips 	struct crypto_alg *alg;
30489c4a7965SKim Phillips 
30499c4a7965SKim Phillips 	t_alg = kzalloc(sizeof(struct talitos_crypto_alg), GFP_KERNEL);
30509c4a7965SKim Phillips 	if (!t_alg)
30519c4a7965SKim Phillips 		return ERR_PTR(-ENOMEM);
30529c4a7965SKim Phillips 
3053acbf7c62SLee Nipper 	t_alg->algt = *template;
3054acbf7c62SLee Nipper 
3055acbf7c62SLee Nipper 	switch (t_alg->algt.type) {
3056acbf7c62SLee Nipper 	case CRYPTO_ALG_TYPE_ABLKCIPHER:
3057497f2e6bSLee Nipper 		alg = &t_alg->algt.alg.crypto;
3058497f2e6bSLee Nipper 		alg->cra_init = talitos_cra_init;
3059d4cd3283SKim Phillips 		alg->cra_type = &crypto_ablkcipher_type;
3060b286e003SKim Phillips 		alg->cra_ablkcipher.setkey = ablkcipher_setkey;
3061b286e003SKim Phillips 		alg->cra_ablkcipher.encrypt = ablkcipher_encrypt;
3062b286e003SKim Phillips 		alg->cra_ablkcipher.decrypt = ablkcipher_decrypt;
3063b286e003SKim Phillips 		alg->cra_ablkcipher.geniv = "eseqiv";
3064497f2e6bSLee Nipper 		break;
3065acbf7c62SLee Nipper 	case CRYPTO_ALG_TYPE_AEAD:
3066aeb4c132SHerbert Xu 		alg = &t_alg->algt.alg.aead.base;
3067aeb4c132SHerbert Xu 		t_alg->algt.alg.aead.init = talitos_cra_init_aead;
3068aeb4c132SHerbert Xu 		t_alg->algt.alg.aead.setkey = aead_setkey;
3069aeb4c132SHerbert Xu 		t_alg->algt.alg.aead.encrypt = aead_encrypt;
3070aeb4c132SHerbert Xu 		t_alg->algt.alg.aead.decrypt = aead_decrypt;
30716cda075aSLEROY Christophe 		if (!(priv->features & TALITOS_FTR_SHA224_HWINIT) &&
30726cda075aSLEROY Christophe 		    !strncmp(alg->cra_name, "authenc(hmac(sha224)", 20)) {
30736cda075aSLEROY Christophe 			kfree(t_alg);
30746cda075aSLEROY Christophe 			return ERR_PTR(-ENOTSUPP);
30756cda075aSLEROY Christophe 		}
3076acbf7c62SLee Nipper 		break;
3077acbf7c62SLee Nipper 	case CRYPTO_ALG_TYPE_AHASH:
3078acbf7c62SLee Nipper 		alg = &t_alg->algt.alg.hash.halg.base;
3079497f2e6bSLee Nipper 		alg->cra_init = talitos_cra_init_ahash;
3080d4cd3283SKim Phillips 		alg->cra_type = &crypto_ahash_type;
3081b286e003SKim Phillips 		t_alg->algt.alg.hash.init = ahash_init;
3082b286e003SKim Phillips 		t_alg->algt.alg.hash.update = ahash_update;
3083b286e003SKim Phillips 		t_alg->algt.alg.hash.final = ahash_final;
3084b286e003SKim Phillips 		t_alg->algt.alg.hash.finup = ahash_finup;
3085b286e003SKim Phillips 		t_alg->algt.alg.hash.digest = ahash_digest;
308656136631SLEROY Christophe 		if (!strncmp(alg->cra_name, "hmac", 4))
3087b286e003SKim Phillips 			t_alg->algt.alg.hash.setkey = ahash_setkey;
30883639ca84SHoria Geant? 		t_alg->algt.alg.hash.import = ahash_import;
30893639ca84SHoria Geant? 		t_alg->algt.alg.hash.export = ahash_export;
3090b286e003SKim Phillips 
309179b3a418SLee Nipper 		if (!(priv->features & TALITOS_FTR_HMAC_OK) &&
30920b2730d8SKim Phillips 		    !strncmp(alg->cra_name, "hmac", 4)) {
30930b2730d8SKim Phillips 			kfree(t_alg);
309479b3a418SLee Nipper 			return ERR_PTR(-ENOTSUPP);
30950b2730d8SKim Phillips 		}
309660f208d7SKim Phillips 		if (!(priv->features & TALITOS_FTR_SHA224_HWINIT) &&
309779b3a418SLee Nipper 		    (!strcmp(alg->cra_name, "sha224") ||
309879b3a418SLee Nipper 		     !strcmp(alg->cra_name, "hmac(sha224)"))) {
309960f208d7SKim Phillips 			t_alg->algt.alg.hash.init = ahash_init_sha224_swinit;
310060f208d7SKim Phillips 			t_alg->algt.desc_hdr_template =
310160f208d7SKim Phillips 					DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
310260f208d7SKim Phillips 					DESC_HDR_SEL0_MDEUA |
310360f208d7SKim Phillips 					DESC_HDR_MODE0_MDEU_SHA256;
310460f208d7SKim Phillips 		}
3105497f2e6bSLee Nipper 		break;
31061d11911aSKim Phillips 	default:
31071d11911aSKim Phillips 		dev_err(dev, "unknown algorithm type %d\n", t_alg->algt.type);
31085fa7dadcSHoria Geant? 		kfree(t_alg);
31091d11911aSKim Phillips 		return ERR_PTR(-EINVAL);
3110acbf7c62SLee Nipper 	}
31119c4a7965SKim Phillips 
31129c4a7965SKim Phillips 	alg->cra_module = THIS_MODULE;
3113b0057763SLEROY Christophe 	if (t_alg->algt.priority)
3114b0057763SLEROY Christophe 		alg->cra_priority = t_alg->algt.priority;
3115b0057763SLEROY Christophe 	else
31169c4a7965SKim Phillips 		alg->cra_priority = TALITOS_CRA_PRIORITY;
31179c4a7965SKim Phillips 	alg->cra_alignmask = 0;
31189c4a7965SKim Phillips 	alg->cra_ctxsize = sizeof(struct talitos_ctx);
3119d912bb76SNikos Mavrogiannopoulos 	alg->cra_flags |= CRYPTO_ALG_KERN_DRIVER_ONLY;
31209c4a7965SKim Phillips 
31219c4a7965SKim Phillips 	t_alg->dev = dev;
31229c4a7965SKim Phillips 
31239c4a7965SKim Phillips 	return t_alg;
31249c4a7965SKim Phillips }
31259c4a7965SKim Phillips 
3126c3e337f8SKim Phillips static int talitos_probe_irq(struct platform_device *ofdev)
3127c3e337f8SKim Phillips {
3128c3e337f8SKim Phillips 	struct device *dev = &ofdev->dev;
3129c3e337f8SKim Phillips 	struct device_node *np = ofdev->dev.of_node;
3130c3e337f8SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
3131c3e337f8SKim Phillips 	int err;
3132dd3c0987SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
3133c3e337f8SKim Phillips 
3134c3e337f8SKim Phillips 	priv->irq[0] = irq_of_parse_and_map(np, 0);
31352cdba3cfSKim Phillips 	if (!priv->irq[0]) {
3136c3e337f8SKim Phillips 		dev_err(dev, "failed to map irq\n");
3137c3e337f8SKim Phillips 		return -EINVAL;
3138c3e337f8SKim Phillips 	}
3139dd3c0987SLEROY Christophe 	if (is_sec1) {
3140dd3c0987SLEROY Christophe 		err = request_irq(priv->irq[0], talitos1_interrupt_4ch, 0,
3141dd3c0987SLEROY Christophe 				  dev_driver_string(dev), dev);
3142dd3c0987SLEROY Christophe 		goto primary_out;
3143dd3c0987SLEROY Christophe 	}
3144c3e337f8SKim Phillips 
3145c3e337f8SKim Phillips 	priv->irq[1] = irq_of_parse_and_map(np, 1);
3146c3e337f8SKim Phillips 
3147c3e337f8SKim Phillips 	/* get the primary irq line */
31482cdba3cfSKim Phillips 	if (!priv->irq[1]) {
3149dd3c0987SLEROY Christophe 		err = request_irq(priv->irq[0], talitos2_interrupt_4ch, 0,
3150c3e337f8SKim Phillips 				  dev_driver_string(dev), dev);
3151c3e337f8SKim Phillips 		goto primary_out;
3152c3e337f8SKim Phillips 	}
3153c3e337f8SKim Phillips 
3154dd3c0987SLEROY Christophe 	err = request_irq(priv->irq[0], talitos2_interrupt_ch0_2, 0,
3155c3e337f8SKim Phillips 			  dev_driver_string(dev), dev);
3156c3e337f8SKim Phillips 	if (err)
3157c3e337f8SKim Phillips 		goto primary_out;
3158c3e337f8SKim Phillips 
3159c3e337f8SKim Phillips 	/* get the secondary irq line */
3160dd3c0987SLEROY Christophe 	err = request_irq(priv->irq[1], talitos2_interrupt_ch1_3, 0,
3161c3e337f8SKim Phillips 			  dev_driver_string(dev), dev);
3162c3e337f8SKim Phillips 	if (err) {
3163c3e337f8SKim Phillips 		dev_err(dev, "failed to request secondary irq\n");
3164c3e337f8SKim Phillips 		irq_dispose_mapping(priv->irq[1]);
31652cdba3cfSKim Phillips 		priv->irq[1] = 0;
3166c3e337f8SKim Phillips 	}
3167c3e337f8SKim Phillips 
3168c3e337f8SKim Phillips 	return err;
3169c3e337f8SKim Phillips 
3170c3e337f8SKim Phillips primary_out:
3171c3e337f8SKim Phillips 	if (err) {
3172c3e337f8SKim Phillips 		dev_err(dev, "failed to request primary irq\n");
3173c3e337f8SKim Phillips 		irq_dispose_mapping(priv->irq[0]);
31742cdba3cfSKim Phillips 		priv->irq[0] = 0;
3175c3e337f8SKim Phillips 	}
3176c3e337f8SKim Phillips 
3177c3e337f8SKim Phillips 	return err;
3178c3e337f8SKim Phillips }
3179c3e337f8SKim Phillips 
31801c48a5c9SGrant Likely static int talitos_probe(struct platform_device *ofdev)
31819c4a7965SKim Phillips {
31829c4a7965SKim Phillips 	struct device *dev = &ofdev->dev;
318361c7a080SGrant Likely 	struct device_node *np = ofdev->dev.of_node;
31849c4a7965SKim Phillips 	struct talitos_private *priv;
31859c4a7965SKim Phillips 	const unsigned int *prop;
31869c4a7965SKim Phillips 	int i, err;
31875fa7fa14SLEROY Christophe 	int stride;
31889c4a7965SKim Phillips 
31899c4a7965SKim Phillips 	priv = kzalloc(sizeof(struct talitos_private), GFP_KERNEL);
31909c4a7965SKim Phillips 	if (!priv)
31919c4a7965SKim Phillips 		return -ENOMEM;
31929c4a7965SKim Phillips 
3193f3de9cb1SKevin Hao 	INIT_LIST_HEAD(&priv->alg_list);
3194f3de9cb1SKevin Hao 
31959c4a7965SKim Phillips 	dev_set_drvdata(dev, priv);
31969c4a7965SKim Phillips 
31979c4a7965SKim Phillips 	priv->ofdev = ofdev;
31989c4a7965SKim Phillips 
3199511d63cbSHoria Geanta 	spin_lock_init(&priv->reg_lock);
3200511d63cbSHoria Geanta 
32019c4a7965SKim Phillips 	priv->reg = of_iomap(np, 0);
32029c4a7965SKim Phillips 	if (!priv->reg) {
32039c4a7965SKim Phillips 		dev_err(dev, "failed to of_iomap\n");
32049c4a7965SKim Phillips 		err = -ENOMEM;
32059c4a7965SKim Phillips 		goto err_out;
32069c4a7965SKim Phillips 	}
32079c4a7965SKim Phillips 
32089c4a7965SKim Phillips 	/* get SEC version capabilities from device tree */
32099c4a7965SKim Phillips 	prop = of_get_property(np, "fsl,num-channels", NULL);
32109c4a7965SKim Phillips 	if (prop)
32119c4a7965SKim Phillips 		priv->num_channels = *prop;
32129c4a7965SKim Phillips 
32139c4a7965SKim Phillips 	prop = of_get_property(np, "fsl,channel-fifo-len", NULL);
32149c4a7965SKim Phillips 	if (prop)
32159c4a7965SKim Phillips 		priv->chfifo_len = *prop;
32169c4a7965SKim Phillips 
32179c4a7965SKim Phillips 	prop = of_get_property(np, "fsl,exec-units-mask", NULL);
32189c4a7965SKim Phillips 	if (prop)
32199c4a7965SKim Phillips 		priv->exec_units = *prop;
32209c4a7965SKim Phillips 
32219c4a7965SKim Phillips 	prop = of_get_property(np, "fsl,descriptor-types-mask", NULL);
32229c4a7965SKim Phillips 	if (prop)
32239c4a7965SKim Phillips 		priv->desc_types = *prop;
32249c4a7965SKim Phillips 
32259c4a7965SKim Phillips 	if (!is_power_of_2(priv->num_channels) || !priv->chfifo_len ||
32269c4a7965SKim Phillips 	    !priv->exec_units || !priv->desc_types) {
32279c4a7965SKim Phillips 		dev_err(dev, "invalid property data in device tree node\n");
32289c4a7965SKim Phillips 		err = -EINVAL;
32299c4a7965SKim Phillips 		goto err_out;
32309c4a7965SKim Phillips 	}
32319c4a7965SKim Phillips 
3232f3c85bc1SLee Nipper 	if (of_device_is_compatible(np, "fsl,sec3.0"))
3233f3c85bc1SLee Nipper 		priv->features |= TALITOS_FTR_SRC_LINK_TBL_LEN_INCLUDES_EXTENT;
3234f3c85bc1SLee Nipper 
3235fe5720e2SKim Phillips 	if (of_device_is_compatible(np, "fsl,sec2.1"))
323660f208d7SKim Phillips 		priv->features |= TALITOS_FTR_HW_AUTH_CHECK |
323779b3a418SLee Nipper 				  TALITOS_FTR_SHA224_HWINIT |
323879b3a418SLee Nipper 				  TALITOS_FTR_HMAC_OK;
3239fe5720e2SKim Phillips 
324021590888SLEROY Christophe 	if (of_device_is_compatible(np, "fsl,sec1.0"))
324121590888SLEROY Christophe 		priv->features |= TALITOS_FTR_SEC1;
324221590888SLEROY Christophe 
32435fa7fa14SLEROY Christophe 	if (of_device_is_compatible(np, "fsl,sec1.2")) {
32445fa7fa14SLEROY Christophe 		priv->reg_deu = priv->reg + TALITOS12_DEU;
32455fa7fa14SLEROY Christophe 		priv->reg_aesu = priv->reg + TALITOS12_AESU;
32465fa7fa14SLEROY Christophe 		priv->reg_mdeu = priv->reg + TALITOS12_MDEU;
32475fa7fa14SLEROY Christophe 		stride = TALITOS1_CH_STRIDE;
32485fa7fa14SLEROY Christophe 	} else if (of_device_is_compatible(np, "fsl,sec1.0")) {
32495fa7fa14SLEROY Christophe 		priv->reg_deu = priv->reg + TALITOS10_DEU;
32505fa7fa14SLEROY Christophe 		priv->reg_aesu = priv->reg + TALITOS10_AESU;
32515fa7fa14SLEROY Christophe 		priv->reg_mdeu = priv->reg + TALITOS10_MDEU;
32525fa7fa14SLEROY Christophe 		priv->reg_afeu = priv->reg + TALITOS10_AFEU;
32535fa7fa14SLEROY Christophe 		priv->reg_rngu = priv->reg + TALITOS10_RNGU;
32545fa7fa14SLEROY Christophe 		priv->reg_pkeu = priv->reg + TALITOS10_PKEU;
32555fa7fa14SLEROY Christophe 		stride = TALITOS1_CH_STRIDE;
32565fa7fa14SLEROY Christophe 	} else {
32575fa7fa14SLEROY Christophe 		priv->reg_deu = priv->reg + TALITOS2_DEU;
32585fa7fa14SLEROY Christophe 		priv->reg_aesu = priv->reg + TALITOS2_AESU;
32595fa7fa14SLEROY Christophe 		priv->reg_mdeu = priv->reg + TALITOS2_MDEU;
32605fa7fa14SLEROY Christophe 		priv->reg_afeu = priv->reg + TALITOS2_AFEU;
32615fa7fa14SLEROY Christophe 		priv->reg_rngu = priv->reg + TALITOS2_RNGU;
32625fa7fa14SLEROY Christophe 		priv->reg_pkeu = priv->reg + TALITOS2_PKEU;
32635fa7fa14SLEROY Christophe 		priv->reg_keu = priv->reg + TALITOS2_KEU;
32645fa7fa14SLEROY Christophe 		priv->reg_crcu = priv->reg + TALITOS2_CRCU;
32655fa7fa14SLEROY Christophe 		stride = TALITOS2_CH_STRIDE;
32665fa7fa14SLEROY Christophe 	}
32675fa7fa14SLEROY Christophe 
3268dd3c0987SLEROY Christophe 	err = talitos_probe_irq(ofdev);
3269dd3c0987SLEROY Christophe 	if (err)
3270dd3c0987SLEROY Christophe 		goto err_out;
3271dd3c0987SLEROY Christophe 
3272dd3c0987SLEROY Christophe 	if (of_device_is_compatible(np, "fsl,sec1.0")) {
3273dd3c0987SLEROY Christophe 		tasklet_init(&priv->done_task[0], talitos1_done_4ch,
3274dd3c0987SLEROY Christophe 			     (unsigned long)dev);
3275dd3c0987SLEROY Christophe 	} else {
3276dd3c0987SLEROY Christophe 		if (!priv->irq[1]) {
3277dd3c0987SLEROY Christophe 			tasklet_init(&priv->done_task[0], talitos2_done_4ch,
3278dd3c0987SLEROY Christophe 				     (unsigned long)dev);
3279dd3c0987SLEROY Christophe 		} else {
3280dd3c0987SLEROY Christophe 			tasklet_init(&priv->done_task[0], talitos2_done_ch0_2,
3281dd3c0987SLEROY Christophe 				     (unsigned long)dev);
3282dd3c0987SLEROY Christophe 			tasklet_init(&priv->done_task[1], talitos2_done_ch1_3,
3283dd3c0987SLEROY Christophe 				     (unsigned long)dev);
3284dd3c0987SLEROY Christophe 		}
3285dd3c0987SLEROY Christophe 	}
3286dd3c0987SLEROY Christophe 
32874b992628SKim Phillips 	priv->chan = kzalloc(sizeof(struct talitos_channel) *
32884b992628SKim Phillips 			     priv->num_channels, GFP_KERNEL);
32894b992628SKim Phillips 	if (!priv->chan) {
32904b992628SKim Phillips 		dev_err(dev, "failed to allocate channel management space\n");
32919c4a7965SKim Phillips 		err = -ENOMEM;
32929c4a7965SKim Phillips 		goto err_out;
32939c4a7965SKim Phillips 	}
32949c4a7965SKim Phillips 
3295f641ddddSMartin Hicks 	priv->fifo_len = roundup_pow_of_two(priv->chfifo_len);
3296f641ddddSMartin Hicks 
3297c3e337f8SKim Phillips 	for (i = 0; i < priv->num_channels; i++) {
32985fa7fa14SLEROY Christophe 		priv->chan[i].reg = priv->reg + stride * (i + 1);
32992cdba3cfSKim Phillips 		if (!priv->irq[1] || !(i & 1))
3300c3e337f8SKim Phillips 			priv->chan[i].reg += TALITOS_CH_BASE_OFFSET;
3301ad42d5fcSKim Phillips 
33024b992628SKim Phillips 		spin_lock_init(&priv->chan[i].head_lock);
33034b992628SKim Phillips 		spin_lock_init(&priv->chan[i].tail_lock);
33049c4a7965SKim Phillips 
33054b992628SKim Phillips 		priv->chan[i].fifo = kzalloc(sizeof(struct talitos_request) *
33069c4a7965SKim Phillips 					     priv->fifo_len, GFP_KERNEL);
33074b992628SKim Phillips 		if (!priv->chan[i].fifo) {
33089c4a7965SKim Phillips 			dev_err(dev, "failed to allocate request fifo %d\n", i);
33099c4a7965SKim Phillips 			err = -ENOMEM;
33109c4a7965SKim Phillips 			goto err_out;
33119c4a7965SKim Phillips 		}
33129c4a7965SKim Phillips 
33134b992628SKim Phillips 		atomic_set(&priv->chan[i].submit_count,
33144b992628SKim Phillips 			   -(priv->chfifo_len - 1));
3315f641ddddSMartin Hicks 	}
33169c4a7965SKim Phillips 
331781eb024cSKim Phillips 	dma_set_mask(dev, DMA_BIT_MASK(36));
331881eb024cSKim Phillips 
33199c4a7965SKim Phillips 	/* reset and initialize the h/w */
33209c4a7965SKim Phillips 	err = init_device(dev);
33219c4a7965SKim Phillips 	if (err) {
33229c4a7965SKim Phillips 		dev_err(dev, "failed to initialize device\n");
33239c4a7965SKim Phillips 		goto err_out;
33249c4a7965SKim Phillips 	}
33259c4a7965SKim Phillips 
33269c4a7965SKim Phillips 	/* register the RNG, if available */
33279c4a7965SKim Phillips 	if (hw_supports(dev, DESC_HDR_SEL0_RNG)) {
33289c4a7965SKim Phillips 		err = talitos_register_rng(dev);
33299c4a7965SKim Phillips 		if (err) {
33309c4a7965SKim Phillips 			dev_err(dev, "failed to register hwrng: %d\n", err);
33319c4a7965SKim Phillips 			goto err_out;
33329c4a7965SKim Phillips 		} else
33339c4a7965SKim Phillips 			dev_info(dev, "hwrng\n");
33349c4a7965SKim Phillips 	}
33359c4a7965SKim Phillips 
33369c4a7965SKim Phillips 	/* register crypto algorithms the device supports */
33379c4a7965SKim Phillips 	for (i = 0; i < ARRAY_SIZE(driver_algs); i++) {
33389c4a7965SKim Phillips 		if (hw_supports(dev, driver_algs[i].desc_hdr_template)) {
33399c4a7965SKim Phillips 			struct talitos_crypto_alg *t_alg;
3340aeb4c132SHerbert Xu 			struct crypto_alg *alg = NULL;
33419c4a7965SKim Phillips 
33429c4a7965SKim Phillips 			t_alg = talitos_alg_alloc(dev, &driver_algs[i]);
33439c4a7965SKim Phillips 			if (IS_ERR(t_alg)) {
33449c4a7965SKim Phillips 				err = PTR_ERR(t_alg);
33450b2730d8SKim Phillips 				if (err == -ENOTSUPP)
334679b3a418SLee Nipper 					continue;
33479c4a7965SKim Phillips 				goto err_out;
33489c4a7965SKim Phillips 			}
33499c4a7965SKim Phillips 
3350acbf7c62SLee Nipper 			switch (t_alg->algt.type) {
3351acbf7c62SLee Nipper 			case CRYPTO_ALG_TYPE_ABLKCIPHER:
3352acbf7c62SLee Nipper 				err = crypto_register_alg(
3353acbf7c62SLee Nipper 						&t_alg->algt.alg.crypto);
3354aeb4c132SHerbert Xu 				alg = &t_alg->algt.alg.crypto;
3355acbf7c62SLee Nipper 				break;
3356aeb4c132SHerbert Xu 
3357aeb4c132SHerbert Xu 			case CRYPTO_ALG_TYPE_AEAD:
3358aeb4c132SHerbert Xu 				err = crypto_register_aead(
3359aeb4c132SHerbert Xu 					&t_alg->algt.alg.aead);
3360aeb4c132SHerbert Xu 				alg = &t_alg->algt.alg.aead.base;
3361aeb4c132SHerbert Xu 				break;
3362aeb4c132SHerbert Xu 
3363acbf7c62SLee Nipper 			case CRYPTO_ALG_TYPE_AHASH:
3364acbf7c62SLee Nipper 				err = crypto_register_ahash(
3365acbf7c62SLee Nipper 						&t_alg->algt.alg.hash);
3366aeb4c132SHerbert Xu 				alg = &t_alg->algt.alg.hash.halg.base;
3367acbf7c62SLee Nipper 				break;
3368acbf7c62SLee Nipper 			}
33699c4a7965SKim Phillips 			if (err) {
33709c4a7965SKim Phillips 				dev_err(dev, "%s alg registration failed\n",
3371aeb4c132SHerbert Xu 					alg->cra_driver_name);
33729c4a7965SKim Phillips 				kfree(t_alg);
3373991155baSHoria Geanta 			} else
33749c4a7965SKim Phillips 				list_add_tail(&t_alg->entry, &priv->alg_list);
33759c4a7965SKim Phillips 		}
33769c4a7965SKim Phillips 	}
33775b859b6eSKim Phillips 	if (!list_empty(&priv->alg_list))
33785b859b6eSKim Phillips 		dev_info(dev, "%s algorithms registered in /proc/crypto\n",
33795b859b6eSKim Phillips 			 (char *)of_get_property(np, "compatible", NULL));
33809c4a7965SKim Phillips 
33819c4a7965SKim Phillips 	return 0;
33829c4a7965SKim Phillips 
33839c4a7965SKim Phillips err_out:
33849c4a7965SKim Phillips 	talitos_remove(ofdev);
33859c4a7965SKim Phillips 
33869c4a7965SKim Phillips 	return err;
33879c4a7965SKim Phillips }
33889c4a7965SKim Phillips 
33896c3f975aSMárton Németh static const struct of_device_id talitos_match[] = {
33900635b7dbSLEROY Christophe #ifdef CONFIG_CRYPTO_DEV_TALITOS1
33910635b7dbSLEROY Christophe 	{
33920635b7dbSLEROY Christophe 		.compatible = "fsl,sec1.0",
33930635b7dbSLEROY Christophe 	},
33940635b7dbSLEROY Christophe #endif
33950635b7dbSLEROY Christophe #ifdef CONFIG_CRYPTO_DEV_TALITOS2
33969c4a7965SKim Phillips 	{
33979c4a7965SKim Phillips 		.compatible = "fsl,sec2.0",
33989c4a7965SKim Phillips 	},
33990635b7dbSLEROY Christophe #endif
34009c4a7965SKim Phillips 	{},
34019c4a7965SKim Phillips };
34029c4a7965SKim Phillips MODULE_DEVICE_TABLE(of, talitos_match);
34039c4a7965SKim Phillips 
34041c48a5c9SGrant Likely static struct platform_driver talitos_driver = {
34054018294bSGrant Likely 	.driver = {
34069c4a7965SKim Phillips 		.name = "talitos",
34074018294bSGrant Likely 		.of_match_table = talitos_match,
34084018294bSGrant Likely 	},
34099c4a7965SKim Phillips 	.probe = talitos_probe,
3410596f1034SAl Viro 	.remove = talitos_remove,
34119c4a7965SKim Phillips };
34129c4a7965SKim Phillips 
3413741e8c2dSAxel Lin module_platform_driver(talitos_driver);
34149c4a7965SKim Phillips 
34159c4a7965SKim Phillips MODULE_LICENSE("GPL");
34169c4a7965SKim Phillips MODULE_AUTHOR("Kim Phillips <kim.phillips@freescale.com>");
34179c4a7965SKim Phillips MODULE_DESCRIPTION("Freescale integrated security engine (SEC) driver");
3418