Lines Matching +full:op +full:- +full:mode
1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * sun4i-ss-hash.c - hardware cryptographic accelerator for Allwinner A20 SoC
5 * Copyright (C) 2013-2015 Corentin LABBE <clabbe.montjoie@gmail.com>
11 #include "sun4i-ss.h"
20 struct sun4i_tfm_ctx *op = crypto_tfm_ctx(tfm); in sun4i_hash_crainit() local
21 struct ahash_alg *alg = __crypto_ahash_alg(tfm->__crt_alg); in sun4i_hash_crainit()
25 memset(op, 0, sizeof(struct sun4i_tfm_ctx)); in sun4i_hash_crainit()
28 op->ss = algt->ss; in sun4i_hash_crainit()
30 err = pm_runtime_resume_and_get(op->ss->dev); in sun4i_hash_crainit()
41 struct sun4i_tfm_ctx *op = crypto_tfm_ctx(tfm); in sun4i_hash_craexit() local
43 pm_runtime_put(op->ss->dev); in sun4i_hash_craexit()
49 struct sun4i_req_ctx *op = ahash_request_ctx(areq); in sun4i_hash_init() local
51 struct ahash_alg *alg = __crypto_ahash_alg(tfm->base.__crt_alg); in sun4i_hash_init()
54 memset(op, 0, sizeof(struct sun4i_req_ctx)); in sun4i_hash_init()
57 op->mode = algt->mode; in sun4i_hash_init()
64 struct sun4i_req_ctx *op = ahash_request_ctx(areq); in sun4i_hash_export_md5() local
68 octx->byte_count = op->byte_count + op->len; in sun4i_hash_export_md5()
70 memcpy(octx->block, op->buf, op->len); in sun4i_hash_export_md5()
72 if (op->byte_count) { in sun4i_hash_export_md5()
74 octx->hash[i] = op->hash[i]; in sun4i_hash_export_md5()
76 octx->hash[0] = SHA1_H0; in sun4i_hash_export_md5()
77 octx->hash[1] = SHA1_H1; in sun4i_hash_export_md5()
78 octx->hash[2] = SHA1_H2; in sun4i_hash_export_md5()
79 octx->hash[3] = SHA1_H3; in sun4i_hash_export_md5()
87 struct sun4i_req_ctx *op = ahash_request_ctx(areq); in sun4i_hash_import_md5() local
93 op->byte_count = ictx->byte_count & ~0x3F; in sun4i_hash_import_md5()
94 op->len = ictx->byte_count & 0x3F; in sun4i_hash_import_md5()
96 memcpy(op->buf, ictx->block, op->len); in sun4i_hash_import_md5()
99 op->hash[i] = ictx->hash[i]; in sun4i_hash_import_md5()
106 struct sun4i_req_ctx *op = ahash_request_ctx(areq); in sun4i_hash_export_sha1() local
110 octx->count = op->byte_count + op->len; in sun4i_hash_export_sha1()
112 memcpy(octx->buffer, op->buf, op->len); in sun4i_hash_export_sha1()
114 if (op->byte_count) { in sun4i_hash_export_sha1()
116 octx->state[i] = op->hash[i]; in sun4i_hash_export_sha1()
118 octx->state[0] = SHA1_H0; in sun4i_hash_export_sha1()
119 octx->state[1] = SHA1_H1; in sun4i_hash_export_sha1()
120 octx->state[2] = SHA1_H2; in sun4i_hash_export_sha1()
121 octx->state[3] = SHA1_H3; in sun4i_hash_export_sha1()
122 octx->state[4] = SHA1_H4; in sun4i_hash_export_sha1()
130 struct sun4i_req_ctx *op = ahash_request_ctx(areq); in sun4i_hash_import_sha1() local
136 op->byte_count = ictx->count & ~0x3F; in sun4i_hash_import_sha1()
137 op->len = ictx->count & 0x3F; in sun4i_hash_import_sha1()
139 memcpy(op->buf, ictx->buffer, op->len); in sun4i_hash_import_sha1()
142 op->hash[i] = ictx->state[i]; in sun4i_hash_import_sha1()
161 * The extra bytes will go to a temporary buffer op->buf storing op->len bytes
164 * if op->len + areq->nbytes < 64
165 * => all data will be written to wait buffer (op->buf) and end=0
166 * if not, write all data from op->buf to the device and position end to
170 * update1 60o => op->len=60
173 * so write all data from op->buf and one word of SGs
174 * write remaining data in op->buf
175 * final state op->len=56
180 * i is the total bytes read from SGs, to be compared to areq->nbytes in sun4i_hash()
182 * SG->length could be greater than areq->nbytes in sun4i_hash()
192 struct sun4i_req_ctx *op = ahash_request_ctx(areq); in sun4i_hash() local
194 struct ahash_alg *alg = __crypto_ahash_alg(tfm->base.__crt_alg); in sun4i_hash()
196 struct sun4i_ss_ctx *ss = tfmctx->ss; in sun4i_hash()
198 struct scatterlist *in_sg = areq->src; in sun4i_hash()
204 dev_dbg(ss->dev, "%s %s bc=%llu len=%u mode=%x wl=%u h0=%0x", in sun4i_hash()
205 __func__, crypto_tfm_alg_name(areq->base.tfm), in sun4i_hash()
206 op->byte_count, areq->nbytes, op->mode, in sun4i_hash()
207 op->len, op->hash[0]); in sun4i_hash()
209 if (unlikely(!areq->nbytes) && !(op->flags & SS_HASH_FINAL)) in sun4i_hash()
213 if (unlikely(areq->nbytes > UINT_MAX - op->len)) { in sun4i_hash()
214 dev_err(ss->dev, "Cannot process too large request\n"); in sun4i_hash()
215 return -EINVAL; in sun4i_hash()
218 if (op->len + areq->nbytes < 64 && !(op->flags & SS_HASH_FINAL)) { in sun4i_hash()
219 /* linearize data to op->buf */ in sun4i_hash()
220 copied = sg_pcopy_to_buffer(areq->src, sg_nents(areq->src), in sun4i_hash()
221 op->buf + op->len, areq->nbytes, 0); in sun4i_hash()
222 op->len += copied; in sun4i_hash()
226 spin_lock_bh(&ss->slock); in sun4i_hash()
232 if (op->byte_count) { in sun4i_hash()
235 writel(op->hash[i], ss->base + SS_IV0 + i * 4); in sun4i_hash()
238 writel(op->mode | SS_ENABLED | ivmode, ss->base + SS_CTL); in sun4i_hash()
240 if (!(op->flags & SS_HASH_UPDATE)) in sun4i_hash()
244 if (!(op->flags & SS_HASH_FINAL)) { in sun4i_hash()
245 end = ((areq->nbytes + op->len) / 64) * 64 - op->len; in sun4i_hash()
247 if (end > areq->nbytes || areq->nbytes - end > 63) { in sun4i_hash()
248 dev_err(ss->dev, "ERROR: Bound error %u %u\n", in sun4i_hash()
249 end, areq->nbytes); in sun4i_hash()
250 err = -EINVAL; in sun4i_hash()
255 if (areq->nbytes < 4) in sun4i_hash()
258 end = ((areq->nbytes + op->len) / 4) * 4 - op->len; in sun4i_hash()
261 /* TODO if SGlen % 4 and !op->len then DMA */ in sun4i_hash()
264 if (in_sg->length % 4) in sun4i_hash()
268 if (i == 1 && !op->len && areq->nbytes) in sun4i_hash()
269 dev_dbg(ss->dev, "We can DMA\n"); in sun4i_hash()
272 sg_miter_start(&mi, areq->src, sg_nents(areq->src), in sun4i_hash()
280 * - the buffer is already used in sun4i_hash()
281 * - the SG does not have enough byte remaining ( < 4) in sun4i_hash()
283 if (op->len || (mi.length - in_i) < 4) { in sun4i_hash()
286 * - the buffer is full in sun4i_hash()
287 * - reach the end in sun4i_hash()
289 while (op->len < 64 && i < end) { in sun4i_hash()
291 in_r = min(end - i, 64 - op->len); in sun4i_hash()
292 in_r = min_t(size_t, mi.length - in_i, in_r); in sun4i_hash()
293 memcpy(op->buf + op->len, mi.addr + in_i, in_r); in sun4i_hash()
294 op->len += in_r; in sun4i_hash()
302 if (op->len > 3 && !(op->len % 4)) { in sun4i_hash()
304 writesl(ss->base + SS_RXFIFO, op->buf, in sun4i_hash()
305 op->len / 4); in sun4i_hash()
306 op->byte_count += op->len; in sun4i_hash()
307 op->len = 0; in sun4i_hash()
310 if (mi.length - in_i > 3 && i < end) { in sun4i_hash()
312 in_r = min_t(size_t, mi.length - in_i, areq->nbytes - i); in sun4i_hash()
313 in_r = min_t(size_t, ((mi.length - in_i) / 4) * 4, in_r); in sun4i_hash()
315 todo = min3((u32)(end - i) / 4, rx_cnt, (u32)in_r / 4); in sun4i_hash()
316 writesl(ss->base + SS_RXFIFO, mi.addr + in_i, todo); in sun4i_hash()
317 op->byte_count += todo * 4; in sun4i_hash()
320 rx_cnt -= todo; in sun4i_hash()
322 spaces = readl(ss->base + SS_FCSR); in sun4i_hash()
334 * store the remaining bytes in op->buf in sun4i_hash()
336 if ((areq->nbytes - i) < 64) { in sun4i_hash()
337 while (i < areq->nbytes && in_i < mi.length && op->len < 64) { in sun4i_hash()
339 in_r = min(areq->nbytes - i, 64 - op->len); in sun4i_hash()
340 in_r = min_t(size_t, mi.length - in_i, in_r); in sun4i_hash()
341 memcpy(op->buf + op->len, mi.addr + in_i, in_r); in sun4i_hash()
342 op->len += in_r; in sun4i_hash()
359 if (op->flags & SS_HASH_FINAL) in sun4i_hash()
362 writel(op->mode | SS_ENABLED | SS_DATA_END, ss->base + SS_CTL); in sun4i_hash()
365 v = readl(ss->base + SS_CTL); in sun4i_hash()
369 dev_err_ratelimited(ss->dev, in sun4i_hash()
371 i, SS_TIMEOUT, v, areq->nbytes); in sun4i_hash()
372 err = -EIO; in sun4i_hash()
386 op->hash[i] = readl(ss->base + SS_MD0 + i * 4); in sun4i_hash()
405 algt->stat_req++; in sun4i_hash()
409 if (op->len) { in sun4i_hash()
410 nwait = op->len / 4; in sun4i_hash()
412 writesl(ss->base + SS_RXFIFO, op->buf, nwait); in sun4i_hash()
413 op->byte_count += 4 * nwait; in sun4i_hash()
416 nbw = op->len - 4 * nwait; in sun4i_hash()
418 wb = le32_to_cpup((__le32 *)(op->buf + nwait * 4)); in sun4i_hash()
419 wb &= GENMASK((nbw * 8) - 1, 0); in sun4i_hash()
421 op->byte_count += nbw; in sun4i_hash()
435 fill = 64 - (op->byte_count % 64); in sun4i_hash()
442 j += (fill - min_fill) / sizeof(u32); in sun4i_hash()
445 if (op->mode == SS_OP_SHA1) { in sun4i_hash()
447 *bits = cpu_to_be64(op->byte_count << 3); in sun4i_hash()
451 *bits = cpu_to_le64(op->byte_count << 3); in sun4i_hash()
454 writesl(ss->base + SS_RXFIFO, bf, j); in sun4i_hash()
457 writel(op->mode | SS_ENABLED | SS_DATA_END, ss->base + SS_CTL); in sun4i_hash()
466 v = readl(ss->base + SS_CTL); in sun4i_hash()
470 dev_err_ratelimited(ss->dev, in sun4i_hash()
472 i, SS_TIMEOUT, v, areq->nbytes); in sun4i_hash()
473 err = -EIO; in sun4i_hash()
487 if (op->mode == SS_OP_SHA1) { in sun4i_hash()
489 v = readl(ss->base + SS_MD0 + i * 4); in sun4i_hash()
490 if (ss->variant->sha1_in_be) in sun4i_hash()
491 put_unaligned_le32(v, areq->result + i * 4); in sun4i_hash()
493 put_unaligned_be32(v, areq->result + i * 4); in sun4i_hash()
497 v = readl(ss->base + SS_MD0 + i * 4); in sun4i_hash()
498 put_unaligned_le32(v, areq->result + i * 4); in sun4i_hash()
503 writel(0, ss->base + SS_CTL); in sun4i_hash()
504 spin_unlock_bh(&ss->slock); in sun4i_hash()
510 struct sun4i_req_ctx *op = ahash_request_ctx(areq); in sun4i_hash_final() local
512 op->flags = SS_HASH_FINAL; in sun4i_hash_final()
518 struct sun4i_req_ctx *op = ahash_request_ctx(areq); in sun4i_hash_update() local
520 op->flags = SS_HASH_UPDATE; in sun4i_hash_update()
527 struct sun4i_req_ctx *op = ahash_request_ctx(areq); in sun4i_hash_finup() local
529 op->flags = SS_HASH_UPDATE | SS_HASH_FINAL; in sun4i_hash_finup()
537 struct sun4i_req_ctx *op = ahash_request_ctx(areq); in sun4i_hash_digest() local
543 op->flags = SS_HASH_UPDATE | SS_HASH_FINAL; in sun4i_hash_digest()