124f90d66SChris Wilson // SPDX-License-Identifier: GPL-2.0
2112ed2d3SChris Wilson /*
3112ed2d3SChris Wilson  * Copyright © 2018 Intel Corporation
4112ed2d3SChris Wilson  */
5112ed2d3SChris Wilson 
63c7a44bbSChris Wilson #include <linux/sort.h>
73c7a44bbSChris Wilson 
845233ab2SChris Wilson #include "intel_gpu_commands.h"
93c7a44bbSChris Wilson #include "intel_gt_pm.h"
103c7a44bbSChris Wilson #include "intel_rps.h"
113c7a44bbSChris Wilson 
123c7a44bbSChris Wilson #include "i915_selftest.h"
133c7a44bbSChris Wilson #include "selftests/igt_flush_test.h"
143c7a44bbSChris Wilson 
153c7a44bbSChris Wilson #define COUNT 5
163c7a44bbSChris Wilson 
cmp_u32(const void * A,const void * B)173c7a44bbSChris Wilson static int cmp_u32(const void *A, const void *B)
183c7a44bbSChris Wilson {
193c7a44bbSChris Wilson 	const u32 *a = A, *b = B;
203c7a44bbSChris Wilson 
213c7a44bbSChris Wilson 	return *a - *b;
223c7a44bbSChris Wilson }
233c7a44bbSChris Wilson 
perf_begin(struct intel_gt * gt)243c7a44bbSChris Wilson static void perf_begin(struct intel_gt *gt)
253c7a44bbSChris Wilson {
263c7a44bbSChris Wilson 	intel_gt_pm_get(gt);
273c7a44bbSChris Wilson 
283c7a44bbSChris Wilson 	/* Boost gpufreq to max [waitboost] and keep it fixed */
293c7a44bbSChris Wilson 	atomic_inc(&gt->rps.num_waiters);
303c7a44bbSChris Wilson 	queue_work(gt->i915->unordered_wq, &gt->rps.work);
313c7a44bbSChris Wilson 	flush_work(&gt->rps.work);
323c7a44bbSChris Wilson }
333c7a44bbSChris Wilson 
perf_end(struct intel_gt * gt)343c7a44bbSChris Wilson static int perf_end(struct intel_gt *gt)
353c7a44bbSChris Wilson {
363c7a44bbSChris Wilson 	atomic_dec(&gt->rps.num_waiters);
373c7a44bbSChris Wilson 	intel_gt_pm_put(gt);
383c7a44bbSChris Wilson 
393c7a44bbSChris Wilson 	return igt_flush_test(gt->i915);
403c7a44bbSChris Wilson }
413c7a44bbSChris Wilson 
timestamp_reg(struct intel_engine_cs * engine)421086af67SVille Syrjälä static i915_reg_t timestamp_reg(struct intel_engine_cs *engine)
431086af67SVille Syrjälä {
441086af67SVille Syrjälä 	struct drm_i915_private *i915 = engine->i915;
451086af67SVille Syrjälä 
461086af67SVille Syrjälä 	if (GRAPHICS_VER(i915) == 5 || IS_G4X(i915))
471086af67SVille Syrjälä 		return RING_TIMESTAMP_UDW(engine->mmio_base);
481086af67SVille Syrjälä 	else
491086af67SVille Syrjälä 		return RING_TIMESTAMP(engine->mmio_base);
501086af67SVille Syrjälä }
511086af67SVille Syrjälä 
write_timestamp(struct i915_request * rq,int slot)523c7a44bbSChris Wilson static int write_timestamp(struct i915_request *rq, int slot)
533c7a44bbSChris Wilson {
5412ca695dSMaarten Lankhorst 	struct intel_timeline *tl =
5512ca695dSMaarten Lankhorst 		rcu_dereference_protected(rq->timeline,
5612ca695dSMaarten Lankhorst 					  !i915_request_signaled(rq));
573c7a44bbSChris Wilson 	u32 cmd;
583c7a44bbSChris Wilson 	u32 *cs;
593c7a44bbSChris Wilson 
603c7a44bbSChris Wilson 	cs = intel_ring_begin(rq, 4);
613c7a44bbSChris Wilson 	if (IS_ERR(cs))
623c7a44bbSChris Wilson 		return PTR_ERR(cs);
633c7a44bbSChris Wilson 
643c7a44bbSChris Wilson 	cmd = MI_STORE_REGISTER_MEM | MI_USE_GGTT;
65*d3f23ab9SAndrzej Hajda 	if (GRAPHICS_VER(rq->i915) >= 8)
663c7a44bbSChris Wilson 		cmd++;
673c7a44bbSChris Wilson 	*cs++ = cmd;
681086af67SVille Syrjälä 	*cs++ = i915_mmio_reg_offset(timestamp_reg(rq->engine));
6912ca695dSMaarten Lankhorst 	*cs++ = tl->hwsp_offset + slot * sizeof(u32);
703c7a44bbSChris Wilson 	*cs++ = 0;
713c7a44bbSChris Wilson 
723c7a44bbSChris Wilson 	intel_ring_advance(rq, cs);
733c7a44bbSChris Wilson 
743c7a44bbSChris Wilson 	return 0;
753c7a44bbSChris Wilson }
763c7a44bbSChris Wilson 
create_empty_batch(struct intel_context * ce)773c7a44bbSChris Wilson static struct i915_vma *create_empty_batch(struct intel_context *ce)
783c7a44bbSChris Wilson {
793c7a44bbSChris Wilson 	struct drm_i915_gem_object *obj;
803c7a44bbSChris Wilson 	struct i915_vma *vma;
813c7a44bbSChris Wilson 	u32 *cs;
823c7a44bbSChris Wilson 	int err;
833c7a44bbSChris Wilson 
843c7a44bbSChris Wilson 	obj = i915_gem_object_create_internal(ce->engine->i915, PAGE_SIZE);
853c7a44bbSChris Wilson 	if (IS_ERR(obj))
863c7a44bbSChris Wilson 		return ERR_CAST(obj);
873c7a44bbSChris Wilson 
88b91e1b11SMaarten Lankhorst 	cs = i915_gem_object_pin_map_unlocked(obj, I915_MAP_WB);
893c7a44bbSChris Wilson 	if (IS_ERR(cs)) {
903c7a44bbSChris Wilson 		err = PTR_ERR(cs);
913c7a44bbSChris Wilson 		goto err_put;
923c7a44bbSChris Wilson 	}
933c7a44bbSChris Wilson 
943c7a44bbSChris Wilson 	cs[0] = MI_BATCH_BUFFER_END;
953c7a44bbSChris Wilson 
963c7a44bbSChris Wilson 	i915_gem_object_flush_map(obj);
973c7a44bbSChris Wilson 
983c7a44bbSChris Wilson 	vma = i915_vma_instance(obj, ce->vm, NULL);
993c7a44bbSChris Wilson 	if (IS_ERR(vma)) {
1003c7a44bbSChris Wilson 		err = PTR_ERR(vma);
1013c7a44bbSChris Wilson 		goto err_unpin;
1023c7a44bbSChris Wilson 	}
1033c7a44bbSChris Wilson 
1043c7a44bbSChris Wilson 	err = i915_vma_pin(vma, 0, 0, PIN_USER);
1053c7a44bbSChris Wilson 	if (err)
1063c7a44bbSChris Wilson 		goto err_unpin;
1073c7a44bbSChris Wilson 
1083c7a44bbSChris Wilson 	i915_gem_object_unpin_map(obj);
1093c7a44bbSChris Wilson 	return vma;
1103c7a44bbSChris Wilson 
1113c7a44bbSChris Wilson err_unpin:
1123c7a44bbSChris Wilson 	i915_gem_object_unpin_map(obj);
1133c7a44bbSChris Wilson err_put:
1143c7a44bbSChris Wilson 	i915_gem_object_put(obj);
1153c7a44bbSChris Wilson 	return ERR_PTR(err);
1163c7a44bbSChris Wilson }
1173c7a44bbSChris Wilson 
trifilter(u32 * a)1183c7a44bbSChris Wilson static u32 trifilter(u32 *a)
1193c7a44bbSChris Wilson {
1203c7a44bbSChris Wilson 	u64 sum;
1213c7a44bbSChris Wilson 
1223c7a44bbSChris Wilson 	sort(a, COUNT, sizeof(*a), cmp_u32, NULL);
1233c7a44bbSChris Wilson 
1241805ec67SColin Ian King 	sum = mul_u32_u32(a[2], 2);
1253c7a44bbSChris Wilson 	sum += a[1];
1263c7a44bbSChris Wilson 	sum += a[3];
1273c7a44bbSChris Wilson 
1283c7a44bbSChris Wilson 	return sum >> 2;
1293c7a44bbSChris Wilson }
1303c7a44bbSChris Wilson 
perf_mi_bb_start(void * arg)1313c7a44bbSChris Wilson static int perf_mi_bb_start(void *arg)
1323c7a44bbSChris Wilson {
1333c7a44bbSChris Wilson 	struct intel_gt *gt = arg;
1343c7a44bbSChris Wilson 	struct intel_engine_cs *engine;
1353c7a44bbSChris Wilson 	enum intel_engine_id id;
1363c7a44bbSChris Wilson 	int err = 0;
1373c7a44bbSChris Wilson 
1381086af67SVille Syrjälä 	if (GRAPHICS_VER(gt->i915) < 4) /* Any CS_TIMESTAMP? */
1393c7a44bbSChris Wilson 		return 0;
1403c7a44bbSChris Wilson 
1413c7a44bbSChris Wilson 	perf_begin(gt);
1423c7a44bbSChris Wilson 	for_each_engine(engine, gt, id) {
1433c7a44bbSChris Wilson 		struct intel_context *ce = engine->kernel_context;
1443c7a44bbSChris Wilson 		struct i915_vma *batch;
1453c7a44bbSChris Wilson 		u32 cycles[COUNT];
1463c7a44bbSChris Wilson 		int i;
1473c7a44bbSChris Wilson 
148cf8a82deSVille Syrjälä 		if (GRAPHICS_VER(engine->i915) < 7 && engine->id != RCS0)
149cf8a82deSVille Syrjälä 			continue;
150cf8a82deSVille Syrjälä 
151de5825beSChris Wilson 		intel_engine_pm_get(engine);
152de5825beSChris Wilson 
1533c7a44bbSChris Wilson 		batch = create_empty_batch(ce);
1543c7a44bbSChris Wilson 		if (IS_ERR(batch)) {
1553c7a44bbSChris Wilson 			err = PTR_ERR(batch);
156de5825beSChris Wilson 			intel_engine_pm_put(engine);
1573c7a44bbSChris Wilson 			break;
1583c7a44bbSChris Wilson 		}
1593c7a44bbSChris Wilson 
1603c7a44bbSChris Wilson 		err = i915_vma_sync(batch);
1613c7a44bbSChris Wilson 		if (err) {
162de5825beSChris Wilson 			intel_engine_pm_put(engine);
1633c7a44bbSChris Wilson 			i915_vma_put(batch);
1643c7a44bbSChris Wilson 			break;
1653c7a44bbSChris Wilson 		}
1663c7a44bbSChris Wilson 
1673c7a44bbSChris Wilson 		for (i = 0; i < ARRAY_SIZE(cycles); i++) {
1683c7a44bbSChris Wilson 			struct i915_request *rq;
1693c7a44bbSChris Wilson 
1703c7a44bbSChris Wilson 			rq = i915_request_create(ce);
1713c7a44bbSChris Wilson 			if (IS_ERR(rq)) {
1723c7a44bbSChris Wilson 				err = PTR_ERR(rq);
1733c7a44bbSChris Wilson 				break;
1743c7a44bbSChris Wilson 			}
1753c7a44bbSChris Wilson 
1763c7a44bbSChris Wilson 			err = write_timestamp(rq, 2);
1773c7a44bbSChris Wilson 			if (err)
1783c7a44bbSChris Wilson 				goto out;
1793c7a44bbSChris Wilson 
1803c7a44bbSChris Wilson 			err = rq->engine->emit_bb_start(rq,
1818e4ee5e8SChris Wilson 							i915_vma_offset(batch), 8,
1823c7a44bbSChris Wilson 							0);
1833c7a44bbSChris Wilson 			if (err)
1843c7a44bbSChris Wilson 				goto out;
1853c7a44bbSChris Wilson 
1863c7a44bbSChris Wilson 			err = write_timestamp(rq, 3);
1873c7a44bbSChris Wilson 			if (err)
1883c7a44bbSChris Wilson 				goto out;
1893c7a44bbSChris Wilson 
1903c7a44bbSChris Wilson out:
1913c7a44bbSChris Wilson 			i915_request_get(rq);
1923c7a44bbSChris Wilson 			i915_request_add(rq);
1933c7a44bbSChris Wilson 
1943c7a44bbSChris Wilson 			if (i915_request_wait(rq, 0, HZ / 5) < 0)
1953c7a44bbSChris Wilson 				err = -EIO;
1963c7a44bbSChris Wilson 			i915_request_put(rq);
1973c7a44bbSChris Wilson 			if (err)
1983c7a44bbSChris Wilson 				break;
1993c7a44bbSChris Wilson 
2003c7a44bbSChris Wilson 			cycles[i] = rq->hwsp_seqno[3] - rq->hwsp_seqno[2];
2013c7a44bbSChris Wilson 		}
2023c7a44bbSChris Wilson 		i915_vma_put(batch);
203de5825beSChris Wilson 		intel_engine_pm_put(engine);
2043c7a44bbSChris Wilson 		if (err)
2053c7a44bbSChris Wilson 			break;
2063c7a44bbSChris Wilson 
2073c7a44bbSChris Wilson 		pr_info("%s: MI_BB_START cycles: %u\n",
2083c7a44bbSChris Wilson 			engine->name, trifilter(cycles));
2093c7a44bbSChris Wilson 	}
2103c7a44bbSChris Wilson 	if (perf_end(gt))
2113c7a44bbSChris Wilson 		err = -EIO;
2123c7a44bbSChris Wilson 
2133c7a44bbSChris Wilson 	return err;
2143c7a44bbSChris Wilson }
2153c7a44bbSChris Wilson 
create_nop_batch(struct intel_context * ce)2163c7a44bbSChris Wilson static struct i915_vma *create_nop_batch(struct intel_context *ce)
2173c7a44bbSChris Wilson {
2183c7a44bbSChris Wilson 	struct drm_i915_gem_object *obj;
2193c7a44bbSChris Wilson 	struct i915_vma *vma;
2203c7a44bbSChris Wilson 	u32 *cs;
2213c7a44bbSChris Wilson 	int err;
2223c7a44bbSChris Wilson 
2233c7a44bbSChris Wilson 	obj = i915_gem_object_create_internal(ce->engine->i915, SZ_64K);
2243c7a44bbSChris Wilson 	if (IS_ERR(obj))
2253c7a44bbSChris Wilson 		return ERR_CAST(obj);
2263c7a44bbSChris Wilson 
227b91e1b11SMaarten Lankhorst 	cs = i915_gem_object_pin_map_unlocked(obj, I915_MAP_WB);
2283c7a44bbSChris Wilson 	if (IS_ERR(cs)) {
2293c7a44bbSChris Wilson 		err = PTR_ERR(cs);
2303c7a44bbSChris Wilson 		goto err_put;
2313c7a44bbSChris Wilson 	}
2323c7a44bbSChris Wilson 
2333c7a44bbSChris Wilson 	memset(cs, 0, SZ_64K);
2343c7a44bbSChris Wilson 	cs[SZ_64K / sizeof(*cs) - 1] = MI_BATCH_BUFFER_END;
2353c7a44bbSChris Wilson 
2363c7a44bbSChris Wilson 	i915_gem_object_flush_map(obj);
2373c7a44bbSChris Wilson 
2383c7a44bbSChris Wilson 	vma = i915_vma_instance(obj, ce->vm, NULL);
2393c7a44bbSChris Wilson 	if (IS_ERR(vma)) {
2403c7a44bbSChris Wilson 		err = PTR_ERR(vma);
2413c7a44bbSChris Wilson 		goto err_unpin;
2423c7a44bbSChris Wilson 	}
2433c7a44bbSChris Wilson 
2443c7a44bbSChris Wilson 	err = i915_vma_pin(vma, 0, 0, PIN_USER);
2453c7a44bbSChris Wilson 	if (err)
2463c7a44bbSChris Wilson 		goto err_unpin;
2473c7a44bbSChris Wilson 
2483c7a44bbSChris Wilson 	i915_gem_object_unpin_map(obj);
2493c7a44bbSChris Wilson 	return vma;
2503c7a44bbSChris Wilson 
2513c7a44bbSChris Wilson err_unpin:
2523c7a44bbSChris Wilson 	i915_gem_object_unpin_map(obj);
2533c7a44bbSChris Wilson err_put:
2543c7a44bbSChris Wilson 	i915_gem_object_put(obj);
2553c7a44bbSChris Wilson 	return ERR_PTR(err);
2563c7a44bbSChris Wilson }
2573c7a44bbSChris Wilson 
perf_mi_noop(void * arg)2583c7a44bbSChris Wilson static int perf_mi_noop(void *arg)
2593c7a44bbSChris Wilson {
2603c7a44bbSChris Wilson 	struct intel_gt *gt = arg;
2613c7a44bbSChris Wilson 	struct intel_engine_cs *engine;
2623c7a44bbSChris Wilson 	enum intel_engine_id id;
2633c7a44bbSChris Wilson 	int err = 0;
2643c7a44bbSChris Wilson 
2651086af67SVille Syrjälä 	if (GRAPHICS_VER(gt->i915) < 4) /* Any CS_TIMESTAMP? */
2663c7a44bbSChris Wilson 		return 0;
2673c7a44bbSChris Wilson 
2683c7a44bbSChris Wilson 	perf_begin(gt);
2693c7a44bbSChris Wilson 	for_each_engine(engine, gt, id) {
2703c7a44bbSChris Wilson 		struct intel_context *ce = engine->kernel_context;
2713c7a44bbSChris Wilson 		struct i915_vma *base, *nop;
2723c7a44bbSChris Wilson 		u32 cycles[COUNT];
2733c7a44bbSChris Wilson 		int i;
2743c7a44bbSChris Wilson 
275cf8a82deSVille Syrjälä 		if (GRAPHICS_VER(engine->i915) < 7 && engine->id != RCS0)
276cf8a82deSVille Syrjälä 			continue;
277cf8a82deSVille Syrjälä 
278de5825beSChris Wilson 		intel_engine_pm_get(engine);
279de5825beSChris Wilson 
2803c7a44bbSChris Wilson 		base = create_empty_batch(ce);
2813c7a44bbSChris Wilson 		if (IS_ERR(base)) {
2823c7a44bbSChris Wilson 			err = PTR_ERR(base);
283de5825beSChris Wilson 			intel_engine_pm_put(engine);
2843c7a44bbSChris Wilson 			break;
2853c7a44bbSChris Wilson 		}
2863c7a44bbSChris Wilson 
2873c7a44bbSChris Wilson 		err = i915_vma_sync(base);
2883c7a44bbSChris Wilson 		if (err) {
2893c7a44bbSChris Wilson 			i915_vma_put(base);
290de5825beSChris Wilson 			intel_engine_pm_put(engine);
2913c7a44bbSChris Wilson 			break;
2923c7a44bbSChris Wilson 		}
2933c7a44bbSChris Wilson 
2943c7a44bbSChris Wilson 		nop = create_nop_batch(ce);
2953c7a44bbSChris Wilson 		if (IS_ERR(nop)) {
2963c7a44bbSChris Wilson 			err = PTR_ERR(nop);
2973c7a44bbSChris Wilson 			i915_vma_put(base);
298de5825beSChris Wilson 			intel_engine_pm_put(engine);
2993c7a44bbSChris Wilson 			break;
3003c7a44bbSChris Wilson 		}
3013c7a44bbSChris Wilson 
3023c7a44bbSChris Wilson 		err = i915_vma_sync(nop);
3033c7a44bbSChris Wilson 		if (err) {
3043c7a44bbSChris Wilson 			i915_vma_put(nop);
3053c7a44bbSChris Wilson 			i915_vma_put(base);
306de5825beSChris Wilson 			intel_engine_pm_put(engine);
3073c7a44bbSChris Wilson 			break;
3083c7a44bbSChris Wilson 		}
3093c7a44bbSChris Wilson 
3103c7a44bbSChris Wilson 		for (i = 0; i < ARRAY_SIZE(cycles); i++) {
3113c7a44bbSChris Wilson 			struct i915_request *rq;
3123c7a44bbSChris Wilson 
3133c7a44bbSChris Wilson 			rq = i915_request_create(ce);
3143c7a44bbSChris Wilson 			if (IS_ERR(rq)) {
3153c7a44bbSChris Wilson 				err = PTR_ERR(rq);
3163c7a44bbSChris Wilson 				break;
3173c7a44bbSChris Wilson 			}
3183c7a44bbSChris Wilson 
3193c7a44bbSChris Wilson 			err = write_timestamp(rq, 2);
3203c7a44bbSChris Wilson 			if (err)
3213c7a44bbSChris Wilson 				goto out;
3223c7a44bbSChris Wilson 
3233c7a44bbSChris Wilson 			err = rq->engine->emit_bb_start(rq,
3248e4ee5e8SChris Wilson 							i915_vma_offset(base), 8,
3253c7a44bbSChris Wilson 							0);
3263c7a44bbSChris Wilson 			if (err)
3273c7a44bbSChris Wilson 				goto out;
3283c7a44bbSChris Wilson 
3293c7a44bbSChris Wilson 			err = write_timestamp(rq, 3);
3303c7a44bbSChris Wilson 			if (err)
3313c7a44bbSChris Wilson 				goto out;
3323c7a44bbSChris Wilson 
3333c7a44bbSChris Wilson 			err = rq->engine->emit_bb_start(rq,
3348e4ee5e8SChris Wilson 							i915_vma_offset(nop),
3358e4ee5e8SChris Wilson 							i915_vma_size(nop),
3363c7a44bbSChris Wilson 							0);
3373c7a44bbSChris Wilson 			if (err)
3383c7a44bbSChris Wilson 				goto out;
3393c7a44bbSChris Wilson 
3403c7a44bbSChris Wilson 			err = write_timestamp(rq, 4);
3413c7a44bbSChris Wilson 			if (err)
3423c7a44bbSChris Wilson 				goto out;
3433c7a44bbSChris Wilson 
3443c7a44bbSChris Wilson out:
3453c7a44bbSChris Wilson 			i915_request_get(rq);
3463c7a44bbSChris Wilson 			i915_request_add(rq);
3473c7a44bbSChris Wilson 
3483c7a44bbSChris Wilson 			if (i915_request_wait(rq, 0, HZ / 5) < 0)
3493c7a44bbSChris Wilson 				err = -EIO;
3503c7a44bbSChris Wilson 			i915_request_put(rq);
3513c7a44bbSChris Wilson 			if (err)
3523c7a44bbSChris Wilson 				break;
3533c7a44bbSChris Wilson 
3543c7a44bbSChris Wilson 			cycles[i] =
3553c7a44bbSChris Wilson 				(rq->hwsp_seqno[4] - rq->hwsp_seqno[3]) -
3563c7a44bbSChris Wilson 				(rq->hwsp_seqno[3] - rq->hwsp_seqno[2]);
3573c7a44bbSChris Wilson 		}
3583c7a44bbSChris Wilson 		i915_vma_put(nop);
3593c7a44bbSChris Wilson 		i915_vma_put(base);
360de5825beSChris Wilson 		intel_engine_pm_put(engine);
3613c7a44bbSChris Wilson 		if (err)
3623c7a44bbSChris Wilson 			break;
3633c7a44bbSChris Wilson 
3643c7a44bbSChris Wilson 		pr_info("%s: 16K MI_NOOP cycles: %u\n",
3653c7a44bbSChris Wilson 			engine->name, trifilter(cycles));
3663c7a44bbSChris Wilson 	}
3673c7a44bbSChris Wilson 	if (perf_end(gt))
3683c7a44bbSChris Wilson 		err = -EIO;
3693c7a44bbSChris Wilson 
3703c7a44bbSChris Wilson 	return err;
3713c7a44bbSChris Wilson }
3723c7a44bbSChris Wilson 
intel_engine_cs_perf_selftests(struct drm_i915_private * i915)3733c7a44bbSChris Wilson int intel_engine_cs_perf_selftests(struct drm_i915_private *i915)
3743c7a44bbSChris Wilson {
3753c7a44bbSChris Wilson 	static const struct i915_subtest tests[] = {
3763c7a44bbSChris Wilson 		SUBTEST(perf_mi_bb_start),
3773c7a44bbSChris Wilson 		SUBTEST(perf_mi_noop),
3783c7a44bbSChris Wilson 	};
3793c7a44bbSChris Wilson 
380c14adcbdSMichał Winiarski 	if (intel_gt_is_wedged(to_gt(i915)))
3813c7a44bbSChris Wilson 		return 0;
3823c7a44bbSChris Wilson 
383c14adcbdSMichał Winiarski 	return intel_gt_live_subtests(tests, to_gt(i915));
3843c7a44bbSChris Wilson }
385112ed2d3SChris Wilson 
intel_mmio_bases_check(void * arg)386112ed2d3SChris Wilson static int intel_mmio_bases_check(void *arg)
387112ed2d3SChris Wilson {
388112ed2d3SChris Wilson 	int i, j;
389112ed2d3SChris Wilson 
390112ed2d3SChris Wilson 	for (i = 0; i < ARRAY_SIZE(intel_engines); i++) {
391112ed2d3SChris Wilson 		const struct engine_info *info = &intel_engines[i];
392112ed2d3SChris Wilson 		u8 prev = U8_MAX;
393112ed2d3SChris Wilson 
394112ed2d3SChris Wilson 		for (j = 0; j < MAX_MMIO_BASES; j++) {
3951b9d8406SLucas De Marchi 			u8 ver = info->mmio_bases[j].graphics_ver;
396112ed2d3SChris Wilson 			u32 base = info->mmio_bases[j].base;
397112ed2d3SChris Wilson 
3981b9d8406SLucas De Marchi 			if (ver >= prev) {
3991b9d8406SLucas De Marchi 				pr_err("%s(%s, class:%d, instance:%d): mmio base for graphics ver %u is before the one for ver %u\n",
4002edda80dSChris Wilson 				       __func__,
4012edda80dSChris Wilson 				       intel_engine_class_repr(info->class),
4022edda80dSChris Wilson 				       info->class, info->instance,
4031b9d8406SLucas De Marchi 				       prev, ver);
404112ed2d3SChris Wilson 				return -EINVAL;
405112ed2d3SChris Wilson 			}
406112ed2d3SChris Wilson 
4071b9d8406SLucas De Marchi 			if (ver == 0)
408112ed2d3SChris Wilson 				break;
409112ed2d3SChris Wilson 
410112ed2d3SChris Wilson 			if (!base) {
4111b9d8406SLucas De Marchi 				pr_err("%s(%s, class:%d, instance:%d): invalid mmio base (%x) for graphics ver %u at entry %u\n",
4122edda80dSChris Wilson 				       __func__,
4132edda80dSChris Wilson 				       intel_engine_class_repr(info->class),
4142edda80dSChris Wilson 				       info->class, info->instance,
4151b9d8406SLucas De Marchi 				       base, ver, j);
416112ed2d3SChris Wilson 				return -EINVAL;
417112ed2d3SChris Wilson 			}
418112ed2d3SChris Wilson 
4191b9d8406SLucas De Marchi 			prev = ver;
420112ed2d3SChris Wilson 		}
421112ed2d3SChris Wilson 
4221b9d8406SLucas De Marchi 		pr_debug("%s: min graphics version supported for %s%d is %u\n",
4232edda80dSChris Wilson 			 __func__,
4242edda80dSChris Wilson 			 intel_engine_class_repr(info->class),
4252edda80dSChris Wilson 			 info->instance,
4262edda80dSChris Wilson 			 prev);
427112ed2d3SChris Wilson 	}
428112ed2d3SChris Wilson 
429112ed2d3SChris Wilson 	return 0;
430112ed2d3SChris Wilson }
431112ed2d3SChris Wilson 
intel_engine_cs_mock_selftests(void)432112ed2d3SChris Wilson int intel_engine_cs_mock_selftests(void)
433112ed2d3SChris Wilson {
434112ed2d3SChris Wilson 	static const struct i915_subtest tests[] = {
435112ed2d3SChris Wilson 		SUBTEST(intel_mmio_bases_check),
436112ed2d3SChris Wilson 	};
437112ed2d3SChris Wilson 
438112ed2d3SChris Wilson 	return i915_subtests(tests, NULL);
439112ed2d3SChris Wilson }
440