For many configuration details within RC6 and RPS we are programming
intervals for the internal clocks. From gen11, these clocks are
configuration via the RPM_CONFIG and so for convenience, we would like
to convert to/from more natural units (ns).

Signed-off-by: Chris Wilson <ch...@chris-wilson.co.uk>
Cc: Andi Shyti <andi.sh...@intel.com>
Cc: Mika Kuoppala <mika.kuopp...@linux.intel.com>
---
 drivers/gpu/drm/i915/Makefile           |  1 +
 drivers/gpu/drm/i915/gt/debugfs_gt_pm.c | 27 +++++----
 drivers/gpu/drm/i915/gt/intel_gt_clk.c  | 78 +++++++++++++++++++++++++
 drivers/gpu/drm/i915/gt/intel_gt_clk.h  | 21 +++++++
 drivers/gpu/drm/i915/gt/intel_rps.c     | 37 +++++++-----
 drivers/gpu/drm/i915/gt/selftest_rps.c  |  7 ++-
 drivers/gpu/drm/i915/i915_debugfs.c     | 34 +++++++----
 drivers/gpu/drm/i915/i915_reg.h         | 25 --------
 8 files changed, 164 insertions(+), 66 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/gt/intel_gt_clk.c
 create mode 100644 drivers/gpu/drm/i915/gt/intel_gt_clk.h

diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index 44c506b7e117..fa8d78e40dad 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -91,6 +91,7 @@ gt-y += \
        gt/intel_ggtt.o \
        gt/intel_ggtt_fencing.o \
        gt/intel_gt.o \
+       gt/intel_gt_clk.o \
        gt/intel_gt_irq.o \
        gt/intel_gt_pm.o \
        gt/intel_gt_pm_irq.o \
diff --git a/drivers/gpu/drm/i915/gt/debugfs_gt_pm.c 
b/drivers/gpu/drm/i915/gt/debugfs_gt_pm.c
index aab30d908072..cd466472599f 100644
--- a/drivers/gpu/drm/i915/gt/debugfs_gt_pm.c
+++ b/drivers/gpu/drm/i915/gt/debugfs_gt_pm.c
@@ -10,6 +10,7 @@
 #include "debugfs_gt_pm.h"
 #include "i915_drv.h"
 #include "intel_gt.h"
+#include "intel_gt_clk.h"
 #include "intel_llc.h"
 #include "intel_rc6.h"
 #include "intel_rps.h"
@@ -394,21 +395,23 @@ static int frequency_show(struct seq_file *m, void 
*unused)
                seq_printf(m, "RPDECLIMIT: 0x%08x\n", rpdeclimit);
                seq_printf(m, "RPNSWREQ: %dMHz\n", reqf);
                seq_printf(m, "CAGF: %dMHz\n", cagf);
-               seq_printf(m, "RP CUR UP EI: %d (%dus)\n",
-                          rpupei, GT_PM_INTERVAL_TO_US(i915, rpupei));
-               seq_printf(m, "RP CUR UP: %d (%dus)\n",
-                          rpcurup, GT_PM_INTERVAL_TO_US(i915, rpcurup));
-               seq_printf(m, "RP PREV UP: %d (%dus)\n",
-                          rpprevup, GT_PM_INTERVAL_TO_US(i915, rpprevup));
+               seq_printf(m, "RP CUR UP EI: %d (%dns)\n",
+                          rpupei, intel_gt_pm_interval_to_ns(gt, rpupei));
+               seq_printf(m, "RP CUR UP: %d (%dns)\n",
+                          rpcurup, intel_gt_pm_interval_to_ns(gt, rpcurup));
+               seq_printf(m, "RP PREV UP: %d (%dns)\n",
+                          rpprevup, intel_gt_pm_interval_to_ns(gt, rpprevup));
                seq_printf(m, "Up threshold: %d%%\n",
                           rps->power.up_threshold);
 
