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 
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 
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 	schedule_work(&gt->rps.work);
313c7a44bbSChris Wilson 	flush_work(&gt->rps.work);
323c7a44bbSChris Wilson }
333c7a44bbSChris Wilson 
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 
423c7a44bbSChris Wilson static int write_timestamp(struct i915_request *rq, int slot)
433c7a44bbSChris Wilson {
4412ca695dSMaarten Lankhorst 	struct intel_timeline *tl =
4512ca695dSMaarten Lankhorst 		rcu_dereference_protected(rq->timeline,
4612ca695dSMaarten Lankhorst 					  !i915_request_signaled(rq));
473c7a44bbSChris Wilson 	u32 cmd;
483c7a44bbSChris Wilson 	u32 *cs;
493c7a44bbSChris Wilson 
503c7a44bbSChris Wilson 	cs = intel_ring_begin(rq, 4);
513c7a44bbSChris Wilson 	if (IS_ERR(cs))
523c7a44bbSChris Wilson 		return PTR_ERR(cs);
533c7a44bbSChris Wilson 
543c7a44bbSChris Wilson 	cmd = MI_STORE_REGISTER_MEM | MI_USE_GGTT;
555a833995SChris Wilson 	if (INTEL_GEN(rq->engine->i915) >= 8)
563c7a44bbSChris Wilson 		cmd++;
573c7a44bbSChris Wilson 	*cs++ = cmd;
583c7a44bbSChris Wilson 	*cs++ = i915_mmio_reg_offset(RING_TIMESTAMP(rq->engine->mmio_base));
5912ca695dSMaarten Lankhorst 	*cs++ = tl->hwsp_offset + slot * sizeof(u32);
603c7a44bbSChris Wilson 	*cs++ = 0;
613c7a44bbSChris Wilson 
623c7a44bbSChris Wilson 	intel_ring_advance(rq, cs);
633c7a44bbSChris Wilson 
643c7a44bbSChris Wilson 	return 0;
653c7a44bbSChris Wilson }
663c7a44bbSChris Wilson 
673c7a44bbSChris Wilson static struct i915_vma *create_empty_batch(struct intel_context *ce)
683c7a44bbSChris Wilson {
693c7a44bbSChris Wilson 	struct drm_i915_gem_object *obj;
703c7a44bbSChris Wilson 	struct i915_vma *vma;
713c7a44bbSChris Wilson 	u32 *cs;
723c7a44bbSChris Wilson 	int err;
733c7a44bbSChris Wilson 
743c7a44bbSChris Wilson 	obj = i915_gem_object_create_internal(ce->engine->i915, PAGE_SIZE);
753c7a44bbSChris Wilson 	if (IS_ERR(obj))
763c7a44bbSChris Wilson 		return ERR_CAST(obj);
773c7a44bbSChris Wilson 
78b91e1b11SMaarten Lankhorst 	cs = i915_gem_object_pin_map_unlocked(obj, I915_MAP_WB);
793c7a44bbSChris Wilson 	if (IS_ERR(cs)) {
803c7a44bbSChris Wilson 		err = PTR_ERR(cs);
813c7a44bbSChris Wilson 		goto err_put;
823c7a44bbSChris Wilson 	}
833c7a44bbSChris Wilson 
843c7a44bbSChris Wilson 	cs[0] = MI_BATCH_BUFFER_END;
853c7a44bbSChris Wilson 
863c7a44bbSChris Wilson 	i915_gem_object_flush_map(obj);
873c7a44bbSChris Wilson 
883c7a44bbSChris Wilson 	vma = i915_vma_instance(obj, ce->vm, NULL);
893c7a44bbSChris Wilson 	if (IS_ERR(vma)) {
903c7a44bbSChris Wilson 		err = PTR_ERR(vma);
913c7a44bbSChris Wilson 		goto err_unpin;
923c7a44bbSChris Wilson 	}
933c7a44bbSChris Wilson 
943c7a44bbSChris Wilson 	err = i915_vma_pin(vma, 0, 0, PIN_USER);
953c7a44bbSChris Wilson 	if (err)
963c7a44bbSChris Wilson 		goto err_unpin;
973c7a44bbSChris Wilson 
983c7a44bbSChris Wilson 	i915_gem_object_unpin_map(obj);
993c7a44bbSChris Wilson 	return vma;
1003c7a44bbSChris Wilson 
1013c7a44bbSChris Wilson err_unpin:
1023c7a44bbSChris Wilson 	i915_gem_object_unpin_map(obj);
1033c7a44bbSChris Wilson err_put:
1043c7a44bbSChris Wilson 	i915_gem_object_put(obj);
1053c7a44bbSChris Wilson 	return ERR_PTR(err);
1063c7a44bbSChris Wilson }
1073c7a44bbSChris Wilson 
1083c7a44bbSChris Wilson static u32 trifilter(u32 *a)
1093c7a44bbSChris Wilson {
1103c7a44bbSChris Wilson 	u64 sum;
1113c7a44bbSChris Wilson 
1123c7a44bbSChris Wilson 	sort(a, COUNT, sizeof(*a), cmp_u32, NULL);
1133c7a44bbSChris Wilson 
1141805ec67SColin Ian King 	sum = mul_u32_u32(a[2], 2);
1153c7a44bbSChris Wilson 	sum += a[1];
1163c7a44bbSChris Wilson 	sum += a[3];
1173c7a44bbSChris Wilson 
1183c7a44bbSChris Wilson 	return sum >> 2;
1193c7a44bbSChris Wilson }
1203c7a44bbSChris Wilson 
1213c7a44bbSChris Wilson static int perf_mi_bb_start(void *arg)
1223c7a44bbSChris Wilson {
1233c7a44bbSChris Wilson 	struct intel_gt *gt = arg;
1243c7a44bbSChris Wilson 	struct intel_engine_cs *engine;
1253c7a44bbSChris Wilson 	enum intel_engine_id id;
1263c7a44bbSChris Wilson 	int err = 0;
1273c7a44bbSChris Wilson 
1283c7a44bbSChris Wilson 	if (INTEL_GEN(gt->i915) < 7) /* for per-engine CS_TIMESTAMP */
1293c7a44bbSChris Wilson 		return 0;
1303c7a44bbSChris Wilson 
1313c7a44bbSChris Wilson 	perf_begin(gt);
1323c7a44bbSChris Wilson 	for_each_engine(engine, gt, id) {
1333c7a44bbSChris Wilson 		struct intel_context *ce = engine->kernel_context;
1343c7a44bbSChris Wilson 		struct i915_vma *batch;
1353c7a44bbSChris Wilson 		u32 cycles[COUNT];
1363c7a44bbSChris Wilson 		int i;
1373c7a44bbSChris Wilson 
138de5825beSChris Wilson 		intel_engine_pm_get(engine);
139de5825beSChris Wilson 
1403c7a44bbSChris Wilson 		batch = create_empty_batch(ce);
1413c7a44bbSChris Wilson 		if (IS_ERR(batch)) {
1423c7a44bbSChris Wilson 			err = PTR_ERR(batch);
143de5825beSChris Wilson 			intel_engine_pm_put(engine);
1443c7a44bbSChris Wilson 			break;
1453c7a44bbSChris Wilson 		}
1463c7a44bbSChris Wilson 
1473c7a44bbSChris Wilson 		err = i915_vma_sync(batch);
1483c7a44bbSChris Wilson 		if (err) {
149de5825beSChris Wilson 			intel_engine_pm_put(engine);
1503c7a44bbSChris Wilson 			i915_vma_put(batch);
1513c7a44bbSChris Wilson 			break;
1523c7a44bbSChris Wilson 		}
1533c7a44bbSChris Wilson 
1543c7a44bbSChris Wilson 		for (i = 0; i < ARRAY_SIZE(cycles); i++) {
1553c7a44bbSChris Wilson 			struct i915_request *rq;
1563c7a44bbSChris Wilson 
1573c7a44bbSChris Wilson 			rq = i915_request_create(ce);
1583c7a44bbSChris Wilson 			if (IS_ERR(rq)) {
1593c7a44bbSChris Wilson 				err = PTR_ERR(rq);
1603c7a44bbSChris Wilson 				break;
1613c7a44bbSChris Wilson 			}
1623c7a44bbSChris Wilson 
1633c7a44bbSChris Wilson 			err = write_timestamp(rq, 2);
1643c7a44bbSChris Wilson 			if (err)
1653c7a44bbSChris Wilson 				goto out;
1663c7a44bbSChris Wilson 
1673c7a44bbSChris Wilson 			err = rq->engine->emit_bb_start(rq,
1683c7a44bbSChris Wilson 							batch->node.start, 8,
1693c7a44bbSChris Wilson 							0);
1703c7a44bbSChris Wilson 			if (err)
1713c7a44bbSChris Wilson 				goto out;
1723c7a44bbSChris Wilson 
1733c7a44bbSChris Wilson 			err = write_timestamp(rq, 3);
1743c7a44bbSChris Wilson 			if (err)
1753c7a44bbSChris Wilson 				goto out;
1763c7a44bbSChris Wilson 
1773c7a44bbSChris Wilson out:
1783c7a44bbSChris Wilson 			i915_request_get(rq);
1793c7a44bbSChris Wilson 			i915_request_add(rq);
1803c7a44bbSChris Wilson 
1813c7a44bbSChris Wilson 			if (i915_request_wait(rq, 0, HZ / 5) < 0)
1823c7a44bbSChris Wilson 				err = -EIO;
1833c7a44bbSChris Wilson 			i915_request_put(rq);
1843c7a44bbSChris Wilson 			if (err)
1853c7a44bbSChris Wilson 				break;
1863c7a44bbSChris Wilson 
1873c7a44bbSChris Wilson 			cycles[i] = rq->hwsp_seqno[3] - rq->hwsp_seqno[2];
1883c7a44bbSChris Wilson 		}
1893c7a44bbSChris Wilson 		i915_vma_put(batch);
190de5825beSChris Wilson 		intel_engine_pm_put(engine);
1913c7a44bbSChris Wilson 		if (err)
1923c7a44bbSChris Wilson 			break;
1933c7a44bbSChris Wilson 
1943c7a44bbSChris Wilson 		pr_info("%s: MI_BB_START cycles: %u\n",
1953c7a44bbSChris Wilson 			engine->name, trifilter(cycles));
1963c7a44bbSChris Wilson 	}
1973c7a44bbSChris Wilson 	if (perf_end(gt))
1983c7a44bbSChris Wilson 		err = -EIO;
1993c7a44bbSChris Wilson 
2003c7a44bbSChris Wilson 	return err;
2013c7a44bbSChris Wilson }
2023c7a44bbSChris Wilson 
2033c7a44bbSChris Wilson static struct i915_vma *create_nop_batch(struct intel_context *ce)
2043c7a44bbSChris Wilson {
2053c7a44bbSChris Wilson 	struct drm_i915_gem_object *obj;
2063c7a44bbSChris Wilson 	struct i915_vma *vma;
2073c7a44bbSChris Wilson 	u32 *cs;
2083c7a44bbSChris Wilson 	int err;
2093c7a44bbSChris Wilson 
2103c7a44bbSChris Wilson 	obj = i915_gem_object_create_internal(ce->engine->i915, SZ_64K);
2113c7a44bbSChris Wilson 	if (IS_ERR(obj))
2123c7a44bbSChris Wilson 		return ERR_CAST(obj);
2133c7a44bbSChris Wilson 
214b91e1b11SMaarten Lankhorst 	cs = i915_gem_object_pin_map_unlocked(obj, I915_MAP_WB);
2153c7a44bbSChris Wilson 	if (IS_ERR(cs)) {
2163c7a44bbSChris Wilson 		err = PTR_ERR(cs);
2173c7a44bbSChris Wilson 		goto err_put;
2183c7a44bbSChris Wilson 	}
2193c7a44bbSChris Wilson 
2203c7a44bbSChris Wilson 	memset(cs, 0, SZ_64K);
2213c7a44bbSChris Wilson 	cs[SZ_64K / sizeof(*cs) - 1] = MI_BATCH_BUFFER_END;
2223c7a44bbSChris Wilson 
2233c7a44bbSChris Wilson 	i915_gem_object_flush_map(obj);
2243c7a44bbSChris Wilson 
2253c7a44bbSChris Wilson 	vma = i915_vma_instance(obj, ce->vm, NULL);
2263c7a44bbSChris Wilson 	if (IS_ERR(vma)) {
2273c7a44bbSChris Wilson 		err = PTR_ERR(vma);
2283c7a44bbSChris Wilson 		goto err_unpin;
2293c7a44bbSChris Wilson 	}
2303c7a44bbSChris Wilson 
2313c7a44bbSChris Wilson 	err = i915_vma_pin(vma, 0, 0, PIN_USER);
2323c7a44bbSChris Wilson 	if (err)
2333c7a44bbSChris Wilson 		goto err_unpin;
2343c7a44bbSChris Wilson 
2353c7a44bbSChris Wilson 	i915_gem_object_unpin_map(obj);
2363c7a44bbSChris Wilson 	return vma;
2373c7a44bbSChris Wilson 
2383c7a44bbSChris Wilson err_unpin:
2393c7a44bbSChris Wilson 	i915_gem_object_unpin_map(obj);
2403c7a44bbSChris Wilson err_put:
2413c7a44bbSChris Wilson 	i915_gem_object_put(obj);
2423c7a44bbSChris Wilson 	return ERR_PTR(err);
2433c7a44bbSChris Wilson }
2443c7a44bbSChris Wilson 
2453c7a44bbSChris Wilson static int perf_mi_noop(void *arg)
2463c7a44bbSChris Wilson {
2473c7a44bbSChris Wilson 	struct intel_gt *gt = arg;
2483c7a44bbSChris Wilson 	struct intel_engine_cs *engine;
2493c7a44bbSChris Wilson 	enum intel_engine_id id;
2503c7a44bbSChris Wilson 	int err = 0;
2513c7a44bbSChris Wilson 
2523c7a44bbSChris Wilson 	if (INTEL_GEN(gt->i915) < 7) /* for per-engine CS_TIMESTAMP */
2533c7a44bbSChris Wilson 		return 0;
2543c7a44bbSChris Wilson 
2553c7a44bbSChris Wilson 	perf_begin(gt);
2563c7a44bbSChris Wilson 	for_each_engine(engine, gt, id) {
2573c7a44bbSChris Wilson 		struct intel_context *ce = engine->kernel_context;
2583c7a44bbSChris Wilson 		struct i915_vma *base, *nop;
2593c7a44bbSChris Wilson 		u32 cycles[COUNT];
2603c7a44bbSChris Wilson 		int i;
2613c7a44bbSChris Wilson 
262de5825beSChris Wilson 		intel_engine_pm_get(engine);
263de5825beSChris Wilson 
2643c7a44bbSChris Wilson 		base = create_empty_batch(ce);
2653c7a44bbSChris Wilson 		if (IS_ERR(base)) {
2663c7a44bbSChris Wilson 			err = PTR_ERR(base);
267de5825beSChris Wilson 			intel_engine_pm_put(engine);
2683c7a44bbSChris Wilson 			break;
2693c7a44bbSChris Wilson 		}
2703c7a44bbSChris Wilson 
2713c7a44bbSChris Wilson 		err = i915_vma_sync(base);
2723c7a44bbSChris Wilson 		if (err) {
2733c7a44bbSChris Wilson 			i915_vma_put(base);
274de5825beSChris Wilson 			intel_engine_pm_put(engine);
2753c7a44bbSChris Wilson 			break;
2763c7a44bbSChris Wilson 		}
2773c7a44bbSChris Wilson 
2783c7a44bbSChris Wilson 		nop = create_nop_batch(ce);
2793c7a44bbSChris Wilson 		if (IS_ERR(nop)) {
2803c7a44bbSChris Wilson 			err = PTR_ERR(nop);
2813c7a44bbSChris Wilson 			i915_vma_put(base);
282de5825beSChris Wilson 			intel_engine_pm_put(engine);
2833c7a44bbSChris Wilson 			break;
2843c7a44bbSChris Wilson 		}
2853c7a44bbSChris Wilson 
2863c7a44bbSChris Wilson 		err = i915_vma_sync(nop);
2873c7a44bbSChris Wilson 		if (err) {
2883c7a44bbSChris Wilson 			i915_vma_put(nop);
2893c7a44bbSChris Wilson 			i915_vma_put(base);
290de5825beSChris Wilson 			intel_engine_pm_put(engine);
2913c7a44bbSChris Wilson 			break;
2923c7a44bbSChris Wilson 		}
2933c7a44bbSChris Wilson 
2943c7a44bbSChris Wilson 		for (i = 0; i < ARRAY_SIZE(cycles); i++) {
2953c7a44bbSChris Wilson 			struct i915_request *rq;
2963c7a44bbSChris Wilson 
2973c7a44bbSChris Wilson 			rq = i915_request_create(ce);
2983c7a44bbSChris Wilson 			if (IS_ERR(rq)) {
2993c7a44bbSChris Wilson 				err = PTR_ERR(rq);
3003c7a44bbSChris Wilson 				break;
3013c7a44bbSChris Wilson 			}
3023c7a44bbSChris Wilson 
3033c7a44bbSChris Wilson 			err = write_timestamp(rq, 2);
3043c7a44bbSChris Wilson 			if (err)
3053c7a44bbSChris Wilson 				goto out;
3063c7a44bbSChris Wilson 
3073c7a44bbSChris Wilson 			err = rq->engine->emit_bb_start(rq,
3083c7a44bbSChris Wilson 							base->node.start, 8,
3093c7a44bbSChris Wilson 							0);
3103c7a44bbSChris Wilson 			if (err)
3113c7a44bbSChris Wilson 				goto out;
3123c7a44bbSChris Wilson 
3133c7a44bbSChris Wilson 			err = write_timestamp(rq, 3);
3143c7a44bbSChris Wilson 			if (err)
3153c7a44bbSChris Wilson 				goto out;
3163c7a44bbSChris Wilson 
3173c7a44bbSChris Wilson 			err = rq->engine->emit_bb_start(rq,
3183c7a44bbSChris Wilson 							nop->node.start,
3193c7a44bbSChris Wilson 							nop->node.size,
3203c7a44bbSChris Wilson 							0);
3213c7a44bbSChris Wilson 			if (err)
3223c7a44bbSChris Wilson 				goto out;
3233c7a44bbSChris Wilson 
3243c7a44bbSChris Wilson 			err = write_timestamp(rq, 4);
3253c7a44bbSChris Wilson 			if (err)
3263c7a44bbSChris Wilson 				goto out;
3273c7a44bbSChris Wilson 
3283c7a44bbSChris Wilson out:
3293c7a44bbSChris Wilson 			i915_request_get(rq);
3303c7a44bbSChris Wilson 			i915_request_add(rq);
3313c7a44bbSChris Wilson 
3323c7a44bbSChris Wilson 			if (i915_request_wait(rq, 0, HZ / 5) < 0)
3333c7a44bbSChris Wilson 				err = -EIO;
3343c7a44bbSChris Wilson 			i915_request_put(rq);
3353c7a44bbSChris Wilson 			if (err)
3363c7a44bbSChris Wilson 				break;
3373c7a44bbSChris Wilson 
3383c7a44bbSChris Wilson 			cycles[i] =
3393c7a44bbSChris Wilson 				(rq->hwsp_seqno[4] - rq->hwsp_seqno[3]) -
3403c7a44bbSChris Wilson 				(rq->hwsp_seqno[3] - rq->hwsp_seqno[2]);
3413c7a44bbSChris Wilson 		}
3423c7a44bbSChris Wilson 		i915_vma_put(nop);
3433c7a44bbSChris Wilson 		i915_vma_put(base);
344de5825beSChris Wilson 		intel_engine_pm_put(engine);
3453c7a44bbSChris Wilson 		if (err)
3463c7a44bbSChris Wilson 			break;
3473c7a44bbSChris Wilson 
3483c7a44bbSChris Wilson 		pr_info("%s: 16K MI_NOOP cycles: %u\n",
3493c7a44bbSChris Wilson 			engine->name, trifilter(cycles));
3503c7a44bbSChris Wilson 	}
3513c7a44bbSChris Wilson 	if (perf_end(gt))
3523c7a44bbSChris Wilson 		err = -EIO;
3533c7a44bbSChris Wilson 
3543c7a44bbSChris Wilson 	return err;
3553c7a44bbSChris Wilson }
3563c7a44bbSChris Wilson 
3573c7a44bbSChris Wilson int intel_engine_cs_perf_selftests(struct drm_i915_private *i915)
3583c7a44bbSChris Wilson {
3593c7a44bbSChris Wilson 	static const struct i915_subtest tests[] = {
3603c7a44bbSChris Wilson 		SUBTEST(perf_mi_bb_start),
3613c7a44bbSChris Wilson 		SUBTEST(perf_mi_noop),
3623c7a44bbSChris Wilson 	};
3633c7a44bbSChris Wilson 
3643c7a44bbSChris Wilson 	if (intel_gt_is_wedged(&i915->gt))
3653c7a44bbSChris Wilson 		return 0;
3663c7a44bbSChris Wilson 
3673c7a44bbSChris Wilson 	return intel_gt_live_subtests(tests, &i915->gt);
3683c7a44bbSChris Wilson }
369112ed2d3SChris Wilson 
370112ed2d3SChris Wilson static int intel_mmio_bases_check(void *arg)
371112ed2d3SChris Wilson {
372112ed2d3SChris Wilson 	int i, j;
373112ed2d3SChris Wilson 
374112ed2d3SChris Wilson 	for (i = 0; i < ARRAY_SIZE(intel_engines); i++) {
375112ed2d3SChris Wilson 		const struct engine_info *info = &intel_engines[i];
376112ed2d3SChris Wilson 		u8 prev = U8_MAX;
377112ed2d3SChris Wilson 
378112ed2d3SChris Wilson 		for (j = 0; j < MAX_MMIO_BASES; j++) {
379*1b9d8406SLucas De Marchi 			u8 ver = info->mmio_bases[j].graphics_ver;
380112ed2d3SChris Wilson 			u32 base = info->mmio_bases[j].base;
381112ed2d3SChris Wilson 
382*1b9d8406SLucas De Marchi 			if (ver >= prev) {
383*1b9d8406SLucas De Marchi 				pr_err("%s(%s, class:%d, instance:%d): mmio base for graphics ver %u is before the one for ver %u\n",
3842edda80dSChris Wilson 				       __func__,
3852edda80dSChris Wilson 				       intel_engine_class_repr(info->class),
3862edda80dSChris Wilson 				       info->class, info->instance,
387*1b9d8406SLucas De Marchi 				       prev, ver);
388112ed2d3SChris Wilson 				return -EINVAL;
389112ed2d3SChris Wilson 			}
390112ed2d3SChris Wilson 
391*1b9d8406SLucas De Marchi 			if (ver == 0)
392112ed2d3SChris Wilson 				break;
393112ed2d3SChris Wilson 
394112ed2d3SChris Wilson 			if (!base) {
395*1b9d8406SLucas De Marchi 				pr_err("%s(%s, class:%d, instance:%d): invalid mmio base (%x) for graphics ver %u at entry %u\n",
3962edda80dSChris Wilson 				       __func__,
3972edda80dSChris Wilson 				       intel_engine_class_repr(info->class),
3982edda80dSChris Wilson 				       info->class, info->instance,
399*1b9d8406SLucas De Marchi 				       base, ver, j);
400112ed2d3SChris Wilson 				return -EINVAL;
401112ed2d3SChris Wilson 			}
402112ed2d3SChris Wilson 
403*1b9d8406SLucas De Marchi 			prev = ver;
404112ed2d3SChris Wilson 		}
405112ed2d3SChris Wilson 
406*1b9d8406SLucas De Marchi 		pr_debug("%s: min graphics version supported for %s%d is %u\n",
4072edda80dSChris Wilson 			 __func__,
4082edda80dSChris Wilson 			 intel_engine_class_repr(info->class),
4092edda80dSChris Wilson 			 info->instance,
4102edda80dSChris Wilson 			 prev);
411112ed2d3SChris Wilson 	}
412112ed2d3SChris Wilson 
413112ed2d3SChris Wilson 	return 0;
414112ed2d3SChris Wilson }
415112ed2d3SChris Wilson 
416112ed2d3SChris Wilson int intel_engine_cs_mock_selftests(void)
417112ed2d3SChris Wilson {
418112ed2d3SChris Wilson 	static const struct i915_subtest tests[] = {
419112ed2d3SChris Wilson 		SUBTEST(intel_mmio_bases_check),
420112ed2d3SChris Wilson 	};
421112ed2d3SChris Wilson 
422112ed2d3SChris Wilson 	return i915_subtests(tests, NULL);
423112ed2d3SChris Wilson }
424