Browse Source

disp: msm: remove runtime_pm support from rsc driver

Remove runtime_pm support from rsc driver. RSC driver
does not vote for MMCX. It relies on sde core driver
to keep vote and trigger call. That brings additional
dependency to manage runtime_pm references during
pm_suspend/pm_resume call. This change also updates
the runtime_pm call to manage the pm_suspend in
msm drm driver.

Change-Id: I111771994822c82db53fb6c23e5d942f90fd1af2
Signed-off-by: Dhaval Patel <[email protected]>
Dhaval Patel 5 năm trước cách đây
mục cha
commit
c1cef9cfaf
3 tập tin đã thay đổi với 99 bổ sung87 xóa
  1. 9 1
      msm/sde/sde_kms.c
  2. 88 86
      msm/sde_rsc.c
  3. 2 0
      msm/sde_rsc_priv.h

+ 9 - 1
msm/sde/sde_kms.c

@@ -2641,7 +2641,6 @@ static int sde_kms_pm_suspend(struct device *dev)
 
 	sde_kms = to_sde_kms(ddev_to_msm_kms(ddev));
 	SDE_EVT32(0);
-	pm_runtime_put_noidle(dev);
 
 	/* disable hot-plug polling */
 	drm_kms_helper_poll_disable(ddev);
@@ -2750,6 +2749,15 @@ unlock:
 	}
 	drm_modeset_drop_locks(&ctx);
 	drm_modeset_acquire_fini(&ctx);
+
+	/*
+	 * pm runtime driver avoids multiple runtime_suspend API call by
+	 * checking runtime_status. However, this call helps when there is a
+	 * race condition between pm_suspend call and doze_suspend/power_off
+	 * commit. It removes the extra vote from suspend and adds it back
+	 * later to allow power collapse during pm_suspend call
+	 */
+	pm_runtime_put_sync(dev);
 	pm_runtime_get_noresume(dev);
 
 	return ret;

+ 88 - 86
msm/sde_rsc.c

@@ -15,7 +15,6 @@
 #include <linux/mutex.h>
 #include <linux/of_platform.h>
 #include <linux/module.h>
-#include <linux/pm_runtime.h>
 #include <linux/msm-bus.h>
 
 #include <soc/qcom/rpmh.h>
@@ -399,6 +398,86 @@ static u32 sde_rsc_timer_calculate(struct sde_rsc_priv *rsc,
 	return ret;
 }
 
