/*
 * SPDX-License-Identifier: GPL-2.0
 *
 * Copyright © 2018 Intel Corporation
 */

#include <linux/sort.h>

#include "intel_gt_pm.h"
#include "intel_rps.h"

#include "i915_selftest.h"
#include "selftests/igt_flush_test.h"

#define COUNT 5

static int cmp_u32(const void *A, const void *B)
{
	const u32 *a = A, *b = B;

	return *a - *b;
}

static void perf_begin(struct intel_gt *gt)
{
	intel_gt_pm_get(gt);

	/* Boost gpufreq to max [waitboost] and keep it fixed */
	atomic_inc(&gt->rps.num_waiters);
	schedule_work(&gt->rps.work);
	flush_work(&gt->rps.work);
}

static int perf_end(struct intel_gt *gt)
{
	atomic_dec(&gt->rps.num_waiters);
	intel_gt_pm_put(gt);

	return igt_flush_test(gt->i915);
}

static int write_timestamp(struct i915_request *rq, int slot)
{
	u32 cmd;
	u32 *cs;

	cs = intel_ring_begin(rq, 4);
	if (IS_ERR(cs))
		return PTR_ERR(cs);

	cmd = MI_STORE_REGISTER_MEM | MI_USE_GGTT;
	if (INTEL_GEN(rq->engine->i915) >= 8)
		cmd++;
	*cs++ = cmd;
	*cs++ = i915_mmio_reg_offset(RING_TIMESTAMP(rq->engine->mmio_base));
	*cs++ = i915_request_timeline(rq)->hwsp_offset + slot * sizeof(u32);
	*cs++ = 0;

	intel_ring_advance(rq, cs);

	return 0;
}

static struct i915_vma *create_empty_batch(struct intel_context *ce)
{
	struct drm_i915_gem_object *obj;
	struct i915_vma *vma;
	u32 *cs;
	int err;

	obj = i915_gem_object_create_internal(ce->engine->i915, PAGE_SIZE);
	if (IS_ERR(obj))
		return ERR_CAST(obj);

	cs = i915_gem_object_pin_map(obj, I915_MAP_WB);
	if (IS_ERR(cs)) {
		err = PTR_ERR(cs);
		goto err_put;
	}

	cs[0] = MI_BATCH_BUFFER_END;

	i915_gem_object_flush_map(obj);

	vma = i915_vma_instance(obj, ce->vm, NULL);
	if (IS_ERR(vma)) {
		err = PTR_ERR(vma);
		goto err_unpin;
	}

	err = i915_vma_pin(vma, 0, 0, PIN_USER);
	if (err)
		goto err_unpin;

	i915_gem_object_unpin_map(obj);
	return vma;

err_unpin:
	i915_gem_object_unpin_map(obj);
err_put:
	i915_gem_object_put(obj);
	return ERR_PTR(err);
}

static u32 trifilter(u32 *a)
{
	u64 sum;

	sort(a, COUNT, sizeof(*a), cmp_u32, NULL);

	sum = mul_u32_u32(a[2], 2);
	sum += a[1];
	sum += a[3];

	return sum >> 2;
}

static int perf_mi_bb_start(void *arg)
{
	struct intel_gt *gt = arg;
	struct intel_engine_cs *engine;
	enum intel_engine_id id;
	int err = 0;

	if (INTEL_GEN(gt->i915) < 7) /* for per-engine CS_TIMESTAMP */
		return 0;

	perf_begin(gt);
	for_each_engine(engine, gt, id) {
		struct intel_context *ce = engine->kernel_context;
		struct i915_vma *batch;
		u32 cycles[COUNT];
		int i;

		intel_engine_pm_get(engine);

		batch = create_empty_batch(ce);
		if (IS_ERR(batch)) {
			err = PTR_ERR(batch);
			intel_engine_pm_put(engine);
			break;
		}

		err = i915_vma_sync(batch);
		if (err) {
			intel_engine_pm_put(engine);
			i915_vma_put(batch);
			break;
		}

		for (i = 0; i < ARRAY_SIZE(cycles); i++) {
			struct i915_request *rq;

			rq = i915_request_create(ce);
			if (IS_ERR(rq)) {
				err = PTR_ERR(rq);
				break;
			}

			err = write_timestamp(rq, 2);
			if (err)
				goto out;

			err = rq->engine->emit_bb_start(rq,
							batch->node.start, 8,
							0);
			if (err)
				goto out;

			err = write_timestamp(rq, 3);
			if (err)
				goto out;

out:
			i915_request_get(rq);
			i915_request_add(rq);

			if (i915_request_wait(rq, 0, HZ / 5) < 0)
				err = -EIO;
			i915_request_put(rq);
			if (err)
				break;

			cycles[i] = rq->hwsp_seqno[3] - rq->hwsp_seqno[2];
		}
		i915_vma_put(batch);
		intel_engine_pm_put(engine);
		if (err)
			break;

		pr_info("%s: MI_BB_START cycles: %u\n",
			engine->name, trifilter(cycles));
	}
	if (perf_end(gt))
		err = -EIO;

	return err;
}

static struct i915_vma *create_nop_batch(struct intel_context *ce)
{
	struct drm_i915_gem_object *obj;
	struct i915_vma *vma;
	u32 *cs;
	int err;

	obj = i915_gem_object_create_internal(ce->engine->i915, SZ_64K);
	if (IS_ERR(obj))
		return ERR_CAST(obj);

