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 9169c4a7965SKim Phillips /* 91756af8cd4SLee Nipper * talitos_edesc - s/w-extended descriptor 9189c4a7965SKim Phillips * @src_nents: number of segments in input scatterlist 9199c4a7965SKim Phillips * @dst_nents: number of segments in output scatterlist 920aeb4c132SHerbert Xu * @icv_ool: whether ICV is out-of-line 92179fd31d3SHoria Geanta * @iv_dma: dma address of iv for checking continuity and link table 9229c4a7965SKim Phillips * @dma_len: length of dma mapped link_tbl space 9236f65f6acSLEROY Christophe * @dma_link_tbl: bus physical address of link_tbl/buf 9249c4a7965SKim Phillips * @desc: h/w descriptor 9256f65f6acSLEROY Christophe * @link_tbl: input and output h/w link tables (if {src,dst}_nents > 1) (SEC2) 9266f65f6acSLEROY Christophe * @buf: input and output buffeur (if {src,dst}_nents > 1) (SEC1) 9279c4a7965SKim Phillips * 9289c4a7965SKim Phillips * if decrypting (with authcheck), or either one of src_nents or dst_nents 9299c4a7965SKim Phillips * is greater than 1, an integrity check value is concatenated to the end 9309c4a7965SKim Phillips * of link_tbl data 9319c4a7965SKim Phillips */ 93256af8cd4SLee Nipper struct talitos_edesc { 9339c4a7965SKim Phillips int src_nents; 9349c4a7965SKim Phillips int dst_nents; 935aeb4c132SHerbert Xu bool icv_ool; 93679fd31d3SHoria Geanta dma_addr_t iv_dma; 9379c4a7965SKim Phillips int dma_len; 9389c4a7965SKim Phillips dma_addr_t dma_link_tbl; 9399c4a7965SKim Phillips struct talitos_desc desc; 9406f65f6acSLEROY Christophe union { 9419c4a7965SKim Phillips struct talitos_ptr link_tbl[0]; 9426f65f6acSLEROY Christophe u8 buf[0]; 9436f65f6acSLEROY Christophe }; 9449c4a7965SKim Phillips }; 9459c4a7965SKim Phillips 9464de9d0b5SLee Nipper static void talitos_sg_unmap(struct device *dev, 9474de9d0b5SLee Nipper struct talitos_edesc *edesc, 9484de9d0b5SLee Nipper struct scatterlist *src, 9496a1e8d14SLEROY Christophe struct scatterlist *dst, 9506a1e8d14SLEROY Christophe unsigned int len, unsigned int offset) 951246a87cdSLEROY Christophe { 952246a87cdSLEROY Christophe struct talitos_private *priv = dev_get_drvdata(dev); 953246a87cdSLEROY Christophe bool is_sec1 = has_ftr_sec1(priv); 9546a1e8d14SLEROY Christophe unsigned int src_nents = edesc->src_nents ? : 1; 9556a1e8d14SLEROY Christophe unsigned int dst_nents = edesc->dst_nents ? : 1; 956246a87cdSLEROY Christophe 9576a1e8d14SLEROY Christophe if (is_sec1 && dst && dst_nents > 1) { 9586a1e8d14SLEROY Christophe dma_sync_single_for_device(dev, edesc->dma_link_tbl + offset, 959246a87cdSLEROY Christophe len, DMA_FROM_DEVICE); 9606a1e8d14SLEROY Christophe sg_pcopy_from_buffer(dst, dst_nents, edesc->buf + offset, len, 9616a1e8d14SLEROY Christophe offset); 962246a87cdSLEROY Christophe } 9636a1e8d14SLEROY Christophe if (src != dst) { 9646a1e8d14SLEROY Christophe if (src_nents == 1 || !is_sec1) 9656a1e8d14SLEROY Christophe dma_unmap_sg(dev, src, src_nents, DMA_TO_DEVICE); 9666a1e8d14SLEROY Christophe 9676a1e8d14SLEROY Christophe if (dst && (dst_nents == 1 || !is_sec1)) 9686a1e8d14SLEROY Christophe dma_unmap_sg(dev, dst, dst_nents, DMA_FROM_DEVICE); 9696a1e8d14SLEROY Christophe } else if (src_nents == 1 || !is_sec1) { 9706a1e8d14SLEROY Christophe dma_unmap_sg(dev, src, src_nents, DMA_BIDIRECTIONAL); 971246a87cdSLEROY Christophe } 972246a87cdSLEROY Christophe } 973246a87cdSLEROY Christophe 9749c4a7965SKim Phillips static void ipsec_esp_unmap(struct device *dev, 97556af8cd4SLee Nipper struct talitos_edesc *edesc, 9769c4a7965SKim Phillips struct aead_request *areq) 9779c4a7965SKim Phillips { 978549bd8bcSLEROY Christophe struct crypto_aead *aead = crypto_aead_reqtfm(areq); 979549bd8bcSLEROY Christophe struct talitos_ctx *ctx = crypto_aead_ctx(aead); 980549bd8bcSLEROY Christophe unsigned int ivsize = crypto_aead_ivsize(aead); 9819a655608SLEROY Christophe bool is_ipsec_esp = edesc->desc.hdr & DESC_HDR_TYPE_IPSEC_ESP; 9829a655608SLEROY Christophe struct talitos_ptr *civ_ptr = &edesc->desc.ptr[is_ipsec_esp ? 2 : 3]; 983549bd8bcSLEROY Christophe 9849a655608SLEROY Christophe if (is_ipsec_esp) 985549bd8bcSLEROY Christophe unmap_single_talitos_ptr(dev, &edesc->desc.ptr[6], 986549bd8bcSLEROY Christophe DMA_FROM_DEVICE); 9879a655608SLEROY Christophe unmap_single_talitos_ptr(dev, civ_ptr, DMA_TO_DEVICE); 9889c4a7965SKim Phillips 9896a1e8d14SLEROY Christophe talitos_sg_unmap(dev, edesc, areq->src, areq->dst, areq->cryptlen, 9906a1e8d14SLEROY Christophe areq->assoclen); 9919c4a7965SKim Phillips 9929c4a7965SKim Phillips if (edesc->dma_len) 9939c4a7965SKim Phillips dma_unmap_single(dev, edesc->dma_link_tbl, edesc->dma_len, 9949c4a7965SKim Phillips DMA_BIDIRECTIONAL); 995549bd8bcSLEROY Christophe 9969a655608SLEROY Christophe if (!is_ipsec_esp) { 997549bd8bcSLEROY Christophe unsigned int dst_nents = edesc->dst_nents ? : 1; 998549bd8bcSLEROY Christophe 999549bd8bcSLEROY Christophe sg_pcopy_to_buffer(areq->dst, dst_nents, ctx->iv, ivsize, 1000549bd8bcSLEROY Christophe areq->assoclen + areq->cryptlen - ivsize); 1001549bd8bcSLEROY Christophe } 10029c4a7965SKim Phillips } 10039c4a7965SKim Phillips 10049c4a7965SKim Phillips /* 10059c4a7965SKim Phillips * ipsec_esp descriptor callbacks 10069c4a7965SKim Phillips */ 10079c4a7965SKim Phillips static void ipsec_esp_encrypt_done(struct device *dev, 10089c4a7965SKim Phillips struct talitos_desc *desc, void *context, 10099c4a7965SKim Phillips int err) 10109c4a7965SKim Phillips { 1011549bd8bcSLEROY Christophe struct talitos_private *priv = dev_get_drvdata(dev); 1012549bd8bcSLEROY Christophe bool is_sec1 = has_ftr_sec1(priv); 10139c4a7965SKim Phillips struct aead_request *areq = context; 10149c4a7965SKim Phillips struct crypto_aead *authenc = crypto_aead_reqtfm(areq); 1015aeb4c132SHerbert Xu unsigned int authsize = crypto_aead_authsize(authenc); 10162e13ce08SLEROY Christophe unsigned int ivsize = crypto_aead_ivsize(authenc); 101719bbbc63SKim Phillips struct talitos_edesc *edesc; 10189c4a7965SKim Phillips struct scatterlist *sg; 10199c4a7965SKim Phillips void *icvdata; 10209c4a7965SKim Phillips 102119bbbc63SKim Phillips edesc = container_of(desc, struct talitos_edesc, desc); 102219bbbc63SKim Phillips 10239c4a7965SKim Phillips ipsec_esp_unmap(dev, edesc, areq); 10249c4a7965SKim Phillips 10259c4a7965SKim Phillips /* copy the generated ICV to dst */ 1026aeb4c132SHerbert Xu if (edesc->icv_ool) { 1027549bd8bcSLEROY Christophe if (is_sec1) 1028549bd8bcSLEROY Christophe icvdata = edesc->buf + areq->assoclen + areq->cryptlen; 1029549bd8bcSLEROY Christophe else 10309c4a7965SKim Phillips icvdata = &edesc->link_tbl[edesc->src_nents + 1031aeb4c132SHerbert Xu edesc->dst_nents + 2]; 10329c4a7965SKim Phillips sg = sg_last(areq->dst, edesc->dst_nents); 1033aeb4c132SHerbert Xu memcpy((char *)sg_virt(sg) + sg->length - authsize, 1034aeb4c132SHerbert Xu icvdata, authsize); 10359c4a7965SKim Phillips } 10369c4a7965SKim Phillips 10372e13ce08SLEROY Christophe dma_unmap_single(dev, edesc->iv_dma, ivsize, DMA_TO_DEVICE); 10382e13ce08SLEROY Christophe 10399c4a7965SKim Phillips kfree(edesc); 10409c4a7965SKim Phillips 10419c4a7965SKim Phillips aead_request_complete(areq, err); 10429c4a7965SKim Phillips } 10439c4a7965SKim Phillips 1044fe5720e2SKim Phillips static void ipsec_esp_decrypt_swauth_done(struct device *dev, 1045e938e465SKim Phillips struct talitos_desc *desc, 1046e938e465SKim Phillips void *context, int err) 10479c4a7965SKim Phillips { 10489c4a7965SKim Phillips struct aead_request *req = context; 10499c4a7965SKim Phillips struct crypto_aead *authenc = crypto_aead_reqtfm(req); 1050aeb4c132SHerbert Xu unsigned int authsize = crypto_aead_authsize(authenc); 105119bbbc63SKim Phillips struct talitos_edesc *edesc; 10529c4a7965SKim Phillips struct scatterlist *sg; 1053aeb4c132SHerbert Xu char *oicv, *icv; 1054549bd8bcSLEROY Christophe struct talitos_private *priv = dev_get_drvdata(dev); 1055549bd8bcSLEROY Christophe bool is_sec1 = has_ftr_sec1(priv); 10569c4a7965SKim Phillips 105719bbbc63SKim Phillips edesc = container_of(desc, struct talitos_edesc, desc); 105819bbbc63SKim Phillips 10599c4a7965SKim Phillips ipsec_esp_unmap(dev, edesc, req); 10609c4a7965SKim Phillips 10619c4a7965SKim Phillips if (!err) { 10629c4a7965SKim Phillips /* auth check */ 10639c4a7965SKim Phillips sg = sg_last(req->dst, edesc->dst_nents ? : 1); 1064aeb4c132SHerbert Xu icv = (char *)sg_virt(sg) + sg->length - authsize; 1065aeb4c132SHerbert Xu 1066aeb4c132SHerbert Xu if (edesc->dma_len) { 1067549bd8bcSLEROY Christophe if (is_sec1) 1068549bd8bcSLEROY Christophe oicv = (char *)&edesc->dma_link_tbl + 1069549bd8bcSLEROY Christophe req->assoclen + req->cryptlen; 1070549bd8bcSLEROY Christophe else 1071549bd8bcSLEROY Christophe oicv = (char *) 1072549bd8bcSLEROY Christophe &edesc->link_tbl[edesc->src_nents + 1073aeb4c132SHerbert Xu edesc->dst_nents + 2]; 1074aeb4c132SHerbert Xu if (edesc->icv_ool) 1075aeb4c132SHerbert Xu icv = oicv + authsize; 1076aeb4c132SHerbert Xu } else 1077aeb4c132SHerbert Xu oicv = (char *)&edesc->link_tbl[0]; 1078aeb4c132SHerbert Xu 107979960943SDavid Gstir err = crypto_memneq(oicv, icv, authsize) ? -EBADMSG : 0; 10809c4a7965SKim Phillips } 10819c4a7965SKim Phillips 10829c4a7965SKim Phillips kfree(edesc); 10839c4a7965SKim Phillips 10849c4a7965SKim Phillips aead_request_complete(req, err); 10859c4a7965SKim Phillips } 10869c4a7965SKim Phillips 1087fe5720e2SKim Phillips static void ipsec_esp_decrypt_hwauth_done(struct device *dev, 1088e938e465SKim Phillips struct talitos_desc *desc, 1089e938e465SKim Phillips void *context, int err) 1090fe5720e2SKim Phillips { 1091fe5720e2SKim Phillips struct aead_request *req = context; 109219bbbc63SKim Phillips struct talitos_edesc *edesc; 109319bbbc63SKim Phillips 109419bbbc63SKim Phillips edesc = container_of(desc, struct talitos_edesc, desc); 1095fe5720e2SKim Phillips 1096fe5720e2SKim Phillips ipsec_esp_unmap(dev, edesc, req); 1097fe5720e2SKim Phillips 1098fe5720e2SKim Phillips /* check ICV auth status */ 1099e938e465SKim Phillips if (!err && ((desc->hdr_lo & DESC_HDR_LO_ICCR1_MASK) != 1100e938e465SKim Phillips DESC_HDR_LO_ICCR1_PASS)) 1101fe5720e2SKim Phillips err = -EBADMSG; 1102fe5720e2SKim Phillips 1103fe5720e2SKim Phillips kfree(edesc); 1104fe5720e2SKim Phillips 1105fe5720e2SKim Phillips aead_request_complete(req, err); 1106fe5720e2SKim Phillips } 1107fe5720e2SKim Phillips 11089c4a7965SKim Phillips /* 11099c4a7965SKim Phillips * convert scatterlist to SEC h/w link table format 11109c4a7965SKim Phillips * stop at cryptlen bytes 11119c4a7965SKim Phillips */ 1112aeb4c132SHerbert Xu static int sg_to_link_tbl_offset(struct scatterlist *sg, int sg_count, 1113aeb4c132SHerbert Xu unsigned int offset, int cryptlen, 1114aeb4c132SHerbert Xu struct talitos_ptr *link_tbl_ptr) 11159c4a7965SKim Phillips { 111670bcaca7SLee Nipper int n_sg = sg_count; 1117aeb4c132SHerbert Xu int count = 0; 111870bcaca7SLee Nipper 1119aeb4c132SHerbert Xu while (cryptlen && sg && n_sg--) { 1120aeb4c132SHerbert Xu unsigned int len = sg_dma_len(sg); 1121aeb4c132SHerbert Xu 1122aeb4c132SHerbert Xu if (offset >= len) { 1123aeb4c132SHerbert Xu offset -= len; 1124aeb4c132SHerbert Xu goto next; 1125aeb4c132SHerbert Xu } 1126aeb4c132SHerbert Xu 1127aeb4c132SHerbert Xu len -= offset; 1128aeb4c132SHerbert Xu 1129aeb4c132SHerbert Xu if (len > cryptlen) 1130aeb4c132SHerbert Xu len = cryptlen; 1131aeb4c132SHerbert Xu 1132aeb4c132SHerbert Xu to_talitos_ptr(link_tbl_ptr + count, 1133da9de146SLEROY Christophe sg_dma_address(sg) + offset, len, 0); 1134b096b544SLEROY Christophe to_talitos_ptr_ext_set(link_tbl_ptr + count, 0, 0); 1135aeb4c132SHerbert Xu count++; 1136aeb4c132SHerbert Xu cryptlen -= len; 1137aeb4c132SHerbert Xu offset = 0; 1138aeb4c132SHerbert Xu 1139aeb4c132SHerbert Xu next: 11405be4d4c9SCristian Stoica sg = sg_next(sg); 11419c4a7965SKim Phillips } 11429c4a7965SKim Phillips 11439c4a7965SKim Phillips /* tag end of link table */ 1144aeb4c132SHerbert Xu if (count > 0) 1145b096b544SLEROY Christophe to_talitos_ptr_ext_set(link_tbl_ptr + count - 1, 1146b096b544SLEROY Christophe DESC_PTR_LNKTBL_RETURN, 0); 114770bcaca7SLee Nipper 1148aeb4c132SHerbert Xu return count; 1149aeb4c132SHerbert Xu } 1150aeb4c132SHerbert Xu 11512b122730SLEROY Christophe static int talitos_sg_map_ext(struct device *dev, struct scatterlist *src, 1152246a87cdSLEROY Christophe unsigned int len, struct talitos_edesc *edesc, 11532b122730SLEROY Christophe struct talitos_ptr *ptr, int sg_count, 11542b122730SLEROY Christophe unsigned int offset, int tbl_off, int elen) 1155246a87cdSLEROY Christophe { 1156246a87cdSLEROY Christophe struct talitos_private *priv = dev_get_drvdata(dev); 1157246a87cdSLEROY Christophe bool is_sec1 = has_ftr_sec1(priv); 1158246a87cdSLEROY Christophe 115987a81dceSLEROY Christophe if (!src) { 116087a81dceSLEROY Christophe to_talitos_ptr(ptr, 0, 0, is_sec1); 116187a81dceSLEROY Christophe return 1; 116287a81dceSLEROY Christophe } 11632b122730SLEROY Christophe to_talitos_ptr_ext_set(ptr, elen, is_sec1); 1164246a87cdSLEROY Christophe if (sg_count == 1) { 1165da9de146SLEROY Christophe to_talitos_ptr(ptr, sg_dma_address(src) + offset, len, is_sec1); 1166246a87cdSLEROY Christophe return sg_count; 1167246a87cdSLEROY Christophe } 1168246a87cdSLEROY Christophe if (is_sec1) { 1169da9de146SLEROY Christophe to_talitos_ptr(ptr, edesc->dma_link_tbl + offset, len, is_sec1); 11706a1e8d14SLEROY Christophe return sg_count; 1171246a87cdSLEROY Christophe } 11722b122730SLEROY Christophe sg_count = sg_to_link_tbl_offset(src, sg_count, offset, len + elen, 11736a1e8d14SLEROY Christophe &edesc->link_tbl[tbl_off]); 1174246a87cdSLEROY Christophe if (sg_count == 1) { 11756a1e8d14SLEROY Christophe /* Only one segment now, so no link tbl needed*/ 11766a1e8d14SLEROY Christophe copy_talitos_ptr(ptr, &edesc->link_tbl[tbl_off], is_sec1); 11776a1e8d14SLEROY Christophe return sg_count; 11786a1e8d14SLEROY Christophe } 1179246a87cdSLEROY Christophe to_talitos_ptr(ptr, edesc->dma_link_tbl + 1180da9de146SLEROY Christophe tbl_off * sizeof(struct talitos_ptr), len, is_sec1); 11816a1e8d14SLEROY Christophe to_talitos_ptr_ext_or(ptr, DESC_PTR_LNKTBL_JUMP, is_sec1); 11826a1e8d14SLEROY Christophe 11836a1e8d14SLEROY Christophe return sg_count; 1184246a87cdSLEROY Christophe } 1185246a87cdSLEROY Christophe 11862b122730SLEROY Christophe static int talitos_sg_map(struct device *dev, struct scatterlist *src, 11872b122730SLEROY Christophe unsigned int len, struct talitos_edesc *edesc, 11882b122730SLEROY Christophe struct talitos_ptr *ptr, int sg_count, 11892b122730SLEROY Christophe unsigned int offset, int tbl_off) 11902b122730SLEROY Christophe { 11912b122730SLEROY Christophe return talitos_sg_map_ext(dev, src, len, edesc, ptr, sg_count, offset, 11922b122730SLEROY Christophe tbl_off, 0); 11932b122730SLEROY Christophe } 11942b122730SLEROY Christophe 11959c4a7965SKim Phillips /* 11969c4a7965SKim Phillips * fill in and submit ipsec_esp descriptor 11979c4a7965SKim Phillips */ 119856af8cd4SLee Nipper static int ipsec_esp(struct talitos_edesc *edesc, struct aead_request *areq, 1199aeb4c132SHerbert Xu void (*callback)(struct device *dev, 12009c4a7965SKim Phillips struct talitos_desc *desc, 12019c4a7965SKim Phillips void *context, int error)) 12029c4a7965SKim Phillips { 12039c4a7965SKim Phillips struct crypto_aead *aead = crypto_aead_reqtfm(areq); 1204aeb4c132SHerbert Xu unsigned int authsize = crypto_aead_authsize(aead); 12059c4a7965SKim Phillips struct talitos_ctx *ctx = crypto_aead_ctx(aead); 12069c4a7965SKim Phillips struct device *dev = ctx->dev; 12079c4a7965SKim Phillips struct talitos_desc *desc = &edesc->desc; 12089c4a7965SKim Phillips unsigned int cryptlen = areq->cryptlen; 1209e41256f1SKim Phillips unsigned int ivsize = crypto_aead_ivsize(aead); 1210aeb4c132SHerbert Xu int tbl_off = 0; 1211fa86a267SKim Phillips int sg_count, ret; 12122b122730SLEROY Christophe int elen = 0; 1213549bd8bcSLEROY Christophe bool sync_needed = false; 1214549bd8bcSLEROY Christophe struct talitos_private *priv = dev_get_drvdata(dev); 1215549bd8bcSLEROY Christophe bool is_sec1 = has_ftr_sec1(priv); 12169a655608SLEROY Christophe bool is_ipsec_esp = desc->hdr & DESC_HDR_TYPE_IPSEC_ESP; 12179a655608SLEROY Christophe struct talitos_ptr *civ_ptr = &desc->ptr[is_ipsec_esp ? 2 : 3]; 12189a655608SLEROY Christophe struct talitos_ptr *ckey_ptr = &desc->ptr[is_ipsec_esp ? 3 : 2]; 12199c4a7965SKim Phillips 12209c4a7965SKim Phillips /* hmac key */ 12212e13ce08SLEROY Christophe to_talitos_ptr(&desc->ptr[0], ctx->dma_key, ctx->authkeylen, is_sec1); 122279fd31d3SHoria Geanta 1223549bd8bcSLEROY Christophe sg_count = edesc->src_nents ?: 1; 1224549bd8bcSLEROY Christophe if (is_sec1 && sg_count > 1) 1225549bd8bcSLEROY Christophe sg_copy_to_buffer(areq->src, sg_count, edesc->buf, 1226549bd8bcSLEROY Christophe areq->assoclen + cryptlen); 1227549bd8bcSLEROY Christophe else 1228549bd8bcSLEROY Christophe sg_count = dma_map_sg(dev, areq->src, sg_count, 1229549bd8bcSLEROY Christophe (areq->src == areq->dst) ? 1230549bd8bcSLEROY Christophe DMA_BIDIRECTIONAL : DMA_TO_DEVICE); 1231549bd8bcSLEROY Christophe 12329c4a7965SKim Phillips /* hmac data */ 1233549bd8bcSLEROY Christophe ret = talitos_sg_map(dev, areq->src, areq->assoclen, edesc, 1234549bd8bcSLEROY Christophe &desc->ptr[1], sg_count, 0, tbl_off); 123579fd31d3SHoria Geanta 1236549bd8bcSLEROY Christophe if (ret > 1) { 1237340ff60aSHoria Geant? tbl_off += ret; 1238549bd8bcSLEROY Christophe sync_needed = true; 123979fd31d3SHoria Geanta } 124079fd31d3SHoria Geanta 12419c4a7965SKim Phillips /* cipher iv */ 12429a655608SLEROY Christophe to_talitos_ptr(civ_ptr, edesc->iv_dma, ivsize, is_sec1); 12439c4a7965SKim Phillips 12449c4a7965SKim Phillips /* cipher key */ 12452e13ce08SLEROY Christophe to_talitos_ptr(ckey_ptr, ctx->dma_key + ctx->authkeylen, 12462e13ce08SLEROY Christophe ctx->enckeylen, is_sec1); 12479c4a7965SKim Phillips 12489c4a7965SKim Phillips /* 12499c4a7965SKim Phillips * cipher in 12509c4a7965SKim Phillips * map and adjust cipher len to aead request cryptlen. 12519c4a7965SKim Phillips * extent is bytes of HMAC postpended to ciphertext, 12529c4a7965SKim Phillips * typically 12 for ipsec 12539c4a7965SKim Phillips */ 12542b122730SLEROY Christophe if (is_ipsec_esp && (desc->hdr & DESC_HDR_MODE1_MDEU_CICV)) 12552b122730SLEROY Christophe elen = authsize; 1256549bd8bcSLEROY Christophe 12572b122730SLEROY Christophe ret = talitos_sg_map_ext(dev, areq->src, cryptlen, edesc, &desc->ptr[4], 12582b122730SLEROY Christophe sg_count, areq->assoclen, tbl_off, elen); 1259549bd8bcSLEROY Christophe 1260ec8c7d14SLEROY Christophe if (ret > 1) { 1261ec8c7d14SLEROY Christophe tbl_off += ret; 1262549bd8bcSLEROY Christophe sync_needed = true; 1263340ff60aSHoria Geant? } 12649c4a7965SKim Phillips 12659c4a7965SKim Phillips /* cipher out */ 1266549bd8bcSLEROY Christophe if (areq->src != areq->dst) { 1267549bd8bcSLEROY Christophe sg_count = edesc->dst_nents ? : 1; 1268549bd8bcSLEROY Christophe if (!is_sec1 || sg_count == 1) 1269549bd8bcSLEROY Christophe dma_map_sg(dev, areq->dst, sg_count, DMA_FROM_DEVICE); 1270549bd8bcSLEROY Christophe } 12719c4a7965SKim Phillips 1272e04a61beSLEROY Christophe ret = talitos_sg_map(dev, areq->dst, cryptlen, edesc, &desc->ptr[5], 1273e04a61beSLEROY Christophe sg_count, areq->assoclen, tbl_off); 12749c4a7965SKim Phillips 12759a655608SLEROY Christophe if (is_ipsec_esp) 1276549bd8bcSLEROY Christophe to_talitos_ptr_ext_or(&desc->ptr[5], authsize, is_sec1); 1277aeb4c132SHerbert Xu 1278e04a61beSLEROY Christophe /* ICV data */ 1279e04a61beSLEROY Christophe if (ret > 1) { 1280e04a61beSLEROY Christophe tbl_off += ret; 1281549bd8bcSLEROY Christophe edesc->icv_ool = true; 1282549bd8bcSLEROY Christophe sync_needed = true; 1283549bd8bcSLEROY Christophe 12849a655608SLEROY Christophe if (is_ipsec_esp) { 128579fd31d3SHoria Geanta struct talitos_ptr *tbl_ptr = &edesc->link_tbl[tbl_off]; 1286549bd8bcSLEROY Christophe int offset = (edesc->src_nents + edesc->dst_nents + 2) * 1287549bd8bcSLEROY Christophe sizeof(struct talitos_ptr) + authsize; 1288fe5720e2SKim Phillips 1289f3c85bc1SLee Nipper /* Add an entry to the link table for ICV data */ 1290e04a61beSLEROY Christophe to_talitos_ptr_ext_set(tbl_ptr - 1, 0, is_sec1); 1291549bd8bcSLEROY Christophe to_talitos_ptr_ext_set(tbl_ptr, DESC_PTR_LNKTBL_RETURN, 1292549bd8bcSLEROY Christophe is_sec1); 12939c4a7965SKim Phillips 12949c4a7965SKim Phillips /* icv data follows link tables */ 1295549bd8bcSLEROY Christophe to_talitos_ptr(tbl_ptr, edesc->dma_link_tbl + offset, 1296da9de146SLEROY Christophe authsize, is_sec1); 1297e04a61beSLEROY Christophe } else { 1298e04a61beSLEROY Christophe dma_addr_t addr = edesc->dma_link_tbl; 1299e04a61beSLEROY Christophe 1300e04a61beSLEROY Christophe if (is_sec1) 1301e04a61beSLEROY Christophe addr += areq->assoclen + cryptlen; 1302e04a61beSLEROY Christophe else 1303e04a61beSLEROY Christophe addr += sizeof(struct talitos_ptr) * tbl_off; 1304e04a61beSLEROY Christophe 1305da9de146SLEROY Christophe to_talitos_ptr(&desc->ptr[6], addr, authsize, is_sec1); 1306549bd8bcSLEROY Christophe } 13079a655608SLEROY Christophe } else if (!is_ipsec_esp) { 1308e04a61beSLEROY Christophe ret = talitos_sg_map(dev, areq->dst, authsize, edesc, 1309e04a61beSLEROY Christophe &desc->ptr[6], sg_count, areq->assoclen + 1310e04a61beSLEROY Christophe cryptlen, 1311e04a61beSLEROY Christophe tbl_off); 1312e04a61beSLEROY Christophe if (ret > 1) { 1313e04a61beSLEROY Christophe tbl_off += ret; 1314e04a61beSLEROY Christophe edesc->icv_ool = true; 1315e04a61beSLEROY Christophe sync_needed = true; 1316340ff60aSHoria Geant? } else { 1317549bd8bcSLEROY Christophe edesc->icv_ool = false; 1318549bd8bcSLEROY Christophe } 1319e04a61beSLEROY Christophe } else { 1320e04a61beSLEROY Christophe edesc->icv_ool = false; 1321340ff60aSHoria Geant? } 13229c4a7965SKim Phillips 13239c4a7965SKim Phillips /* iv out */ 13249a655608SLEROY Christophe if (is_ipsec_esp) 1325a2b35aa8SLEROY Christophe map_single_talitos_ptr(dev, &desc->ptr[6], ivsize, ctx->iv, 13269c4a7965SKim Phillips DMA_FROM_DEVICE); 13279c4a7965SKim Phillips 1328549bd8bcSLEROY Christophe if (sync_needed) 1329549bd8bcSLEROY Christophe dma_sync_single_for_device(dev, edesc->dma_link_tbl, 1330549bd8bcSLEROY Christophe edesc->dma_len, 1331549bd8bcSLEROY Christophe DMA_BIDIRECTIONAL); 1332549bd8bcSLEROY Christophe 13335228f0f7SKim Phillips ret = talitos_submit(dev, ctx->ch, desc, callback, areq); 1334fa86a267SKim Phillips if (ret != -EINPROGRESS) { 1335fa86a267SKim Phillips ipsec_esp_unmap(dev, edesc, areq); 1336fa86a267SKim Phillips kfree(edesc); 1337fa86a267SKim Phillips } 1338fa86a267SKim Phillips return ret; 13399c4a7965SKim Phillips } 13409c4a7965SKim Phillips 13419c4a7965SKim Phillips /* 134256af8cd4SLee Nipper * allocate and map the extended descriptor 13439c4a7965SKim Phillips */ 13444de9d0b5SLee Nipper static struct talitos_edesc *talitos_edesc_alloc(struct device *dev, 13454de9d0b5SLee Nipper struct scatterlist *src, 13464de9d0b5SLee Nipper struct scatterlist *dst, 134779fd31d3SHoria Geanta u8 *iv, 134879fd31d3SHoria Geanta unsigned int assoclen, 13494de9d0b5SLee Nipper unsigned int cryptlen, 13504de9d0b5SLee Nipper unsigned int authsize, 135179fd31d3SHoria Geanta unsigned int ivsize, 13524de9d0b5SLee Nipper int icv_stashing, 135362293a37SHoria Geanta u32 cryptoflags, 135462293a37SHoria Geanta bool encrypt) 13559c4a7965SKim Phillips { 135656af8cd4SLee Nipper struct talitos_edesc *edesc; 13576a1e8d14SLEROY Christophe int src_nents, dst_nents, alloc_len, dma_len, src_len, dst_len; 135879fd31d3SHoria Geanta dma_addr_t iv_dma = 0; 13594de9d0b5SLee Nipper gfp_t flags = cryptoflags & CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL : 1360586725f8SKim Phillips GFP_ATOMIC; 13616f65f6acSLEROY Christophe struct talitos_private *priv = dev_get_drvdata(dev); 13626f65f6acSLEROY Christophe bool is_sec1 = has_ftr_sec1(priv); 13636f65f6acSLEROY Christophe int max_len = is_sec1 ? TALITOS1_MAX_DATA_LEN : TALITOS2_MAX_DATA_LEN; 13649c4a7965SKim Phillips 13656f65f6acSLEROY Christophe if (cryptlen + authsize > max_len) { 13664de9d0b5SLee Nipper dev_err(dev, "length exceeds h/w max limit\n"); 13679c4a7965SKim Phillips return ERR_PTR(-EINVAL); 13689c4a7965SKim Phillips } 13699c4a7965SKim Phillips 137062293a37SHoria Geanta if (!dst || dst == src) { 13716a1e8d14SLEROY Christophe src_len = assoclen + cryptlen + authsize; 13726a1e8d14SLEROY Christophe src_nents = sg_nents_for_len(src, src_len); 13738e409fe1SLABBE Corentin if (src_nents < 0) { 13748e409fe1SLABBE Corentin dev_err(dev, "Invalid number of src SG.\n"); 1375c56c2e17SChristophe Leroy return ERR_PTR(-EINVAL); 13768e409fe1SLABBE Corentin } 13779c4a7965SKim Phillips src_nents = (src_nents == 1) ? 0 : src_nents; 137862293a37SHoria Geanta dst_nents = dst ? src_nents : 0; 13796a1e8d14SLEROY Christophe dst_len = 0; 138062293a37SHoria Geanta } else { /* dst && dst != src*/ 13816a1e8d14SLEROY Christophe src_len = assoclen + cryptlen + (encrypt ? 0 : authsize); 13826a1e8d14SLEROY Christophe src_nents = sg_nents_for_len(src, src_len); 13838e409fe1SLABBE Corentin if (src_nents < 0) { 13848e409fe1SLABBE Corentin dev_err(dev, "Invalid number of src SG.\n"); 1385c56c2e17SChristophe Leroy return ERR_PTR(-EINVAL); 13868e409fe1SLABBE Corentin } 138762293a37SHoria Geanta src_nents = (src_nents == 1) ? 0 : src_nents; 13886a1e8d14SLEROY Christophe dst_len = assoclen + cryptlen + (encrypt ? authsize : 0); 13896a1e8d14SLEROY Christophe dst_nents = sg_nents_for_len(dst, dst_len); 13908e409fe1SLABBE Corentin if (dst_nents < 0) { 13918e409fe1SLABBE Corentin dev_err(dev, "Invalid number of dst SG.\n"); 1392c56c2e17SChristophe Leroy return ERR_PTR(-EINVAL); 13938e409fe1SLABBE Corentin } 1394695ad589SLee Nipper dst_nents = (dst_nents == 1) ? 0 : dst_nents; 13959c4a7965SKim Phillips } 13969c4a7965SKim Phillips 13979c4a7965SKim Phillips /* 13989c4a7965SKim Phillips * allocate space for base edesc plus the link tables, 1399aeb4c132SHerbert Xu * allowing for two separate entries for AD and generated ICV (+ 2), 1400aeb4c132SHerbert Xu * and space for two sets of ICVs (stashed and generated) 14019c4a7965SKim Phillips */ 140256af8cd4SLee Nipper alloc_len = sizeof(struct talitos_edesc); 1403aeb4c132SHerbert Xu if (src_nents || dst_nents) { 14046f65f6acSLEROY Christophe if (is_sec1) 14056a1e8d14SLEROY Christophe dma_len = (src_nents ? src_len : 0) + 14066a1e8d14SLEROY Christophe (dst_nents ? dst_len : 0); 14076f65f6acSLEROY Christophe else 1408aeb4c132SHerbert Xu dma_len = (src_nents + dst_nents + 2) * 1409aeb4c132SHerbert Xu sizeof(struct talitos_ptr) + authsize * 2; 14109c4a7965SKim Phillips alloc_len += dma_len; 14119c4a7965SKim Phillips } else { 14129c4a7965SKim Phillips dma_len = 0; 14134de9d0b5SLee Nipper alloc_len += icv_stashing ? authsize : 0; 14149c4a7965SKim Phillips } 14159c4a7965SKim Phillips 141637b5e889SLEROY Christophe /* if its a ahash, add space for a second desc next to the first one */ 141737b5e889SLEROY Christophe if (is_sec1 && !dst) 141837b5e889SLEROY Christophe alloc_len += sizeof(struct talitos_desc); 1419*1bea445bSChristophe Leroy alloc_len += ivsize; 142037b5e889SLEROY Christophe 1421586725f8SKim Phillips edesc = kmalloc(alloc_len, GFP_DMA | flags); 1422c56c2e17SChristophe Leroy if (!edesc) 1423c56c2e17SChristophe Leroy return ERR_PTR(-ENOMEM); 1424*1bea445bSChristophe Leroy if (ivsize) { 1425*1bea445bSChristophe Leroy iv = memcpy(((u8 *)edesc) + alloc_len - ivsize, iv, ivsize); 1426c56c2e17SChristophe Leroy iv_dma = dma_map_single(dev, iv, ivsize, DMA_TO_DEVICE); 1427*1bea445bSChristophe Leroy } 1428e4a647c4SLEROY Christophe memset(&edesc->desc, 0, sizeof(edesc->desc)); 14299c4a7965SKim Phillips 14309c4a7965SKim Phillips edesc->src_nents = src_nents; 14319c4a7965SKim Phillips edesc->dst_nents = dst_nents; 143279fd31d3SHoria Geanta edesc->iv_dma = iv_dma; 14339c4a7965SKim Phillips edesc->dma_len = dma_len; 143437b5e889SLEROY Christophe if (dma_len) { 143537b5e889SLEROY Christophe void *addr = &edesc->link_tbl[0]; 143637b5e889SLEROY Christophe 143737b5e889SLEROY Christophe if (is_sec1 && !dst) 143837b5e889SLEROY Christophe addr += sizeof(struct talitos_desc); 143937b5e889SLEROY Christophe edesc->dma_link_tbl = dma_map_single(dev, addr, 1440497f2e6bSLee Nipper edesc->dma_len, 1441497f2e6bSLee Nipper DMA_BIDIRECTIONAL); 144237b5e889SLEROY Christophe } 14439c4a7965SKim Phillips return edesc; 14449c4a7965SKim Phillips } 14459c4a7965SKim Phillips 144679fd31d3SHoria Geanta static struct talitos_edesc *aead_edesc_alloc(struct aead_request *areq, u8 *iv, 144762293a37SHoria Geanta int icv_stashing, bool encrypt) 14484de9d0b5SLee Nipper { 14494de9d0b5SLee Nipper struct crypto_aead *authenc = crypto_aead_reqtfm(areq); 1450aeb4c132SHerbert Xu unsigned int authsize = crypto_aead_authsize(authenc); 14514de9d0b5SLee Nipper struct talitos_ctx *ctx = crypto_aead_ctx(authenc); 145279fd31d3SHoria Geanta unsigned int ivsize = crypto_aead_ivsize(authenc); 14534de9d0b5SLee Nipper 1454aeb4c132SHerbert Xu return talitos_edesc_alloc(ctx->dev, areq->src, areq->dst, 145579fd31d3SHoria Geanta iv, areq->assoclen, areq->cryptlen, 1456aeb4c132SHerbert Xu authsize, ivsize, icv_stashing, 145762293a37SHoria Geanta areq->base.flags, encrypt); 14584de9d0b5SLee Nipper } 14594de9d0b5SLee Nipper 146056af8cd4SLee Nipper static int aead_encrypt(struct aead_request *req) 14619c4a7965SKim Phillips { 14629c4a7965SKim Phillips struct crypto_aead *authenc = crypto_aead_reqtfm(req); 14639c4a7965SKim Phillips struct talitos_ctx *ctx = crypto_aead_ctx(authenc); 146456af8cd4SLee Nipper struct talitos_edesc *edesc; 14659c4a7965SKim Phillips 14669c4a7965SKim Phillips /* allocate extended descriptor */ 146762293a37SHoria Geanta edesc = aead_edesc_alloc(req, req->iv, 0, true); 14689c4a7965SKim Phillips if (IS_ERR(edesc)) 14699c4a7965SKim Phillips return PTR_ERR(edesc); 14709c4a7965SKim Phillips 14719c4a7965SKim Phillips /* set encrypt */ 147270bcaca7SLee Nipper edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_MODE0_ENCRYPT; 14739c4a7965SKim Phillips 1474aeb4c132SHerbert Xu return ipsec_esp(edesc, req, ipsec_esp_encrypt_done); 14759c4a7965SKim Phillips } 14769c4a7965SKim Phillips 147756af8cd4SLee Nipper static int aead_decrypt(struct aead_request *req) 14789c4a7965SKim Phillips { 14799c4a7965SKim Phillips struct crypto_aead *authenc = crypto_aead_reqtfm(req); 1480aeb4c132SHerbert Xu unsigned int authsize = crypto_aead_authsize(authenc); 14819c4a7965SKim Phillips struct talitos_ctx *ctx = crypto_aead_ctx(authenc); 1482fe5720e2SKim Phillips struct talitos_private *priv = dev_get_drvdata(ctx->dev); 148356af8cd4SLee Nipper struct talitos_edesc *edesc; 14849c4a7965SKim Phillips struct scatterlist *sg; 14859c4a7965SKim Phillips void *icvdata; 14869c4a7965SKim Phillips 14879c4a7965SKim Phillips req->cryptlen -= authsize; 14889c4a7965SKim Phillips 14899c4a7965SKim Phillips /* allocate extended descriptor */ 149062293a37SHoria Geanta edesc = aead_edesc_alloc(req, req->iv, 1, false); 14919c4a7965SKim Phillips if (IS_ERR(edesc)) 14929c4a7965SKim Phillips return PTR_ERR(edesc); 14939c4a7965SKim Phillips 1494fe5720e2SKim Phillips if ((priv->features & TALITOS_FTR_HW_AUTH_CHECK) && 1495e938e465SKim Phillips ((!edesc->src_nents && !edesc->dst_nents) || 1496e938e465SKim Phillips priv->features & TALITOS_FTR_SRC_LINK_TBL_LEN_INCLUDES_EXTENT)) { 1497fe5720e2SKim Phillips 1498fe5720e2SKim Phillips /* decrypt and check the ICV */ 1499e938e465SKim Phillips edesc->desc.hdr = ctx->desc_hdr_template | 1500e938e465SKim Phillips DESC_HDR_DIR_INBOUND | 1501fe5720e2SKim Phillips DESC_HDR_MODE1_MDEU_CICV; 1502fe5720e2SKim Phillips 1503fe5720e2SKim Phillips /* reset integrity check result bits */ 1504fe5720e2SKim Phillips 1505aeb4c132SHerbert Xu return ipsec_esp(edesc, req, ipsec_esp_decrypt_hwauth_done); 1506e938e465SKim Phillips } 1507fe5720e2SKim Phillips 1508fe5720e2SKim Phillips /* Have to check the ICV with software */ 1509fe5720e2SKim Phillips edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_DIR_INBOUND; 1510fe5720e2SKim Phillips 15119c4a7965SKim Phillips /* stash incoming ICV for later cmp with ICV generated by the h/w */ 15129c4a7965SKim Phillips if (edesc->dma_len) 1513aeb4c132SHerbert Xu icvdata = (char *)&edesc->link_tbl[edesc->src_nents + 1514aeb4c132SHerbert Xu edesc->dst_nents + 2]; 15159c4a7965SKim Phillips else 15169c4a7965SKim Phillips icvdata = &edesc->link_tbl[0]; 15179c4a7965SKim Phillips 15189c4a7965SKim Phillips sg = sg_last(req->src, edesc->src_nents ? : 1); 15199c4a7965SKim Phillips 1520aeb4c132SHerbert Xu memcpy(icvdata, (char *)sg_virt(sg) + sg->length - authsize, authsize); 15219c4a7965SKim Phillips 1522aeb4c132SHerbert Xu return ipsec_esp(edesc, req, ipsec_esp_decrypt_swauth_done); 15239c4a7965SKim Phillips } 15249c4a7965SKim Phillips 15254de9d0b5SLee Nipper static int ablkcipher_setkey(struct crypto_ablkcipher *cipher, 15264de9d0b5SLee Nipper const u8 *key, unsigned int keylen) 15274de9d0b5SLee Nipper { 15284de9d0b5SLee Nipper struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher); 15292e13ce08SLEROY Christophe struct device *dev = ctx->dev; 1530f384cdc4SLEROY Christophe u32 tmp[DES_EXPKEY_WORDS]; 15314de9d0b5SLee Nipper 153203d2c511SMartin Hicks if (keylen > TALITOS_MAX_KEY_SIZE) { 153303d2c511SMartin Hicks crypto_ablkcipher_set_flags(cipher, CRYPTO_TFM_RES_BAD_KEY_LEN); 153403d2c511SMartin Hicks return -EINVAL; 153503d2c511SMartin Hicks } 153603d2c511SMartin Hicks 1537f384cdc4SLEROY Christophe if (unlikely(crypto_ablkcipher_get_flags(cipher) & 1538f384cdc4SLEROY Christophe CRYPTO_TFM_REQ_WEAK_KEY) && 1539f384cdc4SLEROY Christophe !des_ekey(tmp, key)) { 1540f384cdc4SLEROY Christophe crypto_ablkcipher_set_flags(cipher, CRYPTO_TFM_RES_WEAK_KEY); 1541f384cdc4SLEROY Christophe return -EINVAL; 1542f384cdc4SLEROY Christophe } 1543f384cdc4SLEROY Christophe 15442e13ce08SLEROY Christophe if (ctx->keylen) 15452e13ce08SLEROY Christophe dma_unmap_single(dev, ctx->dma_key, ctx->keylen, DMA_TO_DEVICE); 15462e13ce08SLEROY Christophe 15474de9d0b5SLee Nipper memcpy(&ctx->key, key, keylen); 15484de9d0b5SLee Nipper ctx->keylen = keylen; 15494de9d0b5SLee Nipper 15502e13ce08SLEROY Christophe ctx->dma_key = dma_map_single(dev, ctx->key, keylen, DMA_TO_DEVICE); 15512e13ce08SLEROY Christophe 15524de9d0b5SLee Nipper return 0; 15534de9d0b5SLee Nipper } 15544de9d0b5SLee Nipper 15554de9d0b5SLee Nipper static void common_nonsnoop_unmap(struct device *dev, 15564de9d0b5SLee Nipper struct talitos_edesc *edesc, 15574de9d0b5SLee Nipper struct ablkcipher_request *areq) 15584de9d0b5SLee Nipper { 15594de9d0b5SLee Nipper unmap_single_talitos_ptr(dev, &edesc->desc.ptr[5], DMA_FROM_DEVICE); 1560032d197eSLEROY Christophe 15616a1e8d14SLEROY Christophe talitos_sg_unmap(dev, edesc, areq->src, areq->dst, areq->nbytes, 0); 15624de9d0b5SLee Nipper unmap_single_talitos_ptr(dev, &edesc->desc.ptr[1], DMA_TO_DEVICE); 15634de9d0b5SLee Nipper 15644de9d0b5SLee Nipper if (edesc->dma_len) 15654de9d0b5SLee Nipper dma_unmap_single(dev, edesc->dma_link_tbl, edesc->dma_len, 15664de9d0b5SLee Nipper DMA_BIDIRECTIONAL); 15674de9d0b5SLee Nipper } 15684de9d0b5SLee Nipper 15694de9d0b5SLee Nipper static void ablkcipher_done(struct device *dev, 15704de9d0b5SLee Nipper struct talitos_desc *desc, void *context, 15714de9d0b5SLee Nipper int err) 15724de9d0b5SLee Nipper { 15734de9d0b5SLee Nipper struct ablkcipher_request *areq = context; 157419bbbc63SKim Phillips struct talitos_edesc *edesc; 157519bbbc63SKim Phillips 157619bbbc63SKim Phillips edesc = container_of(desc, struct talitos_edesc, desc); 15774de9d0b5SLee Nipper 15784de9d0b5SLee Nipper common_nonsnoop_unmap(dev, edesc, areq); 15794de9d0b5SLee Nipper 15804de9d0b5SLee Nipper kfree(edesc); 15814de9d0b5SLee Nipper 15824de9d0b5SLee Nipper areq->base.complete(&areq->base, err); 15834de9d0b5SLee Nipper } 15844de9d0b5SLee Nipper 15854de9d0b5SLee Nipper static int common_nonsnoop(struct talitos_edesc *edesc, 15864de9d0b5SLee Nipper struct ablkcipher_request *areq, 15874de9d0b5SLee Nipper void (*callback) (struct device *dev, 15884de9d0b5SLee Nipper struct talitos_desc *desc, 15894de9d0b5SLee Nipper void *context, int error)) 15904de9d0b5SLee Nipper { 15914de9d0b5SLee Nipper struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(areq); 15924de9d0b5SLee Nipper struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher); 15934de9d0b5SLee Nipper struct device *dev = ctx->dev; 15944de9d0b5SLee Nipper struct talitos_desc *desc = &edesc->desc; 15954de9d0b5SLee Nipper unsigned int cryptlen = areq->nbytes; 159679fd31d3SHoria Geanta unsigned int ivsize = crypto_ablkcipher_ivsize(cipher); 15974de9d0b5SLee Nipper int sg_count, ret; 15986a1e8d14SLEROY Christophe bool sync_needed = false; 1599922f9dc8SLEROY Christophe struct talitos_private *priv = dev_get_drvdata(dev); 1600922f9dc8SLEROY Christophe bool is_sec1 = has_ftr_sec1(priv); 16014de9d0b5SLee Nipper 16024de9d0b5SLee Nipper /* first DWORD empty */ 16034de9d0b5SLee Nipper 16044de9d0b5SLee Nipper /* cipher iv */ 1605da9de146SLEROY Christophe to_talitos_ptr(&desc->ptr[1], edesc->iv_dma, ivsize, is_sec1); 16064de9d0b5SLee Nipper 16074de9d0b5SLee Nipper /* cipher key */ 16082e13ce08SLEROY Christophe to_talitos_ptr(&desc->ptr[2], ctx->dma_key, ctx->keylen, is_sec1); 16094de9d0b5SLee Nipper 16106a1e8d14SLEROY Christophe sg_count = edesc->src_nents ?: 1; 16116a1e8d14SLEROY Christophe if (is_sec1 && sg_count > 1) 16126a1e8d14SLEROY Christophe sg_copy_to_buffer(areq->src, sg_count, edesc->buf, 16136a1e8d14SLEROY Christophe cryptlen); 16146a1e8d14SLEROY Christophe else 16156a1e8d14SLEROY Christophe sg_count = dma_map_sg(dev, areq->src, sg_count, 16166a1e8d14SLEROY Christophe (areq->src == areq->dst) ? 16176a1e8d14SLEROY Christophe DMA_BIDIRECTIONAL : DMA_TO_DEVICE); 16184de9d0b5SLee Nipper /* 16194de9d0b5SLee Nipper * cipher in 16204de9d0b5SLee Nipper */ 16216a1e8d14SLEROY Christophe sg_count = talitos_sg_map(dev, areq->src, cryptlen, edesc, 16226a1e8d14SLEROY Christophe &desc->ptr[3], sg_count, 0, 0); 16236a1e8d14SLEROY Christophe if (sg_count > 1) 16246a1e8d14SLEROY Christophe sync_needed = true; 16254de9d0b5SLee Nipper 16264de9d0b5SLee Nipper /* cipher out */ 16276a1e8d14SLEROY Christophe if (areq->src != areq->dst) { 16286a1e8d14SLEROY Christophe sg_count = edesc->dst_nents ? : 1; 16296a1e8d14SLEROY Christophe if (!is_sec1 || sg_count == 1) 16306a1e8d14SLEROY Christophe dma_map_sg(dev, areq->dst, sg_count, DMA_FROM_DEVICE); 16316a1e8d14SLEROY Christophe } 16326a1e8d14SLEROY Christophe 16336a1e8d14SLEROY Christophe ret = talitos_sg_map(dev, areq->dst, cryptlen, edesc, &desc->ptr[4], 16346a1e8d14SLEROY Christophe sg_count, 0, (edesc->src_nents + 1)); 16356a1e8d14SLEROY Christophe if (ret > 1) 16366a1e8d14SLEROY Christophe sync_needed = true; 16374de9d0b5SLee Nipper 16384de9d0b5SLee Nipper /* iv out */ 1639a2b35aa8SLEROY Christophe map_single_talitos_ptr(dev, &desc->ptr[5], ivsize, ctx->iv, 16404de9d0b5SLee Nipper DMA_FROM_DEVICE); 16414de9d0b5SLee Nipper 16424de9d0b5SLee Nipper /* last DWORD empty */ 16434de9d0b5SLee Nipper 16446a1e8d14SLEROY Christophe if (sync_needed) 16456a1e8d14SLEROY Christophe dma_sync_single_for_device(dev, edesc->dma_link_tbl, 16466a1e8d14SLEROY Christophe edesc->dma_len, DMA_BIDIRECTIONAL); 16476a1e8d14SLEROY Christophe 16485228f0f7SKim Phillips ret = talitos_submit(dev, ctx->ch, desc, callback, areq); 16494de9d0b5SLee Nipper if (ret != -EINPROGRESS) { 16504de9d0b5SLee Nipper common_nonsnoop_unmap(dev, edesc, areq); 16514de9d0b5SLee Nipper kfree(edesc); 16524de9d0b5SLee Nipper } 16534de9d0b5SLee Nipper return ret; 16544de9d0b5SLee Nipper } 16554de9d0b5SLee Nipper 1656e938e465SKim Phillips static struct talitos_edesc *ablkcipher_edesc_alloc(struct ablkcipher_request * 165762293a37SHoria Geanta areq, bool encrypt) 16584de9d0b5SLee Nipper { 16594de9d0b5SLee Nipper struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(areq); 16604de9d0b5SLee Nipper struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher); 166179fd31d3SHoria Geanta unsigned int ivsize = crypto_ablkcipher_ivsize(cipher); 16624de9d0b5SLee Nipper 1663aeb4c132SHerbert Xu return talitos_edesc_alloc(ctx->dev, areq->src, areq->dst, 166479fd31d3SHoria Geanta areq->info, 0, areq->nbytes, 0, ivsize, 0, 166562293a37SHoria Geanta areq->base.flags, encrypt); 16664de9d0b5SLee Nipper } 16674de9d0b5SLee Nipper 16684de9d0b5SLee Nipper static int ablkcipher_encrypt(struct ablkcipher_request *areq) 16694de9d0b5SLee Nipper { 16704de9d0b5SLee Nipper struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(areq); 16714de9d0b5SLee Nipper struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher); 16724de9d0b5SLee Nipper struct talitos_edesc *edesc; 16734de9d0b5SLee Nipper 16744de9d0b5SLee Nipper /* allocate extended descriptor */ 167562293a37SHoria Geanta edesc = ablkcipher_edesc_alloc(areq, true); 16764de9d0b5SLee Nipper if (IS_ERR(edesc)) 16774de9d0b5SLee Nipper return PTR_ERR(edesc); 16784de9d0b5SLee Nipper 16794de9d0b5SLee Nipper /* set encrypt */ 16804de9d0b5SLee Nipper edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_MODE0_ENCRYPT; 16814de9d0b5SLee Nipper 1682febec542SKim Phillips return common_nonsnoop(edesc, areq, ablkcipher_done); 16834de9d0b5SLee Nipper } 16844de9d0b5SLee Nipper 16854de9d0b5SLee Nipper static int ablkcipher_decrypt(struct ablkcipher_request *areq) 16864de9d0b5SLee Nipper { 16874de9d0b5SLee Nipper struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(areq); 16884de9d0b5SLee Nipper struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher); 16894de9d0b5SLee Nipper struct talitos_edesc *edesc; 16904de9d0b5SLee Nipper 16914de9d0b5SLee Nipper /* allocate extended descriptor */ 169262293a37SHoria Geanta edesc = ablkcipher_edesc_alloc(areq, false); 16934de9d0b5SLee Nipper if (IS_ERR(edesc)) 16944de9d0b5SLee Nipper return PTR_ERR(edesc); 16954de9d0b5SLee Nipper 16964de9d0b5SLee Nipper edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_DIR_INBOUND; 16974de9d0b5SLee Nipper 1698febec542SKim Phillips return common_nonsnoop(edesc, areq, ablkcipher_done); 16994de9d0b5SLee Nipper } 17004de9d0b5SLee Nipper 1701497f2e6bSLee Nipper static void common_nonsnoop_hash_unmap(struct device *dev, 1702497f2e6bSLee Nipper struct talitos_edesc *edesc, 1703497f2e6bSLee Nipper struct ahash_request *areq) 1704497f2e6bSLee Nipper { 1705497f2e6bSLee Nipper struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq); 1706ad4cd51fSLEROY Christophe struct talitos_private *priv = dev_get_drvdata(dev); 1707ad4cd51fSLEROY Christophe bool is_sec1 = has_ftr_sec1(priv); 1708ad4cd51fSLEROY Christophe struct talitos_desc *desc = &edesc->desc; 1709ad4cd51fSLEROY Christophe struct talitos_desc *desc2 = desc + 1; 1710ad4cd51fSLEROY Christophe 1711ad4cd51fSLEROY Christophe unmap_single_talitos_ptr(dev, &edesc->desc.ptr[5], DMA_FROM_DEVICE); 1712ad4cd51fSLEROY Christophe if (desc->next_desc && 1713ad4cd51fSLEROY Christophe desc->ptr[5].ptr != desc2->ptr[5].ptr) 1714ad4cd51fSLEROY Christophe unmap_single_talitos_ptr(dev, &desc2->ptr[5], DMA_FROM_DEVICE); 1715497f2e6bSLee Nipper 17166a1e8d14SLEROY Christophe talitos_sg_unmap(dev, edesc, req_ctx->psrc, NULL, 0, 0); 1717032d197eSLEROY Christophe 1718ad4cd51fSLEROY Christophe /* When using hashctx-in, must unmap it. */ 1719ad4cd51fSLEROY Christophe if (from_talitos_ptr_len(&edesc->desc.ptr[1], is_sec1)) 1720ad4cd51fSLEROY Christophe unmap_single_talitos_ptr(dev, &edesc->desc.ptr[1], 1721ad4cd51fSLEROY Christophe DMA_TO_DEVICE); 1722ad4cd51fSLEROY Christophe else if (desc->next_desc) 1723ad4cd51fSLEROY Christophe unmap_single_talitos_ptr(dev, &desc2->ptr[1], 1724ad4cd51fSLEROY Christophe DMA_TO_DEVICE); 1725ad4cd51fSLEROY Christophe 1726ad4cd51fSLEROY Christophe if (is_sec1 && req_ctx->nbuf) 1727ad4cd51fSLEROY Christophe unmap_single_talitos_ptr(dev, &desc->ptr[3], 1728ad4cd51fSLEROY Christophe DMA_TO_DEVICE); 1729ad4cd51fSLEROY Christophe 1730497f2e6bSLee Nipper if (edesc->dma_len) 1731497f2e6bSLee Nipper dma_unmap_single(dev, edesc->dma_link_tbl, edesc->dma_len, 1732497f2e6bSLee Nipper DMA_BIDIRECTIONAL); 1733497f2e6bSLee Nipper 173437b5e889SLEROY Christophe if (edesc->desc.next_desc) 173537b5e889SLEROY Christophe dma_unmap_single(dev, be32_to_cpu(edesc->desc.next_desc), 173637b5e889SLEROY Christophe TALITOS_DESC_SIZE, DMA_BIDIRECTIONAL); 1737497f2e6bSLee Nipper } 1738497f2e6bSLee Nipper 1739497f2e6bSLee Nipper static void ahash_done(struct device *dev, 1740497f2e6bSLee Nipper struct talitos_desc *desc, void *context, 1741497f2e6bSLee Nipper int err) 1742497f2e6bSLee Nipper { 1743497f2e6bSLee Nipper struct ahash_request *areq = context; 1744497f2e6bSLee Nipper struct talitos_edesc *edesc = 1745497f2e6bSLee Nipper container_of(desc, struct talitos_edesc, desc); 1746497f2e6bSLee Nipper struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq); 1747497f2e6bSLee Nipper 1748497f2e6bSLee Nipper if (!req_ctx->last && req_ctx->to_hash_later) { 1749497f2e6bSLee Nipper /* Position any partial block for next update/final/finup */ 17503c0dd190SLEROY Christophe req_ctx->buf_idx = (req_ctx->buf_idx + 1) & 1; 17515e833bc4SLee Nipper req_ctx->nbuf = req_ctx->to_hash_later; 1752497f2e6bSLee Nipper } 1753497f2e6bSLee Nipper common_nonsnoop_hash_unmap(dev, edesc, areq); 1754497f2e6bSLee Nipper 1755497f2e6bSLee Nipper kfree(edesc); 1756497f2e6bSLee Nipper 1757497f2e6bSLee Nipper areq->base.complete(&areq->base, err); 1758497f2e6bSLee Nipper } 1759497f2e6bSLee Nipper 17602d02905eSLEROY Christophe /* 17612d02905eSLEROY Christophe * SEC1 doesn't like hashing of 0 sized message, so we do the padding 17622d02905eSLEROY Christophe * ourself and submit a padded block 17632d02905eSLEROY Christophe */ 17645b2cf268SLEROY Christophe static void talitos_handle_buggy_hash(struct talitos_ctx *ctx, 17652d02905eSLEROY Christophe struct talitos_edesc *edesc, 17662d02905eSLEROY Christophe struct talitos_ptr *ptr) 17672d02905eSLEROY Christophe { 17682d02905eSLEROY Christophe static u8 padded_hash[64] = { 17692d02905eSLEROY Christophe 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17702d02905eSLEROY Christophe 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17712d02905eSLEROY Christophe 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17722d02905eSLEROY Christophe 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17732d02905eSLEROY Christophe }; 17742d02905eSLEROY Christophe 17752d02905eSLEROY Christophe pr_err_once("Bug in SEC1, padding ourself\n"); 17762d02905eSLEROY Christophe edesc->desc.hdr &= ~DESC_HDR_MODE0_MDEU_PAD; 17772d02905eSLEROY Christophe map_single_talitos_ptr(ctx->dev, ptr, sizeof(padded_hash), 17782d02905eSLEROY Christophe (char *)padded_hash, DMA_TO_DEVICE); 17792d02905eSLEROY Christophe } 17802d02905eSLEROY Christophe 1781497f2e6bSLee Nipper static int common_nonsnoop_hash(struct talitos_edesc *edesc, 1782497f2e6bSLee Nipper struct ahash_request *areq, unsigned int length, 178337b5e889SLEROY Christophe unsigned int offset, 1784497f2e6bSLee Nipper void (*callback) (struct device *dev, 1785497f2e6bSLee Nipper struct talitos_desc *desc, 1786497f2e6bSLee Nipper void *context, int error)) 1787497f2e6bSLee Nipper { 1788497f2e6bSLee Nipper struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); 1789497f2e6bSLee Nipper struct talitos_ctx *ctx = crypto_ahash_ctx(tfm); 1790497f2e6bSLee Nipper struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq); 1791497f2e6bSLee Nipper struct device *dev = ctx->dev; 1792497f2e6bSLee Nipper struct talitos_desc *desc = &edesc->desc; 1793032d197eSLEROY Christophe int ret; 17946a1e8d14SLEROY Christophe bool sync_needed = false; 1795922f9dc8SLEROY Christophe struct talitos_private *priv = dev_get_drvdata(dev); 1796922f9dc8SLEROY Christophe bool is_sec1 = has_ftr_sec1(priv); 17976a1e8d14SLEROY Christophe int sg_count; 1798497f2e6bSLee Nipper 1799497f2e6bSLee Nipper /* first DWORD empty */ 1800497f2e6bSLee Nipper 180160f208d7SKim Phillips /* hash context in */ 180260f208d7SKim Phillips if (!req_ctx->first || req_ctx->swinit) { 18036a4967c3SLEROY Christophe map_single_talitos_ptr_nosync(dev, &desc->ptr[1], 1804ad4cd51fSLEROY Christophe req_ctx->hw_context_size, 18056a4967c3SLEROY Christophe req_ctx->hw_context, 1806ad4cd51fSLEROY Christophe DMA_TO_DEVICE); 180760f208d7SKim Phillips req_ctx->swinit = 0; 1808afd62fa2SLEROY Christophe } 1809497f2e6bSLee Nipper /* Indicate next op is not the first. */ 1810497f2e6bSLee Nipper req_ctx->first = 0; 1811497f2e6bSLee Nipper 1812497f2e6bSLee Nipper /* HMAC key */ 1813497f2e6bSLee Nipper if (ctx->keylen) 18142e13ce08SLEROY Christophe to_talitos_ptr(&desc->ptr[2], ctx->dma_key, ctx->keylen, 18152e13ce08SLEROY Christophe is_sec1); 1816497f2e6bSLee Nipper 181737b5e889SLEROY Christophe if (is_sec1 && req_ctx->nbuf) 181837b5e889SLEROY Christophe length -= req_ctx->nbuf; 181937b5e889SLEROY Christophe 18206a1e8d14SLEROY Christophe sg_count = edesc->src_nents ?: 1; 18216a1e8d14SLEROY Christophe if (is_sec1 && sg_count > 1) 182237b5e889SLEROY Christophe sg_pcopy_to_buffer(req_ctx->psrc, sg_count, 182337b5e889SLEROY Christophe edesc->buf + sizeof(struct talitos_desc), 182437b5e889SLEROY Christophe length, req_ctx->nbuf); 182537b5e889SLEROY Christophe else if (length) 18266a1e8d14SLEROY Christophe sg_count = dma_map_sg(dev, req_ctx->psrc, sg_count, 18276a1e8d14SLEROY Christophe DMA_TO_DEVICE); 1828497f2e6bSLee Nipper /* 1829497f2e6bSLee Nipper * data in 1830497f2e6bSLee Nipper */ 183137b5e889SLEROY Christophe if (is_sec1 && req_ctx->nbuf) { 1832ad4cd51fSLEROY Christophe map_single_talitos_ptr(dev, &desc->ptr[3], req_ctx->nbuf, 1833ad4cd51fSLEROY Christophe req_ctx->buf[req_ctx->buf_idx], 1834ad4cd51fSLEROY Christophe DMA_TO_DEVICE); 183537b5e889SLEROY Christophe } else { 18366a1e8d14SLEROY Christophe sg_count = talitos_sg_map(dev, req_ctx->psrc, length, edesc, 183737b5e889SLEROY Christophe &desc->ptr[3], sg_count, offset, 0); 18386a1e8d14SLEROY Christophe if (sg_count > 1) 18396a1e8d14SLEROY Christophe sync_needed = true; 184037b5e889SLEROY Christophe } 1841497f2e6bSLee Nipper 1842497f2e6bSLee Nipper /* fifth DWORD empty */ 1843497f2e6bSLee Nipper 1844497f2e6bSLee Nipper /* hash/HMAC out -or- hash context out */ 1845497f2e6bSLee Nipper if (req_ctx->last) 1846497f2e6bSLee Nipper map_single_talitos_ptr(dev, &desc->ptr[5], 1847497f2e6bSLee Nipper crypto_ahash_digestsize(tfm), 1848a2b35aa8SLEROY Christophe areq->result, DMA_FROM_DEVICE); 1849497f2e6bSLee Nipper else 18506a4967c3SLEROY Christophe map_single_talitos_ptr_nosync(dev, &desc->ptr[5], 1851ad4cd51fSLEROY Christophe req_ctx->hw_context_size, 18526a4967c3SLEROY Christophe req_ctx->hw_context, 18536a4967c3SLEROY Christophe DMA_FROM_DEVICE); 1854497f2e6bSLee Nipper 1855497f2e6bSLee Nipper /* last DWORD empty */ 1856497f2e6bSLee Nipper 18572d02905eSLEROY Christophe if (is_sec1 && from_talitos_ptr_len(&desc->ptr[3], true) == 0) 18582d02905eSLEROY Christophe talitos_handle_buggy_hash(ctx, edesc, &desc->ptr[3]); 18592d02905eSLEROY Christophe 186037b5e889SLEROY Christophe if (is_sec1 && req_ctx->nbuf && length) { 186137b5e889SLEROY Christophe struct talitos_desc *desc2 = desc + 1; 186237b5e889SLEROY Christophe dma_addr_t next_desc; 186337b5e889SLEROY Christophe 186437b5e889SLEROY Christophe memset(desc2, 0, sizeof(*desc2)); 186537b5e889SLEROY Christophe desc2->hdr = desc->hdr; 186637b5e889SLEROY Christophe desc2->hdr &= ~DESC_HDR_MODE0_MDEU_INIT; 186737b5e889SLEROY Christophe desc2->hdr1 = desc2->hdr; 186837b5e889SLEROY Christophe desc->hdr &= ~DESC_HDR_MODE0_MDEU_PAD; 186937b5e889SLEROY Christophe desc->hdr |= DESC_HDR_MODE0_MDEU_CONT; 187037b5e889SLEROY Christophe desc->hdr &= ~DESC_HDR_DONE_NOTIFY; 187137b5e889SLEROY Christophe 1872ad4cd51fSLEROY Christophe if (desc->ptr[1].ptr) 1873ad4cd51fSLEROY Christophe copy_talitos_ptr(&desc2->ptr[1], &desc->ptr[1], 1874ad4cd51fSLEROY Christophe is_sec1); 1875ad4cd51fSLEROY Christophe else 18766a4967c3SLEROY Christophe map_single_talitos_ptr_nosync(dev, &desc2->ptr[1], 1877ad4cd51fSLEROY Christophe req_ctx->hw_context_size, 1878ad4cd51fSLEROY Christophe req_ctx->hw_context, 1879ad4cd51fSLEROY Christophe DMA_TO_DEVICE); 188037b5e889SLEROY Christophe copy_talitos_ptr(&desc2->ptr[2], &desc->ptr[2], is_sec1); 188137b5e889SLEROY Christophe sg_count = talitos_sg_map(dev, req_ctx->psrc, length, edesc, 188237b5e889SLEROY Christophe &desc2->ptr[3], sg_count, offset, 0); 188337b5e889SLEROY Christophe if (sg_count > 1) 188437b5e889SLEROY Christophe sync_needed = true; 188537b5e889SLEROY Christophe copy_talitos_ptr(&desc2->ptr[5], &desc->ptr[5], is_sec1); 188637b5e889SLEROY Christophe if (req_ctx->last) 18876a4967c3SLEROY Christophe map_single_talitos_ptr_nosync(dev, &desc->ptr[5], 1888ad4cd51fSLEROY Christophe req_ctx->hw_context_size, 1889ad4cd51fSLEROY Christophe req_ctx->hw_context, 1890ad4cd51fSLEROY Christophe DMA_FROM_DEVICE); 189137b5e889SLEROY Christophe 189237b5e889SLEROY Christophe next_desc = dma_map_single(dev, &desc2->hdr1, TALITOS_DESC_SIZE, 189337b5e889SLEROY Christophe DMA_BIDIRECTIONAL); 189437b5e889SLEROY Christophe desc->next_desc = cpu_to_be32(next_desc); 189537b5e889SLEROY Christophe } 189637b5e889SLEROY Christophe 18976a1e8d14SLEROY Christophe if (sync_needed) 18986a1e8d14SLEROY Christophe dma_sync_single_for_device(dev, edesc->dma_link_tbl, 18996a1e8d14SLEROY Christophe edesc->dma_len, DMA_BIDIRECTIONAL); 19006a1e8d14SLEROY Christophe 19015228f0f7SKim Phillips ret = talitos_submit(dev, ctx->ch, desc, callback, areq); 1902497f2e6bSLee Nipper if (ret != -EINPROGRESS) { 1903497f2e6bSLee Nipper common_nonsnoop_hash_unmap(dev, edesc, areq); 1904497f2e6bSLee Nipper kfree(edesc); 1905497f2e6bSLee Nipper } 1906497f2e6bSLee Nipper return ret; 1907497f2e6bSLee Nipper } 1908497f2e6bSLee Nipper 1909497f2e6bSLee Nipper static struct talitos_edesc *ahash_edesc_alloc(struct ahash_request *areq, 1910497f2e6bSLee Nipper unsigned int nbytes) 1911497f2e6bSLee Nipper { 1912497f2e6bSLee Nipper struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); 1913497f2e6bSLee Nipper struct talitos_ctx *ctx = crypto_ahash_ctx(tfm); 1914497f2e6bSLee Nipper struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq); 191537b5e889SLEROY Christophe struct talitos_private *priv = dev_get_drvdata(ctx->dev); 191637b5e889SLEROY Christophe bool is_sec1 = has_ftr_sec1(priv); 191737b5e889SLEROY Christophe 191837b5e889SLEROY Christophe if (is_sec1) 191937b5e889SLEROY Christophe nbytes -= req_ctx->nbuf; 1920497f2e6bSLee Nipper 1921aeb4c132SHerbert Xu return talitos_edesc_alloc(ctx->dev, req_ctx->psrc, NULL, NULL, 0, 192262293a37SHoria Geanta nbytes, 0, 0, 0, areq->base.flags, false); 1923497f2e6bSLee Nipper } 1924497f2e6bSLee Nipper 1925497f2e6bSLee Nipper static int ahash_init(struct ahash_request *areq) 1926497f2e6bSLee Nipper { 1927497f2e6bSLee Nipper struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); 19286a4967c3SLEROY Christophe struct talitos_ctx *ctx = crypto_ahash_ctx(tfm); 19296a4967c3SLEROY Christophe struct device *dev = ctx->dev; 1930497f2e6bSLee Nipper struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq); 193149f9783bSLEROY Christophe unsigned int size; 19326a4967c3SLEROY Christophe dma_addr_t dma; 1933497f2e6bSLee Nipper 1934497f2e6bSLee Nipper /* Initialize the context */ 19353c0dd190SLEROY Christophe req_ctx->buf_idx = 0; 19365e833bc4SLee Nipper req_ctx->nbuf = 0; 193760f208d7SKim Phillips req_ctx->first = 1; /* first indicates h/w must init its context */ 193860f208d7SKim Phillips req_ctx->swinit = 0; /* assume h/w init of context */ 193949f9783bSLEROY Christophe size = (crypto_ahash_digestsize(tfm) <= SHA256_DIGEST_SIZE) 1940497f2e6bSLee Nipper ? TALITOS_MDEU_CONTEXT_SIZE_MD5_SHA1_SHA256 1941497f2e6bSLee Nipper : TALITOS_MDEU_CONTEXT_SIZE_SHA384_SHA512; 194249f9783bSLEROY Christophe req_ctx->hw_context_size = size; 1943497f2e6bSLee Nipper 19446a4967c3SLEROY Christophe dma = dma_map_single(dev, req_ctx->hw_context, req_ctx->hw_context_size, 19456a4967c3SLEROY Christophe DMA_TO_DEVICE); 19466a4967c3SLEROY Christophe dma_unmap_single(dev, dma, req_ctx->hw_context_size, DMA_TO_DEVICE); 19476a4967c3SLEROY Christophe 1948497f2e6bSLee Nipper return 0; 1949497f2e6bSLee Nipper } 1950497f2e6bSLee Nipper 195160f208d7SKim Phillips /* 195260f208d7SKim Phillips * on h/w without explicit sha224 support, we initialize h/w context 195360f208d7SKim Phillips * manually with sha224 constants, and tell it to run sha256. 195460f208d7SKim Phillips */ 195560f208d7SKim Phillips static int ahash_init_sha224_swinit(struct ahash_request *areq) 195660f208d7SKim Phillips { 195760f208d7SKim Phillips struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq); 195860f208d7SKim Phillips 1959a752447aSKim Phillips req_ctx->hw_context[0] = SHA224_H0; 1960a752447aSKim Phillips req_ctx->hw_context[1] = SHA224_H1; 1961a752447aSKim Phillips req_ctx->hw_context[2] = SHA224_H2; 1962a752447aSKim Phillips req_ctx->hw_context[3] = SHA224_H3; 1963a752447aSKim Phillips req_ctx->hw_context[4] = SHA224_H4; 1964a752447aSKim Phillips req_ctx->hw_context[5] = SHA224_H5; 1965a752447aSKim Phillips req_ctx->hw_context[6] = SHA224_H6; 1966a752447aSKim Phillips req_ctx->hw_context[7] = SHA224_H7; 196760f208d7SKim Phillips 196860f208d7SKim Phillips /* init 64-bit count */ 196960f208d7SKim Phillips req_ctx->hw_context[8] = 0; 197060f208d7SKim Phillips req_ctx->hw_context[9] = 0; 197160f208d7SKim Phillips 19726a4967c3SLEROY Christophe ahash_init(areq); 19736a4967c3SLEROY Christophe req_ctx->swinit = 1;/* prevent h/w initting context with sha256 values*/ 19746a4967c3SLEROY Christophe 197560f208d7SKim Phillips return 0; 197660f208d7SKim Phillips } 197760f208d7SKim Phillips 1978497f2e6bSLee Nipper static int ahash_process_req(struct ahash_request *areq, unsigned int nbytes) 1979497f2e6bSLee Nipper { 1980497f2e6bSLee Nipper struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); 1981497f2e6bSLee Nipper struct talitos_ctx *ctx = crypto_ahash_ctx(tfm); 1982497f2e6bSLee Nipper struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq); 1983497f2e6bSLee Nipper struct talitos_edesc *edesc; 1984497f2e6bSLee Nipper unsigned int blocksize = 1985497f2e6bSLee Nipper crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm)); 1986497f2e6bSLee Nipper unsigned int nbytes_to_hash; 1987497f2e6bSLee Nipper unsigned int to_hash_later; 19885e833bc4SLee Nipper unsigned int nsg; 19898e409fe1SLABBE Corentin int nents; 199037b5e889SLEROY Christophe struct device *dev = ctx->dev; 199137b5e889SLEROY Christophe struct talitos_private *priv = dev_get_drvdata(dev); 199237b5e889SLEROY Christophe bool is_sec1 = has_ftr_sec1(priv); 199337b5e889SLEROY Christophe int offset = 0; 19943c0dd190SLEROY Christophe u8 *ctx_buf = req_ctx->buf[req_ctx->buf_idx]; 1995497f2e6bSLee Nipper 19965e833bc4SLee Nipper if (!req_ctx->last && (nbytes + req_ctx->nbuf <= blocksize)) { 19975e833bc4SLee Nipper /* Buffer up to one whole block */ 19988e409fe1SLABBE Corentin nents = sg_nents_for_len(areq->src, nbytes); 19998e409fe1SLABBE Corentin if (nents < 0) { 20008e409fe1SLABBE Corentin dev_err(ctx->dev, "Invalid number of src SG.\n"); 20018e409fe1SLABBE Corentin return nents; 20028e409fe1SLABBE Corentin } 20038e409fe1SLABBE Corentin sg_copy_to_buffer(areq->src, nents, 20043c0dd190SLEROY Christophe ctx_buf + req_ctx->nbuf, nbytes); 20055e833bc4SLee Nipper req_ctx->nbuf += nbytes; 2006497f2e6bSLee Nipper return 0; 2007497f2e6bSLee Nipper } 2008497f2e6bSLee Nipper 20095e833bc4SLee Nipper /* At least (blocksize + 1) bytes are available to hash */ 20105e833bc4SLee Nipper nbytes_to_hash = nbytes + req_ctx->nbuf; 20115e833bc4SLee Nipper to_hash_later = nbytes_to_hash & (blocksize - 1); 20125e833bc4SLee Nipper 20135e833bc4SLee Nipper if (req_ctx->last) 20145e833bc4SLee Nipper to_hash_later = 0; 20155e833bc4SLee Nipper else if (to_hash_later) 20165e833bc4SLee Nipper /* There is a partial block. Hash the full block(s) now */ 20175e833bc4SLee Nipper nbytes_to_hash -= to_hash_later; 20185e833bc4SLee Nipper else { 20195e833bc4SLee Nipper /* Keep one block buffered */ 20205e833bc4SLee Nipper nbytes_to_hash -= blocksize; 20215e833bc4SLee Nipper to_hash_later = blocksize; 2022497f2e6bSLee Nipper } 20235e833bc4SLee Nipper 20245e833bc4SLee Nipper /* Chain in any previously buffered data */ 202537b5e889SLEROY Christophe if (!is_sec1 && req_ctx->nbuf) { 20265e833bc4SLee Nipper nsg = (req_ctx->nbuf < nbytes_to_hash) ? 2 : 1; 20275e833bc4SLee Nipper sg_init_table(req_ctx->bufsl, nsg); 20283c0dd190SLEROY Christophe sg_set_buf(req_ctx->bufsl, ctx_buf, req_ctx->nbuf); 20295e833bc4SLee Nipper if (nsg > 1) 2030c56f6d12SDan Williams sg_chain(req_ctx->bufsl, 2, areq->src); 20315e833bc4SLee Nipper req_ctx->psrc = req_ctx->bufsl; 203237b5e889SLEROY Christophe } else if (is_sec1 && req_ctx->nbuf && req_ctx->nbuf < blocksize) { 203337b5e889SLEROY Christophe if (nbytes_to_hash > blocksize) 203437b5e889SLEROY Christophe offset = blocksize - req_ctx->nbuf; 203537b5e889SLEROY Christophe else 203637b5e889SLEROY Christophe offset = nbytes_to_hash - req_ctx->nbuf; 203737b5e889SLEROY Christophe nents = sg_nents_for_len(areq->src, offset); 203837b5e889SLEROY Christophe if (nents < 0) { 203937b5e889SLEROY Christophe dev_err(ctx->dev, "Invalid number of src SG.\n"); 204037b5e889SLEROY Christophe return nents; 204137b5e889SLEROY Christophe } 204237b5e889SLEROY Christophe sg_copy_to_buffer(areq->src, nents, 20433c0dd190SLEROY Christophe ctx_buf + req_ctx->nbuf, offset); 204437b5e889SLEROY Christophe req_ctx->nbuf += offset; 204537b5e889SLEROY Christophe req_ctx->psrc = areq->src; 20465e833bc4SLee Nipper } else 20475e833bc4SLee Nipper req_ctx->psrc = areq->src; 20485e833bc4SLee Nipper 2049497f2e6bSLee Nipper if (to_hash_later) { 20508e409fe1SLABBE Corentin nents = sg_nents_for_len(areq->src, nbytes); 20518e409fe1SLABBE Corentin if (nents < 0) { 20528e409fe1SLABBE Corentin dev_err(ctx->dev, "Invalid number of src SG.\n"); 20538e409fe1SLABBE Corentin return nents; 20548e409fe1SLABBE Corentin } 2055d0525723SAkinobu Mita sg_pcopy_to_buffer(areq->src, nents, 20563c0dd190SLEROY Christophe req_ctx->buf[(req_ctx->buf_idx + 1) & 1], 2057497f2e6bSLee Nipper to_hash_later, 2058497f2e6bSLee Nipper nbytes - to_hash_later); 2059497f2e6bSLee Nipper } 2060497f2e6bSLee Nipper req_ctx->to_hash_later = to_hash_later; 2061497f2e6bSLee Nipper 20625e833bc4SLee Nipper /* Allocate extended descriptor */ 2063497f2e6bSLee Nipper edesc = ahash_edesc_alloc(areq, nbytes_to_hash); 2064497f2e6bSLee Nipper if (IS_ERR(edesc)) 2065497f2e6bSLee Nipper return PTR_ERR(edesc); 2066497f2e6bSLee Nipper 2067497f2e6bSLee Nipper edesc->desc.hdr = ctx->desc_hdr_template; 2068497f2e6bSLee Nipper 2069497f2e6bSLee Nipper /* On last one, request SEC to pad; otherwise continue */ 2070497f2e6bSLee Nipper if (req_ctx->last) 2071497f2e6bSLee Nipper edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_PAD; 2072497f2e6bSLee Nipper else 2073497f2e6bSLee Nipper edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_CONT; 2074497f2e6bSLee Nipper 207560f208d7SKim Phillips /* request SEC to INIT hash. */ 207660f208d7SKim Phillips if (req_ctx->first && !req_ctx->swinit) 2077497f2e6bSLee Nipper edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_INIT; 2078497f2e6bSLee Nipper 2079497f2e6bSLee Nipper /* When the tfm context has a keylen, it's an HMAC. 2080497f2e6bSLee Nipper * A first or last (ie. not middle) descriptor must request HMAC. 2081497f2e6bSLee Nipper */ 2082497f2e6bSLee Nipper if (ctx->keylen && (req_ctx->first || req_ctx->last)) 2083497f2e6bSLee Nipper edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_HMAC; 2084497f2e6bSLee Nipper 208537b5e889SLEROY Christophe return common_nonsnoop_hash(edesc, areq, nbytes_to_hash, offset, 2086497f2e6bSLee Nipper ahash_done); 2087497f2e6bSLee Nipper } 2088497f2e6bSLee Nipper 2089497f2e6bSLee Nipper static int ahash_update(struct ahash_request *areq) 2090497f2e6bSLee Nipper { 2091497f2e6bSLee Nipper struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq); 2092497f2e6bSLee Nipper 2093497f2e6bSLee Nipper req_ctx->last = 0; 2094497f2e6bSLee Nipper 2095497f2e6bSLee Nipper return ahash_process_req(areq, areq->nbytes); 2096497f2e6bSLee Nipper } 2097497f2e6bSLee Nipper 2098497f2e6bSLee Nipper static int ahash_final(struct ahash_request *areq) 2099497f2e6bSLee Nipper { 2100497f2e6bSLee Nipper struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq); 2101497f2e6bSLee Nipper 2102497f2e6bSLee Nipper req_ctx->last = 1; 2103497f2e6bSLee Nipper 2104497f2e6bSLee Nipper return ahash_process_req(areq, 0); 2105497f2e6bSLee Nipper } 2106497f2e6bSLee Nipper 2107497f2e6bSLee Nipper static int ahash_finup(struct ahash_request *areq) 2108497f2e6bSLee Nipper { 2109497f2e6bSLee Nipper struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq); 2110497f2e6bSLee Nipper 2111497f2e6bSLee Nipper req_ctx->last = 1; 2112497f2e6bSLee Nipper 2113497f2e6bSLee Nipper return ahash_process_req(areq, areq->nbytes); 2114497f2e6bSLee Nipper } 2115497f2e6bSLee Nipper 2116497f2e6bSLee Nipper static int ahash_digest(struct ahash_request *areq) 2117497f2e6bSLee Nipper { 2118497f2e6bSLee Nipper struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq); 211960f208d7SKim Phillips struct crypto_ahash *ahash = crypto_ahash_reqtfm(areq); 2120497f2e6bSLee Nipper 212160f208d7SKim Phillips ahash->init(areq); 2122497f2e6bSLee Nipper req_ctx->last = 1; 2123497f2e6bSLee Nipper 2124497f2e6bSLee Nipper return ahash_process_req(areq, areq->nbytes); 2125497f2e6bSLee Nipper } 2126497f2e6bSLee Nipper 21273639ca84SHoria Geant? static int ahash_export(struct ahash_request *areq, void *out) 21283639ca84SHoria Geant? { 21293639ca84SHoria Geant? struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq); 21303639ca84SHoria Geant? struct talitos_export_state *export = out; 21316a4967c3SLEROY Christophe struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); 21326a4967c3SLEROY Christophe struct talitos_ctx *ctx = crypto_ahash_ctx(tfm); 21336a4967c3SLEROY Christophe struct device *dev = ctx->dev; 21346a4967c3SLEROY Christophe dma_addr_t dma; 21356a4967c3SLEROY Christophe 21366a4967c3SLEROY Christophe dma = dma_map_single(dev, req_ctx->hw_context, req_ctx->hw_context_size, 21376a4967c3SLEROY Christophe DMA_FROM_DEVICE); 21386a4967c3SLEROY Christophe dma_unmap_single(dev, dma, req_ctx->hw_context_size, DMA_FROM_DEVICE); 21393639ca84SHoria Geant? 21403639ca84SHoria Geant? memcpy(export->hw_context, req_ctx->hw_context, 21413639ca84SHoria Geant? req_ctx->hw_context_size); 21423c0dd190SLEROY Christophe memcpy(export->buf, req_ctx->buf[req_ctx->buf_idx], req_ctx->nbuf); 21433639ca84SHoria Geant? export->swinit = req_ctx->swinit; 21443639ca84SHoria Geant? export->first = req_ctx->first; 21453639ca84SHoria Geant? export->last = req_ctx->last; 21463639ca84SHoria Geant? export->to_hash_later = req_ctx->to_hash_later; 21473639ca84SHoria Geant? export->nbuf = req_ctx->nbuf; 21483639ca84SHoria Geant? 21493639ca84SHoria Geant? return 0; 21503639ca84SHoria Geant? } 21513639ca84SHoria Geant? 21523639ca84SHoria Geant? static int ahash_import(struct ahash_request *areq, const void *in) 21533639ca84SHoria Geant? { 21543639ca84SHoria Geant? struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq); 21553639ca84SHoria Geant? struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); 21566a4967c3SLEROY Christophe struct talitos_ctx *ctx = crypto_ahash_ctx(tfm); 21576a4967c3SLEROY Christophe struct device *dev = ctx->dev; 21583639ca84SHoria Geant? const struct talitos_export_state *export = in; 215949f9783bSLEROY Christophe unsigned int size; 21606a4967c3SLEROY Christophe dma_addr_t dma; 21613639ca84SHoria Geant? 21623639ca84SHoria Geant? memset(req_ctx, 0, sizeof(*req_ctx)); 216349f9783bSLEROY Christophe size = (crypto_ahash_digestsize(tfm) <= SHA256_DIGEST_SIZE) 21643639ca84SHoria Geant? ? TALITOS_MDEU_CONTEXT_SIZE_MD5_SHA1_SHA256 21653639ca84SHoria Geant? : TALITOS_MDEU_CONTEXT_SIZE_SHA384_SHA512; 216649f9783bSLEROY Christophe req_ctx->hw_context_size = size; 216749f9783bSLEROY Christophe memcpy(req_ctx->hw_context, export->hw_context, size); 21683c0dd190SLEROY Christophe memcpy(req_ctx->buf[0], export->buf, export->nbuf); 21693639ca84SHoria Geant? req_ctx->swinit = export->swinit; 21703639ca84SHoria Geant? req_ctx->first = export->first; 21713639ca84SHoria Geant? req_ctx->last = export->last; 21723639ca84SHoria Geant? req_ctx->to_hash_later = export->to_hash_later; 21733639ca84SHoria Geant? req_ctx->nbuf = export->nbuf; 21743639ca84SHoria Geant? 21756a4967c3SLEROY Christophe dma = dma_map_single(dev, req_ctx->hw_context, req_ctx->hw_context_size, 21766a4967c3SLEROY Christophe DMA_TO_DEVICE); 21776a4967c3SLEROY Christophe dma_unmap_single(dev, dma, req_ctx->hw_context_size, DMA_TO_DEVICE); 21786a4967c3SLEROY Christophe 21793639ca84SHoria Geant? return 0; 21803639ca84SHoria Geant? } 21813639ca84SHoria Geant? 218279b3a418SLee Nipper static int keyhash(struct crypto_ahash *tfm, const u8 *key, unsigned int keylen, 218379b3a418SLee Nipper u8 *hash) 218479b3a418SLee Nipper { 218579b3a418SLee Nipper struct talitos_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm)); 218679b3a418SLee Nipper 218779b3a418SLee Nipper struct scatterlist sg[1]; 218879b3a418SLee Nipper struct ahash_request *req; 2189f1c90ac3SGilad Ben-Yossef struct crypto_wait wait; 219079b3a418SLee Nipper int ret; 219179b3a418SLee Nipper 2192f1c90ac3SGilad Ben-Yossef crypto_init_wait(&wait); 219379b3a418SLee Nipper 219479b3a418SLee Nipper req = ahash_request_alloc(tfm, GFP_KERNEL); 219579b3a418SLee Nipper if (!req) 219679b3a418SLee Nipper return -ENOMEM; 219779b3a418SLee Nipper 219879b3a418SLee Nipper /* Keep tfm keylen == 0 during hash of the long key */ 219979b3a418SLee Nipper ctx->keylen = 0; 220079b3a418SLee Nipper ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, 2201f1c90ac3SGilad Ben-Yossef crypto_req_done, &wait); 220279b3a418SLee Nipper 220379b3a418SLee Nipper sg_init_one(&sg[0], key, keylen); 220479b3a418SLee Nipper 220579b3a418SLee Nipper ahash_request_set_crypt(req, sg, hash, keylen); 2206f1c90ac3SGilad Ben-Yossef ret = crypto_wait_req(crypto_ahash_digest(req), &wait); 2207f1c90ac3SGilad Ben-Yossef 220879b3a418SLee Nipper ahash_request_free(req); 220979b3a418SLee Nipper 221079b3a418SLee Nipper return ret; 221179b3a418SLee Nipper } 221279b3a418SLee Nipper 221379b3a418SLee Nipper static int ahash_setkey(struct crypto_ahash *tfm, const u8 *key, 221479b3a418SLee Nipper unsigned int keylen) 221579b3a418SLee Nipper { 221679b3a418SLee Nipper struct talitos_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm)); 22172e13ce08SLEROY Christophe struct device *dev = ctx->dev; 221879b3a418SLee Nipper unsigned int blocksize = 221979b3a418SLee Nipper crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm)); 222079b3a418SLee Nipper unsigned int digestsize = crypto_ahash_digestsize(tfm); 222179b3a418SLee Nipper unsigned int keysize = keylen; 222279b3a418SLee Nipper u8 hash[SHA512_DIGEST_SIZE]; 222379b3a418SLee Nipper int ret; 222479b3a418SLee Nipper 222579b3a418SLee Nipper if (keylen <= blocksize) 222679b3a418SLee Nipper memcpy(ctx->key, key, keysize); 222779b3a418SLee Nipper else { 222879b3a418SLee Nipper /* Must get the hash of the long key */ 222979b3a418SLee Nipper ret = keyhash(tfm, key, keylen, hash); 223079b3a418SLee Nipper 223179b3a418SLee Nipper if (ret) { 223279b3a418SLee Nipper crypto_ahash_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN); 223379b3a418SLee Nipper return -EINVAL; 223479b3a418SLee Nipper } 223579b3a418SLee Nipper 223679b3a418SLee Nipper keysize = digestsize; 223779b3a418SLee Nipper memcpy(ctx->key, hash, digestsize); 223879b3a418SLee Nipper } 223979b3a418SLee Nipper 22402e13ce08SLEROY Christophe if (ctx->keylen) 22412e13ce08SLEROY Christophe dma_unmap_single(dev, ctx->dma_key, ctx->keylen, DMA_TO_DEVICE); 22422e13ce08SLEROY Christophe 224379b3a418SLee Nipper ctx->keylen = keysize; 22442e13ce08SLEROY Christophe ctx->dma_key = dma_map_single(dev, ctx->key, keysize, DMA_TO_DEVICE); 224579b3a418SLee Nipper 224679b3a418SLee Nipper return 0; 224779b3a418SLee Nipper } 224879b3a418SLee Nipper 224979b3a418SLee Nipper 22509c4a7965SKim Phillips struct talitos_alg_template { 2251d5e4aaefSLee Nipper u32 type; 2252b0057763SLEROY Christophe u32 priority; 2253d5e4aaefSLee Nipper union { 2254d5e4aaefSLee Nipper struct crypto_alg crypto; 2255acbf7c62SLee Nipper struct ahash_alg hash; 2256aeb4c132SHerbert Xu struct aead_alg aead; 2257d5e4aaefSLee Nipper } alg; 22589c4a7965SKim Phillips __be32 desc_hdr_template; 22599c4a7965SKim Phillips }; 22609c4a7965SKim Phillips 22619c4a7965SKim Phillips static struct talitos_alg_template driver_algs[] = { 2262991155baSHoria Geanta /* AEAD algorithms. These use a single-pass ipsec_esp descriptor */ 2263d5e4aaefSLee Nipper { .type = CRYPTO_ALG_TYPE_AEAD, 2264aeb4c132SHerbert Xu .alg.aead = { 2265aeb4c132SHerbert Xu .base = { 226656af8cd4SLee Nipper .cra_name = "authenc(hmac(sha1),cbc(aes))", 2267aeb4c132SHerbert Xu .cra_driver_name = "authenc-hmac-sha1-" 2268aeb4c132SHerbert Xu "cbc-aes-talitos", 226956af8cd4SLee Nipper .cra_blocksize = AES_BLOCK_SIZE, 2270aeb4c132SHerbert Xu .cra_flags = CRYPTO_ALG_ASYNC, 2271aeb4c132SHerbert Xu }, 22723952f17eSLee Nipper .ivsize = AES_BLOCK_SIZE, 22733952f17eSLee Nipper .maxauthsize = SHA1_DIGEST_SIZE, 22749c4a7965SKim Phillips }, 22759c4a7965SKim Phillips .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP | 22769c4a7965SKim Phillips DESC_HDR_SEL0_AESU | 22779c4a7965SKim Phillips DESC_HDR_MODE0_AESU_CBC | 22789c4a7965SKim Phillips DESC_HDR_SEL1_MDEUA | 22799c4a7965SKim Phillips DESC_HDR_MODE1_MDEU_INIT | 22809c4a7965SKim Phillips DESC_HDR_MODE1_MDEU_PAD | 22819c4a7965SKim Phillips DESC_HDR_MODE1_MDEU_SHA1_HMAC, 228270bcaca7SLee Nipper }, 2283d5e4aaefSLee Nipper { .type = CRYPTO_ALG_TYPE_AEAD, 22847405c8d7SLEROY Christophe .priority = TALITOS_CRA_PRIORITY_AEAD_HSNA, 22857405c8d7SLEROY Christophe .alg.aead = { 22867405c8d7SLEROY Christophe .base = { 22877405c8d7SLEROY Christophe .cra_name = "authenc(hmac(sha1),cbc(aes))", 22887405c8d7SLEROY Christophe .cra_driver_name = "authenc-hmac-sha1-" 22897405c8d7SLEROY Christophe "cbc-aes-talitos", 22907405c8d7SLEROY Christophe .cra_blocksize = AES_BLOCK_SIZE, 22917405c8d7SLEROY Christophe .cra_flags = CRYPTO_ALG_ASYNC, 22927405c8d7SLEROY Christophe }, 22937405c8d7SLEROY Christophe .ivsize = AES_BLOCK_SIZE, 22947405c8d7SLEROY Christophe .maxauthsize = SHA1_DIGEST_SIZE, 22957405c8d7SLEROY Christophe }, 22967405c8d7SLEROY Christophe .desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU | 22977405c8d7SLEROY Christophe DESC_HDR_SEL0_AESU | 22987405c8d7SLEROY Christophe DESC_HDR_MODE0_AESU_CBC | 22997405c8d7SLEROY Christophe DESC_HDR_SEL1_MDEUA | 23007405c8d7SLEROY Christophe DESC_HDR_MODE1_MDEU_INIT | 23017405c8d7SLEROY Christophe DESC_HDR_MODE1_MDEU_PAD | 23027405c8d7SLEROY Christophe DESC_HDR_MODE1_MDEU_SHA1_HMAC, 23037405c8d7SLEROY Christophe }, 23047405c8d7SLEROY Christophe { .type = CRYPTO_ALG_TYPE_AEAD, 2305aeb4c132SHerbert Xu .alg.aead = { 2306aeb4c132SHerbert Xu .base = { 2307aeb4c132SHerbert Xu .cra_name = "authenc(hmac(sha1)," 2308aeb4c132SHerbert Xu "cbc(des3_ede))", 2309aeb4c132SHerbert Xu .cra_driver_name = "authenc-hmac-sha1-" 2310aeb4c132SHerbert Xu "cbc-3des-talitos", 231156af8cd4SLee Nipper .cra_blocksize = DES3_EDE_BLOCK_SIZE, 2312aeb4c132SHerbert Xu .cra_flags = CRYPTO_ALG_ASYNC, 2313aeb4c132SHerbert Xu }, 23143952f17eSLee Nipper .ivsize = DES3_EDE_BLOCK_SIZE, 23153952f17eSLee Nipper .maxauthsize = SHA1_DIGEST_SIZE, 231670bcaca7SLee Nipper }, 231770bcaca7SLee Nipper .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP | 231870bcaca7SLee Nipper DESC_HDR_SEL0_DEU | 231970bcaca7SLee Nipper DESC_HDR_MODE0_DEU_CBC | 232070bcaca7SLee Nipper DESC_HDR_MODE0_DEU_3DES | 232170bcaca7SLee Nipper DESC_HDR_SEL1_MDEUA | 232270bcaca7SLee Nipper DESC_HDR_MODE1_MDEU_INIT | 232370bcaca7SLee Nipper DESC_HDR_MODE1_MDEU_PAD | 232470bcaca7SLee Nipper DESC_HDR_MODE1_MDEU_SHA1_HMAC, 23253952f17eSLee Nipper }, 2326d5e4aaefSLee Nipper { .type = CRYPTO_ALG_TYPE_AEAD, 23277405c8d7SLEROY Christophe .priority = TALITOS_CRA_PRIORITY_AEAD_HSNA, 23287405c8d7SLEROY Christophe .alg.aead = { 23297405c8d7SLEROY Christophe .base = { 23307405c8d7SLEROY Christophe .cra_name = "authenc(hmac(sha1)," 23317405c8d7SLEROY Christophe "cbc(des3_ede))", 23327405c8d7SLEROY Christophe .cra_driver_name = "authenc-hmac-sha1-" 23337405c8d7SLEROY Christophe "cbc-3des-talitos", 23347405c8d7SLEROY Christophe .cra_blocksize = DES3_EDE_BLOCK_SIZE, 23357405c8d7SLEROY Christophe .cra_flags = CRYPTO_ALG_ASYNC, 23367405c8d7SLEROY Christophe }, 23377405c8d7SLEROY Christophe .ivsize = DES3_EDE_BLOCK_SIZE, 23387405c8d7SLEROY Christophe .maxauthsize = SHA1_DIGEST_SIZE, 23397405c8d7SLEROY Christophe }, 23407405c8d7SLEROY Christophe .desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU | 23417405c8d7SLEROY Christophe DESC_HDR_SEL0_DEU | 23427405c8d7SLEROY Christophe DESC_HDR_MODE0_DEU_CBC | 23437405c8d7SLEROY Christophe DESC_HDR_MODE0_DEU_3DES | 23447405c8d7SLEROY Christophe DESC_HDR_SEL1_MDEUA | 23457405c8d7SLEROY Christophe DESC_HDR_MODE1_MDEU_INIT | 23467405c8d7SLEROY Christophe DESC_HDR_MODE1_MDEU_PAD | 23477405c8d7SLEROY Christophe DESC_HDR_MODE1_MDEU_SHA1_HMAC, 23487405c8d7SLEROY Christophe }, 23497405c8d7SLEROY Christophe { .type = CRYPTO_ALG_TYPE_AEAD, 2350aeb4c132SHerbert Xu .alg.aead = { 2351aeb4c132SHerbert Xu .base = { 2352357fb605SHoria Geanta .cra_name = "authenc(hmac(sha224),cbc(aes))", 2353aeb4c132SHerbert Xu .cra_driver_name = "authenc-hmac-sha224-" 2354aeb4c132SHerbert Xu "cbc-aes-talitos", 2355357fb605SHoria Geanta .cra_blocksize = AES_BLOCK_SIZE, 2356aeb4c132SHerbert Xu .cra_flags = CRYPTO_ALG_ASYNC, 2357aeb4c132SHerbert Xu }, 2358357fb605SHoria Geanta .ivsize = AES_BLOCK_SIZE, 2359357fb605SHoria Geanta .maxauthsize = SHA224_DIGEST_SIZE, 2360357fb605SHoria Geanta }, 2361357fb605SHoria Geanta .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP | 2362357fb605SHoria Geanta DESC_HDR_SEL0_AESU | 2363357fb605SHoria Geanta DESC_HDR_MODE0_AESU_CBC | 2364357fb605SHoria Geanta DESC_HDR_SEL1_MDEUA | 2365357fb605SHoria Geanta DESC_HDR_MODE1_MDEU_INIT | 2366357fb605SHoria Geanta DESC_HDR_MODE1_MDEU_PAD | 2367357fb605SHoria Geanta DESC_HDR_MODE1_MDEU_SHA224_HMAC, 2368357fb605SHoria Geanta }, 2369357fb605SHoria Geanta { .type = CRYPTO_ALG_TYPE_AEAD, 23707405c8d7SLEROY Christophe .priority = TALITOS_CRA_PRIORITY_AEAD_HSNA, 23717405c8d7SLEROY Christophe .alg.aead = { 23727405c8d7SLEROY Christophe .base = { 23737405c8d7SLEROY Christophe .cra_name = "authenc(hmac(sha224),cbc(aes))", 23747405c8d7SLEROY Christophe .cra_driver_name = "authenc-hmac-sha224-" 23757405c8d7SLEROY Christophe "cbc-aes-talitos", 23767405c8d7SLEROY Christophe .cra_blocksize = AES_BLOCK_SIZE, 23777405c8d7SLEROY Christophe .cra_flags = CRYPTO_ALG_ASYNC, 23787405c8d7SLEROY Christophe }, 23797405c8d7SLEROY Christophe .ivsize = AES_BLOCK_SIZE, 23807405c8d7SLEROY Christophe .maxauthsize = SHA224_DIGEST_SIZE, 23817405c8d7SLEROY Christophe }, 23827405c8d7SLEROY Christophe .desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU | 23837405c8d7SLEROY Christophe DESC_HDR_SEL0_AESU | 23847405c8d7SLEROY Christophe DESC_HDR_MODE0_AESU_CBC | 23857405c8d7SLEROY Christophe DESC_HDR_SEL1_MDEUA | 23867405c8d7SLEROY Christophe DESC_HDR_MODE1_MDEU_INIT | 23877405c8d7SLEROY Christophe DESC_HDR_MODE1_MDEU_PAD | 23887405c8d7SLEROY Christophe DESC_HDR_MODE1_MDEU_SHA224_HMAC, 23897405c8d7SLEROY Christophe }, 23907405c8d7SLEROY Christophe { .type = CRYPTO_ALG_TYPE_AEAD, 2391aeb4c132SHerbert Xu .alg.aead = { 2392aeb4c132SHerbert Xu .base = { 2393aeb4c132SHerbert Xu .cra_name = "authenc(hmac(sha224)," 2394aeb4c132SHerbert Xu "cbc(des3_ede))", 2395aeb4c132SHerbert Xu .cra_driver_name = "authenc-hmac-sha224-" 2396aeb4c132SHerbert Xu "cbc-3des-talitos", 2397357fb605SHoria Geanta .cra_blocksize = DES3_EDE_BLOCK_SIZE, 2398aeb4c132SHerbert Xu .cra_flags = CRYPTO_ALG_ASYNC, 2399aeb4c132SHerbert Xu }, 2400357fb605SHoria Geanta .ivsize = DES3_EDE_BLOCK_SIZE, 2401357fb605SHoria Geanta .maxauthsize = SHA224_DIGEST_SIZE, 2402357fb605SHoria Geanta }, 2403357fb605SHoria Geanta .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP | 2404357fb605SHoria Geanta DESC_HDR_SEL0_DEU | 2405357fb605SHoria Geanta DESC_HDR_MODE0_DEU_CBC | 2406357fb605SHoria Geanta DESC_HDR_MODE0_DEU_3DES | 2407357fb605SHoria Geanta DESC_HDR_SEL1_MDEUA | 2408357fb605SHoria Geanta DESC_HDR_MODE1_MDEU_INIT | 2409357fb605SHoria Geanta DESC_HDR_MODE1_MDEU_PAD | 2410357fb605SHoria Geanta DESC_HDR_MODE1_MDEU_SHA224_HMAC, 2411357fb605SHoria Geanta }, 2412357fb605SHoria Geanta { .type = CRYPTO_ALG_TYPE_AEAD, 24137405c8d7SLEROY Christophe .priority = TALITOS_CRA_PRIORITY_AEAD_HSNA, 24147405c8d7SLEROY Christophe .alg.aead = { 24157405c8d7SLEROY Christophe .base = { 24167405c8d7SLEROY Christophe .cra_name = "authenc(hmac(sha224)," 24177405c8d7SLEROY Christophe "cbc(des3_ede))", 24187405c8d7SLEROY Christophe .cra_driver_name = "authenc-hmac-sha224-" 24197405c8d7SLEROY Christophe "cbc-3des-talitos", 24207405c8d7SLEROY Christophe .cra_blocksize = DES3_EDE_BLOCK_SIZE, 24217405c8d7SLEROY Christophe .cra_flags = CRYPTO_ALG_ASYNC, 24227405c8d7SLEROY Christophe }, 24237405c8d7SLEROY Christophe .ivsize = DES3_EDE_BLOCK_SIZE, 24247405c8d7SLEROY Christophe .maxauthsize = SHA224_DIGEST_SIZE, 24257405c8d7SLEROY Christophe }, 24267405c8d7SLEROY Christophe .desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU | 24277405c8d7SLEROY Christophe DESC_HDR_SEL0_DEU | 24287405c8d7SLEROY Christophe DESC_HDR_MODE0_DEU_CBC | 24297405c8d7SLEROY Christophe DESC_HDR_MODE0_DEU_3DES | 24307405c8d7SLEROY Christophe DESC_HDR_SEL1_MDEUA | 24317405c8d7SLEROY Christophe DESC_HDR_MODE1_MDEU_INIT | 24327405c8d7SLEROY Christophe DESC_HDR_MODE1_MDEU_PAD | 24337405c8d7SLEROY Christophe DESC_HDR_MODE1_MDEU_SHA224_HMAC, 24347405c8d7SLEROY Christophe }, 24357405c8d7SLEROY Christophe { .type = CRYPTO_ALG_TYPE_AEAD, 2436aeb4c132SHerbert Xu .alg.aead = { 2437aeb4c132SHerbert Xu .base = { 243856af8cd4SLee Nipper .cra_name = "authenc(hmac(sha256),cbc(aes))", 2439aeb4c132SHerbert Xu .cra_driver_name = "authenc-hmac-sha256-" 2440aeb4c132SHerbert Xu "cbc-aes-talitos", 244156af8cd4SLee Nipper .cra_blocksize = AES_BLOCK_SIZE, 2442aeb4c132SHerbert Xu .cra_flags = CRYPTO_ALG_ASYNC, 2443aeb4c132SHerbert Xu }, 24443952f17eSLee Nipper .ivsize = AES_BLOCK_SIZE, 24453952f17eSLee Nipper .maxauthsize = SHA256_DIGEST_SIZE, 24463952f17eSLee Nipper }, 24473952f17eSLee Nipper .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP | 24483952f17eSLee Nipper DESC_HDR_SEL0_AESU | 24493952f17eSLee Nipper DESC_HDR_MODE0_AESU_CBC | 24503952f17eSLee Nipper DESC_HDR_SEL1_MDEUA | 24513952f17eSLee Nipper DESC_HDR_MODE1_MDEU_INIT | 24523952f17eSLee Nipper DESC_HDR_MODE1_MDEU_PAD | 24533952f17eSLee Nipper DESC_HDR_MODE1_MDEU_SHA256_HMAC, 24543952f17eSLee Nipper }, 2455d5e4aaefSLee Nipper { .type = CRYPTO_ALG_TYPE_AEAD, 24567405c8d7SLEROY Christophe .priority = TALITOS_CRA_PRIORITY_AEAD_HSNA, 24577405c8d7SLEROY Christophe .alg.aead = { 24587405c8d7SLEROY Christophe .base = { 24597405c8d7SLEROY Christophe .cra_name = "authenc(hmac(sha256),cbc(aes))", 24607405c8d7SLEROY Christophe .cra_driver_name = "authenc-hmac-sha256-" 24617405c8d7SLEROY Christophe "cbc-aes-talitos", 24627405c8d7SLEROY Christophe .cra_blocksize = AES_BLOCK_SIZE, 24637405c8d7SLEROY Christophe .cra_flags = CRYPTO_ALG_ASYNC, 24647405c8d7SLEROY Christophe }, 24657405c8d7SLEROY Christophe .ivsize = AES_BLOCK_SIZE, 24667405c8d7SLEROY Christophe .maxauthsize = SHA256_DIGEST_SIZE, 24677405c8d7SLEROY Christophe }, 24687405c8d7SLEROY Christophe .desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU | 24697405c8d7SLEROY Christophe DESC_HDR_SEL0_AESU | 24707405c8d7SLEROY Christophe DESC_HDR_MODE0_AESU_CBC | 24717405c8d7SLEROY Christophe DESC_HDR_SEL1_MDEUA | 24727405c8d7SLEROY Christophe DESC_HDR_MODE1_MDEU_INIT | 24737405c8d7SLEROY Christophe DESC_HDR_MODE1_MDEU_PAD | 24747405c8d7SLEROY Christophe DESC_HDR_MODE1_MDEU_SHA256_HMAC, 24757405c8d7SLEROY Christophe }, 24767405c8d7SLEROY Christophe { .type = CRYPTO_ALG_TYPE_AEAD, 2477aeb4c132SHerbert Xu .alg.aead = { 2478aeb4c132SHerbert Xu .base = { 2479aeb4c132SHerbert Xu .cra_name = "authenc(hmac(sha256)," 2480aeb4c132SHerbert Xu "cbc(des3_ede))", 2481aeb4c132SHerbert Xu .cra_driver_name = "authenc-hmac-sha256-" 2482aeb4c132SHerbert Xu "cbc-3des-talitos", 248356af8cd4SLee Nipper .cra_blocksize = DES3_EDE_BLOCK_SIZE, 2484aeb4c132SHerbert Xu .cra_flags = CRYPTO_ALG_ASYNC, 2485aeb4c132SHerbert Xu }, 24863952f17eSLee Nipper .ivsize = DES3_EDE_BLOCK_SIZE, 24873952f17eSLee Nipper .maxauthsize = SHA256_DIGEST_SIZE, 24883952f17eSLee Nipper }, 24893952f17eSLee Nipper .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP | 24903952f17eSLee Nipper DESC_HDR_SEL0_DEU | 24913952f17eSLee Nipper DESC_HDR_MODE0_DEU_CBC | 24923952f17eSLee Nipper DESC_HDR_MODE0_DEU_3DES | 24933952f17eSLee Nipper DESC_HDR_SEL1_MDEUA | 24943952f17eSLee Nipper DESC_HDR_MODE1_MDEU_INIT | 24953952f17eSLee Nipper DESC_HDR_MODE1_MDEU_PAD | 24963952f17eSLee Nipper DESC_HDR_MODE1_MDEU_SHA256_HMAC, 24973952f17eSLee Nipper }, 2498d5e4aaefSLee Nipper { .type = CRYPTO_ALG_TYPE_AEAD, 24997405c8d7SLEROY Christophe .priority = TALITOS_CRA_PRIORITY_AEAD_HSNA, 25007405c8d7SLEROY Christophe .alg.aead = { 25017405c8d7SLEROY Christophe .base = { 25027405c8d7SLEROY Christophe .cra_name = "authenc(hmac(sha256)," 25037405c8d7SLEROY Christophe "cbc(des3_ede))", 25047405c8d7SLEROY Christophe .cra_driver_name = "authenc-hmac-sha256-" 25057405c8d7SLEROY Christophe "cbc-3des-talitos", 25067405c8d7SLEROY Christophe .cra_blocksize = DES3_EDE_BLOCK_SIZE, 25077405c8d7SLEROY Christophe .cra_flags = CRYPTO_ALG_ASYNC, 25087405c8d7SLEROY Christophe }, 25097405c8d7SLEROY Christophe .ivsize = DES3_EDE_BLOCK_SIZE, 25107405c8d7SLEROY Christophe .maxauthsize = SHA256_DIGEST_SIZE, 25117405c8d7SLEROY Christophe }, 25127405c8d7SLEROY Christophe .desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU | 25137405c8d7SLEROY Christophe DESC_HDR_SEL0_DEU | 25147405c8d7SLEROY Christophe DESC_HDR_MODE0_DEU_CBC | 25157405c8d7SLEROY Christophe DESC_HDR_MODE0_DEU_3DES | 25167405c8d7SLEROY Christophe DESC_HDR_SEL1_MDEUA | 25177405c8d7SLEROY Christophe DESC_HDR_MODE1_MDEU_INIT | 25187405c8d7SLEROY Christophe DESC_HDR_MODE1_MDEU_PAD | 25197405c8d7SLEROY Christophe DESC_HDR_MODE1_MDEU_SHA256_HMAC, 25207405c8d7SLEROY Christophe }, 25217405c8d7SLEROY Christophe { .type = CRYPTO_ALG_TYPE_AEAD, 2522aeb4c132SHerbert Xu .alg.aead = { 2523aeb4c132SHerbert Xu .base = { 2524357fb605SHoria Geanta .cra_name = "authenc(hmac(sha384),cbc(aes))", 2525aeb4c132SHerbert Xu .cra_driver_name = "authenc-hmac-sha384-" 2526aeb4c132SHerbert Xu "cbc-aes-talitos", 2527357fb605SHoria Geanta .cra_blocksize = AES_BLOCK_SIZE, 2528aeb4c132SHerbert Xu .cra_flags = CRYPTO_ALG_ASYNC, 2529aeb4c132SHerbert Xu }, 2530357fb605SHoria Geanta .ivsize = AES_BLOCK_SIZE, 2531357fb605SHoria Geanta .maxauthsize = SHA384_DIGEST_SIZE, 2532357fb605SHoria Geanta }, 2533357fb605SHoria Geanta .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP | 2534357fb605SHoria Geanta DESC_HDR_SEL0_AESU | 2535357fb605SHoria Geanta DESC_HDR_MODE0_AESU_CBC | 2536357fb605SHoria Geanta DESC_HDR_SEL1_MDEUB | 2537357fb605SHoria Geanta DESC_HDR_MODE1_MDEU_INIT | 2538357fb605SHoria Geanta DESC_HDR_MODE1_MDEU_PAD | 2539357fb605SHoria Geanta DESC_HDR_MODE1_MDEUB_SHA384_HMAC, 2540357fb605SHoria Geanta }, 2541357fb605SHoria Geanta { .type = CRYPTO_ALG_TYPE_AEAD, 2542aeb4c132SHerbert Xu .alg.aead = { 2543aeb4c132SHerbert Xu .base = { 2544aeb4c132SHerbert Xu .cra_name = "authenc(hmac(sha384)," 2545aeb4c132SHerbert Xu "cbc(des3_ede))", 2546aeb4c132SHerbert Xu .cra_driver_name = "authenc-hmac-sha384-" 2547aeb4c132SHerbert Xu "cbc-3des-talitos", 2548357fb605SHoria Geanta .cra_blocksize = DES3_EDE_BLOCK_SIZE, 2549aeb4c132SHerbert Xu .cra_flags = CRYPTO_ALG_ASYNC, 2550aeb4c132SHerbert Xu }, 2551357fb605SHoria Geanta .ivsize = DES3_EDE_BLOCK_SIZE, 2552357fb605SHoria Geanta .maxauthsize = SHA384_DIGEST_SIZE, 2553357fb605SHoria Geanta }, 2554357fb605SHoria Geanta .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP | 2555357fb605SHoria Geanta DESC_HDR_SEL0_DEU | 2556357fb605SHoria Geanta DESC_HDR_MODE0_DEU_CBC | 2557357fb605SHoria Geanta DESC_HDR_MODE0_DEU_3DES | 2558357fb605SHoria Geanta DESC_HDR_SEL1_MDEUB | 2559357fb605SHoria Geanta DESC_HDR_MODE1_MDEU_INIT | 2560357fb605SHoria Geanta DESC_HDR_MODE1_MDEU_PAD | 2561357fb605SHoria Geanta DESC_HDR_MODE1_MDEUB_SHA384_HMAC, 2562357fb605SHoria Geanta }, 2563357fb605SHoria Geanta { .type = CRYPTO_ALG_TYPE_AEAD, 2564aeb4c132SHerbert Xu .alg.aead = { 2565aeb4c132SHerbert Xu .base = { 2566357fb605SHoria Geanta .cra_name = "authenc(hmac(sha512),cbc(aes))", 2567aeb4c132SHerbert Xu .cra_driver_name = "authenc-hmac-sha512-" 2568aeb4c132SHerbert Xu "cbc-aes-talitos", 2569357fb605SHoria Geanta .cra_blocksize = AES_BLOCK_SIZE, 2570aeb4c132SHerbert Xu .cra_flags = CRYPTO_ALG_ASYNC, 2571aeb4c132SHerbert Xu }, 2572357fb605SHoria Geanta .ivsize = AES_BLOCK_SIZE, 2573357fb605SHoria Geanta .maxauthsize = SHA512_DIGEST_SIZE, 2574357fb605SHoria Geanta }, 2575357fb605SHoria Geanta .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP | 2576357fb605SHoria Geanta DESC_HDR_SEL0_AESU | 2577357fb605SHoria Geanta DESC_HDR_MODE0_AESU_CBC | 2578357fb605SHoria Geanta DESC_HDR_SEL1_MDEUB | 2579357fb605SHoria Geanta DESC_HDR_MODE1_MDEU_INIT | 2580357fb605SHoria Geanta DESC_HDR_MODE1_MDEU_PAD | 2581357fb605SHoria Geanta DESC_HDR_MODE1_MDEUB_SHA512_HMAC, 2582357fb605SHoria Geanta }, 2583357fb605SHoria Geanta { .type = CRYPTO_ALG_TYPE_AEAD, 2584aeb4c132SHerbert Xu .alg.aead = { 2585aeb4c132SHerbert Xu .base = { 2586aeb4c132SHerbert Xu .cra_name = "authenc(hmac(sha512)," 2587aeb4c132SHerbert Xu "cbc(des3_ede))", 2588aeb4c132SHerbert Xu .cra_driver_name = "authenc-hmac-sha512-" 2589aeb4c132SHerbert Xu "cbc-3des-talitos", 2590357fb605SHoria Geanta .cra_blocksize = DES3_EDE_BLOCK_SIZE, 2591aeb4c132SHerbert Xu .cra_flags = CRYPTO_ALG_ASYNC, 2592aeb4c132SHerbert Xu }, 2593357fb605SHoria Geanta .ivsize = DES3_EDE_BLOCK_SIZE, 2594357fb605SHoria Geanta .maxauthsize = SHA512_DIGEST_SIZE, 2595357fb605SHoria Geanta }, 2596357fb605SHoria Geanta .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP | 2597357fb605SHoria Geanta DESC_HDR_SEL0_DEU | 2598357fb605SHoria Geanta DESC_HDR_MODE0_DEU_CBC | 2599357fb605SHoria Geanta DESC_HDR_MODE0_DEU_3DES | 2600357fb605SHoria Geanta DESC_HDR_SEL1_MDEUB | 2601357fb605SHoria Geanta DESC_HDR_MODE1_MDEU_INIT | 2602357fb605SHoria Geanta DESC_HDR_MODE1_MDEU_PAD | 2603357fb605SHoria Geanta DESC_HDR_MODE1_MDEUB_SHA512_HMAC, 2604357fb605SHoria Geanta }, 2605357fb605SHoria Geanta { .type = CRYPTO_ALG_TYPE_AEAD, 2606aeb4c132SHerbert Xu .alg.aead = { 2607aeb4c132SHerbert Xu .base = { 260856af8cd4SLee Nipper .cra_name = "authenc(hmac(md5),cbc(aes))", 2609aeb4c132SHerbert Xu .cra_driver_name = "authenc-hmac-md5-" 2610aeb4c132SHerbert Xu "cbc-aes-talitos", 261156af8cd4SLee Nipper .cra_blocksize = AES_BLOCK_SIZE, 2612aeb4c132SHerbert Xu .cra_flags = CRYPTO_ALG_ASYNC, 2613aeb4c132SHerbert Xu }, 26143952f17eSLee Nipper .ivsize = AES_BLOCK_SIZE, 26153952f17eSLee Nipper .maxauthsize = MD5_DIGEST_SIZE, 26163952f17eSLee Nipper }, 26173952f17eSLee Nipper .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP | 26183952f17eSLee Nipper DESC_HDR_SEL0_AESU | 26193952f17eSLee Nipper DESC_HDR_MODE0_AESU_CBC | 26203952f17eSLee Nipper DESC_HDR_SEL1_MDEUA | 26213952f17eSLee Nipper DESC_HDR_MODE1_MDEU_INIT | 26223952f17eSLee Nipper DESC_HDR_MODE1_MDEU_PAD | 26233952f17eSLee Nipper DESC_HDR_MODE1_MDEU_MD5_HMAC, 26243952f17eSLee Nipper }, 2625d5e4aaefSLee Nipper { .type = CRYPTO_ALG_TYPE_AEAD, 26267405c8d7SLEROY Christophe .priority = TALITOS_CRA_PRIORITY_AEAD_HSNA, 26277405c8d7SLEROY Christophe .alg.aead = { 26287405c8d7SLEROY Christophe .base = { 26297405c8d7SLEROY Christophe .cra_name = "authenc(hmac(md5),cbc(aes))", 26307405c8d7SLEROY Christophe .cra_driver_name = "authenc-hmac-md5-" 26317405c8d7SLEROY Christophe "cbc-aes-talitos", 26327405c8d7SLEROY Christophe .cra_blocksize = AES_BLOCK_SIZE, 26337405c8d7SLEROY Christophe .cra_flags = CRYPTO_ALG_ASYNC, 26347405c8d7SLEROY Christophe }, 26357405c8d7SLEROY Christophe .ivsize = AES_BLOCK_SIZE, 26367405c8d7SLEROY Christophe .maxauthsize = MD5_DIGEST_SIZE, 26377405c8d7SLEROY Christophe }, 26387405c8d7SLEROY Christophe .desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU | 26397405c8d7SLEROY Christophe DESC_HDR_SEL0_AESU | 26407405c8d7SLEROY Christophe DESC_HDR_MODE0_AESU_CBC | 26417405c8d7SLEROY Christophe DESC_HDR_SEL1_MDEUA | 26427405c8d7SLEROY Christophe DESC_HDR_MODE1_MDEU_INIT | 26437405c8d7SLEROY Christophe DESC_HDR_MODE1_MDEU_PAD | 26447405c8d7SLEROY Christophe DESC_HDR_MODE1_MDEU_MD5_HMAC, 26457405c8d7SLEROY Christophe }, 26467405c8d7SLEROY Christophe { .type = CRYPTO_ALG_TYPE_AEAD, 2647aeb4c132SHerbert Xu .alg.aead = { 2648aeb4c132SHerbert Xu .base = { 264956af8cd4SLee Nipper .cra_name = "authenc(hmac(md5),cbc(des3_ede))", 2650aeb4c132SHerbert Xu .cra_driver_name = "authenc-hmac-md5-" 2651aeb4c132SHerbert Xu "cbc-3des-talitos", 265256af8cd4SLee Nipper .cra_blocksize = DES3_EDE_BLOCK_SIZE, 2653aeb4c132SHerbert Xu .cra_flags = CRYPTO_ALG_ASYNC, 2654aeb4c132SHerbert Xu }, 26553952f17eSLee Nipper .ivsize = DES3_EDE_BLOCK_SIZE, 26563952f17eSLee Nipper .maxauthsize = MD5_DIGEST_SIZE, 26573952f17eSLee Nipper }, 26583952f17eSLee Nipper .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP | 26593952f17eSLee Nipper DESC_HDR_SEL0_DEU | 26603952f17eSLee Nipper DESC_HDR_MODE0_DEU_CBC | 26613952f17eSLee Nipper DESC_HDR_MODE0_DEU_3DES | 26623952f17eSLee Nipper DESC_HDR_SEL1_MDEUA | 26633952f17eSLee Nipper DESC_HDR_MODE1_MDEU_INIT | 26643952f17eSLee Nipper DESC_HDR_MODE1_MDEU_PAD | 26653952f17eSLee Nipper DESC_HDR_MODE1_MDEU_MD5_HMAC, 26664de9d0b5SLee Nipper }, 26677405c8d7SLEROY Christophe { .type = CRYPTO_ALG_TYPE_AEAD, 26687405c8d7SLEROY Christophe .priority = TALITOS_CRA_PRIORITY_AEAD_HSNA, 26697405c8d7SLEROY Christophe .alg.aead = { 26707405c8d7SLEROY Christophe .base = { 26717405c8d7SLEROY Christophe .cra_name = "authenc(hmac(md5),cbc(des3_ede))", 26727405c8d7SLEROY Christophe .cra_driver_name = "authenc-hmac-md5-" 26737405c8d7SLEROY Christophe "cbc-3des-talitos", 26747405c8d7SLEROY Christophe .cra_blocksize = DES3_EDE_BLOCK_SIZE, 26757405c8d7SLEROY Christophe .cra_flags = CRYPTO_ALG_ASYNC, 26767405c8d7SLEROY Christophe }, 26777405c8d7SLEROY Christophe .ivsize = DES3_EDE_BLOCK_SIZE, 26787405c8d7SLEROY Christophe .maxauthsize = MD5_DIGEST_SIZE, 26797405c8d7SLEROY Christophe }, 26807405c8d7SLEROY Christophe .desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU | 26817405c8d7SLEROY Christophe DESC_HDR_SEL0_DEU | 26827405c8d7SLEROY Christophe DESC_HDR_MODE0_DEU_CBC | 26837405c8d7SLEROY Christophe DESC_HDR_MODE0_DEU_3DES | 26847405c8d7SLEROY Christophe DESC_HDR_SEL1_MDEUA | 26857405c8d7SLEROY Christophe DESC_HDR_MODE1_MDEU_INIT | 26867405c8d7SLEROY Christophe DESC_HDR_MODE1_MDEU_PAD | 26877405c8d7SLEROY Christophe DESC_HDR_MODE1_MDEU_MD5_HMAC, 26887405c8d7SLEROY Christophe }, 26894de9d0b5SLee Nipper /* ABLKCIPHER algorithms. */ 2690d5e4aaefSLee Nipper { .type = CRYPTO_ALG_TYPE_ABLKCIPHER, 2691d5e4aaefSLee Nipper .alg.crypto = { 26925e75ae1bSLEROY Christophe .cra_name = "ecb(aes)", 26935e75ae1bSLEROY Christophe .cra_driver_name = "ecb-aes-talitos", 26945e75ae1bSLEROY Christophe .cra_blocksize = AES_BLOCK_SIZE, 26955e75ae1bSLEROY Christophe .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | 26965e75ae1bSLEROY Christophe CRYPTO_ALG_ASYNC, 26975e75ae1bSLEROY Christophe .cra_ablkcipher = { 26985e75ae1bSLEROY Christophe .min_keysize = AES_MIN_KEY_SIZE, 26995e75ae1bSLEROY Christophe .max_keysize = AES_MAX_KEY_SIZE, 27005e75ae1bSLEROY Christophe .ivsize = AES_BLOCK_SIZE, 27015e75ae1bSLEROY Christophe } 27025e75ae1bSLEROY Christophe }, 27035e75ae1bSLEROY Christophe .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | 27045e75ae1bSLEROY Christophe DESC_HDR_SEL0_AESU, 27055e75ae1bSLEROY Christophe }, 27065e75ae1bSLEROY Christophe { .type = CRYPTO_ALG_TYPE_ABLKCIPHER, 27075e75ae1bSLEROY Christophe .alg.crypto = { 27084de9d0b5SLee Nipper .cra_name = "cbc(aes)", 27094de9d0b5SLee Nipper .cra_driver_name = "cbc-aes-talitos", 27104de9d0b5SLee Nipper .cra_blocksize = AES_BLOCK_SIZE, 27114de9d0b5SLee Nipper .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | 27124de9d0b5SLee Nipper CRYPTO_ALG_ASYNC, 27134de9d0b5SLee Nipper .cra_ablkcipher = { 27144de9d0b5SLee Nipper .min_keysize = AES_MIN_KEY_SIZE, 27154de9d0b5SLee Nipper .max_keysize = AES_MAX_KEY_SIZE, 27164de9d0b5SLee Nipper .ivsize = AES_BLOCK_SIZE, 27174de9d0b5SLee Nipper } 27184de9d0b5SLee Nipper }, 27194de9d0b5SLee Nipper .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | 27204de9d0b5SLee Nipper DESC_HDR_SEL0_AESU | 27214de9d0b5SLee Nipper DESC_HDR_MODE0_AESU_CBC, 27224de9d0b5SLee Nipper }, 2723d5e4aaefSLee Nipper { .type = CRYPTO_ALG_TYPE_ABLKCIPHER, 2724d5e4aaefSLee Nipper .alg.crypto = { 27255e75ae1bSLEROY Christophe .cra_name = "ctr(aes)", 27265e75ae1bSLEROY Christophe .cra_driver_name = "ctr-aes-talitos", 27275e75ae1bSLEROY Christophe .cra_blocksize = AES_BLOCK_SIZE, 27285e75ae1bSLEROY Christophe .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | 27295e75ae1bSLEROY Christophe CRYPTO_ALG_ASYNC, 27305e75ae1bSLEROY Christophe .cra_ablkcipher = { 27315e75ae1bSLEROY Christophe .min_keysize = AES_MIN_KEY_SIZE, 27325e75ae1bSLEROY Christophe .max_keysize = AES_MAX_KEY_SIZE, 27335e75ae1bSLEROY Christophe .ivsize = AES_BLOCK_SIZE, 27345e75ae1bSLEROY Christophe } 27355e75ae1bSLEROY Christophe }, 273670d355ccSLEROY Christophe .desc_hdr_template = DESC_HDR_TYPE_AESU_CTR_NONSNOOP | 27375e75ae1bSLEROY Christophe DESC_HDR_SEL0_AESU | 27385e75ae1bSLEROY Christophe DESC_HDR_MODE0_AESU_CTR, 27395e75ae1bSLEROY Christophe }, 27405e75ae1bSLEROY Christophe { .type = CRYPTO_ALG_TYPE_ABLKCIPHER, 27415e75ae1bSLEROY Christophe .alg.crypto = { 27425e75ae1bSLEROY Christophe .cra_name = "ecb(des)", 27435e75ae1bSLEROY Christophe .cra_driver_name = "ecb-des-talitos", 27445e75ae1bSLEROY Christophe .cra_blocksize = DES_BLOCK_SIZE, 27455e75ae1bSLEROY Christophe .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | 27465e75ae1bSLEROY Christophe CRYPTO_ALG_ASYNC, 27475e75ae1bSLEROY Christophe .cra_ablkcipher = { 27485e75ae1bSLEROY Christophe .min_keysize = DES_KEY_SIZE, 27495e75ae1bSLEROY Christophe .max_keysize = DES_KEY_SIZE, 27505e75ae1bSLEROY Christophe .ivsize = DES_BLOCK_SIZE, 27515e75ae1bSLEROY Christophe } 27525e75ae1bSLEROY Christophe }, 27535e75ae1bSLEROY Christophe .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | 27545e75ae1bSLEROY Christophe DESC_HDR_SEL0_DEU, 27555e75ae1bSLEROY Christophe }, 27565e75ae1bSLEROY Christophe { .type = CRYPTO_ALG_TYPE_ABLKCIPHER, 27575e75ae1bSLEROY Christophe .alg.crypto = { 27585e75ae1bSLEROY Christophe .cra_name = "cbc(des)", 27595e75ae1bSLEROY Christophe .cra_driver_name = "cbc-des-talitos", 27605e75ae1bSLEROY Christophe .cra_blocksize = DES_BLOCK_SIZE, 27615e75ae1bSLEROY Christophe .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | 27625e75ae1bSLEROY Christophe CRYPTO_ALG_ASYNC, 27635e75ae1bSLEROY Christophe .cra_ablkcipher = { 27645e75ae1bSLEROY Christophe .min_keysize = DES_KEY_SIZE, 27655e75ae1bSLEROY Christophe .max_keysize = DES_KEY_SIZE, 27665e75ae1bSLEROY Christophe .ivsize = DES_BLOCK_SIZE, 27675e75ae1bSLEROY Christophe } 27685e75ae1bSLEROY Christophe }, 27695e75ae1bSLEROY Christophe .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | 27705e75ae1bSLEROY Christophe DESC_HDR_SEL0_DEU | 27715e75ae1bSLEROY Christophe DESC_HDR_MODE0_DEU_CBC, 27725e75ae1bSLEROY Christophe }, 27735e75ae1bSLEROY Christophe { .type = CRYPTO_ALG_TYPE_ABLKCIPHER, 27745e75ae1bSLEROY Christophe .alg.crypto = { 27755e75ae1bSLEROY Christophe .cra_name = "ecb(des3_ede)", 27765e75ae1bSLEROY Christophe .cra_driver_name = "ecb-3des-talitos", 27775e75ae1bSLEROY Christophe .cra_blocksize = DES3_EDE_BLOCK_SIZE, 27785e75ae1bSLEROY Christophe .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | 27795e75ae1bSLEROY Christophe CRYPTO_ALG_ASYNC, 27805e75ae1bSLEROY Christophe .cra_ablkcipher = { 27815e75ae1bSLEROY Christophe .min_keysize = DES3_EDE_KEY_SIZE, 27825e75ae1bSLEROY Christophe .max_keysize = DES3_EDE_KEY_SIZE, 27835e75ae1bSLEROY Christophe .ivsize = DES3_EDE_BLOCK_SIZE, 27845e75ae1bSLEROY Christophe } 27855e75ae1bSLEROY Christophe }, 27865e75ae1bSLEROY Christophe .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | 27875e75ae1bSLEROY Christophe DESC_HDR_SEL0_DEU | 27885e75ae1bSLEROY Christophe DESC_HDR_MODE0_DEU_3DES, 27895e75ae1bSLEROY Christophe }, 27905e75ae1bSLEROY Christophe { .type = CRYPTO_ALG_TYPE_ABLKCIPHER, 27915e75ae1bSLEROY Christophe .alg.crypto = { 27924de9d0b5SLee Nipper .cra_name = "cbc(des3_ede)", 27934de9d0b5SLee Nipper .cra_driver_name = "cbc-3des-talitos", 27944de9d0b5SLee Nipper .cra_blocksize = DES3_EDE_BLOCK_SIZE, 27954de9d0b5SLee Nipper .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | 27964de9d0b5SLee Nipper CRYPTO_ALG_ASYNC, 27974de9d0b5SLee Nipper .cra_ablkcipher = { 27984de9d0b5SLee Nipper .min_keysize = DES3_EDE_KEY_SIZE, 27994de9d0b5SLee Nipper .max_keysize = DES3_EDE_KEY_SIZE, 28004de9d0b5SLee Nipper .ivsize = DES3_EDE_BLOCK_SIZE, 28014de9d0b5SLee Nipper } 28024de9d0b5SLee Nipper }, 28034de9d0b5SLee Nipper .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | 28044de9d0b5SLee Nipper DESC_HDR_SEL0_DEU | 28054de9d0b5SLee Nipper DESC_HDR_MODE0_DEU_CBC | 28064de9d0b5SLee Nipper DESC_HDR_MODE0_DEU_3DES, 2807497f2e6bSLee Nipper }, 2808497f2e6bSLee Nipper /* AHASH algorithms. */ 2809497f2e6bSLee Nipper { .type = CRYPTO_ALG_TYPE_AHASH, 2810497f2e6bSLee Nipper .alg.hash = { 2811497f2e6bSLee Nipper .halg.digestsize = MD5_DIGEST_SIZE, 28123639ca84SHoria Geant? .halg.statesize = sizeof(struct talitos_export_state), 2813497f2e6bSLee Nipper .halg.base = { 2814497f2e6bSLee Nipper .cra_name = "md5", 2815497f2e6bSLee Nipper .cra_driver_name = "md5-talitos", 2816b3988618SMartin Hicks .cra_blocksize = MD5_HMAC_BLOCK_SIZE, 28176a38f622SEric Biggers .cra_flags = CRYPTO_ALG_ASYNC, 28189c4a7965SKim Phillips } 2819497f2e6bSLee Nipper }, 2820497f2e6bSLee Nipper .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | 2821497f2e6bSLee Nipper DESC_HDR_SEL0_MDEUA | 2822497f2e6bSLee Nipper DESC_HDR_MODE0_MDEU_MD5, 2823497f2e6bSLee Nipper }, 2824497f2e6bSLee Nipper { .type = CRYPTO_ALG_TYPE_AHASH, 2825497f2e6bSLee Nipper .alg.hash = { 2826497f2e6bSLee Nipper .halg.digestsize = SHA1_DIGEST_SIZE, 28273639ca84SHoria Geant? .halg.statesize = sizeof(struct talitos_export_state), 2828497f2e6bSLee Nipper .halg.base = { 2829497f2e6bSLee Nipper .cra_name = "sha1", 2830497f2e6bSLee Nipper .cra_driver_name = "sha1-talitos", 2831497f2e6bSLee Nipper .cra_blocksize = SHA1_BLOCK_SIZE, 28326a38f622SEric Biggers .cra_flags = CRYPTO_ALG_ASYNC, 2833497f2e6bSLee Nipper } 2834497f2e6bSLee Nipper }, 2835497f2e6bSLee Nipper .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | 2836497f2e6bSLee Nipper DESC_HDR_SEL0_MDEUA | 2837497f2e6bSLee Nipper DESC_HDR_MODE0_MDEU_SHA1, 2838497f2e6bSLee Nipper }, 2839497f2e6bSLee Nipper { .type = CRYPTO_ALG_TYPE_AHASH, 2840497f2e6bSLee Nipper .alg.hash = { 284160f208d7SKim Phillips .halg.digestsize = SHA224_DIGEST_SIZE, 28423639ca84SHoria Geant? .halg.statesize = sizeof(struct talitos_export_state), 284360f208d7SKim Phillips .halg.base = { 284460f208d7SKim Phillips .cra_name = "sha224", 284560f208d7SKim Phillips .cra_driver_name = "sha224-talitos", 284660f208d7SKim Phillips .cra_blocksize = SHA224_BLOCK_SIZE, 28476a38f622SEric Biggers .cra_flags = CRYPTO_ALG_ASYNC, 284860f208d7SKim Phillips } 284960f208d7SKim Phillips }, 285060f208d7SKim Phillips .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | 285160f208d7SKim Phillips DESC_HDR_SEL0_MDEUA | 285260f208d7SKim Phillips DESC_HDR_MODE0_MDEU_SHA224, 285360f208d7SKim Phillips }, 285460f208d7SKim Phillips { .type = CRYPTO_ALG_TYPE_AHASH, 285560f208d7SKim Phillips .alg.hash = { 2856497f2e6bSLee Nipper .halg.digestsize = SHA256_DIGEST_SIZE, 28573639ca84SHoria Geant? .halg.statesize = sizeof(struct talitos_export_state), 2858497f2e6bSLee Nipper .halg.base = { 2859497f2e6bSLee Nipper .cra_name = "sha256", 2860497f2e6bSLee Nipper .cra_driver_name = "sha256-talitos", 2861497f2e6bSLee Nipper .cra_blocksize = SHA256_BLOCK_SIZE, 28626a38f622SEric Biggers .cra_flags = CRYPTO_ALG_ASYNC, 2863497f2e6bSLee Nipper } 2864497f2e6bSLee Nipper }, 2865497f2e6bSLee Nipper .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | 2866497f2e6bSLee Nipper DESC_HDR_SEL0_MDEUA | 2867497f2e6bSLee Nipper DESC_HDR_MODE0_MDEU_SHA256, 2868497f2e6bSLee Nipper }, 2869497f2e6bSLee Nipper { .type = CRYPTO_ALG_TYPE_AHASH, 2870497f2e6bSLee Nipper .alg.hash = { 2871497f2e6bSLee Nipper .halg.digestsize = SHA384_DIGEST_SIZE, 28723639ca84SHoria Geant? .halg.statesize = sizeof(struct talitos_export_state), 2873497f2e6bSLee Nipper .halg.base = { 2874497f2e6bSLee Nipper .cra_name = "sha384", 2875497f2e6bSLee Nipper .cra_driver_name = "sha384-talitos", 2876497f2e6bSLee Nipper .cra_blocksize = SHA384_BLOCK_SIZE, 28776a38f622SEric Biggers .cra_flags = CRYPTO_ALG_ASYNC, 2878497f2e6bSLee Nipper } 2879497f2e6bSLee Nipper }, 2880497f2e6bSLee Nipper .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | 2881497f2e6bSLee Nipper DESC_HDR_SEL0_MDEUB | 2882497f2e6bSLee Nipper DESC_HDR_MODE0_MDEUB_SHA384, 2883497f2e6bSLee Nipper }, 2884497f2e6bSLee Nipper { .type = CRYPTO_ALG_TYPE_AHASH, 2885497f2e6bSLee Nipper .alg.hash = { 2886497f2e6bSLee Nipper .halg.digestsize = SHA512_DIGEST_SIZE, 28873639ca84SHoria Geant? .halg.statesize = sizeof(struct talitos_export_state), 2888497f2e6bSLee Nipper .halg.base = { 2889497f2e6bSLee Nipper .cra_name = "sha512", 2890497f2e6bSLee Nipper .cra_driver_name = "sha512-talitos", 2891497f2e6bSLee Nipper .cra_blocksize = SHA512_BLOCK_SIZE, 28926a38f622SEric Biggers .cra_flags = CRYPTO_ALG_ASYNC, 2893497f2e6bSLee Nipper } 2894497f2e6bSLee Nipper }, 2895497f2e6bSLee Nipper .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | 2896497f2e6bSLee Nipper DESC_HDR_SEL0_MDEUB | 2897497f2e6bSLee Nipper DESC_HDR_MODE0_MDEUB_SHA512, 2898497f2e6bSLee Nipper }, 289979b3a418SLee Nipper { .type = CRYPTO_ALG_TYPE_AHASH, 290079b3a418SLee Nipper .alg.hash = { 290179b3a418SLee Nipper .halg.digestsize = MD5_DIGEST_SIZE, 29023639ca84SHoria Geant? .halg.statesize = sizeof(struct talitos_export_state), 290379b3a418SLee Nipper .halg.base = { 290479b3a418SLee Nipper .cra_name = "hmac(md5)", 290579b3a418SLee Nipper .cra_driver_name = "hmac-md5-talitos", 2906b3988618SMartin Hicks .cra_blocksize = MD5_HMAC_BLOCK_SIZE, 29076a38f622SEric Biggers .cra_flags = CRYPTO_ALG_ASYNC, 290879b3a418SLee Nipper } 290979b3a418SLee Nipper }, 291079b3a418SLee Nipper .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | 291179b3a418SLee Nipper DESC_HDR_SEL0_MDEUA | 291279b3a418SLee Nipper DESC_HDR_MODE0_MDEU_MD5, 291379b3a418SLee Nipper }, 291479b3a418SLee Nipper { .type = CRYPTO_ALG_TYPE_AHASH, 291579b3a418SLee Nipper .alg.hash = { 291679b3a418SLee Nipper .halg.digestsize = SHA1_DIGEST_SIZE, 29173639ca84SHoria Geant? .halg.statesize = sizeof(struct talitos_export_state), 291879b3a418SLee Nipper .halg.base = { 291979b3a418SLee Nipper .cra_name = "hmac(sha1)", 292079b3a418SLee Nipper .cra_driver_name = "hmac-sha1-talitos", 292179b3a418SLee Nipper .cra_blocksize = SHA1_BLOCK_SIZE, 29226a38f622SEric Biggers .cra_flags = CRYPTO_ALG_ASYNC, 292379b3a418SLee Nipper } 292479b3a418SLee Nipper }, 292579b3a418SLee Nipper .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | 292679b3a418SLee Nipper DESC_HDR_SEL0_MDEUA | 292779b3a418SLee Nipper DESC_HDR_MODE0_MDEU_SHA1, 292879b3a418SLee Nipper }, 292979b3a418SLee Nipper { .type = CRYPTO_ALG_TYPE_AHASH, 293079b3a418SLee Nipper .alg.hash = { 293179b3a418SLee Nipper .halg.digestsize = SHA224_DIGEST_SIZE, 29323639ca84SHoria Geant? .halg.statesize = sizeof(struct talitos_export_state), 293379b3a418SLee Nipper .halg.base = { 293479b3a418SLee Nipper .cra_name = "hmac(sha224)", 293579b3a418SLee Nipper .cra_driver_name = "hmac-sha224-talitos", 293679b3a418SLee Nipper .cra_blocksize = SHA224_BLOCK_SIZE, 29376a38f622SEric Biggers .cra_flags = CRYPTO_ALG_ASYNC, 293879b3a418SLee Nipper } 293979b3a418SLee Nipper }, 294079b3a418SLee Nipper .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | 294179b3a418SLee Nipper DESC_HDR_SEL0_MDEUA | 294279b3a418SLee Nipper DESC_HDR_MODE0_MDEU_SHA224, 294379b3a418SLee Nipper }, 294479b3a418SLee Nipper { .type = CRYPTO_ALG_TYPE_AHASH, 294579b3a418SLee Nipper .alg.hash = { 294679b3a418SLee Nipper .halg.digestsize = SHA256_DIGEST_SIZE, 29473639ca84SHoria Geant? .halg.statesize = sizeof(struct talitos_export_state), 294879b3a418SLee Nipper .halg.base = { 294979b3a418SLee Nipper .cra_name = "hmac(sha256)", 295079b3a418SLee Nipper .cra_driver_name = "hmac-sha256-talitos", 295179b3a418SLee Nipper .cra_blocksize = SHA256_BLOCK_SIZE, 29526a38f622SEric Biggers .cra_flags = CRYPTO_ALG_ASYNC, 295379b3a418SLee Nipper } 295479b3a418SLee Nipper }, 295579b3a418SLee Nipper .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | 295679b3a418SLee Nipper DESC_HDR_SEL0_MDEUA | 295779b3a418SLee Nipper DESC_HDR_MODE0_MDEU_SHA256, 295879b3a418SLee Nipper }, 295979b3a418SLee Nipper { .type = CRYPTO_ALG_TYPE_AHASH, 296079b3a418SLee Nipper .alg.hash = { 296179b3a418SLee Nipper .halg.digestsize = SHA384_DIGEST_SIZE, 29623639ca84SHoria Geant? .halg.statesize = sizeof(struct talitos_export_state), 296379b3a418SLee Nipper .halg.base = { 296479b3a418SLee Nipper .cra_name = "hmac(sha384)", 296579b3a418SLee Nipper .cra_driver_name = "hmac-sha384-talitos", 296679b3a418SLee Nipper .cra_blocksize = SHA384_BLOCK_SIZE, 29676a38f622SEric Biggers .cra_flags = CRYPTO_ALG_ASYNC, 296879b3a418SLee Nipper } 296979b3a418SLee Nipper }, 297079b3a418SLee Nipper .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | 297179b3a418SLee Nipper DESC_HDR_SEL0_MDEUB | 297279b3a418SLee Nipper DESC_HDR_MODE0_MDEUB_SHA384, 297379b3a418SLee Nipper }, 297479b3a418SLee Nipper { .type = CRYPTO_ALG_TYPE_AHASH, 297579b3a418SLee Nipper .alg.hash = { 297679b3a418SLee Nipper .halg.digestsize = SHA512_DIGEST_SIZE, 29773639ca84SHoria Geant? .halg.statesize = sizeof(struct talitos_export_state), 297879b3a418SLee Nipper .halg.base = { 297979b3a418SLee Nipper .cra_name = "hmac(sha512)", 298079b3a418SLee Nipper .cra_driver_name = "hmac-sha512-talitos", 298179b3a418SLee Nipper .cra_blocksize = SHA512_BLOCK_SIZE, 29826a38f622SEric Biggers .cra_flags = CRYPTO_ALG_ASYNC, 298379b3a418SLee Nipper } 298479b3a418SLee Nipper }, 298579b3a418SLee Nipper .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | 298679b3a418SLee Nipper DESC_HDR_SEL0_MDEUB | 298779b3a418SLee Nipper DESC_HDR_MODE0_MDEUB_SHA512, 298879b3a418SLee Nipper } 29899c4a7965SKim Phillips }; 29909c4a7965SKim Phillips 29919c4a7965SKim Phillips struct talitos_crypto_alg { 29929c4a7965SKim Phillips struct list_head entry; 29939c4a7965SKim Phillips struct device *dev; 2994acbf7c62SLee Nipper struct talitos_alg_template algt; 29959c4a7965SKim Phillips }; 29969c4a7965SKim Phillips 299789d124cbSJonas Eymann static int talitos_init_common(struct talitos_ctx *ctx, 299889d124cbSJonas Eymann struct talitos_crypto_alg *talitos_alg) 29999c4a7965SKim Phillips { 30005228f0f7SKim Phillips struct talitos_private *priv; 30019c4a7965SKim Phillips 30029c4a7965SKim Phillips /* update context with ptr to dev */ 30039c4a7965SKim Phillips ctx->dev = talitos_alg->dev; 300419bbbc63SKim Phillips 30055228f0f7SKim Phillips /* assign SEC channel to tfm in round-robin fashion */ 30065228f0f7SKim Phillips priv = dev_get_drvdata(ctx->dev); 30075228f0f7SKim Phillips ctx->ch = atomic_inc_return(&priv->last_chan) & 30085228f0f7SKim Phillips (priv->num_channels - 1); 30095228f0f7SKim Phillips 30109c4a7965SKim Phillips /* copy descriptor header template value */ 3011acbf7c62SLee Nipper ctx->desc_hdr_template = talitos_alg->algt.desc_hdr_template; 30129c4a7965SKim Phillips 3013602dba5aSKim Phillips /* select done notification */ 3014602dba5aSKim Phillips ctx->desc_hdr_template |= DESC_HDR_DONE_NOTIFY; 3015602dba5aSKim Phillips 3016497f2e6bSLee Nipper return 0; 3017497f2e6bSLee Nipper } 3018497f2e6bSLee Nipper 301989d124cbSJonas Eymann static int talitos_cra_init(struct crypto_tfm *tfm) 302089d124cbSJonas Eymann { 302189d124cbSJonas Eymann struct crypto_alg *alg = tfm->__crt_alg; 302289d124cbSJonas Eymann struct talitos_crypto_alg *talitos_alg; 302389d124cbSJonas Eymann struct talitos_ctx *ctx = crypto_tfm_ctx(tfm); 302489d124cbSJonas Eymann 302589d124cbSJonas Eymann if ((alg->cra_flags & CRYPTO_ALG_TYPE_MASK) == CRYPTO_ALG_TYPE_AHASH) 302689d124cbSJonas Eymann talitos_alg = container_of(__crypto_ahash_alg(alg), 302789d124cbSJonas Eymann struct talitos_crypto_alg, 302889d124cbSJonas Eymann algt.alg.hash); 302989d124cbSJonas Eymann else 303089d124cbSJonas Eymann talitos_alg = container_of(alg, struct talitos_crypto_alg, 303189d124cbSJonas Eymann algt.alg.crypto); 303289d124cbSJonas Eymann 303389d124cbSJonas Eymann return talitos_init_common(ctx, talitos_alg); 303489d124cbSJonas Eymann } 303589d124cbSJonas Eymann 3036aeb4c132SHerbert Xu static int talitos_cra_init_aead(struct crypto_aead *tfm) 3037497f2e6bSLee Nipper { 303889d124cbSJonas Eymann struct aead_alg *alg = crypto_aead_alg(tfm); 303989d124cbSJonas Eymann struct talitos_crypto_alg *talitos_alg; 304089d124cbSJonas Eymann struct talitos_ctx *ctx = crypto_aead_ctx(tfm); 304189d124cbSJonas Eymann 304289d124cbSJonas Eymann talitos_alg = container_of(alg, struct talitos_crypto_alg, 304389d124cbSJonas Eymann algt.alg.aead); 304489d124cbSJonas Eymann 304589d124cbSJonas Eymann return talitos_init_common(ctx, talitos_alg); 30469c4a7965SKim Phillips } 30479c4a7965SKim Phillips 3048497f2e6bSLee Nipper static int talitos_cra_init_ahash(struct crypto_tfm *tfm) 3049497f2e6bSLee Nipper { 3050497f2e6bSLee Nipper struct talitos_ctx *ctx = crypto_tfm_ctx(tfm); 3051497f2e6bSLee Nipper 3052497f2e6bSLee Nipper talitos_cra_init(tfm); 3053497f2e6bSLee Nipper 3054497f2e6bSLee Nipper ctx->keylen = 0; 3055497f2e6bSLee Nipper crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm), 3056497f2e6bSLee Nipper sizeof(struct talitos_ahash_req_ctx)); 3057497f2e6bSLee Nipper 3058497f2e6bSLee Nipper return 0; 3059497f2e6bSLee Nipper } 3060497f2e6bSLee Nipper 30612e13ce08SLEROY Christophe static void talitos_cra_exit(struct crypto_tfm *tfm) 30622e13ce08SLEROY Christophe { 30632e13ce08SLEROY Christophe struct talitos_ctx *ctx = crypto_tfm_ctx(tfm); 30642e13ce08SLEROY Christophe struct device *dev = ctx->dev; 30652e13ce08SLEROY Christophe 30662e13ce08SLEROY Christophe if (ctx->keylen) 30672e13ce08SLEROY Christophe dma_unmap_single(dev, ctx->dma_key, ctx->keylen, DMA_TO_DEVICE); 30682e13ce08SLEROY Christophe } 30692e13ce08SLEROY Christophe 30709c4a7965SKim Phillips /* 30719c4a7965SKim Phillips * given the alg's descriptor header template, determine whether descriptor 30729c4a7965SKim Phillips * type and primary/secondary execution units required match the hw 30739c4a7965SKim Phillips * capabilities description provided in the device tree node. 30749c4a7965SKim Phillips */ 30759c4a7965SKim Phillips static int hw_supports(struct device *dev, __be32 desc_hdr_template) 30769c4a7965SKim Phillips { 30779c4a7965SKim Phillips struct talitos_private *priv = dev_get_drvdata(dev); 30789c4a7965SKim Phillips int ret; 30799c4a7965SKim Phillips 30809c4a7965SKim Phillips ret = (1 << DESC_TYPE(desc_hdr_template) & priv->desc_types) && 30819c4a7965SKim Phillips (1 << PRIMARY_EU(desc_hdr_template) & priv->exec_units); 30829c4a7965SKim Phillips 30839c4a7965SKim Phillips if (SECONDARY_EU(desc_hdr_template)) 30849c4a7965SKim Phillips ret = ret && (1 << SECONDARY_EU(desc_hdr_template) 30859c4a7965SKim Phillips & priv->exec_units); 30869c4a7965SKim Phillips 30879c4a7965SKim Phillips return ret; 30889c4a7965SKim Phillips } 30899c4a7965SKim Phillips 30902dc11581SGrant Likely static int talitos_remove(struct platform_device *ofdev) 30919c4a7965SKim Phillips { 30929c4a7965SKim Phillips struct device *dev = &ofdev->dev; 30939c4a7965SKim Phillips struct talitos_private *priv = dev_get_drvdata(dev); 30949c4a7965SKim Phillips struct talitos_crypto_alg *t_alg, *n; 30959c4a7965SKim Phillips int i; 30969c4a7965SKim Phillips 30979c4a7965SKim Phillips list_for_each_entry_safe(t_alg, n, &priv->alg_list, entry) { 3098acbf7c62SLee Nipper switch (t_alg->algt.type) { 3099acbf7c62SLee Nipper case CRYPTO_ALG_TYPE_ABLKCIPHER: 3100acbf7c62SLee Nipper break; 3101aeb4c132SHerbert Xu case CRYPTO_ALG_TYPE_AEAD: 3102aeb4c132SHerbert Xu crypto_unregister_aead(&t_alg->algt.alg.aead); 3103acbf7c62SLee Nipper case CRYPTO_ALG_TYPE_AHASH: 3104acbf7c62SLee Nipper crypto_unregister_ahash(&t_alg->algt.alg.hash); 3105acbf7c62SLee Nipper break; 3106acbf7c62SLee Nipper } 31079c4a7965SKim Phillips list_del(&t_alg->entry); 31089c4a7965SKim Phillips } 31099c4a7965SKim Phillips 31109c4a7965SKim Phillips if (hw_supports(dev, DESC_HDR_SEL0_RNG)) 31119c4a7965SKim Phillips talitos_unregister_rng(dev); 31129c4a7965SKim Phillips 3113c3e337f8SKim Phillips for (i = 0; i < 2; i++) 31142cdba3cfSKim Phillips if (priv->irq[i]) { 3115c3e337f8SKim Phillips free_irq(priv->irq[i], dev); 3116c3e337f8SKim Phillips irq_dispose_mapping(priv->irq[i]); 31179c4a7965SKim Phillips } 31189c4a7965SKim Phillips 3119c3e337f8SKim Phillips tasklet_kill(&priv->done_task[0]); 31202cdba3cfSKim Phillips if (priv->irq[1]) 3121c3e337f8SKim Phillips tasklet_kill(&priv->done_task[1]); 31229c4a7965SKim Phillips 31239c4a7965SKim Phillips return 0; 31249c4a7965SKim Phillips } 31259c4a7965SKim Phillips 31269c4a7965SKim Phillips static struct talitos_crypto_alg *talitos_alg_alloc(struct device *dev, 31279c4a7965SKim Phillips struct talitos_alg_template 31289c4a7965SKim Phillips *template) 31299c4a7965SKim Phillips { 313060f208d7SKim Phillips struct talitos_private *priv = dev_get_drvdata(dev); 31319c4a7965SKim Phillips struct talitos_crypto_alg *t_alg; 31329c4a7965SKim Phillips struct crypto_alg *alg; 31339c4a7965SKim Phillips 313424b92ff2SLEROY Christophe t_alg = devm_kzalloc(dev, sizeof(struct talitos_crypto_alg), 313524b92ff2SLEROY Christophe GFP_KERNEL); 31369c4a7965SKim Phillips if (!t_alg) 31379c4a7965SKim Phillips return ERR_PTR(-ENOMEM); 31389c4a7965SKim Phillips 3139acbf7c62SLee Nipper t_alg->algt = *template; 3140acbf7c62SLee Nipper 3141acbf7c62SLee Nipper switch (t_alg->algt.type) { 3142acbf7c62SLee Nipper case CRYPTO_ALG_TYPE_ABLKCIPHER: 3143497f2e6bSLee Nipper alg = &t_alg->algt.alg.crypto; 3144497f2e6bSLee Nipper alg->cra_init = talitos_cra_init; 31452e13ce08SLEROY Christophe alg->cra_exit = talitos_cra_exit; 3146d4cd3283SKim Phillips alg->cra_type = &crypto_ablkcipher_type; 3147b286e003SKim Phillips alg->cra_ablkcipher.setkey = ablkcipher_setkey; 3148b286e003SKim Phillips alg->cra_ablkcipher.encrypt = ablkcipher_encrypt; 3149b286e003SKim Phillips alg->cra_ablkcipher.decrypt = ablkcipher_decrypt; 3150497f2e6bSLee Nipper break; 3151acbf7c62SLee Nipper case CRYPTO_ALG_TYPE_AEAD: 3152aeb4c132SHerbert Xu alg = &t_alg->algt.alg.aead.base; 31532e13ce08SLEROY Christophe alg->cra_exit = talitos_cra_exit; 3154aeb4c132SHerbert Xu t_alg->algt.alg.aead.init = talitos_cra_init_aead; 3155aeb4c132SHerbert Xu t_alg->algt.alg.aead.setkey = aead_setkey; 3156aeb4c132SHerbert Xu t_alg->algt.alg.aead.encrypt = aead_encrypt; 3157aeb4c132SHerbert Xu t_alg->algt.alg.aead.decrypt = aead_decrypt; 31586cda075aSLEROY Christophe if (!(priv->features & TALITOS_FTR_SHA224_HWINIT) && 31596cda075aSLEROY Christophe !strncmp(alg->cra_name, "authenc(hmac(sha224)", 20)) { 316024b92ff2SLEROY Christophe devm_kfree(dev, t_alg); 31616cda075aSLEROY Christophe return ERR_PTR(-ENOTSUPP); 31626cda075aSLEROY Christophe } 3163acbf7c62SLee Nipper break; 3164acbf7c62SLee Nipper case CRYPTO_ALG_TYPE_AHASH: 3165acbf7c62SLee Nipper alg = &t_alg->algt.alg.hash.halg.base; 3166497f2e6bSLee Nipper alg->cra_init = talitos_cra_init_ahash; 3167ad4cd51fSLEROY Christophe alg->cra_exit = talitos_cra_exit; 3168b286e003SKim Phillips t_alg->algt.alg.hash.init = ahash_init; 3169b286e003SKim Phillips t_alg->algt.alg.hash.update = ahash_update; 3170b286e003SKim Phillips t_alg->algt.alg.hash.final = ahash_final; 3171b286e003SKim Phillips t_alg->algt.alg.hash.finup = ahash_finup; 3172b286e003SKim Phillips t_alg->algt.alg.hash.digest = ahash_digest; 317356136631SLEROY Christophe if (!strncmp(alg->cra_name, "hmac", 4)) 3174b286e003SKim Phillips t_alg->algt.alg.hash.setkey = ahash_setkey; 31753639ca84SHoria Geant? t_alg->algt.alg.hash.import = ahash_import; 31763639ca84SHoria Geant? t_alg->algt.alg.hash.export = ahash_export; 3177b286e003SKim Phillips 317879b3a418SLee Nipper if (!(priv->features & TALITOS_FTR_HMAC_OK) && 31790b2730d8SKim Phillips !strncmp(alg->cra_name, "hmac", 4)) { 318024b92ff2SLEROY Christophe devm_kfree(dev, t_alg); 318179b3a418SLee Nipper return ERR_PTR(-ENOTSUPP); 31820b2730d8SKim Phillips } 318360f208d7SKim Phillips if (!(priv->features & TALITOS_FTR_SHA224_HWINIT) && 318479b3a418SLee Nipper (!strcmp(alg->cra_name, "sha224") || 318579b3a418SLee Nipper !strcmp(alg->cra_name, "hmac(sha224)"))) { 318660f208d7SKim Phillips t_alg->algt.alg.hash.init = ahash_init_sha224_swinit; 318760f208d7SKim Phillips t_alg->algt.desc_hdr_template = 318860f208d7SKim Phillips DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | 318960f208d7SKim Phillips DESC_HDR_SEL0_MDEUA | 319060f208d7SKim Phillips DESC_HDR_MODE0_MDEU_SHA256; 319160f208d7SKim Phillips } 3192497f2e6bSLee Nipper break; 31931d11911aSKim Phillips default: 31941d11911aSKim Phillips dev_err(dev, "unknown algorithm type %d\n", t_alg->algt.type); 319524b92ff2SLEROY Christophe devm_kfree(dev, t_alg); 31961d11911aSKim Phillips return ERR_PTR(-EINVAL); 3197acbf7c62SLee Nipper } 31989c4a7965SKim Phillips 31999c4a7965SKim Phillips alg->cra_module = THIS_MODULE; 3200b0057763SLEROY Christophe if (t_alg->algt.priority) 3201b0057763SLEROY Christophe alg->cra_priority = t_alg->algt.priority; 3202b0057763SLEROY Christophe else 32039c4a7965SKim Phillips alg->cra_priority = TALITOS_CRA_PRIORITY; 32049c4a7965SKim Phillips alg->cra_alignmask = 0; 32059c4a7965SKim Phillips alg->cra_ctxsize = sizeof(struct talitos_ctx); 3206d912bb76SNikos Mavrogiannopoulos alg->cra_flags |= CRYPTO_ALG_KERN_DRIVER_ONLY; 32079c4a7965SKim Phillips 32089c4a7965SKim Phillips t_alg->dev = dev; 32099c4a7965SKim Phillips 32109c4a7965SKim Phillips return t_alg; 32119c4a7965SKim Phillips } 32129c4a7965SKim Phillips 3213c3e337f8SKim Phillips static int talitos_probe_irq(struct platform_device *ofdev) 3214c3e337f8SKim Phillips { 3215c3e337f8SKim Phillips struct device *dev = &ofdev->dev; 3216c3e337f8SKim Phillips struct device_node *np = ofdev->dev.of_node; 3217c3e337f8SKim Phillips struct talitos_private *priv = dev_get_drvdata(dev); 3218c3e337f8SKim Phillips int err; 3219dd3c0987SLEROY Christophe bool is_sec1 = has_ftr_sec1(priv); 3220c3e337f8SKim Phillips 3221c3e337f8SKim Phillips priv->irq[0] = irq_of_parse_and_map(np, 0); 32222cdba3cfSKim Phillips if (!priv->irq[0]) { 3223c3e337f8SKim Phillips dev_err(dev, "failed to map irq\n"); 3224c3e337f8SKim Phillips return -EINVAL; 3225c3e337f8SKim Phillips } 3226dd3c0987SLEROY Christophe if (is_sec1) { 3227dd3c0987SLEROY Christophe err = request_irq(priv->irq[0], talitos1_interrupt_4ch, 0, 3228dd3c0987SLEROY Christophe dev_driver_string(dev), dev); 3229dd3c0987SLEROY Christophe goto primary_out; 3230dd3c0987SLEROY Christophe } 3231c3e337f8SKim Phillips 3232c3e337f8SKim Phillips priv->irq[1] = irq_of_parse_and_map(np, 1); 3233c3e337f8SKim Phillips 3234c3e337f8SKim Phillips /* get the primary irq line */ 32352cdba3cfSKim Phillips if (!priv->irq[1]) { 3236dd3c0987SLEROY Christophe err = request_irq(priv->irq[0], talitos2_interrupt_4ch, 0, 3237c3e337f8SKim Phillips dev_driver_string(dev), dev); 3238c3e337f8SKim Phillips goto primary_out; 3239c3e337f8SKim Phillips } 3240c3e337f8SKim Phillips 3241dd3c0987SLEROY Christophe err = request_irq(priv->irq[0], talitos2_interrupt_ch0_2, 0, 3242c3e337f8SKim Phillips dev_driver_string(dev), dev); 3243c3e337f8SKim Phillips if (err) 3244c3e337f8SKim Phillips goto primary_out; 3245c3e337f8SKim Phillips 3246c3e337f8SKim Phillips /* get the secondary irq line */ 3247dd3c0987SLEROY Christophe err = request_irq(priv->irq[1], talitos2_interrupt_ch1_3, 0, 3248c3e337f8SKim Phillips dev_driver_string(dev), dev); 3249c3e337f8SKim Phillips if (err) { 3250c3e337f8SKim Phillips dev_err(dev, "failed to request secondary irq\n"); 3251c3e337f8SKim Phillips irq_dispose_mapping(priv->irq[1]); 32522cdba3cfSKim Phillips priv->irq[1] = 0; 3253c3e337f8SKim Phillips } 3254c3e337f8SKim Phillips 3255c3e337f8SKim Phillips return err; 3256c3e337f8SKim Phillips 3257c3e337f8SKim Phillips primary_out: 3258c3e337f8SKim Phillips if (err) { 3259c3e337f8SKim Phillips dev_err(dev, "failed to request primary irq\n"); 3260c3e337f8SKim Phillips irq_dispose_mapping(priv->irq[0]); 32612cdba3cfSKim Phillips priv->irq[0] = 0; 3262c3e337f8SKim Phillips } 3263c3e337f8SKim Phillips 3264c3e337f8SKim Phillips return err; 3265c3e337f8SKim Phillips } 3266c3e337f8SKim Phillips 32671c48a5c9SGrant Likely static int talitos_probe(struct platform_device *ofdev) 32689c4a7965SKim Phillips { 32699c4a7965SKim Phillips struct device *dev = &ofdev->dev; 327061c7a080SGrant Likely struct device_node *np = ofdev->dev.of_node; 32719c4a7965SKim Phillips struct talitos_private *priv; 32729c4a7965SKim Phillips int i, err; 32735fa7fa14SLEROY Christophe int stride; 3274fd5ea7f0SLEROY Christophe struct resource *res; 32759c4a7965SKim Phillips 327624b92ff2SLEROY Christophe priv = devm_kzalloc(dev, sizeof(struct talitos_private), GFP_KERNEL); 32779c4a7965SKim Phillips if (!priv) 32789c4a7965SKim Phillips return -ENOMEM; 32799c4a7965SKim Phillips 3280f3de9cb1SKevin Hao INIT_LIST_HEAD(&priv->alg_list); 3281f3de9cb1SKevin Hao 32829c4a7965SKim Phillips dev_set_drvdata(dev, priv); 32839c4a7965SKim Phillips 32849c4a7965SKim Phillips priv->ofdev = ofdev; 32859c4a7965SKim Phillips 3286511d63cbSHoria Geanta spin_lock_init(&priv->reg_lock); 3287511d63cbSHoria Geanta 3288fd5ea7f0SLEROY Christophe res = platform_get_resource(ofdev, IORESOURCE_MEM, 0); 3289fd5ea7f0SLEROY Christophe if (!res) 3290fd5ea7f0SLEROY Christophe return -ENXIO; 3291fd5ea7f0SLEROY Christophe priv->reg = devm_ioremap(dev, res->start, resource_size(res)); 32929c4a7965SKim Phillips if (!priv->reg) { 32939c4a7965SKim Phillips dev_err(dev, "failed to of_iomap\n"); 32949c4a7965SKim Phillips err = -ENOMEM; 32959c4a7965SKim Phillips goto err_out; 32969c4a7965SKim Phillips } 32979c4a7965SKim Phillips 32989c4a7965SKim Phillips /* get SEC version capabilities from device tree */ 3299fa14c6cfSLEROY Christophe of_property_read_u32(np, "fsl,num-channels", &priv->num_channels); 3300fa14c6cfSLEROY Christophe of_property_read_u32(np, "fsl,channel-fifo-len", &priv->chfifo_len); 3301fa14c6cfSLEROY Christophe of_property_read_u32(np, "fsl,exec-units-mask", &priv->exec_units); 3302fa14c6cfSLEROY Christophe of_property_read_u32(np, "fsl,descriptor-types-mask", 3303fa14c6cfSLEROY Christophe &priv->desc_types); 33049c4a7965SKim Phillips 33059c4a7965SKim Phillips if (!is_power_of_2(priv->num_channels) || !priv->chfifo_len || 33069c4a7965SKim Phillips !priv->exec_units || !priv->desc_types) { 33079c4a7965SKim Phillips dev_err(dev, "invalid property data in device tree node\n"); 33089c4a7965SKim Phillips err = -EINVAL; 33099c4a7965SKim Phillips goto err_out; 33109c4a7965SKim Phillips } 33119c4a7965SKim Phillips 3312f3c85bc1SLee Nipper if (of_device_is_compatible(np, "fsl,sec3.0")) 3313f3c85bc1SLee Nipper priv->features |= TALITOS_FTR_SRC_LINK_TBL_LEN_INCLUDES_EXTENT; 3314f3c85bc1SLee Nipper 3315fe5720e2SKim Phillips if (of_device_is_compatible(np, "fsl,sec2.1")) 331660f208d7SKim Phillips priv->features |= TALITOS_FTR_HW_AUTH_CHECK | 331779b3a418SLee Nipper TALITOS_FTR_SHA224_HWINIT | 331879b3a418SLee Nipper TALITOS_FTR_HMAC_OK; 3319fe5720e2SKim Phillips 332021590888SLEROY Christophe if (of_device_is_compatible(np, "fsl,sec1.0")) 332121590888SLEROY Christophe priv->features |= TALITOS_FTR_SEC1; 332221590888SLEROY Christophe 33235fa7fa14SLEROY Christophe if (of_device_is_compatible(np, "fsl,sec1.2")) { 33245fa7fa14SLEROY Christophe priv->reg_deu = priv->reg + TALITOS12_DEU; 33255fa7fa14SLEROY Christophe priv->reg_aesu = priv->reg + TALITOS12_AESU; 33265fa7fa14SLEROY Christophe priv->reg_mdeu = priv->reg + TALITOS12_MDEU; 33275fa7fa14SLEROY Christophe stride = TALITOS1_CH_STRIDE; 33285fa7fa14SLEROY Christophe } else if (of_device_is_compatible(np, "fsl,sec1.0")) { 33295fa7fa14SLEROY Christophe priv->reg_deu = priv->reg + TALITOS10_DEU; 33305fa7fa14SLEROY Christophe priv->reg_aesu = priv->reg + TALITOS10_AESU; 33315fa7fa14SLEROY Christophe priv->reg_mdeu = priv->reg + TALITOS10_MDEU; 33325fa7fa14SLEROY Christophe priv->reg_afeu = priv->reg + TALITOS10_AFEU; 33335fa7fa14SLEROY Christophe priv->reg_rngu = priv->reg + TALITOS10_RNGU; 33345fa7fa14SLEROY Christophe priv->reg_pkeu = priv->reg + TALITOS10_PKEU; 33355fa7fa14SLEROY Christophe stride = TALITOS1_CH_STRIDE; 33365fa7fa14SLEROY Christophe } else { 33375fa7fa14SLEROY Christophe priv->reg_deu = priv->reg + TALITOS2_DEU; 33385fa7fa14SLEROY Christophe priv->reg_aesu = priv->reg + TALITOS2_AESU; 33395fa7fa14SLEROY Christophe priv->reg_mdeu = priv->reg + TALITOS2_MDEU; 33405fa7fa14SLEROY Christophe priv->reg_afeu = priv->reg + TALITOS2_AFEU; 33415fa7fa14SLEROY Christophe priv->reg_rngu = priv->reg + TALITOS2_RNGU; 33425fa7fa14SLEROY Christophe priv->reg_pkeu = priv->reg + TALITOS2_PKEU; 33435fa7fa14SLEROY Christophe priv->reg_keu = priv->reg + TALITOS2_KEU; 33445fa7fa14SLEROY Christophe priv->reg_crcu = priv->reg + TALITOS2_CRCU; 33455fa7fa14SLEROY Christophe stride = TALITOS2_CH_STRIDE; 33465fa7fa14SLEROY Christophe } 33475fa7fa14SLEROY Christophe 3348dd3c0987SLEROY Christophe err = talitos_probe_irq(ofdev); 3349dd3c0987SLEROY Christophe if (err) 3350dd3c0987SLEROY Christophe goto err_out; 3351dd3c0987SLEROY Christophe 3352dd3c0987SLEROY Christophe if (of_device_is_compatible(np, "fsl,sec1.0")) { 33539c02e285SLEROY Christophe if (priv->num_channels == 1) 33549c02e285SLEROY Christophe tasklet_init(&priv->done_task[0], talitos1_done_ch0, 33559c02e285SLEROY Christophe (unsigned long)dev); 33569c02e285SLEROY Christophe else 3357dd3c0987SLEROY Christophe tasklet_init(&priv->done_task[0], talitos1_done_4ch, 3358dd3c0987SLEROY Christophe (unsigned long)dev); 3359dd3c0987SLEROY Christophe } else { 33609c02e285SLEROY Christophe if (priv->irq[1]) { 3361dd3c0987SLEROY Christophe tasklet_init(&priv->done_task[0], talitos2_done_ch0_2, 3362dd3c0987SLEROY Christophe (unsigned long)dev); 3363dd3c0987SLEROY Christophe tasklet_init(&priv->done_task[1], talitos2_done_ch1_3, 3364dd3c0987SLEROY Christophe (unsigned long)dev); 33659c02e285SLEROY Christophe } else if (priv->num_channels == 1) { 33669c02e285SLEROY Christophe tasklet_init(&priv->done_task[0], talitos2_done_ch0, 33679c02e285SLEROY Christophe (unsigned long)dev); 33689c02e285SLEROY Christophe } else { 33699c02e285SLEROY Christophe tasklet_init(&priv->done_task[0], talitos2_done_4ch, 33709c02e285SLEROY Christophe (unsigned long)dev); 3371dd3c0987SLEROY Christophe } 3372dd3c0987SLEROY Christophe } 3373dd3c0987SLEROY Christophe 3374a86854d0SKees Cook priv->chan = devm_kcalloc(dev, 3375a86854d0SKees Cook priv->num_channels, 3376a86854d0SKees Cook sizeof(struct talitos_channel), 3377a86854d0SKees Cook GFP_KERNEL); 33784b992628SKim Phillips if (!priv->chan) { 33794b992628SKim Phillips dev_err(dev, "failed to allocate channel management space\n"); 33809c4a7965SKim Phillips err = -ENOMEM; 33819c4a7965SKim Phillips goto err_out; 33829c4a7965SKim Phillips } 33839c4a7965SKim Phillips 3384f641ddddSMartin Hicks priv->fifo_len = roundup_pow_of_two(priv->chfifo_len); 3385f641ddddSMartin Hicks 3386c3e337f8SKim Phillips for (i = 0; i < priv->num_channels; i++) { 33875fa7fa14SLEROY Christophe priv->chan[i].reg = priv->reg + stride * (i + 1); 33882cdba3cfSKim Phillips if (!priv->irq[1] || !(i & 1)) 3389c3e337f8SKim Phillips priv->chan[i].reg += TALITOS_CH_BASE_OFFSET; 3390ad42d5fcSKim Phillips 33914b992628SKim Phillips spin_lock_init(&priv->chan[i].head_lock); 33924b992628SKim Phillips spin_lock_init(&priv->chan[i].tail_lock); 33939c4a7965SKim Phillips 3394a86854d0SKees Cook priv->chan[i].fifo = devm_kcalloc(dev, 3395a86854d0SKees Cook priv->fifo_len, 3396a86854d0SKees Cook sizeof(struct talitos_request), 3397a86854d0SKees Cook GFP_KERNEL); 33984b992628SKim Phillips if (!priv->chan[i].fifo) { 33999c4a7965SKim Phillips dev_err(dev, "failed to allocate request fifo %d\n", i); 34009c4a7965SKim Phillips err = -ENOMEM; 34019c4a7965SKim Phillips goto err_out; 34029c4a7965SKim Phillips } 34039c4a7965SKim Phillips 34044b992628SKim Phillips atomic_set(&priv->chan[i].submit_count, 34054b992628SKim Phillips -(priv->chfifo_len - 1)); 3406f641ddddSMartin Hicks } 34079c4a7965SKim Phillips 340881eb024cSKim Phillips dma_set_mask(dev, DMA_BIT_MASK(36)); 340981eb024cSKim Phillips 34109c4a7965SKim Phillips /* reset and initialize the h/w */ 34119c4a7965SKim Phillips err = init_device(dev); 34129c4a7965SKim Phillips if (err) { 34139c4a7965SKim Phillips dev_err(dev, "failed to initialize device\n"); 34149c4a7965SKim Phillips goto err_out; 34159c4a7965SKim Phillips } 34169c4a7965SKim Phillips 34179c4a7965SKim Phillips /* register the RNG, if available */ 34189c4a7965SKim Phillips if (hw_supports(dev, DESC_HDR_SEL0_RNG)) { 34199c4a7965SKim Phillips err = talitos_register_rng(dev); 34209c4a7965SKim Phillips if (err) { 34219c4a7965SKim Phillips dev_err(dev, "failed to register hwrng: %d\n", err); 34229c4a7965SKim Phillips goto err_out; 34239c4a7965SKim Phillips } else 34249c4a7965SKim Phillips dev_info(dev, "hwrng\n"); 34259c4a7965SKim Phillips } 34269c4a7965SKim Phillips 34279c4a7965SKim Phillips /* register crypto algorithms the device supports */ 34289c4a7965SKim Phillips for (i = 0; i < ARRAY_SIZE(driver_algs); i++) { 34299c4a7965SKim Phillips if (hw_supports(dev, driver_algs[i].desc_hdr_template)) { 34309c4a7965SKim Phillips struct talitos_crypto_alg *t_alg; 3431aeb4c132SHerbert Xu struct crypto_alg *alg = NULL; 34329c4a7965SKim Phillips 34339c4a7965SKim Phillips t_alg = talitos_alg_alloc(dev, &driver_algs[i]); 34349c4a7965SKim Phillips if (IS_ERR(t_alg)) { 34359c4a7965SKim Phillips err = PTR_ERR(t_alg); 34360b2730d8SKim Phillips if (err == -ENOTSUPP) 343779b3a418SLee Nipper continue; 34389c4a7965SKim Phillips goto err_out; 34399c4a7965SKim Phillips } 34409c4a7965SKim Phillips 3441acbf7c62SLee Nipper switch (t_alg->algt.type) { 3442acbf7c62SLee Nipper case CRYPTO_ALG_TYPE_ABLKCIPHER: 3443acbf7c62SLee Nipper err = crypto_register_alg( 3444acbf7c62SLee Nipper &t_alg->algt.alg.crypto); 3445aeb4c132SHerbert Xu alg = &t_alg->algt.alg.crypto; 3446acbf7c62SLee Nipper break; 3447aeb4c132SHerbert Xu 3448aeb4c132SHerbert Xu case CRYPTO_ALG_TYPE_AEAD: 3449aeb4c132SHerbert Xu err = crypto_register_aead( 3450aeb4c132SHerbert Xu &t_alg->algt.alg.aead); 3451aeb4c132SHerbert Xu alg = &t_alg->algt.alg.aead.base; 3452aeb4c132SHerbert Xu break; 3453aeb4c132SHerbert Xu 3454acbf7c62SLee Nipper case CRYPTO_ALG_TYPE_AHASH: 3455acbf7c62SLee Nipper err = crypto_register_ahash( 3456acbf7c62SLee Nipper &t_alg->algt.alg.hash); 3457aeb4c132SHerbert Xu alg = &t_alg->algt.alg.hash.halg.base; 3458acbf7c62SLee Nipper break; 3459acbf7c62SLee Nipper } 34609c4a7965SKim Phillips if (err) { 34619c4a7965SKim Phillips dev_err(dev, "%s alg registration failed\n", 3462aeb4c132SHerbert Xu alg->cra_driver_name); 346324b92ff2SLEROY Christophe devm_kfree(dev, t_alg); 3464991155baSHoria Geanta } else 34659c4a7965SKim Phillips list_add_tail(&t_alg->entry, &priv->alg_list); 34669c4a7965SKim Phillips } 34679c4a7965SKim Phillips } 34685b859b6eSKim Phillips if (!list_empty(&priv->alg_list)) 34695b859b6eSKim Phillips dev_info(dev, "%s algorithms registered in /proc/crypto\n", 34705b859b6eSKim Phillips (char *)of_get_property(np, "compatible", NULL)); 34719c4a7965SKim Phillips 34729c4a7965SKim Phillips return 0; 34739c4a7965SKim Phillips 34749c4a7965SKim Phillips err_out: 34759c4a7965SKim Phillips talitos_remove(ofdev); 34769c4a7965SKim Phillips 34779c4a7965SKim Phillips return err; 34789c4a7965SKim Phillips } 34799c4a7965SKim Phillips 34806c3f975aSMárton Németh static const struct of_device_id talitos_match[] = { 34810635b7dbSLEROY Christophe #ifdef CONFIG_CRYPTO_DEV_TALITOS1 34820635b7dbSLEROY Christophe { 34830635b7dbSLEROY Christophe .compatible = "fsl,sec1.0", 34840635b7dbSLEROY Christophe }, 34850635b7dbSLEROY Christophe #endif 34860635b7dbSLEROY Christophe #ifdef CONFIG_CRYPTO_DEV_TALITOS2 34879c4a7965SKim Phillips { 34889c4a7965SKim Phillips .compatible = "fsl,sec2.0", 34899c4a7965SKim Phillips }, 34900635b7dbSLEROY Christophe #endif 34919c4a7965SKim Phillips {}, 34929c4a7965SKim Phillips }; 34939c4a7965SKim Phillips MODULE_DEVICE_TABLE(of, talitos_match); 34949c4a7965SKim Phillips 34951c48a5c9SGrant Likely static struct platform_driver talitos_driver = { 34964018294bSGrant Likely .driver = { 34979c4a7965SKim Phillips .name = "talitos", 34984018294bSGrant Likely .of_match_table = talitos_match, 34994018294bSGrant Likely }, 35009c4a7965SKim Phillips .probe = talitos_probe, 3501596f1034SAl Viro .remove = talitos_remove, 35029c4a7965SKim Phillips }; 35039c4a7965SKim Phillips 3504741e8c2dSAxel Lin module_platform_driver(talitos_driver); 35059c4a7965SKim Phillips 35069c4a7965SKim Phillips MODULE_LICENSE("GPL"); 35079c4a7965SKim Phillips MODULE_AUTHOR("Kim Phillips <kim.phillips@freescale.com>"); 35089c4a7965SKim Phillips MODULE_DESCRIPTION("Freescale integrated security engine (SEC) driver"); 3509