-               seq_printf(m, "RP CUR DOWN EI: %d (%dus)\n",
-                          rpdownei, GT_PM_INTERVAL_TO_US(i915, rpdownei));
-               seq_printf(m, "RP CUR DOWN: %d (%dus)\n",
-                          rpcurdown, GT_PM_INTERVAL_TO_US(i915, rpcurdown));
-               seq_printf(m, "RP PREV DOWN: %d (%dus)\n",
-                          rpprevdown, GT_PM_INTERVAL_TO_US(i915, rpprevdown));
+               seq_printf(m, "RP CUR DOWN EI: %d (%dns)\n",
+                          rpdownei, intel_gt_pm_interval_to_ns(gt, rpdownei));
+               seq_printf(m, "RP CUR DOWN: %d (%dns)\n",
+                          rpcurdown,
+                          intel_gt_pm_interval_to_ns(gt, rpcurdown));
+               seq_printf(m, "RP PREV DOWN: %d (%dns)\n",
+                          rpprevdown,
+                          intel_gt_pm_interval_to_ns(gt, rpprevdown));
                seq_printf(m, "Down threshold: %d%%\n",
                           rps->power.down_threshold);
 
diff --git a/drivers/gpu/drm/i915/gt/intel_gt_clk.c 
b/drivers/gpu/drm/i915/gt/intel_gt_clk.c
new file mode 100644
index 000000000000..7cc3145a63ed
--- /dev/null
+++ b/drivers/gpu/drm/i915/gt/intel_gt_clk.c
@@ -0,0 +1,78 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2020 Intel Corporation
+ */
+
+#include "i915_drv.h"
+#include "intel_gt.h"
+#include "intel_gt_clk.h"
+
+#define MHZ_19_2 19200000 /* 19.2MHz, 52.083ns */
+#define MHZ_24 24000000 /* 24MHz, 83.333ns */
+#define MHZ_25 25000000 /* 25MHz, 80ns */
+
+u32 intel_gt_clk_frequency(struct intel_gt *gt)
+{
+       if (INTEL_GEN(gt->i915) >= 11) {
+               u32 config;
+
+               config = intel_uncore_read(gt->uncore, RPM_CONFIG0);
+               config &= GEN11_RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_MASK;
+               config >>= GEN11_RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_SHIFT;
+
+               switch (config) {
+               case 0: return MHZ_24;
+               case 1:
+               case 2: return MHZ_19_2;
+               default:
+               case 3: return MHZ_25;
+               }
+       } else if (INTEL_GEN(gt->i915) >= 9) {
+               if (IS_GEN9_LP(gt->i915))
+                       return MHZ_19_2;
+               else
+                       return MHZ_24;
+       } else {
+               return MHZ_25;
+       }
+}
+
+static u64 div_u64_roundup(u64 nom, u32 den)
+{
+       return div_u64(nom + den - 1, den);
+}
+
+u32 intel_gt_clk_interval_to_ns(struct intel_gt *gt, u32 count)
+{
+       return div_u64_roundup(mul_u32_u32(count, 1000 * 1000 * 1000),
+                              intel_gt_clk_frequency(gt));
+}
+
+u32 intel_gt_pm_interval_to_ns(struct intel_gt *gt, u32 count)
+{
+       return intel_gt_clk_interval_to_ns(gt, 16 * count);
+}
+
+u32 intel_gt_ns_to_clk_interval(struct intel_gt *gt, u32 ns)
+{
+       return div_u64_roundup(mul_u32_u32(intel_gt_clk_frequency(gt), ns),
+                              1000 * 1000 * 1000);
+}
+
+u32 intel_gt_ns_to_pm_interval(struct intel_gt *gt, u32 ns)
+{
+       u32 val;
+
+       /*
+        * Make these a multiple of magic 25 to avoid SNB (eg. Dell XPS
+        * 8300) freezing up around GPU hangs. Looks as if even
+        * scheduling/timer interrupts start misbehaving if the RPS
+        * EI/thresholds are "bad", leading to a very sluggish or even
+        * frozen machine.
+        */
+       val = DIV_ROUND_UP(intel_gt_ns_to_clk_interval(gt, ns), 16);
+       if (IS_GEN(gt->i915, 6))
+               val = roundup(val, 25);
+
+       return val;
+}
diff --git a/drivers/gpu/drm/i915/gt/intel_gt_clk.h 
b/drivers/gpu/drm/i915/gt/intel_gt_clk.h
new file mode 100644
index 000000000000..35452cb0893d
--- /dev/null
+++ b/drivers/gpu/drm/i915/gt/intel_gt_clk.h
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2020 Intel Corporation
+ */
+
+#ifndef __INTEL_GT_CLK__
+#define __INTEL_GT_CLK__
+
+#include <linux/types.h>
+
+struct intel_gt;
+
+u32 intel_gt_clk_frequency(struct intel_gt *gt);
+
+u32 intel_gt_clk_interval_to_ns(struct intel_gt *gt, u32 count);
+u32 intel_gt_pm_interval_to_ns(struct intel_gt *gt, u32 count);
+
+u32 intel_gt_ns_to_clk_interval(struct intel_gt *gt, u32 ns);
+u32 intel_gt_ns_to_pm_interval(struct intel_gt *gt, u32 ns);
+
+#endif /* __INTEL_GT_CLK__ */
diff --git a/drivers/gpu/drm/i915/gt/intel_rps.c 
b/drivers/gpu/drm/i915/gt/intel_rps.c
index f008d4dcbc7a..51dca16e5326 100644
--- a/drivers/gpu/drm/i915/gt/intel_rps.c
+++ b/drivers/gpu/drm/i915/gt/intel_rps.c
@@ -8,6 +8,7 @@
 
 #include "i915_drv.h"
 #include "intel_gt.h"
