xref: /linux/drivers/crypto/talitos.c (revision 6a1e8d14156d4afb6a835d97170d181ea6b5238c)
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)
593dd3c0987SLEROY Christophe 			dev_err(dev, is_sec1 ? "pointeur 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
814357fb605SHoria Geanta #define TALITOS_MAX_KEY_SIZE		96
8153952f17eSLee Nipper #define TALITOS_MAX_IV_LENGTH		16 /* max of AES_BLOCK_SIZE, DES3_EDE_BLOCK_SIZE */
81670bcaca7SLee Nipper 
8179c4a7965SKim Phillips struct talitos_ctx {
8189c4a7965SKim Phillips 	struct device *dev;
8195228f0f7SKim Phillips 	int ch;
8209c4a7965SKim Phillips 	__be32 desc_hdr_template;
8219c4a7965SKim Phillips 	u8 key[TALITOS_MAX_KEY_SIZE];
82270bcaca7SLee Nipper 	u8 iv[TALITOS_MAX_IV_LENGTH];
8239c4a7965SKim Phillips 	unsigned int keylen;
8249c4a7965SKim Phillips 	unsigned int enckeylen;
8259c4a7965SKim Phillips 	unsigned int authkeylen;
8269c4a7965SKim Phillips };
8279c4a7965SKim Phillips 
828497f2e6bSLee Nipper #define HASH_MAX_BLOCK_SIZE		SHA512_BLOCK_SIZE
829497f2e6bSLee Nipper #define TALITOS_MDEU_MAX_CONTEXT_SIZE	TALITOS_MDEU_CONTEXT_SIZE_SHA384_SHA512
830497f2e6bSLee Nipper 
831497f2e6bSLee Nipper struct talitos_ahash_req_ctx {
83260f208d7SKim Phillips 	u32 hw_context[TALITOS_MDEU_MAX_CONTEXT_SIZE / sizeof(u32)];
833497f2e6bSLee Nipper 	unsigned int hw_context_size;
834497f2e6bSLee Nipper 	u8 buf[HASH_MAX_BLOCK_SIZE];
835497f2e6bSLee Nipper 	u8 bufnext[HASH_MAX_BLOCK_SIZE];
83660f208d7SKim Phillips 	unsigned int swinit;
837497f2e6bSLee Nipper 	unsigned int first;
838497f2e6bSLee Nipper 	unsigned int last;
839497f2e6bSLee Nipper 	unsigned int to_hash_later;
84042e8b0d7SHoria Geant? 	unsigned int nbuf;
841497f2e6bSLee Nipper 	struct scatterlist bufsl[2];
842497f2e6bSLee Nipper 	struct scatterlist *psrc;
843497f2e6bSLee Nipper };
844497f2e6bSLee Nipper 
8453639ca84SHoria Geant? struct talitos_export_state {
8463639ca84SHoria Geant? 	u32 hw_context[TALITOS_MDEU_MAX_CONTEXT_SIZE / sizeof(u32)];
8473639ca84SHoria Geant? 	u8 buf[HASH_MAX_BLOCK_SIZE];
8483639ca84SHoria Geant? 	unsigned int swinit;
8493639ca84SHoria Geant? 	unsigned int first;
8503639ca84SHoria Geant? 	unsigned int last;
8513639ca84SHoria Geant? 	unsigned int to_hash_later;
8523639ca84SHoria Geant? 	unsigned int nbuf;
8533639ca84SHoria Geant? };
8543639ca84SHoria Geant? 
85556af8cd4SLee Nipper static int aead_setkey(struct crypto_aead *authenc,
8569c4a7965SKim Phillips 		       const u8 *key, unsigned int keylen)
8579c4a7965SKim Phillips {
8589c4a7965SKim Phillips 	struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
859c306a98dSMathias Krause 	struct crypto_authenc_keys keys;
8609c4a7965SKim Phillips 
861c306a98dSMathias Krause 	if (crypto_authenc_extractkeys(&keys, key, keylen) != 0)
8629c4a7965SKim Phillips 		goto badkey;
8639c4a7965SKim Phillips 
864c306a98dSMathias Krause 	if (keys.authkeylen + keys.enckeylen > TALITOS_MAX_KEY_SIZE)
8659c4a7965SKim Phillips 		goto badkey;
8669c4a7965SKim Phillips 
867c306a98dSMathias Krause 	memcpy(ctx->key, keys.authkey, keys.authkeylen);
868c306a98dSMathias Krause 	memcpy(&ctx->key[keys.authkeylen], keys.enckey, keys.enckeylen);
8699c4a7965SKim Phillips 
870c306a98dSMathias Krause 	ctx->keylen = keys.authkeylen + keys.enckeylen;
871c306a98dSMathias Krause 	ctx->enckeylen = keys.enckeylen;
872c306a98dSMathias Krause 	ctx->authkeylen = keys.authkeylen;
8739c4a7965SKim Phillips 
8749c4a7965SKim Phillips 	return 0;
8759c4a7965SKim Phillips 
8769c4a7965SKim Phillips badkey:
8779c4a7965SKim Phillips 	crypto_aead_set_flags(authenc, CRYPTO_TFM_RES_BAD_KEY_LEN);
8789c4a7965SKim Phillips 	return -EINVAL;
8799c4a7965SKim Phillips }
8809c4a7965SKim Phillips 
8819c4a7965SKim Phillips /*
88256af8cd4SLee Nipper  * talitos_edesc - s/w-extended descriptor
8839c4a7965SKim Phillips  * @src_nents: number of segments in input scatterlist
8849c4a7965SKim Phillips  * @dst_nents: number of segments in output scatterlist
885aeb4c132SHerbert Xu  * @icv_ool: whether ICV is out-of-line
88679fd31d3SHoria Geanta  * @iv_dma: dma address of iv for checking continuity and link table
8879c4a7965SKim Phillips  * @dma_len: length of dma mapped link_tbl space
8886f65f6acSLEROY Christophe  * @dma_link_tbl: bus physical address of link_tbl/buf
8899c4a7965SKim Phillips  * @desc: h/w descriptor
8906f65f6acSLEROY Christophe  * @link_tbl: input and output h/w link tables (if {src,dst}_nents > 1) (SEC2)
8916f65f6acSLEROY Christophe  * @buf: input and output buffeur (if {src,dst}_nents > 1) (SEC1)
8929c4a7965SKim Phillips  *
8939c4a7965SKim Phillips  * if decrypting (with authcheck), or either one of src_nents or dst_nents
8949c4a7965SKim Phillips  * is greater than 1, an integrity check value is concatenated to the end
8959c4a7965SKim Phillips  * of link_tbl data
8969c4a7965SKim Phillips  */
89756af8cd4SLee Nipper struct talitos_edesc {
8989c4a7965SKim Phillips 	int src_nents;
8999c4a7965SKim Phillips 	int dst_nents;
900aeb4c132SHerbert Xu 	bool icv_ool;
90179fd31d3SHoria Geanta 	dma_addr_t iv_dma;
9029c4a7965SKim Phillips 	int dma_len;
9039c4a7965SKim Phillips 	dma_addr_t dma_link_tbl;
9049c4a7965SKim Phillips 	struct talitos_desc desc;
9056f65f6acSLEROY Christophe 	union {
9069c4a7965SKim Phillips 		struct talitos_ptr link_tbl[0];
9076f65f6acSLEROY Christophe 		u8 buf[0];
9086f65f6acSLEROY Christophe 	};
9099c4a7965SKim Phillips };
9109c4a7965SKim Phillips 
9114de9d0b5SLee Nipper static void talitos_sg_unmap(struct device *dev,
9124de9d0b5SLee Nipper 			     struct talitos_edesc *edesc,
9134de9d0b5SLee Nipper 			     struct scatterlist *src,
914*6a1e8d14SLEROY Christophe 			     struct scatterlist *dst,
915*6a1e8d14SLEROY Christophe 			     unsigned int len, unsigned int offset)
916246a87cdSLEROY Christophe {
917246a87cdSLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
918246a87cdSLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
919*6a1e8d14SLEROY Christophe 	unsigned int src_nents = edesc->src_nents ? : 1;
920*6a1e8d14SLEROY Christophe 	unsigned int dst_nents = edesc->dst_nents ? : 1;
921246a87cdSLEROY Christophe 
922*6a1e8d14SLEROY Christophe 	if (is_sec1 && dst && dst_nents > 1) {
923*6a1e8d14SLEROY Christophe 		dma_sync_single_for_device(dev, edesc->dma_link_tbl + offset,
924246a87cdSLEROY Christophe 					   len, DMA_FROM_DEVICE);
925*6a1e8d14SLEROY Christophe 		sg_pcopy_from_buffer(dst, dst_nents, edesc->buf + offset, len,
926*6a1e8d14SLEROY Christophe 				     offset);
927246a87cdSLEROY Christophe 	}
928*6a1e8d14SLEROY Christophe 	if (src != dst) {
929*6a1e8d14SLEROY Christophe 		if (src_nents == 1 || !is_sec1)
930*6a1e8d14SLEROY Christophe 			dma_unmap_sg(dev, src, src_nents, DMA_TO_DEVICE);
931*6a1e8d14SLEROY Christophe 
932*6a1e8d14SLEROY Christophe 		if (dst && (dst_nents == 1 || !is_sec1))
933*6a1e8d14SLEROY Christophe 			dma_unmap_sg(dev, dst, dst_nents, DMA_FROM_DEVICE);
934*6a1e8d14SLEROY Christophe 	} else if (src_nents == 1 || !is_sec1) {
935*6a1e8d14SLEROY Christophe 		dma_unmap_sg(dev, src, src_nents, DMA_BIDIRECTIONAL);
936246a87cdSLEROY Christophe 	}
937246a87cdSLEROY Christophe }
938246a87cdSLEROY Christophe 
9399c4a7965SKim Phillips static void ipsec_esp_unmap(struct device *dev,
94056af8cd4SLee Nipper 			    struct talitos_edesc *edesc,
9419c4a7965SKim Phillips 			    struct aead_request *areq)
9429c4a7965SKim Phillips {
9439c4a7965SKim Phillips 	unmap_single_talitos_ptr(dev, &edesc->desc.ptr[6], DMA_FROM_DEVICE);
9449c4a7965SKim Phillips 	unmap_single_talitos_ptr(dev, &edesc->desc.ptr[3], DMA_TO_DEVICE);
9459c4a7965SKim Phillips 	unmap_single_talitos_ptr(dev, &edesc->desc.ptr[2], DMA_TO_DEVICE);
9469c4a7965SKim Phillips 	unmap_single_talitos_ptr(dev, &edesc->desc.ptr[0], DMA_TO_DEVICE);
9479c4a7965SKim Phillips 
948*6a1e8d14SLEROY Christophe 	talitos_sg_unmap(dev, edesc, areq->src, areq->dst, areq->cryptlen,
949*6a1e8d14SLEROY Christophe 			 areq->assoclen);
9509c4a7965SKim Phillips 
9519c4a7965SKim Phillips 	if (edesc->dma_len)
9529c4a7965SKim Phillips 		dma_unmap_single(dev, edesc->dma_link_tbl, edesc->dma_len,
9539c4a7965SKim Phillips 				 DMA_BIDIRECTIONAL);
9549c4a7965SKim Phillips }
9559c4a7965SKim Phillips 
9569c4a7965SKim Phillips /*
9579c4a7965SKim Phillips  * ipsec_esp descriptor callbacks
9589c4a7965SKim Phillips  */
9599c4a7965SKim Phillips static void ipsec_esp_encrypt_done(struct device *dev,
9609c4a7965SKim Phillips 				   struct talitos_desc *desc, void *context,
9619c4a7965SKim Phillips 				   int err)
9629c4a7965SKim Phillips {
9639c4a7965SKim Phillips 	struct aead_request *areq = context;
9649c4a7965SKim Phillips 	struct crypto_aead *authenc = crypto_aead_reqtfm(areq);
965aeb4c132SHerbert Xu 	unsigned int authsize = crypto_aead_authsize(authenc);
96619bbbc63SKim Phillips 	struct talitos_edesc *edesc;
9679c4a7965SKim Phillips 	struct scatterlist *sg;
9689c4a7965SKim Phillips 	void *icvdata;
9699c4a7965SKim Phillips 
97019bbbc63SKim Phillips 	edesc = container_of(desc, struct talitos_edesc, desc);
97119bbbc63SKim Phillips 
9729c4a7965SKim Phillips 	ipsec_esp_unmap(dev, edesc, areq);
9739c4a7965SKim Phillips 
9749c4a7965SKim Phillips 	/* copy the generated ICV to dst */
975aeb4c132SHerbert Xu 	if (edesc->icv_ool) {
9769c4a7965SKim Phillips 		icvdata = &edesc->link_tbl[edesc->src_nents +
977aeb4c132SHerbert Xu 					   edesc->dst_nents + 2];
9789c4a7965SKim Phillips 		sg = sg_last(areq->dst, edesc->dst_nents);
979aeb4c132SHerbert Xu 		memcpy((char *)sg_virt(sg) + sg->length - authsize,
980aeb4c132SHerbert Xu 		       icvdata, authsize);
9819c4a7965SKim Phillips 	}
9829c4a7965SKim Phillips 
9839c4a7965SKim Phillips 	kfree(edesc);
9849c4a7965SKim Phillips 
9859c4a7965SKim Phillips 	aead_request_complete(areq, err);
9869c4a7965SKim Phillips }
9879c4a7965SKim Phillips 
988fe5720e2SKim Phillips static void ipsec_esp_decrypt_swauth_done(struct device *dev,
989e938e465SKim Phillips 					  struct talitos_desc *desc,
990e938e465SKim Phillips 					  void *context, int err)
9919c4a7965SKim Phillips {
9929c4a7965SKim Phillips 	struct aead_request *req = context;
9939c4a7965SKim Phillips 	struct crypto_aead *authenc = crypto_aead_reqtfm(req);
994aeb4c132SHerbert Xu 	unsigned int authsize = crypto_aead_authsize(authenc);
99519bbbc63SKim Phillips 	struct talitos_edesc *edesc;
9969c4a7965SKim Phillips 	struct scatterlist *sg;
997aeb4c132SHerbert Xu 	char *oicv, *icv;
9989c4a7965SKim Phillips 
99919bbbc63SKim Phillips 	edesc = container_of(desc, struct talitos_edesc, desc);
100019bbbc63SKim Phillips 
10019c4a7965SKim Phillips 	ipsec_esp_unmap(dev, edesc, req);
10029c4a7965SKim Phillips 
10039c4a7965SKim Phillips 	if (!err) {
10049c4a7965SKim Phillips 		/* auth check */
10059c4a7965SKim Phillips 		sg = sg_last(req->dst, edesc->dst_nents ? : 1);
1006aeb4c132SHerbert Xu 		icv = (char *)sg_virt(sg) + sg->length - authsize;
1007aeb4c132SHerbert Xu 
1008aeb4c132SHerbert Xu 		if (edesc->dma_len) {
1009aeb4c132SHerbert Xu 			oicv = (char *)&edesc->link_tbl[edesc->src_nents +
1010aeb4c132SHerbert Xu 							edesc->dst_nents + 2];
1011aeb4c132SHerbert Xu 			if (edesc->icv_ool)
1012aeb4c132SHerbert Xu 				icv = oicv + authsize;
1013aeb4c132SHerbert Xu 		} else
1014aeb4c132SHerbert Xu 			oicv = (char *)&edesc->link_tbl[0];
1015aeb4c132SHerbert Xu 
101679960943SDavid Gstir 		err = crypto_memneq(oicv, icv, authsize) ? -EBADMSG : 0;
10179c4a7965SKim Phillips 	}
10189c4a7965SKim Phillips 
10199c4a7965SKim Phillips 	kfree(edesc);
10209c4a7965SKim Phillips 
10219c4a7965SKim Phillips 	aead_request_complete(req, err);
10229c4a7965SKim Phillips }
10239c4a7965SKim Phillips 
1024fe5720e2SKim Phillips static void ipsec_esp_decrypt_hwauth_done(struct device *dev,
1025e938e465SKim Phillips 					  struct talitos_desc *desc,
1026e938e465SKim Phillips 					  void *context, int err)
1027fe5720e2SKim Phillips {
1028fe5720e2SKim Phillips 	struct aead_request *req = context;
102919bbbc63SKim Phillips 	struct talitos_edesc *edesc;
103019bbbc63SKim Phillips 
103119bbbc63SKim Phillips 	edesc = container_of(desc, struct talitos_edesc, desc);
1032fe5720e2SKim Phillips 
1033fe5720e2SKim Phillips 	ipsec_esp_unmap(dev, edesc, req);
1034fe5720e2SKim Phillips 
1035fe5720e2SKim Phillips 	/* check ICV auth status */
1036e938e465SKim Phillips 	if (!err && ((desc->hdr_lo & DESC_HDR_LO_ICCR1_MASK) !=
1037e938e465SKim Phillips 		     DESC_HDR_LO_ICCR1_PASS))
1038fe5720e2SKim Phillips 		err = -EBADMSG;
1039fe5720e2SKim Phillips 
1040fe5720e2SKim Phillips 	kfree(edesc);
1041fe5720e2SKim Phillips 
1042fe5720e2SKim Phillips 	aead_request_complete(req, err);
1043fe5720e2SKim Phillips }
1044fe5720e2SKim Phillips 
10459c4a7965SKim Phillips /*
10469c4a7965SKim Phillips  * convert scatterlist to SEC h/w link table format
10479c4a7965SKim Phillips  * stop at cryptlen bytes
10489c4a7965SKim Phillips  */
1049aeb4c132SHerbert Xu static int sg_to_link_tbl_offset(struct scatterlist *sg, int sg_count,
1050aeb4c132SHerbert Xu 				 unsigned int offset, int cryptlen,
1051aeb4c132SHerbert Xu 				 struct talitos_ptr *link_tbl_ptr)
10529c4a7965SKim Phillips {
105370bcaca7SLee Nipper 	int n_sg = sg_count;
1054aeb4c132SHerbert Xu 	int count = 0;
105570bcaca7SLee Nipper 
1056aeb4c132SHerbert Xu 	while (cryptlen && sg && n_sg--) {
1057aeb4c132SHerbert Xu 		unsigned int len = sg_dma_len(sg);
1058aeb4c132SHerbert Xu 
1059aeb4c132SHerbert Xu 		if (offset >= len) {
1060aeb4c132SHerbert Xu 			offset -= len;
1061aeb4c132SHerbert Xu 			goto next;
1062aeb4c132SHerbert Xu 		}
1063aeb4c132SHerbert Xu 
1064aeb4c132SHerbert Xu 		len -= offset;
1065aeb4c132SHerbert Xu 
1066aeb4c132SHerbert Xu 		if (len > cryptlen)
1067aeb4c132SHerbert Xu 			len = cryptlen;
1068aeb4c132SHerbert Xu 
1069aeb4c132SHerbert Xu 		to_talitos_ptr(link_tbl_ptr + count,
1070aeb4c132SHerbert Xu 			       sg_dma_address(sg) + offset, 0);
1071b096b544SLEROY Christophe 		to_talitos_ptr_len(link_tbl_ptr + count, len, 0);
1072b096b544SLEROY Christophe 		to_talitos_ptr_ext_set(link_tbl_ptr + count, 0, 0);
1073aeb4c132SHerbert Xu 		count++;
1074aeb4c132SHerbert Xu 		cryptlen -= len;
1075aeb4c132SHerbert Xu 		offset = 0;
1076aeb4c132SHerbert Xu 
1077aeb4c132SHerbert Xu next:
10785be4d4c9SCristian Stoica 		sg = sg_next(sg);
10799c4a7965SKim Phillips 	}
10809c4a7965SKim Phillips 
10819c4a7965SKim Phillips 	/* tag end of link table */
1082aeb4c132SHerbert Xu 	if (count > 0)
1083b096b544SLEROY Christophe 		to_talitos_ptr_ext_set(link_tbl_ptr + count - 1,
1084b096b544SLEROY Christophe 				       DESC_PTR_LNKTBL_RETURN, 0);
108570bcaca7SLee Nipper 
1086aeb4c132SHerbert Xu 	return count;
1087aeb4c132SHerbert Xu }
1088aeb4c132SHerbert Xu 
1089aeb4c132SHerbert Xu static inline int sg_to_link_tbl(struct scatterlist *sg, int sg_count,
1090aeb4c132SHerbert Xu 				 int cryptlen,
1091aeb4c132SHerbert Xu 				 struct talitos_ptr *link_tbl_ptr)
1092aeb4c132SHerbert Xu {
1093aeb4c132SHerbert Xu 	return sg_to_link_tbl_offset(sg, sg_count, 0, cryptlen,
1094aeb4c132SHerbert Xu 				     link_tbl_ptr);
10959c4a7965SKim Phillips }
10969c4a7965SKim Phillips 
1097*6a1e8d14SLEROY Christophe int talitos_sg_map(struct device *dev, struct scatterlist *src,
1098246a87cdSLEROY Christophe 		   unsigned int len, struct talitos_edesc *edesc,
1099*6a1e8d14SLEROY Christophe 		   struct talitos_ptr *ptr,
1100*6a1e8d14SLEROY Christophe 		   int sg_count, unsigned int offset, int tbl_off)
1101246a87cdSLEROY Christophe {
1102246a87cdSLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
1103246a87cdSLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
1104246a87cdSLEROY Christophe 
1105246a87cdSLEROY Christophe 	to_talitos_ptr_len(ptr, len, is_sec1);
1106246a87cdSLEROY Christophe 	to_talitos_ptr_ext_set(ptr, 0, is_sec1);
1107246a87cdSLEROY Christophe 
1108246a87cdSLEROY Christophe 	if (sg_count == 1) {
1109*6a1e8d14SLEROY Christophe 		to_talitos_ptr(ptr, sg_dma_address(src) + offset, is_sec1);
1110246a87cdSLEROY Christophe 		return sg_count;
1111246a87cdSLEROY Christophe 	}
1112246a87cdSLEROY Christophe 	if (is_sec1) {
1113*6a1e8d14SLEROY Christophe 		to_talitos_ptr(ptr, edesc->dma_link_tbl + offset, is_sec1);
1114*6a1e8d14SLEROY Christophe 		return sg_count;
1115246a87cdSLEROY Christophe 	}
1116*6a1e8d14SLEROY Christophe 	sg_count = sg_to_link_tbl_offset(src, sg_count, offset, len,
1117*6a1e8d14SLEROY Christophe 					 &edesc->link_tbl[tbl_off]);
1118246a87cdSLEROY Christophe 	if (sg_count == 1) {
1119*6a1e8d14SLEROY Christophe 		/* Only one segment now, so no link tbl needed*/
1120*6a1e8d14SLEROY Christophe 		copy_talitos_ptr(ptr, &edesc->link_tbl[tbl_off], is_sec1);
1121*6a1e8d14SLEROY Christophe 		return sg_count;
1122*6a1e8d14SLEROY Christophe 	}
1123246a87cdSLEROY Christophe 	to_talitos_ptr(ptr, edesc->dma_link_tbl +
1124*6a1e8d14SLEROY Christophe 			    tbl_off * sizeof(struct talitos_ptr), is_sec1);
1125*6a1e8d14SLEROY Christophe 	to_talitos_ptr_ext_or(ptr, DESC_PTR_LNKTBL_JUMP, is_sec1);
1126*6a1e8d14SLEROY Christophe 
1127*6a1e8d14SLEROY Christophe 	return sg_count;
1128246a87cdSLEROY Christophe }
1129246a87cdSLEROY Christophe 
11309c4a7965SKim Phillips /*
11319c4a7965SKim Phillips  * fill in and submit ipsec_esp descriptor
11329c4a7965SKim Phillips  */
113356af8cd4SLee Nipper static int ipsec_esp(struct talitos_edesc *edesc, struct aead_request *areq,
1134aeb4c132SHerbert Xu 		     void (*callback)(struct device *dev,
11359c4a7965SKim Phillips 				      struct talitos_desc *desc,
11369c4a7965SKim Phillips 				      void *context, int error))
11379c4a7965SKim Phillips {
11389c4a7965SKim Phillips 	struct crypto_aead *aead = crypto_aead_reqtfm(areq);
1139aeb4c132SHerbert Xu 	unsigned int authsize = crypto_aead_authsize(aead);
11409c4a7965SKim Phillips 	struct talitos_ctx *ctx = crypto_aead_ctx(aead);
11419c4a7965SKim Phillips 	struct device *dev = ctx->dev;
11429c4a7965SKim Phillips 	struct talitos_desc *desc = &edesc->desc;
11439c4a7965SKim Phillips 	unsigned int cryptlen = areq->cryptlen;
1144e41256f1SKim Phillips 	unsigned int ivsize = crypto_aead_ivsize(aead);
1145aeb4c132SHerbert Xu 	int tbl_off = 0;
1146fa86a267SKim Phillips 	int sg_count, ret;
1147fe5720e2SKim Phillips 	int sg_link_tbl_len;
11489c4a7965SKim Phillips 
11499c4a7965SKim Phillips 	/* hmac key */
11509c4a7965SKim Phillips 	map_single_talitos_ptr(dev, &desc->ptr[0], ctx->authkeylen, &ctx->key,
1151a2b35aa8SLEROY Christophe 			       DMA_TO_DEVICE);
115279fd31d3SHoria Geanta 
1153b8a011d4SLABBE Corentin 	sg_count = dma_map_sg(dev, areq->src, edesc->src_nents ?: 1,
1154aeb4c132SHerbert Xu 			      (areq->src == areq->dst) ? DMA_BIDIRECTIONAL
1155b8a011d4SLABBE Corentin 							   : DMA_TO_DEVICE);
11569c4a7965SKim Phillips 	/* hmac data */
1157b096b544SLEROY Christophe 	to_talitos_ptr_len(&desc->ptr[1], areq->assoclen, 0);
1158aeb4c132SHerbert Xu 	if (sg_count > 1 &&
1159aeb4c132SHerbert Xu 	    (ret = sg_to_link_tbl_offset(areq->src, sg_count, 0,
1160aeb4c132SHerbert Xu 					 areq->assoclen,
1161aeb4c132SHerbert Xu 					 &edesc->link_tbl[tbl_off])) > 1) {
116279fd31d3SHoria Geanta 		to_talitos_ptr(&desc->ptr[1], edesc->dma_link_tbl + tbl_off *
1163922f9dc8SLEROY Christophe 			       sizeof(struct talitos_ptr), 0);
1164b096b544SLEROY Christophe 		to_talitos_ptr_ext_set(&desc->ptr[1], DESC_PTR_LNKTBL_JUMP, 0);
116579fd31d3SHoria Geanta 
116679fd31d3SHoria Geanta 		dma_sync_single_for_device(dev, edesc->dma_link_tbl,
116779fd31d3SHoria Geanta 					   edesc->dma_len, DMA_BIDIRECTIONAL);
1168340ff60aSHoria Geant? 
1169340ff60aSHoria Geant? 		tbl_off += ret;
117079fd31d3SHoria Geanta 	} else {
1171aeb4c132SHerbert Xu 		to_talitos_ptr(&desc->ptr[1], sg_dma_address(areq->src), 0);
1172b096b544SLEROY Christophe 		to_talitos_ptr_ext_set(&desc->ptr[1], 0, 0);
117379fd31d3SHoria Geanta 	}
117479fd31d3SHoria Geanta 
11759c4a7965SKim Phillips 	/* cipher iv */
1176922f9dc8SLEROY Christophe 	to_talitos_ptr(&desc->ptr[2], edesc->iv_dma, 0);
1177b096b544SLEROY Christophe 	to_talitos_ptr_len(&desc->ptr[2], ivsize, 0);
1178b096b544SLEROY Christophe 	to_talitos_ptr_ext_set(&desc->ptr[2], 0, 0);
11799c4a7965SKim Phillips 
11809c4a7965SKim Phillips 	/* cipher key */
11819c4a7965SKim Phillips 	map_single_talitos_ptr(dev, &desc->ptr[3], ctx->enckeylen,
1182a2b35aa8SLEROY Christophe 			       (char *)&ctx->key + ctx->authkeylen,
11839c4a7965SKim Phillips 			       DMA_TO_DEVICE);
11849c4a7965SKim Phillips 
11859c4a7965SKim Phillips 	/*
11869c4a7965SKim Phillips 	 * cipher in
11879c4a7965SKim Phillips 	 * map and adjust cipher len to aead request cryptlen.
11889c4a7965SKim Phillips 	 * extent is bytes of HMAC postpended to ciphertext,
11899c4a7965SKim Phillips 	 * typically 12 for ipsec
11909c4a7965SKim Phillips 	 */
1191b096b544SLEROY Christophe 	to_talitos_ptr_len(&desc->ptr[4], cryptlen, 0);
1192b096b544SLEROY Christophe 	to_talitos_ptr_ext_set(&desc->ptr[4], authsize, 0);
11939c4a7965SKim Phillips 
1194fe5720e2SKim Phillips 	sg_link_tbl_len = cryptlen;
1195962a9c99SKim Phillips 	if (edesc->desc.hdr & DESC_HDR_MODE1_MDEU_CICV)
1196aeb4c132SHerbert Xu 		sg_link_tbl_len += authsize;
1197e938e465SKim Phillips 
1198340ff60aSHoria Geant? 	if (sg_count == 1) {
1199340ff60aSHoria Geant? 		to_talitos_ptr(&desc->ptr[4], sg_dma_address(areq->src) +
1200340ff60aSHoria Geant? 			       areq->assoclen, 0);
1201340ff60aSHoria Geant? 	} else if ((ret = sg_to_link_tbl_offset(areq->src, sg_count,
1202340ff60aSHoria Geant? 						areq->assoclen, sg_link_tbl_len,
1203340ff60aSHoria Geant? 						&edesc->link_tbl[tbl_off])) >
1204340ff60aSHoria Geant? 		   1) {
1205b096b544SLEROY Christophe 		to_talitos_ptr_ext_or(&desc->ptr[4], DESC_PTR_LNKTBL_JUMP, 0);
1206aeb4c132SHerbert Xu 		to_talitos_ptr(&desc->ptr[4], edesc->dma_link_tbl +
1207aeb4c132SHerbert Xu 					      tbl_off *
1208aeb4c132SHerbert Xu 					      sizeof(struct talitos_ptr), 0);
1209e938e465SKim Phillips 		dma_sync_single_for_device(dev, edesc->dma_link_tbl,
1210e938e465SKim Phillips 					   edesc->dma_len,
1211e938e465SKim Phillips 					   DMA_BIDIRECTIONAL);
1212340ff60aSHoria Geant? 		tbl_off += ret;
1213340ff60aSHoria Geant? 	} else {
1214340ff60aSHoria Geant? 		copy_talitos_ptr(&desc->ptr[4], &edesc->link_tbl[tbl_off], 0);
1215340ff60aSHoria Geant? 	}
12169c4a7965SKim Phillips 
12179c4a7965SKim Phillips 	/* cipher out */
1218b096b544SLEROY Christophe 	to_talitos_ptr_len(&desc->ptr[5], cryptlen, 0);
1219b096b544SLEROY Christophe 	to_talitos_ptr_ext_set(&desc->ptr[5], authsize, 0);
12209c4a7965SKim Phillips 
1221e938e465SKim Phillips 	if (areq->src != areq->dst)
1222b8a011d4SLABBE Corentin 		sg_count = dma_map_sg(dev, areq->dst, edesc->dst_nents ? : 1,
1223b8a011d4SLABBE Corentin 				      DMA_FROM_DEVICE);
12249c4a7965SKim Phillips 
1225aeb4c132SHerbert Xu 	edesc->icv_ool = false;
1226aeb4c132SHerbert Xu 
1227340ff60aSHoria Geant? 	if (sg_count == 1) {
1228340ff60aSHoria Geant? 		to_talitos_ptr(&desc->ptr[5], sg_dma_address(areq->dst) +
1229340ff60aSHoria Geant? 			       areq->assoclen, 0);
1230340ff60aSHoria Geant? 	} else if ((sg_count =
1231340ff60aSHoria Geant? 			sg_to_link_tbl_offset(areq->dst, sg_count,
1232aeb4c132SHerbert Xu 					      areq->assoclen, cryptlen,
1233340ff60aSHoria Geant? 					      &edesc->link_tbl[tbl_off])) > 1) {
123479fd31d3SHoria Geanta 		struct talitos_ptr *tbl_ptr = &edesc->link_tbl[tbl_off];
12359c4a7965SKim Phillips 
123681eb024cSKim Phillips 		to_talitos_ptr(&desc->ptr[5], edesc->dma_link_tbl +
1237922f9dc8SLEROY Christophe 			       tbl_off * sizeof(struct talitos_ptr), 0);
1238fe5720e2SKim Phillips 
1239f3c85bc1SLee Nipper 		/* Add an entry to the link table for ICV data */
124079fd31d3SHoria Geanta 		tbl_ptr += sg_count - 1;
1241b096b544SLEROY Christophe 		to_talitos_ptr_ext_set(tbl_ptr, 0, 0);
124279fd31d3SHoria Geanta 		tbl_ptr++;
1243b096b544SLEROY Christophe 		to_talitos_ptr_ext_set(tbl_ptr, DESC_PTR_LNKTBL_RETURN, 0);
1244b096b544SLEROY Christophe 		to_talitos_ptr_len(tbl_ptr, authsize, 0);
12459c4a7965SKim Phillips 
12469c4a7965SKim Phillips 		/* icv data follows link tables */
124779fd31d3SHoria Geanta 		to_talitos_ptr(tbl_ptr, edesc->dma_link_tbl +
1248aeb4c132SHerbert Xu 					(edesc->src_nents + edesc->dst_nents +
1249aeb4c132SHerbert Xu 					 2) * sizeof(struct talitos_ptr) +
1250aeb4c132SHerbert Xu 					authsize, 0);
1251b096b544SLEROY Christophe 		to_talitos_ptr_ext_or(&desc->ptr[5], DESC_PTR_LNKTBL_JUMP, 0);
12529c4a7965SKim Phillips 		dma_sync_single_for_device(ctx->dev, edesc->dma_link_tbl,
12539c4a7965SKim Phillips 					   edesc->dma_len, DMA_BIDIRECTIONAL);
1254aeb4c132SHerbert Xu 
1255aeb4c132SHerbert Xu 		edesc->icv_ool = true;
1256340ff60aSHoria Geant? 	} else {
1257340ff60aSHoria Geant? 		copy_talitos_ptr(&desc->ptr[5], &edesc->link_tbl[tbl_off], 0);
1258340ff60aSHoria Geant? 	}
12599c4a7965SKim Phillips 
12609c4a7965SKim Phillips 	/* iv out */
1261a2b35aa8SLEROY Christophe 	map_single_talitos_ptr(dev, &desc->ptr[6], ivsize, ctx->iv,
12629c4a7965SKim Phillips 			       DMA_FROM_DEVICE);
12639c4a7965SKim Phillips 
12645228f0f7SKim Phillips 	ret = talitos_submit(dev, ctx->ch, desc, callback, areq);
1265fa86a267SKim Phillips 	if (ret != -EINPROGRESS) {
1266fa86a267SKim Phillips 		ipsec_esp_unmap(dev, edesc, areq);
1267fa86a267SKim Phillips 		kfree(edesc);
1268fa86a267SKim Phillips 	}
1269fa86a267SKim Phillips 	return ret;
12709c4a7965SKim Phillips }
12719c4a7965SKim Phillips 
12729c4a7965SKim Phillips /*
127356af8cd4SLee Nipper  * allocate and map the extended descriptor
12749c4a7965SKim Phillips  */
12754de9d0b5SLee Nipper static struct talitos_edesc *talitos_edesc_alloc(struct device *dev,
12764de9d0b5SLee Nipper 						 struct scatterlist *src,
12774de9d0b5SLee Nipper 						 struct scatterlist *dst,
127879fd31d3SHoria Geanta 						 u8 *iv,
127979fd31d3SHoria Geanta 						 unsigned int assoclen,
12804de9d0b5SLee Nipper 						 unsigned int cryptlen,
12814de9d0b5SLee Nipper 						 unsigned int authsize,
128279fd31d3SHoria Geanta 						 unsigned int ivsize,
12834de9d0b5SLee Nipper 						 int icv_stashing,
128462293a37SHoria Geanta 						 u32 cryptoflags,
128562293a37SHoria Geanta 						 bool encrypt)
12869c4a7965SKim Phillips {
128756af8cd4SLee Nipper 	struct talitos_edesc *edesc;
1288*6a1e8d14SLEROY Christophe 	int src_nents, dst_nents, alloc_len, dma_len, src_len, dst_len;
128979fd31d3SHoria Geanta 	dma_addr_t iv_dma = 0;
12904de9d0b5SLee Nipper 	gfp_t flags = cryptoflags & CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL :
1291586725f8SKim Phillips 		      GFP_ATOMIC;
12926f65f6acSLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
12936f65f6acSLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
12946f65f6acSLEROY Christophe 	int max_len = is_sec1 ? TALITOS1_MAX_DATA_LEN : TALITOS2_MAX_DATA_LEN;
12958e409fe1SLABBE Corentin 	void *err;
12969c4a7965SKim Phillips 
12976f65f6acSLEROY Christophe 	if (cryptlen + authsize > max_len) {
12984de9d0b5SLee Nipper 		dev_err(dev, "length exceeds h/w max limit\n");
12999c4a7965SKim Phillips 		return ERR_PTR(-EINVAL);
13009c4a7965SKim Phillips 	}
13019c4a7965SKim Phillips 
1302935e99a3SHoria Geanta 	if (ivsize)
130379fd31d3SHoria Geanta 		iv_dma = dma_map_single(dev, iv, ivsize, DMA_TO_DEVICE);
130479fd31d3SHoria Geanta 
130562293a37SHoria Geanta 	if (!dst || dst == src) {
1306*6a1e8d14SLEROY Christophe 		src_len = assoclen + cryptlen + authsize;
1307*6a1e8d14SLEROY Christophe 		src_nents = sg_nents_for_len(src, src_len);
13088e409fe1SLABBE Corentin 		if (src_nents < 0) {
13098e409fe1SLABBE Corentin 			dev_err(dev, "Invalid number of src SG.\n");
13108e409fe1SLABBE Corentin 			err = ERR_PTR(-EINVAL);
13118e409fe1SLABBE Corentin 			goto error_sg;
13128e409fe1SLABBE Corentin 		}
13139c4a7965SKim Phillips 		src_nents = (src_nents == 1) ? 0 : src_nents;
131462293a37SHoria Geanta 		dst_nents = dst ? src_nents : 0;
1315*6a1e8d14SLEROY Christophe 		dst_len = 0;
131662293a37SHoria Geanta 	} else { /* dst && dst != src*/
1317*6a1e8d14SLEROY Christophe 		src_len = assoclen + cryptlen + (encrypt ? 0 : authsize);
1318*6a1e8d14SLEROY Christophe 		src_nents = sg_nents_for_len(src, src_len);
13198e409fe1SLABBE Corentin 		if (src_nents < 0) {
13208e409fe1SLABBE Corentin 			dev_err(dev, "Invalid number of src SG.\n");
13218e409fe1SLABBE Corentin 			err = ERR_PTR(-EINVAL);
13228e409fe1SLABBE Corentin 			goto error_sg;
13238e409fe1SLABBE Corentin 		}
132462293a37SHoria Geanta 		src_nents = (src_nents == 1) ? 0 : src_nents;
1325*6a1e8d14SLEROY Christophe 		dst_len = assoclen + cryptlen + (encrypt ? authsize : 0);
1326*6a1e8d14SLEROY Christophe 		dst_nents = sg_nents_for_len(dst, dst_len);
13278e409fe1SLABBE Corentin 		if (dst_nents < 0) {
13288e409fe1SLABBE Corentin 			dev_err(dev, "Invalid number of dst SG.\n");
13298e409fe1SLABBE Corentin 			err = ERR_PTR(-EINVAL);
13308e409fe1SLABBE Corentin 			goto error_sg;
13318e409fe1SLABBE Corentin 		}
1332695ad589SLee Nipper 		dst_nents = (dst_nents == 1) ? 0 : dst_nents;
13339c4a7965SKim Phillips 	}
13349c4a7965SKim Phillips 
13359c4a7965SKim Phillips 	/*
13369c4a7965SKim Phillips 	 * allocate space for base edesc plus the link tables,
1337aeb4c132SHerbert Xu 	 * allowing for two separate entries for AD and generated ICV (+ 2),
1338aeb4c132SHerbert Xu 	 * and space for two sets of ICVs (stashed and generated)
13399c4a7965SKim Phillips 	 */
134056af8cd4SLee Nipper 	alloc_len = sizeof(struct talitos_edesc);
1341aeb4c132SHerbert Xu 	if (src_nents || dst_nents) {
13426f65f6acSLEROY Christophe 		if (is_sec1)
1343*6a1e8d14SLEROY Christophe 			dma_len = (src_nents ? src_len : 0) +
1344*6a1e8d14SLEROY Christophe 				  (dst_nents ? dst_len : 0);
13456f65f6acSLEROY Christophe 		else
1346aeb4c132SHerbert Xu 			dma_len = (src_nents + dst_nents + 2) *
1347aeb4c132SHerbert Xu 				  sizeof(struct talitos_ptr) + authsize * 2;
13489c4a7965SKim Phillips 		alloc_len += dma_len;
13499c4a7965SKim Phillips 	} else {
13509c4a7965SKim Phillips 		dma_len = 0;
13514de9d0b5SLee Nipper 		alloc_len += icv_stashing ? authsize : 0;
13529c4a7965SKim Phillips 	}
13539c4a7965SKim Phillips 
1354586725f8SKim Phillips 	edesc = kmalloc(alloc_len, GFP_DMA | flags);
13559c4a7965SKim Phillips 	if (!edesc) {
13564de9d0b5SLee Nipper 		dev_err(dev, "could not allocate edescriptor\n");
13578e409fe1SLABBE Corentin 		err = ERR_PTR(-ENOMEM);
13588e409fe1SLABBE Corentin 		goto error_sg;
13599c4a7965SKim Phillips 	}
13609c4a7965SKim Phillips 
13619c4a7965SKim Phillips 	edesc->src_nents = src_nents;
13629c4a7965SKim Phillips 	edesc->dst_nents = dst_nents;
136379fd31d3SHoria Geanta 	edesc->iv_dma = iv_dma;
13649c4a7965SKim Phillips 	edesc->dma_len = dma_len;
1365497f2e6bSLee Nipper 	if (dma_len)
13664de9d0b5SLee Nipper 		edesc->dma_link_tbl = dma_map_single(dev, &edesc->link_tbl[0],
1367497f2e6bSLee Nipper 						     edesc->dma_len,
1368497f2e6bSLee Nipper 						     DMA_BIDIRECTIONAL);
13699c4a7965SKim Phillips 
13709c4a7965SKim Phillips 	return edesc;
13718e409fe1SLABBE Corentin error_sg:
13728e409fe1SLABBE Corentin 	if (iv_dma)
13738e409fe1SLABBE Corentin 		dma_unmap_single(dev, iv_dma, ivsize, DMA_TO_DEVICE);
13748e409fe1SLABBE Corentin 	return err;
13759c4a7965SKim Phillips }
13769c4a7965SKim Phillips 
137779fd31d3SHoria Geanta static struct talitos_edesc *aead_edesc_alloc(struct aead_request *areq, u8 *iv,
137862293a37SHoria Geanta 					      int icv_stashing, bool encrypt)
13794de9d0b5SLee Nipper {
13804de9d0b5SLee Nipper 	struct crypto_aead *authenc = crypto_aead_reqtfm(areq);
1381aeb4c132SHerbert Xu 	unsigned int authsize = crypto_aead_authsize(authenc);
13824de9d0b5SLee Nipper 	struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
138379fd31d3SHoria Geanta 	unsigned int ivsize = crypto_aead_ivsize(authenc);
13844de9d0b5SLee Nipper 
1385aeb4c132SHerbert Xu 	return talitos_edesc_alloc(ctx->dev, areq->src, areq->dst,
138679fd31d3SHoria Geanta 				   iv, areq->assoclen, areq->cryptlen,
1387aeb4c132SHerbert Xu 				   authsize, ivsize, icv_stashing,
138862293a37SHoria Geanta 				   areq->base.flags, encrypt);
13894de9d0b5SLee Nipper }
13904de9d0b5SLee Nipper 
139156af8cd4SLee Nipper static int aead_encrypt(struct aead_request *req)
13929c4a7965SKim Phillips {
13939c4a7965SKim Phillips 	struct crypto_aead *authenc = crypto_aead_reqtfm(req);
13949c4a7965SKim Phillips 	struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
139556af8cd4SLee Nipper 	struct talitos_edesc *edesc;
13969c4a7965SKim Phillips 
13979c4a7965SKim Phillips 	/* allocate extended descriptor */
139862293a37SHoria Geanta 	edesc = aead_edesc_alloc(req, req->iv, 0, true);
13999c4a7965SKim Phillips 	if (IS_ERR(edesc))
14009c4a7965SKim Phillips 		return PTR_ERR(edesc);
14019c4a7965SKim Phillips 
14029c4a7965SKim Phillips 	/* set encrypt */
140370bcaca7SLee Nipper 	edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_MODE0_ENCRYPT;
14049c4a7965SKim Phillips 
1405aeb4c132SHerbert Xu 	return ipsec_esp(edesc, req, ipsec_esp_encrypt_done);
14069c4a7965SKim Phillips }
14079c4a7965SKim Phillips 
140856af8cd4SLee Nipper static int aead_decrypt(struct aead_request *req)
14099c4a7965SKim Phillips {
14109c4a7965SKim Phillips 	struct crypto_aead *authenc = crypto_aead_reqtfm(req);
1411aeb4c132SHerbert Xu 	unsigned int authsize = crypto_aead_authsize(authenc);
14129c4a7965SKim Phillips 	struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
1413fe5720e2SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(ctx->dev);
141456af8cd4SLee Nipper 	struct talitos_edesc *edesc;
14159c4a7965SKim Phillips 	struct scatterlist *sg;
14169c4a7965SKim Phillips 	void *icvdata;
14179c4a7965SKim Phillips 
14189c4a7965SKim Phillips 	req->cryptlen -= authsize;
14199c4a7965SKim Phillips 
14209c4a7965SKim Phillips 	/* allocate extended descriptor */
142162293a37SHoria Geanta 	edesc = aead_edesc_alloc(req, req->iv, 1, false);
14229c4a7965SKim Phillips 	if (IS_ERR(edesc))
14239c4a7965SKim Phillips 		return PTR_ERR(edesc);
14249c4a7965SKim Phillips 
1425fe5720e2SKim Phillips 	if ((priv->features & TALITOS_FTR_HW_AUTH_CHECK) &&
1426e938e465SKim Phillips 	    ((!edesc->src_nents && !edesc->dst_nents) ||
1427e938e465SKim Phillips 	     priv->features & TALITOS_FTR_SRC_LINK_TBL_LEN_INCLUDES_EXTENT)) {
1428fe5720e2SKim Phillips 
1429fe5720e2SKim Phillips 		/* decrypt and check the ICV */
1430e938e465SKim Phillips 		edesc->desc.hdr = ctx->desc_hdr_template |
1431e938e465SKim Phillips 				  DESC_HDR_DIR_INBOUND |
1432fe5720e2SKim Phillips 				  DESC_HDR_MODE1_MDEU_CICV;
1433fe5720e2SKim Phillips 
1434fe5720e2SKim Phillips 		/* reset integrity check result bits */
1435fe5720e2SKim Phillips 		edesc->desc.hdr_lo = 0;
1436fe5720e2SKim Phillips 
1437aeb4c132SHerbert Xu 		return ipsec_esp(edesc, req, ipsec_esp_decrypt_hwauth_done);
1438e938e465SKim Phillips 	}
1439fe5720e2SKim Phillips 
1440fe5720e2SKim Phillips 	/* Have to check the ICV with software */
1441fe5720e2SKim Phillips 	edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_DIR_INBOUND;
1442fe5720e2SKim Phillips 
14439c4a7965SKim Phillips 	/* stash incoming ICV for later cmp with ICV generated by the h/w */
14449c4a7965SKim Phillips 	if (edesc->dma_len)
1445aeb4c132SHerbert Xu 		icvdata = (char *)&edesc->link_tbl[edesc->src_nents +
1446aeb4c132SHerbert Xu 						   edesc->dst_nents + 2];
14479c4a7965SKim Phillips 	else
14489c4a7965SKim Phillips 		icvdata = &edesc->link_tbl[0];
14499c4a7965SKim Phillips 
14509c4a7965SKim Phillips 	sg = sg_last(req->src, edesc->src_nents ? : 1);
14519c4a7965SKim Phillips 
1452aeb4c132SHerbert Xu 	memcpy(icvdata, (char *)sg_virt(sg) + sg->length - authsize, authsize);
14539c4a7965SKim Phillips 
1454aeb4c132SHerbert Xu 	return ipsec_esp(edesc, req, ipsec_esp_decrypt_swauth_done);
14559c4a7965SKim Phillips }
14569c4a7965SKim Phillips 
14574de9d0b5SLee Nipper static int ablkcipher_setkey(struct crypto_ablkcipher *cipher,
14584de9d0b5SLee Nipper 			     const u8 *key, unsigned int keylen)
14594de9d0b5SLee Nipper {
14604de9d0b5SLee Nipper 	struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher);
14614de9d0b5SLee Nipper 
14624de9d0b5SLee Nipper 	memcpy(&ctx->key, key, keylen);
14634de9d0b5SLee Nipper 	ctx->keylen = keylen;
14644de9d0b5SLee Nipper 
14654de9d0b5SLee Nipper 	return 0;
14664de9d0b5SLee Nipper }
14674de9d0b5SLee Nipper 
14684de9d0b5SLee Nipper static void common_nonsnoop_unmap(struct device *dev,
14694de9d0b5SLee Nipper 				  struct talitos_edesc *edesc,
14704de9d0b5SLee Nipper 				  struct ablkcipher_request *areq)
14714de9d0b5SLee Nipper {
14724de9d0b5SLee Nipper 	unmap_single_talitos_ptr(dev, &edesc->desc.ptr[5], DMA_FROM_DEVICE);
1473032d197eSLEROY Christophe 
1474*6a1e8d14SLEROY Christophe 	talitos_sg_unmap(dev, edesc, areq->src, areq->dst, areq->nbytes, 0);
14754de9d0b5SLee Nipper 	unmap_single_talitos_ptr(dev, &edesc->desc.ptr[2], DMA_TO_DEVICE);
14764de9d0b5SLee Nipper 	unmap_single_talitos_ptr(dev, &edesc->desc.ptr[1], DMA_TO_DEVICE);
14774de9d0b5SLee Nipper 
14784de9d0b5SLee Nipper 	if (edesc->dma_len)
14794de9d0b5SLee Nipper 		dma_unmap_single(dev, edesc->dma_link_tbl, edesc->dma_len,
14804de9d0b5SLee Nipper 				 DMA_BIDIRECTIONAL);
14814de9d0b5SLee Nipper }
14824de9d0b5SLee Nipper 
14834de9d0b5SLee Nipper static void ablkcipher_done(struct device *dev,
14844de9d0b5SLee Nipper 			    struct talitos_desc *desc, void *context,
14854de9d0b5SLee Nipper 			    int err)
14864de9d0b5SLee Nipper {
14874de9d0b5SLee Nipper 	struct ablkcipher_request *areq = context;
148819bbbc63SKim Phillips 	struct talitos_edesc *edesc;
148919bbbc63SKim Phillips 
149019bbbc63SKim Phillips 	edesc = container_of(desc, struct talitos_edesc, desc);
14914de9d0b5SLee Nipper 
14924de9d0b5SLee Nipper 	common_nonsnoop_unmap(dev, edesc, areq);
14934de9d0b5SLee Nipper 
14944de9d0b5SLee Nipper 	kfree(edesc);
14954de9d0b5SLee Nipper 
14964de9d0b5SLee Nipper 	areq->base.complete(&areq->base, err);
14974de9d0b5SLee Nipper }
14984de9d0b5SLee Nipper 
14994de9d0b5SLee Nipper static int common_nonsnoop(struct talitos_edesc *edesc,
15004de9d0b5SLee Nipper 			   struct ablkcipher_request *areq,
15014de9d0b5SLee Nipper 			   void (*callback) (struct device *dev,
15024de9d0b5SLee Nipper 					     struct talitos_desc *desc,
15034de9d0b5SLee Nipper 					     void *context, int error))
15044de9d0b5SLee Nipper {
15054de9d0b5SLee Nipper 	struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(areq);
15064de9d0b5SLee Nipper 	struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher);
15074de9d0b5SLee Nipper 	struct device *dev = ctx->dev;
15084de9d0b5SLee Nipper 	struct talitos_desc *desc = &edesc->desc;
15094de9d0b5SLee Nipper 	unsigned int cryptlen = areq->nbytes;
151079fd31d3SHoria Geanta 	unsigned int ivsize = crypto_ablkcipher_ivsize(cipher);
15114de9d0b5SLee Nipper 	int sg_count, ret;
1512*6a1e8d14SLEROY Christophe 	bool sync_needed = false;
1513922f9dc8SLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
1514922f9dc8SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
15154de9d0b5SLee Nipper 
15164de9d0b5SLee Nipper 	/* first DWORD empty */
15172529bc37SLEROY Christophe 	desc->ptr[0] = zero_entry;
15184de9d0b5SLee Nipper 
15194de9d0b5SLee Nipper 	/* cipher iv */
1520922f9dc8SLEROY Christophe 	to_talitos_ptr(&desc->ptr[1], edesc->iv_dma, is_sec1);
1521922f9dc8SLEROY Christophe 	to_talitos_ptr_len(&desc->ptr[1], ivsize, is_sec1);
1522b096b544SLEROY Christophe 	to_talitos_ptr_ext_set(&desc->ptr[1], 0, is_sec1);
15234de9d0b5SLee Nipper 
15244de9d0b5SLee Nipper 	/* cipher key */
15254de9d0b5SLee Nipper 	map_single_talitos_ptr(dev, &desc->ptr[2], ctx->keylen,
1526a2b35aa8SLEROY Christophe 			       (char *)&ctx->key, DMA_TO_DEVICE);
15274de9d0b5SLee Nipper 
1528*6a1e8d14SLEROY Christophe 	sg_count = edesc->src_nents ?: 1;
1529*6a1e8d14SLEROY Christophe 	if (is_sec1 && sg_count > 1)
1530*6a1e8d14SLEROY Christophe 		sg_copy_to_buffer(areq->src, sg_count, edesc->buf,
1531*6a1e8d14SLEROY Christophe 				  cryptlen);
1532*6a1e8d14SLEROY Christophe 	else
1533*6a1e8d14SLEROY Christophe 		sg_count = dma_map_sg(dev, areq->src, sg_count,
1534*6a1e8d14SLEROY Christophe 				      (areq->src == areq->dst) ?
1535*6a1e8d14SLEROY Christophe 				      DMA_BIDIRECTIONAL : DMA_TO_DEVICE);
15364de9d0b5SLee Nipper 	/*
15374de9d0b5SLee Nipper 	 * cipher in
15384de9d0b5SLee Nipper 	 */
1539*6a1e8d14SLEROY Christophe 	sg_count = talitos_sg_map(dev, areq->src, cryptlen, edesc,
1540*6a1e8d14SLEROY Christophe 				  &desc->ptr[3], sg_count, 0, 0);
1541*6a1e8d14SLEROY Christophe 	if (sg_count > 1)
1542*6a1e8d14SLEROY Christophe 		sync_needed = true;
15434de9d0b5SLee Nipper 
15444de9d0b5SLee Nipper 	/* cipher out */
1545*6a1e8d14SLEROY Christophe 	if (areq->src != areq->dst) {
1546*6a1e8d14SLEROY Christophe 		sg_count = edesc->dst_nents ? : 1;
1547*6a1e8d14SLEROY Christophe 		if (!is_sec1 || sg_count == 1)
1548*6a1e8d14SLEROY Christophe 			dma_map_sg(dev, areq->dst, sg_count, DMA_FROM_DEVICE);
1549*6a1e8d14SLEROY Christophe 	}
1550*6a1e8d14SLEROY Christophe 
1551*6a1e8d14SLEROY Christophe 	ret = talitos_sg_map(dev, areq->dst, cryptlen, edesc, &desc->ptr[4],
1552*6a1e8d14SLEROY Christophe 			     sg_count, 0, (edesc->src_nents + 1));
1553*6a1e8d14SLEROY Christophe 	if (ret > 1)
1554*6a1e8d14SLEROY Christophe 		sync_needed = true;
15554de9d0b5SLee Nipper 
15564de9d0b5SLee Nipper 	/* iv out */
1557a2b35aa8SLEROY Christophe 	map_single_talitos_ptr(dev, &desc->ptr[5], ivsize, ctx->iv,
15584de9d0b5SLee Nipper 			       DMA_FROM_DEVICE);
15594de9d0b5SLee Nipper 
15604de9d0b5SLee Nipper 	/* last DWORD empty */
15612529bc37SLEROY Christophe 	desc->ptr[6] = zero_entry;
15624de9d0b5SLee Nipper 
1563*6a1e8d14SLEROY Christophe 	if (sync_needed)
1564*6a1e8d14SLEROY Christophe 		dma_sync_single_for_device(dev, edesc->dma_link_tbl,
1565*6a1e8d14SLEROY Christophe 					   edesc->dma_len, DMA_BIDIRECTIONAL);
1566*6a1e8d14SLEROY Christophe 
15675228f0f7SKim Phillips 	ret = talitos_submit(dev, ctx->ch, desc, callback, areq);
15684de9d0b5SLee Nipper 	if (ret != -EINPROGRESS) {
15694de9d0b5SLee Nipper 		common_nonsnoop_unmap(dev, edesc, areq);
15704de9d0b5SLee Nipper 		kfree(edesc);
15714de9d0b5SLee Nipper 	}
15724de9d0b5SLee Nipper 	return ret;
15734de9d0b5SLee Nipper }
15744de9d0b5SLee Nipper 
1575e938e465SKim Phillips static struct talitos_edesc *ablkcipher_edesc_alloc(struct ablkcipher_request *
157662293a37SHoria Geanta 						    areq, bool encrypt)
15774de9d0b5SLee Nipper {
15784de9d0b5SLee Nipper 	struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(areq);
15794de9d0b5SLee Nipper 	struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher);
158079fd31d3SHoria Geanta 	unsigned int ivsize = crypto_ablkcipher_ivsize(cipher);
15814de9d0b5SLee Nipper 
1582aeb4c132SHerbert Xu 	return talitos_edesc_alloc(ctx->dev, areq->src, areq->dst,
158379fd31d3SHoria Geanta 				   areq->info, 0, areq->nbytes, 0, ivsize, 0,
158462293a37SHoria Geanta 				   areq->base.flags, encrypt);
15854de9d0b5SLee Nipper }
15864de9d0b5SLee Nipper 
15874de9d0b5SLee Nipper static int ablkcipher_encrypt(struct ablkcipher_request *areq)
15884de9d0b5SLee Nipper {
15894de9d0b5SLee Nipper 	struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(areq);
15904de9d0b5SLee Nipper 	struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher);
15914de9d0b5SLee Nipper 	struct talitos_edesc *edesc;
15924de9d0b5SLee Nipper 
15934de9d0b5SLee Nipper 	/* allocate extended descriptor */
159462293a37SHoria Geanta 	edesc = ablkcipher_edesc_alloc(areq, true);
15954de9d0b5SLee Nipper 	if (IS_ERR(edesc))
15964de9d0b5SLee Nipper 		return PTR_ERR(edesc);
15974de9d0b5SLee Nipper 
15984de9d0b5SLee Nipper 	/* set encrypt */
15994de9d0b5SLee Nipper 	edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_MODE0_ENCRYPT;
16004de9d0b5SLee Nipper 
1601febec542SKim Phillips 	return common_nonsnoop(edesc, areq, ablkcipher_done);
16024de9d0b5SLee Nipper }
16034de9d0b5SLee Nipper 
16044de9d0b5SLee Nipper static int ablkcipher_decrypt(struct ablkcipher_request *areq)
16054de9d0b5SLee Nipper {
16064de9d0b5SLee Nipper 	struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(areq);
16074de9d0b5SLee Nipper 	struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher);
16084de9d0b5SLee Nipper 	struct talitos_edesc *edesc;
16094de9d0b5SLee Nipper 
16104de9d0b5SLee Nipper 	/* allocate extended descriptor */
161162293a37SHoria Geanta 	edesc = ablkcipher_edesc_alloc(areq, false);
16124de9d0b5SLee Nipper 	if (IS_ERR(edesc))
16134de9d0b5SLee Nipper 		return PTR_ERR(edesc);
16144de9d0b5SLee Nipper 
16154de9d0b5SLee Nipper 	edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_DIR_INBOUND;
16164de9d0b5SLee Nipper 
1617febec542SKim Phillips 	return common_nonsnoop(edesc, areq, ablkcipher_done);
16184de9d0b5SLee Nipper }
16194de9d0b5SLee Nipper 
1620497f2e6bSLee Nipper static void common_nonsnoop_hash_unmap(struct device *dev,
1621497f2e6bSLee Nipper 				       struct talitos_edesc *edesc,
1622497f2e6bSLee Nipper 				       struct ahash_request *areq)
1623497f2e6bSLee Nipper {
1624497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
1625922f9dc8SLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
1626922f9dc8SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
1627497f2e6bSLee Nipper 
1628497f2e6bSLee Nipper 	unmap_single_talitos_ptr(dev, &edesc->desc.ptr[5], DMA_FROM_DEVICE);
1629497f2e6bSLee Nipper 
1630*6a1e8d14SLEROY Christophe 	talitos_sg_unmap(dev, edesc, req_ctx->psrc, NULL, 0, 0);
1631032d197eSLEROY Christophe 
1632497f2e6bSLee Nipper 	/* When using hashctx-in, must unmap it. */
1633922f9dc8SLEROY Christophe 	if (from_talitos_ptr_len(&edesc->desc.ptr[1], is_sec1))
1634497f2e6bSLee Nipper 		unmap_single_talitos_ptr(dev, &edesc->desc.ptr[1],
1635497f2e6bSLee Nipper 					 DMA_TO_DEVICE);
1636497f2e6bSLee Nipper 
1637922f9dc8SLEROY Christophe 	if (from_talitos_ptr_len(&edesc->desc.ptr[2], is_sec1))
1638497f2e6bSLee Nipper 		unmap_single_talitos_ptr(dev, &edesc->desc.ptr[2],
1639497f2e6bSLee Nipper 					 DMA_TO_DEVICE);
1640497f2e6bSLee Nipper 
1641497f2e6bSLee Nipper 	if (edesc->dma_len)
1642497f2e6bSLee Nipper 		dma_unmap_single(dev, edesc->dma_link_tbl, edesc->dma_len,
1643497f2e6bSLee Nipper 				 DMA_BIDIRECTIONAL);
1644497f2e6bSLee Nipper 
1645497f2e6bSLee Nipper }
1646497f2e6bSLee Nipper 
1647497f2e6bSLee Nipper static void ahash_done(struct device *dev,
1648497f2e6bSLee Nipper 		       struct talitos_desc *desc, void *context,
1649497f2e6bSLee Nipper 		       int err)
1650497f2e6bSLee Nipper {
1651497f2e6bSLee Nipper 	struct ahash_request *areq = context;
1652497f2e6bSLee Nipper 	struct talitos_edesc *edesc =
1653497f2e6bSLee Nipper 		 container_of(desc, struct talitos_edesc, desc);
1654497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
1655497f2e6bSLee Nipper 
1656497f2e6bSLee Nipper 	if (!req_ctx->last && req_ctx->to_hash_later) {
1657497f2e6bSLee Nipper 		/* Position any partial block for next update/final/finup */
1658497f2e6bSLee Nipper 		memcpy(req_ctx->buf, req_ctx->bufnext, req_ctx->to_hash_later);
16595e833bc4SLee Nipper 		req_ctx->nbuf = req_ctx->to_hash_later;
1660497f2e6bSLee Nipper 	}
1661497f2e6bSLee Nipper 	common_nonsnoop_hash_unmap(dev, edesc, areq);
1662497f2e6bSLee Nipper 
1663497f2e6bSLee Nipper 	kfree(edesc);
1664497f2e6bSLee Nipper 
1665497f2e6bSLee Nipper 	areq->base.complete(&areq->base, err);
1666497f2e6bSLee Nipper }
1667497f2e6bSLee Nipper 
16682d02905eSLEROY Christophe /*
16692d02905eSLEROY Christophe  * SEC1 doesn't like hashing of 0 sized message, so we do the padding
16702d02905eSLEROY Christophe  * ourself and submit a padded block
16712d02905eSLEROY Christophe  */
16722d02905eSLEROY Christophe void talitos_handle_buggy_hash(struct talitos_ctx *ctx,
16732d02905eSLEROY Christophe 			       struct talitos_edesc *edesc,
16742d02905eSLEROY Christophe 			       struct talitos_ptr *ptr)
16752d02905eSLEROY Christophe {
16762d02905eSLEROY Christophe 	static u8 padded_hash[64] = {
16772d02905eSLEROY Christophe 		0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
16782d02905eSLEROY Christophe 		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
16792d02905eSLEROY Christophe 		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
16802d02905eSLEROY Christophe 		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
16812d02905eSLEROY Christophe 	};
16822d02905eSLEROY Christophe 
16832d02905eSLEROY Christophe 	pr_err_once("Bug in SEC1, padding ourself\n");
16842d02905eSLEROY Christophe 	edesc->desc.hdr &= ~DESC_HDR_MODE0_MDEU_PAD;
16852d02905eSLEROY Christophe 	map_single_talitos_ptr(ctx->dev, ptr, sizeof(padded_hash),
16862d02905eSLEROY Christophe 			       (char *)padded_hash, DMA_TO_DEVICE);
16872d02905eSLEROY Christophe }
16882d02905eSLEROY Christophe 
1689497f2e6bSLee Nipper static int common_nonsnoop_hash(struct talitos_edesc *edesc,
1690497f2e6bSLee Nipper 				struct ahash_request *areq, unsigned int length,
1691497f2e6bSLee Nipper 				void (*callback) (struct device *dev,
1692497f2e6bSLee Nipper 						  struct talitos_desc *desc,
1693497f2e6bSLee Nipper 						  void *context, int error))
1694497f2e6bSLee Nipper {
1695497f2e6bSLee Nipper 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
1696497f2e6bSLee Nipper 	struct talitos_ctx *ctx = crypto_ahash_ctx(tfm);
1697497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
1698497f2e6bSLee Nipper 	struct device *dev = ctx->dev;
1699497f2e6bSLee Nipper 	struct talitos_desc *desc = &edesc->desc;
1700032d197eSLEROY Christophe 	int ret;
1701*6a1e8d14SLEROY Christophe 	bool sync_needed = false;
1702922f9dc8SLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
1703922f9dc8SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
1704*6a1e8d14SLEROY Christophe 	int sg_count;
1705497f2e6bSLee Nipper 
1706497f2e6bSLee Nipper 	/* first DWORD empty */
1707497f2e6bSLee Nipper 	desc->ptr[0] = zero_entry;
1708497f2e6bSLee Nipper 
170960f208d7SKim Phillips 	/* hash context in */
171060f208d7SKim Phillips 	if (!req_ctx->first || req_ctx->swinit) {
1711497f2e6bSLee Nipper 		map_single_talitos_ptr(dev, &desc->ptr[1],
1712497f2e6bSLee Nipper 				       req_ctx->hw_context_size,
1713a2b35aa8SLEROY Christophe 				       (char *)req_ctx->hw_context,
1714497f2e6bSLee Nipper 				       DMA_TO_DEVICE);
171560f208d7SKim Phillips 		req_ctx->swinit = 0;
1716497f2e6bSLee Nipper 	} else {
1717497f2e6bSLee Nipper 		desc->ptr[1] = zero_entry;
1718497f2e6bSLee Nipper 		/* Indicate next op is not the first. */
1719497f2e6bSLee Nipper 		req_ctx->first = 0;
1720497f2e6bSLee Nipper 	}
1721497f2e6bSLee Nipper 
1722497f2e6bSLee Nipper 	/* HMAC key */
1723497f2e6bSLee Nipper 	if (ctx->keylen)
1724497f2e6bSLee Nipper 		map_single_talitos_ptr(dev, &desc->ptr[2], ctx->keylen,
1725a2b35aa8SLEROY Christophe 				       (char *)&ctx->key, DMA_TO_DEVICE);
1726497f2e6bSLee Nipper 	else
1727497f2e6bSLee Nipper 		desc->ptr[2] = zero_entry;
1728497f2e6bSLee Nipper 
1729*6a1e8d14SLEROY Christophe 	sg_count = edesc->src_nents ?: 1;
1730*6a1e8d14SLEROY Christophe 	if (is_sec1 && sg_count > 1)
1731*6a1e8d14SLEROY Christophe 		sg_copy_to_buffer(areq->src, sg_count, edesc->buf, length);
1732*6a1e8d14SLEROY Christophe 	else
1733*6a1e8d14SLEROY Christophe 		sg_count = dma_map_sg(dev, req_ctx->psrc, sg_count,
1734*6a1e8d14SLEROY Christophe 				      DMA_TO_DEVICE);
1735497f2e6bSLee Nipper 	/*
1736497f2e6bSLee Nipper 	 * data in
1737497f2e6bSLee Nipper 	 */
1738*6a1e8d14SLEROY Christophe 	sg_count = talitos_sg_map(dev, req_ctx->psrc, length, edesc,
1739*6a1e8d14SLEROY Christophe 				  &desc->ptr[3], sg_count, 0, 0);
1740*6a1e8d14SLEROY Christophe 	if (sg_count > 1)
1741*6a1e8d14SLEROY Christophe 		sync_needed = true;
1742497f2e6bSLee Nipper 
1743497f2e6bSLee Nipper 	/* fifth DWORD empty */
1744497f2e6bSLee Nipper 	desc->ptr[4] = zero_entry;
1745497f2e6bSLee Nipper 
1746497f2e6bSLee Nipper 	/* hash/HMAC out -or- hash context out */
1747497f2e6bSLee Nipper 	if (req_ctx->last)
1748497f2e6bSLee Nipper 		map_single_talitos_ptr(dev, &desc->ptr[5],
1749497f2e6bSLee Nipper 				       crypto_ahash_digestsize(tfm),
1750a2b35aa8SLEROY Christophe 				       areq->result, DMA_FROM_DEVICE);
1751497f2e6bSLee Nipper 	else
1752497f2e6bSLee Nipper 		map_single_talitos_ptr(dev, &desc->ptr[5],
1753497f2e6bSLee Nipper 				       req_ctx->hw_context_size,
1754a2b35aa8SLEROY Christophe 				       req_ctx->hw_context, DMA_FROM_DEVICE);
1755497f2e6bSLee Nipper 
1756497f2e6bSLee Nipper 	/* last DWORD empty */
1757497f2e6bSLee Nipper 	desc->ptr[6] = zero_entry;
1758497f2e6bSLee Nipper 
17592d02905eSLEROY Christophe 	if (is_sec1 && from_talitos_ptr_len(&desc->ptr[3], true) == 0)
17602d02905eSLEROY Christophe 		talitos_handle_buggy_hash(ctx, edesc, &desc->ptr[3]);
17612d02905eSLEROY Christophe 
1762*6a1e8d14SLEROY Christophe 	if (sync_needed)
1763*6a1e8d14SLEROY Christophe 		dma_sync_single_for_device(dev, edesc->dma_link_tbl,
1764*6a1e8d14SLEROY Christophe 					   edesc->dma_len, DMA_BIDIRECTIONAL);
1765*6a1e8d14SLEROY Christophe 
17665228f0f7SKim Phillips 	ret = talitos_submit(dev, ctx->ch, desc, callback, areq);
1767497f2e6bSLee Nipper 	if (ret != -EINPROGRESS) {
1768497f2e6bSLee Nipper 		common_nonsnoop_hash_unmap(dev, edesc, areq);
1769497f2e6bSLee Nipper 		kfree(edesc);
1770497f2e6bSLee Nipper 	}
1771497f2e6bSLee Nipper 	return ret;
1772497f2e6bSLee Nipper }
1773497f2e6bSLee Nipper 
1774497f2e6bSLee Nipper static struct talitos_edesc *ahash_edesc_alloc(struct ahash_request *areq,
1775497f2e6bSLee Nipper 					       unsigned int nbytes)
1776497f2e6bSLee Nipper {
1777497f2e6bSLee Nipper 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
1778497f2e6bSLee Nipper 	struct talitos_ctx *ctx = crypto_ahash_ctx(tfm);
1779497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
1780497f2e6bSLee Nipper 
1781aeb4c132SHerbert Xu 	return talitos_edesc_alloc(ctx->dev, req_ctx->psrc, NULL, NULL, 0,
178262293a37SHoria Geanta 				   nbytes, 0, 0, 0, areq->base.flags, false);
1783497f2e6bSLee Nipper }
1784497f2e6bSLee Nipper 
1785497f2e6bSLee Nipper static int ahash_init(struct ahash_request *areq)
1786497f2e6bSLee Nipper {
1787497f2e6bSLee Nipper 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
1788497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
1789497f2e6bSLee Nipper 
1790497f2e6bSLee Nipper 	/* Initialize the context */
17915e833bc4SLee Nipper 	req_ctx->nbuf = 0;
179260f208d7SKim Phillips 	req_ctx->first = 1; /* first indicates h/w must init its context */
179360f208d7SKim Phillips 	req_ctx->swinit = 0; /* assume h/w init of context */
1794497f2e6bSLee Nipper 	req_ctx->hw_context_size =
1795497f2e6bSLee Nipper 		(crypto_ahash_digestsize(tfm) <= SHA256_DIGEST_SIZE)
1796497f2e6bSLee Nipper 			? TALITOS_MDEU_CONTEXT_SIZE_MD5_SHA1_SHA256
1797497f2e6bSLee Nipper 			: TALITOS_MDEU_CONTEXT_SIZE_SHA384_SHA512;
1798497f2e6bSLee Nipper 
1799497f2e6bSLee Nipper 	return 0;
1800497f2e6bSLee Nipper }
1801497f2e6bSLee Nipper 
180260f208d7SKim Phillips /*
180360f208d7SKim Phillips  * on h/w without explicit sha224 support, we initialize h/w context
180460f208d7SKim Phillips  * manually with sha224 constants, and tell it to run sha256.
180560f208d7SKim Phillips  */
180660f208d7SKim Phillips static int ahash_init_sha224_swinit(struct ahash_request *areq)
180760f208d7SKim Phillips {
180860f208d7SKim Phillips 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
180960f208d7SKim Phillips 
181060f208d7SKim Phillips 	ahash_init(areq);
181160f208d7SKim Phillips 	req_ctx->swinit = 1;/* prevent h/w initting context with sha256 values*/
181260f208d7SKim Phillips 
1813a752447aSKim Phillips 	req_ctx->hw_context[0] = SHA224_H0;
1814a752447aSKim Phillips 	req_ctx->hw_context[1] = SHA224_H1;
1815a752447aSKim Phillips 	req_ctx->hw_context[2] = SHA224_H2;
1816a752447aSKim Phillips 	req_ctx->hw_context[3] = SHA224_H3;
1817a752447aSKim Phillips 	req_ctx->hw_context[4] = SHA224_H4;
1818a752447aSKim Phillips 	req_ctx->hw_context[5] = SHA224_H5;
1819a752447aSKim Phillips 	req_ctx->hw_context[6] = SHA224_H6;
1820a752447aSKim Phillips 	req_ctx->hw_context[7] = SHA224_H7;
182160f208d7SKim Phillips 
182260f208d7SKim Phillips 	/* init 64-bit count */
182360f208d7SKim Phillips 	req_ctx->hw_context[8] = 0;
182460f208d7SKim Phillips 	req_ctx->hw_context[9] = 0;
182560f208d7SKim Phillips 
182660f208d7SKim Phillips 	return 0;
182760f208d7SKim Phillips }
182860f208d7SKim Phillips 
1829497f2e6bSLee Nipper static int ahash_process_req(struct ahash_request *areq, unsigned int nbytes)
1830497f2e6bSLee Nipper {
1831497f2e6bSLee Nipper 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
1832497f2e6bSLee Nipper 	struct talitos_ctx *ctx = crypto_ahash_ctx(tfm);
1833497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
1834497f2e6bSLee Nipper 	struct talitos_edesc *edesc;
1835497f2e6bSLee Nipper 	unsigned int blocksize =
1836497f2e6bSLee Nipper 			crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm));
1837497f2e6bSLee Nipper 	unsigned int nbytes_to_hash;
1838497f2e6bSLee Nipper 	unsigned int to_hash_later;
18395e833bc4SLee Nipper 	unsigned int nsg;
18408e409fe1SLABBE Corentin 	int nents;
1841497f2e6bSLee Nipper 
18425e833bc4SLee Nipper 	if (!req_ctx->last && (nbytes + req_ctx->nbuf <= blocksize)) {
18435e833bc4SLee Nipper 		/* Buffer up to one whole block */
18448e409fe1SLABBE Corentin 		nents = sg_nents_for_len(areq->src, nbytes);
18458e409fe1SLABBE Corentin 		if (nents < 0) {
18468e409fe1SLABBE Corentin 			dev_err(ctx->dev, "Invalid number of src SG.\n");
18478e409fe1SLABBE Corentin 			return nents;
18488e409fe1SLABBE Corentin 		}
18498e409fe1SLABBE Corentin 		sg_copy_to_buffer(areq->src, nents,
18505e833bc4SLee Nipper 				  req_ctx->buf + req_ctx->nbuf, nbytes);
18515e833bc4SLee Nipper 		req_ctx->nbuf += nbytes;
1852497f2e6bSLee Nipper 		return 0;
1853497f2e6bSLee Nipper 	}
1854497f2e6bSLee Nipper 
18555e833bc4SLee Nipper 	/* At least (blocksize + 1) bytes are available to hash */
18565e833bc4SLee Nipper 	nbytes_to_hash = nbytes + req_ctx->nbuf;
18575e833bc4SLee Nipper 	to_hash_later = nbytes_to_hash & (blocksize - 1);
18585e833bc4SLee Nipper 
18595e833bc4SLee Nipper 	if (req_ctx->last)
18605e833bc4SLee Nipper 		to_hash_later = 0;
18615e833bc4SLee Nipper 	else if (to_hash_later)
18625e833bc4SLee Nipper 		/* There is a partial block. Hash the full block(s) now */
18635e833bc4SLee Nipper 		nbytes_to_hash -= to_hash_later;
18645e833bc4SLee Nipper 	else {
18655e833bc4SLee Nipper 		/* Keep one block buffered */
18665e833bc4SLee Nipper 		nbytes_to_hash -= blocksize;
18675e833bc4SLee Nipper 		to_hash_later = blocksize;
1868497f2e6bSLee Nipper 	}
18695e833bc4SLee Nipper 
18705e833bc4SLee Nipper 	/* Chain in any previously buffered data */
18715e833bc4SLee Nipper 	if (req_ctx->nbuf) {
18725e833bc4SLee Nipper 		nsg = (req_ctx->nbuf < nbytes_to_hash) ? 2 : 1;
18735e833bc4SLee Nipper 		sg_init_table(req_ctx->bufsl, nsg);
18745e833bc4SLee Nipper 		sg_set_buf(req_ctx->bufsl, req_ctx->buf, req_ctx->nbuf);
18755e833bc4SLee Nipper 		if (nsg > 1)
1876c56f6d12SDan Williams 			sg_chain(req_ctx->bufsl, 2, areq->src);
18775e833bc4SLee Nipper 		req_ctx->psrc = req_ctx->bufsl;
18785e833bc4SLee Nipper 	} else
18795e833bc4SLee Nipper 		req_ctx->psrc = areq->src;
18805e833bc4SLee Nipper 
1881497f2e6bSLee Nipper 	if (to_hash_later) {
18828e409fe1SLABBE Corentin 		nents = sg_nents_for_len(areq->src, nbytes);
18838e409fe1SLABBE Corentin 		if (nents < 0) {
18848e409fe1SLABBE Corentin 			dev_err(ctx->dev, "Invalid number of src SG.\n");
18858e409fe1SLABBE Corentin 			return nents;
18868e409fe1SLABBE Corentin 		}
1887d0525723SAkinobu Mita 		sg_pcopy_to_buffer(areq->src, nents,
1888497f2e6bSLee Nipper 				      req_ctx->bufnext,
1889497f2e6bSLee Nipper 				      to_hash_later,
1890497f2e6bSLee Nipper 				      nbytes - to_hash_later);
1891497f2e6bSLee Nipper 	}
1892497f2e6bSLee Nipper 	req_ctx->to_hash_later = to_hash_later;
1893497f2e6bSLee Nipper 
18945e833bc4SLee Nipper 	/* Allocate extended descriptor */
1895497f2e6bSLee Nipper 	edesc = ahash_edesc_alloc(areq, nbytes_to_hash);
1896497f2e6bSLee Nipper 	if (IS_ERR(edesc))
1897497f2e6bSLee Nipper 		return PTR_ERR(edesc);
1898497f2e6bSLee Nipper 
1899497f2e6bSLee Nipper 	edesc->desc.hdr = ctx->desc_hdr_template;
1900497f2e6bSLee Nipper 
1901497f2e6bSLee Nipper 	/* On last one, request SEC to pad; otherwise continue */
1902497f2e6bSLee Nipper 	if (req_ctx->last)
1903497f2e6bSLee Nipper 		edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_PAD;
1904497f2e6bSLee Nipper 	else
1905497f2e6bSLee Nipper 		edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_CONT;
1906497f2e6bSLee Nipper 
190760f208d7SKim Phillips 	/* request SEC to INIT hash. */
190860f208d7SKim Phillips 	if (req_ctx->first && !req_ctx->swinit)
1909497f2e6bSLee Nipper 		edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_INIT;
1910497f2e6bSLee Nipper 
1911497f2e6bSLee Nipper 	/* When the tfm context has a keylen, it's an HMAC.
1912497f2e6bSLee Nipper 	 * A first or last (ie. not middle) descriptor must request HMAC.
1913497f2e6bSLee Nipper 	 */
1914497f2e6bSLee Nipper 	if (ctx->keylen && (req_ctx->first || req_ctx->last))
1915497f2e6bSLee Nipper 		edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_HMAC;
1916497f2e6bSLee Nipper 
1917497f2e6bSLee Nipper 	return common_nonsnoop_hash(edesc, areq, nbytes_to_hash,
1918497f2e6bSLee Nipper 				    ahash_done);
1919497f2e6bSLee Nipper }
1920497f2e6bSLee Nipper 
1921497f2e6bSLee Nipper static int ahash_update(struct ahash_request *areq)
1922497f2e6bSLee Nipper {
1923497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
1924497f2e6bSLee Nipper 
1925497f2e6bSLee Nipper 	req_ctx->last = 0;
1926497f2e6bSLee Nipper 
1927497f2e6bSLee Nipper 	return ahash_process_req(areq, areq->nbytes);
1928497f2e6bSLee Nipper }
1929497f2e6bSLee Nipper 
1930497f2e6bSLee Nipper static int ahash_final(struct ahash_request *areq)
1931497f2e6bSLee Nipper {
1932497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
1933497f2e6bSLee Nipper 
1934497f2e6bSLee Nipper 	req_ctx->last = 1;
1935497f2e6bSLee Nipper 
1936497f2e6bSLee Nipper 	return ahash_process_req(areq, 0);
1937497f2e6bSLee Nipper }
1938497f2e6bSLee Nipper 
1939497f2e6bSLee Nipper static int ahash_finup(struct ahash_request *areq)
1940497f2e6bSLee Nipper {
1941497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
1942497f2e6bSLee Nipper 
1943497f2e6bSLee Nipper 	req_ctx->last = 1;
1944497f2e6bSLee Nipper 
1945497f2e6bSLee Nipper 	return ahash_process_req(areq, areq->nbytes);
1946497f2e6bSLee Nipper }
1947497f2e6bSLee Nipper 
1948497f2e6bSLee Nipper static int ahash_digest(struct ahash_request *areq)
1949497f2e6bSLee Nipper {
1950497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
195160f208d7SKim Phillips 	struct crypto_ahash *ahash = crypto_ahash_reqtfm(areq);
1952497f2e6bSLee Nipper 
195360f208d7SKim Phillips 	ahash->init(areq);
1954497f2e6bSLee Nipper 	req_ctx->last = 1;
1955497f2e6bSLee Nipper 
1956497f2e6bSLee Nipper 	return ahash_process_req(areq, areq->nbytes);
1957497f2e6bSLee Nipper }
1958497f2e6bSLee Nipper 
19593639ca84SHoria Geant? static int ahash_export(struct ahash_request *areq, void *out)
19603639ca84SHoria Geant? {
19613639ca84SHoria Geant? 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
19623639ca84SHoria Geant? 	struct talitos_export_state *export = out;
19633639ca84SHoria Geant? 
19643639ca84SHoria Geant? 	memcpy(export->hw_context, req_ctx->hw_context,
19653639ca84SHoria Geant? 	       req_ctx->hw_context_size);
19663639ca84SHoria Geant? 	memcpy(export->buf, req_ctx->buf, req_ctx->nbuf);
19673639ca84SHoria Geant? 	export->swinit = req_ctx->swinit;
19683639ca84SHoria Geant? 	export->first = req_ctx->first;
19693639ca84SHoria Geant? 	export->last = req_ctx->last;
19703639ca84SHoria Geant? 	export->to_hash_later = req_ctx->to_hash_later;
19713639ca84SHoria Geant? 	export->nbuf = req_ctx->nbuf;
19723639ca84SHoria Geant? 
19733639ca84SHoria Geant? 	return 0;
19743639ca84SHoria Geant? }
19753639ca84SHoria Geant? 
19763639ca84SHoria Geant? static int ahash_import(struct ahash_request *areq, const void *in)
19773639ca84SHoria Geant? {
19783639ca84SHoria Geant? 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
19793639ca84SHoria Geant? 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
19803639ca84SHoria Geant? 	const struct talitos_export_state *export = in;
19813639ca84SHoria Geant? 
19823639ca84SHoria Geant? 	memset(req_ctx, 0, sizeof(*req_ctx));
19833639ca84SHoria Geant? 	req_ctx->hw_context_size =
19843639ca84SHoria Geant? 		(crypto_ahash_digestsize(tfm) <= SHA256_DIGEST_SIZE)
19853639ca84SHoria Geant? 			? TALITOS_MDEU_CONTEXT_SIZE_MD5_SHA1_SHA256
19863639ca84SHoria Geant? 			: TALITOS_MDEU_CONTEXT_SIZE_SHA384_SHA512;
19873639ca84SHoria Geant? 	memcpy(req_ctx->hw_context, export->hw_context,
19883639ca84SHoria Geant? 	       req_ctx->hw_context_size);
19893639ca84SHoria Geant? 	memcpy(req_ctx->buf, export->buf, export->nbuf);
19903639ca84SHoria Geant? 	req_ctx->swinit = export->swinit;
19913639ca84SHoria Geant? 	req_ctx->first = export->first;
19923639ca84SHoria Geant? 	req_ctx->last = export->last;
19933639ca84SHoria Geant? 	req_ctx->to_hash_later = export->to_hash_later;
19943639ca84SHoria Geant? 	req_ctx->nbuf = export->nbuf;
19953639ca84SHoria Geant? 
19963639ca84SHoria Geant? 	return 0;
19973639ca84SHoria Geant? }
19983639ca84SHoria Geant? 
199979b3a418SLee Nipper struct keyhash_result {
200079b3a418SLee Nipper 	struct completion completion;
200179b3a418SLee Nipper 	int err;
200279b3a418SLee Nipper };
200379b3a418SLee Nipper 
200479b3a418SLee Nipper static void keyhash_complete(struct crypto_async_request *req, int err)
200579b3a418SLee Nipper {
200679b3a418SLee Nipper 	struct keyhash_result *res = req->data;
200779b3a418SLee Nipper 
200879b3a418SLee Nipper 	if (err == -EINPROGRESS)
200979b3a418SLee Nipper 		return;
201079b3a418SLee Nipper 
201179b3a418SLee Nipper 	res->err = err;
201279b3a418SLee Nipper 	complete(&res->completion);
201379b3a418SLee Nipper }
201479b3a418SLee Nipper 
201579b3a418SLee Nipper static int keyhash(struct crypto_ahash *tfm, const u8 *key, unsigned int keylen,
201679b3a418SLee Nipper 		   u8 *hash)
201779b3a418SLee Nipper {
201879b3a418SLee Nipper 	struct talitos_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm));
201979b3a418SLee Nipper 
202079b3a418SLee Nipper 	struct scatterlist sg[1];
202179b3a418SLee Nipper 	struct ahash_request *req;
202279b3a418SLee Nipper 	struct keyhash_result hresult;
202379b3a418SLee Nipper 	int ret;
202479b3a418SLee Nipper 
202579b3a418SLee Nipper 	init_completion(&hresult.completion);
202679b3a418SLee Nipper 
202779b3a418SLee Nipper 	req = ahash_request_alloc(tfm, GFP_KERNEL);
202879b3a418SLee Nipper 	if (!req)
202979b3a418SLee Nipper 		return -ENOMEM;
203079b3a418SLee Nipper 
203179b3a418SLee Nipper 	/* Keep tfm keylen == 0 during hash of the long key */
203279b3a418SLee Nipper 	ctx->keylen = 0;
203379b3a418SLee Nipper 	ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
203479b3a418SLee Nipper 				   keyhash_complete, &hresult);
203579b3a418SLee Nipper 
203679b3a418SLee Nipper 	sg_init_one(&sg[0], key, keylen);
203779b3a418SLee Nipper 
203879b3a418SLee Nipper 	ahash_request_set_crypt(req, sg, hash, keylen);
203979b3a418SLee Nipper 	ret = crypto_ahash_digest(req);
204079b3a418SLee Nipper 	switch (ret) {
204179b3a418SLee Nipper 	case 0:
204279b3a418SLee Nipper 		break;
204379b3a418SLee Nipper 	case -EINPROGRESS:
204479b3a418SLee Nipper 	case -EBUSY:
204579b3a418SLee Nipper 		ret = wait_for_completion_interruptible(
204679b3a418SLee Nipper 			&hresult.completion);
204779b3a418SLee Nipper 		if (!ret)
204879b3a418SLee Nipper 			ret = hresult.err;
204979b3a418SLee Nipper 		break;
205079b3a418SLee Nipper 	default:
205179b3a418SLee Nipper 		break;
205279b3a418SLee Nipper 	}
205379b3a418SLee Nipper 	ahash_request_free(req);
205479b3a418SLee Nipper 
205579b3a418SLee Nipper 	return ret;
205679b3a418SLee Nipper }
205779b3a418SLee Nipper 
205879b3a418SLee Nipper static int ahash_setkey(struct crypto_ahash *tfm, const u8 *key,
205979b3a418SLee Nipper 			unsigned int keylen)
206079b3a418SLee Nipper {
206179b3a418SLee Nipper 	struct talitos_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm));
206279b3a418SLee Nipper 	unsigned int blocksize =
206379b3a418SLee Nipper 			crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm));
206479b3a418SLee Nipper 	unsigned int digestsize = crypto_ahash_digestsize(tfm);
206579b3a418SLee Nipper 	unsigned int keysize = keylen;
206679b3a418SLee Nipper 	u8 hash[SHA512_DIGEST_SIZE];
206779b3a418SLee Nipper 	int ret;
206879b3a418SLee Nipper 
206979b3a418SLee Nipper 	if (keylen <= blocksize)
207079b3a418SLee Nipper 		memcpy(ctx->key, key, keysize);
207179b3a418SLee Nipper 	else {
207279b3a418SLee Nipper 		/* Must get the hash of the long key */
207379b3a418SLee Nipper 		ret = keyhash(tfm, key, keylen, hash);
207479b3a418SLee Nipper 
207579b3a418SLee Nipper 		if (ret) {
207679b3a418SLee Nipper 			crypto_ahash_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
207779b3a418SLee Nipper 			return -EINVAL;
207879b3a418SLee Nipper 		}
207979b3a418SLee Nipper 
208079b3a418SLee Nipper 		keysize = digestsize;
208179b3a418SLee Nipper 		memcpy(ctx->key, hash, digestsize);
208279b3a418SLee Nipper 	}
208379b3a418SLee Nipper 
208479b3a418SLee Nipper 	ctx->keylen = keysize;
208579b3a418SLee Nipper 
208679b3a418SLee Nipper 	return 0;
208779b3a418SLee Nipper }
208879b3a418SLee Nipper 
208979b3a418SLee Nipper 
20909c4a7965SKim Phillips struct talitos_alg_template {
2091d5e4aaefSLee Nipper 	u32 type;
2092d5e4aaefSLee Nipper 	union {
2093d5e4aaefSLee Nipper 		struct crypto_alg crypto;
2094acbf7c62SLee Nipper 		struct ahash_alg hash;
2095aeb4c132SHerbert Xu 		struct aead_alg aead;
2096d5e4aaefSLee Nipper 	} alg;
20979c4a7965SKim Phillips 	__be32 desc_hdr_template;
20989c4a7965SKim Phillips };
20999c4a7965SKim Phillips 
21009c4a7965SKim Phillips static struct talitos_alg_template driver_algs[] = {
2101991155baSHoria Geanta 	/* AEAD algorithms.  These use a single-pass ipsec_esp descriptor */
2102d5e4aaefSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2103aeb4c132SHerbert Xu 		.alg.aead = {
2104aeb4c132SHerbert Xu 			.base = {
210556af8cd4SLee Nipper 				.cra_name = "authenc(hmac(sha1),cbc(aes))",
2106aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha1-"
2107aeb4c132SHerbert Xu 						   "cbc-aes-talitos",
210856af8cd4SLee Nipper 				.cra_blocksize = AES_BLOCK_SIZE,
2109aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2110aeb4c132SHerbert Xu 			},
21113952f17eSLee Nipper 			.ivsize = AES_BLOCK_SIZE,
21123952f17eSLee Nipper 			.maxauthsize = SHA1_DIGEST_SIZE,
21139c4a7965SKim Phillips 		},
21149c4a7965SKim Phillips 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
21159c4a7965SKim Phillips 			             DESC_HDR_SEL0_AESU |
21169c4a7965SKim Phillips 		                     DESC_HDR_MODE0_AESU_CBC |
21179c4a7965SKim Phillips 		                     DESC_HDR_SEL1_MDEUA |
21189c4a7965SKim Phillips 		                     DESC_HDR_MODE1_MDEU_INIT |
21199c4a7965SKim Phillips 		                     DESC_HDR_MODE1_MDEU_PAD |
21209c4a7965SKim Phillips 		                     DESC_HDR_MODE1_MDEU_SHA1_HMAC,
212170bcaca7SLee Nipper 	},
2122d5e4aaefSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2123aeb4c132SHerbert Xu 		.alg.aead = {
2124aeb4c132SHerbert Xu 			.base = {
2125aeb4c132SHerbert Xu 				.cra_name = "authenc(hmac(sha1),"
2126aeb4c132SHerbert Xu 					    "cbc(des3_ede))",
2127aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha1-"
2128aeb4c132SHerbert Xu 						   "cbc-3des-talitos",
212956af8cd4SLee Nipper 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
2130aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2131aeb4c132SHerbert Xu 			},
21323952f17eSLee Nipper 			.ivsize = DES3_EDE_BLOCK_SIZE,
21333952f17eSLee Nipper 			.maxauthsize = SHA1_DIGEST_SIZE,
213470bcaca7SLee Nipper 		},
213570bcaca7SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
213670bcaca7SLee Nipper 			             DESC_HDR_SEL0_DEU |
213770bcaca7SLee Nipper 		                     DESC_HDR_MODE0_DEU_CBC |
213870bcaca7SLee Nipper 		                     DESC_HDR_MODE0_DEU_3DES |
213970bcaca7SLee Nipper 		                     DESC_HDR_SEL1_MDEUA |
214070bcaca7SLee Nipper 		                     DESC_HDR_MODE1_MDEU_INIT |
214170bcaca7SLee Nipper 		                     DESC_HDR_MODE1_MDEU_PAD |
214270bcaca7SLee Nipper 		                     DESC_HDR_MODE1_MDEU_SHA1_HMAC,
21433952f17eSLee Nipper 	},
2144d5e4aaefSLee Nipper 	{       .type = CRYPTO_ALG_TYPE_AEAD,
2145aeb4c132SHerbert Xu 		.alg.aead = {
2146aeb4c132SHerbert Xu 			.base = {
2147357fb605SHoria Geanta 				.cra_name = "authenc(hmac(sha224),cbc(aes))",
2148aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha224-"
2149aeb4c132SHerbert Xu 						   "cbc-aes-talitos",
2150357fb605SHoria Geanta 				.cra_blocksize = AES_BLOCK_SIZE,
2151aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2152aeb4c132SHerbert Xu 			},
2153357fb605SHoria Geanta 			.ivsize = AES_BLOCK_SIZE,
2154357fb605SHoria Geanta 			.maxauthsize = SHA224_DIGEST_SIZE,
2155357fb605SHoria Geanta 		},
2156357fb605SHoria Geanta 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
2157357fb605SHoria Geanta 				     DESC_HDR_SEL0_AESU |
2158357fb605SHoria Geanta 				     DESC_HDR_MODE0_AESU_CBC |
2159357fb605SHoria Geanta 				     DESC_HDR_SEL1_MDEUA |
2160357fb605SHoria Geanta 				     DESC_HDR_MODE1_MDEU_INIT |
2161357fb605SHoria Geanta 				     DESC_HDR_MODE1_MDEU_PAD |
2162357fb605SHoria Geanta 				     DESC_HDR_MODE1_MDEU_SHA224_HMAC,
2163357fb605SHoria Geanta 	},
2164357fb605SHoria Geanta 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2165aeb4c132SHerbert Xu 		.alg.aead = {
2166aeb4c132SHerbert Xu 			.base = {
2167aeb4c132SHerbert Xu 				.cra_name = "authenc(hmac(sha224),"
2168aeb4c132SHerbert Xu 					    "cbc(des3_ede))",
2169aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha224-"
2170aeb4c132SHerbert Xu 						   "cbc-3des-talitos",
2171357fb605SHoria Geanta 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
2172aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2173aeb4c132SHerbert Xu 			},
2174357fb605SHoria Geanta 			.ivsize = DES3_EDE_BLOCK_SIZE,
2175357fb605SHoria Geanta 			.maxauthsize = SHA224_DIGEST_SIZE,
2176357fb605SHoria Geanta 		},
2177357fb605SHoria Geanta 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
2178357fb605SHoria Geanta 			             DESC_HDR_SEL0_DEU |
2179357fb605SHoria Geanta 		                     DESC_HDR_MODE0_DEU_CBC |
2180357fb605SHoria Geanta 		                     DESC_HDR_MODE0_DEU_3DES |
2181357fb605SHoria Geanta 		                     DESC_HDR_SEL1_MDEUA |
2182357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_INIT |
2183357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_PAD |
2184357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_SHA224_HMAC,
2185357fb605SHoria Geanta 	},
2186357fb605SHoria Geanta 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2187aeb4c132SHerbert Xu 		.alg.aead = {
2188aeb4c132SHerbert Xu 			.base = {
218956af8cd4SLee Nipper 				.cra_name = "authenc(hmac(sha256),cbc(aes))",
2190aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha256-"
2191aeb4c132SHerbert Xu 						   "cbc-aes-talitos",
219256af8cd4SLee Nipper 				.cra_blocksize = AES_BLOCK_SIZE,
2193aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2194aeb4c132SHerbert Xu 			},
21953952f17eSLee Nipper 			.ivsize = AES_BLOCK_SIZE,
21963952f17eSLee Nipper 			.maxauthsize = SHA256_DIGEST_SIZE,
21973952f17eSLee Nipper 		},
21983952f17eSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
21993952f17eSLee Nipper 			             DESC_HDR_SEL0_AESU |
22003952f17eSLee Nipper 		                     DESC_HDR_MODE0_AESU_CBC |
22013952f17eSLee Nipper 		                     DESC_HDR_SEL1_MDEUA |
22023952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_INIT |
22033952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_PAD |
22043952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_SHA256_HMAC,
22053952f17eSLee Nipper 	},
2206d5e4aaefSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2207aeb4c132SHerbert Xu 		.alg.aead = {
2208aeb4c132SHerbert Xu 			.base = {
2209aeb4c132SHerbert Xu 				.cra_name = "authenc(hmac(sha256),"
2210aeb4c132SHerbert Xu 					    "cbc(des3_ede))",
2211aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha256-"
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 = SHA256_DIGEST_SIZE,
22183952f17eSLee Nipper 		},
22193952f17eSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
22203952f17eSLee Nipper 			             DESC_HDR_SEL0_DEU |
22213952f17eSLee Nipper 		                     DESC_HDR_MODE0_DEU_CBC |
22223952f17eSLee Nipper 		                     DESC_HDR_MODE0_DEU_3DES |
22233952f17eSLee Nipper 		                     DESC_HDR_SEL1_MDEUA |
22243952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_INIT |
22253952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_PAD |
22263952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_SHA256_HMAC,
22273952f17eSLee Nipper 	},
2228d5e4aaefSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2229aeb4c132SHerbert Xu 		.alg.aead = {
2230aeb4c132SHerbert Xu 			.base = {
2231357fb605SHoria Geanta 				.cra_name = "authenc(hmac(sha384),cbc(aes))",
2232aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha384-"
2233aeb4c132SHerbert Xu 						   "cbc-aes-talitos",
2234357fb605SHoria Geanta 				.cra_blocksize = AES_BLOCK_SIZE,
2235aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2236aeb4c132SHerbert Xu 			},
2237357fb605SHoria Geanta 			.ivsize = AES_BLOCK_SIZE,
2238357fb605SHoria Geanta 			.maxauthsize = SHA384_DIGEST_SIZE,
2239357fb605SHoria Geanta 		},
2240357fb605SHoria Geanta 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
2241357fb605SHoria Geanta 			             DESC_HDR_SEL0_AESU |
2242357fb605SHoria Geanta 		                     DESC_HDR_MODE0_AESU_CBC |
2243357fb605SHoria Geanta 		                     DESC_HDR_SEL1_MDEUB |
2244357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_INIT |
2245357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_PAD |
2246357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEUB_SHA384_HMAC,
2247357fb605SHoria Geanta 	},
2248357fb605SHoria Geanta 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2249aeb4c132SHerbert Xu 		.alg.aead = {
2250aeb4c132SHerbert Xu 			.base = {
2251aeb4c132SHerbert Xu 				.cra_name = "authenc(hmac(sha384),"
2252aeb4c132SHerbert Xu 					    "cbc(des3_ede))",
2253aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha384-"
2254aeb4c132SHerbert Xu 						   "cbc-3des-talitos",
2255357fb605SHoria Geanta 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
2256aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2257aeb4c132SHerbert Xu 			},
2258357fb605SHoria Geanta 			.ivsize = DES3_EDE_BLOCK_SIZE,
2259357fb605SHoria Geanta 			.maxauthsize = SHA384_DIGEST_SIZE,
2260357fb605SHoria Geanta 		},
2261357fb605SHoria Geanta 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
2262357fb605SHoria Geanta 			             DESC_HDR_SEL0_DEU |
2263357fb605SHoria Geanta 		                     DESC_HDR_MODE0_DEU_CBC |
2264357fb605SHoria Geanta 		                     DESC_HDR_MODE0_DEU_3DES |
2265357fb605SHoria Geanta 		                     DESC_HDR_SEL1_MDEUB |
2266357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_INIT |
2267357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_PAD |
2268357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEUB_SHA384_HMAC,
2269357fb605SHoria Geanta 	},
2270357fb605SHoria Geanta 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2271aeb4c132SHerbert Xu 		.alg.aead = {
2272aeb4c132SHerbert Xu 			.base = {
2273357fb605SHoria Geanta 				.cra_name = "authenc(hmac(sha512),cbc(aes))",
2274aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha512-"
2275aeb4c132SHerbert Xu 						   "cbc-aes-talitos",
2276357fb605SHoria Geanta 				.cra_blocksize = AES_BLOCK_SIZE,
2277aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2278aeb4c132SHerbert Xu 			},
2279357fb605SHoria Geanta 			.ivsize = AES_BLOCK_SIZE,
2280357fb605SHoria Geanta 			.maxauthsize = SHA512_DIGEST_SIZE,
2281357fb605SHoria Geanta 		},
2282357fb605SHoria Geanta 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
2283357fb605SHoria Geanta 			             DESC_HDR_SEL0_AESU |
2284357fb605SHoria Geanta 		                     DESC_HDR_MODE0_AESU_CBC |
2285357fb605SHoria Geanta 		                     DESC_HDR_SEL1_MDEUB |
2286357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_INIT |
2287357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_PAD |
2288357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEUB_SHA512_HMAC,
2289357fb605SHoria Geanta 	},
2290357fb605SHoria Geanta 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2291aeb4c132SHerbert Xu 		.alg.aead = {
2292aeb4c132SHerbert Xu 			.base = {
2293aeb4c132SHerbert Xu 				.cra_name = "authenc(hmac(sha512),"
2294aeb4c132SHerbert Xu 					    "cbc(des3_ede))",
2295aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha512-"
2296aeb4c132SHerbert Xu 						   "cbc-3des-talitos",
2297357fb605SHoria Geanta 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
2298aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2299aeb4c132SHerbert Xu 			},
2300357fb605SHoria Geanta 			.ivsize = DES3_EDE_BLOCK_SIZE,
2301357fb605SHoria Geanta 			.maxauthsize = SHA512_DIGEST_SIZE,
2302357fb605SHoria Geanta 		},
2303357fb605SHoria Geanta 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
2304357fb605SHoria Geanta 			             DESC_HDR_SEL0_DEU |
2305357fb605SHoria Geanta 		                     DESC_HDR_MODE0_DEU_CBC |
2306357fb605SHoria Geanta 		                     DESC_HDR_MODE0_DEU_3DES |
2307357fb605SHoria Geanta 		                     DESC_HDR_SEL1_MDEUB |
2308357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_INIT |
2309357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_PAD |
2310357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEUB_SHA512_HMAC,
2311357fb605SHoria Geanta 	},
2312357fb605SHoria Geanta 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2313aeb4c132SHerbert Xu 		.alg.aead = {
2314aeb4c132SHerbert Xu 			.base = {
231556af8cd4SLee Nipper 				.cra_name = "authenc(hmac(md5),cbc(aes))",
2316aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-md5-"
2317aeb4c132SHerbert Xu 						   "cbc-aes-talitos",
231856af8cd4SLee Nipper 				.cra_blocksize = AES_BLOCK_SIZE,
2319aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2320aeb4c132SHerbert Xu 			},
23213952f17eSLee Nipper 			.ivsize = AES_BLOCK_SIZE,
23223952f17eSLee Nipper 			.maxauthsize = MD5_DIGEST_SIZE,
23233952f17eSLee Nipper 		},
23243952f17eSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
23253952f17eSLee Nipper 			             DESC_HDR_SEL0_AESU |
23263952f17eSLee Nipper 		                     DESC_HDR_MODE0_AESU_CBC |
23273952f17eSLee Nipper 		                     DESC_HDR_SEL1_MDEUA |
23283952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_INIT |
23293952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_PAD |
23303952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_MD5_HMAC,
23313952f17eSLee Nipper 	},
2332d5e4aaefSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2333aeb4c132SHerbert Xu 		.alg.aead = {
2334aeb4c132SHerbert Xu 			.base = {
233556af8cd4SLee Nipper 				.cra_name = "authenc(hmac(md5),cbc(des3_ede))",
2336aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-md5-"
2337aeb4c132SHerbert Xu 						   "cbc-3des-talitos",
233856af8cd4SLee Nipper 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
2339aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2340aeb4c132SHerbert Xu 			},
23413952f17eSLee Nipper 			.ivsize = DES3_EDE_BLOCK_SIZE,
23423952f17eSLee Nipper 			.maxauthsize = MD5_DIGEST_SIZE,
23433952f17eSLee Nipper 		},
23443952f17eSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
23453952f17eSLee Nipper 			             DESC_HDR_SEL0_DEU |
23463952f17eSLee Nipper 		                     DESC_HDR_MODE0_DEU_CBC |
23473952f17eSLee Nipper 		                     DESC_HDR_MODE0_DEU_3DES |
23483952f17eSLee Nipper 		                     DESC_HDR_SEL1_MDEUA |
23493952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_INIT |
23503952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_PAD |
23513952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_MD5_HMAC,
23524de9d0b5SLee Nipper 	},
23534de9d0b5SLee Nipper 	/* ABLKCIPHER algorithms. */
2354d5e4aaefSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_ABLKCIPHER,
2355d5e4aaefSLee Nipper 		.alg.crypto = {
23565e75ae1bSLEROY Christophe 			.cra_name = "ecb(aes)",
23575e75ae1bSLEROY Christophe 			.cra_driver_name = "ecb-aes-talitos",
23585e75ae1bSLEROY Christophe 			.cra_blocksize = AES_BLOCK_SIZE,
23595e75ae1bSLEROY Christophe 			.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
23605e75ae1bSLEROY Christophe 				     CRYPTO_ALG_ASYNC,
23615e75ae1bSLEROY Christophe 			.cra_ablkcipher = {
23625e75ae1bSLEROY Christophe 				.min_keysize = AES_MIN_KEY_SIZE,
23635e75ae1bSLEROY Christophe 				.max_keysize = AES_MAX_KEY_SIZE,
23645e75ae1bSLEROY Christophe 				.ivsize = AES_BLOCK_SIZE,
23655e75ae1bSLEROY Christophe 			}
23665e75ae1bSLEROY Christophe 		},
23675e75ae1bSLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
23685e75ae1bSLEROY Christophe 				     DESC_HDR_SEL0_AESU,
23695e75ae1bSLEROY Christophe 	},
23705e75ae1bSLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_ABLKCIPHER,
23715e75ae1bSLEROY Christophe 		.alg.crypto = {
23724de9d0b5SLee Nipper 			.cra_name = "cbc(aes)",
23734de9d0b5SLee Nipper 			.cra_driver_name = "cbc-aes-talitos",
23744de9d0b5SLee Nipper 			.cra_blocksize = AES_BLOCK_SIZE,
23754de9d0b5SLee Nipper 			.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
23764de9d0b5SLee Nipper                                      CRYPTO_ALG_ASYNC,
23774de9d0b5SLee Nipper 			.cra_ablkcipher = {
23784de9d0b5SLee Nipper 				.min_keysize = AES_MIN_KEY_SIZE,
23794de9d0b5SLee Nipper 				.max_keysize = AES_MAX_KEY_SIZE,
23804de9d0b5SLee Nipper 				.ivsize = AES_BLOCK_SIZE,
23814de9d0b5SLee Nipper 			}
23824de9d0b5SLee Nipper 		},
23834de9d0b5SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
23844de9d0b5SLee Nipper 				     DESC_HDR_SEL0_AESU |
23854de9d0b5SLee Nipper 				     DESC_HDR_MODE0_AESU_CBC,
23864de9d0b5SLee Nipper 	},
2387d5e4aaefSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_ABLKCIPHER,
2388d5e4aaefSLee Nipper 		.alg.crypto = {
23895e75ae1bSLEROY Christophe 			.cra_name = "ctr(aes)",
23905e75ae1bSLEROY Christophe 			.cra_driver_name = "ctr-aes-talitos",
23915e75ae1bSLEROY Christophe 			.cra_blocksize = AES_BLOCK_SIZE,
23925e75ae1bSLEROY Christophe 			.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
23935e75ae1bSLEROY Christophe 				     CRYPTO_ALG_ASYNC,
23945e75ae1bSLEROY Christophe 			.cra_ablkcipher = {
23955e75ae1bSLEROY Christophe 				.min_keysize = AES_MIN_KEY_SIZE,
23965e75ae1bSLEROY Christophe 				.max_keysize = AES_MAX_KEY_SIZE,
23975e75ae1bSLEROY Christophe 				.ivsize = AES_BLOCK_SIZE,
23985e75ae1bSLEROY Christophe 			}
23995e75ae1bSLEROY Christophe 		},
24005e75ae1bSLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
24015e75ae1bSLEROY Christophe 				     DESC_HDR_SEL0_AESU |
24025e75ae1bSLEROY Christophe 				     DESC_HDR_MODE0_AESU_CTR,
24035e75ae1bSLEROY Christophe 	},
24045e75ae1bSLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_ABLKCIPHER,
24055e75ae1bSLEROY Christophe 		.alg.crypto = {
24065e75ae1bSLEROY Christophe 			.cra_name = "ecb(des)",
24075e75ae1bSLEROY Christophe 			.cra_driver_name = "ecb-des-talitos",
24085e75ae1bSLEROY Christophe 			.cra_blocksize = DES_BLOCK_SIZE,
24095e75ae1bSLEROY Christophe 			.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
24105e75ae1bSLEROY Christophe 				     CRYPTO_ALG_ASYNC,
24115e75ae1bSLEROY Christophe 			.cra_ablkcipher = {
24125e75ae1bSLEROY Christophe 				.min_keysize = DES_KEY_SIZE,
24135e75ae1bSLEROY Christophe 				.max_keysize = DES_KEY_SIZE,
24145e75ae1bSLEROY Christophe 				.ivsize = DES_BLOCK_SIZE,
24155e75ae1bSLEROY Christophe 			}
24165e75ae1bSLEROY Christophe 		},
24175e75ae1bSLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
24185e75ae1bSLEROY Christophe 				     DESC_HDR_SEL0_DEU,
24195e75ae1bSLEROY Christophe 	},
24205e75ae1bSLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_ABLKCIPHER,
24215e75ae1bSLEROY Christophe 		.alg.crypto = {
24225e75ae1bSLEROY Christophe 			.cra_name = "cbc(des)",
24235e75ae1bSLEROY Christophe 			.cra_driver_name = "cbc-des-talitos",
24245e75ae1bSLEROY Christophe 			.cra_blocksize = DES_BLOCK_SIZE,
24255e75ae1bSLEROY Christophe 			.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
24265e75ae1bSLEROY Christophe 				     CRYPTO_ALG_ASYNC,
24275e75ae1bSLEROY Christophe 			.cra_ablkcipher = {
24285e75ae1bSLEROY Christophe 				.min_keysize = DES_KEY_SIZE,
24295e75ae1bSLEROY Christophe 				.max_keysize = DES_KEY_SIZE,
24305e75ae1bSLEROY Christophe 				.ivsize = DES_BLOCK_SIZE,
24315e75ae1bSLEROY Christophe 			}
24325e75ae1bSLEROY Christophe 		},
24335e75ae1bSLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
24345e75ae1bSLEROY Christophe 				     DESC_HDR_SEL0_DEU |
24355e75ae1bSLEROY Christophe 				     DESC_HDR_MODE0_DEU_CBC,
24365e75ae1bSLEROY Christophe 	},
24375e75ae1bSLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_ABLKCIPHER,
24385e75ae1bSLEROY Christophe 		.alg.crypto = {
24395e75ae1bSLEROY Christophe 			.cra_name = "ecb(des3_ede)",
24405e75ae1bSLEROY Christophe 			.cra_driver_name = "ecb-3des-talitos",
24415e75ae1bSLEROY Christophe 			.cra_blocksize = DES3_EDE_BLOCK_SIZE,
24425e75ae1bSLEROY Christophe 			.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
24435e75ae1bSLEROY Christophe 				     CRYPTO_ALG_ASYNC,
24445e75ae1bSLEROY Christophe 			.cra_ablkcipher = {
24455e75ae1bSLEROY Christophe 				.min_keysize = DES3_EDE_KEY_SIZE,
24465e75ae1bSLEROY Christophe 				.max_keysize = DES3_EDE_KEY_SIZE,
24475e75ae1bSLEROY Christophe 				.ivsize = DES3_EDE_BLOCK_SIZE,
24485e75ae1bSLEROY Christophe 			}
24495e75ae1bSLEROY Christophe 		},
24505e75ae1bSLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
24515e75ae1bSLEROY Christophe 				     DESC_HDR_SEL0_DEU |
24525e75ae1bSLEROY Christophe 				     DESC_HDR_MODE0_DEU_3DES,
24535e75ae1bSLEROY Christophe 	},
24545e75ae1bSLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_ABLKCIPHER,
24555e75ae1bSLEROY Christophe 		.alg.crypto = {
24564de9d0b5SLee Nipper 			.cra_name = "cbc(des3_ede)",
24574de9d0b5SLee Nipper 			.cra_driver_name = "cbc-3des-talitos",
24584de9d0b5SLee Nipper 			.cra_blocksize = DES3_EDE_BLOCK_SIZE,
24594de9d0b5SLee Nipper 			.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
24604de9d0b5SLee Nipper                                      CRYPTO_ALG_ASYNC,
24614de9d0b5SLee Nipper 			.cra_ablkcipher = {
24624de9d0b5SLee Nipper 				.min_keysize = DES3_EDE_KEY_SIZE,
24634de9d0b5SLee Nipper 				.max_keysize = DES3_EDE_KEY_SIZE,
24644de9d0b5SLee Nipper 				.ivsize = DES3_EDE_BLOCK_SIZE,
24654de9d0b5SLee Nipper 			}
24664de9d0b5SLee Nipper 		},
24674de9d0b5SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
24684de9d0b5SLee Nipper 			             DESC_HDR_SEL0_DEU |
24694de9d0b5SLee Nipper 		                     DESC_HDR_MODE0_DEU_CBC |
24704de9d0b5SLee Nipper 		                     DESC_HDR_MODE0_DEU_3DES,
2471497f2e6bSLee Nipper 	},
2472497f2e6bSLee Nipper 	/* AHASH algorithms. */
2473497f2e6bSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
2474497f2e6bSLee Nipper 		.alg.hash = {
2475497f2e6bSLee Nipper 			.halg.digestsize = MD5_DIGEST_SIZE,
24763639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
2477497f2e6bSLee Nipper 			.halg.base = {
2478497f2e6bSLee Nipper 				.cra_name = "md5",
2479497f2e6bSLee Nipper 				.cra_driver_name = "md5-talitos",
2480b3988618SMartin Hicks 				.cra_blocksize = MD5_HMAC_BLOCK_SIZE,
2481497f2e6bSLee Nipper 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
2482497f2e6bSLee Nipper 					     CRYPTO_ALG_ASYNC,
24839c4a7965SKim Phillips 			}
2484497f2e6bSLee Nipper 		},
2485497f2e6bSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
2486497f2e6bSLee Nipper 				     DESC_HDR_SEL0_MDEUA |
2487497f2e6bSLee Nipper 				     DESC_HDR_MODE0_MDEU_MD5,
2488497f2e6bSLee Nipper 	},
2489497f2e6bSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
2490497f2e6bSLee Nipper 		.alg.hash = {
2491497f2e6bSLee Nipper 			.halg.digestsize = SHA1_DIGEST_SIZE,
24923639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
2493497f2e6bSLee Nipper 			.halg.base = {
2494497f2e6bSLee Nipper 				.cra_name = "sha1",
2495497f2e6bSLee Nipper 				.cra_driver_name = "sha1-talitos",
2496497f2e6bSLee Nipper 				.cra_blocksize = SHA1_BLOCK_SIZE,
2497497f2e6bSLee Nipper 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
2498497f2e6bSLee Nipper 					     CRYPTO_ALG_ASYNC,
2499497f2e6bSLee Nipper 			}
2500497f2e6bSLee Nipper 		},
2501497f2e6bSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
2502497f2e6bSLee Nipper 				     DESC_HDR_SEL0_MDEUA |
2503497f2e6bSLee Nipper 				     DESC_HDR_MODE0_MDEU_SHA1,
2504497f2e6bSLee Nipper 	},
2505497f2e6bSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
2506497f2e6bSLee Nipper 		.alg.hash = {
250760f208d7SKim Phillips 			.halg.digestsize = SHA224_DIGEST_SIZE,
25083639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
250960f208d7SKim Phillips 			.halg.base = {
251060f208d7SKim Phillips 				.cra_name = "sha224",
251160f208d7SKim Phillips 				.cra_driver_name = "sha224-talitos",
251260f208d7SKim Phillips 				.cra_blocksize = SHA224_BLOCK_SIZE,
251360f208d7SKim Phillips 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
251460f208d7SKim Phillips 					     CRYPTO_ALG_ASYNC,
251560f208d7SKim Phillips 			}
251660f208d7SKim Phillips 		},
251760f208d7SKim Phillips 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
251860f208d7SKim Phillips 				     DESC_HDR_SEL0_MDEUA |
251960f208d7SKim Phillips 				     DESC_HDR_MODE0_MDEU_SHA224,
252060f208d7SKim Phillips 	},
252160f208d7SKim Phillips 	{	.type = CRYPTO_ALG_TYPE_AHASH,
252260f208d7SKim Phillips 		.alg.hash = {
2523497f2e6bSLee Nipper 			.halg.digestsize = SHA256_DIGEST_SIZE,
25243639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
2525497f2e6bSLee Nipper 			.halg.base = {
2526497f2e6bSLee Nipper 				.cra_name = "sha256",
2527497f2e6bSLee Nipper 				.cra_driver_name = "sha256-talitos",
2528497f2e6bSLee Nipper 				.cra_blocksize = SHA256_BLOCK_SIZE,
2529497f2e6bSLee Nipper 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
2530497f2e6bSLee Nipper 					     CRYPTO_ALG_ASYNC,
2531497f2e6bSLee Nipper 			}
2532497f2e6bSLee Nipper 		},
2533497f2e6bSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
2534497f2e6bSLee Nipper 				     DESC_HDR_SEL0_MDEUA |
2535497f2e6bSLee Nipper 				     DESC_HDR_MODE0_MDEU_SHA256,
2536497f2e6bSLee Nipper 	},
2537497f2e6bSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
2538497f2e6bSLee Nipper 		.alg.hash = {
2539497f2e6bSLee Nipper 			.halg.digestsize = SHA384_DIGEST_SIZE,
25403639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
2541497f2e6bSLee Nipper 			.halg.base = {
2542497f2e6bSLee Nipper 				.cra_name = "sha384",
2543497f2e6bSLee Nipper 				.cra_driver_name = "sha384-talitos",
2544497f2e6bSLee Nipper 				.cra_blocksize = SHA384_BLOCK_SIZE,
2545497f2e6bSLee Nipper 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
2546497f2e6bSLee Nipper 					     CRYPTO_ALG_ASYNC,
2547497f2e6bSLee Nipper 			}
2548497f2e6bSLee Nipper 		},
2549497f2e6bSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
2550497f2e6bSLee Nipper 				     DESC_HDR_SEL0_MDEUB |
2551497f2e6bSLee Nipper 				     DESC_HDR_MODE0_MDEUB_SHA384,
2552497f2e6bSLee Nipper 	},
2553497f2e6bSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
2554497f2e6bSLee Nipper 		.alg.hash = {
2555497f2e6bSLee Nipper 			.halg.digestsize = SHA512_DIGEST_SIZE,
25563639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
2557497f2e6bSLee Nipper 			.halg.base = {
2558497f2e6bSLee Nipper 				.cra_name = "sha512",
2559497f2e6bSLee Nipper 				.cra_driver_name = "sha512-talitos",
2560497f2e6bSLee Nipper 				.cra_blocksize = SHA512_BLOCK_SIZE,
2561497f2e6bSLee Nipper 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
2562497f2e6bSLee Nipper 					     CRYPTO_ALG_ASYNC,
2563497f2e6bSLee Nipper 			}
2564497f2e6bSLee Nipper 		},
2565497f2e6bSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
2566497f2e6bSLee Nipper 				     DESC_HDR_SEL0_MDEUB |
2567497f2e6bSLee Nipper 				     DESC_HDR_MODE0_MDEUB_SHA512,
2568497f2e6bSLee Nipper 	},
256979b3a418SLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
257079b3a418SLee Nipper 		.alg.hash = {
257179b3a418SLee Nipper 			.halg.digestsize = MD5_DIGEST_SIZE,
25723639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
257379b3a418SLee Nipper 			.halg.base = {
257479b3a418SLee Nipper 				.cra_name = "hmac(md5)",
257579b3a418SLee Nipper 				.cra_driver_name = "hmac-md5-talitos",
2576b3988618SMartin Hicks 				.cra_blocksize = MD5_HMAC_BLOCK_SIZE,
257779b3a418SLee Nipper 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
257879b3a418SLee Nipper 					     CRYPTO_ALG_ASYNC,
257979b3a418SLee Nipper 			}
258079b3a418SLee Nipper 		},
258179b3a418SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
258279b3a418SLee Nipper 				     DESC_HDR_SEL0_MDEUA |
258379b3a418SLee Nipper 				     DESC_HDR_MODE0_MDEU_MD5,
258479b3a418SLee Nipper 	},
258579b3a418SLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
258679b3a418SLee Nipper 		.alg.hash = {
258779b3a418SLee Nipper 			.halg.digestsize = SHA1_DIGEST_SIZE,
25883639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
258979b3a418SLee Nipper 			.halg.base = {
259079b3a418SLee Nipper 				.cra_name = "hmac(sha1)",
259179b3a418SLee Nipper 				.cra_driver_name = "hmac-sha1-talitos",
259279b3a418SLee Nipper 				.cra_blocksize = SHA1_BLOCK_SIZE,
259379b3a418SLee Nipper 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
259479b3a418SLee Nipper 					     CRYPTO_ALG_ASYNC,
259579b3a418SLee Nipper 			}
259679b3a418SLee Nipper 		},
259779b3a418SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
259879b3a418SLee Nipper 				     DESC_HDR_SEL0_MDEUA |
259979b3a418SLee Nipper 				     DESC_HDR_MODE0_MDEU_SHA1,
260079b3a418SLee Nipper 	},
260179b3a418SLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
260279b3a418SLee Nipper 		.alg.hash = {
260379b3a418SLee Nipper 			.halg.digestsize = SHA224_DIGEST_SIZE,
26043639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
260579b3a418SLee Nipper 			.halg.base = {
260679b3a418SLee Nipper 				.cra_name = "hmac(sha224)",
260779b3a418SLee Nipper 				.cra_driver_name = "hmac-sha224-talitos",
260879b3a418SLee Nipper 				.cra_blocksize = SHA224_BLOCK_SIZE,
260979b3a418SLee Nipper 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
261079b3a418SLee Nipper 					     CRYPTO_ALG_ASYNC,
261179b3a418SLee Nipper 			}
261279b3a418SLee Nipper 		},
261379b3a418SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
261479b3a418SLee Nipper 				     DESC_HDR_SEL0_MDEUA |
261579b3a418SLee Nipper 				     DESC_HDR_MODE0_MDEU_SHA224,
261679b3a418SLee Nipper 	},
261779b3a418SLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
261879b3a418SLee Nipper 		.alg.hash = {
261979b3a418SLee Nipper 			.halg.digestsize = SHA256_DIGEST_SIZE,
26203639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
262179b3a418SLee Nipper 			.halg.base = {
262279b3a418SLee Nipper 				.cra_name = "hmac(sha256)",
262379b3a418SLee Nipper 				.cra_driver_name = "hmac-sha256-talitos",
262479b3a418SLee Nipper 				.cra_blocksize = SHA256_BLOCK_SIZE,
262579b3a418SLee Nipper 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
262679b3a418SLee Nipper 					     CRYPTO_ALG_ASYNC,
262779b3a418SLee Nipper 			}
262879b3a418SLee Nipper 		},
262979b3a418SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
263079b3a418SLee Nipper 				     DESC_HDR_SEL0_MDEUA |
263179b3a418SLee Nipper 				     DESC_HDR_MODE0_MDEU_SHA256,
263279b3a418SLee Nipper 	},
263379b3a418SLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
263479b3a418SLee Nipper 		.alg.hash = {
263579b3a418SLee Nipper 			.halg.digestsize = SHA384_DIGEST_SIZE,
26363639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
263779b3a418SLee Nipper 			.halg.base = {
263879b3a418SLee Nipper 				.cra_name = "hmac(sha384)",
263979b3a418SLee Nipper 				.cra_driver_name = "hmac-sha384-talitos",
264079b3a418SLee Nipper 				.cra_blocksize = SHA384_BLOCK_SIZE,
264179b3a418SLee Nipper 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
264279b3a418SLee Nipper 					     CRYPTO_ALG_ASYNC,
264379b3a418SLee Nipper 			}
264479b3a418SLee Nipper 		},
264579b3a418SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
264679b3a418SLee Nipper 				     DESC_HDR_SEL0_MDEUB |
264779b3a418SLee Nipper 				     DESC_HDR_MODE0_MDEUB_SHA384,
264879b3a418SLee Nipper 	},
264979b3a418SLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
265079b3a418SLee Nipper 		.alg.hash = {
265179b3a418SLee Nipper 			.halg.digestsize = SHA512_DIGEST_SIZE,
26523639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
265379b3a418SLee Nipper 			.halg.base = {
265479b3a418SLee Nipper 				.cra_name = "hmac(sha512)",
265579b3a418SLee Nipper 				.cra_driver_name = "hmac-sha512-talitos",
265679b3a418SLee Nipper 				.cra_blocksize = SHA512_BLOCK_SIZE,
265779b3a418SLee Nipper 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
265879b3a418SLee Nipper 					     CRYPTO_ALG_ASYNC,
265979b3a418SLee Nipper 			}
266079b3a418SLee Nipper 		},
266179b3a418SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
266279b3a418SLee Nipper 				     DESC_HDR_SEL0_MDEUB |
266379b3a418SLee Nipper 				     DESC_HDR_MODE0_MDEUB_SHA512,
266479b3a418SLee Nipper 	}
26659c4a7965SKim Phillips };
26669c4a7965SKim Phillips 
26679c4a7965SKim Phillips struct talitos_crypto_alg {
26689c4a7965SKim Phillips 	struct list_head entry;
26699c4a7965SKim Phillips 	struct device *dev;
2670acbf7c62SLee Nipper 	struct talitos_alg_template algt;
26719c4a7965SKim Phillips };
26729c4a7965SKim Phillips 
267389d124cbSJonas Eymann static int talitos_init_common(struct talitos_ctx *ctx,
267489d124cbSJonas Eymann 			       struct talitos_crypto_alg *talitos_alg)
26759c4a7965SKim Phillips {
26765228f0f7SKim Phillips 	struct talitos_private *priv;
26779c4a7965SKim Phillips 
26789c4a7965SKim Phillips 	/* update context with ptr to dev */
26799c4a7965SKim Phillips 	ctx->dev = talitos_alg->dev;
268019bbbc63SKim Phillips 
26815228f0f7SKim Phillips 	/* assign SEC channel to tfm in round-robin fashion */
26825228f0f7SKim Phillips 	priv = dev_get_drvdata(ctx->dev);
26835228f0f7SKim Phillips 	ctx->ch = atomic_inc_return(&priv->last_chan) &
26845228f0f7SKim Phillips 		  (priv->num_channels - 1);
26855228f0f7SKim Phillips 
26869c4a7965SKim Phillips 	/* copy descriptor header template value */
2687acbf7c62SLee Nipper 	ctx->desc_hdr_template = talitos_alg->algt.desc_hdr_template;
26889c4a7965SKim Phillips 
2689602dba5aSKim Phillips 	/* select done notification */
2690602dba5aSKim Phillips 	ctx->desc_hdr_template |= DESC_HDR_DONE_NOTIFY;
2691602dba5aSKim Phillips 
2692497f2e6bSLee Nipper 	return 0;
2693497f2e6bSLee Nipper }
2694497f2e6bSLee Nipper 
269589d124cbSJonas Eymann static int talitos_cra_init(struct crypto_tfm *tfm)
269689d124cbSJonas Eymann {
269789d124cbSJonas Eymann 	struct crypto_alg *alg = tfm->__crt_alg;
269889d124cbSJonas Eymann 	struct talitos_crypto_alg *talitos_alg;
269989d124cbSJonas Eymann 	struct talitos_ctx *ctx = crypto_tfm_ctx(tfm);
270089d124cbSJonas Eymann 
270189d124cbSJonas Eymann 	if ((alg->cra_flags & CRYPTO_ALG_TYPE_MASK) == CRYPTO_ALG_TYPE_AHASH)
270289d124cbSJonas Eymann 		talitos_alg = container_of(__crypto_ahash_alg(alg),
270389d124cbSJonas Eymann 					   struct talitos_crypto_alg,
270489d124cbSJonas Eymann 					   algt.alg.hash);
270589d124cbSJonas Eymann 	else
270689d124cbSJonas Eymann 		talitos_alg = container_of(alg, struct talitos_crypto_alg,
270789d124cbSJonas Eymann 					   algt.alg.crypto);
270889d124cbSJonas Eymann 
270989d124cbSJonas Eymann 	return talitos_init_common(ctx, talitos_alg);
271089d124cbSJonas Eymann }
271189d124cbSJonas Eymann 
2712aeb4c132SHerbert Xu static int talitos_cra_init_aead(struct crypto_aead *tfm)
2713497f2e6bSLee Nipper {
271489d124cbSJonas Eymann 	struct aead_alg *alg = crypto_aead_alg(tfm);
271589d124cbSJonas Eymann 	struct talitos_crypto_alg *talitos_alg;
271689d124cbSJonas Eymann 	struct talitos_ctx *ctx = crypto_aead_ctx(tfm);
271789d124cbSJonas Eymann 
271889d124cbSJonas Eymann 	talitos_alg = container_of(alg, struct talitos_crypto_alg,
271989d124cbSJonas Eymann 				   algt.alg.aead);
272089d124cbSJonas Eymann 
272189d124cbSJonas Eymann 	return talitos_init_common(ctx, talitos_alg);
27229c4a7965SKim Phillips }
27239c4a7965SKim Phillips 
2724497f2e6bSLee Nipper static int talitos_cra_init_ahash(struct crypto_tfm *tfm)
2725497f2e6bSLee Nipper {
2726497f2e6bSLee Nipper 	struct talitos_ctx *ctx = crypto_tfm_ctx(tfm);
2727497f2e6bSLee Nipper 
2728497f2e6bSLee Nipper 	talitos_cra_init(tfm);
2729497f2e6bSLee Nipper 
2730497f2e6bSLee Nipper 	ctx->keylen = 0;
2731497f2e6bSLee Nipper 	crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm),
2732497f2e6bSLee Nipper 				 sizeof(struct talitos_ahash_req_ctx));
2733497f2e6bSLee Nipper 
2734497f2e6bSLee Nipper 	return 0;
2735497f2e6bSLee Nipper }
2736497f2e6bSLee Nipper 
27379c4a7965SKim Phillips /*
27389c4a7965SKim Phillips  * given the alg's descriptor header template, determine whether descriptor
27399c4a7965SKim Phillips  * type and primary/secondary execution units required match the hw
27409c4a7965SKim Phillips  * capabilities description provided in the device tree node.
27419c4a7965SKim Phillips  */
27429c4a7965SKim Phillips static int hw_supports(struct device *dev, __be32 desc_hdr_template)
27439c4a7965SKim Phillips {
27449c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
27459c4a7965SKim Phillips 	int ret;
27469c4a7965SKim Phillips 
27479c4a7965SKim Phillips 	ret = (1 << DESC_TYPE(desc_hdr_template) & priv->desc_types) &&
27489c4a7965SKim Phillips 	      (1 << PRIMARY_EU(desc_hdr_template) & priv->exec_units);
27499c4a7965SKim Phillips 
27509c4a7965SKim Phillips 	if (SECONDARY_EU(desc_hdr_template))
27519c4a7965SKim Phillips 		ret = ret && (1 << SECONDARY_EU(desc_hdr_template)
27529c4a7965SKim Phillips 		              & priv->exec_units);
27539c4a7965SKim Phillips 
27549c4a7965SKim Phillips 	return ret;
27559c4a7965SKim Phillips }
27569c4a7965SKim Phillips 
27572dc11581SGrant Likely static int talitos_remove(struct platform_device *ofdev)
27589c4a7965SKim Phillips {
27599c4a7965SKim Phillips 	struct device *dev = &ofdev->dev;
27609c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
27619c4a7965SKim Phillips 	struct talitos_crypto_alg *t_alg, *n;
27629c4a7965SKim Phillips 	int i;
27639c4a7965SKim Phillips 
27649c4a7965SKim Phillips 	list_for_each_entry_safe(t_alg, n, &priv->alg_list, entry) {
2765acbf7c62SLee Nipper 		switch (t_alg->algt.type) {
2766acbf7c62SLee Nipper 		case CRYPTO_ALG_TYPE_ABLKCIPHER:
2767acbf7c62SLee Nipper 			break;
2768aeb4c132SHerbert Xu 		case CRYPTO_ALG_TYPE_AEAD:
2769aeb4c132SHerbert Xu 			crypto_unregister_aead(&t_alg->algt.alg.aead);
2770acbf7c62SLee Nipper 		case CRYPTO_ALG_TYPE_AHASH:
2771acbf7c62SLee Nipper 			crypto_unregister_ahash(&t_alg->algt.alg.hash);
2772acbf7c62SLee Nipper 			break;
2773acbf7c62SLee Nipper 		}
27749c4a7965SKim Phillips 		list_del(&t_alg->entry);
27759c4a7965SKim Phillips 		kfree(t_alg);
27769c4a7965SKim Phillips 	}
27779c4a7965SKim Phillips 
27789c4a7965SKim Phillips 	if (hw_supports(dev, DESC_HDR_SEL0_RNG))
27799c4a7965SKim Phillips 		talitos_unregister_rng(dev);
27809c4a7965SKim Phillips 
278135a3bb3dSAaron Sierra 	for (i = 0; priv->chan && i < priv->num_channels; i++)
27824b992628SKim Phillips 		kfree(priv->chan[i].fifo);
27839c4a7965SKim Phillips 
27844b992628SKim Phillips 	kfree(priv->chan);
27859c4a7965SKim Phillips 
2786c3e337f8SKim Phillips 	for (i = 0; i < 2; i++)
27872cdba3cfSKim Phillips 		if (priv->irq[i]) {
2788c3e337f8SKim Phillips 			free_irq(priv->irq[i], dev);
2789c3e337f8SKim Phillips 			irq_dispose_mapping(priv->irq[i]);
27909c4a7965SKim Phillips 		}
27919c4a7965SKim Phillips 
2792c3e337f8SKim Phillips 	tasklet_kill(&priv->done_task[0]);
27932cdba3cfSKim Phillips 	if (priv->irq[1])
2794c3e337f8SKim Phillips 		tasklet_kill(&priv->done_task[1]);
27959c4a7965SKim Phillips 
27969c4a7965SKim Phillips 	iounmap(priv->reg);
27979c4a7965SKim Phillips 
27989c4a7965SKim Phillips 	kfree(priv);
27999c4a7965SKim Phillips 
28009c4a7965SKim Phillips 	return 0;
28019c4a7965SKim Phillips }
28029c4a7965SKim Phillips 
28039c4a7965SKim Phillips static struct talitos_crypto_alg *talitos_alg_alloc(struct device *dev,
28049c4a7965SKim Phillips 						    struct talitos_alg_template
28059c4a7965SKim Phillips 						           *template)
28069c4a7965SKim Phillips {
280760f208d7SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
28089c4a7965SKim Phillips 	struct talitos_crypto_alg *t_alg;
28099c4a7965SKim Phillips 	struct crypto_alg *alg;
28109c4a7965SKim Phillips 
28119c4a7965SKim Phillips 	t_alg = kzalloc(sizeof(struct talitos_crypto_alg), GFP_KERNEL);
28129c4a7965SKim Phillips 	if (!t_alg)
28139c4a7965SKim Phillips 		return ERR_PTR(-ENOMEM);
28149c4a7965SKim Phillips 
2815acbf7c62SLee Nipper 	t_alg->algt = *template;
2816acbf7c62SLee Nipper 
2817acbf7c62SLee Nipper 	switch (t_alg->algt.type) {
2818acbf7c62SLee Nipper 	case CRYPTO_ALG_TYPE_ABLKCIPHER:
2819497f2e6bSLee Nipper 		alg = &t_alg->algt.alg.crypto;
2820497f2e6bSLee Nipper 		alg->cra_init = talitos_cra_init;
2821d4cd3283SKim Phillips 		alg->cra_type = &crypto_ablkcipher_type;
2822b286e003SKim Phillips 		alg->cra_ablkcipher.setkey = ablkcipher_setkey;
2823b286e003SKim Phillips 		alg->cra_ablkcipher.encrypt = ablkcipher_encrypt;
2824b286e003SKim Phillips 		alg->cra_ablkcipher.decrypt = ablkcipher_decrypt;
2825b286e003SKim Phillips 		alg->cra_ablkcipher.geniv = "eseqiv";
2826497f2e6bSLee Nipper 		break;
2827acbf7c62SLee Nipper 	case CRYPTO_ALG_TYPE_AEAD:
2828aeb4c132SHerbert Xu 		alg = &t_alg->algt.alg.aead.base;
2829aeb4c132SHerbert Xu 		t_alg->algt.alg.aead.init = talitos_cra_init_aead;
2830aeb4c132SHerbert Xu 		t_alg->algt.alg.aead.setkey = aead_setkey;
2831aeb4c132SHerbert Xu 		t_alg->algt.alg.aead.encrypt = aead_encrypt;
2832aeb4c132SHerbert Xu 		t_alg->algt.alg.aead.decrypt = aead_decrypt;
2833acbf7c62SLee Nipper 		break;
2834acbf7c62SLee Nipper 	case CRYPTO_ALG_TYPE_AHASH:
2835acbf7c62SLee Nipper 		alg = &t_alg->algt.alg.hash.halg.base;
2836497f2e6bSLee Nipper 		alg->cra_init = talitos_cra_init_ahash;
2837d4cd3283SKim Phillips 		alg->cra_type = &crypto_ahash_type;
2838b286e003SKim Phillips 		t_alg->algt.alg.hash.init = ahash_init;
2839b286e003SKim Phillips 		t_alg->algt.alg.hash.update = ahash_update;
2840b286e003SKim Phillips 		t_alg->algt.alg.hash.final = ahash_final;
2841b286e003SKim Phillips 		t_alg->algt.alg.hash.finup = ahash_finup;
2842b286e003SKim Phillips 		t_alg->algt.alg.hash.digest = ahash_digest;
2843b286e003SKim Phillips 		t_alg->algt.alg.hash.setkey = ahash_setkey;
28443639ca84SHoria Geant? 		t_alg->algt.alg.hash.import = ahash_import;
28453639ca84SHoria Geant? 		t_alg->algt.alg.hash.export = ahash_export;
2846b286e003SKim Phillips 
284779b3a418SLee Nipper 		if (!(priv->features & TALITOS_FTR_HMAC_OK) &&
28480b2730d8SKim Phillips 		    !strncmp(alg->cra_name, "hmac", 4)) {
28490b2730d8SKim Phillips 			kfree(t_alg);
285079b3a418SLee Nipper 			return ERR_PTR(-ENOTSUPP);
28510b2730d8SKim Phillips 		}
285260f208d7SKim Phillips 		if (!(priv->features & TALITOS_FTR_SHA224_HWINIT) &&
285379b3a418SLee Nipper 		    (!strcmp(alg->cra_name, "sha224") ||
285479b3a418SLee Nipper 		     !strcmp(alg->cra_name, "hmac(sha224)"))) {
285560f208d7SKim Phillips 			t_alg->algt.alg.hash.init = ahash_init_sha224_swinit;
285660f208d7SKim Phillips 			t_alg->algt.desc_hdr_template =
285760f208d7SKim Phillips 					DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
285860f208d7SKim Phillips 					DESC_HDR_SEL0_MDEUA |
285960f208d7SKim Phillips 					DESC_HDR_MODE0_MDEU_SHA256;
286060f208d7SKim Phillips 		}
2861497f2e6bSLee Nipper 		break;
28621d11911aSKim Phillips 	default:
28631d11911aSKim Phillips 		dev_err(dev, "unknown algorithm type %d\n", t_alg->algt.type);
28645fa7dadcSHoria Geant? 		kfree(t_alg);
28651d11911aSKim Phillips 		return ERR_PTR(-EINVAL);
2866acbf7c62SLee Nipper 	}
28679c4a7965SKim Phillips 
28689c4a7965SKim Phillips 	alg->cra_module = THIS_MODULE;
28699c4a7965SKim Phillips 	alg->cra_priority = TALITOS_CRA_PRIORITY;
28709c4a7965SKim Phillips 	alg->cra_alignmask = 0;
28719c4a7965SKim Phillips 	alg->cra_ctxsize = sizeof(struct talitos_ctx);
2872d912bb76SNikos Mavrogiannopoulos 	alg->cra_flags |= CRYPTO_ALG_KERN_DRIVER_ONLY;
28739c4a7965SKim Phillips 
28749c4a7965SKim Phillips 	t_alg->dev = dev;
28759c4a7965SKim Phillips 
28769c4a7965SKim Phillips 	return t_alg;
28779c4a7965SKim Phillips }
28789c4a7965SKim Phillips 
2879c3e337f8SKim Phillips static int talitos_probe_irq(struct platform_device *ofdev)
2880c3e337f8SKim Phillips {
2881c3e337f8SKim Phillips 	struct device *dev = &ofdev->dev;
2882c3e337f8SKim Phillips 	struct device_node *np = ofdev->dev.of_node;
2883c3e337f8SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
2884c3e337f8SKim Phillips 	int err;
2885dd3c0987SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
2886c3e337f8SKim Phillips 
2887c3e337f8SKim Phillips 	priv->irq[0] = irq_of_parse_and_map(np, 0);
28882cdba3cfSKim Phillips 	if (!priv->irq[0]) {
2889c3e337f8SKim Phillips 		dev_err(dev, "failed to map irq\n");
2890c3e337f8SKim Phillips 		return -EINVAL;
2891c3e337f8SKim Phillips 	}
2892dd3c0987SLEROY Christophe 	if (is_sec1) {
2893dd3c0987SLEROY Christophe 		err = request_irq(priv->irq[0], talitos1_interrupt_4ch, 0,
2894dd3c0987SLEROY Christophe 				  dev_driver_string(dev), dev);
2895dd3c0987SLEROY Christophe 		goto primary_out;
2896dd3c0987SLEROY Christophe 	}
2897c3e337f8SKim Phillips 
2898c3e337f8SKim Phillips 	priv->irq[1] = irq_of_parse_and_map(np, 1);
2899c3e337f8SKim Phillips 
2900c3e337f8SKim Phillips 	/* get the primary irq line */
29012cdba3cfSKim Phillips 	if (!priv->irq[1]) {
2902dd3c0987SLEROY Christophe 		err = request_irq(priv->irq[0], talitos2_interrupt_4ch, 0,
2903c3e337f8SKim Phillips 				  dev_driver_string(dev), dev);
2904c3e337f8SKim Phillips 		goto primary_out;
2905c3e337f8SKim Phillips 	}
2906c3e337f8SKim Phillips 
2907dd3c0987SLEROY Christophe 	err = request_irq(priv->irq[0], talitos2_interrupt_ch0_2, 0,
2908c3e337f8SKim Phillips 			  dev_driver_string(dev), dev);
2909c3e337f8SKim Phillips 	if (err)
2910c3e337f8SKim Phillips 		goto primary_out;
2911c3e337f8SKim Phillips 
2912c3e337f8SKim Phillips 	/* get the secondary irq line */
2913dd3c0987SLEROY Christophe 	err = request_irq(priv->irq[1], talitos2_interrupt_ch1_3, 0,
2914c3e337f8SKim Phillips 			  dev_driver_string(dev), dev);
2915c3e337f8SKim Phillips 	if (err) {
2916c3e337f8SKim Phillips 		dev_err(dev, "failed to request secondary irq\n");
2917c3e337f8SKim Phillips 		irq_dispose_mapping(priv->irq[1]);
29182cdba3cfSKim Phillips 		priv->irq[1] = 0;
2919c3e337f8SKim Phillips 	}
2920c3e337f8SKim Phillips 
2921c3e337f8SKim Phillips 	return err;
2922c3e337f8SKim Phillips 
2923c3e337f8SKim Phillips primary_out:
2924c3e337f8SKim Phillips 	if (err) {
2925c3e337f8SKim Phillips 		dev_err(dev, "failed to request primary irq\n");
2926c3e337f8SKim Phillips 		irq_dispose_mapping(priv->irq[0]);
29272cdba3cfSKim Phillips 		priv->irq[0] = 0;
2928c3e337f8SKim Phillips 	}
2929c3e337f8SKim Phillips 
2930c3e337f8SKim Phillips 	return err;
2931c3e337f8SKim Phillips }
2932c3e337f8SKim Phillips 
29331c48a5c9SGrant Likely static int talitos_probe(struct platform_device *ofdev)
29349c4a7965SKim Phillips {
29359c4a7965SKim Phillips 	struct device *dev = &ofdev->dev;
293661c7a080SGrant Likely 	struct device_node *np = ofdev->dev.of_node;
29379c4a7965SKim Phillips 	struct talitos_private *priv;
29389c4a7965SKim Phillips 	const unsigned int *prop;
29399c4a7965SKim Phillips 	int i, err;
29405fa7fa14SLEROY Christophe 	int stride;
29419c4a7965SKim Phillips 
29429c4a7965SKim Phillips 	priv = kzalloc(sizeof(struct talitos_private), GFP_KERNEL);
29439c4a7965SKim Phillips 	if (!priv)
29449c4a7965SKim Phillips 		return -ENOMEM;
29459c4a7965SKim Phillips 
2946f3de9cb1SKevin Hao 	INIT_LIST_HEAD(&priv->alg_list);
2947f3de9cb1SKevin Hao 
29489c4a7965SKim Phillips 	dev_set_drvdata(dev, priv);
29499c4a7965SKim Phillips 
29509c4a7965SKim Phillips 	priv->ofdev = ofdev;
29519c4a7965SKim Phillips 
2952511d63cbSHoria Geanta 	spin_lock_init(&priv->reg_lock);
2953511d63cbSHoria Geanta 
29549c4a7965SKim Phillips 	priv->reg = of_iomap(np, 0);
29559c4a7965SKim Phillips 	if (!priv->reg) {
29569c4a7965SKim Phillips 		dev_err(dev, "failed to of_iomap\n");
29579c4a7965SKim Phillips 		err = -ENOMEM;
29589c4a7965SKim Phillips 		goto err_out;
29599c4a7965SKim Phillips 	}
29609c4a7965SKim Phillips 
29619c4a7965SKim Phillips 	/* get SEC version capabilities from device tree */
29629c4a7965SKim Phillips 	prop = of_get_property(np, "fsl,num-channels", NULL);
29639c4a7965SKim Phillips 	if (prop)
29649c4a7965SKim Phillips 		priv->num_channels = *prop;
29659c4a7965SKim Phillips 
29669c4a7965SKim Phillips 	prop = of_get_property(np, "fsl,channel-fifo-len", NULL);
29679c4a7965SKim Phillips 	if (prop)
29689c4a7965SKim Phillips 		priv->chfifo_len = *prop;
29699c4a7965SKim Phillips 
29709c4a7965SKim Phillips 	prop = of_get_property(np, "fsl,exec-units-mask", NULL);
29719c4a7965SKim Phillips 	if (prop)
29729c4a7965SKim Phillips 		priv->exec_units = *prop;
29739c4a7965SKim Phillips 
29749c4a7965SKim Phillips 	prop = of_get_property(np, "fsl,descriptor-types-mask", NULL);
29759c4a7965SKim Phillips 	if (prop)
29769c4a7965SKim Phillips 		priv->desc_types = *prop;
29779c4a7965SKim Phillips 
29789c4a7965SKim Phillips 	if (!is_power_of_2(priv->num_channels) || !priv->chfifo_len ||
29799c4a7965SKim Phillips 	    !priv->exec_units || !priv->desc_types) {
29809c4a7965SKim Phillips 		dev_err(dev, "invalid property data in device tree node\n");
29819c4a7965SKim Phillips 		err = -EINVAL;
29829c4a7965SKim Phillips 		goto err_out;
29839c4a7965SKim Phillips 	}
29849c4a7965SKim Phillips 
2985f3c85bc1SLee Nipper 	if (of_device_is_compatible(np, "fsl,sec3.0"))
2986f3c85bc1SLee Nipper 		priv->features |= TALITOS_FTR_SRC_LINK_TBL_LEN_INCLUDES_EXTENT;
2987f3c85bc1SLee Nipper 
2988fe5720e2SKim Phillips 	if (of_device_is_compatible(np, "fsl,sec2.1"))
298960f208d7SKim Phillips 		priv->features |= TALITOS_FTR_HW_AUTH_CHECK |
299079b3a418SLee Nipper 				  TALITOS_FTR_SHA224_HWINIT |
299179b3a418SLee Nipper 				  TALITOS_FTR_HMAC_OK;
2992fe5720e2SKim Phillips 
299321590888SLEROY Christophe 	if (of_device_is_compatible(np, "fsl,sec1.0"))
299421590888SLEROY Christophe 		priv->features |= TALITOS_FTR_SEC1;
299521590888SLEROY Christophe 
29965fa7fa14SLEROY Christophe 	if (of_device_is_compatible(np, "fsl,sec1.2")) {
29975fa7fa14SLEROY Christophe 		priv->reg_deu = priv->reg + TALITOS12_DEU;
29985fa7fa14SLEROY Christophe 		priv->reg_aesu = priv->reg + TALITOS12_AESU;
29995fa7fa14SLEROY Christophe 		priv->reg_mdeu = priv->reg + TALITOS12_MDEU;
30005fa7fa14SLEROY Christophe 		stride = TALITOS1_CH_STRIDE;
30015fa7fa14SLEROY Christophe 	} else if (of_device_is_compatible(np, "fsl,sec1.0")) {
30025fa7fa14SLEROY Christophe 		priv->reg_deu = priv->reg + TALITOS10_DEU;
30035fa7fa14SLEROY Christophe 		priv->reg_aesu = priv->reg + TALITOS10_AESU;
30045fa7fa14SLEROY Christophe 		priv->reg_mdeu = priv->reg + TALITOS10_MDEU;
30055fa7fa14SLEROY Christophe 		priv->reg_afeu = priv->reg + TALITOS10_AFEU;
30065fa7fa14SLEROY Christophe 		priv->reg_rngu = priv->reg + TALITOS10_RNGU;
30075fa7fa14SLEROY Christophe 		priv->reg_pkeu = priv->reg + TALITOS10_PKEU;
30085fa7fa14SLEROY Christophe 		stride = TALITOS1_CH_STRIDE;
30095fa7fa14SLEROY Christophe 	} else {
30105fa7fa14SLEROY Christophe 		priv->reg_deu = priv->reg + TALITOS2_DEU;
30115fa7fa14SLEROY Christophe 		priv->reg_aesu = priv->reg + TALITOS2_AESU;
30125fa7fa14SLEROY Christophe 		priv->reg_mdeu = priv->reg + TALITOS2_MDEU;
30135fa7fa14SLEROY Christophe 		priv->reg_afeu = priv->reg + TALITOS2_AFEU;
30145fa7fa14SLEROY Christophe 		priv->reg_rngu = priv->reg + TALITOS2_RNGU;
30155fa7fa14SLEROY Christophe 		priv->reg_pkeu = priv->reg + TALITOS2_PKEU;
30165fa7fa14SLEROY Christophe 		priv->reg_keu = priv->reg + TALITOS2_KEU;
30175fa7fa14SLEROY Christophe 		priv->reg_crcu = priv->reg + TALITOS2_CRCU;
30185fa7fa14SLEROY Christophe 		stride = TALITOS2_CH_STRIDE;
30195fa7fa14SLEROY Christophe 	}
30205fa7fa14SLEROY Christophe 
3021dd3c0987SLEROY Christophe 	err = talitos_probe_irq(ofdev);
3022dd3c0987SLEROY Christophe 	if (err)
3023dd3c0987SLEROY Christophe 		goto err_out;
3024dd3c0987SLEROY Christophe 
3025dd3c0987SLEROY Christophe 	if (of_device_is_compatible(np, "fsl,sec1.0")) {
3026dd3c0987SLEROY Christophe 		tasklet_init(&priv->done_task[0], talitos1_done_4ch,
3027dd3c0987SLEROY Christophe 			     (unsigned long)dev);
3028dd3c0987SLEROY Christophe 	} else {
3029dd3c0987SLEROY Christophe 		if (!priv->irq[1]) {
3030dd3c0987SLEROY Christophe 			tasklet_init(&priv->done_task[0], talitos2_done_4ch,
3031dd3c0987SLEROY Christophe 				     (unsigned long)dev);
3032dd3c0987SLEROY Christophe 		} else {
3033dd3c0987SLEROY Christophe 			tasklet_init(&priv->done_task[0], talitos2_done_ch0_2,
3034dd3c0987SLEROY Christophe 				     (unsigned long)dev);
3035dd3c0987SLEROY Christophe 			tasklet_init(&priv->done_task[1], talitos2_done_ch1_3,
3036dd3c0987SLEROY Christophe 				     (unsigned long)dev);
3037dd3c0987SLEROY Christophe 		}
3038dd3c0987SLEROY Christophe 	}
3039dd3c0987SLEROY Christophe 
30404b992628SKim Phillips 	priv->chan = kzalloc(sizeof(struct talitos_channel) *
30414b992628SKim Phillips 			     priv->num_channels, GFP_KERNEL);
30424b992628SKim Phillips 	if (!priv->chan) {
30434b992628SKim Phillips 		dev_err(dev, "failed to allocate channel management space\n");
30449c4a7965SKim Phillips 		err = -ENOMEM;
30459c4a7965SKim Phillips 		goto err_out;
30469c4a7965SKim Phillips 	}
30479c4a7965SKim Phillips 
3048f641ddddSMartin Hicks 	priv->fifo_len = roundup_pow_of_two(priv->chfifo_len);
3049f641ddddSMartin Hicks 
3050c3e337f8SKim Phillips 	for (i = 0; i < priv->num_channels; i++) {
30515fa7fa14SLEROY Christophe 		priv->chan[i].reg = priv->reg + stride * (i + 1);
30522cdba3cfSKim Phillips 		if (!priv->irq[1] || !(i & 1))
3053c3e337f8SKim Phillips 			priv->chan[i].reg += TALITOS_CH_BASE_OFFSET;
3054ad42d5fcSKim Phillips 
30554b992628SKim Phillips 		spin_lock_init(&priv->chan[i].head_lock);
30564b992628SKim Phillips 		spin_lock_init(&priv->chan[i].tail_lock);
30579c4a7965SKim Phillips 
30584b992628SKim Phillips 		priv->chan[i].fifo = kzalloc(sizeof(struct talitos_request) *
30599c4a7965SKim Phillips 					     priv->fifo_len, GFP_KERNEL);
30604b992628SKim Phillips 		if (!priv->chan[i].fifo) {
30619c4a7965SKim Phillips 			dev_err(dev, "failed to allocate request fifo %d\n", i);
30629c4a7965SKim Phillips 			err = -ENOMEM;
30639c4a7965SKim Phillips 			goto err_out;
30649c4a7965SKim Phillips 		}
30659c4a7965SKim Phillips 
30664b992628SKim Phillips 		atomic_set(&priv->chan[i].submit_count,
30674b992628SKim Phillips 			   -(priv->chfifo_len - 1));
3068f641ddddSMartin Hicks 	}
30699c4a7965SKim Phillips 
307081eb024cSKim Phillips 	dma_set_mask(dev, DMA_BIT_MASK(36));
307181eb024cSKim Phillips 
30729c4a7965SKim Phillips 	/* reset and initialize the h/w */
30739c4a7965SKim Phillips 	err = init_device(dev);
30749c4a7965SKim Phillips 	if (err) {
30759c4a7965SKim Phillips 		dev_err(dev, "failed to initialize device\n");
30769c4a7965SKim Phillips 		goto err_out;
30779c4a7965SKim Phillips 	}
30789c4a7965SKim Phillips 
30799c4a7965SKim Phillips 	/* register the RNG, if available */
30809c4a7965SKim Phillips 	if (hw_supports(dev, DESC_HDR_SEL0_RNG)) {
30819c4a7965SKim Phillips 		err = talitos_register_rng(dev);
30829c4a7965SKim Phillips 		if (err) {
30839c4a7965SKim Phillips 			dev_err(dev, "failed to register hwrng: %d\n", err);
30849c4a7965SKim Phillips 			goto err_out;
30859c4a7965SKim Phillips 		} else
30869c4a7965SKim Phillips 			dev_info(dev, "hwrng\n");
30879c4a7965SKim Phillips 	}
30889c4a7965SKim Phillips 
30899c4a7965SKim Phillips 	/* register crypto algorithms the device supports */
30909c4a7965SKim Phillips 	for (i = 0; i < ARRAY_SIZE(driver_algs); i++) {
30919c4a7965SKim Phillips 		if (hw_supports(dev, driver_algs[i].desc_hdr_template)) {
30929c4a7965SKim Phillips 			struct talitos_crypto_alg *t_alg;
3093aeb4c132SHerbert Xu 			struct crypto_alg *alg = NULL;
30949c4a7965SKim Phillips 
30959c4a7965SKim Phillips 			t_alg = talitos_alg_alloc(dev, &driver_algs[i]);
30969c4a7965SKim Phillips 			if (IS_ERR(t_alg)) {
30979c4a7965SKim Phillips 				err = PTR_ERR(t_alg);
30980b2730d8SKim Phillips 				if (err == -ENOTSUPP)
309979b3a418SLee Nipper 					continue;
31009c4a7965SKim Phillips 				goto err_out;
31019c4a7965SKim Phillips 			}
31029c4a7965SKim Phillips 
3103acbf7c62SLee Nipper 			switch (t_alg->algt.type) {
3104acbf7c62SLee Nipper 			case CRYPTO_ALG_TYPE_ABLKCIPHER:
3105acbf7c62SLee Nipper 				err = crypto_register_alg(
3106acbf7c62SLee Nipper 						&t_alg->algt.alg.crypto);
3107aeb4c132SHerbert Xu 				alg = &t_alg->algt.alg.crypto;
3108acbf7c62SLee Nipper 				break;
3109aeb4c132SHerbert Xu 
3110aeb4c132SHerbert Xu 			case CRYPTO_ALG_TYPE_AEAD:
3111aeb4c132SHerbert Xu 				err = crypto_register_aead(
3112aeb4c132SHerbert Xu 					&t_alg->algt.alg.aead);
3113aeb4c132SHerbert Xu 				alg = &t_alg->algt.alg.aead.base;
3114aeb4c132SHerbert Xu 				break;
3115aeb4c132SHerbert Xu 
3116acbf7c62SLee Nipper 			case CRYPTO_ALG_TYPE_AHASH:
3117acbf7c62SLee Nipper 				err = crypto_register_ahash(
3118acbf7c62SLee Nipper 						&t_alg->algt.alg.hash);
3119aeb4c132SHerbert Xu 				alg = &t_alg->algt.alg.hash.halg.base;
3120acbf7c62SLee Nipper 				break;
3121acbf7c62SLee Nipper 			}
31229c4a7965SKim Phillips 			if (err) {
31239c4a7965SKim Phillips 				dev_err(dev, "%s alg registration failed\n",
3124aeb4c132SHerbert Xu 					alg->cra_driver_name);
31259c4a7965SKim Phillips 				kfree(t_alg);
3126991155baSHoria Geanta 			} else
31279c4a7965SKim Phillips 				list_add_tail(&t_alg->entry, &priv->alg_list);
31289c4a7965SKim Phillips 		}
31299c4a7965SKim Phillips 	}
31305b859b6eSKim Phillips 	if (!list_empty(&priv->alg_list))
31315b859b6eSKim Phillips 		dev_info(dev, "%s algorithms registered in /proc/crypto\n",
31325b859b6eSKim Phillips 			 (char *)of_get_property(np, "compatible", NULL));
31339c4a7965SKim Phillips 
31349c4a7965SKim Phillips 	return 0;
31359c4a7965SKim Phillips 
31369c4a7965SKim Phillips err_out:
31379c4a7965SKim Phillips 	talitos_remove(ofdev);
31389c4a7965SKim Phillips 
31399c4a7965SKim Phillips 	return err;
31409c4a7965SKim Phillips }
31419c4a7965SKim Phillips 
31426c3f975aSMárton Németh static const struct of_device_id talitos_match[] = {
31430635b7dbSLEROY Christophe #ifdef CONFIG_CRYPTO_DEV_TALITOS1
31440635b7dbSLEROY Christophe 	{
31450635b7dbSLEROY Christophe 		.compatible = "fsl,sec1.0",
31460635b7dbSLEROY Christophe 	},
31470635b7dbSLEROY Christophe #endif
31480635b7dbSLEROY Christophe #ifdef CONFIG_CRYPTO_DEV_TALITOS2
31499c4a7965SKim Phillips 	{
31509c4a7965SKim Phillips 		.compatible = "fsl,sec2.0",
31519c4a7965SKim Phillips 	},
31520635b7dbSLEROY Christophe #endif
31539c4a7965SKim Phillips 	{},
31549c4a7965SKim Phillips };
31559c4a7965SKim Phillips MODULE_DEVICE_TABLE(of, talitos_match);
31569c4a7965SKim Phillips 
31571c48a5c9SGrant Likely static struct platform_driver talitos_driver = {
31584018294bSGrant Likely 	.driver = {
31599c4a7965SKim Phillips 		.name = "talitos",
31604018294bSGrant Likely 		.of_match_table = talitos_match,
31614018294bSGrant Likely 	},
31629c4a7965SKim Phillips 	.probe = talitos_probe,
3163596f1034SAl Viro 	.remove = talitos_remove,
31649c4a7965SKim Phillips };
31659c4a7965SKim Phillips 
3166741e8c2dSAxel Lin module_platform_driver(talitos_driver);
31679c4a7965SKim Phillips 
31689c4a7965SKim Phillips MODULE_LICENSE("GPL");
31699c4a7965SKim Phillips MODULE_AUTHOR("Kim Phillips <kim.phillips@freescale.com>");
31709c4a7965SKim Phillips MODULE_DESCRIPTION("Freescale integrated security engine (SEC) driver");
3171