mirror of
https://github.com/torvalds/linux.git
synced 2026-07-27 17:47:41 +02:00
crypto: talitos/hash - prepare SEC1 descriptor chaining, remove additional descriptor
Currently, when SEC1 has buffered data (nbuf != 0), the ahash code creates an additional descriptor on the fly inside common_nonsnoop_hash() to handle the remainder of the data. This approach is incompatible with the arbitrary-length descriptor chaining that follows. Remove the "additional descriptor" logic from common_nonsnoop_hash() and common_nonsnoop_hash_unmap(). Also remove the nbytes adjustment for SEC1 in ahash_edesc_alloc() that subtracted nbuf. Cc: stable@vger.kernel.org Signed-off-by: Paul Louvel <paul.louvel@bootlin.com> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
This commit is contained in:
parent
f8713d9e60
commit
59b5d899e3
|
|
@ -1788,15 +1788,9 @@ static void common_nonsnoop_hash_unmap(struct device *dev,
|
|||
struct talitos_private *priv = dev_get_drvdata(dev);
|
||||
bool is_sec1 = has_ftr_sec1(priv);
|
||||
struct talitos_desc *desc = &edesc->desc;
|
||||
struct talitos_desc *desc2;
|
||||
|
||||
if (desc->next_desc)
|
||||
desc2 = &edesc->next_desc->desc;
|
||||
|
||||
unmap_single_talitos_ptr(dev, &desc->ptr[5], DMA_FROM_DEVICE);
|
||||
if (desc->next_desc &&
|
||||
desc->ptr[5].ptr != desc2->ptr[5].ptr)
|
||||
unmap_single_talitos_ptr(dev, &desc2->ptr[5], DMA_FROM_DEVICE);
|
||||
|
||||
if (req_ctx->last_desc)
|
||||
memcpy(areq->result, req_ctx->hw_context,
|
||||
crypto_ahash_digestsize(tfm));
|
||||
|
|
@ -1808,13 +1802,6 @@ static void common_nonsnoop_hash_unmap(struct device *dev,
|
|||
if (from_talitos_ptr_len(&desc->ptr[1], is_sec1))
|
||||
unmap_single_talitos_ptr(dev, &desc->ptr[1],
|
||||
DMA_TO_DEVICE);
|
||||
else if (desc->next_desc)
|
||||
unmap_single_talitos_ptr(dev, &desc2->ptr[1],
|
||||
DMA_TO_DEVICE);
|
||||
|
||||
if (is_sec1 && req_ctx->nbuf)
|
||||
unmap_single_talitos_ptr(dev, &desc->ptr[3],
|
||||
DMA_TO_DEVICE);
|
||||
|
||||
if (edesc->dma_len)
|
||||
dma_unmap_single(dev, edesc->dma_link_tbl, edesc->dma_len,
|
||||
|
|
@ -1922,9 +1909,6 @@ static int common_nonsnoop_hash(struct talitos_edesc *edesc,
|
|||
to_talitos_ptr(&desc->ptr[2], ctx->dma_key, ctx->keylen,
|
||||
is_sec1);
|
||||
|
||||
if (is_sec1 && req_ctx->nbuf)
|
||||
length -= req_ctx->nbuf;
|
||||
|
||||
sg_count = edesc->src_nents ?: 1;
|
||||
if (is_sec1 && sg_count > 1)
|
||||
sg_copy_to_buffer(req_ctx->psrc, sg_count, edesc->buf, length);
|
||||
|
|
@ -1934,16 +1918,10 @@ static int common_nonsnoop_hash(struct talitos_edesc *edesc,
|
|||
/*
|
||||
* data in
|
||||
*/
|
||||
if (is_sec1 && req_ctx->nbuf) {
|
||||
map_single_talitos_ptr(dev, &desc->ptr[3], req_ctx->nbuf,
|
||||
req_ctx->buf[req_ctx->buf_idx],
|
||||
DMA_TO_DEVICE);
|
||||
} else {
|
||||
sg_count = talitos_sg_map(dev, req_ctx->psrc, length, edesc,
|
||||
&desc->ptr[3], sg_count, 0, 0);
|
||||
if (sg_count > 1)
|
||||
sync_needed = true;
|
||||
}
|
||||
sg_count = talitos_sg_map(dev, req_ctx->psrc, length, edesc,
|
||||
&desc->ptr[3], sg_count, 0, 0);
|
||||
if (sg_count > 1)
|
||||
sync_needed = true;
|
||||
|
||||
/* fifth DWORD empty */
|
||||
|
||||
|
|
@ -1963,49 +1941,6 @@ static int common_nonsnoop_hash(struct talitos_edesc *edesc,
|
|||
if (is_sec1 && from_talitos_ptr_len(&desc->ptr[3], true) == 0)
|
||||
talitos_handle_buggy_hash(ctx, edesc, &desc->ptr[3]);
|
||||
|
||||
if (is_sec1 && req_ctx->nbuf && length) {
|
||||
struct talitos_edesc *edesc2;
|
||||
struct talitos_desc *desc2;
|
||||
|
||||
edesc2 = kzalloc(sizeof(*edesc2),
|
||||
areq->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP ?
|
||||
GFP_KERNEL :
|
||||
GFP_ATOMIC);
|
||||
if (!edesc2) {
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
edesc->next_desc = edesc2;
|
||||
|
||||
desc2 = &edesc2->desc;
|
||||
|
||||
desc2->hdr = desc->hdr;
|
||||
desc2->hdr &= ~DESC_HDR_MODE0_MDEU_INIT;
|
||||
desc->hdr &= ~DESC_HDR_MODE0_MDEU_PAD;
|
||||
desc->hdr |= DESC_HDR_MODE0_MDEU_CONT;
|
||||
desc->hdr &= ~DESC_HDR_DONE_NOTIFY;
|
||||
|
||||
if (desc->ptr[1].ptr)
|
||||
copy_talitos_ptr(&desc2->ptr[1], &desc->ptr[1],
|
||||
is_sec1);
|
||||
else
|
||||
map_single_talitos_ptr_nosync(dev, &desc2->ptr[1],
|
||||
req_ctx->hw_context_size,
|
||||
req_ctx->hw_context,
|
||||
DMA_TO_DEVICE);
|
||||
copy_talitos_ptr(&desc2->ptr[2], &desc->ptr[2], is_sec1);
|
||||
sg_count = talitos_sg_map(dev, req_ctx->psrc, length, edesc,
|
||||
&desc2->ptr[3], sg_count, 0, 0);
|
||||
if (sg_count > 1)
|
||||
sync_needed = true;
|
||||
copy_talitos_ptr(&desc2->ptr[5], &desc->ptr[5], is_sec1);
|
||||
if (req_ctx->last_desc)
|
||||
map_single_talitos_ptr_nosync(dev, &desc->ptr[5],
|
||||
req_ctx->hw_context_size,
|
||||
req_ctx->hw_context,
|
||||
DMA_FROM_DEVICE);
|
||||
}
|
||||
|
||||
if (sync_needed)
|
||||
dma_sync_single_for_device(dev, edesc->dma_link_tbl,
|
||||
edesc->dma_len, DMA_BIDIRECTIONAL);
|
||||
|
|
@ -2028,11 +1963,6 @@ static struct talitos_edesc *ahash_edesc_alloc(struct ahash_request *areq,
|
|||
struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
|
||||
struct talitos_ctx *ctx = crypto_ahash_ctx(tfm);
|
||||
struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
|
||||
struct talitos_private *priv = dev_get_drvdata(ctx->dev);
|
||||
bool is_sec1 = has_ftr_sec1(priv);
|
||||
|
||||
if (is_sec1)
|
||||
nbytes -= req_ctx->nbuf;
|
||||
|
||||
return talitos_edesc_alloc(ctx->dev, req_ctx->psrc, NULL, NULL, 0,
|
||||
nbytes, 0, 0, 0, areq->base.flags, false);
|
||||
|
|
@ -2051,8 +1981,6 @@ static int ahash_process_req_one(struct ahash_request *areq, unsigned int nbytes
|
|||
unsigned int nsg;
|
||||
int nents;
|
||||
struct device *dev = ctx->dev;
|
||||
struct talitos_private *priv = dev_get_drvdata(dev);
|
||||
bool is_sec1 = has_ftr_sec1(priv);
|
||||
u8 *ctx_buf = req_ctx->buf[req_ctx->buf_idx];
|
||||
|
||||
if (!req_ctx->last_desc && (nbytes + req_ctx->nbuf <= blocksize)) {
|
||||
|
|
@ -2084,30 +2012,13 @@ static int ahash_process_req_one(struct ahash_request *areq, unsigned int nbytes
|
|||
}
|
||||
|
||||
/* Chain in any previously buffered data */
|
||||
if (!is_sec1 && req_ctx->nbuf) {
|
||||
if (req_ctx->nbuf) {
|
||||
nsg = (req_ctx->nbuf < nbytes_to_hash) ? 2 : 1;
|
||||
sg_init_table(req_ctx->bufsl, nsg);
|
||||
sg_set_buf(req_ctx->bufsl, ctx_buf, req_ctx->nbuf);
|
||||
if (nsg > 1)
|
||||
sg_chain(req_ctx->bufsl, 2, req_ctx->request_sl);
|
||||
req_ctx->psrc = req_ctx->bufsl;
|
||||
} else if (is_sec1 && req_ctx->nbuf && req_ctx->nbuf < blocksize) {
|
||||
int offset;
|
||||
|
||||
if (nbytes_to_hash > blocksize)
|
||||
offset = blocksize - req_ctx->nbuf;
|
||||
else
|
||||
offset = nbytes_to_hash - req_ctx->nbuf;
|
||||
nents = sg_nents_for_len(req_ctx->request_sl, offset);
|
||||
if (nents < 0) {
|
||||
dev_err(dev, "Invalid number of src SG.\n");
|
||||
return nents;
|
||||
}
|
||||
sg_copy_to_buffer(req_ctx->request_sl, nents,
|
||||
ctx_buf + req_ctx->nbuf, offset);
|
||||
req_ctx->nbuf += offset;
|
||||
req_ctx->psrc = scatterwalk_ffwd(req_ctx->bufsl, req_ctx->request_sl,
|
||||
offset);
|
||||
} else
|
||||
req_ctx->psrc = req_ctx->request_sl;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user