crypto: omap-aes - redundant locking is removed
[pandora-kernel.git] / drivers / crypto / omap-aes.c
index 799ca51..2d8f72e 100644 (file)
@@ -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)
@@ -339,18 +335,6 @@ static int omap_aes_dma_init(struct omap_aes_dev *dd)
                goto err_dma_out;
        }
 
-       omap_set_dma_dest_params(dd->dma_lch_in, 0, OMAP_DMA_AMODE_CONSTANT,
-                                dd->phys_base + AES_REG_DATA, 0, 4);
-
-       omap_set_dma_dest_burst_mode(dd->dma_lch_in, OMAP_DMA_DATA_BURST_4);
-       omap_set_dma_src_burst_mode(dd->dma_lch_in, OMAP_DMA_DATA_BURST_4);
-
-       omap_set_dma_src_params(dd->dma_lch_out, 0, OMAP_DMA_AMODE_CONSTANT,
-                               dd->phys_base + AES_REG_DATA, 0, 4);
-
-       omap_set_dma_src_burst_mode(dd->dma_lch_out, OMAP_DMA_DATA_BURST_4);
-       omap_set_dma_dest_burst_mode(dd->dma_lch_out, OMAP_DMA_DATA_BURST_4);
-
        return 0;
 
 err_dma_out:
@@ -443,6 +427,12 @@ static int omap_aes_crypt_dma(struct crypto_tfm *tfm, dma_addr_t dma_addr_in,
        len32 = DIV_ROUND_UP(length, sizeof(u32));
 
        /* IN */
+       omap_set_dma_dest_params(dd->dma_lch_in, 0, OMAP_DMA_AMODE_CONSTANT,
+                                dd->phys_base + AES_REG_DATA, 0, 4);
+
+       omap_set_dma_dest_burst_mode(dd->dma_lch_in, OMAP_DMA_DATA_BURST_4);
+       omap_set_dma_src_burst_mode(dd->dma_lch_in, OMAP_DMA_DATA_BURST_4);
+
        omap_set_dma_transfer_params(dd->dma_lch_in, OMAP_DMA_DATA_TYPE_S32,
                                     len32, 1, OMAP_DMA_SYNC_PACKET, dd->dma_in,
                                        OMAP_DMA_DST_SYNC);
@@ -451,6 +441,12 @@ static int omap_aes_crypt_dma(struct crypto_tfm *tfm, dma_addr_t dma_addr_in,
                                dma_addr_in, 0, 0);
 
        /* OUT */
+       omap_set_dma_src_params(dd->dma_lch_out, 0, OMAP_DMA_AMODE_CONSTANT,
+                               dd->phys_base + AES_REG_DATA, 0, 4);
+
+       omap_set_dma_src_burst_mode(dd->dma_lch_out, OMAP_DMA_DATA_BURST_4);
+       omap_set_dma_dest_burst_mode(dd->dma_lch_out, OMAP_DMA_DATA_BURST_4);
+
        omap_set_dma_transfer_params(dd->dma_lch_out, OMAP_DMA_DATA_TYPE_S32,
                                     len32, 1, OMAP_DMA_SYNC_PACKET,
                                        dd->dma_out, OMAP_DMA_SRC_SYNC);
@@ -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 ************************************ */