Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

crypto: ccree - fix resume race condition on init

We were enabling autosuspend, which is using data set by the
hash module, prior to the hash module being inited, casuing
a crash on resume as part of the startup sequence if the race
was lost.

This was never a real problem because the PM infra was using low
res timers so we were always winning the race, until commit 8234f6734c5d
("PM-runtime: Switch autosuspend over to using hrtimers") changed that :-)

Fix this by seperating the PM setup and enablement and doing the
latter only at the end of the init sequence.

Signed-off-by: Gilad Ben-Yossef <gilad@benyossef.com>
Cc: Vincent Guittot <vincent.guittot@linaro.org>
Cc: stable@kernel.org # v4.20
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>

authored by

Gilad Ben-Yossef and committed by
Herbert Xu
1358c13a 356690d0

+13 -10
+4 -3
drivers/crypto/ccree/cc_driver.c
··· 380 380 rc = cc_ivgen_init(new_drvdata); 381 381 if (rc) { 382 382 dev_err(dev, "cc_ivgen_init failed\n"); 383 - goto post_power_mgr_err; 383 + goto post_buf_mgr_err; 384 384 } 385 385 386 386 /* Allocate crypto algs */ ··· 403 403 goto post_hash_err; 404 404 } 405 405 406 + /* All set, we can allow autosuspend */ 407 + cc_pm_go(new_drvdata); 408 + 406 409 /* If we got here and FIPS mode is enabled 407 410 * it means all FIPS test passed, so let TEE 408 411 * know we're good. ··· 420 417 cc_cipher_free(new_drvdata); 421 418 post_ivgen_err: 422 419 cc_ivgen_fini(new_drvdata); 423 - post_power_mgr_err: 424 - cc_pm_fini(new_drvdata); 425 420 post_buf_mgr_err: 426 421 cc_buffer_mgr_fini(new_drvdata); 427 422 post_req_mgr_err:
+6 -7
drivers/crypto/ccree/cc_pm.c
··· 100 100 101 101 int cc_pm_init(struct cc_drvdata *drvdata) 102 102 { 103 - int rc = 0; 104 103 struct device *dev = drvdata_to_dev(drvdata); 105 104 106 105 /* must be before the enabling to avoid resdundent suspending */ 107 106 pm_runtime_set_autosuspend_delay(dev, CC_SUSPEND_TIMEOUT); 108 107 pm_runtime_use_autosuspend(dev); 109 108 /* activate the PM module */ 110 - rc = pm_runtime_set_active(dev); 111 - if (rc) 112 - return rc; 113 - /* enable the PM module*/ 114 - pm_runtime_enable(dev); 109 + return pm_runtime_set_active(dev); 110 + } 115 111 116 - return rc; 112 + /* enable the PM module*/ 113 + void cc_pm_go(struct cc_drvdata *drvdata) 114 + { 115 + pm_runtime_enable(drvdata_to_dev(drvdata)); 117 116 } 118 117 119 118 void cc_pm_fini(struct cc_drvdata *drvdata)
+3
drivers/crypto/ccree/cc_pm.h
··· 16 16 extern const struct dev_pm_ops ccree_pm; 17 17 18 18 int cc_pm_init(struct cc_drvdata *drvdata); 19 + void cc_pm_go(struct cc_drvdata *drvdata); 19 20 void cc_pm_fini(struct cc_drvdata *drvdata); 20 21 int cc_pm_suspend(struct device *dev); 21 22 int cc_pm_resume(struct device *dev); ··· 29 28 { 30 29 return 0; 31 30 } 31 + 32 + static void cc_pm_go(struct cc_drvdata *drvdata) {} 32 33 33 34 static inline void cc_pm_fini(struct cc_drvdata *drvdata) {} 34 35