crypto: omap-aes - redundant locking is removed

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@nokia.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
This commit is contained in:
Dmitry Kasatkin 2010-11-30 10:13:28 +02:00 коммит произвёл Herbert Xu
Родитель 3bd2e2216b
Коммит eeb2b202c5
1 изменённых файлов: 32 добавлений и 38 удалений

Просмотреть файл

@ -78,7 +78,7 @@
#define FLAGS_NEW_IV BIT(5) #define FLAGS_NEW_IV BIT(5)
#define FLAGS_INIT BIT(6) #define FLAGS_INIT BIT(6)
#define FLAGS_FAST BIT(7) #define FLAGS_FAST BIT(7)
#define FLAGS_BUSY 8 #define FLAGS_BUSY BIT(8)
struct omap_aes_ctx { struct omap_aes_ctx {
struct omap_aes_dev *dd; 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) static int omap_aes_hw_init(struct omap_aes_dev *dd)
{ {
int err = 0;
clk_enable(dd->iclk); clk_enable(dd->iclk);
if (!(dd->flags & FLAGS_INIT)) { if (!(dd->flags & FLAGS_INIT)) {
/* is it necessary to reset before every operation? */ /* is it necessary to reset before every operation? */
omap_aes_write_mask(dd, AES_REG_MASK, AES_REG_MASK_SOFTRESET, 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");
__asm__ __volatile__("nop"); __asm__ __volatile__("nop");
err = omap_aes_wait(dd, AES_REG_SYSSTATUS, if (omap_aes_wait(dd, AES_REG_SYSSTATUS,
AES_REG_SYSSTATUS_RESETDONE); AES_REG_SYSSTATUS_RESETDONE)) {
if (!err) clk_disable(dd->iclk);
dd->flags |= FLAGS_INIT; return -ETIMEDOUT;
}
dd->flags |= FLAGS_INIT;
} }
return err; return 0;
}
static void omap_aes_hw_cleanup(struct omap_aes_dev *dd)
{
clk_disable(dd->iclk);
} }
static void omap_aes_write_ctrl(struct omap_aes_dev *dd) 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); pr_debug("err: %d\n", err);
dd->flags &= ~FLAGS_BUSY;
ctx = crypto_ablkcipher_ctx(crypto_ablkcipher_reqtfm(dd->req)); ctx = crypto_ablkcipher_ctx(crypto_ablkcipher_reqtfm(dd->req));
if (!dd->total) 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_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_in);
omap_stop_dma(dd->dma_lch_out); 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; 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 crypto_async_request *async_req, *backlog;
struct omap_aes_ctx *ctx; struct omap_aes_ctx *ctx;
struct omap_aes_reqctx *rctx; struct omap_aes_reqctx *rctx;
struct ablkcipher_request *req;
unsigned long flags; unsigned long flags;
int err = 0;
if (dd->total)
goto start;
spin_lock_irqsave(&dd->lock, flags); 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); backlog = crypto_get_backlog(&dd->queue);
async_req = crypto_dequeue_request(&dd->queue); async_req = crypto_dequeue_request(&dd->queue);
if (!async_req) if (async_req)
clear_bit(FLAGS_BUSY, &dd->flags); dd->flags |= FLAGS_BUSY;
spin_unlock_irqrestore(&dd->lock, flags); spin_unlock_irqrestore(&dd->lock, flags);
if (!async_req) 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)) if (!IS_ALIGNED(req->nbytes, AES_BLOCK_SIZE))
pr_err("request size is not exact amount of AES blocks\n"); pr_err("request size is not exact amount of AES blocks\n");
start: omap_aes_crypt_dma_start(dd);
return omap_aes_crypt_dma_start(dd);
return err;
} }
static void omap_aes_task(unsigned long data) static void omap_aes_task(unsigned long data)
{ {
struct omap_aes_dev *dd = (struct omap_aes_dev *)data; struct omap_aes_dev *dd = (struct omap_aes_dev *)data;
int err;
pr_debug("enter\n"); 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"); pr_debug("exit\n");
} }
@ -661,8 +666,6 @@ static int omap_aes_crypt(struct ablkcipher_request *req, unsigned long mode)
crypto_ablkcipher_reqtfm(req)); crypto_ablkcipher_reqtfm(req));
struct omap_aes_reqctx *rctx = ablkcipher_request_ctx(req); struct omap_aes_reqctx *rctx = ablkcipher_request_ctx(req);
struct omap_aes_dev *dd; struct omap_aes_dev *dd;
unsigned long flags;
int err;
pr_debug("nbytes: %d, enc: %d, cbc: %d\n", req->nbytes, pr_debug("nbytes: %d, enc: %d, cbc: %d\n", req->nbytes,
!!(mode & FLAGS_ENCRYPT), !!(mode & FLAGS_ENCRYPT),
@ -674,16 +677,7 @@ static int omap_aes_crypt(struct ablkcipher_request *req, unsigned long mode)
rctx->mode = mode; rctx->mode = mode;
spin_lock_irqsave(&dd->lock, flags); return omap_aes_handle_req(dd, req);
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;
} }
/* ********************** ALG API ************************************ */ /* ********************** ALG API ************************************ */