drm/i915: Report the failure to write to the punit
authorChris Wilson <chris@chris-wilson.co.uk>
Thu, 26 Jan 2017 10:19:19 +0000 (10:19 +0000)
committerChris Wilson <chris@chris-wilson.co.uk>
Thu, 26 Jan 2017 17:09:44 +0000 (17:09 +0000)
The write to the punit may fail, so propagate the error code back to its
callers. Of particular interest are the RPS writes, so add appropriate
user error codes and logging.

v2: Add DEBUG for failed frequency changes during RPS.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Mika Kuoppala <mika.kuoppala@intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/20170126101919.13211-1-chris@chris-wilson.co.uk
Reviewed-by: Mika Kuoppala <mika.kuoppala@intel.com>
drivers/gpu/drm/i915/i915_debugfs.c
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_irq.c
drivers/gpu/drm/i915/i915_sysfs.c
drivers/gpu/drm/i915/intel_pm.c
drivers/gpu/drm/i915/intel_sideband.c

index 0a39487386ad12caa8b12527ff6ae516603f67e9..3ae06568df7bcc5bc29b62cb30e5acfc62be8c4f 100644 (file)
@@ -4278,7 +4278,8 @@ i915_max_freq_set(void *data, u64 val)
 
        dev_priv->rps.max_freq_softlimit = val;
 
-       intel_set_rps(dev_priv, val);
+       if (intel_set_rps(dev_priv, val))
+               DRM_DEBUG_DRIVER("failed to update RPS to new softlimit\n");
 
        mutex_unlock(&dev_priv->rps.hw_lock);
 
@@ -4333,7 +4334,8 @@ i915_min_freq_set(void *data, u64 val)
 
        dev_priv->rps.min_freq_softlimit = val;
 
-       intel_set_rps(dev_priv, val);
+       if (intel_set_rps(dev_priv, val))
+               DRM_DEBUG_DRIVER("failed to update RPS to new softlimit\n");
 
        mutex_unlock(&dev_priv->rps.hw_lock);
 
index 3623a6e462830c9f043acb349472be9b2f8438bc..457129b64d792860d0f789e68c0c7350e4c1b43d 100644 (file)
@@ -3701,7 +3701,7 @@ extern void i915_redisable_vga(struct drm_i915_private *dev_priv);
 extern void i915_redisable_vga_power_on(struct drm_i915_private *dev_priv);
 extern bool ironlake_set_drps(struct drm_i915_private *dev_priv, u8 val);
 extern void intel_init_pch_refclk(struct drm_i915_private *dev_priv);
-extern void intel_set_rps(struct drm_i915_private *dev_priv, u8 val);
+extern int intel_set_rps(struct drm_i915_private *dev_priv, u8 val);
 extern bool intel_set_memory_cxsr(struct drm_i915_private *dev_priv,
                                  bool enable);
 
@@ -3727,7 +3727,7 @@ int skl_pcode_request(struct drm_i915_private *dev_priv, u32 mbox, u32 request,
 
 /* intel_sideband.c */
 u32 vlv_punit_read(struct drm_i915_private *dev_priv, u32 addr);
-void vlv_punit_write(struct drm_i915_private *dev_priv, u32 addr, u32 val);
+int vlv_punit_write(struct drm_i915_private *dev_priv, u32 addr, u32 val);
 u32 vlv_nc_read(struct drm_i915_private *dev_priv, u8 addr);
 u32 vlv_iosf_sb_read(struct drm_i915_private *dev_priv, u8 port, u32 reg);
 void vlv_iosf_sb_write(struct drm_i915_private *dev_priv, u8 port, u32 reg, u32 val);
index 3f3c9082b0f8df125483a32aa76ffad0c7139f5b..059d66b46e1a46d0a41f3913112f72c9c65402e5 100644 (file)
@@ -1209,7 +1209,10 @@ static void gen6_pm_rps_work(struct work_struct *work)
        new_delay += adj;
        new_delay = clamp_t(int, new_delay, min, max);
 
-       intel_set_rps(dev_priv, new_delay);
+       if (intel_set_rps(dev_priv, new_delay)) {
+               DRM_DEBUG_DRIVER("Failed to set new GPU frequency\n");
+               dev_priv->rps.last_adj = 0;
+       }
 
        mutex_unlock(&dev_priv->rps.hw_lock);
 }
