Submitting request involved double locking for enqueuing and dequeuing. Now it is done under the same lock. FLAGS_BUSY is now handled under the same lock. Signed-off-by: Dmitry Kasatkin <dmitry.kasatkin@xxxxxxxxx> --- drivers/crypto/omap-aes.c | 70 ++++++++++++++++++++------------------------ 1 files changed, 32 insertions(+), 38 deletions(-) diff --git a/drivers/crypto/omap-aes.c b/drivers/crypto/omap-aes.c index 41c91f3..2d8f72e 100644 --- a/drivers/crypto/omap-aes.c +++ b/drivers/crypto/omap-aes.c @@ -78,7 +78,7 @@ #define FLAGS_NEW_IV BIT(5) #define FLAGS_INIT BIT(6) #define FLAGS_FAST BIT(7) -#define FLAGS_BUSY 8 +#define FLAGS_BUSY BIT(8) struct omap_aes_ctx { struct omap_aes_dev *dd; @@ -179,9 +179,8 @@ static int omap_aes_wait(struct omap_aes_dev *dd, u32 offset, u32 bit) static int omap_aes_hw_init(struct omap_aes_dev *dd) { - int err = 0; - clk_enable(dd->iclk); + if (!(dd->flags & FLAGS_INIT)) { /* is it necessary to reset before every operation? */ omap_aes_write_mask(dd, AES_REG_MASK, AES_REG_MASK_SOFTRESET, @@ -193,18 +192,15 @@ static int omap_aes_hw_init(struct omap_aes_dev *dd) __asm__ __volatile__("nop"); __asm__ __volatile__("nop"); - err = omap_aes_wait(dd, AES_REG_SYSSTATUS, - AES_REG_SYSSTATUS_RESETDONE); - if (!err) - dd->flags |= FLAGS_INIT; + if (omap_aes_wait(dd, AES_REG_SYSSTATUS, + AES_REG_SYSSTATUS_RESETDONE)) { + clk_disable(dd->iclk); + return -ETIMEDOUT; + } + dd->flags |= FLAGS_INIT; } - return err; -} - -static void omap_aes_hw_cleanup(struct omap_aes_dev *dd) -{ - clk_disable(dd->iclk); + return 0; } static void omap_aes_write_ctrl(struct omap_aes_dev *dd) @@ -538,6 +534,8 @@ static void omap_aes_finish_req(struct omap_aes_dev *dd, int err) pr_debug("err: %d\n", err); + dd->flags &= ~FLAGS_BUSY; + ctx = crypto_ablkcipher_ctx(crypto_ablkcipher_reqtfm(dd->req)); if (!dd->total) @@ -553,7 +551,7 @@ static int omap_aes_crypt_dma_stop(struct omap_aes_dev *dd) omap_aes_write_mask(dd, AES_REG_MASK, 0, AES_REG_MASK_START); - omap_aes_hw_cleanup(dd); + clk_disable(dd->iclk); omap_stop_dma(dd->dma_lch_in); omap_stop_dma(dd->dma_lch_out); @@ -580,22 +578,26 @@ static int omap_aes_crypt_dma_stop(struct omap_aes_dev *dd) return err; } -static int omap_aes_handle_req(struct omap_aes_dev *dd) +static int omap_aes_handle_req(struct omap_aes_dev *dd, + struct ablkcipher_request *req) { struct crypto_async_request *async_req, *backlog; struct omap_aes_ctx *ctx; struct omap_aes_reqctx *rctx; - struct ablkcipher_request *req; unsigned long flags; - - if (dd->total) - goto start; + int err = 0; spin_lock_irqsave(&dd->lock, flags); + if (req) + err = ablkcipher_enqueue_request(&dd->queue, req); + if (dd->flags & FLAGS_BUSY) { + spin_unlock_irqrestore(&dd->lock, flags); + return err; + } backlog = crypto_get_backlog(&dd->queue); async_req = crypto_dequeue_request(&dd->queue); - if (!async_req) - clear_bit(FLAGS_BUSY, &dd->flags); + if (async_req) + dd->flags |= FLAGS_BUSY; spin_unlock_irqrestore(&dd->lock, flags); if (!async_req) @@ -637,20 +639,23 @@ static int omap_aes_handle_req(struct omap_aes_dev *dd) if (!IS_ALIGNED(req->nbytes, AES_BLOCK_SIZE)) pr_err("request size is not exact amount of AES blocks\n"); -start: - return omap_aes_crypt_dma_start(dd); + omap_aes_crypt_dma_start(dd); + + return err; } static void omap_aes_task(unsigned long data) { struct omap_aes_dev *dd = (struct omap_aes_dev *)data; - int err; pr_debug("enter\n"); - err = omap_aes_crypt_dma_stop(dd); + omap_aes_crypt_dma_stop(dd); - err = omap_aes_handle_req(dd); + if (dd->total) + omap_aes_crypt_dma_start(dd); + else + omap_aes_handle_req(dd, NULL); pr_debug("exit\n"); } @@ -661,8 +666,6 @@ static int omap_aes_crypt(struct ablkcipher_request *req, unsigned long mode) crypto_ablkcipher_reqtfm(req)); struct omap_aes_reqctx *rctx = ablkcipher_request_ctx(req); struct omap_aes_dev *dd; - unsigned long flags; - int err; pr_debug("nbytes: %d, enc: %d, cbc: %d\n", req->nbytes, !!(mode & FLAGS_ENCRYPT), @@ -674,16 +677,7 @@ static int omap_aes_crypt(struct ablkcipher_request *req, unsigned long mode) rctx->mode = mode; - spin_lock_irqsave(&dd->lock, flags); - err = ablkcipher_enqueue_request(&dd->queue, req); - spin_unlock_irqrestore(&dd->lock, flags); - - if (!test_and_set_bit(FLAGS_BUSY, &dd->flags)) - omap_aes_handle_req(dd); - - pr_debug("exit\n"); - - return err; + return omap_aes_handle_req(dd, req); } /* ********************** ALG API ************************************ */ -- 1.7.0.4 -- To unsubscribe from this list: send the line "unsubscribe linux-crypto" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html