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

Commit a5e6c0b4 authored by raghavendra ambadas's avatar raghavendra ambadas
Browse files

msm: mdss: fix dead lock between kickof and footswitch ctrl



There is a possibibility of dead lock due to below flow.
mdp3_ctrl.c:mdp3_ctrl_display_commit_kickoff
mutex_lock(&mdp3_res->fs_idle_pc_lock);
mdp3_ctrl.c:mdp3_ctrl_reset
mdp3.c:mdp3_clk_enable
pm_runtime_get_sync
mdp3.c:mdp3_runtime_resume
mdp3.c:mdp3_footswitch_ctrl
mutex_lock(&mdp3_res->fs_idle_pc_lock);

Change-Id: I059053767fe902570c1a448538adb18a2d921c9a
Signed-off-by: default avatarRaghavendra Ambadas <rambad@codeaurora.org>
parent 38bc3d98
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -3198,7 +3198,7 @@ static int mdp3_runtime_resume(struct device *dev)
		atomic_read(&mdp3_res->active_intf_cnt));

	/* do not resume panels when coming out of idle power collapse */
	if (!mdp3_res->idle_pc)
	if (!mdp3_is_idle_pc())
		device_for_each_child(dev, &device_on, mdss_fb_suspres_panel);

	MDSS_XLOG(XLOG_FUNC_ENTRY);
@@ -3230,7 +3230,7 @@ static int mdp3_runtime_suspend(struct device *dev)
	mdp3_footswitch_ctrl(0);

	/* do not suspend panels when going in to idle power collapse */
	if (!mdp3_res->idle_pc)
	if (!mdp3_is_idle_pc())
		device_for_each_child(dev, &device_on, mdss_fb_suspres_panel);

	return 0;
+14 −0
Original line number Diff line number Diff line
@@ -249,6 +249,20 @@ struct mdp3_img_data {

extern struct mdp3_hw_resource *mdp3_res;

/*
 * mdp3_is_idle_pc: - checks if a panel is idle
 */
static inline bool mdp3_is_idle_pc(void)
{
	bool ret = 0;

	mutex_lock(&mdp3_res->fs_idle_pc_lock);
	ret = mdp3_res->idle_pc;
	mutex_unlock(&mdp3_res->fs_idle_pc_lock);

	return ret;
}

struct mdp3_dma *mdp3_get_dma_pipe(int capability);
struct mdp3_intf *mdp3_get_display_intf(int type);
void mdp3_irq_enable(int type);
+8 −18
Original line number Diff line number Diff line
@@ -1324,7 +1324,7 @@ int mdp3_ctrl_reset(struct msm_fb_data_type *mfd)
	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) {
	if (mdp3_is_idle_pc()) {
		mdp3_clk_enable(1, 0);
		mdp3_dynamic_clock_gating_ctrl(0);
		mdp3_qos_remapper_setup(panel);
@@ -1343,7 +1343,7 @@ 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_is_idle_pc())
			mdp3_clk_enable(0, 0);
		goto reset_error;
	}
@@ -1357,7 +1357,7 @@ int mdp3_ctrl_reset(struct msm_fb_data_type *mfd)
	if (vsync_client.handler)
		mdp3_dma->vsync_enable(mdp3_dma, &vsync_client);

	if (!mdp3_res->idle_pc) {
	if (!mdp3_is_idle_pc()) {
		mdp3_session->first_commit = true;
	mfd->panel_info->cont_splash_enabled = 0;
	mdp3_session->in_splash_screen = 0;
@@ -1365,7 +1365,9 @@ int mdp3_ctrl_reset(struct msm_fb_data_type *mfd)
		/* Disable Auto refresh */
		mdp3_autorefresh_disable(mfd->panel_info);
	} else {
		mutex_lock(&mdp3_res->fs_idle_pc_lock);
		mdp3_res->idle_pc = false;
		mutex_unlock(&mdp3_res->fs_idle_pc_lock);
		mdp3_clk_enable(0, 0);
		mdp3_iommu_disable(MDP3_CLIENT_DMA_P);
	}
@@ -1625,19 +1627,16 @@ 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) {
		mdp3_is_idle_pc()) {
		pr_debug("%s: reset- in_splash = %d, idle_pc = %d", __func__,
			mdp3_session->in_splash_screen, mdp3_res->idle_pc);
		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);

	cancel_work_sync(&mdp3_session->clk_off_work);
	mutex_lock(&mdp3_session->lock);
@@ -1848,19 +1847,16 @@ 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) {
		mdp3_is_idle_pc()) {
		pr_debug("%s: reset- in_splash = %d, idle_pc = %d", __func__,
			mdp3_session->in_splash_screen, mdp3_res->idle_pc);
		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);

@@ -2957,23 +2953,19 @@ 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) {
		if (mdp3_session->in_splash_screen || mdp3_is_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);
		if (!rc)
			cancel_work_sync(&mdp3_session->clk_off_work);
		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);
		if (!rc)
			cancel_work_sync(&mdp3_session->clk_off_work);
@@ -3022,10 +3014,8 @@ static int mdp3_ctrl_ioctl_handler(struct msm_fb_data_type *mfd,
		break;
	case MSMFB_OVERLAY_PLAY:
		rc = copy_from_user(&ov_data, argp, sizeof(ov_data));
		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);
		if (!rc)
			rc = mdp3_overlay_play(mfd, &ov_data);
		if (rc)