Skip to content

Commit 9c87855

Browse files
committed
drm/i915/gt: Use the RPM config register to determine clk frequencies
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 <[email protected]> Cc: Andi Shyti <[email protected]> Cc: Mika Kuoppala <[email protected]> Reviewed-by: Andi Shyti <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/[email protected]
1 parent 555a322 commit 9c87855

File tree

11 files changed

+229
-75
lines changed

11 files changed

+229
-75
lines changed

drivers/gpu/drm/i915/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ gt-y += \
9191
gt/intel_ggtt.o \
9292
gt/intel_ggtt_fencing.o \
9393
gt/intel_gt.o \
94+
gt/intel_gt_clock_utils.o \
9495
gt/intel_gt_irq.o \
9596
gt/intel_gt_pm.o \
9697
gt/intel_gt_pm_irq.o \

drivers/gpu/drm/i915/gt/debugfs_gt_pm.c

Lines changed: 39 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include "debugfs_gt_pm.h"
1111
#include "i915_drv.h"
1212
#include "intel_gt.h"
13+
#include "intel_gt_clock_utils.h"
1314
#include "intel_llc.h"
1415
#include "intel_rc6.h"
1516
#include "intel_rps.h"
@@ -268,7 +269,7 @@ static int frequency_show(struct seq_file *m, void *unused)
268269
yesno(rpmodectl & GEN6_RP_ENABLE));
269270
seq_printf(m, "SW control enabled: %s\n",
270271
yesno((rpmodectl & GEN6_RP_MEDIA_MODE_MASK) ==
271-
GEN6_RP_MEDIA_SW_MODE));
272+
GEN6_RP_MEDIA_SW_MODE));
272273

273274
vlv_punit_get(i915);
274275
freq_sts = vlv_punit_read(i915, PUNIT_REG_GPU_FREQ_STS);
@@ -300,8 +301,9 @@ static int frequency_show(struct seq_file *m, void *unused)
300301
u32 rp_state_cap;
301302
u32 rpmodectl, rpinclimit, rpdeclimit;
302303
u32 rpstat, cagf, reqf;
303-
u32 rpupei, rpcurup, rpprevup;
304-
u32 rpdownei, rpcurdown, rpprevdown;
304+
u32 rpcurupei, rpcurup, rpprevup;
305+
u32 rpcurdownei, rpcurdown, rpprevdown;
306+
u32 rpupei, rpupt, rpdownei, rpdownt;
305307
u32 pm_ier, pm_imr, pm_isr, pm_iir, pm_mask;
306308
int max_freq;
307309

@@ -337,9 +339,16 @@ static int frequency_show(struct seq_file *m, void *unused)
337339
rpupei = intel_uncore_read(uncore, GEN6_RP_CUR_UP_EI) & GEN6_CURICONT_MASK;
338340
rpcurup = intel_uncore_read(uncore, GEN6_RP_CUR_UP) & GEN6_CURBSYTAVG_MASK;
339341
rpprevup = intel_uncore_read(uncore, GEN6_RP_PREV_UP) & GEN6_CURBSYTAVG_MASK;
340-
rpdownei = intel_uncore_read(uncore, GEN6_RP_CUR_DOWN_EI) & GEN6_CURIAVG_MASK;
342+
rpcurdownei = intel_uncore_read(uncore, GEN6_RP_CUR_DOWN_EI) & GEN6_CURIAVG_MASK;
341343
rpcurdown = intel_uncore_read(uncore, GEN6_RP_CUR_DOWN) & GEN6_CURBSYTAVG_MASK;
342344
rpprevdown = intel_uncore_read(uncore, GEN6_RP_PREV_DOWN) & GEN6_CURBSYTAVG_MASK;
345+
346+
rpupei = intel_uncore_read(uncore, GEN6_RP_UP_EI);
347+
rpupt = intel_uncore_read(uncore, GEN6_RP_UP_THRESHOLD);
348+
349+
rpdownei = intel_uncore_read(uncore, GEN6_RP_DOWN_EI);
350+
rpdownt = intel_uncore_read(uncore, GEN6_RP_DOWN_THRESHOLD);
351+
343352
cagf = intel_rps_read_actual_frequency(rps);
344353

345354
intel_uncore_forcewake_put(uncore, FORCEWAKE_ALL);
@@ -372,7 +381,7 @@ static int frequency_show(struct seq_file *m, void *unused)
372381
yesno(rpmodectl & GEN6_RP_ENABLE));
373382
seq_printf(m, "SW control enabled: %s\n",
374383
yesno((rpmodectl & GEN6_RP_MEDIA_MODE_MASK) ==
375-
GEN6_RP_MEDIA_SW_MODE));
384+
GEN6_RP_MEDIA_SW_MODE));
376385

377386
seq_printf(m, "PM IER=0x%08x IMR=0x%08x, MASK=0x%08x\n",
378387
pm_ier, pm_imr, pm_mask);
@@ -394,23 +403,35 @@ static int frequency_show(struct seq_file *m, void *unused)
394403
seq_printf(m, "RPDECLIMIT: 0x%08x\n", rpdeclimit);
395404
seq_printf(m, "RPNSWREQ: %dMHz\n", reqf);
396405
seq_printf(m, "CAGF: %dMHz\n", cagf);
397-
seq_printf(m, "RP CUR UP EI: %d (%dus)\n",
398-
rpupei, GT_PM_INTERVAL_TO_US(i915, rpupei));
399-
seq_printf(m, "RP CUR UP: %d (%dus)\n",
400-
rpcurup, GT_PM_INTERVAL_TO_US(i915, rpcurup));
401-
seq_printf(m, "RP PREV UP: %d (%dus)\n",
402-
rpprevup, GT_PM_INTERVAL_TO_US(i915, rpprevup));
406+
seq_printf(m, "RP CUR UP EI: %d (%dns)\n",
407+
rpcurupei,
408+
intel_gt_pm_interval_to_ns(gt, rpcurupei));
409+
seq_printf(m, "RP CUR UP: %d (%dns)\n",
410+
rpcurup, intel_gt_pm_interval_to_ns(gt, rpcurup));
411+
seq_printf(m, "RP PREV UP: %d (%dns)\n",
412+
rpprevup, intel_gt_pm_interval_to_ns(gt, rpprevup));
403413
seq_printf(m, "Up threshold: %d%%\n",
404414
rps->power.up_threshold);
405-
406-
seq_printf(m, "RP CUR DOWN EI: %d (%dus)\n",
407-
rpdownei, GT_PM_INTERVAL_TO_US(i915, rpdownei));
408-
seq_printf(m, "RP CUR DOWN: %d (%dus)\n",
409-
rpcurdown, GT_PM_INTERVAL_TO_US(i915, rpcurdown));
410-
seq_printf(m, "RP PREV DOWN: %d (%dus)\n",
411-
rpprevdown, GT_PM_INTERVAL_TO_US(i915, rpprevdown));
415+
seq_printf(m, "RP UP EI: %d (%dns)\n",
416+
rpupei, intel_gt_pm_interval_to_ns(gt, rpupei));
417+
seq_printf(m, "RP UP THRESHOLD: %d (%dns)\n",
418+
rpupt, intel_gt_pm_interval_to_ns(gt, rpupt));
419+
420+
seq_printf(m, "RP CUR DOWN EI: %d (%dns)\n",
421+
rpcurdownei,
422+
intel_gt_pm_interval_to_ns(gt, rpcurdownei));
423+
seq_printf(m, "RP CUR DOWN: %d (%dns)\n",
424+
rpcurdown,
425+
intel_gt_pm_interval_to_ns(gt, rpcurdown));
426+
seq_printf(m, "RP PREV DOWN: %d (%dns)\n",
427+
rpprevdown,
428+
intel_gt_pm_interval_to_ns(gt, rpprevdown));
412429
seq_printf(m, "Down threshold: %d%%\n",
413430
rps->power.down_threshold);
431+
seq_printf(m, "RP DOWN EI: %d (%dns)\n",
432+
rpdownei, intel_gt_pm_interval_to_ns(gt, rpdownei));
433+
seq_printf(m, "RP DOWN THRESHOLD: %d (%dns)\n",
434+
rpdownt, intel_gt_pm_interval_to_ns(gt, rpdownt));
414435

