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

Commit 1a6b2764 authored by Sachin Bhayare's avatar Sachin Bhayare Committed by Krishna Manikandan
Browse files

msm: mdss: fix race condition in idle power collapse logic



MDP3 GDSC can be turned off, or power-collased for command mode panels
in static screen use-cases. In the current implementation, the power
collapse is triggered by a worker thread in the interface driver
whenever it enters the idle state.

Use mutex to protect the idle_pc access and to avoid race condition.

Change-Id: I17a824c88e374aee2404da7f57d5ba5f39e314bc
Signed-off-by: default avatarSachin Bhayare <sachin.bhayare@codeaurora.org>
parent d23a4d38
Loading
Loading
Loading
Loading
+8 −2
Original line number Diff line number Diff line
@@ -2629,10 +2629,12 @@ int mdp3_footswitch_ctrl(int enable)
	int rc = 0;
	int active_cnt = 0;

	mutex_lock(&mdp3_res->fs_idle_pc_lock);
	if (!mdp3_res->fs_ena && enable) {
		rc = regulator_enable(mdp3_res->fs);
		if (rc) {
			pr_err("mdp footswitch ctrl enable failed\n");
			mutex_unlock(&mdp3_res->fs_idle_pc_lock);
			return -EINVAL;
		}
		pr_debug("mdp footswitch ctrl enable success\n");
@@ -2653,13 +2655,16 @@ int mdp3_footswitch_ctrl(int enable)
		rc = regulator_disable(mdp3_res->fs);
		if (rc) {
			pr_err("mdp footswitch ctrl disable failed\n");
			mutex_unlock(&mdp3_res->fs_idle_pc_lock);
			return -EINVAL;
		}
			mdp3_res->fs_ena = false;
		pr_debug("mdp3 footswitch ctrl disable configured\n");
	} else {
		pr_debug("mdp3 footswitch ctrl already configured\n");
	}

	mutex_unlock(&mdp3_res->fs_idle_pc_lock);
	return rc;
}

@@ -2723,6 +2728,7 @@ static int mdp3_probe(struct platform_device *pdev)
	pdev->id = 0;
	mdp3_res->pdev = pdev;
	mutex_init(&mdp3_res->res_mutex);
	mutex_init(&mdp3_res->fs_idle_pc_lock);
	spin_lock_init(&mdp3_res->irq_lock);
	platform_set_drvdata(pdev, mdp3_res);
	atomic_set(&mdp3_res->active_intf_cnt, 0);
+1 −0
Original line number Diff line number Diff line
@@ -168,6 +168,7 @@ struct mdp3_hw_resource {
	bool allow_iommu_update;
	struct ion_handle *ion_handle;
	struct mutex iommu_lock;
	struct mutex fs_idle_pc_lock;

	struct mdp3_dma dma[MDP3_DMA_MAX];
	struct mdp3_intf intf[MDP3_DMA_OUTPUT_SEL_MAX];
+15 −2
Original line number Diff line number Diff line
@@ -1071,7 +1071,10 @@ static int mdp3_ctrl_reset(struct msm_fb_data_type *mfd)
	panel = mdp3_session->panel;
	mdp3_dma = mdp3_session->dma;
	mutex_lock(&mdp3_session->lock);
	if (mdp3_res->idle_pc) {
	pr_debug("mdp3_ctrl_reset idle_pc %s FS_EN %s\n",
		mdp3_res->idle_pc ? "True":"False",
		mdp3_res->fs_ena ? "True":"False");
	if (mdp3_res->idle_pc || mdp3_res->fs_ena) {
		mdp3_clk_enable(1, 0);
		mdp3_dynamic_clock_gating_ctrl(0);
		mdp3_qos_remapper_setup(panel);
@@ -1080,7 +1083,7 @@ static int mdp3_ctrl_reset(struct msm_fb_data_type *mfd)
	rc = mdp3_iommu_enable(MDP3_CLIENT_DMA_P);
	if (rc) {
		pr_err("fail to attach dma iommu\n");
		if (mdp3_res->idle_pc)
		if (mdp3_res->idle_pc || mdp3_res->fs_ena)
			mdp3_clk_enable(0, 0);
		goto reset_error;
	}
@@ -1323,6 +1326,7 @@ static int mdp3_ctrl_display_commit_kickoff(struct msm_fb_data_type *mfd,
	}

	panel = mdp3_session->panel;
	mutex_lock(&mdp3_res->fs_idle_pc_lock);
	if (mdp3_session->in_splash_screen ||
		mdp3_res->idle_pc) {
		pr_debug("%s: reset- in_splash = %d, idle_pc = %d", __func__,
@@ -1330,9 +1334,11 @@ static int mdp3_ctrl_display_commit_kickoff(struct msm_fb_data_type *mfd,
		rc = mdp3_ctrl_reset(mfd);
		if (rc) {
			pr_err("fail to reset display\n");
			mutex_unlock(&mdp3_res->fs_idle_pc_lock);
			return -EINVAL;
		}
	}
	mutex_unlock(&mdp3_res->fs_idle_pc_lock);

	mutex_lock(&mdp3_session->lock);

@@ -1465,6 +1471,7 @@ static void mdp3_ctrl_pan_display(struct msm_fb_data_type *mfd)
	if (!mdp3_session || !mdp3_session->dma)
		return;

	mutex_lock(&mdp3_res->fs_idle_pc_lock);
	if (mdp3_session->in_splash_screen ||
		mdp3_res->idle_pc) {
		pr_debug("%s: reset- in_splash = %d, idle_pc = %d", __func__,
@@ -1472,9 +1479,11 @@ static void mdp3_ctrl_pan_display(struct msm_fb_data_type *mfd)
		rc = mdp3_ctrl_reset(mfd);
		if (rc) {
			pr_err("fail to reset display\n");
			mutex_unlock(&mdp3_res->fs_idle_pc_lock);
			return;
		}
	}
	mutex_unlock(&mdp3_res->fs_idle_pc_lock);

	mutex_lock(&mdp3_session->lock);

@@ -2540,17 +2549,21 @@ static int mdp3_ctrl_ioctl_handler(struct msm_fb_data_type *mfd,
		}
		break;
	case MSMFB_ASYNC_BLIT:
		mutex_lock(&mdp3_res->fs_idle_pc_lock);
		if (mdp3_session->in_splash_screen || mdp3_res->idle_pc) {
			pr_debug("%s: reset- in_splash = %d, idle_pc = %d",
				__func__, mdp3_session->in_splash_screen,
				mdp3_res->idle_pc);
			mdp3_ctrl_reset(mfd);
		}
		mutex_unlock(&mdp3_res->fs_idle_pc_lock);
		rc = mdp3_ctrl_async_blit_req(mfd, argp);
		break;
	case MSMFB_BLIT:
		mutex_lock(&mdp3_res->fs_idle_pc_lock);
		if (mdp3_session->in_splash_screen)
			mdp3_ctrl_reset(mfd);
		mutex_unlock(&mdp3_res->fs_idle_pc_lock);
		rc = mdp3_ctrl_blit_req(mfd, argp);
		break;
	case MSMFB_METADATA_GET: