aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/crypto/mv_cesa.c
diff options
context:
space:
mode:
authorPhil Sutter <phil.sutter@viprinet.com>2012-05-25 09:54:46 -0400
committerHerbert Xu <herbert@gondor.apana.org.au>2012-06-12 04:37:20 -0400
commit170dd56dfc3b13e7dafd48e27f67fddb3f17ef2a (patch)
tree0e3811c00402a91d1bf0f4f196e374854d3095f5 /drivers/crypto/mv_cesa.c
parentb8840098b70c11d70c29263e0765f103e6cbe55e (diff)
crypto: mv_cesa - add an expiry timer in case anything goes wrong
The timer triggers when 500ms have gone by after triggering the engine and no completion interrupt was received. The callback then tries to sanitise things as well as possible. Signed-off-by: Phil Sutter <phil.sutter@viprinet.com> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to 'drivers/crypto/mv_cesa.c')
-rw-r--r--drivers/crypto/mv_cesa.c41
1 files changed, 31 insertions, 10 deletions
diff --git a/drivers/crypto/mv_cesa.c b/drivers/crypto/mv_cesa.c
index 1cc6b3f3e262..b0b2f02518f8 100644
--- a/drivers/crypto/mv_cesa.c
+++ b/drivers/crypto/mv_cesa.c
@@ -24,6 +24,7 @@
24 24
25#define MV_CESA "MV-CESA:" 25#define MV_CESA "MV-CESA:"
26#define MAX_HW_HASH_SIZE 0xFFFF 26#define MAX_HW_HASH_SIZE 0xFFFF
27#define MV_CESA_EXPIRE 500 /* msec */
27 28
28/* 29/*
29 * STM: 30 * STM:
@@ -87,6 +88,7 @@ struct crypto_priv {
87 spinlock_t lock; 88 spinlock_t lock;
88 struct crypto_queue queue; 89 struct crypto_queue queue;
89 enum engine_status eng_st; 90 enum engine_status eng_st;
91 struct timer_list completion_timer;
90 struct crypto_async_request *cur_req; 92 struct crypto_async_request *cur_req;
91 struct req_progress p; 93 struct req_progress p;
92 int max_req_size; 94 int max_req_size;
@@ -138,6 +140,29 @@ struct mv_req_hash_ctx {
138 int count_add; 140 int count_add;
139}; 141};
140 142
143static void mv_completion_timer_callback(unsigned long unused)
144{
145 int active = readl(cpg->reg + SEC_ACCEL_CMD) & SEC_CMD_EN_SEC_ACCL0;
146
147 printk(KERN_ERR MV_CESA
148 "completion timer expired (CESA %sactive), cleaning up.\n",
149 active ? "" : "in");
150
151 del_timer(&cpg->completion_timer);
152 writel(SEC_CMD_DISABLE_SEC, cpg->reg + SEC_ACCEL_CMD);
153 while(readl(cpg->reg + SEC_ACCEL_CMD) & SEC_CMD_DISABLE_SEC)
154 printk(KERN_INFO MV_CESA "%s: waiting for engine finishing\n", __func__);
155 cpg->eng_st = ENGINE_W_DEQUEUE;
156 wake_up_process(cpg->queue_th);
157}
158
159static void mv_setup_timer(void)
160{
161 setup_timer(&cpg->completion_timer, &mv_completion_timer_callback, 0);
162 mod_timer(&cpg->completion_timer,
163 jiffies + msecs_to_jiffies(MV_CESA_EXPIRE));
164}
165
141static void compute_aes_dec_key(struct mv_ctx *ctx) 166static void compute_aes_dec_key(struct mv_ctx *ctx)
142{ 167{
143 struct crypto_aes_ctx gen_aes_key; 168 struct crypto_aes_ctx gen_aes_key;
@@ -273,12 +298,8 @@ static void mv_process_current_q(int first_block)
273 sizeof(struct sec_accel_config)); 298 sizeof(struct sec_accel_config));
274 299
275 /* GO */ 300 /* GO */
301 mv_setup_timer();
276 writel(SEC_CMD_EN_SEC_ACCL0, cpg->reg + SEC_ACCEL_CMD); 302 writel(SEC_CMD_EN_SEC_ACCL0, cpg->reg + SEC_ACCEL_CMD);
277
278 /*
279 * XXX: add timer if the interrupt does not occur for some mystery
280 * reason
281 */
282} 303}
283 304
284static void mv_crypto_algo_completion(void) 305static void mv_crypto_algo_completion(void)
@@ -357,12 +378,8 @@ static void mv_process_hash_current(int first_block)
357 memcpy(cpg->sram + SRAM_CONFIG, &op, sizeof(struct sec_accel_config)); 378 memcpy(cpg->sram + SRAM_CONFIG, &op, sizeof(struct sec_accel_config));
358 379
359 /* GO */ 380 /* GO */
381 mv_setup_timer();
360 writel(SEC_CMD_EN_SEC_ACCL0, cpg->reg + SEC_ACCEL_CMD); 382 writel(SEC_CMD_EN_SEC_ACCL0, cpg->reg + SEC_ACCEL_CMD);
361
362 /*
363 * XXX: add timer if the interrupt does not occur for some mystery
364 * reason
365 */
366} 383}
367 384
368static inline int mv_hash_import_sha1_ctx(const struct mv_req_hash_ctx *ctx, 385static inline int mv_hash_import_sha1_ctx(const struct mv_req_hash_ctx *ctx,
@@ -888,6 +905,10 @@ irqreturn_t crypto_int(int irq, void *priv)
888 if (!(val & SEC_INT_ACCEL0_DONE)) 905 if (!(val & SEC_INT_ACCEL0_DONE))
889 return IRQ_NONE; 906 return IRQ_NONE;
890 907
908 if (!del_timer(&cpg->completion_timer)) {
909 printk(KERN_WARNING MV_CESA
910 "got an interrupt but no pending timer?\n");
911 }
891 val &= ~SEC_INT_ACCEL0_DONE; 912 val &= ~SEC_INT_ACCEL0_DONE;
892 writel(val, cpg->reg + FPGA_INT_STATUS); 913 writel(val, cpg->reg + FPGA_INT_STATUS);
893 writel(val, cpg->reg + SEC_ACCEL_INT_STATUS); 914 writel(val, cpg->reg + SEC_ACCEL_INT_STATUS);