summaryrefslogtreecommitdiff
path: root/drivers/crypto/atmel-sha.c
diff options
context:
space:
mode:
authorCyrille Pitchen <cyrille.pitchen@atmel.com>2017-02-09 17:51:21 +0100
committerHerbert Xu <herbert@gondor.apana.org.au>2017-02-15 13:23:33 +0800
commit19998acb0ff67cb8843668f3b94bdbe6018fa7d8 (patch)
tree30c4a789fee823f608a4496661d05e3094dd955e /drivers/crypto/atmel-sha.c
parentdd3f9f40b58168f91f27ab686c7bae1f35edd3d4 (diff)
crypto: atmel-sha - fix error management in atmel_sha_start()
This patch clarifies and fixes how errors should be handled by atmel_sha_start(). For update operations, the previous code wrongly assumed that (err != -EINPROGRESS) implies (err == 0). It's wrong because that doesn't take the error cases (err < 0) into account. This patch also adds many comments to detail all the possible returned values and what should be done in each case. Especially, when an error occurs, since atmel_sha_complete() has already been called, hence releasing the hardware, atmel_sha_start() must not call atmel_sha_finish_req() later otherwise atmel_sha_complete() would be called a second time. Signed-off-by: Cyrille Pitchen <cyrille.pitchen@atmel.com> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to 'drivers/crypto/atmel-sha.c')
-rw-r--r--drivers/crypto/atmel-sha.c27
1 files changed, 22 insertions, 5 deletions
diff --git a/drivers/crypto/atmel-sha.c b/drivers/crypto/atmel-sha.c
index bc033178d0e7..a9482023d7d3 100644
--- a/drivers/crypto/atmel-sha.c
+++ b/drivers/crypto/atmel-sha.c
@@ -1106,22 +1106,39 @@ static int atmel_sha_start(struct atmel_sha_dev *dd)
ctx->op, req->nbytes);
err = atmel_sha_hw_init(dd);
-
if (err)
- goto err1;
+ return atmel_sha_complete(dd, err);
+
+ /*
+ * atmel_sha_update_req() and atmel_sha_final_req() can return either:
+ * -EINPROGRESS: the hardware is busy and the SHA driver will resume
+ * its job later in the done_task.
+ * This is the main path.
+ *
+ * 0: the SHA driver can continue its job then release the hardware
+ * later, if needed, with atmel_sha_finish_req().
+ * This is the alternate path.
+ *
+ * < 0: an error has occurred so atmel_sha_complete(dd, err) has already
+ * been called, hence the hardware has been released.
+ * The SHA driver must stop its job without calling
+ * atmel_sha_finish_req(), otherwise atmel_sha_complete() would be
+ * called a second time.
+ *
+ * Please note that currently, atmel_sha_final_req() never returns 0.
+ */
dd->resume = atmel_sha_done;
if (ctx->op == SHA_OP_UPDATE) {
err = atmel_sha_update_req(dd);
- if (err != -EINPROGRESS && (ctx->flags & SHA_FLAGS_FINUP))
+ if (!err && (ctx->flags & SHA_FLAGS_FINUP))
/* no final() after finup() */
err = atmel_sha_final_req(dd);
} else if (ctx->op == SHA_OP_FINAL) {
err = atmel_sha_final_req(dd);
}
-err1:
- if (err != -EINPROGRESS)
+ if (!err)
/* done_task will not finish it, so do it here */
atmel_sha_finish_req(req, err);