OSDN Git Service

drm/msm/sde: synchronize mdp clk with frame update
authorAbhinav Kumar <abhinavk@codeaurora.org>
Sat, 14 Oct 2017 04:02:23 +0000 (21:02 -0700)
committerGerrit - the friendly Code Review server <code-review@localhost>
Wed, 18 Oct 2017 02:20:50 +0000 (19:20 -0700)
There is a race condition between the commit and
the validate, where the mdp clock or the bandwidth
can be updated for voting before the actual configuration
is taking place.

Fix this issue by caching the performance values in the crtc
till the current hw configuration is on-going.

Change-Id: Icc71c4f58cbc305529d308335f44b8c05702ebee
Signed-off-by: Abhinav Kumar <abhinavk@codeaurora.org>
drivers/gpu/drm/msm/sde/sde_core_perf.c
drivers/gpu/drm/msm/sde/sde_crtc.h

index 8c312b7..29e746e 100644 (file)
@@ -304,18 +304,27 @@ static int _sde_core_select_clk_lvl(struct sde_kms *kms,
        return clk_round_rate(kms->perf.core_clk, clk_rate);
 }
 
-static u32 _sde_core_perf_get_core_clk_rate(struct sde_kms *kms)
+static u32 _sde_core_perf_get_core_clk_rate(struct sde_kms *kms,
+       struct sde_core_perf_params *crct_perf, struct drm_crtc *crtc)
 {
        u32 clk_rate = 0;
-       struct drm_crtc *crtc;
+       struct drm_crtc *tmp_crtc;
        struct sde_crtc_state *sde_cstate;
        int ncrtc = 0;
+       u32 tmp_rate;
+
+       drm_for_each_crtc(tmp_crtc, kms->dev) {
+               if (_sde_core_perf_crtc_is_power_on(tmp_crtc)) {
 
-       drm_for_each_crtc(crtc, kms->dev) {
-               if (_sde_core_perf_crtc_is_power_on(crtc)) {
-                       sde_cstate = to_sde_crtc_state(crtc->state);
-                       clk_rate = max(sde_cstate->new_perf.core_clk_rate,
-                                                       clk_rate);
+                       if (crtc->base.id == tmp_crtc->base.id) {
+                               /* for current CRTC, use the cached value */
+                               tmp_rate = crct_perf->core_clk_rate;
+                       } else {
+                               sde_cstate = to_sde_crtc_state(tmp_crtc->state);
+                               tmp_rate = sde_cstate->new_perf.core_clk_rate;
+                       }
+
+                       clk_rate = max(tmp_rate, clk_rate);
                        clk_rate = clk_round_rate(kms->perf.core_clk, clk_rate);
                }
                ncrtc++;
@@ -359,8 +368,18 @@ void sde_core_perf_crtc_update(struct drm_crtc *crtc,
 
        SDE_ATRACE_BEGIN(__func__);
 
+       /*
+        * cache the performance numbers in the crtc prior to the
+        * crtc kickoff, so the same numbers are used during the
+        * perf update that happens post kickoff.
+        */
+
+       if (params_changed)
+               memcpy(&sde_crtc->new_perf, &sde_cstate->new_perf,
+                          sizeof(struct sde_core_perf_params));
+
        old = &sde_crtc->cur_perf;
-       new = &sde_cstate->new_perf;
+       new = &sde_crtc->new_perf;
 
        if (_sde_core_perf_crtc_is_power_on(crtc) && !stop_req) {
                /*
@@ -401,7 +420,7 @@ void sde_core_perf_crtc_update(struct drm_crtc *crtc,
         * use the new clock for the rotator bw calculation.
         */
        if (update_clk)
-               clk_rate = _sde_core_perf_get_core_clk_rate(kms);
+               clk_rate = _sde_core_perf_get_core_clk_rate(kms, old, crtc);
 
        if (update_bus)
                _sde_core_perf_crtc_update_bus(kms, crtc, clk_rate);
@@ -412,7 +431,9 @@ void sde_core_perf_crtc_update(struct drm_crtc *crtc,
         */
        if (update_clk) {
                SDE_ATRACE_INT(kms->perf.clk_name, clk_rate);
-               SDE_EVT32(kms->dev, stop_req, clk_rate);
+               SDE_EVT32(kms->dev, stop_req, clk_rate, params_changed,
+                                 old->core_clk_rate, new->core_clk_rate);
+
                ret = sde_power_clk_set_rate(&priv->phandle,
                                kms->perf.clk_name, clk_rate);
                if (ret) {
index 531b790..2000739 100644 (file)
@@ -96,6 +96,7 @@ struct sde_crtc_frame_event {
  * @pending       : Whether any page-flip events are pending signal
  * @spin_lock     : spin lock for frame event, transaction status, etc...
  * @cur_perf      : current performance committed to clock/bandwidth driver
+ * @new_perf      : new performance committed to clock/bandwidth driver
  */
 struct sde_crtc {
        struct drm_crtc base;
@@ -137,6 +138,7 @@ struct sde_crtc {
        spinlock_t spin_lock;
 
        struct sde_core_perf_params cur_perf;
+       struct sde_core_perf_params new_perf;
 };
 
 #define to_sde_crtc(x) container_of(x, struct sde_crtc, base)