+#include "intel_gt_clk.h"
 #include "intel_gt_irq.h"
 #include "intel_gt_pm_irq.h"
 #include "intel_rps.h"
@@ -535,8 +536,8 @@ static u32 rps_limits(struct intel_rps *rps, u8 val)
 
 static void rps_set_power(struct intel_rps *rps, int new_power)
 {
-       struct intel_uncore *uncore = rps_to_uncore(rps);
-       struct drm_i915_private *i915 = rps_to_i915(rps);
+       struct intel_gt *gt = rps_to_gt(rps);
+       struct intel_uncore *uncore = gt->uncore;
        u32 threshold_up = 0, threshold_down = 0; /* in % */
        u32 ei_up = 0, ei_down = 0;
 
@@ -581,23 +582,25 @@ static void rps_set_power(struct intel_rps *rps, int 
new_power)
        /* When byt can survive without system hang with dynamic
         * sw freq adjustments, this restriction can be lifted.
         */
-       if (IS_VALLEYVIEW(i915))
+       if (IS_VALLEYVIEW(gt->i915))
                goto skip_hw_write;
 
-       GT_TRACE(rps_to_gt(rps),
+       GT_TRACE(gt,
                 "changing power mode [%d], up %d%% @ %dus, down %d%% @ %dus\n",
                 new_power, threshold_up, ei_up, threshold_down, ei_down);
 
-       set(uncore, GEN6_RP_UP_EI, GT_INTERVAL_FROM_US(i915, ei_up));
+       set(uncore, GEN6_RP_UP_EI,
+           intel_gt_ns_to_pm_interval(gt, ei_up * 1000));
        set(uncore, GEN6_RP_UP_THRESHOLD,
-           GT_INTERVAL_FROM_US(i915, ei_up * threshold_up / 100));
+           intel_gt_ns_to_pm_interval(gt, ei_up * threshold_up * 1000 / 100));
 
-       set(uncore, GEN6_RP_DOWN_EI, GT_INTERVAL_FROM_US(i915, ei_down));
+       set(uncore, GEN6_RP_DOWN_EI,
+           intel_gt_ns_to_pm_interval(gt, ei_down * 1000));
        set(uncore, GEN6_RP_DOWN_THRESHOLD,
-           GT_INTERVAL_FROM_US(i915, ei_down * threshold_down / 100));
+           intel_gt_ns_to_pm_interval(gt, ei_down * threshold_down * 1000 / 
100));
 
        set(uncore, GEN6_RP_CONTROL,
-           (INTEL_GEN(i915) > 9 ? 0 : GEN6_RP_MEDIA_TURBO) |
+           (INTEL_GEN(gt->i915) > 9 ? 0 : GEN6_RP_MEDIA_TURBO) |
            GEN6_RP_MEDIA_HW_NORMAL_MODE |
            GEN6_RP_MEDIA_IS_GFX |
            GEN6_RP_ENABLE |
@@ -934,17 +937,17 @@ static bool rps_reset(struct intel_rps *rps)
 /* See the Gen9_GT_PM_Programming_Guide doc for the below */
 static bool gen9_rps_enable(struct intel_rps *rps)
 {
-       struct drm_i915_private *i915 = rps_to_i915(rps);
-       struct intel_uncore *uncore = rps_to_uncore(rps);
+       struct intel_gt *gt = rps_to_gt(rps);
+       struct intel_uncore *uncore = gt->uncore;
 
        /* Program defaults and thresholds for RPS */
-       if (IS_GEN(i915, 9))
+       if (IS_GEN(gt->i915, 9))
                intel_uncore_write_fw(uncore, GEN6_RC_VIDEO_FREQ,
                                      GEN9_FREQUENCY(rps->rp1_freq));
 
        /* 1 second timeout */
        intel_uncore_write_fw(uncore, GEN6_RP_DOWN_TIMEOUT,
-                             GT_INTERVAL_FROM_US(i915, 1000000));
+                             intel_gt_ns_to_pm_interval(gt, 1000000));
 
        intel_uncore_write_fw(uncore, GEN6_RP_IDLE_HYSTERSIS, 0xa);
 
@@ -1224,6 +1227,10 @@ void intel_rps_enable(struct intel_rps *rps)
        if (!HAS_RPS(i915))
                return;
 
+       GT_TRACE(rps_to_gt(rps),
+                "Using clk frequency: %dkHz\n",
+                intel_gt_clk_frequency(rps_to_gt(rps)) / 1000);
+
        intel_uncore_forcewake_get(uncore, FORCEWAKE_ALL);
        if (IS_CHERRYVIEW(i915))
                rps->enabled = chv_rps_enable(rps);
@@ -1760,7 +1767,7 @@ static u32 read_cagf(struct intel_rps *rps)
                freq = vlv_punit_read(i915, PUNIT_REG_GPU_FREQ_STS);
                vlv_punit_put(i915);
        } else {
-               freq = intel_uncore_read(rps_to_gt(rps)->uncore, GEN6_RPSTAT1);
+               freq = intel_uncore_read(rps_to_uncore(rps), GEN6_RPSTAT1);
        }
 
        return intel_rps_get_cagf(rps, freq);
