Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 161b2d66 authored by Xiaoyu Ye's avatar Xiaoyu Ye Committed by Gerrit - the friendly Code Review server
Browse files

ASoC: wcd-dsp-mgr: fix race during subsystem restart



Whenever subsystem restart or DSP boot occurs, the manager driver
parses the dsp image and stores the segments in list. During
certain back to back regression tests, it is observed that SSR
is failing due to race between SSR handling and DSP enablement.
Fix this by acquiring the ssr_mutex during enabling DSP and
sequence to list operations such that there is no race conditions.

Change-Id: I15c55bf96737e4ffd7e0faf571a1109ba6c38163
Signed-off-by: default avatarBhalchandra Gajare <gajare@codeaurora.org>
Signed-off-by: default avatarXiaoyu Ye <benyxy@codeaurora.org>
parent 5f300da0
Loading
Loading
Loading
Loading
+14 −8
Original line number Original line Diff line number Diff line
@@ -417,22 +417,23 @@ static int wdsp_download_segments(struct wdsp_mgr_priv *wdsp,
	/* Go through the list of segments and download one by one */
	/* Go through the list of segments and download one by one */
	list_for_each_entry(seg, wdsp->seg_list, list) {
	list_for_each_entry(seg, wdsp->seg_list, list) {
		ret = wdsp_load_each_segment(wdsp, seg);
		ret = wdsp_load_each_segment(wdsp, seg);
		if (ret < 0) {
		if (ret)
			wdsp_broadcast_event_downseq(wdsp,
						     WDSP_EVENT_DLOAD_FAILED,
						     NULL);
			goto dload_error;
			goto dload_error;
	}
	}
	}

	/* Flush the list before setting status and notifying components */
	wdsp_flush_segment_list(wdsp->seg_list);


	WDSP_SET_STATUS(wdsp, status);
	WDSP_SET_STATUS(wdsp, status);


	/* Notify all components that image is downloaded */
	/* Notify all components that image is downloaded */
	wdsp_broadcast_event_downseq(wdsp, post, NULL);
	wdsp_broadcast_event_downseq(wdsp, post, NULL);
done:
	return ret;


dload_error:
dload_error:
	wdsp_flush_segment_list(wdsp->seg_list);
	wdsp_flush_segment_list(wdsp->seg_list);
done:
	wdsp_broadcast_event_downseq(wdsp, WDSP_EVENT_DLOAD_FAILED, NULL);
	return ret;
	return ret;
}
}


@@ -486,10 +487,14 @@ static int wdsp_enable_dsp(struct wdsp_mgr_priv *wdsp)
	/* Make sure wdsp is in good state */
	/* Make sure wdsp is in good state */
	if (!WDSP_STATUS_IS_SET(wdsp, WDSP_STATUS_CODE_DLOADED)) {
	if (!WDSP_STATUS_IS_SET(wdsp, WDSP_STATUS_CODE_DLOADED)) {
		WDSP_ERR(wdsp, "WDSP in invalid state 0x%x", wdsp->status);
		WDSP_ERR(wdsp, "WDSP in invalid state 0x%x", wdsp->status);
		ret = -EINVAL;
		return -EINVAL;
		goto done;
	}
	}


	/*
	 * Acquire SSR mutex lock to make sure enablement of DSP
	 * does not race with SSR handling.
	 */
	WDSP_MGR_MUTEX_LOCK(wdsp, wdsp->ssr_mutex);
	/* Download the read-write sections of image */
	/* Download the read-write sections of image */
	ret = wdsp_download_segments(wdsp, WDSP_ELF_FLAG_WRITE);
	ret = wdsp_download_segments(wdsp, WDSP_ELF_FLAG_WRITE);
	if (ret < 0) {
	if (ret < 0) {
@@ -510,6 +515,7 @@ static int wdsp_enable_dsp(struct wdsp_mgr_priv *wdsp)
	wdsp_broadcast_event_downseq(wdsp, WDSP_EVENT_POST_BOOTUP, NULL);
	wdsp_broadcast_event_downseq(wdsp, WDSP_EVENT_POST_BOOTUP, NULL);
	WDSP_SET_STATUS(wdsp, WDSP_STATUS_BOOTED);
	WDSP_SET_STATUS(wdsp, WDSP_STATUS_BOOTED);
done:
done:
	WDSP_MGR_MUTEX_UNLOCK(wdsp, wdsp->ssr_mutex);
	return ret;
	return ret;
}
}