19c4a7965SKim Phillips /* 29c4a7965SKim Phillips * talitos - Freescale Integrated Security Engine (SEC) device driver 39c4a7965SKim Phillips * 45228f0f7SKim Phillips * Copyright (c) 2008-2011 Freescale Semiconductor, Inc. 59c4a7965SKim Phillips * 69c4a7965SKim Phillips * Scatterlist Crypto API glue code copied from files with the following: 79c4a7965SKim Phillips * Copyright (c) 2006-2007 Herbert Xu <herbert@gondor.apana.org.au> 89c4a7965SKim Phillips * 99c4a7965SKim Phillips * Crypto algorithm registration code copied from hifn driver: 109c4a7965SKim Phillips * 2007+ Copyright (c) Evgeniy Polyakov <johnpol@2ka.mipt.ru> 119c4a7965SKim Phillips * All rights reserved. 129c4a7965SKim Phillips * 139c4a7965SKim Phillips * This program is free software; you can redistribute it and/or modify 149c4a7965SKim Phillips * it under the terms of the GNU General Public License as published by 159c4a7965SKim Phillips * the Free Software Foundation; either version 2 of the License, or 169c4a7965SKim Phillips * (at your option) any later version. 179c4a7965SKim Phillips * 189c4a7965SKim Phillips * This program is distributed in the hope that it will be useful, 199c4a7965SKim Phillips * but WITHOUT ANY WARRANTY; without even the implied warranty of 209c4a7965SKim Phillips * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 219c4a7965SKim Phillips * GNU General Public License for more details. 229c4a7965SKim Phillips * 239c4a7965SKim Phillips * You should have received a copy of the GNU General Public License 249c4a7965SKim Phillips * along with this program; if not, write to the Free Software 259c4a7965SKim Phillips * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 269c4a7965SKim Phillips */ 279c4a7965SKim Phillips 289c4a7965SKim Phillips #include <linux/kernel.h> 299c4a7965SKim Phillips #include <linux/module.h> 309c4a7965SKim Phillips #include <linux/mod_devicetable.h> 319c4a7965SKim Phillips #include <linux/device.h> 329c4a7965SKim Phillips #include <linux/interrupt.h> 339c4a7965SKim Phillips #include <linux/crypto.h> 349c4a7965SKim Phillips #include <linux/hw_random.h> 355af50730SRob Herring #include <linux/of_address.h> 365af50730SRob Herring #include <linux/of_irq.h> 379c4a7965SKim Phillips #include <linux/of_platform.h> 389c4a7965SKim Phillips #include <linux/dma-mapping.h> 399c4a7965SKim Phillips #include <linux/io.h> 409c4a7965SKim Phillips #include <linux/spinlock.h> 419c4a7965SKim Phillips #include <linux/rtnetlink.h> 425a0e3ad6STejun Heo #include <linux/slab.h> 439c4a7965SKim Phillips 449c4a7965SKim Phillips #include <crypto/algapi.h> 459c4a7965SKim Phillips #include <crypto/aes.h> 463952f17eSLee Nipper #include <crypto/des.h> 479c4a7965SKim Phillips #include <crypto/sha.h> 48497f2e6bSLee Nipper #include <crypto/md5.h> 49e98014abSHerbert Xu #include <crypto/internal/aead.h> 509c4a7965SKim Phillips #include <crypto/authenc.h> 514de9d0b5SLee Nipper #include <crypto/skcipher.h> 52acbf7c62SLee Nipper #include <crypto/hash.h> 53acbf7c62SLee Nipper #include <crypto/internal/hash.h> 544de9d0b5SLee Nipper #include <crypto/scatterwalk.h> 559c4a7965SKim Phillips 569c4a7965SKim Phillips #include "talitos.h" 579c4a7965SKim Phillips 58922f9dc8SLEROY Christophe static void to_talitos_ptr(struct talitos_ptr *ptr, dma_addr_t dma_addr, 59da9de146SLEROY Christophe unsigned int len, bool is_sec1) 6081eb024cSKim Phillips { 61edc6bd69SLEROY Christophe ptr->ptr = cpu_to_be32(lower_32_bits(dma_addr)); 62da9de146SLEROY Christophe if (is_sec1) { 63da9de146SLEROY Christophe ptr->len1 = cpu_to_be16(len); 64da9de146SLEROY Christophe } else { 65da9de146SLEROY Christophe ptr->len = cpu_to_be16(len); 66edc6bd69SLEROY Christophe ptr->eptr = upper_32_bits(dma_addr); 6781eb024cSKim Phillips } 68da9de146SLEROY Christophe } 6981eb024cSKim Phillips 70340ff60aSHoria Geant? static void copy_talitos_ptr(struct talitos_ptr *dst_ptr, 71340ff60aSHoria Geant? struct talitos_ptr *src_ptr, bool is_sec1) 72340ff60aSHoria Geant? { 73340ff60aSHoria Geant? dst_ptr->ptr = src_ptr->ptr; 74922f9dc8SLEROY Christophe if (is_sec1) { 75da9de146SLEROY Christophe dst_ptr->len1 = src_ptr->len1; 76922f9dc8SLEROY Christophe } else { 77da9de146SLEROY Christophe dst_ptr->len = src_ptr->len; 78da9de146SLEROY Christophe dst_ptr->eptr = src_ptr->eptr; 79538caf83SLEROY Christophe } 80922f9dc8SLEROY Christophe } 81538caf83SLEROY Christophe 82922f9dc8SLEROY Christophe static unsigned short from_talitos_ptr_len(struct talitos_ptr *ptr, 83922f9dc8SLEROY Christophe bool is_sec1) 84538caf83SLEROY Christophe { 85922f9dc8SLEROY Christophe if (is_sec1) 86922f9dc8SLEROY Christophe return be16_to_cpu(ptr->len1); 87922f9dc8SLEROY Christophe else 88538caf83SLEROY Christophe return be16_to_cpu(ptr->len); 89538caf83SLEROY Christophe } 90538caf83SLEROY Christophe 91b096b544SLEROY Christophe static void to_talitos_ptr_ext_set(struct talitos_ptr *ptr, u8 val, 92b096b544SLEROY Christophe bool is_sec1) 93185eb79fSLEROY Christophe { 94922f9dc8SLEROY Christophe if (!is_sec1) 95b096b544SLEROY Christophe ptr->j_extent = val; 96b096b544SLEROY Christophe } 97b096b544SLEROY Christophe 98b096b544SLEROY Christophe static void to_talitos_ptr_ext_or(struct talitos_ptr *ptr, u8 val, bool is_sec1) 99b096b544SLEROY Christophe { 100b096b544SLEROY Christophe if (!is_sec1) 101b096b544SLEROY Christophe ptr->j_extent |= val; 102185eb79fSLEROY Christophe } 103185eb79fSLEROY Christophe 1049c4a7965SKim Phillips /* 1059c4a7965SKim Phillips * map virtual single (contiguous) pointer to h/w descriptor pointer 1069c4a7965SKim Phillips */ 1076a4967c3SLEROY Christophe static void __map_single_talitos_ptr(struct device *dev, 1086a4967c3SLEROY Christophe struct talitos_ptr *ptr, 1096a4967c3SLEROY Christophe unsigned int len, void *data, 1106a4967c3SLEROY Christophe enum dma_data_direction dir, 1116a4967c3SLEROY Christophe unsigned long attrs) 1126a4967c3SLEROY Christophe { 1136a4967c3SLEROY Christophe dma_addr_t dma_addr = dma_map_single_attrs(dev, data, len, dir, attrs); 1146a4967c3SLEROY Christophe struct talitos_private *priv = dev_get_drvdata(dev); 1156a4967c3SLEROY Christophe bool is_sec1 = has_ftr_sec1(priv); 1166a4967c3SLEROY Christophe 1176a4967c3SLEROY Christophe to_talitos_ptr(ptr, dma_addr, len, is_sec1); 1186a4967c3SLEROY Christophe } 1196a4967c3SLEROY Christophe 1209c4a7965SKim Phillips static void map_single_talitos_ptr(struct device *dev, 121edc6bd69SLEROY Christophe struct talitos_ptr *ptr, 12242e8b0d7SHoria Geant? unsigned int len, void *data, 1239c4a7965SKim Phillips enum dma_data_direction dir) 1249c4a7965SKim Phillips { 1256a4967c3SLEROY Christophe __map_single_talitos_ptr(dev, ptr, len, data, dir, 0); 1266a4967c3SLEROY Christophe } 12781eb024cSKim Phillips 1286a4967c3SLEROY Christophe static void map_single_talitos_ptr_nosync(struct device *dev, 1296a4967c3SLEROY Christophe struct talitos_ptr *ptr, 1306a4967c3SLEROY Christophe unsigned int len, void *data, 1316a4967c3SLEROY Christophe enum dma_data_direction dir) 1326a4967c3SLEROY Christophe { 1336a4967c3SLEROY Christophe __map_single_talitos_ptr(dev, ptr, len, data, dir, 1346a4967c3SLEROY Christophe DMA_ATTR_SKIP_CPU_SYNC); 1359c4a7965SKim Phillips } 1369c4a7965SKim Phillips 1379c4a7965SKim Phillips /* 1389c4a7965SKim Phillips * unmap bus single (contiguous) h/w descriptor pointer 1399c4a7965SKim Phillips */ 1409c4a7965SKim Phillips static void unmap_single_talitos_ptr(struct device *dev, 141edc6bd69SLEROY Christophe struct talitos_ptr *ptr, 1429c4a7965SKim Phillips enum dma_data_direction dir) 1439c4a7965SKim Phillips { 144922f9dc8SLEROY Christophe struct talitos_private *priv = dev_get_drvdata(dev); 145922f9dc8SLEROY Christophe bool is_sec1 = has_ftr_sec1(priv); 146922f9dc8SLEROY Christophe 147edc6bd69SLEROY Christophe dma_unmap_single(dev, be32_to_cpu(ptr->ptr), 148922f9dc8SLEROY Christophe from_talitos_ptr_len(ptr, is_sec1), dir); 1499c4a7965SKim Phillips } 1509c4a7965SKim Phillips 1519c4a7965SKim Phillips static int reset_channel(struct device *dev, int ch) 1529c4a7965SKim Phillips { 1539c4a7965SKim Phillips struct talitos_private *priv = dev_get_drvdata(dev); 1549c4a7965SKim Phillips unsigned int timeout = TALITOS_TIMEOUT; 155dd3c0987SLEROY Christophe bool is_sec1 = has_ftr_sec1(priv); 1569c4a7965SKim Phillips 157dd3c0987SLEROY Christophe if (is_sec1) { 158dd3c0987SLEROY Christophe setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO, 159dd3c0987SLEROY Christophe TALITOS1_CCCR_LO_RESET); 1609c4a7965SKim Phillips 161dd3c0987SLEROY Christophe while ((in_be32(priv->chan[ch].reg + TALITOS_CCCR_LO) & 162dd3c0987SLEROY Christophe TALITOS1_CCCR_LO_RESET) && --timeout) 1639c4a7965SKim Phillips cpu_relax(); 164dd3c0987SLEROY Christophe } else { 165dd3c0987SLEROY Christophe setbits32(priv->chan[ch].reg + TALITOS_CCCR, 166dd3c0987SLEROY Christophe TALITOS2_CCCR_RESET); 167dd3c0987SLEROY Christophe 168dd3c0987SLEROY Christophe while ((in_be32(priv->chan[ch].reg + TALITOS_CCCR) & 169dd3c0987SLEROY Christophe TALITOS2_CCCR_RESET) && --timeout) 170dd3c0987SLEROY Christophe cpu_relax(); 171dd3c0987SLEROY Christophe } 1729c4a7965SKim Phillips 1739c4a7965SKim Phillips if (timeout == 0) { 1749c4a7965SKim Phillips dev_err(dev, "failed to reset channel %d\n", ch); 1759c4a7965SKim Phillips return -EIO; 1769c4a7965SKim Phillips } 1779c4a7965SKim Phillips 17881eb024cSKim Phillips /* set 36-bit addressing, done writeback enable and done IRQ enable */ 179ad42d5fcSKim Phillips setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO, TALITOS_CCCR_LO_EAE | 18081eb024cSKim Phillips TALITOS_CCCR_LO_CDWE | TALITOS_CCCR_LO_CDIE); 18137b5e889SLEROY Christophe /* enable chaining descriptors */ 18237b5e889SLEROY Christophe if (is_sec1) 18337b5e889SLEROY Christophe setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO, 18437b5e889SLEROY Christophe TALITOS_CCCR_LO_NE); 1859c4a7965SKim Phillips 186fe5720e2SKim Phillips /* and ICCR writeback, if available */ 187fe5720e2SKim Phillips if (priv->features & TALITOS_FTR_HW_AUTH_CHECK) 188ad42d5fcSKim Phillips setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO, 189fe5720e2SKim Phillips TALITOS_CCCR_LO_IWSE); 190fe5720e2SKim Phillips 1919c4a7965SKim Phillips return 0; 1929c4a7965SKim Phillips } 1939c4a7965SKim Phillips 1949c4a7965SKim Phillips static int reset_device(struct device *dev) 1959c4a7965SKim Phillips { 1969c4a7965SKim Phillips struct talitos_private *priv = dev_get_drvdata(dev); 1979c4a7965SKim Phillips unsigned int timeout = TALITOS_TIMEOUT; 198dd3c0987SLEROY Christophe bool is_sec1 = has_ftr_sec1(priv); 199dd3c0987SLEROY Christophe u32 mcr = is_sec1 ? TALITOS1_MCR_SWR : TALITOS2_MCR_SWR; 2009c4a7965SKim Phillips 201c3e337f8SKim Phillips setbits32(priv->reg + TALITOS_MCR, mcr); 2029c4a7965SKim Phillips 203dd3c0987SLEROY Christophe while ((in_be32(priv->reg + TALITOS_MCR) & mcr) 2049c4a7965SKim Phillips && --timeout) 2059c4a7965SKim Phillips cpu_relax(); 2069c4a7965SKim Phillips 2072cdba3cfSKim Phillips if (priv->irq[1]) { 208c3e337f8SKim Phillips mcr = TALITOS_MCR_RCA1 | TALITOS_MCR_RCA3; 209c3e337f8SKim Phillips setbits32(priv->reg + TALITOS_MCR, mcr); 210c3e337f8SKim Phillips } 211c3e337f8SKim Phillips 2129c4a7965SKim Phillips if (timeout == 0) { 2139c4a7965SKim Phillips dev_err(dev, "failed to reset device\n"); 2149c4a7965SKim Phillips return -EIO; 2159c4a7965SKim Phillips } 2169c4a7965SKim Phillips 2179c4a7965SKim Phillips return 0; 2189c4a7965SKim Phillips } 2199c4a7965SKim Phillips 2209c4a7965SKim Phillips /* 2219c4a7965SKim Phillips * Reset and initialize the device 2229c4a7965SKim Phillips */ 2239c4a7965SKim Phillips static int init_device(struct device *dev) 2249c4a7965SKim Phillips { 2259c4a7965SKim Phillips struct talitos_private *priv = dev_get_drvdata(dev); 2269c4a7965SKim Phillips int ch, err; 227dd3c0987SLEROY Christophe bool is_sec1 = has_ftr_sec1(priv); 2289c4a7965SKim Phillips 2299c4a7965SKim Phillips /* 2309c4a7965SKim Phillips * Master reset 2319c4a7965SKim Phillips * errata documentation: warning: certain SEC interrupts 2329c4a7965SKim Phillips * are not fully cleared by writing the MCR:SWR bit, 2339c4a7965SKim Phillips * set bit twice to completely reset 2349c4a7965SKim Phillips */ 2359c4a7965SKim Phillips err = reset_device(dev); 2369c4a7965SKim Phillips if (err) 2379c4a7965SKim Phillips return err; 2389c4a7965SKim Phillips 2399c4a7965SKim Phillips err = reset_device(dev); 2409c4a7965SKim Phillips if (err) 2419c4a7965SKim Phillips return err; 2429c4a7965SKim Phillips 2439c4a7965SKim Phillips /* reset channels */ 2449c4a7965SKim Phillips for (ch = 0; ch < priv->num_channels; ch++) { 2459c4a7965SKim Phillips err = reset_channel(dev, ch); 2469c4a7965SKim Phillips if (err) 2479c4a7965SKim Phillips return err; 2489c4a7965SKim Phillips } 2499c4a7965SKim Phillips 2509c4a7965SKim Phillips /* enable channel done and error interrupts */ 251dd3c0987SLEROY Christophe if (is_sec1) { 252dd3c0987SLEROY Christophe clrbits32(priv->reg + TALITOS_IMR, TALITOS1_IMR_INIT); 253dd3c0987SLEROY Christophe clrbits32(priv->reg + TALITOS_IMR_LO, TALITOS1_IMR_LO_INIT); 254dd3c0987SLEROY Christophe /* disable parity error check in DEU (erroneous? test vect.) */ 255dd3c0987SLEROY Christophe setbits32(priv->reg_deu + TALITOS_EUICR, TALITOS1_DEUICR_KPE); 256dd3c0987SLEROY Christophe } else { 257dd3c0987SLEROY Christophe setbits32(priv->reg + TALITOS_IMR, TALITOS2_IMR_INIT); 258dd3c0987SLEROY Christophe setbits32(priv->reg + TALITOS_IMR_LO, TALITOS2_IMR_LO_INIT); 259dd3c0987SLEROY Christophe } 2609c4a7965SKim Phillips 261fe5720e2SKim Phillips /* disable integrity check error interrupts (use writeback instead) */ 262fe5720e2SKim Phillips if (priv->features & TALITOS_FTR_HW_AUTH_CHECK) 2635fa7fa14SLEROY Christophe setbits32(priv->reg_mdeu + TALITOS_EUICR_LO, 264fe5720e2SKim Phillips TALITOS_MDEUICR_LO_ICE); 265fe5720e2SKim Phillips 2669c4a7965SKim Phillips return 0; 2679c4a7965SKim Phillips } 2689c4a7965SKim Phillips 2699c4a7965SKim Phillips /** 2709c4a7965SKim Phillips * talitos_submit - submits a descriptor to the device for processing 2719c4a7965SKim Phillips * @dev: the SEC device to be used 2725228f0f7SKim Phillips * @ch: the SEC device channel to be used 2739c4a7965SKim Phillips * @desc: the descriptor to be processed by the device 2749c4a7965SKim Phillips * @callback: whom to call when processing is complete 2759c4a7965SKim Phillips * @context: a handle for use by caller (optional) 2769c4a7965SKim Phillips * 2779c4a7965SKim Phillips * desc must contain valid dma-mapped (bus physical) address pointers. 2789c4a7965SKim Phillips * callback must check err and feedback in descriptor header 2799c4a7965SKim Phillips * for device processing status. 2809c4a7965SKim Phillips */ 281865d5061SHoria Geanta int talitos_submit(struct device *dev, int ch, struct talitos_desc *desc, 2829c4a7965SKim Phillips void (*callback)(struct device *dev, 2839c4a7965SKim Phillips struct talitos_desc *desc, 2849c4a7965SKim Phillips void *context, int error), 2859c4a7965SKim Phillips void *context) 2869c4a7965SKim Phillips { 2879c4a7965SKim Phillips struct talitos_private *priv = dev_get_drvdata(dev); 2889c4a7965SKim Phillips struct talitos_request *request; 2895228f0f7SKim Phillips unsigned long flags; 2909c4a7965SKim Phillips int head; 2917d607c6aSLEROY Christophe bool is_sec1 = has_ftr_sec1(priv); 2929c4a7965SKim Phillips 2934b992628SKim Phillips spin_lock_irqsave(&priv->chan[ch].head_lock, flags); 2949c4a7965SKim Phillips 2954b992628SKim Phillips if (!atomic_inc_not_zero(&priv->chan[ch].submit_count)) { 296ec6644d6SKim Phillips /* h/w fifo is full */ 2974b992628SKim Phillips spin_unlock_irqrestore(&priv->chan[ch].head_lock, flags); 2989c4a7965SKim Phillips return -EAGAIN; 2999c4a7965SKim Phillips } 3009c4a7965SKim Phillips 3014b992628SKim Phillips head = priv->chan[ch].head; 3024b992628SKim Phillips request = &priv->chan[ch].fifo[head]; 303ec6644d6SKim Phillips 3049c4a7965SKim Phillips /* map descriptor and save caller data */ 3057d607c6aSLEROY Christophe if (is_sec1) { 3067d607c6aSLEROY Christophe desc->hdr1 = desc->hdr; 3077d607c6aSLEROY Christophe request->dma_desc = dma_map_single(dev, &desc->hdr1, 3087d607c6aSLEROY Christophe TALITOS_DESC_SIZE, 3099c4a7965SKim Phillips DMA_BIDIRECTIONAL); 3107d607c6aSLEROY Christophe } else { 3117d607c6aSLEROY Christophe request->dma_desc = dma_map_single(dev, desc, 3127d607c6aSLEROY Christophe TALITOS_DESC_SIZE, 3137d607c6aSLEROY Christophe DMA_BIDIRECTIONAL); 3147d607c6aSLEROY Christophe } 3159c4a7965SKim Phillips request->callback = callback; 3169c4a7965SKim Phillips request->context = context; 3179c4a7965SKim Phillips 3189c4a7965SKim Phillips /* increment fifo head */ 3194b992628SKim Phillips priv->chan[ch].head = (priv->chan[ch].head + 1) & (priv->fifo_len - 1); 3209c4a7965SKim Phillips 3219c4a7965SKim Phillips smp_wmb(); 3229c4a7965SKim Phillips request->desc = desc; 3239c4a7965SKim Phillips 3249c4a7965SKim Phillips /* GO! */ 3259c4a7965SKim Phillips wmb(); 326ad42d5fcSKim Phillips out_be32(priv->chan[ch].reg + TALITOS_FF, 327ad42d5fcSKim Phillips upper_32_bits(request->dma_desc)); 328ad42d5fcSKim Phillips out_be32(priv->chan[ch].reg + TALITOS_FF_LO, 329a752447aSKim Phillips lower_32_bits(request->dma_desc)); 3309c4a7965SKim Phillips 3314b992628SKim Phillips spin_unlock_irqrestore(&priv->chan[ch].head_lock, flags); 3329c4a7965SKim Phillips 3339c4a7965SKim Phillips return -EINPROGRESS; 3349c4a7965SKim Phillips } 335865d5061SHoria Geanta EXPORT_SYMBOL(talitos_submit); 3369c4a7965SKim Phillips 3379c4a7965SKim Phillips /* 3389c4a7965SKim Phillips * process what was done, notify callback of error if not 3399c4a7965SKim Phillips */ 3409c4a7965SKim Phillips static void flush_channel(struct device *dev, int ch, int error, int reset_ch) 3419c4a7965SKim Phillips { 3429c4a7965SKim Phillips struct talitos_private *priv = dev_get_drvdata(dev); 3439c4a7965SKim Phillips struct talitos_request *request, saved_req; 3449c4a7965SKim Phillips unsigned long flags; 3459c4a7965SKim Phillips int tail, status; 3467d607c6aSLEROY Christophe bool is_sec1 = has_ftr_sec1(priv); 3479c4a7965SKim Phillips 3484b992628SKim Phillips spin_lock_irqsave(&priv->chan[ch].tail_lock, flags); 3499c4a7965SKim Phillips 3504b992628SKim Phillips tail = priv->chan[ch].tail; 3514b992628SKim Phillips while (priv->chan[ch].fifo[tail].desc) { 3527d607c6aSLEROY Christophe __be32 hdr; 3537d607c6aSLEROY Christophe 3544b992628SKim Phillips request = &priv->chan[ch].fifo[tail]; 3559c4a7965SKim Phillips 3569c4a7965SKim Phillips /* descriptors with their done bits set don't get the error */ 3579c4a7965SKim Phillips rmb(); 35837b5e889SLEROY Christophe if (!is_sec1) 35937b5e889SLEROY Christophe hdr = request->desc->hdr; 36037b5e889SLEROY Christophe else if (request->desc->next_desc) 36137b5e889SLEROY Christophe hdr = (request->desc + 1)->hdr1; 36237b5e889SLEROY Christophe else 36337b5e889SLEROY Christophe hdr = request->desc->hdr1; 3647d607c6aSLEROY Christophe 3657d607c6aSLEROY Christophe if ((hdr & DESC_HDR_DONE) == DESC_HDR_DONE) 3669c4a7965SKim Phillips status = 0; 367ca38a814SLee Nipper else 3689c4a7965SKim Phillips if (!error) 3699c4a7965SKim Phillips break; 3709c4a7965SKim Phillips else 3719c4a7965SKim Phillips status = error; 3729c4a7965SKim Phillips 3739c4a7965SKim Phillips dma_unmap_single(dev, request->dma_desc, 3747d607c6aSLEROY Christophe TALITOS_DESC_SIZE, 375e938e465SKim Phillips DMA_BIDIRECTIONAL); 3769c4a7965SKim Phillips 3779c4a7965SKim Phillips /* copy entries so we can call callback outside lock */ 3789c4a7965SKim Phillips saved_req.desc = request->desc; 3799c4a7965SKim Phillips saved_req.callback = request->callback; 3809c4a7965SKim Phillips saved_req.context = request->context; 3819c4a7965SKim Phillips 3829c4a7965SKim Phillips /* release request entry in fifo */ 3839c4a7965SKim Phillips smp_wmb(); 3849c4a7965SKim Phillips request->desc = NULL; 3859c4a7965SKim Phillips 3869c4a7965SKim Phillips /* increment fifo tail */ 3874b992628SKim Phillips priv->chan[ch].tail = (tail + 1) & (priv->fifo_len - 1); 3889c4a7965SKim Phillips 3894b992628SKim Phillips spin_unlock_irqrestore(&priv->chan[ch].tail_lock, flags); 390ec6644d6SKim Phillips 3914b992628SKim Phillips atomic_dec(&priv->chan[ch].submit_count); 392ec6644d6SKim Phillips 3939c4a7965SKim Phillips saved_req.callback(dev, saved_req.desc, saved_req.context, 3949c4a7965SKim Phillips status); 3959c4a7965SKim Phillips /* channel may resume processing in single desc error case */ 3969c4a7965SKim Phillips if (error && !reset_ch && status == error) 3979c4a7965SKim Phillips return; 3984b992628SKim Phillips spin_lock_irqsave(&priv->chan[ch].tail_lock, flags); 3994b992628SKim Phillips tail = priv->chan[ch].tail; 4009c4a7965SKim Phillips } 4019c4a7965SKim Phillips 4024b992628SKim Phillips spin_unlock_irqrestore(&priv->chan[ch].tail_lock, flags); 4039c4a7965SKim Phillips } 4049c4a7965SKim Phillips 4059c4a7965SKim Phillips /* 4069c4a7965SKim Phillips * process completed requests for channels that have done status 4079c4a7965SKim Phillips */ 408dd3c0987SLEROY Christophe #define DEF_TALITOS1_DONE(name, ch_done_mask) \ 409dd3c0987SLEROY Christophe static void talitos1_done_##name(unsigned long data) \ 410dd3c0987SLEROY Christophe { \ 411dd3c0987SLEROY Christophe struct device *dev = (struct device *)data; \ 412dd3c0987SLEROY Christophe struct talitos_private *priv = dev_get_drvdata(dev); \ 413dd3c0987SLEROY Christophe unsigned long flags; \ 414dd3c0987SLEROY Christophe \ 415dd3c0987SLEROY Christophe if (ch_done_mask & 0x10000000) \ 416dd3c0987SLEROY Christophe flush_channel(dev, 0, 0, 0); \ 417dd3c0987SLEROY Christophe if (ch_done_mask & 0x40000000) \ 418dd3c0987SLEROY Christophe flush_channel(dev, 1, 0, 0); \ 419dd3c0987SLEROY Christophe if (ch_done_mask & 0x00010000) \ 420dd3c0987SLEROY Christophe flush_channel(dev, 2, 0, 0); \ 421dd3c0987SLEROY Christophe if (ch_done_mask & 0x00040000) \ 422dd3c0987SLEROY Christophe flush_channel(dev, 3, 0, 0); \ 423dd3c0987SLEROY Christophe \ 424dd3c0987SLEROY Christophe /* At this point, all completed channels have been processed */ \ 425dd3c0987SLEROY Christophe /* Unmask done interrupts for channels completed later on. */ \ 426dd3c0987SLEROY Christophe spin_lock_irqsave(&priv->reg_lock, flags); \ 427dd3c0987SLEROY Christophe clrbits32(priv->reg + TALITOS_IMR, ch_done_mask); \ 428dd3c0987SLEROY Christophe clrbits32(priv->reg + TALITOS_IMR_LO, TALITOS1_IMR_LO_INIT); \ 429dd3c0987SLEROY Christophe spin_unlock_irqrestore(&priv->reg_lock, flags); \ 430dd3c0987SLEROY Christophe } 431dd3c0987SLEROY Christophe 432dd3c0987SLEROY Christophe DEF_TALITOS1_DONE(4ch, TALITOS1_ISR_4CHDONE) 4339c02e285SLEROY Christophe DEF_TALITOS1_DONE(ch0, TALITOS1_ISR_CH_0_DONE) 434dd3c0987SLEROY Christophe 435dd3c0987SLEROY Christophe #define DEF_TALITOS2_DONE(name, ch_done_mask) \ 436dd3c0987SLEROY Christophe static void talitos2_done_##name(unsigned long data) \ 437c3e337f8SKim Phillips { \ 438c3e337f8SKim Phillips struct device *dev = (struct device *)data; \ 439c3e337f8SKim Phillips struct talitos_private *priv = dev_get_drvdata(dev); \ 440511d63cbSHoria Geanta unsigned long flags; \ 441c3e337f8SKim Phillips \ 442c3e337f8SKim Phillips if (ch_done_mask & 1) \ 443c3e337f8SKim Phillips flush_channel(dev, 0, 0, 0); \ 444c3e337f8SKim Phillips if (ch_done_mask & (1 << 2)) \ 445c3e337f8SKim Phillips flush_channel(dev, 1, 0, 0); \ 446c3e337f8SKim Phillips if (ch_done_mask & (1 << 4)) \ 447c3e337f8SKim Phillips flush_channel(dev, 2, 0, 0); \ 448c3e337f8SKim Phillips if (ch_done_mask & (1 << 6)) \ 449c3e337f8SKim Phillips flush_channel(dev, 3, 0, 0); \ 450c3e337f8SKim Phillips \ 451c3e337f8SKim Phillips /* At this point, all completed channels have been processed */ \ 452c3e337f8SKim Phillips /* Unmask done interrupts for channels completed later on. */ \ 453511d63cbSHoria Geanta spin_lock_irqsave(&priv->reg_lock, flags); \ 454c3e337f8SKim Phillips setbits32(priv->reg + TALITOS_IMR, ch_done_mask); \ 455dd3c0987SLEROY Christophe setbits32(priv->reg + TALITOS_IMR_LO, TALITOS2_IMR_LO_INIT); \ 456511d63cbSHoria Geanta spin_unlock_irqrestore(&priv->reg_lock, flags); \ 4579c4a7965SKim Phillips } 458dd3c0987SLEROY Christophe 459dd3c0987SLEROY Christophe DEF_TALITOS2_DONE(4ch, TALITOS2_ISR_4CHDONE) 4609c02e285SLEROY Christophe DEF_TALITOS2_DONE(ch0, TALITOS2_ISR_CH_0_DONE) 461dd3c0987SLEROY Christophe DEF_TALITOS2_DONE(ch0_2, TALITOS2_ISR_CH_0_2_DONE) 462dd3c0987SLEROY Christophe DEF_TALITOS2_DONE(ch1_3, TALITOS2_ISR_CH_1_3_DONE) 4639c4a7965SKim Phillips 4649c4a7965SKim Phillips /* 4659c4a7965SKim Phillips * locate current (offending) descriptor 4669c4a7965SKim Phillips */ 4673e721aebSKim Phillips static u32 current_desc_hdr(struct device *dev, int ch) 4689c4a7965SKim Phillips { 4699c4a7965SKim Phillips struct talitos_private *priv = dev_get_drvdata(dev); 470b62ffd8cSHoria Geanta int tail, iter; 4719c4a7965SKim Phillips dma_addr_t cur_desc; 4729c4a7965SKim Phillips 473b62ffd8cSHoria Geanta cur_desc = ((u64)in_be32(priv->chan[ch].reg + TALITOS_CDPR)) << 32; 474b62ffd8cSHoria Geanta cur_desc |= in_be32(priv->chan[ch].reg + TALITOS_CDPR_LO); 4759c4a7965SKim Phillips 476b62ffd8cSHoria Geanta if (!cur_desc) { 477b62ffd8cSHoria Geanta dev_err(dev, "CDPR is NULL, giving up search for offending descriptor\n"); 478b62ffd8cSHoria Geanta return 0; 479b62ffd8cSHoria Geanta } 480b62ffd8cSHoria Geanta 481b62ffd8cSHoria Geanta tail = priv->chan[ch].tail; 482b62ffd8cSHoria Geanta 483b62ffd8cSHoria Geanta iter = tail; 48437b5e889SLEROY Christophe while (priv->chan[ch].fifo[iter].dma_desc != cur_desc && 48537b5e889SLEROY Christophe priv->chan[ch].fifo[iter].desc->next_desc != cur_desc) { 486b62ffd8cSHoria Geanta iter = (iter + 1) & (priv->fifo_len - 1); 487b62ffd8cSHoria Geanta if (iter == tail) { 4889c4a7965SKim Phillips dev_err(dev, "couldn't locate current descriptor\n"); 4893e721aebSKim Phillips return 0; 4909c4a7965SKim Phillips } 4919c4a7965SKim Phillips } 4929c4a7965SKim Phillips 49337b5e889SLEROY Christophe if (priv->chan[ch].fifo[iter].desc->next_desc == cur_desc) 49437b5e889SLEROY Christophe return (priv->chan[ch].fifo[iter].desc + 1)->hdr; 49537b5e889SLEROY Christophe 496b62ffd8cSHoria Geanta return priv->chan[ch].fifo[iter].desc->hdr; 4979c4a7965SKim Phillips } 4989c4a7965SKim Phillips 4999c4a7965SKim Phillips /* 5009c4a7965SKim Phillips * user diagnostics; report root cause of error based on execution unit status 5019c4a7965SKim Phillips */ 5023e721aebSKim Phillips static void report_eu_error(struct device *dev, int ch, u32 desc_hdr) 5039c4a7965SKim Phillips { 5049c4a7965SKim Phillips struct talitos_private *priv = dev_get_drvdata(dev); 5059c4a7965SKim Phillips int i; 5069c4a7965SKim Phillips 5073e721aebSKim Phillips if (!desc_hdr) 508ad42d5fcSKim Phillips desc_hdr = in_be32(priv->chan[ch].reg + TALITOS_DESCBUF); 5093e721aebSKim Phillips 5103e721aebSKim Phillips switch (desc_hdr & DESC_HDR_SEL0_MASK) { 5119c4a7965SKim Phillips case DESC_HDR_SEL0_AFEU: 5129c4a7965SKim Phillips dev_err(dev, "AFEUISR 0x%08x_%08x\n", 5135fa7fa14SLEROY Christophe in_be32(priv->reg_afeu + TALITOS_EUISR), 5145fa7fa14SLEROY Christophe in_be32(priv->reg_afeu + TALITOS_EUISR_LO)); 5159c4a7965SKim Phillips break; 5169c4a7965SKim Phillips case DESC_HDR_SEL0_DEU: 5179c4a7965SKim Phillips dev_err(dev, "DEUISR 0x%08x_%08x\n", 5185fa7fa14SLEROY Christophe in_be32(priv->reg_deu + TALITOS_EUISR), 5195fa7fa14SLEROY Christophe in_be32(priv->reg_deu + TALITOS_EUISR_LO)); 5209c4a7965SKim Phillips break; 5219c4a7965SKim Phillips case DESC_HDR_SEL0_MDEUA: 5229c4a7965SKim Phillips case DESC_HDR_SEL0_MDEUB: 5239c4a7965SKim Phillips dev_err(dev, "MDEUISR 0x%08x_%08x\n", 5245fa7fa14SLEROY Christophe in_be32(priv->reg_mdeu + TALITOS_EUISR), 5255fa7fa14SLEROY Christophe in_be32(priv->reg_mdeu + TALITOS_EUISR_LO)); 5269c4a7965SKim Phillips break; 5279c4a7965SKim Phillips case DESC_HDR_SEL0_RNG: 5289c4a7965SKim Phillips dev_err(dev, "RNGUISR 0x%08x_%08x\n", 5295fa7fa14SLEROY Christophe in_be32(priv->reg_rngu + TALITOS_ISR), 5305fa7fa14SLEROY Christophe in_be32(priv->reg_rngu + TALITOS_ISR_LO)); 5319c4a7965SKim Phillips break; 5329c4a7965SKim Phillips case DESC_HDR_SEL0_PKEU: 5339c4a7965SKim Phillips dev_err(dev, "PKEUISR 0x%08x_%08x\n", 5345fa7fa14SLEROY Christophe in_be32(priv->reg_pkeu + TALITOS_EUISR), 5355fa7fa14SLEROY Christophe in_be32(priv->reg_pkeu + TALITOS_EUISR_LO)); 5369c4a7965SKim Phillips break; 5379c4a7965SKim Phillips case DESC_HDR_SEL0_AESU: 5389c4a7965SKim Phillips dev_err(dev, "AESUISR 0x%08x_%08x\n", 5395fa7fa14SLEROY Christophe in_be32(priv->reg_aesu + TALITOS_EUISR), 5405fa7fa14SLEROY Christophe in_be32(priv->reg_aesu + TALITOS_EUISR_LO)); 5419c4a7965SKim Phillips break; 5429c4a7965SKim Phillips case DESC_HDR_SEL0_CRCU: 5439c4a7965SKim Phillips dev_err(dev, "CRCUISR 0x%08x_%08x\n", 5445fa7fa14SLEROY Christophe in_be32(priv->reg_crcu + TALITOS_EUISR), 5455fa7fa14SLEROY Christophe in_be32(priv->reg_crcu + TALITOS_EUISR_LO)); 5469c4a7965SKim Phillips break; 5479c4a7965SKim Phillips case DESC_HDR_SEL0_KEU: 5489c4a7965SKim Phillips dev_err(dev, "KEUISR 0x%08x_%08x\n", 5495fa7fa14SLEROY Christophe in_be32(priv->reg_pkeu + TALITOS_EUISR), 5505fa7fa14SLEROY Christophe in_be32(priv->reg_pkeu + TALITOS_EUISR_LO)); 5519c4a7965SKim Phillips break; 5529c4a7965SKim Phillips } 5539c4a7965SKim Phillips 5543e721aebSKim Phillips switch (desc_hdr & DESC_HDR_SEL1_MASK) { 5559c4a7965SKim Phillips case DESC_HDR_SEL1_MDEUA: 5569c4a7965SKim Phillips case DESC_HDR_SEL1_MDEUB: 5579c4a7965SKim Phillips dev_err(dev, "MDEUISR 0x%08x_%08x\n", 5585fa7fa14SLEROY Christophe in_be32(priv->reg_mdeu + TALITOS_EUISR), 5595fa7fa14SLEROY Christophe in_be32(priv->reg_mdeu + TALITOS_EUISR_LO)); 5609c4a7965SKim Phillips break; 5619c4a7965SKim Phillips case DESC_HDR_SEL1_CRCU: 5629c4a7965SKim Phillips dev_err(dev, "CRCUISR 0x%08x_%08x\n", 5635fa7fa14SLEROY Christophe in_be32(priv->reg_crcu + TALITOS_EUISR), 5645fa7fa14SLEROY Christophe in_be32(priv->reg_crcu + TALITOS_EUISR_LO)); 5659c4a7965SKim Phillips break; 5669c4a7965SKim Phillips } 5679c4a7965SKim Phillips 5689c4a7965SKim Phillips for (i = 0; i < 8; i++) 5699c4a7965SKim Phillips dev_err(dev, "DESCBUF 0x%08x_%08x\n", 570ad42d5fcSKim Phillips in_be32(priv->chan[ch].reg + TALITOS_DESCBUF + 8*i), 571ad42d5fcSKim Phillips in_be32(priv->chan[ch].reg + TALITOS_DESCBUF_LO + 8*i)); 5729c4a7965SKim Phillips } 5739c4a7965SKim Phillips 5749c4a7965SKim Phillips /* 5759c4a7965SKim Phillips * recover from error interrupts 5769c4a7965SKim Phillips */ 5775e718a09SKim Phillips static void talitos_error(struct device *dev, u32 isr, u32 isr_lo) 5789c4a7965SKim Phillips { 5799c4a7965SKim Phillips struct talitos_private *priv = dev_get_drvdata(dev); 5809c4a7965SKim Phillips unsigned int timeout = TALITOS_TIMEOUT; 581dd3c0987SLEROY Christophe int ch, error, reset_dev = 0; 58242e8b0d7SHoria Geant? u32 v_lo; 583dd3c0987SLEROY Christophe bool is_sec1 = has_ftr_sec1(priv); 584dd3c0987SLEROY Christophe int reset_ch = is_sec1 ? 1 : 0; /* only SEC2 supports continuation */ 5859c4a7965SKim Phillips 5869c4a7965SKim Phillips for (ch = 0; ch < priv->num_channels; ch++) { 5879c4a7965SKim Phillips /* skip channels without errors */ 588dd3c0987SLEROY Christophe if (is_sec1) { 589dd3c0987SLEROY Christophe /* bits 29, 31, 17, 19 */ 590dd3c0987SLEROY Christophe if (!(isr & (1 << (29 + (ch & 1) * 2 - (ch & 2) * 6)))) 591dd3c0987SLEROY Christophe continue; 592dd3c0987SLEROY Christophe } else { 5939c4a7965SKim Phillips if (!(isr & (1 << (ch * 2 + 1)))) 5949c4a7965SKim Phillips continue; 595dd3c0987SLEROY Christophe } 5969c4a7965SKim Phillips 5979c4a7965SKim Phillips error = -EINVAL; 5989c4a7965SKim Phillips 599ad42d5fcSKim Phillips v_lo = in_be32(priv->chan[ch].reg + TALITOS_CCPSR_LO); 6009c4a7965SKim Phillips 6019c4a7965SKim Phillips if (v_lo & TALITOS_CCPSR_LO_DOF) { 6029c4a7965SKim Phillips dev_err(dev, "double fetch fifo overflow error\n"); 6039c4a7965SKim Phillips error = -EAGAIN; 6049c4a7965SKim Phillips reset_ch = 1; 6059c4a7965SKim Phillips } 6069c4a7965SKim Phillips if (v_lo & TALITOS_CCPSR_LO_SOF) { 6079c4a7965SKim Phillips /* h/w dropped descriptor */ 6089c4a7965SKim Phillips dev_err(dev, "single fetch fifo overflow error\n"); 6099c4a7965SKim Phillips error = -EAGAIN; 6109c4a7965SKim Phillips } 6119c4a7965SKim Phillips if (v_lo & TALITOS_CCPSR_LO_MDTE) 6129c4a7965SKim Phillips dev_err(dev, "master data transfer error\n"); 6139c4a7965SKim Phillips if (v_lo & TALITOS_CCPSR_LO_SGDLZ) 6144d9b3a5bSColin Ian King dev_err(dev, is_sec1 ? "pointer not complete error\n" 615dd3c0987SLEROY Christophe : "s/g data length zero error\n"); 6169c4a7965SKim Phillips if (v_lo & TALITOS_CCPSR_LO_FPZ) 617dd3c0987SLEROY Christophe dev_err(dev, is_sec1 ? "parity error\n" 618dd3c0987SLEROY Christophe : "fetch pointer zero error\n"); 6199c4a7965SKim Phillips if (v_lo & TALITOS_CCPSR_LO_IDH) 6209c4a7965SKim Phillips dev_err(dev, "illegal descriptor header error\n"); 6219c4a7965SKim Phillips if (v_lo & TALITOS_CCPSR_LO_IEU) 622dd3c0987SLEROY Christophe dev_err(dev, is_sec1 ? "static assignment error\n" 623dd3c0987SLEROY Christophe : "invalid exec unit error\n"); 6249c4a7965SKim Phillips if (v_lo & TALITOS_CCPSR_LO_EU) 6253e721aebSKim Phillips report_eu_error(dev, ch, current_desc_hdr(dev, ch)); 626dd3c0987SLEROY Christophe if (!is_sec1) { 6279c4a7965SKim Phillips if (v_lo & TALITOS_CCPSR_LO_GB) 6289c4a7965SKim Phillips dev_err(dev, "gather boundary error\n"); 6299c4a7965SKim Phillips if (v_lo & TALITOS_CCPSR_LO_GRL) 6309c4a7965SKim Phillips dev_err(dev, "gather return/length error\n"); 6319c4a7965SKim Phillips if (v_lo & TALITOS_CCPSR_LO_SB) 6329c4a7965SKim Phillips dev_err(dev, "scatter boundary error\n"); 6339c4a7965SKim Phillips if (v_lo & TALITOS_CCPSR_LO_SRL) 6349c4a7965SKim Phillips dev_err(dev, "scatter return/length error\n"); 635dd3c0987SLEROY Christophe } 6369c4a7965SKim Phillips 6379c4a7965SKim Phillips flush_channel(dev, ch, error, reset_ch); 6389c4a7965SKim Phillips 6399c4a7965SKim Phillips if (reset_ch) { 6409c4a7965SKim Phillips reset_channel(dev, ch); 6419c4a7965SKim Phillips } else { 642ad42d5fcSKim Phillips setbits32(priv->chan[ch].reg + TALITOS_CCCR, 643dd3c0987SLEROY Christophe TALITOS2_CCCR_CONT); 644ad42d5fcSKim Phillips setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO, 0); 645ad42d5fcSKim Phillips while ((in_be32(priv->chan[ch].reg + TALITOS_CCCR) & 646dd3c0987SLEROY Christophe TALITOS2_CCCR_CONT) && --timeout) 6479c4a7965SKim Phillips cpu_relax(); 6489c4a7965SKim Phillips if (timeout == 0) { 6499c4a7965SKim Phillips dev_err(dev, "failed to restart channel %d\n", 6509c4a7965SKim Phillips ch); 6519c4a7965SKim Phillips reset_dev = 1; 6529c4a7965SKim Phillips } 6539c4a7965SKim Phillips } 6549c4a7965SKim Phillips } 655dd3c0987SLEROY Christophe if (reset_dev || (is_sec1 && isr & ~TALITOS1_ISR_4CHERR) || 656dd3c0987SLEROY Christophe (!is_sec1 && isr & ~TALITOS2_ISR_4CHERR) || isr_lo) { 657dd3c0987SLEROY Christophe if (is_sec1 && (isr_lo & TALITOS1_ISR_TEA_ERR)) 658dd3c0987SLEROY Christophe dev_err(dev, "TEA error: ISR 0x%08x_%08x\n", 659dd3c0987SLEROY Christophe isr, isr_lo); 660dd3c0987SLEROY Christophe else 661dd3c0987SLEROY Christophe dev_err(dev, "done overflow, internal time out, or " 662dd3c0987SLEROY Christophe "rngu error: ISR 0x%08x_%08x\n", isr, isr_lo); 6639c4a7965SKim Phillips 6649c4a7965SKim Phillips /* purge request queues */ 6659c4a7965SKim Phillips for (ch = 0; ch < priv->num_channels; ch++) 6669c4a7965SKim Phillips flush_channel(dev, ch, -EIO, 1); 6679c4a7965SKim Phillips 6689c4a7965SKim Phillips /* reset and reinitialize the device */ 6699c4a7965SKim Phillips init_device(dev); 6709c4a7965SKim Phillips } 6719c4a7965SKim Phillips } 6729c4a7965SKim Phillips 673dd3c0987SLEROY Christophe #define DEF_TALITOS1_INTERRUPT(name, ch_done_mask, ch_err_mask, tlet) \ 674dd3c0987SLEROY Christophe static irqreturn_t talitos1_interrupt_##name(int irq, void *data) \ 675dd3c0987SLEROY Christophe { \ 676dd3c0987SLEROY Christophe struct device *dev = data; \ 677dd3c0987SLEROY Christophe struct talitos_private *priv = dev_get_drvdata(dev); \ 678dd3c0987SLEROY Christophe u32 isr, isr_lo; \ 679dd3c0987SLEROY Christophe unsigned long flags; \ 680dd3c0987SLEROY Christophe \ 681dd3c0987SLEROY Christophe spin_lock_irqsave(&priv->reg_lock, flags); \ 682dd3c0987SLEROY Christophe isr = in_be32(priv->reg + TALITOS_ISR); \ 683dd3c0987SLEROY Christophe isr_lo = in_be32(priv->reg + TALITOS_ISR_LO); \ 684dd3c0987SLEROY Christophe /* Acknowledge interrupt */ \ 685dd3c0987SLEROY Christophe out_be32(priv->reg + TALITOS_ICR, isr & (ch_done_mask | ch_err_mask)); \ 686dd3c0987SLEROY Christophe out_be32(priv->reg + TALITOS_ICR_LO, isr_lo); \ 687dd3c0987SLEROY Christophe \ 688dd3c0987SLEROY Christophe if (unlikely(isr & ch_err_mask || isr_lo & TALITOS1_IMR_LO_INIT)) { \ 689dd3c0987SLEROY Christophe spin_unlock_irqrestore(&priv->reg_lock, flags); \ 690dd3c0987SLEROY Christophe talitos_error(dev, isr & ch_err_mask, isr_lo); \ 691dd3c0987SLEROY Christophe } \ 692dd3c0987SLEROY Christophe else { \ 693dd3c0987SLEROY Christophe if (likely(isr & ch_done_mask)) { \ 694dd3c0987SLEROY Christophe /* mask further done interrupts. */ \ 695dd3c0987SLEROY Christophe setbits32(priv->reg + TALITOS_IMR, ch_done_mask); \ 696dd3c0987SLEROY Christophe /* done_task will unmask done interrupts at exit */ \ 697dd3c0987SLEROY Christophe tasklet_schedule(&priv->done_task[tlet]); \ 698dd3c0987SLEROY Christophe } \ 699dd3c0987SLEROY Christophe spin_unlock_irqrestore(&priv->reg_lock, flags); \ 700dd3c0987SLEROY Christophe } \ 701dd3c0987SLEROY Christophe \ 702dd3c0987SLEROY Christophe return (isr & (ch_done_mask | ch_err_mask) || isr_lo) ? IRQ_HANDLED : \ 703dd3c0987SLEROY Christophe IRQ_NONE; \ 704dd3c0987SLEROY Christophe } 705dd3c0987SLEROY Christophe 706dd3c0987SLEROY Christophe DEF_TALITOS1_INTERRUPT(4ch, TALITOS1_ISR_4CHDONE, TALITOS1_ISR_4CHERR, 0) 707dd3c0987SLEROY Christophe 708dd3c0987SLEROY Christophe #define DEF_TALITOS2_INTERRUPT(name, ch_done_mask, ch_err_mask, tlet) \ 709dd3c0987SLEROY Christophe static irqreturn_t talitos2_interrupt_##name(int irq, void *data) \ 710c3e337f8SKim Phillips { \ 711c3e337f8SKim Phillips struct device *dev = data; \ 712c3e337f8SKim Phillips struct talitos_private *priv = dev_get_drvdata(dev); \ 713c3e337f8SKim Phillips u32 isr, isr_lo; \ 714511d63cbSHoria Geanta unsigned long flags; \ 715c3e337f8SKim Phillips \ 716511d63cbSHoria Geanta spin_lock_irqsave(&priv->reg_lock, flags); \ 717c3e337f8SKim Phillips isr = in_be32(priv->reg + TALITOS_ISR); \ 718c3e337f8SKim Phillips isr_lo = in_be32(priv->reg + TALITOS_ISR_LO); \ 719c3e337f8SKim Phillips /* Acknowledge interrupt */ \ 720c3e337f8SKim Phillips out_be32(priv->reg + TALITOS_ICR, isr & (ch_done_mask | ch_err_mask)); \ 721c3e337f8SKim Phillips out_be32(priv->reg + TALITOS_ICR_LO, isr_lo); \ 722c3e337f8SKim Phillips \ 723511d63cbSHoria Geanta if (unlikely(isr & ch_err_mask || isr_lo)) { \ 724511d63cbSHoria Geanta spin_unlock_irqrestore(&priv->reg_lock, flags); \ 725511d63cbSHoria Geanta talitos_error(dev, isr & ch_err_mask, isr_lo); \ 726511d63cbSHoria Geanta } \ 727511d63cbSHoria Geanta else { \ 728c3e337f8SKim Phillips if (likely(isr & ch_done_mask)) { \ 729c3e337f8SKim Phillips /* mask further done interrupts. */ \ 730c3e337f8SKim Phillips clrbits32(priv->reg + TALITOS_IMR, ch_done_mask); \ 731c3e337f8SKim Phillips /* done_task will unmask done interrupts at exit */ \ 732c3e337f8SKim Phillips tasklet_schedule(&priv->done_task[tlet]); \ 733c3e337f8SKim Phillips } \ 734511d63cbSHoria Geanta spin_unlock_irqrestore(&priv->reg_lock, flags); \ 735511d63cbSHoria Geanta } \ 736c3e337f8SKim Phillips \ 737c3e337f8SKim Phillips return (isr & (ch_done_mask | ch_err_mask) || isr_lo) ? IRQ_HANDLED : \ 738c3e337f8SKim Phillips IRQ_NONE; \ 7391c2e8811SLee Nipper } 740dd3c0987SLEROY Christophe 741dd3c0987SLEROY Christophe DEF_TALITOS2_INTERRUPT(4ch, TALITOS2_ISR_4CHDONE, TALITOS2_ISR_4CHERR, 0) 742dd3c0987SLEROY Christophe DEF_TALITOS2_INTERRUPT(ch0_2, TALITOS2_ISR_CH_0_2_DONE, TALITOS2_ISR_CH_0_2_ERR, 743dd3c0987SLEROY Christophe 0) 744dd3c0987SLEROY Christophe DEF_TALITOS2_INTERRUPT(ch1_3, TALITOS2_ISR_CH_1_3_DONE, TALITOS2_ISR_CH_1_3_ERR, 745dd3c0987SLEROY Christophe 1) 7469c4a7965SKim Phillips 7479c4a7965SKim Phillips /* 7489c4a7965SKim Phillips * hwrng 7499c4a7965SKim Phillips */ 7509c4a7965SKim Phillips static int talitos_rng_data_present(struct hwrng *rng, int wait) 7519c4a7965SKim Phillips { 7529c4a7965SKim Phillips struct device *dev = (struct device *)rng->priv; 7539c4a7965SKim Phillips struct talitos_private *priv = dev_get_drvdata(dev); 7549c4a7965SKim Phillips u32 ofl; 7559c4a7965SKim Phillips int i; 7569c4a7965SKim Phillips 7579c4a7965SKim Phillips for (i = 0; i < 20; i++) { 7585fa7fa14SLEROY Christophe ofl = in_be32(priv->reg_rngu + TALITOS_EUSR_LO) & 7599c4a7965SKim Phillips TALITOS_RNGUSR_LO_OFL; 7609c4a7965SKim Phillips if (ofl || !wait) 7619c4a7965SKim Phillips break; 7629c4a7965SKim Phillips udelay(10); 7639c4a7965SKim Phillips } 7649c4a7965SKim Phillips 7659c4a7965SKim Phillips return !!ofl; 7669c4a7965SKim Phillips } 7679c4a7965SKim Phillips 7689c4a7965SKim Phillips static int talitos_rng_data_read(struct hwrng *rng, u32 *data) 7699c4a7965SKim Phillips { 7709c4a7965SKim Phillips struct device *dev = (struct device *)rng->priv; 7719c4a7965SKim Phillips struct talitos_private *priv = dev_get_drvdata(dev); 7729c4a7965SKim Phillips 7739c4a7965SKim Phillips /* rng fifo requires 64-bit accesses */ 7745fa7fa14SLEROY Christophe *data = in_be32(priv->reg_rngu + TALITOS_EU_FIFO); 7755fa7fa14SLEROY Christophe *data = in_be32(priv->reg_rngu + TALITOS_EU_FIFO_LO); 7769c4a7965SKim Phillips 7779c4a7965SKim Phillips return sizeof(u32); 7789c4a7965SKim Phillips } 7799c4a7965SKim Phillips 7809c4a7965SKim Phillips static int talitos_rng_init(struct hwrng *rng) 7819c4a7965SKim Phillips { 7829c4a7965SKim Phillips struct device *dev = (struct device *)rng->priv; 7839c4a7965SKim Phillips struct talitos_private *priv = dev_get_drvdata(dev); 7849c4a7965SKim Phillips unsigned int timeout = TALITOS_TIMEOUT; 7859c4a7965SKim Phillips 7865fa7fa14SLEROY Christophe setbits32(priv->reg_rngu + TALITOS_EURCR_LO, TALITOS_RNGURCR_LO_SR); 7875fa7fa14SLEROY Christophe while (!(in_be32(priv->reg_rngu + TALITOS_EUSR_LO) 7885fa7fa14SLEROY Christophe & TALITOS_RNGUSR_LO_RD) 7899c4a7965SKim Phillips && --timeout) 7909c4a7965SKim Phillips cpu_relax(); 7919c4a7965SKim Phillips if (timeout == 0) { 7929c4a7965SKim Phillips dev_err(dev, "failed to reset rng hw\n"); 7939c4a7965SKim Phillips return -ENODEV; 7949c4a7965SKim Phillips } 7959c4a7965SKim Phillips 7969c4a7965SKim Phillips /* start generating */ 7975fa7fa14SLEROY Christophe setbits32(priv->reg_rngu + TALITOS_EUDSR_LO, 0); 7989c4a7965SKim Phillips 7999c4a7965SKim Phillips return 0; 8009c4a7965SKim Phillips } 8019c4a7965SKim Phillips 8029c4a7965SKim Phillips static int talitos_register_rng(struct device *dev) 8039c4a7965SKim Phillips { 8049c4a7965SKim Phillips struct talitos_private *priv = dev_get_drvdata(dev); 80535a3bb3dSAaron Sierra int err; 8069c4a7965SKim Phillips 8079c4a7965SKim Phillips priv->rng.name = dev_driver_string(dev), 8089c4a7965SKim Phillips priv->rng.init = talitos_rng_init, 8099c4a7965SKim Phillips priv->rng.data_present = talitos_rng_data_present, 8109c4a7965SKim Phillips priv->rng.data_read = talitos_rng_data_read, 8119c4a7965SKim Phillips priv->rng.priv = (unsigned long)dev; 8129c4a7965SKim Phillips 81335a3bb3dSAaron Sierra err = hwrng_register(&priv->rng); 81435a3bb3dSAaron Sierra if (!err) 81535a3bb3dSAaron Sierra priv->rng_registered = true; 81635a3bb3dSAaron Sierra 81735a3bb3dSAaron Sierra return err; 8189c4a7965SKim Phillips } 8199c4a7965SKim Phillips 8209c4a7965SKim Phillips static void talitos_unregister_rng(struct device *dev) 8219c4a7965SKim Phillips { 8229c4a7965SKim Phillips struct talitos_private *priv = dev_get_drvdata(dev); 8239c4a7965SKim Phillips 82435a3bb3dSAaron Sierra if (!priv->rng_registered) 82535a3bb3dSAaron Sierra return; 82635a3bb3dSAaron Sierra 8279c4a7965SKim Phillips hwrng_unregister(&priv->rng); 82835a3bb3dSAaron Sierra priv->rng_registered = false; 8299c4a7965SKim Phillips } 8309c4a7965SKim Phillips 8319c4a7965SKim Phillips /* 8329c4a7965SKim Phillips * crypto alg 8339c4a7965SKim Phillips */ 8349c4a7965SKim Phillips #define TALITOS_CRA_PRIORITY 3000 8357405c8d7SLEROY Christophe /* 8367405c8d7SLEROY Christophe * Defines a priority for doing AEAD with descriptors type 8377405c8d7SLEROY Christophe * HMAC_SNOOP_NO_AFEA (HSNA) instead of type IPSEC_ESP 8387405c8d7SLEROY Christophe */ 8397405c8d7SLEROY Christophe #define TALITOS_CRA_PRIORITY_AEAD_HSNA (TALITOS_CRA_PRIORITY - 1) 84003d2c511SMartin Hicks #define TALITOS_MAX_KEY_SIZE (AES_MAX_KEY_SIZE + SHA512_BLOCK_SIZE) 8413952f17eSLee Nipper #define TALITOS_MAX_IV_LENGTH 16 /* max of AES_BLOCK_SIZE, DES3_EDE_BLOCK_SIZE */ 84270bcaca7SLee Nipper 8439c4a7965SKim Phillips struct talitos_ctx { 8449c4a7965SKim Phillips struct device *dev; 8455228f0f7SKim Phillips int ch; 8469c4a7965SKim Phillips __be32 desc_hdr_template; 8479c4a7965SKim Phillips u8 key[TALITOS_MAX_KEY_SIZE]; 84870bcaca7SLee Nipper u8 iv[TALITOS_MAX_IV_LENGTH]; 8492e13ce08SLEROY Christophe dma_addr_t dma_key; 8509c4a7965SKim Phillips unsigned int keylen; 8519c4a7965SKim Phillips unsigned int enckeylen; 8529c4a7965SKim Phillips unsigned int authkeylen; 8539c4a7965SKim Phillips }; 8549c4a7965SKim Phillips 855497f2e6bSLee Nipper #define HASH_MAX_BLOCK_SIZE SHA512_BLOCK_SIZE 856497f2e6bSLee Nipper #define TALITOS_MDEU_MAX_CONTEXT_SIZE TALITOS_MDEU_CONTEXT_SIZE_SHA384_SHA512 857497f2e6bSLee Nipper 858497f2e6bSLee Nipper struct talitos_ahash_req_ctx { 85960f208d7SKim Phillips u32 hw_context[TALITOS_MDEU_MAX_CONTEXT_SIZE / sizeof(u32)]; 860497f2e6bSLee Nipper unsigned int hw_context_size; 8613c0dd190SLEROY Christophe u8 buf[2][HASH_MAX_BLOCK_SIZE]; 8623c0dd190SLEROY Christophe int buf_idx; 86360f208d7SKim Phillips unsigned int swinit; 864497f2e6bSLee Nipper unsigned int first; 865497f2e6bSLee Nipper unsigned int last; 866497f2e6bSLee Nipper unsigned int to_hash_later; 86742e8b0d7SHoria Geant? unsigned int nbuf; 868497f2e6bSLee Nipper struct scatterlist bufsl[2]; 869497f2e6bSLee Nipper struct scatterlist *psrc; 870497f2e6bSLee Nipper }; 871497f2e6bSLee Nipper 8723639ca84SHoria Geant? struct talitos_export_state { 8733639ca84SHoria Geant? u32 hw_context[TALITOS_MDEU_MAX_CONTEXT_SIZE / sizeof(u32)]; 8743639ca84SHoria Geant? u8 buf[HASH_MAX_BLOCK_SIZE]; 8753639ca84SHoria Geant? unsigned int swinit; 8763639ca84SHoria Geant? unsigned int first; 8773639ca84SHoria Geant? unsigned int last; 8783639ca84SHoria Geant? unsigned int to_hash_later; 8793639ca84SHoria Geant? unsigned int nbuf; 8803639ca84SHoria Geant? }; 8813639ca84SHoria Geant? 88256af8cd4SLee Nipper static int aead_setkey(struct crypto_aead *authenc, 8839c4a7965SKim Phillips const u8 *key, unsigned int keylen) 8849c4a7965SKim Phillips { 8859c4a7965SKim Phillips struct talitos_ctx *ctx = crypto_aead_ctx(authenc); 8862e13ce08SLEROY Christophe struct device *dev = ctx->dev; 887c306a98dSMathias Krause struct crypto_authenc_keys keys; 8889c4a7965SKim Phillips 889c306a98dSMathias Krause if (crypto_authenc_extractkeys(&keys, key, keylen) != 0) 8909c4a7965SKim Phillips goto badkey; 8919c4a7965SKim Phillips 892c306a98dSMathias Krause if (keys.authkeylen + keys.enckeylen > TALITOS_MAX_KEY_SIZE) 8939c4a7965SKim Phillips goto badkey; 8949c4a7965SKim Phillips 8952e13ce08SLEROY Christophe if (ctx->keylen) 8962e13ce08SLEROY Christophe dma_unmap_single(dev, ctx->dma_key, ctx->keylen, DMA_TO_DEVICE); 8972e13ce08SLEROY Christophe 898c306a98dSMathias Krause memcpy(ctx->key, keys.authkey, keys.authkeylen); 899c306a98dSMathias Krause memcpy(&ctx->key[keys.authkeylen], keys.enckey, keys.enckeylen); 9009c4a7965SKim Phillips 901c306a98dSMathias Krause ctx->keylen = keys.authkeylen + keys.enckeylen; 902c306a98dSMathias Krause ctx->enckeylen = keys.enckeylen; 903c306a98dSMathias Krause ctx->authkeylen = keys.authkeylen; 9042e13ce08SLEROY Christophe ctx->dma_key = dma_map_single(dev, ctx->key, ctx->keylen, 9052e13ce08SLEROY Christophe DMA_TO_DEVICE); 9069c4a7965SKim Phillips 9078f0691fcSTudor-Dan Ambarus memzero_explicit(&keys, sizeof(keys)); 9089c4a7965SKim Phillips return 0; 9099c4a7965SKim Phillips 9109c4a7965SKim Phillips badkey: 9119c4a7965SKim Phillips crypto_aead_set_flags(authenc, CRYPTO_TFM_RES_BAD_KEY_LEN); 9128f0691fcSTudor-Dan Ambarus memzero_explicit(&keys, sizeof(keys)); 9139c4a7965SKim Phillips return -EINVAL; 9149c4a7965SKim Phillips } 9159c4a7965SKim Phillips 916*ef7c5c85SHerbert Xu static int aead_des3_setkey(struct crypto_aead *authenc, 917*ef7c5c85SHerbert Xu const u8 *key, unsigned int keylen) 918*ef7c5c85SHerbert Xu { 919*ef7c5c85SHerbert Xu struct talitos_ctx *ctx = crypto_aead_ctx(authenc); 920*ef7c5c85SHerbert Xu struct device *dev = ctx->dev; 921*ef7c5c85SHerbert Xu struct crypto_authenc_keys keys; 922*ef7c5c85SHerbert Xu u32 flags; 923*ef7c5c85SHerbert Xu int err; 924*ef7c5c85SHerbert Xu 925*ef7c5c85SHerbert Xu err = crypto_authenc_extractkeys(&keys, key, keylen); 926*ef7c5c85SHerbert Xu if (unlikely(err)) 927*ef7c5c85SHerbert Xu goto badkey; 928*ef7c5c85SHerbert Xu 929*ef7c5c85SHerbert Xu err = -EINVAL; 930*ef7c5c85SHerbert Xu if (keys.authkeylen + keys.enckeylen > TALITOS_MAX_KEY_SIZE) 931*ef7c5c85SHerbert Xu goto badkey; 932*ef7c5c85SHerbert Xu 933*ef7c5c85SHerbert Xu if (keys.enckeylen != DES3_EDE_KEY_SIZE) 934*ef7c5c85SHerbert Xu goto badkey; 935*ef7c5c85SHerbert Xu 936*ef7c5c85SHerbert Xu flags = crypto_aead_get_flags(authenc); 937*ef7c5c85SHerbert Xu err = __des3_verify_key(&flags, keys.enckey); 938*ef7c5c85SHerbert Xu if (unlikely(err)) { 939*ef7c5c85SHerbert Xu crypto_aead_set_flags(authenc, flags); 940*ef7c5c85SHerbert Xu goto out; 941*ef7c5c85SHerbert Xu } 942*ef7c5c85SHerbert Xu 943*ef7c5c85SHerbert Xu if (ctx->keylen) 944*ef7c5c85SHerbert Xu dma_unmap_single(dev, ctx->dma_key, ctx->keylen, DMA_TO_DEVICE); 945*ef7c5c85SHerbert Xu 946*ef7c5c85SHerbert Xu memcpy(ctx->key, keys.authkey, keys.authkeylen); 947*ef7c5c85SHerbert Xu memcpy(&ctx->key[keys.authkeylen], keys.enckey, keys.enckeylen); 948*ef7c5c85SHerbert Xu 949*ef7c5c85SHerbert Xu ctx->keylen = keys.authkeylen + keys.enckeylen; 950*ef7c5c85SHerbert Xu ctx->enckeylen = keys.enckeylen; 951*ef7c5c85SHerbert Xu ctx->authkeylen = keys.authkeylen; 952*ef7c5c85SHerbert Xu ctx->dma_key = dma_map_single(dev, ctx->key, ctx->keylen, 953*ef7c5c85SHerbert Xu DMA_TO_DEVICE); 954*ef7c5c85SHerbert Xu 955*ef7c5c85SHerbert Xu out: 956*ef7c5c85SHerbert Xu memzero_explicit(&keys, sizeof(keys)); 957*ef7c5c85SHerbert Xu return err; 958*ef7c5c85SHerbert Xu 959*ef7c5c85SHerbert Xu badkey: 960*ef7c5c85SHerbert Xu crypto_aead_set_flags(authenc, CRYPTO_TFM_RES_BAD_KEY_LEN); 961*ef7c5c85SHerbert Xu goto out; 962*ef7c5c85SHerbert Xu } 963*ef7c5c85SHerbert Xu 9649c4a7965SKim Phillips /* 96556af8cd4SLee Nipper * talitos_edesc - s/w-extended descriptor 9669c4a7965SKim Phillips * @src_nents: number of segments in input scatterlist 9679c4a7965SKim Phillips * @dst_nents: number of segments in output scatterlist 968aeb4c132SHerbert Xu * @icv_ool: whether ICV is out-of-line 96979fd31d3SHoria Geanta * @iv_dma: dma address of iv for checking continuity and link table 9709c4a7965SKim Phillips * @dma_len: length of dma mapped link_tbl space 9716f65f6acSLEROY Christophe * @dma_link_tbl: bus physical address of link_tbl/buf 9729c4a7965SKim Phillips * @desc: h/w descriptor 9736f65f6acSLEROY Christophe * @link_tbl: input and output h/w link tables (if {src,dst}_nents > 1) (SEC2) 9746f65f6acSLEROY Christophe * @buf: input and output buffeur (if {src,dst}_nents > 1) (SEC1) 9759c4a7965SKim Phillips * 9769c4a7965SKim Phillips * if decrypting (with authcheck), or either one of src_nents or dst_nents 9779c4a7965SKim Phillips * is greater than 1, an integrity check value is concatenated to the end 9789c4a7965SKim Phillips * of link_tbl data 9799c4a7965SKim Phillips */ 98056af8cd4SLee Nipper struct talitos_edesc { 9819c4a7965SKim Phillips int src_nents; 9829c4a7965SKim Phillips int dst_nents; 983aeb4c132SHerbert Xu bool icv_ool; 98479fd31d3SHoria Geanta dma_addr_t iv_dma; 9859c4a7965SKim Phillips int dma_len; 9869c4a7965SKim Phillips dma_addr_t dma_link_tbl; 9879c4a7965SKim Phillips struct talitos_desc desc; 9886f65f6acSLEROY Christophe union { 9899c4a7965SKim Phillips struct talitos_ptr link_tbl[0]; 9906f65f6acSLEROY Christophe u8 buf[0]; 9916f65f6acSLEROY Christophe }; 9929c4a7965SKim Phillips }; 9939c4a7965SKim Phillips 9944de9d0b5SLee Nipper static void talitos_sg_unmap(struct device *dev, 9954de9d0b5SLee Nipper struct talitos_edesc *edesc, 9964de9d0b5SLee Nipper struct scatterlist *src, 9976a1e8d14SLEROY Christophe struct scatterlist *dst, 9986a1e8d14SLEROY Christophe unsigned int len, unsigned int offset) 999246a87cdSLEROY Christophe { 1000246a87cdSLEROY Christophe struct talitos_private *priv = dev_get_drvdata(dev); 1001246a87cdSLEROY Christophe bool is_sec1 = has_ftr_sec1(priv); 10026a1e8d14SLEROY Christophe unsigned int src_nents = edesc->src_nents ? : 1; 10036a1e8d14SLEROY Christophe unsigned int dst_nents = edesc->dst_nents ? : 1; 1004246a87cdSLEROY Christophe 10056a1e8d14SLEROY Christophe if (is_sec1 && dst && dst_nents > 1) { 10066a1e8d14SLEROY Christophe dma_sync_single_for_device(dev, edesc->dma_link_tbl + offset, 1007246a87cdSLEROY Christophe len, DMA_FROM_DEVICE); 10086a1e8d14SLEROY Christophe sg_pcopy_from_buffer(dst, dst_nents, edesc->buf + offset, len, 10096a1e8d14SLEROY Christophe offset); 1010246a87cdSLEROY Christophe } 10116a1e8d14SLEROY Christophe if (src != dst) { 10126a1e8d14SLEROY Christophe if (src_nents == 1 || !is_sec1) 10136a1e8d14SLEROY Christophe dma_unmap_sg(dev, src, src_nents, DMA_TO_DEVICE); 10146a1e8d14SLEROY Christophe 10156a1e8d14SLEROY Christophe if (dst && (dst_nents == 1 || !is_sec1)) 10166a1e8d14SLEROY Christophe dma_unmap_sg(dev, dst, dst_nents, DMA_FROM_DEVICE); 10176a1e8d14SLEROY Christophe } else if (src_nents == 1 || !is_sec1) { 10186a1e8d14SLEROY Christophe dma_unmap_sg(dev, src, src_nents, DMA_BIDIRECTIONAL); 1019246a87cdSLEROY Christophe } 1020246a87cdSLEROY Christophe } 1021246a87cdSLEROY Christophe 10229c4a7965SKim Phillips static void ipsec_esp_unmap(struct device *dev, 102356af8cd4SLee Nipper struct talitos_edesc *edesc, 10249c4a7965SKim Phillips struct aead_request *areq) 10259c4a7965SKim Phillips { 1026549bd8bcSLEROY Christophe struct crypto_aead *aead = crypto_aead_reqtfm(areq); 1027549bd8bcSLEROY Christophe struct talitos_ctx *ctx = crypto_aead_ctx(aead); 1028549bd8bcSLEROY Christophe unsigned int ivsize = crypto_aead_ivsize(aead); 10299a655608SLEROY Christophe bool is_ipsec_esp = edesc->desc.hdr & DESC_HDR_TYPE_IPSEC_ESP; 10309a655608SLEROY Christophe struct talitos_ptr *civ_ptr = &edesc->desc.ptr[is_ipsec_esp ? 2 : 3]; 1031549bd8bcSLEROY Christophe 10329a655608SLEROY Christophe if (is_ipsec_esp) 1033549bd8bcSLEROY Christophe unmap_single_talitos_ptr(dev, &edesc->desc.ptr[6], 1034549bd8bcSLEROY Christophe DMA_FROM_DEVICE); 10359a655608SLEROY Christophe unmap_single_talitos_ptr(dev, civ_ptr, DMA_TO_DEVICE); 10369c4a7965SKim Phillips 10376a1e8d14SLEROY Christophe talitos_sg_unmap(dev, edesc, areq->src, areq->dst, areq->cryptlen, 10386a1e8d14SLEROY Christophe areq->assoclen); 10399c4a7965SKim Phillips 10409c4a7965SKim Phillips if (edesc->dma_len) 10419c4a7965SKim Phillips dma_unmap_single(dev, edesc->dma_link_tbl, edesc->dma_len, 10429c4a7965SKim Phillips DMA_BIDIRECTIONAL); 1043549bd8bcSLEROY Christophe 10449a655608SLEROY Christophe if (!is_ipsec_esp) { 1045549bd8bcSLEROY Christophe unsigned int dst_nents = edesc->dst_nents ? : 1; 1046549bd8bcSLEROY Christophe 1047549bd8bcSLEROY Christophe sg_pcopy_to_buffer(areq->dst, dst_nents, ctx->iv, ivsize, 1048549bd8bcSLEROY Christophe areq->assoclen + areq->cryptlen - ivsize); 1049549bd8bcSLEROY Christophe } 10509c4a7965SKim Phillips } 10519c4a7965SKim Phillips 10529c4a7965SKim Phillips /* 10539c4a7965SKim Phillips * ipsec_esp descriptor callbacks 10549c4a7965SKim Phillips */ 10559c4a7965SKim Phillips static void ipsec_esp_encrypt_done(struct device *dev, 10569c4a7965SKim Phillips struct talitos_desc *desc, void *context, 10579c4a7965SKim Phillips int err) 10589c4a7965SKim Phillips { 1059549bd8bcSLEROY Christophe struct talitos_private *priv = dev_get_drvdata(dev); 1060549bd8bcSLEROY Christophe bool is_sec1 = has_ftr_sec1(priv); 10619c4a7965SKim Phillips struct aead_request *areq = context; 10629c4a7965SKim Phillips struct crypto_aead *authenc = crypto_aead_reqtfm(areq); 1063aeb4c132SHerbert Xu unsigned int authsize = crypto_aead_authsize(authenc); 10642e13ce08SLEROY Christophe unsigned int ivsize = crypto_aead_ivsize(authenc); 106519bbbc63SKim Phillips struct talitos_edesc *edesc; 10669c4a7965SKim Phillips struct scatterlist *sg; 10679c4a7965SKim Phillips void *icvdata; 10689c4a7965SKim Phillips 106919bbbc63SKim Phillips edesc = container_of(desc, struct talitos_edesc, desc); 107019bbbc63SKim Phillips 10719c4a7965SKim Phillips ipsec_esp_unmap(dev, edesc, areq); 10729c4a7965SKim Phillips 10739c4a7965SKim Phillips /* copy the generated ICV to dst */ 1074aeb4c132SHerbert Xu if (edesc->icv_ool) { 1075549bd8bcSLEROY Christophe if (is_sec1) 1076549bd8bcSLEROY Christophe icvdata = edesc->buf + areq->assoclen + areq->cryptlen; 1077549bd8bcSLEROY Christophe else 10789c4a7965SKim Phillips icvdata = &edesc->link_tbl[edesc->src_nents + 1079aeb4c132SHerbert Xu edesc->dst_nents + 2]; 10809c4a7965SKim Phillips sg = sg_last(areq->dst, edesc->dst_nents); 1081aeb4c132SHerbert Xu memcpy((char *)sg_virt(sg) + sg->length - authsize, 1082aeb4c132SHerbert Xu icvdata, authsize); 10839c4a7965SKim Phillips } 10849c4a7965SKim Phillips 10852e13ce08SLEROY Christophe dma_unmap_single(dev, edesc->iv_dma, ivsize, DMA_TO_DEVICE); 10862e13ce08SLEROY Christophe 10879c4a7965SKim Phillips kfree(edesc); 10889c4a7965SKim Phillips 10899c4a7965SKim Phillips aead_request_complete(areq, err); 10909c4a7965SKim Phillips } 10919c4a7965SKim Phillips 1092fe5720e2SKim Phillips static void ipsec_esp_decrypt_swauth_done(struct device *dev, 1093e938e465SKim Phillips struct talitos_desc *desc, 1094e938e465SKim Phillips void *context, int err) 10959c4a7965SKim Phillips { 10969c4a7965SKim Phillips struct aead_request *req = context; 10979c4a7965SKim Phillips struct crypto_aead *authenc = crypto_aead_reqtfm(req); 1098aeb4c132SHerbert Xu unsigned int authsize = crypto_aead_authsize(authenc); 109919bbbc63SKim Phillips struct talitos_edesc *edesc; 11009c4a7965SKim Phillips struct scatterlist *sg; 1101aeb4c132SHerbert Xu char *oicv, *icv; 1102549bd8bcSLEROY Christophe struct talitos_private *priv = dev_get_drvdata(dev); 1103549bd8bcSLEROY Christophe bool is_sec1 = has_ftr_sec1(priv); 11049c4a7965SKim Phillips 110519bbbc63SKim Phillips edesc = container_of(desc, struct talitos_edesc, desc); 110619bbbc63SKim Phillips 11079c4a7965SKim Phillips ipsec_esp_unmap(dev, edesc, req); 11089c4a7965SKim Phillips 11099c4a7965SKim Phillips if (!err) { 11109c4a7965SKim Phillips /* auth check */ 11119c4a7965SKim Phillips sg = sg_last(req->dst, edesc->dst_nents ? : 1); 1112aeb4c132SHerbert Xu icv = (char *)sg_virt(sg) + sg->length - authsize; 1113aeb4c132SHerbert Xu 1114aeb4c132SHerbert Xu if (edesc->dma_len) { 1115549bd8bcSLEROY Christophe if (is_sec1) 1116549bd8bcSLEROY Christophe oicv = (char *)&edesc->dma_link_tbl + 1117549bd8bcSLEROY Christophe req->assoclen + req->cryptlen; 1118549bd8bcSLEROY Christophe else 1119549bd8bcSLEROY Christophe oicv = (char *) 1120549bd8bcSLEROY Christophe &edesc->link_tbl[edesc->src_nents + 1121aeb4c132SHerbert Xu edesc->dst_nents + 2]; 1122aeb4c132SHerbert Xu if (edesc->icv_ool) 1123aeb4c132SHerbert Xu icv = oicv + authsize; 1124aeb4c132SHerbert Xu } else 1125aeb4c132SHerbert Xu oicv = (char *)&edesc->link_tbl[0]; 1126aeb4c132SHerbert Xu 112779960943SDavid Gstir err = crypto_memneq(oicv, icv, authsize) ? -EBADMSG : 0; 11289c4a7965SKim Phillips } 11299c4a7965SKim Phillips 11309c4a7965SKim Phillips kfree(edesc); 11319c4a7965SKim Phillips 11329c4a7965SKim Phillips aead_request_complete(req, err); 11339c4a7965SKim Phillips } 11349c4a7965SKim Phillips 1135fe5720e2SKim Phillips static void ipsec_esp_decrypt_hwauth_done(struct device *dev, 1136e938e465SKim Phillips struct talitos_desc *desc, 1137e938e465SKim Phillips void *context, int err) 1138fe5720e2SKim Phillips { 1139fe5720e2SKim Phillips struct aead_request *req = context; 114019bbbc63SKim Phillips struct talitos_edesc *edesc; 114119bbbc63SKim Phillips 114219bbbc63SKim Phillips edesc = container_of(desc, struct talitos_edesc, desc); 1143fe5720e2SKim Phillips 1144fe5720e2SKim Phillips ipsec_esp_unmap(dev, edesc, req); 1145fe5720e2SKim Phillips 1146fe5720e2SKim Phillips /* check ICV auth status */ 1147e938e465SKim Phillips if (!err && ((desc->hdr_lo & DESC_HDR_LO_ICCR1_MASK) != 1148e938e465SKim Phillips DESC_HDR_LO_ICCR1_PASS)) 1149fe5720e2SKim Phillips err = -EBADMSG; 1150fe5720e2SKim Phillips 1151fe5720e2SKim Phillips kfree(edesc); 1152fe5720e2SKim Phillips 1153fe5720e2SKim Phillips aead_request_complete(req, err); 1154fe5720e2SKim Phillips } 1155fe5720e2SKim Phillips 11569c4a7965SKim Phillips /* 11579c4a7965SKim Phillips * convert scatterlist to SEC h/w link table format 11589c4a7965SKim Phillips * stop at cryptlen bytes 11599c4a7965SKim Phillips */ 1160aeb4c132SHerbert Xu static int sg_to_link_tbl_offset(struct scatterlist *sg, int sg_count, 1161aeb4c132SHerbert Xu unsigned int offset, int cryptlen, 1162aeb4c132SHerbert Xu struct talitos_ptr *link_tbl_ptr) 11639c4a7965SKim Phillips { 116470bcaca7SLee Nipper int n_sg = sg_count; 1165aeb4c132SHerbert Xu int count = 0; 116670bcaca7SLee Nipper 1167aeb4c132SHerbert Xu while (cryptlen && sg && n_sg--) { 1168aeb4c132SHerbert Xu unsigned int len = sg_dma_len(sg); 1169aeb4c132SHerbert Xu 1170aeb4c132SHerbert Xu if (offset >= len) { 1171aeb4c132SHerbert Xu offset -= len; 1172aeb4c132SHerbert Xu goto next; 1173aeb4c132SHerbert Xu } 1174aeb4c132SHerbert Xu 1175aeb4c132SHerbert Xu len -= offset; 1176aeb4c132SHerbert Xu 1177aeb4c132SHerbert Xu if (len > cryptlen) 1178aeb4c132SHerbert Xu len = cryptlen; 1179aeb4c132SHerbert Xu 1180aeb4c132SHerbert Xu to_talitos_ptr(link_tbl_ptr + count, 1181da9de146SLEROY Christophe sg_dma_address(sg) + offset, len, 0); 1182b096b544SLEROY Christophe to_talitos_ptr_ext_set(link_tbl_ptr + count, 0, 0); 1183aeb4c132SHerbert Xu count++; 1184aeb4c132SHerbert Xu cryptlen -= len; 1185aeb4c132SHerbert Xu offset = 0; 1186aeb4c132SHerbert Xu 1187aeb4c132SHerbert Xu next: 11885be4d4c9SCristian Stoica sg = sg_next(sg); 11899c4a7965SKim Phillips } 11909c4a7965SKim Phillips 11919c4a7965SKim Phillips /* tag end of link table */ 1192aeb4c132SHerbert Xu if (count > 0) 1193b096b544SLEROY Christophe to_talitos_ptr_ext_set(link_tbl_ptr + count - 1, 1194b096b544SLEROY Christophe DESC_PTR_LNKTBL_RETURN, 0); 119570bcaca7SLee Nipper 1196aeb4c132SHerbert Xu return count; 1197aeb4c132SHerbert Xu } 1198aeb4c132SHerbert Xu 11992b122730SLEROY Christophe static int talitos_sg_map_ext(struct device *dev, struct scatterlist *src, 1200246a87cdSLEROY Christophe unsigned int len, struct talitos_edesc *edesc, 12012b122730SLEROY Christophe struct talitos_ptr *ptr, int sg_count, 12022b122730SLEROY Christophe unsigned int offset, int tbl_off, int elen) 1203246a87cdSLEROY Christophe { 1204246a87cdSLEROY Christophe struct talitos_private *priv = dev_get_drvdata(dev); 1205246a87cdSLEROY Christophe bool is_sec1 = has_ftr_sec1(priv); 1206246a87cdSLEROY Christophe 120787a81dceSLEROY Christophe if (!src) { 120887a81dceSLEROY Christophe to_talitos_ptr(ptr, 0, 0, is_sec1); 120987a81dceSLEROY Christophe return 1; 121087a81dceSLEROY Christophe } 12112b122730SLEROY Christophe to_talitos_ptr_ext_set(ptr, elen, is_sec1); 1212246a87cdSLEROY Christophe if (sg_count == 1) { 1213da9de146SLEROY Christophe to_talitos_ptr(ptr, sg_dma_address(src) + offset, len, is_sec1); 1214246a87cdSLEROY Christophe return sg_count; 1215246a87cdSLEROY Christophe } 1216246a87cdSLEROY Christophe if (is_sec1) { 1217da9de146SLEROY Christophe to_talitos_ptr(ptr, edesc->dma_link_tbl + offset, len, is_sec1); 12186a1e8d14SLEROY Christophe return sg_count; 1219246a87cdSLEROY Christophe } 12202b122730SLEROY Christophe sg_count = sg_to_link_tbl_offset(src, sg_count, offset, len + elen, 12216a1e8d14SLEROY Christophe &edesc->link_tbl[tbl_off]); 1222246a87cdSLEROY Christophe if (sg_count == 1) { 12236a1e8d14SLEROY Christophe /* Only one segment now, so no link tbl needed*/ 12246a1e8d14SLEROY Christophe copy_talitos_ptr(ptr, &edesc->link_tbl[tbl_off], is_sec1); 12256a1e8d14SLEROY Christophe return sg_count; 12266a1e8d14SLEROY Christophe } 1227246a87cdSLEROY Christophe to_talitos_ptr(ptr, edesc->dma_link_tbl + 1228da9de146SLEROY Christophe tbl_off * sizeof(struct talitos_ptr), len, is_sec1); 12296a1e8d14SLEROY Christophe to_talitos_ptr_ext_or(ptr, DESC_PTR_LNKTBL_JUMP, is_sec1); 12306a1e8d14SLEROY Christophe 12316a1e8d14SLEROY Christophe return sg_count; 1232246a87cdSLEROY Christophe } 1233246a87cdSLEROY Christophe 12342b122730SLEROY Christophe static int talitos_sg_map(struct device *dev, struct scatterlist *src, 12352b122730SLEROY Christophe unsigned int len, struct talitos_edesc *edesc, 12362b122730SLEROY Christophe struct talitos_ptr *ptr, int sg_count, 12372b122730SLEROY Christophe unsigned int offset, int tbl_off) 12382b122730SLEROY Christophe { 12392b122730SLEROY Christophe return talitos_sg_map_ext(dev, src, len, edesc, ptr, sg_count, offset, 12402b122730SLEROY Christophe tbl_off, 0); 12412b122730SLEROY Christophe } 12422b122730SLEROY Christophe 12439c4a7965SKim Phillips /* 12449c4a7965SKim Phillips * fill in and submit ipsec_esp descriptor 12459c4a7965SKim Phillips */ 124656af8cd4SLee Nipper static int ipsec_esp(struct talitos_edesc *edesc, struct aead_request *areq, 1247aeb4c132SHerbert Xu void (*callback)(struct device *dev, 12489c4a7965SKim Phillips struct talitos_desc *desc, 12499c4a7965SKim Phillips void *context, int error)) 12509c4a7965SKim Phillips { 12519c4a7965SKim Phillips struct crypto_aead *aead = crypto_aead_reqtfm(areq); 1252aeb4c132SHerbert Xu unsigned int authsize = crypto_aead_authsize(aead); 12539c4a7965SKim Phillips struct talitos_ctx *ctx = crypto_aead_ctx(aead); 12549c4a7965SKim Phillips struct device *dev = ctx->dev; 12559c4a7965SKim Phillips struct talitos_desc *desc = &edesc->desc; 12569c4a7965SKim Phillips unsigned int cryptlen = areq->cryptlen; 1257e41256f1SKim Phillips unsigned int ivsize = crypto_aead_ivsize(aead); 1258aeb4c132SHerbert Xu int tbl_off = 0; 1259fa86a267SKim Phillips int sg_count, ret; 12602b122730SLEROY Christophe int elen = 0; 1261549bd8bcSLEROY Christophe bool sync_needed = false; 1262549bd8bcSLEROY Christophe struct talitos_private *priv = dev_get_drvdata(dev); 1263549bd8bcSLEROY Christophe bool is_sec1 = has_ftr_sec1(priv); 12649a655608SLEROY Christophe bool is_ipsec_esp = desc->hdr & DESC_HDR_TYPE_IPSEC_ESP; 12659a655608SLEROY Christophe struct talitos_ptr *civ_ptr = &desc->ptr[is_ipsec_esp ? 2 : 3]; 12669a655608SLEROY Christophe struct talitos_ptr *ckey_ptr = &desc->ptr[is_ipsec_esp ? 3 : 2]; 12679c4a7965SKim Phillips 12689c4a7965SKim Phillips /* hmac key */ 12692e13ce08SLEROY Christophe to_talitos_ptr(&desc->ptr[0], ctx->dma_key, ctx->authkeylen, is_sec1); 127079fd31d3SHoria Geanta 1271549bd8bcSLEROY Christophe sg_count = edesc->src_nents ?: 1; 1272549bd8bcSLEROY Christophe if (is_sec1 && sg_count > 1) 1273549bd8bcSLEROY Christophe sg_copy_to_buffer(areq->src, sg_count, edesc->buf, 1274549bd8bcSLEROY Christophe areq->assoclen + cryptlen); 1275549bd8bcSLEROY Christophe else 1276549bd8bcSLEROY Christophe sg_count = dma_map_sg(dev, areq->src, sg_count, 1277549bd8bcSLEROY Christophe (areq->src == areq->dst) ? 1278549bd8bcSLEROY Christophe DMA_BIDIRECTIONAL : DMA_TO_DEVICE); 1279549bd8bcSLEROY Christophe 12809c4a7965SKim Phillips /* hmac data */ 1281549bd8bcSLEROY Christophe ret = talitos_sg_map(dev, areq->src, areq->assoclen, edesc, 1282549bd8bcSLEROY Christophe &desc->ptr[1], sg_count, 0, tbl_off); 128379fd31d3SHoria Geanta 1284549bd8bcSLEROY Christophe if (ret > 1) { 1285340ff60aSHoria Geant? tbl_off += ret; 1286549bd8bcSLEROY Christophe sync_needed = true; 128779fd31d3SHoria Geanta } 128879fd31d3SHoria Geanta 12899c4a7965SKim Phillips /* cipher iv */ 12909a655608SLEROY Christophe to_talitos_ptr(civ_ptr, edesc->iv_dma, ivsize, is_sec1); 12919c4a7965SKim Phillips 12929c4a7965SKim Phillips /* cipher key */ 12932e13ce08SLEROY Christophe to_talitos_ptr(ckey_ptr, ctx->dma_key + ctx->authkeylen, 12942e13ce08SLEROY Christophe ctx->enckeylen, is_sec1); 12959c4a7965SKim Phillips 12969c4a7965SKim Phillips /* 12979c4a7965SKim Phillips * cipher in 12989c4a7965SKim Phillips * map and adjust cipher len to aead request cryptlen. 12999c4a7965SKim Phillips * extent is bytes of HMAC postpended to ciphertext, 13009c4a7965SKim Phillips * typically 12 for ipsec 13019c4a7965SKim Phillips */ 13022b122730SLEROY Christophe if (is_ipsec_esp && (desc->hdr & DESC_HDR_MODE1_MDEU_CICV)) 13032b122730SLEROY Christophe elen = authsize; 1304549bd8bcSLEROY Christophe 13052b122730SLEROY Christophe ret = talitos_sg_map_ext(dev, areq->src, cryptlen, edesc, &desc->ptr[4], 13062b122730SLEROY Christophe sg_count, areq->assoclen, tbl_off, elen); 1307549bd8bcSLEROY Christophe 1308ec8c7d14SLEROY Christophe if (ret > 1) { 1309ec8c7d14SLEROY Christophe tbl_off += ret; 1310549bd8bcSLEROY Christophe sync_needed = true; 1311340ff60aSHoria Geant? } 13129c4a7965SKim Phillips 13139c4a7965SKim Phillips /* cipher out */ 1314549bd8bcSLEROY Christophe if (areq->src != areq->dst) { 1315549bd8bcSLEROY Christophe sg_count = edesc->dst_nents ? : 1; 1316549bd8bcSLEROY Christophe if (!is_sec1 || sg_count == 1) 1317549bd8bcSLEROY Christophe dma_map_sg(dev, areq->dst, sg_count, DMA_FROM_DEVICE); 1318549bd8bcSLEROY Christophe } 13199c4a7965SKim Phillips 1320e04a61beSLEROY Christophe ret = talitos_sg_map(dev, areq->dst, cryptlen, edesc, &desc->ptr[5], 1321e04a61beSLEROY Christophe sg_count, areq->assoclen, tbl_off); 13229c4a7965SKim Phillips 13239a655608SLEROY Christophe if (is_ipsec_esp) 1324549bd8bcSLEROY Christophe to_talitos_ptr_ext_or(&desc->ptr[5], authsize, is_sec1); 1325aeb4c132SHerbert Xu 1326e04a61beSLEROY Christophe /* ICV data */ 1327e04a61beSLEROY Christophe if (ret > 1) { 1328e04a61beSLEROY Christophe tbl_off += ret; 1329549bd8bcSLEROY Christophe edesc->icv_ool = true; 1330549bd8bcSLEROY Christophe sync_needed = true; 1331549bd8bcSLEROY Christophe 13329a655608SLEROY Christophe if (is_ipsec_esp) { 133379fd31d3SHoria Geanta struct talitos_ptr *tbl_ptr = &edesc->link_tbl[tbl_off]; 1334549bd8bcSLEROY Christophe int offset = (edesc->src_nents + edesc->dst_nents + 2) * 1335549bd8bcSLEROY Christophe sizeof(struct talitos_ptr) + authsize; 1336fe5720e2SKim Phillips 1337f3c85bc1SLee Nipper /* Add an entry to the link table for ICV data */ 1338e04a61beSLEROY Christophe to_talitos_ptr_ext_set(tbl_ptr - 1, 0, is_sec1); 1339549bd8bcSLEROY Christophe to_talitos_ptr_ext_set(tbl_ptr, DESC_PTR_LNKTBL_RETURN, 1340549bd8bcSLEROY Christophe is_sec1); 13419c4a7965SKim Phillips 13429c4a7965SKim Phillips /* icv data follows link tables */ 1343549bd8bcSLEROY Christophe to_talitos_ptr(tbl_ptr, edesc->dma_link_tbl + offset, 1344da9de146SLEROY Christophe authsize, is_sec1); 1345e04a61beSLEROY Christophe } else { 1346e04a61beSLEROY Christophe dma_addr_t addr = edesc->dma_link_tbl; 1347e04a61beSLEROY Christophe 1348e04a61beSLEROY Christophe if (is_sec1) 1349e04a61beSLEROY Christophe addr += areq->assoclen + cryptlen; 1350e04a61beSLEROY Christophe else 1351e04a61beSLEROY Christophe addr += sizeof(struct talitos_ptr) * tbl_off; 1352e04a61beSLEROY Christophe 1353da9de146SLEROY Christophe to_talitos_ptr(&desc->ptr[6], addr, authsize, is_sec1); 1354549bd8bcSLEROY Christophe } 13559a655608SLEROY Christophe } else if (!is_ipsec_esp) { 1356e04a61beSLEROY Christophe ret = talitos_sg_map(dev, areq->dst, authsize, edesc, 1357e04a61beSLEROY Christophe &desc->ptr[6], sg_count, areq->assoclen + 1358e04a61beSLEROY Christophe cryptlen, 1359e04a61beSLEROY Christophe tbl_off); 1360e04a61beSLEROY Christophe if (ret > 1) { 1361e04a61beSLEROY Christophe tbl_off += ret; 1362e04a61beSLEROY Christophe edesc->icv_ool = true; 1363e04a61beSLEROY Christophe sync_needed = true; 1364340ff60aSHoria Geant? } else { 1365549bd8bcSLEROY Christophe edesc->icv_ool = false; 1366549bd8bcSLEROY Christophe } 1367e04a61beSLEROY Christophe } else { 1368e04a61beSLEROY Christophe edesc->icv_ool = false; 1369340ff60aSHoria Geant? } 13709c4a7965SKim Phillips 13719c4a7965SKim Phillips /* iv out */ 13729a655608SLEROY Christophe if (is_ipsec_esp) 1373a2b35aa8SLEROY Christophe map_single_talitos_ptr(dev, &desc->ptr[6], ivsize, ctx->iv, 13749c4a7965SKim Phillips DMA_FROM_DEVICE); 13759c4a7965SKim Phillips 1376549bd8bcSLEROY Christophe if (sync_needed) 1377549bd8bcSLEROY Christophe dma_sync_single_for_device(dev, edesc->dma_link_tbl, 1378549bd8bcSLEROY Christophe edesc->dma_len, 1379549bd8bcSLEROY Christophe DMA_BIDIRECTIONAL); 1380549bd8bcSLEROY Christophe 13815228f0f7SKim Phillips ret = talitos_submit(dev, ctx->ch, desc, callback, areq); 1382fa86a267SKim Phillips if (ret != -EINPROGRESS) { 1383fa86a267SKim Phillips ipsec_esp_unmap(dev, edesc, areq); 1384fa86a267SKim Phillips kfree(edesc); 1385fa86a267SKim Phillips } 1386fa86a267SKim Phillips return ret; 13879c4a7965SKim Phillips } 13889c4a7965SKim Phillips 13899c4a7965SKim Phillips /* 139056af8cd4SLee Nipper * allocate and map the extended descriptor 13919c4a7965SKim Phillips */ 13924de9d0b5SLee Nipper static struct talitos_edesc *talitos_edesc_alloc(struct device *dev, 13934de9d0b5SLee Nipper struct scatterlist *src, 13944de9d0b5SLee Nipper struct scatterlist *dst, 139579fd31d3SHoria Geanta u8 *iv, 139679fd31d3SHoria Geanta unsigned int assoclen, 13974de9d0b5SLee Nipper unsigned int cryptlen, 13984de9d0b5SLee Nipper unsigned int authsize, 139979fd31d3SHoria Geanta unsigned int ivsize, 14004de9d0b5SLee Nipper int icv_stashing, 140162293a37SHoria Geanta u32 cryptoflags, 140262293a37SHoria Geanta bool encrypt) 14039c4a7965SKim Phillips { 140456af8cd4SLee Nipper struct talitos_edesc *edesc; 14056a1e8d14SLEROY Christophe int src_nents, dst_nents, alloc_len, dma_len, src_len, dst_len; 140679fd31d3SHoria Geanta dma_addr_t iv_dma = 0; 14074de9d0b5SLee Nipper gfp_t flags = cryptoflags & CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL : 1408586725f8SKim Phillips GFP_ATOMIC; 14096f65f6acSLEROY Christophe struct talitos_private *priv = dev_get_drvdata(dev); 14106f65f6acSLEROY Christophe bool is_sec1 = has_ftr_sec1(priv); 14116f65f6acSLEROY Christophe int max_len = is_sec1 ? TALITOS1_MAX_DATA_LEN : TALITOS2_MAX_DATA_LEN; 14129c4a7965SKim Phillips 14136f65f6acSLEROY Christophe if (cryptlen + authsize > max_len) { 14144de9d0b5SLee Nipper dev_err(dev, "length exceeds h/w max limit\n"); 14159c4a7965SKim Phillips return ERR_PTR(-EINVAL); 14169c4a7965SKim Phillips } 14179c4a7965SKim Phillips 141862293a37SHoria Geanta if (!dst || dst == src) { 14196a1e8d14SLEROY Christophe src_len = assoclen + cryptlen + authsize; 14206a1e8d14SLEROY Christophe src_nents = sg_nents_for_len(src, src_len); 14218e409fe1SLABBE Corentin if (src_nents < 0) { 14228e409fe1SLABBE Corentin dev_err(dev, "Invalid number of src SG.\n"); 1423c56c2e17SChristophe Leroy return ERR_PTR(-EINVAL); 14248e409fe1SLABBE Corentin } 14259c4a7965SKim Phillips src_nents = (src_nents == 1) ? 0 : src_nents; 142662293a37SHoria Geanta dst_nents = dst ? src_nents : 0; 14276a1e8d14SLEROY Christophe dst_len = 0; 142862293a37SHoria Geanta } else { /* dst && dst != src*/ 14296a1e8d14SLEROY Christophe src_len = assoclen + cryptlen + (encrypt ? 0 : authsize); 14306a1e8d14SLEROY Christophe src_nents = sg_nents_for_len(src, src_len); 14318e409fe1SLABBE Corentin if (src_nents < 0) { 14328e409fe1SLABBE Corentin dev_err(dev, "Invalid number of src SG.\n"); 1433c56c2e17SChristophe Leroy return ERR_PTR(-EINVAL); 14348e409fe1SLABBE Corentin } 143562293a37SHoria Geanta src_nents = (src_nents == 1) ? 0 : src_nents; 14366a1e8d14SLEROY Christophe dst_len = assoclen + cryptlen + (encrypt ? authsize : 0); 14376a1e8d14SLEROY Christophe dst_nents = sg_nents_for_len(dst, dst_len); 14388e409fe1SLABBE Corentin if (dst_nents < 0) { 14398e409fe1SLABBE Corentin dev_err(dev, "Invalid number of dst SG.\n"); 1440c56c2e17SChristophe Leroy return ERR_PTR(-EINVAL); 14418e409fe1SLABBE Corentin } 1442695ad589SLee Nipper dst_nents = (dst_nents == 1) ? 0 : dst_nents; 14439c4a7965SKim Phillips } 14449c4a7965SKim Phillips 14459c4a7965SKim Phillips /* 14469c4a7965SKim Phillips * allocate space for base edesc plus the link tables, 1447aeb4c132SHerbert Xu * allowing for two separate entries for AD and generated ICV (+ 2), 1448aeb4c132SHerbert Xu * and space for two sets of ICVs (stashed and generated) 14499c4a7965SKim Phillips */ 145056af8cd4SLee Nipper alloc_len = sizeof(struct talitos_edesc); 1451aeb4c132SHerbert Xu if (src_nents || dst_nents) { 14526f65f6acSLEROY Christophe if (is_sec1) 14536a1e8d14SLEROY Christophe dma_len = (src_nents ? src_len : 0) + 14546a1e8d14SLEROY Christophe (dst_nents ? dst_len : 0); 14556f65f6acSLEROY Christophe else 1456aeb4c132SHerbert Xu dma_len = (src_nents + dst_nents + 2) * 1457aeb4c132SHerbert Xu sizeof(struct talitos_ptr) + authsize * 2; 14589c4a7965SKim Phillips alloc_len += dma_len; 14599c4a7965SKim Phillips } else { 14609c4a7965SKim Phillips dma_len = 0; 14614de9d0b5SLee Nipper alloc_len += icv_stashing ? authsize : 0; 14629c4a7965SKim Phillips } 14639c4a7965SKim Phillips 146437b5e889SLEROY Christophe /* if its a ahash, add space for a second desc next to the first one */ 146537b5e889SLEROY Christophe if (is_sec1 && !dst) 146637b5e889SLEROY Christophe alloc_len += sizeof(struct talitos_desc); 14671bea445bSChristophe Leroy alloc_len += ivsize; 146837b5e889SLEROY Christophe 1469586725f8SKim Phillips edesc = kmalloc(alloc_len, GFP_DMA | flags); 1470c56c2e17SChristophe Leroy if (!edesc) 1471c56c2e17SChristophe Leroy return ERR_PTR(-ENOMEM); 14721bea445bSChristophe Leroy if (ivsize) { 14731bea445bSChristophe Leroy iv = memcpy(((u8 *)edesc) + alloc_len - ivsize, iv, ivsize); 1474c56c2e17SChristophe Leroy iv_dma = dma_map_single(dev, iv, ivsize, DMA_TO_DEVICE); 14751bea445bSChristophe Leroy } 1476e4a647c4SLEROY Christophe memset(&edesc->desc, 0, sizeof(edesc->desc)); 14779c4a7965SKim Phillips 14789c4a7965SKim Phillips edesc->src_nents = src_nents; 14799c4a7965SKim Phillips edesc->dst_nents = dst_nents; 148079fd31d3SHoria Geanta edesc->iv_dma = iv_dma; 14819c4a7965SKim Phillips edesc->dma_len = dma_len; 148237b5e889SLEROY Christophe if (dma_len) { 148337b5e889SLEROY Christophe void *addr = &edesc->link_tbl[0]; 148437b5e889SLEROY Christophe 148537b5e889SLEROY Christophe if (is_sec1 && !dst) 148637b5e889SLEROY Christophe addr += sizeof(struct talitos_desc); 148737b5e889SLEROY Christophe edesc->dma_link_tbl = dma_map_single(dev, addr, 1488497f2e6bSLee Nipper edesc->dma_len, 1489497f2e6bSLee Nipper DMA_BIDIRECTIONAL); 149037b5e889SLEROY Christophe } 14919c4a7965SKim Phillips return edesc; 14929c4a7965SKim Phillips } 14939c4a7965SKim Phillips 149479fd31d3SHoria Geanta static struct talitos_edesc *aead_edesc_alloc(struct aead_request *areq, u8 *iv, 149562293a37SHoria Geanta int icv_stashing, bool encrypt) 14964de9d0b5SLee Nipper { 14974de9d0b5SLee Nipper struct crypto_aead *authenc = crypto_aead_reqtfm(areq); 1498aeb4c132SHerbert Xu unsigned int authsize = crypto_aead_authsize(authenc); 14994de9d0b5SLee Nipper struct talitos_ctx *ctx = crypto_aead_ctx(authenc); 150079fd31d3SHoria Geanta unsigned int ivsize = crypto_aead_ivsize(authenc); 15014de9d0b5SLee Nipper 1502aeb4c132SHerbert Xu return talitos_edesc_alloc(ctx->dev, areq->src, areq->dst, 150379fd31d3SHoria Geanta iv, areq->assoclen, areq->cryptlen, 1504aeb4c132SHerbert Xu authsize, ivsize, icv_stashing, 150562293a37SHoria Geanta areq->base.flags, encrypt); 15064de9d0b5SLee Nipper } 15074de9d0b5SLee Nipper 150856af8cd4SLee Nipper static int aead_encrypt(struct aead_request *req) 15099c4a7965SKim Phillips { 15109c4a7965SKim Phillips struct crypto_aead *authenc = crypto_aead_reqtfm(req); 15119c4a7965SKim Phillips struct talitos_ctx *ctx = crypto_aead_ctx(authenc); 151256af8cd4SLee Nipper struct talitos_edesc *edesc; 15139c4a7965SKim Phillips 15149c4a7965SKim Phillips /* allocate extended descriptor */ 151562293a37SHoria Geanta edesc = aead_edesc_alloc(req, req->iv, 0, true); 15169c4a7965SKim Phillips if (IS_ERR(edesc)) 15179c4a7965SKim Phillips return PTR_ERR(edesc); 15189c4a7965SKim Phillips 15199c4a7965SKim Phillips /* set encrypt */ 152070bcaca7SLee Nipper edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_MODE0_ENCRYPT; 15219c4a7965SKim Phillips 1522aeb4c132SHerbert Xu return ipsec_esp(edesc, req, ipsec_esp_encrypt_done); 15239c4a7965SKim Phillips } 15249c4a7965SKim Phillips 152556af8cd4SLee Nipper static int aead_decrypt(struct aead_request *req) 15269c4a7965SKim Phillips { 15279c4a7965SKim Phillips struct crypto_aead *authenc = crypto_aead_reqtfm(req); 1528aeb4c132SHerbert Xu unsigned int authsize = crypto_aead_authsize(authenc); 15299c4a7965SKim Phillips struct talitos_ctx *ctx = crypto_aead_ctx(authenc); 1530fe5720e2SKim Phillips struct talitos_private *priv = dev_get_drvdata(ctx->dev); 153156af8cd4SLee Nipper struct talitos_edesc *edesc; 15329c4a7965SKim Phillips struct scatterlist *sg; 15339c4a7965SKim Phillips void *icvdata; 15349c4a7965SKim Phillips 15359c4a7965SKim Phillips req->cryptlen -= authsize; 15369c4a7965SKim Phillips 15379c4a7965SKim Phillips /* allocate extended descriptor */ 153862293a37SHoria Geanta edesc = aead_edesc_alloc(req, req->iv, 1, false); 15399c4a7965SKim Phillips if (IS_ERR(edesc)) 15409c4a7965SKim Phillips return PTR_ERR(edesc); 15419c4a7965SKim Phillips 1542fe5720e2SKim Phillips if ((priv->features & TALITOS_FTR_HW_AUTH_CHECK) && 1543e938e465SKim Phillips ((!edesc->src_nents && !edesc->dst_nents) || 1544e938e465SKim Phillips priv->features & TALITOS_FTR_SRC_LINK_TBL_LEN_INCLUDES_EXTENT)) { 1545fe5720e2SKim Phillips 1546fe5720e2SKim Phillips /* decrypt and check the ICV */ 1547e938e465SKim Phillips edesc->desc.hdr = ctx->desc_hdr_template | 1548e938e465SKim Phillips DESC_HDR_DIR_INBOUND | 1549fe5720e2SKim Phillips DESC_HDR_MODE1_MDEU_CICV; 1550fe5720e2SKim Phillips 1551fe5720e2SKim Phillips /* reset integrity check result bits */ 1552fe5720e2SKim Phillips 1553aeb4c132SHerbert Xu return ipsec_esp(edesc, req, ipsec_esp_decrypt_hwauth_done); 1554e938e465SKim Phillips } 1555fe5720e2SKim Phillips 1556fe5720e2SKim Phillips /* Have to check the ICV with software */ 1557fe5720e2SKim Phillips edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_DIR_INBOUND; 1558fe5720e2SKim Phillips 15599c4a7965SKim Phillips /* stash incoming ICV for later cmp with ICV generated by the h/w */ 15609c4a7965SKim Phillips if (edesc->dma_len) 1561aeb4c132SHerbert Xu icvdata = (char *)&edesc->link_tbl[edesc->src_nents + 1562aeb4c132SHerbert Xu edesc->dst_nents + 2]; 15639c4a7965SKim Phillips else 15649c4a7965SKim Phillips icvdata = &edesc->link_tbl[0]; 15659c4a7965SKim Phillips 15669c4a7965SKim Phillips sg = sg_last(req->src, edesc->src_nents ? : 1); 15679c4a7965SKim Phillips 1568aeb4c132SHerbert Xu memcpy(icvdata, (char *)sg_virt(sg) + sg->length - authsize, authsize); 15699c4a7965SKim Phillips 1570aeb4c132SHerbert Xu return ipsec_esp(edesc, req, ipsec_esp_decrypt_swauth_done); 15719c4a7965SKim Phillips } 15729c4a7965SKim Phillips 15734de9d0b5SLee Nipper static int ablkcipher_setkey(struct crypto_ablkcipher *cipher, 15744de9d0b5SLee Nipper const u8 *key, unsigned int keylen) 15754de9d0b5SLee Nipper { 15764de9d0b5SLee Nipper struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher); 15772e13ce08SLEROY Christophe struct device *dev = ctx->dev; 1578f384cdc4SLEROY Christophe 15792e13ce08SLEROY Christophe if (ctx->keylen) 15802e13ce08SLEROY Christophe dma_unmap_single(dev, ctx->dma_key, ctx->keylen, DMA_TO_DEVICE); 15812e13ce08SLEROY Christophe 15824de9d0b5SLee Nipper memcpy(&ctx->key, key, keylen); 15834de9d0b5SLee Nipper ctx->keylen = keylen; 15844de9d0b5SLee Nipper 15852e13ce08SLEROY Christophe ctx->dma_key = dma_map_single(dev, ctx->key, keylen, DMA_TO_DEVICE); 15862e13ce08SLEROY Christophe 15874de9d0b5SLee Nipper return 0; 15884de9d0b5SLee Nipper } 15894de9d0b5SLee Nipper 1590*ef7c5c85SHerbert Xu static int ablkcipher_des_setkey(struct crypto_ablkcipher *cipher, 1591*ef7c5c85SHerbert Xu const u8 *key, unsigned int keylen) 1592*ef7c5c85SHerbert Xu { 1593*ef7c5c85SHerbert Xu u32 tmp[DES_EXPKEY_WORDS]; 1594*ef7c5c85SHerbert Xu 1595*ef7c5c85SHerbert Xu if (unlikely(crypto_ablkcipher_get_flags(cipher) & 1596*ef7c5c85SHerbert Xu CRYPTO_TFM_REQ_FORBID_WEAK_KEYS) && 1597*ef7c5c85SHerbert Xu !des_ekey(tmp, key)) { 1598*ef7c5c85SHerbert Xu crypto_ablkcipher_set_flags(cipher, CRYPTO_TFM_RES_WEAK_KEY); 1599*ef7c5c85SHerbert Xu return -EINVAL; 1600*ef7c5c85SHerbert Xu } 1601*ef7c5c85SHerbert Xu 1602*ef7c5c85SHerbert Xu return ablkcipher_setkey(cipher, key, keylen); 1603*ef7c5c85SHerbert Xu } 1604*ef7c5c85SHerbert Xu 1605*ef7c5c85SHerbert Xu static int ablkcipher_des3_setkey(struct crypto_ablkcipher *cipher, 1606*ef7c5c85SHerbert Xu const u8 *key, unsigned int keylen) 1607*ef7c5c85SHerbert Xu { 1608*ef7c5c85SHerbert Xu u32 flags; 1609*ef7c5c85SHerbert Xu int err; 1610*ef7c5c85SHerbert Xu 1611*ef7c5c85SHerbert Xu flags = crypto_ablkcipher_get_flags(cipher); 1612*ef7c5c85SHerbert Xu err = __des3_verify_key(&flags, key); 1613*ef7c5c85SHerbert Xu if (unlikely(err)) { 1614*ef7c5c85SHerbert Xu crypto_ablkcipher_set_flags(cipher, flags); 1615*ef7c5c85SHerbert Xu return err; 1616*ef7c5c85SHerbert Xu } 1617*ef7c5c85SHerbert Xu 1618*ef7c5c85SHerbert Xu return ablkcipher_setkey(cipher, key, keylen); 1619*ef7c5c85SHerbert Xu } 1620*ef7c5c85SHerbert Xu 16214de9d0b5SLee Nipper static void common_nonsnoop_unmap(struct device *dev, 16224de9d0b5SLee Nipper struct talitos_edesc *edesc, 16234de9d0b5SLee Nipper struct ablkcipher_request *areq) 16244de9d0b5SLee Nipper { 16254de9d0b5SLee Nipper unmap_single_talitos_ptr(dev, &edesc->desc.ptr[5], DMA_FROM_DEVICE); 1626032d197eSLEROY Christophe 16276a1e8d14SLEROY Christophe talitos_sg_unmap(dev, edesc, areq->src, areq->dst, areq->nbytes, 0); 16284de9d0b5SLee Nipper unmap_single_talitos_ptr(dev, &edesc->desc.ptr[1], DMA_TO_DEVICE); 16294de9d0b5SLee Nipper 16304de9d0b5SLee Nipper if (edesc->dma_len) 16314de9d0b5SLee Nipper dma_unmap_single(dev, edesc->dma_link_tbl, edesc->dma_len, 16324de9d0b5SLee Nipper DMA_BIDIRECTIONAL); 16334de9d0b5SLee Nipper } 16344de9d0b5SLee Nipper 16354de9d0b5SLee Nipper static void ablkcipher_done(struct device *dev, 16364de9d0b5SLee Nipper struct talitos_desc *desc, void *context, 16374de9d0b5SLee Nipper int err) 16384de9d0b5SLee Nipper { 16394de9d0b5SLee Nipper struct ablkcipher_request *areq = context; 164019bbbc63SKim Phillips struct talitos_edesc *edesc; 164119bbbc63SKim Phillips 164219bbbc63SKim Phillips edesc = container_of(desc, struct talitos_edesc, desc); 16434de9d0b5SLee Nipper 16444de9d0b5SLee Nipper common_nonsnoop_unmap(dev, edesc, areq); 16454de9d0b5SLee Nipper 16464de9d0b5SLee Nipper kfree(edesc); 16474de9d0b5SLee Nipper 16484de9d0b5SLee Nipper areq->base.complete(&areq->base, err); 16494de9d0b5SLee Nipper } 16504de9d0b5SLee Nipper 16514de9d0b5SLee Nipper static int common_nonsnoop(struct talitos_edesc *edesc, 16524de9d0b5SLee Nipper struct ablkcipher_request *areq, 16534de9d0b5SLee Nipper void (*callback) (struct device *dev, 16544de9d0b5SLee Nipper struct talitos_desc *desc, 16554de9d0b5SLee Nipper void *context, int error)) 16564de9d0b5SLee Nipper { 16574de9d0b5SLee Nipper struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(areq); 16584de9d0b5SLee Nipper struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher); 16594de9d0b5SLee Nipper struct device *dev = ctx->dev; 16604de9d0b5SLee Nipper struct talitos_desc *desc = &edesc->desc; 16614de9d0b5SLee Nipper unsigned int cryptlen = areq->nbytes; 166279fd31d3SHoria Geanta unsigned int ivsize = crypto_ablkcipher_ivsize(cipher); 16634de9d0b5SLee Nipper int sg_count, ret; 16646a1e8d14SLEROY Christophe bool sync_needed = false; 1665922f9dc8SLEROY Christophe struct talitos_private *priv = dev_get_drvdata(dev); 1666922f9dc8SLEROY Christophe bool is_sec1 = has_ftr_sec1(priv); 16674de9d0b5SLee Nipper 16684de9d0b5SLee Nipper /* first DWORD empty */ 16694de9d0b5SLee Nipper 16704de9d0b5SLee Nipper /* cipher iv */ 1671da9de146SLEROY Christophe to_talitos_ptr(&desc->ptr[1], edesc->iv_dma, ivsize, is_sec1); 16724de9d0b5SLee Nipper 16734de9d0b5SLee Nipper /* cipher key */ 16742e13ce08SLEROY Christophe to_talitos_ptr(&desc->ptr[2], ctx->dma_key, ctx->keylen, is_sec1); 16754de9d0b5SLee Nipper 16766a1e8d14SLEROY Christophe sg_count = edesc->src_nents ?: 1; 16776a1e8d14SLEROY Christophe if (is_sec1 && sg_count > 1) 16786a1e8d14SLEROY Christophe sg_copy_to_buffer(areq->src, sg_count, edesc->buf, 16796a1e8d14SLEROY Christophe cryptlen); 16806a1e8d14SLEROY Christophe else 16816a1e8d14SLEROY Christophe sg_count = dma_map_sg(dev, areq->src, sg_count, 16826a1e8d14SLEROY Christophe (areq->src == areq->dst) ? 16836a1e8d14SLEROY Christophe DMA_BIDIRECTIONAL : DMA_TO_DEVICE); 16844de9d0b5SLee Nipper /* 16854de9d0b5SLee Nipper * cipher in 16864de9d0b5SLee Nipper */ 16876a1e8d14SLEROY Christophe sg_count = talitos_sg_map(dev, areq->src, cryptlen, edesc, 16886a1e8d14SLEROY Christophe &desc->ptr[3], sg_count, 0, 0); 16896a1e8d14SLEROY Christophe if (sg_count > 1) 16906a1e8d14SLEROY Christophe sync_needed = true; 16914de9d0b5SLee Nipper 16924de9d0b5SLee Nipper /* cipher out */ 16936a1e8d14SLEROY Christophe if (areq->src != areq->dst) { 16946a1e8d14SLEROY Christophe sg_count = edesc->dst_nents ? : 1; 16956a1e8d14SLEROY Christophe if (!is_sec1 || sg_count == 1) 16966a1e8d14SLEROY Christophe dma_map_sg(dev, areq->dst, sg_count, DMA_FROM_DEVICE); 16976a1e8d14SLEROY Christophe } 16986a1e8d14SLEROY Christophe 16996a1e8d14SLEROY Christophe ret = talitos_sg_map(dev, areq->dst, cryptlen, edesc, &desc->ptr[4], 17006a1e8d14SLEROY Christophe sg_count, 0, (edesc->src_nents + 1)); 17016a1e8d14SLEROY Christophe if (ret > 1) 17026a1e8d14SLEROY Christophe sync_needed = true; 17034de9d0b5SLee Nipper 17044de9d0b5SLee Nipper /* iv out */ 1705a2b35aa8SLEROY Christophe map_single_talitos_ptr(dev, &desc->ptr[5], ivsize, ctx->iv, 17064de9d0b5SLee Nipper DMA_FROM_DEVICE); 17074de9d0b5SLee Nipper 17084de9d0b5SLee Nipper /* last DWORD empty */ 17094de9d0b5SLee Nipper 17106a1e8d14SLEROY Christophe if (sync_needed) 17116a1e8d14SLEROY Christophe dma_sync_single_for_device(dev, edesc->dma_link_tbl, 17126a1e8d14SLEROY Christophe edesc->dma_len, DMA_BIDIRECTIONAL); 17136a1e8d14SLEROY Christophe 17145228f0f7SKim Phillips ret = talitos_submit(dev, ctx->ch, desc, callback, areq); 17154de9d0b5SLee Nipper if (ret != -EINPROGRESS) { 17164de9d0b5SLee Nipper common_nonsnoop_unmap(dev, edesc, areq); 17174de9d0b5SLee Nipper kfree(edesc); 17184de9d0b5SLee Nipper } 17194de9d0b5SLee Nipper return ret; 17204de9d0b5SLee Nipper } 17214de9d0b5SLee Nipper 1722e938e465SKim Phillips static struct talitos_edesc *ablkcipher_edesc_alloc(struct ablkcipher_request * 172362293a37SHoria Geanta areq, bool encrypt) 17244de9d0b5SLee Nipper { 17254de9d0b5SLee Nipper struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(areq); 17264de9d0b5SLee Nipper struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher); 172779fd31d3SHoria Geanta unsigned int ivsize = crypto_ablkcipher_ivsize(cipher); 17284de9d0b5SLee Nipper 1729aeb4c132SHerbert Xu return talitos_edesc_alloc(ctx->dev, areq->src, areq->dst, 173079fd31d3SHoria Geanta areq->info, 0, areq->nbytes, 0, ivsize, 0, 173162293a37SHoria Geanta areq->base.flags, encrypt); 17324de9d0b5SLee Nipper } 17334de9d0b5SLee Nipper 17344de9d0b5SLee Nipper static int ablkcipher_encrypt(struct ablkcipher_request *areq) 17354de9d0b5SLee Nipper { 17364de9d0b5SLee Nipper struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(areq); 17374de9d0b5SLee Nipper struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher); 17384de9d0b5SLee Nipper struct talitos_edesc *edesc; 17394de9d0b5SLee Nipper 17404de9d0b5SLee Nipper /* allocate extended descriptor */ 174162293a37SHoria Geanta edesc = ablkcipher_edesc_alloc(areq, true); 17424de9d0b5SLee Nipper if (IS_ERR(edesc)) 17434de9d0b5SLee Nipper return PTR_ERR(edesc); 17444de9d0b5SLee Nipper 17454de9d0b5SLee Nipper /* set encrypt */ 17464de9d0b5SLee Nipper edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_MODE0_ENCRYPT; 17474de9d0b5SLee Nipper 1748febec542SKim Phillips return common_nonsnoop(edesc, areq, ablkcipher_done); 17494de9d0b5SLee Nipper } 17504de9d0b5SLee Nipper 17514de9d0b5SLee Nipper static int ablkcipher_decrypt(struct ablkcipher_request *areq) 17524de9d0b5SLee Nipper { 17534de9d0b5SLee Nipper struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(areq); 17544de9d0b5SLee Nipper struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher); 17554de9d0b5SLee Nipper struct talitos_edesc *edesc; 17564de9d0b5SLee Nipper 17574de9d0b5SLee Nipper /* allocate extended descriptor */ 175862293a37SHoria Geanta edesc = ablkcipher_edesc_alloc(areq, false); 17594de9d0b5SLee Nipper if (IS_ERR(edesc)) 17604de9d0b5SLee Nipper return PTR_ERR(edesc); 17614de9d0b5SLee Nipper 17624de9d0b5SLee Nipper edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_DIR_INBOUND; 17634de9d0b5SLee Nipper 1764febec542SKim Phillips return common_nonsnoop(edesc, areq, ablkcipher_done); 17654de9d0b5SLee Nipper } 17664de9d0b5SLee Nipper 1767497f2e6bSLee Nipper static void common_nonsnoop_hash_unmap(struct device *dev, 1768497f2e6bSLee Nipper struct talitos_edesc *edesc, 1769497f2e6bSLee Nipper struct ahash_request *areq) 1770497f2e6bSLee Nipper { 1771497f2e6bSLee Nipper struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq); 1772ad4cd51fSLEROY Christophe struct talitos_private *priv = dev_get_drvdata(dev); 1773ad4cd51fSLEROY Christophe bool is_sec1 = has_ftr_sec1(priv); 1774ad4cd51fSLEROY Christophe struct talitos_desc *desc = &edesc->desc; 1775ad4cd51fSLEROY Christophe struct talitos_desc *desc2 = desc + 1; 1776ad4cd51fSLEROY Christophe 1777ad4cd51fSLEROY Christophe unmap_single_talitos_ptr(dev, &edesc->desc.ptr[5], DMA_FROM_DEVICE); 1778ad4cd51fSLEROY Christophe if (desc->next_desc && 1779ad4cd51fSLEROY Christophe desc->ptr[5].ptr != desc2->ptr[5].ptr) 1780ad4cd51fSLEROY Christophe unmap_single_talitos_ptr(dev, &desc2->ptr[5], DMA_FROM_DEVICE); 1781497f2e6bSLee Nipper 17826a1e8d14SLEROY Christophe talitos_sg_unmap(dev, edesc, req_ctx->psrc, NULL, 0, 0); 1783032d197eSLEROY Christophe 1784ad4cd51fSLEROY Christophe /* When using hashctx-in, must unmap it. */ 1785ad4cd51fSLEROY Christophe if (from_talitos_ptr_len(&edesc->desc.ptr[1], is_sec1)) 1786ad4cd51fSLEROY Christophe unmap_single_talitos_ptr(dev, &edesc->desc.ptr[1], 1787ad4cd51fSLEROY Christophe DMA_TO_DEVICE); 1788ad4cd51fSLEROY Christophe else if (desc->next_desc) 1789ad4cd51fSLEROY Christophe unmap_single_talitos_ptr(dev, &desc2->ptr[1], 1790ad4cd51fSLEROY Christophe DMA_TO_DEVICE); 1791ad4cd51fSLEROY Christophe 1792ad4cd51fSLEROY Christophe if (is_sec1 && req_ctx->nbuf) 1793ad4cd51fSLEROY Christophe unmap_single_talitos_ptr(dev, &desc->ptr[3], 1794ad4cd51fSLEROY Christophe DMA_TO_DEVICE); 1795ad4cd51fSLEROY Christophe 1796497f2e6bSLee Nipper if (edesc->dma_len) 1797497f2e6bSLee Nipper dma_unmap_single(dev, edesc->dma_link_tbl, edesc->dma_len, 1798497f2e6bSLee Nipper DMA_BIDIRECTIONAL); 1799497f2e6bSLee Nipper 180037b5e889SLEROY Christophe if (edesc->desc.next_desc) 180137b5e889SLEROY Christophe dma_unmap_single(dev, be32_to_cpu(edesc->desc.next_desc), 180237b5e889SLEROY Christophe TALITOS_DESC_SIZE, DMA_BIDIRECTIONAL); 1803497f2e6bSLee Nipper } 1804497f2e6bSLee Nipper 1805497f2e6bSLee Nipper static void ahash_done(struct device *dev, 1806497f2e6bSLee Nipper struct talitos_desc *desc, void *context, 1807497f2e6bSLee Nipper int err) 1808497f2e6bSLee Nipper { 1809497f2e6bSLee Nipper struct ahash_request *areq = context; 1810497f2e6bSLee Nipper struct talitos_edesc *edesc = 1811497f2e6bSLee Nipper container_of(desc, struct talitos_edesc, desc); 1812497f2e6bSLee Nipper struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq); 1813497f2e6bSLee Nipper 1814497f2e6bSLee Nipper if (!req_ctx->last && req_ctx->to_hash_later) { 1815497f2e6bSLee Nipper /* Position any partial block for next update/final/finup */ 18163c0dd190SLEROY Christophe req_ctx->buf_idx = (req_ctx->buf_idx + 1) & 1; 18175e833bc4SLee Nipper req_ctx->nbuf = req_ctx->to_hash_later; 1818497f2e6bSLee Nipper } 1819497f2e6bSLee Nipper common_nonsnoop_hash_unmap(dev, edesc, areq); 1820497f2e6bSLee Nipper 1821497f2e6bSLee Nipper kfree(edesc); 1822497f2e6bSLee Nipper 1823497f2e6bSLee Nipper areq->base.complete(&areq->base, err); 1824497f2e6bSLee Nipper } 1825497f2e6bSLee Nipper 18262d02905eSLEROY Christophe /* 18272d02905eSLEROY Christophe * SEC1 doesn't like hashing of 0 sized message, so we do the padding 18282d02905eSLEROY Christophe * ourself and submit a padded block 18292d02905eSLEROY Christophe */ 18305b2cf268SLEROY Christophe static void talitos_handle_buggy_hash(struct talitos_ctx *ctx, 18312d02905eSLEROY Christophe struct talitos_edesc *edesc, 18322d02905eSLEROY Christophe struct talitos_ptr *ptr) 18332d02905eSLEROY Christophe { 18342d02905eSLEROY Christophe static u8 padded_hash[64] = { 18352d02905eSLEROY Christophe 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18362d02905eSLEROY Christophe 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18372d02905eSLEROY Christophe 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18382d02905eSLEROY Christophe 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18392d02905eSLEROY Christophe }; 18402d02905eSLEROY Christophe 18412d02905eSLEROY Christophe pr_err_once("Bug in SEC1, padding ourself\n"); 18422d02905eSLEROY Christophe edesc->desc.hdr &= ~DESC_HDR_MODE0_MDEU_PAD; 18432d02905eSLEROY Christophe map_single_talitos_ptr(ctx->dev, ptr, sizeof(padded_hash), 18442d02905eSLEROY Christophe (char *)padded_hash, DMA_TO_DEVICE); 18452d02905eSLEROY Christophe } 18462d02905eSLEROY Christophe 1847497f2e6bSLee Nipper static int common_nonsnoop_hash(struct talitos_edesc *edesc, 1848497f2e6bSLee Nipper struct ahash_request *areq, unsigned int length, 184937b5e889SLEROY Christophe unsigned int offset, 1850497f2e6bSLee Nipper void (*callback) (struct device *dev, 1851497f2e6bSLee Nipper struct talitos_desc *desc, 1852497f2e6bSLee Nipper void *context, int error)) 1853497f2e6bSLee Nipper { 1854497f2e6bSLee Nipper struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); 1855497f2e6bSLee Nipper struct talitos_ctx *ctx = crypto_ahash_ctx(tfm); 1856497f2e6bSLee Nipper struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq); 1857497f2e6bSLee Nipper struct device *dev = ctx->dev; 1858497f2e6bSLee Nipper struct talitos_desc *desc = &edesc->desc; 1859032d197eSLEROY Christophe int ret; 18606a1e8d14SLEROY Christophe bool sync_needed = false; 1861922f9dc8SLEROY Christophe struct talitos_private *priv = dev_get_drvdata(dev); 1862922f9dc8SLEROY Christophe bool is_sec1 = has_ftr_sec1(priv); 18636a1e8d14SLEROY Christophe int sg_count; 1864497f2e6bSLee Nipper 1865497f2e6bSLee Nipper /* first DWORD empty */ 1866497f2e6bSLee Nipper 186760f208d7SKim Phillips /* hash context in */ 186860f208d7SKim Phillips if (!req_ctx->first || req_ctx->swinit) { 18696a4967c3SLEROY Christophe map_single_talitos_ptr_nosync(dev, &desc->ptr[1], 1870ad4cd51fSLEROY Christophe req_ctx->hw_context_size, 18716a4967c3SLEROY Christophe req_ctx->hw_context, 1872ad4cd51fSLEROY Christophe DMA_TO_DEVICE); 187360f208d7SKim Phillips req_ctx->swinit = 0; 1874afd62fa2SLEROY Christophe } 1875497f2e6bSLee Nipper /* Indicate next op is not the first. */ 1876497f2e6bSLee Nipper req_ctx->first = 0; 1877497f2e6bSLee Nipper 1878497f2e6bSLee Nipper /* HMAC key */ 1879497f2e6bSLee Nipper if (ctx->keylen) 18802e13ce08SLEROY Christophe to_talitos_ptr(&desc->ptr[2], ctx->dma_key, ctx->keylen, 18812e13ce08SLEROY Christophe is_sec1); 1882497f2e6bSLee Nipper 188337b5e889SLEROY Christophe if (is_sec1 && req_ctx->nbuf) 188437b5e889SLEROY Christophe length -= req_ctx->nbuf; 188537b5e889SLEROY Christophe 18866a1e8d14SLEROY Christophe sg_count = edesc->src_nents ?: 1; 18876a1e8d14SLEROY Christophe if (is_sec1 && sg_count > 1) 188837b5e889SLEROY Christophe sg_pcopy_to_buffer(req_ctx->psrc, sg_count, 188937b5e889SLEROY Christophe edesc->buf + sizeof(struct talitos_desc), 189037b5e889SLEROY Christophe length, req_ctx->nbuf); 189137b5e889SLEROY Christophe else if (length) 18926a1e8d14SLEROY Christophe sg_count = dma_map_sg(dev, req_ctx->psrc, sg_count, 18936a1e8d14SLEROY Christophe DMA_TO_DEVICE); 1894497f2e6bSLee Nipper /* 1895497f2e6bSLee Nipper * data in 1896497f2e6bSLee Nipper */ 189737b5e889SLEROY Christophe if (is_sec1 && req_ctx->nbuf) { 1898ad4cd51fSLEROY Christophe map_single_talitos_ptr(dev, &desc->ptr[3], req_ctx->nbuf, 1899ad4cd51fSLEROY Christophe req_ctx->buf[req_ctx->buf_idx], 1900ad4cd51fSLEROY Christophe DMA_TO_DEVICE); 190137b5e889SLEROY Christophe } else { 19026a1e8d14SLEROY Christophe sg_count = talitos_sg_map(dev, req_ctx->psrc, length, edesc, 190337b5e889SLEROY Christophe &desc->ptr[3], sg_count, offset, 0); 19046a1e8d14SLEROY Christophe if (sg_count > 1) 19056a1e8d14SLEROY Christophe sync_needed = true; 190637b5e889SLEROY Christophe } 1907497f2e6bSLee Nipper 1908497f2e6bSLee Nipper /* fifth DWORD empty */ 1909497f2e6bSLee Nipper 1910497f2e6bSLee Nipper /* hash/HMAC out -or- hash context out */ 1911497f2e6bSLee Nipper if (req_ctx->last) 1912497f2e6bSLee Nipper map_single_talitos_ptr(dev, &desc->ptr[5], 1913497f2e6bSLee Nipper crypto_ahash_digestsize(tfm), 1914a2b35aa8SLEROY Christophe areq->result, DMA_FROM_DEVICE); 1915497f2e6bSLee Nipper else 19166a4967c3SLEROY Christophe map_single_talitos_ptr_nosync(dev, &desc->ptr[5], 1917ad4cd51fSLEROY Christophe req_ctx->hw_context_size, 19186a4967c3SLEROY Christophe req_ctx->hw_context, 19196a4967c3SLEROY Christophe DMA_FROM_DEVICE); 1920497f2e6bSLee Nipper 1921497f2e6bSLee Nipper /* last DWORD empty */ 1922497f2e6bSLee Nipper 19232d02905eSLEROY Christophe if (is_sec1 && from_talitos_ptr_len(&desc->ptr[3], true) == 0) 19242d02905eSLEROY Christophe talitos_handle_buggy_hash(ctx, edesc, &desc->ptr[3]); 19252d02905eSLEROY Christophe 192637b5e889SLEROY Christophe if (is_sec1 && req_ctx->nbuf && length) { 192737b5e889SLEROY Christophe struct talitos_desc *desc2 = desc + 1; 192837b5e889SLEROY Christophe dma_addr_t next_desc; 192937b5e889SLEROY Christophe 193037b5e889SLEROY Christophe memset(desc2, 0, sizeof(*desc2)); 193137b5e889SLEROY Christophe desc2->hdr = desc->hdr; 193237b5e889SLEROY Christophe desc2->hdr &= ~DESC_HDR_MODE0_MDEU_INIT; 193337b5e889SLEROY Christophe desc2->hdr1 = desc2->hdr; 193437b5e889SLEROY Christophe desc->hdr &= ~DESC_HDR_MODE0_MDEU_PAD; 193537b5e889SLEROY Christophe desc->hdr |= DESC_HDR_MODE0_MDEU_CONT; 193637b5e889SLEROY Christophe desc->hdr &= ~DESC_HDR_DONE_NOTIFY; 193737b5e889SLEROY Christophe 1938ad4cd51fSLEROY Christophe if (desc->ptr[1].ptr) 1939ad4cd51fSLEROY Christophe copy_talitos_ptr(&desc2->ptr[1], &desc->ptr[1], 1940ad4cd51fSLEROY Christophe is_sec1); 1941ad4cd51fSLEROY Christophe else 19426a4967c3SLEROY Christophe map_single_talitos_ptr_nosync(dev, &desc2->ptr[1], 1943ad4cd51fSLEROY Christophe req_ctx->hw_context_size, 1944ad4cd51fSLEROY Christophe req_ctx->hw_context, 1945ad4cd51fSLEROY Christophe DMA_TO_DEVICE); 194637b5e889SLEROY Christophe copy_talitos_ptr(&desc2->ptr[2], &desc->ptr[2], is_sec1); 194737b5e889SLEROY Christophe sg_count = talitos_sg_map(dev, req_ctx->psrc, length, edesc, 194837b5e889SLEROY Christophe &desc2->ptr[3], sg_count, offset, 0); 194937b5e889SLEROY Christophe if (sg_count > 1) 195037b5e889SLEROY Christophe sync_needed = true; 195137b5e889SLEROY Christophe copy_talitos_ptr(&desc2->ptr[5], &desc->ptr[5], is_sec1); 195237b5e889SLEROY Christophe if (req_ctx->last) 19536a4967c3SLEROY Christophe map_single_talitos_ptr_nosync(dev, &desc->ptr[5], 1954ad4cd51fSLEROY Christophe req_ctx->hw_context_size, 1955ad4cd51fSLEROY Christophe req_ctx->hw_context, 1956ad4cd51fSLEROY Christophe DMA_FROM_DEVICE); 195737b5e889SLEROY Christophe 195837b5e889SLEROY Christophe next_desc = dma_map_single(dev, &desc2->hdr1, TALITOS_DESC_SIZE, 195937b5e889SLEROY Christophe DMA_BIDIRECTIONAL); 196037b5e889SLEROY Christophe desc->next_desc = cpu_to_be32(next_desc); 196137b5e889SLEROY Christophe } 196237b5e889SLEROY Christophe 19636a1e8d14SLEROY Christophe if (sync_needed) 19646a1e8d14SLEROY Christophe dma_sync_single_for_device(dev, edesc->dma_link_tbl, 19656a1e8d14SLEROY Christophe edesc->dma_len, DMA_BIDIRECTIONAL); 19666a1e8d14SLEROY Christophe 19675228f0f7SKim Phillips ret = talitos_submit(dev, ctx->ch, desc, callback, areq); 1968497f2e6bSLee Nipper if (ret != -EINPROGRESS) { 1969497f2e6bSLee Nipper common_nonsnoop_hash_unmap(dev, edesc, areq); 1970497f2e6bSLee Nipper kfree(edesc); 1971497f2e6bSLee Nipper } 1972497f2e6bSLee Nipper return ret; 1973497f2e6bSLee Nipper } 1974497f2e6bSLee Nipper 1975497f2e6bSLee Nipper static struct talitos_edesc *ahash_edesc_alloc(struct ahash_request *areq, 1976497f2e6bSLee Nipper unsigned int nbytes) 1977497f2e6bSLee Nipper { 1978497f2e6bSLee Nipper struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); 1979497f2e6bSLee Nipper struct talitos_ctx *ctx = crypto_ahash_ctx(tfm); 1980497f2e6bSLee Nipper struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq); 198137b5e889SLEROY Christophe struct talitos_private *priv = dev_get_drvdata(ctx->dev); 198237b5e889SLEROY Christophe bool is_sec1 = has_ftr_sec1(priv); 198337b5e889SLEROY Christophe 198437b5e889SLEROY Christophe if (is_sec1) 198537b5e889SLEROY Christophe nbytes -= req_ctx->nbuf; 1986497f2e6bSLee Nipper 1987aeb4c132SHerbert Xu return talitos_edesc_alloc(ctx->dev, req_ctx->psrc, NULL, NULL, 0, 198862293a37SHoria Geanta nbytes, 0, 0, 0, areq->base.flags, false); 1989497f2e6bSLee Nipper } 1990497f2e6bSLee Nipper 1991497f2e6bSLee Nipper static int ahash_init(struct ahash_request *areq) 1992497f2e6bSLee Nipper { 1993497f2e6bSLee Nipper struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); 19946a4967c3SLEROY Christophe struct talitos_ctx *ctx = crypto_ahash_ctx(tfm); 19956a4967c3SLEROY Christophe struct device *dev = ctx->dev; 1996497f2e6bSLee Nipper struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq); 199749f9783bSLEROY Christophe unsigned int size; 19986a4967c3SLEROY Christophe dma_addr_t dma; 1999497f2e6bSLee Nipper 2000497f2e6bSLee Nipper /* Initialize the context */ 20013c0dd190SLEROY Christophe req_ctx->buf_idx = 0; 20025e833bc4SLee Nipper req_ctx->nbuf = 0; 200360f208d7SKim Phillips req_ctx->first = 1; /* first indicates h/w must init its context */ 200460f208d7SKim Phillips req_ctx->swinit = 0; /* assume h/w init of context */ 200549f9783bSLEROY Christophe size = (crypto_ahash_digestsize(tfm) <= SHA256_DIGEST_SIZE) 2006497f2e6bSLee Nipper ? TALITOS_MDEU_CONTEXT_SIZE_MD5_SHA1_SHA256 2007497f2e6bSLee Nipper : TALITOS_MDEU_CONTEXT_SIZE_SHA384_SHA512; 200849f9783bSLEROY Christophe req_ctx->hw_context_size = size; 2009497f2e6bSLee Nipper 20106a4967c3SLEROY Christophe dma = dma_map_single(dev, req_ctx->hw_context, req_ctx->hw_context_size, 20116a4967c3SLEROY Christophe DMA_TO_DEVICE); 20126a4967c3SLEROY Christophe dma_unmap_single(dev, dma, req_ctx->hw_context_size, DMA_TO_DEVICE); 20136a4967c3SLEROY Christophe 2014497f2e6bSLee Nipper return 0; 2015497f2e6bSLee Nipper } 2016497f2e6bSLee Nipper 201760f208d7SKim Phillips /* 201860f208d7SKim Phillips * on h/w without explicit sha224 support, we initialize h/w context 201960f208d7SKim Phillips * manually with sha224 constants, and tell it to run sha256. 202060f208d7SKim Phillips */ 202160f208d7SKim Phillips static int ahash_init_sha224_swinit(struct ahash_request *areq) 202260f208d7SKim Phillips { 202360f208d7SKim Phillips struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq); 202460f208d7SKim Phillips 2025a752447aSKim Phillips req_ctx->hw_context[0] = SHA224_H0; 2026a752447aSKim Phillips req_ctx->hw_context[1] = SHA224_H1; 2027a752447aSKim Phillips req_ctx->hw_context[2] = SHA224_H2; 2028a752447aSKim Phillips req_ctx->hw_context[3] = SHA224_H3; 2029a752447aSKim Phillips req_ctx->hw_context[4] = SHA224_H4; 2030a752447aSKim Phillips req_ctx->hw_context[5] = SHA224_H5; 2031a752447aSKim Phillips req_ctx->hw_context[6] = SHA224_H6; 2032a752447aSKim Phillips req_ctx->hw_context[7] = SHA224_H7; 203360f208d7SKim Phillips 203460f208d7SKim Phillips /* init 64-bit count */ 203560f208d7SKim Phillips req_ctx->hw_context[8] = 0; 203660f208d7SKim Phillips req_ctx->hw_context[9] = 0; 203760f208d7SKim Phillips 20386a4967c3SLEROY Christophe ahash_init(areq); 20396a4967c3SLEROY Christophe req_ctx->swinit = 1;/* prevent h/w initting context with sha256 values*/ 20406a4967c3SLEROY Christophe 204160f208d7SKim Phillips return 0; 204260f208d7SKim Phillips } 204360f208d7SKim Phillips 2044497f2e6bSLee Nipper static int ahash_process_req(struct ahash_request *areq, unsigned int nbytes) 2045497f2e6bSLee Nipper { 2046497f2e6bSLee Nipper struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); 2047497f2e6bSLee Nipper struct talitos_ctx *ctx = crypto_ahash_ctx(tfm); 2048497f2e6bSLee Nipper struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq); 2049497f2e6bSLee Nipper struct talitos_edesc *edesc; 2050497f2e6bSLee Nipper unsigned int blocksize = 2051497f2e6bSLee Nipper crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm)); 2052497f2e6bSLee Nipper unsigned int nbytes_to_hash; 2053497f2e6bSLee Nipper unsigned int to_hash_later; 20545e833bc4SLee Nipper unsigned int nsg; 20558e409fe1SLABBE Corentin int nents; 205637b5e889SLEROY Christophe struct device *dev = ctx->dev; 205737b5e889SLEROY Christophe struct talitos_private *priv = dev_get_drvdata(dev); 205837b5e889SLEROY Christophe bool is_sec1 = has_ftr_sec1(priv); 205937b5e889SLEROY Christophe int offset = 0; 20603c0dd190SLEROY Christophe u8 *ctx_buf = req_ctx->buf[req_ctx->buf_idx]; 2061497f2e6bSLee Nipper 20625e833bc4SLee Nipper if (!req_ctx->last && (nbytes + req_ctx->nbuf <= blocksize)) { 20635e833bc4SLee Nipper /* Buffer up to one whole block */ 20648e409fe1SLABBE Corentin nents = sg_nents_for_len(areq->src, nbytes); 20658e409fe1SLABBE Corentin if (nents < 0) { 20668e409fe1SLABBE Corentin dev_err(ctx->dev, "Invalid number of src SG.\n"); 20678e409fe1SLABBE Corentin return nents; 20688e409fe1SLABBE Corentin } 20698e409fe1SLABBE Corentin sg_copy_to_buffer(areq->src, nents, 20703c0dd190SLEROY Christophe ctx_buf + req_ctx->nbuf, nbytes); 20715e833bc4SLee Nipper req_ctx->nbuf += nbytes; 2072497f2e6bSLee Nipper return 0; 2073497f2e6bSLee Nipper } 2074497f2e6bSLee Nipper 20755e833bc4SLee Nipper /* At least (blocksize + 1) bytes are available to hash */ 20765e833bc4SLee Nipper nbytes_to_hash = nbytes + req_ctx->nbuf; 20775e833bc4SLee Nipper to_hash_later = nbytes_to_hash & (blocksize - 1); 20785e833bc4SLee Nipper 20795e833bc4SLee Nipper if (req_ctx->last) 20805e833bc4SLee Nipper to_hash_later = 0; 20815e833bc4SLee Nipper else if (to_hash_later) 20825e833bc4SLee Nipper /* There is a partial block. Hash the full block(s) now */ 20835e833bc4SLee Nipper nbytes_to_hash -= to_hash_later; 20845e833bc4SLee Nipper else { 20855e833bc4SLee Nipper /* Keep one block buffered */ 20865e833bc4SLee Nipper nbytes_to_hash -= blocksize; 20875e833bc4SLee Nipper to_hash_later = blocksize; 2088497f2e6bSLee Nipper } 20895e833bc4SLee Nipper 20905e833bc4SLee Nipper /* Chain in any previously buffered data */ 209137b5e889SLEROY Christophe if (!is_sec1 && req_ctx->nbuf) { 20925e833bc4SLee Nipper nsg = (req_ctx->nbuf < nbytes_to_hash) ? 2 : 1; 20935e833bc4SLee Nipper sg_init_table(req_ctx->bufsl, nsg); 20943c0dd190SLEROY Christophe sg_set_buf(req_ctx->bufsl, ctx_buf, req_ctx->nbuf); 20955e833bc4SLee Nipper if (nsg > 1) 2096c56f6d12SDan Williams sg_chain(req_ctx->bufsl, 2, areq->src); 20975e833bc4SLee Nipper req_ctx->psrc = req_ctx->bufsl; 209837b5e889SLEROY Christophe } else if (is_sec1 && req_ctx->nbuf && req_ctx->nbuf < blocksize) { 209937b5e889SLEROY Christophe if (nbytes_to_hash > blocksize) 210037b5e889SLEROY Christophe offset = blocksize - req_ctx->nbuf; 210137b5e889SLEROY Christophe else 210237b5e889SLEROY Christophe offset = nbytes_to_hash - req_ctx->nbuf; 210337b5e889SLEROY Christophe nents = sg_nents_for_len(areq->src, offset); 210437b5e889SLEROY Christophe if (nents < 0) { 210537b5e889SLEROY Christophe dev_err(ctx->dev, "Invalid number of src SG.\n"); 210637b5e889SLEROY Christophe return nents; 210737b5e889SLEROY Christophe } 210837b5e889SLEROY Christophe sg_copy_to_buffer(areq->src, nents, 21093c0dd190SLEROY Christophe ctx_buf + req_ctx->nbuf, offset); 211037b5e889SLEROY Christophe req_ctx->nbuf += offset; 211137b5e889SLEROY Christophe req_ctx->psrc = areq->src; 21125e833bc4SLee Nipper } else 21135e833bc4SLee Nipper req_ctx->psrc = areq->src; 21145e833bc4SLee Nipper 2115497f2e6bSLee Nipper if (to_hash_later) { 21168e409fe1SLABBE Corentin nents = sg_nents_for_len(areq->src, nbytes); 21178e409fe1SLABBE Corentin if (nents < 0) { 21188e409fe1SLABBE Corentin dev_err(ctx->dev, "Invalid number of src SG.\n"); 21198e409fe1SLABBE Corentin return nents; 21208e409fe1SLABBE Corentin } 2121d0525723SAkinobu Mita sg_pcopy_to_buffer(areq->src, nents, 21223c0dd190SLEROY Christophe req_ctx->buf[(req_ctx->buf_idx + 1) & 1], 2123497f2e6bSLee Nipper to_hash_later, 2124497f2e6bSLee Nipper nbytes - to_hash_later); 2125497f2e6bSLee Nipper } 2126497f2e6bSLee Nipper req_ctx->to_hash_later = to_hash_later; 2127497f2e6bSLee Nipper 21285e833bc4SLee Nipper /* Allocate extended descriptor */ 2129497f2e6bSLee Nipper edesc = ahash_edesc_alloc(areq, nbytes_to_hash); 2130497f2e6bSLee Nipper if (IS_ERR(edesc)) 2131497f2e6bSLee Nipper return PTR_ERR(edesc); 2132497f2e6bSLee Nipper 2133497f2e6bSLee Nipper edesc->desc.hdr = ctx->desc_hdr_template; 2134497f2e6bSLee Nipper 2135497f2e6bSLee Nipper /* On last one, request SEC to pad; otherwise continue */ 2136497f2e6bSLee Nipper if (req_ctx->last) 2137497f2e6bSLee Nipper edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_PAD; 2138497f2e6bSLee Nipper else 2139497f2e6bSLee Nipper edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_CONT; 2140497f2e6bSLee Nipper 214160f208d7SKim Phillips /* request SEC to INIT hash. */ 214260f208d7SKim Phillips if (req_ctx->first && !req_ctx->swinit) 2143497f2e6bSLee Nipper edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_INIT; 2144497f2e6bSLee Nipper 2145497f2e6bSLee Nipper /* When the tfm context has a keylen, it's an HMAC. 2146497f2e6bSLee Nipper * A first or last (ie. not middle) descriptor must request HMAC. 2147497f2e6bSLee Nipper */ 2148497f2e6bSLee Nipper if (ctx->keylen && (req_ctx->first || req_ctx->last)) 2149497f2e6bSLee Nipper edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_HMAC; 2150497f2e6bSLee Nipper 215137b5e889SLEROY Christophe return common_nonsnoop_hash(edesc, areq, nbytes_to_hash, offset, 2152497f2e6bSLee Nipper ahash_done); 2153497f2e6bSLee Nipper } 2154497f2e6bSLee Nipper 2155497f2e6bSLee Nipper static int ahash_update(struct ahash_request *areq) 2156497f2e6bSLee Nipper { 2157497f2e6bSLee Nipper struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq); 2158497f2e6bSLee Nipper 2159497f2e6bSLee Nipper req_ctx->last = 0; 2160497f2e6bSLee Nipper 2161497f2e6bSLee Nipper return ahash_process_req(areq, areq->nbytes); 2162497f2e6bSLee Nipper } 2163497f2e6bSLee Nipper 2164497f2e6bSLee Nipper static int ahash_final(struct ahash_request *areq) 2165497f2e6bSLee Nipper { 2166497f2e6bSLee Nipper struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq); 2167497f2e6bSLee Nipper 2168497f2e6bSLee Nipper req_ctx->last = 1; 2169497f2e6bSLee Nipper 2170497f2e6bSLee Nipper return ahash_process_req(areq, 0); 2171497f2e6bSLee Nipper } 2172497f2e6bSLee Nipper 2173497f2e6bSLee Nipper static int ahash_finup(struct ahash_request *areq) 2174497f2e6bSLee Nipper { 2175497f2e6bSLee Nipper struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq); 2176497f2e6bSLee Nipper 2177497f2e6bSLee Nipper req_ctx->last = 1; 2178497f2e6bSLee Nipper 2179497f2e6bSLee Nipper return ahash_process_req(areq, areq->nbytes); 2180497f2e6bSLee Nipper } 2181497f2e6bSLee Nipper 2182497f2e6bSLee Nipper static int ahash_digest(struct ahash_request *areq) 2183497f2e6bSLee Nipper { 2184497f2e6bSLee Nipper struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq); 218560f208d7SKim Phillips struct crypto_ahash *ahash = crypto_ahash_reqtfm(areq); 2186497f2e6bSLee Nipper 218760f208d7SKim Phillips ahash->init(areq); 2188497f2e6bSLee Nipper req_ctx->last = 1; 2189497f2e6bSLee Nipper 2190497f2e6bSLee Nipper return ahash_process_req(areq, areq->nbytes); 2191497f2e6bSLee Nipper } 2192497f2e6bSLee Nipper 21933639ca84SHoria Geant? static int ahash_export(struct ahash_request *areq, void *out) 21943639ca84SHoria Geant? { 21953639ca84SHoria Geant? struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq); 21963639ca84SHoria Geant? struct talitos_export_state *export = out; 21976a4967c3SLEROY Christophe struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); 21986a4967c3SLEROY Christophe struct talitos_ctx *ctx = crypto_ahash_ctx(tfm); 21996a4967c3SLEROY Christophe struct device *dev = ctx->dev; 22006a4967c3SLEROY Christophe dma_addr_t dma; 22016a4967c3SLEROY Christophe 22026a4967c3SLEROY Christophe dma = dma_map_single(dev, req_ctx->hw_context, req_ctx->hw_context_size, 22036a4967c3SLEROY Christophe DMA_FROM_DEVICE); 22046a4967c3SLEROY Christophe dma_unmap_single(dev, dma, req_ctx->hw_context_size, DMA_FROM_DEVICE); 22053639ca84SHoria Geant? 22063639ca84SHoria Geant? memcpy(export->hw_context, req_ctx->hw_context, 22073639ca84SHoria Geant? req_ctx->hw_context_size); 22083c0dd190SLEROY Christophe memcpy(export->buf, req_ctx->buf[req_ctx->buf_idx], req_ctx->nbuf); 22093639ca84SHoria Geant? export->swinit = req_ctx->swinit; 22103639ca84SHoria Geant? export->first = req_ctx->first; 22113639ca84SHoria Geant? export->last = req_ctx->last; 22123639ca84SHoria Geant? export->to_hash_later = req_ctx->to_hash_later; 22133639ca84SHoria Geant? export->nbuf = req_ctx->nbuf; 22143639ca84SHoria Geant? 22153639ca84SHoria Geant? return 0; 22163639ca84SHoria Geant? } 22173639ca84SHoria Geant? 22183639ca84SHoria Geant? static int ahash_import(struct ahash_request *areq, const void *in) 22193639ca84SHoria Geant? { 22203639ca84SHoria Geant? struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq); 22213639ca84SHoria Geant? struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); 22226a4967c3SLEROY Christophe struct talitos_ctx *ctx = crypto_ahash_ctx(tfm); 22236a4967c3SLEROY Christophe struct device *dev = ctx->dev; 22243639ca84SHoria Geant? const struct talitos_export_state *export = in; 222549f9783bSLEROY Christophe unsigned int size; 22266a4967c3SLEROY Christophe dma_addr_t dma; 22273639ca84SHoria Geant? 22283639ca84SHoria Geant? memset(req_ctx, 0, sizeof(*req_ctx)); 222949f9783bSLEROY Christophe size = (crypto_ahash_digestsize(tfm) <= SHA256_DIGEST_SIZE) 22303639ca84SHoria Geant? ? TALITOS_MDEU_CONTEXT_SIZE_MD5_SHA1_SHA256 22313639ca84SHoria Geant? : TALITOS_MDEU_CONTEXT_SIZE_SHA384_SHA512; 223249f9783bSLEROY Christophe req_ctx->hw_context_size = size; 223349f9783bSLEROY Christophe memcpy(req_ctx->hw_context, export->hw_context, size); 22343c0dd190SLEROY Christophe memcpy(req_ctx->buf[0], export->buf, export->nbuf); 22353639ca84SHoria Geant? req_ctx->swinit = export->swinit; 22363639ca84SHoria Geant? req_ctx->first = export->first; 22373639ca84SHoria Geant? req_ctx->last = export->last; 22383639ca84SHoria Geant? req_ctx->to_hash_later = export->to_hash_later; 22393639ca84SHoria Geant? req_ctx->nbuf = export->nbuf; 22403639ca84SHoria Geant? 22416a4967c3SLEROY Christophe dma = dma_map_single(dev, req_ctx->hw_context, req_ctx->hw_context_size, 22426a4967c3SLEROY Christophe DMA_TO_DEVICE); 22436a4967c3SLEROY Christophe dma_unmap_single(dev, dma, req_ctx->hw_context_size, DMA_TO_DEVICE); 22446a4967c3SLEROY Christophe 22453639ca84SHoria Geant? return 0; 22463639ca84SHoria Geant? } 22473639ca84SHoria Geant? 224879b3a418SLee Nipper static int keyhash(struct crypto_ahash *tfm, const u8 *key, unsigned int keylen, 224979b3a418SLee Nipper u8 *hash) 225079b3a418SLee Nipper { 225179b3a418SLee Nipper struct talitos_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm)); 225279b3a418SLee Nipper 225379b3a418SLee Nipper struct scatterlist sg[1]; 225479b3a418SLee Nipper struct ahash_request *req; 2255f1c90ac3SGilad Ben-Yossef struct crypto_wait wait; 225679b3a418SLee Nipper int ret; 225779b3a418SLee Nipper 2258f1c90ac3SGilad Ben-Yossef crypto_init_wait(&wait); 225979b3a418SLee Nipper 226079b3a418SLee Nipper req = ahash_request_alloc(tfm, GFP_KERNEL); 226179b3a418SLee Nipper if (!req) 226279b3a418SLee Nipper return -ENOMEM; 226379b3a418SLee Nipper 226479b3a418SLee Nipper /* Keep tfm keylen == 0 during hash of the long key */ 226579b3a418SLee Nipper ctx->keylen = 0; 226679b3a418SLee Nipper ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, 2267f1c90ac3SGilad Ben-Yossef crypto_req_done, &wait); 226879b3a418SLee Nipper 226979b3a418SLee Nipper sg_init_one(&sg[0], key, keylen); 227079b3a418SLee Nipper 227179b3a418SLee Nipper ahash_request_set_crypt(req, sg, hash, keylen); 2272f1c90ac3SGilad Ben-Yossef ret = crypto_wait_req(crypto_ahash_digest(req), &wait); 2273f1c90ac3SGilad Ben-Yossef 227479b3a418SLee Nipper ahash_request_free(req); 227579b3a418SLee Nipper 227679b3a418SLee Nipper return ret; 227779b3a418SLee Nipper } 227879b3a418SLee Nipper 227979b3a418SLee Nipper static int ahash_setkey(struct crypto_ahash *tfm, const u8 *key, 228079b3a418SLee Nipper unsigned int keylen) 228179b3a418SLee Nipper { 228279b3a418SLee Nipper struct talitos_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm)); 22832e13ce08SLEROY Christophe struct device *dev = ctx->dev; 228479b3a418SLee Nipper unsigned int blocksize = 228579b3a418SLee Nipper crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm)); 228679b3a418SLee Nipper unsigned int digestsize = crypto_ahash_digestsize(tfm); 228779b3a418SLee Nipper unsigned int keysize = keylen; 228879b3a418SLee Nipper u8 hash[SHA512_DIGEST_SIZE]; 228979b3a418SLee Nipper int ret; 229079b3a418SLee Nipper 229179b3a418SLee Nipper if (keylen <= blocksize) 229279b3a418SLee Nipper memcpy(ctx->key, key, keysize); 229379b3a418SLee Nipper else { 229479b3a418SLee Nipper /* Must get the hash of the long key */ 229579b3a418SLee Nipper ret = keyhash(tfm, key, keylen, hash); 229679b3a418SLee Nipper 229779b3a418SLee Nipper if (ret) { 229879b3a418SLee Nipper crypto_ahash_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN); 229979b3a418SLee Nipper return -EINVAL; 230079b3a418SLee Nipper } 230179b3a418SLee Nipper 230279b3a418SLee Nipper keysize = digestsize; 230379b3a418SLee Nipper memcpy(ctx->key, hash, digestsize); 230479b3a418SLee Nipper } 230579b3a418SLee Nipper 23062e13ce08SLEROY Christophe if (ctx->keylen) 23072e13ce08SLEROY Christophe dma_unmap_single(dev, ctx->dma_key, ctx->keylen, DMA_TO_DEVICE); 23082e13ce08SLEROY Christophe 230979b3a418SLee Nipper ctx->keylen = keysize; 23102e13ce08SLEROY Christophe ctx->dma_key = dma_map_single(dev, ctx->key, keysize, DMA_TO_DEVICE); 231179b3a418SLee Nipper 231279b3a418SLee Nipper return 0; 231379b3a418SLee Nipper } 231479b3a418SLee Nipper 231579b3a418SLee Nipper 23169c4a7965SKim Phillips struct talitos_alg_template { 2317d5e4aaefSLee Nipper u32 type; 2318b0057763SLEROY Christophe u32 priority; 2319d5e4aaefSLee Nipper union { 2320d5e4aaefSLee Nipper struct crypto_alg crypto; 2321acbf7c62SLee Nipper struct ahash_alg hash; 2322aeb4c132SHerbert Xu struct aead_alg aead; 2323d5e4aaefSLee Nipper } alg; 23249c4a7965SKim Phillips __be32 desc_hdr_template; 23259c4a7965SKim Phillips }; 23269c4a7965SKim Phillips 23279c4a7965SKim Phillips static struct talitos_alg_template driver_algs[] = { 2328991155baSHoria Geanta /* AEAD algorithms. These use a single-pass ipsec_esp descriptor */ 2329d5e4aaefSLee Nipper { .type = CRYPTO_ALG_TYPE_AEAD, 2330aeb4c132SHerbert Xu .alg.aead = { 2331aeb4c132SHerbert Xu .base = { 233256af8cd4SLee Nipper .cra_name = "authenc(hmac(sha1),cbc(aes))", 2333aeb4c132SHerbert Xu .cra_driver_name = "authenc-hmac-sha1-" 2334aeb4c132SHerbert Xu "cbc-aes-talitos", 233556af8cd4SLee Nipper .cra_blocksize = AES_BLOCK_SIZE, 2336aeb4c132SHerbert Xu .cra_flags = CRYPTO_ALG_ASYNC, 2337aeb4c132SHerbert Xu }, 23383952f17eSLee Nipper .ivsize = AES_BLOCK_SIZE, 23393952f17eSLee Nipper .maxauthsize = SHA1_DIGEST_SIZE, 23409c4a7965SKim Phillips }, 23419c4a7965SKim Phillips .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP | 23429c4a7965SKim Phillips DESC_HDR_SEL0_AESU | 23439c4a7965SKim Phillips DESC_HDR_MODE0_AESU_CBC | 23449c4a7965SKim Phillips DESC_HDR_SEL1_MDEUA | 23459c4a7965SKim Phillips DESC_HDR_MODE1_MDEU_INIT | 23469c4a7965SKim Phillips DESC_HDR_MODE1_MDEU_PAD | 23479c4a7965SKim Phillips DESC_HDR_MODE1_MDEU_SHA1_HMAC, 234870bcaca7SLee Nipper }, 2349d5e4aaefSLee Nipper { .type = CRYPTO_ALG_TYPE_AEAD, 23507405c8d7SLEROY Christophe .priority = TALITOS_CRA_PRIORITY_AEAD_HSNA, 23517405c8d7SLEROY Christophe .alg.aead = { 23527405c8d7SLEROY Christophe .base = { 23537405c8d7SLEROY Christophe .cra_name = "authenc(hmac(sha1),cbc(aes))", 23547405c8d7SLEROY Christophe .cra_driver_name = "authenc-hmac-sha1-" 23557405c8d7SLEROY Christophe "cbc-aes-talitos", 23567405c8d7SLEROY Christophe .cra_blocksize = AES_BLOCK_SIZE, 23577405c8d7SLEROY Christophe .cra_flags = CRYPTO_ALG_ASYNC, 23587405c8d7SLEROY Christophe }, 23597405c8d7SLEROY Christophe .ivsize = AES_BLOCK_SIZE, 23607405c8d7SLEROY Christophe .maxauthsize = SHA1_DIGEST_SIZE, 23617405c8d7SLEROY Christophe }, 23627405c8d7SLEROY Christophe .desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU | 23637405c8d7SLEROY Christophe DESC_HDR_SEL0_AESU | 23647405c8d7SLEROY Christophe DESC_HDR_MODE0_AESU_CBC | 23657405c8d7SLEROY Christophe DESC_HDR_SEL1_MDEUA | 23667405c8d7SLEROY Christophe DESC_HDR_MODE1_MDEU_INIT | 23677405c8d7SLEROY Christophe DESC_HDR_MODE1_MDEU_PAD | 23687405c8d7SLEROY Christophe DESC_HDR_MODE1_MDEU_SHA1_HMAC, 23697405c8d7SLEROY Christophe }, 23707405c8d7SLEROY Christophe { .type = CRYPTO_ALG_TYPE_AEAD, 2371aeb4c132SHerbert Xu .alg.aead = { 2372aeb4c132SHerbert Xu .base = { 2373aeb4c132SHerbert Xu .cra_name = "authenc(hmac(sha1)," 2374aeb4c132SHerbert Xu "cbc(des3_ede))", 2375aeb4c132SHerbert Xu .cra_driver_name = "authenc-hmac-sha1-" 2376aeb4c132SHerbert Xu "cbc-3des-talitos", 237756af8cd4SLee Nipper .cra_blocksize = DES3_EDE_BLOCK_SIZE, 2378aeb4c132SHerbert Xu .cra_flags = CRYPTO_ALG_ASYNC, 2379aeb4c132SHerbert Xu }, 23803952f17eSLee Nipper .ivsize = DES3_EDE_BLOCK_SIZE, 23813952f17eSLee Nipper .maxauthsize = SHA1_DIGEST_SIZE, 2382*ef7c5c85SHerbert Xu .setkey = aead_des3_setkey, 238370bcaca7SLee Nipper }, 238470bcaca7SLee Nipper .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP | 238570bcaca7SLee Nipper DESC_HDR_SEL0_DEU | 238670bcaca7SLee Nipper DESC_HDR_MODE0_DEU_CBC | 238770bcaca7SLee Nipper DESC_HDR_MODE0_DEU_3DES | 238870bcaca7SLee Nipper DESC_HDR_SEL1_MDEUA | 238970bcaca7SLee Nipper DESC_HDR_MODE1_MDEU_INIT | 239070bcaca7SLee Nipper DESC_HDR_MODE1_MDEU_PAD | 239170bcaca7SLee Nipper DESC_HDR_MODE1_MDEU_SHA1_HMAC, 23923952f17eSLee Nipper }, 2393d5e4aaefSLee Nipper { .type = CRYPTO_ALG_TYPE_AEAD, 23947405c8d7SLEROY Christophe .priority = TALITOS_CRA_PRIORITY_AEAD_HSNA, 23957405c8d7SLEROY Christophe .alg.aead = { 23967405c8d7SLEROY Christophe .base = { 23977405c8d7SLEROY Christophe .cra_name = "authenc(hmac(sha1)," 23987405c8d7SLEROY Christophe "cbc(des3_ede))", 23997405c8d7SLEROY Christophe .cra_driver_name = "authenc-hmac-sha1-" 24007405c8d7SLEROY Christophe "cbc-3des-talitos", 24017405c8d7SLEROY Christophe .cra_blocksize = DES3_EDE_BLOCK_SIZE, 24027405c8d7SLEROY Christophe .cra_flags = CRYPTO_ALG_ASYNC, 24037405c8d7SLEROY Christophe }, 24047405c8d7SLEROY Christophe .ivsize = DES3_EDE_BLOCK_SIZE, 24057405c8d7SLEROY Christophe .maxauthsize = SHA1_DIGEST_SIZE, 2406*ef7c5c85SHerbert Xu .setkey = aead_des3_setkey, 24077405c8d7SLEROY Christophe }, 24087405c8d7SLEROY Christophe .desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU | 24097405c8d7SLEROY Christophe DESC_HDR_SEL0_DEU | 24107405c8d7SLEROY Christophe DESC_HDR_MODE0_DEU_CBC | 24117405c8d7SLEROY Christophe DESC_HDR_MODE0_DEU_3DES | 24127405c8d7SLEROY Christophe DESC_HDR_SEL1_MDEUA | 24137405c8d7SLEROY Christophe DESC_HDR_MODE1_MDEU_INIT | 24147405c8d7SLEROY Christophe DESC_HDR_MODE1_MDEU_PAD | 24157405c8d7SLEROY Christophe DESC_HDR_MODE1_MDEU_SHA1_HMAC, 24167405c8d7SLEROY Christophe }, 24177405c8d7SLEROY Christophe { .type = CRYPTO_ALG_TYPE_AEAD, 2418aeb4c132SHerbert Xu .alg.aead = { 2419aeb4c132SHerbert Xu .base = { 2420357fb605SHoria Geanta .cra_name = "authenc(hmac(sha224),cbc(aes))", 2421aeb4c132SHerbert Xu .cra_driver_name = "authenc-hmac-sha224-" 2422aeb4c132SHerbert Xu "cbc-aes-talitos", 2423357fb605SHoria Geanta .cra_blocksize = AES_BLOCK_SIZE, 2424aeb4c132SHerbert Xu .cra_flags = CRYPTO_ALG_ASYNC, 2425aeb4c132SHerbert Xu }, 2426357fb605SHoria Geanta .ivsize = AES_BLOCK_SIZE, 2427357fb605SHoria Geanta .maxauthsize = SHA224_DIGEST_SIZE, 2428357fb605SHoria Geanta }, 2429357fb605SHoria Geanta .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP | 2430357fb605SHoria Geanta DESC_HDR_SEL0_AESU | 2431357fb605SHoria Geanta DESC_HDR_MODE0_AESU_CBC | 2432357fb605SHoria Geanta DESC_HDR_SEL1_MDEUA | 2433357fb605SHoria Geanta DESC_HDR_MODE1_MDEU_INIT | 2434357fb605SHoria Geanta DESC_HDR_MODE1_MDEU_PAD | 2435357fb605SHoria Geanta DESC_HDR_MODE1_MDEU_SHA224_HMAC, 2436357fb605SHoria Geanta }, 2437357fb605SHoria Geanta { .type = CRYPTO_ALG_TYPE_AEAD, 24387405c8d7SLEROY Christophe .priority = TALITOS_CRA_PRIORITY_AEAD_HSNA, 24397405c8d7SLEROY Christophe .alg.aead = { 24407405c8d7SLEROY Christophe .base = { 24417405c8d7SLEROY Christophe .cra_name = "authenc(hmac(sha224),cbc(aes))", 24427405c8d7SLEROY Christophe .cra_driver_name = "authenc-hmac-sha224-" 24437405c8d7SLEROY Christophe "cbc-aes-talitos", 24447405c8d7SLEROY Christophe .cra_blocksize = AES_BLOCK_SIZE, 24457405c8d7SLEROY Christophe .cra_flags = CRYPTO_ALG_ASYNC, 24467405c8d7SLEROY Christophe }, 24477405c8d7SLEROY Christophe .ivsize = AES_BLOCK_SIZE, 24487405c8d7SLEROY Christophe .maxauthsize = SHA224_DIGEST_SIZE, 24497405c8d7SLEROY Christophe }, 24507405c8d7SLEROY Christophe .desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU | 24517405c8d7SLEROY Christophe DESC_HDR_SEL0_AESU | 24527405c8d7SLEROY Christophe DESC_HDR_MODE0_AESU_CBC | 24537405c8d7SLEROY Christophe DESC_HDR_SEL1_MDEUA | 24547405c8d7SLEROY Christophe DESC_HDR_MODE1_MDEU_INIT | 24557405c8d7SLEROY Christophe DESC_HDR_MODE1_MDEU_PAD | 24567405c8d7SLEROY Christophe DESC_HDR_MODE1_MDEU_SHA224_HMAC, 24577405c8d7SLEROY Christophe }, 24587405c8d7SLEROY Christophe { .type = CRYPTO_ALG_TYPE_AEAD, 2459aeb4c132SHerbert Xu .alg.aead = { 2460aeb4c132SHerbert Xu .base = { 2461aeb4c132SHerbert Xu .cra_name = "authenc(hmac(sha224)," 2462aeb4c132SHerbert Xu "cbc(des3_ede))", 2463aeb4c132SHerbert Xu .cra_driver_name = "authenc-hmac-sha224-" 2464aeb4c132SHerbert Xu "cbc-3des-talitos", 2465357fb605SHoria Geanta .cra_blocksize = DES3_EDE_BLOCK_SIZE, 2466aeb4c132SHerbert Xu .cra_flags = CRYPTO_ALG_ASYNC, 2467aeb4c132SHerbert Xu }, 2468357fb605SHoria Geanta .ivsize = DES3_EDE_BLOCK_SIZE, 2469357fb605SHoria Geanta .maxauthsize = SHA224_DIGEST_SIZE, 2470*ef7c5c85SHerbert Xu .setkey = aead_des3_setkey, 2471357fb605SHoria Geanta }, 2472357fb605SHoria Geanta .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP | 2473357fb605SHoria Geanta DESC_HDR_SEL0_DEU | 2474357fb605SHoria Geanta DESC_HDR_MODE0_DEU_CBC | 2475357fb605SHoria Geanta DESC_HDR_MODE0_DEU_3DES | 2476357fb605SHoria Geanta DESC_HDR_SEL1_MDEUA | 2477357fb605SHoria Geanta DESC_HDR_MODE1_MDEU_INIT | 2478357fb605SHoria Geanta DESC_HDR_MODE1_MDEU_PAD | 2479357fb605SHoria Geanta DESC_HDR_MODE1_MDEU_SHA224_HMAC, 2480357fb605SHoria Geanta }, 2481357fb605SHoria Geanta { .type = CRYPTO_ALG_TYPE_AEAD, 24827405c8d7SLEROY Christophe .priority = TALITOS_CRA_PRIORITY_AEAD_HSNA, 24837405c8d7SLEROY Christophe .alg.aead = { 24847405c8d7SLEROY Christophe .base = { 24857405c8d7SLEROY Christophe .cra_name = "authenc(hmac(sha224)," 24867405c8d7SLEROY Christophe "cbc(des3_ede))", 24877405c8d7SLEROY Christophe .cra_driver_name = "authenc-hmac-sha224-" 24887405c8d7SLEROY Christophe "cbc-3des-talitos", 24897405c8d7SLEROY Christophe .cra_blocksize = DES3_EDE_BLOCK_SIZE, 24907405c8d7SLEROY Christophe .cra_flags = CRYPTO_ALG_ASYNC, 24917405c8d7SLEROY Christophe }, 24927405c8d7SLEROY Christophe .ivsize = DES3_EDE_BLOCK_SIZE, 24937405c8d7SLEROY Christophe .maxauthsize = SHA224_DIGEST_SIZE, 2494*ef7c5c85SHerbert Xu .setkey = aead_des3_setkey, 24957405c8d7SLEROY Christophe }, 24967405c8d7SLEROY Christophe .desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU | 24977405c8d7SLEROY Christophe DESC_HDR_SEL0_DEU | 24987405c8d7SLEROY Christophe DESC_HDR_MODE0_DEU_CBC | 24997405c8d7SLEROY Christophe DESC_HDR_MODE0_DEU_3DES | 25007405c8d7SLEROY Christophe DESC_HDR_SEL1_MDEUA | 25017405c8d7SLEROY Christophe DESC_HDR_MODE1_MDEU_INIT | 25027405c8d7SLEROY Christophe DESC_HDR_MODE1_MDEU_PAD | 25037405c8d7SLEROY Christophe DESC_HDR_MODE1_MDEU_SHA224_HMAC, 25047405c8d7SLEROY Christophe }, 25057405c8d7SLEROY Christophe { .type = CRYPTO_ALG_TYPE_AEAD, 2506aeb4c132SHerbert Xu .alg.aead = { 2507aeb4c132SHerbert Xu .base = { 250856af8cd4SLee Nipper .cra_name = "authenc(hmac(sha256),cbc(aes))", 2509aeb4c132SHerbert Xu .cra_driver_name = "authenc-hmac-sha256-" 2510aeb4c132SHerbert Xu "cbc-aes-talitos", 251156af8cd4SLee Nipper .cra_blocksize = AES_BLOCK_SIZE, 2512aeb4c132SHerbert Xu .cra_flags = CRYPTO_ALG_ASYNC, 2513aeb4c132SHerbert Xu }, 25143952f17eSLee Nipper .ivsize = AES_BLOCK_SIZE, 25153952f17eSLee Nipper .maxauthsize = SHA256_DIGEST_SIZE, 25163952f17eSLee Nipper }, 25173952f17eSLee Nipper .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP | 25183952f17eSLee Nipper DESC_HDR_SEL0_AESU | 25193952f17eSLee Nipper DESC_HDR_MODE0_AESU_CBC | 25203952f17eSLee Nipper DESC_HDR_SEL1_MDEUA | 25213952f17eSLee Nipper DESC_HDR_MODE1_MDEU_INIT | 25223952f17eSLee Nipper DESC_HDR_MODE1_MDEU_PAD | 25233952f17eSLee Nipper DESC_HDR_MODE1_MDEU_SHA256_HMAC, 25243952f17eSLee Nipper }, 2525d5e4aaefSLee Nipper { .type = CRYPTO_ALG_TYPE_AEAD, 25267405c8d7SLEROY Christophe .priority = TALITOS_CRA_PRIORITY_AEAD_HSNA, 25277405c8d7SLEROY Christophe .alg.aead = { 25287405c8d7SLEROY Christophe .base = { 25297405c8d7SLEROY Christophe .cra_name = "authenc(hmac(sha256),cbc(aes))", 25307405c8d7SLEROY Christophe .cra_driver_name = "authenc-hmac-sha256-" 25317405c8d7SLEROY Christophe "cbc-aes-talitos", 25327405c8d7SLEROY Christophe .cra_blocksize = AES_BLOCK_SIZE, 25337405c8d7SLEROY Christophe .cra_flags = CRYPTO_ALG_ASYNC, 25347405c8d7SLEROY Christophe }, 25357405c8d7SLEROY Christophe .ivsize = AES_BLOCK_SIZE, 25367405c8d7SLEROY Christophe .maxauthsize = SHA256_DIGEST_SIZE, 25377405c8d7SLEROY Christophe }, 25387405c8d7SLEROY Christophe .desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU | 25397405c8d7SLEROY Christophe DESC_HDR_SEL0_AESU | 25407405c8d7SLEROY Christophe DESC_HDR_MODE0_AESU_CBC | 25417405c8d7SLEROY Christophe DESC_HDR_SEL1_MDEUA | 25427405c8d7SLEROY Christophe DESC_HDR_MODE1_MDEU_INIT | 25437405c8d7SLEROY Christophe DESC_HDR_MODE1_MDEU_PAD | 25447405c8d7SLEROY Christophe DESC_HDR_MODE1_MDEU_SHA256_HMAC, 25457405c8d7SLEROY Christophe }, 25467405c8d7SLEROY Christophe { .type = CRYPTO_ALG_TYPE_AEAD, 2547aeb4c132SHerbert Xu .alg.aead = { 2548aeb4c132SHerbert Xu .base = { 2549aeb4c132SHerbert Xu .cra_name = "authenc(hmac(sha256)," 2550aeb4c132SHerbert Xu "cbc(des3_ede))", 2551aeb4c132SHerbert Xu .cra_driver_name = "authenc-hmac-sha256-" 2552aeb4c132SHerbert Xu "cbc-3des-talitos", 255356af8cd4SLee Nipper .cra_blocksize = DES3_EDE_BLOCK_SIZE, 2554aeb4c132SHerbert Xu .cra_flags = CRYPTO_ALG_ASYNC, 2555aeb4c132SHerbert Xu }, 25563952f17eSLee Nipper .ivsize = DES3_EDE_BLOCK_SIZE, 25573952f17eSLee Nipper .maxauthsize = SHA256_DIGEST_SIZE, 2558*ef7c5c85SHerbert Xu .setkey = aead_des3_setkey, 25593952f17eSLee Nipper }, 25603952f17eSLee Nipper .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP | 25613952f17eSLee Nipper DESC_HDR_SEL0_DEU | 25623952f17eSLee Nipper DESC_HDR_MODE0_DEU_CBC | 25633952f17eSLee Nipper DESC_HDR_MODE0_DEU_3DES | 25643952f17eSLee Nipper DESC_HDR_SEL1_MDEUA | 25653952f17eSLee Nipper DESC_HDR_MODE1_MDEU_INIT | 25663952f17eSLee Nipper DESC_HDR_MODE1_MDEU_PAD | 25673952f17eSLee Nipper DESC_HDR_MODE1_MDEU_SHA256_HMAC, 25683952f17eSLee Nipper }, 2569d5e4aaefSLee Nipper { .type = CRYPTO_ALG_TYPE_AEAD, 25707405c8d7SLEROY Christophe .priority = TALITOS_CRA_PRIORITY_AEAD_HSNA, 25717405c8d7SLEROY Christophe .alg.aead = { 25727405c8d7SLEROY Christophe .base = { 25737405c8d7SLEROY Christophe .cra_name = "authenc(hmac(sha256)," 25747405c8d7SLEROY Christophe "cbc(des3_ede))", 25757405c8d7SLEROY Christophe .cra_driver_name = "authenc-hmac-sha256-" 25767405c8d7SLEROY Christophe "cbc-3des-talitos", 25777405c8d7SLEROY Christophe .cra_blocksize = DES3_EDE_BLOCK_SIZE, 25787405c8d7SLEROY Christophe .cra_flags = CRYPTO_ALG_ASYNC, 25797405c8d7SLEROY Christophe }, 25807405c8d7SLEROY Christophe .ivsize = DES3_EDE_BLOCK_SIZE, 25817405c8d7SLEROY Christophe .maxauthsize = SHA256_DIGEST_SIZE, 2582*ef7c5c85SHerbert Xu .setkey = aead_des3_setkey, 25837405c8d7SLEROY Christophe }, 25847405c8d7SLEROY Christophe .desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU | 25857405c8d7SLEROY Christophe DESC_HDR_SEL0_DEU | 25867405c8d7SLEROY Christophe DESC_HDR_MODE0_DEU_CBC | 25877405c8d7SLEROY Christophe DESC_HDR_MODE0_DEU_3DES | 25887405c8d7SLEROY Christophe DESC_HDR_SEL1_MDEUA | 25897405c8d7SLEROY Christophe DESC_HDR_MODE1_MDEU_INIT | 25907405c8d7SLEROY Christophe DESC_HDR_MODE1_MDEU_PAD | 25917405c8d7SLEROY Christophe DESC_HDR_MODE1_MDEU_SHA256_HMAC, 25927405c8d7SLEROY Christophe }, 25937405c8d7SLEROY Christophe { .type = CRYPTO_ALG_TYPE_AEAD, 2594aeb4c132SHerbert Xu .alg.aead = { 2595aeb4c132SHerbert Xu .base = { 2596357fb605SHoria Geanta .cra_name = "authenc(hmac(sha384),cbc(aes))", 2597aeb4c132SHerbert Xu .cra_driver_name = "authenc-hmac-sha384-" 2598aeb4c132SHerbert Xu "cbc-aes-talitos", 2599357fb605SHoria Geanta .cra_blocksize = AES_BLOCK_SIZE, 2600aeb4c132SHerbert Xu .cra_flags = CRYPTO_ALG_ASYNC, 2601aeb4c132SHerbert Xu }, 2602357fb605SHoria Geanta .ivsize = AES_BLOCK_SIZE, 2603357fb605SHoria Geanta .maxauthsize = SHA384_DIGEST_SIZE, 2604357fb605SHoria Geanta }, 2605357fb605SHoria Geanta .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP | 2606357fb605SHoria Geanta DESC_HDR_SEL0_AESU | 2607357fb605SHoria Geanta DESC_HDR_MODE0_AESU_CBC | 2608357fb605SHoria Geanta DESC_HDR_SEL1_MDEUB | 2609357fb605SHoria Geanta DESC_HDR_MODE1_MDEU_INIT | 2610357fb605SHoria Geanta DESC_HDR_MODE1_MDEU_PAD | 2611357fb605SHoria Geanta DESC_HDR_MODE1_MDEUB_SHA384_HMAC, 2612357fb605SHoria Geanta }, 2613357fb605SHoria Geanta { .type = CRYPTO_ALG_TYPE_AEAD, 2614aeb4c132SHerbert Xu .alg.aead = { 2615aeb4c132SHerbert Xu .base = { 2616aeb4c132SHerbert Xu .cra_name = "authenc(hmac(sha384)," 2617aeb4c132SHerbert Xu "cbc(des3_ede))", 2618aeb4c132SHerbert Xu .cra_driver_name = "authenc-hmac-sha384-" 2619aeb4c132SHerbert Xu "cbc-3des-talitos", 2620357fb605SHoria Geanta .cra_blocksize = DES3_EDE_BLOCK_SIZE, 2621aeb4c132SHerbert Xu .cra_flags = CRYPTO_ALG_ASYNC, 2622aeb4c132SHerbert Xu }, 2623357fb605SHoria Geanta .ivsize = DES3_EDE_BLOCK_SIZE, 2624357fb605SHoria Geanta .maxauthsize = SHA384_DIGEST_SIZE, 2625*ef7c5c85SHerbert Xu .setkey = aead_des3_setkey, 2626357fb605SHoria Geanta }, 2627357fb605SHoria Geanta .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP | 2628357fb605SHoria Geanta DESC_HDR_SEL0_DEU | 2629357fb605SHoria Geanta DESC_HDR_MODE0_DEU_CBC | 2630357fb605SHoria Geanta DESC_HDR_MODE0_DEU_3DES | 2631357fb605SHoria Geanta DESC_HDR_SEL1_MDEUB | 2632357fb605SHoria Geanta DESC_HDR_MODE1_MDEU_INIT | 2633357fb605SHoria Geanta DESC_HDR_MODE1_MDEU_PAD | 2634357fb605SHoria Geanta DESC_HDR_MODE1_MDEUB_SHA384_HMAC, 2635357fb605SHoria Geanta }, 2636357fb605SHoria Geanta { .type = CRYPTO_ALG_TYPE_AEAD, 2637aeb4c132SHerbert Xu .alg.aead = { 2638aeb4c132SHerbert Xu .base = { 2639357fb605SHoria Geanta .cra_name = "authenc(hmac(sha512),cbc(aes))", 2640aeb4c132SHerbert Xu .cra_driver_name = "authenc-hmac-sha512-" 2641aeb4c132SHerbert Xu "cbc-aes-talitos", 2642357fb605SHoria Geanta .cra_blocksize = AES_BLOCK_SIZE, 2643aeb4c132SHerbert Xu .cra_flags = CRYPTO_ALG_ASYNC, 2644aeb4c132SHerbert Xu }, 2645357fb605SHoria Geanta .ivsize = AES_BLOCK_SIZE, 2646357fb605SHoria Geanta .maxauthsize = SHA512_DIGEST_SIZE, 2647357fb605SHoria Geanta }, 2648357fb605SHoria Geanta .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP | 2649357fb605SHoria Geanta DESC_HDR_SEL0_AESU | 2650357fb605SHoria Geanta DESC_HDR_MODE0_AESU_CBC | 2651357fb605SHoria Geanta DESC_HDR_SEL1_MDEUB | 2652357fb605SHoria Geanta DESC_HDR_MODE1_MDEU_INIT | 2653357fb605SHoria Geanta DESC_HDR_MODE1_MDEU_PAD | 2654357fb605SHoria Geanta DESC_HDR_MODE1_MDEUB_SHA512_HMAC, 2655357fb605SHoria Geanta }, 2656357fb605SHoria Geanta { .type = CRYPTO_ALG_TYPE_AEAD, 2657aeb4c132SHerbert Xu .alg.aead = { 2658aeb4c132SHerbert Xu .base = { 2659aeb4c132SHerbert Xu .cra_name = "authenc(hmac(sha512)," 2660aeb4c132SHerbert Xu "cbc(des3_ede))", 2661aeb4c132SHerbert Xu .cra_driver_name = "authenc-hmac-sha512-" 2662aeb4c132SHerbert Xu "cbc-3des-talitos", 2663357fb605SHoria Geanta .cra_blocksize = DES3_EDE_BLOCK_SIZE, 2664aeb4c132SHerbert Xu .cra_flags = CRYPTO_ALG_ASYNC, 2665aeb4c132SHerbert Xu }, 2666357fb605SHoria Geanta .ivsize = DES3_EDE_BLOCK_SIZE, 2667357fb605SHoria Geanta .maxauthsize = SHA512_DIGEST_SIZE, 2668*ef7c5c85SHerbert Xu .setkey = aead_des3_setkey, 2669357fb605SHoria Geanta }, 2670357fb605SHoria Geanta .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP | 2671357fb605SHoria Geanta DESC_HDR_SEL0_DEU | 2672357fb605SHoria Geanta DESC_HDR_MODE0_DEU_CBC | 2673357fb605SHoria Geanta DESC_HDR_MODE0_DEU_3DES | 2674357fb605SHoria Geanta DESC_HDR_SEL1_MDEUB | 2675357fb605SHoria Geanta DESC_HDR_MODE1_MDEU_INIT | 2676357fb605SHoria Geanta DESC_HDR_MODE1_MDEU_PAD | 2677357fb605SHoria Geanta DESC_HDR_MODE1_MDEUB_SHA512_HMAC, 2678357fb605SHoria Geanta }, 2679357fb605SHoria Geanta { .type = CRYPTO_ALG_TYPE_AEAD, 2680aeb4c132SHerbert Xu .alg.aead = { 2681aeb4c132SHerbert Xu .base = { 268256af8cd4SLee Nipper .cra_name = "authenc(hmac(md5),cbc(aes))", 2683aeb4c132SHerbert Xu .cra_driver_name = "authenc-hmac-md5-" 2684aeb4c132SHerbert Xu "cbc-aes-talitos", 268556af8cd4SLee Nipper .cra_blocksize = AES_BLOCK_SIZE, 2686aeb4c132SHerbert Xu .cra_flags = CRYPTO_ALG_ASYNC, 2687aeb4c132SHerbert Xu }, 26883952f17eSLee Nipper .ivsize = AES_BLOCK_SIZE, 26893952f17eSLee Nipper .maxauthsize = MD5_DIGEST_SIZE, 26903952f17eSLee Nipper }, 26913952f17eSLee Nipper .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP | 26923952f17eSLee Nipper DESC_HDR_SEL0_AESU | 26933952f17eSLee Nipper DESC_HDR_MODE0_AESU_CBC | 26943952f17eSLee Nipper DESC_HDR_SEL1_MDEUA | 26953952f17eSLee Nipper DESC_HDR_MODE1_MDEU_INIT | 26963952f17eSLee Nipper DESC_HDR_MODE1_MDEU_PAD | 26973952f17eSLee Nipper DESC_HDR_MODE1_MDEU_MD5_HMAC, 26983952f17eSLee Nipper }, 2699d5e4aaefSLee Nipper { .type = CRYPTO_ALG_TYPE_AEAD, 27007405c8d7SLEROY Christophe .priority = TALITOS_CRA_PRIORITY_AEAD_HSNA, 27017405c8d7SLEROY Christophe .alg.aead = { 27027405c8d7SLEROY Christophe .base = { 27037405c8d7SLEROY Christophe .cra_name = "authenc(hmac(md5),cbc(aes))", 27047405c8d7SLEROY Christophe .cra_driver_name = "authenc-hmac-md5-" 27057405c8d7SLEROY Christophe "cbc-aes-talitos", 27067405c8d7SLEROY Christophe .cra_blocksize = AES_BLOCK_SIZE, 27077405c8d7SLEROY Christophe .cra_flags = CRYPTO_ALG_ASYNC, 27087405c8d7SLEROY Christophe }, 27097405c8d7SLEROY Christophe .ivsize = AES_BLOCK_SIZE, 27107405c8d7SLEROY Christophe .maxauthsize = MD5_DIGEST_SIZE, 27117405c8d7SLEROY Christophe }, 27127405c8d7SLEROY Christophe .desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU | 27137405c8d7SLEROY Christophe DESC_HDR_SEL0_AESU | 27147405c8d7SLEROY Christophe DESC_HDR_MODE0_AESU_CBC | 27157405c8d7SLEROY Christophe DESC_HDR_SEL1_MDEUA | 27167405c8d7SLEROY Christophe DESC_HDR_MODE1_MDEU_INIT | 27177405c8d7SLEROY Christophe DESC_HDR_MODE1_MDEU_PAD | 27187405c8d7SLEROY Christophe DESC_HDR_MODE1_MDEU_MD5_HMAC, 27197405c8d7SLEROY Christophe }, 27207405c8d7SLEROY Christophe { .type = CRYPTO_ALG_TYPE_AEAD, 2721aeb4c132SHerbert Xu .alg.aead = { 2722aeb4c132SHerbert Xu .base = { 272356af8cd4SLee Nipper .cra_name = "authenc(hmac(md5),cbc(des3_ede))", 2724aeb4c132SHerbert Xu .cra_driver_name = "authenc-hmac-md5-" 2725aeb4c132SHerbert Xu "cbc-3des-talitos", 272656af8cd4SLee Nipper .cra_blocksize = DES3_EDE_BLOCK_SIZE, 2727aeb4c132SHerbert Xu .cra_flags = CRYPTO_ALG_ASYNC, 2728aeb4c132SHerbert Xu }, 27293952f17eSLee Nipper .ivsize = DES3_EDE_BLOCK_SIZE, 27303952f17eSLee Nipper .maxauthsize = MD5_DIGEST_SIZE, 2731*ef7c5c85SHerbert Xu .setkey = aead_des3_setkey, 27323952f17eSLee Nipper }, 27333952f17eSLee Nipper .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP | 27343952f17eSLee Nipper DESC_HDR_SEL0_DEU | 27353952f17eSLee Nipper DESC_HDR_MODE0_DEU_CBC | 27363952f17eSLee Nipper DESC_HDR_MODE0_DEU_3DES | 27373952f17eSLee Nipper DESC_HDR_SEL1_MDEUA | 27383952f17eSLee Nipper DESC_HDR_MODE1_MDEU_INIT | 27393952f17eSLee Nipper DESC_HDR_MODE1_MDEU_PAD | 27403952f17eSLee Nipper DESC_HDR_MODE1_MDEU_MD5_HMAC, 27414de9d0b5SLee Nipper }, 27427405c8d7SLEROY Christophe { .type = CRYPTO_ALG_TYPE_AEAD, 27437405c8d7SLEROY Christophe .priority = TALITOS_CRA_PRIORITY_AEAD_HSNA, 27447405c8d7SLEROY Christophe .alg.aead = { 27457405c8d7SLEROY Christophe .base = { 27467405c8d7SLEROY Christophe .cra_name = "authenc(hmac(md5),cbc(des3_ede))", 27477405c8d7SLEROY Christophe .cra_driver_name = "authenc-hmac-md5-" 27487405c8d7SLEROY Christophe "cbc-3des-talitos", 27497405c8d7SLEROY Christophe .cra_blocksize = DES3_EDE_BLOCK_SIZE, 27507405c8d7SLEROY Christophe .cra_flags = CRYPTO_ALG_ASYNC, 27517405c8d7SLEROY Christophe }, 27527405c8d7SLEROY Christophe .ivsize = DES3_EDE_BLOCK_SIZE, 27537405c8d7SLEROY Christophe .maxauthsize = MD5_DIGEST_SIZE, 2754*ef7c5c85SHerbert Xu .setkey = aead_des3_setkey, 27557405c8d7SLEROY Christophe }, 27567405c8d7SLEROY Christophe .desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU | 27577405c8d7SLEROY Christophe DESC_HDR_SEL0_DEU | 27587405c8d7SLEROY Christophe DESC_HDR_MODE0_DEU_CBC | 27597405c8d7SLEROY Christophe DESC_HDR_MODE0_DEU_3DES | 27607405c8d7SLEROY Christophe DESC_HDR_SEL1_MDEUA | 27617405c8d7SLEROY Christophe DESC_HDR_MODE1_MDEU_INIT | 27627405c8d7SLEROY Christophe DESC_HDR_MODE1_MDEU_PAD | 27637405c8d7SLEROY Christophe DESC_HDR_MODE1_MDEU_MD5_HMAC, 27647405c8d7SLEROY Christophe }, 27654de9d0b5SLee Nipper /* ABLKCIPHER algorithms. */ 2766d5e4aaefSLee Nipper { .type = CRYPTO_ALG_TYPE_ABLKCIPHER, 2767d5e4aaefSLee Nipper .alg.crypto = { 27685e75ae1bSLEROY Christophe .cra_name = "ecb(aes)", 27695e75ae1bSLEROY Christophe .cra_driver_name = "ecb-aes-talitos", 27705e75ae1bSLEROY Christophe .cra_blocksize = AES_BLOCK_SIZE, 27715e75ae1bSLEROY Christophe .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | 27725e75ae1bSLEROY Christophe CRYPTO_ALG_ASYNC, 27735e75ae1bSLEROY Christophe .cra_ablkcipher = { 27745e75ae1bSLEROY Christophe .min_keysize = AES_MIN_KEY_SIZE, 27755e75ae1bSLEROY Christophe .max_keysize = AES_MAX_KEY_SIZE, 27765e75ae1bSLEROY Christophe .ivsize = AES_BLOCK_SIZE, 27775e75ae1bSLEROY Christophe } 27785e75ae1bSLEROY Christophe }, 27795e75ae1bSLEROY Christophe .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | 27805e75ae1bSLEROY Christophe DESC_HDR_SEL0_AESU, 27815e75ae1bSLEROY Christophe }, 27825e75ae1bSLEROY Christophe { .type = CRYPTO_ALG_TYPE_ABLKCIPHER, 27835e75ae1bSLEROY Christophe .alg.crypto = { 27844de9d0b5SLee Nipper .cra_name = "cbc(aes)", 27854de9d0b5SLee Nipper .cra_driver_name = "cbc-aes-talitos", 27864de9d0b5SLee Nipper .cra_blocksize = AES_BLOCK_SIZE, 27874de9d0b5SLee Nipper .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | 27884de9d0b5SLee Nipper CRYPTO_ALG_ASYNC, 27894de9d0b5SLee Nipper .cra_ablkcipher = { 27904de9d0b5SLee Nipper .min_keysize = AES_MIN_KEY_SIZE, 27914de9d0b5SLee Nipper .max_keysize = AES_MAX_KEY_SIZE, 27924de9d0b5SLee Nipper .ivsize = AES_BLOCK_SIZE, 27934de9d0b5SLee Nipper } 27944de9d0b5SLee Nipper }, 27954de9d0b5SLee Nipper .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | 27964de9d0b5SLee Nipper DESC_HDR_SEL0_AESU | 27974de9d0b5SLee Nipper DESC_HDR_MODE0_AESU_CBC, 27984de9d0b5SLee Nipper }, 2799d5e4aaefSLee Nipper { .type = CRYPTO_ALG_TYPE_ABLKCIPHER, 2800d5e4aaefSLee Nipper .alg.crypto = { 28015e75ae1bSLEROY Christophe .cra_name = "ctr(aes)", 28025e75ae1bSLEROY Christophe .cra_driver_name = "ctr-aes-talitos", 28035e75ae1bSLEROY Christophe .cra_blocksize = AES_BLOCK_SIZE, 28045e75ae1bSLEROY Christophe .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | 28055e75ae1bSLEROY Christophe CRYPTO_ALG_ASYNC, 28065e75ae1bSLEROY Christophe .cra_ablkcipher = { 28075e75ae1bSLEROY Christophe .min_keysize = AES_MIN_KEY_SIZE, 28085e75ae1bSLEROY Christophe .max_keysize = AES_MAX_KEY_SIZE, 28095e75ae1bSLEROY Christophe .ivsize = AES_BLOCK_SIZE, 28105e75ae1bSLEROY Christophe } 28115e75ae1bSLEROY Christophe }, 281270d355ccSLEROY Christophe .desc_hdr_template = DESC_HDR_TYPE_AESU_CTR_NONSNOOP | 28135e75ae1bSLEROY Christophe DESC_HDR_SEL0_AESU | 28145e75ae1bSLEROY Christophe DESC_HDR_MODE0_AESU_CTR, 28155e75ae1bSLEROY Christophe }, 28165e75ae1bSLEROY Christophe { .type = CRYPTO_ALG_TYPE_ABLKCIPHER, 28175e75ae1bSLEROY Christophe .alg.crypto = { 28185e75ae1bSLEROY Christophe .cra_name = "ecb(des)", 28195e75ae1bSLEROY Christophe .cra_driver_name = "ecb-des-talitos", 28205e75ae1bSLEROY Christophe .cra_blocksize = DES_BLOCK_SIZE, 28215e75ae1bSLEROY Christophe .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | 28225e75ae1bSLEROY Christophe CRYPTO_ALG_ASYNC, 28235e75ae1bSLEROY Christophe .cra_ablkcipher = { 28245e75ae1bSLEROY Christophe .min_keysize = DES_KEY_SIZE, 28255e75ae1bSLEROY Christophe .max_keysize = DES_KEY_SIZE, 28265e75ae1bSLEROY Christophe .ivsize = DES_BLOCK_SIZE, 2827*ef7c5c85SHerbert Xu .setkey = ablkcipher_des_setkey, 28285e75ae1bSLEROY Christophe } 28295e75ae1bSLEROY Christophe }, 28305e75ae1bSLEROY Christophe .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | 28315e75ae1bSLEROY Christophe DESC_HDR_SEL0_DEU, 28325e75ae1bSLEROY Christophe }, 28335e75ae1bSLEROY Christophe { .type = CRYPTO_ALG_TYPE_ABLKCIPHER, 28345e75ae1bSLEROY Christophe .alg.crypto = { 28355e75ae1bSLEROY Christophe .cra_name = "cbc(des)", 28365e75ae1bSLEROY Christophe .cra_driver_name = "cbc-des-talitos", 28375e75ae1bSLEROY Christophe .cra_blocksize = DES_BLOCK_SIZE, 28385e75ae1bSLEROY Christophe .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | 28395e75ae1bSLEROY Christophe CRYPTO_ALG_ASYNC, 28405e75ae1bSLEROY Christophe .cra_ablkcipher = { 28415e75ae1bSLEROY Christophe .min_keysize = DES_KEY_SIZE, 28425e75ae1bSLEROY Christophe .max_keysize = DES_KEY_SIZE, 28435e75ae1bSLEROY Christophe .ivsize = DES_BLOCK_SIZE, 2844*ef7c5c85SHerbert Xu .setkey = ablkcipher_des_setkey, 28455e75ae1bSLEROY Christophe } 28465e75ae1bSLEROY Christophe }, 28475e75ae1bSLEROY Christophe .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | 28485e75ae1bSLEROY Christophe DESC_HDR_SEL0_DEU | 28495e75ae1bSLEROY Christophe DESC_HDR_MODE0_DEU_CBC, 28505e75ae1bSLEROY Christophe }, 28515e75ae1bSLEROY Christophe { .type = CRYPTO_ALG_TYPE_ABLKCIPHER, 28525e75ae1bSLEROY Christophe .alg.crypto = { 28535e75ae1bSLEROY Christophe .cra_name = "ecb(des3_ede)", 28545e75ae1bSLEROY Christophe .cra_driver_name = "ecb-3des-talitos", 28555e75ae1bSLEROY Christophe .cra_blocksize = DES3_EDE_BLOCK_SIZE, 28565e75ae1bSLEROY Christophe .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | 28575e75ae1bSLEROY Christophe CRYPTO_ALG_ASYNC, 28585e75ae1bSLEROY Christophe .cra_ablkcipher = { 28595e75ae1bSLEROY Christophe .min_keysize = DES3_EDE_KEY_SIZE, 28605e75ae1bSLEROY Christophe .max_keysize = DES3_EDE_KEY_SIZE, 28615e75ae1bSLEROY Christophe .ivsize = DES3_EDE_BLOCK_SIZE, 2862*ef7c5c85SHerbert Xu .setkey = ablkcipher_des3_setkey, 28635e75ae1bSLEROY Christophe } 28645e75ae1bSLEROY Christophe }, 28655e75ae1bSLEROY Christophe .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | 28665e75ae1bSLEROY Christophe DESC_HDR_SEL0_DEU | 28675e75ae1bSLEROY Christophe DESC_HDR_MODE0_DEU_3DES, 28685e75ae1bSLEROY Christophe }, 28695e75ae1bSLEROY Christophe { .type = CRYPTO_ALG_TYPE_ABLKCIPHER, 28705e75ae1bSLEROY Christophe .alg.crypto = { 28714de9d0b5SLee Nipper .cra_name = "cbc(des3_ede)", 28724de9d0b5SLee Nipper .cra_driver_name = "cbc-3des-talitos", 28734de9d0b5SLee Nipper .cra_blocksize = DES3_EDE_BLOCK_SIZE, 28744de9d0b5SLee Nipper .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | 28754de9d0b5SLee Nipper CRYPTO_ALG_ASYNC, 28764de9d0b5SLee Nipper .cra_ablkcipher = { 28774de9d0b5SLee Nipper .min_keysize = DES3_EDE_KEY_SIZE, 28784de9d0b5SLee Nipper .max_keysize = DES3_EDE_KEY_SIZE, 28794de9d0b5SLee Nipper .ivsize = DES3_EDE_BLOCK_SIZE, 2880*ef7c5c85SHerbert Xu .setkey = ablkcipher_des3_setkey, 28814de9d0b5SLee Nipper } 28824de9d0b5SLee Nipper }, 28834de9d0b5SLee Nipper .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | 28844de9d0b5SLee Nipper DESC_HDR_SEL0_DEU | 28854de9d0b5SLee Nipper DESC_HDR_MODE0_DEU_CBC | 28864de9d0b5SLee Nipper DESC_HDR_MODE0_DEU_3DES, 2887497f2e6bSLee Nipper }, 2888497f2e6bSLee Nipper /* AHASH algorithms. */ 2889497f2e6bSLee Nipper { .type = CRYPTO_ALG_TYPE_AHASH, 2890497f2e6bSLee Nipper .alg.hash = { 2891497f2e6bSLee Nipper .halg.digestsize = MD5_DIGEST_SIZE, 28923639ca84SHoria Geant? .halg.statesize = sizeof(struct talitos_export_state), 2893497f2e6bSLee Nipper .halg.base = { 2894497f2e6bSLee Nipper .cra_name = "md5", 2895497f2e6bSLee Nipper .cra_driver_name = "md5-talitos", 2896b3988618SMartin Hicks .cra_blocksize = MD5_HMAC_BLOCK_SIZE, 28976a38f622SEric Biggers .cra_flags = CRYPTO_ALG_ASYNC, 28989c4a7965SKim Phillips } 2899497f2e6bSLee Nipper }, 2900497f2e6bSLee Nipper .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | 2901497f2e6bSLee Nipper DESC_HDR_SEL0_MDEUA | 2902497f2e6bSLee Nipper DESC_HDR_MODE0_MDEU_MD5, 2903497f2e6bSLee Nipper }, 2904497f2e6bSLee Nipper { .type = CRYPTO_ALG_TYPE_AHASH, 2905497f2e6bSLee Nipper .alg.hash = { 2906497f2e6bSLee Nipper .halg.digestsize = SHA1_DIGEST_SIZE, 29073639ca84SHoria Geant? .halg.statesize = sizeof(struct talitos_export_state), 2908497f2e6bSLee Nipper .halg.base = { 2909497f2e6bSLee Nipper .cra_name = "sha1", 2910497f2e6bSLee Nipper .cra_driver_name = "sha1-talitos", 2911497f2e6bSLee Nipper .cra_blocksize = SHA1_BLOCK_SIZE, 29126a38f622SEric Biggers .cra_flags = CRYPTO_ALG_ASYNC, 2913497f2e6bSLee Nipper } 2914497f2e6bSLee Nipper }, 2915497f2e6bSLee Nipper .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | 2916497f2e6bSLee Nipper DESC_HDR_SEL0_MDEUA | 2917497f2e6bSLee Nipper DESC_HDR_MODE0_MDEU_SHA1, 2918497f2e6bSLee Nipper }, 2919497f2e6bSLee Nipper { .type = CRYPTO_ALG_TYPE_AHASH, 2920497f2e6bSLee Nipper .alg.hash = { 292160f208d7SKim Phillips .halg.digestsize = SHA224_DIGEST_SIZE, 29223639ca84SHoria Geant? .halg.statesize = sizeof(struct talitos_export_state), 292360f208d7SKim Phillips .halg.base = { 292460f208d7SKim Phillips .cra_name = "sha224", 292560f208d7SKim Phillips .cra_driver_name = "sha224-talitos", 292660f208d7SKim Phillips .cra_blocksize = SHA224_BLOCK_SIZE, 29276a38f622SEric Biggers .cra_flags = CRYPTO_ALG_ASYNC, 292860f208d7SKim Phillips } 292960f208d7SKim Phillips }, 293060f208d7SKim Phillips .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | 293160f208d7SKim Phillips DESC_HDR_SEL0_MDEUA | 293260f208d7SKim Phillips DESC_HDR_MODE0_MDEU_SHA224, 293360f208d7SKim Phillips }, 293460f208d7SKim Phillips { .type = CRYPTO_ALG_TYPE_AHASH, 293560f208d7SKim Phillips .alg.hash = { 2936497f2e6bSLee Nipper .halg.digestsize = SHA256_DIGEST_SIZE, 29373639ca84SHoria Geant? .halg.statesize = sizeof(struct talitos_export_state), 2938497f2e6bSLee Nipper .halg.base = { 2939497f2e6bSLee Nipper .cra_name = "sha256", 2940497f2e6bSLee Nipper .cra_driver_name = "sha256-talitos", 2941497f2e6bSLee Nipper .cra_blocksize = SHA256_BLOCK_SIZE, 29426a38f622SEric Biggers .cra_flags = CRYPTO_ALG_ASYNC, 2943497f2e6bSLee Nipper } 2944497f2e6bSLee Nipper }, 2945497f2e6bSLee Nipper .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | 2946497f2e6bSLee Nipper DESC_HDR_SEL0_MDEUA | 2947497f2e6bSLee Nipper DESC_HDR_MODE0_MDEU_SHA256, 2948497f2e6bSLee Nipper }, 2949497f2e6bSLee Nipper { .type = CRYPTO_ALG_TYPE_AHASH, 2950497f2e6bSLee Nipper .alg.hash = { 2951497f2e6bSLee Nipper .halg.digestsize = SHA384_DIGEST_SIZE, 29523639ca84SHoria Geant? .halg.statesize = sizeof(struct talitos_export_state), 2953497f2e6bSLee Nipper .halg.base = { 2954497f2e6bSLee Nipper .cra_name = "sha384", 2955497f2e6bSLee Nipper .cra_driver_name = "sha384-talitos", 2956497f2e6bSLee Nipper .cra_blocksize = SHA384_BLOCK_SIZE, 29576a38f622SEric Biggers .cra_flags = CRYPTO_ALG_ASYNC, 2958497f2e6bSLee Nipper } 2959497f2e6bSLee Nipper }, 2960497f2e6bSLee Nipper .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | 2961497f2e6bSLee Nipper DESC_HDR_SEL0_MDEUB | 2962497f2e6bSLee Nipper DESC_HDR_MODE0_MDEUB_SHA384, 2963497f2e6bSLee Nipper }, 2964497f2e6bSLee Nipper { .type = CRYPTO_ALG_TYPE_AHASH, 2965497f2e6bSLee Nipper .alg.hash = { 2966497f2e6bSLee Nipper .halg.digestsize = SHA512_DIGEST_SIZE, 29673639ca84SHoria Geant? .halg.statesize = sizeof(struct talitos_export_state), 2968497f2e6bSLee Nipper .halg.base = { 2969497f2e6bSLee Nipper .cra_name = "sha512", 2970497f2e6bSLee Nipper .cra_driver_name = "sha512-talitos", 2971497f2e6bSLee Nipper .cra_blocksize = SHA512_BLOCK_SIZE, 29726a38f622SEric Biggers .cra_flags = CRYPTO_ALG_ASYNC, 2973497f2e6bSLee Nipper } 2974497f2e6bSLee Nipper }, 2975497f2e6bSLee Nipper .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | 2976497f2e6bSLee Nipper DESC_HDR_SEL0_MDEUB | 2977497f2e6bSLee Nipper DESC_HDR_MODE0_MDEUB_SHA512, 2978497f2e6bSLee Nipper }, 297979b3a418SLee Nipper { .type = CRYPTO_ALG_TYPE_AHASH, 298079b3a418SLee Nipper .alg.hash = { 298179b3a418SLee Nipper .halg.digestsize = MD5_DIGEST_SIZE, 29823639ca84SHoria Geant? .halg.statesize = sizeof(struct talitos_export_state), 298379b3a418SLee Nipper .halg.base = { 298479b3a418SLee Nipper .cra_name = "hmac(md5)", 298579b3a418SLee Nipper .cra_driver_name = "hmac-md5-talitos", 2986b3988618SMartin Hicks .cra_blocksize = MD5_HMAC_BLOCK_SIZE, 29876a38f622SEric Biggers .cra_flags = CRYPTO_ALG_ASYNC, 298879b3a418SLee Nipper } 298979b3a418SLee Nipper }, 299079b3a418SLee Nipper .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | 299179b3a418SLee Nipper DESC_HDR_SEL0_MDEUA | 299279b3a418SLee Nipper DESC_HDR_MODE0_MDEU_MD5, 299379b3a418SLee Nipper }, 299479b3a418SLee Nipper { .type = CRYPTO_ALG_TYPE_AHASH, 299579b3a418SLee Nipper .alg.hash = { 299679b3a418SLee Nipper .halg.digestsize = SHA1_DIGEST_SIZE, 29973639ca84SHoria Geant? .halg.statesize = sizeof(struct talitos_export_state), 299879b3a418SLee Nipper .halg.base = { 299979b3a418SLee Nipper .cra_name = "hmac(sha1)", 300079b3a418SLee Nipper .cra_driver_name = "hmac-sha1-talitos", 300179b3a418SLee Nipper .cra_blocksize = SHA1_BLOCK_SIZE, 30026a38f622SEric Biggers .cra_flags = CRYPTO_ALG_ASYNC, 300379b3a418SLee Nipper } 300479b3a418SLee Nipper }, 300579b3a418SLee Nipper .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | 300679b3a418SLee Nipper DESC_HDR_SEL0_MDEUA | 300779b3a418SLee Nipper DESC_HDR_MODE0_MDEU_SHA1, 300879b3a418SLee Nipper }, 300979b3a418SLee Nipper { .type = CRYPTO_ALG_TYPE_AHASH, 301079b3a418SLee Nipper .alg.hash = { 301179b3a418SLee Nipper .halg.digestsize = SHA224_DIGEST_SIZE, 30123639ca84SHoria Geant? .halg.statesize = sizeof(struct talitos_export_state), 301379b3a418SLee Nipper .halg.base = { 301479b3a418SLee Nipper .cra_name = "hmac(sha224)", 301579b3a418SLee Nipper .cra_driver_name = "hmac-sha224-talitos", 301679b3a418SLee Nipper .cra_blocksize = SHA224_BLOCK_SIZE, 30176a38f622SEric Biggers .cra_flags = CRYPTO_ALG_ASYNC, 301879b3a418SLee Nipper } 301979b3a418SLee Nipper }, 302079b3a418SLee Nipper .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | 302179b3a418SLee Nipper DESC_HDR_SEL0_MDEUA | 302279b3a418SLee Nipper DESC_HDR_MODE0_MDEU_SHA224, 302379b3a418SLee Nipper }, 302479b3a418SLee Nipper { .type = CRYPTO_ALG_TYPE_AHASH, 302579b3a418SLee Nipper .alg.hash = { 302679b3a418SLee Nipper .halg.digestsize = SHA256_DIGEST_SIZE, 30273639ca84SHoria Geant? .halg.statesize = sizeof(struct talitos_export_state), 302879b3a418SLee Nipper .halg.base = { 302979b3a418SLee Nipper .cra_name = "hmac(sha256)", 303079b3a418SLee Nipper .cra_driver_name = "hmac-sha256-talitos", 303179b3a418SLee Nipper .cra_blocksize = SHA256_BLOCK_SIZE, 30326a38f622SEric Biggers .cra_flags = CRYPTO_ALG_ASYNC, 303379b3a418SLee Nipper } 303479b3a418SLee Nipper }, 303579b3a418SLee Nipper .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | 303679b3a418SLee Nipper DESC_HDR_SEL0_MDEUA | 303779b3a418SLee Nipper DESC_HDR_MODE0_MDEU_SHA256, 303879b3a418SLee Nipper }, 303979b3a418SLee Nipper { .type = CRYPTO_ALG_TYPE_AHASH, 304079b3a418SLee Nipper .alg.hash = { 304179b3a418SLee Nipper .halg.digestsize = SHA384_DIGEST_SIZE, 30423639ca84SHoria Geant? .halg.statesize = sizeof(struct talitos_export_state), 304379b3a418SLee Nipper .halg.base = { 304479b3a418SLee Nipper .cra_name = "hmac(sha384)", 304579b3a418SLee Nipper .cra_driver_name = "hmac-sha384-talitos", 304679b3a418SLee Nipper .cra_blocksize = SHA384_BLOCK_SIZE, 30476a38f622SEric Biggers .cra_flags = CRYPTO_ALG_ASYNC, 304879b3a418SLee Nipper } 304979b3a418SLee Nipper }, 305079b3a418SLee Nipper .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | 305179b3a418SLee Nipper DESC_HDR_SEL0_MDEUB | 305279b3a418SLee Nipper DESC_HDR_MODE0_MDEUB_SHA384, 305379b3a418SLee Nipper }, 305479b3a418SLee Nipper { .type = CRYPTO_ALG_TYPE_AHASH, 305579b3a418SLee Nipper .alg.hash = { 305679b3a418SLee Nipper .halg.digestsize = SHA512_DIGEST_SIZE, 30573639ca84SHoria Geant? .halg.statesize = sizeof(struct talitos_export_state), 305879b3a418SLee Nipper .halg.base = { 305979b3a418SLee Nipper .cra_name = "hmac(sha512)", 306079b3a418SLee Nipper .cra_driver_name = "hmac-sha512-talitos", 306179b3a418SLee Nipper .cra_blocksize = SHA512_BLOCK_SIZE, 30626a38f622SEric Biggers .cra_flags = CRYPTO_ALG_ASYNC, 306379b3a418SLee Nipper } 306479b3a418SLee Nipper }, 306579b3a418SLee Nipper .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | 306679b3a418SLee Nipper DESC_HDR_SEL0_MDEUB | 306779b3a418SLee Nipper DESC_HDR_MODE0_MDEUB_SHA512, 306879b3a418SLee Nipper } 30699c4a7965SKim Phillips }; 30709c4a7965SKim Phillips 30719c4a7965SKim Phillips struct talitos_crypto_alg { 30729c4a7965SKim Phillips struct list_head entry; 30739c4a7965SKim Phillips struct device *dev; 3074acbf7c62SLee Nipper struct talitos_alg_template algt; 30759c4a7965SKim Phillips }; 30769c4a7965SKim Phillips 307789d124cbSJonas Eymann static int talitos_init_common(struct talitos_ctx *ctx, 307889d124cbSJonas Eymann struct talitos_crypto_alg *talitos_alg) 30799c4a7965SKim Phillips { 30805228f0f7SKim Phillips struct talitos_private *priv; 30819c4a7965SKim Phillips 30829c4a7965SKim Phillips /* update context with ptr to dev */ 30839c4a7965SKim Phillips ctx->dev = talitos_alg->dev; 308419bbbc63SKim Phillips 30855228f0f7SKim Phillips /* assign SEC channel to tfm in round-robin fashion */ 30865228f0f7SKim Phillips priv = dev_get_drvdata(ctx->dev); 30875228f0f7SKim Phillips ctx->ch = atomic_inc_return(&priv->last_chan) & 30885228f0f7SKim Phillips (priv->num_channels - 1); 30895228f0f7SKim Phillips 30909c4a7965SKim Phillips /* copy descriptor header template value */ 3091acbf7c62SLee Nipper ctx->desc_hdr_template = talitos_alg->algt.desc_hdr_template; 30929c4a7965SKim Phillips 3093602dba5aSKim Phillips /* select done notification */ 3094602dba5aSKim Phillips ctx->desc_hdr_template |= DESC_HDR_DONE_NOTIFY; 3095602dba5aSKim Phillips 3096497f2e6bSLee Nipper return 0; 3097497f2e6bSLee Nipper } 3098497f2e6bSLee Nipper 309989d124cbSJonas Eymann static int talitos_cra_init(struct crypto_tfm *tfm) 310089d124cbSJonas Eymann { 310189d124cbSJonas Eymann struct crypto_alg *alg = tfm->__crt_alg; 310289d124cbSJonas Eymann struct talitos_crypto_alg *talitos_alg; 310389d124cbSJonas Eymann struct talitos_ctx *ctx = crypto_tfm_ctx(tfm); 310489d124cbSJonas Eymann 310589d124cbSJonas Eymann if ((alg->cra_flags & CRYPTO_ALG_TYPE_MASK) == CRYPTO_ALG_TYPE_AHASH) 310689d124cbSJonas Eymann talitos_alg = container_of(__crypto_ahash_alg(alg), 310789d124cbSJonas Eymann struct talitos_crypto_alg, 310889d124cbSJonas Eymann algt.alg.hash); 310989d124cbSJonas Eymann else 311089d124cbSJonas Eymann talitos_alg = container_of(alg, struct talitos_crypto_alg, 311189d124cbSJonas Eymann algt.alg.crypto); 311289d124cbSJonas Eymann 311389d124cbSJonas Eymann return talitos_init_common(ctx, talitos_alg); 311489d124cbSJonas Eymann } 311589d124cbSJonas Eymann 3116aeb4c132SHerbert Xu static int talitos_cra_init_aead(struct crypto_aead *tfm) 3117497f2e6bSLee Nipper { 311889d124cbSJonas Eymann struct aead_alg *alg = crypto_aead_alg(tfm); 311989d124cbSJonas Eymann struct talitos_crypto_alg *talitos_alg; 312089d124cbSJonas Eymann struct talitos_ctx *ctx = crypto_aead_ctx(tfm); 312189d124cbSJonas Eymann 312289d124cbSJonas Eymann talitos_alg = container_of(alg, struct talitos_crypto_alg, 312389d124cbSJonas Eymann algt.alg.aead); 312489d124cbSJonas Eymann 312589d124cbSJonas Eymann return talitos_init_common(ctx, talitos_alg); 31269c4a7965SKim Phillips } 31279c4a7965SKim Phillips 3128497f2e6bSLee Nipper static int talitos_cra_init_ahash(struct crypto_tfm *tfm) 3129497f2e6bSLee Nipper { 3130497f2e6bSLee Nipper struct talitos_ctx *ctx = crypto_tfm_ctx(tfm); 3131497f2e6bSLee Nipper 3132497f2e6bSLee Nipper talitos_cra_init(tfm); 3133497f2e6bSLee Nipper 3134497f2e6bSLee Nipper ctx->keylen = 0; 3135497f2e6bSLee Nipper crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm), 3136497f2e6bSLee Nipper sizeof(struct talitos_ahash_req_ctx)); 3137497f2e6bSLee Nipper 3138497f2e6bSLee Nipper return 0; 3139497f2e6bSLee Nipper } 3140497f2e6bSLee Nipper 31412e13ce08SLEROY Christophe static void talitos_cra_exit(struct crypto_tfm *tfm) 31422e13ce08SLEROY Christophe { 31432e13ce08SLEROY Christophe struct talitos_ctx *ctx = crypto_tfm_ctx(tfm); 31442e13ce08SLEROY Christophe struct device *dev = ctx->dev; 31452e13ce08SLEROY Christophe 31462e13ce08SLEROY Christophe if (ctx->keylen) 31472e13ce08SLEROY Christophe dma_unmap_single(dev, ctx->dma_key, ctx->keylen, DMA_TO_DEVICE); 31482e13ce08SLEROY Christophe } 31492e13ce08SLEROY Christophe 31509c4a7965SKim Phillips /* 31519c4a7965SKim Phillips * given the alg's descriptor header template, determine whether descriptor 31529c4a7965SKim Phillips * type and primary/secondary execution units required match the hw 31539c4a7965SKim Phillips * capabilities description provided in the device tree node. 31549c4a7965SKim Phillips */ 31559c4a7965SKim Phillips static int hw_supports(struct device *dev, __be32 desc_hdr_template) 31569c4a7965SKim Phillips { 31579c4a7965SKim Phillips struct talitos_private *priv = dev_get_drvdata(dev); 31589c4a7965SKim Phillips int ret; 31599c4a7965SKim Phillips 31609c4a7965SKim Phillips ret = (1 << DESC_TYPE(desc_hdr_template) & priv->desc_types) && 31619c4a7965SKim Phillips (1 << PRIMARY_EU(desc_hdr_template) & priv->exec_units); 31629c4a7965SKim Phillips 31639c4a7965SKim Phillips if (SECONDARY_EU(desc_hdr_template)) 31649c4a7965SKim Phillips ret = ret && (1 << SECONDARY_EU(desc_hdr_template) 31659c4a7965SKim Phillips & priv->exec_units); 31669c4a7965SKim Phillips 31679c4a7965SKim Phillips return ret; 31689c4a7965SKim Phillips } 31699c4a7965SKim Phillips 31702dc11581SGrant Likely static int talitos_remove(struct platform_device *ofdev) 31719c4a7965SKim Phillips { 31729c4a7965SKim Phillips struct device *dev = &ofdev->dev; 31739c4a7965SKim Phillips struct talitos_private *priv = dev_get_drvdata(dev); 31749c4a7965SKim Phillips struct talitos_crypto_alg *t_alg, *n; 31759c4a7965SKim Phillips int i; 31769c4a7965SKim Phillips 31779c4a7965SKim Phillips list_for_each_entry_safe(t_alg, n, &priv->alg_list, entry) { 3178acbf7c62SLee Nipper switch (t_alg->algt.type) { 3179acbf7c62SLee Nipper case CRYPTO_ALG_TYPE_ABLKCIPHER: 3180acbf7c62SLee Nipper break; 3181aeb4c132SHerbert Xu case CRYPTO_ALG_TYPE_AEAD: 3182aeb4c132SHerbert Xu crypto_unregister_aead(&t_alg->algt.alg.aead); 3183acbf7c62SLee Nipper case CRYPTO_ALG_TYPE_AHASH: 3184acbf7c62SLee Nipper crypto_unregister_ahash(&t_alg->algt.alg.hash); 3185acbf7c62SLee Nipper break; 3186acbf7c62SLee Nipper } 31879c4a7965SKim Phillips list_del(&t_alg->entry); 31889c4a7965SKim Phillips } 31899c4a7965SKim Phillips 31909c4a7965SKim Phillips if (hw_supports(dev, DESC_HDR_SEL0_RNG)) 31919c4a7965SKim Phillips talitos_unregister_rng(dev); 31929c4a7965SKim Phillips 3193c3e337f8SKim Phillips for (i = 0; i < 2; i++) 31942cdba3cfSKim Phillips if (priv->irq[i]) { 3195c3e337f8SKim Phillips free_irq(priv->irq[i], dev); 3196c3e337f8SKim Phillips irq_dispose_mapping(priv->irq[i]); 31979c4a7965SKim Phillips } 31989c4a7965SKim Phillips 3199c3e337f8SKim Phillips tasklet_kill(&priv->done_task[0]); 32002cdba3cfSKim Phillips if (priv->irq[1]) 3201c3e337f8SKim Phillips tasklet_kill(&priv->done_task[1]); 32029c4a7965SKim Phillips 32039c4a7965SKim Phillips return 0; 32049c4a7965SKim Phillips } 32059c4a7965SKim Phillips 32069c4a7965SKim Phillips static struct talitos_crypto_alg *talitos_alg_alloc(struct device *dev, 32079c4a7965SKim Phillips struct talitos_alg_template 32089c4a7965SKim Phillips *template) 32099c4a7965SKim Phillips { 321060f208d7SKim Phillips struct talitos_private *priv = dev_get_drvdata(dev); 32119c4a7965SKim Phillips struct talitos_crypto_alg *t_alg; 32129c4a7965SKim Phillips struct crypto_alg *alg; 32139c4a7965SKim Phillips 321424b92ff2SLEROY Christophe t_alg = devm_kzalloc(dev, sizeof(struct talitos_crypto_alg), 321524b92ff2SLEROY Christophe GFP_KERNEL); 32169c4a7965SKim Phillips if (!t_alg) 32179c4a7965SKim Phillips return ERR_PTR(-ENOMEM); 32189c4a7965SKim Phillips 3219acbf7c62SLee Nipper t_alg->algt = *template; 3220acbf7c62SLee Nipper 3221acbf7c62SLee Nipper switch (t_alg->algt.type) { 3222acbf7c62SLee Nipper case CRYPTO_ALG_TYPE_ABLKCIPHER: 3223497f2e6bSLee Nipper alg = &t_alg->algt.alg.crypto; 3224497f2e6bSLee Nipper alg->cra_init = talitos_cra_init; 32252e13ce08SLEROY Christophe alg->cra_exit = talitos_cra_exit; 3226d4cd3283SKim Phillips alg->cra_type = &crypto_ablkcipher_type; 3227*ef7c5c85SHerbert Xu alg->cra_ablkcipher.setkey = alg->cra_ablkcipher.setkey ?: 3228*ef7c5c85SHerbert Xu ablkcipher_setkey; 3229b286e003SKim Phillips alg->cra_ablkcipher.encrypt = ablkcipher_encrypt; 3230b286e003SKim Phillips alg->cra_ablkcipher.decrypt = ablkcipher_decrypt; 3231497f2e6bSLee Nipper break; 3232acbf7c62SLee Nipper case CRYPTO_ALG_TYPE_AEAD: 3233aeb4c132SHerbert Xu alg = &t_alg->algt.alg.aead.base; 32342e13ce08SLEROY Christophe alg->cra_exit = talitos_cra_exit; 3235aeb4c132SHerbert Xu t_alg->algt.alg.aead.init = talitos_cra_init_aead; 3236*ef7c5c85SHerbert Xu t_alg->algt.alg.aead.setkey = t_alg->algt.alg.aead.setkey ?: 3237*ef7c5c85SHerbert Xu aead_setkey; 3238aeb4c132SHerbert Xu t_alg->algt.alg.aead.encrypt = aead_encrypt; 3239aeb4c132SHerbert Xu t_alg->algt.alg.aead.decrypt = aead_decrypt; 32406cda075aSLEROY Christophe if (!(priv->features & TALITOS_FTR_SHA224_HWINIT) && 32416cda075aSLEROY Christophe !strncmp(alg->cra_name, "authenc(hmac(sha224)", 20)) { 324224b92ff2SLEROY Christophe devm_kfree(dev, t_alg); 32436cda075aSLEROY Christophe return ERR_PTR(-ENOTSUPP); 32446cda075aSLEROY Christophe } 3245acbf7c62SLee Nipper break; 3246acbf7c62SLee Nipper case CRYPTO_ALG_TYPE_AHASH: 3247acbf7c62SLee Nipper alg = &t_alg->algt.alg.hash.halg.base; 3248497f2e6bSLee Nipper alg->cra_init = talitos_cra_init_ahash; 3249ad4cd51fSLEROY Christophe alg->cra_exit = talitos_cra_exit; 3250b286e003SKim Phillips t_alg->algt.alg.hash.init = ahash_init; 3251b286e003SKim Phillips t_alg->algt.alg.hash.update = ahash_update; 3252b286e003SKim Phillips t_alg->algt.alg.hash.final = ahash_final; 3253b286e003SKim Phillips t_alg->algt.alg.hash.finup = ahash_finup; 3254b286e003SKim Phillips t_alg->algt.alg.hash.digest = ahash_digest; 325556136631SLEROY Christophe if (!strncmp(alg->cra_name, "hmac", 4)) 3256b286e003SKim Phillips t_alg->algt.alg.hash.setkey = ahash_setkey; 32573639ca84SHoria Geant? t_alg->algt.alg.hash.import = ahash_import; 32583639ca84SHoria Geant? t_alg->algt.alg.hash.export = ahash_export; 3259b286e003SKim Phillips 326079b3a418SLee Nipper if (!(priv->features & TALITOS_FTR_HMAC_OK) && 32610b2730d8SKim Phillips !strncmp(alg->cra_name, "hmac", 4)) { 326224b92ff2SLEROY Christophe devm_kfree(dev, t_alg); 326379b3a418SLee Nipper return ERR_PTR(-ENOTSUPP); 32640b2730d8SKim Phillips } 326560f208d7SKim Phillips if (!(priv->features & TALITOS_FTR_SHA224_HWINIT) && 326679b3a418SLee Nipper (!strcmp(alg->cra_name, "sha224") || 326779b3a418SLee Nipper !strcmp(alg->cra_name, "hmac(sha224)"))) { 326860f208d7SKim Phillips t_alg->algt.alg.hash.init = ahash_init_sha224_swinit; 326960f208d7SKim Phillips t_alg->algt.desc_hdr_template = 327060f208d7SKim Phillips DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | 327160f208d7SKim Phillips DESC_HDR_SEL0_MDEUA | 327260f208d7SKim Phillips DESC_HDR_MODE0_MDEU_SHA256; 327360f208d7SKim Phillips } 3274497f2e6bSLee Nipper break; 32751d11911aSKim Phillips default: 32761d11911aSKim Phillips dev_err(dev, "unknown algorithm type %d\n", t_alg->algt.type); 327724b92ff2SLEROY Christophe devm_kfree(dev, t_alg); 32781d11911aSKim Phillips return ERR_PTR(-EINVAL); 3279acbf7c62SLee Nipper } 32809c4a7965SKim Phillips 32819c4a7965SKim Phillips alg->cra_module = THIS_MODULE; 3282b0057763SLEROY Christophe if (t_alg->algt.priority) 3283b0057763SLEROY Christophe alg->cra_priority = t_alg->algt.priority; 3284b0057763SLEROY Christophe else 32859c4a7965SKim Phillips alg->cra_priority = TALITOS_CRA_PRIORITY; 32869c4a7965SKim Phillips alg->cra_alignmask = 0; 32879c4a7965SKim Phillips alg->cra_ctxsize = sizeof(struct talitos_ctx); 3288d912bb76SNikos Mavrogiannopoulos alg->cra_flags |= CRYPTO_ALG_KERN_DRIVER_ONLY; 32899c4a7965SKim Phillips 32909c4a7965SKim Phillips t_alg->dev = dev; 32919c4a7965SKim Phillips 32929c4a7965SKim Phillips return t_alg; 32939c4a7965SKim Phillips } 32949c4a7965SKim Phillips 3295c3e337f8SKim Phillips static int talitos_probe_irq(struct platform_device *ofdev) 3296c3e337f8SKim Phillips { 3297c3e337f8SKim Phillips struct device *dev = &ofdev->dev; 3298c3e337f8SKim Phillips struct device_node *np = ofdev->dev.of_node; 3299c3e337f8SKim Phillips struct talitos_private *priv = dev_get_drvdata(dev); 3300c3e337f8SKim Phillips int err; 3301dd3c0987SLEROY Christophe bool is_sec1 = has_ftr_sec1(priv); 3302c3e337f8SKim Phillips 3303c3e337f8SKim Phillips priv->irq[0] = irq_of_parse_and_map(np, 0); 33042cdba3cfSKim Phillips if (!priv->irq[0]) { 3305c3e337f8SKim Phillips dev_err(dev, "failed to map irq\n"); 3306c3e337f8SKim Phillips return -EINVAL; 3307c3e337f8SKim Phillips } 3308dd3c0987SLEROY Christophe if (is_sec1) { 3309dd3c0987SLEROY Christophe err = request_irq(priv->irq[0], talitos1_interrupt_4ch, 0, 3310dd3c0987SLEROY Christophe dev_driver_string(dev), dev); 3311dd3c0987SLEROY Christophe goto primary_out; 3312dd3c0987SLEROY Christophe } 3313c3e337f8SKim Phillips 3314c3e337f8SKim Phillips priv->irq[1] = irq_of_parse_and_map(np, 1); 3315c3e337f8SKim Phillips 3316c3e337f8SKim Phillips /* get the primary irq line */ 33172cdba3cfSKim Phillips if (!priv->irq[1]) { 3318dd3c0987SLEROY Christophe err = request_irq(priv->irq[0], talitos2_interrupt_4ch, 0, 3319c3e337f8SKim Phillips dev_driver_string(dev), dev); 3320c3e337f8SKim Phillips goto primary_out; 3321c3e337f8SKim Phillips } 3322c3e337f8SKim Phillips 3323dd3c0987SLEROY Christophe err = request_irq(priv->irq[0], talitos2_interrupt_ch0_2, 0, 3324c3e337f8SKim Phillips dev_driver_string(dev), dev); 3325c3e337f8SKim Phillips if (err) 3326c3e337f8SKim Phillips goto primary_out; 3327c3e337f8SKim Phillips 3328c3e337f8SKim Phillips /* get the secondary irq line */ 3329dd3c0987SLEROY Christophe err = request_irq(priv->irq[1], talitos2_interrupt_ch1_3, 0, 3330c3e337f8SKim Phillips dev_driver_string(dev), dev); 3331c3e337f8SKim Phillips if (err) { 3332c3e337f8SKim Phillips dev_err(dev, "failed to request secondary irq\n"); 3333c3e337f8SKim Phillips irq_dispose_mapping(priv->irq[1]); 33342cdba3cfSKim Phillips priv->irq[1] = 0; 3335c3e337f8SKim Phillips } 3336c3e337f8SKim Phillips 3337c3e337f8SKim Phillips return err; 3338c3e337f8SKim Phillips 3339c3e337f8SKim Phillips primary_out: 3340c3e337f8SKim Phillips if (err) { 3341c3e337f8SKim Phillips dev_err(dev, "failed to request primary irq\n"); 3342c3e337f8SKim Phillips irq_dispose_mapping(priv->irq[0]); 33432cdba3cfSKim Phillips priv->irq[0] = 0; 3344c3e337f8SKim Phillips } 3345c3e337f8SKim Phillips 3346c3e337f8SKim Phillips return err; 3347c3e337f8SKim Phillips } 3348c3e337f8SKim Phillips 33491c48a5c9SGrant Likely static int talitos_probe(struct platform_device *ofdev) 33509c4a7965SKim Phillips { 33519c4a7965SKim Phillips struct device *dev = &ofdev->dev; 335261c7a080SGrant Likely struct device_node *np = ofdev->dev.of_node; 33539c4a7965SKim Phillips struct talitos_private *priv; 33549c4a7965SKim Phillips int i, err; 33555fa7fa14SLEROY Christophe int stride; 3356fd5ea7f0SLEROY Christophe struct resource *res; 33579c4a7965SKim Phillips 335824b92ff2SLEROY Christophe priv = devm_kzalloc(dev, sizeof(struct talitos_private), GFP_KERNEL); 33599c4a7965SKim Phillips if (!priv) 33609c4a7965SKim Phillips return -ENOMEM; 33619c4a7965SKim Phillips 3362f3de9cb1SKevin Hao INIT_LIST_HEAD(&priv->alg_list); 3363f3de9cb1SKevin Hao 33649c4a7965SKim Phillips dev_set_drvdata(dev, priv); 33659c4a7965SKim Phillips 33669c4a7965SKim Phillips priv->ofdev = ofdev; 33679c4a7965SKim Phillips 3368511d63cbSHoria Geanta spin_lock_init(&priv->reg_lock); 3369511d63cbSHoria Geanta 3370fd5ea7f0SLEROY Christophe res = platform_get_resource(ofdev, IORESOURCE_MEM, 0); 3371fd5ea7f0SLEROY Christophe if (!res) 3372fd5ea7f0SLEROY Christophe return -ENXIO; 3373fd5ea7f0SLEROY Christophe priv->reg = devm_ioremap(dev, res->start, resource_size(res)); 33749c4a7965SKim Phillips if (!priv->reg) { 33759c4a7965SKim Phillips dev_err(dev, "failed to of_iomap\n"); 33769c4a7965SKim Phillips err = -ENOMEM; 33779c4a7965SKim Phillips goto err_out; 33789c4a7965SKim Phillips } 33799c4a7965SKim Phillips 33809c4a7965SKim Phillips /* get SEC version capabilities from device tree */ 3381fa14c6cfSLEROY Christophe of_property_read_u32(np, "fsl,num-channels", &priv->num_channels); 3382fa14c6cfSLEROY Christophe of_property_read_u32(np, "fsl,channel-fifo-len", &priv->chfifo_len); 3383fa14c6cfSLEROY Christophe of_property_read_u32(np, "fsl,exec-units-mask", &priv->exec_units); 3384fa14c6cfSLEROY Christophe of_property_read_u32(np, "fsl,descriptor-types-mask", 3385fa14c6cfSLEROY Christophe &priv->desc_types); 33869c4a7965SKim Phillips 33879c4a7965SKim Phillips if (!is_power_of_2(priv->num_channels) || !priv->chfifo_len || 33889c4a7965SKim Phillips !priv->exec_units || !priv->desc_types) { 33899c4a7965SKim Phillips dev_err(dev, "invalid property data in device tree node\n"); 33909c4a7965SKim Phillips err = -EINVAL; 33919c4a7965SKim Phillips goto err_out; 33929c4a7965SKim Phillips } 33939c4a7965SKim Phillips 3394f3c85bc1SLee Nipper if (of_device_is_compatible(np, "fsl,sec3.0")) 3395f3c85bc1SLee Nipper priv->features |= TALITOS_FTR_SRC_LINK_TBL_LEN_INCLUDES_EXTENT; 3396f3c85bc1SLee Nipper 3397fe5720e2SKim Phillips if (of_device_is_compatible(np, "fsl,sec2.1")) 339860f208d7SKim Phillips priv->features |= TALITOS_FTR_HW_AUTH_CHECK | 339979b3a418SLee Nipper TALITOS_FTR_SHA224_HWINIT | 340079b3a418SLee Nipper TALITOS_FTR_HMAC_OK; 3401fe5720e2SKim Phillips 340221590888SLEROY Christophe if (of_device_is_compatible(np, "fsl,sec1.0")) 340321590888SLEROY Christophe priv->features |= TALITOS_FTR_SEC1; 340421590888SLEROY Christophe 34055fa7fa14SLEROY Christophe if (of_device_is_compatible(np, "fsl,sec1.2")) { 34065fa7fa14SLEROY Christophe priv->reg_deu = priv->reg + TALITOS12_DEU; 34075fa7fa14SLEROY Christophe priv->reg_aesu = priv->reg + TALITOS12_AESU; 34085fa7fa14SLEROY Christophe priv->reg_mdeu = priv->reg + TALITOS12_MDEU; 34095fa7fa14SLEROY Christophe stride = TALITOS1_CH_STRIDE; 34105fa7fa14SLEROY Christophe } else if (of_device_is_compatible(np, "fsl,sec1.0")) { 34115fa7fa14SLEROY Christophe priv->reg_deu = priv->reg + TALITOS10_DEU; 34125fa7fa14SLEROY Christophe priv->reg_aesu = priv->reg + TALITOS10_AESU; 34135fa7fa14SLEROY Christophe priv->reg_mdeu = priv->reg + TALITOS10_MDEU; 34145fa7fa14SLEROY Christophe priv->reg_afeu = priv->reg + TALITOS10_AFEU; 34155fa7fa14SLEROY Christophe priv->reg_rngu = priv->reg + TALITOS10_RNGU; 34165fa7fa14SLEROY Christophe priv->reg_pkeu = priv->reg + TALITOS10_PKEU; 34175fa7fa14SLEROY Christophe stride = TALITOS1_CH_STRIDE; 34185fa7fa14SLEROY Christophe } else { 34195fa7fa14SLEROY Christophe priv->reg_deu = priv->reg + TALITOS2_DEU; 34205fa7fa14SLEROY Christophe priv->reg_aesu = priv->reg + TALITOS2_AESU; 34215fa7fa14SLEROY Christophe priv->reg_mdeu = priv->reg + TALITOS2_MDEU; 34225fa7fa14SLEROY Christophe priv->reg_afeu = priv->reg + TALITOS2_AFEU; 34235fa7fa14SLEROY Christophe priv->reg_rngu = priv->reg + TALITOS2_RNGU; 34245fa7fa14SLEROY Christophe priv->reg_pkeu = priv->reg + TALITOS2_PKEU; 34255fa7fa14SLEROY Christophe priv->reg_keu = priv->reg + TALITOS2_KEU; 34265fa7fa14SLEROY Christophe priv->reg_crcu = priv->reg + TALITOS2_CRCU; 34275fa7fa14SLEROY Christophe stride = TALITOS2_CH_STRIDE; 34285fa7fa14SLEROY Christophe } 34295fa7fa14SLEROY Christophe 3430dd3c0987SLEROY Christophe err = talitos_probe_irq(ofdev); 3431dd3c0987SLEROY Christophe if (err) 3432dd3c0987SLEROY Christophe goto err_out; 3433dd3c0987SLEROY Christophe 3434dd3c0987SLEROY Christophe if (of_device_is_compatible(np, "fsl,sec1.0")) { 34359c02e285SLEROY Christophe if (priv->num_channels == 1) 34369c02e285SLEROY Christophe tasklet_init(&priv->done_task[0], talitos1_done_ch0, 34379c02e285SLEROY Christophe (unsigned long)dev); 34389c02e285SLEROY Christophe else 3439dd3c0987SLEROY Christophe tasklet_init(&priv->done_task[0], talitos1_done_4ch, 3440dd3c0987SLEROY Christophe (unsigned long)dev); 3441dd3c0987SLEROY Christophe } else { 34429c02e285SLEROY Christophe if (priv->irq[1]) { 3443dd3c0987SLEROY Christophe tasklet_init(&priv->done_task[0], talitos2_done_ch0_2, 3444dd3c0987SLEROY Christophe (unsigned long)dev); 3445dd3c0987SLEROY Christophe tasklet_init(&priv->done_task[1], talitos2_done_ch1_3, 3446dd3c0987SLEROY Christophe (unsigned long)dev); 34479c02e285SLEROY Christophe } else if (priv->num_channels == 1) { 34489c02e285SLEROY Christophe tasklet_init(&priv->done_task[0], talitos2_done_ch0, 34499c02e285SLEROY Christophe (unsigned long)dev); 34509c02e285SLEROY Christophe } else { 34519c02e285SLEROY Christophe tasklet_init(&priv->done_task[0], talitos2_done_4ch, 34529c02e285SLEROY Christophe (unsigned long)dev); 3453dd3c0987SLEROY Christophe } 3454dd3c0987SLEROY Christophe } 3455dd3c0987SLEROY Christophe 3456a86854d0SKees Cook priv->chan = devm_kcalloc(dev, 3457a86854d0SKees Cook priv->num_channels, 3458a86854d0SKees Cook sizeof(struct talitos_channel), 3459a86854d0SKees Cook GFP_KERNEL); 34604b992628SKim Phillips if (!priv->chan) { 34614b992628SKim Phillips dev_err(dev, "failed to allocate channel management space\n"); 34629c4a7965SKim Phillips err = -ENOMEM; 34639c4a7965SKim Phillips goto err_out; 34649c4a7965SKim Phillips } 34659c4a7965SKim Phillips 3466f641ddddSMartin Hicks priv->fifo_len = roundup_pow_of_two(priv->chfifo_len); 3467f641ddddSMartin Hicks 3468c3e337f8SKim Phillips for (i = 0; i < priv->num_channels; i++) { 34695fa7fa14SLEROY Christophe priv->chan[i].reg = priv->reg + stride * (i + 1); 34702cdba3cfSKim Phillips if (!priv->irq[1] || !(i & 1)) 3471c3e337f8SKim Phillips priv->chan[i].reg += TALITOS_CH_BASE_OFFSET; 3472ad42d5fcSKim Phillips 34734b992628SKim Phillips spin_lock_init(&priv->chan[i].head_lock); 34744b992628SKim Phillips spin_lock_init(&priv->chan[i].tail_lock); 34759c4a7965SKim Phillips 3476a86854d0SKees Cook priv->chan[i].fifo = devm_kcalloc(dev, 3477a86854d0SKees Cook priv->fifo_len, 3478a86854d0SKees Cook sizeof(struct talitos_request), 3479a86854d0SKees Cook GFP_KERNEL); 34804b992628SKim Phillips if (!priv->chan[i].fifo) { 34819c4a7965SKim Phillips dev_err(dev, "failed to allocate request fifo %d\n", i); 34829c4a7965SKim Phillips err = -ENOMEM; 34839c4a7965SKim Phillips goto err_out; 34849c4a7965SKim Phillips } 34859c4a7965SKim Phillips 34864b992628SKim Phillips atomic_set(&priv->chan[i].submit_count, 34874b992628SKim Phillips -(priv->chfifo_len - 1)); 3488f641ddddSMartin Hicks } 34899c4a7965SKim Phillips 349081eb024cSKim Phillips dma_set_mask(dev, DMA_BIT_MASK(36)); 349181eb024cSKim Phillips 34929c4a7965SKim Phillips /* reset and initialize the h/w */ 34939c4a7965SKim Phillips err = init_device(dev); 34949c4a7965SKim Phillips if (err) { 34959c4a7965SKim Phillips dev_err(dev, "failed to initialize device\n"); 34969c4a7965SKim Phillips goto err_out; 34979c4a7965SKim Phillips } 34989c4a7965SKim Phillips 34999c4a7965SKim Phillips /* register the RNG, if available */ 35009c4a7965SKim Phillips if (hw_supports(dev, DESC_HDR_SEL0_RNG)) { 35019c4a7965SKim Phillips err = talitos_register_rng(dev); 35029c4a7965SKim Phillips if (err) { 35039c4a7965SKim Phillips dev_err(dev, "failed to register hwrng: %d\n", err); 35049c4a7965SKim Phillips goto err_out; 35059c4a7965SKim Phillips } else 35069c4a7965SKim Phillips dev_info(dev, "hwrng\n"); 35079c4a7965SKim Phillips } 35089c4a7965SKim Phillips 35099c4a7965SKim Phillips /* register crypto algorithms the device supports */ 35109c4a7965SKim Phillips for (i = 0; i < ARRAY_SIZE(driver_algs); i++) { 35119c4a7965SKim Phillips if (hw_supports(dev, driver_algs[i].desc_hdr_template)) { 35129c4a7965SKim Phillips struct talitos_crypto_alg *t_alg; 3513aeb4c132SHerbert Xu struct crypto_alg *alg = NULL; 35149c4a7965SKim Phillips 35159c4a7965SKim Phillips t_alg = talitos_alg_alloc(dev, &driver_algs[i]); 35169c4a7965SKim Phillips if (IS_ERR(t_alg)) { 35179c4a7965SKim Phillips err = PTR_ERR(t_alg); 35180b2730d8SKim Phillips if (err == -ENOTSUPP) 351979b3a418SLee Nipper continue; 35209c4a7965SKim Phillips goto err_out; 35219c4a7965SKim Phillips } 35229c4a7965SKim Phillips 3523acbf7c62SLee Nipper switch (t_alg->algt.type) { 3524acbf7c62SLee Nipper case CRYPTO_ALG_TYPE_ABLKCIPHER: 3525acbf7c62SLee Nipper err = crypto_register_alg( 3526acbf7c62SLee Nipper &t_alg->algt.alg.crypto); 3527aeb4c132SHerbert Xu alg = &t_alg->algt.alg.crypto; 3528acbf7c62SLee Nipper break; 3529aeb4c132SHerbert Xu 3530aeb4c132SHerbert Xu case CRYPTO_ALG_TYPE_AEAD: 3531aeb4c132SHerbert Xu err = crypto_register_aead( 3532aeb4c132SHerbert Xu &t_alg->algt.alg.aead); 3533aeb4c132SHerbert Xu alg = &t_alg->algt.alg.aead.base; 3534aeb4c132SHerbert Xu break; 3535aeb4c132SHerbert Xu 3536acbf7c62SLee Nipper case CRYPTO_ALG_TYPE_AHASH: 3537acbf7c62SLee Nipper err = crypto_register_ahash( 3538acbf7c62SLee Nipper &t_alg->algt.alg.hash); 3539aeb4c132SHerbert Xu alg = &t_alg->algt.alg.hash.halg.base; 3540acbf7c62SLee Nipper break; 3541acbf7c62SLee Nipper } 35429c4a7965SKim Phillips if (err) { 35439c4a7965SKim Phillips dev_err(dev, "%s alg registration failed\n", 3544aeb4c132SHerbert Xu alg->cra_driver_name); 354524b92ff2SLEROY Christophe devm_kfree(dev, t_alg); 3546991155baSHoria Geanta } else 35479c4a7965SKim Phillips list_add_tail(&t_alg->entry, &priv->alg_list); 35489c4a7965SKim Phillips } 35499c4a7965SKim Phillips } 35505b859b6eSKim Phillips if (!list_empty(&priv->alg_list)) 35515b859b6eSKim Phillips dev_info(dev, "%s algorithms registered in /proc/crypto\n", 35525b859b6eSKim Phillips (char *)of_get_property(np, "compatible", NULL)); 35539c4a7965SKim Phillips 35549c4a7965SKim Phillips return 0; 35559c4a7965SKim Phillips 35569c4a7965SKim Phillips err_out: 35579c4a7965SKim Phillips talitos_remove(ofdev); 35589c4a7965SKim Phillips 35599c4a7965SKim Phillips return err; 35609c4a7965SKim Phillips } 35619c4a7965SKim Phillips 35626c3f975aSMárton Németh static const struct of_device_id talitos_match[] = { 35630635b7dbSLEROY Christophe #ifdef CONFIG_CRYPTO_DEV_TALITOS1 35640635b7dbSLEROY Christophe { 35650635b7dbSLEROY Christophe .compatible = "fsl,sec1.0", 35660635b7dbSLEROY Christophe }, 35670635b7dbSLEROY Christophe #endif 35680635b7dbSLEROY Christophe #ifdef CONFIG_CRYPTO_DEV_TALITOS2 35699c4a7965SKim Phillips { 35709c4a7965SKim Phillips .compatible = "fsl,sec2.0", 35719c4a7965SKim Phillips }, 35720635b7dbSLEROY Christophe #endif 35739c4a7965SKim Phillips {}, 35749c4a7965SKim Phillips }; 35759c4a7965SKim Phillips MODULE_DEVICE_TABLE(of, talitos_match); 35769c4a7965SKim Phillips 35771c48a5c9SGrant Likely static struct platform_driver talitos_driver = { 35784018294bSGrant Likely .driver = { 35799c4a7965SKim Phillips .name = "talitos", 35804018294bSGrant Likely .of_match_table = talitos_match, 35814018294bSGrant Likely }, 35829c4a7965SKim Phillips .probe = talitos_probe, 3583596f1034SAl Viro .remove = talitos_remove, 35849c4a7965SKim Phillips }; 35859c4a7965SKim Phillips 3586741e8c2dSAxel Lin module_platform_driver(talitos_driver); 35879c4a7965SKim Phillips 35889c4a7965SKim Phillips MODULE_LICENSE("GPL"); 35899c4a7965SKim Phillips MODULE_AUTHOR("Kim Phillips <kim.phillips@freescale.com>"); 35909c4a7965SKim Phillips MODULE_DESCRIPTION("Freescale integrated security engine (SEC) driver"); 3591