@@ -1768,7 +1775,7 @@ static u32 read_cagf(struct intel_rps *rps)
 
 u32 intel_rps_read_actual_frequency(struct intel_rps *rps)
 {
-       struct intel_runtime_pm *rpm = rps_to_gt(rps)->uncore->rpm;
+       struct intel_runtime_pm *rpm = rps_to_uncore(rps)->rpm;
        intel_wakeref_t wakeref;
        u32 freq = 0;
 
diff --git a/drivers/gpu/drm/i915/gt/selftest_rps.c 
b/drivers/gpu/drm/i915/gt/selftest_rps.c
index 26aadc2ae3be..5ad5bee6bdba 100644
--- a/drivers/gpu/drm/i915/gt/selftest_rps.c
+++ b/drivers/gpu/drm/i915/gt/selftest_rps.c
@@ -4,6 +4,7 @@
  */
 
 #include "intel_engine_pm.h"
+#include "intel_gt_clk.h"
 #include "intel_gt_pm.h"
 #include "intel_rc6.h"
 #include "selftest_rps.h"
@@ -69,7 +70,8 @@ static int __rps_up_interrupt(struct intel_rps *rps,
        }
 
        timeout = intel_uncore_read(uncore, GEN6_RP_UP_EI);
-       timeout = GT_PM_INTERVAL_TO_US(engine->i915, timeout);
+       timeout = intel_gt_pm_interval_to_ns(engine->gt, timeout);
+       timeout /= 1000;
 
        usleep_range(2 * timeout, 3 * timeout);
        GEM_BUG_ON(i915_request_completed(rq));
@@ -120,7 +122,8 @@ static int __rps_down_interrupt(struct intel_rps *rps,
        }
 
        timeout = intel_uncore_read(uncore, GEN6_RP_DOWN_EI);
-       timeout = GT_PM_INTERVAL_TO_US(engine->i915, timeout);
+       timeout = intel_gt_pm_interval_to_ns(engine->gt, timeout);
+       timeout /= 1000;
 
        /* Flush any previous EI */
        usleep_range(timeout, 2 * timeout);
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c 
b/drivers/gpu/drm/i915/i915_debugfs.c
index aa35a59f1c7d..4b3d065100a0 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -32,6 +32,7 @@
 #include <drm/drm_debugfs.h>
 
 #include "gem/i915_gem_context.h"
+#include "gt/intel_gt_clk.h"
 #include "gt/intel_gt_pm.h"
 #include "gt/intel_gt_requests.h"
 #include "gt/intel_reset.h"
@@ -926,21 +927,30 @@ static int i915_frequency_info(struct seq_file *m, void 
*unused)
                seq_printf(m, "RPDECLIMIT: 0x%08x\n", rpdeclimit);
                seq_printf(m, "RPNSWREQ: %dMHz\n", reqf);
                seq_printf(m, "CAGF: %dMHz\n", cagf);
-               seq_printf(m, "RP CUR UP EI: %d (%dus)\n",
-                          rpupei, GT_PM_INTERVAL_TO_US(dev_priv, rpupei));
-               seq_printf(m, "RP CUR UP: %d (%dus)\n",
-                          rpcurup, GT_PM_INTERVAL_TO_US(dev_priv, rpcurup));
-               seq_printf(m, "RP PREV UP: %d (%dus)\n",
-                          rpprevup, GT_PM_INTERVAL_TO_US(dev_priv, rpprevup));
+               seq_printf(m, "RP CUR UP EI: %d (%dns)\n",
+                          rpupei,
+                          intel_gt_pm_interval_to_ns(&dev_priv->gt, rpupei));
+               seq_printf(m, "RP CUR UP: %d (%dun)\n",
+                          rpcurup,
+                          intel_gt_pm_interval_to_ns(&dev_priv->gt, rpcurup));
+               seq_printf(m, "RP PREV UP: %d (%dns)\n",
+                          rpprevup,
+                          intel_gt_pm_interval_to_ns(&dev_priv->gt, rpprevup));
                seq_printf(m, "Up threshold: %d%%\n",
                           rps->power.up_threshold);
 
-               seq_printf(m, "RP CUR DOWN EI: %d (%dus)\n",
-                          rpdownei, GT_PM_INTERVAL_TO_US(dev_priv, rpdownei));
-               seq_printf(m, "RP CUR DOWN: %d (%dus)\n",
-                          rpcurdown, GT_PM_INTERVAL_TO_US(dev_priv, 
rpcurdown));
-               seq_printf(m, "RP PREV DOWN: %d (%dus)\n",
-                          rpprevdown, GT_PM_INTERVAL_TO_US(dev_priv, 
rpprevdown));
+               seq_printf(m, "RP CUR DOWN EI: %d (%dns)\n",
+                          rpdownei,
+                          intel_gt_pm_interval_to_ns(&dev_priv->gt,
+                                                     rpdownei));
+               seq_printf(m, "RP CUR DOWN: %d (%dns)\n",
+                          rpcurdown,
+                          intel_gt_pm_interval_to_ns(&dev_priv->gt,
+                                                     rpcurdown));
+               seq_printf(m, "RP PREV DOWN: %d (%dns)\n",
+                          rpprevdown,
+                          intel_gt_pm_interval_to_ns(&dev_priv->gt,
+                                                     rpprevdown));
                seq_printf(m, "Down threshold: %d%%\n",
                           rps->power.down_threshold);
 
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index edda3f29c8aa..ce28278f4e79 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -4014,31 +4014,6 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg)
 #define GEN6_RP_STATE_CAP      _MMIO(MCHBAR_MIRROR_BASE_SNB + 0x5998)
 #define BXT_RP_STATE_CAP        _MMIO(0x138170)
 