	cs = i915_gem_object_pin_map(obj, I915_MAP_WB);
	if (IS_ERR(cs)) {
		err = PTR_ERR(cs);
		goto err_put;
	}

	memset(cs, 0, SZ_64K);
	cs[SZ_64K / sizeof(*cs) - 1] = MI_BATCH_BUFFER_END;

	i915_gem_object_flush_map(obj);

	vma = i915_vma_instance(obj, ce->vm, NULL);
	if (IS_ERR(vma)) {
		err = PTR_ERR(vma);
		goto err_unpin;
	}

	err = i915_vma_pin(vma, 0, 0, PIN_USER);
	if (err)
		goto err_unpin;

	i915_gem_object_unpin_map(obj);
	return vma;

err_unpin:
	i915_gem_object_unpin_map(obj);
err_put:
	i915_gem_object_put(obj);
	return ERR_PTR(err);
}

static int perf_mi_noop(void *arg)
{
	struct intel_gt *gt = arg;
	struct intel_engine_cs *engine;
	enum intel_engine_id id;
	int err = 0;

	if (INTEL_GEN(gt->i915) < 7) /* for per-engine CS_TIMESTAMP */
		return 0;

	perf_begin(gt);
	for_each_engine(engine, gt, id) {
		struct intel_context *ce = engine->kernel_context;
		struct i915_vma *base, *nop;
		u32 cycles[COUNT];
		int i;

		intel_engine_pm_get(engine);

		base = create_empty_batch(ce);
		if (IS_ERR(base)) {
			err = PTR_ERR(base);
			intel_engine_pm_put(engine);
			break;
		}

		err = i915_vma_sync(base);
		if (err) {
			i915_vma_put(base);
			intel_engine_pm_put(engine);
			break;
		}

		nop = create_nop_batch(ce);
		if (IS_ERR(nop)) {
			err = PTR_ERR(nop);
			i915_vma_put(base);
			intel_engine_pm_put(engine);
			break;
		}

		err = i915_vma_sync(nop);
		if (err) {
			i915_vma_put(nop);
			i915_vma_put(base);
			intel_engine_pm_put(engine);
			break;
		}

		for (i = 0; i < ARRAY_SIZE(cycles); i++) {
			struct i915_request *rq;

			rq = i915_request_create(ce);
			if (IS_ERR(rq)) {
				err = PTR_ERR(rq);
				break;
			}

			err = write_timestamp(rq, 2);
			if (err)
				goto out;

			err = rq->engine->emit_bb_start(rq,
							base->node.start, 8,
							0);
			if (err)
				goto out;

			err = write_timestamp(rq, 3);
			if (err)
				goto out;

			err = rq->engine->emit_bb_start(rq,
							nop->node.start,
							nop->node.size,
							0);
			if (err)
				goto out;

			err = write_timestamp(rq, 4);
			if (err)
				goto out;

out:
			i915_request_get(rq);
			i915_request_add(rq);

			if (i915_request_wait(rq, 0, HZ / 5) < 0)
				err = -EIO;
			i915_request_put(rq);
			if (err)
				break;

			cycles[i] =
				(rq->hwsp_seqno[4] - rq->hwsp_seqno[3]) -
				(rq->hwsp_seqno[3] - rq->hwsp_seqno[2]);
		}
		i915_vma_put(nop);
		i915_vma_put(base);
		intel_engine_pm_put(engine);
		if (err)
			break;

		pr_info("%s: 16K MI_NOOP cycles: %u\n",
			engine->name, trifilter(cycles));
	}
	if (perf_end(gt))
		err = -EIO;

	return err;
}

int intel_engine_cs_perf_selftests(struct drm_i915_private *i915)
{
	static const struct i915_subtest tests[] = {
		SUBTEST(perf_mi_bb_start),
		SUBTEST(perf_mi_noop),
	};

	if (intel_gt_is_wedged(&i915->gt))
		return 0;

	return intel_gt_live_subtests(tests, &i915->gt);
}

static int intel_mmio_bases_check(void *arg)
{
	int i, j;

	for (i = 0; i < ARRAY_SIZE(intel_engines); i++) {
		const struct engine_info *info = &intel_engines[i];
		u8 prev = U8_MAX;

		for (j = 0; j < MAX_MMIO_BASES; j++) {
			u8 gen = info->mmio_bases[j].gen;
			u32 base = info->mmio_bases[j].base;

			if (gen >= prev) {
				pr_err("%s(%s, class:%d, instance:%d): mmio base for gen %x is before the one for gen %x\n",
				       __func__,
				       intel_engine_class_repr(info->class),
				       info->class, info->instance,
				       prev, gen);
				return -EINVAL;
			}

			if (gen == 0)
				break;

			if (!base) {
				pr_err("%s(%s, class:%d, instance:%d): invalid mmio base (%x) for gen %x at entry %u\n",
				       __func__,
				       intel_engine_class_repr(info->class),
				       info->class, info->instance,
				       base, gen, j);
				return -EINVAL;
			}

			prev = gen;
		}

		pr_debug("%s: min gen supported for %s%d is %d\n",
			 __func__,
			 intel_engine_class_repr(info->class),
			 info->instance,
			 prev);
	}

	return 0;
}

int intel_engine_cs_mock_selftests(void)
{
	static const struct i915_subtest tests[] = {
		SUBTEST(intel_mmio_bases_check),
	};

	return i915_subtests(tests, NULL);
}
