Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/i915/gt: Fix up clock frequency

The bspec lists both the clock frequency and the effective interval. The
interval corresponds to observed behaviour, so adjust the frequency to
match.

v2: Mika rightfully asked if we could measure the clock frequency from a
selftest.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Acked-by: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20200427154554.12736-1-chris@chris-wilson.co.uk

+147 -6
+6 -6
drivers/gpu/drm/i915/gt/intel_gt_clock_utils.c
··· 7 7 #include "intel_gt.h" 8 8 #include "intel_gt_clock_utils.h" 9 9 10 + #define MHZ_12 12000000 /* 12MHz (24MHz/2), 83.333ns */ 11 + #define MHZ_12_5 12500000 /* 12.5MHz (25MHz/2), 80ns */ 10 12 #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 13 14 14 static u32 read_clock_frequency(const struct intel_gt *gt) 15 15 { ··· 21 21 config >>= GEN11_RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_SHIFT; 22 22 23 23 switch (config) { 24 - case 0: return MHZ_24; 24 + case 0: return MHZ_12; 25 25 case 1: 26 26 case 2: return MHZ_19_2; 27 27 default: 28 - case 3: return MHZ_25; 28 + case 3: return MHZ_12_5; 29 29 } 30 30 } else if (INTEL_GEN(gt->i915) >= 9) { 31 31 if (IS_GEN9_LP(gt->i915)) 32 32 return MHZ_19_2; 33 33 else 34 - return MHZ_24; 34 + return MHZ_12; 35 35 } else { 36 - return MHZ_25; 36 + return MHZ_12_5; 37 37 } 38 38 } 39 39
+1
drivers/gpu/drm/i915/gt/selftest_gt_pm.c
··· 53 53 { 54 54 static const struct i915_subtest tests[] = { 55 55 SUBTEST(live_rc6_manual), 56 + SUBTEST(live_rps_clock_interval), 56 57 SUBTEST(live_rps_control), 57 58 SUBTEST(live_rps_frequency_cs), 58 59 SUBTEST(live_rps_frequency_srm),
+139
drivers/gpu/drm/i915/gt/selftest_rps.c
··· 208 208 } 209 209 } 210 210 211 + int live_rps_clock_interval(void *arg) 212 + { 213 + struct intel_gt *gt = arg; 214 + struct intel_rps *rps = &gt->rps; 215 + void (*saved_work)(struct work_struct *wrk); 216 + struct intel_engine_cs *engine; 217 + enum intel_engine_id id; 218 + struct igt_spinner spin; 219 + int err = 0; 220 + 221 + if (!rps->enabled) 222 + return 0; 223 + 224 + if (igt_spinner_init(&spin, gt)) 225 + return -ENOMEM; 226 + 227 + intel_gt_pm_wait_for_idle(gt); 228 + saved_work = rps->work.func; 229 + rps->work.func = dummy_rps_work; 230 + 231 + intel_gt_pm_get(gt); 232 + intel_rps_disable(&gt->rps); 233 + 234 + intel_gt_check_clock_frequency(gt); 235 + 236 + for_each_engine(engine, gt, id) { 237 + unsigned long saved_heartbeat; 238 + struct i915_request *rq; 239 + ktime_t dt; 240 + u32 cycles; 241 + 242 + if (!intel_engine_can_store_dword(engine)) 243 + continue; 244 + 245 + saved_heartbeat = engine_heartbeat_disable(engine); 246 + 247 + rq = igt_spinner_create_request(&spin, 248 + engine->kernel_context, 249 + MI_NOOP); 250 + if (IS_ERR(rq)) { 251 + engine_heartbeat_enable(engine, saved_heartbeat); 252 + err = PTR_ERR(rq); 253 + break; 254 + } 255 + 256 + i915_request_add(rq); 257 + 258 + if (!igt_wait_for_spinner(&spin, rq)) { 259 + pr_err("%s: RPS spinner did not start\n", 260 + engine->name); 261 + igt_spinner_end(&spin); 262 + engine_heartbeat_enable(engine, saved_heartbeat); 263 + intel_gt_set_wedged(engine->gt); 264 + err = -EIO; 265 + break; 266 + } 267 + 268 + intel_uncore_forcewake_get(gt->uncore, FORCEWAKE_ALL); 269 + 270 + intel_uncore_write_fw(gt->uncore, GEN6_RP_CUR_UP_EI, 0); 271 + 272 + /* Set the evaluation interval to infinity! */ 273 + intel_uncore_write_fw(gt->uncore, 274 + GEN6_RP_UP_EI, 0xffffffff); 275 + intel_uncore_write_fw(gt->uncore, 276 + GEN6_RP_UP_THRESHOLD, 0xffffffff); 277 + 278 + intel_uncore_write_fw(gt->uncore, GEN6_RP_CONTROL, 279 + GEN6_RP_ENABLE | GEN6_RP_UP_BUSY_AVG); 280 + 281 + if (wait_for(intel_uncore_read_fw(gt->uncore, 282 + GEN6_RP_CUR_UP_EI), 283 + 10)) { 284 + /* Just skip the test; assume lack of HW support */ 285 + pr_notice("%s: rps evalution interval not ticking\n", 286 + engine->name); 287 + err = -ENODEV; 288 + } else { 289 + preempt_disable(); 290 + dt = ktime_get(); 291 + cycles = -intel_uncore_read_fw(gt->uncore, 292 + GEN6_RP_CUR_UP_EI); 293 + udelay(1000); 294 + dt = ktime_sub(ktime_get(), dt); 295 + cycles += intel_uncore_read_fw(gt->uncore, 296 + GEN6_RP_CUR_UP_EI); 297 + preempt_enable(); 298 + } 299 + 300 + intel_uncore_write_fw(gt->uncore, GEN6_RP_CONTROL, 0); 301 + intel_uncore_forcewake_put(gt->uncore, FORCEWAKE_ALL); 302 + 303 + igt_spinner_end(&spin); 304 + engine_heartbeat_enable(engine, saved_heartbeat); 305 + 306 + if (err == 0) { 307 + u64 time = intel_gt_pm_interval_to_ns(gt, cycles); 308 + u32 expected = 309 + intel_gt_ns_to_pm_interval(gt, ktime_to_ns(dt)); 310 + 311 + pr_info("%s: rps counted %d C0 cycles [%lldns] in %lldns [%d cycles], using GT clock frequency of %uKHz\n", 312 + engine->name, cycles, time, ktime_to_ns(dt), expected, 313 + gt->clock_frequency / 1000); 314 + 315 + if (10 * time < 9 * ktime_to_ns(dt) || 316 + 10 * time > 11 * ktime_to_ns(dt)) { 317 + pr_err("%s: rps clock time does not match walltime!\n", 318 + engine->name); 319 + err = -EINVAL; 320 + } 321 + 322 + if (10 * expected < 9 * cycles || 323 + 10 * expected > 11 * cycles) { 324 + pr_err("%s: walltime does not match rps clock ticks!\n", 325 + engine->name); 326 + err = -EINVAL; 327 + } 328 + } 329 + 330 + if (igt_flush_test(gt->i915)) 331 + err = -EIO; 332 + 333 + break; /* once is enough */ 334 + } 335 + 336 + intel_rps_enable(&gt->rps); 337 + intel_gt_pm_put(gt); 338 + 339 + igt_spinner_fini(&spin); 340 + 341 + intel_gt_pm_wait_for_idle(gt); 342 + rps->work.func = saved_work; 343 + 344 + if (err == -ENODEV) /* skipped, don't report a fail */ 345 + err = 0; 346 + 347 + return err; 348 + } 349 + 211 350 int live_rps_control(void *arg) 212 351 { 213 352 struct intel_gt *gt = arg;
+1
drivers/gpu/drm/i915/gt/selftest_rps.h
··· 7 7 #define SELFTEST_RPS_H 8 8 9 9 int live_rps_control(void *arg); 10 + int live_rps_clock_interval(void *arg); 10 11 int live_rps_frequency_cs(void *arg); 11 12 int live_rps_frequency_srm(void *arg); 12 13 int live_rps_power(void *arg);