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

Commit 420e7e1f authored by Ajay Singh Parmar's avatar Ajay Singh Parmar
Browse files

drm/msm/dp: protect controller functionalities when powered off



DP controller exposes some of its functionalities to DP display.
DP display may call into these functionalities in response to
attention messages received from sink or user-space calls.
In some cases, DP controller may be in idle or powered off state.
Making calls to DP controller in such state may result in unstable
state. Check for DP controller state before calling its functionalities.

CRs-Fixed: 2163274
Change-Id: I0cd2653924e77ce9c673c1b3a3007fd200346314
Signed-off-by: default avatarAjay Singh Parmar <aparmar@codeaurora.org>
parent 84337307
Loading
Loading
Loading
Loading
+17 −4
Original line number Diff line number Diff line
/*
 * Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
 * Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -71,6 +71,8 @@ struct dp_ctrl_private {
	struct completion video_comp;

	bool orientation;
	bool power_on;

	atomic_t aborted;

	u32 pixel_rate;
@@ -128,6 +130,11 @@ static void dp_ctrl_push_idle(struct dp_ctrl *dp_ctrl)

	ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl);

	if (!ctrl->power_on || atomic_read(&ctrl->aborted)) {
		pr_err("CTRL off, return\n");
		return;
	}

	reinit_completion(&ctrl->idle_comp);
	dp_ctrl_state_ctrl(ctrl, ST_PUSH_IDLE);

@@ -833,7 +840,7 @@ static int dp_ctrl_link_train_1(struct dp_ctrl_private *ctrl)

	tries = 0;
	old_v_level = ctrl->link->phy_params.v_level;
	while (1) {
	while (!atomic_read(&ctrl->aborted)) {
		drm_dp_link_train_clock_recovery_delay(ctrl->panel->dpcd);

		ret = dp_ctrl_read_link_status(ctrl, link_status);
@@ -960,7 +967,7 @@ static int dp_ctrl_link_training_2(struct dp_ctrl_private *ctrl)
			ret = -EINVAL;
			break;
		}
	} while (1);
	} while (!atomic_read(&ctrl->aborted));

	return ret;
}
@@ -1180,6 +1187,11 @@ static int dp_ctrl_link_maintenance(struct dp_ctrl *dp_ctrl)

	ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl);

	if (!ctrl->power_on || atomic_read(&ctrl->aborted)) {
		pr_err("CTRL off, return\n");
		return -EINVAL;
	}

	ctrl->dp_ctrl.push_idle(&ctrl->dp_ctrl);
	ctrl->dp_ctrl.reset(&ctrl->dp_ctrl);

@@ -1341,7 +1353,6 @@ static int dp_ctrl_on(struct dp_ctrl *dp_ctrl)
	atomic_set(&ctrl->aborted, 0);
	rate = ctrl->panel->link_info.rate;

	ctrl->power->clk_enable(ctrl->power, DP_CORE_PM, true);
	ctrl->catalog->hpd_config(ctrl->catalog, true);

	if (ctrl->link->sink_request & DP_TEST_LINK_PHY_TEST_PATTERN) {
@@ -1396,6 +1407,7 @@ static int dp_ctrl_on(struct dp_ctrl *dp_ctrl)
	if (ctrl->link->sink_request & DP_TEST_LINK_PHY_TEST_PATTERN)
		dp_ctrl_send_phy_test_pattern(ctrl);

	ctrl->power_on = true;
	pr_debug("End-\n");

end:
@@ -1419,6 +1431,7 @@ static void dp_ctrl_off(struct dp_ctrl *dp_ctrl)

	dp_ctrl_disable_mainlink_clocks(ctrl);

	ctrl->power_on = false;
	pr_debug("DP off done\n");
}

+5 −3
Original line number Diff line number Diff line
@@ -579,8 +579,6 @@ static int dp_display_process_hpd_low(struct dp_display_private *dp)

	rc = dp_display_send_hpd_notification(dp, false);

	dp->aux->deinit(dp->aux);

	dp->panel->video_test = false;

	return rc;
@@ -625,6 +623,8 @@ static void dp_display_clean(struct dp_display_private *dp)

	dp->ctrl->push_idle(dp->ctrl);
	dp->ctrl->off(dp->ctrl);
	dp->panel->deinit(dp->panel);
	dp->aux->deinit(dp->aux);
	dp->power_on = false;
}

@@ -759,7 +759,8 @@ static int dp_display_usbpd_attention_cb(struct device *dev)
		return -ENODEV;
	}

	if (dp->usbpd->hpd_irq && dp->usbpd->hpd_high) {
	if (dp->usbpd->hpd_irq && dp->usbpd->hpd_high &&
	    dp->power_on) {
		dp->link->process_request(dp->link);
		queue_work(dp->wq, &dp->attention_work);
	} else if (dp->usbpd->hpd_high) {
@@ -1156,6 +1157,7 @@ static int dp_display_disable(struct dp_display *dp_display)

	dp->ctrl->off(dp->ctrl);
	dp->panel->deinit(dp->panel);
	dp->aux->deinit(dp->aux);

	connector->hdr_eotf = 0;
	connector->hdr_metadata_type_one = 0;