162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * talitos - Freescale Integrated Security Engine (SEC) device driver 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (c) 2008-2011 Freescale Semiconductor, Inc. 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * Scatterlist Crypto API glue code copied from files with the following: 862306a36Sopenharmony_ci * Copyright (c) 2006-2007 Herbert Xu <herbert@gondor.apana.org.au> 962306a36Sopenharmony_ci * 1062306a36Sopenharmony_ci * Crypto algorithm registration code copied from hifn driver: 1162306a36Sopenharmony_ci * 2007+ Copyright (c) Evgeniy Polyakov <johnpol@2ka.mipt.ru> 1262306a36Sopenharmony_ci * All rights reserved. 1362306a36Sopenharmony_ci */ 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci#include <linux/kernel.h> 1662306a36Sopenharmony_ci#include <linux/module.h> 1762306a36Sopenharmony_ci#include <linux/mod_devicetable.h> 1862306a36Sopenharmony_ci#include <linux/device.h> 1962306a36Sopenharmony_ci#include <linux/interrupt.h> 2062306a36Sopenharmony_ci#include <linux/crypto.h> 2162306a36Sopenharmony_ci#include <linux/hw_random.h> 2262306a36Sopenharmony_ci#include <linux/of.h> 2362306a36Sopenharmony_ci#include <linux/of_irq.h> 2462306a36Sopenharmony_ci#include <linux/platform_device.h> 2562306a36Sopenharmony_ci#include <linux/dma-mapping.h> 2662306a36Sopenharmony_ci#include <linux/io.h> 2762306a36Sopenharmony_ci#include <linux/spinlock.h> 2862306a36Sopenharmony_ci#include <linux/rtnetlink.h> 2962306a36Sopenharmony_ci#include <linux/slab.h> 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ci#include <crypto/algapi.h> 3262306a36Sopenharmony_ci#include <crypto/aes.h> 3362306a36Sopenharmony_ci#include <crypto/internal/des.h> 3462306a36Sopenharmony_ci#include <crypto/sha1.h> 3562306a36Sopenharmony_ci#include <crypto/sha2.h> 3662306a36Sopenharmony_ci#include <crypto/md5.h> 3762306a36Sopenharmony_ci#include <crypto/internal/aead.h> 3862306a36Sopenharmony_ci#include <crypto/authenc.h> 3962306a36Sopenharmony_ci#include <crypto/internal/skcipher.h> 4062306a36Sopenharmony_ci#include <crypto/hash.h> 4162306a36Sopenharmony_ci#include <crypto/internal/hash.h> 4262306a36Sopenharmony_ci#include <crypto/scatterwalk.h> 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci#include "talitos.h" 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_cistatic void to_talitos_ptr(struct talitos_ptr *ptr, dma_addr_t dma_addr, 4762306a36Sopenharmony_ci unsigned int len, bool is_sec1) 4862306a36Sopenharmony_ci{ 4962306a36Sopenharmony_ci ptr->ptr = cpu_to_be32(lower_32_bits(dma_addr)); 5062306a36Sopenharmony_ci if (is_sec1) { 5162306a36Sopenharmony_ci ptr->len1 = cpu_to_be16(len); 5262306a36Sopenharmony_ci } else { 5362306a36Sopenharmony_ci ptr->len = cpu_to_be16(len); 5462306a36Sopenharmony_ci ptr->eptr = upper_32_bits(dma_addr); 5562306a36Sopenharmony_ci } 5662306a36Sopenharmony_ci} 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_cistatic void copy_talitos_ptr(struct talitos_ptr *dst_ptr, 5962306a36Sopenharmony_ci struct talitos_ptr *src_ptr, bool is_sec1) 6062306a36Sopenharmony_ci{ 6162306a36Sopenharmony_ci dst_ptr->ptr = src_ptr->ptr; 6262306a36Sopenharmony_ci if (is_sec1) { 6362306a36Sopenharmony_ci dst_ptr->len1 = src_ptr->len1; 6462306a36Sopenharmony_ci } else { 6562306a36Sopenharmony_ci dst_ptr->len = src_ptr->len; 6662306a36Sopenharmony_ci dst_ptr->eptr = src_ptr->eptr; 6762306a36Sopenharmony_ci } 6862306a36Sopenharmony_ci} 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_cistatic unsigned short from_talitos_ptr_len(struct talitos_ptr *ptr, 7162306a36Sopenharmony_ci bool is_sec1) 7262306a36Sopenharmony_ci{ 7362306a36Sopenharmony_ci if (is_sec1) 7462306a36Sopenharmony_ci return be16_to_cpu(ptr->len1); 7562306a36Sopenharmony_ci else 7662306a36Sopenharmony_ci return be16_to_cpu(ptr->len); 7762306a36Sopenharmony_ci} 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_cistatic void to_talitos_ptr_ext_set(struct talitos_ptr *ptr, u8 val, 8062306a36Sopenharmony_ci bool is_sec1) 8162306a36Sopenharmony_ci{ 8262306a36Sopenharmony_ci if (!is_sec1) 8362306a36Sopenharmony_ci ptr->j_extent = val; 8462306a36Sopenharmony_ci} 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_cistatic void to_talitos_ptr_ext_or(struct talitos_ptr *ptr, u8 val, bool is_sec1) 8762306a36Sopenharmony_ci{ 8862306a36Sopenharmony_ci if (!is_sec1) 8962306a36Sopenharmony_ci ptr->j_extent |= val; 9062306a36Sopenharmony_ci} 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_ci/* 9362306a36Sopenharmony_ci * map virtual single (contiguous) pointer to h/w descriptor pointer 9462306a36Sopenharmony_ci */ 9562306a36Sopenharmony_cistatic void __map_single_talitos_ptr(struct device *dev, 9662306a36Sopenharmony_ci struct talitos_ptr *ptr, 9762306a36Sopenharmony_ci unsigned int len, void *data, 9862306a36Sopenharmony_ci enum dma_data_direction dir, 9962306a36Sopenharmony_ci unsigned long attrs) 10062306a36Sopenharmony_ci{ 10162306a36Sopenharmony_ci dma_addr_t dma_addr = dma_map_single_attrs(dev, data, len, dir, attrs); 10262306a36Sopenharmony_ci struct talitos_private *priv = dev_get_drvdata(dev); 10362306a36Sopenharmony_ci bool is_sec1 = has_ftr_sec1(priv); 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_ci to_talitos_ptr(ptr, dma_addr, len, is_sec1); 10662306a36Sopenharmony_ci} 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_cistatic void map_single_talitos_ptr(struct device *dev, 10962306a36Sopenharmony_ci struct talitos_ptr *ptr, 11062306a36Sopenharmony_ci unsigned int len, void *data, 11162306a36Sopenharmony_ci enum dma_data_direction dir) 11262306a36Sopenharmony_ci{ 11362306a36Sopenharmony_ci __map_single_talitos_ptr(dev, ptr, len, data, dir, 0); 11462306a36Sopenharmony_ci} 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_cistatic void map_single_talitos_ptr_nosync(struct device *dev, 11762306a36Sopenharmony_ci struct talitos_ptr *ptr, 11862306a36Sopenharmony_ci unsigned int len, void *data, 11962306a36Sopenharmony_ci enum dma_data_direction dir) 12062306a36Sopenharmony_ci{ 12162306a36Sopenharmony_ci __map_single_talitos_ptr(dev, ptr, len, data, dir, 12262306a36Sopenharmony_ci DMA_ATTR_SKIP_CPU_SYNC); 12362306a36Sopenharmony_ci} 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ci/* 12662306a36Sopenharmony_ci * unmap bus single (contiguous) h/w descriptor pointer 12762306a36Sopenharmony_ci */ 12862306a36Sopenharmony_cistatic void unmap_single_talitos_ptr(struct device *dev, 12962306a36Sopenharmony_ci struct talitos_ptr *ptr, 13062306a36Sopenharmony_ci enum dma_data_direction dir) 13162306a36Sopenharmony_ci{ 13262306a36Sopenharmony_ci struct talitos_private *priv = dev_get_drvdata(dev); 13362306a36Sopenharmony_ci bool is_sec1 = has_ftr_sec1(priv); 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_ci dma_unmap_single(dev, be32_to_cpu(ptr->ptr), 13662306a36Sopenharmony_ci from_talitos_ptr_len(ptr, is_sec1), dir); 13762306a36Sopenharmony_ci} 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_cistatic int reset_channel(struct device *dev, int ch) 14062306a36Sopenharmony_ci{ 14162306a36Sopenharmony_ci struct talitos_private *priv = dev_get_drvdata(dev); 14262306a36Sopenharmony_ci unsigned int timeout = TALITOS_TIMEOUT; 14362306a36Sopenharmony_ci bool is_sec1 = has_ftr_sec1(priv); 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_ci if (is_sec1) { 14662306a36Sopenharmony_ci setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO, 14762306a36Sopenharmony_ci TALITOS1_CCCR_LO_RESET); 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_ci while ((in_be32(priv->chan[ch].reg + TALITOS_CCCR_LO) & 15062306a36Sopenharmony_ci TALITOS1_CCCR_LO_RESET) && --timeout) 15162306a36Sopenharmony_ci cpu_relax(); 15262306a36Sopenharmony_ci } else { 15362306a36Sopenharmony_ci setbits32(priv->chan[ch].reg + TALITOS_CCCR, 15462306a36Sopenharmony_ci TALITOS2_CCCR_RESET); 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ci while ((in_be32(priv->chan[ch].reg + TALITOS_CCCR) & 15762306a36Sopenharmony_ci TALITOS2_CCCR_RESET) && --timeout) 15862306a36Sopenharmony_ci cpu_relax(); 15962306a36Sopenharmony_ci } 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_ci if (timeout == 0) { 16262306a36Sopenharmony_ci dev_err(dev, "failed to reset channel %d\n", ch); 16362306a36Sopenharmony_ci return -EIO; 16462306a36Sopenharmony_ci } 16562306a36Sopenharmony_ci 16662306a36Sopenharmony_ci /* set 36-bit addressing, done writeback enable and done IRQ enable */ 16762306a36Sopenharmony_ci setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO, TALITOS_CCCR_LO_EAE | 16862306a36Sopenharmony_ci TALITOS_CCCR_LO_CDWE | TALITOS_CCCR_LO_CDIE); 16962306a36Sopenharmony_ci /* enable chaining descriptors */ 17062306a36Sopenharmony_ci if (is_sec1) 17162306a36Sopenharmony_ci setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO, 17262306a36Sopenharmony_ci TALITOS_CCCR_LO_NE); 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_ci /* and ICCR writeback, if available */ 17562306a36Sopenharmony_ci if (priv->features & TALITOS_FTR_HW_AUTH_CHECK) 17662306a36Sopenharmony_ci setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO, 17762306a36Sopenharmony_ci TALITOS_CCCR_LO_IWSE); 17862306a36Sopenharmony_ci 17962306a36Sopenharmony_ci return 0; 18062306a36Sopenharmony_ci} 18162306a36Sopenharmony_ci 18262306a36Sopenharmony_cistatic int reset_device(struct device *dev) 18362306a36Sopenharmony_ci{ 18462306a36Sopenharmony_ci struct talitos_private *priv = dev_get_drvdata(dev); 18562306a36Sopenharmony_ci unsigned int timeout = TALITOS_TIMEOUT; 18662306a36Sopenharmony_ci bool is_sec1 = has_ftr_sec1(priv); 18762306a36Sopenharmony_ci u32 mcr = is_sec1 ? TALITOS1_MCR_SWR : TALITOS2_MCR_SWR; 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_ci setbits32(priv->reg + TALITOS_MCR, mcr); 19062306a36Sopenharmony_ci 19162306a36Sopenharmony_ci while ((in_be32(priv->reg + TALITOS_MCR) & mcr) 19262306a36Sopenharmony_ci && --timeout) 19362306a36Sopenharmony_ci cpu_relax(); 19462306a36Sopenharmony_ci 19562306a36Sopenharmony_ci if (priv->irq[1]) { 19662306a36Sopenharmony_ci mcr = TALITOS_MCR_RCA1 | TALITOS_MCR_RCA3; 19762306a36Sopenharmony_ci setbits32(priv->reg + TALITOS_MCR, mcr); 19862306a36Sopenharmony_ci } 19962306a36Sopenharmony_ci 20062306a36Sopenharmony_ci if (timeout == 0) { 20162306a36Sopenharmony_ci dev_err(dev, "failed to reset device\n"); 20262306a36Sopenharmony_ci return -EIO; 20362306a36Sopenharmony_ci } 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_ci return 0; 20662306a36Sopenharmony_ci} 20762306a36Sopenharmony_ci 20862306a36Sopenharmony_ci/* 20962306a36Sopenharmony_ci * Reset and initialize the device 21062306a36Sopenharmony_ci */ 21162306a36Sopenharmony_cistatic int init_device(struct device *dev) 21262306a36Sopenharmony_ci{ 21362306a36Sopenharmony_ci struct talitos_private *priv = dev_get_drvdata(dev); 21462306a36Sopenharmony_ci int ch, err; 21562306a36Sopenharmony_ci bool is_sec1 = has_ftr_sec1(priv); 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_ci /* 21862306a36Sopenharmony_ci * Master reset 21962306a36Sopenharmony_ci * errata documentation: warning: certain SEC interrupts 22062306a36Sopenharmony_ci * are not fully cleared by writing the MCR:SWR bit, 22162306a36Sopenharmony_ci * set bit twice to completely reset 22262306a36Sopenharmony_ci */ 22362306a36Sopenharmony_ci err = reset_device(dev); 22462306a36Sopenharmony_ci if (err) 22562306a36Sopenharmony_ci return err; 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_ci err = reset_device(dev); 22862306a36Sopenharmony_ci if (err) 22962306a36Sopenharmony_ci return err; 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_ci /* reset channels */ 23262306a36Sopenharmony_ci for (ch = 0; ch < priv->num_channels; ch++) { 23362306a36Sopenharmony_ci err = reset_channel(dev, ch); 23462306a36Sopenharmony_ci if (err) 23562306a36Sopenharmony_ci return err; 23662306a36Sopenharmony_ci } 23762306a36Sopenharmony_ci 23862306a36Sopenharmony_ci /* enable channel done and error interrupts */ 23962306a36Sopenharmony_ci if (is_sec1) { 24062306a36Sopenharmony_ci clrbits32(priv->reg + TALITOS_IMR, TALITOS1_IMR_INIT); 24162306a36Sopenharmony_ci clrbits32(priv->reg + TALITOS_IMR_LO, TALITOS1_IMR_LO_INIT); 24262306a36Sopenharmony_ci /* disable parity error check in DEU (erroneous? test vect.) */ 24362306a36Sopenharmony_ci setbits32(priv->reg_deu + TALITOS_EUICR, TALITOS1_DEUICR_KPE); 24462306a36Sopenharmony_ci } else { 24562306a36Sopenharmony_ci setbits32(priv->reg + TALITOS_IMR, TALITOS2_IMR_INIT); 24662306a36Sopenharmony_ci setbits32(priv->reg + TALITOS_IMR_LO, TALITOS2_IMR_LO_INIT); 24762306a36Sopenharmony_ci } 24862306a36Sopenharmony_ci 24962306a36Sopenharmony_ci /* disable integrity check error interrupts (use writeback instead) */ 25062306a36Sopenharmony_ci if (priv->features & TALITOS_FTR_HW_AUTH_CHECK) 25162306a36Sopenharmony_ci setbits32(priv->reg_mdeu + TALITOS_EUICR_LO, 25262306a36Sopenharmony_ci TALITOS_MDEUICR_LO_ICE); 25362306a36Sopenharmony_ci 25462306a36Sopenharmony_ci return 0; 25562306a36Sopenharmony_ci} 25662306a36Sopenharmony_ci 25762306a36Sopenharmony_ci/** 25862306a36Sopenharmony_ci * talitos_submit - submits a descriptor to the device for processing 25962306a36Sopenharmony_ci * @dev: the SEC device to be used 26062306a36Sopenharmony_ci * @ch: the SEC device channel to be used 26162306a36Sopenharmony_ci * @desc: the descriptor to be processed by the device 26262306a36Sopenharmony_ci * @callback: whom to call when processing is complete 26362306a36Sopenharmony_ci * @context: a handle for use by caller (optional) 26462306a36Sopenharmony_ci * 26562306a36Sopenharmony_ci * desc must contain valid dma-mapped (bus physical) address pointers. 26662306a36Sopenharmony_ci * callback must check err and feedback in descriptor header 26762306a36Sopenharmony_ci * for device processing status. 26862306a36Sopenharmony_ci */ 26962306a36Sopenharmony_cistatic int talitos_submit(struct device *dev, int ch, struct talitos_desc *desc, 27062306a36Sopenharmony_ci void (*callback)(struct device *dev, 27162306a36Sopenharmony_ci struct talitos_desc *desc, 27262306a36Sopenharmony_ci void *context, int error), 27362306a36Sopenharmony_ci void *context) 27462306a36Sopenharmony_ci{ 27562306a36Sopenharmony_ci struct talitos_private *priv = dev_get_drvdata(dev); 27662306a36Sopenharmony_ci struct talitos_request *request; 27762306a36Sopenharmony_ci unsigned long flags; 27862306a36Sopenharmony_ci int head; 27962306a36Sopenharmony_ci bool is_sec1 = has_ftr_sec1(priv); 28062306a36Sopenharmony_ci 28162306a36Sopenharmony_ci spin_lock_irqsave(&priv->chan[ch].head_lock, flags); 28262306a36Sopenharmony_ci 28362306a36Sopenharmony_ci if (!atomic_inc_not_zero(&priv->chan[ch].submit_count)) { 28462306a36Sopenharmony_ci /* h/w fifo is full */ 28562306a36Sopenharmony_ci spin_unlock_irqrestore(&priv->chan[ch].head_lock, flags); 28662306a36Sopenharmony_ci return -EAGAIN; 28762306a36Sopenharmony_ci } 28862306a36Sopenharmony_ci 28962306a36Sopenharmony_ci head = priv->chan[ch].head; 29062306a36Sopenharmony_ci request = &priv->chan[ch].fifo[head]; 29162306a36Sopenharmony_ci 29262306a36Sopenharmony_ci /* map descriptor and save caller data */ 29362306a36Sopenharmony_ci if (is_sec1) { 29462306a36Sopenharmony_ci desc->hdr1 = desc->hdr; 29562306a36Sopenharmony_ci request->dma_desc = dma_map_single(dev, &desc->hdr1, 29662306a36Sopenharmony_ci TALITOS_DESC_SIZE, 29762306a36Sopenharmony_ci DMA_BIDIRECTIONAL); 29862306a36Sopenharmony_ci } else { 29962306a36Sopenharmony_ci request->dma_desc = dma_map_single(dev, desc, 30062306a36Sopenharmony_ci TALITOS_DESC_SIZE, 30162306a36Sopenharmony_ci DMA_BIDIRECTIONAL); 30262306a36Sopenharmony_ci } 30362306a36Sopenharmony_ci request->callback = callback; 30462306a36Sopenharmony_ci request->context = context; 30562306a36Sopenharmony_ci 30662306a36Sopenharmony_ci /* increment fifo head */ 30762306a36Sopenharmony_ci priv->chan[ch].head = (priv->chan[ch].head + 1) & (priv->fifo_len - 1); 30862306a36Sopenharmony_ci 30962306a36Sopenharmony_ci smp_wmb(); 31062306a36Sopenharmony_ci request->desc = desc; 31162306a36Sopenharmony_ci 31262306a36Sopenharmony_ci /* GO! */ 31362306a36Sopenharmony_ci wmb(); 31462306a36Sopenharmony_ci out_be32(priv->chan[ch].reg + TALITOS_FF, 31562306a36Sopenharmony_ci upper_32_bits(request->dma_desc)); 31662306a36Sopenharmony_ci out_be32(priv->chan[ch].reg + TALITOS_FF_LO, 31762306a36Sopenharmony_ci lower_32_bits(request->dma_desc)); 31862306a36Sopenharmony_ci 31962306a36Sopenharmony_ci spin_unlock_irqrestore(&priv->chan[ch].head_lock, flags); 32062306a36Sopenharmony_ci 32162306a36Sopenharmony_ci return -EINPROGRESS; 32262306a36Sopenharmony_ci} 32362306a36Sopenharmony_ci 32462306a36Sopenharmony_cistatic __be32 get_request_hdr(struct talitos_request *request, bool is_sec1) 32562306a36Sopenharmony_ci{ 32662306a36Sopenharmony_ci struct talitos_edesc *edesc; 32762306a36Sopenharmony_ci 32862306a36Sopenharmony_ci if (!is_sec1) 32962306a36Sopenharmony_ci return request->desc->hdr; 33062306a36Sopenharmony_ci 33162306a36Sopenharmony_ci if (!request->desc->next_desc) 33262306a36Sopenharmony_ci return request->desc->hdr1; 33362306a36Sopenharmony_ci 33462306a36Sopenharmony_ci edesc = container_of(request->desc, struct talitos_edesc, desc); 33562306a36Sopenharmony_ci 33662306a36Sopenharmony_ci return ((struct talitos_desc *)(edesc->buf + edesc->dma_len))->hdr1; 33762306a36Sopenharmony_ci} 33862306a36Sopenharmony_ci 33962306a36Sopenharmony_ci/* 34062306a36Sopenharmony_ci * process what was done, notify callback of error if not 34162306a36Sopenharmony_ci */ 34262306a36Sopenharmony_cistatic void flush_channel(struct device *dev, int ch, int error, int reset_ch) 34362306a36Sopenharmony_ci{ 34462306a36Sopenharmony_ci struct talitos_private *priv = dev_get_drvdata(dev); 34562306a36Sopenharmony_ci struct talitos_request *request, saved_req; 34662306a36Sopenharmony_ci unsigned long flags; 34762306a36Sopenharmony_ci int tail, status; 34862306a36Sopenharmony_ci bool is_sec1 = has_ftr_sec1(priv); 34962306a36Sopenharmony_ci 35062306a36Sopenharmony_ci spin_lock_irqsave(&priv->chan[ch].tail_lock, flags); 35162306a36Sopenharmony_ci 35262306a36Sopenharmony_ci tail = priv->chan[ch].tail; 35362306a36Sopenharmony_ci while (priv->chan[ch].fifo[tail].desc) { 35462306a36Sopenharmony_ci __be32 hdr; 35562306a36Sopenharmony_ci 35662306a36Sopenharmony_ci request = &priv->chan[ch].fifo[tail]; 35762306a36Sopenharmony_ci 35862306a36Sopenharmony_ci /* descriptors with their done bits set don't get the error */ 35962306a36Sopenharmony_ci rmb(); 36062306a36Sopenharmony_ci hdr = get_request_hdr(request, is_sec1); 36162306a36Sopenharmony_ci 36262306a36Sopenharmony_ci if ((hdr & DESC_HDR_DONE) == DESC_HDR_DONE) 36362306a36Sopenharmony_ci status = 0; 36462306a36Sopenharmony_ci else 36562306a36Sopenharmony_ci if (!error) 36662306a36Sopenharmony_ci break; 36762306a36Sopenharmony_ci else 36862306a36Sopenharmony_ci status = error; 36962306a36Sopenharmony_ci 37062306a36Sopenharmony_ci dma_unmap_single(dev, request->dma_desc, 37162306a36Sopenharmony_ci TALITOS_DESC_SIZE, 37262306a36Sopenharmony_ci DMA_BIDIRECTIONAL); 37362306a36Sopenharmony_ci 37462306a36Sopenharmony_ci /* copy entries so we can call callback outside lock */ 37562306a36Sopenharmony_ci saved_req.desc = request->desc; 37662306a36Sopenharmony_ci saved_req.callback = request->callback; 37762306a36Sopenharmony_ci saved_req.context = request->context; 37862306a36Sopenharmony_ci 37962306a36Sopenharmony_ci /* release request entry in fifo */ 38062306a36Sopenharmony_ci smp_wmb(); 38162306a36Sopenharmony_ci request->desc = NULL; 38262306a36Sopenharmony_ci 38362306a36Sopenharmony_ci /* increment fifo tail */ 38462306a36Sopenharmony_ci priv->chan[ch].tail = (tail + 1) & (priv->fifo_len - 1); 38562306a36Sopenharmony_ci 38662306a36Sopenharmony_ci spin_unlock_irqrestore(&priv->chan[ch].tail_lock, flags); 38762306a36Sopenharmony_ci 38862306a36Sopenharmony_ci atomic_dec(&priv->chan[ch].submit_count); 38962306a36Sopenharmony_ci 39062306a36Sopenharmony_ci saved_req.callback(dev, saved_req.desc, saved_req.context, 39162306a36Sopenharmony_ci status); 39262306a36Sopenharmony_ci /* channel may resume processing in single desc error case */ 39362306a36Sopenharmony_ci if (error && !reset_ch && status == error) 39462306a36Sopenharmony_ci return; 39562306a36Sopenharmony_ci spin_lock_irqsave(&priv->chan[ch].tail_lock, flags); 39662306a36Sopenharmony_ci tail = priv->chan[ch].tail; 39762306a36Sopenharmony_ci } 39862306a36Sopenharmony_ci 39962306a36Sopenharmony_ci spin_unlock_irqrestore(&priv->chan[ch].tail_lock, flags); 40062306a36Sopenharmony_ci} 40162306a36Sopenharmony_ci 40262306a36Sopenharmony_ci/* 40362306a36Sopenharmony_ci * process completed requests for channels that have done status 40462306a36Sopenharmony_ci */ 40562306a36Sopenharmony_ci#define DEF_TALITOS1_DONE(name, ch_done_mask) \ 40662306a36Sopenharmony_cistatic void talitos1_done_##name(unsigned long data) \ 40762306a36Sopenharmony_ci{ \ 40862306a36Sopenharmony_ci struct device *dev = (struct device *)data; \ 40962306a36Sopenharmony_ci struct talitos_private *priv = dev_get_drvdata(dev); \ 41062306a36Sopenharmony_ci unsigned long flags; \ 41162306a36Sopenharmony_ci \ 41262306a36Sopenharmony_ci if (ch_done_mask & 0x10000000) \ 41362306a36Sopenharmony_ci flush_channel(dev, 0, 0, 0); \ 41462306a36Sopenharmony_ci if (ch_done_mask & 0x40000000) \ 41562306a36Sopenharmony_ci flush_channel(dev, 1, 0, 0); \ 41662306a36Sopenharmony_ci if (ch_done_mask & 0x00010000) \ 41762306a36Sopenharmony_ci flush_channel(dev, 2, 0, 0); \ 41862306a36Sopenharmony_ci if (ch_done_mask & 0x00040000) \ 41962306a36Sopenharmony_ci flush_channel(dev, 3, 0, 0); \ 42062306a36Sopenharmony_ci \ 42162306a36Sopenharmony_ci /* At this point, all completed channels have been processed */ \ 42262306a36Sopenharmony_ci /* Unmask done interrupts for channels completed later on. */ \ 42362306a36Sopenharmony_ci spin_lock_irqsave(&priv->reg_lock, flags); \ 42462306a36Sopenharmony_ci clrbits32(priv->reg + TALITOS_IMR, ch_done_mask); \ 42562306a36Sopenharmony_ci clrbits32(priv->reg + TALITOS_IMR_LO, TALITOS1_IMR_LO_INIT); \ 42662306a36Sopenharmony_ci spin_unlock_irqrestore(&priv->reg_lock, flags); \ 42762306a36Sopenharmony_ci} 42862306a36Sopenharmony_ci 42962306a36Sopenharmony_ciDEF_TALITOS1_DONE(4ch, TALITOS1_ISR_4CHDONE) 43062306a36Sopenharmony_ciDEF_TALITOS1_DONE(ch0, TALITOS1_ISR_CH_0_DONE) 43162306a36Sopenharmony_ci 43262306a36Sopenharmony_ci#define DEF_TALITOS2_DONE(name, ch_done_mask) \ 43362306a36Sopenharmony_cistatic void talitos2_done_##name(unsigned long data) \ 43462306a36Sopenharmony_ci{ \ 43562306a36Sopenharmony_ci struct device *dev = (struct device *)data; \ 43662306a36Sopenharmony_ci struct talitos_private *priv = dev_get_drvdata(dev); \ 43762306a36Sopenharmony_ci unsigned long flags; \ 43862306a36Sopenharmony_ci \ 43962306a36Sopenharmony_ci if (ch_done_mask & 1) \ 44062306a36Sopenharmony_ci flush_channel(dev, 0, 0, 0); \ 44162306a36Sopenharmony_ci if (ch_done_mask & (1 << 2)) \ 44262306a36Sopenharmony_ci flush_channel(dev, 1, 0, 0); \ 44362306a36Sopenharmony_ci if (ch_done_mask & (1 << 4)) \ 44462306a36Sopenharmony_ci flush_channel(dev, 2, 0, 0); \ 44562306a36Sopenharmony_ci if (ch_done_mask & (1 << 6)) \ 44662306a36Sopenharmony_ci flush_channel(dev, 3, 0, 0); \ 44762306a36Sopenharmony_ci \ 44862306a36Sopenharmony_ci /* At this point, all completed channels have been processed */ \ 44962306a36Sopenharmony_ci /* Unmask done interrupts for channels completed later on. */ \ 45062306a36Sopenharmony_ci spin_lock_irqsave(&priv->reg_lock, flags); \ 45162306a36Sopenharmony_ci setbits32(priv->reg + TALITOS_IMR, ch_done_mask); \ 45262306a36Sopenharmony_ci setbits32(priv->reg + TALITOS_IMR_LO, TALITOS2_IMR_LO_INIT); \ 45362306a36Sopenharmony_ci spin_unlock_irqrestore(&priv->reg_lock, flags); \ 45462306a36Sopenharmony_ci} 45562306a36Sopenharmony_ci 45662306a36Sopenharmony_ciDEF_TALITOS2_DONE(4ch, TALITOS2_ISR_4CHDONE) 45762306a36Sopenharmony_ciDEF_TALITOS2_DONE(ch0, TALITOS2_ISR_CH_0_DONE) 45862306a36Sopenharmony_ciDEF_TALITOS2_DONE(ch0_2, TALITOS2_ISR_CH_0_2_DONE) 45962306a36Sopenharmony_ciDEF_TALITOS2_DONE(ch1_3, TALITOS2_ISR_CH_1_3_DONE) 46062306a36Sopenharmony_ci 46162306a36Sopenharmony_ci/* 46262306a36Sopenharmony_ci * locate current (offending) descriptor 46362306a36Sopenharmony_ci */ 46462306a36Sopenharmony_cistatic __be32 current_desc_hdr(struct device *dev, int ch) 46562306a36Sopenharmony_ci{ 46662306a36Sopenharmony_ci struct talitos_private *priv = dev_get_drvdata(dev); 46762306a36Sopenharmony_ci int tail, iter; 46862306a36Sopenharmony_ci dma_addr_t cur_desc; 46962306a36Sopenharmony_ci 47062306a36Sopenharmony_ci cur_desc = ((u64)in_be32(priv->chan[ch].reg + TALITOS_CDPR)) << 32; 47162306a36Sopenharmony_ci cur_desc |= in_be32(priv->chan[ch].reg + TALITOS_CDPR_LO); 47262306a36Sopenharmony_ci 47362306a36Sopenharmony_ci if (!cur_desc) { 47462306a36Sopenharmony_ci dev_err(dev, "CDPR is NULL, giving up search for offending descriptor\n"); 47562306a36Sopenharmony_ci return 0; 47662306a36Sopenharmony_ci } 47762306a36Sopenharmony_ci 47862306a36Sopenharmony_ci tail = priv->chan[ch].tail; 47962306a36Sopenharmony_ci 48062306a36Sopenharmony_ci iter = tail; 48162306a36Sopenharmony_ci while (priv->chan[ch].fifo[iter].dma_desc != cur_desc && 48262306a36Sopenharmony_ci priv->chan[ch].fifo[iter].desc->next_desc != cpu_to_be32(cur_desc)) { 48362306a36Sopenharmony_ci iter = (iter + 1) & (priv->fifo_len - 1); 48462306a36Sopenharmony_ci if (iter == tail) { 48562306a36Sopenharmony_ci dev_err(dev, "couldn't locate current descriptor\n"); 48662306a36Sopenharmony_ci return 0; 48762306a36Sopenharmony_ci } 48862306a36Sopenharmony_ci } 48962306a36Sopenharmony_ci 49062306a36Sopenharmony_ci if (priv->chan[ch].fifo[iter].desc->next_desc == cpu_to_be32(cur_desc)) { 49162306a36Sopenharmony_ci struct talitos_edesc *edesc; 49262306a36Sopenharmony_ci 49362306a36Sopenharmony_ci edesc = container_of(priv->chan[ch].fifo[iter].desc, 49462306a36Sopenharmony_ci struct talitos_edesc, desc); 49562306a36Sopenharmony_ci return ((struct talitos_desc *) 49662306a36Sopenharmony_ci (edesc->buf + edesc->dma_len))->hdr; 49762306a36Sopenharmony_ci } 49862306a36Sopenharmony_ci 49962306a36Sopenharmony_ci return priv->chan[ch].fifo[iter].desc->hdr; 50062306a36Sopenharmony_ci} 50162306a36Sopenharmony_ci 50262306a36Sopenharmony_ci/* 50362306a36Sopenharmony_ci * user diagnostics; report root cause of error based on execution unit status 50462306a36Sopenharmony_ci */ 50562306a36Sopenharmony_cistatic void report_eu_error(struct device *dev, int ch, __be32 desc_hdr) 50662306a36Sopenharmony_ci{ 50762306a36Sopenharmony_ci struct talitos_private *priv = dev_get_drvdata(dev); 50862306a36Sopenharmony_ci int i; 50962306a36Sopenharmony_ci 51062306a36Sopenharmony_ci if (!desc_hdr) 51162306a36Sopenharmony_ci desc_hdr = cpu_to_be32(in_be32(priv->chan[ch].reg + TALITOS_DESCBUF)); 51262306a36Sopenharmony_ci 51362306a36Sopenharmony_ci switch (desc_hdr & DESC_HDR_SEL0_MASK) { 51462306a36Sopenharmony_ci case DESC_HDR_SEL0_AFEU: 51562306a36Sopenharmony_ci dev_err(dev, "AFEUISR 0x%08x_%08x\n", 51662306a36Sopenharmony_ci in_be32(priv->reg_afeu + TALITOS_EUISR), 51762306a36Sopenharmony_ci in_be32(priv->reg_afeu + TALITOS_EUISR_LO)); 51862306a36Sopenharmony_ci break; 51962306a36Sopenharmony_ci case DESC_HDR_SEL0_DEU: 52062306a36Sopenharmony_ci dev_err(dev, "DEUISR 0x%08x_%08x\n", 52162306a36Sopenharmony_ci in_be32(priv->reg_deu + TALITOS_EUISR), 52262306a36Sopenharmony_ci in_be32(priv->reg_deu + TALITOS_EUISR_LO)); 52362306a36Sopenharmony_ci break; 52462306a36Sopenharmony_ci case DESC_HDR_SEL0_MDEUA: 52562306a36Sopenharmony_ci case DESC_HDR_SEL0_MDEUB: 52662306a36Sopenharmony_ci dev_err(dev, "MDEUISR 0x%08x_%08x\n", 52762306a36Sopenharmony_ci in_be32(priv->reg_mdeu + TALITOS_EUISR), 52862306a36Sopenharmony_ci in_be32(priv->reg_mdeu + TALITOS_EUISR_LO)); 52962306a36Sopenharmony_ci break; 53062306a36Sopenharmony_ci case DESC_HDR_SEL0_RNG: 53162306a36Sopenharmony_ci dev_err(dev, "RNGUISR 0x%08x_%08x\n", 53262306a36Sopenharmony_ci in_be32(priv->reg_rngu + TALITOS_ISR), 53362306a36Sopenharmony_ci in_be32(priv->reg_rngu + TALITOS_ISR_LO)); 53462306a36Sopenharmony_ci break; 53562306a36Sopenharmony_ci case DESC_HDR_SEL0_PKEU: 53662306a36Sopenharmony_ci dev_err(dev, "PKEUISR 0x%08x_%08x\n", 53762306a36Sopenharmony_ci in_be32(priv->reg_pkeu + TALITOS_EUISR), 53862306a36Sopenharmony_ci in_be32(priv->reg_pkeu + TALITOS_EUISR_LO)); 53962306a36Sopenharmony_ci break; 54062306a36Sopenharmony_ci case DESC_HDR_SEL0_AESU: 54162306a36Sopenharmony_ci dev_err(dev, "AESUISR 0x%08x_%08x\n", 54262306a36Sopenharmony_ci in_be32(priv->reg_aesu + TALITOS_EUISR), 54362306a36Sopenharmony_ci in_be32(priv->reg_aesu + TALITOS_EUISR_LO)); 54462306a36Sopenharmony_ci break; 54562306a36Sopenharmony_ci case DESC_HDR_SEL0_CRCU: 54662306a36Sopenharmony_ci dev_err(dev, "CRCUISR 0x%08x_%08x\n", 54762306a36Sopenharmony_ci in_be32(priv->reg_crcu + TALITOS_EUISR), 54862306a36Sopenharmony_ci in_be32(priv->reg_crcu + TALITOS_EUISR_LO)); 54962306a36Sopenharmony_ci break; 55062306a36Sopenharmony_ci case DESC_HDR_SEL0_KEU: 55162306a36Sopenharmony_ci dev_err(dev, "KEUISR 0x%08x_%08x\n", 55262306a36Sopenharmony_ci in_be32(priv->reg_pkeu + TALITOS_EUISR), 55362306a36Sopenharmony_ci in_be32(priv->reg_pkeu + TALITOS_EUISR_LO)); 55462306a36Sopenharmony_ci break; 55562306a36Sopenharmony_ci } 55662306a36Sopenharmony_ci 55762306a36Sopenharmony_ci switch (desc_hdr & DESC_HDR_SEL1_MASK) { 55862306a36Sopenharmony_ci case DESC_HDR_SEL1_MDEUA: 55962306a36Sopenharmony_ci case DESC_HDR_SEL1_MDEUB: 56062306a36Sopenharmony_ci dev_err(dev, "MDEUISR 0x%08x_%08x\n", 56162306a36Sopenharmony_ci in_be32(priv->reg_mdeu + TALITOS_EUISR), 56262306a36Sopenharmony_ci in_be32(priv->reg_mdeu + TALITOS_EUISR_LO)); 56362306a36Sopenharmony_ci break; 56462306a36Sopenharmony_ci case DESC_HDR_SEL1_CRCU: 56562306a36Sopenharmony_ci dev_err(dev, "CRCUISR 0x%08x_%08x\n", 56662306a36Sopenharmony_ci in_be32(priv->reg_crcu + TALITOS_EUISR), 56762306a36Sopenharmony_ci in_be32(priv->reg_crcu + TALITOS_EUISR_LO)); 56862306a36Sopenharmony_ci break; 56962306a36Sopenharmony_ci } 57062306a36Sopenharmony_ci 57162306a36Sopenharmony_ci for (i = 0; i < 8; i++) 57262306a36Sopenharmony_ci dev_err(dev, "DESCBUF 0x%08x_%08x\n", 57362306a36Sopenharmony_ci in_be32(priv->chan[ch].reg + TALITOS_DESCBUF + 8*i), 57462306a36Sopenharmony_ci in_be32(priv->chan[ch].reg + TALITOS_DESCBUF_LO + 8*i)); 57562306a36Sopenharmony_ci} 57662306a36Sopenharmony_ci 57762306a36Sopenharmony_ci/* 57862306a36Sopenharmony_ci * recover from error interrupts 57962306a36Sopenharmony_ci */ 58062306a36Sopenharmony_cistatic void talitos_error(struct device *dev, u32 isr, u32 isr_lo) 58162306a36Sopenharmony_ci{ 58262306a36Sopenharmony_ci struct talitos_private *priv = dev_get_drvdata(dev); 58362306a36Sopenharmony_ci unsigned int timeout = TALITOS_TIMEOUT; 58462306a36Sopenharmony_ci int ch, error, reset_dev = 0; 58562306a36Sopenharmony_ci u32 v_lo; 58662306a36Sopenharmony_ci bool is_sec1 = has_ftr_sec1(priv); 58762306a36Sopenharmony_ci int reset_ch = is_sec1 ? 1 : 0; /* only SEC2 supports continuation */ 58862306a36Sopenharmony_ci 58962306a36Sopenharmony_ci for (ch = 0; ch < priv->num_channels; ch++) { 59062306a36Sopenharmony_ci /* skip channels without errors */ 59162306a36Sopenharmony_ci if (is_sec1) { 59262306a36Sopenharmony_ci /* bits 29, 31, 17, 19 */ 59362306a36Sopenharmony_ci if (!(isr & (1 << (29 + (ch & 1) * 2 - (ch & 2) * 6)))) 59462306a36Sopenharmony_ci continue; 59562306a36Sopenharmony_ci } else { 59662306a36Sopenharmony_ci if (!(isr & (1 << (ch * 2 + 1)))) 59762306a36Sopenharmony_ci continue; 59862306a36Sopenharmony_ci } 59962306a36Sopenharmony_ci 60062306a36Sopenharmony_ci error = -EINVAL; 60162306a36Sopenharmony_ci 60262306a36Sopenharmony_ci v_lo = in_be32(priv->chan[ch].reg + TALITOS_CCPSR_LO); 60362306a36Sopenharmony_ci 60462306a36Sopenharmony_ci if (v_lo & TALITOS_CCPSR_LO_DOF) { 60562306a36Sopenharmony_ci dev_err(dev, "double fetch fifo overflow error\n"); 60662306a36Sopenharmony_ci error = -EAGAIN; 60762306a36Sopenharmony_ci reset_ch = 1; 60862306a36Sopenharmony_ci } 60962306a36Sopenharmony_ci if (v_lo & TALITOS_CCPSR_LO_SOF) { 61062306a36Sopenharmony_ci /* h/w dropped descriptor */ 61162306a36Sopenharmony_ci dev_err(dev, "single fetch fifo overflow error\n"); 61262306a36Sopenharmony_ci error = -EAGAIN; 61362306a36Sopenharmony_ci } 61462306a36Sopenharmony_ci if (v_lo & TALITOS_CCPSR_LO_MDTE) 61562306a36Sopenharmony_ci dev_err(dev, "master data transfer error\n"); 61662306a36Sopenharmony_ci if (v_lo & TALITOS_CCPSR_LO_SGDLZ) 61762306a36Sopenharmony_ci dev_err(dev, is_sec1 ? "pointer not complete error\n" 61862306a36Sopenharmony_ci : "s/g data length zero error\n"); 61962306a36Sopenharmony_ci if (v_lo & TALITOS_CCPSR_LO_FPZ) 62062306a36Sopenharmony_ci dev_err(dev, is_sec1 ? "parity error\n" 62162306a36Sopenharmony_ci : "fetch pointer zero error\n"); 62262306a36Sopenharmony_ci if (v_lo & TALITOS_CCPSR_LO_IDH) 62362306a36Sopenharmony_ci dev_err(dev, "illegal descriptor header error\n"); 62462306a36Sopenharmony_ci if (v_lo & TALITOS_CCPSR_LO_IEU) 62562306a36Sopenharmony_ci dev_err(dev, is_sec1 ? "static assignment error\n" 62662306a36Sopenharmony_ci : "invalid exec unit error\n"); 62762306a36Sopenharmony_ci if (v_lo & TALITOS_CCPSR_LO_EU) 62862306a36Sopenharmony_ci report_eu_error(dev, ch, current_desc_hdr(dev, ch)); 62962306a36Sopenharmony_ci if (!is_sec1) { 63062306a36Sopenharmony_ci if (v_lo & TALITOS_CCPSR_LO_GB) 63162306a36Sopenharmony_ci dev_err(dev, "gather boundary error\n"); 63262306a36Sopenharmony_ci if (v_lo & TALITOS_CCPSR_LO_GRL) 63362306a36Sopenharmony_ci dev_err(dev, "gather return/length error\n"); 63462306a36Sopenharmony_ci if (v_lo & TALITOS_CCPSR_LO_SB) 63562306a36Sopenharmony_ci dev_err(dev, "scatter boundary error\n"); 63662306a36Sopenharmony_ci if (v_lo & TALITOS_CCPSR_LO_SRL) 63762306a36Sopenharmony_ci dev_err(dev, "scatter return/length error\n"); 63862306a36Sopenharmony_ci } 63962306a36Sopenharmony_ci 64062306a36Sopenharmony_ci flush_channel(dev, ch, error, reset_ch); 64162306a36Sopenharmony_ci 64262306a36Sopenharmony_ci if (reset_ch) { 64362306a36Sopenharmony_ci reset_channel(dev, ch); 64462306a36Sopenharmony_ci } else { 64562306a36Sopenharmony_ci setbits32(priv->chan[ch].reg + TALITOS_CCCR, 64662306a36Sopenharmony_ci TALITOS2_CCCR_CONT); 64762306a36Sopenharmony_ci setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO, 0); 64862306a36Sopenharmony_ci while ((in_be32(priv->chan[ch].reg + TALITOS_CCCR) & 64962306a36Sopenharmony_ci TALITOS2_CCCR_CONT) && --timeout) 65062306a36Sopenharmony_ci cpu_relax(); 65162306a36Sopenharmony_ci if (timeout == 0) { 65262306a36Sopenharmony_ci dev_err(dev, "failed to restart channel %d\n", 65362306a36Sopenharmony_ci ch); 65462306a36Sopenharmony_ci reset_dev = 1; 65562306a36Sopenharmony_ci } 65662306a36Sopenharmony_ci } 65762306a36Sopenharmony_ci } 65862306a36Sopenharmony_ci if (reset_dev || (is_sec1 && isr & ~TALITOS1_ISR_4CHERR) || 65962306a36Sopenharmony_ci (!is_sec1 && isr & ~TALITOS2_ISR_4CHERR) || isr_lo) { 66062306a36Sopenharmony_ci if (is_sec1 && (isr_lo & TALITOS1_ISR_TEA_ERR)) 66162306a36Sopenharmony_ci dev_err(dev, "TEA error: ISR 0x%08x_%08x\n", 66262306a36Sopenharmony_ci isr, isr_lo); 66362306a36Sopenharmony_ci else 66462306a36Sopenharmony_ci dev_err(dev, "done overflow, internal time out, or " 66562306a36Sopenharmony_ci "rngu error: ISR 0x%08x_%08x\n", isr, isr_lo); 66662306a36Sopenharmony_ci 66762306a36Sopenharmony_ci /* purge request queues */ 66862306a36Sopenharmony_ci for (ch = 0; ch < priv->num_channels; ch++) 66962306a36Sopenharmony_ci flush_channel(dev, ch, -EIO, 1); 67062306a36Sopenharmony_ci 67162306a36Sopenharmony_ci /* reset and reinitialize the device */ 67262306a36Sopenharmony_ci init_device(dev); 67362306a36Sopenharmony_ci } 67462306a36Sopenharmony_ci} 67562306a36Sopenharmony_ci 67662306a36Sopenharmony_ci#define DEF_TALITOS1_INTERRUPT(name, ch_done_mask, ch_err_mask, tlet) \ 67762306a36Sopenharmony_cistatic irqreturn_t talitos1_interrupt_##name(int irq, void *data) \ 67862306a36Sopenharmony_ci{ \ 67962306a36Sopenharmony_ci struct device *dev = data; \ 68062306a36Sopenharmony_ci struct talitos_private *priv = dev_get_drvdata(dev); \ 68162306a36Sopenharmony_ci u32 isr, isr_lo; \ 68262306a36Sopenharmony_ci unsigned long flags; \ 68362306a36Sopenharmony_ci \ 68462306a36Sopenharmony_ci spin_lock_irqsave(&priv->reg_lock, flags); \ 68562306a36Sopenharmony_ci isr = in_be32(priv->reg + TALITOS_ISR); \ 68662306a36Sopenharmony_ci isr_lo = in_be32(priv->reg + TALITOS_ISR_LO); \ 68762306a36Sopenharmony_ci /* Acknowledge interrupt */ \ 68862306a36Sopenharmony_ci out_be32(priv->reg + TALITOS_ICR, isr & (ch_done_mask | ch_err_mask)); \ 68962306a36Sopenharmony_ci out_be32(priv->reg + TALITOS_ICR_LO, isr_lo); \ 69062306a36Sopenharmony_ci \ 69162306a36Sopenharmony_ci if (unlikely(isr & ch_err_mask || isr_lo & TALITOS1_IMR_LO_INIT)) { \ 69262306a36Sopenharmony_ci spin_unlock_irqrestore(&priv->reg_lock, flags); \ 69362306a36Sopenharmony_ci talitos_error(dev, isr & ch_err_mask, isr_lo); \ 69462306a36Sopenharmony_ci } \ 69562306a36Sopenharmony_ci else { \ 69662306a36Sopenharmony_ci if (likely(isr & ch_done_mask)) { \ 69762306a36Sopenharmony_ci /* mask further done interrupts. */ \ 69862306a36Sopenharmony_ci setbits32(priv->reg + TALITOS_IMR, ch_done_mask); \ 69962306a36Sopenharmony_ci /* done_task will unmask done interrupts at exit */ \ 70062306a36Sopenharmony_ci tasklet_schedule(&priv->done_task[tlet]); \ 70162306a36Sopenharmony_ci } \ 70262306a36Sopenharmony_ci spin_unlock_irqrestore(&priv->reg_lock, flags); \ 70362306a36Sopenharmony_ci } \ 70462306a36Sopenharmony_ci \ 70562306a36Sopenharmony_ci return (isr & (ch_done_mask | ch_err_mask) || isr_lo) ? IRQ_HANDLED : \ 70662306a36Sopenharmony_ci IRQ_NONE; \ 70762306a36Sopenharmony_ci} 70862306a36Sopenharmony_ci 70962306a36Sopenharmony_ciDEF_TALITOS1_INTERRUPT(4ch, TALITOS1_ISR_4CHDONE, TALITOS1_ISR_4CHERR, 0) 71062306a36Sopenharmony_ci 71162306a36Sopenharmony_ci#define DEF_TALITOS2_INTERRUPT(name, ch_done_mask, ch_err_mask, tlet) \ 71262306a36Sopenharmony_cistatic irqreturn_t talitos2_interrupt_##name(int irq, void *data) \ 71362306a36Sopenharmony_ci{ \ 71462306a36Sopenharmony_ci struct device *dev = data; \ 71562306a36Sopenharmony_ci struct talitos_private *priv = dev_get_drvdata(dev); \ 71662306a36Sopenharmony_ci u32 isr, isr_lo; \ 71762306a36Sopenharmony_ci unsigned long flags; \ 71862306a36Sopenharmony_ci \ 71962306a36Sopenharmony_ci spin_lock_irqsave(&priv->reg_lock, flags); \ 72062306a36Sopenharmony_ci isr = in_be32(priv->reg + TALITOS_ISR); \ 72162306a36Sopenharmony_ci isr_lo = in_be32(priv->reg + TALITOS_ISR_LO); \ 72262306a36Sopenharmony_ci /* Acknowledge interrupt */ \ 72362306a36Sopenharmony_ci out_be32(priv->reg + TALITOS_ICR, isr & (ch_done_mask | ch_err_mask)); \ 72462306a36Sopenharmony_ci out_be32(priv->reg + TALITOS_ICR_LO, isr_lo); \ 72562306a36Sopenharmony_ci \ 72662306a36Sopenharmony_ci if (unlikely(isr & ch_err_mask || isr_lo)) { \ 72762306a36Sopenharmony_ci spin_unlock_irqrestore(&priv->reg_lock, flags); \ 72862306a36Sopenharmony_ci talitos_error(dev, isr & ch_err_mask, isr_lo); \ 72962306a36Sopenharmony_ci } \ 73062306a36Sopenharmony_ci else { \ 73162306a36Sopenharmony_ci if (likely(isr & ch_done_mask)) { \ 73262306a36Sopenharmony_ci /* mask further done interrupts. */ \ 73362306a36Sopenharmony_ci clrbits32(priv->reg + TALITOS_IMR, ch_done_mask); \ 73462306a36Sopenharmony_ci /* done_task will unmask done interrupts at exit */ \ 73562306a36Sopenharmony_ci tasklet_schedule(&priv->done_task[tlet]); \ 73662306a36Sopenharmony_ci } \ 73762306a36Sopenharmony_ci spin_unlock_irqrestore(&priv->reg_lock, flags); \ 73862306a36Sopenharmony_ci } \ 73962306a36Sopenharmony_ci \ 74062306a36Sopenharmony_ci return (isr & (ch_done_mask | ch_err_mask) || isr_lo) ? IRQ_HANDLED : \ 74162306a36Sopenharmony_ci IRQ_NONE; \ 74262306a36Sopenharmony_ci} 74362306a36Sopenharmony_ci 74462306a36Sopenharmony_ciDEF_TALITOS2_INTERRUPT(4ch, TALITOS2_ISR_4CHDONE, TALITOS2_ISR_4CHERR, 0) 74562306a36Sopenharmony_ciDEF_TALITOS2_INTERRUPT(ch0_2, TALITOS2_ISR_CH_0_2_DONE, TALITOS2_ISR_CH_0_2_ERR, 74662306a36Sopenharmony_ci 0) 74762306a36Sopenharmony_ciDEF_TALITOS2_INTERRUPT(ch1_3, TALITOS2_ISR_CH_1_3_DONE, TALITOS2_ISR_CH_1_3_ERR, 74862306a36Sopenharmony_ci 1) 74962306a36Sopenharmony_ci 75062306a36Sopenharmony_ci/* 75162306a36Sopenharmony_ci * hwrng 75262306a36Sopenharmony_ci */ 75362306a36Sopenharmony_cistatic int talitos_rng_data_present(struct hwrng *rng, int wait) 75462306a36Sopenharmony_ci{ 75562306a36Sopenharmony_ci struct device *dev = (struct device *)rng->priv; 75662306a36Sopenharmony_ci struct talitos_private *priv = dev_get_drvdata(dev); 75762306a36Sopenharmony_ci u32 ofl; 75862306a36Sopenharmony_ci int i; 75962306a36Sopenharmony_ci 76062306a36Sopenharmony_ci for (i = 0; i < 20; i++) { 76162306a36Sopenharmony_ci ofl = in_be32(priv->reg_rngu + TALITOS_EUSR_LO) & 76262306a36Sopenharmony_ci TALITOS_RNGUSR_LO_OFL; 76362306a36Sopenharmony_ci if (ofl || !wait) 76462306a36Sopenharmony_ci break; 76562306a36Sopenharmony_ci udelay(10); 76662306a36Sopenharmony_ci } 76762306a36Sopenharmony_ci 76862306a36Sopenharmony_ci return !!ofl; 76962306a36Sopenharmony_ci} 77062306a36Sopenharmony_ci 77162306a36Sopenharmony_cistatic int talitos_rng_data_read(struct hwrng *rng, u32 *data) 77262306a36Sopenharmony_ci{ 77362306a36Sopenharmony_ci struct device *dev = (struct device *)rng->priv; 77462306a36Sopenharmony_ci struct talitos_private *priv = dev_get_drvdata(dev); 77562306a36Sopenharmony_ci 77662306a36Sopenharmony_ci /* rng fifo requires 64-bit accesses */ 77762306a36Sopenharmony_ci *data = in_be32(priv->reg_rngu + TALITOS_EU_FIFO); 77862306a36Sopenharmony_ci *data = in_be32(priv->reg_rngu + TALITOS_EU_FIFO_LO); 77962306a36Sopenharmony_ci 78062306a36Sopenharmony_ci return sizeof(u32); 78162306a36Sopenharmony_ci} 78262306a36Sopenharmony_ci 78362306a36Sopenharmony_cistatic int talitos_rng_init(struct hwrng *rng) 78462306a36Sopenharmony_ci{ 78562306a36Sopenharmony_ci struct device *dev = (struct device *)rng->priv; 78662306a36Sopenharmony_ci struct talitos_private *priv = dev_get_drvdata(dev); 78762306a36Sopenharmony_ci unsigned int timeout = TALITOS_TIMEOUT; 78862306a36Sopenharmony_ci 78962306a36Sopenharmony_ci setbits32(priv->reg_rngu + TALITOS_EURCR_LO, TALITOS_RNGURCR_LO_SR); 79062306a36Sopenharmony_ci while (!(in_be32(priv->reg_rngu + TALITOS_EUSR_LO) 79162306a36Sopenharmony_ci & TALITOS_RNGUSR_LO_RD) 79262306a36Sopenharmony_ci && --timeout) 79362306a36Sopenharmony_ci cpu_relax(); 79462306a36Sopenharmony_ci if (timeout == 0) { 79562306a36Sopenharmony_ci dev_err(dev, "failed to reset rng hw\n"); 79662306a36Sopenharmony_ci return -ENODEV; 79762306a36Sopenharmony_ci } 79862306a36Sopenharmony_ci 79962306a36Sopenharmony_ci /* start generating */ 80062306a36Sopenharmony_ci setbits32(priv->reg_rngu + TALITOS_EUDSR_LO, 0); 80162306a36Sopenharmony_ci 80262306a36Sopenharmony_ci return 0; 80362306a36Sopenharmony_ci} 80462306a36Sopenharmony_ci 80562306a36Sopenharmony_cistatic int talitos_register_rng(struct device *dev) 80662306a36Sopenharmony_ci{ 80762306a36Sopenharmony_ci struct talitos_private *priv = dev_get_drvdata(dev); 80862306a36Sopenharmony_ci int err; 80962306a36Sopenharmony_ci 81062306a36Sopenharmony_ci priv->rng.name = dev_driver_string(dev); 81162306a36Sopenharmony_ci priv->rng.init = talitos_rng_init; 81262306a36Sopenharmony_ci priv->rng.data_present = talitos_rng_data_present; 81362306a36Sopenharmony_ci priv->rng.data_read = talitos_rng_data_read; 81462306a36Sopenharmony_ci priv->rng.priv = (unsigned long)dev; 81562306a36Sopenharmony_ci 81662306a36Sopenharmony_ci err = hwrng_register(&priv->rng); 81762306a36Sopenharmony_ci if (!err) 81862306a36Sopenharmony_ci priv->rng_registered = true; 81962306a36Sopenharmony_ci 82062306a36Sopenharmony_ci return err; 82162306a36Sopenharmony_ci} 82262306a36Sopenharmony_ci 82362306a36Sopenharmony_cistatic void talitos_unregister_rng(struct device *dev) 82462306a36Sopenharmony_ci{ 82562306a36Sopenharmony_ci struct talitos_private *priv = dev_get_drvdata(dev); 82662306a36Sopenharmony_ci 82762306a36Sopenharmony_ci if (!priv->rng_registered) 82862306a36Sopenharmony_ci return; 82962306a36Sopenharmony_ci 83062306a36Sopenharmony_ci hwrng_unregister(&priv->rng); 83162306a36Sopenharmony_ci priv->rng_registered = false; 83262306a36Sopenharmony_ci} 83362306a36Sopenharmony_ci 83462306a36Sopenharmony_ci/* 83562306a36Sopenharmony_ci * crypto alg 83662306a36Sopenharmony_ci */ 83762306a36Sopenharmony_ci#define TALITOS_CRA_PRIORITY 3000 83862306a36Sopenharmony_ci/* 83962306a36Sopenharmony_ci * Defines a priority for doing AEAD with descriptors type 84062306a36Sopenharmony_ci * HMAC_SNOOP_NO_AFEA (HSNA) instead of type IPSEC_ESP 84162306a36Sopenharmony_ci */ 84262306a36Sopenharmony_ci#define TALITOS_CRA_PRIORITY_AEAD_HSNA (TALITOS_CRA_PRIORITY - 1) 84362306a36Sopenharmony_ci#ifdef CONFIG_CRYPTO_DEV_TALITOS2 84462306a36Sopenharmony_ci#define TALITOS_MAX_KEY_SIZE (AES_MAX_KEY_SIZE + SHA512_BLOCK_SIZE) 84562306a36Sopenharmony_ci#else 84662306a36Sopenharmony_ci#define TALITOS_MAX_KEY_SIZE (AES_MAX_KEY_SIZE + SHA256_BLOCK_SIZE) 84762306a36Sopenharmony_ci#endif 84862306a36Sopenharmony_ci#define TALITOS_MAX_IV_LENGTH 16 /* max of AES_BLOCK_SIZE, DES3_EDE_BLOCK_SIZE */ 84962306a36Sopenharmony_ci 85062306a36Sopenharmony_cistruct talitos_ctx { 85162306a36Sopenharmony_ci struct device *dev; 85262306a36Sopenharmony_ci int ch; 85362306a36Sopenharmony_ci __be32 desc_hdr_template; 85462306a36Sopenharmony_ci u8 key[TALITOS_MAX_KEY_SIZE]; 85562306a36Sopenharmony_ci u8 iv[TALITOS_MAX_IV_LENGTH]; 85662306a36Sopenharmony_ci dma_addr_t dma_key; 85762306a36Sopenharmony_ci unsigned int keylen; 85862306a36Sopenharmony_ci unsigned int enckeylen; 85962306a36Sopenharmony_ci unsigned int authkeylen; 86062306a36Sopenharmony_ci}; 86162306a36Sopenharmony_ci 86262306a36Sopenharmony_ci#define HASH_MAX_BLOCK_SIZE SHA512_BLOCK_SIZE 86362306a36Sopenharmony_ci#define TALITOS_MDEU_MAX_CONTEXT_SIZE TALITOS_MDEU_CONTEXT_SIZE_SHA384_SHA512 86462306a36Sopenharmony_ci 86562306a36Sopenharmony_cistruct talitos_ahash_req_ctx { 86662306a36Sopenharmony_ci u32 hw_context[TALITOS_MDEU_MAX_CONTEXT_SIZE / sizeof(u32)]; 86762306a36Sopenharmony_ci unsigned int hw_context_size; 86862306a36Sopenharmony_ci u8 buf[2][HASH_MAX_BLOCK_SIZE]; 86962306a36Sopenharmony_ci int buf_idx; 87062306a36Sopenharmony_ci unsigned int swinit; 87162306a36Sopenharmony_ci unsigned int first; 87262306a36Sopenharmony_ci unsigned int last; 87362306a36Sopenharmony_ci unsigned int to_hash_later; 87462306a36Sopenharmony_ci unsigned int nbuf; 87562306a36Sopenharmony_ci struct scatterlist bufsl[2]; 87662306a36Sopenharmony_ci struct scatterlist *psrc; 87762306a36Sopenharmony_ci}; 87862306a36Sopenharmony_ci 87962306a36Sopenharmony_cistruct talitos_export_state { 88062306a36Sopenharmony_ci u32 hw_context[TALITOS_MDEU_MAX_CONTEXT_SIZE / sizeof(u32)]; 88162306a36Sopenharmony_ci u8 buf[HASH_MAX_BLOCK_SIZE]; 88262306a36Sopenharmony_ci unsigned int swinit; 88362306a36Sopenharmony_ci unsigned int first; 88462306a36Sopenharmony_ci unsigned int last; 88562306a36Sopenharmony_ci unsigned int to_hash_later; 88662306a36Sopenharmony_ci unsigned int nbuf; 88762306a36Sopenharmony_ci}; 88862306a36Sopenharmony_ci 88962306a36Sopenharmony_cistatic int aead_setkey(struct crypto_aead *authenc, 89062306a36Sopenharmony_ci const u8 *key, unsigned int keylen) 89162306a36Sopenharmony_ci{ 89262306a36Sopenharmony_ci struct talitos_ctx *ctx = crypto_aead_ctx(authenc); 89362306a36Sopenharmony_ci struct device *dev = ctx->dev; 89462306a36Sopenharmony_ci struct crypto_authenc_keys keys; 89562306a36Sopenharmony_ci 89662306a36Sopenharmony_ci if (crypto_authenc_extractkeys(&keys, key, keylen) != 0) 89762306a36Sopenharmony_ci goto badkey; 89862306a36Sopenharmony_ci 89962306a36Sopenharmony_ci if (keys.authkeylen + keys.enckeylen > TALITOS_MAX_KEY_SIZE) 90062306a36Sopenharmony_ci goto badkey; 90162306a36Sopenharmony_ci 90262306a36Sopenharmony_ci if (ctx->keylen) 90362306a36Sopenharmony_ci dma_unmap_single(dev, ctx->dma_key, ctx->keylen, DMA_TO_DEVICE); 90462306a36Sopenharmony_ci 90562306a36Sopenharmony_ci memcpy(ctx->key, keys.authkey, keys.authkeylen); 90662306a36Sopenharmony_ci memcpy(&ctx->key[keys.authkeylen], keys.enckey, keys.enckeylen); 90762306a36Sopenharmony_ci 90862306a36Sopenharmony_ci ctx->keylen = keys.authkeylen + keys.enckeylen; 90962306a36Sopenharmony_ci ctx->enckeylen = keys.enckeylen; 91062306a36Sopenharmony_ci ctx->authkeylen = keys.authkeylen; 91162306a36Sopenharmony_ci ctx->dma_key = dma_map_single(dev, ctx->key, ctx->keylen, 91262306a36Sopenharmony_ci DMA_TO_DEVICE); 91362306a36Sopenharmony_ci 91462306a36Sopenharmony_ci memzero_explicit(&keys, sizeof(keys)); 91562306a36Sopenharmony_ci return 0; 91662306a36Sopenharmony_ci 91762306a36Sopenharmony_cibadkey: 91862306a36Sopenharmony_ci memzero_explicit(&keys, sizeof(keys)); 91962306a36Sopenharmony_ci return -EINVAL; 92062306a36Sopenharmony_ci} 92162306a36Sopenharmony_ci 92262306a36Sopenharmony_cistatic int aead_des3_setkey(struct crypto_aead *authenc, 92362306a36Sopenharmony_ci const u8 *key, unsigned int keylen) 92462306a36Sopenharmony_ci{ 92562306a36Sopenharmony_ci struct talitos_ctx *ctx = crypto_aead_ctx(authenc); 92662306a36Sopenharmony_ci struct device *dev = ctx->dev; 92762306a36Sopenharmony_ci struct crypto_authenc_keys keys; 92862306a36Sopenharmony_ci int err; 92962306a36Sopenharmony_ci 93062306a36Sopenharmony_ci err = crypto_authenc_extractkeys(&keys, key, keylen); 93162306a36Sopenharmony_ci if (unlikely(err)) 93262306a36Sopenharmony_ci goto out; 93362306a36Sopenharmony_ci 93462306a36Sopenharmony_ci err = -EINVAL; 93562306a36Sopenharmony_ci if (keys.authkeylen + keys.enckeylen > TALITOS_MAX_KEY_SIZE) 93662306a36Sopenharmony_ci goto out; 93762306a36Sopenharmony_ci 93862306a36Sopenharmony_ci err = verify_aead_des3_key(authenc, keys.enckey, keys.enckeylen); 93962306a36Sopenharmony_ci if (err) 94062306a36Sopenharmony_ci goto out; 94162306a36Sopenharmony_ci 94262306a36Sopenharmony_ci if (ctx->keylen) 94362306a36Sopenharmony_ci dma_unmap_single(dev, ctx->dma_key, ctx->keylen, DMA_TO_DEVICE); 94462306a36Sopenharmony_ci 94562306a36Sopenharmony_ci memcpy(ctx->key, keys.authkey, keys.authkeylen); 94662306a36Sopenharmony_ci memcpy(&ctx->key[keys.authkeylen], keys.enckey, keys.enckeylen); 94762306a36Sopenharmony_ci 94862306a36Sopenharmony_ci ctx->keylen = keys.authkeylen + keys.enckeylen; 94962306a36Sopenharmony_ci ctx->enckeylen = keys.enckeylen; 95062306a36Sopenharmony_ci ctx->authkeylen = keys.authkeylen; 95162306a36Sopenharmony_ci ctx->dma_key = dma_map_single(dev, ctx->key, ctx->keylen, 95262306a36Sopenharmony_ci DMA_TO_DEVICE); 95362306a36Sopenharmony_ci 95462306a36Sopenharmony_ciout: 95562306a36Sopenharmony_ci memzero_explicit(&keys, sizeof(keys)); 95662306a36Sopenharmony_ci return err; 95762306a36Sopenharmony_ci} 95862306a36Sopenharmony_ci 95962306a36Sopenharmony_cistatic void talitos_sg_unmap(struct device *dev, 96062306a36Sopenharmony_ci struct talitos_edesc *edesc, 96162306a36Sopenharmony_ci struct scatterlist *src, 96262306a36Sopenharmony_ci struct scatterlist *dst, 96362306a36Sopenharmony_ci unsigned int len, unsigned int offset) 96462306a36Sopenharmony_ci{ 96562306a36Sopenharmony_ci struct talitos_private *priv = dev_get_drvdata(dev); 96662306a36Sopenharmony_ci bool is_sec1 = has_ftr_sec1(priv); 96762306a36Sopenharmony_ci unsigned int src_nents = edesc->src_nents ? : 1; 96862306a36Sopenharmony_ci unsigned int dst_nents = edesc->dst_nents ? : 1; 96962306a36Sopenharmony_ci 97062306a36Sopenharmony_ci if (is_sec1 && dst && dst_nents > 1) { 97162306a36Sopenharmony_ci dma_sync_single_for_device(dev, edesc->dma_link_tbl + offset, 97262306a36Sopenharmony_ci len, DMA_FROM_DEVICE); 97362306a36Sopenharmony_ci sg_pcopy_from_buffer(dst, dst_nents, edesc->buf + offset, len, 97462306a36Sopenharmony_ci offset); 97562306a36Sopenharmony_ci } 97662306a36Sopenharmony_ci if (src != dst) { 97762306a36Sopenharmony_ci if (src_nents == 1 || !is_sec1) 97862306a36Sopenharmony_ci dma_unmap_sg(dev, src, src_nents, DMA_TO_DEVICE); 97962306a36Sopenharmony_ci 98062306a36Sopenharmony_ci if (dst && (dst_nents == 1 || !is_sec1)) 98162306a36Sopenharmony_ci dma_unmap_sg(dev, dst, dst_nents, DMA_FROM_DEVICE); 98262306a36Sopenharmony_ci } else if (src_nents == 1 || !is_sec1) { 98362306a36Sopenharmony_ci dma_unmap_sg(dev, src, src_nents, DMA_BIDIRECTIONAL); 98462306a36Sopenharmony_ci } 98562306a36Sopenharmony_ci} 98662306a36Sopenharmony_ci 98762306a36Sopenharmony_cistatic void ipsec_esp_unmap(struct device *dev, 98862306a36Sopenharmony_ci struct talitos_edesc *edesc, 98962306a36Sopenharmony_ci struct aead_request *areq, bool encrypt) 99062306a36Sopenharmony_ci{ 99162306a36Sopenharmony_ci struct crypto_aead *aead = crypto_aead_reqtfm(areq); 99262306a36Sopenharmony_ci struct talitos_ctx *ctx = crypto_aead_ctx(aead); 99362306a36Sopenharmony_ci unsigned int ivsize = crypto_aead_ivsize(aead); 99462306a36Sopenharmony_ci unsigned int authsize = crypto_aead_authsize(aead); 99562306a36Sopenharmony_ci unsigned int cryptlen = areq->cryptlen - (encrypt ? 0 : authsize); 99662306a36Sopenharmony_ci bool is_ipsec_esp = edesc->desc.hdr & DESC_HDR_TYPE_IPSEC_ESP; 99762306a36Sopenharmony_ci struct talitos_ptr *civ_ptr = &edesc->desc.ptr[is_ipsec_esp ? 2 : 3]; 99862306a36Sopenharmony_ci 99962306a36Sopenharmony_ci if (is_ipsec_esp) 100062306a36Sopenharmony_ci unmap_single_talitos_ptr(dev, &edesc->desc.ptr[6], 100162306a36Sopenharmony_ci DMA_FROM_DEVICE); 100262306a36Sopenharmony_ci unmap_single_talitos_ptr(dev, civ_ptr, DMA_TO_DEVICE); 100362306a36Sopenharmony_ci 100462306a36Sopenharmony_ci talitos_sg_unmap(dev, edesc, areq->src, areq->dst, 100562306a36Sopenharmony_ci cryptlen + authsize, areq->assoclen); 100662306a36Sopenharmony_ci 100762306a36Sopenharmony_ci if (edesc->dma_len) 100862306a36Sopenharmony_ci dma_unmap_single(dev, edesc->dma_link_tbl, edesc->dma_len, 100962306a36Sopenharmony_ci DMA_BIDIRECTIONAL); 101062306a36Sopenharmony_ci 101162306a36Sopenharmony_ci if (!is_ipsec_esp) { 101262306a36Sopenharmony_ci unsigned int dst_nents = edesc->dst_nents ? : 1; 101362306a36Sopenharmony_ci 101462306a36Sopenharmony_ci sg_pcopy_to_buffer(areq->dst, dst_nents, ctx->iv, ivsize, 101562306a36Sopenharmony_ci areq->assoclen + cryptlen - ivsize); 101662306a36Sopenharmony_ci } 101762306a36Sopenharmony_ci} 101862306a36Sopenharmony_ci 101962306a36Sopenharmony_ci/* 102062306a36Sopenharmony_ci * ipsec_esp descriptor callbacks 102162306a36Sopenharmony_ci */ 102262306a36Sopenharmony_cistatic void ipsec_esp_encrypt_done(struct device *dev, 102362306a36Sopenharmony_ci struct talitos_desc *desc, void *context, 102462306a36Sopenharmony_ci int err) 102562306a36Sopenharmony_ci{ 102662306a36Sopenharmony_ci struct aead_request *areq = context; 102762306a36Sopenharmony_ci struct crypto_aead *authenc = crypto_aead_reqtfm(areq); 102862306a36Sopenharmony_ci unsigned int ivsize = crypto_aead_ivsize(authenc); 102962306a36Sopenharmony_ci struct talitos_edesc *edesc; 103062306a36Sopenharmony_ci 103162306a36Sopenharmony_ci edesc = container_of(desc, struct talitos_edesc, desc); 103262306a36Sopenharmony_ci 103362306a36Sopenharmony_ci ipsec_esp_unmap(dev, edesc, areq, true); 103462306a36Sopenharmony_ci 103562306a36Sopenharmony_ci dma_unmap_single(dev, edesc->iv_dma, ivsize, DMA_TO_DEVICE); 103662306a36Sopenharmony_ci 103762306a36Sopenharmony_ci kfree(edesc); 103862306a36Sopenharmony_ci 103962306a36Sopenharmony_ci aead_request_complete(areq, err); 104062306a36Sopenharmony_ci} 104162306a36Sopenharmony_ci 104262306a36Sopenharmony_cistatic void ipsec_esp_decrypt_swauth_done(struct device *dev, 104362306a36Sopenharmony_ci struct talitos_desc *desc, 104462306a36Sopenharmony_ci void *context, int err) 104562306a36Sopenharmony_ci{ 104662306a36Sopenharmony_ci struct aead_request *req = context; 104762306a36Sopenharmony_ci struct crypto_aead *authenc = crypto_aead_reqtfm(req); 104862306a36Sopenharmony_ci unsigned int authsize = crypto_aead_authsize(authenc); 104962306a36Sopenharmony_ci struct talitos_edesc *edesc; 105062306a36Sopenharmony_ci char *oicv, *icv; 105162306a36Sopenharmony_ci 105262306a36Sopenharmony_ci edesc = container_of(desc, struct talitos_edesc, desc); 105362306a36Sopenharmony_ci 105462306a36Sopenharmony_ci ipsec_esp_unmap(dev, edesc, req, false); 105562306a36Sopenharmony_ci 105662306a36Sopenharmony_ci if (!err) { 105762306a36Sopenharmony_ci /* auth check */ 105862306a36Sopenharmony_ci oicv = edesc->buf + edesc->dma_len; 105962306a36Sopenharmony_ci icv = oicv - authsize; 106062306a36Sopenharmony_ci 106162306a36Sopenharmony_ci err = crypto_memneq(oicv, icv, authsize) ? -EBADMSG : 0; 106262306a36Sopenharmony_ci } 106362306a36Sopenharmony_ci 106462306a36Sopenharmony_ci kfree(edesc); 106562306a36Sopenharmony_ci 106662306a36Sopenharmony_ci aead_request_complete(req, err); 106762306a36Sopenharmony_ci} 106862306a36Sopenharmony_ci 106962306a36Sopenharmony_cistatic void ipsec_esp_decrypt_hwauth_done(struct device *dev, 107062306a36Sopenharmony_ci struct talitos_desc *desc, 107162306a36Sopenharmony_ci void *context, int err) 107262306a36Sopenharmony_ci{ 107362306a36Sopenharmony_ci struct aead_request *req = context; 107462306a36Sopenharmony_ci struct talitos_edesc *edesc; 107562306a36Sopenharmony_ci 107662306a36Sopenharmony_ci edesc = container_of(desc, struct talitos_edesc, desc); 107762306a36Sopenharmony_ci 107862306a36Sopenharmony_ci ipsec_esp_unmap(dev, edesc, req, false); 107962306a36Sopenharmony_ci 108062306a36Sopenharmony_ci /* check ICV auth status */ 108162306a36Sopenharmony_ci if (!err && ((desc->hdr_lo & DESC_HDR_LO_ICCR1_MASK) != 108262306a36Sopenharmony_ci DESC_HDR_LO_ICCR1_PASS)) 108362306a36Sopenharmony_ci err = -EBADMSG; 108462306a36Sopenharmony_ci 108562306a36Sopenharmony_ci kfree(edesc); 108662306a36Sopenharmony_ci 108762306a36Sopenharmony_ci aead_request_complete(req, err); 108862306a36Sopenharmony_ci} 108962306a36Sopenharmony_ci 109062306a36Sopenharmony_ci/* 109162306a36Sopenharmony_ci * convert scatterlist to SEC h/w link table format 109262306a36Sopenharmony_ci * stop at cryptlen bytes 109362306a36Sopenharmony_ci */ 109462306a36Sopenharmony_cistatic int sg_to_link_tbl_offset(struct scatterlist *sg, int sg_count, 109562306a36Sopenharmony_ci unsigned int offset, int datalen, int elen, 109662306a36Sopenharmony_ci struct talitos_ptr *link_tbl_ptr, int align) 109762306a36Sopenharmony_ci{ 109862306a36Sopenharmony_ci int n_sg = elen ? sg_count + 1 : sg_count; 109962306a36Sopenharmony_ci int count = 0; 110062306a36Sopenharmony_ci int cryptlen = datalen + elen; 110162306a36Sopenharmony_ci int padding = ALIGN(cryptlen, align) - cryptlen; 110262306a36Sopenharmony_ci 110362306a36Sopenharmony_ci while (cryptlen && sg && n_sg--) { 110462306a36Sopenharmony_ci unsigned int len = sg_dma_len(sg); 110562306a36Sopenharmony_ci 110662306a36Sopenharmony_ci if (offset >= len) { 110762306a36Sopenharmony_ci offset -= len; 110862306a36Sopenharmony_ci goto next; 110962306a36Sopenharmony_ci } 111062306a36Sopenharmony_ci 111162306a36Sopenharmony_ci len -= offset; 111262306a36Sopenharmony_ci 111362306a36Sopenharmony_ci if (len > cryptlen) 111462306a36Sopenharmony_ci len = cryptlen; 111562306a36Sopenharmony_ci 111662306a36Sopenharmony_ci if (datalen > 0 && len > datalen) { 111762306a36Sopenharmony_ci to_talitos_ptr(link_tbl_ptr + count, 111862306a36Sopenharmony_ci sg_dma_address(sg) + offset, datalen, 0); 111962306a36Sopenharmony_ci to_talitos_ptr_ext_set(link_tbl_ptr + count, 0, 0); 112062306a36Sopenharmony_ci count++; 112162306a36Sopenharmony_ci len -= datalen; 112262306a36Sopenharmony_ci offset += datalen; 112362306a36Sopenharmony_ci } 112462306a36Sopenharmony_ci to_talitos_ptr(link_tbl_ptr + count, 112562306a36Sopenharmony_ci sg_dma_address(sg) + offset, sg_next(sg) ? len : len + padding, 0); 112662306a36Sopenharmony_ci to_talitos_ptr_ext_set(link_tbl_ptr + count, 0, 0); 112762306a36Sopenharmony_ci count++; 112862306a36Sopenharmony_ci cryptlen -= len; 112962306a36Sopenharmony_ci datalen -= len; 113062306a36Sopenharmony_ci offset = 0; 113162306a36Sopenharmony_ci 113262306a36Sopenharmony_cinext: 113362306a36Sopenharmony_ci sg = sg_next(sg); 113462306a36Sopenharmony_ci } 113562306a36Sopenharmony_ci 113662306a36Sopenharmony_ci /* tag end of link table */ 113762306a36Sopenharmony_ci if (count > 0) 113862306a36Sopenharmony_ci to_talitos_ptr_ext_set(link_tbl_ptr + count - 1, 113962306a36Sopenharmony_ci DESC_PTR_LNKTBL_RET, 0); 114062306a36Sopenharmony_ci 114162306a36Sopenharmony_ci return count; 114262306a36Sopenharmony_ci} 114362306a36Sopenharmony_ci 114462306a36Sopenharmony_cistatic int talitos_sg_map_ext(struct device *dev, struct scatterlist *src, 114562306a36Sopenharmony_ci unsigned int len, struct talitos_edesc *edesc, 114662306a36Sopenharmony_ci struct talitos_ptr *ptr, int sg_count, 114762306a36Sopenharmony_ci unsigned int offset, int tbl_off, int elen, 114862306a36Sopenharmony_ci bool force, int align) 114962306a36Sopenharmony_ci{ 115062306a36Sopenharmony_ci struct talitos_private *priv = dev_get_drvdata(dev); 115162306a36Sopenharmony_ci bool is_sec1 = has_ftr_sec1(priv); 115262306a36Sopenharmony_ci int aligned_len = ALIGN(len, align); 115362306a36Sopenharmony_ci 115462306a36Sopenharmony_ci if (!src) { 115562306a36Sopenharmony_ci to_talitos_ptr(ptr, 0, 0, is_sec1); 115662306a36Sopenharmony_ci return 1; 115762306a36Sopenharmony_ci } 115862306a36Sopenharmony_ci to_talitos_ptr_ext_set(ptr, elen, is_sec1); 115962306a36Sopenharmony_ci if (sg_count == 1 && !force) { 116062306a36Sopenharmony_ci to_talitos_ptr(ptr, sg_dma_address(src) + offset, aligned_len, is_sec1); 116162306a36Sopenharmony_ci return sg_count; 116262306a36Sopenharmony_ci } 116362306a36Sopenharmony_ci if (is_sec1) { 116462306a36Sopenharmony_ci to_talitos_ptr(ptr, edesc->dma_link_tbl + offset, aligned_len, is_sec1); 116562306a36Sopenharmony_ci return sg_count; 116662306a36Sopenharmony_ci } 116762306a36Sopenharmony_ci sg_count = sg_to_link_tbl_offset(src, sg_count, offset, len, elen, 116862306a36Sopenharmony_ci &edesc->link_tbl[tbl_off], align); 116962306a36Sopenharmony_ci if (sg_count == 1 && !force) { 117062306a36Sopenharmony_ci /* Only one segment now, so no link tbl needed*/ 117162306a36Sopenharmony_ci copy_talitos_ptr(ptr, &edesc->link_tbl[tbl_off], is_sec1); 117262306a36Sopenharmony_ci return sg_count; 117362306a36Sopenharmony_ci } 117462306a36Sopenharmony_ci to_talitos_ptr(ptr, edesc->dma_link_tbl + 117562306a36Sopenharmony_ci tbl_off * sizeof(struct talitos_ptr), aligned_len, is_sec1); 117662306a36Sopenharmony_ci to_talitos_ptr_ext_or(ptr, DESC_PTR_LNKTBL_JUMP, is_sec1); 117762306a36Sopenharmony_ci 117862306a36Sopenharmony_ci return sg_count; 117962306a36Sopenharmony_ci} 118062306a36Sopenharmony_ci 118162306a36Sopenharmony_cistatic int talitos_sg_map(struct device *dev, struct scatterlist *src, 118262306a36Sopenharmony_ci unsigned int len, struct talitos_edesc *edesc, 118362306a36Sopenharmony_ci struct talitos_ptr *ptr, int sg_count, 118462306a36Sopenharmony_ci unsigned int offset, int tbl_off) 118562306a36Sopenharmony_ci{ 118662306a36Sopenharmony_ci return talitos_sg_map_ext(dev, src, len, edesc, ptr, sg_count, offset, 118762306a36Sopenharmony_ci tbl_off, 0, false, 1); 118862306a36Sopenharmony_ci} 118962306a36Sopenharmony_ci 119062306a36Sopenharmony_ci/* 119162306a36Sopenharmony_ci * fill in and submit ipsec_esp descriptor 119262306a36Sopenharmony_ci */ 119362306a36Sopenharmony_cistatic int ipsec_esp(struct talitos_edesc *edesc, struct aead_request *areq, 119462306a36Sopenharmony_ci bool encrypt, 119562306a36Sopenharmony_ci void (*callback)(struct device *dev, 119662306a36Sopenharmony_ci struct talitos_desc *desc, 119762306a36Sopenharmony_ci void *context, int error)) 119862306a36Sopenharmony_ci{ 119962306a36Sopenharmony_ci struct crypto_aead *aead = crypto_aead_reqtfm(areq); 120062306a36Sopenharmony_ci unsigned int authsize = crypto_aead_authsize(aead); 120162306a36Sopenharmony_ci struct talitos_ctx *ctx = crypto_aead_ctx(aead); 120262306a36Sopenharmony_ci struct device *dev = ctx->dev; 120362306a36Sopenharmony_ci struct talitos_desc *desc = &edesc->desc; 120462306a36Sopenharmony_ci unsigned int cryptlen = areq->cryptlen - (encrypt ? 0 : authsize); 120562306a36Sopenharmony_ci unsigned int ivsize = crypto_aead_ivsize(aead); 120662306a36Sopenharmony_ci int tbl_off = 0; 120762306a36Sopenharmony_ci int sg_count, ret; 120862306a36Sopenharmony_ci int elen = 0; 120962306a36Sopenharmony_ci bool sync_needed = false; 121062306a36Sopenharmony_ci struct talitos_private *priv = dev_get_drvdata(dev); 121162306a36Sopenharmony_ci bool is_sec1 = has_ftr_sec1(priv); 121262306a36Sopenharmony_ci bool is_ipsec_esp = desc->hdr & DESC_HDR_TYPE_IPSEC_ESP; 121362306a36Sopenharmony_ci struct talitos_ptr *civ_ptr = &desc->ptr[is_ipsec_esp ? 2 : 3]; 121462306a36Sopenharmony_ci struct talitos_ptr *ckey_ptr = &desc->ptr[is_ipsec_esp ? 3 : 2]; 121562306a36Sopenharmony_ci dma_addr_t dma_icv = edesc->dma_link_tbl + edesc->dma_len - authsize; 121662306a36Sopenharmony_ci 121762306a36Sopenharmony_ci /* hmac key */ 121862306a36Sopenharmony_ci to_talitos_ptr(&desc->ptr[0], ctx->dma_key, ctx->authkeylen, is_sec1); 121962306a36Sopenharmony_ci 122062306a36Sopenharmony_ci sg_count = edesc->src_nents ?: 1; 122162306a36Sopenharmony_ci if (is_sec1 && sg_count > 1) 122262306a36Sopenharmony_ci sg_copy_to_buffer(areq->src, sg_count, edesc->buf, 122362306a36Sopenharmony_ci areq->assoclen + cryptlen); 122462306a36Sopenharmony_ci else 122562306a36Sopenharmony_ci sg_count = dma_map_sg(dev, areq->src, sg_count, 122662306a36Sopenharmony_ci (areq->src == areq->dst) ? 122762306a36Sopenharmony_ci DMA_BIDIRECTIONAL : DMA_TO_DEVICE); 122862306a36Sopenharmony_ci 122962306a36Sopenharmony_ci /* hmac data */ 123062306a36Sopenharmony_ci ret = talitos_sg_map(dev, areq->src, areq->assoclen, edesc, 123162306a36Sopenharmony_ci &desc->ptr[1], sg_count, 0, tbl_off); 123262306a36Sopenharmony_ci 123362306a36Sopenharmony_ci if (ret > 1) { 123462306a36Sopenharmony_ci tbl_off += ret; 123562306a36Sopenharmony_ci sync_needed = true; 123662306a36Sopenharmony_ci } 123762306a36Sopenharmony_ci 123862306a36Sopenharmony_ci /* cipher iv */ 123962306a36Sopenharmony_ci to_talitos_ptr(civ_ptr, edesc->iv_dma, ivsize, is_sec1); 124062306a36Sopenharmony_ci 124162306a36Sopenharmony_ci /* cipher key */ 124262306a36Sopenharmony_ci to_talitos_ptr(ckey_ptr, ctx->dma_key + ctx->authkeylen, 124362306a36Sopenharmony_ci ctx->enckeylen, is_sec1); 124462306a36Sopenharmony_ci 124562306a36Sopenharmony_ci /* 124662306a36Sopenharmony_ci * cipher in 124762306a36Sopenharmony_ci * map and adjust cipher len to aead request cryptlen. 124862306a36Sopenharmony_ci * extent is bytes of HMAC postpended to ciphertext, 124962306a36Sopenharmony_ci * typically 12 for ipsec 125062306a36Sopenharmony_ci */ 125162306a36Sopenharmony_ci if (is_ipsec_esp && (desc->hdr & DESC_HDR_MODE1_MDEU_CICV)) 125262306a36Sopenharmony_ci elen = authsize; 125362306a36Sopenharmony_ci 125462306a36Sopenharmony_ci ret = talitos_sg_map_ext(dev, areq->src, cryptlen, edesc, &desc->ptr[4], 125562306a36Sopenharmony_ci sg_count, areq->assoclen, tbl_off, elen, 125662306a36Sopenharmony_ci false, 1); 125762306a36Sopenharmony_ci 125862306a36Sopenharmony_ci if (ret > 1) { 125962306a36Sopenharmony_ci tbl_off += ret; 126062306a36Sopenharmony_ci sync_needed = true; 126162306a36Sopenharmony_ci } 126262306a36Sopenharmony_ci 126362306a36Sopenharmony_ci /* cipher out */ 126462306a36Sopenharmony_ci if (areq->src != areq->dst) { 126562306a36Sopenharmony_ci sg_count = edesc->dst_nents ? : 1; 126662306a36Sopenharmony_ci if (!is_sec1 || sg_count == 1) 126762306a36Sopenharmony_ci dma_map_sg(dev, areq->dst, sg_count, DMA_FROM_DEVICE); 126862306a36Sopenharmony_ci } 126962306a36Sopenharmony_ci 127062306a36Sopenharmony_ci if (is_ipsec_esp && encrypt) 127162306a36Sopenharmony_ci elen = authsize; 127262306a36Sopenharmony_ci else 127362306a36Sopenharmony_ci elen = 0; 127462306a36Sopenharmony_ci ret = talitos_sg_map_ext(dev, areq->dst, cryptlen, edesc, &desc->ptr[5], 127562306a36Sopenharmony_ci sg_count, areq->assoclen, tbl_off, elen, 127662306a36Sopenharmony_ci is_ipsec_esp && !encrypt, 1); 127762306a36Sopenharmony_ci tbl_off += ret; 127862306a36Sopenharmony_ci 127962306a36Sopenharmony_ci if (!encrypt && is_ipsec_esp) { 128062306a36Sopenharmony_ci struct talitos_ptr *tbl_ptr = &edesc->link_tbl[tbl_off]; 128162306a36Sopenharmony_ci 128262306a36Sopenharmony_ci /* Add an entry to the link table for ICV data */ 128362306a36Sopenharmony_ci to_talitos_ptr_ext_set(tbl_ptr - 1, 0, is_sec1); 128462306a36Sopenharmony_ci to_talitos_ptr_ext_set(tbl_ptr, DESC_PTR_LNKTBL_RET, is_sec1); 128562306a36Sopenharmony_ci 128662306a36Sopenharmony_ci /* icv data follows link tables */ 128762306a36Sopenharmony_ci to_talitos_ptr(tbl_ptr, dma_icv, authsize, is_sec1); 128862306a36Sopenharmony_ci to_talitos_ptr_ext_or(&desc->ptr[5], authsize, is_sec1); 128962306a36Sopenharmony_ci sync_needed = true; 129062306a36Sopenharmony_ci } else if (!encrypt) { 129162306a36Sopenharmony_ci to_talitos_ptr(&desc->ptr[6], dma_icv, authsize, is_sec1); 129262306a36Sopenharmony_ci sync_needed = true; 129362306a36Sopenharmony_ci } else if (!is_ipsec_esp) { 129462306a36Sopenharmony_ci talitos_sg_map(dev, areq->dst, authsize, edesc, &desc->ptr[6], 129562306a36Sopenharmony_ci sg_count, areq->assoclen + cryptlen, tbl_off); 129662306a36Sopenharmony_ci } 129762306a36Sopenharmony_ci 129862306a36Sopenharmony_ci /* iv out */ 129962306a36Sopenharmony_ci if (is_ipsec_esp) 130062306a36Sopenharmony_ci map_single_talitos_ptr(dev, &desc->ptr[6], ivsize, ctx->iv, 130162306a36Sopenharmony_ci DMA_FROM_DEVICE); 130262306a36Sopenharmony_ci 130362306a36Sopenharmony_ci if (sync_needed) 130462306a36Sopenharmony_ci dma_sync_single_for_device(dev, edesc->dma_link_tbl, 130562306a36Sopenharmony_ci edesc->dma_len, 130662306a36Sopenharmony_ci DMA_BIDIRECTIONAL); 130762306a36Sopenharmony_ci 130862306a36Sopenharmony_ci ret = talitos_submit(dev, ctx->ch, desc, callback, areq); 130962306a36Sopenharmony_ci if (ret != -EINPROGRESS) { 131062306a36Sopenharmony_ci ipsec_esp_unmap(dev, edesc, areq, encrypt); 131162306a36Sopenharmony_ci kfree(edesc); 131262306a36Sopenharmony_ci } 131362306a36Sopenharmony_ci return ret; 131462306a36Sopenharmony_ci} 131562306a36Sopenharmony_ci 131662306a36Sopenharmony_ci/* 131762306a36Sopenharmony_ci * allocate and map the extended descriptor 131862306a36Sopenharmony_ci */ 131962306a36Sopenharmony_cistatic struct talitos_edesc *talitos_edesc_alloc(struct device *dev, 132062306a36Sopenharmony_ci struct scatterlist *src, 132162306a36Sopenharmony_ci struct scatterlist *dst, 132262306a36Sopenharmony_ci u8 *iv, 132362306a36Sopenharmony_ci unsigned int assoclen, 132462306a36Sopenharmony_ci unsigned int cryptlen, 132562306a36Sopenharmony_ci unsigned int authsize, 132662306a36Sopenharmony_ci unsigned int ivsize, 132762306a36Sopenharmony_ci int icv_stashing, 132862306a36Sopenharmony_ci u32 cryptoflags, 132962306a36Sopenharmony_ci bool encrypt) 133062306a36Sopenharmony_ci{ 133162306a36Sopenharmony_ci struct talitos_edesc *edesc; 133262306a36Sopenharmony_ci int src_nents, dst_nents, alloc_len, dma_len, src_len, dst_len; 133362306a36Sopenharmony_ci dma_addr_t iv_dma = 0; 133462306a36Sopenharmony_ci gfp_t flags = cryptoflags & CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL : 133562306a36Sopenharmony_ci GFP_ATOMIC; 133662306a36Sopenharmony_ci struct talitos_private *priv = dev_get_drvdata(dev); 133762306a36Sopenharmony_ci bool is_sec1 = has_ftr_sec1(priv); 133862306a36Sopenharmony_ci int max_len = is_sec1 ? TALITOS1_MAX_DATA_LEN : TALITOS2_MAX_DATA_LEN; 133962306a36Sopenharmony_ci 134062306a36Sopenharmony_ci if (cryptlen + authsize > max_len) { 134162306a36Sopenharmony_ci dev_err(dev, "length exceeds h/w max limit\n"); 134262306a36Sopenharmony_ci return ERR_PTR(-EINVAL); 134362306a36Sopenharmony_ci } 134462306a36Sopenharmony_ci 134562306a36Sopenharmony_ci if (!dst || dst == src) { 134662306a36Sopenharmony_ci src_len = assoclen + cryptlen + authsize; 134762306a36Sopenharmony_ci src_nents = sg_nents_for_len(src, src_len); 134862306a36Sopenharmony_ci if (src_nents < 0) { 134962306a36Sopenharmony_ci dev_err(dev, "Invalid number of src SG.\n"); 135062306a36Sopenharmony_ci return ERR_PTR(-EINVAL); 135162306a36Sopenharmony_ci } 135262306a36Sopenharmony_ci src_nents = (src_nents == 1) ? 0 : src_nents; 135362306a36Sopenharmony_ci dst_nents = dst ? src_nents : 0; 135462306a36Sopenharmony_ci dst_len = 0; 135562306a36Sopenharmony_ci } else { /* dst && dst != src*/ 135662306a36Sopenharmony_ci src_len = assoclen + cryptlen + (encrypt ? 0 : authsize); 135762306a36Sopenharmony_ci src_nents = sg_nents_for_len(src, src_len); 135862306a36Sopenharmony_ci if (src_nents < 0) { 135962306a36Sopenharmony_ci dev_err(dev, "Invalid number of src SG.\n"); 136062306a36Sopenharmony_ci return ERR_PTR(-EINVAL); 136162306a36Sopenharmony_ci } 136262306a36Sopenharmony_ci src_nents = (src_nents == 1) ? 0 : src_nents; 136362306a36Sopenharmony_ci dst_len = assoclen + cryptlen + (encrypt ? authsize : 0); 136462306a36Sopenharmony_ci dst_nents = sg_nents_for_len(dst, dst_len); 136562306a36Sopenharmony_ci if (dst_nents < 0) { 136662306a36Sopenharmony_ci dev_err(dev, "Invalid number of dst SG.\n"); 136762306a36Sopenharmony_ci return ERR_PTR(-EINVAL); 136862306a36Sopenharmony_ci } 136962306a36Sopenharmony_ci dst_nents = (dst_nents == 1) ? 0 : dst_nents; 137062306a36Sopenharmony_ci } 137162306a36Sopenharmony_ci 137262306a36Sopenharmony_ci /* 137362306a36Sopenharmony_ci * allocate space for base edesc plus the link tables, 137462306a36Sopenharmony_ci * allowing for two separate entries for AD and generated ICV (+ 2), 137562306a36Sopenharmony_ci * and space for two sets of ICVs (stashed and generated) 137662306a36Sopenharmony_ci */ 137762306a36Sopenharmony_ci alloc_len = sizeof(struct talitos_edesc); 137862306a36Sopenharmony_ci if (src_nents || dst_nents || !encrypt) { 137962306a36Sopenharmony_ci if (is_sec1) 138062306a36Sopenharmony_ci dma_len = (src_nents ? src_len : 0) + 138162306a36Sopenharmony_ci (dst_nents ? dst_len : 0) + authsize; 138262306a36Sopenharmony_ci else 138362306a36Sopenharmony_ci dma_len = (src_nents + dst_nents + 2) * 138462306a36Sopenharmony_ci sizeof(struct talitos_ptr) + authsize; 138562306a36Sopenharmony_ci alloc_len += dma_len; 138662306a36Sopenharmony_ci } else { 138762306a36Sopenharmony_ci dma_len = 0; 138862306a36Sopenharmony_ci } 138962306a36Sopenharmony_ci alloc_len += icv_stashing ? authsize : 0; 139062306a36Sopenharmony_ci 139162306a36Sopenharmony_ci /* if its a ahash, add space for a second desc next to the first one */ 139262306a36Sopenharmony_ci if (is_sec1 && !dst) 139362306a36Sopenharmony_ci alloc_len += sizeof(struct talitos_desc); 139462306a36Sopenharmony_ci alloc_len += ivsize; 139562306a36Sopenharmony_ci 139662306a36Sopenharmony_ci edesc = kmalloc(ALIGN(alloc_len, dma_get_cache_alignment()), flags); 139762306a36Sopenharmony_ci if (!edesc) 139862306a36Sopenharmony_ci return ERR_PTR(-ENOMEM); 139962306a36Sopenharmony_ci if (ivsize) { 140062306a36Sopenharmony_ci iv = memcpy(((u8 *)edesc) + alloc_len - ivsize, iv, ivsize); 140162306a36Sopenharmony_ci iv_dma = dma_map_single(dev, iv, ivsize, DMA_TO_DEVICE); 140262306a36Sopenharmony_ci } 140362306a36Sopenharmony_ci memset(&edesc->desc, 0, sizeof(edesc->desc)); 140462306a36Sopenharmony_ci 140562306a36Sopenharmony_ci edesc->src_nents = src_nents; 140662306a36Sopenharmony_ci edesc->dst_nents = dst_nents; 140762306a36Sopenharmony_ci edesc->iv_dma = iv_dma; 140862306a36Sopenharmony_ci edesc->dma_len = dma_len; 140962306a36Sopenharmony_ci if (dma_len) 141062306a36Sopenharmony_ci edesc->dma_link_tbl = dma_map_single(dev, &edesc->link_tbl[0], 141162306a36Sopenharmony_ci edesc->dma_len, 141262306a36Sopenharmony_ci DMA_BIDIRECTIONAL); 141362306a36Sopenharmony_ci 141462306a36Sopenharmony_ci return edesc; 141562306a36Sopenharmony_ci} 141662306a36Sopenharmony_ci 141762306a36Sopenharmony_cistatic struct talitos_edesc *aead_edesc_alloc(struct aead_request *areq, u8 *iv, 141862306a36Sopenharmony_ci int icv_stashing, bool encrypt) 141962306a36Sopenharmony_ci{ 142062306a36Sopenharmony_ci struct crypto_aead *authenc = crypto_aead_reqtfm(areq); 142162306a36Sopenharmony_ci unsigned int authsize = crypto_aead_authsize(authenc); 142262306a36Sopenharmony_ci struct talitos_ctx *ctx = crypto_aead_ctx(authenc); 142362306a36Sopenharmony_ci unsigned int ivsize = crypto_aead_ivsize(authenc); 142462306a36Sopenharmony_ci unsigned int cryptlen = areq->cryptlen - (encrypt ? 0 : authsize); 142562306a36Sopenharmony_ci 142662306a36Sopenharmony_ci return talitos_edesc_alloc(ctx->dev, areq->src, areq->dst, 142762306a36Sopenharmony_ci iv, areq->assoclen, cryptlen, 142862306a36Sopenharmony_ci authsize, ivsize, icv_stashing, 142962306a36Sopenharmony_ci areq->base.flags, encrypt); 143062306a36Sopenharmony_ci} 143162306a36Sopenharmony_ci 143262306a36Sopenharmony_cistatic int aead_encrypt(struct aead_request *req) 143362306a36Sopenharmony_ci{ 143462306a36Sopenharmony_ci struct crypto_aead *authenc = crypto_aead_reqtfm(req); 143562306a36Sopenharmony_ci struct talitos_ctx *ctx = crypto_aead_ctx(authenc); 143662306a36Sopenharmony_ci struct talitos_edesc *edesc; 143762306a36Sopenharmony_ci 143862306a36Sopenharmony_ci /* allocate extended descriptor */ 143962306a36Sopenharmony_ci edesc = aead_edesc_alloc(req, req->iv, 0, true); 144062306a36Sopenharmony_ci if (IS_ERR(edesc)) 144162306a36Sopenharmony_ci return PTR_ERR(edesc); 144262306a36Sopenharmony_ci 144362306a36Sopenharmony_ci /* set encrypt */ 144462306a36Sopenharmony_ci edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_MODE0_ENCRYPT; 144562306a36Sopenharmony_ci 144662306a36Sopenharmony_ci return ipsec_esp(edesc, req, true, ipsec_esp_encrypt_done); 144762306a36Sopenharmony_ci} 144862306a36Sopenharmony_ci 144962306a36Sopenharmony_cistatic int aead_decrypt(struct aead_request *req) 145062306a36Sopenharmony_ci{ 145162306a36Sopenharmony_ci struct crypto_aead *authenc = crypto_aead_reqtfm(req); 145262306a36Sopenharmony_ci unsigned int authsize = crypto_aead_authsize(authenc); 145362306a36Sopenharmony_ci struct talitos_ctx *ctx = crypto_aead_ctx(authenc); 145462306a36Sopenharmony_ci struct talitos_private *priv = dev_get_drvdata(ctx->dev); 145562306a36Sopenharmony_ci struct talitos_edesc *edesc; 145662306a36Sopenharmony_ci void *icvdata; 145762306a36Sopenharmony_ci 145862306a36Sopenharmony_ci /* allocate extended descriptor */ 145962306a36Sopenharmony_ci edesc = aead_edesc_alloc(req, req->iv, 1, false); 146062306a36Sopenharmony_ci if (IS_ERR(edesc)) 146162306a36Sopenharmony_ci return PTR_ERR(edesc); 146262306a36Sopenharmony_ci 146362306a36Sopenharmony_ci if ((edesc->desc.hdr & DESC_HDR_TYPE_IPSEC_ESP) && 146462306a36Sopenharmony_ci (priv->features & TALITOS_FTR_HW_AUTH_CHECK) && 146562306a36Sopenharmony_ci ((!edesc->src_nents && !edesc->dst_nents) || 146662306a36Sopenharmony_ci priv->features & TALITOS_FTR_SRC_LINK_TBL_LEN_INCLUDES_EXTENT)) { 146762306a36Sopenharmony_ci 146862306a36Sopenharmony_ci /* decrypt and check the ICV */ 146962306a36Sopenharmony_ci edesc->desc.hdr = ctx->desc_hdr_template | 147062306a36Sopenharmony_ci DESC_HDR_DIR_INBOUND | 147162306a36Sopenharmony_ci DESC_HDR_MODE1_MDEU_CICV; 147262306a36Sopenharmony_ci 147362306a36Sopenharmony_ci /* reset integrity check result bits */ 147462306a36Sopenharmony_ci 147562306a36Sopenharmony_ci return ipsec_esp(edesc, req, false, 147662306a36Sopenharmony_ci ipsec_esp_decrypt_hwauth_done); 147762306a36Sopenharmony_ci } 147862306a36Sopenharmony_ci 147962306a36Sopenharmony_ci /* Have to check the ICV with software */ 148062306a36Sopenharmony_ci edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_DIR_INBOUND; 148162306a36Sopenharmony_ci 148262306a36Sopenharmony_ci /* stash incoming ICV for later cmp with ICV generated by the h/w */ 148362306a36Sopenharmony_ci icvdata = edesc->buf + edesc->dma_len; 148462306a36Sopenharmony_ci 148562306a36Sopenharmony_ci sg_pcopy_to_buffer(req->src, edesc->src_nents ? : 1, icvdata, authsize, 148662306a36Sopenharmony_ci req->assoclen + req->cryptlen - authsize); 148762306a36Sopenharmony_ci 148862306a36Sopenharmony_ci return ipsec_esp(edesc, req, false, ipsec_esp_decrypt_swauth_done); 148962306a36Sopenharmony_ci} 149062306a36Sopenharmony_ci 149162306a36Sopenharmony_cistatic int skcipher_setkey(struct crypto_skcipher *cipher, 149262306a36Sopenharmony_ci const u8 *key, unsigned int keylen) 149362306a36Sopenharmony_ci{ 149462306a36Sopenharmony_ci struct talitos_ctx *ctx = crypto_skcipher_ctx(cipher); 149562306a36Sopenharmony_ci struct device *dev = ctx->dev; 149662306a36Sopenharmony_ci 149762306a36Sopenharmony_ci if (ctx->keylen) 149862306a36Sopenharmony_ci dma_unmap_single(dev, ctx->dma_key, ctx->keylen, DMA_TO_DEVICE); 149962306a36Sopenharmony_ci 150062306a36Sopenharmony_ci memcpy(&ctx->key, key, keylen); 150162306a36Sopenharmony_ci ctx->keylen = keylen; 150262306a36Sopenharmony_ci 150362306a36Sopenharmony_ci ctx->dma_key = dma_map_single(dev, ctx->key, keylen, DMA_TO_DEVICE); 150462306a36Sopenharmony_ci 150562306a36Sopenharmony_ci return 0; 150662306a36Sopenharmony_ci} 150762306a36Sopenharmony_ci 150862306a36Sopenharmony_cistatic int skcipher_des_setkey(struct crypto_skcipher *cipher, 150962306a36Sopenharmony_ci const u8 *key, unsigned int keylen) 151062306a36Sopenharmony_ci{ 151162306a36Sopenharmony_ci return verify_skcipher_des_key(cipher, key) ?: 151262306a36Sopenharmony_ci skcipher_setkey(cipher, key, keylen); 151362306a36Sopenharmony_ci} 151462306a36Sopenharmony_ci 151562306a36Sopenharmony_cistatic int skcipher_des3_setkey(struct crypto_skcipher *cipher, 151662306a36Sopenharmony_ci const u8 *key, unsigned int keylen) 151762306a36Sopenharmony_ci{ 151862306a36Sopenharmony_ci return verify_skcipher_des3_key(cipher, key) ?: 151962306a36Sopenharmony_ci skcipher_setkey(cipher, key, keylen); 152062306a36Sopenharmony_ci} 152162306a36Sopenharmony_ci 152262306a36Sopenharmony_cistatic int skcipher_aes_setkey(struct crypto_skcipher *cipher, 152362306a36Sopenharmony_ci const u8 *key, unsigned int keylen) 152462306a36Sopenharmony_ci{ 152562306a36Sopenharmony_ci if (keylen == AES_KEYSIZE_128 || keylen == AES_KEYSIZE_192 || 152662306a36Sopenharmony_ci keylen == AES_KEYSIZE_256) 152762306a36Sopenharmony_ci return skcipher_setkey(cipher, key, keylen); 152862306a36Sopenharmony_ci 152962306a36Sopenharmony_ci return -EINVAL; 153062306a36Sopenharmony_ci} 153162306a36Sopenharmony_ci 153262306a36Sopenharmony_cistatic void common_nonsnoop_unmap(struct device *dev, 153362306a36Sopenharmony_ci struct talitos_edesc *edesc, 153462306a36Sopenharmony_ci struct skcipher_request *areq) 153562306a36Sopenharmony_ci{ 153662306a36Sopenharmony_ci unmap_single_talitos_ptr(dev, &edesc->desc.ptr[5], DMA_FROM_DEVICE); 153762306a36Sopenharmony_ci 153862306a36Sopenharmony_ci talitos_sg_unmap(dev, edesc, areq->src, areq->dst, areq->cryptlen, 0); 153962306a36Sopenharmony_ci unmap_single_talitos_ptr(dev, &edesc->desc.ptr[1], DMA_TO_DEVICE); 154062306a36Sopenharmony_ci 154162306a36Sopenharmony_ci if (edesc->dma_len) 154262306a36Sopenharmony_ci dma_unmap_single(dev, edesc->dma_link_tbl, edesc->dma_len, 154362306a36Sopenharmony_ci DMA_BIDIRECTIONAL); 154462306a36Sopenharmony_ci} 154562306a36Sopenharmony_ci 154662306a36Sopenharmony_cistatic void skcipher_done(struct device *dev, 154762306a36Sopenharmony_ci struct talitos_desc *desc, void *context, 154862306a36Sopenharmony_ci int err) 154962306a36Sopenharmony_ci{ 155062306a36Sopenharmony_ci struct skcipher_request *areq = context; 155162306a36Sopenharmony_ci struct crypto_skcipher *cipher = crypto_skcipher_reqtfm(areq); 155262306a36Sopenharmony_ci struct talitos_ctx *ctx = crypto_skcipher_ctx(cipher); 155362306a36Sopenharmony_ci unsigned int ivsize = crypto_skcipher_ivsize(cipher); 155462306a36Sopenharmony_ci struct talitos_edesc *edesc; 155562306a36Sopenharmony_ci 155662306a36Sopenharmony_ci edesc = container_of(desc, struct talitos_edesc, desc); 155762306a36Sopenharmony_ci 155862306a36Sopenharmony_ci common_nonsnoop_unmap(dev, edesc, areq); 155962306a36Sopenharmony_ci memcpy(areq->iv, ctx->iv, ivsize); 156062306a36Sopenharmony_ci 156162306a36Sopenharmony_ci kfree(edesc); 156262306a36Sopenharmony_ci 156362306a36Sopenharmony_ci skcipher_request_complete(areq, err); 156462306a36Sopenharmony_ci} 156562306a36Sopenharmony_ci 156662306a36Sopenharmony_cistatic int common_nonsnoop(struct talitos_edesc *edesc, 156762306a36Sopenharmony_ci struct skcipher_request *areq, 156862306a36Sopenharmony_ci void (*callback) (struct device *dev, 156962306a36Sopenharmony_ci struct talitos_desc *desc, 157062306a36Sopenharmony_ci void *context, int error)) 157162306a36Sopenharmony_ci{ 157262306a36Sopenharmony_ci struct crypto_skcipher *cipher = crypto_skcipher_reqtfm(areq); 157362306a36Sopenharmony_ci struct talitos_ctx *ctx = crypto_skcipher_ctx(cipher); 157462306a36Sopenharmony_ci struct device *dev = ctx->dev; 157562306a36Sopenharmony_ci struct talitos_desc *desc = &edesc->desc; 157662306a36Sopenharmony_ci unsigned int cryptlen = areq->cryptlen; 157762306a36Sopenharmony_ci unsigned int ivsize = crypto_skcipher_ivsize(cipher); 157862306a36Sopenharmony_ci int sg_count, ret; 157962306a36Sopenharmony_ci bool sync_needed = false; 158062306a36Sopenharmony_ci struct talitos_private *priv = dev_get_drvdata(dev); 158162306a36Sopenharmony_ci bool is_sec1 = has_ftr_sec1(priv); 158262306a36Sopenharmony_ci bool is_ctr = (desc->hdr & DESC_HDR_SEL0_MASK) == DESC_HDR_SEL0_AESU && 158362306a36Sopenharmony_ci (desc->hdr & DESC_HDR_MODE0_AESU_MASK) == DESC_HDR_MODE0_AESU_CTR; 158462306a36Sopenharmony_ci 158562306a36Sopenharmony_ci /* first DWORD empty */ 158662306a36Sopenharmony_ci 158762306a36Sopenharmony_ci /* cipher iv */ 158862306a36Sopenharmony_ci to_talitos_ptr(&desc->ptr[1], edesc->iv_dma, ivsize, is_sec1); 158962306a36Sopenharmony_ci 159062306a36Sopenharmony_ci /* cipher key */ 159162306a36Sopenharmony_ci to_talitos_ptr(&desc->ptr[2], ctx->dma_key, ctx->keylen, is_sec1); 159262306a36Sopenharmony_ci 159362306a36Sopenharmony_ci sg_count = edesc->src_nents ?: 1; 159462306a36Sopenharmony_ci if (is_sec1 && sg_count > 1) 159562306a36Sopenharmony_ci sg_copy_to_buffer(areq->src, sg_count, edesc->buf, 159662306a36Sopenharmony_ci cryptlen); 159762306a36Sopenharmony_ci else 159862306a36Sopenharmony_ci sg_count = dma_map_sg(dev, areq->src, sg_count, 159962306a36Sopenharmony_ci (areq->src == areq->dst) ? 160062306a36Sopenharmony_ci DMA_BIDIRECTIONAL : DMA_TO_DEVICE); 160162306a36Sopenharmony_ci /* 160262306a36Sopenharmony_ci * cipher in 160362306a36Sopenharmony_ci */ 160462306a36Sopenharmony_ci sg_count = talitos_sg_map_ext(dev, areq->src, cryptlen, edesc, &desc->ptr[3], 160562306a36Sopenharmony_ci sg_count, 0, 0, 0, false, is_ctr ? 16 : 1); 160662306a36Sopenharmony_ci if (sg_count > 1) 160762306a36Sopenharmony_ci sync_needed = true; 160862306a36Sopenharmony_ci 160962306a36Sopenharmony_ci /* cipher out */ 161062306a36Sopenharmony_ci if (areq->src != areq->dst) { 161162306a36Sopenharmony_ci sg_count = edesc->dst_nents ? : 1; 161262306a36Sopenharmony_ci if (!is_sec1 || sg_count == 1) 161362306a36Sopenharmony_ci dma_map_sg(dev, areq->dst, sg_count, DMA_FROM_DEVICE); 161462306a36Sopenharmony_ci } 161562306a36Sopenharmony_ci 161662306a36Sopenharmony_ci ret = talitos_sg_map(dev, areq->dst, cryptlen, edesc, &desc->ptr[4], 161762306a36Sopenharmony_ci sg_count, 0, (edesc->src_nents + 1)); 161862306a36Sopenharmony_ci if (ret > 1) 161962306a36Sopenharmony_ci sync_needed = true; 162062306a36Sopenharmony_ci 162162306a36Sopenharmony_ci /* iv out */ 162262306a36Sopenharmony_ci map_single_talitos_ptr(dev, &desc->ptr[5], ivsize, ctx->iv, 162362306a36Sopenharmony_ci DMA_FROM_DEVICE); 162462306a36Sopenharmony_ci 162562306a36Sopenharmony_ci /* last DWORD empty */ 162662306a36Sopenharmony_ci 162762306a36Sopenharmony_ci if (sync_needed) 162862306a36Sopenharmony_ci dma_sync_single_for_device(dev, edesc->dma_link_tbl, 162962306a36Sopenharmony_ci edesc->dma_len, DMA_BIDIRECTIONAL); 163062306a36Sopenharmony_ci 163162306a36Sopenharmony_ci ret = talitos_submit(dev, ctx->ch, desc, callback, areq); 163262306a36Sopenharmony_ci if (ret != -EINPROGRESS) { 163362306a36Sopenharmony_ci common_nonsnoop_unmap(dev, edesc, areq); 163462306a36Sopenharmony_ci kfree(edesc); 163562306a36Sopenharmony_ci } 163662306a36Sopenharmony_ci return ret; 163762306a36Sopenharmony_ci} 163862306a36Sopenharmony_ci 163962306a36Sopenharmony_cistatic struct talitos_edesc *skcipher_edesc_alloc(struct skcipher_request * 164062306a36Sopenharmony_ci areq, bool encrypt) 164162306a36Sopenharmony_ci{ 164262306a36Sopenharmony_ci struct crypto_skcipher *cipher = crypto_skcipher_reqtfm(areq); 164362306a36Sopenharmony_ci struct talitos_ctx *ctx = crypto_skcipher_ctx(cipher); 164462306a36Sopenharmony_ci unsigned int ivsize = crypto_skcipher_ivsize(cipher); 164562306a36Sopenharmony_ci 164662306a36Sopenharmony_ci return talitos_edesc_alloc(ctx->dev, areq->src, areq->dst, 164762306a36Sopenharmony_ci areq->iv, 0, areq->cryptlen, 0, ivsize, 0, 164862306a36Sopenharmony_ci areq->base.flags, encrypt); 164962306a36Sopenharmony_ci} 165062306a36Sopenharmony_ci 165162306a36Sopenharmony_cistatic int skcipher_encrypt(struct skcipher_request *areq) 165262306a36Sopenharmony_ci{ 165362306a36Sopenharmony_ci struct crypto_skcipher *cipher = crypto_skcipher_reqtfm(areq); 165462306a36Sopenharmony_ci struct talitos_ctx *ctx = crypto_skcipher_ctx(cipher); 165562306a36Sopenharmony_ci struct talitos_edesc *edesc; 165662306a36Sopenharmony_ci unsigned int blocksize = 165762306a36Sopenharmony_ci crypto_tfm_alg_blocksize(crypto_skcipher_tfm(cipher)); 165862306a36Sopenharmony_ci 165962306a36Sopenharmony_ci if (!areq->cryptlen) 166062306a36Sopenharmony_ci return 0; 166162306a36Sopenharmony_ci 166262306a36Sopenharmony_ci if (areq->cryptlen % blocksize) 166362306a36Sopenharmony_ci return -EINVAL; 166462306a36Sopenharmony_ci 166562306a36Sopenharmony_ci /* allocate extended descriptor */ 166662306a36Sopenharmony_ci edesc = skcipher_edesc_alloc(areq, true); 166762306a36Sopenharmony_ci if (IS_ERR(edesc)) 166862306a36Sopenharmony_ci return PTR_ERR(edesc); 166962306a36Sopenharmony_ci 167062306a36Sopenharmony_ci /* set encrypt */ 167162306a36Sopenharmony_ci edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_MODE0_ENCRYPT; 167262306a36Sopenharmony_ci 167362306a36Sopenharmony_ci return common_nonsnoop(edesc, areq, skcipher_done); 167462306a36Sopenharmony_ci} 167562306a36Sopenharmony_ci 167662306a36Sopenharmony_cistatic int skcipher_decrypt(struct skcipher_request *areq) 167762306a36Sopenharmony_ci{ 167862306a36Sopenharmony_ci struct crypto_skcipher *cipher = crypto_skcipher_reqtfm(areq); 167962306a36Sopenharmony_ci struct talitos_ctx *ctx = crypto_skcipher_ctx(cipher); 168062306a36Sopenharmony_ci struct talitos_edesc *edesc; 168162306a36Sopenharmony_ci unsigned int blocksize = 168262306a36Sopenharmony_ci crypto_tfm_alg_blocksize(crypto_skcipher_tfm(cipher)); 168362306a36Sopenharmony_ci 168462306a36Sopenharmony_ci if (!areq->cryptlen) 168562306a36Sopenharmony_ci return 0; 168662306a36Sopenharmony_ci 168762306a36Sopenharmony_ci if (areq->cryptlen % blocksize) 168862306a36Sopenharmony_ci return -EINVAL; 168962306a36Sopenharmony_ci 169062306a36Sopenharmony_ci /* allocate extended descriptor */ 169162306a36Sopenharmony_ci edesc = skcipher_edesc_alloc(areq, false); 169262306a36Sopenharmony_ci if (IS_ERR(edesc)) 169362306a36Sopenharmony_ci return PTR_ERR(edesc); 169462306a36Sopenharmony_ci 169562306a36Sopenharmony_ci edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_DIR_INBOUND; 169662306a36Sopenharmony_ci 169762306a36Sopenharmony_ci return common_nonsnoop(edesc, areq, skcipher_done); 169862306a36Sopenharmony_ci} 169962306a36Sopenharmony_ci 170062306a36Sopenharmony_cistatic void common_nonsnoop_hash_unmap(struct device *dev, 170162306a36Sopenharmony_ci struct talitos_edesc *edesc, 170262306a36Sopenharmony_ci struct ahash_request *areq) 170362306a36Sopenharmony_ci{ 170462306a36Sopenharmony_ci struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq); 170562306a36Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); 170662306a36Sopenharmony_ci struct talitos_private *priv = dev_get_drvdata(dev); 170762306a36Sopenharmony_ci bool is_sec1 = has_ftr_sec1(priv); 170862306a36Sopenharmony_ci struct talitos_desc *desc = &edesc->desc; 170962306a36Sopenharmony_ci struct talitos_desc *desc2 = (struct talitos_desc *) 171062306a36Sopenharmony_ci (edesc->buf + edesc->dma_len); 171162306a36Sopenharmony_ci 171262306a36Sopenharmony_ci unmap_single_talitos_ptr(dev, &desc->ptr[5], DMA_FROM_DEVICE); 171362306a36Sopenharmony_ci if (desc->next_desc && 171462306a36Sopenharmony_ci desc->ptr[5].ptr != desc2->ptr[5].ptr) 171562306a36Sopenharmony_ci unmap_single_talitos_ptr(dev, &desc2->ptr[5], DMA_FROM_DEVICE); 171662306a36Sopenharmony_ci if (req_ctx->last) 171762306a36Sopenharmony_ci memcpy(areq->result, req_ctx->hw_context, 171862306a36Sopenharmony_ci crypto_ahash_digestsize(tfm)); 171962306a36Sopenharmony_ci 172062306a36Sopenharmony_ci if (req_ctx->psrc) 172162306a36Sopenharmony_ci talitos_sg_unmap(dev, edesc, req_ctx->psrc, NULL, 0, 0); 172262306a36Sopenharmony_ci 172362306a36Sopenharmony_ci /* When using hashctx-in, must unmap it. */ 172462306a36Sopenharmony_ci if (from_talitos_ptr_len(&desc->ptr[1], is_sec1)) 172562306a36Sopenharmony_ci unmap_single_talitos_ptr(dev, &desc->ptr[1], 172662306a36Sopenharmony_ci DMA_TO_DEVICE); 172762306a36Sopenharmony_ci else if (desc->next_desc) 172862306a36Sopenharmony_ci unmap_single_talitos_ptr(dev, &desc2->ptr[1], 172962306a36Sopenharmony_ci DMA_TO_DEVICE); 173062306a36Sopenharmony_ci 173162306a36Sopenharmony_ci if (is_sec1 && req_ctx->nbuf) 173262306a36Sopenharmony_ci unmap_single_talitos_ptr(dev, &desc->ptr[3], 173362306a36Sopenharmony_ci DMA_TO_DEVICE); 173462306a36Sopenharmony_ci 173562306a36Sopenharmony_ci if (edesc->dma_len) 173662306a36Sopenharmony_ci dma_unmap_single(dev, edesc->dma_link_tbl, edesc->dma_len, 173762306a36Sopenharmony_ci DMA_BIDIRECTIONAL); 173862306a36Sopenharmony_ci 173962306a36Sopenharmony_ci if (desc->next_desc) 174062306a36Sopenharmony_ci dma_unmap_single(dev, be32_to_cpu(desc->next_desc), 174162306a36Sopenharmony_ci TALITOS_DESC_SIZE, DMA_BIDIRECTIONAL); 174262306a36Sopenharmony_ci} 174362306a36Sopenharmony_ci 174462306a36Sopenharmony_cistatic void ahash_done(struct device *dev, 174562306a36Sopenharmony_ci struct talitos_desc *desc, void *context, 174662306a36Sopenharmony_ci int err) 174762306a36Sopenharmony_ci{ 174862306a36Sopenharmony_ci struct ahash_request *areq = context; 174962306a36Sopenharmony_ci struct talitos_edesc *edesc = 175062306a36Sopenharmony_ci container_of(desc, struct talitos_edesc, desc); 175162306a36Sopenharmony_ci struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq); 175262306a36Sopenharmony_ci 175362306a36Sopenharmony_ci if (!req_ctx->last && req_ctx->to_hash_later) { 175462306a36Sopenharmony_ci /* Position any partial block for next update/final/finup */ 175562306a36Sopenharmony_ci req_ctx->buf_idx = (req_ctx->buf_idx + 1) & 1; 175662306a36Sopenharmony_ci req_ctx->nbuf = req_ctx->to_hash_later; 175762306a36Sopenharmony_ci } 175862306a36Sopenharmony_ci common_nonsnoop_hash_unmap(dev, edesc, areq); 175962306a36Sopenharmony_ci 176062306a36Sopenharmony_ci kfree(edesc); 176162306a36Sopenharmony_ci 176262306a36Sopenharmony_ci ahash_request_complete(areq, err); 176362306a36Sopenharmony_ci} 176462306a36Sopenharmony_ci 176562306a36Sopenharmony_ci/* 176662306a36Sopenharmony_ci * SEC1 doesn't like hashing of 0 sized message, so we do the padding 176762306a36Sopenharmony_ci * ourself and submit a padded block 176862306a36Sopenharmony_ci */ 176962306a36Sopenharmony_cistatic void talitos_handle_buggy_hash(struct talitos_ctx *ctx, 177062306a36Sopenharmony_ci struct talitos_edesc *edesc, 177162306a36Sopenharmony_ci struct talitos_ptr *ptr) 177262306a36Sopenharmony_ci{ 177362306a36Sopenharmony_ci static u8 padded_hash[64] = { 177462306a36Sopenharmony_ci 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 177562306a36Sopenharmony_ci 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 177662306a36Sopenharmony_ci 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 177762306a36Sopenharmony_ci 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 177862306a36Sopenharmony_ci }; 177962306a36Sopenharmony_ci 178062306a36Sopenharmony_ci pr_err_once("Bug in SEC1, padding ourself\n"); 178162306a36Sopenharmony_ci edesc->desc.hdr &= ~DESC_HDR_MODE0_MDEU_PAD; 178262306a36Sopenharmony_ci map_single_talitos_ptr(ctx->dev, ptr, sizeof(padded_hash), 178362306a36Sopenharmony_ci (char *)padded_hash, DMA_TO_DEVICE); 178462306a36Sopenharmony_ci} 178562306a36Sopenharmony_ci 178662306a36Sopenharmony_cistatic int common_nonsnoop_hash(struct talitos_edesc *edesc, 178762306a36Sopenharmony_ci struct ahash_request *areq, unsigned int length, 178862306a36Sopenharmony_ci void (*callback) (struct device *dev, 178962306a36Sopenharmony_ci struct talitos_desc *desc, 179062306a36Sopenharmony_ci void *context, int error)) 179162306a36Sopenharmony_ci{ 179262306a36Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); 179362306a36Sopenharmony_ci struct talitos_ctx *ctx = crypto_ahash_ctx(tfm); 179462306a36Sopenharmony_ci struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq); 179562306a36Sopenharmony_ci struct device *dev = ctx->dev; 179662306a36Sopenharmony_ci struct talitos_desc *desc = &edesc->desc; 179762306a36Sopenharmony_ci int ret; 179862306a36Sopenharmony_ci bool sync_needed = false; 179962306a36Sopenharmony_ci struct talitos_private *priv = dev_get_drvdata(dev); 180062306a36Sopenharmony_ci bool is_sec1 = has_ftr_sec1(priv); 180162306a36Sopenharmony_ci int sg_count; 180262306a36Sopenharmony_ci 180362306a36Sopenharmony_ci /* first DWORD empty */ 180462306a36Sopenharmony_ci 180562306a36Sopenharmony_ci /* hash context in */ 180662306a36Sopenharmony_ci if (!req_ctx->first || req_ctx->swinit) { 180762306a36Sopenharmony_ci map_single_talitos_ptr_nosync(dev, &desc->ptr[1], 180862306a36Sopenharmony_ci req_ctx->hw_context_size, 180962306a36Sopenharmony_ci req_ctx->hw_context, 181062306a36Sopenharmony_ci DMA_TO_DEVICE); 181162306a36Sopenharmony_ci req_ctx->swinit = 0; 181262306a36Sopenharmony_ci } 181362306a36Sopenharmony_ci /* Indicate next op is not the first. */ 181462306a36Sopenharmony_ci req_ctx->first = 0; 181562306a36Sopenharmony_ci 181662306a36Sopenharmony_ci /* HMAC key */ 181762306a36Sopenharmony_ci if (ctx->keylen) 181862306a36Sopenharmony_ci to_talitos_ptr(&desc->ptr[2], ctx->dma_key, ctx->keylen, 181962306a36Sopenharmony_ci is_sec1); 182062306a36Sopenharmony_ci 182162306a36Sopenharmony_ci if (is_sec1 && req_ctx->nbuf) 182262306a36Sopenharmony_ci length -= req_ctx->nbuf; 182362306a36Sopenharmony_ci 182462306a36Sopenharmony_ci sg_count = edesc->src_nents ?: 1; 182562306a36Sopenharmony_ci if (is_sec1 && sg_count > 1) 182662306a36Sopenharmony_ci sg_copy_to_buffer(req_ctx->psrc, sg_count, edesc->buf, length); 182762306a36Sopenharmony_ci else if (length) 182862306a36Sopenharmony_ci sg_count = dma_map_sg(dev, req_ctx->psrc, sg_count, 182962306a36Sopenharmony_ci DMA_TO_DEVICE); 183062306a36Sopenharmony_ci /* 183162306a36Sopenharmony_ci * data in 183262306a36Sopenharmony_ci */ 183362306a36Sopenharmony_ci if (is_sec1 && req_ctx->nbuf) { 183462306a36Sopenharmony_ci map_single_talitos_ptr(dev, &desc->ptr[3], req_ctx->nbuf, 183562306a36Sopenharmony_ci req_ctx->buf[req_ctx->buf_idx], 183662306a36Sopenharmony_ci DMA_TO_DEVICE); 183762306a36Sopenharmony_ci } else { 183862306a36Sopenharmony_ci sg_count = talitos_sg_map(dev, req_ctx->psrc, length, edesc, 183962306a36Sopenharmony_ci &desc->ptr[3], sg_count, 0, 0); 184062306a36Sopenharmony_ci if (sg_count > 1) 184162306a36Sopenharmony_ci sync_needed = true; 184262306a36Sopenharmony_ci } 184362306a36Sopenharmony_ci 184462306a36Sopenharmony_ci /* fifth DWORD empty */ 184562306a36Sopenharmony_ci 184662306a36Sopenharmony_ci /* hash/HMAC out -or- hash context out */ 184762306a36Sopenharmony_ci if (req_ctx->last) 184862306a36Sopenharmony_ci map_single_talitos_ptr(dev, &desc->ptr[5], 184962306a36Sopenharmony_ci crypto_ahash_digestsize(tfm), 185062306a36Sopenharmony_ci req_ctx->hw_context, DMA_FROM_DEVICE); 185162306a36Sopenharmony_ci else 185262306a36Sopenharmony_ci map_single_talitos_ptr_nosync(dev, &desc->ptr[5], 185362306a36Sopenharmony_ci req_ctx->hw_context_size, 185462306a36Sopenharmony_ci req_ctx->hw_context, 185562306a36Sopenharmony_ci DMA_FROM_DEVICE); 185662306a36Sopenharmony_ci 185762306a36Sopenharmony_ci /* last DWORD empty */ 185862306a36Sopenharmony_ci 185962306a36Sopenharmony_ci if (is_sec1 && from_talitos_ptr_len(&desc->ptr[3], true) == 0) 186062306a36Sopenharmony_ci talitos_handle_buggy_hash(ctx, edesc, &desc->ptr[3]); 186162306a36Sopenharmony_ci 186262306a36Sopenharmony_ci if (is_sec1 && req_ctx->nbuf && length) { 186362306a36Sopenharmony_ci struct talitos_desc *desc2 = (struct talitos_desc *) 186462306a36Sopenharmony_ci (edesc->buf + edesc->dma_len); 186562306a36Sopenharmony_ci dma_addr_t next_desc; 186662306a36Sopenharmony_ci 186762306a36Sopenharmony_ci memset(desc2, 0, sizeof(*desc2)); 186862306a36Sopenharmony_ci desc2->hdr = desc->hdr; 186962306a36Sopenharmony_ci desc2->hdr &= ~DESC_HDR_MODE0_MDEU_INIT; 187062306a36Sopenharmony_ci desc2->hdr1 = desc2->hdr; 187162306a36Sopenharmony_ci desc->hdr &= ~DESC_HDR_MODE0_MDEU_PAD; 187262306a36Sopenharmony_ci desc->hdr |= DESC_HDR_MODE0_MDEU_CONT; 187362306a36Sopenharmony_ci desc->hdr &= ~DESC_HDR_DONE_NOTIFY; 187462306a36Sopenharmony_ci 187562306a36Sopenharmony_ci if (desc->ptr[1].ptr) 187662306a36Sopenharmony_ci copy_talitos_ptr(&desc2->ptr[1], &desc->ptr[1], 187762306a36Sopenharmony_ci is_sec1); 187862306a36Sopenharmony_ci else 187962306a36Sopenharmony_ci map_single_talitos_ptr_nosync(dev, &desc2->ptr[1], 188062306a36Sopenharmony_ci req_ctx->hw_context_size, 188162306a36Sopenharmony_ci req_ctx->hw_context, 188262306a36Sopenharmony_ci DMA_TO_DEVICE); 188362306a36Sopenharmony_ci copy_talitos_ptr(&desc2->ptr[2], &desc->ptr[2], is_sec1); 188462306a36Sopenharmony_ci sg_count = talitos_sg_map(dev, req_ctx->psrc, length, edesc, 188562306a36Sopenharmony_ci &desc2->ptr[3], sg_count, 0, 0); 188662306a36Sopenharmony_ci if (sg_count > 1) 188762306a36Sopenharmony_ci sync_needed = true; 188862306a36Sopenharmony_ci copy_talitos_ptr(&desc2->ptr[5], &desc->ptr[5], is_sec1); 188962306a36Sopenharmony_ci if (req_ctx->last) 189062306a36Sopenharmony_ci map_single_talitos_ptr_nosync(dev, &desc->ptr[5], 189162306a36Sopenharmony_ci req_ctx->hw_context_size, 189262306a36Sopenharmony_ci req_ctx->hw_context, 189362306a36Sopenharmony_ci DMA_FROM_DEVICE); 189462306a36Sopenharmony_ci 189562306a36Sopenharmony_ci next_desc = dma_map_single(dev, &desc2->hdr1, TALITOS_DESC_SIZE, 189662306a36Sopenharmony_ci DMA_BIDIRECTIONAL); 189762306a36Sopenharmony_ci desc->next_desc = cpu_to_be32(next_desc); 189862306a36Sopenharmony_ci } 189962306a36Sopenharmony_ci 190062306a36Sopenharmony_ci if (sync_needed) 190162306a36Sopenharmony_ci dma_sync_single_for_device(dev, edesc->dma_link_tbl, 190262306a36Sopenharmony_ci edesc->dma_len, DMA_BIDIRECTIONAL); 190362306a36Sopenharmony_ci 190462306a36Sopenharmony_ci ret = talitos_submit(dev, ctx->ch, desc, callback, areq); 190562306a36Sopenharmony_ci if (ret != -EINPROGRESS) { 190662306a36Sopenharmony_ci common_nonsnoop_hash_unmap(dev, edesc, areq); 190762306a36Sopenharmony_ci kfree(edesc); 190862306a36Sopenharmony_ci } 190962306a36Sopenharmony_ci return ret; 191062306a36Sopenharmony_ci} 191162306a36Sopenharmony_ci 191262306a36Sopenharmony_cistatic struct talitos_edesc *ahash_edesc_alloc(struct ahash_request *areq, 191362306a36Sopenharmony_ci unsigned int nbytes) 191462306a36Sopenharmony_ci{ 191562306a36Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); 191662306a36Sopenharmony_ci struct talitos_ctx *ctx = crypto_ahash_ctx(tfm); 191762306a36Sopenharmony_ci struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq); 191862306a36Sopenharmony_ci struct talitos_private *priv = dev_get_drvdata(ctx->dev); 191962306a36Sopenharmony_ci bool is_sec1 = has_ftr_sec1(priv); 192062306a36Sopenharmony_ci 192162306a36Sopenharmony_ci if (is_sec1) 192262306a36Sopenharmony_ci nbytes -= req_ctx->nbuf; 192362306a36Sopenharmony_ci 192462306a36Sopenharmony_ci return talitos_edesc_alloc(ctx->dev, req_ctx->psrc, NULL, NULL, 0, 192562306a36Sopenharmony_ci nbytes, 0, 0, 0, areq->base.flags, false); 192662306a36Sopenharmony_ci} 192762306a36Sopenharmony_ci 192862306a36Sopenharmony_cistatic int ahash_init(struct ahash_request *areq) 192962306a36Sopenharmony_ci{ 193062306a36Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); 193162306a36Sopenharmony_ci struct talitos_ctx *ctx = crypto_ahash_ctx(tfm); 193262306a36Sopenharmony_ci struct device *dev = ctx->dev; 193362306a36Sopenharmony_ci struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq); 193462306a36Sopenharmony_ci unsigned int size; 193562306a36Sopenharmony_ci dma_addr_t dma; 193662306a36Sopenharmony_ci 193762306a36Sopenharmony_ci /* Initialize the context */ 193862306a36Sopenharmony_ci req_ctx->buf_idx = 0; 193962306a36Sopenharmony_ci req_ctx->nbuf = 0; 194062306a36Sopenharmony_ci req_ctx->first = 1; /* first indicates h/w must init its context */ 194162306a36Sopenharmony_ci req_ctx->swinit = 0; /* assume h/w init of context */ 194262306a36Sopenharmony_ci size = (crypto_ahash_digestsize(tfm) <= SHA256_DIGEST_SIZE) 194362306a36Sopenharmony_ci ? TALITOS_MDEU_CONTEXT_SIZE_MD5_SHA1_SHA256 194462306a36Sopenharmony_ci : TALITOS_MDEU_CONTEXT_SIZE_SHA384_SHA512; 194562306a36Sopenharmony_ci req_ctx->hw_context_size = size; 194662306a36Sopenharmony_ci 194762306a36Sopenharmony_ci dma = dma_map_single(dev, req_ctx->hw_context, req_ctx->hw_context_size, 194862306a36Sopenharmony_ci DMA_TO_DEVICE); 194962306a36Sopenharmony_ci dma_unmap_single(dev, dma, req_ctx->hw_context_size, DMA_TO_DEVICE); 195062306a36Sopenharmony_ci 195162306a36Sopenharmony_ci return 0; 195262306a36Sopenharmony_ci} 195362306a36Sopenharmony_ci 195462306a36Sopenharmony_ci/* 195562306a36Sopenharmony_ci * on h/w without explicit sha224 support, we initialize h/w context 195662306a36Sopenharmony_ci * manually with sha224 constants, and tell it to run sha256. 195762306a36Sopenharmony_ci */ 195862306a36Sopenharmony_cistatic int ahash_init_sha224_swinit(struct ahash_request *areq) 195962306a36Sopenharmony_ci{ 196062306a36Sopenharmony_ci struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq); 196162306a36Sopenharmony_ci 196262306a36Sopenharmony_ci req_ctx->hw_context[0] = SHA224_H0; 196362306a36Sopenharmony_ci req_ctx->hw_context[1] = SHA224_H1; 196462306a36Sopenharmony_ci req_ctx->hw_context[2] = SHA224_H2; 196562306a36Sopenharmony_ci req_ctx->hw_context[3] = SHA224_H3; 196662306a36Sopenharmony_ci req_ctx->hw_context[4] = SHA224_H4; 196762306a36Sopenharmony_ci req_ctx->hw_context[5] = SHA224_H5; 196862306a36Sopenharmony_ci req_ctx->hw_context[6] = SHA224_H6; 196962306a36Sopenharmony_ci req_ctx->hw_context[7] = SHA224_H7; 197062306a36Sopenharmony_ci 197162306a36Sopenharmony_ci /* init 64-bit count */ 197262306a36Sopenharmony_ci req_ctx->hw_context[8] = 0; 197362306a36Sopenharmony_ci req_ctx->hw_context[9] = 0; 197462306a36Sopenharmony_ci 197562306a36Sopenharmony_ci ahash_init(areq); 197662306a36Sopenharmony_ci req_ctx->swinit = 1;/* prevent h/w initting context with sha256 values*/ 197762306a36Sopenharmony_ci 197862306a36Sopenharmony_ci return 0; 197962306a36Sopenharmony_ci} 198062306a36Sopenharmony_ci 198162306a36Sopenharmony_cistatic int ahash_process_req(struct ahash_request *areq, unsigned int nbytes) 198262306a36Sopenharmony_ci{ 198362306a36Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); 198462306a36Sopenharmony_ci struct talitos_ctx *ctx = crypto_ahash_ctx(tfm); 198562306a36Sopenharmony_ci struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq); 198662306a36Sopenharmony_ci struct talitos_edesc *edesc; 198762306a36Sopenharmony_ci unsigned int blocksize = 198862306a36Sopenharmony_ci crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm)); 198962306a36Sopenharmony_ci unsigned int nbytes_to_hash; 199062306a36Sopenharmony_ci unsigned int to_hash_later; 199162306a36Sopenharmony_ci unsigned int nsg; 199262306a36Sopenharmony_ci int nents; 199362306a36Sopenharmony_ci struct device *dev = ctx->dev; 199462306a36Sopenharmony_ci struct talitos_private *priv = dev_get_drvdata(dev); 199562306a36Sopenharmony_ci bool is_sec1 = has_ftr_sec1(priv); 199662306a36Sopenharmony_ci u8 *ctx_buf = req_ctx->buf[req_ctx->buf_idx]; 199762306a36Sopenharmony_ci 199862306a36Sopenharmony_ci if (!req_ctx->last && (nbytes + req_ctx->nbuf <= blocksize)) { 199962306a36Sopenharmony_ci /* Buffer up to one whole block */ 200062306a36Sopenharmony_ci nents = sg_nents_for_len(areq->src, nbytes); 200162306a36Sopenharmony_ci if (nents < 0) { 200262306a36Sopenharmony_ci dev_err(dev, "Invalid number of src SG.\n"); 200362306a36Sopenharmony_ci return nents; 200462306a36Sopenharmony_ci } 200562306a36Sopenharmony_ci sg_copy_to_buffer(areq->src, nents, 200662306a36Sopenharmony_ci ctx_buf + req_ctx->nbuf, nbytes); 200762306a36Sopenharmony_ci req_ctx->nbuf += nbytes; 200862306a36Sopenharmony_ci return 0; 200962306a36Sopenharmony_ci } 201062306a36Sopenharmony_ci 201162306a36Sopenharmony_ci /* At least (blocksize + 1) bytes are available to hash */ 201262306a36Sopenharmony_ci nbytes_to_hash = nbytes + req_ctx->nbuf; 201362306a36Sopenharmony_ci to_hash_later = nbytes_to_hash & (blocksize - 1); 201462306a36Sopenharmony_ci 201562306a36Sopenharmony_ci if (req_ctx->last) 201662306a36Sopenharmony_ci to_hash_later = 0; 201762306a36Sopenharmony_ci else if (to_hash_later) 201862306a36Sopenharmony_ci /* There is a partial block. Hash the full block(s) now */ 201962306a36Sopenharmony_ci nbytes_to_hash -= to_hash_later; 202062306a36Sopenharmony_ci else { 202162306a36Sopenharmony_ci /* Keep one block buffered */ 202262306a36Sopenharmony_ci nbytes_to_hash -= blocksize; 202362306a36Sopenharmony_ci to_hash_later = blocksize; 202462306a36Sopenharmony_ci } 202562306a36Sopenharmony_ci 202662306a36Sopenharmony_ci /* Chain in any previously buffered data */ 202762306a36Sopenharmony_ci if (!is_sec1 && req_ctx->nbuf) { 202862306a36Sopenharmony_ci nsg = (req_ctx->nbuf < nbytes_to_hash) ? 2 : 1; 202962306a36Sopenharmony_ci sg_init_table(req_ctx->bufsl, nsg); 203062306a36Sopenharmony_ci sg_set_buf(req_ctx->bufsl, ctx_buf, req_ctx->nbuf); 203162306a36Sopenharmony_ci if (nsg > 1) 203262306a36Sopenharmony_ci sg_chain(req_ctx->bufsl, 2, areq->src); 203362306a36Sopenharmony_ci req_ctx->psrc = req_ctx->bufsl; 203462306a36Sopenharmony_ci } else if (is_sec1 && req_ctx->nbuf && req_ctx->nbuf < blocksize) { 203562306a36Sopenharmony_ci int offset; 203662306a36Sopenharmony_ci 203762306a36Sopenharmony_ci if (nbytes_to_hash > blocksize) 203862306a36Sopenharmony_ci offset = blocksize - req_ctx->nbuf; 203962306a36Sopenharmony_ci else 204062306a36Sopenharmony_ci offset = nbytes_to_hash - req_ctx->nbuf; 204162306a36Sopenharmony_ci nents = sg_nents_for_len(areq->src, offset); 204262306a36Sopenharmony_ci if (nents < 0) { 204362306a36Sopenharmony_ci dev_err(dev, "Invalid number of src SG.\n"); 204462306a36Sopenharmony_ci return nents; 204562306a36Sopenharmony_ci } 204662306a36Sopenharmony_ci sg_copy_to_buffer(areq->src, nents, 204762306a36Sopenharmony_ci ctx_buf + req_ctx->nbuf, offset); 204862306a36Sopenharmony_ci req_ctx->nbuf += offset; 204962306a36Sopenharmony_ci req_ctx->psrc = scatterwalk_ffwd(req_ctx->bufsl, areq->src, 205062306a36Sopenharmony_ci offset); 205162306a36Sopenharmony_ci } else 205262306a36Sopenharmony_ci req_ctx->psrc = areq->src; 205362306a36Sopenharmony_ci 205462306a36Sopenharmony_ci if (to_hash_later) { 205562306a36Sopenharmony_ci nents = sg_nents_for_len(areq->src, nbytes); 205662306a36Sopenharmony_ci if (nents < 0) { 205762306a36Sopenharmony_ci dev_err(dev, "Invalid number of src SG.\n"); 205862306a36Sopenharmony_ci return nents; 205962306a36Sopenharmony_ci } 206062306a36Sopenharmony_ci sg_pcopy_to_buffer(areq->src, nents, 206162306a36Sopenharmony_ci req_ctx->buf[(req_ctx->buf_idx + 1) & 1], 206262306a36Sopenharmony_ci to_hash_later, 206362306a36Sopenharmony_ci nbytes - to_hash_later); 206462306a36Sopenharmony_ci } 206562306a36Sopenharmony_ci req_ctx->to_hash_later = to_hash_later; 206662306a36Sopenharmony_ci 206762306a36Sopenharmony_ci /* Allocate extended descriptor */ 206862306a36Sopenharmony_ci edesc = ahash_edesc_alloc(areq, nbytes_to_hash); 206962306a36Sopenharmony_ci if (IS_ERR(edesc)) 207062306a36Sopenharmony_ci return PTR_ERR(edesc); 207162306a36Sopenharmony_ci 207262306a36Sopenharmony_ci edesc->desc.hdr = ctx->desc_hdr_template; 207362306a36Sopenharmony_ci 207462306a36Sopenharmony_ci /* On last one, request SEC to pad; otherwise continue */ 207562306a36Sopenharmony_ci if (req_ctx->last) 207662306a36Sopenharmony_ci edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_PAD; 207762306a36Sopenharmony_ci else 207862306a36Sopenharmony_ci edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_CONT; 207962306a36Sopenharmony_ci 208062306a36Sopenharmony_ci /* request SEC to INIT hash. */ 208162306a36Sopenharmony_ci if (req_ctx->first && !req_ctx->swinit) 208262306a36Sopenharmony_ci edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_INIT; 208362306a36Sopenharmony_ci 208462306a36Sopenharmony_ci /* When the tfm context has a keylen, it's an HMAC. 208562306a36Sopenharmony_ci * A first or last (ie. not middle) descriptor must request HMAC. 208662306a36Sopenharmony_ci */ 208762306a36Sopenharmony_ci if (ctx->keylen && (req_ctx->first || req_ctx->last)) 208862306a36Sopenharmony_ci edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_HMAC; 208962306a36Sopenharmony_ci 209062306a36Sopenharmony_ci return common_nonsnoop_hash(edesc, areq, nbytes_to_hash, ahash_done); 209162306a36Sopenharmony_ci} 209262306a36Sopenharmony_ci 209362306a36Sopenharmony_cistatic int ahash_update(struct ahash_request *areq) 209462306a36Sopenharmony_ci{ 209562306a36Sopenharmony_ci struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq); 209662306a36Sopenharmony_ci 209762306a36Sopenharmony_ci req_ctx->last = 0; 209862306a36Sopenharmony_ci 209962306a36Sopenharmony_ci return ahash_process_req(areq, areq->nbytes); 210062306a36Sopenharmony_ci} 210162306a36Sopenharmony_ci 210262306a36Sopenharmony_cistatic int ahash_final(struct ahash_request *areq) 210362306a36Sopenharmony_ci{ 210462306a36Sopenharmony_ci struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq); 210562306a36Sopenharmony_ci 210662306a36Sopenharmony_ci req_ctx->last = 1; 210762306a36Sopenharmony_ci 210862306a36Sopenharmony_ci return ahash_process_req(areq, 0); 210962306a36Sopenharmony_ci} 211062306a36Sopenharmony_ci 211162306a36Sopenharmony_cistatic int ahash_finup(struct ahash_request *areq) 211262306a36Sopenharmony_ci{ 211362306a36Sopenharmony_ci struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq); 211462306a36Sopenharmony_ci 211562306a36Sopenharmony_ci req_ctx->last = 1; 211662306a36Sopenharmony_ci 211762306a36Sopenharmony_ci return ahash_process_req(areq, areq->nbytes); 211862306a36Sopenharmony_ci} 211962306a36Sopenharmony_ci 212062306a36Sopenharmony_cistatic int ahash_digest(struct ahash_request *areq) 212162306a36Sopenharmony_ci{ 212262306a36Sopenharmony_ci struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq); 212362306a36Sopenharmony_ci struct crypto_ahash *ahash = crypto_ahash_reqtfm(areq); 212462306a36Sopenharmony_ci 212562306a36Sopenharmony_ci ahash->init(areq); 212662306a36Sopenharmony_ci req_ctx->last = 1; 212762306a36Sopenharmony_ci 212862306a36Sopenharmony_ci return ahash_process_req(areq, areq->nbytes); 212962306a36Sopenharmony_ci} 213062306a36Sopenharmony_ci 213162306a36Sopenharmony_cistatic int ahash_export(struct ahash_request *areq, void *out) 213262306a36Sopenharmony_ci{ 213362306a36Sopenharmony_ci struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq); 213462306a36Sopenharmony_ci struct talitos_export_state *export = out; 213562306a36Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); 213662306a36Sopenharmony_ci struct talitos_ctx *ctx = crypto_ahash_ctx(tfm); 213762306a36Sopenharmony_ci struct device *dev = ctx->dev; 213862306a36Sopenharmony_ci dma_addr_t dma; 213962306a36Sopenharmony_ci 214062306a36Sopenharmony_ci dma = dma_map_single(dev, req_ctx->hw_context, req_ctx->hw_context_size, 214162306a36Sopenharmony_ci DMA_FROM_DEVICE); 214262306a36Sopenharmony_ci dma_unmap_single(dev, dma, req_ctx->hw_context_size, DMA_FROM_DEVICE); 214362306a36Sopenharmony_ci 214462306a36Sopenharmony_ci memcpy(export->hw_context, req_ctx->hw_context, 214562306a36Sopenharmony_ci req_ctx->hw_context_size); 214662306a36Sopenharmony_ci memcpy(export->buf, req_ctx->buf[req_ctx->buf_idx], req_ctx->nbuf); 214762306a36Sopenharmony_ci export->swinit = req_ctx->swinit; 214862306a36Sopenharmony_ci export->first = req_ctx->first; 214962306a36Sopenharmony_ci export->last = req_ctx->last; 215062306a36Sopenharmony_ci export->to_hash_later = req_ctx->to_hash_later; 215162306a36Sopenharmony_ci export->nbuf = req_ctx->nbuf; 215262306a36Sopenharmony_ci 215362306a36Sopenharmony_ci return 0; 215462306a36Sopenharmony_ci} 215562306a36Sopenharmony_ci 215662306a36Sopenharmony_cistatic int ahash_import(struct ahash_request *areq, const void *in) 215762306a36Sopenharmony_ci{ 215862306a36Sopenharmony_ci struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq); 215962306a36Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); 216062306a36Sopenharmony_ci struct talitos_ctx *ctx = crypto_ahash_ctx(tfm); 216162306a36Sopenharmony_ci struct device *dev = ctx->dev; 216262306a36Sopenharmony_ci const struct talitos_export_state *export = in; 216362306a36Sopenharmony_ci unsigned int size; 216462306a36Sopenharmony_ci dma_addr_t dma; 216562306a36Sopenharmony_ci 216662306a36Sopenharmony_ci memset(req_ctx, 0, sizeof(*req_ctx)); 216762306a36Sopenharmony_ci size = (crypto_ahash_digestsize(tfm) <= SHA256_DIGEST_SIZE) 216862306a36Sopenharmony_ci ? TALITOS_MDEU_CONTEXT_SIZE_MD5_SHA1_SHA256 216962306a36Sopenharmony_ci : TALITOS_MDEU_CONTEXT_SIZE_SHA384_SHA512; 217062306a36Sopenharmony_ci req_ctx->hw_context_size = size; 217162306a36Sopenharmony_ci memcpy(req_ctx->hw_context, export->hw_context, size); 217262306a36Sopenharmony_ci memcpy(req_ctx->buf[0], export->buf, export->nbuf); 217362306a36Sopenharmony_ci req_ctx->swinit = export->swinit; 217462306a36Sopenharmony_ci req_ctx->first = export->first; 217562306a36Sopenharmony_ci req_ctx->last = export->last; 217662306a36Sopenharmony_ci req_ctx->to_hash_later = export->to_hash_later; 217762306a36Sopenharmony_ci req_ctx->nbuf = export->nbuf; 217862306a36Sopenharmony_ci 217962306a36Sopenharmony_ci dma = dma_map_single(dev, req_ctx->hw_context, req_ctx->hw_context_size, 218062306a36Sopenharmony_ci DMA_TO_DEVICE); 218162306a36Sopenharmony_ci dma_unmap_single(dev, dma, req_ctx->hw_context_size, DMA_TO_DEVICE); 218262306a36Sopenharmony_ci 218362306a36Sopenharmony_ci return 0; 218462306a36Sopenharmony_ci} 218562306a36Sopenharmony_ci 218662306a36Sopenharmony_cistatic int keyhash(struct crypto_ahash *tfm, const u8 *key, unsigned int keylen, 218762306a36Sopenharmony_ci u8 *hash) 218862306a36Sopenharmony_ci{ 218962306a36Sopenharmony_ci struct talitos_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm)); 219062306a36Sopenharmony_ci 219162306a36Sopenharmony_ci struct scatterlist sg[1]; 219262306a36Sopenharmony_ci struct ahash_request *req; 219362306a36Sopenharmony_ci struct crypto_wait wait; 219462306a36Sopenharmony_ci int ret; 219562306a36Sopenharmony_ci 219662306a36Sopenharmony_ci crypto_init_wait(&wait); 219762306a36Sopenharmony_ci 219862306a36Sopenharmony_ci req = ahash_request_alloc(tfm, GFP_KERNEL); 219962306a36Sopenharmony_ci if (!req) 220062306a36Sopenharmony_ci return -ENOMEM; 220162306a36Sopenharmony_ci 220262306a36Sopenharmony_ci /* Keep tfm keylen == 0 during hash of the long key */ 220362306a36Sopenharmony_ci ctx->keylen = 0; 220462306a36Sopenharmony_ci ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, 220562306a36Sopenharmony_ci crypto_req_done, &wait); 220662306a36Sopenharmony_ci 220762306a36Sopenharmony_ci sg_init_one(&sg[0], key, keylen); 220862306a36Sopenharmony_ci 220962306a36Sopenharmony_ci ahash_request_set_crypt(req, sg, hash, keylen); 221062306a36Sopenharmony_ci ret = crypto_wait_req(crypto_ahash_digest(req), &wait); 221162306a36Sopenharmony_ci 221262306a36Sopenharmony_ci ahash_request_free(req); 221362306a36Sopenharmony_ci 221462306a36Sopenharmony_ci return ret; 221562306a36Sopenharmony_ci} 221662306a36Sopenharmony_ci 221762306a36Sopenharmony_cistatic int ahash_setkey(struct crypto_ahash *tfm, const u8 *key, 221862306a36Sopenharmony_ci unsigned int keylen) 221962306a36Sopenharmony_ci{ 222062306a36Sopenharmony_ci struct talitos_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm)); 222162306a36Sopenharmony_ci struct device *dev = ctx->dev; 222262306a36Sopenharmony_ci unsigned int blocksize = 222362306a36Sopenharmony_ci crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm)); 222462306a36Sopenharmony_ci unsigned int digestsize = crypto_ahash_digestsize(tfm); 222562306a36Sopenharmony_ci unsigned int keysize = keylen; 222662306a36Sopenharmony_ci u8 hash[SHA512_DIGEST_SIZE]; 222762306a36Sopenharmony_ci int ret; 222862306a36Sopenharmony_ci 222962306a36Sopenharmony_ci if (keylen <= blocksize) 223062306a36Sopenharmony_ci memcpy(ctx->key, key, keysize); 223162306a36Sopenharmony_ci else { 223262306a36Sopenharmony_ci /* Must get the hash of the long key */ 223362306a36Sopenharmony_ci ret = keyhash(tfm, key, keylen, hash); 223462306a36Sopenharmony_ci 223562306a36Sopenharmony_ci if (ret) 223662306a36Sopenharmony_ci return -EINVAL; 223762306a36Sopenharmony_ci 223862306a36Sopenharmony_ci keysize = digestsize; 223962306a36Sopenharmony_ci memcpy(ctx->key, hash, digestsize); 224062306a36Sopenharmony_ci } 224162306a36Sopenharmony_ci 224262306a36Sopenharmony_ci if (ctx->keylen) 224362306a36Sopenharmony_ci dma_unmap_single(dev, ctx->dma_key, ctx->keylen, DMA_TO_DEVICE); 224462306a36Sopenharmony_ci 224562306a36Sopenharmony_ci ctx->keylen = keysize; 224662306a36Sopenharmony_ci ctx->dma_key = dma_map_single(dev, ctx->key, keysize, DMA_TO_DEVICE); 224762306a36Sopenharmony_ci 224862306a36Sopenharmony_ci return 0; 224962306a36Sopenharmony_ci} 225062306a36Sopenharmony_ci 225162306a36Sopenharmony_ci 225262306a36Sopenharmony_cistruct talitos_alg_template { 225362306a36Sopenharmony_ci u32 type; 225462306a36Sopenharmony_ci u32 priority; 225562306a36Sopenharmony_ci union { 225662306a36Sopenharmony_ci struct skcipher_alg skcipher; 225762306a36Sopenharmony_ci struct ahash_alg hash; 225862306a36Sopenharmony_ci struct aead_alg aead; 225962306a36Sopenharmony_ci } alg; 226062306a36Sopenharmony_ci __be32 desc_hdr_template; 226162306a36Sopenharmony_ci}; 226262306a36Sopenharmony_ci 226362306a36Sopenharmony_cistatic struct talitos_alg_template driver_algs[] = { 226462306a36Sopenharmony_ci /* AEAD algorithms. These use a single-pass ipsec_esp descriptor */ 226562306a36Sopenharmony_ci { .type = CRYPTO_ALG_TYPE_AEAD, 226662306a36Sopenharmony_ci .alg.aead = { 226762306a36Sopenharmony_ci .base = { 226862306a36Sopenharmony_ci .cra_name = "authenc(hmac(sha1),cbc(aes))", 226962306a36Sopenharmony_ci .cra_driver_name = "authenc-hmac-sha1-" 227062306a36Sopenharmony_ci "cbc-aes-talitos", 227162306a36Sopenharmony_ci .cra_blocksize = AES_BLOCK_SIZE, 227262306a36Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 227362306a36Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY, 227462306a36Sopenharmony_ci }, 227562306a36Sopenharmony_ci .ivsize = AES_BLOCK_SIZE, 227662306a36Sopenharmony_ci .maxauthsize = SHA1_DIGEST_SIZE, 227762306a36Sopenharmony_ci }, 227862306a36Sopenharmony_ci .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP | 227962306a36Sopenharmony_ci DESC_HDR_SEL0_AESU | 228062306a36Sopenharmony_ci DESC_HDR_MODE0_AESU_CBC | 228162306a36Sopenharmony_ci DESC_HDR_SEL1_MDEUA | 228262306a36Sopenharmony_ci DESC_HDR_MODE1_MDEU_INIT | 228362306a36Sopenharmony_ci DESC_HDR_MODE1_MDEU_PAD | 228462306a36Sopenharmony_ci DESC_HDR_MODE1_MDEU_SHA1_HMAC, 228562306a36Sopenharmony_ci }, 228662306a36Sopenharmony_ci { .type = CRYPTO_ALG_TYPE_AEAD, 228762306a36Sopenharmony_ci .priority = TALITOS_CRA_PRIORITY_AEAD_HSNA, 228862306a36Sopenharmony_ci .alg.aead = { 228962306a36Sopenharmony_ci .base = { 229062306a36Sopenharmony_ci .cra_name = "authenc(hmac(sha1),cbc(aes))", 229162306a36Sopenharmony_ci .cra_driver_name = "authenc-hmac-sha1-" 229262306a36Sopenharmony_ci "cbc-aes-talitos-hsna", 229362306a36Sopenharmony_ci .cra_blocksize = AES_BLOCK_SIZE, 229462306a36Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 229562306a36Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY, 229662306a36Sopenharmony_ci }, 229762306a36Sopenharmony_ci .ivsize = AES_BLOCK_SIZE, 229862306a36Sopenharmony_ci .maxauthsize = SHA1_DIGEST_SIZE, 229962306a36Sopenharmony_ci }, 230062306a36Sopenharmony_ci .desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU | 230162306a36Sopenharmony_ci DESC_HDR_SEL0_AESU | 230262306a36Sopenharmony_ci DESC_HDR_MODE0_AESU_CBC | 230362306a36Sopenharmony_ci DESC_HDR_SEL1_MDEUA | 230462306a36Sopenharmony_ci DESC_HDR_MODE1_MDEU_INIT | 230562306a36Sopenharmony_ci DESC_HDR_MODE1_MDEU_PAD | 230662306a36Sopenharmony_ci DESC_HDR_MODE1_MDEU_SHA1_HMAC, 230762306a36Sopenharmony_ci }, 230862306a36Sopenharmony_ci { .type = CRYPTO_ALG_TYPE_AEAD, 230962306a36Sopenharmony_ci .alg.aead = { 231062306a36Sopenharmony_ci .base = { 231162306a36Sopenharmony_ci .cra_name = "authenc(hmac(sha1)," 231262306a36Sopenharmony_ci "cbc(des3_ede))", 231362306a36Sopenharmony_ci .cra_driver_name = "authenc-hmac-sha1-" 231462306a36Sopenharmony_ci "cbc-3des-talitos", 231562306a36Sopenharmony_ci .cra_blocksize = DES3_EDE_BLOCK_SIZE, 231662306a36Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 231762306a36Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY, 231862306a36Sopenharmony_ci }, 231962306a36Sopenharmony_ci .ivsize = DES3_EDE_BLOCK_SIZE, 232062306a36Sopenharmony_ci .maxauthsize = SHA1_DIGEST_SIZE, 232162306a36Sopenharmony_ci .setkey = aead_des3_setkey, 232262306a36Sopenharmony_ci }, 232362306a36Sopenharmony_ci .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP | 232462306a36Sopenharmony_ci DESC_HDR_SEL0_DEU | 232562306a36Sopenharmony_ci DESC_HDR_MODE0_DEU_CBC | 232662306a36Sopenharmony_ci DESC_HDR_MODE0_DEU_3DES | 232762306a36Sopenharmony_ci DESC_HDR_SEL1_MDEUA | 232862306a36Sopenharmony_ci DESC_HDR_MODE1_MDEU_INIT | 232962306a36Sopenharmony_ci DESC_HDR_MODE1_MDEU_PAD | 233062306a36Sopenharmony_ci DESC_HDR_MODE1_MDEU_SHA1_HMAC, 233162306a36Sopenharmony_ci }, 233262306a36Sopenharmony_ci { .type = CRYPTO_ALG_TYPE_AEAD, 233362306a36Sopenharmony_ci .priority = TALITOS_CRA_PRIORITY_AEAD_HSNA, 233462306a36Sopenharmony_ci .alg.aead = { 233562306a36Sopenharmony_ci .base = { 233662306a36Sopenharmony_ci .cra_name = "authenc(hmac(sha1)," 233762306a36Sopenharmony_ci "cbc(des3_ede))", 233862306a36Sopenharmony_ci .cra_driver_name = "authenc-hmac-sha1-" 233962306a36Sopenharmony_ci "cbc-3des-talitos-hsna", 234062306a36Sopenharmony_ci .cra_blocksize = DES3_EDE_BLOCK_SIZE, 234162306a36Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 234262306a36Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY, 234362306a36Sopenharmony_ci }, 234462306a36Sopenharmony_ci .ivsize = DES3_EDE_BLOCK_SIZE, 234562306a36Sopenharmony_ci .maxauthsize = SHA1_DIGEST_SIZE, 234662306a36Sopenharmony_ci .setkey = aead_des3_setkey, 234762306a36Sopenharmony_ci }, 234862306a36Sopenharmony_ci .desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU | 234962306a36Sopenharmony_ci DESC_HDR_SEL0_DEU | 235062306a36Sopenharmony_ci DESC_HDR_MODE0_DEU_CBC | 235162306a36Sopenharmony_ci DESC_HDR_MODE0_DEU_3DES | 235262306a36Sopenharmony_ci DESC_HDR_SEL1_MDEUA | 235362306a36Sopenharmony_ci DESC_HDR_MODE1_MDEU_INIT | 235462306a36Sopenharmony_ci DESC_HDR_MODE1_MDEU_PAD | 235562306a36Sopenharmony_ci DESC_HDR_MODE1_MDEU_SHA1_HMAC, 235662306a36Sopenharmony_ci }, 235762306a36Sopenharmony_ci { .type = CRYPTO_ALG_TYPE_AEAD, 235862306a36Sopenharmony_ci .alg.aead = { 235962306a36Sopenharmony_ci .base = { 236062306a36Sopenharmony_ci .cra_name = "authenc(hmac(sha224),cbc(aes))", 236162306a36Sopenharmony_ci .cra_driver_name = "authenc-hmac-sha224-" 236262306a36Sopenharmony_ci "cbc-aes-talitos", 236362306a36Sopenharmony_ci .cra_blocksize = AES_BLOCK_SIZE, 236462306a36Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 236562306a36Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY, 236662306a36Sopenharmony_ci }, 236762306a36Sopenharmony_ci .ivsize = AES_BLOCK_SIZE, 236862306a36Sopenharmony_ci .maxauthsize = SHA224_DIGEST_SIZE, 236962306a36Sopenharmony_ci }, 237062306a36Sopenharmony_ci .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP | 237162306a36Sopenharmony_ci DESC_HDR_SEL0_AESU | 237262306a36Sopenharmony_ci DESC_HDR_MODE0_AESU_CBC | 237362306a36Sopenharmony_ci DESC_HDR_SEL1_MDEUA | 237462306a36Sopenharmony_ci DESC_HDR_MODE1_MDEU_INIT | 237562306a36Sopenharmony_ci DESC_HDR_MODE1_MDEU_PAD | 237662306a36Sopenharmony_ci DESC_HDR_MODE1_MDEU_SHA224_HMAC, 237762306a36Sopenharmony_ci }, 237862306a36Sopenharmony_ci { .type = CRYPTO_ALG_TYPE_AEAD, 237962306a36Sopenharmony_ci .priority = TALITOS_CRA_PRIORITY_AEAD_HSNA, 238062306a36Sopenharmony_ci .alg.aead = { 238162306a36Sopenharmony_ci .base = { 238262306a36Sopenharmony_ci .cra_name = "authenc(hmac(sha224),cbc(aes))", 238362306a36Sopenharmony_ci .cra_driver_name = "authenc-hmac-sha224-" 238462306a36Sopenharmony_ci "cbc-aes-talitos-hsna", 238562306a36Sopenharmony_ci .cra_blocksize = AES_BLOCK_SIZE, 238662306a36Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 238762306a36Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY, 238862306a36Sopenharmony_ci }, 238962306a36Sopenharmony_ci .ivsize = AES_BLOCK_SIZE, 239062306a36Sopenharmony_ci .maxauthsize = SHA224_DIGEST_SIZE, 239162306a36Sopenharmony_ci }, 239262306a36Sopenharmony_ci .desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU | 239362306a36Sopenharmony_ci DESC_HDR_SEL0_AESU | 239462306a36Sopenharmony_ci DESC_HDR_MODE0_AESU_CBC | 239562306a36Sopenharmony_ci DESC_HDR_SEL1_MDEUA | 239662306a36Sopenharmony_ci DESC_HDR_MODE1_MDEU_INIT | 239762306a36Sopenharmony_ci DESC_HDR_MODE1_MDEU_PAD | 239862306a36Sopenharmony_ci DESC_HDR_MODE1_MDEU_SHA224_HMAC, 239962306a36Sopenharmony_ci }, 240062306a36Sopenharmony_ci { .type = CRYPTO_ALG_TYPE_AEAD, 240162306a36Sopenharmony_ci .alg.aead = { 240262306a36Sopenharmony_ci .base = { 240362306a36Sopenharmony_ci .cra_name = "authenc(hmac(sha224)," 240462306a36Sopenharmony_ci "cbc(des3_ede))", 240562306a36Sopenharmony_ci .cra_driver_name = "authenc-hmac-sha224-" 240662306a36Sopenharmony_ci "cbc-3des-talitos", 240762306a36Sopenharmony_ci .cra_blocksize = DES3_EDE_BLOCK_SIZE, 240862306a36Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 240962306a36Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY, 241062306a36Sopenharmony_ci }, 241162306a36Sopenharmony_ci .ivsize = DES3_EDE_BLOCK_SIZE, 241262306a36Sopenharmony_ci .maxauthsize = SHA224_DIGEST_SIZE, 241362306a36Sopenharmony_ci .setkey = aead_des3_setkey, 241462306a36Sopenharmony_ci }, 241562306a36Sopenharmony_ci .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP | 241662306a36Sopenharmony_ci DESC_HDR_SEL0_DEU | 241762306a36Sopenharmony_ci DESC_HDR_MODE0_DEU_CBC | 241862306a36Sopenharmony_ci DESC_HDR_MODE0_DEU_3DES | 241962306a36Sopenharmony_ci DESC_HDR_SEL1_MDEUA | 242062306a36Sopenharmony_ci DESC_HDR_MODE1_MDEU_INIT | 242162306a36Sopenharmony_ci DESC_HDR_MODE1_MDEU_PAD | 242262306a36Sopenharmony_ci DESC_HDR_MODE1_MDEU_SHA224_HMAC, 242362306a36Sopenharmony_ci }, 242462306a36Sopenharmony_ci { .type = CRYPTO_ALG_TYPE_AEAD, 242562306a36Sopenharmony_ci .priority = TALITOS_CRA_PRIORITY_AEAD_HSNA, 242662306a36Sopenharmony_ci .alg.aead = { 242762306a36Sopenharmony_ci .base = { 242862306a36Sopenharmony_ci .cra_name = "authenc(hmac(sha224)," 242962306a36Sopenharmony_ci "cbc(des3_ede))", 243062306a36Sopenharmony_ci .cra_driver_name = "authenc-hmac-sha224-" 243162306a36Sopenharmony_ci "cbc-3des-talitos-hsna", 243262306a36Sopenharmony_ci .cra_blocksize = DES3_EDE_BLOCK_SIZE, 243362306a36Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 243462306a36Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY, 243562306a36Sopenharmony_ci }, 243662306a36Sopenharmony_ci .ivsize = DES3_EDE_BLOCK_SIZE, 243762306a36Sopenharmony_ci .maxauthsize = SHA224_DIGEST_SIZE, 243862306a36Sopenharmony_ci .setkey = aead_des3_setkey, 243962306a36Sopenharmony_ci }, 244062306a36Sopenharmony_ci .desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU | 244162306a36Sopenharmony_ci DESC_HDR_SEL0_DEU | 244262306a36Sopenharmony_ci DESC_HDR_MODE0_DEU_CBC | 244362306a36Sopenharmony_ci DESC_HDR_MODE0_DEU_3DES | 244462306a36Sopenharmony_ci DESC_HDR_SEL1_MDEUA | 244562306a36Sopenharmony_ci DESC_HDR_MODE1_MDEU_INIT | 244662306a36Sopenharmony_ci DESC_HDR_MODE1_MDEU_PAD | 244762306a36Sopenharmony_ci DESC_HDR_MODE1_MDEU_SHA224_HMAC, 244862306a36Sopenharmony_ci }, 244962306a36Sopenharmony_ci { .type = CRYPTO_ALG_TYPE_AEAD, 245062306a36Sopenharmony_ci .alg.aead = { 245162306a36Sopenharmony_ci .base = { 245262306a36Sopenharmony_ci .cra_name = "authenc(hmac(sha256),cbc(aes))", 245362306a36Sopenharmony_ci .cra_driver_name = "authenc-hmac-sha256-" 245462306a36Sopenharmony_ci "cbc-aes-talitos", 245562306a36Sopenharmony_ci .cra_blocksize = AES_BLOCK_SIZE, 245662306a36Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 245762306a36Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY, 245862306a36Sopenharmony_ci }, 245962306a36Sopenharmony_ci .ivsize = AES_BLOCK_SIZE, 246062306a36Sopenharmony_ci .maxauthsize = SHA256_DIGEST_SIZE, 246162306a36Sopenharmony_ci }, 246262306a36Sopenharmony_ci .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP | 246362306a36Sopenharmony_ci DESC_HDR_SEL0_AESU | 246462306a36Sopenharmony_ci DESC_HDR_MODE0_AESU_CBC | 246562306a36Sopenharmony_ci DESC_HDR_SEL1_MDEUA | 246662306a36Sopenharmony_ci DESC_HDR_MODE1_MDEU_INIT | 246762306a36Sopenharmony_ci DESC_HDR_MODE1_MDEU_PAD | 246862306a36Sopenharmony_ci DESC_HDR_MODE1_MDEU_SHA256_HMAC, 246962306a36Sopenharmony_ci }, 247062306a36Sopenharmony_ci { .type = CRYPTO_ALG_TYPE_AEAD, 247162306a36Sopenharmony_ci .priority = TALITOS_CRA_PRIORITY_AEAD_HSNA, 247262306a36Sopenharmony_ci .alg.aead = { 247362306a36Sopenharmony_ci .base = { 247462306a36Sopenharmony_ci .cra_name = "authenc(hmac(sha256),cbc(aes))", 247562306a36Sopenharmony_ci .cra_driver_name = "authenc-hmac-sha256-" 247662306a36Sopenharmony_ci "cbc-aes-talitos-hsna", 247762306a36Sopenharmony_ci .cra_blocksize = AES_BLOCK_SIZE, 247862306a36Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 247962306a36Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY, 248062306a36Sopenharmony_ci }, 248162306a36Sopenharmony_ci .ivsize = AES_BLOCK_SIZE, 248262306a36Sopenharmony_ci .maxauthsize = SHA256_DIGEST_SIZE, 248362306a36Sopenharmony_ci }, 248462306a36Sopenharmony_ci .desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU | 248562306a36Sopenharmony_ci DESC_HDR_SEL0_AESU | 248662306a36Sopenharmony_ci DESC_HDR_MODE0_AESU_CBC | 248762306a36Sopenharmony_ci DESC_HDR_SEL1_MDEUA | 248862306a36Sopenharmony_ci DESC_HDR_MODE1_MDEU_INIT | 248962306a36Sopenharmony_ci DESC_HDR_MODE1_MDEU_PAD | 249062306a36Sopenharmony_ci DESC_HDR_MODE1_MDEU_SHA256_HMAC, 249162306a36Sopenharmony_ci }, 249262306a36Sopenharmony_ci { .type = CRYPTO_ALG_TYPE_AEAD, 249362306a36Sopenharmony_ci .alg.aead = { 249462306a36Sopenharmony_ci .base = { 249562306a36Sopenharmony_ci .cra_name = "authenc(hmac(sha256)," 249662306a36Sopenharmony_ci "cbc(des3_ede))", 249762306a36Sopenharmony_ci .cra_driver_name = "authenc-hmac-sha256-" 249862306a36Sopenharmony_ci "cbc-3des-talitos", 249962306a36Sopenharmony_ci .cra_blocksize = DES3_EDE_BLOCK_SIZE, 250062306a36Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 250162306a36Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY, 250262306a36Sopenharmony_ci }, 250362306a36Sopenharmony_ci .ivsize = DES3_EDE_BLOCK_SIZE, 250462306a36Sopenharmony_ci .maxauthsize = SHA256_DIGEST_SIZE, 250562306a36Sopenharmony_ci .setkey = aead_des3_setkey, 250662306a36Sopenharmony_ci }, 250762306a36Sopenharmony_ci .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP | 250862306a36Sopenharmony_ci DESC_HDR_SEL0_DEU | 250962306a36Sopenharmony_ci DESC_HDR_MODE0_DEU_CBC | 251062306a36Sopenharmony_ci DESC_HDR_MODE0_DEU_3DES | 251162306a36Sopenharmony_ci DESC_HDR_SEL1_MDEUA | 251262306a36Sopenharmony_ci DESC_HDR_MODE1_MDEU_INIT | 251362306a36Sopenharmony_ci DESC_HDR_MODE1_MDEU_PAD | 251462306a36Sopenharmony_ci DESC_HDR_MODE1_MDEU_SHA256_HMAC, 251562306a36Sopenharmony_ci }, 251662306a36Sopenharmony_ci { .type = CRYPTO_ALG_TYPE_AEAD, 251762306a36Sopenharmony_ci .priority = TALITOS_CRA_PRIORITY_AEAD_HSNA, 251862306a36Sopenharmony_ci .alg.aead = { 251962306a36Sopenharmony_ci .base = { 252062306a36Sopenharmony_ci .cra_name = "authenc(hmac(sha256)," 252162306a36Sopenharmony_ci "cbc(des3_ede))", 252262306a36Sopenharmony_ci .cra_driver_name = "authenc-hmac-sha256-" 252362306a36Sopenharmony_ci "cbc-3des-talitos-hsna", 252462306a36Sopenharmony_ci .cra_blocksize = DES3_EDE_BLOCK_SIZE, 252562306a36Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 252662306a36Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY, 252762306a36Sopenharmony_ci }, 252862306a36Sopenharmony_ci .ivsize = DES3_EDE_BLOCK_SIZE, 252962306a36Sopenharmony_ci .maxauthsize = SHA256_DIGEST_SIZE, 253062306a36Sopenharmony_ci .setkey = aead_des3_setkey, 253162306a36Sopenharmony_ci }, 253262306a36Sopenharmony_ci .desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU | 253362306a36Sopenharmony_ci DESC_HDR_SEL0_DEU | 253462306a36Sopenharmony_ci DESC_HDR_MODE0_DEU_CBC | 253562306a36Sopenharmony_ci DESC_HDR_MODE0_DEU_3DES | 253662306a36Sopenharmony_ci DESC_HDR_SEL1_MDEUA | 253762306a36Sopenharmony_ci DESC_HDR_MODE1_MDEU_INIT | 253862306a36Sopenharmony_ci DESC_HDR_MODE1_MDEU_PAD | 253962306a36Sopenharmony_ci DESC_HDR_MODE1_MDEU_SHA256_HMAC, 254062306a36Sopenharmony_ci }, 254162306a36Sopenharmony_ci { .type = CRYPTO_ALG_TYPE_AEAD, 254262306a36Sopenharmony_ci .alg.aead = { 254362306a36Sopenharmony_ci .base = { 254462306a36Sopenharmony_ci .cra_name = "authenc(hmac(sha384),cbc(aes))", 254562306a36Sopenharmony_ci .cra_driver_name = "authenc-hmac-sha384-" 254662306a36Sopenharmony_ci "cbc-aes-talitos", 254762306a36Sopenharmony_ci .cra_blocksize = AES_BLOCK_SIZE, 254862306a36Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 254962306a36Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY, 255062306a36Sopenharmony_ci }, 255162306a36Sopenharmony_ci .ivsize = AES_BLOCK_SIZE, 255262306a36Sopenharmony_ci .maxauthsize = SHA384_DIGEST_SIZE, 255362306a36Sopenharmony_ci }, 255462306a36Sopenharmony_ci .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP | 255562306a36Sopenharmony_ci DESC_HDR_SEL0_AESU | 255662306a36Sopenharmony_ci DESC_HDR_MODE0_AESU_CBC | 255762306a36Sopenharmony_ci DESC_HDR_SEL1_MDEUB | 255862306a36Sopenharmony_ci DESC_HDR_MODE1_MDEU_INIT | 255962306a36Sopenharmony_ci DESC_HDR_MODE1_MDEU_PAD | 256062306a36Sopenharmony_ci DESC_HDR_MODE1_MDEUB_SHA384_HMAC, 256162306a36Sopenharmony_ci }, 256262306a36Sopenharmony_ci { .type = CRYPTO_ALG_TYPE_AEAD, 256362306a36Sopenharmony_ci .alg.aead = { 256462306a36Sopenharmony_ci .base = { 256562306a36Sopenharmony_ci .cra_name = "authenc(hmac(sha384)," 256662306a36Sopenharmony_ci "cbc(des3_ede))", 256762306a36Sopenharmony_ci .cra_driver_name = "authenc-hmac-sha384-" 256862306a36Sopenharmony_ci "cbc-3des-talitos", 256962306a36Sopenharmony_ci .cra_blocksize = DES3_EDE_BLOCK_SIZE, 257062306a36Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 257162306a36Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY, 257262306a36Sopenharmony_ci }, 257362306a36Sopenharmony_ci .ivsize = DES3_EDE_BLOCK_SIZE, 257462306a36Sopenharmony_ci .maxauthsize = SHA384_DIGEST_SIZE, 257562306a36Sopenharmony_ci .setkey = aead_des3_setkey, 257662306a36Sopenharmony_ci }, 257762306a36Sopenharmony_ci .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP | 257862306a36Sopenharmony_ci DESC_HDR_SEL0_DEU | 257962306a36Sopenharmony_ci DESC_HDR_MODE0_DEU_CBC | 258062306a36Sopenharmony_ci DESC_HDR_MODE0_DEU_3DES | 258162306a36Sopenharmony_ci DESC_HDR_SEL1_MDEUB | 258262306a36Sopenharmony_ci DESC_HDR_MODE1_MDEU_INIT | 258362306a36Sopenharmony_ci DESC_HDR_MODE1_MDEU_PAD | 258462306a36Sopenharmony_ci DESC_HDR_MODE1_MDEUB_SHA384_HMAC, 258562306a36Sopenharmony_ci }, 258662306a36Sopenharmony_ci { .type = CRYPTO_ALG_TYPE_AEAD, 258762306a36Sopenharmony_ci .alg.aead = { 258862306a36Sopenharmony_ci .base = { 258962306a36Sopenharmony_ci .cra_name = "authenc(hmac(sha512),cbc(aes))", 259062306a36Sopenharmony_ci .cra_driver_name = "authenc-hmac-sha512-" 259162306a36Sopenharmony_ci "cbc-aes-talitos", 259262306a36Sopenharmony_ci .cra_blocksize = AES_BLOCK_SIZE, 259362306a36Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 259462306a36Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY, 259562306a36Sopenharmony_ci }, 259662306a36Sopenharmony_ci .ivsize = AES_BLOCK_SIZE, 259762306a36Sopenharmony_ci .maxauthsize = SHA512_DIGEST_SIZE, 259862306a36Sopenharmony_ci }, 259962306a36Sopenharmony_ci .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP | 260062306a36Sopenharmony_ci DESC_HDR_SEL0_AESU | 260162306a36Sopenharmony_ci DESC_HDR_MODE0_AESU_CBC | 260262306a36Sopenharmony_ci DESC_HDR_SEL1_MDEUB | 260362306a36Sopenharmony_ci DESC_HDR_MODE1_MDEU_INIT | 260462306a36Sopenharmony_ci DESC_HDR_MODE1_MDEU_PAD | 260562306a36Sopenharmony_ci DESC_HDR_MODE1_MDEUB_SHA512_HMAC, 260662306a36Sopenharmony_ci }, 260762306a36Sopenharmony_ci { .type = CRYPTO_ALG_TYPE_AEAD, 260862306a36Sopenharmony_ci .alg.aead = { 260962306a36Sopenharmony_ci .base = { 261062306a36Sopenharmony_ci .cra_name = "authenc(hmac(sha512)," 261162306a36Sopenharmony_ci "cbc(des3_ede))", 261262306a36Sopenharmony_ci .cra_driver_name = "authenc-hmac-sha512-" 261362306a36Sopenharmony_ci "cbc-3des-talitos", 261462306a36Sopenharmony_ci .cra_blocksize = DES3_EDE_BLOCK_SIZE, 261562306a36Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 261662306a36Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY, 261762306a36Sopenharmony_ci }, 261862306a36Sopenharmony_ci .ivsize = DES3_EDE_BLOCK_SIZE, 261962306a36Sopenharmony_ci .maxauthsize = SHA512_DIGEST_SIZE, 262062306a36Sopenharmony_ci .setkey = aead_des3_setkey, 262162306a36Sopenharmony_ci }, 262262306a36Sopenharmony_ci .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP | 262362306a36Sopenharmony_ci DESC_HDR_SEL0_DEU | 262462306a36Sopenharmony_ci DESC_HDR_MODE0_DEU_CBC | 262562306a36Sopenharmony_ci DESC_HDR_MODE0_DEU_3DES | 262662306a36Sopenharmony_ci DESC_HDR_SEL1_MDEUB | 262762306a36Sopenharmony_ci DESC_HDR_MODE1_MDEU_INIT | 262862306a36Sopenharmony_ci DESC_HDR_MODE1_MDEU_PAD | 262962306a36Sopenharmony_ci DESC_HDR_MODE1_MDEUB_SHA512_HMAC, 263062306a36Sopenharmony_ci }, 263162306a36Sopenharmony_ci { .type = CRYPTO_ALG_TYPE_AEAD, 263262306a36Sopenharmony_ci .alg.aead = { 263362306a36Sopenharmony_ci .base = { 263462306a36Sopenharmony_ci .cra_name = "authenc(hmac(md5),cbc(aes))", 263562306a36Sopenharmony_ci .cra_driver_name = "authenc-hmac-md5-" 263662306a36Sopenharmony_ci "cbc-aes-talitos", 263762306a36Sopenharmony_ci .cra_blocksize = AES_BLOCK_SIZE, 263862306a36Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 263962306a36Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY, 264062306a36Sopenharmony_ci }, 264162306a36Sopenharmony_ci .ivsize = AES_BLOCK_SIZE, 264262306a36Sopenharmony_ci .maxauthsize = MD5_DIGEST_SIZE, 264362306a36Sopenharmony_ci }, 264462306a36Sopenharmony_ci .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP | 264562306a36Sopenharmony_ci DESC_HDR_SEL0_AESU | 264662306a36Sopenharmony_ci DESC_HDR_MODE0_AESU_CBC | 264762306a36Sopenharmony_ci DESC_HDR_SEL1_MDEUA | 264862306a36Sopenharmony_ci DESC_HDR_MODE1_MDEU_INIT | 264962306a36Sopenharmony_ci DESC_HDR_MODE1_MDEU_PAD | 265062306a36Sopenharmony_ci DESC_HDR_MODE1_MDEU_MD5_HMAC, 265162306a36Sopenharmony_ci }, 265262306a36Sopenharmony_ci { .type = CRYPTO_ALG_TYPE_AEAD, 265362306a36Sopenharmony_ci .priority = TALITOS_CRA_PRIORITY_AEAD_HSNA, 265462306a36Sopenharmony_ci .alg.aead = { 265562306a36Sopenharmony_ci .base = { 265662306a36Sopenharmony_ci .cra_name = "authenc(hmac(md5),cbc(aes))", 265762306a36Sopenharmony_ci .cra_driver_name = "authenc-hmac-md5-" 265862306a36Sopenharmony_ci "cbc-aes-talitos-hsna", 265962306a36Sopenharmony_ci .cra_blocksize = AES_BLOCK_SIZE, 266062306a36Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 266162306a36Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY, 266262306a36Sopenharmony_ci }, 266362306a36Sopenharmony_ci .ivsize = AES_BLOCK_SIZE, 266462306a36Sopenharmony_ci .maxauthsize = MD5_DIGEST_SIZE, 266562306a36Sopenharmony_ci }, 266662306a36Sopenharmony_ci .desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU | 266762306a36Sopenharmony_ci DESC_HDR_SEL0_AESU | 266862306a36Sopenharmony_ci DESC_HDR_MODE0_AESU_CBC | 266962306a36Sopenharmony_ci DESC_HDR_SEL1_MDEUA | 267062306a36Sopenharmony_ci DESC_HDR_MODE1_MDEU_INIT | 267162306a36Sopenharmony_ci DESC_HDR_MODE1_MDEU_PAD | 267262306a36Sopenharmony_ci DESC_HDR_MODE1_MDEU_MD5_HMAC, 267362306a36Sopenharmony_ci }, 267462306a36Sopenharmony_ci { .type = CRYPTO_ALG_TYPE_AEAD, 267562306a36Sopenharmony_ci .alg.aead = { 267662306a36Sopenharmony_ci .base = { 267762306a36Sopenharmony_ci .cra_name = "authenc(hmac(md5),cbc(des3_ede))", 267862306a36Sopenharmony_ci .cra_driver_name = "authenc-hmac-md5-" 267962306a36Sopenharmony_ci "cbc-3des-talitos", 268062306a36Sopenharmony_ci .cra_blocksize = DES3_EDE_BLOCK_SIZE, 268162306a36Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 268262306a36Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY, 268362306a36Sopenharmony_ci }, 268462306a36Sopenharmony_ci .ivsize = DES3_EDE_BLOCK_SIZE, 268562306a36Sopenharmony_ci .maxauthsize = MD5_DIGEST_SIZE, 268662306a36Sopenharmony_ci .setkey = aead_des3_setkey, 268762306a36Sopenharmony_ci }, 268862306a36Sopenharmony_ci .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP | 268962306a36Sopenharmony_ci DESC_HDR_SEL0_DEU | 269062306a36Sopenharmony_ci DESC_HDR_MODE0_DEU_CBC | 269162306a36Sopenharmony_ci DESC_HDR_MODE0_DEU_3DES | 269262306a36Sopenharmony_ci DESC_HDR_SEL1_MDEUA | 269362306a36Sopenharmony_ci DESC_HDR_MODE1_MDEU_INIT | 269462306a36Sopenharmony_ci DESC_HDR_MODE1_MDEU_PAD | 269562306a36Sopenharmony_ci DESC_HDR_MODE1_MDEU_MD5_HMAC, 269662306a36Sopenharmony_ci }, 269762306a36Sopenharmony_ci { .type = CRYPTO_ALG_TYPE_AEAD, 269862306a36Sopenharmony_ci .priority = TALITOS_CRA_PRIORITY_AEAD_HSNA, 269962306a36Sopenharmony_ci .alg.aead = { 270062306a36Sopenharmony_ci .base = { 270162306a36Sopenharmony_ci .cra_name = "authenc(hmac(md5),cbc(des3_ede))", 270262306a36Sopenharmony_ci .cra_driver_name = "authenc-hmac-md5-" 270362306a36Sopenharmony_ci "cbc-3des-talitos-hsna", 270462306a36Sopenharmony_ci .cra_blocksize = DES3_EDE_BLOCK_SIZE, 270562306a36Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 270662306a36Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY, 270762306a36Sopenharmony_ci }, 270862306a36Sopenharmony_ci .ivsize = DES3_EDE_BLOCK_SIZE, 270962306a36Sopenharmony_ci .maxauthsize = MD5_DIGEST_SIZE, 271062306a36Sopenharmony_ci .setkey = aead_des3_setkey, 271162306a36Sopenharmony_ci }, 271262306a36Sopenharmony_ci .desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU | 271362306a36Sopenharmony_ci DESC_HDR_SEL0_DEU | 271462306a36Sopenharmony_ci DESC_HDR_MODE0_DEU_CBC | 271562306a36Sopenharmony_ci DESC_HDR_MODE0_DEU_3DES | 271662306a36Sopenharmony_ci DESC_HDR_SEL1_MDEUA | 271762306a36Sopenharmony_ci DESC_HDR_MODE1_MDEU_INIT | 271862306a36Sopenharmony_ci DESC_HDR_MODE1_MDEU_PAD | 271962306a36Sopenharmony_ci DESC_HDR_MODE1_MDEU_MD5_HMAC, 272062306a36Sopenharmony_ci }, 272162306a36Sopenharmony_ci /* SKCIPHER algorithms. */ 272262306a36Sopenharmony_ci { .type = CRYPTO_ALG_TYPE_SKCIPHER, 272362306a36Sopenharmony_ci .alg.skcipher = { 272462306a36Sopenharmony_ci .base.cra_name = "ecb(aes)", 272562306a36Sopenharmony_ci .base.cra_driver_name = "ecb-aes-talitos", 272662306a36Sopenharmony_ci .base.cra_blocksize = AES_BLOCK_SIZE, 272762306a36Sopenharmony_ci .base.cra_flags = CRYPTO_ALG_ASYNC | 272862306a36Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY, 272962306a36Sopenharmony_ci .min_keysize = AES_MIN_KEY_SIZE, 273062306a36Sopenharmony_ci .max_keysize = AES_MAX_KEY_SIZE, 273162306a36Sopenharmony_ci .setkey = skcipher_aes_setkey, 273262306a36Sopenharmony_ci }, 273362306a36Sopenharmony_ci .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | 273462306a36Sopenharmony_ci DESC_HDR_SEL0_AESU, 273562306a36Sopenharmony_ci }, 273662306a36Sopenharmony_ci { .type = CRYPTO_ALG_TYPE_SKCIPHER, 273762306a36Sopenharmony_ci .alg.skcipher = { 273862306a36Sopenharmony_ci .base.cra_name = "cbc(aes)", 273962306a36Sopenharmony_ci .base.cra_driver_name = "cbc-aes-talitos", 274062306a36Sopenharmony_ci .base.cra_blocksize = AES_BLOCK_SIZE, 274162306a36Sopenharmony_ci .base.cra_flags = CRYPTO_ALG_ASYNC | 274262306a36Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY, 274362306a36Sopenharmony_ci .min_keysize = AES_MIN_KEY_SIZE, 274462306a36Sopenharmony_ci .max_keysize = AES_MAX_KEY_SIZE, 274562306a36Sopenharmony_ci .ivsize = AES_BLOCK_SIZE, 274662306a36Sopenharmony_ci .setkey = skcipher_aes_setkey, 274762306a36Sopenharmony_ci }, 274862306a36Sopenharmony_ci .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | 274962306a36Sopenharmony_ci DESC_HDR_SEL0_AESU | 275062306a36Sopenharmony_ci DESC_HDR_MODE0_AESU_CBC, 275162306a36Sopenharmony_ci }, 275262306a36Sopenharmony_ci { .type = CRYPTO_ALG_TYPE_SKCIPHER, 275362306a36Sopenharmony_ci .alg.skcipher = { 275462306a36Sopenharmony_ci .base.cra_name = "ctr(aes)", 275562306a36Sopenharmony_ci .base.cra_driver_name = "ctr-aes-talitos", 275662306a36Sopenharmony_ci .base.cra_blocksize = 1, 275762306a36Sopenharmony_ci .base.cra_flags = CRYPTO_ALG_ASYNC | 275862306a36Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY, 275962306a36Sopenharmony_ci .min_keysize = AES_MIN_KEY_SIZE, 276062306a36Sopenharmony_ci .max_keysize = AES_MAX_KEY_SIZE, 276162306a36Sopenharmony_ci .ivsize = AES_BLOCK_SIZE, 276262306a36Sopenharmony_ci .setkey = skcipher_aes_setkey, 276362306a36Sopenharmony_ci }, 276462306a36Sopenharmony_ci .desc_hdr_template = DESC_HDR_TYPE_AESU_CTR_NONSNOOP | 276562306a36Sopenharmony_ci DESC_HDR_SEL0_AESU | 276662306a36Sopenharmony_ci DESC_HDR_MODE0_AESU_CTR, 276762306a36Sopenharmony_ci }, 276862306a36Sopenharmony_ci { .type = CRYPTO_ALG_TYPE_SKCIPHER, 276962306a36Sopenharmony_ci .alg.skcipher = { 277062306a36Sopenharmony_ci .base.cra_name = "ctr(aes)", 277162306a36Sopenharmony_ci .base.cra_driver_name = "ctr-aes-talitos", 277262306a36Sopenharmony_ci .base.cra_blocksize = 1, 277362306a36Sopenharmony_ci .base.cra_flags = CRYPTO_ALG_ASYNC | 277462306a36Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY, 277562306a36Sopenharmony_ci .min_keysize = AES_MIN_KEY_SIZE, 277662306a36Sopenharmony_ci .max_keysize = AES_MAX_KEY_SIZE, 277762306a36Sopenharmony_ci .ivsize = AES_BLOCK_SIZE, 277862306a36Sopenharmony_ci .setkey = skcipher_aes_setkey, 277962306a36Sopenharmony_ci }, 278062306a36Sopenharmony_ci .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | 278162306a36Sopenharmony_ci DESC_HDR_SEL0_AESU | 278262306a36Sopenharmony_ci DESC_HDR_MODE0_AESU_CTR, 278362306a36Sopenharmony_ci }, 278462306a36Sopenharmony_ci { .type = CRYPTO_ALG_TYPE_SKCIPHER, 278562306a36Sopenharmony_ci .alg.skcipher = { 278662306a36Sopenharmony_ci .base.cra_name = "ecb(des)", 278762306a36Sopenharmony_ci .base.cra_driver_name = "ecb-des-talitos", 278862306a36Sopenharmony_ci .base.cra_blocksize = DES_BLOCK_SIZE, 278962306a36Sopenharmony_ci .base.cra_flags = CRYPTO_ALG_ASYNC | 279062306a36Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY, 279162306a36Sopenharmony_ci .min_keysize = DES_KEY_SIZE, 279262306a36Sopenharmony_ci .max_keysize = DES_KEY_SIZE, 279362306a36Sopenharmony_ci .setkey = skcipher_des_setkey, 279462306a36Sopenharmony_ci }, 279562306a36Sopenharmony_ci .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | 279662306a36Sopenharmony_ci DESC_HDR_SEL0_DEU, 279762306a36Sopenharmony_ci }, 279862306a36Sopenharmony_ci { .type = CRYPTO_ALG_TYPE_SKCIPHER, 279962306a36Sopenharmony_ci .alg.skcipher = { 280062306a36Sopenharmony_ci .base.cra_name = "cbc(des)", 280162306a36Sopenharmony_ci .base.cra_driver_name = "cbc-des-talitos", 280262306a36Sopenharmony_ci .base.cra_blocksize = DES_BLOCK_SIZE, 280362306a36Sopenharmony_ci .base.cra_flags = CRYPTO_ALG_ASYNC | 280462306a36Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY, 280562306a36Sopenharmony_ci .min_keysize = DES_KEY_SIZE, 280662306a36Sopenharmony_ci .max_keysize = DES_KEY_SIZE, 280762306a36Sopenharmony_ci .ivsize = DES_BLOCK_SIZE, 280862306a36Sopenharmony_ci .setkey = skcipher_des_setkey, 280962306a36Sopenharmony_ci }, 281062306a36Sopenharmony_ci .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | 281162306a36Sopenharmony_ci DESC_HDR_SEL0_DEU | 281262306a36Sopenharmony_ci DESC_HDR_MODE0_DEU_CBC, 281362306a36Sopenharmony_ci }, 281462306a36Sopenharmony_ci { .type = CRYPTO_ALG_TYPE_SKCIPHER, 281562306a36Sopenharmony_ci .alg.skcipher = { 281662306a36Sopenharmony_ci .base.cra_name = "ecb(des3_ede)", 281762306a36Sopenharmony_ci .base.cra_driver_name = "ecb-3des-talitos", 281862306a36Sopenharmony_ci .base.cra_blocksize = DES3_EDE_BLOCK_SIZE, 281962306a36Sopenharmony_ci .base.cra_flags = CRYPTO_ALG_ASYNC | 282062306a36Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY, 282162306a36Sopenharmony_ci .min_keysize = DES3_EDE_KEY_SIZE, 282262306a36Sopenharmony_ci .max_keysize = DES3_EDE_KEY_SIZE, 282362306a36Sopenharmony_ci .setkey = skcipher_des3_setkey, 282462306a36Sopenharmony_ci }, 282562306a36Sopenharmony_ci .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | 282662306a36Sopenharmony_ci DESC_HDR_SEL0_DEU | 282762306a36Sopenharmony_ci DESC_HDR_MODE0_DEU_3DES, 282862306a36Sopenharmony_ci }, 282962306a36Sopenharmony_ci { .type = CRYPTO_ALG_TYPE_SKCIPHER, 283062306a36Sopenharmony_ci .alg.skcipher = { 283162306a36Sopenharmony_ci .base.cra_name = "cbc(des3_ede)", 283262306a36Sopenharmony_ci .base.cra_driver_name = "cbc-3des-talitos", 283362306a36Sopenharmony_ci .base.cra_blocksize = DES3_EDE_BLOCK_SIZE, 283462306a36Sopenharmony_ci .base.cra_flags = CRYPTO_ALG_ASYNC | 283562306a36Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY, 283662306a36Sopenharmony_ci .min_keysize = DES3_EDE_KEY_SIZE, 283762306a36Sopenharmony_ci .max_keysize = DES3_EDE_KEY_SIZE, 283862306a36Sopenharmony_ci .ivsize = DES3_EDE_BLOCK_SIZE, 283962306a36Sopenharmony_ci .setkey = skcipher_des3_setkey, 284062306a36Sopenharmony_ci }, 284162306a36Sopenharmony_ci .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | 284262306a36Sopenharmony_ci DESC_HDR_SEL0_DEU | 284362306a36Sopenharmony_ci DESC_HDR_MODE0_DEU_CBC | 284462306a36Sopenharmony_ci DESC_HDR_MODE0_DEU_3DES, 284562306a36Sopenharmony_ci }, 284662306a36Sopenharmony_ci /* AHASH algorithms. */ 284762306a36Sopenharmony_ci { .type = CRYPTO_ALG_TYPE_AHASH, 284862306a36Sopenharmony_ci .alg.hash = { 284962306a36Sopenharmony_ci .halg.digestsize = MD5_DIGEST_SIZE, 285062306a36Sopenharmony_ci .halg.statesize = sizeof(struct talitos_export_state), 285162306a36Sopenharmony_ci .halg.base = { 285262306a36Sopenharmony_ci .cra_name = "md5", 285362306a36Sopenharmony_ci .cra_driver_name = "md5-talitos", 285462306a36Sopenharmony_ci .cra_blocksize = MD5_HMAC_BLOCK_SIZE, 285562306a36Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 285662306a36Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY, 285762306a36Sopenharmony_ci } 285862306a36Sopenharmony_ci }, 285962306a36Sopenharmony_ci .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | 286062306a36Sopenharmony_ci DESC_HDR_SEL0_MDEUA | 286162306a36Sopenharmony_ci DESC_HDR_MODE0_MDEU_MD5, 286262306a36Sopenharmony_ci }, 286362306a36Sopenharmony_ci { .type = CRYPTO_ALG_TYPE_AHASH, 286462306a36Sopenharmony_ci .alg.hash = { 286562306a36Sopenharmony_ci .halg.digestsize = SHA1_DIGEST_SIZE, 286662306a36Sopenharmony_ci .halg.statesize = sizeof(struct talitos_export_state), 286762306a36Sopenharmony_ci .halg.base = { 286862306a36Sopenharmony_ci .cra_name = "sha1", 286962306a36Sopenharmony_ci .cra_driver_name = "sha1-talitos", 287062306a36Sopenharmony_ci .cra_blocksize = SHA1_BLOCK_SIZE, 287162306a36Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 287262306a36Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY, 287362306a36Sopenharmony_ci } 287462306a36Sopenharmony_ci }, 287562306a36Sopenharmony_ci .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | 287662306a36Sopenharmony_ci DESC_HDR_SEL0_MDEUA | 287762306a36Sopenharmony_ci DESC_HDR_MODE0_MDEU_SHA1, 287862306a36Sopenharmony_ci }, 287962306a36Sopenharmony_ci { .type = CRYPTO_ALG_TYPE_AHASH, 288062306a36Sopenharmony_ci .alg.hash = { 288162306a36Sopenharmony_ci .halg.digestsize = SHA224_DIGEST_SIZE, 288262306a36Sopenharmony_ci .halg.statesize = sizeof(struct talitos_export_state), 288362306a36Sopenharmony_ci .halg.base = { 288462306a36Sopenharmony_ci .cra_name = "sha224", 288562306a36Sopenharmony_ci .cra_driver_name = "sha224-talitos", 288662306a36Sopenharmony_ci .cra_blocksize = SHA224_BLOCK_SIZE, 288762306a36Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 288862306a36Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY, 288962306a36Sopenharmony_ci } 289062306a36Sopenharmony_ci }, 289162306a36Sopenharmony_ci .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | 289262306a36Sopenharmony_ci DESC_HDR_SEL0_MDEUA | 289362306a36Sopenharmony_ci DESC_HDR_MODE0_MDEU_SHA224, 289462306a36Sopenharmony_ci }, 289562306a36Sopenharmony_ci { .type = CRYPTO_ALG_TYPE_AHASH, 289662306a36Sopenharmony_ci .alg.hash = { 289762306a36Sopenharmony_ci .halg.digestsize = SHA256_DIGEST_SIZE, 289862306a36Sopenharmony_ci .halg.statesize = sizeof(struct talitos_export_state), 289962306a36Sopenharmony_ci .halg.base = { 290062306a36Sopenharmony_ci .cra_name = "sha256", 290162306a36Sopenharmony_ci .cra_driver_name = "sha256-talitos", 290262306a36Sopenharmony_ci .cra_blocksize = SHA256_BLOCK_SIZE, 290362306a36Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 290462306a36Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY, 290562306a36Sopenharmony_ci } 290662306a36Sopenharmony_ci }, 290762306a36Sopenharmony_ci .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | 290862306a36Sopenharmony_ci DESC_HDR_SEL0_MDEUA | 290962306a36Sopenharmony_ci DESC_HDR_MODE0_MDEU_SHA256, 291062306a36Sopenharmony_ci }, 291162306a36Sopenharmony_ci { .type = CRYPTO_ALG_TYPE_AHASH, 291262306a36Sopenharmony_ci .alg.hash = { 291362306a36Sopenharmony_ci .halg.digestsize = SHA384_DIGEST_SIZE, 291462306a36Sopenharmony_ci .halg.statesize = sizeof(struct talitos_export_state), 291562306a36Sopenharmony_ci .halg.base = { 291662306a36Sopenharmony_ci .cra_name = "sha384", 291762306a36Sopenharmony_ci .cra_driver_name = "sha384-talitos", 291862306a36Sopenharmony_ci .cra_blocksize = SHA384_BLOCK_SIZE, 291962306a36Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 292062306a36Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY, 292162306a36Sopenharmony_ci } 292262306a36Sopenharmony_ci }, 292362306a36Sopenharmony_ci .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | 292462306a36Sopenharmony_ci DESC_HDR_SEL0_MDEUB | 292562306a36Sopenharmony_ci DESC_HDR_MODE0_MDEUB_SHA384, 292662306a36Sopenharmony_ci }, 292762306a36Sopenharmony_ci { .type = CRYPTO_ALG_TYPE_AHASH, 292862306a36Sopenharmony_ci .alg.hash = { 292962306a36Sopenharmony_ci .halg.digestsize = SHA512_DIGEST_SIZE, 293062306a36Sopenharmony_ci .halg.statesize = sizeof(struct talitos_export_state), 293162306a36Sopenharmony_ci .halg.base = { 293262306a36Sopenharmony_ci .cra_name = "sha512", 293362306a36Sopenharmony_ci .cra_driver_name = "sha512-talitos", 293462306a36Sopenharmony_ci .cra_blocksize = SHA512_BLOCK_SIZE, 293562306a36Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 293662306a36Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY, 293762306a36Sopenharmony_ci } 293862306a36Sopenharmony_ci }, 293962306a36Sopenharmony_ci .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | 294062306a36Sopenharmony_ci DESC_HDR_SEL0_MDEUB | 294162306a36Sopenharmony_ci DESC_HDR_MODE0_MDEUB_SHA512, 294262306a36Sopenharmony_ci }, 294362306a36Sopenharmony_ci { .type = CRYPTO_ALG_TYPE_AHASH, 294462306a36Sopenharmony_ci .alg.hash = { 294562306a36Sopenharmony_ci .halg.digestsize = MD5_DIGEST_SIZE, 294662306a36Sopenharmony_ci .halg.statesize = sizeof(struct talitos_export_state), 294762306a36Sopenharmony_ci .halg.base = { 294862306a36Sopenharmony_ci .cra_name = "hmac(md5)", 294962306a36Sopenharmony_ci .cra_driver_name = "hmac-md5-talitos", 295062306a36Sopenharmony_ci .cra_blocksize = MD5_HMAC_BLOCK_SIZE, 295162306a36Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 295262306a36Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY, 295362306a36Sopenharmony_ci } 295462306a36Sopenharmony_ci }, 295562306a36Sopenharmony_ci .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | 295662306a36Sopenharmony_ci DESC_HDR_SEL0_MDEUA | 295762306a36Sopenharmony_ci DESC_HDR_MODE0_MDEU_MD5, 295862306a36Sopenharmony_ci }, 295962306a36Sopenharmony_ci { .type = CRYPTO_ALG_TYPE_AHASH, 296062306a36Sopenharmony_ci .alg.hash = { 296162306a36Sopenharmony_ci .halg.digestsize = SHA1_DIGEST_SIZE, 296262306a36Sopenharmony_ci .halg.statesize = sizeof(struct talitos_export_state), 296362306a36Sopenharmony_ci .halg.base = { 296462306a36Sopenharmony_ci .cra_name = "hmac(sha1)", 296562306a36Sopenharmony_ci .cra_driver_name = "hmac-sha1-talitos", 296662306a36Sopenharmony_ci .cra_blocksize = SHA1_BLOCK_SIZE, 296762306a36Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 296862306a36Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY, 296962306a36Sopenharmony_ci } 297062306a36Sopenharmony_ci }, 297162306a36Sopenharmony_ci .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | 297262306a36Sopenharmony_ci DESC_HDR_SEL0_MDEUA | 297362306a36Sopenharmony_ci DESC_HDR_MODE0_MDEU_SHA1, 297462306a36Sopenharmony_ci }, 297562306a36Sopenharmony_ci { .type = CRYPTO_ALG_TYPE_AHASH, 297662306a36Sopenharmony_ci .alg.hash = { 297762306a36Sopenharmony_ci .halg.digestsize = SHA224_DIGEST_SIZE, 297862306a36Sopenharmony_ci .halg.statesize = sizeof(struct talitos_export_state), 297962306a36Sopenharmony_ci .halg.base = { 298062306a36Sopenharmony_ci .cra_name = "hmac(sha224)", 298162306a36Sopenharmony_ci .cra_driver_name = "hmac-sha224-talitos", 298262306a36Sopenharmony_ci .cra_blocksize = SHA224_BLOCK_SIZE, 298362306a36Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 298462306a36Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY, 298562306a36Sopenharmony_ci } 298662306a36Sopenharmony_ci }, 298762306a36Sopenharmony_ci .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | 298862306a36Sopenharmony_ci DESC_HDR_SEL0_MDEUA | 298962306a36Sopenharmony_ci DESC_HDR_MODE0_MDEU_SHA224, 299062306a36Sopenharmony_ci }, 299162306a36Sopenharmony_ci { .type = CRYPTO_ALG_TYPE_AHASH, 299262306a36Sopenharmony_ci .alg.hash = { 299362306a36Sopenharmony_ci .halg.digestsize = SHA256_DIGEST_SIZE, 299462306a36Sopenharmony_ci .halg.statesize = sizeof(struct talitos_export_state), 299562306a36Sopenharmony_ci .halg.base = { 299662306a36Sopenharmony_ci .cra_name = "hmac(sha256)", 299762306a36Sopenharmony_ci .cra_driver_name = "hmac-sha256-talitos", 299862306a36Sopenharmony_ci .cra_blocksize = SHA256_BLOCK_SIZE, 299962306a36Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 300062306a36Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY, 300162306a36Sopenharmony_ci } 300262306a36Sopenharmony_ci }, 300362306a36Sopenharmony_ci .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | 300462306a36Sopenharmony_ci DESC_HDR_SEL0_MDEUA | 300562306a36Sopenharmony_ci DESC_HDR_MODE0_MDEU_SHA256, 300662306a36Sopenharmony_ci }, 300762306a36Sopenharmony_ci { .type = CRYPTO_ALG_TYPE_AHASH, 300862306a36Sopenharmony_ci .alg.hash = { 300962306a36Sopenharmony_ci .halg.digestsize = SHA384_DIGEST_SIZE, 301062306a36Sopenharmony_ci .halg.statesize = sizeof(struct talitos_export_state), 301162306a36Sopenharmony_ci .halg.base = { 301262306a36Sopenharmony_ci .cra_name = "hmac(sha384)", 301362306a36Sopenharmony_ci .cra_driver_name = "hmac-sha384-talitos", 301462306a36Sopenharmony_ci .cra_blocksize = SHA384_BLOCK_SIZE, 301562306a36Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 301662306a36Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY, 301762306a36Sopenharmony_ci } 301862306a36Sopenharmony_ci }, 301962306a36Sopenharmony_ci .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | 302062306a36Sopenharmony_ci DESC_HDR_SEL0_MDEUB | 302162306a36Sopenharmony_ci DESC_HDR_MODE0_MDEUB_SHA384, 302262306a36Sopenharmony_ci }, 302362306a36Sopenharmony_ci { .type = CRYPTO_ALG_TYPE_AHASH, 302462306a36Sopenharmony_ci .alg.hash = { 302562306a36Sopenharmony_ci .halg.digestsize = SHA512_DIGEST_SIZE, 302662306a36Sopenharmony_ci .halg.statesize = sizeof(struct talitos_export_state), 302762306a36Sopenharmony_ci .halg.base = { 302862306a36Sopenharmony_ci .cra_name = "hmac(sha512)", 302962306a36Sopenharmony_ci .cra_driver_name = "hmac-sha512-talitos", 303062306a36Sopenharmony_ci .cra_blocksize = SHA512_BLOCK_SIZE, 303162306a36Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 303262306a36Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY, 303362306a36Sopenharmony_ci } 303462306a36Sopenharmony_ci }, 303562306a36Sopenharmony_ci .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | 303662306a36Sopenharmony_ci DESC_HDR_SEL0_MDEUB | 303762306a36Sopenharmony_ci DESC_HDR_MODE0_MDEUB_SHA512, 303862306a36Sopenharmony_ci } 303962306a36Sopenharmony_ci}; 304062306a36Sopenharmony_ci 304162306a36Sopenharmony_cistruct talitos_crypto_alg { 304262306a36Sopenharmony_ci struct list_head entry; 304362306a36Sopenharmony_ci struct device *dev; 304462306a36Sopenharmony_ci struct talitos_alg_template algt; 304562306a36Sopenharmony_ci}; 304662306a36Sopenharmony_ci 304762306a36Sopenharmony_cistatic int talitos_init_common(struct talitos_ctx *ctx, 304862306a36Sopenharmony_ci struct talitos_crypto_alg *talitos_alg) 304962306a36Sopenharmony_ci{ 305062306a36Sopenharmony_ci struct talitos_private *priv; 305162306a36Sopenharmony_ci 305262306a36Sopenharmony_ci /* update context with ptr to dev */ 305362306a36Sopenharmony_ci ctx->dev = talitos_alg->dev; 305462306a36Sopenharmony_ci 305562306a36Sopenharmony_ci /* assign SEC channel to tfm in round-robin fashion */ 305662306a36Sopenharmony_ci priv = dev_get_drvdata(ctx->dev); 305762306a36Sopenharmony_ci ctx->ch = atomic_inc_return(&priv->last_chan) & 305862306a36Sopenharmony_ci (priv->num_channels - 1); 305962306a36Sopenharmony_ci 306062306a36Sopenharmony_ci /* copy descriptor header template value */ 306162306a36Sopenharmony_ci ctx->desc_hdr_template = talitos_alg->algt.desc_hdr_template; 306262306a36Sopenharmony_ci 306362306a36Sopenharmony_ci /* select done notification */ 306462306a36Sopenharmony_ci ctx->desc_hdr_template |= DESC_HDR_DONE_NOTIFY; 306562306a36Sopenharmony_ci 306662306a36Sopenharmony_ci return 0; 306762306a36Sopenharmony_ci} 306862306a36Sopenharmony_ci 306962306a36Sopenharmony_cistatic int talitos_cra_init_aead(struct crypto_aead *tfm) 307062306a36Sopenharmony_ci{ 307162306a36Sopenharmony_ci struct aead_alg *alg = crypto_aead_alg(tfm); 307262306a36Sopenharmony_ci struct talitos_crypto_alg *talitos_alg; 307362306a36Sopenharmony_ci struct talitos_ctx *ctx = crypto_aead_ctx(tfm); 307462306a36Sopenharmony_ci 307562306a36Sopenharmony_ci talitos_alg = container_of(alg, struct talitos_crypto_alg, 307662306a36Sopenharmony_ci algt.alg.aead); 307762306a36Sopenharmony_ci 307862306a36Sopenharmony_ci return talitos_init_common(ctx, talitos_alg); 307962306a36Sopenharmony_ci} 308062306a36Sopenharmony_ci 308162306a36Sopenharmony_cistatic int talitos_cra_init_skcipher(struct crypto_skcipher *tfm) 308262306a36Sopenharmony_ci{ 308362306a36Sopenharmony_ci struct skcipher_alg *alg = crypto_skcipher_alg(tfm); 308462306a36Sopenharmony_ci struct talitos_crypto_alg *talitos_alg; 308562306a36Sopenharmony_ci struct talitos_ctx *ctx = crypto_skcipher_ctx(tfm); 308662306a36Sopenharmony_ci 308762306a36Sopenharmony_ci talitos_alg = container_of(alg, struct talitos_crypto_alg, 308862306a36Sopenharmony_ci algt.alg.skcipher); 308962306a36Sopenharmony_ci 309062306a36Sopenharmony_ci return talitos_init_common(ctx, talitos_alg); 309162306a36Sopenharmony_ci} 309262306a36Sopenharmony_ci 309362306a36Sopenharmony_cistatic int talitos_cra_init_ahash(struct crypto_tfm *tfm) 309462306a36Sopenharmony_ci{ 309562306a36Sopenharmony_ci struct crypto_alg *alg = tfm->__crt_alg; 309662306a36Sopenharmony_ci struct talitos_crypto_alg *talitos_alg; 309762306a36Sopenharmony_ci struct talitos_ctx *ctx = crypto_tfm_ctx(tfm); 309862306a36Sopenharmony_ci 309962306a36Sopenharmony_ci talitos_alg = container_of(__crypto_ahash_alg(alg), 310062306a36Sopenharmony_ci struct talitos_crypto_alg, 310162306a36Sopenharmony_ci algt.alg.hash); 310262306a36Sopenharmony_ci 310362306a36Sopenharmony_ci ctx->keylen = 0; 310462306a36Sopenharmony_ci crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm), 310562306a36Sopenharmony_ci sizeof(struct talitos_ahash_req_ctx)); 310662306a36Sopenharmony_ci 310762306a36Sopenharmony_ci return talitos_init_common(ctx, talitos_alg); 310862306a36Sopenharmony_ci} 310962306a36Sopenharmony_ci 311062306a36Sopenharmony_cistatic void talitos_cra_exit(struct crypto_tfm *tfm) 311162306a36Sopenharmony_ci{ 311262306a36Sopenharmony_ci struct talitos_ctx *ctx = crypto_tfm_ctx(tfm); 311362306a36Sopenharmony_ci struct device *dev = ctx->dev; 311462306a36Sopenharmony_ci 311562306a36Sopenharmony_ci if (ctx->keylen) 311662306a36Sopenharmony_ci dma_unmap_single(dev, ctx->dma_key, ctx->keylen, DMA_TO_DEVICE); 311762306a36Sopenharmony_ci} 311862306a36Sopenharmony_ci 311962306a36Sopenharmony_ci/* 312062306a36Sopenharmony_ci * given the alg's descriptor header template, determine whether descriptor 312162306a36Sopenharmony_ci * type and primary/secondary execution units required match the hw 312262306a36Sopenharmony_ci * capabilities description provided in the device tree node. 312362306a36Sopenharmony_ci */ 312462306a36Sopenharmony_cistatic int hw_supports(struct device *dev, __be32 desc_hdr_template) 312562306a36Sopenharmony_ci{ 312662306a36Sopenharmony_ci struct talitos_private *priv = dev_get_drvdata(dev); 312762306a36Sopenharmony_ci int ret; 312862306a36Sopenharmony_ci 312962306a36Sopenharmony_ci ret = (1 << DESC_TYPE(desc_hdr_template) & priv->desc_types) && 313062306a36Sopenharmony_ci (1 << PRIMARY_EU(desc_hdr_template) & priv->exec_units); 313162306a36Sopenharmony_ci 313262306a36Sopenharmony_ci if (SECONDARY_EU(desc_hdr_template)) 313362306a36Sopenharmony_ci ret = ret && (1 << SECONDARY_EU(desc_hdr_template) 313462306a36Sopenharmony_ci & priv->exec_units); 313562306a36Sopenharmony_ci 313662306a36Sopenharmony_ci return ret; 313762306a36Sopenharmony_ci} 313862306a36Sopenharmony_ci 313962306a36Sopenharmony_cistatic int talitos_remove(struct platform_device *ofdev) 314062306a36Sopenharmony_ci{ 314162306a36Sopenharmony_ci struct device *dev = &ofdev->dev; 314262306a36Sopenharmony_ci struct talitos_private *priv = dev_get_drvdata(dev); 314362306a36Sopenharmony_ci struct talitos_crypto_alg *t_alg, *n; 314462306a36Sopenharmony_ci int i; 314562306a36Sopenharmony_ci 314662306a36Sopenharmony_ci list_for_each_entry_safe(t_alg, n, &priv->alg_list, entry) { 314762306a36Sopenharmony_ci switch (t_alg->algt.type) { 314862306a36Sopenharmony_ci case CRYPTO_ALG_TYPE_SKCIPHER: 314962306a36Sopenharmony_ci crypto_unregister_skcipher(&t_alg->algt.alg.skcipher); 315062306a36Sopenharmony_ci break; 315162306a36Sopenharmony_ci case CRYPTO_ALG_TYPE_AEAD: 315262306a36Sopenharmony_ci crypto_unregister_aead(&t_alg->algt.alg.aead); 315362306a36Sopenharmony_ci break; 315462306a36Sopenharmony_ci case CRYPTO_ALG_TYPE_AHASH: 315562306a36Sopenharmony_ci crypto_unregister_ahash(&t_alg->algt.alg.hash); 315662306a36Sopenharmony_ci break; 315762306a36Sopenharmony_ci } 315862306a36Sopenharmony_ci list_del(&t_alg->entry); 315962306a36Sopenharmony_ci } 316062306a36Sopenharmony_ci 316162306a36Sopenharmony_ci if (hw_supports(dev, DESC_HDR_SEL0_RNG)) 316262306a36Sopenharmony_ci talitos_unregister_rng(dev); 316362306a36Sopenharmony_ci 316462306a36Sopenharmony_ci for (i = 0; i < 2; i++) 316562306a36Sopenharmony_ci if (priv->irq[i]) { 316662306a36Sopenharmony_ci free_irq(priv->irq[i], dev); 316762306a36Sopenharmony_ci irq_dispose_mapping(priv->irq[i]); 316862306a36Sopenharmony_ci } 316962306a36Sopenharmony_ci 317062306a36Sopenharmony_ci tasklet_kill(&priv->done_task[0]); 317162306a36Sopenharmony_ci if (priv->irq[1]) 317262306a36Sopenharmony_ci tasklet_kill(&priv->done_task[1]); 317362306a36Sopenharmony_ci 317462306a36Sopenharmony_ci return 0; 317562306a36Sopenharmony_ci} 317662306a36Sopenharmony_ci 317762306a36Sopenharmony_cistatic struct talitos_crypto_alg *talitos_alg_alloc(struct device *dev, 317862306a36Sopenharmony_ci struct talitos_alg_template 317962306a36Sopenharmony_ci *template) 318062306a36Sopenharmony_ci{ 318162306a36Sopenharmony_ci struct talitos_private *priv = dev_get_drvdata(dev); 318262306a36Sopenharmony_ci struct talitos_crypto_alg *t_alg; 318362306a36Sopenharmony_ci struct crypto_alg *alg; 318462306a36Sopenharmony_ci 318562306a36Sopenharmony_ci t_alg = devm_kzalloc(dev, sizeof(struct talitos_crypto_alg), 318662306a36Sopenharmony_ci GFP_KERNEL); 318762306a36Sopenharmony_ci if (!t_alg) 318862306a36Sopenharmony_ci return ERR_PTR(-ENOMEM); 318962306a36Sopenharmony_ci 319062306a36Sopenharmony_ci t_alg->algt = *template; 319162306a36Sopenharmony_ci 319262306a36Sopenharmony_ci switch (t_alg->algt.type) { 319362306a36Sopenharmony_ci case CRYPTO_ALG_TYPE_SKCIPHER: 319462306a36Sopenharmony_ci alg = &t_alg->algt.alg.skcipher.base; 319562306a36Sopenharmony_ci alg->cra_exit = talitos_cra_exit; 319662306a36Sopenharmony_ci t_alg->algt.alg.skcipher.init = talitos_cra_init_skcipher; 319762306a36Sopenharmony_ci t_alg->algt.alg.skcipher.setkey = 319862306a36Sopenharmony_ci t_alg->algt.alg.skcipher.setkey ?: skcipher_setkey; 319962306a36Sopenharmony_ci t_alg->algt.alg.skcipher.encrypt = skcipher_encrypt; 320062306a36Sopenharmony_ci t_alg->algt.alg.skcipher.decrypt = skcipher_decrypt; 320162306a36Sopenharmony_ci if (!strcmp(alg->cra_name, "ctr(aes)") && !has_ftr_sec1(priv) && 320262306a36Sopenharmony_ci DESC_TYPE(t_alg->algt.desc_hdr_template) != 320362306a36Sopenharmony_ci DESC_TYPE(DESC_HDR_TYPE_AESU_CTR_NONSNOOP)) { 320462306a36Sopenharmony_ci devm_kfree(dev, t_alg); 320562306a36Sopenharmony_ci return ERR_PTR(-ENOTSUPP); 320662306a36Sopenharmony_ci } 320762306a36Sopenharmony_ci break; 320862306a36Sopenharmony_ci case CRYPTO_ALG_TYPE_AEAD: 320962306a36Sopenharmony_ci alg = &t_alg->algt.alg.aead.base; 321062306a36Sopenharmony_ci alg->cra_exit = talitos_cra_exit; 321162306a36Sopenharmony_ci t_alg->algt.alg.aead.init = talitos_cra_init_aead; 321262306a36Sopenharmony_ci t_alg->algt.alg.aead.setkey = t_alg->algt.alg.aead.setkey ?: 321362306a36Sopenharmony_ci aead_setkey; 321462306a36Sopenharmony_ci t_alg->algt.alg.aead.encrypt = aead_encrypt; 321562306a36Sopenharmony_ci t_alg->algt.alg.aead.decrypt = aead_decrypt; 321662306a36Sopenharmony_ci if (!(priv->features & TALITOS_FTR_SHA224_HWINIT) && 321762306a36Sopenharmony_ci !strncmp(alg->cra_name, "authenc(hmac(sha224)", 20)) { 321862306a36Sopenharmony_ci devm_kfree(dev, t_alg); 321962306a36Sopenharmony_ci return ERR_PTR(-ENOTSUPP); 322062306a36Sopenharmony_ci } 322162306a36Sopenharmony_ci break; 322262306a36Sopenharmony_ci case CRYPTO_ALG_TYPE_AHASH: 322362306a36Sopenharmony_ci alg = &t_alg->algt.alg.hash.halg.base; 322462306a36Sopenharmony_ci alg->cra_init = talitos_cra_init_ahash; 322562306a36Sopenharmony_ci alg->cra_exit = talitos_cra_exit; 322662306a36Sopenharmony_ci t_alg->algt.alg.hash.init = ahash_init; 322762306a36Sopenharmony_ci t_alg->algt.alg.hash.update = ahash_update; 322862306a36Sopenharmony_ci t_alg->algt.alg.hash.final = ahash_final; 322962306a36Sopenharmony_ci t_alg->algt.alg.hash.finup = ahash_finup; 323062306a36Sopenharmony_ci t_alg->algt.alg.hash.digest = ahash_digest; 323162306a36Sopenharmony_ci if (!strncmp(alg->cra_name, "hmac", 4)) 323262306a36Sopenharmony_ci t_alg->algt.alg.hash.setkey = ahash_setkey; 323362306a36Sopenharmony_ci t_alg->algt.alg.hash.import = ahash_import; 323462306a36Sopenharmony_ci t_alg->algt.alg.hash.export = ahash_export; 323562306a36Sopenharmony_ci 323662306a36Sopenharmony_ci if (!(priv->features & TALITOS_FTR_HMAC_OK) && 323762306a36Sopenharmony_ci !strncmp(alg->cra_name, "hmac", 4)) { 323862306a36Sopenharmony_ci devm_kfree(dev, t_alg); 323962306a36Sopenharmony_ci return ERR_PTR(-ENOTSUPP); 324062306a36Sopenharmony_ci } 324162306a36Sopenharmony_ci if (!(priv->features & TALITOS_FTR_SHA224_HWINIT) && 324262306a36Sopenharmony_ci (!strcmp(alg->cra_name, "sha224") || 324362306a36Sopenharmony_ci !strcmp(alg->cra_name, "hmac(sha224)"))) { 324462306a36Sopenharmony_ci t_alg->algt.alg.hash.init = ahash_init_sha224_swinit; 324562306a36Sopenharmony_ci t_alg->algt.desc_hdr_template = 324662306a36Sopenharmony_ci DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | 324762306a36Sopenharmony_ci DESC_HDR_SEL0_MDEUA | 324862306a36Sopenharmony_ci DESC_HDR_MODE0_MDEU_SHA256; 324962306a36Sopenharmony_ci } 325062306a36Sopenharmony_ci break; 325162306a36Sopenharmony_ci default: 325262306a36Sopenharmony_ci dev_err(dev, "unknown algorithm type %d\n", t_alg->algt.type); 325362306a36Sopenharmony_ci devm_kfree(dev, t_alg); 325462306a36Sopenharmony_ci return ERR_PTR(-EINVAL); 325562306a36Sopenharmony_ci } 325662306a36Sopenharmony_ci 325762306a36Sopenharmony_ci alg->cra_module = THIS_MODULE; 325862306a36Sopenharmony_ci if (t_alg->algt.priority) 325962306a36Sopenharmony_ci alg->cra_priority = t_alg->algt.priority; 326062306a36Sopenharmony_ci else 326162306a36Sopenharmony_ci alg->cra_priority = TALITOS_CRA_PRIORITY; 326262306a36Sopenharmony_ci if (has_ftr_sec1(priv)) 326362306a36Sopenharmony_ci alg->cra_alignmask = 3; 326462306a36Sopenharmony_ci else 326562306a36Sopenharmony_ci alg->cra_alignmask = 0; 326662306a36Sopenharmony_ci alg->cra_ctxsize = sizeof(struct talitos_ctx); 326762306a36Sopenharmony_ci alg->cra_flags |= CRYPTO_ALG_KERN_DRIVER_ONLY; 326862306a36Sopenharmony_ci 326962306a36Sopenharmony_ci t_alg->dev = dev; 327062306a36Sopenharmony_ci 327162306a36Sopenharmony_ci return t_alg; 327262306a36Sopenharmony_ci} 327362306a36Sopenharmony_ci 327462306a36Sopenharmony_cistatic int talitos_probe_irq(struct platform_device *ofdev) 327562306a36Sopenharmony_ci{ 327662306a36Sopenharmony_ci struct device *dev = &ofdev->dev; 327762306a36Sopenharmony_ci struct device_node *np = ofdev->dev.of_node; 327862306a36Sopenharmony_ci struct talitos_private *priv = dev_get_drvdata(dev); 327962306a36Sopenharmony_ci int err; 328062306a36Sopenharmony_ci bool is_sec1 = has_ftr_sec1(priv); 328162306a36Sopenharmony_ci 328262306a36Sopenharmony_ci priv->irq[0] = irq_of_parse_and_map(np, 0); 328362306a36Sopenharmony_ci if (!priv->irq[0]) { 328462306a36Sopenharmony_ci dev_err(dev, "failed to map irq\n"); 328562306a36Sopenharmony_ci return -EINVAL; 328662306a36Sopenharmony_ci } 328762306a36Sopenharmony_ci if (is_sec1) { 328862306a36Sopenharmony_ci err = request_irq(priv->irq[0], talitos1_interrupt_4ch, 0, 328962306a36Sopenharmony_ci dev_driver_string(dev), dev); 329062306a36Sopenharmony_ci goto primary_out; 329162306a36Sopenharmony_ci } 329262306a36Sopenharmony_ci 329362306a36Sopenharmony_ci priv->irq[1] = irq_of_parse_and_map(np, 1); 329462306a36Sopenharmony_ci 329562306a36Sopenharmony_ci /* get the primary irq line */ 329662306a36Sopenharmony_ci if (!priv->irq[1]) { 329762306a36Sopenharmony_ci err = request_irq(priv->irq[0], talitos2_interrupt_4ch, 0, 329862306a36Sopenharmony_ci dev_driver_string(dev), dev); 329962306a36Sopenharmony_ci goto primary_out; 330062306a36Sopenharmony_ci } 330162306a36Sopenharmony_ci 330262306a36Sopenharmony_ci err = request_irq(priv->irq[0], talitos2_interrupt_ch0_2, 0, 330362306a36Sopenharmony_ci dev_driver_string(dev), dev); 330462306a36Sopenharmony_ci if (err) 330562306a36Sopenharmony_ci goto primary_out; 330662306a36Sopenharmony_ci 330762306a36Sopenharmony_ci /* get the secondary irq line */ 330862306a36Sopenharmony_ci err = request_irq(priv->irq[1], talitos2_interrupt_ch1_3, 0, 330962306a36Sopenharmony_ci dev_driver_string(dev), dev); 331062306a36Sopenharmony_ci if (err) { 331162306a36Sopenharmony_ci dev_err(dev, "failed to request secondary irq\n"); 331262306a36Sopenharmony_ci irq_dispose_mapping(priv->irq[1]); 331362306a36Sopenharmony_ci priv->irq[1] = 0; 331462306a36Sopenharmony_ci } 331562306a36Sopenharmony_ci 331662306a36Sopenharmony_ci return err; 331762306a36Sopenharmony_ci 331862306a36Sopenharmony_ciprimary_out: 331962306a36Sopenharmony_ci if (err) { 332062306a36Sopenharmony_ci dev_err(dev, "failed to request primary irq\n"); 332162306a36Sopenharmony_ci irq_dispose_mapping(priv->irq[0]); 332262306a36Sopenharmony_ci priv->irq[0] = 0; 332362306a36Sopenharmony_ci } 332462306a36Sopenharmony_ci 332562306a36Sopenharmony_ci return err; 332662306a36Sopenharmony_ci} 332762306a36Sopenharmony_ci 332862306a36Sopenharmony_cistatic int talitos_probe(struct platform_device *ofdev) 332962306a36Sopenharmony_ci{ 333062306a36Sopenharmony_ci struct device *dev = &ofdev->dev; 333162306a36Sopenharmony_ci struct device_node *np = ofdev->dev.of_node; 333262306a36Sopenharmony_ci struct talitos_private *priv; 333362306a36Sopenharmony_ci int i, err; 333462306a36Sopenharmony_ci int stride; 333562306a36Sopenharmony_ci struct resource *res; 333662306a36Sopenharmony_ci 333762306a36Sopenharmony_ci priv = devm_kzalloc(dev, sizeof(struct talitos_private), GFP_KERNEL); 333862306a36Sopenharmony_ci if (!priv) 333962306a36Sopenharmony_ci return -ENOMEM; 334062306a36Sopenharmony_ci 334162306a36Sopenharmony_ci INIT_LIST_HEAD(&priv->alg_list); 334262306a36Sopenharmony_ci 334362306a36Sopenharmony_ci dev_set_drvdata(dev, priv); 334462306a36Sopenharmony_ci 334562306a36Sopenharmony_ci priv->ofdev = ofdev; 334662306a36Sopenharmony_ci 334762306a36Sopenharmony_ci spin_lock_init(&priv->reg_lock); 334862306a36Sopenharmony_ci 334962306a36Sopenharmony_ci res = platform_get_resource(ofdev, IORESOURCE_MEM, 0); 335062306a36Sopenharmony_ci if (!res) 335162306a36Sopenharmony_ci return -ENXIO; 335262306a36Sopenharmony_ci priv->reg = devm_ioremap(dev, res->start, resource_size(res)); 335362306a36Sopenharmony_ci if (!priv->reg) { 335462306a36Sopenharmony_ci dev_err(dev, "failed to of_iomap\n"); 335562306a36Sopenharmony_ci err = -ENOMEM; 335662306a36Sopenharmony_ci goto err_out; 335762306a36Sopenharmony_ci } 335862306a36Sopenharmony_ci 335962306a36Sopenharmony_ci /* get SEC version capabilities from device tree */ 336062306a36Sopenharmony_ci of_property_read_u32(np, "fsl,num-channels", &priv->num_channels); 336162306a36Sopenharmony_ci of_property_read_u32(np, "fsl,channel-fifo-len", &priv->chfifo_len); 336262306a36Sopenharmony_ci of_property_read_u32(np, "fsl,exec-units-mask", &priv->exec_units); 336362306a36Sopenharmony_ci of_property_read_u32(np, "fsl,descriptor-types-mask", 336462306a36Sopenharmony_ci &priv->desc_types); 336562306a36Sopenharmony_ci 336662306a36Sopenharmony_ci if (!is_power_of_2(priv->num_channels) || !priv->chfifo_len || 336762306a36Sopenharmony_ci !priv->exec_units || !priv->desc_types) { 336862306a36Sopenharmony_ci dev_err(dev, "invalid property data in device tree node\n"); 336962306a36Sopenharmony_ci err = -EINVAL; 337062306a36Sopenharmony_ci goto err_out; 337162306a36Sopenharmony_ci } 337262306a36Sopenharmony_ci 337362306a36Sopenharmony_ci if (of_device_is_compatible(np, "fsl,sec3.0")) 337462306a36Sopenharmony_ci priv->features |= TALITOS_FTR_SRC_LINK_TBL_LEN_INCLUDES_EXTENT; 337562306a36Sopenharmony_ci 337662306a36Sopenharmony_ci if (of_device_is_compatible(np, "fsl,sec2.1")) 337762306a36Sopenharmony_ci priv->features |= TALITOS_FTR_HW_AUTH_CHECK | 337862306a36Sopenharmony_ci TALITOS_FTR_SHA224_HWINIT | 337962306a36Sopenharmony_ci TALITOS_FTR_HMAC_OK; 338062306a36Sopenharmony_ci 338162306a36Sopenharmony_ci if (of_device_is_compatible(np, "fsl,sec1.0")) 338262306a36Sopenharmony_ci priv->features |= TALITOS_FTR_SEC1; 338362306a36Sopenharmony_ci 338462306a36Sopenharmony_ci if (of_device_is_compatible(np, "fsl,sec1.2")) { 338562306a36Sopenharmony_ci priv->reg_deu = priv->reg + TALITOS12_DEU; 338662306a36Sopenharmony_ci priv->reg_aesu = priv->reg + TALITOS12_AESU; 338762306a36Sopenharmony_ci priv->reg_mdeu = priv->reg + TALITOS12_MDEU; 338862306a36Sopenharmony_ci stride = TALITOS1_CH_STRIDE; 338962306a36Sopenharmony_ci } else if (of_device_is_compatible(np, "fsl,sec1.0")) { 339062306a36Sopenharmony_ci priv->reg_deu = priv->reg + TALITOS10_DEU; 339162306a36Sopenharmony_ci priv->reg_aesu = priv->reg + TALITOS10_AESU; 339262306a36Sopenharmony_ci priv->reg_mdeu = priv->reg + TALITOS10_MDEU; 339362306a36Sopenharmony_ci priv->reg_afeu = priv->reg + TALITOS10_AFEU; 339462306a36Sopenharmony_ci priv->reg_rngu = priv->reg + TALITOS10_RNGU; 339562306a36Sopenharmony_ci priv->reg_pkeu = priv->reg + TALITOS10_PKEU; 339662306a36Sopenharmony_ci stride = TALITOS1_CH_STRIDE; 339762306a36Sopenharmony_ci } else { 339862306a36Sopenharmony_ci priv->reg_deu = priv->reg + TALITOS2_DEU; 339962306a36Sopenharmony_ci priv->reg_aesu = priv->reg + TALITOS2_AESU; 340062306a36Sopenharmony_ci priv->reg_mdeu = priv->reg + TALITOS2_MDEU; 340162306a36Sopenharmony_ci priv->reg_afeu = priv->reg + TALITOS2_AFEU; 340262306a36Sopenharmony_ci priv->reg_rngu = priv->reg + TALITOS2_RNGU; 340362306a36Sopenharmony_ci priv->reg_pkeu = priv->reg + TALITOS2_PKEU; 340462306a36Sopenharmony_ci priv->reg_keu = priv->reg + TALITOS2_KEU; 340562306a36Sopenharmony_ci priv->reg_crcu = priv->reg + TALITOS2_CRCU; 340662306a36Sopenharmony_ci stride = TALITOS2_CH_STRIDE; 340762306a36Sopenharmony_ci } 340862306a36Sopenharmony_ci 340962306a36Sopenharmony_ci err = talitos_probe_irq(ofdev); 341062306a36Sopenharmony_ci if (err) 341162306a36Sopenharmony_ci goto err_out; 341262306a36Sopenharmony_ci 341362306a36Sopenharmony_ci if (has_ftr_sec1(priv)) { 341462306a36Sopenharmony_ci if (priv->num_channels == 1) 341562306a36Sopenharmony_ci tasklet_init(&priv->done_task[0], talitos1_done_ch0, 341662306a36Sopenharmony_ci (unsigned long)dev); 341762306a36Sopenharmony_ci else 341862306a36Sopenharmony_ci tasklet_init(&priv->done_task[0], talitos1_done_4ch, 341962306a36Sopenharmony_ci (unsigned long)dev); 342062306a36Sopenharmony_ci } else { 342162306a36Sopenharmony_ci if (priv->irq[1]) { 342262306a36Sopenharmony_ci tasklet_init(&priv->done_task[0], talitos2_done_ch0_2, 342362306a36Sopenharmony_ci (unsigned long)dev); 342462306a36Sopenharmony_ci tasklet_init(&priv->done_task[1], talitos2_done_ch1_3, 342562306a36Sopenharmony_ci (unsigned long)dev); 342662306a36Sopenharmony_ci } else if (priv->num_channels == 1) { 342762306a36Sopenharmony_ci tasklet_init(&priv->done_task[0], talitos2_done_ch0, 342862306a36Sopenharmony_ci (unsigned long)dev); 342962306a36Sopenharmony_ci } else { 343062306a36Sopenharmony_ci tasklet_init(&priv->done_task[0], talitos2_done_4ch, 343162306a36Sopenharmony_ci (unsigned long)dev); 343262306a36Sopenharmony_ci } 343362306a36Sopenharmony_ci } 343462306a36Sopenharmony_ci 343562306a36Sopenharmony_ci priv->chan = devm_kcalloc(dev, 343662306a36Sopenharmony_ci priv->num_channels, 343762306a36Sopenharmony_ci sizeof(struct talitos_channel), 343862306a36Sopenharmony_ci GFP_KERNEL); 343962306a36Sopenharmony_ci if (!priv->chan) { 344062306a36Sopenharmony_ci dev_err(dev, "failed to allocate channel management space\n"); 344162306a36Sopenharmony_ci err = -ENOMEM; 344262306a36Sopenharmony_ci goto err_out; 344362306a36Sopenharmony_ci } 344462306a36Sopenharmony_ci 344562306a36Sopenharmony_ci priv->fifo_len = roundup_pow_of_two(priv->chfifo_len); 344662306a36Sopenharmony_ci 344762306a36Sopenharmony_ci for (i = 0; i < priv->num_channels; i++) { 344862306a36Sopenharmony_ci priv->chan[i].reg = priv->reg + stride * (i + 1); 344962306a36Sopenharmony_ci if (!priv->irq[1] || !(i & 1)) 345062306a36Sopenharmony_ci priv->chan[i].reg += TALITOS_CH_BASE_OFFSET; 345162306a36Sopenharmony_ci 345262306a36Sopenharmony_ci spin_lock_init(&priv->chan[i].head_lock); 345362306a36Sopenharmony_ci spin_lock_init(&priv->chan[i].tail_lock); 345462306a36Sopenharmony_ci 345562306a36Sopenharmony_ci priv->chan[i].fifo = devm_kcalloc(dev, 345662306a36Sopenharmony_ci priv->fifo_len, 345762306a36Sopenharmony_ci sizeof(struct talitos_request), 345862306a36Sopenharmony_ci GFP_KERNEL); 345962306a36Sopenharmony_ci if (!priv->chan[i].fifo) { 346062306a36Sopenharmony_ci dev_err(dev, "failed to allocate request fifo %d\n", i); 346162306a36Sopenharmony_ci err = -ENOMEM; 346262306a36Sopenharmony_ci goto err_out; 346362306a36Sopenharmony_ci } 346462306a36Sopenharmony_ci 346562306a36Sopenharmony_ci atomic_set(&priv->chan[i].submit_count, 346662306a36Sopenharmony_ci -(priv->chfifo_len - 1)); 346762306a36Sopenharmony_ci } 346862306a36Sopenharmony_ci 346962306a36Sopenharmony_ci dma_set_mask(dev, DMA_BIT_MASK(36)); 347062306a36Sopenharmony_ci 347162306a36Sopenharmony_ci /* reset and initialize the h/w */ 347262306a36Sopenharmony_ci err = init_device(dev); 347362306a36Sopenharmony_ci if (err) { 347462306a36Sopenharmony_ci dev_err(dev, "failed to initialize device\n"); 347562306a36Sopenharmony_ci goto err_out; 347662306a36Sopenharmony_ci } 347762306a36Sopenharmony_ci 347862306a36Sopenharmony_ci /* register the RNG, if available */ 347962306a36Sopenharmony_ci if (hw_supports(dev, DESC_HDR_SEL0_RNG)) { 348062306a36Sopenharmony_ci err = talitos_register_rng(dev); 348162306a36Sopenharmony_ci if (err) { 348262306a36Sopenharmony_ci dev_err(dev, "failed to register hwrng: %d\n", err); 348362306a36Sopenharmony_ci goto err_out; 348462306a36Sopenharmony_ci } else 348562306a36Sopenharmony_ci dev_info(dev, "hwrng\n"); 348662306a36Sopenharmony_ci } 348762306a36Sopenharmony_ci 348862306a36Sopenharmony_ci /* register crypto algorithms the device supports */ 348962306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(driver_algs); i++) { 349062306a36Sopenharmony_ci if (hw_supports(dev, driver_algs[i].desc_hdr_template)) { 349162306a36Sopenharmony_ci struct talitos_crypto_alg *t_alg; 349262306a36Sopenharmony_ci struct crypto_alg *alg = NULL; 349362306a36Sopenharmony_ci 349462306a36Sopenharmony_ci t_alg = talitos_alg_alloc(dev, &driver_algs[i]); 349562306a36Sopenharmony_ci if (IS_ERR(t_alg)) { 349662306a36Sopenharmony_ci err = PTR_ERR(t_alg); 349762306a36Sopenharmony_ci if (err == -ENOTSUPP) 349862306a36Sopenharmony_ci continue; 349962306a36Sopenharmony_ci goto err_out; 350062306a36Sopenharmony_ci } 350162306a36Sopenharmony_ci 350262306a36Sopenharmony_ci switch (t_alg->algt.type) { 350362306a36Sopenharmony_ci case CRYPTO_ALG_TYPE_SKCIPHER: 350462306a36Sopenharmony_ci err = crypto_register_skcipher( 350562306a36Sopenharmony_ci &t_alg->algt.alg.skcipher); 350662306a36Sopenharmony_ci alg = &t_alg->algt.alg.skcipher.base; 350762306a36Sopenharmony_ci break; 350862306a36Sopenharmony_ci 350962306a36Sopenharmony_ci case CRYPTO_ALG_TYPE_AEAD: 351062306a36Sopenharmony_ci err = crypto_register_aead( 351162306a36Sopenharmony_ci &t_alg->algt.alg.aead); 351262306a36Sopenharmony_ci alg = &t_alg->algt.alg.aead.base; 351362306a36Sopenharmony_ci break; 351462306a36Sopenharmony_ci 351562306a36Sopenharmony_ci case CRYPTO_ALG_TYPE_AHASH: 351662306a36Sopenharmony_ci err = crypto_register_ahash( 351762306a36Sopenharmony_ci &t_alg->algt.alg.hash); 351862306a36Sopenharmony_ci alg = &t_alg->algt.alg.hash.halg.base; 351962306a36Sopenharmony_ci break; 352062306a36Sopenharmony_ci } 352162306a36Sopenharmony_ci if (err) { 352262306a36Sopenharmony_ci dev_err(dev, "%s alg registration failed\n", 352362306a36Sopenharmony_ci alg->cra_driver_name); 352462306a36Sopenharmony_ci devm_kfree(dev, t_alg); 352562306a36Sopenharmony_ci } else 352662306a36Sopenharmony_ci list_add_tail(&t_alg->entry, &priv->alg_list); 352762306a36Sopenharmony_ci } 352862306a36Sopenharmony_ci } 352962306a36Sopenharmony_ci if (!list_empty(&priv->alg_list)) 353062306a36Sopenharmony_ci dev_info(dev, "%s algorithms registered in /proc/crypto\n", 353162306a36Sopenharmony_ci (char *)of_get_property(np, "compatible", NULL)); 353262306a36Sopenharmony_ci 353362306a36Sopenharmony_ci return 0; 353462306a36Sopenharmony_ci 353562306a36Sopenharmony_cierr_out: 353662306a36Sopenharmony_ci talitos_remove(ofdev); 353762306a36Sopenharmony_ci 353862306a36Sopenharmony_ci return err; 353962306a36Sopenharmony_ci} 354062306a36Sopenharmony_ci 354162306a36Sopenharmony_cistatic const struct of_device_id talitos_match[] = { 354262306a36Sopenharmony_ci#ifdef CONFIG_CRYPTO_DEV_TALITOS1 354362306a36Sopenharmony_ci { 354462306a36Sopenharmony_ci .compatible = "fsl,sec1.0", 354562306a36Sopenharmony_ci }, 354662306a36Sopenharmony_ci#endif 354762306a36Sopenharmony_ci#ifdef CONFIG_CRYPTO_DEV_TALITOS2 354862306a36Sopenharmony_ci { 354962306a36Sopenharmony_ci .compatible = "fsl,sec2.0", 355062306a36Sopenharmony_ci }, 355162306a36Sopenharmony_ci#endif 355262306a36Sopenharmony_ci {}, 355362306a36Sopenharmony_ci}; 355462306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, talitos_match); 355562306a36Sopenharmony_ci 355662306a36Sopenharmony_cistatic struct platform_driver talitos_driver = { 355762306a36Sopenharmony_ci .driver = { 355862306a36Sopenharmony_ci .name = "talitos", 355962306a36Sopenharmony_ci .of_match_table = talitos_match, 356062306a36Sopenharmony_ci }, 356162306a36Sopenharmony_ci .probe = talitos_probe, 356262306a36Sopenharmony_ci .remove = talitos_remove, 356362306a36Sopenharmony_ci}; 356462306a36Sopenharmony_ci 356562306a36Sopenharmony_cimodule_platform_driver(talitos_driver); 356662306a36Sopenharmony_ci 356762306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 356862306a36Sopenharmony_ciMODULE_AUTHOR("Kim Phillips <kim.phillips@freescale.com>"); 356962306a36Sopenharmony_ciMODULE_DESCRIPTION("Freescale integrated security engine (SEC) driver"); 3570