-/*
- * Make these a multiple of magic 25 to avoid SNB (eg. Dell XPS
- * 8300) freezing up around GPU hangs. Looks as if even
- * scheduling/timer interrupts start misbehaving if the RPS
- * EI/thresholds are "bad", leading to a very sluggish or even
- * frozen machine.
- */
-#define INTERVAL_1_28_US(us)   roundup(((us) * 100) >> 7, 25)
-#define INTERVAL_1_33_US(us)   (((us) * 3)   >> 2)
-#define INTERVAL_0_833_US(us)  (((us) * 6) / 5)
-#define GT_INTERVAL_FROM_US(dev_priv, us) (INTEL_GEN(dev_priv) >= 9 ? \
-                               (IS_GEN9_LP(dev_priv) ? \
-                               INTERVAL_0_833_US(us) : \
-                               INTERVAL_1_33_US(us)) : \
-                               INTERVAL_1_28_US(us))
-
-#define INTERVAL_1_28_TO_US(interval)  (((interval) << 7) / 100)
-#define INTERVAL_1_33_TO_US(interval)  (((interval) << 2) / 3)
-#define INTERVAL_0_833_TO_US(interval) (((interval) * 5)  / 6)
-#define GT_PM_INTERVAL_TO_US(dev_priv, interval) (INTEL_GEN(dev_priv) >= 9 ? \
-                           (IS_GEN9_LP(dev_priv) ? \
-                           INTERVAL_0_833_TO_US(interval) : \
-                           INTERVAL_1_33_TO_US(interval)) : \
-                           INTERVAL_1_28_TO_US(interval))
-
 /*
  * Logical Context regs
  */
-- 
2.20.1

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to