blob: 9a8a18aafd5cb6eb577285c7a9cd1c4105f190b2 [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?cd780352016-04-19 20:33:48 +030066static void copy_talitos_ptr(struct talitos_ptr *dst_ptr,
67 struct talitos_ptr *src_ptr, bool is_sec1)
68{
69 dst_ptr->ptr = src_ptr->ptr;
70 if (!is_sec1)
71 dst_ptr->eptr = src_ptr->eptr;
72}
73
Horia Geant?42e8b0d2015-05-11 20:04:56 +030074static void to_talitos_ptr_len(struct talitos_ptr *ptr, unsigned int len,
LEROY Christophe922f9dc2015-04-17 16:32:07 +020075 bool is_sec1)
LEROY Christophe538caf82015-04-17 16:31:59 +020076{
LEROY Christophe922f9dc2015-04-17 16:32:07 +020077 if (is_sec1) {
78 ptr->res = 0;
79 ptr->len1 = cpu_to_be16(len);
80 } else {
81 ptr->len = cpu_to_be16(len);
82 }
LEROY Christophe538caf82015-04-17 16:31:59 +020083}
84
LEROY Christophe922f9dc2015-04-17 16:32:07 +020085static unsigned short from_talitos_ptr_len(struct talitos_ptr *ptr,
86 bool is_sec1)
LEROY Christophe538caf82015-04-17 16:31:59 +020087{
LEROY Christophe922f9dc2015-04-17 16:32:07 +020088 if (is_sec1)
89 return be16_to_cpu(ptr->len1);
90 else
91 return be16_to_cpu(ptr->len);
LEROY Christophe538caf82015-04-17 16:31:59 +020092}
93
LEROY Christophe922f9dc2015-04-17 16:32:07 +020094static void to_talitos_ptr_extent_clear(struct talitos_ptr *ptr, bool is_sec1)
LEROY Christophe185eb792015-04-17 16:31:55 +020095{
LEROY Christophe922f9dc2015-04-17 16:32:07 +020096 if (!is_sec1)
97 ptr->j_extent = 0;
LEROY Christophe185eb792015-04-17 16:31:55 +020098}
99
Kim Phillips9c4a7962008-06-23 19:50:15 +0800100/*
101 * map virtual single (contiguous) pointer to h/w descriptor pointer
102 */
103static void map_single_talitos_ptr(struct device *dev,
LEROY Christopheedc6bd62015-04-17 16:31:53 +0200104 struct talitos_ptr *ptr,
Horia Geant?42e8b0d2015-05-11 20:04:56 +0300105 unsigned int len, void *data,
Kim Phillips9c4a7962008-06-23 19:50:15 +0800106 enum dma_data_direction dir)
107{
Kim Phillips81eb0242009-08-13 11:51:51 +1000108 dma_addr_t dma_addr = dma_map_single(dev, data, len, dir);
LEROY Christophe922f9dc2015-04-17 16:32:07 +0200109 struct talitos_private *priv = dev_get_drvdata(dev);
110 bool is_sec1 = has_ftr_sec1(priv);
Kim Phillips81eb0242009-08-13 11:51:51 +1000111
LEROY Christophe922f9dc2015-04-17 16:32:07 +0200112 to_talitos_ptr_len(ptr, len, is_sec1);
113 to_talitos_ptr(ptr, dma_addr, is_sec1);
114 to_talitos_ptr_extent_clear(ptr, is_sec1);
Kim Phillips9c4a7962008-06-23 19:50:15 +0800115}
116
117/*
118 * unmap bus single (contiguous) h/w descriptor pointer
119 */
120static void unmap_single_talitos_ptr(struct device *dev,
LEROY Christopheedc6bd62015-04-17 16:31:53 +0200121 struct talitos_ptr *ptr,
Kim Phillips9c4a7962008-06-23 19:50:15 +0800122 enum dma_data_direction dir)
123{
LEROY Christophe922f9dc2015-04-17 16:32:07 +0200124 struct talitos_private *priv = dev_get_drvdata(dev);
125 bool is_sec1 = has_ftr_sec1(priv);
126
LEROY Christopheedc6bd62015-04-17 16:31:53 +0200127 dma_unmap_single(dev, be32_to_cpu(ptr->ptr),
LEROY Christophe922f9dc2015-04-17 16:32:07 +0200128 from_talitos_ptr_len(ptr, is_sec1), dir);
Kim Phillips9c4a7962008-06-23 19:50:15 +0800129}
130
131static int reset_channel(struct device *dev, int ch)
132{
133 struct talitos_private *priv = dev_get_drvdata(dev);
134 unsigned int timeout = TALITOS_TIMEOUT;
LEROY Christophedd3c0982015-04-17 16:32:13 +0200135 bool is_sec1 = has_ftr_sec1(priv);
Kim Phillips9c4a7962008-06-23 19:50:15 +0800136
LEROY Christophedd3c0982015-04-17 16:32:13 +0200137 if (is_sec1) {
138 setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO,
139 TALITOS1_CCCR_LO_RESET);
Kim Phillips9c4a7962008-06-23 19:50:15 +0800140
LEROY Christophedd3c0982015-04-17 16:32:13 +0200141 while ((in_be32(priv->chan[ch].reg + TALITOS_CCCR_LO) &
142 TALITOS1_CCCR_LO_RESET) && --timeout)
143 cpu_relax();
144 } else {
145 setbits32(priv->chan[ch].reg + TALITOS_CCCR,
146 TALITOS2_CCCR_RESET);
147
148 while ((in_be32(priv->chan[ch].reg + TALITOS_CCCR) &
149 TALITOS2_CCCR_RESET) && --timeout)
150 cpu_relax();
151 }
Kim Phillips9c4a7962008-06-23 19:50:15 +0800152
153 if (timeout == 0) {
154 dev_err(dev, "failed to reset channel %d\n", ch);
155 return -EIO;
156 }
157
Kim Phillips81eb0242009-08-13 11:51:51 +1000158 /* set 36-bit addressing, done writeback enable and done IRQ enable */
Kim Phillipsad42d5f2011-11-21 16:13:27 +0800159 setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO, TALITOS_CCCR_LO_EAE |
Kim Phillips81eb0242009-08-13 11:51:51 +1000160 TALITOS_CCCR_LO_CDWE | TALITOS_CCCR_LO_CDIE);
Kim Phillips9c4a7962008-06-23 19:50:15 +0800161
Kim Phillipsfe5720e2008-10-12 20:33:14 +0800162 /* and ICCR writeback, if available */
163 if (priv->features & TALITOS_FTR_HW_AUTH_CHECK)
Kim Phillipsad42d5f2011-11-21 16:13:27 +0800164 setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO,
Kim Phillipsfe5720e2008-10-12 20:33:14 +0800165 TALITOS_CCCR_LO_IWSE);
166
Kim Phillips9c4a7962008-06-23 19:50:15 +0800167 return 0;
168}
169
170static int reset_device(struct device *dev)
171{
172 struct talitos_private *priv = dev_get_drvdata(dev);
173 unsigned int timeout = TALITOS_TIMEOUT;
LEROY Christophedd3c0982015-04-17 16:32:13 +0200174 bool is_sec1 = has_ftr_sec1(priv);
175 u32 mcr = is_sec1 ? TALITOS1_MCR_SWR : TALITOS2_MCR_SWR;
Kim Phillips9c4a7962008-06-23 19:50:15 +0800176
Kim Phillipsc3e337f2011-11-21 16:13:27 +0800177 setbits32(priv->reg + TALITOS_MCR, mcr);
Kim Phillips9c4a7962008-06-23 19:50:15 +0800178
LEROY Christophedd3c0982015-04-17 16:32:13 +0200179 while ((in_be32(priv->reg + TALITOS_MCR) & mcr)
Kim Phillips9c4a7962008-06-23 19:50:15 +0800180 && --timeout)
181 cpu_relax();
182
Kim Phillips2cdba3c2011-12-12 14:59:11 -0600183 if (priv->irq[1]) {
Kim Phillipsc3e337f2011-11-21 16:13:27 +0800184 mcr = TALITOS_MCR_RCA1 | TALITOS_MCR_RCA3;
185 setbits32(priv->reg + TALITOS_MCR, mcr);
186 }
187
Kim Phillips9c4a7962008-06-23 19:50:15 +0800188 if (timeout == 0) {
189 dev_err(dev, "failed to reset device\n");
190 return -EIO;
191 }
192
193 return 0;
194}
195
196/*
197 * Reset and initialize the device
198 */
199static int init_device(struct device *dev)
200{
201 struct talitos_private *priv = dev_get_drvdata(dev);
202 int ch, err;
LEROY Christophedd3c0982015-04-17 16:32:13 +0200203 bool is_sec1 = has_ftr_sec1(priv);
Kim Phillips9c4a7962008-06-23 19:50:15 +0800204
205 /*
206 * Master reset
207 * errata documentation: warning: certain SEC interrupts
208 * are not fully cleared by writing the MCR:SWR bit,
209 * set bit twice to completely reset
210 */
211 err = reset_device(dev);
212 if (err)
213 return err;
214
215 err = reset_device(dev);
216 if (err)
217 return err;
218
219 /* reset channels */
220 for (ch = 0; ch < priv->num_channels; ch++) {
221 err = reset_channel(dev, ch);
222 if (err)
223 return err;
224 }
225
226 /* enable channel done and error interrupts */
LEROY Christophedd3c0982015-04-17 16:32:13 +0200227 if (is_sec1) {
228 clrbits32(priv->reg + TALITOS_IMR, TALITOS1_IMR_INIT);
229 clrbits32(priv->reg + TALITOS_IMR_LO, TALITOS1_IMR_LO_INIT);
230 /* disable parity error check in DEU (erroneous? test vect.) */
231 setbits32(priv->reg_deu + TALITOS_EUICR, TALITOS1_DEUICR_KPE);
232 } else {
233 setbits32(priv->reg + TALITOS_IMR, TALITOS2_IMR_INIT);
234 setbits32(priv->reg + TALITOS_IMR_LO, TALITOS2_IMR_LO_INIT);
235 }
Kim Phillips9c4a7962008-06-23 19:50:15 +0800236
Kim Phillipsfe5720e2008-10-12 20:33:14 +0800237 /* disable integrity check error interrupts (use writeback instead) */
238 if (priv->features & TALITOS_FTR_HW_AUTH_CHECK)
LEROY Christophe5fa7fa12015-04-17 16:32:11 +0200239 setbits32(priv->reg_mdeu + TALITOS_EUICR_LO,
Kim Phillipsfe5720e2008-10-12 20:33:14 +0800240 TALITOS_MDEUICR_LO_ICE);
241
Kim Phillips9c4a7962008-06-23 19:50:15 +0800242 return 0;
243}
244
245/**
246 * talitos_submit - submits a descriptor to the device for processing
247 * @dev: the SEC device to be used
Kim Phillips5228f0f2011-07-15 11:21:38 +0800248 * @ch: the SEC device channel to be used
Kim Phillips9c4a7962008-06-23 19:50:15 +0800249 * @desc: the descriptor to be processed by the device
250 * @callback: whom to call when processing is complete
251 * @context: a handle for use by caller (optional)
252 *
253 * desc must contain valid dma-mapped (bus physical) address pointers.
254 * callback must check err and feedback in descriptor header
255 * for device processing status.
256 */
Horia Geanta865d5062012-07-03 19:16:52 +0300257int talitos_submit(struct device *dev, int ch, struct talitos_desc *desc,
258 void (*callback)(struct device *dev,
259 struct talitos_desc *desc,
260 void *context, int error),
261 void *context)
Kim Phillips9c4a7962008-06-23 19:50:15 +0800262{
263 struct talitos_private *priv = dev_get_drvdata(dev);
264 struct talitos_request *request;
Kim Phillips5228f0f2011-07-15 11:21:38 +0800265 unsigned long flags;
Kim Phillips9c4a7962008-06-23 19:50:15 +0800266 int head;
LEROY Christophe7d607c6a2015-04-17 16:32:09 +0200267 bool is_sec1 = has_ftr_sec1(priv);
Kim Phillips9c4a7962008-06-23 19:50:15 +0800268
Kim Phillips4b9926282009-08-13 11:50:38 +1000269 spin_lock_irqsave(&priv->chan[ch].head_lock, flags);
Kim Phillips9c4a7962008-06-23 19:50:15 +0800270
Kim Phillips4b9926282009-08-13 11:50:38 +1000271 if (!atomic_inc_not_zero(&priv->chan[ch].submit_count)) {
Kim Phillipsec6644d2008-07-17 20:16:40 +0800272 /* h/w fifo is full */
Kim Phillips4b9926282009-08-13 11:50:38 +1000273 spin_unlock_irqrestore(&priv->chan[ch].head_lock, flags);
Kim Phillips9c4a7962008-06-23 19:50:15 +0800274 return -EAGAIN;
275 }
276
Kim Phillips4b9926282009-08-13 11:50:38 +1000277 head = priv->chan[ch].head;
278 request = &priv->chan[ch].fifo[head];
Kim Phillipsec6644d2008-07-17 20:16:40 +0800279
Kim Phillips9c4a7962008-06-23 19:50:15 +0800280 /* map descriptor and save caller data */
LEROY Christophe7d607c6a2015-04-17 16:32:09 +0200281 if (is_sec1) {
282 desc->hdr1 = desc->hdr;
283 desc->next_desc = 0;
284 request->dma_desc = dma_map_single(dev, &desc->hdr1,
285 TALITOS_DESC_SIZE,
286 DMA_BIDIRECTIONAL);
287 } else {
288 request->dma_desc = dma_map_single(dev, desc,
289 TALITOS_DESC_SIZE,
290 DMA_BIDIRECTIONAL);
291 }
Kim Phillips9c4a7962008-06-23 19:50:15 +0800292 request->callback = callback;
293 request->context = context;
294
295 /* increment fifo head */
Kim Phillips4b9926282009-08-13 11:50:38 +1000296 priv->chan[ch].head = (priv->chan[ch].head + 1) & (priv->fifo_len - 1);
Kim Phillips9c4a7962008-06-23 19:50:15 +0800297
298 smp_wmb();
299 request->desc = desc;
300
301 /* GO! */
302 wmb();
Kim Phillipsad42d5f2011-11-21 16:13:27 +0800303 out_be32(priv->chan[ch].reg + TALITOS_FF,
304 upper_32_bits(request->dma_desc));
305 out_be32(priv->chan[ch].reg + TALITOS_FF_LO,
Kim Phillipsa7524472010-09-23 15:56:38 +0800306 lower_32_bits(request->dma_desc));
Kim Phillips9c4a7962008-06-23 19:50:15 +0800307
Kim Phillips4b9926282009-08-13 11:50:38 +1000308 spin_unlock_irqrestore(&priv->chan[ch].head_lock, flags);
Kim Phillips9c4a7962008-06-23 19:50:15 +0800309
310 return -EINPROGRESS;
311}
Horia Geanta865d5062012-07-03 19:16:52 +0300312EXPORT_SYMBOL(talitos_submit);
Kim Phillips9c4a7962008-06-23 19:50:15 +0800313
314/*
315 * process what was done, notify callback of error if not
316 */
317static void flush_channel(struct device *dev, int ch, int error, int reset_ch)
318{
319 struct talitos_private *priv = dev_get_drvdata(dev);
320 struct talitos_request *request, saved_req;
321 unsigned long flags;
322 int tail, status;
LEROY Christophe7d607c6a2015-04-17 16:32:09 +0200323 bool is_sec1 = has_ftr_sec1(priv);
Kim Phillips9c4a7962008-06-23 19:50:15 +0800324
Kim Phillips4b9926282009-08-13 11:50:38 +1000325 spin_lock_irqsave(&priv->chan[ch].tail_lock, flags);
Kim Phillips9c4a7962008-06-23 19:50:15 +0800326
Kim Phillips4b9926282009-08-13 11:50:38 +1000327 tail = priv->chan[ch].tail;
328 while (priv->chan[ch].fifo[tail].desc) {
LEROY Christophe7d607c6a2015-04-17 16:32:09 +0200329 __be32 hdr;
330
Kim Phillips4b9926282009-08-13 11:50:38 +1000331 request = &priv->chan[ch].fifo[tail];
Kim Phillips9c4a7962008-06-23 19:50:15 +0800332
333 /* descriptors with their done bits set don't get the error */
334 rmb();
LEROY Christophe7d607c6a2015-04-17 16:32:09 +0200335 hdr = is_sec1 ? request->desc->hdr1 : request->desc->hdr;
336
337 if ((hdr & DESC_HDR_DONE) == DESC_HDR_DONE)
Kim Phillips9c4a7962008-06-23 19:50:15 +0800338 status = 0;
Lee Nipperca38a812008-12-20 17:09:25 +1100339 else
Kim Phillips9c4a7962008-06-23 19:50:15 +0800340 if (!error)
341 break;
342 else
343 status = error;
344
345 dma_unmap_single(dev, request->dma_desc,
LEROY Christophe7d607c6a2015-04-17 16:32:09 +0200346 TALITOS_DESC_SIZE,
Kim Phillipse938e462009-03-29 15:53:23 +0800347 DMA_BIDIRECTIONAL);
Kim Phillips9c4a7962008-06-23 19:50:15 +0800348
349 /* copy entries so we can call callback outside lock */
350 saved_req.desc = request->desc;
351 saved_req.callback = request->callback;
352 saved_req.context = request->context;
353
354 /* release request entry in fifo */
355 smp_wmb();
356 request->desc = NULL;
357
358 /* increment fifo tail */
Kim Phillips4b9926282009-08-13 11:50:38 +1000359 priv->chan[ch].tail = (tail + 1) & (priv->fifo_len - 1);
Kim Phillips9c4a7962008-06-23 19:50:15 +0800360
Kim Phillips4b9926282009-08-13 11:50:38 +1000361 spin_unlock_irqrestore(&priv->chan[ch].tail_lock, flags);
Kim Phillipsec6644d2008-07-17 20:16:40 +0800362
Kim Phillips4b9926282009-08-13 11:50:38 +1000363 atomic_dec(&priv->chan[ch].submit_count);
Kim Phillipsec6644d2008-07-17 20:16:40 +0800364
Kim Phillips9c4a7962008-06-23 19:50:15 +0800365 saved_req.callback(dev, saved_req.desc, saved_req.context,
366 status);
367 /* channel may resume processing in single desc error case */
368 if (error && !reset_ch && status == error)
369 return;
Kim Phillips4b9926282009-08-13 11:50:38 +1000370 spin_lock_irqsave(&priv->chan[ch].tail_lock, flags);
371 tail = priv->chan[ch].tail;
Kim Phillips9c4a7962008-06-23 19:50:15 +0800372 }
373
Kim Phillips4b9926282009-08-13 11:50:38 +1000374 spin_unlock_irqrestore(&priv->chan[ch].tail_lock, flags);
Kim Phillips9c4a7962008-06-23 19:50:15 +0800375}
376
377/*
378 * process completed requests for channels that have done status
379 */
LEROY Christophedd3c0982015-04-17 16:32:13 +0200380#define DEF_TALITOS1_DONE(name, ch_done_mask) \
381static void talitos1_done_##name(unsigned long data) \
382{ \
383 struct device *dev = (struct device *)data; \
384 struct talitos_private *priv = dev_get_drvdata(dev); \
385 unsigned long flags; \
386 \
387 if (ch_done_mask & 0x10000000) \
388 flush_channel(dev, 0, 0, 0); \
389 if (priv->num_channels == 1) \
390 goto out; \
391 if (ch_done_mask & 0x40000000) \
392 flush_channel(dev, 1, 0, 0); \
393 if (ch_done_mask & 0x00010000) \
394 flush_channel(dev, 2, 0, 0); \
395 if (ch_done_mask & 0x00040000) \
396 flush_channel(dev, 3, 0, 0); \
397 \
398out: \
399 /* At this point, all completed channels have been processed */ \
400 /* Unmask done interrupts for channels completed later on. */ \
401 spin_lock_irqsave(&priv->reg_lock, flags); \
402 clrbits32(priv->reg + TALITOS_IMR, ch_done_mask); \
403 clrbits32(priv->reg + TALITOS_IMR_LO, TALITOS1_IMR_LO_INIT); \
404 spin_unlock_irqrestore(&priv->reg_lock, flags); \
405}
406
407DEF_TALITOS1_DONE(4ch, TALITOS1_ISR_4CHDONE)
408
409#define DEF_TALITOS2_DONE(name, ch_done_mask) \
410static void talitos2_done_##name(unsigned long data) \
Kim Phillipsc3e337f2011-11-21 16:13:27 +0800411{ \
412 struct device *dev = (struct device *)data; \
413 struct talitos_private *priv = dev_get_drvdata(dev); \
Horia Geanta511d63c2012-03-30 17:49:53 +0300414 unsigned long flags; \
Kim Phillipsc3e337f2011-11-21 16:13:27 +0800415 \
416 if (ch_done_mask & 1) \
417 flush_channel(dev, 0, 0, 0); \
418 if (priv->num_channels == 1) \
419 goto out; \
420 if (ch_done_mask & (1 << 2)) \
421 flush_channel(dev, 1, 0, 0); \
422 if (ch_done_mask & (1 << 4)) \
423 flush_channel(dev, 2, 0, 0); \
424 if (ch_done_mask & (1 << 6)) \
425 flush_channel(dev, 3, 0, 0); \
426 \
427out: \
428 /* At this point, all completed channels have been processed */ \
429 /* Unmask done interrupts for channels completed later on. */ \
Horia Geanta511d63c2012-03-30 17:49:53 +0300430 spin_lock_irqsave(&priv->reg_lock, flags); \
Kim Phillipsc3e337f2011-11-21 16:13:27 +0800431 setbits32(priv->reg + TALITOS_IMR, ch_done_mask); \
LEROY Christophedd3c0982015-04-17 16:32:13 +0200432 setbits32(priv->reg + TALITOS_IMR_LO, TALITOS2_IMR_LO_INIT); \
Horia Geanta511d63c2012-03-30 17:49:53 +0300433 spin_unlock_irqrestore(&priv->reg_lock, flags); \
Kim Phillips9c4a7962008-06-23 19:50:15 +0800434}
LEROY Christophedd3c0982015-04-17 16:32:13 +0200435
436DEF_TALITOS2_DONE(4ch, TALITOS2_ISR_4CHDONE)
437DEF_TALITOS2_DONE(ch0_2, TALITOS2_ISR_CH_0_2_DONE)
438DEF_TALITOS2_DONE(ch1_3, TALITOS2_ISR_CH_1_3_DONE)
Kim Phillips9c4a7962008-06-23 19:50:15 +0800439
440/*
441 * locate current (offending) descriptor
442 */
Kim Phillips3e721ae2011-10-21 15:20:28 +0200443static u32 current_desc_hdr(struct device *dev, int ch)
Kim Phillips9c4a7962008-06-23 19:50:15 +0800444{
445 struct talitos_private *priv = dev_get_drvdata(dev);
Horia Geantab62ffd82013-11-13 12:20:37 +0200446 int tail, iter;
Kim Phillips9c4a7962008-06-23 19:50:15 +0800447 dma_addr_t cur_desc;
448
Horia Geantab62ffd82013-11-13 12:20:37 +0200449 cur_desc = ((u64)in_be32(priv->chan[ch].reg + TALITOS_CDPR)) << 32;
450 cur_desc |= in_be32(priv->chan[ch].reg + TALITOS_CDPR_LO);
Kim Phillips9c4a7962008-06-23 19:50:15 +0800451
Horia Geantab62ffd82013-11-13 12:20:37 +0200452 if (!cur_desc) {
453 dev_err(dev, "CDPR is NULL, giving up search for offending descriptor\n");
454 return 0;
455 }
456
457 tail = priv->chan[ch].tail;
458
459 iter = tail;
460 while (priv->chan[ch].fifo[iter].dma_desc != cur_desc) {
461 iter = (iter + 1) & (priv->fifo_len - 1);
462 if (iter == tail) {
Kim Phillips9c4a7962008-06-23 19:50:15 +0800463 dev_err(dev, "couldn't locate current descriptor\n");
Kim Phillips3e721ae2011-10-21 15:20:28 +0200464 return 0;
Kim Phillips9c4a7962008-06-23 19:50:15 +0800465 }
466 }
467
Horia Geantab62ffd82013-11-13 12:20:37 +0200468 return priv->chan[ch].fifo[iter].desc->hdr;
Kim Phillips9c4a7962008-06-23 19:50:15 +0800469}
470
471/*
472 * user diagnostics; report root cause of error based on execution unit status
473 */
Kim Phillips3e721ae2011-10-21 15:20:28 +0200474static void report_eu_error(struct device *dev, int ch, u32 desc_hdr)
Kim Phillips9c4a7962008-06-23 19:50:15 +0800475{
476 struct talitos_private *priv = dev_get_drvdata(dev);
477 int i;
478
Kim Phillips3e721ae2011-10-21 15:20:28 +0200479 if (!desc_hdr)
Kim Phillipsad42d5f2011-11-21 16:13:27 +0800480 desc_hdr = in_be32(priv->chan[ch].reg + TALITOS_DESCBUF);
Kim Phillips3e721ae2011-10-21 15:20:28 +0200481
482 switch (desc_hdr & DESC_HDR_SEL0_MASK) {
Kim Phillips9c4a7962008-06-23 19:50:15 +0800483 case DESC_HDR_SEL0_AFEU:
484 dev_err(dev, "AFEUISR 0x%08x_%08x\n",
LEROY Christophe5fa7fa12015-04-17 16:32:11 +0200485 in_be32(priv->reg_afeu + TALITOS_EUISR),
486 in_be32(priv->reg_afeu + TALITOS_EUISR_LO));
Kim Phillips9c4a7962008-06-23 19:50:15 +0800487 break;
488 case DESC_HDR_SEL0_DEU:
489 dev_err(dev, "DEUISR 0x%08x_%08x\n",
LEROY Christophe5fa7fa12015-04-17 16:32:11 +0200490 in_be32(priv->reg_deu + TALITOS_EUISR),
491 in_be32(priv->reg_deu + TALITOS_EUISR_LO));
Kim Phillips9c4a7962008-06-23 19:50:15 +0800492 break;
493 case DESC_HDR_SEL0_MDEUA:
494 case DESC_HDR_SEL0_MDEUB:
495 dev_err(dev, "MDEUISR 0x%08x_%08x\n",
LEROY Christophe5fa7fa12015-04-17 16:32:11 +0200496 in_be32(priv->reg_mdeu + TALITOS_EUISR),
497 in_be32(priv->reg_mdeu + TALITOS_EUISR_LO));
Kim Phillips9c4a7962008-06-23 19:50:15 +0800498 break;
499 case DESC_HDR_SEL0_RNG:
500 dev_err(dev, "RNGUISR 0x%08x_%08x\n",
LEROY Christophe5fa7fa12015-04-17 16:32:11 +0200501 in_be32(priv->reg_rngu + TALITOS_ISR),
502 in_be32(priv->reg_rngu + TALITOS_ISR_LO));
Kim Phillips9c4a7962008-06-23 19:50:15 +0800503 break;
504 case DESC_HDR_SEL0_PKEU:
505 dev_err(dev, "PKEUISR 0x%08x_%08x\n",
LEROY Christophe5fa7fa12015-04-17 16:32:11 +0200506 in_be32(priv->reg_pkeu + TALITOS_EUISR),
507 in_be32(priv->reg_pkeu + TALITOS_EUISR_LO));
Kim Phillips9c4a7962008-06-23 19:50:15 +0800508 break;
509 case DESC_HDR_SEL0_AESU:
510 dev_err(dev, "AESUISR 0x%08x_%08x\n",
LEROY Christophe5fa7fa12015-04-17 16:32:11 +0200511 in_be32(priv->reg_aesu + TALITOS_EUISR),
512 in_be32(priv->reg_aesu + TALITOS_EUISR_LO));
Kim Phillips9c4a7962008-06-23 19:50:15 +0800513 break;
514 case DESC_HDR_SEL0_CRCU:
515 dev_err(dev, "CRCUISR 0x%08x_%08x\n",
LEROY Christophe5fa7fa12015-04-17 16:32:11 +0200516 in_be32(priv->reg_crcu + TALITOS_EUISR),
517 in_be32(priv->reg_crcu + TALITOS_EUISR_LO));
Kim Phillips9c4a7962008-06-23 19:50:15 +0800518 break;
519 case DESC_HDR_SEL0_KEU:
520 dev_err(dev, "KEUISR 0x%08x_%08x\n",
LEROY Christophe5fa7fa12015-04-17 16:32:11 +0200521 in_be32(priv->reg_pkeu + TALITOS_EUISR),
522 in_be32(priv->reg_pkeu + TALITOS_EUISR_LO));
Kim Phillips9c4a7962008-06-23 19:50:15 +0800523 break;
524 }
525
Kim Phillips3e721ae2011-10-21 15:20:28 +0200526 switch (desc_hdr & DESC_HDR_SEL1_MASK) {
Kim Phillips9c4a7962008-06-23 19:50:15 +0800527 case DESC_HDR_SEL1_MDEUA:
528 case DESC_HDR_SEL1_MDEUB:
529 dev_err(dev, "MDEUISR 0x%08x_%08x\n",
LEROY Christophe5fa7fa12015-04-17 16:32:11 +0200530 in_be32(priv->reg_mdeu + TALITOS_EUISR),
531 in_be32(priv->reg_mdeu + TALITOS_EUISR_LO));
Kim Phillips9c4a7962008-06-23 19:50:15 +0800532 break;
533 case DESC_HDR_SEL1_CRCU:
534 dev_err(dev, "CRCUISR 0x%08x_%08x\n",
LEROY Christophe5fa7fa12015-04-17 16:32:11 +0200535 in_be32(priv->reg_crcu + TALITOS_EUISR),
536 in_be32(priv->reg_crcu + TALITOS_EUISR_LO));
Kim Phillips9c4a7962008-06-23 19:50:15 +0800537 break;
538 }
539
540 for (i = 0; i < 8; i++)
541 dev_err(dev, "DESCBUF 0x%08x_%08x\n",
Kim Phillipsad42d5f2011-11-21 16:13:27 +0800542 in_be32(priv->chan[ch].reg + TALITOS_DESCBUF + 8*i),
543 in_be32(priv->chan[ch].reg + TALITOS_DESCBUF_LO + 8*i));
Kim Phillips9c4a7962008-06-23 19:50:15 +0800544}
545
546/*
547 * recover from error interrupts
548 */
Kim Phillips5e718a02011-12-12 14:59:12 -0600549static void talitos_error(struct device *dev, u32 isr, u32 isr_lo)
Kim Phillips9c4a7962008-06-23 19:50:15 +0800550{
Kim Phillips9c4a7962008-06-23 19:50:15 +0800551 struct talitos_private *priv = dev_get_drvdata(dev);
552 unsigned int timeout = TALITOS_TIMEOUT;
LEROY Christophedd3c0982015-04-17 16:32:13 +0200553 int ch, error, reset_dev = 0;
Horia Geant?42e8b0d2015-05-11 20:04:56 +0300554 u32 v_lo;
LEROY Christophedd3c0982015-04-17 16:32:13 +0200555 bool is_sec1 = has_ftr_sec1(priv);
556 int reset_ch = is_sec1 ? 1 : 0; /* only SEC2 supports continuation */
Kim Phillips9c4a7962008-06-23 19:50:15 +0800557
558 for (ch = 0; ch < priv->num_channels; ch++) {
559 /* skip channels without errors */
LEROY Christophedd3c0982015-04-17 16:32:13 +0200560 if (is_sec1) {
561 /* bits 29, 31, 17, 19 */
562 if (!(isr & (1 << (29 + (ch & 1) * 2 - (ch & 2) * 6))))
563 continue;
564 } else {
565 if (!(isr & (1 << (ch * 2 + 1))))
566 continue;
567 }
Kim Phillips9c4a7962008-06-23 19:50:15 +0800568
569 error = -EINVAL;
570
Kim Phillipsad42d5f2011-11-21 16:13:27 +0800571 v_lo = in_be32(priv->chan[ch].reg + TALITOS_CCPSR_LO);
Kim Phillips9c4a7962008-06-23 19:50:15 +0800572
573 if (v_lo & TALITOS_CCPSR_LO_DOF) {
574 dev_err(dev, "double fetch fifo overflow error\n");
575 error = -EAGAIN;
576 reset_ch = 1;
577 }
578 if (v_lo & TALITOS_CCPSR_LO_SOF) {
579 /* h/w dropped descriptor */
580 dev_err(dev, "single fetch fifo overflow error\n");
581 error = -EAGAIN;
582 }
583 if (v_lo & TALITOS_CCPSR_LO_MDTE)
584 dev_err(dev, "master data transfer error\n");
585 if (v_lo & TALITOS_CCPSR_LO_SGDLZ)
LEROY Christophedd3c0982015-04-17 16:32:13 +0200586 dev_err(dev, is_sec1 ? "pointeur not complete error\n"
587 : "s/g data length zero error\n");
Kim Phillips9c4a7962008-06-23 19:50:15 +0800588 if (v_lo & TALITOS_CCPSR_LO_FPZ)
LEROY Christophedd3c0982015-04-17 16:32:13 +0200589 dev_err(dev, is_sec1 ? "parity error\n"
590 : "fetch pointer zero error\n");
Kim Phillips9c4a7962008-06-23 19:50:15 +0800591 if (v_lo & TALITOS_CCPSR_LO_IDH)
592 dev_err(dev, "illegal descriptor header error\n");
593 if (v_lo & TALITOS_CCPSR_LO_IEU)
LEROY Christophedd3c0982015-04-17 16:32:13 +0200594 dev_err(dev, is_sec1 ? "static assignment error\n"
595 : "invalid exec unit error\n");
Kim Phillips9c4a7962008-06-23 19:50:15 +0800596 if (v_lo & TALITOS_CCPSR_LO_EU)
Kim Phillips3e721ae2011-10-21 15:20:28 +0200597 report_eu_error(dev, ch, current_desc_hdr(dev, ch));
LEROY Christophedd3c0982015-04-17 16:32:13 +0200598 if (!is_sec1) {
599 if (v_lo & TALITOS_CCPSR_LO_GB)
600 dev_err(dev, "gather boundary error\n");
601 if (v_lo & TALITOS_CCPSR_LO_GRL)
602 dev_err(dev, "gather return/length error\n");
603 if (v_lo & TALITOS_CCPSR_LO_SB)
604 dev_err(dev, "scatter boundary error\n");
605 if (v_lo & TALITOS_CCPSR_LO_SRL)
606 dev_err(dev, "scatter return/length error\n");
607 }
Kim Phillips9c4a7962008-06-23 19:50:15 +0800608
609 flush_channel(dev, ch, error, reset_ch);
610
611 if (reset_ch) {
612 reset_channel(dev, ch);
613 } else {
Kim Phillipsad42d5f2011-11-21 16:13:27 +0800614 setbits32(priv->chan[ch].reg + TALITOS_CCCR,
LEROY Christophedd3c0982015-04-17 16:32:13 +0200615 TALITOS2_CCCR_CONT);
Kim Phillipsad42d5f2011-11-21 16:13:27 +0800616 setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO, 0);
617 while ((in_be32(priv->chan[ch].reg + TALITOS_CCCR) &
LEROY Christophedd3c0982015-04-17 16:32:13 +0200618 TALITOS2_CCCR_CONT) && --timeout)
Kim Phillips9c4a7962008-06-23 19:50:15 +0800619 cpu_relax();
620 if (timeout == 0) {
621 dev_err(dev, "failed to restart channel %d\n",
622 ch);
623 reset_dev = 1;
624 }
625 }
626 }
LEROY Christophedd3c0982015-04-17 16:32:13 +0200627 if (reset_dev || (is_sec1 && isr & ~TALITOS1_ISR_4CHERR) ||
628 (!is_sec1 && isr & ~TALITOS2_ISR_4CHERR) || isr_lo) {
629 if (is_sec1 && (isr_lo & TALITOS1_ISR_TEA_ERR))
630 dev_err(dev, "TEA error: ISR 0x%08x_%08x\n",
631 isr, isr_lo);
632 else
633 dev_err(dev, "done overflow, internal time out, or "
634 "rngu error: ISR 0x%08x_%08x\n", isr, isr_lo);
Kim Phillips9c4a7962008-06-23 19:50:15 +0800635
636 /* purge request queues */
637 for (ch = 0; ch < priv->num_channels; ch++)
638 flush_channel(dev, ch, -EIO, 1);
639
640 /* reset and reinitialize the device */
641 init_device(dev);
642 }
643}
644
LEROY Christophedd3c0982015-04-17 16:32:13 +0200645#define DEF_TALITOS1_INTERRUPT(name, ch_done_mask, ch_err_mask, tlet) \
646static irqreturn_t talitos1_interrupt_##name(int irq, void *data) \
647{ \
648 struct device *dev = data; \
649 struct talitos_private *priv = dev_get_drvdata(dev); \
650 u32 isr, isr_lo; \
651 unsigned long flags; \
652 \
653 spin_lock_irqsave(&priv->reg_lock, flags); \
654 isr = in_be32(priv->reg + TALITOS_ISR); \
655 isr_lo = in_be32(priv->reg + TALITOS_ISR_LO); \
656 /* Acknowledge interrupt */ \
657 out_be32(priv->reg + TALITOS_ICR, isr & (ch_done_mask | ch_err_mask)); \
658 out_be32(priv->reg + TALITOS_ICR_LO, isr_lo); \
659 \
660 if (unlikely(isr & ch_err_mask || isr_lo & TALITOS1_IMR_LO_INIT)) { \
661 spin_unlock_irqrestore(&priv->reg_lock, flags); \
662 talitos_error(dev, isr & ch_err_mask, isr_lo); \
663 } \
664 else { \
665 if (likely(isr & ch_done_mask)) { \
666 /* mask further done interrupts. */ \
667 setbits32(priv->reg + TALITOS_IMR, ch_done_mask); \
668 /* done_task will unmask done interrupts at exit */ \
669 tasklet_schedule(&priv->done_task[tlet]); \
670 } \
671 spin_unlock_irqrestore(&priv->reg_lock, flags); \
672 } \
673 \
674 return (isr & (ch_done_mask | ch_err_mask) || isr_lo) ? IRQ_HANDLED : \
675 IRQ_NONE; \
676}
677
678DEF_TALITOS1_INTERRUPT(4ch, TALITOS1_ISR_4CHDONE, TALITOS1_ISR_4CHERR, 0)
679
680#define DEF_TALITOS2_INTERRUPT(name, ch_done_mask, ch_err_mask, tlet) \
681static irqreturn_t talitos2_interrupt_##name(int irq, void *data) \
Kim Phillipsc3e337f2011-11-21 16:13:27 +0800682{ \
683 struct device *dev = data; \
684 struct talitos_private *priv = dev_get_drvdata(dev); \
685 u32 isr, isr_lo; \
Horia Geanta511d63c2012-03-30 17:49:53 +0300686 unsigned long flags; \
Kim Phillipsc3e337f2011-11-21 16:13:27 +0800687 \
Horia Geanta511d63c2012-03-30 17:49:53 +0300688 spin_lock_irqsave(&priv->reg_lock, flags); \
Kim Phillipsc3e337f2011-11-21 16:13:27 +0800689 isr = in_be32(priv->reg + TALITOS_ISR); \
690 isr_lo = in_be32(priv->reg + TALITOS_ISR_LO); \
691 /* Acknowledge interrupt */ \
692 out_be32(priv->reg + TALITOS_ICR, isr & (ch_done_mask | ch_err_mask)); \
693 out_be32(priv->reg + TALITOS_ICR_LO, isr_lo); \
694 \
Horia Geanta511d63c2012-03-30 17:49:53 +0300695 if (unlikely(isr & ch_err_mask || isr_lo)) { \
696 spin_unlock_irqrestore(&priv->reg_lock, flags); \
697 talitos_error(dev, isr & ch_err_mask, isr_lo); \
698 } \
699 else { \
Kim Phillipsc3e337f2011-11-21 16:13:27 +0800700 if (likely(isr & ch_done_mask)) { \
701 /* mask further done interrupts. */ \
702 clrbits32(priv->reg + TALITOS_IMR, ch_done_mask); \
703 /* done_task will unmask done interrupts at exit */ \
704 tasklet_schedule(&priv->done_task[tlet]); \
705 } \
Horia Geanta511d63c2012-03-30 17:49:53 +0300706 spin_unlock_irqrestore(&priv->reg_lock, flags); \
707 } \
Kim Phillipsc3e337f2011-11-21 16:13:27 +0800708 \
709 return (isr & (ch_done_mask | ch_err_mask) || isr_lo) ? IRQ_HANDLED : \
710 IRQ_NONE; \
Kim Phillips9c4a7962008-06-23 19:50:15 +0800711}
LEROY Christophedd3c0982015-04-17 16:32:13 +0200712
713DEF_TALITOS2_INTERRUPT(4ch, TALITOS2_ISR_4CHDONE, TALITOS2_ISR_4CHERR, 0)
714DEF_TALITOS2_INTERRUPT(ch0_2, TALITOS2_ISR_CH_0_2_DONE, TALITOS2_ISR_CH_0_2_ERR,
715 0)
716DEF_TALITOS2_INTERRUPT(ch1_3, TALITOS2_ISR_CH_1_3_DONE, TALITOS2_ISR_CH_1_3_ERR,
717 1)
Kim Phillips9c4a7962008-06-23 19:50:15 +0800718
719/*
720 * hwrng
721 */
722static int talitos_rng_data_present(struct hwrng *rng, int wait)
723{
724 struct device *dev = (struct device *)rng->priv;
725 struct talitos_private *priv = dev_get_drvdata(dev);
726 u32 ofl;
727 int i;
728
729 for (i = 0; i < 20; i++) {
LEROY Christophe5fa7fa12015-04-17 16:32:11 +0200730 ofl = in_be32(priv->reg_rngu + TALITOS_EUSR_LO) &
Kim Phillips9c4a7962008-06-23 19:50:15 +0800731 TALITOS_RNGUSR_LO_OFL;
732 if (ofl || !wait)
733 break;
734 udelay(10);
735 }
736
737 return !!ofl;
738}
739
740static int talitos_rng_data_read(struct hwrng *rng, u32 *data)
741{
742 struct device *dev = (struct device *)rng->priv;
743 struct talitos_private *priv = dev_get_drvdata(dev);
744
745 /* rng fifo requires 64-bit accesses */
LEROY Christophe5fa7fa12015-04-17 16:32:11 +0200746 *data = in_be32(priv->reg_rngu + TALITOS_EU_FIFO);
747 *data = in_be32(priv->reg_rngu + TALITOS_EU_FIFO_LO);
Kim Phillips9c4a7962008-06-23 19:50:15 +0800748
749 return sizeof(u32);
750}
751
752static int talitos_rng_init(struct hwrng *rng)
753{
754 struct device *dev = (struct device *)rng->priv;
755 struct talitos_private *priv = dev_get_drvdata(dev);
756 unsigned int timeout = TALITOS_TIMEOUT;
757
LEROY Christophe5fa7fa12015-04-17 16:32:11 +0200758 setbits32(priv->reg_rngu + TALITOS_EURCR_LO, TALITOS_RNGURCR_LO_SR);
759 while (!(in_be32(priv->reg_rngu + TALITOS_EUSR_LO)
760 & TALITOS_RNGUSR_LO_RD)
Kim Phillips9c4a7962008-06-23 19:50:15 +0800761 && --timeout)
762 cpu_relax();
763 if (timeout == 0) {
764 dev_err(dev, "failed to reset rng hw\n");
765 return -ENODEV;
766 }
767
768 /* start generating */
LEROY Christophe5fa7fa12015-04-17 16:32:11 +0200769 setbits32(priv->reg_rngu + TALITOS_EUDSR_LO, 0);
Kim Phillips9c4a7962008-06-23 19:50:15 +0800770
771 return 0;
772}
773
774static int talitos_register_rng(struct device *dev)
775{
776 struct talitos_private *priv = dev_get_drvdata(dev);
Aaron Sierra35a3bb32015-08-05 16:52:08 -0500777 int err;
Kim Phillips9c4a7962008-06-23 19:50:15 +0800778
779 priv->rng.name = dev_driver_string(dev),
780 priv->rng.init = talitos_rng_init,
781 priv->rng.data_present = talitos_rng_data_present,
782 priv->rng.data_read = talitos_rng_data_read,
783 priv->rng.priv = (unsigned long)dev;
784
Aaron Sierra35a3bb32015-08-05 16:52:08 -0500785 err = hwrng_register(&priv->rng);
786 if (!err)
787 priv->rng_registered = true;
788
789 return err;
Kim Phillips9c4a7962008-06-23 19:50:15 +0800790}
791
792static void talitos_unregister_rng(struct device *dev)
793{
794 struct talitos_private *priv = dev_get_drvdata(dev);
795
Aaron Sierra35a3bb32015-08-05 16:52:08 -0500796 if (!priv->rng_registered)
797 return;
798
Kim Phillips9c4a7962008-06-23 19:50:15 +0800799 hwrng_unregister(&priv->rng);
Aaron Sierra35a3bb32015-08-05 16:52:08 -0500800 priv->rng_registered = false;
Kim Phillips9c4a7962008-06-23 19:50:15 +0800801}
802
803/*
804 * crypto alg
805 */
806#define TALITOS_CRA_PRIORITY 3000
Horia Geanta357fb602012-07-03 19:16:53 +0300807#define TALITOS_MAX_KEY_SIZE 96
Lee Nipper3952f172008-07-10 18:29:18 +0800808#define TALITOS_MAX_IV_LENGTH 16 /* max of AES_BLOCK_SIZE, DES3_EDE_BLOCK_SIZE */
Lee Nipper70bcaca2008-07-03 19:08:46 +0800809
Kim Phillips9c4a7962008-06-23 19:50:15 +0800810struct talitos_ctx {
811 struct device *dev;
Kim Phillips5228f0f2011-07-15 11:21:38 +0800812 int ch;
Kim Phillips9c4a7962008-06-23 19:50:15 +0800813 __be32 desc_hdr_template;
814 u8 key[TALITOS_MAX_KEY_SIZE];
Lee Nipper70bcaca2008-07-03 19:08:46 +0800815 u8 iv[TALITOS_MAX_IV_LENGTH];
Kim Phillips9c4a7962008-06-23 19:50:15 +0800816 unsigned int keylen;
817 unsigned int enckeylen;
818 unsigned int authkeylen;
Kim Phillips9c4a7962008-06-23 19:50:15 +0800819};
820
Lee Nipper497f2e62010-05-19 19:20:36 +1000821#define HASH_MAX_BLOCK_SIZE SHA512_BLOCK_SIZE
822#define TALITOS_MDEU_MAX_CONTEXT_SIZE TALITOS_MDEU_CONTEXT_SIZE_SHA384_SHA512
823
824struct talitos_ahash_req_ctx {
Kim Phillips60f208d2010-05-19 19:21:53 +1000825 u32 hw_context[TALITOS_MDEU_MAX_CONTEXT_SIZE / sizeof(u32)];
Lee Nipper497f2e62010-05-19 19:20:36 +1000826 unsigned int hw_context_size;
827 u8 buf[HASH_MAX_BLOCK_SIZE];
828 u8 bufnext[HASH_MAX_BLOCK_SIZE];
Kim Phillips60f208d2010-05-19 19:21:53 +1000829 unsigned int swinit;
Lee Nipper497f2e62010-05-19 19:20:36 +1000830 unsigned int first;
831 unsigned int last;
832 unsigned int to_hash_later;
Horia Geant?42e8b0d2015-05-11 20:04:56 +0300833 unsigned int nbuf;
Lee Nipper497f2e62010-05-19 19:20:36 +1000834 struct scatterlist bufsl[2];
835 struct scatterlist *psrc;
836};
837
Horia Geant?efc1e732016-04-21 19:24:55 +0300838struct talitos_export_state {
839 u32 hw_context[TALITOS_MDEU_MAX_CONTEXT_SIZE / sizeof(u32)];
840 u8 buf[HASH_MAX_BLOCK_SIZE];
841 unsigned int swinit;
842 unsigned int first;
843 unsigned int last;
844 unsigned int to_hash_later;
845 unsigned int nbuf;
846};
847
Lee Nipper56af8cd2009-03-29 15:50:50 +0800848static int aead_setkey(struct crypto_aead *authenc,
849 const u8 *key, unsigned int keylen)
Kim Phillips9c4a7962008-06-23 19:50:15 +0800850{
851 struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
Mathias Krausec306a982013-10-15 13:49:34 +0200852 struct crypto_authenc_keys keys;
Kim Phillips9c4a7962008-06-23 19:50:15 +0800853
Mathias Krausec306a982013-10-15 13:49:34 +0200854 if (crypto_authenc_extractkeys(&keys, key, keylen) != 0)
Kim Phillips9c4a7962008-06-23 19:50:15 +0800855 goto badkey;
856
Mathias Krausec306a982013-10-15 13:49:34 +0200857 if (keys.authkeylen + keys.enckeylen > TALITOS_MAX_KEY_SIZE)
Kim Phillips9c4a7962008-06-23 19:50:15 +0800858 goto badkey;
859
Mathias Krausec306a982013-10-15 13:49:34 +0200860 memcpy(ctx->key, keys.authkey, keys.authkeylen);
861 memcpy(&ctx->key[keys.authkeylen], keys.enckey, keys.enckeylen);
Kim Phillips9c4a7962008-06-23 19:50:15 +0800862
Mathias Krausec306a982013-10-15 13:49:34 +0200863 ctx->keylen = keys.authkeylen + keys.enckeylen;
864 ctx->enckeylen = keys.enckeylen;
865 ctx->authkeylen = keys.authkeylen;
Kim Phillips9c4a7962008-06-23 19:50:15 +0800866
867 return 0;
868
869badkey:
870 crypto_aead_set_flags(authenc, CRYPTO_TFM_RES_BAD_KEY_LEN);
871 return -EINVAL;
872}
873
874/*
Lee Nipper56af8cd2009-03-29 15:50:50 +0800875 * talitos_edesc - s/w-extended descriptor
Kim Phillips9c4a7962008-06-23 19:50:15 +0800876 * @src_nents: number of segments in input scatterlist
877 * @dst_nents: number of segments in output scatterlist
Herbert Xuaeb4c132015-07-30 17:53:22 +0800878 * @icv_ool: whether ICV is out-of-line
Horia Geanta79fd31d2012-08-02 17:16:40 +0300879 * @iv_dma: dma address of iv for checking continuity and link table
Kim Phillips9c4a7962008-06-23 19:50:15 +0800880 * @dma_len: length of dma mapped link_tbl space
LEROY Christophe6f65f6a2015-04-17 16:32:15 +0200881 * @dma_link_tbl: bus physical address of link_tbl/buf
Kim Phillips9c4a7962008-06-23 19:50:15 +0800882 * @desc: h/w descriptor
LEROY Christophe6f65f6a2015-04-17 16:32:15 +0200883 * @link_tbl: input and output h/w link tables (if {src,dst}_nents > 1) (SEC2)
884 * @buf: input and output buffeur (if {src,dst}_nents > 1) (SEC1)
Kim Phillips9c4a7962008-06-23 19:50:15 +0800885 *
886 * if decrypting (with authcheck), or either one of src_nents or dst_nents
887 * is greater than 1, an integrity check value is concatenated to the end
888 * of link_tbl data
889 */
Lee Nipper56af8cd2009-03-29 15:50:50 +0800890struct talitos_edesc {
Kim Phillips9c4a7962008-06-23 19:50:15 +0800891 int src_nents;
892 int dst_nents;
Herbert Xuaeb4c132015-07-30 17:53:22 +0800893 bool icv_ool;
Horia Geanta79fd31d2012-08-02 17:16:40 +0300894 dma_addr_t iv_dma;
Kim Phillips9c4a7962008-06-23 19:50:15 +0800895 int dma_len;
896 dma_addr_t dma_link_tbl;
897 struct talitos_desc desc;
LEROY Christophe6f65f6a2015-04-17 16:32:15 +0200898 union {
899 struct talitos_ptr link_tbl[0];
900 u8 buf[0];
901 };
Kim Phillips9c4a7962008-06-23 19:50:15 +0800902};
903
Lee Nipper4de9d0b2009-03-29 15:52:32 +0800904static void talitos_sg_unmap(struct device *dev,
905 struct talitos_edesc *edesc,
906 struct scatterlist *src,
907 struct scatterlist *dst)
908{
909 unsigned int src_nents = edesc->src_nents ? : 1;
910 unsigned int dst_nents = edesc->dst_nents ? : 1;
911
912 if (src != dst) {
LABBE Corentinb8a011d2015-09-23 13:55:25 +0200913 dma_unmap_sg(dev, src, src_nents, DMA_TO_DEVICE);
Lee Nipper4de9d0b2009-03-29 15:52:32 +0800914
Lee Nipper497f2e62010-05-19 19:20:36 +1000915 if (dst) {
LABBE Corentinb8a011d2015-09-23 13:55:25 +0200916 dma_unmap_sg(dev, dst, dst_nents, DMA_FROM_DEVICE);
Lee Nipper497f2e62010-05-19 19:20:36 +1000917 }
Lee Nipper4de9d0b2009-03-29 15:52:32 +0800918 } else
LABBE Corentinb8a011d2015-09-23 13:55:25 +0200919 dma_unmap_sg(dev, src, src_nents, DMA_BIDIRECTIONAL);
Lee Nipper4de9d0b2009-03-29 15:52:32 +0800920}
921
Kim Phillips9c4a7962008-06-23 19:50:15 +0800922static void ipsec_esp_unmap(struct device *dev,
Lee Nipper56af8cd2009-03-29 15:50:50 +0800923 struct talitos_edesc *edesc,
Kim Phillips9c4a7962008-06-23 19:50:15 +0800924 struct aead_request *areq)
925{
926 unmap_single_talitos_ptr(dev, &edesc->desc.ptr[6], DMA_FROM_DEVICE);
927 unmap_single_talitos_ptr(dev, &edesc->desc.ptr[3], DMA_TO_DEVICE);
928 unmap_single_talitos_ptr(dev, &edesc->desc.ptr[2], DMA_TO_DEVICE);
929 unmap_single_talitos_ptr(dev, &edesc->desc.ptr[0], DMA_TO_DEVICE);
930
Lee Nipper4de9d0b2009-03-29 15:52:32 +0800931 talitos_sg_unmap(dev, edesc, areq->src, areq->dst);
Kim Phillips9c4a7962008-06-23 19:50:15 +0800932
933 if (edesc->dma_len)
934 dma_unmap_single(dev, edesc->dma_link_tbl, edesc->dma_len,
935 DMA_BIDIRECTIONAL);
936}
937
938/*
939 * ipsec_esp descriptor callbacks
940 */
941static void ipsec_esp_encrypt_done(struct device *dev,
942 struct talitos_desc *desc, void *context,
943 int err)
944{
945 struct aead_request *areq = context;
Kim Phillips9c4a7962008-06-23 19:50:15 +0800946 struct crypto_aead *authenc = crypto_aead_reqtfm(areq);
Herbert Xuaeb4c132015-07-30 17:53:22 +0800947 unsigned int authsize = crypto_aead_authsize(authenc);
Kim Phillips19bbbc62009-03-29 15:53:59 +0800948 struct talitos_edesc *edesc;
Kim Phillips9c4a7962008-06-23 19:50:15 +0800949 struct scatterlist *sg;
950 void *icvdata;
951
Kim Phillips19bbbc62009-03-29 15:53:59 +0800952 edesc = container_of(desc, struct talitos_edesc, desc);
953
Kim Phillips9c4a7962008-06-23 19:50:15 +0800954 ipsec_esp_unmap(dev, edesc, areq);
955
956 /* copy the generated ICV to dst */
Herbert Xuaeb4c132015-07-30 17:53:22 +0800957 if (edesc->icv_ool) {
Kim Phillips9c4a7962008-06-23 19:50:15 +0800958 icvdata = &edesc->link_tbl[edesc->src_nents +
Herbert Xuaeb4c132015-07-30 17:53:22 +0800959 edesc->dst_nents + 2];
Kim Phillips9c4a7962008-06-23 19:50:15 +0800960 sg = sg_last(areq->dst, edesc->dst_nents);
Herbert Xuaeb4c132015-07-30 17:53:22 +0800961 memcpy((char *)sg_virt(sg) + sg->length - authsize,
962 icvdata, authsize);
Kim Phillips9c4a7962008-06-23 19:50:15 +0800963 }
964
965 kfree(edesc);
966
967 aead_request_complete(areq, err);
968}
969
Kim Phillipsfe5720e2008-10-12 20:33:14 +0800970static void ipsec_esp_decrypt_swauth_done(struct device *dev,
Kim Phillipse938e462009-03-29 15:53:23 +0800971 struct talitos_desc *desc,
972 void *context, int err)
Kim Phillips9c4a7962008-06-23 19:50:15 +0800973{
974 struct aead_request *req = context;
Kim Phillips9c4a7962008-06-23 19:50:15 +0800975 struct crypto_aead *authenc = crypto_aead_reqtfm(req);
Herbert Xuaeb4c132015-07-30 17:53:22 +0800976 unsigned int authsize = crypto_aead_authsize(authenc);
Kim Phillips19bbbc62009-03-29 15:53:59 +0800977 struct talitos_edesc *edesc;
Kim Phillips9c4a7962008-06-23 19:50:15 +0800978 struct scatterlist *sg;
Herbert Xuaeb4c132015-07-30 17:53:22 +0800979 char *oicv, *icv;
Kim Phillips9c4a7962008-06-23 19:50:15 +0800980
Kim Phillips19bbbc62009-03-29 15:53:59 +0800981 edesc = container_of(desc, struct talitos_edesc, desc);
982
Kim Phillips9c4a7962008-06-23 19:50:15 +0800983 ipsec_esp_unmap(dev, edesc, req);
984
985 if (!err) {
986 /* auth check */
Kim Phillips9c4a7962008-06-23 19:50:15 +0800987 sg = sg_last(req->dst, edesc->dst_nents ? : 1);
Herbert Xuaeb4c132015-07-30 17:53:22 +0800988 icv = (char *)sg_virt(sg) + sg->length - authsize;
989
990 if (edesc->dma_len) {
991 oicv = (char *)&edesc->link_tbl[edesc->src_nents +
992 edesc->dst_nents + 2];
993 if (edesc->icv_ool)
994 icv = oicv + authsize;
995 } else
996 oicv = (char *)&edesc->link_tbl[0];
997
David Gstir79960942015-11-15 17:14:42 +0100998 err = crypto_memneq(oicv, icv, authsize) ? -EBADMSG : 0;
Kim Phillips9c4a7962008-06-23 19:50:15 +0800999 }
1000
1001 kfree(edesc);
1002
1003 aead_request_complete(req, err);
1004}
1005
Kim Phillipsfe5720e2008-10-12 20:33:14 +08001006static void ipsec_esp_decrypt_hwauth_done(struct device *dev,
Kim Phillipse938e462009-03-29 15:53:23 +08001007 struct talitos_desc *desc,
1008 void *context, int err)
Kim Phillipsfe5720e2008-10-12 20:33:14 +08001009{
1010 struct aead_request *req = context;
Kim Phillips19bbbc62009-03-29 15:53:59 +08001011 struct talitos_edesc *edesc;
1012
1013 edesc = container_of(desc, struct talitos_edesc, desc);
Kim Phillipsfe5720e2008-10-12 20:33:14 +08001014
1015 ipsec_esp_unmap(dev, edesc, req);
1016
1017 /* check ICV auth status */
Kim Phillipse938e462009-03-29 15:53:23 +08001018 if (!err && ((desc->hdr_lo & DESC_HDR_LO_ICCR1_MASK) !=
1019 DESC_HDR_LO_ICCR1_PASS))
1020 err = -EBADMSG;
Kim Phillipsfe5720e2008-10-12 20:33:14 +08001021
1022 kfree(edesc);
1023
1024 aead_request_complete(req, err);
1025}
1026
Kim Phillips9c4a7962008-06-23 19:50:15 +08001027/*
1028 * convert scatterlist to SEC h/w link table format
1029 * stop at cryptlen bytes
1030 */
Herbert Xuaeb4c132015-07-30 17:53:22 +08001031static int sg_to_link_tbl_offset(struct scatterlist *sg, int sg_count,
1032 unsigned int offset, int cryptlen,
1033 struct talitos_ptr *link_tbl_ptr)
Kim Phillips9c4a7962008-06-23 19:50:15 +08001034{
Lee Nipper70bcaca2008-07-03 19:08:46 +08001035 int n_sg = sg_count;
Herbert Xuaeb4c132015-07-30 17:53:22 +08001036 int count = 0;
Lee Nipper70bcaca2008-07-03 19:08:46 +08001037
Herbert Xuaeb4c132015-07-30 17:53:22 +08001038 while (cryptlen && sg && n_sg--) {
1039 unsigned int len = sg_dma_len(sg);
1040
1041 if (offset >= len) {
1042 offset -= len;
1043 goto next;
1044 }
1045
1046 len -= offset;
1047
1048 if (len > cryptlen)
1049 len = cryptlen;
1050
1051 to_talitos_ptr(link_tbl_ptr + count,
1052 sg_dma_address(sg) + offset, 0);
1053 link_tbl_ptr[count].len = cpu_to_be16(len);
1054 link_tbl_ptr[count].j_extent = 0;
1055 count++;
1056 cryptlen -= len;
1057 offset = 0;
1058
1059next:
Cristian Stoica5be4d4c2015-01-20 10:06:16 +02001060 sg = sg_next(sg);
Kim Phillips9c4a7962008-06-23 19:50:15 +08001061 }
1062
Kim Phillips9c4a7962008-06-23 19:50:15 +08001063 /* tag end of link table */
Herbert Xuaeb4c132015-07-30 17:53:22 +08001064 if (count > 0)
1065 link_tbl_ptr[count - 1].j_extent = DESC_PTR_LNKTBL_RETURN;
Lee Nipper70bcaca2008-07-03 19:08:46 +08001066
Herbert Xuaeb4c132015-07-30 17:53:22 +08001067 return count;
1068}
1069
1070static inline int sg_to_link_tbl(struct scatterlist *sg, int sg_count,
1071 int cryptlen,
1072 struct talitos_ptr *link_tbl_ptr)
1073{
1074 return sg_to_link_tbl_offset(sg, sg_count, 0, cryptlen,
1075 link_tbl_ptr);
Kim Phillips9c4a7962008-06-23 19:50:15 +08001076}
1077
1078/*
1079 * fill in and submit ipsec_esp descriptor
1080 */
Lee Nipper56af8cd2009-03-29 15:50:50 +08001081static int ipsec_esp(struct talitos_edesc *edesc, struct aead_request *areq,
Herbert Xuaeb4c132015-07-30 17:53:22 +08001082 void (*callback)(struct device *dev,
1083 struct talitos_desc *desc,
1084 void *context, int error))
Kim Phillips9c4a7962008-06-23 19:50:15 +08001085{
1086 struct crypto_aead *aead = crypto_aead_reqtfm(areq);
Herbert Xuaeb4c132015-07-30 17:53:22 +08001087 unsigned int authsize = crypto_aead_authsize(aead);
Kim Phillips9c4a7962008-06-23 19:50:15 +08001088 struct talitos_ctx *ctx = crypto_aead_ctx(aead);
1089 struct device *dev = ctx->dev;
1090 struct talitos_desc *desc = &edesc->desc;
1091 unsigned int cryptlen = areq->cryptlen;
Kim Phillipse41256f2009-08-13 11:49:06 +10001092 unsigned int ivsize = crypto_aead_ivsize(aead);
Herbert Xuaeb4c132015-07-30 17:53:22 +08001093 int tbl_off = 0;
Kim Phillipsfa86a262008-07-17 20:20:06 +08001094 int sg_count, ret;
Kim Phillipsfe5720e2008-10-12 20:33:14 +08001095 int sg_link_tbl_len;
Kim Phillips9c4a7962008-06-23 19:50:15 +08001096
1097 /* hmac key */
1098 map_single_talitos_ptr(dev, &desc->ptr[0], ctx->authkeylen, &ctx->key,
LEROY Christophea2b35aa2015-04-17 16:31:57 +02001099 DMA_TO_DEVICE);
Horia Geanta79fd31d2012-08-02 17:16:40 +03001100
LABBE Corentinb8a011d2015-09-23 13:55:25 +02001101 sg_count = dma_map_sg(dev, areq->src, edesc->src_nents ?: 1,
1102 (areq->src == areq->dst) ? DMA_BIDIRECTIONAL
1103 : DMA_TO_DEVICE);
Kim Phillips9c4a7962008-06-23 19:50:15 +08001104 /* hmac data */
Herbert Xuaeb4c132015-07-30 17:53:22 +08001105 desc->ptr[1].len = cpu_to_be16(areq->assoclen);
1106 if (sg_count > 1 &&
1107 (ret = sg_to_link_tbl_offset(areq->src, sg_count, 0,
1108 areq->assoclen,
1109 &edesc->link_tbl[tbl_off])) > 1) {
Horia Geanta79fd31d2012-08-02 17:16:40 +03001110 to_talitos_ptr(&desc->ptr[1], edesc->dma_link_tbl + tbl_off *
LEROY Christophe922f9dc2015-04-17 16:32:07 +02001111 sizeof(struct talitos_ptr), 0);
Horia Geanta79fd31d2012-08-02 17:16:40 +03001112 desc->ptr[1].j_extent = DESC_PTR_LNKTBL_JUMP;
1113
Horia Geanta79fd31d2012-08-02 17:16:40 +03001114 dma_sync_single_for_device(dev, edesc->dma_link_tbl,
1115 edesc->dma_len, DMA_BIDIRECTIONAL);
Horia Geant?cd780352016-04-19 20:33:48 +03001116
1117 tbl_off += ret;
Horia Geanta79fd31d2012-08-02 17:16:40 +03001118 } else {
Herbert Xuaeb4c132015-07-30 17:53:22 +08001119 to_talitos_ptr(&desc->ptr[1], sg_dma_address(areq->src), 0);
Horia Geanta79fd31d2012-08-02 17:16:40 +03001120 desc->ptr[1].j_extent = 0;
1121 }
1122
Kim Phillips9c4a7962008-06-23 19:50:15 +08001123 /* cipher iv */
LEROY Christophe922f9dc2015-04-17 16:32:07 +02001124 to_talitos_ptr(&desc->ptr[2], edesc->iv_dma, 0);
Horia Geanta79fd31d2012-08-02 17:16:40 +03001125 desc->ptr[2].len = cpu_to_be16(ivsize);
1126 desc->ptr[2].j_extent = 0;
Kim Phillips9c4a7962008-06-23 19:50:15 +08001127
1128 /* cipher key */
1129 map_single_talitos_ptr(dev, &desc->ptr[3], ctx->enckeylen,
LEROY Christophea2b35aa2015-04-17 16:31:57 +02001130 (char *)&ctx->key + ctx->authkeylen,
Kim Phillips9c4a7962008-06-23 19:50:15 +08001131 DMA_TO_DEVICE);
1132
1133 /*
1134 * cipher in
1135 * map and adjust cipher len to aead request cryptlen.
1136 * extent is bytes of HMAC postpended to ciphertext,
1137 * typically 12 for ipsec
1138 */
1139 desc->ptr[4].len = cpu_to_be16(cryptlen);
1140 desc->ptr[4].j_extent = authsize;
1141
Herbert Xuaeb4c132015-07-30 17:53:22 +08001142 sg_link_tbl_len = cryptlen;
1143 if (edesc->desc.hdr & DESC_HDR_MODE1_MDEU_CICV)
1144 sg_link_tbl_len += authsize;
Kim Phillips9c4a7962008-06-23 19:50:15 +08001145
Horia Geant?cd780352016-04-19 20:33:48 +03001146 if (sg_count == 1) {
1147 to_talitos_ptr(&desc->ptr[4], sg_dma_address(areq->src) +
1148 areq->assoclen, 0);
1149 } else if ((ret = sg_to_link_tbl_offset(areq->src, sg_count,
1150 areq->assoclen, sg_link_tbl_len,
1151 &edesc->link_tbl[tbl_off])) >
1152 1) {
Herbert Xuaeb4c132015-07-30 17:53:22 +08001153 desc->ptr[4].j_extent |= DESC_PTR_LNKTBL_JUMP;
1154 to_talitos_ptr(&desc->ptr[4], edesc->dma_link_tbl +
1155 tbl_off *
1156 sizeof(struct talitos_ptr), 0);
1157 dma_sync_single_for_device(dev, edesc->dma_link_tbl,
1158 edesc->dma_len,
1159 DMA_BIDIRECTIONAL);
Horia Geant?cd780352016-04-19 20:33:48 +03001160 tbl_off += ret;
1161 } else {
1162 copy_talitos_ptr(&desc->ptr[4], &edesc->link_tbl[tbl_off], 0);
1163 }
Kim Phillips9c4a7962008-06-23 19:50:15 +08001164
1165 /* cipher out */
1166 desc->ptr[5].len = cpu_to_be16(cryptlen);
1167 desc->ptr[5].j_extent = authsize;
1168
Kim Phillipse938e462009-03-29 15:53:23 +08001169 if (areq->src != areq->dst)
LABBE Corentinb8a011d2015-09-23 13:55:25 +02001170 sg_count = dma_map_sg(dev, areq->dst, edesc->dst_nents ? : 1,
1171 DMA_FROM_DEVICE);
Kim Phillips9c4a7962008-06-23 19:50:15 +08001172
Herbert Xuaeb4c132015-07-30 17:53:22 +08001173 edesc->icv_ool = false;
1174
Horia Geant?cd780352016-04-19 20:33:48 +03001175 if (sg_count == 1) {
1176 to_talitos_ptr(&desc->ptr[5], sg_dma_address(areq->dst) +
1177 areq->assoclen, 0);
1178 } else if ((sg_count =
1179 sg_to_link_tbl_offset(areq->dst, sg_count,
Herbert Xuaeb4c132015-07-30 17:53:22 +08001180 areq->assoclen, cryptlen,
Horia Geant?cd780352016-04-19 20:33:48 +03001181 &edesc->link_tbl[tbl_off])) > 1) {
Horia Geanta79fd31d2012-08-02 17:16:40 +03001182 struct talitos_ptr *tbl_ptr = &edesc->link_tbl[tbl_off];
Kim Phillips9c4a7962008-06-23 19:50:15 +08001183
Kim Phillips81eb0242009-08-13 11:51:51 +10001184 to_talitos_ptr(&desc->ptr[5], edesc->dma_link_tbl +
LEROY Christophe922f9dc2015-04-17 16:32:07 +02001185 tbl_off * sizeof(struct talitos_ptr), 0);
Kim Phillipsfe5720e2008-10-12 20:33:14 +08001186
Lee Nipperf3c85bc2008-07-30 16:26:57 +08001187 /* Add an entry to the link table for ICV data */
Horia Geanta79fd31d2012-08-02 17:16:40 +03001188 tbl_ptr += sg_count - 1;
1189 tbl_ptr->j_extent = 0;
1190 tbl_ptr++;
1191 tbl_ptr->j_extent = DESC_PTR_LNKTBL_RETURN;
1192 tbl_ptr->len = cpu_to_be16(authsize);
Kim Phillips9c4a7962008-06-23 19:50:15 +08001193
1194 /* icv data follows link tables */
Horia Geanta79fd31d2012-08-02 17:16:40 +03001195 to_talitos_ptr(tbl_ptr, edesc->dma_link_tbl +
Herbert Xuaeb4c132015-07-30 17:53:22 +08001196 (edesc->src_nents + edesc->dst_nents +
1197 2) * sizeof(struct talitos_ptr) +
1198 authsize, 0);
Kim Phillips9c4a7962008-06-23 19:50:15 +08001199 desc->ptr[5].j_extent |= DESC_PTR_LNKTBL_JUMP;
1200 dma_sync_single_for_device(ctx->dev, edesc->dma_link_tbl,
1201 edesc->dma_len, DMA_BIDIRECTIONAL);
Herbert Xuaeb4c132015-07-30 17:53:22 +08001202
1203 edesc->icv_ool = true;
Horia Geant?cd780352016-04-19 20:33:48 +03001204 } else {
1205 copy_talitos_ptr(&desc->ptr[5], &edesc->link_tbl[tbl_off], 0);
1206 }
Kim Phillips9c4a7962008-06-23 19:50:15 +08001207
1208 /* iv out */
LEROY Christophea2b35aa2015-04-17 16:31:57 +02001209 map_single_talitos_ptr(dev, &desc->ptr[6], ivsize, ctx->iv,
Kim Phillips9c4a7962008-06-23 19:50:15 +08001210 DMA_FROM_DEVICE);
1211
Kim Phillips5228f0f2011-07-15 11:21:38 +08001212 ret = talitos_submit(dev, ctx->ch, desc, callback, areq);
Kim Phillipsfa86a262008-07-17 20:20:06 +08001213 if (ret != -EINPROGRESS) {
1214 ipsec_esp_unmap(dev, edesc, areq);
1215 kfree(edesc);
1216 }
1217 return ret;
Kim Phillips9c4a7962008-06-23 19:50:15 +08001218}
1219
Kim Phillips9c4a7962008-06-23 19:50:15 +08001220/*
Lee Nipper56af8cd2009-03-29 15:50:50 +08001221 * allocate and map the extended descriptor
Kim Phillips9c4a7962008-06-23 19:50:15 +08001222 */
Lee Nipper4de9d0b2009-03-29 15:52:32 +08001223static struct talitos_edesc *talitos_edesc_alloc(struct device *dev,
1224 struct scatterlist *src,
1225 struct scatterlist *dst,
Horia Geanta79fd31d2012-08-02 17:16:40 +03001226 u8 *iv,
1227 unsigned int assoclen,
Lee Nipper4de9d0b2009-03-29 15:52:32 +08001228 unsigned int cryptlen,
1229 unsigned int authsize,
Horia Geanta79fd31d2012-08-02 17:16:40 +03001230 unsigned int ivsize,
Lee Nipper4de9d0b2009-03-29 15:52:32 +08001231 int icv_stashing,
Horia Geanta62293a32013-11-28 15:11:17 +02001232 u32 cryptoflags,
1233 bool encrypt)
Kim Phillips9c4a7962008-06-23 19:50:15 +08001234{
Lee Nipper56af8cd2009-03-29 15:50:50 +08001235 struct talitos_edesc *edesc;
Herbert Xuaeb4c132015-07-30 17:53:22 +08001236 int src_nents, dst_nents, alloc_len, dma_len;
Horia Geanta79fd31d2012-08-02 17:16:40 +03001237 dma_addr_t iv_dma = 0;
Lee Nipper4de9d0b2009-03-29 15:52:32 +08001238 gfp_t flags = cryptoflags & CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL :
Kim Phillips586725f2008-07-17 20:19:18 +08001239 GFP_ATOMIC;
LEROY Christophe6f65f6a2015-04-17 16:32:15 +02001240 struct talitos_private *priv = dev_get_drvdata(dev);
1241 bool is_sec1 = has_ftr_sec1(priv);
1242 int max_len = is_sec1 ? TALITOS1_MAX_DATA_LEN : TALITOS2_MAX_DATA_LEN;
Kim Phillips9c4a7962008-06-23 19:50:15 +08001243
LEROY Christophe6f65f6a2015-04-17 16:32:15 +02001244 if (cryptlen + authsize > max_len) {
Lee Nipper4de9d0b2009-03-29 15:52:32 +08001245 dev_err(dev, "length exceeds h/w max limit\n");
Kim Phillips9c4a7962008-06-23 19:50:15 +08001246 return ERR_PTR(-EINVAL);
1247 }
1248
Horia Geanta935e99a2013-11-19 14:57:49 +02001249 if (ivsize)
Horia Geanta79fd31d2012-08-02 17:16:40 +03001250 iv_dma = dma_map_single(dev, iv, ivsize, DMA_TO_DEVICE);
1251
Horia Geanta62293a32013-11-28 15:11:17 +02001252 if (!dst || dst == src) {
LABBE Corentinb8a011d2015-09-23 13:55:25 +02001253 src_nents = sg_nents_for_len(src,
1254 assoclen + cryptlen + authsize);
Horia Geanta62293a32013-11-28 15:11:17 +02001255 src_nents = (src_nents == 1) ? 0 : src_nents;
1256 dst_nents = dst ? src_nents : 0;
1257 } else { /* dst && dst != src*/
LABBE Corentinb8a011d2015-09-23 13:55:25 +02001258 src_nents = sg_nents_for_len(src, assoclen + cryptlen +
1259 (encrypt ? 0 : authsize));
Horia Geanta62293a32013-11-28 15:11:17 +02001260 src_nents = (src_nents == 1) ? 0 : src_nents;
LABBE Corentinb8a011d2015-09-23 13:55:25 +02001261 dst_nents = sg_nents_for_len(dst, assoclen + cryptlen +
1262 (encrypt ? authsize : 0));
Horia Geanta62293a32013-11-28 15:11:17 +02001263 dst_nents = (dst_nents == 1) ? 0 : dst_nents;
Kim Phillips9c4a7962008-06-23 19:50:15 +08001264 }
1265
1266 /*
1267 * allocate space for base edesc plus the link tables,
Herbert Xuaeb4c132015-07-30 17:53:22 +08001268 * allowing for two separate entries for AD and generated ICV (+ 2),
1269 * and space for two sets of ICVs (stashed and generated)
Kim Phillips9c4a7962008-06-23 19:50:15 +08001270 */
Lee Nipper56af8cd2009-03-29 15:50:50 +08001271 alloc_len = sizeof(struct talitos_edesc);
Herbert Xuaeb4c132015-07-30 17:53:22 +08001272 if (src_nents || dst_nents) {
LEROY Christophe6f65f6a2015-04-17 16:32:15 +02001273 if (is_sec1)
Dan Carpenter608f37d2015-05-11 13:10:09 +03001274 dma_len = (src_nents ? cryptlen : 0) +
1275 (dst_nents ? cryptlen : 0);
LEROY Christophe6f65f6a2015-04-17 16:32:15 +02001276 else
Herbert Xuaeb4c132015-07-30 17:53:22 +08001277 dma_len = (src_nents + dst_nents + 2) *
1278 sizeof(struct talitos_ptr) + authsize * 2;
Kim Phillips9c4a7962008-06-23 19:50:15 +08001279 alloc_len += dma_len;
1280 } else {
1281 dma_len = 0;
Lee Nipper4de9d0b2009-03-29 15:52:32 +08001282 alloc_len += icv_stashing ? authsize : 0;
Kim Phillips9c4a7962008-06-23 19:50:15 +08001283 }
1284
Kim Phillips586725f2008-07-17 20:19:18 +08001285 edesc = kmalloc(alloc_len, GFP_DMA | flags);
Kim Phillips9c4a7962008-06-23 19:50:15 +08001286 if (!edesc) {
Horia Geanta79fd31d2012-08-02 17:16:40 +03001287 if (iv_dma)
1288 dma_unmap_single(dev, iv_dma, ivsize, DMA_TO_DEVICE);
Horia Geanta935e99a2013-11-19 14:57:49 +02001289
Lee Nipper4de9d0b2009-03-29 15:52:32 +08001290 dev_err(dev, "could not allocate edescriptor\n");
Kim Phillips9c4a7962008-06-23 19:50:15 +08001291 return ERR_PTR(-ENOMEM);
1292 }
1293
1294 edesc->src_nents = src_nents;
1295 edesc->dst_nents = dst_nents;
Horia Geanta79fd31d2012-08-02 17:16:40 +03001296 edesc->iv_dma = iv_dma;
Kim Phillips9c4a7962008-06-23 19:50:15 +08001297 edesc->dma_len = dma_len;
Lee Nipper497f2e62010-05-19 19:20:36 +10001298 if (dma_len)
1299 edesc->dma_link_tbl = dma_map_single(dev, &edesc->link_tbl[0],
1300 edesc->dma_len,
1301 DMA_BIDIRECTIONAL);
Kim Phillips9c4a7962008-06-23 19:50:15 +08001302
1303 return edesc;
1304}
1305
Horia Geanta79fd31d2012-08-02 17:16:40 +03001306static struct talitos_edesc *aead_edesc_alloc(struct aead_request *areq, u8 *iv,
Horia Geanta62293a32013-11-28 15:11:17 +02001307 int icv_stashing, bool encrypt)
Lee Nipper4de9d0b2009-03-29 15:52:32 +08001308{
1309 struct crypto_aead *authenc = crypto_aead_reqtfm(areq);
Herbert Xuaeb4c132015-07-30 17:53:22 +08001310 unsigned int authsize = crypto_aead_authsize(authenc);
Lee Nipper4de9d0b2009-03-29 15:52:32 +08001311 struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
Horia Geanta79fd31d2012-08-02 17:16:40 +03001312 unsigned int ivsize = crypto_aead_ivsize(authenc);
Lee Nipper4de9d0b2009-03-29 15:52:32 +08001313
Herbert Xuaeb4c132015-07-30 17:53:22 +08001314 return talitos_edesc_alloc(ctx->dev, areq->src, areq->dst,
Horia Geanta79fd31d2012-08-02 17:16:40 +03001315 iv, areq->assoclen, areq->cryptlen,
Herbert Xuaeb4c132015-07-30 17:53:22 +08001316 authsize, ivsize, icv_stashing,
Horia Geanta62293a32013-11-28 15:11:17 +02001317 areq->base.flags, encrypt);
Lee Nipper4de9d0b2009-03-29 15:52:32 +08001318}
1319
Lee Nipper56af8cd2009-03-29 15:50:50 +08001320static int aead_encrypt(struct aead_request *req)
Kim Phillips9c4a7962008-06-23 19:50:15 +08001321{
1322 struct crypto_aead *authenc = crypto_aead_reqtfm(req);
1323 struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
Lee Nipper56af8cd2009-03-29 15:50:50 +08001324 struct talitos_edesc *edesc;
Kim Phillips9c4a7962008-06-23 19:50:15 +08001325
1326 /* allocate extended descriptor */
Horia Geanta62293a32013-11-28 15:11:17 +02001327 edesc = aead_edesc_alloc(req, req->iv, 0, true);
Kim Phillips9c4a7962008-06-23 19:50:15 +08001328 if (IS_ERR(edesc))
1329 return PTR_ERR(edesc);
1330
1331 /* set encrypt */
Lee Nipper70bcaca2008-07-03 19:08:46 +08001332 edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_MODE0_ENCRYPT;
Kim Phillips9c4a7962008-06-23 19:50:15 +08001333
Herbert Xuaeb4c132015-07-30 17:53:22 +08001334 return ipsec_esp(edesc, req, ipsec_esp_encrypt_done);
Kim Phillips9c4a7962008-06-23 19:50:15 +08001335}
1336
Lee Nipper56af8cd2009-03-29 15:50:50 +08001337static int aead_decrypt(struct aead_request *req)
Kim Phillips9c4a7962008-06-23 19:50:15 +08001338{
1339 struct crypto_aead *authenc = crypto_aead_reqtfm(req);
Herbert Xuaeb4c132015-07-30 17:53:22 +08001340 unsigned int authsize = crypto_aead_authsize(authenc);
Kim Phillips9c4a7962008-06-23 19:50:15 +08001341 struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
Kim Phillipsfe5720e2008-10-12 20:33:14 +08001342 struct talitos_private *priv = dev_get_drvdata(ctx->dev);
Lee Nipper56af8cd2009-03-29 15:50:50 +08001343 struct talitos_edesc *edesc;
Kim Phillips9c4a7962008-06-23 19:50:15 +08001344 struct scatterlist *sg;
1345 void *icvdata;
1346
1347 req->cryptlen -= authsize;
1348
1349 /* allocate extended descriptor */
Horia Geanta62293a32013-11-28 15:11:17 +02001350 edesc = aead_edesc_alloc(req, req->iv, 1, false);
Kim Phillips9c4a7962008-06-23 19:50:15 +08001351 if (IS_ERR(edesc))
1352 return PTR_ERR(edesc);
1353
Kim Phillipsfe5720e2008-10-12 20:33:14 +08001354 if ((priv->features & TALITOS_FTR_HW_AUTH_CHECK) &&
Kim Phillipse938e462009-03-29 15:53:23 +08001355 ((!edesc->src_nents && !edesc->dst_nents) ||
1356 priv->features & TALITOS_FTR_SRC_LINK_TBL_LEN_INCLUDES_EXTENT)) {
Kim Phillips9c4a7962008-06-23 19:50:15 +08001357
Kim Phillipsfe5720e2008-10-12 20:33:14 +08001358 /* decrypt and check the ICV */
Kim Phillipse938e462009-03-29 15:53:23 +08001359 edesc->desc.hdr = ctx->desc_hdr_template |
1360 DESC_HDR_DIR_INBOUND |
Kim Phillipsfe5720e2008-10-12 20:33:14 +08001361 DESC_HDR_MODE1_MDEU_CICV;
Kim Phillips9c4a7962008-06-23 19:50:15 +08001362
Kim Phillipsfe5720e2008-10-12 20:33:14 +08001363 /* reset integrity check result bits */
1364 edesc->desc.hdr_lo = 0;
Kim Phillips9c4a7962008-06-23 19:50:15 +08001365
Herbert Xuaeb4c132015-07-30 17:53:22 +08001366 return ipsec_esp(edesc, req, ipsec_esp_decrypt_hwauth_done);
Kim Phillipsfe5720e2008-10-12 20:33:14 +08001367 }
Kim Phillipse938e462009-03-29 15:53:23 +08001368
1369 /* Have to check the ICV with software */
1370 edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_DIR_INBOUND;
1371
1372 /* stash incoming ICV for later cmp with ICV generated by the h/w */
1373 if (edesc->dma_len)
Herbert Xuaeb4c132015-07-30 17:53:22 +08001374 icvdata = (char *)&edesc->link_tbl[edesc->src_nents +
1375 edesc->dst_nents + 2];
Kim Phillipse938e462009-03-29 15:53:23 +08001376 else
1377 icvdata = &edesc->link_tbl[0];
1378
1379 sg = sg_last(req->src, edesc->src_nents ? : 1);
1380
Herbert Xuaeb4c132015-07-30 17:53:22 +08001381 memcpy(icvdata, (char *)sg_virt(sg) + sg->length - authsize, authsize);
Kim Phillipse938e462009-03-29 15:53:23 +08001382
Herbert Xuaeb4c132015-07-30 17:53:22 +08001383 return ipsec_esp(edesc, req, ipsec_esp_decrypt_swauth_done);
Kim Phillips9c4a7962008-06-23 19:50:15 +08001384}
1385
Lee Nipper4de9d0b2009-03-29 15:52:32 +08001386static int ablkcipher_setkey(struct crypto_ablkcipher *cipher,
1387 const u8 *key, unsigned int keylen)
1388{
1389 struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher);
Lee Nipper4de9d0b2009-03-29 15:52:32 +08001390
1391 memcpy(&ctx->key, key, keylen);
1392 ctx->keylen = keylen;
1393
1394 return 0;
Lee Nipper4de9d0b2009-03-29 15:52:32 +08001395}
1396
LEROY Christophe032d1972015-04-17 16:31:51 +02001397static void unmap_sg_talitos_ptr(struct device *dev, struct scatterlist *src,
1398 struct scatterlist *dst, unsigned int len,
1399 struct talitos_edesc *edesc)
1400{
LEROY Christophe6f65f6a2015-04-17 16:32:15 +02001401 struct talitos_private *priv = dev_get_drvdata(dev);
1402 bool is_sec1 = has_ftr_sec1(priv);
1403
1404 if (is_sec1) {
1405 if (!edesc->src_nents) {
1406 dma_unmap_sg(dev, src, 1,
1407 dst != src ? DMA_TO_DEVICE
1408 : DMA_BIDIRECTIONAL);
1409 }
1410 if (dst && edesc->dst_nents) {
1411 dma_sync_single_for_device(dev,
1412 edesc->dma_link_tbl + len,
1413 len, DMA_FROM_DEVICE);
1414 sg_copy_from_buffer(dst, edesc->dst_nents ? : 1,
1415 edesc->buf + len, len);
1416 } else if (dst && dst != src) {
1417 dma_unmap_sg(dev, dst, 1, DMA_FROM_DEVICE);
1418 }
1419 } else {
1420 talitos_sg_unmap(dev, edesc, src, dst);
1421 }
LEROY Christophe032d1972015-04-17 16:31:51 +02001422}
1423
Lee Nipper4de9d0b2009-03-29 15:52:32 +08001424static void common_nonsnoop_unmap(struct device *dev,
1425 struct talitos_edesc *edesc,
1426 struct ablkcipher_request *areq)
1427{
1428 unmap_single_talitos_ptr(dev, &edesc->desc.ptr[5], DMA_FROM_DEVICE);
LEROY Christophe032d1972015-04-17 16:31:51 +02001429
1430 unmap_sg_talitos_ptr(dev, areq->src, areq->dst, areq->nbytes, edesc);
Lee Nipper4de9d0b2009-03-29 15:52:32 +08001431 unmap_single_talitos_ptr(dev, &edesc->desc.ptr[2], DMA_TO_DEVICE);
1432 unmap_single_talitos_ptr(dev, &edesc->desc.ptr[1], DMA_TO_DEVICE);
1433
Lee Nipper4de9d0b2009-03-29 15:52:32 +08001434 if (edesc->dma_len)
1435 dma_unmap_single(dev, edesc->dma_link_tbl, edesc->dma_len,
1436 DMA_BIDIRECTIONAL);
1437}
1438
1439static void ablkcipher_done(struct device *dev,
1440 struct talitos_desc *desc, void *context,
1441 int err)
1442{
1443 struct ablkcipher_request *areq = context;
Kim Phillips19bbbc62009-03-29 15:53:59 +08001444 struct talitos_edesc *edesc;
1445
1446 edesc = container_of(desc, struct talitos_edesc, desc);
Lee Nipper4de9d0b2009-03-29 15:52:32 +08001447
1448 common_nonsnoop_unmap(dev, edesc, areq);
1449
1450 kfree(edesc);
1451
1452 areq->base.complete(&areq->base, err);
1453}
1454
LEROY Christophe032d1972015-04-17 16:31:51 +02001455int map_sg_in_talitos_ptr(struct device *dev, struct scatterlist *src,
1456 unsigned int len, struct talitos_edesc *edesc,
1457 enum dma_data_direction dir, struct talitos_ptr *ptr)
1458{
1459 int sg_count;
LEROY Christophe922f9dc2015-04-17 16:32:07 +02001460 struct talitos_private *priv = dev_get_drvdata(dev);
1461 bool is_sec1 = has_ftr_sec1(priv);
LEROY Christophe032d1972015-04-17 16:31:51 +02001462
LEROY Christophe922f9dc2015-04-17 16:32:07 +02001463 to_talitos_ptr_len(ptr, len, is_sec1);
LEROY Christophe032d1972015-04-17 16:31:51 +02001464
LEROY Christophe6f65f6a2015-04-17 16:32:15 +02001465 if (is_sec1) {
1466 sg_count = edesc->src_nents ? : 1;
LEROY Christophe032d1972015-04-17 16:31:51 +02001467
LEROY Christophe6f65f6a2015-04-17 16:32:15 +02001468 if (sg_count == 1) {
1469 dma_map_sg(dev, src, 1, dir);
LEROY Christophe922f9dc2015-04-17 16:32:07 +02001470 to_talitos_ptr(ptr, sg_dma_address(src), is_sec1);
LEROY Christophe6f65f6a2015-04-17 16:32:15 +02001471 } else {
1472 sg_copy_to_buffer(src, sg_count, edesc->buf, len);
1473 to_talitos_ptr(ptr, edesc->dma_link_tbl, is_sec1);
1474 dma_sync_single_for_device(dev, edesc->dma_link_tbl,
1475 len, DMA_TO_DEVICE);
1476 }
1477 } else {
1478 to_talitos_ptr_extent_clear(ptr, is_sec1);
1479
LABBE Corentinb8a011d2015-09-23 13:55:25 +02001480 sg_count = dma_map_sg(dev, src, edesc->src_nents ? : 1, dir);
LEROY Christophe6f65f6a2015-04-17 16:32:15 +02001481
1482 if (sg_count == 1) {
1483 to_talitos_ptr(ptr, sg_dma_address(src), is_sec1);
1484 } else {
1485 sg_count = sg_to_link_tbl(src, sg_count, len,
1486 &edesc->link_tbl[0]);
1487 if (sg_count > 1) {
1488 to_talitos_ptr(ptr, edesc->dma_link_tbl, 0);
1489 ptr->j_extent |= DESC_PTR_LNKTBL_JUMP;
1490 dma_sync_single_for_device(dev,
1491 edesc->dma_link_tbl,
1492 edesc->dma_len,
1493 DMA_BIDIRECTIONAL);
1494 } else {
1495 /* Only one segment now, so no link tbl needed*/
1496 to_talitos_ptr(ptr, sg_dma_address(src),
1497 is_sec1);
1498 }
LEROY Christophe032d1972015-04-17 16:31:51 +02001499 }
1500 }
1501 return sg_count;
1502}
1503
1504void map_sg_out_talitos_ptr(struct device *dev, struct scatterlist *dst,
1505 unsigned int len, struct talitos_edesc *edesc,
1506 enum dma_data_direction dir,
1507 struct talitos_ptr *ptr, int sg_count)
1508{
LEROY Christophe922f9dc2015-04-17 16:32:07 +02001509 struct talitos_private *priv = dev_get_drvdata(dev);
1510 bool is_sec1 = has_ftr_sec1(priv);
1511
LEROY Christophe032d1972015-04-17 16:31:51 +02001512 if (dir != DMA_NONE)
LABBE Corentinb8a011d2015-09-23 13:55:25 +02001513 sg_count = dma_map_sg(dev, dst, edesc->dst_nents ? : 1, dir);
LEROY Christophe032d1972015-04-17 16:31:51 +02001514
LEROY Christophe6f65f6a2015-04-17 16:32:15 +02001515 to_talitos_ptr_len(ptr, len, is_sec1);
LEROY Christophe032d1972015-04-17 16:31:51 +02001516
LEROY Christophe6f65f6a2015-04-17 16:32:15 +02001517 if (is_sec1) {
1518 if (sg_count == 1) {
1519 if (dir != DMA_NONE)
1520 dma_map_sg(dev, dst, 1, dir);
1521 to_talitos_ptr(ptr, sg_dma_address(dst), is_sec1);
1522 } else {
1523 to_talitos_ptr(ptr, edesc->dma_link_tbl + len, is_sec1);
1524 dma_sync_single_for_device(dev,
1525 edesc->dma_link_tbl + len,
1526 len, DMA_FROM_DEVICE);
1527 }
1528 } else {
1529 to_talitos_ptr_extent_clear(ptr, is_sec1);
1530
1531 if (sg_count == 1) {
1532 to_talitos_ptr(ptr, sg_dma_address(dst), is_sec1);
1533 } else {
1534 struct talitos_ptr *link_tbl_ptr =
1535 &edesc->link_tbl[edesc->src_nents + 1];
1536
1537 to_talitos_ptr(ptr, edesc->dma_link_tbl +
1538 (edesc->src_nents + 1) *
1539 sizeof(struct talitos_ptr), 0);
1540 ptr->j_extent |= DESC_PTR_LNKTBL_JUMP;
Horia Geant?42e8b0d2015-05-11 20:04:56 +03001541 sg_to_link_tbl(dst, sg_count, len, link_tbl_ptr);
LEROY Christophe6f65f6a2015-04-17 16:32:15 +02001542 dma_sync_single_for_device(dev, edesc->dma_link_tbl,
1543 edesc->dma_len,
1544 DMA_BIDIRECTIONAL);
1545 }
LEROY Christophe032d1972015-04-17 16:31:51 +02001546 }
1547}
1548
Lee Nipper4de9d0b2009-03-29 15:52:32 +08001549static int common_nonsnoop(struct talitos_edesc *edesc,
1550 struct ablkcipher_request *areq,
Lee Nipper4de9d0b2009-03-29 15:52:32 +08001551 void (*callback) (struct device *dev,
1552 struct talitos_desc *desc,
1553 void *context, int error))
1554{
1555 struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(areq);
1556 struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher);
1557 struct device *dev = ctx->dev;
1558 struct talitos_desc *desc = &edesc->desc;
1559 unsigned int cryptlen = areq->nbytes;
Horia Geanta79fd31d2012-08-02 17:16:40 +03001560 unsigned int ivsize = crypto_ablkcipher_ivsize(cipher);
Lee Nipper4de9d0b2009-03-29 15:52:32 +08001561 int sg_count, ret;
LEROY Christophe922f9dc2015-04-17 16:32:07 +02001562 struct talitos_private *priv = dev_get_drvdata(dev);
1563 bool is_sec1 = has_ftr_sec1(priv);
Lee Nipper4de9d0b2009-03-29 15:52:32 +08001564
1565 /* first DWORD empty */
LEROY Christophe2529bc32015-04-17 16:31:49 +02001566 desc->ptr[0] = zero_entry;
Lee Nipper4de9d0b2009-03-29 15:52:32 +08001567
1568 /* cipher iv */
LEROY Christophe922f9dc2015-04-17 16:32:07 +02001569 to_talitos_ptr(&desc->ptr[1], edesc->iv_dma, is_sec1);
1570 to_talitos_ptr_len(&desc->ptr[1], ivsize, is_sec1);
1571 to_talitos_ptr_extent_clear(&desc->ptr[1], is_sec1);
Lee Nipper4de9d0b2009-03-29 15:52:32 +08001572
1573 /* cipher key */
1574 map_single_talitos_ptr(dev, &desc->ptr[2], ctx->keylen,
LEROY Christophea2b35aa2015-04-17 16:31:57 +02001575 (char *)&ctx->key, DMA_TO_DEVICE);
Lee Nipper4de9d0b2009-03-29 15:52:32 +08001576
1577 /*
1578 * cipher in
1579 */
LEROY Christophe032d1972015-04-17 16:31:51 +02001580 sg_count = map_sg_in_talitos_ptr(dev, areq->src, cryptlen, edesc,
1581 (areq->src == areq->dst) ?
1582 DMA_BIDIRECTIONAL : DMA_TO_DEVICE,
1583 &desc->ptr[3]);
Lee Nipper4de9d0b2009-03-29 15:52:32 +08001584
1585 /* cipher out */
LEROY Christophe032d1972015-04-17 16:31:51 +02001586 map_sg_out_talitos_ptr(dev, areq->dst, cryptlen, edesc,
1587 (areq->src == areq->dst) ? DMA_NONE
1588 : DMA_FROM_DEVICE,
1589 &desc->ptr[4], sg_count);
Lee Nipper4de9d0b2009-03-29 15:52:32 +08001590
1591 /* iv out */
LEROY Christophea2b35aa2015-04-17 16:31:57 +02001592 map_single_talitos_ptr(dev, &desc->ptr[5], ivsize, ctx->iv,
Lee Nipper4de9d0b2009-03-29 15:52:32 +08001593 DMA_FROM_DEVICE);
1594
1595 /* last DWORD empty */
LEROY Christophe2529bc32015-04-17 16:31:49 +02001596 desc->ptr[6] = zero_entry;
Lee Nipper4de9d0b2009-03-29 15:52:32 +08001597
Kim Phillips5228f0f2011-07-15 11:21:38 +08001598 ret = talitos_submit(dev, ctx->ch, desc, callback, areq);
Lee Nipper4de9d0b2009-03-29 15:52:32 +08001599 if (ret != -EINPROGRESS) {
1600 common_nonsnoop_unmap(dev, edesc, areq);
1601 kfree(edesc);
1602 }
1603 return ret;
1604}
1605
Kim Phillipse938e462009-03-29 15:53:23 +08001606static struct talitos_edesc *ablkcipher_edesc_alloc(struct ablkcipher_request *
Horia Geanta62293a32013-11-28 15:11:17 +02001607 areq, bool encrypt)
Lee Nipper4de9d0b2009-03-29 15:52:32 +08001608{
1609 struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(areq);
1610 struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher);
Horia Geanta79fd31d2012-08-02 17:16:40 +03001611 unsigned int ivsize = crypto_ablkcipher_ivsize(cipher);
Lee Nipper4de9d0b2009-03-29 15:52:32 +08001612
Herbert Xuaeb4c132015-07-30 17:53:22 +08001613 return talitos_edesc_alloc(ctx->dev, areq->src, areq->dst,
Horia Geanta79fd31d2012-08-02 17:16:40 +03001614 areq->info, 0, areq->nbytes, 0, ivsize, 0,
Horia Geanta62293a32013-11-28 15:11:17 +02001615 areq->base.flags, encrypt);
Lee Nipper4de9d0b2009-03-29 15:52:32 +08001616}
1617
1618static int ablkcipher_encrypt(struct ablkcipher_request *areq)
1619{
1620 struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(areq);
1621 struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher);
1622 struct talitos_edesc *edesc;
1623
1624 /* allocate extended descriptor */
Horia Geanta62293a32013-11-28 15:11:17 +02001625 edesc = ablkcipher_edesc_alloc(areq, true);
Lee Nipper4de9d0b2009-03-29 15:52:32 +08001626 if (IS_ERR(edesc))
1627 return PTR_ERR(edesc);
1628
1629 /* set encrypt */
1630 edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_MODE0_ENCRYPT;
1631
Kim Phillipsfebec542011-07-15 11:21:39 +08001632 return common_nonsnoop(edesc, areq, ablkcipher_done);
Lee Nipper4de9d0b2009-03-29 15:52:32 +08001633}
1634
1635static int ablkcipher_decrypt(struct ablkcipher_request *areq)
1636{
1637 struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(areq);
1638 struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher);
1639 struct talitos_edesc *edesc;
1640
1641 /* allocate extended descriptor */
Horia Geanta62293a32013-11-28 15:11:17 +02001642 edesc = ablkcipher_edesc_alloc(areq, false);
Lee Nipper4de9d0b2009-03-29 15:52:32 +08001643 if (IS_ERR(edesc))
1644 return PTR_ERR(edesc);
1645
1646 edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_DIR_INBOUND;
1647
Kim Phillipsfebec542011-07-15 11:21:39 +08001648 return common_nonsnoop(edesc, areq, ablkcipher_done);
Lee Nipper4de9d0b2009-03-29 15:52:32 +08001649}
1650
Lee Nipper497f2e62010-05-19 19:20:36 +10001651static void common_nonsnoop_hash_unmap(struct device *dev,
1652 struct talitos_edesc *edesc,
1653 struct ahash_request *areq)
1654{
1655 struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
LEROY Christophe922f9dc2015-04-17 16:32:07 +02001656 struct talitos_private *priv = dev_get_drvdata(dev);
1657 bool is_sec1 = has_ftr_sec1(priv);
Lee Nipper497f2e62010-05-19 19:20:36 +10001658
1659 unmap_single_talitos_ptr(dev, &edesc->desc.ptr[5], DMA_FROM_DEVICE);
1660
LEROY Christophe032d1972015-04-17 16:31:51 +02001661 unmap_sg_talitos_ptr(dev, req_ctx->psrc, NULL, 0, edesc);
1662
Lee Nipper497f2e62010-05-19 19:20:36 +10001663 /* When using hashctx-in, must unmap it. */
LEROY Christophe922f9dc2015-04-17 16:32:07 +02001664 if (from_talitos_ptr_len(&edesc->desc.ptr[1], is_sec1))
Lee Nipper497f2e62010-05-19 19:20:36 +10001665 unmap_single_talitos_ptr(dev, &edesc->desc.ptr[1],
1666 DMA_TO_DEVICE);
1667
LEROY Christophe922f9dc2015-04-17 16:32:07 +02001668 if (from_talitos_ptr_len(&edesc->desc.ptr[2], is_sec1))
Lee Nipper497f2e62010-05-19 19:20:36 +10001669 unmap_single_talitos_ptr(dev, &edesc->desc.ptr[2],
1670 DMA_TO_DEVICE);
1671
Lee Nipper497f2e62010-05-19 19:20:36 +10001672 if (edesc->dma_len)
1673 dma_unmap_single(dev, edesc->dma_link_tbl, edesc->dma_len,
1674 DMA_BIDIRECTIONAL);
1675
1676}
1677
1678static void ahash_done(struct device *dev,
1679 struct talitos_desc *desc, void *context,
1680 int err)
1681{
1682 struct ahash_request *areq = context;
1683 struct talitos_edesc *edesc =
1684 container_of(desc, struct talitos_edesc, desc);
1685 struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
1686
1687 if (!req_ctx->last && req_ctx->to_hash_later) {
1688 /* Position any partial block for next update/final/finup */
1689 memcpy(req_ctx->buf, req_ctx->bufnext, req_ctx->to_hash_later);
Lee Nipper5e833bc2010-06-16 15:29:15 +10001690 req_ctx->nbuf = req_ctx->to_hash_later;
Lee Nipper497f2e62010-05-19 19:20:36 +10001691 }
1692 common_nonsnoop_hash_unmap(dev, edesc, areq);
1693
1694 kfree(edesc);
1695
1696 areq->base.complete(&areq->base, err);
1697}
1698
LEROY Christophe2d029052015-04-17 16:32:18 +02001699/*
1700 * SEC1 doesn't like hashing of 0 sized message, so we do the padding
1701 * ourself and submit a padded block
1702 */
1703void talitos_handle_buggy_hash(struct talitos_ctx *ctx,
1704 struct talitos_edesc *edesc,
1705 struct talitos_ptr *ptr)
1706{
1707 static u8 padded_hash[64] = {
1708 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1709 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1710 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1711 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1712 };
1713
1714 pr_err_once("Bug in SEC1, padding ourself\n");
1715 edesc->desc.hdr &= ~DESC_HDR_MODE0_MDEU_PAD;
1716 map_single_talitos_ptr(ctx->dev, ptr, sizeof(padded_hash),
1717 (char *)padded_hash, DMA_TO_DEVICE);
1718}
1719
Lee Nipper497f2e62010-05-19 19:20:36 +10001720static int common_nonsnoop_hash(struct talitos_edesc *edesc,
1721 struct ahash_request *areq, unsigned int length,
1722 void (*callback) (struct device *dev,
1723 struct talitos_desc *desc,
1724 void *context, int error))
1725{
1726 struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
1727 struct talitos_ctx *ctx = crypto_ahash_ctx(tfm);
1728 struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
1729 struct device *dev = ctx->dev;
1730 struct talitos_desc *desc = &edesc->desc;
LEROY Christophe032d1972015-04-17 16:31:51 +02001731 int ret;
LEROY Christophe922f9dc2015-04-17 16:32:07 +02001732 struct talitos_private *priv = dev_get_drvdata(dev);
1733 bool is_sec1 = has_ftr_sec1(priv);
Lee Nipper497f2e62010-05-19 19:20:36 +10001734
1735 /* first DWORD empty */
1736 desc->ptr[0] = zero_entry;
1737
Kim Phillips60f208d2010-05-19 19:21:53 +10001738 /* hash context in */
1739 if (!req_ctx->first || req_ctx->swinit) {
Lee Nipper497f2e62010-05-19 19:20:36 +10001740 map_single_talitos_ptr(dev, &desc->ptr[1],
1741 req_ctx->hw_context_size,
LEROY Christophea2b35aa2015-04-17 16:31:57 +02001742 (char *)req_ctx->hw_context,
Lee Nipper497f2e62010-05-19 19:20:36 +10001743 DMA_TO_DEVICE);
Kim Phillips60f208d2010-05-19 19:21:53 +10001744 req_ctx->swinit = 0;
Lee Nipper497f2e62010-05-19 19:20:36 +10001745 } else {
1746 desc->ptr[1] = zero_entry;
1747 /* Indicate next op is not the first. */
1748 req_ctx->first = 0;
1749 }
1750
1751 /* HMAC key */
1752 if (ctx->keylen)
1753 map_single_talitos_ptr(dev, &desc->ptr[2], ctx->keylen,
LEROY Christophea2b35aa2015-04-17 16:31:57 +02001754 (char *)&ctx->key, DMA_TO_DEVICE);
Lee Nipper497f2e62010-05-19 19:20:36 +10001755 else
1756 desc->ptr[2] = zero_entry;
1757
1758 /*
1759 * data in
1760 */
LEROY Christophe032d1972015-04-17 16:31:51 +02001761 map_sg_in_talitos_ptr(dev, req_ctx->psrc, length, edesc,
1762 DMA_TO_DEVICE, &desc->ptr[3]);
Lee Nipper497f2e62010-05-19 19:20:36 +10001763
1764 /* fifth DWORD empty */
1765 desc->ptr[4] = zero_entry;
1766
1767 /* hash/HMAC out -or- hash context out */
1768 if (req_ctx->last)
1769 map_single_talitos_ptr(dev, &desc->ptr[5],
1770 crypto_ahash_digestsize(tfm),
LEROY Christophea2b35aa2015-04-17 16:31:57 +02001771 areq->result, DMA_FROM_DEVICE);
Lee Nipper497f2e62010-05-19 19:20:36 +10001772 else
1773 map_single_talitos_ptr(dev, &desc->ptr[5],
1774 req_ctx->hw_context_size,
LEROY Christophea2b35aa2015-04-17 16:31:57 +02001775 req_ctx->hw_context, DMA_FROM_DEVICE);
Lee Nipper497f2e62010-05-19 19:20:36 +10001776
1777 /* last DWORD empty */
1778 desc->ptr[6] = zero_entry;
1779
LEROY Christophe2d029052015-04-17 16:32:18 +02001780 if (is_sec1 && from_talitos_ptr_len(&desc->ptr[3], true) == 0)
1781 talitos_handle_buggy_hash(ctx, edesc, &desc->ptr[3]);
1782
Kim Phillips5228f0f2011-07-15 11:21:38 +08001783 ret = talitos_submit(dev, ctx->ch, desc, callback, areq);
Lee Nipper497f2e62010-05-19 19:20:36 +10001784 if (ret != -EINPROGRESS) {
1785 common_nonsnoop_hash_unmap(dev, edesc, areq);
1786 kfree(edesc);
1787 }
1788 return ret;
1789}
1790
1791static struct talitos_edesc *ahash_edesc_alloc(struct ahash_request *areq,
1792 unsigned int nbytes)
1793{
1794 struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
1795 struct talitos_ctx *ctx = crypto_ahash_ctx(tfm);
1796 struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
1797
Herbert Xuaeb4c132015-07-30 17:53:22 +08001798 return talitos_edesc_alloc(ctx->dev, req_ctx->psrc, NULL, NULL, 0,
Horia Geanta62293a32013-11-28 15:11:17 +02001799 nbytes, 0, 0, 0, areq->base.flags, false);
Lee Nipper497f2e62010-05-19 19:20:36 +10001800}
1801
1802static int ahash_init(struct ahash_request *areq)
1803{
1804 struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
1805 struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
1806
1807 /* Initialize the context */
Lee Nipper5e833bc2010-06-16 15:29:15 +10001808 req_ctx->nbuf = 0;
Kim Phillips60f208d2010-05-19 19:21:53 +10001809 req_ctx->first = 1; /* first indicates h/w must init its context */
1810 req_ctx->swinit = 0; /* assume h/w init of context */
Lee Nipper497f2e62010-05-19 19:20:36 +10001811 req_ctx->hw_context_size =
1812 (crypto_ahash_digestsize(tfm) <= SHA256_DIGEST_SIZE)
1813 ? TALITOS_MDEU_CONTEXT_SIZE_MD5_SHA1_SHA256
1814 : TALITOS_MDEU_CONTEXT_SIZE_SHA384_SHA512;
1815
1816 return 0;
1817}
1818
Kim Phillips60f208d2010-05-19 19:21:53 +10001819/*
1820 * on h/w without explicit sha224 support, we initialize h/w context
1821 * manually with sha224 constants, and tell it to run sha256.
1822 */
1823static int ahash_init_sha224_swinit(struct ahash_request *areq)
1824{
1825 struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
1826
1827 ahash_init(areq);
1828 req_ctx->swinit = 1;/* prevent h/w initting context with sha256 values*/
1829
Kim Phillipsa7524472010-09-23 15:56:38 +08001830 req_ctx->hw_context[0] = SHA224_H0;
1831 req_ctx->hw_context[1] = SHA224_H1;
1832 req_ctx->hw_context[2] = SHA224_H2;
1833 req_ctx->hw_context[3] = SHA224_H3;
1834 req_ctx->hw_context[4] = SHA224_H4;
1835 req_ctx->hw_context[5] = SHA224_H5;
1836 req_ctx->hw_context[6] = SHA224_H6;
1837 req_ctx->hw_context[7] = SHA224_H7;
Kim Phillips60f208d2010-05-19 19:21:53 +10001838
1839 /* init 64-bit count */
1840 req_ctx->hw_context[8] = 0;
1841 req_ctx->hw_context[9] = 0;
1842
1843 return 0;
1844}
1845
Lee Nipper497f2e62010-05-19 19:20:36 +10001846static int ahash_process_req(struct ahash_request *areq, unsigned int nbytes)
1847{
1848 struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
1849 struct talitos_ctx *ctx = crypto_ahash_ctx(tfm);
1850 struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
1851 struct talitos_edesc *edesc;
1852 unsigned int blocksize =
1853 crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm));
1854 unsigned int nbytes_to_hash;
1855 unsigned int to_hash_later;
Lee Nipper5e833bc2010-06-16 15:29:15 +10001856 unsigned int nsg;
Lee Nipper497f2e62010-05-19 19:20:36 +10001857
Lee Nipper5e833bc2010-06-16 15:29:15 +10001858 if (!req_ctx->last && (nbytes + req_ctx->nbuf <= blocksize)) {
1859 /* Buffer up to one whole block */
Lee Nipper497f2e62010-05-19 19:20:36 +10001860 sg_copy_to_buffer(areq->src,
LABBE Corentinb8a011d2015-09-23 13:55:25 +02001861 sg_nents_for_len(areq->src, nbytes),
Lee Nipper5e833bc2010-06-16 15:29:15 +10001862 req_ctx->buf + req_ctx->nbuf, nbytes);
1863 req_ctx->nbuf += nbytes;
Lee Nipper497f2e62010-05-19 19:20:36 +10001864 return 0;
1865 }
1866
Lee Nipper5e833bc2010-06-16 15:29:15 +10001867 /* At least (blocksize + 1) bytes are available to hash */
1868 nbytes_to_hash = nbytes + req_ctx->nbuf;
1869 to_hash_later = nbytes_to_hash & (blocksize - 1);
1870
1871 if (req_ctx->last)
1872 to_hash_later = 0;
1873 else if (to_hash_later)
1874 /* There is a partial block. Hash the full block(s) now */
1875 nbytes_to_hash -= to_hash_later;
1876 else {
1877 /* Keep one block buffered */
1878 nbytes_to_hash -= blocksize;
1879 to_hash_later = blocksize;
1880 }
1881
1882 /* Chain in any previously buffered data */
1883 if (req_ctx->nbuf) {
1884 nsg = (req_ctx->nbuf < nbytes_to_hash) ? 2 : 1;
1885 sg_init_table(req_ctx->bufsl, nsg);
1886 sg_set_buf(req_ctx->bufsl, req_ctx->buf, req_ctx->nbuf);
1887 if (nsg > 1)
Dan Williamsc56f6d12015-08-07 18:15:13 +02001888 sg_chain(req_ctx->bufsl, 2, areq->src);
Lee Nipper497f2e62010-05-19 19:20:36 +10001889 req_ctx->psrc = req_ctx->bufsl;
Lee Nipper5e833bc2010-06-16 15:29:15 +10001890 } else
Lee Nipper497f2e62010-05-19 19:20:36 +10001891 req_ctx->psrc = areq->src;
Lee Nipper497f2e62010-05-19 19:20:36 +10001892
Lee Nipper5e833bc2010-06-16 15:29:15 +10001893 if (to_hash_later) {
LABBE Corentinb8a011d2015-09-23 13:55:25 +02001894 int nents = sg_nents_for_len(areq->src, nbytes);
Akinobu Mitad0525722013-07-08 16:01:55 -07001895 sg_pcopy_to_buffer(areq->src, nents,
Lee Nipper5e833bc2010-06-16 15:29:15 +10001896 req_ctx->bufnext,
1897 to_hash_later,
1898 nbytes - to_hash_later);
Lee Nipper497f2e62010-05-19 19:20:36 +10001899 }
Lee Nipper5e833bc2010-06-16 15:29:15 +10001900 req_ctx->to_hash_later = to_hash_later;
Lee Nipper497f2e62010-05-19 19:20:36 +10001901
Lee Nipper5e833bc2010-06-16 15:29:15 +10001902 /* Allocate extended descriptor */
Lee Nipper497f2e62010-05-19 19:20:36 +10001903 edesc = ahash_edesc_alloc(areq, nbytes_to_hash);
1904 if (IS_ERR(edesc))
1905 return PTR_ERR(edesc);
1906
1907 edesc->desc.hdr = ctx->desc_hdr_template;
1908
1909 /* On last one, request SEC to pad; otherwise continue */
1910 if (req_ctx->last)
1911 edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_PAD;
1912 else
1913 edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_CONT;
1914
Kim Phillips60f208d2010-05-19 19:21:53 +10001915 /* request SEC to INIT hash. */
1916 if (req_ctx->first && !req_ctx->swinit)
Lee Nipper497f2e62010-05-19 19:20:36 +10001917 edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_INIT;
1918
1919 /* When the tfm context has a keylen, it's an HMAC.
1920 * A first or last (ie. not middle) descriptor must request HMAC.
1921 */
1922 if (ctx->keylen && (req_ctx->first || req_ctx->last))
1923 edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_HMAC;
1924
1925 return common_nonsnoop_hash(edesc, areq, nbytes_to_hash,
1926 ahash_done);
1927}
1928
1929static int ahash_update(struct ahash_request *areq)
1930{
1931 struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
1932
1933 req_ctx->last = 0;
1934
1935 return ahash_process_req(areq, areq->nbytes);
1936}
1937
1938static int ahash_final(struct ahash_request *areq)
1939{
1940 struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
1941
1942 req_ctx->last = 1;
1943
1944 return ahash_process_req(areq, 0);
1945}
1946
1947static int ahash_finup(struct ahash_request *areq)
1948{
1949 struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
1950
1951 req_ctx->last = 1;
1952
1953 return ahash_process_req(areq, areq->nbytes);
1954}
1955
1956static int ahash_digest(struct ahash_request *areq)
1957{
1958 struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
Kim Phillips60f208d2010-05-19 19:21:53 +10001959 struct crypto_ahash *ahash = crypto_ahash_reqtfm(areq);
Lee Nipper497f2e62010-05-19 19:20:36 +10001960
Kim Phillips60f208d2010-05-19 19:21:53 +10001961 ahash->init(areq);
Lee Nipper497f2e62010-05-19 19:20:36 +10001962 req_ctx->last = 1;
1963
1964 return ahash_process_req(areq, areq->nbytes);
1965}
1966
Horia Geant?efc1e732016-04-21 19:24:55 +03001967static int ahash_export(struct ahash_request *areq, void *out)
1968{
1969 struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
1970 struct talitos_export_state *export = out;
1971
1972 memcpy(export->hw_context, req_ctx->hw_context,
1973 req_ctx->hw_context_size);
1974 memcpy(export->buf, req_ctx->buf, req_ctx->nbuf);
1975 export->swinit = req_ctx->swinit;
1976 export->first = req_ctx->first;
1977 export->last = req_ctx->last;
1978 export->to_hash_later = req_ctx->to_hash_later;
1979 export->nbuf = req_ctx->nbuf;
1980
1981 return 0;
1982}
1983
1984static int ahash_import(struct ahash_request *areq, const void *in)
1985{
1986 struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
1987 struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
1988 const struct talitos_export_state *export = in;
1989
1990 memset(req_ctx, 0, sizeof(*req_ctx));
1991 req_ctx->hw_context_size =
1992 (crypto_ahash_digestsize(tfm) <= SHA256_DIGEST_SIZE)
1993 ? TALITOS_MDEU_CONTEXT_SIZE_MD5_SHA1_SHA256
1994 : TALITOS_MDEU_CONTEXT_SIZE_SHA384_SHA512;
1995 memcpy(req_ctx->hw_context, export->hw_context,
1996 req_ctx->hw_context_size);
1997 memcpy(req_ctx->buf, export->buf, export->nbuf);
1998 req_ctx->swinit = export->swinit;
1999 req_ctx->first = export->first;
2000 req_ctx->last = export->last;
2001 req_ctx->to_hash_later = export->to_hash_later;
2002 req_ctx->nbuf = export->nbuf;
2003
2004 return 0;
2005}
2006
Lee Nipper79b3a412011-11-21 16:13:25 +08002007struct keyhash_result {
2008 struct completion completion;
2009 int err;
2010};
2011
2012static void keyhash_complete(struct crypto_async_request *req, int err)
2013{
2014 struct keyhash_result *res = req->data;
2015
2016 if (err == -EINPROGRESS)
2017 return;
2018
2019 res->err = err;
2020 complete(&res->completion);
2021}
2022
2023static int keyhash(struct crypto_ahash *tfm, const u8 *key, unsigned int keylen,
2024 u8 *hash)
2025{
2026 struct talitos_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm));
2027
2028 struct scatterlist sg[1];
2029 struct ahash_request *req;
2030 struct keyhash_result hresult;
2031 int ret;
2032
2033 init_completion(&hresult.completion);
2034
2035 req = ahash_request_alloc(tfm, GFP_KERNEL);
2036 if (!req)
2037 return -ENOMEM;
2038
2039 /* Keep tfm keylen == 0 during hash of the long key */
2040 ctx->keylen = 0;
2041 ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
2042 keyhash_complete, &hresult);
2043
2044 sg_init_one(&sg[0], key, keylen);
2045
2046 ahash_request_set_crypt(req, sg, hash, keylen);
2047 ret = crypto_ahash_digest(req);
2048 switch (ret) {
2049 case 0:
2050 break;
2051 case -EINPROGRESS:
2052 case -EBUSY:
2053 ret = wait_for_completion_interruptible(
2054 &hresult.completion);
2055 if (!ret)
2056 ret = hresult.err;
2057 break;
2058 default:
2059 break;
2060 }
2061 ahash_request_free(req);
2062
2063 return ret;
2064}
2065
2066static int ahash_setkey(struct crypto_ahash *tfm, const u8 *key,
2067 unsigned int keylen)
2068{
2069 struct talitos_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm));
2070 unsigned int blocksize =
2071 crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm));
2072 unsigned int digestsize = crypto_ahash_digestsize(tfm);
2073 unsigned int keysize = keylen;
2074 u8 hash[SHA512_DIGEST_SIZE];
2075 int ret;
2076
2077 if (keylen <= blocksize)
2078 memcpy(ctx->key, key, keysize);
2079 else {
2080 /* Must get the hash of the long key */
2081 ret = keyhash(tfm, key, keylen, hash);
2082
2083 if (ret) {
2084 crypto_ahash_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
2085 return -EINVAL;
2086 }
2087
2088 keysize = digestsize;
2089 memcpy(ctx->key, hash, digestsize);
2090 }
2091
2092 ctx->keylen = keysize;
2093
2094 return 0;
2095}
2096
2097
Kim Phillips9c4a7962008-06-23 19:50:15 +08002098struct talitos_alg_template {
Lee Nipperd5e4aae2010-05-19 19:18:38 +10002099 u32 type;
2100 union {
2101 struct crypto_alg crypto;
Lee Nipperacbf7c622010-05-19 19:19:33 +10002102 struct ahash_alg hash;
Herbert Xuaeb4c132015-07-30 17:53:22 +08002103 struct aead_alg aead;
Lee Nipperd5e4aae2010-05-19 19:18:38 +10002104 } alg;
Kim Phillips9c4a7962008-06-23 19:50:15 +08002105 __be32 desc_hdr_template;
2106};
2107
2108static struct talitos_alg_template driver_algs[] = {
Horia Geanta991155b2013-03-20 16:31:38 +02002109 /* AEAD algorithms. These use a single-pass ipsec_esp descriptor */
Lee Nipperd5e4aae2010-05-19 19:18:38 +10002110 { .type = CRYPTO_ALG_TYPE_AEAD,
Herbert Xuaeb4c132015-07-30 17:53:22 +08002111 .alg.aead = {
2112 .base = {
2113 .cra_name = "authenc(hmac(sha1),cbc(aes))",
2114 .cra_driver_name = "authenc-hmac-sha1-"
2115 "cbc-aes-talitos",
2116 .cra_blocksize = AES_BLOCK_SIZE,
2117 .cra_flags = CRYPTO_ALG_ASYNC,
2118 },
2119 .ivsize = AES_BLOCK_SIZE,
2120 .maxauthsize = SHA1_DIGEST_SIZE,
Lee Nipper56af8cd2009-03-29 15:50:50 +08002121 },
Kim Phillips9c4a7962008-06-23 19:50:15 +08002122 .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
2123 DESC_HDR_SEL0_AESU |
2124 DESC_HDR_MODE0_AESU_CBC |
2125 DESC_HDR_SEL1_MDEUA |
2126 DESC_HDR_MODE1_MDEU_INIT |
2127 DESC_HDR_MODE1_MDEU_PAD |
2128 DESC_HDR_MODE1_MDEU_SHA1_HMAC,
Lee Nipper70bcaca2008-07-03 19:08:46 +08002129 },
Lee Nipperd5e4aae2010-05-19 19:18:38 +10002130 { .type = CRYPTO_ALG_TYPE_AEAD,
Herbert Xuaeb4c132015-07-30 17:53:22 +08002131 .alg.aead = {
2132 .base = {
2133 .cra_name = "authenc(hmac(sha1),"
2134 "cbc(des3_ede))",
2135 .cra_driver_name = "authenc-hmac-sha1-"
2136 "cbc-3des-talitos",
2137 .cra_blocksize = DES3_EDE_BLOCK_SIZE,
2138 .cra_flags = CRYPTO_ALG_ASYNC,
2139 },
2140 .ivsize = DES3_EDE_BLOCK_SIZE,
2141 .maxauthsize = SHA1_DIGEST_SIZE,
Lee Nipper56af8cd2009-03-29 15:50:50 +08002142 },
Lee Nipper70bcaca2008-07-03 19:08:46 +08002143 .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
2144 DESC_HDR_SEL0_DEU |
2145 DESC_HDR_MODE0_DEU_CBC |
2146 DESC_HDR_MODE0_DEU_3DES |
2147 DESC_HDR_SEL1_MDEUA |
2148 DESC_HDR_MODE1_MDEU_INIT |
2149 DESC_HDR_MODE1_MDEU_PAD |
2150 DESC_HDR_MODE1_MDEU_SHA1_HMAC,
Lee Nipper3952f172008-07-10 18:29:18 +08002151 },
Horia Geanta357fb602012-07-03 19:16:53 +03002152 { .type = CRYPTO_ALG_TYPE_AEAD,
Herbert Xuaeb4c132015-07-30 17:53:22 +08002153 .alg.aead = {
2154 .base = {
2155 .cra_name = "authenc(hmac(sha224),cbc(aes))",
2156 .cra_driver_name = "authenc-hmac-sha224-"
2157 "cbc-aes-talitos",
2158 .cra_blocksize = AES_BLOCK_SIZE,
2159 .cra_flags = CRYPTO_ALG_ASYNC,
2160 },
2161 .ivsize = AES_BLOCK_SIZE,
2162 .maxauthsize = SHA224_DIGEST_SIZE,
Horia Geanta357fb602012-07-03 19:16:53 +03002163 },
2164 .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
2165 DESC_HDR_SEL0_AESU |
2166 DESC_HDR_MODE0_AESU_CBC |
2167 DESC_HDR_SEL1_MDEUA |
2168 DESC_HDR_MODE1_MDEU_INIT |
2169 DESC_HDR_MODE1_MDEU_PAD |
2170 DESC_HDR_MODE1_MDEU_SHA224_HMAC,
2171 },
2172 { .type = CRYPTO_ALG_TYPE_AEAD,
Herbert Xuaeb4c132015-07-30 17:53:22 +08002173 .alg.aead = {
2174 .base = {
2175 .cra_name = "authenc(hmac(sha224),"
2176 "cbc(des3_ede))",
2177 .cra_driver_name = "authenc-hmac-sha224-"
2178 "cbc-3des-talitos",
2179 .cra_blocksize = DES3_EDE_BLOCK_SIZE,
2180 .cra_flags = CRYPTO_ALG_ASYNC,
2181 },
2182 .ivsize = DES3_EDE_BLOCK_SIZE,
2183 .maxauthsize = SHA224_DIGEST_SIZE,
Horia Geanta357fb602012-07-03 19:16:53 +03002184 },
2185 .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
2186 DESC_HDR_SEL0_DEU |
2187 DESC_HDR_MODE0_DEU_CBC |
2188 DESC_HDR_MODE0_DEU_3DES |
2189 DESC_HDR_SEL1_MDEUA |
2190 DESC_HDR_MODE1_MDEU_INIT |
2191 DESC_HDR_MODE1_MDEU_PAD |
2192 DESC_HDR_MODE1_MDEU_SHA224_HMAC,
2193 },
Lee Nipperd5e4aae2010-05-19 19:18:38 +10002194 { .type = CRYPTO_ALG_TYPE_AEAD,
Herbert Xuaeb4c132015-07-30 17:53:22 +08002195 .alg.aead = {
2196 .base = {
2197 .cra_name = "authenc(hmac(sha256),cbc(aes))",
2198 .cra_driver_name = "authenc-hmac-sha256-"
2199 "cbc-aes-talitos",
2200 .cra_blocksize = AES_BLOCK_SIZE,
2201 .cra_flags = CRYPTO_ALG_ASYNC,
2202 },
2203 .ivsize = AES_BLOCK_SIZE,
2204 .maxauthsize = SHA256_DIGEST_SIZE,
Lee Nipper56af8cd2009-03-29 15:50:50 +08002205 },
Lee Nipper3952f172008-07-10 18:29:18 +08002206 .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
2207 DESC_HDR_SEL0_AESU |
2208 DESC_HDR_MODE0_AESU_CBC |
2209 DESC_HDR_SEL1_MDEUA |
2210 DESC_HDR_MODE1_MDEU_INIT |
2211 DESC_HDR_MODE1_MDEU_PAD |
2212 DESC_HDR_MODE1_MDEU_SHA256_HMAC,
2213 },
Lee Nipperd5e4aae2010-05-19 19:18:38 +10002214 { .type = CRYPTO_ALG_TYPE_AEAD,
Herbert Xuaeb4c132015-07-30 17:53:22 +08002215 .alg.aead = {
2216 .base = {
2217 .cra_name = "authenc(hmac(sha256),"
2218 "cbc(des3_ede))",
2219 .cra_driver_name = "authenc-hmac-sha256-"
2220 "cbc-3des-talitos",
2221 .cra_blocksize = DES3_EDE_BLOCK_SIZE,
2222 .cra_flags = CRYPTO_ALG_ASYNC,
2223 },
2224 .ivsize = DES3_EDE_BLOCK_SIZE,
2225 .maxauthsize = SHA256_DIGEST_SIZE,
Lee Nipper56af8cd2009-03-29 15:50:50 +08002226 },
Lee Nipper3952f172008-07-10 18:29:18 +08002227 .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
2228 DESC_HDR_SEL0_DEU |
2229 DESC_HDR_MODE0_DEU_CBC |
2230 DESC_HDR_MODE0_DEU_3DES |
2231 DESC_HDR_SEL1_MDEUA |
2232 DESC_HDR_MODE1_MDEU_INIT |
2233 DESC_HDR_MODE1_MDEU_PAD |
2234 DESC_HDR_MODE1_MDEU_SHA256_HMAC,
2235 },
Lee Nipperd5e4aae2010-05-19 19:18:38 +10002236 { .type = CRYPTO_ALG_TYPE_AEAD,
Herbert Xuaeb4c132015-07-30 17:53:22 +08002237 .alg.aead = {
2238 .base = {
2239 .cra_name = "authenc(hmac(sha384),cbc(aes))",
2240 .cra_driver_name = "authenc-hmac-sha384-"
2241 "cbc-aes-talitos",
2242 .cra_blocksize = AES_BLOCK_SIZE,
2243 .cra_flags = CRYPTO_ALG_ASYNC,
2244 },
2245 .ivsize = AES_BLOCK_SIZE,
2246 .maxauthsize = SHA384_DIGEST_SIZE,
Horia Geanta357fb602012-07-03 19:16:53 +03002247 },
2248 .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
2249 DESC_HDR_SEL0_AESU |
2250 DESC_HDR_MODE0_AESU_CBC |
2251 DESC_HDR_SEL1_MDEUB |
2252 DESC_HDR_MODE1_MDEU_INIT |
2253 DESC_HDR_MODE1_MDEU_PAD |
2254 DESC_HDR_MODE1_MDEUB_SHA384_HMAC,
2255 },
2256 { .type = CRYPTO_ALG_TYPE_AEAD,
Herbert Xuaeb4c132015-07-30 17:53:22 +08002257 .alg.aead = {
2258 .base = {
2259 .cra_name = "authenc(hmac(sha384),"
2260 "cbc(des3_ede))",
2261 .cra_driver_name = "authenc-hmac-sha384-"
2262 "cbc-3des-talitos",
2263 .cra_blocksize = DES3_EDE_BLOCK_SIZE,
2264 .cra_flags = CRYPTO_ALG_ASYNC,
2265 },
2266 .ivsize = DES3_EDE_BLOCK_SIZE,
2267 .maxauthsize = SHA384_DIGEST_SIZE,
Horia Geanta357fb602012-07-03 19:16:53 +03002268 },
2269 .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
2270 DESC_HDR_SEL0_DEU |
2271 DESC_HDR_MODE0_DEU_CBC |
2272 DESC_HDR_MODE0_DEU_3DES |
2273 DESC_HDR_SEL1_MDEUB |
2274 DESC_HDR_MODE1_MDEU_INIT |
2275 DESC_HDR_MODE1_MDEU_PAD |
2276 DESC_HDR_MODE1_MDEUB_SHA384_HMAC,
2277 },
2278 { .type = CRYPTO_ALG_TYPE_AEAD,
Herbert Xuaeb4c132015-07-30 17:53:22 +08002279 .alg.aead = {
2280 .base = {
2281 .cra_name = "authenc(hmac(sha512),cbc(aes))",
2282 .cra_driver_name = "authenc-hmac-sha512-"
2283 "cbc-aes-talitos",
2284 .cra_blocksize = AES_BLOCK_SIZE,
2285 .cra_flags = CRYPTO_ALG_ASYNC,
2286 },
2287 .ivsize = AES_BLOCK_SIZE,
2288 .maxauthsize = SHA512_DIGEST_SIZE,
Horia Geanta357fb602012-07-03 19:16:53 +03002289 },
2290 .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
2291 DESC_HDR_SEL0_AESU |
2292 DESC_HDR_MODE0_AESU_CBC |
2293 DESC_HDR_SEL1_MDEUB |
2294 DESC_HDR_MODE1_MDEU_INIT |
2295 DESC_HDR_MODE1_MDEU_PAD |
2296 DESC_HDR_MODE1_MDEUB_SHA512_HMAC,
2297 },
2298 { .type = CRYPTO_ALG_TYPE_AEAD,
Herbert Xuaeb4c132015-07-30 17:53:22 +08002299 .alg.aead = {
2300 .base = {
2301 .cra_name = "authenc(hmac(sha512),"
2302 "cbc(des3_ede))",
2303 .cra_driver_name = "authenc-hmac-sha512-"
2304 "cbc-3des-talitos",
2305 .cra_blocksize = DES3_EDE_BLOCK_SIZE,
2306 .cra_flags = CRYPTO_ALG_ASYNC,
2307 },
2308 .ivsize = DES3_EDE_BLOCK_SIZE,
2309 .maxauthsize = SHA512_DIGEST_SIZE,
Horia Geanta357fb602012-07-03 19:16:53 +03002310 },
2311 .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
2312 DESC_HDR_SEL0_DEU |
2313 DESC_HDR_MODE0_DEU_CBC |
2314 DESC_HDR_MODE0_DEU_3DES |
2315 DESC_HDR_SEL1_MDEUB |
2316 DESC_HDR_MODE1_MDEU_INIT |
2317 DESC_HDR_MODE1_MDEU_PAD |
2318 DESC_HDR_MODE1_MDEUB_SHA512_HMAC,
2319 },
2320 { .type = CRYPTO_ALG_TYPE_AEAD,
Herbert Xuaeb4c132015-07-30 17:53:22 +08002321 .alg.aead = {
2322 .base = {
2323 .cra_name = "authenc(hmac(md5),cbc(aes))",
2324 .cra_driver_name = "authenc-hmac-md5-"
2325 "cbc-aes-talitos",
2326 .cra_blocksize = AES_BLOCK_SIZE,
2327 .cra_flags = CRYPTO_ALG_ASYNC,
2328 },
2329 .ivsize = AES_BLOCK_SIZE,
2330 .maxauthsize = MD5_DIGEST_SIZE,
Lee Nipper56af8cd2009-03-29 15:50:50 +08002331 },
Lee Nipper3952f172008-07-10 18:29:18 +08002332 .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
2333 DESC_HDR_SEL0_AESU |
2334 DESC_HDR_MODE0_AESU_CBC |
2335 DESC_HDR_SEL1_MDEUA |
2336 DESC_HDR_MODE1_MDEU_INIT |
2337 DESC_HDR_MODE1_MDEU_PAD |
2338 DESC_HDR_MODE1_MDEU_MD5_HMAC,
2339 },
Lee Nipperd5e4aae2010-05-19 19:18:38 +10002340 { .type = CRYPTO_ALG_TYPE_AEAD,
Herbert Xuaeb4c132015-07-30 17:53:22 +08002341 .alg.aead = {
2342 .base = {
2343 .cra_name = "authenc(hmac(md5),cbc(des3_ede))",
2344 .cra_driver_name = "authenc-hmac-md5-"
2345 "cbc-3des-talitos",
2346 .cra_blocksize = DES3_EDE_BLOCK_SIZE,
2347 .cra_flags = CRYPTO_ALG_ASYNC,
2348 },
2349 .ivsize = DES3_EDE_BLOCK_SIZE,
2350 .maxauthsize = MD5_DIGEST_SIZE,
Lee Nipper56af8cd2009-03-29 15:50:50 +08002351 },
Lee Nipper3952f172008-07-10 18:29:18 +08002352 .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
2353 DESC_HDR_SEL0_DEU |
2354 DESC_HDR_MODE0_DEU_CBC |
2355 DESC_HDR_MODE0_DEU_3DES |
2356 DESC_HDR_SEL1_MDEUA |
2357 DESC_HDR_MODE1_MDEU_INIT |
2358 DESC_HDR_MODE1_MDEU_PAD |
2359 DESC_HDR_MODE1_MDEU_MD5_HMAC,
Lee Nipper4de9d0b2009-03-29 15:52:32 +08002360 },
2361 /* ABLKCIPHER algorithms. */
Lee Nipperd5e4aae2010-05-19 19:18:38 +10002362 { .type = CRYPTO_ALG_TYPE_ABLKCIPHER,
2363 .alg.crypto = {
Lee Nipper4de9d0b2009-03-29 15:52:32 +08002364 .cra_name = "cbc(aes)",
2365 .cra_driver_name = "cbc-aes-talitos",
2366 .cra_blocksize = AES_BLOCK_SIZE,
2367 .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
2368 CRYPTO_ALG_ASYNC,
Lee Nipper4de9d0b2009-03-29 15:52:32 +08002369 .cra_ablkcipher = {
Lee Nipper4de9d0b2009-03-29 15:52:32 +08002370 .min_keysize = AES_MIN_KEY_SIZE,
2371 .max_keysize = AES_MAX_KEY_SIZE,
2372 .ivsize = AES_BLOCK_SIZE,
2373 }
2374 },
2375 .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
2376 DESC_HDR_SEL0_AESU |
2377 DESC_HDR_MODE0_AESU_CBC,
2378 },
Lee Nipperd5e4aae2010-05-19 19:18:38 +10002379 { .type = CRYPTO_ALG_TYPE_ABLKCIPHER,
2380 .alg.crypto = {
Lee Nipper4de9d0b2009-03-29 15:52:32 +08002381 .cra_name = "cbc(des3_ede)",
2382 .cra_driver_name = "cbc-3des-talitos",
2383 .cra_blocksize = DES3_EDE_BLOCK_SIZE,
2384 .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
2385 CRYPTO_ALG_ASYNC,
Lee Nipper4de9d0b2009-03-29 15:52:32 +08002386 .cra_ablkcipher = {
Lee Nipper4de9d0b2009-03-29 15:52:32 +08002387 .min_keysize = DES3_EDE_KEY_SIZE,
2388 .max_keysize = DES3_EDE_KEY_SIZE,
2389 .ivsize = DES3_EDE_BLOCK_SIZE,
2390 }
2391 },
2392 .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
2393 DESC_HDR_SEL0_DEU |
2394 DESC_HDR_MODE0_DEU_CBC |
2395 DESC_HDR_MODE0_DEU_3DES,
Lee Nipper497f2e62010-05-19 19:20:36 +10002396 },
2397 /* AHASH algorithms. */
2398 { .type = CRYPTO_ALG_TYPE_AHASH,
2399 .alg.hash = {
Lee Nipper497f2e62010-05-19 19:20:36 +10002400 .halg.digestsize = MD5_DIGEST_SIZE,
Horia Geant?efc1e732016-04-21 19:24:55 +03002401 .halg.statesize = sizeof(struct talitos_export_state),
Lee Nipper497f2e62010-05-19 19:20:36 +10002402 .halg.base = {
2403 .cra_name = "md5",
2404 .cra_driver_name = "md5-talitos",
Martin Hicksb3988612015-03-03 08:21:34 -05002405 .cra_blocksize = MD5_HMAC_BLOCK_SIZE,
Lee Nipper497f2e62010-05-19 19:20:36 +10002406 .cra_flags = CRYPTO_ALG_TYPE_AHASH |
2407 CRYPTO_ALG_ASYNC,
Lee Nipper497f2e62010-05-19 19:20:36 +10002408 }
2409 },
2410 .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
2411 DESC_HDR_SEL0_MDEUA |
2412 DESC_HDR_MODE0_MDEU_MD5,
2413 },
2414 { .type = CRYPTO_ALG_TYPE_AHASH,
2415 .alg.hash = {
Lee Nipper497f2e62010-05-19 19:20:36 +10002416 .halg.digestsize = SHA1_DIGEST_SIZE,
Horia Geant?efc1e732016-04-21 19:24:55 +03002417 .halg.statesize = sizeof(struct talitos_export_state),
Lee Nipper497f2e62010-05-19 19:20:36 +10002418 .halg.base = {
2419 .cra_name = "sha1",
2420 .cra_driver_name = "sha1-talitos",
2421 .cra_blocksize = SHA1_BLOCK_SIZE,
2422 .cra_flags = CRYPTO_ALG_TYPE_AHASH |
2423 CRYPTO_ALG_ASYNC,
Lee Nipper497f2e62010-05-19 19:20:36 +10002424 }
2425 },
2426 .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
2427 DESC_HDR_SEL0_MDEUA |
2428 DESC_HDR_MODE0_MDEU_SHA1,
2429 },
2430 { .type = CRYPTO_ALG_TYPE_AHASH,
2431 .alg.hash = {
Kim Phillips60f208d2010-05-19 19:21:53 +10002432 .halg.digestsize = SHA224_DIGEST_SIZE,
Horia Geant?efc1e732016-04-21 19:24:55 +03002433 .halg.statesize = sizeof(struct talitos_export_state),
Kim Phillips60f208d2010-05-19 19:21:53 +10002434 .halg.base = {
2435 .cra_name = "sha224",
2436 .cra_driver_name = "sha224-talitos",
2437 .cra_blocksize = SHA224_BLOCK_SIZE,
2438 .cra_flags = CRYPTO_ALG_TYPE_AHASH |
2439 CRYPTO_ALG_ASYNC,
Kim Phillips60f208d2010-05-19 19:21:53 +10002440 }
2441 },
2442 .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
2443 DESC_HDR_SEL0_MDEUA |
2444 DESC_HDR_MODE0_MDEU_SHA224,
2445 },
2446 { .type = CRYPTO_ALG_TYPE_AHASH,
2447 .alg.hash = {
Lee Nipper497f2e62010-05-19 19:20:36 +10002448 .halg.digestsize = SHA256_DIGEST_SIZE,
Horia Geant?efc1e732016-04-21 19:24:55 +03002449 .halg.statesize = sizeof(struct talitos_export_state),
Lee Nipper497f2e62010-05-19 19:20:36 +10002450 .halg.base = {
2451 .cra_name = "sha256",
2452 .cra_driver_name = "sha256-talitos",
2453 .cra_blocksize = SHA256_BLOCK_SIZE,
2454 .cra_flags = CRYPTO_ALG_TYPE_AHASH |
2455 CRYPTO_ALG_ASYNC,
Lee Nipper497f2e62010-05-19 19:20:36 +10002456 }
2457 },
2458 .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
2459 DESC_HDR_SEL0_MDEUA |
2460 DESC_HDR_MODE0_MDEU_SHA256,
2461 },
2462 { .type = CRYPTO_ALG_TYPE_AHASH,
2463 .alg.hash = {
Lee Nipper497f2e62010-05-19 19:20:36 +10002464 .halg.digestsize = SHA384_DIGEST_SIZE,
Horia Geant?efc1e732016-04-21 19:24:55 +03002465 .halg.statesize = sizeof(struct talitos_export_state),
Lee Nipper497f2e62010-05-19 19:20:36 +10002466 .halg.base = {
2467 .cra_name = "sha384",
2468 .cra_driver_name = "sha384-talitos",
2469 .cra_blocksize = SHA384_BLOCK_SIZE,
2470 .cra_flags = CRYPTO_ALG_TYPE_AHASH |
2471 CRYPTO_ALG_ASYNC,
Lee Nipper497f2e62010-05-19 19:20:36 +10002472 }
2473 },
2474 .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
2475 DESC_HDR_SEL0_MDEUB |
2476 DESC_HDR_MODE0_MDEUB_SHA384,
2477 },
2478 { .type = CRYPTO_ALG_TYPE_AHASH,
2479 .alg.hash = {
Lee Nipper497f2e62010-05-19 19:20:36 +10002480 .halg.digestsize = SHA512_DIGEST_SIZE,
Horia Geant?efc1e732016-04-21 19:24:55 +03002481 .halg.statesize = sizeof(struct talitos_export_state),
Lee Nipper497f2e62010-05-19 19:20:36 +10002482 .halg.base = {
2483 .cra_name = "sha512",
2484 .cra_driver_name = "sha512-talitos",
2485 .cra_blocksize = SHA512_BLOCK_SIZE,
2486 .cra_flags = CRYPTO_ALG_TYPE_AHASH |
2487 CRYPTO_ALG_ASYNC,
Lee Nipper497f2e62010-05-19 19:20:36 +10002488 }
2489 },
2490 .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
2491 DESC_HDR_SEL0_MDEUB |
2492 DESC_HDR_MODE0_MDEUB_SHA512,
2493 },
Lee Nipper79b3a412011-11-21 16:13:25 +08002494 { .type = CRYPTO_ALG_TYPE_AHASH,
2495 .alg.hash = {
Lee Nipper79b3a412011-11-21 16:13:25 +08002496 .halg.digestsize = MD5_DIGEST_SIZE,
Horia Geant?efc1e732016-04-21 19:24:55 +03002497 .halg.statesize = sizeof(struct talitos_export_state),
Lee Nipper79b3a412011-11-21 16:13:25 +08002498 .halg.base = {
2499 .cra_name = "hmac(md5)",
2500 .cra_driver_name = "hmac-md5-talitos",
Martin Hicksb3988612015-03-03 08:21:34 -05002501 .cra_blocksize = MD5_HMAC_BLOCK_SIZE,
Lee Nipper79b3a412011-11-21 16:13:25 +08002502 .cra_flags = CRYPTO_ALG_TYPE_AHASH |
2503 CRYPTO_ALG_ASYNC,
Lee Nipper79b3a412011-11-21 16:13:25 +08002504 }
2505 },
2506 .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
2507 DESC_HDR_SEL0_MDEUA |
2508 DESC_HDR_MODE0_MDEU_MD5,
2509 },
2510 { .type = CRYPTO_ALG_TYPE_AHASH,
2511 .alg.hash = {
Lee Nipper79b3a412011-11-21 16:13:25 +08002512 .halg.digestsize = SHA1_DIGEST_SIZE,
Horia Geant?efc1e732016-04-21 19:24:55 +03002513 .halg.statesize = sizeof(struct talitos_export_state),
Lee Nipper79b3a412011-11-21 16:13:25 +08002514 .halg.base = {
2515 .cra_name = "hmac(sha1)",
2516 .cra_driver_name = "hmac-sha1-talitos",
2517 .cra_blocksize = SHA1_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_MDEUA |
2524 DESC_HDR_MODE0_MDEU_SHA1,
2525 },
2526 { .type = CRYPTO_ALG_TYPE_AHASH,
2527 .alg.hash = {
Lee Nipper79b3a412011-11-21 16:13:25 +08002528 .halg.digestsize = SHA224_DIGEST_SIZE,
Horia Geant?efc1e732016-04-21 19:24:55 +03002529 .halg.statesize = sizeof(struct talitos_export_state),
Lee Nipper79b3a412011-11-21 16:13:25 +08002530 .halg.base = {
2531 .cra_name = "hmac(sha224)",
2532 .cra_driver_name = "hmac-sha224-talitos",
2533 .cra_blocksize = SHA224_BLOCK_SIZE,
2534 .cra_flags = CRYPTO_ALG_TYPE_AHASH |
2535 CRYPTO_ALG_ASYNC,
Lee Nipper79b3a412011-11-21 16:13:25 +08002536 }
2537 },
2538 .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
2539 DESC_HDR_SEL0_MDEUA |
2540 DESC_HDR_MODE0_MDEU_SHA224,
2541 },
2542 { .type = CRYPTO_ALG_TYPE_AHASH,
2543 .alg.hash = {
Lee Nipper79b3a412011-11-21 16:13:25 +08002544 .halg.digestsize = SHA256_DIGEST_SIZE,
Horia Geant?efc1e732016-04-21 19:24:55 +03002545 .halg.statesize = sizeof(struct talitos_export_state),
Lee Nipper79b3a412011-11-21 16:13:25 +08002546 .halg.base = {
2547 .cra_name = "hmac(sha256)",
2548 .cra_driver_name = "hmac-sha256-talitos",
2549 .cra_blocksize = SHA256_BLOCK_SIZE,
2550 .cra_flags = CRYPTO_ALG_TYPE_AHASH |
2551 CRYPTO_ALG_ASYNC,
Lee Nipper79b3a412011-11-21 16:13:25 +08002552 }
2553 },
2554 .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
2555 DESC_HDR_SEL0_MDEUA |
2556 DESC_HDR_MODE0_MDEU_SHA256,
2557 },
2558 { .type = CRYPTO_ALG_TYPE_AHASH,
2559 .alg.hash = {
Lee Nipper79b3a412011-11-21 16:13:25 +08002560 .halg.digestsize = SHA384_DIGEST_SIZE,
Horia Geant?efc1e732016-04-21 19:24:55 +03002561 .halg.statesize = sizeof(struct talitos_export_state),
Lee Nipper79b3a412011-11-21 16:13:25 +08002562 .halg.base = {
2563 .cra_name = "hmac(sha384)",
2564 .cra_driver_name = "hmac-sha384-talitos",
2565 .cra_blocksize = SHA384_BLOCK_SIZE,
2566 .cra_flags = CRYPTO_ALG_TYPE_AHASH |
2567 CRYPTO_ALG_ASYNC,
Lee Nipper79b3a412011-11-21 16:13:25 +08002568 }
2569 },
2570 .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
2571 DESC_HDR_SEL0_MDEUB |
2572 DESC_HDR_MODE0_MDEUB_SHA384,
2573 },
2574 { .type = CRYPTO_ALG_TYPE_AHASH,
2575 .alg.hash = {
Lee Nipper79b3a412011-11-21 16:13:25 +08002576 .halg.digestsize = SHA512_DIGEST_SIZE,
Horia Geant?efc1e732016-04-21 19:24:55 +03002577 .halg.statesize = sizeof(struct talitos_export_state),
Lee Nipper79b3a412011-11-21 16:13:25 +08002578 .halg.base = {
2579 .cra_name = "hmac(sha512)",
2580 .cra_driver_name = "hmac-sha512-talitos",
2581 .cra_blocksize = SHA512_BLOCK_SIZE,
2582 .cra_flags = CRYPTO_ALG_TYPE_AHASH |
2583 CRYPTO_ALG_ASYNC,
Lee Nipper79b3a412011-11-21 16:13:25 +08002584 }
2585 },
2586 .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
2587 DESC_HDR_SEL0_MDEUB |
2588 DESC_HDR_MODE0_MDEUB_SHA512,
2589 }
Kim Phillips9c4a7962008-06-23 19:50:15 +08002590};
2591
2592struct talitos_crypto_alg {
2593 struct list_head entry;
2594 struct device *dev;
Lee Nipperacbf7c622010-05-19 19:19:33 +10002595 struct talitos_alg_template algt;
Kim Phillips9c4a7962008-06-23 19:50:15 +08002596};
2597
Jonas Eymann0dedb762016-04-19 20:33:47 +03002598static int talitos_init_common(struct talitos_ctx *ctx,
2599 struct talitos_crypto_alg *talitos_alg)
Kim Phillips9c4a7962008-06-23 19:50:15 +08002600{
Kim Phillips5228f0f2011-07-15 11:21:38 +08002601 struct talitos_private *priv;
Kim Phillips9c4a7962008-06-23 19:50:15 +08002602
2603 /* update context with ptr to dev */
2604 ctx->dev = talitos_alg->dev;
Kim Phillips19bbbc62009-03-29 15:53:59 +08002605
Kim Phillips5228f0f2011-07-15 11:21:38 +08002606 /* assign SEC channel to tfm in round-robin fashion */
2607 priv = dev_get_drvdata(ctx->dev);
2608 ctx->ch = atomic_inc_return(&priv->last_chan) &
2609 (priv->num_channels - 1);
2610
Kim Phillips9c4a7962008-06-23 19:50:15 +08002611 /* copy descriptor header template value */
Lee Nipperacbf7c622010-05-19 19:19:33 +10002612 ctx->desc_hdr_template = talitos_alg->algt.desc_hdr_template;
Kim Phillips9c4a7962008-06-23 19:50:15 +08002613
Kim Phillips602dba52011-07-15 11:21:39 +08002614 /* select done notification */
2615 ctx->desc_hdr_template |= DESC_HDR_DONE_NOTIFY;
2616
Lee Nipper497f2e62010-05-19 19:20:36 +10002617 return 0;
2618}
2619
Jonas Eymann0dedb762016-04-19 20:33:47 +03002620static int talitos_cra_init(struct crypto_tfm *tfm)
2621{
2622 struct crypto_alg *alg = tfm->__crt_alg;
2623 struct talitos_crypto_alg *talitos_alg;
2624 struct talitos_ctx *ctx = crypto_tfm_ctx(tfm);
2625
2626 if ((alg->cra_flags & CRYPTO_ALG_TYPE_MASK) == CRYPTO_ALG_TYPE_AHASH)
2627 talitos_alg = container_of(__crypto_ahash_alg(alg),
2628 struct talitos_crypto_alg,
2629 algt.alg.hash);
2630 else
2631 talitos_alg = container_of(alg, struct talitos_crypto_alg,
2632 algt.alg.crypto);
2633
2634 return talitos_init_common(ctx, talitos_alg);
2635}
2636
Herbert Xuaeb4c132015-07-30 17:53:22 +08002637static int talitos_cra_init_aead(struct crypto_aead *tfm)
Lee Nipper497f2e62010-05-19 19:20:36 +10002638{
Jonas Eymann0dedb762016-04-19 20:33:47 +03002639 struct aead_alg *alg = crypto_aead_alg(tfm);
2640 struct talitos_crypto_alg *talitos_alg;
2641 struct talitos_ctx *ctx = crypto_aead_ctx(tfm);
2642
2643 talitos_alg = container_of(alg, struct talitos_crypto_alg,
2644 algt.alg.aead);
2645
2646 return talitos_init_common(ctx, talitos_alg);
Kim Phillips9c4a7962008-06-23 19:50:15 +08002647}
2648
Lee Nipper497f2e62010-05-19 19:20:36 +10002649static int talitos_cra_init_ahash(struct crypto_tfm *tfm)
2650{
2651 struct talitos_ctx *ctx = crypto_tfm_ctx(tfm);
2652
2653 talitos_cra_init(tfm);
2654
2655 ctx->keylen = 0;
2656 crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm),
2657 sizeof(struct talitos_ahash_req_ctx));
2658
2659 return 0;
2660}
2661
Kim Phillips9c4a7962008-06-23 19:50:15 +08002662/*
2663 * given the alg's descriptor header template, determine whether descriptor
2664 * type and primary/secondary execution units required match the hw
2665 * capabilities description provided in the device tree node.
2666 */
2667static int hw_supports(struct device *dev, __be32 desc_hdr_template)
2668{
2669 struct talitos_private *priv = dev_get_drvdata(dev);
2670 int ret;
2671
2672 ret = (1 << DESC_TYPE(desc_hdr_template) & priv->desc_types) &&
2673 (1 << PRIMARY_EU(desc_hdr_template) & priv->exec_units);
2674
2675 if (SECONDARY_EU(desc_hdr_template))
2676 ret = ret && (1 << SECONDARY_EU(desc_hdr_template)
2677 & priv->exec_units);
2678
2679 return ret;
2680}
2681
Grant Likely2dc11582010-08-06 09:25:50 -06002682static int talitos_remove(struct platform_device *ofdev)
Kim Phillips9c4a7962008-06-23 19:50:15 +08002683{
2684 struct device *dev = &ofdev->dev;
2685 struct talitos_private *priv = dev_get_drvdata(dev);
2686 struct talitos_crypto_alg *t_alg, *n;
2687 int i;
2688
2689 list_for_each_entry_safe(t_alg, n, &priv->alg_list, entry) {
Lee Nipperacbf7c622010-05-19 19:19:33 +10002690 switch (t_alg->algt.type) {
2691 case CRYPTO_ALG_TYPE_ABLKCIPHER:
Lee Nipperacbf7c622010-05-19 19:19:33 +10002692 break;
Herbert Xuaeb4c132015-07-30 17:53:22 +08002693 case CRYPTO_ALG_TYPE_AEAD:
2694 crypto_unregister_aead(&t_alg->algt.alg.aead);
Lee Nipperacbf7c622010-05-19 19:19:33 +10002695 case CRYPTO_ALG_TYPE_AHASH:
2696 crypto_unregister_ahash(&t_alg->algt.alg.hash);
2697 break;
2698 }
Kim Phillips9c4a7962008-06-23 19:50:15 +08002699 list_del(&t_alg->entry);
2700 kfree(t_alg);
2701 }
2702
2703 if (hw_supports(dev, DESC_HDR_SEL0_RNG))
2704 talitos_unregister_rng(dev);
2705
Aaron Sierra35a3bb32015-08-05 16:52:08 -05002706 for (i = 0; priv->chan && i < priv->num_channels; i++)
Kim Phillips0b798242010-09-23 15:56:08 +08002707 kfree(priv->chan[i].fifo);
Kim Phillips9c4a7962008-06-23 19:50:15 +08002708
Kim Phillips4b9926282009-08-13 11:50:38 +10002709 kfree(priv->chan);
Kim Phillips9c4a7962008-06-23 19:50:15 +08002710
Kim Phillipsc3e337f2011-11-21 16:13:27 +08002711 for (i = 0; i < 2; i++)
Kim Phillips2cdba3c2011-12-12 14:59:11 -06002712 if (priv->irq[i]) {
Kim Phillipsc3e337f2011-11-21 16:13:27 +08002713 free_irq(priv->irq[i], dev);
2714 irq_dispose_mapping(priv->irq[i]);
2715 }
Kim Phillips9c4a7962008-06-23 19:50:15 +08002716
Kim Phillipsc3e337f2011-11-21 16:13:27 +08002717 tasklet_kill(&priv->done_task[0]);
Kim Phillips2cdba3c2011-12-12 14:59:11 -06002718 if (priv->irq[1])
Kim Phillipsc3e337f2011-11-21 16:13:27 +08002719 tasklet_kill(&priv->done_task[1]);
Kim Phillips9c4a7962008-06-23 19:50:15 +08002720
2721 iounmap(priv->reg);
2722
Kim Phillips9c4a7962008-06-23 19:50:15 +08002723 kfree(priv);
2724
2725 return 0;
2726}
2727
2728static struct talitos_crypto_alg *talitos_alg_alloc(struct device *dev,
2729 struct talitos_alg_template
2730 *template)
2731{
Kim Phillips60f208d2010-05-19 19:21:53 +10002732 struct talitos_private *priv = dev_get_drvdata(dev);
Kim Phillips9c4a7962008-06-23 19:50:15 +08002733 struct talitos_crypto_alg *t_alg;
2734 struct crypto_alg *alg;
2735
2736 t_alg = kzalloc(sizeof(struct talitos_crypto_alg), GFP_KERNEL);
2737 if (!t_alg)
2738 return ERR_PTR(-ENOMEM);
2739
Lee Nipperacbf7c622010-05-19 19:19:33 +10002740 t_alg->algt = *template;
2741
2742 switch (t_alg->algt.type) {
2743 case CRYPTO_ALG_TYPE_ABLKCIPHER:
Lee Nipper497f2e62010-05-19 19:20:36 +10002744 alg = &t_alg->algt.alg.crypto;
2745 alg->cra_init = talitos_cra_init;
Kim Phillipsd4cd3282012-08-08 20:32:00 -05002746 alg->cra_type = &crypto_ablkcipher_type;
Kim Phillipsb286e002012-08-08 20:33:34 -05002747 alg->cra_ablkcipher.setkey = ablkcipher_setkey;
2748 alg->cra_ablkcipher.encrypt = ablkcipher_encrypt;
2749 alg->cra_ablkcipher.decrypt = ablkcipher_decrypt;
2750 alg->cra_ablkcipher.geniv = "eseqiv";
Lee Nipper497f2e62010-05-19 19:20:36 +10002751 break;
Lee Nipperacbf7c622010-05-19 19:19:33 +10002752 case CRYPTO_ALG_TYPE_AEAD:
Herbert Xuaeb4c132015-07-30 17:53:22 +08002753 alg = &t_alg->algt.alg.aead.base;
Herbert Xuaeb4c132015-07-30 17:53:22 +08002754 t_alg->algt.alg.aead.init = talitos_cra_init_aead;
2755 t_alg->algt.alg.aead.setkey = aead_setkey;
2756 t_alg->algt.alg.aead.encrypt = aead_encrypt;
2757 t_alg->algt.alg.aead.decrypt = aead_decrypt;
Lee Nipperacbf7c622010-05-19 19:19:33 +10002758 break;
2759 case CRYPTO_ALG_TYPE_AHASH:
2760 alg = &t_alg->algt.alg.hash.halg.base;
Lee Nipper497f2e62010-05-19 19:20:36 +10002761 alg->cra_init = talitos_cra_init_ahash;
Kim Phillipsd4cd3282012-08-08 20:32:00 -05002762 alg->cra_type = &crypto_ahash_type;
Kim Phillipsb286e002012-08-08 20:33:34 -05002763 t_alg->algt.alg.hash.init = ahash_init;
2764 t_alg->algt.alg.hash.update = ahash_update;
2765 t_alg->algt.alg.hash.final = ahash_final;
2766 t_alg->algt.alg.hash.finup = ahash_finup;
2767 t_alg->algt.alg.hash.digest = ahash_digest;
2768 t_alg->algt.alg.hash.setkey = ahash_setkey;
Horia Geant?efc1e732016-04-21 19:24:55 +03002769 t_alg->algt.alg.hash.import = ahash_import;
2770 t_alg->algt.alg.hash.export = ahash_export;
Kim Phillipsb286e002012-08-08 20:33:34 -05002771
Lee Nipper79b3a412011-11-21 16:13:25 +08002772 if (!(priv->features & TALITOS_FTR_HMAC_OK) &&
Kim Phillips0b2730d2011-12-12 14:59:10 -06002773 !strncmp(alg->cra_name, "hmac", 4)) {
2774 kfree(t_alg);
Lee Nipper79b3a412011-11-21 16:13:25 +08002775 return ERR_PTR(-ENOTSUPP);
Kim Phillips0b2730d2011-12-12 14:59:10 -06002776 }
Kim Phillips60f208d2010-05-19 19:21:53 +10002777 if (!(priv->features & TALITOS_FTR_SHA224_HWINIT) &&
Lee Nipper79b3a412011-11-21 16:13:25 +08002778 (!strcmp(alg->cra_name, "sha224") ||
2779 !strcmp(alg->cra_name, "hmac(sha224)"))) {
Kim Phillips60f208d2010-05-19 19:21:53 +10002780 t_alg->algt.alg.hash.init = ahash_init_sha224_swinit;
2781 t_alg->algt.desc_hdr_template =
2782 DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
2783 DESC_HDR_SEL0_MDEUA |
2784 DESC_HDR_MODE0_MDEU_SHA256;
2785 }
Lee Nipper497f2e62010-05-19 19:20:36 +10002786 break;
Kim Phillips1d119112010-09-23 15:55:27 +08002787 default:
2788 dev_err(dev, "unknown algorithm type %d\n", t_alg->algt.type);
Horia Geant?5fa7dad2015-05-11 20:03:24 +03002789 kfree(t_alg);
Kim Phillips1d119112010-09-23 15:55:27 +08002790 return ERR_PTR(-EINVAL);
Lee Nipperacbf7c622010-05-19 19:19:33 +10002791 }
Kim Phillips9c4a7962008-06-23 19:50:15 +08002792
Kim Phillips9c4a7962008-06-23 19:50:15 +08002793 alg->cra_module = THIS_MODULE;
Kim Phillips9c4a7962008-06-23 19:50:15 +08002794 alg->cra_priority = TALITOS_CRA_PRIORITY;
Kim Phillips9c4a7962008-06-23 19:50:15 +08002795 alg->cra_alignmask = 0;
Kim Phillips9c4a7962008-06-23 19:50:15 +08002796 alg->cra_ctxsize = sizeof(struct talitos_ctx);
Nikos Mavrogiannopoulosd912bb72011-11-01 13:39:56 +01002797 alg->cra_flags |= CRYPTO_ALG_KERN_DRIVER_ONLY;
Kim Phillips9c4a7962008-06-23 19:50:15 +08002798
Kim Phillips9c4a7962008-06-23 19:50:15 +08002799 t_alg->dev = dev;
2800
2801 return t_alg;
2802}
2803
Kim Phillipsc3e337f2011-11-21 16:13:27 +08002804static int talitos_probe_irq(struct platform_device *ofdev)
2805{
2806 struct device *dev = &ofdev->dev;
2807 struct device_node *np = ofdev->dev.of_node;
2808 struct talitos_private *priv = dev_get_drvdata(dev);
2809 int err;
LEROY Christophedd3c0982015-04-17 16:32:13 +02002810 bool is_sec1 = has_ftr_sec1(priv);
Kim Phillipsc3e337f2011-11-21 16:13:27 +08002811
2812 priv->irq[0] = irq_of_parse_and_map(np, 0);
Kim Phillips2cdba3c2011-12-12 14:59:11 -06002813 if (!priv->irq[0]) {
Kim Phillipsc3e337f2011-11-21 16:13:27 +08002814 dev_err(dev, "failed to map irq\n");
2815 return -EINVAL;
2816 }
LEROY Christophedd3c0982015-04-17 16:32:13 +02002817 if (is_sec1) {
2818 err = request_irq(priv->irq[0], talitos1_interrupt_4ch, 0,
2819 dev_driver_string(dev), dev);
2820 goto primary_out;
2821 }
Kim Phillipsc3e337f2011-11-21 16:13:27 +08002822
2823 priv->irq[1] = irq_of_parse_and_map(np, 1);
2824
2825 /* get the primary irq line */
Kim Phillips2cdba3c2011-12-12 14:59:11 -06002826 if (!priv->irq[1]) {
LEROY Christophedd3c0982015-04-17 16:32:13 +02002827 err = request_irq(priv->irq[0], talitos2_interrupt_4ch, 0,
Kim Phillipsc3e337f2011-11-21 16:13:27 +08002828 dev_driver_string(dev), dev);
2829 goto primary_out;
2830 }
2831
LEROY Christophedd3c0982015-04-17 16:32:13 +02002832 err = request_irq(priv->irq[0], talitos2_interrupt_ch0_2, 0,
Kim Phillipsc3e337f2011-11-21 16:13:27 +08002833 dev_driver_string(dev), dev);
2834 if (err)
2835 goto primary_out;
2836
2837 /* get the secondary irq line */
LEROY Christophedd3c0982015-04-17 16:32:13 +02002838 err = request_irq(priv->irq[1], talitos2_interrupt_ch1_3, 0,
Kim Phillipsc3e337f2011-11-21 16:13:27 +08002839 dev_driver_string(dev), dev);
2840 if (err) {
2841 dev_err(dev, "failed to request secondary irq\n");
2842 irq_dispose_mapping(priv->irq[1]);
Kim Phillips2cdba3c2011-12-12 14:59:11 -06002843 priv->irq[1] = 0;
Kim Phillipsc3e337f2011-11-21 16:13:27 +08002844 }
2845
2846 return err;
2847
2848primary_out:
2849 if (err) {
2850 dev_err(dev, "failed to request primary irq\n");
2851 irq_dispose_mapping(priv->irq[0]);
Kim Phillips2cdba3c2011-12-12 14:59:11 -06002852 priv->irq[0] = 0;
Kim Phillipsc3e337f2011-11-21 16:13:27 +08002853 }
2854
2855 return err;
2856}
2857
Grant Likely1c48a5c2011-02-17 02:43:24 -07002858static int talitos_probe(struct platform_device *ofdev)
Kim Phillips9c4a7962008-06-23 19:50:15 +08002859{
2860 struct device *dev = &ofdev->dev;
Grant Likely61c7a082010-04-13 16:12:29 -07002861 struct device_node *np = ofdev->dev.of_node;
Kim Phillips9c4a7962008-06-23 19:50:15 +08002862 struct talitos_private *priv;
2863 const unsigned int *prop;
2864 int i, err;
LEROY Christophe5fa7fa12015-04-17 16:32:11 +02002865 int stride;
Kim Phillips9c4a7962008-06-23 19:50:15 +08002866
2867 priv = kzalloc(sizeof(struct talitos_private), GFP_KERNEL);
2868 if (!priv)
2869 return -ENOMEM;
2870
Kevin Haof3de9cb2014-01-28 20:17:23 +08002871 INIT_LIST_HEAD(&priv->alg_list);
2872
Kim Phillips9c4a7962008-06-23 19:50:15 +08002873 dev_set_drvdata(dev, priv);
2874
2875 priv->ofdev = ofdev;
2876
Horia Geanta511d63c2012-03-30 17:49:53 +03002877 spin_lock_init(&priv->reg_lock);
2878
Kim Phillips9c4a7962008-06-23 19:50:15 +08002879 priv->reg = of_iomap(np, 0);
2880 if (!priv->reg) {
2881 dev_err(dev, "failed to of_iomap\n");
2882 err = -ENOMEM;
2883 goto err_out;
2884 }
2885
2886 /* get SEC version capabilities from device tree */
2887 prop = of_get_property(np, "fsl,num-channels", NULL);
2888 if (prop)
2889 priv->num_channels = *prop;
2890
2891 prop = of_get_property(np, "fsl,channel-fifo-len", NULL);
2892 if (prop)
2893 priv->chfifo_len = *prop;
2894
2895 prop = of_get_property(np, "fsl,exec-units-mask", NULL);
2896 if (prop)
2897 priv->exec_units = *prop;
2898
2899 prop = of_get_property(np, "fsl,descriptor-types-mask", NULL);
2900 if (prop)
2901 priv->desc_types = *prop;
2902
2903 if (!is_power_of_2(priv->num_channels) || !priv->chfifo_len ||
2904 !priv->exec_units || !priv->desc_types) {
2905 dev_err(dev, "invalid property data in device tree node\n");
2906 err = -EINVAL;
2907 goto err_out;
2908 }
2909
Lee Nipperf3c85bc2008-07-30 16:26:57 +08002910 if (of_device_is_compatible(np, "fsl,sec3.0"))
2911 priv->features |= TALITOS_FTR_SRC_LINK_TBL_LEN_INCLUDES_EXTENT;
2912
Kim Phillipsfe5720e2008-10-12 20:33:14 +08002913 if (of_device_is_compatible(np, "fsl,sec2.1"))
Kim Phillips60f208d2010-05-19 19:21:53 +10002914 priv->features |= TALITOS_FTR_HW_AUTH_CHECK |
Lee Nipper79b3a412011-11-21 16:13:25 +08002915 TALITOS_FTR_SHA224_HWINIT |
2916 TALITOS_FTR_HMAC_OK;
Kim Phillipsfe5720e2008-10-12 20:33:14 +08002917
LEROY Christophe21590882015-04-17 16:32:05 +02002918 if (of_device_is_compatible(np, "fsl,sec1.0"))
2919 priv->features |= TALITOS_FTR_SEC1;
2920
LEROY Christophe5fa7fa12015-04-17 16:32:11 +02002921 if (of_device_is_compatible(np, "fsl,sec1.2")) {
2922 priv->reg_deu = priv->reg + TALITOS12_DEU;
2923 priv->reg_aesu = priv->reg + TALITOS12_AESU;
2924 priv->reg_mdeu = priv->reg + TALITOS12_MDEU;
2925 stride = TALITOS1_CH_STRIDE;
2926 } else if (of_device_is_compatible(np, "fsl,sec1.0")) {
2927 priv->reg_deu = priv->reg + TALITOS10_DEU;
2928 priv->reg_aesu = priv->reg + TALITOS10_AESU;
2929 priv->reg_mdeu = priv->reg + TALITOS10_MDEU;
2930 priv->reg_afeu = priv->reg + TALITOS10_AFEU;
2931 priv->reg_rngu = priv->reg + TALITOS10_RNGU;
2932 priv->reg_pkeu = priv->reg + TALITOS10_PKEU;
2933 stride = TALITOS1_CH_STRIDE;
2934 } else {
2935 priv->reg_deu = priv->reg + TALITOS2_DEU;
2936 priv->reg_aesu = priv->reg + TALITOS2_AESU;
2937 priv->reg_mdeu = priv->reg + TALITOS2_MDEU;
2938 priv->reg_afeu = priv->reg + TALITOS2_AFEU;
2939 priv->reg_rngu = priv->reg + TALITOS2_RNGU;
2940 priv->reg_pkeu = priv->reg + TALITOS2_PKEU;
2941 priv->reg_keu = priv->reg + TALITOS2_KEU;
2942 priv->reg_crcu = priv->reg + TALITOS2_CRCU;
2943 stride = TALITOS2_CH_STRIDE;
2944 }
2945
LEROY Christophedd3c0982015-04-17 16:32:13 +02002946 err = talitos_probe_irq(ofdev);
2947 if (err)
2948 goto err_out;
2949
2950 if (of_device_is_compatible(np, "fsl,sec1.0")) {
2951 tasklet_init(&priv->done_task[0], talitos1_done_4ch,
2952 (unsigned long)dev);
2953 } else {
2954 if (!priv->irq[1]) {
2955 tasklet_init(&priv->done_task[0], talitos2_done_4ch,
2956 (unsigned long)dev);
2957 } else {
2958 tasklet_init(&priv->done_task[0], talitos2_done_ch0_2,
2959 (unsigned long)dev);
2960 tasklet_init(&priv->done_task[1], talitos2_done_ch1_3,
2961 (unsigned long)dev);
2962 }
2963 }
2964
Kim Phillips4b9926282009-08-13 11:50:38 +10002965 priv->chan = kzalloc(sizeof(struct talitos_channel) *
2966 priv->num_channels, GFP_KERNEL);
2967 if (!priv->chan) {
2968 dev_err(dev, "failed to allocate channel management space\n");
Kim Phillips9c4a7962008-06-23 19:50:15 +08002969 err = -ENOMEM;
2970 goto err_out;
2971 }
2972
Martin Hicksf641ddd2015-03-03 08:21:33 -05002973 priv->fifo_len = roundup_pow_of_two(priv->chfifo_len);
2974
Kim Phillipsc3e337f2011-11-21 16:13:27 +08002975 for (i = 0; i < priv->num_channels; i++) {
LEROY Christophe5fa7fa12015-04-17 16:32:11 +02002976 priv->chan[i].reg = priv->reg + stride * (i + 1);
Kim Phillips2cdba3c2011-12-12 14:59:11 -06002977 if (!priv->irq[1] || !(i & 1))
Kim Phillipsc3e337f2011-11-21 16:13:27 +08002978 priv->chan[i].reg += TALITOS_CH_BASE_OFFSET;
Kim Phillipsad42d5f2011-11-21 16:13:27 +08002979
Kim Phillips4b9926282009-08-13 11:50:38 +10002980 spin_lock_init(&priv->chan[i].head_lock);
2981 spin_lock_init(&priv->chan[i].tail_lock);
Kim Phillips9c4a7962008-06-23 19:50:15 +08002982
Kim Phillips4b9926282009-08-13 11:50:38 +10002983 priv->chan[i].fifo = kzalloc(sizeof(struct talitos_request) *
2984 priv->fifo_len, GFP_KERNEL);
2985 if (!priv->chan[i].fifo) {
Kim Phillips9c4a7962008-06-23 19:50:15 +08002986 dev_err(dev, "failed to allocate request fifo %d\n", i);
2987 err = -ENOMEM;
2988 goto err_out;
2989 }
Kim Phillips9c4a7962008-06-23 19:50:15 +08002990
Kim Phillips4b9926282009-08-13 11:50:38 +10002991 atomic_set(&priv->chan[i].submit_count,
2992 -(priv->chfifo_len - 1));
Martin Hicksf641ddd2015-03-03 08:21:33 -05002993 }
Kim Phillips9c4a7962008-06-23 19:50:15 +08002994
Kim Phillips81eb0242009-08-13 11:51:51 +10002995 dma_set_mask(dev, DMA_BIT_MASK(36));
2996
Kim Phillips9c4a7962008-06-23 19:50:15 +08002997 /* reset and initialize the h/w */
2998 err = init_device(dev);
2999 if (err) {
3000 dev_err(dev, "failed to initialize device\n");
3001 goto err_out;
3002 }
3003
3004 /* register the RNG, if available */
3005 if (hw_supports(dev, DESC_HDR_SEL0_RNG)) {
3006 err = talitos_register_rng(dev);
3007 if (err) {
3008 dev_err(dev, "failed to register hwrng: %d\n", err);
3009 goto err_out;
3010 } else
3011 dev_info(dev, "hwrng\n");
3012 }
3013
3014 /* register crypto algorithms the device supports */
Kim Phillips9c4a7962008-06-23 19:50:15 +08003015 for (i = 0; i < ARRAY_SIZE(driver_algs); i++) {
3016 if (hw_supports(dev, driver_algs[i].desc_hdr_template)) {
3017 struct talitos_crypto_alg *t_alg;
Herbert Xuaeb4c132015-07-30 17:53:22 +08003018 struct crypto_alg *alg = NULL;
Kim Phillips9c4a7962008-06-23 19:50:15 +08003019
3020 t_alg = talitos_alg_alloc(dev, &driver_algs[i]);
3021 if (IS_ERR(t_alg)) {
3022 err = PTR_ERR(t_alg);
Kim Phillips0b2730d2011-12-12 14:59:10 -06003023 if (err == -ENOTSUPP)
Lee Nipper79b3a412011-11-21 16:13:25 +08003024 continue;
Kim Phillips9c4a7962008-06-23 19:50:15 +08003025 goto err_out;
3026 }
3027
Lee Nipperacbf7c622010-05-19 19:19:33 +10003028 switch (t_alg->algt.type) {
3029 case CRYPTO_ALG_TYPE_ABLKCIPHER:
Lee Nipperacbf7c622010-05-19 19:19:33 +10003030 err = crypto_register_alg(
3031 &t_alg->algt.alg.crypto);
Herbert Xuaeb4c132015-07-30 17:53:22 +08003032 alg = &t_alg->algt.alg.crypto;
Lee Nipperacbf7c622010-05-19 19:19:33 +10003033 break;
Herbert Xuaeb4c132015-07-30 17:53:22 +08003034
3035 case CRYPTO_ALG_TYPE_AEAD:
3036 err = crypto_register_aead(
3037 &t_alg->algt.alg.aead);
3038 alg = &t_alg->algt.alg.aead.base;
3039 break;
3040
Lee Nipperacbf7c622010-05-19 19:19:33 +10003041 case CRYPTO_ALG_TYPE_AHASH:
3042 err = crypto_register_ahash(
3043 &t_alg->algt.alg.hash);
Herbert Xuaeb4c132015-07-30 17:53:22 +08003044 alg = &t_alg->algt.alg.hash.halg.base;
Lee Nipperacbf7c622010-05-19 19:19:33 +10003045 break;
3046 }
Kim Phillips9c4a7962008-06-23 19:50:15 +08003047 if (err) {
3048 dev_err(dev, "%s alg registration failed\n",
Herbert Xuaeb4c132015-07-30 17:53:22 +08003049 alg->cra_driver_name);
Kim Phillips9c4a7962008-06-23 19:50:15 +08003050 kfree(t_alg);
Horia Geanta991155b2013-03-20 16:31:38 +02003051 } else
Kim Phillips9c4a7962008-06-23 19:50:15 +08003052 list_add_tail(&t_alg->entry, &priv->alg_list);
Kim Phillips9c4a7962008-06-23 19:50:15 +08003053 }
3054 }
Kim Phillips5b859b6e2011-11-21 16:13:26 +08003055 if (!list_empty(&priv->alg_list))
3056 dev_info(dev, "%s algorithms registered in /proc/crypto\n",
3057 (char *)of_get_property(np, "compatible", NULL));
Kim Phillips9c4a7962008-06-23 19:50:15 +08003058
3059 return 0;
3060
3061err_out:
3062 talitos_remove(ofdev);
Kim Phillips9c4a7962008-06-23 19:50:15 +08003063
3064 return err;
3065}
3066
Márton Németh6c3f9752010-01-17 21:54:01 +11003067static const struct of_device_id talitos_match[] = {
LEROY Christophe0635b7d2015-04-17 16:32:20 +02003068#ifdef CONFIG_CRYPTO_DEV_TALITOS1
3069 {
3070 .compatible = "fsl,sec1.0",
3071 },
3072#endif
3073#ifdef CONFIG_CRYPTO_DEV_TALITOS2
Kim Phillips9c4a7962008-06-23 19:50:15 +08003074 {
3075 .compatible = "fsl,sec2.0",
3076 },
LEROY Christophe0635b7d2015-04-17 16:32:20 +02003077#endif
Kim Phillips9c4a7962008-06-23 19:50:15 +08003078 {},
3079};
3080MODULE_DEVICE_TABLE(of, talitos_match);
3081
Grant Likely1c48a5c2011-02-17 02:43:24 -07003082static struct platform_driver talitos_driver = {
Grant Likely40182942010-04-13 16:13:02 -07003083 .driver = {
3084 .name = "talitos",
Grant Likely40182942010-04-13 16:13:02 -07003085 .of_match_table = talitos_match,
3086 },
Kim Phillips9c4a7962008-06-23 19:50:15 +08003087 .probe = talitos_probe,
Al Viro596f1032008-11-22 17:34:24 +00003088 .remove = talitos_remove,
Kim Phillips9c4a7962008-06-23 19:50:15 +08003089};
3090
Axel Lin741e8c22011-11-26 21:26:19 +08003091module_platform_driver(talitos_driver);
Kim Phillips9c4a7962008-06-23 19:50:15 +08003092
3093MODULE_LICENSE("GPL");
3094MODULE_AUTHOR("Kim Phillips <kim.phillips@freescale.com>");
3095MODULE_DESCRIPTION("Freescale integrated security engine (SEC) driver");