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.
Unified · Split
| @@ -24,6 +24,7 @@ · 23 unmodified lines | ||
| 24 | 24 | |
| 25 | 25 | #define MV_CESA "MV-CESA:" |
| 26 | 26 | #define MAX_HW_HASH_SIZE 0xFFFF |
| 27 | +#define MV_CESA_EXPIRE 500 /* msec */ | |
| 27 | 28 | |
| 28 | 29 | /* |
| 29 | 30 | * STM: |
| @@ -87,6 +88,7 @@ struct crypto_priv { · 57 unmodified lines | ||
| 87 | 88 | spinlock_t lock; |
| 88 | 89 | struct crypto_queue queue; |
| 89 | 90 | enum engine_status eng_st; |
| 91 | + struct timer_list completion_timer; | |
| 90 | 92 | struct crypto_async_request *cur_req; |
| 91 | 93 | struct req_progress p; |
| 92 | 94 | int max_req_size; |
| @@ -138,6 +140,29 @@ struct mv_req_hash_ctx { · 45 unmodified lines | ||
| 138 | 140 | int count_add; |
| 139 | 141 | }; |
| 140 | 142 | |
| 143 | +static 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 | + | |
| 159 | +static 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 | + | |
| 141 | 166 | static void compute_aes_dec_key(struct mv_ctx *ctx) |
| 142 | 167 | { |
| 143 | 168 | struct crypto_aes_ctx gen_aes_key; |
| @@ -273,12 +298,8 @@ static void mv_process_current_q(int first_block) · 129 unmodified lines | ||
| 273 | 298 | sizeof(struct sec_accel_config)); |
| 274 | 299 | |
| 275 | 300 | /* GO */ |
| 301 | + mv_setup_timer(); | |
| 276 | 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 | |
| 284 | 305 | static void mv_crypto_algo_completion(void) |
| @@ -357,12 +378,8 @@ static void mv_process_hash_current(int first_block) · 72 unmodified lines | ||
| 357 | 378 | memcpy(cpg->sram + SRAM_CONFIG, &op, sizeof(struct sec_accel_config)); |
| 358 | 379 | |
| 359 | 380 | /* GO */ |
| 381 | + mv_setup_timer(); | |
| 360 | 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 | |
| 368 | 385 | static 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) · 519 unmodified lines | ||
| 888 | 905 | if (!(val & SEC_INT_ACCEL0_DONE)) |
| 889 | 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 | 912 | val &= ~SEC_INT_ACCEL0_DONE; |
| 892 | 913 | writel(val, cpg->reg + FPGA_INT_STATUS); |
| 893 | 914 | writel(val, cpg->reg + SEC_ACCEL_INT_STATUS); |