@@ -34,6 +34,7 @@ struct tegra_sha_reqctx {
3434 struct tegra_se_datbuf datbuf ;
3535 struct tegra_se_datbuf residue ;
3636 struct tegra_se_datbuf digest ;
37+ struct tegra_se_datbuf intr_res ;
3738 unsigned int alg ;
3839 unsigned int config ;
3940 unsigned int total_len ;
@@ -211,9 +212,62 @@ static int tegra_sha_fallback_export(struct ahash_request *req, void *out)
211212 return crypto_ahash_export (& rctx -> fallback_req , out );
212213}
213214
214- static int tegra_sha_prep_cmd (struct tegra_se * se , u32 * cpuvaddr ,
215+ static int tegra_se_insert_hash_result (struct tegra_sha_ctx * ctx , u32 * cpuvaddr ,
216+ struct tegra_sha_reqctx * rctx )
217+ {
218+ __be32 * res_be = (__be32 * )rctx -> intr_res .buf ;
219+ u32 * res = (u32 * )rctx -> intr_res .buf ;
220+ int i = 0 , j ;
221+
222+ cpuvaddr [i ++ ] = 0 ;
223+ cpuvaddr [i ++ ] = host1x_opcode_setpayload (HASH_RESULT_REG_COUNT );
224+ cpuvaddr [i ++ ] = se_host1x_opcode_incr_w (SE_SHA_HASH_RESULT );
225+
226+ for (j = 0 ; j < HASH_RESULT_REG_COUNT ; j ++ ) {
227+ int idx = j ;
228+
229+ /*
230+ * The initial, intermediate and final hash value of SHA-384, SHA-512
231+ * in SHA_HASH_RESULT registers follow the below layout of bytes.
232+ *
233+ * +---------------+------------+
234+ * | HASH_RESULT_0 | B4...B7 |
235+ * +---------------+------------+
236+ * | HASH_RESULT_1 | B0...B3 |
237+ * +---------------+------------+
238+ * | HASH_RESULT_2 | B12...B15 |
239+ * +---------------+------------+
240+ * | HASH_RESULT_3 | B8...B11 |
241+ * +---------------+------------+
242+ * | ...... |
243+ * +---------------+------------+
244+ * | HASH_RESULT_14| B60...B63 |
245+ * +---------------+------------+
246+ * | HASH_RESULT_15| B56...B59 |
247+ * +---------------+------------+
248+ *
249+ */
250+ if (ctx -> alg == SE_ALG_SHA384 || ctx -> alg == SE_ALG_SHA512 )
251+ idx = (j % 2 ) ? j - 1 : j + 1 ;
252+
253+ /* For SHA-1, SHA-224, SHA-256, SHA-384, SHA-512 the initial
254+ * intermediate and final hash value when stored in
255+ * SHA_HASH_RESULT registers, the byte order is NOT in
256+ * little-endian.
257+ */
258+ if (ctx -> alg <= SE_ALG_SHA512 )
259+ cpuvaddr [i ++ ] = be32_to_cpu (res_be [idx ]);
260+ else
261+ cpuvaddr [i ++ ] = res [idx ];
262+ }
263+
264+ return i ;
265+ }
266+
267+ static int tegra_sha_prep_cmd (struct tegra_sha_ctx * ctx , u32 * cpuvaddr ,
215268 struct tegra_sha_reqctx * rctx )
216269{
270+ struct tegra_se * se = ctx -> se ;
217271 u64 msg_len , msg_left ;
218272 int i = 0 ;
219273
@@ -241,23 +295,37 @@ static int tegra_sha_prep_cmd(struct tegra_se *se, u32 *cpuvaddr,
241295 cpuvaddr [i ++ ] = upper_32_bits (msg_left );
242296 cpuvaddr [i ++ ] = 0 ;
243297 cpuvaddr [i ++ ] = 0 ;
244- cpuvaddr [i ++ ] = host1x_opcode_setpayload (6 );
298+ cpuvaddr [i ++ ] = host1x_opcode_setpayload (2 );
245299 cpuvaddr [i ++ ] = se_host1x_opcode_incr_w (SE_SHA_CFG );
246300 cpuvaddr [i ++ ] = rctx -> config ;
247301
248302 if (rctx -> task & SHA_FIRST ) {
249303 cpuvaddr [i ++ ] = SE_SHA_TASK_HASH_INIT ;
250304 rctx -> task &= ~SHA_FIRST ;
251305 } else {
252- cpuvaddr [i ++ ] = 0 ;
306+ /*
307+ * If it isn't the first task, program the HASH_RESULT register
308+ * with the intermediate result from the previous task
309+ */
310+ i += tegra_se_insert_hash_result (ctx , cpuvaddr + i , rctx );
253311 }
254312
313+ cpuvaddr [i ++ ] = host1x_opcode_setpayload (4 );
314+ cpuvaddr [i ++ ] = se_host1x_opcode_incr_w (SE_SHA_IN_ADDR );
255315 cpuvaddr [i ++ ] = rctx -> datbuf .addr ;
256316 cpuvaddr [i ++ ] = (u32 )(SE_ADDR_HI_MSB (upper_32_bits (rctx -> datbuf .addr )) |
257317 SE_ADDR_HI_SZ (rctx -> datbuf .size ));
258- cpuvaddr [i ++ ] = rctx -> digest .addr ;
259- cpuvaddr [i ++ ] = (u32 )(SE_ADDR_HI_MSB (upper_32_bits (rctx -> digest .addr )) |
260- SE_ADDR_HI_SZ (rctx -> digest .size ));
318+
319+ if (rctx -> task & SHA_UPDATE ) {
320+ cpuvaddr [i ++ ] = rctx -> intr_res .addr ;
321+ cpuvaddr [i ++ ] = (u32 )(SE_ADDR_HI_MSB (upper_32_bits (rctx -> intr_res .addr )) |
322+ SE_ADDR_HI_SZ (rctx -> intr_res .size ));
323+ } else {
324+ cpuvaddr [i ++ ] = rctx -> digest .addr ;
325+ cpuvaddr [i ++ ] = (u32 )(SE_ADDR_HI_MSB (upper_32_bits (rctx -> digest .addr )) |
326+ SE_ADDR_HI_SZ (rctx -> digest .size ));
327+ }
328+
261329 if (rctx -> key_id ) {
262330 cpuvaddr [i ++ ] = host1x_opcode_setpayload (1 );
263331 cpuvaddr [i ++ ] = se_host1x_opcode_nonincr_w (SE_SHA_CRYPTO_CFG );
@@ -266,36 +334,18 @@ static int tegra_sha_prep_cmd(struct tegra_se *se, u32 *cpuvaddr,
266334
267335 cpuvaddr [i ++ ] = host1x_opcode_setpayload (1 );
268336 cpuvaddr [i ++ ] = se_host1x_opcode_nonincr_w (SE_SHA_OPERATION );
269- cpuvaddr [i ++ ] = SE_SHA_OP_WRSTALL |
270- SE_SHA_OP_START |
337+ cpuvaddr [i ++ ] = SE_SHA_OP_WRSTALL | SE_SHA_OP_START |
271338 SE_SHA_OP_LASTBUF ;
272339 cpuvaddr [i ++ ] = se_host1x_opcode_nonincr (host1x_uclass_incr_syncpt_r (), 1 );
273340 cpuvaddr [i ++ ] = host1x_uclass_incr_syncpt_cond_f (1 ) |
274341 host1x_uclass_incr_syncpt_indx_f (se -> syncpt_id );
275342
276- dev_dbg (se -> dev , "msg len %llu msg left %llu cfg %#x" ,
277- msg_len , msg_left , rctx -> config );
343+ dev_dbg (se -> dev , "msg len %llu msg left %llu sz %lu cfg %#x" ,
344+ msg_len , msg_left , rctx -> datbuf . size , rctx -> config );
278345
279346 return i ;
280347}
281348
282- static void tegra_sha_copy_hash_result (struct tegra_se * se , struct tegra_sha_reqctx * rctx )
283- {
284- int i ;
285-
286- for (i = 0 ; i < HASH_RESULT_REG_COUNT ; i ++ )
287- rctx -> result [i ] = readl (se -> base + se -> hw -> regs -> result + (i * 4 ));
288- }
289-
290- static void tegra_sha_paste_hash_result (struct tegra_se * se , struct tegra_sha_reqctx * rctx )
291- {
292- int i ;
293-
294- for (i = 0 ; i < HASH_RESULT_REG_COUNT ; i ++ )
295- writel (rctx -> result [i ],
296- se -> base + se -> hw -> regs -> result + (i * 4 ));
297- }
298-
299349static int tegra_sha_do_init (struct ahash_request * req )
300350{
301351 struct tegra_sha_reqctx * rctx = ahash_request_ctx (req );
@@ -325,8 +375,17 @@ static int tegra_sha_do_init(struct ahash_request *req)
325375 if (!rctx -> residue .buf )
326376 goto resbuf_fail ;
327377
378+ rctx -> intr_res .size = HASH_RESULT_REG_COUNT * 4 ;
379+ rctx -> intr_res .buf = dma_alloc_coherent (se -> dev , rctx -> intr_res .size ,
380+ & rctx -> intr_res .addr , GFP_KERNEL );
381+ if (!rctx -> intr_res .buf )
382+ goto intr_res_fail ;
383+
328384 return 0 ;
329385
386+ intr_res_fail :
387+ dma_free_coherent (se -> dev , rctx -> residue .size , rctx -> residue .buf ,
388+ rctx -> residue .addr );
330389resbuf_fail :
331390 dma_free_coherent (se -> dev , rctx -> digest .size , rctx -> digest .buf ,
332391 rctx -> digest .addr );
@@ -356,7 +415,6 @@ static int tegra_sha_do_update(struct ahash_request *req)
356415
357416 rctx -> src_sg = req -> src ;
358417 rctx -> datbuf .size = (req -> nbytes + rctx -> residue .size ) - nresidue ;
359- rctx -> total_len += rctx -> datbuf .size ;
360418
361419 /*
362420 * If nbytes are less than a block size, copy it residue and
@@ -365,12 +423,12 @@ static int tegra_sha_do_update(struct ahash_request *req)
365423 if (nblks < 1 ) {
366424 scatterwalk_map_and_copy (rctx -> residue .buf + rctx -> residue .size ,
367425 rctx -> src_sg , 0 , req -> nbytes , 0 );
368-
369426 rctx -> residue .size += req -> nbytes ;
427+
370428 return 0 ;
371429 }
372430
373- rctx -> datbuf .buf = dma_alloc_coherent (ctx -> se -> dev , rctx -> datbuf .size ,
431+ rctx -> datbuf .buf = dma_alloc_coherent (se -> dev , rctx -> datbuf .size ,
374432 & rctx -> datbuf .addr , GFP_KERNEL );
375433 if (!rctx -> datbuf .buf )
376434 return - ENOMEM ;
@@ -387,31 +445,15 @@ static int tegra_sha_do_update(struct ahash_request *req)
387445
388446 /* Update residue value with the residue after current block */
389447 rctx -> residue .size = nresidue ;
448+ rctx -> total_len += rctx -> datbuf .size ;
390449
391450 rctx -> config = tegra_sha_get_config (rctx -> alg ) |
392- SE_SHA_DST_HASH_REG ;
393-
394- /*
395- * If this is not the first 'update' call, paste the previous copied
396- * intermediate results to the registers so that it gets picked up.
397- * This is to support the import/export functionality.
398- */
399- if (!(rctx -> task & SHA_FIRST ))
400- tegra_sha_paste_hash_result (se , rctx );
401-
402- size = tegra_sha_prep_cmd (se , cpuvaddr , rctx );
451+ SE_SHA_DST_MEMORY ;
403452
453+ size = tegra_sha_prep_cmd (ctx , cpuvaddr , rctx );
404454 ret = tegra_se_host1x_submit (se , se -> cmdbuf , size );
405455
406- /*
407- * If this is not the final update, copy the intermediate results
408- * from the registers so that it can be used in the next 'update'
409- * call. This is to support the import/export functionality.
410- */
411- if (!(rctx -> task & SHA_FINAL ))
412- tegra_sha_copy_hash_result (se , rctx );
413-
414- dma_free_coherent (ctx -> se -> dev , rctx -> datbuf .size ,
456+ dma_free_coherent (se -> dev , rctx -> datbuf .size ,
415457 rctx -> datbuf .buf , rctx -> datbuf .addr );
416458
417459 return ret ;
@@ -443,8 +485,7 @@ static int tegra_sha_do_final(struct ahash_request *req)
443485 rctx -> config = tegra_sha_get_config (rctx -> alg ) |
444486 SE_SHA_DST_MEMORY ;
445487
446- size = tegra_sha_prep_cmd (se , cpuvaddr , rctx );
447-
488+ size = tegra_sha_prep_cmd (ctx , cpuvaddr , rctx );
448489 ret = tegra_se_host1x_submit (se , se -> cmdbuf , size );
449490 if (ret )
450491 goto out ;
@@ -461,6 +502,10 @@ static int tegra_sha_do_final(struct ahash_request *req)
461502 rctx -> residue .buf , rctx -> residue .addr );
462503 dma_free_coherent (se -> dev , rctx -> digest .size , rctx -> digest .buf ,
463504 rctx -> digest .addr );
505+
506+ dma_free_coherent (se -> dev , rctx -> intr_res .size , rctx -> intr_res .buf ,
507+ rctx -> intr_res .addr );
508+
464509 return ret ;
465510}
466511
0 commit comments