Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: MIT
0002 /*
0003  * Copyright © 2019 Intel Corporation
0004  */
0005 
0006 #include <linux/sort.h>
0007 
0008 #include "intel_engine_regs.h"
0009 #include "intel_gt_clock_utils.h"
0010 
0011 #include "selftest_llc.h"
0012 #include "selftest_rc6.h"
0013 #include "selftest_rps.h"
0014 
0015 static int cmp_u64(const void *A, const void *B)
0016 {
0017     const u64 *a = A, *b = B;
0018 
0019     if (a < b)
0020         return -1;
0021     else if (a > b)
0022         return 1;
0023     else
0024         return 0;
0025 }
0026 
0027 static int cmp_u32(const void *A, const void *B)
0028 {
0029     const u32 *a = A, *b = B;
0030 
0031     if (a < b)
0032         return -1;
0033     else if (a > b)
0034         return 1;
0035     else
0036         return 0;
0037 }
0038 
0039 static void measure_clocks(struct intel_engine_cs *engine,
0040                u32 *out_cycles, ktime_t *out_dt)
0041 {
0042     ktime_t dt[5];
0043     u32 cycles[5];
0044     int i;
0045 
0046     for (i = 0; i < 5; i++) {
0047         local_irq_disable();
0048         cycles[i] = -ENGINE_READ_FW(engine, RING_TIMESTAMP);
0049         dt[i] = ktime_get();
0050 
0051         udelay(1000);
0052 
0053         dt[i] = ktime_sub(ktime_get(), dt[i]);
0054         cycles[i] += ENGINE_READ_FW(engine, RING_TIMESTAMP);
0055         local_irq_enable();
0056     }
0057 
0058     /* Use the median of both cycle/dt; close enough */
0059     sort(cycles, 5, sizeof(*cycles), cmp_u32, NULL);
0060     *out_cycles = (cycles[1] + 2 * cycles[2] + cycles[3]) / 4;
0061 
0062     sort(dt, 5, sizeof(*dt), cmp_u64, NULL);
0063     *out_dt = div_u64(dt[1] + 2 * dt[2] + dt[3], 4);
0064 }
0065 
0066 static int live_gt_clocks(void *arg)
0067 {
0068     struct intel_gt *gt = arg;
0069     struct intel_engine_cs *engine;
0070     enum intel_engine_id id;
0071     int err = 0;
0072 
0073     if (!gt->clock_frequency) { /* unknown */
0074         pr_info("CS_TIMESTAMP frequency unknown\n");
0075         return 0;
0076     }
0077 
0078     if (GRAPHICS_VER(gt->i915) < 4) /* Any CS_TIMESTAMP? */
0079         return 0;
0080 
0081     if (GRAPHICS_VER(gt->i915) == 5)
0082         /*
0083          * XXX CS_TIMESTAMP low dword is dysfunctional?
0084          *
0085          * Ville's experiments indicate the high dword still works,
0086          * but at a correspondingly reduced frequency.
0087          */
0088         return 0;
0089 
0090     if (GRAPHICS_VER(gt->i915) == 4)
0091         /*
0092          * XXX CS_TIMESTAMP appears gibberish
0093          *
0094          * Ville's experiments indicate that it mostly appears 'stuck'
0095          * in that we see the register report the same cycle count
0096          * for a couple of reads.
0097          */
0098         return 0;
0099 
0100     intel_gt_pm_get(gt);
0101     intel_uncore_forcewake_get(gt->uncore, FORCEWAKE_ALL);
0102 
0103     for_each_engine(engine, gt, id) {
0104         u32 cycles;
0105         u32 expected;
0106         u64 time;
0107         u64 dt;
0108 
0109         if (GRAPHICS_VER(engine->i915) < 7 && engine->id != RCS0)
0110             continue;
0111 
0112         measure_clocks(engine, &cycles, &dt);
0113 
0114         time = intel_gt_clock_interval_to_ns(engine->gt, cycles);
0115         expected = intel_gt_ns_to_clock_interval(engine->gt, dt);
0116 
0117         pr_info("%s: TIMESTAMP %d cycles [%lldns] in %lldns [%d cycles], using CS clock frequency of %uKHz\n",
0118             engine->name, cycles, time, dt, expected,
0119             engine->gt->clock_frequency / 1000);
0120 
0121         if (9 * time < 8 * dt || 8 * time > 9 * dt) {
0122             pr_err("%s: CS ticks did not match walltime!\n",
0123                    engine->name);
0124             err = -EINVAL;
0125             break;
0126         }
0127 
0128         if (9 * expected < 8 * cycles || 8 * expected > 9 * cycles) {
0129             pr_err("%s: walltime did not match CS ticks!\n",
0130                    engine->name);
0131             err = -EINVAL;
0132             break;
0133         }
0134     }
0135 
0136     intel_uncore_forcewake_put(gt->uncore, FORCEWAKE_ALL);
0137     intel_gt_pm_put(gt);
0138 
0139     return err;
0140 }
0141 
0142 static int live_gt_resume(void *arg)
0143 {
0144     struct intel_gt *gt = arg;
0145     IGT_TIMEOUT(end_time);
0146     int err;
0147 
0148     /* Do several suspend/resume cycles to check we don't explode! */
0149     do {
0150         intel_gt_suspend_prepare(gt);
0151         intel_gt_suspend_late(gt);
0152 
0153         if (gt->rc6.enabled) {
0154             pr_err("rc6 still enabled after suspend!\n");
0155             intel_gt_set_wedged_on_init(gt);
0156             err = -EINVAL;
0157             break;
0158         }
0159 
0160         err = intel_gt_resume(gt);
0161         if (err)
0162             break;
0163 
0164         if (gt->rc6.supported && !gt->rc6.enabled) {
0165             pr_err("rc6 not enabled upon resume!\n");
0166             intel_gt_set_wedged_on_init(gt);
0167             err = -EINVAL;
0168             break;
0169         }
0170 
0171         err = st_llc_verify(&gt->llc);
0172         if (err) {
0173             pr_err("llc state not restored upon resume!\n");
0174             intel_gt_set_wedged_on_init(gt);
0175             break;
0176         }
0177     } while (!__igt_timeout(end_time, NULL));
0178 
0179     return err;
0180 }
0181 
0182 int intel_gt_pm_live_selftests(struct drm_i915_private *i915)
0183 {
0184     static const struct i915_subtest tests[] = {
0185         SUBTEST(live_gt_clocks),
0186         SUBTEST(live_rc6_manual),
0187         SUBTEST(live_rps_clock_interval),
0188         SUBTEST(live_rps_control),
0189         SUBTEST(live_rps_frequency_cs),
0190         SUBTEST(live_rps_frequency_srm),
0191         SUBTEST(live_rps_power),
0192         SUBTEST(live_rps_interrupt),
0193         SUBTEST(live_rps_dynamic),
0194         SUBTEST(live_gt_resume),
0195     };
0196 
0197     if (intel_gt_is_wedged(to_gt(i915)))
0198         return 0;
0199 
0200     return intel_gt_live_subtests(tests, to_gt(i915));
0201 }
0202 
0203 int intel_gt_pm_late_selftests(struct drm_i915_private *i915)
0204 {
0205     static const struct i915_subtest tests[] = {
0206         /*
0207          * These tests may leave the system in an undesirable state.
0208          * They are intended to be run last in CI and the system
0209          * rebooted afterwards.
0210          */
0211         SUBTEST(live_rc6_ctx_wa),
0212     };
0213 
0214     if (intel_gt_is_wedged(to_gt(i915)))
0215         return 0;
0216 
0217     return intel_gt_live_subtests(tests, to_gt(i915));
0218 }