index 376ac957cd1c8fa528edc83b5682581ce7f50e36..a721ff1161016447bcf1c2a568fa20759e693415 100644 (file)
@@ -395,13 +395,13 @@ static ssize_t gt_max_freq_mhz_store(struct device *kdev,
        /* We still need *_set_rps to process the new max_delay and
         * update the interrupt limits and PMINTRMSK even though
         * frequency request may be unchanged. */
-       intel_set_rps(dev_priv, val);
+       ret = intel_set_rps(dev_priv, val);
 
        mutex_unlock(&dev_priv->rps.hw_lock);
 
        intel_runtime_pm_put(dev_priv);
 
-       return count;
+       return ret ?: count;
 }
 
 static ssize_t gt_min_freq_mhz_show(struct device *kdev, struct device_attribute *attr, char *buf)
@@ -448,14 +448,13 @@ static ssize_t gt_min_freq_mhz_store(struct device *kdev,
        /* We still need *_set_rps to process the new min_delay and
         * update the interrupt limits and PMINTRMSK even though
         * frequency request may be unchanged. */
-       intel_set_rps(dev_priv, val);
+       ret = intel_set_rps(dev_priv, val);
 
        mutex_unlock(&dev_priv->rps.hw_lock);
 
        intel_runtime_pm_put(dev_priv);
 
-       return count;
-
+       return ret ?: count;
 }
 
 static DEVICE_ATTR(gt_act_freq_mhz, S_IRUGO, gt_act_freq_mhz_show, NULL);
index a04d81aa1fc13cd33d615b85dd8825f9e43adfbb..bec4283cc2283db6a5f065a7d28e9dcd6be37e7c 100644 (file)
@@ -4933,7 +4933,7 @@ static u32 gen6_rps_pm_mask(struct drm_i915_private *dev_priv, u8 val)
 /* gen6_set_rps is called to update the frequency request, but should also be
  * called when the range (min_delay and max_delay) is modified so that we can
  * update the GEN6_RP_INTERRUPT_LIMITS register accordingly. */
-static void gen6_set_rps(struct drm_i915_private *dev_priv, u8 val)
+static int gen6_set_rps(struct drm_i915_private *dev_priv, u8 val)
 {
        WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock));
        WARN_ON(val > dev_priv->rps.max_freq);
@@ -4968,10 +4968,14 @@ static void gen6_set_rps(struct drm_i915_private *dev_priv, u8 val)
 
        dev_priv->rps.cur_freq = val;
        trace_intel_gpu_freq_change(intel_gpu_freq(dev_priv, val));
+
+       return 0;
 }
 
-static void valleyview_set_rps(struct drm_i915_private *dev_priv, u8 val)
+static int valleyview_set_rps(struct drm_i915_private *dev_priv, u8 val)
 {
+       int err;
+
        WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock));
        WARN_ON(val > dev_priv->rps.max_freq);
        WARN_ON(val < dev_priv->rps.min_freq);
@@ -4983,13 +4987,18 @@ static void valleyview_set_rps(struct drm_i915_private *dev_priv, u8 val)
        I915_WRITE(GEN6_PMINTRMSK, gen6_rps_pm_mask(dev_priv, val));
 
        if (val != dev_priv->rps.cur_freq) {
-               vlv_punit_write(dev_priv, PUNIT_REG_GPU_FREQ_REQ, val);
+               err = vlv_punit_write(dev_priv, PUNIT_REG_GPU_FREQ_REQ, val);
+               if (err)
+                       return err;
+
                if (!IS_CHERRYVIEW(dev_priv))
                        gen6_set_rps_thresholds(dev_priv, val);
        }
 
        dev_priv->rps.cur_freq = val;
        trace_intel_gpu_freq_change(intel_gpu_freq(dev_priv, val));
+
+       return 0;
 }
 
 /* vlv_set_rps_idle: Set the frequency to idle, if Gfx clocks are down
@@ -5002,6 +5011,7 @@ static void valleyview_set_rps(struct drm_i915_private *dev_priv, u8 val)
 static void vlv_set_rps_idle(struct drm_i915_private *dev_priv)
 {
        u32 val = dev_priv->rps.idle_freq;
+       int err;
 
        if (dev_priv->rps.cur_freq <= val)
                return;
@@ -5019,8 +5029,11 @@ static void vlv_set_rps_idle(struct drm_i915_private *dev_priv)
         * power than the render powerwell.
         */
        intel_uncore_forcewake_get(dev_priv, FORCEWAKE_MEDIA);
