drm/i915: Don't enable IPS when pixel rate exceeds 95%
[deliverable/linux.git] / drivers / gpu / drm / i915 / intel_pm.c
index 5dda008698a2955f202eec6be71645deebda4f6e..d091fec1e10187cf377cbdddb438bfa51f7dfd49 100644 (file)
@@ -1434,23 +1434,22 @@ static void i845_update_wm(struct drm_crtc *unused_crtc)
        I915_WRITE(FW_BLC, fwater_lo);
 }
 
-static uint32_t ilk_pipe_pixel_rate(struct drm_device *dev,
-                                   struct drm_crtc *crtc)
+uint32_t ilk_pipe_pixel_rate(const struct intel_crtc_state *pipe_config)
 {
-       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        uint32_t pixel_rate;
 
-       pixel_rate = intel_crtc->config->base.adjusted_mode.crtc_clock;
+       pixel_rate = pipe_config->base.adjusted_mode.crtc_clock;
 
        /* We only use IF-ID interlacing. If we ever use PF-ID we'll need to
         * adjust the pixel_rate here. */
 
-       if (intel_crtc->config->pch_pfit.enabled) {
+       if (pipe_config->pch_pfit.enabled) {
                uint64_t pipe_w, pipe_h, pfit_w, pfit_h;
-               uint32_t pfit_size = intel_crtc->config->pch_pfit.size;
+               uint32_t pfit_size = pipe_config->pch_pfit.size;
+
+               pipe_w = pipe_config->pipe_src_w;
+               pipe_h = pipe_config->pipe_src_h;
 
-               pipe_w = intel_crtc->config->pipe_src_w;
-               pipe_h = intel_crtc->config->pipe_src_h;
                pfit_w = (pfit_size >> 16) & 0xFFFF;
                pfit_h = pfit_size & 0xFFFF;
                if (pipe_w < pfit_w)
@@ -1815,7 +1814,7 @@ hsw_compute_linetime_wm(struct drm_device *dev, struct drm_crtc *crtc)
        linetime = DIV_ROUND_CLOSEST(mode->crtc_htotal * 1000 * 8,
                                     mode->crtc_clock);
        ips_linetime = DIV_ROUND_CLOSEST(mode->crtc_htotal * 1000 * 8,
-                                        dev_priv->display.get_display_clock_speed(dev_priv->dev));
+                                        dev_priv->cdclk_freq);
 
        return PIPE_WM_LINETIME_IPS_LINETIME(ips_linetime) |
               PIPE_WM_LINETIME_TIME(linetime);
@@ -2066,24 +2065,22 @@ static void ilk_compute_wm_parameters(struct drm_crtc *crtc,
 
        p->active = true;
        p->pipe_htotal = intel_crtc->config->base.adjusted_mode.crtc_htotal;
-       p->pixel_rate = ilk_pipe_pixel_rate(dev, crtc);
+       p->pixel_rate = ilk_pipe_pixel_rate(intel_crtc->config);
 
-       if (crtc->primary->state->fb) {
-               p->pri.enabled = true;
+       if (crtc->primary->state->fb)
                p->pri.bytes_per_pixel =
                        crtc->primary->state->fb->bits_per_pixel / 8;
-       } else {
-               p->pri.enabled = false;
-               p->pri.bytes_per_pixel = 0;
-       }
+       else
+               p->pri.bytes_per_pixel = 4;
+
+       p->cur.bytes_per_pixel = 4;
+       /*
+        * TODO: for now, assume primary and cursor planes are always enabled.
+        * Setting them to false makes the screen flicker.
+        */
+       p->pri.enabled = true;
+       p->cur.enabled = true;
 
-       if (crtc->cursor->state->fb) {
-               p->cur.enabled = true;
-               p->cur.bytes_per_pixel = 4;
-       } else {
-               p->cur.enabled = false;
-               p->cur.bytes_per_pixel = 0;
-       }
        p->pri.horiz_pixels = intel_crtc->config->pipe_src_w;
        p->cur.horiz_pixels = intel_crtc->base.cursor->state->crtc_w;
 
@@ -4143,33 +4140,48 @@ void gen6_rps_idle(struct drm_i915_private *dev_priv)
                dev_priv->rps.last_adj = 0;
                I915_WRITE(GEN6_PMINTRMSK, 0xffffffff);
        }
+       mutex_unlock(&dev_priv->rps.hw_lock);
 
+       spin_lock(&dev_priv->rps.client_lock);
        while (!list_empty(&dev_priv->rps.clients))
                list_del_init(dev_priv->rps.clients.next);
-       mutex_unlock(&dev_priv->rps.hw_lock);
+       spin_unlock(&dev_priv->rps.client_lock);
 }
 
 void gen6_rps_boost(struct drm_i915_private *dev_priv,
-                   struct drm_i915_file_private *file_priv)
+                   struct intel_rps_client *rps,
+                   unsigned long submitted)
 {
-       u32 val;
+       /* This is intentionally racy! We peek at the state here, then
+        * validate inside the RPS worker.
+        */
+       if (!(dev_priv->mm.busy &&
+             dev_priv->rps.enabled &&
+             dev_priv->rps.cur_freq < dev_priv->rps.max_freq_softlimit))
+               return;
 
-       mutex_lock(&dev_priv->rps.hw_lock);
-       val = dev_priv->rps.max_freq_softlimit;
-       if (dev_priv->rps.enabled &&
-           dev_priv->mm.busy &&
-           dev_priv->rps.cur_freq < val &&
-           (file_priv == NULL || list_empty(&file_priv->rps_boost))) {
-               intel_set_rps(dev_priv->dev, val);
-               dev_priv->rps.last_adj = 0;
+       /* Force a RPS boost (and don't count it against the client) if
+        * the GPU is severely congested.
+        */
+       if (rps && time_after(jiffies, submitted + DRM_I915_THROTTLE_JIFFIES))
+               rps = NULL;
+
+       spin_lock(&dev_priv->rps.client_lock);
+       if (rps == NULL || list_empty(&rps->link)) {
+               spin_lock_irq(&dev_priv->irq_lock);
+               if (dev_priv->rps.interrupts_enabled) {
+                       dev_priv->rps.client_boost = true;
+                       queue_work(dev_priv->wq, &dev_priv->rps.work);
+               }
+               spin_unlock_irq(&dev_priv->irq_lock);
 
-               if (file_priv != NULL) {
-                       list_add(&file_priv->rps_boost, &dev_priv->rps.clients);
-                       file_priv->rps_boosts++;
+               if (rps != NULL) {
+                       list_add(&rps->link, &dev_priv->rps.clients);
+                       rps->boosts++;
                } else
                        dev_priv->rps.boosts++;
        }
-       mutex_unlock(&dev_priv->rps.hw_lock);
+       spin_unlock(&dev_priv->rps.client_lock);
 }
 
 void intel_set_rps(struct drm_device *dev, u8 val)
@@ -4949,9 +4961,9 @@ static void cherryview_init_gt_powersave(struct drm_device *dev)
 
        mutex_lock(&dev_priv->rps.hw_lock);
 
-       mutex_lock(&dev_priv->dpio_lock);
+       mutex_lock(&dev_priv->sb_lock);
        val = vlv_cck_read(dev_priv, CCK_FUSE_REG);
-       mutex_unlock(&dev_priv->dpio_lock);
+       mutex_unlock(&dev_priv->sb_lock);
 
        switch ((val >> 2) & 0x7) {
        case 0:
@@ -5871,13 +5883,15 @@ static void ibx_init_clock_gating(struct drm_device *dev)
 static void g4x_disable_trickle_feed(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       int pipe;
+       enum pipe pipe;
 
        for_each_pipe(dev_priv, pipe) {
                I915_WRITE(DSPCNTR(pipe),
                           I915_READ(DSPCNTR(pipe)) |
                           DISPPLANE_TRICKLE_FEED_DISABLE);
-               intel_flush_primary_plane(dev_priv, pipe);
+
+               I915_WRITE(DSPSURF(pipe), I915_READ(DSPSURF(pipe)));
+               POSTING_READ(DSPSURF(pipe));
        }
 }
 
@@ -6167,10 +6181,9 @@ static void broadwell_init_clock_gating(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
        enum pipe pipe;
+       uint32_t misccpctl;
 
-       I915_WRITE(WM3_LP_ILK, 0);
-       I915_WRITE(WM2_LP_ILK, 0);
-       I915_WRITE(WM1_LP_ILK, 0);
+       ilk_init_lp_watermarks(dev);
 
        /* WaSwitchSolVfFArbitrationPriority:bdw */
        I915_WRITE(GAM_ECOCHK, I915_READ(GAM_ECOCHK) | HSW_ECOCHK_ARB_PRIO_SOL);
@@ -6199,6 +6212,22 @@ static void broadwell_init_clock_gating(struct drm_device *dev)
        I915_WRITE(GEN8_UCGCTL6, I915_READ(GEN8_UCGCTL6) |
                   GEN8_SDEUNIT_CLOCK_GATE_DISABLE);
 
+       /*
+        * WaProgramL3SqcReg1Default:bdw
+        * WaTempDisableDOPClkGating:bdw
+        */
+       misccpctl = I915_READ(GEN7_MISCCPCTL);
+       I915_WRITE(GEN7_MISCCPCTL, misccpctl & ~GEN7_DOP_CLOCK_GATE_ENABLE);
+       I915_WRITE(GEN8_L3SQCREG1, BDW_WA_L3SQCREG1_DEFAULT);
+       I915_WRITE(GEN7_MISCCPCTL, misccpctl);
+
+       /*
+        * WaGttCachingOffByDefault:bdw
+        * GTT cache may not work with big pages, so if those
+        * are ever enabled GTT cache may need to be disabled.
+        */
+       I915_WRITE(HSW_GTT_CACHE_EN, GTT_CACHE_EN_ALL);
+
        lpt_init_clock_gating(dev);
 }
 
@@ -6474,6 +6503,12 @@ static void cherryview_init_clock_gating(struct drm_device *dev)
        /* WaDisableSDEUnitClockGating:chv */
        I915_WRITE(GEN8_UCGCTL6, I915_READ(GEN8_UCGCTL6) |
                   GEN8_SDEUNIT_CLOCK_GATE_DISABLE);
+
+       /*
+        * GTT cache may not work with big pages, so if those
+        * are ever enabled GTT cache may need to be disabled.
+        */
+       I915_WRITE(HSW_GTT_CACHE_EN, GTT_CACHE_EN_ALL);
 }
 
 static void g4x_init_clock_gating(struct drm_device *dev)
@@ -6848,11 +6883,13 @@ struct request_boost {
 static void __intel_rps_boost_work(struct work_struct *work)
 {
        struct request_boost *boost = container_of(work, struct request_boost, work);
+       struct drm_i915_gem_request *req = boost->req;
 
-       if (!i915_gem_request_completed(boost->req, true))
-               gen6_rps_boost(to_i915(boost->req->ring->dev), NULL);
+       if (!i915_gem_request_completed(req, true))
+               gen6_rps_boost(to_i915(req->ring->dev), NULL,
+                              req->emitted_jiffies);
 
-       i915_gem_request_unreference__unlocked(boost->req);
+       i915_gem_request_unreference__unlocked(req);
        kfree(boost);
 }
 
@@ -6864,6 +6901,9 @@ void intel_queue_rps_boost_for_request(struct drm_device *dev,
        if (req == NULL || INTEL_INFO(dev)->gen < 6)
                return;
 
+       if (i915_gem_request_completed(req, true))
+               return;
+
        boost = kmalloc(sizeof(*boost), GFP_ATOMIC);
        if (boost == NULL)
                return;
@@ -6880,10 +6920,13 @@ void intel_pm_setup(struct drm_device *dev)
        struct drm_i915_private *dev_priv = dev->dev_private;
 
        mutex_init(&dev_priv->rps.hw_lock);
+       spin_lock_init(&dev_priv->rps.client_lock);
 
        INIT_DELAYED_WORK(&dev_priv->rps.delayed_resume_work,
                          intel_gen6_powersave_work);
        INIT_LIST_HEAD(&dev_priv->rps.clients);
+       INIT_LIST_HEAD(&dev_priv->rps.semaphores.link);
+       INIT_LIST_HEAD(&dev_priv->rps.mmioflips.link);
 
        dev_priv->pm.suspended = false;
 }
This page took 0.041832 seconds and 5 git commands to generate.