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

Commit 5f0fb8f9 authored by Adrian Salido-Moreno's avatar Adrian Salido-Moreno
Browse files

msm: mdss: isolate cleanup of pipes within kickoff



During display commit cycle, we need to iterate through pipes that have
been marked for cleanup and destroy these. However in the middle of the
function we may block for sometime to wait for display to be ready, when
this happens we are releasing ov_lock which controls access to this
cleanup list. If there is any cleanup done in this period, then there
could be some pipes incorrectly cleaned up after this.

To fix this race condition, add a local variable to keep track of pipes
that should be cleaned up.

Change-Id: Ib80cf91e10d66e318754c327fd71a489b8c42676
Signed-off-by: default avatarAdrian Salido-Moreno <adrianm@codeaurora.org>
parent a65cf5a3
Loading
Loading
Loading
Loading
+17 −9
Original line number Diff line number Diff line
@@ -1077,18 +1077,24 @@ static void __mdss_mdp_overlay_free_list_add(struct msm_fb_data_type *mfd,
	memset(buf, 0, sizeof(*buf));
}

static void mdss_mdp_overlay_cleanup(struct msm_fb_data_type *mfd)
/**
 * mdss_mdp_overlay_cleanup() - handles cleanup after frame commit
 * @mfd:           Msm frame buffer data structure for the associated fb
 * @destroy_pipes: list of pipes that should be destroyed as part of cleanup
 *
 * Goes through destroy_pipes list and ensures they are ready to be destroyed
 * and cleaned up. Also cleanup of any pipe buffers after flip.
 */
static void mdss_mdp_overlay_cleanup(struct msm_fb_data_type *mfd,
		struct list_head *destroy_pipes)
{
	struct mdss_mdp_pipe *pipe, *tmp;
	struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
	struct mdss_mdp_ctl *ctl = mfd_to_ctl(mfd);
	bool recovery_mode = false;
	LIST_HEAD(destroy_pipes);

	mutex_lock(&mdp5_data->list_lock);
	list_for_each_entry_safe(pipe, tmp, &mdp5_data->pipes_cleanup, list) {
		list_move(&pipe->list, &destroy_pipes);

	list_for_each_entry(pipe, destroy_pipes, list) {
		/* make sure pipe fetch has been halted before freeing buffer */
		if (mdss_mdp_pipe_fetch_halt(pipe)) {
			/*
@@ -1123,7 +1129,7 @@ static void mdss_mdp_overlay_cleanup(struct msm_fb_data_type *mfd)
		}
	}

	list_for_each_entry_safe(pipe, tmp, &destroy_pipes, list) {
	list_for_each_entry_safe(pipe, tmp, destroy_pipes, list) {
		/*
		 * in case of secure UI, the buffer needs to be released as
		 * soon as session is closed.
@@ -1421,13 +1427,14 @@ int mdss_mdp_overlay_kickoff(struct msm_fb_data_type *mfd,
				struct mdp_display_commit *data)
{
	struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
	struct mdss_mdp_pipe *pipe;
	struct mdss_mdp_pipe *pipe, *tmp;
	struct mdss_mdp_ctl *ctl = mfd_to_ctl(mfd);
	struct mdp_display_commit temp_data;
	int ret = 0;
	int sd_in_pipe = 0;
	bool need_cleanup = false;
	struct mdss_mdp_commit_cb commit_cb;
	LIST_HEAD(destroy_pipes);

	ATRACE_BEGIN(__func__);
	if (ctl->shared_lock) {
@@ -1503,10 +1510,11 @@ int mdss_mdp_overlay_kickoff(struct msm_fb_data_type *mfd,
	 * Setup pipe in solid fill before unstaging,
	 * to ensure no fetches are happening after dettach or reattach.
	 */
	list_for_each_entry(pipe, &mdp5_data->pipes_cleanup, list) {
	list_for_each_entry_safe(pipe, tmp, &mdp5_data->pipes_cleanup, list) {
		mdss_mdp_pipe_queue_data(pipe, NULL);
		mdss_mdp_mixer_pipe_unstage(pipe, pipe->mixer_left);
		mdss_mdp_mixer_pipe_unstage(pipe, pipe->mixer_right);
		list_move(&pipe->list, &destroy_pipes);
		need_cleanup = true;
	}

@@ -1563,7 +1571,7 @@ int mdss_mdp_overlay_kickoff(struct msm_fb_data_type *mfd,
	mdss_fb_update_notify_update(mfd);
commit_fail:
	ATRACE_BEGIN("overlay_cleanup");
	mdss_mdp_overlay_cleanup(mfd);
	mdss_mdp_overlay_cleanup(mfd, &destroy_pipes);
	ATRACE_END("overlay_cleanup");
	mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF);
	mdss_mdp_ctl_notify(ctl, MDP_NOTIFY_FRAME_FLUSHED);