-       valleyview_set_rps(dev_priv, val);
+       err = valleyview_set_rps(dev_priv, val);
        intel_uncore_forcewake_put(dev_priv, FORCEWAKE_MEDIA);
+
+       if (err)
+               DRM_ERROR("Failed to set RPS for idle\n");
 }
 
 void gen6_rps_busy(struct drm_i915_private *dev_priv)
@@ -5035,10 +5048,11 @@ void gen6_rps_busy(struct drm_i915_private *dev_priv)
                gen6_enable_rps_interrupts(dev_priv);
 
                /* Ensure we start at the user's desired frequency */
-               intel_set_rps(dev_priv,
-                             clamp(dev_priv->rps.cur_freq,
-                                   dev_priv->rps.min_freq_softlimit,
-                                   dev_priv->rps.max_freq_softlimit));
+               if (intel_set_rps(dev_priv,
+                                 clamp(dev_priv->rps.cur_freq,
+                                       dev_priv->rps.min_freq_softlimit,
+                                       dev_priv->rps.max_freq_softlimit)))
+                       DRM_DEBUG_DRIVER("Failed to set idle frequency\n");
        }
        mutex_unlock(&dev_priv->rps.hw_lock);
 }
@@ -5106,12 +5120,16 @@ void gen6_rps_boost(struct drm_i915_private *dev_priv,
        spin_unlock(&dev_priv->rps.client_lock);
 }
 
-void intel_set_rps(struct drm_i915_private *dev_priv, u8 val)
+int intel_set_rps(struct drm_i915_private *dev_priv, u8 val)
 {
+       int err;
+
        if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
-               valleyview_set_rps(dev_priv, val);
+               err = valleyview_set_rps(dev_priv, val);
        else
-               gen6_set_rps(dev_priv, val);
+               err = gen6_set_rps(dev_priv, val);
+
+       return err;
 }
 
 static void gen9_disable_rc6(struct drm_i915_private *dev_priv)
@@ -5315,7 +5333,7 @@ static void gen6_init_rps_frequencies(struct drm_i915_private *dev_priv)
 }
 
 static void reset_rps(struct drm_i915_private *dev_priv,
-                     void (*set)(struct drm_i915_private *, u8))
+                     int (*set)(struct drm_i915_private *, u8))
 {
        u8 freq = dev_priv->rps.cur_freq;
 
@@ -5323,7 +5341,8 @@ static void reset_rps(struct drm_i915_private *dev_priv,
        dev_priv->rps.power = -1;
        dev_priv->rps.cur_freq = -1;
 
-       set(dev_priv, freq);
+       if (set(dev_priv, freq))
+               DRM_ERROR("Failed to reset RPS to initial values\n");
 }
 
 /* See the Gen9_GT_PM_Programming_Guide doc for the below */
index 1a840bf92eeac888f2baadae0ef257b8d3f8bdb0..d3d49a09c919a3d372599127a9b8774a0b7767a5 100644 (file)
@@ -93,14 +93,18 @@ u32 vlv_punit_read(struct drm_i915_private *dev_priv, u32 addr)
        return val;
 }
 
-void vlv_punit_write(struct drm_i915_private *dev_priv, u32 addr, u32 val)
+int vlv_punit_write(struct drm_i915_private *dev_priv, u32 addr, u32 val)
 {
+       int err;
+
        WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock));
 
        mutex_lock(&dev_priv->sb_lock);
-       vlv_sideband_rw(dev_priv, PCI_DEVFN(0, 0), IOSF_PORT_PUNIT,
-                       SB_CRWRDA_NP, addr, &val);
+       err = vlv_sideband_rw(dev_priv, PCI_DEVFN(0, 0), IOSF_PORT_PUNIT,
+                             SB_CRWRDA_NP, addr, &val);
        mutex_unlock(&dev_priv->sb_lock);
+
+       return err;
 }
 
 u32 vlv_bunit_read(struct drm_i915_private *dev_priv, u32 reg)