diff options
author | Dmitry Kasatkin <dmitry.kasatkin@nokia.com> | 2011-06-02 14:10:06 -0400 |
---|---|---|
committer | Herbert Xu <herbert@gondor.apana.org.au> | 2011-06-29 19:44:02 -0400 |
commit | a929cbeef7d8e5c3603a6f43b977c03c922aada3 (patch) | |
tree | dd5321e7f54daf6eea76902523312a87ed56ad10 | |
parent | ea1fd2246f3c3c6b739529db2a547fa080cf09a3 (diff) |
crypto: omap-sham - replace flags operation with atomic bit operations
Some flags are changed in interrupt handlers and verified in the tasklet.
There might be a race condition when tasklet is interrupted or another
cpu/core will run IRQ handler and tasklet in parallel.
Atomic bitops functions are now used instead of bitmask operations.
Signed-off-by: Dmitry Kasatkin <dmitry.kasatkin@nokia.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
-rw-r--r-- | drivers/crypto/omap-sham.c | 29 |
1 files changed, 13 insertions, 16 deletions
diff --git a/drivers/crypto/omap-sham.c b/drivers/crypto/omap-sham.c index 64698adec0c1..208404e20ef7 100644 --- a/drivers/crypto/omap-sham.c +++ b/drivers/crypto/omap-sham.c | |||
@@ -240,7 +240,7 @@ static int omap_sham_hw_init(struct omap_sham_dev *dd) | |||
240 | { | 240 | { |
241 | clk_enable(dd->iclk); | 241 | clk_enable(dd->iclk); |
242 | 242 | ||
243 | if (!(dd->flags & BIT(FLAGS_INIT))) { | 243 | if (!test_bit(FLAGS_INIT, &dd->flags)) { |
244 | omap_sham_write_mask(dd, SHA_REG_MASK, | 244 | omap_sham_write_mask(dd, SHA_REG_MASK, |
245 | SHA_REG_MASK_SOFTRESET, SHA_REG_MASK_SOFTRESET); | 245 | SHA_REG_MASK_SOFTRESET, SHA_REG_MASK_SOFTRESET); |
246 | 246 | ||
@@ -248,7 +248,7 @@ static int omap_sham_hw_init(struct omap_sham_dev *dd) | |||
248 | SHA_REG_SYSSTATUS_RESETDONE)) | 248 | SHA_REG_SYSSTATUS_RESETDONE)) |
249 | return -ETIMEDOUT; | 249 | return -ETIMEDOUT; |
250 | 250 | ||
251 | dd->flags |= BIT(FLAGS_INIT); | 251 | set_bit(FLAGS_INIT, &dd->flags); |
252 | dd->err = 0; | 252 | dd->err = 0; |
253 | } | 253 | } |
254 | 254 | ||
@@ -303,7 +303,7 @@ static int omap_sham_xmit_cpu(struct omap_sham_dev *dd, const u8 *buf, | |||
303 | return -ETIMEDOUT; | 303 | return -ETIMEDOUT; |
304 | 304 | ||
305 | if (final) | 305 | if (final) |
306 | ctx->flags |= BIT(FLAGS_FINAL); /* catch last interrupt */ | 306 | set_bit(FLAGS_FINAL, &ctx->flags); /* catch last interrupt */ |
307 | 307 | ||
308 | len32 = DIV_ROUND_UP(length, sizeof(u32)); | 308 | len32 = DIV_ROUND_UP(length, sizeof(u32)); |
309 | 309 | ||
@@ -336,9 +336,9 @@ static int omap_sham_xmit_dma(struct omap_sham_dev *dd, dma_addr_t dma_addr, | |||
336 | ctx->digcnt += length; | 336 | ctx->digcnt += length; |
337 | 337 | ||
338 | if (final) | 338 | if (final) |
339 | ctx->flags |= BIT(FLAGS_FINAL); /* catch last interrupt */ | 339 | set_bit(FLAGS_FINAL, &ctx->flags); /* catch last interrupt */ |
340 | 340 | ||
341 | dd->flags |= BIT(FLAGS_DMA_ACTIVE); | 341 | set_bit(FLAGS_DMA_ACTIVE, &dd->flags); |
342 | 342 | ||
343 | omap_start_dma(dd->dma_lch); | 343 | omap_start_dma(dd->dma_lch); |
344 | 344 | ||
@@ -642,7 +642,7 @@ static void omap_sham_finish_req(struct ahash_request *req, int err) | |||
642 | 642 | ||
643 | if (!err) { | 643 | if (!err) { |
644 | omap_sham_copy_hash(req, 1); | 644 | omap_sham_copy_hash(req, 1); |
645 | if (ctx->flags & BIT(FLAGS_FINAL)) | 645 | if (test_bit(FLAGS_FINAL, &ctx->flags)) |
646 | err = omap_sham_finish(req); | 646 | err = omap_sham_finish(req); |
647 | } else { | 647 | } else { |
648 | ctx->flags |= BIT(FLAGS_ERROR); | 648 | ctx->flags |= BIT(FLAGS_ERROR); |
@@ -666,14 +666,14 @@ static int omap_sham_handle_queue(struct omap_sham_dev *dd, | |||
666 | spin_lock_irqsave(&dd->lock, flags); | 666 | spin_lock_irqsave(&dd->lock, flags); |
667 | if (req) | 667 | if (req) |
668 | ret = ahash_enqueue_request(&dd->queue, req); | 668 | ret = ahash_enqueue_request(&dd->queue, req); |
669 | if (dd->flags & BIT(FLAGS_BUSY)) { | 669 | if (test_bit(FLAGS_BUSY, &dd->flags)) { |
670 | spin_unlock_irqrestore(&dd->lock, flags); | 670 | spin_unlock_irqrestore(&dd->lock, flags); |
671 | return ret; | 671 | return ret; |
672 | } | 672 | } |
673 | backlog = crypto_get_backlog(&dd->queue); | 673 | backlog = crypto_get_backlog(&dd->queue); |
674 | async_req = crypto_dequeue_request(&dd->queue); | 674 | async_req = crypto_dequeue_request(&dd->queue); |
675 | if (async_req) | 675 | if (async_req) |
676 | dd->flags |= BIT(FLAGS_BUSY); | 676 | set_bit(FLAGS_BUSY, &dd->flags); |
677 | spin_unlock_irqrestore(&dd->lock, flags); | 677 | spin_unlock_irqrestore(&dd->lock, flags); |
678 | 678 | ||
679 | if (!async_req) | 679 | if (!async_req) |
@@ -1037,13 +1037,10 @@ static void omap_sham_done_task(unsigned long data) | |||
1037 | struct omap_sham_reqctx *ctx = ahash_request_ctx(req); | 1037 | struct omap_sham_reqctx *ctx = ahash_request_ctx(req); |
1038 | int ready = 0, err = 0; | 1038 | int ready = 0, err = 0; |
1039 | 1039 | ||
1040 | if (ctx->flags & BIT(FLAGS_OUTPUT_READY)) { | 1040 | if (test_and_clear_bit(FLAGS_OUTPUT_READY, &ctx->flags)) |
1041 | ctx->flags &= ~BIT(FLAGS_OUTPUT_READY); | ||
1042 | ready = 1; | 1041 | ready = 1; |
1043 | } | ||
1044 | 1042 | ||
1045 | if (dd->flags & BIT(FLAGS_DMA_ACTIVE)) { | 1043 | if (test_and_clear_bit(FLAGS_DMA_ACTIVE, &dd->flags)) { |
1046 | dd->flags &= ~BIT(FLAGS_DMA_ACTIVE); | ||
1047 | omap_sham_update_dma_stop(dd); | 1044 | omap_sham_update_dma_stop(dd); |
1048 | if (!dd->err) | 1045 | if (!dd->err) |
1049 | err = omap_sham_update_dma_start(dd); | 1046 | err = omap_sham_update_dma_start(dd); |
@@ -1077,7 +1074,7 @@ static irqreturn_t omap_sham_irq(int irq, void *dev_id) | |||
1077 | return IRQ_HANDLED; | 1074 | return IRQ_HANDLED; |
1078 | } | 1075 | } |
1079 | 1076 | ||
1080 | if (unlikely(ctx->flags & BIT(FLAGS_FINAL))) | 1077 | if (unlikely(test_bit(FLAGS_FINAL, &ctx->flags))) |
1081 | /* final -> allow device to go to power-saving mode */ | 1078 | /* final -> allow device to go to power-saving mode */ |
1082 | omap_sham_write_mask(dd, SHA_REG_CTRL, 0, SHA_REG_CTRL_LENGTH); | 1079 | omap_sham_write_mask(dd, SHA_REG_CTRL, 0, SHA_REG_CTRL_LENGTH); |
1083 | 1080 | ||
@@ -1085,7 +1082,7 @@ static irqreturn_t omap_sham_irq(int irq, void *dev_id) | |||
1085 | SHA_REG_CTRL_OUTPUT_READY); | 1082 | SHA_REG_CTRL_OUTPUT_READY); |
1086 | omap_sham_read(dd, SHA_REG_CTRL); | 1083 | omap_sham_read(dd, SHA_REG_CTRL); |
1087 | 1084 | ||
1088 | ctx->flags |= BIT(FLAGS_OUTPUT_READY); | 1085 | set_bit(FLAGS_OUTPUT_READY, &ctx->flags); |
1089 | dd->err = 0; | 1086 | dd->err = 0; |
1090 | tasklet_schedule(&dd->done_task); | 1087 | tasklet_schedule(&dd->done_task); |
1091 | 1088 | ||
@@ -1099,7 +1096,7 @@ static void omap_sham_dma_callback(int lch, u16 ch_status, void *data) | |||
1099 | if (ch_status != OMAP_DMA_BLOCK_IRQ) { | 1096 | if (ch_status != OMAP_DMA_BLOCK_IRQ) { |
1100 | pr_err("omap-sham DMA error status: 0x%hx\n", ch_status); | 1097 | pr_err("omap-sham DMA error status: 0x%hx\n", ch_status); |
1101 | dd->err = -EIO; | 1098 | dd->err = -EIO; |
1102 | dd->flags &= ~BIT(FLAGS_INIT); /* request to re-initialize */ | 1099 | clear_bit(FLAGS_INIT, &dd->flags);/* request to re-initialize */ |
1103 | } | 1100 | } |
1104 | 1101 | ||
1105 | tasklet_schedule(&dd->done_task); | 1102 | tasklet_schedule(&dd->done_task); |