blob: ab3389881af7a1bb5c3d9ca749303d35d940ac7a [file] [log] [blame]
Kim Phillips9c4a7962008-06-23 19:50:15 +08001/*
2 * talitos - Freescale Integrated Security Engine (SEC) device driver
3 *
Kim Phillips5228f0f2011-07-15 11:21:38 +08004 * Copyright (c) 2008-2011 Freescale Semiconductor, Inc.
Kim Phillips9c4a7962008-06-23 19:50:15 +08005 *
6 * Scatterlist Crypto API glue code copied from files with the following:
7 * Copyright (c) 2006-2007 Herbert Xu <herbert@gondor.apana.org.au>
8 *
9 * Crypto algorithm registration code copied from hifn driver:
10 * 2007+ Copyright (c) Evgeniy Polyakov <johnpol@2ka.mipt.ru>
11 * All rights reserved.
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 */
27
28#include <linux/kernel.h>
29#include <linux/module.h>
30#include <linux/mod_devicetable.h>
31#include <linux/device.h>
32#include <linux/interrupt.h>
33#include <linux/crypto.h>
34#include <linux/hw_random.h>
Rob Herring5af50732013-09-17 14:28:33 -050035#include <linux/of_address.h>
36#include <linux/of_irq.h>
Kim Phillips9c4a7962008-06-23 19:50:15 +080037#include <linux/of_platform.h>
38#include <linux/dma-mapping.h>
39#include <linux/io.h>
40#include <linux/spinlock.h>
41#include <linux/rtnetlink.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090042#include <linux/slab.h>
Kim Phillips9c4a7962008-06-23 19:50:15 +080043
44#include <crypto/algapi.h>
45#include <crypto/aes.h>
Lee Nipper3952f172008-07-10 18:29:18 +080046#include <crypto/des.h>
Kim Phillips9c4a7962008-06-23 19:50:15 +080047#include <crypto/sha.h>
Lee Nipper497f2e62010-05-19 19:20:36 +100048#include <crypto/md5.h>
Herbert Xue98014a2015-05-11 17:47:48 +080049#include <crypto/internal/aead.h>
Kim Phillips9c4a7962008-06-23 19:50:15 +080050#include <crypto/authenc.h>
Lee Nipper4de9d0b2009-03-29 15:52:32 +080051#include <crypto/skcipher.h>
Lee Nipperacbf7c622010-05-19 19:19:33 +100052#include <crypto/hash.h>
53#include <crypto/internal/hash.h>
Lee Nipper4de9d0b2009-03-29 15:52:32 +080054#include <crypto/scatterwalk.h>
Kim Phillips9c4a7962008-06-23 19:50:15 +080055
56#include "talitos.h"
57
LEROY Christophe922f9dc2015-04-17 16:32:07 +020058static void to_talitos_ptr(struct talitos_ptr *ptr, dma_addr_t dma_addr,
59 bool is_sec1)
Kim Phillips81eb0242009-08-13 11:51:51 +100060{
LEROY Christopheedc6bd62015-04-17 16:31:53 +020061 ptr->ptr = cpu_to_be32(lower_32_bits(dma_addr));
LEROY Christophe922f9dc2015-04-17 16:32:07 +020062 if (!is_sec1)
63 ptr->eptr = upper_32_bits(dma_addr);
Kim Phillips81eb0242009-08-13 11:51:51 +100064}
65
Horia Geant?42e8b0d2015-05-11 20:04:56 +030066static void to_talitos_ptr_len(struct talitos_ptr *ptr, unsigned int len,
LEROY Christophe922f9dc2015-04-17 16:32:07 +020067 bool is_sec1)
LEROY Christophe538caf82015-04-17 16:31:59 +020068{
LEROY Christophe922f9dc2015-04-17 16:32:07 +020069 if (is_sec1) {
70 ptr->res = 0;
71 ptr->len1 = cpu_to_be16(len);
72 } else {
73 ptr->len = cpu_to_be16(len);
74 }
LEROY Christophe538caf82015-04-17 16:31:59 +020075}
76
LEROY Christophe922f9dc2015-04-17 16:32:07 +020077static unsigned short from_talitos_ptr_len(struct talitos_ptr *ptr,
78 bool is_sec1)
LEROY Christophe538caf82015-04-17 16:31:59 +020079{
LEROY Christophe922f9dc2015-04-17 16:32:07 +020080 if (is_sec1)
81 return be16_to_cpu(ptr->len1);
82 else
83 return be16_to_cpu(ptr->len);
LEROY Christophe538caf82015-04-17 16:31:59 +020084}
85
LEROY Christophe922f9dc2015-04-17 16:32:07 +020086static void to_talitos_ptr_extent_clear(struct talitos_ptr *ptr, bool is_sec1)
LEROY Christophe185eb792015-04-17 16:31:55 +020087{
LEROY Christophe922f9dc2015-04-17 16:32:07 +020088 if (!is_sec1)
89 ptr->j_extent = 0;
LEROY Christophe185eb792015-04-17 16:31:55 +020090}
91
Kim Phillips9c4a7962008-06-23 19:50:15 +080092/*
93 * map virtual single (contiguous) pointer to h/w descriptor pointer
94 */
95static void map_single_talitos_ptr(struct device *dev,
LEROY Christopheedc6bd62015-04-17 16:31:53 +020096 struct talitos_ptr *ptr,
Horia Geant?42e8b0d2015-05-11 20:04:56 +030097 unsigned int len, void *data,
Kim Phillips9c4a7962008-06-23 19:50:15 +080098 enum dma_data_direction dir)
99{
Kim Phillips81eb0242009-08-13 11:51:51 +1000100 dma_addr_t dma_addr = dma_map_single(dev, data, len, dir);
LEROY Christophe922f9dc2015-04-17 16:32:07 +0200101 struct talitos_private *priv = dev_get_drvdata(dev);
102 bool is_sec1 = has_ftr_sec1(priv);
Kim Phillips81eb0242009-08-13 11:51:51 +1000103
LEROY Christophe922f9dc2015-04-17 16:32:07 +0200104 to_talitos_ptr_len(ptr, len, is_sec1);
105 to_talitos_ptr(ptr, dma_addr, is_sec1);
106 to_talitos_ptr_extent_clear(ptr, is_sec1);
Kim Phillips9c4a7962008-06-23 19:50:15 +0800107}
108
109/*
110 * unmap bus single (contiguous) h/w descriptor pointer
111 */
112static void unmap_single_talitos_ptr(struct device *dev,
LEROY Christopheedc6bd62015-04-17 16:31:53 +0200113 struct talitos_ptr *ptr,
Kim Phillips9c4a7962008-06-23 19:50:15 +0800114 enum dma_data_direction dir)
115{
LEROY Christophe922f9dc2015-04-17 16:32:07 +0200116 struct talitos_private *priv = dev_get_drvdata(dev);
117 bool is_sec1 = has_ftr_sec1(priv);
118
LEROY Christopheedc6bd62015-04-17 16:31:53 +0200119 dma_unmap_single(dev, be32_to_cpu(ptr->ptr),
LEROY Christophe922f9dc2015-04-17 16:32:07 +0200120 from_talitos_ptr_len(ptr, is_sec1), dir);
Kim Phillips9c4a7962008-06-23 19:50:15 +0800121}
122
123static int reset_channel(struct device *dev, int ch)
124{
125 struct talitos_private *priv = dev_get_drvdata(dev);
126 unsigned int timeout = TALITOS_TIMEOUT;
LEROY Christophedd3c0982015-04-17 16:32:13 +0200127 bool is_sec1 = has_ftr_sec1(priv);
Kim Phillips9c4a7962008-06-23 19:50:15 +0800128
LEROY Christophedd3c0982015-04-17 16:32:13 +0200129 if (is_sec1) {
130 setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO,
131 TALITOS1_CCCR_LO_RESET);
Kim Phillips9c4a7962008-06-23 19:50:15 +0800132
LEROY Christophedd3c0982015-04-17 16:32:13 +0200133 while ((in_be32(priv->chan[ch].reg + TALITOS_CCCR_LO) &
134 TALITOS1_CCCR_LO_RESET) && --timeout)
135 cpu_relax();
136 } else {
137 setbits32(priv->chan[ch].reg + TALITOS_CCCR,
138 TALITOS2_CCCR_RESET);
139
140 while ((in_be32(priv->chan[ch].reg + TALITOS_CCCR) &
141 TALITOS2_CCCR_RESET) && --timeout)
142 cpu_relax();
143 }
Kim Phillips9c4a7962008-06-23 19:50:15 +0800144
145 if (timeout == 0) {
146 dev_err(dev, "failed to reset channel %d\n", ch);
147 return -EIO;
148 }
149
Kim Phillips81eb0242009-08-13 11:51:51 +1000150 /* set 36-bit addressing, done writeback enable and done IRQ enable */
Kim Phillipsad42d5f2011-11-21 16:13:27 +0800151 setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO, TALITOS_CCCR_LO_EAE |
Kim Phillips81eb0242009-08-13 11:51:51 +1000152 TALITOS_CCCR_LO_CDWE | TALITOS_CCCR_LO_CDIE);
Kim Phillips9c4a7962008-06-23 19:50:15 +0800153
Kim Phillipsfe5720e2008-10-12 20:33:14 +0800154 /* and ICCR writeback, if available */
155 if (priv->features & TALITOS_FTR_HW_AUTH_CHECK)
Kim Phillipsad42d5f2011-11-21 16:13:27 +0800156 setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO,
Kim Phillipsfe5720e2008-10-12 20:33:14 +0800157 TALITOS_CCCR_LO_IWSE);
158
Kim Phillips9c4a7962008-06-23 19:50:15 +0800159 return 0;
160}
161
162static int reset_device(struct device *dev)
163{
164 struct talitos_private *priv = dev_get_drvdata(dev);
165 unsigned int timeout = TALITOS_TIMEOUT;
LEROY Christophedd3c0982015-04-17 16:32:13 +0200166 bool is_sec1 = has_ftr_sec1(priv);
167 u32 mcr = is_sec1 ? TALITOS1_MCR_SWR : TALITOS2_MCR_SWR;
Kim Phillips9c4a7962008-06-23 19:50:15 +0800168
Kim Phillipsc3e337f2011-11-21 16:13:27 +0800169 setbits32(priv->reg + TALITOS_MCR, mcr);
Kim Phillips9c4a7962008-06-23 19:50:15 +0800170
LEROY Christophedd3c0982015-04-17 16:32:13 +0200171 while ((in_be32(priv->reg + TALITOS_MCR) & mcr)
Kim Phillips9c4a7962008-06-23 19:50:15 +0800172 && --timeout)
173 cpu_relax();
174
Kim Phillips2cdba3c2011-12-12 14:59:11 -0600175 if (priv->irq[1]) {
Kim Phillipsc3e337f2011-11-21 16:13:27 +0800176 mcr = TALITOS_MCR_RCA1 | TALITOS_MCR_RCA3;
177 setbits32(priv->reg + TALITOS_MCR, mcr);
178 }
179
Kim Phillips9c4a7962008-06-23 19:50:15 +0800180 if (timeout == 0) {
181 dev_err(dev, "failed to reset device\n");
182 return -EIO;
183 }
184
185 return 0;
186}
187
188/*
189 * Reset and initialize the device
190 */
191static int init_device(struct device *dev)
192{
193 struct talitos_private *priv = dev_get_drvdata(dev);
194 int ch, err;
LEROY Christophedd3c0982015-04-17 16:32:13 +0200195 bool is_sec1 = has_ftr_sec1(priv);
Kim Phillips9c4a7962008-06-23 19:50:15 +0800196
197 /*
198 * Master reset
199 * errata documentation: warning: certain SEC interrupts
200 * are not fully cleared by writing the MCR:SWR bit,
201 * set bit twice to completely reset
202 */
203 err = reset_device(dev);
204 if (err)
205 return err;
206
207 err = reset_device(dev);
208 if (err)
209 return err;
210
211 /* reset channels */
212 for (ch = 0; ch < priv->num_channels; ch++) {
213 err = reset_channel(dev, ch);
214 if (err)
215 return err;
216 }
217
218 /* enable channel done and error interrupts */
LEROY Christophedd3c0982015-04-17 16:32:13 +0200219 if (is_sec1) {
220 clrbits32(priv->reg + TALITOS_IMR, TALITOS1_IMR_INIT);
221 clrbits32(priv->reg + TALITOS_IMR_LO, TALITOS1_IMR_LO_INIT);
222 /* disable parity error check in DEU (erroneous? test vect.) */
223 setbits32(priv->reg_deu + TALITOS_EUICR, TALITOS1_DEUICR_KPE);
224 } else {
225 setbits32(priv->reg + TALITOS_IMR, TALITOS2_IMR_INIT);
226 setbits32(priv->reg + TALITOS_IMR_LO, TALITOS2_IMR_LO_INIT);
227 }
Kim Phillips9c4a7962008-06-23 19:50:15 +0800228
Kim Phillipsfe5720e2008-10-12 20:33:14 +0800229 /* disable integrity check error interrupts (use writeback instead) */
230 if (priv->features & TALITOS_FTR_HW_AUTH_CHECK)
LEROY Christophe5fa7fa12015-04-17 16:32:11 +0200231 setbits32(priv->reg_mdeu + TALITOS_EUICR_LO,
Kim Phillipsfe5720e2008-10-12 20:33:14 +0800232 TALITOS_MDEUICR_LO_ICE);
233
Kim Phillips9c4a7962008-06-23 19:50:15 +0800234 return 0;
235}
236
237/**
238 * talitos_submit - submits a descriptor to the device for processing
239 * @dev: the SEC device to be used
Kim Phillips5228f0f2011-07-15 11:21:38 +0800240 * @ch: the SEC device channel to be used
Kim Phillips9c4a7962008-06-23 19:50:15 +0800241 * @desc: the descriptor to be processed by the device
242 * @callback: whom to call when processing is complete
243 * @context: a handle for use by caller (optional)
244 *
245 * desc must contain valid dma-mapped (bus physical) address pointers.
246 * callback must check err and feedback in descriptor header
247 * for device processing status.
248 */
Horia Geanta865d5062012-07-03 19:16:52 +0300249int talitos_submit(struct device *dev, int ch, struct talitos_desc *desc,
250 void (*callback)(struct device *dev,
251 struct talitos_desc *desc,
252 void *context, int error),
253 void *context)
Kim Phillips9c4a7962008-06-23 19:50:15 +0800254{
255 struct talitos_private *priv = dev_get_drvdata(dev);
256 struct talitos_request *request;
Kim Phillips5228f0f2011-07-15 11:21:38 +0800257 unsigned long flags;
Kim Phillips9c4a7962008-06-23 19:50:15 +0800258 int head;
LEROY Christophe7d607c6a2015-04-17 16:32:09 +0200259 bool is_sec1 = has_ftr_sec1(priv);
Kim Phillips9c4a7962008-06-23 19:50:15 +0800260
Kim Phillips4b9926282009-08-13 11:50:38 +1000261 spin_lock_irqsave(&priv->chan[ch].head_lock, flags);
Kim Phillips9c4a7962008-06-23 19:50:15 +0800262
Kim Phillips4b9926282009-08-13 11:50:38 +1000263 if (!atomic_inc_not_zero(&priv->chan[ch].submit_count)) {
Kim Phillipsec6644d2008-07-17 20:16:40 +0800264 /* h/w fifo is full */
Kim Phillips4b9926282009-08-13 11:50:38 +1000265 spin_unlock_irqrestore(&priv->chan[ch].head_lock, flags);
Kim Phillips9c4a7962008-06-23 19:50:15 +0800266 return -EAGAIN;
267 }
268
Kim Phillips4b9926282009-08-13 11:50:38 +1000269 head = priv->chan[ch].head;
270 request = &priv->chan[ch].fifo[head];
Kim Phillipsec6644d2008-07-17 20:16:40 +0800271
Kim Phillips9c4a7962008-06-23 19:50:15 +0800272 /* map descriptor and save caller data */
LEROY Christophe7d607c6a2015-04-17 16:32:09 +0200273 if (is_sec1) {
274 desc->hdr1 = desc->hdr;
275 desc->next_desc = 0;
276 request->dma_desc = dma_map_single(dev, &desc->hdr1,
277 TALITOS_DESC_SIZE,
278 DMA_BIDIRECTIONAL);
279 } else {
280 request->dma_desc = dma_map_single(dev, desc,
281 TALITOS_DESC_SIZE,
282 DMA_BIDIRECTIONAL);
283 }
Kim Phillips9c4a7962008-06-23 19:50:15 +0800284 request->callback = callback;
285 request->context = context;
286
287 /* increment fifo head */
Kim Phillips4b9926282009-08-13 11:50:38 +1000288 priv->chan[ch].head = (priv->chan[ch].head + 1) & (priv->fifo_len - 1);
Kim Phillips9c4a7962008-06-23 19:50:15 +0800289
290 smp_wmb();
291 request->desc = desc;
292
293 /* GO! */
294 wmb();
Kim Phillipsad42d5f2011-11-21 16:13:27 +0800295 out_be32(priv->chan[ch].reg + TALITOS_FF,
296 upper_32_bits(request->dma_desc));
297 out_be32(priv->chan[ch].reg + TALITOS_FF_LO,
Kim Phillipsa7524472010-09-23 15:56:38 +0800298 lower_32_bits(request->dma_desc));
Kim Phillips9c4a7962008-06-23 19:50:15 +0800299
Kim Phillips4b9926282009-08-13 11:50:38 +1000300 spin_unlock_irqrestore(&priv->chan[ch].head_lock, flags);
Kim Phillips9c4a7962008-06-23 19:50:15 +0800301
302 return -EINPROGRESS;
303}
Horia Geanta865d5062012-07-03 19:16:52 +0300304EXPORT_SYMBOL(talitos_submit);
Kim Phillips9c4a7962008-06-23 19:50:15 +0800305
306/*
307 * process what was done, notify callback of error if not
308 */
309static void flush_channel(struct device *dev, int ch, int error, int reset_ch)
310{
311 struct talitos_private *priv = dev_get_drvdata(dev);
312 struct talitos_request *request, saved_req;
313 unsigned long flags;
314 int tail, status;
LEROY Christophe7d607c6a2015-04-17 16:32:09 +0200315 bool is_sec1 = has_ftr_sec1(priv);
Kim Phillips9c4a7962008-06-23 19:50:15 +0800316
Kim Phillips4b9926282009-08-13 11:50:38 +1000317 spin_lock_irqsave(&priv->chan[ch].tail_lock, flags);
Kim Phillips9c4a7962008-06-23 19:50:15 +0800318
Kim Phillips4b9926282009-08-13 11:50:38 +1000319 tail = priv->chan[ch].tail;
320 while (priv->chan[ch].fifo[tail].desc) {
LEROY Christophe7d607c6a2015-04-17 16:32:09 +0200321 __be32 hdr;
322
Kim Phillips4b9926282009-08-13 11:50:38 +1000323 request = &priv->chan[ch].fifo[tail];
Kim Phillips9c4a7962008-06-23 19:50:15 +0800324
325 /* descriptors with their done bits set don't get the error */
326 rmb();
LEROY Christophe7d607c6a2015-04-17 16:32:09 +0200327 hdr = is_sec1 ? request->desc->hdr1 : request->desc->hdr;
328
329 if ((hdr & DESC_HDR_DONE) == DESC_HDR_DONE)
Kim Phillips9c4a7962008-06-23 19:50:15 +0800330 status = 0;
Lee Nipperca38a812008-12-20 17:09:25 +1100331 else
Kim Phillips9c4a7962008-06-23 19:50:15 +0800332 if (!error)
333 break;
334 else
335 status = error;
336
337 dma_unmap_single(dev, request->dma_desc,
LEROY Christophe7d607c6a2015-04-17 16:32:09 +0200338 TALITOS_DESC_SIZE,
Kim Phillipse938e462009-03-29 15:53:23 +0800339 DMA_BIDIRECTIONAL);
Kim Phillips9c4a7962008-06-23 19:50:15 +0800340
341 /* copy entries so we can call callback outside lock */
342 saved_req.desc = request->desc;
343 saved_req.callback = request->callback;
344 saved_req.context = request->context;
345
346 /* release request entry in fifo */
347 smp_wmb();
348 request->desc = NULL;
349
350 /* increment fifo tail */
Kim Phillips4b9926282009-08-13 11:50:38 +1000351 priv->chan[ch].tail = (tail + 1) & (priv->fifo_len - 1);
Kim Phillips9c4a7962008-06-23 19:50:15 +0800352
Kim Phillips4b9926282009-08-13 11:50:38 +1000353 spin_unlock_irqrestore(&priv->chan[ch].tail_lock, flags);
Kim Phillipsec6644d2008-07-17 20:16:40 +0800354
Kim Phillips4b9926282009-08-13 11:50:38 +1000355 atomic_dec(&priv->chan[ch].submit_count);
Kim Phillipsec6644d2008-07-17 20:16:40 +0800356
Kim Phillips9c4a7962008-06-23 19:50:15 +0800357 saved_req.callback(dev, saved_req.desc, saved_req.context,
358 status);
359 /* channel may resume processing in single desc error case */
360 if (error && !reset_ch && status == error)
361 return;
Kim Phillips4b9926282009-08-13 11:50:38 +1000362 spin_lock_irqsave(&priv->chan[ch].tail_lock, flags);
363 tail = priv->chan[ch].tail;
Kim Phillips9c4a7962008-06-23 19:50:15 +0800364 }
365
Kim Phillips4b9926282009-08-13 11:50:38 +1000366 spin_unlock_irqrestore(&priv->chan[ch].tail_lock, flags);
Kim Phillips9c4a7962008-06-23 19:50:15 +0800367}
368
369/*
370 * process completed requests for channels that have done status
371 */
LEROY Christophedd3c0982015-04-17 16:32:13 +0200372#define DEF_TALITOS1_DONE(name, ch_done_mask) \
373static void talitos1_done_##name(unsigned long data) \
374{ \
375 struct device *dev = (struct device *)data; \
376 struct talitos_private *priv = dev_get_drvdata(dev); \
377 unsigned long flags; \
378 \
379 if (ch_done_mask & 0x10000000) \
380 flush_channel(dev, 0, 0, 0); \
381 if (priv->num_channels == 1) \
382 goto out; \
383 if (ch_done_mask & 0x40000000) \
384 flush_channel(dev, 1, 0, 0); \
385 if (ch_done_mask & 0x00010000) \
386 flush_channel(dev, 2, 0, 0); \
387 if (ch_done_mask & 0x00040000) \
388 flush_channel(dev, 3, 0, 0); \
389 \
390out: \
391 /* At this point, all completed channels have been processed */ \
392 /* Unmask done interrupts for channels completed later on. */ \
393 spin_lock_irqsave(&priv->reg_lock, flags); \
394 clrbits32(priv->reg + TALITOS_IMR, ch_done_mask); \
395 clrbits32(priv->reg + TALITOS_IMR_LO, TALITOS1_IMR_LO_INIT); \
396 spin_unlock_irqrestore(&priv->reg_lock, flags); \
397}
398
399DEF_TALITOS1_DONE(4ch, TALITOS1_ISR_4CHDONE)
400
401#define DEF_TALITOS2_DONE(name, ch_done_mask) \
402static void talitos2_done_##name(unsigned long data) \
Kim Phillipsc3e337f2011-11-21 16:13:27 +0800403{ \
404 struct device *dev = (struct device *)data; \
405 struct talitos_private *priv = dev_get_drvdata(dev); \
Horia Geanta511d63c2012-03-30 17:49:53 +0300406 unsigned long flags; \
Kim Phillipsc3e337f2011-11-21 16:13:27 +0800407 \
408 if (ch_done_mask & 1) \
409 flush_channel(dev, 0, 0, 0); \
410 if (priv->num_channels == 1) \
411 goto out; \
412 if (ch_done_mask & (1 << 2)) \
413 flush_channel(dev, 1, 0, 0); \
414 if (ch_done_mask & (1 << 4)) \
415 flush_channel(dev, 2, 0, 0); \
416 if (ch_done_mask & (1 << 6)) \
417 flush_channel(dev, 3, 0, 0); \
418 \
419out: \
420 /* At this point, all completed channels have been processed */ \
421 /* Unmask done interrupts for channels completed later on. */ \
Horia Geanta511d63c2012-03-30 17:49:53 +0300422 spin_lock_irqsave(&priv->reg_lock, flags); \
Kim Phillipsc3e337f2011-11-21 16:13:27 +0800423 setbits32(priv->reg + TALITOS_IMR, ch_done_mask); \
LEROY Christophedd3c0982015-04-17 16:32:13 +0200424 setbits32(priv->reg + TALITOS_IMR_LO, TALITOS2_IMR_LO_INIT); \
Horia Geanta511d63c2012-03-30 17:49:53 +0300425 spin_unlock_irqrestore(&priv->reg_lock, flags); \
Kim Phillips9c4a7962008-06-23 19:50:15 +0800426}
LEROY Christophedd3c0982015-04-17 16:32:13 +0200427
428DEF_TALITOS2_DONE(4ch, TALITOS2_ISR_4CHDONE)
429DEF_TALITOS2_DONE(ch0_2, TALITOS2_ISR_CH_0_2_DONE)
430DEF_TALITOS2_DONE(ch1_3, TALITOS2_ISR_CH_1_3_DONE)
Kim Phillips9c4a7962008-06-23 19:50:15 +0800431
432/*
433 * locate current (offending) descriptor
434 */
Kim Phillips3e721ae2011-10-21 15:20:28 +0200435static u32 current_desc_hdr(struct device *dev, int ch)
Kim Phillips9c4a7962008-06-23 19:50:15 +0800436{
437 struct talitos_private *priv = dev_get_drvdata(dev);
Horia Geantab62ffd82013-11-13 12:20:37 +0200438 int tail, iter;
Kim Phillips9c4a7962008-06-23 19:50:15 +0800439 dma_addr_t cur_desc;
440
Horia Geantab62ffd82013-11-13 12:20:37 +0200441 cur_desc = ((u64)in_be32(priv->chan[ch].reg + TALITOS_CDPR)) << 32;
442 cur_desc |= in_be32(priv->chan[ch].reg + TALITOS_CDPR_LO);
Kim Phillips9c4a7962008-06-23 19:50:15 +0800443
Horia Geantab62ffd82013-11-13 12:20:37 +0200444 if (!cur_desc) {
445 dev_err(dev, "CDPR is NULL, giving up search for offending descriptor\n");
446 return 0;
447 }
448
449 tail = priv->chan[ch].tail;
450
451 iter = tail;
452 while (priv->chan[ch].fifo[iter].dma_desc != cur_desc) {
453 iter = (iter + 1) & (priv->fifo_len - 1);
454 if (iter == tail) {
Kim Phillips9c4a7962008-06-23 19:50:15 +0800455 dev_err(dev, "couldn't locate current descriptor\n");
Kim Phillips3e721ae2011-10-21 15:20:28 +0200456 return 0;
Kim Phillips9c4a7962008-06-23 19:50:15 +0800457 }
458 }
459
Horia Geantab62ffd82013-11-13 12:20:37 +0200460 return priv->chan[ch].fifo[iter].desc->hdr;
Kim Phillips9c4a7962008-06-23 19:50:15 +0800461}
462
463/*
464 * user diagnostics; report root cause of error based on execution unit status
465 */
Kim Phillips3e721ae2011-10-21 15:20:28 +0200466static void report_eu_error(struct device *dev, int ch, u32 desc_hdr)
Kim Phillips9c4a7962008-06-23 19:50:15 +0800467{
468 struct talitos_private *priv = dev_get_drvdata(dev);
469 int i;
470
Kim Phillips3e721ae2011-10-21 15:20:28 +0200471 if (!desc_hdr)
Kim Phillipsad42d5f2011-11-21 16:13:27 +0800472 desc_hdr = in_be32(priv->chan[ch].reg + TALITOS_DESCBUF);
Kim Phillips3e721ae2011-10-21 15:20:28 +0200473
474 switch (desc_hdr & DESC_HDR_SEL0_MASK) {
Kim Phillips9c4a7962008-06-23 19:50:15 +0800475 case DESC_HDR_SEL0_AFEU:
476 dev_err(dev, "AFEUISR 0x%08x_%08x\n",
LEROY Christophe5fa7fa12015-04-17 16:32:11 +0200477 in_be32(priv->reg_afeu + TALITOS_EUISR),
478 in_be32(priv->reg_afeu + TALITOS_EUISR_LO));
Kim Phillips9c4a7962008-06-23 19:50:15 +0800479 break;
480 case DESC_HDR_SEL0_DEU:
481 dev_err(dev, "DEUISR 0x%08x_%08x\n",
LEROY Christophe5fa7fa12015-04-17 16:32:11 +0200482 in_be32(priv->reg_deu + TALITOS_EUISR),
483 in_be32(priv->reg_deu + TALITOS_EUISR_LO));
Kim Phillips9c4a7962008-06-23 19:50:15 +0800484 break;
485 case DESC_HDR_SEL0_MDEUA:
486 case DESC_HDR_SEL0_MDEUB:
487 dev_err(dev, "MDEUISR 0x%08x_%08x\n",
LEROY Christophe5fa7fa12015-04-17 16:32:11 +0200488 in_be32(priv->reg_mdeu + TALITOS_EUISR),
489 in_be32(priv->reg_mdeu + TALITOS_EUISR_LO));
Kim Phillips9c4a7962008-06-23 19:50:15 +0800490 break;
491 case DESC_HDR_SEL0_RNG:
492 dev_err(dev, "RNGUISR 0x%08x_%08x\n",
LEROY Christophe5fa7fa12015-04-17 16:32:11 +0200493 in_be32(priv->reg_rngu + TALITOS_ISR),
494 in_be32(priv->reg_rngu + TALITOS_ISR_LO));
Kim Phillips9c4a7962008-06-23 19:50:15 +0800495 break;
496 case DESC_HDR_SEL0_PKEU:
497 dev_err(dev, "PKEUISR 0x%08x_%08x\n",
LEROY Christophe5fa7fa12015-04-17 16:32:11 +0200498 in_be32(priv->reg_pkeu + TALITOS_EUISR),
499 in_be32(priv->reg_pkeu + TALITOS_EUISR_LO));
Kim Phillips9c4a7962008-06-23 19:50:15 +0800500 break;
501 case DESC_HDR_SEL0_AESU:
502 dev_err(dev, "AESUISR 0x%08x_%08x\n",
LEROY Christophe5fa7fa12015-04-17 16:32:11 +0200503 in_be32(priv->reg_aesu + TALITOS_EUISR),
504 in_be32(priv->reg_aesu + TALITOS_EUISR_LO));
Kim Phillips9c4a7962008-06-23 19:50:15 +0800505 break;
506 case DESC_HDR_SEL0_CRCU:
507 dev_err(dev, "CRCUISR 0x%08x_%08x\n",
LEROY Christophe5fa7fa12015-04-17 16:32:11 +0200508 in_be32(priv->reg_crcu + TALITOS_EUISR),
509 in_be32(priv->reg_crcu + TALITOS_EUISR_LO));
Kim Phillips9c4a7962008-06-23 19:50:15 +0800510 break;
511 case DESC_HDR_SEL0_KEU:
512 dev_err(dev, "KEUISR 0x%08x_%08x\n",
LEROY Christophe5fa7fa12015-04-17 16:32:11 +0200513 in_be32(priv->reg_pkeu + TALITOS_EUISR),
514 in_be32(priv->reg_pkeu + TALITOS_EUISR_LO));
Kim Phillips9c4a7962008-06-23 19:50:15 +0800515 break;
516 }
517
Kim Phillips3e721ae2011-10-21 15:20:28 +0200518 switch (desc_hdr & DESC_HDR_SEL1_MASK) {
Kim Phillips9c4a7962008-06-23 19:50:15 +0800519 case DESC_HDR_SEL1_MDEUA:
520 case DESC_HDR_SEL1_MDEUB:
521 dev_err(dev, "MDEUISR 0x%08x_%08x\n",
LEROY Christophe5fa7fa12015-04-17 16:32:11 +0200522 in_be32(priv->reg_mdeu + TALITOS_EUISR),
523 in_be32(priv->reg_mdeu + TALITOS_EUISR_LO));
Kim Phillips9c4a7962008-06-23 19:50:15 +0800524 break;
525 case DESC_HDR_SEL1_CRCU:
526 dev_err(dev, "CRCUISR 0x%08x_%08x\n",
LEROY Christophe5fa7fa12015-04-17 16:32:11 +0200527 in_be32(priv->reg_crcu + TALITOS_EUISR),
528 in_be32(priv->reg_crcu + TALITOS_EUISR_LO));
Kim Phillips9c4a7962008-06-23 19:50:15 +0800529 break;
530 }
531
532 for (i = 0; i < 8; i++)
533 dev_err(dev, "DESCBUF 0x%08x_%08x\n",
Kim Phillipsad42d5f2011-11-21 16:13:27 +0800534 in_be32(priv->chan[ch].reg + TALITOS_DESCBUF + 8*i),
535 in_be32(priv->chan[ch].reg + TALITOS_DESCBUF_LO + 8*i));
Kim Phillips9c4a7962008-06-23 19:50:15 +0800536}
537
538/*
539 * recover from error interrupts
540 */
Kim Phillips5e718a02011-12-12 14:59:12 -0600541static void talitos_error(struct device *dev, u32 isr, u32 isr_lo)
Kim Phillips9c4a7962008-06-23 19:50:15 +0800542{
Kim Phillips9c4a7962008-06-23 19:50:15 +0800543 struct talitos_private *priv = dev_get_drvdata(dev);
544 unsigned int timeout = TALITOS_TIMEOUT;
LEROY Christophedd3c0982015-04-17 16:32:13 +0200545 int ch, error, reset_dev = 0;
Horia Geant?42e8b0d2015-05-11 20:04:56 +0300546 u32 v_lo;
LEROY Christophedd3c0982015-04-17 16:32:13 +0200547 bool is_sec1 = has_ftr_sec1(priv);
548 int reset_ch = is_sec1 ? 1 : 0; /* only SEC2 supports continuation */
Kim Phillips9c4a7962008-06-23 19:50:15 +0800549
550 for (ch = 0; ch < priv->num_channels; ch++) {
551 /* skip channels without errors */
LEROY Christophedd3c0982015-04-17 16:32:13 +0200552 if (is_sec1) {
553 /* bits 29, 31, 17, 19 */
554 if (!(isr & (1 << (29 + (ch & 1) * 2 - (ch & 2) * 6))))
555 continue;
556 } else {
557 if (!(isr & (1 << (ch * 2 + 1))))
558 continue;
559 }
Kim Phillips9c4a7962008-06-23 19:50:15 +0800560
561 error = -EINVAL;
562
Kim Phillipsad42d5f2011-11-21 16:13:27 +0800563 v_lo = in_be32(priv->chan[ch].reg + TALITOS_CCPSR_LO);
Kim Phillips9c4a7962008-06-23 19:50:15 +0800564
565 if (v_lo & TALITOS_CCPSR_LO_DOF) {
566 dev_err(dev, "double fetch fifo overflow error\n");
567 error = -EAGAIN;
568 reset_ch = 1;
569 }
570 if (v_lo & TALITOS_CCPSR_LO_SOF) {
571 /* h/w dropped descriptor */
572 dev_err(dev, "single fetch fifo overflow error\n");
573 error = -EAGAIN;
574 }
575 if (v_lo & TALITOS_CCPSR_LO_MDTE)
576 dev_err(dev, "master data transfer error\n");
577 if (v_lo & TALITOS_CCPSR_LO_SGDLZ)
LEROY Christophedd3c0982015-04-17 16:32:13 +0200578 dev_err(dev, is_sec1 ? "pointeur not complete error\n"
579 : "s/g data length zero error\n");
Kim Phillips9c4a7962008-06-23 19:50:15 +0800580 if (v_lo & TALITOS_CCPSR_LO_FPZ)
LEROY Christophedd3c0982015-04-17 16:32:13 +0200581 dev_err(dev, is_sec1 ? "parity error\n"
582 : "fetch pointer zero error\n");
Kim Phillips9c4a7962008-06-23 19:50:15 +0800583 if (v_lo & TALITOS_CCPSR_LO_IDH)
584 dev_err(dev, "illegal descriptor header error\n");
585 if (v_lo & TALITOS_CCPSR_LO_IEU)
LEROY Christophedd3c0982015-04-17 16:32:13 +0200586 dev_err(dev, is_sec1 ? "static assignment error\n"
587 : "invalid exec unit error\n");
Kim Phillips9c4a7962008-06-23 19:50:15 +0800588 if (v_lo & TALITOS_CCPSR_LO_EU)
Kim Phillips3e721ae2011-10-21 15:20:28 +0200589 report_eu_error(dev, ch, current_desc_hdr(dev, ch));
LEROY Christophedd3c0982015-04-17 16:32:13 +0200590 if (!is_sec1) {
591 if (v_lo & TALITOS_CCPSR_LO_GB)
592 dev_err(dev, "gather boundary error\n");
593 if (v_lo & TALITOS_CCPSR_LO_GRL)
594 dev_err(dev, "gather return/length error\n");
595 if (v_lo & TALITOS_CCPSR_LO_SB)
596 dev_err(dev, "scatter boundary error\n");
597 if (v_lo & TALITOS_CCPSR_LO_SRL)
598 dev_err(dev, "scatter return/length error\n");
599 }
Kim Phillips9c4a7962008-06-23 19:50:15 +0800600
601 flush_channel(dev, ch, error, reset_ch);
602
603 if (reset_ch) {
604 reset_channel(dev, ch);
605 } else {
Kim Phillipsad42d5f2011-11-21 16:13:27 +0800606 setbits32(priv->chan[ch].reg + TALITOS_CCCR,
LEROY Christophedd3c0982015-04-17 16:32:13 +0200607 TALITOS2_CCCR_CONT);
Kim Phillipsad42d5f2011-11-21 16:13:27 +0800608 setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO, 0);
609 while ((in_be32(priv->chan[ch].reg + TALITOS_CCCR) &
LEROY Christophedd3c0982015-04-17 16:32:13 +0200610 TALITOS2_CCCR_CONT) && --timeout)
Kim Phillips9c4a7962008-06-23 19:50:15 +0800611 cpu_relax();
612 if (timeout == 0) {
613 dev_err(dev, "failed to restart channel %d\n",
614 ch);
615 reset_dev = 1;
616 }
617 }
618 }
LEROY Christophedd3c0982015-04-17 16:32:13 +0200619 if (reset_dev || (is_sec1 && isr & ~TALITOS1_ISR_4CHERR) ||
620 (!is_sec1 && isr & ~TALITOS2_ISR_4CHERR) || isr_lo) {
621 if (is_sec1 && (isr_lo & TALITOS1_ISR_TEA_ERR))
622 dev_err(dev, "TEA error: ISR 0x%08x_%08x\n",
623 isr, isr_lo);
624 else
625 dev_err(dev, "done overflow, internal time out, or "
626 "rngu error: ISR 0x%08x_%08x\n", isr, isr_lo);
Kim Phillips9c4a7962008-06-23 19:50:15 +0800627
628 /* purge request queues */
629 for (ch = 0; ch < priv->num_channels; ch++)
630 flush_channel(dev, ch, -EIO, 1);
631
632 /* reset and reinitialize the device */
633 init_device(dev);
634 }
635}
636
LEROY Christophedd3c0982015-04-17 16:32:13 +0200637#define DEF_TALITOS1_INTERRUPT(name, ch_done_mask, ch_err_mask, tlet) \
638static irqreturn_t talitos1_interrupt_##name(int irq, void *data) \
639{ \
640 struct device *dev = data; \
641 struct talitos_private *priv = dev_get_drvdata(dev); \
642 u32 isr, isr_lo; \
643 unsigned long flags; \
644 \
645 spin_lock_irqsave(&priv->reg_lock, flags); \
646 isr = in_be32(priv->reg + TALITOS_ISR); \
647 isr_lo = in_be32(priv->reg + TALITOS_ISR_LO); \
648 /* Acknowledge interrupt */ \
649 out_be32(priv->reg + TALITOS_ICR, isr & (ch_done_mask | ch_err_mask)); \
650 out_be32(priv->reg + TALITOS_ICR_LO, isr_lo); \
651 \
652 if (unlikely(isr & ch_err_mask || isr_lo & TALITOS1_IMR_LO_INIT)) { \
653 spin_unlock_irqrestore(&priv->reg_lock, flags); \
654 talitos_error(dev, isr & ch_err_mask, isr_lo); \
655 } \
656 else { \
657 if (likely(isr & ch_done_mask)) { \
658 /* mask further done interrupts. */ \
659 setbits32(priv->reg + TALITOS_IMR, ch_done_mask); \
660 /* done_task will unmask done interrupts at exit */ \
661 tasklet_schedule(&priv->done_task[tlet]); \
662 } \
663 spin_unlock_irqrestore(&priv->reg_lock, flags); \
664 } \
665 \
666 return (isr & (ch_done_mask | ch_err_mask) || isr_lo) ? IRQ_HANDLED : \
667 IRQ_NONE; \
668}
669
670DEF_TALITOS1_INTERRUPT(4ch, TALITOS1_ISR_4CHDONE, TALITOS1_ISR_4CHERR, 0)
671
672#define DEF_TALITOS2_INTERRUPT(name, ch_done_mask, ch_err_mask, tlet) \
673static irqreturn_t talitos2_interrupt_##name(int irq, void *data) \
Kim Phillipsc3e337f2011-11-21 16:13:27 +0800674{ \
675 struct device *dev = data; \
676 struct talitos_private *priv = dev_get_drvdata(dev); \
677 u32 isr, isr_lo; \
Horia Geanta511d63c2012-03-30 17:49:53 +0300678 unsigned long flags; \
Kim Phillipsc3e337f2011-11-21 16:13:27 +0800679 \
Horia Geanta511d63c2012-03-30 17:49:53 +0300680 spin_lock_irqsave(&priv->reg_lock, flags); \
Kim Phillipsc3e337f2011-11-21 16:13:27 +0800681 isr = in_be32(priv->reg + TALITOS_ISR); \
682 isr_lo = in_be32(priv->reg + TALITOS_ISR_LO); \
683 /* Acknowledge interrupt */ \
684 out_be32(priv->reg + TALITOS_ICR, isr & (ch_done_mask | ch_err_mask)); \
685 out_be32(priv->reg + TALITOS_ICR_LO, isr_lo); \
686 \
Horia Geanta511d63c2012-03-30 17:49:53 +0300687 if (unlikely(isr & ch_err_mask || isr_lo)) { \
688 spin_unlock_irqrestore(&priv->reg_lock, flags); \
689 talitos_error(dev, isr & ch_err_mask, isr_lo); \
690 } \
691 else { \
Kim Phillipsc3e337f2011-11-21 16:13:27 +0800692 if (likely(isr & ch_done_mask)) { \
693 /* mask further done interrupts. */ \
694 clrbits32(priv->reg + TALITOS_IMR, ch_done_mask); \
695 /* done_task will unmask done interrupts at exit */ \
696 tasklet_schedule(&priv->done_task[tlet]); \
697 } \
Horia Geanta511d63c2012-03-30 17:49:53 +0300698 spin_unlock_irqrestore(&priv->reg_lock, flags); \
699 } \
Kim Phillipsc3e337f2011-11-21 16:13:27 +0800700 \
701 return (isr & (ch_done_mask | ch_err_mask) || isr_lo) ? IRQ_HANDLED : \
702 IRQ_NONE; \
Kim Phillips9c4a7962008-06-23 19:50:15 +0800703}
LEROY Christophedd3c0982015-04-17 16:32:13 +0200704
705DEF_TALITOS2_INTERRUPT(4ch, TALITOS2_ISR_4CHDONE, TALITOS2_ISR_4CHERR, 0)
706DEF_TALITOS2_INTERRUPT(ch0_2, TALITOS2_ISR_CH_0_2_DONE, TALITOS2_ISR_CH_0_2_ERR,
707 0)
708DEF_TALITOS2_INTERRUPT(ch1_3, TALITOS2_ISR_CH_1_3_DONE, TALITOS2_ISR_CH_1_3_ERR,
709 1)
Kim Phillips9c4a7962008-06-23 19:50:15 +0800710
711/*
712 * hwrng
713 */
714static int talitos_rng_data_present(struct hwrng *rng, int wait)
715{
716 struct device *dev = (struct device *)rng->priv;
717 struct talitos_private *priv = dev_get_drvdata(dev);
718 u32 ofl;
719 int i;
720
721 for (i = 0; i < 20; i++) {
LEROY Christophe5fa7fa12015-04-17 16:32:11 +0200722 ofl = in_be32(priv->reg_rngu + TALITOS_EUSR_LO) &
Kim Phillips9c4a7962008-06-23 19:50:15 +0800723 TALITOS_RNGUSR_LO_OFL;
724 if (ofl || !wait)
725 break;
726 udelay(10);
727 }
728
729 return !!ofl;
730}
731
732static int talitos_rng_data_read(struct hwrng *rng, u32 *data)
733{
734 struct device *dev = (struct device *)rng->priv;
735 struct talitos_private *priv = dev_get_drvdata(dev);
736
737 /* rng fifo requires 64-bit accesses */
LEROY Christophe5fa7fa12015-04-17 16:32:11 +0200738 *data = in_be32(priv->reg_rngu + TALITOS_EU_FIFO);
739 *data = in_be32(priv->reg_rngu + TALITOS_EU_FIFO_LO);
Kim Phillips9c4a7962008-06-23 19:50:15 +0800740
741 return sizeof(u32);
742}
743
744static int talitos_rng_init(struct hwrng *rng)
745{
746 struct device *dev = (struct device *)rng->priv;
747 struct talitos_private *priv = dev_get_drvdata(dev);
748 unsigned int timeout = TALITOS_TIMEOUT;
749
LEROY Christophe5fa7fa12015-04-17 16:32:11 +0200750 setbits32(priv->reg_rngu + TALITOS_EURCR_LO, TALITOS_RNGURCR_LO_SR);
751 while (!(in_be32(priv->reg_rngu + TALITOS_EUSR_LO)
752 & TALITOS_RNGUSR_LO_RD)
Kim Phillips9c4a7962008-06-23 19:50:15 +0800753 && --timeout)
754 cpu_relax();
755 if (timeout == 0) {
756 dev_err(dev, "failed to reset rng hw\n");
757 return -ENODEV;
758 }
759
760 /* start generating */
LEROY Christophe5fa7fa12015-04-17 16:32:11 +0200761 setbits32(priv->reg_rngu + TALITOS_EUDSR_LO, 0);
Kim Phillips9c4a7962008-06-23 19:50:15 +0800762
763 return 0;
764}
765
766static int talitos_register_rng(struct device *dev)
767{
768 struct talitos_private *priv = dev_get_drvdata(dev);
Aaron Sierra35a3bb32015-08-05 16:52:08 -0500769 int err;
Kim Phillips9c4a7962008-06-23 19:50:15 +0800770
771 priv->rng.name = dev_driver_string(dev),
772 priv->rng.init = talitos_rng_init,
773 priv->rng.data_present = talitos_rng_data_present,
774 priv->rng.data_read = talitos_rng_data_read,
775 priv->rng.priv = (unsigned long)dev;
776
Aaron Sierra35a3bb32015-08-05 16:52:08 -0500777 err = hwrng_register(&priv->rng);
778 if (!err)
779 priv->rng_registered = true;
780
781 return err;
Kim Phillips9c4a7962008-06-23 19:50:15 +0800782}
783
784static void talitos_unregister_rng(struct device *dev)
785{
786 struct talitos_private *priv = dev_get_drvdata(dev);
787
Aaron Sierra35a3bb32015-08-05 16:52:08 -0500788 if (!priv->rng_registered)
789 return;
790
Kim Phillips9c4a7962008-06-23 19:50:15 +0800791 hwrng_unregister(&priv->rng);
Aaron Sierra35a3bb32015-08-05 16:52:08 -0500792 priv->rng_registered = false;
Kim Phillips9c4a7962008-06-23 19:50:15 +0800793}
794
795/*
796 * crypto alg
797 */
798#define TALITOS_CRA_PRIORITY 3000
Horia Geanta357fb602012-07-03 19:16:53 +0300799#define TALITOS_MAX_KEY_SIZE 96
Lee Nipper3952f172008-07-10 18:29:18 +0800800#define TALITOS_MAX_IV_LENGTH 16 /* max of AES_BLOCK_SIZE, DES3_EDE_BLOCK_SIZE */
Lee Nipper70bcaca2008-07-03 19:08:46 +0800801
Kim Phillips9c4a7962008-06-23 19:50:15 +0800802struct talitos_ctx {
803 struct device *dev;
Kim Phillips5228f0f2011-07-15 11:21:38 +0800804 int ch;
Kim Phillips9c4a7962008-06-23 19:50:15 +0800805 __be32 desc_hdr_template;
806 u8 key[TALITOS_MAX_KEY_SIZE];
Lee Nipper70bcaca2008-07-03 19:08:46 +0800807 u8 iv[TALITOS_MAX_IV_LENGTH];
Kim Phillips9c4a7962008-06-23 19:50:15 +0800808 unsigned int keylen;
809 unsigned int enckeylen;
810 unsigned int authkeylen;
Kim Phillips9c4a7962008-06-23 19:50:15 +0800811};
812
Lee Nipper497f2e62010-05-19 19:20:36 +1000813#define HASH_MAX_BLOCK_SIZE SHA512_BLOCK_SIZE
814#define TALITOS_MDEU_MAX_CONTEXT_SIZE TALITOS_MDEU_CONTEXT_SIZE_SHA384_SHA512
815
816struct talitos_ahash_req_ctx {
Kim Phillips60f208d2010-05-19 19:21:53 +1000817 u32 hw_context[TALITOS_MDEU_MAX_CONTEXT_SIZE / sizeof(u32)];
Lee Nipper497f2e62010-05-19 19:20:36 +1000818 unsigned int hw_context_size;
819 u8 buf[HASH_MAX_BLOCK_SIZE];
820 u8 bufnext[HASH_MAX_BLOCK_SIZE];
Kim Phillips60f208d2010-05-19 19:21:53 +1000821 unsigned int swinit;
Lee Nipper497f2e62010-05-19 19:20:36 +1000822 unsigned int first;
823 unsigned int last;
824 unsigned int to_hash_later;
Horia Geant?42e8b0d2015-05-11 20:04:56 +0300825 unsigned int nbuf;
Lee Nipper497f2e62010-05-19 19:20:36 +1000826 struct scatterlist bufsl[2];
827 struct scatterlist *psrc;
828};
829
Lee Nipper56af8cd2009-03-29 15:50:50 +0800830static int aead_setkey(struct crypto_aead *authenc,
831 const u8 *key, unsigned int keylen)
Kim Phillips9c4a7962008-06-23 19:50:15 +0800832{
833 struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
Mathias Krausec306a982013-10-15 13:49:34 +0200834 struct crypto_authenc_keys keys;
Kim Phillips9c4a7962008-06-23 19:50:15 +0800835
Mathias Krausec306a982013-10-15 13:49:34 +0200836 if (crypto_authenc_extractkeys(&keys, key, keylen) != 0)
Kim Phillips9c4a7962008-06-23 19:50:15 +0800837 goto badkey;
838
Mathias Krausec306a982013-10-15 13:49:34 +0200839 if (keys.authkeylen + keys.enckeylen > TALITOS_MAX_KEY_SIZE)
Kim Phillips9c4a7962008-06-23 19:50:15 +0800840 goto badkey;
841
Mathias Krausec306a982013-10-15 13:49:34 +0200842 memcpy(ctx->key, keys.authkey, keys.authkeylen);
843 memcpy(&ctx->key[keys.authkeylen], keys.enckey, keys.enckeylen);
Kim Phillips9c4a7962008-06-23 19:50:15 +0800844
Mathias Krausec306a982013-10-15 13:49:34 +0200845 ctx->keylen = keys.authkeylen + keys.enckeylen;
846 ctx->enckeylen = keys.enckeylen;
847 ctx->authkeylen = keys.authkeylen;
Kim Phillips9c4a7962008-06-23 19:50:15 +0800848
849 return 0;
850
851badkey:
852 crypto_aead_set_flags(authenc, CRYPTO_TFM_RES_BAD_KEY_LEN);
853 return -EINVAL;
854}
855
856/*
Lee Nipper56af8cd2009-03-29 15:50:50 +0800857 * talitos_edesc - s/w-extended descriptor
Kim Phillips9c4a7962008-06-23 19:50:15 +0800858 * @src_nents: number of segments in input scatterlist
859 * @dst_nents: number of segments in output scatterlist
Herbert Xuaeb4c132015-07-30 17:53:22 +0800860 * @icv_ool: whether ICV is out-of-line
Horia Geanta79fd31d2012-08-02 17:16:40 +0300861 * @iv_dma: dma address of iv for checking continuity and link table
Kim Phillips9c4a7962008-06-23 19:50:15 +0800862 * @dma_len: length of dma mapped link_tbl space
LEROY Christophe6f65f6a2015-04-17 16:32:15 +0200863 * @dma_link_tbl: bus physical address of link_tbl/buf
Kim Phillips9c4a7962008-06-23 19:50:15 +0800864 * @desc: h/w descriptor
LEROY Christophe6f65f6a2015-04-17 16:32:15 +0200865 * @link_tbl: input and output h/w link tables (if {src,dst}_nents > 1) (SEC2)
866 * @buf: input and output buffeur (if {src,dst}_nents > 1) (SEC1)
Kim Phillips9c4a7962008-06-23 19:50:15 +0800867 *
868 * if decrypting (with authcheck), or either one of src_nents or dst_nents
869 * is greater than 1, an integrity check value is concatenated to the end
870 * of link_tbl data
871 */
Lee Nipper56af8cd2009-03-29 15:50:50 +0800872struct talitos_edesc {
Kim Phillips9c4a7962008-06-23 19:50:15 +0800873 int src_nents;
874 int dst_nents;
Herbert Xuaeb4c132015-07-30 17:53:22 +0800875 bool icv_ool;
Horia Geanta79fd31d2012-08-02 17:16:40 +0300876 dma_addr_t iv_dma;
Kim Phillips9c4a7962008-06-23 19:50:15 +0800877 int dma_len;
878 dma_addr_t dma_link_tbl;
879 struct talitos_desc desc;
LEROY Christophe6f65f6a2015-04-17 16:32:15 +0200880 union {
881 struct talitos_ptr link_tbl[0];
882 u8 buf[0];
883 };
Kim Phillips9c4a7962008-06-23 19:50:15 +0800884};
885
Lee Nipper4de9d0b2009-03-29 15:52:32 +0800886static void talitos_sg_unmap(struct device *dev,
887 struct talitos_edesc *edesc,
888 struct scatterlist *src,
889 struct scatterlist *dst)
890{
891 unsigned int src_nents = edesc->src_nents ? : 1;
892 unsigned int dst_nents = edesc->dst_nents ? : 1;
893
894 if (src != dst) {
LABBE Corentinb8a011d2015-09-23 13:55:25 +0200895 dma_unmap_sg(dev, src, src_nents, DMA_TO_DEVICE);
Lee Nipper4de9d0b2009-03-29 15:52:32 +0800896
Lee Nipper497f2e62010-05-19 19:20:36 +1000897 if (dst) {
LABBE Corentinb8a011d2015-09-23 13:55:25 +0200898 dma_unmap_sg(dev, dst, dst_nents, DMA_FROM_DEVICE);
Lee Nipper497f2e62010-05-19 19:20:36 +1000899 }
Lee Nipper4de9d0b2009-03-29 15:52:32 +0800900 } else
LABBE Corentinb8a011d2015-09-23 13:55:25 +0200901 dma_unmap_sg(dev, src, src_nents, DMA_BIDIRECTIONAL);
Lee Nipper4de9d0b2009-03-29 15:52:32 +0800902}
903
Kim Phillips9c4a7962008-06-23 19:50:15 +0800904static void ipsec_esp_unmap(struct device *dev,
Lee Nipper56af8cd2009-03-29 15:50:50 +0800905 struct talitos_edesc *edesc,
Kim Phillips9c4a7962008-06-23 19:50:15 +0800906 struct aead_request *areq)
907{
908 unmap_single_talitos_ptr(dev, &edesc->desc.ptr[6], DMA_FROM_DEVICE);
909 unmap_single_talitos_ptr(dev, &edesc->desc.ptr[3], DMA_TO_DEVICE);
910 unmap_single_talitos_ptr(dev, &edesc->desc.ptr[2], DMA_TO_DEVICE);
911 unmap_single_talitos_ptr(dev, &edesc->desc.ptr[0], DMA_TO_DEVICE);
912
Lee Nipper4de9d0b2009-03-29 15:52:32 +0800913 talitos_sg_unmap(dev, edesc, areq->src, areq->dst);
Kim Phillips9c4a7962008-06-23 19:50:15 +0800914
915 if (edesc->dma_len)
916 dma_unmap_single(dev, edesc->dma_link_tbl, edesc->dma_len,
917 DMA_BIDIRECTIONAL);
918}
919
920/*
921 * ipsec_esp descriptor callbacks
922 */
923static void ipsec_esp_encrypt_done(struct device *dev,
924 struct talitos_desc *desc, void *context,
925 int err)
926{
927 struct aead_request *areq = context;
Kim Phillips9c4a7962008-06-23 19:50:15 +0800928 struct crypto_aead *authenc = crypto_aead_reqtfm(areq);
Herbert Xuaeb4c132015-07-30 17:53:22 +0800929 unsigned int authsize = crypto_aead_authsize(authenc);
Kim Phillips19bbbc62009-03-29 15:53:59 +0800930 struct talitos_edesc *edesc;
Kim Phillips9c4a7962008-06-23 19:50:15 +0800931 struct scatterlist *sg;
932 void *icvdata;
933
Kim Phillips19bbbc62009-03-29 15:53:59 +0800934 edesc = container_of(desc, struct talitos_edesc, desc);
935
Kim Phillips9c4a7962008-06-23 19:50:15 +0800936 ipsec_esp_unmap(dev, edesc, areq);
937
938 /* copy the generated ICV to dst */
Herbert Xuaeb4c132015-07-30 17:53:22 +0800939 if (edesc->icv_ool) {
Kim Phillips9c4a7962008-06-23 19:50:15 +0800940 icvdata = &edesc->link_tbl[edesc->src_nents +
Herbert Xuaeb4c132015-07-30 17:53:22 +0800941 edesc->dst_nents + 2];
Kim Phillips9c4a7962008-06-23 19:50:15 +0800942 sg = sg_last(areq->dst, edesc->dst_nents);
Herbert Xuaeb4c132015-07-30 17:53:22 +0800943 memcpy((char *)sg_virt(sg) + sg->length - authsize,
944 icvdata, authsize);
Kim Phillips9c4a7962008-06-23 19:50:15 +0800945 }
946
947 kfree(edesc);
948
949 aead_request_complete(areq, err);
950}
951
Kim Phillipsfe5720e2008-10-12 20:33:14 +0800952static void ipsec_esp_decrypt_swauth_done(struct device *dev,
Kim Phillipse938e462009-03-29 15:53:23 +0800953 struct talitos_desc *desc,
954 void *context, int err)
Kim Phillips9c4a7962008-06-23 19:50:15 +0800955{
956 struct aead_request *req = context;
Kim Phillips9c4a7962008-06-23 19:50:15 +0800957 struct crypto_aead *authenc = crypto_aead_reqtfm(req);
Herbert Xuaeb4c132015-07-30 17:53:22 +0800958 unsigned int authsize = crypto_aead_authsize(authenc);
Kim Phillips19bbbc62009-03-29 15:53:59 +0800959 struct talitos_edesc *edesc;
Kim Phillips9c4a7962008-06-23 19:50:15 +0800960 struct scatterlist *sg;
Herbert Xuaeb4c132015-07-30 17:53:22 +0800961 char *oicv, *icv;
Kim Phillips9c4a7962008-06-23 19:50:15 +0800962
Kim Phillips19bbbc62009-03-29 15:53:59 +0800963 edesc = container_of(desc, struct talitos_edesc, desc);
964
Kim Phillips9c4a7962008-06-23 19:50:15 +0800965 ipsec_esp_unmap(dev, edesc, req);
966
967 if (!err) {
968 /* auth check */
Kim Phillips9c4a7962008-06-23 19:50:15 +0800969 sg = sg_last(req->dst, edesc->dst_nents ? : 1);
Herbert Xuaeb4c132015-07-30 17:53:22 +0800970 icv = (char *)sg_virt(sg) + sg->length - authsize;
971
972 if (edesc->dma_len) {
973 oicv = (char *)&edesc->link_tbl[edesc->src_nents +
974 edesc->dst_nents + 2];
975 if (edesc->icv_ool)
976 icv = oicv + authsize;
977 } else
978 oicv = (char *)&edesc->link_tbl[0];
979
David Gstir79960942015-11-15 17:14:42 +0100980 err = crypto_memneq(oicv, icv, authsize) ? -EBADMSG : 0;
Kim Phillips9c4a7962008-06-23 19:50:15 +0800981 }
982
983 kfree(edesc);
984
985 aead_request_complete(req, err);
986}
987
Kim Phillipsfe5720e2008-10-12 20:33:14 +0800988static void ipsec_esp_decrypt_hwauth_done(struct device *dev,
Kim Phillipse938e462009-03-29 15:53:23 +0800989 struct talitos_desc *desc,
990 void *context, int err)
Kim Phillipsfe5720e2008-10-12 20:33:14 +0800991{
992 struct aead_request *req = context;
Kim Phillips19bbbc62009-03-29 15:53:59 +0800993 struct talitos_edesc *edesc;
994
995 edesc = container_of(desc, struct talitos_edesc, desc);
Kim Phillipsfe5720e2008-10-12 20:33:14 +0800996
997 ipsec_esp_unmap(dev, edesc, req);
998
999 /* check ICV auth status */
Kim Phillipse938e462009-03-29 15:53:23 +08001000 if (!err && ((desc->hdr_lo & DESC_HDR_LO_ICCR1_MASK) !=
1001 DESC_HDR_LO_ICCR1_PASS))
1002 err = -EBADMSG;
Kim Phillipsfe5720e2008-10-12 20:33:14 +08001003
1004 kfree(edesc);
1005
1006 aead_request_complete(req, err);
1007}
1008
Kim Phillips9c4a7962008-06-23 19:50:15 +08001009/*
1010 * convert scatterlist to SEC h/w link table format
1011 * stop at cryptlen bytes
1012 */
Herbert Xuaeb4c132015-07-30 17:53:22 +08001013static int sg_to_link_tbl_offset(struct scatterlist *sg, int sg_count,
1014 unsigned int offset, int cryptlen,
1015 struct talitos_ptr *link_tbl_ptr)
Kim Phillips9c4a7962008-06-23 19:50:15 +08001016{
Lee Nipper70bcaca2008-07-03 19:08:46 +08001017 int n_sg = sg_count;
Herbert Xuaeb4c132015-07-30 17:53:22 +08001018 int count = 0;
Lee Nipper70bcaca2008-07-03 19:08:46 +08001019
Herbert Xuaeb4c132015-07-30 17:53:22 +08001020 while (cryptlen && sg && n_sg--) {
1021 unsigned int len = sg_dma_len(sg);
1022
1023 if (offset >= len) {
1024 offset -= len;
1025 goto next;
1026 }
1027
1028 len -= offset;
1029
1030 if (len > cryptlen)
1031 len = cryptlen;
1032
1033 to_talitos_ptr(link_tbl_ptr + count,
1034 sg_dma_address(sg) + offset, 0);
1035 link_tbl_ptr[count].len = cpu_to_be16(len);
1036 link_tbl_ptr[count].j_extent = 0;
1037 count++;
1038 cryptlen -= len;
1039 offset = 0;
1040
1041next:
Cristian Stoica5be4d4c2015-01-20 10:06:16 +02001042 sg = sg_next(sg);
Kim Phillips9c4a7962008-06-23 19:50:15 +08001043 }
1044
Kim Phillips9c4a7962008-06-23 19:50:15 +08001045 /* tag end of link table */
Herbert Xuaeb4c132015-07-30 17:53:22 +08001046 if (count > 0)
1047 link_tbl_ptr[count - 1].j_extent = DESC_PTR_LNKTBL_RETURN;
Lee Nipper70bcaca2008-07-03 19:08:46 +08001048
Herbert Xuaeb4c132015-07-30 17:53:22 +08001049 return count;
1050}
1051
1052static inline int sg_to_link_tbl(struct scatterlist *sg, int sg_count,
1053 int cryptlen,
1054 struct talitos_ptr *link_tbl_ptr)
1055{
1056 return sg_to_link_tbl_offset(sg, sg_count, 0, cryptlen,
1057 link_tbl_ptr);
Kim Phillips9c4a7962008-06-23 19:50:15 +08001058}
1059
1060/*
1061 * fill in and submit ipsec_esp descriptor
1062 */
Lee Nipper56af8cd2009-03-29 15:50:50 +08001063static int ipsec_esp(struct talitos_edesc *edesc, struct aead_request *areq,
Herbert Xuaeb4c132015-07-30 17:53:22 +08001064 void (*callback)(struct device *dev,
1065 struct talitos_desc *desc,
1066 void *context, int error))
Kim Phillips9c4a7962008-06-23 19:50:15 +08001067{
1068 struct crypto_aead *aead = crypto_aead_reqtfm(areq);
Herbert Xuaeb4c132015-07-30 17:53:22 +08001069 unsigned int authsize = crypto_aead_authsize(aead);
Kim Phillips9c4a7962008-06-23 19:50:15 +08001070 struct talitos_ctx *ctx = crypto_aead_ctx(aead);
1071 struct device *dev = ctx->dev;
1072 struct talitos_desc *desc = &edesc->desc;
1073 unsigned int cryptlen = areq->cryptlen;
Kim Phillipse41256f2009-08-13 11:49:06 +10001074 unsigned int ivsize = crypto_aead_ivsize(aead);
Herbert Xuaeb4c132015-07-30 17:53:22 +08001075 int tbl_off = 0;
Kim Phillipsfa86a262008-07-17 20:20:06 +08001076 int sg_count, ret;
Kim Phillipsfe5720e2008-10-12 20:33:14 +08001077 int sg_link_tbl_len;
Kim Phillips9c4a7962008-06-23 19:50:15 +08001078
1079 /* hmac key */
1080 map_single_talitos_ptr(dev, &desc->ptr[0], ctx->authkeylen, &ctx->key,
LEROY Christophea2b35aa2015-04-17 16:31:57 +02001081 DMA_TO_DEVICE);
Horia Geanta79fd31d2012-08-02 17:16:40 +03001082
LABBE Corentinb8a011d2015-09-23 13:55:25 +02001083 sg_count = dma_map_sg(dev, areq->src, edesc->src_nents ?: 1,
1084 (areq->src == areq->dst) ? DMA_BIDIRECTIONAL
1085 : DMA_TO_DEVICE);
Herbert Xuaeb4c132015-07-30 17:53:22 +08001086
Kim Phillips9c4a7962008-06-23 19:50:15 +08001087 /* hmac data */
Herbert Xuaeb4c132015-07-30 17:53:22 +08001088 desc->ptr[1].len = cpu_to_be16(areq->assoclen);
1089 if (sg_count > 1 &&
1090 (ret = sg_to_link_tbl_offset(areq->src, sg_count, 0,
1091 areq->assoclen,
1092 &edesc->link_tbl[tbl_off])) > 1) {
1093 tbl_off += ret;
Horia Geanta79fd31d2012-08-02 17:16:40 +03001094
1095 to_talitos_ptr(&desc->ptr[1], edesc->dma_link_tbl + tbl_off *
LEROY Christophe922f9dc2015-04-17 16:32:07 +02001096 sizeof(struct talitos_ptr), 0);
Horia Geanta79fd31d2012-08-02 17:16:40 +03001097 desc->ptr[1].j_extent = DESC_PTR_LNKTBL_JUMP;
1098
Horia Geanta79fd31d2012-08-02 17:16:40 +03001099 dma_sync_single_for_device(dev, edesc->dma_link_tbl,
1100 edesc->dma_len, DMA_BIDIRECTIONAL);
1101 } else {
Herbert Xuaeb4c132015-07-30 17:53:22 +08001102 to_talitos_ptr(&desc->ptr[1], sg_dma_address(areq->src), 0);
Horia Geanta79fd31d2012-08-02 17:16:40 +03001103 desc->ptr[1].j_extent = 0;
1104 }
1105
Kim Phillips9c4a7962008-06-23 19:50:15 +08001106 /* cipher iv */
LEROY Christophe922f9dc2015-04-17 16:32:07 +02001107 to_talitos_ptr(&desc->ptr[2], edesc->iv_dma, 0);
Horia Geanta79fd31d2012-08-02 17:16:40 +03001108 desc->ptr[2].len = cpu_to_be16(ivsize);
1109 desc->ptr[2].j_extent = 0;
Kim Phillips9c4a7962008-06-23 19:50:15 +08001110
1111 /* cipher key */
1112 map_single_talitos_ptr(dev, &desc->ptr[3], ctx->enckeylen,
LEROY Christophea2b35aa2015-04-17 16:31:57 +02001113 (char *)&ctx->key + ctx->authkeylen,
Kim Phillips9c4a7962008-06-23 19:50:15 +08001114 DMA_TO_DEVICE);
1115
1116 /*
1117 * cipher in
1118 * map and adjust cipher len to aead request cryptlen.
1119 * extent is bytes of HMAC postpended to ciphertext,
1120 * typically 12 for ipsec
1121 */
1122 desc->ptr[4].len = cpu_to_be16(cryptlen);
1123 desc->ptr[4].j_extent = authsize;
1124
Herbert Xuaeb4c132015-07-30 17:53:22 +08001125 sg_link_tbl_len = cryptlen;
1126 if (edesc->desc.hdr & DESC_HDR_MODE1_MDEU_CICV)
1127 sg_link_tbl_len += authsize;
Kim Phillips9c4a7962008-06-23 19:50:15 +08001128
Herbert Xuaeb4c132015-07-30 17:53:22 +08001129 if (sg_count > 1 &&
1130 (ret = sg_to_link_tbl_offset(areq->src, sg_count, areq->assoclen,
1131 sg_link_tbl_len,
1132 &edesc->link_tbl[tbl_off])) > 1) {
1133 tbl_off += ret;
1134 desc->ptr[4].j_extent |= DESC_PTR_LNKTBL_JUMP;
1135 to_talitos_ptr(&desc->ptr[4], edesc->dma_link_tbl +
1136 tbl_off *
1137 sizeof(struct talitos_ptr), 0);
1138 dma_sync_single_for_device(dev, edesc->dma_link_tbl,
1139 edesc->dma_len,
1140 DMA_BIDIRECTIONAL);
1141 } else
LEROY Christophe922f9dc2015-04-17 16:32:07 +02001142 to_talitos_ptr(&desc->ptr[4], sg_dma_address(areq->src), 0);
Kim Phillips9c4a7962008-06-23 19:50:15 +08001143
1144 /* cipher out */
1145 desc->ptr[5].len = cpu_to_be16(cryptlen);
1146 desc->ptr[5].j_extent = authsize;
1147
Kim Phillipse938e462009-03-29 15:53:23 +08001148 if (areq->src != areq->dst)
LABBE Corentinb8a011d2015-09-23 13:55:25 +02001149 sg_count = dma_map_sg(dev, areq->dst, edesc->dst_nents ? : 1,
1150 DMA_FROM_DEVICE);
Kim Phillips9c4a7962008-06-23 19:50:15 +08001151
Herbert Xuaeb4c132015-07-30 17:53:22 +08001152 edesc->icv_ool = false;
1153
1154 if (sg_count > 1 &&
1155 (sg_count = sg_to_link_tbl_offset(areq->dst, sg_count,
1156 areq->assoclen, cryptlen,
1157 &edesc->link_tbl[tbl_off])) >
1158 1) {
Horia Geanta79fd31d2012-08-02 17:16:40 +03001159 struct talitos_ptr *tbl_ptr = &edesc->link_tbl[tbl_off];
Kim Phillips9c4a7962008-06-23 19:50:15 +08001160
Kim Phillips81eb0242009-08-13 11:51:51 +10001161 to_talitos_ptr(&desc->ptr[5], edesc->dma_link_tbl +
LEROY Christophe922f9dc2015-04-17 16:32:07 +02001162 tbl_off * sizeof(struct talitos_ptr), 0);
Kim Phillipsfe5720e2008-10-12 20:33:14 +08001163
Lee Nipperf3c85bc2008-07-30 16:26:57 +08001164 /* Add an entry to the link table for ICV data */
Horia Geanta79fd31d2012-08-02 17:16:40 +03001165 tbl_ptr += sg_count - 1;
1166 tbl_ptr->j_extent = 0;
1167 tbl_ptr++;
1168 tbl_ptr->j_extent = DESC_PTR_LNKTBL_RETURN;
1169 tbl_ptr->len = cpu_to_be16(authsize);
Kim Phillips9c4a7962008-06-23 19:50:15 +08001170
1171 /* icv data follows link tables */
Horia Geanta79fd31d2012-08-02 17:16:40 +03001172 to_talitos_ptr(tbl_ptr, edesc->dma_link_tbl +
Herbert Xuaeb4c132015-07-30 17:53:22 +08001173 (edesc->src_nents + edesc->dst_nents +
1174 2) * sizeof(struct talitos_ptr) +
1175 authsize, 0);
Kim Phillips9c4a7962008-06-23 19:50:15 +08001176 desc->ptr[5].j_extent |= DESC_PTR_LNKTBL_JUMP;
1177 dma_sync_single_for_device(ctx->dev, edesc->dma_link_tbl,
1178 edesc->dma_len, DMA_BIDIRECTIONAL);
Herbert Xuaeb4c132015-07-30 17:53:22 +08001179
1180 edesc->icv_ool = true;
1181 } else
1182 to_talitos_ptr(&desc->ptr[5], sg_dma_address(areq->dst), 0);
Kim Phillips9c4a7962008-06-23 19:50:15 +08001183
1184 /* iv out */
LEROY Christophea2b35aa2015-04-17 16:31:57 +02001185 map_single_talitos_ptr(dev, &desc->ptr[6], ivsize, ctx->iv,
Kim Phillips9c4a7962008-06-23 19:50:15 +08001186 DMA_FROM_DEVICE);
1187
Kim Phillips5228f0f2011-07-15 11:21:38 +08001188 ret = talitos_submit(dev, ctx->ch, desc, callback, areq);
Kim Phillipsfa86a262008-07-17 20:20:06 +08001189 if (ret != -EINPROGRESS) {
1190 ipsec_esp_unmap(dev, edesc, areq);
1191 kfree(edesc);
1192 }
1193 return ret;
Kim Phillips9c4a7962008-06-23 19:50:15 +08001194}
1195
Kim Phillips9c4a7962008-06-23 19:50:15 +08001196/*
Lee Nipper56af8cd2009-03-29 15:50:50 +08001197 * allocate and map the extended descriptor
Kim Phillips9c4a7962008-06-23 19:50:15 +08001198 */
Lee Nipper4de9d0b2009-03-29 15:52:32 +08001199static struct talitos_edesc *talitos_edesc_alloc(struct device *dev,
1200 struct scatterlist *src,
1201 struct scatterlist *dst,
Horia Geanta79fd31d2012-08-02 17:16:40 +03001202 u8 *iv,
1203 unsigned int assoclen,
Lee Nipper4de9d0b2009-03-29 15:52:32 +08001204 unsigned int cryptlen,
1205 unsigned int authsize,
Horia Geanta79fd31d2012-08-02 17:16:40 +03001206 unsigned int ivsize,
Lee Nipper4de9d0b2009-03-29 15:52:32 +08001207 int icv_stashing,
Horia Geanta62293a32013-11-28 15:11:17 +02001208 u32 cryptoflags,
1209 bool encrypt)
Kim Phillips9c4a7962008-06-23 19:50:15 +08001210{
Lee Nipper56af8cd2009-03-29 15:50:50 +08001211 struct talitos_edesc *edesc;
Herbert Xuaeb4c132015-07-30 17:53:22 +08001212 int src_nents, dst_nents, alloc_len, dma_len;
Horia Geanta79fd31d2012-08-02 17:16:40 +03001213 dma_addr_t iv_dma = 0;
Lee Nipper4de9d0b2009-03-29 15:52:32 +08001214 gfp_t flags = cryptoflags & CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL :
Kim Phillips586725f2008-07-17 20:19:18 +08001215 GFP_ATOMIC;
LEROY Christophe6f65f6a2015-04-17 16:32:15 +02001216 struct talitos_private *priv = dev_get_drvdata(dev);
1217 bool is_sec1 = has_ftr_sec1(priv);
1218 int max_len = is_sec1 ? TALITOS1_MAX_DATA_LEN : TALITOS2_MAX_DATA_LEN;
LABBE Corentin8e409fe2015-11-04 21:13:34 +01001219 void *err;
Kim Phillips9c4a7962008-06-23 19:50:15 +08001220
LEROY Christophe6f65f6a2015-04-17 16:32:15 +02001221 if (cryptlen + authsize > max_len) {
Lee Nipper4de9d0b2009-03-29 15:52:32 +08001222 dev_err(dev, "length exceeds h/w max limit\n");
Kim Phillips9c4a7962008-06-23 19:50:15 +08001223 return ERR_PTR(-EINVAL);
1224 }
1225
Horia Geanta935e99a2013-11-19 14:57:49 +02001226 if (ivsize)
Horia Geanta79fd31d2012-08-02 17:16:40 +03001227 iv_dma = dma_map_single(dev, iv, ivsize, DMA_TO_DEVICE);
1228
Horia Geanta62293a32013-11-28 15:11:17 +02001229 if (!dst || dst == src) {
LABBE Corentinb8a011d2015-09-23 13:55:25 +02001230 src_nents = sg_nents_for_len(src,
1231 assoclen + cryptlen + authsize);
LABBE Corentin8e409fe2015-11-04 21:13:34 +01001232 if (src_nents < 0) {
1233 dev_err(dev, "Invalid number of src SG.\n");
1234 err = ERR_PTR(-EINVAL);
1235 goto error_sg;
1236 }
Horia Geanta62293a32013-11-28 15:11:17 +02001237 src_nents = (src_nents == 1) ? 0 : src_nents;
1238 dst_nents = dst ? src_nents : 0;
1239 } else { /* dst && dst != src*/
LABBE Corentinb8a011d2015-09-23 13:55:25 +02001240 src_nents = sg_nents_for_len(src, assoclen + cryptlen +
1241 (encrypt ? 0 : authsize));
LABBE Corentin8e409fe2015-11-04 21:13:34 +01001242 if (src_nents < 0) {
1243 dev_err(dev, "Invalid number of src SG.\n");
1244 err = ERR_PTR(-EINVAL);
1245 goto error_sg;
1246 }
Horia Geanta62293a32013-11-28 15:11:17 +02001247 src_nents = (src_nents == 1) ? 0 : src_nents;
LABBE Corentinb8a011d2015-09-23 13:55:25 +02001248 dst_nents = sg_nents_for_len(dst, assoclen + cryptlen +
1249 (encrypt ? authsize : 0));
LABBE Corentin8e409fe2015-11-04 21:13:34 +01001250 if (dst_nents < 0) {
1251 dev_err(dev, "Invalid number of dst SG.\n");
1252 err = ERR_PTR(-EINVAL);
1253 goto error_sg;
1254 }
Horia Geanta62293a32013-11-28 15:11:17 +02001255 dst_nents = (dst_nents == 1) ? 0 : dst_nents;
Kim Phillips9c4a7962008-06-23 19:50:15 +08001256 }
1257
1258 /*
1259 * allocate space for base edesc plus the link tables,
Herbert Xuaeb4c132015-07-30 17:53:22 +08001260 * allowing for two separate entries for AD and generated ICV (+ 2),
1261 * and space for two sets of ICVs (stashed and generated)
Kim Phillips9c4a7962008-06-23 19:50:15 +08001262 */
Lee Nipper56af8cd2009-03-29 15:50:50 +08001263 alloc_len = sizeof(struct talitos_edesc);
Herbert Xuaeb4c132015-07-30 17:53:22 +08001264 if (src_nents || dst_nents) {
LEROY Christophe6f65f6a2015-04-17 16:32:15 +02001265 if (is_sec1)
Dan Carpenter608f37d2015-05-11 13:10:09 +03001266 dma_len = (src_nents ? cryptlen : 0) +
1267 (dst_nents ? cryptlen : 0);
LEROY Christophe6f65f6a2015-04-17 16:32:15 +02001268 else
Herbert Xuaeb4c132015-07-30 17:53:22 +08001269 dma_len = (src_nents + dst_nents + 2) *
1270 sizeof(struct talitos_ptr) + authsize * 2;
Kim Phillips9c4a7962008-06-23 19:50:15 +08001271 alloc_len += dma_len;
1272 } else {
1273 dma_len = 0;
Lee Nipper4de9d0b2009-03-29 15:52:32 +08001274 alloc_len += icv_stashing ? authsize : 0;
Kim Phillips9c4a7962008-06-23 19:50:15 +08001275 }
1276
Kim Phillips586725f2008-07-17 20:19:18 +08001277 edesc = kmalloc(alloc_len, GFP_DMA | flags);
Kim Phillips9c4a7962008-06-23 19:50:15 +08001278 if (!edesc) {
Lee Nipper4de9d0b2009-03-29 15:52:32 +08001279 dev_err(dev, "could not allocate edescriptor\n");
LABBE Corentin8e409fe2015-11-04 21:13:34 +01001280 err = ERR_PTR(-ENOMEM);
1281 goto error_sg;
Kim Phillips9c4a7962008-06-23 19:50:15 +08001282 }
1283
1284 edesc->src_nents = src_nents;
1285 edesc->dst_nents = dst_nents;
Horia Geanta79fd31d2012-08-02 17:16:40 +03001286 edesc->iv_dma = iv_dma;
Kim Phillips9c4a7962008-06-23 19:50:15 +08001287 edesc->dma_len = dma_len;
Lee Nipper497f2e62010-05-19 19:20:36 +10001288 if (dma_len)
1289 edesc->dma_link_tbl = dma_map_single(dev, &edesc->link_tbl[0],
1290 edesc->dma_len,
1291 DMA_BIDIRECTIONAL);
Kim Phillips9c4a7962008-06-23 19:50:15 +08001292
1293 return edesc;
LABBE Corentin8e409fe2015-11-04 21:13:34 +01001294error_sg:
1295 if (iv_dma)
1296 dma_unmap_single(dev, iv_dma, ivsize, DMA_TO_DEVICE);
1297 return err;
Kim Phillips9c4a7962008-06-23 19:50:15 +08001298}
1299
Horia Geanta79fd31d2012-08-02 17:16:40 +03001300static struct talitos_edesc *aead_edesc_alloc(struct aead_request *areq, u8 *iv,
Horia Geanta62293a32013-11-28 15:11:17 +02001301 int icv_stashing, bool encrypt)
Lee Nipper4de9d0b2009-03-29 15:52:32 +08001302{
1303 struct crypto_aead *authenc = crypto_aead_reqtfm(areq);
Herbert Xuaeb4c132015-07-30 17:53:22 +08001304 unsigned int authsize = crypto_aead_authsize(authenc);
Lee Nipper4de9d0b2009-03-29 15:52:32 +08001305 struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
Horia Geanta79fd31d2012-08-02 17:16:40 +03001306 unsigned int ivsize = crypto_aead_ivsize(authenc);
Lee Nipper4de9d0b2009-03-29 15:52:32 +08001307
Herbert Xuaeb4c132015-07-30 17:53:22 +08001308 return talitos_edesc_alloc(ctx->dev, areq->src, areq->dst,
Horia Geanta79fd31d2012-08-02 17:16:40 +03001309 iv, areq->assoclen, areq->cryptlen,
Herbert Xuaeb4c132015-07-30 17:53:22 +08001310 authsize, ivsize, icv_stashing,
Horia Geanta62293a32013-11-28 15:11:17 +02001311 areq->base.flags, encrypt);
Lee Nipper4de9d0b2009-03-29 15:52:32 +08001312}
1313
Lee Nipper56af8cd2009-03-29 15:50:50 +08001314static int aead_encrypt(struct aead_request *req)
Kim Phillips9c4a7962008-06-23 19:50:15 +08001315{
1316 struct crypto_aead *authenc = crypto_aead_reqtfm(req);
1317 struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
Lee Nipper56af8cd2009-03-29 15:50:50 +08001318 struct talitos_edesc *edesc;
Kim Phillips9c4a7962008-06-23 19:50:15 +08001319
1320 /* allocate extended descriptor */
Horia Geanta62293a32013-11-28 15:11:17 +02001321 edesc = aead_edesc_alloc(req, req->iv, 0, true);
Kim Phillips9c4a7962008-06-23 19:50:15 +08001322 if (IS_ERR(edesc))
1323 return PTR_ERR(edesc);
1324
1325 /* set encrypt */
Lee Nipper70bcaca2008-07-03 19:08:46 +08001326 edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_MODE0_ENCRYPT;
Kim Phillips9c4a7962008-06-23 19:50:15 +08001327
Herbert Xuaeb4c132015-07-30 17:53:22 +08001328 return ipsec_esp(edesc, req, ipsec_esp_encrypt_done);
Kim Phillips9c4a7962008-06-23 19:50:15 +08001329}
1330
Lee Nipper56af8cd2009-03-29 15:50:50 +08001331static int aead_decrypt(struct aead_request *req)
Kim Phillips9c4a7962008-06-23 19:50:15 +08001332{
1333 struct crypto_aead *authenc = crypto_aead_reqtfm(req);
Herbert Xuaeb4c132015-07-30 17:53:22 +08001334 unsigned int authsize = crypto_aead_authsize(authenc);
Kim Phillips9c4a7962008-06-23 19:50:15 +08001335 struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
Kim Phillipsfe5720e2008-10-12 20:33:14 +08001336 struct talitos_private *priv = dev_get_drvdata(ctx->dev);
Lee Nipper56af8cd2009-03-29 15:50:50 +08001337 struct talitos_edesc *edesc;
Kim Phillips9c4a7962008-06-23 19:50:15 +08001338 struct scatterlist *sg;
1339 void *icvdata;
1340
1341 req->cryptlen -= authsize;
1342
1343 /* allocate extended descriptor */
Horia Geanta62293a32013-11-28 15:11:17 +02001344 edesc = aead_edesc_alloc(req, req->iv, 1, false);
Kim Phillips9c4a7962008-06-23 19:50:15 +08001345 if (IS_ERR(edesc))
1346 return PTR_ERR(edesc);
1347
Kim Phillipsfe5720e2008-10-12 20:33:14 +08001348 if ((priv->features & TALITOS_FTR_HW_AUTH_CHECK) &&
Kim Phillipse938e462009-03-29 15:53:23 +08001349 ((!edesc->src_nents && !edesc->dst_nents) ||
1350 priv->features & TALITOS_FTR_SRC_LINK_TBL_LEN_INCLUDES_EXTENT)) {
Kim Phillips9c4a7962008-06-23 19:50:15 +08001351
Kim Phillipsfe5720e2008-10-12 20:33:14 +08001352 /* decrypt and check the ICV */
Kim Phillipse938e462009-03-29 15:53:23 +08001353 edesc->desc.hdr = ctx->desc_hdr_template |
1354 DESC_HDR_DIR_INBOUND |
Kim Phillipsfe5720e2008-10-12 20:33:14 +08001355 DESC_HDR_MODE1_MDEU_CICV;
Kim Phillips9c4a7962008-06-23 19:50:15 +08001356
Kim Phillipsfe5720e2008-10-12 20:33:14 +08001357 /* reset integrity check result bits */
1358 edesc->desc.hdr_lo = 0;
Kim Phillips9c4a7962008-06-23 19:50:15 +08001359
Herbert Xuaeb4c132015-07-30 17:53:22 +08001360 return ipsec_esp(edesc, req, ipsec_esp_decrypt_hwauth_done);
Kim Phillipsfe5720e2008-10-12 20:33:14 +08001361 }
Kim Phillipse938e462009-03-29 15:53:23 +08001362
1363 /* Have to check the ICV with software */
1364 edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_DIR_INBOUND;
1365
1366 /* stash incoming ICV for later cmp with ICV generated by the h/w */
1367 if (edesc->dma_len)
Herbert Xuaeb4c132015-07-30 17:53:22 +08001368 icvdata = (char *)&edesc->link_tbl[edesc->src_nents +
1369 edesc->dst_nents + 2];
Kim Phillipse938e462009-03-29 15:53:23 +08001370 else
1371 icvdata = &edesc->link_tbl[0];
1372
1373 sg = sg_last(req->src, edesc->src_nents ? : 1);
1374
Herbert Xuaeb4c132015-07-30 17:53:22 +08001375 memcpy(icvdata, (char *)sg_virt(sg) + sg->length - authsize, authsize);
Kim Phillipse938e462009-03-29 15:53:23 +08001376
Herbert Xuaeb4c132015-07-30 17:53:22 +08001377 return ipsec_esp(edesc, req, ipsec_esp_decrypt_swauth_done);
Kim Phillips9c4a7962008-06-23 19:50:15 +08001378}
1379
Lee Nipper4de9d0b2009-03-29 15:52:32 +08001380static int ablkcipher_setkey(struct crypto_ablkcipher *cipher,
1381 const u8 *key, unsigned int keylen)
1382{
1383 struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher);
Lee Nipper4de9d0b2009-03-29 15:52:32 +08001384
1385 memcpy(&ctx->key, key, keylen);
1386 ctx->keylen = keylen;
1387
1388 return 0;
Lee Nipper4de9d0b2009-03-29 15:52:32 +08001389}
1390
LEROY Christophe032d1972015-04-17 16:31:51 +02001391static void unmap_sg_talitos_ptr(struct device *dev, struct scatterlist *src,
1392 struct scatterlist *dst, unsigned int len,
1393 struct talitos_edesc *edesc)
1394{
LEROY Christophe6f65f6a2015-04-17 16:32:15 +02001395 struct talitos_private *priv = dev_get_drvdata(dev);
1396 bool is_sec1 = has_ftr_sec1(priv);
1397
1398 if (is_sec1) {
1399 if (!edesc->src_nents) {
1400 dma_unmap_sg(dev, src, 1,
1401 dst != src ? DMA_TO_DEVICE
1402 : DMA_BIDIRECTIONAL);
1403 }
1404 if (dst && edesc->dst_nents) {
1405 dma_sync_single_for_device(dev,
1406 edesc->dma_link_tbl + len,
1407 len, DMA_FROM_DEVICE);
1408 sg_copy_from_buffer(dst, edesc->dst_nents ? : 1,
1409 edesc->buf + len, len);
1410 } else if (dst && dst != src) {
1411 dma_unmap_sg(dev, dst, 1, DMA_FROM_DEVICE);
1412 }
1413 } else {
1414 talitos_sg_unmap(dev, edesc, src, dst);
1415 }
LEROY Christophe032d1972015-04-17 16:31:51 +02001416}
1417
Lee Nipper4de9d0b2009-03-29 15:52:32 +08001418static void common_nonsnoop_unmap(struct device *dev,
1419 struct talitos_edesc *edesc,
1420 struct ablkcipher_request *areq)
1421{
1422 unmap_single_talitos_ptr(dev, &edesc->desc.ptr[5], DMA_FROM_DEVICE);
LEROY Christophe032d1972015-04-17 16:31:51 +02001423
1424 unmap_sg_talitos_ptr(dev, areq->src, areq->dst, areq->nbytes, edesc);
Lee Nipper4de9d0b2009-03-29 15:52:32 +08001425 unmap_single_talitos_ptr(dev, &edesc->desc.ptr[2], DMA_TO_DEVICE);
1426 unmap_single_talitos_ptr(dev, &edesc->desc.ptr[1], DMA_TO_DEVICE);
1427
Lee Nipper4de9d0b2009-03-29 15:52:32 +08001428 if (edesc->dma_len)
1429 dma_unmap_single(dev, edesc->dma_link_tbl, edesc->dma_len,
1430 DMA_BIDIRECTIONAL);
1431}
1432
1433static void ablkcipher_done(struct device *dev,
1434 struct talitos_desc *desc, void *context,
1435 int err)
1436{
1437 struct ablkcipher_request *areq = context;
Kim Phillips19bbbc62009-03-29 15:53:59 +08001438 struct talitos_edesc *edesc;
1439
1440 edesc = container_of(desc, struct talitos_edesc, desc);
Lee Nipper4de9d0b2009-03-29 15:52:32 +08001441
1442 common_nonsnoop_unmap(dev, edesc, areq);
1443
1444 kfree(edesc);
1445
1446 areq->base.complete(&areq->base, err);
1447}
1448
LEROY Christophe032d1972015-04-17 16:31:51 +02001449int map_sg_in_talitos_ptr(struct device *dev, struct scatterlist *src,
1450 unsigned int len, struct talitos_edesc *edesc,
1451 enum dma_data_direction dir, struct talitos_ptr *ptr)
1452{
1453 int sg_count;
LEROY Christophe922f9dc2015-04-17 16:32:07 +02001454 struct talitos_private *priv = dev_get_drvdata(dev);
1455 bool is_sec1 = has_ftr_sec1(priv);
LEROY Christophe032d1972015-04-17 16:31:51 +02001456
LEROY Christophe922f9dc2015-04-17 16:32:07 +02001457 to_talitos_ptr_len(ptr, len, is_sec1);
LEROY Christophe032d1972015-04-17 16:31:51 +02001458
LEROY Christophe6f65f6a2015-04-17 16:32:15 +02001459 if (is_sec1) {
1460 sg_count = edesc->src_nents ? : 1;
LEROY Christophe032d1972015-04-17 16:31:51 +02001461
LEROY Christophe6f65f6a2015-04-17 16:32:15 +02001462 if (sg_count == 1) {
1463 dma_map_sg(dev, src, 1, dir);
LEROY Christophe922f9dc2015-04-17 16:32:07 +02001464 to_talitos_ptr(ptr, sg_dma_address(src), is_sec1);
LEROY Christophe6f65f6a2015-04-17 16:32:15 +02001465 } else {
1466 sg_copy_to_buffer(src, sg_count, edesc->buf, len);
1467 to_talitos_ptr(ptr, edesc->dma_link_tbl, is_sec1);
1468 dma_sync_single_for_device(dev, edesc->dma_link_tbl,
1469 len, DMA_TO_DEVICE);
1470 }
1471 } else {
1472 to_talitos_ptr_extent_clear(ptr, is_sec1);
1473
LABBE Corentinb8a011d2015-09-23 13:55:25 +02001474 sg_count = dma_map_sg(dev, src, edesc->src_nents ? : 1, dir);
LEROY Christophe6f65f6a2015-04-17 16:32:15 +02001475
1476 if (sg_count == 1) {
1477 to_talitos_ptr(ptr, sg_dma_address(src), is_sec1);
1478 } else {
1479 sg_count = sg_to_link_tbl(src, sg_count, len,
1480 &edesc->link_tbl[0]);
1481 if (sg_count > 1) {
1482 to_talitos_ptr(ptr, edesc->dma_link_tbl, 0);
1483 ptr->j_extent |= DESC_PTR_LNKTBL_JUMP;
1484 dma_sync_single_for_device(dev,
1485 edesc->dma_link_tbl,
1486 edesc->dma_len,
1487 DMA_BIDIRECTIONAL);
1488 } else {
1489 /* Only one segment now, so no link tbl needed*/
1490 to_talitos_ptr(ptr, sg_dma_address(src),
1491 is_sec1);
1492 }
LEROY Christophe032d1972015-04-17 16:31:51 +02001493 }
1494 }
1495 return sg_count;
1496}
1497
1498void map_sg_out_talitos_ptr(struct device *dev, struct scatterlist *dst,
1499 unsigned int len, struct talitos_edesc *edesc,
1500 enum dma_data_direction dir,
1501 struct talitos_ptr *ptr, int sg_count)
1502{
LEROY Christophe922f9dc2015-04-17 16:32:07 +02001503 struct talitos_private *priv = dev_get_drvdata(dev);
1504 bool is_sec1 = has_ftr_sec1(priv);
1505
LEROY Christophe032d1972015-04-17 16:31:51 +02001506 if (dir != DMA_NONE)
LABBE Corentinb8a011d2015-09-23 13:55:25 +02001507 sg_count = dma_map_sg(dev, dst, edesc->dst_nents ? : 1, dir);
LEROY Christophe032d1972015-04-17 16:31:51 +02001508
LEROY Christophe6f65f6a2015-04-17 16:32:15 +02001509 to_talitos_ptr_len(ptr, len, is_sec1);
LEROY Christophe032d1972015-04-17 16:31:51 +02001510
LEROY Christophe6f65f6a2015-04-17 16:32:15 +02001511 if (is_sec1) {
1512 if (sg_count == 1) {
1513 if (dir != DMA_NONE)
1514 dma_map_sg(dev, dst, 1, dir);
1515 to_talitos_ptr(ptr, sg_dma_address(dst), is_sec1);
1516 } else {
1517 to_talitos_ptr(ptr, edesc->dma_link_tbl + len, is_sec1);
1518 dma_sync_single_for_device(dev,
1519 edesc->dma_link_tbl + len,
1520 len, DMA_FROM_DEVICE);
1521 }
1522 } else {
1523 to_talitos_ptr_extent_clear(ptr, is_sec1);
1524
1525 if (sg_count == 1) {
1526 to_talitos_ptr(ptr, sg_dma_address(dst), is_sec1);
1527 } else {
1528 struct talitos_ptr *link_tbl_ptr =
1529 &edesc->link_tbl[edesc->src_nents + 1];
1530
1531 to_talitos_ptr(ptr, edesc->dma_link_tbl +
1532 (edesc->src_nents + 1) *
1533 sizeof(struct talitos_ptr), 0);
1534 ptr->j_extent |= DESC_PTR_LNKTBL_JUMP;
Horia Geant?42e8b0d2015-05-11 20:04:56 +03001535 sg_to_link_tbl(dst, sg_count, len, link_tbl_ptr);
LEROY Christophe6f65f6a2015-04-17 16:32:15 +02001536 dma_sync_single_for_device(dev, edesc->dma_link_tbl,
1537 edesc->dma_len,
1538 DMA_BIDIRECTIONAL);
1539 }
LEROY Christophe032d1972015-04-17 16:31:51 +02001540 }
1541}
1542
Lee Nipper4de9d0b2009-03-29 15:52:32 +08001543static int common_nonsnoop(struct talitos_edesc *edesc,
1544 struct ablkcipher_request *areq,
Lee Nipper4de9d0b2009-03-29 15:52:32 +08001545 void (*callback) (struct device *dev,
1546 struct talitos_desc *desc,
1547 void *context, int error))
1548{
1549 struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(areq);
1550 struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher);
1551 struct device *dev = ctx->dev;
1552 struct talitos_desc *desc = &edesc->desc;
1553 unsigned int cryptlen = areq->nbytes;
Horia Geanta79fd31d2012-08-02 17:16:40 +03001554 unsigned int ivsize = crypto_ablkcipher_ivsize(cipher);
Lee Nipper4de9d0b2009-03-29 15:52:32 +08001555 int sg_count, ret;
LEROY Christophe922f9dc2015-04-17 16:32:07 +02001556 struct talitos_private *priv = dev_get_drvdata(dev);
1557 bool is_sec1 = has_ftr_sec1(priv);
Lee Nipper4de9d0b2009-03-29 15:52:32 +08001558
1559 /* first DWORD empty */
LEROY Christophe2529bc32015-04-17 16:31:49 +02001560 desc->ptr[0] = zero_entry;
Lee Nipper4de9d0b2009-03-29 15:52:32 +08001561
1562 /* cipher iv */
LEROY Christophe922f9dc2015-04-17 16:32:07 +02001563 to_talitos_ptr(&desc->ptr[1], edesc->iv_dma, is_sec1);
1564 to_talitos_ptr_len(&desc->ptr[1], ivsize, is_sec1);
1565 to_talitos_ptr_extent_clear(&desc->ptr[1], is_sec1);
Lee Nipper4de9d0b2009-03-29 15:52:32 +08001566
1567 /* cipher key */
1568 map_single_talitos_ptr(dev, &desc->ptr[2], ctx->keylen,
LEROY Christophea2b35aa2015-04-17 16:31:57 +02001569 (char *)&ctx->key, DMA_TO_DEVICE);
Lee Nipper4de9d0b2009-03-29 15:52:32 +08001570
1571 /*
1572 * cipher in
1573 */
LEROY Christophe032d1972015-04-17 16:31:51 +02001574 sg_count = map_sg_in_talitos_ptr(dev, areq->src, cryptlen, edesc,
1575 (areq->src == areq->dst) ?
1576 DMA_BIDIRECTIONAL : DMA_TO_DEVICE,
1577 &desc->ptr[3]);
Lee Nipper4de9d0b2009-03-29 15:52:32 +08001578
1579 /* cipher out */
LEROY Christophe032d1972015-04-17 16:31:51 +02001580 map_sg_out_talitos_ptr(dev, areq->dst, cryptlen, edesc,
1581 (areq->src == areq->dst) ? DMA_NONE
1582 : DMA_FROM_DEVICE,
1583 &desc->ptr[4], sg_count);
Lee Nipper4de9d0b2009-03-29 15:52:32 +08001584
1585 /* iv out */
LEROY Christophea2b35aa2015-04-17 16:31:57 +02001586 map_single_talitos_ptr(dev, &desc->ptr[5], ivsize, ctx->iv,
Lee Nipper4de9d0b2009-03-29 15:52:32 +08001587 DMA_FROM_DEVICE);
1588
1589 /* last DWORD empty */
LEROY Christophe2529bc32015-04-17 16:31:49 +02001590 desc->ptr[6] = zero_entry;
Lee Nipper4de9d0b2009-03-29 15:52:32 +08001591
Kim Phillips5228f0f2011-07-15 11:21:38 +08001592 ret = talitos_submit(dev, ctx->ch, desc, callback, areq);
Lee Nipper4de9d0b2009-03-29 15:52:32 +08001593 if (ret != -EINPROGRESS) {
1594 common_nonsnoop_unmap(dev, edesc, areq);
1595 kfree(edesc);
1596 }
1597 return ret;
1598}
1599
Kim Phillipse938e462009-03-29 15:53:23 +08001600static struct talitos_edesc *ablkcipher_edesc_alloc(struct ablkcipher_request *
Horia Geanta62293a32013-11-28 15:11:17 +02001601 areq, bool encrypt)
Lee Nipper4de9d0b2009-03-29 15:52:32 +08001602{
1603 struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(areq);
1604 struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher);
Horia Geanta79fd31d2012-08-02 17:16:40 +03001605 unsigned int ivsize = crypto_ablkcipher_ivsize(cipher);
Lee Nipper4de9d0b2009-03-29 15:52:32 +08001606
Herbert Xuaeb4c132015-07-30 17:53:22 +08001607 return talitos_edesc_alloc(ctx->dev, areq->src, areq->dst,
Horia Geanta79fd31d2012-08-02 17:16:40 +03001608 areq->info, 0, areq->nbytes, 0, ivsize, 0,
Horia Geanta62293a32013-11-28 15:11:17 +02001609 areq->base.flags, encrypt);
Lee Nipper4de9d0b2009-03-29 15:52:32 +08001610}
1611
1612static int ablkcipher_encrypt(struct ablkcipher_request *areq)
1613{
1614 struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(areq);
1615 struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher);
1616 struct talitos_edesc *edesc;
1617
1618 /* allocate extended descriptor */
Horia Geanta62293a32013-11-28 15:11:17 +02001619 edesc = ablkcipher_edesc_alloc(areq, true);
Lee Nipper4de9d0b2009-03-29 15:52:32 +08001620 if (IS_ERR(edesc))
1621 return PTR_ERR(edesc);
1622
1623 /* set encrypt */
1624 edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_MODE0_ENCRYPT;
1625
Kim Phillipsfebec542011-07-15 11:21:39 +08001626 return common_nonsnoop(edesc, areq, ablkcipher_done);
Lee Nipper4de9d0b2009-03-29 15:52:32 +08001627}
1628
1629static int ablkcipher_decrypt(struct ablkcipher_request *areq)
1630{
1631 struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(areq);
1632 struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher);
1633 struct talitos_edesc *edesc;
1634
1635 /* allocate extended descriptor */
Horia Geanta62293a32013-11-28 15:11:17 +02001636 edesc = ablkcipher_edesc_alloc(areq, false);
Lee Nipper4de9d0b2009-03-29 15:52:32 +08001637 if (IS_ERR(edesc))
1638 return PTR_ERR(edesc);
1639
1640 edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_DIR_INBOUND;
1641
Kim Phillipsfebec542011-07-15 11:21:39 +08001642 return common_nonsnoop(edesc, areq, ablkcipher_done);
Lee Nipper4de9d0b2009-03-29 15:52:32 +08001643}
1644
Lee Nipper497f2e62010-05-19 19:20:36 +10001645static void common_nonsnoop_hash_unmap(struct device *dev,
1646 struct talitos_edesc *edesc,
1647 struct ahash_request *areq)
1648{
1649 struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
LEROY Christophe922f9dc2015-04-17 16:32:07 +02001650 struct talitos_private *priv = dev_get_drvdata(dev);
1651 bool is_sec1 = has_ftr_sec1(priv);
Lee Nipper497f2e62010-05-19 19:20:36 +10001652
1653 unmap_single_talitos_ptr(dev, &edesc->desc.ptr[5], DMA_FROM_DEVICE);
1654
LEROY Christophe032d1972015-04-17 16:31:51 +02001655 unmap_sg_talitos_ptr(dev, req_ctx->psrc, NULL, 0, edesc);
1656
Lee Nipper497f2e62010-05-19 19:20:36 +10001657 /* When using hashctx-in, must unmap it. */
LEROY Christophe922f9dc2015-04-17 16:32:07 +02001658 if (from_talitos_ptr_len(&edesc->desc.ptr[1], is_sec1))
Lee Nipper497f2e62010-05-19 19:20:36 +10001659 unmap_single_talitos_ptr(dev, &edesc->desc.ptr[1],
1660 DMA_TO_DEVICE);
1661
LEROY Christophe922f9dc2015-04-17 16:32:07 +02001662 if (from_talitos_ptr_len(&edesc->desc.ptr[2], is_sec1))
Lee Nipper497f2e62010-05-19 19:20:36 +10001663 unmap_single_talitos_ptr(dev, &edesc->desc.ptr[2],
1664 DMA_TO_DEVICE);
1665
Lee Nipper497f2e62010-05-19 19:20:36 +10001666 if (edesc->dma_len)
1667 dma_unmap_single(dev, edesc->dma_link_tbl, edesc->dma_len,
1668 DMA_BIDIRECTIONAL);
1669
1670}
1671
1672static void ahash_done(struct device *dev,
1673 struct talitos_desc *desc, void *context,
1674 int err)
1675{
1676 struct ahash_request *areq = context;
1677 struct talitos_edesc *edesc =
1678 container_of(desc, struct talitos_edesc, desc);
1679 struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
1680
1681 if (!req_ctx->last && req_ctx->to_hash_later) {
1682 /* Position any partial block for next update/final/finup */
1683 memcpy(req_ctx->buf, req_ctx->bufnext, req_ctx->to_hash_later);
Lee Nipper5e833bc2010-06-16 15:29:15 +10001684 req_ctx->nbuf = req_ctx->to_hash_later;
Lee Nipper497f2e62010-05-19 19:20:36 +10001685 }
1686 common_nonsnoop_hash_unmap(dev, edesc, areq);
1687
1688 kfree(edesc);
1689
1690 areq->base.complete(&areq->base, err);
1691}
1692
LEROY Christophe2d029052015-04-17 16:32:18 +02001693/*
1694 * SEC1 doesn't like hashing of 0 sized message, so we do the padding
1695 * ourself and submit a padded block
1696 */
1697void talitos_handle_buggy_hash(struct talitos_ctx *ctx,
1698 struct talitos_edesc *edesc,
1699 struct talitos_ptr *ptr)
1700{
1701 static u8 padded_hash[64] = {
1702 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1703 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1704 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1705 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1706 };
1707
1708 pr_err_once("Bug in SEC1, padding ourself\n");
1709 edesc->desc.hdr &= ~DESC_HDR_MODE0_MDEU_PAD;
1710 map_single_talitos_ptr(ctx->dev, ptr, sizeof(padded_hash),
1711 (char *)padded_hash, DMA_TO_DEVICE);
1712}
1713
Lee Nipper497f2e62010-05-19 19:20:36 +10001714static int common_nonsnoop_hash(struct talitos_edesc *edesc,
1715 struct ahash_request *areq, unsigned int length,
1716 void (*callback) (struct device *dev,
1717 struct talitos_desc *desc,
1718 void *context, int error))
1719{
1720 struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
1721 struct talitos_ctx *ctx = crypto_ahash_ctx(tfm);
1722 struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
1723 struct device *dev = ctx->dev;
1724 struct talitos_desc *desc = &edesc->desc;
LEROY Christophe032d1972015-04-17 16:31:51 +02001725 int ret;
LEROY Christophe922f9dc2015-04-17 16:32:07 +02001726 struct talitos_private *priv = dev_get_drvdata(dev);
1727 bool is_sec1 = has_ftr_sec1(priv);
Lee Nipper497f2e62010-05-19 19:20:36 +10001728
1729 /* first DWORD empty */
1730 desc->ptr[0] = zero_entry;
1731
Kim Phillips60f208d2010-05-19 19:21:53 +10001732 /* hash context in */
1733 if (!req_ctx->first || req_ctx->swinit) {
Lee Nipper497f2e62010-05-19 19:20:36 +10001734 map_single_talitos_ptr(dev, &desc->ptr[1],
1735 req_ctx->hw_context_size,
LEROY Christophea2b35aa2015-04-17 16:31:57 +02001736 (char *)req_ctx->hw_context,
Lee Nipper497f2e62010-05-19 19:20:36 +10001737 DMA_TO_DEVICE);
Kim Phillips60f208d2010-05-19 19:21:53 +10001738 req_ctx->swinit = 0;
Lee Nipper497f2e62010-05-19 19:20:36 +10001739 } else {
1740 desc->ptr[1] = zero_entry;
1741 /* Indicate next op is not the first. */
1742 req_ctx->first = 0;
1743 }
1744
1745 /* HMAC key */
1746 if (ctx->keylen)
1747 map_single_talitos_ptr(dev, &desc->ptr[2], ctx->keylen,
LEROY Christophea2b35aa2015-04-17 16:31:57 +02001748 (char *)&ctx->key, DMA_TO_DEVICE);
Lee Nipper497f2e62010-05-19 19:20:36 +10001749 else
1750 desc->ptr[2] = zero_entry;
1751
1752 /*
1753 * data in
1754 */
LEROY Christophe032d1972015-04-17 16:31:51 +02001755 map_sg_in_talitos_ptr(dev, req_ctx->psrc, length, edesc,
1756 DMA_TO_DEVICE, &desc->ptr[3]);
Lee Nipper497f2e62010-05-19 19:20:36 +10001757
1758 /* fifth DWORD empty */
1759 desc->ptr[4] = zero_entry;
1760
1761 /* hash/HMAC out -or- hash context out */
1762 if (req_ctx->last)
1763 map_single_talitos_ptr(dev, &desc->ptr[5],
1764 crypto_ahash_digestsize(tfm),
LEROY Christophea2b35aa2015-04-17 16:31:57 +02001765 areq->result, DMA_FROM_DEVICE);
Lee Nipper497f2e62010-05-19 19:20:36 +10001766 else
1767 map_single_talitos_ptr(dev, &desc->ptr[5],
1768 req_ctx->hw_context_size,
LEROY Christophea2b35aa2015-04-17 16:31:57 +02001769 req_ctx->hw_context, DMA_FROM_DEVICE);
Lee Nipper497f2e62010-05-19 19:20:36 +10001770
1771 /* last DWORD empty */
1772 desc->ptr[6] = zero_entry;
1773
LEROY Christophe2d029052015-04-17 16:32:18 +02001774 if (is_sec1 && from_talitos_ptr_len(&desc->ptr[3], true) == 0)
1775 talitos_handle_buggy_hash(ctx, edesc, &desc->ptr[3]);
1776
Kim Phillips5228f0f2011-07-15 11:21:38 +08001777 ret = talitos_submit(dev, ctx->ch, desc, callback, areq);
Lee Nipper497f2e62010-05-19 19:20:36 +10001778 if (ret != -EINPROGRESS) {
1779 common_nonsnoop_hash_unmap(dev, edesc, areq);
1780 kfree(edesc);
1781 }
1782 return ret;
1783}
1784
1785static struct talitos_edesc *ahash_edesc_alloc(struct ahash_request *areq,
1786 unsigned int nbytes)
1787{
1788 struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
1789 struct talitos_ctx *ctx = crypto_ahash_ctx(tfm);
1790 struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
1791
Herbert Xuaeb4c132015-07-30 17:53:22 +08001792 return talitos_edesc_alloc(ctx->dev, req_ctx->psrc, NULL, NULL, 0,
Horia Geanta62293a32013-11-28 15:11:17 +02001793 nbytes, 0, 0, 0, areq->base.flags, false);
Lee Nipper497f2e62010-05-19 19:20:36 +10001794}
1795
1796static int ahash_init(struct ahash_request *areq)
1797{
1798 struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
1799 struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
1800
1801 /* Initialize the context */
Lee Nipper5e833bc2010-06-16 15:29:15 +10001802 req_ctx->nbuf = 0;
Kim Phillips60f208d2010-05-19 19:21:53 +10001803 req_ctx->first = 1; /* first indicates h/w must init its context */
1804 req_ctx->swinit = 0; /* assume h/w init of context */
Lee Nipper497f2e62010-05-19 19:20:36 +10001805 req_ctx->hw_context_size =
1806 (crypto_ahash_digestsize(tfm) <= SHA256_DIGEST_SIZE)
1807 ? TALITOS_MDEU_CONTEXT_SIZE_MD5_SHA1_SHA256
1808 : TALITOS_MDEU_CONTEXT_SIZE_SHA384_SHA512;
1809
1810 return 0;
1811}
1812
Kim Phillips60f208d2010-05-19 19:21:53 +10001813/*
1814 * on h/w without explicit sha224 support, we initialize h/w context
1815 * manually with sha224 constants, and tell it to run sha256.
1816 */
1817static int ahash_init_sha224_swinit(struct ahash_request *areq)
1818{
1819 struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
1820
1821 ahash_init(areq);
1822 req_ctx->swinit = 1;/* prevent h/w initting context with sha256 values*/
1823
Kim Phillipsa7524472010-09-23 15:56:38 +08001824 req_ctx->hw_context[0] = SHA224_H0;
1825 req_ctx->hw_context[1] = SHA224_H1;
1826 req_ctx->hw_context[2] = SHA224_H2;
1827 req_ctx->hw_context[3] = SHA224_H3;
1828 req_ctx->hw_context[4] = SHA224_H4;
1829 req_ctx->hw_context[5] = SHA224_H5;
1830 req_ctx->hw_context[6] = SHA224_H6;
1831 req_ctx->hw_context[7] = SHA224_H7;
Kim Phillips60f208d2010-05-19 19:21:53 +10001832
1833 /* init 64-bit count */
1834 req_ctx->hw_context[8] = 0;
1835 req_ctx->hw_context[9] = 0;
1836
1837 return 0;
1838}
1839
Lee Nipper497f2e62010-05-19 19:20:36 +10001840static int ahash_process_req(struct ahash_request *areq, unsigned int nbytes)
1841{
1842 struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
1843 struct talitos_ctx *ctx = crypto_ahash_ctx(tfm);
1844 struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
1845 struct talitos_edesc *edesc;
1846 unsigned int blocksize =
1847 crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm));
1848 unsigned int nbytes_to_hash;
1849 unsigned int to_hash_later;
Lee Nipper5e833bc2010-06-16 15:29:15 +10001850 unsigned int nsg;
LABBE Corentin8e409fe2015-11-04 21:13:34 +01001851 int nents;
Lee Nipper497f2e62010-05-19 19:20:36 +10001852
Lee Nipper5e833bc2010-06-16 15:29:15 +10001853 if (!req_ctx->last && (nbytes + req_ctx->nbuf <= blocksize)) {
1854 /* Buffer up to one whole block */
LABBE Corentin8e409fe2015-11-04 21:13:34 +01001855 nents = sg_nents_for_len(areq->src, nbytes);
1856 if (nents < 0) {
1857 dev_err(ctx->dev, "Invalid number of src SG.\n");
1858 return nents;
1859 }
1860 sg_copy_to_buffer(areq->src, nents,
Lee Nipper5e833bc2010-06-16 15:29:15 +10001861 req_ctx->buf + req_ctx->nbuf, nbytes);
1862 req_ctx->nbuf += nbytes;
Lee Nipper497f2e62010-05-19 19:20:36 +10001863 return 0;
1864 }
1865
Lee Nipper5e833bc2010-06-16 15:29:15 +10001866 /* At least (blocksize + 1) bytes are available to hash */
1867 nbytes_to_hash = nbytes + req_ctx->nbuf;
1868 to_hash_later = nbytes_to_hash & (blocksize - 1);
1869
1870 if (req_ctx->last)
1871 to_hash_later = 0;
1872 else if (to_hash_later)
1873 /* There is a partial block. Hash the full block(s) now */
1874 nbytes_to_hash -= to_hash_later;
1875 else {
1876 /* Keep one block buffered */
1877 nbytes_to_hash -= blocksize;
1878 to_hash_later = blocksize;
1879 }
1880
1881 /* Chain in any previously buffered data */
1882 if (req_ctx->nbuf) {
1883 nsg = (req_ctx->nbuf < nbytes_to_hash) ? 2 : 1;
1884 sg_init_table(req_ctx->bufsl, nsg);
1885 sg_set_buf(req_ctx->bufsl, req_ctx->buf, req_ctx->nbuf);
1886 if (nsg > 1)
Dan Williamsc56f6d12015-08-07 18:15:13 +02001887 sg_chain(req_ctx->bufsl, 2, areq->src);
Lee Nipper497f2e62010-05-19 19:20:36 +10001888 req_ctx->psrc = req_ctx->bufsl;
Lee Nipper5e833bc2010-06-16 15:29:15 +10001889 } else
Lee Nipper497f2e62010-05-19 19:20:36 +10001890 req_ctx->psrc = areq->src;
Lee Nipper497f2e62010-05-19 19:20:36 +10001891
Lee Nipper5e833bc2010-06-16 15:29:15 +10001892 if (to_hash_later) {
LABBE Corentin8e409fe2015-11-04 21:13:34 +01001893 nents = sg_nents_for_len(areq->src, nbytes);
1894 if (nents < 0) {
1895 dev_err(ctx->dev, "Invalid number of src SG.\n");
1896 return nents;
1897 }
Akinobu Mitad0525722013-07-08 16:01:55 -07001898 sg_pcopy_to_buffer(areq->src, nents,
Lee Nipper5e833bc2010-06-16 15:29:15 +10001899 req_ctx->bufnext,
1900 to_hash_later,
1901 nbytes - to_hash_later);
Lee Nipper497f2e62010-05-19 19:20:36 +10001902 }
Lee Nipper5e833bc2010-06-16 15:29:15 +10001903 req_ctx->to_hash_later = to_hash_later;
Lee Nipper497f2e62010-05-19 19:20:36 +10001904
Lee Nipper5e833bc2010-06-16 15:29:15 +10001905 /* Allocate extended descriptor */
Lee Nipper497f2e62010-05-19 19:20:36 +10001906 edesc = ahash_edesc_alloc(areq, nbytes_to_hash);
1907 if (IS_ERR(edesc))
1908 return PTR_ERR(edesc);
1909
1910 edesc->desc.hdr = ctx->desc_hdr_template;
1911
1912 /* On last one, request SEC to pad; otherwise continue */
1913 if (req_ctx->last)
1914 edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_PAD;
1915 else
1916 edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_CONT;
1917
Kim Phillips60f208d2010-05-19 19:21:53 +10001918 /* request SEC to INIT hash. */
1919 if (req_ctx->first && !req_ctx->swinit)
Lee Nipper497f2e62010-05-19 19:20:36 +10001920 edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_INIT;
1921
1922 /* When the tfm context has a keylen, it's an HMAC.
1923 * A first or last (ie. not middle) descriptor must request HMAC.
1924 */
1925 if (ctx->keylen && (req_ctx->first || req_ctx->last))
1926 edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_HMAC;
1927
1928 return common_nonsnoop_hash(edesc, areq, nbytes_to_hash,
1929 ahash_done);
1930}
1931
1932static int ahash_update(struct ahash_request *areq)
1933{
1934 struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
1935
1936 req_ctx->last = 0;
1937
1938 return ahash_process_req(areq, areq->nbytes);
1939}
1940
1941static int ahash_final(struct ahash_request *areq)
1942{
1943 struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
1944
1945 req_ctx->last = 1;
1946
1947 return ahash_process_req(areq, 0);
1948}
1949
1950static int ahash_finup(struct ahash_request *areq)
1951{
1952 struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
1953
1954 req_ctx->last = 1;
1955
1956 return ahash_process_req(areq, areq->nbytes);
1957}
1958
1959static int ahash_digest(struct ahash_request *areq)
1960{
1961 struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
Kim Phillips60f208d2010-05-19 19:21:53 +10001962 struct crypto_ahash *ahash = crypto_ahash_reqtfm(areq);
Lee Nipper497f2e62010-05-19 19:20:36 +10001963
Kim Phillips60f208d2010-05-19 19:21:53 +10001964 ahash->init(areq);
Lee Nipper497f2e62010-05-19 19:20:36 +10001965 req_ctx->last = 1;
1966
1967 return ahash_process_req(areq, areq->nbytes);
1968}
1969
Lee Nipper79b3a412011-11-21 16:13:25 +08001970struct keyhash_result {
1971 struct completion completion;
1972 int err;
1973};
1974
1975static void keyhash_complete(struct crypto_async_request *req, int err)
1976{
1977 struct keyhash_result *res = req->data;
1978
1979 if (err == -EINPROGRESS)
1980 return;
1981
1982 res->err = err;
1983 complete(&res->completion);
1984}
1985
1986static int keyhash(struct crypto_ahash *tfm, const u8 *key, unsigned int keylen,
1987 u8 *hash)
1988{
1989 struct talitos_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm));
1990
1991 struct scatterlist sg[1];
1992 struct ahash_request *req;
1993 struct keyhash_result hresult;
1994 int ret;
1995
1996 init_completion(&hresult.completion);
1997
1998 req = ahash_request_alloc(tfm, GFP_KERNEL);
1999 if (!req)
2000 return -ENOMEM;
2001
2002 /* Keep tfm keylen == 0 during hash of the long key */
2003 ctx->keylen = 0;
2004 ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
2005 keyhash_complete, &hresult);
2006
2007 sg_init_one(&sg[0], key, keylen);
2008
2009 ahash_request_set_crypt(req, sg, hash, keylen);
2010 ret = crypto_ahash_digest(req);
2011 switch (ret) {
2012 case 0:
2013 break;
2014 case -EINPROGRESS:
2015 case -EBUSY:
2016 ret = wait_for_completion_interruptible(
2017 &hresult.completion);
2018 if (!ret)
2019 ret = hresult.err;
2020 break;
2021 default:
2022 break;
2023 }
2024 ahash_request_free(req);
2025
2026 return ret;
2027}
2028
2029static int ahash_setkey(struct crypto_ahash *tfm, const u8 *key,
2030 unsigned int keylen)
2031{
2032 struct talitos_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm));
2033 unsigned int blocksize =
2034 crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm));
2035 unsigned int digestsize = crypto_ahash_digestsize(tfm);
2036 unsigned int keysize = keylen;
2037 u8 hash[SHA512_DIGEST_SIZE];
2038 int ret;
2039
2040 if (keylen <= blocksize)
2041 memcpy(ctx->key, key, keysize);
2042 else {
2043 /* Must get the hash of the long key */
2044 ret = keyhash(tfm, key, keylen, hash);
2045
2046 if (ret) {
2047 crypto_ahash_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
2048 return -EINVAL;
2049 }
2050
2051 keysize = digestsize;
2052 memcpy(ctx->key, hash, digestsize);
2053 }
2054
2055 ctx->keylen = keysize;
2056
2057 return 0;
2058}
2059
2060
Kim Phillips9c4a7962008-06-23 19:50:15 +08002061struct talitos_alg_template {
Lee Nipperd5e4aae2010-05-19 19:18:38 +10002062 u32 type;
2063 union {
2064 struct crypto_alg crypto;
Lee Nipperacbf7c622010-05-19 19:19:33 +10002065 struct ahash_alg hash;
Herbert Xuaeb4c132015-07-30 17:53:22 +08002066 struct aead_alg aead;
Lee Nipperd5e4aae2010-05-19 19:18:38 +10002067 } alg;
Kim Phillips9c4a7962008-06-23 19:50:15 +08002068 __be32 desc_hdr_template;
2069};
2070
2071static struct talitos_alg_template driver_algs[] = {
Horia Geanta991155b2013-03-20 16:31:38 +02002072 /* AEAD algorithms. These use a single-pass ipsec_esp descriptor */
Lee Nipperd5e4aae2010-05-19 19:18:38 +10002073 { .type = CRYPTO_ALG_TYPE_AEAD,
Herbert Xuaeb4c132015-07-30 17:53:22 +08002074 .alg.aead = {
2075 .base = {
2076 .cra_name = "authenc(hmac(sha1),cbc(aes))",
2077 .cra_driver_name = "authenc-hmac-sha1-"
2078 "cbc-aes-talitos",
2079 .cra_blocksize = AES_BLOCK_SIZE,
2080 .cra_flags = CRYPTO_ALG_ASYNC,
2081 },
2082 .ivsize = AES_BLOCK_SIZE,
2083 .maxauthsize = SHA1_DIGEST_SIZE,
Lee Nipper56af8cd2009-03-29 15:50:50 +08002084 },
Kim Phillips9c4a7962008-06-23 19:50:15 +08002085 .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
2086 DESC_HDR_SEL0_AESU |
2087 DESC_HDR_MODE0_AESU_CBC |
2088 DESC_HDR_SEL1_MDEUA |
2089 DESC_HDR_MODE1_MDEU_INIT |
2090 DESC_HDR_MODE1_MDEU_PAD |
2091 DESC_HDR_MODE1_MDEU_SHA1_HMAC,
Lee Nipper70bcaca2008-07-03 19:08:46 +08002092 },
Lee Nipperd5e4aae2010-05-19 19:18:38 +10002093 { .type = CRYPTO_ALG_TYPE_AEAD,
Herbert Xuaeb4c132015-07-30 17:53:22 +08002094 .alg.aead = {
2095 .base = {
2096 .cra_name = "authenc(hmac(sha1),"
2097 "cbc(des3_ede))",
2098 .cra_driver_name = "authenc-hmac-sha1-"
2099 "cbc-3des-talitos",
2100 .cra_blocksize = DES3_EDE_BLOCK_SIZE,
2101 .cra_flags = CRYPTO_ALG_ASYNC,
2102 },
2103 .ivsize = DES3_EDE_BLOCK_SIZE,
2104 .maxauthsize = SHA1_DIGEST_SIZE,
Lee Nipper56af8cd2009-03-29 15:50:50 +08002105 },
Lee Nipper70bcaca2008-07-03 19:08:46 +08002106 .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
2107 DESC_HDR_SEL0_DEU |
2108 DESC_HDR_MODE0_DEU_CBC |
2109 DESC_HDR_MODE0_DEU_3DES |
2110 DESC_HDR_SEL1_MDEUA |
2111 DESC_HDR_MODE1_MDEU_INIT |
2112 DESC_HDR_MODE1_MDEU_PAD |
2113 DESC_HDR_MODE1_MDEU_SHA1_HMAC,
Lee Nipper3952f172008-07-10 18:29:18 +08002114 },
Horia Geanta357fb602012-07-03 19:16:53 +03002115 { .type = CRYPTO_ALG_TYPE_AEAD,
Herbert Xuaeb4c132015-07-30 17:53:22 +08002116 .alg.aead = {
2117 .base = {
2118 .cra_name = "authenc(hmac(sha224),cbc(aes))",
2119 .cra_driver_name = "authenc-hmac-sha224-"
2120 "cbc-aes-talitos",
2121 .cra_blocksize = AES_BLOCK_SIZE,
2122 .cra_flags = CRYPTO_ALG_ASYNC,
2123 },
2124 .ivsize = AES_BLOCK_SIZE,
2125 .maxauthsize = SHA224_DIGEST_SIZE,
Horia Geanta357fb602012-07-03 19:16:53 +03002126 },
2127 .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
2128 DESC_HDR_SEL0_AESU |
2129 DESC_HDR_MODE0_AESU_CBC |
2130 DESC_HDR_SEL1_MDEUA |
2131 DESC_HDR_MODE1_MDEU_INIT |
2132 DESC_HDR_MODE1_MDEU_PAD |
2133 DESC_HDR_MODE1_MDEU_SHA224_HMAC,
2134 },
2135 { .type = CRYPTO_ALG_TYPE_AEAD,
Herbert Xuaeb4c132015-07-30 17:53:22 +08002136 .alg.aead = {
2137 .base = {
2138 .cra_name = "authenc(hmac(sha224),"
2139 "cbc(des3_ede))",
2140 .cra_driver_name = "authenc-hmac-sha224-"
2141 "cbc-3des-talitos",
2142 .cra_blocksize = DES3_EDE_BLOCK_SIZE,
2143 .cra_flags = CRYPTO_ALG_ASYNC,
2144 },
2145 .ivsize = DES3_EDE_BLOCK_SIZE,
2146 .maxauthsize = SHA224_DIGEST_SIZE,
Horia Geanta357fb602012-07-03 19:16:53 +03002147 },
2148 .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
2149 DESC_HDR_SEL0_DEU |
2150 DESC_HDR_MODE0_DEU_CBC |
2151 DESC_HDR_MODE0_DEU_3DES |
2152 DESC_HDR_SEL1_MDEUA |
2153 DESC_HDR_MODE1_MDEU_INIT |
2154 DESC_HDR_MODE1_MDEU_PAD |
2155 DESC_HDR_MODE1_MDEU_SHA224_HMAC,
2156 },
Lee Nipperd5e4aae2010-05-19 19:18:38 +10002157 { .type = CRYPTO_ALG_TYPE_AEAD,
Herbert Xuaeb4c132015-07-30 17:53:22 +08002158 .alg.aead = {
2159 .base = {
2160 .cra_name = "authenc(hmac(sha256),cbc(aes))",
2161 .cra_driver_name = "authenc-hmac-sha256-"
2162 "cbc-aes-talitos",
2163 .cra_blocksize = AES_BLOCK_SIZE,
2164 .cra_flags = CRYPTO_ALG_ASYNC,
2165 },
2166 .ivsize = AES_BLOCK_SIZE,
2167 .maxauthsize = SHA256_DIGEST_SIZE,
Lee Nipper56af8cd2009-03-29 15:50:50 +08002168 },
Lee Nipper3952f172008-07-10 18:29:18 +08002169 .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
2170 DESC_HDR_SEL0_AESU |
2171 DESC_HDR_MODE0_AESU_CBC |
2172 DESC_HDR_SEL1_MDEUA |
2173 DESC_HDR_MODE1_MDEU_INIT |
2174 DESC_HDR_MODE1_MDEU_PAD |
2175 DESC_HDR_MODE1_MDEU_SHA256_HMAC,
2176 },
Lee Nipperd5e4aae2010-05-19 19:18:38 +10002177 { .type = CRYPTO_ALG_TYPE_AEAD,
Herbert Xuaeb4c132015-07-30 17:53:22 +08002178 .alg.aead = {
2179 .base = {
2180 .cra_name = "authenc(hmac(sha256),"
2181 "cbc(des3_ede))",
2182 .cra_driver_name = "authenc-hmac-sha256-"
2183 "cbc-3des-talitos",
2184 .cra_blocksize = DES3_EDE_BLOCK_SIZE,
2185 .cra_flags = CRYPTO_ALG_ASYNC,
2186 },
2187 .ivsize = DES3_EDE_BLOCK_SIZE,
2188 .maxauthsize = SHA256_DIGEST_SIZE,
Lee Nipper56af8cd2009-03-29 15:50:50 +08002189 },
Lee Nipper3952f172008-07-10 18:29:18 +08002190 .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
2191 DESC_HDR_SEL0_DEU |
2192 DESC_HDR_MODE0_DEU_CBC |
2193 DESC_HDR_MODE0_DEU_3DES |
2194 DESC_HDR_SEL1_MDEUA |
2195 DESC_HDR_MODE1_MDEU_INIT |
2196 DESC_HDR_MODE1_MDEU_PAD |
2197 DESC_HDR_MODE1_MDEU_SHA256_HMAC,
2198 },
Lee Nipperd5e4aae2010-05-19 19:18:38 +10002199 { .type = CRYPTO_ALG_TYPE_AEAD,
Herbert Xuaeb4c132015-07-30 17:53:22 +08002200 .alg.aead = {
2201 .base = {
2202 .cra_name = "authenc(hmac(sha384),cbc(aes))",
2203 .cra_driver_name = "authenc-hmac-sha384-"
2204 "cbc-aes-talitos",
2205 .cra_blocksize = AES_BLOCK_SIZE,
2206 .cra_flags = CRYPTO_ALG_ASYNC,
2207 },
2208 .ivsize = AES_BLOCK_SIZE,
2209 .maxauthsize = SHA384_DIGEST_SIZE,
Horia Geanta357fb602012-07-03 19:16:53 +03002210 },
2211 .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
2212 DESC_HDR_SEL0_AESU |
2213 DESC_HDR_MODE0_AESU_CBC |
2214 DESC_HDR_SEL1_MDEUB |
2215 DESC_HDR_MODE1_MDEU_INIT |
2216 DESC_HDR_MODE1_MDEU_PAD |
2217 DESC_HDR_MODE1_MDEUB_SHA384_HMAC,
2218 },
2219 { .type = CRYPTO_ALG_TYPE_AEAD,
Herbert Xuaeb4c132015-07-30 17:53:22 +08002220 .alg.aead = {
2221 .base = {
2222 .cra_name = "authenc(hmac(sha384),"
2223 "cbc(des3_ede))",
2224 .cra_driver_name = "authenc-hmac-sha384-"
2225 "cbc-3des-talitos",
2226 .cra_blocksize = DES3_EDE_BLOCK_SIZE,
2227 .cra_flags = CRYPTO_ALG_ASYNC,
2228 },
2229 .ivsize = DES3_EDE_BLOCK_SIZE,
2230 .maxauthsize = SHA384_DIGEST_SIZE,
Horia Geanta357fb602012-07-03 19:16:53 +03002231 },
2232 .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
2233 DESC_HDR_SEL0_DEU |
2234 DESC_HDR_MODE0_DEU_CBC |
2235 DESC_HDR_MODE0_DEU_3DES |
2236 DESC_HDR_SEL1_MDEUB |
2237 DESC_HDR_MODE1_MDEU_INIT |
2238 DESC_HDR_MODE1_MDEU_PAD |
2239 DESC_HDR_MODE1_MDEUB_SHA384_HMAC,
2240 },
2241 { .type = CRYPTO_ALG_TYPE_AEAD,
Herbert Xuaeb4c132015-07-30 17:53:22 +08002242 .alg.aead = {
2243 .base = {
2244 .cra_name = "authenc(hmac(sha512),cbc(aes))",
2245 .cra_driver_name = "authenc-hmac-sha512-"
2246 "cbc-aes-talitos",
2247 .cra_blocksize = AES_BLOCK_SIZE,
2248 .cra_flags = CRYPTO_ALG_ASYNC,
2249 },
2250 .ivsize = AES_BLOCK_SIZE,
2251 .maxauthsize = SHA512_DIGEST_SIZE,
Horia Geanta357fb602012-07-03 19:16:53 +03002252 },
2253 .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
2254 DESC_HDR_SEL0_AESU |
2255 DESC_HDR_MODE0_AESU_CBC |
2256 DESC_HDR_SEL1_MDEUB |
2257 DESC_HDR_MODE1_MDEU_INIT |
2258 DESC_HDR_MODE1_MDEU_PAD |
2259 DESC_HDR_MODE1_MDEUB_SHA512_HMAC,
2260 },
2261 { .type = CRYPTO_ALG_TYPE_AEAD,
Herbert Xuaeb4c132015-07-30 17:53:22 +08002262 .alg.aead = {
2263 .base = {
2264 .cra_name = "authenc(hmac(sha512),"
2265 "cbc(des3_ede))",
2266 .cra_driver_name = "authenc-hmac-sha512-"
2267 "cbc-3des-talitos",
2268 .cra_blocksize = DES3_EDE_BLOCK_SIZE,
2269 .cra_flags = CRYPTO_ALG_ASYNC,
2270 },
2271 .ivsize = DES3_EDE_BLOCK_SIZE,
2272 .maxauthsize = SHA512_DIGEST_SIZE,
Horia Geanta357fb602012-07-03 19:16:53 +03002273 },
2274 .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
2275 DESC_HDR_SEL0_DEU |
2276 DESC_HDR_MODE0_DEU_CBC |
2277 DESC_HDR_MODE0_DEU_3DES |
2278 DESC_HDR_SEL1_MDEUB |
2279 DESC_HDR_MODE1_MDEU_INIT |
2280 DESC_HDR_MODE1_MDEU_PAD |
2281 DESC_HDR_MODE1_MDEUB_SHA512_HMAC,
2282 },
2283 { .type = CRYPTO_ALG_TYPE_AEAD,
Herbert Xuaeb4c132015-07-30 17:53:22 +08002284 .alg.aead = {
2285 .base = {
2286 .cra_name = "authenc(hmac(md5),cbc(aes))",
2287 .cra_driver_name = "authenc-hmac-md5-"
2288 "cbc-aes-talitos",
2289 .cra_blocksize = AES_BLOCK_SIZE,
2290 .cra_flags = CRYPTO_ALG_ASYNC,
2291 },
2292 .ivsize = AES_BLOCK_SIZE,
2293 .maxauthsize = MD5_DIGEST_SIZE,
Lee Nipper56af8cd2009-03-29 15:50:50 +08002294 },
Lee Nipper3952f172008-07-10 18:29:18 +08002295 .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
2296 DESC_HDR_SEL0_AESU |
2297 DESC_HDR_MODE0_AESU_CBC |
2298 DESC_HDR_SEL1_MDEUA |
2299 DESC_HDR_MODE1_MDEU_INIT |
2300 DESC_HDR_MODE1_MDEU_PAD |
2301 DESC_HDR_MODE1_MDEU_MD5_HMAC,
2302 },
Lee Nipperd5e4aae2010-05-19 19:18:38 +10002303 { .type = CRYPTO_ALG_TYPE_AEAD,
Herbert Xuaeb4c132015-07-30 17:53:22 +08002304 .alg.aead = {
2305 .base = {
2306 .cra_name = "authenc(hmac(md5),cbc(des3_ede))",
2307 .cra_driver_name = "authenc-hmac-md5-"
2308 "cbc-3des-talitos",
2309 .cra_blocksize = DES3_EDE_BLOCK_SIZE,
2310 .cra_flags = CRYPTO_ALG_ASYNC,
2311 },
2312 .ivsize = DES3_EDE_BLOCK_SIZE,
2313 .maxauthsize = MD5_DIGEST_SIZE,
Lee Nipper56af8cd2009-03-29 15:50:50 +08002314 },
Lee Nipper3952f172008-07-10 18:29:18 +08002315 .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
2316 DESC_HDR_SEL0_DEU |
2317 DESC_HDR_MODE0_DEU_CBC |
2318 DESC_HDR_MODE0_DEU_3DES |
2319 DESC_HDR_SEL1_MDEUA |
2320 DESC_HDR_MODE1_MDEU_INIT |
2321 DESC_HDR_MODE1_MDEU_PAD |
2322 DESC_HDR_MODE1_MDEU_MD5_HMAC,
Lee Nipper4de9d0b2009-03-29 15:52:32 +08002323 },
2324 /* ABLKCIPHER algorithms. */
Lee Nipperd5e4aae2010-05-19 19:18:38 +10002325 { .type = CRYPTO_ALG_TYPE_ABLKCIPHER,
2326 .alg.crypto = {
Lee Nipper4de9d0b2009-03-29 15:52:32 +08002327 .cra_name = "cbc(aes)",
2328 .cra_driver_name = "cbc-aes-talitos",
2329 .cra_blocksize = AES_BLOCK_SIZE,
2330 .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
2331 CRYPTO_ALG_ASYNC,
Lee Nipper4de9d0b2009-03-29 15:52:32 +08002332 .cra_ablkcipher = {
Lee Nipper4de9d0b2009-03-29 15:52:32 +08002333 .min_keysize = AES_MIN_KEY_SIZE,
2334 .max_keysize = AES_MAX_KEY_SIZE,
2335 .ivsize = AES_BLOCK_SIZE,
2336 }
2337 },
2338 .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
2339 DESC_HDR_SEL0_AESU |
2340 DESC_HDR_MODE0_AESU_CBC,
2341 },
Lee Nipperd5e4aae2010-05-19 19:18:38 +10002342 { .type = CRYPTO_ALG_TYPE_ABLKCIPHER,
2343 .alg.crypto = {
Lee Nipper4de9d0b2009-03-29 15:52:32 +08002344 .cra_name = "cbc(des3_ede)",
2345 .cra_driver_name = "cbc-3des-talitos",
2346 .cra_blocksize = DES3_EDE_BLOCK_SIZE,
2347 .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
2348 CRYPTO_ALG_ASYNC,
Lee Nipper4de9d0b2009-03-29 15:52:32 +08002349 .cra_ablkcipher = {
Lee Nipper4de9d0b2009-03-29 15:52:32 +08002350 .min_keysize = DES3_EDE_KEY_SIZE,
2351 .max_keysize = DES3_EDE_KEY_SIZE,
2352 .ivsize = DES3_EDE_BLOCK_SIZE,
2353 }
2354 },
2355 .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
2356 DESC_HDR_SEL0_DEU |
2357 DESC_HDR_MODE0_DEU_CBC |
2358 DESC_HDR_MODE0_DEU_3DES,
Lee Nipper497f2e62010-05-19 19:20:36 +10002359 },
2360 /* AHASH algorithms. */
2361 { .type = CRYPTO_ALG_TYPE_AHASH,
2362 .alg.hash = {
Lee Nipper497f2e62010-05-19 19:20:36 +10002363 .halg.digestsize = MD5_DIGEST_SIZE,
2364 .halg.base = {
2365 .cra_name = "md5",
2366 .cra_driver_name = "md5-talitos",
Martin Hicksb3988612015-03-03 08:21:34 -05002367 .cra_blocksize = MD5_HMAC_BLOCK_SIZE,
Lee Nipper497f2e62010-05-19 19:20:36 +10002368 .cra_flags = CRYPTO_ALG_TYPE_AHASH |
2369 CRYPTO_ALG_ASYNC,
Lee Nipper497f2e62010-05-19 19:20:36 +10002370 }
2371 },
2372 .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
2373 DESC_HDR_SEL0_MDEUA |
2374 DESC_HDR_MODE0_MDEU_MD5,
2375 },
2376 { .type = CRYPTO_ALG_TYPE_AHASH,
2377 .alg.hash = {
Lee Nipper497f2e62010-05-19 19:20:36 +10002378 .halg.digestsize = SHA1_DIGEST_SIZE,
2379 .halg.base = {
2380 .cra_name = "sha1",
2381 .cra_driver_name = "sha1-talitos",
2382 .cra_blocksize = SHA1_BLOCK_SIZE,
2383 .cra_flags = CRYPTO_ALG_TYPE_AHASH |
2384 CRYPTO_ALG_ASYNC,
Lee Nipper497f2e62010-05-19 19:20:36 +10002385 }
2386 },
2387 .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
2388 DESC_HDR_SEL0_MDEUA |
2389 DESC_HDR_MODE0_MDEU_SHA1,
2390 },
2391 { .type = CRYPTO_ALG_TYPE_AHASH,
2392 .alg.hash = {
Kim Phillips60f208d2010-05-19 19:21:53 +10002393 .halg.digestsize = SHA224_DIGEST_SIZE,
2394 .halg.base = {
2395 .cra_name = "sha224",
2396 .cra_driver_name = "sha224-talitos",
2397 .cra_blocksize = SHA224_BLOCK_SIZE,
2398 .cra_flags = CRYPTO_ALG_TYPE_AHASH |
2399 CRYPTO_ALG_ASYNC,
Kim Phillips60f208d2010-05-19 19:21:53 +10002400 }
2401 },
2402 .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
2403 DESC_HDR_SEL0_MDEUA |
2404 DESC_HDR_MODE0_MDEU_SHA224,
2405 },
2406 { .type = CRYPTO_ALG_TYPE_AHASH,
2407 .alg.hash = {
Lee Nipper497f2e62010-05-19 19:20:36 +10002408 .halg.digestsize = SHA256_DIGEST_SIZE,
2409 .halg.base = {
2410 .cra_name = "sha256",
2411 .cra_driver_name = "sha256-talitos",
2412 .cra_blocksize = SHA256_BLOCK_SIZE,
2413 .cra_flags = CRYPTO_ALG_TYPE_AHASH |
2414 CRYPTO_ALG_ASYNC,
Lee Nipper497f2e62010-05-19 19:20:36 +10002415 }
2416 },
2417 .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
2418 DESC_HDR_SEL0_MDEUA |
2419 DESC_HDR_MODE0_MDEU_SHA256,
2420 },
2421 { .type = CRYPTO_ALG_TYPE_AHASH,
2422 .alg.hash = {
Lee Nipper497f2e62010-05-19 19:20:36 +10002423 .halg.digestsize = SHA384_DIGEST_SIZE,
2424 .halg.base = {
2425 .cra_name = "sha384",
2426 .cra_driver_name = "sha384-talitos",
2427 .cra_blocksize = SHA384_BLOCK_SIZE,
2428 .cra_flags = CRYPTO_ALG_TYPE_AHASH |
2429 CRYPTO_ALG_ASYNC,
Lee Nipper497f2e62010-05-19 19:20:36 +10002430 }
2431 },
2432 .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
2433 DESC_HDR_SEL0_MDEUB |
2434 DESC_HDR_MODE0_MDEUB_SHA384,
2435 },
2436 { .type = CRYPTO_ALG_TYPE_AHASH,
2437 .alg.hash = {
Lee Nipper497f2e62010-05-19 19:20:36 +10002438 .halg.digestsize = SHA512_DIGEST_SIZE,
2439 .halg.base = {
2440 .cra_name = "sha512",
2441 .cra_driver_name = "sha512-talitos",
2442 .cra_blocksize = SHA512_BLOCK_SIZE,
2443 .cra_flags = CRYPTO_ALG_TYPE_AHASH |
2444 CRYPTO_ALG_ASYNC,
Lee Nipper497f2e62010-05-19 19:20:36 +10002445 }
2446 },
2447 .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
2448 DESC_HDR_SEL0_MDEUB |
2449 DESC_HDR_MODE0_MDEUB_SHA512,
2450 },
Lee Nipper79b3a412011-11-21 16:13:25 +08002451 { .type = CRYPTO_ALG_TYPE_AHASH,
2452 .alg.hash = {
Lee Nipper79b3a412011-11-21 16:13:25 +08002453 .halg.digestsize = MD5_DIGEST_SIZE,
2454 .halg.base = {
2455 .cra_name = "hmac(md5)",
2456 .cra_driver_name = "hmac-md5-talitos",
Martin Hicksb3988612015-03-03 08:21:34 -05002457 .cra_blocksize = MD5_HMAC_BLOCK_SIZE,
Lee Nipper79b3a412011-11-21 16:13:25 +08002458 .cra_flags = CRYPTO_ALG_TYPE_AHASH |
2459 CRYPTO_ALG_ASYNC,
Lee Nipper79b3a412011-11-21 16:13:25 +08002460 }
2461 },
2462 .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
2463 DESC_HDR_SEL0_MDEUA |
2464 DESC_HDR_MODE0_MDEU_MD5,
2465 },
2466 { .type = CRYPTO_ALG_TYPE_AHASH,
2467 .alg.hash = {
Lee Nipper79b3a412011-11-21 16:13:25 +08002468 .halg.digestsize = SHA1_DIGEST_SIZE,
2469 .halg.base = {
2470 .cra_name = "hmac(sha1)",
2471 .cra_driver_name = "hmac-sha1-talitos",
2472 .cra_blocksize = SHA1_BLOCK_SIZE,
2473 .cra_flags = CRYPTO_ALG_TYPE_AHASH |
2474 CRYPTO_ALG_ASYNC,
Lee Nipper79b3a412011-11-21 16:13:25 +08002475 }
2476 },
2477 .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
2478 DESC_HDR_SEL0_MDEUA |
2479 DESC_HDR_MODE0_MDEU_SHA1,
2480 },
2481 { .type = CRYPTO_ALG_TYPE_AHASH,
2482 .alg.hash = {
Lee Nipper79b3a412011-11-21 16:13:25 +08002483 .halg.digestsize = SHA224_DIGEST_SIZE,
2484 .halg.base = {
2485 .cra_name = "hmac(sha224)",
2486 .cra_driver_name = "hmac-sha224-talitos",
2487 .cra_blocksize = SHA224_BLOCK_SIZE,
2488 .cra_flags = CRYPTO_ALG_TYPE_AHASH |
2489 CRYPTO_ALG_ASYNC,
Lee Nipper79b3a412011-11-21 16:13:25 +08002490 }
2491 },
2492 .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
2493 DESC_HDR_SEL0_MDEUA |
2494 DESC_HDR_MODE0_MDEU_SHA224,
2495 },
2496 { .type = CRYPTO_ALG_TYPE_AHASH,
2497 .alg.hash = {
Lee Nipper79b3a412011-11-21 16:13:25 +08002498 .halg.digestsize = SHA256_DIGEST_SIZE,
2499 .halg.base = {
2500 .cra_name = "hmac(sha256)",
2501 .cra_driver_name = "hmac-sha256-talitos",
2502 .cra_blocksize = SHA256_BLOCK_SIZE,
2503 .cra_flags = CRYPTO_ALG_TYPE_AHASH |
2504 CRYPTO_ALG_ASYNC,
Lee Nipper79b3a412011-11-21 16:13:25 +08002505 }
2506 },
2507 .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
2508 DESC_HDR_SEL0_MDEUA |
2509 DESC_HDR_MODE0_MDEU_SHA256,
2510 },
2511 { .type = CRYPTO_ALG_TYPE_AHASH,
2512 .alg.hash = {
Lee Nipper79b3a412011-11-21 16:13:25 +08002513 .halg.digestsize = SHA384_DIGEST_SIZE,
2514 .halg.base = {
2515 .cra_name = "hmac(sha384)",
2516 .cra_driver_name = "hmac-sha384-talitos",
2517 .cra_blocksize = SHA384_BLOCK_SIZE,
2518 .cra_flags = CRYPTO_ALG_TYPE_AHASH |
2519 CRYPTO_ALG_ASYNC,
Lee Nipper79b3a412011-11-21 16:13:25 +08002520 }
2521 },
2522 .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
2523 DESC_HDR_SEL0_MDEUB |
2524 DESC_HDR_MODE0_MDEUB_SHA384,
2525 },
2526 { .type = CRYPTO_ALG_TYPE_AHASH,
2527 .alg.hash = {
Lee Nipper79b3a412011-11-21 16:13:25 +08002528 .halg.digestsize = SHA512_DIGEST_SIZE,
2529 .halg.base = {
2530 .cra_name = "hmac(sha512)",
2531 .cra_driver_name = "hmac-sha512-talitos",
2532 .cra_blocksize = SHA512_BLOCK_SIZE,
2533 .cra_flags = CRYPTO_ALG_TYPE_AHASH |
2534 CRYPTO_ALG_ASYNC,
Lee Nipper79b3a412011-11-21 16:13:25 +08002535 }
2536 },
2537 .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
2538 DESC_HDR_SEL0_MDEUB |
2539 DESC_HDR_MODE0_MDEUB_SHA512,
2540 }
Kim Phillips9c4a7962008-06-23 19:50:15 +08002541};
2542
2543struct talitos_crypto_alg {
2544 struct list_head entry;
2545 struct device *dev;
Lee Nipperacbf7c622010-05-19 19:19:33 +10002546 struct talitos_alg_template algt;
Kim Phillips9c4a7962008-06-23 19:50:15 +08002547};
2548
2549static int talitos_cra_init(struct crypto_tfm *tfm)
2550{
2551 struct crypto_alg *alg = tfm->__crt_alg;
Kim Phillips19bbbc62009-03-29 15:53:59 +08002552 struct talitos_crypto_alg *talitos_alg;
Kim Phillips9c4a7962008-06-23 19:50:15 +08002553 struct talitos_ctx *ctx = crypto_tfm_ctx(tfm);
Kim Phillips5228f0f2011-07-15 11:21:38 +08002554 struct talitos_private *priv;
Kim Phillips9c4a7962008-06-23 19:50:15 +08002555
Lee Nipper497f2e62010-05-19 19:20:36 +10002556 if ((alg->cra_flags & CRYPTO_ALG_TYPE_MASK) == CRYPTO_ALG_TYPE_AHASH)
2557 talitos_alg = container_of(__crypto_ahash_alg(alg),
2558 struct talitos_crypto_alg,
2559 algt.alg.hash);
2560 else
2561 talitos_alg = container_of(alg, struct talitos_crypto_alg,
2562 algt.alg.crypto);
Kim Phillips19bbbc62009-03-29 15:53:59 +08002563
Kim Phillips9c4a7962008-06-23 19:50:15 +08002564 /* update context with ptr to dev */
2565 ctx->dev = talitos_alg->dev;
Kim Phillips19bbbc62009-03-29 15:53:59 +08002566
Kim Phillips5228f0f2011-07-15 11:21:38 +08002567 /* assign SEC channel to tfm in round-robin fashion */
2568 priv = dev_get_drvdata(ctx->dev);
2569 ctx->ch = atomic_inc_return(&priv->last_chan) &
2570 (priv->num_channels - 1);
2571
Kim Phillips9c4a7962008-06-23 19:50:15 +08002572 /* copy descriptor header template value */
Lee Nipperacbf7c622010-05-19 19:19:33 +10002573 ctx->desc_hdr_template = talitos_alg->algt.desc_hdr_template;
Kim Phillips9c4a7962008-06-23 19:50:15 +08002574
Kim Phillips602dba52011-07-15 11:21:39 +08002575 /* select done notification */
2576 ctx->desc_hdr_template |= DESC_HDR_DONE_NOTIFY;
2577
Lee Nipper497f2e62010-05-19 19:20:36 +10002578 return 0;
2579}
2580
Herbert Xuaeb4c132015-07-30 17:53:22 +08002581static int talitos_cra_init_aead(struct crypto_aead *tfm)
Lee Nipper497f2e62010-05-19 19:20:36 +10002582{
Herbert Xuaeb4c132015-07-30 17:53:22 +08002583 talitos_cra_init(crypto_aead_tfm(tfm));
Kim Phillips9c4a7962008-06-23 19:50:15 +08002584 return 0;
2585}
2586
Lee Nipper497f2e62010-05-19 19:20:36 +10002587static int talitos_cra_init_ahash(struct crypto_tfm *tfm)
2588{
2589 struct talitos_ctx *ctx = crypto_tfm_ctx(tfm);
2590
2591 talitos_cra_init(tfm);
2592
2593 ctx->keylen = 0;
2594 crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm),
2595 sizeof(struct talitos_ahash_req_ctx));
2596
2597 return 0;
2598}
2599
Kim Phillips9c4a7962008-06-23 19:50:15 +08002600/*
2601 * given the alg's descriptor header template, determine whether descriptor
2602 * type and primary/secondary execution units required match the hw
2603 * capabilities description provided in the device tree node.
2604 */
2605static int hw_supports(struct device *dev, __be32 desc_hdr_template)
2606{
2607 struct talitos_private *priv = dev_get_drvdata(dev);
2608 int ret;
2609
2610 ret = (1 << DESC_TYPE(desc_hdr_template) & priv->desc_types) &&
2611 (1 << PRIMARY_EU(desc_hdr_template) & priv->exec_units);
2612
2613 if (SECONDARY_EU(desc_hdr_template))
2614 ret = ret && (1 << SECONDARY_EU(desc_hdr_template)
2615 & priv->exec_units);
2616
2617 return ret;
2618}
2619
Grant Likely2dc11582010-08-06 09:25:50 -06002620static int talitos_remove(struct platform_device *ofdev)
Kim Phillips9c4a7962008-06-23 19:50:15 +08002621{
2622 struct device *dev = &ofdev->dev;
2623 struct talitos_private *priv = dev_get_drvdata(dev);
2624 struct talitos_crypto_alg *t_alg, *n;
2625 int i;
2626
2627 list_for_each_entry_safe(t_alg, n, &priv->alg_list, entry) {
Lee Nipperacbf7c622010-05-19 19:19:33 +10002628 switch (t_alg->algt.type) {
2629 case CRYPTO_ALG_TYPE_ABLKCIPHER:
Lee Nipperacbf7c622010-05-19 19:19:33 +10002630 break;
Herbert Xuaeb4c132015-07-30 17:53:22 +08002631 case CRYPTO_ALG_TYPE_AEAD:
2632 crypto_unregister_aead(&t_alg->algt.alg.aead);
Lee Nipperacbf7c622010-05-19 19:19:33 +10002633 case CRYPTO_ALG_TYPE_AHASH:
2634 crypto_unregister_ahash(&t_alg->algt.alg.hash);
2635 break;
2636 }
Kim Phillips9c4a7962008-06-23 19:50:15 +08002637 list_del(&t_alg->entry);
2638 kfree(t_alg);
2639 }
2640
2641 if (hw_supports(dev, DESC_HDR_SEL0_RNG))
2642 talitos_unregister_rng(dev);
2643
Aaron Sierra35a3bb32015-08-05 16:52:08 -05002644 for (i = 0; priv->chan && i < priv->num_channels; i++)
Kim Phillips0b798242010-09-23 15:56:08 +08002645 kfree(priv->chan[i].fifo);
Kim Phillips9c4a7962008-06-23 19:50:15 +08002646
Kim Phillips4b9926282009-08-13 11:50:38 +10002647 kfree(priv->chan);
Kim Phillips9c4a7962008-06-23 19:50:15 +08002648
Kim Phillipsc3e337f2011-11-21 16:13:27 +08002649 for (i = 0; i < 2; i++)
Kim Phillips2cdba3c2011-12-12 14:59:11 -06002650 if (priv->irq[i]) {
Kim Phillipsc3e337f2011-11-21 16:13:27 +08002651 free_irq(priv->irq[i], dev);
2652 irq_dispose_mapping(priv->irq[i]);
2653 }
Kim Phillips9c4a7962008-06-23 19:50:15 +08002654
Kim Phillipsc3e337f2011-11-21 16:13:27 +08002655 tasklet_kill(&priv->done_task[0]);
Kim Phillips2cdba3c2011-12-12 14:59:11 -06002656 if (priv->irq[1])
Kim Phillipsc3e337f2011-11-21 16:13:27 +08002657 tasklet_kill(&priv->done_task[1]);
Kim Phillips9c4a7962008-06-23 19:50:15 +08002658
2659 iounmap(priv->reg);
2660
Kim Phillips9c4a7962008-06-23 19:50:15 +08002661 kfree(priv);
2662
2663 return 0;
2664}
2665
2666static struct talitos_crypto_alg *talitos_alg_alloc(struct device *dev,
2667 struct talitos_alg_template
2668 *template)
2669{
Kim Phillips60f208d2010-05-19 19:21:53 +10002670 struct talitos_private *priv = dev_get_drvdata(dev);
Kim Phillips9c4a7962008-06-23 19:50:15 +08002671 struct talitos_crypto_alg *t_alg;
2672 struct crypto_alg *alg;
2673
2674 t_alg = kzalloc(sizeof(struct talitos_crypto_alg), GFP_KERNEL);
2675 if (!t_alg)
2676 return ERR_PTR(-ENOMEM);
2677
Lee Nipperacbf7c622010-05-19 19:19:33 +10002678 t_alg->algt = *template;
2679
2680 switch (t_alg->algt.type) {
2681 case CRYPTO_ALG_TYPE_ABLKCIPHER:
Lee Nipper497f2e62010-05-19 19:20:36 +10002682 alg = &t_alg->algt.alg.crypto;
2683 alg->cra_init = talitos_cra_init;
Kim Phillipsd4cd3282012-08-08 20:32:00 -05002684 alg->cra_type = &crypto_ablkcipher_type;
Kim Phillipsb286e002012-08-08 20:33:34 -05002685 alg->cra_ablkcipher.setkey = ablkcipher_setkey;
2686 alg->cra_ablkcipher.encrypt = ablkcipher_encrypt;
2687 alg->cra_ablkcipher.decrypt = ablkcipher_decrypt;
2688 alg->cra_ablkcipher.geniv = "eseqiv";
Lee Nipper497f2e62010-05-19 19:20:36 +10002689 break;
Lee Nipperacbf7c622010-05-19 19:19:33 +10002690 case CRYPTO_ALG_TYPE_AEAD:
Herbert Xuaeb4c132015-07-30 17:53:22 +08002691 alg = &t_alg->algt.alg.aead.base;
Herbert Xuaeb4c132015-07-30 17:53:22 +08002692 t_alg->algt.alg.aead.init = talitos_cra_init_aead;
2693 t_alg->algt.alg.aead.setkey = aead_setkey;
2694 t_alg->algt.alg.aead.encrypt = aead_encrypt;
2695 t_alg->algt.alg.aead.decrypt = aead_decrypt;
Lee Nipperacbf7c622010-05-19 19:19:33 +10002696 break;
2697 case CRYPTO_ALG_TYPE_AHASH:
2698 alg = &t_alg->algt.alg.hash.halg.base;
Lee Nipper497f2e62010-05-19 19:20:36 +10002699 alg->cra_init = talitos_cra_init_ahash;
Kim Phillipsd4cd3282012-08-08 20:32:00 -05002700 alg->cra_type = &crypto_ahash_type;
Kim Phillipsb286e002012-08-08 20:33:34 -05002701 t_alg->algt.alg.hash.init = ahash_init;
2702 t_alg->algt.alg.hash.update = ahash_update;
2703 t_alg->algt.alg.hash.final = ahash_final;
2704 t_alg->algt.alg.hash.finup = ahash_finup;
2705 t_alg->algt.alg.hash.digest = ahash_digest;
2706 t_alg->algt.alg.hash.setkey = ahash_setkey;
2707
Lee Nipper79b3a412011-11-21 16:13:25 +08002708 if (!(priv->features & TALITOS_FTR_HMAC_OK) &&
Kim Phillips0b2730d2011-12-12 14:59:10 -06002709 !strncmp(alg->cra_name, "hmac", 4)) {
2710 kfree(t_alg);
Lee Nipper79b3a412011-11-21 16:13:25 +08002711 return ERR_PTR(-ENOTSUPP);
Kim Phillips0b2730d2011-12-12 14:59:10 -06002712 }
Kim Phillips60f208d2010-05-19 19:21:53 +10002713 if (!(priv->features & TALITOS_FTR_SHA224_HWINIT) &&
Lee Nipper79b3a412011-11-21 16:13:25 +08002714 (!strcmp(alg->cra_name, "sha224") ||
2715 !strcmp(alg->cra_name, "hmac(sha224)"))) {
Kim Phillips60f208d2010-05-19 19:21:53 +10002716 t_alg->algt.alg.hash.init = ahash_init_sha224_swinit;
2717 t_alg->algt.desc_hdr_template =
2718 DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
2719 DESC_HDR_SEL0_MDEUA |
2720 DESC_HDR_MODE0_MDEU_SHA256;
2721 }
Lee Nipper497f2e62010-05-19 19:20:36 +10002722 break;
Kim Phillips1d119112010-09-23 15:55:27 +08002723 default:
2724 dev_err(dev, "unknown algorithm type %d\n", t_alg->algt.type);
Horia Geant?5fa7dad2015-05-11 20:03:24 +03002725 kfree(t_alg);
Kim Phillips1d119112010-09-23 15:55:27 +08002726 return ERR_PTR(-EINVAL);
Lee Nipperacbf7c622010-05-19 19:19:33 +10002727 }
Kim Phillips9c4a7962008-06-23 19:50:15 +08002728
Kim Phillips9c4a7962008-06-23 19:50:15 +08002729 alg->cra_module = THIS_MODULE;
Kim Phillips9c4a7962008-06-23 19:50:15 +08002730 alg->cra_priority = TALITOS_CRA_PRIORITY;
Kim Phillips9c4a7962008-06-23 19:50:15 +08002731 alg->cra_alignmask = 0;
Kim Phillips9c4a7962008-06-23 19:50:15 +08002732 alg->cra_ctxsize = sizeof(struct talitos_ctx);
Nikos Mavrogiannopoulosd912bb72011-11-01 13:39:56 +01002733 alg->cra_flags |= CRYPTO_ALG_KERN_DRIVER_ONLY;
Kim Phillips9c4a7962008-06-23 19:50:15 +08002734
Kim Phillips9c4a7962008-06-23 19:50:15 +08002735 t_alg->dev = dev;
2736
2737 return t_alg;
2738}
2739
Kim Phillipsc3e337f2011-11-21 16:13:27 +08002740static int talitos_probe_irq(struct platform_device *ofdev)
2741{
2742 struct device *dev = &ofdev->dev;
2743 struct device_node *np = ofdev->dev.of_node;
2744 struct talitos_private *priv = dev_get_drvdata(dev);
2745 int err;
LEROY Christophedd3c0982015-04-17 16:32:13 +02002746 bool is_sec1 = has_ftr_sec1(priv);
Kim Phillipsc3e337f2011-11-21 16:13:27 +08002747
2748 priv->irq[0] = irq_of_parse_and_map(np, 0);
Kim Phillips2cdba3c2011-12-12 14:59:11 -06002749 if (!priv->irq[0]) {
Kim Phillipsc3e337f2011-11-21 16:13:27 +08002750 dev_err(dev, "failed to map irq\n");
2751 return -EINVAL;
2752 }
LEROY Christophedd3c0982015-04-17 16:32:13 +02002753 if (is_sec1) {
2754 err = request_irq(priv->irq[0], talitos1_interrupt_4ch, 0,
2755 dev_driver_string(dev), dev);
2756 goto primary_out;
2757 }
Kim Phillipsc3e337f2011-11-21 16:13:27 +08002758
2759 priv->irq[1] = irq_of_parse_and_map(np, 1);
2760
2761 /* get the primary irq line */
Kim Phillips2cdba3c2011-12-12 14:59:11 -06002762 if (!priv->irq[1]) {
LEROY Christophedd3c0982015-04-17 16:32:13 +02002763 err = request_irq(priv->irq[0], talitos2_interrupt_4ch, 0,
Kim Phillipsc3e337f2011-11-21 16:13:27 +08002764 dev_driver_string(dev), dev);
2765 goto primary_out;
2766 }
2767
LEROY Christophedd3c0982015-04-17 16:32:13 +02002768 err = request_irq(priv->irq[0], talitos2_interrupt_ch0_2, 0,
Kim Phillipsc3e337f2011-11-21 16:13:27 +08002769 dev_driver_string(dev), dev);
2770 if (err)
2771 goto primary_out;
2772
2773 /* get the secondary irq line */
LEROY Christophedd3c0982015-04-17 16:32:13 +02002774 err = request_irq(priv->irq[1], talitos2_interrupt_ch1_3, 0,
Kim Phillipsc3e337f2011-11-21 16:13:27 +08002775 dev_driver_string(dev), dev);
2776 if (err) {
2777 dev_err(dev, "failed to request secondary irq\n");
2778 irq_dispose_mapping(priv->irq[1]);
Kim Phillips2cdba3c2011-12-12 14:59:11 -06002779 priv->irq[1] = 0;
Kim Phillipsc3e337f2011-11-21 16:13:27 +08002780 }
2781
2782 return err;
2783
2784primary_out:
2785 if (err) {
2786 dev_err(dev, "failed to request primary irq\n");
2787 irq_dispose_mapping(priv->irq[0]);
Kim Phillips2cdba3c2011-12-12 14:59:11 -06002788 priv->irq[0] = 0;
Kim Phillipsc3e337f2011-11-21 16:13:27 +08002789 }
2790
2791 return err;
2792}
2793
Grant Likely1c48a5c2011-02-17 02:43:24 -07002794static int talitos_probe(struct platform_device *ofdev)
Kim Phillips9c4a7962008-06-23 19:50:15 +08002795{
2796 struct device *dev = &ofdev->dev;
Grant Likely61c7a082010-04-13 16:12:29 -07002797 struct device_node *np = ofdev->dev.of_node;
Kim Phillips9c4a7962008-06-23 19:50:15 +08002798 struct talitos_private *priv;
2799 const unsigned int *prop;
2800 int i, err;
LEROY Christophe5fa7fa12015-04-17 16:32:11 +02002801 int stride;
Kim Phillips9c4a7962008-06-23 19:50:15 +08002802
2803 priv = kzalloc(sizeof(struct talitos_private), GFP_KERNEL);
2804 if (!priv)
2805 return -ENOMEM;
2806
Kevin Haof3de9cb2014-01-28 20:17:23 +08002807 INIT_LIST_HEAD(&priv->alg_list);
2808
Kim Phillips9c4a7962008-06-23 19:50:15 +08002809 dev_set_drvdata(dev, priv);
2810
2811 priv->ofdev = ofdev;
2812
Horia Geanta511d63c2012-03-30 17:49:53 +03002813 spin_lock_init(&priv->reg_lock);
2814
Kim Phillips9c4a7962008-06-23 19:50:15 +08002815 priv->reg = of_iomap(np, 0);
2816 if (!priv->reg) {
2817 dev_err(dev, "failed to of_iomap\n");
2818 err = -ENOMEM;
2819 goto err_out;
2820 }
2821
2822 /* get SEC version capabilities from device tree */
2823 prop = of_get_property(np, "fsl,num-channels", NULL);
2824 if (prop)
2825 priv->num_channels = *prop;
2826
2827 prop = of_get_property(np, "fsl,channel-fifo-len", NULL);
2828 if (prop)
2829 priv->chfifo_len = *prop;
2830
2831 prop = of_get_property(np, "fsl,exec-units-mask", NULL);
2832 if (prop)
2833 priv->exec_units = *prop;
2834
2835 prop = of_get_property(np, "fsl,descriptor-types-mask", NULL);
2836 if (prop)
2837 priv->desc_types = *prop;
2838
2839 if (!is_power_of_2(priv->num_channels) || !priv->chfifo_len ||
2840 !priv->exec_units || !priv->desc_types) {
2841 dev_err(dev, "invalid property data in device tree node\n");
2842 err = -EINVAL;
2843 goto err_out;
2844 }
2845
Lee Nipperf3c85bc2008-07-30 16:26:57 +08002846 if (of_device_is_compatible(np, "fsl,sec3.0"))
2847 priv->features |= TALITOS_FTR_SRC_LINK_TBL_LEN_INCLUDES_EXTENT;
2848
Kim Phillipsfe5720e2008-10-12 20:33:14 +08002849 if (of_device_is_compatible(np, "fsl,sec2.1"))
Kim Phillips60f208d2010-05-19 19:21:53 +10002850 priv->features |= TALITOS_FTR_HW_AUTH_CHECK |
Lee Nipper79b3a412011-11-21 16:13:25 +08002851 TALITOS_FTR_SHA224_HWINIT |
2852 TALITOS_FTR_HMAC_OK;
Kim Phillipsfe5720e2008-10-12 20:33:14 +08002853
LEROY Christophe21590882015-04-17 16:32:05 +02002854 if (of_device_is_compatible(np, "fsl,sec1.0"))
2855 priv->features |= TALITOS_FTR_SEC1;
2856
LEROY Christophe5fa7fa12015-04-17 16:32:11 +02002857 if (of_device_is_compatible(np, "fsl,sec1.2")) {
2858 priv->reg_deu = priv->reg + TALITOS12_DEU;
2859 priv->reg_aesu = priv->reg + TALITOS12_AESU;
2860 priv->reg_mdeu = priv->reg + TALITOS12_MDEU;
2861 stride = TALITOS1_CH_STRIDE;
2862 } else if (of_device_is_compatible(np, "fsl,sec1.0")) {
2863 priv->reg_deu = priv->reg + TALITOS10_DEU;
2864 priv->reg_aesu = priv->reg + TALITOS10_AESU;
2865 priv->reg_mdeu = priv->reg + TALITOS10_MDEU;
2866 priv->reg_afeu = priv->reg + TALITOS10_AFEU;
2867 priv->reg_rngu = priv->reg + TALITOS10_RNGU;
2868 priv->reg_pkeu = priv->reg + TALITOS10_PKEU;
2869 stride = TALITOS1_CH_STRIDE;
2870 } else {
2871 priv->reg_deu = priv->reg + TALITOS2_DEU;
2872 priv->reg_aesu = priv->reg + TALITOS2_AESU;
2873 priv->reg_mdeu = priv->reg + TALITOS2_MDEU;
2874 priv->reg_afeu = priv->reg + TALITOS2_AFEU;
2875 priv->reg_rngu = priv->reg + TALITOS2_RNGU;
2876 priv->reg_pkeu = priv->reg + TALITOS2_PKEU;
2877 priv->reg_keu = priv->reg + TALITOS2_KEU;
2878 priv->reg_crcu = priv->reg + TALITOS2_CRCU;
2879 stride = TALITOS2_CH_STRIDE;
2880 }
2881
LEROY Christophedd3c0982015-04-17 16:32:13 +02002882 err = talitos_probe_irq(ofdev);
2883 if (err)
2884 goto err_out;
2885
2886 if (of_device_is_compatible(np, "fsl,sec1.0")) {
2887 tasklet_init(&priv->done_task[0], talitos1_done_4ch,
2888 (unsigned long)dev);
2889 } else {
2890 if (!priv->irq[1]) {
2891 tasklet_init(&priv->done_task[0], talitos2_done_4ch,
2892 (unsigned long)dev);
2893 } else {
2894 tasklet_init(&priv->done_task[0], talitos2_done_ch0_2,
2895 (unsigned long)dev);
2896 tasklet_init(&priv->done_task[1], talitos2_done_ch1_3,
2897 (unsigned long)dev);
2898 }
2899 }
2900
Kim Phillips4b9926282009-08-13 11:50:38 +10002901 priv->chan = kzalloc(sizeof(struct talitos_channel) *
2902 priv->num_channels, GFP_KERNEL);
2903 if (!priv->chan) {
2904 dev_err(dev, "failed to allocate channel management space\n");
Kim Phillips9c4a7962008-06-23 19:50:15 +08002905 err = -ENOMEM;
2906 goto err_out;
2907 }
2908
Martin Hicksf641ddd2015-03-03 08:21:33 -05002909 priv->fifo_len = roundup_pow_of_two(priv->chfifo_len);
2910
Kim Phillipsc3e337f2011-11-21 16:13:27 +08002911 for (i = 0; i < priv->num_channels; i++) {
LEROY Christophe5fa7fa12015-04-17 16:32:11 +02002912 priv->chan[i].reg = priv->reg + stride * (i + 1);
Kim Phillips2cdba3c2011-12-12 14:59:11 -06002913 if (!priv->irq[1] || !(i & 1))
Kim Phillipsc3e337f2011-11-21 16:13:27 +08002914 priv->chan[i].reg += TALITOS_CH_BASE_OFFSET;
Kim Phillipsad42d5f2011-11-21 16:13:27 +08002915
Kim Phillips4b9926282009-08-13 11:50:38 +10002916 spin_lock_init(&priv->chan[i].head_lock);
2917 spin_lock_init(&priv->chan[i].tail_lock);
Kim Phillips9c4a7962008-06-23 19:50:15 +08002918
Kim Phillips4b9926282009-08-13 11:50:38 +10002919 priv->chan[i].fifo = kzalloc(sizeof(struct talitos_request) *
2920 priv->fifo_len, GFP_KERNEL);
2921 if (!priv->chan[i].fifo) {
Kim Phillips9c4a7962008-06-23 19:50:15 +08002922 dev_err(dev, "failed to allocate request fifo %d\n", i);
2923 err = -ENOMEM;
2924 goto err_out;
2925 }
Kim Phillips9c4a7962008-06-23 19:50:15 +08002926
Kim Phillips4b9926282009-08-13 11:50:38 +10002927 atomic_set(&priv->chan[i].submit_count,
2928 -(priv->chfifo_len - 1));
Martin Hicksf641ddd2015-03-03 08:21:33 -05002929 }
Kim Phillips9c4a7962008-06-23 19:50:15 +08002930
Kim Phillips81eb0242009-08-13 11:51:51 +10002931 dma_set_mask(dev, DMA_BIT_MASK(36));
2932
Kim Phillips9c4a7962008-06-23 19:50:15 +08002933 /* reset and initialize the h/w */
2934 err = init_device(dev);
2935 if (err) {
2936 dev_err(dev, "failed to initialize device\n");
2937 goto err_out;
2938 }
2939
2940 /* register the RNG, if available */
2941 if (hw_supports(dev, DESC_HDR_SEL0_RNG)) {
2942 err = talitos_register_rng(dev);
2943 if (err) {
2944 dev_err(dev, "failed to register hwrng: %d\n", err);
2945 goto err_out;
2946 } else
2947 dev_info(dev, "hwrng\n");
2948 }
2949
2950 /* register crypto algorithms the device supports */
Kim Phillips9c4a7962008-06-23 19:50:15 +08002951 for (i = 0; i < ARRAY_SIZE(driver_algs); i++) {
2952 if (hw_supports(dev, driver_algs[i].desc_hdr_template)) {
2953 struct talitos_crypto_alg *t_alg;
Herbert Xuaeb4c132015-07-30 17:53:22 +08002954 struct crypto_alg *alg = NULL;
Kim Phillips9c4a7962008-06-23 19:50:15 +08002955
2956 t_alg = talitos_alg_alloc(dev, &driver_algs[i]);
2957 if (IS_ERR(t_alg)) {
2958 err = PTR_ERR(t_alg);
Kim Phillips0b2730d2011-12-12 14:59:10 -06002959 if (err == -ENOTSUPP)
Lee Nipper79b3a412011-11-21 16:13:25 +08002960 continue;
Kim Phillips9c4a7962008-06-23 19:50:15 +08002961 goto err_out;
2962 }
2963
Lee Nipperacbf7c622010-05-19 19:19:33 +10002964 switch (t_alg->algt.type) {
2965 case CRYPTO_ALG_TYPE_ABLKCIPHER:
Lee Nipperacbf7c622010-05-19 19:19:33 +10002966 err = crypto_register_alg(
2967 &t_alg->algt.alg.crypto);
Herbert Xuaeb4c132015-07-30 17:53:22 +08002968 alg = &t_alg->algt.alg.crypto;
Lee Nipperacbf7c622010-05-19 19:19:33 +10002969 break;
Herbert Xuaeb4c132015-07-30 17:53:22 +08002970
2971 case CRYPTO_ALG_TYPE_AEAD:
2972 err = crypto_register_aead(
2973 &t_alg->algt.alg.aead);
2974 alg = &t_alg->algt.alg.aead.base;
2975 break;
2976
Lee Nipperacbf7c622010-05-19 19:19:33 +10002977 case CRYPTO_ALG_TYPE_AHASH:
2978 err = crypto_register_ahash(
2979 &t_alg->algt.alg.hash);
Herbert Xuaeb4c132015-07-30 17:53:22 +08002980 alg = &t_alg->algt.alg.hash.halg.base;
Lee Nipperacbf7c622010-05-19 19:19:33 +10002981 break;
2982 }
Kim Phillips9c4a7962008-06-23 19:50:15 +08002983 if (err) {
2984 dev_err(dev, "%s alg registration failed\n",
Herbert Xuaeb4c132015-07-30 17:53:22 +08002985 alg->cra_driver_name);
Kim Phillips9c4a7962008-06-23 19:50:15 +08002986 kfree(t_alg);
Horia Geanta991155b2013-03-20 16:31:38 +02002987 } else
Kim Phillips9c4a7962008-06-23 19:50:15 +08002988 list_add_tail(&t_alg->entry, &priv->alg_list);
Kim Phillips9c4a7962008-06-23 19:50:15 +08002989 }
2990 }
Kim Phillips5b859b6e2011-11-21 16:13:26 +08002991 if (!list_empty(&priv->alg_list))
2992 dev_info(dev, "%s algorithms registered in /proc/crypto\n",
2993 (char *)of_get_property(np, "compatible", NULL));
Kim Phillips9c4a7962008-06-23 19:50:15 +08002994
2995 return 0;
2996
2997err_out:
2998 talitos_remove(ofdev);
Kim Phillips9c4a7962008-06-23 19:50:15 +08002999
3000 return err;
3001}
3002
Márton Németh6c3f9752010-01-17 21:54:01 +11003003static const struct of_device_id talitos_match[] = {
LEROY Christophe0635b7d2015-04-17 16:32:20 +02003004#ifdef CONFIG_CRYPTO_DEV_TALITOS1
3005 {
3006 .compatible = "fsl,sec1.0",
3007 },
3008#endif
3009#ifdef CONFIG_CRYPTO_DEV_TALITOS2
Kim Phillips9c4a7962008-06-23 19:50:15 +08003010 {
3011 .compatible = "fsl,sec2.0",
3012 },
LEROY Christophe0635b7d2015-04-17 16:32:20 +02003013#endif
Kim Phillips9c4a7962008-06-23 19:50:15 +08003014 {},
3015};
3016MODULE_DEVICE_TABLE(of, talitos_match);
3017
Grant Likely1c48a5c2011-02-17 02:43:24 -07003018static struct platform_driver talitos_driver = {
Grant Likely40182942010-04-13 16:13:02 -07003019 .driver = {
3020 .name = "talitos",
Grant Likely40182942010-04-13 16:13:02 -07003021 .of_match_table = talitos_match,
3022 },
Kim Phillips9c4a7962008-06-23 19:50:15 +08003023 .probe = talitos_probe,
Al Viro596f1032008-11-22 17:34:24 +00003024 .remove = talitos_remove,
Kim Phillips9c4a7962008-06-23 19:50:15 +08003025};
3026
Axel Lin741e8c22011-11-26 21:26:19 +08003027module_platform_driver(talitos_driver);
Kim Phillips9c4a7962008-06-23 19:50:15 +08003028
3029MODULE_LICENSE("GPL");
3030MODULE_AUTHOR("Kim Phillips <kim.phillips@freescale.com>");
3031MODULE_DESCRIPTION("Freescale integrated security engine (SEC) driver");