xref: /linux/drivers/crypto/talitos.c (revision 9c02e2852fcabf0e1542929e887867d01414dec6)
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->len1 = cpu_to_be16(len);
79922f9dc8SLEROY Christophe 	} else {
80538caf83SLEROY Christophe 		ptr->len = cpu_to_be16(len);
81538caf83SLEROY Christophe 	}
82922f9dc8SLEROY Christophe }
83538caf83SLEROY Christophe 
84922f9dc8SLEROY Christophe static unsigned short from_talitos_ptr_len(struct talitos_ptr *ptr,
85922f9dc8SLEROY Christophe 					   bool is_sec1)
86538caf83SLEROY Christophe {
87922f9dc8SLEROY Christophe 	if (is_sec1)
88922f9dc8SLEROY Christophe 		return be16_to_cpu(ptr->len1);
89922f9dc8SLEROY Christophe 	else
90538caf83SLEROY Christophe 		return be16_to_cpu(ptr->len);
91538caf83SLEROY Christophe }
92538caf83SLEROY Christophe 
93b096b544SLEROY Christophe static void to_talitos_ptr_ext_set(struct talitos_ptr *ptr, u8 val,
94b096b544SLEROY Christophe 				   bool is_sec1)
95185eb79fSLEROY Christophe {
96922f9dc8SLEROY Christophe 	if (!is_sec1)
97b096b544SLEROY Christophe 		ptr->j_extent = val;
98b096b544SLEROY Christophe }
99b096b544SLEROY Christophe 
100b096b544SLEROY Christophe static void to_talitos_ptr_ext_or(struct talitos_ptr *ptr, u8 val, bool is_sec1)
101b096b544SLEROY Christophe {
102b096b544SLEROY Christophe 	if (!is_sec1)
103b096b544SLEROY Christophe 		ptr->j_extent |= val;
104185eb79fSLEROY Christophe }
105185eb79fSLEROY Christophe 
1069c4a7965SKim Phillips /*
1079c4a7965SKim Phillips  * map virtual single (contiguous) pointer to h/w descriptor pointer
1089c4a7965SKim Phillips  */
1099c4a7965SKim Phillips static void map_single_talitos_ptr(struct device *dev,
110edc6bd69SLEROY Christophe 				   struct talitos_ptr *ptr,
11142e8b0d7SHoria Geant? 				   unsigned int len, void *data,
1129c4a7965SKim Phillips 				   enum dma_data_direction dir)
1139c4a7965SKim Phillips {
11481eb024cSKim Phillips 	dma_addr_t dma_addr = dma_map_single(dev, data, len, dir);
115922f9dc8SLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
116922f9dc8SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
11781eb024cSKim Phillips 
118922f9dc8SLEROY Christophe 	to_talitos_ptr_len(ptr, len, is_sec1);
119922f9dc8SLEROY Christophe 	to_talitos_ptr(ptr, dma_addr, is_sec1);
1209c4a7965SKim Phillips }
1219c4a7965SKim Phillips 
1229c4a7965SKim Phillips /*
1239c4a7965SKim Phillips  * unmap bus single (contiguous) h/w descriptor pointer
1249c4a7965SKim Phillips  */
1259c4a7965SKim Phillips static void unmap_single_talitos_ptr(struct device *dev,
126edc6bd69SLEROY Christophe 				     struct talitos_ptr *ptr,
1279c4a7965SKim Phillips 				     enum dma_data_direction dir)
1289c4a7965SKim Phillips {
129922f9dc8SLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
130922f9dc8SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
131922f9dc8SLEROY Christophe 
132edc6bd69SLEROY Christophe 	dma_unmap_single(dev, be32_to_cpu(ptr->ptr),
133922f9dc8SLEROY Christophe 			 from_talitos_ptr_len(ptr, is_sec1), dir);
1349c4a7965SKim Phillips }
1359c4a7965SKim Phillips 
1369c4a7965SKim Phillips static int reset_channel(struct device *dev, int ch)
1379c4a7965SKim Phillips {
1389c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
1399c4a7965SKim Phillips 	unsigned int timeout = TALITOS_TIMEOUT;
140dd3c0987SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
1419c4a7965SKim Phillips 
142dd3c0987SLEROY Christophe 	if (is_sec1) {
143dd3c0987SLEROY Christophe 		setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO,
144dd3c0987SLEROY Christophe 			  TALITOS1_CCCR_LO_RESET);
1459c4a7965SKim Phillips 
146dd3c0987SLEROY Christophe 		while ((in_be32(priv->chan[ch].reg + TALITOS_CCCR_LO) &
147dd3c0987SLEROY Christophe 			TALITOS1_CCCR_LO_RESET) && --timeout)
1489c4a7965SKim Phillips 			cpu_relax();
149dd3c0987SLEROY Christophe 	} else {
150dd3c0987SLEROY Christophe 		setbits32(priv->chan[ch].reg + TALITOS_CCCR,
151dd3c0987SLEROY Christophe 			  TALITOS2_CCCR_RESET);
152dd3c0987SLEROY Christophe 
153dd3c0987SLEROY Christophe 		while ((in_be32(priv->chan[ch].reg + TALITOS_CCCR) &
154dd3c0987SLEROY Christophe 			TALITOS2_CCCR_RESET) && --timeout)
155dd3c0987SLEROY Christophe 			cpu_relax();
156dd3c0987SLEROY Christophe 	}
1579c4a7965SKim Phillips 
1589c4a7965SKim Phillips 	if (timeout == 0) {
1599c4a7965SKim Phillips 		dev_err(dev, "failed to reset channel %d\n", ch);
1609c4a7965SKim Phillips 		return -EIO;
1619c4a7965SKim Phillips 	}
1629c4a7965SKim Phillips 
16381eb024cSKim Phillips 	/* set 36-bit addressing, done writeback enable and done IRQ enable */
164ad42d5fcSKim Phillips 	setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO, TALITOS_CCCR_LO_EAE |
16581eb024cSKim Phillips 		  TALITOS_CCCR_LO_CDWE | TALITOS_CCCR_LO_CDIE);
1669c4a7965SKim Phillips 
167fe5720e2SKim Phillips 	/* and ICCR writeback, if available */
168fe5720e2SKim Phillips 	if (priv->features & TALITOS_FTR_HW_AUTH_CHECK)
169ad42d5fcSKim Phillips 		setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO,
170fe5720e2SKim Phillips 		          TALITOS_CCCR_LO_IWSE);
171fe5720e2SKim Phillips 
1729c4a7965SKim Phillips 	return 0;
1739c4a7965SKim Phillips }
1749c4a7965SKim Phillips 
1759c4a7965SKim Phillips static int reset_device(struct device *dev)
1769c4a7965SKim Phillips {
1779c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
1789c4a7965SKim Phillips 	unsigned int timeout = TALITOS_TIMEOUT;
179dd3c0987SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
180dd3c0987SLEROY Christophe 	u32 mcr = is_sec1 ? TALITOS1_MCR_SWR : TALITOS2_MCR_SWR;
1819c4a7965SKim Phillips 
182c3e337f8SKim Phillips 	setbits32(priv->reg + TALITOS_MCR, mcr);
1839c4a7965SKim Phillips 
184dd3c0987SLEROY Christophe 	while ((in_be32(priv->reg + TALITOS_MCR) & mcr)
1859c4a7965SKim Phillips 	       && --timeout)
1869c4a7965SKim Phillips 		cpu_relax();
1879c4a7965SKim Phillips 
1882cdba3cfSKim Phillips 	if (priv->irq[1]) {
189c3e337f8SKim Phillips 		mcr = TALITOS_MCR_RCA1 | TALITOS_MCR_RCA3;
190c3e337f8SKim Phillips 		setbits32(priv->reg + TALITOS_MCR, mcr);
191c3e337f8SKim Phillips 	}
192c3e337f8SKim Phillips 
1939c4a7965SKim Phillips 	if (timeout == 0) {
1949c4a7965SKim Phillips 		dev_err(dev, "failed to reset device\n");
1959c4a7965SKim Phillips 		return -EIO;
1969c4a7965SKim Phillips 	}
1979c4a7965SKim Phillips 
1989c4a7965SKim Phillips 	return 0;
1999c4a7965SKim Phillips }
2009c4a7965SKim Phillips 
2019c4a7965SKim Phillips /*
2029c4a7965SKim Phillips  * Reset and initialize the device
2039c4a7965SKim Phillips  */
2049c4a7965SKim Phillips static int init_device(struct device *dev)
2059c4a7965SKim Phillips {
2069c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
2079c4a7965SKim Phillips 	int ch, err;
208dd3c0987SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
2099c4a7965SKim Phillips 
2109c4a7965SKim Phillips 	/*
2119c4a7965SKim Phillips 	 * Master reset
2129c4a7965SKim Phillips 	 * errata documentation: warning: certain SEC interrupts
2139c4a7965SKim Phillips 	 * are not fully cleared by writing the MCR:SWR bit,
2149c4a7965SKim Phillips 	 * set bit twice to completely reset
2159c4a7965SKim Phillips 	 */
2169c4a7965SKim Phillips 	err = reset_device(dev);
2179c4a7965SKim Phillips 	if (err)
2189c4a7965SKim Phillips 		return err;
2199c4a7965SKim Phillips 
2209c4a7965SKim Phillips 	err = reset_device(dev);
2219c4a7965SKim Phillips 	if (err)
2229c4a7965SKim Phillips 		return err;
2239c4a7965SKim Phillips 
2249c4a7965SKim Phillips 	/* reset channels */
2259c4a7965SKim Phillips 	for (ch = 0; ch < priv->num_channels; ch++) {
2269c4a7965SKim Phillips 		err = reset_channel(dev, ch);
2279c4a7965SKim Phillips 		if (err)
2289c4a7965SKim Phillips 			return err;
2299c4a7965SKim Phillips 	}
2309c4a7965SKim Phillips 
2319c4a7965SKim Phillips 	/* enable channel done and error interrupts */
232dd3c0987SLEROY Christophe 	if (is_sec1) {
233dd3c0987SLEROY Christophe 		clrbits32(priv->reg + TALITOS_IMR, TALITOS1_IMR_INIT);
234dd3c0987SLEROY Christophe 		clrbits32(priv->reg + TALITOS_IMR_LO, TALITOS1_IMR_LO_INIT);
235dd3c0987SLEROY Christophe 		/* disable parity error check in DEU (erroneous? test vect.) */
236dd3c0987SLEROY Christophe 		setbits32(priv->reg_deu + TALITOS_EUICR, TALITOS1_DEUICR_KPE);
237dd3c0987SLEROY Christophe 	} else {
238dd3c0987SLEROY Christophe 		setbits32(priv->reg + TALITOS_IMR, TALITOS2_IMR_INIT);
239dd3c0987SLEROY Christophe 		setbits32(priv->reg + TALITOS_IMR_LO, TALITOS2_IMR_LO_INIT);
240dd3c0987SLEROY Christophe 	}
2419c4a7965SKim Phillips 
242fe5720e2SKim Phillips 	/* disable integrity check error interrupts (use writeback instead) */
243fe5720e2SKim Phillips 	if (priv->features & TALITOS_FTR_HW_AUTH_CHECK)
2445fa7fa14SLEROY Christophe 		setbits32(priv->reg_mdeu + TALITOS_EUICR_LO,
245fe5720e2SKim Phillips 		          TALITOS_MDEUICR_LO_ICE);
246fe5720e2SKim Phillips 
2479c4a7965SKim Phillips 	return 0;
2489c4a7965SKim Phillips }
2499c4a7965SKim Phillips 
2509c4a7965SKim Phillips /**
2519c4a7965SKim Phillips  * talitos_submit - submits a descriptor to the device for processing
2529c4a7965SKim Phillips  * @dev:	the SEC device to be used
2535228f0f7SKim Phillips  * @ch:		the SEC device channel to be used
2549c4a7965SKim Phillips  * @desc:	the descriptor to be processed by the device
2559c4a7965SKim Phillips  * @callback:	whom to call when processing is complete
2569c4a7965SKim Phillips  * @context:	a handle for use by caller (optional)
2579c4a7965SKim Phillips  *
2589c4a7965SKim Phillips  * desc must contain valid dma-mapped (bus physical) address pointers.
2599c4a7965SKim Phillips  * callback must check err and feedback in descriptor header
2609c4a7965SKim Phillips  * for device processing status.
2619c4a7965SKim Phillips  */
262865d5061SHoria Geanta int talitos_submit(struct device *dev, int ch, struct talitos_desc *desc,
2639c4a7965SKim Phillips 		   void (*callback)(struct device *dev,
2649c4a7965SKim Phillips 				    struct talitos_desc *desc,
2659c4a7965SKim Phillips 				    void *context, int error),
2669c4a7965SKim Phillips 		   void *context)
2679c4a7965SKim Phillips {
2689c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
2699c4a7965SKim Phillips 	struct talitos_request *request;
2705228f0f7SKim Phillips 	unsigned long flags;
2719c4a7965SKim Phillips 	int head;
2727d607c6aSLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
2739c4a7965SKim Phillips 
2744b992628SKim Phillips 	spin_lock_irqsave(&priv->chan[ch].head_lock, flags);
2759c4a7965SKim Phillips 
2764b992628SKim Phillips 	if (!atomic_inc_not_zero(&priv->chan[ch].submit_count)) {
277ec6644d6SKim Phillips 		/* h/w fifo is full */
2784b992628SKim Phillips 		spin_unlock_irqrestore(&priv->chan[ch].head_lock, flags);
2799c4a7965SKim Phillips 		return -EAGAIN;
2809c4a7965SKim Phillips 	}
2819c4a7965SKim Phillips 
2824b992628SKim Phillips 	head = priv->chan[ch].head;
2834b992628SKim Phillips 	request = &priv->chan[ch].fifo[head];
284ec6644d6SKim Phillips 
2859c4a7965SKim Phillips 	/* map descriptor and save caller data */
2867d607c6aSLEROY Christophe 	if (is_sec1) {
2877d607c6aSLEROY Christophe 		desc->hdr1 = desc->hdr;
2887d607c6aSLEROY Christophe 		request->dma_desc = dma_map_single(dev, &desc->hdr1,
2897d607c6aSLEROY Christophe 						   TALITOS_DESC_SIZE,
2909c4a7965SKim Phillips 						   DMA_BIDIRECTIONAL);
2917d607c6aSLEROY Christophe 	} else {
2927d607c6aSLEROY Christophe 		request->dma_desc = dma_map_single(dev, desc,
2937d607c6aSLEROY Christophe 						   TALITOS_DESC_SIZE,
2947d607c6aSLEROY Christophe 						   DMA_BIDIRECTIONAL);
2957d607c6aSLEROY Christophe 	}
2969c4a7965SKim Phillips 	request->callback = callback;
2979c4a7965SKim Phillips 	request->context = context;
2989c4a7965SKim Phillips 
2999c4a7965SKim Phillips 	/* increment fifo head */
3004b992628SKim Phillips 	priv->chan[ch].head = (priv->chan[ch].head + 1) & (priv->fifo_len - 1);
3019c4a7965SKim Phillips 
3029c4a7965SKim Phillips 	smp_wmb();
3039c4a7965SKim Phillips 	request->desc = desc;
3049c4a7965SKim Phillips 
3059c4a7965SKim Phillips 	/* GO! */
3069c4a7965SKim Phillips 	wmb();
307ad42d5fcSKim Phillips 	out_be32(priv->chan[ch].reg + TALITOS_FF,
308ad42d5fcSKim Phillips 		 upper_32_bits(request->dma_desc));
309ad42d5fcSKim Phillips 	out_be32(priv->chan[ch].reg + TALITOS_FF_LO,
310a752447aSKim Phillips 		 lower_32_bits(request->dma_desc));
3119c4a7965SKim Phillips 
3124b992628SKim Phillips 	spin_unlock_irqrestore(&priv->chan[ch].head_lock, flags);
3139c4a7965SKim Phillips 
3149c4a7965SKim Phillips 	return -EINPROGRESS;
3159c4a7965SKim Phillips }
316865d5061SHoria Geanta EXPORT_SYMBOL(talitos_submit);
3179c4a7965SKim Phillips 
3189c4a7965SKim Phillips /*
3199c4a7965SKim Phillips  * process what was done, notify callback of error if not
3209c4a7965SKim Phillips  */
3219c4a7965SKim Phillips static void flush_channel(struct device *dev, int ch, int error, int reset_ch)
3229c4a7965SKim Phillips {
3239c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
3249c4a7965SKim Phillips 	struct talitos_request *request, saved_req;
3259c4a7965SKim Phillips 	unsigned long flags;
3269c4a7965SKim Phillips 	int tail, status;
3277d607c6aSLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
3289c4a7965SKim Phillips 
3294b992628SKim Phillips 	spin_lock_irqsave(&priv->chan[ch].tail_lock, flags);
3309c4a7965SKim Phillips 
3314b992628SKim Phillips 	tail = priv->chan[ch].tail;
3324b992628SKim Phillips 	while (priv->chan[ch].fifo[tail].desc) {
3337d607c6aSLEROY Christophe 		__be32 hdr;
3347d607c6aSLEROY Christophe 
3354b992628SKim Phillips 		request = &priv->chan[ch].fifo[tail];
3369c4a7965SKim Phillips 
3379c4a7965SKim Phillips 		/* descriptors with their done bits set don't get the error */
3389c4a7965SKim Phillips 		rmb();
3397d607c6aSLEROY Christophe 		hdr = is_sec1 ? request->desc->hdr1 : request->desc->hdr;
3407d607c6aSLEROY Christophe 
3417d607c6aSLEROY Christophe 		if ((hdr & DESC_HDR_DONE) == DESC_HDR_DONE)
3429c4a7965SKim Phillips 			status = 0;
343ca38a814SLee Nipper 		else
3449c4a7965SKim Phillips 			if (!error)
3459c4a7965SKim Phillips 				break;
3469c4a7965SKim Phillips 			else
3479c4a7965SKim Phillips 				status = error;
3489c4a7965SKim Phillips 
3499c4a7965SKim Phillips 		dma_unmap_single(dev, request->dma_desc,
3507d607c6aSLEROY Christophe 				 TALITOS_DESC_SIZE,
351e938e465SKim Phillips 				 DMA_BIDIRECTIONAL);
3529c4a7965SKim Phillips 
3539c4a7965SKim Phillips 		/* copy entries so we can call callback outside lock */
3549c4a7965SKim Phillips 		saved_req.desc = request->desc;
3559c4a7965SKim Phillips 		saved_req.callback = request->callback;
3569c4a7965SKim Phillips 		saved_req.context = request->context;
3579c4a7965SKim Phillips 
3589c4a7965SKim Phillips 		/* release request entry in fifo */
3599c4a7965SKim Phillips 		smp_wmb();
3609c4a7965SKim Phillips 		request->desc = NULL;
3619c4a7965SKim Phillips 
3629c4a7965SKim Phillips 		/* increment fifo tail */
3634b992628SKim Phillips 		priv->chan[ch].tail = (tail + 1) & (priv->fifo_len - 1);
3649c4a7965SKim Phillips 
3654b992628SKim Phillips 		spin_unlock_irqrestore(&priv->chan[ch].tail_lock, flags);
366ec6644d6SKim Phillips 
3674b992628SKim Phillips 		atomic_dec(&priv->chan[ch].submit_count);
368ec6644d6SKim Phillips 
3699c4a7965SKim Phillips 		saved_req.callback(dev, saved_req.desc, saved_req.context,
3709c4a7965SKim Phillips 				   status);
3719c4a7965SKim Phillips 		/* channel may resume processing in single desc error case */
3729c4a7965SKim Phillips 		if (error && !reset_ch && status == error)
3739c4a7965SKim Phillips 			return;
3744b992628SKim Phillips 		spin_lock_irqsave(&priv->chan[ch].tail_lock, flags);
3754b992628SKim Phillips 		tail = priv->chan[ch].tail;
3769c4a7965SKim Phillips 	}
3779c4a7965SKim Phillips 
3784b992628SKim Phillips 	spin_unlock_irqrestore(&priv->chan[ch].tail_lock, flags);
3799c4a7965SKim Phillips }
3809c4a7965SKim Phillips 
3819c4a7965SKim Phillips /*
3829c4a7965SKim Phillips  * process completed requests for channels that have done status
3839c4a7965SKim Phillips  */
384dd3c0987SLEROY Christophe #define DEF_TALITOS1_DONE(name, ch_done_mask)				\
385dd3c0987SLEROY Christophe static void talitos1_done_##name(unsigned long data)			\
386dd3c0987SLEROY Christophe {									\
387dd3c0987SLEROY Christophe 	struct device *dev = (struct device *)data;			\
388dd3c0987SLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);		\
389dd3c0987SLEROY Christophe 	unsigned long flags;						\
390dd3c0987SLEROY Christophe 									\
391dd3c0987SLEROY Christophe 	if (ch_done_mask & 0x10000000)					\
392dd3c0987SLEROY Christophe 		flush_channel(dev, 0, 0, 0);			\
393dd3c0987SLEROY Christophe 	if (ch_done_mask & 0x40000000)					\
394dd3c0987SLEROY Christophe 		flush_channel(dev, 1, 0, 0);			\
395dd3c0987SLEROY Christophe 	if (ch_done_mask & 0x00010000)					\
396dd3c0987SLEROY Christophe 		flush_channel(dev, 2, 0, 0);			\
397dd3c0987SLEROY Christophe 	if (ch_done_mask & 0x00040000)					\
398dd3c0987SLEROY Christophe 		flush_channel(dev, 3, 0, 0);			\
399dd3c0987SLEROY Christophe 									\
400dd3c0987SLEROY Christophe 	/* At this point, all completed channels have been processed */	\
401dd3c0987SLEROY Christophe 	/* Unmask done interrupts for channels completed later on. */	\
402dd3c0987SLEROY Christophe 	spin_lock_irqsave(&priv->reg_lock, flags);			\
403dd3c0987SLEROY Christophe 	clrbits32(priv->reg + TALITOS_IMR, ch_done_mask);		\
404dd3c0987SLEROY Christophe 	clrbits32(priv->reg + TALITOS_IMR_LO, TALITOS1_IMR_LO_INIT);	\
405dd3c0987SLEROY Christophe 	spin_unlock_irqrestore(&priv->reg_lock, flags);			\
406dd3c0987SLEROY Christophe }
407dd3c0987SLEROY Christophe 
408dd3c0987SLEROY Christophe DEF_TALITOS1_DONE(4ch, TALITOS1_ISR_4CHDONE)
409*9c02e285SLEROY Christophe DEF_TALITOS1_DONE(ch0, TALITOS1_ISR_CH_0_DONE)
410dd3c0987SLEROY Christophe 
411dd3c0987SLEROY Christophe #define DEF_TALITOS2_DONE(name, ch_done_mask)				\
412dd3c0987SLEROY Christophe static void talitos2_done_##name(unsigned long data)			\
413c3e337f8SKim Phillips {									\
414c3e337f8SKim Phillips 	struct device *dev = (struct device *)data;			\
415c3e337f8SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);		\
416511d63cbSHoria Geanta 	unsigned long flags;						\
417c3e337f8SKim Phillips 									\
418c3e337f8SKim Phillips 	if (ch_done_mask & 1)						\
419c3e337f8SKim Phillips 		flush_channel(dev, 0, 0, 0);				\
420c3e337f8SKim Phillips 	if (ch_done_mask & (1 << 2))					\
421c3e337f8SKim Phillips 		flush_channel(dev, 1, 0, 0);				\
422c3e337f8SKim Phillips 	if (ch_done_mask & (1 << 4))					\
423c3e337f8SKim Phillips 		flush_channel(dev, 2, 0, 0);				\
424c3e337f8SKim Phillips 	if (ch_done_mask & (1 << 6))					\
425c3e337f8SKim Phillips 		flush_channel(dev, 3, 0, 0);				\
426c3e337f8SKim Phillips 									\
427c3e337f8SKim Phillips 	/* At this point, all completed channels have been processed */	\
428c3e337f8SKim Phillips 	/* Unmask done interrupts for channels completed later on. */	\
429511d63cbSHoria Geanta 	spin_lock_irqsave(&priv->reg_lock, flags);			\
430c3e337f8SKim Phillips 	setbits32(priv->reg + TALITOS_IMR, ch_done_mask);		\
431dd3c0987SLEROY Christophe 	setbits32(priv->reg + TALITOS_IMR_LO, TALITOS2_IMR_LO_INIT);	\
432511d63cbSHoria Geanta 	spin_unlock_irqrestore(&priv->reg_lock, flags);			\
4339c4a7965SKim Phillips }
434dd3c0987SLEROY Christophe 
435dd3c0987SLEROY Christophe DEF_TALITOS2_DONE(4ch, TALITOS2_ISR_4CHDONE)
436*9c02e285SLEROY Christophe DEF_TALITOS2_DONE(ch0, TALITOS2_ISR_CH_0_DONE)
437dd3c0987SLEROY Christophe DEF_TALITOS2_DONE(ch0_2, TALITOS2_ISR_CH_0_2_DONE)
438dd3c0987SLEROY Christophe DEF_TALITOS2_DONE(ch1_3, TALITOS2_ISR_CH_1_3_DONE)
4399c4a7965SKim Phillips 
4409c4a7965SKim Phillips /*
4419c4a7965SKim Phillips  * locate current (offending) descriptor
4429c4a7965SKim Phillips  */
4433e721aebSKim Phillips static u32 current_desc_hdr(struct device *dev, int ch)
4449c4a7965SKim Phillips {
4459c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
446b62ffd8cSHoria Geanta 	int tail, iter;
4479c4a7965SKim Phillips 	dma_addr_t cur_desc;
4489c4a7965SKim Phillips 
449b62ffd8cSHoria Geanta 	cur_desc = ((u64)in_be32(priv->chan[ch].reg + TALITOS_CDPR)) << 32;
450b62ffd8cSHoria Geanta 	cur_desc |= in_be32(priv->chan[ch].reg + TALITOS_CDPR_LO);
4519c4a7965SKim Phillips 
452b62ffd8cSHoria Geanta 	if (!cur_desc) {
453b62ffd8cSHoria Geanta 		dev_err(dev, "CDPR is NULL, giving up search for offending descriptor\n");
454b62ffd8cSHoria Geanta 		return 0;
455b62ffd8cSHoria Geanta 	}
456b62ffd8cSHoria Geanta 
457b62ffd8cSHoria Geanta 	tail = priv->chan[ch].tail;
458b62ffd8cSHoria Geanta 
459b62ffd8cSHoria Geanta 	iter = tail;
460b62ffd8cSHoria Geanta 	while (priv->chan[ch].fifo[iter].dma_desc != cur_desc) {
461b62ffd8cSHoria Geanta 		iter = (iter + 1) & (priv->fifo_len - 1);
462b62ffd8cSHoria Geanta 		if (iter == tail) {
4639c4a7965SKim Phillips 			dev_err(dev, "couldn't locate current descriptor\n");
4643e721aebSKim Phillips 			return 0;
4659c4a7965SKim Phillips 		}
4669c4a7965SKim Phillips 	}
4679c4a7965SKim Phillips 
468b62ffd8cSHoria Geanta 	return priv->chan[ch].fifo[iter].desc->hdr;
4699c4a7965SKim Phillips }
4709c4a7965SKim Phillips 
4719c4a7965SKim Phillips /*
4729c4a7965SKim Phillips  * user diagnostics; report root cause of error based on execution unit status
4739c4a7965SKim Phillips  */
4743e721aebSKim Phillips static void report_eu_error(struct device *dev, int ch, u32 desc_hdr)
4759c4a7965SKim Phillips {
4769c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
4779c4a7965SKim Phillips 	int i;
4789c4a7965SKim Phillips 
4793e721aebSKim Phillips 	if (!desc_hdr)
480ad42d5fcSKim Phillips 		desc_hdr = in_be32(priv->chan[ch].reg + TALITOS_DESCBUF);
4813e721aebSKim Phillips 
4823e721aebSKim Phillips 	switch (desc_hdr & DESC_HDR_SEL0_MASK) {
4839c4a7965SKim Phillips 	case DESC_HDR_SEL0_AFEU:
4849c4a7965SKim Phillips 		dev_err(dev, "AFEUISR 0x%08x_%08x\n",
4855fa7fa14SLEROY Christophe 			in_be32(priv->reg_afeu + TALITOS_EUISR),
4865fa7fa14SLEROY Christophe 			in_be32(priv->reg_afeu + TALITOS_EUISR_LO));
4879c4a7965SKim Phillips 		break;
4889c4a7965SKim Phillips 	case DESC_HDR_SEL0_DEU:
4899c4a7965SKim Phillips 		dev_err(dev, "DEUISR 0x%08x_%08x\n",
4905fa7fa14SLEROY Christophe 			in_be32(priv->reg_deu + TALITOS_EUISR),
4915fa7fa14SLEROY Christophe 			in_be32(priv->reg_deu + TALITOS_EUISR_LO));
4929c4a7965SKim Phillips 		break;
4939c4a7965SKim Phillips 	case DESC_HDR_SEL0_MDEUA:
4949c4a7965SKim Phillips 	case DESC_HDR_SEL0_MDEUB:
4959c4a7965SKim Phillips 		dev_err(dev, "MDEUISR 0x%08x_%08x\n",
4965fa7fa14SLEROY Christophe 			in_be32(priv->reg_mdeu + TALITOS_EUISR),
4975fa7fa14SLEROY Christophe 			in_be32(priv->reg_mdeu + TALITOS_EUISR_LO));
4989c4a7965SKim Phillips 		break;
4999c4a7965SKim Phillips 	case DESC_HDR_SEL0_RNG:
5009c4a7965SKim Phillips 		dev_err(dev, "RNGUISR 0x%08x_%08x\n",
5015fa7fa14SLEROY Christophe 			in_be32(priv->reg_rngu + TALITOS_ISR),
5025fa7fa14SLEROY Christophe 			in_be32(priv->reg_rngu + TALITOS_ISR_LO));
5039c4a7965SKim Phillips 		break;
5049c4a7965SKim Phillips 	case DESC_HDR_SEL0_PKEU:
5059c4a7965SKim Phillips 		dev_err(dev, "PKEUISR 0x%08x_%08x\n",
5065fa7fa14SLEROY Christophe 			in_be32(priv->reg_pkeu + TALITOS_EUISR),
5075fa7fa14SLEROY Christophe 			in_be32(priv->reg_pkeu + TALITOS_EUISR_LO));
5089c4a7965SKim Phillips 		break;
5099c4a7965SKim Phillips 	case DESC_HDR_SEL0_AESU:
5109c4a7965SKim Phillips 		dev_err(dev, "AESUISR 0x%08x_%08x\n",
5115fa7fa14SLEROY Christophe 			in_be32(priv->reg_aesu + TALITOS_EUISR),
5125fa7fa14SLEROY Christophe 			in_be32(priv->reg_aesu + TALITOS_EUISR_LO));
5139c4a7965SKim Phillips 		break;
5149c4a7965SKim Phillips 	case DESC_HDR_SEL0_CRCU:
5159c4a7965SKim Phillips 		dev_err(dev, "CRCUISR 0x%08x_%08x\n",
5165fa7fa14SLEROY Christophe 			in_be32(priv->reg_crcu + TALITOS_EUISR),
5175fa7fa14SLEROY Christophe 			in_be32(priv->reg_crcu + TALITOS_EUISR_LO));
5189c4a7965SKim Phillips 		break;
5199c4a7965SKim Phillips 	case DESC_HDR_SEL0_KEU:
5209c4a7965SKim Phillips 		dev_err(dev, "KEUISR 0x%08x_%08x\n",
5215fa7fa14SLEROY Christophe 			in_be32(priv->reg_pkeu + TALITOS_EUISR),
5225fa7fa14SLEROY Christophe 			in_be32(priv->reg_pkeu + TALITOS_EUISR_LO));
5239c4a7965SKim Phillips 		break;
5249c4a7965SKim Phillips 	}
5259c4a7965SKim Phillips 
5263e721aebSKim Phillips 	switch (desc_hdr & DESC_HDR_SEL1_MASK) {
5279c4a7965SKim Phillips 	case DESC_HDR_SEL1_MDEUA:
5289c4a7965SKim Phillips 	case DESC_HDR_SEL1_MDEUB:
5299c4a7965SKim Phillips 		dev_err(dev, "MDEUISR 0x%08x_%08x\n",
5305fa7fa14SLEROY Christophe 			in_be32(priv->reg_mdeu + TALITOS_EUISR),
5315fa7fa14SLEROY Christophe 			in_be32(priv->reg_mdeu + TALITOS_EUISR_LO));
5329c4a7965SKim Phillips 		break;
5339c4a7965SKim Phillips 	case DESC_HDR_SEL1_CRCU:
5349c4a7965SKim Phillips 		dev_err(dev, "CRCUISR 0x%08x_%08x\n",
5355fa7fa14SLEROY Christophe 			in_be32(priv->reg_crcu + TALITOS_EUISR),
5365fa7fa14SLEROY Christophe 			in_be32(priv->reg_crcu + TALITOS_EUISR_LO));
5379c4a7965SKim Phillips 		break;
5389c4a7965SKim Phillips 	}
5399c4a7965SKim Phillips 
5409c4a7965SKim Phillips 	for (i = 0; i < 8; i++)
5419c4a7965SKim Phillips 		dev_err(dev, "DESCBUF 0x%08x_%08x\n",
542ad42d5fcSKim Phillips 			in_be32(priv->chan[ch].reg + TALITOS_DESCBUF + 8*i),
543ad42d5fcSKim Phillips 			in_be32(priv->chan[ch].reg + TALITOS_DESCBUF_LO + 8*i));
5449c4a7965SKim Phillips }
5459c4a7965SKim Phillips 
5469c4a7965SKim Phillips /*
5479c4a7965SKim Phillips  * recover from error interrupts
5489c4a7965SKim Phillips  */
5495e718a09SKim Phillips static void talitos_error(struct device *dev, u32 isr, u32 isr_lo)
5509c4a7965SKim Phillips {
5519c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
5529c4a7965SKim Phillips 	unsigned int timeout = TALITOS_TIMEOUT;
553dd3c0987SLEROY Christophe 	int ch, error, reset_dev = 0;
55442e8b0d7SHoria Geant? 	u32 v_lo;
555dd3c0987SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
556dd3c0987SLEROY Christophe 	int reset_ch = is_sec1 ? 1 : 0; /* only SEC2 supports continuation */
5579c4a7965SKim Phillips 
5589c4a7965SKim Phillips 	for (ch = 0; ch < priv->num_channels; ch++) {
5599c4a7965SKim Phillips 		/* skip channels without errors */
560dd3c0987SLEROY Christophe 		if (is_sec1) {
561dd3c0987SLEROY Christophe 			/* bits 29, 31, 17, 19 */
562dd3c0987SLEROY Christophe 			if (!(isr & (1 << (29 + (ch & 1) * 2 - (ch & 2) * 6))))
563dd3c0987SLEROY Christophe 				continue;
564dd3c0987SLEROY Christophe 		} else {
5659c4a7965SKim Phillips 			if (!(isr & (1 << (ch * 2 + 1))))
5669c4a7965SKim Phillips 				continue;
567dd3c0987SLEROY Christophe 		}
5689c4a7965SKim Phillips 
5699c4a7965SKim Phillips 		error = -EINVAL;
5709c4a7965SKim Phillips 
571ad42d5fcSKim Phillips 		v_lo = in_be32(priv->chan[ch].reg + TALITOS_CCPSR_LO);
5729c4a7965SKim Phillips 
5739c4a7965SKim Phillips 		if (v_lo & TALITOS_CCPSR_LO_DOF) {
5749c4a7965SKim Phillips 			dev_err(dev, "double fetch fifo overflow error\n");
5759c4a7965SKim Phillips 			error = -EAGAIN;
5769c4a7965SKim Phillips 			reset_ch = 1;
5779c4a7965SKim Phillips 		}
5789c4a7965SKim Phillips 		if (v_lo & TALITOS_CCPSR_LO_SOF) {
5799c4a7965SKim Phillips 			/* h/w dropped descriptor */
5809c4a7965SKim Phillips 			dev_err(dev, "single fetch fifo overflow error\n");
5819c4a7965SKim Phillips 			error = -EAGAIN;
5829c4a7965SKim Phillips 		}
5839c4a7965SKim Phillips 		if (v_lo & TALITOS_CCPSR_LO_MDTE)
5849c4a7965SKim Phillips 			dev_err(dev, "master data transfer error\n");
5859c4a7965SKim Phillips 		if (v_lo & TALITOS_CCPSR_LO_SGDLZ)
5864d9b3a5bSColin Ian King 			dev_err(dev, is_sec1 ? "pointer not complete error\n"
587dd3c0987SLEROY Christophe 					     : "s/g data length zero error\n");
5889c4a7965SKim Phillips 		if (v_lo & TALITOS_CCPSR_LO_FPZ)
589dd3c0987SLEROY Christophe 			dev_err(dev, is_sec1 ? "parity error\n"
590dd3c0987SLEROY Christophe 					     : "fetch pointer zero error\n");
5919c4a7965SKim Phillips 		if (v_lo & TALITOS_CCPSR_LO_IDH)
5929c4a7965SKim Phillips 			dev_err(dev, "illegal descriptor header error\n");
5939c4a7965SKim Phillips 		if (v_lo & TALITOS_CCPSR_LO_IEU)
594dd3c0987SLEROY Christophe 			dev_err(dev, is_sec1 ? "static assignment error\n"
595dd3c0987SLEROY Christophe 					     : "invalid exec unit error\n");
5969c4a7965SKim Phillips 		if (v_lo & TALITOS_CCPSR_LO_EU)
5973e721aebSKim Phillips 			report_eu_error(dev, ch, current_desc_hdr(dev, ch));
598dd3c0987SLEROY Christophe 		if (!is_sec1) {
5999c4a7965SKim Phillips 			if (v_lo & TALITOS_CCPSR_LO_GB)
6009c4a7965SKim Phillips 				dev_err(dev, "gather boundary error\n");
6019c4a7965SKim Phillips 			if (v_lo & TALITOS_CCPSR_LO_GRL)
6029c4a7965SKim Phillips 				dev_err(dev, "gather return/length error\n");
6039c4a7965SKim Phillips 			if (v_lo & TALITOS_CCPSR_LO_SB)
6049c4a7965SKim Phillips 				dev_err(dev, "scatter boundary error\n");
6059c4a7965SKim Phillips 			if (v_lo & TALITOS_CCPSR_LO_SRL)
6069c4a7965SKim Phillips 				dev_err(dev, "scatter return/length error\n");
607dd3c0987SLEROY Christophe 		}
6089c4a7965SKim Phillips 
6099c4a7965SKim Phillips 		flush_channel(dev, ch, error, reset_ch);
6109c4a7965SKim Phillips 
6119c4a7965SKim Phillips 		if (reset_ch) {
6129c4a7965SKim Phillips 			reset_channel(dev, ch);
6139c4a7965SKim Phillips 		} else {
614ad42d5fcSKim Phillips 			setbits32(priv->chan[ch].reg + TALITOS_CCCR,
615dd3c0987SLEROY Christophe 				  TALITOS2_CCCR_CONT);
616ad42d5fcSKim Phillips 			setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO, 0);
617ad42d5fcSKim Phillips 			while ((in_be32(priv->chan[ch].reg + TALITOS_CCCR) &
618dd3c0987SLEROY Christophe 			       TALITOS2_CCCR_CONT) && --timeout)
6199c4a7965SKim Phillips 				cpu_relax();
6209c4a7965SKim Phillips 			if (timeout == 0) {
6219c4a7965SKim Phillips 				dev_err(dev, "failed to restart channel %d\n",
6229c4a7965SKim Phillips 					ch);
6239c4a7965SKim Phillips 				reset_dev = 1;
6249c4a7965SKim Phillips 			}
6259c4a7965SKim Phillips 		}
6269c4a7965SKim Phillips 	}
627dd3c0987SLEROY Christophe 	if (reset_dev || (is_sec1 && isr & ~TALITOS1_ISR_4CHERR) ||
628dd3c0987SLEROY Christophe 	    (!is_sec1 && isr & ~TALITOS2_ISR_4CHERR) || isr_lo) {
629dd3c0987SLEROY Christophe 		if (is_sec1 && (isr_lo & TALITOS1_ISR_TEA_ERR))
630dd3c0987SLEROY Christophe 			dev_err(dev, "TEA error: ISR 0x%08x_%08x\n",
631dd3c0987SLEROY Christophe 				isr, isr_lo);
632dd3c0987SLEROY Christophe 		else
633dd3c0987SLEROY Christophe 			dev_err(dev, "done overflow, internal time out, or "
634dd3c0987SLEROY Christophe 				"rngu error: ISR 0x%08x_%08x\n", isr, isr_lo);
6359c4a7965SKim Phillips 
6369c4a7965SKim Phillips 		/* purge request queues */
6379c4a7965SKim Phillips 		for (ch = 0; ch < priv->num_channels; ch++)
6389c4a7965SKim Phillips 			flush_channel(dev, ch, -EIO, 1);
6399c4a7965SKim Phillips 
6409c4a7965SKim Phillips 		/* reset and reinitialize the device */
6419c4a7965SKim Phillips 		init_device(dev);
6429c4a7965SKim Phillips 	}
6439c4a7965SKim Phillips }
6449c4a7965SKim Phillips 
645dd3c0987SLEROY Christophe #define DEF_TALITOS1_INTERRUPT(name, ch_done_mask, ch_err_mask, tlet)	       \
646dd3c0987SLEROY Christophe static irqreturn_t talitos1_interrupt_##name(int irq, void *data)	       \
647dd3c0987SLEROY Christophe {									       \
648dd3c0987SLEROY Christophe 	struct device *dev = data;					       \
649dd3c0987SLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);		       \
650dd3c0987SLEROY Christophe 	u32 isr, isr_lo;						       \
651dd3c0987SLEROY Christophe 	unsigned long flags;						       \
652dd3c0987SLEROY Christophe 									       \
653dd3c0987SLEROY Christophe 	spin_lock_irqsave(&priv->reg_lock, flags);			       \
654dd3c0987SLEROY Christophe 	isr = in_be32(priv->reg + TALITOS_ISR);				       \
655dd3c0987SLEROY Christophe 	isr_lo = in_be32(priv->reg + TALITOS_ISR_LO);			       \
656dd3c0987SLEROY Christophe 	/* Acknowledge interrupt */					       \
657dd3c0987SLEROY Christophe 	out_be32(priv->reg + TALITOS_ICR, isr & (ch_done_mask | ch_err_mask)); \
658dd3c0987SLEROY Christophe 	out_be32(priv->reg + TALITOS_ICR_LO, isr_lo);			       \
659dd3c0987SLEROY Christophe 									       \
660dd3c0987SLEROY Christophe 	if (unlikely(isr & ch_err_mask || isr_lo & TALITOS1_IMR_LO_INIT)) {    \
661dd3c0987SLEROY Christophe 		spin_unlock_irqrestore(&priv->reg_lock, flags);		       \
662dd3c0987SLEROY Christophe 		talitos_error(dev, isr & ch_err_mask, isr_lo);		       \
663dd3c0987SLEROY Christophe 	}								       \
664dd3c0987SLEROY Christophe 	else {								       \
665dd3c0987SLEROY Christophe 		if (likely(isr & ch_done_mask)) {			       \
666dd3c0987SLEROY Christophe 			/* mask further done interrupts. */		       \
667dd3c0987SLEROY Christophe 			setbits32(priv->reg + TALITOS_IMR, ch_done_mask);      \
668dd3c0987SLEROY Christophe 			/* done_task will unmask done interrupts at exit */    \
669dd3c0987SLEROY Christophe 			tasklet_schedule(&priv->done_task[tlet]);	       \
670dd3c0987SLEROY Christophe 		}							       \
671dd3c0987SLEROY Christophe 		spin_unlock_irqrestore(&priv->reg_lock, flags);		       \
672dd3c0987SLEROY Christophe 	}								       \
673dd3c0987SLEROY Christophe 									       \
674dd3c0987SLEROY Christophe 	return (isr & (ch_done_mask | ch_err_mask) || isr_lo) ? IRQ_HANDLED :  \
675dd3c0987SLEROY Christophe 								IRQ_NONE;      \
676dd3c0987SLEROY Christophe }
677dd3c0987SLEROY Christophe 
678dd3c0987SLEROY Christophe DEF_TALITOS1_INTERRUPT(4ch, TALITOS1_ISR_4CHDONE, TALITOS1_ISR_4CHERR, 0)
679dd3c0987SLEROY Christophe 
680dd3c0987SLEROY Christophe #define DEF_TALITOS2_INTERRUPT(name, ch_done_mask, ch_err_mask, tlet)	       \
681dd3c0987SLEROY Christophe static irqreturn_t talitos2_interrupt_##name(int irq, void *data)	       \
682c3e337f8SKim Phillips {									       \
683c3e337f8SKim Phillips 	struct device *dev = data;					       \
684c3e337f8SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);		       \
685c3e337f8SKim Phillips 	u32 isr, isr_lo;						       \
686511d63cbSHoria Geanta 	unsigned long flags;						       \
687c3e337f8SKim Phillips 									       \
688511d63cbSHoria Geanta 	spin_lock_irqsave(&priv->reg_lock, flags);			       \
689c3e337f8SKim Phillips 	isr = in_be32(priv->reg + TALITOS_ISR);				       \
690c3e337f8SKim Phillips 	isr_lo = in_be32(priv->reg + TALITOS_ISR_LO);			       \
691c3e337f8SKim Phillips 	/* Acknowledge interrupt */					       \
692c3e337f8SKim Phillips 	out_be32(priv->reg + TALITOS_ICR, isr & (ch_done_mask | ch_err_mask)); \
693c3e337f8SKim Phillips 	out_be32(priv->reg + TALITOS_ICR_LO, isr_lo);			       \
694c3e337f8SKim Phillips 									       \
695511d63cbSHoria Geanta 	if (unlikely(isr & ch_err_mask || isr_lo)) {			       \
696511d63cbSHoria Geanta 		spin_unlock_irqrestore(&priv->reg_lock, flags);		       \
697511d63cbSHoria Geanta 		talitos_error(dev, isr & ch_err_mask, isr_lo);		       \
698511d63cbSHoria Geanta 	}								       \
699511d63cbSHoria Geanta 	else {								       \
700c3e337f8SKim Phillips 		if (likely(isr & ch_done_mask)) {			       \
701c3e337f8SKim Phillips 			/* mask further done interrupts. */		       \
702c3e337f8SKim Phillips 			clrbits32(priv->reg + TALITOS_IMR, ch_done_mask);      \
703c3e337f8SKim Phillips 			/* done_task will unmask done interrupts at exit */    \
704c3e337f8SKim Phillips 			tasklet_schedule(&priv->done_task[tlet]);	       \
705c3e337f8SKim Phillips 		}							       \
706511d63cbSHoria Geanta 		spin_unlock_irqrestore(&priv->reg_lock, flags);		       \
707511d63cbSHoria Geanta 	}								       \
708c3e337f8SKim Phillips 									       \
709c3e337f8SKim Phillips 	return (isr & (ch_done_mask | ch_err_mask) || isr_lo) ? IRQ_HANDLED :  \
710c3e337f8SKim Phillips 								IRQ_NONE;      \
7111c2e8811SLee Nipper }
712dd3c0987SLEROY Christophe 
713dd3c0987SLEROY Christophe DEF_TALITOS2_INTERRUPT(4ch, TALITOS2_ISR_4CHDONE, TALITOS2_ISR_4CHERR, 0)
714dd3c0987SLEROY Christophe DEF_TALITOS2_INTERRUPT(ch0_2, TALITOS2_ISR_CH_0_2_DONE, TALITOS2_ISR_CH_0_2_ERR,
715dd3c0987SLEROY Christophe 		       0)
716dd3c0987SLEROY Christophe DEF_TALITOS2_INTERRUPT(ch1_3, TALITOS2_ISR_CH_1_3_DONE, TALITOS2_ISR_CH_1_3_ERR,
717dd3c0987SLEROY Christophe 		       1)
7189c4a7965SKim Phillips 
7199c4a7965SKim Phillips /*
7209c4a7965SKim Phillips  * hwrng
7219c4a7965SKim Phillips  */
7229c4a7965SKim Phillips static int talitos_rng_data_present(struct hwrng *rng, int wait)
7239c4a7965SKim Phillips {
7249c4a7965SKim Phillips 	struct device *dev = (struct device *)rng->priv;
7259c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
7269c4a7965SKim Phillips 	u32 ofl;
7279c4a7965SKim Phillips 	int i;
7289c4a7965SKim Phillips 
7299c4a7965SKim Phillips 	for (i = 0; i < 20; i++) {
7305fa7fa14SLEROY Christophe 		ofl = in_be32(priv->reg_rngu + TALITOS_EUSR_LO) &
7319c4a7965SKim Phillips 		      TALITOS_RNGUSR_LO_OFL;
7329c4a7965SKim Phillips 		if (ofl || !wait)
7339c4a7965SKim Phillips 			break;
7349c4a7965SKim Phillips 		udelay(10);
7359c4a7965SKim Phillips 	}
7369c4a7965SKim Phillips 
7379c4a7965SKim Phillips 	return !!ofl;
7389c4a7965SKim Phillips }
7399c4a7965SKim Phillips 
7409c4a7965SKim Phillips static int talitos_rng_data_read(struct hwrng *rng, u32 *data)
7419c4a7965SKim Phillips {
7429c4a7965SKim Phillips 	struct device *dev = (struct device *)rng->priv;
7439c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
7449c4a7965SKim Phillips 
7459c4a7965SKim Phillips 	/* rng fifo requires 64-bit accesses */
7465fa7fa14SLEROY Christophe 	*data = in_be32(priv->reg_rngu + TALITOS_EU_FIFO);
7475fa7fa14SLEROY Christophe 	*data = in_be32(priv->reg_rngu + TALITOS_EU_FIFO_LO);
7489c4a7965SKim Phillips 
7499c4a7965SKim Phillips 	return sizeof(u32);
7509c4a7965SKim Phillips }
7519c4a7965SKim Phillips 
7529c4a7965SKim Phillips static int talitos_rng_init(struct hwrng *rng)
7539c4a7965SKim Phillips {
7549c4a7965SKim Phillips 	struct device *dev = (struct device *)rng->priv;
7559c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
7569c4a7965SKim Phillips 	unsigned int timeout = TALITOS_TIMEOUT;
7579c4a7965SKim Phillips 
7585fa7fa14SLEROY Christophe 	setbits32(priv->reg_rngu + TALITOS_EURCR_LO, TALITOS_RNGURCR_LO_SR);
7595fa7fa14SLEROY Christophe 	while (!(in_be32(priv->reg_rngu + TALITOS_EUSR_LO)
7605fa7fa14SLEROY Christophe 		 & TALITOS_RNGUSR_LO_RD)
7619c4a7965SKim Phillips 	       && --timeout)
7629c4a7965SKim Phillips 		cpu_relax();
7639c4a7965SKim Phillips 	if (timeout == 0) {
7649c4a7965SKim Phillips 		dev_err(dev, "failed to reset rng hw\n");
7659c4a7965SKim Phillips 		return -ENODEV;
7669c4a7965SKim Phillips 	}
7679c4a7965SKim Phillips 
7689c4a7965SKim Phillips 	/* start generating */
7695fa7fa14SLEROY Christophe 	setbits32(priv->reg_rngu + TALITOS_EUDSR_LO, 0);
7709c4a7965SKim Phillips 
7719c4a7965SKim Phillips 	return 0;
7729c4a7965SKim Phillips }
7739c4a7965SKim Phillips 
7749c4a7965SKim Phillips static int talitos_register_rng(struct device *dev)
7759c4a7965SKim Phillips {
7769c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
77735a3bb3dSAaron Sierra 	int err;
7789c4a7965SKim Phillips 
7799c4a7965SKim Phillips 	priv->rng.name		= dev_driver_string(dev),
7809c4a7965SKim Phillips 	priv->rng.init		= talitos_rng_init,
7819c4a7965SKim Phillips 	priv->rng.data_present	= talitos_rng_data_present,
7829c4a7965SKim Phillips 	priv->rng.data_read	= talitos_rng_data_read,
7839c4a7965SKim Phillips 	priv->rng.priv		= (unsigned long)dev;
7849c4a7965SKim Phillips 
78535a3bb3dSAaron Sierra 	err = hwrng_register(&priv->rng);
78635a3bb3dSAaron Sierra 	if (!err)
78735a3bb3dSAaron Sierra 		priv->rng_registered = true;
78835a3bb3dSAaron Sierra 
78935a3bb3dSAaron Sierra 	return err;
7909c4a7965SKim Phillips }
7919c4a7965SKim Phillips 
7929c4a7965SKim Phillips static void talitos_unregister_rng(struct device *dev)
7939c4a7965SKim Phillips {
7949c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
7959c4a7965SKim Phillips 
79635a3bb3dSAaron Sierra 	if (!priv->rng_registered)
79735a3bb3dSAaron Sierra 		return;
79835a3bb3dSAaron Sierra 
7999c4a7965SKim Phillips 	hwrng_unregister(&priv->rng);
80035a3bb3dSAaron Sierra 	priv->rng_registered = false;
8019c4a7965SKim Phillips }
8029c4a7965SKim Phillips 
8039c4a7965SKim Phillips /*
8049c4a7965SKim Phillips  * crypto alg
8059c4a7965SKim Phillips  */
8069c4a7965SKim Phillips #define TALITOS_CRA_PRIORITY		3000
8077405c8d7SLEROY Christophe /*
8087405c8d7SLEROY Christophe  * Defines a priority for doing AEAD with descriptors type
8097405c8d7SLEROY Christophe  * HMAC_SNOOP_NO_AFEA (HSNA) instead of type IPSEC_ESP
8107405c8d7SLEROY Christophe  */
8117405c8d7SLEROY Christophe #define TALITOS_CRA_PRIORITY_AEAD_HSNA	(TALITOS_CRA_PRIORITY - 1)
81203d2c511SMartin Hicks #define TALITOS_MAX_KEY_SIZE		(AES_MAX_KEY_SIZE + SHA512_BLOCK_SIZE)
8133952f17eSLee Nipper #define TALITOS_MAX_IV_LENGTH		16 /* max of AES_BLOCK_SIZE, DES3_EDE_BLOCK_SIZE */
81470bcaca7SLee Nipper 
8159c4a7965SKim Phillips struct talitos_ctx {
8169c4a7965SKim Phillips 	struct device *dev;
8175228f0f7SKim Phillips 	int ch;
8189c4a7965SKim Phillips 	__be32 desc_hdr_template;
8199c4a7965SKim Phillips 	u8 key[TALITOS_MAX_KEY_SIZE];
82070bcaca7SLee Nipper 	u8 iv[TALITOS_MAX_IV_LENGTH];
8219c4a7965SKim Phillips 	unsigned int keylen;
8229c4a7965SKim Phillips 	unsigned int enckeylen;
8239c4a7965SKim Phillips 	unsigned int authkeylen;
8249c4a7965SKim Phillips };
8259c4a7965SKim Phillips 
826497f2e6bSLee Nipper #define HASH_MAX_BLOCK_SIZE		SHA512_BLOCK_SIZE
827497f2e6bSLee Nipper #define TALITOS_MDEU_MAX_CONTEXT_SIZE	TALITOS_MDEU_CONTEXT_SIZE_SHA384_SHA512
828497f2e6bSLee Nipper 
829497f2e6bSLee Nipper struct talitos_ahash_req_ctx {
83060f208d7SKim Phillips 	u32 hw_context[TALITOS_MDEU_MAX_CONTEXT_SIZE / sizeof(u32)];
831497f2e6bSLee Nipper 	unsigned int hw_context_size;
832497f2e6bSLee Nipper 	u8 buf[HASH_MAX_BLOCK_SIZE];
833497f2e6bSLee Nipper 	u8 bufnext[HASH_MAX_BLOCK_SIZE];
83460f208d7SKim Phillips 	unsigned int swinit;
835497f2e6bSLee Nipper 	unsigned int first;
836497f2e6bSLee Nipper 	unsigned int last;
837497f2e6bSLee Nipper 	unsigned int to_hash_later;
83842e8b0d7SHoria Geant? 	unsigned int nbuf;
839497f2e6bSLee Nipper 	struct scatterlist bufsl[2];
840497f2e6bSLee Nipper 	struct scatterlist *psrc;
841497f2e6bSLee Nipper };
842497f2e6bSLee Nipper 
8433639ca84SHoria Geant? struct talitos_export_state {
8443639ca84SHoria Geant? 	u32 hw_context[TALITOS_MDEU_MAX_CONTEXT_SIZE / sizeof(u32)];
8453639ca84SHoria Geant? 	u8 buf[HASH_MAX_BLOCK_SIZE];
8463639ca84SHoria Geant? 	unsigned int swinit;
8473639ca84SHoria Geant? 	unsigned int first;
8483639ca84SHoria Geant? 	unsigned int last;
8493639ca84SHoria Geant? 	unsigned int to_hash_later;
8503639ca84SHoria Geant? 	unsigned int nbuf;
8513639ca84SHoria Geant? };
8523639ca84SHoria Geant? 
85356af8cd4SLee Nipper static int aead_setkey(struct crypto_aead *authenc,
8549c4a7965SKim Phillips 		       const u8 *key, unsigned int keylen)
8559c4a7965SKim Phillips {
8569c4a7965SKim Phillips 	struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
857c306a98dSMathias Krause 	struct crypto_authenc_keys keys;
8589c4a7965SKim Phillips 
859c306a98dSMathias Krause 	if (crypto_authenc_extractkeys(&keys, key, keylen) != 0)
8609c4a7965SKim Phillips 		goto badkey;
8619c4a7965SKim Phillips 
862c306a98dSMathias Krause 	if (keys.authkeylen + keys.enckeylen > TALITOS_MAX_KEY_SIZE)
8639c4a7965SKim Phillips 		goto badkey;
8649c4a7965SKim Phillips 
865c306a98dSMathias Krause 	memcpy(ctx->key, keys.authkey, keys.authkeylen);
866c306a98dSMathias Krause 	memcpy(&ctx->key[keys.authkeylen], keys.enckey, keys.enckeylen);
8679c4a7965SKim Phillips 
868c306a98dSMathias Krause 	ctx->keylen = keys.authkeylen + keys.enckeylen;
869c306a98dSMathias Krause 	ctx->enckeylen = keys.enckeylen;
870c306a98dSMathias Krause 	ctx->authkeylen = keys.authkeylen;
8719c4a7965SKim Phillips 
8729c4a7965SKim Phillips 	return 0;
8739c4a7965SKim Phillips 
8749c4a7965SKim Phillips badkey:
8759c4a7965SKim Phillips 	crypto_aead_set_flags(authenc, CRYPTO_TFM_RES_BAD_KEY_LEN);
8769c4a7965SKim Phillips 	return -EINVAL;
8779c4a7965SKim Phillips }
8789c4a7965SKim Phillips 
8799c4a7965SKim Phillips /*
88056af8cd4SLee Nipper  * talitos_edesc - s/w-extended descriptor
8819c4a7965SKim Phillips  * @src_nents: number of segments in input scatterlist
8829c4a7965SKim Phillips  * @dst_nents: number of segments in output scatterlist
883aeb4c132SHerbert Xu  * @icv_ool: whether ICV is out-of-line
88479fd31d3SHoria Geanta  * @iv_dma: dma address of iv for checking continuity and link table
8859c4a7965SKim Phillips  * @dma_len: length of dma mapped link_tbl space
8866f65f6acSLEROY Christophe  * @dma_link_tbl: bus physical address of link_tbl/buf
8879c4a7965SKim Phillips  * @desc: h/w descriptor
8886f65f6acSLEROY Christophe  * @link_tbl: input and output h/w link tables (if {src,dst}_nents > 1) (SEC2)
8896f65f6acSLEROY Christophe  * @buf: input and output buffeur (if {src,dst}_nents > 1) (SEC1)
8909c4a7965SKim Phillips  *
8919c4a7965SKim Phillips  * if decrypting (with authcheck), or either one of src_nents or dst_nents
8929c4a7965SKim Phillips  * is greater than 1, an integrity check value is concatenated to the end
8939c4a7965SKim Phillips  * of link_tbl data
8949c4a7965SKim Phillips  */
89556af8cd4SLee Nipper struct talitos_edesc {
8969c4a7965SKim Phillips 	int src_nents;
8979c4a7965SKim Phillips 	int dst_nents;
898aeb4c132SHerbert Xu 	bool icv_ool;
89979fd31d3SHoria Geanta 	dma_addr_t iv_dma;
9009c4a7965SKim Phillips 	int dma_len;
9019c4a7965SKim Phillips 	dma_addr_t dma_link_tbl;
9029c4a7965SKim Phillips 	struct talitos_desc desc;
9036f65f6acSLEROY Christophe 	union {
9049c4a7965SKim Phillips 		struct talitos_ptr link_tbl[0];
9056f65f6acSLEROY Christophe 		u8 buf[0];
9066f65f6acSLEROY Christophe 	};
9079c4a7965SKim Phillips };
9089c4a7965SKim Phillips 
9094de9d0b5SLee Nipper static void talitos_sg_unmap(struct device *dev,
9104de9d0b5SLee Nipper 			     struct talitos_edesc *edesc,
9114de9d0b5SLee Nipper 			     struct scatterlist *src,
9126a1e8d14SLEROY Christophe 			     struct scatterlist *dst,
9136a1e8d14SLEROY Christophe 			     unsigned int len, unsigned int offset)
914246a87cdSLEROY Christophe {
915246a87cdSLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
916246a87cdSLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
9176a1e8d14SLEROY Christophe 	unsigned int src_nents = edesc->src_nents ? : 1;
9186a1e8d14SLEROY Christophe 	unsigned int dst_nents = edesc->dst_nents ? : 1;
919246a87cdSLEROY Christophe 
9206a1e8d14SLEROY Christophe 	if (is_sec1 && dst && dst_nents > 1) {
9216a1e8d14SLEROY Christophe 		dma_sync_single_for_device(dev, edesc->dma_link_tbl + offset,
922246a87cdSLEROY Christophe 					   len, DMA_FROM_DEVICE);
9236a1e8d14SLEROY Christophe 		sg_pcopy_from_buffer(dst, dst_nents, edesc->buf + offset, len,
9246a1e8d14SLEROY Christophe 				     offset);
925246a87cdSLEROY Christophe 	}
9266a1e8d14SLEROY Christophe 	if (src != dst) {
9276a1e8d14SLEROY Christophe 		if (src_nents == 1 || !is_sec1)
9286a1e8d14SLEROY Christophe 			dma_unmap_sg(dev, src, src_nents, DMA_TO_DEVICE);
9296a1e8d14SLEROY Christophe 
9306a1e8d14SLEROY Christophe 		if (dst && (dst_nents == 1 || !is_sec1))
9316a1e8d14SLEROY Christophe 			dma_unmap_sg(dev, dst, dst_nents, DMA_FROM_DEVICE);
9326a1e8d14SLEROY Christophe 	} else if (src_nents == 1 || !is_sec1) {
9336a1e8d14SLEROY Christophe 		dma_unmap_sg(dev, src, src_nents, DMA_BIDIRECTIONAL);
934246a87cdSLEROY Christophe 	}
935246a87cdSLEROY Christophe }
936246a87cdSLEROY Christophe 
9379c4a7965SKim Phillips static void ipsec_esp_unmap(struct device *dev,
93856af8cd4SLee Nipper 			    struct talitos_edesc *edesc,
9399c4a7965SKim Phillips 			    struct aead_request *areq)
9409c4a7965SKim Phillips {
941549bd8bcSLEROY Christophe 	struct crypto_aead *aead = crypto_aead_reqtfm(areq);
942549bd8bcSLEROY Christophe 	struct talitos_ctx *ctx = crypto_aead_ctx(aead);
943549bd8bcSLEROY Christophe 	unsigned int ivsize = crypto_aead_ivsize(aead);
944549bd8bcSLEROY Christophe 
945549bd8bcSLEROY Christophe 	if (edesc->desc.hdr & DESC_HDR_TYPE_IPSEC_ESP)
946549bd8bcSLEROY Christophe 		unmap_single_talitos_ptr(dev, &edesc->desc.ptr[6],
947549bd8bcSLEROY Christophe 					 DMA_FROM_DEVICE);
9489c4a7965SKim Phillips 	unmap_single_talitos_ptr(dev, &edesc->desc.ptr[3], DMA_TO_DEVICE);
9499c4a7965SKim Phillips 	unmap_single_talitos_ptr(dev, &edesc->desc.ptr[2], DMA_TO_DEVICE);
9509c4a7965SKim Phillips 	unmap_single_talitos_ptr(dev, &edesc->desc.ptr[0], DMA_TO_DEVICE);
9519c4a7965SKim Phillips 
9526a1e8d14SLEROY Christophe 	talitos_sg_unmap(dev, edesc, areq->src, areq->dst, areq->cryptlen,
9536a1e8d14SLEROY Christophe 			 areq->assoclen);
9549c4a7965SKim Phillips 
9559c4a7965SKim Phillips 	if (edesc->dma_len)
9569c4a7965SKim Phillips 		dma_unmap_single(dev, edesc->dma_link_tbl, edesc->dma_len,
9579c4a7965SKim Phillips 				 DMA_BIDIRECTIONAL);
958549bd8bcSLEROY Christophe 
959549bd8bcSLEROY Christophe 	if (!(edesc->desc.hdr & DESC_HDR_TYPE_IPSEC_ESP)) {
960549bd8bcSLEROY Christophe 		unsigned int dst_nents = edesc->dst_nents ? : 1;
961549bd8bcSLEROY Christophe 
962549bd8bcSLEROY Christophe 		sg_pcopy_to_buffer(areq->dst, dst_nents, ctx->iv, ivsize,
963549bd8bcSLEROY Christophe 				   areq->assoclen + areq->cryptlen - ivsize);
964549bd8bcSLEROY Christophe 	}
9659c4a7965SKim Phillips }
9669c4a7965SKim Phillips 
9679c4a7965SKim Phillips /*
9689c4a7965SKim Phillips  * ipsec_esp descriptor callbacks
9699c4a7965SKim Phillips  */
9709c4a7965SKim Phillips static void ipsec_esp_encrypt_done(struct device *dev,
9719c4a7965SKim Phillips 				   struct talitos_desc *desc, void *context,
9729c4a7965SKim Phillips 				   int err)
9739c4a7965SKim Phillips {
974549bd8bcSLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
975549bd8bcSLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
9769c4a7965SKim Phillips 	struct aead_request *areq = context;
9779c4a7965SKim Phillips 	struct crypto_aead *authenc = crypto_aead_reqtfm(areq);
978aeb4c132SHerbert Xu 	unsigned int authsize = crypto_aead_authsize(authenc);
97919bbbc63SKim Phillips 	struct talitos_edesc *edesc;
9809c4a7965SKim Phillips 	struct scatterlist *sg;
9819c4a7965SKim Phillips 	void *icvdata;
9829c4a7965SKim Phillips 
98319bbbc63SKim Phillips 	edesc = container_of(desc, struct talitos_edesc, desc);
98419bbbc63SKim Phillips 
9859c4a7965SKim Phillips 	ipsec_esp_unmap(dev, edesc, areq);
9869c4a7965SKim Phillips 
9879c4a7965SKim Phillips 	/* copy the generated ICV to dst */
988aeb4c132SHerbert Xu 	if (edesc->icv_ool) {
989549bd8bcSLEROY Christophe 		if (is_sec1)
990549bd8bcSLEROY Christophe 			icvdata = edesc->buf + areq->assoclen + areq->cryptlen;
991549bd8bcSLEROY Christophe 		else
9929c4a7965SKim Phillips 			icvdata = &edesc->link_tbl[edesc->src_nents +
993aeb4c132SHerbert Xu 						   edesc->dst_nents + 2];
9949c4a7965SKim Phillips 		sg = sg_last(areq->dst, edesc->dst_nents);
995aeb4c132SHerbert Xu 		memcpy((char *)sg_virt(sg) + sg->length - authsize,
996aeb4c132SHerbert Xu 		       icvdata, authsize);
9979c4a7965SKim Phillips 	}
9989c4a7965SKim Phillips 
9999c4a7965SKim Phillips 	kfree(edesc);
10009c4a7965SKim Phillips 
10019c4a7965SKim Phillips 	aead_request_complete(areq, err);
10029c4a7965SKim Phillips }
10039c4a7965SKim Phillips 
1004fe5720e2SKim Phillips static void ipsec_esp_decrypt_swauth_done(struct device *dev,
1005e938e465SKim Phillips 					  struct talitos_desc *desc,
1006e938e465SKim Phillips 					  void *context, int err)
10079c4a7965SKim Phillips {
10089c4a7965SKim Phillips 	struct aead_request *req = context;
10099c4a7965SKim Phillips 	struct crypto_aead *authenc = crypto_aead_reqtfm(req);
1010aeb4c132SHerbert Xu 	unsigned int authsize = crypto_aead_authsize(authenc);
101119bbbc63SKim Phillips 	struct talitos_edesc *edesc;
10129c4a7965SKim Phillips 	struct scatterlist *sg;
1013aeb4c132SHerbert Xu 	char *oicv, *icv;
1014549bd8bcSLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
1015549bd8bcSLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
10169c4a7965SKim Phillips 
101719bbbc63SKim Phillips 	edesc = container_of(desc, struct talitos_edesc, desc);
101819bbbc63SKim Phillips 
10199c4a7965SKim Phillips 	ipsec_esp_unmap(dev, edesc, req);
10209c4a7965SKim Phillips 
10219c4a7965SKim Phillips 	if (!err) {
10229c4a7965SKim Phillips 		/* auth check */
10239c4a7965SKim Phillips 		sg = sg_last(req->dst, edesc->dst_nents ? : 1);
1024aeb4c132SHerbert Xu 		icv = (char *)sg_virt(sg) + sg->length - authsize;
1025aeb4c132SHerbert Xu 
1026aeb4c132SHerbert Xu 		if (edesc->dma_len) {
1027549bd8bcSLEROY Christophe 			if (is_sec1)
1028549bd8bcSLEROY Christophe 				oicv = (char *)&edesc->dma_link_tbl +
1029549bd8bcSLEROY Christophe 					       req->assoclen + req->cryptlen;
1030549bd8bcSLEROY Christophe 			else
1031549bd8bcSLEROY Christophe 				oicv = (char *)
1032549bd8bcSLEROY Christophe 				       &edesc->link_tbl[edesc->src_nents +
1033aeb4c132SHerbert Xu 							edesc->dst_nents + 2];
1034aeb4c132SHerbert Xu 			if (edesc->icv_ool)
1035aeb4c132SHerbert Xu 				icv = oicv + authsize;
1036aeb4c132SHerbert Xu 		} else
1037aeb4c132SHerbert Xu 			oicv = (char *)&edesc->link_tbl[0];
1038aeb4c132SHerbert Xu 
103979960943SDavid Gstir 		err = crypto_memneq(oicv, icv, authsize) ? -EBADMSG : 0;
10409c4a7965SKim Phillips 	}
10419c4a7965SKim Phillips 
10429c4a7965SKim Phillips 	kfree(edesc);
10439c4a7965SKim Phillips 
10449c4a7965SKim Phillips 	aead_request_complete(req, err);
10459c4a7965SKim Phillips }
10469c4a7965SKim Phillips 
1047fe5720e2SKim Phillips static void ipsec_esp_decrypt_hwauth_done(struct device *dev,
1048e938e465SKim Phillips 					  struct talitos_desc *desc,
1049e938e465SKim Phillips 					  void *context, int err)
1050fe5720e2SKim Phillips {
1051fe5720e2SKim Phillips 	struct aead_request *req = context;
105219bbbc63SKim Phillips 	struct talitos_edesc *edesc;
105319bbbc63SKim Phillips 
105419bbbc63SKim Phillips 	edesc = container_of(desc, struct talitos_edesc, desc);
1055fe5720e2SKim Phillips 
1056fe5720e2SKim Phillips 	ipsec_esp_unmap(dev, edesc, req);
1057fe5720e2SKim Phillips 
1058fe5720e2SKim Phillips 	/* check ICV auth status */
1059e938e465SKim Phillips 	if (!err && ((desc->hdr_lo & DESC_HDR_LO_ICCR1_MASK) !=
1060e938e465SKim Phillips 		     DESC_HDR_LO_ICCR1_PASS))
1061fe5720e2SKim Phillips 		err = -EBADMSG;
1062fe5720e2SKim Phillips 
1063fe5720e2SKim Phillips 	kfree(edesc);
1064fe5720e2SKim Phillips 
1065fe5720e2SKim Phillips 	aead_request_complete(req, err);
1066fe5720e2SKim Phillips }
1067fe5720e2SKim Phillips 
10689c4a7965SKim Phillips /*
10699c4a7965SKim Phillips  * convert scatterlist to SEC h/w link table format
10709c4a7965SKim Phillips  * stop at cryptlen bytes
10719c4a7965SKim Phillips  */
1072aeb4c132SHerbert Xu static int sg_to_link_tbl_offset(struct scatterlist *sg, int sg_count,
1073aeb4c132SHerbert Xu 				 unsigned int offset, int cryptlen,
1074aeb4c132SHerbert Xu 				 struct talitos_ptr *link_tbl_ptr)
10759c4a7965SKim Phillips {
107670bcaca7SLee Nipper 	int n_sg = sg_count;
1077aeb4c132SHerbert Xu 	int count = 0;
107870bcaca7SLee Nipper 
1079aeb4c132SHerbert Xu 	while (cryptlen && sg && n_sg--) {
1080aeb4c132SHerbert Xu 		unsigned int len = sg_dma_len(sg);
1081aeb4c132SHerbert Xu 
1082aeb4c132SHerbert Xu 		if (offset >= len) {
1083aeb4c132SHerbert Xu 			offset -= len;
1084aeb4c132SHerbert Xu 			goto next;
1085aeb4c132SHerbert Xu 		}
1086aeb4c132SHerbert Xu 
1087aeb4c132SHerbert Xu 		len -= offset;
1088aeb4c132SHerbert Xu 
1089aeb4c132SHerbert Xu 		if (len > cryptlen)
1090aeb4c132SHerbert Xu 			len = cryptlen;
1091aeb4c132SHerbert Xu 
1092aeb4c132SHerbert Xu 		to_talitos_ptr(link_tbl_ptr + count,
1093aeb4c132SHerbert Xu 			       sg_dma_address(sg) + offset, 0);
1094b096b544SLEROY Christophe 		to_talitos_ptr_len(link_tbl_ptr + count, len, 0);
1095b096b544SLEROY Christophe 		to_talitos_ptr_ext_set(link_tbl_ptr + count, 0, 0);
1096aeb4c132SHerbert Xu 		count++;
1097aeb4c132SHerbert Xu 		cryptlen -= len;
1098aeb4c132SHerbert Xu 		offset = 0;
1099aeb4c132SHerbert Xu 
1100aeb4c132SHerbert Xu next:
11015be4d4c9SCristian Stoica 		sg = sg_next(sg);
11029c4a7965SKim Phillips 	}
11039c4a7965SKim Phillips 
11049c4a7965SKim Phillips 	/* tag end of link table */
1105aeb4c132SHerbert Xu 	if (count > 0)
1106b096b544SLEROY Christophe 		to_talitos_ptr_ext_set(link_tbl_ptr + count - 1,
1107b096b544SLEROY Christophe 				       DESC_PTR_LNKTBL_RETURN, 0);
110870bcaca7SLee Nipper 
1109aeb4c132SHerbert Xu 	return count;
1110aeb4c132SHerbert Xu }
1111aeb4c132SHerbert Xu 
11125b2cf268SLEROY Christophe static int talitos_sg_map(struct device *dev, struct scatterlist *src,
1113246a87cdSLEROY Christophe 		   unsigned int len, struct talitos_edesc *edesc,
11146a1e8d14SLEROY Christophe 		   struct talitos_ptr *ptr,
11156a1e8d14SLEROY Christophe 		   int sg_count, unsigned int offset, int tbl_off)
1116246a87cdSLEROY Christophe {
1117246a87cdSLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
1118246a87cdSLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
1119246a87cdSLEROY Christophe 
1120246a87cdSLEROY Christophe 	to_talitos_ptr_len(ptr, len, is_sec1);
1121246a87cdSLEROY Christophe 
1122246a87cdSLEROY Christophe 	if (sg_count == 1) {
11236a1e8d14SLEROY Christophe 		to_talitos_ptr(ptr, sg_dma_address(src) + offset, is_sec1);
1124246a87cdSLEROY Christophe 		return sg_count;
1125246a87cdSLEROY Christophe 	}
1126246a87cdSLEROY Christophe 	if (is_sec1) {
11276a1e8d14SLEROY Christophe 		to_talitos_ptr(ptr, edesc->dma_link_tbl + offset, is_sec1);
11286a1e8d14SLEROY Christophe 		return sg_count;
1129246a87cdSLEROY Christophe 	}
11306a1e8d14SLEROY Christophe 	sg_count = sg_to_link_tbl_offset(src, sg_count, offset, len,
11316a1e8d14SLEROY Christophe 					 &edesc->link_tbl[tbl_off]);
1132246a87cdSLEROY Christophe 	if (sg_count == 1) {
11336a1e8d14SLEROY Christophe 		/* Only one segment now, so no link tbl needed*/
11346a1e8d14SLEROY Christophe 		copy_talitos_ptr(ptr, &edesc->link_tbl[tbl_off], is_sec1);
11356a1e8d14SLEROY Christophe 		return sg_count;
11366a1e8d14SLEROY Christophe 	}
1137246a87cdSLEROY Christophe 	to_talitos_ptr(ptr, edesc->dma_link_tbl +
11386a1e8d14SLEROY Christophe 			    tbl_off * sizeof(struct talitos_ptr), is_sec1);
11396a1e8d14SLEROY Christophe 	to_talitos_ptr_ext_or(ptr, DESC_PTR_LNKTBL_JUMP, is_sec1);
11406a1e8d14SLEROY Christophe 
11416a1e8d14SLEROY Christophe 	return sg_count;
1142246a87cdSLEROY Christophe }
1143246a87cdSLEROY Christophe 
11449c4a7965SKim Phillips /*
11459c4a7965SKim Phillips  * fill in and submit ipsec_esp descriptor
11469c4a7965SKim Phillips  */
114756af8cd4SLee Nipper static int ipsec_esp(struct talitos_edesc *edesc, struct aead_request *areq,
1148aeb4c132SHerbert Xu 		     void (*callback)(struct device *dev,
11499c4a7965SKim Phillips 				      struct talitos_desc *desc,
11509c4a7965SKim Phillips 				      void *context, int error))
11519c4a7965SKim Phillips {
11529c4a7965SKim Phillips 	struct crypto_aead *aead = crypto_aead_reqtfm(areq);
1153aeb4c132SHerbert Xu 	unsigned int authsize = crypto_aead_authsize(aead);
11549c4a7965SKim Phillips 	struct talitos_ctx *ctx = crypto_aead_ctx(aead);
11559c4a7965SKim Phillips 	struct device *dev = ctx->dev;
11569c4a7965SKim Phillips 	struct talitos_desc *desc = &edesc->desc;
11579c4a7965SKim Phillips 	unsigned int cryptlen = areq->cryptlen;
1158e41256f1SKim Phillips 	unsigned int ivsize = crypto_aead_ivsize(aead);
1159aeb4c132SHerbert Xu 	int tbl_off = 0;
1160fa86a267SKim Phillips 	int sg_count, ret;
1161fe5720e2SKim Phillips 	int sg_link_tbl_len;
1162549bd8bcSLEROY Christophe 	bool sync_needed = false;
1163549bd8bcSLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
1164549bd8bcSLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
11659c4a7965SKim Phillips 
11669c4a7965SKim Phillips 	/* hmac key */
11679c4a7965SKim Phillips 	map_single_talitos_ptr(dev, &desc->ptr[0], ctx->authkeylen, &ctx->key,
1168a2b35aa8SLEROY Christophe 			       DMA_TO_DEVICE);
116979fd31d3SHoria Geanta 
1170549bd8bcSLEROY Christophe 	sg_count = edesc->src_nents ?: 1;
1171549bd8bcSLEROY Christophe 	if (is_sec1 && sg_count > 1)
1172549bd8bcSLEROY Christophe 		sg_copy_to_buffer(areq->src, sg_count, edesc->buf,
1173549bd8bcSLEROY Christophe 				  areq->assoclen + cryptlen);
1174549bd8bcSLEROY Christophe 	else
1175549bd8bcSLEROY Christophe 		sg_count = dma_map_sg(dev, areq->src, sg_count,
1176549bd8bcSLEROY Christophe 				      (areq->src == areq->dst) ?
1177549bd8bcSLEROY Christophe 				      DMA_BIDIRECTIONAL : DMA_TO_DEVICE);
1178549bd8bcSLEROY Christophe 
11799c4a7965SKim Phillips 	/* hmac data */
1180549bd8bcSLEROY Christophe 	ret = talitos_sg_map(dev, areq->src, areq->assoclen, edesc,
1181549bd8bcSLEROY Christophe 			     &desc->ptr[1], sg_count, 0, tbl_off);
118279fd31d3SHoria Geanta 
1183549bd8bcSLEROY Christophe 	if (ret > 1) {
1184340ff60aSHoria Geant? 		tbl_off += ret;
1185549bd8bcSLEROY Christophe 		sync_needed = true;
118679fd31d3SHoria Geanta 	}
118779fd31d3SHoria Geanta 
11889c4a7965SKim Phillips 	/* cipher iv */
1189549bd8bcSLEROY Christophe 	if (desc->hdr & DESC_HDR_TYPE_IPSEC_ESP) {
1190549bd8bcSLEROY Christophe 		to_talitos_ptr(&desc->ptr[2], edesc->iv_dma, is_sec1);
1191549bd8bcSLEROY Christophe 		to_talitos_ptr_len(&desc->ptr[2], ivsize, is_sec1);
1192549bd8bcSLEROY Christophe 	} else {
1193549bd8bcSLEROY Christophe 		to_talitos_ptr(&desc->ptr[3], edesc->iv_dma, is_sec1);
1194549bd8bcSLEROY Christophe 		to_talitos_ptr_len(&desc->ptr[3], ivsize, is_sec1);
1195549bd8bcSLEROY Christophe 	}
11969c4a7965SKim Phillips 
11979c4a7965SKim Phillips 	/* cipher key */
1198549bd8bcSLEROY Christophe 	if (desc->hdr & DESC_HDR_TYPE_IPSEC_ESP)
11999c4a7965SKim Phillips 		map_single_talitos_ptr(dev, &desc->ptr[3], ctx->enckeylen,
1200a2b35aa8SLEROY Christophe 				       (char *)&ctx->key + ctx->authkeylen,
12019c4a7965SKim Phillips 				       DMA_TO_DEVICE);
1202549bd8bcSLEROY Christophe 	else
1203549bd8bcSLEROY Christophe 		map_single_talitos_ptr(dev, &desc->ptr[2], ctx->enckeylen,
1204549bd8bcSLEROY Christophe 				       (char *)&ctx->key + ctx->authkeylen,
1205549bd8bcSLEROY Christophe 				       DMA_TO_DEVICE);
12069c4a7965SKim Phillips 
12079c4a7965SKim Phillips 	/*
12089c4a7965SKim Phillips 	 * cipher in
12099c4a7965SKim Phillips 	 * map and adjust cipher len to aead request cryptlen.
12109c4a7965SKim Phillips 	 * extent is bytes of HMAC postpended to ciphertext,
12119c4a7965SKim Phillips 	 * typically 12 for ipsec
12129c4a7965SKim Phillips 	 */
1213549bd8bcSLEROY Christophe 	to_talitos_ptr_len(&desc->ptr[4], cryptlen, is_sec1);
12149c4a7965SKim Phillips 
1215fe5720e2SKim Phillips 	sg_link_tbl_len = cryptlen;
1216549bd8bcSLEROY Christophe 
1217549bd8bcSLEROY Christophe 	if (desc->hdr & DESC_HDR_TYPE_IPSEC_ESP) {
1218549bd8bcSLEROY Christophe 		to_talitos_ptr_ext_set(&desc->ptr[4], authsize, is_sec1);
1219549bd8bcSLEROY Christophe 
1220962a9c99SKim Phillips 		if (edesc->desc.hdr & DESC_HDR_MODE1_MDEU_CICV)
1221aeb4c132SHerbert Xu 			sg_link_tbl_len += authsize;
1222549bd8bcSLEROY Christophe 	}
1223e938e465SKim Phillips 
1224fbb22137SLEROY Christophe 	ret = talitos_sg_map(dev, areq->src, sg_link_tbl_len, edesc,
1225fbb22137SLEROY Christophe 			     &desc->ptr[4], sg_count, areq->assoclen, tbl_off);
1226549bd8bcSLEROY Christophe 
1227ec8c7d14SLEROY Christophe 	if (ret > 1) {
1228ec8c7d14SLEROY Christophe 		tbl_off += ret;
1229549bd8bcSLEROY Christophe 		sync_needed = true;
1230340ff60aSHoria Geant? 	}
12319c4a7965SKim Phillips 
12329c4a7965SKim Phillips 	/* cipher out */
1233549bd8bcSLEROY Christophe 	if (areq->src != areq->dst) {
1234549bd8bcSLEROY Christophe 		sg_count = edesc->dst_nents ? : 1;
1235549bd8bcSLEROY Christophe 		if (!is_sec1 || sg_count == 1)
1236549bd8bcSLEROY Christophe 			dma_map_sg(dev, areq->dst, sg_count, DMA_FROM_DEVICE);
1237549bd8bcSLEROY Christophe 	}
12389c4a7965SKim Phillips 
1239e04a61beSLEROY Christophe 	ret = talitos_sg_map(dev, areq->dst, cryptlen, edesc, &desc->ptr[5],
1240e04a61beSLEROY Christophe 			     sg_count, areq->assoclen, tbl_off);
12419c4a7965SKim Phillips 
1242549bd8bcSLEROY Christophe 	if (desc->hdr & DESC_HDR_TYPE_IPSEC_ESP)
1243549bd8bcSLEROY Christophe 		to_talitos_ptr_ext_or(&desc->ptr[5], authsize, is_sec1);
1244aeb4c132SHerbert Xu 
1245e04a61beSLEROY Christophe 	/* ICV data */
1246e04a61beSLEROY Christophe 	if (ret > 1) {
1247e04a61beSLEROY Christophe 		tbl_off += ret;
1248549bd8bcSLEROY Christophe 		edesc->icv_ool = true;
1249549bd8bcSLEROY Christophe 		sync_needed = true;
1250549bd8bcSLEROY Christophe 
1251549bd8bcSLEROY Christophe 		if (desc->hdr & DESC_HDR_TYPE_IPSEC_ESP) {
125279fd31d3SHoria Geanta 			struct talitos_ptr *tbl_ptr = &edesc->link_tbl[tbl_off];
1253549bd8bcSLEROY Christophe 			int offset = (edesc->src_nents + edesc->dst_nents + 2) *
1254549bd8bcSLEROY Christophe 				     sizeof(struct talitos_ptr) + authsize;
1255fe5720e2SKim Phillips 
1256f3c85bc1SLee Nipper 			/* Add an entry to the link table for ICV data */
1257e04a61beSLEROY Christophe 			to_talitos_ptr_ext_set(tbl_ptr - 1, 0, is_sec1);
1258549bd8bcSLEROY Christophe 			to_talitos_ptr_ext_set(tbl_ptr, DESC_PTR_LNKTBL_RETURN,
1259549bd8bcSLEROY Christophe 					       is_sec1);
1260549bd8bcSLEROY Christophe 			to_talitos_ptr_len(tbl_ptr, authsize, is_sec1);
12619c4a7965SKim Phillips 
12629c4a7965SKim Phillips 			/* icv data follows link tables */
1263549bd8bcSLEROY Christophe 			to_talitos_ptr(tbl_ptr, edesc->dma_link_tbl + offset,
1264549bd8bcSLEROY Christophe 				       is_sec1);
1265e04a61beSLEROY Christophe 		} else {
1266e04a61beSLEROY Christophe 			dma_addr_t addr = edesc->dma_link_tbl;
1267e04a61beSLEROY Christophe 
1268e04a61beSLEROY Christophe 			if (is_sec1)
1269e04a61beSLEROY Christophe 				addr += areq->assoclen + cryptlen;
1270e04a61beSLEROY Christophe 			else
1271e04a61beSLEROY Christophe 				addr += sizeof(struct talitos_ptr) * tbl_off;
1272e04a61beSLEROY Christophe 
1273e04a61beSLEROY Christophe 			to_talitos_ptr(&desc->ptr[6], addr, is_sec1);
1274e04a61beSLEROY Christophe 			to_talitos_ptr_len(&desc->ptr[6], authsize, is_sec1);
1275549bd8bcSLEROY Christophe 		}
1276e04a61beSLEROY Christophe 	} else if (!(desc->hdr & DESC_HDR_TYPE_IPSEC_ESP)) {
1277e04a61beSLEROY Christophe 		ret = talitos_sg_map(dev, areq->dst, authsize, edesc,
1278e04a61beSLEROY Christophe 				     &desc->ptr[6], sg_count, areq->assoclen +
1279e04a61beSLEROY Christophe 							      cryptlen,
1280e04a61beSLEROY Christophe 				     tbl_off);
1281e04a61beSLEROY Christophe 		if (ret > 1) {
1282e04a61beSLEROY Christophe 			tbl_off += ret;
1283e04a61beSLEROY Christophe 			edesc->icv_ool = true;
1284e04a61beSLEROY Christophe 			sync_needed = true;
1285340ff60aSHoria Geant? 		} else {
1286549bd8bcSLEROY Christophe 			edesc->icv_ool = false;
1287549bd8bcSLEROY Christophe 		}
1288e04a61beSLEROY Christophe 	} else {
1289e04a61beSLEROY Christophe 		edesc->icv_ool = false;
1290340ff60aSHoria Geant? 	}
12919c4a7965SKim Phillips 
12929c4a7965SKim Phillips 	/* iv out */
1293549bd8bcSLEROY Christophe 	if (desc->hdr & DESC_HDR_TYPE_IPSEC_ESP)
1294a2b35aa8SLEROY Christophe 		map_single_talitos_ptr(dev, &desc->ptr[6], ivsize, ctx->iv,
12959c4a7965SKim Phillips 				       DMA_FROM_DEVICE);
12969c4a7965SKim Phillips 
1297549bd8bcSLEROY Christophe 	if (sync_needed)
1298549bd8bcSLEROY Christophe 		dma_sync_single_for_device(dev, edesc->dma_link_tbl,
1299549bd8bcSLEROY Christophe 					   edesc->dma_len,
1300549bd8bcSLEROY Christophe 					   DMA_BIDIRECTIONAL);
1301549bd8bcSLEROY Christophe 
13025228f0f7SKim Phillips 	ret = talitos_submit(dev, ctx->ch, desc, callback, areq);
1303fa86a267SKim Phillips 	if (ret != -EINPROGRESS) {
1304fa86a267SKim Phillips 		ipsec_esp_unmap(dev, edesc, areq);
1305fa86a267SKim Phillips 		kfree(edesc);
1306fa86a267SKim Phillips 	}
1307fa86a267SKim Phillips 	return ret;
13089c4a7965SKim Phillips }
13099c4a7965SKim Phillips 
13109c4a7965SKim Phillips /*
131156af8cd4SLee Nipper  * allocate and map the extended descriptor
13129c4a7965SKim Phillips  */
13134de9d0b5SLee Nipper static struct talitos_edesc *talitos_edesc_alloc(struct device *dev,
13144de9d0b5SLee Nipper 						 struct scatterlist *src,
13154de9d0b5SLee Nipper 						 struct scatterlist *dst,
131679fd31d3SHoria Geanta 						 u8 *iv,
131779fd31d3SHoria Geanta 						 unsigned int assoclen,
13184de9d0b5SLee Nipper 						 unsigned int cryptlen,
13194de9d0b5SLee Nipper 						 unsigned int authsize,
132079fd31d3SHoria Geanta 						 unsigned int ivsize,
13214de9d0b5SLee Nipper 						 int icv_stashing,
132262293a37SHoria Geanta 						 u32 cryptoflags,
132362293a37SHoria Geanta 						 bool encrypt)
13249c4a7965SKim Phillips {
132556af8cd4SLee Nipper 	struct talitos_edesc *edesc;
13266a1e8d14SLEROY Christophe 	int src_nents, dst_nents, alloc_len, dma_len, src_len, dst_len;
132779fd31d3SHoria Geanta 	dma_addr_t iv_dma = 0;
13284de9d0b5SLee Nipper 	gfp_t flags = cryptoflags & CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL :
1329586725f8SKim Phillips 		      GFP_ATOMIC;
13306f65f6acSLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
13316f65f6acSLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
13326f65f6acSLEROY Christophe 	int max_len = is_sec1 ? TALITOS1_MAX_DATA_LEN : TALITOS2_MAX_DATA_LEN;
13338e409fe1SLABBE Corentin 	void *err;
13349c4a7965SKim Phillips 
13356f65f6acSLEROY Christophe 	if (cryptlen + authsize > max_len) {
13364de9d0b5SLee Nipper 		dev_err(dev, "length exceeds h/w max limit\n");
13379c4a7965SKim Phillips 		return ERR_PTR(-EINVAL);
13389c4a7965SKim Phillips 	}
13399c4a7965SKim Phillips 
1340935e99a3SHoria Geanta 	if (ivsize)
134179fd31d3SHoria Geanta 		iv_dma = dma_map_single(dev, iv, ivsize, DMA_TO_DEVICE);
134279fd31d3SHoria Geanta 
134362293a37SHoria Geanta 	if (!dst || dst == src) {
13446a1e8d14SLEROY Christophe 		src_len = assoclen + cryptlen + authsize;
13456a1e8d14SLEROY Christophe 		src_nents = sg_nents_for_len(src, src_len);
13468e409fe1SLABBE Corentin 		if (src_nents < 0) {
13478e409fe1SLABBE Corentin 			dev_err(dev, "Invalid number of src SG.\n");
13488e409fe1SLABBE Corentin 			err = ERR_PTR(-EINVAL);
13498e409fe1SLABBE Corentin 			goto error_sg;
13508e409fe1SLABBE Corentin 		}
13519c4a7965SKim Phillips 		src_nents = (src_nents == 1) ? 0 : src_nents;
135262293a37SHoria Geanta 		dst_nents = dst ? src_nents : 0;
13536a1e8d14SLEROY Christophe 		dst_len = 0;
135462293a37SHoria Geanta 	} else { /* dst && dst != src*/
13556a1e8d14SLEROY Christophe 		src_len = assoclen + cryptlen + (encrypt ? 0 : authsize);
13566a1e8d14SLEROY Christophe 		src_nents = sg_nents_for_len(src, src_len);
13578e409fe1SLABBE Corentin 		if (src_nents < 0) {
13588e409fe1SLABBE Corentin 			dev_err(dev, "Invalid number of src SG.\n");
13598e409fe1SLABBE Corentin 			err = ERR_PTR(-EINVAL);
13608e409fe1SLABBE Corentin 			goto error_sg;
13618e409fe1SLABBE Corentin 		}
136262293a37SHoria Geanta 		src_nents = (src_nents == 1) ? 0 : src_nents;
13636a1e8d14SLEROY Christophe 		dst_len = assoclen + cryptlen + (encrypt ? authsize : 0);
13646a1e8d14SLEROY Christophe 		dst_nents = sg_nents_for_len(dst, dst_len);
13658e409fe1SLABBE Corentin 		if (dst_nents < 0) {
13668e409fe1SLABBE Corentin 			dev_err(dev, "Invalid number of dst SG.\n");
13678e409fe1SLABBE Corentin 			err = ERR_PTR(-EINVAL);
13688e409fe1SLABBE Corentin 			goto error_sg;
13698e409fe1SLABBE Corentin 		}
1370695ad589SLee Nipper 		dst_nents = (dst_nents == 1) ? 0 : dst_nents;
13719c4a7965SKim Phillips 	}
13729c4a7965SKim Phillips 
13739c4a7965SKim Phillips 	/*
13749c4a7965SKim Phillips 	 * allocate space for base edesc plus the link tables,
1375aeb4c132SHerbert Xu 	 * allowing for two separate entries for AD and generated ICV (+ 2),
1376aeb4c132SHerbert Xu 	 * and space for two sets of ICVs (stashed and generated)
13779c4a7965SKim Phillips 	 */
137856af8cd4SLee Nipper 	alloc_len = sizeof(struct talitos_edesc);
1379aeb4c132SHerbert Xu 	if (src_nents || dst_nents) {
13806f65f6acSLEROY Christophe 		if (is_sec1)
13816a1e8d14SLEROY Christophe 			dma_len = (src_nents ? src_len : 0) +
13826a1e8d14SLEROY Christophe 				  (dst_nents ? dst_len : 0);
13836f65f6acSLEROY Christophe 		else
1384aeb4c132SHerbert Xu 			dma_len = (src_nents + dst_nents + 2) *
1385aeb4c132SHerbert Xu 				  sizeof(struct talitos_ptr) + authsize * 2;
13869c4a7965SKim Phillips 		alloc_len += dma_len;
13879c4a7965SKim Phillips 	} else {
13889c4a7965SKim Phillips 		dma_len = 0;
13894de9d0b5SLee Nipper 		alloc_len += icv_stashing ? authsize : 0;
13909c4a7965SKim Phillips 	}
13919c4a7965SKim Phillips 
1392586725f8SKim Phillips 	edesc = kmalloc(alloc_len, GFP_DMA | flags);
13939c4a7965SKim Phillips 	if (!edesc) {
13944de9d0b5SLee Nipper 		dev_err(dev, "could not allocate edescriptor\n");
13958e409fe1SLABBE Corentin 		err = ERR_PTR(-ENOMEM);
13968e409fe1SLABBE Corentin 		goto error_sg;
13979c4a7965SKim Phillips 	}
1398e4a647c4SLEROY Christophe 	memset(&edesc->desc, 0, sizeof(edesc->desc));
13999c4a7965SKim Phillips 
14009c4a7965SKim Phillips 	edesc->src_nents = src_nents;
14019c4a7965SKim Phillips 	edesc->dst_nents = dst_nents;
140279fd31d3SHoria Geanta 	edesc->iv_dma = iv_dma;
14039c4a7965SKim Phillips 	edesc->dma_len = dma_len;
1404497f2e6bSLee Nipper 	if (dma_len)
14054de9d0b5SLee Nipper 		edesc->dma_link_tbl = dma_map_single(dev, &edesc->link_tbl[0],
1406497f2e6bSLee Nipper 						     edesc->dma_len,
1407497f2e6bSLee Nipper 						     DMA_BIDIRECTIONAL);
14089c4a7965SKim Phillips 
14099c4a7965SKim Phillips 	return edesc;
14108e409fe1SLABBE Corentin error_sg:
14118e409fe1SLABBE Corentin 	if (iv_dma)
14128e409fe1SLABBE Corentin 		dma_unmap_single(dev, iv_dma, ivsize, DMA_TO_DEVICE);
14138e409fe1SLABBE Corentin 	return err;
14149c4a7965SKim Phillips }
14159c4a7965SKim Phillips 
141679fd31d3SHoria Geanta static struct talitos_edesc *aead_edesc_alloc(struct aead_request *areq, u8 *iv,
141762293a37SHoria Geanta 					      int icv_stashing, bool encrypt)
14184de9d0b5SLee Nipper {
14194de9d0b5SLee Nipper 	struct crypto_aead *authenc = crypto_aead_reqtfm(areq);
1420aeb4c132SHerbert Xu 	unsigned int authsize = crypto_aead_authsize(authenc);
14214de9d0b5SLee Nipper 	struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
142279fd31d3SHoria Geanta 	unsigned int ivsize = crypto_aead_ivsize(authenc);
14234de9d0b5SLee Nipper 
1424aeb4c132SHerbert Xu 	return talitos_edesc_alloc(ctx->dev, areq->src, areq->dst,
142579fd31d3SHoria Geanta 				   iv, areq->assoclen, areq->cryptlen,
1426aeb4c132SHerbert Xu 				   authsize, ivsize, icv_stashing,
142762293a37SHoria Geanta 				   areq->base.flags, encrypt);
14284de9d0b5SLee Nipper }
14294de9d0b5SLee Nipper 
143056af8cd4SLee Nipper static int aead_encrypt(struct aead_request *req)
14319c4a7965SKim Phillips {
14329c4a7965SKim Phillips 	struct crypto_aead *authenc = crypto_aead_reqtfm(req);
14339c4a7965SKim Phillips 	struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
143456af8cd4SLee Nipper 	struct talitos_edesc *edesc;
14359c4a7965SKim Phillips 
14369c4a7965SKim Phillips 	/* allocate extended descriptor */
143762293a37SHoria Geanta 	edesc = aead_edesc_alloc(req, req->iv, 0, true);
14389c4a7965SKim Phillips 	if (IS_ERR(edesc))
14399c4a7965SKim Phillips 		return PTR_ERR(edesc);
14409c4a7965SKim Phillips 
14419c4a7965SKim Phillips 	/* set encrypt */
144270bcaca7SLee Nipper 	edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_MODE0_ENCRYPT;
14439c4a7965SKim Phillips 
1444aeb4c132SHerbert Xu 	return ipsec_esp(edesc, req, ipsec_esp_encrypt_done);
14459c4a7965SKim Phillips }
14469c4a7965SKim Phillips 
144756af8cd4SLee Nipper static int aead_decrypt(struct aead_request *req)
14489c4a7965SKim Phillips {
14499c4a7965SKim Phillips 	struct crypto_aead *authenc = crypto_aead_reqtfm(req);
1450aeb4c132SHerbert Xu 	unsigned int authsize = crypto_aead_authsize(authenc);
14519c4a7965SKim Phillips 	struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
1452fe5720e2SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(ctx->dev);
145356af8cd4SLee Nipper 	struct talitos_edesc *edesc;
14549c4a7965SKim Phillips 	struct scatterlist *sg;
14559c4a7965SKim Phillips 	void *icvdata;
14569c4a7965SKim Phillips 
14579c4a7965SKim Phillips 	req->cryptlen -= authsize;
14589c4a7965SKim Phillips 
14599c4a7965SKim Phillips 	/* allocate extended descriptor */
146062293a37SHoria Geanta 	edesc = aead_edesc_alloc(req, req->iv, 1, false);
14619c4a7965SKim Phillips 	if (IS_ERR(edesc))
14629c4a7965SKim Phillips 		return PTR_ERR(edesc);
14639c4a7965SKim Phillips 
1464fe5720e2SKim Phillips 	if ((priv->features & TALITOS_FTR_HW_AUTH_CHECK) &&
1465e938e465SKim Phillips 	    ((!edesc->src_nents && !edesc->dst_nents) ||
1466e938e465SKim Phillips 	     priv->features & TALITOS_FTR_SRC_LINK_TBL_LEN_INCLUDES_EXTENT)) {
1467fe5720e2SKim Phillips 
1468fe5720e2SKim Phillips 		/* decrypt and check the ICV */
1469e938e465SKim Phillips 		edesc->desc.hdr = ctx->desc_hdr_template |
1470e938e465SKim Phillips 				  DESC_HDR_DIR_INBOUND |
1471fe5720e2SKim Phillips 				  DESC_HDR_MODE1_MDEU_CICV;
1472fe5720e2SKim Phillips 
1473fe5720e2SKim Phillips 		/* reset integrity check result bits */
1474fe5720e2SKim Phillips 
1475aeb4c132SHerbert Xu 		return ipsec_esp(edesc, req, ipsec_esp_decrypt_hwauth_done);
1476e938e465SKim Phillips 	}
1477fe5720e2SKim Phillips 
1478fe5720e2SKim Phillips 	/* Have to check the ICV with software */
1479fe5720e2SKim Phillips 	edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_DIR_INBOUND;
1480fe5720e2SKim Phillips 
14819c4a7965SKim Phillips 	/* stash incoming ICV for later cmp with ICV generated by the h/w */
14829c4a7965SKim Phillips 	if (edesc->dma_len)
1483aeb4c132SHerbert Xu 		icvdata = (char *)&edesc->link_tbl[edesc->src_nents +
1484aeb4c132SHerbert Xu 						   edesc->dst_nents + 2];
14859c4a7965SKim Phillips 	else
14869c4a7965SKim Phillips 		icvdata = &edesc->link_tbl[0];
14879c4a7965SKim Phillips 
14889c4a7965SKim Phillips 	sg = sg_last(req->src, edesc->src_nents ? : 1);
14899c4a7965SKim Phillips 
1490aeb4c132SHerbert Xu 	memcpy(icvdata, (char *)sg_virt(sg) + sg->length - authsize, authsize);
14919c4a7965SKim Phillips 
1492aeb4c132SHerbert Xu 	return ipsec_esp(edesc, req, ipsec_esp_decrypt_swauth_done);
14939c4a7965SKim Phillips }
14949c4a7965SKim Phillips 
14954de9d0b5SLee Nipper static int ablkcipher_setkey(struct crypto_ablkcipher *cipher,
14964de9d0b5SLee Nipper 			     const u8 *key, unsigned int keylen)
14974de9d0b5SLee Nipper {
14984de9d0b5SLee Nipper 	struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher);
1499f384cdc4SLEROY Christophe 	u32 tmp[DES_EXPKEY_WORDS];
15004de9d0b5SLee Nipper 
150103d2c511SMartin Hicks 	if (keylen > TALITOS_MAX_KEY_SIZE) {
150203d2c511SMartin Hicks 		crypto_ablkcipher_set_flags(cipher, CRYPTO_TFM_RES_BAD_KEY_LEN);
150303d2c511SMartin Hicks 		return -EINVAL;
150403d2c511SMartin Hicks 	}
150503d2c511SMartin Hicks 
1506f384cdc4SLEROY Christophe 	if (unlikely(crypto_ablkcipher_get_flags(cipher) &
1507f384cdc4SLEROY Christophe 		     CRYPTO_TFM_REQ_WEAK_KEY) &&
1508f384cdc4SLEROY Christophe 	    !des_ekey(tmp, key)) {
1509f384cdc4SLEROY Christophe 		crypto_ablkcipher_set_flags(cipher, CRYPTO_TFM_RES_WEAK_KEY);
1510f384cdc4SLEROY Christophe 		return -EINVAL;
1511f384cdc4SLEROY Christophe 	}
1512f384cdc4SLEROY Christophe 
15134de9d0b5SLee Nipper 	memcpy(&ctx->key, key, keylen);
15144de9d0b5SLee Nipper 	ctx->keylen = keylen;
15154de9d0b5SLee Nipper 
15164de9d0b5SLee Nipper 	return 0;
15174de9d0b5SLee Nipper }
15184de9d0b5SLee Nipper 
15194de9d0b5SLee Nipper static void common_nonsnoop_unmap(struct device *dev,
15204de9d0b5SLee Nipper 				  struct talitos_edesc *edesc,
15214de9d0b5SLee Nipper 				  struct ablkcipher_request *areq)
15224de9d0b5SLee Nipper {
15234de9d0b5SLee Nipper 	unmap_single_talitos_ptr(dev, &edesc->desc.ptr[5], DMA_FROM_DEVICE);
1524032d197eSLEROY Christophe 
15256a1e8d14SLEROY Christophe 	talitos_sg_unmap(dev, edesc, areq->src, areq->dst, areq->nbytes, 0);
15264de9d0b5SLee Nipper 	unmap_single_talitos_ptr(dev, &edesc->desc.ptr[2], DMA_TO_DEVICE);
15274de9d0b5SLee Nipper 	unmap_single_talitos_ptr(dev, &edesc->desc.ptr[1], DMA_TO_DEVICE);
15284de9d0b5SLee Nipper 
15294de9d0b5SLee Nipper 	if (edesc->dma_len)
15304de9d0b5SLee Nipper 		dma_unmap_single(dev, edesc->dma_link_tbl, edesc->dma_len,
15314de9d0b5SLee Nipper 				 DMA_BIDIRECTIONAL);
15324de9d0b5SLee Nipper }
15334de9d0b5SLee Nipper 
15344de9d0b5SLee Nipper static void ablkcipher_done(struct device *dev,
15354de9d0b5SLee Nipper 			    struct talitos_desc *desc, void *context,
15364de9d0b5SLee Nipper 			    int err)
15374de9d0b5SLee Nipper {
15384de9d0b5SLee Nipper 	struct ablkcipher_request *areq = context;
153919bbbc63SKim Phillips 	struct talitos_edesc *edesc;
154019bbbc63SKim Phillips 
154119bbbc63SKim Phillips 	edesc = container_of(desc, struct talitos_edesc, desc);
15424de9d0b5SLee Nipper 
15434de9d0b5SLee Nipper 	common_nonsnoop_unmap(dev, edesc, areq);
15444de9d0b5SLee Nipper 
15454de9d0b5SLee Nipper 	kfree(edesc);
15464de9d0b5SLee Nipper 
15474de9d0b5SLee Nipper 	areq->base.complete(&areq->base, err);
15484de9d0b5SLee Nipper }
15494de9d0b5SLee Nipper 
15504de9d0b5SLee Nipper static int common_nonsnoop(struct talitos_edesc *edesc,
15514de9d0b5SLee Nipper 			   struct ablkcipher_request *areq,
15524de9d0b5SLee Nipper 			   void (*callback) (struct device *dev,
15534de9d0b5SLee Nipper 					     struct talitos_desc *desc,
15544de9d0b5SLee Nipper 					     void *context, int error))
15554de9d0b5SLee Nipper {
15564de9d0b5SLee Nipper 	struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(areq);
15574de9d0b5SLee Nipper 	struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher);
15584de9d0b5SLee Nipper 	struct device *dev = ctx->dev;
15594de9d0b5SLee Nipper 	struct talitos_desc *desc = &edesc->desc;
15604de9d0b5SLee Nipper 	unsigned int cryptlen = areq->nbytes;
156179fd31d3SHoria Geanta 	unsigned int ivsize = crypto_ablkcipher_ivsize(cipher);
15624de9d0b5SLee Nipper 	int sg_count, ret;
15636a1e8d14SLEROY Christophe 	bool sync_needed = false;
1564922f9dc8SLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
1565922f9dc8SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
15664de9d0b5SLee Nipper 
15674de9d0b5SLee Nipper 	/* first DWORD empty */
15684de9d0b5SLee Nipper 
15694de9d0b5SLee Nipper 	/* cipher iv */
1570922f9dc8SLEROY Christophe 	to_talitos_ptr(&desc->ptr[1], edesc->iv_dma, is_sec1);
1571922f9dc8SLEROY Christophe 	to_talitos_ptr_len(&desc->ptr[1], ivsize, is_sec1);
15724de9d0b5SLee Nipper 
15734de9d0b5SLee Nipper 	/* cipher key */
15744de9d0b5SLee Nipper 	map_single_talitos_ptr(dev, &desc->ptr[2], ctx->keylen,
1575a2b35aa8SLEROY Christophe 			       (char *)&ctx->key, DMA_TO_DEVICE);
15764de9d0b5SLee Nipper 
15776a1e8d14SLEROY Christophe 	sg_count = edesc->src_nents ?: 1;
15786a1e8d14SLEROY Christophe 	if (is_sec1 && sg_count > 1)
15796a1e8d14SLEROY Christophe 		sg_copy_to_buffer(areq->src, sg_count, edesc->buf,
15806a1e8d14SLEROY Christophe 				  cryptlen);
15816a1e8d14SLEROY Christophe 	else
15826a1e8d14SLEROY Christophe 		sg_count = dma_map_sg(dev, areq->src, sg_count,
15836a1e8d14SLEROY Christophe 				      (areq->src == areq->dst) ?
15846a1e8d14SLEROY Christophe 				      DMA_BIDIRECTIONAL : DMA_TO_DEVICE);
15854de9d0b5SLee Nipper 	/*
15864de9d0b5SLee Nipper 	 * cipher in
15874de9d0b5SLee Nipper 	 */
15886a1e8d14SLEROY Christophe 	sg_count = talitos_sg_map(dev, areq->src, cryptlen, edesc,
15896a1e8d14SLEROY Christophe 				  &desc->ptr[3], sg_count, 0, 0);
15906a1e8d14SLEROY Christophe 	if (sg_count > 1)
15916a1e8d14SLEROY Christophe 		sync_needed = true;
15924de9d0b5SLee Nipper 
15934de9d0b5SLee Nipper 	/* cipher out */
15946a1e8d14SLEROY Christophe 	if (areq->src != areq->dst) {
15956a1e8d14SLEROY Christophe 		sg_count = edesc->dst_nents ? : 1;
15966a1e8d14SLEROY Christophe 		if (!is_sec1 || sg_count == 1)
15976a1e8d14SLEROY Christophe 			dma_map_sg(dev, areq->dst, sg_count, DMA_FROM_DEVICE);
15986a1e8d14SLEROY Christophe 	}
15996a1e8d14SLEROY Christophe 
16006a1e8d14SLEROY Christophe 	ret = talitos_sg_map(dev, areq->dst, cryptlen, edesc, &desc->ptr[4],
16016a1e8d14SLEROY Christophe 			     sg_count, 0, (edesc->src_nents + 1));
16026a1e8d14SLEROY Christophe 	if (ret > 1)
16036a1e8d14SLEROY Christophe 		sync_needed = true;
16044de9d0b5SLee Nipper 
16054de9d0b5SLee Nipper 	/* iv out */
1606a2b35aa8SLEROY Christophe 	map_single_talitos_ptr(dev, &desc->ptr[5], ivsize, ctx->iv,
16074de9d0b5SLee Nipper 			       DMA_FROM_DEVICE);
16084de9d0b5SLee Nipper 
16094de9d0b5SLee Nipper 	/* last DWORD empty */
16104de9d0b5SLee Nipper 
16116a1e8d14SLEROY Christophe 	if (sync_needed)
16126a1e8d14SLEROY Christophe 		dma_sync_single_for_device(dev, edesc->dma_link_tbl,
16136a1e8d14SLEROY Christophe 					   edesc->dma_len, DMA_BIDIRECTIONAL);
16146a1e8d14SLEROY Christophe 
16155228f0f7SKim Phillips 	ret = talitos_submit(dev, ctx->ch, desc, callback, areq);
16164de9d0b5SLee Nipper 	if (ret != -EINPROGRESS) {
16174de9d0b5SLee Nipper 		common_nonsnoop_unmap(dev, edesc, areq);
16184de9d0b5SLee Nipper 		kfree(edesc);
16194de9d0b5SLee Nipper 	}
16204de9d0b5SLee Nipper 	return ret;
16214de9d0b5SLee Nipper }
16224de9d0b5SLee Nipper 
1623e938e465SKim Phillips static struct talitos_edesc *ablkcipher_edesc_alloc(struct ablkcipher_request *
162462293a37SHoria Geanta 						    areq, bool encrypt)
16254de9d0b5SLee Nipper {
16264de9d0b5SLee Nipper 	struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(areq);
16274de9d0b5SLee Nipper 	struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher);
162879fd31d3SHoria Geanta 	unsigned int ivsize = crypto_ablkcipher_ivsize(cipher);
16294de9d0b5SLee Nipper 
1630aeb4c132SHerbert Xu 	return talitos_edesc_alloc(ctx->dev, areq->src, areq->dst,
163179fd31d3SHoria Geanta 				   areq->info, 0, areq->nbytes, 0, ivsize, 0,
163262293a37SHoria Geanta 				   areq->base.flags, encrypt);
16334de9d0b5SLee Nipper }
16344de9d0b5SLee Nipper 
16354de9d0b5SLee Nipper static int ablkcipher_encrypt(struct ablkcipher_request *areq)
16364de9d0b5SLee Nipper {
16374de9d0b5SLee Nipper 	struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(areq);
16384de9d0b5SLee Nipper 	struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher);
16394de9d0b5SLee Nipper 	struct talitos_edesc *edesc;
16404de9d0b5SLee Nipper 
16414de9d0b5SLee Nipper 	/* allocate extended descriptor */
164262293a37SHoria Geanta 	edesc = ablkcipher_edesc_alloc(areq, true);
16434de9d0b5SLee Nipper 	if (IS_ERR(edesc))
16444de9d0b5SLee Nipper 		return PTR_ERR(edesc);
16454de9d0b5SLee Nipper 
16464de9d0b5SLee Nipper 	/* set encrypt */
16474de9d0b5SLee Nipper 	edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_MODE0_ENCRYPT;
16484de9d0b5SLee Nipper 
1649febec542SKim Phillips 	return common_nonsnoop(edesc, areq, ablkcipher_done);
16504de9d0b5SLee Nipper }
16514de9d0b5SLee Nipper 
16524de9d0b5SLee Nipper static int ablkcipher_decrypt(struct ablkcipher_request *areq)
16534de9d0b5SLee Nipper {
16544de9d0b5SLee Nipper 	struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(areq);
16554de9d0b5SLee Nipper 	struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher);
16564de9d0b5SLee Nipper 	struct talitos_edesc *edesc;
16574de9d0b5SLee Nipper 
16584de9d0b5SLee Nipper 	/* allocate extended descriptor */
165962293a37SHoria Geanta 	edesc = ablkcipher_edesc_alloc(areq, false);
16604de9d0b5SLee Nipper 	if (IS_ERR(edesc))
16614de9d0b5SLee Nipper 		return PTR_ERR(edesc);
16624de9d0b5SLee Nipper 
16634de9d0b5SLee Nipper 	edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_DIR_INBOUND;
16644de9d0b5SLee Nipper 
1665febec542SKim Phillips 	return common_nonsnoop(edesc, areq, ablkcipher_done);
16664de9d0b5SLee Nipper }
16674de9d0b5SLee Nipper 
1668497f2e6bSLee Nipper static void common_nonsnoop_hash_unmap(struct device *dev,
1669497f2e6bSLee Nipper 				       struct talitos_edesc *edesc,
1670497f2e6bSLee Nipper 				       struct ahash_request *areq)
1671497f2e6bSLee Nipper {
1672497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
1673922f9dc8SLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
1674922f9dc8SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
1675497f2e6bSLee Nipper 
1676497f2e6bSLee Nipper 	unmap_single_talitos_ptr(dev, &edesc->desc.ptr[5], DMA_FROM_DEVICE);
1677497f2e6bSLee Nipper 
16786a1e8d14SLEROY Christophe 	talitos_sg_unmap(dev, edesc, req_ctx->psrc, NULL, 0, 0);
1679032d197eSLEROY Christophe 
1680497f2e6bSLee Nipper 	/* When using hashctx-in, must unmap it. */
1681922f9dc8SLEROY Christophe 	if (from_talitos_ptr_len(&edesc->desc.ptr[1], is_sec1))
1682497f2e6bSLee Nipper 		unmap_single_talitos_ptr(dev, &edesc->desc.ptr[1],
1683497f2e6bSLee Nipper 					 DMA_TO_DEVICE);
1684497f2e6bSLee Nipper 
1685922f9dc8SLEROY Christophe 	if (from_talitos_ptr_len(&edesc->desc.ptr[2], is_sec1))
1686497f2e6bSLee Nipper 		unmap_single_talitos_ptr(dev, &edesc->desc.ptr[2],
1687497f2e6bSLee Nipper 					 DMA_TO_DEVICE);
1688497f2e6bSLee Nipper 
1689497f2e6bSLee Nipper 	if (edesc->dma_len)
1690497f2e6bSLee Nipper 		dma_unmap_single(dev, edesc->dma_link_tbl, edesc->dma_len,
1691497f2e6bSLee Nipper 				 DMA_BIDIRECTIONAL);
1692497f2e6bSLee Nipper 
1693497f2e6bSLee Nipper }
1694497f2e6bSLee Nipper 
1695497f2e6bSLee Nipper static void ahash_done(struct device *dev,
1696497f2e6bSLee Nipper 		       struct talitos_desc *desc, void *context,
1697497f2e6bSLee Nipper 		       int err)
1698497f2e6bSLee Nipper {
1699497f2e6bSLee Nipper 	struct ahash_request *areq = context;
1700497f2e6bSLee Nipper 	struct talitos_edesc *edesc =
1701497f2e6bSLee Nipper 		 container_of(desc, struct talitos_edesc, desc);
1702497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
1703497f2e6bSLee Nipper 
1704497f2e6bSLee Nipper 	if (!req_ctx->last && req_ctx->to_hash_later) {
1705497f2e6bSLee Nipper 		/* Position any partial block for next update/final/finup */
1706497f2e6bSLee Nipper 		memcpy(req_ctx->buf, req_ctx->bufnext, req_ctx->to_hash_later);
17075e833bc4SLee Nipper 		req_ctx->nbuf = req_ctx->to_hash_later;
1708497f2e6bSLee Nipper 	}
1709497f2e6bSLee Nipper 	common_nonsnoop_hash_unmap(dev, edesc, areq);
1710497f2e6bSLee Nipper 
1711497f2e6bSLee Nipper 	kfree(edesc);
1712497f2e6bSLee Nipper 
1713497f2e6bSLee Nipper 	areq->base.complete(&areq->base, err);
1714497f2e6bSLee Nipper }
1715497f2e6bSLee Nipper 
17162d02905eSLEROY Christophe /*
17172d02905eSLEROY Christophe  * SEC1 doesn't like hashing of 0 sized message, so we do the padding
17182d02905eSLEROY Christophe  * ourself and submit a padded block
17192d02905eSLEROY Christophe  */
17205b2cf268SLEROY Christophe static void talitos_handle_buggy_hash(struct talitos_ctx *ctx,
17212d02905eSLEROY Christophe 			       struct talitos_edesc *edesc,
17222d02905eSLEROY Christophe 			       struct talitos_ptr *ptr)
17232d02905eSLEROY Christophe {
17242d02905eSLEROY Christophe 	static u8 padded_hash[64] = {
17252d02905eSLEROY Christophe 		0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
17262d02905eSLEROY Christophe 		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
17272d02905eSLEROY Christophe 		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
17282d02905eSLEROY Christophe 		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
17292d02905eSLEROY Christophe 	};
17302d02905eSLEROY Christophe 
17312d02905eSLEROY Christophe 	pr_err_once("Bug in SEC1, padding ourself\n");
17322d02905eSLEROY Christophe 	edesc->desc.hdr &= ~DESC_HDR_MODE0_MDEU_PAD;
17332d02905eSLEROY Christophe 	map_single_talitos_ptr(ctx->dev, ptr, sizeof(padded_hash),
17342d02905eSLEROY Christophe 			       (char *)padded_hash, DMA_TO_DEVICE);
17352d02905eSLEROY Christophe }
17362d02905eSLEROY Christophe 
1737497f2e6bSLee Nipper static int common_nonsnoop_hash(struct talitos_edesc *edesc,
1738497f2e6bSLee Nipper 				struct ahash_request *areq, unsigned int length,
1739497f2e6bSLee Nipper 				void (*callback) (struct device *dev,
1740497f2e6bSLee Nipper 						  struct talitos_desc *desc,
1741497f2e6bSLee Nipper 						  void *context, int error))
1742497f2e6bSLee Nipper {
1743497f2e6bSLee Nipper 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
1744497f2e6bSLee Nipper 	struct talitos_ctx *ctx = crypto_ahash_ctx(tfm);
1745497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
1746497f2e6bSLee Nipper 	struct device *dev = ctx->dev;
1747497f2e6bSLee Nipper 	struct talitos_desc *desc = &edesc->desc;
1748032d197eSLEROY Christophe 	int ret;
17496a1e8d14SLEROY Christophe 	bool sync_needed = false;
1750922f9dc8SLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
1751922f9dc8SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
17526a1e8d14SLEROY Christophe 	int sg_count;
1753497f2e6bSLee Nipper 
1754497f2e6bSLee Nipper 	/* first DWORD empty */
1755497f2e6bSLee Nipper 
175660f208d7SKim Phillips 	/* hash context in */
175760f208d7SKim Phillips 	if (!req_ctx->first || req_ctx->swinit) {
1758497f2e6bSLee Nipper 		map_single_talitos_ptr(dev, &desc->ptr[1],
1759497f2e6bSLee Nipper 				       req_ctx->hw_context_size,
1760a2b35aa8SLEROY Christophe 				       (char *)req_ctx->hw_context,
1761497f2e6bSLee Nipper 				       DMA_TO_DEVICE);
176260f208d7SKim Phillips 		req_ctx->swinit = 0;
1763afd62fa2SLEROY Christophe 	}
1764497f2e6bSLee Nipper 	/* Indicate next op is not the first. */
1765497f2e6bSLee Nipper 	req_ctx->first = 0;
1766497f2e6bSLee Nipper 
1767497f2e6bSLee Nipper 	/* HMAC key */
1768497f2e6bSLee Nipper 	if (ctx->keylen)
1769497f2e6bSLee Nipper 		map_single_talitos_ptr(dev, &desc->ptr[2], ctx->keylen,
1770a2b35aa8SLEROY Christophe 				       (char *)&ctx->key, DMA_TO_DEVICE);
1771497f2e6bSLee Nipper 
17726a1e8d14SLEROY Christophe 	sg_count = edesc->src_nents ?: 1;
17736a1e8d14SLEROY Christophe 	if (is_sec1 && sg_count > 1)
1774886a27c0SLEROY Christophe 		sg_copy_to_buffer(req_ctx->psrc, sg_count, edesc->buf, length);
17756a1e8d14SLEROY Christophe 	else
17766a1e8d14SLEROY Christophe 		sg_count = dma_map_sg(dev, req_ctx->psrc, sg_count,
17776a1e8d14SLEROY Christophe 				      DMA_TO_DEVICE);
1778497f2e6bSLee Nipper 	/*
1779497f2e6bSLee Nipper 	 * data in
1780497f2e6bSLee Nipper 	 */
17816a1e8d14SLEROY Christophe 	sg_count = talitos_sg_map(dev, req_ctx->psrc, length, edesc,
17826a1e8d14SLEROY Christophe 				  &desc->ptr[3], sg_count, 0, 0);
17836a1e8d14SLEROY Christophe 	if (sg_count > 1)
17846a1e8d14SLEROY Christophe 		sync_needed = true;
1785497f2e6bSLee Nipper 
1786497f2e6bSLee Nipper 	/* fifth DWORD empty */
1787497f2e6bSLee Nipper 
1788497f2e6bSLee Nipper 	/* hash/HMAC out -or- hash context out */
1789497f2e6bSLee Nipper 	if (req_ctx->last)
1790497f2e6bSLee Nipper 		map_single_talitos_ptr(dev, &desc->ptr[5],
1791497f2e6bSLee Nipper 				       crypto_ahash_digestsize(tfm),
1792a2b35aa8SLEROY Christophe 				       areq->result, DMA_FROM_DEVICE);
1793497f2e6bSLee Nipper 	else
1794497f2e6bSLee Nipper 		map_single_talitos_ptr(dev, &desc->ptr[5],
1795497f2e6bSLee Nipper 				       req_ctx->hw_context_size,
1796a2b35aa8SLEROY Christophe 				       req_ctx->hw_context, DMA_FROM_DEVICE);
1797497f2e6bSLee Nipper 
1798497f2e6bSLee Nipper 	/* last DWORD empty */
1799497f2e6bSLee Nipper 
18002d02905eSLEROY Christophe 	if (is_sec1 && from_talitos_ptr_len(&desc->ptr[3], true) == 0)
18012d02905eSLEROY Christophe 		talitos_handle_buggy_hash(ctx, edesc, &desc->ptr[3]);
18022d02905eSLEROY Christophe 
18036a1e8d14SLEROY Christophe 	if (sync_needed)
18046a1e8d14SLEROY Christophe 		dma_sync_single_for_device(dev, edesc->dma_link_tbl,
18056a1e8d14SLEROY Christophe 					   edesc->dma_len, DMA_BIDIRECTIONAL);
18066a1e8d14SLEROY Christophe 
18075228f0f7SKim Phillips 	ret = talitos_submit(dev, ctx->ch, desc, callback, areq);
1808497f2e6bSLee Nipper 	if (ret != -EINPROGRESS) {
1809497f2e6bSLee Nipper 		common_nonsnoop_hash_unmap(dev, edesc, areq);
1810497f2e6bSLee Nipper 		kfree(edesc);
1811497f2e6bSLee Nipper 	}
1812497f2e6bSLee Nipper 	return ret;
1813497f2e6bSLee Nipper }
1814497f2e6bSLee Nipper 
1815497f2e6bSLee Nipper static struct talitos_edesc *ahash_edesc_alloc(struct ahash_request *areq,
1816497f2e6bSLee Nipper 					       unsigned int nbytes)
1817497f2e6bSLee Nipper {
1818497f2e6bSLee Nipper 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
1819497f2e6bSLee Nipper 	struct talitos_ctx *ctx = crypto_ahash_ctx(tfm);
1820497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
1821497f2e6bSLee Nipper 
1822aeb4c132SHerbert Xu 	return talitos_edesc_alloc(ctx->dev, req_ctx->psrc, NULL, NULL, 0,
182362293a37SHoria Geanta 				   nbytes, 0, 0, 0, areq->base.flags, false);
1824497f2e6bSLee Nipper }
1825497f2e6bSLee Nipper 
1826497f2e6bSLee Nipper static int ahash_init(struct ahash_request *areq)
1827497f2e6bSLee Nipper {
1828497f2e6bSLee Nipper 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
1829497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
1830497f2e6bSLee Nipper 
1831497f2e6bSLee Nipper 	/* Initialize the context */
18325e833bc4SLee Nipper 	req_ctx->nbuf = 0;
183360f208d7SKim Phillips 	req_ctx->first = 1; /* first indicates h/w must init its context */
183460f208d7SKim Phillips 	req_ctx->swinit = 0; /* assume h/w init of context */
1835497f2e6bSLee Nipper 	req_ctx->hw_context_size =
1836497f2e6bSLee Nipper 		(crypto_ahash_digestsize(tfm) <= SHA256_DIGEST_SIZE)
1837497f2e6bSLee Nipper 			? TALITOS_MDEU_CONTEXT_SIZE_MD5_SHA1_SHA256
1838497f2e6bSLee Nipper 			: TALITOS_MDEU_CONTEXT_SIZE_SHA384_SHA512;
1839497f2e6bSLee Nipper 
1840497f2e6bSLee Nipper 	return 0;
1841497f2e6bSLee Nipper }
1842497f2e6bSLee Nipper 
184360f208d7SKim Phillips /*
184460f208d7SKim Phillips  * on h/w without explicit sha224 support, we initialize h/w context
184560f208d7SKim Phillips  * manually with sha224 constants, and tell it to run sha256.
184660f208d7SKim Phillips  */
184760f208d7SKim Phillips static int ahash_init_sha224_swinit(struct ahash_request *areq)
184860f208d7SKim Phillips {
184960f208d7SKim Phillips 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
185060f208d7SKim Phillips 
185160f208d7SKim Phillips 	ahash_init(areq);
185260f208d7SKim Phillips 	req_ctx->swinit = 1;/* prevent h/w initting context with sha256 values*/
185360f208d7SKim Phillips 
1854a752447aSKim Phillips 	req_ctx->hw_context[0] = SHA224_H0;
1855a752447aSKim Phillips 	req_ctx->hw_context[1] = SHA224_H1;
1856a752447aSKim Phillips 	req_ctx->hw_context[2] = SHA224_H2;
1857a752447aSKim Phillips 	req_ctx->hw_context[3] = SHA224_H3;
1858a752447aSKim Phillips 	req_ctx->hw_context[4] = SHA224_H4;
1859a752447aSKim Phillips 	req_ctx->hw_context[5] = SHA224_H5;
1860a752447aSKim Phillips 	req_ctx->hw_context[6] = SHA224_H6;
1861a752447aSKim Phillips 	req_ctx->hw_context[7] = SHA224_H7;
186260f208d7SKim Phillips 
186360f208d7SKim Phillips 	/* init 64-bit count */
186460f208d7SKim Phillips 	req_ctx->hw_context[8] = 0;
186560f208d7SKim Phillips 	req_ctx->hw_context[9] = 0;
186660f208d7SKim Phillips 
186760f208d7SKim Phillips 	return 0;
186860f208d7SKim Phillips }
186960f208d7SKim Phillips 
1870497f2e6bSLee Nipper static int ahash_process_req(struct ahash_request *areq, unsigned int nbytes)
1871497f2e6bSLee Nipper {
1872497f2e6bSLee Nipper 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
1873497f2e6bSLee Nipper 	struct talitos_ctx *ctx = crypto_ahash_ctx(tfm);
1874497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
1875497f2e6bSLee Nipper 	struct talitos_edesc *edesc;
1876497f2e6bSLee Nipper 	unsigned int blocksize =
1877497f2e6bSLee Nipper 			crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm));
1878497f2e6bSLee Nipper 	unsigned int nbytes_to_hash;
1879497f2e6bSLee Nipper 	unsigned int to_hash_later;
18805e833bc4SLee Nipper 	unsigned int nsg;
18818e409fe1SLABBE Corentin 	int nents;
1882497f2e6bSLee Nipper 
18835e833bc4SLee Nipper 	if (!req_ctx->last && (nbytes + req_ctx->nbuf <= blocksize)) {
18845e833bc4SLee Nipper 		/* Buffer up to one whole block */
18858e409fe1SLABBE Corentin 		nents = sg_nents_for_len(areq->src, nbytes);
18868e409fe1SLABBE Corentin 		if (nents < 0) {
18878e409fe1SLABBE Corentin 			dev_err(ctx->dev, "Invalid number of src SG.\n");
18888e409fe1SLABBE Corentin 			return nents;
18898e409fe1SLABBE Corentin 		}
18908e409fe1SLABBE Corentin 		sg_copy_to_buffer(areq->src, nents,
18915e833bc4SLee Nipper 				  req_ctx->buf + req_ctx->nbuf, nbytes);
18925e833bc4SLee Nipper 		req_ctx->nbuf += nbytes;
1893497f2e6bSLee Nipper 		return 0;
1894497f2e6bSLee Nipper 	}
1895497f2e6bSLee Nipper 
18965e833bc4SLee Nipper 	/* At least (blocksize + 1) bytes are available to hash */
18975e833bc4SLee Nipper 	nbytes_to_hash = nbytes + req_ctx->nbuf;
18985e833bc4SLee Nipper 	to_hash_later = nbytes_to_hash & (blocksize - 1);
18995e833bc4SLee Nipper 
19005e833bc4SLee Nipper 	if (req_ctx->last)
19015e833bc4SLee Nipper 		to_hash_later = 0;
19025e833bc4SLee Nipper 	else if (to_hash_later)
19035e833bc4SLee Nipper 		/* There is a partial block. Hash the full block(s) now */
19045e833bc4SLee Nipper 		nbytes_to_hash -= to_hash_later;
19055e833bc4SLee Nipper 	else {
19065e833bc4SLee Nipper 		/* Keep one block buffered */
19075e833bc4SLee Nipper 		nbytes_to_hash -= blocksize;
19085e833bc4SLee Nipper 		to_hash_later = blocksize;
1909497f2e6bSLee Nipper 	}
19105e833bc4SLee Nipper 
19115e833bc4SLee Nipper 	/* Chain in any previously buffered data */
19125e833bc4SLee Nipper 	if (req_ctx->nbuf) {
19135e833bc4SLee Nipper 		nsg = (req_ctx->nbuf < nbytes_to_hash) ? 2 : 1;
19145e833bc4SLee Nipper 		sg_init_table(req_ctx->bufsl, nsg);
19155e833bc4SLee Nipper 		sg_set_buf(req_ctx->bufsl, req_ctx->buf, req_ctx->nbuf);
19165e833bc4SLee Nipper 		if (nsg > 1)
1917c56f6d12SDan Williams 			sg_chain(req_ctx->bufsl, 2, areq->src);
19185e833bc4SLee Nipper 		req_ctx->psrc = req_ctx->bufsl;
19195e833bc4SLee Nipper 	} else
19205e833bc4SLee Nipper 		req_ctx->psrc = areq->src;
19215e833bc4SLee Nipper 
1922497f2e6bSLee Nipper 	if (to_hash_later) {
19238e409fe1SLABBE Corentin 		nents = sg_nents_for_len(areq->src, nbytes);
19248e409fe1SLABBE Corentin 		if (nents < 0) {
19258e409fe1SLABBE Corentin 			dev_err(ctx->dev, "Invalid number of src SG.\n");
19268e409fe1SLABBE Corentin 			return nents;
19278e409fe1SLABBE Corentin 		}
1928d0525723SAkinobu Mita 		sg_pcopy_to_buffer(areq->src, nents,
1929497f2e6bSLee Nipper 				      req_ctx->bufnext,
1930497f2e6bSLee Nipper 				      to_hash_later,
1931497f2e6bSLee Nipper 				      nbytes - to_hash_later);
1932497f2e6bSLee Nipper 	}
1933497f2e6bSLee Nipper 	req_ctx->to_hash_later = to_hash_later;
1934497f2e6bSLee Nipper 
19355e833bc4SLee Nipper 	/* Allocate extended descriptor */
1936497f2e6bSLee Nipper 	edesc = ahash_edesc_alloc(areq, nbytes_to_hash);
1937497f2e6bSLee Nipper 	if (IS_ERR(edesc))
1938497f2e6bSLee Nipper 		return PTR_ERR(edesc);
1939497f2e6bSLee Nipper 
1940497f2e6bSLee Nipper 	edesc->desc.hdr = ctx->desc_hdr_template;
1941497f2e6bSLee Nipper 
1942497f2e6bSLee Nipper 	/* On last one, request SEC to pad; otherwise continue */
1943497f2e6bSLee Nipper 	if (req_ctx->last)
1944497f2e6bSLee Nipper 		edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_PAD;
1945497f2e6bSLee Nipper 	else
1946497f2e6bSLee Nipper 		edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_CONT;
1947497f2e6bSLee Nipper 
194860f208d7SKim Phillips 	/* request SEC to INIT hash. */
194960f208d7SKim Phillips 	if (req_ctx->first && !req_ctx->swinit)
1950497f2e6bSLee Nipper 		edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_INIT;
1951497f2e6bSLee Nipper 
1952497f2e6bSLee Nipper 	/* When the tfm context has a keylen, it's an HMAC.
1953497f2e6bSLee Nipper 	 * A first or last (ie. not middle) descriptor must request HMAC.
1954497f2e6bSLee Nipper 	 */
1955497f2e6bSLee Nipper 	if (ctx->keylen && (req_ctx->first || req_ctx->last))
1956497f2e6bSLee Nipper 		edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_HMAC;
1957497f2e6bSLee Nipper 
1958497f2e6bSLee Nipper 	return common_nonsnoop_hash(edesc, areq, nbytes_to_hash,
1959497f2e6bSLee Nipper 				    ahash_done);
1960497f2e6bSLee Nipper }
1961497f2e6bSLee Nipper 
1962497f2e6bSLee Nipper static int ahash_update(struct ahash_request *areq)
1963497f2e6bSLee Nipper {
1964497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
1965497f2e6bSLee Nipper 
1966497f2e6bSLee Nipper 	req_ctx->last = 0;
1967497f2e6bSLee Nipper 
1968497f2e6bSLee Nipper 	return ahash_process_req(areq, areq->nbytes);
1969497f2e6bSLee Nipper }
1970497f2e6bSLee Nipper 
1971497f2e6bSLee Nipper static int ahash_final(struct ahash_request *areq)
1972497f2e6bSLee Nipper {
1973497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
1974497f2e6bSLee Nipper 
1975497f2e6bSLee Nipper 	req_ctx->last = 1;
1976497f2e6bSLee Nipper 
1977497f2e6bSLee Nipper 	return ahash_process_req(areq, 0);
1978497f2e6bSLee Nipper }
1979497f2e6bSLee Nipper 
1980497f2e6bSLee Nipper static int ahash_finup(struct ahash_request *areq)
1981497f2e6bSLee Nipper {
1982497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
1983497f2e6bSLee Nipper 
1984497f2e6bSLee Nipper 	req_ctx->last = 1;
1985497f2e6bSLee Nipper 
1986497f2e6bSLee Nipper 	return ahash_process_req(areq, areq->nbytes);
1987497f2e6bSLee Nipper }
1988497f2e6bSLee Nipper 
1989497f2e6bSLee Nipper static int ahash_digest(struct ahash_request *areq)
1990497f2e6bSLee Nipper {
1991497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
199260f208d7SKim Phillips 	struct crypto_ahash *ahash = crypto_ahash_reqtfm(areq);
1993497f2e6bSLee Nipper 
199460f208d7SKim Phillips 	ahash->init(areq);
1995497f2e6bSLee Nipper 	req_ctx->last = 1;
1996497f2e6bSLee Nipper 
1997497f2e6bSLee Nipper 	return ahash_process_req(areq, areq->nbytes);
1998497f2e6bSLee Nipper }
1999497f2e6bSLee Nipper 
20003639ca84SHoria Geant? static int ahash_export(struct ahash_request *areq, void *out)
20013639ca84SHoria Geant? {
20023639ca84SHoria Geant? 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
20033639ca84SHoria Geant? 	struct talitos_export_state *export = out;
20043639ca84SHoria Geant? 
20053639ca84SHoria Geant? 	memcpy(export->hw_context, req_ctx->hw_context,
20063639ca84SHoria Geant? 	       req_ctx->hw_context_size);
20073639ca84SHoria Geant? 	memcpy(export->buf, req_ctx->buf, req_ctx->nbuf);
20083639ca84SHoria Geant? 	export->swinit = req_ctx->swinit;
20093639ca84SHoria Geant? 	export->first = req_ctx->first;
20103639ca84SHoria Geant? 	export->last = req_ctx->last;
20113639ca84SHoria Geant? 	export->to_hash_later = req_ctx->to_hash_later;
20123639ca84SHoria Geant? 	export->nbuf = req_ctx->nbuf;
20133639ca84SHoria Geant? 
20143639ca84SHoria Geant? 	return 0;
20153639ca84SHoria Geant? }
20163639ca84SHoria Geant? 
20173639ca84SHoria Geant? static int ahash_import(struct ahash_request *areq, const void *in)
20183639ca84SHoria Geant? {
20193639ca84SHoria Geant? 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
20203639ca84SHoria Geant? 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
20213639ca84SHoria Geant? 	const struct talitos_export_state *export = in;
20223639ca84SHoria Geant? 
20233639ca84SHoria Geant? 	memset(req_ctx, 0, sizeof(*req_ctx));
20243639ca84SHoria Geant? 	req_ctx->hw_context_size =
20253639ca84SHoria Geant? 		(crypto_ahash_digestsize(tfm) <= SHA256_DIGEST_SIZE)
20263639ca84SHoria Geant? 			? TALITOS_MDEU_CONTEXT_SIZE_MD5_SHA1_SHA256
20273639ca84SHoria Geant? 			: TALITOS_MDEU_CONTEXT_SIZE_SHA384_SHA512;
20283639ca84SHoria Geant? 	memcpy(req_ctx->hw_context, export->hw_context,
20293639ca84SHoria Geant? 	       req_ctx->hw_context_size);
20303639ca84SHoria Geant? 	memcpy(req_ctx->buf, export->buf, export->nbuf);
20313639ca84SHoria Geant? 	req_ctx->swinit = export->swinit;
20323639ca84SHoria Geant? 	req_ctx->first = export->first;
20333639ca84SHoria Geant? 	req_ctx->last = export->last;
20343639ca84SHoria Geant? 	req_ctx->to_hash_later = export->to_hash_later;
20353639ca84SHoria Geant? 	req_ctx->nbuf = export->nbuf;
20363639ca84SHoria Geant? 
20373639ca84SHoria Geant? 	return 0;
20383639ca84SHoria Geant? }
20393639ca84SHoria Geant? 
204079b3a418SLee Nipper struct keyhash_result {
204179b3a418SLee Nipper 	struct completion completion;
204279b3a418SLee Nipper 	int err;
204379b3a418SLee Nipper };
204479b3a418SLee Nipper 
204579b3a418SLee Nipper static void keyhash_complete(struct crypto_async_request *req, int err)
204679b3a418SLee Nipper {
204779b3a418SLee Nipper 	struct keyhash_result *res = req->data;
204879b3a418SLee Nipper 
204979b3a418SLee Nipper 	if (err == -EINPROGRESS)
205079b3a418SLee Nipper 		return;
205179b3a418SLee Nipper 
205279b3a418SLee Nipper 	res->err = err;
205379b3a418SLee Nipper 	complete(&res->completion);
205479b3a418SLee Nipper }
205579b3a418SLee Nipper 
205679b3a418SLee Nipper static int keyhash(struct crypto_ahash *tfm, const u8 *key, unsigned int keylen,
205779b3a418SLee Nipper 		   u8 *hash)
205879b3a418SLee Nipper {
205979b3a418SLee Nipper 	struct talitos_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm));
206079b3a418SLee Nipper 
206179b3a418SLee Nipper 	struct scatterlist sg[1];
206279b3a418SLee Nipper 	struct ahash_request *req;
206379b3a418SLee Nipper 	struct keyhash_result hresult;
206479b3a418SLee Nipper 	int ret;
206579b3a418SLee Nipper 
206679b3a418SLee Nipper 	init_completion(&hresult.completion);
206779b3a418SLee Nipper 
206879b3a418SLee Nipper 	req = ahash_request_alloc(tfm, GFP_KERNEL);
206979b3a418SLee Nipper 	if (!req)
207079b3a418SLee Nipper 		return -ENOMEM;
207179b3a418SLee Nipper 
207279b3a418SLee Nipper 	/* Keep tfm keylen == 0 during hash of the long key */
207379b3a418SLee Nipper 	ctx->keylen = 0;
207479b3a418SLee Nipper 	ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
207579b3a418SLee Nipper 				   keyhash_complete, &hresult);
207679b3a418SLee Nipper 
207779b3a418SLee Nipper 	sg_init_one(&sg[0], key, keylen);
207879b3a418SLee Nipper 
207979b3a418SLee Nipper 	ahash_request_set_crypt(req, sg, hash, keylen);
208079b3a418SLee Nipper 	ret = crypto_ahash_digest(req);
208179b3a418SLee Nipper 	switch (ret) {
208279b3a418SLee Nipper 	case 0:
208379b3a418SLee Nipper 		break;
208479b3a418SLee Nipper 	case -EINPROGRESS:
208579b3a418SLee Nipper 	case -EBUSY:
208679b3a418SLee Nipper 		ret = wait_for_completion_interruptible(
208779b3a418SLee Nipper 			&hresult.completion);
208879b3a418SLee Nipper 		if (!ret)
208979b3a418SLee Nipper 			ret = hresult.err;
209079b3a418SLee Nipper 		break;
209179b3a418SLee Nipper 	default:
209279b3a418SLee Nipper 		break;
209379b3a418SLee Nipper 	}
209479b3a418SLee Nipper 	ahash_request_free(req);
209579b3a418SLee Nipper 
209679b3a418SLee Nipper 	return ret;
209779b3a418SLee Nipper }
209879b3a418SLee Nipper 
209979b3a418SLee Nipper static int ahash_setkey(struct crypto_ahash *tfm, const u8 *key,
210079b3a418SLee Nipper 			unsigned int keylen)
210179b3a418SLee Nipper {
210279b3a418SLee Nipper 	struct talitos_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm));
210379b3a418SLee Nipper 	unsigned int blocksize =
210479b3a418SLee Nipper 			crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm));
210579b3a418SLee Nipper 	unsigned int digestsize = crypto_ahash_digestsize(tfm);
210679b3a418SLee Nipper 	unsigned int keysize = keylen;
210779b3a418SLee Nipper 	u8 hash[SHA512_DIGEST_SIZE];
210879b3a418SLee Nipper 	int ret;
210979b3a418SLee Nipper 
211079b3a418SLee Nipper 	if (keylen <= blocksize)
211179b3a418SLee Nipper 		memcpy(ctx->key, key, keysize);
211279b3a418SLee Nipper 	else {
211379b3a418SLee Nipper 		/* Must get the hash of the long key */
211479b3a418SLee Nipper 		ret = keyhash(tfm, key, keylen, hash);
211579b3a418SLee Nipper 
211679b3a418SLee Nipper 		if (ret) {
211779b3a418SLee Nipper 			crypto_ahash_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
211879b3a418SLee Nipper 			return -EINVAL;
211979b3a418SLee Nipper 		}
212079b3a418SLee Nipper 
212179b3a418SLee Nipper 		keysize = digestsize;
212279b3a418SLee Nipper 		memcpy(ctx->key, hash, digestsize);
212379b3a418SLee Nipper 	}
212479b3a418SLee Nipper 
212579b3a418SLee Nipper 	ctx->keylen = keysize;
212679b3a418SLee Nipper 
212779b3a418SLee Nipper 	return 0;
212879b3a418SLee Nipper }
212979b3a418SLee Nipper 
213079b3a418SLee Nipper 
21319c4a7965SKim Phillips struct talitos_alg_template {
2132d5e4aaefSLee Nipper 	u32 type;
2133b0057763SLEROY Christophe 	u32 priority;
2134d5e4aaefSLee Nipper 	union {
2135d5e4aaefSLee Nipper 		struct crypto_alg crypto;
2136acbf7c62SLee Nipper 		struct ahash_alg hash;
2137aeb4c132SHerbert Xu 		struct aead_alg aead;
2138d5e4aaefSLee Nipper 	} alg;
21399c4a7965SKim Phillips 	__be32 desc_hdr_template;
21409c4a7965SKim Phillips };
21419c4a7965SKim Phillips 
21429c4a7965SKim Phillips static struct talitos_alg_template driver_algs[] = {
2143991155baSHoria Geanta 	/* AEAD algorithms.  These use a single-pass ipsec_esp descriptor */
2144d5e4aaefSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2145aeb4c132SHerbert Xu 		.alg.aead = {
2146aeb4c132SHerbert Xu 			.base = {
214756af8cd4SLee Nipper 				.cra_name = "authenc(hmac(sha1),cbc(aes))",
2148aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha1-"
2149aeb4c132SHerbert Xu 						   "cbc-aes-talitos",
215056af8cd4SLee Nipper 				.cra_blocksize = AES_BLOCK_SIZE,
2151aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2152aeb4c132SHerbert Xu 			},
21533952f17eSLee Nipper 			.ivsize = AES_BLOCK_SIZE,
21543952f17eSLee Nipper 			.maxauthsize = SHA1_DIGEST_SIZE,
21559c4a7965SKim Phillips 		},
21569c4a7965SKim Phillips 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
21579c4a7965SKim Phillips 			             DESC_HDR_SEL0_AESU |
21589c4a7965SKim Phillips 		                     DESC_HDR_MODE0_AESU_CBC |
21599c4a7965SKim Phillips 		                     DESC_HDR_SEL1_MDEUA |
21609c4a7965SKim Phillips 		                     DESC_HDR_MODE1_MDEU_INIT |
21619c4a7965SKim Phillips 		                     DESC_HDR_MODE1_MDEU_PAD |
21629c4a7965SKim Phillips 		                     DESC_HDR_MODE1_MDEU_SHA1_HMAC,
216370bcaca7SLee Nipper 	},
2164d5e4aaefSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AEAD,
21657405c8d7SLEROY Christophe 		.priority = TALITOS_CRA_PRIORITY_AEAD_HSNA,
21667405c8d7SLEROY Christophe 		.alg.aead = {
21677405c8d7SLEROY Christophe 			.base = {
21687405c8d7SLEROY Christophe 				.cra_name = "authenc(hmac(sha1),cbc(aes))",
21697405c8d7SLEROY Christophe 				.cra_driver_name = "authenc-hmac-sha1-"
21707405c8d7SLEROY Christophe 						   "cbc-aes-talitos",
21717405c8d7SLEROY Christophe 				.cra_blocksize = AES_BLOCK_SIZE,
21727405c8d7SLEROY Christophe 				.cra_flags = CRYPTO_ALG_ASYNC,
21737405c8d7SLEROY Christophe 			},
21747405c8d7SLEROY Christophe 			.ivsize = AES_BLOCK_SIZE,
21757405c8d7SLEROY Christophe 			.maxauthsize = SHA1_DIGEST_SIZE,
21767405c8d7SLEROY Christophe 		},
21777405c8d7SLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU |
21787405c8d7SLEROY Christophe 				     DESC_HDR_SEL0_AESU |
21797405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_AESU_CBC |
21807405c8d7SLEROY Christophe 				     DESC_HDR_SEL1_MDEUA |
21817405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_INIT |
21827405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_PAD |
21837405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_SHA1_HMAC,
21847405c8d7SLEROY Christophe 	},
21857405c8d7SLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2186aeb4c132SHerbert Xu 		.alg.aead = {
2187aeb4c132SHerbert Xu 			.base = {
2188aeb4c132SHerbert Xu 				.cra_name = "authenc(hmac(sha1),"
2189aeb4c132SHerbert Xu 					    "cbc(des3_ede))",
2190aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha1-"
2191aeb4c132SHerbert Xu 						   "cbc-3des-talitos",
219256af8cd4SLee Nipper 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
2193aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2194aeb4c132SHerbert Xu 			},
21953952f17eSLee Nipper 			.ivsize = DES3_EDE_BLOCK_SIZE,
21963952f17eSLee Nipper 			.maxauthsize = SHA1_DIGEST_SIZE,
219770bcaca7SLee Nipper 		},
219870bcaca7SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
219970bcaca7SLee Nipper 			             DESC_HDR_SEL0_DEU |
220070bcaca7SLee Nipper 		                     DESC_HDR_MODE0_DEU_CBC |
220170bcaca7SLee Nipper 		                     DESC_HDR_MODE0_DEU_3DES |
220270bcaca7SLee Nipper 		                     DESC_HDR_SEL1_MDEUA |
220370bcaca7SLee Nipper 		                     DESC_HDR_MODE1_MDEU_INIT |
220470bcaca7SLee Nipper 		                     DESC_HDR_MODE1_MDEU_PAD |
220570bcaca7SLee Nipper 		                     DESC_HDR_MODE1_MDEU_SHA1_HMAC,
22063952f17eSLee Nipper 	},
2207d5e4aaefSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AEAD,
22087405c8d7SLEROY Christophe 		.priority = TALITOS_CRA_PRIORITY_AEAD_HSNA,
22097405c8d7SLEROY Christophe 		.alg.aead = {
22107405c8d7SLEROY Christophe 			.base = {
22117405c8d7SLEROY Christophe 				.cra_name = "authenc(hmac(sha1),"
22127405c8d7SLEROY Christophe 					    "cbc(des3_ede))",
22137405c8d7SLEROY Christophe 				.cra_driver_name = "authenc-hmac-sha1-"
22147405c8d7SLEROY Christophe 						   "cbc-3des-talitos",
22157405c8d7SLEROY Christophe 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
22167405c8d7SLEROY Christophe 				.cra_flags = CRYPTO_ALG_ASYNC,
22177405c8d7SLEROY Christophe 			},
22187405c8d7SLEROY Christophe 			.ivsize = DES3_EDE_BLOCK_SIZE,
22197405c8d7SLEROY Christophe 			.maxauthsize = SHA1_DIGEST_SIZE,
22207405c8d7SLEROY Christophe 		},
22217405c8d7SLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU |
22227405c8d7SLEROY Christophe 				     DESC_HDR_SEL0_DEU |
22237405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_DEU_CBC |
22247405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_DEU_3DES |
22257405c8d7SLEROY Christophe 				     DESC_HDR_SEL1_MDEUA |
22267405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_INIT |
22277405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_PAD |
22287405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_SHA1_HMAC,
22297405c8d7SLEROY Christophe 	},
22307405c8d7SLEROY Christophe 	{       .type = CRYPTO_ALG_TYPE_AEAD,
2231aeb4c132SHerbert Xu 		.alg.aead = {
2232aeb4c132SHerbert Xu 			.base = {
2233357fb605SHoria Geanta 				.cra_name = "authenc(hmac(sha224),cbc(aes))",
2234aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha224-"
2235aeb4c132SHerbert Xu 						   "cbc-aes-talitos",
2236357fb605SHoria Geanta 				.cra_blocksize = AES_BLOCK_SIZE,
2237aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2238aeb4c132SHerbert Xu 			},
2239357fb605SHoria Geanta 			.ivsize = AES_BLOCK_SIZE,
2240357fb605SHoria Geanta 			.maxauthsize = SHA224_DIGEST_SIZE,
2241357fb605SHoria Geanta 		},
2242357fb605SHoria Geanta 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
2243357fb605SHoria Geanta 				     DESC_HDR_SEL0_AESU |
2244357fb605SHoria Geanta 				     DESC_HDR_MODE0_AESU_CBC |
2245357fb605SHoria Geanta 				     DESC_HDR_SEL1_MDEUA |
2246357fb605SHoria Geanta 				     DESC_HDR_MODE1_MDEU_INIT |
2247357fb605SHoria Geanta 				     DESC_HDR_MODE1_MDEU_PAD |
2248357fb605SHoria Geanta 				     DESC_HDR_MODE1_MDEU_SHA224_HMAC,
2249357fb605SHoria Geanta 	},
2250357fb605SHoria Geanta 	{       .type = CRYPTO_ALG_TYPE_AEAD,
22517405c8d7SLEROY Christophe 		.priority = TALITOS_CRA_PRIORITY_AEAD_HSNA,
22527405c8d7SLEROY Christophe 		.alg.aead = {
22537405c8d7SLEROY Christophe 			.base = {
22547405c8d7SLEROY Christophe 				.cra_name = "authenc(hmac(sha224),cbc(aes))",
22557405c8d7SLEROY Christophe 				.cra_driver_name = "authenc-hmac-sha224-"
22567405c8d7SLEROY Christophe 						   "cbc-aes-talitos",
22577405c8d7SLEROY Christophe 				.cra_blocksize = AES_BLOCK_SIZE,
22587405c8d7SLEROY Christophe 				.cra_flags = CRYPTO_ALG_ASYNC,
22597405c8d7SLEROY Christophe 			},
22607405c8d7SLEROY Christophe 			.ivsize = AES_BLOCK_SIZE,
22617405c8d7SLEROY Christophe 			.maxauthsize = SHA224_DIGEST_SIZE,
22627405c8d7SLEROY Christophe 		},
22637405c8d7SLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU |
22647405c8d7SLEROY Christophe 				     DESC_HDR_SEL0_AESU |
22657405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_AESU_CBC |
22667405c8d7SLEROY Christophe 				     DESC_HDR_SEL1_MDEUA |
22677405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_INIT |
22687405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_PAD |
22697405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_SHA224_HMAC,
22707405c8d7SLEROY Christophe 	},
22717405c8d7SLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2272aeb4c132SHerbert Xu 		.alg.aead = {
2273aeb4c132SHerbert Xu 			.base = {
2274aeb4c132SHerbert Xu 				.cra_name = "authenc(hmac(sha224),"
2275aeb4c132SHerbert Xu 					    "cbc(des3_ede))",
2276aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha224-"
2277aeb4c132SHerbert Xu 						   "cbc-3des-talitos",
2278357fb605SHoria Geanta 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
2279aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2280aeb4c132SHerbert Xu 			},
2281357fb605SHoria Geanta 			.ivsize = DES3_EDE_BLOCK_SIZE,
2282357fb605SHoria Geanta 			.maxauthsize = SHA224_DIGEST_SIZE,
2283357fb605SHoria Geanta 		},
2284357fb605SHoria Geanta 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
2285357fb605SHoria Geanta 			             DESC_HDR_SEL0_DEU |
2286357fb605SHoria Geanta 		                     DESC_HDR_MODE0_DEU_CBC |
2287357fb605SHoria Geanta 		                     DESC_HDR_MODE0_DEU_3DES |
2288357fb605SHoria Geanta 		                     DESC_HDR_SEL1_MDEUA |
2289357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_INIT |
2290357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_PAD |
2291357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_SHA224_HMAC,
2292357fb605SHoria Geanta 	},
2293357fb605SHoria Geanta 	{	.type = CRYPTO_ALG_TYPE_AEAD,
22947405c8d7SLEROY Christophe 		.priority = TALITOS_CRA_PRIORITY_AEAD_HSNA,
22957405c8d7SLEROY Christophe 		.alg.aead = {
22967405c8d7SLEROY Christophe 			.base = {
22977405c8d7SLEROY Christophe 				.cra_name = "authenc(hmac(sha224),"
22987405c8d7SLEROY Christophe 					    "cbc(des3_ede))",
22997405c8d7SLEROY Christophe 				.cra_driver_name = "authenc-hmac-sha224-"
23007405c8d7SLEROY Christophe 						   "cbc-3des-talitos",
23017405c8d7SLEROY Christophe 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
23027405c8d7SLEROY Christophe 				.cra_flags = CRYPTO_ALG_ASYNC,
23037405c8d7SLEROY Christophe 			},
23047405c8d7SLEROY Christophe 			.ivsize = DES3_EDE_BLOCK_SIZE,
23057405c8d7SLEROY Christophe 			.maxauthsize = SHA224_DIGEST_SIZE,
23067405c8d7SLEROY Christophe 		},
23077405c8d7SLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU |
23087405c8d7SLEROY Christophe 				     DESC_HDR_SEL0_DEU |
23097405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_DEU_CBC |
23107405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_DEU_3DES |
23117405c8d7SLEROY Christophe 				     DESC_HDR_SEL1_MDEUA |
23127405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_INIT |
23137405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_PAD |
23147405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_SHA224_HMAC,
23157405c8d7SLEROY Christophe 	},
23167405c8d7SLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2317aeb4c132SHerbert Xu 		.alg.aead = {
2318aeb4c132SHerbert Xu 			.base = {
231956af8cd4SLee Nipper 				.cra_name = "authenc(hmac(sha256),cbc(aes))",
2320aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha256-"
2321aeb4c132SHerbert Xu 						   "cbc-aes-talitos",
232256af8cd4SLee Nipper 				.cra_blocksize = AES_BLOCK_SIZE,
2323aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2324aeb4c132SHerbert Xu 			},
23253952f17eSLee Nipper 			.ivsize = AES_BLOCK_SIZE,
23263952f17eSLee Nipper 			.maxauthsize = SHA256_DIGEST_SIZE,
23273952f17eSLee Nipper 		},
23283952f17eSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
23293952f17eSLee Nipper 			             DESC_HDR_SEL0_AESU |
23303952f17eSLee Nipper 		                     DESC_HDR_MODE0_AESU_CBC |
23313952f17eSLee Nipper 		                     DESC_HDR_SEL1_MDEUA |
23323952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_INIT |
23333952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_PAD |
23343952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_SHA256_HMAC,
23353952f17eSLee Nipper 	},
2336d5e4aaefSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AEAD,
23377405c8d7SLEROY Christophe 		.priority = TALITOS_CRA_PRIORITY_AEAD_HSNA,
23387405c8d7SLEROY Christophe 		.alg.aead = {
23397405c8d7SLEROY Christophe 			.base = {
23407405c8d7SLEROY Christophe 				.cra_name = "authenc(hmac(sha256),cbc(aes))",
23417405c8d7SLEROY Christophe 				.cra_driver_name = "authenc-hmac-sha256-"
23427405c8d7SLEROY Christophe 						   "cbc-aes-talitos",
23437405c8d7SLEROY Christophe 				.cra_blocksize = AES_BLOCK_SIZE,
23447405c8d7SLEROY Christophe 				.cra_flags = CRYPTO_ALG_ASYNC,
23457405c8d7SLEROY Christophe 			},
23467405c8d7SLEROY Christophe 			.ivsize = AES_BLOCK_SIZE,
23477405c8d7SLEROY Christophe 			.maxauthsize = SHA256_DIGEST_SIZE,
23487405c8d7SLEROY Christophe 		},
23497405c8d7SLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU |
23507405c8d7SLEROY Christophe 				     DESC_HDR_SEL0_AESU |
23517405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_AESU_CBC |
23527405c8d7SLEROY Christophe 				     DESC_HDR_SEL1_MDEUA |
23537405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_INIT |
23547405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_PAD |
23557405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_SHA256_HMAC,
23567405c8d7SLEROY Christophe 	},
23577405c8d7SLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2358aeb4c132SHerbert Xu 		.alg.aead = {
2359aeb4c132SHerbert Xu 			.base = {
2360aeb4c132SHerbert Xu 				.cra_name = "authenc(hmac(sha256),"
2361aeb4c132SHerbert Xu 					    "cbc(des3_ede))",
2362aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha256-"
2363aeb4c132SHerbert Xu 						   "cbc-3des-talitos",
236456af8cd4SLee Nipper 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
2365aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2366aeb4c132SHerbert Xu 			},
23673952f17eSLee Nipper 			.ivsize = DES3_EDE_BLOCK_SIZE,
23683952f17eSLee Nipper 			.maxauthsize = SHA256_DIGEST_SIZE,
23693952f17eSLee Nipper 		},
23703952f17eSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
23713952f17eSLee Nipper 			             DESC_HDR_SEL0_DEU |
23723952f17eSLee Nipper 		                     DESC_HDR_MODE0_DEU_CBC |
23733952f17eSLee Nipper 		                     DESC_HDR_MODE0_DEU_3DES |
23743952f17eSLee Nipper 		                     DESC_HDR_SEL1_MDEUA |
23753952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_INIT |
23763952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_PAD |
23773952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_SHA256_HMAC,
23783952f17eSLee Nipper 	},
2379d5e4aaefSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AEAD,
23807405c8d7SLEROY Christophe 		.priority = TALITOS_CRA_PRIORITY_AEAD_HSNA,
23817405c8d7SLEROY Christophe 		.alg.aead = {
23827405c8d7SLEROY Christophe 			.base = {
23837405c8d7SLEROY Christophe 				.cra_name = "authenc(hmac(sha256),"
23847405c8d7SLEROY Christophe 					    "cbc(des3_ede))",
23857405c8d7SLEROY Christophe 				.cra_driver_name = "authenc-hmac-sha256-"
23867405c8d7SLEROY Christophe 						   "cbc-3des-talitos",
23877405c8d7SLEROY Christophe 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
23887405c8d7SLEROY Christophe 				.cra_flags = CRYPTO_ALG_ASYNC,
23897405c8d7SLEROY Christophe 			},
23907405c8d7SLEROY Christophe 			.ivsize = DES3_EDE_BLOCK_SIZE,
23917405c8d7SLEROY Christophe 			.maxauthsize = SHA256_DIGEST_SIZE,
23927405c8d7SLEROY Christophe 		},
23937405c8d7SLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU |
23947405c8d7SLEROY Christophe 				     DESC_HDR_SEL0_DEU |
23957405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_DEU_CBC |
23967405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_DEU_3DES |
23977405c8d7SLEROY Christophe 				     DESC_HDR_SEL1_MDEUA |
23987405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_INIT |
23997405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_PAD |
24007405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_SHA256_HMAC,
24017405c8d7SLEROY Christophe 	},
24027405c8d7SLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2403aeb4c132SHerbert Xu 		.alg.aead = {
2404aeb4c132SHerbert Xu 			.base = {
2405357fb605SHoria Geanta 				.cra_name = "authenc(hmac(sha384),cbc(aes))",
2406aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha384-"
2407aeb4c132SHerbert Xu 						   "cbc-aes-talitos",
2408357fb605SHoria Geanta 				.cra_blocksize = AES_BLOCK_SIZE,
2409aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2410aeb4c132SHerbert Xu 			},
2411357fb605SHoria Geanta 			.ivsize = AES_BLOCK_SIZE,
2412357fb605SHoria Geanta 			.maxauthsize = SHA384_DIGEST_SIZE,
2413357fb605SHoria Geanta 		},
2414357fb605SHoria Geanta 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
2415357fb605SHoria Geanta 			             DESC_HDR_SEL0_AESU |
2416357fb605SHoria Geanta 		                     DESC_HDR_MODE0_AESU_CBC |
2417357fb605SHoria Geanta 		                     DESC_HDR_SEL1_MDEUB |
2418357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_INIT |
2419357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_PAD |
2420357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEUB_SHA384_HMAC,
2421357fb605SHoria Geanta 	},
2422357fb605SHoria Geanta 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2423aeb4c132SHerbert Xu 		.alg.aead = {
2424aeb4c132SHerbert Xu 			.base = {
2425aeb4c132SHerbert Xu 				.cra_name = "authenc(hmac(sha384),"
2426aeb4c132SHerbert Xu 					    "cbc(des3_ede))",
2427aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha384-"
2428aeb4c132SHerbert Xu 						   "cbc-3des-talitos",
2429357fb605SHoria Geanta 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
2430aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2431aeb4c132SHerbert Xu 			},
2432357fb605SHoria Geanta 			.ivsize = DES3_EDE_BLOCK_SIZE,
2433357fb605SHoria Geanta 			.maxauthsize = SHA384_DIGEST_SIZE,
2434357fb605SHoria Geanta 		},
2435357fb605SHoria Geanta 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
2436357fb605SHoria Geanta 			             DESC_HDR_SEL0_DEU |
2437357fb605SHoria Geanta 		                     DESC_HDR_MODE0_DEU_CBC |
2438357fb605SHoria Geanta 		                     DESC_HDR_MODE0_DEU_3DES |
2439357fb605SHoria Geanta 		                     DESC_HDR_SEL1_MDEUB |
2440357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_INIT |
2441357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_PAD |
2442357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEUB_SHA384_HMAC,
2443357fb605SHoria Geanta 	},
2444357fb605SHoria Geanta 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2445aeb4c132SHerbert Xu 		.alg.aead = {
2446aeb4c132SHerbert Xu 			.base = {
2447357fb605SHoria Geanta 				.cra_name = "authenc(hmac(sha512),cbc(aes))",
2448aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha512-"
2449aeb4c132SHerbert Xu 						   "cbc-aes-talitos",
2450357fb605SHoria Geanta 				.cra_blocksize = AES_BLOCK_SIZE,
2451aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2452aeb4c132SHerbert Xu 			},
2453357fb605SHoria Geanta 			.ivsize = AES_BLOCK_SIZE,
2454357fb605SHoria Geanta 			.maxauthsize = SHA512_DIGEST_SIZE,
2455357fb605SHoria Geanta 		},
2456357fb605SHoria Geanta 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
2457357fb605SHoria Geanta 			             DESC_HDR_SEL0_AESU |
2458357fb605SHoria Geanta 		                     DESC_HDR_MODE0_AESU_CBC |
2459357fb605SHoria Geanta 		                     DESC_HDR_SEL1_MDEUB |
2460357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_INIT |
2461357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_PAD |
2462357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEUB_SHA512_HMAC,
2463357fb605SHoria Geanta 	},
2464357fb605SHoria Geanta 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2465aeb4c132SHerbert Xu 		.alg.aead = {
2466aeb4c132SHerbert Xu 			.base = {
2467aeb4c132SHerbert Xu 				.cra_name = "authenc(hmac(sha512),"
2468aeb4c132SHerbert Xu 					    "cbc(des3_ede))",
2469aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha512-"
2470aeb4c132SHerbert Xu 						   "cbc-3des-talitos",
2471357fb605SHoria Geanta 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
2472aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2473aeb4c132SHerbert Xu 			},
2474357fb605SHoria Geanta 			.ivsize = DES3_EDE_BLOCK_SIZE,
2475357fb605SHoria Geanta 			.maxauthsize = SHA512_DIGEST_SIZE,
2476357fb605SHoria Geanta 		},
2477357fb605SHoria Geanta 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
2478357fb605SHoria Geanta 			             DESC_HDR_SEL0_DEU |
2479357fb605SHoria Geanta 		                     DESC_HDR_MODE0_DEU_CBC |
2480357fb605SHoria Geanta 		                     DESC_HDR_MODE0_DEU_3DES |
2481357fb605SHoria Geanta 		                     DESC_HDR_SEL1_MDEUB |
2482357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_INIT |
2483357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_PAD |
2484357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEUB_SHA512_HMAC,
2485357fb605SHoria Geanta 	},
2486357fb605SHoria Geanta 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2487aeb4c132SHerbert Xu 		.alg.aead = {
2488aeb4c132SHerbert Xu 			.base = {
248956af8cd4SLee Nipper 				.cra_name = "authenc(hmac(md5),cbc(aes))",
2490aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-md5-"
2491aeb4c132SHerbert Xu 						   "cbc-aes-talitos",
249256af8cd4SLee Nipper 				.cra_blocksize = AES_BLOCK_SIZE,
2493aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2494aeb4c132SHerbert Xu 			},
24953952f17eSLee Nipper 			.ivsize = AES_BLOCK_SIZE,
24963952f17eSLee Nipper 			.maxauthsize = MD5_DIGEST_SIZE,
24973952f17eSLee Nipper 		},
24983952f17eSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
24993952f17eSLee Nipper 			             DESC_HDR_SEL0_AESU |
25003952f17eSLee Nipper 		                     DESC_HDR_MODE0_AESU_CBC |
25013952f17eSLee Nipper 		                     DESC_HDR_SEL1_MDEUA |
25023952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_INIT |
25033952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_PAD |
25043952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_MD5_HMAC,
25053952f17eSLee Nipper 	},
2506d5e4aaefSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AEAD,
25077405c8d7SLEROY Christophe 		.priority = TALITOS_CRA_PRIORITY_AEAD_HSNA,
25087405c8d7SLEROY Christophe 		.alg.aead = {
25097405c8d7SLEROY Christophe 			.base = {
25107405c8d7SLEROY Christophe 				.cra_name = "authenc(hmac(md5),cbc(aes))",
25117405c8d7SLEROY Christophe 				.cra_driver_name = "authenc-hmac-md5-"
25127405c8d7SLEROY Christophe 						   "cbc-aes-talitos",
25137405c8d7SLEROY Christophe 				.cra_blocksize = AES_BLOCK_SIZE,
25147405c8d7SLEROY Christophe 				.cra_flags = CRYPTO_ALG_ASYNC,
25157405c8d7SLEROY Christophe 			},
25167405c8d7SLEROY Christophe 			.ivsize = AES_BLOCK_SIZE,
25177405c8d7SLEROY Christophe 			.maxauthsize = MD5_DIGEST_SIZE,
25187405c8d7SLEROY Christophe 		},
25197405c8d7SLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU |
25207405c8d7SLEROY Christophe 				     DESC_HDR_SEL0_AESU |
25217405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_AESU_CBC |
25227405c8d7SLEROY Christophe 				     DESC_HDR_SEL1_MDEUA |
25237405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_INIT |
25247405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_PAD |
25257405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_MD5_HMAC,
25267405c8d7SLEROY Christophe 	},
25277405c8d7SLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2528aeb4c132SHerbert Xu 		.alg.aead = {
2529aeb4c132SHerbert Xu 			.base = {
253056af8cd4SLee Nipper 				.cra_name = "authenc(hmac(md5),cbc(des3_ede))",
2531aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-md5-"
2532aeb4c132SHerbert Xu 						   "cbc-3des-talitos",
253356af8cd4SLee Nipper 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
2534aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2535aeb4c132SHerbert Xu 			},
25363952f17eSLee Nipper 			.ivsize = DES3_EDE_BLOCK_SIZE,
25373952f17eSLee Nipper 			.maxauthsize = MD5_DIGEST_SIZE,
25383952f17eSLee Nipper 		},
25393952f17eSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
25403952f17eSLee Nipper 			             DESC_HDR_SEL0_DEU |
25413952f17eSLee Nipper 		                     DESC_HDR_MODE0_DEU_CBC |
25423952f17eSLee Nipper 		                     DESC_HDR_MODE0_DEU_3DES |
25433952f17eSLee Nipper 		                     DESC_HDR_SEL1_MDEUA |
25443952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_INIT |
25453952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_PAD |
25463952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_MD5_HMAC,
25474de9d0b5SLee Nipper 	},
25487405c8d7SLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_AEAD,
25497405c8d7SLEROY Christophe 		.priority = TALITOS_CRA_PRIORITY_AEAD_HSNA,
25507405c8d7SLEROY Christophe 		.alg.aead = {
25517405c8d7SLEROY Christophe 			.base = {
25527405c8d7SLEROY Christophe 				.cra_name = "authenc(hmac(md5),cbc(des3_ede))",
25537405c8d7SLEROY Christophe 				.cra_driver_name = "authenc-hmac-md5-"
25547405c8d7SLEROY Christophe 						   "cbc-3des-talitos",
25557405c8d7SLEROY Christophe 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
25567405c8d7SLEROY Christophe 				.cra_flags = CRYPTO_ALG_ASYNC,
25577405c8d7SLEROY Christophe 			},
25587405c8d7SLEROY Christophe 			.ivsize = DES3_EDE_BLOCK_SIZE,
25597405c8d7SLEROY Christophe 			.maxauthsize = MD5_DIGEST_SIZE,
25607405c8d7SLEROY Christophe 		},
25617405c8d7SLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU |
25627405c8d7SLEROY Christophe 				     DESC_HDR_SEL0_DEU |
25637405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_DEU_CBC |
25647405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_DEU_3DES |
25657405c8d7SLEROY Christophe 				     DESC_HDR_SEL1_MDEUA |
25667405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_INIT |
25677405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_PAD |
25687405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_MD5_HMAC,
25697405c8d7SLEROY Christophe 	},
25704de9d0b5SLee Nipper 	/* ABLKCIPHER algorithms. */
2571d5e4aaefSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_ABLKCIPHER,
2572d5e4aaefSLee Nipper 		.alg.crypto = {
25735e75ae1bSLEROY Christophe 			.cra_name = "ecb(aes)",
25745e75ae1bSLEROY Christophe 			.cra_driver_name = "ecb-aes-talitos",
25755e75ae1bSLEROY Christophe 			.cra_blocksize = AES_BLOCK_SIZE,
25765e75ae1bSLEROY Christophe 			.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
25775e75ae1bSLEROY Christophe 				     CRYPTO_ALG_ASYNC,
25785e75ae1bSLEROY Christophe 			.cra_ablkcipher = {
25795e75ae1bSLEROY Christophe 				.min_keysize = AES_MIN_KEY_SIZE,
25805e75ae1bSLEROY Christophe 				.max_keysize = AES_MAX_KEY_SIZE,
25815e75ae1bSLEROY Christophe 				.ivsize = AES_BLOCK_SIZE,
25825e75ae1bSLEROY Christophe 			}
25835e75ae1bSLEROY Christophe 		},
25845e75ae1bSLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
25855e75ae1bSLEROY Christophe 				     DESC_HDR_SEL0_AESU,
25865e75ae1bSLEROY Christophe 	},
25875e75ae1bSLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_ABLKCIPHER,
25885e75ae1bSLEROY Christophe 		.alg.crypto = {
25894de9d0b5SLee Nipper 			.cra_name = "cbc(aes)",
25904de9d0b5SLee Nipper 			.cra_driver_name = "cbc-aes-talitos",
25914de9d0b5SLee Nipper 			.cra_blocksize = AES_BLOCK_SIZE,
25924de9d0b5SLee Nipper 			.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
25934de9d0b5SLee Nipper                                      CRYPTO_ALG_ASYNC,
25944de9d0b5SLee Nipper 			.cra_ablkcipher = {
25954de9d0b5SLee Nipper 				.min_keysize = AES_MIN_KEY_SIZE,
25964de9d0b5SLee Nipper 				.max_keysize = AES_MAX_KEY_SIZE,
25974de9d0b5SLee Nipper 				.ivsize = AES_BLOCK_SIZE,
25984de9d0b5SLee Nipper 			}
25994de9d0b5SLee Nipper 		},
26004de9d0b5SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
26014de9d0b5SLee Nipper 				     DESC_HDR_SEL0_AESU |
26024de9d0b5SLee Nipper 				     DESC_HDR_MODE0_AESU_CBC,
26034de9d0b5SLee Nipper 	},
2604d5e4aaefSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_ABLKCIPHER,
2605d5e4aaefSLee Nipper 		.alg.crypto = {
26065e75ae1bSLEROY Christophe 			.cra_name = "ctr(aes)",
26075e75ae1bSLEROY Christophe 			.cra_driver_name = "ctr-aes-talitos",
26085e75ae1bSLEROY Christophe 			.cra_blocksize = AES_BLOCK_SIZE,
26095e75ae1bSLEROY Christophe 			.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
26105e75ae1bSLEROY Christophe 				     CRYPTO_ALG_ASYNC,
26115e75ae1bSLEROY Christophe 			.cra_ablkcipher = {
26125e75ae1bSLEROY Christophe 				.min_keysize = AES_MIN_KEY_SIZE,
26135e75ae1bSLEROY Christophe 				.max_keysize = AES_MAX_KEY_SIZE,
26145e75ae1bSLEROY Christophe 				.ivsize = AES_BLOCK_SIZE,
26155e75ae1bSLEROY Christophe 			}
26165e75ae1bSLEROY Christophe 		},
261770d355ccSLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_AESU_CTR_NONSNOOP |
26185e75ae1bSLEROY Christophe 				     DESC_HDR_SEL0_AESU |
26195e75ae1bSLEROY Christophe 				     DESC_HDR_MODE0_AESU_CTR,
26205e75ae1bSLEROY Christophe 	},
26215e75ae1bSLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_ABLKCIPHER,
26225e75ae1bSLEROY Christophe 		.alg.crypto = {
26235e75ae1bSLEROY Christophe 			.cra_name = "ecb(des)",
26245e75ae1bSLEROY Christophe 			.cra_driver_name = "ecb-des-talitos",
26255e75ae1bSLEROY Christophe 			.cra_blocksize = DES_BLOCK_SIZE,
26265e75ae1bSLEROY Christophe 			.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
26275e75ae1bSLEROY Christophe 				     CRYPTO_ALG_ASYNC,
26285e75ae1bSLEROY Christophe 			.cra_ablkcipher = {
26295e75ae1bSLEROY Christophe 				.min_keysize = DES_KEY_SIZE,
26305e75ae1bSLEROY Christophe 				.max_keysize = DES_KEY_SIZE,
26315e75ae1bSLEROY Christophe 				.ivsize = DES_BLOCK_SIZE,
26325e75ae1bSLEROY Christophe 			}
26335e75ae1bSLEROY Christophe 		},
26345e75ae1bSLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
26355e75ae1bSLEROY Christophe 				     DESC_HDR_SEL0_DEU,
26365e75ae1bSLEROY Christophe 	},
26375e75ae1bSLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_ABLKCIPHER,
26385e75ae1bSLEROY Christophe 		.alg.crypto = {
26395e75ae1bSLEROY Christophe 			.cra_name = "cbc(des)",
26405e75ae1bSLEROY Christophe 			.cra_driver_name = "cbc-des-talitos",
26415e75ae1bSLEROY Christophe 			.cra_blocksize = DES_BLOCK_SIZE,
26425e75ae1bSLEROY Christophe 			.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
26435e75ae1bSLEROY Christophe 				     CRYPTO_ALG_ASYNC,
26445e75ae1bSLEROY Christophe 			.cra_ablkcipher = {
26455e75ae1bSLEROY Christophe 				.min_keysize = DES_KEY_SIZE,
26465e75ae1bSLEROY Christophe 				.max_keysize = DES_KEY_SIZE,
26475e75ae1bSLEROY Christophe 				.ivsize = DES_BLOCK_SIZE,
26485e75ae1bSLEROY Christophe 			}
26495e75ae1bSLEROY Christophe 		},
26505e75ae1bSLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
26515e75ae1bSLEROY Christophe 				     DESC_HDR_SEL0_DEU |
26525e75ae1bSLEROY Christophe 				     DESC_HDR_MODE0_DEU_CBC,
26535e75ae1bSLEROY Christophe 	},
26545e75ae1bSLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_ABLKCIPHER,
26555e75ae1bSLEROY Christophe 		.alg.crypto = {
26565e75ae1bSLEROY Christophe 			.cra_name = "ecb(des3_ede)",
26575e75ae1bSLEROY Christophe 			.cra_driver_name = "ecb-3des-talitos",
26585e75ae1bSLEROY Christophe 			.cra_blocksize = DES3_EDE_BLOCK_SIZE,
26595e75ae1bSLEROY Christophe 			.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
26605e75ae1bSLEROY Christophe 				     CRYPTO_ALG_ASYNC,
26615e75ae1bSLEROY Christophe 			.cra_ablkcipher = {
26625e75ae1bSLEROY Christophe 				.min_keysize = DES3_EDE_KEY_SIZE,
26635e75ae1bSLEROY Christophe 				.max_keysize = DES3_EDE_KEY_SIZE,
26645e75ae1bSLEROY Christophe 				.ivsize = DES3_EDE_BLOCK_SIZE,
26655e75ae1bSLEROY Christophe 			}
26665e75ae1bSLEROY Christophe 		},
26675e75ae1bSLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
26685e75ae1bSLEROY Christophe 				     DESC_HDR_SEL0_DEU |
26695e75ae1bSLEROY Christophe 				     DESC_HDR_MODE0_DEU_3DES,
26705e75ae1bSLEROY Christophe 	},
26715e75ae1bSLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_ABLKCIPHER,
26725e75ae1bSLEROY Christophe 		.alg.crypto = {
26734de9d0b5SLee Nipper 			.cra_name = "cbc(des3_ede)",
26744de9d0b5SLee Nipper 			.cra_driver_name = "cbc-3des-talitos",
26754de9d0b5SLee Nipper 			.cra_blocksize = DES3_EDE_BLOCK_SIZE,
26764de9d0b5SLee Nipper 			.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
26774de9d0b5SLee Nipper                                      CRYPTO_ALG_ASYNC,
26784de9d0b5SLee Nipper 			.cra_ablkcipher = {
26794de9d0b5SLee Nipper 				.min_keysize = DES3_EDE_KEY_SIZE,
26804de9d0b5SLee Nipper 				.max_keysize = DES3_EDE_KEY_SIZE,
26814de9d0b5SLee Nipper 				.ivsize = DES3_EDE_BLOCK_SIZE,
26824de9d0b5SLee Nipper 			}
26834de9d0b5SLee Nipper 		},
26844de9d0b5SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
26854de9d0b5SLee Nipper 			             DESC_HDR_SEL0_DEU |
26864de9d0b5SLee Nipper 		                     DESC_HDR_MODE0_DEU_CBC |
26874de9d0b5SLee Nipper 		                     DESC_HDR_MODE0_DEU_3DES,
2688497f2e6bSLee Nipper 	},
2689497f2e6bSLee Nipper 	/* AHASH algorithms. */
2690497f2e6bSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
2691497f2e6bSLee Nipper 		.alg.hash = {
2692497f2e6bSLee Nipper 			.halg.digestsize = MD5_DIGEST_SIZE,
26933639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
2694497f2e6bSLee Nipper 			.halg.base = {
2695497f2e6bSLee Nipper 				.cra_name = "md5",
2696497f2e6bSLee Nipper 				.cra_driver_name = "md5-talitos",
2697b3988618SMartin Hicks 				.cra_blocksize = MD5_HMAC_BLOCK_SIZE,
2698497f2e6bSLee Nipper 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
2699497f2e6bSLee Nipper 					     CRYPTO_ALG_ASYNC,
27009c4a7965SKim Phillips 			}
2701497f2e6bSLee Nipper 		},
2702497f2e6bSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
2703497f2e6bSLee Nipper 				     DESC_HDR_SEL0_MDEUA |
2704497f2e6bSLee Nipper 				     DESC_HDR_MODE0_MDEU_MD5,
2705497f2e6bSLee Nipper 	},
2706497f2e6bSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
2707497f2e6bSLee Nipper 		.alg.hash = {
2708497f2e6bSLee Nipper 			.halg.digestsize = SHA1_DIGEST_SIZE,
27093639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
2710497f2e6bSLee Nipper 			.halg.base = {
2711497f2e6bSLee Nipper 				.cra_name = "sha1",
2712497f2e6bSLee Nipper 				.cra_driver_name = "sha1-talitos",
2713497f2e6bSLee Nipper 				.cra_blocksize = SHA1_BLOCK_SIZE,
2714497f2e6bSLee Nipper 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
2715497f2e6bSLee Nipper 					     CRYPTO_ALG_ASYNC,
2716497f2e6bSLee Nipper 			}
2717497f2e6bSLee Nipper 		},
2718497f2e6bSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
2719497f2e6bSLee Nipper 				     DESC_HDR_SEL0_MDEUA |
2720497f2e6bSLee Nipper 				     DESC_HDR_MODE0_MDEU_SHA1,
2721497f2e6bSLee Nipper 	},
2722497f2e6bSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
2723497f2e6bSLee Nipper 		.alg.hash = {
272460f208d7SKim Phillips 			.halg.digestsize = SHA224_DIGEST_SIZE,
27253639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
272660f208d7SKim Phillips 			.halg.base = {
272760f208d7SKim Phillips 				.cra_name = "sha224",
272860f208d7SKim Phillips 				.cra_driver_name = "sha224-talitos",
272960f208d7SKim Phillips 				.cra_blocksize = SHA224_BLOCK_SIZE,
273060f208d7SKim Phillips 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
273160f208d7SKim Phillips 					     CRYPTO_ALG_ASYNC,
273260f208d7SKim Phillips 			}
273360f208d7SKim Phillips 		},
273460f208d7SKim Phillips 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
273560f208d7SKim Phillips 				     DESC_HDR_SEL0_MDEUA |
273660f208d7SKim Phillips 				     DESC_HDR_MODE0_MDEU_SHA224,
273760f208d7SKim Phillips 	},
273860f208d7SKim Phillips 	{	.type = CRYPTO_ALG_TYPE_AHASH,
273960f208d7SKim Phillips 		.alg.hash = {
2740497f2e6bSLee Nipper 			.halg.digestsize = SHA256_DIGEST_SIZE,
27413639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
2742497f2e6bSLee Nipper 			.halg.base = {
2743497f2e6bSLee Nipper 				.cra_name = "sha256",
2744497f2e6bSLee Nipper 				.cra_driver_name = "sha256-talitos",
2745497f2e6bSLee Nipper 				.cra_blocksize = SHA256_BLOCK_SIZE,
2746497f2e6bSLee Nipper 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
2747497f2e6bSLee Nipper 					     CRYPTO_ALG_ASYNC,
2748497f2e6bSLee Nipper 			}
2749497f2e6bSLee Nipper 		},
2750497f2e6bSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
2751497f2e6bSLee Nipper 				     DESC_HDR_SEL0_MDEUA |
2752497f2e6bSLee Nipper 				     DESC_HDR_MODE0_MDEU_SHA256,
2753497f2e6bSLee Nipper 	},
2754497f2e6bSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
2755497f2e6bSLee Nipper 		.alg.hash = {
2756497f2e6bSLee Nipper 			.halg.digestsize = SHA384_DIGEST_SIZE,
27573639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
2758497f2e6bSLee Nipper 			.halg.base = {
2759497f2e6bSLee Nipper 				.cra_name = "sha384",
2760497f2e6bSLee Nipper 				.cra_driver_name = "sha384-talitos",
2761497f2e6bSLee Nipper 				.cra_blocksize = SHA384_BLOCK_SIZE,
2762497f2e6bSLee Nipper 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
2763497f2e6bSLee Nipper 					     CRYPTO_ALG_ASYNC,
2764497f2e6bSLee Nipper 			}
2765497f2e6bSLee Nipper 		},
2766497f2e6bSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
2767497f2e6bSLee Nipper 				     DESC_HDR_SEL0_MDEUB |
2768497f2e6bSLee Nipper 				     DESC_HDR_MODE0_MDEUB_SHA384,
2769497f2e6bSLee Nipper 	},
2770497f2e6bSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
2771497f2e6bSLee Nipper 		.alg.hash = {
2772497f2e6bSLee Nipper 			.halg.digestsize = SHA512_DIGEST_SIZE,
27733639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
2774497f2e6bSLee Nipper 			.halg.base = {
2775497f2e6bSLee Nipper 				.cra_name = "sha512",
2776497f2e6bSLee Nipper 				.cra_driver_name = "sha512-talitos",
2777497f2e6bSLee Nipper 				.cra_blocksize = SHA512_BLOCK_SIZE,
2778497f2e6bSLee Nipper 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
2779497f2e6bSLee Nipper 					     CRYPTO_ALG_ASYNC,
2780497f2e6bSLee Nipper 			}
2781497f2e6bSLee Nipper 		},
2782497f2e6bSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
2783497f2e6bSLee Nipper 				     DESC_HDR_SEL0_MDEUB |
2784497f2e6bSLee Nipper 				     DESC_HDR_MODE0_MDEUB_SHA512,
2785497f2e6bSLee Nipper 	},
278679b3a418SLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
278779b3a418SLee Nipper 		.alg.hash = {
278879b3a418SLee Nipper 			.halg.digestsize = MD5_DIGEST_SIZE,
27893639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
279079b3a418SLee Nipper 			.halg.base = {
279179b3a418SLee Nipper 				.cra_name = "hmac(md5)",
279279b3a418SLee Nipper 				.cra_driver_name = "hmac-md5-talitos",
2793b3988618SMartin Hicks 				.cra_blocksize = MD5_HMAC_BLOCK_SIZE,
279479b3a418SLee Nipper 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
279579b3a418SLee Nipper 					     CRYPTO_ALG_ASYNC,
279679b3a418SLee Nipper 			}
279779b3a418SLee Nipper 		},
279879b3a418SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
279979b3a418SLee Nipper 				     DESC_HDR_SEL0_MDEUA |
280079b3a418SLee Nipper 				     DESC_HDR_MODE0_MDEU_MD5,
280179b3a418SLee Nipper 	},
280279b3a418SLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
280379b3a418SLee Nipper 		.alg.hash = {
280479b3a418SLee Nipper 			.halg.digestsize = SHA1_DIGEST_SIZE,
28053639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
280679b3a418SLee Nipper 			.halg.base = {
280779b3a418SLee Nipper 				.cra_name = "hmac(sha1)",
280879b3a418SLee Nipper 				.cra_driver_name = "hmac-sha1-talitos",
280979b3a418SLee Nipper 				.cra_blocksize = SHA1_BLOCK_SIZE,
281079b3a418SLee Nipper 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
281179b3a418SLee Nipper 					     CRYPTO_ALG_ASYNC,
281279b3a418SLee Nipper 			}
281379b3a418SLee Nipper 		},
281479b3a418SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
281579b3a418SLee Nipper 				     DESC_HDR_SEL0_MDEUA |
281679b3a418SLee Nipper 				     DESC_HDR_MODE0_MDEU_SHA1,
281779b3a418SLee Nipper 	},
281879b3a418SLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
281979b3a418SLee Nipper 		.alg.hash = {
282079b3a418SLee Nipper 			.halg.digestsize = SHA224_DIGEST_SIZE,
28213639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
282279b3a418SLee Nipper 			.halg.base = {
282379b3a418SLee Nipper 				.cra_name = "hmac(sha224)",
282479b3a418SLee Nipper 				.cra_driver_name = "hmac-sha224-talitos",
282579b3a418SLee Nipper 				.cra_blocksize = SHA224_BLOCK_SIZE,
282679b3a418SLee Nipper 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
282779b3a418SLee Nipper 					     CRYPTO_ALG_ASYNC,
282879b3a418SLee Nipper 			}
282979b3a418SLee Nipper 		},
283079b3a418SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
283179b3a418SLee Nipper 				     DESC_HDR_SEL0_MDEUA |
283279b3a418SLee Nipper 				     DESC_HDR_MODE0_MDEU_SHA224,
283379b3a418SLee Nipper 	},
283479b3a418SLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
283579b3a418SLee Nipper 		.alg.hash = {
283679b3a418SLee Nipper 			.halg.digestsize = SHA256_DIGEST_SIZE,
28373639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
283879b3a418SLee Nipper 			.halg.base = {
283979b3a418SLee Nipper 				.cra_name = "hmac(sha256)",
284079b3a418SLee Nipper 				.cra_driver_name = "hmac-sha256-talitos",
284179b3a418SLee Nipper 				.cra_blocksize = SHA256_BLOCK_SIZE,
284279b3a418SLee Nipper 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
284379b3a418SLee Nipper 					     CRYPTO_ALG_ASYNC,
284479b3a418SLee Nipper 			}
284579b3a418SLee Nipper 		},
284679b3a418SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
284779b3a418SLee Nipper 				     DESC_HDR_SEL0_MDEUA |
284879b3a418SLee Nipper 				     DESC_HDR_MODE0_MDEU_SHA256,
284979b3a418SLee Nipper 	},
285079b3a418SLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
285179b3a418SLee Nipper 		.alg.hash = {
285279b3a418SLee Nipper 			.halg.digestsize = SHA384_DIGEST_SIZE,
28533639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
285479b3a418SLee Nipper 			.halg.base = {
285579b3a418SLee Nipper 				.cra_name = "hmac(sha384)",
285679b3a418SLee Nipper 				.cra_driver_name = "hmac-sha384-talitos",
285779b3a418SLee Nipper 				.cra_blocksize = SHA384_BLOCK_SIZE,
285879b3a418SLee Nipper 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
285979b3a418SLee Nipper 					     CRYPTO_ALG_ASYNC,
286079b3a418SLee Nipper 			}
286179b3a418SLee Nipper 		},
286279b3a418SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
286379b3a418SLee Nipper 				     DESC_HDR_SEL0_MDEUB |
286479b3a418SLee Nipper 				     DESC_HDR_MODE0_MDEUB_SHA384,
286579b3a418SLee Nipper 	},
286679b3a418SLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
286779b3a418SLee Nipper 		.alg.hash = {
286879b3a418SLee Nipper 			.halg.digestsize = SHA512_DIGEST_SIZE,
28693639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
287079b3a418SLee Nipper 			.halg.base = {
287179b3a418SLee Nipper 				.cra_name = "hmac(sha512)",
287279b3a418SLee Nipper 				.cra_driver_name = "hmac-sha512-talitos",
287379b3a418SLee Nipper 				.cra_blocksize = SHA512_BLOCK_SIZE,
287479b3a418SLee Nipper 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
287579b3a418SLee Nipper 					     CRYPTO_ALG_ASYNC,
287679b3a418SLee Nipper 			}
287779b3a418SLee Nipper 		},
287879b3a418SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
287979b3a418SLee Nipper 				     DESC_HDR_SEL0_MDEUB |
288079b3a418SLee Nipper 				     DESC_HDR_MODE0_MDEUB_SHA512,
288179b3a418SLee Nipper 	}
28829c4a7965SKim Phillips };
28839c4a7965SKim Phillips 
28849c4a7965SKim Phillips struct talitos_crypto_alg {
28859c4a7965SKim Phillips 	struct list_head entry;
28869c4a7965SKim Phillips 	struct device *dev;
2887acbf7c62SLee Nipper 	struct talitos_alg_template algt;
28889c4a7965SKim Phillips };
28899c4a7965SKim Phillips 
289089d124cbSJonas Eymann static int talitos_init_common(struct talitos_ctx *ctx,
289189d124cbSJonas Eymann 			       struct talitos_crypto_alg *talitos_alg)
28929c4a7965SKim Phillips {
28935228f0f7SKim Phillips 	struct talitos_private *priv;
28949c4a7965SKim Phillips 
28959c4a7965SKim Phillips 	/* update context with ptr to dev */
28969c4a7965SKim Phillips 	ctx->dev = talitos_alg->dev;
289719bbbc63SKim Phillips 
28985228f0f7SKim Phillips 	/* assign SEC channel to tfm in round-robin fashion */
28995228f0f7SKim Phillips 	priv = dev_get_drvdata(ctx->dev);
29005228f0f7SKim Phillips 	ctx->ch = atomic_inc_return(&priv->last_chan) &
29015228f0f7SKim Phillips 		  (priv->num_channels - 1);
29025228f0f7SKim Phillips 
29039c4a7965SKim Phillips 	/* copy descriptor header template value */
2904acbf7c62SLee Nipper 	ctx->desc_hdr_template = talitos_alg->algt.desc_hdr_template;
29059c4a7965SKim Phillips 
2906602dba5aSKim Phillips 	/* select done notification */
2907602dba5aSKim Phillips 	ctx->desc_hdr_template |= DESC_HDR_DONE_NOTIFY;
2908602dba5aSKim Phillips 
2909497f2e6bSLee Nipper 	return 0;
2910497f2e6bSLee Nipper }
2911497f2e6bSLee Nipper 
291289d124cbSJonas Eymann static int talitos_cra_init(struct crypto_tfm *tfm)
291389d124cbSJonas Eymann {
291489d124cbSJonas Eymann 	struct crypto_alg *alg = tfm->__crt_alg;
291589d124cbSJonas Eymann 	struct talitos_crypto_alg *talitos_alg;
291689d124cbSJonas Eymann 	struct talitos_ctx *ctx = crypto_tfm_ctx(tfm);
291789d124cbSJonas Eymann 
291889d124cbSJonas Eymann 	if ((alg->cra_flags & CRYPTO_ALG_TYPE_MASK) == CRYPTO_ALG_TYPE_AHASH)
291989d124cbSJonas Eymann 		talitos_alg = container_of(__crypto_ahash_alg(alg),
292089d124cbSJonas Eymann 					   struct talitos_crypto_alg,
292189d124cbSJonas Eymann 					   algt.alg.hash);
292289d124cbSJonas Eymann 	else
292389d124cbSJonas Eymann 		talitos_alg = container_of(alg, struct talitos_crypto_alg,
292489d124cbSJonas Eymann 					   algt.alg.crypto);
292589d124cbSJonas Eymann 
292689d124cbSJonas Eymann 	return talitos_init_common(ctx, talitos_alg);
292789d124cbSJonas Eymann }
292889d124cbSJonas Eymann 
2929aeb4c132SHerbert Xu static int talitos_cra_init_aead(struct crypto_aead *tfm)
2930497f2e6bSLee Nipper {
293189d124cbSJonas Eymann 	struct aead_alg *alg = crypto_aead_alg(tfm);
293289d124cbSJonas Eymann 	struct talitos_crypto_alg *talitos_alg;
293389d124cbSJonas Eymann 	struct talitos_ctx *ctx = crypto_aead_ctx(tfm);
293489d124cbSJonas Eymann 
293589d124cbSJonas Eymann 	talitos_alg = container_of(alg, struct talitos_crypto_alg,
293689d124cbSJonas Eymann 				   algt.alg.aead);
293789d124cbSJonas Eymann 
293889d124cbSJonas Eymann 	return talitos_init_common(ctx, talitos_alg);
29399c4a7965SKim Phillips }
29409c4a7965SKim Phillips 
2941497f2e6bSLee Nipper static int talitos_cra_init_ahash(struct crypto_tfm *tfm)
2942497f2e6bSLee Nipper {
2943497f2e6bSLee Nipper 	struct talitos_ctx *ctx = crypto_tfm_ctx(tfm);
2944497f2e6bSLee Nipper 
2945497f2e6bSLee Nipper 	talitos_cra_init(tfm);
2946497f2e6bSLee Nipper 
2947497f2e6bSLee Nipper 	ctx->keylen = 0;
2948497f2e6bSLee Nipper 	crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm),
2949497f2e6bSLee Nipper 				 sizeof(struct talitos_ahash_req_ctx));
2950497f2e6bSLee Nipper 
2951497f2e6bSLee Nipper 	return 0;
2952497f2e6bSLee Nipper }
2953497f2e6bSLee Nipper 
29549c4a7965SKim Phillips /*
29559c4a7965SKim Phillips  * given the alg's descriptor header template, determine whether descriptor
29569c4a7965SKim Phillips  * type and primary/secondary execution units required match the hw
29579c4a7965SKim Phillips  * capabilities description provided in the device tree node.
29589c4a7965SKim Phillips  */
29599c4a7965SKim Phillips static int hw_supports(struct device *dev, __be32 desc_hdr_template)
29609c4a7965SKim Phillips {
29619c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
29629c4a7965SKim Phillips 	int ret;
29639c4a7965SKim Phillips 
29649c4a7965SKim Phillips 	ret = (1 << DESC_TYPE(desc_hdr_template) & priv->desc_types) &&
29659c4a7965SKim Phillips 	      (1 << PRIMARY_EU(desc_hdr_template) & priv->exec_units);
29669c4a7965SKim Phillips 
29679c4a7965SKim Phillips 	if (SECONDARY_EU(desc_hdr_template))
29689c4a7965SKim Phillips 		ret = ret && (1 << SECONDARY_EU(desc_hdr_template)
29699c4a7965SKim Phillips 		              & priv->exec_units);
29709c4a7965SKim Phillips 
29719c4a7965SKim Phillips 	return ret;
29729c4a7965SKim Phillips }
29739c4a7965SKim Phillips 
29742dc11581SGrant Likely static int talitos_remove(struct platform_device *ofdev)
29759c4a7965SKim Phillips {
29769c4a7965SKim Phillips 	struct device *dev = &ofdev->dev;
29779c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
29789c4a7965SKim Phillips 	struct talitos_crypto_alg *t_alg, *n;
29799c4a7965SKim Phillips 	int i;
29809c4a7965SKim Phillips 
29819c4a7965SKim Phillips 	list_for_each_entry_safe(t_alg, n, &priv->alg_list, entry) {
2982acbf7c62SLee Nipper 		switch (t_alg->algt.type) {
2983acbf7c62SLee Nipper 		case CRYPTO_ALG_TYPE_ABLKCIPHER:
2984acbf7c62SLee Nipper 			break;
2985aeb4c132SHerbert Xu 		case CRYPTO_ALG_TYPE_AEAD:
2986aeb4c132SHerbert Xu 			crypto_unregister_aead(&t_alg->algt.alg.aead);
2987acbf7c62SLee Nipper 		case CRYPTO_ALG_TYPE_AHASH:
2988acbf7c62SLee Nipper 			crypto_unregister_ahash(&t_alg->algt.alg.hash);
2989acbf7c62SLee Nipper 			break;
2990acbf7c62SLee Nipper 		}
29919c4a7965SKim Phillips 		list_del(&t_alg->entry);
29929c4a7965SKim Phillips 	}
29939c4a7965SKim Phillips 
29949c4a7965SKim Phillips 	if (hw_supports(dev, DESC_HDR_SEL0_RNG))
29959c4a7965SKim Phillips 		talitos_unregister_rng(dev);
29969c4a7965SKim Phillips 
2997c3e337f8SKim Phillips 	for (i = 0; i < 2; i++)
29982cdba3cfSKim Phillips 		if (priv->irq[i]) {
2999c3e337f8SKim Phillips 			free_irq(priv->irq[i], dev);
3000c3e337f8SKim Phillips 			irq_dispose_mapping(priv->irq[i]);
30019c4a7965SKim Phillips 		}
30029c4a7965SKim Phillips 
3003c3e337f8SKim Phillips 	tasklet_kill(&priv->done_task[0]);
30042cdba3cfSKim Phillips 	if (priv->irq[1])
3005c3e337f8SKim Phillips 		tasklet_kill(&priv->done_task[1]);
30069c4a7965SKim Phillips 
30079c4a7965SKim Phillips 	return 0;
30089c4a7965SKim Phillips }
30099c4a7965SKim Phillips 
30109c4a7965SKim Phillips static struct talitos_crypto_alg *talitos_alg_alloc(struct device *dev,
30119c4a7965SKim Phillips 						    struct talitos_alg_template
30129c4a7965SKim Phillips 						           *template)
30139c4a7965SKim Phillips {
301460f208d7SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
30159c4a7965SKim Phillips 	struct talitos_crypto_alg *t_alg;
30169c4a7965SKim Phillips 	struct crypto_alg *alg;
30179c4a7965SKim Phillips 
301824b92ff2SLEROY Christophe 	t_alg = devm_kzalloc(dev, sizeof(struct talitos_crypto_alg),
301924b92ff2SLEROY Christophe 			     GFP_KERNEL);
30209c4a7965SKim Phillips 	if (!t_alg)
30219c4a7965SKim Phillips 		return ERR_PTR(-ENOMEM);
30229c4a7965SKim Phillips 
3023acbf7c62SLee Nipper 	t_alg->algt = *template;
3024acbf7c62SLee Nipper 
3025acbf7c62SLee Nipper 	switch (t_alg->algt.type) {
3026acbf7c62SLee Nipper 	case CRYPTO_ALG_TYPE_ABLKCIPHER:
3027497f2e6bSLee Nipper 		alg = &t_alg->algt.alg.crypto;
3028497f2e6bSLee Nipper 		alg->cra_init = talitos_cra_init;
3029d4cd3283SKim Phillips 		alg->cra_type = &crypto_ablkcipher_type;
3030b286e003SKim Phillips 		alg->cra_ablkcipher.setkey = ablkcipher_setkey;
3031b286e003SKim Phillips 		alg->cra_ablkcipher.encrypt = ablkcipher_encrypt;
3032b286e003SKim Phillips 		alg->cra_ablkcipher.decrypt = ablkcipher_decrypt;
3033b286e003SKim Phillips 		alg->cra_ablkcipher.geniv = "eseqiv";
3034497f2e6bSLee Nipper 		break;
3035acbf7c62SLee Nipper 	case CRYPTO_ALG_TYPE_AEAD:
3036aeb4c132SHerbert Xu 		alg = &t_alg->algt.alg.aead.base;
3037aeb4c132SHerbert Xu 		t_alg->algt.alg.aead.init = talitos_cra_init_aead;
3038aeb4c132SHerbert Xu 		t_alg->algt.alg.aead.setkey = aead_setkey;
3039aeb4c132SHerbert Xu 		t_alg->algt.alg.aead.encrypt = aead_encrypt;
3040aeb4c132SHerbert Xu 		t_alg->algt.alg.aead.decrypt = aead_decrypt;
30416cda075aSLEROY Christophe 		if (!(priv->features & TALITOS_FTR_SHA224_HWINIT) &&
30426cda075aSLEROY Christophe 		    !strncmp(alg->cra_name, "authenc(hmac(sha224)", 20)) {
304324b92ff2SLEROY Christophe 			devm_kfree(dev, t_alg);
30446cda075aSLEROY Christophe 			return ERR_PTR(-ENOTSUPP);
30456cda075aSLEROY Christophe 		}
3046acbf7c62SLee Nipper 		break;
3047acbf7c62SLee Nipper 	case CRYPTO_ALG_TYPE_AHASH:
3048acbf7c62SLee Nipper 		alg = &t_alg->algt.alg.hash.halg.base;
3049497f2e6bSLee Nipper 		alg->cra_init = talitos_cra_init_ahash;
3050d4cd3283SKim Phillips 		alg->cra_type = &crypto_ahash_type;
3051b286e003SKim Phillips 		t_alg->algt.alg.hash.init = ahash_init;
3052b286e003SKim Phillips 		t_alg->algt.alg.hash.update = ahash_update;
3053b286e003SKim Phillips 		t_alg->algt.alg.hash.final = ahash_final;
3054b286e003SKim Phillips 		t_alg->algt.alg.hash.finup = ahash_finup;
3055b286e003SKim Phillips 		t_alg->algt.alg.hash.digest = ahash_digest;
305656136631SLEROY Christophe 		if (!strncmp(alg->cra_name, "hmac", 4))
3057b286e003SKim Phillips 			t_alg->algt.alg.hash.setkey = ahash_setkey;
30583639ca84SHoria Geant? 		t_alg->algt.alg.hash.import = ahash_import;
30593639ca84SHoria Geant? 		t_alg->algt.alg.hash.export = ahash_export;
3060b286e003SKim Phillips 
306179b3a418SLee Nipper 		if (!(priv->features & TALITOS_FTR_HMAC_OK) &&
30620b2730d8SKim Phillips 		    !strncmp(alg->cra_name, "hmac", 4)) {
306324b92ff2SLEROY Christophe 			devm_kfree(dev, t_alg);
306479b3a418SLee Nipper 			return ERR_PTR(-ENOTSUPP);
30650b2730d8SKim Phillips 		}
306660f208d7SKim Phillips 		if (!(priv->features & TALITOS_FTR_SHA224_HWINIT) &&
306779b3a418SLee Nipper 		    (!strcmp(alg->cra_name, "sha224") ||
306879b3a418SLee Nipper 		     !strcmp(alg->cra_name, "hmac(sha224)"))) {
306960f208d7SKim Phillips 			t_alg->algt.alg.hash.init = ahash_init_sha224_swinit;
307060f208d7SKim Phillips 			t_alg->algt.desc_hdr_template =
307160f208d7SKim Phillips 					DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
307260f208d7SKim Phillips 					DESC_HDR_SEL0_MDEUA |
307360f208d7SKim Phillips 					DESC_HDR_MODE0_MDEU_SHA256;
307460f208d7SKim Phillips 		}
3075497f2e6bSLee Nipper 		break;
30761d11911aSKim Phillips 	default:
30771d11911aSKim Phillips 		dev_err(dev, "unknown algorithm type %d\n", t_alg->algt.type);
307824b92ff2SLEROY Christophe 		devm_kfree(dev, t_alg);
30791d11911aSKim Phillips 		return ERR_PTR(-EINVAL);
3080acbf7c62SLee Nipper 	}
30819c4a7965SKim Phillips 
30829c4a7965SKim Phillips 	alg->cra_module = THIS_MODULE;
3083b0057763SLEROY Christophe 	if (t_alg->algt.priority)
3084b0057763SLEROY Christophe 		alg->cra_priority = t_alg->algt.priority;
3085b0057763SLEROY Christophe 	else
30869c4a7965SKim Phillips 		alg->cra_priority = TALITOS_CRA_PRIORITY;
30879c4a7965SKim Phillips 	alg->cra_alignmask = 0;
30889c4a7965SKim Phillips 	alg->cra_ctxsize = sizeof(struct talitos_ctx);
3089d912bb76SNikos Mavrogiannopoulos 	alg->cra_flags |= CRYPTO_ALG_KERN_DRIVER_ONLY;
30909c4a7965SKim Phillips 
30919c4a7965SKim Phillips 	t_alg->dev = dev;
30929c4a7965SKim Phillips 
30939c4a7965SKim Phillips 	return t_alg;
30949c4a7965SKim Phillips }
30959c4a7965SKim Phillips 
3096c3e337f8SKim Phillips static int talitos_probe_irq(struct platform_device *ofdev)
3097c3e337f8SKim Phillips {
3098c3e337f8SKim Phillips 	struct device *dev = &ofdev->dev;
3099c3e337f8SKim Phillips 	struct device_node *np = ofdev->dev.of_node;
3100c3e337f8SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
3101c3e337f8SKim Phillips 	int err;
3102dd3c0987SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
3103c3e337f8SKim Phillips 
3104c3e337f8SKim Phillips 	priv->irq[0] = irq_of_parse_and_map(np, 0);
31052cdba3cfSKim Phillips 	if (!priv->irq[0]) {
3106c3e337f8SKim Phillips 		dev_err(dev, "failed to map irq\n");
3107c3e337f8SKim Phillips 		return -EINVAL;
3108c3e337f8SKim Phillips 	}
3109dd3c0987SLEROY Christophe 	if (is_sec1) {
3110dd3c0987SLEROY Christophe 		err = request_irq(priv->irq[0], talitos1_interrupt_4ch, 0,
3111dd3c0987SLEROY Christophe 				  dev_driver_string(dev), dev);
3112dd3c0987SLEROY Christophe 		goto primary_out;
3113dd3c0987SLEROY Christophe 	}
3114c3e337f8SKim Phillips 
3115c3e337f8SKim Phillips 	priv->irq[1] = irq_of_parse_and_map(np, 1);
3116c3e337f8SKim Phillips 
3117c3e337f8SKim Phillips 	/* get the primary irq line */
31182cdba3cfSKim Phillips 	if (!priv->irq[1]) {
3119dd3c0987SLEROY Christophe 		err = request_irq(priv->irq[0], talitos2_interrupt_4ch, 0,
3120c3e337f8SKim Phillips 				  dev_driver_string(dev), dev);
3121c3e337f8SKim Phillips 		goto primary_out;
3122c3e337f8SKim Phillips 	}
3123c3e337f8SKim Phillips 
3124dd3c0987SLEROY Christophe 	err = request_irq(priv->irq[0], talitos2_interrupt_ch0_2, 0,
3125c3e337f8SKim Phillips 			  dev_driver_string(dev), dev);
3126c3e337f8SKim Phillips 	if (err)
3127c3e337f8SKim Phillips 		goto primary_out;
3128c3e337f8SKim Phillips 
3129c3e337f8SKim Phillips 	/* get the secondary irq line */
3130dd3c0987SLEROY Christophe 	err = request_irq(priv->irq[1], talitos2_interrupt_ch1_3, 0,
3131c3e337f8SKim Phillips 			  dev_driver_string(dev), dev);
3132c3e337f8SKim Phillips 	if (err) {
3133c3e337f8SKim Phillips 		dev_err(dev, "failed to request secondary irq\n");
3134c3e337f8SKim Phillips 		irq_dispose_mapping(priv->irq[1]);
31352cdba3cfSKim Phillips 		priv->irq[1] = 0;
3136c3e337f8SKim Phillips 	}
3137c3e337f8SKim Phillips 
3138c3e337f8SKim Phillips 	return err;
3139c3e337f8SKim Phillips 
3140c3e337f8SKim Phillips primary_out:
3141c3e337f8SKim Phillips 	if (err) {
3142c3e337f8SKim Phillips 		dev_err(dev, "failed to request primary irq\n");
3143c3e337f8SKim Phillips 		irq_dispose_mapping(priv->irq[0]);
31442cdba3cfSKim Phillips 		priv->irq[0] = 0;
3145c3e337f8SKim Phillips 	}
3146c3e337f8SKim Phillips 
3147c3e337f8SKim Phillips 	return err;
3148c3e337f8SKim Phillips }
3149c3e337f8SKim Phillips 
31501c48a5c9SGrant Likely static int talitos_probe(struct platform_device *ofdev)
31519c4a7965SKim Phillips {
31529c4a7965SKim Phillips 	struct device *dev = &ofdev->dev;
315361c7a080SGrant Likely 	struct device_node *np = ofdev->dev.of_node;
31549c4a7965SKim Phillips 	struct talitos_private *priv;
31559c4a7965SKim Phillips 	int i, err;
31565fa7fa14SLEROY Christophe 	int stride;
3157fd5ea7f0SLEROY Christophe 	struct resource *res;
31589c4a7965SKim Phillips 
315924b92ff2SLEROY Christophe 	priv = devm_kzalloc(dev, sizeof(struct talitos_private), GFP_KERNEL);
31609c4a7965SKim Phillips 	if (!priv)
31619c4a7965SKim Phillips 		return -ENOMEM;
31629c4a7965SKim Phillips 
3163f3de9cb1SKevin Hao 	INIT_LIST_HEAD(&priv->alg_list);
3164f3de9cb1SKevin Hao 
31659c4a7965SKim Phillips 	dev_set_drvdata(dev, priv);
31669c4a7965SKim Phillips 
31679c4a7965SKim Phillips 	priv->ofdev = ofdev;
31689c4a7965SKim Phillips 
3169511d63cbSHoria Geanta 	spin_lock_init(&priv->reg_lock);
3170511d63cbSHoria Geanta 
3171fd5ea7f0SLEROY Christophe 	res = platform_get_resource(ofdev, IORESOURCE_MEM, 0);
3172fd5ea7f0SLEROY Christophe 	if (!res)
3173fd5ea7f0SLEROY Christophe 		return -ENXIO;
3174fd5ea7f0SLEROY Christophe 	priv->reg = devm_ioremap(dev, res->start, resource_size(res));
31759c4a7965SKim Phillips 	if (!priv->reg) {
31769c4a7965SKim Phillips 		dev_err(dev, "failed to of_iomap\n");
31779c4a7965SKim Phillips 		err = -ENOMEM;
31789c4a7965SKim Phillips 		goto err_out;
31799c4a7965SKim Phillips 	}
31809c4a7965SKim Phillips 
31819c4a7965SKim Phillips 	/* get SEC version capabilities from device tree */
3182fa14c6cfSLEROY Christophe 	of_property_read_u32(np, "fsl,num-channels", &priv->num_channels);
3183fa14c6cfSLEROY Christophe 	of_property_read_u32(np, "fsl,channel-fifo-len", &priv->chfifo_len);
3184fa14c6cfSLEROY Christophe 	of_property_read_u32(np, "fsl,exec-units-mask", &priv->exec_units);
3185fa14c6cfSLEROY Christophe 	of_property_read_u32(np, "fsl,descriptor-types-mask",
3186fa14c6cfSLEROY Christophe 			     &priv->desc_types);
31879c4a7965SKim Phillips 
31889c4a7965SKim Phillips 	if (!is_power_of_2(priv->num_channels) || !priv->chfifo_len ||
31899c4a7965SKim Phillips 	    !priv->exec_units || !priv->desc_types) {
31909c4a7965SKim Phillips 		dev_err(dev, "invalid property data in device tree node\n");
31919c4a7965SKim Phillips 		err = -EINVAL;
31929c4a7965SKim Phillips 		goto err_out;
31939c4a7965SKim Phillips 	}
31949c4a7965SKim Phillips 
3195f3c85bc1SLee Nipper 	if (of_device_is_compatible(np, "fsl,sec3.0"))
3196f3c85bc1SLee Nipper 		priv->features |= TALITOS_FTR_SRC_LINK_TBL_LEN_INCLUDES_EXTENT;
3197f3c85bc1SLee Nipper 
3198fe5720e2SKim Phillips 	if (of_device_is_compatible(np, "fsl,sec2.1"))
319960f208d7SKim Phillips 		priv->features |= TALITOS_FTR_HW_AUTH_CHECK |
320079b3a418SLee Nipper 				  TALITOS_FTR_SHA224_HWINIT |
320179b3a418SLee Nipper 				  TALITOS_FTR_HMAC_OK;
3202fe5720e2SKim Phillips 
320321590888SLEROY Christophe 	if (of_device_is_compatible(np, "fsl,sec1.0"))
320421590888SLEROY Christophe 		priv->features |= TALITOS_FTR_SEC1;
320521590888SLEROY Christophe 
32065fa7fa14SLEROY Christophe 	if (of_device_is_compatible(np, "fsl,sec1.2")) {
32075fa7fa14SLEROY Christophe 		priv->reg_deu = priv->reg + TALITOS12_DEU;
32085fa7fa14SLEROY Christophe 		priv->reg_aesu = priv->reg + TALITOS12_AESU;
32095fa7fa14SLEROY Christophe 		priv->reg_mdeu = priv->reg + TALITOS12_MDEU;
32105fa7fa14SLEROY Christophe 		stride = TALITOS1_CH_STRIDE;
32115fa7fa14SLEROY Christophe 	} else if (of_device_is_compatible(np, "fsl,sec1.0")) {
32125fa7fa14SLEROY Christophe 		priv->reg_deu = priv->reg + TALITOS10_DEU;
32135fa7fa14SLEROY Christophe 		priv->reg_aesu = priv->reg + TALITOS10_AESU;
32145fa7fa14SLEROY Christophe 		priv->reg_mdeu = priv->reg + TALITOS10_MDEU;
32155fa7fa14SLEROY Christophe 		priv->reg_afeu = priv->reg + TALITOS10_AFEU;
32165fa7fa14SLEROY Christophe 		priv->reg_rngu = priv->reg + TALITOS10_RNGU;
32175fa7fa14SLEROY Christophe 		priv->reg_pkeu = priv->reg + TALITOS10_PKEU;
32185fa7fa14SLEROY Christophe 		stride = TALITOS1_CH_STRIDE;
32195fa7fa14SLEROY Christophe 	} else {
32205fa7fa14SLEROY Christophe 		priv->reg_deu = priv->reg + TALITOS2_DEU;
32215fa7fa14SLEROY Christophe 		priv->reg_aesu = priv->reg + TALITOS2_AESU;
32225fa7fa14SLEROY Christophe 		priv->reg_mdeu = priv->reg + TALITOS2_MDEU;
32235fa7fa14SLEROY Christophe 		priv->reg_afeu = priv->reg + TALITOS2_AFEU;
32245fa7fa14SLEROY Christophe 		priv->reg_rngu = priv->reg + TALITOS2_RNGU;
32255fa7fa14SLEROY Christophe 		priv->reg_pkeu = priv->reg + TALITOS2_PKEU;
32265fa7fa14SLEROY Christophe 		priv->reg_keu = priv->reg + TALITOS2_KEU;
32275fa7fa14SLEROY Christophe 		priv->reg_crcu = priv->reg + TALITOS2_CRCU;
32285fa7fa14SLEROY Christophe 		stride = TALITOS2_CH_STRIDE;
32295fa7fa14SLEROY Christophe 	}
32305fa7fa14SLEROY Christophe 
3231dd3c0987SLEROY Christophe 	err = talitos_probe_irq(ofdev);
3232dd3c0987SLEROY Christophe 	if (err)
3233dd3c0987SLEROY Christophe 		goto err_out;
3234dd3c0987SLEROY Christophe 
3235dd3c0987SLEROY Christophe 	if (of_device_is_compatible(np, "fsl,sec1.0")) {
3236*9c02e285SLEROY Christophe 		if (priv->num_channels == 1)
3237*9c02e285SLEROY Christophe 			tasklet_init(&priv->done_task[0], talitos1_done_ch0,
3238*9c02e285SLEROY Christophe 				     (unsigned long)dev);
3239*9c02e285SLEROY Christophe 		else
3240dd3c0987SLEROY Christophe 			tasklet_init(&priv->done_task[0], talitos1_done_4ch,
3241dd3c0987SLEROY Christophe 				     (unsigned long)dev);
3242dd3c0987SLEROY Christophe 	} else {
3243*9c02e285SLEROY Christophe 		if (priv->irq[1]) {
3244dd3c0987SLEROY Christophe 			tasklet_init(&priv->done_task[0], talitos2_done_ch0_2,
3245dd3c0987SLEROY Christophe 				     (unsigned long)dev);
3246dd3c0987SLEROY Christophe 			tasklet_init(&priv->done_task[1], talitos2_done_ch1_3,
3247dd3c0987SLEROY Christophe 				     (unsigned long)dev);
3248*9c02e285SLEROY Christophe 		} else if (priv->num_channels == 1) {
3249*9c02e285SLEROY Christophe 			tasklet_init(&priv->done_task[0], talitos2_done_ch0,
3250*9c02e285SLEROY Christophe 				     (unsigned long)dev);
3251*9c02e285SLEROY Christophe 		} else {
3252*9c02e285SLEROY Christophe 			tasklet_init(&priv->done_task[0], talitos2_done_4ch,
3253*9c02e285SLEROY Christophe 				     (unsigned long)dev);
3254dd3c0987SLEROY Christophe 		}
3255dd3c0987SLEROY Christophe 	}
3256dd3c0987SLEROY Christophe 
325724b92ff2SLEROY Christophe 	priv->chan = devm_kzalloc(dev, sizeof(struct talitos_channel) *
32584b992628SKim Phillips 				       priv->num_channels, GFP_KERNEL);
32594b992628SKim Phillips 	if (!priv->chan) {
32604b992628SKim Phillips 		dev_err(dev, "failed to allocate channel management space\n");
32619c4a7965SKim Phillips 		err = -ENOMEM;
32629c4a7965SKim Phillips 		goto err_out;
32639c4a7965SKim Phillips 	}
32649c4a7965SKim Phillips 
3265f641ddddSMartin Hicks 	priv->fifo_len = roundup_pow_of_two(priv->chfifo_len);
3266f641ddddSMartin Hicks 
3267c3e337f8SKim Phillips 	for (i = 0; i < priv->num_channels; i++) {
32685fa7fa14SLEROY Christophe 		priv->chan[i].reg = priv->reg + stride * (i + 1);
32692cdba3cfSKim Phillips 		if (!priv->irq[1] || !(i & 1))
3270c3e337f8SKim Phillips 			priv->chan[i].reg += TALITOS_CH_BASE_OFFSET;
3271ad42d5fcSKim Phillips 
32724b992628SKim Phillips 		spin_lock_init(&priv->chan[i].head_lock);
32734b992628SKim Phillips 		spin_lock_init(&priv->chan[i].tail_lock);
32749c4a7965SKim Phillips 
327524b92ff2SLEROY Christophe 		priv->chan[i].fifo = devm_kzalloc(dev,
327624b92ff2SLEROY Christophe 						sizeof(struct talitos_request) *
32779c4a7965SKim Phillips 						priv->fifo_len, GFP_KERNEL);
32784b992628SKim Phillips 		if (!priv->chan[i].fifo) {
32799c4a7965SKim Phillips 			dev_err(dev, "failed to allocate request fifo %d\n", i);
32809c4a7965SKim Phillips 			err = -ENOMEM;
32819c4a7965SKim Phillips 			goto err_out;
32829c4a7965SKim Phillips 		}
32839c4a7965SKim Phillips 
32844b992628SKim Phillips 		atomic_set(&priv->chan[i].submit_count,
32854b992628SKim Phillips 			   -(priv->chfifo_len - 1));
3286f641ddddSMartin Hicks 	}
32879c4a7965SKim Phillips 
328881eb024cSKim Phillips 	dma_set_mask(dev, DMA_BIT_MASK(36));
328981eb024cSKim Phillips 
32909c4a7965SKim Phillips 	/* reset and initialize the h/w */
32919c4a7965SKim Phillips 	err = init_device(dev);
32929c4a7965SKim Phillips 	if (err) {
32939c4a7965SKim Phillips 		dev_err(dev, "failed to initialize device\n");
32949c4a7965SKim Phillips 		goto err_out;
32959c4a7965SKim Phillips 	}
32969c4a7965SKim Phillips 
32979c4a7965SKim Phillips 	/* register the RNG, if available */
32989c4a7965SKim Phillips 	if (hw_supports(dev, DESC_HDR_SEL0_RNG)) {
32999c4a7965SKim Phillips 		err = talitos_register_rng(dev);
33009c4a7965SKim Phillips 		if (err) {
33019c4a7965SKim Phillips 			dev_err(dev, "failed to register hwrng: %d\n", err);
33029c4a7965SKim Phillips 			goto err_out;
33039c4a7965SKim Phillips 		} else
33049c4a7965SKim Phillips 			dev_info(dev, "hwrng\n");
33059c4a7965SKim Phillips 	}
33069c4a7965SKim Phillips 
33079c4a7965SKim Phillips 	/* register crypto algorithms the device supports */
33089c4a7965SKim Phillips 	for (i = 0; i < ARRAY_SIZE(driver_algs); i++) {
33099c4a7965SKim Phillips 		if (hw_supports(dev, driver_algs[i].desc_hdr_template)) {
33109c4a7965SKim Phillips 			struct talitos_crypto_alg *t_alg;
3311aeb4c132SHerbert Xu 			struct crypto_alg *alg = NULL;
33129c4a7965SKim Phillips 
33139c4a7965SKim Phillips 			t_alg = talitos_alg_alloc(dev, &driver_algs[i]);
33149c4a7965SKim Phillips 			if (IS_ERR(t_alg)) {
33159c4a7965SKim Phillips 				err = PTR_ERR(t_alg);
33160b2730d8SKim Phillips 				if (err == -ENOTSUPP)
331779b3a418SLee Nipper 					continue;
33189c4a7965SKim Phillips 				goto err_out;
33199c4a7965SKim Phillips 			}
33209c4a7965SKim Phillips 
3321acbf7c62SLee Nipper 			switch (t_alg->algt.type) {
3322acbf7c62SLee Nipper 			case CRYPTO_ALG_TYPE_ABLKCIPHER:
3323acbf7c62SLee Nipper 				err = crypto_register_alg(
3324acbf7c62SLee Nipper 						&t_alg->algt.alg.crypto);
3325aeb4c132SHerbert Xu 				alg = &t_alg->algt.alg.crypto;
3326acbf7c62SLee Nipper 				break;
3327aeb4c132SHerbert Xu 
3328aeb4c132SHerbert Xu 			case CRYPTO_ALG_TYPE_AEAD:
3329aeb4c132SHerbert Xu 				err = crypto_register_aead(
3330aeb4c132SHerbert Xu 					&t_alg->algt.alg.aead);
3331aeb4c132SHerbert Xu 				alg = &t_alg->algt.alg.aead.base;
3332aeb4c132SHerbert Xu 				break;
3333aeb4c132SHerbert Xu 
3334acbf7c62SLee Nipper 			case CRYPTO_ALG_TYPE_AHASH:
3335acbf7c62SLee Nipper 				err = crypto_register_ahash(
3336acbf7c62SLee Nipper 						&t_alg->algt.alg.hash);
3337aeb4c132SHerbert Xu 				alg = &t_alg->algt.alg.hash.halg.base;
3338acbf7c62SLee Nipper 				break;
3339acbf7c62SLee Nipper 			}
33409c4a7965SKim Phillips 			if (err) {
33419c4a7965SKim Phillips 				dev_err(dev, "%s alg registration failed\n",
3342aeb4c132SHerbert Xu 					alg->cra_driver_name);
334324b92ff2SLEROY Christophe 				devm_kfree(dev, t_alg);
3344991155baSHoria Geanta 			} else
33459c4a7965SKim Phillips 				list_add_tail(&t_alg->entry, &priv->alg_list);
33469c4a7965SKim Phillips 		}
33479c4a7965SKim Phillips 	}
33485b859b6eSKim Phillips 	if (!list_empty(&priv->alg_list))
33495b859b6eSKim Phillips 		dev_info(dev, "%s algorithms registered in /proc/crypto\n",
33505b859b6eSKim Phillips 			 (char *)of_get_property(np, "compatible", NULL));
33519c4a7965SKim Phillips 
33529c4a7965SKim Phillips 	return 0;
33539c4a7965SKim Phillips 
33549c4a7965SKim Phillips err_out:
33559c4a7965SKim Phillips 	talitos_remove(ofdev);
33569c4a7965SKim Phillips 
33579c4a7965SKim Phillips 	return err;
33589c4a7965SKim Phillips }
33599c4a7965SKim Phillips 
33606c3f975aSMárton Németh static const struct of_device_id talitos_match[] = {
33610635b7dbSLEROY Christophe #ifdef CONFIG_CRYPTO_DEV_TALITOS1
33620635b7dbSLEROY Christophe 	{
33630635b7dbSLEROY Christophe 		.compatible = "fsl,sec1.0",
33640635b7dbSLEROY Christophe 	},
33650635b7dbSLEROY Christophe #endif
33660635b7dbSLEROY Christophe #ifdef CONFIG_CRYPTO_DEV_TALITOS2
33679c4a7965SKim Phillips 	{
33689c4a7965SKim Phillips 		.compatible = "fsl,sec2.0",
33699c4a7965SKim Phillips 	},
33700635b7dbSLEROY Christophe #endif
33719c4a7965SKim Phillips 	{},
33729c4a7965SKim Phillips };
33739c4a7965SKim Phillips MODULE_DEVICE_TABLE(of, talitos_match);
33749c4a7965SKim Phillips 
33751c48a5c9SGrant Likely static struct platform_driver talitos_driver = {
33764018294bSGrant Likely 	.driver = {
33779c4a7965SKim Phillips 		.name = "talitos",
33784018294bSGrant Likely 		.of_match_table = talitos_match,
33794018294bSGrant Likely 	},
33809c4a7965SKim Phillips 	.probe = talitos_probe,
3381596f1034SAl Viro 	.remove = talitos_remove,
33829c4a7965SKim Phillips };
33839c4a7965SKim Phillips 
3384741e8c2dSAxel Lin module_platform_driver(talitos_driver);
33859c4a7965SKim Phillips 
33869c4a7965SKim Phillips MODULE_LICENSE("GPL");
33879c4a7965SKim Phillips MODULE_AUTHOR("Kim Phillips <kim.phillips@freescale.com>");
33889c4a7965SKim Phillips MODULE_DESCRIPTION("Freescale integrated security engine (SEC) driver");
3389