ANDROID: GKI: ASoC: Add locking in DAPM widget power update
While playback and capture is done concurrently the dapm widget data is accessed parallelly which results in data corruption and kernel panic. Fix this problem by serializing the stream event operation by adding lock dapm_seq_run will invoke dapm power sequence for pre-sorted list of widgets to be powered up. Kernel panic issue is observed during stability runs with the above sequence caused by null pointer dereference in dapm_seq_run_coalesced. Fix kernel panic issue by checking for valid snd_soc_dapm_context pointer in dapm_seq_run before invoking dapm_seq_run_coalesced Widget list in dapm is getting corrupted during concurrent use cases where dapm_power_widget is accessed. This corruption is resulting in kernel crash in dapm. Fix the issue by adding protection in dapm_power_widgets API. This change also squashes the below changes- (1) ASoC: dapm: fix race condition in dapm Dirty widget list can be accessed by multiple paths in dapm framework. Dirty list is protected by dapm mutex. Since dapm_force_enable_pin function accesses the dirty list, protect it using the dapm mutex. (2) soc-dapm: Fix double mutex lock dapm_mutex lock is acquired from soc_dapm_force_enable_pin_unlocked function which will cause double lock because the same mutex is acquired in soc_dapm_force_enable_pin(). Fix this issue by removing dapm_mutex acquire from soc_dapm_force_enable_pin_unlocked function. CRs-Fixed: 388785 Test: build Bug: 151372815 Change-Id: I49d19860277726cf3152e104ab40627fd56c021c Signed-off-by: Sriranjan Srikantam <cssrika@codeaurora.org> Signed-off-by: Gopikrishnaiah Anandan <agopik@codeaurora.org> Signed-off-by: Banajit Goswami <bgoswami@codeaurora.org> (cherry picked from commit 853ed7c58fd03dd1b024f30a20f69a8df06cceed) Signed-off-by: Hridya Valsaraju <hridya@google.com>
This commit is contained in:
parent
eac5d88e91
commit
7560c37851
3 changed files with 6 additions and 2 deletions
|
@ -1067,6 +1067,7 @@ struct snd_soc_card {
|
|||
|
||||
struct mutex mutex;
|
||||
struct mutex dapm_mutex;
|
||||
struct mutex dapm_power_mutex;
|
||||
|
||||
bool instantiated;
|
||||
bool topology_shortname_created;
|
||||
|
|
|
@ -2747,6 +2747,7 @@ int snd_soc_register_card(struct snd_soc_card *card)
|
|||
card->instantiated = 0;
|
||||
mutex_init(&card->mutex);
|
||||
mutex_init(&card->dapm_mutex);
|
||||
mutex_init(&card->dapm_power_mutex);
|
||||
|
||||
ret = snd_soc_instantiate_card(card);
|
||||
if (ret != 0)
|
||||
|
|
|
@ -1591,7 +1591,7 @@ static void dapm_seq_run(struct snd_soc_card *card,
|
|||
/* Do we need to apply any queued changes? */
|
||||
if (sort[w->id] != cur_sort || w->reg != cur_reg ||
|
||||
w->dapm != cur_dapm || w->subseq != cur_subseq) {
|
||||
if (!list_empty(&pending))
|
||||
if (cur_dapm && !list_empty(&pending))
|
||||
dapm_seq_run_coalesced(card, &pending);
|
||||
|
||||
if (cur_dapm && cur_dapm->seq_notifier) {
|
||||
|
@ -1654,7 +1654,7 @@ static void dapm_seq_run(struct snd_soc_card *card,
|
|||
"ASoC: Failed to apply widget power: %d\n", ret);
|
||||
}
|
||||
|
||||
if (!list_empty(&pending))
|
||||
if (cur_dapm && !list_empty(&pending))
|
||||
dapm_seq_run_coalesced(card, &pending);
|
||||
|
||||
if (cur_dapm && cur_dapm->seq_notifier) {
|
||||
|
@ -1899,6 +1899,7 @@ static int dapm_power_widgets(struct snd_soc_card *card, int event)
|
|||
lockdep_assert_held(&card->dapm_mutex);
|
||||
|
||||
trace_snd_soc_dapm_start(card);
|
||||
mutex_lock(&card->dapm_power_mutex);
|
||||
|
||||
list_for_each_entry(d, &card->dapm_list, list) {
|
||||
if (dapm_idle_bias_off(d))
|
||||
|
@ -2018,6 +2019,7 @@ static int dapm_power_widgets(struct snd_soc_card *card, int event)
|
|||
pop_dbg(card->dev, card->pop_time,
|
||||
"DAPM sequencing finished, waiting %dms\n", card->pop_time);
|
||||
pop_wait(card->pop_time);
|
||||
mutex_unlock(&card->dapm_power_mutex);
|
||||
|
||||
trace_snd_soc_dapm_done(card);
|
||||
|
||||
|
|
Loading…
Reference in a new issue