+static int sde_rsc_resource_disable(struct sde_rsc_priv *rsc)
+{
+	struct dss_module_power *mp;
+	u32 reg_bus_hdl;
+
+	if (!rsc) {
+		pr_err("invalid drv data\n");
+		return -EINVAL;
+	}
+
+	if (atomic_read(&rsc->resource_refcount) == 0) {
+		pr_err("%pS: invalid rsc resource disable call\n",
+			__builtin_return_address(0));
+		return -EINVAL;
+	}
+
+	if (atomic_dec_return(&rsc->resource_refcount) != 0)
+		return 0;
+
+	mp = &rsc->phandle.mp;
+	msm_dss_enable_clk(mp->clk_config, mp->num_clk, false);
+	reg_bus_hdl = rsc->phandle.reg_bus_hdl;
+	if (reg_bus_hdl)
+		msm_bus_scale_client_update_request(reg_bus_hdl,
+				VOTE_INDEX_DISABLE);
+	msm_dss_enable_vreg(mp->vreg_config, mp->num_vreg, false);
+
+	return 0;
+}
+
+static int sde_rsc_resource_enable(struct sde_rsc_priv *rsc)
+{
+	struct dss_module_power *mp;
+	int rc = 0;
+	u32 reg_bus_hdl;
+
+	if (!rsc) {
+		pr_err("invalid drv data\n");
+		return -EINVAL;
+	}
+
+	if (atomic_inc_return(&rsc->resource_refcount) != 1)
+		return 0;
+
+	mp = &rsc->phandle.mp;
+	rc = msm_dss_enable_vreg(mp->vreg_config, mp->num_vreg, true);
+	if (rc) {
+		pr_err("failed to enable vregs rc=%d\n", rc);
+		goto end;
+	}
+
+	reg_bus_hdl = rsc->phandle.reg_bus_hdl;
+	if (reg_bus_hdl) {
+		rc = msm_bus_scale_client_update_request(reg_bus_hdl,
+				VOTE_INDEX_LOW);
+		if (rc) {
+			pr_err("failed to set reg bus vote rc=%d\n", rc);
+			goto reg_bus_hdl_err;
+		}
+	}
+
+	rc = msm_dss_enable_clk(mp->clk_config, mp->num_clk, true);
+	if (rc) {
+		pr_err("clock enable failed rc:%d\n", rc);
+		goto clk_err;
+	}
+
+	return rc;
+
+clk_err:
+	if (reg_bus_hdl)
+		msm_bus_scale_client_update_request(reg_bus_hdl,
+				VOTE_INDEX_DISABLE);
+reg_bus_hdl_err:
+	msm_dss_enable_vreg(mp->vreg_config, mp->num_vreg, false);
+end:
+	atomic_dec(&rsc->resource_refcount);
+	return rc;
+}
+
 static int sde_rsc_switch_to_cmd(struct sde_rsc_priv *rsc,
 	struct sde_rsc_cmd_config *config,
 	struct sde_rsc_client *caller_client,
@@ -824,7 +903,7 @@ int sde_rsc_client_state_update(struct sde_rsc_client *caller_client,
 		caller_client->name, state);
 
 	if (rsc->current_state == SDE_RSC_IDLE_STATE)
-		pm_runtime_get_sync(rsc->dev);
+		sde_rsc_resource_enable(rsc);
 
 	switch (state) {
 	case SDE_RSC_IDLE_STATE:
@@ -882,7 +961,7 @@ int sde_rsc_client_state_update(struct sde_rsc_client *caller_client,
 
 clk_disable:
 	if (rsc->current_state == SDE_RSC_IDLE_STATE)
-		pm_runtime_put_sync(rsc->dev);
+		sde_rsc_resource_disable(rsc);
 end:
 	mutex_unlock(&rsc->client_lock);
 	return rc;
@@ -959,7 +1038,7 @@ int sde_rsc_client_trigger_vote(struct sde_rsc_client *caller_client,
 		rsc->bw_config.ib_vote[i] = rsc->bw_config.new_ib_vote[i];
 	}
 
-	rc = pm_runtime_get_sync(rsc->dev);
+	rc = sde_rsc_resource_enable(rsc);
 	if (rc < 0)
 		goto clk_enable_fail;
 
@@ -990,7 +1069,7 @@ int sde_rsc_client_trigger_vote(struct sde_rsc_client *caller_client,
 		rsc->hw_ops.tcs_use_ok(rsc);
 
 end:
-	pm_runtime_put_sync(rsc->dev);
+	sde_rsc_resource_disable(rsc);
 clk_enable_fail:
 	mutex_unlock(&rsc->client_lock);
 
@@ -1299,7 +1378,7 @@ static void sde_rsc_deinit(struct platform_device *pdev,
 	if (!rsc)
 		return;
 
-	pm_runtime_put_sync(rsc->dev);
+	sde_rsc_resource_disable(rsc);
 	if (rsc->sw_fs_enabled)
 		regulator_disable(rsc->fs);
 	if (rsc->fs)
@@ -1314,82 +1393,6 @@ static void sde_rsc_deinit(struct platform_device *pdev,
 	kfree(rsc);
 }
 
-#ifdef CONFIG_PM
-static int sde_rsc_runtime_suspend(struct device *dev)
-{
-	struct sde_rsc_priv *rsc = dev_get_drvdata(dev);
-	struct dss_module_power *mp;
-	u32 reg_bus_hdl;
-
-	if (!rsc) {
-		pr_err("invalid drv data\n");
-		return -EINVAL;
-	}
-
-	mp = &rsc->phandle.mp;
-	msm_dss_enable_clk(mp->clk_config, mp->num_clk, false);
-	reg_bus_hdl = rsc->phandle.reg_bus_hdl;
-	if (reg_bus_hdl)
-		msm_bus_scale_client_update_request(reg_bus_hdl,
-				VOTE_INDEX_DISABLE);
-	msm_dss_enable_vreg(mp->vreg_config, mp->num_vreg, false);
-
-	return 0;
-}
-
-static int sde_rsc_runtime_resume(struct device *dev)
-{
-	struct sde_rsc_priv *rsc = dev_get_drvdata(dev);
-	struct dss_module_power *mp;
-	int rc = 0;
-	u32 reg_bus_hdl;
-
-	if (!rsc) {
-		pr_err("invalid drv data\n");
-		return -EINVAL;
-	}
-
-	mp = &rsc->phandle.mp;
-	rc = msm_dss_enable_vreg(mp->vreg_config, mp->num_vreg, true);
-	if (rc) {
-		pr_err("failed to enable vregs rc=%d\n", rc);
-		goto end;
-	}
-
-	reg_bus_hdl = rsc->phandle.reg_bus_hdl;
-	if (reg_bus_hdl) {
-		rc = msm_bus_scale_client_update_request(reg_bus_hdl,
-				VOTE_INDEX_LOW);
-		if (rc) {
-			pr_err("failed to set reg bus vote rc=%d\n", rc);
-			goto reg_bus_hdl_err;
-		}
-	}
-
-	rc = msm_dss_enable_clk(mp->clk_config, mp->num_clk, true);
-	if (rc) {
-		pr_err("clock enable failed rc:%d\n", rc);
-		goto clk_err;
-	}
-
-	return rc;
-
-clk_err:
-	if (reg_bus_hdl)
-		msm_bus_scale_client_update_request(reg_bus_hdl,
-				VOTE_INDEX_DISABLE);
-reg_bus_hdl_err:
-	msm_dss_enable_vreg(mp->vreg_config, mp->num_vreg, false);
-end:
-	return rc;
-}
-#endif
-
-static const struct dev_pm_ops sde_rsc_pm_ops = {
-	SET_RUNTIME_PM_OPS(sde_rsc_runtime_suspend,
-				sde_rsc_runtime_resume, NULL)
-};
-
 /**
  * sde_rsc_bind - bind rsc device with controlling device
  * @dev:        Pointer to base of platform device
@@ -1556,8 +1559,7 @@ static int sde_rsc_probe(struct platform_device *pdev)
 
 	rsc->sw_fs_enabled = true;
 
-	pm_runtime_enable(rsc->dev);
-	ret = pm_runtime_get_sync(rsc->dev);
+	ret = sde_rsc_resource_enable(rsc);
 	if (ret < 0) {
 		pr_err("failed to enable sde rsc power resources rc:%d\n", ret);
 		goto sde_rsc_fail;
@@ -1566,12 +1568,13 @@ static int sde_rsc_probe(struct platform_device *pdev)
 	if (sde_rsc_timer_calculate(rsc, NULL, SDE_RSC_IDLE_STATE))
 		goto sde_rsc_fail;
 
-	pm_runtime_put_sync(rsc->dev);
+	sde_rsc_resource_disable(rsc);
 
 	INIT_LIST_HEAD(&rsc->client_list);
 	INIT_LIST_HEAD(&rsc->event_list);
 	mutex_init(&rsc->client_lock);
 	init_waitqueue_head(&rsc->rsc_vsync_waitq);
+	atomic_set(&rsc->resource_refcount, 0);
 
 	pr_info("sde rsc index:%d probed successfully\n",
 				SDE_RSC_INDEX + counter);
@@ -1644,7 +1647,6 @@ static struct platform_driver sde_rsc_platform_driver = {
 		.name   = "sde_rsc",
 		.of_match_table = dt_match,
 		.suppress_bind_attrs = true,
-		.pm     = &sde_rsc_pm_ops,
 	},
 };
 

+ 2 - 0
msm/sde_rsc_priv.h

@@ -185,6 +185,7 @@ struct sde_rsc_bw_config {
  * rsc_vsync_waitq:   Queue to wait for the vsync.
  * bw_config:		check sde_rsc_bw_config structure description.
  * dev:			rsc device node
+ * resource_refcount:	Track rsc resource refcount
  */
 struct sde_rsc_priv {
 	u32 version;
@@ -225,6 +226,7 @@ struct sde_rsc_priv {
 
 	struct sde_rsc_bw_config bw_config;
 	struct device *dev;
+	atomic_t resource_refcount;
 };
 
 /**