415436
max_freq = (IS_GEN9_LP(i915) ? rp_state_cap >> 0 :
416437
rp_state_cap >> 16) & 0xff;

drivers/gpu/drm/i915/gt/intel_gt.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include "i915_drv.h"
88
#include "intel_context.h"
99
#include "intel_gt.h"
10+
#include "intel_gt_clock_utils.h"
1011
#include "intel_gt_pm.h"
1112
#include "intel_gt_requests.h"
1213
#include "intel_mocs.h"
@@ -576,6 +577,8 @@ int intel_gt_init(struct intel_gt *gt)
576577
*/
577578
intel_uncore_forcewake_get(gt->uncore, FORCEWAKE_ALL);
578579

580+
intel_gt_init_clock_frequency(gt);
581+
579582
err = intel_gt_init_scratch(gt, IS_GEN(gt->i915, 2) ? SZ_256K : SZ_4K);
580583
if (err)
581584
goto out_fw;
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
// SPDX-License-Identifier: MIT
2+
/*
3+
* Copyright © 2020 Intel Corporation
4+
*/
5+
6+
#include "i915_drv.h"
7+
#include "intel_gt.h"
8+
#include "intel_gt_clock_utils.h"
9+
10+
#define MHZ_19_2 19200000 /* 19.2MHz, 52.083ns */
11+
#define MHZ_24 24000000 /* 24MHz, 83.333ns */
12+
#define MHZ_25 25000000 /* 25MHz, 80ns */
13+
14+
static u32 read_clock_frequency(const struct intel_gt *gt)
15+
{
16+
if (INTEL_GEN(gt->i915) >= 11) {
17+
u32 config;
18+
19+
config = intel_uncore_read(gt->uncore, RPM_CONFIG0);
20+
config &= GEN11_RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_MASK;
21+
config >>= GEN11_RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_SHIFT;
22+
23+
switch (config) {
24+
case 0: return MHZ_24;
25+
case 1:
26+
case 2: return MHZ_19_2;
27+
default:
28+
case 3: return MHZ_25;
29+
}
30+
} else if (INTEL_GEN(gt->i915) >= 9) {
31+
if (IS_GEN9_LP(gt->i915))
32+
return MHZ_19_2;
33+
else
34+
return MHZ_24;
35+
} else {
36+
return MHZ_25;
37+
}
38+
}
39+
40+
void intel_gt_init_clock_frequency(struct intel_gt *gt)
41+
{
42+
/*
43+
* Note that on gen11+, the clock frequency may be reconfigured.
44+
* We do not, and we assume nobody else does.
45+
*/
46+
gt->clock_frequency = read_clock_frequency(gt);
47+
GT_TRACE(gt,
48+
"Using clock frequency: %dkHz\n",
49+
gt->clock_frequency / 1000);
50+
}
51+
52+
#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM)
53+
void intel_gt_check_clock_frequency(const struct intel_gt *gt)
54+
{
55+
if (gt->clock_frequency != read_clock_frequency(gt)) {
56+
dev_err(gt->i915->drm.dev,
57+
"GT clock frequency changed, was %uHz, now %uHz!\n",
58+
gt->clock_frequency,
59+
read_clock_frequency(gt));
60+
}
61+
}
62+
#endif
63+
64+
static u64 div_u64_roundup(u64 nom, u32 den)
65+
{
66+
return div_u64(nom + den - 1, den);
67+
}
68+
69+
u32 intel_gt_clock_interval_to_ns(const struct intel_gt *gt, u32 count)
70+
{
71+
return div_u64_roundup(mul_u32_u32(count, 1000 * 1000 * 1000),
72+
gt->clock_frequency);
73+
}
74+
75+
u32 intel_gt_pm_interval_to_ns(const struct intel_gt *gt, u32 count)
76+
{
77+
return intel_gt_clock_interval_to_ns(gt, 16 * count);
78+
}
79+
80+
u32 intel_gt_ns_to_clock_interval(const struct intel_gt *gt, u32 ns)
81+
{
82+
return div_u64_roundup(mul_u32_u32(gt->clock_frequency, ns),
83+
1000 * 1000 * 1000);
84+
}
85+
86+
u32 intel_gt_ns_to_pm_interval(const struct intel_gt *gt, u32 ns)
87+
{
88+
u32 val;
89+
90+
/*
91+
* Make these a multiple of magic 25 to avoid SNB (eg. Dell XPS
92+
* 8300) freezing up around GPU hangs. Looks as if even
93+
* scheduling/timer interrupts start misbehaving if the RPS
94+
* EI/thresholds are "bad", leading to a very sluggish or even
95+
* frozen machine.
96+
*/
97+
val = DIV_ROUND_UP(intel_gt_ns_to_clock_interval(gt, ns), 16);
98+
if (IS_GEN(gt->i915, 6))
99+
val = roundup(val, 25);
100+
101+
return val;
102+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/* SPDX-License-Identifier: MIT */
2+
/*
3+
* Copyright © 2020 Intel Corporation
4+
*/
5+
6+
#ifndef __INTEL_GT_CLOCK_UTILS_H__
7+
#define __INTEL_GT_CLOCK_UTILS_H__
8+
9+
#include <linux/types.h>
10+
11+
struct intel_gt;
12+
13+
void intel_gt_init_clock_frequency(struct intel_gt *gt);
14+
15+
#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM)
16+
void intel_gt_check_clock_frequency(const struct intel_gt *gt);
17+
#else
18+
static inline void intel_gt_check_clock_frequency(const struct intel_gt *gt) {}
19+
#endif
20+
21+
u32 intel_gt_clock_interval_to_ns(const struct intel_gt *gt, u32 count);
22+
u32 intel_gt_pm_interval_to_ns(const struct intel_gt *gt, u32 count);
23+
24+
u32 intel_gt_ns_to_clock_interval(const struct intel_gt *gt, u32 ns);
25+
u32 intel_gt_ns_to_pm_interval(const struct intel_gt *gt, u32 ns);
26+
27+
#endif /* __INTEL_GT_CLOCK_UTILS_H__ */

drivers/gpu/drm/i915/gt/intel_gt_pm.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include "intel_context.h"
1313
#include "intel_engine_pm.h"
1414
#include "intel_gt.h"
15+
#include "intel_gt_clock_utils.h"
1516
#include "intel_gt_pm.h"
1617
#include "intel_gt_requests.h"
1718
#include "intel_llc.h"
@@ -138,6 +139,8 @@ static void gt_sanitize(struct intel_gt *gt, bool force)
138139
wakeref = intel_runtime_pm_get(gt->uncore->rpm);
139140
intel_uncore_forcewake_get(gt->uncore, FORCEWAKE_ALL);
140141

142+
intel_gt_check_clock_frequency(gt);
143+
141144
/*
142145
* As we have just resumed the machine and woken the device up from
143146
* deep PCI sleep (presumably D3_cold), assume the HW has been reset

drivers/gpu/drm/i915/gt/intel_gt_types.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ struct intel_gt {
6161
struct list_head closed_vma;
6262
spinlock_t closed_lock; /* guards the list of closed_vma */
6363

64+
ktime_t last_init_time;
6465
struct intel_reset reset;
6566

6667
/**
@@ -72,14 +73,12 @@ struct intel_gt {
7273
*/
7374
intel_wakeref_t awake;
7475

76+
u32 clock_frequency;
77+
7578
struct intel_llc llc;
7679
struct intel_rc6 rc6;
7780
struct intel_rps rps;
7881

79-
ktime_t last_init_time;
80-
81-
struct i915_vma *scratch;
82-
8382
spinlock_t irq_lock;
8483
u32 gt_imr;
8584
u32 pm_ier;
@@ -97,6 +96,8 @@ struct intel_gt {
9796
* Reserved for exclusive use by the kernel.
9897
*/
9998
struct i915_address_space *vm;
99+
100+
struct i915_vma *scratch;
100101
};
101102

102103
enum intel_gt_scratch_field {

0 commit comments

Comments
 (0)