xref: /linux/drivers/crypto/talitos.c (revision a2b35aa86eeaca6c1d416e3c43d44222c34727fb)
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>
499c4a7965SKim Phillips #include <crypto/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 
58edc6bd69SLEROY Christophe static void to_talitos_ptr(struct talitos_ptr *ptr, dma_addr_t dma_addr)
5981eb024cSKim Phillips {
60edc6bd69SLEROY Christophe 	ptr->ptr = cpu_to_be32(lower_32_bits(dma_addr));
61edc6bd69SLEROY Christophe 	ptr->eptr = upper_32_bits(dma_addr);
6281eb024cSKim Phillips }
6381eb024cSKim Phillips 
64185eb79fSLEROY Christophe static void to_talitos_ptr_extent_clear(struct talitos_ptr *ptr)
65185eb79fSLEROY Christophe {
66185eb79fSLEROY Christophe 	ptr->j_extent = 0;
67185eb79fSLEROY Christophe }
68185eb79fSLEROY Christophe 
699c4a7965SKim Phillips /*
709c4a7965SKim Phillips  * map virtual single (contiguous) pointer to h/w descriptor pointer
719c4a7965SKim Phillips  */
729c4a7965SKim Phillips static void map_single_talitos_ptr(struct device *dev,
73edc6bd69SLEROY Christophe 				   struct talitos_ptr *ptr,
749c4a7965SKim Phillips 				   unsigned short len, void *data,
759c4a7965SKim Phillips 				   enum dma_data_direction dir)
769c4a7965SKim Phillips {
7781eb024cSKim Phillips 	dma_addr_t dma_addr = dma_map_single(dev, data, len, dir);
7881eb024cSKim Phillips 
79edc6bd69SLEROY Christophe 	ptr->len = cpu_to_be16(len);
80edc6bd69SLEROY Christophe 	to_talitos_ptr(ptr, dma_addr);
81*a2b35aa8SLEROY Christophe 	to_talitos_ptr_extent_clear(ptr);
829c4a7965SKim Phillips }
839c4a7965SKim Phillips 
849c4a7965SKim Phillips /*
859c4a7965SKim Phillips  * unmap bus single (contiguous) h/w descriptor pointer
869c4a7965SKim Phillips  */
879c4a7965SKim Phillips static void unmap_single_talitos_ptr(struct device *dev,
88edc6bd69SLEROY Christophe 				     struct talitos_ptr *ptr,
899c4a7965SKim Phillips 				     enum dma_data_direction dir)
909c4a7965SKim Phillips {
91edc6bd69SLEROY Christophe 	dma_unmap_single(dev, be32_to_cpu(ptr->ptr),
92edc6bd69SLEROY Christophe 			 be16_to_cpu(ptr->len), dir);
939c4a7965SKim Phillips }
949c4a7965SKim Phillips 
959c4a7965SKim Phillips static int reset_channel(struct device *dev, int ch)
969c4a7965SKim Phillips {
979c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
989c4a7965SKim Phillips 	unsigned int timeout = TALITOS_TIMEOUT;
999c4a7965SKim Phillips 
100ad42d5fcSKim Phillips 	setbits32(priv->chan[ch].reg + TALITOS_CCCR, TALITOS_CCCR_RESET);
1019c4a7965SKim Phillips 
102ad42d5fcSKim Phillips 	while ((in_be32(priv->chan[ch].reg + TALITOS_CCCR) & TALITOS_CCCR_RESET)
1039c4a7965SKim Phillips 	       && --timeout)
1049c4a7965SKim Phillips 		cpu_relax();
1059c4a7965SKim Phillips 
1069c4a7965SKim Phillips 	if (timeout == 0) {
1079c4a7965SKim Phillips 		dev_err(dev, "failed to reset channel %d\n", ch);
1089c4a7965SKim Phillips 		return -EIO;
1099c4a7965SKim Phillips 	}
1109c4a7965SKim Phillips 
11181eb024cSKim Phillips 	/* set 36-bit addressing, done writeback enable and done IRQ enable */
112ad42d5fcSKim Phillips 	setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO, TALITOS_CCCR_LO_EAE |
11381eb024cSKim Phillips 		  TALITOS_CCCR_LO_CDWE | TALITOS_CCCR_LO_CDIE);
1149c4a7965SKim Phillips 
115fe5720e2SKim Phillips 	/* and ICCR writeback, if available */
116fe5720e2SKim Phillips 	if (priv->features & TALITOS_FTR_HW_AUTH_CHECK)
117ad42d5fcSKim Phillips 		setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO,
118fe5720e2SKim Phillips 		          TALITOS_CCCR_LO_IWSE);
119fe5720e2SKim Phillips 
1209c4a7965SKim Phillips 	return 0;
1219c4a7965SKim Phillips }
1229c4a7965SKim Phillips 
1239c4a7965SKim Phillips static int reset_device(struct device *dev)
1249c4a7965SKim Phillips {
1259c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
1269c4a7965SKim Phillips 	unsigned int timeout = TALITOS_TIMEOUT;
127c3e337f8SKim Phillips 	u32 mcr = TALITOS_MCR_SWR;
1289c4a7965SKim Phillips 
129c3e337f8SKim Phillips 	setbits32(priv->reg + TALITOS_MCR, mcr);
1309c4a7965SKim Phillips 
1319c4a7965SKim Phillips 	while ((in_be32(priv->reg + TALITOS_MCR) & TALITOS_MCR_SWR)
1329c4a7965SKim Phillips 	       && --timeout)
1339c4a7965SKim Phillips 		cpu_relax();
1349c4a7965SKim Phillips 
1352cdba3cfSKim Phillips 	if (priv->irq[1]) {
136c3e337f8SKim Phillips 		mcr = TALITOS_MCR_RCA1 | TALITOS_MCR_RCA3;
137c3e337f8SKim Phillips 		setbits32(priv->reg + TALITOS_MCR, mcr);
138c3e337f8SKim Phillips 	}
139c3e337f8SKim Phillips 
1409c4a7965SKim Phillips 	if (timeout == 0) {
1419c4a7965SKim Phillips 		dev_err(dev, "failed to reset device\n");
1429c4a7965SKim Phillips 		return -EIO;
1439c4a7965SKim Phillips 	}
1449c4a7965SKim Phillips 
1459c4a7965SKim Phillips 	return 0;
1469c4a7965SKim Phillips }
1479c4a7965SKim Phillips 
1489c4a7965SKim Phillips /*
1499c4a7965SKim Phillips  * Reset and initialize the device
1509c4a7965SKim Phillips  */
1519c4a7965SKim Phillips static int init_device(struct device *dev)
1529c4a7965SKim Phillips {
1539c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
1549c4a7965SKim Phillips 	int ch, err;
1559c4a7965SKim Phillips 
1569c4a7965SKim Phillips 	/*
1579c4a7965SKim Phillips 	 * Master reset
1589c4a7965SKim Phillips 	 * errata documentation: warning: certain SEC interrupts
1599c4a7965SKim Phillips 	 * are not fully cleared by writing the MCR:SWR bit,
1609c4a7965SKim Phillips 	 * set bit twice to completely reset
1619c4a7965SKim Phillips 	 */
1629c4a7965SKim Phillips 	err = reset_device(dev);
1639c4a7965SKim Phillips 	if (err)
1649c4a7965SKim Phillips 		return err;
1659c4a7965SKim Phillips 
1669c4a7965SKim Phillips 	err = reset_device(dev);
1679c4a7965SKim Phillips 	if (err)
1689c4a7965SKim Phillips 		return err;
1699c4a7965SKim Phillips 
1709c4a7965SKim Phillips 	/* reset channels */
1719c4a7965SKim Phillips 	for (ch = 0; ch < priv->num_channels; ch++) {
1729c4a7965SKim Phillips 		err = reset_channel(dev, ch);
1739c4a7965SKim Phillips 		if (err)
1749c4a7965SKim Phillips 			return err;
1759c4a7965SKim Phillips 	}
1769c4a7965SKim Phillips 
1779c4a7965SKim Phillips 	/* enable channel done and error interrupts */
1789c4a7965SKim Phillips 	setbits32(priv->reg + TALITOS_IMR, TALITOS_IMR_INIT);
1799c4a7965SKim Phillips 	setbits32(priv->reg + TALITOS_IMR_LO, TALITOS_IMR_LO_INIT);
1809c4a7965SKim Phillips 
181fe5720e2SKim Phillips 	/* disable integrity check error interrupts (use writeback instead) */
182fe5720e2SKim Phillips 	if (priv->features & TALITOS_FTR_HW_AUTH_CHECK)
183fe5720e2SKim Phillips 		setbits32(priv->reg + TALITOS_MDEUICR_LO,
184fe5720e2SKim Phillips 		          TALITOS_MDEUICR_LO_ICE);
185fe5720e2SKim Phillips 
1869c4a7965SKim Phillips 	return 0;
1879c4a7965SKim Phillips }
1889c4a7965SKim Phillips 
1899c4a7965SKim Phillips /**
1909c4a7965SKim Phillips  * talitos_submit - submits a descriptor to the device for processing
1919c4a7965SKim Phillips  * @dev:	the SEC device to be used
1925228f0f7SKim Phillips  * @ch:		the SEC device channel to be used
1939c4a7965SKim Phillips  * @desc:	the descriptor to be processed by the device
1949c4a7965SKim Phillips  * @callback:	whom to call when processing is complete
1959c4a7965SKim Phillips  * @context:	a handle for use by caller (optional)
1969c4a7965SKim Phillips  *
1979c4a7965SKim Phillips  * desc must contain valid dma-mapped (bus physical) address pointers.
1989c4a7965SKim Phillips  * callback must check err and feedback in descriptor header
1999c4a7965SKim Phillips  * for device processing status.
2009c4a7965SKim Phillips  */
201865d5061SHoria Geanta int talitos_submit(struct device *dev, int ch, struct talitos_desc *desc,
2029c4a7965SKim Phillips 		   void (*callback)(struct device *dev,
2039c4a7965SKim Phillips 				    struct talitos_desc *desc,
2049c4a7965SKim Phillips 				    void *context, int error),
2059c4a7965SKim Phillips 		   void *context)
2069c4a7965SKim Phillips {
2079c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
2089c4a7965SKim Phillips 	struct talitos_request *request;
2095228f0f7SKim Phillips 	unsigned long flags;
2109c4a7965SKim Phillips 	int head;
2119c4a7965SKim Phillips 
2124b992628SKim Phillips 	spin_lock_irqsave(&priv->chan[ch].head_lock, flags);
2139c4a7965SKim Phillips 
2144b992628SKim Phillips 	if (!atomic_inc_not_zero(&priv->chan[ch].submit_count)) {
215ec6644d6SKim Phillips 		/* h/w fifo is full */
2164b992628SKim Phillips 		spin_unlock_irqrestore(&priv->chan[ch].head_lock, flags);
2179c4a7965SKim Phillips 		return -EAGAIN;
2189c4a7965SKim Phillips 	}
2199c4a7965SKim Phillips 
2204b992628SKim Phillips 	head = priv->chan[ch].head;
2214b992628SKim Phillips 	request = &priv->chan[ch].fifo[head];
222ec6644d6SKim Phillips 
2239c4a7965SKim Phillips 	/* map descriptor and save caller data */
2249c4a7965SKim Phillips 	request->dma_desc = dma_map_single(dev, desc, sizeof(*desc),
2259c4a7965SKim Phillips 					   DMA_BIDIRECTIONAL);
2269c4a7965SKim Phillips 	request->callback = callback;
2279c4a7965SKim Phillips 	request->context = context;
2289c4a7965SKim Phillips 
2299c4a7965SKim Phillips 	/* increment fifo head */
2304b992628SKim Phillips 	priv->chan[ch].head = (priv->chan[ch].head + 1) & (priv->fifo_len - 1);
2319c4a7965SKim Phillips 
2329c4a7965SKim Phillips 	smp_wmb();
2339c4a7965SKim Phillips 	request->desc = desc;
2349c4a7965SKim Phillips 
2359c4a7965SKim Phillips 	/* GO! */
2369c4a7965SKim Phillips 	wmb();
237ad42d5fcSKim Phillips 	out_be32(priv->chan[ch].reg + TALITOS_FF,
238ad42d5fcSKim Phillips 		 upper_32_bits(request->dma_desc));
239ad42d5fcSKim Phillips 	out_be32(priv->chan[ch].reg + TALITOS_FF_LO,
240a752447aSKim Phillips 		 lower_32_bits(request->dma_desc));
2419c4a7965SKim Phillips 
2424b992628SKim Phillips 	spin_unlock_irqrestore(&priv->chan[ch].head_lock, flags);
2439c4a7965SKim Phillips 
2449c4a7965SKim Phillips 	return -EINPROGRESS;
2459c4a7965SKim Phillips }
246865d5061SHoria Geanta EXPORT_SYMBOL(talitos_submit);
2479c4a7965SKim Phillips 
2489c4a7965SKim Phillips /*
2499c4a7965SKim Phillips  * process what was done, notify callback of error if not
2509c4a7965SKim Phillips  */
2519c4a7965SKim Phillips static void flush_channel(struct device *dev, int ch, int error, int reset_ch)
2529c4a7965SKim Phillips {
2539c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
2549c4a7965SKim Phillips 	struct talitos_request *request, saved_req;
2559c4a7965SKim Phillips 	unsigned long flags;
2569c4a7965SKim Phillips 	int tail, status;
2579c4a7965SKim Phillips 
2584b992628SKim Phillips 	spin_lock_irqsave(&priv->chan[ch].tail_lock, flags);
2599c4a7965SKim Phillips 
2604b992628SKim Phillips 	tail = priv->chan[ch].tail;
2614b992628SKim Phillips 	while (priv->chan[ch].fifo[tail].desc) {
2624b992628SKim Phillips 		request = &priv->chan[ch].fifo[tail];
2639c4a7965SKim Phillips 
2649c4a7965SKim Phillips 		/* descriptors with their done bits set don't get the error */
2659c4a7965SKim Phillips 		rmb();
266ca38a814SLee Nipper 		if ((request->desc->hdr & DESC_HDR_DONE) == DESC_HDR_DONE)
2679c4a7965SKim Phillips 			status = 0;
268ca38a814SLee Nipper 		else
2699c4a7965SKim Phillips 			if (!error)
2709c4a7965SKim Phillips 				break;
2719c4a7965SKim Phillips 			else
2729c4a7965SKim Phillips 				status = error;
2739c4a7965SKim Phillips 
2749c4a7965SKim Phillips 		dma_unmap_single(dev, request->dma_desc,
275e938e465SKim Phillips 				 sizeof(struct talitos_desc),
276e938e465SKim Phillips 				 DMA_BIDIRECTIONAL);
2779c4a7965SKim Phillips 
2789c4a7965SKim Phillips 		/* copy entries so we can call callback outside lock */
2799c4a7965SKim Phillips 		saved_req.desc = request->desc;
2809c4a7965SKim Phillips 		saved_req.callback = request->callback;
2819c4a7965SKim Phillips 		saved_req.context = request->context;
2829c4a7965SKim Phillips 
2839c4a7965SKim Phillips 		/* release request entry in fifo */
2849c4a7965SKim Phillips 		smp_wmb();
2859c4a7965SKim Phillips 		request->desc = NULL;
2869c4a7965SKim Phillips 
2879c4a7965SKim Phillips 		/* increment fifo tail */
2884b992628SKim Phillips 		priv->chan[ch].tail = (tail + 1) & (priv->fifo_len - 1);
2899c4a7965SKim Phillips 
2904b992628SKim Phillips 		spin_unlock_irqrestore(&priv->chan[ch].tail_lock, flags);
291ec6644d6SKim Phillips 
2924b992628SKim Phillips 		atomic_dec(&priv->chan[ch].submit_count);
293ec6644d6SKim Phillips 
2949c4a7965SKim Phillips 		saved_req.callback(dev, saved_req.desc, saved_req.context,
2959c4a7965SKim Phillips 				   status);
2969c4a7965SKim Phillips 		/* channel may resume processing in single desc error case */
2979c4a7965SKim Phillips 		if (error && !reset_ch && status == error)
2989c4a7965SKim Phillips 			return;
2994b992628SKim Phillips 		spin_lock_irqsave(&priv->chan[ch].tail_lock, flags);
3004b992628SKim Phillips 		tail = priv->chan[ch].tail;
3019c4a7965SKim Phillips 	}
3029c4a7965SKim Phillips 
3034b992628SKim Phillips 	spin_unlock_irqrestore(&priv->chan[ch].tail_lock, flags);
3049c4a7965SKim Phillips }
3059c4a7965SKim Phillips 
3069c4a7965SKim Phillips /*
3079c4a7965SKim Phillips  * process completed requests for channels that have done status
3089c4a7965SKim Phillips  */
309c3e337f8SKim Phillips #define DEF_TALITOS_DONE(name, ch_done_mask)				\
310c3e337f8SKim Phillips static void talitos_done_##name(unsigned long data)			\
311c3e337f8SKim Phillips {									\
312c3e337f8SKim Phillips 	struct device *dev = (struct device *)data;			\
313c3e337f8SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);		\
314511d63cbSHoria Geanta 	unsigned long flags;						\
315c3e337f8SKim Phillips 									\
316c3e337f8SKim Phillips 	if (ch_done_mask & 1)						\
317c3e337f8SKim Phillips 		flush_channel(dev, 0, 0, 0);				\
318c3e337f8SKim Phillips 	if (priv->num_channels == 1)					\
319c3e337f8SKim Phillips 		goto out;						\
320c3e337f8SKim Phillips 	if (ch_done_mask & (1 << 2))					\
321c3e337f8SKim Phillips 		flush_channel(dev, 1, 0, 0);				\
322c3e337f8SKim Phillips 	if (ch_done_mask & (1 << 4))					\
323c3e337f8SKim Phillips 		flush_channel(dev, 2, 0, 0);				\
324c3e337f8SKim Phillips 	if (ch_done_mask & (1 << 6))					\
325c3e337f8SKim Phillips 		flush_channel(dev, 3, 0, 0);				\
326c3e337f8SKim Phillips 									\
327c3e337f8SKim Phillips out:									\
328c3e337f8SKim Phillips 	/* At this point, all completed channels have been processed */	\
329c3e337f8SKim Phillips 	/* Unmask done interrupts for channels completed later on. */	\
330511d63cbSHoria Geanta 	spin_lock_irqsave(&priv->reg_lock, flags);			\
331c3e337f8SKim Phillips 	setbits32(priv->reg + TALITOS_IMR, ch_done_mask);		\
332c3e337f8SKim Phillips 	setbits32(priv->reg + TALITOS_IMR_LO, TALITOS_IMR_LO_INIT);	\
333511d63cbSHoria Geanta 	spin_unlock_irqrestore(&priv->reg_lock, flags);			\
3349c4a7965SKim Phillips }
335c3e337f8SKim Phillips DEF_TALITOS_DONE(4ch, TALITOS_ISR_4CHDONE)
336c3e337f8SKim Phillips DEF_TALITOS_DONE(ch0_2, TALITOS_ISR_CH_0_2_DONE)
337c3e337f8SKim Phillips DEF_TALITOS_DONE(ch1_3, TALITOS_ISR_CH_1_3_DONE)
3389c4a7965SKim Phillips 
3399c4a7965SKim Phillips /*
3409c4a7965SKim Phillips  * locate current (offending) descriptor
3419c4a7965SKim Phillips  */
3423e721aebSKim Phillips static u32 current_desc_hdr(struct device *dev, int ch)
3439c4a7965SKim Phillips {
3449c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
345b62ffd8cSHoria Geanta 	int tail, iter;
3469c4a7965SKim Phillips 	dma_addr_t cur_desc;
3479c4a7965SKim Phillips 
348b62ffd8cSHoria Geanta 	cur_desc = ((u64)in_be32(priv->chan[ch].reg + TALITOS_CDPR)) << 32;
349b62ffd8cSHoria Geanta 	cur_desc |= in_be32(priv->chan[ch].reg + TALITOS_CDPR_LO);
3509c4a7965SKim Phillips 
351b62ffd8cSHoria Geanta 	if (!cur_desc) {
352b62ffd8cSHoria Geanta 		dev_err(dev, "CDPR is NULL, giving up search for offending descriptor\n");
353b62ffd8cSHoria Geanta 		return 0;
354b62ffd8cSHoria Geanta 	}
355b62ffd8cSHoria Geanta 
356b62ffd8cSHoria Geanta 	tail = priv->chan[ch].tail;
357b62ffd8cSHoria Geanta 
358b62ffd8cSHoria Geanta 	iter = tail;
359b62ffd8cSHoria Geanta 	while (priv->chan[ch].fifo[iter].dma_desc != cur_desc) {
360b62ffd8cSHoria Geanta 		iter = (iter + 1) & (priv->fifo_len - 1);
361b62ffd8cSHoria Geanta 		if (iter == tail) {
3629c4a7965SKim Phillips 			dev_err(dev, "couldn't locate current descriptor\n");
3633e721aebSKim Phillips 			return 0;
3649c4a7965SKim Phillips 		}
3659c4a7965SKim Phillips 	}
3669c4a7965SKim Phillips 
367b62ffd8cSHoria Geanta 	return priv->chan[ch].fifo[iter].desc->hdr;
3689c4a7965SKim Phillips }
3699c4a7965SKim Phillips 
3709c4a7965SKim Phillips /*
3719c4a7965SKim Phillips  * user diagnostics; report root cause of error based on execution unit status
3729c4a7965SKim Phillips  */
3733e721aebSKim Phillips static void report_eu_error(struct device *dev, int ch, u32 desc_hdr)
3749c4a7965SKim Phillips {
3759c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
3769c4a7965SKim Phillips 	int i;
3779c4a7965SKim Phillips 
3783e721aebSKim Phillips 	if (!desc_hdr)
379ad42d5fcSKim Phillips 		desc_hdr = in_be32(priv->chan[ch].reg + TALITOS_DESCBUF);
3803e721aebSKim Phillips 
3813e721aebSKim Phillips 	switch (desc_hdr & DESC_HDR_SEL0_MASK) {
3829c4a7965SKim Phillips 	case DESC_HDR_SEL0_AFEU:
3839c4a7965SKim Phillips 		dev_err(dev, "AFEUISR 0x%08x_%08x\n",
3849c4a7965SKim Phillips 			in_be32(priv->reg + TALITOS_AFEUISR),
3859c4a7965SKim Phillips 			in_be32(priv->reg + TALITOS_AFEUISR_LO));
3869c4a7965SKim Phillips 		break;
3879c4a7965SKim Phillips 	case DESC_HDR_SEL0_DEU:
3889c4a7965SKim Phillips 		dev_err(dev, "DEUISR 0x%08x_%08x\n",
3899c4a7965SKim Phillips 			in_be32(priv->reg + TALITOS_DEUISR),
3909c4a7965SKim Phillips 			in_be32(priv->reg + TALITOS_DEUISR_LO));
3919c4a7965SKim Phillips 		break;
3929c4a7965SKim Phillips 	case DESC_HDR_SEL0_MDEUA:
3939c4a7965SKim Phillips 	case DESC_HDR_SEL0_MDEUB:
3949c4a7965SKim Phillips 		dev_err(dev, "MDEUISR 0x%08x_%08x\n",
3959c4a7965SKim Phillips 			in_be32(priv->reg + TALITOS_MDEUISR),
3969c4a7965SKim Phillips 			in_be32(priv->reg + TALITOS_MDEUISR_LO));
3979c4a7965SKim Phillips 		break;
3989c4a7965SKim Phillips 	case DESC_HDR_SEL0_RNG:
3999c4a7965SKim Phillips 		dev_err(dev, "RNGUISR 0x%08x_%08x\n",
4009c4a7965SKim Phillips 			in_be32(priv->reg + TALITOS_RNGUISR),
4019c4a7965SKim Phillips 			in_be32(priv->reg + TALITOS_RNGUISR_LO));
4029c4a7965SKim Phillips 		break;
4039c4a7965SKim Phillips 	case DESC_HDR_SEL0_PKEU:
4049c4a7965SKim Phillips 		dev_err(dev, "PKEUISR 0x%08x_%08x\n",
4059c4a7965SKim Phillips 			in_be32(priv->reg + TALITOS_PKEUISR),
4069c4a7965SKim Phillips 			in_be32(priv->reg + TALITOS_PKEUISR_LO));
4079c4a7965SKim Phillips 		break;
4089c4a7965SKim Phillips 	case DESC_HDR_SEL0_AESU:
4099c4a7965SKim Phillips 		dev_err(dev, "AESUISR 0x%08x_%08x\n",
4109c4a7965SKim Phillips 			in_be32(priv->reg + TALITOS_AESUISR),
4119c4a7965SKim Phillips 			in_be32(priv->reg + TALITOS_AESUISR_LO));
4129c4a7965SKim Phillips 		break;
4139c4a7965SKim Phillips 	case DESC_HDR_SEL0_CRCU:
4149c4a7965SKim Phillips 		dev_err(dev, "CRCUISR 0x%08x_%08x\n",
4159c4a7965SKim Phillips 			in_be32(priv->reg + TALITOS_CRCUISR),
4169c4a7965SKim Phillips 			in_be32(priv->reg + TALITOS_CRCUISR_LO));
4179c4a7965SKim Phillips 		break;
4189c4a7965SKim Phillips 	case DESC_HDR_SEL0_KEU:
4199c4a7965SKim Phillips 		dev_err(dev, "KEUISR 0x%08x_%08x\n",
4209c4a7965SKim Phillips 			in_be32(priv->reg + TALITOS_KEUISR),
4219c4a7965SKim Phillips 			in_be32(priv->reg + TALITOS_KEUISR_LO));
4229c4a7965SKim Phillips 		break;
4239c4a7965SKim Phillips 	}
4249c4a7965SKim Phillips 
4253e721aebSKim Phillips 	switch (desc_hdr & DESC_HDR_SEL1_MASK) {
4269c4a7965SKim Phillips 	case DESC_HDR_SEL1_MDEUA:
4279c4a7965SKim Phillips 	case DESC_HDR_SEL1_MDEUB:
4289c4a7965SKim Phillips 		dev_err(dev, "MDEUISR 0x%08x_%08x\n",
4299c4a7965SKim Phillips 			in_be32(priv->reg + TALITOS_MDEUISR),
4309c4a7965SKim Phillips 			in_be32(priv->reg + TALITOS_MDEUISR_LO));
4319c4a7965SKim Phillips 		break;
4329c4a7965SKim Phillips 	case DESC_HDR_SEL1_CRCU:
4339c4a7965SKim Phillips 		dev_err(dev, "CRCUISR 0x%08x_%08x\n",
4349c4a7965SKim Phillips 			in_be32(priv->reg + TALITOS_CRCUISR),
4359c4a7965SKim Phillips 			in_be32(priv->reg + TALITOS_CRCUISR_LO));
4369c4a7965SKim Phillips 		break;
4379c4a7965SKim Phillips 	}
4389c4a7965SKim Phillips 
4399c4a7965SKim Phillips 	for (i = 0; i < 8; i++)
4409c4a7965SKim Phillips 		dev_err(dev, "DESCBUF 0x%08x_%08x\n",
441ad42d5fcSKim Phillips 			in_be32(priv->chan[ch].reg + TALITOS_DESCBUF + 8*i),
442ad42d5fcSKim Phillips 			in_be32(priv->chan[ch].reg + TALITOS_DESCBUF_LO + 8*i));
4439c4a7965SKim Phillips }
4449c4a7965SKim Phillips 
4459c4a7965SKim Phillips /*
4469c4a7965SKim Phillips  * recover from error interrupts
4479c4a7965SKim Phillips  */
4485e718a09SKim Phillips static void talitos_error(struct device *dev, u32 isr, u32 isr_lo)
4499c4a7965SKim Phillips {
4509c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
4519c4a7965SKim Phillips 	unsigned int timeout = TALITOS_TIMEOUT;
4529c4a7965SKim Phillips 	int ch, error, reset_dev = 0, reset_ch = 0;
45340405f10SKim Phillips 	u32 v, v_lo;
4549c4a7965SKim Phillips 
4559c4a7965SKim Phillips 	for (ch = 0; ch < priv->num_channels; ch++) {
4569c4a7965SKim Phillips 		/* skip channels without errors */
4579c4a7965SKim Phillips 		if (!(isr & (1 << (ch * 2 + 1))))
4589c4a7965SKim Phillips 			continue;
4599c4a7965SKim Phillips 
4609c4a7965SKim Phillips 		error = -EINVAL;
4619c4a7965SKim Phillips 
462ad42d5fcSKim Phillips 		v = in_be32(priv->chan[ch].reg + TALITOS_CCPSR);
463ad42d5fcSKim Phillips 		v_lo = in_be32(priv->chan[ch].reg + TALITOS_CCPSR_LO);
4649c4a7965SKim Phillips 
4659c4a7965SKim Phillips 		if (v_lo & TALITOS_CCPSR_LO_DOF) {
4669c4a7965SKim Phillips 			dev_err(dev, "double fetch fifo overflow error\n");
4679c4a7965SKim Phillips 			error = -EAGAIN;
4689c4a7965SKim Phillips 			reset_ch = 1;
4699c4a7965SKim Phillips 		}
4709c4a7965SKim Phillips 		if (v_lo & TALITOS_CCPSR_LO_SOF) {
4719c4a7965SKim Phillips 			/* h/w dropped descriptor */
4729c4a7965SKim Phillips 			dev_err(dev, "single fetch fifo overflow error\n");
4739c4a7965SKim Phillips 			error = -EAGAIN;
4749c4a7965SKim Phillips 		}
4759c4a7965SKim Phillips 		if (v_lo & TALITOS_CCPSR_LO_MDTE)
4769c4a7965SKim Phillips 			dev_err(dev, "master data transfer error\n");
4779c4a7965SKim Phillips 		if (v_lo & TALITOS_CCPSR_LO_SGDLZ)
4789c4a7965SKim Phillips 			dev_err(dev, "s/g data length zero error\n");
4799c4a7965SKim Phillips 		if (v_lo & TALITOS_CCPSR_LO_FPZ)
4809c4a7965SKim Phillips 			dev_err(dev, "fetch pointer zero error\n");
4819c4a7965SKim Phillips 		if (v_lo & TALITOS_CCPSR_LO_IDH)
4829c4a7965SKim Phillips 			dev_err(dev, "illegal descriptor header error\n");
4839c4a7965SKim Phillips 		if (v_lo & TALITOS_CCPSR_LO_IEU)
4849c4a7965SKim Phillips 			dev_err(dev, "invalid execution unit error\n");
4859c4a7965SKim Phillips 		if (v_lo & TALITOS_CCPSR_LO_EU)
4863e721aebSKim Phillips 			report_eu_error(dev, ch, current_desc_hdr(dev, ch));
4879c4a7965SKim Phillips 		if (v_lo & TALITOS_CCPSR_LO_GB)
4889c4a7965SKim Phillips 			dev_err(dev, "gather boundary error\n");
4899c4a7965SKim Phillips 		if (v_lo & TALITOS_CCPSR_LO_GRL)
4909c4a7965SKim Phillips 			dev_err(dev, "gather return/length error\n");
4919c4a7965SKim Phillips 		if (v_lo & TALITOS_CCPSR_LO_SB)
4929c4a7965SKim Phillips 			dev_err(dev, "scatter boundary error\n");
4939c4a7965SKim Phillips 		if (v_lo & TALITOS_CCPSR_LO_SRL)
4949c4a7965SKim Phillips 			dev_err(dev, "scatter return/length error\n");
4959c4a7965SKim Phillips 
4969c4a7965SKim Phillips 		flush_channel(dev, ch, error, reset_ch);
4979c4a7965SKim Phillips 
4989c4a7965SKim Phillips 		if (reset_ch) {
4999c4a7965SKim Phillips 			reset_channel(dev, ch);
5009c4a7965SKim Phillips 		} else {
501ad42d5fcSKim Phillips 			setbits32(priv->chan[ch].reg + TALITOS_CCCR,
5029c4a7965SKim Phillips 				  TALITOS_CCCR_CONT);
503ad42d5fcSKim Phillips 			setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO, 0);
504ad42d5fcSKim Phillips 			while ((in_be32(priv->chan[ch].reg + TALITOS_CCCR) &
5059c4a7965SKim Phillips 			       TALITOS_CCCR_CONT) && --timeout)
5069c4a7965SKim Phillips 				cpu_relax();
5079c4a7965SKim Phillips 			if (timeout == 0) {
5089c4a7965SKim Phillips 				dev_err(dev, "failed to restart channel %d\n",
5099c4a7965SKim Phillips 					ch);
5109c4a7965SKim Phillips 				reset_dev = 1;
5119c4a7965SKim Phillips 			}
5129c4a7965SKim Phillips 		}
5139c4a7965SKim Phillips 	}
514c3e337f8SKim Phillips 	if (reset_dev || isr & ~TALITOS_ISR_4CHERR || isr_lo) {
5159c4a7965SKim Phillips 		dev_err(dev, "done overflow, internal time out, or rngu error: "
5169c4a7965SKim Phillips 		        "ISR 0x%08x_%08x\n", isr, isr_lo);
5179c4a7965SKim Phillips 
5189c4a7965SKim Phillips 		/* purge request queues */
5199c4a7965SKim Phillips 		for (ch = 0; ch < priv->num_channels; ch++)
5209c4a7965SKim Phillips 			flush_channel(dev, ch, -EIO, 1);
5219c4a7965SKim Phillips 
5229c4a7965SKim Phillips 		/* reset and reinitialize the device */
5239c4a7965SKim Phillips 		init_device(dev);
5249c4a7965SKim Phillips 	}
5259c4a7965SKim Phillips }
5269c4a7965SKim Phillips 
527c3e337f8SKim Phillips #define DEF_TALITOS_INTERRUPT(name, ch_done_mask, ch_err_mask, tlet)	       \
528c3e337f8SKim Phillips static irqreturn_t talitos_interrupt_##name(int irq, void *data)	       \
529c3e337f8SKim Phillips {									       \
530c3e337f8SKim Phillips 	struct device *dev = data;					       \
531c3e337f8SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);		       \
532c3e337f8SKim Phillips 	u32 isr, isr_lo;						       \
533511d63cbSHoria Geanta 	unsigned long flags;						       \
534c3e337f8SKim Phillips 									       \
535511d63cbSHoria Geanta 	spin_lock_irqsave(&priv->reg_lock, flags);			       \
536c3e337f8SKim Phillips 	isr = in_be32(priv->reg + TALITOS_ISR);				       \
537c3e337f8SKim Phillips 	isr_lo = in_be32(priv->reg + TALITOS_ISR_LO);			       \
538c3e337f8SKim Phillips 	/* Acknowledge interrupt */					       \
539c3e337f8SKim Phillips 	out_be32(priv->reg + TALITOS_ICR, isr & (ch_done_mask | ch_err_mask)); \
540c3e337f8SKim Phillips 	out_be32(priv->reg + TALITOS_ICR_LO, isr_lo);			       \
541c3e337f8SKim Phillips 									       \
542511d63cbSHoria Geanta 	if (unlikely(isr & ch_err_mask || isr_lo)) {			       \
543511d63cbSHoria Geanta 		spin_unlock_irqrestore(&priv->reg_lock, flags);		       \
544511d63cbSHoria Geanta 		talitos_error(dev, isr & ch_err_mask, isr_lo);		       \
545511d63cbSHoria Geanta 	}								       \
546511d63cbSHoria Geanta 	else {								       \
547c3e337f8SKim Phillips 		if (likely(isr & ch_done_mask)) {			       \
548c3e337f8SKim Phillips 			/* mask further done interrupts. */		       \
549c3e337f8SKim Phillips 			clrbits32(priv->reg + TALITOS_IMR, ch_done_mask);      \
550c3e337f8SKim Phillips 			/* done_task will unmask done interrupts at exit */    \
551c3e337f8SKim Phillips 			tasklet_schedule(&priv->done_task[tlet]);	       \
552c3e337f8SKim Phillips 		}							       \
553511d63cbSHoria Geanta 		spin_unlock_irqrestore(&priv->reg_lock, flags);		       \
554511d63cbSHoria Geanta 	}								       \
555c3e337f8SKim Phillips 									       \
556c3e337f8SKim Phillips 	return (isr & (ch_done_mask | ch_err_mask) || isr_lo) ? IRQ_HANDLED :  \
557c3e337f8SKim Phillips 								IRQ_NONE;      \
5581c2e8811SLee Nipper }
559c3e337f8SKim Phillips DEF_TALITOS_INTERRUPT(4ch, TALITOS_ISR_4CHDONE, TALITOS_ISR_4CHERR, 0)
560c3e337f8SKim Phillips DEF_TALITOS_INTERRUPT(ch0_2, TALITOS_ISR_CH_0_2_DONE, TALITOS_ISR_CH_0_2_ERR, 0)
561c3e337f8SKim Phillips DEF_TALITOS_INTERRUPT(ch1_3, TALITOS_ISR_CH_1_3_DONE, TALITOS_ISR_CH_1_3_ERR, 1)
5629c4a7965SKim Phillips 
5639c4a7965SKim Phillips /*
5649c4a7965SKim Phillips  * hwrng
5659c4a7965SKim Phillips  */
5669c4a7965SKim Phillips static int talitos_rng_data_present(struct hwrng *rng, int wait)
5679c4a7965SKim Phillips {
5689c4a7965SKim Phillips 	struct device *dev = (struct device *)rng->priv;
5699c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
5709c4a7965SKim Phillips 	u32 ofl;
5719c4a7965SKim Phillips 	int i;
5729c4a7965SKim Phillips 
5739c4a7965SKim Phillips 	for (i = 0; i < 20; i++) {
5749c4a7965SKim Phillips 		ofl = in_be32(priv->reg + TALITOS_RNGUSR_LO) &
5759c4a7965SKim Phillips 		      TALITOS_RNGUSR_LO_OFL;
5769c4a7965SKim Phillips 		if (ofl || !wait)
5779c4a7965SKim Phillips 			break;
5789c4a7965SKim Phillips 		udelay(10);
5799c4a7965SKim Phillips 	}
5809c4a7965SKim Phillips 
5819c4a7965SKim Phillips 	return !!ofl;
5829c4a7965SKim Phillips }
5839c4a7965SKim Phillips 
5849c4a7965SKim Phillips static int talitos_rng_data_read(struct hwrng *rng, u32 *data)
5859c4a7965SKim Phillips {
5869c4a7965SKim Phillips 	struct device *dev = (struct device *)rng->priv;
5879c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
5889c4a7965SKim Phillips 
5899c4a7965SKim Phillips 	/* rng fifo requires 64-bit accesses */
5909c4a7965SKim Phillips 	*data = in_be32(priv->reg + TALITOS_RNGU_FIFO);
5919c4a7965SKim Phillips 	*data = in_be32(priv->reg + TALITOS_RNGU_FIFO_LO);
5929c4a7965SKim Phillips 
5939c4a7965SKim Phillips 	return sizeof(u32);
5949c4a7965SKim Phillips }
5959c4a7965SKim Phillips 
5969c4a7965SKim Phillips static int talitos_rng_init(struct hwrng *rng)
5979c4a7965SKim Phillips {
5989c4a7965SKim Phillips 	struct device *dev = (struct device *)rng->priv;
5999c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
6009c4a7965SKim Phillips 	unsigned int timeout = TALITOS_TIMEOUT;
6019c4a7965SKim Phillips 
6029c4a7965SKim Phillips 	setbits32(priv->reg + TALITOS_RNGURCR_LO, TALITOS_RNGURCR_LO_SR);
6039c4a7965SKim Phillips 	while (!(in_be32(priv->reg + TALITOS_RNGUSR_LO) & TALITOS_RNGUSR_LO_RD)
6049c4a7965SKim Phillips 	       && --timeout)
6059c4a7965SKim Phillips 		cpu_relax();
6069c4a7965SKim Phillips 	if (timeout == 0) {
6079c4a7965SKim Phillips 		dev_err(dev, "failed to reset rng hw\n");
6089c4a7965SKim Phillips 		return -ENODEV;
6099c4a7965SKim Phillips 	}
6109c4a7965SKim Phillips 
6119c4a7965SKim Phillips 	/* start generating */
6129c4a7965SKim Phillips 	setbits32(priv->reg + TALITOS_RNGUDSR_LO, 0);
6139c4a7965SKim Phillips 
6149c4a7965SKim Phillips 	return 0;
6159c4a7965SKim Phillips }
6169c4a7965SKim Phillips 
6179c4a7965SKim Phillips static int talitos_register_rng(struct device *dev)
6189c4a7965SKim Phillips {
6199c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
6209c4a7965SKim Phillips 
6219c4a7965SKim Phillips 	priv->rng.name		= dev_driver_string(dev),
6229c4a7965SKim Phillips 	priv->rng.init		= talitos_rng_init,
6239c4a7965SKim Phillips 	priv->rng.data_present	= talitos_rng_data_present,
6249c4a7965SKim Phillips 	priv->rng.data_read	= talitos_rng_data_read,
6259c4a7965SKim Phillips 	priv->rng.priv		= (unsigned long)dev;
6269c4a7965SKim Phillips 
6279c4a7965SKim Phillips 	return hwrng_register(&priv->rng);
6289c4a7965SKim Phillips }
6299c4a7965SKim Phillips 
6309c4a7965SKim Phillips static void talitos_unregister_rng(struct device *dev)
6319c4a7965SKim Phillips {
6329c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
6339c4a7965SKim Phillips 
6349c4a7965SKim Phillips 	hwrng_unregister(&priv->rng);
6359c4a7965SKim Phillips }
6369c4a7965SKim Phillips 
6379c4a7965SKim Phillips /*
6389c4a7965SKim Phillips  * crypto alg
6399c4a7965SKim Phillips  */
6409c4a7965SKim Phillips #define TALITOS_CRA_PRIORITY		3000
641357fb605SHoria Geanta #define TALITOS_MAX_KEY_SIZE		96
6423952f17eSLee Nipper #define TALITOS_MAX_IV_LENGTH		16 /* max of AES_BLOCK_SIZE, DES3_EDE_BLOCK_SIZE */
64370bcaca7SLee Nipper 
6449c4a7965SKim Phillips struct talitos_ctx {
6459c4a7965SKim Phillips 	struct device *dev;
6465228f0f7SKim Phillips 	int ch;
6479c4a7965SKim Phillips 	__be32 desc_hdr_template;
6489c4a7965SKim Phillips 	u8 key[TALITOS_MAX_KEY_SIZE];
64970bcaca7SLee Nipper 	u8 iv[TALITOS_MAX_IV_LENGTH];
6509c4a7965SKim Phillips 	unsigned int keylen;
6519c4a7965SKim Phillips 	unsigned int enckeylen;
6529c4a7965SKim Phillips 	unsigned int authkeylen;
6539c4a7965SKim Phillips 	unsigned int authsize;
6549c4a7965SKim Phillips };
6559c4a7965SKim Phillips 
656497f2e6bSLee Nipper #define HASH_MAX_BLOCK_SIZE		SHA512_BLOCK_SIZE
657497f2e6bSLee Nipper #define TALITOS_MDEU_MAX_CONTEXT_SIZE	TALITOS_MDEU_CONTEXT_SIZE_SHA384_SHA512
658497f2e6bSLee Nipper 
659497f2e6bSLee Nipper struct talitos_ahash_req_ctx {
66060f208d7SKim Phillips 	u32 hw_context[TALITOS_MDEU_MAX_CONTEXT_SIZE / sizeof(u32)];
661497f2e6bSLee Nipper 	unsigned int hw_context_size;
662497f2e6bSLee Nipper 	u8 buf[HASH_MAX_BLOCK_SIZE];
663497f2e6bSLee Nipper 	u8 bufnext[HASH_MAX_BLOCK_SIZE];
66460f208d7SKim Phillips 	unsigned int swinit;
665497f2e6bSLee Nipper 	unsigned int first;
666497f2e6bSLee Nipper 	unsigned int last;
667497f2e6bSLee Nipper 	unsigned int to_hash_later;
6685e833bc4SLee Nipper 	u64 nbuf;
669497f2e6bSLee Nipper 	struct scatterlist bufsl[2];
670497f2e6bSLee Nipper 	struct scatterlist *psrc;
671497f2e6bSLee Nipper };
672497f2e6bSLee Nipper 
67356af8cd4SLee Nipper static int aead_setauthsize(struct crypto_aead *authenc,
6749c4a7965SKim Phillips 			    unsigned int authsize)
6759c4a7965SKim Phillips {
6769c4a7965SKim Phillips 	struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
6779c4a7965SKim Phillips 
6789c4a7965SKim Phillips 	ctx->authsize = authsize;
6799c4a7965SKim Phillips 
6809c4a7965SKim Phillips 	return 0;
6819c4a7965SKim Phillips }
6829c4a7965SKim Phillips 
68356af8cd4SLee Nipper static int aead_setkey(struct crypto_aead *authenc,
6849c4a7965SKim Phillips 		       const u8 *key, unsigned int keylen)
6859c4a7965SKim Phillips {
6869c4a7965SKim Phillips 	struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
687c306a98dSMathias Krause 	struct crypto_authenc_keys keys;
6889c4a7965SKim Phillips 
689c306a98dSMathias Krause 	if (crypto_authenc_extractkeys(&keys, key, keylen) != 0)
6909c4a7965SKim Phillips 		goto badkey;
6919c4a7965SKim Phillips 
692c306a98dSMathias Krause 	if (keys.authkeylen + keys.enckeylen > TALITOS_MAX_KEY_SIZE)
6939c4a7965SKim Phillips 		goto badkey;
6949c4a7965SKim Phillips 
695c306a98dSMathias Krause 	memcpy(ctx->key, keys.authkey, keys.authkeylen);
696c306a98dSMathias Krause 	memcpy(&ctx->key[keys.authkeylen], keys.enckey, keys.enckeylen);
6979c4a7965SKim Phillips 
698c306a98dSMathias Krause 	ctx->keylen = keys.authkeylen + keys.enckeylen;
699c306a98dSMathias Krause 	ctx->enckeylen = keys.enckeylen;
700c306a98dSMathias Krause 	ctx->authkeylen = keys.authkeylen;
7019c4a7965SKim Phillips 
7029c4a7965SKim Phillips 	return 0;
7039c4a7965SKim Phillips 
7049c4a7965SKim Phillips badkey:
7059c4a7965SKim Phillips 	crypto_aead_set_flags(authenc, CRYPTO_TFM_RES_BAD_KEY_LEN);
7069c4a7965SKim Phillips 	return -EINVAL;
7079c4a7965SKim Phillips }
7089c4a7965SKim Phillips 
7099c4a7965SKim Phillips /*
71056af8cd4SLee Nipper  * talitos_edesc - s/w-extended descriptor
71179fd31d3SHoria Geanta  * @assoc_nents: number of segments in associated data scatterlist
7129c4a7965SKim Phillips  * @src_nents: number of segments in input scatterlist
7139c4a7965SKim Phillips  * @dst_nents: number of segments in output scatterlist
71479fd31d3SHoria Geanta  * @assoc_chained: whether assoc is chained or not
7152a1cfe46SHoria Geanta  * @src_chained: whether src is chained or not
7162a1cfe46SHoria Geanta  * @dst_chained: whether dst is chained or not
71779fd31d3SHoria Geanta  * @iv_dma: dma address of iv for checking continuity and link table
7189c4a7965SKim Phillips  * @dma_len: length of dma mapped link_tbl space
7199c4a7965SKim Phillips  * @dma_link_tbl: bus physical address of link_tbl
7209c4a7965SKim Phillips  * @desc: h/w descriptor
7219c4a7965SKim Phillips  * @link_tbl: input and output h/w link tables (if {src,dst}_nents > 1)
7229c4a7965SKim Phillips  *
7239c4a7965SKim Phillips  * if decrypting (with authcheck), or either one of src_nents or dst_nents
7249c4a7965SKim Phillips  * is greater than 1, an integrity check value is concatenated to the end
7259c4a7965SKim Phillips  * of link_tbl data
7269c4a7965SKim Phillips  */
72756af8cd4SLee Nipper struct talitos_edesc {
72879fd31d3SHoria Geanta 	int assoc_nents;
7299c4a7965SKim Phillips 	int src_nents;
7309c4a7965SKim Phillips 	int dst_nents;
73179fd31d3SHoria Geanta 	bool assoc_chained;
7322a1cfe46SHoria Geanta 	bool src_chained;
7332a1cfe46SHoria Geanta 	bool dst_chained;
73479fd31d3SHoria Geanta 	dma_addr_t iv_dma;
7359c4a7965SKim Phillips 	int dma_len;
7369c4a7965SKim Phillips 	dma_addr_t dma_link_tbl;
7379c4a7965SKim Phillips 	struct talitos_desc desc;
7389c4a7965SKim Phillips 	struct talitos_ptr link_tbl[0];
7399c4a7965SKim Phillips };
7409c4a7965SKim Phillips 
7414de9d0b5SLee Nipper static int talitos_map_sg(struct device *dev, struct scatterlist *sg,
7424de9d0b5SLee Nipper 			  unsigned int nents, enum dma_data_direction dir,
7432a1cfe46SHoria Geanta 			  bool chained)
7444de9d0b5SLee Nipper {
7454de9d0b5SLee Nipper 	if (unlikely(chained))
7464de9d0b5SLee Nipper 		while (sg) {
7474de9d0b5SLee Nipper 			dma_map_sg(dev, sg, 1, dir);
7485be4d4c9SCristian Stoica 			sg = sg_next(sg);
7494de9d0b5SLee Nipper 		}
7504de9d0b5SLee Nipper 	else
7514de9d0b5SLee Nipper 		dma_map_sg(dev, sg, nents, dir);
7524de9d0b5SLee Nipper 	return nents;
7534de9d0b5SLee Nipper }
7544de9d0b5SLee Nipper 
7554de9d0b5SLee Nipper static void talitos_unmap_sg_chain(struct device *dev, struct scatterlist *sg,
7564de9d0b5SLee Nipper 				   enum dma_data_direction dir)
7574de9d0b5SLee Nipper {
7584de9d0b5SLee Nipper 	while (sg) {
7594de9d0b5SLee Nipper 		dma_unmap_sg(dev, sg, 1, dir);
7605be4d4c9SCristian Stoica 		sg = sg_next(sg);
7614de9d0b5SLee Nipper 	}
7624de9d0b5SLee Nipper }
7634de9d0b5SLee Nipper 
7644de9d0b5SLee Nipper static void talitos_sg_unmap(struct device *dev,
7654de9d0b5SLee Nipper 			     struct talitos_edesc *edesc,
7664de9d0b5SLee Nipper 			     struct scatterlist *src,
7674de9d0b5SLee Nipper 			     struct scatterlist *dst)
7684de9d0b5SLee Nipper {
7694de9d0b5SLee Nipper 	unsigned int src_nents = edesc->src_nents ? : 1;
7704de9d0b5SLee Nipper 	unsigned int dst_nents = edesc->dst_nents ? : 1;
7714de9d0b5SLee Nipper 
7724de9d0b5SLee Nipper 	if (src != dst) {
7732a1cfe46SHoria Geanta 		if (edesc->src_chained)
7744de9d0b5SLee Nipper 			talitos_unmap_sg_chain(dev, src, DMA_TO_DEVICE);
7754de9d0b5SLee Nipper 		else
7764de9d0b5SLee Nipper 			dma_unmap_sg(dev, src, src_nents, DMA_TO_DEVICE);
7774de9d0b5SLee Nipper 
778497f2e6bSLee Nipper 		if (dst) {
7792a1cfe46SHoria Geanta 			if (edesc->dst_chained)
780497f2e6bSLee Nipper 				talitos_unmap_sg_chain(dev, dst,
781497f2e6bSLee Nipper 						       DMA_FROM_DEVICE);
7824de9d0b5SLee Nipper 			else
783497f2e6bSLee Nipper 				dma_unmap_sg(dev, dst, dst_nents,
784497f2e6bSLee Nipper 					     DMA_FROM_DEVICE);
785497f2e6bSLee Nipper 		}
7864de9d0b5SLee Nipper 	} else
7872a1cfe46SHoria Geanta 		if (edesc->src_chained)
7884de9d0b5SLee Nipper 			talitos_unmap_sg_chain(dev, src, DMA_BIDIRECTIONAL);
7894de9d0b5SLee Nipper 		else
7904de9d0b5SLee Nipper 			dma_unmap_sg(dev, src, src_nents, DMA_BIDIRECTIONAL);
7914de9d0b5SLee Nipper }
7924de9d0b5SLee Nipper 
7939c4a7965SKim Phillips static void ipsec_esp_unmap(struct device *dev,
79456af8cd4SLee Nipper 			    struct talitos_edesc *edesc,
7959c4a7965SKim Phillips 			    struct aead_request *areq)
7969c4a7965SKim Phillips {
7979c4a7965SKim Phillips 	unmap_single_talitos_ptr(dev, &edesc->desc.ptr[6], DMA_FROM_DEVICE);
7989c4a7965SKim Phillips 	unmap_single_talitos_ptr(dev, &edesc->desc.ptr[3], DMA_TO_DEVICE);
7999c4a7965SKim Phillips 	unmap_single_talitos_ptr(dev, &edesc->desc.ptr[2], DMA_TO_DEVICE);
8009c4a7965SKim Phillips 	unmap_single_talitos_ptr(dev, &edesc->desc.ptr[0], DMA_TO_DEVICE);
8019c4a7965SKim Phillips 
80279fd31d3SHoria Geanta 	if (edesc->assoc_chained)
80379fd31d3SHoria Geanta 		talitos_unmap_sg_chain(dev, areq->assoc, DMA_TO_DEVICE);
804935e99a3SHoria Geanta 	else if (areq->assoclen)
80579fd31d3SHoria Geanta 		/* assoc_nents counts also for IV in non-contiguous cases */
80679fd31d3SHoria Geanta 		dma_unmap_sg(dev, areq->assoc,
80779fd31d3SHoria Geanta 			     edesc->assoc_nents ? edesc->assoc_nents - 1 : 1,
80879fd31d3SHoria Geanta 			     DMA_TO_DEVICE);
8099c4a7965SKim Phillips 
8104de9d0b5SLee Nipper 	talitos_sg_unmap(dev, edesc, areq->src, areq->dst);
8119c4a7965SKim Phillips 
8129c4a7965SKim Phillips 	if (edesc->dma_len)
8139c4a7965SKim Phillips 		dma_unmap_single(dev, edesc->dma_link_tbl, edesc->dma_len,
8149c4a7965SKim Phillips 				 DMA_BIDIRECTIONAL);
8159c4a7965SKim Phillips }
8169c4a7965SKim Phillips 
8179c4a7965SKim Phillips /*
8189c4a7965SKim Phillips  * ipsec_esp descriptor callbacks
8199c4a7965SKim Phillips  */
8209c4a7965SKim Phillips static void ipsec_esp_encrypt_done(struct device *dev,
8219c4a7965SKim Phillips 				   struct talitos_desc *desc, void *context,
8229c4a7965SKim Phillips 				   int err)
8239c4a7965SKim Phillips {
8249c4a7965SKim Phillips 	struct aead_request *areq = context;
8259c4a7965SKim Phillips 	struct crypto_aead *authenc = crypto_aead_reqtfm(areq);
8269c4a7965SKim Phillips 	struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
82719bbbc63SKim Phillips 	struct talitos_edesc *edesc;
8289c4a7965SKim Phillips 	struct scatterlist *sg;
8299c4a7965SKim Phillips 	void *icvdata;
8309c4a7965SKim Phillips 
83119bbbc63SKim Phillips 	edesc = container_of(desc, struct talitos_edesc, desc);
83219bbbc63SKim Phillips 
8339c4a7965SKim Phillips 	ipsec_esp_unmap(dev, edesc, areq);
8349c4a7965SKim Phillips 
8359c4a7965SKim Phillips 	/* copy the generated ICV to dst */
83660542505SHoria Geanta 	if (edesc->dst_nents) {
8379c4a7965SKim Phillips 		icvdata = &edesc->link_tbl[edesc->src_nents +
83879fd31d3SHoria Geanta 					   edesc->dst_nents + 2 +
83979fd31d3SHoria Geanta 					   edesc->assoc_nents];
8409c4a7965SKim Phillips 		sg = sg_last(areq->dst, edesc->dst_nents);
8419c4a7965SKim Phillips 		memcpy((char *)sg_virt(sg) + sg->length - ctx->authsize,
8429c4a7965SKim Phillips 		       icvdata, ctx->authsize);
8439c4a7965SKim Phillips 	}
8449c4a7965SKim Phillips 
8459c4a7965SKim Phillips 	kfree(edesc);
8469c4a7965SKim Phillips 
8479c4a7965SKim Phillips 	aead_request_complete(areq, err);
8489c4a7965SKim Phillips }
8499c4a7965SKim Phillips 
850fe5720e2SKim Phillips static void ipsec_esp_decrypt_swauth_done(struct device *dev,
851e938e465SKim Phillips 					  struct talitos_desc *desc,
852e938e465SKim Phillips 					  void *context, int err)
8539c4a7965SKim Phillips {
8549c4a7965SKim Phillips 	struct aead_request *req = context;
8559c4a7965SKim Phillips 	struct crypto_aead *authenc = crypto_aead_reqtfm(req);
8569c4a7965SKim Phillips 	struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
85719bbbc63SKim Phillips 	struct talitos_edesc *edesc;
8589c4a7965SKim Phillips 	struct scatterlist *sg;
8599c4a7965SKim Phillips 	void *icvdata;
8609c4a7965SKim Phillips 
86119bbbc63SKim Phillips 	edesc = container_of(desc, struct talitos_edesc, desc);
86219bbbc63SKim Phillips 
8639c4a7965SKim Phillips 	ipsec_esp_unmap(dev, edesc, req);
8649c4a7965SKim Phillips 
8659c4a7965SKim Phillips 	if (!err) {
8669c4a7965SKim Phillips 		/* auth check */
8679c4a7965SKim Phillips 		if (edesc->dma_len)
8689c4a7965SKim Phillips 			icvdata = &edesc->link_tbl[edesc->src_nents +
86979fd31d3SHoria Geanta 						   edesc->dst_nents + 2 +
87079fd31d3SHoria Geanta 						   edesc->assoc_nents];
8719c4a7965SKim Phillips 		else
8729c4a7965SKim Phillips 			icvdata = &edesc->link_tbl[0];
8739c4a7965SKim Phillips 
8749c4a7965SKim Phillips 		sg = sg_last(req->dst, edesc->dst_nents ? : 1);
8759c4a7965SKim Phillips 		err = memcmp(icvdata, (char *)sg_virt(sg) + sg->length -
8769c4a7965SKim Phillips 			     ctx->authsize, ctx->authsize) ? -EBADMSG : 0;
8779c4a7965SKim Phillips 	}
8789c4a7965SKim Phillips 
8799c4a7965SKim Phillips 	kfree(edesc);
8809c4a7965SKim Phillips 
8819c4a7965SKim Phillips 	aead_request_complete(req, err);
8829c4a7965SKim Phillips }
8839c4a7965SKim Phillips 
884fe5720e2SKim Phillips static void ipsec_esp_decrypt_hwauth_done(struct device *dev,
885e938e465SKim Phillips 					  struct talitos_desc *desc,
886e938e465SKim Phillips 					  void *context, int err)
887fe5720e2SKim Phillips {
888fe5720e2SKim Phillips 	struct aead_request *req = context;
88919bbbc63SKim Phillips 	struct talitos_edesc *edesc;
89019bbbc63SKim Phillips 
89119bbbc63SKim Phillips 	edesc = container_of(desc, struct talitos_edesc, desc);
892fe5720e2SKim Phillips 
893fe5720e2SKim Phillips 	ipsec_esp_unmap(dev, edesc, req);
894fe5720e2SKim Phillips 
895fe5720e2SKim Phillips 	/* check ICV auth status */
896e938e465SKim Phillips 	if (!err && ((desc->hdr_lo & DESC_HDR_LO_ICCR1_MASK) !=
897e938e465SKim Phillips 		     DESC_HDR_LO_ICCR1_PASS))
898fe5720e2SKim Phillips 		err = -EBADMSG;
899fe5720e2SKim Phillips 
900fe5720e2SKim Phillips 	kfree(edesc);
901fe5720e2SKim Phillips 
902fe5720e2SKim Phillips 	aead_request_complete(req, err);
903fe5720e2SKim Phillips }
904fe5720e2SKim Phillips 
9059c4a7965SKim Phillips /*
9069c4a7965SKim Phillips  * convert scatterlist to SEC h/w link table format
9079c4a7965SKim Phillips  * stop at cryptlen bytes
9089c4a7965SKim Phillips  */
90970bcaca7SLee Nipper static int sg_to_link_tbl(struct scatterlist *sg, int sg_count,
9109c4a7965SKim Phillips 			   int cryptlen, struct talitos_ptr *link_tbl_ptr)
9119c4a7965SKim Phillips {
91270bcaca7SLee Nipper 	int n_sg = sg_count;
91370bcaca7SLee Nipper 
91470bcaca7SLee Nipper 	while (n_sg--) {
91581eb024cSKim Phillips 		to_talitos_ptr(link_tbl_ptr, sg_dma_address(sg));
9169c4a7965SKim Phillips 		link_tbl_ptr->len = cpu_to_be16(sg_dma_len(sg));
9179c4a7965SKim Phillips 		link_tbl_ptr->j_extent = 0;
9189c4a7965SKim Phillips 		link_tbl_ptr++;
9199c4a7965SKim Phillips 		cryptlen -= sg_dma_len(sg);
9205be4d4c9SCristian Stoica 		sg = sg_next(sg);
9219c4a7965SKim Phillips 	}
9229c4a7965SKim Phillips 
92370bcaca7SLee Nipper 	/* adjust (decrease) last one (or two) entry's len to cryptlen */
9249c4a7965SKim Phillips 	link_tbl_ptr--;
925c0e741d4SKim Phillips 	while (be16_to_cpu(link_tbl_ptr->len) <= (-cryptlen)) {
92670bcaca7SLee Nipper 		/* Empty this entry, and move to previous one */
92770bcaca7SLee Nipper 		cryptlen += be16_to_cpu(link_tbl_ptr->len);
92870bcaca7SLee Nipper 		link_tbl_ptr->len = 0;
92970bcaca7SLee Nipper 		sg_count--;
93070bcaca7SLee Nipper 		link_tbl_ptr--;
93170bcaca7SLee Nipper 	}
9327291a932SWei Yongjun 	be16_add_cpu(&link_tbl_ptr->len, cryptlen);
9339c4a7965SKim Phillips 
9349c4a7965SKim Phillips 	/* tag end of link table */
9359c4a7965SKim Phillips 	link_tbl_ptr->j_extent = DESC_PTR_LNKTBL_RETURN;
93670bcaca7SLee Nipper 
93770bcaca7SLee Nipper 	return sg_count;
9389c4a7965SKim Phillips }
9399c4a7965SKim Phillips 
9409c4a7965SKim Phillips /*
9419c4a7965SKim Phillips  * fill in and submit ipsec_esp descriptor
9429c4a7965SKim Phillips  */
94356af8cd4SLee Nipper static int ipsec_esp(struct talitos_edesc *edesc, struct aead_request *areq,
94479fd31d3SHoria Geanta 		     u64 seq, void (*callback) (struct device *dev,
9459c4a7965SKim Phillips 						struct talitos_desc *desc,
9469c4a7965SKim Phillips 						void *context, int error))
9479c4a7965SKim Phillips {
9489c4a7965SKim Phillips 	struct crypto_aead *aead = crypto_aead_reqtfm(areq);
9499c4a7965SKim Phillips 	struct talitos_ctx *ctx = crypto_aead_ctx(aead);
9509c4a7965SKim Phillips 	struct device *dev = ctx->dev;
9519c4a7965SKim Phillips 	struct talitos_desc *desc = &edesc->desc;
9529c4a7965SKim Phillips 	unsigned int cryptlen = areq->cryptlen;
9539c4a7965SKim Phillips 	unsigned int authsize = ctx->authsize;
954e41256f1SKim Phillips 	unsigned int ivsize = crypto_aead_ivsize(aead);
955fa86a267SKim Phillips 	int sg_count, ret;
956fe5720e2SKim Phillips 	int sg_link_tbl_len;
9579c4a7965SKim Phillips 
9589c4a7965SKim Phillips 	/* hmac key */
9599c4a7965SKim Phillips 	map_single_talitos_ptr(dev, &desc->ptr[0], ctx->authkeylen, &ctx->key,
960*a2b35aa8SLEROY Christophe 			       DMA_TO_DEVICE);
96179fd31d3SHoria Geanta 
9629c4a7965SKim Phillips 	/* hmac data */
96379fd31d3SHoria Geanta 	desc->ptr[1].len = cpu_to_be16(areq->assoclen + ivsize);
96479fd31d3SHoria Geanta 	if (edesc->assoc_nents) {
96579fd31d3SHoria Geanta 		int tbl_off = edesc->src_nents + edesc->dst_nents + 2;
96679fd31d3SHoria Geanta 		struct talitos_ptr *tbl_ptr = &edesc->link_tbl[tbl_off];
96779fd31d3SHoria Geanta 
96879fd31d3SHoria Geanta 		to_talitos_ptr(&desc->ptr[1], edesc->dma_link_tbl + tbl_off *
96979fd31d3SHoria Geanta 			       sizeof(struct talitos_ptr));
97079fd31d3SHoria Geanta 		desc->ptr[1].j_extent = DESC_PTR_LNKTBL_JUMP;
97179fd31d3SHoria Geanta 
97279fd31d3SHoria Geanta 		/* assoc_nents - 1 entries for assoc, 1 for IV */
97379fd31d3SHoria Geanta 		sg_count = sg_to_link_tbl(areq->assoc, edesc->assoc_nents - 1,
97479fd31d3SHoria Geanta 					  areq->assoclen, tbl_ptr);
97579fd31d3SHoria Geanta 
97679fd31d3SHoria Geanta 		/* add IV to link table */
97779fd31d3SHoria Geanta 		tbl_ptr += sg_count - 1;
97879fd31d3SHoria Geanta 		tbl_ptr->j_extent = 0;
97979fd31d3SHoria Geanta 		tbl_ptr++;
98079fd31d3SHoria Geanta 		to_talitos_ptr(tbl_ptr, edesc->iv_dma);
98179fd31d3SHoria Geanta 		tbl_ptr->len = cpu_to_be16(ivsize);
98279fd31d3SHoria Geanta 		tbl_ptr->j_extent = DESC_PTR_LNKTBL_RETURN;
98379fd31d3SHoria Geanta 
98479fd31d3SHoria Geanta 		dma_sync_single_for_device(dev, edesc->dma_link_tbl,
98579fd31d3SHoria Geanta 					   edesc->dma_len, DMA_BIDIRECTIONAL);
98679fd31d3SHoria Geanta 	} else {
987935e99a3SHoria Geanta 		if (areq->assoclen)
988935e99a3SHoria Geanta 			to_talitos_ptr(&desc->ptr[1],
989935e99a3SHoria Geanta 				       sg_dma_address(areq->assoc));
990935e99a3SHoria Geanta 		else
991935e99a3SHoria Geanta 			to_talitos_ptr(&desc->ptr[1], edesc->iv_dma);
99279fd31d3SHoria Geanta 		desc->ptr[1].j_extent = 0;
99379fd31d3SHoria Geanta 	}
99479fd31d3SHoria Geanta 
9959c4a7965SKim Phillips 	/* cipher iv */
99679fd31d3SHoria Geanta 	to_talitos_ptr(&desc->ptr[2], edesc->iv_dma);
99779fd31d3SHoria Geanta 	desc->ptr[2].len = cpu_to_be16(ivsize);
99879fd31d3SHoria Geanta 	desc->ptr[2].j_extent = 0;
99979fd31d3SHoria Geanta 	/* Sync needed for the aead_givencrypt case */
100079fd31d3SHoria Geanta 	dma_sync_single_for_device(dev, edesc->iv_dma, ivsize, DMA_TO_DEVICE);
10019c4a7965SKim Phillips 
10029c4a7965SKim Phillips 	/* cipher key */
10039c4a7965SKim Phillips 	map_single_talitos_ptr(dev, &desc->ptr[3], ctx->enckeylen,
1004*a2b35aa8SLEROY Christophe 			       (char *)&ctx->key + ctx->authkeylen,
10059c4a7965SKim Phillips 			       DMA_TO_DEVICE);
10069c4a7965SKim Phillips 
10079c4a7965SKim Phillips 	/*
10089c4a7965SKim Phillips 	 * cipher in
10099c4a7965SKim Phillips 	 * map and adjust cipher len to aead request cryptlen.
10109c4a7965SKim Phillips 	 * extent is bytes of HMAC postpended to ciphertext,
10119c4a7965SKim Phillips 	 * typically 12 for ipsec
10129c4a7965SKim Phillips 	 */
10139c4a7965SKim Phillips 	desc->ptr[4].len = cpu_to_be16(cryptlen);
10149c4a7965SKim Phillips 	desc->ptr[4].j_extent = authsize;
10159c4a7965SKim Phillips 
1016e938e465SKim Phillips 	sg_count = talitos_map_sg(dev, areq->src, edesc->src_nents ? : 1,
1017e938e465SKim Phillips 				  (areq->src == areq->dst) ? DMA_BIDIRECTIONAL
1018e938e465SKim Phillips 							   : DMA_TO_DEVICE,
10192a1cfe46SHoria Geanta 				  edesc->src_chained);
10209c4a7965SKim Phillips 
10219c4a7965SKim Phillips 	if (sg_count == 1) {
102281eb024cSKim Phillips 		to_talitos_ptr(&desc->ptr[4], sg_dma_address(areq->src));
10239c4a7965SKim Phillips 	} else {
1024fe5720e2SKim Phillips 		sg_link_tbl_len = cryptlen;
1025fe5720e2SKim Phillips 
1026962a9c99SKim Phillips 		if (edesc->desc.hdr & DESC_HDR_MODE1_MDEU_CICV)
1027fe5720e2SKim Phillips 			sg_link_tbl_len = cryptlen + authsize;
1028e938e465SKim Phillips 
1029fe5720e2SKim Phillips 		sg_count = sg_to_link_tbl(areq->src, sg_count, sg_link_tbl_len,
10309c4a7965SKim Phillips 					  &edesc->link_tbl[0]);
103170bcaca7SLee Nipper 		if (sg_count > 1) {
10329c4a7965SKim Phillips 			desc->ptr[4].j_extent |= DESC_PTR_LNKTBL_JUMP;
103381eb024cSKim Phillips 			to_talitos_ptr(&desc->ptr[4], edesc->dma_link_tbl);
1034e938e465SKim Phillips 			dma_sync_single_for_device(dev, edesc->dma_link_tbl,
1035e938e465SKim Phillips 						   edesc->dma_len,
1036e938e465SKim Phillips 						   DMA_BIDIRECTIONAL);
103770bcaca7SLee Nipper 		} else {
103870bcaca7SLee Nipper 			/* Only one segment now, so no link tbl needed */
103981eb024cSKim Phillips 			to_talitos_ptr(&desc->ptr[4],
104081eb024cSKim Phillips 				       sg_dma_address(areq->src));
104170bcaca7SLee Nipper 		}
10429c4a7965SKim Phillips 	}
10439c4a7965SKim Phillips 
10449c4a7965SKim Phillips 	/* cipher out */
10459c4a7965SKim Phillips 	desc->ptr[5].len = cpu_to_be16(cryptlen);
10469c4a7965SKim Phillips 	desc->ptr[5].j_extent = authsize;
10479c4a7965SKim Phillips 
1048e938e465SKim Phillips 	if (areq->src != areq->dst)
10494de9d0b5SLee Nipper 		sg_count = talitos_map_sg(dev, areq->dst,
10504de9d0b5SLee Nipper 					  edesc->dst_nents ? : 1,
10512a1cfe46SHoria Geanta 					  DMA_FROM_DEVICE, edesc->dst_chained);
10529c4a7965SKim Phillips 
10539c4a7965SKim Phillips 	if (sg_count == 1) {
105481eb024cSKim Phillips 		to_talitos_ptr(&desc->ptr[5], sg_dma_address(areq->dst));
10559c4a7965SKim Phillips 	} else {
105679fd31d3SHoria Geanta 		int tbl_off = edesc->src_nents + 1;
105779fd31d3SHoria Geanta 		struct talitos_ptr *tbl_ptr = &edesc->link_tbl[tbl_off];
10589c4a7965SKim Phillips 
105981eb024cSKim Phillips 		to_talitos_ptr(&desc->ptr[5], edesc->dma_link_tbl +
106079fd31d3SHoria Geanta 			       tbl_off * sizeof(struct talitos_ptr));
106170bcaca7SLee Nipper 		sg_count = sg_to_link_tbl(areq->dst, sg_count, cryptlen,
106279fd31d3SHoria Geanta 					  tbl_ptr);
1063fe5720e2SKim Phillips 
1064f3c85bc1SLee Nipper 		/* Add an entry to the link table for ICV data */
106579fd31d3SHoria Geanta 		tbl_ptr += sg_count - 1;
106679fd31d3SHoria Geanta 		tbl_ptr->j_extent = 0;
106779fd31d3SHoria Geanta 		tbl_ptr++;
106879fd31d3SHoria Geanta 		tbl_ptr->j_extent = DESC_PTR_LNKTBL_RETURN;
106979fd31d3SHoria Geanta 		tbl_ptr->len = cpu_to_be16(authsize);
10709c4a7965SKim Phillips 
10719c4a7965SKim Phillips 		/* icv data follows link tables */
107279fd31d3SHoria Geanta 		to_talitos_ptr(tbl_ptr, edesc->dma_link_tbl +
107379fd31d3SHoria Geanta 			       (tbl_off + edesc->dst_nents + 1 +
107479fd31d3SHoria Geanta 				edesc->assoc_nents) *
107581eb024cSKim Phillips 			       sizeof(struct talitos_ptr));
10769c4a7965SKim Phillips 		desc->ptr[5].j_extent |= DESC_PTR_LNKTBL_JUMP;
10779c4a7965SKim Phillips 		dma_sync_single_for_device(ctx->dev, edesc->dma_link_tbl,
10789c4a7965SKim Phillips 					   edesc->dma_len, DMA_BIDIRECTIONAL);
10799c4a7965SKim Phillips 	}
10809c4a7965SKim Phillips 
10819c4a7965SKim Phillips 	/* iv out */
1082*a2b35aa8SLEROY Christophe 	map_single_talitos_ptr(dev, &desc->ptr[6], ivsize, ctx->iv,
10839c4a7965SKim Phillips 			       DMA_FROM_DEVICE);
10849c4a7965SKim Phillips 
10855228f0f7SKim Phillips 	ret = talitos_submit(dev, ctx->ch, desc, callback, areq);
1086fa86a267SKim Phillips 	if (ret != -EINPROGRESS) {
1087fa86a267SKim Phillips 		ipsec_esp_unmap(dev, edesc, areq);
1088fa86a267SKim Phillips 		kfree(edesc);
1089fa86a267SKim Phillips 	}
1090fa86a267SKim Phillips 	return ret;
10919c4a7965SKim Phillips }
10929c4a7965SKim Phillips 
10939c4a7965SKim Phillips /*
10949c4a7965SKim Phillips  * derive number of elements in scatterlist
10959c4a7965SKim Phillips  */
10962a1cfe46SHoria Geanta static int sg_count(struct scatterlist *sg_list, int nbytes, bool *chained)
10979c4a7965SKim Phillips {
10989c4a7965SKim Phillips 	struct scatterlist *sg = sg_list;
10999c4a7965SKim Phillips 	int sg_nents = 0;
11009c4a7965SKim Phillips 
11012a1cfe46SHoria Geanta 	*chained = false;
11024de9d0b5SLee Nipper 	while (nbytes > 0) {
11039c4a7965SKim Phillips 		sg_nents++;
11049c4a7965SKim Phillips 		nbytes -= sg->length;
11054de9d0b5SLee Nipper 		if (!sg_is_last(sg) && (sg + 1)->length == 0)
11062a1cfe46SHoria Geanta 			*chained = true;
11075be4d4c9SCristian Stoica 		sg = sg_next(sg);
11089c4a7965SKim Phillips 	}
11099c4a7965SKim Phillips 
11109c4a7965SKim Phillips 	return sg_nents;
11119c4a7965SKim Phillips }
11129c4a7965SKim Phillips 
11139c4a7965SKim Phillips /*
111456af8cd4SLee Nipper  * allocate and map the extended descriptor
11159c4a7965SKim Phillips  */
11164de9d0b5SLee Nipper static struct talitos_edesc *talitos_edesc_alloc(struct device *dev,
111779fd31d3SHoria Geanta 						 struct scatterlist *assoc,
11184de9d0b5SLee Nipper 						 struct scatterlist *src,
11194de9d0b5SLee Nipper 						 struct scatterlist *dst,
112079fd31d3SHoria Geanta 						 u8 *iv,
112179fd31d3SHoria Geanta 						 unsigned int assoclen,
11224de9d0b5SLee Nipper 						 unsigned int cryptlen,
11234de9d0b5SLee Nipper 						 unsigned int authsize,
112479fd31d3SHoria Geanta 						 unsigned int ivsize,
11254de9d0b5SLee Nipper 						 int icv_stashing,
112662293a37SHoria Geanta 						 u32 cryptoflags,
112762293a37SHoria Geanta 						 bool encrypt)
11289c4a7965SKim Phillips {
112956af8cd4SLee Nipper 	struct talitos_edesc *edesc;
113079fd31d3SHoria Geanta 	int assoc_nents = 0, src_nents, dst_nents, alloc_len, dma_len;
113179fd31d3SHoria Geanta 	bool assoc_chained = false, src_chained = false, dst_chained = false;
113279fd31d3SHoria Geanta 	dma_addr_t iv_dma = 0;
11334de9d0b5SLee Nipper 	gfp_t flags = cryptoflags & CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL :
1134586725f8SKim Phillips 		      GFP_ATOMIC;
11359c4a7965SKim Phillips 
11364de9d0b5SLee Nipper 	if (cryptlen + authsize > TALITOS_MAX_DATA_LEN) {
11374de9d0b5SLee Nipper 		dev_err(dev, "length exceeds h/w max limit\n");
11389c4a7965SKim Phillips 		return ERR_PTR(-EINVAL);
11399c4a7965SKim Phillips 	}
11409c4a7965SKim Phillips 
1141935e99a3SHoria Geanta 	if (ivsize)
114279fd31d3SHoria Geanta 		iv_dma = dma_map_single(dev, iv, ivsize, DMA_TO_DEVICE);
114379fd31d3SHoria Geanta 
1144935e99a3SHoria Geanta 	if (assoclen) {
114579fd31d3SHoria Geanta 		/*
114679fd31d3SHoria Geanta 		 * Currently it is assumed that iv is provided whenever assoc
114779fd31d3SHoria Geanta 		 * is.
114879fd31d3SHoria Geanta 		 */
114979fd31d3SHoria Geanta 		BUG_ON(!iv);
115079fd31d3SHoria Geanta 
115179fd31d3SHoria Geanta 		assoc_nents = sg_count(assoc, assoclen, &assoc_chained);
115279fd31d3SHoria Geanta 		talitos_map_sg(dev, assoc, assoc_nents, DMA_TO_DEVICE,
115379fd31d3SHoria Geanta 			       assoc_chained);
115479fd31d3SHoria Geanta 		assoc_nents = (assoc_nents == 1) ? 0 : assoc_nents;
115579fd31d3SHoria Geanta 
115679fd31d3SHoria Geanta 		if (assoc_nents || sg_dma_address(assoc) + assoclen != iv_dma)
115779fd31d3SHoria Geanta 			assoc_nents = assoc_nents ? assoc_nents + 1 : 2;
115879fd31d3SHoria Geanta 	}
115979fd31d3SHoria Geanta 
116062293a37SHoria Geanta 	if (!dst || dst == src) {
11614de9d0b5SLee Nipper 		src_nents = sg_count(src, cryptlen + authsize, &src_chained);
11629c4a7965SKim Phillips 		src_nents = (src_nents == 1) ? 0 : src_nents;
116362293a37SHoria Geanta 		dst_nents = dst ? src_nents : 0;
116462293a37SHoria Geanta 	} else { /* dst && dst != src*/
116562293a37SHoria Geanta 		src_nents = sg_count(src, cryptlen + (encrypt ? 0 : authsize),
116662293a37SHoria Geanta 				     &src_chained);
116762293a37SHoria Geanta 		src_nents = (src_nents == 1) ? 0 : src_nents;
116862293a37SHoria Geanta 		dst_nents = sg_count(dst, cryptlen + (encrypt ? authsize : 0),
1169497f2e6bSLee Nipper 				     &dst_chained);
1170695ad589SLee Nipper 		dst_nents = (dst_nents == 1) ? 0 : dst_nents;
11719c4a7965SKim Phillips 	}
11729c4a7965SKim Phillips 
11739c4a7965SKim Phillips 	/*
11749c4a7965SKim Phillips 	 * allocate space for base edesc plus the link tables,
1175f3c85bc1SLee Nipper 	 * allowing for two separate entries for ICV and generated ICV (+ 2),
11769c4a7965SKim Phillips 	 * and the ICV data itself
11779c4a7965SKim Phillips 	 */
117856af8cd4SLee Nipper 	alloc_len = sizeof(struct talitos_edesc);
117979fd31d3SHoria Geanta 	if (assoc_nents || src_nents || dst_nents) {
118079fd31d3SHoria Geanta 		dma_len = (src_nents + dst_nents + 2 + assoc_nents) *
11814de9d0b5SLee Nipper 			  sizeof(struct talitos_ptr) + authsize;
11829c4a7965SKim Phillips 		alloc_len += dma_len;
11839c4a7965SKim Phillips 	} else {
11849c4a7965SKim Phillips 		dma_len = 0;
11854de9d0b5SLee Nipper 		alloc_len += icv_stashing ? authsize : 0;
11869c4a7965SKim Phillips 	}
11879c4a7965SKim Phillips 
1188586725f8SKim Phillips 	edesc = kmalloc(alloc_len, GFP_DMA | flags);
11899c4a7965SKim Phillips 	if (!edesc) {
1190935e99a3SHoria Geanta 		if (assoc_chained)
119179fd31d3SHoria Geanta 			talitos_unmap_sg_chain(dev, assoc, DMA_TO_DEVICE);
1192935e99a3SHoria Geanta 		else if (assoclen)
1193935e99a3SHoria Geanta 			dma_unmap_sg(dev, assoc,
1194935e99a3SHoria Geanta 				     assoc_nents ? assoc_nents - 1 : 1,
1195935e99a3SHoria Geanta 				     DMA_TO_DEVICE);
1196935e99a3SHoria Geanta 
119779fd31d3SHoria Geanta 		if (iv_dma)
119879fd31d3SHoria Geanta 			dma_unmap_single(dev, iv_dma, ivsize, DMA_TO_DEVICE);
1199935e99a3SHoria Geanta 
12004de9d0b5SLee Nipper 		dev_err(dev, "could not allocate edescriptor\n");
12019c4a7965SKim Phillips 		return ERR_PTR(-ENOMEM);
12029c4a7965SKim Phillips 	}
12039c4a7965SKim Phillips 
120479fd31d3SHoria Geanta 	edesc->assoc_nents = assoc_nents;
12059c4a7965SKim Phillips 	edesc->src_nents = src_nents;
12069c4a7965SKim Phillips 	edesc->dst_nents = dst_nents;
120779fd31d3SHoria Geanta 	edesc->assoc_chained = assoc_chained;
12082a1cfe46SHoria Geanta 	edesc->src_chained = src_chained;
12092a1cfe46SHoria Geanta 	edesc->dst_chained = dst_chained;
121079fd31d3SHoria Geanta 	edesc->iv_dma = iv_dma;
12119c4a7965SKim Phillips 	edesc->dma_len = dma_len;
1212497f2e6bSLee Nipper 	if (dma_len)
12134de9d0b5SLee Nipper 		edesc->dma_link_tbl = dma_map_single(dev, &edesc->link_tbl[0],
1214497f2e6bSLee Nipper 						     edesc->dma_len,
1215497f2e6bSLee Nipper 						     DMA_BIDIRECTIONAL);
12169c4a7965SKim Phillips 
12179c4a7965SKim Phillips 	return edesc;
12189c4a7965SKim Phillips }
12199c4a7965SKim Phillips 
122079fd31d3SHoria Geanta static struct talitos_edesc *aead_edesc_alloc(struct aead_request *areq, u8 *iv,
122162293a37SHoria Geanta 					      int icv_stashing, bool encrypt)
12224de9d0b5SLee Nipper {
12234de9d0b5SLee Nipper 	struct crypto_aead *authenc = crypto_aead_reqtfm(areq);
12244de9d0b5SLee Nipper 	struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
122579fd31d3SHoria Geanta 	unsigned int ivsize = crypto_aead_ivsize(authenc);
12264de9d0b5SLee Nipper 
122779fd31d3SHoria Geanta 	return talitos_edesc_alloc(ctx->dev, areq->assoc, areq->src, areq->dst,
122879fd31d3SHoria Geanta 				   iv, areq->assoclen, areq->cryptlen,
122979fd31d3SHoria Geanta 				   ctx->authsize, ivsize, icv_stashing,
123062293a37SHoria Geanta 				   areq->base.flags, encrypt);
12314de9d0b5SLee Nipper }
12324de9d0b5SLee Nipper 
123356af8cd4SLee Nipper static int aead_encrypt(struct aead_request *req)
12349c4a7965SKim Phillips {
12359c4a7965SKim Phillips 	struct crypto_aead *authenc = crypto_aead_reqtfm(req);
12369c4a7965SKim Phillips 	struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
123756af8cd4SLee Nipper 	struct talitos_edesc *edesc;
12389c4a7965SKim Phillips 
12399c4a7965SKim Phillips 	/* allocate extended descriptor */
124062293a37SHoria Geanta 	edesc = aead_edesc_alloc(req, req->iv, 0, true);
12419c4a7965SKim Phillips 	if (IS_ERR(edesc))
12429c4a7965SKim Phillips 		return PTR_ERR(edesc);
12439c4a7965SKim Phillips 
12449c4a7965SKim Phillips 	/* set encrypt */
124570bcaca7SLee Nipper 	edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_MODE0_ENCRYPT;
12469c4a7965SKim Phillips 
124779fd31d3SHoria Geanta 	return ipsec_esp(edesc, req, 0, ipsec_esp_encrypt_done);
12489c4a7965SKim Phillips }
12499c4a7965SKim Phillips 
125056af8cd4SLee Nipper static int aead_decrypt(struct aead_request *req)
12519c4a7965SKim Phillips {
12529c4a7965SKim Phillips 	struct crypto_aead *authenc = crypto_aead_reqtfm(req);
12539c4a7965SKim Phillips 	struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
12549c4a7965SKim Phillips 	unsigned int authsize = ctx->authsize;
1255fe5720e2SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(ctx->dev);
125656af8cd4SLee Nipper 	struct talitos_edesc *edesc;
12579c4a7965SKim Phillips 	struct scatterlist *sg;
12589c4a7965SKim Phillips 	void *icvdata;
12599c4a7965SKim Phillips 
12609c4a7965SKim Phillips 	req->cryptlen -= authsize;
12619c4a7965SKim Phillips 
12629c4a7965SKim Phillips 	/* allocate extended descriptor */
126362293a37SHoria Geanta 	edesc = aead_edesc_alloc(req, req->iv, 1, false);
12649c4a7965SKim Phillips 	if (IS_ERR(edesc))
12659c4a7965SKim Phillips 		return PTR_ERR(edesc);
12669c4a7965SKim Phillips 
1267fe5720e2SKim Phillips 	if ((priv->features & TALITOS_FTR_HW_AUTH_CHECK) &&
1268e938e465SKim Phillips 	    ((!edesc->src_nents && !edesc->dst_nents) ||
1269e938e465SKim Phillips 	     priv->features & TALITOS_FTR_SRC_LINK_TBL_LEN_INCLUDES_EXTENT)) {
1270fe5720e2SKim Phillips 
1271fe5720e2SKim Phillips 		/* decrypt and check the ICV */
1272e938e465SKim Phillips 		edesc->desc.hdr = ctx->desc_hdr_template |
1273e938e465SKim Phillips 				  DESC_HDR_DIR_INBOUND |
1274fe5720e2SKim Phillips 				  DESC_HDR_MODE1_MDEU_CICV;
1275fe5720e2SKim Phillips 
1276fe5720e2SKim Phillips 		/* reset integrity check result bits */
1277fe5720e2SKim Phillips 		edesc->desc.hdr_lo = 0;
1278fe5720e2SKim Phillips 
127979fd31d3SHoria Geanta 		return ipsec_esp(edesc, req, 0, ipsec_esp_decrypt_hwauth_done);
1280e938e465SKim Phillips 	}
1281fe5720e2SKim Phillips 
1282fe5720e2SKim Phillips 	/* Have to check the ICV with software */
1283fe5720e2SKim Phillips 	edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_DIR_INBOUND;
1284fe5720e2SKim Phillips 
12859c4a7965SKim Phillips 	/* stash incoming ICV for later cmp with ICV generated by the h/w */
12869c4a7965SKim Phillips 	if (edesc->dma_len)
12879c4a7965SKim Phillips 		icvdata = &edesc->link_tbl[edesc->src_nents +
128879fd31d3SHoria Geanta 					   edesc->dst_nents + 2 +
128979fd31d3SHoria Geanta 					   edesc->assoc_nents];
12909c4a7965SKim Phillips 	else
12919c4a7965SKim Phillips 		icvdata = &edesc->link_tbl[0];
12929c4a7965SKim Phillips 
12939c4a7965SKim Phillips 	sg = sg_last(req->src, edesc->src_nents ? : 1);
12949c4a7965SKim Phillips 
12959c4a7965SKim Phillips 	memcpy(icvdata, (char *)sg_virt(sg) + sg->length - ctx->authsize,
12969c4a7965SKim Phillips 	       ctx->authsize);
12979c4a7965SKim Phillips 
129879fd31d3SHoria Geanta 	return ipsec_esp(edesc, req, 0, ipsec_esp_decrypt_swauth_done);
1299fe5720e2SKim Phillips }
13009c4a7965SKim Phillips 
130156af8cd4SLee Nipper static int aead_givencrypt(struct aead_givcrypt_request *req)
13029c4a7965SKim Phillips {
13039c4a7965SKim Phillips 	struct aead_request *areq = &req->areq;
13049c4a7965SKim Phillips 	struct crypto_aead *authenc = crypto_aead_reqtfm(areq);
13059c4a7965SKim Phillips 	struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
130656af8cd4SLee Nipper 	struct talitos_edesc *edesc;
13079c4a7965SKim Phillips 
13089c4a7965SKim Phillips 	/* allocate extended descriptor */
130962293a37SHoria Geanta 	edesc = aead_edesc_alloc(areq, req->giv, 0, true);
13109c4a7965SKim Phillips 	if (IS_ERR(edesc))
13119c4a7965SKim Phillips 		return PTR_ERR(edesc);
13129c4a7965SKim Phillips 
13139c4a7965SKim Phillips 	/* set encrypt */
131470bcaca7SLee Nipper 	edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_MODE0_ENCRYPT;
13159c4a7965SKim Phillips 
13169c4a7965SKim Phillips 	memcpy(req->giv, ctx->iv, crypto_aead_ivsize(authenc));
1317ba95487dSKim Phillips 	/* avoid consecutive packets going out with same IV */
1318ba95487dSKim Phillips 	*(__be64 *)req->giv ^= cpu_to_be64(req->seq);
13199c4a7965SKim Phillips 
132079fd31d3SHoria Geanta 	return ipsec_esp(edesc, areq, req->seq, ipsec_esp_encrypt_done);
13219c4a7965SKim Phillips }
13229c4a7965SKim Phillips 
13234de9d0b5SLee Nipper static int ablkcipher_setkey(struct crypto_ablkcipher *cipher,
13244de9d0b5SLee Nipper 			     const u8 *key, unsigned int keylen)
13254de9d0b5SLee Nipper {
13264de9d0b5SLee Nipper 	struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher);
13274de9d0b5SLee Nipper 
13284de9d0b5SLee Nipper 	memcpy(&ctx->key, key, keylen);
13294de9d0b5SLee Nipper 	ctx->keylen = keylen;
13304de9d0b5SLee Nipper 
13314de9d0b5SLee Nipper 	return 0;
13324de9d0b5SLee Nipper }
13334de9d0b5SLee Nipper 
1334032d197eSLEROY Christophe static void unmap_sg_talitos_ptr(struct device *dev, struct scatterlist *src,
1335032d197eSLEROY Christophe 				 struct scatterlist *dst, unsigned int len,
1336032d197eSLEROY Christophe 				 struct talitos_edesc *edesc)
1337032d197eSLEROY Christophe {
1338032d197eSLEROY Christophe 	talitos_sg_unmap(dev, edesc, src, dst);
1339032d197eSLEROY Christophe }
1340032d197eSLEROY Christophe 
13414de9d0b5SLee Nipper static void common_nonsnoop_unmap(struct device *dev,
13424de9d0b5SLee Nipper 				  struct talitos_edesc *edesc,
13434de9d0b5SLee Nipper 				  struct ablkcipher_request *areq)
13444de9d0b5SLee Nipper {
13454de9d0b5SLee Nipper 	unmap_single_talitos_ptr(dev, &edesc->desc.ptr[5], DMA_FROM_DEVICE);
1346032d197eSLEROY Christophe 
1347032d197eSLEROY Christophe 	unmap_sg_talitos_ptr(dev, areq->src, areq->dst, areq->nbytes, edesc);
13484de9d0b5SLee Nipper 	unmap_single_talitos_ptr(dev, &edesc->desc.ptr[2], DMA_TO_DEVICE);
13494de9d0b5SLee Nipper 	unmap_single_talitos_ptr(dev, &edesc->desc.ptr[1], DMA_TO_DEVICE);
13504de9d0b5SLee Nipper 
13514de9d0b5SLee Nipper 	if (edesc->dma_len)
13524de9d0b5SLee Nipper 		dma_unmap_single(dev, edesc->dma_link_tbl, edesc->dma_len,
13534de9d0b5SLee Nipper 				 DMA_BIDIRECTIONAL);
13544de9d0b5SLee Nipper }
13554de9d0b5SLee Nipper 
13564de9d0b5SLee Nipper static void ablkcipher_done(struct device *dev,
13574de9d0b5SLee Nipper 			    struct talitos_desc *desc, void *context,
13584de9d0b5SLee Nipper 			    int err)
13594de9d0b5SLee Nipper {
13604de9d0b5SLee Nipper 	struct ablkcipher_request *areq = context;
136119bbbc63SKim Phillips 	struct talitos_edesc *edesc;
136219bbbc63SKim Phillips 
136319bbbc63SKim Phillips 	edesc = container_of(desc, struct talitos_edesc, desc);
13644de9d0b5SLee Nipper 
13654de9d0b5SLee Nipper 	common_nonsnoop_unmap(dev, edesc, areq);
13664de9d0b5SLee Nipper 
13674de9d0b5SLee Nipper 	kfree(edesc);
13684de9d0b5SLee Nipper 
13694de9d0b5SLee Nipper 	areq->base.complete(&areq->base, err);
13704de9d0b5SLee Nipper }
13714de9d0b5SLee Nipper 
1372032d197eSLEROY Christophe int map_sg_in_talitos_ptr(struct device *dev, struct scatterlist *src,
1373032d197eSLEROY Christophe 			  unsigned int len, struct talitos_edesc *edesc,
1374032d197eSLEROY Christophe 			  enum dma_data_direction dir, struct talitos_ptr *ptr)
1375032d197eSLEROY Christophe {
1376032d197eSLEROY Christophe 	int sg_count;
1377032d197eSLEROY Christophe 
1378032d197eSLEROY Christophe 	ptr->len = cpu_to_be16(len);
1379185eb79fSLEROY Christophe 	to_talitos_ptr_extent_clear(ptr);
1380032d197eSLEROY Christophe 
1381032d197eSLEROY Christophe 	sg_count = talitos_map_sg(dev, src, edesc->src_nents ? : 1, dir,
1382032d197eSLEROY Christophe 				  edesc->src_chained);
1383032d197eSLEROY Christophe 
1384032d197eSLEROY Christophe 	if (sg_count == 1) {
1385032d197eSLEROY Christophe 		to_talitos_ptr(ptr, sg_dma_address(src));
1386032d197eSLEROY Christophe 	} else {
1387032d197eSLEROY Christophe 		sg_count = sg_to_link_tbl(src, sg_count, len,
1388032d197eSLEROY Christophe 					  &edesc->link_tbl[0]);
1389032d197eSLEROY Christophe 		if (sg_count > 1) {
1390032d197eSLEROY Christophe 			to_talitos_ptr(ptr, edesc->dma_link_tbl);
1391032d197eSLEROY Christophe 			ptr->j_extent |= DESC_PTR_LNKTBL_JUMP;
1392032d197eSLEROY Christophe 			dma_sync_single_for_device(dev, edesc->dma_link_tbl,
1393032d197eSLEROY Christophe 						   edesc->dma_len,
1394032d197eSLEROY Christophe 						   DMA_BIDIRECTIONAL);
1395032d197eSLEROY Christophe 		} else {
1396032d197eSLEROY Christophe 			/* Only one segment now, so no link tbl needed */
1397032d197eSLEROY Christophe 			to_talitos_ptr(ptr, sg_dma_address(src));
1398032d197eSLEROY Christophe 		}
1399032d197eSLEROY Christophe 	}
1400032d197eSLEROY Christophe 	return sg_count;
1401032d197eSLEROY Christophe }
1402032d197eSLEROY Christophe 
1403032d197eSLEROY Christophe void map_sg_out_talitos_ptr(struct device *dev, struct scatterlist *dst,
1404032d197eSLEROY Christophe 			    unsigned int len, struct talitos_edesc *edesc,
1405032d197eSLEROY Christophe 			    enum dma_data_direction dir,
1406032d197eSLEROY Christophe 			    struct talitos_ptr *ptr, int sg_count)
1407032d197eSLEROY Christophe {
1408032d197eSLEROY Christophe 	ptr->len = cpu_to_be16(len);
1409185eb79fSLEROY Christophe 	to_talitos_ptr_extent_clear(ptr);
1410032d197eSLEROY Christophe 
1411032d197eSLEROY Christophe 	if (dir != DMA_NONE)
1412032d197eSLEROY Christophe 		sg_count = talitos_map_sg(dev, dst, edesc->dst_nents ? : 1,
1413032d197eSLEROY Christophe 					  dir, edesc->dst_chained);
1414032d197eSLEROY Christophe 
1415032d197eSLEROY Christophe 	if (sg_count == 1) {
1416032d197eSLEROY Christophe 		to_talitos_ptr(ptr, sg_dma_address(dst));
1417032d197eSLEROY Christophe 	} else {
1418032d197eSLEROY Christophe 		struct talitos_ptr *link_tbl_ptr =
1419032d197eSLEROY Christophe 			&edesc->link_tbl[edesc->src_nents + 1];
1420032d197eSLEROY Christophe 
1421032d197eSLEROY Christophe 		to_talitos_ptr(ptr, edesc->dma_link_tbl +
1422032d197eSLEROY Christophe 					      (edesc->src_nents + 1) *
1423032d197eSLEROY Christophe 					      sizeof(struct talitos_ptr));
1424032d197eSLEROY Christophe 		ptr->j_extent |= DESC_PTR_LNKTBL_JUMP;
1425032d197eSLEROY Christophe 		sg_count = sg_to_link_tbl(dst, sg_count, len, link_tbl_ptr);
1426032d197eSLEROY Christophe 		dma_sync_single_for_device(dev, edesc->dma_link_tbl,
1427032d197eSLEROY Christophe 					   edesc->dma_len, DMA_BIDIRECTIONAL);
1428032d197eSLEROY Christophe 	}
1429032d197eSLEROY Christophe }
1430032d197eSLEROY Christophe 
14314de9d0b5SLee Nipper static int common_nonsnoop(struct talitos_edesc *edesc,
14324de9d0b5SLee Nipper 			   struct ablkcipher_request *areq,
14334de9d0b5SLee Nipper 			   void (*callback) (struct device *dev,
14344de9d0b5SLee Nipper 					     struct talitos_desc *desc,
14354de9d0b5SLee Nipper 					     void *context, int error))
14364de9d0b5SLee Nipper {
14374de9d0b5SLee Nipper 	struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(areq);
14384de9d0b5SLee Nipper 	struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher);
14394de9d0b5SLee Nipper 	struct device *dev = ctx->dev;
14404de9d0b5SLee Nipper 	struct talitos_desc *desc = &edesc->desc;
14414de9d0b5SLee Nipper 	unsigned int cryptlen = areq->nbytes;
144279fd31d3SHoria Geanta 	unsigned int ivsize = crypto_ablkcipher_ivsize(cipher);
14434de9d0b5SLee Nipper 	int sg_count, ret;
14444de9d0b5SLee Nipper 
14454de9d0b5SLee Nipper 	/* first DWORD empty */
14462529bc37SLEROY Christophe 	desc->ptr[0] = zero_entry;
14474de9d0b5SLee Nipper 
14484de9d0b5SLee Nipper 	/* cipher iv */
144979fd31d3SHoria Geanta 	to_talitos_ptr(&desc->ptr[1], edesc->iv_dma);
145079fd31d3SHoria Geanta 	desc->ptr[1].len = cpu_to_be16(ivsize);
1451185eb79fSLEROY Christophe 	to_talitos_ptr_extent_clear(&desc->ptr[1]);
14524de9d0b5SLee Nipper 
14534de9d0b5SLee Nipper 	/* cipher key */
14544de9d0b5SLee Nipper 	map_single_talitos_ptr(dev, &desc->ptr[2], ctx->keylen,
1455*a2b35aa8SLEROY Christophe 			       (char *)&ctx->key, DMA_TO_DEVICE);
14564de9d0b5SLee Nipper 
14574de9d0b5SLee Nipper 	/*
14584de9d0b5SLee Nipper 	 * cipher in
14594de9d0b5SLee Nipper 	 */
1460032d197eSLEROY Christophe 	sg_count = map_sg_in_talitos_ptr(dev, areq->src, cryptlen, edesc,
1461032d197eSLEROY Christophe 					 (areq->src == areq->dst) ?
1462032d197eSLEROY Christophe 					  DMA_BIDIRECTIONAL : DMA_TO_DEVICE,
1463032d197eSLEROY Christophe 					  &desc->ptr[3]);
14644de9d0b5SLee Nipper 
14654de9d0b5SLee Nipper 	/* cipher out */
1466032d197eSLEROY Christophe 	map_sg_out_talitos_ptr(dev, areq->dst, cryptlen, edesc,
1467032d197eSLEROY Christophe 			       (areq->src == areq->dst) ? DMA_NONE
1468032d197eSLEROY Christophe 							: DMA_FROM_DEVICE,
1469032d197eSLEROY Christophe 			       &desc->ptr[4], sg_count);
14704de9d0b5SLee Nipper 
14714de9d0b5SLee Nipper 	/* iv out */
1472*a2b35aa8SLEROY Christophe 	map_single_talitos_ptr(dev, &desc->ptr[5], ivsize, ctx->iv,
14734de9d0b5SLee Nipper 			       DMA_FROM_DEVICE);
14744de9d0b5SLee Nipper 
14754de9d0b5SLee Nipper 	/* last DWORD empty */
14762529bc37SLEROY Christophe 	desc->ptr[6] = zero_entry;
14774de9d0b5SLee Nipper 
14785228f0f7SKim Phillips 	ret = talitos_submit(dev, ctx->ch, desc, callback, areq);
14794de9d0b5SLee Nipper 	if (ret != -EINPROGRESS) {
14804de9d0b5SLee Nipper 		common_nonsnoop_unmap(dev, edesc, areq);
14814de9d0b5SLee Nipper 		kfree(edesc);
14824de9d0b5SLee Nipper 	}
14834de9d0b5SLee Nipper 	return ret;
14844de9d0b5SLee Nipper }
14854de9d0b5SLee Nipper 
1486e938e465SKim Phillips static struct talitos_edesc *ablkcipher_edesc_alloc(struct ablkcipher_request *
148762293a37SHoria Geanta 						    areq, bool encrypt)
14884de9d0b5SLee Nipper {
14894de9d0b5SLee Nipper 	struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(areq);
14904de9d0b5SLee Nipper 	struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher);
149179fd31d3SHoria Geanta 	unsigned int ivsize = crypto_ablkcipher_ivsize(cipher);
14924de9d0b5SLee Nipper 
149379fd31d3SHoria Geanta 	return talitos_edesc_alloc(ctx->dev, NULL, areq->src, areq->dst,
149479fd31d3SHoria Geanta 				   areq->info, 0, areq->nbytes, 0, ivsize, 0,
149562293a37SHoria Geanta 				   areq->base.flags, encrypt);
14964de9d0b5SLee Nipper }
14974de9d0b5SLee Nipper 
14984de9d0b5SLee Nipper static int ablkcipher_encrypt(struct ablkcipher_request *areq)
14994de9d0b5SLee Nipper {
15004de9d0b5SLee Nipper 	struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(areq);
15014de9d0b5SLee Nipper 	struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher);
15024de9d0b5SLee Nipper 	struct talitos_edesc *edesc;
15034de9d0b5SLee Nipper 
15044de9d0b5SLee Nipper 	/* allocate extended descriptor */
150562293a37SHoria Geanta 	edesc = ablkcipher_edesc_alloc(areq, true);
15064de9d0b5SLee Nipper 	if (IS_ERR(edesc))
15074de9d0b5SLee Nipper 		return PTR_ERR(edesc);
15084de9d0b5SLee Nipper 
15094de9d0b5SLee Nipper 	/* set encrypt */
15104de9d0b5SLee Nipper 	edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_MODE0_ENCRYPT;
15114de9d0b5SLee Nipper 
1512febec542SKim Phillips 	return common_nonsnoop(edesc, areq, ablkcipher_done);
15134de9d0b5SLee Nipper }
15144de9d0b5SLee Nipper 
15154de9d0b5SLee Nipper static int ablkcipher_decrypt(struct ablkcipher_request *areq)
15164de9d0b5SLee Nipper {
15174de9d0b5SLee Nipper 	struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(areq);
15184de9d0b5SLee Nipper 	struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher);
15194de9d0b5SLee Nipper 	struct talitos_edesc *edesc;
15204de9d0b5SLee Nipper 
15214de9d0b5SLee Nipper 	/* allocate extended descriptor */
152262293a37SHoria Geanta 	edesc = ablkcipher_edesc_alloc(areq, false);
15234de9d0b5SLee Nipper 	if (IS_ERR(edesc))
15244de9d0b5SLee Nipper 		return PTR_ERR(edesc);
15254de9d0b5SLee Nipper 
15264de9d0b5SLee Nipper 	edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_DIR_INBOUND;
15274de9d0b5SLee Nipper 
1528febec542SKim Phillips 	return common_nonsnoop(edesc, areq, ablkcipher_done);
15294de9d0b5SLee Nipper }
15304de9d0b5SLee Nipper 
1531497f2e6bSLee Nipper static void common_nonsnoop_hash_unmap(struct device *dev,
1532497f2e6bSLee Nipper 				       struct talitos_edesc *edesc,
1533497f2e6bSLee Nipper 				       struct ahash_request *areq)
1534497f2e6bSLee Nipper {
1535497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
1536497f2e6bSLee Nipper 
1537497f2e6bSLee Nipper 	unmap_single_talitos_ptr(dev, &edesc->desc.ptr[5], DMA_FROM_DEVICE);
1538497f2e6bSLee Nipper 
1539032d197eSLEROY Christophe 	unmap_sg_talitos_ptr(dev, req_ctx->psrc, NULL, 0, edesc);
1540032d197eSLEROY Christophe 
1541497f2e6bSLee Nipper 	/* When using hashctx-in, must unmap it. */
1542497f2e6bSLee Nipper 	if (edesc->desc.ptr[1].len)
1543497f2e6bSLee Nipper 		unmap_single_talitos_ptr(dev, &edesc->desc.ptr[1],
1544497f2e6bSLee Nipper 					 DMA_TO_DEVICE);
1545497f2e6bSLee Nipper 
1546497f2e6bSLee Nipper 	if (edesc->desc.ptr[2].len)
1547497f2e6bSLee Nipper 		unmap_single_talitos_ptr(dev, &edesc->desc.ptr[2],
1548497f2e6bSLee Nipper 					 DMA_TO_DEVICE);
1549497f2e6bSLee Nipper 
1550497f2e6bSLee Nipper 	if (edesc->dma_len)
1551497f2e6bSLee Nipper 		dma_unmap_single(dev, edesc->dma_link_tbl, edesc->dma_len,
1552497f2e6bSLee Nipper 				 DMA_BIDIRECTIONAL);
1553497f2e6bSLee Nipper 
1554497f2e6bSLee Nipper }
1555497f2e6bSLee Nipper 
1556497f2e6bSLee Nipper static void ahash_done(struct device *dev,
1557497f2e6bSLee Nipper 		       struct talitos_desc *desc, void *context,
1558497f2e6bSLee Nipper 		       int err)
1559497f2e6bSLee Nipper {
1560497f2e6bSLee Nipper 	struct ahash_request *areq = context;
1561497f2e6bSLee Nipper 	struct talitos_edesc *edesc =
1562497f2e6bSLee Nipper 		 container_of(desc, struct talitos_edesc, desc);
1563497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
1564497f2e6bSLee Nipper 
1565497f2e6bSLee Nipper 	if (!req_ctx->last && req_ctx->to_hash_later) {
1566497f2e6bSLee Nipper 		/* Position any partial block for next update/final/finup */
1567497f2e6bSLee Nipper 		memcpy(req_ctx->buf, req_ctx->bufnext, req_ctx->to_hash_later);
15685e833bc4SLee Nipper 		req_ctx->nbuf = req_ctx->to_hash_later;
1569497f2e6bSLee Nipper 	}
1570497f2e6bSLee Nipper 	common_nonsnoop_hash_unmap(dev, edesc, areq);
1571497f2e6bSLee Nipper 
1572497f2e6bSLee Nipper 	kfree(edesc);
1573497f2e6bSLee Nipper 
1574497f2e6bSLee Nipper 	areq->base.complete(&areq->base, err);
1575497f2e6bSLee Nipper }
1576497f2e6bSLee Nipper 
1577497f2e6bSLee Nipper static int common_nonsnoop_hash(struct talitos_edesc *edesc,
1578497f2e6bSLee Nipper 				struct ahash_request *areq, unsigned int length,
1579497f2e6bSLee Nipper 				void (*callback) (struct device *dev,
1580497f2e6bSLee Nipper 						  struct talitos_desc *desc,
1581497f2e6bSLee Nipper 						  void *context, int error))
1582497f2e6bSLee Nipper {
1583497f2e6bSLee Nipper 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
1584497f2e6bSLee Nipper 	struct talitos_ctx *ctx = crypto_ahash_ctx(tfm);
1585497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
1586497f2e6bSLee Nipper 	struct device *dev = ctx->dev;
1587497f2e6bSLee Nipper 	struct talitos_desc *desc = &edesc->desc;
1588032d197eSLEROY Christophe 	int ret;
1589497f2e6bSLee Nipper 
1590497f2e6bSLee Nipper 	/* first DWORD empty */
1591497f2e6bSLee Nipper 	desc->ptr[0] = zero_entry;
1592497f2e6bSLee Nipper 
159360f208d7SKim Phillips 	/* hash context in */
159460f208d7SKim Phillips 	if (!req_ctx->first || req_ctx->swinit) {
1595497f2e6bSLee Nipper 		map_single_talitos_ptr(dev, &desc->ptr[1],
1596497f2e6bSLee Nipper 				       req_ctx->hw_context_size,
1597*a2b35aa8SLEROY Christophe 				       (char *)req_ctx->hw_context,
1598497f2e6bSLee Nipper 				       DMA_TO_DEVICE);
159960f208d7SKim Phillips 		req_ctx->swinit = 0;
1600497f2e6bSLee Nipper 	} else {
1601497f2e6bSLee Nipper 		desc->ptr[1] = zero_entry;
1602497f2e6bSLee Nipper 		/* Indicate next op is not the first. */
1603497f2e6bSLee Nipper 		req_ctx->first = 0;
1604497f2e6bSLee Nipper 	}
1605497f2e6bSLee Nipper 
1606497f2e6bSLee Nipper 	/* HMAC key */
1607497f2e6bSLee Nipper 	if (ctx->keylen)
1608497f2e6bSLee Nipper 		map_single_talitos_ptr(dev, &desc->ptr[2], ctx->keylen,
1609*a2b35aa8SLEROY Christophe 				       (char *)&ctx->key, DMA_TO_DEVICE);
1610497f2e6bSLee Nipper 	else
1611497f2e6bSLee Nipper 		desc->ptr[2] = zero_entry;
1612497f2e6bSLee Nipper 
1613497f2e6bSLee Nipper 	/*
1614497f2e6bSLee Nipper 	 * data in
1615497f2e6bSLee Nipper 	 */
1616032d197eSLEROY Christophe 	map_sg_in_talitos_ptr(dev, req_ctx->psrc, length, edesc,
1617032d197eSLEROY Christophe 			      DMA_TO_DEVICE, &desc->ptr[3]);
1618497f2e6bSLee Nipper 
1619497f2e6bSLee Nipper 	/* fifth DWORD empty */
1620497f2e6bSLee Nipper 	desc->ptr[4] = zero_entry;
1621497f2e6bSLee Nipper 
1622497f2e6bSLee Nipper 	/* hash/HMAC out -or- hash context out */
1623497f2e6bSLee Nipper 	if (req_ctx->last)
1624497f2e6bSLee Nipper 		map_single_talitos_ptr(dev, &desc->ptr[5],
1625497f2e6bSLee Nipper 				       crypto_ahash_digestsize(tfm),
1626*a2b35aa8SLEROY Christophe 				       areq->result, DMA_FROM_DEVICE);
1627497f2e6bSLee Nipper 	else
1628497f2e6bSLee Nipper 		map_single_talitos_ptr(dev, &desc->ptr[5],
1629497f2e6bSLee Nipper 				       req_ctx->hw_context_size,
1630*a2b35aa8SLEROY Christophe 				       req_ctx->hw_context, DMA_FROM_DEVICE);
1631497f2e6bSLee Nipper 
1632497f2e6bSLee Nipper 	/* last DWORD empty */
1633497f2e6bSLee Nipper 	desc->ptr[6] = zero_entry;
1634497f2e6bSLee Nipper 
16355228f0f7SKim Phillips 	ret = talitos_submit(dev, ctx->ch, desc, callback, areq);
1636497f2e6bSLee Nipper 	if (ret != -EINPROGRESS) {
1637497f2e6bSLee Nipper 		common_nonsnoop_hash_unmap(dev, edesc, areq);
1638497f2e6bSLee Nipper 		kfree(edesc);
1639497f2e6bSLee Nipper 	}
1640497f2e6bSLee Nipper 	return ret;
1641497f2e6bSLee Nipper }
1642497f2e6bSLee Nipper 
1643497f2e6bSLee Nipper static struct talitos_edesc *ahash_edesc_alloc(struct ahash_request *areq,
1644497f2e6bSLee Nipper 					       unsigned int nbytes)
1645497f2e6bSLee Nipper {
1646497f2e6bSLee Nipper 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
1647497f2e6bSLee Nipper 	struct talitos_ctx *ctx = crypto_ahash_ctx(tfm);
1648497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
1649497f2e6bSLee Nipper 
165079fd31d3SHoria Geanta 	return talitos_edesc_alloc(ctx->dev, NULL, req_ctx->psrc, NULL, NULL, 0,
165162293a37SHoria Geanta 				   nbytes, 0, 0, 0, areq->base.flags, false);
1652497f2e6bSLee Nipper }
1653497f2e6bSLee Nipper 
1654497f2e6bSLee Nipper static int ahash_init(struct ahash_request *areq)
1655497f2e6bSLee Nipper {
1656497f2e6bSLee Nipper 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
1657497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
1658497f2e6bSLee Nipper 
1659497f2e6bSLee Nipper 	/* Initialize the context */
16605e833bc4SLee Nipper 	req_ctx->nbuf = 0;
166160f208d7SKim Phillips 	req_ctx->first = 1; /* first indicates h/w must init its context */
166260f208d7SKim Phillips 	req_ctx->swinit = 0; /* assume h/w init of context */
1663497f2e6bSLee Nipper 	req_ctx->hw_context_size =
1664497f2e6bSLee Nipper 		(crypto_ahash_digestsize(tfm) <= SHA256_DIGEST_SIZE)
1665497f2e6bSLee Nipper 			? TALITOS_MDEU_CONTEXT_SIZE_MD5_SHA1_SHA256
1666497f2e6bSLee Nipper 			: TALITOS_MDEU_CONTEXT_SIZE_SHA384_SHA512;
1667497f2e6bSLee Nipper 
1668497f2e6bSLee Nipper 	return 0;
1669497f2e6bSLee Nipper }
1670497f2e6bSLee Nipper 
167160f208d7SKim Phillips /*
167260f208d7SKim Phillips  * on h/w without explicit sha224 support, we initialize h/w context
167360f208d7SKim Phillips  * manually with sha224 constants, and tell it to run sha256.
167460f208d7SKim Phillips  */
167560f208d7SKim Phillips static int ahash_init_sha224_swinit(struct ahash_request *areq)
167660f208d7SKim Phillips {
167760f208d7SKim Phillips 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
167860f208d7SKim Phillips 
167960f208d7SKim Phillips 	ahash_init(areq);
168060f208d7SKim Phillips 	req_ctx->swinit = 1;/* prevent h/w initting context with sha256 values*/
168160f208d7SKim Phillips 
1682a752447aSKim Phillips 	req_ctx->hw_context[0] = SHA224_H0;
1683a752447aSKim Phillips 	req_ctx->hw_context[1] = SHA224_H1;
1684a752447aSKim Phillips 	req_ctx->hw_context[2] = SHA224_H2;
1685a752447aSKim Phillips 	req_ctx->hw_context[3] = SHA224_H3;
1686a752447aSKim Phillips 	req_ctx->hw_context[4] = SHA224_H4;
1687a752447aSKim Phillips 	req_ctx->hw_context[5] = SHA224_H5;
1688a752447aSKim Phillips 	req_ctx->hw_context[6] = SHA224_H6;
1689a752447aSKim Phillips 	req_ctx->hw_context[7] = SHA224_H7;
169060f208d7SKim Phillips 
169160f208d7SKim Phillips 	/* init 64-bit count */
169260f208d7SKim Phillips 	req_ctx->hw_context[8] = 0;
169360f208d7SKim Phillips 	req_ctx->hw_context[9] = 0;
169460f208d7SKim Phillips 
169560f208d7SKim Phillips 	return 0;
169660f208d7SKim Phillips }
169760f208d7SKim Phillips 
1698497f2e6bSLee Nipper static int ahash_process_req(struct ahash_request *areq, unsigned int nbytes)
1699497f2e6bSLee Nipper {
1700497f2e6bSLee Nipper 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
1701497f2e6bSLee Nipper 	struct talitos_ctx *ctx = crypto_ahash_ctx(tfm);
1702497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
1703497f2e6bSLee Nipper 	struct talitos_edesc *edesc;
1704497f2e6bSLee Nipper 	unsigned int blocksize =
1705497f2e6bSLee Nipper 			crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm));
1706497f2e6bSLee Nipper 	unsigned int nbytes_to_hash;
1707497f2e6bSLee Nipper 	unsigned int to_hash_later;
17085e833bc4SLee Nipper 	unsigned int nsg;
17092a1cfe46SHoria Geanta 	bool chained;
1710497f2e6bSLee Nipper 
17115e833bc4SLee Nipper 	if (!req_ctx->last && (nbytes + req_ctx->nbuf <= blocksize)) {
17125e833bc4SLee Nipper 		/* Buffer up to one whole block */
1713497f2e6bSLee Nipper 		sg_copy_to_buffer(areq->src,
1714497f2e6bSLee Nipper 				  sg_count(areq->src, nbytes, &chained),
17155e833bc4SLee Nipper 				  req_ctx->buf + req_ctx->nbuf, nbytes);
17165e833bc4SLee Nipper 		req_ctx->nbuf += nbytes;
1717497f2e6bSLee Nipper 		return 0;
1718497f2e6bSLee Nipper 	}
1719497f2e6bSLee Nipper 
17205e833bc4SLee Nipper 	/* At least (blocksize + 1) bytes are available to hash */
17215e833bc4SLee Nipper 	nbytes_to_hash = nbytes + req_ctx->nbuf;
17225e833bc4SLee Nipper 	to_hash_later = nbytes_to_hash & (blocksize - 1);
17235e833bc4SLee Nipper 
17245e833bc4SLee Nipper 	if (req_ctx->last)
17255e833bc4SLee Nipper 		to_hash_later = 0;
17265e833bc4SLee Nipper 	else if (to_hash_later)
17275e833bc4SLee Nipper 		/* There is a partial block. Hash the full block(s) now */
17285e833bc4SLee Nipper 		nbytes_to_hash -= to_hash_later;
17295e833bc4SLee Nipper 	else {
17305e833bc4SLee Nipper 		/* Keep one block buffered */
17315e833bc4SLee Nipper 		nbytes_to_hash -= blocksize;
17325e833bc4SLee Nipper 		to_hash_later = blocksize;
1733497f2e6bSLee Nipper 	}
17345e833bc4SLee Nipper 
17355e833bc4SLee Nipper 	/* Chain in any previously buffered data */
17365e833bc4SLee Nipper 	if (req_ctx->nbuf) {
17375e833bc4SLee Nipper 		nsg = (req_ctx->nbuf < nbytes_to_hash) ? 2 : 1;
17385e833bc4SLee Nipper 		sg_init_table(req_ctx->bufsl, nsg);
17395e833bc4SLee Nipper 		sg_set_buf(req_ctx->bufsl, req_ctx->buf, req_ctx->nbuf);
17405e833bc4SLee Nipper 		if (nsg > 1)
17415e833bc4SLee Nipper 			scatterwalk_sg_chain(req_ctx->bufsl, 2, areq->src);
17425e833bc4SLee Nipper 		req_ctx->psrc = req_ctx->bufsl;
17435e833bc4SLee Nipper 	} else
17445e833bc4SLee Nipper 		req_ctx->psrc = areq->src;
17455e833bc4SLee Nipper 
1746497f2e6bSLee Nipper 	if (to_hash_later) {
17475e833bc4SLee Nipper 		int nents = sg_count(areq->src, nbytes, &chained);
1748d0525723SAkinobu Mita 		sg_pcopy_to_buffer(areq->src, nents,
1749497f2e6bSLee Nipper 				      req_ctx->bufnext,
1750497f2e6bSLee Nipper 				      to_hash_later,
1751497f2e6bSLee Nipper 				      nbytes - to_hash_later);
1752497f2e6bSLee Nipper 	}
1753497f2e6bSLee Nipper 	req_ctx->to_hash_later = to_hash_later;
1754497f2e6bSLee Nipper 
17555e833bc4SLee Nipper 	/* Allocate extended descriptor */
1756497f2e6bSLee Nipper 	edesc = ahash_edesc_alloc(areq, nbytes_to_hash);
1757497f2e6bSLee Nipper 	if (IS_ERR(edesc))
1758497f2e6bSLee Nipper 		return PTR_ERR(edesc);
1759497f2e6bSLee Nipper 
1760497f2e6bSLee Nipper 	edesc->desc.hdr = ctx->desc_hdr_template;
1761497f2e6bSLee Nipper 
1762497f2e6bSLee Nipper 	/* On last one, request SEC to pad; otherwise continue */
1763497f2e6bSLee Nipper 	if (req_ctx->last)
1764497f2e6bSLee Nipper 		edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_PAD;
1765497f2e6bSLee Nipper 	else
1766497f2e6bSLee Nipper 		edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_CONT;
1767497f2e6bSLee Nipper 
176860f208d7SKim Phillips 	/* request SEC to INIT hash. */
176960f208d7SKim Phillips 	if (req_ctx->first && !req_ctx->swinit)
1770497f2e6bSLee Nipper 		edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_INIT;
1771497f2e6bSLee Nipper 
1772497f2e6bSLee Nipper 	/* When the tfm context has a keylen, it's an HMAC.
1773497f2e6bSLee Nipper 	 * A first or last (ie. not middle) descriptor must request HMAC.
1774497f2e6bSLee Nipper 	 */
1775497f2e6bSLee Nipper 	if (ctx->keylen && (req_ctx->first || req_ctx->last))
1776497f2e6bSLee Nipper 		edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_HMAC;
1777497f2e6bSLee Nipper 
1778497f2e6bSLee Nipper 	return common_nonsnoop_hash(edesc, areq, nbytes_to_hash,
1779497f2e6bSLee Nipper 				    ahash_done);
1780497f2e6bSLee Nipper }
1781497f2e6bSLee Nipper 
1782497f2e6bSLee Nipper static int ahash_update(struct ahash_request *areq)
1783497f2e6bSLee Nipper {
1784497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
1785497f2e6bSLee Nipper 
1786497f2e6bSLee Nipper 	req_ctx->last = 0;
1787497f2e6bSLee Nipper 
1788497f2e6bSLee Nipper 	return ahash_process_req(areq, areq->nbytes);
1789497f2e6bSLee Nipper }
1790497f2e6bSLee Nipper 
1791497f2e6bSLee Nipper static int ahash_final(struct ahash_request *areq)
1792497f2e6bSLee Nipper {
1793497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
1794497f2e6bSLee Nipper 
1795497f2e6bSLee Nipper 	req_ctx->last = 1;
1796497f2e6bSLee Nipper 
1797497f2e6bSLee Nipper 	return ahash_process_req(areq, 0);
1798497f2e6bSLee Nipper }
1799497f2e6bSLee Nipper 
1800497f2e6bSLee Nipper static int ahash_finup(struct ahash_request *areq)
1801497f2e6bSLee Nipper {
1802497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
1803497f2e6bSLee Nipper 
1804497f2e6bSLee Nipper 	req_ctx->last = 1;
1805497f2e6bSLee Nipper 
1806497f2e6bSLee Nipper 	return ahash_process_req(areq, areq->nbytes);
1807497f2e6bSLee Nipper }
1808497f2e6bSLee Nipper 
1809497f2e6bSLee Nipper static int ahash_digest(struct ahash_request *areq)
1810497f2e6bSLee Nipper {
1811497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
181260f208d7SKim Phillips 	struct crypto_ahash *ahash = crypto_ahash_reqtfm(areq);
1813497f2e6bSLee Nipper 
181460f208d7SKim Phillips 	ahash->init(areq);
1815497f2e6bSLee Nipper 	req_ctx->last = 1;
1816497f2e6bSLee Nipper 
1817497f2e6bSLee Nipper 	return ahash_process_req(areq, areq->nbytes);
1818497f2e6bSLee Nipper }
1819497f2e6bSLee Nipper 
182079b3a418SLee Nipper struct keyhash_result {
182179b3a418SLee Nipper 	struct completion completion;
182279b3a418SLee Nipper 	int err;
182379b3a418SLee Nipper };
182479b3a418SLee Nipper 
182579b3a418SLee Nipper static void keyhash_complete(struct crypto_async_request *req, int err)
182679b3a418SLee Nipper {
182779b3a418SLee Nipper 	struct keyhash_result *res = req->data;
182879b3a418SLee Nipper 
182979b3a418SLee Nipper 	if (err == -EINPROGRESS)
183079b3a418SLee Nipper 		return;
183179b3a418SLee Nipper 
183279b3a418SLee Nipper 	res->err = err;
183379b3a418SLee Nipper 	complete(&res->completion);
183479b3a418SLee Nipper }
183579b3a418SLee Nipper 
183679b3a418SLee Nipper static int keyhash(struct crypto_ahash *tfm, const u8 *key, unsigned int keylen,
183779b3a418SLee Nipper 		   u8 *hash)
183879b3a418SLee Nipper {
183979b3a418SLee Nipper 	struct talitos_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm));
184079b3a418SLee Nipper 
184179b3a418SLee Nipper 	struct scatterlist sg[1];
184279b3a418SLee Nipper 	struct ahash_request *req;
184379b3a418SLee Nipper 	struct keyhash_result hresult;
184479b3a418SLee Nipper 	int ret;
184579b3a418SLee Nipper 
184679b3a418SLee Nipper 	init_completion(&hresult.completion);
184779b3a418SLee Nipper 
184879b3a418SLee Nipper 	req = ahash_request_alloc(tfm, GFP_KERNEL);
184979b3a418SLee Nipper 	if (!req)
185079b3a418SLee Nipper 		return -ENOMEM;
185179b3a418SLee Nipper 
185279b3a418SLee Nipper 	/* Keep tfm keylen == 0 during hash of the long key */
185379b3a418SLee Nipper 	ctx->keylen = 0;
185479b3a418SLee Nipper 	ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
185579b3a418SLee Nipper 				   keyhash_complete, &hresult);
185679b3a418SLee Nipper 
185779b3a418SLee Nipper 	sg_init_one(&sg[0], key, keylen);
185879b3a418SLee Nipper 
185979b3a418SLee Nipper 	ahash_request_set_crypt(req, sg, hash, keylen);
186079b3a418SLee Nipper 	ret = crypto_ahash_digest(req);
186179b3a418SLee Nipper 	switch (ret) {
186279b3a418SLee Nipper 	case 0:
186379b3a418SLee Nipper 		break;
186479b3a418SLee Nipper 	case -EINPROGRESS:
186579b3a418SLee Nipper 	case -EBUSY:
186679b3a418SLee Nipper 		ret = wait_for_completion_interruptible(
186779b3a418SLee Nipper 			&hresult.completion);
186879b3a418SLee Nipper 		if (!ret)
186979b3a418SLee Nipper 			ret = hresult.err;
187079b3a418SLee Nipper 		break;
187179b3a418SLee Nipper 	default:
187279b3a418SLee Nipper 		break;
187379b3a418SLee Nipper 	}
187479b3a418SLee Nipper 	ahash_request_free(req);
187579b3a418SLee Nipper 
187679b3a418SLee Nipper 	return ret;
187779b3a418SLee Nipper }
187879b3a418SLee Nipper 
187979b3a418SLee Nipper static int ahash_setkey(struct crypto_ahash *tfm, const u8 *key,
188079b3a418SLee Nipper 			unsigned int keylen)
188179b3a418SLee Nipper {
188279b3a418SLee Nipper 	struct talitos_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm));
188379b3a418SLee Nipper 	unsigned int blocksize =
188479b3a418SLee Nipper 			crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm));
188579b3a418SLee Nipper 	unsigned int digestsize = crypto_ahash_digestsize(tfm);
188679b3a418SLee Nipper 	unsigned int keysize = keylen;
188779b3a418SLee Nipper 	u8 hash[SHA512_DIGEST_SIZE];
188879b3a418SLee Nipper 	int ret;
188979b3a418SLee Nipper 
189079b3a418SLee Nipper 	if (keylen <= blocksize)
189179b3a418SLee Nipper 		memcpy(ctx->key, key, keysize);
189279b3a418SLee Nipper 	else {
189379b3a418SLee Nipper 		/* Must get the hash of the long key */
189479b3a418SLee Nipper 		ret = keyhash(tfm, key, keylen, hash);
189579b3a418SLee Nipper 
189679b3a418SLee Nipper 		if (ret) {
189779b3a418SLee Nipper 			crypto_ahash_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
189879b3a418SLee Nipper 			return -EINVAL;
189979b3a418SLee Nipper 		}
190079b3a418SLee Nipper 
190179b3a418SLee Nipper 		keysize = digestsize;
190279b3a418SLee Nipper 		memcpy(ctx->key, hash, digestsize);
190379b3a418SLee Nipper 	}
190479b3a418SLee Nipper 
190579b3a418SLee Nipper 	ctx->keylen = keysize;
190679b3a418SLee Nipper 
190779b3a418SLee Nipper 	return 0;
190879b3a418SLee Nipper }
190979b3a418SLee Nipper 
191079b3a418SLee Nipper 
19119c4a7965SKim Phillips struct talitos_alg_template {
1912d5e4aaefSLee Nipper 	u32 type;
1913d5e4aaefSLee Nipper 	union {
1914d5e4aaefSLee Nipper 		struct crypto_alg crypto;
1915acbf7c62SLee Nipper 		struct ahash_alg hash;
1916d5e4aaefSLee Nipper 	} alg;
19179c4a7965SKim Phillips 	__be32 desc_hdr_template;
19189c4a7965SKim Phillips };
19199c4a7965SKim Phillips 
19209c4a7965SKim Phillips static struct talitos_alg_template driver_algs[] = {
1921991155baSHoria Geanta 	/* AEAD algorithms.  These use a single-pass ipsec_esp descriptor */
1922d5e4aaefSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AEAD,
1923d5e4aaefSLee Nipper 		.alg.crypto = {
192456af8cd4SLee Nipper 			.cra_name = "authenc(hmac(sha1),cbc(aes))",
192556af8cd4SLee Nipper 			.cra_driver_name = "authenc-hmac-sha1-cbc-aes-talitos",
192656af8cd4SLee Nipper 			.cra_blocksize = AES_BLOCK_SIZE,
192756af8cd4SLee Nipper 			.cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC,
192856af8cd4SLee Nipper 			.cra_aead = {
19293952f17eSLee Nipper 				.ivsize = AES_BLOCK_SIZE,
19303952f17eSLee Nipper 				.maxauthsize = SHA1_DIGEST_SIZE,
193156af8cd4SLee Nipper 			}
19329c4a7965SKim Phillips 		},
19339c4a7965SKim Phillips 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
19349c4a7965SKim Phillips 			             DESC_HDR_SEL0_AESU |
19359c4a7965SKim Phillips 		                     DESC_HDR_MODE0_AESU_CBC |
19369c4a7965SKim Phillips 		                     DESC_HDR_SEL1_MDEUA |
19379c4a7965SKim Phillips 		                     DESC_HDR_MODE1_MDEU_INIT |
19389c4a7965SKim Phillips 		                     DESC_HDR_MODE1_MDEU_PAD |
19399c4a7965SKim Phillips 		                     DESC_HDR_MODE1_MDEU_SHA1_HMAC,
194070bcaca7SLee Nipper 	},
1941d5e4aaefSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AEAD,
1942d5e4aaefSLee Nipper 		.alg.crypto = {
194356af8cd4SLee Nipper 			.cra_name = "authenc(hmac(sha1),cbc(des3_ede))",
194456af8cd4SLee Nipper 			.cra_driver_name = "authenc-hmac-sha1-cbc-3des-talitos",
194556af8cd4SLee Nipper 			.cra_blocksize = DES3_EDE_BLOCK_SIZE,
194656af8cd4SLee Nipper 			.cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC,
194756af8cd4SLee Nipper 			.cra_aead = {
19483952f17eSLee Nipper 				.ivsize = DES3_EDE_BLOCK_SIZE,
19493952f17eSLee Nipper 				.maxauthsize = SHA1_DIGEST_SIZE,
195056af8cd4SLee Nipper 			}
195170bcaca7SLee Nipper 		},
195270bcaca7SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
195370bcaca7SLee Nipper 			             DESC_HDR_SEL0_DEU |
195470bcaca7SLee Nipper 		                     DESC_HDR_MODE0_DEU_CBC |
195570bcaca7SLee Nipper 		                     DESC_HDR_MODE0_DEU_3DES |
195670bcaca7SLee Nipper 		                     DESC_HDR_SEL1_MDEUA |
195770bcaca7SLee Nipper 		                     DESC_HDR_MODE1_MDEU_INIT |
195870bcaca7SLee Nipper 		                     DESC_HDR_MODE1_MDEU_PAD |
195970bcaca7SLee Nipper 		                     DESC_HDR_MODE1_MDEU_SHA1_HMAC,
19603952f17eSLee Nipper 	},
1961d5e4aaefSLee Nipper 	{       .type = CRYPTO_ALG_TYPE_AEAD,
1962d5e4aaefSLee Nipper 		.alg.crypto = {
1963357fb605SHoria Geanta 			.cra_name = "authenc(hmac(sha224),cbc(aes))",
1964357fb605SHoria Geanta 			.cra_driver_name = "authenc-hmac-sha224-cbc-aes-talitos",
1965357fb605SHoria Geanta 			.cra_blocksize = AES_BLOCK_SIZE,
1966357fb605SHoria Geanta 			.cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC,
1967357fb605SHoria Geanta 			.cra_aead = {
1968357fb605SHoria Geanta 				.ivsize = AES_BLOCK_SIZE,
1969357fb605SHoria Geanta 				.maxauthsize = SHA224_DIGEST_SIZE,
1970357fb605SHoria Geanta 			}
1971357fb605SHoria Geanta 		},
1972357fb605SHoria Geanta 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
1973357fb605SHoria Geanta 				     DESC_HDR_SEL0_AESU |
1974357fb605SHoria Geanta 				     DESC_HDR_MODE0_AESU_CBC |
1975357fb605SHoria Geanta 				     DESC_HDR_SEL1_MDEUA |
1976357fb605SHoria Geanta 				     DESC_HDR_MODE1_MDEU_INIT |
1977357fb605SHoria Geanta 				     DESC_HDR_MODE1_MDEU_PAD |
1978357fb605SHoria Geanta 				     DESC_HDR_MODE1_MDEU_SHA224_HMAC,
1979357fb605SHoria Geanta 	},
1980357fb605SHoria Geanta 	{	.type = CRYPTO_ALG_TYPE_AEAD,
1981357fb605SHoria Geanta 		.alg.crypto = {
1982357fb605SHoria Geanta 			.cra_name = "authenc(hmac(sha224),cbc(des3_ede))",
1983357fb605SHoria Geanta 			.cra_driver_name = "authenc-hmac-sha224-cbc-3des-talitos",
1984357fb605SHoria Geanta 			.cra_blocksize = DES3_EDE_BLOCK_SIZE,
1985357fb605SHoria Geanta 			.cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC,
1986357fb605SHoria Geanta 			.cra_aead = {
1987357fb605SHoria Geanta 				.ivsize = DES3_EDE_BLOCK_SIZE,
1988357fb605SHoria Geanta 				.maxauthsize = SHA224_DIGEST_SIZE,
1989357fb605SHoria Geanta 			}
1990357fb605SHoria Geanta 		},
1991357fb605SHoria Geanta 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
1992357fb605SHoria Geanta 			             DESC_HDR_SEL0_DEU |
1993357fb605SHoria Geanta 		                     DESC_HDR_MODE0_DEU_CBC |
1994357fb605SHoria Geanta 		                     DESC_HDR_MODE0_DEU_3DES |
1995357fb605SHoria Geanta 		                     DESC_HDR_SEL1_MDEUA |
1996357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_INIT |
1997357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_PAD |
1998357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_SHA224_HMAC,
1999357fb605SHoria Geanta 	},
2000357fb605SHoria Geanta 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2001357fb605SHoria Geanta 		.alg.crypto = {
200256af8cd4SLee Nipper 			.cra_name = "authenc(hmac(sha256),cbc(aes))",
200356af8cd4SLee Nipper 			.cra_driver_name = "authenc-hmac-sha256-cbc-aes-talitos",
200456af8cd4SLee Nipper 			.cra_blocksize = AES_BLOCK_SIZE,
200556af8cd4SLee Nipper 			.cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC,
200656af8cd4SLee Nipper 			.cra_aead = {
20073952f17eSLee Nipper 				.ivsize = AES_BLOCK_SIZE,
20083952f17eSLee Nipper 				.maxauthsize = SHA256_DIGEST_SIZE,
200956af8cd4SLee Nipper 			}
20103952f17eSLee Nipper 		},
20113952f17eSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
20123952f17eSLee Nipper 			             DESC_HDR_SEL0_AESU |
20133952f17eSLee Nipper 		                     DESC_HDR_MODE0_AESU_CBC |
20143952f17eSLee Nipper 		                     DESC_HDR_SEL1_MDEUA |
20153952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_INIT |
20163952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_PAD |
20173952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_SHA256_HMAC,
20183952f17eSLee Nipper 	},
2019d5e4aaefSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2020d5e4aaefSLee Nipper 		.alg.crypto = {
202156af8cd4SLee Nipper 			.cra_name = "authenc(hmac(sha256),cbc(des3_ede))",
202256af8cd4SLee Nipper 			.cra_driver_name = "authenc-hmac-sha256-cbc-3des-talitos",
202356af8cd4SLee Nipper 			.cra_blocksize = DES3_EDE_BLOCK_SIZE,
202456af8cd4SLee Nipper 			.cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC,
202556af8cd4SLee Nipper 			.cra_aead = {
20263952f17eSLee Nipper 				.ivsize = DES3_EDE_BLOCK_SIZE,
20273952f17eSLee Nipper 				.maxauthsize = SHA256_DIGEST_SIZE,
202856af8cd4SLee Nipper 			}
20293952f17eSLee Nipper 		},
20303952f17eSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
20313952f17eSLee Nipper 			             DESC_HDR_SEL0_DEU |
20323952f17eSLee Nipper 		                     DESC_HDR_MODE0_DEU_CBC |
20333952f17eSLee Nipper 		                     DESC_HDR_MODE0_DEU_3DES |
20343952f17eSLee Nipper 		                     DESC_HDR_SEL1_MDEUA |
20353952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_INIT |
20363952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_PAD |
20373952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_SHA256_HMAC,
20383952f17eSLee Nipper 	},
2039d5e4aaefSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2040d5e4aaefSLee Nipper 		.alg.crypto = {
2041357fb605SHoria Geanta 			.cra_name = "authenc(hmac(sha384),cbc(aes))",
2042357fb605SHoria Geanta 			.cra_driver_name = "authenc-hmac-sha384-cbc-aes-talitos",
2043357fb605SHoria Geanta 			.cra_blocksize = AES_BLOCK_SIZE,
2044357fb605SHoria Geanta 			.cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC,
2045357fb605SHoria Geanta 			.cra_aead = {
2046357fb605SHoria Geanta 				.ivsize = AES_BLOCK_SIZE,
2047357fb605SHoria Geanta 				.maxauthsize = SHA384_DIGEST_SIZE,
2048357fb605SHoria Geanta 			}
2049357fb605SHoria Geanta 		},
2050357fb605SHoria Geanta 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
2051357fb605SHoria Geanta 			             DESC_HDR_SEL0_AESU |
2052357fb605SHoria Geanta 		                     DESC_HDR_MODE0_AESU_CBC |
2053357fb605SHoria Geanta 		                     DESC_HDR_SEL1_MDEUB |
2054357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_INIT |
2055357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_PAD |
2056357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEUB_SHA384_HMAC,
2057357fb605SHoria Geanta 	},
2058357fb605SHoria Geanta 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2059357fb605SHoria Geanta 		.alg.crypto = {
2060357fb605SHoria Geanta 			.cra_name = "authenc(hmac(sha384),cbc(des3_ede))",
2061357fb605SHoria Geanta 			.cra_driver_name = "authenc-hmac-sha384-cbc-3des-talitos",
2062357fb605SHoria Geanta 			.cra_blocksize = DES3_EDE_BLOCK_SIZE,
2063357fb605SHoria Geanta 			.cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC,
2064357fb605SHoria Geanta 			.cra_aead = {
2065357fb605SHoria Geanta 				.ivsize = DES3_EDE_BLOCK_SIZE,
2066357fb605SHoria Geanta 				.maxauthsize = SHA384_DIGEST_SIZE,
2067357fb605SHoria Geanta 			}
2068357fb605SHoria Geanta 		},
2069357fb605SHoria Geanta 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
2070357fb605SHoria Geanta 			             DESC_HDR_SEL0_DEU |
2071357fb605SHoria Geanta 		                     DESC_HDR_MODE0_DEU_CBC |
2072357fb605SHoria Geanta 		                     DESC_HDR_MODE0_DEU_3DES |
2073357fb605SHoria Geanta 		                     DESC_HDR_SEL1_MDEUB |
2074357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_INIT |
2075357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_PAD |
2076357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEUB_SHA384_HMAC,
2077357fb605SHoria Geanta 	},
2078357fb605SHoria Geanta 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2079357fb605SHoria Geanta 		.alg.crypto = {
2080357fb605SHoria Geanta 			.cra_name = "authenc(hmac(sha512),cbc(aes))",
2081357fb605SHoria Geanta 			.cra_driver_name = "authenc-hmac-sha512-cbc-aes-talitos",
2082357fb605SHoria Geanta 			.cra_blocksize = AES_BLOCK_SIZE,
2083357fb605SHoria Geanta 			.cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC,
2084357fb605SHoria Geanta 			.cra_aead = {
2085357fb605SHoria Geanta 				.ivsize = AES_BLOCK_SIZE,
2086357fb605SHoria Geanta 				.maxauthsize = SHA512_DIGEST_SIZE,
2087357fb605SHoria Geanta 			}
2088357fb605SHoria Geanta 		},
2089357fb605SHoria Geanta 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
2090357fb605SHoria Geanta 			             DESC_HDR_SEL0_AESU |
2091357fb605SHoria Geanta 		                     DESC_HDR_MODE0_AESU_CBC |
2092357fb605SHoria Geanta 		                     DESC_HDR_SEL1_MDEUB |
2093357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_INIT |
2094357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_PAD |
2095357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEUB_SHA512_HMAC,
2096357fb605SHoria Geanta 	},
2097357fb605SHoria Geanta 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2098357fb605SHoria Geanta 		.alg.crypto = {
2099357fb605SHoria Geanta 			.cra_name = "authenc(hmac(sha512),cbc(des3_ede))",
2100357fb605SHoria Geanta 			.cra_driver_name = "authenc-hmac-sha512-cbc-3des-talitos",
2101357fb605SHoria Geanta 			.cra_blocksize = DES3_EDE_BLOCK_SIZE,
2102357fb605SHoria Geanta 			.cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC,
2103357fb605SHoria Geanta 			.cra_aead = {
2104357fb605SHoria Geanta 				.ivsize = DES3_EDE_BLOCK_SIZE,
2105357fb605SHoria Geanta 				.maxauthsize = SHA512_DIGEST_SIZE,
2106357fb605SHoria Geanta 			}
2107357fb605SHoria Geanta 		},
2108357fb605SHoria Geanta 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
2109357fb605SHoria Geanta 			             DESC_HDR_SEL0_DEU |
2110357fb605SHoria Geanta 		                     DESC_HDR_MODE0_DEU_CBC |
2111357fb605SHoria Geanta 		                     DESC_HDR_MODE0_DEU_3DES |
2112357fb605SHoria Geanta 		                     DESC_HDR_SEL1_MDEUB |
2113357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_INIT |
2114357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_PAD |
2115357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEUB_SHA512_HMAC,
2116357fb605SHoria Geanta 	},
2117357fb605SHoria Geanta 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2118357fb605SHoria Geanta 		.alg.crypto = {
211956af8cd4SLee Nipper 			.cra_name = "authenc(hmac(md5),cbc(aes))",
212056af8cd4SLee Nipper 			.cra_driver_name = "authenc-hmac-md5-cbc-aes-talitos",
212156af8cd4SLee Nipper 			.cra_blocksize = AES_BLOCK_SIZE,
212256af8cd4SLee Nipper 			.cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC,
212356af8cd4SLee Nipper 			.cra_aead = {
21243952f17eSLee Nipper 				.ivsize = AES_BLOCK_SIZE,
21253952f17eSLee Nipper 				.maxauthsize = MD5_DIGEST_SIZE,
212656af8cd4SLee Nipper 			}
21273952f17eSLee Nipper 		},
21283952f17eSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
21293952f17eSLee Nipper 			             DESC_HDR_SEL0_AESU |
21303952f17eSLee Nipper 		                     DESC_HDR_MODE0_AESU_CBC |
21313952f17eSLee Nipper 		                     DESC_HDR_SEL1_MDEUA |
21323952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_INIT |
21333952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_PAD |
21343952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_MD5_HMAC,
21353952f17eSLee Nipper 	},
2136d5e4aaefSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2137d5e4aaefSLee Nipper 		.alg.crypto = {
213856af8cd4SLee Nipper 			.cra_name = "authenc(hmac(md5),cbc(des3_ede))",
213956af8cd4SLee Nipper 			.cra_driver_name = "authenc-hmac-md5-cbc-3des-talitos",
214056af8cd4SLee Nipper 			.cra_blocksize = DES3_EDE_BLOCK_SIZE,
214156af8cd4SLee Nipper 			.cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC,
214256af8cd4SLee Nipper 			.cra_aead = {
21433952f17eSLee Nipper 				.ivsize = DES3_EDE_BLOCK_SIZE,
21443952f17eSLee Nipper 				.maxauthsize = MD5_DIGEST_SIZE,
214556af8cd4SLee Nipper 			}
21463952f17eSLee Nipper 		},
21473952f17eSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
21483952f17eSLee Nipper 			             DESC_HDR_SEL0_DEU |
21493952f17eSLee Nipper 		                     DESC_HDR_MODE0_DEU_CBC |
21503952f17eSLee Nipper 		                     DESC_HDR_MODE0_DEU_3DES |
21513952f17eSLee Nipper 		                     DESC_HDR_SEL1_MDEUA |
21523952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_INIT |
21533952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_PAD |
21543952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_MD5_HMAC,
21554de9d0b5SLee Nipper 	},
21564de9d0b5SLee Nipper 	/* ABLKCIPHER algorithms. */
2157d5e4aaefSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_ABLKCIPHER,
2158d5e4aaefSLee Nipper 		.alg.crypto = {
21594de9d0b5SLee Nipper 			.cra_name = "cbc(aes)",
21604de9d0b5SLee Nipper 			.cra_driver_name = "cbc-aes-talitos",
21614de9d0b5SLee Nipper 			.cra_blocksize = AES_BLOCK_SIZE,
21624de9d0b5SLee Nipper 			.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
21634de9d0b5SLee Nipper                                      CRYPTO_ALG_ASYNC,
21644de9d0b5SLee Nipper 			.cra_ablkcipher = {
21654de9d0b5SLee Nipper 				.min_keysize = AES_MIN_KEY_SIZE,
21664de9d0b5SLee Nipper 				.max_keysize = AES_MAX_KEY_SIZE,
21674de9d0b5SLee Nipper 				.ivsize = AES_BLOCK_SIZE,
21684de9d0b5SLee Nipper 			}
21694de9d0b5SLee Nipper 		},
21704de9d0b5SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
21714de9d0b5SLee Nipper 				     DESC_HDR_SEL0_AESU |
21724de9d0b5SLee Nipper 				     DESC_HDR_MODE0_AESU_CBC,
21734de9d0b5SLee Nipper 	},
2174d5e4aaefSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_ABLKCIPHER,
2175d5e4aaefSLee Nipper 		.alg.crypto = {
21764de9d0b5SLee Nipper 			.cra_name = "cbc(des3_ede)",
21774de9d0b5SLee Nipper 			.cra_driver_name = "cbc-3des-talitos",
21784de9d0b5SLee Nipper 			.cra_blocksize = DES3_EDE_BLOCK_SIZE,
21794de9d0b5SLee Nipper 			.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
21804de9d0b5SLee Nipper                                      CRYPTO_ALG_ASYNC,
21814de9d0b5SLee Nipper 			.cra_ablkcipher = {
21824de9d0b5SLee Nipper 				.min_keysize = DES3_EDE_KEY_SIZE,
21834de9d0b5SLee Nipper 				.max_keysize = DES3_EDE_KEY_SIZE,
21844de9d0b5SLee Nipper 				.ivsize = DES3_EDE_BLOCK_SIZE,
21854de9d0b5SLee Nipper 			}
21864de9d0b5SLee Nipper 		},
21874de9d0b5SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
21884de9d0b5SLee Nipper 			             DESC_HDR_SEL0_DEU |
21894de9d0b5SLee Nipper 		                     DESC_HDR_MODE0_DEU_CBC |
21904de9d0b5SLee Nipper 		                     DESC_HDR_MODE0_DEU_3DES,
2191497f2e6bSLee Nipper 	},
2192497f2e6bSLee Nipper 	/* AHASH algorithms. */
2193497f2e6bSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
2194497f2e6bSLee Nipper 		.alg.hash = {
2195497f2e6bSLee Nipper 			.halg.digestsize = MD5_DIGEST_SIZE,
2196497f2e6bSLee Nipper 			.halg.base = {
2197497f2e6bSLee Nipper 				.cra_name = "md5",
2198497f2e6bSLee Nipper 				.cra_driver_name = "md5-talitos",
2199b3988618SMartin Hicks 				.cra_blocksize = MD5_HMAC_BLOCK_SIZE,
2200497f2e6bSLee Nipper 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
2201497f2e6bSLee Nipper 					     CRYPTO_ALG_ASYNC,
22029c4a7965SKim Phillips 			}
2203497f2e6bSLee Nipper 		},
2204497f2e6bSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
2205497f2e6bSLee Nipper 				     DESC_HDR_SEL0_MDEUA |
2206497f2e6bSLee Nipper 				     DESC_HDR_MODE0_MDEU_MD5,
2207497f2e6bSLee Nipper 	},
2208497f2e6bSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
2209497f2e6bSLee Nipper 		.alg.hash = {
2210497f2e6bSLee Nipper 			.halg.digestsize = SHA1_DIGEST_SIZE,
2211497f2e6bSLee Nipper 			.halg.base = {
2212497f2e6bSLee Nipper 				.cra_name = "sha1",
2213497f2e6bSLee Nipper 				.cra_driver_name = "sha1-talitos",
2214497f2e6bSLee Nipper 				.cra_blocksize = SHA1_BLOCK_SIZE,
2215497f2e6bSLee Nipper 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
2216497f2e6bSLee Nipper 					     CRYPTO_ALG_ASYNC,
2217497f2e6bSLee Nipper 			}
2218497f2e6bSLee Nipper 		},
2219497f2e6bSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
2220497f2e6bSLee Nipper 				     DESC_HDR_SEL0_MDEUA |
2221497f2e6bSLee Nipper 				     DESC_HDR_MODE0_MDEU_SHA1,
2222497f2e6bSLee Nipper 	},
2223497f2e6bSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
2224497f2e6bSLee Nipper 		.alg.hash = {
222560f208d7SKim Phillips 			.halg.digestsize = SHA224_DIGEST_SIZE,
222660f208d7SKim Phillips 			.halg.base = {
222760f208d7SKim Phillips 				.cra_name = "sha224",
222860f208d7SKim Phillips 				.cra_driver_name = "sha224-talitos",
222960f208d7SKim Phillips 				.cra_blocksize = SHA224_BLOCK_SIZE,
223060f208d7SKim Phillips 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
223160f208d7SKim Phillips 					     CRYPTO_ALG_ASYNC,
223260f208d7SKim Phillips 			}
223360f208d7SKim Phillips 		},
223460f208d7SKim Phillips 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
223560f208d7SKim Phillips 				     DESC_HDR_SEL0_MDEUA |
223660f208d7SKim Phillips 				     DESC_HDR_MODE0_MDEU_SHA224,
223760f208d7SKim Phillips 	},
223860f208d7SKim Phillips 	{	.type = CRYPTO_ALG_TYPE_AHASH,
223960f208d7SKim Phillips 		.alg.hash = {
2240497f2e6bSLee Nipper 			.halg.digestsize = SHA256_DIGEST_SIZE,
2241497f2e6bSLee Nipper 			.halg.base = {
2242497f2e6bSLee Nipper 				.cra_name = "sha256",
2243497f2e6bSLee Nipper 				.cra_driver_name = "sha256-talitos",
2244497f2e6bSLee Nipper 				.cra_blocksize = SHA256_BLOCK_SIZE,
2245497f2e6bSLee Nipper 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
2246497f2e6bSLee Nipper 					     CRYPTO_ALG_ASYNC,
2247497f2e6bSLee Nipper 			}
2248497f2e6bSLee Nipper 		},
2249497f2e6bSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
2250497f2e6bSLee Nipper 				     DESC_HDR_SEL0_MDEUA |
2251497f2e6bSLee Nipper 				     DESC_HDR_MODE0_MDEU_SHA256,
2252497f2e6bSLee Nipper 	},
2253497f2e6bSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
2254497f2e6bSLee Nipper 		.alg.hash = {
2255497f2e6bSLee Nipper 			.halg.digestsize = SHA384_DIGEST_SIZE,
2256497f2e6bSLee Nipper 			.halg.base = {
2257497f2e6bSLee Nipper 				.cra_name = "sha384",
2258497f2e6bSLee Nipper 				.cra_driver_name = "sha384-talitos",
2259497f2e6bSLee Nipper 				.cra_blocksize = SHA384_BLOCK_SIZE,
2260497f2e6bSLee Nipper 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
2261497f2e6bSLee Nipper 					     CRYPTO_ALG_ASYNC,
2262497f2e6bSLee Nipper 			}
2263497f2e6bSLee Nipper 		},
2264497f2e6bSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
2265497f2e6bSLee Nipper 				     DESC_HDR_SEL0_MDEUB |
2266497f2e6bSLee Nipper 				     DESC_HDR_MODE0_MDEUB_SHA384,
2267497f2e6bSLee Nipper 	},
2268497f2e6bSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
2269497f2e6bSLee Nipper 		.alg.hash = {
2270497f2e6bSLee Nipper 			.halg.digestsize = SHA512_DIGEST_SIZE,
2271497f2e6bSLee Nipper 			.halg.base = {
2272497f2e6bSLee Nipper 				.cra_name = "sha512",
2273497f2e6bSLee Nipper 				.cra_driver_name = "sha512-talitos",
2274497f2e6bSLee Nipper 				.cra_blocksize = SHA512_BLOCK_SIZE,
2275497f2e6bSLee Nipper 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
2276497f2e6bSLee Nipper 					     CRYPTO_ALG_ASYNC,
2277497f2e6bSLee Nipper 			}
2278497f2e6bSLee Nipper 		},
2279497f2e6bSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
2280497f2e6bSLee Nipper 				     DESC_HDR_SEL0_MDEUB |
2281497f2e6bSLee Nipper 				     DESC_HDR_MODE0_MDEUB_SHA512,
2282497f2e6bSLee Nipper 	},
228379b3a418SLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
228479b3a418SLee Nipper 		.alg.hash = {
228579b3a418SLee Nipper 			.halg.digestsize = MD5_DIGEST_SIZE,
228679b3a418SLee Nipper 			.halg.base = {
228779b3a418SLee Nipper 				.cra_name = "hmac(md5)",
228879b3a418SLee Nipper 				.cra_driver_name = "hmac-md5-talitos",
2289b3988618SMartin Hicks 				.cra_blocksize = MD5_HMAC_BLOCK_SIZE,
229079b3a418SLee Nipper 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
229179b3a418SLee Nipper 					     CRYPTO_ALG_ASYNC,
229279b3a418SLee Nipper 			}
229379b3a418SLee Nipper 		},
229479b3a418SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
229579b3a418SLee Nipper 				     DESC_HDR_SEL0_MDEUA |
229679b3a418SLee Nipper 				     DESC_HDR_MODE0_MDEU_MD5,
229779b3a418SLee Nipper 	},
229879b3a418SLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
229979b3a418SLee Nipper 		.alg.hash = {
230079b3a418SLee Nipper 			.halg.digestsize = SHA1_DIGEST_SIZE,
230179b3a418SLee Nipper 			.halg.base = {
230279b3a418SLee Nipper 				.cra_name = "hmac(sha1)",
230379b3a418SLee Nipper 				.cra_driver_name = "hmac-sha1-talitos",
230479b3a418SLee Nipper 				.cra_blocksize = SHA1_BLOCK_SIZE,
230579b3a418SLee Nipper 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
230679b3a418SLee Nipper 					     CRYPTO_ALG_ASYNC,
230779b3a418SLee Nipper 			}
230879b3a418SLee Nipper 		},
230979b3a418SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
231079b3a418SLee Nipper 				     DESC_HDR_SEL0_MDEUA |
231179b3a418SLee Nipper 				     DESC_HDR_MODE0_MDEU_SHA1,
231279b3a418SLee Nipper 	},
231379b3a418SLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
231479b3a418SLee Nipper 		.alg.hash = {
231579b3a418SLee Nipper 			.halg.digestsize = SHA224_DIGEST_SIZE,
231679b3a418SLee Nipper 			.halg.base = {
231779b3a418SLee Nipper 				.cra_name = "hmac(sha224)",
231879b3a418SLee Nipper 				.cra_driver_name = "hmac-sha224-talitos",
231979b3a418SLee Nipper 				.cra_blocksize = SHA224_BLOCK_SIZE,
232079b3a418SLee Nipper 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
232179b3a418SLee Nipper 					     CRYPTO_ALG_ASYNC,
232279b3a418SLee Nipper 			}
232379b3a418SLee Nipper 		},
232479b3a418SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
232579b3a418SLee Nipper 				     DESC_HDR_SEL0_MDEUA |
232679b3a418SLee Nipper 				     DESC_HDR_MODE0_MDEU_SHA224,
232779b3a418SLee Nipper 	},
232879b3a418SLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
232979b3a418SLee Nipper 		.alg.hash = {
233079b3a418SLee Nipper 			.halg.digestsize = SHA256_DIGEST_SIZE,
233179b3a418SLee Nipper 			.halg.base = {
233279b3a418SLee Nipper 				.cra_name = "hmac(sha256)",
233379b3a418SLee Nipper 				.cra_driver_name = "hmac-sha256-talitos",
233479b3a418SLee Nipper 				.cra_blocksize = SHA256_BLOCK_SIZE,
233579b3a418SLee Nipper 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
233679b3a418SLee Nipper 					     CRYPTO_ALG_ASYNC,
233779b3a418SLee Nipper 			}
233879b3a418SLee Nipper 		},
233979b3a418SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
234079b3a418SLee Nipper 				     DESC_HDR_SEL0_MDEUA |
234179b3a418SLee Nipper 				     DESC_HDR_MODE0_MDEU_SHA256,
234279b3a418SLee Nipper 	},
234379b3a418SLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
234479b3a418SLee Nipper 		.alg.hash = {
234579b3a418SLee Nipper 			.halg.digestsize = SHA384_DIGEST_SIZE,
234679b3a418SLee Nipper 			.halg.base = {
234779b3a418SLee Nipper 				.cra_name = "hmac(sha384)",
234879b3a418SLee Nipper 				.cra_driver_name = "hmac-sha384-talitos",
234979b3a418SLee Nipper 				.cra_blocksize = SHA384_BLOCK_SIZE,
235079b3a418SLee Nipper 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
235179b3a418SLee Nipper 					     CRYPTO_ALG_ASYNC,
235279b3a418SLee Nipper 			}
235379b3a418SLee Nipper 		},
235479b3a418SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
235579b3a418SLee Nipper 				     DESC_HDR_SEL0_MDEUB |
235679b3a418SLee Nipper 				     DESC_HDR_MODE0_MDEUB_SHA384,
235779b3a418SLee Nipper 	},
235879b3a418SLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
235979b3a418SLee Nipper 		.alg.hash = {
236079b3a418SLee Nipper 			.halg.digestsize = SHA512_DIGEST_SIZE,
236179b3a418SLee Nipper 			.halg.base = {
236279b3a418SLee Nipper 				.cra_name = "hmac(sha512)",
236379b3a418SLee Nipper 				.cra_driver_name = "hmac-sha512-talitos",
236479b3a418SLee Nipper 				.cra_blocksize = SHA512_BLOCK_SIZE,
236579b3a418SLee Nipper 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
236679b3a418SLee Nipper 					     CRYPTO_ALG_ASYNC,
236779b3a418SLee Nipper 			}
236879b3a418SLee Nipper 		},
236979b3a418SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
237079b3a418SLee Nipper 				     DESC_HDR_SEL0_MDEUB |
237179b3a418SLee Nipper 				     DESC_HDR_MODE0_MDEUB_SHA512,
237279b3a418SLee Nipper 	}
23739c4a7965SKim Phillips };
23749c4a7965SKim Phillips 
23759c4a7965SKim Phillips struct talitos_crypto_alg {
23769c4a7965SKim Phillips 	struct list_head entry;
23779c4a7965SKim Phillips 	struct device *dev;
2378acbf7c62SLee Nipper 	struct talitos_alg_template algt;
23799c4a7965SKim Phillips };
23809c4a7965SKim Phillips 
23819c4a7965SKim Phillips static int talitos_cra_init(struct crypto_tfm *tfm)
23829c4a7965SKim Phillips {
23839c4a7965SKim Phillips 	struct crypto_alg *alg = tfm->__crt_alg;
238419bbbc63SKim Phillips 	struct talitos_crypto_alg *talitos_alg;
23859c4a7965SKim Phillips 	struct talitos_ctx *ctx = crypto_tfm_ctx(tfm);
23865228f0f7SKim Phillips 	struct talitos_private *priv;
23879c4a7965SKim Phillips 
2388497f2e6bSLee Nipper 	if ((alg->cra_flags & CRYPTO_ALG_TYPE_MASK) == CRYPTO_ALG_TYPE_AHASH)
2389497f2e6bSLee Nipper 		talitos_alg = container_of(__crypto_ahash_alg(alg),
2390497f2e6bSLee Nipper 					   struct talitos_crypto_alg,
2391497f2e6bSLee Nipper 					   algt.alg.hash);
2392497f2e6bSLee Nipper 	else
2393acbf7c62SLee Nipper 		talitos_alg = container_of(alg, struct talitos_crypto_alg,
2394acbf7c62SLee Nipper 					   algt.alg.crypto);
239519bbbc63SKim Phillips 
23969c4a7965SKim Phillips 	/* update context with ptr to dev */
23979c4a7965SKim Phillips 	ctx->dev = talitos_alg->dev;
239819bbbc63SKim Phillips 
23995228f0f7SKim Phillips 	/* assign SEC channel to tfm in round-robin fashion */
24005228f0f7SKim Phillips 	priv = dev_get_drvdata(ctx->dev);
24015228f0f7SKim Phillips 	ctx->ch = atomic_inc_return(&priv->last_chan) &
24025228f0f7SKim Phillips 		  (priv->num_channels - 1);
24035228f0f7SKim Phillips 
24049c4a7965SKim Phillips 	/* copy descriptor header template value */
2405acbf7c62SLee Nipper 	ctx->desc_hdr_template = talitos_alg->algt.desc_hdr_template;
24069c4a7965SKim Phillips 
2407602dba5aSKim Phillips 	/* select done notification */
2408602dba5aSKim Phillips 	ctx->desc_hdr_template |= DESC_HDR_DONE_NOTIFY;
2409602dba5aSKim Phillips 
2410497f2e6bSLee Nipper 	return 0;
2411497f2e6bSLee Nipper }
2412497f2e6bSLee Nipper 
2413497f2e6bSLee Nipper static int talitos_cra_init_aead(struct crypto_tfm *tfm)
2414497f2e6bSLee Nipper {
2415497f2e6bSLee Nipper 	struct talitos_ctx *ctx = crypto_tfm_ctx(tfm);
2416497f2e6bSLee Nipper 
2417497f2e6bSLee Nipper 	talitos_cra_init(tfm);
24189c4a7965SKim Phillips 
24199c4a7965SKim Phillips 	/* random first IV */
242070bcaca7SLee Nipper 	get_random_bytes(ctx->iv, TALITOS_MAX_IV_LENGTH);
24219c4a7965SKim Phillips 
24229c4a7965SKim Phillips 	return 0;
24239c4a7965SKim Phillips }
24249c4a7965SKim Phillips 
2425497f2e6bSLee Nipper static int talitos_cra_init_ahash(struct crypto_tfm *tfm)
2426497f2e6bSLee Nipper {
2427497f2e6bSLee Nipper 	struct talitos_ctx *ctx = crypto_tfm_ctx(tfm);
2428497f2e6bSLee Nipper 
2429497f2e6bSLee Nipper 	talitos_cra_init(tfm);
2430497f2e6bSLee Nipper 
2431497f2e6bSLee Nipper 	ctx->keylen = 0;
2432497f2e6bSLee Nipper 	crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm),
2433497f2e6bSLee Nipper 				 sizeof(struct talitos_ahash_req_ctx));
2434497f2e6bSLee Nipper 
2435497f2e6bSLee Nipper 	return 0;
2436497f2e6bSLee Nipper }
2437497f2e6bSLee Nipper 
24389c4a7965SKim Phillips /*
24399c4a7965SKim Phillips  * given the alg's descriptor header template, determine whether descriptor
24409c4a7965SKim Phillips  * type and primary/secondary execution units required match the hw
24419c4a7965SKim Phillips  * capabilities description provided in the device tree node.
24429c4a7965SKim Phillips  */
24439c4a7965SKim Phillips static int hw_supports(struct device *dev, __be32 desc_hdr_template)
24449c4a7965SKim Phillips {
24459c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
24469c4a7965SKim Phillips 	int ret;
24479c4a7965SKim Phillips 
24489c4a7965SKim Phillips 	ret = (1 << DESC_TYPE(desc_hdr_template) & priv->desc_types) &&
24499c4a7965SKim Phillips 	      (1 << PRIMARY_EU(desc_hdr_template) & priv->exec_units);
24509c4a7965SKim Phillips 
24519c4a7965SKim Phillips 	if (SECONDARY_EU(desc_hdr_template))
24529c4a7965SKim Phillips 		ret = ret && (1 << SECONDARY_EU(desc_hdr_template)
24539c4a7965SKim Phillips 		              & priv->exec_units);
24549c4a7965SKim Phillips 
24559c4a7965SKim Phillips 	return ret;
24569c4a7965SKim Phillips }
24579c4a7965SKim Phillips 
24582dc11581SGrant Likely static int talitos_remove(struct platform_device *ofdev)
24599c4a7965SKim Phillips {
24609c4a7965SKim Phillips 	struct device *dev = &ofdev->dev;
24619c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
24629c4a7965SKim Phillips 	struct talitos_crypto_alg *t_alg, *n;
24639c4a7965SKim Phillips 	int i;
24649c4a7965SKim Phillips 
24659c4a7965SKim Phillips 	list_for_each_entry_safe(t_alg, n, &priv->alg_list, entry) {
2466acbf7c62SLee Nipper 		switch (t_alg->algt.type) {
2467acbf7c62SLee Nipper 		case CRYPTO_ALG_TYPE_ABLKCIPHER:
2468acbf7c62SLee Nipper 		case CRYPTO_ALG_TYPE_AEAD:
2469acbf7c62SLee Nipper 			crypto_unregister_alg(&t_alg->algt.alg.crypto);
2470acbf7c62SLee Nipper 			break;
2471acbf7c62SLee Nipper 		case CRYPTO_ALG_TYPE_AHASH:
2472acbf7c62SLee Nipper 			crypto_unregister_ahash(&t_alg->algt.alg.hash);
2473acbf7c62SLee Nipper 			break;
2474acbf7c62SLee Nipper 		}
24759c4a7965SKim Phillips 		list_del(&t_alg->entry);
24769c4a7965SKim Phillips 		kfree(t_alg);
24779c4a7965SKim Phillips 	}
24789c4a7965SKim Phillips 
24799c4a7965SKim Phillips 	if (hw_supports(dev, DESC_HDR_SEL0_RNG))
24809c4a7965SKim Phillips 		talitos_unregister_rng(dev);
24819c4a7965SKim Phillips 
24829c4a7965SKim Phillips 	for (i = 0; i < priv->num_channels; i++)
24834b992628SKim Phillips 		kfree(priv->chan[i].fifo);
24849c4a7965SKim Phillips 
24854b992628SKim Phillips 	kfree(priv->chan);
24869c4a7965SKim Phillips 
2487c3e337f8SKim Phillips 	for (i = 0; i < 2; i++)
24882cdba3cfSKim Phillips 		if (priv->irq[i]) {
2489c3e337f8SKim Phillips 			free_irq(priv->irq[i], dev);
2490c3e337f8SKim Phillips 			irq_dispose_mapping(priv->irq[i]);
24919c4a7965SKim Phillips 		}
24929c4a7965SKim Phillips 
2493c3e337f8SKim Phillips 	tasklet_kill(&priv->done_task[0]);
24942cdba3cfSKim Phillips 	if (priv->irq[1])
2495c3e337f8SKim Phillips 		tasklet_kill(&priv->done_task[1]);
24969c4a7965SKim Phillips 
24979c4a7965SKim Phillips 	iounmap(priv->reg);
24989c4a7965SKim Phillips 
24999c4a7965SKim Phillips 	kfree(priv);
25009c4a7965SKim Phillips 
25019c4a7965SKim Phillips 	return 0;
25029c4a7965SKim Phillips }
25039c4a7965SKim Phillips 
25049c4a7965SKim Phillips static struct talitos_crypto_alg *talitos_alg_alloc(struct device *dev,
25059c4a7965SKim Phillips 						    struct talitos_alg_template
25069c4a7965SKim Phillips 						           *template)
25079c4a7965SKim Phillips {
250860f208d7SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
25099c4a7965SKim Phillips 	struct talitos_crypto_alg *t_alg;
25109c4a7965SKim Phillips 	struct crypto_alg *alg;
25119c4a7965SKim Phillips 
25129c4a7965SKim Phillips 	t_alg = kzalloc(sizeof(struct talitos_crypto_alg), GFP_KERNEL);
25139c4a7965SKim Phillips 	if (!t_alg)
25149c4a7965SKim Phillips 		return ERR_PTR(-ENOMEM);
25159c4a7965SKim Phillips 
2516acbf7c62SLee Nipper 	t_alg->algt = *template;
2517acbf7c62SLee Nipper 
2518acbf7c62SLee Nipper 	switch (t_alg->algt.type) {
2519acbf7c62SLee Nipper 	case CRYPTO_ALG_TYPE_ABLKCIPHER:
2520497f2e6bSLee Nipper 		alg = &t_alg->algt.alg.crypto;
2521497f2e6bSLee Nipper 		alg->cra_init = talitos_cra_init;
2522d4cd3283SKim Phillips 		alg->cra_type = &crypto_ablkcipher_type;
2523b286e003SKim Phillips 		alg->cra_ablkcipher.setkey = ablkcipher_setkey;
2524b286e003SKim Phillips 		alg->cra_ablkcipher.encrypt = ablkcipher_encrypt;
2525b286e003SKim Phillips 		alg->cra_ablkcipher.decrypt = ablkcipher_decrypt;
2526b286e003SKim Phillips 		alg->cra_ablkcipher.geniv = "eseqiv";
2527497f2e6bSLee Nipper 		break;
2528acbf7c62SLee Nipper 	case CRYPTO_ALG_TYPE_AEAD:
2529acbf7c62SLee Nipper 		alg = &t_alg->algt.alg.crypto;
2530497f2e6bSLee Nipper 		alg->cra_init = talitos_cra_init_aead;
2531d4cd3283SKim Phillips 		alg->cra_type = &crypto_aead_type;
2532b286e003SKim Phillips 		alg->cra_aead.setkey = aead_setkey;
2533b286e003SKim Phillips 		alg->cra_aead.setauthsize = aead_setauthsize;
2534b286e003SKim Phillips 		alg->cra_aead.encrypt = aead_encrypt;
2535b286e003SKim Phillips 		alg->cra_aead.decrypt = aead_decrypt;
2536b286e003SKim Phillips 		alg->cra_aead.givencrypt = aead_givencrypt;
2537b286e003SKim Phillips 		alg->cra_aead.geniv = "<built-in>";
2538acbf7c62SLee Nipper 		break;
2539acbf7c62SLee Nipper 	case CRYPTO_ALG_TYPE_AHASH:
2540acbf7c62SLee Nipper 		alg = &t_alg->algt.alg.hash.halg.base;
2541497f2e6bSLee Nipper 		alg->cra_init = talitos_cra_init_ahash;
2542d4cd3283SKim Phillips 		alg->cra_type = &crypto_ahash_type;
2543b286e003SKim Phillips 		t_alg->algt.alg.hash.init = ahash_init;
2544b286e003SKim Phillips 		t_alg->algt.alg.hash.update = ahash_update;
2545b286e003SKim Phillips 		t_alg->algt.alg.hash.final = ahash_final;
2546b286e003SKim Phillips 		t_alg->algt.alg.hash.finup = ahash_finup;
2547b286e003SKim Phillips 		t_alg->algt.alg.hash.digest = ahash_digest;
2548b286e003SKim Phillips 		t_alg->algt.alg.hash.setkey = ahash_setkey;
2549b286e003SKim Phillips 
255079b3a418SLee Nipper 		if (!(priv->features & TALITOS_FTR_HMAC_OK) &&
25510b2730d8SKim Phillips 		    !strncmp(alg->cra_name, "hmac", 4)) {
25520b2730d8SKim Phillips 			kfree(t_alg);
255379b3a418SLee Nipper 			return ERR_PTR(-ENOTSUPP);
25540b2730d8SKim Phillips 		}
255560f208d7SKim Phillips 		if (!(priv->features & TALITOS_FTR_SHA224_HWINIT) &&
255679b3a418SLee Nipper 		    (!strcmp(alg->cra_name, "sha224") ||
255779b3a418SLee Nipper 		     !strcmp(alg->cra_name, "hmac(sha224)"))) {
255860f208d7SKim Phillips 			t_alg->algt.alg.hash.init = ahash_init_sha224_swinit;
255960f208d7SKim Phillips 			t_alg->algt.desc_hdr_template =
256060f208d7SKim Phillips 					DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
256160f208d7SKim Phillips 					DESC_HDR_SEL0_MDEUA |
256260f208d7SKim Phillips 					DESC_HDR_MODE0_MDEU_SHA256;
256360f208d7SKim Phillips 		}
2564497f2e6bSLee Nipper 		break;
25651d11911aSKim Phillips 	default:
25661d11911aSKim Phillips 		dev_err(dev, "unknown algorithm type %d\n", t_alg->algt.type);
25671d11911aSKim Phillips 		return ERR_PTR(-EINVAL);
2568acbf7c62SLee Nipper 	}
25699c4a7965SKim Phillips 
25709c4a7965SKim Phillips 	alg->cra_module = THIS_MODULE;
25719c4a7965SKim Phillips 	alg->cra_priority = TALITOS_CRA_PRIORITY;
25729c4a7965SKim Phillips 	alg->cra_alignmask = 0;
25739c4a7965SKim Phillips 	alg->cra_ctxsize = sizeof(struct talitos_ctx);
2574d912bb76SNikos Mavrogiannopoulos 	alg->cra_flags |= CRYPTO_ALG_KERN_DRIVER_ONLY;
25759c4a7965SKim Phillips 
25769c4a7965SKim Phillips 	t_alg->dev = dev;
25779c4a7965SKim Phillips 
25789c4a7965SKim Phillips 	return t_alg;
25799c4a7965SKim Phillips }
25809c4a7965SKim Phillips 
2581c3e337f8SKim Phillips static int talitos_probe_irq(struct platform_device *ofdev)
2582c3e337f8SKim Phillips {
2583c3e337f8SKim Phillips 	struct device *dev = &ofdev->dev;
2584c3e337f8SKim Phillips 	struct device_node *np = ofdev->dev.of_node;
2585c3e337f8SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
2586c3e337f8SKim Phillips 	int err;
2587c3e337f8SKim Phillips 
2588c3e337f8SKim Phillips 	priv->irq[0] = irq_of_parse_and_map(np, 0);
25892cdba3cfSKim Phillips 	if (!priv->irq[0]) {
2590c3e337f8SKim Phillips 		dev_err(dev, "failed to map irq\n");
2591c3e337f8SKim Phillips 		return -EINVAL;
2592c3e337f8SKim Phillips 	}
2593c3e337f8SKim Phillips 
2594c3e337f8SKim Phillips 	priv->irq[1] = irq_of_parse_and_map(np, 1);
2595c3e337f8SKim Phillips 
2596c3e337f8SKim Phillips 	/* get the primary irq line */
25972cdba3cfSKim Phillips 	if (!priv->irq[1]) {
2598c3e337f8SKim Phillips 		err = request_irq(priv->irq[0], talitos_interrupt_4ch, 0,
2599c3e337f8SKim Phillips 				  dev_driver_string(dev), dev);
2600c3e337f8SKim Phillips 		goto primary_out;
2601c3e337f8SKim Phillips 	}
2602c3e337f8SKim Phillips 
2603c3e337f8SKim Phillips 	err = request_irq(priv->irq[0], talitos_interrupt_ch0_2, 0,
2604c3e337f8SKim Phillips 			  dev_driver_string(dev), dev);
2605c3e337f8SKim Phillips 	if (err)
2606c3e337f8SKim Phillips 		goto primary_out;
2607c3e337f8SKim Phillips 
2608c3e337f8SKim Phillips 	/* get the secondary irq line */
2609c3e337f8SKim Phillips 	err = request_irq(priv->irq[1], talitos_interrupt_ch1_3, 0,
2610c3e337f8SKim Phillips 			  dev_driver_string(dev), dev);
2611c3e337f8SKim Phillips 	if (err) {
2612c3e337f8SKim Phillips 		dev_err(dev, "failed to request secondary irq\n");
2613c3e337f8SKim Phillips 		irq_dispose_mapping(priv->irq[1]);
26142cdba3cfSKim Phillips 		priv->irq[1] = 0;
2615c3e337f8SKim Phillips 	}
2616c3e337f8SKim Phillips 
2617c3e337f8SKim Phillips 	return err;
2618c3e337f8SKim Phillips 
2619c3e337f8SKim Phillips primary_out:
2620c3e337f8SKim Phillips 	if (err) {
2621c3e337f8SKim Phillips 		dev_err(dev, "failed to request primary irq\n");
2622c3e337f8SKim Phillips 		irq_dispose_mapping(priv->irq[0]);
26232cdba3cfSKim Phillips 		priv->irq[0] = 0;
2624c3e337f8SKim Phillips 	}
2625c3e337f8SKim Phillips 
2626c3e337f8SKim Phillips 	return err;
2627c3e337f8SKim Phillips }
2628c3e337f8SKim Phillips 
26291c48a5c9SGrant Likely static int talitos_probe(struct platform_device *ofdev)
26309c4a7965SKim Phillips {
26319c4a7965SKim Phillips 	struct device *dev = &ofdev->dev;
263261c7a080SGrant Likely 	struct device_node *np = ofdev->dev.of_node;
26339c4a7965SKim Phillips 	struct talitos_private *priv;
26349c4a7965SKim Phillips 	const unsigned int *prop;
26359c4a7965SKim Phillips 	int i, err;
26369c4a7965SKim Phillips 
26379c4a7965SKim Phillips 	priv = kzalloc(sizeof(struct talitos_private), GFP_KERNEL);
26389c4a7965SKim Phillips 	if (!priv)
26399c4a7965SKim Phillips 		return -ENOMEM;
26409c4a7965SKim Phillips 
2641f3de9cb1SKevin Hao 	INIT_LIST_HEAD(&priv->alg_list);
2642f3de9cb1SKevin Hao 
26439c4a7965SKim Phillips 	dev_set_drvdata(dev, priv);
26449c4a7965SKim Phillips 
26459c4a7965SKim Phillips 	priv->ofdev = ofdev;
26469c4a7965SKim Phillips 
2647511d63cbSHoria Geanta 	spin_lock_init(&priv->reg_lock);
2648511d63cbSHoria Geanta 
2649c3e337f8SKim Phillips 	err = talitos_probe_irq(ofdev);
2650c3e337f8SKim Phillips 	if (err)
2651c3e337f8SKim Phillips 		goto err_out;
2652c3e337f8SKim Phillips 
26532cdba3cfSKim Phillips 	if (!priv->irq[1]) {
2654c3e337f8SKim Phillips 		tasklet_init(&priv->done_task[0], talitos_done_4ch,
2655c3e337f8SKim Phillips 			     (unsigned long)dev);
2656c3e337f8SKim Phillips 	} else {
2657c3e337f8SKim Phillips 		tasklet_init(&priv->done_task[0], talitos_done_ch0_2,
2658c3e337f8SKim Phillips 			     (unsigned long)dev);
2659c3e337f8SKim Phillips 		tasklet_init(&priv->done_task[1], talitos_done_ch1_3,
2660c3e337f8SKim Phillips 			     (unsigned long)dev);
2661c3e337f8SKim Phillips 	}
26629c4a7965SKim Phillips 
26639c4a7965SKim Phillips 	priv->reg = of_iomap(np, 0);
26649c4a7965SKim Phillips 	if (!priv->reg) {
26659c4a7965SKim Phillips 		dev_err(dev, "failed to of_iomap\n");
26669c4a7965SKim Phillips 		err = -ENOMEM;
26679c4a7965SKim Phillips 		goto err_out;
26689c4a7965SKim Phillips 	}
26699c4a7965SKim Phillips 
26709c4a7965SKim Phillips 	/* get SEC version capabilities from device tree */
26719c4a7965SKim Phillips 	prop = of_get_property(np, "fsl,num-channels", NULL);
26729c4a7965SKim Phillips 	if (prop)
26739c4a7965SKim Phillips 		priv->num_channels = *prop;
26749c4a7965SKim Phillips 
26759c4a7965SKim Phillips 	prop = of_get_property(np, "fsl,channel-fifo-len", NULL);
26769c4a7965SKim Phillips 	if (prop)
26779c4a7965SKim Phillips 		priv->chfifo_len = *prop;
26789c4a7965SKim Phillips 
26799c4a7965SKim Phillips 	prop = of_get_property(np, "fsl,exec-units-mask", NULL);
26809c4a7965SKim Phillips 	if (prop)
26819c4a7965SKim Phillips 		priv->exec_units = *prop;
26829c4a7965SKim Phillips 
26839c4a7965SKim Phillips 	prop = of_get_property(np, "fsl,descriptor-types-mask", NULL);
26849c4a7965SKim Phillips 	if (prop)
26859c4a7965SKim Phillips 		priv->desc_types = *prop;
26869c4a7965SKim Phillips 
26879c4a7965SKim Phillips 	if (!is_power_of_2(priv->num_channels) || !priv->chfifo_len ||
26889c4a7965SKim Phillips 	    !priv->exec_units || !priv->desc_types) {
26899c4a7965SKim Phillips 		dev_err(dev, "invalid property data in device tree node\n");
26909c4a7965SKim Phillips 		err = -EINVAL;
26919c4a7965SKim Phillips 		goto err_out;
26929c4a7965SKim Phillips 	}
26939c4a7965SKim Phillips 
2694f3c85bc1SLee Nipper 	if (of_device_is_compatible(np, "fsl,sec3.0"))
2695f3c85bc1SLee Nipper 		priv->features |= TALITOS_FTR_SRC_LINK_TBL_LEN_INCLUDES_EXTENT;
2696f3c85bc1SLee Nipper 
2697fe5720e2SKim Phillips 	if (of_device_is_compatible(np, "fsl,sec2.1"))
269860f208d7SKim Phillips 		priv->features |= TALITOS_FTR_HW_AUTH_CHECK |
269979b3a418SLee Nipper 				  TALITOS_FTR_SHA224_HWINIT |
270079b3a418SLee Nipper 				  TALITOS_FTR_HMAC_OK;
2701fe5720e2SKim Phillips 
27024b992628SKim Phillips 	priv->chan = kzalloc(sizeof(struct talitos_channel) *
27034b992628SKim Phillips 			     priv->num_channels, GFP_KERNEL);
27044b992628SKim Phillips 	if (!priv->chan) {
27054b992628SKim Phillips 		dev_err(dev, "failed to allocate channel management space\n");
27069c4a7965SKim Phillips 		err = -ENOMEM;
27079c4a7965SKim Phillips 		goto err_out;
27089c4a7965SKim Phillips 	}
27099c4a7965SKim Phillips 
2710f641ddddSMartin Hicks 	priv->fifo_len = roundup_pow_of_two(priv->chfifo_len);
2711f641ddddSMartin Hicks 
2712c3e337f8SKim Phillips 	for (i = 0; i < priv->num_channels; i++) {
2713c3e337f8SKim Phillips 		priv->chan[i].reg = priv->reg + TALITOS_CH_STRIDE * (i + 1);
27142cdba3cfSKim Phillips 		if (!priv->irq[1] || !(i & 1))
2715c3e337f8SKim Phillips 			priv->chan[i].reg += TALITOS_CH_BASE_OFFSET;
2716ad42d5fcSKim Phillips 
27174b992628SKim Phillips 		spin_lock_init(&priv->chan[i].head_lock);
27184b992628SKim Phillips 		spin_lock_init(&priv->chan[i].tail_lock);
27199c4a7965SKim Phillips 
27204b992628SKim Phillips 		priv->chan[i].fifo = kzalloc(sizeof(struct talitos_request) *
27219c4a7965SKim Phillips 					     priv->fifo_len, GFP_KERNEL);
27224b992628SKim Phillips 		if (!priv->chan[i].fifo) {
27239c4a7965SKim Phillips 			dev_err(dev, "failed to allocate request fifo %d\n", i);
27249c4a7965SKim Phillips 			err = -ENOMEM;
27259c4a7965SKim Phillips 			goto err_out;
27269c4a7965SKim Phillips 		}
27279c4a7965SKim Phillips 
27284b992628SKim Phillips 		atomic_set(&priv->chan[i].submit_count,
27294b992628SKim Phillips 			   -(priv->chfifo_len - 1));
2730f641ddddSMartin Hicks 	}
27319c4a7965SKim Phillips 
273281eb024cSKim Phillips 	dma_set_mask(dev, DMA_BIT_MASK(36));
273381eb024cSKim Phillips 
27349c4a7965SKim Phillips 	/* reset and initialize the h/w */
27359c4a7965SKim Phillips 	err = init_device(dev);
27369c4a7965SKim Phillips 	if (err) {
27379c4a7965SKim Phillips 		dev_err(dev, "failed to initialize device\n");
27389c4a7965SKim Phillips 		goto err_out;
27399c4a7965SKim Phillips 	}
27409c4a7965SKim Phillips 
27419c4a7965SKim Phillips 	/* register the RNG, if available */
27429c4a7965SKim Phillips 	if (hw_supports(dev, DESC_HDR_SEL0_RNG)) {
27439c4a7965SKim Phillips 		err = talitos_register_rng(dev);
27449c4a7965SKim Phillips 		if (err) {
27459c4a7965SKim Phillips 			dev_err(dev, "failed to register hwrng: %d\n", err);
27469c4a7965SKim Phillips 			goto err_out;
27479c4a7965SKim Phillips 		} else
27489c4a7965SKim Phillips 			dev_info(dev, "hwrng\n");
27499c4a7965SKim Phillips 	}
27509c4a7965SKim Phillips 
27519c4a7965SKim Phillips 	/* register crypto algorithms the device supports */
27529c4a7965SKim Phillips 	for (i = 0; i < ARRAY_SIZE(driver_algs); i++) {
27539c4a7965SKim Phillips 		if (hw_supports(dev, driver_algs[i].desc_hdr_template)) {
27549c4a7965SKim Phillips 			struct talitos_crypto_alg *t_alg;
2755acbf7c62SLee Nipper 			char *name = NULL;
27569c4a7965SKim Phillips 
27579c4a7965SKim Phillips 			t_alg = talitos_alg_alloc(dev, &driver_algs[i]);
27589c4a7965SKim Phillips 			if (IS_ERR(t_alg)) {
27599c4a7965SKim Phillips 				err = PTR_ERR(t_alg);
27600b2730d8SKim Phillips 				if (err == -ENOTSUPP)
276179b3a418SLee Nipper 					continue;
27629c4a7965SKim Phillips 				goto err_out;
27639c4a7965SKim Phillips 			}
27649c4a7965SKim Phillips 
2765acbf7c62SLee Nipper 			switch (t_alg->algt.type) {
2766acbf7c62SLee Nipper 			case CRYPTO_ALG_TYPE_ABLKCIPHER:
2767acbf7c62SLee Nipper 			case CRYPTO_ALG_TYPE_AEAD:
2768acbf7c62SLee Nipper 				err = crypto_register_alg(
2769acbf7c62SLee Nipper 						&t_alg->algt.alg.crypto);
2770acbf7c62SLee Nipper 				name = t_alg->algt.alg.crypto.cra_driver_name;
2771acbf7c62SLee Nipper 				break;
2772acbf7c62SLee Nipper 			case CRYPTO_ALG_TYPE_AHASH:
2773acbf7c62SLee Nipper 				err = crypto_register_ahash(
2774acbf7c62SLee Nipper 						&t_alg->algt.alg.hash);
2775acbf7c62SLee Nipper 				name =
2776acbf7c62SLee Nipper 				 t_alg->algt.alg.hash.halg.base.cra_driver_name;
2777acbf7c62SLee Nipper 				break;
2778acbf7c62SLee Nipper 			}
27799c4a7965SKim Phillips 			if (err) {
27809c4a7965SKim Phillips 				dev_err(dev, "%s alg registration failed\n",
2781acbf7c62SLee Nipper 					name);
27829c4a7965SKim Phillips 				kfree(t_alg);
2783991155baSHoria Geanta 			} else
27849c4a7965SKim Phillips 				list_add_tail(&t_alg->entry, &priv->alg_list);
27859c4a7965SKim Phillips 		}
27869c4a7965SKim Phillips 	}
27875b859b6eSKim Phillips 	if (!list_empty(&priv->alg_list))
27885b859b6eSKim Phillips 		dev_info(dev, "%s algorithms registered in /proc/crypto\n",
27895b859b6eSKim Phillips 			 (char *)of_get_property(np, "compatible", NULL));
27909c4a7965SKim Phillips 
27919c4a7965SKim Phillips 	return 0;
27929c4a7965SKim Phillips 
27939c4a7965SKim Phillips err_out:
27949c4a7965SKim Phillips 	talitos_remove(ofdev);
27959c4a7965SKim Phillips 
27969c4a7965SKim Phillips 	return err;
27979c4a7965SKim Phillips }
27989c4a7965SKim Phillips 
27996c3f975aSMárton Németh static const struct of_device_id talitos_match[] = {
28009c4a7965SKim Phillips 	{
28019c4a7965SKim Phillips 		.compatible = "fsl,sec2.0",
28029c4a7965SKim Phillips 	},
28039c4a7965SKim Phillips 	{},
28049c4a7965SKim Phillips };
28059c4a7965SKim Phillips MODULE_DEVICE_TABLE(of, talitos_match);
28069c4a7965SKim Phillips 
28071c48a5c9SGrant Likely static struct platform_driver talitos_driver = {
28084018294bSGrant Likely 	.driver = {
28099c4a7965SKim Phillips 		.name = "talitos",
28104018294bSGrant Likely 		.of_match_table = talitos_match,
28114018294bSGrant Likely 	},
28129c4a7965SKim Phillips 	.probe = talitos_probe,
2813596f1034SAl Viro 	.remove = talitos_remove,
28149c4a7965SKim Phillips };
28159c4a7965SKim Phillips 
2816741e8c2dSAxel Lin module_platform_driver(talitos_driver);
28179c4a7965SKim Phillips 
28189c4a7965SKim Phillips MODULE_LICENSE("GPL");
28199c4a7965SKim Phillips MODULE_AUTHOR("Kim Phillips <kim.phillips@freescale.com>");
28209c4a7965SKim Phillips MODULE_DESCRIPTION("Freescale integrated security engine (SEC) driver");
2821