diff options
author | leonardian <leonardian@google.com> | 2024-04-10 03:20:02 +0000 |
---|---|---|
committer | leonardian <leonardian@google.com> | 2024-04-12 17:16:42 +0000 |
commit | 5b1e209347f26dd45487755f49ffbdebee37b082 (patch) | |
tree | 98391640d8d529fe985d95f7fce358d75a022836 | |
parent | 5a2c5d2c3a5ae205ed5985d5695a4b417e16ed30 (diff) | |
download | amplifiers-android-gs-bluejay-5.10-android15-beta.tar.gz |
CS40L26: Fix race conditions between cl_dsp struct and sysfs accessandroid-15-beta-2_r0.5android-15-beta-2_r0.2android-15-beta-2_r0.1android-gs-raviole-5.10-android15-betaandroid-gs-felix-5.10-android15-betaandroid-gs-bluejay-5.10-android15-beta
Add mutex lock cl_dsp_lock on the following functions:
- cs40l26_cl_dsp_reinit()
- cs40l26_get_num_waves()
- f0_offset_store()
- owt_free_space_show()
Add flush_work to ensure proper synchronization during reset recovery
Bug: 324075191
Test: Primitive vibration with reset no KP
Test: idlcli commands
Test: Alarm, keyboard vibrations
Change-Id: I24cfc6631efcf4ccae64318e8a408facb3a76d4b
Signed-off-by: leonardian <leonardian@google.com>
-rw-r--r-- | cs40l26/cs40l26-sysfs.c | 22 | ||||
-rw-r--r-- | cs40l26/cs40l26.c | 31 | ||||
-rw-r--r-- | cs40l26/cs40l26.h | 1 |
3 files changed, 49 insertions, 5 deletions
diff --git a/cs40l26/cs40l26-sysfs.c b/cs40l26/cs40l26-sysfs.c index bb6f3d8..bf1b2da 100644 --- a/cs40l26/cs40l26-sysfs.c +++ b/cs40l26/cs40l26-sysfs.c @@ -261,8 +261,14 @@ static ssize_t owt_free_space_show(struct device *dev, if (ret) return ret; +#if IS_ENABLED(CONFIG_GOOG_CUST) + mutex_lock(&cs40l26->cl_dsp_lock); +#endif ret = cl_dsp_get_reg(cs40l26->dsp, "OWT_SIZE_XM", CL_DSP_XM_UNPACKED_TYPE, CS40L26_VIBEGEN_ALGO_ID, ®); +#if IS_ENABLED(CONFIG_GOOG_CUST) + mutex_unlock(&cs40l26->cl_dsp_lock); +#endif if (ret) goto err_pm; @@ -468,10 +474,15 @@ static ssize_t f0_offset_store(struct device *dev, return ret; mutex_lock(&cs40l26->lock); - +#if IS_ENABLED(CONFIG_GOOG_CUST) + mutex_lock(&cs40l26->cl_dsp_lock); +#endif ret = cl_dsp_get_reg(cs40l26->dsp, "F0_OFFSET", CL_DSP_XM_UNPACKED_TYPE, CS40L26_VIBEGEN_ALGO_ID, ®); +#if IS_ENABLED(CONFIG_GOOG_CUST) + mutex_unlock(&cs40l26->cl_dsp_lock); +#endif if (ret) goto err_mutex; @@ -841,9 +852,12 @@ static ssize_t reset_store(struct device *dev, if (ret) return ret; - if (choice == 0) { - cs40l26_make_reset_decision(cs40l26, __func__); - } else if (choice == 1) { + /* + * Calling flush_work() within sysfs function will cause KP. + * cs40l26_make_reset_decision(cs40l26, __func__); + */ + + if (choice == 1) { cs40l26->reset_event = CS40L26_RESET_EVENT_NONEED; cs40l26->reset_count = 0; queue_work(cs40l26->vibe_workqueue, &cs40l26->reset_work); diff --git a/cs40l26/cs40l26.c b/cs40l26/cs40l26.c index 4dfdc85..124493a 100644 --- a/cs40l26/cs40l26.c +++ b/cs40l26/cs40l26.c @@ -2162,9 +2162,15 @@ int cs40l26_get_num_waves(struct cs40l26_private *cs40l26, u32 *num_waves) int ret; u32 reg, nwaves, nowt; +#if IS_ENABLED(CONFIG_GOOG_CUST) + mutex_lock(&cs40l26->cl_dsp_lock); +#endif ret = cl_dsp_get_reg(cs40l26->dsp, "NUM_OF_WAVES", CL_DSP_XM_UNPACKED_TYPE, CS40L26_VIBEGEN_ALGO_ID, ®); +#if IS_ENABLED(CONFIG_GOOG_CUST) + mutex_unlock(&cs40l26->cl_dsp_lock); +#endif if (ret) return ret; @@ -2172,8 +2178,14 @@ int cs40l26_get_num_waves(struct cs40l26_private *cs40l26, u32 *num_waves) if (ret) return ret; +#if IS_ENABLED(CONFIG_GOOG_CUST) + mutex_lock(&cs40l26->cl_dsp_lock); +#endif ret = cl_dsp_get_reg(cs40l26->dsp, "OWT_NUM_OF_WAVES_XM", CL_DSP_XM_UNPACKED_TYPE, CS40L26_VIBEGEN_ALGO_ID, ®); +#if IS_ENABLED(CONFIG_GOOG_CUST) + mutex_unlock(&cs40l26->cl_dsp_lock); +#endif if (ret) return ret; @@ -4410,10 +4422,16 @@ static int cs40l26_cl_dsp_reinit(struct cs40l26_private *cs40l26) { int ret; +#if IS_ENABLED(CONFIG_GOOG_CUST) + mutex_lock(&cs40l26->cl_dsp_lock); +#endif if (cs40l26->dsp) { ret = cl_dsp_destroy(cs40l26->dsp); if (ret) { dev_err(cs40l26->dev, "Failed to destroy DSP struct\n"); +#if IS_ENABLED(CONFIG_GOOG_CUST) + mutex_unlock(&cs40l26->cl_dsp_lock); +#endif return ret; } @@ -4421,6 +4439,9 @@ static int cs40l26_cl_dsp_reinit(struct cs40l26_private *cs40l26) } cs40l26->dsp = cl_dsp_create(cs40l26->dev, cs40l26->regmap); +#if IS_ENABLED(CONFIG_GOOG_CUST) + mutex_unlock(&cs40l26->cl_dsp_lock); +#endif if (IS_ERR(cs40l26->dsp)) return PTR_ERR(cs40l26->dsp); @@ -5077,6 +5098,9 @@ void cs40l26_make_reset_decision(struct cs40l26_private *cs40l26, const char *fu if (trigger) { dev_info(dev, "Queue reset work after %s", func); queue_work(cs40l26->vibe_workqueue, &cs40l26->reset_work); + + /* Wait for reset to finish */ + flush_work(&cs40l26->reset_work); } else dev_info(dev, "Reset event: %d. Skip this trigger from %s.", cs40l26->reset_event, func); @@ -5090,6 +5114,9 @@ int cs40l26_probe(struct cs40l26_private *cs40l26, int ret; mutex_init(&cs40l26->lock); +#if IS_ENABLED(CONFIG_GOOG_CUST) + mutex_init(&cs40l26->cl_dsp_lock); +#endif cs40l26->vibe_workqueue = alloc_ordered_workqueue("vibe_workqueue", WQ_HIGHPRI); @@ -5239,7 +5266,9 @@ int cs40l26_remove(struct cs40l26_private *cs40l26) disable_irq(cs40l26->irq); mutex_destroy(&cs40l26->lock); - +#if IS_ENABLED(CONFIG_GOOG_CUST) + mutex_destroy(&cs40l26->cl_dsp_lock); +#endif if (cs40l26->pm_ready) cs40l26_pm_runtime_teardown(cs40l26); diff --git a/cs40l26/cs40l26.h b/cs40l26/cs40l26.h index 13f24db..99e1915 100644 --- a/cs40l26/cs40l26.h +++ b/cs40l26/cs40l26.h @@ -1588,6 +1588,7 @@ struct cs40l26_private { struct cl_dsp_debugfs *cl_dsp_db; #endif #if IS_ENABLED(CONFIG_GOOG_CUST) + struct mutex cl_dsp_lock; struct work_struct reset_work; enum cs40l26_reset_event reset_event; u8 reset_count; |